home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9302 / tvision / tvpas / xmenus.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-11-10  |  22.5 KB  |  840 lines

  1. (* ------------------------------------------------------ *)
  2. (*                       XMENUS.PAS                       *)
  3. (*                                                        *)
  4. (*   Routinen und Objekte für erweiterte Menüfunktionen   *)
  5. (*        (C) 1992 by Christian Ohr & DMV-Verlag          *)
  6. (* ------------------------------------------------------ *)
  7. {$R-,S-,I-,B-,D-,L-,V-,A+,F+,O+,X+}
  8.  
  9.  
  10. UNIT XMenus;
  11.  
  12.  
  13. INTERFACE
  14.  
  15.  
  16. USES Objects, Views, Drivers, Menus, App;
  17.  
  18.  
  19. CONST
  20.   cmPinMenuOpen  = 130;
  21.   cmPinMenuClose = 131;
  22.   cmPin          = 132;
  23.   cmOwnerCloses  = 133;
  24.  
  25.   cWinMenuView   =  #9#10#11#12#13#14;
  26.   cWinStatusLine =  #9#10#11#12#13#14;
  27.  
  28.  
  29. TYPE
  30.  
  31.   (* Wird ein Menüpunkt der Menüzeile mit der rechten     *)
  32.   (* Maustaste angeklickt, so wird das zugehörige Unter-  *)
  33.   (* menü in den Desktop eingefügt. Näheres siehe bei     *)
  34.   (* tPinMenuBox. Wird ein Menü normal geöffnet, so wird  *)
  35.   (* eine tRipMenuBox erzeugt.                            *)
  36.  
  37.   pRipMenuBar = ^tRipMenuBar;
  38.   tRipMenuBar = OBJECT(tMenuBar)
  39.     Rip : BOOLEAN;
  40.     CONSTRUCTOR Init (VAR Bounds: tRect; AMenu: pMenu);
  41.     CONSTRUCTOR Load (VAR S: tStream);
  42.     PROCEDURE HandleEvent (VAR Event: tEvent); VIRTUAL;
  43.     FUNCTION NewSubView(VAR Bounds: tRect; AMenu: pMenu;
  44.                         AParentMenu: pMenuView)
  45.                         : pMenuView; VIRTUAL;
  46.     FUNCTION NewPinView (VAR Bounds: tRect; AMenu: pMenu)
  47.                         : pMenuView; VIRTUAL;
  48.     PROCEDURE Store (VAR S: tStream); VIRTUAL;
  49.   END;
  50.  
  51.  
  52.   (* Wird ein Menüpunkt der Menübox, hinter dem sich ein  *)
  53.   (* weiteres Untermenü verbirgt, mit der rechten Maus-   *)
  54.   (* taste angeklickt, so wird ein Untermenü vom Typ      *)
  55.   (* tPinMenuBox erzeugt und in den Desktop eingefügt.    *)
  56.   (* Wird normal angeklickt, so ist d. Untermenü wiederum *)
  57.   (* vom Typ tRipMenuBox.                                 *)
  58.  
  59.   pRipMenuBox = ^tRipMenuBox;
  60.   tRipMenuBox = OBJECT(tMenuBox)
  61.     Rip : BOOLEAN;
  62.     CONSTRUCTOR Init(VAR Bounds: tRect; AMenu: pMenu;
  63.                      AParentMenu: pMenuView);
  64.     CONSTRUCTOR Load (VAR S: tStream);
  65.     PROCEDURE GetEvent (VAR Event: tEvent); VIRTUAL;
  66.     PROCEDURE HandleEvent (VAR Event: tEvent); VIRTUAL;
  67.     FUNCTION NewSubView (VAR Bounds: tRect; AMenu: pMenu;
  68.                          AParentMenu: pMenuView)
  69.                          : pMenuView; VIRTUAL;
  70.     FUNCTION NewPinView (VAR Bounds: tRect; AMenu: pMenu)
  71.                         : pMenuView; VIRTUAL;
  72.     PROCEDURE Store (VAR S: tStream); VIRTUAL;
  73.   PRIVATE
  74.     PM: tPoint;
  75.   END;
  76.  
  77.  
  78.   (* Diese tPinMenuBox ist frei auf dem Bildschirm ver-   *)
  79.   (* schiebbar. Sie kann durch Anklicken d.Schließbuttons *)
  80.   (* oder mit ESCape wieder geschlossen werden. Eine      *)
  81.   (* tPinMenuBox drängelt sich immer v. alle nichtmodalen *)
  82.   (* View-Objekte auf dem Desktop.                        *)
  83.  
  84.   pPinMenuBox = ^tPinMenuBox;
  85.   tPinMenuBox = OBJECT(tRipMenuBox)
  86.     MyOwner: pView;
  87.     CONSTRUCTOR Init (VAR Bounds: tRect; AMenu: pMenu;
  88.                       AnOwner: pView);
  89.     CONSTRUCTOR Load (VAR S: tStream);
  90.     PROCEDURE Draw; VIRTUAL;
  91.     PROCEDURE HandleEvent (VAR Event: tEvent); VIRTUAL;
  92.     FUNCTION NewPinView (VAR Bounds: tRect; AMenu: pMenu)
  93.                         : pMenuView; VIRTUAL;
  94.     PROCEDURE Store (VAR S: tStream); VIRTUAL;
  95.   END;
  96.  
  97.  
  98.   (* tWinRipMenuBar korrigiert die Farben der MenuBar     *)
  99.   (* innerhalb des Windows.                               *)
  100.  
  101.   pWinRipMenuBar = ^tWinRipMenuBar;
  102.   tWinRipMenuBar = OBJECT(tRipMenuBar)
  103.     FUNCTION GetPalette: pPalette; VIRTUAL;
  104.     FUNCTION NewSubView(VAR Bounds: tRect; AMenu: pMenu;
  105.                         AParentMenu: pMenuView)
  106.                         : pMenuView; VIRTUAL;
  107.   END;
  108.  
  109.  
  110.   (* tWinRipMenuBox achtet darauf, daß d. Menü nicht oben *)
  111.   (* aus dem Fenster herausgeschoben wird, falls d. Platz *)
  112.   (* in der Vertikalen nicht ausreicht. Außerdem wird die *)
  113.   (* Farbe der Window-Palette angepaßt.                   *)
  114.  
  115.   pWinRipMenuBox = ^tWinRipMenuBox;
  116.   tWinRipMenuBox = OBJECT(tRipMenuBox)
  117.     CONSTRUCTOR Init (VAR Bounds: tRect; aMenu: pMenu;
  118.                       aParentMenu: pMenuView);
  119.     FUNCTION GetPalette: pPalette; VIRTUAL;
  120.     FUNCTION NewSubView (VAR Bounds: tRect; AMenu: pMenu;
  121.                          AParentMenu: pMenuView)
  122.                          : pMenuView; VIRTUAL;
  123.   END;
  124.  
  125.   (* tWinStatusLine korrigiert die Farben der StatusLine  *)
  126.   (* innerhalb des Windows.                               *)
  127.  
  128.   pWinStatusLine = ^tWinStatusLine;
  129.   tWinStatusLine = OBJECT(tStatusLine)
  130.     FUNCTION GetPalette: pPalette; VIRTUAL;
  131.   END;
  132.  
  133.  
  134.   (* Wenn beim Öffnen einer tAltF3MenuBox doppelt geklickt*)
  135.   (* wurde, wird ein Betätigen der Tastenkombination Alt- *)
  136.   (* F3 simuliert.                                        *)
  137.  
  138.   pAltF3MenuBox = ^tAltF3MenuBox;
  139.   tAltF3MenuBox = OBJECT(tMenuBox)
  140.     PROCEDURE GetEvent (VAR Event: tEvent); VIRTUAL;
  141.   END;
  142.  
  143.  
  144. CONST
  145.   rRipMenuBar: tStreamRec = (
  146.     ObjType: 1300;
  147.     VmtLink: Ofs(TypeOf(tRipMenuBar)^);
  148.     Load:    @tRipMenuBar.Load;
  149.     Store:   @tRipMenuBar.Store
  150.   );
  151.   rRipMenuBox: tStreamRec = (
  152.     ObjType: 1301;
  153.     VmtLink: Ofs(TypeOf(tRipMenuBox)^);
  154.     Load:    @tRipMenuBox.Load;
  155.     Store:   @tRipMenuBox.Store
  156.   );
  157.   rPinMenuBox: tStreamRec = (
  158.     ObjType: 1302;
  159.     VmtLink: Ofs(TypeOf(tPinMenuBox)^);
  160.     Load:    @tPinMenuBox.Load;
  161.     Store:   @tPinMenuBox.Store
  162.   );
  163.   rWinRipMenuBar: tStreamRec = (
  164.     ObjType: 1310;
  165.     VmtLink: Ofs(TypeOf(tWinRipMenuBar)^);
  166.     Load:    @tWinRipMenuBar.Load;
  167.     Store:   @tWinRipMenuBar.Store
  168.   );
  169.   rWinRipMenuBox: tStreamRec = (
  170.     ObjType: 1311;
  171.     VmtLink: Ofs(TypeOf(tWinRipMenuBox)^);
  172.     Load:    @tWinRipMenuBox.Load;
  173.     Store:   @tWinRipMenuBox.Store
  174.   );
  175.   rAltF3MenuBox: tStreamRec = (
  176.     ObjType: 1312;
  177.     VmtLink: Ofs(TypeOf(tAltF3MenuBox)^);
  178.     Load:    @tAltF3MenuBox.Load;
  179.     Store:   @tAltF3MenuBox.Store
  180.   );
  181.   rWinStatusLine: tStreamRec = (
  182.     ObjType: 1320;
  183.     VmtLink: Ofs(TypeOf(tWinStatusLine)^);
  184.     Load:    @tWinStatusLine.Load;
  185.     Store:   @tWinStatusLine.Store
  186.   );
  187.  
  188.  
  189. (* Einfügen v. Menüpunkten. Der Menüpunkt Item (kann auch *)
  190. (* ein komplettes Submenu sein) wird hinter dem Menüpunkt *)
  191. (* Behind in die Menüstruktur eingefügt                   *)
  192.  
  193. PROCEDURE PutItem (Item, Behind: pMenuItem);
  194.  
  195.  
  196. (* Ausklinken von Menüpunkten. Der Menüpunkt nach Behind  *)
  197. (* wird aus d. Menüstruktur genommen. Um einen bestimmten *)
  198. (* Punkt auszufügen, ist ein Aufruf erforderlich wie etwa *)
  199. (* RemoveItem(FindBeforeItem(FirstMenu, cmRemove, TRUE)); *)
  200.  
  201. FUNCTION  DeleteItem (Behind: pMenuItem): pMenuItem;
  202.  
  203.  
  204. (* Löschen von Menüpunkten. Handelt es sich bei Item um   *)
  205. (* e. komplettes Untermenü wird dieses inklusive weiterer *)
  206. (* Untermenüs rekursiv aus dem Speicher geworfen          *)
  207.  
  208. PROCEDURE FreeItem (Item: pMenuItem);
  209.  
  210.  
  211. (* Finden des aktuellen Menüpunkts. Diese Funktion gibt   *)
  212. (* die Adresse des aktuellen Menüpunkts zurück. Aufrufbsp.*)
  213. (*   RemoveItem(FindDefaultItem(FirstMenu, cmThisCmd));   *)
  214. (* Dieser Aufruf bewirkt, das der Nachfolger d. gewählten *)
  215. (* Menüpunkts aus der Menüstruktur ausgeklinkt wird.      *)
  216.  
  217. FUNCTION  FindDefaultItem (Start: pMenu; Cmd: WORD)
  218.                           : pMenuItem;
  219.  
  220.  
  221. (* Sucht ab dem Eintrag Start einen Menüpunkt mit dem     *)
  222. (* Kommando Cmd. Näheres siehe FindBeforeItem             *)
  223.  
  224. FUNCTION  FindItem (Start: POINTER; Cmd: WORD;
  225.                     Recurs: BOOLEAN): pMenuItem;
  226.  
  227.  
  228. (* Sucht ab dem Eintrag Start (Menüpunkt, Submenü oder    *)
  229. (* pMenu-Typ) dem Vorgänger des Menüpunkts m. d. Kommando *)
  230. (* Cmd. Ist Recurs TRUE, so werden auch alle gefundenen   *)
  231. (* Submenus abgeklappert. Da das erste Recordelement von  *)
  232. (* tMenu und tMenuItem jeweils ein Zeiger auf d. nächsten *)
  233. (* Menüpunkt ist, kann für beide Typen d. gleiche Routine *)
  234. (* verwendet werden.                                      *)
  235.  
  236. FUNCTION  FindBeforeItem (Start: POINTER; Cmd: WORD;
  237.                           Recurs: BOOLEAN): pMenuItem;
  238.  
  239.  
  240. (* Sucht ab dem Eintrag Start ein Untermenü mit dem Namen *)
  241. (* Name. Näheres siehe FindBeforeSubMenu                  *)
  242.  
  243. FUNCTION  FindSubMenu (Start: POINTER; Name: tMenuStr;
  244.                        Recurs: BOOLEAN): pMenuItem;
  245.  
  246.  
  247. (* Sucht ab dem Eintrag Start (Menüpunkt, Submenü oder    *)
  248. (* pMenu-Typ) dem Vorgänger des Menüpunkts mit dem Namen  *)
  249. (* Name. Ist Recurs TRUE, so werden auch alle gefundenen  *)
  250. (* Submenüs abgeklappert.                                 *)
  251.  
  252. FUNCTION  FindBeforeSubMenu (Start: POINTER; Name: tMenuStr;
  253.                              Recurs: BOOLEAN): pMenuItem;
  254.  
  255.  
  256. (* Gibt die Startadresse der aktuellen Menüleiste zurück  *)
  257.  
  258. FUNCTION  FirstMenu: pMenu;
  259.  
  260.  
  261. (* ------------------------------------------------------ *)
  262. (* Prozeduren zum alternativen Aufbau von Menüstrukturen  *)
  263. (* ------------------------------------------------------ *)
  264.  
  265. PROCEDURE StartMenuAt (Menu: pMenu);
  266. PROCEDURE AddSub (Name: tMenuStr; AHelpCtx: WORD);
  267. PROCEDURE AddItem (Name, param: tMenuStr; KeyCode,
  268.                    Command, AHelpCtx: WORD);
  269. PROCEDURE AddLine;
  270. PROCEDURE CloseSub (Name: tMenuStr);
  271.  
  272.  
  273.  
  274. PROCEDURE RegisterXMenus;
  275.  
  276.  
  277. IMPLEMENTATION
  278.  
  279.  
  280. VAR
  281.   FirstMenuRec : pMenu;
  282.   CurrentItem  : pMenuItem;
  283.   CurrentMenu  : pMenu;
  284.  
  285.  
  286.  
  287. (* ------------------------------------------------------ *)
  288. (*                      tRipMenuBar                       *)
  289. (* ------------------------------------------------------ *)
  290.  
  291.  
  292. CONSTRUCTOR tRipMenuBar.Init(VAR Bounds: tRect;
  293.                              AMenu: pMenu);
  294. BEGIN
  295.   tMenuBar.Init(Bounds, AMenu);
  296.   Rip := TRUE;
  297. END;
  298.  
  299.  
  300. CONSTRUCTOR tRipMenuBar.Load (VAR S: tStream);
  301. BEGIN
  302.   tMenuBar.Load(S);
  303.   S.Read(Rip, SizeOf(BOOLEAN));
  304. END;
  305.  
  306.  
  307. PROCEDURE tRipMenuBar.HandleEvent (VAR Event: tEvent);
  308. VAR
  309.   P: tPoint;
  310.   R: tRect;
  311.   Item: pMenuItem;
  312. BEGIN
  313.   IF Rip AND (Event.What = evMouseDown) AND
  314.      (Event.Buttons = mbRightButton) THEN
  315.     IF (Menu <> NIL) AND (Menu^.Items <> NIL) THEN BEGIN
  316.  
  317.       (* Herausfinden, welcher Menüpunkt angeklickt wurde *)
  318.       MakeLocal(Event.Where, P);
  319.       Item := pMenuItem(Menu);
  320.       REPEAT
  321.         GetItemRect(Item^.Next, R);
  322.         Item := Item^.Next;
  323.       UNTIL (Item = NIL) OR R.Contains(P);
  324.  
  325.       (* Neues pMenu erzeugen und an pPinMenuBox leiten *)
  326.       IF Item <> NIL THEN BEGIN
  327.         MakeGlobal(R.A, R.A);
  328.         Desktop^.MakeLocal(R.A, R.A);
  329.         R.Move(-1, 1);
  330.         Desktop^.Insert(NewPinView(R, Item^.SubMenu));
  331.       END;
  332.       ClearEvent(Event);
  333.     END;
  334.  
  335.   tMenuBar.HandleEvent(Event);
  336. END;
  337.  
  338.  
  339. FUNCTION tRipMenuBar.NewSubView(VAR Bounds: tRect;
  340.                      AMenu: pMenu; AParentMenu : pMenuView)
  341.                      : pMenuView;
  342. BEGIN
  343.   NewSubView := New(pRipMenuBox, Init(
  344.                     Bounds, AMenu, AParentMenu));
  345. END;
  346.  
  347.  
  348. FUNCTION tRipMenuBar.NewPinView (VAR Bounds: tRect;
  349.                   AMenu: pMenu): pMenuView;
  350. BEGIN
  351.   NewPinView := New(pPinMenuBox, Init(Bounds, AMenu,Owner));
  352. END;
  353.  
  354.  
  355. PROCEDURE tRipMenuBar.Store (VAR S: tStream);
  356. BEGIN
  357.   tMenuBar.Store(S);
  358.   S.Write(Rip, SizeOf(BOOLEAN));
  359. END;
  360.  
  361.  
  362.  
  363. (* ------------------------------------------------------ *)
  364. (*                      tRipMenuBox                       *)
  365. (* ------------------------------------------------------ *)
  366.  
  367.  
  368. CONSTRUCTOR tRipMenuBox.Init(VAR Bounds: tRect;
  369.                AMenu: pMenu; AParentMenu: pMenuView);
  370. BEGIN
  371.   tMenuBox.Init(Bounds, AMenu, AParentMenu);
  372.   Rip := TRUE;
  373. END;
  374.  
  375.  
  376. CONSTRUCTOR tRipMenuBox.Load (VAR S: tStream);
  377. BEGIN
  378.   tMenuBox.Load(S);
  379.   S.Read(Rip, SizeOf(BOOLEAN));
  380. END;
  381.  
  382.  
  383. PROCEDURE tRipMenuBox.GetEvent (VAR Event: tEvent);
  384. BEGIN
  385.   tMenuBox.GetEvent(Event);
  386.   IF Rip AND (Event.What = evMouseDown) AND
  387.     (Event.Buttons = mbRightButton) THEN BEGIN
  388.     PM := Event.Where;
  389.     ClearEvent(Event);
  390.     Event.What := evCommand;
  391.     Event.Command := cmPin;
  392.   END;
  393. END;
  394.  
  395.  
  396. PROCEDURE tRipMenuBox.HandleEvent (VAR Event: tEvent);
  397. VAR
  398.   R: tRect;
  399.   Item: pMenuItem;
  400. BEGIN
  401.   IF Event.Command = cmPin THEN BEGIN
  402.     MakeLocal(PM, PM);
  403.     Item := pMenuItem(Menu);
  404.     REPEAT
  405.       GetItemRect(Item^.Next, R);
  406.       Item := Item^.Next;
  407.     UNTIL (Item = NIL) OR R.Contains(PM);
  408.  
  409.     IF (Item <> NIL) AND (Item^.Command = 0) THEN BEGIN
  410.       MakeGlobal(PM, R.A);
  411.       Desktop^.MakeLocal(R.A, R.A);
  412.       Desktop^.Insert(NewPinView(R, Item^.SubMenu));
  413.       ClearEvent(Event);
  414.     END;
  415.   END;
  416.  
  417.   tMenuBox.HandleEvent(Event);
  418. END;
  419.  
  420.  
  421. FUNCTION tRipMenuBox.NewSubView(VAR Bounds: tRect;
  422.            AMenu: pMenu; AParentMenu: pMenuView): pMenuView;
  423. BEGIN
  424.   NewSubView := New(pRipMenuBox, Init(
  425.                     Bounds, AMenu, AParentMenu));
  426. END;
  427.  
  428.  
  429. FUNCTION tRipMenuBox.NewPinView (VAR Bounds: tRect;
  430.                   AMenu: pMenu): pMenuView;
  431. BEGIN
  432.   NewPinView := New(pPinMenuBox, Init(Bounds, AMenu,Owner));
  433. END;
  434.  
  435.  
  436. PROCEDURE tRipMenuBox.Store (VAR S: tStream);
  437. BEGIN
  438.   tMenuBox.Store(S);
  439.   S.Write(Rip, SizeOf(BOOLEAN));
  440. END;
  441.  
  442.  
  443.  
  444. (* ------------------------------------------------------ *)
  445. (*                      tPinMenuBox                       *)
  446. (* ------------------------------------------------------ *)
  447.  
  448. CONSTRUCTOR tPinMenuBox.Init (VAR Bounds: tRect;
  449.              AMenu: pMenu; AnOwner: pView);
  450. BEGIN
  451.   IF AMenu <> NIL THEN BEGIN
  452.     tRipMenuBox.Init(Bounds, AMenu, NIL);
  453.     MyOwner := AnOwner;
  454.     MoveTo(Bounds.A.X, Bounds.A.Y);
  455.     Options := Options AND NOT ofSelectable; {OR ofTopSelect;}
  456.     Message(Application, evBroadcast, cmPinMenuOpen, @Self);
  457.   END;
  458. END;
  459.  
  460.  
  461. CONSTRUCTOR tPinMenuBox.Load (VAR S: tStream);
  462. BEGIN
  463.   tRipMenuBox.Load(S);
  464.   GetPeerViewPtr(S, MyOwner);
  465. END;
  466.  
  467.  
  468. PROCEDURE tPinMenuBox.Draw;
  469. BEGIN
  470.   tRipMenuBox.Draw;
  471.   WriteChar(3, 0, '[', 1, 1);
  472.   WriteChar(4, 0, #254, 3, 1);
  473.   WriteChar(5, 0, ']', 1, 1);
  474. END;
  475.  
  476.  
  477. PROCEDURE tPinMenuBox.HandleEvent (VAR Event: tEvent);
  478. VAR
  479.   Limits: tRect;
  480.   P: tPoint;
  481.  
  482.   PROCEDURE ClosePinMenu;
  483.   BEGIN
  484.     Message(Application, evBroadcast, cmPinMenuClose,@Self);
  485.     Free;
  486.   END;
  487.  
  488. BEGIN
  489.   CASE Event.What OF
  490.     evMouseDown:
  491.       BEGIN
  492.         MakeLocal(Event.Where, P);
  493.         IF P.Y = 0 THEN BEGIN
  494.           IF (P.X > 2) AND (P.X < 6) THEN
  495.             ClosePinMenu ELSE
  496.           BEGIN
  497.             Owner^.GetExtent(Limits);
  498.             (* Nur bis zur Menüzeile verschiebbar *)
  499.             Inc(Limits.A.Y, Pred(Size.Y));
  500.             DragView(Event, dmDragMove, Limits,
  501.                      Limits.A, Limits.B);
  502.           END;
  503.           ClearEvent(Event);
  504.         END;
  505.       END;
  506.     evKeyDown:
  507.       IF Event.KeyCode = kbEsc THEN BEGIN
  508.         ClosePinMenu;
  509.         ClearEvent(Event);
  510.       END;
  511.     evBroadcast:
  512.       CASE Event.Command OF
  513.         cmOwnerCloses:
  514.           IF pView(Event.InfoPtr) = MyOwner THEN
  515.             ClosePinMenu;
  516.         cmCommandSetChanged:
  517.           DrawView;
  518.         cmReceivedFocus:
  519.           IF NOT pView(Event.InfoPtr)^.GetState(sfModal)
  520.             THEN MakeFirst;
  521.       END;
  522.   END;
  523.   tRipMenuBox.HandleEvent(Event);
  524. END;
  525.  
  526.  
  527. FUNCTION tPinMenuBox.NewPinView (VAR Bounds: tRect;
  528.                   AMenu: pMenu) : pMenuView;
  529. BEGIN
  530.   NewPinView := New(pPinMenuBox, Init(Bounds, AMenu,
  531.                                       MyOwner));
  532. END;
  533.  
  534.  
  535. PROCEDURE tPinMenuBox.Store (VAR S: tStream);
  536. BEGIN
  537.   tRipMenuBox.Store(S);
  538.   PutPeerViewPtr(S, MyOwner);
  539. END;
  540.  
  541.  
  542.  
  543. (* ------------------------------------------------------ *)
  544. (*                     tWinRipMenuBar                     *)
  545. (* ------------------------------------------------------ *)
  546.  
  547.  
  548. FUNCTION tWinRipMenuBar.GetPalette: pPalette;
  549. CONST
  550.   P: STRING[Length(cWinMenuView)] = cWinMenuView;
  551. BEGIN
  552.   GetPalette := @P;
  553. END;
  554.  
  555.  
  556. FUNCTION tWinRipMenuBar.NewSubView(VAR Bounds: tRect;
  557.            AMenu: pMenu; AParentMenu: pMenuView): pMenuView;
  558. BEGIN
  559.   NewSubView := New(pWinRipMenuBox, Init(
  560.                     Bounds, AMenu, AParentMenu));
  561. END;
  562.  
  563.  
  564.  
  565. (* ------------------------------------------------------ *)
  566. (*                    tWinRipMenuBox                      *)
  567. (* ------------------------------------------------------ *)
  568.  
  569. CONSTRUCTOR tWinRipMenuBox.Init (VAR Bounds: tRect;
  570.                     aMenu: pMenu; aParentMenu: pMenuView);
  571.  
  572. VAR
  573.   W, H, L: INTEGER;
  574.   P: pMenuItem;
  575.   R: tRect;
  576. BEGIN
  577.   W := 10; H := 2;
  578.   IF AMenu <> NIL THEN BEGIN
  579.     P := AMenu^.Items;
  580.     WHILE P <> NIL DO BEGIN
  581.       IF P^.Name <> NIL THEN BEGIN
  582.         L := CStrLen(P^.Name^) + 6;
  583.         IF P^.Command = 0 THEN
  584.           Inc(L, 3) ELSE
  585.           IF P^.Param <> NIL THEN
  586.             Inc(L, CStrLen(P^.Param^) + 2);
  587.         IF L > W THEN W := L;
  588.       END;
  589.       Inc(H);
  590.       P := P^.Next;
  591.     END;
  592.   END;
  593.   R.Copy(Bounds);
  594.   IF R.A.X + W < R.B.X THEN
  595.     R.B.X := R.A.X + W ELSE BEGIN
  596.       R.A.X := Pred(R.B.X - W);
  597.       R.B.X := Pred(R.B.X);
  598.     END;
  599.   IF R.A.Y + H < R.B.Y THEN
  600.     R.B.Y := R.A.Y + H ELSE
  601.     R.B.Y := Pred(R.B.Y);
  602.   tMenuView.Init(R);
  603.   State := State OR sfShadow;
  604.   Options := Options OR ofPreProcess;
  605.   Menu := AMenu;
  606.   ParentMenu := AParentMenu;
  607.  
  608. END;
  609.  
  610.  
  611. FUNCTION tWinRipMenuBox.GetPalette: pPalette;
  612. CONST
  613.   P: STRING[Length(cWinMenuView)] = cWinMenuView;
  614. BEGIN
  615.   GetPalette := @P;
  616. END;
  617.  
  618.  
  619. FUNCTION tWinRipMenuBox.NewSubView(VAR Bounds: tRect;
  620.           AMenu: pMenu; AParentMenu: pMenuView): pMenuView;
  621. BEGIN
  622.   NewSubView := New(pWinRipMenuBox, Init(
  623.                     Bounds, AMenu, AParentMenu));
  624. END;
  625.  
  626.  
  627.  
  628. (* ------------------------------------------------------ *)
  629. (*                    tWinStatusLine                      *)
  630. (* ------------------------------------------------------ *)
  631.  
  632.  
  633. FUNCTION tWinStatusLine.GetPalette: pPalette;
  634. CONST
  635.   P: STRING[Length(cWinStatusLine)] = cWinStatusLine;
  636. BEGIN
  637.   GetPalette := @P;
  638. END;
  639.  
  640.  
  641.  
  642. (* ------------------------------------------------------ *)
  643. (*                    tAltF3MenuBox                       *)
  644. (* ------------------------------------------------------ *)
  645.  
  646.  
  647. PROCEDURE tAltF3MenuBox.GetEvent (VAR Event: tEvent);
  648. BEGIN
  649.   tMenuBox.GetEvent(Event);
  650.   IF (Event.What = evMouseDown) AND Event.DOUBLE THEN BEGIN
  651.     Event.What := evKeyDown;
  652.     Event.KeyCode := kbAltF3;
  653.   END;
  654. END;
  655.  
  656.  
  657.  
  658.  
  659. PROCEDURE PutItem (Item, Behind: pMenuItem);
  660. BEGIN
  661.   IF (Item <> NIL) AND (Behind <> NIL) THEN BEGIN
  662.     Item^.Next := Behind^.Next;
  663.     Behind^.Next := Item;
  664.   END;
  665. END;
  666.  
  667.  
  668. FUNCTION DeleteItem (Behind: pMenuItem): pMenuItem;
  669. BEGIN
  670.   IF Behind <> NIL THEN BEGIN
  671.     DeleteItem := Behind^.Next;
  672.     Behind^.Next := Behind^.Next^.Next
  673.   END ELSE DeleteItem := NIL;
  674. END;
  675.  
  676.  
  677. PROCEDURE FreeItem (Item: pMenuItem);
  678. BEGIN
  679.   IF Item <> NIL THEN
  680.     IF Item^.Command <> 0 THEN
  681.       Dispose(Item) ELSE
  682.       DisposeMenu(Item^.SubMenu);
  683. END;
  684.  
  685.  
  686. FUNCTION FindDefaultItem (Start: pMenu; Cmd: WORD)
  687.                           : pMenuItem;
  688. VAR
  689.   Item: pMenuItem;
  690.   Menu: pMenu;
  691. BEGIN
  692.   IF Start <> NIL THEN BEGIN
  693.     Menu := Start;
  694.     Item := Menu^.Default;
  695.     WHILE (Item <> NIL) AND (Item^.Command <> Cmd) DO
  696.       IF Item^.Command = 0 THEN BEGIN
  697.         Menu := Item^.SubMenu;
  698.         Item := Menu^.Default
  699.       END ELSE Item := NIL;
  700.   END;
  701.   FindDefaultItem := Item
  702. END;
  703.  
  704.  
  705. FUNCTION FindItem (Start: POINTER; Cmd: WORD;
  706.                    Recurs: BOOLEAN): pMenuItem;
  707. VAR
  708.   Item: pMenuItem;
  709. BEGIN
  710.   Item := FindBeforeItem(Start, Cmd, Recurs);
  711.   IF Item <> NIL THEN
  712.     FindItem := Item^.Next ELSE
  713.     FindItem := NIL;
  714. END;
  715.  
  716.  
  717. FUNCTION FindBeforeItem (Start: POINTER; Cmd: WORD;
  718.                          Recurs: BOOLEAN): pMenuItem;
  719. VAR
  720.   SubItem, Item: pMenuItem;
  721. BEGIN
  722.   IF Start <> NIL THEN BEGIN
  723.     Item := Start;
  724.     WHILE (Item^.Next <> NIL) AND
  725.           (Item^.Next^.Command <> Cmd) DO
  726.       IF (Item^.Next^.Command = 0) AND
  727.          (Item^.Next^.Name <> NIL) AND Recurs THEN BEGIN
  728.         SubItem := FindBeforeItem(Item^.Next^.SubMenu, Cmd,
  729.                                   Recurs);
  730.         IF SubItem^.Next <> NIL THEN
  731.           Item := SubItem ELSE
  732.           Item := Item^.Next;
  733.       END ELSE Item := Item^.Next;
  734.     FindBeforeItem := Item
  735.   END ELSE FindBeforeItem := NIL;
  736. END;
  737.  
  738.  
  739. FUNCTION FindSubMenu (Start: POINTER; Name: tMenuStr;
  740.                       Recurs: BOOLEAN): pMenuItem;
  741. VAR
  742.   Item: pMenuItem;
  743. BEGIN
  744.   Item := FindBeforeSubMenu(Start, Name, Recurs);
  745.   IF Item <> NIL THEN
  746.     FindSubMenu := Item^.Next ELSE
  747.     FindSubMenu := NIL;
  748. END;
  749.  
  750.  
  751. FUNCTION FindBeforeSubMenu (Start: POINTER; Name: tMenuStr;
  752.                              Recurs: BOOLEAN): pMenuItem;
  753. VAR
  754.   SubItem, Item: pMenuItem;
  755. BEGIN
  756.   IF Start <> NIL THEN BEGIN
  757.     Item := Start;
  758.     WHILE (Item^.Next <> NIL) AND
  759.           (Item^.Next^.Name^ <> Name) DO
  760.       IF (Item^.Next^.Command = 0) AND
  761.          (Item^.Next^.Name <> NIL) AND Recurs THEN BEGIN
  762.         SubItem := FindBeforeSubMenu(Item^.Next^.SubMenu,
  763.                                      Name, Recurs);
  764.         IF SubItem^.Next <> NIL THEN
  765.           Item := SubItem ELSE
  766.           Item := Item^.Next;
  767.       END ELSE Item := Item^.Next;
  768.     FindBeforeSubMenu := Item
  769.   END ELSE FindBeforeSubMenu := NIL;
  770. END;
  771.  
  772.  
  773. FUNCTION FirstMenu: pMenu;
  774. BEGIN
  775.   IF MenuBar <> NIL THEN
  776.     FirstMenu := MenuBar^.Menu ELSE
  777.     FirstMenu := NIL;
  778. END;
  779.  
  780.  
  781.  
  782. PROCEDURE StartMenuAt (Menu: pMenu);
  783. BEGIN
  784.   FirstMenuRec := Menu;
  785.   CurrentMenu := FirstMenuRec;
  786.   CurrentItem := pMenuItem(FirstMenuRec);
  787. END;
  788.  
  789.  
  790. PROCEDURE AddSub (Name: tMenuStr; AHelpCtx: WORD);
  791. BEGIN
  792.   PutItem(NewSubMenu(Name, AHelpCtx, NewMenu(NIL), NIL),
  793.           CurrentItem);
  794.   CurrentMenu^.Default := CurrentMenu^.Items;
  795.   CurrentMenu := CurrentItem^.Next^.SubMenu;
  796.   CurrentItem := pMenuItem(CurrentMenu);
  797. END;
  798.  
  799.  
  800. PROCEDURE AddItem (Name, Param: tMenuStr; KeyCode,
  801.                        Command, AHelpCtx: WORD);
  802. BEGIN
  803.   PutItem(NewItem(Name, Param, KeyCode, Command, AHelpCtx,
  804.           NIL), CurrentItem);
  805.   CurrentMenu^.Default := CurrentMenu^.Items;
  806.   CurrentItem := CurrentItem^.Next;
  807. END;
  808.  
  809.  
  810. PROCEDURE AddLine;
  811. BEGIN
  812.   PutItem(NewLine(NIL), CurrentItem);
  813.   CurrentItem := CurrentItem^.Next;
  814. END;
  815.  
  816.  
  817. PROCEDURE CloseSub (Name: tMenuStr);
  818. BEGIN
  819.   CurrentItem := FindSubMenu(FirstMenuRec, Name, TRUE);
  820. END;
  821.  
  822.  
  823. PROCEDURE RegisterXMenus;
  824. BEGIN
  825.   RegisterType(rRipMenuBar);
  826.   RegisterType(rRipMenuBox);
  827.   RegisterType(rPinMenuBox);
  828.   RegisterType(rWinRipMenuBar);
  829.   RegisterType(rWinRipMenuBox);
  830.   RegisterType(rAltF3MenuBox);
  831.   RegisterType(rWinStatusLine);
  832. END;
  833.  
  834.  
  835. END.
  836.  
  837.  
  838. (* ------------------------------------------------------ *)
  839. (*                 Ende von XMENUS.PAS                    *)
  840.