2 * Copyright (C) 1984-2016 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, see the README file.
12 * High level routines dealing with the output to the screen.
16 #if MSDOS_COMPILER==WIN32C
20 public int errmsgs; /* Count of messages displayed by error() */
22 public int final_attr;
27 extern int so_s_width, so_e_width;
28 extern int screen_trashed;
29 extern int any_display;
33 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
35 extern int nm_fg_color, nm_bg_color;
36 extern int bo_fg_color, bo_bg_color;
37 extern int ul_fg_color, ul_bg_color;
38 extern int so_fg_color, so_bg_color;
39 extern int bl_fg_color, bl_bg_color;
44 * Display the line which is in the line buffer.
56 * Don't output if a signal is pending.
62 final_attr = AT_NORMAL;
64 for (i = 0; (c = gline(i, &a)) != '\0'; i++)
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.
102 n = (int) (ob - obuf);
106 #if MSDOS_COMPILER==MSOFTC
107 if (is_tty && any_display)
115 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
116 if (is_tty && any_display)
119 if (ctldisp != OPT_ONPLUS)
120 WIN32textout(obuf, ob - obuf);
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 static unsigned char fg, fgi, bg, bgi;
131 static unsigned char at;
133 #if MSDOS_COMPILER==WIN32C
134 /* Screen colors used by 3x and 4x SGR commands. */
135 static unsigned char screen_color[] = {
139 FOREGROUND_RED|FOREGROUND_GREEN,
141 FOREGROUND_BLUE|FOREGROUND_RED,
142 FOREGROUND_BLUE|FOREGROUND_GREEN,
143 FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
146 static enum COLORS screen_color[] = {
147 BLACK, RED, GREEN, BROWN,
148 BLUE, MAGENTA, CYAN, LIGHTGRAY
152 if (fg == 0 && bg == 0)
154 fg = nm_fg_color & 7;
155 fgi = nm_fg_color & 8;
156 bg = nm_bg_color & 7;
157 bgi = nm_bg_color & 8;
159 for (anchor = p_next = obuf;
160 (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; )
163 if (p[1] == '[') /* "ESC-[" sequence */
168 * If some chars seen since
169 * the last escape sequence,
170 * write them out to the screen.
172 WIN32textout(anchor, p-anchor);
175 p += 2; /* Skip the "ESC-[" */
179 * Handle null escape sequence
180 * "ESC[m", which restores
185 fg = nm_fg_color & 7;
186 fgi = nm_fg_color & 8;
187 bg = nm_bg_color & 7;
188 bgi = nm_bg_color & 8;
190 WIN32setcolors(nm_fg_color, nm_bg_color);
197 * Select foreground/background colors
198 * based on the escape sequence.
200 while (!is_ansi_end(*p))
203 long code = strtol(p, &q, 10);
208 * Incomplete sequence.
209 * Leave it unprocessed
212 int slop = (int) (q - anchor);
213 /* {{ strcpy args overlap! }} */
214 strcpy(obuf, anchor);
220 code > 49 || code < 0 ||
221 (!is_ansi_end(*q) && *q != ';'))
235 /* case 0: all attrs off */
236 fg = nm_fg_color & 7;
237 bg = nm_bg_color & 7;
242 * \e[0;...m resets them
250 fgi = nm_fg_color & 8;
251 bgi = nm_bg_color & 8;
254 case 1: /* bold on */
258 case 3: /* italic on */
259 case 7: /* inverse on */
262 case 4: /* underline on */
266 case 5: /* slow blink on */
267 case 6: /* fast blink on */
271 case 8: /* concealed on */
274 case 22: /* bold off */
278 case 23: /* italic off */
279 case 27: /* inverse off */
282 case 24: /* underline off */
286 case 28: /* concealed off */
289 case 30: case 31: case 32:
290 case 33: case 34: case 35:
292 fg = screen_color[code - 30];
295 case 39: /* default fg */
296 fg = nm_fg_color & 7;
299 case 40: case 41: case 42:
300 case 43: case 44: case 45:
302 bg = screen_color[code - 40];
305 case 49: /* default bg */
306 bg = nm_bg_color & 7;
312 if (!is_ansi_end(*p) || p == p_next)
315 * In SGR mode, the ANSI sequence is
316 * always honored; otherwise if an attr
317 * is used by itself ("\e[1m" versus
318 * "\e[1;33m", for example), set the
319 * color assigned to that attribute.
321 if (sgr_mode || (at & 32))
360 WIN32setcolors(f, b);
361 p_next = anchor = p + 1;
366 /* Output what's left in the buffer. */
367 WIN32textout(anchor, ob - anchor);
374 fd = (any_display) ? 1 : 2;
375 if (write(fd, obuf, n) != n)
381 * Output a character.
387 #if 0 /* fake UTF-8 output for testing */
391 static char ubuf[MAX_UTF_CHAR_LEN];
392 static int ubuf_len = 0;
393 static int ubuf_index = 0;
396 ubuf_len = utf_len(c);
399 ubuf[ubuf_index++] = c;
400 if (ubuf_index < ubuf_len)
402 c = get_wchar(ubuf) & 0xFF;
412 if (c == '\n' && is_tty)
419 if (c == '\n' && is_tty) /* In OS-9, '\n' == 0x0D */
424 * Some versions of flush() write to *ob, so we must flush
425 * when we are still one char from the end of obuf.
427 if (ob >= &obuf[sizeof(obuf)-1])
447 * Convert an integral type to a string.
449 #define TYPE_TO_A_FUNC(funcname, type) \
450 void funcname(num, buf) \
454 int neg = (num < 0); \
455 char tbuf[INT_STRLEN_BOUND(num)+2]; \
456 register char *s = tbuf + sizeof(tbuf); \
457 if (neg) num = -num; \
460 *--s = (num % 10) + '0'; \
461 } while ((num /= 10) != 0); \
462 if (neg) *--s = '-'; \
466 TYPE_TO_A_FUNC(postoa, POSITION)
467 TYPE_TO_A_FUNC(linenumtoa, LINENUM)
468 TYPE_TO_A_FUNC(inttoa, int)
471 * Output an integer in a given radix.
477 char buf[INT_STRLEN_BOUND(num)];
481 return ((int) strlen(buf));
485 * Output a line number in a given radix.
491 char buf[INT_STRLEN_BOUND(num)];
493 linenumtoa(num, buf);
495 return ((int) strlen(buf));
499 * This function implements printf-like functionality
500 * using a more portable argument list mechanism than printf's.
503 less_printf(fmt, parg)
532 col += iprint_int(parg->p_int);
536 col += iprint_linenum(parg->p_linenum);
547 * If some other non-trivial char is pressed, unget it, so it will
548 * become the next command.
556 while ((c = getchr()) != '\n' && c != '\r')
560 if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
566 * Output a message in the lower left corner of the screen
567 * and wait for carriage return.
575 static char return_to_continue[] = " (press RETURN)";
579 if (any_display && is_tty)
585 at_enter(AT_STANDOUT);
589 col += less_printf(fmt, parg);
591 if (!(any_display && is_tty))
597 putstr(return_to_continue);
599 col += sizeof(return_to_continue) + so_e_width;
607 * Printing the message has probably scrolled the screen.
608 * {{ Unless the terminal doesn't have auto margins,
609 * in which case we just hammered on the right margin. }}
616 static char intr_to_abort[] = "... (interrupt to abort)";
619 * Output a message in the lower left corner of the screen
620 * and don't wait for carriage return.
621 * Usually used to warn that we are beginning a potentially
622 * time-consuming operation.
631 at_enter(AT_STANDOUT);
632 (void) less_printf(fmt, parg);
633 putstr(intr_to_abort);
640 * Output a message in the lower left corner of the screen
641 * and return a single-character response.
651 if (any_display && is_tty)
654 (void) less_printf(fmt, parg);
657 if (!(any_display && is_tty))