Get rid of c_printf().
[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 cgetline(char *line, int max) {
294     if (curses) {
295 #ifndef SERGEEV
296         wgetnstr(stdscr, line, max);
297         wrefresh(stdscr);
298 #else /* SERGEEV */
299         line[0]=max-1;
300         cgets(line);
301         memmove(line,&line[2],max-3);
302 #endif /* SERGEEV */
303     } else {
304         fgets(line, max, stdin);
305         line[strlen(line)-1] = '\0';
306     }
307 }
308
309 void setwnd(short wndnum){
310 /* change windows -- OK for this to be a no-op in tty mode */
311 #ifdef SERGEEV
312      int cury;
313      cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
314      if ((curwnd==FULLSCREEN_WINDOW)&&(wndnum!=FULLSCREEN_WINDOW)) clrscr();
315      window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
316      if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
317         gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
318         skip(1);
319      }
320      curwnd=wndnum;
321      gotoxy(1,cury);
322 #endif /* SERGEEV */
323 }
324
325 void commandhook(char *cmd, int before) {
326 }
327
328 /*
329  * Things past this point have policy implications.
330  */
331
332 void drawmaps(short l) {
333 /* hook to be called after moving to redraw maps */
334 #ifdef SERGEEV
335      _setcursortype(_NOCURSOR);
336      if (l==1) sensor();
337      if (l!=2) setwnd(LEFTUPPER_WINDOW);
338      gotoxy(1,1);
339      enqueue("no");
340      srscan(SCAN_FULL);
341      if (l!=2){
342         setwnd(SRSCAN_WINDOW);
343         clrscr();
344         srscan(SCAN_NO_LEFTSIDE);
345         setwnd(LRSCAN_WINDOW);
346         clrscr();
347         enqueue("l");
348         lrscan();
349         _setcursortype(_NORMALCURSOR);
350      }
351 #endif /* SERGEEV */
352 }
353
354 void boom(int ii, int jj)
355 /* enemy fall down, go boom */ 
356 {
357 #ifdef SERGEEV
358     int crx, cry;
359     crx=wherex();
360     cry=wherey();
361     setwnd(LEFTUPPER_WINDOW);
362     drawmaps(2);
363     gotoxy(jj*2+3,ii+2);
364     highvideo();
365     proutn("%c", game.quad[ii][jj]);
366     gotoxy(wherex()-1,wherey());
367     sound(500);
368     delay(1000);
369     nosound();
370     lowvideo();
371     proutn("%c", game.quad[ii][jj]);
372     setwnd(LOWER_WINDOW);
373     gotoxy(crx,cry);
374     _setcursortype(_NORMALCURSOR);
375     delay(500);
376 #endif /* SERGEEV */
377
378
379 void warble(void)
380 /* sound and visual effects for teleportation */
381 {
382 #ifdef SERGEEV
383     int posx, posy;
384     posx=wherex();
385     posy=wherey();
386     drawmaps(1);
387     setwnd(LOWER_WINDOW);
388     gotoxy(posx,posy);
389     sound(50);
390     delay(1000);
391     nosound();
392 #else
393     prouts(" . . . . . ");
394 #endif /* SERGEEV */
395 }
396
397 void tracktorpedo(int x, int y, int ix, int iy, int wait, int l, int i, int n, int iquad)
398 /* torpedo-track animation */
399 {
400 #ifndef SERGEEV
401     if (l == 1) {
402         if (n != 1) {
403             skip(1);
404             proutn("Track for torpedo number %d-  ", i);
405         }
406         else {
407             skip(1);
408             proutn("Torpedo track- ");
409         }
410     } else if (l==4 || l==9) 
411         skip(1);
412     proutn("%d - %d   ", (int)x, (int)y);
413 #else
414     if (game.damage[DSRSENS]==0 || condit==IHDOCKED) {
415         drawmaps(2);
416         delay((wait!=1)*400);
417         gotoxy(iy*2+3,ix+2);
418         if ((game.quad[ix][iy]==IHDOT)||(game.quad[ix][iy]==IHBLANK)){
419             game.quad[ix][iy]='+';
420             drawmaps(2);
421             game.quad[ix][iy]=iquad;
422             sound(l*10);
423             delay(100);
424             nosound();
425         }
426         else {
427             game.quad[ix][iy]|=128;
428             drawmaps(2);
429             game.quad[ix][iy]=iquad;
430             _setcursortype(_NOCURSOR);
431             sound(500);
432             delay(1000);
433             nosound();
434             lowvideo();
435             _setcursortype(_NORMALCURSOR);
436         }
437     } else {
438         proutn("%d - %d   ", (int)x, (int)y);
439     }
440 #endif /* SERGEEV */
441 }
442
443 void makechart(void) {
444 #ifdef SERGEEV
445     _setcursortype(_NOCURSOR);
446     setwnd(LOWER_WINDOW);
447     clrscr();
448     chart(0);
449     _setcursortype(_NORMALCURSOR);
450 #endif /* SERGEEV */
451 }
452
453 void setpassword(void) {
454 #ifndef SERGEEV
455         while (TRUE) {
456                 scan();
457                 strcpy(game.passwd, citem);
458                 chew();
459                 if (*game.passwd != 0) break;
460                 proutn("Please type in a secret password-");
461         }
462 #else
463         int i;
464         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
465         game.passwd[3]=0;
466 #endif /* SERGEEV */
467 }
468