// xupdate.sr


get "DISPLAY.DF"
get "BRAVO1.DF"
get "HEAP.DF"
get "MSG.DF"
get "SELECT.DF"
get "DOC.DF"
get "ALTOFILESYS.D"
get "FONT.DF"


// Incoming procedures

external
[
initCnDcb
mpDlDld
drawcaret
ult
dlToDisplay
LruInc
format
mult
hpalloc
makebitmap
hpfree
chaseCnDcb
decCnDcb
incCnDcb
replaceCnDcb
compactdisplay
hpguarantee
hpalloca
enww
ugt
finddl
forwardscan
move
]


// Incoming statics

external
[
vfIniting
mpWwWwd
vpzone
rgyfirst
SDldNew
vdoc
vselcaret
rgmaccp
fddlrutimer
vww
vld
pbmfirstfree
macww
fcp
vdlhint
vcpfirst
vcplast
vCnDcbFree
SDld
]


// Outgoing procedures

external
[
updatewindow;
freedl;
updatedisplay;
invalidatedisplay;
invalidatewindow;
invalidateband;
setupdate;
invalidateipar;
mpDldDcbBm;
updateDlMaps;
MoveBoth
//
invalidatedisplayk;
//
resetupdate;
//
updatedisplaycond;
//
updatewindowcond;
]


// Outgoing statics

external
[
rgcpfirst
rgcpfirstnew
vwwlock;
vcompactlock;
]


// Local statics

static
[
rgcpfirst
rgcpfirstnew
vwwlock;
vcompactlock;
dlfirstfree
//
vinvalidatek;
]


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

