.TITLE	FEDMNG ... Form Editting Manager
.IDENT	/310583/
.enabl	lc
;
;
;
;
;	Written by	Ray Di Marco
;			1-Oct-80.
;
;
;	Version		011080/07
;
;
;----------------------------------------------------------------------
;
;
; This module contains the routines needed to edit a DBSMNG form. A DBSMNG
; form is described by a Record Descriptor Table (RDT) which specifies the
; fields in the record. The address of the RDT for the form to be editted
; must be passed over in R5. A field specification includes its logical name,
; position on the screen and attributes. The two entries to the module are
; 
; 	FED.NW	calling this entry causes the record contents to be zeroed
; 		before new data is entered. This entry should be called
; 		when creating a new entry
; 
; 	FED.OD	calling this entry causes the record contents not to be
; 		zeroed. This entry should be called to edit an existing
; 		record.
;
; The C flag will be set on exit iff the editting of the form was ABORTED. 
; The following global variables are of particular significance
;
;	FED.MD	bit 0	if set record zeroed upon entry (set by FED.NW)
;		bit 1	if set start in Form Entry Mode	(set by FED.NW/OD)
;		bit 2	is set disable Command Mode (set by caller)
;	PAGE$$		currently selected page (set to 1 by FED.NW)
;	PAGE$$+2	default page (loaded into PAGE$$ by FED.OD)
;
;
;

.SBTTL	MODIFICATIONS
;
;
; 14-JAN-81	SUPPORT 'WNDIOF' RESETTING.
; 28-APR-81	'ENTER' - SUPPORT 'BACKSP' KEY
; 30-APR-81	MAJOR CHANGES TO SUPPORT MULTIPLE PAGES
; 29-APR-82	remove MFPS/MTPS instructions.
;  1-Oct-82	change LOCFLD to support exact/approximate matching
;  1-Jun-83	major rewrite to clean up module and provide proper
;		support of labels.
;
;

.SBTTL	DECLARATIONS
;
;
.MCALL	.PUSH,.POP				; STACKING
.MCALL	CNAF,ABORT,CMDTAB
;
;
.GLOBL	FED.OD,FED.NW				; ENTRIES
.GLOBL	FED.MD					; MODE CONTROL FLAG
.GLOBL	PAGE$$					;; PAGE NUMBER
;
.GLOBL	TBLKUP					; "TBLKUP" TABLE LOOKUP
.GLOBL	FRM.EF,FRM.ZE,FRM.BG,FRM.FG		; "FRMIO"
.GLOBL	FLD.OU,FLD.IN,FLD.CK			; "FLDIO"
.GLOBL	WND.IN					; "WNDIO"
.GLOBL	WND.FL					; "WNDIO"
.GLOBL	ASCNUM					; "ASCNUM"
.GLOBL	CNAFD2					; 'CNAFD'
.GLOBL	LOCFLD					; "LOCFLD"
;
;
;
	.PSECT	CODE				; OPEN CODE AREA
;	------	----
;
;
ENTSIZ	= 40					; FDB SIZE IN BYTES
;
;

.SBTTL	Macro Definitions
;
.MACRO	INPUT	BUFFER=IOM.BF,PROMPT,STATUS,ERROR
	.GLOBL	IOM.PT,IOM.IN,IOM.ER,IOM.BF,IOM.ST
	MOV	R0,-(SP)
	.IF	NB,ERROR
		MOV	ERROR,R0
		CALL	IOM.ER
	.ENDC
	.IF	NB,STATUS
		MOV	STATUS,R0
		CALL	IOM.ST
	.ENDC
	.IF	NB,PROMPT
		MOV	PROMPT,R0
		CALL	IOM.PT
	.ENDC
	MOV	(SP)+,R0
	MOV	BUFFER,R0
	CALL	IOM.IN
.ENDM	INPUT
;
.MACRO	DISPLAY	PROMPT,STATUS,ERROR
	.GLOBL	IOM.PT,IOM.ER,IOM.ST
	MOV	R0,-(SP)
	.IF	NB,ERROR
		MOV	ERROR,R0
		CALL	IOM.ER
	.ENDC
	.IF	NB,STATUS
		MOV	STATUS,R0
		CALL	IOM.ST
	.ENDC
	.IF	NB,PROMPT
		MOV	PROMPT,R0
		CALL	IOM.PT
	.ENDC
