PROCEDURE	<INDEX - Insert index item>,010001
;+
; Copyright (c) 1976
; Digital Equipment Corporation, Maynard, Mass.
;
; This software is furnished under  a license for use only  on  a
; single computer system and may be  copied only with  the inclu-
; sion of  the  above  copyright notice. This software,  or  any
; other copies thereof, may not be  provided  or  otherwise  made
; Available to any other person except  for  use  on  such system
; and to  one who agrees  to  these license  terms. Title to and
; ownership of the software shall at all times remain in DEC.
;
; The information in this software  is  subject to change without
; notice and should not be construed  as  a commitment by Digital
; Equipment Corporation.
;
; DEC assumes no responsibility for the use or reliability of its
; software on equipment which is not supplied by DEC.
;
; Abstract: This module inserts an item into the Index list
;
; Written: 1-Jun-72, -0.0.0-, L. Wade
; 
; Modified: 12-Jan-80, -1.0.0-, Henry R. Tumblin
;	Produced Duke supported version
;
; Verified: 12-Jan-80, -1.0.0-, Henry R. Tumblin
;
; Modified: 06-Nov-81, -1.0.1-, John D. Leonard
;	No need to change page number for number page lower condition.
;-

	.sbttl	Runoff Definitions

	.GLOBL	APNDN		; current appendix letter
	.GLOBL	CHPTN		; current chapter number
	.GLOBL	CR		; carriage return
	.GLOBL	GCIN		; get character from input file
	.GLOBL	PAGENO		; current page number
	.GLOBL	S1		; temporary accumulator
	.GLOBL	XFIRST		; pointer to first index block pointer
	.GLOBL	$FRCND		; force to logical end of command
 
;	index globals

	.GLOBL	INDEX		; module entry point

	.SBTTL	INDEX FLAGS AND DEFINITONS

;	index flags

	IDXCF	=	1	; case difference flag
	IDXRF	=	2	; repeated item flag
 
;	Index link block offsets
 
	ID.FWD	=	0	; foward pointer
	ID.BCK	=	ID.FWD + 2; back pointer
	ID.TXT	=	ID.BCK + 2; asciz text pointer
	ID.PNO	=	ID.TXT + 2; page number
	ID.CHA	=	ID.PNO + 2; chapter/appendix number.
	ID.LEN	=	ID.CHA + 2; length of index block header

	.SBTTL	Local data 

	DATA	INDEXD,LCL

IDXFLG:	.BLKW	1		; index flags word

ICBUF:	.BLKB	52.		; index item buffer

	ICBFE	=	.-2

	.SBTTL	Start mainline
;+
; **-INDEX-add index item to index data
;-
	CODE	INDEX		; set up index p-sect
;	
;	This command inserts index text into the index
;	list, which is a circular linked list.
 
;	First copy the index string into the temporary string
;	area. The maximum length of an index string is
;	currently 52 bytes. If the index string is too long, then
;	it will be truncated to 52 characters, and a diagnostic
;	message generated.
 
INDEX::	MOV	#ICBUF,R0	; get address of index item buffer
	MOV	R0,R5		; copy index item buffer address
10$:	CLR	(R0)+		; clear index item buffer
	CMP	R0,#ICBFE	; At end of holding buffer ?
	BLOS	10$		; LOS - not yet
	MOV	#<ICBFE-ICBUF>,R3 ; end test on buffer
	CLR	IDXFLG		; Reset flags

	CALL	$FRCND		; force to logical end of command
 
;	Get the index string from the input file.
 
INDX1:	CALL	GCIN		; read character from file
	CMPEQ	R1,#CR,INDX2	; end of line?
	MOVB	R1,(R5)+	; store character of index data
	DEC	R3		; loop if room
	BGT	INDX1		; GT - go back for more
;
;	Tell user that their index string is being truncated
;	and print same.
 
	DIAG	IDTRNC		; Output truncate message

;	Insure that the string is word aligned  for
;	insertion into the INDEX TEXT buffer.

INDX2:	BITEQ	#1,R5,10$	; check for boundary alignment
	DEC	R5		; back up one byte
10$:	SUB	#ICBUF-2,R5	; calculate length of asciz string
	MOV	R5,S1		; save for later use
	MOV	XFIRST,R2	; get address of first item so far
	BEQ	INDXV		; if none, list is empty. start it.

	.sbttl	Scan for index match

;	This loop scans the index list for a match for
;	this index item. If found, then the pointer in the
;	index list to the index text will point to the same item
;	and only the entry block is entered, and no new text
;	is inserted. If a match isn't found, then a new entry is
;	created.
 
;	R0 - Character from old string
;	R1 - Character from new string
;	R2 - Pointer to INDEX list
;	R3 - Pointer to existing index item asciz string
;	R4 - Pointer to item eligable to be added
;	R5 - Not used

;	Initialize

INDXL2:	BIC	#IDXCF,IDXFLG	; clear case difference flag
	MOV	4(R2),R3	; address of asciz of old item
	MOV	#ICBUF,R4	; pointer to new item

; 	Compare strings

INDXL1:	MOVB	(R3)+,R1	; get char of old
	MOVB	(R4)+,R0	; and one of new
	CMPEQ	R1,R0,10$	; same before case merge?
	BIS	#IDXCF,IDXFLG	; set case difference flag
10$:	BITB	#CHALC,CHATBL(R1) ; Is it lower case?
	BEQ	20$		; EQ - no
	BIC	#40,R1		; Convert to upper case
