; Doug's Programming Language  -- DPL, Version 2.22
; Copyright (c) 1988 Douglas S. Cody, All rights reserved.
;------------------------------------------------
; EDITS -- EDIT A STRING OF CHARACTERS THE SAME WAY THE
;	   DOS COMMAND LINE EDITS IT'S COMMAND LINE.
;
; Entry conditions:
;	AX points to the target string
; Exit conditions:
;	AL holds the last character typed
;	No other registers modified
;	Target string modified
;
SUBPGM	EDITS
;
F1KEY		EQU	3B00H		; F1 KEY - SAVE THIS CHARACTER
F2KEY		EQU	3C00H		; F2 KEY - DELETE TO END OF LINE
F3KEY		EQU	3D00H		; F3 KEY - SAVE ENTIRE LINE
F4KEY		EQU	3E00H		; F4 KEY - DELETE ENTIRE LINE
F5KEY		EQU	3F00H		; F5 KEY - DELETE TO END OF LINE
F7KEY		EQU	4100H		; F7 KEY - DELETE ENTIRE LINE
INSERT		EQU	5200H		; INSERT KEY
DELETE		EQU	5300H		; DELETE KEY
HOME		EQU	4700H		; HOME KEY
ENDKEY		EQU	4F00H		; END KEY
LEFTKEY		EQU	4B00H		; LEFT ARROW KEY
RIGHTKEY	EQU	4D00H		; RIGHT ARROW KEY
;
;-----------------------==============================-------------------------
;-----------------------====< START OF EXECUTION >====-------------------------
;-----------------------==============================-------------------------
;
BEGIN	EDITS
	EXTRN	_STREND:NEAR
	PUSH	ES		; SAVE EVERYTHING...
;
	PUSH	DS		; SEGMENT ARE SET TO BE THE SAME
	POP	ES
;
	PUSH	BP
	PUSH	SI
	PUSH	DX
	PUSH	CX
	PUSH	BX		; + 2 SAVE THE STRING LENGTH
	PUSH	AX		; + 0 SAVE THE ORIGINAL POINTER
;
	MOV	BP,SP		; BP - X WILL HOLD WORKING LOCALS
;
	MOV	SI,AX		; SI = START OF BUFFER
	ADD	BX,AX		; AX = END OF BUFFER POINTER
	PUSH	BX		; BP - 2 END OF LINE
	MOV	BYTE PTR [BX],0	; SET A DEFAULT TERMINATOR
	CALL	_STREND		; MOVE OUT TO THE END
        CMP	SI,BX		; IS SI = BX (END OF LINE?)
	JZ	EDS_PRE_000	; YES, DON'T NULL IT OUT
	CALL	NULL_TO_END	; FLUSH THE REST OF THE STRING
;
EDS_PRE_000:
	MOV	SI,[BP+0]	; RESTORE THE START OF THE STRING
;
; GET THE CURSOR X/Y & SHAPE
;
	MOV	BH,[VIDPAGE]
	MOV	AH,03		; GET THE CURSOR X/Y & SHAPE
	INT	10H
	PUSH	DX		; BP - 4 = ORIGINAL ROW/COLUMN
	PUSH	CX		; BP - 6 = ORIGINAL CURSOR SHAPE
;
	CALL	CURSOR_SHAPE	; PERFORM A CURSOR SHAPE MODIFICATION
;
EDS_00A:
;
; PRINT THE STRING TO THE SCREEN
;
	CALL	DO_HOME
;
; FETCH A KEY & PROCESS IT
;
EDS_00:
	CALL	CHECK_END		; SEE IF WE'RE AT THE STRING'S END
;
	INKEY	,WAIT
;
; CHECK FOR F1/F3/HOME/END
;
	CMP	AX,F1KEY		; F1 TYPED?
	JZ	EDS_15			; YES, CONTINUE ON...
	CMP	AX,RIGHTKEY		; RIGHT ARROW KEY TYPED?
	JZ	EDS_15			; YES, CONTINUE ON...
;
; F2 OR F5 KEY CHECK
;
	CMP	AX,F2KEY		; F2 TYPED?
	JZ	EDS_35			; YES, CONTINUE ON...
	CMP	AX,F5KEY		; END TYPED?
	JZ	EDS_35			; YES, CONTINUE ON...
