// O W I N D O W

get "BRAVO1.DF";
get "CHAR.DF";
get "SELECT.DF";
get "DISPLAY.DF";
get "DOC.DF";
get "VM.DF";
get "rn1.df"
get "com.df"
get "format.df"

// Incoming procedures

external
	[
	HorizScroll
	deactivateomseq
	augmentomseq
	ValidateSel
	deletea
	SetRegionSys
	SplitWw
	stcopy;
	updateunderline
	updatedisplay;
	bravochar;
	endofkeystream;
	puts;
	tsmakegood;
	waitbug;
	setbug;
	formaty;
	min;
	ult;
	invalidatesel;
	docalloc;
	createdoce
	createdocm;
	selectwholeww;
	gets;
	errhlta;
	resetts;
	innum;
	outnum;
	abs;
	nobug;
	underline;
	invalidatewindow;
	freedl;
	stappend;
	ckdoc;
	remakevmtb;
	hpfree;
	confirm;
	deallocfn;
	updatewindow;
	max;
	initCnDcb;
	chaseCnDcb;
	incCnDcb;
	replaceCnDcb;
	BeamLoc;
	ReadClock;
	move;
	array;
	mpDlDld
	splitWindow
	insertWindow
	deleteWindow
	updateDlMaps
	]

// Incoming statics

external
	[
	vybot
	comno;
	tsread;
	chcom;
	fnts;
	sbstate;
	rgcpfirst;
	vdl;
	vww;
	selmain;
	tscorrect;
	macww;
	rgyfirst;
	pbmfirstfree;
	rgpctb;
	rgmaccp;
	rgcfn;
	mpfnof;
	macbp;
	rgvpa;
	rglastused;
	mpWwWwd;
	vYdofDl;
	vRtcVertInt;
	vfVertInt;
	SDld;
	dcpendofdoc
	vxleftmargstd
	vytop
	vymid
	]

// Outgoing procedures

external
	[
	owindowcommands;
	pointww;
	ydToDcbPrev
	FWwSys
	MoveWwSys;
	]

// Outgoing statics

external
	[
	vfRemove;
	]

// Outgoing statics

static
	[
	vfRemove;
	]

manifest [ 
	mergelower = 13;
	] 

