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