// FB.SR


get "BRAVO1.DF";
get "CHAR.DF";
get "MSG.DF"
get "FORMAT.DF"
get "VM.DF"
get "COM.DF"


// Incoming Procedures

external	[
	binsearcha
	getvp
	ugt
	ult
	errhlta
	move
	min
	SetVab
	];


// Incoming Statics

external	[
	mpfnof
	vbi
	mpbifc
	rgmpbifc
	mpbifb
	rgmpbifb
	vfb
	mpfrfc
	pctb
	rgpctb
	mppccp
	vpc
	ppcd
	vcuripar
	vfn
	vfc
	pcfirst
	vfcfirst
	vfopPara
	vfclast
	pclast
	parstd
	rgmaccp
	vfcofopenpar
	rgbs
	vbp
	];


// Outgoing Procedures

external	[
	mapfc;
	getbin;
	cpparabounds
	cpfc;
	fcparabounds
	getfb;
	VpaGetScratchBin
	GetSi
	SiPut
//	getnextfr;
//	establishpara
//	paraloc;
//	bifrpara;
	];


// Outgoing Statics

external	[
	vfr;
	vbifr;
	vpfb
	parofbounds;
	vWaOfSiMac

	vlook1;
	vlook2;
	vlook1old;
	vlook2old;
	vdxleftmarg
	vdxrightmarg
	vdxleftmargf
//	vbifrpara
//	vfcstatus;
//	vfbloc;
//	vlparam;
//	vchlcom;
	]


// Local Statics

static	[
	vfr;
	vbifr;
	vpfb
	parofbounds;
	vWaOfSiMac

	vpar
//	vcpnextpc
//	vcpthispc

	vlook1;
	vlook2;
	vlook1old;
	vlook2old;
	vdxleftmarg
	vdxrightmarg
	vdxleftmargf
//	vbifrpara
//	vfcstatus;
//	vfbloc;
//	vlparam;
//	vchlcom;
	]


// Local Manifests

// manifest
//	[ 
//	look1orbold = 4;
//	look1orital = 8;
//	look1orul = 32;
//	] 


// M A P F C

let mapfc(fn, fc) be
[
unless (mpfnof ! fn)>>OF.formatted do
	[
	vbi = -1;
	vfr = -1;
	vbifr = -1;
	return
	]
mpbifc = rgmpbifc ! fn;
mpbifb = rgmpbifb ! fn;
vbi = binsearcha(mpbifc, (mpfnof ! fn)>>OF.macbi, fc);
vfb = mpbifb ! vbi;
let pfb = getfb(vfb);
mpfrfc = pfb+pfb>>FB.mpfrfc;
vfr = binsearcha(mpfrfc, pfb>>FB.macfr, fc);
vbifr<<FBFR.fb = vbi;
vbifr<<FBFR.fr = vfr;
]


// G E T N E X T F R
// 
// and getnextfr(fn, bifr) = valof
// [
// let vpa = nil;
// vpa<<VPA.fn = fnscrfs;
// bifr = bifr+1;
// 	[
// 	vpa<<VPA.fp = (rgmpbifb ! fn) ! (bifr<<FBFR.fb);
// 	let pfb = getvp(vpa);
// 	if (bifr<<FBFR.fr ls pfb>>FB.macfr) then
// 		resultis bifr;
// 	bifr<<FBFR.fb = bifr<<FBFR.fb+1;
// 	bifr<<FBFR.fr = 0;
// 	] repeat
// ]


// G E T B I N

and getbin(fn, bi) = valof
[
let vpa = nil;
(lv vpa)>>VPA.fn = fnscrfs;
let fb = (rgmpbifb ! fn) ! bi;
(lv vpa)>>VPA.fp = fb;
resultis getvp(vpa);
]


// B I F R P A R A
// 
// and bifrpara(fn, bifr) = valof
// [
// sets vpfb and returns fbbw of paragraph
// vpfb = getbin(fn, bifr<<BIFR.bi) 
// resultis (lv (vpfb>>FB.rvdnpi)) !
// 	(((vpfb + vpfb>>FB.rglook1) ! (bifr<<BIFR.fr)) <<LOOK1.pi)
// ]


// C P F C

and cpfc(doc, cp) = valof
[
// computes key piece data and returns vfc
// this is a subset of establishpc
// it also sets vpc
pctb = rgpctb ! doc
mppccp = lv (pctb>>PCTB.rvmppccp)
vpc = binsearcha(mppccp, pctb>>PCTB.macpc, cp)
ppcd = (pctb + pctb>>PCTB.rgpcd)+(vpc lshift 2)
// vcpnextpc = mppccp ! (vpc+1)
// vcpthispc = mppccp ! vpc
resultis pcfc(cp)
]


// C P P A R A B O U N D S

