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

Annotation of src/usr.bin/less/doscreen.c, Revision 1.2

1.2     ! 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:  * Routines which deal with the characteristics of the terminal.
                     32:  *
                     33:  * This file is specific to MS-DOS and uses Microsoft C graphics functions.
                     34:  */
                     35:
                     36: #include "less.h"
                     37: #include "cmd.h"
                     38:
                     39: #include <graph.h>
                     40: #include <time.h>
                     41:
                     42: static int init_done = 0;
                     43: static int videopages;
                     44: static long msec_loops;
                     45:
                     46: public int auto_wrap;          /* Terminal does \r\n when write past margin */
                     47: public int ignaw;              /* Terminal ignores \n immediately after wrap */
                     48: public int erase_char, kill_char; /* The user's erase and line-kill chars */
                     49: public int sc_width, sc_height;        /* Height & width of screen */
                     50: public int bo_s_width, bo_e_width;     /* Printing width of boldface seq */
                     51: public int ul_s_width, ul_e_width;     /* Printing width of underline seq */
                     52: public int so_s_width, so_e_width;     /* Printing width of standout seq */
                     53: public int bl_s_width, bl_e_width;     /* Printing width of blink seq */
                     54:
                     55: public int nm_fg_color = 7;                    /* Color of normal text */
                     56: public int nm_bg_color = 0;
                     57: public int bo_fg_color = 15;           /* Color of bold text */
                     58: public int bo_bg_color = 0;
                     59: public int ul_fg_color = 9;                    /* Color of underlined text */
                     60: public int ul_bg_color = 0;
                     61: public int so_fg_color = 0;                    /* Color of standout text */
                     62: public int so_bg_color = 7;
                     63: public int bl_fg_color = 12;           /* Color of blinking text */
                     64: public int bl_bg_color = 0;
                     65:
                     66: static int sy_fg_color;
                     67: static int sy_bg_color;
                     68: static int flash_created = 0;
                     69:
                     70: extern int quiet;              /* If VERY_QUIET, use visual bell for bell */
                     71: extern int know_dumb;          /* Don't complain about a dumb terminal */
                     72: extern int back_scroll;
                     73: extern int swindow;
                     74: extern char *getenv();
                     75:
                     76: /*
                     77:  * Change terminal to "raw mode", or restore to "normal" mode.
                     78:  * "Raw mode" means
                     79:  *     1. An outstanding read will complete on receipt of a single keystroke.
                     80:  *     2. Input is not echoed.
                     81:  *     3. On output, \n is mapped to \r\n.
                     82:  *     4. \t is NOT expanded into spaces.
                     83:  *     5. Signal-causing characters such as ctrl-C (interrupt),
                     84:  *        etc. are NOT disabled.
                     85:  * It doesn't matter whether an input \n is mapped to \r, or vice versa.
                     86:  */
                     87:        public void
                     88: raw_mode(on)
                     89:        int on;
                     90: {
                     91:        static int curr_on = 0;
                     92:
                     93:        if (on == curr_on)
                     94:                return;
                     95:        erase_char = CONTROL('h');
                     96:        kill_char = '\33'; /* ESC */
                     97:        curr_on = on;
                     98: }
                     99:
                    100: /*
                    101:  * Get size of the output screen.
                    102:  */
                    103:        public void
                    104: scrsize(p_height, p_width)
                    105:        int *p_height;
                    106:        int *p_width;
                    107: {
                    108:        register char *s;
                    109:        struct videoconfig w;
                    110:
                    111:        _getvideoconfig(&w);
                    112:
                    113:        if (w.numtextrows)
                    114:                *p_height = w.numtextrows;
                    115:        else if ((s = getenv("LINES")) != NULL && *s != '\0')
                    116:                *p_height = atoi(s);
                    117:        if (*p_height <= 0)
                    118:                *p_height = 24;
                    119:
                    120:        if (w.numtextcols > 0)
                    121:                *p_width = w.numtextcols;
                    122:        else if ((s = getenv("COLUMNS")) != NULL)
                    123:                *p_width = atoi(s);
                    124:        if (*p_width <= 0)
                    125:                *p_width = 80;
                    126: }
                    127:
                    128: /*
                    129:  * Figure out how many empty loops it takes to delay a millisecond.
                    130:  */
                    131:        static void
                    132: get_clock()
                    133: {
                    134:        clock_t start;
                    135:
                    136:        /*
                    137:         * Get synchronized at the start of a tick.
                    138:         */
                    139:        start = clock();
                    140:        while (clock() == start)
                    141:                ;
                    142:        /*
                    143:         * Now count loops till the next tick.
                    144:         */
                    145:        start = clock();
                    146:        msec_loops = 0;
                    147:        while (clock() == start)
                    148:                msec_loops++;
                    149:        /*
                    150:         * Convert from (loops per clock) to (loops per millisecond).
                    151:         */
                    152:        msec_loops *= CLOCKS_PER_SEC;
                    153:        msec_loops /= 1000;
                    154: }
                    155:
                    156:        public void
                    157: get_editkeys()
                    158: {
                    159: }
                    160:
                    161: /*
                    162:  * Get terminal capabilities via termcap.
                    163:  */
                    164:        public void
                    165: get_term()
                    166: {
                    167:        scrsize(&sc_height, &sc_width);
                    168:        pos_init();
                    169:        auto_wrap = 1;
                    170:        ignaw = 0;
                    171:        so_e_width = so_s_width = 0;
                    172:        bo_s_width = bo_e_width = 0;
                    173:        ul_s_width = ul_e_width = 0;
                    174:        bl_s_width = bl_e_width = 0;
                    175:        get_clock();
                    176: }
                    177:
                    178:
                    179: /*
                    180:  * Below are the functions which perform all the
                    181:  * terminal-specific screen manipulation.
                    182:  */
                    183:
                    184:
                    185: /*
                    186:  * Initialize terminal
                    187:  */
                    188:        public void
                    189: init()
                    190: {
                    191:        /* {{ What could we take no_init (-X) to mean? }} */
                    192:        sy_bg_color = _getbkcolor();
                    193:        sy_fg_color = _gettextcolor();
                    194:        flush();
                    195:        init_done = 1;
                    196: }
                    197:
                    198: /*
                    199:  * Create an alternate screen which is all white.
                    200:  * This screen is used to create a "flash" effect, by displaying it
                    201:  * briefly and then switching back to the normal screen.
                    202:  * {{ Yuck!  There must be a better way to get a visual bell. }}
                    203:  */
                    204:        static void
                    205: create_flash()
                    206: {
                    207:        struct videoconfig w;
                    208:        char *blanks;
                    209:        int row, col;
                    210:
                    211:        _getvideoconfig(&w);
                    212:        videopages = w.numvideopages;
                    213:        if (videopages < 2)
                    214:        {
                    215:                so_enter();
                    216:                so_exit();
                    217:        } else
                    218:        {
                    219:                _setactivepage(1);
                    220:                so_enter();
                    221:                blanks = (char *) ecalloc(w.numtextcols, sizeof(char));
                    222:                for (col = 0;  col < w.numtextcols;  col++)
                    223:                        blanks[col] = ' ';
                    224:                for (row = w.numtextrows;  row > 0;  row--)
                    225:                        _outmem(blanks, w.numtextcols);
                    226:                _setactivepage(0);
                    227:                _setvisualpage(0);
                    228:                free(blanks);
                    229:                so_exit();
                    230:        }
                    231:        flash_created = 1;
                    232: }
                    233:
                    234: /*
                    235:  * Deinitialize terminal
                    236:  */
                    237:        public void
                    238: deinit()
                    239: {
                    240:        if (!init_done)
                    241:                return;
                    242:        _setbkcolor(sy_bg_color);
                    243:        _settextcolor(sy_fg_color);
                    244:        putstr("\n");
                    245:        init_done = 0;
                    246: }
                    247:
                    248: /*
                    249:  * Home cursor (move to upper left corner of screen).
                    250:  */
                    251:        public void
                    252: home()
                    253: {
                    254:        flush();
                    255:        _settextposition(1,1);
                    256: }
                    257:
                    258: /*
                    259:  * Add a blank line (called with cursor at home).
                    260:  * Should scroll the display down.
                    261:  */
                    262:        public void
                    263: add_line()
                    264: {
                    265:        flush();
                    266:        _scrolltextwindow(_GSCROLLDOWN);
                    267:        _settextposition(1,1);
                    268: }
                    269:
                    270: /*
                    271:  * Move cursor to lower left corner of screen.
                    272:  */
                    273:        public void
                    274: lower_left()
                    275: {
                    276:        flush();
                    277:        _settextposition(sc_height,1);
                    278: }
                    279:
                    280: /*
                    281:  * Delay for a specified number of milliseconds.
                    282:  */
                    283:        static void
                    284: dummy_func()
                    285: {
                    286:        static long delay_dummy = 0;
                    287:        delay_dummy++;
                    288: }
                    289:
                    290:        static void
                    291: delay(msec)
                    292:        int msec;
                    293: {
                    294:        long i;
                    295:
                    296:        while (msec-- > 0)
                    297:        {
                    298:                for (i = 0;  i < msec_loops;  i++)
                    299:                {
                    300:                        /*
                    301:                         * Make it look like we're doing something here,
                    302:                         * so the optimizer doesn't remove the whole loop.
                    303:                         */
                    304:                        dummy_func();
                    305:                }
                    306:        }
                    307: }
                    308:
                    309: /*
                    310:  * Make a noise.
                    311:  */
                    312:        static void
                    313: beep()
                    314: {
                    315:        write(1, "\7", 1);
                    316: }
                    317:
                    318: /*
                    319:  * Output the "visual bell", if there is one.
                    320:  */
                    321:        public void
                    322: vbell()
                    323: {
                    324:        if (!flash_created)
                    325:                /*
                    326:                 * Create a "flash" on the second video page.
                    327:                 */
                    328:                create_flash();
                    329:        if (videopages < 2)
                    330:                /*
                    331:                 * There is no "second video page".
                    332:                 */
                    333:                return;
                    334:        _setvisualpage(1);
                    335:        /*
                    336:         * Leave it displayed for 100 msec.
                    337:         */
                    338:        delay(100);
                    339:        _setvisualpage(0);
                    340: }
                    341:
                    342: /*
                    343:  * Ring the terminal bell.
                    344:  */
                    345:        public void
                    346: bell()
                    347: {
                    348:        if (quiet == VERY_QUIET)
                    349:                vbell();
                    350:        else
                    351:                beep();
                    352: }
                    353:
                    354: /*
                    355:  * Clear the screen.
                    356:  */
                    357:        public void
                    358: clear()
                    359: {
                    360:        flush();
                    361:        _clearscreen(_GCLEARSCREEN);
                    362: }
                    363:
                    364: /*
                    365:  * Clear from the cursor to the end of the cursor's line.
                    366:  * {{ This must not move the cursor. }}
                    367:  */
                    368:        public void
                    369: clear_eol()
                    370: {
                    371:        short top, left;
                    372:        short bot, right;
                    373:        struct rccoord tpos;
                    374:
                    375:        flush();
                    376:        /*
                    377:         * Save current state.
                    378:         */
                    379:        tpos = _gettextposition();
                    380:        _gettextwindow(&top, &left, &bot, &right);
                    381:        /*
                    382:         * Set a temporary window to the current line,
                    383:         * from the cursor's position to the right edge of the screen.
                    384:         * Then clear that window.
                    385:         */
                    386:        _settextwindow(tpos.row, tpos.col, tpos.row, sc_width);
                    387:        _clearscreen(_GWINDOW);
                    388:        /*
                    389:         * Restore state.
                    390:         */
                    391:        _settextwindow(top, left, bot, right);
                    392:        _settextposition(tpos.row, tpos.col);
                    393: }
                    394:
                    395: /*
                    396:  * Clear the bottom line of the display.
                    397:  * Leave the cursor at the beginning of the bottom line.
                    398:  */
                    399:        public void
                    400: clear_bot()
                    401: {
                    402:        lower_left();
                    403:        clear_eol();
                    404: }
                    405:
                    406: /*
                    407:  * Begin "standout" (bold, underline, or whatever).
                    408:  */
                    409:        public void
                    410: so_enter()
                    411: {
                    412:        flush();
                    413:        _setbkcolor(so_bg_color);
                    414:        _settextcolor(so_fg_color);
                    415: }
                    416:
                    417: /*
                    418:  * End "standout".
                    419:  */
                    420:        public void
                    421: so_exit()
                    422: {
                    423:        flush();
                    424:        _setbkcolor(nm_bg_color);
                    425:        _settextcolor(nm_fg_color);
                    426: }
                    427:
                    428: /*
                    429:  * Begin "underline" (hopefully real underlining,
                    430:  * otherwise whatever the terminal provides).
                    431:  */
                    432:        public void
                    433: ul_enter()
                    434: {
                    435:        flush();
                    436:        _setbkcolor(ul_bg_color);
                    437:        _settextcolor(ul_fg_color);
                    438: }
                    439:
                    440: /*
                    441:  * End "underline".
                    442:  */
                    443:        public void
                    444: ul_exit()
                    445: {
                    446:        flush();
                    447:        _setbkcolor(nm_bg_color);
                    448:        _settextcolor(nm_fg_color);
                    449: }
                    450:
                    451: /*
                    452:  * Begin "bold"
                    453:  */
                    454:        public void
                    455: bo_enter()
                    456: {
                    457:        flush();
                    458:        _setbkcolor(bo_bg_color);
                    459:        _settextcolor(bo_fg_color);
                    460: }
                    461:
                    462: /*
                    463:  * End "bold".
                    464:  */
                    465:        public void
                    466: bo_exit()
                    467: {
                    468:        flush();
                    469:        _setbkcolor(nm_bg_color);
                    470:        _settextcolor(nm_fg_color);
                    471: }
                    472:
                    473: /*
                    474:  * Begin "blink"
                    475:  */
                    476:        public void
                    477: bl_enter()
                    478: {
                    479:        flush();
                    480:        _setbkcolor(bl_bg_color);
                    481:        _settextcolor(bl_fg_color);
                    482: }
                    483:
                    484: /*
                    485:  * End "blink".
                    486:  */
                    487:        public void
                    488: bl_exit()
                    489: {
                    490:        flush();
                    491:        _setbkcolor(nm_bg_color);
                    492:        _settextcolor(nm_fg_color);
                    493: }
                    494:
                    495: /*
                    496:  * Erase the character to the left of the cursor
                    497:  * and move the cursor left.
                    498:  */
                    499:        public void
                    500: backspace()
                    501: {
                    502:        struct rccoord tpos;
                    503:
                    504:        /*
                    505:         * Erase the previous character by overstriking with a space.
                    506:         */
                    507:        flush();
                    508:        tpos = _gettextposition();
                    509:        if (tpos.col <= 1)
                    510:                return;
                    511:        _settextposition(tpos.row, tpos.col-1);
                    512:        _outtext(" ");
                    513:        _settextposition(tpos.row, tpos.col-1);
                    514: }
                    515:
                    516: /*
                    517:  * Output a plain backspace, without erasing the previous char.
                    518:  */
                    519:        public void
                    520: putbs()
                    521: {
                    522:        struct rccoord tpos;
                    523:
                    524:        flush();
                    525:        tpos = _gettextposition();
                    526:        if (tpos.col <= 1)
                    527:                return;
                    528:        _settextposition(tpos.row, tpos.col-1);
                    529: }
                    530:
                    531: /*
                    532:  * Table of line editting characters, for editchar() in decode.c.
                    533:  */
                    534: char edittable[] = {
                    535:        '\340','\115',0,        EC_RIGHT,       /* RIGHTARROW */
                    536:        '\340','\113',0,        EC_LEFT,        /* LEFTARROW */
                    537:        '\340','\163',0,        EC_W_LEFT,      /* CTRL-LEFTARROW */
                    538:        '\340','\164',0,        EC_W_RIGHT,     /* CTRL-RIGHTARROW */
                    539:        '\340','\122',0,        EC_INSERT,      /* INSERT */
                    540:        '\340','\123',0,        EC_DELETE,      /* DELETE */
                    541:        '\340','\223',0,        EC_W_DELETE,    /* CTRL-DELETE */
                    542:        '\177',0,               EC_W_BACKSPACE, /* CTRL-BACKSPACE */
                    543:        '\340','\107',0,        EC_HOME,        /* HOME */
                    544:        '\340','\117',0,        EC_END,         /* END */
                    545:        '\340','\110',0,        EC_UP,          /* UPARROW */
                    546:        '\340','\120',0,        EC_DOWN,        /* DOWNARROW */
                    547:        '\t',0,                 EC_F_COMPLETE,  /* TAB */
                    548:        '\17',0,                EC_B_COMPLETE,  /* BACKTAB (?) */
                    549:        '\340','\17',0,         EC_B_COMPLETE,  /* BACKTAB */
                    550:        '\14',0,                EC_EXPAND,      /* CTRL-L */
                    551:        0  /* Extra byte to terminate; subtracted from size, below */
                    552: };
                    553:
                    554: int sz_edittable = sizeof(edittable) -1;
                    555:
                    556:
                    557: char kcmdtable[] =
                    558: {
                    559:        /*
                    560:         * PC function keys.
                    561:         * Note that '\0' is converted to '\340' on input.
                    562:         */
                    563:        '\340','\120',0,                A_F_LINE,               /* down arrow */
                    564:        '\340','\121',0,                A_F_SCREEN,             /* page down */
                    565:        '\340','\110',0,                A_B_LINE,               /* up arrow */
                    566:        '\340','\111',0,                A_B_SCREEN,             /* page up */
                    567:        '\340','\107',0,                A_GOLINE,               /* home */
                    568:        '\340','\117',0,                A_GOEND,                /* end */
                    569:        '\340','\073',0,                A_HELP,                 /* F1 */
                    570:        '\340','\022',0,                A_EXAMINE,              /* Alt-E */
                    571:        0
                    572: };
                    573: int sz_kcmdtable = sizeof(kcmdtable) - 1;