Compucolor.org – Virtual Media

Listing of file='FIELDS.SRC;01' on disk='vmedia/chip_53-sector.ccvf'


		;FIELD HANDLING ROUTINE WHICH
		;ENABLES BASIC TO CREATE
		;'PROTECTED' & 'UNPROTECTED' FIELDS
		;ON THE SCREEN.
		;
		;AUTHOR. BERNIE RAFFE
		;         HARROW
		;	   ENGLAND
		;FEBRUARY 1981
		;
;
;	DATA AREA USED TO PASS PARAMETERS
;
COUNT:	DB	0	;CHARACTER COUNT
NA:	DS	1	;NUMERIC OR ALPHA;SET BY BASIC
CHARIN:	DS	1	;TEMPORARY CHARACTER STORE
FLDADR:	DS	1	;START OF FIELD;SET BY BASIC

MAXBAS	EQU	32940	;POINTER TO END OF BASIC RAM
VCALL	EQU	33282	;CALL VECTOR

;	SUBROUTINE TO SET UP LINKAGES WHEN RUN FROM FCS
;
START:	PUSH	H	;SAVE SOME REGS
	PUSH	D
	PUSH	PSW
	LXI	H,COUNT-1	;SET END OF BASIC RAM POINTER
	SHLD	MAXBAS	;TO 1 BYTE IN FRONT OF PGM
	MVI	A,(JMP)	;SET UP JUMP TO OUR RTN IN CALL VECT.
	LXI	H,CIINIT ;SO CALL WILL GO TO CIINIT
	STA	VCALL
	SHLD	VCALL+1	;STORE ADDRESS
	LXI	H,1C78H	;ASSUME LO ADDRESS IS IN V879
	LDA	0001H	;CHECK
	CPI	6CH	;IS IT?
	JNZ	STUFF	;YES
	LXI	H,3392H	;NO, CHANGE TO V678 ADDRESS
STUFF:	SHLD	LO+1	;PUT PROPER ADDR. INTO INSTRUCTION
	POP	PSW	;PREPARE TO EXIT
	POP	D
	POP	H
	MVI	B,0	;CLEAR B TO INDIC. NO ERR. TO FCS
	RET		;RETURN TO FCS

;	LO LINKAGE
;		VERSIONIZED BY START ROUTINE

LO:	JMP	0FFFFH	;JUMP TO LO ROUTINE IN MONITOR
			;ACTUAL ADDRESS FILLED IN BY START

	PAGE
CR	EQU	13	;CARRIAGE RETURN
DELINE	EQU	04	;DELETE LINE KEY
INSERT	EQU	05	;INSERT KEY
DELETE	EQU	127	;DELETE KEY
HT	EQU	9	;HORIZONTAL TAB
RIGHT	EQU	25	;MOVE CURSOR RIGHT
LEFT	EQU	26	;MOVE CURSOR LEFT
SPACE	EQU	32	;SPACE CHRACTER
SLASH	EQU	47
INPCRT	EQU	81C5H	;JUMP VECTOR #31
KBDFL	EQU	81DFH	;HOLD NO. OF JUMP
KBRDY	EQU	81FFH	;KEYBOARD READY FLAG
			;VECTOR FOR KEYBOARD

NUMMIN	EQU	45	;NUMERIC MINIMUM
NUMMAX	EQU	58	;NUMERIC MAXIMUM
ALPHMIN	EQU	32	;ALPHANUMERIC MINIMUM
ALPHMAX	EQU	91	;ALPHANUMERIC MAXIMUM



		;THIS CHARACTER INPUT INITIALISATION
		;ROUTINE SETS UP THE PARAMETERS
		;NECESSARY FOR THE 'CHRINT' AND
		;'CI' ROUTINES.

