; > adfs::TimsWini.arm.SourceDisc.!IKHG.Source.IntKeyBody

; ************************************************************
; ***    C h a n g e   L i s t  (better late than never!)  ***
; ************************************************************

; Date       Description
; ----       -----------
; 17-Feb-88  Modified Norway/Denmark, Sweden/Finland
; 19-Feb-88  Modified InkeyTran so that INKEY(-95) returns state of new key
;             next to left shift key on international keyboards
; 19-Feb-88  Added code to select configured keyboard on initialisation
; 16-Mar-88  Conditional versioning between 1.20 and 2.00
;            Started modify AltCharTable mechanism
; 13-Apr-88  Fixed pound/backtick problem
; 14-Apr-88  Attempt to fix initialisation problem on A500s
; 28-Apr-88  Changed version string to "Int'l Keyboard"
; 20-Jul-88  Allow kbids from 1-31
; 24-Oct-88  Modify for International Keyboard Handler Generator
; 18-Jul-89  Started to modify to allow Alt+key to give dead accents
; 31-Jul-89  Changed 'Dir', 'Hdr' etc to 'IKHG$Dir', 'IKHG$Hdr' etc
; 18-Oct-89  Corrected entry for shift-2 in TopBitSetTable1
; 02-Feb-90  Added entries to IDD table, and changed Esperanto to 1100

        GET     <IKHG$Hdr>.ListOpts
        GET     <IKHG$Hdr>.Macros
        GET     <IKHG$Hdr>.System
        GET     <IKHG$Hdr>.ModHand
        GET     <IKHG$Hdr>.Services
        GET     <IKHG$Hdr>.Proc
        GET     <IKHG$Hdr>.NewErrors
        GET     <IKHG$Dir>.Chars.Latin1

        LEADR   Module_LoadAddr

TAB     *       9
LF      *       10
FF      *       12
CR      *       13

        [ Arthur120
KeyWorkSpace *  &640                    ; Yugh

         ^       &07, R11               ; Yughgh!
ResetState      # 1
        ]

OsbyteSetCountry * &46
OsbyteSetAlphKey * &47
OsbyteFindOsbyteVars * &A6
OsbyteTABch     * &DB
OsbyteKeyBase   * &EE
OsbyteKeyOpt    * &FE

Country_UK      * 1
Country_Master  * 2
Country_Compact * 3
Country_Italy   * 4
Country_Spain   * 5
Country_France  * 6
Country_Germany * 7
Country_Portugal * 8
Country_Esperanto * 9
Country_Greece  * 10
Country_Sweden  * 11
Country_Finland * 12
Country_Denmark * 14
Country_Norway  * 15
Country_Iceland * 16
Country_Canada1 * 17
Country_Canada2 * 18
Country_Canada  * 19
Country_Turkey  * 20
Country_Arabic  * 21
Country_Ireland * 22
Country_HongKong * 23
Country_Russia  * 24
Country_Russia2 * 25
                    
Country_ISO1    * 80
Country_ISO2    * 81
Country_ISO3    * 82
Country_ISO4    * 83
Country_ISO5    * 84
Country_ISO6    * 85
Country_ISO7    * 86
Country_ISO8    * 87
Country_ISO9    * 88

Alphabet_Bfont  * 100
Alphabet_Latin1 * 101
Alphabet_Latin2 * 102
Alphabet_Latin3 * 103
Alphabet_Latin4 * 104
Alphabet_Cyrillic * 105
Alphabet_Arabic * 106
Alphabet_Greek  * 107
Alphabet_Hebrew * 108
Alphabet_Latin5 * 109

Alphabet_Cyrillic2 * 120

Keyboard_A500   * 0
Keyboard_A1     * 1
Keyboard_A1Limit * 32 ; Lowest one we don't recognise
Keyboard_None   * &FF

        GBLL    BleedinDaveBell
BleedinDaveBell SETL    {TRUE}

        [ BleedinDaveBell
Alphabet_Default * Alphabet_Latin1
        |
Alphabet_Default * Alphabet_Bfont
        ]

        MACRO
        IKT     $A, $B, $C, $D, $E, $F, $G, $H
        IKT2    $A
        IKT2    $B
        IKT2    $C
        IKT2    $D
        IKT2    $E
        IKT2    $F
        IKT2    $G
        IKT2    $H
        MEND

        MACRO
        IKT2    $TE
        LCLA    T
T       SETA    $TE
        [ (T :AND: &FF00) = 0
T       SETA    T :OR: &FF00
        ]
        [ (T :AND: &FF0000) = 0
T       SETA    T :OR: &FF0000
        ]
        [ (T :AND: &FF000000) = 0
T       SETA    T :OR: &FF000000
        ]
        &       T
        MEND

        MACRO
        BodgeKeyHandler $cond
        [ Arthur120
        Push    "R11,R12", $cond
        MOV$cond R11, #KeyWorkSpace
        MOV$cond R12, #&FE                       ; not expected, so will
        STR$cond.B R12, ResetState               ; cause a reset (we hope)
        Pull    "R11,R12", $cond
        ]
        MEND

        MACRO
$label  DoTopBit        $No
$label  ROUT
        ADRL    R3, TopBitSetTable$No-((K$No.TopBitSet-SpecialList$No):SHL:4)
        B       DoTopBitCommon
        MEND

        MACRO
        DoAccent $No, $AName
