Annotation of coherent/g/usr/bin/vi/pc.c, revision 1.1.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.