// B R A C K E T 
// Surrounds the current selection with [,(,{,',",<

get "bravo1.df"
get "com.df"
get "st.df"
get "rn1.df"
get "display.df"
get "select.df"
get "char.df"

//incoming procedures

external	[
	DelInKbdBuf
	bravochar
	putsonts
	umin
	umax
	errhlt
	move
	ugt
	ult
	SetRegionW
	SetRegionSys
	insertc
	setupdate
	setsel
	invalidatesel
	updateunderline
	underline
	getvch
	invalidatedisplay
	invalidateband
	deletea
	mapcp
	]

//outgoing procedure

external 	[
	EncBracket
	Bracket
	]

//incoming statics

external	[
	tsread
	selaux
	vrlwsys
	mpWwWwd
	vdoc
	vcp
	vmapstatus
	rgmaccp
	vundocom
	dcpendofdoc
	vlook1
	vlook2
	]

//local manifest
manifest	[
	statusPut= 1
	statusDel= 2
	statusMatch= 1
	statusUnmatch= 2
	chMatch= $y
	chNoMatch= $n
	chComTerm= chdel
	]

//-=-=-=-=-=-=-=-=-==-
let Bracket(cf) = valof
//-=-=-=-=-=-==-=-=--=
[
//store chcom in w0 for Esc and Undo
//store mode (statusPut,statusDel) in w1
let chcom = cf>>CF.chcom
let w1= cf>>CF.w1
if cf>>CF.frepeat then resultis selecton w1 into
	[
	case statusPut: PutBrackets(cf)
	case statusDel: DelBrackets(cf)
	]
if vundocom then resultis selecton w1 into
	[
	case statusPut: DelBrackets(cf)
	case statusDel: PutBrackets(cf)
	]
resultis PutBrackets(cf)
]
	
//-=-=-=-=-=-=-=-=-=-=-=
and PutBrackets(cf) = valof
//-=-=-=-=-=-=-=-===-=-=

[
let chcom = cf>>CF.chcom
let sbch= vec 1
let sel= cf>>CF.sel
let doc= sel>>SEL.doc
let cpfirst= sel>>SEL.cpfirst
let cplast= sel>>SEL.cplast
let cpMac = umin(cplast+1, rgmaccp!doc - dcpendofdoc)
let trid=0

cf>>CF.w1= statusPut

if cf>>CF.frepeat % vundocom then chcom= cf>>CF.w0
cf>>CF.w0= chcom

unless ult(cpfirst,cpMac) do 
	[
	SetRegionSys(risyspast,39,50)	//sel empty- term
	resultis abmsg
	]

//chcom= selecton chcom into
//	[
//	case $]: $[;
//	case $}: ${;
//	case $>: $<;
//	case $): $(;
//	default: chcom
//	]

sbch>>SB.cch=1
sbch>>SB.ch↑0= selecton chcom into
	[
	case $[: $];
	case ${: $};
	case $<: $>;
	case $(: $);
	default: chcom
	]

vmapstatus = statusblind
mapcp(doc, cpfirst)
let tlook1 = vlook1
let tlook2 = vlook2

insertc(doc, cpMac, sbch, tlook1, tlook2)
sbch>>SB.ch↑0= chcom
insertc(doc, cpfirst, sbch, tlook1, tlook2)

sel>>SEL.cplast=cplast+2

SetRegionW(vrlwsys,0,sbch)
trid<<RID.nrl=1
trid<<RID.ri=0
SetRegionSys(risyspast,25,trid)

resultis abmsg
]


//-=-=-=-=-=-=-=-=-=-=-==-=-=
and DelBrackets(cf) = valof
//-=-=-=-=-=-=-=-=-=-=-=-=-=-

[
let sel= cf>>CF.sel
let doc= sel>>SEL.doc
let cpfirst= sel>>SEL.cpfirst
let cplast= sel>>SEL.cplast
let ww= sel>>SEL.ww
let cpMac= umin (cplast+1, rgmaccp!doc - dcpendofdoc)
let trid=0

cf>>CF.w1= statusDel

unless ult(cpfirst,cpMac-1) do [ SetRegionSys(risyspast,186,50); resultis abmsg ]

vmapstatus= statusblind
vdoc=doc
vcp=cplast

let chmatch= selecton getvch() into
	[
	case $]: $[;
	case $}: ${;
	case $): $(;
	case $>: $<;
	case $': $';
	case $": $";
	default: 0
	]

if chmatch eq 0 then [ SetRegionSys(risyspast,186,50); resultis abmsg ]

vmapstatus=statusblind
vcp= cpfirst

test chmatch eq getvch()
ifso	[
	cf>>CF.w0= chmatch
	deletea(doc,cplast,cplast)
	deletea(doc,cpfirst,cpfirst)
	invalidateband(doc,cpfirst,cplast)
	sel>>SEL.cplast= cplast - 2
	let sbch=vec 1
	sbch>>SB.cch=1
	sbch>>SB.ch↑0=chmatch
	SetRegionW(vrlwsys,0,sbch)
	trid<<RID.nrl=1
	trid<<RID.ri=0
	SetRegionSys(risyspast,25,185,trid)
	(mpWwWwd!ww)>>WWD.fUpdate = true
	resultis abmsg
	]
ifnot [ SetRegionSys(risyspast,186,50); resultis abmsg ]
]

//=--=-=-=-=-=-=-=-=-=-=-==
and EncBracket(cf) = valof
//-=-=-==-=-=-=-=-=-=-=--=-=