// W I N D O W C O M M A N D S 
//
let owindowcommands(cf) = valof
[ 
let sel = cf>>CF.sel
let dydReplace,fMergeLower,wwFirst,wwLast = 0,false,nil,nil
let ab,tab = nil,nil
let cwwGroup,wwNextGroup,wwEndofGroup = nil,nil,nil
let wgd = vec lwgd
let fgroup = nil
let dYd = nil
let wwdPrev,twwd,wwgroup,wwNext = nil,nil,nil,nil
let wwd = nil
let dcbFirst = nil; let dcbMac = nil; let dcbPrev = nil
let cnDcbOld = vec lCnDcb; let cnDcbNew = vec lCnDcb
let dcbWw = nil; let dcbWw1 = nil;
let yloc = nil;
let closest = nil;
let tdoc = nil;let docWw = nil
let wwclosest = nil;
let tchar = nil;
let ppctb = nil;
let tww = nil;
let tcp = nil;
let wwselm = nil;
let bugval = 7
let tDlist = array(maxcdcb*dcbl+1)
if tDlist<<odd then tDlist = tDlist+1
let rgwcom = table [ 
	0;0;0;$m;0;$n;$s;0;0;0;0;$d;0;$d;$c;0 ] 
test tsread ifnot
	[ 
	while (bugval eq 7) & endofkeystream() do bugval = rv(bug) & 7
	test bugval eq 7 ifso 
		tchar = bravochar();
	ifnot	[ if chcom eq $k then bugval = bugval+8;
		tchar = rgwcom ! bugval;
		puts(fnts,tchar);
		tsmakegood();
		] 
	] 
ifso	tchar = bravochar();
if tchar eq ctrlc then
	[
	ab<<AB.crid = 1		//Command terminated
	ab<<AB.nrid = 1
	resultis ab
	]
if tchar ge $A & tchar le $Z then tchar = tchar+#40
let wwdNext = nil
if chcom eq $k & bugval eq mergelower then fMergeLower = true
underline(uloff,sel)
updateunderline()
switchon tchar into
	[
case $s:
	SetRegionSys(risysstate,103)	//Split window;
	updatedisplay( );
	if macww+1 gr maxww then
		[ ab<<AB.crid = 2		//Out of windows
		ab<<AB.nrid = 10
		resultis ab
		]
	tab = pointww($s,lv yloc)
	if tab ne abnil resultis tab
	tcp = rgcpfirst ! vdl;
	tww = vww;
	wwd = mpWwWwd!tww
	wwNext = tww + 1
	yloc = min(yloc,(rgyfirst!wwNext-dYdWwMin))
	wgd>>WGDTABLE.cww = 1
// 	wgd = FillInWgd(wgd,1,yloc,(rgyfirst!wwNext-yloc),
// 		wwd>>WWD.doc,tcp,0,wwd>>WWD.fHd,wwd>>WWD.mag,
// 		wwd>>WWD.xdUd)
	wgd = FillInWgd(wgd,1,yloc,(rgyfirst!wwNext-yloc),
		wwd>>WWD.doc,tcp,0,wwd>>WWD.fHd,100,
		wwd>>WWD.xdUd)
	SplitWw(yloc,wgd,wwNext+1)
	wwd = mpWwWwd!vww
	wwdPrev = mpWwWwd!(vww-1)
	wwd>>WWD.wwgroup = wwdPrev>>WWD.wwgroup
	if (sel>>SEL.ww eq tww) & not ult(sel>>SEL.cpfirst,tcp) then
		sel>>SEL.ww = tww+1;
	invalidatesel(sel);
	goto lmove1;
	
case $n:
	SetRegionSys(risysstate,106)	//New window;
	updatedisplay( );
	if macww+2 gr maxww then
		[ ab<<AB.crid = 2		//Out of windows
		ab<<AB.nrid = 10
		resultis ab
		]
	tab = pointww($n,lv yloc)
	if tab ne abnil then resultis tab
// system window
	tdoc = docalloc();
	if (tdoc eq -1) then 
		[
		ab<<AB.crid = 2		//Out of documents -
		ab<<AB.nrid = 2
		resultis ab
		];
	tww = vww
	if FWwSys(tww) then
		[ yloc = rgyfirst!tww-1
		formaty(yloc)
		tww = vww
		]
	cwwGroup = CwwInWgd(tww)
	wwEndofGroup = (mpWwWwd!tww)>>WWD.wwgroup+cwwGroup-1
	if wwEndofGroup gr tww then 
		deleteWindow(tww+1,wwEndofGroup-tww)
	yloc = min(yloc,(rgyfirst!(tww+1)-dydsysww-dYdWwMin))
	createdocm(tdoc)
	wgd>>WGDTABLE.cww = 2
	wgd = FillInWgd(wgd,1,yloc,dydsysww,tdoc,0,1,false,100,vxleftmargstd rshift 5)
// document window
	tdoc = docalloc()
	if (tdoc eq -1) then 
		[
		ab<<AB.crid = 2		//Out of documents -
		ab<<AB.nrid = 2
		resultis ab
		];
	createdocm(tdoc);
	wwNext = tww + 1
	wgd = FillInWgd(wgd,2,yloc+dydsysww,(rgyfirst!wwNext-yloc-
		dydsysww),tdoc,0,0,false,100,vxleftmargstd rshift 5)
	SplitWw(yloc,wgd,wwNext+2);
	(mpWwWwd!(vww-1))>>WWD.wwgroup = vww - 1
	(mpWwWwd!vww)>>WWD.wwgroup = vww - 1
	(mpWwWwd!vww)>>WWD.fDirty = false;
	selectwholeww(sel,vww);
	goto lmove1;
	
case $m:
lmove:
	SetRegionSys(risysstate,112)	//Move boundary;
	updatedisplay( );
	unless waitbug() then 
		[
		ab<<AB.crid = 1	//Command terminated
		ab>>AB.nrid = 1
		resultis ab
		]
setbug(sreset);

lmove1:	closest = 10000;
	test tsread ifso
		[ 
		let tchar = gets(fnts);
		test tchar eq chat ifso
			[ tchar = gets(fnts);
			unless tchar eq $E do errhlta(73);
			resetts();
			tsread = false;
			tscorrect = false;
			] 
		ifnot	[ 
			rv(ybugloc) = innum(fnts,8);
			] 
		] 
	ifnot
		[ puts(fnts,$y);
		outnum(fnts,rv ybugloc,8);
		puts(fnts,$,);
		tsmakegood();
		] 
	yloc = rv ybugloc;
	for ww = 1 to macww do
		[ dYd = rgyfirst ! ww-yloc
		if abs(dYd) ls closest then
			[
			closest = abs(dYd);
			wwclosest = ww;
			];
		] 
	if wwclosest eq macww resultis abnil
	wwFirst = wwclosest; wwLast = wwclosest
	if FWwSys(wwclosest-1) then wwFirst = max(1,wwclosest-1)
	if FWwSys(wwclosest) then wwLast = min(macww,wwclosest+1)
		[ 
		test tsread ifso
			[ 
			let tchar = gets(fnts);
			test tchar eq chat ifso
				[ tchar = gets(fnts);
				unless tchar eq $E do errhlta(73);
				resetts();
				tsread = false;
				tscorrect = false;
				] 
			ifnot	[ 
				rv(ybugloc) = innum(fnts,8);
				] 
			] 
		ifnot	if nobug( ) then
			[ puts(fnts,$y);
			outnum(fnts,rv ybugloc,8);
			puts(fnts,$,);
			tsmakegood();
			break;
			] 
		yloc = (rv ybugloc);
		MoveWws(wwFirst,wwLast,yloc,tDlist)
		if tsread then break;
		] repeat
	until vfVertInt then loop
	underline(ulmode1,sel)
	updateunderline()
	resultis abnil
case $c:
	SetRegionSys(risysstate,104)	//Clear window;
	updatedisplay( );
	tab = pointww($c, lv yloc)
	if tab ne abnil do
		resultis tab
	tww = vww;
	wwd = mpWwWwd ! tww
	deletea(wwd>>WWD.doc,0,rgmaccp!(wwd>>WWD.doc)-
		dcpendofdoc-1)
	cwwGroup = CwwInWgd(tww)
	wwFirst = wwd>>WWD.wwgroup
	wwd = mpWwWwd ! wwFirst
	deletea(wwd>>WWD.doc,0,rgmaccp!(wwd>>WWD.doc)-
		dcpendofdoc-1)
	wwLast = wwFirst + cwwGroup
	for tww = wwFirst to wwLast do
		[
		wwd = mpWwWwd ! tww
		wwd>>WWD.fDirty = false
		wwd>>WWD.cpFDispl = 0
		wwd>>WWD.fHd = false
// 		wwd>>WWD.mag = 100
		wwd>>WWD.xdUd = xleftmargstd rshift 5
		invalidatewindow(tww);
		]
	selectwholeww(sel,vww);
	underline(ulmode1,sel)
	updateunderline()
	resultis abnil
case $d:		//WWGROUP THRU WWENDOFGROUP DESTROYED
	SetRegionSys(risysstate,107)	//Destroy window;
	updatedisplay();
	tab = pointww($d, lv yloc)
	if tab ne abnil do
		resultis tab
	tww = vww;
// special case #4027 - don't want huge system window
	if tww le wwsys+2 then fMergeLower = true
	cwwGroup = CwwInWgd(tww)
	test FWwSys(tww) % cwwGroup eq 2 ifso	//whole group
		[
		wwd = mpWwWwd!tww
		wwgroup = wwd>>WWD.wwgroup
		dcbWw = wwd>>WWD.dcbFirst
		wwEndofGroup = wwgroup + cwwGroup - 1
		DestroyDoc( (mpWwWwd!wwgroup)>>WWD.doc )
		DestroyDoc( (mpWwWwd!wwEndofGroup)>>WWD.doc )
		]
	ifnot	[			//single window
		wwgroup = tww
		wwEndofGroup = tww
		wwd = mpWwWwd!tww
		if wwd>>WWD.wwgroup eq tww - 1 then
			fMergeLower = true	//1st user window
		dcbWw = wwd>>WWD.dcbFirst
		]		
	yloc = rgyfirst ! wwgroup
	wwNextGroup = wwEndofGroup + 1
	if fMergeLower & wwNextGroup eq macww then
		fMergeLower = false
	if sel>>SEL.ww ge wwNextGroup then
		sel>>SEL.ww = sel>>SEL.ww-(wwNextGroup-wwgroup);
	wwdNext = mpWwWwd!wwNextGroup
	dcbWw1 = wwdNext>>WWD.dcbFirst

	dcbPrev = ydToDcbPrev(yloc,@lvCnDcbRoot)
	dcbFirst = dcbPrev>>DCB.next
	dcbMac = dcbWw1

	initCnDcb(cnDcbOld,dcbFirst,1)
	until (cnDcbOld>>CNDCB.dcbLast)>>DCB.next eq dcbMac do
		chaseCnDcb(cnDcbOld,1)
	initCnDcb(cnDcbNew,0,0)
	[ let dcb = dcbFirst
		until dcb eq dcbMac do
		[ dydReplace = dydReplace + (dcb>>DCB.slc) lshift 1
		dcb = dcb>>DCB.next
		]
	]
	incCnDcb(cnDcbNew,0,dydReplace,0,0,0)
	replaceCnDcb(cnDcbOld,cnDcbNew,dcbPrev,yloc)
// 	for ww = wwgroup to wwEndofGroup do
// 		(mpWwWwd!ww)>>WWD.hpUsed = 0
// 	for dl=wwd>>WWD.dlFirst to (mpWwWwd!(wwEndofGroup))
// 			>> WWD.dlLast do
// 		[ let dld = mpDlDld(dl)
// 		pbmfirstfree = 1; freedl(dl,dld);
// 		]
// 	[ let dlMacWw = wwdNext>>WWD.dlFirst
// 	let dlFirst = wwd>>WWD.dlFirst
// 	let dDlMac = dlFirst-dlMacWw
// 	test  (wwgroup ls macww-1) ifso
// 		updateDlMaps(wwgroup,dlFirst,0,dlMacWw,dlFirst)
// 	ifnot	dDlMac = 0
// 	let cWwDeleted = wwNextGroup-wwgroup
// ****** deletewindow has all this commented code now *****
	deleteWindow(wwgroup,wwNextGroup-wwgroup)
// 	for ww = wwgroup to macww-1 do
// 		[
// 		let wwd = mpWwWwd ! ww
// 		wwd>>WWD.dlFirst = wwd>>WWD.dlFirst+dDlMac
// 		wwd>>WWD.dlLast = wwd>>WWD.dlLast+dDlMac
// 		] 
// 	] 
	if fMergeLower then
		[ let cwwMove = (cwwGroup le 2) ? 1,0
		MoveWws(wwgroup,wwgroup+cwwMove,yloc,tDlist)
		]
	updatewindow(wwgroup-1)
	unless wwgroup eq macww then updatewindow(wwgroup)
	ValidateSel(sel)
	underline(ulmode1,sel)
	updateunderline()
	resultis abnil
case $e:
	SetRegionSys(risysstate,205)	//horiz scroll
	updatedisplay()
	augmentomseq("M*140")
	ab = HorizScroll(cf)
	deactivateomseq("M*140","M*140")
	resultis abnil
case ctrlf:
	resultis abnil
default:
	goto wcabort;
	];
wcabort:
	underline(ulmode1,sel)
	updateunderline()
	ab<<AB.crid = 2		//Illegal window command - 
	ab<<AB.nrid = 4
	resultis ab
] 

