// CPDL.SR 	cp <-> dl

get "BRAVO1.DF"
get "CHAR.DF"
get "DISPLAY.DF"
get "COM.DF"

// Incoming procedures

external
	[
	ult
	ugt
	ratio
	umax
	binsearcha
	invalidatedisplay
	updatedisplay
	mapcp
	move
	format
	umin;
	movec;
	errhlta;
	mapcpb;
	updatewindowcond;
	cpparabounds;
// 	setmag;
	mpDlDld;
	]

// Incoming statics

external
	[
	rgcpfirst
	vcp
	rgmaccp
	pctb
	rgpctb
	mppccp
	vpc
	vchremain
	vlb
	vpw
	vcplast
	vww;
	vdoc;
	vrgcc1;
	vchremainb;
	vmapstatus;
// 	vmag;
	mpWwWwd;
	vsgd;
	]

// Outgoing procedures

external
	[
	finddl;
	normalize;
	cpvisible;
	backdylines;
	visible;
	forwardscan;
	]

// Outgoing statics

external
	[
	rgcpfirstback
	rgheightdback;
	vwwback;
	avdcpfix;
	avdcpl;
	avheight;
	]

// Local statics

static
	[
	rgcpfirstback
	rgheightdback;
	maclback;
	vwwback;
	avdcpfix;
	avdcpl;
	avheight;
	]

// F I N D D L
// SPE catalogue no.

let finddl(ww,cp) = valof
[ let wwd = mpWwWwd ! ww
let dlfirst = wwd>>WWD.dlFirst;
let dldFirst = mpDlDld(dlfirst)
let dlLast = wwd>>WWD.dlLast; let dldLast = mpDlDld(dlLast)
if (dlLast ls dlfirst) % ult(cp,rgcpfirst ! dlfirst) % ugt(
cp,dldLast>>DLD.cpLast)
then resultis -1;
unless ult(cp,rgcpfirst ! dlLast) then resultis dlLast
resultis dlfirst+binsearcha(lv(rgcpfirst ! dlfirst),(dlLast-dlfirst),cp);
] // end finddl

// N O R M A L I Z E 
//

and normalize(cf) = valof
[
let sel= cf>>CF.sel
let selcpfirst= sel>>SEL.cpfirst
let ww= sel>>SEL.ww
cpvisible(ww,selcpfirst)
resultis abnil
]

// C P V I S I B L E 
// 
and cpvisible(ww,cp) be 
[ let wwd = mpWwWwd ! ww
backdylines(ww,cp,0);
wwd>>WWD.cpFDispl= vcp
wwd>>WWD.fUpdate = true
updatedisplay()

//let tcpfdispl = wwd>>WWD.cpFDispl;
//let tcpfirst = nil;
//test visible(ww,vcp) ifnot
//	[ tcpfdispl = vcp
//	tcpfirst = tcpfdispl
//	] 
//ifso	tcpfirst = vcp;
//	[ wwd>>WWD.cpFDispl = tcpfdispl;
//	wwd>>WWD.fUpdate = true;
//	updatedisplay( );
//	unless wwd>>WWD.dlFirst eq wwd>>WWD.dlLast then
//		tcpfdispl = rgcpfirst ! (wwd>>WWD.dlFirst+1);
//	] repeatwhile ult(tcpfirst,wwd>>WWD.cpFDispl)
] 

// U P D A T E A V
//
and updateav(av,value) be
[
av >> AV.nom = av >> AV.nom + value;
av >> AV.denom = av >> AV.denom + 1;
if av >> AV.denom ls 0 then
	[
	av >> AV.nom = av >> AV.nom rshift 1;
	av >> AV.denom = av >> AV.denom rshift 1;
	];
]
// A V E R A G E
//
and average(av) = ratio(av >> AV.nom,1,av >> AV.denom)

