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