[BACK]Return to output.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/output.c, Revision 1.18

1.1       etheisen    1: /*
1.9       shadchin    2:  * Copyright (C) 1984-2012  Mark Nudelman
1.12      nicm        3:  * Modified for use with illumos by Garrett D'Amore.
                      4:  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
1.1       etheisen    5:  *
1.5       millert     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.
1.1       etheisen    8:  *
1.9       shadchin    9:  * For more information, see the README file.
1.10      nicm       10:  */
1.1       etheisen   11:
                     12: /*
                     13:  * High level routines dealing with the output to the screen.
                     14:  */
                     15:
                     16: #include "less.h"
1.10      nicm       17:
                     18: int errmsgs;   /* Count of messages displayed by error() */
1.1       etheisen   19:
                     20: extern int sc_width;
                     21: extern int so_s_width, so_e_width;
                     22: extern int screen_trashed;
                     23: extern int any_display;
1.5       millert    24: extern int is_tty;
1.6       shadchin   25: extern int oldbot;
1.5       millert    26:
1.10      nicm       27: static int need_clr;
1.1       etheisen   28:
                     29: /*
                     30:  * Display the line which is in the line buffer.
                     31:  */
1.10      nicm       32: void
                     33: put_line(void)
1.1       etheisen   34: {
1.10      nicm       35:        int c;
                     36:        int i;
1.1       etheisen   37:        int a;
                     38:
1.18    ! deraadt    39:        if (abort_sigs()) {
1.1       etheisen   40:                /*
                     41:                 * Don't output if a signal is pending.
                     42:                 */
                     43:                screen_trashed = 1;
                     44:                return;
                     45:        }
                     46:
1.17      deraadt    47:        for (i = 0; (c = gline(i, &a)) != '\0'; i++) {
1.6       shadchin   48:                at_switch(a);
1.1       etheisen   49:                if (c == '\b')
                     50:                        putbs();
                     51:                else
1.10      nicm       52:                        (void) putchr(c);
1.1       etheisen   53:        }
                     54:
1.6       shadchin   55:        at_exit();
1.1       etheisen   56: }
                     57:
1.5       millert    58: static char obuf[OUTBUF_SIZE];
1.1       etheisen   59: static char *ob = obuf;
                     60:
                     61: /*
                     62:  * Flush buffered output.
                     63:  *
                     64:  * If we haven't displayed any file data yet,
                     65:  * output messages on error output (file descriptor 2),
                     66:  * otherwise output on standard output (file descriptor 1).
                     67:  *
                     68:  * This has the desirable effect of producing all
                     69:  * error messages on error output if standard output
                     70:  * is directed to a file.  It also does the same if
                     71:  * we never produce any real output; for example, if
                     72:  * the input file(s) cannot be opened.  If we do
                     73:  * eventually produce output, code in edit() makes
                     74:  * sure these messages can be seen before they are
                     75:  * overwritten or scrolled away.
                     76:  */
1.10      nicm       77: void
1.13      nicm       78: flush(int ignore_errors)
1.1       etheisen   79: {
1.10      nicm       80:        int n;
                     81:        int fd;
1.8       millert    82:        ssize_t nwritten;
1.1       etheisen   83:
1.10      nicm       84:        n = (intptr_t)ob - (intptr_t)obuf;
1.1       etheisen   85:        if (n == 0)
                     86:                return;
1.5       millert    87:
1.6       shadchin   88:        fd = (any_display) ? STDOUT_FILENO : STDERR_FILENO;
1.8       millert    89:        nwritten = write(fd, obuf, n);
                     90:        if (nwritten != n) {
1.13      nicm       91:                if (nwritten == -1 && !ignore_errors)
1.8       millert    92:                        quit(QUIT_ERROR);
1.1       etheisen   93:                screen_trashed = 1;
1.8       millert    94:        }
1.1       etheisen   95:        ob = obuf;
                     96: }
                     97:
                     98: /*
                     99:  * Output a character.
                    100:  */
1.10      nicm      101: int
                    102: putchr(int c)