.ENDM	DISPLAY
;
.MACRO	PROMPT	MESSAGE
	.GLOBL	IOM.PT
	MOV	R0,-(SP)
	.IIF	NB,MESSAGE	MOV	MESSAGE,R0
	CALL	IOM.PT
	MOV	(SP)+,R0
.ENDM	PROMPT
;
.MACRO	STATUS	MESSAGE
	.GLOBL	IOM.ST
	MOV	R0,-(SP)
	.IIF	NB,MESSAGE	MOV	MESSAGE,R0
	CALL	IOM.ST
	MOV	(SP)+,R0
.ENDM	STATUS
;
.MACRO	ERROR	MESSAGE
	.GLOBL	IOM.ER
	MOV	R0,-(SP)
	.IIF	NB,MESSAGE	MOV	MESSAGE,R0
	CALL	IOM.ER
	MOV	(SP)+,R0
.ENDM	ERROR
;

.SBTTL	Entry Points
;
; Two entry points are provided to the mode. They setup the FED.MD and
; PAGE$$ variables before passing control to the command loop code.
; These variables are global and have the following usage
;
;	FED.MD	bit 0	if set record zeroed upon entry (set by FED.NW)
;		bit 1	if set start in Form Entry Mode	(set by FED.NW/OD)
;		bit 2	is set disable Command Mode (set by caller)
;	PAGE$$		currently selected page (set to 1 by FED.NW)
;			PAGE$$+2 is loaded into PAGE$$ by FED.OD
;
;
;
; 	FED.NW	calling this entry causes the record contents to be zeroed
; 		before new data is entered. This entry should be called
; 		when creating a new entry
;
FED.NW:	BIS	#3,FED.MD	; zero record, start in Entry Mode
	MOV	#1,PAGE$$	; select page 1
	JMP	CMDMNG		; enter common loop
;
;
; 	FED.OD	calling this entry causes the record contents not to be
; 		zeroed. This entry should be called to edit an existing
; 		record.
;
FED.OD:	BIC	#1,FED.MD	; no zero
	BIS	#2,FED.MD	; start in Entry Mode
	MOV	PAGE$$+2,PAGE$$	; select default page
	JMP	CMDMNG		; goto main loop
;
;

.SBTTL	Command Dispatch loop
;
; Initialize registers etc
;
CMDMNG:	.PUSH	<R0,R1,R2,R3,R4,R5>	;	save
	MOV	R5,RECPNT		;	save RDT address
	MOV	(R5),RECADD		;	save rec address
	CNAF	SD,STRING=#9011$,NUMBER=10(R5) ; number pages
	ERROR	#0			;	no errors as yet
	MOVB	#1,WND.FL+1		;	select normal edit mode
	MOV	R5,R0			; R0 ->	RDT
	MOV	(R5),R5			; R5 ->	Buffer
;
; Zero record if needed
;
	BIT	#1,FED.MD		;	need to zero record?
	BEQ	200$			;	 no --> skip
	CALL	FRM.ZE			; 	 yes -> zero record
;
; Display form
;
200$:	CALL	FRM.EF			;	erase form area
	CALL	FRM.BG			;	display background
	CALL	FRM.FG			;	display fg
	CALL	MOVTOP			;	move to top of page
;
; See if immediate Entry mode enabled or if Command mode disabled
;
	BIT	#2,FED.MD		;	entry mode enabled?
	BEQ	700$			;	 no --> command mode
	CALL	.EDIT			;	 yes -> enter data
	BIT	#4,FED.MD		; 	command mode disabled?
	BNE	777$			;	 yes -> quit
;
; Command Mode loop
;
700$:	CNAF	SD,STRING=#9012$,NUMBER=PAGE$$ ; setup page num in 901$
	INPUT	,#900$,#901$		;	input command
	ERROR	#0			;	clear error message
	TSTB	(R0)			;	null input?
	BEQ	777$			;	 yes -> exit
	MOV	#1000$,R1		; R1 ->	command table
	CALL	TBLKUP			;	lookup time
	BCS	770$			;	trap lookup failure
	MOV	R0,R2			; R2 ->	rest of input
	MOV	RECPNT,R0		; R0 ->	RDT
	CALL	@2(R1)			;	execute command
	BR	700$			;	loop
770$:	ERROR	#902$			;	sorry, illegal command
	BR	700$			;	try for another command
777$:	CALL	.QUIT			;	quit command loop
;

