
Documentation of: package\nkcc.s
Date of creation: Monday  27.06.1994  16.35

********************************************************************************
*
*  Project name : NORMALIZED KEY CODE CONVERTER (NKCC)
*  Module name  : Main module
*  Symbol prefix: nkc
*
*  Author       : Harald Siegmund (HS)
*  Co-Authors   : -
*  Write access : HS
*
*  Notes        : The symbol NKCGEM will have to be defined on the assembler's
*                 command line when translating the source of NKCC. Set its
*                 value to 1 if you like to create the complete version. A value
*                 of 0 will supress inclusion of the GEM part, making NKCC a few
*                 KBytes smaller. Some functions and the GEM parameter arrays
*                 are not available then.
*
*                 Translate this source with the MadMac assembler:
*                 mac -dNKCGEM=1 -onkcc.o nkcc.s
*                 mac -dNKCGEM=0 -onkcc_tos.o nkcc.s
*
*-------------------------------------------------------------------------------
*  NKCC was developed with Atari's MadMac assembler. It should be possible to
*  adapt the source to different assemblers with minor effort. Here's an
*  overview of all MadMac-specific assembly directives used in this source file:
*
*  .globl         declares a symbol to be imported from another module
*                  respectively exported from the current source (depending if
*                  the symbol is defined in the source or not)
*  .if <expr>     conditional assembly; <expr> is tested to be non-zero (true)
*                 or zero (false)
*  .else
*  .endif
*  =              equate
*  .abs           absolute section; is usually used to defined structure
*                  offsets. Labels in the absolute section get a constant
*                  value and usually have a .ds directive in their opcode
*                  field incrementing the value for the next label
*  .macro         introduces a macro definition
*  .endm          ends a macro definition
*
*  Macros:
*   .macro name [argument,argument,...]
*   Arguments accesses inside the macro must have a backslash character
*    (e.g. move   \argument1,d0)
*   The expression  \?{argument}  tests if an argument is defined or not.
*
*  Symbols:
*   MadMac supports local symbols with a limited scope. Their name starts with
*   a period (.) and their scope ends at the next global symbol (in both
*   directions).
*
*-------------------------------------------------------------------------------
*  Things to do :
*
*  -  NKCC will support additional (and more complex) deadkeys some time, such
*     like Arabian ones. A communication interface between NKCC and a text
*     editor will be built in for that purpose (Arabian languages' deadkeys can
*     affect existing text!).
*
*-------------------------------------------------------------------------------
*  History:
*
*  1989:
*     May 14: creation of file (NKCC 1.00)
*     Jun 07/15-16/19/21/Jul 11: improvements, changes, debugging
*  1990:
*     Jan 13: global functions now available in two versions:
*             parameters passed via registers (e.g. for Turbo C)
*             parameters passed via stack (underscore before label name)
*
*     May 23-24/26-28: creation of NKCC 2.00 (almost every function rewritten)
*     Jun 16/27: assembler-entry added by Gerd Knops
*     Jun 30/Jul 02: return shift key flags in nkc_multi()/amulti() as NKF?_...
*     Jul 09: nkc_kstate()
*     Aug 03: nkc_cmp()
*     Aug 18: fatal bug in nkc_kstate() fixed
*     Sep 15: nkc_timer()
*     Sep 15-17/30: own button event handler
*     Oct 03: debugging
*             nkc_vlink()/vunlink()
*             documentation syntax changed (LRef/XRef removed; Reg: changed)
*     Oct 05: debugging mouse button handler (problems with menu bar)
*     Oct 07: Control/Alternate + character always returns capital characters
*             changing key code comparism rules in nkc_cmp()
*     Oct 22: debugging nkc_cmp() (did sometimes recognize unique key codes)
*             debugging ASCII code input in nkc_amulti()
*     Dec 11/15/17: MU_XTIMER
*  1991:
*     Jan 11: don't call AES with set MU_XTIMER flag
*     Mar 31: ensure that evnt_multi() parameters are restored when being
*             corrupted by a bug in AES!!
*     Apr 01: debugging
*     Apr 13: nkc_conv() renamed to nkc_tconv()
*     Apr 13-14: nkc_gconv()
*     May 10: debugging (nk_beend())
*     May 29: debugging (double shift key compare)
*             export nkc_toupper and nkc_tolower
*     Jul 05: completing history
*     Jul 31: version number before XBRA header
*     Aug 06: " is now a deadkey!
*     Aug 07: more deadkeys...
*     Aug 22: deadkeys can now be enabled/disabled separately
*             nkc_set() changed
*             nkc_init() returns version #
*             bug fixed: nkc_cmp() corrupted high words of D3 and D4
*     Sep 07/14: nkc_cmp() improved; NKF?_RESVD now in use
*     Nov 05: adjustments to ASCII input feature of TOS 3.06
*     Nov 16: bug fixed in nkc_cmp() mechanism
*             Control key emulation
*     Dec 29: small corrections and extensions of the documentation
*             source documentation syntax now in extra file
*  1992:
*     Jan 03: changing documentation of nkc_init()
*             revising info lines in function headers
*     Jan 12: adjusting nkc_init() to its new documentation!
*             appending .b respectively .l to all instructions with a default
*              operand size which is not .w
*             changing macro XBRA_HD
*     Feb 11: adjusting button event handler to MINT
*     Feb 28: NKCOWNPB switch
*  1993:
*     Dec 11: merging the two existing NKCC versions to one source:
*             - version number set to $0290
*             - NKCNOGEM/NKCOWNPB keys replaced by NKCGEM key
*             - NKCC uses its own AES/VDI parameter arrays now
*             - nkc_init() gets one more parameter: ^AES global array
*             - nkc_toupper and nkc_tolower are functions now
*             - dynamic double click time
*             - MU_MESAG occured -> don't create self-made button events
*     Dec 12: GEM keyboard events: try to get original shift flags from the
*              Iorec buffer
*             new functions: nkc_n2tos() and nkc_n2gem()
*     Dec 13: debugging: ! operator changed to ~ in nk_bestart
*             implementing nkc_n2tos()
*             size of GEM parameter arrays changed to 32 (larger than required
*              but better too big than too small!)
*     Dec 16: debugging nkc_n2tos()
*     Dec 19: improving nkc_gconv() (scan code translation table)
*             debugging nkc_n2tos()
*             cosmetic changes
*     Dec 23: debugging nkc_vunlink(): return status was garbage!
*  1994:
*     May 19: release 2.91:
*             don't restore conterm (it may be changed by another process in
*              the meantime)
*             new deadkeys (/2 /4)
*             adding overview of used MadMac directives in the note section of
*              the file header
*     Jun 27: release 2.92:
*             check for illegal scan codes (e.g. $ff under Mag!x)
*
********************************************************************************
*KEY _NAME="NKCC"


