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