2 * see www.geocities.com/SiliconValley/4942/filemenu.html
8 #include "wine/obj_base.h"
9 #include "wine/obj_enumidlist.h"
10 #include "wine/obj_shellfolder.h"
11 #include "undocshell.h"
14 #include "shell32_main.h"
18 #include "debugtools.h"
20 static BOOL FileMenu_AppendItemA(HMENU hMenu, LPCSTR lpText, UINT uID, int icon,
21 HMENU hMenuPopup, int nItemHeight);
28 COLORREF crBorderColor;
32 /* insert using pidl */
37 LPFNFMCALLBACK lpfnCallback;
47 static BOOL bAbortInit;
49 #define CCH_MAXITEMTEXT 256
51 DEFAULT_DEBUG_CHANNEL(shell);
53 LPFMINFO FM_GetMenuInfo(HMENU hmenu)
57 MenuInfo.cbSize = sizeof(MENUINFO);
58 MenuInfo.fMask = MIM_MENUDATA;
60 if (! GetMenuInfo(hmenu, &MenuInfo))
63 menudata = (LPFMINFO)MenuInfo.dwMenuData;
65 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
67 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
74 /*************************************************************************
75 * FM_SetMenuParameter [internal]
78 static LPFMINFO FM_SetMenuParameter(
84 LPFNFMCALLBACK lpfnCallback)
90 menudata = FM_GetMenuInfo(hmenu);
93 { SHFree(menudata->pidl);
97 menudata->pidl = ILClone(pidl);
98 menudata->uFlags = uFlags;
99 menudata->uEnumFlags = uEnumFlags;
100 menudata->lpfnCallback = lpfnCallback;
105 /*************************************************************************
106 * FM_InitMenuPopup [internal]
109 static int FM_InitMenuPopup(HMENU hmenu, LPITEMIDLIST pAlternatePidl)
110 { IShellFolder *lpsf, *lpsf2;
111 ULONG ulItemAttr = SFGAO_FOLDER;
112 UINT uID, uFlags, uEnumFlags;
113 LPFNFMCALLBACK lpfnCallback;
115 char sTemp[MAX_PATH];
116 int NumberOfItems = 0, iIcon;
120 TRACE("0x%04x %p\n", hmenu, pAlternatePidl);
122 MenuInfo.cbSize = sizeof(MENUINFO);
123 MenuInfo.fMask = MIM_MENUDATA;
125 if (! GetMenuInfo(hmenu, &MenuInfo))
128 menudata = (LPFMINFO)MenuInfo.dwMenuData;
130 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
132 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
136 if (menudata->bInitialized)
139 pidl = ((pAlternatePidl) ? pAlternatePidl : menudata->pidl);
144 uFlags = menudata->uFlags;
145 uEnumFlags = menudata->uEnumFlags;
146 lpfnCallback = menudata->lpfnCallback;
147 menudata->bInitialized = FALSE;
149 SetMenuInfo(hmenu, &MenuInfo);
151 if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
153 if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
155 IEnumIDList *lpe = NULL;
157 if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
160 LPITEMIDLIST pidlTemp = NULL;
163 while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)))
165 if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
167 ILGetDisplayName( pidlTemp, sTemp);
168 if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon)))
169 iIcon = FM_BLANK_ICON;
170 if ( SFGAO_FOLDER & ulItemAttr)
174 HMENU hMenuPopup = CreatePopupMenu();
176 lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
178 lpFmMi->pidl = ILCombine(pidl, pidlTemp);
179 lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
181 MenuInfo.cbSize = sizeof(MENUINFO);
182 MenuInfo.fMask = MIM_MENUDATA;
183 MenuInfo.dwMenuData = (DWORD) lpFmMi;
184 SetMenuInfo (hMenuPopup, &MenuInfo);
186 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
190 ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
191 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
197 TRACE("enter callback\n");
198 lpfnCallback ( pidl, pidlTemp);
199 TRACE("leave callback\n");
204 IEnumIDList_Release (lpe);
206 IShellFolder_Release(lpsf2);
208 IShellFolder_Release(lpsf);
211 if ( GetMenuItemCount (hmenu) == 0 )
212 { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
216 menudata->bInitialized = TRUE;
217 SetMenuInfo(hmenu, &MenuInfo);
219 return NumberOfItems;
221 /*************************************************************************
222 * FileMenu_Create [SHELL32.114]
225 * for non-root menus values are
226 * (ffffffff,00000000,00000000,00000000,00000000)
228 HMENU WINAPI FileMenu_Create (
229 COLORREF crBorderColor,
238 HMENU hMenu = CreatePopupMenu();
240 TRACE("0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x hMenu=0x%08x\n",
241 crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu);
243 menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
244 menudata->crBorderColor = crBorderColor;
245 menudata->nBorderWidth = nBorderWidth;
246 menudata->hBorderBmp = hBorderBmp;
248 MenuInfo.cbSize = sizeof(MENUINFO);
249 MenuInfo.fMask = MIM_MENUDATA;
250 MenuInfo.dwMenuData = (DWORD) menudata;
251 SetMenuInfo (hMenu, &MenuInfo);
256 /*************************************************************************
257 * FileMenu_Destroy [SHELL32.118]
262 void WINAPI FileMenu_Destroy (HMENU hmenu)
266 TRACE("0x%08x\n", hmenu);
268 FileMenu_DeleteAllItems (hmenu);
270 menudata = FM_GetMenuInfo(hmenu);
273 { SHFree( menudata->pidl);
275 HeapFree(GetProcessHeap(), 0, menudata);
280 /*************************************************************************
281 * FileMenu_AppendItem [SHELL32.115]
284 static BOOL FileMenu_AppendItemA(
292 LPSTR lpszText = (LPSTR)lpText;
299 TRACE("0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
300 hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
301 uID, icon, hMenuPopup, nItemHeight);
303 ZeroMemory (&mii, sizeof(MENUITEMINFOA));
305 mii.cbSize = sizeof(MENUITEMINFOA);
307 if (lpText != FM_SEPARATOR)
308 { int len = strlen (lpText);
309 myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
310 strcpy (myItem->szItemText, lpText);
311 myItem->cchItemText = len;
312 myItem->iIconIndex = icon;
313 myItem->hMenu = hMenu;
314 mii.fMask = MIIM_DATA;
315 mii.dwItemData = (DWORD) myItem;
320 mii.fMask |= MIIM_TYPE | MIIM_SUBMENU;
321 mii.fType = MFT_OWNERDRAW;
322 mii.hSubMenu = hMenuPopup;
324 else if (lpText == FM_SEPARATOR )
325 { mii.fMask |= MIIM_ID | MIIM_TYPE;
326 mii.fType = MFT_SEPARATOR;
330 mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE;
331 mii.fState = MFS_ENABLED | MFS_DEFAULT;
332 mii.fType = MFT_OWNERDRAW;
336 InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
338 /* set bFixedItems to true */
339 MenuInfo.cbSize = sizeof(MENUINFO);
340 MenuInfo.fMask = MIM_MENUDATA;
342 if (! GetMenuInfo(hMenu, &MenuInfo))
345 menudata = (LPFMINFO)MenuInfo.dwMenuData;
346 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
348 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
352 menudata->bFixedItems = TRUE;
353 SetMenuInfo(hMenu, &MenuInfo);
359 /**********************************************************************/
361 BOOL WINAPI FileMenu_AppendItemAW(
372 if (SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR))
373 lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
375 ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : lpText, uID, icon, hMenuPopup, nItemHeight);
378 HeapFree( GetProcessHeap(), 0, lpszText );
382 /*************************************************************************
383 * FileMenu_InsertUsingPidl [SHELL32.110]
386 * uEnumFlags any SHCONTF flag
388 int WINAPI FileMenu_InsertUsingPidl (
394 LPFNFMCALLBACK lpfnCallback)
396 TRACE("0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
397 hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
403 FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
405 return FM_InitMenuPopup(hmenu, NULL);
408 /*************************************************************************
409 * FileMenu_ReplaceUsingPidl [SHELL32.113]
411 * FIXME: the static items are deleted but wont be refreshed
413 int WINAPI FileMenu_ReplaceUsingPidl(
418 LPFNFMCALLBACK lpfnCallback)
420 TRACE("0x%08x 0x%08x %p 0x%08x %p\n",
421 hmenu, uID, pidl, uEnumFlags, lpfnCallback);
423 FileMenu_DeleteAllItems (hmenu);
425 FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback);
427 return FM_InitMenuPopup(hmenu, NULL);
430 /*************************************************************************
431 * FileMenu_Invalidate [SHELL32.111]
433 void WINAPI FileMenu_Invalidate (HMENU hMenu)
435 FIXME("0x%08x\n",hMenu);
438 /*************************************************************************
439 * FileMenu_FindSubMenuByPidl [SHELL32.106]
441 HMENU WINAPI FileMenu_FindSubMenuByPidl(
445 FIXME("0x%08x %p\n",hMenu, pidl);
449 /*************************************************************************
450 * FileMenu_AppendFilesForPidl [SHELL32.124]
452 int WINAPI FileMenu_AppendFilesForPidl(
459 menudata = FM_GetMenuInfo(hmenu);
461 menudata->bInitialized = FALSE;
463 FM_InitMenuPopup(hmenu, pidl);
466 FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
468 TRACE("0x%08x %p 0x%08x\n",hmenu, pidl,bAddSeperator);
472 /*************************************************************************
473 * FileMenu_AddFilesForPidl [SHELL32.125]
476 * uEnumFlags any SHCONTF flag
478 int WINAPI FileMenu_AddFilesForPidl (
485 LPFNFMCALLBACK lpfnCallback)
487 TRACE("0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
488 hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
490 return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
495 /*************************************************************************
496 * FileMenu_TrackPopupMenuEx [SHELL32.116]
498 BOOL WINAPI FileMenu_TrackPopupMenuEx (
506 TRACE("0x%08x 0x%08x 0x%x 0x%x 0x%08x %p\n",
507 hMenu, uFlags, x, y, hWnd, lptpm);
508 return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
511 /*************************************************************************
512 * FileMenu_GetLastSelectedItemPidls [SHELL32.107]
514 BOOL WINAPI FileMenu_GetLastSelectedItemPidls(
516 LPCITEMIDLIST *ppidlFolder,
517 LPCITEMIDLIST *ppidlItem)
519 FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
523 #define FM_ICON_SIZE 16
527 #define FM_LEFTBORDER 2
528 #define FM_RIGHTBORDER 8
529 /*************************************************************************
530 * FileMenu_MeasureItem [SHELL32.112]
532 LRESULT WINAPI FileMenu_MeasureItem(
534 LPMEASUREITEMSTRUCT lpmis)
536 LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData);
537 HDC hdc = GetDC(hWnd);
541 TRACE("0x%08x %p %s\n", hWnd, lpmis, pMyItem->szItemText);
543 GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
545 lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
546 lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
548 /* add the menubitmap */
549 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
550 if (menuinfo->nBorderWidth)
551 lpmis->itemWidth += menuinfo->nBorderWidth;
553 TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight);
554 ReleaseDC (hWnd, hdc);
557 /*************************************************************************
558 * FileMenu_DrawItem [SHELL32.105]
560 LRESULT WINAPI FileMenu_DrawItem(
562 LPDRAWITEMSTRUCT lpdis)
564 LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData);
565 COLORREF clrPrevText, clrPrevBkgnd;
567 HIMAGELIST hImageList;
568 RECT TextRect, BorderRect;
571 TRACE("0x%08x %p %s\n", hWnd, lpdis, pMyItem->szItemText);
573 if (lpdis->itemState & ODS_SELECTED)
575 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
576 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
580 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT));
581 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU));
584 CopyRect(&TextRect, &(lpdis->rcItem));
586 /* add the menubitmap */
587 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
588 if (menuinfo->nBorderWidth)
589 TextRect.left += menuinfo->nBorderWidth;
591 BorderRect.right = menuinfo->nBorderWidth;
592 /* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor));
594 TextRect.left += FM_LEFTBORDER;
595 xi = TextRect.left + FM_SPACE1;
596 yi = TextRect.top + FM_Y_SPACE/2;
597 TextRect.bottom -= FM_Y_SPACE/2;
599 xt = xi + FM_ICON_SIZE + FM_SPACE2;
602 ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
604 Shell_GetImageList(0, &hImageList);
605 ImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
607 TRACE("-- 0x%04x 0x%04x 0x%04x 0x%04x\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom);
609 SetTextColor(lpdis->hDC, clrPrevText);
610 SetBkColor(lpdis->hDC, clrPrevBkgnd);
615 /*************************************************************************
616 * FileMenu_InitMenuPopup [SHELL32.109]
619 * The filemenu is a ownerdrawn menu. Call this function responding to
623 BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu)
625 FM_InitMenuPopup(hmenu, NULL);
629 /*************************************************************************
630 * FileMenu_HandleMenuChar [SHELL32.108]
632 LRESULT WINAPI FileMenu_HandleMenuChar(
636 FIXME("0x%08x 0x%08x\n",hMenu,wParam);
640 /*************************************************************************
641 * FileMenu_DeleteAllItems [SHELL32.104]
646 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
653 TRACE("0x%08x\n", hmenu);
655 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
656 mii.cbSize = sizeof(MENUITEMINFOA);
657 mii.fMask = MIIM_SUBMENU|MIIM_DATA;
659 for (i = 0; i < GetMenuItemCount( hmenu ); i++)
660 { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
663 SHFree((LPFMINFO)mii.dwItemData);
666 FileMenu_Destroy(mii.hSubMenu);
669 while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){};
671 menudata = FM_GetMenuInfo(hmenu);
673 menudata->bInitialized = FALSE;
678 /*************************************************************************
679 * FileMenu_DeleteItemByCmd [SHELL32.117]
682 BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
686 TRACE("0x%08x 0x%08x\n", hMenu, uID);
688 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
689 mii.cbSize = sizeof(MENUITEMINFOA);
690 mii.fMask = MIIM_SUBMENU;
692 GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
695 /* FIXME: Do what? */
698 DeleteMenu(hMenu, MF_BYCOMMAND, uID);
702 /*************************************************************************
703 * FileMenu_DeleteItemByIndex [SHELL32.140]
705 BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
709 TRACE("0x%08x 0x%08x\n", hMenu, uPos);
711 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
712 mii.cbSize = sizeof(MENUITEMINFOA);
713 mii.fMask = MIIM_SUBMENU;
715 GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
718 /* FIXME: Do what? */
721 DeleteMenu(hMenu, MF_BYPOSITION, uPos);
725 /*************************************************************************
726 * FileMenu_DeleteItemByFirstID [SHELL32.141]
728 BOOL WINAPI FileMenu_DeleteItemByFirstID(
732 TRACE("0x%08x 0x%08x\n", hMenu, uID);
736 /*************************************************************************
737 * FileMenu_DeleteSeparator [SHELL32.142]
739 BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu)
741 TRACE("0x%08x\n", hMenu);
745 /*************************************************************************
746 * FileMenu_EnableItemByCmd [SHELL32.143]
748 BOOL WINAPI FileMenu_EnableItemByCmd(
753 TRACE("0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
757 /*************************************************************************
758 * FileMenu_GetItemExtent [SHELL32.144]
761 * if the menu is too big, entries are getting cut away!!
763 DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos)
766 FIXME("0x%08x 0x%08x\n", hMenu, uPos);
768 if (GetMenuItemRect(0, hMenu, uPos, &rect))
769 { FIXME("0x%04x 0x%04x 0x%04x 0x%04x\n",
770 rect.right, rect.left, rect.top, rect.bottom);
771 return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
773 return 0x00100010; /*fixme*/
776 /*************************************************************************
777 * FileMenu_AbortInitMenu [SHELL32.120]
780 void WINAPI FileMenu_AbortInitMenu (void)
785 /*************************************************************************
786 * SHFind_InitMenuPopup [SHELL32.149]
790 * hMenu [in] handle of menu previously created
791 * hWndParent [in] parent window
792 * w [in] no pointer (0x209 over here) perhaps menu IDs ???
793 * x [in] no pointer (0x226 over here)
796 * LPXXXXX pointer to struct containing a func addr at offset 8
797 * or NULL at failure.
799 LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x)
800 { FIXME("hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
801 hMenu,hWndParent,w,x);
802 return NULL; /* this is supposed to be a pointer */
805 /*************************************************************************
806 * Shell_MergeMenus [SHELL32.67]
809 BOOL _SHIsMenuSeparator(HMENU hm, int i)
813 mii.cbSize = sizeof(MENUITEMINFOA);
814 mii.fMask = MIIM_TYPE;
815 mii.cch = 0; /* WARNING: We MUST initialize it to 0*/
816 if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
821 if (mii.fType & MFT_SEPARATOR)
829 /**********************************************************************/
831 HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
834 BOOL bAlreadySeparated;
835 MENUITEMINFOA miiSrc;
837 UINT uTemp, uIDMax = uIDAdjust;
839 TRACE("hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x 0x%04lx\n",
840 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
842 if (!hmDst || !hmSrc)
846 nItem = GetMenuItemCount(hmDst);
848 if (uInsert >= (UINT)nItem) /* insert position inside menu? */
850 uInsert = (UINT)nItem; /* append on the end */
851 bAlreadySeparated = TRUE;
855 bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
858 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
860 /* Add a separator between the menus */
861 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
862 bAlreadySeparated = TRUE;
866 /* Go through the menu items and clone them*/
867 for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
869 miiSrc.cbSize = sizeof(MENUITEMINFOA);
870 miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
872 /* We need to reset this every time through the loop in case menus DON'T have IDs*/
873 miiSrc.fType = MFT_STRING;
874 miiSrc.dwTypeData = szName;
875 miiSrc.dwItemData = 0;
876 miiSrc.cch = sizeof(szName);
878 if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
883 /* TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
885 if (miiSrc.fType & MFT_SEPARATOR)
887 /* This is a separator; don't put two of them in a row */
888 if (bAlreadySeparated)
891 bAlreadySeparated = TRUE;
893 else if (miiSrc.hSubMenu)
895 if (uFlags & MM_SUBMENUSHAVEIDS)
897 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
899 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
902 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
903 uIDMax = miiSrc.wID + 1;
907 miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */
909 hmSubMenu = miiSrc.hSubMenu;
911 miiSrc.hSubMenu = CreatePopupMenu();
913 if (!miiSrc.hSubMenu) return(uIDMax);
915 uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS);
920 bAlreadySeparated = FALSE;
922 else /* normal menu item */
924 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
926 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
929 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
930 uIDMax = miiSrc.wID + 1;
932 bAlreadySeparated = FALSE;
935 /* TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
937 if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
943 /* Ensure the correct number of separators at the beginning of the
944 inserted menu items*/
947 if (bAlreadySeparated)
949 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
954 if (_SHIsMenuSeparator(hmDst, uInsert-1))
956 if (bAlreadySeparated)
958 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
963 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
965 /* Add a separator between the menus*/
966 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);