Syntax10.Scn.FntSyntax10i.Scn.FntIStampElemsAlloc17 Dec 98,qBalloonElemsAllocSyntax10.Scn.FntSyntax10i.Scn.Fnt ,  50="OpenPanel" PROCEDURE OpenPanel(p : PanelElems.Panel; name : ARRAY OF CHAR; fnt : Fonts.Font; col : SHORTINT); opens a new viewer with panel p, name, font fnt and color col. "LoadPanel" PROCEDURE LoadPanel(name : ARRAY OF CHAR; VAR p : PanelElems.Panel; VAR fnt : Fonts.Font; VAR col : SHORTINT); loads a panel from file name into p. "Open" PROCEDURE Open; opens a panel. Accepts the name of the panel as parameter. MarkElemsAlloc98FoldElemsNewx8 ^J888 g3%8M8 ` 8a8 y8N8 =8}8 ND)8z8 88 3:08R8 L28-P8.878-82LZ848JyC%8 V^n-88 0a58M8 '38888G88q8N8 +%788 Syntax10b.Scn.Fntױ O88#Syntax10.Scn.Fnt set ideal height 8v8  [8o8  8"8  88<(MODULE Panel; (* CE  *)  IMPORT Out, Elems, PanelElems, TextFrames, Texts, MenuViewers, Viewers, Oberon, Files, Fonts, Display, GU := GUtils, Input, Strings; CONST menu = "System.Close System.Copy System.Grow Panel.Store "; 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 GetMenu (p : PanelElems.Panel; VAR mnu : ARRAY OF CHAR);  VAR f : Files.File; BEGIN IF p # NIL THEN Elems.GetString(p, "Menu", mnu) END; IF (p # NIL) & Elems.Done THEN f := Files.Old(mnu); IF f # NIL THEN Strings.Insert("^", 0, mnu) END END; IF (p = NIL) OR ~Elems.Done OR (f = NIL) THEN f := Files.Old("Panel.Menu.Text"); IF f = NIL THEN COPY(menu, mnu) ELSE COPY("^Panel.Menu.Text", mnu) END END END GetMenu; PROCEDURE Min(a, b : INTEGER) : INTEGER; BEGIN IF a < b THEN RETURN a ELSE RETURN b END END Min; 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; 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);*) f.Y := 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 ELSE Forward(f, msg) 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 OpenPanel*(p : PanelElems.Panel; name : ARRAY OF CHAR; fnt : Fonts.Font; col : SHORTINT); VAR f : Frame; V, v, vmax : Viewers.Viewer; X, Y, h : INTEGER; mnu : ARRAY 64 OF CHAR; BEGIN NEW(f); f.handle := Handle; f.hasCar := FALSE; f.hasSel := FALSE; f.txt := TextFrames.Text(""); IF p = NIL THEN NEW(p); PanelElems.Init(p); fnt := Fonts.Default; col := 13; END; Texts.SetFont(W, fnt); Texts.SetColor(W, col); Texts.WriteElem(W, p); Texts.Append(f.txt, W.buf); SetPanel(f); Oberon.AllocateSystemViewer(Oberon.Mouse.X, X, Y);  v := Viewers.This(X, 0); vmax := NIL; h := 0; WHILE v.state > 1 DO IF v.H > h THEN vmax := v; h := v.H END; v := Viewers.Next (v) END; IF vmax # NIL THEN Y := Min (vmax.Y + SHORT(f.p.H DIV Display.Unit) + TextFrames.menuH +3, vmax.Y + vmax.H - TextFrames.menuH -2) END;  GetMenu(f.p, mnu); V := MenuViewers.New(TextFrames.NewMenu(name, mnu), f,TextFrames.menuH, X, Y); END OpenPanel; PROCEDURE LoadPanel*(name : ARRAY OF CHAR; VAR p : PanelElems.Panel; VAR fnt : Fonts.Font; VAR col : SHORTINT); VAR r : Texts.Reader; txt : Texts.Text; BEGIN p := NIL; IF (name # "") & (Files.Old(name) # NIL) THEN txt := TextFrames.Text(name); Texts.OpenReader(r, txt, 0); Texts.ReadElem(r); IF (r.elem # NIL) & (r.elem IS PanelElems.Panel) THEN p := r.elem(PanelElems.Panel); fnt := r.fnt; col := r.col; Texts.Delete(txt, 0, txt.len); END END END LoadPanel; PROCEDURE Open*; VAR s : Texts.Scanner; t : Texts.Text; beg, end, time : LONGINT; col : SHORTINT; fnt : Fonts.Font; p : PanelElems.Panel; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF t # NIL THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) ELSE s.class := Texts.Inval END END; IF s.class IN {Texts.Name, Texts.String} THEN LoadPanel(s.s, p, fnt, col); OpenPanel(p, s.s, fnt, col); ELSE OpenPanel(NIL, "", NIL, 0); END END Open; PROCEDURE Store*; VAR v: Viewers.Viewer; s: Texts.Scanner; name: ARRAY 64 OF CHAR; t : Texts.Text; R : Texts.Reader; ch : CHAR; BEGIN v := Oberon.Par.vwr; name := ""; IF (v.dsc # Oberon.Par.frame) OR (v.dsc = NIL) OR (v.dsc.next = NIL) OR ~(v.dsc.next IS Frame) THEN v := Oberon.MarkedViewer(); Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.line = 0) & (s.class IN {Texts.Name, Texts.String}) THEN COPY(s.s, name) END END; IF (v.dsc # NIL) & (v.dsc.next # NIL) & (v.dsc.next IS Frame) THEN IF (name = "") & (v.dsc IS TextFrames.Frame) THEN Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s); IF (s.line = 0) & (s.class IN {Texts.Name, Texts.String}) THEN COPY(s.s, name) END END; IF name # "" THEN Texts.SetColor(W, 15); Texts.SetFont(W, Fonts.Default); Texts.WriteString(W, "Panel.Store "); Texts.WriteString(W, name); Texts.Close(v.dsc.next(Frame).txt, name); Texts.WriteString(W, " done"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); t := v.dsc(TextFrames.Frame).text; Texts.OpenReader(R, t, t.len - 1); Texts.Read(R, ch); IF ch ="!" THEN Texts.Delete(t, t.len - 1, t.len) END END END END Store; BEGIN Texts.OpenWriter(W) END Panel. System.Free Panel ~