;
; F3 OR END KEY CHECK
;
	CMP	AX,F3KEY		; F3 TYPED?
	JZ	EDS_20			; YES, CONTINUE ON...
	CMP	AX,ENDKEY		; END TYPED?
	JZ	EDS_20			; YES, CONTINUE ON...
;
; F4 KEY CHECK
;
	CMP	AX,F4KEY		; F4 TYPED?
	JZ	EDS_40			; YES, CONTINUE ON...
;
; HOME KEY CHECK
;
	CMP	AX,HOME			; HOME TYPED?
	JZ	EDS_00A			; YES, GO PRINT ENTIRE STRING
;
; DELETE KEY CHECK
;
	CMP	AX,DELETE		; DELETE KEY TYPED?
	JZ	EDS_30			; YES, MOVE THE STRING LEFT
;
; INSERT KEY CHECK
;
	CMP	AX,INSERT		; INSERT KEY TYPED?
	JZ	EDS_25			; YES, GO FORM THE CURSOR
;
; CHECK FOR LEFT ARROW KEY
;
	CMP	AX,LEFTKEY		; LEFT ARROW KEY?
	JZ	EDS_10			; YES, GO ATTEMPT A BACKSPACE
;
; SPECIAL KEY CHECK, AH=XX,AL=00
;
	CMP	AL,0			; GOOD CHARACTER?
	JZ	EDS_00			; NO, CONTINUE WAITING
;
; CHECK FOR BACKSPACE
;
	CMP	AL,08			; BACKSPACE?
	JZ	EDS_10			; YES, GO ATTEMPT A BACKSPACE
;
; CHECK FOR EXIT DUE TO 'ESC' OR 'ENTER'
;
	CMP	AL,0DH			; CARRIAGE RETURN?
	JZ	EDS_100			; YES, EXIT HOME
	CMP	AL,1BH			; ESCAPE KEY TYPED?
	JZ	EDS_100			; YES, EXIT HOME...
;
; STORE THE CHARACTER IN THE STRING & DISPLAY THE CHARACTER
;
	CALL	CHK_INS			; CHECK INSERT STATE
	MOV	[SI],AL			; STORE IN THE TARGET STRING
	INC	SI
	CALL	PRTCHAR			; GO PRINT IT
	JMP	EDS_00			; CONTINUE THE INPUT...
;
; BACKSPACE PROCESSING...
;
EDS_10:
	CMP	SI,[BP+0]		; ARE WE AT THE START?
	JZ	EDS_00			; YES, TOSS THE BACKSPACE
	DEC	SI			; BACKSTEP THE TARGET POINTER
	MOV	AL,08H			; FORCE TO A BACKSPACE
	CALL	PRTCHAR			; GO 'PRINT' THE BACKSPACE
	JMP	EDS_00			; NO, GO BACK TO INPUTTING...
;
; F1 KEY PROCESSING
;
EDS_15:
	CALL	ORIGCHR			; PERFORM AN F1 REPEAT
	JMP	EDS_00			; GO BACK FOR MORE
;
; F3 KEY PROCESSING
;
EDS_20:
	CALL	ORIGSTR			; PERFORM AN F3 REPEAT
	JMP	EDS_00			; GO BACK FOR MORE...
;
; INSERT KEY PROCESSING
;
EDS_25:
	CALL	CURSOR_SHAPE		; MODIFY THE CURSOR
	JMP	EDS_00
;
; DELETE KEY PROCESSING
;
EDS_30:
	CALL	SHIFT_LEFT		; MOVE STRING LEFT
	CALL	PRINT_REST		; PRINT THE STRING FROM THE CURSOR TO RIGHT
	JMP	EDS_00			; GO FOR MORE
;
; DELETE TO END OF LINE - F5,F2 PROCESSING
;
EDS_35:
	CALL	NULL_TO_END		; FLUSH IT
	CALL	CLEAR_REST		; CLEAR THE SCREEN TO THE END OF LINE
	JMP	EDS_00			; GO FOR MORE