let updatewindow(ww) be
[
if vfIniting then return
let fIncTimer = true
let wwd = mpWwWwd ! ww
if (wwd>>WWD.dcbFirst)>>DCB.next eq 0 then return
let pbm,heightd,nwrds,tchpleft,xdfirst,bmsize =
nil,nil,nil,nil,nil,nil;
let czpbm = 0;
let cp = wwd>>WWD.cpFDispl;
let dlold = wwd>>WWD.dlFirst;
let chpleft = vpzone >> ZONE.cfree+wwd>>WWD.hpUsed;
let dlnewlast = nil;
let dllast = wwd>>WWD.dlLast;
let xdhd = (wwd>>WWD.xdUd)-xaudleft;
let cnDcbOld = vec lCnDcb
let cnDcbNew = vec lCnDcb
initCnDcb(cnDcbOld,wwd>>WWD.dcbFirst,1)
let upState = vec lUps
upState>>UPS.ydCur = rgyfirst ! ww+2
// 2 for black line
upState>>UPS.ydMacFreed = upState>>UPS.ydCur
let dld = vec lDld
let dldOld = mpDlDld(dlold); let dldNew = SDldNew+lDld*dlold;

vdoc = wwd>>WWD.doc;
vwwlock = ww;
// vupdatemag = vupdatemag % (vmag ne wwd>>WWD.mag)
vcompactlock = true;
let chpleftold = chpleft;

if (vselcaret >> SEL.type eq scaret) & (vselcaret >> SEL.ww eq ww) & (vselcaret >> SEL.toggle eq careton) then
[
drawcaret(ww,vselcaret >> SEL.dl,vselcaret >> SEL.xdfirst);
vselcaret >> SEL.toggle = caretoff;
]
let dlnew = dlold
// dlold = dlFirst
while ult(cp,rgmaccp ! vdoc) do
[
while (dlold le dllast) & ((dldOld>>DLD.xdLast ls 0) %
ult(rgcpfirst ! dlold,cp)) do
[
freedl(dlold,dldOld);
dlold = dlold+1;
dldOld = dldOld+lDld
];
test (dlold le dllast) & (cp eq rgcpfirst ! dlold) ifso
[
// 1
bmsize = ((dldOld>>DLD.pbm)-((offset HP.use)/16)) >> HP.siz;
if fDisplayOflow(ww,chpleft,bmsize,upState>>UPS.ydCur,dldOld>>DLD.dYdBm,dldOld>>DLD.ld) then
//
[ dlnewlast = dlnew-1;
break;
//
];
// 2
chpleft = chpleft-bmsize;
dlToDisplay(cnDcbOld,cnDcbNew,upState,ww,dlnew,dldOld,dldNew,rgcpfirst ! dlold)
dlold = dlold+1;
dldOld = dldOld+lDld
]
ifnot [
if fIncTimer then
[ wwd>>WWD.lru = LruInc(lv fddlrutimer)
fIncTimer = false
]
vww = ww;
dld>>DLD.ul = uloff
format(ww,cp,0,dld);
bmsize = mult(dld>>DLD.nwrds,dld>>DLD.dYdBm);
// 3
// ***or if ydCur+ld+heightd>=ydMax
if fDisplayOflow(ww,chpleft,bmsize,upState>>UPS.ydCur,dld>>DLD.dYdBm,vld) then
// 4
//
[ dlnewlast = dlnew-1;
break;
//
]
pbm = (czpbm & ult(vpzone >> ZONE.cfree, displaybuf)) ? 0,hpalloc(bmsize);

dld>>DLD.pbm = pbm
test pbm ifso
[ makebitmap(dlnew,dld);
chpleft = chpleft-(pbm - ((offset HP.use)/16)) >>HP.siz;
]
ifnot
[
// ***
(mpdldcb ! dlnew) >> DCB.nwrds = 0;
czpbm = czpbm+1;
chpleft = chpleft-bmsize-(vpzone >> ZONE.ovh);
];
dlToDisplay(cnDcbOld,cnDcbNew,upState,ww,dlnew,dld,dldNew,cp)
];
//
dlnewlast = dlnew;
cp = dldNew>>DLD.cpLast+1;
dlnew = dlnew+1
dldNew = dldNew+lDld
if dlnew ge maxdl then break
]

dlnewlast = dlnew-1
// updateww: // Breakpoint for debugging.
let dld = mpDlDld(dlold)
for dl = dlold to dllast do
[ freedl(dl,dld);
dld = dld+lDld
]

wwd>>WWD.dlLast = dlnewlast;
// for dlnew = dlnewlast+1 to (rgmaxdl ! ww)-1 do
//
makeclearbitmap(dlnew);

if pbmfirstfree then
[
let dld = mpDlDld(dlfirstfree)
let dcb = mpDldDcbBm(dld)
if pbmfirstfree eq dcb>>DCB.sa then
dcb >> DCB.nwrds = 0;
hpfree(pbmfirstfree);
pbmfirstfree = 0;
];

let dlfirst = wwd>>WWD.dlFirst;
let dlrange = dlnewlast - dlfirst+1;
// hope this doesn’t execute for out of bounds (ww+1)
let dlMacOld = (mpWwWwd ! (ww+1))>>WWD.dlFirst;
let dlMacNew = dlnewlast+1

updateDlMaps(ww,dlfirst,dlrange,dlMacOld,dlMacNew)

let dDlMac = dlMacNew-dlMacOld
unless dDlMac eq 0 then
for tWw = ww+1 to macww-1 do
[ let wwd = mpWwWwd ! tWw
wwd>>WWD.dlFirst = wwd>>WWD.dlFirst+dDlMac
wwd>>WWD.dlLast = wwd>>WWD.dlLast+dDlMac
]
//
// move(lv (rgxdfirstnew ! dlfirst),lv (rgxdfirst ! dlfirst),dlrange);
// move(lv (rgcpfirstnew ! dlfirst),lv (rgcpfirst ! dlfirst),dlrange);
// move(lv (rgcplastnew ! dlfirst),lv (rgcplast ! dlfirst),dlrange);
// move(lv (rgxdlastnew ! dlfirst),lv (rgxdlast ! dlfirst),dlrange);
// move(lv (rgpbmnew ! dlfirst),lv (rgpbm ! dlfirst),dlrange);
// move(lv (rgheightdnew ! dlfirst),lv (rgheightd ! dlfirst),dlrange);
// move(lv (rgnwrdsnew ! dlfirst),lv (rgnwrds ! dlfirst),dlrange);
// move(lv (mpDlLdNew ! dlfirst),lv (mpDlLd ! dlfirst),dlrange);

vcompactlock = false;
//*** gather up whatever is left at end and replace it with 1 slop dcb
// i.e until we hit first dcb of next ww add then to cnDcbOld
// if cnDcbOld>>CNDCB.cDcb ne 1 or 2 then ...
let wwdNext = mpWwWwd ! (ww+1)
let dcbWwNext = wwdNext>>WWD.dcbFirst
let ydNext = rgyfirst ! (ww+1)
until (cnDcbOld>>CNDCB.dcbLast)>>DCB.next eq dcbWwNext do
chaseCnDcb(cnDcbOld,1)
let dcbPrev = decCnDcb(cnDcbOld)
let ydCur = upState>>UPS.ydCur
test (cnDcbOld>>CNDCB.cDcb gr 1) % (ydCur+cnDcbOld>>CNDCB.dYd ne ydNext) ifso
[ initCnDcb(cnDcbNew,0,0)
if ydCur ls ydNext then
incCnDcb(cnDcbNew,0,ydNext-ydCur,0,0,
(mpWwWwd!ww)>>WWD.bw)
replaceCnDcb(cnDcbOld,cnDcbNew,dcbPrev,upState>>UPS.ydCur)
]
ifnot
(cnDcbOld >> CNDCB.dcbFirst) >> DCB.nwrds = 0
if czpbm then
[
recompact:
compactdisplay();
let dld = mpDlDld(wwd>>WWD.dlFirst)
for dl = wwd>>WWD.dlFirst to dlnewlast do
[ let tpbm = dld>>DLD.pbm
if tpbm eq 0 then
[
vww = ww;
format(ww,rgcpfirstnew ! dl,0,dld);
bmsize = mult(dld>>DLD.dYdBm,dld>>DLD.nwrds);
tpbm = valof
[ if (vdoc eq docsys) then
test hpguarantee(bmsize) ifso
resultis hpalloca(bmsize)
ifnot resultis 0
resultis hpalloc(bmsize);
]
dld>>DLD.pbm = tpbm
if tpbm eq 0 then
[ pbmfirstfree = 1;
let dldLast = mpDlDld(dlnewlast)
freedl(dlnewlast,dldLast);
bmsize = dldLast>>DLD.dYdBm * dldLast>>DLD.nwrds
chpleft = chpleft+bmsize+(vpzone >> ZONE.ovh);
dlnewlast = dlnewlast-1;
wwd>>WWD.dlLast = dlnewlast;
goto recompact;
]
chpleft = chpleft-(bmsize+(vpzone >> ZONE.ovh))+(tpbm - ((offset HP.use)/16)) >> HP.siz;
makebitmap(dl,dld);
let dcb = mpDldDcbBm(dld)
dcb>>DCB.sa = tpbm
dcb>>DCB.nwrds = dld>>DLD.nwrds
]; // end for dl
dld = dld+lDld
]
]; // end if

wwd>>WWD.hpUsed = chpleftold-chpleft;
vwwlock = -1;
] // end update window