// P O I N T W W
//
and pointww(charcom,lvyloc) = valof
[ let ab,trid = nil,nil
let yloc,tww = nil,nil
let cgroups = 0
let cww = nil
// supposed to have all special cases of pointing at windows
// basically:
//	CLEAR - if group dirty then ask for confirm
//	DESTROY - if one user window & its dirty then ask
//		if >1 & its dirty go ahead
//	KILL - if group is dirty then ask
//	SPLIT - can't split a system window
//	NEW - case in owindowcoms takes care of boundary probs

if charcom eq $c % charcom eq $d then
	[
	for tww = 0 to macww do
		if FWwSys(tww) do cgroups = cgroups + 1
	if cgroups le 3 then 
		[ vww = 2
		cww = CwwInWgd(vww)
		test charcom eq $c ifso
			resultis (CleanWindow(charcom,vww))
// can't destroy single user window
		ifnot	if cww eq 2 then
			[ ab<<AB.crid = 2
			ab<<AB.nrid = 6
			resultis ab
			]
		]
	]
if charcom eq $c % charcom eq $d then 
	[ trid = ((charcom eq $c) ? 104, 107)
	SetRegionSys(risysstate,trid,113)	//Select window
	updatedisplay()
	]
unless waitbug() then 
	[ ab<<AB.crid = 1	//Command terminated
	ab<<AB.nrid = 1
	setbug(sreset)
	resultis ab
	]
yloc = rv ybugloc
unless (yloc gr rgyfirst ! 0) & (yloc ls rgyfirst ! macww) then
	[ ab<<AB.crid = 2		//Mouse out of bounds
	ab<<AB.nrid = 0
	resultis ab 
	] 
@lvyloc = yloc
formaty(yloc)
tww = vww
if yloc ls rgyfirst ! 1 % (FWwSys(tww) & charcom eq $s) then
	[ ab<<AB.crid = 2	//Illegal request for system window
	ab<<AB.nrid = 8
	resultis ab
	] 
if charcom eq $s % charcom eq $n resultis abnil
resultis (CleanWindow(charcom,vww))
] 



