;	Keyboard Handler Module for MicroEMACS 3.10e
;
;	Recognises Archimedes keypresses, and generates a distinct
;	input buffer character (or set thereof) for each possible
;	combination.
;

;	History
;	-------
;
;	Original	Set up as a relocatable module, installed from
;			Emacs, in TTinit().
;
;	14/04/91	Converted to relocatable code, linked with Emacs

; Register declarations

R0	RN	0
R1	RN	1
R2	RN	2
R3	RN	3
R4	RN	4
R5	RN	5
R6	RN	6
R7	RN	7
R8	RN	8
R9	RN	9
R10	RN	10
R11	RN	11
R12	RN	12
R13	RN	13
R14	RN	14
R15	RN	15

r0	RN	0
r1	RN	1
r2	RN	2
r3	RN	3
r4	RN	4
r5	RN	5
r6	RN	6
r7	RN	7
r8	RN	8
r9	RN	9
r10	RN	10
r11	RN	11
r12	RN	12
r13	RN	13
r14	RN	14
r15	RN	15

wr	RN	12
sp	RN	13
lr	RN	14
pc	RN	15

; PC flags

Overflow	*	&10000000
Carry		*	&20000000
Zero		*	&40000000
Negative	*	&80000000
USR_Mode	*	&00000003

; SWI numbers

OS_CallAVector	*	&00020034

; Vector numbers

InsV		*	&14
EventV		*	&10

; Event numbers

KeyPress	*	&0B

; Keyboard Codes

LShift		*	&4C
RShift		*	&58
LCtrl		*	&3B
RCtrl		*	&61
LAlt		*	&5E
RAlt		*	&60

Delete		*	&34
Home		*	&20
PageDown	*	&36
PageUp		*	&21
Backspace	*	&1E
Return		*	&47
Enter		*	&67

; New buffer codes for non-standard keys

NewDelete	*	&C0
NewHome		*	&C1
NewPageDown	*	&C2
NewPageUp	*	&C3
NewBackspace	*	&C4
NewReturn	*	&C5
NewEnter	*	&C6

Alt_Prefix	*	&7F

; Service call numbers

	AREA	|Asm$$code|, CODE, READONLY

	EXPORT	Event_Handler
	EXPORT	Insert_Handler

; This is our event handler for the keypress event. It keeps track of the
; last key pressed, and also the shift status of the various "shifting"
; keys (ie Shift, Ctrl and Alt).

Event_Handler
	CMP	R0,#KeyPress		; Is it our event?
	MOVNES	pc,lr			; If not, quit

	STR	R2,Vector_Key		; Save the last key pressed

	CMP	R2,#LShift		; Check for Shift keys
	CMPNE	R2,#RShift
	STREQ	R1,Vector_Shift		; Save Shift status

	CMP	R2,#LCtrl		; Check for Control keys
	CMPNE	R2,#RCtrl
	STREQ	R1,Vector_Ctrl		; Save Control status

	CMP	R2,#LAlt		; Check for ALT keys
	CMPNE	R2,#RAlt
	STREQ	R1,Vector_Alt		; Save ALT status

	MOVS	pc,lr

; This is our insert vector handler. It checks every key code entering
; the keyboard buffer. If it is "ambiguous" (eg Home or Delete), or it is
; Alt-ed, then a substitute, unique, buffer code sequence is inserted in
; its place.

Insert_Handler
	STMFD	sp!,{R1-R2,lr}

	CMP	R1,#0			; Only the keyboard buffer
	BNE	Ins_1

	LDR	R2,Vector_Recursive	; Don't run recursively
	CMP	R2,#0
	BNE	Ins_1

;	If ALT is pressed, and it is not modifying a keypad key,
;	then insert a prefix byte (Alt_Prefix) into the input stream.

	LDR	R1,Vector_Alt
	LDR	R2,Vector_Key

	CMP	R1,#1		; Check for an ALT
	BNE	%F1

;	Do not process ALT if the international keyboard is in action
	LDR	R1,Vector_International
	CMP	R1,#1
	BEQ	%F1

	MOV	R1,#1			; Don't intercept the recursive call,
	STR	R1,Vector_Recursive	; or we'll get in an infinite loop!

	MOV	R9,pc			; Go into USR mode
	ORR	R1,R9,#USR_Mode
	TEQP	R1,#0
	MOVNV	R0,R0

	STMFD	sp!,{R0,R2,R9,lr}	; Insert the prefix into the buffer
	MOV	R0,#Alt_Prefix
	MOV	R1,#0
	MOV	R9,#InsV
	SWI	OS_CallAVector
	LDMFD	sp!,{R0,R2,R9,lr}

	TEQP	R9,#0			; Return to previous mode
	MOVNV	R0,R0

	MOV	R1,#0			; We have finished recursing
	STR	R1,Vector_Recursive

;	Now start checking for specific keys

1	CMP	R2,#PageDown		; Page Down
	BNE	%F2
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewPageDown
	B	Ins_1

2	CMP	R2,#PageUp		; Page Up
	BNE	%F3
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewPageUp
	B	Ins_1

3	CMP	R2,#Delete		; Delete
	BNE	%F4
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewDelete
	B	Ins_1

4	CMP	R2,#Home		; Home
	BNE	%F5
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewHome
	B	Ins_1

5	CMP	R2,#Backspace		; Backspace
	BNE	%F6
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewBackspace
	B	Ins_1

6	CMP	R2,#Return		; Return
	BNE	%F7
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewReturn
	B	Ins_1

7	CMP	R2,#Enter		; Enter (numeric keypad)
	BNE	%F8
	LDR	R1,Vector_Shift		; Put Shift/Control status
	LDR	R0,Vector_Ctrl		; in bits 4 and 5 of the new
	ADD	R1,R1,R0,LSL #1		; code, respectively. This is
	MOV	R1,R1,LSL #4		; the 'standard' for codes > &80
	ADD	R0,R1,#NewEnter
	B	Ins_1

8
Ins_1
	LDMFD	sp!,{R1-R2,pc}^

; The following are handler status variables. 
; The variables are set up based on r12. The appropriate value of r12
; must be supplied to the vector code to ensure correct working. This is
; handled in C.Archimedes, where the r12 value passed to OS_Claim is set
; to point to a suitable area of memory.

			^	0,r12
Vector_Recursive	#	4	; Module has been entered recursively
Vector_Key		#	4	; Last key pressed
Vector_Shift		#	4	; Shift key status
Vector_Ctrl		#	4	; Control key status
Vector_Alt		#	4	; ALT key status
Vector_International	#	4	; International Keboard present

    END