// F R E E D L

and freedl(dl,dld) be
[
let tpbm = dld>>DLD.pbm;
if tpbm eq 0 then return;
test pbmfirstfree ifso
[
hpfree(tpbm);
let dcb = mpDldDcbBm(dld)
if tpbm eq dcb >> DCB.sa then
dcb >> DCB.nwrds = 0;
]
ifnot
[
pbmfirstfree = tpbm;
dlfirstfree = dl;
];
] // end freedl


// U P D A T E D I S P L A Y

and updatedisplay() be
[
for ww = 0 to macww-1 do
if (mpWwWwd ! ww)>>WWD.fUpdate then
[
(mpWwWwd ! ww)>>WWD.fUpdate = false;
updatewindow(ww);
];
] // end updatedisplay


// I N V A L I D A T E D I S P L A Y

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
//
// 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

and invalidate1(ww) be
[
let wwd = mpWwWwd ! ww
let dld = mpDlDld(vdlhint)
unless (vdlhint ge wwd>>WWD.dlFirst) & (vdlhint le wwd>>WWD.dlLast)
& (not ugt(rgcpfirst ! vdlhint,fcp))
& (not ugt(fcp,dld>>DLD.cpLast)) then
[
vdlhint = finddl(ww,fcp);
vww = ww;
dld = mpDlDld(vdlhint)
];

if vdlhint ge 0 then
[
dld>>DLD.xdLast = -1;
wwd>>WWD.fUpdate = true;
let dldPrev = dld-lDld
//
if (not vinvalidatek) & (vdlhint ne wwd>>WWD.dlFirst) &
if vdlhint ne wwd>>WWD.dlFirst &
not forwardscan(wwd>>WWD.doc, dldPrev>>DLD.cpLast, fcp, 0) then
dldPrev>>DLD.xdLast = -1;
];
] // end invalidate1