[
// mode (statusMatch,statusUnmatch) stored in w1
let w1= cf>>CF.w1
if cf>>CF.frepeat then resultis selecton w1 into
	[
	case statusMatch: MatchBracket(cf)
	case statusUnmatch: UnmatchBracket(cf)
	]
if vundocom then resultis selecton w1 into
	[
	case statusMatch: UnmatchBracket(cf)
	case statusUnmatch: MatchBracket(cf)
	]
resultis MatchBracket(cf)
]


//=--=-=-=-=-=-=-=-=-=-=-==
and MatchBracket(cf) = valof
//-=-=-==-=-=-=-=-=-=-=--=-=

[
let char= nil
let chresult= nil
let cloops= 0
if tsread then
	[
	char= bravochar()
	if char eq chNoMatch then 
		[
		SetRegionSys(risyspast,212,50)
		resultis abmsg
		]
	if char eq chComTerm then 
		[
		SetRegionSys(risyspast,210,50)
		resultis abmsg
		]
	]
cf>>CF.w1= statusMatch
let chr= cf>>CF.chcom
test cf>>CF.frepeat % vundocom 
	ifso chr= cf>>CF.w0
	ifnot [ chr= cf>>CF.chcom; cf>>CF.w0= chr ]

let chl= selecton chr into
	[
	case $): $(;
	case $]: $[;
	case $}: ${;
	case $>: $<;
	default: errhlt("matchbracket")
	]
let cneedl= 0
let cneedr= 0
let sel= cf>>CF.sel
let doc= sel>>SEL.doc
let maccp= rgmaccp!doc - dcpendofdoc
let cpfirst= sel>>SEL.cpfirst
let cplast= sel>>SEL.cplast
let char= nil
let cpl= nil
let cpr= nil

move(sel,selaux,sell)		//selaux used by undo


//count selection - start from left
vmapstatus= statusblind
vdoc= doc
vcp= cpfirst+1
for cp= cpfirst+1 to cplast-1 do
	[ 
	if (cloops & #377) eq 0 then
	 if DelInKbdBuf(true) ne 0 then 
		[
		SetRegionSys(risyspast, 210, 50)
		chresult= chComTerm
		goto lbpts
		]
	cloops= cloops+1
	char= getvch()
	if char eq chl then cneedr= cneedr + 1
	if char eq chr then test cneedr eq 0
		ifso cneedl= cneedl + 1
		ifnot cneedr= cneedr - 1
	]
cneedl= cneedl + 1
cneedr= cneedr + 1

if cpfirst eq cplast then	//special case if one-char [ or ]
	[
	vcp= cpfirst
	vmapstatus= statusblind
	char= getvch()
	if char eq chl then cplast= cpfirst + 1
	if char eq chr then cpfirst= cplast - 1
	]

if OuterMatch(sel,chl,chr) then	//special case if match
	[
	cneedl= cneedl + 1
	cneedr= cneedr + 1
	]

//start at cpfirst(backwards) and cplast(forwards)
//going forwards
vmapstatus= statusblind
vcp= cplast
for cp= cplast to maccp-1 do
	[ 
	if (cloops & #377) eq 0 then
	 if DelInKbdBuf(true) ne 0 then 
		[
		SetRegionSys(risyspast, 210, 50)
		chresult= chComTerm
		goto lbpts
		]
	cloops= cloops+1
	char= getvch()
	if char eq chr then cneedr= cneedr-1
	if char eq chl then cneedr= cneedr+1
	if cneedr eq 0 then 
		[
		cpr= cp
		break
		]
	]
if cneedr ne 0 then  
	[
	chresult= chNoMatch
	SetRegionSys(risyspast,212,50)
	goto lbpts
	]



//going backwards
for cp= cpfirst to 0 by -1 do
	[ 
	if (cloops & #377) eq 0 then
	 if DelInKbdBuf(true) ne 0 then 
		[
		SetRegionSys(risyspast,210,50)
		chresult= chComTerm
		goto lbpts
		]
	cloops= cloops+1
	vmapstatus= statusblind
	vcp= cp
	char= getvch()
	if char eq chl then cneedl= cneedl-1
	if char eq chr then cneedl= cneedl+1
	if cneedl eq 0 then 
		[
		cpl = cp
		break
		]
	]
if cneedl ne 0 then 
	[
	SetRegionSys(risyspast,212,50)
	chresult= chNoMatch
	goto lbpts
	]

setsel(sel,cpl,cpr)
SetRegionSys(risyspast,25,210)
chresult= chMatch

lbpts:
unless tsread do putsonts(chresult)
resultis abmsg
]


//-=-=-=-=-=-==-=-=-=--=
and OuterMatch(sel,chl,chr) = valof
//-=-=-=-=-=-=-=-=-=-=-=-
[
vmapstatus=statusblind
vcp= sel>>SEL.cpfirst
if chl ne getvch() then resultis false
vmapstatus=statusblind
vcp= sel>>SEL.cplast
resultis getvch() eq chr
]

//-=-=-=-=-=-==-=-=-=--=
and UnmatchBracket(cf) = valof
//-=-=-=-=-=-=-=-=-=-=-=-

[
let sel= cf>>CF.sel
SetRegionSys(risyspast,25,211)
invalidatesel(sel)
underline(uloff,sel)
move(selaux,sel,sell)
updateunderline()
resultis abmsg
]