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

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