and cpparabounds(doc, cp, ptextstart, ptrailerstart, ptrailerend) be
[
// changes static variables like vpc, ppcd, etc
// leaves the pcd of pclast in ppcd!!!
if (vcuripar>>IPAR.doc eq doc) & (not ugt(vcuripar>>IPAR.cpfirst, cp)) & (not ult(vcuripar>>IPAR.cplast, cp)) then
	[
	if ptextstart then @ptextstart = vcuripar>>IPAR.cpfirst;
	if ptrailerstart then @ptrailerstart = vcuripar>>IPAR.cptrailer;
	if ptrailerend then @ptrailerend = vcuripar>>IPAR.cplast;
	return;
	]

lrestart:
vcuripar>>IPAR.doc = -1;
let fbbw = nil
cpfc(doc, cp)
let fnofcp = vfn;
let fcofcp = vfc;
let pcofcp = vpc;
let pcdofcp = ppcd;
let cpfirstofpcofcp = mppccp ! pcofcp;
let tfn = -1;
let tfnlast = nil;
let pcd = nil;
let trailerlength = nil;
let tcp = nil;
let tfc = nil; 
let macpc = pctb>>PCTB.macpc;
let cptrailerend = nil
let tpar = vec parovhd;
if ptextstart ne 0 then @ptextstart = valof
	[
	pcfirst = pcofcp;
	pcd = pcdofcp;
	if cp eq cpfirstofpcofcp then
		test pcd>>PCD.parastart ifso
			resultis cp
		ifnot	[
			pcfirst = pcfirst-1;
			pcd = pcd-4;
			]
		[
		test (pcd>>PCD.live) % (pcd>>PCD.paraend eq 0) ifso
			if pcd>>PCD.parastart then
				resultis mppccp ! pcfirst;
		ifnot	break;
		pcfirst = pcfirst-1;
		if pcfirst eq -1 then errhlta(155);
		pcd = pcd-4;
		] repeat
	let tcpfirst = mppccp ! pcfirst;
	test pcfirst eq pcofcp ifso
		[
		tcp = cp;
		tfn = fnofcp;
		tfc = fcofcp;
		]
	ifnot	[
		tcp = mppccp ! (pcfirst+1) - 1;
		tfn = (pcd>>PCD.vpa)<<VPA.fn;
		tfc = pcd>>PCD.rc + (pcd>>PCD.vpa)<<VPA.fp lshift 9 + tcp - mppccp ! pcfirst;
		]
	fcparabounds(tfn, tfc);
	trailerlength = vpar>>PAR.trailerlength;
	move(vpar, tpar, parovhd);
	if ugt(tfc-vfcfirst, tcp-tcpfirst) then
		[
		unless pcfirst eq pcofcp then errhlta(156);
		if pcd>>PCD.parastart then
			resultis tcpfirst;
		vfopPara = pcd>>PCD.fop;
		cptrailerend = tcp+(vfclast-tfc)
		if ptrailerend ne 0 then
			[
			@ptrailerend = cptrailerend;
			ptrailerend = 0;
			]
		if ptrailerstart ne 0 then
			[
			@ptrailerstart = cptrailerend-trailerlength+1;
			ptrailerstart = 0;
			]
		move(tpar, parofbounds, parovhd);
		cpparabounds(doc, tcpfirst-1, ptextstart, 0, 0);
		resultis @ptextstart;
		]
	resultis tcp-(tfc-vfcfirst);
	]
if (ptrailerend ne 0) % (ptrailerstart ne 0) then
	[
	cptrailerend = valof
		[
		pclast = pcofcp;
		pcd = pcdofcp;
			[
			if (pclast eq macpc) then
				errhlta(157);
			if pcd>>PCD.paraend then break;
			pclast = pclast+1;
			pcd = pcd+4;
			] repeat
		let tcplast = (mppccp ! (pclast+1))-1;
		vfopPara = pcd>>PCD.fop;
		if pcd>>PCD.live then
			[
			move(parstd, parofbounds, parovhd);
			trailerlength = 2;
			resultis tcplast;
			]
		test pclast eq pcofcp ifso
			[
			tcp = cp;
			tfnlast = fnofcp;
			tfc = fcofcp;
			]
		ifnot	[
			tcp = mppccp ! pclast;
			tfnlast = (pcd>>PCD.vpa)<<VPA.fn;
			tfc = pcd>>PCD.rc + (pcd>>PCD.vpa)<<VPA.fp lshift 9
			]
		test (tfnlast eq tfn) & (not ugt(tfc, vfclast)) & (not ult(tfc, vfcfirst)) ifnot
			[
			fcparabounds(tfnlast, tfc);
			trailerlength = vpar>>PAR.trailerlength;
			move(vpar, parofbounds, parovhd);
			]
		ifso	move(tpar, parofbounds, parovhd);
		if ugt(vfclast-tfc, tcplast-tcp) then
			[
			unless pclast eq pcofcp then errhlta(158);
			cpparabounds(doc, tcplast+1, 0, ptrailerstart, ptrailerend);
			resultis @ptrailerend;
			]
		resultis tcp+(vfclast-tfc);
		]
	if ptrailerend ne 0 then
		[
		@ptrailerend = cptrailerend;
		unless cptrailerend eq rgmaccp ! doc-1 do
			[
			cpfc(doc, cptrailerend);
			if ppcd>>PCD.visibuf then
				[
				ptextstart = 0;
				cp = cptrailerend+1;
				goto lrestart;
				]
			]
		]
	if ptrailerstart ne 0 then
		@ptrailerstart = cptrailerend-trailerlength+1;
	]
]


