// December 8, 1976  12:47 PM by Taft			*** overlay A ***

get "ZPDEFS.bcpl"

// outgoing procedures:

external [
	DTTitems
	unDTTitems
	addItemTable
	countItemTable
	checkItemID
	showItem
	eraseItem
	markItem
	flushItem
	]


// incoming procedures:

external [
	MoveBlock			// SYSTEM

	obtainBlock			// ZPBLOCK
	putBlock
	pushDTTstack

	remakeText			// ZPTEXT
	checkTextID
	showText
	eraseText
	markText

	remakeSpline			// ZPMAKE

	checkSplineID			// ZPDRAW
	drawSpline
	eraseSpline
	markSpline

	refreshDisplay			// ZPDISP	(same overlay)

	transformItem			// ZPUPDATE	(same overlay)
	]


// incoming statics:

external [
	@splineTable			// ZPINIT
	@textTable
	@DTTstack
	@DTTstackTop

	@maxSplineID
	@maxTextID
	@maxItem
	@maxDTTstack
	]


//********************************************************************
// DTT = Delete / Translate / Transform
//********************************************************************


let DTTitems(itemTable, q0, npoints; numargs nargs) be [DTTitems
	// possible parameter list:
	// code 0 (DELETE): itemTable
	// code 4 (2-point TRANSFORM=TRANSLATE): itemTable, q0, npoints=2
	// code 8 (4-point TRANSFORM): itemTable, q0, npoints=4
	// code 12 (6-point TRANSFORM): itemTable, q0, npoints=6

	let itemCount=countItemTable(itemTable)
	unless itemCount gr 0 return
	let code=(nargs eq 1) ? 0, 2*npoints
	while (DTTstackTop+itemCount+code+1) gr maxDTTstack do pushDTTstack()
	let doRefresh=(code ge 8) ? 0, (itemTable>>itemCOUNT.spline) gr (splineTable!0)/2
	unless doRefresh for i=1 to itemCount do eraseItem(itemTable!i)
	let count=0
	let oldDTTstackTop=DTTstackTop
	for i=1 to itemCount do [
		let itemID=itemTable!i
		let itemPointer=checkItemID(itemID)
		unless itemPointer loop
		let pointerTable=nil
		test code eq 0
		ifso [
			// delete:
			test itemID<<itemID.tFlag
			ifso pointerTable=textTable
			ifnot [
				pointerTable=splineTable
				putBlock(itemPointer>>SPLINE.chain)
				itemPointer>>SPLINE.chain=0
				]
			itemPointer>>ITEM.selected=0
			pointerTable!(itemID<<itemID.id)=0
			pointerTable!0=pointerTable!0-1
			]
			// 2-point (translate), 4-point & 6-point transform:
		ifnot unless transformItem(itemID, q0, npoints) loop
		count=count+1
		DTTstack!(oldDTTstackTop+count)=itemPointer
		]
	test doRefresh
	ifso refreshDisplay()
	ifnot if code eq 4 then for i=1 to itemCount do showItem(itemTable!i)
	//put REVERSED arguments & count/code word on DTTstack
	unless count gr 0 return
	DTTstack!oldDTTstackTop<<stackCOUNT.count=count
	DTTstack!oldDTTstackTop<<stackCOUNT.code=code
	let top=oldDTTstackTop+count+1
	if code ne 0 then [
		MoveBlock(DTTstack+top+npoints, q0, npoints)
		MoveBlock(DTTstack+top, q0+npoints, npoints)
		]
	//now see if DTTstack has changed since (because of pushDTTstacks!)
	if DTTstackTop ne oldDTTstackTop then
		MoveBlock(DTTstack+DTTstackTop, DTTstack+oldDTTstackTop, count+code+1)
	DTTstackTop=DTTstackTop+count+code+1
	]DTTitems




and unDTTitems() = valof [unDTTitems
	unless DTTstackTop gr 0 resultis 0
	let top=0
	let count,code=nil,nil
	[ count= DTTstack!top<<stackCOUNT.count
	  code=DTTstack!top<<stackCOUNT.code
	  let newTop=top+count+code+1
	  if newTop eq DTTstackTop break
	  top=newTop
	  ] repeat
	// first push stack down!
	DTTstackTop=DTTstackTop-count-code-1
	// now unDTT
	let top1=top+1
	let topCount=top+count
	// count splines!
	let sp=0
	for i=top1 to topCount do unless (DTTstack!i)>>ITEM.tFlag then sp=sp+1
	let doRefresh=code ge 8 ? 0, (sp gr (splineTable!0)/2)
	if code ne 0 then for i=top1 to topCount do [
		DTTstack!i=findItemID(DTTstack!i)
		unless doRefresh then eraseItem(DTTstack!i)
		]

	for i=top1 to topCount do test code eq 0
	ifso [
		// unDELETE:
		let itemPointer=DTTstack!i
		unless (itemPointer>>ITEM.tFlag ? remakeText(itemPointer),
			remakeSpline(itemPointer)) then putBlock(itemPointer)
		]
		// unTRANSLATE & unTRANSFORM:
	ifnot transformItem(DTTstack!i, DTTstack+topCount+1, code/2)

	if code eq 4 then test doRefresh
	ifso refreshDisplay()
	ifnot for i=top1 to topCount do showItem(DTTstack!i)
	]unDTTitems


//********************************************************************
// item operations
//********************************************************************

// NOTICE: for spline id=itemID


and checkItemID(itemID) = itemID<<itemID.tFlag ?
	checkTextID(itemID<<itemID.id), checkSplineID(itemID)



and findItemID(itemPointer) = valof [findItemID
	let tFlag=itemPointer>>ITEM.tFlag ? textFlag, 0
	let pointerTable= tFlag ? textTable, splineTable
	for id=1 to (tFlag ? maxTextID, maxSplineID) do
		if itemPointer eq pointerTable!id resultis (tFlag + id)
	resultis 0
	]findItemID



and eraseItem(itemID) = itemID<<itemID.tFlag ?
	eraseText(itemID<<itemID.id), eraseSpline(itemID)
	


and showItem(itemID) = itemID<<itemID.tFlag ?
	showText(itemID<<itemID.id), drawSpline(itemID)
	


and markItem(itemID,b) = itemID<<itemID.tFlag ?
	markText(itemID<<itemID.id,b), markSpline(itemID,b)



and flushItem(itemID) be [flushItem
	let itemPointer=checkItemID(itemID)
	unless itemPointer return
	let pointerTable=itemID<<itemID.tFlag ? textTable, splineTable
	unless itemID<<itemID.tFlag then putBlock(itemPointer>>SPLINE.chain)
	putBlock(itemPointer)
	pointerTable!(itemID<<itemID.id)=0
	pointerTable!0=pointerTable!0-1
	]flushItem
	


//********************************************************************
// item table operations
//********************************************************************



and countItemTable(itemTable) =
	itemTable>>itemCOUNT.spline + itemTable>>itemCOUNT.text



and addItemTable(itemTable,itemID) = valof [addItemTable
	let n=countItemTable(itemTable)
	if n eq maxItem resultis 0
	// already there ?
	for i=1 to n do if itemID eq itemTable!i resultis 0
	n=n+1
	itemTable!n=itemID
	itemTable!0=itemTable!0 +
		(itemID<<itemID.tFlag ? oneMoreTextItem, oneMoreSplineItem)
	resultis itemID
	]addItemTable