home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / sys / mac / programm / 13142 < prev    next >
Encoding:
Text File  |  1992-07-29  |  20.0 KB  |  867 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!ames!eos!data.nas.nasa.gov!taligent!keith@taligent.com
  2. From: keith@taligent.com (Keith Rollin)
  3. Newsgroups: comp.sys.mac.programmer
  4. Subject: Re: menubar in dialogs (long)
  5. Message-ID: <Bs55p8.1D8@taligent.com>
  6. Date: 29 Jul 92 08:17:31 GMT
  7. References: <kaas-280792151810@jojo.cc.ruu.nl>
  8. Sender: usenet@taligent.com (More Bytes Than You Can Read)
  9. Organization: Taligent
  10. Lines: 855
  11.  
  12. In article <kaas-280792151810@jojo.cc.ruu.nl>, kaas@cc.ruu.nl (Dick Kaas)
  13. writes:
  14. > I'm planning to write a TCL pane for a menu-bar.
  15. > Is there a simple way to implement a menubar into dialogs  (like WP and
  16. > superboomerang) without having to write a complete menu package by
  17. > yourself?
  18. > I have looked at the low memory globals, such as MenuBarHook etc. None of
  19. > these seem useful.
  20. >
  21.  
  22. I did one of these. I wouldn't consider the approach I took to be "simple."
  23. Although I wrote the bulk of it in a couple of nights, they were long nights. I
  24. had to re-implement and wrap up a lot of stuff. My first attempt that tried
  25. setting the origin of the window manager port at strategic times didn't work
  26. because of a bug in System 7.0's background saving and restoring routines.
  27.  
  28. I did it as a control to make it easy for others to use. It's included below.
  29.  
  30. How to use: create a control item in your DITL, and specify the CDEF shown
  31. below. When the user clicks on the item, the dialog manager will call
  32. TrackControl. If you are writing a TCL pane, then call TrackControl yourself.
  33. The control will track the menus and leave the chosen item in contrlValue, so
  34. all you have to do is call GetCtlValue to get the chosen menu item.
  35.  
  36. If you want to manipulate the menubar, use one of the macros starting with a "Z"
  37. included below. Those macros will call the CDEF directly with a custom message
  38. number. Please note that for the CallIt macro to work, the CDEF must be marked
  39. as locked. If you don't want to lock your CDEF, then you'll need a more
  40. elaborate way to call the CDEF than just dereferencing the handle and jumping.
  41. As an example of what you might need, I've included a commented-out function at
  42. the end of this posting that calls the standard MBDF directly.
  43.  
  44. A note: pay no attention to the UseGlobals and DoneWithGlobals stuff. That's for
  45. an MPW package that allows globals in standalone code. If you are using THINK C,
  46. don't worry about it. If you are using MPW, use the techniques shown in Technote
  47. #256.
  48.  
  49. (BTW: as you'll see below, MenubarHook _was_ useful!)
  50.  
  51. As a final note, I found it useful to write a wrapper for the standard MDEF.
  52. Because the below CDEF essentially works by using popup menus, you need to have
  53. fine control over where the popup menus show up. The standard MBDF will try to
  54. position popup menus so that as much of them will appear on the screen as
  55. possible. However, we don't want that with our menubar CDEF; we want to the top
  56. of the menu to be right below the menubar. Therefore, I wrap up the standard
  57. MDEF with one of my own that first calls the standard MDEF, and then checks to
  58. see if the message handled was mPopUpMsg. If so, the top of the menu is adjusted
  59. by executing "menuRect->top = *itemID;".
  60.  
  61. Sorry for the lack of any comments in the source code...
  62.  
  63. -------------
  64. MenubarCDEF.h
  65. -------------
  66.  
  67. #ifndef THINK_C
  68. #include <Controls.h>
  69. #endif
  70.  
  71. #define kStayPutMDEF    90
  72.  
  73. #define clearMenuBar    128
  74. #define deleteMenu        129            // param = ID of menu to remove
  75. #define drawMenuBar        130
  76. #define flashMenuBar    131            // param = ID of menu to flash
  77. #define getMenuBar        132            // result = handle to custom data
  78. #define getMHandle        133            // param = menu ID, result = menuHandle
  79. #define hiliteMenu        134            // param = ID of menu to hilite
  80. #define insertMenu        135            // param = menuHandle, varCode = before menu ID
  81. #define menuKey            136            // param = char, result = same as MenuKey
  82. #define menuSelect        137            // param = startPt, result = same as MenuSelect
  83. #define setMenuBar        138            // param = result from getMenuBar
  84.  
  85. typedef pascal long (*CDEFProc)(short varCode, ControlHandle theControl,
  86.                                     short msg, long param);
  87.  
  88. #define CallIt(ctl) ((CDEFProc) *((**ctl).contrlDefProc))
  89.  
  90. #define ZClearMenuBar(ctl)            CallIt(ctl)(0, ctl, clearMenuBar, 0)
  91. #define ZDeleteMenu(ctl, menuID)    CallIt(ctl)(0, ctl, deleteMenu, menuID)
  92. #define ZDrawMenuBar(ctl)            CallIt(ctl)(0, ctl, drawMenuBar, 0)
  93. #define ZFlashMenuBar(ctl, menuID)    CallIt(ctl)(0, ctl, flashMenuBar, menuID)
  94. #define ZGetMenuBar(ctl)            (Handle) CallIt(ctl)(0, ctl, getMenuBar, 0)
  95. #define ZGetMHandle(ctl, menuID)    (MenuHandle) CallIt(ctl)(0, ctl, getMHandle,
  96. menuID)
  97. #define ZHiliteMenu(ctl, menuID)    CallIt(ctl)(0, ctl, hiliteMenu, 0)
  98. #define ZInsertMenu(ctl, mh, id)    CallIt(ctl)(id, ctl, insertMenu, mh)
  99. #define ZMenuKey(ctl, key)            CallIt(ctl)(0, ctl, menuKey, key)
  100. #define ZMenuSelect(ctl, startPt)    CallIt(ctl)(0, ctl, menuSelect, startPt)
  101. #define ZSetMenuBar(ctl, mbar)        CallIt(ctl)(0, ctl, setMenuBar, mbar)
  102.  
  103.  
  104.  
  105. -------------
  106. MenubarCDEF.c
  107. -------------
  108.  
  109.  
  110. /*
  111.     To do:
  112.     
  113.     % Support hierarchicals
  114.     % Support color
  115. */
  116.  
  117. #include "MetaGlobal.h"
  118. #include "MenubarCDEF.h"
  119.  
  120. #ifdef THINK_C
  121.     #include <SetUpA4.h>
  122.     Ptr GetA0(void) = { 0x2008 };
  123. #else
  124.     #include <Types.h>
  125.     #include <Memory.h>
  126.     #include <Menus.h>
  127.     #include <OSEvents.h>            // For EvQPtr
  128.     #include <Resources.h>            // For GetResource
  129.     #include <Script.h>                // For GetMBarHeight
  130.     #include <ToolUtils.h>            // For HiWord, LoWord
  131.     #include <Windows.h>            // we return inMenubar as our part
  132.     #include "SAGlobals.h"
  133.     
  134.     #define MenuHook (*(ProcPtr*) 0xA30)
  135.     #define MenuList (*(Handle*) 0xA1C)
  136. #endif
  137.  
  138. #define NIL                NULL
  139. #define kTopMargin        1
  140. #define kBottomMargin    1
  141. #define kTextMargin        8
  142.  
  143.  
  144. typedef struct {
  145.     MenuHandle        menu;
  146.     short            menuLeft;
  147. } MenuRec, *MenuRecPtr;
  148.  
  149.  
  150. typedef struct {
  151.     MenuHandle        menu;
  152.     short            reserved;
  153. } HMenuRec, *HMenuRecPtr;
  154.  
  155.  
  156. typedef struct {
  157.     short            lastMenu;
  158.     short            lastRight;
  159.     short            mbResID;
  160.     MenuRec            menus[1];
  161.     //    short            lastHMenu;
  162.     //    PixMapHandle    menuTitleSave;
  163.     //    MenuRec            hmenus[1];
  164. } MenuBar, *MenuBarPtr, **MenuBarHdl;
  165.  
  166.  
  167. ProcPtr            gOldMenuHook;
  168. ControlHandle    gControl;
  169. MenuBarHdl        gMenuList;
  170. short            gTheMenu;            // _Index_ of currently hilighted menu
  171. short            gNormalHeight;
  172. FontInfo        gFontInfo;
  173. short            gBaseline;
  174.  
  175.  
  176. pascal long        main(short varCode, ControlHandle theControl, short msg, long
  177. param);
  178.  
  179. void            DrawMyControl(short part);
  180. short            TestMyControl(Point location);
  181. void            InitMyControl(void);
  182. void            DisposeMyControl(void);
  183.  
  184. void            DoClearMenuBar(void);
  185. void            DoDeleteMenu(short menuID);
  186. void            DoDrawMenuBar(void);
  187. void            DoFlashMenuBar(short menuID);
  188. MenuBarHdl        DoGetMenuBar(void);
  189. MenuHandle        DoGetMHandle(short menuID);
  190. void            DoHiliteMenu(short menuID);
  191. void            DoInsertMenu(MenuHandle menu, short before);
  192. long            DoMenuKey(char theKey);
  193. long            DoMenuSelect(Point startPt);
  194. void            DoSetMenuBar(MenuBarHdl menuBar);
  195.  
  196. void            DrawMenuTitle(short menuIndex);
  197. short            FindHitMenu(Point location);        // returns menuIndex (or -1)
  198. short            GetFreeHMenuID(void);
  199. Rect            GetHitRect(short menuIndex);
  200. Rect            GetInvertRect(short menuIndex);
  201. short            GetMenuCount(void);
  202. MenuHandle        GetNthMenu(short index);
  203. Point            GetTitleLocation(short menuIndex);
  204. short            IDToIndex(short);
  205. short            IndexToID(short);
  206. void            MyMenuHook(void);
  207. void            SwapMenuBars(void);
  208.  
  209. //--------------------------------------------------------------------------------
  210.  
  211. pascal long    main(short varCode, ControlHandle theControl, short msg, long param)
  212. {
  213.     long        result;
  214.     Ptr            oldA5;
  215.     char        oldState;
  216.     Handle        ourHandle;
  217.     Ptr            ourPtr;
  218.  
  219.     ourPtr = GetA0();
  220.  
  221. #ifdef THINK_C
  222.     RememberA0();
  223.     SetUpA4();
  224. #else
  225.     oldA5 = UseGlobals();
  226. #endif
  227.  
  228.     ourHandle = RecoverHandle(ourPtr);
  229.     oldState = HGetState(ourHandle);
  230.     HLock(ourHandle);
  231.     
  232.     result = 0;
  233.     gControl = theControl;
  234.     GetFontInfo(&gFontInfo);
  235.     gBaseline = kTopMargin + gFontInfo.leading + gFontInfo.ascent;
  236.  
  237.     if (msg < 128) {
  238.         switch (msg) {
  239.             case drawCntl:
  240.                 DrawMyControl((short) param);
  241.                 break;
  242.             case testCntl:
  243.                 result = TestMyControl(*(Point*) ¶m);
  244.                 break;
  245.             case initCntl:
  246.                 InitMyControl();
  247.                 break;
  248.             case dispCntl:
  249.                 DisposeMyControl();
  250.                 break;
  251.             case calcCntlRgn:
  252.             case calcThumbRgn:
  253.                 RectRgn((RgnHandle) param, &(**gControl).contrlRect);
  254.                 result = 1;
  255.                 break;
  256.         }
  257.     } else {
  258.         switch (msg) {
  259.             case clearMenuBar:
  260.                 DoClearMenuBar();
  261.                 break;
  262.             case deleteMenu:
  263.                 DoDeleteMenu((short) param);
  264.                 break;
  265.             case drawMenuBar:
  266.                 DoDrawMenuBar();
  267.                 break;
  268.             case flashMenuBar:
  269.                 DoFlashMenuBar((short) param);
  270.                 break;
  271.             case getMenuBar:
  272.                 result = (long) DoGetMenuBar();
  273.                 break;
  274.             case getMHandle:
  275.                 result = (long) DoGetMHandle((short) param);
  276.                 break;
  277.             case hiliteMenu:
  278.                 DoHiliteMenu((short) param);
  279.                 break;
  280.             case insertMenu:
  281.                 DoInsertMenu((MenuHandle) param, varCode);
  282.                 break;
  283.             case menuKey:
  284.                 result = DoMenuKey((char) param);
  285.                 break;
  286.             case menuSelect:
  287.                 result = DoMenuSelect(*(Point*) ¶m);
  288.                 break;
  289.             case setMenuBar:
  290.                 DoSetMenuBar((MenuBarHdl) param);
  291.                 break;
  292.         }
  293.     }
  294.  
  295. #ifdef THINK_C
  296.     RestoreA4();
  297. #else
  298.     DoneWithGlobals(oldA5);
  299. #endif
  300.     
  301.     HSetState(ourHandle, oldState);
  302.  
  303.     return result;
  304. }
  305.  
  306.  
  307. //--------------------------------------------------------------------------------
  308.  
  309. void    DrawMyControl(short part)
  310. {
  311. #pragma unused (part)
  312.  
  313.     if ((**gControl).contrlVis != false) {
  314.         DoDrawMenuBar();
  315.     }
  316. }
  317.  
  318.  
  319. //--------------------------------------------------------------------------------
  320.  
  321. short    TestMyControl(Point location)
  322. {
  323.     short        hitPart;
  324.     
  325.     hitPart = 0;
  326.     if (FindHitMenu(location) >= 0) {
  327.         hitPart = inMenuBar;
  328.         if (Button()) {
  329.             DoMenuSelect(location);
  330.             if ((**gControl).contrlValue == 0) {
  331.                 hitPart = 0;
  332.             }
  333.         }
  334.     }
  335.  
  336.     return hitPart;
  337. }
  338.  
  339.  
  340. //--------------------------------------------------------------------------------
  341.  
  342. void    InitMyControl()
  343. {
  344.     Handle        menuBar;
  345.  
  346.     gOldMenuHook = NIL;
  347.     gMenuList = NIL;
  348.     gTheMenu = -1;
  349.     gNormalHeight = GetMBarHeight();
  350.     (**gControl).contrlRect.bottom = (**gControl).contrlRect.top + gBaseline
  351.                         + gFontInfo.descent + gFontInfo.leading + kBottomMargin;
  352.  
  353.     GetMBarHeight() = 0;
  354.     menuBar = GetNewMBar((**gControl).contrlMin);
  355.     if (menuBar != NIL) {
  356.         gMenuList = (MenuBarHdl) menuBar;
  357.     } else {
  358.         menuBar = GetMenuBar();
  359.         ClearMenuBar();
  360.         gMenuList = (MenuBarHdl) GetMenuBar();
  361.         SetMenuBar(menuBar);
  362.         DisposeHandle(menuBar);
  363.     }
  364.     GetMBarHeight() = gNormalHeight;
  365. }
  366.  
  367.  
  368. //--------------------------------------------------------------------------------
  369.  
  370. void    DisposeMyControl()
  371. {
  372.     DisposeHandle((Handle) gMenuList);
  373. }
  374.  
  375.  
  376. //--------------------------------------------------------------------------------
  377.  
  378. void    DoClearMenuBar()
  379. {
  380.     SwapMenuBars();
  381.     ClearMenuBar();
  382.     SwapMenuBars();
  383. }
  384.  
  385.  
  386. //--------------------------------------------------------------------------------
  387.  
  388. void    DoDeleteMenu(short menuID)
  389. {
  390.     if (IndexToID(gTheMenu) == menuID)
  391.         gTheMenu = -1;
  392.  
  393.     SwapMenuBars();
  394.     DeleteMenu(menuID);
  395.     SwapMenuBars();
  396. }
  397.  
  398.  
  399. //--------------------------------------------------------------------------------
  400.  
  401. void    DoDrawMenuBar()
  402. {
  403.     Rect            frame;
  404.     short            loop;
  405.  
  406.     PenNormal();
  407.     frame = (**gControl).contrlRect;
  408.     FrameRect(&frame);
  409.  
  410.     gTheMenu = -1;
  411.     for (loop = GetMenuCount() - 1; loop >= 0; loop--) {
  412.         DrawMenuTitle(loop);
  413.     }
  414. }
  415.  
  416.  
  417. //--------------------------------------------------------------------------------
  418.  
  419. void    DoFlashMenuBar(short menuID)
  420. {
  421.     Rect        bounds;
  422.  
  423.     if (menuID != 0)
  424.         DoHiliteMenu(menuID);
  425.     else {
  426.         bounds = (**gControl).contrlRect;
  427.         InsetRect(&bounds, 1, 1);
  428.         InvertRect(&bounds);
  429.     }
  430. }
  431.  
  432.  
  433. //--------------------------------------------------------------------------------
  434.  
  435. MenuBarHdl    DoGetMenuBar()
  436. {
  437.     return gMenuList;
  438. }
  439.  
  440.  
  441. //--------------------------------------------------------------------------------
  442.  
  443. MenuHandle    DoGetMHandle(short menuID)
  444. {
  445.     short    menuIndex;
  446.     
  447.     menuIndex = IDToIndex(menuID);
  448.     if (menuIndex >= 0)
  449.         return GetNthMenu(menuIndex);
  450.     else
  451.         return NIL;
  452. }
  453.  
  454.  
  455. //--------------------------------------------------------------------------------
  456.  
  457. void    DoHiliteMenu(short menuID)
  458. {
  459.     short        menuIndex;
  460.     Rect        invertRect;
  461.     
  462.     menuIndex = IDToIndex(menuID);
  463.     if (menuIndex != gTheMenu) {
  464.         if (menuIndex >= 0) {
  465.             invertRect = GetInvertRect(menuIndex);
  466.             InvertRect(&invertRect);
  467.         }
  468.         gTheMenu = menuIndex;
  469.     }
  470. }
  471.  
  472.  
  473. //--------------------------------------------------------------------------------
  474.  
  475. void    DoInsertMenu(MenuHandle menu, short before)
  476. {
  477.     SwapMenuBars();
  478.     InsertMenu(menu, before);
  479.     SwapMenuBars();
  480. }
  481.  
  482.  
  483. //--------------------------------------------------------------------------------
  484.  
  485. long    DoMenuKey(char theKey)
  486. {
  487.     char            upperKey[2];
  488.     short            loop;
  489.     MenuHandle        menu;
  490.     short            mItems;
  491.     short            menuItem;
  492.     short            key;
  493.  
  494.     upperKey[0] = 1;
  495.     upperKey[1] = theKey;
  496.     UprString((StringPtr) &upperKey, true);
  497.  
  498.     for (loop = GetMenuCount() - 1; loop >= 0; loop--) {
  499.         menu = GetNthMenu(loop);
  500.         mItems = CountMItems(menu);
  501.         for (menuItem = 1; menuItem <= mItems; menuItem++) {
  502.             if (menuItem > 31 || (((**menu).enableFlags & (1 << menuItem)) != 0)) {
  503.                 GetItemCmd(menu, menuItem, &key);
  504.                 if (key == upperKey[1]) {
  505.                     return ((long) (**menu).menuID << 16) + menuItem;
  506.                 }
  507.             }
  508.         }
  509.     }
  510.  
  511.     return 0;
  512. }
  513.  
  514.  
  515. //--------------------------------------------------------------------------------
  516.  
  517. long    DoMenuSelect(Point startPt)
  518. {
  519. #pragma unused (startPt)
  520.  
  521.     Point            currentLocation;
  522.     short            oldMenuIndex;
  523.     short            newMenuIndex;
  524.     Rect            invertRect;
  525.     Point            where;
  526.     MenuHandle        menu;
  527.     long            menuAndItem;
  528.     short            oldMenuID;
  529.     Handle            myMDEF;
  530.  
  531.     menuAndItem = 0;
  532.     while (Button()) {
  533.         GetMouse(¤tLocation);
  534.         oldMenuIndex = gTheMenu;
  535.         newMenuIndex = FindHitMenu(currentLocation);
  536.         if (oldMenuIndex != newMenuIndex) {
  537.             gTheMenu = newMenuIndex;
  538.             DrawMenuTitle(oldMenuIndex);
  539.             if (newMenuIndex >= 0) {
  540.                 DrawMenuTitle(newMenuIndex);
  541.     
  542.                 invertRect = GetInvertRect(newMenuIndex);
  543.                 where.v = invertRect.bottom + 1;
  544.                 where.h = invertRect.left + 1;
  545.                 LocalToGlobal(&where);
  546.     
  547.                 gOldMenuHook = MenuHook;
  548.                 MenuHook = (ProcPtr) MyMenuHook;
  549.     
  550.                 menu = GetNthMenu(newMenuIndex);
  551.     
  552.                 oldMenuID = (**menu).menuID;
  553.                 (**menu).menuID = GetFreeHMenuID();
  554.     
  555.                 myMDEF = GetResource('MDEF', kStayPutMDEF);
  556.                 if (myMDEF != NIL) {
  557.                     (**(StdHeaderHdl) myMDEF).refCon = (long) (**menu).menuProc;
  558.                     (**menu).menuProc = myMDEF;
  559.                 }
  560.     
  561.                 InsertMenu(menu, hierMenu);
  562.                 menuAndItem = PopUpMenuSelect(menu, where.v, where.h, 1);
  563.                 DeleteMenu((**menu).menuID);
  564.     
  565.                 (**menu).menuID = oldMenuID;
  566.     
  567.                 if (myMDEF != NIL) {
  568.                     (**menu).menuProc = (Handle) (**(StdHeaderHdl) myMDEF).refCon;
  569.                     (**(StdHeaderHdl) myMDEF).refCon = (long) NIL;
  570.                 }
  571.     
  572.                 MenuHook = gOldMenuHook;
  573.     
  574.                 if (HiWord(menuAndItem) != 0)
  575.                     menuAndItem = ((long) oldMenuID << 16) + (short) menuAndItem;
  576.     
  577.                 (**gControl).contrlValue = HiWord(menuAndItem);
  578.                 (**gControl).contrlMax = LoWord(menuAndItem);
  579.             }
  580.         }
  581.     }
  582.  
  583.     if (gTheMenu != -1) {
  584.         oldMenuIndex = gTheMenu;
  585.         gTheMenu = -1;
  586.         DrawMenuTitle(oldMenuIndex);
  587.     }
  588.  
  589.     return menuAndItem;
  590. }
  591.  
  592.  
  593. //--------------------------------------------------------------------------------
  594.  
  595. void    DoSetMenuBar(MenuBarHdl menuBar)
  596. {
  597.     DisposeHandle((Handle) gMenuList);
  598.     gMenuList = menuBar;
  599.     DoDrawMenuBar();
  600. }
  601.  
  602.  
  603. //--------------------------------------------------------------------------------
  604.  
  605. void    DrawMenuTitle(short menuIndex)
  606. {
  607.     Rect            invertRect;
  608.     Point            titleLocation;
  609.     MenuHandle        menu;
  610.  
  611.     if ((menuIndex >= 0) && (menuIndex < GetMenuCount())) {
  612.  
  613.         invertRect = GetInvertRect(menuIndex);
  614.         EraseRect(&invertRect);
  615.  
  616.         menu = GetNthMenu(menuIndex);
  617.         if ((((**menu).enableFlags & 1) == 0) || ((**gControl).contrlHilite == 255))
  618.             TextMode(grayishTextOr);
  619.         else
  620.             TextMode(srcOr);
  621.         
  622.         titleLocation = GetTitleLocation(menuIndex);
  623.         MoveTo(titleLocation.h, titleLocation.v);
  624.         HLock((Handle) menu);
  625.         DrawString((**menu).menuData);
  626.         HUnlock((Handle) menu);
  627.  
  628.         if (gTheMenu == menuIndex)
  629.             InvertRect(&invertRect);
  630.     }
  631. }
  632.  
  633.  
  634. //--------------------------------------------------------------------------------
  635.  
  636. short    FindHitMenu(Point location)
  637. {
  638.     short            loop;
  639.     Rect            hitRect;
  640.  
  641.     for (loop = GetMenuCount() - 1; loop >= 0; loop--) {
  642.         hitRect = GetHitRect(loop);
  643.         if (PtInRect(location, &hitRect)) {
  644.             break;
  645.         }
  646.     }
  647.  
  648.     return loop;        // returns -1 if no hit
  649. }
  650.  
  651.  
  652. //--------------------------------------------------------------------------------
  653.  
  654. short    GetFreeHMenuID(void)
  655. {
  656.     short    index;
  657.  
  658.     for (index = 235-20; index > 0; index--) {
  659.         if (GetMHandle(index) == NIL)
  660.             return index;
  661.     }
  662.     return -1;
  663. }
  664.  
  665.  
  666. //--------------------------------------------------------------------------------
  667.  
  668. Rect    GetHitRect(short menuIndex)
  669. {
  670.     Rect        bounds;
  671.     RectPtr        rectPtr;
  672.     MenuBarPtr    menuBarPtr;
  673.     
  674.     rectPtr = &(**gControl).contrlRect;
  675.     menuBarPtr = *gMenuList;
  676.  
  677.     bounds.top = rectPtr->top + 1;
  678.     bounds.bottom = rectPtr->bottom - 1;
  679.     bounds.left = rectPtr->left + menuBarPtr->menus[menuIndex].menuLeft;
  680.     menuIndex++;
  681.     bounds.right = rectPtr->left + ((menuIndex < GetMenuCount())
  682.                                         ? menuBarPtr->menus[menuIndex].menuLeft
  683.                                         : menuBarPtr->lastRight);
  684.     
  685.     return bounds;
  686. }
  687.  
  688.  
  689. //--------------------------------------------------------------------------------
  690.  
  691. Rect    GetInvertRect(short menuIndex)
  692. {
  693.     Rect        bounds;
  694.     
  695.     bounds = GetHitRect(menuIndex);
  696.     bounds.left--;
  697.     bounds.right += 4;
  698.     return bounds;
  699. }
  700.  
  701.  
  702. //--------------------------------------------------------------------------------
  703.  
  704. short    GetMenuCount()
  705. {
  706.     return (**gMenuList).lastMenu / (short) sizeof(MenuRec);
  707. }
  708.  
  709.  
  710. //--------------------------------------------------------------------------------
  711.  
  712. MenuHandle    GetNthMenu(short index)
  713. {
  714.     return (**gMenuList).menus[index].menu;
  715. }
  716.  
  717.  
  718. //--------------------------------------------------------------------------------
  719.  
  720. Point    GetTitleLocation(short menuIndex)
  721. {
  722.     Point    result;
  723.     
  724.     result.h = (**gMenuList).menus[menuIndex].menuLeft + kTextMargin;
  725.     result.v = (**gControl).contrlRect.top + gBaseline;
  726.     
  727.     return result;
  728. }
  729.  
  730.  
  731. //--------------------------------------------------------------------------------
  732.  
  733. short    IDToIndex(short menuID)
  734. {
  735.     short        loop;
  736.  
  737.     for (loop = GetMenuCount() - 1; loop >= 0; loop--) {
  738.         if ((**GetNthMenu(loop)).menuID == menuID)
  739.             break;
  740.     }
  741.     return loop;
  742. }
  743.  
  744.  
  745. //--------------------------------------------------------------------------------
  746.  
  747. short    IndexToID(short menuIndex)
  748. {
  749.     if ((menuIndex >= 0) && (menuIndex < GetMenuCount()))
  750.         return (**GetNthMenu(menuIndex)).menuID;
  751.     else
  752.         return 0;
  753. }
  754.  
  755.  
  756. //--------------------------------------------------------------------------------
  757.  
  758. void    MyMenuHook()
  759. {
  760.     typedef void (*MenuHookProc)(void);
  761.  
  762.     GrafPtr        oldPort;
  763.     Point        mouseLocation;
  764.     short        hitMenu;
  765.     Ptr            oldA5;
  766.  
  767. #ifdef THINK_C
  768.     SetUpA4();
  769. #else
  770.     oldA5 = UseGlobals();
  771. #endif
  772.  
  773.     if (gOldMenuHook != NIL)
  774.         ((MenuHookProc) gOldMenuHook)();
  775.  
  776.     GetPort(&oldPort);
  777.     SetPort((**gControl).contrlOwner);
  778.     GetMouse(&mouseLocation);
  779.     hitMenu = FindHitMenu(mouseLocation);
  780.     if ((hitMenu >= 0) && (hitMenu != gTheMenu)) {
  781.         PostEvent(mouseUp, 0);
  782.     }
  783.     SetPort(oldPort);
  784.  
  785. #ifdef THINK_C
  786.     RestoreA4();
  787. #else
  788.     DoneWithGlobals(oldA5);
  789. #endif
  790. }
  791.  
  792.  
  793. //--------------------------------------------------------------------------------
  794.  
  795. void    SwapMenuBars()
  796. {
  797.     MenuBarHdl        oldMenuBar;
  798.     
  799.     oldMenuBar = (MenuBarHdl) MenuList;
  800.     MenuList = (Handle) gMenuList;
  801.     gMenuList = oldMenuBar;
  802. }
  803.  
  804.  
  805.  
  806.  
  807.  
  808. #if 0
  809.  
  810. void            CalcMenuPositions(short index);
  811. long            CallMBDF(short message, short param1, long param2);
  812.  
  813. //--------------------------------------------------------------------------------
  814.  
  815. void    CalcMenuPositions(short index)
  816. {
  817.     SwapMenuBars();
  818.     CallMBDF(2, 0, (index+1) * 6);
  819.     SwapMenuBars();
  820. }
  821.  
  822.  
  823. //--------------------------------------------------------------------------------
  824.  
  825. long    CallMBDF(short message, short param1, long param2)
  826. {
  827.     typedef pascal long (*MBDFProc)(short selector, short message, short
  828. parameter1,
  829.                                         long parameter2);
  830.     Handle        mbdfHandle;
  831.     short        mbResID;
  832.     short        resID;
  833.     short        mbVariant;
  834.     char        oldState;
  835.     long        result;
  836.     
  837.     mbResID = (**gMenuList).mbResID;
  838.     resID = mbResID >> 3;
  839.     mbVariant = mbResID & 0x0007;
  840.     mbdfHandle = GetResource('MBDF', resID);
  841.     if (mbdfHandle != NIL) {
  842.         if (*mbdfHandle == NIL)  {
  843.             LoadResource(mbdfHandle);
  844.         }
  845.         if (*mbdfHandle != NIL) {
  846.         
  847.             oldState = HGetState(mbdfHandle);
  848.             HLock(mbdfHandle);
  849.             result = ((MBDFProc) *mbdfHandle)(mbVariant, message, param1, param2);
  850.             HSetState(mbdfHandle, oldState);
  851.             return result;
  852.         }
  853.     }
  854.  
  855.     SysError(dsMBarNFnd);
  856. }
  857. #endif
  858.  
  859.  
  860. --
  861. Keith Rollin
  862. Phantom Programmer
  863. Taligent, Inc.
  864.