getline -> cgetline.
[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
10 #include "conio.h"
11 #include "sstlinux.h"
12 #include "sst.h"
13
14 #ifndef SERGEEV
15 static int linecount;   /* for paging */
16 #endif /* SERGEEV */
17 static int screenheight = 24, screenwidth = 80;
18 #ifndef SERGEEV
19 static int curses = FALSE;
20 #else /* SERGEEV */
21 static int curses = TRUE;
22 #endif /* SERGEEV */
23
24 #ifdef SERGEEV
25 wnd wnds[6]={{1,1,80,25},       /* FULLSCREEN_WINDOW */
26              {1,1,25,12},       /* LEFTUPPER_WINDOW */
27              {26,2,80,12},      /* SRSCAN_WINDOW */
28              {65,1,80,10},      /* LRSCAN_WINDOW */
29              {1,13,80,23},      /* LOWER_WINDOW */
30              {1,24,80,25},      /* BOTTOM_WINDOW */
31 };
32 short curwnd;
33 #endif /* SERGEEV */
34
35 static void outro(int sig) {
36 /* wrap up, either normally or due to signal */
37     if (curses) {
38         clear();
39         (void)refresh();
40         (void)resetterm();
41         //(void)echo();
42         (void)endwin();
43     }
44 }
45
46 static void fastexit(int sig) {
47     outro(sig);
48     putchar('\n');
49     exit(0);
50 }
51
52 void iostart(int usecurses) {
53         (void) signal(SIGINT, fastexit);
54         (void) signal(SIGINT, fastexit);
55 #ifdef SIGIOT
56         (void) signal(SIGIOT,fastexit);         /* for assert(3) */
57 #endif /* SIGIOT */
58         if(signal(SIGQUIT,SIG_IGN) != SIG_IGN)
59             (void)signal(SIGQUIT,fastexit);
60
61         if ((curses = usecurses)) {
62                 (void)initscr();
63 #ifdef KEY_MIN
64                 keypad(stdscr, TRUE);
65 #endif /* KEY_MIN */
66                 (void)saveterm();
67                 (void)nonl();
68                 (void)cbreak();
69                 //(void)noecho();
70                 scrollok(stdscr, TRUE);
71                 getmaxyx(stdscr, screenheight, screenwidth);
72         } else {
73                 char *LINES = getenv("LINES");
74                 if (LINES)
75                     screenheight = atoi(LINES);
76         }
77 }
78
79 void ioend(void) {
80     outro(0);
81 }
82
83 void waitfor(void) {
84 /* wait for user action -- OK to do nothing if on a TTY */
85 #ifdef SERGEEV
86         getche();
87 #endif /* SERGEEV */
88 }
89
90 void pause_game(int i) {
91         char *prompt;
92 #ifndef SERGEEV
93         char buf[BUFSIZ];
94 #else /* SERGEEV */
95         drawmaps(0);
96         setwnd(BOTTOM_WINDOW);
97 #endif /* SERGEEV */
98         if (i==1) {
99                 if (skill > 2)
100                         prompt = "[ANOUNCEMENT ARRIVING...]";
101                 else
102                         prompt = "[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]";
103         }
104         else {
105                 if (skill > 2)
106                         prompt = "[CONTINUE?]";
107                 else
108                         prompt = "[PRESS ENTER TO CONTINUE]";
109
110         }
111 #ifndef SERGEEV
112         if (curses) {
113             waddch(stdscr, '\n');
114                 waddstr(stdscr, prompt);
115                 wgetnstr(stdscr, buf, sizeof(buf));
116                 wclear(stdscr);
117                 wrefresh(stdscr);
118         } else {
119                 putchar('\n');
120                 proutn(prompt);
121                 fgets(buf, sizeof(buf), stdin);
122                 if (i != 0) {
123                     /* much more in that old-TTY spirit to throw linefeeds */
124                     int j;
125                     for (j = 0; j < screenheight; j++)
126                         putchar('\n');
127                 }
128                 linecount = 0;
129         }
130 #else /* SERGEEV */
131         proutn(prompt);
132         getche();
133         clrscr();
134         setwnd(LOWER_WINDOW);
135         clrscr();
136 #endif /* SERGEEV */
137 }
138
139
140 void skip(int i) {
141 #ifndef SERGEEV
142     while (i-- > 0) {
143         if (curses) {
144             int y, x;
145             getyx(stdscr, y, x);
146             if (y == screenheight-1)
147                 pause_game(0);
148             else
149                 waddch(stdscr, '\n');
150         } else {
151             linecount++;
152             if (linecount >= screenheight)
153                 pause_game(0);
154             else
155                 putchar('\n');
156         }
157 #else /* SERGEEV */
158         while (i-- > 0) proutn("\n\r");
159 }
160
161 static void vproutn(char *fmt, va_list ap) {
162     char *s, *p;
163     vasprintf(&s, fmt, ap);
164     p=s;
165     if ((curwnd==LOWER_WINDOW)&&(wherey()==wnds[curwnd].wndbottom-wnds[curwnd].wndtop)){
166        if (strchr(s,'\n')) {
167           p=strchr(s,'\n');
168           p[0]=0;
169           cprintf("%s",s);
170           p++;
171           pause_game(0);
172        }
173 #endif /* SERGEEV */
174     }
175 #ifdef SERGEEV
176     if ((curwnd==LOWER_WINDOW)&&(wherey()>wnds[curwnd].wndbottom-wnds[curwnd].wndtop+1))
177        cprintf("\r");
178 //        setwnd(curwnd);
179     if (strchr(s,'\n') || strchr(s,'\r')) clreol();
180     cprintf("%s",p);
181     free(s);
182 #endif /* SERGEEV */
183 }
184
185 void proutn(char *fmt, ...) {
186     va_list ap;
187     va_start(ap, fmt);
188 #ifndef SERGEEV
189     if (curses) {
190         vw_printw(stdscr, fmt, ap);
191         wrefresh(stdscr);
192     } else
193         vprintf(fmt, ap);
194 #else /* SERGEEV */
195     vproutn(fmt, ap);
196 #endif /* SERGEEV */
197     va_end(ap);
198 }
199
200 void prout(char *fmt, ...) {
201     va_list ap;
202     va_start(ap, fmt);
203 #ifndef SERGEEV
204     if (curses) {
205         vw_printw(stdscr, fmt, ap);
206         wrefresh(stdscr);
207     } else
208         vprintf(fmt, ap);
209 #else /* SERGEEV */
210     vproutn(fmt, ap);
211 #endif /* SERGEEV */
212     va_end(ap);
213     skip(1);
214 }
215
216 void proutc(char *line) {
217     line[strlen(line)-1] = '\0';
218 #ifndef SERGEEV
219     if (curses)
220         waddstr(stdscr, line);
221     else
222         fputs(line, stdout);
223 #else /* SERGEEV */
224     cputs(line);
225 #endif /* SERGEEV */
226     skip(1);
227 }
228
229 #ifdef SERGEEV
230 static void prchr(char *s){
231      char str[2];
232      strncpy(str,s,1);
233      str[1]=0;
234      proutn(str);
235 }
236
237 static void vprouts(char *fmt, va_list ap) {
238     char *s, *p;
239     vasprintf(&s, fmt, ap);
240     p=s;
241     while (*p) {
242         prchr(p++);
243         delay(30);
244     }
245     free(s);
246 }
247
248 #endif /* SERGEEV */
249 void prouts(char *fmt, ...) {
250 #ifndef SERGEEV
251         clock_t endTime;
252         char *s, buf[BUFSIZ];
253         /* print slowly! */
254         va_list ap;
255         va_start(ap, fmt);
256         vsprintf(buf, fmt, ap);
257         va_end(ap);
258         skip(1);
259         for (s = buf; *s; s++) {
260                 endTime = clock() + CLOCKS_PER_SEC*0.05;
261                 while (clock() < endTime) continue;
262                 if (curses) {
263                     waddch(stdscr, *s);
264                     wrefresh(stdscr);
265                 }
266                 else {
267                     putchar(*s);
268                     fflush(stdout);
269                 }
270         }
271 #else /* SERGEEV */
272     va_list ap;
273     va_start(ap, fmt);
274     vprouts(fmt, ap);
275     va_end(ap);
276 #endif /* SERGEEV */
277 }
278
279 void c_printf (char *format, ... )
280 {
281     char buffer[BUFSIZ]; /* Well, BUFSIZ is from ncurses...  */
282     va_list argp;
283     va_start(argp,format);
284     vsprintf(buffer,format,argp);
285     va_end(argp);
286 #ifdef SERGEEV
287     waddstr(conio_scr,buffer);
288 #else
289     proutn(buffer);
290 #endif /* SERGEEV */
291 }
292
293 void warble(void)
294 /* sound and visual effects for teleportation */
295 {
296 #ifdef SERGEEV
297     int posx, posy;
298     posx=wherex();
299     posy=wherey();
300     drawmaps(1);
301     setwnd(LOWER_WINDOW);
302     gotoxy(posx,posy);
303     sound(50);
304     delay(1000);
305     nosound();
306 #else
307     prouts(" . . . . . ");
308 #endif /* SERGEEV */
309 }
310
311 void setpassword(void) {
312 #ifndef SERGEEV
313         while (TRUE) {
314                 scan();
315                 strcpy(game.passwd, citem);
316                 chew();
317                 if (*game.passwd != 0) break;
318                 proutn("Please type in a secret password-");
319         }
320 #else
321         int i;
322         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
323         game.passwd[3]=0;
324 #endif /* SERGEEV */
325 }
326
327 void cgetline(char *line, int max) {
328     if (curses) {
329 #ifndef SERGEEV
330         wgetnstr(stdscr, line, max);
331         wrefresh(stdscr);
332 #else /* SERGEEV */
333         line[0]=max-1;
334         cgets(line);
335         memmove(line,&line[2],max-3);
336 #endif /* SERGEEV */
337     } else {
338         fgets(line, max, stdin);
339         line[strlen(line)-1] = '\0';
340     }
341 }
342
343 void setwnd(short wndnum){
344 /* change windows -- OK for this to be a no-op in tty mode */
345 #ifdef SERGEEV
346      int cury;
347      cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
348      if ((curwnd==FULLSCREEN_WINDOW)&&(wndnum!=FULLSCREEN_WINDOW)) clrscr();
349      window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
350      if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
351         gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
352         skip(1);
353      }
354      curwnd=wndnum;
355      gotoxy(1,cury);
356 #endif /* SERGEEV */
357 }
358
359 void commandhook(char *cmd, int before) {
360 }