-- BeadsNoodles.mesa

--merge should take bw

DIRECTORY IODefs:FROM"IODefs",
SystemDefs:FROM"SystemDefs",
BeadsInlines:FROM"BeadsInlines",
InlineDefs:FROM"InlineDefs",
BeadsDefs:FROM"BeadsDefs";
BeadsNoodles:PROGRAM IMPORTS SystemDefs, BeadsInlines, InlineDefs, IODefs, BeadsDefs
EXPORTS BeadsDefs=
BEGIN OPEN BeadsDefs, BeadsInlines;

Error:SIGNAL=CODE;
NoMoreBeads:SIGNAL=CODE;

noodleChain:POINTER TO ARRAY [0..10000] OF CARDINAL;
noodleDX:POINTER TO ARRAY [0..10000] OF INTEGER;
noodleDY:POINTER TO ARRAY [0..10000] OF INTEGER;
freeNoodleChain:CARDINAL;

KeepMesaHappy:PROCEDURE =BEGIN IODefs.WriteChar[’*]; END;

AllocateNoodles:PUBLIC PROCEDURE=BEGIN OPEN SystemDefs;
noodleChain←AllocateSegment[topNoodle+1];
noodleDX←AllocateSegment[topNoodle+1];
noodleDY←AllocateSegment[topNoodle+1];
END;

FreeNoodles:PUBLIC PROCEDURE=BEGIN OPEN SystemDefs;
FreeSegment[noodleChain];
FreeSegment[noodleDX];
FreeSegment[noodleDY];
END;

StartBentWire:PUBLIC PROCEDURE[ii:CARDINAL,bw:BentWire] =BEGIN OPEN bw;
i:Desc←GetDesc[ii]; wpi:WorkPtr←Getw[i];
IF ~i.p.wire THEN Error;
oldOld← old←topNoodle; this←i.p.noodle;
oldX← firstX← thisX←Lfm[i]-i.p.h; lastX←Rtm[i];
oldY← thisY←wpi.newY;
olddx← olddy←0;
next←IF this#topNoodle THEN noodleChain[this] ELSE topNoodle;
dx←IF this#topNoodle THEN noodleDX[this] ELSE lastX-thisX;
dy←IF this#topNoodle THEN noodleDY[this] ELSE 0;
nextdx←IF this#topNoodle THEN noodleDX[next] ELSE 0;
nextdy←IF this#topNoodle THEN noodleDY[next] ELSE 0;
nextX← thisX+ dx; nextY← thisY+ dy;
done←FALSE;
me←i; lf←DescL[i]; rt←DescR[i];
END;

AdvanceBentWire:PUBLIC PROCEDURE[bw:BentWire] =BEGIN OPEN bw;
oldOld←old; old← this; this← next; next←noodleChain[this];
oldX← thisX; oldY← thisY;
thisX← nextX; thisY← nextY;
olddx←noodleDX[ old]; olddy←noodleDY[ old];
dx←IF this#topNoodle THEN noodleDX[this] ELSE lastX-thisX;
dy←IF this#topNoodle THEN noodleDY[this] ELSE 0;
nextdx←IF this#topNoodle THEN noodleDX[next] ELSE 0;
nextdy←IF this#topNoodle THEN noodleDY[next] ELSE 0;
nextX← thisX+ dx; nextY← thisY+ dy;
END;

FollowShortNoodle:PUBLIC PROCEDURE[i:Desc,call:PROCEDURE[Coord]]= BEGIN
FOR j:CARDINAL←i.p.noodle,noodleChain[j]
UNTIL j=topNoodle DO call[[noodleDX[j],noodleDY[j]]]; ENDLOOP;
END;

FollowNoodle:PUBLIC PROCEDURE[i:Desc,bw:BentWire,call:PROCEDURE]=
BEGIN
StartBentWire[i.z,bw];
UNTIL bw.this=topNoodle OR bw.done DO call[]; AdvanceBentWire[bw]; ENDLOOP;
END;

InitNoodle:PUBLIC PROCEDURE= BEGIN
FOR i:CARDINAL IN [0..topNoodle) DO noodleChain[i]←i+1; ENDLOOP;
freeNoodleChain←0;
END;

GetFreeNoodle:PUBLIC PROCEDURE RETURNS[a:CARDINAL] =BEGIN
a←freeNoodleChain;
IF a>=topNoodle-1 THEN Error;--not enough noodles
freeNoodleChain←noodleChain[a];
END;

