home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / gppconio.c < prev    next >
C/C++ Source or Header  |  1998-04-28  |  19KB  |  774 lines

  1.  
  2. /* This file is properly part of the excellent DJGPP compiler/tools package
  3.     put out by DJ Delorie for use under DOS.  Unfortunately, the module
  4.     as distributed in many versions of the DJGPP is buggy -- this copy
  5.     of gppconio.c fixes many of those bugs.  I understand that these
  6.     changes have been sent back to the DJGPP maintainers -- hopefully
  7.     vile will not need to include this file in the future.  -pgf 9/95
  8. */
  9.  
  10.  
  11. #if __DJGPP__ < 2
  12.  
  13. /**********************************************************************
  14.  *
  15.  *  NAME:           gppconio.c
  16.  *
  17.  *  DESCRIPTION:    simulate Borland text video funcs for GNU C++
  18.  *
  19.  *  copyright (c) 1991 J. Alan Eldridge
  20.  *
  21.  *  M O D I F I C A T I O N   H I S T O R Y
  22.  *
  23.  *  when        who                 what
  24.  *  -------------------------------------------------------------------
  25.  *  10/27/91    J. Alan Eldridge    created
  26.  *  01/06/92    D. Buerssner        make it work with extended characters
  27.  * (buers@dg1.chemie.uni-konstanz.de) speed-up of cputs
  28.  *                                  some missing brackets in VIDADDR
  29.  *                                  don't need scrollwindow anymore
  30.  *  07/15/93    D. Buerssner        take care of cursor tracking
  31.  *                                    txinfo.curx and txinfo.cury
  32.  *                                  fill in missing functionality
  33.  *                                    - textmode
  34.  *                                    - cscanf
  35.  *                                    - cgets
  36.  *                                    - getch and ungetch
  37.  *                                    - _setcursortype
  38.  *                                    - kbhit
  39.  *                                  (hpefully) proper initialization of
  40.  *                                    txinfo.normattrib and txinfo.attribute
  41.  *                                  gotoxy(1,1) in clrscr (bug introduced
  42.  *                                    by my previous patches)
  43.  *                                  gotoxy(1,1) in window
  44.  *                                  take care of BELL and BACKSPACE
  45.  *                                    in putch and cputs
  46.  *                                  take care of blinking bit in textcolor
  47.  *                                    and textbackground
  48.  *                                  declare (and ignore) directvideo
  49.  *  10/09/93    DJ Delorie          Switch to dosmem*() for DPMI
  50.  *  05/01/94    DJ Delorie          Add _wscroll
  51.  *********************************************************************/
  52.  
  53. #include    <stdlib.h>
  54. #include    <stdio.h>
  55. #include    <stdarg.h>
  56. #include    <dos.h>
  57. #include    <pc.h>
  58. #include    <go32.h>
  59. #include    "gppconio.h"
  60.  
  61. int _wscroll = 1;
  62.  
  63. int directvideo = 1;  /* We ignore this */
  64.  
  65. static void setcursor(unsigned int shape);
  66. static int getvideomode(void);
  67. static void bell(void);
  68. static int get_screenattrib(void);
  69. static int isEGA(void);
  70. static int _scan_getche(FILE *fp);
  71. static int _scan_ungetch(int c, FILE *fp);
  72.  
  73. #define DBGGTINFO   0
  74.  
  75. static unsigned ScreenAddress = 0xb8000UL; /* initialize just in case */
  76. static struct text_info txinfo;
  77. static int ungot_char;
  78. static int char_avail = 0;
  79.  
  80. #define VIDADDR(r,c) (ScreenAddress + 2*(((r) * txinfo.screenwidth) + (c)))
  81.  
  82. int puttext(int c, int r, int c2, int r2, void *buf)
  83. {
  84.   short *cbuf = (short *)buf;
  85.   /* we should check for valid parameters, and maybe return 0 */
  86.   r--, r2--, c--, c2--;
  87.   for (; r <= r2; r++)
  88.   {
  89.     dosmemput(cbuf, (c2-c+1)*2, VIDADDR(r, c));
  90.     cbuf += c2-c+1;
  91.   }
  92.   return 1;
  93. }
  94.  
  95. int gettext(int c, int r, int c2, int r2, void *buf)
  96. {
  97.   short *cbuf = (short *)buf;
  98.   /* we should check for valid parameters, and maybe return 0 */
  99.   r--, r2--, c--, c2--;
  100.   for (; r <= r2; r++)
  101.   {
  102.     dosmemget(VIDADDR(r, c), (c2-c+1)*2, cbuf);
  103.     cbuf += c2-c+1;
  104.   }
  105.   return 1;
  106. }
  107.  
  108. void gotoxy(int col, int row)
  109. {
  110.   ScreenSetCursor(row + txinfo.wintop - 2, col + txinfo.winleft - 2);
  111.   txinfo.curx = col;
  112.   txinfo.cury = row;
  113. }
  114.  
  115. int wherex(void)
  116. {
  117.   int row, col;
  118.  
  119.   ScreenGetCursor(&row, &col);
  120.  
  121.   return col - txinfo.winleft + 2;
  122. }
  123.  
  124. int wherey(void)
  125. {
  126.   int row, col;
  127.  
  128.   ScreenGetCursor(&row, &col);
  129.  
  130.   return row - txinfo.wintop + 2;
  131. }
  132.  
  133. void textmode(int mode)
  134. {
  135.     union REGS regs;
  136.     int mode_to_set = mode;
  137.     if (mode == LASTMODE)
  138.         mode = mode_to_set = txinfo.currmode;
  139.     if (mode == C4350)
  140.         /*
  141.          * just set mode 3 and load 8x8 font, idea taken
  142.          * (and code translated from Assembler to C)
  143.          * form Csaba Biegels stdvga.asm
  144.          */
  145.         mode_to_set = 0x03;
  146.     regs.h.ah = 0x00; /* set mode */
  147.     regs.h.al = mode_to_set;
  148.     int86(0x10, ®s, ®s);
  149.     if (mode == C80 || mode == BW80 || mode == C4350)
  150.     {
  151.         if (isEGA())
  152.         {
  153.             /*
  154.              * enable cursor size emulation, see Ralf Browns
  155.              * interrupt list
  156.              */
  157.             regs.h.ah = 0x12;
  158.             regs.h.bl = 0x34;
  159.             regs.h.al = 0x00; /* 0: enable (1: disable) */
  160.             int86(0x10, ®s, ®s);
  161.     }
  162.     }
  163.     if (mode == C4350)
  164.     {
  165.         if (!isEGA())
  166.             return;
  167.         /* load 8x8 font */
  168.         regs.x.ax = 0x1112;
  169.         regs.x.bx = 0;
  170.         int86(0x10, ®s, ®s);
  171.     }
  172. /*    _setcursortype(_NORMALCURSOR); */
  173.     /* reinitialize txinfo structure to take into account new mode */
  174.     gppconio_init();
  175. #if 0
  176.     /*
  177.      * For mode C4350 the screen is not cleared on my OAK-VGA.
  178.      * Should we clear it here? TURBOC doesn't so we don't bother either.
  179.      */
  180.     clrscr();
  181. #endif
  182. }
  183.  
  184. void textattr(int attr)
  185. {
  186.   txinfo.attribute = ScreenAttrib = (unsigned char)attr;
  187. }
  188.  
  189. void textcolor(int color)
  190. {
  191.   /* strip blinking (highest) bit and textcolor */
  192.   ScreenAttrib &= 0x70; /* strip blinking (highest) bit and textcolor */
  193.   txinfo.attribute=(ScreenAttrib |= (color & 0x8f));
  194. }
  195.  
  196. void textbackground(int color)
  197. {
  198.   /* strip background color, keep blinking bit */
  199.   ScreenAttrib &= 0x8f;
  200.   /* high intensity background colors (>7) are not allowed
  201.      so we strip 0x08 bit (and higher bits) of color */
  202.   txinfo.attribute=(ScreenAttrib |= ((color & 0x07) << 4));
  203. }
  204.  
  205. void highvideo(void)
  206. {
  207.   txinfo.attribute=(ScreenAttrib |= 0x08);
  208. }
  209.  
  210. void lowvideo(void)
  211. {
  212.   txinfo.attribute=(ScreenAttrib &= 0x07);
  213. }
  214.  
  215. void normvideo(void)
  216. {
  217.   txinfo.attribute = ScreenAttrib = txinfo.normattr;
  218. }
  219.  
  220. void _setcursortype(int type)
  221. {
  222.     unsigned cursor_shape;
  223.     switch (type)
  224.     {
  225.         case _NOCURSOR:
  226.             cursor_shape = 0x0700;
  227.             break;
  228.         case _SOLIDCURSOR:
  229.             cursor_shape = 0x0007;
  230.             break;
  231. /*      case _NORMALCURSOR: */
  232.         default:
  233.             cursor_shape = 0x0607;
  234.             break;
  235.     }
  236.     setcursor(cursor_shape);
  237. }
  238.  
  239. static void setcursor(unsigned int cursor_shape)
  240. /* Sets the shape of the cursor */
  241. {
  242.     union REGS      reg;
  243.  
  244.     reg.h.ah = 1;
  245.     reg.x.cx = cursor_shape;
  246.     int86(0x10, ®, ®);
  247. }                /* setcursor */
  248.  
  249. static void getwincursor(int *row, int *col)
  250. {
  251.   ScreenGetCursor(row, col);
  252. }
  253.  
  254. void clreol(void)
  255. {
  256.   short   image[ 256 ];
  257.   short   val = ' ' | (ScreenAttrib << 8);
  258.   int     c, row, col, ncols;
  259.  
  260.   getwincursor(&row, &col);
  261.   ncols = txinfo.winright - col;
  262.  
  263.   for (c = 0; c < ncols; c++)
  264.     image[ c ] = val;
  265.  
  266.   puttext(col + 1, row + 1, txinfo.winright, row + 1, image);
  267. }
  268.  
  269. static void fillrow(int row, int left, int right, int fill)
  270. {
  271.   int col;
  272.   short filler[right-left+1];
  273.  
  274.   for (col = left; col <= right; col++)
  275.     filler[col-left] = fill;
  276.   dosmemput(filler, (right-left+1)*2, VIDADDR(row, left));
  277. }
  278.  
  279. void clrscr(void)
  280. {
  281.   short filler[txinfo.winright - txinfo.winleft + 1];
  282.   int row, col;
  283.   for (col=0; col < txinfo.winright - txinfo.winleft + 1; col++)
  284.     filler[col] = ' ' | (ScreenAttrib << 8);
  285.   for (row=txinfo.wintop-1; row < txinfo.winbottom; row++)
  286.     dosmemput(filler, (txinfo.winright - txinfo.winleft + 1)*2,
  287.      VIDADDR(row, txinfo.winleft - 1));
  288.   gotoxy(1, 1);
  289. }
  290.  
  291. int putch(int c)
  292. {
  293.   int     row, col;
  294.  
  295.   ScreenGetCursor(&row, &col);
  296.  
  297.   /*  first, handle the character */
  298.   if (c == '\n')
  299.     {
  300.       row++;
  301.     }
  302.   else if (c == '\r')
  303.     {
  304.       col = txinfo.winleft - 1;
  305.     }
  306.   else if (c == '\b')
  307.   {
  308.       if (col > txinfo.winleft - 1)
  309.           col--;
  310.       else if (row > txinfo.wintop -1)
  311.       {
  312.           /*
  313.            * Turbo-C ignores this case; we are smarter.
  314.            */
  315.           row--;
  316.           col = txinfo.winright-1;
  317.       }
  318.   }
  319.   else if (c == 0x07)
  320.     bell();
  321.   else {
  322.     /* short   val = c | (ScreenAttrib << 8); */
  323.     /* puttext(col + 1, row + 1, col + 1, row + 1, &val); */
  324.     ScreenPutChar(c, ScreenAttrib, col, row);
  325.     col++;
  326.   }
  327.  
  328.   /* now, readjust the window     */
  329.  
  330.   if (col >= txinfo.winright) {
  331.     col = txinfo.winleft - 1;
  332.     row++;
  333.   }
  334.  
  335.   if (row >= txinfo.winbottom) {
  336.     /* scrollwin(0, txinfo.winbottom - txinfo.wintop, 1); */
  337.     if (_wscroll)
  338.     {
  339.       ScreenSetCursor(txinfo.wintop-1,0);
  340.       delline();
  341.     }
  342.     row--;
  343.   }
  344.  
  345.   ScreenSetCursor(row, col);
  346.   txinfo.cury = row - txinfo.wintop + 2;
  347.   txinfo.curx = col - txinfo.winleft + 2;
  348.   return c;
  349. }
  350.  
  351. int getche(void)
  352. {
  353.   if (char_avail)
  354.     /*
  355.      * We don't know, wether the ungot char was already echoed
  356.      * we assume yes (for example in cscanf, probably the only
  357.      * place where ungetch is ever called.
  358.      * There is no way to check for this really, because
  359.      * ungetch could have been called with a character that
  360.      * hasn't been got by a conio function.
  361.      * We don't echo again.
  362.      */
  363.     return(getch());
  364.   return (putch(getch()));
  365. }
  366.  
  367. int getch(void)
  368. {
  369.     union REGS regs;
  370.     int c;
  371.     if (char_avail)
  372.     {
  373.         c = ungot_char;
  374.         char_avail = 0;
  375.     }
  376.     else
  377.     {
  378.         regs.x.ax = 0x0700;
  379.         int86(0x21, ®s, ®s);
  380.         c = regs.h.al;
  381.     }
  382.     return(c);
  383. }
  384.  
  385. int ungetch(int c)
  386. {
  387.     if (char_avail)
  388.         return(EOF);
  389.     ungot_char = c;
  390.     char_avail = 1;
  391.     return(c);
  392. }
  393.  
  394. /*
  395.  * kbhit from libc in libsrc/c/dos/kbhit.s doesn't check
  396.  * for ungotten chars, so we have to provide a new one
  397.  * Don't call it kbhit, rather use a new name (_conio_kbhit)
  398.  * and do a #define kbhit _conio_kbhit in gppconio.h.
  399.  * The old kbhit still can be used if gppconio.h
  400.  * is not included of after #undef kbhit
  401.  * If you don't use ungetch (directly or indirectly by cscanf)
  402.  * both kbhit and _conio_kbhit are the same.
  403.  * So this shouldn't cause any trouble with previously written
  404.  * source, because ungetch wasn't available.
  405.  * The only problem might be, if anybody just included gppconio.h
  406.  * and has not linked with libpc, (I can't think of a good reason
  407.  * for this). This will result a link error (undefined symbol _conio_kbhit).
  408.  */
  409.  
  410. #undef kbhit  /* want to be able to call kbhit from libc */
  411.  
  412. /* The kbhit in libc doesn't work for the second byte of extended chars. */
  413. int kbhit(void)
  414. {
  415.     union REGS regs;
  416.     regs.h.ah = 0x0b;
  417.     int86(0x21, ®s, ®s);
  418.     return regs.h.al ? -1 : 0;
  419. }
  420.  
  421. int _conio_kbhit(void)
  422. {
  423.     if (char_avail)
  424.         return(1);
  425.     else
  426.         return(kbhit());
  427. }
  428.  
  429. /*
  430.  * The next two functions are needed by cscanf
  431.  */
  432. static int _scan_getche(FILE *fp)
  433. {
  434.     return(getche());
  435. }
  436.  
  437. static int _scan_ungetch(int c, FILE *fp)
  438. {
  439.     return(ungetch(c));
  440. }
  441.  
  442.  
  443. void insline(void)
  444. {
  445.   int row, col, left, right, nbytes, bot, fill;
  446.   ScreenGetCursor(&row, &col);
  447.   left = txinfo.winleft - 1;
  448.   right = txinfo.winright - 1;
  449.   nbytes = (right-left+1)*2;
  450.   bot = txinfo.winbottom-1;
  451.   fill = ' ' | (ScreenAttrib << 8);
  452.   while(bot > row)
  453.     {
  454.       movedata(_go32_conventional_mem_selector(), VIDADDR(bot-1, left),
  455.                _go32_conventional_mem_selector(), VIDADDR(bot, left),
  456.                nbytes);
  457.       bot--;
  458.     }
  459.   if (row <= bot)
  460.     {
  461.       fillrow(row,left,right,fill);
  462.     }
  463. }
  464.  
  465.  
  466. void delline(void)
  467. {
  468.   int row, col, left, right, nbytes, bot, fill;
  469.   ScreenGetCursor(&row, &col);
  470.   left = txinfo.winleft - 1;
  471.   right = txinfo.winright - 1;
  472.   nbytes = (right-left+1)*2;
  473.   bot = txinfo.winbottom-1;
  474.   fill = ' ' | (ScreenAttrib << 8);
  475.   while(row < bot)
  476.     {
  477.       movedata(_go32_conventional_mem_selector(), VIDADDR(row+1, left),
  478.                _go32_conventional_mem_selector(), VIDADDR(row, left),
  479.                nbytes);
  480.       row++;
  481.     }
  482.   fillrow(bot,left,right,fill);
  483. }
  484.  
  485.  
  486. void window(int left, int top, int right, int bottom)
  487. {
  488.   if (top < 1 || left < 1 || right > txinfo.screenwidth ||
  489.       bottom > txinfo.screenheight)
  490.     return;
  491.  
  492.   txinfo.wintop = top;
  493.   txinfo.winleft = left;
  494.   txinfo.winright = right;
  495.   txinfo.winbottom = bottom;
  496.   gotoxy(1,1);
  497. }
  498.  
  499.  
  500. int cputs(const char *s)
  501. {
  502.   int     row, col,c;
  503.   const unsigned char *ss = (const unsigned char *)s;
  504.   short *viaddr;
  505.   short sa = ScreenAttrib << 8;
  506.   ScreenGetCursor(&row, &col);
  507.   viaddr = (short *)VIDADDR(row,col);
  508.   /*
  509.    * Instead of just calling putch; we do everything by hand here,
  510.    * This is much faster. We don't move the cursor after each character,
  511.    * only after the whole string is written, because ScreenSetCursor
  512.    * needs to long because of switching to real mode needed with djgpp.
  513.    * You won't recognize the difference.
  514.    */
  515.   while ((c = *ss++))
  516.     {
  517.       /*  first, handle the character */
  518.       if (c == '\n')
  519.     {
  520.       row++;
  521.       viaddr += txinfo.screenwidth;
  522.     }
  523.       else if (c == '\r')
  524.     {
  525.       col = txinfo.winleft - 1;
  526.       viaddr = (short *)VIDADDR(row,col);
  527.     }
  528.       else if (c == '\b')
  529.         {
  530.           if (col > txinfo.winleft-1)
  531.           {
  532.               col--;
  533.               viaddr--;
  534.           }
  535.           else if (row > txinfo.wintop -1)
  536.           {
  537.               /*
  538.                * Turbo-C ignores this case. We want to be able to
  539.                * edit strings with backspace in gets after
  540.                * a linefeed, so we are smarter
  541.                */
  542.               row--;
  543.               col = txinfo.winright-1;
  544.               viaddr = (short *)VIDADDR(row,col);
  545.           }
  546.         }
  547.       else if (c == 0x07)
  548.           bell();
  549.       else {
  550.         short q = c | sa;
  551.         dosmemput(&q, 2, (int)viaddr);
  552.     viaddr++;
  553.     col++;
  554.       }
  555.  
  556.       /* now, readjust the window     */
  557.  
  558.       if (col >= txinfo.winright) {
  559.     col = txinfo.winleft - 1;
  560.     row++;
  561.     viaddr = (short *)VIDADDR(row,col);
  562.       }
  563.  
  564.       if (row >= txinfo.winbottom) {
  565.     ScreenSetCursor(txinfo.wintop-1,0); /* goto first line in window */
  566.     delline();                          /* and delete it */
  567.     row--;
  568.     viaddr -= txinfo.screenwidth;
  569.       }
  570.     }
  571.  
  572.   ScreenSetCursor(row, col);
  573.   txinfo.cury = row - txinfo.wintop + 2;
  574.   txinfo.curx = col - txinfo.winleft + 2;
  575.   return(*(--ss));
  576. }
  577.  
  578.  
  579. int cprintf(const char *fmt, ...)
  580. {
  581.   int     cnt;
  582.   char    buf[ 2048 ]; /* this is buggy, because buffer might be too small. */
  583.   va_list ap;
  584.  
  585.   va_start(ap, fmt);
  586.   cnt = vsprintf(buf, fmt, ap);
  587.   va_end(ap);
  588.  
  589.   cputs(buf);
  590.   return cnt;
  591. }
  592.  
  593. char *cgets(char *string)
  594. {
  595.     unsigned len = 0;
  596.     unsigned int maxlen_wanted;
  597.     char *sp;
  598.     int c;
  599.     /*
  600.      * Be smart and check for NULL pointer.
  601.      * Don't know wether TURBOC does this.
  602.      */
  603.     if (!string)
  604.         return(NULL);
  605.     maxlen_wanted = (unsigned int)((unsigned char)string[0]);
  606.     sp = &(string[2]);
  607.     /*
  608.      * Should the string be shorter maxlen_wanted including or excluding
  609.      * the trailing '\0' ? We don't take any risk.
  610.      */
  611.     while(len < maxlen_wanted-1)
  612.     {
  613.         c=getch();
  614.         /*
  615.          * shold we check for backspace here?
  616.          * TURBOC does (just checked) but doesn't in cscanf (thats harder
  617.          * or even impossible). We do the same.
  618.          */
  619.         if (c == '\b')
  620.         {
  621.             if (len > 0)
  622.             {
  623.                cputs("\b \b"); /* go back, clear char on screen with space
  624.                                   and go back again */
  625.                len--;
  626.                sp[len] = '\0'; /* clear the character in the string */
  627.             }
  628.         }
  629.         else if (c == '\r')
  630.         {
  631.             sp[len] = '\0';
  632.             break;
  633.         }
  634.         else if (c == 0)
  635.         {
  636.             /* special character ends input */
  637.             sp[len] = '\0';
  638.             ungetch(c); /* keep the char for later processing */
  639.             break;
  640.         }
  641.         else
  642.         {
  643.            sp[len] = putch(c);
  644.            len++;
  645.         }
  646.      }
  647.      sp[maxlen_wanted-1] = '\0';
  648.      string[1] = (char)((unsigned char)len);
  649.      return(sp);
  650. }
  651.  
  652. int cscanf(const char *fmt, ...)
  653. {
  654.     return(_doscan_low(NULL, _scan_getche, _scan_ungetch,
  655.                        fmt, (void **)((&fmt)+1)));
  656. }
  657.  
  658. int movetext(int left, int top, int right, int bottom, int dleft, int dtop)
  659. {
  660.   char    *buf = malloc((right - left + 1) * (bottom - top + 1) * 2);
  661.  
  662.   if (!buf)
  663.     return 0;
  664.  
  665.   gettext(left, top, right, bottom, buf);
  666.   puttext(dleft, dtop, dleft + right - left, dtop + bottom - top, buf);
  667.   free(buf);
  668.   return 1;
  669. }
  670.  
  671. static void _gettextinfo(struct text_info *t)
  672. {
  673.   int row, col;
  674.  
  675.   t->winleft = t->wintop = 1;
  676.   t->winright = t->screenwidth = ScreenCols();
  677.   t->winbottom = t->screenheight = ScreenRows();
  678.   ScreenAttrib = t->attribute = t->normattr = get_screenattrib();
  679.   t->currmode = getvideomode();
  680.   ScreenGetCursor(&row, &col);
  681.   t->curx = col+1;
  682.   t->cury = row+1;
  683. #if DBGGTINFO
  684.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  685.      t->winright,t->wintop,t->winbottom);
  686.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  687.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  688.      t->curx, t->cury);
  689. #endif
  690. }
  691.  
  692. void gettextinfo(struct text_info *t)
  693. {
  694.   *t = txinfo;
  695. #if DBGGTINFO
  696.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  697.      t->winright,t->wintop,t->winbottom);
  698.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  699.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  700.      t->curx, t->cury);
  701. #endif
  702. }
  703.  
  704. static int
  705. getvideomode(void)
  706. {
  707.     int mode = ScreenMode();
  708.     /*
  709.      * in mode C80 we might have loaded a different font
  710.      */
  711.     if (mode == C80)
  712.         if (ScreenRows() > 25)
  713.            mode = C4350;
  714.     return(mode);
  715. }
  716.  
  717.  
  718. static void bell(void)
  719. {
  720.     union REGS regs;
  721. #if 0
  722.     /* use BIOS */
  723.     regs.h.ah = 0x0e; /* write */
  724.     regs.h.al = 0x07; /* bell */
  725.     int86(0x10, ®s, ®s);
  726. #else
  727.     /* use DOS */
  728.     regs.h.ah = 0x06; /* write */
  729.     regs.h.dl = 0x07; /* bell */
  730.     int86(0x21, ®s, ®s);
  731. #endif
  732. }
  733.  
  734. static int
  735. get_screenattrib(void)
  736. {
  737.     union REGS regs;
  738.     regs.h.ah = 0x08; /* read character and attribute */
  739.     regs.h.bh = 0;    /* video page 0 */
  740.     int86(0x10, ®s, ®s);
  741.     return(regs.h.ah & 0x7f); /* strip highest (BLINK) bit */
  742. }
  743.  
  744. /* check if we have at least EGA (idea form Ralf Browns interrupt list) */
  745. static int
  746. isEGA(void)
  747. {
  748.     union REGS regs;
  749.     regs.h.ah = 0x12;
  750.     regs.h.bl = 0x10;
  751.     regs.h.bh = 0xff;
  752.     int86(0x10, ®s, ®s);
  753.     return(regs.h.bh != 0xff);
  754. }
  755.  
  756.  
  757. extern int _gppconio_init;
  758.  
  759. void gppconio_init(void)
  760. {
  761.     static int oldattrib =  -1;
  762.     if (oldattrib == -1)
  763.         oldattrib = get_screenattrib();
  764.     _gettextinfo(&txinfo);
  765.     if (txinfo.currmode == 7)    /* MONO */
  766.         ScreenAddress = 0xb0000UL;
  767.     else
  768.     ScreenAddress = 0xb8000UL;
  769.     ScreenAttrib = txinfo.normattr = txinfo.attribute = oldattrib;
  770.     _gppconio_init = 1;
  771. }
  772.  
  773. #endif /* __DJGPP__ < 2 */
  774.