]> code.citadel.org Git - citadel.git/blob - citadel/textclient/screen.c
The new paginator now makes use of the server-supplied prompt.
[citadel.git] / citadel / textclient / screen.c
1 /*
2  * Screen output handling
3  */
4
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <signal.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <sys/types.h>
12 #include "sysdep.h"
13 #ifndef HAVE_SNPRINTF
14 #include "snprintf.h"
15 #endif
16 #include <libcitadel.h>
17 #include "citadel.h"
18 #include "citadel_ipc.h"
19 #include "citadel_decls.h"
20 #include "commands.h"
21 #include "screen.h"
22
23 char arg_screen;
24
25 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
26 char *moreprompt = " -- more -- ";
27
28 extern int screenheight;
29 extern int screenwidth;
30 int lines_printed = 0;
31 int cols_printed = 0;
32
33 extern int rc_ansi_color;
34 extern int rc_prompt_control;
35 extern void check_screen_dims(void);
36
37 void do_keepalive(void);
38
39 /*
40  * Initialize the screen
41  */
42 void screen_new(void)
43 {
44         send_ansi_detect();
45         look_for_ansi();
46         cls(0);
47         color(DIM_WHITE);
48 }
49
50
51
52 /*
53  * Beep.
54  */
55 void ctdl_beep(void) {
56         putc(7, stdout);
57 }
58         
59
60
61
62 /*
63  * scr_printf() outputs to the terminal
64  */
65 int scr_printf(char *fmt, ...)
66 {
67         static char outbuf[4096];       /* static for performance -- not re-entrant -- change if needed */
68         va_list ap;
69         register int retval;
70         int i, len;
71
72         va_start(ap, fmt);
73         retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
74         va_end(ap);
75
76         len = strlen(outbuf);
77         for (i=0; i<len; ++i) {
78                 scr_putc(outbuf[i]);
79         }
80         return retval;
81 }
82
83
84 /*
85  * Read one character from the terminal
86  */
87 int scr_getc(int delay)
88 {
89         unsigned char buf;
90
91         scr_flush();
92
93         buf = '\0';
94         if (!read (0, &buf, 1))
95                 logoff(NULL, 3);
96
97         lines_printed = 0;
98         return buf;
99 }
100
101 /*
102  * Issue the paginator prompt (more / hit any key to continue)
103  */
104 void hit_any_key(void) {
105         int a, b;
106
107         color(COLOR_PUSH);
108         color(DIM_RED);
109         scr_printf("%s\r", moreprompt);
110         color(COLOR_POP);
111         b=inkey();
112         for (a=0; a<screenwidth; ++a) {
113                 scr_putc(' ');
114         }
115         scr_printf("\r");
116
117         if ( (rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
118                 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
119                         b = STOP_KEY;
120                 }
121                 if (b == 'n' || b == 'N') {
122                         b = NEXT_KEY;
123                 }
124         }
125
126         if (b==NEXT_KEY) sigcaught = SIGINT;
127         if (b==STOP_KEY) sigcaught = SIGQUIT;
128 }
129
130
131 /*
132  * Output one character to the terminal
133  */
134 int scr_putc(int c)
135 {
136         /* handle tabs normally */
137         if (c == '\t') {
138                 do {
139                         scr_putc(' ');
140                 } while ((cols_printed % 8) != 0);
141                 return(c);
142         }
143
144         /* Output the character... */
145         if (putc(c, stdout) == EOF) {
146                 logoff(NULL, 3);
147         }
148
149         if (c == '\n') {
150                 ++lines_printed;
151                 cols_printed = 0;
152         }
153         else if (c == '\r') {
154                 cols_printed = 0;
155         }
156         else if (isprint(c)) {
157                 ++cols_printed;
158                 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
159                         ++lines_printed;
160                         cols_printed = 0;
161                 }
162         }
163
164         //      if we want to do a top status line, this is a reasonable way to do it
165         //      printf("\033[s\033[0;70H");
166         //      printf("\033[K   %d/%d  %d/%d", cols_printed, screenwidth, lines_printed, screenheight);
167         //      printf("\033[u");
168
169         if ((screenheight > 0) && (lines_printed > (screenheight-2))) {
170                 lines_printed = 0;
171                 hit_any_key();
172                 lines_printed = 0;
173                 cols_printed = 0;
174         }
175
176         return c;
177 }
178
179
180 void scr_flush(void)
181 {
182         fflush(stdout);
183 }
184
185
186 static volatile int caught_sigwinch = 0;
187
188
189 /*
190  * scr_winch() handles window size changes from SIGWINCH
191  * resizes all our windows for us
192  */
193 RETSIGTYPE scr_winch(int signum)
194 {
195         /* if we receive this signal, we must be running
196          * in a terminal that supports resizing.
197          */
198         have_xterm = 1;
199         caught_sigwinch = 1;
200         check_screen_dims();
201         signal(SIGWINCH, scr_winch);
202 }