ReleaseNoodle:PUBLIC PROCEDURE[a,old:CARDINAL,d:Desc] =BEGIN
next:CARDINAL←noodleChain[a];
IF a>topNoodle THEN Error;
IF a=topNoodle THEN RETURN;
noodleChain[a]←freeNoodleChain;
freeNoodleChain←a;
IF old=topNoodle THEN d.p.noodle←next ELSE noodleChain[old]←next;
END;

IncrementNoodle:PUBLIC PROCEDURE[this:CARDINAL,x,y:INTEGER] =BEGIN
IF this=topNoodle THEN RETURN;
noodleDY[this]←noodleDY[this]+y;
noodleDX[this]←noodleDX[this]+x;
END;

SetNoodle:PUBLIC PROCEDURE[this:CARDINAL,x,y:INTEGER] =
BEGIN noodleDY[this]←y; noodleDX[this]←x; END;

GetNoodle:PUBLIC PROCEDURE[this:CARDINAL] RETURNS[dx,dy:INTEGER,c:CARDINAL] =
BEGIN RETURN[noodleDX[this],noodleDY[this],noodleChain[this]]; END;

InsertNewNoodle:PUBLIC PROCEDURE[this:CARDINAL,bpj:BeadPtr]
RETURNS[new:CARDINAL]=BEGIN
new←GetFreeNoodle[];
IF this=topNoodle
THEN {noodleChain[new]←bpj.noodle; bpj.noodle←new;}
ELSE {noodleChain[new]←noodleChain[this]; noodleChain[this]←new;}
END;

MakeNewNoodle:PUBLIC PROCEDURE[this:CARDINAL,bpj:BeadPtr,x,y:INTEGER]
RETURNS[new:CARDINAL]=
BEGIN new←InsertNewNoodle[this,bpj]; SetNoodle[new,x,y]; END;

MoveJog:PUBLIC PROCEDURE[this:CARDINAL,x,y:INTEGER]=BEGIN
IF this=topNoodle THEN RETURN;
IncrementNoodle[this,x,y];
IncrementNoodle[noodleChain[this],-x,-y];
END;

MergeLeft:PUBLIC PROCEDURE[j,old:CARDINAL]=BEGIN
this:CARDINAL;
--probable error if old=topNodle
this←IF old=topNoodle THEN Get[j].noodle ELSE noodleChain[old];
IF this=topNoodle THEN {IncrementNoodle[old,0,-noodleDY[old]]; RETURN};
IncrementNoodle[old,noodleDX[this],noodleDY[this]];
ReleaseNoodle[this,old,GetDesc[j]];
END;

MergeLPlus:PUBLIC PROCEDURE[bw:BentWire]=BEGIN OPEN bw;
done←TRUE;
IF next=topNoodle
THEN IF old=topNoodle AND nextY ~IN [Bot[rt]..Top[rt]-Height[me]]
THEN IncrementNoodle[this,nextdx,-dy]
ELSE ReleaseNoodle[this,old,me]
ELSE {IncrementNoodle[this,nextdx,nextdy]; ReleaseNoodle[next,this,me]; next←this};
END;

MergeL:PUBLIC PROCEDURE[bw:BentWire]=BEGIN OPEN bw;
IF this=topNoodle
THEN IF oldOld=topNoodle AND thisY ~IN [Bot[rt]..Top[rt]-Height[me]]
THEN IncrementNoodle[old,dx,-olddy]
ELSE ReleaseNoodle[old,oldOld,me]
ELSE {IncrementNoodle[old,dx,dy]; ReleaseNoodle[this,old,me]; this←old};
END;

MergeRight:PUBLIC PROCEDURE[j,old:CARDINAL]=BEGIN
this:CARDINAL←IF old=topNoodle THEN Get[j].noodle ELSE noodleChain[old];
IF this>=topNoodle THEN Error;
MoveJog[this,-noodleDX[this],0];
MoveJog[old,0,noodleDY[this]];
IF old#topNoodle THEN ReleaseNoodle[this,old,GetDesc[j]];
END;

MergeR:PUBLIC PROCEDURE[bw:BentWire]=BEGIN OPEN bw;
IF this>topNoodle THEN Error;
MoveJog[this,-dx,0];
MoveJog[old,0,nextY-thisY];--better not be dy
IF old#topNoodle THEN ReleaseNoodle[this,old,me];
END;

ReleaseLink:PUBLIC PROCEDURE[j,old:CARDINAL]=BEGIN
IF old>topNoodle THEN Error ELSE BEGIN
this:CARDINAL←IF old=topNoodle THEN Get[j].noodle ELSE noodleChain[old];
ReleaseNoodle[this,old,GetDesc[j]];
END; END;

END..