// B A C K D Y L I N E S
//catalogue no. = 116
and backdylines(ww,cp,dy) = valof
[ let wwd = mpWwWwd ! ww
let doc = wwd>>WWD.doc;
let tdy = nil;
if (cp eq rgmaccp ! doc) & (cp ne 0) then
	cp = cp-1;

if (ww eq vwwback) & (maclback gr 1) & (not ult(cp,rgcpfirstback ! 0))
	& (not ugt(cp,rgcpfirstback ! (maclback-1))) then
	[
	tdy = 0;
	for l = binsearcha(lv(rgcpfirstback ! 0),maclback-1,cp)
		to 1 by -1 do
		[
		tdy = tdy + rgheightdback ! (l-1);
		if tdy ge dy then
			[
			vcp = rgcpfirstback ! (dy ? l-1,l);
			resultis tdy;
			]
		];
	cp = rgcpfirstback ! 0; dy = dy - tdy;
	];

let cpfirstpar = nil;
let tcp = cp;
	[
	cpparabounds(doc,tcp,lv cpfirstpar,0,0);
	if (dy eq 0) % ult(cpfirstpar,cp) % (cp eq 0) then break;
	tcp = cpfirstpar - 1;
	] repeat;
vcp = cpfirstpar;
let dcpavfix2 = average(avdcpfix) lshift 1;

if ult(dcpavfix2,cp-cpfirstpar) then
	[
	let dcp = umax(1,umin(dcpavfix2,
		umax(3,ratio(dy,average(avdcpl),average(avheight)))));
	let cplastscan = cp;
		[
		if cplastscan eq 0 then
			[
			vcp = 0; goto fixpoint;
			];
		cplastscan = cplastscan - 1;
		if not ult(cpfirstpar+dcp,cplastscan) then
			[
			vcp = cpfirstpar; goto fixpoint;
			];
		let cpfirstscan = cplastscan - dcp;
		if forwardscan(doc,cpfirstscan,cplastscan,chcr) then
			[
			vcp = vcp + 1;
			if (dy eq 0) % ult(vcp,cp) then
				goto fixpoint;
			];
		cplastscan = cpfirstscan;
		dcp = 700;
		] repeat
	];

fixpoint:
updateav(avdcpfix,cp-vcp);

vww = ww;
// if vmag ne wwd>>WWD.mag then setmag(ww);

let l = 0;
	[ 
	let cpfirst = vcp;
	format(ww,vcp,modex);
	let dYdDl = ((vsgd>>SG.topmax+vsgd>>SG.blmax+1) & (-2)) +(((vsgd>>SG.ldTop) + 1) & (-2))
	test l ls maxl ifso
		[
		rgcpfirstback ! l = cpfirst;
		rgheightdback ! l = dYdDl;
		]
	ifnot	[
		move(rgcpfirstback+1,rgcpfirstback,maxl-1)
		move(rgheightdback+1,rgheightdback,maxl-1)
		rgcpfirstback ! (maxl-1) = cpfirst;
		rgheightdback ! (maxl-1) = dYdDl;
		]; 
	updateav(avdcpl,vcplast-cpfirst+1)
	updateav(avheight,dYdDl)
	if not ult(vcplast,cp) then
		[
		maclback = umin(maxl,l+1);
		vwwback = ww;
		tdy = 0;
		for l1 = maclback-1 to 1 by -1 do
			[
			tdy = tdy + rgheightdback ! (l1-1);
			if tdy ge dy then
				[
				vcp=rgcpfirstback ! (dy ? l1-1,l1);
				resultis tdy;
				]
			]
		vcp = rgcpfirstback ! 0; resultis tdy;
		]; 
	vcp = vcplast+1;
	l = l+1;
	] repeat 
] 

// V I S I B L E
//
and visible(ww,cp) = valof
[ let wwd = mpWwWwd ! ww
test ult(cp,wwd>>WWD.cpFDispl) % ugt(cp,(mpDlDld(wwd>>WWD.dlLast))>>DLD.cpLast) ifso
	resultis false
ifnot	resultis true;
] 
// F O R W A R D S C A N
//
and forwardscan(doc,cp,cplast,char) = valof
[
let tchar = nil;
cplast = umin((rgmaccp ! doc)-1,cplast);
if ult(cplast,cp) then errhlta(100);

vcp = cp;
vmapstatus = statusblind;
let breakcharlast = false;
let breakcharcurrent = nil;
let fswtfound = false
	[ 
	mapcp(doc,vcp);
	while vchremain do
		[ test vlb ifso
			[ tchar = vpw >> lh;
			vlb = false;
			] 
		ifnot	[ tchar = vpw >> rh;
			vlb = true;
			vpw = vpw+1;
			] 
		vchremain = vchremain-1;
		test char ne 0 ifso
			[
			if tchar eq char then
				resultis true;
			]
		ifnot
			[
			test cp eq vcp ifso
				[
				if tchar eq chcr then
					resultis true;
				]
			ifnot
				[ if fswtfound eq true then
					resultis true
				breakcharcurrent = (vrgcc1 ! tchar) << CC.breakchar;
				test breakcharlast ifnot
					breakcharlast = breakcharcurrent;
				ifso
					[
					unless breakcharcurrent then
						fswtfound = true;
					]
				]
			];
		if vcp eq cplast then
			resultis false;
		vcp = vcp+1;
		] 
	] repeat 
]