2 * Screen output handling
4 * Copyright (c) 1987-2018 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 version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include "textclient.h"
18 int enable_status_line = 0;
19 char status_line[1024] = " ";
21 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
22 char *moreprompt = " -- more -- ";
24 int screenheight = 24;
26 int lines_printed = 0;
29 extern int rc_ansi_color;
30 extern int rc_prompt_control;
31 void do_keepalive(void);
34 * Attempt to discover the screen dimensions.
35 * WARNING: This is sometimes called from a signal handler.
37 void check_screen_dims(void)
41 unsigned short height; /* rows */
42 unsigned short width; /* columns */
43 unsigned short xpixels;
44 unsigned short ypixels; /* pixels */
47 if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
49 screenheight = (int) xwinsz.height;
51 screenwidth = (int) xwinsz.width;
58 * Initialize the screen
82 * scr_printf() outputs to the terminal
84 int scr_printf(char *fmt, ...)
86 static char outbuf[4096]; /* static for performance -- not re-entrant -- change if needed */
92 retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
96 for (i = 0; i < len; ++i) {
104 * Read one character from the terminal
106 int scr_getc(int delay)
113 if (!read(0, &buf, 1))
121 * Issue the paginator prompt (more / hit any key to continue)
123 void hit_any_key(void)
129 scr_printf("%s\r", moreprompt);
132 for (a = 0; a < screenwidth; ++a) {
137 if ((rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL))) {
138 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
141 if (b == 'n' || b == 'N') {
154 * Output one character to the terminal
158 /* handle tabs normally */
162 } while ((cols_printed % 8) != 0);
166 /* Output the character... */
167 if (putc(c, stdout) == EOF) {
174 } else if (c == '\r') {
176 } else if (isprint(c)) {
178 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
184 /* How many lines output before stopping for the paginator?
185 * Depends on whether we are displaying a status line.
187 int height_offset = (((enable_color) && (screenwidth > 0) && (enable_status_line)) ? (3) : (2));
189 /* Ok, go check it. Stop and display the paginator prompt if necessary. */
190 if ((screenheight > 0) && (lines_printed > (screenheight - height_offset))) {
202 if ((enable_color) && (screenwidth > 0) && (enable_status_line)) {
203 if (strlen(status_line) < screenwidth) {
204 memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
206 printf("\033[s\033[1;1H\033[K\033[7m");
207 fwrite(status_line, screenwidth, 1, stdout);
208 printf("\033[27m\033[u");
214 static volatile int caught_sigwinch = 0;
218 * scr_winch() handles window size changes from SIGWINCH
219 * resizes all our windows for us
221 sighandler_t scr_winch(int signum)
223 /* if we receive this signal, we must be running
224 * in a terminal that supports resizing.
228 signal(SIGWINCH, scr_winch);
234 * Display a 3270-style "wait" indicator at the bottom of the screen
236 void scr_wait_indicator(int state)
238 int sp = (screenwidth - 2);
240 if (!enable_status_line)
243 if (screenwidth > 0) {
247 status_line[sp] = ' ';
249 case 1: /* Waiting */
250 status_line[sp] = 'X';
252 case 2: /* Receiving */
253 status_line[sp] = '<';
255 case 3: /* Sending */
256 status_line[sp] = '>';