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