// diablofinfo.sr

// Last modified October 25, 1979  6:45 PM by Taft


get "BRAVO1.DF"
get "CHAR.DF"
get "ST.DF"
get "MSG.DF"
get "DIABLO.DF"
get "COM.DF"
get "HARDCOPY.DF"


// Outgoing Procedures

external	[
	FinfoToDiablo
	MoveX
	PositionYd
	]


// Outgoing Statics

external	[
	vxwChuldiablo
	vxDiablo
	]


// Incoming Procedures

external	[
	ratio
	DiabloMoveXd
	errhlta
	DiabloMoveYd
	DiabloPrintChar
	]


// Incoming Statics

external	[
	vxdDiablo
	vydDiablo
	rgfinfo
	vmaccr
	rgxw
	msgtbl
	look1std
	look2std
	]


// Local Statics

static	[
	vxDiablo
	vyDiablo
	vxwChuldiablo
	]


// Local Structures

// structure


// Local Manifests

manifest	[
	chulDiablo = #137		// get from font width description
	dydItalic = 2
	cprintBold = 3
	]


// D X D   F R O M   D X   M I C A S

let DxdFromDxMicas(dx) = valof
[
let fsign = dx ls 0
let dxd = (ratio((fsign ? -dx, dx), 2 * mictodmlt, mictoddiv) + 1) rshift 1
resultis (fsign ? -dxd, dxd)
] // end DxdFromDxMicas


// D Y D   F R O M   D Y   P O I N T S

and DydFromDyPoints(dy) = valof
[
let fsign = dy ls 0
let dyd = (ratio((fsign ? -dy, dy), 2 * pttodmlt, pttoddiv) + 1) rshift 1
resultis (fsign ? -dyd, dyd)
] // end DydFromDyPoints


// M O V E   X

and MoveX(dx) be
[
vxDiablo = vxDiablo + dx
// if vxDiablo ls 0 % vxDiablo ge vxEdgeofpage then errhlt("mxb")
DiabloMoveXd(DxdFromDxMicas(vxDiablo) - vxdDiablo)
] // end MoveX


// P O S I T I O N   Y D

and PositionYd(yd) be
[
if yd ls 0 % yd ge ydMax then errhlta(203)
DiabloMoveYd(yd - vydDiablo)
] // end PositionYd


// F I N F O   T O   D I A B L O

