]> code.citadel.org Git - citadel.git/blob - citadel/screen.c
* curses client: allow goodbye message to be seen on some terminals
[citadel.git] / citadel / screen.c
1 /* $Id$ */
2
3 /*
4  * Handle full-screen curses stuff
5  */
6
7 #include "sysdep.h"
8 #ifdef HAVE_CURSES_H
9 #include <curses.h>
10 #endif
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <unistd.h>
15 #include <sys/types.h>
16 #ifdef VW_PRINTW_IN_CURSES
17 #define _vwprintw vw_printw
18 #else
19 /* Ancient curses implementations, this needs testing. Anybody got XENIX? */
20 #define _vwprintw vwprintw
21 #endif
22 #ifndef HAVE_SNPRINTF
23 #include "snprintf.h"
24 #endif
25 #include "citadel.h"
26 #include "commands.h"
27 #include "screen.h"
28
29 #ifdef HAVE_CURSES_H
30 static SCREEN *myscreen = NULL;
31 static WINDOW *mainwindow = NULL;
32 static WINDOW *statuswindow = NULL;
33
34 char rc_screen;
35 char arg_screen;
36
37 extern int screenheight;
38 extern int screenwidth;
39 extern int rc_ansi_color;
40 extern void check_screen_dims(void);
41 #endif
42
43
44 /*
45  * status_line() is a convenience function for writing a "typical"
46  * status line to the window.
47  */
48 void status_line(const char *humannode, const char *bbs_city,
49                  const char *room_name, int secure, int newmailcount)
50 {
51 #ifdef HAVE_CURSES_H
52         if (statuswindow) {
53                 if (secure)
54                         sln_printf("Secure ");
55                 else
56                         sln_printf("Not secure ");
57                 waddch(statuswindow, ACS_VLINE);
58                 waddch(statuswindow, ' ');
59                 if (humannode && bbs_city)
60                         sln_printf("%s at %s ", humannode, bbs_city);
61                 if (room_name)
62                         sln_printf("in %s ", room_name);
63                 if (newmailcount > -1) {
64                         waddch(statuswindow, ACS_VLINE);
65                         sln_printf(" %d unread mail", newmailcount);
66                 }
67                 sln_printf("\n");
68         }
69 #endif /* HAVE_CURSES_H */
70 }
71
72
73 /*
74  * Initialize the screen.  If newterm() fails, myscreen will be NULL and
75  * further handlers will assume we should be in line mode.
76  */
77 void screen_new(void)
78 {
79 #ifdef HAVE_CURSES_H
80         if (arg_screen != RC_NO && rc_screen != RC_NO)
81                 myscreen = newterm(NULL, stdout, stdin);
82         if (myscreen) {
83                 cbreak();
84                 noecho();
85                 nonl();
86                 intrflush(stdscr, FALSE);
87                 keypad(stdscr, TRUE);
88                 /* Setup all our colors */
89                 start_color();
90                 if (rc_ansi_color)
91                         enable_color = 1;
92                 init_pair(1+DIM_BLACK, COLOR_BLACK, COLOR_BLACK);
93                 init_pair(1+DIM_RED, COLOR_RED, COLOR_BLACK);
94                 init_pair(1+DIM_GREEN, COLOR_GREEN, COLOR_BLACK);
95                 init_pair(1+DIM_YELLOW, COLOR_YELLOW, COLOR_BLACK);
96                 init_pair(1+DIM_BLUE, COLOR_BLUE, COLOR_BLACK);
97                 init_pair(1+DIM_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
98                 init_pair(1+DIM_CYAN, COLOR_CYAN, COLOR_BLACK);
99                 init_pair(1+DIM_WHITE, COLOR_WHITE, COLOR_BLACK);
100                 init_pair(17, COLOR_WHITE, COLOR_BLUE);
101         } else
102 #endif /* HAVE_CURSES_H */
103         {
104                 send_ansi_detect();
105                 look_for_ansi();
106                 cls(0);
107                 color(1+DIM_WHITE);
108         }
109         screen_set();
110         windows_new();
111 }
112
113
114 /*
115  * Kill the screen completely (used at exit).  It is safe to call this
116  * function more than once.
117  */
118 void screen_delete(void)
119 {
120         windows_delete();
121         screen_reset();
122 #ifdef HAVE_CURSES_H
123         if (myscreen)
124                 delscreen(myscreen);
125         myscreen = NULL;
126 #endif
127 }
128
129
130 /*
131  * Set screen/IO parameters, e.g. at start of program or return from external
132  * program run.
133  */
134 int screen_set(void)
135 {
136 #ifdef HAVE_CURSES_H
137         if (myscreen) {
138                 set_term(myscreen);
139                 wrefresh(curscr);
140                 return 1;
141         }
142 #endif /* HAVE_CURSES_H */
143         return 0;
144 }
145
146
147 /*
148  * Reset screen/IO parameters, e.g. at exit or fork of external program.
149  */
150 int screen_reset(void)
151 {
152 #ifdef HAVE_CURSES_H
153         if (myscreen) {
154                 endwin();
155                 return 1;
156         }
157 #endif /* HAVE_CURSES_H */
158         return 0;
159 }
160
161
162 /*
163  * scr_printf() outputs to the main window (or screen if not in curses)
164  */
165 int scr_printf(char *fmt, ...)
166 {
167         va_list ap;
168         register int retval;
169
170         va_start(ap, fmt);
171 #ifdef HAVE_CURSES_H
172         if (mainwindow) {
173                 retval = _vwprintw(mainwindow, fmt, ap);
174                 /*
175                 if (fmt[strlen(fmt) - 1] == '\n')
176                         wrefresh(mainwindow);
177                 */
178         } else
179 #endif
180                 retval = vprintf(fmt, ap);
181         va_end(ap);
182         return retval;
183 }
184
185
186 /*
187  * err_printf() outputs to error status window (or stderr if not in curses)
188  */
189 int err_printf(char *fmt, ...)
190 {
191         va_list ap;
192         register int retval;
193
194         va_start(ap, fmt);
195 #ifdef HAVE_CURSES_H
196         if (mainwindow) {               /* FIXME: direct to error window */
197                 retval = _vwprintw(mainwindow, fmt, ap);
198                 if (fmt[strlen(fmt) - 1] == '\n')
199                         wrefresh(mainwindow);
200         } else
201 #endif
202                 retval = vfprintf(stderr, fmt, ap);
203         va_end(ap);
204         return retval;
205 }
206
207
208 /*
209  * sln_printf() outputs to error status window (or stderr if not in curses)
210  */
211 int sln_printf(char *fmt, ...)
212 {
213         va_list ap;
214         register int retval;
215 #ifdef HAVE_CURSES_H
216         static char buf[4096];
217 #endif
218
219         va_start(ap, fmt);
220 #ifdef HAVE_CURSES_H
221         if (statuswindow) {
222                 register char *i;
223                 
224                 retval = vsnprintf(buf, 4096, fmt, ap);
225                 for (i = buf; *i; i++) {
226                         if (*i == '\r' || *i == '\n')
227                                 wclrtoeol(statuswindow);
228                         sln_putc(*i);
229                         if (*i == '\r' || *i == '\n')
230                                 mvwinch(statuswindow, 0, 0);
231                 }
232         } else
233 #endif
234                 retval = vprintf(fmt, ap);
235         va_end(ap);
236         return retval;
237 }
238
239
240 /*
241  * sln_printf_if() outputs to status window, no output if not in curses
242  */
243 int sln_printf_if(char *fmt, ...)
244 {
245         register int retval = 1;
246 #ifdef HAVE_CURSES_H
247         static char buf[4096];
248         va_list ap;
249
250         va_start(ap, fmt);
251         if (statuswindow) {
252                 register char *i;
253                 
254                 retval = vsnprintf(buf, 4096, fmt, ap);
255                 for (i = buf; *i; i++) {
256                         if (*i == '\r' || *i == '\n')
257                                 wclrtoeol(statuswindow);
258                         sln_putc(*i);
259                         if (*i == '\r' || *i == '\n')
260                                 mvwinch(statuswindow, 0, 0);
261                 }
262         }
263         va_end(ap);
264 #endif
265         return retval;
266 }
267
268
269 int scr_getc(void)
270 {
271 #ifdef HAVE_CURSES_H
272         if (mainwindow)
273                 return wgetch(mainwindow);
274 #endif
275         return getchar();
276 }
277
278
279 /*
280  * scr_putc() outputs a single character
281  */
282 int scr_putc(int c)
283 {
284 #ifdef HAVE_CURSES_H
285         if (mainwindow)
286                 return ((waddch(mainwindow, c) == OK) ? c : EOF);
287 #endif
288         return putc(c, stdout);
289 }
290
291
292 int sln_putc(int c)
293 {
294 #ifdef HAVE_CURSES_H
295         if (statuswindow)
296                 return ((waddch(statuswindow, c) == OK) ? c : EOF);
297 #endif
298         return putc(c, stdout);
299 }
300
301
302 int sln_putc_if(int c)
303 {
304 #ifdef HAVE_CURSES_H
305         if (statuswindow)
306                 return ((waddch(statuswindow, c) == OK) ? c : EOF);
307 #endif
308         return 1;
309 }
310
311
312 /*
313  * scr_color() sets the window color for mainwindow
314  */
315 int scr_color(int colornum)
316 {
317 #ifdef HAVE_CURSES_H
318         if (mainwindow) {
319                 wcolor_set(mainwindow, 1 + (colornum & 7), NULL);
320                 if (colornum & 8) {
321                         wattron(mainwindow, A_BOLD);
322                 } else {
323                         wattroff(mainwindow, A_BOLD);
324                 }
325                 return 1;
326         }
327 #endif
328         return 0;
329 }
330
331
332 void scr_flush(void)
333 {
334 #ifdef HAVE_CURSES_H
335         if (mainwindow)
336                 wrefresh(mainwindow);
337         else
338 #endif
339                 fflush(stdout);
340 }
341
342
343 void err_flush(void)
344 {
345 #ifdef HAVE_CURSES_H
346         if (mainwindow)         /* FIXME: error status window needed */
347                 wrefresh(mainwindow);
348         else
349 #endif
350                 fflush(stderr);
351 }
352
353
354 void sln_flush(void)
355 {
356 #ifdef HAVE_CURSES_H
357         if (statuswindow)
358                 wrefresh(statuswindow);
359         else
360 #endif
361                 fflush(stdout);
362 }
363
364
365 int scr_set_windowsize(void)
366 {
367 #ifdef HAVE_CURSES_H
368         int y, x;
369
370         if (mainwindow) {
371                 getmaxyx(mainwindow, y, x);
372                 screenheight = y;
373                 screenwidth = x;
374                 return 1;
375         }
376 #endif /* HAVE_CURSES_H */
377         return 0;
378 }
379
380
381 /*
382  * scr_winch() handles window size changes from SIGWINCH
383  * resizes all our windows for us
384  */
385 RETSIGTYPE scr_winch(void)
386 {
387 #ifdef HAVE_CURSES_H
388         /* FIXME: not implemented */
389 #endif
390         check_screen_dims();
391 }
392
393
394 /*
395  * Initialize the window(s) we will be using.
396  */
397 void windows_new(void)
398 {
399 #ifdef HAVE_CURSES_H
400         register int x, y;
401
402         if (myscreen) {
403                 getmaxyx(stdscr, y, x);
404                 mainwindow = newwin(y - 1, x, 0, 0);
405                 screenwidth = x;
406                 screenheight = y - 1;
407                 immedok(mainwindow, FALSE);
408                 leaveok(mainwindow, FALSE);
409                 scrollok(mainwindow, TRUE);
410                 statuswindow = newwin(1, x, y - 1, 0);
411                 wbkgdset(statuswindow, COLOR_PAIR(17));
412                 werase(statuswindow);
413                 immedok(statuswindow, TRUE);
414                 leaveok(statuswindow, FALSE);
415                 scrollok(statuswindow, FALSE);
416                 wrefresh(statuswindow);
417         }
418 #else /* HAVE_CURSES_H */
419
420 #endif /* HAVE_CURSES_H */
421 }
422
423
424 /*
425  * Deinitialize the window(s) we were using (at exit).
426  */
427 void windows_delete(void)
428 {
429 #ifdef HAVE_CURSES_H
430         if (mainwindow)
431                 delwin(mainwindow);
432         mainwindow = NULL;
433         if (statuswindow)
434                 delwin(statuswindow);
435         statuswindow = NULL;
436 #else /* HAVE_CURSES_H */
437
438 #endif /* HAVE_CURSES_H */
439 }