2 * Screen output handling
4 * Copyright (c) 1987-2011 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
35 #include <libcitadel.h>
37 #include "citadel_ipc.h"
38 #include "citadel_decls.h"
42 int enable_status_line = 0; /* FIXME the status line works, but not on Mac. Make this configurable. */
43 char status_line[1024] = " ";
45 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
46 char *moreprompt = " -- more -- ";
48 int screenheight = 24;
50 int lines_printed = 0;
53 extern int rc_ansi_color;
54 extern int rc_prompt_control;
55 void do_keepalive(void);
58 * Attempt to discover the screen dimensions.
59 * WARNING: This is sometimes called from a signal handler.
61 void check_screen_dims(void)
65 unsigned short height; /* rows */
66 unsigned short width; /* columns */
67 unsigned short xpixels;
68 unsigned short ypixels; /* pixels */
71 if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
73 screenheight = (int) xwinsz.height;
75 screenwidth = (int) xwinsz.width;
82 * Initialize the screen
97 void ctdl_beep(void) {
105 * scr_printf() outputs to the terminal
107 int scr_printf(char *fmt, ...)
109 static char outbuf[4096]; /* static for performance -- not re-entrant -- change if needed */
115 retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
118 len = strlen(outbuf);
119 for (i=0; i<len; ++i) {
127 * Read one character from the terminal
129 int scr_getc(int delay)
136 if (!read (0, &buf, 1))
144 * Issue the paginator prompt (more / hit any key to continue)
146 void hit_any_key(void) {
151 scr_printf("%s\r", moreprompt);
154 for (a=0; a<screenwidth; ++a) {
159 if ( (rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
160 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
163 if (b == 'n' || b == 'N') {
168 if (b==NEXT_KEY) sigcaught = SIGINT;
169 if (b==STOP_KEY) sigcaught = SIGQUIT;
174 * Output one character to the terminal
178 /* handle tabs normally */
182 } while ((cols_printed % 8) != 0);
186 /* Output the character... */
187 if (putc(c, stdout) == EOF) {
195 else if (c == '\r') {
198 else if (isprint(c)) {
200 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
206 /* How many lines output before stopping for the paginator?
207 * Depends on whether we are displaying a status line.
209 int height_offset = ( ((enable_color) && (screenwidth > 0) && (enable_status_line)) ? (3) : (2) ) ;
211 /* Ok, go check it. Stop and display the paginator prompt if necessary. */
212 if ((screenheight > 0) && (lines_printed > (screenheight-height_offset))) {
224 if ((enable_color) && (screenwidth > 0) && (enable_status_line)) {
225 if (strlen(status_line) < screenwidth) {
226 memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
228 printf("\033[s\033[1;1H\033[K\033[7m");
229 fwrite(status_line, screenwidth, 1, stdout);
230 printf("\033[27m\033[u");
236 static volatile int caught_sigwinch = 0;
240 * scr_winch() handles window size changes from SIGWINCH
241 * resizes all our windows for us
243 RETSIGTYPE scr_winch(int signum)
245 /* if we receive this signal, we must be running
246 * in a terminal that supports resizing.
250 signal(SIGWINCH, scr_winch);
256 * Display a 3270-style "wait" indicator at the bottom of the screen
258 void scr_wait_indicator(int state) {
259 int sp = (screenwidth - 2);
261 if (!enable_status_line) return;
263 if (screenwidth > 0) {
267 status_line[sp] = ' ';
269 case 1: /* Waiting */
270 status_line[sp] = 'X';
272 case 2: /* Receiving */
273 status_line[sp] = '<';
275 case 3: /* Sending */
276 status_line[sp] = '>';