1 /* $NetBSD: output.c,v 1.4 2013/09/04 19:44:21 tron Exp $ */
4 * Copyright (C) 1984-2012 Mark Nudelman
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Less License, as specified in the README file.
9 * For more information, see the README file.
14 * High level routines dealing with the output to the screen.
18 #if MSDOS_COMPILER==WIN32C
22 public int errmsgs
; /* Count of messages displayed by error() */
24 public int final_attr
;
29 extern int so_s_width
, so_e_width
;
30 extern int screen_trashed
;
31 extern int any_display
;
35 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
37 extern int nm_fg_color
, nm_bg_color
;
38 extern int bo_fg_color
, bo_bg_color
;
39 extern int ul_fg_color
, ul_bg_color
;
40 extern int so_fg_color
, so_bg_color
;
41 extern int bl_fg_color
, bl_bg_color
;
45 * Display the line which is in the line buffer.
57 * Don't output if a signal is pending.
63 final_attr
= AT_NORMAL
;
65 for (i
= 0; (c
= gline(i
, &a
)) != '\0'; i
++)
78 static char obuf
[OUTBUF_SIZE
];
79 static char *ob
= obuf
;
82 * Flush buffered output.
84 * If we haven't displayed any file data yet,
85 * output messages on error output (file descriptor 2),
86 * otherwise output on standard output (file descriptor 1).
88 * This has the desirable effect of producing all
89 * error messages on error output if standard output
90 * is directed to a file. It also does the same if
91 * we never produce any real output; for example, if
92 * the input file(s) cannot be opened. If we do
93 * eventually produce output, code in edit() makes
94 * sure these messages can be seen before they are
95 * overwritten or scrolled away.
107 #if MSDOS_COMPILER==MSOFTC
108 if (is_tty
&& any_display
)
116 #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
117 if (is_tty
&& any_display
)
120 if (ctldisp
!= OPT_ONPLUS
)
121 WIN32textout(obuf
, ob
- obuf
);
125 * Look for SGR escape sequences, and convert them
126 * to color commands. Replace bold, underline,
127 * and italic escapes into colors specified via
128 * the -D command-line option.
130 char *anchor
, *p
, *p_next
;
131 unsigned char fg
, bg
;
132 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 for (anchor
= p_next
= obuf
;
153 (p_next
= memchr(p_next
, ESC
, ob
- p_next
)) != NULL
; )
156 if (p
[1] == '[') /* "ESC-[" sequence */
161 * If some chars seen since
162 * the last escape sequence,
163 * write them out to the screen.
165 WIN32textout(anchor
, p
-anchor
);
168 p
+= 2; /* Skip the "ESC-[" */
172 * Handle null escape sequence
173 * "ESC[m", which restores
179 WIN32setcolors(nm_fg_color
, nm_bg_color
);
185 * Select foreground/background colors
186 * based on the escape sequence.
190 while (!is_ansi_end(*p
))
193 long code
= strtol(p
, &q
, 10);
198 * Incomplete sequence.
199 * Leave it unprocessed
202 int slop
= q
- anchor
;
203 /* {{ strcpy args overlap! }} */
204 strcpy(obuf
, anchor
);
210 code
> 49 || code
< 0 ||
211 (!is_ansi_end(*q
) && *q
!= ';'))
222 /* case 0: all attrs off */
227 case 1: /* bold on */
230 case 3: /* italic on */
231 case 7: /* inverse on */
234 case 4: /* underline on */
237 case 5: /* slow blink on */
238 case 6: /* fast blink on */
241 case 8: /* concealed on */
244 case 22: /* bold off */
247 case 23: /* italic off */
248 case 27: /* inverse off */
251 case 24: /* underline off */
254 case 30: case 31: case 32:
255 case 33: case 34: case 35:
257 fg
= (fg
& 8) | (screen_color
[code
- 30]);
259 case 39: /* default fg */
262 case 40: case 41: case 42:
263 case 43: case 44: case 45:
265 bg
= (bg
& 8) | (screen_color
[code
- 40]);
267 case 49: /* default fg */
273 if (!is_ansi_end(*p
) || p
== p_next
)
278 * If \e[1m use defined bold
279 * color, else set intensity.
283 #if MSDOS_COMPILER==WIN32C
284 fg
|= FOREGROUND_INTENSITY
;
285 bg
|= BACKGROUND_INTENSITY
;
307 WIN32setcolors(fg
, bg
);
308 p_next
= anchor
= p
+ 1;
313 /* Output what's left in the buffer. */
314 WIN32textout(anchor
, ob
- anchor
);
321 fd
= (any_display
) ? 1 : 2;
322 if (write(fd
, obuf
, n
) != n
)
328 * Output a character.
334 #if 0 /* fake UTF-8 output for testing */
338 static char ubuf
[MAX_UTF_CHAR_LEN
];
339 static int ubuf_len
= 0;
340 static int ubuf_index
= 0;
343 ubuf_len
= utf_len(c
);
346 ubuf
[ubuf_index
++] = c
;
347 if (ubuf_index
< ubuf_len
)
349 c
= get_wchar(ubuf
) & 0xFF;
359 if (c
== '\n' && is_tty
)
366 if (c
== '\n' && is_tty
) /* In OS-9, '\n' == 0x0D */
371 * Some versions of flush() write to *ob, so we must flush
372 * when we are still one char from the end of obuf.
374 if (ob
>= &obuf
[sizeof(obuf
)-1])
394 * Convert an integral type to a string.
396 #define TYPE_TO_A_FUNC(funcname, type) \
397 void funcname(num, buf) \
401 int neg = (num < 0); \
402 char tbuf[INT_STRLEN_BOUND(num)+2]; \
403 register char *s = tbuf + sizeof(tbuf); \
404 if (neg) num = -num; \
407 *--s = (num % 10) + '0'; \
408 } while ((num /= 10) != 0); \
409 if (neg) *--s = '-'; \
413 TYPE_TO_A_FUNC(postoa
, POSITION
)
414 TYPE_TO_A_FUNC(linenumtoa
, LINENUM
)
415 TYPE_TO_A_FUNC(inttoa
, int)
418 * Output an integer in a given radix.
424 char buf
[INT_STRLEN_BOUND(num
)];
428 return (strlen(buf
));
432 * Output a line number in a given radix.
438 char buf
[INT_STRLEN_BOUND(num
)];
440 linenumtoa(num
, buf
);
442 return (strlen(buf
));
446 * This function implements printf-like functionality
447 * using a more portable argument list mechanism than printf's.
450 less_printf(fmt
, parg
)
454 register constant
char *s
;
479 col
+= iprint_int(parg
->p_int
);
483 col
+= iprint_linenum(parg
->p_linenum
);
494 * If some other non-trivial char is pressed, unget it, so it will
495 * become the next command.
503 while ((c
= getchr()) != '\n' && c
!= '\r')
507 if (c
!= '\n' && c
!= '\r' && c
!= ' ' && c
!= READ_INTR
)
513 * Output a message in the lower left corner of the screen
514 * and wait for carriage return.
522 static char return_to_continue
[] = " (press RETURN)";
526 if (any_display
&& is_tty
)
532 at_enter(AT_STANDOUT
);
536 col
+= less_printf(fmt
, parg
);
538 if (!(any_display
&& is_tty
))
544 putstr(return_to_continue
);
546 col
+= sizeof(return_to_continue
) + so_e_width
;
554 * Printing the message has probably scrolled the screen.
555 * {{ Unless the terminal doesn't have auto margins,
556 * in which case we just hammered on the right margin. }}
563 static char intr_to_abort
[] = "... (interrupt to abort)";
566 * Output a message in the lower left corner of the screen
567 * and don't wait for carriage return.
568 * Usually used to warn that we are beginning a potentially
569 * time-consuming operation.
578 at_enter(AT_STANDOUT
);
579 (void) less_printf(fmt
, parg
);
580 putstr(intr_to_abort
);
587 * Output a message in the lower left corner of the screen
588 * and return a single-character response.
598 if (any_display
&& is_tty
)
601 (void) less_printf(fmt
, parg
);
604 if (!(any_display
&& is_tty
))