386BSD 0.1 development
[unix-history] / usr / othersrc / public / less-177 / output.c
CommitLineData
77e25d77
WJ
1/*
2 * High level routines dealing with the output to the screen.
3 */
4
5#include "less.h"
6
7public int errmsgs; /* Count of messages displayed by error() */
8public int need_clr;
9
10extern int sigs;
11extern int sc_width;
12extern int so_s_width, so_e_width;
13extern int screen_trashed;
14extern int any_display;
15#if __MSDOS__
16extern int output_mode;
17#endif
18
19/*
20 * Display the line which is in the line buffer.
21 */
22 public void
23put_line()
24{
25 register int c;
26 register int i;
27 int a;
28 int curr_attr;
29
30 if (sigs)
31 {
32 /*
33 * Don't output if a signal is pending.
34 */
35 screen_trashed = 1;
36 return;
37 }
38
39 curr_attr = NORMAL;
40
41 for (i = 0; (c = gline(i, &a)) != '\0'; i++)
42 {
43 if (a != curr_attr)
44 {
45 /*
46 * Changing attributes.
47 * Display the exit sequence for the old attribute
48 * and the enter sequence for the new one.
49 */
50 switch (curr_attr)
51 {
52 case UNDERLINE: ul_exit(); break;
53 case BOLD: bo_exit(); break;
54 case BLINK: bl_exit(); break;
55 }
56 switch (a)
57 {
58 case UNDERLINE: ul_enter(); break;
59 case BOLD: bo_enter(); break;
60 case BLINK: bl_enter(); break;
61 }
62 curr_attr = a;
63 }
64 if (curr_attr == INVIS)
65 continue;
66 if (c == '\b')
67 putbs();
68 else
69 putchr(c);
70 }
71}
72
73static char obuf[1024];
74static char *ob = obuf;
75
76/*
77 * Flush buffered output.
78 *
79 * If we haven't displayed any file data yet,
80 * output messages on error output (file descriptor 2),
81 * otherwise output on standard output (file descriptor 1).
82 *
83 * This has the desirable effect of producing all
84 * error messages on error output if standard output
85 * is directed to a file. It also does the same if
86 * we never produce any real output; for example, if
87 * the input file(s) cannot be opened. If we do
88 * eventually produce output, code in edit() makes
89 * sure these messages can be seen before they are
90 * overwritten or scrolled away.
91 */
92 public void
93flush()
94{
95 register int n;
96 register int fd;
97
98#if __MSDOS__
99 if (output_mode == 0)
100 {
101 *ob = '\0';
102 cputs(obuf);
103 ob = obuf;
104 return;
105 }
106#endif
107 n = ob - obuf;
108 if (n == 0)
109 return;
110 fd = (any_display) ? 1 : 2;
111 if (write(fd, obuf, n) != n)
112 screen_trashed = 1;
113 ob = obuf;
114}
115
116/*
117 * Output a character.
118 */
119 public void
120putchr(c)
121 int c;
122{
123 if (ob >= &obuf[sizeof(obuf)])
124 flush();
125 if (need_clr)
126 {
127 need_clr = 0;
128 lower_left();
129 clear_eol();
130 }
131#if __MSDOS__
132 if (c == '\n')
133 *ob++ = '\r';
134#endif
135 *ob++ = c;
136}
137
138/*
139 * Output a string.
140 */
141 public void
142putstr(s)
143 register char *s;
144{
145 while (*s != '\0')
146 putchr(*s++);
147}
148
149
150/*
151 * Output an integer in a given radix.
152 */
153 static int
154iprintnum(num, radix)
155 int num;
156 int radix;
157{
158 register char *s;
159 int r;
160 int neg;
161 char buf[10];
162
163 if (neg = (num < 0))
164 num = -num;
165
166 s = buf;
167 do
168 {
169 *s++ = (num % radix) + '0';
170 } while ((num /= radix) != 0);
171
172 if (neg)
173 *s++ = '-';
174 r = s - buf;
175
176 while (s > buf)
177 putchr(*--s);
178 return (r);
179}
180
181/*
182 * This function implements printf-like functionality
183 * using a more portable argument list mechanism than printf's.
184 */
185 static int
186iprintf(fmt, parg)
187 register char *fmt;
188 PARG *parg;
189{
190 register char *s;
191 register int n;
192 register int col;
193
194 col = 0;
195 while (*fmt != '\0')
196 {
197 if (*fmt != '%')
198 {
199 putchr(*fmt++);
200 col++;
201 } else
202 {
203 ++fmt;
204 switch (*fmt++) {
205 case 's':
206 s = parg->p_string;
207 parg++;
208 while (*s != '\0')
209 {
210 putchr(*s++);
211 col++;
212 }
213 break;
214 case 'd':
215 n = parg->p_int;
216 parg++;
217 col += iprintnum(n, 10);
218 break;
219 }
220 }
221 }
222 return (col);
223}
224
225/*
226 * Output a message in the lower left corner of the screen
227 * and wait for carriage return.
228 */
229 public void
230error(fmt, parg)
231 char *fmt;
232 PARG *parg;
233{
234 int c;
235 int col = 0;
236 static char return_to_continue[] = " (press RETURN)";
237
238 errmsgs++;
239
240 if (any_display)
241 {
242 lower_left();
243 clear_eol();
244 so_enter();
245 col += so_s_width;
246 }
247
248 col += iprintf(fmt, parg);
249
250 if (!any_display)
251 {
252 putchr('\n');
253 return;
254 }
255
256 putstr(return_to_continue);
257 so_exit();
258 col += sizeof(return_to_continue) + so_e_width;
259
260#if ONLY_RETURN
261 while ((c = getchr()) != '\n' && c != '\r')
262 bell();
263#else
264 c = getchr();
265 if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
266 ungetcc(c);
267#endif
268 lower_left();
269
270 if (col >= sc_width)
271 /*
272 * Printing the message has probably scrolled the screen.
273 * {{ Unless the terminal doesn't have auto margins,
274 * in which case we just hammered on the right margin. }}
275 */
276 screen_trashed = 1;
277
278 flush();
279}
280
281static char intr_to_abort[] = "... (interrupt to abort)";
282
283/*
284 * Output a message in the lower left corner of the screen
285 * and don't wait for carriage return.
286 * Usually used to warn that we are beginning a potentially
287 * time-consuming operation.
288 */
289 public void
290ierror(fmt, parg)
291 char *fmt;
292 PARG *parg;
293{
294 lower_left();
295 clear_eol();
296 so_enter();
297 (void) iprintf(fmt, parg);
298 putstr(intr_to_abort);
299 so_exit();
300 flush();
301 need_clr = 1;
302}
303
304/*
305 * Output a message in the lower left corner of the screen
306 * and return a single-character response.
307 */
308 public int
309query(fmt, parg)
310 char *fmt;
311 PARG *parg;
312{
313 register int c;
314 int col = 0;
315
316 if (any_display)
317 {
318 lower_left();
319 clear_eol();
320 }
321
322 (void) iprintf(fmt, parg);
323 c = getchr();
324
325 if (!any_display)
326 {
327 putchr('\n');
328 return (c);
329 }
330
331 lower_left();
332 if (col >= sc_width)
333 screen_trashed = 1;
334 flush();
335
336 return (c);
337}