;
; keyString.s
;
; Translating key codes to strings (MDW)
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sapphire library.
;
; Sapphire is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Sapphire is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Sapphire.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

;----- External dependencies ------------------------------------------------

		GET	sapphire:msgs
		GET	sapphire:keyMap
		GET	sapphire:string

;----- Constants ------------------------------------------------------------

kstr__shift	EQU	(1<<8)
kstr__ctrl	EQU	(1<<9)
kstr__keypad	EQU	(1<<10)
kstr__func	EQU	(1<<11)

;----- Macros ---------------------------------------------------------------

		MACRO
$label		KENTRY	$char,$shift,$ctrl,$keypad,$func
$label		DCB	$char
		DCB	($shift<<0)+($ctrl<<1)+($keypad<<2)+($func<<3)
		MEND

;----- KeyString tables -----------------------------------------------------

		AREA	|Sapphire$$Code|,CODE,READONLY

		; --- &000 - &00F ---

kstr__lower	KENTRY	' ',	0,1,0,0
		KENTRY	'A',	0,1,0,0
		KENTRY	'B',	0,1,0,0
		KENTRY	'C',	0,1,0,0
		KENTRY	'D',	0,1,0,0
		KENTRY	'E',	0,1,0,0
		KENTRY	'F',	0,1,0,0
		KENTRY	'G',	0,1,0,0
		KENTRY	'H',	0,1,0,0
		KENTRY	'I',	0,1,0,0
		KENTRY	'J',	0,1,0,0
		KENTRY	'K',	0,1,0,0
		KENTRY	'L',	0,1,0,0
		KENTRY	'M',	0,1,0,0
		KENTRY	'N',	0,1,0,0
		KENTRY	'O',	0,1,0,0

		; --- &010 - &01F ---

		KENTRY	'P',	0,1,0,0
		KENTRY	'Q',	0,1,0,0
		KENTRY	'R',	0,1,0,0
		KENTRY	'S',	0,1,0,0
		KENTRY	'T',	0,1,0,0
		KENTRY	'U',	0,1,0,0
		KENTRY	'V',	0,1,0,0
		KENTRY	'W',	0,1,0,0
		KENTRY	'X',	0,1,0,0
		KENTRY	'Y',	0,1,0,0
		KENTRY	'Z',	0,1,0,0
		KENTRY	&01B,	0,0,0,0
		KENTRY	&01C,	0,0,0,0
		KENTRY	&01D,	0,0,0,0
		KENTRY	&01E,	0,0,0,0
		KENTRY	&07F,	0,1,0,0

		; --- &100 - &10F ---