// I N V A L I D A T E W I N D O W

and invalidatewindow(ww) be
[
let wwd = mpWwWwd ! ww; let dld = mpDlDld(wwd>>WWD.dlFirst)
for dl = wwd>>WWD.dlFirst to wwd>>WWD.dlLast do
[ dld>>DLD.xdLast = -1;
dld = dld+lDld
]
wwd>>WWD.fUpdate = 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;
let wwd = mpWwWwd ! ww
if ugt(vcpfirst,(mpDlDld(wwd>>WWD.dlLast))>>DLD.cpLast) %
ult(vcplast,wwd>>WWD.cpFDispl) then return;
dlfrom = finddl(ww,vcpfirst);
dlto = finddl(ww,vcplast);
if dlto ls 0 then
dlto = wwd>>WWD.dlLast;
if dlfrom ls 0 then
dlfrom = wwd>>WWD.dlFirst;
unless dlto eq wwd>>WWD.dlLast then dlto = dlto+1;
let dld = mpDlDld(dlfrom)
for dl = dlfrom to dlto do
[ dld>>DLD.xdLast = -1;
dld = dld+lDld
]
wwd>>WWD.fUpdate = true;
]


// S E T U P D A T E

and setupdate(ww) be
(mpWwWwd ! ww)>>WWD.fUpdate = true;


// R E S E T U P D A T E
//
// and resetupdate(ww) be
//
(mpWwWwd ! ww)>>WWD.fUpdate = false;


// U P D A T E D I S P L A Y C O N D
//
// and updatedisplaycond() be
// [
// for ww = 0 to macww-1 do
//
if (mpWwWwd ! ww)>>WWD.fUpdate then
//
[
//
updatedisplay();
//
return;
//
]
// ]


// U P D A T E W I N D O W C O N D
//
// and updatewindowcond(ww) be
// [
// if (mpWwWwd ! ww)>>WWD.fUpdate then
//
[
//
updatewindow(ww);
//
(mpWwWwd ! ww)>>WWD.fUpdate = false;
//
]
// ]


// I N V A L I D A T E I P A R

and invalidateipar(ipar,doc,cp) = valof
[
test (ipar >> IPAR.doc eq doc) & (not ugt(ipar >> IPAR.cpfirst,cp)) & (not ult(ipar >> IPAR.cplast,cp)) ifso
[ ipar >> IPAR.doc = -1;
resultis true;
]
ifnot
resultis false
]


// F D I S P L A Y O F L O W

and fDisplayOflow(ww,chpleft,bmsize,ydCur,heightd,ld) = valof
[ if (not ugt(chpleft,displaybuf+bmsize+5) & ww ne (mpWwWwd ! ww) >> WWD.wwgroup) %
(ydCur+heightd+ld gr rgyfirst ! (ww+1)) %
(vCnDcbFree>>CNDCB.cDcb ls 5) then resultis true
resultis false;
]


// U P D A T E D L M A P

