1 1.21 rillig /* $NetBSD: graphics.c,v 1.21 2021/05/02 12:50:43 rillig Exp $ */ 2 1.3 cgd 3 1.1 cgd /*- 4 1.3 cgd * Copyright (c) 1990, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * This code is derived from software contributed to Berkeley by 8 1.1 cgd * Ed James. 9 1.1 cgd * 10 1.1 cgd * Redistribution and use in source and binary forms, with or without 11 1.1 cgd * modification, are permitted provided that the following conditions 12 1.1 cgd * are met: 13 1.1 cgd * 1. Redistributions of source code must retain the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer. 15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 cgd * notice, this list of conditions and the following disclaimer in the 17 1.1 cgd * documentation and/or other materials provided with the distribution. 18 1.10 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 cgd * may be used to endorse or promote products derived from this software 20 1.1 cgd * without specific prior written permission. 21 1.1 cgd * 22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 cgd * SUCH DAMAGE. 33 1.1 cgd */ 34 1.1 cgd 35 1.1 cgd /* 36 1.1 cgd * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. 37 1.1 cgd * 38 1.1 cgd * Copy permission is hereby granted provided that this notice is 39 1.1 cgd * retained on all partial or complete copies. 40 1.1 cgd * 41 1.1 cgd * For more info on this and all of my stuff, mail edjames (at) berkeley.edu. 42 1.1 cgd */ 43 1.1 cgd 44 1.4 lukem #include <sys/cdefs.h> 45 1.1 cgd #ifndef lint 46 1.3 cgd #if 0 47 1.3 cgd static char sccsid[] = "@(#)graphics.c 8.1 (Berkeley) 5/31/93"; 48 1.3 cgd #else 49 1.21 rillig __RCSID("$NetBSD: graphics.c,v 1.21 2021/05/02 12:50:43 rillig Exp $"); 50 1.3 cgd #endif 51 1.1 cgd #endif /* not lint */ 52 1.1 cgd 53 1.19 dholland #include <stdio.h> 54 1.19 dholland #include <stdlib.h> 55 1.19 dholland #include <curses.h> 56 1.19 dholland #include <errno.h> 57 1.19 dholland #include <err.h> 58 1.19 dholland 59 1.19 dholland #include "def.h" 60 1.19 dholland #include "struct.h" 61 1.19 dholland #include "extern.h" 62 1.19 dholland #include "tunable.h" 63 1.1 cgd 64 1.1 cgd #define C_TOPBOTTOM '-' 65 1.1 cgd #define C_LEFTRIGHT '|' 66 1.1 cgd #define C_AIRPORT '=' 67 1.1 cgd #define C_LINE '+' 68 1.1 cgd #define C_BACKROUND '.' 69 1.1 cgd #define C_BEACON '*' 70 1.1 cgd #define C_CREDIT '*' 71 1.1 cgd 72 1.16 dholland static void draw_line(WINDOW *, int, int, int, int, const char *); 73 1.16 dholland 74 1.16 dholland static WINDOW *radar, *cleanradar, *credit, *input, *planes; 75 1.1 cgd 76 1.4 lukem int 77 1.11 jmc getAChar(void) 78 1.1 cgd { 79 1.1 cgd int c; 80 1.1 cgd 81 1.8 hubertf errno = 0; 82 1.9 jsm while ((c = getchar()) == EOF && errno == EINTR) { 83 1.8 hubertf errno = 0; 84 1.8 hubertf clearerr(stdin); 85 1.8 hubertf } 86 1.1 cgd return(c); 87 1.1 cgd } 88 1.1 cgd 89 1.4 lukem void 90 1.11 jmc erase_all(void) 91 1.1 cgd { 92 1.1 cgd PLANE *pp; 93 1.1 cgd 94 1.1 cgd for (pp = air.head; pp != NULL; pp = pp->next) { 95 1.12 rpaulo (void)wmove(cleanradar, pp->ypos, pp->xpos * 2); 96 1.12 rpaulo (void)wmove(radar, pp->ypos, pp->xpos * 2); 97 1.12 rpaulo (void)waddch(radar, winch(cleanradar)); 98 1.12 rpaulo (void)wmove(cleanradar, pp->ypos, pp->xpos * 2 + 1); 99 1.12 rpaulo (void)wmove(radar, pp->ypos, pp->xpos * 2 + 1); 100 1.12 rpaulo (void)waddch(radar, winch(cleanradar)); 101 1.1 cgd } 102 1.1 cgd } 103 1.1 cgd 104 1.4 lukem void 105 1.11 jmc draw_all(void) 106 1.1 cgd { 107 1.1 cgd PLANE *pp; 108 1.1 cgd 109 1.1 cgd for (pp = air.head; pp != NULL; pp = pp->next) { 110 1.1 cgd if (pp->status == S_MARKED) 111 1.12 rpaulo (void)wstandout(radar); 112 1.12 rpaulo (void)wmove(radar, pp->ypos, pp->xpos * 2); 113 1.12 rpaulo (void)waddch(radar, name(pp)); 114 1.12 rpaulo (void)waddch(radar, '0' + pp->altitude); 115 1.1 cgd if (pp->status == S_MARKED) 116 1.12 rpaulo (void)wstandend(radar); 117 1.1 cgd } 118 1.12 rpaulo (void)wrefresh(radar); 119 1.12 rpaulo (void)planewin(); 120 1.12 rpaulo (void)wrefresh(input); /* return cursor */ 121 1.12 rpaulo (void)fflush(stdout); 122 1.1 cgd } 123 1.1 cgd 124 1.4 lukem void 125 1.11 jmc init_gr(void) 126 1.1 cgd { 127 1.1 cgd static char buffer[BUFSIZ]; 128 1.1 cgd 129 1.15 drochner if (!initscr()) 130 1.15 drochner errx(0, "couldn't initialize screen"); 131 1.1 cgd setbuf(stdout, buffer); 132 1.1 cgd input = newwin(INPUT_LINES, COLS - PLANE_COLS, LINES - INPUT_LINES, 0); 133 1.21 rillig credit = newwin(INPUT_LINES, PLANE_COLS, LINES - INPUT_LINES, 134 1.1 cgd COLS - PLANE_COLS); 135 1.1 cgd planes = newwin(LINES - INPUT_LINES, PLANE_COLS, 0, COLS - PLANE_COLS); 136 1.1 cgd } 137 1.1 cgd 138 1.4 lukem void 139 1.20 dholland shutdown_gr(void) 140 1.20 dholland { 141 1.20 dholland (void)clear(); /* move to top of screen */ 142 1.20 dholland (void)refresh(); 143 1.20 dholland (void)fflush(stdout); 144 1.20 dholland (void)endwin(); 145 1.20 dholland } 146 1.20 dholland 147 1.20 dholland void 148 1.11 jmc setup_screen(const C_SCREEN *scp) 149 1.1 cgd { 150 1.4 lukem int i, j; 151 1.17 dholland unsigned iu; 152 1.5 hubertf char str[3]; 153 1.5 hubertf const char *airstr; 154 1.1 cgd 155 1.1 cgd str[2] = '\0'; 156 1.1 cgd 157 1.1 cgd if (radar != NULL) 158 1.12 rpaulo (void)delwin(radar); 159 1.1 cgd radar = newwin(scp->height, scp->width * 2, 0, 0); 160 1.1 cgd 161 1.1 cgd if (cleanradar != NULL) 162 1.12 rpaulo (void)delwin(cleanradar); 163 1.1 cgd cleanradar = newwin(scp->height, scp->width * 2, 0, 0); 164 1.1 cgd 165 1.1 cgd /* minus one here to prevent a scroll */ 166 1.1 cgd for (i = 0; i < PLANE_COLS - 1; i++) { 167 1.12 rpaulo (void)wmove(credit, 0, i); 168 1.12 rpaulo (void)waddch(credit, C_CREDIT); 169 1.12 rpaulo (void)wmove(credit, INPUT_LINES - 1, i); 170 1.12 rpaulo (void)waddch(credit, C_CREDIT); 171 1.1 cgd } 172 1.12 rpaulo (void)wmove(credit, INPUT_LINES / 2, 1); 173 1.12 rpaulo (void)waddstr(credit, AUTHOR_STR); 174 1.1 cgd 175 1.1 cgd for (i = 1; i < scp->height - 1; i++) { 176 1.1 cgd for (j = 1; j < scp->width - 1; j++) { 177 1.12 rpaulo (void)wmove(radar, i, j * 2); 178 1.12 rpaulo (void)waddch(radar, C_BACKROUND); 179 1.1 cgd } 180 1.1 cgd } 181 1.1 cgd 182 1.1 cgd /* 183 1.1 cgd * Draw the lines first, since people like to draw lines 184 1.1 cgd * through beacons and exit points. 185 1.1 cgd */ 186 1.1 cgd str[0] = C_LINE; 187 1.18 dholland for (iu = 0; iu < scp->num_lines; iu++) { 188 1.1 cgd str[1] = ' '; 189 1.18 dholland draw_line(radar, scp->line[iu].p1.x, scp->line[iu].p1.y, 190 1.18 dholland scp->line[iu].p2.x, scp->line[iu].p2.y, str); 191 1.1 cgd } 192 1.1 cgd 193 1.1 cgd str[0] = C_TOPBOTTOM; 194 1.1 cgd str[1] = C_TOPBOTTOM; 195 1.12 rpaulo (void)wmove(radar, 0, 0); 196 1.1 cgd for (i = 0; i < scp->width - 1; i++) 197 1.12 rpaulo (void)waddstr(radar, str); 198 1.12 rpaulo (void)waddch(radar, C_TOPBOTTOM); 199 1.1 cgd 200 1.1 cgd str[0] = C_TOPBOTTOM; 201 1.1 cgd str[1] = C_TOPBOTTOM; 202 1.12 rpaulo (void)wmove(radar, scp->height - 1, 0); 203 1.1 cgd for (i = 0; i < scp->width - 1; i++) 204 1.12 rpaulo (void)waddstr(radar, str); 205 1.12 rpaulo (void)waddch(radar, C_TOPBOTTOM); 206 1.1 cgd 207 1.1 cgd for (i = 1; i < scp->height - 1; i++) { 208 1.12 rpaulo (void)wmove(radar, i, 0); 209 1.12 rpaulo (void)waddch(radar, C_LEFTRIGHT); 210 1.12 rpaulo (void)wmove(radar, i, (scp->width - 1) * 2); 211 1.12 rpaulo (void)waddch(radar, C_LEFTRIGHT); 212 1.1 cgd } 213 1.1 cgd 214 1.1 cgd str[0] = C_BEACON; 215 1.17 dholland for (iu = 0; iu < scp->num_beacons; iu++) { 216 1.17 dholland str[1] = '0' + iu; 217 1.17 dholland (void)wmove(radar, scp->beacon[iu].y, scp->beacon[iu].x * 2); 218 1.12 rpaulo (void)waddstr(radar, str); 219 1.1 cgd } 220 1.1 cgd 221 1.17 dholland for (iu = 0; iu < scp->num_exits; iu++) { 222 1.17 dholland (void)wmove(radar, scp->exit[iu].y, scp->exit[iu].x * 2); 223 1.17 dholland (void)waddch(radar, '0' + iu); 224 1.1 cgd } 225 1.1 cgd 226 1.1 cgd airstr = "^?>?v?<?"; 227 1.17 dholland for (iu = 0; iu < scp->num_airports; iu++) { 228 1.17 dholland str[0] = airstr[scp->airport[iu].dir]; 229 1.17 dholland str[1] = '0' + iu; 230 1.17 dholland (void)wmove(radar, scp->airport[iu].y, scp->airport[iu].x * 2); 231 1.12 rpaulo (void)waddstr(radar, str); 232 1.1 cgd } 233 1.21 rillig 234 1.12 rpaulo (void)overwrite(radar, cleanradar); 235 1.12 rpaulo (void)wrefresh(radar); 236 1.12 rpaulo (void)wrefresh(credit); 237 1.12 rpaulo (void)fflush(stdout); 238 1.1 cgd } 239 1.1 cgd 240 1.16 dholland static void 241 1.11 jmc draw_line(WINDOW *w, int x, int y, int lx, int ly, const char *s) 242 1.1 cgd { 243 1.1 cgd int dx, dy; 244 1.1 cgd 245 1.1 cgd dx = SGN(lx - x); 246 1.1 cgd dy = SGN(ly - y); 247 1.1 cgd for (;;) { 248 1.12 rpaulo (void)wmove(w, y, x * 2); 249 1.12 rpaulo (void)waddstr(w, s); 250 1.1 cgd if (x == lx && y == ly) 251 1.1 cgd break; 252 1.1 cgd x += dx; 253 1.1 cgd y += dy; 254 1.1 cgd } 255 1.1 cgd } 256 1.1 cgd 257 1.4 lukem void 258 1.11 jmc ioclrtoeol(int pos) 259 1.1 cgd { 260 1.12 rpaulo (void)wmove(input, 0, pos); 261 1.12 rpaulo (void)wclrtoeol(input); 262 1.12 rpaulo (void)wrefresh(input); 263 1.12 rpaulo (void)fflush(stdout); 264 1.1 cgd } 265 1.1 cgd 266 1.4 lukem void 267 1.11 jmc iomove(int pos) 268 1.1 cgd { 269 1.12 rpaulo (void)wmove(input, 0, pos); 270 1.12 rpaulo (void)wrefresh(input); 271 1.12 rpaulo (void)fflush(stdout); 272 1.1 cgd } 273 1.1 cgd 274 1.4 lukem void 275 1.11 jmc ioaddstr(int pos, const char *str) 276 1.1 cgd { 277 1.12 rpaulo (void)wmove(input, 0, pos); 278 1.12 rpaulo (void)waddstr(input, str); 279 1.12 rpaulo (void)wrefresh(input); 280 1.12 rpaulo (void)fflush(stdout); 281 1.1 cgd } 282 1.1 cgd 283 1.4 lukem void 284 1.11 jmc ioclrtobot(void) 285 1.1 cgd { 286 1.12 rpaulo (void)wclrtobot(input); 287 1.12 rpaulo (void)wrefresh(input); 288 1.12 rpaulo (void)fflush(stdout); 289 1.1 cgd } 290 1.1 cgd 291 1.4 lukem void 292 1.11 jmc ioerror(int pos, int len, const char *str) 293 1.1 cgd { 294 1.1 cgd int i; 295 1.1 cgd 296 1.12 rpaulo (void)wmove(input, 1, pos); 297 1.1 cgd for (i = 0; i < len; i++) 298 1.12 rpaulo (void)waddch(input, '^'); 299 1.12 rpaulo (void)wmove(input, 2, 0); 300 1.12 rpaulo (void)waddstr(input, str); 301 1.12 rpaulo (void)wrefresh(input); 302 1.12 rpaulo (void)fflush(stdout); 303 1.1 cgd } 304 1.1 cgd 305 1.20 dholland static int ioquit_x, ioquit_y; 306 1.20 dholland 307 1.4 lukem void 308 1.20 dholland ioaskquit(void) 309 1.1 cgd { 310 1.20 dholland getyx(input, ioquit_y, ioquit_x); 311 1.12 rpaulo (void)wmove(input, 2, 0); 312 1.12 rpaulo (void)waddstr(input, "Really quit? (y/n) "); 313 1.12 rpaulo (void)wclrtobot(input); 314 1.12 rpaulo (void)wrefresh(input); 315 1.12 rpaulo (void)fflush(stdout); 316 1.20 dholland } 317 1.1 cgd 318 1.20 dholland void 319 1.20 dholland ionoquit(void) 320 1.20 dholland { 321 1.12 rpaulo (void)wmove(input, 2, 0); 322 1.12 rpaulo (void)wclrtobot(input); 323 1.20 dholland (void)wmove(input, ioquit_y, ioquit_x); 324 1.12 rpaulo (void)wrefresh(input); 325 1.12 rpaulo (void)fflush(stdout); 326 1.1 cgd } 327 1.1 cgd 328 1.4 lukem void 329 1.11 jmc planewin(void) 330 1.1 cgd { 331 1.1 cgd PLANE *pp; 332 1.1 cgd int warning = 0; 333 1.1 cgd 334 1.1 cgd #ifdef BSD 335 1.12 rpaulo (void)wclear(planes); 336 1.1 cgd #endif 337 1.1 cgd 338 1.12 rpaulo (void)wmove(planes, 0,0); 339 1.1 cgd 340 1.1 cgd #ifdef SYSV 341 1.1 cgd wclrtobot(planes); 342 1.1 cgd #endif 343 1.12 rpaulo (void)wprintw(planes, "Time: %-4d Safe: %d", clck, safe_planes); 344 1.12 rpaulo (void)wmove(planes, 2, 0); 345 1.1 cgd 346 1.12 rpaulo (void)waddstr(planes, "pl dt comm"); 347 1.1 cgd for (pp = air.head; pp != NULL; pp = pp->next) { 348 1.1 cgd if (waddch(planes, '\n') == ERR) { 349 1.1 cgd warning++; 350 1.1 cgd break; 351 1.1 cgd } 352 1.12 rpaulo (void)waddstr(planes, command(pp)); 353 1.1 cgd } 354 1.12 rpaulo (void)waddch(planes, '\n'); 355 1.1 cgd for (pp = ground.head; pp != NULL; pp = pp->next) { 356 1.1 cgd if (waddch(planes, '\n') == ERR) { 357 1.1 cgd warning++; 358 1.1 cgd break; 359 1.1 cgd } 360 1.12 rpaulo (void)waddstr(planes, command(pp)); 361 1.1 cgd } 362 1.1 cgd if (warning) { 363 1.12 rpaulo (void)wmove(planes, LINES - INPUT_LINES - 1, 0); 364 1.12 rpaulo (void)waddstr(planes, "---- more ----"); 365 1.12 rpaulo (void)wclrtoeol(planes); 366 1.1 cgd } 367 1.12 rpaulo (void)wrefresh(planes); 368 1.12 rpaulo (void)fflush(stdout); 369 1.1 cgd } 370 1.1 cgd 371 1.4 lukem void 372 1.20 dholland losermsg(const PLANE *p, const char *msg) 373 1.1 cgd { 374 1.12 rpaulo (void)wmove(input, 0, 0); 375 1.12 rpaulo (void)wclrtobot(input); 376 1.6 hubertf /* p may be NULL if we ran out of memory */ 377 1.6 hubertf if (p == NULL) 378 1.12 rpaulo (void)wprintw(input, "%s\n\nHit space for top players list...", 379 1.20 dholland msg); 380 1.13 jnemeth else { 381 1.20 dholland (void)wprintw(input, "Plane '%c' %s\n\n", name(p), msg); 382 1.12 rpaulo (void)wprintw(input, "Hit space for top players list..."); 383 1.13 jnemeth } 384 1.12 rpaulo (void)wrefresh(input); 385 1.12 rpaulo (void)fflush(stdout); 386 1.1 cgd } 387 1.1 cgd 388 1.4 lukem void 389 1.11 jmc redraw(void) 390 1.1 cgd { 391 1.12 rpaulo (void)clear(); 392 1.12 rpaulo (void)refresh(); 393 1.1 cgd 394 1.12 rpaulo (void)touchwin(radar); 395 1.12 rpaulo (void)wrefresh(radar); 396 1.12 rpaulo (void)touchwin(planes); 397 1.12 rpaulo (void)wrefresh(planes); 398 1.12 rpaulo (void)touchwin(credit); 399 1.12 rpaulo (void)wrefresh(credit); 400 1.1 cgd 401 1.1 cgd /* refresh input last to get cursor in right place */ 402 1.12 rpaulo (void)touchwin(input); 403 1.12 rpaulo (void)wrefresh(input); 404 1.12 rpaulo (void)fflush(stdout); 405 1.1 cgd } 406 1.1 cgd 407 1.4 lukem void 408 1.11 jmc done_screen(void) 409 1.1 cgd { 410 1.12 rpaulo (void)clear(); 411 1.12 rpaulo (void)refresh(); 412 1.12 rpaulo (void)endwin(); /* clean up curses */ 413 1.1 cgd } 414