;
; DELETE THE ENTIRE LINE - F4 PROCESSING
;
EDS_40:
	MOV	SI,[BP+0]		; GRAB THE START OF THE STRING
	CALL	NULL_TO_END		; FLUSH IT
	MOV	DX,[BP-4]		; GET THE ORIGINAL CURSOR POSITION
	CALL	MOVE_CURSOR		; & MOVE TO START OF SCREEN
	CALL	CLEAR_REST		; CLEAR THE SCREEN TO THE END OF LINE
	JMP	EDS_00			; GO FOR MORE
;
; CARRIAGE RETURN & ESCAPE KEY PROCESSING
;
EDS_100:
	PUSH	AX			; SAVE THE RETURN CHARACTER
	MOV	CX,[BP-6]		; RESTORE THE ORIGINAL CURSOR SHAPE
	MOV	AH,01
	INT	10H
	POP	AX
;
	MOV	SP,BP			; FLUSH THE STACK
	POP	BX			; RESTORE THE CRITICALS
	POP	BX
	POP	CX
	POP	DX
	POP	SI
	POP	BP
	POP	ES
	RETURN
;
;
;=====================
;   ROUTINE SECTION
;	LEVEL 1
;=====================
;
;
; C H E C K _ E N D  --  MAKE SURE DS:SI IS WITHIN THE BUFFER
;
; Entry conditions:
;	DS:SI point to the string
; Exit conditions:
;	DS:SI possibly modified
;	AL possibly modified
; 
CHECK_END	PROC	NEAR
	CMP	SI,[BP-2]		; ARE WE TOO FAR RIGHT?
	JNZ	CKND_05			; NO, CONTINUE ON...
	DEC	SI			; YES, MOVE BACK
	MOV	AL,08
	CALL	PRTCHAR
;
CKND_05:
	RETURN

CHECK_END	ENDP
;
;
; C H K _ I N S  --  CHECK THE INSERT STATE & MOVE THE STRING, IF SET.
;
; Entry conditions:
;	None
; Exit conditions:
;	No registers modified
; 
CHK_INS	PROC	NEAR
	PUSH	AX
	PUSH	BX
	PUSH	CX
;
	MOV	AH,02
	INT	16H		; GET THE SHIFT STATE
	SHL	AL,1		; MOVE THE BIT TO THE CARRY
	JNC	CHINS_10	; EXIT IF INSERT STATE NOT SET
	CALL	SHIFT_RIGHT	; MOVE THE STRING RIGHT
	CALL	PRINT_REST	; PRINT IT TO THE SCREEN
;
CHINS_10:
	POP	CX
	POP	BX
	POP	AX
	RETURN

CHK_INS	ENDP
;
;
; C L E A R _ R E S T  --  CLEAR THE REST OF THE SCREEN TO END OF FIELD
;
; Entry conditions:
;	SI points to the start of the clear
; Exit conditions:
;	AX modified
;	No other registers modified
;
CLEAR_REST	PROC	NEAR
	PUSH	SI
	PUSH	DX
	PUSH	CX
;
	MOV	AH,03		; FETCH THE CURRENT CURSOR POSITION
	INT	10H
	PUSH	DX		; SAVE THE CURSOR POSITION
;
	SUB	AL,AL
;
CLRST_05:
	CMP	SI,[BP-2]	; ARE WE AT THE END?
	JZ	CLRST_10	; YES, DONE, SO EXIT
	CALL	PRTCHAR		; PRINT THE NULL
	INC	SI		; MOVE TO NEXT LOCATION
	JMP	SHORT CLRST_05
;
CLRST_10:
	POP	DX		; RESTORE THE CURSOR POSITION
	MOV	AH,02
	INT	10H
;
	POP	CX
	POP	DX
	POP	SI
	RETURN

CLEAR_REST	ENDP
;
;
; C U R S O R _ S H A P E  --  SET THE CURSOR SHAPE DEPENDING UPON
;			       THE INSERT STATE
;
; Entry conditions:
;	None
; Exit conditions:
;	No registers modified
; 
CURSOR_SHAPE	PROC	NEAR
	PUSH	AX
	PUSH	BX
	PUSH	CX