****************************************************************************
*                         ASSEMBLER CONTROL SECTION                        *
****************************************************************************

*KEY &NKCGEM
*     define this symbol on the assembler's command line
*     =0    create TOS-version of NKCC (without GEM part)
*     =1    create GEM-version of NKCC

               .include "nkcc.sh"            ; NKCC definitions


****************************************************************************
*                                  EXPORT                                  *
****************************************************************************

                                             ; functions
               .globl   nkc_init             ; init NKCC
               .globl   nkc_exit             ; exit NKCC
               .globl   nkc_set              ; set special key flags
               .globl   nkc_conin            ; NKCC key input via GEMDOS
               .globl   nkc_cstat            ; console input status via GEMDOS
               .globl   nkc_tconv            ; TOS key code converter
               .globl   nkc_gconv            ; GEM key code converter
               .globl   nkc_n2tos            ; NKC to TOS key code converter
               .globl   nkc_n2gem            ; NKC to GEM key code converter
               .globl   nkc_kstate           ; return shift key state
               .globl   nkc_timer            ; return 200 Hz system clock
               .globl   nkc_cmp              ; compare two key codes
               .globl   nkc_vlink            ; link function to XBRA vector list
               .globl   nkc_vunlink          ; unlink function from XBRA list
               .globl   nkc_toupper          ; convert character to upper case
               .globl   nkc_tolower          ; convert character to lower case

               .if      NKCGEM=1

                .globl  nkc_multi            ; NKCC multi event handler
                .globl  nkc_amulti           ; multi event, assembler binding
                .globl  nkc_contrl           ; GEM parameter arrays
                .globl  nkc_intin
                .globl  nkc_intout
                .globl  nkc_adrin
                .globl  nkc_adrout
                .globl  nkc_ptsin
                .globl  nkc_ptsout

               .endif   ; .if NKCGEM=1


