home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / jËzyki_programowania / oberon / system / foldelems.mod (.txt) < prev    next >
Oberon Text  |  1977-12-31  |  14KB  |  365 lines

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 14 Apr 96
  5. Syntax10b.Scn.Fnt
  6. MODULE FoldElems;    (** HM 
  7. IMPORT Display, Oberon, Input, Files, Texts, Viewers, MenuViewers, TextFrames, TextPrinter;
  8. CONST
  9.     rightKey = 0; middleKey = 1; leftKey = 2;
  10.     colLeft* = 0; colRight* = 1; expRight* = 2; expLeft* = 3; tempLeft* = 4; findLeft* = 5;    (*fold element mode*)
  11.     leftMode = {colLeft, expLeft, tempLeft, findLeft};
  12.     rightMode = {colRight, expRight};
  13.     tempMode = {tempLeft, findLeft};
  14.     pixel = 10000;
  15.     invisW = 1 * pixel;  (*width of an invisible element*)
  16.     Elem* = POINTER TO ElemDesc;
  17.     ElemDesc* = RECORD (Texts.ElemDesc)
  18.         mode*: SHORTINT;
  19.         hidden*: Texts.Buffer;
  20.         visible*: BOOLEAN
  21.     END ;
  22.     CheckProc* = PROCEDURE(e: Texts.Elem): BOOLEAN;
  23.     MarkElem = POINTER TO MarkElemDesc;
  24.     MarkElemDesc = RECORD (Texts.ElemDesc) END ;
  25.     FindInfo = RECORD
  26.         found: BOOLEAN;
  27.         text: Texts.Text;
  28.         pos: LONGINT;
  29.         pat: ARRAY 128 OF CHAR;
  30.         len: INTEGER
  31.     END ;
  32.     PrepSwitchMsg* = RECORD (Texts.ElemMsg) END ;
  33.     elemW-, elemH-: LONGINT;
  34.     w: Texts.Writer;
  35.     inf: FindInfo;
  36.     x0, y0: INTEGER; (*x and y metric of fold characters*)
  37.     Pat: ARRAY 6 OF Display.Pattern; (* x = 0, y = 3, w = 8, h = 9 *)
  38.     icl, icr, iel, ier: ARRAY 4 OF SET;
  39. PROCEDURE NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);
  40. END NoNotify;
  41. PROCEDURE FindCheck (e: Texts.Elem): BOOLEAN;
  42. BEGIN RETURN e IS MarkElem
  43. END FindCheck;
  44. PROCEDURE TargetText (): Texts.Text;
  45.     VAR f: Display.Frame; v: Viewers.Viewer;
  46. BEGIN f := NIL;
  47.     IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN f := Oberon.Par.frame.next
  48.     ELSE v := Oberon.MarkedViewer();
  49.         IF (v # NIL) & (v.dsc # NIL) THEN f := v.dsc.next END
  50.     END ;
  51.     IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame).text
  52.     ELSE RETURN NIL
  53. END TargetText;
  54. PROCEDURE Echo* (t: Texts.Text; on: BOOLEAN);
  55. BEGIN
  56.     IF on THEN t.notify := TextFrames.NotifyDisplay ELSE t.notify := NoNotify END
  57. END Echo;
  58. PROCEDURE Update (e: Elem);
  59.     VAR t: Texts.Text; pos: LONGINT;
  60. BEGIN t := Texts.ElemBase(e); pos := Texts.ElemPos(e); t.notify(t, Texts.replace, pos, pos+1)
  61. END Update;
  62. PROCEDURE Twin* (e: Elem): Elem;
  63.     VAR level, sp: INTEGER; stack: ARRAY 8 OF Elem; r: Texts.Reader; E: Elem;
  64. BEGIN E := NIL; level := 1;
  65.     IF e.mode IN leftMode THEN Texts.OpenReader(r, Texts.ElemBase(e), Texts.ElemPos(e)+1);
  66.         LOOP Texts.ReadElem(r);
  67.             IF r.elem = NIL THEN EXIT
  68.             ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  69.                 IF E.mode IN leftMode THEN INC(level) ELSE DEC(level) END ;
  70.                 IF level = 0 THEN EXIT END
  71.             END
  72.         END
  73.     ELSE
  74.         Texts.OpenReader(r, Texts.ElemBase(e), Texts.ElemPos(e));
  75.         LOOP Texts.ReadPrevElem(r);
  76.             IF r.elem = NIL THEN EXIT
  77.             ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  78.                 IF E.mode IN rightMode THEN INC(level) ELSE DEC(level) END ;
  79.                 IF level = 0 THEN EXIT END
  80.             END
  81.         END
  82.     END ;
  83.     RETURN E
  84. END Twin;
  85. PROCEDURE Switch* (e: Elem);
  86.     VAR a, b: Elem; apos: LONGINT; t: Texts.Text; buf: Texts.Buffer; prepare: PrepSwitchMsg;
  87. BEGIN
  88.     IF e.mode IN leftMode THEN a := e; b := Twin(a) ELSE b := e; a := Twin(b) END ;
  89.     IF a.mode IN tempMode THEN a.mode := expLeft END ;
  90.     IF (a # NIL) & (b # NIL) THEN
  91.         a.handle(a, prepare);
  92.         t := Texts.ElemBase(a); apos := Texts.ElemPos(a);
  93.         a.mode := 3 - a.mode; b.mode := 3 - b.mode;
  94.         Texts.Delete(t, apos+1, Texts.ElemPos(b)); Texts.Recall(buf);
  95.         Texts.Insert(t, apos+1, a.hidden); a.hidden := buf;
  96.         Update(a)
  97. END Switch;
  98. PROCEDURE ExpandAll* (t: Texts.Text; from: LONGINT; temporal: BOOLEAN);
  99.     VAR r: Texts.Reader; E: Elem; res: INTEGER;
  100. BEGIN Texts.OpenReader(r, t, from);
  101.     LOOP Texts.ReadElem(r);
  102.         IF r.elem = NIL THEN EXIT
  103.         ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  104.             IF E.mode = colLeft THEN
  105.                 Switch(E); IF temporal THEN E.mode := tempLeft END ;
  106.                 Texts.OpenReader(r, t, Texts.ElemPos(E)+1)
  107.             END
  108.         END
  109. END ExpandAll;
  110. PROCEDURE CollapseAll* (t: Texts.Text; modes: SET);
  111.     VAR r: Texts.Reader;
  112. BEGIN Texts.OpenReader(r, t, t.len);
  113.     LOOP Texts.ReadPrevElem(r);
  114.         IF r.elem = NIL THEN EXIT
  115.         ELSIF (r.elem IS Elem) & (r.elem(Elem).mode IN modes) THEN Switch(r.elem(Elem))
  116.         END
  117. END CollapseAll;
  118. PROCEDURE FindElem* (t: Texts.Text; pos: LONGINT; P: CheckProc; VAR elem: Texts.Elem);
  119.     VAR r: Texts.Reader; E: Elem;
  120.     PROCEDURE Inside(buf: Texts.Buffer): BOOLEAN;
  121.         VAR r: Texts.Reader; t0: Texts.Text; found: BOOLEAN;
  122.     BEGIN t0 := TextFrames.Text(""); Texts.Append(t0, buf); Texts.OpenReader(r, t0, 0); found := FALSE;
  123.         LOOP Texts.ReadElem(r);
  124.             IF r.elem = NIL THEN EXIT
  125.             ELSIF P(r.elem) OR (r.elem IS Elem) & (r.elem(Elem).mode = colLeft) & Inside(r.elem(Elem).hidden) THEN
  126.                 found := TRUE; EXIT
  127.             END
  128.         END ;
  129.         Texts.Save(t0, 0, t0.len, buf); RETURN found
  130.     END Inside;
  131. BEGIN Texts.OpenReader(r, t, pos);
  132.     LOOP Texts.ReadElem(r); pos := Texts.Pos(r);
  133.         IF (r.elem = NIL) OR P(r.elem) THEN elem := r.elem; EXIT END ;
  134.         IF r.elem IS Elem THEN E := r.elem(Elem);
  135.             IF (E.mode = colLeft) & Inside(E.hidden) THEN
  136.                 Switch(E); E.mode := findLeft; Texts.OpenReader(r, t, pos)
  137.             END
  138.         END
  139. END FindElem;
  140. PROCEDURE FoldHandler* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  141.     VAR a: Elem; keys: SET; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer; k, mode: SHORTINT;
  142.         neutralize: Oberon.ControlMsg;
  143. BEGIN
  144.     WITH e: Elem DO
  145.         WITH
  146.             m: Texts.FileMsg DO
  147.                 IF m.id = Texts.load THEN
  148.                     Files.Read(m.r, k); e.mode := k MOD 4; e.visible := e.W > invisW;
  149.                     IF e.mode IN leftMode THEN
  150.                         NEW(e.hidden); Texts.OpenBuf(e.hidden);
  151.                         IF k < 4 THEN (*text not empty*)
  152.                             t := TextFrames.Text("");
  153.                             Texts.Load(m.r, t);
  154.                             Texts.Save(t, 0, t.len, e.hidden)
  155.                         END
  156.                     END
  157.                 ELSE (*Texts.store*)
  158.                     mode := e.mode;
  159.                     IF mode IN tempMode THEN mode := expLeft END ;
  160.                     IF (mode IN leftMode) & (e.hidden.len = 0) THEN k := mode +  4 ELSE k := mode END ;
  161.                     Files.Write(m.r, k);
  162.                     IF (k < 4)  & (mode IN leftMode) THEN
  163.                         t := TextFrames.Text("");
  164.                         NEW(buf); Texts.OpenBuf(buf); Texts.Copy(e.hidden, buf); Texts.Append(t, buf);
  165.                         Texts.Store(m.r, t)
  166.                     END
  167.                 END
  168.         | m: Texts.CopyMsg DO
  169.                 IF m.e = NIL THEN NEW(a); m.e := a ELSE a := m.e(Elem) END ;
  170.                 Texts.CopyElem(e, a);
  171.                 a.mode := e.mode; a.visible := e.visible;
  172.                 IF e.mode IN leftMode THEN
  173.                     NEW(a.hidden); Texts.OpenBuf(a.hidden); Texts.Copy(e.hidden, a.hidden)
  174.                 END ;
  175.         | m: Texts.IdentifyMsg DO
  176.                 m.mod := "FoldElems"; m.proc := "New"
  177.         | m: TextFrames.DisplayMsg DO
  178.             IF m.prepare THEN
  179.                 IF e.visible THEN e.W := elemW ELSE e.W := invisW END
  180.             ELSIF e.visible THEN
  181.                 Display.CopyPattern(15, Pat[e.mode], m.X0 + x0, m.Y0 + y0, Display.replace)
  182.             END
  183.         | m: TextPrinter.PrintMsg DO
  184.             IF m.prepare THEN e.W := 0 ELSE e.W := elemW END
  185.         | m: TextFrames.TrackMsg DO
  186.                 IF middleKey IN m.keys THEN
  187.                     neutralize.id := Oberon.neutralize; m.frame.handle(m.frame, neutralize);
  188.                     IF e.mode IN tempMode THEN mode := expLeft ELSE mode := e.mode END ;
  189.                     Display.CopyPattern(Display.white, Pat[mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  190.                     Display.CopyPattern(Display.white, Pat[3 - mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  191.                     REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  192.                         Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
  193.                     UNTIL keys = {};
  194.                     IF m.keys = {middleKey} THEN Switch(e)
  195.                     ELSE
  196.                         Display.CopyPattern(Display.white, Pat[3 - mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  197.                         Display.CopyPattern(Display.white, Pat[mode], m.X0 + x0, m.Y0 + y0, Display.invert)
  198.                     END
  199.                 END
  200.         ELSE
  201.         END
  202. END FoldHandler;
  203. PROCEDURE MarkHandler (e: Texts.Elem; VAR m: Texts.ElemMsg);
  204.     VAR a: MarkElem;
  205. BEGIN
  206.     IF m IS Texts.CopyMsg THEN NEW(a); Texts.CopyElem(e, a); m(Texts.CopyMsg).e := a END
  207. END MarkHandler;
  208. PROCEDURE Insert*;
  209.     VAR e: Elem; t: Texts.Text; beg, end, time: LONGINT;
  210. BEGIN
  211.     Oberon.GetSelection(t, beg, end, time);
  212.     IF (time >= 0) & (t IS Texts.Text) THEN
  213.         NEW(e); e.mode := expRight; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  214.         e.visible := TRUE; Texts.WriteElem(w, e); Texts.Insert(t, end, w.buf);
  215.         NEW(e); e.mode := expLeft; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  216.         NEW(e.hidden); Texts.OpenBuf(e.hidden); e.visible := TRUE;
  217.         Texts.WriteElem(w, e); Texts.Insert(t, beg, w.buf)
  218. END Insert;
  219. PROCEDURE InsertCollapsed*;
  220.     VAR e: Elem; t: Texts.Text; beg, end, time: LONGINT;
  221. BEGIN
  222.     Oberon.GetSelection(t, beg, end, time);
  223.     IF (time >= 0) & (t IS Texts.Text) THEN
  224.         NEW(e); e.mode := colRight; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  225.         e.visible := TRUE; Texts.WriteElem(w, e); Texts.Insert(t, end, w.buf);
  226.         NEW(e); e.mode := colLeft; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  227.         NEW(e.hidden); Texts.OpenBuf(e.hidden); e.visible := TRUE;
  228.         Texts.WriteElem(w, e); Texts.Insert(t, beg, w.buf)
  229. END InsertCollapsed;
  230. PROCEDURE Marks*;
  231.     VAR s: Texts.Scanner; t: Texts.Text; beg, end, time: LONGINT; visible: BOOLEAN;
  232.         wt: Texts.Text; r: Texts.Reader;
  233. BEGIN
  234.     wt := TargetText();
  235.     IF wt # NIL THEN
  236.         Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
  237.         IF (s.class = Texts.Char) & (s.c = "^") & (s.line = 0) THEN
  238.             Oberon.GetSelection(t, beg, end, time);
  239.             IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END
  240.         END ;
  241.         IF (s.class = Texts.Name) & ((s.s = "on") OR (s.s = "off")) THEN visible := s.s = "on";
  242.             Texts.OpenReader(r, wt, 0);
  243.             LOOP Texts.ReadElem(r);
  244.                 IF r.elem = NIL THEN EXIT
  245.                 ELSIF r.elem IS Elem THEN
  246.                     r.elem(Elem).visible := visible;
  247.                     Update(r.elem(Elem))
  248.                 END
  249.             END
  250.         END
  251. END Marks;
  252. PROCEDURE Search*;
  253.     VAR v: Viewers.Viewer; f: TextFrames.Frame; t: Texts.Text; r: Texts.Reader; beg, end, time, lim: LONGINT;
  254.         i: INTEGER; ch: CHAR; e: Texts.Elem; ntfy: Texts.Notifier; E: MarkElem; m: Oberon.ControlMsg;
  255. BEGIN
  256.     v := Oberon.Par.vwr;
  257.     IF Oberon.Par.frame # v.dsc THEN v := Oberon.FocusViewer END ;
  258.     IF (v # NIL) & (v IS MenuViewers.Viewer) & (v.dsc.next IS TextFrames.Frame) THEN
  259.         f := v.dsc.next(TextFrames.Frame);
  260.         inf.text := f.text;
  261.         IF f.hasCar THEN inf.pos := f.carloc.pos; TextFrames.RemoveCaret(f) ELSE inf.pos := 0 END ;
  262.         Oberon.GetSelection(t, beg, end, time);
  263.         IF time >= 0 THEN    (*else find again*)
  264.             Texts.OpenReader(r, t, beg); inf.len := 0;
  265.             WHILE (beg < end) & (inf.len<127) DO Texts.Read(r, inf.pat[inf.len]); INC(inf.len); INC(beg) END ;
  266.             inf.pat[inf.len] := 0X;
  267.             m.id := Oberon.neutralize; Viewers.Broadcast(m);
  268.         END ;
  269.         IF inf.len > 0 THEN
  270.             Echo(inf.text, FALSE);
  271.             ExpandAll(inf.text, inf.pos, TRUE);
  272.             inf.found := FALSE; lim := inf.text.len - inf.len;
  273.             Texts.OpenReader(r, inf.text, inf.pos);
  274.             LOOP Texts.Read(r, ch);    (*find*)
  275.                 IF inf.pos > lim THEN EXIT
  276.                 ELSIF ch = inf.pat[0] THEN
  277.                     Texts.Read(r, ch); i := 1;
  278.                     WHILE (i < inf.len) & (ch = inf.pat[i]) DO Texts.Read(r, ch); INC(i) END ;
  279.                     IF i = inf.len THEN inf.pos := inf.pos + inf.len; inf.found := TRUE; EXIT
  280.                     ELSE INC(inf.pos); Texts.OpenReader(r, inf.text, inf.pos)
  281.                     END
  282.                 ELSE INC(inf.pos)
  283.                 END
  284.             END ;
  285.             IF inf.found THEN
  286.                 NEW(E); E.W := 0; E.H := 0; E.handle := MarkHandler;
  287.                 Texts.WriteElem(w, E); Texts.Insert(inf.text, inf.pos, w.buf);
  288.                 CollapseAll(inf.text, {tempLeft});
  289.                 Echo(inf.text, TRUE);
  290.                 FindElem(inf.text, 0, FindCheck, e); inf.pos := Texts.ElemPos(e);
  291.                 IF E = e (*FindElem did not expand anything*) THEN Echo(inf.text, FALSE) END ;
  292.                 Texts.Delete(inf.text, inf.pos, inf.pos + 1); Echo(inf.text, TRUE);
  293.                 end := TextFrames.Pos(f, f.X + f.W, f.Y);
  294.                 IF (inf.pos < f.org) OR (inf.pos >= end) THEN TextFrames.Show(f, inf.pos - 120) END ;
  295.                 TextFrames.SetCaret(f, inf.pos)
  296.             ELSE CollapseAll(inf.text, {tempLeft}); Echo(inf.text, TRUE)
  297.             END
  298.         END
  299. END Search;
  300. PROCEDURE Restore*;
  301.     VAR t: Texts.Text;
  302. BEGIN t := TargetText(); IF t # NIL THEN CollapseAll(t, {findLeft}) END
  303. END Restore;
  304. PROCEDURE Expand*;
  305.     VAR t: Texts.Text;
  306. BEGIN t := TargetText(); IF t # NIL THEN ExpandAll(t, 0, FALSE) END
  307. END Expand;
  308. PROCEDURE Collapse*;
  309.     VAR t: Texts.Text;
  310. BEGIN t := TargetText(); IF t # NIL THEN CollapseAll(t, {expLeft, tempLeft, findLeft}) END
  311. END Collapse;
  312. PROCEDURE New*;
  313.     VAR e: Elem;
  314. BEGIN NEW(e); e.handle := FoldHandler; Texts.new := e
  315. END New;
  316. PROCEDURE Init;    (*for SPARCstatiom, DECstation, RS6000 and PowerMacintosh *)
  317.     VAR img: ARRAY 10 OF SET;
  318. BEGIN
  319.     img[1] := {2};
  320.     img[2] := {2..3};
  321.     img[3] := {2..4};
  322.     img[4] := {2..5};
  323.     img[5] := {2..6};
  324.     img[6] := {2..5};
  325.     img[7] := {2..4};
  326.     img[8] := {2..3};
  327.     img[9] := {2};
  328.     Pat[0]:=Display.NewPattern(img, 8, 9);    (*collapsed left*)
  329.     img[1] := {2};
  330.     img[2] := {2, 3};
  331.     img[3] := {2, 4};
  332.     img[4] := {2, 5};
  333.     img[5] := {2, 6};
  334.     img[6] := {2, 5};
  335.     img[7] := {2, 4};
  336.     img[8] := {2, 3};
  337.     img[9] := {2};
  338.     Pat[3]:=Display.NewPattern(img, 8, 9);    (*expanded left*)
  339.     img[1] := {5};
  340.     img[2] := {4..5};
  341.     img[3] := {3..5};
  342.     img[4] := {2..5};
  343.     img[5] := {1..5};
  344.     img[6] := {2..5};
  345.     img[7] := {3..5};
  346.     img[8] := {4..5};
  347.     img[9] := {5};
  348.     Pat[1]:=Display.NewPattern(img, 8, 9);    (*collapsed right*)
  349.     img[1] := {5};
  350.     img[2] := {4, 5};
  351.     img[3] := {3, 5};
  352.     img[4] := {2, 5};
  353.     img[5] := {1, 5};
  354.     img[6] := {2, 5};
  355.     img[7] := {3, 5};
  356.     img[8] := {4, 5};
  357.     img[9] := {5};
  358.     Pat[2]:=Display.NewPattern(img, 8, 9);    (*expanded right*)
  359.     Pat[4]:=Pat[3]; Pat[5]:=Pat[3];
  360.     inf.len:=0; elemW:=8*LONG(pixel); elemH:=12*LONG(pixel); x0:=0; y0:=3
  361. END Init;
  362. BEGIN
  363.     Init; Texts.OpenWriter(w)
  364. END FoldElems.
  365.