This completely merges the line-oriented and screen I/O managers,
[super-star-trek.git] / io.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <termios.h>
4 #include <curses.h>
5 #include <signal.h>
6 #include <ctype.h>
7 #include <stdarg.h>
8 #include <time.h>
9
10 #include "sst.h"
11 #include "sstlinux.h"
12
13 static int linecount;   /* for paging */
14 static int curses = TRUE;
15
16 WINDOW *curwnd;
17
18 static void outro(void)
19 /* wrap up, either normally or due to signal */
20 {
21     if (curses) {
22         clear();
23         curs_set(1);
24         (void)refresh();
25         (void)resetterm();
26         //(void)echo();
27         (void)endwin();
28         putchar('\n');
29     }
30 }
31
32 void iostart(int usecurses) 
33 {
34     if ((curses = usecurses)) {
35         if (atexit(outro)){
36             fprintf(stderr,"Unable to register outro(), exiting...\n");
37             exit(1);
38         }
39         (void)initscr();
40 #ifdef KEY_MIN
41         keypad(stdscr, TRUE);
42 #endif /* KEY_MIN */
43         (void)saveterm();
44         (void)nonl();
45         (void)cbreak();
46         //(void)noecho();
47         FULLSCREEN_WINDOW = stdscr;
48         SRSCAN_WINDOW     = newwin(12, 25, 0,       0);
49         REPORT_WINDOW     = newwin(10, 0,  1,       25);
50         LRSCAN_WINDOW     = newwin(10, 0,  0,       64); 
51         LOWER_WINDOW      = newwin(0,  0,  12,      0);
52         BOTTOM_WINDOW     = newwin(1,  0,  LINES-1, 0); 
53         scrollok(LOWER_WINDOW, TRUE);
54     }
55 }
56
57
58 void waitfor(void)
59 /* wait for user action -- OK to do nothing if on a TTY */
60 {
61     if (curses)
62         getch();
63 }
64
65 void pause_game(int i) 
66 {
67     char *prompt;
68     char buf[BUFSIZ];
69     if (i==1) {
70         if (skill > 2)
71             prompt = "[ANOUNCEMENT ARRIVING...]";
72         else
73             prompt = "[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]";
74     }
75     else {
76         if (skill > 2)
77             prompt = "[CONTINUE?]";
78         else
79             prompt = "[PRESS ENTER TO CONTINUE]";
80
81     }
82     if (curses) {
83         drawmaps(0);
84         setwnd(BOTTOM_WINDOW);
85         wclear(BOTTOM_WINDOW);
86         waddstr(BOTTOM_WINDOW, prompt);
87         wgetnstr(BOTTOM_WINDOW, buf, sizeof(buf));
88         wclear(BOTTOM_WINDOW);
89         wrefresh(BOTTOM_WINDOW);
90         setwnd(LOWER_WINDOW);
91     } else {
92         putchar('\n');
93         proutn(prompt);
94         fgets(buf, sizeof(buf), stdin);
95         if (i != 0) {
96             int j;
97             for (j = 0; j < 24; j++)
98                 putchar('\n');
99         }
100         linecount = 0;
101     }
102 }
103
104
105 void skip(int i) 
106 {
107     while (i-- > 0) {
108         if (curses) {
109             proutn("\n\r");
110         } else {
111             linecount++;
112             if (linecount >= 24)
113                 pause_game(0);
114             else
115                 putchar('\n');
116         }
117     }
118 }
119
120 static void vproutn(char *fmt, va_list ap) 
121 {
122     if (curses) {
123         vwprintw(curwnd, fmt, ap);
124         wrefresh(curwnd);
125     }
126     else
127         vprintf(fmt, ap);
128 }
129
130 void proutn(char *fmt, ...) 
131 {
132     va_list ap;
133     va_start(ap, fmt);
134     vproutn(fmt, ap);
135     va_end(ap);
136 }
137
138 void prout(char *fmt, ...) 
139 {
140     va_list ap;
141     va_start(ap, fmt);
142     vproutn(fmt, ap);
143     va_end(ap);
144     skip(1);
145 }
146
147 void prouts(char *fmt, ...) 
148 /* print slowly! */
149 {
150     clock_t endTime;
151     char *s, buf[BUFSIZ];
152     va_list ap;
153     va_start(ap, fmt);
154     vsprintf(buf, fmt, ap);
155     va_end(ap);
156     skip(1);
157     for (s = buf; *s; s++) {
158         endTime = clock() + CLOCKS_PER_SEC*0.05;
159         while (clock() < endTime) continue;
160         if (curses) {
161             waddch(curwnd, *s);
162             wrefresh(curwnd);
163         }
164         else {
165             putchar(*s);
166             fflush(stdout);
167         }
168     }
169 }
170
171 void cgetline(char *line, int max)
172 {
173     if (curses) {
174         wgetnstr(curwnd, line, max);
175         strcat(line, "\n");
176         wrefresh(curwnd);
177     } else {
178         fgets(line, max, stdin);
179     }
180     line[strlen(line)-1] = '\0';
181 }
182
183 void setwnd(WINDOW *wnd)
184 /* change windows -- OK for this to be a no-op in tty mode */
185 {
186     if (curses) {
187      curwnd=wnd;
188      curs_set(wnd == FULLSCREEN_WINDOW || wnd == LOWER_WINDOW);
189     }
190 }
191
192 void clreol (void)
193 /* clear to end of line -- can be a no-op in tty mode */
194 {
195    if (curses) {
196        wclrtoeol(curwnd);
197        wrefresh(curwnd);
198    }
199 }
200
201 void clrscr (void)
202 /* clear screen -- can be a no-op in tty mode */
203 {
204    if (curses) {
205        wclear(curwnd);
206        wmove(curwnd,0,0);
207        wrefresh(curwnd);
208    }
209 }
210
211 void textcolor (int color)
212 {
213     if (curses) {
214         wattroff(curwnd, A_REVERSE);
215         // FIXME
216    }
217 }
218
219 void highvideo (void)
220 {
221     if (curses) {
222         attron(A_REVERSE);
223     }
224 }
225  
226 void commandhook(char *cmd, int before) {
227 }
228
229 /*
230  * Things past this point have policy implications.
231  */
232
233 void drawmaps(short l)
234 /* hook to be called after moving to redraw maps */
235 {
236     if (curses) {
237         if (l == 1) 
238             sensor();
239         if (l != 2) {
240             setwnd(SRSCAN_WINDOW);
241             wmove(curwnd, 0, 0);
242             enqueue("no");
243             srscan(SCAN_FULL);
244             setwnd(REPORT_WINDOW);
245             wclear(REPORT_WINDOW);
246             wmove(REPORT_WINDOW, 0, 0);
247             srscan(SCAN_NO_LEFTSIDE);
248             setwnd(LRSCAN_WINDOW);
249             wclear(LRSCAN_WINDOW);
250             wmove(LRSCAN_WINDOW, 0, 0);
251             enqueue("l");
252             lrscan();
253         }
254     }
255 }
256
257 void boom(int ii, int jj)
258 /* enemy fall down, go boom */ 
259 {
260     if (curses) {
261         setwnd(SRSCAN_WINDOW);
262         drawmaps(2);
263         wmove(SRSCAN_WINDOW, ii*2+3, jj+2);
264         wattron(SRSCAN_WINDOW, A_REVERSE);
265         waddch(SRSCAN_WINDOW, game.quad[ii][jj]);
266         wrefresh(SRSCAN_WINDOW);
267         sound(500);
268         delay(1000);
269         nosound();
270         wmove(SRSCAN_WINDOW, ii*2+3, jj+2);
271         wattroff(SRSCAN_WINDOW, A_REVERSE);
272         waddch(SRSCAN_WINDOW, game.quad[ii][jj]);
273         wrefresh(SRSCAN_WINDOW);
274         setwnd(LOWER_WINDOW);
275         delay(500);
276     }
277
278
279 void warble(void)
280 /* sound and visual effects for teleportation */
281 {
282     if (curses) {
283         drawmaps(1);
284         setwnd(LOWER_WINDOW);
285         sound(50);
286         delay(1000);
287         nosound();
288     } else
289         prouts(" . . . . . ");
290 }
291
292 void tracktorpedo(int x, int y, int ix, int iy, int wait, int l, int i, int n, int iquad)
293 /* torpedo-track animation */
294 {
295     if (!curses) {
296         if (l == 1) {
297             if (n != 1) {
298                 skip(1);
299                 proutn("Track for torpedo number %d-  ", i);
300             }
301             else {
302                 skip(1);
303                 proutn("Torpedo track- ");
304             }
305         } else if (l==4 || l==9) 
306             skip(1);
307         proutn("%d - %d   ", (int)x, (int)y);
308     } else {
309         if (game.damage[DSRSENS]==0 || condit==IHDOCKED) {
310             drawmaps(2);
311             delay((wait!=1)*400);
312             if ((game.quad[ix][iy]==IHDOT)||(game.quad[ix][iy]==IHBLANK)){
313                 game.quad[ix][iy]='+';
314                 drawmaps(2);
315                 game.quad[ix][iy]=iquad;
316                 sound(l*10);
317                 delay(100);
318                 nosound();
319             }
320             else {
321                 game.quad[ix][iy] |= DAMAGED;
322                 drawmaps(2);
323                 game.quad[ix][iy]=iquad;
324                 sound(500);
325                 delay(1000);
326                 nosound();
327                 wattroff(curwnd, A_REVERSE);
328             }
329         } else {
330             proutn("%d - %d   ", (int)x, (int)y);
331         }
332     }
333 }
334
335 void makechart(void) 
336 {
337     if (curses) {
338         setwnd(LOWER_WINDOW);
339         wclear(LOWER_WINDOW);
340         chart(0);
341     }
342 }
343
344 void setpassword(void) 
345 {
346     if (!curses) {
347         while (TRUE) {
348             scan();
349             strcpy(game.passwd, citem);
350             chew();
351             if (*game.passwd != 0) break;
352             proutn("Please type in a secret password-");
353         }
354     } else {
355         int i;
356         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
357         game.passwd[3]=0;
358     }
359 }
360