****************************************************************************
*                            GLOBAL TEXT SECTION                           *
****************************************************************************


****************************************************************************
*
*  nkc_init: initialize NKCC
*  # G U
*
*  This function initializes NKCC. It must be called once before any other
*  NKCC routine. It performs some tasks that may be important for you to
*  know:
*
*  - bit 3 of the system variable <conterm> ($484.B) is set
*  - a 200 Hz clock interrupt is installed, using the XBRA method (ID is
*    "NKCC")
*
*  nkc_init() gets some flags which configure NKCC and enable some special
*  functions:
*
*  NKI?_BUTHND       install NKCC's button event handler (see documentation
*                    NKCC.DOC for details)
*  NKI?_BHTOS        additional flag: install only, if TOS has mouse click bug
*  NKI?_NO200HZ      don't install the 200 Hz timer interrupt
*
*  Notes:
*
*  - if NKCC is assembled as TOS-only version (symbol NKCGEM set to 0),
*    both NKI?_BUTHND and NKI?_BHTOS flags are ignored.
*
*  - if the button event handler is installed, the NKI?_NO200HZ flag is
*    ignored (because the 200 Hz clock is needed by the handler). Besides,
*    the initialization continues:
*
*    - an own GEM trap handler (trap #2) is installed, using the XBRA method
*      (to be up to date when a new double click time is set via the AES
*      function evnt_dclick())
*
*    - a vex_butv() call (VDI) is made to install a mouse button exchange
*      handler
*
*  In:   D0.L           miscellaneous flags (NKI?_...); see above
*        D1.W           handle of an open VDI workstation
*                       (must only be valid if the button handler is
*                       installed)
*        A0.L           ^applications GLOBAL array (from GEM parameter block)
*                       not used in the TOS version of NKCC
*
*  Out:  D0.W           NKCC's version number as 4 digit BCD
*                       (main # in high byte, sub # in low byte)
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_exit: exit NKCC
*  # G U
*
*  nkc_exit() must be called before the program is quit. It removes all
*  handlers installed in the system.
*
*  In:   -
*
*  Out:  D0.W           status flag:
*                       0     OK
*                       -1    can't remove 200 Hz clock interrupt
*                       -2    can't remove trap #2 handler
*                       -3    can't remove both handlers
*                       An error can happen if somebody corrupted the
*                       XBRA vector list. This is fatal!
*
*  Reg:  D:01234567   A:01234567   CCR
*          ***.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_set: set special key flags
*  # G
*
*  This function is used to enable/disable special key handling procedures.
*  The features which can be set are:
*
*  - direct input of ASCII codes; when switched on, pressing the Alternate
*    key plus one of the numbers on the numeric keypad will start the input
*    of a decimal ASCII number. The input is finished either when 3 digits
*    are typed in or the Alternate key is released. NKCC will return the
*    corresponding character with the entered ASCII code. This feature makes
*    it possible to use the whole range of the character set (from 0 ... 255).
*
*  - deadkey management; when switched on, NKCC will combine some combi-
*    nations of two key strokes to one character. This is used to generate
*    characters with accents which are not on the keyboard. The supported
*    deadkeys are:
*
*    ^   +   aeiou      =         (NKS?_D_CIRCUM)
*    ~   +   nNaoAo     =  คฅฐฑทธ      (NKS?_D_TILDE)
*    '   +   eEaiou     =   กขฃ      (NKS?_D_AGUI)
*    `   +   aeiouA     =  ถ      (NKS?_D_GRAVE)
*    น   +   aeiouyAOU  =     (NKS?_D_UMLAUT)
*    "   +   aeiouyAOU  =     (NKS?_D_QUOTE)
*    ๘   +   aA         =            (NKS?_D_SMOERE)
*    ,   +   cC         =            (NKS?_D_CEDIL)
*    /   +   oO24       =  ณฒซฌ        (NKS?_D_SLASH)
*
*    The quote character as synonym for umlaut is e.g. needed on the Dutch
*    keyboard, where neither umlaut characters nor the umlaut itself are
*    available.
*
*    Each deadkey can be enabled/disabled separately.
*
*  - Control key emulation: Control plus an ASCII code in the range of
*    $40...$5F (characters @, A...Z, [, \, ], ^ and _) is converted
*    to an ASCII code of $00...$1F.
*
*
*  In:   D0.L           new key flags (bit set = feature on):
*                       NKS?_ALTNUM       ASCII input
*                       NKS?_D_...        deadkey ...
*                                         (NKSf_DEADKEY: all deadkeys)
*                       NKS?_CTRL         control key emulation
*
*  Out:  -
*
*  Reg:  D:01234567   A:01234567   CCR
*          ***.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_conin: raw console character input
*  # G
*
*  This routine replaces the Gemdos function Crawcin. However, it returns
*  a WORD with the key code in normalized format rather than a LONG with
*  the key code in the language dependend TOS format.
*
*  In:   -
*
*  Out:  D0.W           key code in normalized format
*                       for details see nkc_tconv()
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          W**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_cstat: return console character input status
*  # G
*
*  This function checks, if a key is in the key input buffer or not.
*
*  In:   -
*
*  Out:  D0.W           flag:
*                       0     no key in buffer
*                       -1    at least one key in buffer
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          W**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_multi: NKCC multi event
*  # G U
*
*  nkc_multi() is a binding function to the AES multi event handler. The
*  only differences are the keyboard events and the shift key state: the key
*  codes are returned in normalized format (see nkc_tconv()), the shift key
*  state is compatible to the NKF?_... flags. For a detailed description of
*  the whole mass of parameters consult your AES manual or compiler handbook!
*
*  In:    4(SP).w       event mask (MU_...)
*         6(SP).w       MU_BUTTON: max # of clicks to wait for
*         8(SP).w       MU_BUTTON: mask of buttons to check
*        10(SP).w       MU_BUTTON: button states to wait for
*        12(SP).w       MU_M1: area enter/leave flag
*        14(SP).w       MU_M1: x position of area
*        16(SP).w       MU_M1: y position of area
*        18(SP).w       MU_M1: width of area
*        20(SP).w       MU_M1: height of area
*        22(SP).w       MU_M2: area enter/leave flag
*        24(SP).w       MU_M2: x position of area
*        26(SP).w       MU_M2: y position of area
*        28(SP).w       MU_M2: width of area
*        30(SP).w       MU_M2: height of area
*        32(SP).L       MU_MESAG: ^8 words of message buffer
*        36(SP).w       MU_TIMER: low word of time to wait
*        38(SP).w       MU_TIMER: high word of time to wait
*        40(SP).L       MU_BUTTON/M1/M2: ^word for mouse x
*        44(SP).L       MU_BUTTON/M1/M2: ^word for mouse y
*        48(SP).L       MU_BUTTON/M1/M2: ^word for button state
*        52(SP).L       MU_BUTTON/M1/M2: ^word for shift state
*        56(SP).L       MU_KEYBD: ^word for key code in normalized format
*        60(SP).L       MU_BUTTON: ^word for # of mouse clicks
*
*  Out:  D0.W           mask of occured events (MU_...)
*
*  Reg:  D:01234567   A:01234567   CCR
*          W**.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_amulti: NKCC multi event called by Assembler  *** added by Gerd Knops
*  # G U
*
*  See description of nkc_multi()!
*
*  usage: instead of    move.l   #aespb,d1
*                       move  #$c8,d0
*                       trap  #2
*
*         do            jsr   nkc_amulti
*
*  In:   all parameters for evnt_multi in the AES parameter arrays
*
*  Out:  values in intout and message buffer
*
*  Reg:  D:01234567   A:01234567   CCR
*          ***.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_tconv: TOS key code converter
*  # G R
*
*  This is the most important function within NKCC: it takes a key code
*  returned by TOS and converts it to the sophisticated normalized format.
*
*  Note: the raw converter does no deadkey handling, ASCII input or
*        Control key emulation.
*
*  In:   D0.L           key code in TOS format:
*                                   0                    1
*                       bit 31:     ignored              ignored
*                       bit 30:     ignored              ignored
*                       bit 29:     ignored              ignored
*                       bit 28:     no CapsLock          CapsLock
*                       bit 27:     no Alternate         Alternate pressed
*                       bit 26:     no Control           Control pressed
*                       bit 25:     no left Shift key    left Shift pressed
*                       bit 24:     no right Shift key   right Shift pressed
*
*                       bits 23...16: scan code
*                       bits 15...08: ignored
*                       bits 07...00: ASCII code (or rubbish in most cases
*                          when Control or Alternate is pressed ...)
*
*  Out:  D0.W           normalized key code:
*                       bits 15...08: flags:
*                                   0                    1
*                       NKF?_FUNC   printable char       "function key"
*                       NKF?_RESVD  ignore it            ignore it
*                       NKF?_NUM    main keypad          numeric keypad
*                       NKF?_CAPS   no CapsLock          CapsLock
*                       NKF?_ALT    no Alternate         Alternate pressed
*                       NKF?_CTRL   no Control           Control pressed
*                       NKF?_LSH    no left Shift key    left Shift pressed
*                       NKF?_RSH    no right Shift key   right Shift pressed
*
*                       bits 07...00: key code
*                       function (NKF?_FUNC set):
*                          < 32: special key (NK_...)
*                          >=32: printable char + Control and/or Alternate
*                       no function (NKF?_FUNC not set):
*                          printable character (0...255!!!)
*
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_gconv: GEM key code converter
*  # G R
*
*  Why a second key code converter, you ask? Well, in some cases it might
*  happen that the key status byte of the original key code (with states
*  of both Shift keys, Control, Alternate and CapsLock) is lost. Then
*  this converter function must be called, which uses another algorithm
*  to construct the normalized key code.
*
*  Notes:
*  -  the raw converter does no deadkey handling, ASCII input or Control
*     key emulation.
*  -  NKCC does not use this function at all for its own purposes!
*  -  some key combinations cannot be distinguished without the flag byte!
*     For example, "Alternate A" and "Shift Alternate A" produce the same
*     result. Whenever possible, use nkc_tconv()!
*
*  In:   D0.W           key code in GEM format:
*                       bits 15...08: scan code
*                       bits 07...00: ASCII code
*
*  Out:  D0.W           normalized key code (see nkc_tconv() for details)
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_n2tos: convert normalized key codes back to TOS format
*  # G R
*
*  In some cases you might have to have key codes in the original TOS format
*  again, as returned by the GEMDOS functions Cconin(), Crawcin() or the BIOS
*  function Bconin(). Use nkc_n2tos() to convert them. For a detailed
*  description of the returned format consult the header of the function
*  nkc_tconv().
*
*  In:   D0.W           key code in normalized format
*
*  Out:  D0.L           key code in TOS format:
*                       bits 24...31: shift key flags
*                       bits 23...16: scan code
*                       bits 08...15: reserved (0)
*                       bits 00...07: ASCII code
*        CCR            set according content of D0.L
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......   =D0.L
*
****************************************************************************


****************************************************************************
*
*  nkc_n2gem: convert normalized key codes back to GEM format
*  # G R
*
*  Similar to nkc_n2tos(), this function converts normalized key codes back
*  to the operating system's format. The result is a key code as returned
*  by the AES functions evnt_keybd() respectively evnt_multi().
*
*  In:   D0.W           key code in normalized format
*
*  Out:  D0.W           key code in GEM format:
*                       bits 08...15: scan code
*                       bits 00...07: ASCII code
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_kstate: return state of Shift/Control/Alternate/CapsLock in
*              normalized format
*  # G R
*
*  This is a very *FAST* function which returns the state of the Shift/
*  Control/Alternate and CapsLock keys in normalized format.
*
*  In:   -
*
*  Out:  D0.W           normalized key flags:
*                                   0                    1
*                       NKF?_CAPS   no CapsLock          CapsLock
*                       NKF?_ALT    no Alternate         Alternate pressed
*                       NKF?_CTRL   no Control           Control pressed
*                       NKF?_LSH    no left Shift key    left Shift pressed
*                       NKF?_RSH    no right Shift key   right Shift pressed
*
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          w**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_timer: return current value of 200 Hz system clock
*  # G R
*
*  This is a very *FAST* function which returns the content of the 200 Hz
*  system clock.
*
*  In:   -
*
*  Out:  D0.L           current 200 HZ system clock value
*
*  Reg:  D:01234567   A:01234567   CCR
*          w**.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_cmp: compare two key codes
*  # G R
*
*  nkc_cmp() compares key codes. What for, you ask? A simple "if key_code1
*  = key_code2" would also do it? No! This function follows some specific
*  rules, which improve the flexibility of key code comparism.
*
*  One of the key codes passed to nkc_cmp() is called the "reference key
*  code". The other is the "test key code", which is got from nkc_conin()
*  or nkc_multi(). Some flags of the reference code are treated a special
*  way:
*
*  NKF?_IGNUM (same as NKF?_RESVD)
*     if set, the numeric keypad flag doesn't matter
*
*  NKF?_CAPS (CapsLock)
*     if set, the case of the ASCII code doesn't matter
*
*  NKFf_SHIFT (both Shift key flags)
*     if BOTH shift flags are set, the combination of shift key flags in
*     the test key code doesn't matter: only one shift flag has to be set,
*     no matter which one.
*
*  In:   D0.W           reference key code
*        D1.W           key code to test
*
*  Out:  D0.W           flag: 1 = key codes match
*                             0 = key codes don't match
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          u**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_vlink: link function to XBRA vector list
*  # G U
*
*  This function can be used to change system vectors and let them point
*  to own functions, using a standard method. The vector, which should be
*  changed, is described by the contents of D0.L and D1.W. It can be
*  either a standard vector number, e.g. 2 for the bus error exception
*  vector, or the absolute address of the vector, e.g. $502 for the screen
*  dump vector. The function to install must have the following header:
*
*  .dc.b    "XBRA"         magic longword
*  .dc.b    "myID"         four ASCII character ID of the function
*                          (NKCC uses "NKCC", for example)
*  .dc.l    0              buffer for the old vector content
*  function: ...           start of the function code
*
*  The function should end with:
*
*  move.l   function-4(pc),-(sp)
*  rts
*
*
*  Note: in NKXM_ADR mode, this function automatically switches (temporary)
*        to Supervisor mode to prevent bus errors
*
*
*  In:   D0.L           vector descriptor
*        D1.W           mode:
*                       NKXM_NUM = D0.L contains a vector number
*                       NKXM_ADR = D0.L contains a vector address
*        A0.L           ^function to install (NOT ^XBRA header!)
*
*  Out:  -4(A0.L).L     old content of vector
*
*  Reg:  D:01234567   A:01234567   CCR
*          ***.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_vunlink: unlink function from XBRA vector list
*  # G U
*
*  nkc_vunlink() removes a function which was installed using the XBRA method.
*  For details see nkc_link(). If the XBRA list was corrupted, the function
*  aborts with an error code. This happens, when a non-XBRA routine is
*  installed on the same vector after the nkc_vlink() call of the function
*  to remove.
*
*  Note: the function automatically switches (temporary) to Supervisor mode
*        to prevent bus errors
*
*  In:   D0.L           vector descriptor
*        D1.W           mode:
*                       NKXM_NUM = D0.L contains a vector number
*                       NKXM_ADR = D0.L contains a vector address
*        A0.L           ^function to remove (NOT ^XBRA header!)
*
*  Out:  D0.W           status:
*                       0 = OK
*                       -1 = can't remove (XBRA list corrupted)
*        CCR            set according content of D0.W
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......   =D0.W
*
****************************************************************************


****************************************************************************
*
*  nkc_toupper: convert character to upper case
*  # G
*
*  A character is converted to upper case. Examples:
*
*  'a'   ->   'A'          (converted)
*  '/'   ->   '/'          (unchanged; there's no upper case version for this)
*  'A'   ->   'A'          (unchanged; already converted)
*
*
*  In:   D0.B           any character
*
*  Out:  D0.B           character converted to upper case
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......    *
*
****************************************************************************


****************************************************************************
*
*  nkc_tolower: convert character to lower case
*  # G
*
*  The counterpart of nkc_toupper(). A character is converted to lower case.
*
*  In:   D0.B           any character
*
*  Out:  D0.B           character converted to lower case
*
*  Reg:  D:01234567   A:01234567   CCR
*          U**.....     **......    *
*
****************************************************************************


****************************************************************************
*                            GLOBAL BSS SECTION                            *
****************************************************************************


*  GEM parameter arrays
*  (needed if using nkc_amulti())

               .if      NKCGEM=1

nkc_contrl:     .ds.w   32                   ; control array
nkc_intin:      .ds.w   32                   ; integer input array
nkc_intout:     .ds.w   32                   ; integer output array
nkc_adrin:      .ds.l   32                   ; address input array
nkc_adrout:     .ds.l   32                   ; address output array
nkc_ptsin:      .ds.l   32                   ; pointers input array
nkc_ptsout:     .ds.l   32                   ; pointers output array

               .endif   ; .if NKCGEM=1


* End Of File