kstr__upper	KENTRY	' ',	1,1,0,0
		KENTRY	'A',	1,1,0,0
		KENTRY	'B',	1,1,0,0
		KENTRY	'C',	1,1,0,0
		KENTRY	'D',	1,1,0,0
		KENTRY	'E',	1,1,0,0
		KENTRY	'F',	1,1,0,0
		KENTRY	'G',	1,1,0,0
		KENTRY	'H',	1,1,0,0
		KENTRY	'I',	1,1,0,0
		KENTRY	'J',	1,1,0,0
		KENTRY	'K',	1,1,0,0
		KENTRY	'L',	1,1,0,0
		KENTRY	'M',	1,1,0,0
		KENTRY	'N',	1,1,0,0
		KENTRY	'O',	1,1,0,0

		; --- &110 - &11F ---

		KENTRY	'P',	1,1,0,0
		KENTRY	'Q',	1,1,0,0
		KENTRY	'R',	1,1,0,0
		KENTRY	'S',	1,1,0,0
		KENTRY	'T',	1,1,0,0
		KENTRY	'U',	1,1,0,0
		KENTRY	'V',	1,1,0,0
		KENTRY	'W',	1,1,0,0
		KENTRY	'X',	1,1,0,0
		KENTRY	'Y',	1,1,0,0
		KENTRY	'Z',	1,1,0,0
		KENTRY	&01B,	1,0,0,0
		KENTRY	&01C,	1,0,0,0
		KENTRY	&01D,	1,0,0,0
		KENTRY	&01E,	1,0,0,0
		KENTRY	&07F,	1,1,0,0

		; --- &120 - &12F ---

		KENTRY	' ',	1,0,0,0
		KENTRY	'/',	0,1,1,0
		KENTRY	'*',	0,1,1,0
		KENTRY	'#',	0,1,1,0
		KENTRY	'-',	0,1,1,0
		KENTRY	'+',	0,1,1,0
		KENTRY	&01D,	0,1,1,0
		KENTRY	'.',	0,1,1,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	'[',	0,1,0,0
		KENTRY	'\',	0,1,0,0
		KENTRY	']',	0,1,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	'-',	0,1,0,0

		; --- &130 - &13F ---

		KENTRY	'0',	0,1,0,0
		KENTRY	'1',	0,1,0,0
		KENTRY	'2',	0,1,0,0
		KENTRY	'3',	0,1,0,0
		KENTRY	'4',	0,1,0,0
		KENTRY	'5',	0,1,0,0
		KENTRY	'6',	0,1,0,0
		KENTRY	'7',	0,1,0,0
		KENTRY	'8',	0,1,0,0
		KENTRY	'9',	0,1,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	&01B,	0,1,0,0
		KENTRY	&01C,	0,1,0,0
		KENTRY	&01D,	0,1,0,0
		KENTRY	&01E,	0,1,0,0
		KENTRY	0,	0,0,0,0

		; --- &140 - &14F ---

		KENTRY	0,	0,0,0,0
		KENTRY	'/',	1,1,1,0
		KENTRY	'*',	1,1,1,0
		KENTRY	'#',	1,1,1,0
		KENTRY	'-',	1,1,1,0
		KENTRY	'+',	1,1,1,0
		KENTRY	&01D,	1,1,1,0
		KENTRY	'.',	1,1,1,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	'[',	1,1,0,0
		KENTRY	'\',	1,1,0,0
		KENTRY	']',	1,1,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	'-',	1,1,0,0

		; --- &150 - &15F ---

		KENTRY	'0',	1,1,0,0
		KENTRY	'1',	1,1,0,0
		KENTRY	'2',	1,1,0,0
		KENTRY	'3',	1,1,0,0
		KENTRY	'4',	1,1,0,0
		KENTRY	'5',	1,1,0,0
		KENTRY	'6',	1,1,0,0
		KENTRY	'7',	1,1,0,0
		KENTRY	'8',	1,1,0,0
		KENTRY	'9',	1,1,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	&01B,	1,1,0,0
		KENTRY	&01C,	1,1,0,0
		KENTRY	&01D,	1,1,0,0
		KENTRY	&01E,	1,1,0,0
		KENTRY	0,	0,0,0,0

		; --- &160 - &16F ---

		KENTRY	0,	0,0,0,0
		KENTRY	'/',	0,0,1,0
		KENTRY	'*',	0,0,1,0
		KENTRY	'#',	0,0,1,0
		KENTRY	'-',	0,0,1,0
		KENTRY	'+',	0,0,1,0
		KENTRY	&01D,	0,0,1,0
		KENTRY	'.',	0,0,1,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0

		; --- &170 - &17F ---

		KENTRY	0,	0,0,0,0
		KENTRY	'/',	1,0,1,0
		KENTRY	'*',	1,0,1,0
		KENTRY	'#',	1,0,1,0
		KENTRY	'-',	1,0,1,0
		KENTRY	'+',	1,0,1,0
		KENTRY	&01D,	1,0,1,0
		KENTRY	'.',	1,0,1,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	0,	0,0,0,0
		KENTRY	&07F,	1,0,0,0

		; --- &180 - &18F ---

		KENTRY	0,	0,0,0,1
		KENTRY	1,	0,0,0,1
		KENTRY	2,	0,0,0,1
		KENTRY	3,	0,0,0,1
		KENTRY	4,	0,0,0,1
		KENTRY	5,	0,0,0,1
		KENTRY	6,	0,0,0,1
		KENTRY	7,	0,0,0,1
		KENTRY	8,	0,0,0,1
		KENTRY	9,	0,0,0,1
		KENTRY	13,	0,0,0,1
		KENTRY	14,	0,0,0,1
		KENTRY	15,	0,0,0,1
		KENTRY	16,	0,0,0,1
		KENTRY	17,	0,0,0,1
		KENTRY	18,	0,0,0,1

		; --- &190 - &19F ---

		KENTRY	0,	1,0,0,1
		KENTRY	1,	1,0,0,1
		KENTRY	2,	1,0,0,1
		KENTRY	3,	1,0,0,1
		KENTRY	4,	1,0,0,1
		KENTRY	5,	1,0,0,1
		KENTRY	6,	1,0,0,1
		KENTRY	7,	1,0,0,1
		KENTRY	8,	1,0,0,1
		KENTRY	9,	1,0,0,1
		KENTRY	13,	1,0,0,1
		KENTRY	14,	1,0,0,1
		KENTRY	15,	1,0,0,1
		KENTRY	16,	1,0,0,1
		KENTRY	17,	1,0,0,1
		KENTRY	18,	1,0,0,1

		; --- &1A0 - &1AF ---

		KENTRY	0,	0,1,0,1
		KENTRY	1,	0,1,0,1
		KENTRY	2,	0,1,0,1
		KENTRY	3,	0,1,0,1
		KENTRY	4,	0,1,0,1
		KENTRY	5,	0,1,0,1
		KENTRY	6,	0,1,0,1
		KENTRY	7,	0,1,0,1
		KENTRY	8,	0,1,0,1
		KENTRY	9,	0,1,0,1
		KENTRY	13,	0,1,0,1
		KENTRY	14,	0,1,0,1
		KENTRY	15,	0,1,0,1
		KENTRY	16,	0,1,0,1
		KENTRY	17,	0,1,0,1
		KENTRY	18,	0,1,0,1

		; --- &1B0 - &1BF ---

		KENTRY	0,	1,1,0,1
		KENTRY	1,	1,1,0,1
		KENTRY	2,	1,1,0,1
		KENTRY	3,	1,1,0,1
		KENTRY	4,	1,1,0,1
		KENTRY	5,	1,1,0,1
		KENTRY	6,	1,1,0,1
		KENTRY	7,	1,1,0,1
		KENTRY	8,	1,1,0,1
		KENTRY	9,	1,1,0,1
		KENTRY	13,	1,1,0,1
		KENTRY	14,	1,1,0,1
		KENTRY	15,	1,1,0,1
		KENTRY	16,	1,1,0,1
		KENTRY	17,	1,1,0,1
		KENTRY	18,	1,1,0,1

		; --- &1C0 - &1CF ---

		KENTRY	'0',	0,0,1,0
		KENTRY	'1',	0,0,1,0
		KENTRY	'2',	0,0,1,0
		KENTRY	'3',	0,0,1,0
		KENTRY	'4',	0,0,1,0
		KENTRY	'5',	0,0,1,0
		KENTRY	'6',	0,0,1,0
		KENTRY	'7',	0,0,1,0
		KENTRY	'8',	0,0,1,0
		KENTRY	'9',	0,0,1,0
		KENTRY	10,	0,0,0,1
		KENTRY	11,	0,0,0,1
		KENTRY	12,	0,0,0,1
		KENTRY	19,	0,0,0,1
		KENTRY	20,	0,0,0,1
		KENTRY	21,	0,0,0,1

		; --- &1D0 - &1DF ---

		KENTRY	'0',	1,0,1,0
		KENTRY	'1',	1,0,1,0
		KENTRY	'2',	1,0,1,0
		KENTRY	'3',	1,0,1,0
		KENTRY	'4',	1,0,1,0
		KENTRY	'5',	1,0,1,0
		KENTRY	'6',	1,0,1,0
		KENTRY	'7',	1,0,1,0
		KENTRY	'8',	1,0,1,0
		KENTRY	'9',	1,0,1,0
		KENTRY	10,	1,0,0,1
		KENTRY	11,	1,0,0,1
		KENTRY	12,	1,0,0,1
		KENTRY	19,	1,0,0,1
		KENTRY	20,	1,0,0,1
		KENTRY	21,	1,0,0,1

		; --- &1E0 - &1EF ---

		KENTRY	'0',	0,1,1,0
		KENTRY	'1',	0,1,1,0
		KENTRY	'2',	0,1,1,0
		KENTRY	'3',	0,1,1,0
		KENTRY	'4',	0,1,1,0
		KENTRY	'5',	0,1,1,0
		KENTRY	'6',	0,1,1,0
		KENTRY	'7',	0,1,1,0
		KENTRY	'8',	0,1,1,0
		KENTRY	'9',	0,1,1,0
		KENTRY	10,	0,1,0,1
		KENTRY	11,	0,1,0,1
		KENTRY	12,	0,1,0,1
		KENTRY	19,	0,1,0,1
		KENTRY	20,	0,1,0,1
		KENTRY	21,	0,1,0,1

		; --- &1F0 - &1FF ---

		KENTRY	'0',	1,1,1,0
		KENTRY	'1',	1,1,1,0
		KENTRY	'2',	1,1,1,0
		KENTRY	'3',	1,1,1,0
		KENTRY	'4',	1,1,1,0
		KENTRY	'5',	1,1,1,0
		KENTRY	'6',	1,1,1,0
		KENTRY	'7',	1,1,1,0
		KENTRY	'8',	1,1,1,0
		KENTRY	'9',	1,1,1,0
		KENTRY	10,	1,1,0,1
		KENTRY	11,	1,1,0,1
		KENTRY	12,	1,1,0,1
		KENTRY	19,	1,1,0,1
		KENTRY	20,	1,1,0,1
		KENTRY	21,	1,1,0,1