1.1       etheisen  103: {
1.10      nicm      104:        if (need_clr) {
1.1       etheisen  105:                need_clr = 0;
                    106:                clear_bot();
                    107:        }
1.5       millert   108:        /*
                    109:         * Some versions of flush() write to *ob, so we must flush
                    110:         * when we are still one char from the end of obuf.
                    111:         */
1.10      nicm      112:        if (ob >= &obuf[sizeof (obuf)-1])
1.13      nicm      113:                flush(0);
1.10      nicm      114:        *ob++ = (char)c;
1.1       etheisen  115:        return (c);
                    116: }
                    117:
                    118: /*
                    119:  * Output a string.
                    120:  */
1.10      nicm      121: void
                    122: putstr(const char *s)
1.1       etheisen  123: {
                    124:        while (*s != '\0')
1.10      nicm      125:                (void) putchr(*s++);
1.1       etheisen  126: }
                    127:
                    128:
                    129: /*
1.5       millert   130:  * Convert an integral type to a string.
                    131:  */
1.10      nicm      132: #define        TYPE_TO_A_FUNC(funcname, type)          \
                    133: void                                           \
                    134: funcname(type num, char *buf, size_t len)      \
                    135: {                                              \
                    136:        int neg = (num < 0);                    \
1.16      mmcc      137:        char tbuf[23];  \
1.10      nicm      138:        char *s = tbuf + sizeof (tbuf);         \
                    139:        if (neg)                                \
                    140:                num = -num;                     \
                    141:        *--s = '\0';                            \
                    142:        do {                                    \
                    143:                *--s = (num % 10) + '0';        \
                    144:        } while ((num /= 10) != 0);             \
                    145:        if (neg)                                \
                    146:                 *--s = '-';                    \
                    147:        (void) strlcpy(buf, s, len);            \
1.5       millert   148: }
                    149:
1.10      nicm      150: TYPE_TO_A_FUNC(postoa, off_t)
1.5       millert   151: TYPE_TO_A_FUNC(inttoa, int)
                    152:
                    153: /*
1.1       etheisen  154:  * Output an integer in a given radix.
                    155:  */
1.10      nicm      156: static int
                    157: iprint_int(int num)
1.1       etheisen  158: {
1.16      mmcc      159:        char buf[11];
1.1       etheisen  160:
1.10      nicm      161:        inttoa(num, buf, sizeof (buf));
1.5       millert   162:        putstr(buf);
                    163:        return (strlen(buf));
                    164: }
1.1       etheisen  165:
1.5       millert   166: /*
                    167:  * Output a line number in a given radix.
                    168:  */
1.10      nicm      169: static int
1.14      mmcc      170: iprint_linenum(off_t num)
1.5       millert   171: {
1.16      mmcc      172:        char buf[21];
1.1       etheisen  173:
1.15      mmcc      174:        postoa(num, buf, sizeof(buf));
1.5       millert   175:        putstr(buf);
                    176:        return (strlen(buf));
1.1       etheisen  177: }
                    178:
                    179: /*
                    180:  * This function implements printf-like functionality
                    181:  * using a more portable argument list mechanism than printf's.
                    182:  */
1.10      nicm      183: static int
                    184: less_printf(const char *fmt, PARG *parg)
1.1       etheisen  185: {
1.11      tedu      186:        char *s;
                    187:        int col;
1.1       etheisen  188:
                    189:        col = 0;
1.10      nicm      190:        while (*fmt != '\0') {
                    191:                if (*fmt != '%') {
                    192:                        (void) putchr(*fmt++);
1.1       etheisen  193:                        col++;
1.10      nicm      194:                } else {
1.1       etheisen  195:                        ++fmt;
1.10      nicm      196:                        switch (*fmt++) {
1.1       etheisen  197:                        case 's':
                    198:                                s = parg->p_string;
                    199:                                parg++;
1.10      nicm      200:                                while (*s != '\0') {
                    201:                                        (void) putchr(*s++);
1.1       etheisen  202:                                        col++;
                    203:                                }
                    204:                                break;
                    205:                        case 'd':
1.5       millert   206:                                col += iprint_int(parg->p_int);
                    207:                                parg++;
                    208:                                break;
                    209:                        case 'n':
                    210:                                col += iprint_linenum(parg->p_linenum);
1.1       etheisen  211:                                parg++;
                    212:                                break;
                    213:                        }
                    214:                }
                    215:        }
                    216:        return (col);
                    217: }
                    218:
                    219: /*
1.5       millert   220:  * Get a RETURN.
                    221:  * If some other non-trivial char is pressed, unget it, so it will
                    222:  * become the next command.
                    223:  */