// C L E A N W I N D O W 
//
and CleanWindow(char,ww) = valof
[ let cww = CwwInWgd(ww)
let tww = ww
if FWwSys(ww) then tww = ww+1	// concerned about user window
// destroy - ask when one copy and it's dirty
if ( (char eq $d & cww le 2) % (chcom eq $k & FWwSys(ww)) )
	& ((mpWwWwd ! tww)>>WWD.fDirty) & not confirm(" ") do 
	[ vww = ww
	resultis abmsg
	]
// clear - ask when any group window is dirty
if char eq $c & ((mpWwWwd ! tww)>>WWD.fDirty) & not confirm(" ") do
	[ vww = ww
	resultis abmsg
	]
vww = ww
resultis abnil
] 

// M O V E B O U N D A R Y
//
and moveBoundary(dlist,ww,newYdFirst,fgroup) be
[ let dYd = (newYdFirst-rgyfirst ! ww+1) & (-2)
let magDYd = abs(dYd)
if magDYd ls 2 then return
let ty1,ty2,wwShrink,wwGrow,wwfirst,wwlast = nil,nil,nil,nil,nil,nil
// two types of boundaries - system on top of user, and two users
// check crossings and find shrinking and growing windows
test fgroup ifso				// system window
	[
	test dYd ls 0 ifso			// up
		[
		ty1 = rgyfirst!(ww-1) + dYdWwMin
		ty2 = rgyfirst!(ww) + dYd
		if ty2 ls ty1 then return
		wwShrink = ww - 1
		wwGrow = ww + 1
		]
	ifnot	[			// down
		ty1 = rgyfirst!(ww+2) - dYdWwMin
		ty2 = rgyfirst!ww + dYd
LMOVE:		if ty2 gr ty1 then return
		wwShrink = ww + 1
		wwGrow = ww - 1
		]
	wwfirst = ww ;	wwlast = ww + 1
	]

ifnot	[				// user window
	test dYd ls 0 ifso			// up
		[
		ty1 = rgyfirst!(ww-1) + dYdWwMin
		ty2 = rgyfirst!ww + dYd
		if ty2 ls ty1 then return
		wwShrink = ww - 1
		wwGrow = ww
		]
	ifnot	[			// down
		ty1 = rgyfirst!(ww+1) - dYdWwMin
		ty2 = rgyfirst!ww + dYd
		if ty2 gr ty1 then return
		wwShrink = ww
		wwGrow = ww - 1
		]
	wwfirst = ww;	wwlast = ww
	]
let cnDcbOldShrink = vec lCnDcb; let cnDcbNewShrink = vec lCnDcb
let cnDcbOldGrow = vec lCnDcb; let cnDcbNewGrow = vec lCnDcb
let ydOfDcb = 0
// dYd ls 0 means up; dyd gr 0 means down
// have to check for system window, and keep its width constant
let ydShrink = rgyfirst ! (wwShrink+1)-magDYd
initCnDcb(cnDcbNewShrink,0,0)
let dcbPrevShrink = nil
test wwShrink eq macww ifnot
	[ dcbPrevShrink = ydToDcbPrev(ydShrink,dlist,lv ydOfDcb)
	initCnDcb(cnDcbOldShrink,dcbPrevShrink>>DCB.next,1)
	let dcbWwNext = (mpWwWwd ! (wwShrink+1))>>WWD.dcbFirst
	until (cnDcbOldShrink>>CNDCB.dcbLast)>>DCB.next eq dcbWwNext do
		chaseCnDcb(cnDcbOldShrink,1)
	let dYdSlop = ydShrink-ydOfDcb
	unless dYdSlop eq 0 then
		incCnDcb(cnDcbNewShrink,0,dYdSlop,0,0,
			(mpWwWwd!wwShrink)>>WWD.bw)
	] 
ifso	initCnDcb(cnDcbOldShrink,0,0)
let ydGrow = rgyfirst ! (wwGrow+1)
initCnDcb(cnDcbOldGrow,0,0)
initCnDcb(cnDcbNewGrow,0,0)
let dcbPrevGrow = nil
unless wwGrow eq macww then
	[ dcbPrevGrow = ydToDcbPrev(ydGrow,dlist)
	incCnDcb(cnDcbNewGrow,0,magDYd,0,0,
			(mpWwWwd!wwGrow)>>WWD.bw)
	] 
replaceCnDcb(cnDcbOldGrow,cnDcbNewGrow,dcbPrevGrow,ydGrow)
replaceCnDcb(cnDcbOldShrink,cnDcbNewShrink,dcbPrevShrink,ydOfDcb)
for tww = wwfirst to wwlast do
	rgyfirst!tww = rgyfirst!tww + dYd
] 

