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