home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0020 - 0029 / ibm0020-0029 / ibm0028.tar / ibm0028 / GRLF-C-2.ZIP / GFUNC / USERIN.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-05-30  |  31.0 KB  |  1,178 lines

  1.         page    58,132
  2.  
  3. ; userin.asm
  4. ; contains:  Userin(), inikbd(), mousinst(), ctlmscur(), setcbvec()
  5. ;         rescbvec(), cntrlbrk(), setmctyp()
  6. ;
  7.         ifndef    _LCODE
  8.          include    model.h
  9.         endif
  10.         include    prologue.h
  11.         name    userin
  12.  
  13. ;==>-- Options for conditional Assembly
  14. ;
  15. GETKEYCODE    equ    1            ;Return old-style getkey() code
  16. USERBUFFER    equ    1            ;Input from user buffer feature enabled
  17.  
  18.     if    (_LCODE eq 0) and (_LDATA eq 0)    ;;Small Model
  19. _codepsize    equ    1            ;size of code pointer (words)
  20. _datapsize    equ    1            ;size of data pointer (words)
  21.     endif
  22.         
  23.     if    (_LCODE eq 0) and (_LDATA ne 0) ;;Compact Model
  24. _codepsize    equ    1            ;size of code pointer (words)
  25. _datapsize    equ    2            ;size of data pointer (words)
  26.     endif
  27.  
  28.     if    (_LCODE ne 0) and (_LDATA eq 0)    ;;Medium Model
  29. _codepsize    equ    2            ;size of code pointer (words)
  30. _datapsize    equ    1            ;size of data pointer (words)
  31.     endif
  32.  
  33.     if    (_LCODE ne 0) and (_LDATA ne 0)    ;;Large Model
  34. _codepsize    equ    2            ;size of code pointer (words)
  35. _datapsize    equ    2            ;size of data pointer (words)
  36.     endif
  37.  
  38.  
  39.  
  40. ;==>--    GKEYdefines the structure thats address is passed to the keyboard
  41. ;    function.
  42. ;
  43. GKEY    struc
  44.     Option        dw    ?        ;See Option bits below
  45.     Status        dw    ?        ;See Status values below
  46.     Mstat        dw    ?        ;See Mstat values below
  47.     Char        db    ?        ;Character code (ASCII)
  48.     Scan        db    ?        ;Scan code
  49.     Shift        dw    ?        ;Shift Status bits
  50.     MouseX        dw    ?        ;Mouse X position
  51.     MouseY        dw    ?        ;Mouse Y position
  52.     MouseBtns    dw    ?        ;Mouse button information
  53.     UserHook    dw    _codepsize dup(?) ;Points to optional user idle function
  54.     UserData    dw    _datapsize dup(?) ;Points to optional user input buffer
  55.     GetKeyVal    dw    ?        ;For compatibility getkey() return value
  56. GKEY    ends
  57.  
  58. ;==>-- Bits for Option structure member.
  59. ;
  60. WAITFORKEY    equ    0000000000000001b    ;Wait for key before returning
  61. MONSHIFT    equ    0000000000000010b    ;Monitor Shift Status
  62. MONXMOUSE    equ    0000000000000100b    ;Monitor Mouse X position
  63. MONYMOUSE    equ    0000000000001000b    ;Monitor Mouse Y position
  64. MONMOUSEBUTTN    equ    0000000000010000b    ;Monitor Mouse Buttons
  65. MOUSEMAPPING    equ    0000000000100000b    ;Enable Mouse Character Position mapping
  66. CALLDOS     equ    0000000001000000b    ;Call Dos before checking keyboard
  67. NOEXTKBDTEST    equ    0000000010000000b    ;Skip Extended keyboard test
  68. PASSEXTCHCODES    equ    0000000100000000b    ;Pass Extended character codes
  69. BUFFERSCAN    equ    1000000000000000b    ;Buffer has scan/ascii codes
  70.  
  71. ;==>-- Possible values for Status structure member and return code from
  72. ;      function.
  73. ;
  74. KEYACTIVITY    equ    0fff0h            ;A key has been pressed.
  75. MOUSEACTIVITY    equ    0fff1h            ;Mouse activity detected, look at Mstat.
  76. SHIFTACTIVITY    equ    0fff2h            ;Shift activity.
  77.  
  78. ;==>-- Possible values for Mstat structure member.
  79. ;
  80. MOUXCHANGE    equ    1            ;Mouse X position has changed.
  81. MOUYCHANGE    equ    2            ;Mouse Y position has changed.
  82. MOUBUTTNCHANGE    equ    3            ;Mouse Button status has changed.
  83.  
  84. ;==>-- Possible values for bits in MouseBtns structure member.
  85. ;
  86. MOURIGHTBUTTON    equ    2            ;Right mouse button is pressed
  87. MOULEFTBUTTON    equ    1            ;Left mouse button is pressed
  88.  
  89. ;==>-- Constants for DOS, BIOS and Mouse function calls
  90. ;
  91. DOSCALL     equ    21h            ;Dos: call software interrupt number
  92. DOSCBREAK    equ    23h            ;Dos: Control break vector
  93. DOSGETVECTOR    equ    35h            ;Dos: Get Interrupt vector function number
  94. DOSSETVECTOR    equ    25h            ;Dos: Set Interrupt vector
  95. CHKSTDINPUTST    equ    0bh            ;Dos: Check standard input status
  96. CONTROLBRKCHK    equ    33h            ;Dos: Control Break Set/Check
  97. MOUSECALL    equ    33h            ;Mouse: call software interrupt number
  98. MOUGETBSTMPOS    equ    03h            ;Mouse: Get Button Status and Mouse Position
  99. MOUSHOWCURSOR    equ    01h            ;Mouse: Show cursor
  100. MOUHIDECURSOR    equ    02h            ;Mouse: Hide cursor
  101. MOUSETTXTCURSOR equ    0ah            ;Mouse: Set Text Cursor Type
  102. MOUSESETMAXY    equ    08h            ;Mouse: Set Maximum Y position
  103. KBDCALL     equ    16h            ;Keyboard: call software interrupt number
  104. KBDREAD     equ    00h            ;Keyboard: read function number
  105. KBDSTATUS    equ    01h            ;Keyboard: status function number
  106. XKBDWRITE    equ    05h            ;Extended: Keyboard Write function number
  107. XKBDREAD    equ    10h            ;Extended: read function number
  108. XKBDSTATUS    equ    11h            ;Extended: status function number
  109.  
  110. NOKEY        equ    0ffffh            ;When returned from the idle function
  111.                         ;signifies that the idle function is
  112.                         ;not returning any keyboard codes.
  113.  
  114. DONTKNOW    equ    0ffh            ;Constant for MouseInstalled and EnhancedKeybd
  115.  
  116. ;;==>-- Values passed to users idle function
  117. ;;
  118. IDLEINIT    equ    00h            ;Initialize idle function
  119. IDLEIDLE    equ    01h            ;Keyboard waiting
  120. IDLESHUTDOWN    equ    02h            ;Shutdown idle function
  121.  
  122. ROMBIOSSEG    equ    040h            ;Rom Bios Segment
  123. KBFLAG        equ    017h            ;Offset for keyboard flag in ROM Bios Segment
  124.  
  125.         dseg    duserin
  126.  
  127.  
  128.         ifdef    TURBOC
  129.          if    _HUGE
  130.           assume es:_duserin_DATA
  131.          else
  132.           assume es:DGROUP
  133.          endif
  134.         else
  135.          ifndef AZTEC
  136.           assume  es:DGROUP
  137.          else
  138.           assume  es:dataseg
  139.          endif
  140.         endif
  141.  
  142. MouseInstalled    db    DONTKNOW        ;001h=Yes, 000h=No
  143. EnhancedKeybd    db    DONTKNOW        ;010h=Yes, 000h=No
  144. IdleState    db    DONTKNOW
  145. PrevCtlBreak    dd    0            ;Previous control break address
  146.         if    _LCODE
  147. CtlBreakAddress dd    0            ;Users control break function
  148.         else
  149. CtlBreakAddress dw    0            ;Users control break function
  150.         endif
  151.  
  152.         endds
  153.  
  154.         pseg    puserin
  155. ;/*
  156. ;**  unsigned 
  157. ;** UserIn(GKEY *table)
  158. ;**
  159. ;** ARGUMENT(s)
  160. ;**  (GKEY *)    table        -    pointer to a GKEY data structure
  161. ;**
  162. ;** DESCRIPTION
  163. ;**
  164. ;** RETURNS
  165. ;**  table.Status
  166. ;**
  167. ;** AUTHOR
  168. ;**  ""   Tue 01-Nov-1988    10:22:32
  169. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  170. ;**
  171. ;** MODIFICATIONS
  172. ;**  "" Fri 02-Dec-1988 09:53:37
  173. ;**   Added code to translate the 0xE0 returned as a character code when any
  174. ;**   of the four cursor keys on the extended keyboard are pressed to a 0x00
  175. ;**   character code to be consistent with the character code returned from
  176. ;**   the cursor keys on a non-extended keyboard.
  177. ;**
  178. ;*/
  179.         cproc    UserIn
  180.         mov    IdleState,DONTKNOW
  181.         push    es
  182.         if    _LDATA
  183.          push    ds
  184.          mov    di,ds
  185.          lds    si,parm1_        ;DS:SI -> GKEY
  186.         else
  187.          mov    si,parm1_        ;DS:SI -> GKEY
  188.          mov    di,ds
  189.         endif
  190.         mov    [si+Status],0        ;Say nothing happened
  191.         mov    [si+Mstat],0        ;clear mouse status also
  192.         if    GETKEYCODE
  193.          mov    [si+GetKeyVal],NOKEY
  194.         endif
  195.  
  196.           if      USERBUFFER
  197.  
  198.         ; See if users data structure has UserData pointing to some data,
  199.         ; if so return value as if a key had been pressed.  Increment
  200.         ; UserData until the end of the data is detected.  When the end
  201.         ; is detected set UserData = (void *)0.
  202.  
  203.         if    _LDATA
  204.          les    bx,dword ptr [si+UserData] ;ES:BX -> user's data buffer
  205.          mov    ax,es
  206.          or    ax,bx            ;check for (void *)0
  207.         else
  208.          mov    bx,[si+UserData]    ;BX -> users data buffer
  209.          or    bx,bx            ;check for (void *)0
  210.         endif
  211.         jz    CheckShift        ;if pointer == (void *)0 skip out
  212.         test    [si+Option],BUFFERSCAN    ;does buffer have scan codes
  213.         jnz    hasscans
  214.         if    _LDATA
  215.          mov    al,es:[bx]        ;ASCII character to AL
  216.         else
  217.          mov    al,[bx]         ;ASCII character to AL
  218.         endif
  219.         or    al,al            ;terminator reached?
  220.         jnz    notterm1        ;if not take jump else set
  221.                         ;UserData=(void *)0
  222.         if    _LDATA
  223.          mov    word ptr [si+UserData],0
  224.          mov    word ptr [si+UserData+2],0
  225.         else
  226.          mov    [si+UserData],0
  227.         endif
  228.         jmp    short CheckShift
  229. notterm1:    mov    [si+Char],al        ;Save in structure
  230.         mov    [si+Scan],0        ;Clear Scan code
  231.         if    GETKEYCODE
  232.          xor     ah,ah
  233.          mov     [si+GetKeyVal],ax
  234.         endif
  235.         mov    [si+Status],KEYACTIVITY
  236.         inc    bx            ;Increment data pointer
  237.         if    _LDATA
  238.          mov    word ptr [si+UserData],bx
  239.         else
  240.          mov    [si+UserData],bx
  241.         endif
  242.         jmp    NewKeyExit        ;get out with value
  243. hasscans:
  244.         if    _LDATA
  245.          mov    ax,es:[bx]        ;AL=Character, AH=Scan
  246.         else
  247.          mov    ax,[bx]         ;AL=Character, AH=Scan
  248.         endif
  249.         or    ax,ax            ;reached terminator?
  250.         jnz    notterm2
  251.         if    _LDATA
  252.          mov    word ptr [si+UserData],0
  253.          mov    word ptr [si+UserData+2],0
  254.         else
  255.          mov    [si+UserData],0
  256.         endif
  257.         jmp    short CheckShift
  258. notterm2:    mov    [si+Char],al        ;save ASCII code in structure
  259.         mov    [si+Scan],ah        ;save Scan code in structure
  260.         mov    [si+Status],KEYACTIVITY
  261.         add    bx,2            ;bx+=2
  262.         if    _LDATA
  263.          mov    word ptr [si+UserData],bx
  264.         else
  265.          mov    [si+UserData],bx
  266.         endif
  267.         if    GETKEYCODE
  268.          or     al,al            ;is it extended?
  269.          jz     xltkey1        ;if so put in structure
  270.          xor     ah,ah            ;else zero high 8 bits
  271. xltkey1:     mov     [si+GetKeyVal],ax
  272.         endif
  273.         jmp    NewKeyExit        ;Exit function with value in AX
  274.           endif
  275.  
  276.         ; Now see if Option has the MONSHIFT bit set, if so call the GetShiftWord
  277.         ; routine and compare the return value (AX) to the Shift structure member.
  278.         ; If they are different put the new value in the Shift structure member
  279.         ; and set the Status member to SHIFTACTIVITY.
  280. CheckShift:
  281.         test    [si+Option],MONSHIFT    ;monitor shift status?
  282.         jz    CheckMouse        ;if not skip to mouse test
  283.         call    GetShiftWord        ;get 16 bits of shift info to AX
  284.         cmp    ax,[si+Shift]        ;is it different?
  285.         jz    CheckMouse        ;if not skip to mouse
  286.         mov    [si+Shift],ax        ;else update data structure and return
  287.         mov    [si+Status],SHIFTACTIVITY
  288.         jmp    NewKeyExit
  289.  
  290.         ; See if Option has the MONXMOUSE, MONYMOUSE or MONMOUSEBUTTN
  291.         ; bits set. If so check for each in this order: MONMOUSEBUTTN,
  292.         ; MONXMOUSE and MONYMOUSE.  Return on the first condition that
  293.         ; has changed.
  294.  
  295. CheckMouse:    test    [si+Option],MONXMOUSE+MONYMOUSE+MONMOUSEBUTTN
  296.         jnz    reqmouse
  297.         jmp     CheckKeys
  298. reqmouse:
  299.         if    _LDATA
  300.          mov   es,di            ;ES = original DS
  301.          mov   al,es:MouseInstalled    ;AL = MouseInstalled Variable
  302.         else
  303.          mov   al,MouseInstalled    ;AL = MouseInstalled Variable
  304.         endif
  305.         cmp    al,1            ;MouseInstalled==1==mouseinstalled
  306.         jz    chkmousebtn
  307.         or    al,al            ;if(MouseInstalled==0), no mouse
  308.          ;;;jz    CheckKeys        ;skip mouse testing
  309.         jnz    reqm1
  310.         jmp    short CheckKeys
  311.  
  312.         ; See if mouse is installed, update MouseInstalled to 1 if installed, 0 if
  313.         ; not installed.
  314.  
  315. reqm1:        call    MousePresent
  316.         or    ax,ax
  317.         jnz    chkmousebtn
  318.         jmp    short CheckKeys
  319.  
  320.         ; Mouse is definitely installed at this point, it is safe to make mouse
  321.         ; function calls via the software interrupt interface.
  322.  
  323. chkmousebtn:    mov    ax,MOUGETBSTMPOS    ;get mouse information from mouse driver
  324.         int    MOUSECALL
  325.  
  326.         ; If user program wants to know about button changes and the button
  327.         ; change value has changed update structure with new value, set
  328.         ; Status=MOUSEACTIVITY and Mstat=MOUBUTTNCHANGE.
  329.  
  330.         test    [si+Option],MONMOUSEBUTTN
  331.         jz    chkmousexpos
  332.         cmp    [si+MouseBtns],bx    ;did button status change?
  333.         jz    chkmousexpos        ;if not check next
  334.         mov    [si+MouseBtns],bx    ;update structure
  335.         mov    [si+Status],MOUSEACTIVITY
  336.         mov    [si+Mstat],MOUBUTTNCHANGE
  337.         jmp    NewKeyExit
  338.  
  339.         ; If user program wants to know about changes in the X (horizontal)
  340.         ; mouse position and the position has changed update structure with
  341.         ; new value, set status=MOUSEACTIVITY and Mstat=MOUXCHANGE.
  342.  
  343. chkmousexpos:    test    [si+Option],MONXMOUSE
  344.         jz    chkmouseypos
  345.         test    [si+Option],MOUSEMAPPING
  346.         jz    nomapchkx
  347.         shr    cx,1            ;divide mouse position by 8
  348.         shr    cx,1
  349.         shr    cx,1
  350. nomapchkx:    cmp    [si+MouseX],cx        ;did x position change?
  351.         jz    chkmouseypos        ;if not check
  352.         mov    [si+MouseX],cx        ;update structure
  353.         mov    [si+Status],MOUSEACTIVITY
  354.         mov    [si+Mstat],MOUXCHANGE
  355.         jmp    NewKeyExit
  356.  
  357.         ; If user program wants to know about changes in the Y (vertical)
  358.         ; mouse position and the position has changed update structure with
  359.         ; new value, set status=MOUSEACTIVITY and Mstat=MOUYCHANGE.
  360.  
  361. chkmouseypos:    test    [si+Option],MONYMOUSE
  362.         jz    CheckKeys
  363.         test    [si+Option],MOUSEMAPPING
  364.         jz    nomapchky
  365.         shr    dx,1            ;divide mouse positon by 8
  366.         shr    dx,1
  367.         shr    dx,1
  368. nomapchky:    cmp    [si+MouseY],dx        ;did y position change?
  369.         jz    CheckKeys        ;if not go on with keyboard
  370.         mov    [si+MouseY],dx        ;update structure
  371.         mov    [si+Status],MOUSEACTIVITY
  372.         mov    [si+Mstat],MOUYCHANGE
  373.         jmp    NewKeyExit
  374.  
  375.         ; Check for keyboard activity, if first time through determine if
  376.         ; extended keyboard functions are supported.  If so set EnhancedKeybd
  377.         ; variable to 0x10 if not supported set to 00h
  378. CheckKeys:
  379.         test    [si+Option],CALLDOS    ;do we call dos
  380.         jz    nocalldos
  381.         mov    ah,CHKSTDINPUTST
  382.         int    DOSCALL
  383. nocalldos:
  384.         if    _LDATA
  385.          mov   es,di            ;ES = original DS
  386.          mov   al,es:EnhancedKeybd    ;AL = EnhancedKeybd Variable
  387.         else
  388.          mov   al,EnhancedKeybd     ;AL = EnhancedKeybd Variable
  389.         endif
  390.         cmp    al,DONTKNOW
  391.         jnz    keysetup
  392.  
  393.         ; Test for enhanced keyboard, update EnhancedKeybd variable
  394.         test    [si+Option],NOEXTKBDTEST
  395.         jz    oktotest        ;skip extended keyboard test?
  396.         if    _LDATA
  397.          mov    es:EnhancedKeybd,0
  398.         else
  399.          mov    EnhancedKeybd,0
  400.         endif
  401.         jmp    short keysetup
  402. oktotest:    call    ExtendedKbdFunc
  403.         if    _LDATA
  404.          mov    es:EnhancedKeybd,al    ;save return value in variable
  405.         else
  406.          mov    EnhancedKeybd,al    ;save return value in variable
  407.         endif
  408.  
  409.         ; We now know if we can accept the extended keyboard codes or
  410.         ; not and the EnhancedKeybd variable is set accordingly.
  411.         ; Next we see if there is a key available from the keyboard, if
  412.         ; so we put it in the structure and set the Status member
  413.         ; indicating there is KEYACTIVITY.
  414. keysetup:
  415.         mov    ah,KBDSTATUS
  416.         if    _LDATA
  417.          or    ah,es:EnhancedKeybd
  418.         else
  419.          or    ah,EnhancedKeybd
  420.         endif
  421.         int    KBDCALL         ;check for keyboard activity
  422.         jz    nokeyavail        ;if nothing available
  423.         mov    ah,KBDREAD        ;read the key now
  424.         if    _LDATA
  425.          or    ah,es:EnhancedKeybd
  426.         else
  427.          or    ah,EnhancedKeybd
  428.         endif
  429.         int    KBDCALL         ;AL=ASCII, AH=Scan
  430.         cmp    al,0E0h         ;Ascii==0E0h?
  431.         jnz    noxlte0
  432.         or    ah,ah            ;is scan = 0
  433.         jz    noxlte0
  434.         test    [si+Option],PASSEXTCHCODES
  435.         jnz    noxlte0
  436.         xor    al,al            ;make ascii == 0
  437. noxlte0:    mov    [si+Char],al
  438.         mov    [si+Scan],ah        ;save in structure
  439.         mov    [si+Status],KEYACTIVITY ;say there is key activity
  440.         if    GETKEYCODE
  441.          or     al,al            ;is it extended?
  442.          jz     xltkey4        ;if so put in structure
  443.          xor     ah,ah            ;else zero high 8 bits
  444. xltkey4:     mov     [si+GetKeyVal],ax
  445.         endif
  446.         jmp    short NewKeyExit        ;and leave
  447.  
  448.         ; No keyboard code is available, do we wait for one?  If
  449.         ; so is there an idle function? If so let's call it now
  450.  
  451. nokeyavail:    test    [si+Option],WAITFORKEY    ;wait for a key
  452.         jz    NewKeyExit        ;no, don't wait leave
  453.         if    _LCODE
  454.          les    bx,dword ptr [si+UserHook] ;ES:BX = UserHook
  455.          mov    ax,es
  456.          or    ax,bx            ;is pointer 0:0?
  457.         else
  458.          mov    bx,[si+UserHook]    ;BX = UserHook
  459.          or    bx,bx            ;is pointer 0?
  460.         endif
  461.         jz    endcheckkeys        ;if no user hook repeat loop
  462.  
  463.         ; There is an idle function to be called, if it has not yet
  464.         ; been called we will call it twice.  The first time with
  465.         ; a parameter of 0 so it can set things up, immediately
  466.         ; followed by a call with a parameter of 1 which says
  467.         ; we are waiting.  When a parameter of 1 is passed to
  468.         ; the idle function it (the idle function) can return
  469.         ; keyboard codes.  We assume that this is a 16 bit code
  470.         ; with the scan code in the upper 8 bits and the ascii
  471.         ; code in the lower 8 bits.  If the idle function is not
  472.         ; returning a keyboard/scan code it returns the value
  473.         ; NOKEY (0xffff)
  474.  
  475.         if    _LDATA
  476.          mov    es,di
  477.          mov    al,es:IdleState     ;AL=IdleState Variable
  478.         else
  479.          mov    al,IdleState        ;AL=IdleState Variable
  480.         endif
  481.         cmp    al,DONTKNOW        ;have we initialized it?
  482.         jnz    idle1            ;if so skip initialization
  483.         mov    ax,IDLEINIT        ;initialize the idle function
  484.         call    DispatchIdle
  485.         if    _LDATA
  486.          mov    es:IdleState,IDLEIDLE    ;advance state
  487.         else
  488.          mov    IdleState,IDLEIDLE
  489.         endif
  490.  
  491. idle1:        mov    ax,IDLEIDLE        ;we are now idling
  492.         call    DispatchIdle
  493.         cmp    ax,NOKEY        ;was value returned?
  494.         jz    endcheckkeys        ;if not go to bottom of loop
  495.  
  496.         ; The idle function has returned a 16 bit keyboard code.
  497.         ; We act as though this value was actually received from
  498.         ; the ROM BIOS.
  499.  
  500.         mov    [si+Char],al
  501.         mov    [si+Scan],ah        ;save in structure
  502.         mov    [si+Status],KEYACTIVITY ;say there is key activity
  503.         if    GETKEYCODE
  504.          or     al,al            ;is it extended?
  505.          jz     xltkey6        ;if so put in structure
  506.          xor     ah,ah            ;else zero high 8 bits
  507. xltkey6:     mov     [si+GetKeyVal],ax
  508.         endif
  509.         jmp    short NewKeyExit
  510. endcheckkeys:    jmp    CheckShift        ;repeat thyself
  511.  
  512.         ; When execution gets to this point it is time to go back
  513.         ; to the caller.  Before returning we must see if we have
  514.         ; initialized an idle function.  If we have then we must
  515.         ; call it with a parameter of IDLESHUTDOWN.  The return value
  516.         ; of this function is equal to the Status member of the
  517.         ; structure.
  518. NewKeyExit:
  519.         if    _LDATA
  520.          mov    es,di
  521.          cmp    es:IdleState,DONTKNOW
  522.         else
  523.          cmp    IdleState,DONTKNOW
  524.         endif
  525.         jz    noidleshutdown
  526.         mov    ax,IDLESHUTDOWN
  527.         call    DispatchIdle
  528. noidleshutdown:
  529.         if    GETKEYCODE
  530.          mov     ax,[si+GetKeyVal]     ;return value of GetKeyVal
  531.          cmp     ax,NOKEY         ;make sure it is not NOKEY
  532.          jnz     getkeyhasval
  533.         endif
  534.         mov    ax,[si+Status]        ;return value == Status
  535. getkeyhasval:
  536.         if    _LDATA
  537.          pop    ds            ;Restore original DS
  538.         endif
  539.         pop    es
  540.         cproce
  541.  
  542.  
  543. ;/*
  544. ;**  void
  545. ;** inikbd(unsigned option,GKEY *table)
  546. ;**
  547. ;** ARGUMENT(s)
  548. ;**  (unsigned        option  -       values for Option member of structure.
  549. ;**  (GKEY *)          table   -       points to the GKEY data structure.
  550. ;**
  551. ;** DESCRIPTION
  552. ;**  inikbd() is responsible for initializing the GKEY data structure to
  553. ;**  the following values:
  554. ;**
  555. ;**     Option      =     option parameter
  556. ;**     Status      =     0
  557. ;**     Mstat         =     0
  558. ;**     Char         =     0
  559. ;**     Scan         =     0
  560. ;**     Shift         =     Current Shift Status
  561. ;**     MouseX      =     Current Mouse X position (if mouse attached)
  562. ;**     MouseY      =     Current Mouse Y position (if mouse attached)
  563. ;**     MouseBtns     =     Current Mouse Button information (if mouse attached)
  564. ;**     UserHook     =     (unsigned (*)())0
  565. ;**     UserData     =     (void *)0
  566. ;**     GetKeyVal     =     NOKEY
  567. ;**
  568. ;** RETURNS
  569. ;**  void
  570. ;**
  571. ;** AUTHOR
  572. ;**  ""   Tue 01-Nov-1988    17:52:39
  573. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  574. ;**
  575. ;** MODIFICATIONS
  576. ;**
  577. ;*/
  578.         cproc    inikbd
  579.         if    _LDATA
  580.          push    ds
  581.          lds    si,parm2_        ;DS:SI -> GKEY
  582.         else
  583.          mov    si,parm2_        ;DS:SI -> GKEY
  584.         endif
  585.         mov    ax,parm1_        ;AX=option parameter
  586.         mov    [si+Option],ax
  587.         xor    ax,ax
  588.         mov    [si+Status],ax
  589.         mov    [si+Mstat],ax
  590.         mov    [si+Char],al
  591.         mov    [si+Scan],al
  592.         mov    [si+GetKeyVal],NOKEY
  593.         if    _LDATA
  594.          mov    word ptr [si+UserData],ax
  595.          mov    word ptr [si+UserData+2],ax
  596.         else
  597.          mov    [si+UserData],ax
  598.         endif
  599.         if    _LCODE
  600.          mov    word ptr [si+UserHook],ax
  601.          mov    word ptr [si+UserHook+2],ax
  602.         else
  603.          mov    [si+UserHook],ax
  604.         endif
  605.         call    GetShiftWord        ;get shift word to AX
  606.         mov    [si+Shift],ax        ;and save in structure
  607.         call    MousePresent        ;is mouse present
  608.         or    ax,ax
  609.         jnz    initmouse
  610.         mov    [si+MouseX],ax        ;if no mouse init to 0
  611.         mov    [si+MouseY],ax
  612.         mov    [si+MouseBtns],ax
  613.         jmp    short skipmouse
  614. initmouse:    mov    ax,MOUGETBSTMPOS    ;call mouse driver for current info
  615.         int    MOUSECALL
  616.         test    [si+Option],MOUSEMAPPING
  617.         jz    nomapinit
  618.         shr    cx,1            ;divide mouse X & Y positons
  619.         shr    cx,1            ;by 8
  620.         shr    cx,1
  621.         shr    dx,1
  622.         shr    dx,1
  623.         shr    dx,1
  624. nomapinit:    mov    [si+MouseX],cx        ;save mouse x position
  625.         mov    [si+MouseY],dx        ;save mouse y position
  626.         mov    [si+MouseBtns],bx    ;save mouse button information
  627. skipmouse:
  628.         if    _LDATA
  629.          pop    ds
  630.         endif
  631.         cproce
  632.  
  633.  
  634. ;/*
  635. ;**  int
  636. ;** mousinst(void)
  637. ;**
  638. ;** ARGUMENT(s)
  639. ;**  (none)
  640. ;**
  641. ;** DESCRIPTION
  642. ;**  Checks for presence of mouse driver.
  643. ;**
  644. ;** RETURNS
  645. ;**  TRUE  (1) = Mouse is installed.
  646. ;**  FALSE (0) = Mouse is NOT installed.
  647. ;**
  648. ;** AUTHOR
  649. ;**  "" Wed 02-Nov-1988    15:39:49
  650. ;**   Copyright (C)1988-1990  Greenleaf Software Inc. All Rights Reserved.
  651. ;**
  652. ;** MODIFICATIONS
  653. ;**
  654. ;*/
  655.         cproc    mousinst
  656.         call    MousePresent        ;MousePresent returns with AX==1 if present,
  657.                         ;AX==0 if not present.
  658.         cproce
  659.  
  660. ;/*
  661. ;**  void
  662. ;** ctlmscur(int option)
  663. ;**
  664. ;** ARGUMENT(s)
  665. ;**  (int)    option    -    1 == show cursor
  666. ;**                0 == hide cursor
  667. ;**
  668. ;** DESCRIPTION
  669. ;**  Controls whether or not the mouse cursor is visible.  This function
  670. ;**  does its own test for mouse present making it always safe to call.
  671. ;**
  672. ;** RETURNS
  673. ;**  void (nothing)
  674. ;**
  675. ;** AUTHOR
  676. ;**  ""   Wed 02-Nov-1988    13:21:59
  677. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  678. ;**
  679. ;** MODIFICATIONS
  680. ;**
  681. ;*/
  682.         cproc    ctlmscur
  683.         if    _LDATA
  684.          push    es
  685.          mov    ax,seg MouseInstalled
  686.          mov    es,ax
  687.          mov    al,es:MouseInstalled
  688.          pop    es
  689.         else
  690.          mov   al,MouseInstalled    ;AL = MouseInstalled Variable
  691.         endif
  692.         cmp    al,1            ;MouseInstalled==1==mouseinstalled
  693.         jz    ctlmscur1        ;O.K. to make mouse calls
  694.         or    al,al            ;is mouse not present
  695.         jz    ctlmscurexit        ;if not skip this
  696.         call    MousePresent        ;is mouse with us?
  697.         or    ax,ax
  698.         jz    ctlmscurexit        ;if not get out
  699. ctlmscur1:    mov    ax,MOUHIDECURSOR    ;assume hide
  700.         cmp    word ptr parm1_,0    ;check assumption
  701.         jz    ctlmsset
  702.         mov    ax,MOUSHOWCURSOR    ;correct assumption
  703. ctlmsset:    int    MOUSECALL
  704. ctlmscurexit:
  705.         cproce
  706.  
  707. ;/*
  708. ;**  void setcbvec(void (*)())
  709. ;**
  710. ;** ARGUMENT(s)
  711. ;**  (int (*)())    -    pointer to new interrupt routine
  712. ;**
  713. ;** DESCRIPTION
  714. ;**  Sets a users control break handler.  This function also stores the
  715. ;**  original value in an internal static variable.
  716. ;**
  717. ;** RETURNS
  718. ;**  void
  719. ;**
  720. ;** AUTHOR
  721. ;**  ""    Thu 03-Nov-1988    09:33:41
  722. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  723. ;**
  724. ;** MODIFICATIONS
  725. ;**
  726. ;*/
  727.         cproc    setcbvec
  728.         push    es
  729.         push    ds
  730.         mov    ax,DOSGETVECTOR*256+DOSCBREAK
  731.         int    DOSCALL         ;get current settings first
  732.         mov    word ptr PrevCtlBreak,bx
  733.         mov    word ptr PrevCtlBreak+2,es
  734.         if    _LCODE
  735.          les    bx,parm1_
  736.          mov    word ptr CtlBreakAddress,bx
  737.          mov    word ptr CtlBreakAddress+2,es
  738.         else
  739.          mov    bx,parm1_
  740.          mov    CtlBreakAddress,bx
  741.         endif
  742.         mov    ax,seg CBDispatch
  743.         mov    ds,ax
  744.         mov    dx,offset CBDispatch
  745.         mov    ax,DOSSETVECTOR*256+DOSCBREAK
  746.         int    DOSCALL
  747.         pop    ds
  748.         pop    es
  749.         cproce
  750.  
  751.  
  752. ;/*
  753. ;**  void rescbvec(void)
  754. ;**
  755. ;** ARGUMENT(s)
  756. ;**  none
  757. ;**
  758. ;** DESCRIPTION
  759. ;**  Restores previously stored control break handler.
  760. ;**
  761. ;** RETURNS
  762. ;**  void
  763. ;**
  764. ;** AUTHOR
  765. ;**  "" Thu 03-Nov-1988 13:02:19
  766. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  767. ;**
  768. ;** MODIFICATIONS
  769. ;**
  770. ;*/
  771.         cproc    rescbvec
  772.         push    ds
  773.         lds    dx,PrevCtlBreak
  774.         mov    ax,ds
  775.         or    ax,dx
  776.         jz    skipreset
  777.         mov    ax,DOSSETVECTOR*256+DOSCBREAK
  778.         int    DOSCALL
  779. skipreset:    pop    ds
  780.         cproce
  781.  
  782.  
  783.  
  784. ;/*
  785. ;**  int
  786. ;** cntrlbrk(int option)
  787. ;**
  788. ;** ARGUMENT(s)
  789. ;**  (int)    option        -    Determines whether to set break on, off
  790. ;**                    or just inquire the current setting.
  791. ;**
  792. ;**                    0 = set current state OFF
  793. ;**                    1 = set current state ON
  794. ;**                    2 = inquire current state only
  795. ;**
  796. ;** DESCRIPTION
  797. ;**  Interface with MS-DOS control break checking/setting function.
  798. ;**
  799. ;** RETURNS
  800. ;**  option==0 or option==1 return the previous condition of Ctrl-Break
  801. ;**  checking.    option=2 return the current state of Ctrl-Break checking.
  802. ;**
  803. ;** AUTHOR
  804. ;**  ""   Wed 09-Nov-1988    15:24:21
  805. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  806. ;**
  807. ;** MODIFICATIONS
  808. ;**
  809. ;*/
  810.         cproc    cntrlbrk
  811.         mov    ax,CONTROLBRKCHK*256+0    ;get current state
  812.         int    DOSCALL         ;from DOS
  813.         xor    dh,dh            ;dx=current value
  814.         mov    ax,dx            ;put in ax for possible return
  815.         mov    dl,parm1_        ;get parameter from user
  816.         cmp    dl,2            ;just want to read current value?
  817.         jz    cntrlbrkout        ;if so leave
  818.         push    ax            ;else save for later
  819.         mov    ax,CONTROLBRKCHK*256+1    ;set current state
  820.         int    DOSCALL         ;dl=users parameter
  821.         pop    ax            ;get previous value back
  822. cntrlbrkout:
  823.         cproce
  824.  
  825. ;/*
  826. ;**  void
  827. ;** setmctyp(unsigned select,unsigned scrnmaskstart,unsigned curmaskstop)
  828. ;**
  829. ;** ARGUMENT(s)
  830. ;**  (unsigned)        select        -    Specifies which cursor is selected
  831. ;**                           0 = software text cursor.
  832. ;**                           1 = hardware text cursor.
  833. ;**
  834. ;**  (unsigned)        scrnmaskstart    -    Specifies screen mask if software
  835. ;**                        text cursor is selected.  Specifies
  836. ;**                        starting scan line number when the
  837. ;**                        hardware text cursor has been selected.
  838. ;**
  839. ;**  (unsigned)        curmaskstop    -    Specifies cursor mask if software
  840. ;**                        text cursor is selected.  Specifies
  841. ;**                        ending scan line number when the
  842. ;**                        hardware text cursor has been selected.
  843. ;**
  844. ;** DESCRIPTION
  845. ;**  Selects the software or hardware text cursor.  Your program must call
  846. ;**  ctlmscur(1) to actually display the cursor.
  847. ;**
  848. ;** RETURNS
  849. ;**  void
  850. ;**
  851. ;** AUTHOR
  852. ;**  ""   Wed 09-Nov-1988    15:24:21
  853. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  854. ;**
  855. ;** MODIFICATIONS
  856. ;**
  857. ;*/
  858.         cproc    setmctyp
  859.         if    _LDATA
  860.          push    es
  861.          mov    ax,seg MouseInstalled
  862.          mov    es,ax
  863.          mov    al,es:MouseInstalled
  864.          pop    es
  865.         else
  866.          mov   al,MouseInstalled    ;AL = MouseInstalled Variable
  867.         endif
  868.         cmp    al,1            ;MouseInstalled==1==mouseinstalled
  869.         jz    setmctype        ;O.K. to make mouse calls
  870.         or    al,al            ;is mouse not present
  871.         jz    setmctypexit        ;if not skip this
  872.         call    MousePresent        ;is mouse with us?
  873.         or    ax,ax
  874.         jz    setmctypexit        ;if not get out
  875. setmctype:    mov    bx,parm1_        ;bx=select
  876.         mov    cx,parm2_        ;cx=screen mask / scan start
  877.         mov    dx,parm3_        ;dx=cursor mask / scan stop
  878.         mov    ax,MOUSETTXTCURSOR    ;ax=function number
  879.         int    MOUSECALL        ;call mouse driver
  880. setmctypexit:
  881.         cproce
  882.  
  883.  
  884. ;/*
  885. ;**  void
  886. ;** setmxy(unsigned minvert,unsigned maxvert)
  887. ;**
  888. ;** ARGUMENT(s)
  889. ;**  maxvert        -    minimum vertical cursor position
  890. ;**  maxhoriz        -    maximum vertical cursor position
  891. ;**
  892. ;** DESCRIPTION
  893. ;**  Sets the minimum and maximum vertical mouse positions.
  894. ;**
  895. ;** RETURNS
  896. ;**  void
  897. ;**
  898. ;** AUTHOR
  899. ;**  ""   Thu 15-Dec-1988    10:07:55
  900. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  901. ;**
  902. ;** MODIFICATIONS
  903. ;**
  904. ;*/
  905.         cproc    setmxy
  906.         if    _LDATA
  907.          push    es
  908.          mov    ax,seg MouseInstalled
  909.          mov    es,ax
  910.          mov    al,es:MouseInstalled
  911.          pop    es
  912.         else
  913.          mov   al,MouseInstalled    ;AL = MouseInstalled Variable
  914.         endif
  915.         cmp    al,1            ;MouseInstalled==1==mouseinstalled
  916.         jz    oksetmaxy         ;O.K. to make mouse calls
  917.         or    al,al            ;is mouse not present
  918.         jz    setmaxyexit        ;if not skip this
  919.         call    MousePresent        ;is mouse with us?
  920.         or    ax,ax
  921.         jz    setmctypexit        ;if not get out
  922. oksetmaxy:    mov    cx,parm1_        ;bx=min y
  923.         mov    dx,parm2_        ;dx=max y
  924.         mov    ax,MOUSESETMAXY     ;ax=function number
  925.         int    MOUSECALL        ;call mouse driver
  926. setmaxyexit:
  927.         cproce
  928.  
  929.         subttl    ***[ Internal Helper Routines (Not C Functions) ]***
  930.         page
  931.  
  932. ;/*
  933. ;**  interrupt far
  934. ;** CBDispatcher()
  935. ;**
  936. ;** ARGUMENT(s)
  937. ;**  none
  938. ;**
  939. ;** DESCRIPTION
  940. ;**  Gets control when the control break happens, calls users C routine.
  941. ;**
  942. ;**
  943. ;** RETURNS
  944. ;**  via IRET instruction
  945. ;**
  946. ;** AUTHOR
  947. ;**  ""   Thu 03-Nov-1988    12:34:44
  948. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  949. ;**
  950. ;** MODIFICATIONS
  951. ;**
  952. ;*/
  953. CBDispatch    proc    far
  954.         push    ax            ;save registers
  955.         push    cx
  956.         push    dx
  957.         push    bx
  958.         push    sp
  959.         push    bp
  960.         push    si
  961.         push    di
  962.         push    ds
  963.         push    es
  964.         mov    bp,sp
  965.         ifdef    TURBOC
  966.          if    _HUGE
  967.           mov    ax,es:_duserin_DATA
  968.          else
  969.           mov    ax,DGROUP
  970.          endif
  971.         else
  972.          ifndef AZTEC
  973.           mov    ax,DGROUP
  974.          else
  975.           mov    ax,dataseg
  976.          endif
  977.         endif
  978.         mov    ds,ax
  979.         cld
  980.         sti
  981.         call    CtlBreakAddress
  982.         mov    sp,bp
  983.         pop    es
  984.         pop    ds
  985.         pop    di
  986.         pop    si
  987.         pop    bp
  988.         pop    sp
  989.         pop    bx
  990.         pop    dx
  991.         pop    cx
  992.         pop    ax
  993.         iret
  994. CBDispatch    endp
  995.  
  996. ;/*
  997. ;**  static unsigned 
  998. ;** DispatchIdle(void)
  999. ;**
  1000. ;** ARGUMENT(s)
  1001. ;**  No formal parameters, however the following registers must be set
  1002. ;**  up:
  1003. ;**        AX = parameter to be passed to idle function (0, 1 or 2)
  1004. ;**
  1005. ;**          Small Data Models:
  1006. ;**        DS    = points to default data segment
  1007. ;**        DS:SI = points to GKEYdata structure
  1008. ;**          Large Data Models:
  1009. ;**        DS:SI = points to GKEYdata structure
  1010. ;**        DI    = contains the address of the default data segment
  1011. ;** DESCRIPTION
  1012. ;**  Calls user defined idle function.    This function CANNOT be called from C.
  1013. ;**
  1014. ;** RETURNS
  1015. ;**  Return value from user idle function (in AX).
  1016. ;**
  1017. ;** AUTHOR
  1018. ;**  ""   Wed 02-Nov-1988    11:40:27
  1019. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  1020. ;**
  1021. ;** MODIFICATIONS
  1022. ;**
  1023. ;*/
  1024. DispatchIdle    proc    near
  1025.         push    bx            ;save our registers
  1026.         push    cx
  1027.         push    si
  1028.         push    di
  1029.         push    es
  1030.         if    _LDATA
  1031.          push    ds
  1032.          push    ax            ;parameter for call
  1033.          mov    ax,ds
  1034.          mov    es,ax            ;ES:SI point to GKEY structure
  1035.          mov    ds,di            ;make di point to default data
  1036.          if    _LCODE
  1037.           call     dword ptr es:[si+UserHook]
  1038.          else
  1039.           call     es:[si+UserHook]
  1040.          endif
  1041.          add    sp,2            ;re-align stack
  1042.          pop    ds
  1043.         else
  1044.          push     ax            ;parameter for call
  1045.          if    _LCODE
  1046.           call    dword ptr es:[si+UserHook]
  1047.          else
  1048.           call     [si+UserHook]
  1049.          endif
  1050.          add    sp,2            ;re-align stack
  1051.         endif
  1052.         pop    es            ;restore our registers
  1053.         pop    di
  1054.         pop    si
  1055.         pop    cx
  1056.         pop    bx
  1057.         ret
  1058. DispatchIdle    endp
  1059.  
  1060. ;/*
  1061. ;**  static int
  1062. ;** ExtendedKbdFunc(void)
  1063. ;**
  1064. ;** ARGUMENT(s)
  1065. ;**  none
  1066. ;**
  1067. ;** DESCRIPTION
  1068. ;**  Determine if the enhanced keyboard functions are supported.  Use the method
  1069. ;**  described in the IBM Personal System/2 and Personal Computer BIOS
  1070. ;**  Interface Technical Reference.  This function CANNOT be called from C.
  1071. ;**
  1072. ;** RETURNS
  1073. ;**  0x10 = Extended keyboard functions supported.
  1074. ;**  0x00 = Extended keyboard functions are NOT supported.
  1075. ;**
  1076. ;** AUTHOR
  1077. ;**  ""   Wed 02-Nov-1988    09:33:58
  1078. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  1079. ;**
  1080. ;** MODIFICATIONS
  1081. ;**
  1082. ;*/
  1083. ExtendedKbdFunc proc    near
  1084.         mov    cx,0ffffh        ;write scan code/character code
  1085.         mov    ah,XKBDWRITE        ;combination FFFF to buffer
  1086.         int    KBDCALL
  1087.         mov    dl,16            ;dl = counter
  1088. extchkloop:    mov    ah,XKBDREAD
  1089.         int    KBDCALL
  1090.         inc    ax            ;check for return of FFFF
  1091.         jz    isextended        ;if so hop out
  1092.         dec    dh            ;else try again
  1093.         jnz    extchkloop        ;repeat 16 times
  1094.         xor    ax,ax            ;say not installed
  1095.         jmp    short extkbex
  1096. isextended:    mov    ax,XKBDREAD-KBDREAD    ;is extended, return value
  1097. extkbex:    ret
  1098. ExtendedKbdFunc endp
  1099.  
  1100. ;/*
  1101. ;**  static int
  1102. ;** MousePresent(void)
  1103. ;**
  1104. ;** ARGUMENT(s)
  1105. ;**  none
  1106. ;**
  1107. ;** DESCRIPTION
  1108. ;**  Determine if mouse is installed or not.  This function CANNOT be
  1109. ;**  called from C.  The method used for checking is documented in
  1110. ;**  the Microsoft Mouse Programmers Reference Guide.  This function also
  1111. ;**  updates the local variable indicating whether or not a mouse is installed.
  1112. ;**
  1113. ;** RETURNS (AX)
  1114. ;**  TRUE  (1) = Mouse is installed.
  1115. ;**  FALSE (0) = Mouse is NOT installed.
  1116. ;**
  1117. ;** AUTHOR
  1118. ;**  ""   Tue 01-Nov-1988    17:33:16
  1119. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  1120. ;**
  1121. ;** MODIFICATIONS
  1122. ;**
  1123. ;*/
  1124. MousePresent    proc    near
  1125.         mov    ax,DOSGETVECTOR*256+MOUSECALL
  1126.         int    DOSCALL         ;ES:BX points to interrupt handler
  1127.         xor    ax,ax            ;assume return value to false
  1128.         mov    cx,es            ;see if 0000:0000
  1129.         or    cx,bx            ;check assumption
  1130.         jz    mouinnom
  1131.         cmp    byte ptr es:[bx],0cfh
  1132.         jz    mouinnom        ;check another assumption
  1133.         inc    ax            ;assumption wrong
  1134. mouinnom:
  1135.         if    _LDATA
  1136.          push    ds
  1137.          mov    cx,seg MouseInstalled
  1138.          mov    ds,cx
  1139.          mov    MouseInstalled,al
  1140.          pop    ds
  1141.         else
  1142.          mov    MouseInstalled,al
  1143.         endif
  1144.         ret
  1145. MousePresent    endp
  1146.  
  1147. ;/*
  1148. ;**  static unsigned 
  1149. ;** GetShiftWord(void)
  1150. ;**
  1151. ;** ARGUMENT(s)
  1152. ;**  none
  1153. ;**
  1154. ;** DESCRIPTION
  1155. ;**  Gets 16 bits of shift information, KB_FLAG is returned in AL,
  1156. ;**  KB_FLAG1 is returned in AH.  This function CANNOT be called
  1157. ;**  from C.
  1158. ;**
  1159. ;** AUTHOR
  1160. ;**  ""   Tue 01-Nov-1988    13:43:03
  1161. ;**   Copyright (C)1988-1990 Greenleaf Software Inc. All Rights Reserved.
  1162. ;**
  1163. ;** MODIFICATIONS
  1164. ;**
  1165. ;*/
  1166. GetShiftWord    proc    near
  1167.         mov    ax,ROMBIOSSEG
  1168.         mov    cx,ds            ;save DS in CX
  1169.         mov    ds,ax            ;DS = Rom bios data segment
  1170.         mov    bx,KBFLAG
  1171.         mov    ax,[bx]            ;get keyboard flags to AX
  1172.         mov    ds,cx            ;restore DS from CX
  1173.         ret
  1174. GetShiftWord    endp
  1175.  
  1176.         endps
  1177.         end
  1178.