Annotation of coherent/g/usr/bin/vi/pc.c, revision 1.1

1.1     ! root        1: /* pc.c */
        !             2: 
        !             3: /* Author:
        !             4:  *     Guntram Blohm
        !             5:  *     Buchenstrasse 19
        !             6:  *     7904 Erbach, West Germany
        !             7:  *     Tel. ++49-7305-6997
        !             8:  *     sorry - no regular network connection
        !             9:  */
        !            10: 
        !            11: /* This file implements the ibm pc bios interface. See IBM documentation
        !            12:  * for details.
        !            13:  * If TERM is set upon invocation of elvis, this code is ignored completely,
        !            14:  * and the standard termcap functions are used, thus, even not-so-close
        !            15:  * compatibles can run elvis. For close compatibles however, bios output
        !            16:  * is much faster (and permits reverse scrolling, adding and deleting lines,
        !            17:  * and much more ansi.sys isn't capable of). GB.
        !            18:  */
        !            19: 
        !            20: /* The routines for setting raw mode were written by Dan Kegel.  They were
        !            21:  * taken [with slight modifications] from the "raw.c" file that he distributes
        !            22:  * with his NANSI.SYS console driver.  Email: [email protected]
        !            23:  */
        !            24: 
        !            25: #include "config.h"
        !            26: #include "vi.h"
        !            27: 
        !            28: #if MSDOS
        !            29: 
        !            30: #include <dos.h>
        !            31: 
        !            32: static void video();
        !            33: 
        !            34: /* vmode contains the screen attribute index and is set by attrset.*/
        !            35: 
        !            36: int vmode;
        !            37: 
        !            38: /* The following array contains attribute definitions for
        !            39:  * color/monochrome attributes. Screen selects one of the sets.
        !            40:  * Maybe i'll put them into elvis options one day.
        !            41:  */
        !            42: 
        !            43: static int screen;
        !            44: static char attr[2][8] =
        !            45: {
        !            46:     /* :se:    :so:    :VB:    :ul:    :as:    popup   visible quit    */
        !            47:     {  0x1f,   0x1d,   0x1e,   0x1a,   0x1c,   0x2f,   0x3f,   0x07},  /* color */
        !            48:     {  0x07,   0x70,   0x0f,   0x01,   0x0f,   0x70,   0x70,   0x07},  /* mono */
        !            49: };
        !            50: 
        !            51: /*
        !            52:  * bios interface functions for elvis - pc version
        !            53:  */
        !            54: 
        !            55: int biosquit()
        !            56: {
        !            57:        int     cx = 1;
        !            58: 
        !            59:        vmode = 7;
        !            60:        v_ce();
        !            61: }
        !            62: 
        !            63: 
        !            64: /* This function changes the table of attribute bytes used during BIOS output.
        !            65:  */
        !            66: int bioscolor(mode, attrbyte)
        !            67:        int     mode;   /* e.g. A_NORMAL */
        !            68:        int     attrbyte;/* color code, as a PC attribute byte */
        !            69: {
        !            70:        attr[0][mode] = attrbyte;
        !            71:        return 0;
        !            72: }
        !            73: 
        !            74: /* IOCTL GETBITS/SETBITS bits. */
        !            75: #define DEVICE         0x80
        !            76: #define RAW            0x20
        !            77: 
        !            78: /* IOCTL operations */
        !            79: #define GETBITS                0
        !            80: #define SETBITS                1
        !            81: #define GETINSTATUS    6
        !            82: 
        !            83: /* DOS function numbers. */
        !            84: #define BREAKCHECK     0x33
        !            85: #define IOCTL          0x44
        !            86: 
        !            87: /* A nice way to call the DOS IOCTL function */
        !            88: static int
        !            89: ioctl(int handle, int mode, unsigned setvalue)
        !            90: {
        !            91:        union REGS regs;
        !            92: 
        !            93:        regs.h.ah = IOCTL;
        !            94:        regs.h.al = (char) mode;
        !            95:        regs.x.bx = handle;
        !            96:        regs.h.dl = (char) setvalue;
        !            97:        regs.h.dh = 0;                  /* Zero out dh */
        !            98:        intdos(&regs, &regs);
        !            99:        return (regs.x.dx);
        !           100: }
        !           101: 
        !           102: 
        !           103: /*--------------------------------------------------------------------------
        !           104:  Call this routine to set or clear RAW mode for the device associated with
        !           105:  the given file.
        !           106:  Example: raw_set(1, TRUE);
        !           107: --------------------------------------------------------------------------*/
        !           108: void raw_set(fd, rawstate)
        !           109:        int fd;
        !           110:        int rawstate;
        !           111: {
        !           112:        int bits;
        !           113:        bits = ioctl(fd, GETBITS, 0);
        !           114:        if (DEVICE & bits) {
        !           115:                if (rawstate)
        !           116:                        bits |= RAW;
        !           117:                else
        !           118:                        bits &= ~RAW;
        !           119:                (void) ioctl(fd, SETBITS, bits);
        !           120:        }
        !           121: }
        !           122: 
        !           123: /* A nice way to call the DOS BREAKCHECK function */
        !           124: static int breakctl(int mode, int setvalue)
        !           125: {
        !           126:        union REGS regs;
        !           127: 
        !           128:        regs.h.ah = BREAKCHECK;
        !           129:        regs.h.al = (char) mode;
        !           130:        regs.h.dl = (char) setvalue;
        !           131:        intdos(&regs, &regs);
        !           132:        return (regs.x.dx & 0xff);
        !           133: }
        !           134: 
        !           135: /*--------------------------------------------------------------------------
        !           136:  Call this routine to determine whether DOS is checking for break (Control-C)
        !           137:  before it executes any DOS function call.
        !           138:  Return value is FALSE if it only checks before console I/O function calls,
        !           139:  TRUE if it checks before any function call.
        !           140: --------------------------------------------------------------------------*/
        !           141: int break_get(void)
        !           142: {
        !           143:        return ( 0 != breakctl(GETBITS, 0));
        !           144: }
        !           145: 
        !           146: /*--------------------------------------------------------------------------
        !           147:  Call this routine with TRUE to tell DOS to check for break (Control-C)
        !           148:  before it executes any DOS function call.
        !           149:  Call this routine with FALSE to tell DOS to only check for break before
        !           150:  it executes console I/O function calls.
        !           151: --------------------------------------------------------------------------*/
        !           152: void break_set(check)
        !           153:        int check;
        !           154: {
        !           155:        (void) breakctl(SETBITS, check);
        !           156: }
        !           157: 
        !           158: /*--------------------------------------------------------------------------
        !           159:  One routine to set (or clear) raw mode on stdin and stdout,
        !           160:  clear (or restore) break checking, and turn off input buffering on stdin.
        !           161:  This is the most common configuration; under MS-DOS, since setting raw mode
        !           162:  on stdout sometimes sets it on stdin, it's best to set it on both & be done
        !           163:  with it.
        !           164: --------------------------------------------------------------------------*/
        !           165: void raw_set_stdio(rawstate)
        !           166:        int rawstate;   /* TRUE -> set raw mode; FALSE -> clear raw mode */
        !           167: {
        !           168:        static int was_break_checking = 0;
        !           169: 
        !           170:        raw_set(0, rawstate);
        !           171:        raw_set(1, rawstate);
        !           172:        if (rawstate) {
        !           173:                was_break_checking = break_get();
        !           174:                break_set(0);
        !           175:        } else {
        !           176:                break_set(was_break_checking);
        !           177:        }
        !           178: }
        !           179: 
        !           180: 
        !           181: 
        !           182: 
        !           183: 
        !           184: 
        !           185: /* cursor up: determine current position, decrement row, set position */
        !           186: 
        !           187: void v_up()
        !           188: {
        !           189:        int dx;
        !           190:        video(0x300,(int *)0,&dx);
        !           191:        dx-=0x100;
        !           192:        video(0x200,(int *)0,&dx);
        !           193: }
        !           194: 
        !           195: #ifndef NO_CURSORSHAPE
        !           196: /* cursor big: set begin scan to end scan - 4 */
        !           197: void v_cb()
        !           198: {
        !           199:        int cx;
        !           200:        video(0x300, &cx, (int *)0);
        !           201:        cx=((cx&0xff)|(((cx&0xff)-4)<<8));
        !           202:        video(0x100, &cx, (int *)0);
        !           203: }
        !           204: 
        !           205: /* cursor small: set begin scan to end scan - 1 */
        !           206: void v_cs()
        !           207: {
        !           208:        int cx;
        !           209:        video(0x300, &cx, (int *)0);
        !           210:        cx=((cx&0xff)|(((cx&0xff)-1)<<8));
        !           211:        video(0x100, &cx, (int *)0);
        !           212: }
        !           213: #endif
        !           214: 
        !           215: /* clear to end: get cursor position and emit the aproppriate number
        !           216:  * of spaces, without moving cursor.
        !           217:  */
        !           218:  
        !           219: void v_ce()
        !           220: {
        !           221:        int cx, dx;
        !           222:        video(0x300,(int *)0,&dx);
        !           223:        cx=COLS-(dx&0xff);
        !           224:        video(0x920,&cx,(int *)0);
        !           225: }
        !           226: 
        !           227: /* clear screen: clear all and set cursor home */
        !           228: 
        !           229: void v_cl()
        !           230: {
        !           231:        int cx=0, dx=((LINES-1)<<8)+COLS-1;
        !           232:        video(0x0600,&cx,&dx);
        !           233:        dx=0;
        !           234:        video(0x0200,&cx,&dx);
        !           235: }
        !           236: 
        !           237: /* clear to bottom: get position, clear to eol, clear next line to end */
        !           238: 
        !           239: void v_cd()
        !           240: {
        !           241:        int cx, dx, dxtmp;
        !           242:        video(0x0300,(int *)0,&dx);
        !           243:        dxtmp=(dx&0xff00)|(COLS-1);
        !           244:        cx=dx;
        !           245:        video(0x0600,&cx,&dxtmp);
        !           246:        cx=(dx&0xff00)+0x100;
        !           247:        dx=((LINES-1)<<8)+COLS-1;
        !           248:        video(0x600,&cx,&dx);
        !           249: }
        !           250: 
        !           251: /* add line: scroll rest of screen down */
        !           252: 
        !           253: void v_al()
        !           254: {
        !           255:        int cx,dx;
        !           256:        video(0x0300,(int *)0,&dx);
        !           257:        cx=(dx&0xff00);
        !           258:        dx=((LINES-1)<<8)+COLS-1;
        !           259:        video(0x701,&cx,&dx);
        !           260: }
        !           261: 
        !           262: /* delete line: scroll rest up */
        !           263: 
        !           264: void v_dl()
        !           265: {
        !           266:        int cx,dx;
        !           267:        video(0x0300,(int *)0,&dx);
        !           268:        cx=(dx&0xff00)/*+0x100*/;
        !           269:        dx=((LINES-1)<<8)+COLS-1;
        !           270:        video(0x601,&cx,&dx);
        !           271: }
        !           272: 
        !           273: /* scroll reverse: scroll whole screen */
        !           274: 
        !           275: void v_sr()
        !           276: {
        !           277:        int cx=0, dx=((LINES-1)<<8)+COLS-1;
        !           278:        video(0x0701,&cx,&dx);
        !           279: }
        !           280: 
        !           281: /* set cursor */
        !           282: 
        !           283: void v_move(x,y)
        !           284:        int x, y;
        !           285: {
        !           286:        int dx=(y<<8)+x;
        !           287:        video(0x200,(int *)0,&dx);
        !           288: }
        !           289: 
        !           290: /* put character: set attribute first, then execute char.
        !           291:  * Also remember if current line has changed.
        !           292:  */
        !           293: 
        !           294: int v_put(ch)
        !           295:        int ch;
        !           296: {
        !           297:        int cx=1;
        !           298:        ch&=0xff;
        !           299:        if (ch>=' ')
        !           300:                video(0x900|ch,&cx,(int *)0);
        !           301:        video(0xe00|ch,(int *)0, (int *)0);
        !           302:        if (ch=='\n')
        !           303:        {       exwrote = TRUE;
        !           304:                video(0xe0d, (int *)0, (int *)0);
        !           305:        }
        !           306:        return ch;
        !           307: }
        !           308: 
        !           309: /* determine number of screen columns. Also set attrset according
        !           310:  * to monochrome/color screen.
        !           311:  */
        !           312: 
        !           313: int v_cols()
        !           314: {
        !           315:        union REGS regs;
        !           316:        regs.h.ah=0x0f;
        !           317:        int86(0x10, &regs, &regs);
        !           318:        if (regs.h.al==7)                       /* monochrome mode ? */
        !           319:                screen=1;
        !           320:        else
        !           321:                screen=0;
        !           322:        return regs.h.ah;
        !           323: }
        !           324: 
        !           325: /* Getting the number of rows is hard. Most screens support 25 only,
        !           326:  * EGA/VGA also support 43/50 lines, and some OEM's even more.
        !           327:  * Unfortunately, there is no standard bios variable for the number
        !           328:  * of lines, and the bios screen memory size is always rounded up
        !           329:  * to 0x1000. So, we'll really have to cheat.
        !           330:  * When using the screen memory size, keep in mind that each character
        !           331:  * byte has an associated attribute byte.
        !           332:  *
        !           333:  * uses:       word at 40:4c contains  memory size
        !           334:  *             byte at 40:84           # of rows-1 (sometimes)
        !           335:  *             byte at 40:4a           # of columns
        !           336:  */
        !           337: 
        !           338: int v_rows()
        !           339: {
        !           340:        int line, oldline;
        !           341: 
        !           342:        /* screen size less then 4K? then we have 25 lines only */
        !           343: 
        !           344:        if (*(int far *)(0x0040004cl)<=4096)
        !           345:                return 25;
        !           346: 
        !           347:        /* VEGA vga uses the bios byte at 0x40:0x84 for # of rows.
        !           348:         * Use that byte, if it makes sense together with memory size.
        !           349:         */
        !           350: 
        !           351:        if ((((*(unsigned char far *)(0x0040004aL)*2*
        !           352:                (*(unsigned char far *)(0x00400084L)+1))+0xfff)&(~0xfff))==
        !           353:                *(unsigned int far *)(0x0040004cL))
        !           354:                        return *(unsigned char far *)(0x00400084L)+1;
        !           355: 
        !           356:        /* uh oh. Emit '\n's until screen starts scrolling. */
        !           357: 
        !           358:        v_move(oldline=0, 0);
        !           359:        for (;;)
        !           360:        {
        !           361:                video(0xe0a,(int *)0,(int *)0);
        !           362:                video(0x300,(int *)0,&line);
        !           363:                line>>=8;
        !           364:                if (oldline==line)
        !           365:                        return line+1;
        !           366:                oldline=line;   
        !           367:        }
        !           368: }
        !           369: 
        !           370: /* the REAL bios interface -- used internally only. */
        !           371: 
        !           372: static void video(ax, cx, dx)
        !           373:        int ax, *cx, *dx;
        !           374: {
        !           375:        union REGS regs;
        !           376: 
        !           377:        regs.x.ax=ax;
        !           378:        if ((ax&0xff00)==0x600 || (ax&0xff00)==0x700)
        !           379:                regs.h.bh=attr[screen][vmode];
        !           380:        else
        !           381:        {
        !           382:                regs.h.bh=0;
        !           383:                regs.h.bl=attr[screen][vmode];
        !           384:        }
        !           385:        if (cx) regs.x.cx=*cx;
        !           386:        if (dx) regs.x.dx=*dx;
        !           387:        int86(0x10, &regs, &regs);
        !           388:        if (dx) *dx=regs.x.dx;
        !           389:        if (cx) *cx=regs.x.cx;
        !           390: }
        !           391: 
        !           392: /* The following function determines which character is used for
        !           393:  * commandline-options by command.com. This system call is undocumented
        !           394:  * and valid for versions < 4.00 only.
        !           395:  */
        !           396:  
        !           397: int switchar()
        !           398: {
        !           399:        union REGS regs;
        !           400:        regs.x.ax=0x3700;
        !           401:        int86(0x21, &regs, &regs);
        !           402:        return regs.h.dl;
        !           403: }
        !           404: 
        !           405: 
        !           406: /* this function returns the DOS time, as a 32-bit long int representing
        !           407:  * hundredths of a second since midnight.  Some systems may be limited to
        !           408:  * a resolution of whole seconds, but the values will still represent
        !           409:  * hundredths.
        !           410:  */
        !           411: static long dostime()
        !           412: {
        !           413:        union REGS      regs;
        !           414: 
        !           415:        regs.h.ah = 0x2c;       /* MS-DOS "get time" service */
        !           416:        intdos(&regs, &regs);
        !           417:        return (((regs.h.ch * 60L) + regs.h.cl) * 60L + regs.h.dh) * 100L + regs.h.dl;
        !           418: }
        !           419: 
        !           420: 
        !           421: /*ARGSUSED*/
        !           422: /* This function implements a raw read from the keyboard, with timeout. */
        !           423: int ttyread(buf, len, time)
        !           424:        char    *buf;   /* where to store the keystrokes */
        !           425:        int     len;    /* maximum number of characters to get -- ignored */
        !           426:        int     time;   /* maximum time to wait, in 1/9th second increments */
        !           427: {
        !           428:        long    stop;
        !           429: 
        !           430:        /* are we going to timeout? */
        !           431:        if (time != 0)
        !           432:        {
        !           433:                /* compute the time when we'll give up */
        !           434:                stop = dostime() + time * 10L;
        !           435: 
        !           436:                /* wait for either keystroke or timeout */
        !           437:                while (!kbhit())
        !           438:                {
        !           439:                        if (dostime() > stop)
        !           440:                        {
        !           441:                                /* we couldn't read any characters
        !           442:                                 * before timeout
        !           443:                                 */
        !           444:                                return 0;
        !           445:                        }
        !           446:                }
        !           447:        }
        !           448: 
        !           449:        /* get a keystroke */
        !           450:        buf[0] = getch();
        !           451:        if (buf[0] == 0) /* function key? */
        !           452:        {
        !           453:                buf[0] = '#';
        !           454:                buf[1] = getch();
        !           455:                return 2;
        !           456:        }
        !           457:        else
        !           458:        {
        !           459:                return 1;
        !           460:        }
        !           461: }
        !           462: 
        !           463: #if !TURBOC 
        !           464: /* Turboc provides sleep, declared as void sleep(unsigned seconds) */
        !           465: int sleep(seconds)
        !           466:        unsigned seconds;
        !           467: {
        !           468:        long    stop;
        !           469: 
        !           470:        stop = dostime() + 100L * seconds;
        !           471:        while (dostime() < stop)
        !           472:        {
        !           473:        }
        !           474:        return 0;
        !           475: }
        !           476: #endif
        !           477: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.