and FinfoToDiablo(fm, cp, xFirst, xLast, yd) = valof
[
let cchPgbrk = 0
if (rgfinfo ! (vmaccr-1))<<FINFO.char eq chcr then
	[
	vmaccr = vmaccr-1
	xLast = xLast - rgxw ! vmaccr
	]
PositionYd(yd)
if vmaccr eq 0 then resultis 0
let ofsetd = 0
let fBackwards = vxDiablo gr (xFirst + xLast+1) rshift 1

let tfmsg = msgtbl
// let fOvstrikePrev = false
// let crFirstOvstrike = nil
// let xwOvstrike = nil
for tcr = 0 to vmaccr-1 do
	[
	let tfinfo = rgfinfo ! tcr
	if tfinfo<<FINFO.newmsg then
		tfmsg = tfmsg + 2
//	let fOvstrike = (tfmsg>>FMSG.look1)<<LOOK1.ovstrike ne 0
//	test fOvstrike ifso
//		test fOvstrikePrev ifnot
//			[
//			crFirstOvstrike = tcr
//			xwOvstrike = rgxw ! tcr
//			]
//		ifso	xwOvstrike = xwOvstrike + rgxw ! tcr
//	ifnot	if fOvstrikePrev then
//			[
//			xwOvstrike = xwOvstrike + rgxw ! tcr
//			for ttcr = crFirstOvstrike to tcr do
//				rgxw ! ttcr = xwOvstrike
//			]
//	fOvstrikePrev = fOvstrike
	]
let tfmsgCrMinus1 = tfmsg		// msg belonging to cr = vmaccr - 1
tfmsg = msgtbl			// msg belonging to cr = 0 - 1
let tfmsgdefault = vec 1; tfmsgdefault!0 = look1std; tfmsgdefault!1 = look2std

let cr = (fBackwards ? vmaccr-1, 0)
MoveX((fBackwards ? xLast+1, xFirst) - vxDiablo)
let fNewmsg = true
let finfoOld = 0
let look1Old = 0
let cprint = 1
let ch = nil
let xw = nil
let xwLeftHalf = nil
let xwRightHalf = nil
let xwResidue = 0
let dxMove = nil
let look1 = nil
let look2 = nil
while cr ge 0 & cr ls vmaccr do
	[
	let finfo = rgfinfo ! cr
	let finfoTrans = nil

	test fBackwards ifso
		[
// this really needs a few words:
// assume tfmsgCrMinus1 is good, i.e. really was the msg belonging to the cr 1 less than previous iteration -- then it must be the right msg for this iteration (since we're going backwards) -- so use it
		if tfmsg ne tfmsgCrMinus1 then
			[
			tfmsg = tfmsgCrMinus1
			fNewmsg = true
			]
// now, if this cr has a different msg than the cr one less than it (newmsg bit set), then what we want to do is find that other msg for tfmsgCrMinus1
		if finfo<<FINFO.newmsg then
			tfmsgCrMinus1 = tfmsgCrMinus1 - 2
		]
	ifnot	[
// forward case is straightforward (by comparison anyway) -- remember old msg, inc if necessary for new
		tfmsgCrMinus1 = tfmsg
		if finfo<<FINFO.newmsg then
			[
			tfmsg = tfmsg + 2
			fNewmsg = true
			]
		]
// one last tweak:
	if tfmsgCrMinus1 eq msgtbl then
		tfmsgCrMinus1 = tfmsgdefault

	if fNewmsg then
		[
		finfoOld = 0
		look1 = tfmsg>>FMSG.look1
		look2 = tfmsg>>FMSG.look2
		let look1Trans = not look1Old & look1
		look1Old = look1
		if look1<<LOOK1.vanish then
			goto nextcr
		let ofsetNew = look2<<LOOK2.ofset
		let ofsetdNew = DydFromDyPoints(look2<<LOOK2.ofsetsgn ?
			ofsetNew % ofsetsgnext, ofsetNew)
		if ofsetdNew ne ofsetd then
			[
			DiabloMoveYd(ofsetdNew-ofsetd)
			ofsetd = ofsetdNew
			]
		if look1Trans<<LOOK1.italic then
			[
			let look1mask = 0
			look1mask<<LOOK1.italic = true
			look1mask<<LOOK1.ovstrike = true
			let look2mask = 0
			look2mask<<LOOK2.ofset = true
			let txw = XwLookAhead(cr, tfmsg, fBackwards, 0, look1mask, look2mask)
			MoveX((fBackwards ? -xwResidue, xwResidue))
			xwResidue = 0
			DrawLine(txw, fBackwards)
			DiabloMoveYd(-dydItalic)
			DrawLine(txw, not fBackwards)
			DiabloMoveYd(dydItalic)
			]
		cprint = (look1<<LOOK1.boldface ? cprintBold, 1)
		if look2<<LOOK2.fun ne 0 then
			cprint = 0
		fNewmsg = false
		]
	finfoTrans = not finfoOld & finfo
	finfoOld = finfo
	if finfoTrans<<FINFO.lowbar then
		[
		MoveX((fBackwards ? -xwResidue, xwResidue))
		xwResidue = 0
		let xOld = vxDiablo
		let finfomask = 0
		finfomask<<FINFO.lowbar = true
//		finfomask<<FINFO.ovstrike = true
		let look2mask = 0
		look2mask<<LOOK2.ofset = true
		DrawLine(XwLookAhead(cr, tfmsg, fBackwards, finfomask, 0, look2mask), fBackwards)
		MoveX(xOld - vxDiablo)
		]
//	handle other bars bits in similar fashion

	ch = finfo<<FINFO.char
	if ch eq chpgbrk then cchPgbrk = cchPgbrk + 1

	xw = rgxw ! cr
	xwLeftHalf = xw rshift 1
	xwRightHalf = xw - xwLeftHalf
//	if (tfmsgCrMinus1>>FMSG.look1)<<LOOK1.ovstrike then
//		xwLeftHalf = 0
//	if look1<<LOOK1.ovstrike then
//		xwRightHalf = 0
	dxMove = xwResidue + (fBackwards ? xwRightHalf, xwLeftHalf)
	MoveX((fBackwards ? -dxMove, dxMove))
	xwResidue = (fBackwards ? xwLeftHalf, xwRightHalf)

	if (finfo<<FINFO.space eq 0) & ch ne chsp & ch ne chpgbrk then
		for i = 1 to cprint do
			[
			test ch eq $← ifso
				[
//			kluge for missing backarrow character
				DiabloPrintChar($-)
				DiabloPrintChar($<)
				]
			ifnot
				DiabloPrintChar(ch)
			]

nextcr:
	cr = cr + (fBackwards ? -1, 1)
	]
if ofsetd ne 0 then DiabloMoveYd(-ofsetd)
resultis cchPgbrk
] // end FinfoToDiablo


// X W   L O O K   A H E A D

and XwLookAhead(cr, fmsg, fBackwards, finfomask, look1mask, look2mask) = valof
[
let xw = 0
let finfo = rgfinfo ! cr
let finfoFirst = finfo & finfomask
let look1First = fmsg>>FMSG.look1 & look1mask
let look2First = fmsg>>FMSG.look2 & look2mask
while (finfo & finfomask) eq finfoFirst &
	(fmsg>>FMSG.look1 & look1mask) eq look1First &
	(fmsg>>FMSG.look2 & look2mask) eq look2First do
	[
	xw = xw + rgxw ! cr
	if fBackwards & finfo<<FINFO.newmsg then
		fmsg = fmsg - 2
	cr = cr + (fBackwards ? -1, 1)
	if cr ls 0 % cr ge vmaccr then break
	finfo = rgfinfo ! cr
	if not fBackwards & finfo<<FINFO.newmsg then
		fmsg = fmsg + 2
	]
resultis xw
] // end XwLookAhead


// D R A W   L I N E

and DrawLine(xwToFill, fBackwards) be
[
// if xwToFill ls vxwChuldiablo then errhlt("drl")
let dxMove = vxwChuldiablo rshift 1
let dxMoveLast = vxwChuldiablo - dxMove
while xwToFill ge vxwChuldiablo do
	[
	MoveX((fBackwards ? -dxMove, dxMove))
	DiabloPrintChar(chulDiablo)
	dxMove = vxwChuldiablo
	xwToFill = xwToFill - vxwChuldiablo
	]
if xwToFill gr 0 then
	[
	MoveX((fBackwards ? -xwToFill, xwToFill))
	DiabloPrintChar(chulDiablo)
	]
MoveX((fBackwards ? -dxMoveLast, dxMoveLast))
] // end DrawLine