ða Syntax10.Scn.FntSyntax10i.Scn.FntõÿÿÿzðIStampElemsAlloc17 Dec 98¨Syntax10b.Scn.Fnt     &üÿÿÿÀÔ°­MarkElemsAlloc‚` +ÿÿÿÿ€8ÀÔFoldElemsNewÿÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­Àü  /ÿÿÿÿ€8ÀÔà=tÅÿÿÿ€8ÀÔ#Syntax10.Scn.Fnt allowed input at maxLen œÿÿÿÿ€8ÀÔ74]Zÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­yÄ–5ÿÿÿÿ€8ÀÔpÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­Àü  0ÿÿÿÿ€8ÀÔ4ÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­³ÀÎ „ÿÿÿÿ€8ÀÔùÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­“r!1ÿÿÿÿ€8ÀÔ_ÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔ ÿÿÿÿ€8ÀÔYÿÿÿÿ€8ÀÔ3ÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­HŠ/ÿÿÿÿ€8ÀÔtÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­KŠ+ÿÿÿÿ€8ÀÔ·™ k+?Œÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­Dd< ÿÿÿÿ€8ÀÔ»ÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­LŠÿÿÿÿ€8ÀÔ=ÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­MŠÿÿÿÿ€8ÀÔ4ÿÿÿÿ€8ÀÔFÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­ƒNç<ÿÿÿÿ€8ÀÔ%aÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­‰“r ÿÿÿÿ€8ÀÔûÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­“r!3ÿÿÿÿ€8ÀÔ9ÿÿÿÿ€8ÀÔ3ÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔ/ÿÿÿÿ€8ÀÔ  )ÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­Dd<ÿÿÿÿ€8ÀÔÒÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­F çÿÿÿÿ€8ÀÔCÿÿÿÿ€8ÀÔ üÿÿÿÀÔ°­÷6ç ÿÿÿÿ€8ÀÔ<ÿÿÿÿ€8ÀÔÄõ*MODULE TextFieldElems; (* CE  SA: PWElems *) IMPORT Texts, TextFrames, TextPrinter, Oberon, Display, Viewers, Files, Fonts, Elems, GU := GUtils, MenuViewers; CONST DUnit = TextFrames.Unit; MM = 1; TYPE Elem* = POINTER TO ElemDesc; ElemDesc* = RECORD (Elems.ElemDesc) txt* : Texts.Text; maxLen* : SHORTINT; END; PWElem* = POINTER TO PWElemDesc; PWElemDesc* = RECORD (ElemDesc); END; PWText* = POINTER TO PWTextDesc; PWTextDesc* = RECORD (Texts.TextDesc) hidden* : Texts.Text END; Frame* = POINTER TO FrameDesc; FrameDesc* = RECORD(Display.FrameDesc) e* : Elem; END; VAR curElem* : Elem; W : Texts.Writer; PROCEDURE TextToString* (t : Texts.Text; VAR str : ARRAY OF CHAR); VAR r : Texts.Reader; ch : CHAR; i, len : INTEGER; BEGIN len := SHORT(LEN(str)); i := 0; Texts.OpenReader(r, t, 0); Texts.Read(r, ch); WHILE ~r.eot & (i < len-1) DO str[i] := ch; INC(i); Texts.Read(r, ch); END; str[i] := 0X END TextToString; PROCEDURE TextHandle* (f: Display.Frame; VAR msg: Display.FrameMsg); VAR isempty, done : BOOLEAN; fnt : Fonts.Font; col : SHORTINT; pos : LONGINT; track : TextFrames.TrackMsg; exec : Elems.ExecMsg; BEGIN WITH f : TextFrames.Frame DO WITH msg : Oberon.InputMsg DO IF (msg.id = Oberon.consume) & f.hasCar THEN IF (msg.ch = Elems.CR) OR (msg.ch = Elems.LF) THEN exec.e := curElem; exec.x := f.X; exec.y := f.Y; exec.f := f; exec.unload := FALSE; curElem.handle(curElem, exec) ELSIF msg.ch = Elems.TAB THEN msg.id := -1; (* invalidate message (panel sends input to all subframes) *) Elems.TabStop(curElem, f) ELSIF (curElem.maxLen > 0) & (SHORT(f.text.len) >= curElem.maxLen) THEN IF  (msg.ch = Elems.DEL) OR (msg.ch = Elems.BACKSPC) OR (msg.ch = Elems.CRSL) OR (msg.ch = Elems.CRSR) OR (msg.ch = Elems.HOME) OR (msg.ch = Elems.EOL)  THEN TextFrames.Handle(f, msg) END ELSE (* set text color to elem color if text is empty *) isempty := f.text.len = 0; TextFrames.Handle(f, msg); IF isempty & (f.text.len > 0) THEN pos := f.carloc.pos; Elems.GetLook(curElem, fnt, col); Texts.ChangeLooks(f.text, 0, f.text.len, {0, 1}, fnt, col, 0); TextFrames.SetCaret(f, pos) END END ELSIF (msg.id = Oberon.track) & (msg.keys = {MM}) THEN (* maybe a resize *) track.X0 := f.X; track.Y0 := f.Y; track.X := msg.X; track.Y := msg.Y; track.keys := msg.keys; track.frame := f; Elems.Track(curElem, track, done); IF done THEN Elems.UpdateElem(curElem) ELSE TextFrames.Handle(f, msg) END ELSE TextFrames.Handle(f, msg) END; ELSE TextFrames.Handle(f, msg) END END END TextHandle; PROCEDURE SetFrameCoords(src : Frame; dest : TextFrames.Frame); BEGIN dest.X := src.X + 2; dest.Y := src.Y + 2; dest.H := src.H - 4; dest.W := src.W - 4; END SetFrameCoords; PROCEDURE FrameHandle*(f : Display.Frame; VAR msg : Display.FrameMsg); BEGIN WITH msg : MenuViewers.ModifyMsg DO SetFrameCoords(f(Frame), f.dsc(TextFrames.Frame)) | msg : Elems.GetFrameMsg DO IF msg.e = f(Frame).e THEN msg.f := f.dsc END | msg : Oberon.InputMsg DO curElem := f(Frame).e; f.dsc.handle(f.dsc, msg) ELSE f.dsc.handle(f.dsc, msg) END END FrameHandle; PROCEDURE OpenFrame* (e : Elem; f : Display.Frame; textHandler : Display.Handler; frameHandler : Display.Handler; x, y, w, h : INTEGER) : Display.Frame; VAR new : Frame; m : MenuViewers.ModifyMsg; tf : TextFrames.Frame; BEGIN NEW(new); new.handle := frameHandler; new.e := e; new.X := x; new.Y := y; new.W := w; new.H := h; tf := TextFrames.NewText(e.txt, 0); tf.left := 2; tf.right := 2; tf.top := 1; tf.bot := 0; tf.barW := 0; tf.showsParcs := FALSE; tf.handle := textHandler; Elems.AdjustSubFrame(f, new); SetFrameCoords(new, tf); m.id := 1; m.Y := tf.Y; m.H := tf.H; new.dsc := tf; new.dsc.handle(new.dsc, m); RETURN new; END OpenFrame; PROCEDURE HandleAttrMsg(e : Elem; VAR msg : Elems.AttrMsg); VAR fnt : Fonts.Font; col : SHORTINT; BEGIN Elems.Done := TRUE; IF msg.id = Elems.get THEN IF msg.name = "Value" THEN msg.class := Elems.String; TextToString(e.txt, msg.s) ELSIF msg.name = "ValueT" THEN msg.class := Elems.Text; msg.t := e.txt ELSIF msg.name = "MaxLen" THEN msg.class := Elems.Int; msg.i := e.maxLen ELSE Elems.Handle(e, msg) END ELSIF msg.id = Elems.set THEN IF msg.name = "Value" THEN Texts.Delete(e.txt, 0, e.txt.len); IF Texts.ElemBase(e) # NIL THEN Elems.GetLook(e, fnt, col); Texts.SetFont(W, fnt); Texts.SetColor(W, col); END; Elems.WriteAttr(W, msg); Texts.Append(e.txt, W.buf) ELSIF msg.name = "ValueT" THEN IF msg.class = Elems.Text THEN e.txt := msg.t END ELSIF msg.name = "MaxLen" THEN IF msg.class = Elems.Int THEN e.maxLen := SHORT(SHORT(msg.i)) END; IF e.maxLen < 0 THEN e.maxLen := 0 END ELSE Elems.Handle(e, msg) END ELSIF msg.id = Elems.enum THEN Elems.Handle(e, msg); msg.enum("Value", Elems.String); msg.enum("MaxLen", Elems.Int) ELSE Elems.Handle(e, msg) END END HandleAttrMsg; PROCEDURE Draw* (e : Elem; x, y : INTEGER; f : Display.Frame); VAR h, w : INTEGER; pos : LONGINT; BEGIN h := GU.Unit(e.H, TRUE); w := GU.Unit(e.W, TRUE); GU.Area(f, 0, 12, x, y, w, h, GU.Unit(2, FALSE), FALSE, TRUE); IF GU.device = GU.printer THEN pos := 0; h := h - GU.Unit(4, FALSE); w := w - GU.Unit(4, FALSE); TextPrinter.PlaceBody(x + GU.Unit(2, FALSE), y + GU.Unit(2, FALSE), w, h, e.txt, pos, 0, TRUE) END END Draw; PROCEDURE Handle* (e : Texts.Elem; VAR msg : Texts.ElemMsg); VAR copy: Elem; ch: CHAR; int : INTEGER; BEGIN WITH e : Elem DO WITH msg: TextFrames.DisplayMsg DO IF ~msg.prepare THEN GU.SetDevice(GU.display); msg.elemFrame := OpenFrame(e, msg.frame, TextHandle, FrameHandle, msg.X0, msg.Y0, SHORT(e.W DIV DUnit), SHORT(e.H DIV DUnit)); Draw(e, msg.X0, msg.Y0, msg.elemFrame) END | msg : TextPrinter.PrintMsg DO IF ~msg.prepare THEN GU.SetDevice(GU.printer); Draw(e, msg.X0, msg.Y0, NIL); GU.SetDevice(GU.display) END | msg : Texts.CopyMsg DO IF msg.e = NIL THEN NEW(copy); msg.e := copy ELSE copy := msg.e(Elem) END; Elems.CopyElem(e, copy); copy.txt := Elems.CopyText(e.txt); copy.maxLen := e.maxLen | msg : Texts.IdentifyMsg DO msg.mod := "TextFieldElems"; msg.proc := "New" | msg : Elems.AttrMsg DO HandleAttrMsg(e, msg) | msg : Texts.FileMsg DO Elems.Handle(e, msg); IF msg.id = Texts.load THEN Files.Read(msg.r, ch); (* version -> not yet used *) Files.ReadInt(msg.r, int); e.maxLen := SHORT(int); Texts.Load(msg.r, e.txt); ELSIF msg.id = Texts.store THEN Files.Write(msg.r, 0X); (* version *) Files.WriteInt(msg.r, e.maxLen); Texts.Store(msg.r, e.txt) END | msg : TextFrames.FocusMsg DO (* set caret while activating his frame *) IF msg.focus THEN msg.elemFrame := msg.elemFrame.dsc; (* set to textframe *) Elems.Focusing(msg) END | msg : Elems.TabStopMsg DO msg.accepted := TRUE; ELSE Elems.Handle(e, msg) END END END Handle; PROCEDURE Init* (e : Elem); BEGIN Elems.Init(e); e.handle := Handle; e.txt := TextFrames.Text(""); e.maxLen := 0; e.H := LONG(Fonts.Default.maxY - Fonts.Default.minY + 5) * DUnit; e.W := 120 * DUnit END Init; PROCEDURE New*; VAR e : Elem; BEGIN NEW(e); Init(e); Texts.new := e END New; PROCEDURE Insert*; (** Name Cmd Par W H Value *)  VAR e : Elem; m : TextFrames.InsertElemMsg; s : Texts.Scanner; BEGIN NEW(e); Init(e); Elems.GetPar(e, s); IF ~s.eot & (s.class IN {Texts.Name, Texts.String}) THEN Texts.Delete(e.txt, 0, e.txt.len); Texts.WriteString(W, s.s); Texts.Append(e.txt, W.buf) END; m.e := e; Viewers.Broadcast(m) END Insert; (**** PWElems ****) PROCEDURE NoNotify (T: Texts.Text; op: INTEGER; beg, end: LONGINT);  END NoNotify; PROCEDURE PWNotifier (T: Texts.Text; op: INTEGER; beg, end: LONGINT);  VAR i : LONGINT; fnt : Fonts.Font; col : SHORTINT; BEGIN T.notify := NoNotify; WITH T : PWText DO IF op = Texts.insert THEN Texts.Save(T, beg, end, W.buf); Texts.Insert(T.hidden, beg, W.buf); Texts.Delete(T, beg, end); IF (curElem # NIL) & (Texts.ElemBase(curElem) # NIL) THEN (* in a text *) Elems.GetLook(curElem, fnt, col); Texts.SetFont(W, fnt); Texts.SetColor(W, col); END; FOR i := beg TO end - 1 DO Texts.Write(W, '*') END; Texts.Insert(T, beg, W.buf); ELSIF op = Texts.delete THEN Texts.Delete(T.hidden, beg, end) END ELSE END; T.notify := PWNotifier; TextFrames.NotifyDisplay(T, op, beg, end) END PWNotifier; PROCEDURE CopyPWText* (T: PWText): PWText; VAR txt : PWText; BEGIN Texts.Save(T.hidden, 0, T.hidden.len, W.buf); NEW(txt); Texts.Open(txt, ""); txt.notify := PWNotifier; txt.hidden := TextFrames.Text(""); txt.hidden.notify := NoNotify; Texts.Append(txt, W.buf); RETURN txt END CopyPWText; PROCEDURE HandlePWAttrMsg(e : Elem; VAR msg : Elems.AttrMsg); BEGIN Elems.Done := TRUE; IF msg.id = Elems.get THEN IF msg.name = "ValueT" THEN msg.class := Elems.Text; msg.t := e.txt(PWText).hidden ELSIF msg.name = "Value" THEN msg.class := Elems.String; msg.s := "" ELSIF msg.name = "PValue" THEN msg.class := Elems.String; TextToString(e.txt(PWText).hidden, msg.s) ELSE Handle(e, msg) END ELSIF msg.id = Elems.set THEN IF msg.name = "ValueT" THEN IF msg.class = Elems.Text THEN e.txt(PWText).hidden := msg.t END ELSE Handle(e, msg) END ELSE Handle(e, msg) END END HandlePWAttrMsg; PROCEDURE HandlePW* (e: Texts.Elem; VAR msg: Texts.ElemMsg); VAR copy : PWElem; BEGIN WITH e : PWElem DO WITH msg : Texts.CopyMsg DO IF msg.e = NIL THEN NEW(copy); msg.e := copy ELSE copy := msg.e(PWElem) END; Handle(e, msg); copy.txt := CopyPWText(e.txt(PWText)); | msg : Texts.IdentifyMsg DO msg.mod := "TextFieldElems"; msg.proc := "NewPW" | msg : Elems.AttrMsg DO HandlePWAttrMsg(e, msg) | msg : Texts.FileMsg DO Handle(e, msg); IF msg.id = Texts.load THEN Texts.Delete(e.txt, 0, e.txt.len) END ELSE Handle(e, msg) END END END HandlePW;  PROCEDURE InitPW* (e : PWElem); VAR txt : PWText; BEGIN Init(e); e.handle := HandlePW; NEW(txt); Texts.Open(txt, ""); txt.notify := PWNotifier; txt.hidden := TextFrames.Text(""); txt.hidden.notify := NoNotify; e.txt := txt; END InitPW; PROCEDURE NewPW*;  VAR e: PWElem; BEGIN NEW(e); InitPW(e); Texts.new := e END NewPW;  PROCEDURE InsertPW*;  VAR e : PWElem; m : TextFrames.InsertElemMsg; s : Texts.Scanner; BEGIN NEW(e); InitPW(e); Elems.GetPar(e, s); IF ~s.eot & (s.class IN {Texts.Name, Texts.String}) THEN Texts.Delete(e.txt, 0, e.txt.len); Texts.WriteString(W, s.s); Texts.Append(e.txt, W.buf) END; m.e := e; Viewers.Broadcast(m) END InsertPW;  BEGIN Texts.OpenWriter(W) END TextFieldElems. System.Free TextFieldElems ~ TextFieldElems.Insert "" Edit.Open "#Value" 0 0 default ~ TextFieldElems.InsertPW "" System.Time "" 0 0 default ~