ð1Syntax10.Scn.Fnt·Æ,•JMODULE Mirrors; (* J. Templ 06.02.92 *) (*TD Index returning procedure variables *) IMPORT SYSTEM, Types, Modules, KeplerPorts, Texts, Oberon, KeplerFrames, KeplerGraphs, TextFrames, Viewers, Kepler2, Kepler7, Kepler8, Files, Ref, RefElems, Fonts, Display, In, Input, Out; CONST ML = 2; MM = 1; MR = 0; ArrLen = 24; ArrH = 8; xrec = 0; TYPE Mirror* = POINTER TO MirrorDesc; MirrorDesc* = RECORD (KeplerFrames.ButtonDesc) text*: Texts.Text; margin*, level*: INTEGER; o*: SYSTEM.PTR; END ; Connection* = POINTER TO ConnectionDesc; ConnectionDesc* = RECORD (KeplerGraphs.ConsDesc) yoff*: INTEGER END ; HashTab = POINTER TO ARRAY OF SYSTEM.PTR; Map = RECORD nofobjs: LONGINT; obj: HashTab; primIdx: INTEGER END ; VAR level: INTEGER; W: Texts.Writer; B: KeplerPorts.BalloonPort; fntHeight: INTEGER; primTab: ARRAY 8 OF LONGINT; PROCEDURE OpenConnection(G: KeplerGraphs.Graph; M: Mirror; s2, s3: KeplerGraphs.Star; i: INTEGER); VAR C: Connection; s0, s1: KeplerGraphs.Star; BEGIN s0 := M.p[0]; s1 := M.p[1]; NEW(C); C.nofpts := 3; C.yoff := M.margin + i * fntHeight + fntHeight DIV 2; IF s2 = NIL THEN NEW(s2); IF s3.x > s1.x THEN s2.x := (s1.x + s3.x) DIV 2; s2.y := s3.y ELSE s2.x := s0.x - ArrLen * 2; s2.y := s3.y END ; G.Append(s2); END ; C.p[0] := s0; C.p[1] := s2; C.p[2] := s3; INC(s0.refcnt); INC(s2.refcnt); INC(s3.refcnt); G.Insert(C, G.cons) END OpenConnection; PROCEDURE (C: Connection) Draw* (F: KeplerPorts.Port); VAR x0, x1, x2, y0, y1, y2: INTEGER; BEGIN y0 := C.p[0].y - C.yoff; y1 := C.p[1].y; y2 := C.p[2].y - 1; x0 := C.p[0].x; x1 := C.p[1].x; x2 := C.p[2].x; IF x2 > x1 THEN F.DrawLine(x1, y0, x0, y0, Display.white, Display.replace); F.DrawLine(x1, y0, x1, y2, Display.white, Display.replace); F.DrawLine(x1, y2, x2, y2, Display.white, Display.replace); F.FillQuad(x2 - ArrLen, y2 - ArrH, x2, y2, x2 - ArrLen, y2 + ArrH, x2 - ArrLen, y2, Display.white, 5, Display.replace) ELSIF y0 > y2 THEN F.DrawLine(x1, y0, x0, y0, Display.white, Display.replace); F.DrawLine(x1, y0, x1, y2, Display.white, Display.replace); F.DrawLine(x1, y2, x2, y2, Display.white, Display.replace); F.FillQuad(x1 - ArrH, y2 + ArrLen, x1, y2, x1 + ArrH, y2 + ArrLen, x1, y2 + ArrLen, Display.white, 5, Display.replace) ELSIF x1 > x2 THEN F.DrawLine(x1, y0, x0, y0, Display.white, Display.replace); F.DrawLine(x1, y0, x1, y1, Display.white, Display.replace); F.DrawLine(x1, y1, x2 - 2*ArrLen, y1, Display.white, Display.replace); F.DrawLine(x2 - 2*ArrLen, y1, x2 - 2*ArrLen, y2, Display.white, Display.replace); F.DrawLine(x2 - 2*ArrLen, y2, x2, y2, Display.white, Display.replace); F.FillQuad(x2 - ArrLen, y2 - ArrH, x2, y2, x2 - ArrLen, y2 + ArrH, x2 - ArrLen, y2, Display.white, 5, Display.replace) END END Draw; PROCEDURE Visible(M: Mirror; F: KeplerPorts.Port): BOOLEAN; VAR x0, x1, y0, y1: INTEGER; BEGIN x0 := F.CX(M.p[0].x); y0 := F.CY(M.p[0].y); x1 := F.CX(M.p[1].x); y1 := F.CY(M.p[1].y); RETURN ~((x1 < F.X) OR (x0 > F.X + F.W) OR (y0 < F.Y) OR (y1 > F.Y + F.H)) END Visible; PROCEDURE (M: Mirror) Draw* (F: KeplerPorts.Port); VAR r : Texts.Reader; ch : CHAR; i, xBase, y : INTEGER; curFont : Fonts.Font; curCol, curVoff : SHORTINT; line : ARRAY 256 OF CHAR; BEGIN IF ~(F IS KeplerFrames.Frame) OR Visible(M, F) THEN (* display frame *) Texts.OpenReader(r, M.text, 0); Texts.Read(r, ch); curFont := r.fnt; curCol := r.col; curVoff := r.voff; xBase := M.p[0].x + M.margin; y := M.p[0].y + 12 - M.margin; WHILE ~ r.eot DO y := y - 4 * curFont.height; i := 0; WHILE ~ r.eot & (ch # 0DX) DO IF (ch = Texts.ElemChar) & (r.elem IS RefElems.Elem) THEN (* IF r.elem(RefElems.Elem).p = NIL THEN line[i] := "N"; line[i+1] := "I"; line[i+2] := "L"; INC(i, 3) ELSIF r.elem(RefElems.Elem).proc THEN line[i] := "@"; INC(i) ELSE line[i] := "^"; INC(i) END line[i] := "^"; INC(i); *) ELSE line[i] := ch; INC(i) END ; Texts.Read(r, ch) END ; line[i] := 0X; F.DrawString(xBase, y + curVoff, line, curFont, curCol, Display.paint); IF ~ r.eot THEN Texts.Read(r, ch ) END END END END Draw; PROCEDURE GetMirror(o: SYSTEM.PTR; level: INTEGER; s0: KeplerGraphs.Star; VAR m: Mirror; VAR w, h: INTEGER); VAR R: Ref.Rider; t: Types.Type; (*lobj: Libraries.Object;*) name: ARRAY 32 OF CHAR; BEGIN NEW(m); m.o := o; m.margin := 8; m.level := level; m.p[0] := s0; INC(s0.refcnt); m.text := TextFrames.Text(""); Texts.OpenWriter(W); (* t := Types.Type(o); (*resets mark bit of procedure objects!*) lobj := SYSTEM.VAL(Libraries.Object, o); IF (lobj IS Modules.Procedure) & (level = 0) THEN Texts.WriteString(W, lobj.lib.name); Texts.Write(W, "."); lobj(Modules.Procedure).lib.GetName(lobj(Modules.Procedure).ref, name); Texts.WriteString(W, name); Texts.WriteLn(W) ELSE Ref.OpenRider(R, o); Ref.WriteObj(W, R, level, 0); END ; *) Ref.OpenPtr(o, R); RefElems.WriteRider(W, R, 0); Texts.Append(m.text, W.buf); (* Texts.Delete(m.text, m.text.len-1, m.text.len); (*remove terminating CR *) *) Texts.Delete(m.text, 0, 1); (* remove first CR *) KeplerPorts.InitBalloon(B); m.Draw(B); IF B.W < 0 THEN w := 20*m.margin; h := 5*m.margin ELSE w := B.W + 2*m.margin; h := B.H + 2*m.margin END ; INC(w, -w MOD 4); INC(h, -h MOD 4); w := w + 40 - w MOD 40 END GetMirror; PROCEDURE OpenMirror(G: KeplerGraphs.Graph; M: Mirror; w, h: INTEGER); VAR p1: Kepler2.Offset; aRect: Kepler8.AttrRect; BEGIN NEW(p1); NEW(p1.c); NEW(aRect); M.p[1] := p1; M.nofpts := 2; p1.c.p[0] := M.p[0]; p1.c.nofpts := 1; p1.dx := w; p1.dy := -h; p1.Calc; aRect.nofpts := 2; aRect.p[0] := M.p[0]; aRect.p[1] := p1; aRect.lineWidth := 4; INC(M.p[0].refcnt, 2); p1.refcnt := 2; G.Append(p1); G.Append(aRect); G.Append(M) END OpenMirror; PROCEDURE TheMirror(G: KeplerGraphs.Graph; o: SYSTEM.PTR): Mirror; VAR m: KeplerGraphs.Constellation; BEGIN m := G.cons; WHILE (m # NIL) & (~(m IS Mirror) OR (m(Mirror).o # o)) DO m := m.next END ; IF m = NIL THEN RETURN NIL ELSE RETURN m(Mirror) END END TheMirror; PROCEDURE TheMirrorAt(G: KeplerGraphs.Graph; x, y: INTEGER): Mirror; VAR p0, p1: KeplerGraphs.Star; m: Mirror; c: KeplerGraphs.Constellation; BEGIN c := G.cons; m := NIL; WHILE c # NIL DO IF c IS Mirror THEN p0 := c.p[0]; p1 := c.p[1]; IF (p0.x < x) & (x < p1.x) & (p0.y > y) & (y > p1.y) THEN m := c(Mirror) END END ; c := c.next END ; RETURN m END TheMirrorAt; (* PROCEDURE GetPtr(x: SYSTEM.PTR; VAR field: ARRAY OF CHAR; VAR val: SYSTEM.PTR; VAR i: INTEGER); VAR R: Ref.RecordRider; Rfield: ARRAY 32 OF CHAR; vis: SHORTINT; BEGIN i := 0; Ref.OpenRider(R, x); R.GetLocation(Rfield, vis); WHILE (R.mode # 0) & (Rfield # field) DO INC(i); R.Skip; R.GetLocation(Rfield, vis) END ; IF R.class = Ref.Pointer THEN R.ReadPtr(val) ELSE val := NIL END END GetPtr; *) PROCEDURE GetPtr(x: SYSTEM.PTR; VAR field: ARRAY OF CHAR; VAR val: SYSTEM.PTR; VAR i: INTEGER); VAR R: Ref.Rider; Rfield: ARRAY 32 OF CHAR; (* vis: SHORTINT; *) BEGIN i := 0; Ref.OpenPtr(x, R); WHILE (R.mode # Ref.End) & (R.name # field) DO INC(i); R.Next END ; IF R.form = Ref.Pointer THEN R.ReadPtr(val) ELSE val := NIL END END GetPtr; PROCEDURE TheConnection(G: KeplerGraphs.Graph; m0, m1: Mirror): Connection; VAR c: KeplerGraphs.Constellation; BEGIN c := G.cons; WHILE (c # NIL) & (~(c IS Connection) OR (c(Connection).p[0] # m1.p[0]) OR (c(Connection).p[2] # m0.p[0])) DO c := c.next END ; IF c = NIL THEN RETURN NIL ELSE RETURN c(Connection) END END TheConnection; PROCEDURE Index(VAR R: Ref.Rider; level, idx: INTEGER; VAR at: INTEGER; VAR p: SYSTEM.PTR); VAR R1: Ref.Rider (* RecordRider *); R2: Ref.Rider (* ArrayRider *); BEGIN WHILE (R.mode # Ref.None) & (at < idx) DO IF R.form = Ref.Record THEN INC(at); IF level > 0 THEN R.Zoom(R1); Index(R1, level - 1, idx, at, p); INC(at) END ELSIF R.form = Ref.Array THEN INC(at); IF level > 0 THEN R.Zoom(R2); IF R2.form # Ref.Char THEN Index(R2, level - 1, idx, at, p); INC(at) END END ELSIF R.form < Ref.Array THEN INC(at); IF at = idx THEN IF R.form = Ref.Pointer THEN R.ReadPtr(p) ELSIF R.form = Ref.Procedure THEN p := NIL (* R.ReadProc(p) *) (*TD*) END ; RETURN END END ; IF at >= idx THEN RETURN END ; R.Next END END Index; PROCEDURE Zoom(VAR R: Ref.Rider; F: KeplerFrames.Frame; M: Mirror; x, y: INTEGER; keys: SET); VAR t: Kepler7.Text; BEGIN RefElems.WriteRider(W, R, 0); NEW(t); t.text := TextFrames.Text(""); Texts.Append(t.text, W.buf); KeplerPorts.InitBalloon(B); NEW(t.p[0]); t.p[0].x := x; t.p[0].y := y; t.Draw(B); Oberon.RemoveMarks(F.X, F.Y, F.W, F.H); F.FillRect(B.X - 8, B.Y + B.H - 8, B.W + 16, B.H + 16, Display.black, 5, Display.replace); F.DrawRect(B.X - 8, B.Y + B.H - 8, B.W + 16, B.H + 16, Display.white, Display.replace); INC(t.p[0].y, B.H); t.Draw(F); REPEAT Input.Mouse(keys, x, y); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y) UNTIL keys = {}; F.Restore(F.CX(B.X - 12), F.CY(B.Y + B.H - 12), (B.W + 24) DIV F.scale, (B.H + 24) DIV F.scale) END Zoom; PROCEDURE (M: Mirror) HandleMouse*(F : KeplerFrames.Frame; x, y: INTEGER; keys: SET); VAR n, y0, w, h, last, level: INTEGER; keySum: SET; R, R1: Ref.Rider; (* RecordRider *) R2: Ref.Rider; (* ArrayRider *) t: Types.Type; s2, s, p0, p1: KeplerGraphs.Star; m: Mirror; name: ARRAY 32 OF CHAR; p: SYSTEM.PTR; BEGIN IF (keys = {MM}) & (M.o # NIL) THEN n := (M.p[0].y - y - M.margin) DIV fntHeight; Ref.OpenPtr(M.o, R); last := -1; p := NIL; m := NIL; Index(R, M.level, n, last, p); IF p # NIL THEN m := TheMirror(F.G, p); IF m # NIL THEN F.DrawRect(m.p[0].x - 4, m.p[1].y - 4, m.p[1].x - m.p[0].x + 4, m.p[0].y - m.p[1].y + 4, Display.white, Display.invert) END ; p0 := M.p[0]; p1 := M.p[1]; y0 := p0.y - M.margin - (n+1) * fntHeight; F.DrawRect(p0.x + 4, y0, p1.x - p0.x - 12, fntHeight, Display.white, Display.invert) ELSIF M.level = 0 THEN IF R.form = Ref.Record THEN R.Zoom(R1); Zoom(R1, F, M, x, y, keys); RETURN ELSIF R.form = Ref.Array THEN R.Zoom(R2); IF R2.form # Ref.Char THEN Zoom(R2, F, M, x, y, keys); RETURN END END END ; keySum := keys; REPEAT F.TrackMouse(x, y, keys ); KeplerFrames.GetMouse(F, x, y, keys); keySum := keySum + keys; UNTIL keys = {}; IF p # NIL THEN F.DrawRect(p0.x + 4, y0, p1.x - p0.x - 12, fntHeight, Display.white, Display.invert); IF m # NIL THEN F.DrawRect(m.p[0].x - 4, m.p[1].y - 4, m.p[1].x - m.p[0].x + 4, m.p[0].y - m.p[1].y + 4, Display.white, Display.invert) END ; IF keySum = {ML, MM} THEN keySum := {MM}; level := MAX(INTEGER) ELSE level := 0 END ; IF keySum = {MM} THEN (* track pointer *) Oberon.RemoveMarks(F.X, F.Y, F.W, F.H); IF m = NIL THEN NEW(s); s.x := x; s.y := y; F.G.Append(s); IF Types.TypeOf(p) # NIL THEN GetMirror(p, level, s, m, w, h); OpenMirror(F.G, m, w, h); OpenConnection(F.G, M, NIL, s, n) END ELSIF (x < p0.x) OR (x > p1.x) OR (y > p0.y) OR (y < p1.y) THEN NEW(s2); s2.x := x; s2.y := y; F.G.Append(s2); OpenConnection(F.G, M, s2, m.p[0], n) END END END ; IF keySum = {MM, MR} THEN (*dump value*) Texts.WriteHex(W, SYSTEM.VAL(LONGINT, M.o)); Texts.WriteString(W, "H: "); Ref.OpenPtr(M.o, R); IF R.mode # Ref.End THEN Texts.WriteString(W, R.mod); Texts.Write(W, "."); Texts.WriteString(W, R.name) END ; Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) END END END HandleMouse; (* PROCEDURE NamedObject(name: ARRAY OF CHAR): SYSTEM.PTR; VAR i, j: INTEGER; o: Libraries.Object; ch: CHAR; lib: Libraries.Library; ref: LONGINT; BEGIN i := 0; o := NIL; WHILE name[i] # 0X DO INC(i) END ; WHILE (i > 0) & (name[i] # ".") DO DEC(i) END ; IF i > 0 THEN name[i] := 0X; lib := Modules.ThisMod(name); IF lib # NIL THEN j := 0; REPEAT INC(i); ch := name[i]; name[j] := ch; INC(j) UNTIL ch = 0X; lib.GetRef(name, ref); IF ref >= 0 THEN lib.GetObj(ref, o) END END END ; RETURN o END NamedObject; *) PROCEDURE SetLevel*; BEGIN In.Open; In.Int(level); END SetLevel; PROCEDURE NewMirror*; VAR o: SYSTEM.PTR; s: KeplerGraphs.Star; adr: LONGINT; ch: CHAR; m: Mirror; w, h, i: INTEGER; qualid: ARRAY 64 OF CHAR; T: Texts.Text; beg, end, time: LONGINT; R: Texts.Reader; S: Texts.Scanner; BEGIN o := NIL; IF KeplerFrames.nofpts >= 1 THEN Oberon.GetSelection(T, beg, end, time); IF time >= 0 THEN Texts.OpenReader(R, T, beg); Texts.ReadElem(R); IF (R.elem # NIL) & (Texts.ElemPos(R.elem) <= end) THEN IF R.elem IS RefElems.Elem THEN o := R.elem(RefElems.Elem).p ELSE o := R.elem END ELSE Texts.OpenScanner(S, T, beg); Texts.Scan(S); IF S.class = Texts.Int THEN o := SYSTEM.VAL(SYSTEM.PTR, S.i) END END END ; IF o # NIL THEN KeplerFrames.GetPoint(s); KeplerFrames.Focus.Append(s); GetMirror(o, level, s, m, w, h); OpenMirror(KeplerFrames.Focus, m, w, h) END END END NewMirror; PROCEDURE InitMap(VAR map: Map; x: SYSTEM.PTR); BEGIN map.nofobjs := 1; NEW(map.obj, 2); map.obj[0] := x; map.obj[1] := NIL; map.primIdx := -1 END InitMap; PROCEDURE RehashObj(VAR m: Map); VAR h, i, j, len, len1: LONGINT; o: SYSTEM.PTR; otab: HashTab; BEGIN otab := m.obj; len := LEN(otab^); INC(m.primIdx); len1 := primTab[m.primIdx]; NEW(m.obj, len1); FOR j := 0 TO len1 - 1 DO m.obj[j] := NIL END ; FOR j := 0 TO len - 1 DO o := otab[j]; IF o # NIL THEN h := SYSTEM.ADR(o^) MOD len1; WHILE m.obj[h] # NIL DO INC(h); IF h >= len1 THEN h := 0 END END ; m.obj[h] := o END END END RehashObj; PROCEDURE HashObj (VAR m: Map; x: SYSTEM.PTR; VAR new: BOOLEAN); VAR h, nofObjs, len: LONGINT; BEGIN IF x = NIL THEN new := FALSE; RETURN END ; (*linear probing with load factor between 1/3 and 2/3*) len := LEN(m.obj^); h := SYSTEM.ADR(x^) MOD len; LOOP IF m.obj[h] = NIL THEN new := TRUE; m.obj[h] := x; INC(m.nofobjs); IF m.nofobjs * 3 >= len * 2 THEN RehashObj(m) END ; RETURN ELSIF m.obj[h] = x THEN new := FALSE; RETURN ELSE INC(h); IF h >= len THEN h := 0 END END END END HashObj; PROCEDURE List*; VAR dx, dy, i, w, h: INTEGER; next: ARRAY 32 OF CHAR; V: Viewers.Viewer; F: Display.Frame; K: KeplerFrames.Frame; G: KeplerGraphs.Graph; m, m1: Mirror; s: KeplerGraphs.Star; map: Map; p: SYSTEM.PTR; new: BOOLEAN; BEGIN IF Oberon.Pointer.on THEN V := Oberon.MarkedViewer(); F := V.dsc.next; IF F IS KeplerFrames.Frame THEN K := F(KeplerFrames.Frame); G := K.G; In.Open; In.Name(next); IF In.Done THEN In.Int(dx); IF ~In.Done THEN dx := 0; dy := 0 ELSE In.Int(dy); IF ~In.Done THEN dy := 0 END END ; m := TheMirrorAt(G, K.Cx(Oberon.Pointer.X), K.Cy(Oberon.Pointer.Y)); IF m # NIL THEN InitMap(map, m.o); LOOP GetPtr(m.o, next, p, i); HashObj(map, p, new); IF ~new THEN EXIT END ; NEW(s); s.x := m.p[1].x + SHORT(dx) + 100; s.y := m.p[0].y + SHORT(dy); IF (ABS(s.x) < 8000) & (ABS(s.y) < 8000) THEN G.Append(s); GetMirror(p, level, s, m1, w, h); OpenMirror(G, m1, w, h); OpenConnection(G, m, NIL, s, i); m := m1; ELSE EXIT END END END END END END END List; PROCEDURE BinTree*; VAR li: LONGINT; gap, x, y, xb, yb, dummy, il, ir: INTEGER; left, right: ARRAY 32 OF CHAR; V: Viewers.Viewer; F: Display.Frame; K: KeplerFrames.Frame; G: KeplerGraphs.Graph; m, ml, mr: Mirror; s: KeplerGraphs.Star; map: Map; PROCEDURE ConnectTree(m, ml, mr: Mirror; il, ir: INTEGER); VAR s2: KeplerGraphs.Star; BEGIN IF ml # NIL THEN NEW(s2); s2.x := (ml.p[0].x + ml.p[1].x) DIV 2; s2.y := ml.p[0].y; G.Append(s2); IF s2.x >= m.p[0].x - 40 THEN s2.x := (ml.p[0].x + m.p[0].x) DIV 2 END ; OpenConnection(G, m, s2, ml.p[0], il) END ; IF mr # NIL THEN NEW(s2); s2.x := (mr.p[0].x + mr.p[1].x) DIV 2; s2.y := mr.p[0].y; G.Append(s2); IF s2.x <= m.p[1].x + 40 THEN s2.x := (m.p[1].x + mr.p[1].x) DIV 2 END ; OpenConnection(G, m, s2, mr.p[0], ir) END END ConnectTree; PROCEDURE AdjustRight(o: SYSTEM.PTR; rb, ub: INTEGER; VAR field: ARRAY OF CHAR; VAR rb2, i: INTEGER; VAR m: Mirror); VAR l: SYSTEM.PTR; w, h, il, ir: INTEGER; s: KeplerGraphs.Star; ml, mr: Mirror; new: BOOLEAN; BEGIN GetPtr(o, field, l, i); HashObj(map, l, new); IF new THEN NEW(s); GetMirror(l, level, s, m, w, h); AdjustRight(l, rb, ub - h - gap, right, rb2, ir, mr); IF mr = NIL THEN s.x := rb - w; rb2 := rb - w DIV 2 - gap DIV 2 ELSE s.x := rb2 + gap DIV 2 - w DIV 2 END ; s.y := ub; G.Append(s); OpenMirror(G, m, w, h); rb := rb2; AdjustRight(l, rb, ub - h - gap, left, rb2, il, ml); IF ml = NIL THEN rb2 := s.x - gap END ; ConnectTree(m, ml, mr, il, ir) ELSE m := NIL END END AdjustRight; PROCEDURE AdjustLeft(o: SYSTEM.PTR; lb, ub: INTEGER; VAR field: ARRAY OF CHAR; VAR lb2, i: INTEGER; VAR m: Mirror); VAR r: SYSTEM.PTR; w, h, il, ir: INTEGER; s: KeplerGraphs.Star; ml, mr: Mirror; new: BOOLEAN; BEGIN GetPtr(o, field, r, i); HashObj(map, r, new); IF new THEN NEW(s); GetMirror(r, level, s, m, w, h); AdjustLeft(r, lb, ub - h - gap, left, lb2, il, ml); IF ml = NIL THEN s.x := lb; lb2 := lb + w DIV 2+ gap DIV 2 ELSE s.x := lb2 - gap DIV 2 - w DIV 2 END ; s.y := ub; G.Append(s); OpenMirror(G, m, w, h); lb := lb2; AdjustLeft(r, lb, ub - h - gap, right, lb2, ir, mr); IF mr = NIL THEN lb2 := s.x + w + gap END ; ConnectTree(m, ml, mr, il, ir) ELSE m := NIL END END AdjustLeft; BEGIN (*BinTree*) IF Oberon.Pointer.on THEN V := Oberon.MarkedViewer(); F := V.dsc.next; IF F IS KeplerFrames.Frame THEN K := F(KeplerFrames.Frame); G := K.G; In.Open; In.Name(left); In.Name(right); IF In.Done THEN In.Int(gap); IF ~In.Done THEN gap := 40 END ; x := K.Cx(Oberon.Pointer.X); y := K.Cy(Oberon.Pointer.Y); m := TheMirrorAt(G, x, y); IF m # NIL THEN InitMap(map, m.o); xb := (m.p[0].x + m.p[1].x) DIV 2 - gap DIV 2; yb := m.p[1].y - gap; AdjustRight(m.o, xb, yb, left, dummy, il, ml); xb := xb + gap; AdjustLeft(m.o, xb, yb, right, dummy, ir, mr); ConnectTree(m, ml, mr, il, ir) END END END END END BinTree; BEGIN NEW(B); Texts.OpenWriter(W); fntHeight := Fonts.Default.height * 4; primTab[0] := 163; primTab[1] := 491; primTab[2] := 1481; primTab[3] := 4447; primTab[4] := 13367; primTab[5] := 40111; primTab[6] := 120349; primTab[7] := 361069; END Mirrors. Mirrors.NewMirror Mirrors.BinTree dsc next Mirrors.List next