2 * Copyright (C) 1984-2002 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.
13 * High level routines dealing with the output to the screen.
17 #if MSDOS_COMPILER==WIN32C
21 public int errmsgs
; /* Count of messages displayed by error() */
23 public int final_attr
;
27 extern int so_s_width
, so_e_width
;
28 extern int screen_trashed
;
29 extern int any_display
;
32 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
34 extern int nm_fg_color
, nm_bg_color
;
35 extern int bo_fg_color
, bo_bg_color
;
36 extern int ul_fg_color
, ul_bg_color
;
37 extern int so_fg_color
, so_bg_color
;
38 extern int bl_fg_color
, bl_bg_color
;
42 * Display the line which is in the line buffer.
55 * Don't output if a signal is pending.
61 curr_attr
= AT_NORMAL
;
63 for (i
= 0; (c
= gline(i
, &a
)) != '\0'; i
++)
68 * Changing attributes.
69 * Display the exit sequence for the old attribute
70 * and the enter sequence for the new one.
74 case AT_UNDERLINE
: ul_exit(); break;
75 case AT_BOLD
: bo_exit(); break;
76 case AT_BLINK
: bl_exit(); break;
77 case AT_STANDOUT
: so_exit(); break;
81 case AT_UNDERLINE
: ul_enter(); break;
82 case AT_BOLD
: bo_enter(); break;
83 case AT_BLINK
: bl_enter(); break;
84 case AT_STANDOUT
: so_enter(); break;
88 if (curr_attr
== AT_INVIS
)
98 case AT_UNDERLINE
: ul_exit(); break;
99 case AT_BOLD
: bo_exit(); break;
100 case AT_BLINK
: bl_exit(); break;
101 case AT_STANDOUT
: so_exit(); break;
103 final_attr
= curr_attr
;
106 static char obuf
[OUTBUF_SIZE
];
107 static char *ob
= obuf
;
110 * Flush buffered output.
112 * If we haven't displayed any file data yet,
113 * output messages on error output (file descriptor 2),
114 * otherwise output on standard output (file descriptor 1).
116 * This has the desirable effect of producing all
117 * error messages on error output if standard output
118 * is directed to a file. It also does the same if
119 * we never produce any real output; for example, if
120 * the input file(s) cannot be opened. If we do
121 * eventually produce output, code in edit() makes
122 * sure these messages can be seen before they are
123 * overwritten or scrolled away.
134 #if MSDOS_COMPILER==WIN32C
135 if (is_tty
&& any_display
)
139 CONSOLE_SCREEN_BUFFER_INFO scr
;
143 extern HANDLE con_out
;
147 * There is a bug in Win32 WriteConsole() if we're
148 * writing in the last cell with a different color.
149 * To avoid color problems in the bottom line,
150 * we scroll the screen manually, before writing.
152 GetConsoleScreenBufferInfo(con_out
, &scr
);
153 col
= scr
.dwCursorPosition
.X
;
154 row
= scr
.dwCursorPosition
.Y
;
155 for (op
= obuf
; op
< obuf
+ olen
; op
++)
161 } else if (*op
== '\r')
174 if (row
> scr
.srWindow
.Bottom
)
175 win32_scroll_up(row
- scr
.srWindow
.Bottom
);
176 WriteConsole(con_out
, obuf
, olen
, &nwritten
, NULL
);
181 #if MSDOS_COMPILER==MSOFTC
182 if (is_tty
&& any_display
)
190 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
191 if (is_tty
&& any_display
)
194 if (ctldisp
!= OPT_ONPLUS
)
199 * Look for SGR escape sequences, and convert them
200 * to color commands. Replace bold, underline,
201 * and italic escapes into colors specified via
202 * the -D command-line option.
204 char *anchor
, *p
, *p_next
;
205 int buflen
= ob
- obuf
;
206 unsigned char fg
, bg
, norm_attr
;
208 * Only dark colors mentioned here, so that
209 * bold has visible effect.
211 static enum COLORS screen_color
[] = {
212 BLACK
, RED
, GREEN
, BROWN
,
213 BLUE
, MAGENTA
, CYAN
, LIGHTGRAY
216 /* Normal text colors are used as baseline. */
217 bg
= nm_bg_color
& 0xf;
218 fg
= nm_fg_color
& 0xf;
219 norm_attr
= (bg
<< 4) | fg
;
220 for (anchor
= p_next
= obuf
;
221 (p_next
= memchr (p_next
, ESC
,
222 buflen
- (p_next
- obuf
)))
228 * Handle the null escape sequence
229 * (ESC-[m), which is used to restore
230 * the original color.
232 if (p
[1] == '[' && is_ansi_end(p
[2]))
240 if (p
[1] == '[') /* "Esc-[" sequence */
243 * If some chars seen since
244 * the last escape sequence,
245 * write it out to the screen
246 * using current text attributes.
257 while (!is_ansi_end(*p
))
260 long code
= strtol(p
, &q
, 10);
265 * Incomplete sequence.
266 * Leave it unprocessed
269 int slop
= q
- anchor
;
270 strcpy(obuf
, anchor
);
276 || code
> 49 || code
< 0
288 case 1: /* bold on */
292 case 3: /* italic on */
296 case 4: /* underline on */
300 case 8: /* concealed on */
303 case 0: /* all attrs off */
304 case 22:/* bold off */
305 case 23:/* italic off */
306 case 24:/* underline off */
310 case 30: case 31: case 32:
311 case 33: case 34: case 35:
313 fg
= (fg
& 8) | (screen_color
[code
- 30]);
315 case 39: /* default fg */
318 case 40: case 41: case 42:
319 case 43: case 44: case 45:
321 bg
= (bg
& 8) | (screen_color
[code
- 40]);
323 case 49: /* default fg */
329 if (is_ansi_end(*p
) && p
> p_next
)
333 textattr ((bg
<< 4)| fg
);
334 p_next
= anchor
= p
+ 1;
341 /* Output what's left in the buffer. */
350 fd
= (any_display
) ? 1 : 2;
351 if (write(fd
, obuf
, n
) != n
)
357 * Output a character.
369 if (c
== '\n' && is_tty
)
376 if (c
== '\n' && is_tty
) /* In OS-9, '\n' == 0x0D */
381 * Some versions of flush() write to *ob, so we must flush
382 * when we are still one char from the end of obuf.
384 if (ob
>= &obuf
[sizeof(obuf
)-1])
403 * Convert an integral type to a string.
405 #define TYPE_TO_A_FUNC(funcname, type) \
406 void funcname(num, buf) \
410 int neg = (num < 0); \
411 char tbuf[INT_STRLEN_BOUND(num)+2]; \
412 register char *s = tbuf + sizeof(tbuf); \
413 if (neg) num = -num; \
416 *--s = (num % 10) + '0'; \
417 } while ((num /= 10) != 0); \
418 if (neg) *--s = '-'; \
422 TYPE_TO_A_FUNC(postoa
, POSITION
)
423 TYPE_TO_A_FUNC(linenumtoa
, LINENUM
)
424 TYPE_TO_A_FUNC(inttoa
, int)
427 * Output an integer in a given radix.
433 char buf
[INT_STRLEN_BOUND(num
)];
437 return (strlen(buf
));
441 * Output a line number in a given radix.
447 char buf
[INT_STRLEN_BOUND(num
)];
449 linenumtoa(num
, buf
);
451 return (strlen(buf
));
455 * This function implements printf-like functionality
456 * using a more portable argument list mechanism than printf's.
459 less_printf(fmt
, parg
)
488 col
+= iprint_int(parg
->p_int
);
492 col
+= iprint_linenum(parg
->p_linenum
);
503 * If some other non-trivial char is pressed, unget it, so it will
504 * become the next command.
512 while ((c
= getchr()) != '\n' && c
!= '\r')
516 if (c
!= '\n' && c
!= '\r' && c
!= ' ' && c
!= READ_INTR
)
522 * Output a message in the lower left corner of the screen
523 * and wait for carriage return.
531 static char return_to_continue
[] = " (press RETURN)";
535 if (any_display
&& is_tty
)
542 col
+= less_printf(fmt
, parg
);
544 if (!(any_display
&& is_tty
))
550 putstr(return_to_continue
);
552 col
+= sizeof(return_to_continue
) + so_e_width
;
559 * Printing the message has probably scrolled the screen.
560 * {{ Unless the terminal doesn't have auto margins,
561 * in which case we just hammered on the right margin. }}
568 static char intr_to_abort
[] = "... (interrupt to abort)";
571 * Output a message in the lower left corner of the screen
572 * and don't wait for carriage return.
573 * Usually used to warn that we are beginning a potentially
574 * time-consuming operation.
583 (void) less_printf(fmt
, parg
);
584 putstr(intr_to_abort
);
591 * Output a message in the lower left corner of the screen
592 * and return a single-character response.
602 if (any_display
&& is_tty
)
605 (void) less_printf(fmt
, parg
);
608 if (!(any_display
&& is_tty
))