// Y D T O D C B P R E V
//
and ydToDcbPrev(yd,dlist,lvYdOfDcb; numargs na) = valof
[ let cnDcb = vec lCnDcb
initCnDcb(cnDcb,dlist,1)
let dcbNext = (dlist)>>DCB.next
until (dcbNext eq 0) % ((cnDcb>>CNDCB.dYd+(dcbNext>>DCB.slc lshift 1)) gr yd) do
	[ chaseCnDcb(cnDcb,1)
	dcbNext = (cnDcb>>CNDCB.dcbLast)>>DCB.next
	] 
unless na ls 3 then @lvYdOfDcb = cnDcb>>CNDCB.dYd
resultis cnDcb>>CNDCB.dcbLast;
] 

// C O P Y D L I S T
//
and copyDlist(dlistDest,dlistSrc) be
[ let dcbSrc = dlistSrc; let dcbDest = dlistDest
move(dcbSrc,dcbDest,dcbl)
	[ dcbSrc = dcbSrc>>DCB.next
	if dcbSrc eq 0 then break
	dcbDest = dcbDest+dcbl
	move(dcbSrc,dcbDest,dcbl)
	(dcbDest-dcbl)>>DCB.next = dcbDest
	] repeat
dcbDest>>DCB.next = 0;
] 