PendingAltCode$No
        ADR     R6, KeyReturn
        STRB    R3, [R6, #1]
PendingAltSpecial$No
        ADRL    R4, AccentTable_$AName
        B       PendingAltSpecialCommon
        MEND

; UK Keyboard keys

K1Escape        * &00
K1Function1     * &01
K1Function2     * &02
K1Function3     * &03
K1Function4     * &04
K1Function5     * &05
K1Function6     * &06
K1Function7     * &07
K1Function8     * &08
K1Function9     * &09
K1Function10    * &0A
K1Function11    * &0B
K1Function12    * &0C
K1Print         * &0D
K1ScrollLock    * &0E
K1Break         * &0F
K1BackTick      * &10
K1Digit1        * &11
K1Digit2        * &12
K1Digit3        * &13
K1Digit4        * &14
K1Digit5        * &15
K1Digit6        * &16
K1Digit7        * &17
K1Digit8        * &18
K1Digit9        * &19
K1Digit0        * &1A
K1Minus         * &1B
K1Equals        * &1C
K1Pound         * &1D
K1BackSpace     * &1E
K1Insert        * &1F
K1Home          * &20
K1PageUp        * &21
K1NumLock       * &22
K1NumPadSlash   * &23
K1NumPadStar    * &24
K1NumPadHash    * &25
K1Tab           * &26
K1LetterQ       * &27
K1LetterW       * &28
K1LetterE       * &29
K1LetterR       * &2A
K1LetterT       * &2B
K1LetterY       * &2C
K1LetterU       * &2D
K1LetterI       * &2E
K1LetterO       * &2F
K1LetterP       * &30
K1OpenSquare    * &31
K1CloseSquare   * &32
K1BackSlash     * &33
K1Delete        * &34
K1Copy          * &35
K1PageDown      * &36
K1NumPad7       * &37
K1NumPad8       * &38
K1NumPad9       * &39
K1NumPadMinus   * &3A
K1CtrlLeft      * &3B
K1LetterA       * &3C
K1LetterS       * &3D
K1LetterD       * &3E
K1LetterF       * &3F
K1LetterG       * &40
K1LetterH       * &41
K1LetterJ       * &42
K1LetterK       * &43
K1LetterL       * &44
K1SemiColon     * &45
K1Tick          * &46
K1Return        * &47
K1NumPad4       * &48
K1NumPad5       * &49
K1NumPad6       * &4A
K1NumPadPlus    * &4B
K1ShiftLeft     * &4C
K1NotFitted     * &4D
K1LetterZ       * &4E
K1LetterX       * &4F
K1LetterC       * &50
K1LetterV       * &51
K1LetterB       * &52
K1LetterN       * &53
K1LetterM       * &54
K1Comma         * &55
K1Dot           * &56
K1Slash         * &57
K1ShiftRight    * &58
K1CursorUp      * &59
K1NumPad1       * &5A
K1NumPad2       * &5B
K1NumPad3       * &5C
K1CapsLock      * &5D
K1AltLeft       * &5E
K1Space         * &5F
K1AltRight      * &60
K1CtrlRight     * &61
K1CursorLeft    * &62
K1CursorDown    * &63
K1CursorRight   * &64
K1NumPad0       * &65
K1NumPadDot     * &66
K1NumPadEnter   * &67
K1LeftMouse     * &70
K1CentreMouse   * &71
K1RightMouse    * &72

; Bits in pending ALT flag

KBAlt_AccentMask  * 31

KBAlt_AltDown        * (1 :SHL: 5)
KBAlt_DigitsPresent  * (1 :SHL: 6)
KBAlt_SelectKeyboard * (1 :SHL: 7)      ; set after CTRL-ALT-F12

KVPendingAltSpecial  * &20 ; offset from structure to new entry

; Module workspace allocation

        ^ 0, R12

NewKeyStructWP  # &24   ; key structure header, must be first thing
OldKeyHandler   # 4
CurrentKeyboard # 4     ; current keyboard setting
CurrentKeyAlphabet # 4  ; alphabet for current keyboard
OsbyteVars      # 4
AltDigitValue   # 4

        ^ :INDEX: CurrentKeyboard, R0

R0CurrentKeyboard # 4
R0CurrentKeyAlphabet # 4
R0OsbyteVars    # 4
R0AltDigitValue # 4     ; value of ALT+digits so far

A1Key_WorkspaceSize * :INDEX: @

; User key workspace allocation

        ^ 0, R12

ShiftCount      # 1
CtrlCount       # 1
AltCount        # 1
MyMouseButtons  # 1     ; bit0=R, bit1=C, bit2=L
KeyReturn       # 2     ; length byte (1), value byte
KeyNULReturn    # 3     ; length byte (2), NUL, value byte
NowtReturn      * KeyNULReturn +1 ; zero length list

; **************** Module code starts here **********************

Module_BaseAddr

        DCD     0
        DCD     A1Key_Init    -Module_BaseAddr
        DCD     A1Key_Die     -Module_BaseAddr
        DCD     A1Key_Service -Module_BaseAddr
        DCD     A1Key_Title   -Module_BaseAddr
        DCD     A1Key_HelpStr -Module_BaseAddr
        DCD     A1Key_HC_Table-Module_BaseAddr

A1Key_Title
        =       "InternationalKeyboard", 0

A1Key_HelpStr
        =       "Int'l Keyboard"
        =       TAB
        =       "0.25 (02 Feb 1990) (Generated version)"
        [ Arthur120
        =       " (Arthur 1.20 version)"
        ]
        =       0
        ALIGN

; *****************************************************************************

A1Key_HC_Table * Module_BaseAddr

; *****************************************************************************
;
;       A1Key_Init - Initialisation routine
;

A1Key_Init ENTRY
        LDR     R2, [R12]               ; have we got workspace yet ?
        TEQ     R2, #0
        BNE     %FT05

        MOV     R0, #ModHandReason_Claim
        MOV     R3, #A1Key_WorkspaceSize
        SWI     XOS_Module
        EXIT    VS

; R2 -> workspace

        STR     R2, [R12]               ; save address in my workspace pointer,
                                        ; so Tutu can free it for me when I die
05
        MOV     R12, R2

        MOV     R0, #OsbyteSetAlphKey
        MOV     R1, #128                ; set default keyboard
        SWI     XOS_Byte

        BL      ClaimVec
        EXIT    VS

        [ :LNOT: Arthur120
        MOV     R1, #I_bit
        MOV     R2, #0
06
        MOV     R0, #1                  ; read keyboard id
        SWI     XOS_InstallKeyHandler
        CMP     R0, #Keyboard_None      ; if no keyboard id
        BNE     %FT08

        TST     R1, PC                  ; if I bit set
        MOVNE   R2, R1                  ; then set R2 to toggle
        TEQNEP  R2, PC
        B       %BT06

08
        TEQP    R2, PC                  ; restore old I_bit
        CMP     R0, #Keyboard_A500      ; if not zero (A500) (C=1 if EQ)
        CMPNE   R0, #Keyboard_A1Limit   ; and less than 32
        BCC     %FT09                   ; then install ourselves
        CLRV                            ; else exit, but with V clear, so
        EXIT                            ; someone can plug A1 kb in after
09
        ]
        BL      SetUpHandler
        [ Arthur120
        EXIT    VC
        BL      ReleaseVec              ; if on 1.2, must release ByteV
        SETV                            ; before exiting VS
        ]
        EXIT

        [ Arthur120
ClaimVec ENTRY
10
        BL      ReleaseVec              ; release until failed
        BVC     %BT10

        BL      SetUpKeyStructure       ; put appropriate structure header
                                        ; in workspace
        MOV     R0, #ByteV
        ADR     R1, OsbyteHandler
        MOV     R2, R12
        SWI     XOS_Claim
        EXIT
        ]

; *****************************************************************************
;
;       A1Key_Die - Die entry
;

A1Key_Die ENTRY
        LDR     R12, [R12]
        PHPSEI                          ; disable interrupts round this bit
        Push    R14                     ; (R14 contains previous I_bit status)

        MOV     R0, #0                  ; read current handler address
        SWI     XOS_InstallKeyHandler
        TEQ     R0, R12
        BNE     %FT10                   ; key handler isn't us, so exit

        LDR     R0, OldKeyHandler
        SWI     XOS_InstallKeyHandler
        BodgeKeyHandler

10
        Pull    R14
        PLP                             ; restore old IRQ state
        [ Arthur120
        BL      ReleaseVec
        ]
        CLRV
        EXIT

        [ Arthur120
ReleaseVec ENTRY
        MOV     R0, #ByteV
        ADR     R1, OsbyteHandler
        MOV     R2, R12
        SWI     XOS_Release
        EXIT
        ]

; *****************************************************************************
;
;       A1Key_Service - Main entry point for services
;
; in:   R1 = service reason code
;       R2 = parameter
;
; out:  R1 = 0 if we claimed it
;       R2 preserved
;

A1Key_Service ENTRY
        LDR     R12, [R12]                      ; point to workspace

        TEQ     R1, #Service_Reset
        BNE     %FT10
        Push    "R0-R6"
        BL      ClaimVec
        Pull    "R0-R6"
        EXIT
10
        TEQ     R1, #Service_KeyHandler         ; is it our service ?
        [ Arthur120
        EXIT    NE
        |
        BNE     TryInter
        ]
        CMP     R2, #Keyboard_A500      ; if not zero (A500) (C=1 if EQ)
        CMPNE   R2, #Keyboard_A1Limit   ; and less than 32
        BLCC    SetUpHandler            ; then install ourselves
        EXIT

        [ :LNOT: Arthur120
TryInter
        TEQ     R1, #Service_International      ; check for internat. service
        TEQEQ   R2, #Inter_Keyboard             ; and new keyboard reason
        EXIT    NE

        STR     R3, CurrentKeyboard
        Push    "R0-R2"
        BL      SetUpKeyStructure
        Pull    "R0-R2"
        EXIT
        ]

; *****************************************************************************

SetUpHandler ROUT
        Push    "R0,R1,R14"
        MOV     R1, PC
        AND     R1, R1, #3 :OR: I_bit
        EOR     R1, R1, #SVC_mode :OR: I_bit    ; R1 = EOR of mode and SVC_mode
        TEQP    R1, PC                          ; and I_bit (disable IRQs)
        MOVNV   R0, R0

        Push    R14
        MOV     R0, R12                         ; point handler into workspace
        SWI     XOS_InstallKeyHandler
        BVS     %FT20
        TEQ     R0, R12                         ; are we already the handler?
        STRNE   R0, OldKeyHandler               ; if not, then save old
        BodgeKeyHandler
20
        Pull    R14

        TEQP    R1, PC                          ; go back to previous mode
        MOVNV   R0, R0

        Pull    R0, VC                          ; if no error, restore R0
        ADD     R13, R13, #4                    ; and junk R1, else junk R0
        Pull    R1, VS                          ; and restore R1
        MOVVC   R1, #0                          ; if no error, claim service
        Pull    PC

        LTORG

        [ Arthur120

; *****************************************************************************
;
;       OsbyteHandler - Routine to handle OSBYTE
;

OsbyteHandler ROUT
        TEQ     R0, #OsbyteSetCountry
        BEQ     SetCountryHandler
        TEQ     R0, #OsbyteSetAlphKey
        MOVNE   PC, R14                 ; pass it on ASAP if not ours
SetAlphKeyHandler
        TST     R1, #&80                ; NZ => setting keyboard, not alphabet
        TEQNE   R1, #&FF                ; &FF => reading keyboard
        MOVEQ   PC, R14                 ; ignore those

; else we can drop thru to ...

SetCountryHandler ROUT
        TEQ     R1, #127                ; if just reading
        MOVEQ   PC, R14                 ; then ignore, else call old handler

        Push    "R12"                   ; save wp
        Push    PC                      ; push address of %FT10
        MOV     PC, R14
        &       0
10
        TEQ     R1, #0                  ; was it accepted ?
        Pull    "R12,PC", EQ            ; no, then ignore
        Push    "R0-R2"
        LDR     R12, [R13, #12]         ; reload workspace pointer

        BL      SetUpKeyStructure       ; copy appropriate structure header
                                        ; into workspace
        Pull    "R0-R2,R12,PC"

        ]

; *****************************************************************************
;
;       SetUpKeyStructure - Put appropriate structure header in workspace
;
; in:   R12 -> workspace
;       SVC mode
;
; out:  R0-R2 can be corrupted
;

        [ :LNOT: Arthur120
ClaimVec
        ]
SetUpKeyStructure ENTRY "R3,R4"
        MOV     R0, #OsbyteFindOsbyteVars
        MOV     R1, #0
        MOV     R2, #&FF
        SWI     XOS_Byte
        ORR     R1, R1, R2, LSL #8
        STR     R1, OsbyteVars          ; set up osbyte vars address

        MOV     R0, #OsbyteSetAlphKey
        MOV     R1, #&FF                ; read keyboard number
        SWI     XOS_Byte
        STR     R1, CurrentKeyboard

        Push    R1
        MOV     R3, R1
        MOV     R1, #Service_International
        MOV     R2, #Inter_CNoToANo
        MOV     R4, #Alphabet_Default
        SWI     XOS_ServiceCall
        STR     R4, CurrentKeyAlphabet  ; alphabet associated with this kb
        Pull    R1

        CMP     R1, #(KeyStructureTableEnd-KeyStructureTable) :SHR: 2
                                        ; if out of range
        MOVCS   R1, #0                  ; then use default

        ADRL    R0, KeyStructureTable
        LDR     R1, [R0, R1, LSL #2]    ; load offset to correct structure
        ADD     R0, R0, R1              ; R0 -> appropriate structure

        PHPSEI                          ; disable IRQs, put status in R14

        SUB     R1, R0, R12             ; offset from workspace to structure
        MOV     R2, #&20
10
        LDR     R3, [R0, R2]
        TEQ     R2, #&04                ; is it KeyTranSize ?
        ADDNE   R3, R3, R1              ; if not then relative offset
        STR     R3, [R12, R2]
        SUBS    R2, R2, #4
        BCS     %BT10

        PLP                             ; restore IRQ state

        EXIT

; Now the code to handle it

; Initialise keyboard table handler
;
; in:   R0 -> KeyStruct
;       R1 = keyboard id
;       R5 = KeyBdStatus
;       R7 = PendingAltType
;       R12 -> my workspace
;
; out:  R5 = new KeyBdStatus
;       R7 = new PendingAltType

KeyStructInit ROUT
        MOV     R0, #0                  ; no shift or ctrl keys down
        STRB    R0, ShiftCount
        STRB    R0, CtrlCount
        STRB    R0, AltCount
        STRB    R0, MyMouseButtons
        STRB    R0, KeyNULReturn+1      ; NUL for NUL char return
        MOV     R0, #1                  ; string length for single key return
        STRB    R0, KeyReturn+0
        MOV     R0, #2                  ; length for NUL char return
        STRB    R0, KeyNULReturn+0

        BIC     R5, R5, #(KBStat_ShiftEngaged :OR: KBStat_CtrlEngaged :OR: KBStat_PendingAlt)
        MOV     R7, #0                  ; 0 pending ALT
        MOV     PC, R14

ProcessKShift ROUT
        ADR     R0, ShiftCount
        MOV     R2, #KBStat_ShiftEngaged
ProcessShiftOrCtrl
        TEQ     R1, #0                  ; R1=1 => down, R1=0 => up
        LDRB    R3, [R0]
        ADDNE   R3, R3, #1              ; if down then increment (still NE)
        SUBEQS  R3, R3, #1              ; if up then decrement and setup Z
        STRB    R3, [R0]
        ORRNE   R5, R5, R2              ; one or more shift/ctrl keys down
        BICEQ   R5, R5, R2              ; zero shift/ctrl keys down
        MOV     PC, R14

ProcessKCtrl ROUT
        ADR     R0, CtrlCount
        MOV     R2, #KBStat_CtrlEngaged
        B       ProcessShiftOrCtrl

ProcessKRight ROUT
        MOV     R2, #1
ProcessMouseButton
        TEQ     R1, #0
        LDRB    R0, MyMouseButtons
        ORRNE   R0, R0, R2              ; button going down
        BICEQ   R0, R0, R2              ; button going up
        STRB    R0, MyMouseButtons
        MOV     PC, R3                  ; call his routine and exit

ProcessKCentre ROUT
        MOV     R2, #2
        B       ProcessMouseButton

ProcessKLeft ROUT
        MOV     R2, #4
        B       ProcessMouseButton

ProcessKAlt ROUT
        LDRB    R3, AltCount
        TEQ     R3, #0                  ; if no ALTs down so far, then must be

        STREQ   R3, R0AltDigitValue     ; going down, so zero cumulative digits

        TEQ     R1, #0                  ; 0 => up, 1 => down
        ADDNE   R3, R3, #1              ; if down then increment
        SUBEQS  R3, R3, #1              ; if up then decrement and setup Z
        STRB    R3, AltCount
        BNE     %FT10

        TST     R7, #KBAlt_DigitsPresent ; if no digits present
        BEQ     %FT05                   ; then skip

        LDR     R0, R0AltDigitValue     ; load digits
        TST     R7, #KBAlt_SelectKeyboard ; selecting keyboard (CTRL-ALT-F12)?
        ADREQ   R6, KeyNULReturn        ; no, then return NUL char
        STREQB  R0, [R6, #2]
        BEQ     %FT05

        ADR     R1, IDDTable
03
        LDMIA   R1!, {R2, R3}           ; load IDD number, country number
        CMP     R2, #-1                 ; end of table ?
        BEQ     %FT05                   ; then not recognised, so do nothing
        TEQ     R2, R0                  ; found match ?
        BNE     %BT03

        ORR     R1, R3, #&80
        Push    R14
        BL      SelectKeyboard
        Pull    R14

05
        BICS    R7, R7, #(KBAlt_AltDown :OR: KBAlt_DigitsPresent :OR: KBAlt_SelectKeyboard)
        B       %FT15
10
        ORRS    R7, R7, #KBAlt_AltDown
15
        ORRNE   R5, R5, #KBStat_PendingAlt ; if NZ then still need bit set
        BICEQ   R5, R5, #KBStat_PendingAlt ; else clear bit
        MOV     PC, R14

IDDTable
        &       044, Country_UK
        &       001, Country_UK
        &       039, Country_Italy
        &       034, Country_Spain
        &       033, Country_France
        &       049, Country_Germany
        &       351, Country_Portugal
        &      1100, Country_Esperanto
        &       030, Country_Greece
        &       046, Country_Sweden
        &       358, Country_Finland
        &       045, Country_Denmark
        &       047, Country_Norway
        &       354, Country_Iceland
        &       000, Country_Ireland
        &       852, Country_HongKong
        &       007, Country_Russia

        &      1001, Country_ISO1
        &      1002, Country_ISO2
        &      1003, Country_ISO3
        &      1004, Country_ISO4
        &      1005, Country_ISO5
        &      1006, Country_ISO6
        &      1007, Country_ISO7
        &      1008, Country_ISO8
        &      1009, Country_ISO9
        &       -1, -1

ProcessKCaps ROUT
        TEQ     R1, #2                          ; is it first press ?
        MOVNE   PC, R14                         ; don't auto-repeat

        TST     R5, #KBStat_ShiftEngaged        ; if shift down
        BICNE   R5, R5, #KBStat_NoCapsLock      ; then force CAPS on
        ORRNE   R5, R5, #KBStat_ShiftEnable     ; and SHIFT CAPS state
        EOREQ   R5, R5, #KBStat_NoCapsLock      ; else toggle caps lock state
        BICEQ   R5, R5, #KBStat_ShiftEnable     ; and cancel shift enable

        MOV     PC, R14

ProcessKTab ROUT
        LDR     R1, R0OsbyteVars
        LDRB    R1, [R1, #OsbyteTABch]          ; TAB key code
        TST     R1, #&80                        ; top bit set ?
        BEQ     ReturnOneCharAlt                ; no, don't shift or ctrl it
        TST     R5, #KBStat_ShiftEngaged
        EORNE   R1, R1, #&10                    ; modify for shift
        TST     R5, #KBStat_CtrlEngaged
        EORNE   R1, R1, #&20                    ; modify for ctrl
ReturnOneCharAlt
        ADR     R6, KeyReturn                   ; pass pointer back to MOS
        STRB    R1, [R6, #1]                    ; having poked byte in
ReturnCharAlt
        TST     R5, #KBStat_PendingAlt          ; if no pending alt
        TSTNE   R7, #KBAlt_AccentMask           ; or its not an accent
        MOVEQ   PC, R14                         ; then return this
        LDR     R1, [R0, #KVPendingAltSpecial]  ; else call the special entry
        ADD     PC, R0, R1

ProcessKNum ROUT
        TEQ     R1, #2                          ; is it first press ?
        EOREQ   R5, R5, #KBStat_NoNumLock       ; yes, then toggle num lock
        MOV     PC, R14                         ; (don't auto-repeat)

ProcessKScroll ROUT
        TEQ     R1, #2                          ; is it first press ?
        EOREQ   R5, R5, #KBStat_ScrollLock      ; yes, then toggle scroll lock
        MOV     PC, R14                         ; (don't auto-repeat)

ProcessKBreak ROUT
        ADD     PC, R3, #4                      ; offset for break routine

ProcessK1Pad ROUT
        ADR     R3, PadK1NumTran-(SpecialList1Pad-SpecialList1) ; on
        TST     R7, #KBAlt_AltDown
        BNE     AltKeyPad

        BICS    R7, R7, #KBAlt_AccentMask       ; cancel accents
        BICEQ   R5, R5, #KBStat_PendingAlt

        LDR     R1, R0OsbyteVars
        ADR     R2, PadK1CurTran-(SpecialList1Pad-SpecialList1) ; off
        TST     R5, #KBStat_NoNumLock           ; test num lock
        MOVNE   R3, R2                          ; numlock off -> use R2
        LDRB    R0, [R3, R4]                    ; get table entry
        TEQ     R0, #&FF                        ; dummy key ?
        MOVEQ   PC, R14                         ; then exit

        LDRB    R2, [R1, #OsbyteKeyBase]        ; add on numeric key base
        SUB     R0, R0, #"0"
        ADD     R0, R0, R2

        LDRB    R2, [R1, #OsbyteKeyOpt]         ; zero => ctrl/shift modifies
        TEQ     R2, #0
        BNE     %FT10                           ; [don't modify]

        TST     R0, #&80                        ; top bit set ?
        BEQ     %FT10                           ; no, then don't modify

        TST     R5, #KBStat_ShiftEngaged
        EORNE   R0, R0, #&10                    ; modify for shift
        TST     R5, #KBStat_CtrlEngaged
        EORNE   R0, R0, #&20                    ; modify for ctrl
10
ReturnOneChar
        ADR     R6, KeyReturn                   ; pass pointer back to MOS
        STRB    R0, [R6, #1]                    ; having poked byte in
        MOV     PC, R14

PadK1NumTran
        =       "/*#789-456+123",13,"0."
PadK1CurTran
        =       "/*#",&1E,&8F,&9F,"-",&8C,&FF,&8D,"+",&8B,&8E,&9E,13,&CD,&7F
        ALIGN

AltKeyPad ROUT
        LDRB    R3, [R3, R4]                    ; get value from PadK1NumTran
        SUB     R3, R3, #"0"
        CMP     R3, #10                         ; if not in range 0-9
        BICCS   R7, R7, #(KBAlt_DigitsPresent :OR: KBAlt_SelectKeyboard)
                                                ; then get rid of digs + select
        ORRCC   R7, R7, #KBAlt_DigitsPresent    ; else indicate we have digits
        MOVCS   R2, #0                          ; if no digits
        STRCS   R2, R0AltDigitValue             ; then zero digits
        MOVCS   PC, R14                         ; and exit

        LDR     R2, R0AltDigitValue
        MOV     R1, #10
        MLA     R3, R2, R1, R3                  ; digits = digits*10+new digit
        STR     R3, R0AltDigitValue
        MOV     PC, R14

ReturnNULCharAlt
        ADR     R6, KeyNULReturn                ; store char
        STRB    R1, [R6, #2]
        B       ReturnCharAlt

ReturnNULChar
        ADR     R6, KeyNULReturn
        STRB    R0, [R6, #2]
        MOV     PC, R14

DoTopBitCommon ROUT
        TST     R5, #KBStat_ShiftEngaged
        ADDNE   R3, R3, #2
        TST     R5, #KBStat_CtrlEngaged
        ADDNE   R3, R3, #4
        TST     R7, #KBAlt_AltDown
        ADDNE   R3, R3, #8
        LDRB    R1, [R3, R4, LSL #4]!
        LDRB    R6, [R3, #1]

; 0 => non-alpha, 1 => alpha, 2 => dead accent, 3 => nowt

        MOVS    R6, R6, LSL #31         ; put bit 1 into C, bit 0 into N
        BCS     %FT20
        BPL     ReturnOneOrNULAlt       ; not alpha, so skip

        TST     R5, #KBStat_ShiftEnable
        EORNE   R3, R3, #2
        TSTEQ   R5, #KBStat_NoCapsLock
        ORREQ   R3, R3, #2
        LDRB    R1, [R3]
ReturnOneOrNULAlt
        CMP     R1, #0                  ; if zero (C=1 if equal)
        CMPNE   R1, #&80                ; or if >= &80
        BCS     ReturnNULCharAlt        ; then return NUL char
        B       ReturnOneCharAlt

; come here for dead accent (N=0) or for nowt (N=1)

20
        ADR     R6, NowtReturn          ; point to zero length list
        BICPL   R7, R7, #KBAlt_AccentMask ; if accent, then clear accents
        ORRPL   R7, R7, R1              ; put in new accent
        ORRPL   R5, R5, #KBStat_PendingAlt ; and indicate it
        MOV     PC, R14

; *****************************************************************************
;
;       PendingAltCode1 - Process Alt+Char or Accent+Char
;
; in:   R0 -> key structure
;       R2 = internal key number for char
;       R3 = character which would be returned if not an ALT, if not special
;       R4 -> accent table for this keyboard's alphabet
;       R5 = keyboard status
;       R6 -> list that would be returned if not an ALT
;       R7 = pending alt type
;
; out:  R6 -> returned key list
;

PendingAltSpecialCommon ROUT
        TST     R7, #KBAlt_AccentMask   ; is it due to dead accent ?
        BEQ     AlternateChar           ; no, then must be Alt down

; called because of accented char

        AND     R2, R7, #KBAlt_AccentMask ; get just the accent
        LDR     R2, [R4, R2, LSL #2]    ; offset to appropriate accent
        ADD     R4, R4, R2              ; R4 now points to accent list

        BICS    R7, R7, #KBAlt_AccentMask ; no more accents
        BICEQ   R5, R5, #KBStat_PendingAlt ; if no more then zero status bit

        LDRB    R2, [R6]                ; load length of current returned list
        LDRB    R2, [R6, R2]            ; R2 = unaccented character
10
        LDRB    R3, [R4], #2            ; R3 = source char
        TEQ     R3, #0                  ; zero => end of list
        MOVEQ   PC, R14                 ; so return char unmodified
        TEQ     R3, R2                  ; if not the char we want
        BNE     %BT10                   ; then loop

        LDRB    R0, [R4, #-1]           ; else load translated char
ReturnOneOrNUL
        CMP     R0, #0                  ; if 0 then return 0 0 (C=1)
        CMPNE   R0, #&80                ; elif -ve return 0 char
        BCS     ReturnNULChar
        B       ReturnOneChar           ; else return 0 char

        
AlternateChar ROUT
        MOV     R2, R2, LSL #2                  ; multiply index by 4

        TST     R5, #KBStat_CtrlEngaged
        ADDNE   R2, R2, #2

        TST     R5, #KBStat_ShiftEngaged
        ADDNE   R2, R2, #1

        TEQ     R2, #(K1Function1 :SHL: 2) +2   ; is it CTRL-ALT-F1 ?
        BEQ     SelectUKKeyboard                ; then select UK keyboard
        TEQ     R2, #(K1Function2 :SHL: 2) +2   ; is it CTRL-ALT-F2 ?
        BEQ     SelectConfiguredKeyboard        ; then select configured kb
        TEQ     R2, #(K1Function12 :SHL: 2) +2  ; is it CTRL-ALT-F12
        ORREQ   R7, R7, #KBAlt_SelectKeyboard   ; then set IDD selection flag

        B       ReturnNowt                      ; if not one of these
                                                ; then return nowt, since all
                                                ; real ALTs are special

SelectConfiguredKeyboard ROUT
        MOV     R1, #&80                        ; select default keyboard
        B       SelectKeyboard
SelectUKKeyboard
        MOV     R1, #&81                        ; select UK keyboard
SelectKeyboard
        MOV     R3, PC
        AND     R3, R3, #3
        EOR     R3, R3, #SVC_mode
        TEQP    R3, PC                          ; select SVC mode
        MOVNV   R0, R0                          ; wait for it to happen

        Push    R14
        MOV     R0, #OsbyteSetAlphKey
        SWI     XOS_Byte
        Pull    R14

        TEQP    R3, PC                          ; reenter previous mode
        MOVNV   R0, R0                          ; wait for it to happen
ReturnNowt
        ADR     R6, NowtReturn                  ; return nowt
        MOV     PC, R14

        OutputAccentTable_Latin1

; *****************************************************************************
;
;       Reverse table lookup for INKEY(-ve)
;

InkeyTran
        IKT     &FF, &FF, &FF, &5B, &49, &48, &64, &33          ; 80-87
        IKT     &09, &08, &06, &05, &03, &02, &01, &00          ; 88-8F
        IKT     &FF, &FF, &FF, &5C, &5A, &65, &35, &57          ; 90-97
        IKT     &56, &55, &54, &52, &51, &5F, &4E, &26          ; 98-9F
        IKT     &FF, &4D, &1C, &FF, &24, &25, &34, &32          ; A0-A7
        IKT     &45, &44, &53, &41, &40, &50, &3D, &FF          ; A8-AF
        IKT     &46, &36, &22, &66, &FF, &23, &47, &45          ; B0-B7
        IKT     &12, &43, &42, &2C, &3F, &4F, &3C, &5D          ; B8-BF
        IKT     &21, &20, &1F, &67, &3A, &4B, &59, &31          ; C0-C7
        IKT     &30, &2F, &2D, &16, &2A, &3E, &12, &11          ; C8-CF
        IKT     &1E, &1D, &10, &0F, &39, &38, &63, &1B          ; D0-D7
        IKT     &1A, &19, &2E, &17, &2B, &29, &28, &0D          ; D8-DF
        IKT     &0E, &0A, &0C, &0B, &37, &4A, &62, &16          ; E0-E7
        IKT     &1B, &07, &18, &04, &15, &14, &13, &27          ; E8-EF
        IKT     &FF, &FF, &FF, &FF, &72, &71, &70, &60          ; F0-F7
        IKT     &61, &58, &5E, &3B, &4C, &5E60, &3B61, &4C58    ; F8-FF

; *****************************************************************************

KeyStruct1 ROUT
        &       KeyTran1-KeyStruct1
        &       (KeyTran1End-KeyTran1) :SHR: 2
        &       InkeyTran-KeyStruct1
        &       ShiftingKeyList-KeyStruct1
        &       SpecialList1-KeyStruct1
        &       SpecialCodeTable1-KeyStruct1
        &       KeyStructInit-KeyStruct1
        &       PendingAltCode1-KeyStruct1
        &       PendingAltSpecial1-KeyStruct1

ShiftingKeyList
        =       ShiftingKeyListEnd-ShiftingKeyList-1
        =       K1ShiftLeft, K1ShiftRight, K1CtrlLeft, K1CtrlRight
        =       K1AltLeft, K1AltRight
        =       K1RightMouse, K1CentreMouse, K1LeftMouse, K1Break
ShiftingKeyListEnd
        ALIGN

SpecialList1
        =       SpecialList1End-SpecialList1-1
SpecialList1Pad
        =       K1NumPadSlash, K1NumPadStar, K1NumPadHash
        =       K1NumPad7, K1NumPad8, K1NumPad9, K1NumPadMinus
        =       K1NumPad4, K1NumPad5, K1NumPad6, K1NumPadPlus
        =       K1NumPad1, K1NumPad2, K1NumPad3, K1NumPadEnter
        =       K1NumPad0, K1NumPadDot

        =       K1ShiftLeft, K1ShiftRight, K1CtrlLeft, K1CtrlRight
        =       K1AltLeft, K1AltRight
        =       K1RightMouse, K1CentreMouse, K1LeftMouse
        =       K1CapsLock, K1Tab
        =       K1NumLock, K1ScrollLock, K1Break, K1Pound
        =       K1BackTick
K1TopBitSet
        =       K1Digit1, K1Digit2, K1Digit3, K1Digit9
        =       K1Digit0, K1Minus, K1LetterR, K1LetterY
        =       K1LetterS, K1LetterZ, K1LetterX, K1LetterC
        =       K1LetterM, K1Comma, K1Dot, K1Space
SpecialList1End
        ALIGN

SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1
        &       ProcessK1Pad-SpecialCodeTable1

        &       ProcessKShift-SpecialCodeTable1
        &       ProcessKShift-SpecialCodeTable1
        &       ProcessKCtrl-SpecialCodeTable1
        &       ProcessKCtrl-SpecialCodeTable1
        &       ProcessKAlt-SpecialCodeTable1
        &       ProcessKAlt-SpecialCodeTable1
        &       ProcessKRight-SpecialCodeTable1
        &       ProcessKCentre-SpecialCodeTable1
        &       ProcessKLeft-SpecialCodeTable1
        &       ProcessKCaps-SpecialCodeTable1
        &       ProcessKTab-SpecialCodeTable1
        &       ProcessKNum-SpecialCodeTable1
        &       ProcessKScroll-SpecialCodeTable1
        &       ProcessKBreak-SpecialCodeTable1
        &       ProcessK1Pound-SpecialCodeTable1
        &       ProcessK1BackTick-SpecialCodeTable1

        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1
        &       ProcessK1TopBitSet-SpecialCodeTable1

; Now the code to handle it

ProcessK1BackTick ROUT
        TST     R7, #KBAlt_AltDown              ; if alt down
        BNE     %FT10                           ; then do other things
        TST     R5, #KBStat_ShiftEngaged        ; if shift down
        MOVNE   R1, #"~"                        ; then ~
        BNE     ReturnOneCharAlt
        Push    R14
        BL      TestForBfont                    ; else check for Bfont
        Pull    R14
        MOVEQ   R1, #&BB                        ; BFont back tick
        MOVNE   R1, #&60                        ; anything else back tick
        B       ReturnOneOrNULAlt

10
        TST     R5, #KBStat_CtrlEngaged         ; if C-A or C-S-A then nothing
        BNE     ReturnNowt
        MOV     R1, #&AC                        ; if A or S-A return NOT symbol
        B       ReturnNULCharAlt

ProcessK1Pound ROUT
        Push    R14
        BL      TestForBfont
        Pull    R14
        BNE     %FT10
        TST     R5, #KBStat_ShiftEngaged
        MOVEQ   R1, #&60                        ; Bfont pound
        MOVNE   R1, #&9E                        ; Bfont currency
        B       ReturnNULCharAlt
10
        TST     R5, #KBStat_ShiftEngaged
        MOVEQ   R1, #&A3                        ; anything else 'pound'
        MOVNE   R1, #&A4                        ; anything else currency
        B       ReturnNULCharAlt


; *****************************************************************************
;
;       TestForBfont - Check if keyboard corresponds to a Bfont font
;
; in:   IRQ mode
;       R0 -> key structure (= module workspace)
;
; out:  Z => Bfont, NZ => anything else
;

TestForBfont ROUT
        Push    R14
        LDR     R14, R0CurrentKeyAlphabet
        TEQ     R14, #Alphabet_Bfont
        Pull    PC

; *****************************************************************************

; Keyboard table for UK, Master, Compact

KeyTran1 ROUT

; Column 0

00
        =       &1B, &1B, &1B, &1B      ; Escape
        =       &81, &91, &A1, &B1      ; f1
        =       &82, &92, &A2, &B2      ; f2
        =       &83, &93, &A3, &B3      ; f3
        =       &84, &94, &A4, &B4      ; f4
        =       &85, &95, &A5, &B5      ; f5
        =       &86, &96, &A6, &B6      ; f6
        =       &87, &97, &A7, &B7      ; f7
        =       &88, &98, &A8, &B8      ; f8
        =       &89, &99, &A9, &B9      ; f9
        =       &CA, &DA, &EA, &FA      ; f10 (or is it f0)
        =       &CB, &DB, &EB, &FB      ; f11
        =       &CC, &DC, &EC, &FC      ; f12
        =       &80, &90, &A0, &B0      ; Print
        &       -1                      ; Scroll Lock
        &       -1                      ; Break

; Column 1

10
        &       -1                      ; back tick and ~
        &       -1                      ; 1 (Alt -> superscript 1)
        &       -1                      ; 2 (Alt -> superscript 2)
        &       -1                      ; 3 (Alt -> superscript 3)
        =       "4$4$"                  ; 4
        =       "5%5%"                  ; 5
        =       "6^", &1E, &1E          ; 6
        =       "7&7&"                  ; 7
        =       "8*8*"                  ; 8
        &       -1                      ; 9 (Alt -> +/-)
        &       -1                      ; 0 (Alt -> superscript 0 / ring)
        &       -1                      ; - (Alt -> soft hyphen)
        =       "=+=+"                  ; =
        &       -1                      ; pound and currency ()
        =       &08, &08, &08, &08      ; backspace
        =       &CD, &DD, &ED, &FD      ; Insert

; Column 2

20
        =       &1E, &1E, &1E, &1E      ; Home
        =       &9F, &8F, &BF, &AF      ; Page Up
        &       -1                      ; Num Lock
        &       -1                      ; pad /
        &       -1                      ; pad *
        &       -1                      ; pad #
        &       -1                      ; Tab
        =       "qQ", &11, &11          ; Q
        =       "wW", &17, &17          ; W
        =       "eE", &05, &05          ; E
        &       -1                      ; R (Alt -> registered)
        =       "tT", &14, &14          ; T
        &       -1                      ; Y (Alt -> yen)
        =       "uU", &15, &15          ; U
        =       "iI", &09, &09          ; I
        =       "oO", &0F, &0F          ; O

; Column 3

30
        =       "pP", &10, &10          ; P
        =       "[{", &1B, &1B          ; [
        =       "]}", &1D, &1D          ; ]
        =       "\|", &1C, &1C          ; \
        =       &7F, &7F, &7F, &7F      ; Delete
        =       &8B, &9B, &AB, &BB      ; Copy
        =       &9E, &8E, &BE, &AE      ; Page Down
        &       -1                      ; pad 7
        &       -1                      ; pad 8
        &       -1                      ; pad 9
        &       -1                      ; pad -
        &       -1                      ; Ctrl (left)
        =       "aA", &01, &01          ; A
        &       -1                      ; S (Alt -> paragraph)
        =       "dD", &04, &04          ; D
        =       "fF", &06, &06          ; F

; Column 4

40
        =       "gG", &07, &07          ; G
        =       "hH", &08, &08          ; H
        =       "jJ", &0A, &0A          ; J
        =       "kK", &0B, &0B          ; K
        =       "lL", &0C, &0C          ; L
        =       ";:;:"                  ; ;
        =       "'""'"""                ; '
        =       &0D, &0D, &0D, &0D      ; Return
        &       -1                      ; pad 4
        &       -1                      ; pad 5
        &       -1                      ; pad 6
        &       -1                      ; pad +
        &       -1                      ; Shift (left)
        &       -1                      ; not fitted
        &       -1                      ; Z (Alt -> <<)
        &       -1                      ; X (Alt -> >>)

; Column 5

50
        &       -1                      ; C (Alt -> cent, Shift-Alt -> copyrt)
        =       "vV", &16, &16          ; V
        =       "bB", &02, &02          ; B
        =       "nN", &0E, &0E          ; N
        &       -1                      ; M (Alt -> mu)
        &       -1                      ; , (Alt -> multiply)
        &       -1                      ; . (Alt -> divide)
        =       "/?/?"                  ; /
        &       -1                      ; Shift (right)
        =       &8F, &9F, &AF, &BF      ; cursor up
        &       -1                      ; pad 1
        &       -1                      ; pad 2
        &       -1                      ; pad 3
        &       -1                      ; Caps Lock
        &       -1                      ; Alt (left)
        &       -1                      ; space bar (Alt -> non-break-space)

; Column 6

60
        &       -1                      ; Alt (right)
        &       -1                      ; Ctrl (right)
        =       &8C, &9C, &AC, &BC      ; cursor left
        =       &8E, &9E, &AE, &BE      ; cursor down
        =       &8D, &9D, &AD, &BD      ; cursor right

        [ Arthur120
        &       -1                      ; pad 0         ; don't comment out
        &       -1                      ; pad .         ; cos of MOS bug
        &       -1                      ; pad Enter
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted
        &       -1                      ; not fitted

; Column 7

70
        &       -1                      ; mouse left
        &       -1                      ; mouse centre
        &       -1                      ; mouse right
        ]

        ASSERT  %10-%00 = 16*4
        ASSERT  %20-%10 = 16*4
        ASSERT  %30-%20 = 16*4
        ASSERT  %40-%30 = 16*4
        ASSERT  %50-%40 = 16*4
        ASSERT  %60-%50 = 16*4
KeyTran1End

; *****************************************************************************

TopBitSetTable1
        =       "1", 0, "!", 0, "1", 0, "!", 0          ; 1
        =       &B9, 0, &B9, 0, &00, 3, &00, 3          ; -> &B9
        =       "2", 0, "@", 0, &00, 0, &00, 0          ; 2
        =       &B2, 0, &B2, 0, &00, 3, &00, 3          ; -> &B2
        =       "3", 0, "#", 0, "3", 0, "#", 0          ; 3
        =       &B3, 0, &B3, 0, &00, 3, &00, 3          ; -> &B3
        =       "9", 0, "(", 0, "9", 0, "(", 0          ; 9
        =       &B1, 0, &B1, 0, &00, 3, &00, 3          ; -> &B1
        =       "0", 0, ")", 0, "0", 0, ")", 0          ; 0
        =       &B0, 0, &B0, 0, &00, 3, &00, 3          ; -> &B0
        =       "-", 0, "_", 0, &1F, 0, &1F, 0          ; -
        =       &AD, 0, &AD, 0, &00, 3, &00, 3          ; -> &AD
        =       "r", 1, "R", 1, &12, 0, &12, 0          ; R
        =       &AE, 0, &AE, 0, &00, 3, &00, 3          ; -> &AE
        =       "y", 1, "Y", 1, &19, 0, &19, 0          ; Y
        =       &A5, 0, &A5, 0, &00, 3, &00, 3          ; -> &A5
        =       "s", 1, "S", 1, &13, 0, &13, 0          ; S
        =       &A7, 0, &A7, 0, &00, 3, &00, 3          ; -> &A7
        =       "z", 1, "Z", 1, &1A, 0, &1A, 0          ; Z
        =       &AB, 0, &AB, 0, &00, 3, &00, 3          ; -> &AB
        =       "x", 1, "X", 1, &18, 0, &18, 0          ; X
        =       &BB, 0, &BB, 0, &00, 3, &00, 3          ; -> &BB
        =       "c", 1, "C", 1, &03, 0, &03, 0          ; C
        =       &A2, 0, &A9, 0, &00, 3, &00, 3          ; -> &A2, &A9
        =       "m", 1, "M", 1, &0D, 0, &0D, 0          ; M
        =       &B5, 0, &B5, 0, &00, 3, &00, 3          ; -> &B5
        =       ",", 0, "<", 0, ",", 0, "<", 0          ; ,
        =       &D7, 0, &D7, 0, &00, 3, &00, 3          ; -> &D7
        =       ".", 0, ">", 0, ".", 0, ">", 0          ; .
        =       &F7, 0, &F7, 0, &00, 3, &00, 3          ; -> &F7
        =       " ", 0, " ", 0, " ", 0, " ", 0          ; space
        =       &A0, 0, &A0, 0, &00, 3, &00, 3          ; -> &A0

ProcessK1TopBitSet      DoTopBit        1

        DoAccent 1, Latin1

        LNK     <IKHG$Dir>.GenSource
