home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / ibmpc.c < prev    next >
C/C++ Source or Header  |  1998-05-14  |  35KB  |  1,447 lines

  1. /*
  2.  * The routines in this file provide support for the IBM-PC family
  3.  * of machines. It goes directly to the graphics RAM to do screen output.
  4.  *
  5.  * Supported monitor cards include
  6.  *    CGA, MONO, EGA, VGA.
  7.  *
  8.  * Modified by Pete Ruczynski (pjr) for auto-sensing and selection of
  9.  * display type.
  10.  *
  11.  * $Header: /usr/build/vile/vile/RCS/ibmpc.c,v 1.88 1998/05/14 23:14:56 tom Exp $
  12.  *
  13.  */
  14.  
  15. #define    termdef    1            /* don't define "term" external */
  16.  
  17. #include        "estruct.h"
  18. #include        "edef.h"
  19.  
  20. #if DISP_BORLAND || !DISP_IBMPC
  21. #error misconfigured:  DISP_IBMPC should be defined if using ibmpc.c
  22. #error (and DISP_BORLAND should not be defined)
  23. #endif
  24.  
  25. #if CC_DJGPP
  26. #include <pc.h>
  27. #define min(a,b) (((a) < (b)) ? (a) : (b))
  28. #define max(a,b) (((a) > (b)) ? (a) : (b))
  29. #define outp(p,v) outportb(p,v)
  30. #define inp(p) inportb(p)
  31. #define far
  32. #include <io.h> /* for setmode() */
  33. #include <fcntl.h> /* for O_BINARY */
  34. #include <dpmi.h> /* for the register struct */
  35. #include <go32.h>
  36. #endif
  37.  
  38. #define NROW    50            /* Max Screen size.        */
  39. #define NCOL    80            /* Edit if you want to.         */
  40. #define    MARGIN    8            /* size of minimum margin and    */
  41. #define    SCRSIZ    64            /* scroll size for extended lines */
  42. #define    NPAUSE    200            /* # times thru update to pause */
  43. #define    SPACE    32            /* space character        */
  44.  
  45. #if CC_WATCOM
  46. #define    SCADC    (0xb800 << 4)        /* CGA address of screen RAM    */
  47. #define    SCADM    (0xb000 << 4)        /* MONO address of screen RAM    */
  48. #define SCADE    (0xb800 << 4)        /* EGA address of screen RAM    */
  49. #endif
  50.  
  51. #if CC_DJGPP
  52. #define FAR_POINTER(s,o) (0xe0000000 + s*16 + o)
  53. #define FP_SEG(a)    ((unsigned long)(a) >> 4L)
  54. #define FP_OFF(a)    ((unsigned long)(a) & 0x0fL)
  55. #define    SCADC    0xb800            /* CGA address of screen RAM    */
  56. #define    SCADM    0xb000            /* MONO address of screen RAM    */
  57. #define SCADE    0xb800            /* EGA address of screen RAM    */
  58. #endif
  59.  
  60. #ifndef SCADC
  61. #define    SCADC    0xb8000000L        /* CGA address of screen RAM    */
  62. #define    SCADM    0xb0000000L        /* MONO address of screen RAM    */
  63. #define SCADE    0xb8000000L        /* EGA address of screen RAM    */
  64. #endif
  65.  
  66. #ifndef FAR_POINTER
  67. #define FAR_POINTER(s,o) (s)
  68. #endif
  69.  
  70. #if CC_WATCOM
  71. #ifdef __386__
  72. #define    INTX86(a,b,c)        int386(a, b, c)
  73. #define    INTX86X(a,b,c,d)    int386x(a, b, c, d)
  74. #else
  75. #define    INTX86(a,b,c)        int86(a, b, c)
  76. #define    INTX86X(a,b,c,d)    int86x(a, b, c, d)
  77. #endif
  78. #define    _AX_        eax
  79. #define    _BX_        ebx
  80. #define    _CX_        ecx
  81. #define    _DX_        edx
  82. #define    _DI_        edi
  83. #else
  84. #define    INTX86(a,b,c)    int86(a, b, c)
  85. #define    INTX86X(a,b,c,d)    int86x(a, b, c, d)
  86. #define    _AX_        ax
  87. #define    _BX_        bx
  88. #define    _CX_        cx
  89. #define    _DX_        dx
  90. #define    _DI_        di
  91. #endif
  92.  
  93. #define    ColorDisplay()    (dtype != CDMONO && !monochrome)
  94. #define    AttrColor(b,f)    (((ctrans[b] & 7) << 4) | (ctrans[f] & 15))
  95. #define    Black(n)    ((n) ? 0 : 7)
  96. #define    White(n)    ((n) ? 7 : 0)
  97. #define    AttrMono(f)    (((Black(f) & 7) << 4) | (White(f) & 15))
  98.  
  99. #if OPT_MS_MOUSE
  100.     static    int    ms_crsr2inx  ( int, int );
  101.     static    void    ms_deinstall (void);
  102.     static    void    ms_hidecrsr  (void);
  103.     static    void    ms_install   (void);
  104.     static    void    ms_setvrange ( int, int );
  105.     static    void    ms_showcrsr  (void);
  106. #else
  107. # define ms_deinstall()
  108. # define ms_install()
  109. #endif
  110.  
  111. static    int    dtype = -1;    /* current display type        */
  112. #if CC_DJGPP
  113. #define PACKED __attribute__ ((packed))
  114. #else
  115. #define PACKED
  116. #endif
  117.  
  118.     /* mode-independent VGA-BIOS status information */
  119. typedef    struct {
  120.     UCHAR    video_modes[3] PACKED;    /* 00 Supported video-modes */
  121.     UCHAR    reserved[4] PACKED;    /* 03 */
  122.     UCHAR    text_scanlines PACKED;    /* 07 Number of pixel rows in text mode */
  123.     UCHAR    num_charsets PACKED;    /* 08 Number of character sets that can be displayed */
  124.     UCHAR    num_loadable PACKED;    /* 09 Number of character sets loadable into video RAM */
  125.     UCHAR    capability PACKED;    /* 0A VGA-BIOS capability info */
  126.     UCHAR    more_info PACKED;    /* 0B More VGA-BIOS capability info */
  127.     UCHAR    reserved2[4] PACKED;    /* 0C */
  128.     } static_VGA_info PACKED;
  129.  
  130.     /* mode-dependent VGA-BIOS status information */
  131. typedef    struct {
  132.     static_VGA_info *static_info PACKED; /* 00 Address of table containing static info */
  133.     UCHAR    code_number PACKED;    /* 04 Code number of current video mode */
  134.     USHORT    num_columns PACKED;    /* 05 Number of displayed screen or pixel cols */
  135.     USHORT    page_length PACKED;    /* 07 Length of display page in video RAM */
  136.     USHORT    curr_page PACKED;    /* 09 Starting address of current display-page in video RAM */
  137.     UCHAR    crsr_pos[8][2] PACKED;    /* 0B Cursor positions in display-pages in col/row order */
  138.     UCHAR    crsr_end PACKED;    /* 1B Ending row of cursor (pixel) row */
  139.     UCHAR    crsr_start PACKED;    /* 1C Starting row of cursor (pixel) row */
  140.     UCHAR    curr_page_num PACKED;    /* 1D Number of current display page */
  141.     USHORT    port_crt PACKED;    /* 1E Port address of the CRT controller address register */
  142.     UCHAR    curr_crtc PACKED;    /* 20 Current contents of CRTC control registers */
  143.     UCHAR    curr_color_sel PACKED;    /* 21 Current color selection register contents */
  144.     UCHAR    num_rows PACKED;    /* 22 Number of screen rows displayed */
  145.     USHORT    char_height PACKED;    /* 23 Height of characters in pixel rows */
  146.     UCHAR    code_active PACKED;    /* 25 Code number of active video adapter */
  147.     UCHAR    code_inactive PACKED;    /* 26 Code number of inactive video adapter */
  148.     USHORT    num_colors PACKED;    /* 27 Number of displayable colors (0=monochrome) */
  149.     UCHAR    num_pages PACKED;    /* 29 Number of screen pages */
  150.     UCHAR    num_pixel_rows PACKED;    /* 2A Number of displayed pixel rows (RES_200, etc.) */
  151.     UCHAR    num_cset0 PACKED;    /* 2B Number of char-table used with chars whose 3rd attr bit is 0 */
  152.     UCHAR    num_cset1 PACKED;    /* 2C Number of char-table used with chars whose 3rd attr bit is 1 */
  153.     UCHAR    misc_info PACKED;    /* 2D Miscellaneous information */
  154.     UCHAR    reserved[3] PACKED;    /* 2E */
  155.     UCHAR    size_of_ram PACKED;    /* 31 Size of available video RAM (0=64k, 1=128k, 2=192k, 3=256k) */
  156.     UCHAR    reserved2[14] PACKED;    /* 32 */
  157.     } dynamic_VGA_info PACKED;    /* length == 64 bytes */
  158.  
  159.     /* scan-line resolution codes */
  160. #define    RES_200    0
  161. #define    RES_350    1
  162. #define    RES_400    2
  163. #define RES_480 3
  164.  
  165.     /* character-size codes */
  166. #define    C8x8    0x12
  167. #define    C8x14    0x11
  168. #define    C8x16    0x14
  169.  
  170.     /* character-size in pixels, for mouse-positioning */
  171. static    int    chr_wide = 8;
  172. static    int    chr_high = 8;
  173.  
  174. typedef    struct    {
  175.     char    *name;
  176.     UCHAR    type;
  177.     UCHAR    mode;
  178.     UCHAR    vchr;    /* code for setting character-height */
  179.     UCHAR    rows;
  180.     UCHAR    cols;
  181.     UCHAR    vres;    /* required scan-lines, RES_200, ... */
  182.     } DRIVERS;
  183.  
  184. #define ORIGTYPE  0    /* store original info in this slot.
  185.                (these values should all (?) get replaced
  186.                at open time) */
  187.  
  188. /* order this table so that more higher resolution entries for the same
  189.  *  name come first.  remember -- synonyms take only 10 bytes, plus the
  190.  *  name itself.
  191.  */
  192. static    DRIVERS drivers[] = {
  193.         {"default",ORIGTYPE,    3,      C8x8,   25,  80, RES_200},
  194.         {"2",      CDVGA,    3,    C8x16,    25,  80, RES_400},
  195.         {"25",     CDVGA,    3,    C8x16,    25,  80, RES_400},
  196.         {"2",      CDCGA,    3,    C8x8,    25,  80, RES_200},
  197.         {"25",     CDCGA,    3,    C8x8,    25,  80, RES_200},
  198.         {"CGA",    CDCGA,    3,    C8x8,    25,  80, RES_200},
  199.         {"MONO",   CDMONO,    3,    C8x8,    25,  80, RES_200},
  200.         {"80x25",  CDVGA,    3,    C8x16,    25,  80, RES_400},
  201.         {"80x28",  CDVGA,    3,    C8x14,  28,  80, RES_400},
  202.         {"EGA",    CDEGA,    3,    C8x8,    43,  80, RES_350},
  203.         {"4",      CDEGA,    3,    C8x8,    43,  80, RES_350},
  204.         {"43",     CDEGA,    3,    C8x8,    43,  80, RES_350},
  205.         {"80x43",  CDVGA,    3,    C8x8,   43,  80, RES_350},
  206.         {"5",      CDVGA,    3,    C8x8,    50,  80, RES_400},
  207.         {"50",     CDVGA,    3,    C8x8,    50,  80, RES_400},
  208.         {"VGA",    CDVGA,    3,    C8x8,    50,  80, RES_400},
  209.         {"80x50",  CDVGA,    3,    C8x8,    50,  80, RES_400},
  210.         {"80x14",  CDVGA,    3,    C8x14,  14,  80, RES_200},
  211.         {"40x12",  CDVGA,    1,    C8x16,    12,  40, RES_200},
  212.         {"40x21",  CDVGA,    1,    C8x16,    21,  40, RES_350},
  213.         {"40x25",  CDVGA,    1,    C8x16,    25,  40, RES_400},
  214.         {"40x28",  CDVGA,    1,    C8x14,  28,  40, RES_400},
  215.         {"40x50",  CDVGA,    1,    C8x8,   50,  40, RES_400},
  216.  
  217.     };
  218.  
  219. static    const    long    ScreenAddress[] = {
  220.         SCADC,    /* CDCGA: Color graphics adapter */
  221.         SCADM,    /* CDMONO: Monochrome adapter */
  222.         SCADE,    /* CDEGA: Enhanced graphics adapter */
  223.         SCADE    /* CDVGA: VGA adapter */
  224.     };
  225.  
  226. /*  the following should be sized dynamically, but it may not be worth it,
  227.     if we come up in the biggest size anyway, since we never shrink
  228.     but only grow */
  229. USHORT *scptr[NROW];            /* pointer to screen lines    */
  230. USHORT *s2ptr[NROW];            /* pointer to page-1 lines    */
  231. USHORT sline[NCOL];            /* screen line image        */
  232. extern union REGS rg;            /* cpu register for use of DOS calls */
  233.  
  234. static    int    ibm_opened,
  235.         original_page,    /* display-page (we use 0)    */
  236.         allowed_vres,    /* possible scan-lines, 1 bit per value */
  237.         original_curs,    /* start/stop scan lines    */
  238.         monochrome    = FALSE;
  239.  
  240. static    int    egaexist = FALSE;    /* is an EGA card available?    */
  241.  
  242.                     /* Forward references.          */
  243. extern  void    ibmmove   (int,int);
  244. extern  void    ibmeeol   (void);
  245. extern  void    ibmeeop   (void);
  246. extern  void    ibmbeep   (void);
  247. extern  void    ibmopen   (void);
  248. extern    void    ibmrev    (UINT);
  249. extern    int    ibmcres   (const char *);
  250. extern    void    ibmclose  (void);
  251. extern    void    ibmputc   (int);
  252. extern    void    ibmkopen  (void);
  253. extern    void    ibmkclose (void);
  254.  
  255. #if    OPT_COLOR
  256. extern    void    ibmfcol   (int);
  257. extern    void    ibmbcol   (int);
  258.  
  259. int    cfcolor = -1;        /* current forground color */
  260. int    cbcolor = -1;        /* current background color */
  261. static    const char *initpalettestr = "0 4 2 6 1 5 3 7 8 12 10 14 9 13 11 15";
  262. /* black, red, green, yellow, blue, magenta, cyan, white   */
  263. #endif
  264. extern    void    ibmscroll (int,int,int);
  265.  
  266. static    int    scinit    (int);
  267. static    int    getboard  (void);
  268. static    int    scblank   (void);
  269.  
  270. #ifdef MUCK_WITH_KBD_RATE
  271. static    void    maxkbdrate   (void);
  272. #endif
  273.  
  274. static    const struct {
  275.     char  *seq;
  276.     int   code;
  277. } keyseqs[] = {    /* use 'Z' in place of leading 0, so these can be C-strings */
  278.     /* Arrow keys */
  279.     {"Z\110",     KEY_Up},
  280.     {"Z\120",     KEY_Down},
  281.     {"Z\115",     KEY_Right},
  282.     {"Z\113",     KEY_Left},
  283.     /* page scroll */
  284.     {"Z\121",     KEY_Next},
  285.     {"Z\111",     KEY_Prior},
  286.     {"Z\107",     KEY_Home},
  287.     {"Z\117",     KEY_End},
  288.     /* editing */
  289.         {"ZR",        KEY_Insert},
  290.     {"Z\123",     KEY_Delete},
  291.     /* function keys */
  292.         {"Z;",      KEY_F1},
  293.     {"Z<",      KEY_F2},
  294.     {"Z=",      KEY_F3},
  295.     {"Z>",      KEY_F4},
  296.     {"Z?",      KEY_F5},
  297.     {"Z@",      KEY_F6},
  298.     {"ZA",      KEY_F7},
  299.     {"ZB",      KEY_F8},
  300.     {"ZC",      KEY_F9},
  301.         {"ZD",      KEY_F10},
  302. };
  303.  
  304. static int current_ibmtype;
  305.  
  306. /*
  307.  * Standard terminal interface dispatch table. Most of the fields point into
  308.  * "termio" code.
  309.  */
  310. TERM    term    = {
  311.     NROW,
  312.     NROW,
  313.     NCOL,
  314.     NCOL,
  315.     MARGIN,
  316.     SCRSIZ,
  317.     NPAUSE,
  318.     ibmopen,
  319.     ibmclose,
  320.     ibmkopen,
  321.     ibmkclose,
  322.     ttgetc,
  323.     ibmputc,
  324.     tttypahead,
  325.     ttflush,
  326.     ibmmove,
  327.     ibmeeol,
  328.     ibmeeop,
  329.     ibmbeep,
  330.     ibmrev,
  331.     ibmcres,
  332. #if    OPT_COLOR
  333.     ibmfcol,
  334.     ibmbcol,
  335.     set_ctrans,
  336. #else
  337.     null_t_setfor,
  338.     null_t_setback,
  339.     null_t_setpal,
  340. #endif
  341.     ibmscroll,
  342.     null_t_pflush,
  343.     null_t_icursor,
  344.     null_t_title,
  345.     null_t_watchfd,
  346.     null_t_unwatchfd,
  347. };
  348.  
  349. #if CC_DJGPP
  350. _go32_dpmi_seginfo vgainfo;
  351. #endif
  352.  
  353. static int
  354. get_vga_bios_info(dynamic_VGA_info *buffer)
  355. {
  356. # if CC_DJGPP
  357.     _go32_dpmi_registers regs;
  358.     vgainfo.size = (sizeof (dynamic_VGA_info)+15) / 16;
  359.     if (_go32_dpmi_allocate_dos_memory(&vgainfo) != 0) {
  360.         fprintf(stderr,"Couldn't allocate vgainfo memory\n");
  361.         exit(BADEXIT);
  362.     }
  363.  
  364.     regs.x.ax = 0x1b00;
  365.     regs.x.bx = 0;
  366.     regs.x.ss = regs.x.sp = 0;
  367.     regs.x.es = vgainfo.rm_segment;
  368.     regs.x.di = 0;
  369.     _go32_dpmi_simulate_int(0x10, ®s);
  370.  
  371.     dosmemget( vgainfo.rm_segment*16, sizeof (dynamic_VGA_info), buffer);
  372.  
  373.     _go32_dpmi_free_dos_memory(&vgainfo);
  374.  
  375.     return (regs.h.al == 0x1b);
  376. #else
  377.     struct SREGS segs;
  378.  
  379. #if CC_WATCOM
  380.     segread(&segs);
  381. #else
  382.     segs.es   = FP_SEG(buffer);
  383. #endif
  384.     rg.x._DI_ = FP_OFF(buffer);
  385.     rg.x._AX_ = 0x1b00;
  386.     rg.x._BX_ = 0;
  387.     INTX86X(0x10, &rg, &rg, &segs); /* Get VGA-BIOS status */
  388.  
  389.     return (rg.h.al == 0x1b);
  390. #endif
  391. }
  392.  
  393. static void
  394. set_display (int mode)
  395. {
  396.     rg.h.ah = 0;
  397.     rg.h.al = mode;
  398.     INTX86(0x10, &rg, &rg);
  399. }
  400.  
  401. static void
  402. set_page (int page)
  403. {
  404.     rg.h.ah = 5;
  405.     rg.h.al = page;
  406.     INTX86(0x10, &rg, &rg);
  407. }
  408.  
  409. #ifdef MUCK_WITH_KBD_RATE
  410. /*  set the keyboard rate to max */
  411. static void
  412. maxkbdrate (void)
  413. {
  414.     rg.h.ah = 0x3;
  415.     rg.h.al = 0x5;
  416.     rg.h.bh = 0x0;
  417.     rg.h.bl = 0x0;
  418.     INTX86(0x16, &rg, &rg);
  419. }
  420. #endif
  421.  
  422. static void
  423. set_char_size(int code)
  424. {
  425.     switch (code) {
  426.     case C8x8:    chr_wide = 8;    chr_high = 8;    break;
  427.     case C8x14:    chr_wide = 8;    chr_high = 14;    break;
  428.     case C8x16:    chr_wide = 8;    chr_high = 16;    break;
  429.     default:    return;        /* cannot set this one! */
  430.     }
  431.     rg.h.ah = 0x11;        /* set char. generator function code    */
  432.     rg.h.al = code;        /*  to specified ROM            */
  433.     rg.h.bl = 0;        /* Character table 0            */
  434.     INTX86(0x10, &rg, &rg);    /* VIDEO - TEXT-MODE CHARACTER GENERATOR FUNCTIONS */
  435. }
  436.  
  437. static void
  438. set_cursor(int start_stop)
  439. {
  440.     rg.h.ah = 1;        /* set cursor size function code */
  441.     rg.x._CX_ = (drivers[ORIGTYPE].mode <= 3) ?
  442.         start_stop & 0x707 : start_stop;
  443.     INTX86(0x10, &rg, &rg);    /* VIDEO - SET TEXT-MODE CURSOR SHAPE */
  444. }
  445.  
  446. static int
  447. get_cursor(void)
  448. {
  449.     rg.h.ah = 3;
  450.     rg.h.bh = 0;
  451.     INTX86(0x10, &rg, &rg);    /* VIDEO - GET CURSOR POSITION */
  452.     return rg.x._CX_;
  453. }
  454.  
  455. static void
  456. set_vertical_resolution(int code)
  457. {
  458.     rg.h.ah = 0x12;
  459.     rg.h.al = code;
  460.     rg.h.bl = 0x30;
  461.     INTX86(0x10, &rg, &rg);    /* VIDEO - SELECT VERTICAL RESOLUTION */
  462.     if (code == RES_200)
  463.         delay(50);    /* patch: timing problem? */
  464. }
  465.  
  466. /*--------------------------------------------------------------------------*/
  467.  
  468. #if    OPT_COLOR
  469. void
  470. ibmfcol(        /* set the current output color */
  471. int color)        /* color to set */
  472. {
  473.     if (color < 0)
  474.         color = C_WHITE;
  475.     cfcolor = ctrans[color];
  476. }
  477.  
  478. void
  479. ibmbcol(        /* set the current background color */
  480. int color)        /* color to set */
  481. {
  482.     if (color < 0)
  483.         color = C_BLACK;
  484.     cbcolor = ctrans[color];
  485. }
  486. #endif
  487.  
  488. void
  489. ibmmove(int row, int col)
  490. {
  491.     rg.h.ah = 2;        /* set cursor position function code */
  492.     rg.h.dl = col;
  493.     rg.h.dh = row;
  494.     rg.h.bh = 0;        /* set screen page number */
  495.     INTX86(0x10, &rg, &rg);
  496. }
  497.  
  498. /* erase to the end of the line */
  499. void
  500. ibmeeol(void)
  501. {
  502.     int ccol,crow;    /* current column,row for cursor */
  503.  
  504.     /* find the current cursor position */
  505.     rg.h.ah = 3;        /* read cursor position function code */
  506.     rg.h.bh = 0;        /* current video page */
  507.     INTX86(0x10, &rg, &rg);
  508.  
  509.     ccol = rg.h.dl;        /* record current column */
  510.     crow = rg.h.dh;        /* and row */
  511.  
  512.     scwrite(crow, ccol, term.t_ncol-ccol, NULL, NULL, gfcolor, gbcolor);
  513.  
  514. }
  515.  
  516. /* put a character at the current position in the current colors */
  517. void
  518. ibmputc(int ch)
  519. {
  520.     rg.h.ah = 14;        /* write char to screen with current attrs */
  521.     rg.h.al = ch;
  522. #if    OPT_COLOR
  523.     if (ColorDisplay())
  524.         rg.h.bl = cfcolor;
  525.     else
  526. #endif
  527.     rg.h.bl = White(TRUE);
  528.     rg.h.bh = 0;        /* current video page */
  529.     INTX86(0x10, &rg, &rg);
  530. }
  531.  
  532. void
  533. ibmeeop(void)
  534. {
  535.     rg.h.ah = 6;        /* scroll page up function code */
  536.     rg.h.al = 0;        /* # lines to scroll (clear it) */
  537.     rg.x._CX_ = 0;        /* upper left corner of scroll */
  538.     rg.h.dh = term.t_nrow - 1; /* lower right corner of scroll */
  539.     rg.h.dl = term.t_ncol - 1;
  540.     rg.h.bh = scblank();
  541.     INTX86(0x10, &rg, &rg);
  542. }
  543.  
  544. void
  545. ibmrev(        /* change reverse video state */
  546. UINT state)    /* TRUE = reverse, FALSE = normal */
  547. {
  548.     /* This never gets used under the IBM-PC driver */
  549. }
  550.  
  551. int
  552. ibmcres(    /* change screen resolution */
  553. const char *res)    /* resolution to change to */
  554. {
  555.     register int i;        /* index */
  556.     int    status = FALSE;
  557.  
  558.     if (!res || !strcmp(res, "?"))     /* find the default configuration */
  559.         res = "default";
  560.  
  561.     /* try for a name match on all drivers, until we find it
  562.         and succeed or fall off the bottom */
  563.     for (i = 0; i < TABLESIZE(drivers); i++) {
  564.         if (strcmp(res, drivers[i].name) == 0) {
  565.             if ((status = scinit(i)) == TRUE) {
  566.                 strcpy(current_res_name, res);
  567.                 break;
  568.             }
  569.         }
  570.     }
  571.     return status;
  572. }
  573.  
  574. #if OPT_MS_MOUSE || OPT_FLASH
  575. extern VIDEO **vscreen;    /* patch: edef.h */
  576.  
  577. static    int    vp2attr ( VIDEO *, int );
  578. static    void    move2nd ( int, int );
  579. static    void    copy2nd ( int );
  580.  
  581. static int
  582. vp2attr(VIDEO *vp, int inverted)
  583. {
  584.     int    attr;
  585. #if    OPT_COLOR
  586.     if (ColorDisplay())
  587.         attr = AttrColor(
  588.             inverted ? ReqFcolor(vp) : ReqBcolor(vp),
  589.             inverted ? ReqBcolor(vp) : ReqFcolor(vp));
  590.     else
  591. #endif
  592.      attr = AttrMono(!inverted);
  593.     return (attr << 8);
  594. }
  595.  
  596. static void
  597. move2nd(int row, int col)
  598. {
  599.     rg.h.ah = 0x02;
  600.     rg.h.bh = 1;
  601.     rg.h.dh = row;
  602.     rg.h.dl = col;
  603.     INTX86(0x10, &rg, &rg);
  604. }
  605.  
  606. static void
  607. copy2nd(int inverted)
  608. {
  609.     WINDOW    *wp;
  610.     VIDEO    *vp;
  611.     USHORT *lp;
  612.     char *tt;
  613.     register int    row, col, attr;
  614.  
  615.     for_each_visible_window(wp) {
  616.         for (row = wp->w_toprow; row <= mode_row(wp); row++) {
  617.             vp = vscreen[row];
  618.             lp = s2ptr[row];
  619.             tt = vp->v_text;
  620.             attr = vp2attr(vp, inverted ^ (row == mode_row(wp)));
  621.             for (col = 0; col < term.t_ncol; col++) {
  622.                 lp[col] = (attr | tt[col]);
  623.             }
  624.         }
  625.     }
  626.  
  627.     /* fill in the message line */
  628.     lp = s2ptr[term.t_nrow-1];
  629.     attr = scblank() << 8;
  630.     for (col = 0; col < term.t_ncol; col++)
  631.         lp[col] = attr | SPACE;
  632.     move2nd(ttrow, ttcol);
  633. }
  634. #endif
  635.  
  636. /*
  637.  * Reading back from display memory does not work properly when using a mouse,
  638.  * because the portion of the display line beginning with the mouse cursor is
  639.  * altered (by the mouse driver, apparently).  Flash the display by building an
  640.  * inverted copy of the screen in the second display-page and toggling
  641.  * momentarily to that copy.
  642.  *
  643.  * Note: there's no window from which to copy the message line.
  644.  */
  645. #if OPT_FLASH
  646. void
  647. flash_display (void)
  648. {
  649.     copy2nd(TRUE);
  650.     set_page(1);
  651.     catnap(100,FALSE); /* if we don't wait, we cannot see the flash */
  652.     set_page(0);
  653. }
  654. #endif    /* OPT_FLASH */
  655.  
  656. void
  657. ibmbeep(void)
  658. {
  659. #if    OPT_FLASH
  660.     if (global_g_val(GMDFLASH) && ibm_opened) {
  661.         flash_display();
  662.         return;
  663.     }
  664. #endif
  665.     bdos(6, BEL, 0);    /* annoying!! */
  666. }
  667.  
  668. void
  669. ibmopen(void)
  670. {
  671.     register DRIVERS *driver = &drivers[ORIGTYPE];
  672.     int i;
  673.  
  674.     if (sizeof(dynamic_VGA_info) != 64) {
  675.         printf("DOS vile build error -- dynamic_VGA_info struct"
  676.             " must be packed (ibmpc.c)\n");
  677.         exit(BADEXIT);
  678.     }
  679.  
  680.     rg.h.ah = 0xf;
  681.     INTX86(0x10,&rg, &rg);    /* VIDEO - GET DISPLAY MODE */
  682.  
  683.     driver->vchr  = C8x8;
  684.     driver->vres  = RES_200;
  685.     driver->rows  = 25;
  686.     driver->cols  = rg.h.ah;
  687.     driver->mode  = rg.h.al;
  688.     original_page = rg.h.bh;
  689.     driver->type  = getboard();
  690.     allowed_vres  = (1<<RES_200);    /* assume only 200 scan-lines */
  691.  
  692.     if (driver->type == CDVGA) {    /* we can determine original rows */
  693.         dynamic_VGA_info buffer;
  694.  
  695.         if (get_vga_bios_info(&buffer)) {
  696. #undef TESTIT
  697. #ifdef TESTIT
  698.             printf ("call succeeded\n");
  699.             printf ("static_info is 0x%x\n", buffer.static_info);
  700.             printf ("code_number is 0x%x\n", buffer.code_number);
  701.             printf ("num_columns is 0x%x\n", buffer.num_columns);
  702.             printf ("page_length is 0x%x\n", buffer.page_length);
  703.             printf ("curr_page is 0x%x\n", buffer.curr_page);
  704.             printf ("num_rows is 0x%x\n", buffer.num_rows);
  705. #endif
  706.             switch (buffer.char_height) {
  707.             case 8:        driver->vchr = C8x8;    break;
  708.             case 14:    driver->vchr = C8x14;    break;
  709.             case 16:    driver->vchr = C8x16;    break;
  710.             }
  711.             driver->rows = buffer.num_rows;
  712. #if CC_DJGPP
  713.             { u_long staticinfop;
  714.             static_VGA_info static_info;
  715.             staticinfop = ((u_long)buffer.static_info & 0xffffL);
  716.             staticinfop += (((u_long)buffer.static_info >> 12) &
  717.                         0xffff0L);
  718.             dosmemget( staticinfop, sizeof(static_info),
  719.                     &static_info);
  720.             allowed_vres = static_info.text_scanlines;
  721.             }
  722. #elif CC_WATCOM
  723.             {
  724.             static_VGA_info __far *staticinfop;
  725.             staticinfop = MK_FP (
  726.             ((unsigned long)(buffer.static_info) >> 16) & 0xffffL,
  727.             ((unsigned long)(buffer.static_info)      ) & 0xffffL
  728.                 );
  729.             allowed_vres = staticinfop->text_scanlines;
  730.             }
  731. #else
  732.             allowed_vres = buffer.static_info->text_scanlines;
  733. #endif
  734.             driver->vres = buffer.num_pixel_rows;
  735.         }
  736.     } else if (driver->type == CDEGA) {
  737.         allowed_vres |= (1<<RES_350);
  738.     }
  739.  
  740.     original_curs = get_cursor();
  741.  
  742. #ifdef PVGA
  743.     set_display(10);    /* set graphic 640x350 mode */
  744.     rg.x._AX_ = 0x007F;
  745.     rg.h.bh = 0x01;        /* set non-VGA mode */
  746.     INTX86(0x10,&rg, &rg);
  747.     set_display(7);        /* set Hercule mode */
  748.     current_res_name = "25";
  749. #endif
  750.  
  751. #if    OPT_COLOR
  752.     set_palette(initpalettestr);
  753. #endif
  754.     if (!ibmcres(current_res_name))
  755.         (void)scinit(ORIGTYPE);
  756.     revexist = TRUE;
  757.     ttopen();
  758.  
  759. #ifdef MUCK_WITH_KBD_RATE
  760.     maxkbdrate();   /* set the keyboard rate to max */
  761. #endif
  762.     for (i = TABLESIZE(keyseqs); i--; ) {
  763.          int len = strlen(keyseqs[i].seq);
  764.         if (keyseqs[i].seq[0] == 'Z') {
  765.             keyseqs[i].seq[0] = '\0';
  766.         }
  767.         addtosysmap(keyseqs[i].seq, len, keyseqs[i].code);
  768.     }
  769.  
  770.     ibm_opened = TRUE;    /* now safe to use 'flash', etc. */
  771. }
  772.  
  773. void
  774. ibmclose(void)
  775. {
  776.     int    ctype = current_ibmtype;
  777.  
  778.     if (current_ibmtype != ORIGTYPE)
  779.         scinit(ORIGTYPE);
  780.     if (original_page != 0)
  781.         set_page(original_page);
  782.     set_cursor(original_curs);
  783.  
  784.     current_ibmtype = ctype; /* ...so subsequent TTopen restores us */
  785.  
  786.     dtype = CDMONO;        /* ...force monochrome */
  787.     kbd_erase_to_end(0);    /* ...force colors _off_ */
  788.     kbd_flush();
  789. }
  790.  
  791. void
  792. ibmkopen(void)        /* open the keyboard */
  793. {
  794.     ms_install();
  795. #if CC_DJGPP
  796.     setmode(0,O_BINARY);
  797. #endif
  798. }
  799.  
  800. void
  801. ibmkclose(void)        /* close the keyboard */
  802. {
  803. #if CC_DJGPP
  804.     setmode(0,O_TEXT);
  805. #endif
  806.     ms_deinstall();
  807. }
  808.  
  809. static int
  810. scinit(            /* initialize the screen head pointers */
  811. int newtype)        /* type of adapter to init for */
  812. {
  813.     dynamic_VGA_info buffer;
  814.     union {
  815.         long laddr;        /* long form of address */
  816.         USHORT *paddr;        /* pointer form of address */
  817.     } addr;
  818.     long pagesize;
  819.     register DRIVERS *driver;
  820.     register int i;
  821.     int         type, rows, cols;
  822.  
  823.     driver = &drivers[newtype];
  824.  
  825.     /* check to see if we're allow this many scan-lines */
  826.     if ((allowed_vres & (1 << (driver->vres))) == 0)
  827.         return FALSE;
  828.  
  829.     type = driver->type;
  830.     rows = driver->rows;
  831.     cols = driver->cols;
  832.  
  833.     /* and set up the various parameters as needed */
  834.     set_vertical_resolution(driver->vres);
  835.  
  836.     set_display(driver->mode);
  837.     set_vertical_resolution(driver->vres);
  838.     set_char_size(driver->vchr);
  839.  
  840.     /* reset the original cursor -- it gets changed above somewhere */
  841.     set_cursor(original_curs);
  842.  
  843.     /*
  844.      * Install an alternative hardcopy routine which prints as many lines
  845.      * as are displayed on the screen. The normal BIOS routine always
  846.      * prints 25 lines.
  847.      */
  848.     if (rows > 25) {
  849.         rg.h.ah = 0x12;        /* alternate select function code    */
  850.         rg.h.bl = 0x20;        /* alt. print screen routine         */
  851.         INTX86(0x10, &rg, &rg);    /* VIDEO - SELECT ALTERNATE PRTSCRN  */
  852.     }
  853.  
  854.     if (driver->type == CDEGA) {
  855.         outp(0x3d4, 10);    /* video bios bug patch */
  856.         outp(0x3d5, 6);
  857.     }
  858.  
  859.     /* reset the $sres environment variable */
  860.     (void)strcpy(sres, driver->name);
  861.  
  862.     if ((type == CDMONO) != (dtype == CDMONO))
  863.         sgarbf = TRUE;
  864.     dtype = type;
  865.     current_ibmtype = newtype;
  866.  
  867.     /* initialize the screen pointer array */
  868.     if (monochrome)
  869.         addr.laddr = FAR_POINTER(ScreenAddress[CDMONO],0x0000);
  870.     else if (type == CDMONO)
  871.         addr.laddr = FAR_POINTER(ScreenAddress[CDCGA],0x0000);
  872.     else
  873.         addr.laddr = FAR_POINTER(ScreenAddress[type],0x0000);
  874.  
  875.     for (i = 0; i < rows; i++)
  876.         scptr[i] = addr.paddr + (cols * i);
  877.  
  878. #if OPT_FLASH || OPT_MS_MOUSE
  879.     /* Build row-indices for display page #1, to use it in screen flashing
  880.      * or for mouse highlighting.
  881.      */
  882.     if ((type == CDVGA) && get_vga_bios_info(&buffer)) {
  883.         /*
  884.          * Setting page-1 seems to make Window 3.1 "aware" that we're
  885.          * going to write to that page.  Otherwise, the "flash" mode
  886.          * doesn't write to the correct address.
  887.          */
  888.         set_page(1);
  889.         get_vga_bios_info(&buffer);
  890.         pagesize = (long)buffer.page_length; /* also, page-1 offset */
  891.         set_page(0);
  892.     } else {
  893.         /*
  894.          * This was tested for all of the VGA combinations running
  895.          * with MSDOS, but isn't general -- dickey@software.org
  896.          */
  897.         pagesize = (rows * cols);
  898.         switch (cols) {
  899.         case 40:    pagesize += ((4*cols) - 32);    break;
  900.         case 80:    pagesize += ((2*cols) - 32);    break;
  901.         }
  902.         pagesize <<= 1;
  903.     }
  904.     addr.laddr += pagesize;
  905.     for (i = 0; i < rows; i++)
  906.         s2ptr[i] = addr.paddr + (cols * i);
  907. #endif
  908.     /* changing the screen-size forces an update, so we do this last */
  909.     newscreensize(rows, cols);
  910. #if OPT_MS_MOUSE
  911.     if (ms_exists()) {
  912.         ms_deinstall();
  913.         ms_install();
  914.     }
  915. #endif
  916.     return(TRUE);
  917. }
  918.  
  919. /* getboard:    Determine which type of display board is attached.
  920.  *        Current known types include:
  921.  *
  922.  *        CDMONO    Monochrome graphics adapter
  923.  *        CDCGA    Color Graphics Adapter
  924.  *        CDEGA    Extended graphics Adapter
  925.  *        CDVGA    VGA graphics Adapter
  926.  */
  927.  
  928. int getboard(void)
  929. {
  930.     monochrome = FALSE;
  931.     egaexist = FALSE;
  932.  
  933.     /* check for VGA or MCGA */
  934.     rg.x._AX_ = 0x1a00;
  935.     rg.h.bl = 0x00;
  936.     INTX86(0x10,&rg, &rg);    /* VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA,MCGA) */
  937.  
  938.     if (rg.h.al == 0x1a) {    /* function succeeded */
  939.         switch (rg.h.bl) {
  940.         case 0x01:    monochrome = TRUE;
  941.                 return (CDMONO);
  942.  
  943.         case 0x02:    return (CDCGA);
  944.  
  945.         case 0x05:    monochrome = TRUE;
  946.         case 0x04:    egaexist = TRUE;
  947.                 return (CDEGA);
  948.  
  949.         case 0x07:    monochrome = TRUE;
  950.         case 0x08:    return (CDVGA);
  951.  
  952.         case 0x0b:    monochrome = TRUE;
  953.         case 0x0a:
  954.         case 0x0c:    return (CDCGA);    /* MCGA */
  955.         }
  956.     }
  957.  
  958.     /*
  959.      * Check for MONO board
  960.      */
  961.     INTX86(0x11, &rg, &rg);    /* BIOS - GET EQUIPMENT LIST */
  962.  
  963.     /* Bits 4-5 in ax are:
  964.      *    00 EGA, VGA or PGA
  965.      *    01 40x25 color
  966.      *    10 80x25 color
  967.      *    11 80x25 monochrome
  968.      */
  969.     if (((rg.x._AX_ & 0x30) == 0x30)) {
  970.         monochrome = TRUE;
  971.         return(CDMONO);
  972.     }
  973.  
  974.     /*
  975.      * Test if EGA present
  976.      */
  977.     rg.h.ah = 0x12;
  978.     rg.h.bl = 0x10;
  979.     INTX86(0x10,&rg, &rg);    /* VIDEO - GET EGA INFO */
  980.  
  981.     if (rg.h.bl != 0x10) {    /* function succeeded */
  982.         egaexist = TRUE;
  983.         return(CDEGA);
  984.     }
  985.  
  986.     return (CDCGA);
  987. }
  988.  
  989. void
  990. scwrite(        /* write a line out*/
  991.     int row,    /* row of screen to place outstr on */
  992.     int col,    /* col of screen to place outstr on */
  993.     int nchar,    /* length of outstr */
  994.     const char *outstr,  /* string to write out (must be term.t_ncol long) */
  995.     VIDEO_ATTR *attrstr, /* attributes to write out (must be term.t_ncol long) */
  996.     int forg,    /* foreground color of string to write */
  997.     int bacg)    /* background color */
  998. {
  999.     register USHORT *lnptr;    /* pointer to the destination line */
  1000.     register int i;
  1001.  
  1002.     if (row > term.t_nrow-1)
  1003.         return;
  1004.  
  1005.     if (flickcode && (dtype == CDCGA))
  1006.         lnptr = sline;
  1007.     else
  1008.         lnptr = scptr[row]+col;
  1009.  
  1010.     if (attrstr) {
  1011.         register USHORT attrnorm;
  1012.         register USHORT attrrev;
  1013. #if    OPT_COLOR
  1014.         if (ColorDisplay()) {
  1015.             attrnorm = AttrColor(bacg,forg) << 8;
  1016.             attrrev = AttrColor(forg,bacg) << 8;
  1017.         } else
  1018. #endif
  1019.         {
  1020.         attrnorm = AttrMono(bacg<forg) << 8;
  1021.         attrrev = AttrMono(forg<bacg) << 8;
  1022.         }
  1023.         for (i = 0; i < nchar; i++) {
  1024.             *lnptr++ = ((outstr != 0)
  1025.                 ? (outstr[i+col] & 0xff)
  1026.                 : SPACE) | ((attrstr[i+col] & (VAREV|VASEL))
  1027.                     ? attrrev
  1028.                     : attrnorm);
  1029.         }
  1030.     } else {
  1031.         register USHORT attr; /* attribute byte mask to place in RAM */
  1032.         /* build the attribute byte and setup the screen pointer */
  1033. #if    OPT_COLOR
  1034.         if (ColorDisplay())
  1035.             attr = AttrColor(bacg,forg);
  1036.         else
  1037. #endif
  1038.         attr = AttrMono(bacg<forg);
  1039.         attr <<= 8;
  1040.         for (i = 0; i < nchar; i++) {
  1041.             *lnptr++ = ((outstr != 0)
  1042.                 ? (outstr[i+col] & 0xff)
  1043.                 : SPACE) | attr;
  1044.         }
  1045.     }
  1046.  
  1047.     if (flickcode && (dtype == CDCGA)) {
  1048.         /* wait for vertical retrace to be off */
  1049.         while ((inp(0x3da) & 8))
  1050.             ;
  1051.         /* and to be back on */
  1052.         while ((inp(0x3da) & 8) == 0)
  1053.             ;
  1054.         /* and send the string out */
  1055.         movmem(sline, scptr[row]+col, nchar*sizeof(short));
  1056.     }
  1057. }
  1058.  
  1059. /* reads back a line into a VIDEO struct, used in line-update computation */
  1060. VIDEO *
  1061. scread(VIDEO *vp, int row)
  1062. {
  1063.     register int    i;
  1064.  
  1065.     if (row > term.t_nrow-1)
  1066.         return 0;
  1067.  
  1068.     if (vp == 0) {
  1069.         static    VIDEO    *mine;
  1070.         if (video_alloc(&mine))
  1071.             vp = mine;
  1072.         else
  1073.             tidy_exit(BADEXIT);
  1074.     }
  1075.     movmem(scptr[row], &sline[0], term.t_ncol*sizeof(short));
  1076.     for (i = 0; i < term.t_ncol; i++)
  1077.         vp->v_text[i] = sline[i];
  1078.     return vp;
  1079. }
  1080.  
  1081. /* returns attribute for blank/empty space */
  1082. static int
  1083. scblank(void)
  1084. {
  1085.     register int attr;
  1086. #if    OPT_COLOR
  1087.     if (ColorDisplay())
  1088.         attr = AttrColor(gbcolor,gfcolor);
  1089.     else
  1090. #endif
  1091.      attr = AttrMono(TRUE);
  1092.     return attr;
  1093. }
  1094.  
  1095. /*
  1096.  * Move 'n' lines starting at 'from' to 'to'
  1097.  *
  1098.  * OPT_PRETTIER_SCROLL is prettier but slower -- it scrolls a line at a time
  1099.  *    instead of all at once.
  1100.  */
  1101. void
  1102. ibmscroll(int from, int to, int n)
  1103. {
  1104. #if OPT_PRETTIER_SCROLL
  1105.     if (absol(from-to) > 1) {
  1106.         ibmscroll(from, (from < to) ? to-1 : to+1, n);
  1107.         if (from < to)
  1108.             from = to-1;
  1109.         else
  1110.             from = to+1;
  1111.     }
  1112. #endif
  1113.     if (from > to) {
  1114.         rg.h.ah = 0x06;        /* scroll window up */
  1115.         rg.h.al = from - to;    /* number of lines to scroll */
  1116.         rg.h.ch = to;        /* upper window row */
  1117.         rg.h.dh = from + n - 1;    /* lower window row */
  1118.     } else {
  1119.         rg.h.ah = 0x07;        /* scroll window down */
  1120.         rg.h.al = to - from;    /* number of lines to scroll */
  1121.         rg.h.ch = from;        /* upper window row */
  1122.         rg.h.dh = to + n - 1;    /* lower window row */
  1123.     }
  1124.     rg.h.bh = scblank();    /* attribute to use for line-fill */
  1125.     rg.h.cl = 0;        /* left window column */
  1126.     rg.h.dl = term.t_ncol - 1; /* lower window column */
  1127.     INTX86(0x10, &rg, &rg);
  1128. }
  1129.  
  1130.  
  1131. /*--------------------------------------------------------------------------*/
  1132.  
  1133. #if OPT_MS_MOUSE
  1134.  
  1135. /* Define translations between mouse (pixels) and chars (row/col).
  1136.  * patch: why does 8 by 8 work, not chr_high by chr_wide?
  1137.  */
  1138. #define MS_CHAR_WIDE    ((term.t_ncol == 80) ? 8 : 16)
  1139. #define MS_CHAR_HIGH    8
  1140.  
  1141. #define    pixels2col(x)   ((x)/MS_CHAR_WIDE)
  1142. #define pixels2row(y)   ((y)/MS_CHAR_HIGH)
  1143.  
  1144. #define col2pixels(x)   ((x)*MS_CHAR_WIDE)
  1145. #define row2pixels(y)   ((y)*MS_CHAR_HIGH)
  1146.  
  1147. /* Define a macro for calling mouse services */
  1148. #define MouseCall INTX86(0x33, &rg, &rg)
  1149.  
  1150. #define MS_MOVEMENT    iBIT(0)    /* mouse cursor movement */
  1151. #define    MS_BTN1_PRESS   iBIT(1)    /* left button */
  1152. #define MS_BTN1_RELEASE iBIT(2)
  1153. #define MS_BTN2_PRESS   iBIT(3)    /* right button */
  1154. #define MS_BTN2_RELEASE iBIT(4)
  1155. #define MS_BTN3_PRESS   iBIT(5)    /* center button */
  1156. #define MS_BTN3_RELEASE iBIT(6)
  1157.  
  1158. #define BLINK 0x8000
  1159.  
  1160.     /* These have to be "far", otherwise TurboC doesn't force the
  1161.      * segment register to be specified from 'ms_event_handler()'
  1162.      */
  1163. int    far    button_pending;    /* 0=none, 1=pressed, 2=released */
  1164. int    far    button_number;    /* 1=left, 2=right, 3=center */
  1165. int    far    button_press_x;
  1166. int    far    button_press_y;
  1167. int    far    button_relsd_x;
  1168. int    far    button_relsd_y;
  1169. int        rodent_exists;
  1170. int        rodent_cursor_display;
  1171.  
  1172. #if CC_TURBO
  1173. #define    MsButtonPending() button_pending
  1174. #endif
  1175.  
  1176. /*
  1177.  * If we're using a DPMI configuration, we'll not be able to use the mouse
  1178.  * event handler, since it relies on a call rather than an interrupt.  We can
  1179.  * do polling instead.
  1180.  */
  1181. #if !CC_TURBO
  1182. static int
  1183. MsButtonPending(void)
  1184. {
  1185.     rg.x._AX_ = 3;    /* query the mouse */
  1186.     MouseCall;
  1187.  
  1188.     if (rg.x._BX_ & 7) {
  1189.         if (rg.x._BX_ & 1)
  1190.             button_number = 1;
  1191.         else if (rg.x._BX_ & 2)
  1192.             button_number = 2;
  1193.         else if (rg.x._BX_ & 4)
  1194.             button_number = 3;
  1195.  
  1196.         button_press_x = button_relsd_x = rg.x._CX_;
  1197.         button_press_y = button_relsd_y = rg.x._DX_;
  1198.         button_pending = 1;
  1199.  
  1200.     } else {
  1201.         if (button_pending)
  1202.             button_pending = 2;
  1203.         button_relsd_x = rg.x._CX_;
  1204.         button_relsd_y = rg.x._DX_;
  1205.     }
  1206.     return button_pending;
  1207. }
  1208. #endif
  1209.  
  1210. int
  1211. ms_exists (void)
  1212. {
  1213.     return rodent_exists;
  1214. }
  1215.  
  1216. void
  1217. ms_processing (void)
  1218. {
  1219.     WINDOW    *wp;
  1220.     int    copied = FALSE,
  1221.         invert, normal,
  1222.         first, first_x = ttcol, first_y = ttrow,
  1223.         last,  last_x  = ttcol,  last_y = ttrow,
  1224.         that,  that_x,  that_y,
  1225.         attr, delta;
  1226.     USHORT *s2page = s2ptr[0];
  1227.  
  1228.     ms_showcrsr();
  1229.     while (MsButtonPending()) {
  1230.         if (button_pending == 2) {    /* released? */
  1231.             button_pending = 0;
  1232.             break;
  1233.         } else {    /* selection */
  1234.  
  1235. #if CC_TURBO
  1236.             disable();
  1237.             that_x = button_relsd_x;
  1238.             that_y = button_relsd_y;
  1239.             enable();
  1240. #else
  1241.             that_x = button_relsd_x;
  1242.             that_y = button_relsd_y;
  1243. #endif
  1244.  
  1245.             if (!copied) {
  1246.                 int x = pixels2col(button_press_x);
  1247.                 int y = pixels2row(button_press_y);
  1248.                 wp = row2window(y);
  1249.                 /* Set the dot-location if button 1 was pressed
  1250.                  * in a window.
  1251.                  */
  1252.                 if (wp != 0
  1253.                  && ttrow != term.t_nrow - 1
  1254.                  && setcursor(y, x)) {
  1255.                     (void)update(TRUE);
  1256.                     ms_setvrange(wp->w_toprow,
  1257.                              mode_row(wp) - 1);
  1258.                 } else {    /* cannot reposition */
  1259.                     kbd_alarm();
  1260.                     while (MsButtonPending() != 2)
  1261.                         ;
  1262.                     continue;
  1263.                 }
  1264.                 first_x = last_x = col2pixels(ttcol);
  1265.                 first_y = last_y = row2pixels(ttrow);
  1266.                 first = ms_crsr2inx(first_x, first_y);
  1267.  
  1268.                 copy2nd(FALSE);
  1269.                 set_page(1);
  1270.                 copied = TRUE;
  1271.  
  1272.                 invert = vp2attr(vscreen[ttrow],TRUE);
  1273.                 normal = vp2attr(vscreen[ttrow],FALSE);
  1274.             }
  1275.  
  1276.             that  = ms_crsr2inx(that_x, that_y);
  1277.             last  = ms_crsr2inx(last_x, last_y);
  1278.             delta = (last < that) ? 1 : -1;
  1279.  
  1280.             if (that != last) {
  1281.                 register int j;
  1282.                 if (((last < that) && (last <= first))
  1283.                  || ((last > that) && (last >= first))) {
  1284.                     attr = normal;
  1285.                 } else {
  1286.                     attr = invert;
  1287.                 }
  1288. #define HiLite(n,attr) s2page[n] = attr | (s2page[n] & 0xff)
  1289.  
  1290.                 for (j = last; j != that; j += delta) {
  1291.                     if (j == first) {
  1292.                         if (attr == normal) {
  1293.                             attr = invert;
  1294.                         } else {
  1295.                             attr = normal;
  1296.                         }
  1297.                     }
  1298.                     HiLite(j,attr);
  1299.                 }
  1300.                 HiLite(that,invert|BLINK);
  1301.             }
  1302.             last_x = that_x;
  1303.             last_y = that_y;
  1304.         }
  1305.     }
  1306.  
  1307.     /*
  1308.      * If we've been highlighting the selection, finish it off.
  1309.      */
  1310.     if (copied) {
  1311.         set_page(0);
  1312.         ms_setvrange(0, term.t_nrow-1);
  1313.         mlerase();
  1314.         setwmark(pixels2row(last_y), pixels2col(last_x));
  1315.         if (DOT.l != MK.l
  1316.          || DOT.o != MK.o) {
  1317.             regionshape = EXACT;
  1318.             (void)yankregion();
  1319.             (void)update(TRUE);
  1320.         }
  1321.         movecursor(pixels2row(first_y), pixels2col(first_x));
  1322.     }
  1323. }
  1324.  
  1325. /* translate cursor position (pixels) to array-index of the text-position */
  1326. static int
  1327. ms_crsr2inx(int x, int y)
  1328. {
  1329.     return pixels2col(x) + (pixels2row(y) * term.t_ncol);
  1330. }
  1331.  
  1332. static void
  1333. ms_deinstall(void)
  1334. {
  1335.     ms_hidecrsr();
  1336.     rg.x._AX_ = 0;    /* reset the mouse */
  1337.     MouseCall;
  1338.     rodent_exists = FALSE;
  1339. }
  1340.  
  1341.     /* This event-handler cannot do I/O; tracing it can be tricky...
  1342.      */
  1343. #if CC_TURBO
  1344. void far
  1345. ms_event_handler (void)
  1346. {
  1347.     UINT    ms_event  = _AX;
  1348. /*    UINT    ms_button = _BX;*/
  1349.     UINT    ms_horz   = _CX;
  1350.     UINT    ms_vert   = _DX;
  1351.  
  1352.     if (ms_event & MS_BTN1_PRESS) {
  1353.         button_pending = 1;
  1354.         button_number  = 1;
  1355.         button_press_x = button_relsd_x = ms_horz;
  1356.         button_press_y = button_relsd_y = ms_vert;
  1357.     } else {    /* movement or release */
  1358.         if (ms_event & MS_BTN1_RELEASE)
  1359.             button_pending = 2;
  1360.         button_relsd_x = ms_horz;
  1361.         button_relsd_y = ms_vert;
  1362.     }
  1363.     return;
  1364. }
  1365. #endif
  1366.  
  1367. static void
  1368. ms_hidecrsr(void)
  1369. {
  1370.     /* Hides the mouse cursor if it is displayed */
  1371.     if (rodent_cursor_display) {
  1372.         rodent_cursor_display = FALSE;
  1373.         rg.x._AX_ = 0x02;
  1374.         MouseCall;
  1375.     }
  1376. } /* End of ms_hidecrsr() */
  1377.  
  1378. static void
  1379. ms_install(void)
  1380. {
  1381.     if (rodent_exists)
  1382.         return;
  1383.  
  1384.     /* If a mouse is installed, initializes the mouse and
  1385.      * sets rodent_exists to 1. If no mouse is installed,
  1386.      * sets rodent_exists to 0.
  1387.      */
  1388.     rg.x._AX_ = 0;
  1389.     MouseCall;
  1390.     rodent_exists = rg.x._AX_;
  1391.     rodent_cursor_display = FALSE; /* safest assumption */
  1392.     if (ms_exists()) {
  1393.         struct SREGS segs;
  1394.  
  1395.         memset(&rg, 0, sizeof(rg));
  1396.         memset(&segs, 0, sizeof(segs));
  1397.  
  1398.         rg.x._AX_ = 0x4;    /* set mouse position */
  1399.         rg.x._CX_ = 0;
  1400.         rg.x._DX_ = 0;
  1401.         MouseCall;
  1402.  
  1403. #if CC_TURBO
  1404.         rg.x._AX_ = 0xc;    /* define event handler */
  1405.         rg.x._CX_ = MS_MOVEMENT | MS_BTN1_PRESS | MS_BTN1_RELEASE;
  1406.         rg.x._DX_ = FP_OFF(ms_event_handler);
  1407.         segs.es = FP_SEG(ms_event_handler);
  1408.         INTX86X(0x33, &rg, &rg, &segs);
  1409. #endif
  1410.     }
  1411. }
  1412.  
  1413. static void
  1414. ms_setvrange(int upperrow, int lowerrow)
  1415. {
  1416.     /* Restricts vertical cursor movement to the screen region
  1417.      * between upperrow and lowerrow.  If the cursor is outside the range,
  1418.      * it is moved inside.
  1419.      */
  1420.     rg.x._AX_ = 0x08;
  1421.     rg.x._CX_ = row2pixels(upperrow);
  1422.     rg.x._DX_ = row2pixels(lowerrow);
  1423.     MouseCall;
  1424. } /* End of ms_setvrange() */
  1425.  
  1426.  
  1427. static void
  1428. ms_showcrsr(void)
  1429. {
  1430.     /* Displays the mouse cursor */
  1431.     int counter;
  1432.  
  1433.     /* Call Int 33H Function 2AH to get the value of the display counter */
  1434.     rg.x._AX_ = 0x2A;
  1435.     MouseCall;
  1436.     counter = rg.x._AX_;
  1437.  
  1438.     /* Call Int 33H Function 01H as many times as needed to display */
  1439.     /* the mouse cursor */
  1440.     while (counter-- > 0) {
  1441.         rg.x._AX_ = 0x01;
  1442.         MouseCall;
  1443.     }
  1444.     rodent_cursor_display = TRUE;
  1445. } /* End of ms_showcrsr() */
  1446. #endif /* OPT_MS_MOUSE */
  1447.