2 * Copyright (C) 1984-2017 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
18 #ifndef COMMON_LVB_UNDERSCORE
19 #define COMMON_LVB_UNDERSCORE 0x8000
23 public int errmsgs; /* Count of messages displayed by error() */
25 public int final_attr;
30 extern int so_s_width, so_e_width;
31 extern int screen_trashed;
32 extern int any_display;
36 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
38 extern int nm_fg_color, nm_bg_color;
39 extern int bo_fg_color, bo_bg_color;
40 extern int ul_fg_color, ul_bg_color;
41 extern int so_fg_color, so_bg_color;
42 extern int bl_fg_color, bl_bg_color;
44 #if MSDOS_COMPILER==WIN32C
50 * Display the line which is in the line buffer.
62 * Don't output if a signal is pending.
68 final_attr = AT_NORMAL;
70 for (i = 0; (c = gline(i, &a)) != '\0'; i++)
83 static char obuf[OUTBUF_SIZE];
84 static char *ob = obuf;
87 * Flush buffered output.
89 * If we haven't displayed any file data yet,
90 * output messages on error output (file descriptor 2),
91 * otherwise output on standard output (file descriptor 1).
93 * This has the desirable effect of producing all
94 * error messages on error output if standard output
95 * is directed to a file. It also does the same if
96 * we never produce any real output; for example, if
97 * the input file(s) cannot be opened. If we do
98 * eventually produce output, code in edit() makes
99 * sure these messages can be seen before they are
100 * overwritten or scrolled away.
108 n = (int) (ob - obuf);
112 #if MSDOS_COMPILER==MSOFTC
113 if (is_tty && any_display)
121 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
122 if (is_tty && any_display)
125 if (ctldisp != OPT_ONPLUS)
126 WIN32textout(obuf, ob - obuf);
130 * Look for SGR escape sequences, and convert them
131 * to color commands. Replace bold, underline,
132 * and italic escapes into colors specified via
133 * the -D command-line option.
135 char *anchor, *p, *p_next;
136 static int fg, fgi, bg, bgi;
139 #if MSDOS_COMPILER==WIN32C
140 /* Screen colors used by 3x and 4x SGR commands. */
141 static unsigned char screen_color[] = {
145 FOREGROUND_RED|FOREGROUND_GREEN,
147 FOREGROUND_BLUE|FOREGROUND_RED,
148 FOREGROUND_BLUE|FOREGROUND_GREEN,
149 FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
152 static enum COLORS screen_color[] = {
153 BLACK, RED, GREEN, BROWN,
154 BLUE, MAGENTA, CYAN, LIGHTGRAY
158 if (fg == 0 && bg == 0)
160 fg = nm_fg_color & 7;
161 fgi = nm_fg_color & 8;
162 bg = nm_bg_color & 7;
163 bgi = nm_bg_color & 8;
165 for (anchor = p_next = obuf;
166 (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; )
169 if (p[1] == '[') /* "ESC-[" sequence */
174 * If some chars seen since
175 * the last escape sequence,
176 * write them out to the screen.
178 WIN32textout(anchor, p-anchor);
181 p += 2; /* Skip the "ESC-[" */
185 * Handle null escape sequence
186 * "ESC[m", which restores
191 fg = nm_fg_color & 7;
192 fgi = nm_fg_color & 8;
193 bg = nm_bg_color & 7;
194 bgi = nm_bg_color & 8;
196 WIN32setcolors(nm_fg_color, nm_bg_color);
203 * Select foreground/background colors
204 * based on the escape sequence.
206 while (!is_ansi_end(*p))
209 long code = strtol(p, &q, 10);
214 * Incomplete sequence.
215 * Leave it unprocessed
218 int slop = (int) (q - anchor);
219 /* {{ strcpy args overlap! }} */
220 strcpy(obuf, anchor);
226 code > 49 || code < 0 ||
227 (!is_ansi_end(*q) && *q != ';'))
241 /* case 0: all attrs off */
242 fg = nm_fg_color & 7;
243 bg = nm_bg_color & 7;
248 * \e[0;...m resets them
256 fgi = nm_fg_color & 8;
257 bgi = nm_bg_color & 8;
260 case 1: /* bold on */
264 case 3: /* italic on */
265 case 7: /* inverse on */
268 case 4: /* underline on */
269 #if MSDOS_COMPILER==WIN32C
271 bgi = COMMON_LVB_UNDERSCORE >> 4;
277 case 5: /* slow blink on */
278 case 6: /* fast blink on */
282 case 8: /* concealed on */
285 case 22: /* bold off */
289 case 23: /* italic off */
290 case 27: /* inverse off */
293 case 24: /* underline off */
297 case 28: /* concealed off */
300 case 30: case 31: case 32:
301 case 33: case 34: case 35:
303 fg = screen_color[code - 30];
306 case 39: /* default fg */
307 fg = nm_fg_color & 7;
310 case 40: case 41: case 42:
311 case 43: case 44: case 45:
313 bg = screen_color[code - 40];
316 case 49: /* default bg */
317 bg = nm_bg_color & 7;
323 if (!is_ansi_end(*p) || p == p_next)
326 * In SGR mode, the ANSI sequence is
327 * always honored; otherwise if an attr
328 * is used by itself ("\e[1m" versus
329 * "\e[1;33m", for example), set the
330 * color assigned to that attribute.
332 if (sgr_mode || (at & 32))
370 #if MSDOS_COMPILER==WIN32C
371 b &= 0xf | (COMMON_LVB_UNDERSCORE >> 4);
375 WIN32setcolors(f, b);
376 p_next = anchor = p + 1;
381 /* Output what's left in the buffer. */
382 WIN32textout(anchor, ob - anchor);
389 fd = (any_display) ? 1 : 2;
390 if (write(fd, obuf, n) != n)
396 * Output a character.
402 #if 0 /* fake UTF-8 output for testing */
406 static char ubuf[MAX_UTF_CHAR_LEN];
407 static int ubuf_len = 0;
408 static int ubuf_index = 0;
411 ubuf_len = utf_len(c);
414 ubuf[ubuf_index++] = c;
415 if (ubuf_index < ubuf_len)
417 c = get_wchar(ubuf) & 0xFF;
427 if (c == '\n' && is_tty)
434 if (c == '\n' && is_tty) /* In OS-9, '\n' == 0x0D */
439 * Some versions of flush() write to *ob, so we must flush
440 * when we are still one char from the end of obuf.
442 if (ob >= &obuf[sizeof(obuf)-1])
462 * Convert an integral type to a string.
464 #define TYPE_TO_A_FUNC(funcname, type) \
465 void funcname(num, buf) \
469 int neg = (num < 0); \
470 char tbuf[INT_STRLEN_BOUND(num)+2]; \
471 char *s = tbuf + sizeof(tbuf); \
472 if (neg) num = -num; \
475 *--s = (num % 10) + '0'; \
476 } while ((num /= 10) != 0); \
477 if (neg) *--s = '-'; \
481 TYPE_TO_A_FUNC(postoa, POSITION)
482 TYPE_TO_A_FUNC(linenumtoa, LINENUM)
483 TYPE_TO_A_FUNC(inttoa, int)
486 * Output an integer in a given radix.
492 char buf[INT_STRLEN_BOUND(num)];
496 return ((int) strlen(buf));
500 * Output a line number in a given radix.
506 char buf[INT_STRLEN_BOUND(num)];
508 linenumtoa(num, buf);
510 return ((int) strlen(buf));
514 * This function implements printf-like functionality
515 * using a more portable argument list mechanism than printf's.
518 less_printf(fmt, parg)
547 col += iprint_int(parg->p_int);
551 col += iprint_linenum(parg->p_linenum);
565 * If some other non-trivial char is pressed, unget it, so it will
566 * become the next command.
574 while ((c = getchr()) != '\n' && c != '\r')
578 if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
584 * Output a message in the lower left corner of the screen
585 * and wait for carriage return.
593 static char return_to_continue[] = " (press RETURN)";
597 if (any_display && is_tty)
603 at_enter(AT_STANDOUT);
607 col += less_printf(fmt, parg);
609 if (!(any_display && is_tty))
615 putstr(return_to_continue);
617 col += sizeof(return_to_continue) + so_e_width;
625 * Printing the message has probably scrolled the screen.
626 * {{ Unless the terminal doesn't have auto margins,
627 * in which case we just hammered on the right margin. }}
634 static char intr_to_abort[] = "... (interrupt to abort)";
637 * Output a message in the lower left corner of the screen
638 * and don't wait for carriage return.
639 * Usually used to warn that we are beginning a potentially
640 * time-consuming operation.
649 at_enter(AT_STANDOUT);
650 (void) less_printf(fmt, parg);
651 putstr(intr_to_abort);
658 * Output a message in the lower left corner of the screen
659 * and return a single-character response.
669 if (any_display && is_tty)
672 (void) less_printf(fmt, parg);
675 if (!(any_display && is_tty))