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

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 22 Apr 96
  5. Syntax10b.Scn.Fnt
  6. Syntax10i.Scn.Fnt
  7. MarkElems
  8. Alloc
  9. MODULE LinkElems;  (** HM 
  10. IMPORT
  11.     Files, Fonts, Display, Input, Viewers, Texts, TextFrames, MenuViewers, TextPrinter, Oberon, PopupElems, MarkElems, FoldElems;
  12. CONST
  13.     left =2; middle = 1; right = 0;
  14.     pixel = LONG(10000);
  15.     stdMenu = "System.Close  System.Copy  System.Grow  Edit.Search  Edit.Replace  Edit.Store ";
  16.     Elem* = POINTER TO ElemDesc;
  17.     ElemDesc* = RECORD (Texts.ElemDesc)
  18.         file*: ARRAY 32 OF CHAR;
  19.         key*: LONGINT
  20.     END ;
  21.     FollowMsg* = RECORD (Texts.ElemMsg) f*: Display.Frame END ;
  22.     Menu* = POINTER TO MenuDesc;
  23.     MenuDesc* = RECORD (PopupElems.ElemDesc)
  24.     END ;
  25.     Frame = POINTER TO FrameDesc;
  26.     FrameDesc = RECORD (TextFrames.FrameDesc)
  27.         e: Elem
  28.     END ;
  29.     searchKey: LONGINT;    (*key of mark element searched in FollowLink; used in Check*)
  30.     hint: TextFrames.Frame;    (*suggests frame to be used for links emanating from a link menu*)
  31.     icon, invIcon: Display.Pattern; (* x = 0, y = 3, w = 9, h = 8 *)
  32.     w: Texts.Writer;
  33. PROCEDURE^ New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
  34. PROCEDURE 
  35. GetSelection (VAR f: TextFrames.Frame);
  36.     (* return frame f with the latest text selection*)
  37.     VAR v: Viewers.Viewer; f0: Display.Frame; time: LONGINT; x: INTEGER;
  38. BEGIN
  39.     x := 0; time := -1; f := NIL;
  40.     WHILE x < Display.Width DO
  41.         v := Viewers.This(x, 0);
  42.         WHILE v.state > 1 DO
  43.             f0 := v.dsc;
  44.             WHILE f0 # NIL DO
  45.                 WITH f0: TextFrames.Frame DO
  46.                     IF f0.hasSel & (f0.time > time) THEN f := f0; time := f.time END
  47.                 ELSE
  48.                 END ;
  49.                 f0 := f0.next
  50.             END ;
  51.             v := Viewers.Next(v)
  52.         END ;
  53.         x := x + v.W
  54. END GetSelection;
  55. PROCEDURE 
  56. GetFileName (t: Texts.Text; VAR name: ARRAY OF CHAR);
  57.     (* return the name of the viewer which contains text t*)
  58.     VAR v, V: Viewers.Viewer; f: Display.Frame; s: Texts.Scanner; x: INTEGER;
  59. BEGIN
  60.     V := NIL; x := 0;
  61.     WHILE x < Display.Width DO
  62.         v := Viewers.This(x, 0);
  63.         WHILE v.state > 1 DO
  64.             f := v.dsc;
  65.             WHILE f # NIL DO
  66.                 IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = t) THEN V := v END ;
  67.                 f := f.next
  68.             END ;
  69.             v := Viewers.Next(v)
  70.         END ;
  71.         x := x + v.W
  72.     END ;
  73.     IF V # NIL THEN
  74.         Texts.OpenScanner(s, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
  75.         IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, name) ELSE name[0] := 0X END
  76. END GetFileName;
  77. PROCEDURE 
  78. GetFrame (name: ARRAY OF CHAR; VAR f: TextFrames.Frame);
  79.     VAR x: INTEGER; v: Viewers.Viewer; s: Texts.Scanner;
  80. BEGIN
  81.     IF hint # NIL THEN f := hint
  82.     ELSE
  83.         x := 0; f := NIL;
  84.         WHILE x < Display.Width DO
  85.             v := Viewers.This(x, 0);
  86.             WHILE v.state > 1 DO
  87.                 IF (v.dsc # NIL) & (v.dsc IS TextFrames.Frame) THEN
  88.                     Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
  89.                     IF s.s = name THEN f := v.dsc.next(TextFrames.Frame); RETURN END
  90.                 END ;
  91.                 v := Viewers.Next(v)
  92.             END ;
  93.             x := x + v.W
  94.         END
  95. END GetFrame;
  96. PROCEDURE 
  97. GetDsr (f: Display.Frame; pos: LONGINT; fnt: Fonts.Font; VAR dsr: INTEGER);
  98.     VAR p: TextFrames.Parc; beg: LONGINT;
  99. BEGIN
  100.     IF f = NIL THEN
  101.         IF fnt = NIL THEN dsr := 0 ELSE dsr := - fnt.minY END
  102.     ELSE
  103.         TextFrames.ParcBefore(f(TextFrames.Frame).text, pos, p, beg);
  104.         dsr := SHORT(p.dsr DIV TextFrames.Unit)
  105. END GetDsr;
  106. PROCEDURE 
  107. CollectMarks (pop: Menu; f0: Display.Frame);
  108.     (* Fill popup menu with all mark elements in f0.next.text*)
  109.     VAR r: Texts.Reader; s: Texts.Scanner; ch: CHAR; f: TextFrames.Frame; mark: MarkElems.Elem; link: Elem; n: INTEGER;
  110.         file: ARRAY 32 OF CHAR;
  111. BEGIN
  112.     pop.menu := TextFrames.Text("");
  113.     IF (f0.next = NIL) OR ~ (f0.next IS TextFrames.Frame) THEN
  114.         Texts.WriteString(w, "link menu not in menu bar of a text viewer"); Texts.WriteLn(w); Texts.WriteLn(w)
  115.     ELSE
  116.         f := f0.next(TextFrames.Frame); hint := f; GetFileName(f.text, file); n := 0;
  117.         Texts.OpenReader(r, f.text, 0); Texts.ReadElem(r);
  118.         WHILE ~ r.eot DO
  119.             IF r.elem IS MarkElems.Elem THEN
  120.                 mark := r.elem(MarkElems.Elem);
  121.                 link := New(file, mark.key);
  122.                 Texts.WriteElem(w, link); Texts.Write(w, " ");
  123.                 Texts.OpenScanner(s, f.text, Texts.Pos(r)); Texts.Scan(s);
  124.                 WHILE ~s.eot & (s.class # Texts.Name) DO Texts.Scan(s) END ;
  125.                 IF ~s.eot THEN Texts.WriteString(w, s.s); Texts.WriteLn(w); INC(n)
  126.                 END
  127.             END ;
  128.             Texts.ReadElem(r)
  129.         END ;
  130.         IF n = 0 THEN Texts.WriteString(w, "no marks"); Texts.WriteLn(w) END ;
  131.         IF n <= 1 THEN Texts.WriteLn(w) END ;
  132.     END ;
  133.     Texts.Append(pop.menu, w.buf); PopupElems.MeasureMenu(pop)
  134. END CollectMarks;
  135. PROCEDURE 
  136. ShowPos (f: TextFrames.Frame; pos: LONGINT);
  137.     VAR beg, end, delta: LONGINT;
  138. BEGIN delta := 200;
  139.     LOOP beg := f.org; end := TextFrames.Pos(f, f.X + f.W, f.Y);
  140.         IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END ;
  141.         TextFrames.Show(f, pos - delta); delta := delta DIV 2
  142.     END ;
  143.     TextFrames.SetSelection(f, pos, pos + 1)
  144. END ShowPos;
  145. PROCEDURE 
  146. Check (e: Texts.Elem): BOOLEAN;
  147. BEGIN RETURN (e IS MarkElems.Elem) & (e(MarkElems.Elem).key = searchKey)
  148. END Check;
  149. PROCEDURE 
  150. FollowLink* (file: ARRAY OF CHAR; key: LONGINT; backF: Display.Frame; backE: Texts.Elem);
  151.     VAR v: Viewers.Viewer; menu: TextFrames.Frame; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer;
  152.         mark: Texts.Elem; f: TextFrames.Frame;
  153. BEGIN
  154.     GetFrame(file, f);
  155.     IF f = NIL THEN
  156.         f := TextFrames.NewText(TextFrames.Text(file), 0);
  157.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  158.         IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(file, stdMenu)
  159.         ELSE menu := TextFrames.NewMenu(file, "");
  160.             NEW(t); Texts.Open(t, "Edit.Menu.Text");
  161.             NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, 0, t.len, buf); Texts.Append(menu.text, buf)
  162.         END ;
  163.         v := MenuViewers.New(menu, f, TextFrames.menuH, x, y)
  164.     END ;
  165.     searchKey := key;
  166.     FoldElems.FindElem(f.text, 0, Check, mark);
  167.     IF mark # NIL THEN
  168.         ShowPos(f, Texts.ElemPos(mark));
  169.         IF backF # NIL THEN MarkElems.backF := backF(TextFrames.Frame) ELSE MarkElems.backF := NIL END ;
  170.         MarkElems.backE := backE
  171. END FollowLink;
  172. PROCEDURE 
  173. Edit (e: Elem);
  174.     VAR t: Texts.Text; v: MenuViewers.Viewer; f: Frame; x, y: INTEGER;
  175. BEGIN
  176.     t := TextFrames.Text("");
  177.     Texts.WriteString(w, e.file); Texts.Write(w, " "); Texts.WriteInt(w, e.key, 0);
  178.     Texts.Append(t, w.buf);
  179.     NEW(f); f.e := e; TextFrames.Open(f, t, 0);
  180.     Oberon.AllocateSystemViewer(0, x, y);
  181.     v := MenuViewers.New(
  182.         TextFrames.NewMenu("LinkElem", "System.Close  LinkElems.Update "),
  183.         f, TextFrames.menuH, x, y)
  184. END Edit;
  185. PROCEDURE 
  186. Handle* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  187.     VAR e1: Elem; x, y, dsr, i: INTEGER; keys: SET; ch: CHAR; follow: FollowMsg;
  188. BEGIN
  189.     WITH e: Elem DO
  190.         WITH m: Texts.FileMsg DO
  191.             IF m.id = Texts.load THEN
  192.                 i := 0; REPEAT Files.Read(m.r, ch); e.file[i] := ch; INC(i) UNTIL ch = 0X;
  193.                 Files.ReadLInt(m.r, e.key)
  194.             ELSE (*Texts.store*)
  195.                 i := 0; REPEAT ch := e.file[i]; Files.Write(m.r, ch); INC(i) UNTIL ch = 0X;
  196.                 Files.WriteLInt(m.r, e.key)
  197.             END
  198.         | m: Texts.CopyMsg DO
  199.             IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END ;
  200.             Texts.CopyElem(e, e1); COPY(e.file, e1.file); e1.key := e.key
  201.         | m: Texts.IdentifyMsg DO
  202.             m.mod := "LinkElems"; m.proc := "Alloc"
  203.         | m: TextFrames.DisplayMsg DO
  204.             IF ~m.prepare THEN
  205.                 GetDsr(m.frame, m.pos, m.fnt, dsr);
  206.                 Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.paint)
  207.             END
  208.         | m: TextPrinter.PrintMsg DO
  209.             IF m.prepare THEN e.W := 1 ELSE e.W := 10 * pixel END
  210.         | m: TextFrames.TrackMsg DO
  211.                 IF middle IN m.keys THEN
  212.                     IF m.frame # NIL THEN
  213.                         GetDsr(m.frame, m.pos, m.fnt, dsr);
  214.                         Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert);
  215.                         Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
  216.                         REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  217.                             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
  218.                         UNTIL keys = {};
  219.                         Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
  220.                         Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert)
  221.                     END ;
  222.                     IF m.keys = {middle} THEN follow.f := m.frame; e.handle(e, follow)
  223.                     ELSIF m.keys = {middle, right} THEN Edit(e)
  224.                     END
  225.                 END
  226.         | m: FollowMsg DO
  227.             FollowLink(e.file, e.key, m.f, e)
  228.         ELSE
  229.         END
  230. END Handle;
  231. PROCEDURE 
  232. HandleMenu* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  233.     VAR e1: Menu;
  234. BEGIN
  235.     WITH e: Menu DO
  236.         WITH
  237.           m: Texts.IdentifyMsg DO
  238.             m.mod := "LinkElems"; m.proc := "AllocMenu"
  239.         | m: Texts.CopyMsg DO
  240.             NEW(e1); m.e := e1; PopupElems.Handle(e, m)
  241.         | m: TextFrames.DisplayMsg DO
  242.             IF m.prepare THEN
  243.                 e.W := 13 * pixel; e.H := LONG(TextFrames.menuH-1) * pixel;
  244.             ELSE e.name := ""; PopupElems.Handle(e, m);
  245.                 Display.CopyPattern(Display.white, icon, m.X0+2, m.Y0+3, Display.paint)
  246.             END
  247.         | m: TextFrames.TrackMsg DO
  248.             IF middle IN m.keys THEN
  249.                 CollectMarks(e, m.frame); PopupElems.Handle(e, m); hint := NIL
  250.             END
  251.         ELSE PopupElems.Handle(e, m)
  252.         END
  253. END HandleMenu;
  254. PROCEDURE 
  255. Alloc*;
  256.     VAR e: Elem;
  257. BEGIN
  258.     NEW(e); e.handle := Handle; Texts.new := e
  259. END Alloc;
  260. PROCEDURE 
  261. AllocMenu*;
  262.     VAR e: Menu;
  263. BEGIN
  264.     NEW(e); e.handle := HandleMenu; Texts.new := e
  265. END AllocMenu;
  266. PROCEDURE 
  267. New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
  268.     VAR e: Elem;
  269. BEGIN
  270.     NEW(e); e.W := 10 * pixel; e.H := 11 * pixel; e.handle := Handle; COPY(file, e.file); e.key := key;
  271.     RETURN e
  272. END New;
  273. PROCEDURE 
  274. Insert*;
  275.     VAR link: Elem; mark: MarkElems.Elem; fromT, toT: Texts.Text; toPos, end, time: LONGINT;
  276.         r: Texts.Reader; ch: CHAR; m: TextFrames.InsertElemMsg; f: TextFrames.Frame;
  277. BEGIN
  278.     f := Oberon.FocusViewer.dsc(TextFrames.Frame);
  279.     IF f.hasCar THEN fromT := f.text ELSE fromT := f.next(TextFrames.Frame).text END ;
  280.     Oberon.GetSelection(toT, toPos, end, time);
  281.     IF time >= 0 THEN
  282.         link := New("", 0); GetFileName(toT, link.file);
  283.         Texts.OpenReader(r, toT, toPos); Texts.Read(r, ch);
  284.         m.e := link; Viewers.Broadcast(m);
  285.         IF (ch = Texts.ElemChar) & (r.elem IS MarkElems.Elem) THEN
  286.             link.key := r.elem(MarkElems.Elem).key
  287.         ELSE
  288.             IF (fromT = toT) & (Texts.ElemPos(link) <= toPos) THEN INC(toPos) END ;
  289.             mark := MarkElems.New(); link.key := mark.key;
  290.             Texts.WriteElem(w, mark); Texts.Insert(toT, toPos, w.buf)
  291.         END
  292. END Insert;
  293. PROCEDURE 
  294. InsertMenu*;
  295.     VAR e: Menu; insert: TextFrames.InsertElemMsg;
  296. BEGIN
  297.     NEW(e); e.handle := HandleMenu; e.name := ""; e.menu := TextFrames.Text(""); e.small := TRUE;
  298.     PopupElems.MeasureMenu(e);
  299.     insert.e := e; Viewers.Broadcast(insert)
  300. END InsertMenu;
  301. PROCEDURE 
  302. Update*;
  303.     VAR f: Frame; t: Texts.Text; s: Texts.Scanner; r: Texts.Reader; ch: CHAR;
  304. BEGIN
  305.     IF (Oberon.Par.frame = Oberon.Par.vwr.dsc) & (Oberon.Par.frame.next IS Frame) THEN
  306.         f := Oberon.Par.frame.next(Frame);
  307.         Texts.OpenScanner(s, f.text, 0); Texts.Scan(s);
  308.         IF s.class = Texts.Name THEN
  309.             COPY(s.s, f.e.file); Texts.Scan(s);
  310.             IF s.class = Texts.Int THEN
  311.                 f.e.key := s.i;
  312.                 t := Oberon.Par.frame(TextFrames.Frame).text;
  313.                 Texts.OpenReader(r, t, t.len-1); Texts.Read(r, ch);
  314.                 IF ch = "!" THEN Texts.Delete(t, t.len-1, t.len) END
  315.             END
  316.         END
  317. END Update;
  318. PROCEDURE 
  319. InitIcon;
  320.     VAR line: ARRAY 9 OF SET;
  321. BEGIN
  322.     line[8] := {4};
  323.     line[7] := {3, 5};
  324.     line[6] := {2, 6};
  325.     line[5] := {1..3, 5..7};
  326.     line[4] := {3, 5};
  327.     line[3] := {3, 5};
  328.     line[2] := {3, 5};
  329.     line[1] := {3..5};
  330.     icon := Display.NewPattern(line, 9, 8);
  331.     line[8] := {4};
  332.     line[7] := {3..5};
  333.     line[6] := {2..6};
  334.     line[5] := {1..7};
  335.     line[4] := {3..5};
  336.     line[3] := {3..5};
  337.     line[2] := {3..5};
  338.     line[1] := {3..5};
  339.     invIcon := Display.NewPattern(line, 9, 8)
  340. END InitIcon;
  341. BEGIN
  342.     Texts.OpenWriter(w);
  343.     InitIcon;
  344.     hint := NIL
  345. END LinkElems.
  346.