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

  1. Syntax10.Scn.Fnt
  2. Syntax10i.Scn.Fnt
  3. Syntax12.Scn.Fnt
  4. Syntax10b.Scn.Fnt
  5. MODULE Edit;    (** CAS/MH/HM 27.4.1994 **)
  6.     IMPORT
  7.         Modules, Oberon, Files, Display, Viewers, MenuViewers, Fonts, Printer,
  8.         Texts, TextFrames, ParcElems, TextPrinter;
  9.     CONST
  10.         OptionChar = "\";    (* << RC *)
  11.         Menu = "System.Close  System.Copy  System.Grow  Edit.Search  Edit.Replace  Edit.Parcs  Edit.Store ";
  12.         mm = TextFrames.mm; unit = TextFrames.Unit; Unit = TextPrinter.Unit;
  13.         Scale = mm DIV 10;    (*unit of user setable attributes is 1/10 mm*)
  14.         headerX = 15 * mm DIV Unit;
  15.         headerW = 165 * mm DIV Unit;
  16.         bodyX = 15 * mm DIV Unit; bodyY = 15 * mm DIV Unit;
  17.         bodyW = 165 * mm DIV Unit; bodyMaxW = 180 * mm DIV Unit;
  18.         MaxPat = 128;
  19.         CR = 0DX;
  20.         R: Texts.Reader;
  21.         W: Texts.Writer;
  22.         mnam: ARRAY 12*3 + 1 OF CHAR;
  23.         find: RECORD
  24.             time, len: LONGINT;
  25.             buf: ARRAY MaxPat OF CHAR
  26.         END;
  27.         repl: RECORD
  28.             time: LONGINT;
  29.             buf: Texts.Buffer
  30.         END;
  31.     PROCEDURE Ch (ch: CHAR);
  32.     BEGIN Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)
  33.     END Ch;
  34.     PROCEDURE Str (s: ARRAY OF CHAR);
  35.     BEGIN Texts.WriteString(W, s); Texts.Append(Oberon.Log, W.buf)
  36.     END Str;
  37.     PROCEDURE Int (n: LONGINT);
  38.     BEGIN Texts.Write(W, " "); Texts.WriteInt(W, n, 0); Texts.Append(Oberon.Log, W.buf)
  39.     END Int;
  40.     PROCEDURE Ln;
  41.     BEGIN Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  42.     END Ln;
  43.     PROCEDURE Min (x, y: LONGINT): LONGINT;
  44.     BEGIN
  45.         IF x < y THEN RETURN x ELSE RETURN y END
  46.     END Min;
  47.     PROCEDURE AppendNum (VAR s: ARRAY OF CHAR; VAR i: INTEGER; n: LONGINT);
  48.         VAR j: INTEGER; digits: ARRAY 16 OF CHAR;
  49.     BEGIN j := 0;
  50.         REPEAT digits[j] := CHR(n MOD 10 + 30H); INC(j); n := n DIV 10 UNTIL n = 0;
  51.         REPEAT DEC(j); s[i] := digits[j]; INC(i) UNTIL j = 0;
  52.         s[i] := 0X
  53.     END AppendNum;
  54.     PROCEDURE AppendDate (VAR s: ARRAY OF CHAR);    (*s := s & "   (dd mmm yy)"*)
  55.         VAR time, date: LONGINT; i, j, k, m: INTEGER;
  56.     BEGIN Oberon.GetClock(time, date); i := 0;
  57.         WHILE s[i] # 0X DO INC(i) END;
  58.         s[i] := " "; s[i + 1] := " "; s[i + 2] := " "; s[i + 3] := "("; INC(i, 4);
  59.         AppendNum(s, i, date MOD 20H); s[i] := " "; INC(i);
  60.         m := SHORT((date DIV 20H) MOD 10H); k := m * 3; j := k - 3;
  61.         REPEAT s[i] := mnam[j]; INC(i); INC(j) UNTIL j = k;
  62.         s[i] := " "; INC(i); AppendNum(s, i, (date DIV 200H) MOD 100);
  63.         s[i] := ")"; s[i + 1] := 0X
  64.     END AppendDate;
  65.     PROCEDURE ShowAliens (t: Texts.Text);
  66.         VAR R: Texts.Reader; identify: Texts.IdentifyMsg;
  67.     BEGIN
  68.         Texts.OpenReader(R, t, 0); Texts.ReadElem(R);
  69.         WHILE ~R.eot DO identify.mod[31] := 0X; R.elem.handle(R.elem, identify);
  70.             IF identify.mod[31] = 1X THEN Ln; Str("pos"); Int(Texts.Pos(R) - 1);
  71.                 Str("  unknown element allocator: "); Str(identify.mod); Ch("."); Str(identify.proc)
  72.             END;
  73.             Texts.ReadElem(R)
  74.         END;
  75.         IF W.buf.len > 0 THEN Ln; Texts.Append(Oberon.Log, W.buf) END
  76.     END ShowAliens;
  77.     (* view support *)
  78.     PROCEDURE ShowPos (F: TextFrames.Frame; pos: LONGINT);
  79.         VAR beg, end, delta: LONGINT;
  80.     BEGIN delta := 200;
  81.         LOOP beg := F.org; end := TextFrames.Pos(F, F.X + F.W, F.Y);
  82.             IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END;
  83.             TextFrames.Show(F, pos - delta); delta := delta DIV 2
  84.         END
  85.     END ShowPos;
  86.     PROCEDURE SetCaret (F: TextFrames.Frame; pos: LONGINT);
  87.     BEGIN Oberon.PassFocus(Viewers.This(F.X, F.Y)); TextFrames.SetCaret(F, pos)
  88.     END SetCaret;
  89.     PROCEDURE NewView (name: ARRAY OF CHAR; class: INTEGER;
  90.             T: Texts.Text; org: LONGINT): TextFrames.Frame;
  91.         VAR V: MenuViewers.Viewer; F, M: TextFrames.Frame; buf: Texts.Buffer; i, x, y: INTEGER;
  92.     BEGIN
  93.         IF class = Texts.String THEN i := 0;
  94.             WHILE name[i] # 0X DO INC(i) END;
  95.             name[i] := 22X; INC(i); name[i] := 0X;
  96.             WHILE i >= 0 DO name[i+1] := name[i]; DEC(i) END;
  97.             name[0] := 22X
  98.         END;
  99.         F := TextFrames.NewText(T, org);
  100.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  101.         IF Files.Old("Edit.Menu.Text") = NIL THEN M := TextFrames.NewMenu(name, Menu)
  102.         ELSE M := TextFrames.NewMenu(name, "");
  103.             NEW(T); Texts.Open(T, "Edit.Menu.Text");
  104.             NEW(buf); Texts.OpenBuf(buf); Texts.Save(T, 0, T.len, buf); Texts.Append(M.text, buf)
  105.         END;
  106.         V := MenuViewers.New(M, F, TextFrames.menuH, x, y);
  107.         ShowPos(F, org);
  108.         RETURN F
  109.     END NewView;
  110.     (* search & replace *)
  111.     PROCEDURE Find (T: Texts.Text; beg: LONGINT; VAR end: LONGINT);
  112.         VAR i, j, b, e: INTEGER; ch: CHAR; ref: ARRAY MaxPat OF CHAR;    (*ref [b..e) is readback buffer*)
  113.     BEGIN
  114.         Texts.OpenReader(R, T, beg); Texts.Read(R, ch); i := 0; ref[0] := ch; j := 0; b := 0; e := 1;
  115.         WHILE ~R.eot & (i < find.len) DO
  116.             IF (find.buf[i] = ch)
  117.                 OR (find.buf[i] = 0FFX)
  118.                     & ((ch < "0") OR (ch > "9") & (ch < "A") OR (ch > "Z") & (ch < "a") OR (ch > "z"))
  119.                         THEN INC(i); j := (j + 1) MOD MaxPat
  120.             ELSE i := 0; b := (b + 1) MOD MaxPat; j := b
  121.             END;
  122.             IF j # e THEN ch := ref[j]
  123.             ELSE Texts.Read(R, ch); ref[j] := ch; e := (e + 1) MOD MaxPat; INC(beg);
  124.             END
  125.         END;
  126.         IF i = find.len THEN end := beg ELSE end := -1 END
  127.     END Find;
  128.     PROCEDURE Check (T: Texts.Text; beg: LONGINT): BOOLEAN;
  129.         VAR ch: CHAR; i: INTEGER;
  130.     BEGIN i := 0;
  131.         IF (beg >= 0) & (find.len > 0) THEN Texts.OpenReader(R, T, beg); Texts.Read(R, ch);
  132.             WHILE ~R.eot & (i < find.len) & (ch = find.buf[i]) DO Texts.Read(R, ch); INC(i) END;
  133.         END;
  134.         RETURN i = find.len
  135.     END Check;
  136.     PROCEDURE SetReplBuf;
  137.         VAR T: Texts.Text; B: Texts.Buffer; beg, end, time: LONGINT;
  138.     BEGIN Oberon.GetSelection(T, beg, end, time);
  139.         IF time > repl.time THEN repl.time := time;
  140.             Texts.OpenBuf(repl.buf); Texts.Save(T, beg, end, repl.buf)
  141.         END
  142.     END SetReplBuf;
  143.     PROCEDURE Subst (T: Texts.Text; beg: LONGINT; VAR end: LONGINT);
  144.     BEGIN Texts.Delete(T, beg, beg + find.len);
  145.         end := beg + repl.buf.len;
  146.         IF repl.buf.len > 0 THEN
  147.             Texts.Insert(T, beg, repl.buf); Texts.Save(T, beg, end, repl.buf)
  148.         END
  149.     END Subst;
  150.     (* arguments *)
  151.     PROCEDURE MarkedFrame (): TextFrames.Frame;
  152.         VAR V: Viewers.Viewer;
  153.     BEGIN V := Oberon.MarkedViewer();
  154.         IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc.next IS TextFrames.Frame) THEN
  155.             RETURN V.dsc.next(TextFrames.Frame)
  156.         ELSE RETURN NIL
  157.         END
  158.     END MarkedFrame;
  159.     PROCEDURE FocusFrame (): TextFrames.Frame;
  160.         VAR V: Viewers.Viewer; f: Display.Frame;
  161.     BEGIN V := Oberon.FocusViewer;
  162.         IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc # NIL) THEN f := V.dsc.next;
  163.             IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END
  164.         ELSE RETURN NIL
  165.         END
  166.     END FocusFrame;
  167.     PROCEDURE TargetFrame (): TextFrames.Frame;    (*body frame or focus frame*)
  168.         VAR f: Display.Frame;
  169.     BEGIN
  170.         IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN f := Oberon.Par.frame.next;
  171.             IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END
  172.         ELSE RETURN FocusFrame()
  173.         END
  174.     END TargetFrame;
  175.     PROCEDURE GetMainArg (VAR S: Texts.Scanner; VAR end: LONGINT); (*takes recent selection if ^*)
  176.         VAR text: Texts.Text; beg, time: LONGINT;
  177.     BEGIN Texts.Scan(S); end := MAX(LONGINT);
  178.         IF (S.class = Texts.Char) & (S.c = "^") THEN Oberon.GetSelection(text, beg, end, time);
  179.             IF time >= 0 THEN Texts.OpenScanner(S, text, beg); Texts.Scan(S) END
  180.         END;
  181.         IF S.line # 0 THEN S.class := Texts.Inval END
  182.     END GetMainArg;
  183.     PROCEDURE GetArg (VAR S: Texts.Scanner);
  184.         (*takes selection in command frame if ^*)
  185.         VAR F: TextFrames.Frame;
  186.     BEGIN
  187.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  188.         IF (S.class = Texts.Char) & (S.c = "^") THEN F := Oberon.Par.frame(TextFrames.Frame);
  189.             IF F.hasSel THEN 
  190.                 Texts.OpenScanner(S, F.text, F.selbeg.pos); Texts.Scan(S); F.time := 0;
  191.             END
  192.         END
  193.     END GetArg;
  194.     PROCEDURE Change (sel: SET);
  195.         VAR S: Texts.Scanner; fnt: Fonts.Font; text: Texts.Text; beg, end, time: LONGINT; col, off: SHORTINT;
  196.     BEGIN GetArg(S); Oberon.GetSelection(text, beg, end, time);
  197.         IF time >= 0 THEN
  198.             IF (sel = {0}) & (S.class = Texts.Name) THEN fnt := Fonts.This(S.s)
  199.             ELSIF (sel = {1}) & (S.class = Texts.Int) & (0 <= S.i) & (S.i < 16) THEN col := SHORT(SHORT(S.i))
  200.             ELSIF (sel = {2}) & (S.class = Texts.Int) & (-128 <= S.i) & (S.i < 128) THEN off := SHORT(SHORT(S.i))
  201.             ELSE sel := {}
  202.             END;
  203.             IF sel # {} THEN Texts.ChangeLooks(text, beg, end, sel, fnt, col, off) END
  204.         END
  205.     END Change;
  206.     (* commands *)
  207.     PROCEDURE Locate*;
  208.         VAR S: Texts.Scanner; F: TextFrames.Frame; text: Texts.Text; beg, end, time: LONGINT;
  209.     BEGIN F := MarkedFrame(); Oberon.GetSelection(text, beg, end, time);
  210.         IF time > 0 THEN Texts.OpenScanner(S, text, beg); Texts.Scan(S);
  211.             WHILE (S.class # Texts.Int) & (S.line = 0) & ~S.eot DO Texts.Scan(S) END;
  212.             IF (F # NIL) & (S.class = Texts.Int) & (S.line = 0) THEN ShowPos(F, S.i); SetCaret(F, S.i) END
  213.         END;
  214.     END Locate;
  215.     PROCEDURE Search*;
  216.         VAR F: TextFrames.Frame; T: Texts.Text; i, beg, end, time: LONGINT; ch: CHAR;
  217.     BEGIN Oberon.GetSelection(T, beg, end, time); F := TargetFrame();
  218.         IF time > find.time THEN find.time := time; find.len := Min(end - beg, MaxPat);
  219.             Texts.OpenReader(R, T, beg); i := 0;
  220.             REPEAT Texts.Read(R, find.buf[i]); INC(i) UNTIL i = find.len
  221.         END;
  222.         IF F # NIL THEN
  223.             IF F.hasCar THEN beg := F.carloc.pos ELSE beg := 0 END;
  224.             Find(F.text, beg, end);
  225.             IF end >= 0 THEN ShowPos(F, end); SetCaret(F, end)
  226.             ELSE TextFrames.RemoveCaret(F)
  227.             END;
  228.             TextFrames.RemoveSelection(F)
  229.         END
  230.     END Search;
  231.     PROCEDURE Show*;
  232.         VAR S: Texts.Scanner; R: Texts.Reader; F: TextFrames.Frame; text: Texts.Text;
  233.             i, j, beg, end, time: LONGINT; ch: CHAR;
  234.             name: ARRAY Modules.ModNameLen + 4 OF CHAR;
  235.     BEGIN text := Oberon.Par.text; beg := Oberon.Par.pos; end := Oberon.Par.text.len; time := Oberon.Time();
  236.         Texts.OpenScanner(S, text, beg); Texts.Scan(S);
  237.         IF (S.class = Texts.Char) & (S.c = "^") OR (S.line > 0) THEN Oberon.GetSelection(text, beg, end, time);
  238.             IF time >= 0 THEN Texts.OpenScanner(S, text, beg); Texts.Scan(S) END
  239.         END;
  240.         IF (time >= 0) & (S.class = Texts.Name) THEN i := 0;
  241.             WHILE (S.s[i] # 0X) & (S.s[i] # ".") DO name[i] := S.s[i]; INC(i) END;
  242.             IF i < Modules.ModNameLen THEN
  243.                 name[i] := "."; name[i+1] := "M"; name[i+2] := "o"; name[i+3] := "d"; name[i+4] := 0X;
  244.                 find.len := 0; j := i + 1; 
  245.                 WHILE S.s[j] # 0X DO find.buf[find.len] := S.s[j]; INC(find.len); INC(j) END;
  246.                 find.buf[find.len] := 0FFX; INC(find.len);
  247.                 find.time := time;
  248.                 text := TextFrames.Text(name);
  249.                 Find(text, 0, end); IF end < 0 THEN end := 0 END;
  250.                 F := NewView(name, Texts.Name, text, end);
  251.                 IF end > 0 THEN SetCaret(F, end) END
  252.             END
  253.         END
  254.     END Show;
  255.     PROCEDURE Recall*;
  256.         VAR B: Texts.Buffer; copyover: Oberon.CopyOverMsg;
  257.     BEGIN Texts.Recall(B);
  258.         IF B # NIL THEN copyover.beg := 0; copyover.end := B.len;
  259.             copyover.text := TextFrames.Text(""); Texts.Append(copyover.text, B);
  260.             Oberon.FocusViewer.handle(Oberon.FocusViewer, copyover)
  261.         END
  262.     END Recall;
  263.     PROCEDURE ClearReplaceBuffer*;
  264.     BEGIN Texts.OpenBuf(repl.buf)
  265.     END ClearReplaceBuffer;
  266.     PROCEDURE Replace*;
  267.         VAR F: TextFrames.Frame; T: Texts.Text; beg, end: LONGINT;
  268.     BEGIN F := TargetFrame(); SetReplBuf;
  269.         IF (F # NIL) & F.hasCar THEN T := F.text; end := F.carloc.pos; beg := end - find.len;
  270.             TextFrames.RemoveSelection(F);
  271.             IF Check(T, beg) THEN Subst(T, beg, end) END;
  272.             Find(T, end, beg);
  273.             IF beg >= 0 THEN ShowPos(F, beg); SetCaret(F, beg)
  274.             ELSE TextFrames.RemoveCaret(F)
  275.             END
  276.         END
  277.     END Replace;
  278.     PROCEDURE ReplaceAll*;
  279.         VAR F: TextFrames.Frame; T: Texts.Text; beg, end: LONGINT;
  280.     BEGIN F := TargetFrame(); SetReplBuf;
  281.         IF (F # NIL) & F.hasCar THEN T := F.text; end := F.carloc.pos; beg := end - find.len;
  282.             TextFrames.RemoveSelection(F);
  283.             IF Check(T, beg) THEN Subst(T, beg, end) END;
  284.             LOOP Find(T, end, beg);
  285.                 IF beg < 0 THEN EXIT END;
  286.                 Subst(T, beg - find.len, end)
  287.             END
  288.         END
  289.     END ReplaceAll;
  290.     PROCEDURE ChangeFont*;
  291.     BEGIN Change({0})
  292.     END ChangeFont;
  293.     PROCEDURE ChangeColor*;
  294.     BEGIN Change({1})
  295.     END ChangeColor;
  296.     PROCEDURE ChangeOffset*;
  297.     BEGIN Change({2})
  298.     END ChangeOffset;
  299.     PROCEDURE ChangeBackgroundColor*;
  300.         VAR F: TextFrames.Frame; m: MenuViewers.ModifyMsg; S: Texts.Scanner; H: INTEGER;
  301.     BEGIN F := MarkedFrame();
  302.         IF F # NIL THEN GetArg(S);
  303.             IF S.class = Texts.Int THEN
  304.                 F.col := SHORT(SHORT(S.i)) MOD (Display.white+1);    (*<< SHML/CN *)
  305.                 m.id := MenuViewers.extend; m.Y := F.Y; H := F.H;
  306.                 m.H := 0; F.handle(F, m); (*suspend*)
  307.                 m.H := H; F.handle(F, m) (*extend*)
  308.             END
  309.         END
  310.     END ChangeBackgroundColor;
  311.     PROCEDURE InsertParc*;
  312.         VAR copy: Texts.CopyMsg; insert: TextFrames.InsertElemMsg;
  313.     BEGIN
  314.         TextFrames.defParc.handle(TextFrames.defParc, copy); insert.e := copy.e;
  315.         Oberon.FocusViewer.handle(Oberon.FocusViewer, insert)
  316.     END InsertParc;
  317.     PROCEDURE Parcs*;
  318.         VAR S: Texts.Scanner; V: Viewers.Viewer; F: TextFrames.Frame; um: TextFrames.UpdateMsg;
  319.             end: LONGINT; R: Texts.Reader;
  320.     BEGIN
  321.         IF Oberon.Par.frame # Oberon.Par.vwr.dsc THEN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  322.             Texts.Scan(S);
  323.             IF (S.class = Texts.Char) & (S.line = 0) & (S.c = "*") THEN V := Oberon.MarkedViewer() ELSE V := NIL END
  324.         ELSE V := Oberon.Par.vwr
  325.         END;
  326.         IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc.next IS TextFrames.Frame) THEN
  327.             F := V.dsc.next(TextFrames.Frame); F.showsParcs := ~ F.showsParcs;
  328.             Texts.OpenReader(R, F.text, F.org); Texts.ReadElem(R); end := TextFrames.Pos(F, F.X + F.W, F.Y);
  329.             WHILE (Texts.Pos(R) <= end) & (R.elem # NIL) & ~(R.elem IS TextFrames.Parc) DO Texts.ReadElem(R) END;
  330.             IF (R.elem # NIL) & (R.elem IS TextFrames.Parc) & (Texts.Pos(R) <= end) THEN
  331.                 um.id := Texts.replace; um.text := F.text; um.end := end;
  332.                 um.beg := Texts.Pos(R)-1;
  333.                 F.handle(F, um)
  334.             END
  335.         END
  336.     END Parcs;
  337.     PROCEDURE Open*;
  338.         VAR S: Texts.Scanner; F: TextFrames.Frame; end: LONGINT;
  339.     BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); GetMainArg(S, end);
  340.         IF (S.class = Texts.Name) OR (S.class = Texts.String) THEN
  341.             F := NewView(S.s, S.class, TextFrames.Text(S.s), 0);
  342.             ShowAliens(F.text)
  343.         END
  344.     END Open;
  345.     PROCEDURE Store*;
  346.         VAR S: Texts.Scanner; R: Texts.Reader; V: Viewers.Viewer; T: Texts.Text; ch: CHAR;
  347.     BEGIN V := NIL;
  348.         IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN V := Oberon.Par.vwr
  349.         ELSIF Oberon.Pointer.on THEN  V := Oberon.MarkedViewer()
  350.         END;
  351.         IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc IS TextFrames.Frame) & (V.dsc.next IS TextFrames.Frame) THEN
  352.             Texts.OpenScanner(S, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(S);
  353.             IF (S.class = Texts.Name) OR (S.class = Texts.String) THEN
  354.                 Str("Edit.Store "); Str(S.s); T := V.dsc.next(TextFrames.Frame).text;
  355.                 Texts.Close(T, S.s); Int(T.len); Ln;
  356.                 T := V.dsc(TextFrames.Frame).text;
  357.                 Texts.OpenReader(R, T, T.len - 1); Texts.Read(R, ch);
  358.                 IF ch = "!" THEN Texts.Delete(T, T.len - 1, T.len) END
  359.             END
  360.         END
  361.     END Store;
  362.     PROCEDURE Set*;
  363.         VAR S: Texts.Scanner; R: Texts.Reader; text: Texts.Text; P: TextFrames.Parc;
  364.             msg: ParcElems.StateMsg; pos, beg, end, time: LONGINT;
  365.     BEGIN GetArg(S); Oberon.GetSelection(text, beg, end, time);
  366.         IF time >= 0 THEN Texts.OpenReader(R, text, beg); 
  367.             REPEAT Texts.ReadElem(R); pos := Texts.Pos(R);
  368.                 IF ~R.eot & (pos <= end) & (R.elem IS TextFrames.Parc) THEN
  369.                     msg.id := ParcElems.set; msg.pos := pos - 1; msg.frame := NIL; msg.par := S; msg.log := Oberon.Log;
  370.                     P := R.elem(TextFrames.Parc); P.handle(P, msg);
  371.                 END
  372.             UNTIL R.eot OR (pos > end)
  373.         ELSE Str("Edit.Set failed (no parc selected)"); Ln
  374.         END
  375.     END Set;
  376.     PROCEDURE Get*;
  377.         VAR S: Texts.Scanner; R: Texts.Reader; text: Texts.Text; P: TextFrames.Parc; pos, beg, end, time: LONGINT;
  378.             msg: ParcElems.StateMsg;
  379.     BEGIN GetArg(S); Oberon.GetSelection(text, beg, end, time);
  380.         IF time >= 0 THEN
  381.             Texts.OpenReader(R, text, beg); Texts.ReadElem(R); pos := Texts.Pos(R);
  382.             IF ~R.eot & (pos <= end) & (R.elem IS TextFrames.Parc) THEN
  383.                 Str("Edit.Set ^ ");
  384.                 msg.id := ParcElems.get; msg.pos := pos - 1; msg.frame := NIL; msg.par := S; msg.log := Oberon.Log;
  385.                 P := R.elem(TextFrames.Parc); P.handle(P, msg)
  386.             ELSE Str("Edit.Get failed (no parc selected)")
  387.             END
  388.         ELSE Str("Edit.Get failed (no parc selected)")
  389.         END;
  390.     END Get;
  391.     PROCEDURE Print*;
  392.         VAR S, S1: Texts.Scanner; V: Viewers.Viewer; F: TextFrames.Frame; end: LONGINT; draft: BOOLEAN;
  393.         PROCEDURE PrintText(VAR S: Texts.Scanner; T: Texts.Text; name: ARRAY OF CHAR; draft: BOOLEAN);
  394.             CONST headerLen = 128;
  395.             VAR pos, len: LONGINT; ch: CHAR;
  396.                 hx, hy, hw, bx, by, bw, bh, i, k: INTEGER;
  397.                 nofcopies, pno, first, last, arab: INTEGER;
  398.                 fnt: Fonts.Font; label, labelfirst, alt: BOOLEAN;
  399.                 header: ARRAY headerLen OF CHAR;
  400.         BEGIN hx := headerX; hw := headerW;
  401.             hy := SHORT((LONG(Printer.PageHeight) * Unit - 17 * mm) DIV Unit);
  402.             bx := bodyX; by := bodyY; bw := bodyW;
  403.             bh := SHORT((LONG(Printer.PageHeight) * Unit - 37 * mm) DIV Unit);
  404.             nofcopies := 1; pno := 0; first := 0; last := 10000; arab := 1;
  405.             label := TRUE; labelfirst := TRUE; alt := FALSE;
  406.             header[0] := 0X; fnt := Fonts.Default;
  407.             Texts.Scan(S);
  408.             WHILE (S.class = Texts.Char) & (S.c = OptionChar) DO
  409.                 Texts.Scan(S);
  410.                 IF S.class = Texts.Name THEN ch := CAP(S.s[0]);
  411.                     IF ch # "H" THEN Texts.Scan(S) END;
  412.                     IF ch = "A" THEN alt := TRUE
  413.                     ELSIF (ch = "C") & (S.class = Texts.Int) & (1 <= S.i) & (S.i < 10) THEN nofcopies := SHORT(S.i); Texts.Scan(S)
  414.                     ELSIF (ch = "F") & (S.class = Texts.Name) THEN fnt := Fonts.This(S.s); Texts.Scan(S)
  415.                     ELSIF ch = "H" THEN
  416.                         REPEAT Texts.Read(S, ch) UNTIL (ch > " ") OR S.eot;
  417.                         IF ch = 22X THEN i := 0; (* read string *)
  418.                             REPEAT Texts.Read(S, ch); header[i] := ch; INC(i) UNTIL (ch = 22X) OR (ch = CR);
  419.                             header[i-1] := 0X; Texts.Read(S, ch);
  420.                             (*COPY(S.s, header); Texts.Scan(S)*)
  421.                         ELSE COPY(name, header); AppendDate(header)
  422.                         END;
  423.                         S.nextCh := ch; Texts.Scan(S);
  424.                     ELSIF ch = "M" THEN    (*margin options*)
  425.                         IF S.class = Texts.Name THEN ch := CAP(S.s[0]); Texts.Scan(S); i := 0;
  426.                             WHILE (S.class = Texts.Int) & (0 <= S.i) DO
  427.                                 k := SHORT(S.i * Scale DIV TextPrinter.Unit); INC(i); Texts.Scan(S);
  428.                                 IF ch = "H" THEN
  429.                                     IF i = 1 THEN hx := k ELSIF i = 2 THEN hy := k ELSIF i = 3 THEN hw := k END
  430.                                 ELSIF ch = "B" THEN
  431.                                     IF i = 1 THEN bx := k ELSIF i = 2 THEN by := k
  432.                                     ELSIF i = 3 THEN bw := k ELSIF i = 4 THEN bh := k
  433.                                     END
  434.                                 END
  435.                             END
  436.                         END
  437.                     ELSIF ch = "P" THEN    (*page numbering options*)
  438.                         IF (S.class = Texts.Int) & (0 <= S.i) THEN pno := SHORT(S.i); first := pno; Texts.Scan(S)
  439.                         ELSIF S.class = Texts.Name THEN ch := CAP(S.s[0]); Texts.Scan(S);
  440.                             IF ch = "F" THEN labelfirst := FALSE
  441.                             ELSIF ch = "N" THEN label := FALSE
  442.                             ELSIF ch = "R" THEN arab := -1;
  443.                                 IF first = 0 THEN pno := 1; first := 1 END
  444.                             END
  445.                         END
  446.                     ELSIF (ch = "S") & (S.class = Texts.Int) & (0 <= S.i) THEN first := SHORT(S.i); Texts.Scan(S);
  447.                         IF (S.class = Texts.Int) & (0 <= S.i) THEN last := SHORT(S.i); Texts.Scan(S) ELSE last := first END
  448.                     END
  449.                 END
  450.             END;
  451.             Ch(" "); Str(name); Int(nofcopies); Ch(" ");
  452.             IF draft THEN TextPrinter.PrintDraft(T, name, nofcopies)
  453.             ELSE pos := 0; len := T.len;
  454.                 WHILE (pos < len) & (pno <= last) & (Printer.res = 0) DO
  455.                     IF (first <= pno) & label & labelfirst THEN
  456.                         TextPrinter.PlaceHeader(hx, hy, hw, arab*pno, fnt, header, alt)
  457.                     END;
  458.                     TextPrinter.PlaceBody(bx, by, bw, bh, T, pos, pno, (first <= pno) & (pno <= last));
  459.                     IF first <= pno THEN Printer.Page(nofcopies); Ch(".") ELSE Ch("'") END;
  460.                     INC(pno); labelfirst := TRUE
  461.                 END
  462.             END;
  463.             Ln
  464.         END PrintText;
  465.     BEGIN Str("Edit.Print "); Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  466.         IF ((S.class = Texts.Name) OR (S.class = Texts.String)) & (S.line = 0) THEN Str(S.s);
  467.             Printer.Open(S.s, Oberon.User, Oberon.Password); TextPrinter.InitFonts;
  468.             IF Printer.res = 0 THEN GetMainArg(S, end);
  469.                 IF (S.class = Texts.Char) & (S.c = "%") THEN draft := TRUE; Texts.Scan(S) ELSE draft := FALSE END;
  470.                 IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN
  471.                     F := Oberon.Par.frame(TextFrames.Frame);
  472.                     IF (F.next # NIL) & (F.next IS TextFrames.Frame) THEN
  473.                         Texts.OpenScanner(S1, F.text, 0); Texts.Scan(S1);
  474.                         PrintText(S, F.next(TextFrames.Frame).text, S1.s, draft)
  475.                     END
  476.                 ELSIF (S.class = Texts.Char) & (S.c = "*") THEN V := Oberon.MarkedViewer();
  477.                     IF (V IS MenuViewers.Viewer) & (V.dsc.next IS TextFrames.Frame) THEN
  478.                         Texts.OpenScanner(S1, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(S1);
  479.                         IF S1.class # Texts.Name THEN S1.s[0] := "*"; S1.s[1] := 0X END;
  480.                         PrintText(S, V.dsc.next(TextFrames.Frame).text, S1.s, draft)
  481.                     ELSE Str(" failed (bad * marker)"); Ln
  482.                     END
  483.                 ELSIF S.class = Texts.Name THEN
  484.                     REPEAT
  485.                         PrintText(S, TextFrames.Text(S.s), S.s, draft)
  486.                     UNTIL S.eot OR (S.class # Texts.Name) OR (Texts.Pos(S) > end)
  487.                 ELSE Ln
  488.                 END;
  489.                 Printer.Close
  490.             ELSE Str(" failed (");
  491.                 IF Printer.res = 1 THEN Str("no such printer)")
  492.                 ELSIF Printer.res = 2 THEN Str("no link)")
  493.                 ELSIF Printer.res = 3 THEN Str("printer not ready)")
  494.                 ELSIF Printer.res = 4 THEN Str("no permission)")
  495.                 ELSE Str("res ="); Int(Printer.res); Str(" ?)")
  496.                 END;
  497.                 Ln
  498.             END
  499.         ELSE Str("failed (no printer specified)"); Ln
  500.         END
  501.     END Print;
  502. BEGIN Texts.OpenWriter(W);
  503.     mnam := "JanFebMarAprMayJunJulAugSepOctNovDec";
  504.     find.time := -1; find.len := 0;
  505.     repl.time := -1; NEW(repl.buf); Texts.OpenBuf(repl.buf)
  506. END Edit.
  507.