// C W W I N W G D
and CwwInWgd(ww) = valof
[
let wwGroup = (mpWwWwd!ww)>>WWD.wwgroup
let tww = wwGroup
while (mpWwWwd!tww)>>WWD.wwgroup eq wwGroup do
	tww = tww + 1
resultis (tww-wwGroup)
]

// F W W S Y S
and FWwSys(ww) = valof
[ test ww eq (mpWwWwd!ww)>>WWD.wwgroup
	ifso resultis true
	ifnot resultis false
]

// M O V E W W S
and MoveWws(wwFirst,wwLast,ydFirstNew,tDlist) be
[
let dyd = ydFirstNew - rgyfirst!wwFirst
if abs(dyd) ls dYdWwMin then return
let wwShrink = (dyd ls 0) ? wwFirst-1,wwLast
//let dydWwShrink = 0
//let dcb = (mpWwWwd!wwShrink)>>WWD.dcbFirst
//let dcbMac = (mpWwWwd!(wwLast+1))>>WWD.dcbFirst
//until dcb eq dcbMac do
//	[ dydWwShrink = dydWwShrink + (dcb>>DCB.slc) lshift 1
//	dcb = dcb>>DCB.next
//	]
//if wwShrink ne macww & (abs(dyd) gr (dYdWwMin +dydWwShrink )) then
//	dyd = dydWwShrink - dYdWwMin
//if dyd eq 0 return

let ydMax,dlist,fgroup = nil,nil,true
test dyd ls 0 ifso
	[ ydMax = rgyfirst!wwShrink + dYdWwMin
	if rgyfirst!wwFirst eq ydMax then return
	if ydFirstNew ls ydMax then ydFirstNew = ydMax
	]
ifnot	[ ydMax = rgyfirst!(wwLast+1) - dYdWwMin
	if rgyfirst!wwLast eq ydMax then return
	if ydFirstNew ge ydMax then ydFirstNew = ydMax
	if wwFirst ne wwLast then ydFirstNew = ydFirstNew - dydsysww
	]
copyDlist(tDlist,@lvCnDcbRoot)
dlist = @lvCnDcbRoot
@lvCnDcbRoot = tDlist
vfVertInt = false
until vfVertInt then loop
if wwFirst eq wwLast then fgroup = false
if (mpWwWwd!wwLast)>>WWD.wwgroup eq wwLast then fgroup = true
moveBoundary(dlist,wwFirst,ydFirstNew,fgroup)
@lvCnDcbRoot = dlist
vfVertInt = false
updatewindow(wwFirst-1)
unless wwFirst eq macww then updatewindow(wwFirst)
unless wwLast ge macww then updatewindow(wwLast)
underline(ulmode1,selmain);

]


and DestroyDoc(doc) be
[
let pctb = rgpctb!doc
hpfree(pctb)
rgpctb!doc = -1
rgmaccp!doc = 0
]


and FillInWgd(wgd,i,ydFirst,dyd,doc,cpFDispl,bonw,fHd,mag,xdUd) = valof
[
wgd>>WGDTABLE.ydFirst↑i = ydFirst
wgd>>WGDTABLE.dyd↑i = dyd
wgd>>WGDTABLE.doc↑i = doc
wgd>>WGDTABLE.cpFDispl↑i = cpFDispl
wgd>>WGDTABLE.bonw↑i = bonw
wgd>>WGDTABLE.fHd↑i = fHd
wgd>>WGDTABLE.mag↑i = mag
wgd>>WGDTABLE.xdUd↑i = xdUd
resultis wgd
]

// M O V E W W S Y S
//
and MoveWwSys() be
[ let tDlist = array(maxcdcb*dcbl+1)
if tDlist<<odd then tDlist = tDlist+1
let ydFirstNew = vfRemove ? vytop+4, vymid+dydsysww;
vfRemove = not vfRemove;
if (ydFirstNew+dydsysww) ge rgyfirst ! 3 then return
MoveWws(1,2,ydFirstNew,tDlist);
]