// GUPDATE.SR -- UPDATE AND INVALIDATE // GYPSY added rgulnew

get "DISPLAY.DF"
get "BRAVO.DF"
get "HEAP.DF"
get "GINN.DF"

// Incoming procedures

external
	[
	finddl
	ugt
	enww
	ult
	format
	hpalloc
	makebitmap
	makeclearbitmap
	hpfree
	move
	compactdisplay
	errhlt
	establishww
	hpalloca;
	mult;
	backscan;
	cppara // **
	gcspecs
	unparsespec
	enpspecs
	cppage
	pagecp
	bitmapwidth // **
	trycpspec
//	makeroominheap // %%
	]

// Incoming statics

external
	[
	xleftmargstd
	rgcpfdispl
	rgdlfirst
	vpzone
	rghpused
	vdoc
	rgdoc
	rgmaccp
	rgmaxdl
	rgcdlblank
	rgdllast
	vheight
	vwidth
	pbmfirstfree
	rgccomp
	macww
	vww
	fcp
	vdlhint
	vxfirst
	vxlast
	vcplast
	vcpfirst;
	rgul // **
	rgview
	vinsertk
	rgchoppage
	mdoc
	vturning
	mww // %%
	]

// Outgoing procedures

external
	[
	// ** updatewindow;
	freedl;
	updatedisplay;
	invalidatedisplay;
	invalidatewindow;
	invalidateband;
	invalidatedisplayk;
	filldisplay
	]

// Outgoing statics

external
	[
	rgupdate
	rgxfirst
	rgxfirstnew
	rgxlast
	rgxlastnew
	rgcpfirst
	rgcpfirstnew
	rgcplast
	rgcplastnew
	rgpbm
	rgpbmnew
	mpdldcb
	dlfirstfree
	vinvalidatek;
	vwwlock;
	vcompactlock;
	rgulnew // **
	]


// Local procedures:
//	invalidate1

// Local statics

static
	[
	rgupdate
	rgxfirst
	rgxfirstnew
	rgxlast
	rgxlastnew
	rgcpfirst
	rgcpfirstnew
	rgcplast
	rgcplastnew
	rgpbm
	rgpbmnew
	mpdldcb
	dlfirstfree
	vinvalidatek;
	vwwlock;
	vcompactlock;
	rgulnew // **
	]

// U P D A T E W I N D O W

