// GLIST.SR	Lists

get "BRAVO.DF"
get "CHAR.DF"
get "GINN.DF"

// Incoming procedures

external
	[
	getint
	binsearcha
	hpfree
	getvch
	putvch
	mapscrcp
	errhlt
	stcopy
	stnum
	stappend
	stsize
	insertstring
	deletea
	hpalloca
	hpalloc
	move
	movec
	enww
	readsel
	stequal
	invalidatedisplay
	receivechange
	backscan
	parsespec
	unparsespec
	min
	cpc
	]

// Incoming statics

external
	[
	rgdlfirst
	rgdllast
	rgmaxdl
	macww
	rgdoc
	vdoc
	vcp
	vchremain
	rgmaccp
	rgcpfdispl
	rgcplast
	vxleftmarg
	vxrightmarg
	cpscrt
	vdlhint
	vinsertk
	mdoc
	umax
	umin
	vwheel
	vlooktrailer
	]

// Outgoing procedures

external
	[
	makelist
	cpadjustlist
	bubblesegs
	growlist
	uadjust
	]

// Outgoing statics


// Local statics

let makelist(siz, segs, prelude, okrobdisplay) = valof
[
let t = (siz*segs) + prelude
let list = okrobdisplay? hpalloca(t), hpalloc(t) ;
movec(list, list + t - 1, 0)
list >> LIST.max = siz ;
list >> LIST.siz = siz ;
resultis list
]

and cpadjustlist(list, evenadjuster, oddadjuster) be
[
unless list do return
let s = list + listbase
let siz = list >> LIST.siz - 1
for i = cpc(vcp,s!1) ls 0 ? 0,binsearcha(s, siz, vcp) to siz do
	test i << odd
	ifso	oddadjuster(s+i)
	ifnot	evenadjuster(s+i)
s ! 0 = 0
]

and bubblesegs(siz, amt, r, v1, v2, v3, v4 ; numargs N) = valof
[
for i = 0 to N-4 do bubbleup(siz-r, amt, ((lv v1)!i)+r)
resultis siz + amt
]

and bubbleup(len, amt, v) be
[
if amt & len then
test amt gr 0
ifso	for i = 1 to len do v ! (len+amt-i) = v ! (len-i)
ifnot	move(v, v+amt, len)
]

and growlist(plist, growamount, spares, nsegs, base) be
[
let list = @plist
let siz = list >> LIST.siz
let lim = list >> LIST.max
let newsiz = siz + growamount
test newsiz le lim
ifso	list >> LIST.siz = newsiz
ifnot	[
	let newlim = newsiz + spares
	let newlist = makelist(newlim, nsegs, listbase, true)
	newlist >> LIST.siz = newsiz
	list = @plist
	if base gr listbase then
		move(list+listbase, newlist+listbase, base-listbase)
	for i = 0 to nsegs-1 do
		move(list+base+i*lim, newlist+base+i*newlim, siz)
	@plist = newlist
	]
]