home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CDOSDSK4.ZIP / CDOSDSK4.TD0 / XIOS / KEYBOARD.A86 < prev    next >
Encoding:
Text File  |  1989-01-26  |  42.4 KB  |  1,507 lines

  1. ; KEYBOARD.A86
  2. title 'Keyboard ISR'
  3. pagesize 60+11
  4. ;************************************************
  5. ;*                        *
  6. ;*    KEYBOARD INTERRUPT HANDLER        *
  7. ;*    CDOS 6.0 XIOS                *
  8. ;*    DRI OS ENGR, JMB, GMS            *
  9. ;*                        *
  10. ;************************************************
  11. ; Modifications:
  12. ; 6.x
  13. ;  6 JAN 89 -- throw away scan code if re-entering              GMS
  14. ; 22 Nov 88 -- Allow enhanced DEL_SCAN through GERMAN etc          GMS
  15. ;  2 Nov 88 -- reload load DS in save_buf, stack swap only once          IJ
  16. ; 10 OCT 88 -- allow CRTL/ALT dead keys                      GMS
  17. ;  6 SEP 88 -- do not allow SWITCH on enhanced arrow keys          GMS
  18. ; 22 JUN 88 -- Fix problem with FRENCH & GERMAN enhanced          GMS
  19. ; 19 FEB 88 -- Bug fix for national enhanced keyboard on model 30         GMS
  20. ; 18 FEB 88 -- JMP to MP_RESET@                          GMS
  21. ; 6.0
  22. ; 18 NOV 87 -- re-enable AST color card support                  GMS
  23. ; 12 NOV 87 -- ROS keyboard data areas mapped for PC terminals          GMS
  24. ; 11 NOV 87 -- bug fix re ALT GR key on enhanced keyboards          GMS
  25. ;  7 NOV 87 -- keyboard interrupt stack increased (ran out on DELL 286)      JW
  26. ;  3 NOV 87 -- print screen not checked if CONTROL SHIFT          GMS
  27. ;  3 NOV 87 -- throw away CTRL/NUMLOCK and PAUSE keys              GMS
  28. ;  1 NOV 87 -- removed S_REAL BDOS call - we now hardware reset the 386   JW
  29. ; 30 OCT 87 -- CNTRL BREAK handled by XIOS not ROS              GMS
  30. ; 17 SEP 87 -- fix for 84 german keyboard numpad keys              GMS
  31. ;  7 SEP 87 -- code added for V386pc option                  GMS
  32. ;  8 JUN 87 -- disable MMU on Ctl/Alt/Del w/ hw EEMM driver          JW
  33. ; 5.2
  34. ; 13 MAY 87 -- Some National Keyboard changes added              GMS
  35. ;  2 APR 87 -- Less stack usage for calls to ROS keyboard int routine      GMS
  36. ; 18 MAR 87 -- Add support for enhanced keyboards              GMS
  37. ;        Test Setup byte for disabling of CTRL\ALT\DEL.
  38. ; 28 JAN 87 -- CDOS 386 Ctrl/Alt/Del - system call to reset to real mode- GMS
  39. ; 5.1
  40. ;  9 JAN 87 -- Alt key in national check upto '=' key            - GMS
  41. ; 12 DEC 86 -- Test if AT/compatible and disable keyboard - wyse AT bug - GMS
  42. ; 26 NOV 86 -- Nat keyboards return pc scan code for ALT keys in PCMODE - GMS
  43. ; 11 NOV 86 -- Bug fix for old ros kb/buffer on old COMPAQ machines    - GMS
  44. ; 25 SEP 86 -- European keyboard support added                - GMS
  45. ;  5 SEP 86 -- fix AT isr reentrancy on caps-lock, num-lock and scroll-lock
  46. ; 12 AUG 86 -- NSEOI to SEOI (thx RH,JF)
  47. ; 19 JUN 86 -- make wmenu comes up if CAPS-LOCK on
  48. ; 27 MAY 86 -- add cntl-break isr
  49. ;  9 MAY 86 -- if FULL screen key w/ no wmenu, handle
  50. ; 29 APR 86 -- don't read AT kbd status if we've been preambled
  51. ; 16 APR 86 -- set keyboard isr mx flag for timer isr
  52. ;  1 APR 86 -- fix SYS-REQ and cntl-NUMLOCK bug
  53. ;  8 NOV 85 -- add cntl-pad-5 to toggle AST enhancment
  54. ;  7 JUN 85 -- update 4.1 ASM86 XIOS to 5.0 RASM86
  55. ; 23 OCT 85 -- rewrite to use ROS
  56.  
  57. ; include COPYRITE.TXT
  58.  
  59. nolist
  60. include CDOS.EQU
  61. include XIOS.EQU
  62. include PCHW.EQU
  63. include ROSDATA.EQU
  64. include ASCII.EQU
  65. include NAT.EQU
  66. list
  67. ; These have been included:
  68. ; include CDOS.EQU
  69. ; include XIOS.EQU
  70. ; include PCHW.EQU
  71. ; include ROSDATA.EQU
  72. ; include ASCII.EQU
  73. ; include NAT.EQU
  74.  
  75.  
  76.  
  77. CGROUP    group    CODE
  78. DGROUP    group    DATA
  79.  
  80. DATA    dseg
  81. public    switch_key$, wmenu_key$, prtsc_key$, key_flag$    ; for CONIN.A86
  82. public    switch_bits$                    ; for PUBDATA.A86
  83. public    keyboard_isr$                    ; for INIT.A86
  84. public    kbd_imhere$                    ; for INIT.A86
  85. public    cntl_break$                    ; for CONIN.A86
  86. if V386
  87. public    save_kbdata$                    ; for PCTERM.A86
  88. extrn    active_vc$:byte
  89. endif
  90. extrn    colsel_640$:word, ast_enhanced$:word        ; in WINDOWS1.A86
  91. extrn    ast_flag$:byte
  92. extrn    top_screen$:byte, im_here$:byte            ; in WINDOWS3.A86
  93. extrn    pc_at$:byte
  94. extrn    beep_counter$:byte                ; in ISRS.A86
  95. extrn    su_kbd_bits$:byte                ; in HEADER.A86
  96.  
  97.                             ; in NATDATA.A86
  98. extrn    NX_tmp_us_flg$ :byte,    NX_mode_table$    :byte
  99. extrn    NX_ascii$ :word,    NX_shift$ :word
  100. extrn    NX_ctrl$ :word
  101. extrn    NX_language$ :byte,    NX_kbd_type$ :byte
  102. extrn    NX_natnlmode$ :byte, NX_natnlstat$ :byte 
  103. extrn    NX_dead_key$ :byte, NX_ncasetbl$ :byte
  104. extrn    NX_n7to8tbl$ :byte, NX_n7to8chr$ :byte
  105. extrn   NX_deadtable$: word, NX_alt_table$ :byte, NX_dead_ascii$: word
  106. extrn    NX_alt_chars$: byte
  107. extrn    NX_dkeyv$ :word, NX_dkeyx$ :word
  108. extrn    NX_last_dkey$ :word, NX_dkey_buff$ :byte
  109. extrn    key_table$ :word, shift_table$ :word, control_table$ :word
  110. extrn    NX_nasciitable$ :word, NX_nshifttable$ :word, NX_nctrltable$ :word
  111. extrn   NX_ctrlalt$ :word, NX_ctrlalt_shft$ :word
  112.  
  113.  
  114.  
  115.     cseg
  116. public    i_keyboard@                    ; for INIT.A86
  117. public    keyboard_isr$
  118. public    NX_init@                    
  119. public    NX_scanstr@                    ; for LISTNAT.A86
  120. public    NX_conout_xlat@                    ; for WINDOWS1.A86
  121.  
  122. extrn    flagset@:near                    ; in HEADER.A86
  123. extrn    sysdat$:word
  124. extrn    disp_addr$    :dword
  125. extrn    ros_color@:near                    ; in WINDOWS1.A86
  126. extrn    point_vs@:near                    ; in WINDOWS3.A86
  127. extrn    io_list_normal@:near                ; 
  128. extrn    reset@:near                    ; in ISRS.A86
  129. if XM
  130. extrn    mp_reset@:near                    ; in EMM.A86
  131. endif
  132. if V386
  133. extrn    get_kbd_flags@:near                ; in PCTERM.A86
  134. endif
  135. eject
  136.  
  137. ;-----------
  138. i_keyboard@:
  139. ;-----------
  140. ; Use the ROS as much as possible for scan-code translation, etc., but
  141. ;  we must 1) do flagsets to wake up CONIN or WMENU; and 2) look for
  142. ;  screen-switch and WMENU key combinations which the ROS discards, and
  143. ;  do our own print-screen.
  144. ;    If AT and KBD STATUS is not exactly right, go to ROS ISR.
  145. ;    If RELEASE instead of MAKE, go directly to ROS ISR.
  146. ;    If MAKE, but not SWITCH, WMENU, or PRINT-SCREEN keys,
  147. ;     go to ROS ISR, flagset, then dispatch.
  148. ;    If SWITCH, WMENU, or PRINT-SCREEN, flagset, reset HW, then dispatch.
  149. ;    If AST key stroke, toggle word for mode switcher and hit port.
  150. ;     (12-4-85...don't hit port...it blanks the screen...too shocking)
  151. ;
  152. ; This ISR will set the flag specified in key_flag$, which will be
  153. ; CI_FLAG or WW_FLAG or ER_FLAG.  Conin or ww_key or the statline error handler
  154. ; must at that point check switch_key$, wmenu_key$, and prtsc_key$ if desired
  155. ; before calling ROS to return a "regular" keystroke.  Those three variables
  156. ; contain 0 if no screen-switch, wmenu-wake or full-window, or print-screen
  157. ; combination was typed.
  158.  
  159. ; There is a small interrupt window in the ROS keyboard ISR where a timer int
  160. ; might come in.  Our timer isr is significantly longer than ROS, and that
  161. ; apparently causes problems occasionally.  Hard to pinpoint exactly where,
  162. ; but the timer isr now checks the kbd_imhere flag set here and just irets.
  163. ; This hits our performance, but not significantly.
  164.  
  165. ; Enhanced keyboards have extra ALT key which can only be truly recognized
  166. ; by a scan code of 0E0H which preceeds both the make and break codes.
  167. ; This extra ALT key is used by international keyboards for characters on
  168. ; some keys which have 3/4 chars per key.
  169.  
  170.     cli                        ; in case someone pre-
  171.     cld                        ;; ambled us
  172.     push    ds
  173.     mov    ds,sysdat
  174.     inc    kbd_imhere$                ;; indicate our presence
  175.     push    ax                    ;;
  176.     test    pc_at$,0ffh                ;; are we on an AT
  177.      jz    not_at1                    ;; jump if no
  178.     mov    al,DIS_KBD                ;; disable keyboard
  179.     call    exec                    ;; execute command
  180. not_at1:
  181.     push    ds                    ;; check to see if we've
  182.     sub    ax,ax                    ;;
  183.     mov    ds,ax                    ;;  been preambled
  184.     mov    ax,cs                    ;;
  185.     cmp    .26h,ax                    ;; int 9
  186.     pop    ds                    ;;
  187.      jne    been_preambled                ;; can't re-read status
  188.  
  189.     test    pc_at$,0ffh                ;; are we on an AT
  190.      jz    not_at                    ;; jump if no
  191.     in    al,AT_KBD_STATUS            ;; then check keyboard
  192.     test    al,KEY_READY                ;; hunky-dory?
  193.      jnz    been_preambled
  194.      jmp    jmp_to_ros                ;; if no, off to ROS
  195. been_preambled:
  196. not_at:
  197.     in    al,KBD_DATA                ;; get the scan code
  198.     cmp    NX_language$,0                ;; U.S keyboard?
  199.      je    not_nat                    ;; avoid ALT GR test
  200.     test    NX_natnlstat$,NX_nkbd_bit
  201.      jz    not_nat                    ;; not national
  202.         
  203.     test    last_char,HC                ;; was last char hidden
  204.      jz    not_alt_gr                ;; no..
  205.     cmp    al,ALT                    ;; is this one ALT
  206.      jne    test_alt_br                
  207.     or    alt_gr,ALT_GR_BIT            ;; set ALT GR status
  208. test_alt_br:
  209.     cmp    al,ALT+80h                ;; ALT break key
  210.      jne    not_alt_gr
  211.     and    alt_gr,not ALT_GR_BIT            ;; yes .. reset status
  212. not_alt_gr:
  213.     and    last_char,not HC            ;; clear hidden flag
  214.     cmp    al,HIDDEN_KEY
  215.      jne    not_nat
  216.     or    last_char,HC                ;; set flag
  217. not_nat:
  218.     cmp    al,0FAh                    ;; is it ACK
  219.     jne    call_to_ros
  220.      jmp    jmp_to_ros                ;; yes go direct to ros
  221.  
  222. if not V386
  223. call_to_ros:
  224.     test    al,80h                    ;; break?
  225.      jz    not_break                ;; no, so continue
  226. ;; We're going to call direct to ROS
  227.     mov    ax,PC_SEGMENT        
  228.     mov    ds,ax            ;* point to the nether region
  229.     mov    ax,buffer_tail_40    ;;* buffer head
  230.     mov    ds,sysdat
  231.     mov    buf_tail,ax        ;;* save it
  232.     pop    ax ! pop ds        ;; pop registers to save stack
  233.  
  234.     pushf                ;; fake an int
  235.     callf    keyboard_isr$        ;;
  236.  
  237.     push    ds ! push ax        ;; save registers
  238.     mov    ax,PC_SEGMENT        ;* in buffer 
  239.     mov    ds,ax            ;* point to the nether region
  240.     mov    ax,buffer_tail_40    ;;* buffer head
  241.     mov    ds,sysdat
  242.     cmp    ax,buf_tail        ;;* compare to previous start
  243.      jne    is_char            ;;* char inserted so wake process
  244.     dec    kbd_imhere$        ;; now we're done
  245.     pop    ax ! pop ds
  246.     iret                ;; AT keyboard has been re-enabled
  247.                     ;; by the ROS keyboard ISR
  248. endif
  249. if V386
  250. ;; We're going to call to ROS at sometime
  251. ;; so first we must ensure correct keyboard flag
  252. ;; data is in the ROS data area..
  253. call_to_ros:
  254.     cmp    kbd_imhere$,1
  255.     jne    call_ros        ; don't resave
  256.     push    cx
  257.     push    es
  258.     push    ax
  259.     push si ! push di
  260.     cmp    active_vc$,NUM_VIR_CONS
  261.     jae    not_main        ; must be serial in context
  262.     push    ds            ; else update save area from ROS
  263.     push ds ! pop es
  264.     mov    ax,PC_SEGMENT        ; point at ROS data
  265.     mov    ds,ax
  266.     mov    si,offset kb_flag_40     ; keyboard data area
  267.     mov    di,offset save_kbdata$    ; save area
  268.     mov    cx,39
  269.     rep    movsb            ; save kbd flags and buffer
  270.     pop    ds
  271. not_main:
  272.     mov    ax,PC_SEGMENT        
  273.     mov    es,ax
  274.     mov    si,offset save_kbdata$    ; get saved ROS params
  275.     mov    di,offset kb_flag_40    ; and switch in
  276.     mov    cx,39
  277.     rep    movsb
  278.     pop di ! pop si
  279.     pop    ax
  280.     pop    es
  281.     pop    cx
  282. call_ros:
  283.     test    al,80h            ;; break char ?
  284.     jnz    save_buf
  285.      jmp    not_break        ;; no, so continue - keyboard flags
  286.                     ;; restored on exit
  287. save_buf:                    
  288.     mov    ax,PC_SEGMENT        
  289.     mov    ds,ax            ;* point to the nether region
  290.     mov    ax,buffer_tail_40    ;;* buffer head
  291.     mov    ds,sysdat
  292.     mov    buf_tail,ax        ;;* save it
  293.     pop    ax ! pop ds        ;; pop registers to save stack
  294.  
  295.     pushf                ;; fake an int
  296.     callf    keyboard_isr$        ;;
  297.  
  298.     cli
  299.     cld
  300.     push    ds ! push ax        ;; save registers
  301.     mov    ax,PC_SEGMENT        ;#IJ - reload seg register
  302.     mov    ds,ax            ;(corrupted by pop/push to save stack)
  303.     mov    ax,ds:buffer_tail_40    ;;* buffer head from ROS
  304.     mov    ds,sysdat
  305.     cmp    ax,buf_tail        ;;* compare to previous start
  306.      jne    is_char            ;;* char inserted so wake process
  307.                     ;;   do not restore keyboard flags
  308.                     ;;   done at exit
  309.                     
  310.     cmp    kbd_imhere$,1
  311.     jne    call_ros1
  312.     push di ! push si ! push cx
  313.     push    es
  314.     push     ds
  315.     push ds ! pop es
  316.     mov    ax,PC_SEGMENT        ;* in buffer 
  317.     mov    ds,ax            ;* point to the nether region
  318.     mov    si,offset kb_flag_40     ; save main console ROS params
  319.     mov    di,offset save_kbdata$
  320.     mov    cx,39
  321.     rep    movsb
  322.     pop    ds
  323.     call    get_kbd_flags@        ; get active_vc save area offset in SI
  324.     mov    ax,PC_SEGMENT
  325.     mov    es,ax
  326.     mov    di,offset kb_flag_40    ; ROS keyboard data area offset
  327.     mov    cx,39            ; flags and buffer
  328.     rep    movsb            ; put new values into ROS
  329.  
  330.     pop    es
  331.     pop cx ! pop si ! pop di
  332. call_ros1:
  333.     dec    kbd_imhere$        ;; now we're done
  334.     pop    ax ! pop ds
  335.     iret                ;; AT keyboard has been re-enabled
  336.  
  337. endif
  338. jmp_to_ros:
  339.     mov    ds,sysdat
  340.     dec    kbd_imhere$        
  341.     pop    ax            ;; restore ax
  342.     pop    ds
  343.     jmpf    keyboard_isr$        ;; let the ROS do it
  344.  
  345. eject
  346.  
  347. ; char been inserted in buffer after a break
  348. ; We're going to flagset, so save'em all:
  349. ; this will allow ALT numpad keys to generate
  350. ; a char instantly....
  351. is_char:
  352.     cmp    kbd_imhere$,1
  353.      jne    no_swap1
  354.     mov    kbd_ss,ss            ;;
  355.     mov    kbd_sp,sp            ;;
  356.     mov    ss,sysdat$            ;;
  357.     mov    sp,offset kbd_i_stack        ;;
  358. no_swap1:
  359.  
  360.     push es ! push bx ! push cx ! push dx 
  361.     push bp    ! push si ! push di
  362.  
  363.     jmp    normal1                ;; now do flagset and dispatch
  364.  
  365.  
  366. not_break:
  367. ; We know we must flagset, so save'em all:
  368.  
  369.     cmp    kbd_imhere$,1
  370.     je    swap_stack
  371.  
  372. ; If we've been re-entered just throw key away
  373.     mov    al,PIC_OCW_SEOI+KEYBOARD_CHANNEL ;; end-of-interrupt
  374.     out    PIC_OCW_PORT,al            ;;
  375.  
  376. ; make sure keyboard re-enabled on AT's
  377.     test    pc_at$,0ffh            ;; are we on an AT
  378.      jz    not_at4                ;; jump if no
  379.     mov    al,ENA_KBD            ;; enable keyboard
  380.     call    exec                ;; execute command
  381. not_at4:
  382.     dec    kbd_imhere$            ;;
  383.     pop    ax
  384.     pop     ds
  385.     iret
  386.  
  387.  
  388. swap_stack:
  389.     mov    kbd_ss,ss            ;;
  390.     mov    kbd_sp,sp            ;;
  391.     mov    ss,sysdat$            ;;
  392.     mov    sp,offset kbd_i_stack        ;;
  393. no_swap2:
  394.     push es ! push bx ! push cx ! push dx 
  395.     push bp    ! push si ! push di
  396.  
  397.     mov    kbd_scan,al            ;;
  398.     mov    pc_scan_code,al
  399.  
  400. ; Get shift state to be used by switch, menu, and print-screen:
  401.     mov    bx,ax                ;;
  402.      mov    ax,PC_SEGMENT            ;;
  403.      mov    es,ax                ;;
  404.      mov    ah,es:kb_flag_40        ;; get action state
  405.     mov    al,bl                ;; restore scan code
  406.  
  407. ; Test for CTRL_BREAK
  408.  
  409.     test    ah,CTRL_BIT            ;; control shift
  410.     jz    not_ctr
  411.     cmp    al,BREAK_SCAN
  412.     jne    not_prtsc
  413.     test    pc_at$,0ffh            ;; are we on an AT
  414.      jz    not_ate                ;; jump if no
  415.     test    es:kb_flag_3_40,KBX        ;; is it enhanced
  416.      jz    not_ate                ;; no .. normal keyboard
  417.     test    es:kb_flag_3_40,LC_E0        ;; last char marker ??
  418.     jz    not_prtsc
  419. not_ate:
  420.     mov    cntl_break$,0ffh        ;; set flag
  421.     jmp    hw_back                ;; and leave
  422.  
  423.  
  424. ; Test for PRTSCR: not in CONTROL SHIFT
  425. not_ctr:
  426.     cmp    al,PRTSC_SCAN            ;;
  427.      jne    not_prtsc            ;;
  428.     test    pc_at$,0ffh            ;; are we on an AT
  429.      jz    not_at2                ;; jump if no
  430.     test    es:kb_flag_3_40,KBX        ;; is it enhanced
  431.      jz    not_at2                ;; no .. normal keyboard
  432.     test    es:kb_flag_3_40,LC_E0        ;; last char marker ??
  433.      jnz    prtsc                ;; yes.. is print screen
  434.     jmps    not_prtsc
  435. not_at2:
  436.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT ;;
  437.      jz    not_prtsc            ;;
  438. prtsc:
  439.     mov    prtsc_key$,al            ;; save scan
  440.     jmp    hw_back                ;; and leave
  441.     
  442. not_prtsc:
  443.     cmp    al,NUMLOCK            ;; We can't let cntl-numlock
  444.      jne    not_numlock            ;;  through...it kills us
  445.     test    es:kb_flag_3_40,LC_E1        ;; Enhanced keyboard hidden 
  446.      jz    not_pause            ;; code flag (used with PAUSE)
  447.     and    es:kb_flag_3_40,not LC_E1    ;; Clear flag before allowing
  448. not_pause:                    ;; NUMLOCK through
  449.     test    ah,CTRL_BIT            ;;
  450.     jz    not_numlock
  451.     jmp    hw_back                ;; throw away PAUSE key
  452.                         ;;  and ctrl/numlock
  453. ;;     jnz    is_numlock            ;; 
  454. ;;    jmps    not_numlock
  455.     
  456. ; Here if we need to fake out the cntl-numlock bit:
  457. ;;is_numlock:
  458. ;;    and    es:kb_flag_40,not CTRL_BIT    ;; turn off control
  459. ;;    pushf                    ;; fake an int
  460. ;;    callf    keyboard_isr$            ;;
  461. ;;    or    es:kb_flag_40,CTRL_BIT        ;; turn control back on
  462. ;;    jmp    disp_back            ;; and proceed as a normal key
  463.  
  464.  
  465. ; Test for CTRL/ALT/F1 thru F5 function keys for national
  466. not_numlock:
  467.     push    ax                ;; save shift state
  468.     and    ah,CTRL_BIT or ALT_BIT        ;; check only those shift keys
  469.     cmp    ah,CTRL_BIT or ALT_BIT
  470.     pop    ax
  471.      jne    not_ctrlalt_pfk            ;; ignore if not CTRL/ALT
  472.     cmp    al,DEL_SCAN
  473.      jne    not_ctrlalt_del
  474.     test    su_kbd_bits$,01h        ;; test ctrl/alt/del disabled
  475.      jz    is_ctrlalt_del            ;; no
  476.     jmp    hw_back1            ;; else throw away...
  477. is_ctrlalt_del:
  478.  
  479. if V386
  480. ; ** RESET SYSTEM TO REAL MODE **   to be used with caution.
  481.  
  482. if 0                    ;; The following call has been disabled
  483.                     ;;   as it will only work if the OS
  484.                     ;;   does not reside in paged memory.
  485.                     ;; As we sometimes move SYSDAT into
  486.                     ;;   paged memory, the results are
  487.                     ;;   a bit unpredictable...
  488.                     ;; We now force RESET@ to reset the
  489.                     ;;   the CPU via the 8042 chip.
  490.     mov    cl,S_REAL
  491.     int    224            ;; set to real mode
  492. endif
  493.     jmp    reset@            ;; hardware RESET
  494.  
  495. endif
  496.  
  497. if XM
  498.     jmp    mp_reset@        ;; disable EEMS MMU
  499.                     ;; and do hardware RESET
  500.  
  501. endif
  502.  
  503.  
  504. not_ctrlalt_del:
  505.     cmp    al,F1_SCAN            ;; check if function key
  506.      jb    not_ctrlalt_pfk
  507.     cmp    al,F5_SCAN
  508.      ja    not_ctrlalt_pfk
  509.     sub    al,F1_SCAN            ;; make it zero based
  510.     mov    NX_natnlmode$,al        ;; save current national mode
  511.     call    NX_update_mode
  512.     jmp    hw_back1            ;; exit.....
  513.  
  514. not_ctrlalt_pfk:
  515.     cmp    al,PAD4_SCAN            ;; anything below = normal
  516.      jb    normal                ;;
  517.     cmp    al,DEL_SCAN            ;; anything above is unwanted
  518.      ja    normal                ;;
  519.  
  520. ; Go through a jump table based on scan codes from 75 (pad-4) to 83 (del):
  521.     sub    bl,PAD4_SCAN            ;;
  522.     sub    bh,bh                ;;
  523.     shl    bx,1                ;; word table
  524.     jmp    pad_table[bx]            ;;
  525.  
  526. pad_table    dw    switch            ;; PAD 4  75
  527.         dw    ast            ;; PAD 5  76
  528.         dw    normal            ;; PAD 6  77
  529.         dw    menu            ;; PAD +  78
  530.         dw    switch            ;; PAD 1  79
  531.         dw    switch            ;; PAD 2  80
  532.         dw    switch            ;; PAD 3  81
  533.         dw    normal            ;; INS    82
  534.         dw    menu            ;; DEL    83
  535. eject
  536.  
  537. ; Here if we want to toggle the AST enhanced graphics switch to/from
  538. ; normal from/to enhanced.
  539. ast:
  540.     cmp    ah,CTRL_BIT            ;; control-state?
  541.      jne    normal                ;;
  542.  
  543.     test    ast_flag$,0ffh            ; make sure it is possibly AST
  544.     jz    not_ast
  545.  
  546.     mov    ax,ast_enhanced            ;;
  547.     xchg    ah,al                ;;
  548.     mov    ast_enhanced,ax            ;;
  549.     mov    dx,AST_ENHANCED_PORT        ;;
  550.     out    dx,al                ;;
  551.  
  552. ; Now deal w/ the color select register:...change the default for 640,
  553. ; and also replace the value for the top screen mode if it's equal to
  554. ; the old default:
  555.     mov    dl,top_screen$            ;;
  556.     call    point_vs@            ;;
  557.  
  558.     mov    ax,ds:colsel_640$        ;; toggle default 640 col sel.
  559.     xchg    ah,al                ;;
  560.     mov    ds:colsel_640$,ax        ;;
  561.  
  562.     cmp    ah,VS_COLORSEL            ;; is the one we just toggled
  563.      jne    dont_switch            ;; FROM equal to what's in vs_?
  564.     mov    VS_COLORSEL,al            ;;
  565. dont_switch:
  566.     mov    dx,COLOR_PORT            ;; entry requirement
  567.     call    ros_color@            ;; hit it
  568. not_ast:
  569.     jmp    hw_back                ;;
  570.  
  571.  
  572. ; Here if it's a "normal" key:
  573. ; now test if we're on the main 
  574. ; section of the keyboard..... scan codes 1-53 + 86(enhanced keyboard)
  575. ; some languages affect certain keypad chars.
  576. normal:
  577.     cmp    NX_language$,0        ;; U.S keyboard?
  578.      je    normala    
  579.     test    NX_natnlstat$,NX_nkbd_bit
  580.      jz    normala
  581.     test    Eshiftlock,01h        ;; is it FRENCH/GERMAN enhanced
  582.      jz    normala
  583.     test    ah,CAPSLOCK_BIT        ; is CAPSLOCK already down
  584.      jz    normala            ; no let ROS have it
  585.     cmp    al,CAPSLOCK        ; is it CAPSLOCK key
  586.      jne    test_eshift
  587.     jmp    hw_back1        ; yes.. throw it away
  588.     
  589. test_eshift:                ; if CAPSLOCK on and SHIFT key
  590.     cmp    al,SHFT_RIGHT        ; then we must toggle CAPSLOCK off
  591.      je    tog_caps
  592.     cmp    al,SHFT_LEFT
  593.      jne    normala
  594. tog_caps:
  595.     test    es:kb_flag_3_40,LC_E0    ;; Enhanced keyboard hidden 
  596.     jnz    normala            ;; then not genuine shift
  597.     and    es:kb_flag_40,not CAPSLOCK_BIT ;; lets pretend it was CAPSLOCK
  598.     jmps    normal_ros1
  599.     
  600. normala:
  601.     cmp    al,SPACE_SCAN        ;; let national have space key
  602.      je    nat_jmp            ;; for special case deadkey support
  603.     cmp    al,SCAN_102        ;; extra key - enhanced keyboard
  604.      je    nat_jmp
  605.     cmp    al,ALT
  606.      je    normal_ros1        ;; don't do flagset
  607.     cmp    al,SHFT_RIGHT
  608.      je    normal_ros1        ;; don't do flagset
  609.      ja    test_keypad        ;; test keypad for some languages
  610.     cmp    al,SHFT_LEFT        ;;
  611.      je    normal_ros1        ;; don't do flagset
  612.     cmp    al,CTRL            ;; control key
  613.      je    normal_ros1        ;; don't do flagset
  614.     cmp    al,DIV_SCAN        ;; NUMPAD divide key ?
  615.      jne    nat_jmp            ;; no
  616.     test    es:kb_flag_3_40,LC_E0    ;; Enhanced keyboard hidden 
  617.      jz    nat_jmp            ;; no..
  618.     jmps     normal_ros        ;; else let the ROS handle it
  619.  
  620. ; is it national keyboard ??
  621. nat_jmp:
  622.     cmp    NX_language$,0        ;; U.S keyboard?
  623.      je    normal_ros        ;; ....let the ROS do it
  624.     test    NX_natnlstat$,NX_nkbd_bit
  625.      jz    normal_ros
  626.     jmp    nat_kbd            ;; national keyboard support ....
  627.  
  628. ; let ROS handle input if not national mode
  629. normal_ros1:
  630.     pushf                ;; fake an int.
  631.     callf    keyboard_isr$        ;;
  632.     jmp    disp_back        ;; don't flagset
  633.     
  634. normal_ros:
  635.     pushf                ;; fake an int.
  636.     callf    keyboard_isr$        ;;
  637. ;    jmp    normal1            ;; go wake system
  638.  
  639. ; Wake up the system after keyboard input
  640. ; springs to life at "io_conin@:"
  641. normal1:
  642.     mov    dx,key_flag$            ;;
  643.     call    flagset@            ;;
  644.  
  645.     jmp    disp_back            ;;
  646.  
  647. ; some keypad keys are translated in some languages
  648. test_keypad:
  649.     cmp    al,DEL_SCAN            ; SHIFT DEL -> conv to ','
  650.      jne    test_prt
  651.     test    es:kb_flag_3_40,LC_E0    ;; Enhanced keyboard hidden 
  652.     jnz    normal_ros
  653.     test    ah,NUMLOCK_BIT
  654.      jz    no_num
  655.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  656.      jz    test_lang            ; NUMLOCK + no SHIFT
  657.     jmps    normal_ros            ; else let ros have it
  658. no_num:
  659.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT ; no NUMLOCK + SHIFT
  660.      jz    normal_ros            ; no let ros have it
  661.     
  662. test_lang:
  663.     test    NX_natnlstat$,NX_nkbd_bit
  664.      jz    normal_ros            ;; not national
  665.     cmp    NX_language,4            ; Danish
  666.     je    conv_dot
  667.     cmp    NX_language,5            ; Swedish
  668.     je    conv_dot
  669.     cmp    NX_language,8            ; Norwegian
  670.     je    conv_dot
  671.     test    NX_kbd_type$,NX_enhanced    ; is it enchanced keyboard version
  672.     jz    normal_ros            ; no
  673.     cmp    NX_language,2            ; German enhanced ?
  674.     je    conv_dot            ; yes
  675.     jne    normal_ros
  676. conv_dot:
  677.     mov    al,','                ; convert '.' to ','
  678.     jmp    save_with_msb            ; save it
  679.         
  680. test_prt:
  681.     cmp    NX_language,7            ; SPANISH ?
  682.     jne    normal_ros            ; no ..
  683.     test    NX_kbd_type$,NX_enhanced    ; is it enchanced keyboard version
  684.     jnz    normal_ros            ; yes .. no translate
  685.     cmp    al,PRTSC_SCAN            ; print screen key
  686.     jne    normal_ros
  687.     mov    al,'^'                ; '*' converted to '^'
  688.     jmp    save_with_msb
  689.     
  690. ; Here if it's maybe a "screen-switch" command:
  691. switch:
  692.     test    es:kb_flag_3_40,LC_E0        ;; last char marker ??
  693.     jnz    normal_jmp            ;; yes ignore switch
  694.     and    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT or CTRL_BIT or ALT_BIT ;;
  695.     cmp    ah,switch_bits$            ;; same ?
  696.      jnz    normal_jmp            ;; no, so leave
  697.  
  698.     mov    switch_key,al            ;; save for conin
  699.     jmps    hw_back                ;;
  700.  
  701. ; Here if it's maybe a wmenu key:
  702. normal_jmp:
  703.     jmp    normal
  704.  
  705. menu:
  706.     test    ah,CTRL_BIT            ;; for us?
  707.      jz    normal_jmp            ;;
  708.     cmp    al,DEL_SCAN            ;; wmenu doesn't need to be
  709.      je    menu1                ;;  here for FULL SCR. toggle
  710.     cmp    im_here$,0            ;; if wmenu not here...
  711.      je    normal_jmp            ;;
  712. menu1:
  713.     test    ah,ALT_BIT            ;; control-alt del. check
  714.      jnz    normal_jmp
  715.  
  716.     mov    wmenu_key,al            ;; save for conin/wmenu
  717. ;    jmps    hw_back                ;;
  718.  
  719. eject
  720.  
  721. ; Watch the fall-through.
  722. ;; Exit point for keys handled by national
  723. ;; routines and not the ROS 
  724. hw_back:
  725.     mov    dx,key_flag$            ;; CI_FLAG or WW_FLAG or ER_FLAG
  726.     call    flagset@            ;;
  727.  
  728. ; Finish up with the HW:
  729. hw_back1:
  730.     in    al,KBD_CONTROL            ;; get current cntl value
  731.     mov    ah,al                ;;
  732.     or    al,80h                ;; set RESET bit
  733.     out    KBD_CONTROL,al            ;; reset keyboard
  734.     mov    al,ah                ;; get original value
  735.     jmps    $+2                ;;
  736.     out    KBD_CONTROL,al            ;;
  737.  
  738. ; Talk to the PIC:
  739.     mov    al,PIC_OCW_SEOI+KEYBOARD_CHANNEL ;; end-of-interrupt
  740.     out    PIC_OCW_PORT,al            ;;
  741.  
  742. ; make sure keyboard re-enabled on AT's
  743.     test    pc_at$,0ffh            ;; are we on an AT
  744.      jz    not_at3                ;; jump if no
  745.     mov    al,ENA_KBD            ;; enable keyboard
  746.     call    exec                ;; execute command
  747. not_at3:
  748.  
  749. ; And iret by dispatching:
  750. disp_back:
  751.  
  752. if V386                    ; restore the current keyboard flags
  753.     cmp    kbd_imhere$,1
  754.     jne    disp_exit
  755.     cld
  756.     push     ds
  757.     push ds ! pop es
  758.     mov    ax,PC_SEGMENT        ;* in buffer 
  759.     mov    ds,ax            ;* point to the nether region
  760.     mov    si,offset kb_flag_40     ; save main console ROS params
  761.     mov    di,offset save_kbdata$
  762.     mov    cx,39
  763.     rep    movsb
  764.     pop    ds
  765.     call    get_kbd_flags@        ; get active_vc save area offset in SI
  766.     mov    ax,PC_SEGMENT
  767.     mov    es,ax
  768.     mov    di,offset kb_flag_40    ; ROS keyboard data area offset
  769.     mov    cx,39            ; flags and buffer
  770.     rep    movsb            ; put new values into ROS
  771.     
  772. disp_exit:
  773. endif
  774.  
  775.     pop di ! pop si
  776.     pop bp ! pop dx ! pop cx 
  777.  
  778.     pop bx ! pop es                ;;
  779.  
  780.     cmp    kbd_imhere$,1
  781.      jne    no_swap3
  782.     mov    ss,kbd_ss            ;;
  783.     mov    sp,kbd_sp            ;;
  784. no_swap3:
  785.     dec    kbd_imhere$            ;;
  786.  
  787.     pop    ax
  788.     jmpf    dispatch_addr$
  789. ;#IJ    pop ds
  790. ;#IJ    jmpf    disp_addr$            ;; gone
  791.  
  792. exec:
  793.     push    ax ! push cx
  794.     sub    cx,cx
  795. exec1:
  796.     in    al,AT_KBD_STATUS
  797.     test    al,IN_BUF_FULL
  798.     loopnz    exec1                ;; wait until command accepted
  799.     pop    cx ! pop ax
  800.     out    AT_KBD_STATUS,al        ;; send command to keyboard 
  801.     ret                    ;; controller
  802.  
  803. eject
  804.  
  805. ;************************************************
  806. ;*                        *
  807. ;*    NATIONAL KEYBOARD SUPPORT        *
  808. ;*                        *
  809. ;************************************************
  810.  
  811. ;    AL = raw scan code
  812. ;    AH = action state
  813.  
  814. ;    First correct an annoying feature (a bug)
  815. ;    of the PC AT keyboard layout/firmware. On all European keyboards,
  816. ;    the scancodes sent for two of the keys are swapped compared to
  817. ;    the PC and XT keyboards. Long live IBM !
  818. nat_kbd:
  819.     push    ax
  820.     mov    dl,top_screen$            ;;
  821.     call    point_vs@            ;;
  822.     mov    al,VS_MODE
  823.     mov    key_vs_mode,al
  824.     pop    ax
  825.  
  826.     cmp    pc_at$,0        ; are we running on an AT or clone?
  827.      jne    do_swap            ; skip on PC's & XT's
  828.     test    NX_kbd_type$,NX_enhanced ; is it enchanced keyboard version
  829.     jz    test_alt        ; handle enhanced keys on XT and model 30
  830. do_swap:    
  831.     cmp    al,41            ; is it 1st key?
  832.      je    pc_at_swap        ; yes, fix it
  833.     cmp    al,43            ; is it 2nd key?
  834.      jne    test_alt        ; others are OK
  835. pc_at_swap:                ; swap the key codes
  836.     xor    al,41 xor 43        ; 41 => 43, 43 => 41
  837.     mov    pc_scan_code,al        ; save new value
  838. test_alt:
  839.     test    NX_kbd_type$,NX_enhanced    ; is it enchanced keyboard version
  840.      jz    test_alt_norm        ; no .. normal keyboard
  841.     test    alt_gr,ALT_GR_BIT    ; ALT GR key down ?
  842.      jz    test_ctrl_alt
  843.  
  844.     push    ds                ;; same with PAUSE key
  845.     mov    bx,PC_SEGMENT            ;;
  846.     mov    ds,bx                ;;
  847.     test    kb_flag_1_40,L_ALT        ;; is left ALT down
  848.     pop    ds
  849.      jnz    test_ctrl_alt        ; yes.. ignore ALT GR
  850.     and    ah,not ALT_BIT        ; else remove ALT bit from status
  851.     test    ah,CTRL_BIT        ; yes.. is ctrl key down
  852.      jnz    test_alt_norm        ; yes .. ignore ALT GR
  853.     jmps    get_alt_gr        ; else do ALT GR translate
  854. test_ctrl_alt:
  855.     test    ah,ALT_BIT+CTRL_BIT
  856.      jz    test_alt_norm
  857. not_gr:
  858.     mov    ch,ah
  859.     and    ch,ALT_BIT+CTRL_BIT
  860.     cmp    ch,ALT_BIT+CTRL_BIT
  861.      jne    test_alt_norm
  862.     
  863. ; Get key from ALT GR - (CTRL\ALT) table
  864. ; for national enhanced keyboards
  865. get_alt_gr:
  866.     mov    bx,offset NX_ctrlalt$        ; pointer to CTRL\ALT table
  867.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  868.      jz    not_shift            ; leave it if not shifted
  869.     mov    bx,offset NX_ctrlalt_shft$    ; use CTRL\ALT shift table
  870. not_shift:
  871.     mov    NX_tmp_us_flg$, TRUE        ; disable 7 to 8 temporarily
  872.  
  873.     mov    al,pc_scan_code        ; use this value in case translated
  874.     cmp    byte ptr kbd_scan,29h
  875.      jne    test_102
  876.     mov    al,54            ; character position reserved for extra key
  877. test_102:
  878.     cmp    byte ptr kbd_scan,SCAN_102  ; extra key (102 keyboard)
  879.      jne    just_xlat
  880.     mov    al,2bh            ; key 102 uses old char 2bh scan code
  881. just_xlat:
  882.     cmp    al,SPACE_SCAN        ;; don't translate
  883.      jne    do_xlat
  884.     mov    al,' '            ;; space char
  885.     jmp    key_scan_ok
  886. do_xlat:
  887.     xlat    bx            ; get ASCII char in AL
  888.     cmp    al, 0ffh        ; is it undefined
  889.      je    key_scan_nok        
  890. ;;    jmp    NX_test_2nd_dkey    ; no.....valid key
  891.     jmp    key_scan_ok
  892.  
  893. key_scan_nok:
  894.     mov    ch,ah
  895.     and    ch,ALT_BIT + CTRL_BIT
  896.     cmp    ch,ALT_BIT + CTRL_BIT
  897.      je    test_alt_norm        ; if CTRL\ALT then treat normal
  898.     jmp    key_scan_done        ; else .... ignore
  899.  
  900. ; Normal keyboard -    
  901. test_alt_norm:
  902.     test    ah,ALT_BIT 
  903.      jnz    test_alt_down
  904.     jmp    not_alt            ; not ALT key
  905.  
  906. ;    The following piece of code had to be added to support ALT/letter
  907. ;    on international keyboards, where the location of some keys is
  908. ;    different from the US keyboard. 
  909. test_alt_down:
  910.     test    ah,CTRL_BIT
  911.      jz    not_ctrlalt        ; not CTRL\ALT
  912.     mov    al, pc_scan_code    ; restore scan code
  913.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  914.      jz    not_shft_alt
  915.     or    al, 80h            ; shift marked like this in ALT table
  916. not_shft_alt:
  917.     mov    cx, 0
  918.     mov    cl, NX_alt_table$    ; get number of special ALT's
  919.      jcxz    not_ctrlalt        ; none of them
  920.     push    es
  921.     push    ds ! pop es        ; point ES to DS
  922.     mov    di, offset NX_alt_table$+1    ; scan thru them
  923.     cld
  924.     repne    scasb
  925.     pop    es
  926.      jne    not_ctrlalt
  927.  
  928.     sub    di,offset NX_alt_table$ + 2    ; get number of scanned chars
  929.     mov    al,NX_alt_chars$[di]        ; save the character
  930.     mov    NX_tmp_us_flg$, TRUE    ; display as ascii (flag "CONOUT")
  931.     jmp    save_with_msb
  932.  
  933.  
  934. not_ctrlalt:
  935.     mov    al, pc_scan_code    ; restore scan code
  936.     cmp    al, 2            ; scan code of digit "1"
  937.      jb    test_alt_letter        ; below, forget it
  938.     cmp    al, 13            ; above "=", check if letter
  939.      ja    test_alt_letter        ; check if ALT/letter
  940.     add    pc_scan_code, 118    ; ALT/1 thru ALT/0 are 120,...
  941.     jmp    turn_on_msb        ; now it's all right
  942.  
  943.  
  944. test_alt_letter:
  945.     mov    bx, offset NX_nasciitable$    ; see if letter on keyboard
  946.     xlat    bx                ; lookup table
  947.     cmp    al, 'a'                ; check lower boundary
  948.      jb    not_alt_letter            ; too small
  949.     cmp    al, 'z'                ; check upper boundary
  950.      ja    not_alt_letter            ; too big
  951.  
  952.     push    es                ; save ES
  953.     push    ds ! pop es            ; MOV DS,ES
  954.     mov    di, offset key_table$        ; scan through US key table
  955.     mov    cx, 54                ; 54 chars at most
  956.     cld                    ; scan forward
  957.     repne    scasb                ; find out location on US kbd
  958.     sub    di, offset key_table$+1        ; subtract base + overscan
  959.     mov    ax, di                ; AL = scan code
  960.     mov    pc_scan_code,al
  961.     pop    es                ; restore extra segment
  962.     jmp    turn_on_msb            ; return extended code for ALT
  963.  
  964.  
  965. ;    test if this is an alt dead key.
  966. ;    eat it up if it is one, continue if not.
  967. ;    bit 7 in DEADTABLE contains shift bit,
  968. ;    bit 6 in DEADTABLE contains alt bit
  969. ;    (works fine because those codes are 1-59)
  970. ;
  971. not_alt_letter:
  972.     cmp    NX_natnlmode$, 1        ; 8 bit National mode ONLY
  973.      jne    no_alt_dkey
  974.     mov    cl, pc_scan_code        ; get key code
  975.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  976.      jz    alt_dkey_noshift        ; no shift, leave it
  977.     or    cl, 80h                ; turn on shift bit
  978. alt_dkey_noshift:
  979.     or    cl, 40h                ; turn on alt bit
  980.     mov    di, offset NX_deadtable$    ; find out if alt dead key
  981.     call    NX_scanstr@            ; look for a match
  982.     cmp    di,0FFFFh            ; no match
  983.      je    no_alt_dkey            ; forget it
  984.     mov    NX_last_dkey$, di        ; save dead key
  985. no_alt_dkey:
  986.     jmp    key_scan_done            ; eat up this code
  987.  
  988.  
  989. ; CTRL, SHIFT or NORMAL ascii national key
  990. not_alt:
  991.     mov    bx, NX_ascii$        ; translation table for single keys
  992.     test    ah,CTRL_BIT        ; is control key down ?
  993.      jz    test_for_shift        ; no, try shift
  994.  
  995.     mov    bx, NX_ctrl$        ; yes, point to control key table
  996.     jmps    translate        ; and make control code
  997.  
  998. test_for_shift:
  999.     cmp    shiftlock,FALSE        ;; french keyboard flag
  1000.      jnz    test_caps        ;; true
  1001.     test    Eshiftlock,01h        ; is german/french capslock down
  1002.      jz    shift_test
  1003. test_caps:
  1004.     test    ah,CAPSLOCK_BIT
  1005.      jnz    shift_t            ; YES..
  1006. shift_test:
  1007.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1008.      jz    translate        ; not shifted
  1009. shift_t:
  1010.     mov    bx, NX_shift$
  1011. ;    jmps    translate        ;use shift table if numlock
  1012.  
  1013. translate:
  1014.     mov    al,pc_scan_code        ; use this value in case translated
  1015.  
  1016.     test    NX_kbd_type$,NX_enhanced    ; is it enhanced keyboard
  1017.      jz    just_xlat1        ; no..
  1018.     cmp    byte ptr kbd_scan,29h
  1019.      jne    test_102_a
  1020.     mov    al,54            ; character position reserved for extra key
  1021. test_102_a:
  1022.     cmp    byte ptr kbd_scan,SCAN_102  ; extra key (102 keyboard)
  1023.      jne    just_xlat1
  1024.     mov    al,2bh            ; key 102 uses old char 2bh scan code
  1025. just_xlat1:
  1026.     cmp    al,SPACE_SCAN        ;; don't translate
  1027.      jne    translate1
  1028.     mov    al,' '            ;; space char
  1029.     jmps    key_scan_ok
  1030. translate1:
  1031.     xlat    bx            ; get ASCII char in AL
  1032.     cmp    al, 0ffh        ; is it undefined
  1033.      jne    key_scan_ok        ; no.....valid key
  1034.     jmp    key_scan_done        ; yes .... ignore
  1035.  
  1036. key_scan_ok:
  1037.     call    NX_isdkey        ; check if this is a dead key
  1038.     cmp    di, 0FFFFh        ; no match in table
  1039.      je    NX_test_2nd_dkey    ; character is not a dead key
  1040.     jmp    key_scan_done        ; just save it for later combination
  1041. NX_test_2nd_dkey:
  1042.     call    NX_chk_dkey        ; try to combine it with dead key
  1043.  
  1044.     test    ah,CAPSLOCK_BIT        ;test for caps lock
  1045.      jz    save_with_msb        ; no...
  1046.     cmp    shiftlock,FALSE        ;; french keyboard flag
  1047.      jnz    test_french        ;; true
  1048.     test    Eshiftlock,01h        ; enhanced keyb shift lock supported ?
  1049.      jnz    save_with_msb        ; yes.. ignore CAPS translate
  1050.     test    alt_gr,ALT_GR_BIT    ; ALT GR key down
  1051.     jnz    save_with_msb
  1052.     call    NX_case_change        ; else check if case sensitive
  1053.     jmps    save_with_msb
  1054.     
  1055. ;; Special test for FRENCH keyboard support
  1056. ;; if CAPSLOCK numeric keys assume shift position
  1057. test_french:
  1058.     test    alt_gr,ALT_GR_BIT    ; ALT GR key down ?
  1059.      jnz    save_with_msb        ; yes.. no further translation
  1060.     
  1061.     cmp    kbd_scan,2        ; numeric keys and '-' and '='
  1062.      jb    save_with_msb        ; ignore keys below 1
  1063.     
  1064.     cmp    kbd_scan,13        ; and above '+'
  1065.      ja    save_with_msb    
  1066.     
  1067.     mov    al,kbd_scan        ; restore the scan code
  1068.     mov    bx,NX_shift$        ; assume no shift key down
  1069.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1070.      jz    caps_xlat
  1071.     mov    bx,NX_ascii$
  1072. caps_xlat:
  1073.     xlat    bx
  1074.     jmps    save_with_msb
  1075.  
  1076. turn_on_msb:
  1077.     mov    ah, kbd_scan
  1078.     mov    al,pc_scan_code
  1079.     mov    kbd_scan,al
  1080.     xor    al, al
  1081.     cmp    ah, 2
  1082.      jb    skip_alt_char
  1083.     cmp    ah, 14
  1084.      jb    save_with_msb        ;check for alt and 1234567890-= keys
  1085.     cmp    ah, 16 ! 
  1086.      jb    skip_alt_char
  1087.     cmp    ah, 26
  1088.      jb    save_with_msb        ;check for alt and qwertyuiop keys
  1089.     cmp    ah, 30
  1090.      jb    skip_alt_char
  1091.     cmp    ah, 39
  1092.      jb    save_with_msb        ;check for alt and asdfghjkl keys
  1093.     cmp    ah, 44
  1094.      jb    skip_alt_char
  1095.     cmp    ah, 51
  1096.      jb    save_with_msb        ;check for alt and zxcvbnm keys
  1097.  
  1098. skip_alt_char:
  1099.     jmp key_scan_done
  1100.  
  1101. save_with_msb:
  1102.     call    NX_conin_xlat        ; translate & check if valid
  1103.      jc    key_scan_done        ; eat it if invalid
  1104.  
  1105. ;; Save character and scan code in ROS keyboard buffer
  1106.     mov    ah,kbd_scan        ; scan code value into AH
  1107. insert_char:
  1108.     push    ds
  1109.     mov    cx,PC_SEGMENT        
  1110.     mov    ds,cx            ;* point to the nether region
  1111.     mov    bx,buffer_tail_40    ; get the buffer end pointer
  1112.     mov    si,bx
  1113.     inc bx ! inc bx            ; advance pointer
  1114.     cmp    bx,buffer_end_40    ; at end of buffer ?
  1115.     jne    not_end            
  1116.     mov    bx,buffer_start_40    ; yes... reset to start
  1117. not_end:
  1118.     cmp    bx,buffer_head_40    ; has the buffer wrapped
  1119.      je    buf_full_beep        ; yes...sound beeper !!
  1120.     mov    [si],ax            ; else poke scan/char into buffer
  1121.     mov    buffer_tail_40,bx
  1122. ;;    mov    ax,09102h
  1123. ;;    int    15h
  1124.     pop    ds
  1125.     sub    al, al            ; clear and test buffer (JW)
  1126.     xchg    al, NX_dkey_buff$    ; see if dead key character
  1127.     test    al, al            ; is available
  1128.      jz    key_scan_nokey        ; no, just continue
  1129.     mov    ah, dkey_scan        ; no scan code
  1130.     jmps    insert_char        ; insert in ROS output buffer
  1131. key_scan_nokey:                
  1132.     jmp    hw_back            ;; do FLAGSET then exit INT
  1133.  
  1134. buf_full_beep:
  1135.     pop    ds
  1136.     inc    beep_counter$        ; sound beeper and exit......
  1137.     jmp    hw_back
  1138.  
  1139.  
  1140. ;    Common exit if no character was detected
  1141.  
  1142. key_scan_done:
  1143. ;-------------
  1144.     jmp    hw_back1        ;; reset hardware and exit
  1145.                     ;; no FLAGSET    
  1146. eject
  1147. ;****************************************
  1148. ;*     National keyboard subroutines
  1149. ;****************************************
  1150.  
  1151. ;=========
  1152. NX_init@:    ; initialize keyboard/screen/printer
  1153. ;=========
  1154.     mov    al, NX_natnlmode$
  1155. ;    call    NX_update_mode
  1156. ;    ret                ; back to XIOS_INIT
  1157.  
  1158. NX_update_mode:
  1159.     cbw                ; make it a word value
  1160.     mov    bx, ax            ; put it into index register
  1161.     mov    al, NX_mode_table$[bx]    ; get desired mode bits
  1162.     mov    NX_natnlstat$, al    ; setup new mode bits
  1163.     test    al, NX_nkbd_bit        ; see if european keyboard mode
  1164.      jnz    NX_set_nt_kbd        ; if set, enable european xlat table
  1165.  
  1166. NX_set_us_kbd:            ; else enable U.S. keyboard table
  1167.     mov    NX_ascii$, offset key_table$        ;-> unshifted
  1168.     mov    NX_shift$, offset shift_table$        ;-> shifted
  1169.     mov    NX_ctrl$, offset control_table$        ;-> control
  1170.     jmps    NX_update_mode_done
  1171.  
  1172. NX_set_nt_kbd:            ; enable European keyboard table
  1173.     mov    NX_ascii$, offset NX_nasciitable$    ;-> unshifted table
  1174.     mov    NX_shift$, offset NX_nshifttable$    ;-> shift table
  1175.     mov    NX_ctrl$, offset NX_nctrltable$    ;-> control table
  1176.  
  1177. ;;; Handle the special case of FRENCH CAPSLOCK KEY which
  1178. ;;; acts as a SHIFTLOCK by translating all the keys on the keyboard 
  1179. ;;; and not just azerty keys.
  1180.  
  1181. NX_update_mode_done:
  1182.     mov    shiftlock,FALSE        ; assume normal
  1183.     cmp    NX_language$,1        ; is it FRENCH system
  1184.      jnz    NX_update_exit1
  1185.     test    al,NX_nkbd_bit        ; national keyboard support
  1186.      jz    NX_update_exit1
  1187.     mov    shiftlock,TRUE
  1188. NX_update_exit1:
  1189.     test    NX_kbd_type$,NX_enhanced ; is it enchanced keyboard version
  1190.      jz    NX_update_exit        ; no .. normal keyboard
  1191.  
  1192. ;; Handle special case of CAPSLOCK key on 
  1193. ;; FRENCH and GERMAN enhanced keyboard
  1194.  
  1195.     cmp    NX_language$,1        ; is it FRENCH system
  1196.      jnz    test_german
  1197.     or    Eshiftlock,01h
  1198. test_german:
  1199.     cmp    NX_language$,2        ; is it GERMAN system
  1200.      jnz    NX_update_exit
  1201.     or    Eshiftlock,01h
  1202.  
  1203. NX_update_exit:
  1204.     ret
  1205.  
  1206.  
  1207. ;---------------
  1208. NX_conin_xlat:    ;translate 8 bit back to 7 bit if in 7 bit mode
  1209. ;---------------
  1210. ;    Input:    AL = char to translate
  1211. ;    Output:    AL = translated character
  1212. ;
  1213.     cmp    NX_natnlmode$,3    ;Ctrl/Alt/F4 or F5 mode?
  1214.      jb    NX_conin_xlat_done    ;nothing to do if not
  1215. ;
  1216.     mov    bx,offset NX_n7to8chr$    ; scan thru 8 bit eqv chars
  1217. NX_conin_loop:
  1218.     cmp    byte ptr [bx], 0    ; see if end of translate tbl
  1219.      jz    NX_conin_xlat_ignore    ; yes, ignore if 8 bits
  1220.     cmp    al,[bx]            ; see if translation required
  1221.      jz    NX_conin_8to7        ; yes, one of those characters
  1222.     inc    bx            ; no, may be next time
  1223.     jmps    NX_conin_loop        ; give it another try
  1224.  
  1225. NX_conin_8to7:
  1226.     sub    bx,offset NX_n7to8chr$    ; see how many chars checked
  1227.     mov    al, NX_n7to8tbl$[bx]    ; substitute it
  1228.  
  1229. NX_conin_xlat_done:
  1230.     test    al, al            ; clear carry
  1231.     ret                ; back to keyboard interrupt routine
  1232.  
  1233. NX_conin_xlat_ignore:
  1234.     test    al, al            ; seven bits?
  1235.      jns    NX_conin_xlat_done    ; yes, return
  1236.     stc                ; set carry
  1237.     ret
  1238.  
  1239.  
  1240. NX_case_change:    ; check if we need to change lower case <-> upper case
  1241. ;----------------
  1242.     cmp    al, 'z'            ; yes
  1243.      ja    NX_case_test        ; not alphabetic
  1244.     cmp    al, 'a'            ; is it lower case ?
  1245.      jae    do_case_change        ; yes $ switch case
  1246.     cmp    al, 'Z'
  1247.      ja    NX_case_test        ; not alphabetic
  1248.     cmp    al, 'A'            ; test for upper case
  1249.      jb    NX_case_test        ; not alphabetic
  1250. do_case_change:
  1251.     xor    al, 020h        ; switch the case
  1252.     ret
  1253.  
  1254. NX_case_test:
  1255. ;--------------
  1256.     mov    cl, al
  1257.     mov    di, offset NX_ncasetbl$
  1258.     call    NX_scanstr@
  1259.     cmp    di, 0FFFFh
  1260.      je    NX_no_case_change
  1261.     xor    di, 1            ; lower < --- > upper
  1262.     mov    al, NX_ncasetbl$[di]    ; pick up the other
  1263. NX_no_case_change:
  1264.     ret
  1265.  
  1266.  
  1267. NX_isdkey:    ; check if character is a dead key
  1268. ;-----------    ; AH = Shift state
  1269.  
  1270.     mov    di, -1            ; assume no dead key
  1271. ;    test    ah, CTRL_BIT+ALT_BIT
  1272. ;     jnz    NX_no_dkey
  1273.     cmp    NX_natnlmode$, 1        ; Ctrl/Alt/F2 mode?
  1274.      jne    NX_no_dkey            ; (others don't support dead keys)
  1275.     cmp    al,'~'
  1276.      je    is_dead
  1277.     mov    cl,al
  1278.     mov    di,offset NX_dead_ascii$
  1279.     call    NX_scanstr@
  1280.     cmp    di, -1
  1281.      je    NX_no_dkey
  1282. is_dead:    
  1283.     mov    cl, kbd_scan
  1284.     test    Eshiftlock,01h        ; is german/french capslock down
  1285.      jz    shift_test3
  1286.     test    ah,CAPSLOCK_BIT
  1287.      jnz    shift_t3        ; YES..
  1288. shift_test3:
  1289.     test    ah, SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1290.      jz    NX_isdkey_noshift
  1291. shift_t3:
  1292.     or    cl, 80H
  1293. NX_isdkey_noshift:
  1294.     mov    di, offset NX_deadtable$
  1295.     call    NX_scanstr@
  1296.     cmp    di, -1
  1297.      je    NX_no_dkey
  1298.     mov    NX_last_dkey$, di
  1299.     mov    cl,kbd_scan
  1300.     mov    dkey_scan,cl
  1301. NX_no_dkey:
  1302.     ret
  1303.  
  1304.  
  1305. NX_chk_dkey:
  1306. ;-------------
  1307. ;    entry:    al = character to combine with previous dead key
  1308. ;    exit:    al = combined character
  1309.  
  1310.     mov    di, NX_last_dkey$
  1311.     cmp    di, -1
  1312.      je    NX_chk_dkey_done
  1313.     mov    cl, al
  1314.     shl    di, 1
  1315.     mov    di, NX_dkeyv$[di]
  1316.     call    NX_scanstr@
  1317.     cmp    di, -1
  1318.      je    NX_bad_dkey
  1319.  
  1320.     mov    bx, NX_last_dkey$
  1321.     shl    bx, 1
  1322.     mov    bx, NX_dkeyx$[bx]
  1323.     mov    al, [bx+di]
  1324.     jmps    NX_chk_dkey_done
  1325.  
  1326. NX_bad_dkey:
  1327.     mov    cl,dkey_scan            ; swap old and new scan codes
  1328.     xchg    cl,kbd_scan
  1329.     mov    dkey_scan,cl
  1330.     mov    di, NX_last_dkey$        ; was dead key != '..' ?
  1331.     cmp    al, ' '                ; DEADKEY + ' ' --> DEAD
  1332.      je    NX_dkey_blank        ; don't return 2nd char if blank
  1333.     mov    NX_dkey_buff$,al        ; else save second character
  1334. NX_dkey_blank:
  1335.     test    di, di                ; (has index zero)
  1336.      jnz    NX_chk_space            
  1337.     mov    al,0f9h                ; insert IBM decimal point char
  1338. ;;    inc    beep_counter$            ; always beep
  1339.     jmps    NX_chk_dkey_done
  1340. NX_chk_space:
  1341. ;;    cmp    al, ' '                ; dead key + ' ' doesn't beep
  1342. ;;    je    NX_dkey_beep
  1343. ;;    inc    beep_counter$            ; all others do
  1344. NX_dkey_beep:
  1345.     mov    al, NX_dead_key$[di]
  1346. NX_chk_dkey_done:
  1347.     mov    NX_last_dkey$, -1
  1348.     ret
  1349.  
  1350.  
  1351.  
  1352. NX_xlt_7to8:        ; translate 7 to 8 bit code
  1353. ;-------------
  1354. ;    entry:    cl = character to translate
  1355. ;    exit:    cl = translated character
  1356.  
  1357.     push    bx                ; keep every register safe
  1358.     cmp    NX_natnlmode$,3        ; 7 bit, nat scn, nat kbd?
  1359.     jne    NX_xlt78_not_xlt        ; not Ctrl/Alt/F4 mode
  1360.  
  1361.     mov    bx,offset NX_n7to8tbl$        ; scan thru 7 bit eqv chars
  1362. NX_xlt78_loop:
  1363.     cmp    byte ptr [bx],0            ; see if end of translate tbl
  1364.      jz    NX_xlt78_not_xlt        ; yes, check for paragraph
  1365.     cmp    cl,[bx]                ; see if translation required
  1366.      jz    NX_xlt78_7to8            ; yes, one of those characters
  1367.     inc    bx                ; no, may be next time
  1368.     jmps    NX_xlt78_loop            ; give it another try
  1369.  
  1370. NX_xlt78_7to8:
  1371.     sub    bx,offset NX_n7to8tbl$        ; see how many chars checked
  1372.     mov    cl,NX_n7to8chr$[bx]        ; get substitution
  1373.  
  1374. NX_xlt78_not_xlt:
  1375.     pop    bx
  1376.     ret
  1377.  
  1378.  
  1379. NX_scanstr@:        ; search for a character in a table
  1380. ;------------
  1381. ;    entry:    cl = character to look for
  1382. ;        di = address of string to search
  1383. ;    exit:    cl = unmodified
  1384. ;        di = relative position of cl in string if match
  1385. ;        di = 0xffff if no match
  1386.  
  1387.     push    ax                ; save our scratch register
  1388.     mov    ax, di                ; save table in ax
  1389. NX_scanstr_loop:
  1390.     cmp    byte ptr [di], 0        ; end of string?
  1391.     je    NX_scanstr_nomatch        ; yes, definitly no match
  1392.     cmp    cl, [di]            ; match with character
  1393.     je    NX_scanstr_match        ; yes, found it
  1394.     inc    di                ; no, next character
  1395.     jmps    NX_scanstr_loop        ; another try...
  1396.  
  1397. NX_scanstr_nomatch:
  1398.     mov    di, 0ffffh            ; get failure code
  1399.     jmps    NX_scanstr_done        ; return it
  1400. NX_scanstr_match:
  1401.     sub    di, ax                ; offset to start of string
  1402. NX_scanstr_done:                ; return code
  1403.     pop    ax                ; restore scratch register
  1404.     ret
  1405.  
  1406.  
  1407. ;----------------
  1408. NX_conout_xlat@:    ;called from module WINDOWS1.A86
  1409. ;----------------
  1410. ;    Input:    AL = character to translate
  1411. ;    Output:    AL = translated character
  1412. ;        all others maintained
  1413.  
  1414.     push    bx                ; keep every register safe
  1415.     cmp    NX_natnlmode$, 3        ; 7 bit, nat scn, nat kbd?
  1416.     jne    NX_conout_not_xlt        ; not Ctrl/Alt/F4 mode
  1417.     cmp    NX_tmp_us_flg$, 0        ; temparaily 7/8 xlt off
  1418.     mov    NX_tmp_us_flg$, 0        ; reset temporary US display
  1419.     jnz    NX_conout_not_xlt        ; leap if disabled
  1420.  
  1421.     mov    bx, offset NX_n7to8tbl$    ; scan thru 7 bit eqv chars
  1422. NX_conout_loop:
  1423.     cmp    byte ptr [bx], 0        ; see if end of translate tbl
  1424.      jz    NX_conout_not_xlt        ; yes, check for paragraph
  1425.     cmp    al, [bx]            ; see if translation required
  1426.      jz    NX_conout_7to8        ; yes, one of those characters
  1427.     inc    bx                ; no, may be next time
  1428.     jmps    NX_conout_loop        ; give it another try
  1429.  
  1430. NX_conout_7to8:
  1431.     sub    bx, offset NX_n7to8tbl$    ; see how many chars checked
  1432.     mov    al, NX_n7to8chr$[bx]        ; get substitution
  1433.  
  1434. NX_conout_not_xlt:
  1435.     cmp    al, 236                ; this is how we store para
  1436.      jne    NX_conout_not_para        ; not bloody paragraph char
  1437.     mov    al, 21                ; IBM sez: paragraph = Ctrl/U
  1438. NX_conout_not_para:
  1439.     pop    bx
  1440.     ret                    ; back to display routine
  1441.  
  1442.  
  1443.  
  1444. eject
  1445.  
  1446. ;****************************************
  1447. ;*    KEYBOARD INTERRUPT DATA AREA    *
  1448. ;****************************************
  1449.  
  1450. DATA    dseg
  1451. ; Stack:
  1452.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1453.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1454.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1455.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1456.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1457.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1458.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1459.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1460.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1461.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1462.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1463.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1464.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1465.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1466.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1467.     dw    0CCCCh,0CCCCh,0CCCCh,0CCCCh
  1468. kbd_i_stack    rw    0
  1469.  
  1470. kbd_ss        rw    1            ; saved user stack
  1471. kbd_sp        rw    1
  1472.  
  1473. switch_bits$     db    CTRL_BIT        ; set by FUNCTION
  1474.  
  1475. switch_key$    db    0            ; for CONIN
  1476. wmenu_key$    db    0            ; for WMENU/CONIN
  1477. prtsc_key$    db    0            ; for CONIN
  1478.  
  1479. key_flag$    dw    CI_FLAG            ; CI_FLAG or WW_FLAG or ER_FLAG
  1480. kbd_scan    rb    1            ; temp storage
  1481. dkey_scan    rb    1            ; temp storage
  1482. buf_tail    rw    1            ; temp buffer tail storage
  1483. kbd_imhere$    db    0            ; mx
  1484.  
  1485. cntl_break$    db    0            ; = FF if cntl-brk has been typed
  1486.  
  1487. shiftlock    db    FALSE        ; shift lock flag for FRENCH keyboard
  1488. Eshiftlock    db    0        ; Enhanced keyboard shiftlock flag
  1489. key_vs_mode    db    0        ; temp VS_MODE storage
  1490. pc_scan_code    db    0        ; pcmode scan code
  1491.  
  1492. ; enhanced keyboard support
  1493. last_char    db    0        ; last char hidden flag
  1494. alt_gr        db    0        ; ALT GR key depressed status
  1495.  
  1496. if V386
  1497. save_kbdata$    rb    39        ; ROS keyboard data save area
  1498.                     ; offset 17h- 3Eh in ROS data area
  1499. endif
  1500.  
  1501. eject
  1502.     cseg
  1503.  
  1504. keyboard_isr$    rd    1            ; set in INIT
  1505.  
  1506.     end
  1507.