let updatewindow(ww) be
[
let czpbm = 0;
let cp = rgcpfdispl ! ww;
let dlold = rgdlfirst ! ww;
let chpleft = vpzone >> ZONE.cfree+rghpused ! ww;
let dlnewlast = nil;
vdoc = rgdoc ! ww;
let stopcp = rgchoppage ! vdoc? pagecp(vdoc, cppage(vdoc, cp) + 1),
	rgmaccp ! vdoc // **
vwwlock = ww;
vcompactlock = true;
let chpleftold = chpleft;

czpbm = 0;
test rgmaccp ! vdoc eq cp
ifso dlnewlast = (rgdlfirst ! ww)-1
ifnot for dlnew = rgdlfirst ! ww to
		rgmaxdl ! ww-(1+rgcdlblank ! ww) do
	[
	while (dlold le rgdllast ! ww) &
		((rgxlast ! dlold ls 0) % ult(rgcpfirst ! dlold,cp)) do
			[
			freedl(dlold);
			dlold = dlold+1;
			];
	test (dlold le rgdllast ! ww) & (cp eq rgcpfirst ! dlold)
	ifso
		[
		rgulnew ! dlnew = rgul ! dlold ; // ** GYPSY
		rgcpfirstnew ! dlnew = rgcpfirst ! dlold;
		rgcplastnew ! dlnew = rgcplast ! dlold;
		vxfirst = rgxfirst ! dlold;
		vxlast = rgxlast ! dlold;
		let pbm = rgpbm ! dlold;
		rgxfirstnew ! dlnew = vxfirst;
		rgxlastnew ! dlnew = vxlast;
		rgpbmnew ! dlnew = pbm;
		let tchpleft = chpleft-(pbm-
			((offset HP.use)/16)) >> HP.siz;
		if not ugt(tchpleft,displaybuf) &
			dlnew gr rgdlfirst ! ww +
					(ww eq mww?1,0) // ** %%
				then
			[
			dlnewlast = dlnew-1;
			break;
			];
		chpleft = tchpleft;
		let pdcb = mpdldcb ! dlnew;
		pdcb >> DCB.nwrds = bitmapwidth(vxfirst, vxlast) // **
		pdcb >> DCB.htab = xleftmargstd << X.wordindex; // **
		pdcb >> DCB.sa = pbm;
		dlold = dlold+1;
		]
	ifnot 	[
		vww = ww;
		unless trycpspec(vdoc, cp) then
			[
			dlnewlast = dlnew-1
			break
			]
		format(vdoc,cp);
		let bmsize = mult(vheight,vwidth);
		rgulnew ! dlnew = 0 ; // ** GYPSY
		rgcpfirstnew ! dlnew = cp;
		rgcplastnew ! dlnew = vcplast;
		rgxfirstnew ! dlnew = vxfirst;
		rgxlastnew ! dlnew = vxlast;
		if not ugt(chpleft-bmsize,displaybuf)
			& dlnew gr rgdlfirst ! ww +
					(ww eq mww?1,0) // ** %% // **
			   then

			[ dlnewlast = dlnew-1;
			break;
			] 
		rgpbmnew ! dlnew =
		    (czpbm & ult(vpzone >> ZONE.cfree,displaybuf))?0,
		    hpalloc(bmsize);

		test rgpbmnew ! dlnew ifso 
			[
			makebitmap(dlnew);
			
			chpleft = chpleft-(rgpbmnew ! dlnew - ((offset HP.use)/16)) >>HP.siz;
			] 
		ifnot	[
			(mpdldcb ! dlnew) >> DCB.nwrds = 0;
			czpbm = czpbm+1;
			chpleft = chpleft-bmsize-(vpzone >> ZONE.ovh)
			];

		];
	dlnewlast = dlnew;
	cp = rgcplastnew ! dlnew + 1;
	unless ult(cp,stopcp) do break; // ** was rgmaccp
	]; // end for

updateww: // Breakpoint for debugging.

for dl = dlold to rgdllast ! ww do freedl(dl);

rgdllast ! ww = dlnewlast;
for dlnew = dlnewlast+1 to (rgmaxdl ! ww)-1 do
	makeclearbitmap(dlnew);

if pbmfirstfree then
	[
	if pbmfirstfree eq (mpdldcb ! dlfirstfree) >> DCB.sa then
		(mpdldcb ! dlfirstfree) >> DCB.nwrds = 0;
	hpfree(pbmfirstfree);
	pbmfirstfree = 0;
	];

let dlfirst = rgdlfirst ! ww;
let dlrange = rgdllast ! ww - dlfirst + 1;

move(lv (rgxfirstnew ! dlfirst),lv (rgxfirst ! dlfirst),dlrange);
move(lv (rgcpfirstnew ! dlfirst),lv (rgcpfirst ! dlfirst),dlrange);
move(lv (rgcplastnew ! dlfirst),lv (rgcplast ! dlfirst),dlrange);
move(lv (rgxlastnew ! dlfirst),lv (rgxlast ! dlfirst),dlrange);
move(lv (rgpbmnew ! dlfirst),lv (rgpbm ! dlfirst),dlrange);
move(lv (rgulnew ! dlfirst),lv (rgul ! dlfirst),dlrange); // **
vcompactlock = false;
if czpbm then
	[
recompact:
	compactdisplay();
	for dl = rgdlfirst ! ww to dlnewlast  do
		if rgpbmnew ! dl eq 0 then
			[
			vww = ww;
			let fits = trycpspec(vdoc, rgcpfirstnew ! dl)
//			unless fits do if ww eq mww then // %%
//				[
//				makeroominheap(100)
//				fits=trycpspec(vdoc,rgcpfirstnew ! dl)
//				]
			if fits then
				format(vdoc,rgcpfirstnew ! dl);
			let bmsize = mult(vheight,vwidth);
			rgpbmnew ! dl = not fits? 0,
			    (vdoc eq docsys) % (vdoc eq mdoc) ? 
				hpalloca(bmsize),hpalloc(bmsize);
			rgpbm ! dl = rgpbmnew ! dl;
			if rgpbm ! dl eq 0 then
				[ pbmfirstfree = 1;
				freedl(dlnewlast);
				bmsize = mult(vheight, bitmapwidth(
					rgxfirst!dlnewlast,
					rgxlast!dlnewlast)) // **
				chpleft=chpleft+bmsize+
					vpzone>>ZONE.ovh;
				dlnewlast = dlnewlast-1;
				rgdllast ! ww = dlnewlast;
				goto recompact;
				] 
			rgul ! dl = 0 ; // ** GYPSY
			makebitmap(dl);
			]; // end for dl
	]; // end if

rghpused ! ww = chpleftold-chpleft;
vwwlock = -1;

] // end update window

