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