Actually hook powernow.4 into the build.
[dragonfly.git] / contrib / less / output.c
blob2e7b31c0b207ef390753a0465d9711145f2416ce
1 /*
2 * Copyright (C) 1984-2009 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
9 */
13 * High level routines dealing with the output to the screen.
16 #include "less.h"
17 #if MSDOS_COMPILER==WIN32C
18 #include "windows.h"
19 #endif
21 public int errmsgs; /* Count of messages displayed by error() */
22 public int need_clr;
23 public int final_attr;
24 public int at_prompt;
26 extern int sigs;
27 extern int sc_width;
28 extern int so_s_width, so_e_width;
29 extern int screen_trashed;
30 extern int any_display;
31 extern int is_tty;
32 extern int oldbot;
34 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
35 extern int ctldisp;
36 extern int nm_fg_color, nm_bg_color;
37 extern int bo_fg_color, bo_bg_color;
38 extern int ul_fg_color, ul_bg_color;
39 extern int so_fg_color, so_bg_color;
40 extern int bl_fg_color, bl_bg_color;
41 #endif
44 * Display the line which is in the line buffer.
46 public void
47 put_line()
49 register int c;
50 register int i;
51 int a;
53 if (ABORT_SIGS())
56 * Don't output if a signal is pending.
58 screen_trashed = 1;
59 return;
62 final_attr = AT_NORMAL;
64 for (i = 0; (c = gline(i, &a)) != '\0'; i++)
66 at_switch(a);
67 final_attr = a;
68 if (c == '\b')
69 putbs();
70 else
71 putchr(c);
74 at_exit();
77 static char obuf[OUTBUF_SIZE];
78 static char *ob = obuf;
81 * Flush buffered output.
83 * If we haven't displayed any file data yet,
84 * output messages on error output (file descriptor 2),
85 * otherwise output on standard output (file descriptor 1).
87 * This has the desirable effect of producing all
88 * error messages on error output if standard output
89 * is directed to a file. It also does the same if
90 * we never produce any real output; for example, if
91 * the input file(s) cannot be opened. If we do
92 * eventually produce output, code in edit() makes
93 * sure these messages can be seen before they are
94 * overwritten or scrolled away.
96 public void
97 flush()
99 register int n;
100 register int fd;
102 n = ob - obuf;
103 if (n == 0)
104 return;
106 #if MSDOS_COMPILER==MSOFTC
107 if (is_tty && any_display)
109 *ob = '\0';
110 _outtext(obuf);
111 ob = obuf;
112 return;
114 #else
115 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
116 if (is_tty && any_display)
118 *ob = '\0';
119 if (ctldisp != OPT_ONPLUS)
120 WIN32textout(obuf, ob - obuf);
121 else
124 * Look for SGR escape sequences, and convert them
125 * to color commands. Replace bold, underline,
126 * and italic escapes into colors specified via
127 * the -D command-line option.
129 char *anchor, *p, *p_next;
130 unsigned char fg, bg;
131 static unsigned char at;
132 #if MSDOS_COMPILER==WIN32C
133 /* Screen colors used by 3x and 4x SGR commands. */
134 static unsigned char screen_color[] = {
135 0, /* BLACK */
136 FOREGROUND_RED,
137 FOREGROUND_GREEN,
138 FOREGROUND_RED|FOREGROUND_GREEN,
139 FOREGROUND_BLUE,
140 FOREGROUND_BLUE|FOREGROUND_RED,
141 FOREGROUND_BLUE|FOREGROUND_GREEN,
142 FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
144 #else
145 static enum COLORS screen_color[] = {
146 BLACK, RED, GREEN, BROWN,
147 BLUE, MAGENTA, CYAN, LIGHTGRAY
149 #endif
151 for (anchor = p_next = obuf;
152 (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; )
154 p = p_next;
155 if (p[1] == '[') /* "ESC-[" sequence */
157 if (p > anchor)
160 * If some chars seen since
161 * the last escape sequence,
162 * write them out to the screen.
164 WIN32textout(anchor, p-anchor);
165 anchor = p;
167 p += 2; /* Skip the "ESC-[" */
168 if (is_ansi_end(*p))
171 * Handle null escape sequence
172 * "ESC[m", which restores
173 * the normal color.
175 p++;
176 anchor = p_next = p;
177 WIN32setcolors(nm_fg_color, nm_bg_color);
178 continue;
180 p_next = p;
183 * Select foreground/background colors
184 * based on the escape sequence.
186 fg = nm_fg_color;
187 bg = nm_bg_color;
188 while (!is_ansi_end(*p))
190 char *q;
191 long code = strtol(p, &q, 10);
193 if (*q == '\0')
196 * Incomplete sequence.
197 * Leave it unprocessed
198 * in the buffer.
200 int slop = q - anchor;
201 /* {{ strcpy args overlap! }} */
202 strcpy(obuf, anchor);
203 ob = &obuf[slop];
204 return;
207 if (q == p ||
208 code > 49 || code < 0 ||
209 (!is_ansi_end(*q) && *q != ';'))
211 p_next = q;
212 break;
214 if (*q == ';')
215 q++;
217 switch (code)
219 default:
220 /* case 0: all attrs off */
221 fg = nm_fg_color;
222 bg = nm_bg_color;
223 at = 0;
224 break;
225 case 1: /* bold on */
226 at |= 1;
227 break;
228 case 3: /* italic on */
229 case 7: /* inverse on */
230 at |= 2;
231 break;
232 case 4: /* underline on */
233 at |= 4;
234 break;
235 case 5: /* slow blink on */
236 case 6: /* fast blink on */
237 at |= 8;
238 break;
239 case 8: /* concealed on */
240 fg = (bg & 7) | 8;
241 break;
242 case 22: /* bold off */
243 at &= ~1;
244 break;
245 case 23: /* italic off */
246 case 27: /* inverse off */
247 at &= ~2;
248 break;
249 case 24: /* underline off */
250 at &= ~4;
251 break;
252 case 30: case 31: case 32:
253 case 33: case 34: case 35:
254 case 36: case 37:
255 fg = (fg & 8) | (screen_color[code - 30]);
256 break;
257 case 39: /* default fg */
258 fg = nm_fg_color;
259 break;
260 case 40: case 41: case 42:
261 case 43: case 44: case 45:
262 case 46: case 47:
263 bg = (bg & 8) | (screen_color[code - 40]);
264 break;
265 case 49: /* default fg */
266 bg = nm_bg_color;
267 break;
269 p = q;
271 if (!is_ansi_end(*p) || p == p_next)
272 break;
273 if (at & 1)
275 fg = bo_fg_color;
276 bg = bo_bg_color;
277 } else if (at & 2)
279 fg = so_fg_color;
280 bg = so_bg_color;
281 } else if (at & 4)
283 fg = ul_fg_color;
284 bg = ul_bg_color;
285 } else if (at & 8)
287 fg = bl_fg_color;
288 bg = bl_bg_color;
290 fg &= 0xf;
291 bg &= 0xf;
292 WIN32setcolors(fg, bg);
293 p_next = anchor = p + 1;
294 } else
295 p_next++;
298 /* Output what's left in the buffer. */
299 WIN32textout(anchor, ob - anchor);
301 ob = obuf;
302 return;
304 #endif
305 #endif
306 fd = (any_display) ? 1 : 2;
307 if (write(fd, obuf, n) != n)
308 screen_trashed = 1;
309 ob = obuf;
313 * Output a character.
315 public int
316 putchr(c)
317 int c;
319 #if 0 /* fake UTF-8 output for testing */
320 extern int utf_mode;
321 if (utf_mode)
323 static char ubuf[MAX_UTF_CHAR_LEN];
324 static int ubuf_len = 0;
325 static int ubuf_index = 0;
326 if (ubuf_len == 0)
328 ubuf_len = utf_len(c);
329 ubuf_index = 0;
331 ubuf[ubuf_index++] = c;
332 if (ubuf_index < ubuf_len)
333 return c;
334 c = get_wchar(ubuf) & 0xFF;
335 ubuf_len = 0;
337 #endif
338 if (need_clr)
340 need_clr = 0;
341 clear_bot();
343 #if MSDOS_COMPILER
344 if (c == '\n' && is_tty)
346 /* remove_top(1); */
347 putchr('\r');
349 #else
350 #ifdef _OSK
351 if (c == '\n' && is_tty) /* In OS-9, '\n' == 0x0D */
352 putchr(0x0A);
353 #endif
354 #endif
356 * Some versions of flush() write to *ob, so we must flush
357 * when we are still one char from the end of obuf.
359 if (ob >= &obuf[sizeof(obuf)-1])
360 flush();
361 *ob++ = c;
362 at_prompt = 0;
363 return (c);
367 * Output a string.
369 public void
370 putstr(s)
371 register char *s;
373 while (*s != '\0')
374 putchr(*s++);
379 * Convert an integral type to a string.
381 #define TYPE_TO_A_FUNC(funcname, type) \
382 void funcname(num, buf) \
383 type num; \
384 char *buf; \
386 int neg = (num < 0); \
387 char tbuf[INT_STRLEN_BOUND(num)+2]; \
388 register char *s = tbuf + sizeof(tbuf); \
389 if (neg) num = -num; \
390 *--s = '\0'; \
391 do { \
392 *--s = (num % 10) + '0'; \
393 } while ((num /= 10) != 0); \
394 if (neg) *--s = '-'; \
395 strcpy(buf, s); \
398 TYPE_TO_A_FUNC(postoa, POSITION)
399 TYPE_TO_A_FUNC(linenumtoa, LINENUM)
400 TYPE_TO_A_FUNC(inttoa, int)
403 * Output an integer in a given radix.
405 static int
406 iprint_int(num)
407 int num;
409 char buf[INT_STRLEN_BOUND(num)];
411 inttoa(num, buf);
412 putstr(buf);
413 return (strlen(buf));
417 * Output a line number in a given radix.
419 static int
420 iprint_linenum(num)
421 LINENUM num;
423 char buf[INT_STRLEN_BOUND(num)];
425 linenumtoa(num, buf);
426 putstr(buf);
427 return (strlen(buf));
431 * This function implements printf-like functionality
432 * using a more portable argument list mechanism than printf's.
434 static int
435 less_printf(fmt, parg)
436 register char *fmt;
437 PARG *parg;
439 register char *s;
440 register int col;
442 col = 0;
443 while (*fmt != '\0')
445 if (*fmt != '%')
447 putchr(*fmt++);
448 col++;
449 } else
451 ++fmt;
452 switch (*fmt++)
454 case 's':
455 s = parg->p_string;
456 parg++;
457 while (*s != '\0')
459 putchr(*s++);
460 col++;
462 break;
463 case 'd':
464 col += iprint_int(parg->p_int);
465 parg++;
466 break;
467 case 'n':
468 col += iprint_linenum(parg->p_linenum);
469 parg++;
470 break;
474 return (col);
478 * Get a RETURN.
479 * If some other non-trivial char is pressed, unget it, so it will
480 * become the next command.
482 public void
483 get_return()
485 int c;
487 #if ONLY_RETURN
488 while ((c = getchr()) != '\n' && c != '\r')
489 bell();
490 #else
491 c = getchr();
492 if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
493 ungetcc(c);
494 #endif
498 * Output a message in the lower left corner of the screen
499 * and wait for carriage return.
501 public void
502 error(fmt, parg)
503 char *fmt;
504 PARG *parg;
506 int col = 0;
507 static char return_to_continue[] = " (press RETURN)";
509 errmsgs++;
511 if (any_display && is_tty)
513 if (!oldbot)
514 squish_check();
515 at_exit();
516 clear_bot();
517 at_enter(AT_STANDOUT);
518 col += so_s_width;
521 col += less_printf(fmt, parg);
523 if (!(any_display && is_tty))
525 putchr('\n');
526 return;
529 putstr(return_to_continue);
530 at_exit();
531 col += sizeof(return_to_continue) + so_e_width;
533 get_return();
534 lower_left();
536 if (col >= sc_width)
538 * Printing the message has probably scrolled the screen.
539 * {{ Unless the terminal doesn't have auto margins,
540 * in which case we just hammered on the right margin. }}
542 screen_trashed = 1;
544 flush();
547 static char intr_to_abort[] = "... (interrupt to abort)";
550 * Output a message in the lower left corner of the screen
551 * and don't wait for carriage return.
552 * Usually used to warn that we are beginning a potentially
553 * time-consuming operation.
555 public void
556 ierror(fmt, parg)
557 char *fmt;
558 PARG *parg;
560 at_exit();
561 clear_bot();
562 at_enter(AT_STANDOUT);
563 (void) less_printf(fmt, parg);
564 putstr(intr_to_abort);
565 at_exit();
566 flush();
567 need_clr = 1;
571 * Output a message in the lower left corner of the screen
572 * and return a single-character response.
574 public int
575 query(fmt, parg)
576 char *fmt;
577 PARG *parg;
579 register int c;
580 int col = 0;
582 if (any_display && is_tty)
583 clear_bot();
585 (void) less_printf(fmt, parg);
586 c = getchr();
588 if (!(any_display && is_tty))
590 putchr('\n');
591 return (c);
594 lower_left();
595 if (col >= sc_width)
596 screen_trashed = 1;
597 flush();
599 return (c);