;
; Messages
;
.nlist	bin
900$:	.ASCII	|Commands <CR>=EXit ABort|
	.ASCII	| First Top Enter LOcate Page Refresh CLEAR|<200>
;
901$:	.ASCII	|FEDMNG - Command Mode! (Page |
 9012$:	.ASCII	|XX of |
 9011$:	.ASCII	|XX)|<200>
902$:	.ASCII	|SORRY-Command not recognized?|<7><200>
.even
.list	bin
;
;
; Command decode table
;
	CMDTAB	1000$			;	declare table
	CMDENT	<AB-ORT>,.ABORT		;	abort
	CMDENT	<QU-IT>,.QUIT		;	quit
	CMDENT	<EX-IT>,.QUIT		;	quit
	CMDENT	<F-IRST>,.FIRST		;	first field
	CMDENT	<T-OP>,.TOP		;	top of form
	CMDENT	<E-DIT>,.EDIT		;	edit
	CMDENT	<EN-TER>,.EDIT		;	enter data
	CMDENT	<CLEAR->,.CLEAR		;	clear
	CMDENT	<R-EFRESH>,.REFRE	;	refresh
	CMDENT	<LO-CATE>,.LOCATE	;	locate
	CMDENT	<P-AGE>,.PAGE		;	page number
	.WORD	0,0,0,0			;	end of table
;
;

.SBTTL	Simple Command Routines
;
; This page contains the code for the simpler command routines. The following
; facts should be kept in mind
;
;	R0 holds the address of the RDT
;	R2 points to the rest of the input string
;	R5 holds the address of the record buffer
;
;
; Both .QUIT and .ABORT terminate editting. .QUIT writes out the modified
; data and .ABORT does not.
;
.QUIT:	TST	(PC)+			;	clear abort flag
.ABORT:	SEC				;	set abort flag
	MOV	(SP)+,R0		;	discard internal call address
	.POP	<R5,R4,R3,R2,R1,R0>	;	restore
	MOV	#0,FED.MD		;	reset mode flags
	RETURN				;	home
;
;
; .EDIT resumes editting at the last activated field, while .TOP starts
; editting at the first field on the page.
;
.TOP:	CALL	MOVTOP			;	move to top of form
.EDIT:	JMP	ENTER			;	enter data
;
; Erase the data in the record
; 
.CLEAR:	CALL	FRM.ZE			;	zero data
	JMP	FRM.FG			;	redisplay data
;
; Refresh the screen
;
.REFRE:	CALL	FRM.EF			;	erase form part of scree
	CALL	FRM.BG			;	display background
	JMP	FRM.FG			;	display foreground
;

.SBTTL	Command	- .PAGE		...	switch to page N
;
;
; Are here to change to page specified as part of command. If already on
; page no need to do anything; if not already on page must do a page flip
; (ie refresh the screen) and activate first field on the page.
;
;
; See if page flip necessary
;
.PAGE:	MOV	R2,R1			; R1 -> input
	CALL	ASCNUM			; R0 =	desired page number
	CMP	R0,PAGE$$		;	page change needed?
	BEQ	1000$			;	 no --> skip
	MOV	R0,PAGE$$		;	 yes -> set up page number
;
; Refresh screen and move to start of page
;
	MOV	RECPNT,R0		; R0 ->	RDT
	CALL	.REFRESH		;	refresh page
	CALL	MOVTOP			;	move to top
1000$:	RETURN				;	home
;

.SBTTL	Command	- .FIRST	...	activate first field of template
;
; The FIRST command allows the first field to be activated. A page flip is 
; auto-matically done if the first field is not on the currently selected
; page.
;
; Scan through FDBs till find an acceptable field
;
.FIRST:	MOV	2(R0),R1		; R1 -> FDB #1
	MOV	4(R0),R2		; R2 =	number of FDBS
100$:	TST	(R1)			;	protected field?
	BMI	120$			;	 yes -> ignore
	TST	10(R1)			;	Y = 0 (ie LABEL)?
	BNE	2000$			;	 no --> accept
120$:	ADD	#40,R1			;	try next field
	SOB	R2,100$			;	loop
	ABORT	<FEDMNG-fatal-illegal template>
;
; Setup ENTDAT+0/2 for field
;
2000$:	MOV	R1,ENTDAT		;	setup pointer to entry
	SUB	2(R0),R1		; R1 =	offset from first FDB
	ASH	#-5,R1			; R1 =	number of entry
	MOV	4(R0),ENTDAT+2		;	calculate number
	SUB	R1,ENTDAT+2		;	 entries left
