Converted to the new debugging interface (done with the help of the
[wine] / dlls / shell32 / shlmenu.c
1 /*
2  *
3  */
4 #include <string.h>
5
6 #include "wine/obj_base.h"
7 #include "wine/obj_enumidlist.h"
8 #include "wine/obj_shellfolder.h"
9
10 #include "heap.h"
11 #include "debug.h"
12 #include "winversion.h"
13 #include "shell32_main.h"
14
15 #include "pidl.h"
16
17 DEFAULT_DEBUG_CHANNEL(shell)
18
19 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hMenu);
20
21 /*************************************************************************
22  * FileMenu_Create                              [SHELL32.114]
23  *
24  */
25 HMENU WINAPI FileMenu_Create (
26         COLORREF crBorderColor,
27         int nBorderWidth,
28         HBITMAP hBorderBmp,
29         int nSelHeight,
30         UINT uFlags)
31 {
32         HMENU ret = CreatePopupMenu();
33
34         FIXME(shell,"0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x  ret=0x%08x\n",
35         crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, ret);
36
37         return ret;
38 }
39
40 /*************************************************************************
41  * FileMenu_Destroy                             [SHELL32.118]
42  *
43  * NOTES
44  *  exported by name
45  */
46 void WINAPI FileMenu_Destroy (HMENU hMenu)
47 {
48         TRACE(shell,"0x%08x\n", hMenu);
49         FileMenu_DeleteAllItems (hMenu);
50         DestroyMenu (hMenu);
51 }
52
53 /*************************************************************************
54  * FileMenu_AppendItemAW                        [SHELL32.115]
55  *
56  */
57 BOOL WINAPI FileMenu_AppendItemAW(
58         HMENU hMenu,
59         LPCVOID lpText,
60         UINT uID,
61         int icon,
62         HMENU hMenuPopup,
63         int nItemHeight)
64 {
65         LPSTR lpszText = (LPSTR)lpText;
66         MENUITEMINFOA   mii;
67         ZeroMemory (&mii, sizeof(MENUITEMINFOA));
68         
69         if (VERSION_OsIsUnicode() && (lpszText!=FM_SEPARATOR))
70           lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
71
72         FIXME(shell,"0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
73         hMenu, (lpszText!=FM_SEPARATOR) ? lpszText: NULL,
74         uID, icon, hMenuPopup, nItemHeight);
75
76         mii.cbSize = sizeof(mii);
77         
78         if ( hMenuPopup )
79         { /* sub menu */
80           mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;;
81           mii.hSubMenu = hMenuPopup;
82           mii.fType = MFT_STRING;
83           mii.dwTypeData = lpszText;
84         }
85         else if (lpText == FM_SEPARATOR )
86         { mii.fMask = MIIM_ID | MIIM_TYPE;
87           mii.fType = MFT_SEPARATOR;
88         }
89         else
90         { /* normal item */
91           mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
92           mii.dwTypeData = lpszText;
93           mii.fState = MFS_ENABLED | MFS_DEFAULT;
94           mii.fType = MFT_STRING;
95         }
96         mii.wID = uID;
97
98         InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
99
100         if (VERSION_OsIsUnicode())
101           HeapFree( GetProcessHeap(), 0, lpszText );
102         
103         return TRUE;
104
105 }
106  
107 /*************************************************************************
108  * FileMenu_InsertUsingPidl                     [SHELL32.110]
109  *
110  * NOTES
111  *      uEnumFlags      any SHCONTF flag
112  */
113 int WINAPI FileMenu_InsertUsingPidl (
114         HMENU hMenu,
115         UINT uID,
116         LPCITEMIDLIST pidl,
117         UINT uFlags,
118         UINT uEnumFlags,
119         LPFNFMCALLBACK lpfnCallback)
120 {       
121         IShellFolder    *lpsf, *lpsf2;
122         IEnumIDList     *lpe=0;
123         ULONG           ulFetched;
124         LPITEMIDLIST    pidlTemp=0;
125         ULONG           ulItemAttr;
126         char            sTemp[MAX_PATH];
127         int             NumberOfItems = 0;
128
129         FIXME(shell,"0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
130         hMenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
131         pdump (pidl);
132
133         if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
134         { if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
135           { if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
136             { while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))
137               { if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
138                 { ILGetDisplayName( pidlTemp, sTemp);
139                   if ( SFGAO_FOLDER & ulItemAttr)
140                   { FileMenu_AppendItemAW (hMenu, sTemp, uID, FM_BLANK_ICON, CreatePopupMenu(), FM_DEFAULT_HEIGHT);
141                   }
142                   else
143                   { FileMenu_AppendItemAW (hMenu, sTemp, uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
144                   }
145                 }
146                 TRACE(shell,"enter callback\n");
147                 lpfnCallback ( pidl, pidlTemp);
148                 TRACE(shell,"leave callback\n");
149                 NumberOfItems++;
150               }
151               IEnumIDList_Release (lpe);
152             }
153             IShellFolder_Release(lpsf2);
154           }
155           IShellFolder_Release(lpsf);
156         }
157
158         return NumberOfItems;
159 }
160
161 /*************************************************************************
162  * FileMenu_ReplaceUsingPidl                    [SHELL32.113]
163  *
164  */
165 int WINAPI FileMenu_ReplaceUsingPidl(
166         HMENU   hMenu,
167         UINT    uID,
168         LPCITEMIDLIST   pidl,
169         UINT    uEnumFlags,
170         LPFNFMCALLBACK lpfnCallback)
171 {
172         FIXME(shell,"0x%08x 0x%08x %p 0x%08x %p\n",
173         hMenu, uID, pidl, uEnumFlags, lpfnCallback);
174         return 0;
175 }
176
177 /*************************************************************************
178  * FileMenu_Invalidate                  [SHELL32.111]
179  */
180 void WINAPI FileMenu_Invalidate (HMENU hMenu)
181 {
182         FIXME(shell,"0x%08x\n",hMenu);  
183 }
184
185 /*************************************************************************
186  * FileMenu_FindSubMenuByPidl                   [SHELL32.106]
187  */
188 HMENU WINAPI FileMenu_FindSubMenuByPidl(
189         HMENU   hMenu,
190         LPCITEMIDLIST   pidl)
191 {
192         FIXME(shell,"0x%08x %p\n",hMenu, pidl); 
193         return 0;
194 }
195
196 /*************************************************************************
197  * FileMenu_AppendFilesForPidl                  [SHELL32.124]
198  */
199 HMENU WINAPI FileMenu_AppendFilesForPidl(
200         HMENU   hMenu,
201         LPCITEMIDLIST   pidl,
202         BOOL    bAddSeperator)
203 {
204         FIXME(shell,"0x%08x %p 0x%08x\n",hMenu, pidl,bAddSeperator);    
205         return 0;
206 }
207 /*************************************************************************
208  * FileMenu_AddFilesForPidl                     [SHELL32.125]
209  *
210  * NOTES
211  *      uEnumFlags      any SHCONTF flag
212  */
213 int WINAPI FileMenu_AddFilesForPidl (
214         HMENU   hMenu,
215         UINT    uReserved,
216         UINT    uID,
217         LPCITEMIDLIST   pidl,
218         UINT    uFlags,
219         UINT    uEnumFlags,
220         LPFNFMCALLBACK  lpfnCallback)
221 {
222         FIXME(shell,"0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
223         hMenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
224         pdump (pidl);
225         return 0;
226
227 }
228
229
230 /*************************************************************************
231  * FileMenu_TrackPopupMenuEx                    [SHELL32.116]
232  */
233 HRESULT WINAPI FileMenu_TrackPopupMenuEx (
234         HMENU hMenu,
235         UINT uFlags,
236         int x,
237         int y,
238         HWND hWnd,
239         LPTPMPARAMS lptpm)
240 {
241         FIXME(shell,"0x%08x 0x%08x 0x%x 0x%x 0x%08x %p stub\n",
242         hMenu, uFlags, x, y, hWnd, lptpm);
243         return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
244 }
245
246 /*************************************************************************
247  * FileMenu_GetLastSelectedItemPidls            [SHELL32.107]
248  */
249 BOOL WINAPI FileMenu_GetLastSelectedItemPidls(
250         UINT    uReserved,
251         LPCITEMIDLIST   *ppidlFolder,
252         LPCITEMIDLIST   *ppidlItem)
253 {
254         FIXME(shell,"0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
255         return 0;
256 }
257
258 /*************************************************************************
259  * FileMenu_MeasureItem                         [SHELL32.112]
260  */
261 LRESULT WINAPI FileMenu_MeasureItem(
262         HWND    hWnd,
263         LPMEASUREITEMSTRUCT     lpmis)
264 {
265         FIXME(shell,"0x%08x %p\n", hWnd, lpmis);
266         return 0;
267 }
268
269 /*************************************************************************
270  * FileMenu_DrawItem                            [SHELL32.105]
271  */
272 LRESULT WINAPI FileMenu_DrawItem(
273         HWND                    hWnd,
274         LPDRAWITEMSTRUCT        lpdis)
275 {
276         FIXME(shell,"0x%08x %p\n", hWnd, lpdis);
277         return 0;
278 }
279
280 /*************************************************************************
281  * FileMenu_InitMenuPopup                       [SHELL32.109]
282  *
283  * NOTES
284  *  The filemenu is a ownerdrawn menu. Call this function responding to 
285  *  WM_INITPOPUPMENU
286  *
287  */
288 HRESULT WINAPI FileMenu_InitMenuPopup (DWORD hmenu)
289 {       FIXME(shell,"hmenu=0x%lx stub\n",hmenu);
290         return 0;
291 }
292
293 /*************************************************************************
294  * FileMenu_HandleMenuChar                      [SHELL32.108]
295  */
296 LRESULT WINAPI FileMenu_HandleMenuChar(
297         HMENU   hMenu,
298         WPARAM  wParam)
299 {
300         FIXME(shell,"0x%08x 0x%08x\n",hMenu,wParam);
301         return 0;
302 }
303
304 /*************************************************************************
305  * FileMenu_DeleteAllItems                      [SHELL32.104]
306  *
307  * NOTES
308  *  exported by name
309  */
310 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hMenu)
311 {
312         FIXME(shell,"0x%08x stub\n", hMenu);
313         DestroyMenu (hMenu);
314         return TRUE;
315 }
316
317 /*************************************************************************
318  * FileMenu_DeleteItemByCmd                     [SHELL32.]
319  *
320  */
321 BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
322 {
323         TRACE(shell,"0x%08x 0x%08x\n", hMenu, uID);
324
325         DeleteMenu(hMenu, MF_BYCOMMAND, uID);
326         return TRUE;
327 }
328
329 /*************************************************************************
330  * FileMenu_DeleteItemByIndex                   [SHELL32.140]
331  */
332 BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
333 {
334         TRACE(shell,"0x%08x 0x%08x\n", hMenu, uPos);
335
336         DeleteMenu(hMenu, MF_BYPOSITION, uPos);
337         return TRUE;
338 }
339
340 /*************************************************************************
341  * FileMenu_DeleteItemByFirstID                 [SHELL32.141]
342  */
343 BOOL WINAPI FileMenu_DeleteItemByFirstID(
344         HMENU   hMenu,
345         UINT    uID)
346 {
347         TRACE(shell,"0x%08x 0x%08x\n", hMenu, uID);
348         return 0;
349 }
350
351 /*************************************************************************
352  * FileMenu_DeleteSeparator                     [SHELL32.142]
353  */
354 BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu)
355 {
356         TRACE(shell,"0x%08x\n", hMenu);
357         return 0;
358 }
359
360 /*************************************************************************
361  * FileMenu_EnableItemByCmd                     [SHELL32.143]
362  */
363 BOOL WINAPI FileMenu_EnableItemByCmd(
364         HMENU   hMenu,
365         UINT    uID,
366         BOOL    bEnable)
367 {
368         TRACE(shell,"0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
369         return 0;
370 }
371
372 /*************************************************************************
373  * FileMenu_GetItemExtent                       [SHELL32.144]
374  *
375  */
376 DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos)
377 {       RECT rect;
378         
379         FIXME (shell,"0x%08x 0x%08x\n", hMenu, uPos);
380
381         if (GetMenuItemRect(0, hMenu, uPos, &rect))
382         { FIXME (shell,"0x%04x 0x%04x 0x%04x 0x%04x\n",
383           rect.right, rect.left, rect.top, rect.bottom);
384           return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
385         }
386         return 0x00200020; /*fixme*/
387 }
388
389 /*************************************************************************
390  * FileMenu_AbortInitMenu                       [SHELL32.120]
391  *
392  */
393 void WINAPI FileMenu_AbortInitMenu (void)
394 {       TRACE(shell,"\n");
395 }
396
397
398
399
400
401
402
403
404
405
406
407 /*************************************************************************
408  * SHFind_InitMenuPopup                         [SHELL32.149]
409  *
410  *
411  * PARAMETERS
412  *  hMenu               [in] handel of menu previously created
413  *  hWndParent  [in] parent window
414  *  w                   [in] no pointer
415  *  x                   [in] no pointer
416  */
417 HRESULT WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x)
418 {       FIXME(shell,"hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
419                 hMenu,hWndParent,w,x);
420         return TRUE;
421 }
422
423 /*************************************************************************
424  * Shell_MergeMenus                             [SHELL32.67]
425  *
426  */
427 BOOL _SHIsMenuSeparator(HMENU hm, int i)
428 {
429         MENUITEMINFOA mii;
430
431         mii.cbSize = sizeof(MENUITEMINFOA);
432         mii.fMask = MIIM_TYPE;
433         mii.cch = 0;    /* WARNING: We MUST initialize it to 0*/
434         if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
435         { return(FALSE);
436         }
437
438         if (mii.fType & MFT_SEPARATOR)
439         { return(TRUE);
440         }
441
442         return(FALSE);
443 }
444 #define MM_ADDSEPARATOR         0x00000001L
445 #define MM_SUBMENUSHAVEIDS      0x00000002L
446 HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
447 {       int             nItem;
448         HMENU           hmSubMenu;
449         BOOL            bAlreadySeparated;
450         MENUITEMINFOA miiSrc;
451         char            szName[256];
452         UINT            uTemp, uIDMax = uIDAdjust;
453
454         FIXME(shell,"hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x  0x%04lx stub\n",
455                  hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
456
457         if (!hmDst || !hmSrc)
458         { return uIDMax;
459         }
460
461         nItem = GetMenuItemCount(hmDst);
462         if (uInsert >= (UINT)nItem)
463         { uInsert = (UINT)nItem;
464           bAlreadySeparated = TRUE;
465         }
466         else
467         { bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
468         }
469         if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
470         { /* Add a separator between the menus */
471           InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
472           bAlreadySeparated = TRUE;
473         }
474
475
476         /* Go through the menu items and clone them*/
477         for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
478         { miiSrc.cbSize = sizeof(MENUITEMINFOA);
479           miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
480           /* We need to reset this every time through the loop in case
481           menus DON'T have IDs*/
482           miiSrc.fType = MFT_STRING;
483           miiSrc.dwTypeData = szName;
484           miiSrc.dwItemData = 0;
485           miiSrc.cch = sizeof(szName);
486
487           if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
488           { continue;
489           }
490           if (miiSrc.fType & MFT_SEPARATOR)
491           { /* This is a separator; don't put two of them in a row*/
492             if (bAlreadySeparated)
493             { continue;
494             }
495             bAlreadySeparated = TRUE;
496           }
497           else if (miiSrc.hSubMenu)
498           { if (uFlags & MM_SUBMENUSHAVEIDS)
499             { /* Adjust the ID and check it*/
500               miiSrc.wID += uIDAdjust;
501               if (miiSrc.wID > uIDAdjustMax)
502               { continue;
503               }
504               if (uIDMax <= miiSrc.wID)
505               { uIDMax = miiSrc.wID + 1;
506               }
507             }
508             else
509             { /* Don't set IDs for submenus that didn't have them already */
510               miiSrc.fMask &= ~MIIM_ID;
511             }
512             hmSubMenu = miiSrc.hSubMenu;
513             miiSrc.hSubMenu = CreatePopupMenu();
514             if (!miiSrc.hSubMenu)
515             { return(uIDMax);
516             }
517             uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags&MM_SUBMENUSHAVEIDS);
518             if (uIDMax <= uTemp)
519             { uIDMax = uTemp;
520             }
521             bAlreadySeparated = FALSE;
522           }
523           else
524           { /* Adjust the ID and check it*/
525             miiSrc.wID += uIDAdjust;
526             if (miiSrc.wID > uIDAdjustMax)
527             { continue;
528             }
529             if (uIDMax <= miiSrc.wID)
530             { uIDMax = miiSrc.wID + 1;
531             }
532             bAlreadySeparated = FALSE;
533           }
534           if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
535           { return(uIDMax);
536           }
537         }
538
539         /* Ensure the correct number of separators at the beginning of the
540         inserted menu items*/
541         if (uInsert == 0)
542         { if (bAlreadySeparated)
543           { DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
544           }
545         }
546         else
547         { if (_SHIsMenuSeparator(hmDst, uInsert-1))
548           { if (bAlreadySeparated)
549             { DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
550             }
551           }
552           else
553           { if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
554             { /* Add a separator between the menus*/
555               InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
556             }
557           }
558         }
559         return(uIDMax);
560 }