CIINIT:	PUSH	PSW		;SAVE REGISTERS REQ'STD BY BASIC
	PUSH	H
	LDA	KBDFL		;SAVE BASIC'S JUMP VECTOR #
	PUSH	PSW
	MVI	A,31		;SETUP NEW JUMP VECTOR #
	STA	KBDFL
	MVI	A,0C3H		;PLACE 'JMP' AT VECTOR LOCATION
	STA	INPCRT
	LXI	H,CHRINT	;GET ADDRESS OF 'CHRINT' ROUTN
	SHLD	INPCRT+1	;PLACE ADDRESS AFTER 'JMP'
	XRA	A
	MOV	B,A
	STA	KBRDY
	STA	CHARIN
	STA	COUNT	;RESET CHARACTER COUNT
	JMP	GETNXT

	;CHRINT       - THIS CHARACTER INPUT ROUTINE IS
			;VECTORED TO FROM THE KEYBOARD INPUT
			;ROUTINE THROUGH THE JUMP VECTOR (#31).
			;THE CHARACTER FROM THE KEYBOARD
			;ROUTINE IS IN REGISTER 'E'.

CHRINT:	LXI	H,CHARIN	;GET ADDRESS OF TEMP
			;CHARACTER STORAGE.
	XRA	A	;CLEAR ACCUMULATOR
	CMP	M	;TEST FOR 'CHARIN' FOR ZERO
	JNZ	CFIN	;IF NOT ZERO THEN IGNORE INPUT
	MOV	A,E	;GET CHAR FROM 'E'
	ANI	127	;STRIP UPPER BIT FOR ASCII
	MOV	M,A	;PUT CHAR IN 'CHARIN'

CFIN:	EI		;ENABLE INTERRUPTS
	RET		;RETURN FROM INTERRUPT


	;CI  - 	THIS CHARACTER INPUT ROUTINE GETS A CHARACTER
	;	FROM THE TEMPORARY STORAGE LOCATION 'CHARIN'
	;	CLEARS THE KEYBOARD READY FLAG
	;	AND RETURNS WITH THE CHARACTER IN 'A'.
	;	IF THERE IS NO CHARACTER IN 'CHARIN',
	;	THEN 'CI' WILL HANG AND WAIT FOR ONE.

CI:	EI	;ENABLE INTERRUPTS
CI10:	LDA	CHARIN	;GET CHARACTER
	CPI	0	;HAVE A CHAR?
	JZ	CI10	;IF NOT,HANG FOR ONE
	PUSH	PSW	;GOT ONE,NOW SAVE IT
	XRA	A
	STA	KBRDY	;CLEAR KEYBOARD READY FLAG
	STA	CHARIN	;CLEAR TEMP STORAGE FOR NEXT CHAR
	POP	PSW	;RESTORE CHAR
	RET

GETNXT:	CALL	CI	;GET NEXT KEYBOARD CHARACTER
	MOV	D,A	;STORE IN 'D'
	CPI	LEFT	;BACKSPACE?
	JZ	LEFTKEY	;JUMP TO BACKSPACE ROUTINE
	CPI	HT	;TAB?
	JZ	MAINFIN	;YES-JUMP TO END ROUTINE
	CPI	CR	;RETURN?
	JZ	MAINFIN	;YES - JUMP TO END ROUTINE
	CPI	RIGHT	;CURSOR RIGHT
	JZ	RGHTKEY	;PUT IT ON SCREEN
	CPI	INSERT	;INSERT A NEW CHARACTER
	JZ	INS10
	CPI	DELETE	;DELETE A CHARACTER
	JZ	DEL10
	CPI	DELINE	;DELETE LINE CHAR
	JZ	DLIN10
	MOV	A,B	;FIELD FULL?
	CMP	E
	JZ	GETNXT	;YES SO IGNORE
	LDA	NA	;NUMERIC OR ALPHANUMERIC FIELD
	CPI	65	;A=ALPHA
	JZ	ALPHA

NUMERIC:MOV	A,D	;NUMERIC VALIDATION
	CPI	NUMMAX	;RANGE TEST-MAXIMUM VALUE
	JNC	GETNXT	;IGNORE
	CPI	NUMMIN	;           MINIMUM VALUE
	JC	GETNXT	;IGNORE
	CPI	SLASH	;= '/'
	JZ	GETNXT	;IGNORE
	JMP	KEYOK	;ACCEPT KEY

ALPHA:	MOV	A,D	;ALPHANUMERIC VALIDATION
	CPI	ALPHMAX ;RANGE TEST - MAXIMUM VALUE
	JNC	GETNXT	;IGNORE
	CPI	ALPHMIN	;             MINIMUM VALUE
	JC	GETNXT	;IGNORE

KEYOK:	CALL	LO	;PUT IT ON SCREEN
	INR	B	;INCREMENT FINAL COUNT
	JMP	GETNXT	;GET NEXT CHAR

MAINFIN:	MVI	A,3	;PUT CURSOR OFF SCREEN
	CALL	LO
	MVI	A,64
	CALL	LO
	XRA	A
	CALL	LO
	CALL	CNT10	;SETUP FIELD COUNT FOR BASIC
	STA	COUNT
	MOV	E,D	;PUT LAST CHAR IN 'E'
	XRA	A
	MOV	D,A
	POP	PSW	;RSTORE BASIC JUMP VECTOR #
	STA	KBDFL
	POP	H	;RESTORE USED REGISTERS
	POP	PSW
	RET

LEFTKEY:	MOV	A,B	;BACKSPACE SUBROUTINE
	CPI	0	;IF ON FIRST CHAR
	JZ	GETNXT	;THEN IGNORE
	DCR	B	;DECREMENT CHAR COUNT
	MVI	A,LEFT	;BACKSPACE CURSOR
	CALL	LO
	JMP	GETNXT

RGHTKEY:	MOV	A,B	;RIGHT CURSOR FUNCTION
	CMP	E	;CHECK IF FIELD FULL
	MOV A,D		;RESTORE CHARACTER
	JNZ	KEYOK	;NO SO O.K.
	JMP	GETNXT	;IGNORE


	;INSERT A CHARACTER ROUTINE....
	;REGISTER USAGE:-
	;  A=NO OF CHARS ALREADY IN FIELD
	;  B=POSITION WITHIN FIELD
	;  C=NO OF CHARS TO SHUFFLE
	;  E=MAX NO OF CHARS IN FIELD

INS10:	CALL	CNT10	;DETERMINE SIZE OF FIELD RTN
	CPI	0	;IGNORE IF NO CHARS IN FIELD
	JZ	GETNXT
	PUSH	D
	LHLD	FLDADR	;SET UP HL
	DCX	H
	DCX	H
	SUB	B	;CALCULATE NO OF CHARS
	JM	INS55	;RETURN IF PAST LAST CHAR (NAUGHTY!)
	JZ	INS55
	MOV	C,A	;PUT IN C
	ADD	B	;RESTORE A
	CMP	E	;IS FIELD FULL
	JNZ	INS20	;NO
	DCX	H	;YES - SO ARRANGE FOR LAST CHAR
	DCX	H	;TO DISAPPEAR FROM FACE OF EARTH
	DCR	C
	JZ	INS55	;IGNORE IF SITTING ON LAST CHAR
INS20:	MVI	D,0	;POSITION HL TO LAST CHAR
	MOV	E,A
	DAD	D
	DAD	D
	LXI	D,0FFFCH ;TO SUBTRACT 4 LATER ON

INS30:	MOV	A,M	;GET CHAR FROM FIELD
	INX	H
	INX	H
	MOV	M,A	;AND SHIFT UP

INS40:	DCR	C	;ANY MORE?
	JZ	INS50	;NO
	DAD	D	;YES POINT TO PREVIOUS CHAR
	JMP	INS30

INS50:	DCX	H	;PUT A SPACE AT CURSOR POSITION
	DCX	H
	MVI	M,SPACE

INS55:	POP	D
	JMP	GETNXT	;RETURN

	;DELETE A CHARACTER ROUTINE.....
	;REGISTER USAGE:-
	; A=NO OF CHARACTERS ALREADY IN FIELD (AFTER CNT10 CALL)
	; B=POSITION WITHIN FIELD
	; C=NO OF CHARACTERS TO SHUFFLE

DEL10:	CALL	CNT10	;DETERMINE SIZE OF FIELD
	CPI	0	;IGNORE IF NOTHING IN IT
	JZ	GETNXT
	PUSH	D
	LHLD	FLDADR	;SETUP HL
	INX	H
	INX	H
	SUB	B	;CALCULATE NO OF CHARS
	MOV	C,A	;TO SHUFFLE & PUT IN C

DEL20:	MOV	E,B	;POSITION HL TO FIRST CHAR TO SHUFFLE
	MVI	D,0
	DAD	D
	DAD	D
	LXI	D,4	;TO ADD 4 LATER ON

DEL25:	DCR	C
	JM	DEL55	;RETURN IF PAST LAST CHAR
	JNZ	DEL30	;SPECIAL TEST FOR LAST CHAR
	DCX	H
	DCX	H
	JMP	DEL53

DEL30:	MOV	A,M	;GET CHAR FROM FIELD
	DCX	H
	DCX	H
	MOV	M,A	;AND SHIFT UP

DEL40:	DCR	C	;ANY MORE?
	JZ	DEL50	;NO
	DAD	D	;YES - POINT TO NEXT ONE
	JMP	DEL30

DEL50:	INX	H	;PUT A SPACE AT LAST
	INX	H	;CHARACTER POSITION
DEL53:	MVI	M,SPACE

DEL55:	POP	D
	JMP	GETNXT	;RETURN


	;ROUTINE TO DELETE ALL THE REMAINING
	;CHARACTERS IN THE FIELD

DLIN10:	CALL	CNT10	;GET NO OF CHARS IN FIELD
	PUSH	D
	LHLD	FLDADR	;START OF FIELD
	SUB	B	;CALCULATE NO.OF CHARS TO DELETE
	JM	DLIN40	;IGNORE IF AT END
	JZ	DLIN40
	MOV	C,A

DLIN20:	MVI	D,0	;SET H&L TO 1ST CHAR TO DELETE
	MOV	E,B
	DAD	D
	DAD	D
	MVI	A,SPACE

DLIN30:	MOV	M,A	;DELETE CHARS
	DCR	C	;ANY MORE?
	JZ	DLIN40	;NO
	INX	H
	INX	H
	JMP	DLIN30

DLIN40:	POP	D
	JMP	GETNXT

	;ROUTINE TO DETERMINE THE EXACT LENGTH
	;OF A FIELD ON THE SCREEN.
	;FINAL COUNT IS PUT IN 'A'.

CNT10:	PUSH	B	;SAVE IT
	LHLD	FLDADR	;START OF FIELD
	DCX	H
	DCX	H
	MVI	B,0

CNT20:	MVI	C,0	;C WILL CONTAIN NO OF SPACES
			;PAST THE END OF THE FIELD
CNT30:	MOV	A,B	;B CONTAINS THE FIELD COUNT
	CMP	E	;ARE WE AT MAXIMUM
	JZ	CNT40	;YES - FINISHED
	INX	H	;GET TO NEXT CHAR
	INX	H
	INR	B	;ADD 1 TO COUNT
	MOV	A,M
	CPI	SPACE	;IS IT A SPACE
	JNZ	CNT20	;NOPE
	INR	C	;INCREMENT SPACE COUNT
	JMP	CNT30	;BACK & SHUFFLE NEXT ONE

CNT40:	MOV	A,B	;CALCULATE EXACT COUNT
	SUB	C
	POP	B	;RESTORE USED REGISTER
	RET



	END	START