home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / libs / nkcc-293.lzh / SOURCE / NKCC.S
Text File  |  1995-11-09  |  154KB  |  3,735 lines

  1. ********************************************************************************
  2. *
  3. *  Project name : NORMALIZED KEY CODE CONVERTER (NKCC)
  4. *  Module name  : Main module
  5. *  Symbol prefix: nkc
  6. *
  7. *  Author       : Harald Siegmund (HS)
  8. *  Co-Authors   : -
  9. *  Write access : HS
  10. *
  11. *  Notes        : The symbol NKCGEM will have to be defined on the assembler's
  12. *                 command line when translating the source of NKCC. Set its
  13. *                 value to 1 if you like to create the complete version. A value
  14. *                 of 0 will supress inclusion of the GEM part, making NKCC a few
  15. *                 KBytes smaller. Some functions and the GEM parameter arrays
  16. *                 are not available then.
  17. *
  18. *                 Translate this source with the Pure assembler:
  19. *                 pasm [-B] -DNKCGEM=1 -Onkcc.o nkcc.s
  20. *                 pasm [-B] -DNKCGEM=0 -Onkcc_tos.o nkcc.s
  21. *
  22. *                 WARNING: Old versions of the Pure assemblers have serious
  23. *                          bugs! Version Jun 21 1993 works fine.
  24. *
  25. *-------------------------------------------------------------------------------
  26. *END
  27. *  Things to do :
  28. *
  29. *  -  NKCC will support additional (and more complex) deadkeys some time, such
  30. *     like Arabian ones. A communication interface between NKCC and a text
  31. *     editor will be built in for that purpose (Arabian languages' deadkeys can
  32. *     affect existing text!).
  33. *
  34. *-------------------------------------------------------------------------------
  35. *  History:
  36. *
  37. *  1989:
  38. *     May 14: creation of file (NKCC 1.00)
  39. *     Jun 07/15-16/19/21/Jul 11: improvements, changes, debugging
  40. *  1990:
  41. *     Jan 13: global functions now available in two versions:
  42. *             parameters passed via registers (e.g. for Turbo C)
  43. *             parameters passed via stack (underscore before label name)
  44. *
  45. *     May 23-24/26-28: creation of NKCC 2.00 (almost every function rewritten)
  46. *     Jun 16/27: assembler-entry added by Gerd Knops
  47. *     Jun 30/Jul 02: return shift key flags in nkc_multi()/amulti() as NKF?_...
  48. *     Jul 09: nkc_kstate()
  49. *     Aug 03: nkc_cmp()
  50. *     Aug 18: fatal bug in nkc_kstate() fixed
  51. *     Sep 15: nkc_timer()
  52. *     Sep 15-17/30: own button event handler
  53. *     Oct 03: debugging
  54. *             nkc_vlink()/vunlink()
  55. *             documentation syntax changed (LRef/XRef removed; Reg: changed)
  56. *     Oct 05: debugging mouse button handler (problems with menu bar)
  57. *     Oct 07: Control/Alternate + character always returns capital characters
  58. *             changing key code comparism rules in nkc_cmp()
  59. *     Oct 22: debugging nkc_cmp() (did sometimes recognize unique key codes)
  60. *             debugging ASCII code input in nkc_amulti()
  61. *     Dec 11/15/17: MU_XTIMER
  62. *  1991:
  63. *     Jan 11: don't call AES with set MU_XTIMER flag
  64. *     Mar 31: ensure that evnt_multi() parameters are restored when being
  65. *             corrupted by a bug in AES!!
  66. *     Apr 01: debugging
  67. *     Apr 13: nkc_conv() renamed to nkc_tconv()
  68. *     Apr 13-14: nkc_gconv()
  69. *     May 10: debugging (nk_beend())
  70. *     May 29: debugging (double shift key compare)
  71. *             export nkc_toupper and nkc_tolower
  72. *     Jul 05: completing history
  73. *     Jul 31: version number before XBRA header
  74. *     Aug 06: " is now a deadkey!
  75. *     Aug 07: more deadkeys...
  76. *     Aug 22: deadkeys can now be enabled/disabled separately
  77. *             nkc_set() changed
  78. *             nkc_init() returns version #
  79. *             bug fixed: nkc_cmp() corrupted high words of D3 and D4
  80. *     Sep 07/14: nkc_cmp() improved; NKF?_RESVD now in use
  81. *     Nov 05: adjustments to ASCII input feature of TOS 3.06
  82. *     Nov 16: bug fixed in nkc_cmp() mechanism
  83. *             Control key emulation
  84. *     Dec 29: small corrections and extensions of the documentation
  85. *             source documentation syntax now in extra file
  86. *  1992:
  87. *     Jan 03: changing documentation of nkc_init()
  88. *             revising info lines in function headers
  89. *     Jan 12: adjusting nkc_init() to its new documentation!
  90. *             appending .b respectively .l to all instructions with a default
  91. *              operand size which is not .w
  92. *             changing macro XBRA_HD
  93. *     Feb 11: adjusting button event handler to MINT
  94. *     Feb 28: NKCOWNPB switch
  95. *  1993:
  96. *     Dec 11: merging the two existing NKCC versions to one source:
  97. *             - version number set to $0290
  98. *             - NKCNOGEM/NKCOWNPB keys replaced by NKCGEM key
  99. *             - NKCC uses its own AES/VDI parameter arrays now
  100. *             - nkc_init() gets one more parameter: ^AES global array
  101. *             - nkc_toupper and nkc_tolower are functions now
  102. *             - dynamic double click time
  103. *             - MU_MESAG occured -> don't create self-made button events
  104. *     Dec 12: GEM keyboard events: try to get original shift flags from the
  105. *              Iorec buffer
  106. *             new functions: nkc_n2tos() and nkc_n2gem()
  107. *     Dec 13: debugging: ! operator changed to ~ in nk_bestart
  108. *             implementing nkc_n2tos()
  109. *             size of GEM parameter arrays changed to 32 (larger than required
  110. *              but better too big than too small!)
  111. *     Dec 16: debugging nkc_n2tos()
  112. *     Dec 19: improving nkc_gconv() (scan code translation table)
  113. *             debugging nkc_n2tos()
  114. *             cosmetic changes
  115. *     Dec 23: debugging nkc_vunlink(): return status was garbage!
  116. *  1994:
  117. *     May 19: release 2.91:
  118. *             don't restore conterm (it may be changed by another process in
  119. *              the meantime)
  120. *             new deadkeys (/2 /4)
  121. *             adding overview of used MadMac directives in the note section of
  122. *              the file header
  123. *     Jun 27: release 2.92:
  124. *             check for illegal scan codes (e.g. $ff under Mag!x)
  125. *     Oct 31: adding C prototypes to headers of public functions
  126. *  1995:
  127. *     Nov 06: source adjusted for translation with Pure assembler
  128. *     Nov 09: release 2.93:
  129. *             the additional keys on the Macintosh keyboard are supported now
  130. *
  131. ********************************************************************************
  132. *KEY _NAME="NKCC"
  133.  
  134. *START
  135. ****************************************************************************
  136. *                         ASSEMBLER CONTROL SECTION                        *
  137. ****************************************************************************
  138.  
  139. *KEY &NKCGEM
  140. *     define this symbol on the assembler's command line
  141. *     =0    create TOS-version of NKCC (without GEM part)
  142. *     =1    create GEM-version of NKCC
  143.  
  144.                .include "nkcc.i"             ; NKCC definitions
  145. *END
  146. *KEY _END
  147.  
  148.  
  149.  
  150. *START
  151. ****************************************************************************
  152. *                                  EXPORT                                  *
  153. ****************************************************************************
  154.  
  155.                                              ; functions
  156.                .globl   nkc_init             ; init NKCC
  157.                .globl   nkc_exit             ; exit NKCC
  158.                .globl   nkc_set              ; set special key flags
  159.                .globl   nkc_conin            ; NKCC key input via GEMDOS
  160.                .globl   nkc_cstat            ; console input status via GEMDOS
  161.                .globl   nkc_tconv            ; TOS key code converter
  162.                .globl   nkc_gconv            ; GEM key code converter
  163.                .globl   nkc_n2tos            ; NKC to TOS key code converter
  164.                .globl   nkc_n2gem            ; NKC to GEM key code converter
  165.                .globl   nkc_kstate           ; return shift key state
  166.                .globl   nkc_timer            ; return 200 Hz system clock
  167.                .globl   nkc_cmp              ; compare two key codes
  168.                .globl   nkc_vlink            ; link function to XBRA vector list
  169.                .globl   nkc_vunlink          ; unlink function from XBRA list
  170.                .globl   nkc_toupper          ; convert character to upper case
  171.                .globl   nkc_tolower          ; convert character to lower case
  172.  
  173.                .if      NKCGEM=1
  174.  
  175.                 .globl  nkc_multi            ; NKCC multi event handler
  176.                 .globl  nkc_amulti           ; multi event, assembler binding
  177.                 .globl  nkc_contrl           ; GEM parameter arrays
  178.                 .globl  nkc_intin
  179.                 .globl  nkc_intout
  180.                 .globl  nkc_adrin
  181.                 .globl  nkc_adrout
  182.                 .globl  nkc_ptsin
  183.                 .globl  nkc_ptsout
  184.  
  185.                .endif   ; .if NKCGEM=1
  186. *END
  187.  
  188.  
  189.  
  190. ****************************************************************************
  191. *                                  EQUATES                                 *
  192. ****************************************************************************
  193.  
  194. VERSION        =        $0293                ; NKCC's version #
  195.  
  196.                                              ; AES event mask bits
  197. MU_KEYBD       =        $0001                ; keyboard
  198. MU_BUTTON      =        $0002                ; mouse button clicks
  199. MU_M1          =        $0004                ; mouse movement #1
  200. MU_M2          =        $0008                ; mouse movement #2
  201. MU_MESAG       =        $0010                ; message
  202. MU_TIMER       =        $0020                ; timer
  203.  
  204. conterm        =        $484                 ; .B: system key flags
  205. _hz_200        =        $4ba                 ; .L: 200 Hz system clock
  206. _sysbase       =        $4f2                 ; .L: ^OS header
  207.  
  208. TIME_ADD       =        20                   ; wait time to add on each click
  209.                                              ;  in 1/200 s (-> 100 ms)
  210.  
  211.  
  212. ****************************************************************************
  213. *                             ABSOLUTE SECTION                             *
  214. ****************************************************************************
  215.  
  216.                .offset                       ; button event info block
  217.  
  218. BI_BSTATE:     .ds.w    1                    ; requested button state
  219. BI_BMASK:      .ds.w    1                    ; requested button mask
  220. BI_REVCOND:    .ds.w    1                    ; event condition reverse flag
  221. BI_MAXCLICKS:  .ds.w    1                    ; max # of clicks to wait for
  222. BI_DCLTIME:    .ds.w    1                    ; AES double click time
  223. BI_BMODE:      .ds.w    1                    ; button handler mode (see
  224.                                              ;  function nk_butvec)
  225. BI_SBSTATE:    .ds.w    1                    ; button state at start of event
  226. BI_PRVBSTATE:  .ds.w    1                    ; previous button state
  227. BI_NCLICKS:    .ds.w    1                    ; # of mouse clicks
  228. BI_DCBUT:      .ds.w    1                    ; double click button mask
  229. BI_DCSTATE:    .ds.w    1                    ; double click button state
  230. BI_BENDTIME:   .ds.l    1                    ; button event timer end value
  231. BI_BEVALID:    .ds.b    1                    ; flag: button event valid
  232. BI_CVALID:     .ds.b    1                    ; flag: button condition valid
  233. BI_LOCK:       .ds.b    1                    ; flag: button event locked
  234.                .even
  235. BI:                                          ; size
  236.  
  237.  
  238.                .offset                       ; IOREC structure
  239.  
  240. IBUF:          .ds.l    1                    ; ^base of I/O buffer
  241. IBUFSIZ:       .ds.w    1                    ; size of buffer in bytes
  242. IBUFHD:        .ds.w    1                    ; head-pointer (offset to last
  243.                                              ;  used read position
  244. IBUFTL:        .ds.w    1                    ; tail-pointer (offset to last
  245.                                              ;  used write position
  246. IBUFLO:        .ds.w    1                    ; low water mark
  247. IBUFHI:        .ds.w    1                    ; high water mark
  248. IOREC:                                       ; size
  249.  
  250.  
  251.  
  252. ****************************************************************************
  253. *                                  MACROS                                  *
  254. ****************************************************************************
  255.  
  256. ****************************************************************************
  257. *
  258. * LWDIVU: divide long value <da> by word value <db>, use <dt> for temp storage
  259. *
  260. * - the result will be stored as LONGword in <da>
  261. * - <db> stays unchanged
  262. * - <da> and <dt> must be data registers
  263. *
  264. ****************************************************************************
  265.  
  266.                .macro   LWDIVU db,da,dt
  267.  
  268.                move.l   &da,&dt              ; copy long-value
  269.                clr      &dt                  ; clear its low word
  270.                swap     &dt                  ; dt.w = high word of long-value
  271.                divu     &db,&dt              ; high word / word-value
  272.                swap     &da                  ; long-value, low and high swapped
  273.                move     &dt,&da              ; da.w = result of high/word-value
  274.                swap     &da                  ; da.w = low word of long-value
  275.                move     &da,&dt              ; remainder and low-word
  276.                divu     &db,&dt              ; divide by word-value
  277.                move     &dt,&da              ; so we get low word of result
  278.  
  279.                .endm
  280.  
  281.  
  282.  
  283. ****************************************************************************
  284. *
  285. * XBRA_HD: XBRA header for NKCC functions
  286. *
  287. * The following structure is stored at the current memory location:
  288. *
  289. * VERSION.L       NKCC's version # (actually not a part of a standard XBRA
  290. *                 header; may be checked in future versions)
  291. * "XBRA".L        magic longword
  292. * "NKCC".L        NKCC's XBRA-ID
  293. * oldvec.L        initial value of buffer for old vector content (passed as
  294. *                 macro parameter); usually 0
  295. *
  296. ****************************************************************************
  297.  
  298.                .macro   XBRA_HD oldvec
  299.  
  300.                .dc.l    VERSION              ; version number
  301.                .dc.b    "XBRA"               ; XBRA header
  302.                .dc.b    "NKCC"               ; ID
  303.                .dc.l    &oldvec              ; chain pointer to next routine
  304.  
  305.                .endm
  306.  
  307.  
  308.  
  309. ****************************************************************************
  310. *                            LOCAL TEXT SECTION                            *
  311. ****************************************************************************
  312.  
  313.                .text
  314.  
  315. ****************************************************************************
  316. *
  317. *  nk_gci: GEMDOS console character input
  318. *  #
  319. *
  320. *  This function returns when
  321. *
  322. *     a) either any key is pressed or
  323. *     b) the Alternate key is released
  324. *
  325. *  The Alternate check can be suppressed by setting the input parameter in
  326. *  D0.W to zero. The routine works then just as a "get key" function.
  327. *
  328. *  In:   D0.W           Alternate key check flag:
  329. *                       zero = don't check it
  330. *                       non-zero = do Alternate check
  331. *
  332. *  Out:  D0.W           key code in normalized format
  333. *                       for details see nkc_tconv()
  334. *        D1.W           flag:
  335. *                       zero = D0.W not valid; Alternate was released
  336. *                       non-zero = D1.W valid; Alternate still pressed
  337. *                          (also returned when Alternate check supressed)
  338. *        CCR            set according content of D1.W
  339. *
  340. *  Reg:  D:01234567   A:01234567   CCR
  341. *          U***....     ****....   =D1.W
  342. *
  343. ****************************************************************************
  344.  
  345. nk_gci:        move     d0,d3                ; Alternate check flag
  346.                beq.s    .getkey              ; no check? just get key
  347.  
  348.                move.l   pshift,a3            ; ^shift key state
  349.  
  350. .loop:         btst.b   #3,(a3)              ; Alternate still pressed?
  351.                beq.s    .abort               ; no->
  352.  
  353.                move     #11,-(sp)            ; Cconis: get key input status
  354.                trap     #1                   ; Gemdos
  355.                addq     #2,sp                ; clean stack
  356.  
  357.                tst      d0                   ; any key pressed?
  358.                beq.s    .loop                ; no->
  359.  
  360. .getkey:       move     #7,-(sp)             ; Crawcin: get key
  361.                trap     #1                   ; Gemdos
  362.                addq     #2,sp                ; clean stack
  363.                bsr      nkc_tconv            ; convert key code
  364.                moveq.l  #-1,d1               ; flag: key code valid
  365.                rts                           ; bye
  366.  
  367. .abort:        moveq.l  #0,d1                ; flag: key code not valid
  368.                rts                           ; bye
  369.  
  370.  
  371.  
  372. ****************************************************************************
  373. *
  374. *  nk_spec: special key code handling
  375. *  #
  376. *
  377. *  nk_spec() performs the special key handling defined by <sflags> (deadkey
  378. *  management, ASCII code input, Control key emulation).
  379. *
  380. *  In:   D0.W           key code in normalized format
  381. *                       for details see nkc_tconv()
  382. *        A0.L           ^function which gets new key codes and checks
  383. *                       the Alternate key state
  384. *                       For the calling conventions consult nk_gci() or
  385. *                       nk_mci(). The function MUST NOT modify the CPU
  386. *                       registers D5-D7 and A5-A6.
  387. *
  388. *  Out:  D0.W           (new) key code in normalized format
  389. *        CCR            set according contents of D0.W
  390. *
  391. *  Reg:  D:01234567   A:01234567   CCR
  392. *          U*******     *******.   =D0.W
  393. *
  394. ****************************************************************************
  395.  
  396. nk_spec:       move.l   a0,a6                ; save ^function
  397.                btst.b   #NKSb_ALTNUM,sflags + 3 ; ASCII input enabled?
  398.                beq.s    .ctrlkey             ; no->
  399.  
  400.  
  401. *------------- ASCII input
  402.  
  403.                moveq.l  #0,d6                ; reset digit counter
  404.                moveq.l  #0,d5                ; reset ASCII code
  405.                bra.s    .isdigit             ; check if valid key
  406.  
  407. .notvalid:     tst      d6                   ; key not valid; first one?
  408.                beq.s    .ctrlkey             ; yes-> exit
  409.  
  410. .getkey:       move     d0,d7                ; save previous key code
  411.                moveq.l  #-1,d0               ; check Alternate
  412.                jsr      (a6)                 ; get key
  413.                beq.s    .makeascii           ; Alternate released? abort loop
  414.  
  415. .isdigit:      move     d0,d1                ; key code
  416.                and      #NKFf_NUM | NKFf_ALT,d1 ; isolate flags
  417.                cmp      #NKFf_NUM | NKFf_ALT,d1 ; with Alternate and numeric?
  418.                bne.s    .notvalid            ; no->
  419.  
  420.                cmp.b    #'0',d0              ; must be in range from 0 ...
  421.                blo.s    .notvalid
  422.  
  423.                cmp.b    #'9',d0              ; ... to 9
  424.                bhi.s    .notvalid
  425.  
  426.                mulu     #10,d5               ; new digit in ASCII code
  427.                sub      #'0',d0              ; ASCII->number
  428.                add      d0,d5                ; add new digit
  429.                addq     #1,d6                ; count digits
  430.                cmp      #3,d6                ; 3rd digit added?
  431.                bne.s    .getkey              ; no-> next key
  432.  
  433. .makeascii:    move     d7,d0                ; previous key code
  434.                and      #NKFf_CAPS,d0        ; isolate CapsLock flag
  435.                move.b   d5,d0                ; add key code (ASCII)
  436.  
  437.  
  438. *------------- Control key emulation
  439.  
  440. .ctrlkey:      btst.b   #NKSb_CTRL,sflags + 3   ; enabled?
  441.                beq.s    .deadkey             ; no ->
  442.  
  443.                btst.l   #NKFb_CTRL,d0        ; Control flag set?
  444.                beq.s    .deadkey             ; no ->
  445.  
  446.                btst.l   #NKFb_ALT,d0         ; Alternate flag set?
  447.                bne.s    .deadkey             ; yes ->
  448.  
  449.                cmp.b    #$40,d0              ; check ASCII code
  450.                blo.s    .deadkey             ; too low ->
  451.  
  452.                cmp.b    #$5f,d0              ; check again
  453.                bhi.s    .deadkey             ; too high ->
  454.  
  455.                                              ; clear function and Control flags
  456.                and      #(!(NKFf_FUNC|NKFf_CTRL)) & $ffff,d0
  457.                sub.b    #$40,d0              ; new ASCII code
  458.  
  459. * The Pure assembler believes that !(NKFf_FUNC|NKFf_CTRL) is a LONGWORD constant
  460. * so we have to mask off the upper 16 bits with $ffff. Gosh!
  461.  
  462.  
  463. *------------- check if key = deadkey
  464.  
  465. .deadkey:      tst      d0                   ; function key?
  466.                bmi.s    .ret                 ; yes-> no deadkey
  467.  
  468.                lea      deadtab,a0           ; ^deadkey table
  469.                move     sflags,d4            ; deadkey flags
  470.                beq.s    .exit                ; no deadkeys at all->
  471.  
  472. .finddead:     move     (a0)+,d2             ; get option flag mask
  473.                beq.s    .exit                ; end of table-> no deadkey
  474.  
  475.                move     (a0)+,d1             ; get key code
  476.                addq     #4,a0                ; skip ^match table
  477.                and      d4,d2                ; is this deadkey enabled?
  478.                beq.s    .finddead            ; no ->
  479.  
  480.                cmp.b    d0,d1                ; deadkey found?
  481.                bne.s    .finddead            ; no->
  482.  
  483.  
  484. *------------- key is dead key, get second key and merge them
  485.  
  486.                move.l   -4(a0),a5            ; ^deadkey match table
  487.                move     d0,-(sp)             ; save key code
  488.                clr      d0                   ; no Alternate check
  489.                jsr      (a6)                 ; get second key
  490.                move     sflags,-(sp)         ; save deadkey flags
  491.                clr      sflags               ; disable deadkeys temporary
  492.                move.l   a6,a0                ; do ASCII input/ctrl key check
  493.                bsr      nk_spec              ; by calling myself!
  494.  
  495.                move     (sp)+,sflags         ; restore deadkey flags
  496.                move     (sp)+,d7             ; restore first key code
  497.                tst      d0                   ; function key?
  498.                bmi.s    .nomatch             ; yes-> doesn't match with deadkey
  499.  
  500. .findmatch:    move     (a5)+,d1             ; merged and second key code
  501.                beq.s    .nomatch             ; end of table->
  502.  
  503.                cmp.b    d0,d1                ; second key code found?
  504.                bne.s    .findmatch           ; no->
  505.  
  506.                lsr      #8,d1                ; yes: merged code in .B
  507.                and      #NKFf_CAPS,d0        ; clear all except CapsLock
  508.                move.b   d1,d0                ; CapsLock flag + merged key
  509.                bra.s    .exit                ; exit
  510.  
  511. .nomatch:      move     d0,prvkey            ; save second key
  512.                st.b     prvvalid             ; set validation flag
  513.                move     d7,d0                ; return first key
  514.  
  515. .ret:          rts                           ; bye
  516.  
  517. .exit:         tst      d0                   ; set CCR
  518.                rts                           ; bye
  519.  
  520.  
  521.  
  522. ****************************************************************************
  523. *
  524. *  nk_ascmatch: check if ASCII code matches with one from the key code tables
  525. *  # R
  526. *
  527. *  This functions proofs, if D0.B equals to D4.B, D5.B or D6.B. An according
  528. *  flag is returned. The flag bytes in the TOS key code D0.L are modified
  529. *  depending on which code matches.
  530. *
  531. *  In:   D0.L           key code in TOS format
  532. *        D4.B           ASCII code from unshifted key table
  533. *        D5.B           ASCII code from shifted key table
  534. *        D6.B           ASCII code from CapsLock key table
  535. *
  536. *  Out:  D0.L           key code in TOS format
  537. *                       (updated flags in upper byte)
  538. *
  539. *        CCR            EQ: ASCII code was found
  540. *                       NE: ASCII code wan't found
  541. *
  542. *  Reg:  D:01234567   A:01234567   CCR
  543. *          U......*     ........   flag (see above)
  544. *
  545. ****************************************************************************
  546.  
  547. nk_ascmatch:   tst.b    d0                   ; zero?
  548.                bne.s    .comp                ; no ->
  549.  
  550.                move.l   d0,d7                ; copy key code
  551.                                              ; Alt/Control already found out?
  552.                and.l    #(NKFf_ALT|NKFf_CTRL)<<16,d7
  553.                bne.s    .unknown             ; yes ->
  554.  
  555. .comp:         cmp.b    d4,d0                ; unshifted?
  556.                bne.s    .shftst              ; no ->
  557.  
  558.                cmp.b    d6,d0                ; in CapsLock table, too?
  559.                beq.s    .exit                ; yes ->
  560.  
  561.                bclr.l   #NKFb_CAPS+16,d0     ; no: cannot be CapsLock
  562.                bra.s    .exit                ; ->
  563.  
  564. .shftst:       cmp.b    d5,d0                ; shifted?
  565.                bne.s    .cpstst              ; no ->
  566.  
  567.                cmp.b    d6,d0                ; in CapsLock table, too?
  568.                bne.s    .shifted             ; no ->
  569.  
  570.                btst.l   #NKFb_CAPS+16,d0     ; CapsLock active?
  571.                bne.s    .exit                ; yes -> it COULD be generated
  572.                                              ;  by pressing Shift, but we
  573.                                              ;  assume CapsLock
  574.  
  575. .shifted:      or.l     #NKFf_SHIFT<<16,d0   ; shifted: set both shift flags
  576.                bra.s    .exit                ; ->
  577.  
  578. .cpstst:       cmp.b    d6,d0                ; in CapsLock table?
  579.                bne.s    .unknown             ; no ->
  580.  
  581.                bset.l   #NKFb_CAPS+16,d0     ; yes: set CapsLock flag
  582.  
  583. .exit:         moveq.l  #0,d7                ; found
  584.                rts
  585.  
  586. .unknown:      moveq.l  #1,d7                ; not found
  587.                rts
  588.  
  589.  
  590.  
  591. ****************************************************************************
  592. *
  593. *  nk_findscan: find scan code
  594. *  # R
  595. *
  596. *  The
  597. *
  598. *  In:   D0.W           normalized key code
  599. *        A0.L           ^base of system's key code table
  600. *
  601. *  Out:  D1.W           found scan code (0 = not found)
  602. *        CCR            set according contents of D1.W
  603. *
  604. *  Reg:  D:01234567   A:01234567   CCR
  605. *          .W......     *.......   =D1
  606. *
  607. ****************************************************************************
  608.  
  609. nk_findscan:   btst.l   #NKFb_NUM,d0         ; on numeric keypad?
  610.                beq.s    .search              ; no ->
  611.  
  612.                move     #$4a,d1              ; yes: try all numeric keypad
  613.                cmp.b    (a0,d1),d0           ;  scan codes first
  614.                beq.s    .found               ; it matches ->
  615.  
  616.                move     #$4e,d1
  617.                cmp.b    (a0,d1),d0
  618.                beq.s    .found
  619.  
  620.                move     #$63,d1              ; block starts at $63
  621.  
  622. .numsearch:    cmp.b    (a0,d1),d0           ; match?
  623.                beq.s    .found               ; yes ->
  624.  
  625.                addq     #1,d1                ; next scan code
  626.                cmp      #$73,d1              ; block end at $72
  627.                blo.s    .numsearch           ; continue search ->
  628.  
  629. .search:       move     #1,d1                ; start with first valid scan code
  630.  
  631. .mainsearch:   cmp.b    (a0,d1),d0           ; match?
  632.                beq.s    .found               ; yes ->
  633.  
  634.                addq.b   #1,d1                ; next scan code
  635.                cmp.b    #$78,d1              ; $78 = last valid scan code
  636.                blo.s    .mainsearch          ; continue search ->
  637.  
  638.                moveq.l  #0,d1                ; not found
  639.                rts
  640.  
  641. .found:        tst      d1                   ; found; set CCR
  642.                rts
  643.  
  644.  
  645.  
  646.                .if      NKCGEM=1
  647.  
  648. ****************************************************************************
  649. *
  650. *  nk_bioscode: convert GEM key code to GEMDOS/BIOS format
  651. *  # R
  652. *
  653. *  This is a simple converter which takes key codes in AES format (two
  654. *  words) and transforms them to the BIOS key format (one longword).
  655. *
  656. *  In:   D0.W           key code
  657. *                       high byte = scan code, low byte = ASCII code
  658. *        D1.W           shift key state flags
  659. *                       Bit 0: right Shift
  660. *                       Bit 1: left Shift
  661. *                       Bit 2: Control
  662. *                       Bit 3: Alternate
  663. *
  664. *  Out:  D0.L           key code in BIOS format
  665. *                       for details see nkc_tconv()
  666. *
  667. *  Reg:  D:01234567   A:01234567   CCR
  668. *          U*......     *.......    *
  669. *
  670. ****************************************************************************
  671.  
  672. nk_bioscode:   swap     d0                   ; key code in high word
  673.                move     d1,d0                ; shift key state
  674.                move.l   pshift,a0            ; ^shift key state system variable
  675.                move.b   (a0),d1              ; get it
  676.                and      #!NKFf_CAPS,d1       ; isolate CapsLock flag
  677.                or       d1,d0                ; merge with other shift flags
  678.                swap     d0                   ; shift state in high word
  679.                lsl.l    #8,d0                ; move 'em up
  680.                lsr      #8,d0                ; now key code in BIOS format
  681.                rts                           ; bye
  682.  
  683.  
  684.  
  685. ****************************************************************************
  686. *
  687. *  nk_real_shift: try to get original shift flags of a key code
  688. *  #
  689. *
  690. *  This function uses the contents of the Iorec keyboard ring buffer to
  691. *  restore the original shift flag byte of a key code which has been
  692. *  transported through AES' event manager and thus stripped off its
  693. *  flag byte.
  694. *
  695. *  In:   D0.L           key code in TOS format
  696. *                       for details see nkc_tconv()
  697. *
  698. *  Out:  D0.L           updated key code in TOS format
  699. *
  700. *  Reg:  D:01234567   A:01234567   CCR
  701. *          U**.....     *.......    *
  702. *
  703. ****************************************************************************
  704.  
  705. nk_real_shift: move.l   kbdiorec,a0          ; ^keyboard's I/O record
  706.                movem.l  d3/d4,-(sp)          ; save registers
  707.                move     IBUFHD(a0),d1        ; head pointer
  708.                move     IBUFTL(a0),d2        ; tail pointer
  709.                move     iohead,d3            ; NKCC's head pointer
  710.  
  711.  
  712. *------------- check if tail pointer has overrun NKCC's head pointer
  713.  
  714.                cmp      d1,d2                ; tail < head?
  715.                blo.s    .tlwrap              ; yes -> it has been wrapped around
  716.  
  717.                cmp      d3,d1                ; my tail between record's
  718.                bhs.s    .search              ;  head and tail?
  719.  
  720.                cmp      d2,d3                ; if so, tail has overrun my
  721.                blo.s    .reset               ;  head -> reset
  722.  
  723.                bra.s    .search              ; no overrun ->
  724.  
  725. .tlwrap:       cmp      d2,d3                ; my tail below wrapped record's
  726.                blo.s    .reset               ;  tail pointer or above head?
  727.  
  728.                cmp      d3,d1                ; then tail has overrun my
  729.                blo.s    .reset               ;  head -> reset
  730.  
  731.  
  732. *------------- find key code in ring buffer
  733.  
  734. .search:       move     IBUFSIZ(a0),d2       ; buffer size
  735.                move.l   IBUF(a0),a0          ; ^base of buffer
  736.                move.l   d0,d4                ; copy key code
  737.                swap     d4                   ; scan code in low byte of d4
  738.                bra.s    .find2               ; ->
  739.  
  740. .find:         addq     #4,d3                ; advance to next read-position
  741.                cmp      d2,d3                ; wrap around?
  742.                blo.s    .getkey              ; no ->
  743.  
  744.                moveq.l  #0,d3                ; yes: wrap
  745.  
  746. .getkey:       cmp.b    3(a0,d3),d0          ; compare ASCII code
  747.                bne.s    .find2               ; doesn't match ->
  748.  
  749.                cmp.b    1(a0,d3),d4          ; compare scan code
  750.                bne.s    .find2               ; doesn't match ->
  751.  
  752.                move.l   (a0,d3),d0           ; found: get complete key code
  753.                bra.s    .exit                ; ->
  754.  
  755. .find2:        cmp      d1,d3                ; my head has reached buffer's head
  756.                bne.s    .find                ; no ->
  757.  
  758. .reset:        move     d1,d3                ; reset head pointer
  759.  
  760. .exit:         move     d3,iohead            ; save new head pointer
  761.                movem.l  (sp)+,d3/d4          ; restore registers
  762.                rts                           ; bye
  763.  
  764.  
  765.  
  766. ****************************************************************************
  767. *
  768. *  nk_mci: multi event console character input
  769. *  # U
  770. *
  771. *  This function returns when
  772. *
  773. *     a) either any key is pressed or
  774. *     b) the Alternate key is released
  775. *
  776. *  The Alternate check can be suppressed by setting the input parameter in
  777. *  D0.W to zero. The routine works then just as a "get key" function.
  778. *
  779. *  In:   D0.W           Alternate key check flag:
  780. *                       zero = don't check it
  781. *                       non-zero = do Alternate check
  782. *
  783. *  Out:  D0.W           key code in normalized format
  784. *                       for details see nkc_tconv()
  785. *        D1.W           flag:
  786. *                       zero = D0.W not valid; Alternate was released
  787. *                       non-zero = D1.W valid; Alternate still pressed
  788. *                          (also returned when Alternate check supressed)
  789. *        CCR            set according content of D1.W
  790. *
  791. *  Reg:  D:01234567   A:01234567   CCR
  792. *          U***....     ****....   =D1.W
  793. *
  794. ****************************************************************************
  795.  
  796. nk_mci:        move     d0,d3                ; save Alternate check flag
  797.                move.l   pshift,a3            ; ^shift key state variable
  798.  
  799. .loop:         lea      nkc_contrl,a0        ; ^control array
  800.                move     #25,(a0)+            ; opcode
  801.                move     #16,(a0)+            ; size of intin
  802.                move     #7,(a0)+             ; size of intout
  803.                move     #1,(a0)+             ; size of addrin
  804.                clr      (a0)                 ; size of addrout
  805.  
  806.                lea      nkc_intin,a0         ; ^intin array
  807.                move     #MU_TIMER|MU_KEYBD,(a0) ; wait for timer and key strokes
  808.                clr.l    7*4(a0)              ; waiting time: 0 ms = minimum!
  809.  
  810.                move     #200,d0              ; opcode for AES
  811.                move.l   #aespb,d1            ; ^AES parameter block
  812.                trap     #2                   ; call GEM
  813.  
  814.                lea      nkc_intout,a0        ; ^intout array
  815.                move     (a0),d0              ; event mask
  816.                move.b   (a3),d1              ; shift key state
  817.                and      #$f,d1               ; clear unused bits
  818.                move     #MU_KEYBD,d2         ; did keyboard event occur?
  819.                and      d0,d2                ; check bit
  820.                bne.s    .keybd               ; yes->
  821.  
  822.                move.l   kbdiorec,a1          ; ^keyboard's I/O record
  823.                move     IBUFHD(a1),iohead    ; reset NKCC's head pointer
  824.                tst      d3                   ; do Alternate check?
  825.                beq.s    .loop                ; no->
  826.  
  827.                btst.l   #3,d1                ; Alternate still pressed?
  828.                bne.s    .loop                ; yes->
  829.  
  830.                moveq.l  #0,d1                ; Alternate released: abort
  831.                rts
  832.  
  833. .keybd:        move     10(a0),d0            ; key code
  834.                bsr      nk_bioscode          ; convert to BIOS keycode
  835.                bsr      nk_real_shift        ; try to get original shift flags
  836.                bsr      nkc_tconv            ; convert to normalized format
  837.                moveq.l  #1,d1                ; key code is valid
  838.                rts                           ; bye
  839.  
  840.  
  841.  
  842. ****************************************************************************
  843. *
  844. *  nk_gemtrap: GEM trap handler
  845. *  # S T2
  846. *
  847. *  This function is linked to the GEM trap vector at initialization time.
  848. *  It waits for evnt_dclick() calls (get/set double click time) and saves
  849. *  new click times in an own buffer.
  850. *
  851. *  In:   D0.W           opcode:
  852. *                       115 = VDI
  853. *                       200 = AES
  854. *        A0.L           AES/VDI parameter block
  855. *
  856. *  Out:  -
  857. *
  858. *  Reg:  D:01234567   A:01234567   CCR
  859. *          ..*.....     **......    *
  860. *
  861. ****************************************************************************
  862.  
  863.                XBRA_HD  0                    ; XBRA header
  864.  
  865. nk_gemtrap:    cmp      #200,d0              ; AES?
  866.                bne.s    .exit                ; no ->
  867.  
  868.                move.l   d1,a0                ; ^parameter block
  869.                move.l   (a0),a1              ; ^contrl array
  870.                cmp      #26,(a1)             ; opcode for evnt_dclick?
  871.                bne.s    .exit                ; no ->
  872.  
  873.                move.l   8(a0),a1             ; ^intin array
  874.                tst      2(a1)                ; set new time?
  875.                beq.s    .exit                ; no ->
  876.  
  877.                move     (a1),d2              ; yes: get new time
  878.                cmp      #4,d2                ; limit check
  879.                bls.s    .save                ; ok: save new value
  880.  
  881.                moveq.l  #4,d2                ; out of range: use maximum
  882.  
  883. .save:         move     d2,bvar+BI_DCLTIME   ; save it
  884.  
  885. .exit:         move.l   nk_gemtrap-4(pc),-(sp)  ; old vector address
  886.                rts                           ; jump to old routine
  887.  
  888.  
  889.  
  890. ****************************************************************************
  891. *
  892. *  nk_butvec: VDI mouse button change handler
  893. *  # I S
  894. *
  895. *  This function handles changes of the mouse button state. It is used
  896. *  for NKCC's own button event handler, which consists mainly of this
  897. *  interrupt and the functions nk_bestart() and nk_beend().
  898. *
  899. *  The handler knows several modes (stored in bvar+BU_BMODE.w):
  900. *
  901. *  0     standby mode: no button event in process, waiting for first click
  902. *  1     wait mode: button event in process, but not yet finished: waiting
  903. *        for a possible second, third ... click
  904. *  2     hold mode: button event was generated, condition still true (buttons
  905. *        are still pressed): repeat button event
  906. *
  907. *  In:   D0.W           current state of mouse buttons
  908. *
  909. *  Out:  D0.W           current state of mouse buttons (unchanged)
  910. *
  911. *  Reg:  D:01234567   A:01234567   CCR
  912. *          ........     ........    *
  913. *
  914. ****************************************************************************
  915.  
  916.                XBRA_HD  nk_bvret             ; XBRA header
  917.  
  918. * Some milliseconds after the installation of this function, the old vector
  919. * address is not set (VDI has to return first). A mouse click during this
  920. * time would lead to a system crash because the new handler jumps through
  921. * this vector. This is the reason why it's initial content points to a
  922. * RTS instruction. (I know, this is a very very improbable situation, but
  923. * it IS possible! And that's reason enough to prepare for it and write
  924. * some silly lines of comment about it!)
  925.  
  926. nk_butvec:     movem.l  d5-d7/a0-a1,-(sp)    ; save registers
  927.                lea      bvar,a1              ; ^button event info block
  928.                move     d0,d7                ; new button mask
  929.                move     BI_BSTATE(a1),d6     ; requested button state
  930.                eor      d6,d7                ; XOR 'em
  931.                move     BI_BMASK(a1),d6      ; button mask
  932.                and      d6,d7                ; isolate valid bits
  933.                tst      BI_REVCOND(a1)       ; condition reverse flag
  934.                bne.s    .rev                 ; reverse ->
  935.  
  936.                tst      d7                   ; 0-> all button conditions true
  937.                seq.b    d6                   ; if so, the set d6 to $ff
  938.                bra.s    .chkmode             ; ->
  939.  
  940. .rev:          eor      d6,d7                ; invert condition flags
  941.                cmp      d6,d7                ; at least one condition true?
  942.                sne.b    d6                   ; yes -> set d6 to $ff
  943.  
  944. * the registers contain now:
  945. *
  946. * d6.b = button condition flag (0=condition false, $ff=condition true)
  947. * d7.w = button condition mask (bits with value 0 indicate true condition)
  948.  
  949. .chkmode:      move.b   d6,BI_CVALID(a1)     ; save flag
  950.                move     BI_BMODE(a1),d5      ; check current mode
  951.                beq.s    .standby             ; standby mode ->
  952.  
  953.                subq     #1,d5                ; check if wait mode
  954.                beq.s    .wait                ; wait mode ->
  955.  
  956.  
  957. *------------- handler is in HOLD mode
  958.  
  959. .hold:         tst.b    d6                   ; hold mode: button condition true?
  960.                beq.s    .reset               ; no ->
  961.  
  962.                move     #1,BI_NCLICKS(a1)    ; 1 mouse click
  963.                move     d0,BI_SBSTATE(a1)    ; use current button state
  964.                st.b     BI_BEVALID(a1)       ; generate mouse click
  965.                bra      .exit
  966.  
  967. .reset:        clr      BI_BMODE(a1)         ; switch to standby mode
  968.                bra.s    .exit
  969.  
  970.  
  971. *------------- handler is in STANDBY mode
  972.  
  973. .standby:      tst.b    BI_BEVALID(a1)       ; old click still in buffer?
  974.                bne.s    .exit                ; yes ->
  975.  
  976.                tst.b    d6                   ; button condition true?
  977.                beq.s    .exit                ; no ->
  978.  
  979.                move     d0,BI_SBSTATE(a1)    ; save button state
  980.                moveq.l  #1,d5
  981.                move     d5,BI_BMODE(a1)      ; change to wait mode
  982.                move     d5,BI_NCLICKS(a1)    ; init # of clicks
  983.  
  984.                lea      timetab,a0           ; ^double click time table
  985.                move     BI_DCLTIME(a1),d5    ; double click time
  986.                add      d5,d5                ; *4 for index
  987.                add      d5,d5
  988.                move.l   (a0,d5),d5           ; get double click time
  989.                add.l    sysclock,d5          ; add current timer value
  990.                move.l   d5,BI_BENDTIME(a1)   ; save as end time
  991.  
  992.                moveq.l  #1,d5                ; find first button
  993.  
  994. .findbut:      add      d5,d5                ; next button
  995.                lsr      d7                   ; check next bit
  996.                bcs.s    .findbut             ; condition not true ->
  997.  
  998.                lsr      d5                   ; first found changed button
  999.  
  1000. .dcbut:        move     d5,BI_DCBUT(a1)      ; save double click button mask
  1001.                and      d0,d5                ; get 'active' state
  1002.                move     d5,BI_DCSTATE(a1)    ; save it
  1003.  
  1004.                bra.s    .exit                ; ->
  1005.  
  1006.  
  1007. *------------- handler is in WAIT mode
  1008.  
  1009. .wait:         tst.b    BI_BEVALID(a1)       ; old click still in buffer?
  1010.                bne.s    .exit                ; yes ->
  1011.  
  1012.                move     BI_DCBUT(a1),d5      ; double click button mask
  1013.                move     BI_PRVBSTATE(a1),d7  ; previous button state
  1014.                eor      d0,d7                ; get button state changes
  1015.                and      d5,d7                ; did dclick button state change?
  1016.                beq.s    .exit                ; no ->
  1017.  
  1018.                and      d0,d5                ; isolate state of dclick button
  1019.                cmp      BI_DCSTATE(a1),d5    ; changed it to 'active' state?
  1020.                bne.s    .exit                ; no ->
  1021.  
  1022.                moveq.l  #1,d7                ; yes: add 1 to # of clicks
  1023.                add      BI_NCLICKS(a1),d7
  1024.                cmp      BI_MAXCLICKS(a1),d7  ; > max # of clicks to wait for?
  1025.                bhi.s    .exit                ; yes ->
  1026.  
  1027.                move     d7,BI_NCLICKS(a1)    ; no: save new # of clicks
  1028.                add.l    #TIME_ADD,BI_BENDTIME(a1)  ; let user more time to click
  1029.  
  1030.  
  1031. *------------- leave interrupt
  1032.  
  1033. .exit:         move     d0,BI_PRVBSTATE(a1)  ; save button state
  1034.                movem.l  (sp)+,d5-d7/a0-a1    ; restore registers
  1035.                move.l   nk_butvec-4(pc),-(sp)   ; old vector address
  1036.  
  1037. nk_bvret:      rts                           ; jump to old routine
  1038.  
  1039.  
  1040.  
  1041.  
  1042. ****************************************************************************
  1043. *
  1044. *  nk_bestart: start special handling of button event
  1045. *  #
  1046. *
  1047. *  In:   -
  1048. *
  1049. *  Out:  D7.W           handler mode (used in nk_beend)
  1050. *
  1051. *  Reg:  D:01234567   A:01234567   CCR
  1052. *          **.....W     **......    *
  1053. *
  1054. ****************************************************************************
  1055.  
  1056. nk_bestart:    moveq.l  #0,d7                ; default: no special handling
  1057.                tst.b    buthnd               ; our handler installed?
  1058.                beq      .exit                ; no ->
  1059.  
  1060.                lea      nkc_intin,a0         ; ^event mask
  1061.                moveq.l  #MU_BUTTON,d0        ; request for button event?
  1062.                and      (a0),d0
  1063.                beq      .exit                ; no ->
  1064.  
  1065.  
  1066. *------------- configure timer event
  1067.  
  1068.                lea      bvar,a1              ; ^button event variables
  1069.                move     2(a0),d7             ; nclicks + reverse flag
  1070.                move.b   d7,BI_MAXCLICKS+1(a1)   ; isolate and save nclicks
  1071.                clr.b    d7                   ; isolate reverse flag
  1072.                move     d7,BI_REVCOND(a1)    ; save reverse flag
  1073.                move     4(a0),BI_BMASK(a1)   ; save button mask
  1074.                move     6(a0),BI_BSTATE(a1)  ; save button state
  1075.                                              ; new mouse button parameters:
  1076.                clr      4(a0)                ; mask = 0
  1077.                clr      6(a0)                ; state = 0
  1078.                moveq.l  #1,d7                ; new handler mode
  1079.                move     d7,2(a0)             ; also used for new nclicks
  1080.                                              ; -> button condition always true
  1081.  
  1082. *------------- configure timer event
  1083.  
  1084.                moveq.l  #MU_TIMER,d0         ; request for timer event?
  1085.                and      (a0),d0
  1086.                beq.s    .no_timer            ; no ->
  1087.  
  1088.                moveq.l  #2,d7                ; new mode
  1089.                move.l   28(a0),d0            ; time = 0 ms?
  1090.                beq.s    .exit                ; yes: fine, exactly what we need
  1091.  
  1092.                moveq.l  #3,d7                ; new mode
  1093.                swap     d0                   ; time in Motorola format
  1094.                cmp.l    prvtime,d0           ; identical to previous time?
  1095.                beq.s    .nulltime            ; yes ->
  1096.  
  1097.                move.l   d0,prvtime           ; no: save timer event value
  1098.                LWDIVU   #5,d0,d1             ; convert to 200 Hz resolution
  1099.                add.l    sysclock,d0          ; + current timer value
  1100.                move.l   d0,tendtime          ; this is our timer end value
  1101.  
  1102.                bra.s    .nulltime            ; and set own one
  1103.  
  1104.  
  1105. *------------- user doesn't want timer events - but we need them!
  1106.  
  1107. .no_timer:     moveq.l  #-1,d0               ; reset previous timer event value
  1108.                move.l   d0,prvtime
  1109.                or       #MU_TIMER,(a0)       ; set bit: check timer events
  1110.  
  1111. .nulltime:     clr.l    28(a0)               ; time: 0 ms
  1112.  
  1113. .exit:         rts                           ; bye
  1114.  
  1115.  
  1116.  
  1117.  
  1118. ****************************************************************************
  1119. *
  1120. *  nk_beend: end special handling of button event
  1121. *  #
  1122. *
  1123. *  In:   D7.W           handler mode:
  1124. *                       0     button event handler inactive
  1125. *                       1     user did not check timer events
  1126. *                       2     user did check timer events with time = 0 ms
  1127. *                       3     user did check timer events with time > 0 ms
  1128. *
  1129. *  Out:  nkc_intout.W[]:updated mouse event information
  1130. *
  1131. *  Reg:  D:01234567   A:01234567   CCR
  1132. *          **......     **......    *
  1133. *
  1134. ****************************************************************************
  1135.  
  1136. nk_beend:      lea      nkc_intout,a0        ; ^event mask
  1137.                move     d7,d0                ; which mode?
  1138.                beq      .exit                ; no special handling
  1139.  
  1140.                lea      bvar,a1              ; ^button event info block
  1141.                move     BI_PRVBSTATE(a1),6(a0)  ; return button state
  1142.  
  1143.  
  1144. *------------- analyze which events have occured
  1145.  
  1146.                moveq.l  #MU_MESAG,d1         ; did message event occur?
  1147.                and      (a0),d1              ; and with event mask
  1148.                beq.s    .chkflag             ; no message event ->
  1149.  
  1150.                and      #!MU_BUTTON,(a0)     ; no button event
  1151.  
  1152. .chkflag:      moveq.l  #MU_BUTTON,d1        ; did button event occur?
  1153.                and      (a0),d1              ; (if not: just moving a window
  1154.                                              ;  or something like that)
  1155.                beq.s    .lock                ; no -> lock mouse button event
  1156.  
  1157.  
  1158. *------------- application has mouse under its control; what now?
  1159.  
  1160.                tst.b    BI_LOCK(a1)          ; is button event locked?
  1161.                bne      .unlock              ; yes -> unlock it
  1162.  
  1163.                tst.b    BI_BEVALID(a1)       ; event valid?
  1164.                bne.s    .butev               ; yes ->
  1165.  
  1166.  
  1167. *------------- mouse click isn't finished, yet; wait
  1168.  
  1169.                move     BI_BMODE(a1),d1      ; no: get handler mode
  1170.                beq.s    .nombut              ; standby mode ->
  1171.  
  1172.                subq     #1,d1                ; wait mode?
  1173.                beq.s    .wait                ; yes ->
  1174.  
  1175. .hold:         clr      12(a0)               ; # of clicks = 0
  1176.                bra.s    .evtimer
  1177.  
  1178. .wait:         move.l   BI_BENDTIME(a1),d1   ; button event end time
  1179.                cmp.l    sysclock,d1          ; end of time reached?
  1180.                bhi.s    .nombut              ; no ->
  1181.  
  1182.                addq     #1,BI_BMODE(a1)      ; change to hold mode
  1183.                tst.b    BI_CVALID(a1)        ; was last button condition valid?
  1184.                bne.s    .butev               ; yes ->
  1185.  
  1186.                clr      BI_BMODE(a1)         ; no: standby mode
  1187.  
  1188. .butev:        move     BI_NCLICKS(a1),12(a0)   ; return # of clicks
  1189.                move     BI_SBSTATE(a1),6(a0)    ; return start button state
  1190.                sf.b     BI_BEVALID(a1)       ; button event fetched
  1191.                bra.s    .evtimer
  1192.  
  1193. .nombut:       and      #!MU_BUTTON,(a0)     ; no mouse button event
  1194.  
  1195.  
  1196. *------------- timer event handling
  1197.  
  1198. .evtimer:      subq     #1,d0                ; timer event checked by us?
  1199.                beq.s    .nktimer             ; yes ->
  1200.  
  1201.                subq     #1,d0                ; 0 ms timer checked by user?
  1202.                beq.s    .exit                ; yes ->
  1203.  
  1204. .user0:        move.l   tendtime,d1          ; timer event end time
  1205.                cmp.l    sysclock,d1          ; end of waiting time reached?
  1206.                bls.s    .exit                ; yes ->
  1207.  
  1208. .nktimer:      and      #!MU_TIMER,(a0)      ; no timer event occured
  1209.  
  1210. .exit:         move     (a0),d0              ; event mask
  1211.                and      #MU_TIMER,d0         ; did a timer event occur?
  1212.                beq.s    .exit2               ; no ->
  1213.  
  1214. .treset:       moveq.l  #-1,d0               ; yes: reset previous timer
  1215.                move.l   d0,prvtime           ;  event value
  1216.  
  1217. .exit2:        rts
  1218.  
  1219.  
  1220. *------------- AES didn't return MU_BUTTON -> screen manager has taken mouse
  1221. *              control: don't create MU_BUTTON events
  1222.  
  1223. .lock:         st.b     BI_LOCK(a1)          ; lock mouse button event
  1224.                move     #MU_XTIMER,d1        ; lock timer events, too?
  1225.                and      nkc_intin,d1         ; check this flag
  1226.                beq.s    .evtimer             ; don't lock ->
  1227.  
  1228.                bra.s    .nktimer             ; lock ->
  1229.  
  1230.  
  1231. *------------- AES did return MU_BUTTON (applications has mouse under its
  1232. *              control) but the button events were locked previously: unlock
  1233. *              them
  1234.  
  1235. .unlock:       sf.b     BI_LOCK(a1)          ; unlock mouse button event
  1236.                clr      BI_BMODE(a1)         ; reset mode
  1237.                sf.b     BI_BEVALID(a1)       ; reset button event flag
  1238.                bra.s    .nombut
  1239.  
  1240.  
  1241.  
  1242. ****************************************************************************
  1243. *
  1244. *  nk_mctrl: set control array for multi event
  1245. *  #
  1246. *
  1247. *  In:   -
  1248. *
  1249. *  Out:  nkc_contrl.W[]: control parameters configured for evnt_multi() call
  1250. *
  1251. *  Reg:  D:01234567   A:01234567   CCR
  1252. *          ........     *.......    *
  1253. *
  1254. ****************************************************************************
  1255.  
  1256. nk_mctrl:      lea      nkc_contrl,a0        ; ^control array
  1257.                move     #25,(a0)+            ; opcode
  1258.                move     #16,(a0)+            ; size of intin
  1259.                move     #7,(a0)+             ; size of intout
  1260.                move     #1,(a0)+             ; size of addrin
  1261.                clr      (a0)                 ; size of addrout
  1262.                rts                           ; bye
  1263.  
  1264.  
  1265.  
  1266.  
  1267. ****************************************************************************
  1268. *
  1269. *  nk_msave: save input parameters for evnt_multi() call in buffer
  1270. *  #
  1271. *
  1272. *  In:   -
  1273. *
  1274. *  Out:  multibuf.W[]:  first 16 words of nkc_intin and first long of
  1275. *                          nkc_adrin
  1276. *
  1277. *  Reg:  D:01234567   A:01234567   CCR
  1278. *          *******.     **......    *
  1279. *
  1280. ****************************************************************************
  1281.  
  1282. nk_msave:      lea      nkc_intin,a0         ; ^intin array
  1283.                lea      multibuf,a1          ; ^save buffer
  1284.                movem.l  (a0)+,d0-d6          ; get first 14 words of nkc_intin
  1285.                movem.l  d0-d6,(a1)           ; save 'em in buffer
  1286.                move.l   (a0),7*4(a1)         ; save last two words
  1287.                move.l   nkc_adrin,8*4(a1)    ; save contents of addrin
  1288.                rts
  1289.  
  1290.  
  1291.  
  1292.  
  1293. ****************************************************************************
  1294. *
  1295. *  nk_mrestore: restore evnt_multi() input parameters corrupted by AES(!)
  1296. *  #
  1297. *
  1298. *  In:   -
  1299. *
  1300. *  Out:  nkc_contrl.w[]: restored data (5 words)
  1301. *        nkc_intin.w[] : restored data (16 words)
  1302. *        nkc_adrin.L[] : restored data (1 longword)
  1303. *
  1304. *  Reg:  D:01234567   A:01234567   CCR
  1305. *          *******.     **......    *
  1306. *
  1307. ****************************************************************************
  1308.  
  1309. nk_mrestore:   lea      multibuf,a0          ; ^save buffer
  1310.                lea      nkc_intin,a1         ; ^intin array
  1311.                movem.l  (a0)+,d0-d6          ; first 14 words of nkc_intin
  1312.                movem.l  d0-d6,(a1)           ; put them in nkc_intin array
  1313.                move.l   (a0)+,7*4(a1)        ; last two words
  1314.                move.l   (a0),nkc_adrin       ; restore addrin array
  1315.                bra.s    nk_mctrl             ; restore contrl array
  1316.  
  1317.                .endif   ; .if NKCGEM=1
  1318.  
  1319.  
  1320.  
  1321.  
  1322. ****************************************************************************
  1323. *
  1324. *  nk_200hz: 200 Hz system clock interrupt
  1325. *  # I S
  1326. *
  1327. *  In:   -
  1328. *
  1329. *  Out:  -
  1330. *
  1331. *  Reg:  D:01234567   A:01234567   CCR
  1332. *          ........     ........    *
  1333. *
  1334. ****************************************************************************
  1335.  
  1336.                XBRA_HD  0                    ; XBRA header
  1337.  
  1338. nk_200hz:      move.l   _hz_200,sysclock     ; just transfer value
  1339.                move.l   nk_200hz-4(pc),-(sp) ; old vector address
  1340.                rts                           ; jump to old routine
  1341.  
  1342.  
  1343.  
  1344. *START
  1345. ****************************************************************************
  1346. *                            GLOBAL TEXT SECTION                           *
  1347. ****************************************************************************
  1348. *END
  1349.  
  1350.                .text
  1351.  
  1352. *START
  1353. ****************************************************************************
  1354. *
  1355. *  nkc_init: initialize NKCC
  1356. *  # G U
  1357. *
  1358. *  C prototype: int nkc_init(unsigned long flags,int vdihnd,int *pglobal);
  1359. *---------------------------------------------------------------------------
  1360. *  This function initializes NKCC. It must be called once before any other
  1361. *  NKCC routine. It performs some tasks that may be important for you to
  1362. *  know:
  1363. *
  1364. *  - bit 3 of the system variable <conterm> ($484.B) is set
  1365. *  - a 200 Hz clock interrupt is installed, using the XBRA method (ID is
  1366. *    "NKCC")
  1367. *
  1368. *  nkc_init() gets some flags which configure NKCC and enable some special
  1369. *  functions:
  1370. *
  1371. *  NKI?_BUTHND       install NKCC's button event handler (see documentation
  1372. *                    NKCC.DOC for details)
  1373. *  NKI?_BHTOS        additional flag: install only, if TOS has mouse click bug
  1374. *  NKI?_NO200HZ      don't install the 200 Hz timer interrupt
  1375. *
  1376. *  Notes:
  1377. *
  1378. *  - if NKCC is assembled as TOS-only version (symbol NKCGEM set to 0),
  1379. *    both NKI?_BUTHND and NKI?_BHTOS flags are ignored.
  1380. *
  1381. *  - if the button event handler is installed, the NKI?_NO200HZ flag is
  1382. *    ignored (because the 200 Hz clock is needed by the handler). Besides,
  1383. *    the initialization continues:
  1384. *
  1385. *    - an own GEM trap handler (trap #2) is installed, using the XBRA method
  1386. *      (to be up to date when a new double click time is set via the AES
  1387. *      function evnt_dclick())
  1388. *
  1389. *    - a vex_butv() call (VDI) is made to install a mouse button exchange
  1390. *      handler
  1391. *
  1392. *  In:   D0.L           miscellaneous flags (NKI?_...); see above
  1393. *        D1.W           handle of an open VDI workstation
  1394. *                       (must only be valid if the button handler is
  1395. *                       installed)
  1396. *        A0.L           ^applications GLOBAL array (from GEM parameter block)
  1397. *                       not used in the TOS version of NKCC
  1398. *
  1399. *  Out:  D0.W           NKCC's version number as 4 digit BCD
  1400. *                       (main # in high byte, sub # in low byte)
  1401. *
  1402. *  Reg:  D:01234567   A:01234567   CCR
  1403. *          U**.....     **......    *
  1404. *
  1405. ****************************************************************************
  1406. *END
  1407.  
  1408. nkc_init:      move.l   a2,-(sp)             ; save a2 for Turbo C/Pure C
  1409.  
  1410.                movem.l  d0-d1,-(sp)          ; save flags and VDI handle
  1411.                subq.l   #2,sp                ; one word local stack space
  1412.  
  1413.                .if      NKCGEM=1
  1414.  
  1415.                 move.l  a0,aespb+4           ; keep ^global array
  1416.  
  1417.                 move    #1,-(sp)             ; device: keyboard
  1418.                 move    #14,-(sp)            ; function opcode: Iorec
  1419.                 trap    #14                  ; XBIOS
  1420.                 addq.l  #4,sp                ; clean stack
  1421.                 move.l  d0,kbdiorec          ; keep ^IOREC structure
  1422.                 move.l  d0,a0                ; load into address register
  1423.                 move    IBUFHD(a0),iohead    ; keep current head pointer
  1424.  
  1425.                .endif   ; .if NKCGEM=1
  1426.  
  1427.  
  1428. *------------- switch to Supervisor mode to have access to system variables
  1429.  
  1430.                clr.l    -(sp)                ; use usp as ssp
  1431.                move     #$20,-(sp)           ; Super
  1432.                trap     #1                   ; GEMDOS
  1433.                move.l   d0,2(sp)             ; save old sp
  1434.                move     #$20,(sp)            ; Super opcode for next call
  1435.  
  1436.  
  1437. *------------- enable auto return of shift/ctrl/alt status
  1438.  
  1439.                bset.b   #3,conterm.w         ; set bit for auto shift return
  1440.  
  1441.  
  1442. *------------- locate shift state system variable
  1443.  
  1444.                move.l   _sysbase.w,a0        ; ^OS header
  1445.                move     2(a0),d0             ; get TOS version
  1446.                move     d0,6(sp)             ; save it in local stack space
  1447.                cmp      #$0100,d0            ; TOS 1.0?
  1448.                beq.s    .tos10               ; yes ->
  1449.  
  1450.                move.l   $24(a0),pshift       ; get ^shift state variable
  1451.                bra.s    .user                ; ->
  1452.  
  1453. .tos10:        move.l   #$e1b,pshift         ; this is the location in TOS 1.0
  1454.  
  1455.  
  1456. *------------- switch back to user mode
  1457.  
  1458. .user:         trap     #1                   ; GEMDOS
  1459.                addq     #6,sp                ; clean stack
  1460.  
  1461.  
  1462. *------------- fetch addresses of TOS' key scan code translation tables
  1463.  
  1464.                moveq.l  #-1,d0               ; the function is also used to
  1465.                move.l   d0,-(sp)             ;  change the addresses; values
  1466.                move.l   d0,-(sp)             ;  of -1 as new addresses tell
  1467.                move.l   d0,-(sp)             ;  XBIOS not to change them
  1468.                move     #$10,-(sp)           ; Keytbl
  1469.                trap     #14                  ; XBIOS
  1470.                lea      $e(sp),sp            ; clean stack
  1471.  
  1472.                move.l   d0,a0                ; ^key table structure
  1473.                move.l   (a0)+,pkey_unshift   ; get ^unshifted table
  1474.                move.l   (a0)+,pkey_shift     ; get ^shifted table
  1475.                move.l   (a0),pkey_caps       ; get ^CapsLock table
  1476.  
  1477.  
  1478. *------------- do some other initialization stuff
  1479.  
  1480.                clr.l    sflags               ; reset special key flags
  1481.                clr.b    prvvalid             ; no previous key code
  1482.  
  1483.  
  1484. *------------- install the mouse button handler
  1485.  
  1486.                move     (sp)+,d0             ; TOS version
  1487.                movem.l  (sp),d1-d2           ; restore flags and VDI handle
  1488.  
  1489.                .if      NKCGEM=1
  1490.  
  1491.                 clr.b   buthnd               ; default: set flag: not installed
  1492.                 btst.l  #NKIb_BUTHND,d1      ; install it?
  1493.                 beq     .timer               ; no ->
  1494.  
  1495.                 btst.l  #NKIb_BHTOS,d1       ; check TOS version number?
  1496.                 beq.s   .butev               ; no ->
  1497.  
  1498.                 cmp     #$0104,d0            ; bug appeared in TOS 1.04!
  1499.                 blo     .timer               ; TOS is ok ->
  1500.  
  1501.                 cmp     #$0306,d0            ; bug is solved since TOS 3.06!
  1502.                 bhs     .timer               ; TOS is ok ->
  1503.  
  1504. .butev:         bclr.l  #NKIb_NO200HZ,d1     ; must install timer interrupt
  1505.                 st.b    buthnd               ; set flag: handler installed
  1506.                 move    d2,vdihnd            ; save VDI handle
  1507.  
  1508.                 moveq.l #0,d0                ; do some initializations
  1509.                 lea     bvar,a1              ; ^button event info block
  1510.                 move    d0,BI_BMODE(a1)      ; init interrupt mode
  1511.                 move.b  d0,BI_BEVALID(a1)    ; mouse click info not valid
  1512.                 move    d0,BI_PRVBSTATE(a1)  ; init previous button state
  1513.                 move    d0,BI_BMASK(a1)      ; don't check any button
  1514.                 move.b  d0,BI_LOCK(a1)       ; mouse button event isn't locked
  1515.                 subq.l  #1,d0                ; d0.l = -1
  1516.                 move    d0,BI_REVCOND(a1)    ; reverse button condition
  1517.                                              ; -> no mouse click is checked
  1518.                 move.l  d0,prvtime           ; previous timer event value
  1519.  
  1520.                 lea     nkc_contrl,a0        ; set parameter array for vex_butv
  1521.                 move    #125,(a0)+           ; opcode
  1522.                 clr.l   (a0)+                ; no ptsin/ptsout entries
  1523.                 clr.l   (a0)+                ; no intin/intout entries
  1524.                 addq    #2,a0                ; entry #5 is unused
  1525.                 move    d2,(a0)+             ; handle of workstation
  1526.                 lea     nk_butvec(pc),a1     ; ^our handler
  1527.                 move.l  a1,(a0)
  1528.                 moveq.l #115,d0              ; opcode: VDI
  1529.                 move.l  #vdipb,d1            ; ^parameter block
  1530.                 trap    #2                   ; execute VDI
  1531.                 move.l  nkc_contrl+18,nk_butvec-4  ; save old handler address
  1532.  
  1533.                 lea     nkc_contrl,a0        ; set parameter for evnt_dclick
  1534.                 move    #26,(a0)+            ; opcode
  1535.                 move    #2,(a0)+             ; # of entries in intin
  1536.                 move    #1,(a0)+             ; # of entries in intout
  1537.                 clr.l   (a0)+                ; no entries in addrin/addrout
  1538.                 clr     nkc_intin+2          ; get/set flag: get value
  1539.                 move    #200,d0              ; opcode for AES
  1540.                 move.l  #aespb,d1            ; ^parameter block
  1541.                 trap    #2                   ; execute AES
  1542.                 move    nkc_intout,bvar+BI_DCLTIME    ; save double click time
  1543.  
  1544.                                              ; install trap #2 handler
  1545.                 moveq.l #34,d0               ; vector number
  1546.                 moveq.l #NKXM_NUM,d1         ; mode: vector number
  1547.                 lea     nk_gemtrap(pc),a0    ; ^function to install
  1548.                 bsr     nkc_vlink            ; install it
  1549.  
  1550.                .endif   ; .if NKCGEM=1
  1551.  
  1552.  
  1553. *------------- install 200 Hz clock interrupt
  1554.  
  1555. .timer:        clr.l    sysclock             ; init 200 Hz clock for the case
  1556.                                              ; that the timer won't be installed
  1557.                movem.l  (sp)+,d1-d2          ; restore flags and VDI handle
  1558.                btst.l   #NKIb_NO200HZ,d1     ; install interrupt?
  1559.                seq.b    timerflag            ; $00 = no, $ff = yes
  1560.                bne.s    .exit                ; no ->
  1561.  
  1562.                moveq.l  #69,d0               ; vector number
  1563.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1564.                lea      nk_200hz(pc),a0      ; ^function to install
  1565.                bsr      nkc_vlink            ; install it
  1566.  
  1567.  
  1568. *------------- restore saved register and exit
  1569.  
  1570. .exit:         move.l   (sp)+,a2             ; restore register
  1571.                move     #VERSION,d0          ; load version #
  1572.                rts                           ; bye
  1573.  
  1574.  
  1575.  
  1576. *START
  1577. ****************************************************************************
  1578. *
  1579. *  nkc_exit: exit NKCC
  1580. *  # G U
  1581. *
  1582. *  C prototype: int nkc_exit(void);
  1583. *---------------------------------------------------------------------------
  1584. *  nkc_exit() must be called before the program is quit. It removes all
  1585. *  handlers installed in the system.
  1586. *
  1587. *  In:   -
  1588. *
  1589. *  Out:  D0.W           status flag:
  1590. *                       0     OK
  1591. *                       -1    can't remove 200 Hz clock interrupt
  1592. *                       -2    can't remove trap #2 handler
  1593. *                       -3    can't remove both handlers
  1594. *                       An error can happen if somebody corrupted the
  1595. *                       XBRA vector list. This is fatal!
  1596. *
  1597. *  Reg:  D:01234567   A:01234567   CCR
  1598. *          ***.....     **......   =D0.W
  1599. *
  1600. ****************************************************************************
  1601. *END
  1602.  
  1603. nkc_exit:      move.l   a2,-(sp)             ; save register
  1604.  
  1605.  
  1606. *------------- remove 200 Hz system clock interrupt
  1607.  
  1608.                clr      -(sp)                ; default remove status for
  1609.                                              ;  timer interrupt
  1610.                tst.b    timerflag            ; installed?
  1611.                beq.s    .buthnd              ; no ->
  1612.  
  1613.                moveq.l  #69,d0               ; vector number
  1614.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1615.                lea      nk_200hz(pc),a0      ; ^function to remove
  1616.                bsr      nkc_vunlink          ; remove it
  1617.                move     d0,(sp)              ; save remove status
  1618.  
  1619.  
  1620. *------------- remove own button event handler
  1621.  
  1622. .buthnd:       clr      -(sp)                ; default remove status for
  1623.                                              ;  button event handler
  1624.  
  1625.                .if      NKCGEM=1
  1626.  
  1627.                tst.b    buthnd               ; handler installed?
  1628.                beq.s    .exit                ; no ->
  1629.  
  1630.                lea      nkc_contrl,a0        ; set paremeter array for vex_butv
  1631.                move     #125,(a0)+           ; opcode
  1632.                clr.l    (a0)+                ; no ptsin/ptsout entries
  1633.                clr.l    (a0)+                ; no intin/intout entries
  1634.                addq     #2,a0                ; entry #5 is unused
  1635.                move     vdihnd,(a0)+         ; handle of workstation
  1636.                lea      nk_butvec(pc),a1     ; ^our handler
  1637.                move.l   -4(a1),(a0)          ; ^old routine
  1638.                moveq.l  #115,d0              ; opcode: VDI
  1639.                move.l   #vdipb,d1            ; ^parameter block
  1640.                trap     #2                   ; execute VDI
  1641.  
  1642.                                              ; remove trap #2 handler
  1643.                moveq.l  #34,d0               ; vector number
  1644.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1645.                lea      nk_gemtrap(pc),a0    ; ^function to remove
  1646.                bsr      nkc_vunlink          ; remove it
  1647.                move     d0,(sp)              ; save status
  1648.  
  1649.                .endif   ; .if NKCGEM=1
  1650.  
  1651.  
  1652. *------------- restore saved registers and exit
  1653.  
  1654. .exit:         move     (sp)+,d0             ; trap #2 remove error?
  1655.                beq.s    .stat0               ; no ->
  1656.  
  1657.                move     (sp)+,d0             ; 200 Hz clock remove error?
  1658.                beq.s    .stat1               ; no ->
  1659.  
  1660.                moveq.l  #-3,d0               ; both failed!
  1661.                bra.s    .ret
  1662.  
  1663. .stat0:        move     (sp)+,d0             ; 200 Hz clock remove error?
  1664.                beq.s    .ret                 ; no ->
  1665.  
  1666.                moveq.l  #-1,d0               ; "only" 200 Hz clock failure?
  1667.                bra.s    .ret
  1668.  
  1669. .stat1:        moveq.l  #-2,d0               ; "only" trap #2 remove failure?
  1670.  
  1671. .ret:          move.l   (sp)+,a2             ; restore register
  1672.                rts                           ; bye
  1673.  
  1674.  
  1675.  
  1676. *START
  1677. ****************************************************************************
  1678. *
  1679. *  nkc_set: set special key flags
  1680. *  # G
  1681. *
  1682. *  C prototype: void nkc_set(unsigned long flags);
  1683. *---------------------------------------------------------------------------
  1684. *  This function is used to enable/disable special key handling procedures.
  1685. *  The features which can be set are:
  1686. *
  1687. *  - direct input of ASCII codes; when switched on, pressing the Alternate
  1688. *    key plus one of the numbers on the numeric keypad will start the input
  1689. *    of a decimal ASCII number. The input is finished either when 3 digits
  1690. *    are typed in or the Alternate key is released. NKCC will return the
  1691. *    corresponding character with the entered ASCII code. This feature makes
  1692. *    it possible to use the whole range of the character set (from 0 ... 255).
  1693. *
  1694. *  - deadkey management; when switched on, NKCC will combine some combi-
  1695. *    nations of two key strokes to one character. This is used to generate
  1696. *    characters with accents which are not on the keyboard. The supported
  1697. *    deadkeys are:
  1698. *
  1699. *    ^   +   aeiou      =  âêîôû       (NKS?_D_CIRCUM)
  1700. *    ~   +   nNaoAo     =  ñÑ░▒╖╕      (NKS?_D_TILDE)
  1701. *    '   +   eEaiou     =  éÉáíóú      (NKS?_D_AGUI)
  1702. *    `   +   aeiouA     =  àèìòù╢      (NKS?_D_GRAVE)
  1703. *    ╣   +   aeiouyAOU  =  äëïöüÿÄÖÜ   (NKS?_D_UMLAUT)
  1704. *    "   +   aeiouyAOU  =  äëïöüÿÄÖÜ   (NKS?_D_QUOTE)
  1705. *    °   +   aA         =  åÅ          (NKS?_D_SMOERE)
  1706. *    ,   +   cC         =  çÇ          (NKS?_D_CEDIL)
  1707. *    /   +   oO24       =  │▓½¼        (NKS?_D_SLASH)
  1708. *
  1709. *    The quote character as synonym for umlaut is e.g. needed on the Dutch
  1710. *    keyboard, where neither umlaut characters nor the umlaut itself are
  1711. *    available.
  1712. *
  1713. *    Each deadkey can be enabled/disabled separately.
  1714. *
  1715. *  - Control key emulation: Control plus an ASCII code in the range of
  1716. *    $40...$5F (characters @, A...Z, [, \, ], ^ and _) is converted
  1717. *    to an ASCII code of $00...$1F.
  1718. *
  1719. *
  1720. *  In:   D0.L           new key flags (bit set = feature on):
  1721. *                       NKS?_ALTNUM       ASCII input
  1722. *                       NKS?_D_...        deadkey ...
  1723. *                                         (NKSf_DEADKEY: all deadkeys)
  1724. *                       NKS?_CTRL         control key emulation
  1725. *
  1726. *  Out:  -
  1727. *
  1728. *  Reg:  D:01234567   A:01234567   CCR
  1729. *          ***.....     **......    *
  1730. *
  1731. ****************************************************************************
  1732. *END
  1733.  
  1734. nkc_set:       move.l   d0,sflags            ; just save flags
  1735.                rts                           ; bye
  1736.  
  1737.  
  1738.  
  1739. *START
  1740. ****************************************************************************
  1741. *
  1742. *  nkc_conin: raw console character input
  1743. *  # G
  1744. *
  1745. *  C prototype: int nkc_conin(void);
  1746. *---------------------------------------------------------------------------
  1747. *  This routine replaces the Gemdos function Crawcin. However, it returns
  1748. *  a WORD with the key code in normalized format rather than a LONG with
  1749. *  the key code in the language dependend TOS format.
  1750. *
  1751. *  In:   -
  1752. *
  1753. *  Out:  D0.W           key code in normalized format
  1754. *                       for details see nkc_tconv()
  1755. *        CCR            set according content of D0.W
  1756. *
  1757. *  Reg:  D:01234567   A:01234567   CCR
  1758. *          W**.....     **......   =D0.W
  1759. *
  1760. ****************************************************************************
  1761. *END
  1762.  
  1763. nkc_conin:     tst.b    prvvalid             ; previous character in buffer?
  1764.                beq.s    .getkey              ; no->
  1765.  
  1766.                clr.b    prvvalid             ; remove key code from buffer
  1767.                move     prvkey,d0            ; get key code
  1768.                rts                           ; bye
  1769.  
  1770.  
  1771. .getkey:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  1772.                clr      d0                   ; don't check Alternate state
  1773.                bsr      nk_gci               ; get key code
  1774.                lea      nk_gci(pc),a0        ; ^function to execute
  1775.                bsr      nk_spec              ; special key handling
  1776.                movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  1777.                rts                           ; bye
  1778.  
  1779.  
  1780.  
  1781. *START
  1782. ****************************************************************************
  1783. *
  1784. *  nkc_cstat: return console character input status
  1785. *  # G
  1786. *
  1787. *  C prototype: int nkc_cstat(void);
  1788. *---------------------------------------------------------------------------
  1789. *  This function checks, if a key is in the key input buffer or not.
  1790. *
  1791. *  In:   -
  1792. *
  1793. *  Out:  D0.W           flag:
  1794. *                       0     no key in buffer
  1795. *                       -1    at least one key in buffer
  1796. *        CCR            set according content of D0.W
  1797. *
  1798. *  Reg:  D:01234567   A:01234567   CCR
  1799. *          W**.....     **......   =D0.W
  1800. *
  1801. ****************************************************************************
  1802. *END
  1803.  
  1804. nkc_cstat:     tst.b    prvvalid             ; previous character in buffer?
  1805.                sne.b    d0                   ; $ff = yes, $00 = no
  1806.                ext      d0                   ; as word
  1807.                bne.s    .exit                ; char available: exit
  1808.  
  1809.                move.l   a2,-(sp)             ; save register for Turbo C/Pure C
  1810.  
  1811.                move     #11,-(sp)            ; Cconis
  1812.                trap     #1                   ; Gemdos
  1813.                addq     #2,sp                ; clean stack
  1814.  
  1815.                move.l   (sp)+,a2             ; restore register
  1816.                tst      d0                   ; set CCR
  1817.  
  1818. .exit:         rts                           ; bye
  1819.  
  1820.  
  1821.  
  1822.                .if      NKCGEM=1
  1823.  
  1824. *START
  1825. ****************************************************************************
  1826. *
  1827. *  nkc_multi: NKCC multi event
  1828. *  # G U
  1829. *
  1830. *  C prototype: int cdecl nkc_multi(
  1831. *                  int mflags,
  1832. *                  int mbclicks,int mbmask,int mbstate,
  1833. *                  int mm1flags,int mm1x,int mm1y,int mm1width,int mm1height,
  1834. *                  int mm2flags,int mm2x,int mm2y,int mm2width,int mm2height,
  1835. *                  int *mmgpbuff,
  1836. *                  int mtlocount,int mthicount,
  1837. *                  int *mmox,int *mmoy,int *mmbutton,int *mmokstate,
  1838. *                  int *mkreturn,int *mbreturn);
  1839. *---------------------------------------------------------------------------
  1840. *  nkc_multi() is a binding function to the AES multi event handler. The
  1841. *  only differences are the keyboard events and the shift key state: the key
  1842. *  codes are returned in normalized format (see nkc_tconv()), the shift key
  1843. *  state is compatible to the NKF?_... flags. For a detailed description of
  1844. *  the whole mass of parameters consult your AES manual or compiler handbook!
  1845. *
  1846. *  In:    4(SP).w       event mask (MU_...)
  1847. *         6(SP).w       MU_BUTTON: max # of clicks to wait for
  1848. *         8(SP).w       MU_BUTTON: mask of buttons to check
  1849. *        10(SP).w       MU_BUTTON: button states to wait for
  1850. *        12(SP).w       MU_M1: area enter/leave flag
  1851. *        14(SP).w       MU_M1: x position of area
  1852. *        16(SP).w       MU_M1: y position of area
  1853. *        18(SP).w       MU_M1: width of area
  1854. *        20(SP).w       MU_M1: height of area
  1855. *        22(SP).w       MU_M2: area enter/leave flag
  1856. *        24(SP).w       MU_M2: x position of area
  1857. *        26(SP).w       MU_M2: y position of area
  1858. *        28(SP).w       MU_M2: width of area
  1859. *        30(SP).w       MU_M2: height of area
  1860. *        32(SP).L       MU_MESAG: ^8 words of message buffer
  1861. *        36(SP).w       MU_TIMER: low word of time to wait
  1862. *        38(SP).w       MU_TIMER: high word of time to wait
  1863. *        40(SP).L       MU_BUTTON/M1/M2: ^word for mouse x
  1864. *        44(SP).L       MU_BUTTON/M1/M2: ^word for mouse y
  1865. *        48(SP).L       MU_BUTTON/M1/M2: ^word for button state
  1866. *        52(SP).L       MU_BUTTON/M1/M2: ^word for shift state
  1867. *        56(SP).L       MU_KEYBD: ^word for key code in normalized format
  1868. *        60(SP).L       MU_BUTTON: ^word for # of mouse clicks
  1869. *
  1870. *  Out:  D0.W           mask of occured events (MU_...)
  1871. *
  1872. *  Reg:  D:01234567   A:01234567   CCR
  1873. *          W**.....     **......    *
  1874. *
  1875. ****************************************************************************
  1876. *END
  1877.  
  1878. nkc_multi:     tst.b    prvvalid             ; previous character in buffer?
  1879.                beq.s    .mevent              ; no ->
  1880.  
  1881.                clr.b    prvvalid             ; remove key code from buffer
  1882.                move.l   56(sp),a0            ; ^buffer for key code
  1883.                move     prvkey,(a0)          ; return key code
  1884.                moveq.l  #MU_KEYBD,d0         ; a keyboard event occured
  1885.                rts                           ; bye
  1886.  
  1887. .mevent:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  1888.  
  1889.  
  1890. *------------- transfer stack arguments to GEM parameter arrays
  1891.  
  1892.                lea      10*4+4(sp),a0        ; ^first parameter
  1893.                lea      nkc_intin,a1         ; ^integer in array
  1894.                movem.l  (a0)+,d1-d7          ; get the first 14 words
  1895.                movem.l  d1-d7,(a1)           ; place them in intin
  1896.                move.l   (a0)+,nkc_adrin      ; ^message buffer in addrin
  1897.                move.l   (a0),7*4(a1)         ; timer event lo and hi count
  1898.  
  1899.                bsr      nk_mctrl             ; setup control array
  1900.  
  1901.  
  1902. *------------- execute multi event
  1903.  
  1904.                bsr      nk_bestart           ; start handling for button event
  1905.                bsr      nk_msave             ; save multi event parameters
  1906.  
  1907. .wait:         cmp      #25,nkc_contrl       ; still evnt_multi() opcode?!?
  1908.                beq.s    .aes                 ; yes ->
  1909.  
  1910.                bsr      nk_mrestore          ; NO! AES corrupted it! restore
  1911.  
  1912. .aes:          lea      nkc_intin,a0         ; ^intin
  1913.                move     (a0),-(sp)           ; save event mask
  1914.                and      #!MU_XTIMER,(a0)     ; clear x-timer flag
  1915.                move     #200,d0              ; opcode for AES
  1916.                move.l   #aespb,d1            ; ^AES parameter block
  1917.                trap     #2                   ; call GEM
  1918.                move     (sp)+,nkc_intin      ; restore event mask
  1919.  
  1920.                move     nkc_intout,d0        ; mask of occured events
  1921.                and      #MU_KEYBD,d0         ; keyboard event?
  1922.                bne.s    .buthnd              ; yes ->
  1923.  
  1924.                move.l   kbdiorec,a0          ; no: get ^keyboard's I/O record
  1925.                move     IBUFHD(a0),iohead    ; reset NKCC's head pointer
  1926.  
  1927. .buthnd:       bsr      nk_beend             ; end handling of button event
  1928.                tst      nkc_intout           ; did any event occur?
  1929.                beq.s    .wait                ; no ->
  1930.  
  1931.  
  1932. *------------- return intout parameters via pointers
  1933.  
  1934.                movem.l  10*4+40(sp),a0-a5    ; get return pointers
  1935.                lea      nkc_intout,a6        ; ^intout array
  1936.                move     (a6)+,d0             ; mask of occured events
  1937.                move     (a6)+,(a0)           ; mouse x
  1938.                move     (a6)+,(a1)           ; mouse y
  1939.                move     (a6)+,(a2)           ; mouse button state
  1940.                move.b   1(a6),(a3)           ; shift key state (NKC flag
  1941.                                              ;  compatible!)
  1942.                clr.b    1(a3)                ; clear low byte of shift state
  1943.                move.l   a6,a3                ; ^shift state in intout
  1944.                move     4(a6),(a5)           ; # of mouse clicks
  1945.                move     2(a6),(a4)           ; key code
  1946.  
  1947. * You wonder why (a4) is written as last one and (a3) points to intout
  1948. * instead of the original return location? This is for the case that
  1949. * the caller isn't interested in one or some of the return values and
  1950. * let them point to ONE dummy variable.
  1951.  
  1952.  
  1953. *------------- check if keyboard event occured and convert key code, if so
  1954.  
  1955.                moveq.l  #MU_KEYBD,d1         ; the flag to test
  1956.                and      d0,d1                ; is it set?
  1957.                beq.s    .exit                ; no-> exit
  1958.  
  1959.                move     d0,-(sp)             ; save event mask
  1960.                move.l   a4,-(sp)             ; save ^key code
  1961.  
  1962.                move     (a4),d0              ; scan code + ASCII code
  1963.                moveq.l  #MU_BUTTON|MU_M1|MU_M2,d1  ; any of the events checked
  1964.                and      10*4+4+6(a7),d1      ; which return shift state?
  1965.                bne.s    .useiout             ; yes->
  1966.  
  1967.                move.l   pshift,a3            ; no: get shift state directly
  1968.                move.b   (a3),d1              ; get it
  1969.                and      #$f,d1               ; isolate valid bits
  1970.                bra.s    .conv
  1971.  
  1972. .useiout:      move     (a3),d1              ; get shift state from intout
  1973.  
  1974. .conv:         bsr      nk_bioscode          ; convert to BIOS format
  1975.                bsr      nk_real_shift        ; try to get original shift flags
  1976.                bsr      nkc_tconv            ; convert to normalized format
  1977.                lea      nk_mci(pc),a0        ; ^function to execute
  1978.                bsr      nk_spec              ; special key code handling
  1979.  
  1980.                move.l   (sp)+,a0             ; restore ^key code
  1981.                move     d0,(a0)              ; return key code
  1982.  
  1983.                move     (sp)+,d0             ; restore event mask
  1984.                move     d0,nkc_intout        ; and intout (changed by nk_spec)
  1985.  
  1986. .exit:         movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  1987.                rts                           ; bye
  1988.  
  1989.  
  1990.  
  1991.  
  1992. *START
  1993. ****************************************************************************
  1994. *
  1995. *  nkc_amulti: NKCC multi event called by Assembler  *** added by Gerd Knops
  1996. *  # G U
  1997. *
  1998. *  See description of nkc_multi()!
  1999. *
  2000. *  usage: instead of    move.l   #aespb,d1
  2001. *                       move  #$c8,d0
  2002. *                       trap  #2
  2003. *
  2004. *         do            jsr   nkc_amulti
  2005. *
  2006. *  In:   all parameters for evnt_multi in the AES parameter arrays
  2007. *
  2008. *  Out:  values in intout and message buffer
  2009. *
  2010. *  Reg:  D:01234567   A:01234567   CCR
  2011. *          ***.....     **......    *
  2012. *
  2013. ****************************************************************************
  2014. *END
  2015.  
  2016. nkc_amulti:    tst.b    prvvalid             ; previous character in buffer?
  2017.                beq.s    .mevent              ; no->
  2018.  
  2019.                clr.b    prvvalid             ; remove key code from buffer
  2020.                clr      nkc_intout+8         ; no SHIFT etc.
  2021.                move     prvkey,nkc_intout+10 ; return key code
  2022.                move     #MU_KEYBD,nkc_intout ; a keyboard event occured
  2023.                rts                           ; bye
  2024.  
  2025. .mevent:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  2026.  
  2027.                move     nkc_intin,-(sp)      ; events to get
  2028.  
  2029.  
  2030. *------------- execute multi event
  2031.  
  2032.                bsr      nk_bestart           ; start handling for button event
  2033.                bsr      nk_msave             ; save multi event parameters
  2034.  
  2035. .wait:         cmp      #25,nkc_contrl       ; still evnt_multi() opcode?!?
  2036.                beq.s    .aes                 ; yes ->
  2037.  
  2038.                bsr      nk_mrestore          ; NO! AES corrupted it! restore
  2039.  
  2040. .aes:          lea      nkc_intin,a0         ; ^intin
  2041.                move     (a0),-(sp)           ; save event mask
  2042.                and      #!MU_XTIMER,(a0)     ; clear x-timer flag
  2043.                move     #200,d0              ; opcode for AES
  2044.                move.l   #aespb,d1            ; ^AES parameter block
  2045.                trap     #2                   ; call GEM
  2046.                move     (sp)+,nkc_intin      ; restore event mask
  2047.  
  2048.                move     nkc_intout,d0        ; mask of occured events
  2049.                and      #MU_KEYBD,d0         ; keyboard event?
  2050.                bne.s    .buthnd              ; yes ->
  2051.  
  2052.                move.l   kbdiorec,a0          ; no: get ^keyboard's I/O record
  2053.                move     IBUFHD(a0),iohead    ; reset NKCC's head pointer
  2054.  
  2055. .buthnd:       bsr      nk_beend             ; end handling of button event
  2056.                tst      nkc_intout           ; did any event occur?
  2057.                beq.s    .wait                ; no ->
  2058.  
  2059.                move     (sp)+,d2             ; events to get
  2060.  
  2061.  
  2062. *------------- check if keyboard event occured and convert key code, if so
  2063.  
  2064.                lea      nkc_intout+8,a3      ; ^shift key state
  2065.                move     (a3),d0              ; make in NKF?_... compatible
  2066.                move.b   d0,(a3)
  2067.                clr.b    1(a3)
  2068.  
  2069.                move     nkc_intout,d0        ; mask of received events
  2070.                moveq.l  #MU_KEYBD,d1         ; the flag to test
  2071.                and      d0,d1                ; is it set?
  2072.                beq.s    .exit                ; no-> exit
  2073.  
  2074.                move     d0,-(sp)             ; save event mask
  2075.  
  2076.                move     nkc_intout+10,d0     ; scan code + ASCII code
  2077.                moveq.l  #MU_BUTTON|MU_M1|MU_M2,d1  ; any of the events checked
  2078.                and      d2,d1                ; which return shift state?
  2079.                bne.s    .useiout             ; yes->
  2080.  
  2081.                move.l   pshift,a3            ; no: get shift state directly
  2082.                move.b   (a3),d1              ; get it
  2083.                and      #$f,d1               ; isolate valid bits
  2084.                bra.s    .conv
  2085.  
  2086. .useiout:      move     nkc_intout+8,d1      ; get shift state from intout
  2087.                lsr      #8,d1                ; in TOS format
  2088.  
  2089. .conv:         bsr      nk_bioscode          ; convert to BIOS format
  2090.                bsr      nk_real_shift        ; try to get original shift flags
  2091.                bsr.s    nkc_tconv            ; convert to normalized format
  2092.                lea      nk_mci(pc),a0        ; ^function to execute
  2093.                bsr      nk_spec              ; special key code handling
  2094.  
  2095.                move     d0,nkc_intout+10     ; save keycode
  2096.                move     (sp)+,d0             ; restore event mask
  2097.                move     d0,nkc_intout        ; and intout (changed by nk_spec)
  2098.  
  2099. .exit:         movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  2100.                rts                           ; bye
  2101.  
  2102.                .endif   ; .if NKCGEM=1
  2103.  
  2104.  
  2105.  
  2106. *START
  2107. ****************************************************************************
  2108. *
  2109. *  nkc_tconv: TOS key code converter
  2110. *  # G R
  2111. *
  2112. *  C prototype: int nkc_tconv(long toskey);
  2113. *---------------------------------------------------------------------------
  2114. *  This is the most important function within NKCC: it takes a key code
  2115. *  returned by TOS and converts it to the sophisticated normalized format.
  2116. *
  2117. *  Note: the raw converter does no deadkey handling, ASCII input or
  2118. *        Control key emulation.
  2119. *
  2120. *  In:   D0.L           key code in TOS format:
  2121. *                                   0                    1
  2122. *                       bit 31:     ignored              ignored
  2123. *                       bit 30:     ignored              ignored
  2124. *                       bit 29:     ignored              ignored
  2125. *                       bit 28:     no CapsLock          CapsLock
  2126. *                       bit 27:     no Alternate         Alternate pressed
  2127. *                       bit 26:     no Control           Control pressed
  2128. *                       bit 25:     no left Shift key    left Shift pressed
  2129. *                       bit 24:     no right Shift key   right Shift pressed
  2130. *
  2131. *                       bits 23...16: scan code
  2132. *                       bits 15...08: ignored
  2133. *                       bits 07...00: ASCII code (or rubbish in most cases
  2134. *                          when Control or Alternate is pressed ...)
  2135. *
  2136. *  Out:  D0.W           normalized key code:
  2137. *                       bits 15...08: flags:
  2138. *                                   0                    1
  2139. *                       NKF?_FUNC   printable char       "function key"
  2140. *                       NKF?_RESVD  ignore it            ignore it
  2141. *                       NKF?_NUM    main keypad          numeric keypad
  2142. *                       NKF?_CAPS   no CapsLock          CapsLock
  2143. *                       NKF?_ALT    no Alternate         Alternate pressed
  2144. *                       NKF?_CTRL   no Control           Control pressed
  2145. *                       NKF?_LSH    no left Shift key    left Shift pressed
  2146. *                       NKF?_RSH    no right Shift key   right Shift pressed
  2147. *
  2148. *                       bits 07...00: key code
  2149. *                       function (NKF?_FUNC set):
  2150. *                          < 32: special key (NK_...)
  2151. *                          >=32: printable char + Control and/or Alternate
  2152. *                       no function (NKF?_FUNC not set):
  2153. *                          printable character (0...255!!!)
  2154. *
  2155. *        CCR            set according content of D0.W
  2156. *
  2157. *  Reg:  D:01234567   A:01234567   CCR
  2158. *          U**.....     **......   =D0.W
  2159. *
  2160. ****************************************************************************
  2161. *END
  2162. *
  2163. * Usage of the NKF?_RESVD flag:
  2164. *
  2165. * If the flag is set, the function nkc_cmp(), which evaluates the flag,
  2166. * has to check the state of the shift keys when comparing two key codes.
  2167. *
  2168. * Don't use the flag outside NKCC! Its content and meaning may change
  2169. * in future versions without notice!
  2170. *
  2171. ****************************************************************************
  2172.  
  2173. nkc_tconv:     movem.l  d3/d4,-(sp)          ; save registers
  2174.  
  2175.  
  2176. *------------- separate TOS key code
  2177.  
  2178.                move.l   d0,d1                ; TOS key code
  2179.                swap     d1                   ; .W = scan code and flags
  2180.                move     d1,d2                ; copy
  2181.                move     #$ff,d3              ; and-mask
  2182.                and      d3,d0                ; .B = ASCII code
  2183.                and      d3,d1                ; .B = scan code
  2184.                beq      .tos306              ; scancode=zero (key code created
  2185.                                              ;  by ASCII input of TOS 3.06)? ->
  2186.                and      #$1f00,d2            ; .W = key flags (in high byte)
  2187.  
  2188.  
  2189. *------------- decide which translation table to use
  2190.  
  2191.                move     d2,d3                ; key flags
  2192.                and      #NKFf_SHIFT,d3       ; isolate bits for shift keys
  2193.                beq.s    .ktab1               ; shift key pressed? no->
  2194.  
  2195.                move.l   pkey_shift,a0        ; yes: use shift table
  2196.                bra.s    .ktab3               ; ->
  2197.  
  2198. .ktab1:        btst.l   #NKFb_CAPS,d2        ; CapsLock?
  2199.                beq.s    .ktab2               ; no->
  2200.  
  2201.                move.l   pkey_caps,a0         ; yes: use CapsLock table
  2202.                bra.s    .ktab3               ; ->
  2203.  
  2204. .ktab2:        move.l   pkey_unshift,a0      ; use unshifted table
  2205.  
  2206.  
  2207. *------------- check if scan code is out of range
  2208. *
  2209. * Illegal scancodes can be used to produce 'macro key codes'. Their format is:
  2210. *
  2211. * - the scancode must be $84 or larger (should be $ff to work properly with old
  2212. *   versions of Mag!x)
  2213. * - the ASCII code must be in the range $20...$ff (values below are set to $20
  2214. *   by NKCC)
  2215. * - Alternate and Control are not used for the normalized key code. However,
  2216. *   if at least one of them is non-zero, then the numeric keypad flag will be
  2217. *   set in the resulting key code.
  2218. *
  2219.  
  2220. .ktab3:        cmp.b    #$84,d1              ; illegal scan code?
  2221.                blo.s    .ktab4               ; no ->
  2222.  
  2223.                move     d2,d1                ; flags
  2224.                and      #NKFf_ALT|NKFf_CTRL,d1  ; Alternate or Control?
  2225.                beq.s    .special             ; no ->
  2226.  
  2227.                or       #NKFf_NUM,d0         ; yes: set numeric keypad flag
  2228.                and      #NKFf_CAPS|NKFf_SHIFT,d2   ; mask off both flags
  2229.  
  2230. .special:      or       d2,d0                ; combine with ASCII code
  2231.                or       #NKFf_FUNC|NKFf_RESVD,d0   ; set function and resvd
  2232.                cmp.b    #$20,d0              ; ASCII code in range?
  2233.                bhs      .exit                ; yes ->
  2234.  
  2235.                move.b   #$20,d0              ; no: use minimum
  2236.                bra      .exit                ; ->
  2237.  
  2238.  
  2239. *------------- check if Alternate + number: they have simulated scan codes
  2240.  
  2241. .ktab4:        cmp.b    #$78,d1              ; scan code of Alt + number?
  2242.                blo.s    .scan1               ; no->
  2243.  
  2244.                sub.b    #$76,d1              ; yes: calculate REAL scan code
  2245.                move.b   (a0,d1),d0           ; fetch ASCII code
  2246.                or       #NKFf_ALT,d2         ; set Alternate flag
  2247.                bra      .cat_codes           ; -> add flag byte and exit
  2248.  
  2249.  
  2250. *------------- check if exception scan code from cursor keypad
  2251.  
  2252. .scan1:        lea      xscantab,a1          ; ^exception scan code table
  2253.  
  2254. .search_scan:  move     (a1)+,d3             ; NKC and scan code
  2255.                bmi.s    .tabend              ; <0? end of table reached ->
  2256.  
  2257.                cmp.b    d1,d3                ; scan code found?
  2258.                bne.s    .search_scan         ; no: continue search ->
  2259.  
  2260.                lsr      #8,d3                ; .B = NKC
  2261.                moveq.l  #0,d0                ; mark: key code found
  2262.                bra.s    .scan2               ; ->
  2263.  
  2264. .tabend:       moveq.l  #0,d3                ; no NKC found yet
  2265.  
  2266.  
  2267. *------------- check if rubbish ASCII code and erase it, if so
  2268.  
  2269. .scan2:        move.b   (a0,d1),d4           ; ASCII code from translation table
  2270.                cmp.b    #32,d0               ; ASCII returned by TOS < 32?
  2271.                bhs.s    .scan3               ; no -> can't be rubbish
  2272.  
  2273.                cmp.b    d4,d0                ; yes: compare with table entry
  2274.                beq.s    .scan3               ; equal: that's ok ->
  2275.  
  2276.                moveq.l  #0,d0                ; not equal: rubbish! clear it
  2277.  
  2278.  
  2279. *------------- check if ASCII code could only be produced via Alternate key
  2280. *              combination
  2281.  
  2282. .scan3:        tst.b    d0                   ; ASCII code valid?
  2283.                beq.s    .scan4               ; no ->
  2284.  
  2285.                cmp.b    d4,d0                ; compare with table entry
  2286.                beq.s    .scan4               ; equal: normal key ->
  2287.  
  2288.                and      #!NKFf_ALT,d2        ; no: clear Alternate flag
  2289.  
  2290.  
  2291. *------------- check if ASCII code found yet, and set it, if not
  2292.  
  2293. .scan4:        tst.b    d0                   ; found?
  2294.                bne.s    .scan5               ; yes ->
  2295.  
  2296.                move.b   d3,d0                ; no: use code from exception table
  2297.                bne.s    .scan5               ; now valid? yes ->
  2298.  
  2299.                move.b   d4,d0                ; no: use code from transl. table
  2300.  
  2301.  
  2302. *------------- check special case: delete key
  2303.  
  2304. .scan5:        cmp.b    #127,d0              ; ASCII code of Delete?
  2305.                bne.s    .scan6               ; no ->
  2306.  
  2307.                move.b   #NK_DEL,d0           ; yes: set according NKC
  2308.  
  2309.  
  2310. *------------- check if key is on numeric keypad (via scan code)
  2311.  
  2312. .scan6:        cmp.b    #$4a,d1              ; numeric pad scan code range?
  2313.                beq.s    .numeric             ; yes ->
  2314.  
  2315.                cmp.b    #$4e,d1
  2316.                beq.s    .numeric             ; yes ->
  2317.  
  2318.                cmp.b    #$63,d1
  2319.                blo.s    .scan7               ; no ->
  2320.  
  2321.                cmp.b    #$72,d1
  2322.                bhi.s    .scan7               ; no ->
  2323.  
  2324. .numeric:      or       #NKFf_NUM,d2         ; yes: set numeric bit
  2325.  
  2326.  
  2327. *------------- check if "function key" and set bit accordingly
  2328.  
  2329. .scan7:        cmp.b    #32,d0               ; ASCII code less than 32?
  2330.                bhs.s    .scan8               ; no ->
  2331.  
  2332.                or       #NKFf_FUNC,d2        ; yes: set function bit
  2333.  
  2334.  
  2335. *------------- check special case: Return or Enter key
  2336.  
  2337.                cmp.b    #13,d0               ; Return or Enter key?
  2338.                bne.s    .scan8               ; no ->
  2339.  
  2340.                btst.l   #NKFb_NUM,d2         ; yes: from the numeric pad?
  2341.                beq.s    .scan8               ; no -> it's Return, keep code
  2342.  
  2343.                moveq.l  #NK_ENTER,d0         ; yes: it's Enter; new code
  2344.  
  2345.  
  2346. *------------- check if function key (F1-F10) via scan code
  2347.  
  2348. .scan8:        cmp.b    #$54,d1              ; shift + function key?
  2349.                blo.s    .scan9               ; no ->
  2350.  
  2351.                cmp.b    #$5d,d1
  2352.                bhi.s    .scan9               ; no ->
  2353.  
  2354.                sub.b    #$54-$3b,d1          ; yes: scan code for unshifted key
  2355.                move     d2,d3                ; shift flags
  2356.                and      #NKFf_SHIFT,d3       ; any shift key flag set?
  2357.                bne.s    .scan9               ; yes ->
  2358.                or       #NKFf_SHIFT,d2       ; no: set both flags
  2359.  
  2360. .scan9:        cmp.b    #$3b,d1              ; (unshifted) function key?
  2361.                blo.s    .cat_codes           ; no ->
  2362.  
  2363.                cmp.b    #$44,d1
  2364.                bhi.s    .cat_codes           ; no ->
  2365.  
  2366.                move.b   d1,d0                ; yes: calc NKC
  2367.                sub.b    #$2b,d0
  2368.  
  2369.  
  2370. *------------- final flag handling; mix key code (low byte) and flag byte
  2371.  
  2372. .cat_codes:    move.l   pkey_shift,a0        ; ^shifted table
  2373.                move.b   (a0,d1),d3           ; get shifted ASCII code
  2374.                or       d2,d0                ; mix flags with key code
  2375.                bmi.s    .scan10              ; result is "function key"? ->
  2376.  
  2377.                and      #NKFf_CTRL+NKFf_ALT,d2  ; Control or Alternate pressed?
  2378.                bne.s    .scan11              ; yes ->
  2379.  
  2380. .scan10:       move.l   pkey_unshift,a0      ; ^unshifted table
  2381.                cmp.b    (a0,d1),d3           ; shifted ASCII = unshifted ASCII?
  2382.                beq.s    .scan12              ; yes ->
  2383.  
  2384.                bra.s    .exit                ; no ->
  2385.  
  2386. .scan11:       or       #NKFf_FUNC,d0        ; Alt/Ctrl + char: set function bit
  2387.                move.l   pkey_caps,a0         ; ^CapsLock table
  2388.                cmp.b    (a0,d1),d3           ; shifted ASCII = CapsLocked ASCII?
  2389.                bne.s    .exit                ; no ->
  2390.  
  2391.                move.b   d3,d0                ; yes: use shifted ASCII code
  2392.  
  2393. .scan12:       or       #NKFf_RESVD,d0       ; yes: nkc_cmp() has to check
  2394.                                              ;  the Shift keys
  2395.  
  2396. *------------- restore registers and exit
  2397.  
  2398. .exit:         tst      d0                   ; set CCR
  2399.                movem.l  (sp)+,d3/d4          ; restore registers
  2400.                rts                           ; bye
  2401.  
  2402.  
  2403. *------------- special handling for key codes created by TOS' 3.06 ASCII input
  2404.  
  2405. .tos306:       and      #NKFf_CAPS,d2        ; isolate CapsLock flag
  2406.                or       d2,d0                ; merge with ASCII code
  2407.                movem.l  (sp)+,d3/d4          ; restore registers
  2408.                rts                           ; bye
  2409.  
  2410.  
  2411.  
  2412.  
  2413. *START
  2414. ****************************************************************************
  2415. *
  2416. *  nkc_gconv: GEM key code converter
  2417. *  # G R
  2418. *
  2419. *  C prototype: int nkc_gconv(int gemkey);
  2420. *---------------------------------------------------------------------------
  2421. *  Why a second key code converter, you ask? Well, in some cases it might
  2422. *  happen that the key status byte of the original key code (with states
  2423. *  of both Shift keys, Control, Alternate and CapsLock) is lost. Then
  2424. *  this converter function must be called, which uses another algorithm
  2425. *  to construct the normalized key code.
  2426. *
  2427. *  Notes:
  2428. *  -  the raw converter does no deadkey handling, ASCII input or Control
  2429. *     key emulation.
  2430. *  -  NKCC does not use this function at all for its own purposes!
  2431. *  -  some key combinations cannot be distinguished without the flag byte!
  2432. *     For example, "Alternate A" and "Shift Alternate A" produce the same
  2433. *     result. Whenever possible, use nkc_tconv()!
  2434. *
  2435. *  In:   D0.W           key code in GEM format:
  2436. *                       bits 15...08: scan code
  2437. *                       bits 07...00: ASCII code
  2438. *
  2439. *  Out:  D0.W           normalized key code (see nkc_tconv() for details)
  2440. *        CCR            set according content of D0.W
  2441. *
  2442. *  Reg:  D:01234567   A:01234567   CCR
  2443. *          U**.....     **......   =D0.W
  2444. *
  2445. ****************************************************************************
  2446. *END
  2447.  
  2448. nkc_gconv:     movem.l  d4-d7,-(sp)          ; save registers
  2449.  
  2450.  
  2451. *------------- find out "real" scan code and convert to TOS key code format
  2452.  
  2453.                move     d0,d1                ; copy key code
  2454.                lsr      #8,d1                ; scan code in d1.w
  2455.                swap     d0                   ; move key code to high word
  2456.                move.l   pshift,a0            ; ^key state flags
  2457.                move.b   (a0),d0              ; get 'em
  2458.                and      #NKFf_CAPS>>8,d0     ; isolate CapsLock flag
  2459.                lea      scan_trans,a0        ; ^scan code translation table
  2460.  
  2461. .trans:        move.l   (a0)+,d2             ; get next entry
  2462.                beq.s    .endtrans            ; end of table? ->
  2463.  
  2464.                cmp.b    d1,d2                ; scan code found?
  2465.                bne.s    .trans               ; no ->
  2466.  
  2467.                lsr      #8,d2                ; "real" scan code
  2468.                move.b   d2,d1                ; use it
  2469.                swap     d2                   ; flags to set
  2470.                or       d2,d0                ; set them
  2471.  
  2472. .endtrans:     swap     d0                   ; move flags up and key code down
  2473.                moveq.l  #0,d7                ; clear for word operation
  2474.                move.b   d0,d7                ; copy ASCII code
  2475.                lsl.l    #8,d0                ; shift flags and scan code up
  2476.                move     d7,d0                ; restore ASCII code
  2477.  
  2478.  
  2479. *------------- try to restore some of the key flags (shift/control/alternate)
  2480.  
  2481.                move.l   pkey_unshift,a0      ; ^unshifted key table
  2482.                move.b   (a0,d1),d4           ; get unshifted code
  2483.                move.l   pkey_shift,a0        ; ^shifted key table
  2484.                move.b   (a0,d1),d5           ; get shifted code
  2485.                move.l   pkey_caps,a0         ; ^CapsLock key table
  2486.                move.b   (a0,d1),d6           ; get CapsLock code
  2487.  
  2488.                bsr      nk_ascmatch          ; try to find ASCII code
  2489.                beq.s    .conv                ; found ->
  2490.  
  2491.                move.b   #$1f,d2              ; maybe modified by Control key...
  2492.                and.b    d2,d4                ; change ASCII code accordingly
  2493.                and.b    d2,d5
  2494.                and.b    d2,d6
  2495.                bsr      nk_ascmatch          ; and try again
  2496.                bne.s    .notfnd              ; no match ->
  2497.  
  2498. .setctrl:      or.l     #(NKFf_FUNC|NKFf_CTRL)<<16,d0    ; Control was pressed
  2499.                bra.s    .conv                ; ->
  2500.  
  2501. .notfnd:       move.l   pkey_unshift,a0      ; not found: restore all three
  2502.                move.b   (a0,d1),d2           ;  ASCII codes
  2503.                move.l   pkey_shift,a0
  2504.                move.b   (a0,d1),d5
  2505.                move.l   pkey_caps,a0
  2506.                move.b   (a0,d1),d6
  2507.                bsr.s    .translate           ; translate unshifted code
  2508.  
  2509.                move.b   d2,d4                ; use translated code
  2510.                move.b   d5,d2                ; translate shifted code
  2511.                bsr.s    .translate
  2512.  
  2513.                move.b   d2,d5                ; use translated code
  2514.                move.b   d6,d2                ; translate shifted code
  2515.                bsr.s    .translate
  2516.  
  2517.                move.b   d2,d6                ; use translated code
  2518.                bsr      nk_ascmatch          ; last try to locate ASCII code
  2519.                beq.s    .setctrl             ; found ->
  2520.  
  2521.                tst.b    d0                   ; not found: ASCII code is 0?
  2522.                bne.s    .conv                ; no ->
  2523.  
  2524.                btst.l   #NKFb_CTRL+16,d0     ; Control key flag already set?
  2525.                bne.s    .conv                ; yes ->
  2526.  
  2527.                                              ; no: must be Alternate
  2528.                or.l     #(NKFf_FUNC|NKFf_ALT)<<16,d0
  2529.  
  2530.  
  2531. *------------- do conversion to normalized format
  2532.  
  2533. .conv:         bsr      nkc_tconv            ; do TOS key code conversion
  2534.  
  2535.                movem.l  (sp)+,d4-d7          ; restore registers
  2536.                tst      d0                   ; set CCR
  2537.                rts                           ; bye
  2538.  
  2539.  
  2540. *  This small sub function changes the ASCII code in D2.B due to the
  2541. *  ASCII code translation table asc_trans. The result is returned in D2.B,
  2542. *  registers D7 and A0 are corrupted.
  2543.  
  2544. .translate:    lea      asc_trans,a0         ; ^translation table
  2545.  
  2546. .transloop:    move     (a0)+,d7             ; get both codes
  2547.                beq.s    .ret                 ; end of table? ->
  2548.  
  2549.                cmp.b    d2,d7                ; found?
  2550.                bne.s    .transloop           ; no ->
  2551.  
  2552.                lsr      #8,d7                ; yes: get translated code
  2553.                move.b   d7,d2                ; and use it
  2554.  
  2555. .ret:          rts                           ; bye
  2556.  
  2557.  
  2558.  
  2559. *START
  2560. ****************************************************************************
  2561. *
  2562. *  nkc_n2tos: convert normalized key codes back to TOS format
  2563. *  # G R
  2564. *
  2565. *  C prototype: long nkc_n2tos(int nkcode);
  2566. *---------------------------------------------------------------------------
  2567. *  In some cases you might have to have key codes in the original TOS format
  2568. *  again, as returned by the GEMDOS functions Cconin(), Crawcin() or the BIOS
  2569. *  function Bconin(). Use nkc_n2tos() to convert them. For a detailed
  2570. *  description of the returned format consult the header of the function
  2571. *  nkc_tconv().
  2572. *
  2573. *  In:   D0.W           key code in normalized format
  2574. *
  2575. *  Out:  D0.L           key code in TOS format:
  2576. *                       bits 24...31: shift key flags
  2577. *                       bits 23...16: scan code
  2578. *                       bits 08...15: reserved (0)
  2579. *                       bits 00...07: ASCII code
  2580. *        CCR            set according content of D0.L
  2581. *
  2582. *  Reg:  D:01234567   A:01234567   CCR
  2583. *          U**.....     **......   =D0.L
  2584. *
  2585. ****************************************************************************
  2586. *END
  2587.  
  2588.  
  2589. nkc_n2tos:     move     d0,d1                ; normalized key code
  2590.                and      #NKFf_FUNC|NKFf_ALT|NKFf_CTRL,d1 ; isolate flags
  2591.                cmp      #NKFf_FUNC,d1        ; only function flag set?
  2592.                bne.s    .ktab0               ; no ->
  2593.  
  2594.                cmp.b    #$20,d0              ; ASCII code >= $20?
  2595.                blo.s    .ktab0               ; no ->
  2596.  
  2597.  
  2598. *------------- macro key
  2599.  
  2600.                move     d0,d1                ; keep normalized key code
  2601.                and.l    #NKFf_CAPS|NKFf_SHIFT,d0   ; isolate usable flags
  2602.                btst.l   #NKFb_NUM,d1         ; numeric keypad flag set?
  2603.                beq.s    .mackey              ; no ->
  2604.  
  2605.                or       #NKFf_ALT|NKFf_CTRL,d0  ; yes: set Alternate + Control
  2606.  
  2607. .mackey:       or.b     #$ff,d0              ; scan code always $ff
  2608.                swap     d0                   ; flags and scan code in upper word
  2609.                move.b   d1,d0                ; ASCII code
  2610.                bra      .exit                ; ->
  2611.  
  2612.  
  2613. *------------- select system key table to use
  2614.  
  2615. .ktab0:        move     d0,d1                ; normalized key code
  2616.                and      #NKFf_SHIFT,d1       ; isolate bits for shift keys
  2617.                beq.s    .ktab1               ; shift key pressed? no->
  2618.  
  2619.                lea      n_to_scan_s,a1       ; ^default translation table
  2620.                move.l   pkey_shift,a0        ; yes: use shift table
  2621.                bra.s    .ktab3               ; ->
  2622.  
  2623. .ktab1:        lea      n_to_scan_u,a1       ; ^unshifted translation table
  2624.                btst.l   #NKFb_CAPS,d0        ; CapsLock?
  2625.                beq.s    .ktab2               ; no->
  2626.  
  2627.                move.l   pkey_caps,a0         ; yes: use CapsLock table
  2628.                bra.s    .ktab3               ; ->
  2629.  
  2630. .ktab2:        move.l   pkey_unshift,a0      ; use unshifted table
  2631.  
  2632.  
  2633. *------------- handling for ASCII codes >= 32
  2634.  
  2635. .ktab3:        cmp.b    #32,d0               ; ASCII code < 32?
  2636.                blo.s    .lowascii            ; yes ->
  2637.  
  2638.                bsr      nk_findscan          ; find scan code
  2639.                bne.s    .found               ; found ->
  2640.  
  2641.                btst.l   #NKFb_FUNC,d0        ; function flag set?
  2642.                beq.s    .notfound            ; no ->
  2643.  
  2644.                move.l   a0,d1                ; save a0
  2645.                lea      tolower,a0           ; ^upper->lower case table
  2646.                moveq.l  #0,d2                ; clear for word operation
  2647.                move.b   d0,d2                ; ASCII code
  2648.                move.b   (a0,d2),d0           ; get lowercased ASCII code
  2649.                move.l   d1,a0                ; restore a0
  2650.                bsr      nk_findscan          ; try to find scan code again
  2651.                bne.s    .found               ; found ->
  2652.  
  2653.  
  2654. *------------- unknown source: treat key code as it was entered using the
  2655. *              TOS 3.06 direct ASCII input
  2656.  
  2657. .notfound:     moveq.l  #0,d1                ; not found: clear for word op.
  2658.                move.b   d0,d1                ; unchanged ASCII code
  2659.                and      #$1f00,d0            ; keep shift flags only
  2660.                swap     d0                   ; -> high word (scan code = 0)
  2661.                move     d1,d0                ; low word: ASCII code
  2662.                bra      .exit                ; ->
  2663.  
  2664.  
  2665. *------------- handling for ASCII codes < 32
  2666.  
  2667. .lowascii:     btst.l   #NKFb_FUNC,d0        ; function key?
  2668.                bne.s    .func                ; yes ->
  2669.  
  2670.                and      #$10ff,d0            ; clear all flags except CapsLock
  2671.                bra.s    .notfound            ; ->
  2672.  
  2673. .func:         moveq.l  #0,d1                ; clear for word operation
  2674.                move.b   d0,d1                ; ASCII code (0...$1f)
  2675.                move     d1,d2                ; copy
  2676.                move.b   (a1,d1),d1           ; get scan code
  2677.                bne.s    .getascii            ; valid? ->
  2678.  
  2679.                moveq    #0,d0                ; invalid key code!! return 0
  2680.                bra      .exit                ; ->
  2681.  
  2682. .getascii:     lea      n_to_scan_u,a1       ; ^unshifted translation table
  2683.                move.b   (a1,d2),d2           ; get scan code from unshifted tab.
  2684.                move.b   (a0,d2),d0           ; get ASCII from system's table
  2685.  
  2686.  
  2687. * register contents:
  2688. *
  2689. * d0.b         ASCII code
  2690. * d1.b         scan code
  2691. * d0.hb        NKCC flags
  2692. *
  2693.  
  2694. .found:        move     d0,d2                ; flags and ASCII code
  2695.                and      #$1f00,d0            ; isolate shift flags
  2696.                move.b   d1,d0                ; merge with scan code
  2697.                swap     d0                   ; -> high byte
  2698.                clr      d0                   ; erase low word
  2699.                move.b   d2,d0                ; restore ASCII code
  2700.  
  2701.  
  2702. *------------- handling for Control key flag
  2703.  
  2704.                btst.l   #NKFb_CTRL,d2        ; control key flag set?
  2705.                beq.s    .alternate           ; no ->
  2706.  
  2707.                cmp.b    #$4b,d1              ; scan code = "cursor left"?
  2708.                bne.s    .scanchk2            ; no ->
  2709.  
  2710.                add.l    #$280000,d0          ; change scan code to $73
  2711.                clr.b    d0                   ; erase ASCII code
  2712.                bra.s    .exit                ; ->
  2713.  
  2714. .scanchk2:     cmp.b    #$4d,d1              ; scan code = "cursor right"?
  2715.                bne.s    .scanchk3            ; no ->
  2716.  
  2717.                add.l    #$270000,d0          ; change scan code to $74
  2718.                clr.b    d0                   ; erase ASCII code
  2719.                bra.s    .exit                ; ->
  2720.  
  2721. .scanchk3:     cmp.b    #$47,d1              ; scan code = "ClrHome"?
  2722.                bne.s    .ascchk              ; no ->
  2723.  
  2724.                add.l    #$300000,d0          ; change scan code to $77
  2725. ; keep ASCII code in this case! What a mess...
  2726.                bra.s    .exit                ; ->
  2727.  
  2728. .ascchk:       lea      asc_trans,a0         ; ^ASCII translation table
  2729.  
  2730. .ascloop:      move     (a0)+,d1             ; get next entry
  2731.                beq.s    .noctrlasc           ; end of table ->
  2732.  
  2733.                cmp.b    d0,d1                ; ASCII code found?
  2734.                bne.s    .ascloop             ; no -> continue search
  2735.  
  2736.                lsr      #8,d1                ; yes: get translated code
  2737.                move.b   d1,d0                ; use it
  2738.                bra.s    .exit                ; ->
  2739.  
  2740. .noctrlasc:    and.b    #$1f,d0              ; mask off upper 3 bits
  2741.                bra.s    .exit                ; ->
  2742.  
  2743.  
  2744. *------------- handling for Alternate key flag
  2745.  
  2746. .alternate:    btst.l   #NKFb_ALT,d2         ; alternate key flag set?
  2747.                beq.s    .exit                ; no ->
  2748.  
  2749.                cmp.b    #2,d1                ; top row on main keyboard?
  2750.                blo.s    .alphachk            ; no ->
  2751.  
  2752.                cmp.b    #$d,d1
  2753.                bhi.s    .alphachk            ; no ->
  2754.  
  2755.                add.l    #$760000,d0          ; yes: change scan code
  2756.                clr.b    d0                   ; and erase ASCII code
  2757.                bra.s    .exit                ; ->
  2758.  
  2759. .alphachk:     cmp.b    #'A',d0              ; alpha-characters?
  2760.                blo.s    .exit                ; no ->
  2761.  
  2762.                cmp.b    #'z',d0
  2763.                bhi.s    .exit                ; no ->
  2764.  
  2765.                cmp.b    #'Z',d0
  2766.                bls.s    .ascii0              ; yes ->
  2767.  
  2768.                cmp.b    #'a',d0
  2769.                blo.s    .exit                ; no ->
  2770.  
  2771. .ascii0:       clr.b    d0                   ; alpha-character: clear ASCII code
  2772.  
  2773. .exit:         tst.l    d0                   ; set CCR
  2774.                rts                           ; bye
  2775.  
  2776.  
  2777.  
  2778. *START
  2779. ****************************************************************************
  2780. *
  2781. *  nkc_n2gem: convert normalized key codes back to GEM format
  2782. *  # G R
  2783. *
  2784. *  C prototype: int nkc_n2gem(int nkcode);
  2785. *---------------------------------------------------------------------------
  2786. *  Similar to nkc_n2tos(), this function converts normalized key codes back
  2787. *  to the operating system's format. The result is a key code as returned
  2788. *  by the AES functions evnt_keybd() respectively evnt_multi().
  2789. *
  2790. *  In:   D0.W           key code in normalized format
  2791. *
  2792. *  Out:  D0.W           key code in GEM format:
  2793. *                       bits 08...15: scan code
  2794. *                       bits 00...07: ASCII code
  2795. *        CCR            set according content of D0.W
  2796. *
  2797. *  Reg:  D:01234567   A:01234567   CCR
  2798. *          U**.....     **......   =D0.W
  2799. *
  2800. ****************************************************************************
  2801. *END
  2802.  
  2803. nkc_n2gem:     bsr      nkc_n2tos            ; convert
  2804.                moveq.l  #0,d1                ; clear for word operation
  2805.                move.b   d0,d1                ; ASCII code
  2806.                ror.l    #8,d0                ; scan code now in high byte
  2807.                move.b   d1,d0                ; put ASCII into low byte
  2808.                tst      d0                   ; set CCR
  2809.                rts                           ; bye
  2810.  
  2811.  
  2812.  
  2813. *START
  2814. ****************************************************************************
  2815. *
  2816. *  nkc_kstate: return state of Shift/Control/Alternate/CapsLock in
  2817. *              normalized format
  2818. *  # G R
  2819. *
  2820. *  C prototype: int nkc_kstate(void);
  2821. *---------------------------------------------------------------------------
  2822. *  This is a very *FAST* function which returns the state of the Shift/
  2823. *  Control/Alternate and CapsLock keys in normalized format.
  2824. *
  2825. *  In:   -
  2826. *
  2827. *  Out:  D0.W           normalized key flags:
  2828. *                                   0                    1
  2829. *                       NKF?_CAPS   no CapsLock          CapsLock
  2830. *                       NKF?_ALT    no Alternate         Alternate pressed
  2831. *                       NKF?_CTRL   no Control           Control pressed
  2832. *                       NKF?_LSH    no left Shift key    left Shift pressed
  2833. *                       NKF?_RSH    no right Shift key   right Shift pressed
  2834. *
  2835. *        CCR            set according content of D0.W
  2836. *
  2837. *  Reg:  D:01234567   A:01234567   CCR
  2838. *          w**.....     **......   =D0.W
  2839. *
  2840. ****************************************************************************
  2841. *END
  2842.  
  2843. nkc_kstate:    move.l   pshift,a0            ; ^shift state variable
  2844.                move.b   (a0),d0              ; get its contents
  2845.                and      #$1f,d0              ; isolate valid bits
  2846.                lsl      #8,d0                ; make it NKC compatible
  2847.                rts                           ; bye
  2848.  
  2849.  
  2850.  
  2851. *START
  2852. ****************************************************************************
  2853. *
  2854. *  nkc_timer: return current value of 200 Hz system clock
  2855. *  # G R
  2856. *
  2857. *  C prototype: unsigned long nkc_timer(void);
  2858. *---------------------------------------------------------------------------
  2859. *  This is a very *FAST* function which returns the content of the 200 Hz
  2860. *  system clock.
  2861. *
  2862. *  In:   -
  2863. *
  2864. *  Out:  D0.L           current 200 HZ system clock value
  2865. *
  2866. *  Reg:  D:01234567   A:01234567   CCR
  2867. *          w**.....     **......    *
  2868. *
  2869. ****************************************************************************
  2870. *END
  2871.  
  2872. nkc_timer:     move.l   sysclock,d0          ; just get value
  2873.                rts                           ; bye bye
  2874.  
  2875.  
  2876.  
  2877. *START
  2878. ****************************************************************************
  2879. *
  2880. *  nkc_cmp: compare two key codes
  2881. *  # G R
  2882. *
  2883. *  C prototype: int nkc_cmp(int refkey,int kcode);
  2884. *---------------------------------------------------------------------------
  2885. *  nkc_cmp() compares key codes. What for, you ask? A simple "if key_code1
  2886. *  = key_code2" would also do it? No! This function follows some specific
  2887. *  rules, which improve the flexibility of key code comparism.
  2888. *
  2889. *  One of the key codes passed to nkc_cmp() is called the "reference key
  2890. *  code". The other is the "test key code", which is got from nkc_conin()
  2891. *  or nkc_multi(). Some flags of the reference code are treated a special
  2892. *  way:
  2893. *
  2894. *  NKF?_IGNUM (same as NKF?_RESVD)
  2895. *     if set, the numeric keypad flag doesn't matter
  2896. *
  2897. *  NKF?_CAPS (CapsLock)
  2898. *     if set, the case of the ASCII code doesn't matter
  2899. *
  2900. *  NKFf_SHIFT (both Shift key flags)
  2901. *     if BOTH shift flags are set, the combination of shift key flags in
  2902. *     the test key code doesn't matter: only one shift flag has to be set,
  2903. *     no matter which one.
  2904. *
  2905. *  In:   D0.W           reference key code
  2906. *        D1.W           key code to test
  2907. *
  2908. *  Out:  D0.W           flag: 1 = key codes match
  2909. *                             0 = key codes don't match
  2910. *        CCR            set according content of D0.W
  2911. *
  2912. *  Reg:  D:01234567   A:01234567   CCR
  2913. *          u**.....     **......   =D0.W
  2914. *
  2915. ****************************************************************************
  2916. *END
  2917.  
  2918. nkc_cmp:       movem.l  d3-d4,-(sp)          ; save registers
  2919.                move     d0,d2                ; reference key code
  2920.                eor      d1,d2                ; XORed with test key code
  2921.                beq      .match               ; identical: key codes match
  2922.  
  2923.                bmi.s    .nomatch             ; func flag differs -> don't match
  2924.  
  2925.                tst      d0                   ; "function" key?
  2926.                bmi.s    .rfunc               ; yes ->
  2927.  
  2928.  
  2929. *------------- printable character
  2930.  
  2931.                btst.l   #NKFb_IGNUM,d0       ; ignore numeric keypad flag?
  2932.                bne.s    .chkn1               ; yes ->
  2933.  
  2934.                btst.l   #NKFb_NUM,d2         ; numeric key flags equal?
  2935.                bne.s    .nomatch             ; no ->
  2936.  
  2937. .chkn1:        lea      toupper,a0           ; ^upper case conversion table
  2938.                moveq.l  #0,d3                ; clear for word operation
  2939.                move.b   d0,d3                ; ASCII code of ref key code
  2940.                move.b   (a0,d3),d4           ; get CapsLocked reference key code
  2941.  
  2942.                cmp.b    d0,d1                ; ASCII code equal?
  2943.                beq.s    .stest               ; yes ->
  2944.  
  2945.                btst.l   #NKFb_CAPS,d0        ; no: ignore case?
  2946.                beq.s    .nomatch             ; no -> codes don't match
  2947.  
  2948.                move.b   d1,d3                ; ASCII of test key code
  2949.                cmp.b    (a0,d3),d4           ; CapsLocked comparism
  2950.                beq.s    .match               ; equal ->
  2951.  
  2952.                bra.s    .nomatch             ; not equal ->
  2953.  
  2954. .stest:        btst.l   #NKFb_RESVD,d1       ; check Shift keys?
  2955.                beq.s    .match               ; no ->
  2956.  
  2957. .stest2:       move     #NKFf_SHIFT,d4       ; Shift key flags
  2958.                move     d2,d3                ; XORed key codes
  2959.                and      d4,d3                ; shift flags equal?
  2960.                beq.s    .match               ; yes ->
  2961.  
  2962.                move     d0,d3                ; reference key code
  2963.                and      d4,d3                ; isolate Shift flags
  2964.                cmp      d3,d4                ; both set?
  2965.                bne.s    .nomatch             ; no -> codes don't match
  2966.  
  2967.                move     d1,d3                ; check if any pressed in test code
  2968.                and      d4,d3
  2969.                bne.s    .match               ; yes ->
  2970.  
  2971.                bra.s    .nomatch             ; no ->
  2972.  
  2973.  
  2974. *------------- "function key"
  2975.  
  2976. .rfunc:        move     d2,d3                ; XORed key codes
  2977.                and      #NKFf_ALT|NKFf_CTRL,d3  ; check Alternate and Control
  2978.                bne.s    .nomatch             ; different -> codes don't match
  2979.  
  2980.                cmp.b    #32,d0               ; special key or character?
  2981.                bhs.s    .rchar               ; character->
  2982.  
  2983.                cmp.b    d0,d1                ; special key codes equal?
  2984.                beq.s    .stest2              ; yes ->
  2985.  
  2986.                bra.s    .nomatch             ; no ->
  2987.  
  2988. .rchar:        btst.l   #NKFb_IGNUM,d0       ; ignore numeric keypad flag?
  2989.                bne.s    .chkn2               ; yes ->
  2990.  
  2991.                btst.l   #NKFb_NUM,d2         ; numeric key flags equal?
  2992.                bne.s    .nomatch             ; no ->
  2993.  
  2994. .chkn2:        cmp.b    d0,d1                ; ASCII codes equal?
  2995.                beq.s    .stest               ; yes ->
  2996.  
  2997. .nomatch:      movem.l  (sp)+,d3-d4          ; restore registers
  2998.                moveq.l  #0,d0                ; codes don't match
  2999.                rts                           ; bye
  3000.  
  3001. .match:        movem.l  (sp)+,d3-d4          ; restore registers
  3002.                moveq.l  #1,d0                ; codes match
  3003.                rts                           ; bye
  3004.  
  3005.  
  3006.  
  3007. *START
  3008. ****************************************************************************
  3009. *
  3010. *  nkc_vlink: link function to XBRA vector list
  3011. *  # G U
  3012. *
  3013. *  C prototype: void nkc_vlink(long vector,int mode,void *pfnc);
  3014. *---------------------------------------------------------------------------
  3015. *  This function can be used to change system vectors and let them point
  3016. *  to own functions, using a standard method. The vector, which should be
  3017. *  changed, is described by the contents of D0.L and D1.W. It can be
  3018. *  either a standard vector number, e.g. 2 for the bus error exception
  3019. *  vector, or the absolute address of the vector, e.g. $502 for the screen
  3020. *  dump vector. The function to install must have the following header:
  3021. *
  3022. *  .dc.b    "XBRA"         magic longword
  3023. *  .dc.b    "myID"         four ASCII character ID of the function
  3024. *                          (NKCC uses "NKCC", for example)
  3025. *  .dc.l    0              buffer for the old vector content
  3026. *  function: ...           start of the function code
  3027. *
  3028. *  The function should end with:
  3029. *
  3030. *  move.l   function-4(pc),-(sp)
  3031. *  rts
  3032. *
  3033. *
  3034. *  Note: in NKXM_ADR mode, this function automatically switches (temporary)
  3035. *        to Supervisor mode to prevent bus errors
  3036. *
  3037. *
  3038. *  In:   D0.L           vector descriptor
  3039. *        D1.W           mode:
  3040. *                       NKXM_NUM = D0.L contains a vector number
  3041. *                       NKXM_ADR = D0.L contains a vector address
  3042. *        A0.L           ^function to install (NOT ^XBRA header!)
  3043. *
  3044. *  Out:  -4(A0.L).L     old content of vector
  3045. *
  3046. *  Reg:  D:01234567   A:01234567   CCR
  3047. *          ***.....     **......    *
  3048. *
  3049. ****************************************************************************
  3050. *END
  3051.  
  3052.  
  3053. nkc_vlink:     tst      d1                   ; which mode?
  3054.                bne.s    .adr                 ; address ->
  3055.  
  3056.  
  3057. *------------- install function by vector number
  3058.  
  3059.                move.l   a2,-(sp)             ; save register
  3060.  
  3061.                move.l   a0,-(sp)             ; ^function
  3062.                move     d0,-(sp)             ; vector number
  3063.                move     #5,-(sp)             ; Setexc
  3064.  
  3065.                moveq.l  #-1,d1               ; ^function: don't change
  3066.                move.l   d1,-(sp)             ;  vector
  3067.                move     d0,-(sp)             ; vector number
  3068.                move     #5,-(sp)             ; Setexc
  3069.  
  3070.                trap     #13                  ; BIOS: get old vector
  3071.                addq     #8,sp                ; clean stack
  3072.  
  3073.                move.l   4(sp),a0             ; ^function
  3074.                move.l   d0,-4(a0)            ; save old vector
  3075.                trap     #13                  ; BIOS: install routine
  3076.                addq     #8,sp                ; clean stack
  3077.  
  3078.                move.l   (sp)+,a2             ; restore register
  3079.                rts                           ; bye
  3080.  
  3081.  
  3082. *------------- install function by vector address
  3083.  
  3084. .adr:          movem.l  a2-a4,-(sp)          ; save registers
  3085.  
  3086.                move.l   a0,a3                ; ^function
  3087.                move.l   d0,a4                ; ^vector
  3088.  
  3089.                clr.l    -(sp)                ; use usp as ssp
  3090.                move     #$20,-(sp)           ; Super
  3091.                trap     #1                   ; GEMDOS
  3092.                move.l   d0,2(sp)             ; save old sp
  3093.                move     #$20,(sp)            ; Super opcode for next call
  3094.  
  3095.                move.l   (a4),-4(a3)          ; save old vector content
  3096.                move.l   a3,(a4)              ; install function
  3097.  
  3098.                trap     #1                   ; GEMDOS (back to User mode)
  3099.                addq     #6,sp                ; clean stack
  3100.  
  3101.                movem.l  (sp)+,a2-a4          ; restore registers
  3102.                rts                           ; bye
  3103.  
  3104.  
  3105.  
  3106. *START
  3107. ****************************************************************************
  3108. *
  3109. *  nkc_vunlink: unlink function from XBRA vector list
  3110. *  # G U
  3111. *
  3112. *  C prototype: int nkc_vunlink(long vector,int mode,void *pfnc);
  3113. *---------------------------------------------------------------------------
  3114. *  nkc_vunlink() removes a function which was installed using the XBRA method.
  3115. *  For details see nkc_link(). If the XBRA list was corrupted, the function
  3116. *  aborts with an error code. This happens, when a non-XBRA routine is
  3117. *  installed on the same vector after the nkc_vlink() call of the function
  3118. *  to remove.
  3119. *
  3120. *  Note: the function automatically switches (temporary) to Supervisor mode
  3121. *        to prevent bus errors
  3122. *
  3123. *  In:   D0.L           vector descriptor
  3124. *        D1.W           mode:
  3125. *                       NKXM_NUM = D0.L contains a vector number
  3126. *                       NKXM_ADR = D0.L contains a vector address
  3127. *        A0.L           ^function to remove (NOT ^XBRA header!)
  3128. *
  3129. *  Out:  D0.W           status:
  3130. *                       0 = OK
  3131. *                       -1 = can't remove (XBRA list corrupted)
  3132. *        CCR            set according content of D0.W
  3133. *
  3134. *  Reg:  D:01234567   A:01234567   CCR
  3135. *          U**.....     **......   =D0.W
  3136. *
  3137. ****************************************************************************
  3138. *END
  3139.  
  3140. nkc_vunlink:   movem.l  d6-d7/a2/a6,-(sp)    ; save registers
  3141.  
  3142.                move.l   d0,d7                ; save vector descriptor
  3143.                move.l   a0,a6                ; save function address
  3144.                move     d1,d6                ; save mode
  3145.                bne.s    .adr                 ; address mode ->
  3146.  
  3147.  
  3148. *------------- check vector content by number
  3149.  
  3150.                moveq.l  #-1,d0               ; get current vector
  3151.                move.l   d0,-(sp)
  3152.                move     d7,-(sp)             ; vector number
  3153.                move     #5,-(sp)             ; Setexc
  3154.                trap     #13                  ; BIOS
  3155.                addq     #8,sp                ; clean stack
  3156.  
  3157.                cmp.l    d0,a6                ; function still on top?
  3158.                bne.s    .search              ; no ->
  3159.  
  3160. .restore:      move.l   -4(a6),-(sp)         ; restore old vector
  3161.                move     d7,-(sp)             ; vector number
  3162.                move     #5,-(sp)             ; Setexc
  3163.                trap     #13                  ; BIOS
  3164.                addq     #8,sp                ; clean stack
  3165.                bra.s    .okstat              ; exit
  3166.  
  3167.  
  3168. *------------- check vector content by address
  3169.  
  3170. .adr:          clr.l    -(sp)                ; use usp as ssp
  3171.                move     #$20,-(sp)           ; Super
  3172.                trap     #1                   ; GEMDOS
  3173.                move.l   d0,2(sp)             ; save old sp
  3174.                move     #$20,(sp)            ; Super opcode for next call
  3175.  
  3176.                move.l   d7,a0                ; vector address
  3177.                move.l   (a0),d0              ; vector content
  3178.                cmp.l    d0,a6                ; function still on top?
  3179.                bne.s    .search              ; no ->
  3180.  
  3181.                move.l   -4(a6),(a0)          ; yes: remove it
  3182.                bra.s    .okstat              ; exit
  3183.  
  3184.  
  3185. *------------- somebody installed a handler (hope he used XBRA ...)
  3186.  
  3187. .search:       move.l   d0,a0                ; ^current handler
  3188.                move.l   #'XBRA',d0           ; XBRA ID
  3189.  
  3190. .find_hnd:     cmp.l    -12(a0),d0           ; XBRA ID before routine?
  3191.                bne.s    .error               ; no!!! can't remove function!!
  3192.  
  3193.                move.l   -4(a0),a1            ; ^next entry in XBRA list
  3194.                cmp.l    a1,a6                ; next entry in list our function?
  3195.                beq.s    .found               ; yes ->
  3196.  
  3197.                move.l   a1,a0                ; no
  3198.                bra.s    .find_hnd            ; continue search
  3199.  
  3200. .found:        move.l   -4(a6),-4(a0)        ; yes: remove function
  3201.  
  3202. .okstat:       moveq.l  #0,d7                ; no error
  3203.                bra.s    .exit
  3204.  
  3205. .error:        moveq.l  #-1,d7               ; error! can't unlink function!
  3206.  
  3207. .exit:         tst      d6                   ; address mode?
  3208.                beq.s    .exit2               ; no ->
  3209.  
  3210.                trap     #1                   ; yes: switch to user mode first
  3211.                addq     #6,sp                ; with a GEMDOS Super() call
  3212.  
  3213. .exit2:        move     d7,d0                ; status code
  3214.                movem.l  (sp)+,d6-d7/a2/a6    ; restore registers
  3215.                rts                           ; bye
  3216.  
  3217.  
  3218.  
  3219.  
  3220. *START
  3221. ****************************************************************************
  3222. *
  3223. *  nkc_toupper: convert character to upper case
  3224. *  # G
  3225. *
  3226. *  C prototype: unsigned char nkc_toupper(unsigned char chr);
  3227. *---------------------------------------------------------------------------
  3228. *  A character is converted to upper case. Examples:
  3229. *
  3230. *  'a'   ->   'A'          (converted)
  3231. *  '/'   ->   '/'          (unchanged; there's no upper case version for this)
  3232. *  'A'   ->   'A'          (unchanged; already converted)
  3233. *
  3234. *
  3235. *  In:   D0.B           any character
  3236. *
  3237. *  Out:  D0.B           character converted to upper case
  3238. *
  3239. *  Reg:  D:01234567   A:01234567   CCR
  3240. *          U**.....     **......    *
  3241. *
  3242. ****************************************************************************
  3243. *END
  3244.  
  3245. nkc_toupper:   lea      toupper,a0           ; ^upper case translation table
  3246.                and      #$ff,d0              ; high byte = 0 for word operation
  3247.                move.b   (a0,d0),d0           ; convert
  3248.                rts                           ; bye
  3249.  
  3250.  
  3251.  
  3252. *START
  3253. ****************************************************************************
  3254. *
  3255. *  nkc_tolower: convert character to lower case
  3256. *  # G
  3257. *
  3258. *  C prototype: unsigned char nkc_tolower(unsigned char chr);
  3259. *---------------------------------------------------------------------------
  3260. *  The counterpart of nkc_toupper(). A character is converted to lower case.
  3261. *
  3262. *  In:   D0.B           any character
  3263. *
  3264. *  Out:  D0.B           character converted to lower case
  3265. *
  3266. *  Reg:  D:01234567   A:01234567   CCR
  3267. *          U**.....     **......    *
  3268. *
  3269. ****************************************************************************
  3270. *END
  3271.  
  3272. nkc_tolower:   lea      tolower,a0           ; ^lower case translation table
  3273.                and      #$ff,d0              ; high byte = 0 for word operation
  3274.                move.b   (a0,d0),d0           ; convert
  3275.                rts                           ; bye
  3276.  
  3277.  
  3278.  
  3279. ****************************************************************************
  3280. *                            LOCAL DATA SECTION                            *
  3281. ****************************************************************************
  3282.  
  3283.                .data
  3284.  
  3285. *  exception scan code table for cursor block keys
  3286. *
  3287. *  first entry.B:  NKCC key code
  3288. *  second entry.B: scan code returned by TOS
  3289. *
  3290. *  the table is terminated with both entries -1
  3291.  
  3292. xscantab:      .dc.b    NK_UP       ,  $48   ; cursor up
  3293.                .dc.b    NK_DOWN     ,  $50   ; cursor down
  3294.                .dc.b    NK_LEFT     ,  $4b   ; cursor left
  3295.                .dc.b    NK_LEFT     ,  $73   ; Control cursor left
  3296.                .dc.b    NK_RIGHT    ,  $4d   ; cursor right
  3297.                .dc.b    NK_RIGHT    ,  $74   ; Control cursor right
  3298.                .dc.b    NK_M_PGUP   ,  $49   ; Mac: page up
  3299.                .dc.b    NK_M_PGDOWN ,  $51   ; Mac: page down
  3300.                .dc.b    NK_M_END    ,  $4f   ; Mac: end
  3301.                .dc.b    NK_INS      ,  $52   ; Insert
  3302.                .dc.b    NK_CLRHOME  ,  $47   ; ClrHome
  3303.                .dc.b    NK_CLRHOME  ,  $77   ; Control ClrHome
  3304.                .dc.b    NK_HELP     ,  $62   ; Help
  3305.                .dc.b    NK_UNDO     ,  $61   ; Undo
  3306.                .dc.b    NK_M_F11    ,  $45   ; Mac: F11
  3307.                .dc.b    NK_M_F12    ,  $46   ; Mac: F12
  3308.                .dc.b    NK_M_F14    ,  $37   ; Mac: F14
  3309.                .dc.w    -1
  3310.  
  3311.  
  3312.  
  3313. *  deadkey table
  3314. *
  3315. *  first entry.B:  deadkey option mask (NKSf_D_...), 16 bits shifted down
  3316. *  second entry.W: ASCII code of deadkey
  3317. *  third entry.L:  ^deadkey match table
  3318. *
  3319. *  the table is terminated with an option mask of 0
  3320.  
  3321. deadtab:       .dc.w    NKSf_D_CIRCUM >> 16
  3322.                .dc.b    0,'^'
  3323.                .dc.l    d_circum
  3324.  
  3325.                .dc.w    NKSf_D_TILDE >> 16
  3326.                .dc.b    0,'~'
  3327.                .dc.l    d_tilde
  3328.  
  3329.                .dc.w    NKSf_D_AGUI >> 16
  3330.                .dc.w    $27
  3331.                .dc.l    d_agui
  3332.  
  3333.                .dc.w    NKSf_D_GRAVE >> 16
  3334.                .dc.b    0,'`'
  3335.                .dc.l    d_grave
  3336.  
  3337.                .dc.w    NKSf_D_UMLAUT >> 16
  3338.                .dc.b    0,'╣'
  3339.                .dc.l    d_umlaut
  3340.  
  3341.                .dc.w    NKSf_D_QUOTE >> 16
  3342.                .dc.w    $22
  3343.                .dc.l    d_umlaut
  3344.  
  3345.                .dc.w    NKSf_D_SMOERE >> 16
  3346.                .dc.b    0,'°'
  3347.                .dc.l    d_smoere
  3348.  
  3349.                .dc.w    NKSf_D_CEDIL >> 16
  3350.                .dc.b    0,','
  3351.                .dc.l    d_cedil
  3352.  
  3353.                .dc.w    NKSf_D_SLASH >> 16
  3354.                .dc.b    0,'/'
  3355.                .dc.l    d_slash
  3356.  
  3357.                .dc.w    0
  3358.  
  3359.  
  3360.  
  3361. *  deadkey match tables
  3362. *
  3363. *  first entry.B:  ASCII code generated by pressing deadkey and key code
  3364. *  second entry.B: key code (of the key which must be pressed directly after
  3365. *                  the deadkey)
  3366. *
  3367. *  the tables are terminated with both entries 0
  3368.  
  3369. d_circum:      .dc.b    '^','^'
  3370.                .dc.b    'â','a'
  3371.                .dc.b    'ê','e'
  3372.                .dc.b    'î','i'
  3373.                .dc.b    'ô','o'
  3374.                .dc.b    'û','u'
  3375.                .dc.w    0
  3376.  
  3377. d_tilde:       .dc.b    '~','~'
  3378.                .dc.b    'ñ','n'
  3379.                .dc.b    'Ñ','N'
  3380.                .dc.b    '░','a'
  3381.                .dc.b    '▒','o'
  3382.                .dc.b    '╖','A'
  3383.                .dc.b    '╕','O'
  3384.                .dc.w    0
  3385.  
  3386. d_agui:        .dc.b    $27,$27              ; ' characters
  3387.                .dc.b    'é','e'
  3388.                .dc.b    'É','E'
  3389.                .dc.b    'á','a'
  3390.                .dc.b    'í','i'
  3391.                .dc.b    'ó','o'
  3392.                .dc.b    'ú','u'
  3393.                .dc.w    0
  3394.  
  3395. d_grave:       .dc.b    '`','`'
  3396.                .dc.b    'à','a'
  3397.                .dc.b    'è','e'
  3398.                .dc.b    'ì','i'
  3399.                .dc.b    'ò','o'
  3400.                .dc.b    'ù','u'
  3401.                .dc.b    '╢','A'
  3402.                .dc.w    0
  3403.  
  3404. d_umlaut:      .dc.b    '╣','╣'
  3405.                .dc.b    $22,$22              ; " characters
  3406.                .dc.b    'ä','a'
  3407.                .dc.b    'ë','e'
  3408.                .dc.b    'ï','i'
  3409.                .dc.b    'ö','o'
  3410.                .dc.b    'ü','u'
  3411.                .dc.b    'ÿ','y'
  3412.                .dc.b    'Ä','A'
  3413.                .dc.b    'Ö','O'
  3414.                .dc.b    'Ü','U'
  3415.                .dc.w    0
  3416.  
  3417. d_smoere:      .dc.b    '°','°'
  3418.                .dc.b    'å','a'
  3419.                .dc.b    'Å','A'
  3420.                .dc.w    0
  3421.  
  3422. d_cedil:       .dc.b    ',',','
  3423.                .dc.b    'ç','c'
  3424.                .dc.b    'Ç','C'
  3425.                .dc.w    0
  3426.  
  3427. d_slash:       .dc.b    '/','/'
  3428.                .dc.b    '│','o'
  3429.                .dc.b    '▓','O'
  3430.                .dc.b    '½','2'
  3431.                .dc.b    '¼','4'
  3432.                .dc.w    0
  3433.  
  3434.  
  3435.  
  3436.                .if      NKCGEM=1
  3437.  
  3438. *  AES parameter block
  3439.  
  3440. aespb:          .dc.l   nkc_contrl
  3441.                 .dc.l   0                    ; set by nkc_init()
  3442.                 .dc.l   nkc_intin
  3443.                 .dc.l   nkc_intout
  3444.                 .dc.l   nkc_adrin
  3445.                 .dc.l   nkc_adrout
  3446.  
  3447. *  VDI parameter block
  3448.  
  3449. vdipb:          .dc.l   nkc_contrl
  3450.                 .dc.l   nkc_intin
  3451.                 .dc.l   nkc_ptsin
  3452.                 .dc.l   nkc_intout
  3453.                 .dc.l   nkc_ptsout
  3454.  
  3455.  
  3456. *  double click time table (values given in 1/200 s)
  3457.  
  3458. timetab:        .dc.l   85                   ; 0.425 s
  3459.                 .dc.l   63                   ; 0.315 s
  3460.                 .dc.l   49                   ; 0.245 s
  3461.                 .dc.l   42                   ; 0.210 s
  3462.                 .dc.l   30                   ; 0.150 s
  3463.  
  3464.                .endif   ;  .if NKCGEM=1
  3465.  
  3466.  
  3467.  
  3468. *  lower case to upper case conversion table
  3469. *  (array of 256 unsigned bytes)
  3470.  
  3471. toupper:
  3472.                .dc.b    $00,$01,$02,$03,$04,$05,$06,$07
  3473.                .dc.b    $08,$09,$0a,$0b,$0c,$0d,$0e,$0f
  3474.                .dc.b    $10,$11,$12,$13,$14,$15,$16,$17
  3475.                .dc.b    $18,$19,$1a,$1b,$1c,$1d,$1e,$1f
  3476.                .dc.b    " !",$22,"#$%&",$27,"()*+,-./0123456789:;<=>?"
  3477.                .dc.b    "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[",$5c,"]^_"
  3478.                .dc.b    "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~"
  3479.                .dc.b    "ÇÜÉâÄ╢ÅÇêëèïîìÄÅÉÆÆôÖòûùÿÖÜ¢£¥₧ƒ"
  3480.                .dc.b    "áíóúÑѪº¿⌐¬½¼¡«»╖╕▓▓╡╡╢╖╕╣║╗╝╜╛┐"
  3481.                .dc.b    "└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀"
  3482.                .dc.b    "αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "
  3483.  
  3484.  
  3485. *  upper case to lower case conversion table
  3486. *  (array of 256 unsigned bytes)
  3487.  
  3488. tolower:
  3489.                .dc.b    $00,$01,$02,$03,$04,$05,$06,$07
  3490.                .dc.b    $08,$09,$0a,$0b,$0c,$0d,$0e,$0f
  3491.                .dc.b    $10,$11,$12,$13,$14,$15,$16,$17
  3492.                .dc.b    $18,$19,$1a,$1b,$1c,$1d,$1e,$1f
  3493.                .dc.b    " !",$22,"#$%&",$27,"()*+,-./0123456789:;<=>?"
  3494.                .dc.b    "@abcdefghijklmnopqrstuvwxyz[",$5c,"]^_"
  3495.                .dc.b    "`abcdefghijklmnopqrstuvwxyz{|}~"
  3496.                .dc.b    "çüéâäàåçêëèïîìäåéææôöòûùÿöü¢£¥₧ƒ"
  3497.                .dc.b    "áíóúññªº¿⌐¬½¼¡«»░▒││┤┤à░▒╣║╗╝╜╛┐"
  3498.                .dc.b    "└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀"
  3499.                .dc.b    "αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "
  3500.  
  3501. * note for both tables:
  3502. *
  3503. * $22 = " character
  3504. * $27 = ' character
  3505. * $5c = \ character
  3506.  
  3507.  
  3508. *  scan code translation table
  3509. *
  3510. *  first entry.W : shift flags (NKFf_CTRL/SHIFT/ALT/FUNC), 8 bits shifted down
  3511. *  second entry.B: real scan code (index into key table)
  3512. *  third entry.B : simulated scan code (set by OS when the flags specified
  3513. *                  above are set)
  3514. *
  3515. *  The table is terminated with all entries 0.
  3516.  
  3517. scan_trans:    .dc.w    NKFf_SHIFT>>8        ; Shift F1
  3518.                .dc.b    $3b,$54
  3519.                .dc.w    NKFf_SHIFT>>8        ; Shift F2
  3520.                .dc.b    $3c,$55
  3521.                .dc.w    NKFf_SHIFT>>8        ; Shift F3
  3522.                .dc.b    $3d,$56
  3523.                .dc.w    NKFf_SHIFT>>8        ; Shift F4
  3524.                .dc.b    $3e,$57
  3525.                .dc.w    NKFf_SHIFT>>8        ; Shift F5
  3526.                .dc.b    $3f,$58
  3527.                .dc.w    NKFf_SHIFT>>8        ; Shift F6
  3528.                .dc.b    $40,$59
  3529.                .dc.w    NKFf_SHIFT>>8        ; Shift F7
  3530.                .dc.b    $41,$5a
  3531.                .dc.w    NKFf_SHIFT>>8        ; Shift F8
  3532.                .dc.b    $42,$5b
  3533.                .dc.w    NKFf_SHIFT>>8        ; Shift F9
  3534.                .dc.b    $43,$5c
  3535.                .dc.w    NKFf_SHIFT>>8        ; Shift F10
  3536.                .dc.b    $44,$5d
  3537.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control cursor left
  3538.                .dc.b    $4b,$73
  3539.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control cursor right
  3540.                .dc.b    $4d,$74
  3541.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control ClrHome
  3542.                .dc.b    $47,$77
  3543.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #1
  3544.                .dc.b    $02,$78
  3545.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #2
  3546.                .dc.b    $03,$79
  3547.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #3
  3548.                .dc.b    $04,$7a
  3549.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #4
  3550.                .dc.b    $05,$7b
  3551.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #5
  3552.                .dc.b    $06,$7c
  3553.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #6
  3554.                .dc.b    $07,$7d
  3555.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #7
  3556.                .dc.b    $08,$7e
  3557.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #8
  3558.                .dc.b    $09,$7f
  3559.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #9
  3560.                .dc.b    $0a,$80
  3561.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #10
  3562.                .dc.b    $0b,$81
  3563.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #11
  3564.                .dc.b    $0c,$82
  3565.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #12
  3566.                .dc.b    $0d,$83
  3567.                .dc.l    0                    ; terminator
  3568.  
  3569.  
  3570. *  ASCII code translation table for Control key
  3571. *
  3572. *  first entry.B:  modified ASCII code returned by TOS
  3573. *  second entry.B: original ASCII code as stored in key table
  3574. *
  3575. *  The table is terminated with both entries 0
  3576.  
  3577. asc_trans:     .dc.b    0,'2'                ; Control '2' becomes ASCII 0
  3578.                .dc.b    $1e,'6'              ; Control '6' becomes ASCII $1e
  3579.                .dc.b    $1f,'-'              ; Control '-' becomes ASCII $1f
  3580.                .dc.b    $a,$d                ; Control Return/Enter: $d -> $a
  3581.                .dc.w    0                    ; terminator
  3582.  
  3583.  
  3584. *  normalized key code -> scan code translation table
  3585. *  for unshifted key codes
  3586. *  indexed by function code (NK_...)
  3587.  
  3588. n_to_scan_u:   .dc.b    $00                  ; invalid key code
  3589.                .dc.b    $48                  ; cursor up
  3590.                .dc.b    $50                  ; cursor down
  3591.                .dc.b    $4d                  ; cursor right
  3592.                .dc.b    $4b                  ; cursor left
  3593.                .dc.b    $49                  ; Mac: page up
  3594.                .dc.b    $51                  ; Mac: page down
  3595.                .dc.b    $4f                  ; Mac: end
  3596.                .dc.b    $0e                  ; Backspace
  3597.                .dc.b    $0f                  ; Tab
  3598.                .dc.b    $72                  ; Enter
  3599.                .dc.b    $52                  ; Insert
  3600.                .dc.b    $47                  ; ClrHome
  3601.                .dc.b    $1c                  ; Return
  3602.                .dc.b    $62                  ; Help
  3603.                .dc.b    $61                  ; Undo
  3604.                .dc.b    $3b                  ; function key #1
  3605.                .dc.b    $3c                  ; function key #2
  3606.                .dc.b    $3d                  ; function key #3
  3607.                .dc.b    $3e                  ; function key #4
  3608.                .dc.b    $3f                  ; function key #5
  3609.                .dc.b    $40                  ; function key #6
  3610.                .dc.b    $41                  ; function key #7
  3611.                .dc.b    $42                  ; function key #8
  3612.                .dc.b    $43                  ; function key #9
  3613.                .dc.b    $44                  ; function key #10
  3614.                .dc.b    $45                  ; Mac: F11
  3615.                .dc.b    $01                  ; Esc
  3616.                .dc.b    $46                  ; Mac: F12
  3617.                .dc.b    $37                  ; Mac: F14
  3618.                .dc.b    $00                  ; reserved!
  3619.                .dc.b    $53                  ; Delete
  3620.  
  3621. *  normalized key code -> scan code translation table
  3622. *  for shifted key codes
  3623. *  indexed by function code (NK_...)
  3624.  
  3625. n_to_scan_s:   .dc.b    $00                  ; invalid key code
  3626.                .dc.b    $48                  ; cursor up
  3627.                .dc.b    $50                  ; cursor down
  3628.                .dc.b    $4d                  ; cursor right
  3629.                .dc.b    $4b                  ; cursor left
  3630.                .dc.b    $49                  ; Mac: page up
  3631.                .dc.b    $51                  ; Mac: page down
  3632.                .dc.b    $4f                  ; Mac: end
  3633.                .dc.b    $0e                  ; Backspace
  3634.                .dc.b    $0f                  ; Tab
  3635.                .dc.b    $72                  ; Enter
  3636.                .dc.b    $52                  ; Insert
  3637.                .dc.b    $47                  ; ClrHome
  3638.                .dc.b    $1c                  ; Return
  3639.                .dc.b    $62                  ; Help
  3640.                .dc.b    $61                  ; Undo
  3641.                .dc.b    $54                  ; function key #1
  3642.                .dc.b    $55                  ; function key #2
  3643.                .dc.b    $56                  ; function key #3
  3644.                .dc.b    $57                  ; function key #4
  3645.                .dc.b    $58                  ; function key #5
  3646.                .dc.b    $59                  ; function key #6
  3647.                .dc.b    $5a                  ; function key #7
  3648.                .dc.b    $5b                  ; function key #8
  3649.                .dc.b    $5c                  ; function key #9
  3650.                .dc.b    $5d                  ; function key #10
  3651.                .dc.b    $45                  ; Mac: F11
  3652.                .dc.b    $01                  ; Esc
  3653.                .dc.b    $46                  ; Mac: F12
  3654.                .dc.b    $37                  ; Mac: F14
  3655.                .dc.b    $00                  ; reserved!
  3656.                .dc.b    $53                  ; Delete
  3657.  
  3658.  
  3659.  
  3660. ****************************************************************************
  3661. *                             LOCAL BSS SECTION                            *
  3662. ****************************************************************************
  3663.  
  3664.                .bss
  3665.  
  3666.  
  3667. *              key code handler
  3668.  
  3669. pkey_unshift:  .ds.l    1                    ; ^unshifted key table
  3670. pkey_shift:    .ds.l    1                    ; ^shifted key table
  3671. pkey_caps:     .ds.l    1                    ; ^CapsLock table
  3672. pshift:        .ds.l    1                    ; ^shift state system variable
  3673. sflags:        .ds.l    1                    ; special key flags
  3674. prvkey:        .ds.w    1                    ; previous key code
  3675. prvvalid:      .ds.b    1                    ; non-zero: prvkey is valid
  3676.                .even
  3677.  
  3678.  
  3679. *              button event handler
  3680.  
  3681.                .if      NKCGEM=1
  3682.  
  3683. bvar:           .ds.b   BI                   ; button event info block
  3684. tendtime:       .ds.l   1                    ; timer event end value
  3685. prvtime:        .ds.l   1                    ; previous timer event value
  3686. vdihnd:         .ds.w   1                    ; handle of VDI workstation
  3687. multibuf:       .ds.w   16+2                 ; buffer for evnt_multi parameters
  3688. buthnd:         .ds.b   1                    ; non-zero:button handler installed
  3689.                 .even
  3690.  
  3691.  
  3692.  
  3693. *              other stuff
  3694.  
  3695. kbdiorec:       .ds.l   1                    ; ^keyboard Iorec structure
  3696. iohead:         .ds.w   1                    ; NKCC's head pointer
  3697.  
  3698.                .endif   ; .if NKCGEM=1
  3699.  
  3700. sysclock:      .ds.l    1                    ; copy of 200 Hz system clock
  3701. timerflag:     .ds.b    1                    ; non-zero:200 Hz timer installed
  3702.                .even
  3703.  
  3704.  
  3705.  
  3706. *START
  3707. ****************************************************************************
  3708. *                            GLOBAL BSS SECTION                            *
  3709. ****************************************************************************
  3710. *END
  3711.  
  3712.                .bss
  3713.  
  3714. *START
  3715. *  GEM parameter arrays
  3716. *  (needed if using nkc_amulti())
  3717.  
  3718.                .if      NKCGEM=1
  3719.  
  3720. nkc_contrl:     .ds.w   32                   ; control array
  3721. nkc_intin:      .ds.w   32                   ; integer input array
  3722. nkc_intout:     .ds.w   32                   ; integer output array
  3723. nkc_adrin:      .ds.l   32                   ; address input array
  3724. nkc_adrout:     .ds.l   32                   ; address output array
  3725. nkc_ptsin:      .ds.l   32                   ; pointers input array
  3726. nkc_ptsout:     .ds.l   32                   ; pointers output array
  3727.  
  3728.                .endif   ; .if NKCGEM=1
  3729. *END
  3730.  
  3731. *START
  3732. * End Of File
  3733. *END
  3734.  
  3735.