Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
7.6 KiB

  1. //
  2. // Menu- and menuband- related utility functions
  3. //
  4. #include "local.h"
  5. #include "dochost.h"
  6. // this goes away when the split is done **and** dochost goes away
  7. /*----------------------------------------------------------
  8. Purpose: Replace the contents of hmenuDst with hmenuSrc. Note any
  9. submenus in hmenuDst will be deleted.
  10. Call Menu_RemoveAllSubMenus if you don't want this to
  11. happen.
  12. */
  13. void Menu_Replace(HMENU hmenuDst, HMENU hmenuSrc)
  14. {
  15. int cItems = GetMenuItemCount(hmenuDst);
  16. int i;
  17. for (i=0; i<cItems; i++)
  18. DeleteMenu(hmenuDst, 0, MF_BYPOSITION);
  19. cItems = GetMenuItemCount(hmenuSrc);
  20. for (i=0; i<cItems; i++)
  21. {
  22. MENUITEMINFO mii;
  23. TCHAR szText[MAX_PATH];
  24. mii.cbSize = SIZEOF(MENUITEMINFO);
  25. mii.dwTypeData = szText;
  26. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_STATE;
  27. mii.cch = ARRAYSIZE(szText);
  28. mii.fType = MFT_SEPARATOR;
  29. mii.hSubMenu = NULL;
  30. mii.dwItemData = 0;
  31. if (GetMenuItemInfo(hmenuSrc, i, TRUE, &mii))
  32. {
  33. HMENU hMenuOldSub = NULL;
  34. if (mii.hSubMenu != NULL)
  35. {
  36. hMenuOldSub = mii.hSubMenu;
  37. mii.hSubMenu = CreateMenu();
  38. Menu_Replace(mii.hSubMenu, hMenuOldSub);
  39. }
  40. InsertMenuItem(hmenuDst, i, TRUE, &mii);
  41. }
  42. }
  43. }
  44. #ifndef POSTPOSTSPLIT
  45. //----------------------------------------------------------------------
  46. //
  47. // CMenuList
  48. //
  49. //----------------------------------------------------------------------
  50. typedef struct
  51. {
  52. HMENU hmenu;
  53. BITBOOL bObject:1; // TRUE: menu belongs to object
  54. } MLITEM; // CMenuList item
  55. CMenuList::CMenuList(void)
  56. {
  57. ASSERT(NULL == _hdsa);
  58. }
  59. CMenuList::~CMenuList(void)
  60. {
  61. if (_hdsa)
  62. {
  63. DSA_Destroy(_hdsa);
  64. _hdsa = NULL;
  65. }
  66. }
  67. /*----------------------------------------------------------
  68. Purpose: Set the menu list (comparable to HOLEMENU) so we can
  69. dispatch commands to the frame or the object correctly.
  70. We do this since menu bands bypass OLE's FrameFilterWndProc.
  71. We build the menu list by comparing the given hmenuShared
  72. with hmenuFrame. Anything in hmenuShared that is not
  73. in hmenuFrame belongs to the object.
  74. */
  75. void CMenuList::Set(HMENU hmenuShared, HMENU hmenuFrame)
  76. {
  77. ASSERT(NULL == hmenuShared || IS_VALID_HANDLE(hmenuShared, MENU));
  78. ASSERT(NULL == hmenuFrame || IS_VALID_HANDLE(hmenuFrame, MENU));
  79. if (_hdsa)
  80. {
  81. ASSERT(IS_VALID_HANDLE(_hdsa, DSA));
  82. DSA_DeleteAllItems(_hdsa);
  83. }
  84. else
  85. _hdsa = DSA_Create(sizeof(MLITEM), 10);
  86. if (_hdsa && hmenuShared && hmenuFrame)
  87. {
  88. int i;
  89. int iFrame = 0;
  90. int cmenu = GetMenuItemCount(hmenuShared);
  91. int cmenuFrame = GetMenuItemCount(hmenuFrame);
  92. BOOL bMatched;
  93. int iSaveFrame;
  94. int iHaveFrame = -1;
  95. TCHAR sz[64];
  96. TCHAR szFrame[64];
  97. MENUITEMINFO miiFrame;
  98. MENUITEMINFO mii;
  99. MLITEM mlitem;
  100. miiFrame.cbSize = sizeof(miiFrame);
  101. mii.cbSize = sizeof(mii);
  102. for (i = 0; i < cmenu; i++)
  103. {
  104. mii.cch = SIZECHARS(sz);
  105. mii.fMask = MIIM_SUBMENU | MIIM_TYPE;
  106. mii.dwTypeData = sz;
  107. EVAL(GetMenuItemInfo(hmenuShared, i, TRUE, &mii));
  108. ASSERT(IS_VALID_HANDLE(mii.hSubMenu, MENU));
  109. mlitem.hmenu = mii.hSubMenu;
  110. iSaveFrame = iFrame;
  111. bMatched = FALSE;
  112. // DocObject might have dropped some of our menus, like edit and view
  113. // Need to be able to skip over dropped frame menus
  114. while (1)
  115. {
  116. if (iHaveFrame != iFrame)
  117. {
  118. iHaveFrame = iFrame;
  119. if (iFrame < cmenuFrame)
  120. {
  121. miiFrame.cch = SIZECHARS(szFrame);
  122. miiFrame.fMask = MIIM_SUBMENU | MIIM_TYPE;
  123. miiFrame.dwTypeData = szFrame;
  124. EVAL(GetMenuItemInfo(hmenuFrame, iFrame, TRUE, &miiFrame));
  125. }
  126. else
  127. {
  128. // Make it so it won't compare
  129. miiFrame.hSubMenu = NULL;
  130. *szFrame = 0;
  131. }
  132. }
  133. ASSERT(iFrame >= cmenuFrame || IS_VALID_HANDLE(miiFrame.hSubMenu, MENU));
  134. // The browser may have a menu that was not merged into
  135. // the shared menu because the object put one in with
  136. // the same name. Have we hit this case? Check by comparing
  137. // sz and szFrame
  138. if (mii.hSubMenu == miiFrame.hSubMenu || 0 == StrCmp(sz, szFrame))
  139. {
  140. bMatched = TRUE;
  141. break;
  142. }
  143. else
  144. {
  145. if (iFrame >= cmenuFrame)
  146. {
  147. break;
  148. }
  149. iFrame++;
  150. }
  151. }
  152. // Is this one of our menus?
  153. mlitem.bObject = (mii.hSubMenu == miiFrame.hSubMenu) ? FALSE:TRUE;
  154. if (bMatched)
  155. {
  156. iFrame++;
  157. }
  158. else
  159. {
  160. iFrame = iSaveFrame;
  161. }
  162. DSA_SetItem(_hdsa, i, &mlitem);
  163. }
  164. }
  165. }
  166. /*----------------------------------------------------------
  167. Purpose: Adds the given hmenu to the list.
  168. */
  169. void CMenuList::AddMenu(HMENU hmenu)
  170. {
  171. ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
  172. if (_hdsa && hmenu)
  173. {
  174. MLITEM mlitem;
  175. mlitem.hmenu = hmenu;
  176. mlitem.bObject = TRUE;
  177. DSA_AppendItem(_hdsa, &mlitem);
  178. }
  179. }
  180. /*----------------------------------------------------------
  181. Purpose: Removes the given hmenu from the list.
  182. */
  183. void CMenuList::RemoveMenu(HMENU hmenu)
  184. {
  185. ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
  186. if (_hdsa && hmenu)
  187. {
  188. int i = DSA_GetItemCount(_hdsa) - 1;
  189. for (; i >= 0; i--)
  190. {
  191. MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
  192. ASSERT(pmlitem);
  193. if (hmenu == pmlitem->hmenu)
  194. {
  195. DSA_DeleteItem(_hdsa, i);
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. /*----------------------------------------------------------
  202. Purpose: Returns TRUE if the given hmenu belongs to the object.
  203. */
  204. BOOL CMenuList::IsObjectMenu(HMENU hmenu)
  205. {
  206. BOOL bRet = FALSE;
  207. ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
  208. if (_hdsa && hmenu)
  209. {
  210. int i;
  211. for (i = 0; i < DSA_GetItemCount(_hdsa); i++)
  212. {
  213. MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
  214. ASSERT(pmlitem);
  215. if (hmenu == pmlitem->hmenu)
  216. {
  217. bRet = pmlitem->bObject;
  218. break;
  219. }
  220. }
  221. }
  222. return bRet;
  223. }
  224. #ifdef DEBUG
  225. void CMenuList::Dump(LPCTSTR pszMsg)
  226. {
  227. if (IsFlagSet(g_dwDumpFlags, DF_DEBUGMENU))
  228. {
  229. TraceMsg(TF_ALWAYS, "CMenuList: Dumping menus for %#08x %s", (LPVOID)this, pszMsg);
  230. if (_hdsa)
  231. {
  232. int i;
  233. for (i = 0; i < DSA_GetItemCount(_hdsa); i++)
  234. {
  235. MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
  236. ASSERT(pmlitem);
  237. TraceMsg(TF_ALWAYS, " [%d] = %x", i, pmlitem->hmenu);
  238. }
  239. }
  240. }
  241. }
  242. #endif
  243. #endif