More factoring out.
[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 warble(void)
364 /* sound and visual effects for teleportation */
365 {
366 #ifdef SERGEEV
367     int posx, posy;
368     posx=wherex();
369     posy=wherey();
370     drawmaps(1);
371     setwnd(LOWER_WINDOW);
372     gotoxy(posx,posy);
373     sound(50);
374     delay(1000);
375     nosound();
376 #else
377     prouts(" . . . . . ");
378 #endif /* SERGEEV */
379 }
380
381 void setpassword(void) {
382 #ifndef SERGEEV
383         while (TRUE) {
384                 scan();
385                 strcpy(game.passwd, citem);
386                 chew();
387                 if (*game.passwd != 0) break;
388                 proutn("Please type in a secret password-");
389         }
390 #else
391         int i;
392         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
393         game.passwd[3]=0;
394 #endif /* SERGEEV */
395 }
396