]> code.citadel.org Git - citadel.git/blob - citadel/textclient/screen.c
Merge branch 'master' of ssh://git.citadel.org/appl/gitroot/citadel
[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 <ctype.h>
12 #include <sys/types.h>
13 #include "sysdep.h"
14 #ifndef HAVE_SNPRINTF
15 #include "snprintf.h"
16 #endif
17 #include <libcitadel.h>
18 #include "citadel.h"
19 #include "citadel_ipc.h"
20 #include "citadel_decls.h"
21 #include "commands.h"
22 #include "screen.h"
23
24 char status_line[1024] = "     ";
25
26 /* the default paginator prompt will be replaced by the server's prompt when we learn it */
27 char *moreprompt = " -- more -- ";
28
29 extern int screenheight;
30 extern int screenwidth;
31 int lines_printed = 0;
32 int cols_printed = 0;
33
34 extern int rc_ansi_color;
35 extern int rc_prompt_control;
36 extern void check_screen_dims(void);
37
38 void do_keepalive(void);
39
40 /*
41  * Initialize the screen
42  */
43 void screen_new(void)
44 {
45         send_ansi_detect();
46         look_for_ansi();
47         cls(0);
48         color(DIM_WHITE);
49 }
50
51
52
53 /*
54  * Beep.
55  */
56 void ctdl_beep(void) {
57         putc(7, stdout);
58 }
59         
60
61
62
63 /*
64  * scr_printf() outputs to the terminal
65  */
66 int scr_printf(char *fmt, ...)
67 {
68         static char outbuf[4096];       /* static for performance -- not re-entrant -- change if needed */
69         va_list ap;
70         register int retval;
71         int i, len;
72
73         va_start(ap, fmt);
74         retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
75         va_end(ap);
76
77         len = strlen(outbuf);
78         for (i=0; i<len; ++i) {
79                 scr_putc(outbuf[i]);
80         }
81         return retval;
82 }
83
84
85 /*
86  * Read one character from the terminal
87  */
88 int scr_getc(int delay)
89 {
90         unsigned char buf;
91
92         scr_flush();
93
94         buf = '\0';
95         if (!read (0, &buf, 1))
96                 logoff(NULL, 3);
97
98         lines_printed = 0;
99         return buf;
100 }
101
102 /*
103  * Issue the paginator prompt (more / hit any key to continue)
104  */
105 void hit_any_key(void) {
106         int a, b;
107
108         color(COLOR_PUSH);
109         color(DIM_RED);
110         scr_printf("%s\r", moreprompt);
111         color(COLOR_POP);
112         b=inkey();
113         for (a=0; a<screenwidth; ++a) {
114                 scr_putc(' ');
115         }
116         scr_printf("\r");
117
118         if ( (rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
119                 if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
120                         b = STOP_KEY;
121                 }
122                 if (b == 'n' || b == 'N') {
123                         b = NEXT_KEY;
124                 }
125         }
126
127         if (b==NEXT_KEY) sigcaught = SIGINT;
128         if (b==STOP_KEY) sigcaught = SIGQUIT;
129 }
130
131
132 /*
133  * Output one character to the terminal
134  */
135 int scr_putc(int c)
136 {
137         /* handle tabs normally */
138         if (c == '\t') {
139                 do {
140                         scr_putc(' ');
141                 } while ((cols_printed % 8) != 0);
142                 return(c);
143         }
144
145         /* Output the character... */
146         if (putc(c, stdout) == EOF) {
147                 logoff(NULL, 3);
148         }
149
150         if (c == '\n') {
151                 ++lines_printed;
152                 cols_printed = 0;
153         }
154         else if (c == '\r') {
155                 cols_printed = 0;
156         }
157         else if (isprint(c)) {
158                 ++cols_printed;
159                 if ((screenwidth > 0) && (cols_printed > screenwidth)) {
160                         ++lines_printed;
161                         cols_printed = 0;
162                 }
163         }
164
165         /* How many lines output before stopping for the paginator?
166          * Depends on whether we are displaying a status line.
167          */
168         int height_offset = ( ((enable_color) && (screenwidth > 0)) ? (3) : (2) ) ;
169
170         /* Ok, go check it.  Stop and display the paginator prompt if necessary. */
171         if ((screenheight > 0) && (lines_printed > (screenheight-height_offset))) {
172                 lines_printed = 0;
173                 hit_any_key();
174                 lines_printed = 0;
175                 cols_printed = 0;
176         }
177
178         return c;
179 }
180
181 void scr_flush(void)
182 {
183         if ((enable_color) && (screenwidth > 0)) {
184                 if (strlen(status_line) < screenwidth) {
185                         memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
186                 }
187                 printf("\033[s\033[1;1H\033[K\033[7m");
188                 fwrite(status_line, screenwidth, 1, stdout);
189                 printf("\033[27m\033[u");
190         }
191         fflush(stdout);
192 }
193
194
195 static volatile int caught_sigwinch = 0;
196
197
198 /*
199  * scr_winch() handles window size changes from SIGWINCH
200  * resizes all our windows for us
201  */
202 RETSIGTYPE scr_winch(int signum)
203 {
204         /* if we receive this signal, we must be running
205          * in a terminal that supports resizing.
206          */
207         have_xterm = 1;
208         caught_sigwinch = 1;
209         check_screen_dims();
210         signal(SIGWINCH, scr_winch);
211 }
212
213
214
215 /*
216  * Display a 3270-style "wait" indicator at the bottom of the screen
217  */
218 void scr_wait_indicator(int state) {
219         int sp = (screenwidth - 2);
220
221         if (screenwidth > 0) {
222                 switch (state) {
223                         default:
224                         case 0:  /* Idle */
225                                 status_line[sp] = ' ';
226                                 break;
227                         case 1:  /* Waiting */
228                                 status_line[sp] = 'X';
229                                 break;
230                         case 2:  /* Receiving */
231                                 status_line[sp] = '<';
232                                 break;
233                         case 3:  /* Sending */
234                                 status_line[sp] = '>';
235                                 break;
236                 }
237                 scr_flush();
238         }
239 }
240