;
	MOV	AH,02
	INT	16H		; GET THE SHIFT STATE
	SHL	AL,1		; MOVE THE BIT TO THE CARRY
	MOV	BL,0
	ADC	BL,0
	MOV	AL,[CRTFLAG]	; GET THE MONO/CGA FLAG
	ROL	BL,1		; MOVE IN THE MONO/CGA FLAG
	SHR	AL,1
	ADC	BL,0
;
; BL HOLDS THE CURSOR SHAPE INDEX
;
	SUB	BH,BH
	SHL	BX,1
	MOV	CX,CS:CURS[BX]	; GET THE SHAPE
	MOV	AH,01
	INT	10H		; & GO SET IT
;
	POP	CX
	POP	BX
	POP	AX
	RETURN

CURSOR_SHAPE	ENDP
;
CURS	LABEL	WORD
	DW	0C0DH ;	BL = 0
	DW	0607H ;	BL = 1
	DW	000DH ;	BL = 2
	DW	0007H ;	BL = 3
;
;
; D O _ H O M E  --  PRINT THE ENTIRE STRING & RESET POINTERS TO START
;
; Entry conditions:
;	DS:SI point to the start of the string
; Exit conditions:
;	AX modified
;	Cursor & string pointers, variables moved to start of string
;
DO_HOME	PROC	NEAR
	CALL	ORIGSTR		; PRINT STRING & LEAVE CURSOR AT TAIL
	MOV	DX,[BP-4]	; GET THE ORIGINAL CURSOR POSITION
	CALL	MOVE_CURSOR
	MOV	SI,[BP+0]	; MOVE SI TO START OF STRING
	RETURN

DO_HOME	ENDP
;
;
; P R I N T _ R E S T  --  PRINT THE REST OF THE STRING TO THE SCREEN
;
; Entry conditions:
;	DS:SI point to the string
; Exit conditions:
;	No registers modidied
;
PRINT_REST	PROC	NEAR
	PUSH	SI			; SAVE THE STRING POSITION
	MOV	AH,03
	INT	10H
	PUSH	DX			; SAVE THE CURSOR POSITION
;
	CALL	ORIGSTR			; PRINT THE STRING
;
	MOV	AL,20H			; WIPE OUT THE TRAILING CHARACTER
	CALL	PRTCHAR
;
	POP	DX			; FETCH THE ORIGINAL CURSOR LOCATION
	CALL	MOVE_CURSOR		; SET THE CURSOR TO THE SAME LOCATION
	POP	SI			; RESTORE THE STRING POINTER
	RETURN

PRINT_REST	ENDP
;
;
; S H I F T _ L E F T  --  MOVE THE CONTENTS OF THE STRING LEFT ONE POSITION
;
; Entry conditions:
;	DS:SI points to the start of the string
; Exit conditions:
;	No registers modified
;
SHIFT_LEFT	PROC	NEAR
	PUSH	CX
	PUSH	SI
	PUSH	DI
;
	MOV	DI,SI
	INC	SI
;
SHLF_05:
	LODSB			; FETCH THE CHARACTER
	STOSB			; & STUFF IN PREVIOUS LOCATION
	OR	AL,AL		; DID WE MOVE THE TERMINATOR?
	JNZ	SHLF_05		; NO, GO FIND IT...
;
	POP	DI
	POP	SI
	POP	CX
	RETURN

SHIFT_LEFT	ENDP
;
;
;=====================
;   ROUTINE SECTION
;	LEVEL 2
;=====================
;
;
; N U L L _ T O _ E N D  --  NULL OUT THE REST OF THE STRING
;
; Entry conditions:
;	BP-2 holds the end of string pointer
;	SI points to the start of the clear
; Exit conditions:
;	AX modified
;	No other registers modified
;
NULL_TO_END	PROC	NEAR
	PUSH	SI
	SUB	AL,AL	
;
NLTOEN_05:
	CMP	SI,[BP-2]	; ARE WE AT THE END?
	JZ	NLTOEN_10	; YES, EXIT NOW
	MOV	[SI],AL		; SET THE TERMINATOR
	INC	SI
	JMP	SHORT NLTOEN_05	; GO FOR MORE...
