* upgraded new version of tiny_mce
[citadel.git] / citadel / screen.c
bloba1d8abd7546f0c477d62725f061458e36fc40684
1 /* $Id$ */
3 /*
4 * Handle full-screen curses stuff
5 */
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <signal.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <sys/types.h>
14 #include "sysdep.h"
15 #ifdef HAVE_VW_PRINTW
16 #define _vwprintw vw_printw
17 #else
18 /* SYSV style curses (Solaris, etc.) */
19 #define _vwprintw vwprintw
20 #endif
21 #ifndef HAVE_SNPRINTF
22 #include "snprintf.h"
23 #endif
24 #include "citadel.h"
25 #include "citadel_ipc.h"
26 #include "citadel_decls.h"
27 #include "commands.h"
28 #include "screen.h"
30 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
31 static SCREEN *myscreen = NULL;
32 static WINDOW *mainwindow = NULL;
33 static WINDOW *statuswindow = NULL;
35 char rc_screen;
36 #endif
37 char arg_screen;
39 extern int screenheight;
40 extern int screenwidth;
41 extern int rc_ansi_color;
42 extern void check_screen_dims(void);
44 void do_keepalive(void);
47 int is_curses_enabled(void) {
48 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
49 return mainwindow != NULL;
50 #else
51 return 0;
52 #endif
56 * status_line() is a convenience function for writing a "typical"
57 * status line to the window.
59 void status_line(const char *humannode, const char *site_location,
60 const char *room_name, int secure, int newmailcount)
62 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
63 if (statuswindow) {
64 if (secure) {
65 sln_printf("Encrypted ");
66 waddch(statuswindow, ACS_VLINE);
67 waddch(statuswindow, ' ');
69 if (room_name)
70 sln_printf("%s on ", room_name);
71 if (humannode)
72 sln_printf("%s ", humannode);
73 if (newmailcount > 0) {
74 waddch(statuswindow, ACS_VLINE);
75 sln_printf(" %d new mail ", newmailcount);
77 sln_printf("\n");
79 #endif /* HAVE_CURSES_H */
84 * Display a 3270-style "wait" indicator at the bottom of the screen
86 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
87 void wait_indicator(int state) {
89 if (statuswindow && !isendwin()) {
91 mvwinch(statuswindow, 0, screenwidth - 2);
92 switch (state) {
93 default:
94 case 0: /* Idle */
95 waddch(statuswindow, ' ');
96 break;
97 case 1: /* Waiting */
98 waddch(statuswindow, 'X');
99 break;
100 case 2: /* Receiving */
101 waddch(statuswindow, '<');
102 break;
103 case 3: /* Sending */
104 waddch(statuswindow, '>');
105 break;
107 waddch(statuswindow, '\r');
108 wrefresh(statuswindow);
109 wrefresh(mainwindow); /* this puts the cursor back */
112 #else
113 void wait_indicator(int state) {}
114 #endif
118 * Initialize the screen. If newterm() fails, myscreen will be NULL and
119 * further handlers will assume we should be in line mode.
121 void screen_new(void)
123 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
124 if (arg_screen != RC_NO && rc_screen != RC_NO)
125 myscreen = newterm(NULL, stdout, stdin);
126 if (myscreen) {
127 cbreak();
128 noecho();
129 nonl();
130 intrflush(stdscr, FALSE);
131 keypad(stdscr, TRUE);
132 /* Setup all our colors */
133 start_color();
134 if (rc_ansi_color)
135 enable_color = 1;
136 /*init_pair(DIM_BLACK, COLOR_BLACK, COLOR_BLACK);*/
137 init_pair(DIM_RED, COLOR_RED, COLOR_BLACK);
138 init_pair(DIM_GREEN, COLOR_GREEN, COLOR_BLACK);
139 init_pair(DIM_YELLOW, COLOR_YELLOW, COLOR_BLACK);
140 init_pair(DIM_BLUE, COLOR_BLUE, COLOR_BLACK);
141 init_pair(DIM_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
142 init_pair(DIM_CYAN, COLOR_CYAN, COLOR_BLACK);
143 init_pair(DIM_WHITE, COLOR_WHITE, COLOR_BLACK);
145 if (COLOR_PAIRS > 8)
146 init_pair(8, COLOR_WHITE, COLOR_BLUE);
147 } else
148 #endif /* HAVE_CURSES_H */
150 send_ansi_detect();
151 look_for_ansi();
152 cls(0);
153 color(DIM_WHITE);
155 screen_set();
156 windows_new();
161 * Kill the screen completely (used at exit). It is safe to call this
162 * function more than once.
164 void screen_delete(void)
166 windows_delete();
167 screen_reset();
168 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
169 if (myscreen) {
170 delscreen(myscreen);
172 myscreen = NULL;
173 #endif
177 * Beep.
179 void ctdl_beep(void) {
180 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
181 if (myscreen)
182 beep();
183 else
184 #endif
185 putc(7, stdout);
191 * Set screen/IO parameters, e.g. at start of program or return from external
192 * program run.
194 int screen_set(void)
196 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
197 if (myscreen) {
198 set_term(myscreen);
199 wrefresh(curscr);
200 return 1;
202 #endif /* HAVE_CURSES_H */
203 return 0;
208 * Reset screen/IO parameters, e.g. at exit or fork of external program.
210 int screen_reset(void)
212 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
213 if (myscreen) {
214 if (!isendwin()) endwin();
215 return 1;
217 #endif /* HAVE_CURSES_H */
218 return 0;
223 * scr_printf() outputs to the main window (or screen if not in curses)
225 int scr_printf(char *fmt, ...)
227 va_list ap;
228 register int retval;
230 va_start(ap, fmt);
231 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
232 if (mainwindow) {
233 retval = _vwprintw(mainwindow, fmt, ap);
234 } else
235 #endif
236 retval = vprintf(fmt, ap);
237 va_end(ap);
238 return retval;
243 * err_printf() outputs to error status window (or stderr if not in curses)
245 int err_printf(char *fmt, ...)
247 va_list ap;
248 register int retval;
250 va_start(ap, fmt);
251 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
252 if (mainwindow) { /* FIXME: direct to error window */
253 retval = _vwprintw(mainwindow, fmt, ap);
254 if (fmt[strlen(fmt) - 1] == '\n')
255 wrefresh(mainwindow);
256 } else
257 #endif
258 retval = vfprintf(stderr, fmt, ap);
259 va_end(ap);
260 return retval;
265 * sln_printf() outputs to error status window (or stderr if not in curses)
267 int sln_printf(char *fmt, ...)
269 va_list ap;
270 register int retval;
271 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
272 static char buf[4096];
273 #endif
275 va_start(ap, fmt);
276 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
277 if (statuswindow) {
278 register char *i;
280 retval = vsnprintf(buf, 4096, fmt, ap);
281 for (i = buf; *i; i++) {
282 if (*i == '\r' || *i == '\n')
283 wclrtoeol(statuswindow);
284 sln_putc(*i);
285 if (*i == '\r' || *i == '\n') {
286 wrefresh(statuswindow);
287 mvwinch(statuswindow, 0, 0);
290 } else
291 #endif
292 retval = vprintf(fmt, ap);
293 va_end(ap);
294 return retval;
299 * sln_printf_if() outputs to status window, no output if not in curses
301 int sln_printf_if(char *fmt, ...)
303 register int retval = 1;
304 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
305 static char buf[4096];
306 va_list ap;
308 va_start(ap, fmt);
309 if (statuswindow) {
310 register char *i;
312 retval = vsnprintf(buf, 4096, fmt, ap);
313 for (i = buf; *i; i++) {
314 if (*i == '\r' || *i == '\n')
315 wclrtoeol(statuswindow);
316 sln_putc(*i);
317 if (*i == '\r' || *i == '\n') {
318 wrefresh(statuswindow);
319 mvwinch(statuswindow, 0, 0);
323 va_end(ap);
324 #endif
325 return retval;
329 int scr_getc(int delay)
331 unsigned char buf;
333 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
334 if (mainwindow) {
335 wtimeout(mainwindow, delay);
336 return wgetch(mainwindow);
338 #endif
340 buf = '\0';
341 if (!read (0, &buf, 1))
342 logoff(NULL, 3);
343 return buf;
346 /* the following is unused and looks broken, but there may
347 be some input problems still lurking in curses mode, so
348 i'll leave it blocked out for now for informational
349 purposes. */
350 #if 0
351 int scr_blockread(void)
353 int a = 0;
354 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
355 wtimeout(mainwindow, S_KEEPALIVE);
356 while (1)
358 do_keepalive();
359 a = wgetch(mainwindow); /* will block for food */
360 if (a != ERR)
361 break;
362 /* a = scr_getc(); */
364 #endif
365 return a;
367 #endif /* 0 */
370 * scr_putc() outputs a single character
372 int scr_putc(int c)
374 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
375 if (mainwindow) {
376 if (c == 7) beep();
377 if (waddch(mainwindow, c) != OK)
378 logoff(NULL, 3);
379 return c;
381 #endif
382 if (putc(c, stdout) == EOF)
383 logoff(NULL, 3);
384 return c;
388 int sln_putc(int c)
390 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
391 if (statuswindow)
392 return ((waddch(statuswindow, c) == OK) ? c : EOF);
393 #endif
394 return putc(c, stdout);
398 int sln_putc_if(int c)
400 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
401 if (statuswindow)
402 return ((waddch(statuswindow, c) == OK) ? c : EOF);
403 #endif
404 return 1;
409 * scr_color() sets the window color for mainwindow
411 int scr_color(int colornum)
413 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
414 if (mainwindow) {
415 #ifdef HAVE_WCOLOR_SET
416 wcolor_set(mainwindow, (colornum & 7), NULL);
417 #else
418 wattron(mainwindow, COLOR_PAIR((colornum & 7)));
419 #endif
420 if (colornum & 8) {
421 wattron(mainwindow, A_BOLD);
422 } else {
423 wattroff(mainwindow, A_BOLD);
425 return 1;
427 #endif
428 return 0;
432 void scr_flush(void)
434 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
435 if (mainwindow)
436 wrefresh(mainwindow);
437 else
438 #endif
439 fflush(stdout);
443 void err_flush(void)
445 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
446 if (mainwindow) /* FIXME: error status window needed */
447 wrefresh(mainwindow);
448 else
449 #endif
450 fflush(stderr);
454 void sln_flush(void)
456 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
457 if (statuswindow)
458 wrefresh(statuswindow);
459 else
460 #endif
461 fflush(stdout);
464 static volatile int caught_sigwinch = 0;
467 * this is not supposed to be called from a signal handler.
469 int scr_set_windowsize(CtdlIPC* ipc)
471 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
472 if (mainwindow && caught_sigwinch) {
473 caught_sigwinch = 0;
474 #ifdef HAVE_RESIZETERM
475 resizeterm(screenheight + 1, screenwidth);
476 #endif
477 #ifdef HAVE_WRESIZE
478 wresize(mainwindow, screenheight, screenwidth);
479 wresize(statuswindow, 1, screenwidth);
480 #endif
481 mvwin(statuswindow, screenheight, 0);
482 status_line(ipc->ServInfo.humannode, ipc->ServInfo.site_location,
483 room_name, secure, -1);
484 wnoutrefresh(mainwindow);
485 wnoutrefresh(statuswindow);
486 doupdate();
487 return 1;
489 #endif /* HAVE_CURSES_H */
490 return 0;
494 * scr_winch() handles window size changes from SIGWINCH
495 * resizes all our windows for us
497 RETSIGTYPE scr_winch(int signum)
499 /* if we receive this signal, we must be running
500 in a terminal that supports resizing. */
501 have_xterm = 1;
502 caught_sigwinch = 1;
503 check_screen_dims();
504 signal(SIGWINCH, scr_winch);
509 * Initialize the window(s) we will be using.
511 void windows_new(void)
513 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
514 register int x, y;
516 if (myscreen) {
517 getmaxyx(stdscr, y, x);
518 mainwindow = newwin(y - 1, x, 0, 0);
519 screenwidth = x;
520 screenheight = y - 1;
521 immedok(mainwindow, FALSE);
522 leaveok(mainwindow, FALSE);
523 scrollok(mainwindow, TRUE);
524 statuswindow = newwin(1, x, y - 1, 0);
526 if (COLOR_PAIRS > 8)
527 wbkgdset(statuswindow, ' ' | COLOR_PAIR(8));
528 else
529 wbkgdset(statuswindow, ' ' | COLOR_PAIR(DIM_WHITE));
531 werase(statuswindow);
532 immedok(statuswindow, FALSE);
533 leaveok(statuswindow, FALSE);
534 scrollok(statuswindow, FALSE);
535 wrefresh(statuswindow);
537 #else /* HAVE_CURSES_H */
539 #endif /* HAVE_CURSES_H */
544 * Deinitialize the window(s) we were using (at exit).
546 void windows_delete(void)
548 #if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
549 if (mainwindow)
550 delwin(mainwindow);
551 mainwindow = NULL;
552 if (statuswindow)
553 delwin(statuswindow);
554 statuswindow = NULL;
555 #else /* HAVE_CURSES_H */
557 #endif /* HAVE_CURSES_H */