20$:	BITB	#CHALC,CHATBL(R0) ; Is it lower case ?
	BEQ	30$		; EQ - no
	BIC	#40,R0		; Convert to upper case
30$:	CMPNE	R1,R0,40$	; not same?
	TSTNE	R1,INDXL1	; end of strings?
40$:	CMPEQ	R1,R0,INDX4	; which is first?
	BGT	INDX3		; new one is first, and different

;	Get the next link in the index list

IDX4A:	MOV	(R2),R3		; no. old one is first. look further
	BEQ	INDX5		; end of list. new is last
	MOV	R3,R2		; move link to a
	BR	INDXL2		; look further

	.sbttl	Add item to list

;	R0 - Backward pointer
;	R1 - Not used
;	R2 - Pointer to INDEX list
;	R3 - Not used
;	R4 - Pointer to item eligable to be added
;	R5 - Not used

INDX3:	BIT	#IDXRF,IDXFLG	; Repeated item ?
	BNE	IDX4B		; EQ - no, then insert normally
	CALL	INDXAD		; add item with page no to storage (unlinked?

	MOV	2(R2),R0	; who preceded old?
	BNE	10$		; anyone?
	MOV	R4,XFIRST	; no. new is first of all.
10$:	MOV	R4,2(R2)	; new is predecessor of old
	MOV	R2,(R4)		; old is successor of new, no predecessor
	MOV	R0,2(R4)	; set old predecessor
	BEQ	20$		; if eq none
	MOV	R4,(R0)		; make new one be his successor
20$:	RETURN			;

	.SBTTL	Repeated Item

INDX4:	BIT	#IDXCF,IDXFLG	; Check case flag
	BNE	INDX3		; case difference?
	BIS	#IDXRF,IDXFLG	; set repeated item flag
	BR	IDX4A		; go look for last occurrence.

IDX4B:	MOV	2(R2),R2	; at end of repeat. get last one.

IDX4C:	CALL	INDXAP		; add pointers only (with page. no link)
	MOV	4(R2),4(R4)	; new points to same text as old
	MOV	(R2),R0		; get previous successor of old
	MOV	R4,(R2)		; make new succeed old
	TSTEQ	R0,10$		; no old next?
	MOV	R4,2(R0)
10$:	MOV	R0,(R4)+	; old successor is successor of new
	MOV	R2,(R4)		; old is predecessor of new
	RETURN			;

	.sbttl	Add new item to list

;	add a new item to the list.

;	R2 - pointer to current index block
;	R4 - pointer to newly allocated index block

INDX5:	BIT	#IDXRF,IDXFLG	; repeated item ?
	BNE	IDX4C		; ne - yes, then add pointers only
	CALL	INDXAD		; create text and pointer block with pageno
	MOV	R4,ID.FWD(R2)	; make new follow old
	CLR	ID.FWD(R4)	; clear forward link
	MOV	R2,ID.BCK(R4)	; and old precede new.
	RETURN			;

	.sbttl	Empty List, create initial entry

;	R4 - pointer to newly allocated block
;	XFIRST - pointer to head of index list

INDXV:	CALL	INDXAD		; create text and pointer block, page no
	MOV	R4,XFIRST	; this is first item (and only)
	CLR	ID.FWD(R4)	; no links at all
	CLR	ID.BCK(R4)
	RETURN			;

	.sbttl	Add index link block to list

INDXAD:	CALL	INDXAX		; allocate item and buffer
	MOV	R4,-(SP)	; save base of new item
	CLR	ID.FWD(R4)	; clear forward link
	CLR	ID.BCK(R4)	; clear backward link
	MOV	R4,ID.TXT(R4)	; set pointer to
	ADD	#ID.LEN,ID.TXT(R4) ; asciz text area
	MOV	ID.TXT(R4),R4	; point to text area

;	move text into block area

	MOV	#ICBUF,R0	; transfer text into buffer
	MOV	S1,R1		; get count of bytes in index item
10$:	MOVB	(R0)+,(R4)+	; transfer index item
	DEC	R1		; any more bytes to move?
	BGT	10$		; if gt yes
	MOV	(SP)+,R4	; restore base of index.
	RETURN			;

	.SBTTL	ALLOCATE LINK BLOCK
	.ENABL	LSB

INDXAP:	CLR	R1		; indicate no additional storage
	BR	10$		;

	.SBTTL	ALLOCATE LINK BLOCK AND ASCIZ BUFFER

INDXAX:	MOV	S1,R1		; indicate buffer storage needed

10$:	ADD	#ID.LEN,R1	; compute length of area.
	CALL	ALLOC		; allocate the area.
	MOV	R1,R4		; return the area allocated.
	MOV	PAGENO,ID.PNO(R4) ; insert page number
	.if	ndf	A$$RAP
	TST	$NUMLW		; Numbering pages at bottom ?
	BEQ	20$		; EQ - no
	INC	ID.PNO(R4)	; Else bump up page number
	.endc
20$:	CLR	ID.CHA(R4)	; assume no chapter/appendix
	MOVB	APNDN,ID.CHA(R4) ;insert current appendix
	BNE	30$		; if NE - we were in an appendix
	MOVB	CHPTN,ID.CHA(R4) ; EQ - then we were in a chapter.
	BEQ	30$		; EQ - No! not in anything!
	COMB	ID.CHA+1(R4)	; designate chapter number
30$:	RETURN			;

	.DSABL	LSB

	.END
