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