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

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