// F R E E D L

and freedl(dl) be
[
let tpbm = rgpbm ! dl;
if tpbm eq 0 then return;
test pbmfirstfree ifso
	[
	hpfree(tpbm);
	if tpbm eq (mpdldcb ! dl) >> DCB.sa then
		(mpdldcb ! dl) >> DCB.nwrds = 0;
	]
ifnot
	[
	pbmfirstfree = tpbm;
	dlfirstfree = dl;
	];

] // end freedl

// U P D A T E D I S P L A Y
// SPE catalogue no.

and updatedisplay() be
[
unless vinsertk do // ** For speed, and also prevents scratch file mess
for ww = 2 to macww-1 do if rgdoc!ww ne rgdoc!(ww-1) then // **
	if ((rgview ! (rgdoc ! ww)) & looktrailermask) ne 0 then
		enpspecs(unparsespec, rgdoc!ww)
gcspecs() // **
for ww = 0 to macww-1 do
	if rgupdate ! ww then 
		[
		rgupdate ! ww = false;
		establishww(ww);
		updatewindow(ww);
		];
vturning = false
gcspecs() // **
] // end updatedisplay

// I N V A L I D A T E D I S P L A Y
// SPE catalogue no.

and invalidatedisplay(doc,cp,dlhint) be
[
fcp = cp;
vdlhint = dlhint;
vinvalidatek = false;
enww(invalidate1,doc);
]

// I N V A L I D A T E D I S P L A Y K
// SPE catalogue no.

and invalidatedisplayk(doc,cp,dlhint) be
[
fcp = cp;
vdlhint = dlhint;
vinvalidatek = true;
enww(invalidate1,doc);
]

// I N V A L I D A T E 1
// SPE catalogue no.

and invalidate1(ww) be
[
unless (vdlhint ge rgdlfirst ! ww) & (vdlhint le rgdllast ! ww)
	& (not ugt(rgcpfirst ! vdlhint,fcp))
	& (not ugt(fcp,rgcplast ! vdlhint)) then
		[
		vdlhint = finddl(ww,fcp);
		vww = ww;
		];

if vdlhint ge 0 then
	[
	rgxlast ! vdlhint = -1;
	rgupdate ! ww = true;
	if (not vinvalidatek) & (fcp ne 0) &
		(vdlhint ne rgdlfirst ! ww) &
		(ult(fcp-1, rgcpfirst ! vdlhint) % // %%
		 backscan(rgdoc ! ww,fcp-1,0,rgcpfirst ! vdlhint)) then
			rgxlast ! (vdlhint-1) = -1;
	];
] // end invalidate1

// I N V A L I D A T E W I N D O W
//
and invalidatewindow(ww) be
[
for dl = rgdlfirst ! ww to rgdllast ! ww do
	rgxlast ! dl = -1;
rgupdate ! ww = true;
]
// I N V A L I D A T E B A N D
//
and invalidateband(doc,cpfirst,cplast) be
[ vcpfirst = cpfirst;
vcplast = cplast;
enww(invalidateband1,doc)
] 
// I N V A L I D A T E B A N D 1
//
and invalidateband1(ww) be
[ 
let dlfrom,dlto = nil,nil;
if ugt(vcpfirst,rgcplast ! (rgdllast ! ww)) %
   ult(vcplast,rgcpfdispl ! ww) then return;
dlfrom = finddl(ww,vcpfirst);
dlto = finddl(ww,vcplast);
if dlto ls 0 then
	dlto = rgdllast ! ww;
if dlfrom ls 0 then
	dlfrom = rgdlfirst ! ww;
unless dlto eq rgdllast ! ww then dlto = dlto+1;
for dl = dlfrom to dlto do
	rgxlast ! dl = -1;
rgupdate ! ww = true;
]

and filldisplay() = valof
[
let doit = false
for ww = 0 to macww-1 do
	if rgdllast!ww ls rgmaxdl!ww - (1+rgcdlblank!ww)
		& ult(rgcplast ! (rgdllast ! ww),
			rgmaccp ! (rgdoc ! ww)-1) then
				[
				rgupdate ! ww = true ;
				doit = true
				]
if doit then updatedisplay() ;
resultis doit
]