ð¥Syntax10.Scn.FntSyntax10i.Scn.Fnt 2 wY™ÔÉ5P%MODULE StringElems; (* gri 6.5.92 *) IMPORT Oberon, Input, Display, Fonts, Viewers, MenuViewers, Files, Printer, Texts, TextFrames, WriteFrames, WritePrinter; CONST middleKey = 1; unit = WriteFrames.Unit; Unit = WritePrinter.Unit; marg = 2*unit; thick = unit DIV 2; Menu = "System.Close Write.Search Write.Replace All StringElems.Update"; TYPE Elem = POINTER TO ElemDesc; ElemDesc = RECORD (Texts.ElemDesc) string: ARRAY 32 OF CHAR END; Frame = POINTER TO FrameDesc; FrameDesc = RECORD (WriteFrames.FrameDesc) E: Elem END; VAR W: Texts.Writer; (* load / store *) PROCEDURE WriteString (VAR R: Files.Rider; s: ARRAY OF CHAR); VAR i: INTEGER; BEGIN i := 0; WHILE s[i] # 0X DO INC(i) END; Files.WriteBytes(R, s, i+1) END WriteString; PROCEDURE ReadString (VAR R: Files.Rider; VAR s: ARRAY OF CHAR); VAR i: INTEGER; ch: CHAR; BEGIN i := 0; REPEAT Files.Read(R, ch); s[i] := ch; INC(i) UNTIL ch = 0X END ReadString; (* display methods *) PROCEDURE* DSize (VAR s: ARRAY OF CHAR; fnt: Fonts.Font; VAR W, H: LONGINT); VAR i, sx, dx, x, y, w, h: INTEGER; pat: Display.Pattern; BEGIN i := 0; sx := 0; WHILE s[i] # 0X DO Display.GetChar(fnt.raster, s[i], dx, x, y, w, h, pat); INC(sx, dx); INC(i) END; W := sx * LONG(unit) + 2*marg; H := fnt.height * LONG(unit) + 2*marg END DSize; PROCEDURE* DBlock (x, y, w, h: INTEGER; col: SHORTINT); BEGIN Display.ReplConst(col, x, y, w, h, Display.replace) END DBlock; PROCEDURE* DString (x0, y0: INTEGER; VAR s: ARRAY OF CHAR; fnt: Fonts.Font; col: SHORTINT); VAR i, dx, x, y, w, h: INTEGER; pat: Display.Pattern; BEGIN INC(y0, -fnt.minY); i := 0; WHILE s[i] # 0X DO Display.GetChar(fnt.raster, s[i], dx, x, y, w, h, pat); Display.CopyPattern(col, pat, x0+x, y0+y, Display.paint); INC(x0, dx); INC(i) END END DString; (* printer methods *) PROCEDURE* PSize (VAR s: ARRAY OF CHAR; fnt: Fonts.Font; VAR W, H: LONGINT); VAR fno: SHORTINT; i: INTEGER; sX, dX, X, Y: LONGINT; BEGIN fno := WritePrinter.FontNo(fnt); i := 0; sX := 0; WHILE s[i] # 0X DO WritePrinter.Get(fno, s[i], dX, X, Y, W, H); INC(sX, dX); INC(i) END; W := sX + 2*marg; H := fnt.height * LONG(unit) + 2*marg END PSize; PROCEDURE* PBlock (x, y, w, h: INTEGER; col: SHORTINT); BEGIN Printer.ReplConst(x, y, w, h) END PBlock; PROCEDURE* PString (x0, y0: INTEGER; VAR s: ARRAY OF CHAR; fnt: Fonts.Font; col: SHORTINT); BEGIN Printer.String(x0, y0 - SHORT(fnt.minY * LONG(unit) DIV Unit), s, fnt.name) END PString; (* drawing *) PROCEDURE Draw (E: Elem; x, y: INTEGER; fnt: Fonts.Font; col: SHORTINT; unit: LONGINT; Block: PROCEDURE (x, y, w, h: INTEGER; col: SHORTINT); String: PROCEDURE (x0, y0: INTEGER; VAR s: ARRAY OF CHAR; fnt: Fonts.Font; col: SHORTINT)); VAR w, h, m1, m2, d, m1d: INTEGER; BEGIN w := SHORT(E.W DIV unit); h := SHORT(E.H DIV unit); IF (w > 0) & (h > 0) THEN m1 := SHORT(thick DIV unit); m2 := SHORT(marg DIV unit); IF m1 < 1 THEN d := 1 ELSE d := m1 END; m1d := m1+d; Block(x+m1, y+m1, w - 2*m1, d, col); Block(x+m1, y+h-m1d, w - 2*m1, d, col); Block(x+m1, y+m1d, d, h - 2*m1d, col); Block(x+w-m1d, y+m1d, d, h - 2*m1d, col); String(x+m2, y+m2, E.string, fnt, col) END END Draw; (* editing *) PROCEDURE NewTextFrame (E: Elem): Frame; VAR T: Texts.Text; F: Frame; BEGIN Texts.Write(W, 22X); Texts.WriteString(W, E.string); Texts.Write(W, 22X); T := WriteFrames.Text(""); Texts.Append(T, W.buf); NEW(F); F.E := E; WriteFrames.Open(F, WriteFrames.Handle, T, 0, WriteFrames.defLeft, WriteFrames.defRight, WriteFrames.defTop, WriteFrames.defBot, WriteFrames.defBarW, WriteFrames.defOpts); RETURN F END NewTextFrame; PROCEDURE Edit (E: Elem; x, y: INTEGER; keySum: SET); VAR w, h, mx, my: INTEGER; keys: SET; V: Viewers.Viewer; BEGIN w := SHORT(E.W DIV unit); h := SHORT(E.H DIV unit); Display.ReplConst(Display.white, x, y, w, h, Display.invert); REPEAT Input.Mouse(keys, mx, my); keySum := keySum + keys; Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my) UNTIL keys = {}; Display.ReplConst(Display.white, x, y, w, h, Display.invert); IF keySum = {middleKey} THEN Oberon.AllocateUserViewer(x, x, y); V := MenuViewers.New(TextFrames.NewMenu("", Menu), NewTextFrame(E), TextFrames.menuH, x, y) END END Edit; PROCEDURE Update*; VAR F: Display.Frame; E: Elem; S: Texts.Scanner; T: Texts.Text; R: Texts.Reader; pos: LONGINT; BEGIN F := Oberon.Par.frame; IF (F # NIL) & (F.next # NIL) THEN F := F.next; IF F IS Frame THEN WITH F: Frame DO E := F.E; Texts.OpenScanner(S, F.text, 0); Texts.Scan(S); IF (S.line = 0) & (S.class IN {Texts.Name, Texts.String}) THEN COPY(S.s, E.string) ELSE E.string := "" END; T := Texts.ElemBase(E); IF T # NIL THEN Texts.OpenReader(R, T, 0); REPEAT Texts.ReadElem(R) UNTIL R.elem = E; pos := Texts.Pos(R); Texts.ChangeLooks(T, pos-1, pos, {}, NIL, 0, 0) END END END END END Update; (* handler *) PROCEDURE* Handle (E: Texts.Elem; VAR msg: Texts.ElemMsg); VAR e: Elem; BEGIN WITH E: Elem DO IF msg IS WriteFrames.DisplayMsg THEN WITH msg: WriteFrames.DisplayMsg DO IF msg.prepare THEN DSize(E.string, msg.fnt, E.W, E.H) ELSE Draw(E, msg.X0, msg.Y0, msg.fnt, msg.col, unit, DBlock, DString) END END ELSIF msg IS WritePrinter.PrintMsg THEN WITH msg: WritePrinter.PrintMsg DO IF msg.prepare THEN PSize(E.string, msg.fnt, E.W, E.H) ELSE Draw(E, msg.X0, msg.Y0, msg.fnt, msg.col, Unit, PBlock, PString) END END ELSIF msg IS Texts.IdentifyMsg THEN WITH msg: Texts.IdentifyMsg DO msg.mod := "StringElems"; msg.proc := "Alloc" END ELSIF msg IS Texts.FileMsg THEN WITH msg: Texts.FileMsg DO IF msg.id = Texts.load THEN ReadString(msg.r, E.string) ELSIF msg.id = Texts.store THEN WriteString(msg.r, E.string) END END ELSIF msg IS Texts.CopyMsg THEN NEW(e); Texts.CopyElem(E, e); e.string := E.string; msg(Texts.CopyMsg).e := e ELSIF msg IS WriteFrames.TrackMsg THEN WITH msg: WriteFrames.TrackMsg DO IF msg.keys = {middleKey} THEN Edit(E, msg.X0, msg.Y0, msg.keys) END END END END END Handle; PROCEDURE Alloc*; VAR E: Elem; BEGIN NEW(E); E.handle := Handle; Texts.new := E END Alloc; (* commands *) PROCEDURE Insert*; VAR E: Elem; S: Texts.Scanner; text: Texts.Text; beg, end, time: LONGINT; BEGIN NEW(E); E.handle := Handle; Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF (S.line = 0) & (S.class = Texts.Char) & (S.c = "^") THEN Oberon.GetSelection(text, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(S, text, beg); Texts.Scan(S) END END; IF (S.line = 0) & (S.class IN {Texts.Name, Texts.String}) THEN COPY(S.s, E.string) ELSE E.string := "" END; WriteFrames.CopyToFocus(E) END Insert; BEGIN Texts.OpenWriter(W) END StringElems.