X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=thirdparty%2Fless%2Foutput.c;fp=thirdparty%2Fless%2Foutput.c;h=a4fdada1ba7c5b38e62a5e35c99ecc8eb93252a6;hb=70c3470408854526136adcf3705d1dc7e7189c0a;hp=0000000000000000000000000000000000000000;hpb=d3846c6fda2eb17ccd0402551be8b569ab2dbc5a;p=apitrace diff --git a/thirdparty/less/output.c b/thirdparty/less/output.c new file mode 100644 index 0000000..a4fdada --- /dev/null +++ b/thirdparty/less/output.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 1984-2011 Mark Nudelman + * + * You may distribute under the terms of either the GNU General Public + * License or the Less License, as specified in the README file. + * + * For more information about less, or for information on how to + * contact the author, see the README file. + */ + + +/* + * High level routines dealing with the output to the screen. + */ + +#include "less.h" +#if MSDOS_COMPILER==WIN32C +#include "windows.h" +#endif + +public int errmsgs; /* Count of messages displayed by error() */ +public int need_clr; +public int final_attr; +public int at_prompt; + +extern int sigs; +extern int sc_width; +extern int so_s_width, so_e_width; +extern int screen_trashed; +extern int any_display; +extern int is_tty; +extern int oldbot; + +#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC +extern int ctldisp; +extern int nm_fg_color, nm_bg_color; +extern int bo_fg_color, bo_bg_color; +extern int ul_fg_color, ul_bg_color; +extern int so_fg_color, so_bg_color; +extern int bl_fg_color, bl_bg_color; +#endif + +/* + * Display the line which is in the line buffer. + */ + public void +put_line() +{ + register int c; + register int i; + int a; + + if (ABORT_SIGS()) + { + /* + * Don't output if a signal is pending. + */ + screen_trashed = 1; + return; + } + + final_attr = AT_NORMAL; + + for (i = 0; (c = gline(i, &a)) != '\0'; i++) + { + at_switch(a); + final_attr = a; + if (c == '\b') + putbs(); + else + putchr(c); + } + + at_exit(); +} + +static char obuf[OUTBUF_SIZE]; +static char *ob = obuf; + +/* + * Flush buffered output. + * + * If we haven't displayed any file data yet, + * output messages on error output (file descriptor 2), + * otherwise output on standard output (file descriptor 1). + * + * This has the desirable effect of producing all + * error messages on error output if standard output + * is directed to a file. It also does the same if + * we never produce any real output; for example, if + * the input file(s) cannot be opened. If we do + * eventually produce output, code in edit() makes + * sure these messages can be seen before they are + * overwritten or scrolled away. + */ + public void +flush() +{ + register int n; + register int fd; + + n = ob - obuf; + if (n == 0) + return; + +#if MSDOS_COMPILER==MSOFTC + if (is_tty && any_display) + { + *ob = '\0'; + _outtext(obuf); + ob = obuf; + return; + } +#else +#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC + if (is_tty && any_display) + { + *ob = '\0'; + if (ctldisp != OPT_ONPLUS) + WIN32textout(obuf, ob - obuf); + else + { + /* + * Look for SGR escape sequences, and convert them + * to color commands. Replace bold, underline, + * and italic escapes into colors specified via + * the -D command-line option. + */ + char *anchor, *p, *p_next; + unsigned char fg, bg; + static unsigned char at; +#if MSDOS_COMPILER==WIN32C + /* Screen colors used by 3x and 4x SGR commands. */ + static unsigned char screen_color[] = { + 0, /* BLACK */ + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_RED|FOREGROUND_GREEN, + FOREGROUND_BLUE, + FOREGROUND_BLUE|FOREGROUND_RED, + FOREGROUND_BLUE|FOREGROUND_GREEN, + FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED + }; +#else + static enum COLORS screen_color[] = { + BLACK, RED, GREEN, BROWN, + BLUE, MAGENTA, CYAN, LIGHTGRAY + }; +#endif + + for (anchor = p_next = obuf; + (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; ) + { + p = p_next; + if (p[1] == '[') /* "ESC-[" sequence */ + { + if (p > anchor) + { + /* + * If some chars seen since + * the last escape sequence, + * write them out to the screen. + */ + WIN32textout(anchor, p-anchor); + anchor = p; + } + p += 2; /* Skip the "ESC-[" */ + if (is_ansi_end(*p)) + { + /* + * Handle null escape sequence + * "ESC[m", which restores + * the normal color. + */ + p++; + anchor = p_next = p; + WIN32setcolors(nm_fg_color, nm_bg_color); + continue; + } + p_next = p; + + /* + * Select foreground/background colors + * based on the escape sequence. + */ + fg = nm_fg_color; + bg = nm_bg_color; + while (!is_ansi_end(*p)) + { + char *q; + long code = strtol(p, &q, 10); + + if (*q == '\0') + { + /* + * Incomplete sequence. + * Leave it unprocessed + * in the buffer. + */ + int slop = q - anchor; + /* {{ strcpy args overlap! }} */ + strcpy(obuf, anchor); + ob = &obuf[slop]; + return; + } + + if (q == p || + code > 49 || code < 0 || + (!is_ansi_end(*q) && *q != ';')) + { + p_next = q; + break; + } + if (*q == ';') + q++; + + switch (code) + { + default: + /* case 0: all attrs off */ + fg = nm_fg_color; + bg = nm_bg_color; + at = 0; + break; + case 1: /* bold on */ + at |= 1; + break; + case 3: /* italic on */ + case 7: /* inverse on */ + at |= 2; + break; + case 4: /* underline on */ + at |= 4; + break; + case 5: /* slow blink on */ + case 6: /* fast blink on */ + at |= 8; + break; + case 8: /* concealed on */ + fg = (bg & 7) | 8; + break; + case 22: /* bold off */ + at &= ~1; + break; + case 23: /* italic off */ + case 27: /* inverse off */ + at &= ~2; + break; + case 24: /* underline off */ + at &= ~4; + break; + case 30: case 31: case 32: + case 33: case 34: case 35: + case 36: case 37: + fg = (fg & 8) | (screen_color[code - 30]); + break; + case 39: /* default fg */ + fg = nm_fg_color; + break; + case 40: case 41: case 42: + case 43: case 44: case 45: + case 46: case 47: + bg = (bg & 8) | (screen_color[code - 40]); + break; + case 49: /* default fg */ + bg = nm_bg_color; + break; + } + p = q; + } + if (!is_ansi_end(*p) || p == p_next) + break; + if (at & 1) + { + fg = bo_fg_color; + bg = bo_bg_color; + } else if (at & 2) + { + fg = so_fg_color; + bg = so_bg_color; + } else if (at & 4) + { + fg = ul_fg_color; + bg = ul_bg_color; + } else if (at & 8) + { + fg = bl_fg_color; + bg = bl_bg_color; + } + fg &= 0xf; + bg &= 0xf; + WIN32setcolors(fg, bg); + p_next = anchor = p + 1; + } else + p_next++; + } + + /* Output what's left in the buffer. */ + WIN32textout(anchor, ob - anchor); + } + ob = obuf; + return; + } +#endif +#endif + fd = (any_display) ? 1 : 2; + if (write(fd, obuf, n) != n) + screen_trashed = 1; + ob = obuf; +} + +/* + * Output a character. + */ + public int +putchr(c) + int c; +{ +#if 0 /* fake UTF-8 output for testing */ + extern int utf_mode; + if (utf_mode) + { + static char ubuf[MAX_UTF_CHAR_LEN]; + static int ubuf_len = 0; + static int ubuf_index = 0; + if (ubuf_len == 0) + { + ubuf_len = utf_len(c); + ubuf_index = 0; + } + ubuf[ubuf_index++] = c; + if (ubuf_index < ubuf_len) + return c; + c = get_wchar(ubuf) & 0xFF; + ubuf_len = 0; + } +#endif + if (need_clr) + { + need_clr = 0; + clear_bot(); + } +#if MSDOS_COMPILER + if (c == '\n' && is_tty) + { + /* remove_top(1); */ + putchr('\r'); + } +#else +#ifdef _OSK + if (c == '\n' && is_tty) /* In OS-9, '\n' == 0x0D */ + putchr(0x0A); +#endif +#endif + /* + * Some versions of flush() write to *ob, so we must flush + * when we are still one char from the end of obuf. + */ + if (ob >= &obuf[sizeof(obuf)-1]) + flush(); + *ob++ = c; + at_prompt = 0; + return (c); +} + +/* + * Output a string. + */ + public void +putstr(s) + register char *s; +{ + while (*s != '\0') + putchr(*s++); +} + + +/* + * Convert an integral type to a string. + */ +#define TYPE_TO_A_FUNC(funcname, type) \ +void funcname(num, buf) \ + type num; \ + char *buf; \ +{ \ + int neg = (num < 0); \ + char tbuf[INT_STRLEN_BOUND(num)+2]; \ + register char *s = tbuf + sizeof(tbuf); \ + if (neg) num = -num; \ + *--s = '\0'; \ + do { \ + *--s = (num % 10) + '0'; \ + } while ((num /= 10) != 0); \ + if (neg) *--s = '-'; \ + strcpy(buf, s); \ +} + +TYPE_TO_A_FUNC(postoa, POSITION) +TYPE_TO_A_FUNC(linenumtoa, LINENUM) +TYPE_TO_A_FUNC(inttoa, int) + +/* + * Output an integer in a given radix. + */ + static int +iprint_int(num) + int num; +{ + char buf[INT_STRLEN_BOUND(num)]; + + inttoa(num, buf); + putstr(buf); + return (strlen(buf)); +} + +/* + * Output a line number in a given radix. + */ + static int +iprint_linenum(num) + LINENUM num; +{ + char buf[INT_STRLEN_BOUND(num)]; + + linenumtoa(num, buf); + putstr(buf); + return (strlen(buf)); +} + +/* + * This function implements printf-like functionality + * using a more portable argument list mechanism than printf's. + */ + static int +less_printf(fmt, parg) + register char *fmt; + PARG *parg; +{ + register char *s; + register int col; + + col = 0; + while (*fmt != '\0') + { + if (*fmt != '%') + { + putchr(*fmt++); + col++; + } else + { + ++fmt; + switch (*fmt++) + { + case 's': + s = parg->p_string; + parg++; + while (*s != '\0') + { + putchr(*s++); + col++; + } + break; + case 'd': + col += iprint_int(parg->p_int); + parg++; + break; + case 'n': + col += iprint_linenum(parg->p_linenum); + parg++; + break; + } + } + } + return (col); +} + +/* + * Get a RETURN. + * If some other non-trivial char is pressed, unget it, so it will + * become the next command. + */ + public void +get_return() +{ + int c; + +#if ONLY_RETURN + while ((c = getchr()) != '\n' && c != '\r') + bell(); +#else + c = getchr(); + if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR) + ungetcc(c); +#endif +} + +/* + * Output a message in the lower left corner of the screen + * and wait for carriage return. + */ + public void +error(fmt, parg) + char *fmt; + PARG *parg; +{ + int col = 0; + static char return_to_continue[] = " (press RETURN)"; + + errmsgs++; + + if (any_display && is_tty) + { + if (!oldbot) + squish_check(); + at_exit(); + clear_bot(); + at_enter(AT_STANDOUT); + col += so_s_width; + } + + col += less_printf(fmt, parg); + + if (!(any_display && is_tty)) + { + putchr('\n'); + return; + } + + putstr(return_to_continue); + at_exit(); + col += sizeof(return_to_continue) + so_e_width; + + get_return(); + lower_left(); + clear_eol(); + + if (col >= sc_width) + /* + * Printing the message has probably scrolled the screen. + * {{ Unless the terminal doesn't have auto margins, + * in which case we just hammered on the right margin. }} + */ + screen_trashed = 1; + + flush(); +} + +static char intr_to_abort[] = "... (interrupt to abort)"; + +/* + * Output a message in the lower left corner of the screen + * and don't wait for carriage return. + * Usually used to warn that we are beginning a potentially + * time-consuming operation. + */ + public void +ierror(fmt, parg) + char *fmt; + PARG *parg; +{ + at_exit(); + clear_bot(); + at_enter(AT_STANDOUT); + (void) less_printf(fmt, parg); + putstr(intr_to_abort); + at_exit(); + flush(); + need_clr = 1; +} + +/* + * Output a message in the lower left corner of the screen + * and return a single-character response. + */ + public int +query(fmt, parg) + char *fmt; + PARG *parg; +{ + register int c; + int col = 0; + + if (any_display && is_tty) + clear_bot(); + + (void) less_printf(fmt, parg); + c = getchr(); + + if (!(any_display && is_tty)) + { + putchr('\n'); + return (c); + } + + lower_left(); + if (col >= sc_width) + screen_trashed = 1; + flush(); + + return (c); +}