1 // Screen output handling
3 // Copyright (c) 1987-2021 by the citadel.org team
5 // This program is open source software. Use, duplication, and/or
6 // disclosure are subject to the GNU General Purpose License version 3.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 #include "textclient.h"
15 int enable_status_line = 0;
16 char status_line[1024] = " ";
18 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
19 char *moreprompt = " -- more -- ";
21 int screenheight = 24;
23 int lines_printed = 0;
26 extern int rc_ansi_color;
27 extern int rc_prompt_control;
28 void do_keepalive(void);
31 * Attempt to discover the screen dimensions.
32 * WARNING: This is sometimes called from a signal handler.
34 void check_screen_dims(void) {
37 unsigned short height; /* rows */
38 unsigned short width; /* columns */
39 unsigned short xpixels;
40 unsigned short ypixels; /* pixels */
43 if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
45 screenheight = (int) xwinsz.height;
47 screenwidth = (int) xwinsz.width;
54 * Initialize the screen
56 void screen_new(void) {
67 void ctdl_beep(void) {
73 * scr_printf() outputs to the terminal
75 int scr_printf(char *fmt, ...) {
76 static char outbuf[4096]; /* static for performance -- not re-entrant -- change if needed */
82 retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
86 for (i = 0; i < len; ++i) {
94 * Read one character from the terminal
96 int scr_getc(int delay) {
102 if (!read(0, &buf, 1))
111 * Issue the paginator prompt (more / hit any key to continue)
113 void hit_any_key(void) {
118 scr_printf("%s\r", moreprompt);
121 for (a = 0; a < screenwidth; ++a) {
126 if ((rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL))) {
127 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
130 if (b == 'n' || b == 'N') {
143 * Output one character to the terminal
145 int scr_putc(int c) {
146 /* handle tabs normally */
150 } while ((cols_printed % 8) != 0);
154 /* Output the character... */
155 if (putc(c, stdout) == EOF) {
163 else if (c == '\r') {
166 else if (isprint(c)) {
168 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
174 /* How many lines output before stopping for the paginator?
175 * Depends on whether we are displaying a status line.
177 int height_offset = (((enable_color) && (screenwidth > 0) && (enable_status_line)) ? (3) : (2));
179 /* Ok, go check it. Stop and display the paginator prompt if necessary. */
180 if ((screenheight > 0) && (lines_printed > (screenheight - height_offset))) {
191 void scr_flush(void) {
192 if ((enable_color) && (screenwidth > 0) && (enable_status_line)) {
193 if (strlen(status_line) < screenwidth) {
194 memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
196 printf("\033[s\033[1;1H\033[K\033[7m");
197 fwrite(status_line, screenwidth, 1, stdout);
198 printf("\033[27m\033[u");
204 static volatile int caught_sigwinch = 0;
208 * scr_winch() handles window size changes from SIGWINCH
209 * resizes all our windows for us
211 sighandler_t scr_winch(int signum) {
212 /* if we receive this signal, we must be running
213 * in a terminal that supports resizing.
217 signal(SIGWINCH, scr_winch);
222 * Display a 3270-style "wait" indicator at the bottom of the screen
224 void scr_wait_indicator(int state) {
225 int sp = (screenwidth - 2);
227 if (!enable_status_line)
230 if (screenwidth > 0) {
234 status_line[sp] = ' ';
236 case 1: /* Waiting */
237 status_line[sp] = 'X';
239 case 2: /* Receiving */
240 status_line[sp] = '<';
242 case 3: /* Sending */
243 status_line[sp] = '>';