1.10      nicm      224: void
                    225: get_return(void)
1.5       millert   226: {
                    227:        int c;
                    228:
                    229:        c = getchr();
                    230:        if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
                    231:                ungetcc(c);
                    232: }
                    233:
                    234: /*
1.1       etheisen  235:  * Output a message in the lower left corner of the screen
                    236:  * and wait for carriage return.
                    237:  */
1.10      nicm      238: void
                    239: error(const char *fmt, PARG *parg)
1.1       etheisen  240: {
                    241:        int col = 0;
                    242:        static char return_to_continue[] = "  (press RETURN)";
                    243:
                    244:        errmsgs++;
                    245:
1.10      nicm      246:        if (any_display && is_tty) {
1.6       shadchin  247:                if (!oldbot)
                    248:                        squish_check();
                    249:                at_exit();
1.1       etheisen  250:                clear_bot();
1.6       shadchin  251:                at_enter(AT_STANDOUT);
1.1       etheisen  252:                col += so_s_width;
                    253:        }
                    254:
1.5       millert   255:        col += less_printf(fmt, parg);
1.1       etheisen  256:
1.10      nicm      257:        if (!(any_display && is_tty)) {
                    258:                (void) putchr('\n');
1.1       etheisen  259:                return;
                    260:        }
                    261:
                    262:        putstr(return_to_continue);
1.6       shadchin  263:        at_exit();
1.10      nicm      264:        col += sizeof (return_to_continue) + so_e_width;
1.1       etheisen  265:
1.5       millert   266:        get_return();
1.1       etheisen  267:        lower_left();
1.10      nicm      268:        clear_eol();
1.1       etheisen  269:
                    270:        if (col >= sc_width)
                    271:                /*
                    272:                 * Printing the message has probably scrolled the screen.
                    273:                 * {{ Unless the terminal doesn't have auto margins,
                    274:                 *    in which case we just hammered on the right margin. }}
                    275:                 */
                    276:                screen_trashed = 1;
                    277:
1.13      nicm      278:        flush(0);
1.1       etheisen  279: }
                    280:
                    281: static char intr_to_abort[] = "... (interrupt to abort)";
                    282:
                    283: /*
                    284:  * Output a message in the lower left corner of the screen
                    285:  * and don't wait for carriage return.
                    286:  * Usually used to warn that we are beginning a potentially
                    287:  * time-consuming operation.
                    288:  */
1.10      nicm      289: void
                    290: ierror(const char *fmt, PARG *parg)
1.1       etheisen  291: {
1.6       shadchin  292:        at_exit();
1.1       etheisen  293:        clear_bot();
1.6       shadchin  294:        at_enter(AT_STANDOUT);
1.5       millert   295:        (void) less_printf(fmt, parg);
1.1       etheisen  296:        putstr(intr_to_abort);
1.6       shadchin  297:        at_exit();
1.13      nicm      298:        flush(0);
1.1       etheisen  299:        need_clr = 1;
                    300: }
                    301:
                    302: /*
                    303:  * Output a message in the lower left corner of the screen
                    304:  * and return a single-character response.
                    305:  */
1.10      nicm      306: int
                    307: query(const char *fmt, PARG *parg)
1.1       etheisen  308: {
1.11      tedu      309:        int c;
1.1       etheisen  310:        int col = 0;
                    311:
1.5       millert   312:        if (any_display && is_tty)
1.1       etheisen  313:                clear_bot();
                    314:
1.5       millert   315:        (void) less_printf(fmt, parg);
1.1       etheisen  316:        c = getchr();
                    317:
1.10      nicm      318:        if (!(any_display && is_tty)) {
                    319:                (void) putchr('\n');
1.1       etheisen  320:                return (c);
                    321:        }
                    322:
                    323:        lower_left();
                    324:        if (col >= sc_width)
                    325:                screen_trashed = 1;
1.13      nicm      326:        flush(0);
1.1       etheisen  327:
                    328:        return (c);
                    329: }