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