Prevent the sensor display from being garbled.
[super-star-trek.git] / io.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <termios.h>
5 #include <curses.h>
6 #include <signal.h>
7 #include <ctype.h>
8 #include <stdarg.h>
9 #include <time.h>
10
11 #include "conio.h"
12 #include "sst.h"
13 #include "sstlinux.h"
14
15 #ifndef SERGEEV
16 static int linecount;   /* for paging */
17 static int screenheight = 24, screenwidth = 80;
18 #endif /* SERGEEV */
19 #ifndef SERGEEV
20 static int curses = FALSE;
21 #else /* SERGEEV */
22 static int curses = TRUE;
23 #endif /* SERGEEV */
24
25 #ifdef SERGEEV
26 wnd wnds[6]={{1,1,80,25},       /* FULLSCREEN_WINDOW */
27              {1,1,25,12},       /* LEFTUPPER_WINDOW */
28              {26,2,80,12},      /* SRSCAN_WINDOW */
29              {65,1,80,10},      /* LRSCAN_WINDOW */
30              {1,13,80,23},      /* LOWER_WINDOW */
31              {1,24,80,25},      /* BOTTOM_WINDOW */
32 };
33 short curwnd;
34 #endif /* SERGEEV */
35
36 #ifndef SERGEEV
37 static void outro(int sig) {
38 /* wrap up, either normally or due to signal */
39     if (curses) {
40         clear();
41         (void)refresh();
42         (void)resetterm();
43         //(void)echo();
44         (void)endwin();
45     }
46 }
47
48 static void fastexit(int sig) {
49     outro(sig);
50     putchar('\n');
51     exit(0);
52 }
53 #endif /* SERGEEV */
54
55 void iostart(int usecurses) {
56 #ifdef SERGEEV
57         initconio();
58         textattr(7);
59         clrscr();
60         setwnd(FULLSCREEN_WINDOW);
61 #else
62         (void) signal(SIGINT, fastexit);
63         (void) signal(SIGINT, fastexit);
64 #ifdef SIGIOT
65         (void) signal(SIGIOT,fastexit);         /* for assert(3) */
66 #endif /* SIGIOT */
67         if(signal(SIGQUIT,SIG_IGN) != SIG_IGN)
68             (void)signal(SIGQUIT,fastexit);
69
70         if ((curses = usecurses)) {
71                 (void)initscr();
72 #ifdef KEY_MIN
73                 keypad(stdscr, TRUE);
74 #endif /* KEY_MIN */
75                 (void)saveterm();
76                 (void)nonl();
77                 (void)cbreak();
78                 //(void)noecho();
79                 scrollok(stdscr, TRUE);
80                 getmaxyx(stdscr, screenheight, screenwidth);
81         } else {
82                 char *LINES = getenv("LINES");
83                 if (LINES)
84                     screenheight = atoi(LINES);
85         }
86 #endif /* SERGEEV */
87 }
88
89 void ioend(void) {
90 #ifndef SERGEEV
91     outro(0);
92 #endif /* SERGEEV */
93 }
94
95 void waitfor(void) {
96 /* wait for user action -- OK to do nothing if on a TTY */
97 #ifdef SERGEEV
98         getche();
99 #endif /* SERGEEV */
100 }
101
102 void pause_game(int i) {
103         char *prompt;
104 #ifndef SERGEEV
105         char buf[BUFSIZ];
106 #else /* SERGEEV */
107         drawmaps(0);
108         setwnd(BOTTOM_WINDOW);
109 #endif /* SERGEEV */
110         if (i==1) {
111                 if (skill > 2)
112                         prompt = "[ANOUNCEMENT ARRIVING...]";
113                 else
114                         prompt = "[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]";
115         }
116         else {
117                 if (skill > 2)
118                         prompt = "[CONTINUE?]";
119                 else
120                         prompt = "[PRESS ENTER TO CONTINUE]";
121
122         }
123 #ifndef SERGEEV
124         if (curses) {
125             waddch(stdscr, '\n');
126                 waddstr(stdscr, prompt);
127                 wgetnstr(stdscr, buf, sizeof(buf));
128                 wclear(stdscr);
129                 wrefresh(stdscr);
130         } else {
131                 putchar('\n');
132                 proutn(prompt);
133                 fgets(buf, sizeof(buf), stdin);
134                 if (i != 0) {
135                     /* much more in that old-TTY spirit to throw linefeeds */
136                     int j;
137                     for (j = 0; j < screenheight; j++)
138                         putchar('\n');
139                 }
140                 linecount = 0;
141         }
142 #else /* SERGEEV */
143         proutn(prompt);
144         getche();
145         clrscr();
146         setwnd(LOWER_WINDOW);
147         clrscr();
148 #endif /* SERGEEV */
149 }
150
151
152 void skip(int i) {
153 #ifndef SERGEEV
154     while (i-- > 0) {
155         if (curses) {
156             int y, x;
157             getyx(stdscr, y, x);
158             if (y == screenheight-1)
159                 pause_game(0);
160             else
161                 waddch(stdscr, '\n');
162         } else {
163             linecount++;
164             if (linecount >= screenheight)
165                 pause_game(0);
166             else
167                 putchar('\n');
168         }
169 #else /* SERGEEV */
170         while (i-- > 0) proutn("\n\r");
171 #endif /* SERGEEV */
172 }
173
174 static void vproutn(char *fmt, va_list ap) {
175 #ifdef SERGEEV
176     char *s, *p;
177     vasprintf(&s, fmt, ap);
178     p=s;
179     if ((curwnd==LOWER_WINDOW)&&(wherey()==wnds[curwnd].wndbottom-wnds[curwnd].wndtop)){
180        if (strchr(s,'\n')) {
181           p=strchr(s,'\n');
182           p[0]=0;
183           cprintf("%s",s);
184           p++;
185           pause_game(0);
186        }
187 #endif /* SERGEEV */
188     }
189 #ifdef SERGEEV
190     if ((curwnd==LOWER_WINDOW)&&(wherey()>wnds[curwnd].wndbottom-wnds[curwnd].wndtop+1))
191        cprintf("\r");
192 //        setwnd(curwnd);
193     if (strchr(s,'\n') || strchr(s,'\r')) clreol();
194     cprintf("%s",p);
195     free(s);
196 #endif /* SERGEEV */
197 }
198
199 void proutn(char *fmt, ...) {
200     va_list ap;
201     va_start(ap, fmt);
202 #ifndef SERGEEV
203     if (curses) {
204         vw_printw(stdscr, fmt, ap);
205         wrefresh(stdscr);
206     } else
207         vprintf(fmt, ap);
208 #else /* SERGEEV */
209     vproutn(fmt, ap);
210 #endif /* SERGEEV */
211     va_end(ap);
212 }
213
214 void prout(char *fmt, ...) {
215     va_list ap;
216     va_start(ap, fmt);
217 #ifndef SERGEEV
218     if (curses) {
219         vw_printw(stdscr, fmt, ap);
220         wrefresh(stdscr);
221     } else
222         vprintf(fmt, ap);
223 #else /* SERGEEV */
224     vproutn(fmt, ap);
225 #endif /* SERGEEV */
226     va_end(ap);
227     skip(1);
228 }
229
230 void proutc(char *line) {
231     line[strlen(line)-1] = '\0';
232 #ifndef SERGEEV
233     if (curses)
234         waddstr(stdscr, line);
235     else
236         fputs(line, stdout);
237 #else /* SERGEEV */
238     cputs(line);
239 #endif /* SERGEEV */
240     skip(1);
241 }
242
243 #ifdef SERGEEV
244 static void prchr(char *s){
245      char str[2];
246      strncpy(str,s,1);
247      str[1]=0;
248      proutn(str);
249 }
250
251 static void vprouts(char *fmt, va_list ap) {
252     char *s, *p;
253     vasprintf(&s, fmt, ap);
254     p=s;
255     while (*p) {
256         prchr(p++);
257         delay(30);
258     }
259     free(s);
260 }
261 #endif /* SERGEEV */
262
263 void prouts(char *fmt, ...) {
264 #ifndef SERGEEV
265         clock_t endTime;
266         char *s, buf[BUFSIZ];
267         /* print slowly! */
268         va_list ap;
269         va_start(ap, fmt);
270         vsprintf(buf, fmt, ap);
271         va_end(ap);
272         skip(1);
273         for (s = buf; *s; s++) {
274                 endTime = clock() + CLOCKS_PER_SEC*0.05;
275                 while (clock() < endTime) continue;
276                 if (curses) {
277                     waddch(stdscr, *s);
278                     wrefresh(stdscr);
279                 }
280                 else {
281                     putchar(*s);
282                     fflush(stdout);
283                 }
284         }
285 #else /* SERGEEV */
286     va_list ap;
287     va_start(ap, fmt);
288     vprouts(fmt, ap);
289     va_end(ap);
290 #endif /* SERGEEV */
291 }
292
293 void c_printf (char *format, ... )
294 {
295     char buffer[BUFSIZ]; /* Well, BUFSIZ is from ncurses...  */
296     va_list argp;
297     va_start(argp,format);
298     vsprintf(buffer,format,argp);
299     va_end(argp);
300 #ifdef SERGEEV
301     waddstr(conio_scr,buffer);
302 #else
303     proutn(buffer);
304 #endif /* SERGEEV */
305 }
306
307 void cgetline(char *line, int max) {
308     if (curses) {
309 #ifndef SERGEEV
310         wgetnstr(stdscr, line, max);
311         wrefresh(stdscr);
312 #else /* SERGEEV */
313         line[0]=max-1;
314         cgets(line);
315         memmove(line,&line[2],max-3);
316 #endif /* SERGEEV */
317     } else {
318         fgets(line, max, stdin);
319         line[strlen(line)-1] = '\0';
320     }
321 }
322
323 void setwnd(short wndnum){
324 /* change windows -- OK for this to be a no-op in tty mode */
325 #ifdef SERGEEV
326      int cury;
327      cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
328      if ((curwnd==FULLSCREEN_WINDOW)&&(wndnum!=FULLSCREEN_WINDOW)) clrscr();
329      window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
330      if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
331         gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
332         skip(1);
333      }
334      curwnd=wndnum;
335      gotoxy(1,cury);
336 #endif /* SERGEEV */
337 }
338
339 void commandhook(char *cmd, int before) {
340 }
341
342 /*
343  * Things past this point have policy implications.
344  */
345
346 void drawmaps(short l) {
347 /* hook to be called after moving to redraw maps */
348 #ifdef SERGEEV
349      _setcursortype(_NOCURSOR);
350      if (l==1) sensor();
351      if (l!=2) setwnd(LEFTUPPER_WINDOW);
352      gotoxy(1,1);
353      enqueue("no");
354      srscan(SCAN_FULL);
355      if (l!=2){
356         setwnd(SRSCAN_WINDOW);
357         clrscr();
358         srscan(SCAN_NO_LEFTSIDE);
359         setwnd(LRSCAN_WINDOW);
360         clrscr();
361         enqueue("l");
362         lrscan();
363         _setcursortype(_NORMALCURSOR);
364      }
365 #endif /* SERGEEV */
366 }
367
368 void boom(int ii, int jj)
369 /* enemy fall down, go boom */ 
370 {
371 #ifdef SERGEEV
372     int crx, cry;
373     crx=wherex();
374     cry=wherey();
375     setwnd(LEFTUPPER_WINDOW);
376     drawmaps(2);
377     gotoxy(jj*2+3,ii+2);
378     highvideo();
379     proutn("%c", game.quad[ii][jj]);
380     gotoxy(wherex()-1,wherey());
381     sound(500);
382     delay(1000);
383     nosound();
384     lowvideo();
385     proutn("%c", game.quad[ii][jj]);
386     setwnd(LOWER_WINDOW);
387     gotoxy(crx,cry);
388     _setcursortype(_NORMALCURSOR);
389     delay(500);
390 #endif /* SERGEEV */
391
392
393 void warble(void)
394 /* sound and visual effects for teleportation */
395 {
396 #ifdef SERGEEV
397     int posx, posy;
398     posx=wherex();
399     posy=wherey();
400     drawmaps(1);
401     setwnd(LOWER_WINDOW);
402     gotoxy(posx,posy);
403     sound(50);
404     delay(1000);
405     nosound();
406 #else
407     prouts(" . . . . . ");
408 #endif /* SERGEEV */
409 }
410
411 void tracktorpedo(int x, int y, int ix, int iy, int wait, int l, int i, int n, int iquad)
412 /* torpedo-track animation */
413 {
414 #ifndef SERGEEV
415     if (l == 1) {
416         if (n != 1) {
417             skip(1);
418             proutn("Track for torpedo number %d-  ", i);
419         }
420         else {
421             skip(1);
422             proutn("Torpedo track- ");
423         }
424     } else if (l==4 || l==9) 
425         skip(1);
426     proutn("%d - %d   ", (int)x, (int)y);
427 #else
428     if (game.damage[DSRSENS]==0 || condit==IHDOCKED) {
429         drawmaps(2);
430         delay((wait!=1)*400);
431         gotoxy(iy*2+3,ix+2);
432         if ((game.quad[ix][iy]==IHDOT)||(game.quad[ix][iy]==IHBLANK)){
433             game.quad[ix][iy]='+';
434             drawmaps(2);
435             game.quad[ix][iy]=iquad;
436             sound(l*10);
437             delay(100);
438             nosound();
439         }
440         else {
441             game.quad[ix][iy]|=128;
442             drawmaps(2);
443             game.quad[ix][iy]=iquad;
444             _setcursortype(_NOCURSOR);
445             sound(500);
446             delay(1000);
447             nosound();
448             lowvideo();
449             _setcursortype(_NORMALCURSOR);
450         }
451     } else {
452         proutn("%d - %d   ", (int)x, (int)y);
453     }
454 #endif /* SERGEEV */
455 }
456
457 void makechart(void) {
458 #ifdef SERGEEV
459     _setcursortype(_NOCURSOR);
460     setwnd(LOWER_WINDOW);
461     clrscr();
462     chart(0);
463     _setcursortype(_NORMALCURSOR);
464 #endif /* SERGEEV */
465 }
466
467 void setpassword(void) {
468 #ifndef SERGEEV
469         while (TRUE) {
470                 scan();
471                 strcpy(game.passwd, citem);
472                 chew();
473                 if (*game.passwd != 0) break;
474                 proutn("Please type in a secret password-");
475         }
476 #else
477         int i;
478         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
479         game.passwd[3]=0;
480 #endif /* SERGEEV */
481 }
482