home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / Chip_2004-07_cd1.bin / tema / aos / files / Oberon.exe / Oberon / Docu.exe / Docu / NoteBooks.Mod (.txt) < prev    next >
Oberon Text  |  2000-02-29  |  22KB  |  524 lines

  1. Oberon10.Scn.Fnt
  2. Syntax10.Scn.Fnt
  3. Syntax10b.Scn.Fnt
  4. (* ETH Oberon, Copyright 2000 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
  5. Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
  6. MODULE NoteBooks; (** portable *)
  7. (* NoteBook Gadgets, jm 5.5.94
  8. The NoteBook gadgets are intended as an example of a more complicated container gadget. It is derived from
  9. the Portrait gadgets also provided in source form. It allows you to insert and remove pages (gadgets) into a
  10. notebook, and then to page through it.
  11. IMPORT Fonts, Objects, Display, Gadgets, Display3, Effects, Oberon, Attributes, Files, Views, Out;
  12. CONST
  13.     border = 4;        (* border width around the sides of the Notebook *)
  14.     topborder = 16; (* Size of the border at the top *)
  15.     NoteBook* = POINTER TO NoteBookDesc;
  16.     NoteBookDesc* = RECORD (Gadgets.FrameDesc)
  17.         pages*: Display.Frame;    (* list of pages belonging to the notebook *)
  18.         time*: LONGINT    (* time of selection *)
  19.     END;
  20.     (* Message to change the current page *)
  21.     PageMsg = RECORD (Display.FrameMsg)
  22.         newpage: Display.Frame;
  23.     END;
  24. (* Set the mask of a specific gadget *)
  25. PROCEDURE SetMask(F: Display.Frame; M: Display3.Mask);
  26. VAR O: Display3.OverlapMsg;
  27. BEGIN IF F # NIL THEN O.M := M; O.x := 0; O.y := 0; O.F := F; O.dlink := NIL; O.res := -1; F.handle(F, O) END
  28. END SetMask;
  29. (* Calculate and set the mask of the current page *)
  30. PROCEDURE SetMainMask(F: NoteBook);
  31. VAR R: Display3.Mask;
  32. BEGIN
  33.     IF F.dsc # NIL THEN
  34.         IF F.mask = NIL THEN SetMask(F.dsc, NIL)
  35.         ELSE Display3.Copy(F.mask, R); R.x := 0; R.y := 0;
  36.             Display3.Intersect(R, F.dsc.X, F.dsc.Y, F.dsc.W, F.dsc.H);
  37.             R.x := -F.dsc.X; R.y := -(F.dsc.Y + F.dsc.H - 1); Display3.Shift(R);
  38.             SetMask(F.dsc, R)
  39.         END
  40. END SetMainMask;
  41. (* Forward a message to the current child *)
  42. PROCEDURE ToMain(F: NoteBook; x, y: INTEGER; VAR M: Display.FrameMsg);
  43. VAR Mdlink, Fdlink: Objects.Object; tx, ty: INTEGER;
  44. BEGIN
  45.     IF F.dsc # NIL THEN tx := M.x; ty := M.y;
  46.         M.x := x; M.y := y + F.H - 1;
  47.         Fdlink := F.dlink; Mdlink := M.dlink; 
  48.         F.dlink := M.dlink; M.dlink := F; F.dsc.handle(F.dsc, M);
  49.         F.dlink := Fdlink; M.dlink := Mdlink;
  50.         M.x := tx; M.y := ty
  51. END ToMain;
  52. (* Handle size adjusting of the NoteBook *)
  53. PROCEDURE Adjust(F: NoteBook; VAR M: Display.ModifyMsg);
  54. VAR A: Display.ModifyMsg;
  55. BEGIN
  56.     IF F.dsc # NIL THEN A.id := Display.extend; A.F := F.dsc; A.mode := Display.state;
  57.         A.X := border; A.Y := -M.H + 1 + border; A.W := M.W - 2 * border; A.H := M.H - (border + topborder);
  58.         A.dX := A.X - F.dsc.X; A.dY := A.Y - F.dsc.Y; A.dW := A.W - F.dsc.W; A.dH := A.H - F.dsc.H;
  59.         A.x := 0; A.y := 0; A.res := -1; Objects.Stamp(A);
  60.         F.dsc.handle(F.dsc, A)
  61.     END;
  62.     Gadgets.framehandle(F, M)
  63. END Adjust;
  64. (* Handle adjusting of the page size *)
  65. PROCEDURE AdjustChild(F: NoteBook; VAR M: Display.ModifyMsg);
  66. VAR A: Display.ModifyMsg;
  67. BEGIN
  68.     IF M.stamp # F.stamp THEN F.stamp := M.stamp;
  69.         A.id := Display.extend; A.F := F; A.mode := Display.display;
  70.         A.X := F.X + M.dX; A.Y := F.Y + M.dY; A.W := M.W + 2 * border; A.H := M.H + (border + topborder);
  71.         A.dX := A.X - F.X; A.dY := A.Y - F.Y; A.dW := A.W - F.W; A.dH := A.H - F.H;
  72.         Display.Broadcast(A)
  73. END AdjustChild;
  74. (* Display the current page title *)
  75. PROCEDURE UpdateTitle(F: NoteBook; R: Display3.Mask; x, y, w, h: INTEGER);
  76. VAR s: ARRAY 64 OF CHAR;
  77. BEGIN
  78.     Display3.ReplConst(R, Display3.textbackC, x + 20, y + h - topborder, w - 21, topborder - 1, Display.replace);
  79.     IF F.dsc # NIL THEN
  80.         Gadgets.GetObjName(F.dsc, s);
  81.         IF s # "" THEN
  82.             Display3.String(R, Display.FG, x + border + 20, y + h - Fonts.Default.height, Fonts.Default, s, Display.paint)
  83.         END
  84.     END;
  85. END UpdateTitle;
  86. PROCEDURE Restore(F: NoteBook; R: Display3.Mask; x, y, w, h: INTEGER; VAR M: Display.DisplayMsg);
  87. VAR D: Display.DisplayMsg; s: ARRAY 64 OF CHAR;
  88.     PROCEDURE ClipAgainst(VAR x, y, w, h: INTEGER; x1, y1, w1, h1: INTEGER);
  89.     VAR r, t, r1, t1: INTEGER;
  90.     BEGIN r := x + w - 1; r1 := x1 + w1 - 1; t := y + h - 1; t1 := y1 + h1 - 1;
  91.         IF x < x1 THEN x := x1 END; IF y < y1 THEN y := y1 END;
  92.         IF r > r1 THEN r := r1 END; IF t > t1 THEN t := t1 END;
  93.         w := r - x + 1; h := t - y + 1;
  94.     END ClipAgainst;
  95. BEGIN
  96.     Display3.ReplConst(R, Display3.textbackC, x + 1, y + h - topborder, w - 2, topborder - 1, Display.replace);
  97.     Display3.Rect(R, Display3.textbackC, Display.solid, x+1, y+1, w-2, h-2, border-1, Display.replace);
  98.     Display3.Rect3D(R, Display3.bottomC, Display3.topC, x, y, w, h, 1, Display.replace);
  99.     s[0] := CHR(31); s[1] := 0X;
  100.     Display3.String(R, Display.FG, x + border, y + h - Fonts.Default.height, Fonts.Default, s, Display.paint);
  101.     s[0] := CHR(27); s[1] := 0X;
  102.     Display3.String(R, Display.FG, x + border + 8, y + h - Fonts.Default.height, Fonts.Default, s, Display.paint);
  103.     IF F.dsc # NIL THEN
  104.         Gadgets.GetObjName(F.dsc, s);
  105.         IF s # "" THEN
  106.             Display3.String(R, Display.FG, x + border + 20, y + h - Fonts.Default.height, Fonts.Default, s, Display.paint)
  107.         END
  108.     END;
  109.     IF F.dsc = NIL THEN
  110.         Display3.FilledRect3D(R, Display3.topC, Display3.bottomC, (* Display3.white *) 3,
  111.             x + border, y + border, w - border * 2, h - (border + topborder), 1, Display.replace)
  112.     ELSIF M.id = Display.area THEN
  113.         D.device := Display.screen; D.id := Display.area; D.F := F.dsc; D.u := M.u; D.v := M.v; D.w := M.w; D.h := M.h;
  114.         ClipAgainst(D.u, D.v, D.w, D.h, F.dsc.X, F.dsc.Y, F.dsc.W, F.dsc.H);
  115.         DEC(D.u, border); INC(D.v, topborder);
  116.         D.dlink := M.dlink; D.res := -1; Objects.Stamp(D);
  117.         ToMain(F, x, y, D);
  118.     ELSE
  119.         D.device := Display.screen; D.id := Display.full; D.F := F.dsc; D.dlink := M.dlink; D.res := -1; Objects.Stamp(D);
  120.         ToMain(F, x, y, D)
  121.     END;
  122.     IF Gadgets.selected IN F.state THEN Display3.FillPattern(R, Display3.white, Display3.selectpat, x, y, x, y, w, h, Display.paint) END
  123. END Restore;
  124. PROCEDURE HandlePageMsg(F: NoteBook; x, y: INTEGER; VAR M: PageMsg);
  125. VAR C: Display.ControlMsg; A: Display.ModifyMsg; f: Display.Frame;
  126.     N: Oberon.ControlMsg; S: Display.SelectMsg;
  127. BEGIN
  128.     IF M.stamp # F.stamp THEN (* first time *)
  129.         F.stamp := M.stamp;
  130.         f := M.newpage;
  131.         IF f # NIL THEN (* inform the page that it missed a few messages while not visible *)
  132.             C.id := Display.restore; C.F := NIL; C.x := 0; C.y := 0; C.dlink := NIL; C.res := -1; f.handle(f, C)
  133.         END;
  134.         F.dsc := f;
  135.         IF f # NIL THEN
  136.             IF Gadgets.selected IN f(Gadgets.Frame).state THEN
  137.                 S.id := Display.reset; S.F := f; S.res := -1; ToMain(F, x, y, S)
  138.             END;
  139.             A.X := border; A.Y := -F.H + 1 + border; A.W := F.W - 2 * border; A.H := F.H - (border + topborder);
  140.             A.id := Display.extend; A.F := f; A.mode := Display.state; A.dlink := NIL;
  141.             A.dX := A.X - f.X; A.dY := A.Y - f.Y; A.dW := A.W - f.W; A.dH := A.H - f.H;
  142.             A.res := -1; Objects.Stamp(A);
  143.             ToMain(F, x, y, A);
  144.             N.id := Oberon.neutralize; N.F := NIL; N.res := -1; N.dlink := M.dlink; ToMain(F, x, y, N)
  145.         END;
  146.         Gadgets.Update(F); M.res := 0;
  147. END HandlePageMsg;
  148. PROCEDURE GotoPage(F: NoteBook; f: Display.Frame);
  149. VAR P: PageMsg;
  150. BEGIN
  151.     IF F.dsc # f THEN P.F := F; P.newpage := f; Display.Broadcast(P) END
  152. END GotoPage;
  153. PROCEDURE InsertPage(F: NoteBook; f: Display.Frame);
  154. VAR t: Display.Frame;
  155. BEGIN
  156.     IF f # NIL THEN
  157.         f.next := NIL;
  158.         IF F.pages = NIL THEN F.pages := f
  159.         ELSE
  160.             t := F.pages;
  161.             WHILE t.next # NIL DO t := t.next END;
  162.             t.next := f
  163.         END
  164. END InsertPage;
  165. PROCEDURE RemovePage(F: NoteBook; f: Display.Frame);
  166. VAR t, t0: Display.Frame;
  167. BEGIN
  168.     IF f # NIL THEN
  169.         t := F.pages; t0 := NIL; 
  170.         WHILE (t # NIL) & (t # f) DO t0 := t; t := t.next END;
  171.         IF t = f THEN
  172.             IF t0 # NIL THEN t0.next := f.next
  173.             ELSE F.pages := f.next
  174.             END
  175.         END
  176.     END;
  177.     f.next := NIL
  178. END RemovePage;
  179. PROCEDURE LocatePage(F: NoteBook; type: ARRAY OF CHAR): Display.Frame;
  180. VAR f, f0: Display.Frame; s: ARRAY 64 OF CHAR;
  181. BEGIN
  182.     f := F.pages; f0 := NIL;
  183.     LOOP
  184.         IF f = NIL THEN EXIT END;
  185.         IF type = "Next" THEN
  186.             IF f = F.dsc THEN RETURN f.next END
  187.         ELSIF type = "Previous" THEN
  188.             IF f = F.dsc THEN RETURN f0 END
  189.         ELSIF type = "First" THEN RETURN f 
  190.         ELSIF type = "Last" THEN
  191.             IF f.next = NIL THEN RETURN f END
  192.         ELSE (* name compare *)
  193.             Gadgets.GetObjName(f, s);
  194.             IF s = type THEN RETURN f END
  195.         END;
  196.         f0 := f; f := f.next
  197.     END;
  198.     RETURN NIL
  199. END LocatePage;
  200. PROCEDURE HandleSelect(F: NoteBook; VAR M: Oberon.InputMsg);
  201. VAR S: Display.SelectMsg; f: Gadgets.Frame; keysum: SET; newpage: Display.Frame;
  202.     C: Objects.CopyMsg;
  203. BEGIN
  204.     f := F.dsc(Gadgets.Frame);
  205.     IF Gadgets.selected IN f.state THEN S.id := Display.reset ELSE S.id := Display.set END;
  206.     S.F := f; S.res := -1; S.dlink := NIL; S.x := 0; S.y := 0; Objects.Stamp(S); f.handle(f, S);
  207.     Gadgets.Update(f); keysum := M.keys;
  208.     REPEAT Effects.TrackMouse(M.keys, M.X, M.Y, Effects.Arrow); keysum := keysum + M.keys; UNTIL M.keys = {};
  209.     M.res := 0;
  210.     IF (keysum = {0, 2}) & (S.id = Display.set) THEN (* RL delete selection *)
  211.         Oberon.FadeCursor(Oberon.Mouse);
  212.         newpage := LocatePage(F, "Previous");
  213.         IF newpage = NIL THEN newpage := LocatePage(F, "First") END;
  214.         IF newpage # F.dsc THEN RemovePage(F, F.dsc); GotoPage(F, newpage)
  215.         ELSE RemovePage(F, F.dsc); GotoPage(F, NIL)
  216.         END
  217.     ELSIF (keysum = {0, 1}) & (S.id = Display.set) THEN (* RM copy to focus *)
  218.         C.id := Objects.shallow; C.obj := NIL; Objects.Stamp(C); F.dsc.handle(F.dsc, C);
  219.         IF C.obj # NIL THEN Gadgets.Integrate(C.obj) END
  220.     ELSE F.time := Oberon.Time()
  221. END HandleSelect;
  222. PROCEDURE Edit(F: NoteBook; x, y, w, h: INTEGER; VAR M: Oberon.InputMsg);
  223. VAR newpage: Display.Frame; s: ARRAY 2 OF CHAR; keysum: SET; R: Display3.Mask;
  224. BEGIN
  225.     IF M.keys = {1} THEN
  226.         IF Effects.Inside(M.X, M.Y, x + border, y + h - Fonts.Default.height, 6, Fonts.Default.height) THEN (* prev *)
  227.             Gadgets.MakeMask(F, x, y, M.dlink, R); Oberon.FadeCursor(Oberon.Mouse);
  228.             s[0] := CHR(31); s[1] := 0X;
  229.             Display3.String(R, Display.FG, x + border, y + h - Fonts.Default.height, Fonts.Default, s, Display.invert);
  230.             keysum := M.keys;
  231.             REPEAT Effects.TrackMouse(M.keys, M.X, M.Y, Effects.Arrow); keysum := keysum + M.keys; UNTIL M.keys = {};
  232.             Oberon.FadeCursor(Oberon.Mouse);
  233.             Display3.String(R, Display.FG, x + border, y + h - Fonts.Default.height, Fonts.Default, s, Display.invert);
  234.             IF keysum = {1} THEN
  235.                 newpage := LocatePage(F, "Previous");
  236.                 IF newpage = NIL THEN newpage := LocatePage(F, "First") END;
  237.                 GotoPage(F, newpage)
  238.             END;
  239.             M.res := 0
  240.         ELSIF Effects.Inside(M.X, M.Y, x + border + 8, y + h - Fonts.Default.height, 6, Fonts.Default.height) THEN (* next *)
  241.             Gadgets.MakeMask(F, x, y, M.dlink, R); Oberon.FadeCursor(Oberon.Mouse);
  242.             s[0] := CHR(27); s[1] := 0X;
  243.             Display3.String(R, Display.FG, x + border + 8, y + h - Fonts.Default.height, Fonts.Default, s, Display.invert);
  244.             keysum := M.keys;
  245.             REPEAT Effects.TrackMouse(M.keys, M.X, M.Y, Effects.Arrow); keysum := keysum + M.keys; UNTIL M.keys = {};
  246.             Oberon.FadeCursor(Oberon.Mouse);
  247.             Display3.String(R, Display.FG, x + border + 8, y + h - Fonts.Default.height, Fonts.Default, s, Display.invert);
  248.             IF keysum = {1} THEN
  249.                 newpage := LocatePage(F, "Next");
  250.                 IF newpage = NIL THEN newpage := LocatePage(F, "Last") END;
  251.                 GotoPage(F, newpage)
  252.             END;
  253.             M.res := 0
  254.         END
  255.     END;
  256. END Edit;
  257. PROCEDURE Neutralize(F: NoteBook);
  258. VAR S: Display.SelectMsg; f: Gadgets.Frame;
  259. BEGIN
  260.     IF F.dsc # NIL THEN
  261.         f := F.dsc(Gadgets.Frame);
  262.         IF Gadgets.selected IN f.state THEN
  263.             S.id := Display.reset;
  264.             S.F := f; S.res := -1; S.dlink := NIL; S.x := 0; S.y := 0; Objects.Stamp(S); f.handle(f, S);
  265.             Gadgets.Update(f);
  266.         END
  267. END Neutralize;
  268. PROCEDURE ConsumeMsg(F: NoteBook; VAR M: Display.ConsumeMsg);
  269. VAR C: Display.ControlMsg; ok: BOOLEAN; obj: Objects.Object; G, lastobj: Gadgets.Frame;
  270. BEGIN
  271.     ok := TRUE; obj := M.obj;
  272.     WHILE (obj # NIL) & ok DO
  273.         IF Gadgets.Recursive(F, obj) THEN Out.String("Not allowed, will cause recursive structures"); Out.Ln; ok := FALSE;
  274.         ELSIF (F.lib # NIL) & (obj.lib # NIL) & (F.lib # obj.lib) & (obj.lib.name # "") THEN
  275.             Out.String("Across library movement not allowed"); Out.Ln; ok := FALSE
  276.         ELSIF ~(obj IS Gadgets.Frame) THEN Out.String("Only gadgets allowed"); Out.Ln; ok := FALSE
  277.         ELSIF Gadgets.transparent IN obj(Gadgets.Frame).state THEN Out.String("No transparent gadgets allowed"); Out.Ln; ok := FALSE
  278.         END;
  279.         obj := obj.slink
  280.     END;
  281.     IF ok THEN
  282.         C.id := Display.remove; C.F := M.obj(Display.Frame); Display.Broadcast(C); (* remove whole list *)
  283.         obj := M.obj;
  284.         WHILE obj # NIL DO
  285.             G := obj(Gadgets.Frame);
  286.             IF Gadgets.lockedsize IN G.state THEN (* create a view *)
  287.                 G := Views.ViewOf(G)
  288.             END;
  289.             lastobj := G; InsertPage(F, G); obj := obj.slink
  290.         END;
  291.         GotoPage(F, lastobj)
  292.     END;
  293.     M.res := 0
  294. END ConsumeMsg;
  295. PROCEDURE Copy*(VAR M: Objects.CopyMsg; from, to: NoteBook);
  296. VAR C: Objects.CopyMsg;
  297. BEGIN
  298.     Gadgets.CopyFrame(M, from, to);
  299.     IF from.dsc # NIL THEN C.id := Objects.shallow; Objects.Stamp(C); from.dsc.handle(from.dsc, C);
  300.         to.dsc := C.obj(Gadgets.Frame)
  301.     ELSE to.dsc := NIL
  302.     END;
  303. END Copy;
  304. PROCEDURE Attr(F: NoteBook; VAR M: Objects.AttrMsg);
  305. BEGIN
  306.     IF M.id = Objects.get THEN
  307.         IF M.name = "Gen" THEN M.s := "NoteBooks.New"; M.class := Objects.String; M.res := 0
  308.         ELSIF M.name = "Locked" THEN M.class := Objects.Bool; M.b := Gadgets.lockedcontents IN F.state; M.res := 0
  309.         ELSE Gadgets.framehandle(F, M)
  310.         END
  311.     ELSIF M.id = Objects.set THEN
  312.         IF M.name = "Locked" THEN
  313.             IF M.class = Objects.Bool THEN
  314.                 IF M.b THEN F.state := F.state + {Gadgets.lockedcontents, Gadgets.lockedsize};
  315.                 ELSE F.state := F.state - {Gadgets.lockedcontents, Gadgets.lockedsize} END;
  316.                 M.res := 0
  317.             END
  318.         ELSE Gadgets.framehandle(F, M)
  319.         END
  320.     ELSIF M.id = Objects.enum THEN
  321.         M.Enum("Locked"); Gadgets.framehandle(F, M)
  322. END Attr;
  323. PROCEDURE Handler*(F: Objects.Object; VAR M: Objects.ObjMsg);
  324. VAR x, y, w, h: INTEGER; F0: NoteBook; R: Display3.Mask;
  325.     f: Display.Frame; ver: LONGINT; obj: Objects.Object;
  326. BEGIN
  327.     WITH F: NoteBook DO
  328.         IF M IS Display.FrameMsg THEN
  329.             WITH M: Display.FrameMsg DO
  330.                 IF (M.F = NIL) OR (M.F = F) THEN    (* message addressed to this frame *)
  331.                     x := M.x + F.X; y := M.y + F.Y; w := F.W; h := F.H; (* calculate display coordinates *)
  332.                     IF M IS Display.DisplayMsg THEN
  333.                         WITH M: Display.DisplayMsg DO
  334.                             IF M.device = Display.screen THEN
  335.                                 IF (M.id = Display.full) OR (M.F = NIL) THEN
  336.                                     Gadgets.MakeMask(F, x, y, M.dlink, R);
  337.                                     Restore(F, R, x, y, w, h, M)
  338.                                 ELSIF M.id = Display.area THEN
  339.                                     Gadgets.MakeMask(F, x, y, M.dlink, R);
  340.                                     Display3.AdjustMask(R, x + M.u, y + h - 1 + M.v, M.w, M.h);
  341.                                     Restore(F, R, x, y, w, h, M)
  342.                                 END
  343.                             ELSIF M.device = Display.printer THEN Gadgets.framehandle(F, M)
  344.                             END
  345.                         END
  346.                     ELSIF M IS Oberon.InputMsg THEN
  347.                         WITH M: Oberon.InputMsg DO
  348.                             IF (M.id = Oberon.track) & ~(Gadgets.selected IN F.state) THEN
  349.                                 IF (F.dsc # NIL) & Effects.Inside(M.X, M.Y, x + border, y + border, F.dsc.W, F.dsc.H) THEN
  350.                                     ToMain(F, x, y, M);
  351.                                     IF (M.res < 0) & (M.keys = {0}) THEN HandleSelect(F, M) (* select *) END;
  352.                                 ELSIF Gadgets.InActiveArea(F, M) THEN Edit(F, x, y, w, h, M);
  353.                                 ELSE Gadgets.framehandle(F, M)
  354.                                 END
  355.                             ELSIF ~(Gadgets.selected IN F.state) THEN ToMain(F, x, y, M)
  356.                             ELSE Gadgets.framehandle(F, M)
  357.                             END
  358.                         END
  359.                     ELSIF M IS Display.ModifyMsg THEN Adjust(F, M(Display.ModifyMsg))
  360.                     ELSIF M IS Display.LocateMsg THEN
  361.                         WITH M: Display.LocateMsg DO
  362.                             IF (M.loc = NIL) & Effects.Inside(M.X, M.Y, x, y, w, h) THEN
  363.                                 ToMain(F, x, y, M);
  364.                                 IF M.loc = NIL THEN M.loc := F; M.u := M.X - x; M.v := M.Y - (y + h - 1); M.res := 0 END;
  365.                             END
  366.                         END
  367.                     ELSIF M IS Display.ConsumeMsg THEN
  368.                         WITH M: Display.ConsumeMsg DO
  369.                             IF (M.id = Display.drop) & (M.F = F) & ~(Gadgets.lockedcontents IN F.state) THEN ConsumeMsg(F, M)
  370.                             ELSE ToMain(F, x, y, M) (* child may want to consume *)
  371.                             END
  372.                         END
  373.                     ELSIF M IS Display3.OverlapMsg THEN
  374.                         WITH M: Display3.OverlapMsg DO F.mask := M.M; SetMainMask(F) END
  375.                     ELSIF M IS Oberon.ControlMsg THEN
  376.                         WITH M: Oberon.ControlMsg DO
  377.                             ToMain(F, x, y, M);
  378.                             IF M.id = Oberon.neutralize THEN Neutralize(F) END
  379.                         END
  380.                     ELSIF M IS Display.SelectMsg THEN
  381.                         WITH M: Display.SelectMsg DO
  382.                             IF M.id = Display.get THEN
  383.                                 ToMain(F, x, y, M);
  384.                                 IF (F.time > M.time) & (F.dsc # NIL) & (Gadgets.selected IN F.dsc(Gadgets.Frame).state) THEN
  385.                                     M.time := F.time; M.obj := F.dsc; M.sel := F;
  386.                                 END;
  387.                             ELSE Gadgets.framehandle(F, M)
  388.                             END
  389.                         END
  390.                     ELSIF M IS Gadgets.UpdateMsg THEN
  391.                         WITH M: Gadgets.UpdateMsg DO
  392.                             IF M.obj = F.dsc THEN
  393.                                 ToMain(F, x, y, M);
  394.                                 Gadgets.MakeMask(F, x, y, M.dlink, R); UpdateTitle(F, R, x, y, w, h)
  395.                             ELSIF M.obj = F THEN Gadgets.framehandle(F, M)
  396.                             ELSE ToMain(F, x, y, M)
  397.                             END
  398.                         END
  399.                     ELSIF M IS PageMsg THEN
  400.                         WITH M: PageMsg DO
  401.                             IF M.F = F THEN HandlePageMsg(F, x, y, M)
  402.                             ELSE ToMain(F, x, y, M)
  403.                             END
  404.                         END
  405.                     ELSIF M.F # NIL THEN Gadgets.framehandle(F, M) 
  406.                     ELSE ToMain(F, x, y, M)
  407.                     END
  408.                 ELSE (* not for this frame but perhaps for a child *)    
  409.                     IF M IS Display3.UpdateMaskMsg THEN
  410.                         WITH M: Display3.UpdateMaskMsg DO
  411.                             IF M.F = F.dsc THEN SetMainMask(F)
  412.                             ELSE ToMain(F, M.x + F.X, M.y + F.Y, M)
  413.                             END
  414.                         END
  415.                     ELSIF M IS Display.ControlMsg THEN
  416.                         WITH M: Display.ControlMsg DO
  417.                             IF (M.id = Display.remove) & (M.F = F.dsc) THEN
  418.                                 f := LocatePage(F, "Previous");
  419.                                 IF f = NIL THEN RemovePage(F, F.dsc);
  420.                                     f := LocatePage(F, "First"); GotoPage(F, f)
  421.                                 ELSE
  422.                                     RemovePage(F, F.dsc); GotoPage(F, f)
  423.                                 END
  424.                             ELSE ToMain(F, M.x + F.X, M.y + F.Y, M) END
  425.                         END
  426.                     ELSIF M IS Display.ModifyMsg THEN
  427.                         IF M.F = F.dsc THEN AdjustChild(F, M(Display.ModifyMsg))
  428.                         ELSE ToMain(F, M.x + F.X, M.y + F.Y, M)
  429.                         END
  430.                     ELSE ToMain(F, M.x + F.X, M.y + F.Y, M)
  431.                     END
  432.                 END
  433.             END
  434.         (* Object messages *)
  435.         ELSIF M IS Objects.AttrMsg THEN Attr(F, M(Objects.AttrMsg))
  436.         ELSIF M IS Objects.BindMsg THEN
  437.             Gadgets.framehandle(F, M);
  438.             f := F.pages; WHILE f # NIL DO f.handle(f, M); f := f.next END (* also bind all children *)
  439.         ELSIF M IS Objects.FileMsg THEN
  440.             WITH M: Objects.FileMsg DO
  441.                 IF M.id = Objects.store THEN
  442.                     Files.WriteNum(M.R, 1);
  443.                     Gadgets.WriteRef(M.R, F.lib, F.dsc);
  444.                     f := F.pages; x := 0; WHILE f # NIL DO INC(x); f := f.next END; (* count the pages *)
  445.                     Files.WriteInt(M.R, x); (* write the count *)
  446.                     f := F.pages; x := 0; WHILE f # NIL DO Gadgets.WriteRef(M.R, F.lib, f); f := f.next END;
  447.                     Gadgets.framehandle(F, M);
  448.                 ELSIF M.id = Objects.load THEN
  449.                     Files.ReadNum(M.R, ver); IF ver # 1 THEN HALT(99) END;
  450.                     Gadgets.ReadRef(M.R, F.lib, obj);
  451.                     IF (obj # NIL) & (obj IS Display.Frame) THEN F.dsc := obj(Display.Frame) ELSE F.dsc := NIL END;
  452.                     Files.ReadInt(M.R, x); F.pages := NIL;
  453.                     WHILE x > 0 DO
  454.                         Gadgets.ReadRef(M.R, F.lib, obj);
  455.                         IF (obj # NIL) & (obj IS Display.Frame) THEN InsertPage(F, obj(Display.Frame))
  456.                         ELSE Out.String(" discarding page"); Out.Ln
  457.                         END;
  458.                         DEC(x)
  459.                     END;
  460.                     IF (F.dsc = NIL) & (F.pages # NIL) THEN F.dsc := F.pages END;
  461.                     Gadgets.framehandle(F, M)
  462.                 END
  463.             END
  464.         ELSIF M IS Objects.CopyMsg THEN
  465.             WITH M: Objects.CopyMsg DO
  466.                 IF M.stamp = F.stamp THEN M.obj := F.dlink (* copy msg arrives again *)
  467.                 ELSE (* first time copy message arrives *)
  468.                     NEW(F0); F.stamp := M.stamp; F.dlink := F0; Copy(M, F, F0); M.obj := F0
  469.                 END
  470.             END
  471.         ELSE    (* unknown msg, framehandler might know it *)
  472.             Gadgets.framehandle(F, M)
  473.         END
  474. END Handler;
  475. PROCEDURE InitNoteBook*(F: NoteBook);
  476. BEGIN F.handle := Handler; F.W := 100; F.H := 100
  477. END InitNoteBook;
  478. PROCEDURE New*;
  479. VAR F: NoteBook;
  480. BEGIN NEW(F); InitNoteBook(F); Objects.NewObj := F;
  481. END New;
  482. (* Show a new page. The following verbs are allowed: "First", "Last", "Next", "Previous", a page name.
  483. The following is accepted by the command:
  484.     NoteBooks.Show "Previous" ~             Move to the indicated page in the current notebook
  485.     NoteBooks.Show notebookname "Next" ~    Move to the indicated page in the named notebook
  486. PROCEDURE Show*;
  487. VAR S: Attributes.Scanner; bookname, where: ARRAY 64 OF CHAR; obj: Objects.Object; f: Display.Frame;
  488. BEGIN
  489.     where := ""; bookname := "";
  490.     Attributes.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  491.     Attributes.Scan(S);
  492.     IF S.class = Attributes.String THEN (* where *)
  493.         COPY(S.s, where)
  494.     ELSIF S.class = Attributes.Name THEN (* book name *)
  495.         COPY(S.s, bookname);
  496.         Attributes.Scan(S);
  497.         IF S.class = Attributes.String THEN (* where *)
  498.             COPY(S.s, where)
  499.         END
  500.     END;
  501.     IF where # "" THEN (* found something *)
  502.         IF bookname # "" THEN (* search for a definite book *)
  503.             obj := Gadgets.FindObj(Gadgets.context, bookname)
  504.         ELSE (* current book *)
  505.             obj := Gadgets.context;
  506.             WHILE (obj # NIL) & ~(obj IS NoteBook) DO obj := obj.dlink END;
  507.         END;
  508.         IF (obj # NIL) & (obj IS NoteBook) THEN
  509.             f := LocatePage(obj(NoteBook), where);
  510.             IF f = NIL THEN
  511.                 IF where = "Next" THEN f := LocatePage(obj(NoteBook), "Last")
  512.                 ELSIF where = "Previous" THEN f := LocatePage(obj(NoteBook), "First")
  513.                 END
  514.             END;
  515.             IF f # NIL THEN GotoPage(obj(NoteBook), f) END
  516.         ELSE Out.String(" [NoteBook not found]"); Out.Ln
  517.         END
  518. END Show;
  519. END NoteBooks.
  520. Gadgets.Insert NoteBooks.New ~
  521. NoteBooks.Show "Previous" ~ Current notebook
  522. NoteBooks.Show notebookname "Next" ~
  523. System.Free NoteBooks ~
  524.