;----- Main code ------------------------------------------------------------

; --- keyString ---
;
; On entry:	R0 == key number, from Straylight extended keymap
;		R1 == 0 => return full shortcuts (for e.g. writable icons)
;		      1 => return abbreviated shortcuts (for e.g. menus)
;
; On exit:	CS if key number was recognised, and
;		  R0 == pointer to short cut string
;		else CC and
;		  R0 corrupted
;
; Use:		Translates a key number into a string suitable for
;		displaying to a user, and returns a pointer to the
;		translated string.

		EXPORT	keyString
keyString	ROUT

		BIC	R14,R14,#C_flag
		STMFD	R13!,{R1-R5,R14}	;Save some registers

		; --- Find the correct entry in the tables ---

		CMP	R0,#' '			;Is it a control key?
		ADRLT	R2,kstr__lower		;Yes -- point to low table
		ADDLT	R2,R2,R0,LSL #1		;And find the entry
		BLT	%10keyString		;Skip ahead after this

		CMP	R0,#&FF			;Is it in the upper half?
		ADRGT	R2,kstr__upper		;Yes -- point to high table
		BICGT	R0,R0,#&100		;Chop off the top bit
		ADDGT	R2,R2,R0,LSL #1		;And find the entry again
		BGT	%10keyString		;Skip ahead after this

		CMP	R0,#&7F			;Is it a delete?
		ADREQ	R2,kstr__delete		;Yes -- point to delete entry
		LDMNEFD	R13!,{R1-R5,PC}^	;No -- return to caller

		; --- Load the entry from the table ---