// E S T A B L I S H P A R A
// 
// and establishpara(fn, fc) be
// [
// sets vbifr, vpar, and vpfb
// mapfc(fn, fc)
// vpar = (vbifr eq -1) ? parstd, paraloc(bifrpara(fn, vbifr))
// ]


// F C P A R A B O U N D S

and fcparabounds(fn, fc) be
[
// computes vbifr, vfcfirst, and vfclast
// establishpara(fn, fc)
mapfc(fn, fc)
// vpar = (vbifr eq -1) ? parstd, paraloc(bifrpara(fn, vbifr))
vpar = (vbifr eq -1) ? parstd, valof
	[
	vpfb = getbin(fn, vbifr<<BIFR.bi) 
	let dnpi = lv (vpfb>>FB.rvdnpi);
	let look1 = (vpfb + vpfb>>FB.rglook1) ! (vbifr<<BIFR.fr);
	let fbbw = dnpi ! (look1<<LOOK1.pi)
	resultis getfb(fbbw<<FBLOC.fb) + fbbw<<FBLOC.bw;
	];
if (fn eq fnscr) & not ult(fc, vfcofopenpar) then
	[ vfcfirst = vfcofopenpar;
	vfclast = -1;
	return;
	]
vfcfirst = (vbifr eq -1) ? 0, vpar>>PAR.fcofpar;
vfclast = (vbifr eq -1) ? (mpfnof ! fn)>>OF.macpos - 1,
	vpar>>PAR.fcofnextpar - 1
]


// G E T F B

and getfb(fb) = valof
[
let vpa = nil
vpa<<VPA.fn = fnscrfs
vpa<<VPA.fp = fb
resultis getvp(vpa)
]


// P A R A L O C
//
// and paraloc(fbbw) = getfb(fbbw<<FBLOC.fb) + fbbw<<FBLOC.bw


// P C F C

and pcfc(cp) = valof
[
// finds fc given ppcd, mppccp, vpc
let vpa = ppcd>>PCD.vpa
vfn = vpa<<VPA.fn
vfc = (vpa<<VPA.fp lshift 9) + ppcd>>PCD.rc + cp - mppccp ! vpc
resultis vfc
]


// V P A G E T S C R A T C H B I N

and VpaGetScratchBin() = valof
[
let vpa = nil;
vpa<<VPA.fn = fnscrfs
let fp = ((mpfnof ! fnscrfs)>>OF.macpos+#777)<<PCD.p
if fp ge #177 then errhlta(159)
vpa<<VPA.fp = fp
fp = fp+1;
(mpfnof ! fnscrfs)>>OF.macpos = fp lshift 9
resultis vpa
]


// G E T S I

and GetSi(pl, si, cwMax) be
[
let p = getfb(si<<WA.fp)
let tPl = p+si<<WA.rw;
let cw = tPl>>PL.cw; 
unless si<<WA.rw+cw-1 ls cWPerPage do errhlta(160)
cw = min(cwMax, cw); 
move(tPl, pl, cw)
]


// S I P U T

and SiPut(si, pl, cw; numargs carg) = valof
[
if carg ls 3 then cw = pl>>PL.cw;
unless ult(cw, cWPerPage) then errhlta(161)
if si eq siNil then
	[
	if (vWaOfSiMac<<WA.fp) ne ((vWaOfSiMac+cw)<<WA.fp) then
		[
		let fcMac = (mpfnof ! fnscrfs)>>OF.macpos
		if (fcMac rshift 9) ge #170 then
			SetVab(abmsg,mtyAnc,227)
		vWaOfSiMac = fcMac rshift 1;
		(mpfnof ! fnscrfs)>>OF.macpos = fcMac+#1000;
		]
	si = vWaOfSiMac
	vWaOfSiMac = vWaOfSiMac+cw
	]
let p = getfb(si<<WA.fp)
let tPl = p+si<<WA.rw;  
move(pl, tPl, cw)
(rgbs ! vbp)<<BS.dirty = true
resultis si
]