and updateDlMaps(ww,dlFirst,dDl,dlMacOld,dlMacNew) be
[
let dlMacDisplay = (mpWwWwd ! (macww-1))>>WWD.dlLast+1
if (ww ls macww-1) & (dlMacDisplay gr dlMacOld) then
[ let dDlMac = dlMacDisplay-dlMacOld
MoveBoth(SDld+dlMacNew*lDld,SDld+dlMacOld*lDld,dDlMac*lDld)
MoveBoth(rgcpfirst+dlMacNew,rgcpfirst+dlMacOld,dDlMac)
]
unless dDl eq 0 then
[ move(SDldNew+dlFirst*lDld,SDld+dlFirst*lDld,dDl*lDld)
move(rgcpfirstnew+dlFirst,rgcpfirst+dlFirst,dDl)
]
]


// M O V E B O T H

and MoveBoth(pwto,pwfrom,cw) be
[
test (ult(pwfrom,pwto) & ugt(pwfrom+cw,pwto))
ifso
for i=cw-1 step -1 to 0 do
pwto ! i = pwfrom ! i
ifnot
move(pwfrom,pwto,cw)
]


// M P D L D D C B B M

and mpDldDcbBm(dld) = valof
[
let dcb = dld>>DLD.dcb
if dld>>DLD.ld then
dcb = dcb>>DCB.next
resultis dcb
]


// F I X C N D C B O L D
//
// and fixCnDcbOld(cnDcbOld,ww) be
// [ let dl = rgdllast ! ww-1
// let dcb = mpdldcb ! dl
// if mpDlLd ! dl ne 0 then dcb = dcb>>DCB.next
// let dcbEnd = cnDcbOld>>CNDCB.dcbFirst
// let cDcb = 0; let dYd = 0;
// let dcbFirst = dcb
// until dcb eq dcbEnd do
//
[ cDcb = cDcb+1;
//
dYd = dYd+(dcb>>DCB.slc lshift 1)
//
dcb = dcb>>DCB.next
//
if dcb eq 0 then errhlt("cn")
//
]
// if cDcb gr 3 then errhlt("cdcb")
// cnDcbOld >> CNDCB.dcbFirst = dcbFirst
// cnDcbOld >> CNDCB.cDcb = cnDcbOld >> CNDCB.cDcb+cDcb
// cnDcbOld >> CNDCB.dYd = cnDcbOld >> CNDCB.dYd+dYd
// ]


// deletions:

// 1
//
rgcpfirstnew ! dlnew = rgcpfirst ! dlold;
//
rgcplastnew ! dlnew = rgcplast ! dlold;
//
rgxdfirstnew ! dlnew = rgxdfirst ! dlold;
//
rgxdlastnew ! dlnew = rgxdlast ! dlold;
//
pbm = rgpbm ! dlold;
//
heightd = rgheightd ! dlold;
//
nwrds = rgnwrds ! dlold;
//
rgpbmnew ! dlnew = pbm;
//
rgheightdnew ! dlnew = heightd;
//
rgnwrdsnew ! dlnew = nwrds;
// ***or if ydCur+ld+heightd>=ydMax
//
if (not ugt(tchpleft,displaybuf) & vdoc ne docsys) then
//
[
//
dlnewlast = dlnew-1;
//
break;
//
];
// 1

// 2
//
let pdcb = mpdldcb ! dlnew;
//
pdcb >> DCB.nwrds = nwrds;
//
pdcb >> DCB.htab = max(rgxdfirstnew ! dlnew-xdhd,xaudleft)
//
<< X.wordindex;
//
pdcb >> DCB.sa = pbm;
//
pdcb >> DCB.slc = heightd rshift 1;
// 2

// 3
//
rgcpfirstnew ! dlnew = cp;
//
rgcplastnew ! dlnew = vcplast;
//
rgxdfirstnew ! dlnew = vxdfirst;
//
rgxdlastnew ! dlnew = vxdlast;
//
rgheightdnew ! dlnew = vheightd
//
rgnwrdsnew ! dlnew = vnwrds
// 3

// 4
//
if not ugt(chpleft,displaybuf+bmsize) & vdoc ne docsys then
// 4