ðÒSyntax10.Scn.FntSyntax10i.Scn.Fntõÿÿÿð+°­StampElemsAlloc17 Aug 95¬Syntax10b.Scn.FntB9>]üÿÿÿÀÔ°­MarkElemsAllocQä~´üÿÿÿÀÔ°­Rä~¼cüÿÿÿÀÔ°­Sä~NüÿÿÿÀÔ°­Vä~‹üÿÿÿÀÔ°­Yä~=üÿÿÿÀÔ°­[ä~YüÿÿÿÀÔ°­]ä~ÄüÿÿÿÀÔ°­^ä~ÓMODULE SectionLinkElems; (** MK  *) IMPORT Files, Fonts, Display, Viewers, Texts, TextFrames, Oberon, MarkElems, FoldElems, TextPrinter, Printer, LinkElems; CONST pixel = LONG(10000); CR = 13X; TYPE Elem* = POINTER TO ElemDesc; ElemDesc* = RECORD (LinkElems.ElemDesc) END; VAR searchKey: LONGINT; (*key of mark element searched in FollowLink; used in Check*) hint: TextFrames.Frame; (*suggests frame to be used for links emanating from a link menu*) w: Texts.Writer; PROCEDURE^ New* (file: ARRAY OF CHAR; key: LONGINT): Elem; PROCEDURE GetFileName (t: Texts.Text; VAR name: ARRAY OF CHAR); (* return the name of the viewer which contains text t*) VAR v, V: Viewers.Viewer; f: Display.Frame; s: Texts.Scanner; x: INTEGER; BEGIN V := NIL; x := 0; WHILE x < Display.Width DO v := Viewers.This(x, 0); WHILE v.state > 1 DO f := v.dsc; WHILE f # NIL DO IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = t) THEN V := v END; f := f.next END; v := Viewers.Next(v) END; x := x + v.W END; IF V # NIL THEN Texts.OpenScanner(s, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, name) ELSE name[0] := 0X END END END GetFileName; PROCEDURE GetFrame (name: ARRAY OF CHAR; VAR f: TextFrames.Frame); VAR x: INTEGER; v: Viewers.Viewer; s: Texts.Scanner; BEGIN IF hint # NIL THEN f := hint ELSE x := 0; f := NIL; WHILE x < Display.Width DO v := Viewers.This(x, 0); WHILE v.state > 1 DO IF (v.dsc # NIL) & (v.dsc IS TextFrames.Frame) THEN Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s); IF s.s = name THEN f := v.dsc.next(TextFrames.Frame); RETURN END END; v := Viewers.Next(v) END; x := x + v.W END END END GetFrame; PROCEDURE GetDsr (f: Display.Frame; pos: LONGINT; fnt: Fonts.Font; VAR dsr: INTEGER); VAR p: TextFrames.Parc; beg: LONGINT; BEGIN IF f = NIL THEN IF fnt = NIL THEN dsr := 0 ELSE dsr := - fnt.minY END ELSE TextFrames.ParcBefore(f(TextFrames.Frame).text, pos, p, beg); dsr := SHORT(p.dsr DIV TextFrames.Unit) END END GetDsr; PROCEDURE Check (e: Texts.Elem): BOOLEAN; BEGIN RETURN (e IS MarkElems.Elem) & (e(MarkElems.Elem).key = searchKey) END Check; PROCEDURE GetLink (file: ARRAY OF CHAR; key: LONGINT; VAR str: ARRAY OF CHAR); VAR mark: Texts.Elem; f: TextFrames.Frame; r: Texts.Reader; x: INTEGER; ch: CHAR; BEGIN GetFrame(file, f); IF f = NIL THEN f := TextFrames.NewText(TextFrames.Text(file), 0) END; searchKey := key; FoldElems.FindElem(f.text, 0, Check, mark); IF mark # NIL THEN Texts.OpenReader (r, f.text, Texts.ElemPos (mark) + 1); Texts.Read (r, ch); WHILE (ch = " ") & ~ r.eot DO Texts.Read (r, ch) END; x := 0; str[x] := ch; Texts.Read (r, ch); WHILE (ch # " ") & (ch # CR) & (ch # ":") & ~ r.eot DO INC (x); str[x] := ch; Texts.Read (r, ch) END; IF str[x] = "." THEN str[x] := 0X ELSE str[x + 1] := 0X END END END GetLink; PROCEDURE StrPrntWidth (fnt: Fonts.Font; s: ARRAY OF CHAR): LONGINT; VAR width, dx, x, y, w, h: LONGINT; i: INTEGER; fno: SHORTINT; ch: CHAR; BEGIN width := 0; fno := TextPrinter.FontNo(fnt); i := 0; ch := s[i]; WHILE ch # 0X DO TextPrinter.Get(fno, ch, dx, x, y, w, h); INC(width, dx); INC(i); ch := s[i] END; RETURN width END StrPrntWidth; PROCEDURE PrntStr (fnt: Fonts.Font; s: ARRAY OF CHAR; x0, y0: INTEGER); BEGIN Printer.String(x0, y0, s, fnt.name) END PrntStr; PROCEDURE PrepPrint (VAR e: Elem; str: ARRAY OF CHAR; fnt: Fonts.Font; VAR dy: INTEGER); BEGIN e.W := StrPrntWidth(fnt, str); e.H := LONG(fnt.height) * TextFrames.Unit; dy := SHORT(fnt.minY * LONG(TextFrames.Unit) DIV TextPrinter.Unit); IF dy > -2 THEN dy := -2 END END PrepPrint; PROCEDURE Print (VAR e: Elem; str: ARRAY OF CHAR; pos: LONGINT; fnt: Fonts.Font; x0, y0: INTEGER); VAR p: TextFrames.Parc; beg: LONGINT; BEGIN TextFrames.ParcBefore(Texts.ElemBase(e), pos, p, beg); INC(y0, SHORT(p.dsr DIV TextPrinter.Unit)); PrntStr(fnt, str, x0, y0); e.W := 10 * pixel; e.H := 11 * pixel END Print; PROCEDURE Handle* (e: Texts.Elem; VAR m: Texts.ElemMsg); VAR str: ARRAY 32 OF CHAR; e1: Elem; BEGIN WITH e: Elem DO WITH m: TextPrinter.PrintMsg DO GetLink (e.file, e.key, str); IF m.prepare THEN PrepPrint (e, str, m.fnt, m.Y0) ELSE Print (e, str, m.pos, m.fnt, m.X0, m.Y0) END | m: Texts.IdentifyMsg DO m.mod := "SectionLinkElems"; m.proc := "Alloc" | m: Texts.CopyMsg DO IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END; Texts.CopyElem(e, e1); COPY(e.file, e1.file); e1.key := e.key ELSE LinkElems.Handle (e, m) END END END Handle; PROCEDURE Alloc*; VAR e: Elem; BEGIN NEW(e); e.handle := Handle; Texts.new := e END Alloc; PROCEDURE New* (file: ARRAY OF CHAR; key: LONGINT): Elem; VAR e: Elem; BEGIN NEW(e); e.W := 10 * pixel; e.H := 11 * pixel; e.handle := Handle; COPY(file, e.file); e.key := key; RETURN e END New; PROCEDURE Insert*; VAR link: Elem; mark: MarkElems.Elem; fromT, toT: Texts.Text; toPos, end, time: LONGINT; r: Texts.Reader; ch: CHAR; m: TextFrames.InsertElemMsg; f: TextFrames.Frame; BEGIN f := Oberon.FocusViewer.dsc(TextFrames.Frame); IF f.hasCar THEN fromT := f.text ELSE fromT := f.next(TextFrames.Frame).text END; Oberon.GetSelection(toT, toPos, end, time); IF time >= 0 THEN link := New("", 0); GetFileName(toT, link.file); Texts.OpenReader(r, toT, toPos); Texts.Read(r, ch); m.e := link; Viewers.Broadcast(m); IF (ch = Texts.ElemChar) & (r.elem IS MarkElems.Elem) THEN link.key := r.elem(MarkElems.Elem).key ELSE IF (fromT = toT) & (Texts.ElemPos(link) <= toPos) THEN INC(toPos) END; mark := MarkElems.New(); link.key := mark.key; Texts.WriteElem(w, mark); Texts.Insert(toT, toPos, w.buf) END END END Insert; BEGIN Texts.OpenWriter(w); hint := NIL END SectionLinkElems.