Syntax10.Scn.FntSyntax10i.Scn.FntIStampElemsAlloc10 Oct 97Syntax10b.Scn.Fnt " MarkElemsAllocg3%8FoldElemsNewL8 ` 8Y8 y8M8 =8}8 ND)8y8 88 3:08Q8 L28F-O8.878-82MA 848NqD"8 V^n-88 0a58L8 '38d88(G>88G88G>@848 +%28(|!B8 T`88+MODULE PanelFrames; (* CE  *) IMPORT PanelElems, Elems, Texts, Display, TextFrames, Fonts, Oberon, Viewers, Input, GU := GUtils, MenuViewers; CONST ML = 2; MM = 1; MR = 0; DUnit = TextFrames.Unit; backCol = 12; TYPE Frame* = POINTER TO FrameDesc; FrameDesc* = RECORD (Display.FrameDesc) p* : PanelElems.Panel; txt : Texts.Text; px, py : INTEGER; hasCar, hasSel : BOOLEAN; selTime : LONGINT; END; VAR W : Texts.Writer; PROCEDURE InvertCaret (f : Frame);  BEGIN GU.Frame(f, 0, f.X, f.Y, f.W, f.H, 3, Display.invert) END InvertCaret; PROCEDURE SetCaret (f : Frame);  BEGIN Oberon.PassFocus(Viewers.This(f.X, f.Y)); f.hasCar := TRUE; InvertCaret(f) END SetCaret; PROCEDURE RemoveCaret (f : Frame); BEGIN IF f.hasCar THEN InvertCaret(f); f.hasCar := FALSE END END RemoveCaret; PROCEDURE DrawPanel (f : Frame); VAR disp : TextFrames.DisplayMsg; BEGIN Elems.GetLook(f.p, disp.fnt, disp.col); disp.pos := 0; disp.frame := f; disp.X0 := f.X + f.px; disp.Y0 := f.py; disp.indent := 0; disp.elemFrame := NIL; disp.prepare := TRUE; f.p.handle(f.p, disp); disp.prepare := FALSE; f.p.handle(f.p, disp); IF disp.elemFrame = NIL THEN HALT(99) END; f.dsc := disp.elemFrame; END DrawPanel; PROCEDURE DrawPanelArea(f : Frame; mode : INTEGER); BEGIN GU.ReplConst(f, backCol, f.X + f.px, f.py, SHORT(f.p.W DIV DUnit), SHORT(f.p.H DIV DUnit), mode) END DrawPanelArea; PROCEDURE SetPanel(f : Frame); VAR r : Texts.Reader; BEGIN IF f.p = NIL THEN Texts.OpenReader(r, f.txt, 0); Texts.ReadElem(r); IF r.elem # NIL THEN f.p := r.elem(PanelElems.Panel) END; END END SetPanel; PROCEDURE Forward (f : Frame; VAR msg : Display.FrameMsg); BEGIN IF (f.dsc # NIL) & ~f.hasSel THEN f.dsc.handle(f.dsc, msg) END END Forward; PROCEDURE Draw(f : Frame); VAR neutralize : Oberon.ControlMsg; BEGIN GU.SetDevice(GU.display); GU.ReplConst(f, backCol, f.X, f.Y, f.W, f.H, Display.replace); IF (f.p # NIL) & (f.H > 0) THEN f.px := 0; f.py := f.Y + f.H - SHORT(f.p.H DIV DUnit); DrawPanel(f) ELSIF f.H = 0 THEN (* remove all marks especially the cursor *) neutralize.id := Oberon.neutralize; Forward(f, neutralize) END; END Draw; PROCEDURE Reduce (f : Frame; newY: INTEGER); BEGIN f.H := f.H + f.Y - newY; f.Y := newY END Reduce; PROCEDURE Extend (f : Frame; newY: INTEGER); VAR dY, newH: INTEGER; BEGIN dY := f.Y - newY; (*Display.ReplConst(backCol, f.X, newY, f.W, f.Y - newY, Display.replace);*) f.H := f.H + f.Y - newY; f.Y := newY; newH := f.H; f.H := dY; (*DrawPanel*) (*InvFocus(F);*) f.H := newH; END Extend; PROCEDURE Modify (f: Frame; id, dY, Y, H: INTEGER); BEGIN Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); f.hasCar := FALSE; f.hasSel := FALSE; IF id = MenuViewers.extend THEN IF dY > 0 THEN (*Display.CopyBlock(f.X, f.Y, f.W, f.H, f.X, f.Y + dY, Display.replace);*) INC(f.Y, dY) END ; Extend(f, Y) ELSIF id = MenuViewers.reduce THEN Reduce(f, Y + dY); IF dY > 0 THEN (*Display.CopyBlock(f.X, f.Y, f.W, f.H, f.X, Y, Display.replace);*) f.Y := Y END END END Modify; PROCEDURE InPanel(f : Frame; x, y : INTEGER) : BOOLEAN; VAR w, h : INTEGER; BEGIN w := SHORT(f.p.W DIV DUnit); h := SHORT(f.p.H DIV DUnit); RETURN (x >= f.X + f.px) & (x <= f.X + f.px + w) & (y >= f.py) & (y <= f.py + h) END InPanel; PROCEDURE CopyInto(f : Frame; txt : Texts.Text; beg : LONGINT); VAR r : Texts.Reader; copy : Texts.CopyMsg; BEGIN Texts.OpenReader(r, txt, beg); Texts.ReadElem(r); IF (r.elem # NIL) & (r.elem IS PanelElems.Panel) THEN copy.e := NIL; r.elem.handle(r.elem, copy); Texts.SetFont(W, r.fnt); Texts.SetColor(W, r.col); Texts.WriteElem(W, copy.e); Texts.Append(f.txt, W.buf) END END CopyInto; PROCEDURE HandleInput (f : Frame; VAR msg : Oberon.InputMsg); VAR keysum : SET; copyOver : Oberon.CopyOverMsg; txt : Texts.Text; beg, end, time : LONGINT; BEGIN keysum := msg.keys; IF msg.id = Oberon.track THEN IF msg.keys = {ML} THEN  IF f.p = NIL THEN SetCaret(f); REPEAT Input.Mouse(msg.keys, msg.X, msg.Y); keysum := keysum + msg.keys; Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, msg.X, msg.Y); UNTIL msg.keys = {}; IF keysum = {ML, MM} THEN Oberon.GetSelection(txt, beg, end, time); IF txt # NIL THEN CopyInto(f, txt, beg) END END ELSIF InPanel(f, msg.X, msg.Y) THEN Forward(f, msg) END;  ELSIF msg.keys = {MM} THEN  IF (f.p # NIL) & InPanel(f, msg.X, msg.Y) THEN Forward(f, msg) END  ELSIF msg.keys = {MR} THEN  IF (f.p # NIL) & ~InPanel(f, msg.X, msg.Y) THEN f.selTime := Oberon.Time(); f.hasSel := ~f.hasSel; DrawPanelArea(f, Display.invert); REPEAT Input.Mouse(msg.keys, msg.X, msg.Y); keysum := keysum + msg.keys; Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, msg.X, msg.Y); UNTIL msg.keys = {}; IF (keysum = {ML, MR}) & f.hasSel THEN (* delete panel *) Texts.Delete(f.txt, 0, f.txt.len) ELSIF (keysum = {MM, MR}) & f.hasSel THEN copyOver.text := f.txt; copyOver.beg := 0; copyOver.end := f.txt.len; Viewers.Broadcast(copyOver) END ELSE Forward(f, msg) END END ELSE Forward(f, msg) END END HandleInput; PROCEDURE Handle* (f : Display.Frame; VAR msg : Display.FrameMsg); VAR F : Frame; BEGIN WITH f : Frame DO WITH msg : Oberon.InputMsg DO HandleInput(f, msg) | msg : Oberon.ControlMsg DO IF f.hasCar & (msg.id IN {Oberon.defocus, Oberon.neutralize}) THEN RemoveCaret(f) END; IF f.hasSel & (msg.id = Oberon.neutralize) THEN DrawPanelArea(f, Display.invert); f.hasSel := FALSE END; Forward(f, msg) | msg : Oberon.CopyOverMsg DO IF f.hasCar THEN CopyInto(f, msg.text, msg.beg) ELSE Forward(f, msg) END | msg : Oberon.SelectionMsg DO Forward(f, msg); IF f.hasSel & (f.selTime > msg.time) THEN msg.text := f.txt; msg.beg := 0; msg.end := f.txt.len; msg.time := f.selTime END | msg : MenuViewers.ModifyMsg DO Modify(f, msg.id, msg.dY, msg.Y, msg.H); Draw(f) | msg: Oberon.CopyMsg DO NEW(F); msg.F := F; F^ := f^ | msg : TextFrames.UpdateMsg DO IF msg.text = f.txt THEN IF msg.id = TextFrames.delete THEN f.p := NIL; f.dsc := NIL END; f.hasSel := FALSE; f.hasCar := FALSE; SetPanel(f); Draw(f) ELSE Forward(f, msg) END | msg : TextFrames.InsertElemMsg DO IF f.hasCar & (msg.e IS PanelElems.Panel) THEN Texts.WriteElem(W, msg.e); Texts.Append(f.txt, W.buf) ELSE Forward(f, msg) END ELSE Forward(f, msg) END END END Handle; PROCEDURE Open* (f : Frame; p : PanelElems.Panel; fnt : Fonts.Font; col : SHORTINT; handle : Display.Handler); BEGIN f.txt := TextFrames.Text(""); f.hasCar := FALSE; f.hasSel := FALSE; f.p := p; Texts.SetFont(W, fnt); Texts.SetColor(W, col); Texts.WriteElem(W, p); Texts.Append(f.txt, W.buf); f.handle := handle END Open; BEGIN Texts.OpenWriter(W); END PanelFrames.