10keyString	AND	R14,R2,#3		;Get bottom two bits of R2
		LDR	R2,[R2,-R14]		;Load the word properly
		MOV	R14,R14,LSL #3		;Get the correct shift value
		MOV	R2,R2,LSR R14		;And shift R2 nicely

		TST	R2,#&FF			;Make sure bottom byte non-0
		TSTEQ	R2,#kstr__func		;Or is it a function key?
		LDMEQFD	R13!,{R1-R5,PC}^	;Return to caller if neither

		; --- Find the base key name ---

		TST	R2,#kstr__func		;Is it really a function key?
		BEQ	%20keyString		;No -- skip this bit
		AND	R4,R2,#&ff		;Get the key byte out
		CMP	R4,#12			;Is it F12?
		LDMEQFD	R13!,{R1-R5,PC}^	;Yes -- always ignore F12

		ADR	R3,kstr__fkeys		;Point to key names table
		LDR	R0,[R3,R4,LSL #2]	;Get the correct entry out
		CMP	R0,#0			;Is it a null pointer?
		BLNE	msgs_lookup		;No -- lookup message
		BNE	%30keyString		;And skip ahead nicely

		ADR	R0,kstr__fmsg		;Point to `kstrF:F%i2'
		BL	msgs_lookup		;Lookup the message
		ADD	R1,R11,#50		;Point to scratchpad
		BL	str_subst		;And fill the string in
		B	%30keyString		;Now do the rest of it all

kstr__delete	KENTRY	&7F,	0,0,0,0		;Dummy entry for delete

kstr__fkeys	DCD	kstr__print
		DCD	0,0,0,0,0,0
		DCD	0,0,0,0,0,0
		DCD	kstr__tab
		DCD	kstr__copy
		DCD	kstr__left
		DCD	kstr__right
		DCD	kstr__down
		DCD	kstr__up
		DCD	kstr__insert
		DCD	kstr__pageDown
		DCD	kstr__pageUp

kstr__fmsg	DCB	"kstrF",0
kstr__print	DCB	"kstrPRT",0
kstr__tab	DCB	"kstrTAB",0
kstr__copy	DCB	"kstrCOPY",0
kstr__left	DCB	"kstrLEFT",0
kstr__right	DCB	"kstrRIGHT",0
kstr__down	DCB	"kstrDOWN",0
kstr__up	DCB	"kstrUP",0
kstr__insert	DCB	"kstrINS",0
kstr__pageDown	DCB	"kstrPDN",0
kstr__pageUp	DCB	"kstrPUP",0

		; --- Handle strange keys in lower map ---

20keyString	AND	R4,R2,#&ff		;Get the key byte out
		CMP	R4,#key_Return		;Is it the return code?
		BNE	%21keyString		;No -- skip
		TST	R2,#kstr__keypad	;Is it on the keypad?
		BNE	%22keyString		;Yes -- handle it

21keyString	CMP	R4,#key_Delete		;Is it a delete key?
		BEQ	%23keyString		;Yes -- handle that too
		CMP	R4,#' '			;Is it a space?
		BEQ	%24keyString		;Yes -- handle that too
		SUB	R14,R4,#&1B		;Is it a strange one?
		CMP	R14,#4			;Is it one of the four?
		BLO	%25keyString		;Yes -- handle that

		ADD	R0,R11,#50		;Point to spare bit of buffer
		STRB	R4,[R0,#0]		;Store character in buffer
		MOV	R3,#0			;Terminate the string
		STRB	R3,[R0,#1]		;Store that in buffer too
		B	%30keyString		;Skip to final processing

		; --- Handle various special cases ---

22keyString	BIC	R2,R2,#kstr__keypad	;Yes -- remove keypad flag
		ADR	R0,kstr__enter		;Yes -- point to string
		BL	msgs_lookup		;Translate it as usual
		B	%30			;We've got a base string

kstr__enter	DCB	"kstrENTER",0

23keyString	ADR	R0,kstr__delmsg		;Point to the string
		BL	msgs_lookup		;Translate it as usual
		B	%30			;We've got a base string

kstr__delmsg	DCB	"kstrDEL",0

24keyString	ADR	R0,kstr__space		;Point to the string
		BL	msgs_lookup		;Translate it as usual
		B	%30			;We've got a base string

kstr__space	DCB	"kstrSPC",0

25keyString	ADR	R0,kstr__lowtbl		;Point to the table
		LDR	R0,[R0,R14,LSL #2]	;Load the correct entry
		BL	msgs_lookup		;Translate it as usual
		B	%30			;We've got a base string

kstr__lowtbl	DCD	kstr__escape
		DCD	kstr__backspc
		DCD	kstr__return
		DCD	kstr__home

kstr__escape	DCB	"kstrESC",0
kstr__backspc	DCB	"kstrBSP",0
kstr__return	DCB	"kstrRET",0
kstr__home	DCB	"kstrHOME",0

		; --- Finally, handle modifier strings ---

30keyString	MOV	R5,R0			;Keep pointer to base key
		LDR	R4,[R13,#0]		;Get shortcut style wanted
		MOV	R0,R11			;Point to the scratchpad

		TST	R2,#kstr__shift		;Is shift held down?
		MOVNE	R1,#''			;Yes -- short character
		ADRNE	R3,kstr__shmod		;And long message
		BLNE	%80keyString		;Sort everything out

		TST	R2,#kstr__ctrl		;Is shift held down?
		MOVNE	R1,#'^'			;Yes -- short character
		ADRNE	R3,kstr__ctmod		;And long message
		BLNE	%80keyString		;Sort everything out

		TST	R2,#kstr__keypad	;Is shift held down?
		MOVNE	R1,#'k'			;Yes -- short character
		ADRNE	R3,kstr__kpmod		;And long message
		BLNE	%80keyString		;Sort everything out

		MOV	R1,R5			;Point to base string
		BL	str_cpy			;Copy the last string in
		MOV	R0,R11			;Point to string in buffer
		LDMFD	R13!,{R1-R5,R14}	;Load the registers
		ORRS	PC,R14,#C_flag		;We handled it (eventually)

kstr__shmod	DCB	"kstrSH",0
kstr__ctmod	DCB	"kstrCTL",0
kstr__kpmod	DCB	"kstrKPD",0

		; --- Work out what a modifier should look like ---

80keyString	CMP	R4,#0			;Do we want short mod chars?
		STRNEB	R1,[R0],#1		;Yes -- store char nicely
		MOVNES	PC,R14			;And return to caller
		STMFD	R13!,{R0,R14}		;Save some registers
		MOV	R0,R3			;Point to message tag
		BL	msgs_lookup		;Translate the string
		MOV	R1,R0			;Keep pointer to message
		LDMFD	R13!,{R0}		;Restore a register
		BL	str_cpy			;Attach string to end
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

;----- That's all, folks ----------------------------------------------------

		END