;
; Insure on right page
;
	MOV	ENTDAT,R1		; R1 ->	FDB for selected field
	MOV	14(R1),R1		; R1 =	page its on
	BEQ	4000$			;	 skip if on page 0
	CMP	R1,PAGE$$		;	on currently selected page?
	BEQ	4000$			;	 yes -> skip
	MOV	R1,PAGE$$		;	 no --> change
	CALL	.REFRE			;		 page
;
; Enter data into field
;
4000$:	JMP	.EDIT			;	save a little code
;

.SBTTL	Command	- .LOCAT	...	locate and activate field
;
; The LOCATE command allows a specified field to be activated. The name of
; the field to activate is entered from the keyboard. A page flip is auto-
; matically done if the specified field is not on the currently selected
; page.
;
; See if field name specified as part of command.
;
.LOCAT:	MOV	R2,R1			; R1 -> rest of input
	MOV	RECPNT,R0		; R0 -> RDT
	CALL	LOCFLD			;	attempt to locate it
	BCC	1000$			;	 skip if suceed
;
; Prompt user for field name and then attempt to locate it
;
	INPUT	,PROMPT=#9000$,STATUS=#9001$,ERROR=#0
	MOV	R0,R1			; R1 ->	input
	MOV	RECPNT,R0		; R0 -> RDT
	CALL	LOCFLD			;	attempt to locate it
	BCC	1000$			;	 skip if failed
;
; Terminate if cannot locate field
;
	ERROR	#9002$			;	sorry, cannot locate field
	RETURN				;	I give in.
;
; Insure field not protected
;
1000$:	TST	(R1)			;	protected field?
	BPL	2000$			;	 no --> skip
	ERROR	#9003$			;	sorry, protected field
	RETURN				;	I give in.
;

;
; Setup ENTDAT+0/2 for field
;
2000$:	MOV	R1,ENTDAT		;	setup pointer to entry
	SUB	2(R0),R1		; R1 =	offset from first FDB
	ASH	#-5,R1			; R1 =	number of entry
	MOV	4(R0),ENTDAT+2		;	calculate number
	SUB	R1,ENTDAT+2		;	 entries left
;
; Insure on right page
;
	MOV	ENTDAT,R1		; R1 ->	FDB for selected field
	MOV	14(R1),R1		; R1 =	page its on
	BEQ	4000$			;	 skip if on page 0
	CMP	R1,PAGE$$		;	on currently selected page?
	BEQ	4000$			;	 yes -> skip
	MOV	R1,PAGE$$		;	 no --> change
	CALL	.REFRE			;		 page
;
; Enter data into field
;
4000$:	JMP	.EDIT			;	save a little code
;
.nlist	bin
9000$:	.ASCII	|Enter NAME of field to be located|<200>
9001$:	.ASCII	|FEDMNG-field Locate Mode!|<200>
9002$:	.ASCII	<7>|ERROR-cannot locate field?|<200>
9003$:	.ASCII	<7>|ERROR-field is PROTECTED!|<200>
.list	bin
.even
;

.SBTTL	Primitive - MOVTOP	...	activate first field on current page
;
; This routine is called to activate the first field in the RDT that lies
; on the currently selected page. It assumes that RECPNT holds the address
; of the record being editted and PAGE$$ the currently selected page. ENTADD,
; ENTADD+2 and ENTADD+4 are loaded with the FDB of the currently selected
; field, the number of remaining fields in the RDT (including the currently
; activated one) and the total number of FDB in the RDT.
;
;
; Use R0 as pointer to RDT, R1 as pointer to FDBs and R2 as count of FDBs.
;
MOVTOP:	.PUSH	<R0,R1,R2>		;	save
	MOV	RECPNT,R0		; R0 -> RDT
	MOV	2(R0),R1		; R1 -> FDB #1
	MOV	4(R0),R2		; R2 =	number of FDBS
	ABORT	<FEDMNG-fatal-illegal template, no fields>,EQ
;
;
; Scan through FDBs till find an acceptable field
;
100$:	TST	(R1)			;	protected field?
	BMI	200$			;	 yes -> ignore
	TST	10(R1)			;	Y = 0 (ie LABEL)?
	BEQ	200$			;	 yes -> ignore
	TST	14(R1)			;	page 0 field?
	BEQ	1000$			;	 yes -> accept
	CMP	14(R1),PAGE$$		;	on this page?
	BEQ	1000$			;	 yes -> accept