;
NLTOEN_10:
	POP	SI
	RETURN

NULL_TO_END	ENDP
;
;
; O R I G S T R  --  SAVE EVERY BYTE IN THE STRING - F3 HAS BEEN TYPED
;
; Entry conditions:
;	DS:SI point to the string
; Exit conditions:
;	DS:SI advanced to the end of the string
;
ORIGSTR	PROC	NEAR
	CALL	ORIGCHR			; NO, MOVE ONE CHARACTER
	JNZ	ORIGSTR			; NOT DONE YET, CONTINUE TILL ALL MOVED
	RETURN

ORIGSTR	ENDP
;
;
; S H I F T _ R I G H T - MOVE THE CONTENTS OF THE STRING RIGHT
;			  ONE POSITION IF THE INSERT STATE IS POSITIVE
;
; Entry conditions:
;	DS:SI points to the start of the string
; Exit conditions:
;	No registers modified
;
SHIFT_RIGHT	PROC	NEAR
	PUSH	AX
	PUSH	SI
	PUSH	DI
;
	MOV	DI,SI		; DI POINTS TO STRING TOO
	MOV	AH,20H		; PRIME THE 1ST STORAGE
;
SHRT_05:
	LODSB			; FETCH THE 1ST CHARACTER
	XCHG	AH,AL		; AL = 1ST CHARACTER, AH = JUST READ CHAR
	STOSB			; SAVE THE 1ST CHARACTER
	OR	AH,AH		; IS AH THE TERMINATOR?
	JNZ	SHRT_05		; NO, CONTINUE THE SHUFFLE
;
	CMP	SI,[BP-2]	; IS SI PAST THE LAST VALID CHARACTER?
	JLE	SHRT_10		; NO, CONTINUE ON...
	DEC	DI		; YES, SO MOVE BACK TO TERMINATE IT
;
SHRT_10:
	MOV	AL,AH		; SET THE NEW TERMINATOR
	STOSB
;
	POP	DI
	POP	SI
	POP	AX
	RETURN

SHIFT_RIGHT	ENDP
;
;
;=====================
;   ROUTINE SECTION
;	LEVEL 3
;=====================
;
;
; O R I G C H R  --  MOVE THE STRING POINTER & DISPLAY
;		     THE CHARACTER FROM THE STRING.
;
; Entry conditions:
;	DS:SI point to the string
; Exit conditions:
;	DS:SI advanced one position
;	Z = terminator encountered, NZ = character printed & saved
;
ORIGCHR	PROC	NEAR
	CMP	BYTE PTR [SI],0		; TERMINATOR?
	JZ	ORCH_05			; YES, EXIT
	LODSB				; FETCH THE CHARACTER
	CALL	PRTCHAR			; PRINT THE CHARACTER
	OR	AL,AL			; SET THE RETURN FLAGS
;
ORCH_05:
	RETURN

ORIGCHR	ENDP
;
;
;=====================
;   ROUTINE SECTION
;	LEVEL 4
;=====================
;
;
; P R T C H A R  --  PRINT THE CHARACTER IN AL AND ADVANCE THE CURSOR
;
; Entry conditions:
;	AL holds the character
; Exit conditions:
;	CX,AX,BX,DX modified
;
PRTCHAR	PROC	NEAR
	MOV	BH,[VIDPAGE]
	MOV	AH,0EH
	INT	10H
	RETURN

PRTCHAR	ENDP
;
;
;=====================
;   ROUTINE SECTION
;	LEVEL 5
;=====================
;
;
; M O V E _ C U R S O R  --  MOVE THE CURSOR TO THE ROW/COLUMN POSITION
;
; Entry conditions:
;	DH = row
;	DL = column
; Exit conditions:
;	No registers modified
;
MOVE_CURSOR	PROC	NEAR
	PUSH	AX
	PUSH	BX
;
	MOV	BH,[VIDPAGE]		; GET THE VIDEO PAGE #
	MOV	AH,02			; SET THE CURSOR POSITION
	INT	10H
;
	POP	BX
	POP	AX
	RETURN

MOVE_CURSOR	ENDP
;
ENDPGM	EDITS
;
