1 // Screen output handling
3 // Copyright (c) 1987-2021 by the citadel.org team
5 // This program is open source software. Use, duplication, or disclosure is subject to the GNU General Public License version 3.
7 #include "textclient.h"
9 int enable_status_line = 0;
10 char status_line[1024] = " ";
12 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
13 char *moreprompt = " -- more -- ";
15 int screenheight = 24;
17 int lines_printed = 0;
20 extern int rc_ansi_color;
21 extern int rc_prompt_control;
22 void do_keepalive(void);
25 * Attempt to discover the screen dimensions.
26 * WARNING: This is sometimes called from a signal handler.
28 void check_screen_dims(void) {
31 unsigned short height; /* rows */
32 unsigned short width; /* columns */
33 unsigned short xpixels;
34 unsigned short ypixels; /* pixels */
37 if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
39 screenheight = (int) xwinsz.height;
41 screenwidth = (int) xwinsz.width;
48 * Initialize the screen
50 void screen_new(void) {
61 void ctdl_beep(void) {
67 * scr_printf() outputs to the terminal
69 int scr_printf(char *fmt, ...) {
70 static char outbuf[4096]; /* static for performance -- not re-entrant -- change if needed */
76 retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
80 for (i = 0; i < len; ++i) {
88 * Read one character from the terminal
90 int scr_getc(int delay) {
96 if (!read(0, &buf, 1))
105 * Issue the paginator prompt (more / hit any key to continue)
107 void hit_any_key(void) {
112 scr_printf("%s\r", moreprompt);
115 for (a = 0; a < screenwidth; ++a) {
120 if ((rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL))) {
121 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
124 if (b == 'n' || b == 'N') {
137 * Output one character to the terminal
139 int scr_putc(int c) {
140 /* handle tabs normally */
144 } while ((cols_printed % 8) != 0);
148 /* Output the character... */
149 if (putc(c, stdout) == EOF) {
157 else if (c == '\r') {
160 else if (isprint(c)) {
162 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
168 /* How many lines output before stopping for the paginator?
169 * Depends on whether we are displaying a status line.
171 int height_offset = (((enable_color) && (screenwidth > 0) && (enable_status_line)) ? (3) : (2));
173 /* Ok, go check it. Stop and display the paginator prompt if necessary. */
174 if ((screenheight > 0) && (lines_printed > (screenheight - height_offset))) {
185 void scr_flush(void) {
186 if ((enable_color) && (screenwidth > 0) && (enable_status_line)) {
187 if (strlen(status_line) < screenwidth) {
188 memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
190 printf("\033[s\033[1;1H\033[K\033[7m");
191 fwrite(status_line, screenwidth, 1, stdout);
192 printf("\033[27m\033[u");
198 static volatile int caught_sigwinch = 0;
202 * scr_winch() handles window size changes from SIGWINCH
203 * resizes all our windows for us
205 void scr_winch(int signum) {
206 /* if we receive this signal, we must be running
207 * in a terminal that supports resizing.
211 signal(SIGWINCH, scr_winch);
216 * Display a 3270-style "wait" indicator at the bottom of the screen
218 void scr_wait_indicator(int state) {
219 int sp = (screenwidth - 2);
221 if (!enable_status_line)
224 if (screenwidth > 0) {
228 status_line[sp] = ' ';
231 status_line[sp] = 'X';
234 status_line[sp] = '<';
237 status_line[sp] = '>';