]> code.citadel.org Git - citadel.git/blob - citadel/textclient/screen.c
* add forward declarations
[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 extern int screenheight;
26 extern int screenwidth;
27 int lines_printed = 0;
28 int cols_printed = 0;
29
30 extern int rc_ansi_color;
31 extern int rc_prompt_control;
32 extern void check_screen_dims(void);
33
34 void do_keepalive(void);
35
36 /*
37  * Initialize the screen
38  */
39 void screen_new(void)
40 {
41         send_ansi_detect();
42         look_for_ansi();
43         cls(0);
44         color(DIM_WHITE);
45 }
46
47
48
49 /*
50  * Beep.
51  */
52 void ctdl_beep(void) {
53         putc(7, stdout);
54 }
55         
56
57
58
59 /*
60  * scr_printf() outputs to the terminal
61  */
62 int scr_printf(char *fmt, ...)
63 {
64         static char outbuf[4096];       /* static for performance -- not re-entrant -- change if needed */
65         va_list ap;
66         register int retval;
67         int i, len;
68
69         va_start(ap, fmt);
70         retval = vsnprintf(outbuf, sizeof outbuf, fmt, ap);
71         va_end(ap);
72
73         len = strlen(outbuf);
74         for (i=0; i<len; ++i) {
75                 scr_putc(outbuf[i]);
76         }
77         return retval;
78 }
79
80
81 /*
82  * Read one character from the terminal
83  */
84 int scr_getc(int delay)
85 {
86         unsigned char buf;
87
88         scr_flush();
89
90         buf = '\0';
91         if (!read (0, &buf, 1))
92                 logoff(NULL, 3);
93
94         lines_printed = 0;
95         return buf;
96 }
97
98 /*
99  * Issue the paginator prompt (more / hit any key to continue)
100  */
101 void hit_any_key(void) {
102         int b;
103
104         color(COLOR_PUSH);
105         color(DIM_RED);
106         /* scr_printf("%s\r", ipc->ServInfo.moreprompt); */
107         scr_printf("<<more>>\r");       // FIXME use the prompt given by the server
108         color(COLOR_POP);
109         stty_ctdl(0);
110         b=inkey();
111         /*
112         for (a=0; !IsEmptyStr(&ipc->ServInfo.moreprompt[a]); ++a)
113                 scr_putc(' ');
114         */
115         scr_printf("        ");
116         scr_putc(13);
117         stty_ctdl(1);
118
119         if ( (rc_prompt_control == 1)
120            || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
121                 if (b == 'q' || b == 'Q' || b == 's' || b == 'S')
122                         b = STOP_KEY;
123                 if (b == 'n' || b == 'N')
124                         b = NEXT_KEY;
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         //      if we want to do a top status line, this is a reasonable way to do it
166         //      printf("\033[s\033[0;70H");
167         //      printf("\033[K   %d/%d  %d/%d", cols_printed, screenwidth, lines_printed, screenheight);
168         //      printf("\033[u");
169
170         if ((screenheight > 0) && (lines_printed > (screenheight-2))) {
171                 lines_printed = 0;
172                 hit_any_key();
173                 lines_printed = 0;
174                 cols_printed = 0;
175         }
176
177         return c;
178 }
179
180
181 void scr_flush(void)
182 {
183         fflush(stdout);
184 }
185
186
187 static volatile int caught_sigwinch = 0;
188
189
190 /*
191  * scr_winch() handles window size changes from SIGWINCH
192  * resizes all our windows for us
193  */
194 RETSIGTYPE scr_winch(int signum)
195 {
196         /* if we receive this signal, we must be running
197          * in a terminal that supports resizing.
198          */
199         have_xterm = 1;
200         caught_sigwinch = 1;
201         check_screen_dims();
202         signal(SIGWINCH, scr_winch);
203 }