200$:	ADD	#40,R1			;	try next field
	SOB	R2,100$			;	loop
	ABORT	<FEDMNG-fatal-illegal template, blank page>
;
; Update ENTDAT, ENTDAT+2 and ENTDAT+4 and exit
;
1000$:	MOV	R1,ENTDAT		;	address of activated FDB
	MOV	R2,ENTDAT+2		;	number FDBs left
	MOV	4(R0),ENTDAT+4		;	total number of FDBs
	.POP	<R2,R1,R0>		;	restore
	RETURN				;	all done
;
;
;

.SBTTL	Primitive - ENTER	...	enter data into form
;
;
; Setup for loop
;
ENTER:	.PUSH	<R0,R1,R2>		;	save
	BIT	#4,FED.MD		;	in special (transperant) mode?
	BNE	100$			;	 yes ->	skip
	STATUS	#20000$			;	 no -->	identify self
100$:	PROMPT	#20001$			;	display prompt message
	MOV	ENTDAT,R1		; R1 ->	address of active rdb
	MOV	ENTDAT+2,R2		; R2 =	number of following records
;
; Input data into field
;
2000$:	MOV	R1,ENTDAT		;	remember which
	MOV	R2,ENTDAT+2		;	 field we are editting
	ERROR	#0			;	clear error message
	MOV	R1,R0			; R0 ->	FDB
	CALL	FLD.OU			;	activate field
2400$:	CALL	WND.IN			;	up date the field
	CALL	FLD.CK			;	any errors?
	BCC	2700$			;	no -> 4000$
	ERROR	#20002$			;	wrong type of data
	BR	2400$			;	loop
2700$:	CALL	FLD.IN			;	accept data
;
; If <TAB> hit activate and enter data into next field
;
4000$:	CMPB	R0,#<'I-'@>		;	tab used to terminate?
	BNE	5000$			;	no -> 8000$
4100$:	DEC	R2			;	can we advance a field?
	BLE	7000$			;	 no --> treat like <CR>
	ADD	#40,R1			; R1 ->	next field
	TST	(R1)			;	protected field?
	BMI	4100$			;	 yes -> ignore it
	TST	14(R1)			;	page 0 field?
	BEQ	2000$			;	 yes -> go edit it
	CMP	14(R1),PAGE$$		;	on this page field?
	BEQ	2000$			;	 yes -> go edit it
	BR	4100$			;	loop
;
; If <BS> hit activate and enter data into previous field
;
5000$:	CMPB	R0,#<'H-'@>		;	backspace?
	BNE	6000$			;	 no --> skip
5100$:	INC	R2			;	possible to
	CMP	R2,ENTDAT+4		;	 backup another field?
	BHI	7000$			;	  no -> treat as <CR>
	SUB	#40,R1			; R1 ->	previous field
	TST	(R1)			;	protected?
	BMI	5100$			;	 yes -> ignore
	TST	14(R1)			;	page 0 field?
	BEQ	2000$			;	 yes -> go edit it
	CMP	14(R1),PAGE$$		;	on this page field?
	BEQ	2000$			;	 yes -> go edit it
	BR	5100$			;	loop
;
; All done
;
6000$:
7000$:	ERROR	#0			;	clear error message
	PROMPT	#0			;	clear prompt message
	BIT	#4,FED.MD		;	in special (transperant) mode?
	BNE	7100$			;	 yes ->	skip
	STATUS	#0			;	 no -->	clear status line
7100$:	.POP	<R2,R1,R0>		;	restore
	RETURN				;	done
;
;
.nlist	bin
20000$:	.ASCII	|FEDMNG-Form Entry Mode!|<200>
20001$:	.ASCII	|<TAB> advance, <BACKSPACE> backup, <RETURN> exit|<200>
20002$:	.ASCII	<7>|ERROR-illegal data, please retype!|<200>
.list	bin
.even

.SBTTL	VARIABLES
;
;
PAGE$$:	.WORD	1			;	selected page
	.WORD	1			;	default page
FED.MD:	.WORD	0			; 	mode flags [Ext:Ent:Zer]
RECPNT:	.WORD	0			;	RDT address
RECADD:	.WORD	0			;	record buffer
ENTDAT:	.WORD	0			;	FDB for active field
	.WORD	0			;	number fields left
	.WORD	0			;	number fields in RDT
	.WORD	0			;	spare
;
.END
