[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.3

1.3     ! niklas      1: /*     $OpenBSD$       */
        !             2:
1.1       etheisen    3: /*
                      4:  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice in the documentation and/or other materials provided with
                     14:  *    the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
                     17:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
                     20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
                     22:  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
                     23:  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     24:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
                     25:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
                     26:  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29:
                     30: /*
                     31:  * High level routines dealing with the output to the screen.
                     32:  */
                     33:
                     34: #include "less.h"
                     35:
                     36: public int errmsgs;    /* Count of messages displayed by error() */
                     37: public int need_clr;
                     38:
                     39: extern int sigs;
                     40: extern int sc_width;
                     41: extern int so_s_width, so_e_width;
                     42: extern int screen_trashed;
                     43: extern int any_display;
                     44:
                     45: /*
                     46:  * Display the line which is in the line buffer.
                     47:  */
                     48:        public void
                     49: put_line()
                     50: {
                     51:        register int c;
                     52:        register int i;
                     53:        int a;
                     54:        int curr_attr;
                     55:
                     56:        if (ABORT_SIGS())
                     57:        {
                     58:                /*
                     59:                 * Don't output if a signal is pending.
                     60:                 */
                     61:                screen_trashed = 1;
                     62:                return;
                     63:        }
                     64:
                     65:        curr_attr = AT_NORMAL;
                     66:
                     67:        for (i = 0;  (c = gline(i, &a)) != '\0';  i++)
                     68:        {
                     69:                if (a != curr_attr)
                     70:                {
                     71:                        /*
                     72:                         * Changing attributes.
                     73:                         * Display the exit sequence for the old attribute
                     74:                         * and the enter sequence for the new one.
                     75:                         */
                     76:                        switch (curr_attr)
                     77:                        {
                     78:                        case AT_UNDERLINE:      ul_exit();      break;
                     79:                        case AT_BOLD:           bo_exit();      break;
                     80:                        case AT_BLINK:          bl_exit();      break;
                     81:                        case AT_STANDOUT:       so_exit();      break;
                     82:                        }
                     83:                        switch (a)
                     84:                        {
                     85:                        case AT_UNDERLINE:      ul_enter();     break;
                     86:                        case AT_BOLD:           bo_enter();     break;
                     87:                        case AT_BLINK:          bl_enter();     break;
                     88:                        case AT_STANDOUT:       so_enter();     break;
                     89:                        }
                     90:                        curr_attr = a;
                     91:                }
                     92:                if (curr_attr == AT_INVIS)
                     93:                        continue;
                     94:                if (c == '\b')
                     95:                        putbs();
                     96:                else
                     97:                        putchr(c);
                     98:        }
                     99:
                    100:        switch (curr_attr)
                    101:        {
                    102:        case AT_UNDERLINE:      ul_exit();      break;
                    103:        case AT_BOLD:           bo_exit();      break;
                    104:        case AT_BLINK:          bl_exit();      break;
                    105:        case AT_STANDOUT:       so_exit();      break;
                    106:        }
                    107: }
                    108:
                    109: static char obuf[1024];
                    110: static char *ob = obuf;
                    111:
                    112: /*
                    113:  * Flush buffered output.
                    114:  *
                    115:  * If we haven't displayed any file data yet,
                    116:  * output messages on error output (file descriptor 2),
                    117:  * otherwise output on standard output (file descriptor 1).
                    118:  *
                    119:  * This has the desirable effect of producing all
                    120:  * error messages on error output if standard output
                    121:  * is directed to a file.  It also does the same if
                    122:  * we never produce any real output; for example, if
                    123:  * the input file(s) cannot be opened.  If we do
                    124:  * eventually produce output, code in edit() makes
                    125:  * sure these messages can be seen before they are
                    126:  * overwritten or scrolled away.
                    127:  */
                    128:        public void
                    129: flush()
                    130: {
                    131:        register int n;
                    132:        register int fd;
                    133:
                    134: #if MSOFTC
                    135:        *ob = '\0';
                    136:        _outtext(obuf);
                    137:        ob = obuf;
                    138: #else
                    139:        n = ob - obuf;
                    140:        if (n == 0)
                    141:                return;
                    142:        fd = (any_display) ? 1 : 2;
                    143:        if (write(fd, obuf, n) != n)
                    144:                screen_trashed = 1;
                    145:        ob = obuf;
                    146: #endif
                    147: }
                    148:
                    149: /*
                    150:  * Output a character.
                    151:  */
                    152:        public int
                    153: putchr(c)
                    154:        int c;
                    155: {
                    156:        if (ob >= &obuf[sizeof(obuf)])
                    157:                flush();
                    158:        if (need_clr)
                    159:        {
                    160:                need_clr = 0;
                    161:                clear_bot();
                    162:        }
                    163: #if MSOFTC
                    164:        if (c == '\n')
                    165:                putchr('\r');
                    166: #endif
                    167:        *ob++ = c;
                    168:        return (c);
                    169: }
                    170:
                    171: /*
                    172:  * Output a string.
                    173:  */
                    174:        public void
                    175: putstr(s)
                    176:        register char *s;
                    177: {
                    178:        while (*s != '\0')
                    179:                putchr(*s++);
                    180: }
                    181:
                    182:
                    183: /*
                    184:  * Output an integer in a given radix.
                    185:  */
                    186:        static int
                    187: iprintnum(num, radix)
                    188:        int num;
                    189:        int radix;
                    190: {
                    191:        register char *s;
                    192:        int r;
                    193:        int neg;
                    194:        char buf[10];
                    195:
                    196:        if (neg = (num < 0))
                    197:                num = -num;
                    198:
                    199:        s = buf;
                    200:        do
                    201:        {
                    202:                *s++ = (num % radix) + '0';
                    203:        } while ((num /= radix) != 0);
                    204:
                    205:        if (neg)
                    206:                *s++ = '-';
                    207:        r = s - buf;
                    208:
                    209:        while (s > buf)
                    210:                putchr(*--s);
                    211:        return (r);
                    212: }
                    213:
                    214: /*
                    215:  * This function implements printf-like functionality
                    216:  * using a more portable argument list mechanism than printf's.
                    217:  */
                    218:        static int
                    219: iprintf(fmt, parg)
                    220:        register char *fmt;
                    221:        PARG *parg;
                    222: {
                    223:        register char *s;
                    224:        register int n;
                    225:        register int col;
                    226:
                    227:        col = 0;
                    228:        while (*fmt != '\0')
                    229:        {
                    230:                if (*fmt != '%')
                    231:                {
                    232:                        putchr(*fmt++);
                    233:                        col++;
                    234:                } else
                    235:                {
                    236:                        ++fmt;
                    237:                        switch (*fmt++) {
                    238:                        case 's':
                    239:                                s = parg->p_string;
                    240:                                parg++;
                    241:                                while (*s != '\0')
                    242:                                {
                    243:                                        putchr(*s++);
                    244:                                        col++;
                    245:                                }
                    246:                                break;
                    247:                        case 'd':
                    248:                                n = parg->p_int;
                    249:                                parg++;
                    250:                                col += iprintnum(n, 10);
                    251:                                break;
                    252:                        }
                    253:                }
                    254:        }
                    255:        return (col);
                    256: }
                    257:
                    258: /*
                    259:  * Output a message in the lower left corner of the screen
                    260:  * and wait for carriage return.
                    261:  */
                    262:        public void
                    263: error(fmt, parg)
                    264:        char *fmt;
                    265:        PARG *parg;
                    266: {
                    267:        int c;
                    268:        int col = 0;
                    269:        static char return_to_continue[] = "  (press RETURN)";
                    270:
                    271:        errmsgs++;
                    272:
                    273:        if (any_display)
                    274:        {
                    275:                clear_bot();
                    276:                so_enter();
                    277:                col += so_s_width;
                    278:        }
                    279:
                    280:        col += iprintf(fmt, parg);
                    281:
                    282:        if (!any_display)
                    283:        {
                    284:                putchr('\n');
                    285:                return;
                    286:        }
                    287:
                    288:        putstr(return_to_continue);
                    289:        so_exit();
                    290:        col += sizeof(return_to_continue) + so_e_width;
                    291:
                    292: #if ONLY_RETURN
                    293:        while ((c = getchr()) != '\n' && c != '\r')
                    294:                bell();
                    295: #else
                    296:        c = getchr();
1.2       etheisen  297:        if (c == 'q')
                    298:                quit(QUIT_OK);
1.1       etheisen  299:        if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
                    300:                ungetcc(c);
                    301: #endif
                    302:        lower_left();
                    303:
                    304:        if (col >= sc_width)
                    305:                /*
                    306:                 * Printing the message has probably scrolled the screen.
                    307:                 * {{ Unless the terminal doesn't have auto margins,
                    308:                 *    in which case we just hammered on the right margin. }}
                    309:                 */
                    310:                screen_trashed = 1;
                    311:
                    312:        flush();
                    313: }
                    314:
                    315: static char intr_to_abort[] = "... (interrupt to abort)";
                    316:
                    317: /*
                    318:  * Output a message in the lower left corner of the screen
                    319:  * and don't wait for carriage return.
                    320:  * Usually used to warn that we are beginning a potentially
                    321:  * time-consuming operation.
                    322:  */
                    323:        public void
                    324: ierror(fmt, parg)
                    325:        char *fmt;
                    326:        PARG *parg;
                    327: {
                    328:        clear_bot();
                    329:        so_enter();
                    330:        (void) iprintf(fmt, parg);
                    331:        putstr(intr_to_abort);
                    332:        so_exit();
                    333:        flush();
                    334:        need_clr = 1;
                    335: }
                    336:
                    337: /*
                    338:  * Output a message in the lower left corner of the screen
                    339:  * and return a single-character response.
                    340:  */
                    341:        public int
                    342: query(fmt, parg)
                    343:        char *fmt;
                    344:        PARG *parg;
                    345: {
                    346:        register int c;
                    347:        int col = 0;
                    348:
                    349:        if (any_display)
                    350:                clear_bot();
                    351:
                    352:        (void) iprintf(fmt, parg);
                    353:        c = getchr();
                    354:
                    355:        if (!any_display)
                    356:        {
                    357:                putchr('\n');
                    358:                return (c);
                    359:        }
                    360:
                    361:        lower_left();
                    362:        if (col >= sc_width)
                    363:                screen_trashed = 1;
                    364:        flush();
                    365:
                    366:        return (c);
                    367: }