- sorted API by groups
[wine] / dlls / shell32 / shlview.c
1 /*
2  *      ShellView
3  *
4  *      Copyright 1998  <juergen.schmied@metronet.de>
5  *
6  *  FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
7  *  Release() ??? 
8  *
9  */
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "winerror.h"
15
16 #include "pidl.h"
17 #include "shlguid.h"
18 #include "shlobj.h"
19 #include "servprov.h"
20 #include "wine/obj_base.h"
21 #include "if_macros.h"
22 #include "shell32_main.h"
23 #include "shresdef.h"
24 #include "spy.h"
25
26 #include "debug.h"
27
28 /***********************************************************************
29 *   IShellView implementation
30 */
31 static HRESULT WINAPI IShellView_QueryInterface(LPSHELLVIEW,REFIID, LPVOID *);
32 static ULONG WINAPI IShellView_AddRef(LPSHELLVIEW) ;
33 static ULONG WINAPI IShellView_Release(LPSHELLVIEW);
34     /* IOleWindow methods */
35 static HRESULT WINAPI IShellView_GetWindow(LPSHELLVIEW,HWND * lphwnd);
36 static HRESULT WINAPI IShellView_ContextSensitiveHelp(LPSHELLVIEW,BOOL fEnterMode);
37     /* IShellView methods */
38 static HRESULT WINAPI IShellView_TranslateAccelerator(LPSHELLVIEW,LPMSG lpmsg);
39 static HRESULT WINAPI IShellView_EnableModeless(LPSHELLVIEW,BOOL fEnable);
40 static HRESULT WINAPI IShellView_UIActivate(LPSHELLVIEW,UINT uState);
41 static HRESULT WINAPI IShellView_Refresh(LPSHELLVIEW);
42 static HRESULT WINAPI IShellView_CreateViewWindow(LPSHELLVIEW, IShellView *lpPrevView,LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,RECT * prcView, HWND  *phWnd);
43 static HRESULT WINAPI IShellView_DestroyViewWindow(LPSHELLVIEW);
44 static HRESULT WINAPI IShellView_GetCurrentInfo(LPSHELLVIEW, LPFOLDERSETTINGS lpfs);
45 static HRESULT WINAPI IShellView_AddPropertySheetPages(LPSHELLVIEW, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam);
46 static HRESULT WINAPI IShellView_SaveViewState(LPSHELLVIEW);
47 static HRESULT WINAPI IShellView_SelectItem(LPSHELLVIEW, LPCITEMIDLIST pidlItem, UINT uFlags);
48 static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW, UINT uItem, REFIID riid,LPVOID *ppv);
49
50 static BOOL ShellView_CanDoIDockingWindow(LPSHELLVIEW);
51
52 static struct IShellView_VTable svvt = 
53 { IShellView_QueryInterface,
54   IShellView_AddRef,
55   IShellView_Release,
56   IShellView_GetWindow,
57   IShellView_ContextSensitiveHelp,
58   IShellView_TranslateAccelerator,
59   IShellView_EnableModeless,
60   IShellView_UIActivate,
61   IShellView_Refresh,
62   IShellView_CreateViewWindow,
63   IShellView_DestroyViewWindow,
64   IShellView_GetCurrentInfo,
65   IShellView_AddPropertySheetPages,
66   IShellView_SaveViewState,
67   IShellView_SelectItem,
68   IShellView_GetItemObject
69 };
70
71 /*menu items */
72 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
73 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
74 #define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
75
76 #define ID_LISTVIEW     2000
77
78 #define MENU_OFFSET  1
79 #define MENU_MAX     100
80
81 #define TOOLBAR_ID   (L"SHELLDLL_DefView")
82 /*windowsx.h */
83 #define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
84 #define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
85 #define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
86 /* winuser.h */
87 #define WM_SETTINGCHANGE                WM_WININICHANGE
88 extern void WINAPI _InsertMenuItem (HMENU hmenu, UINT indexMenu, BOOL fByPosition, 
89                         UINT wID, UINT fType, LPSTR dwTypeData, UINT fState);
90
91 typedef struct
92 {  int   idCommand;
93    int   iImage;
94    int   idButtonString;
95    int   idMenuString;
96    int   nStringOffset;
97    BYTE  bState;
98    BYTE  bStyle;
99 } MYTOOLINFO, *LPMYTOOLINFO;
100
101 extern  LPCVOID _Resource_Men_MENU_001_0_data;
102 extern  LPCVOID _Resource_Men_MENU_002_0_data;
103
104 MYTOOLINFO g_Tools[] = 
105 { {IDM_VIEW_FILES, 0, IDS_TB_VIEW_FILES, IDS_MI_VIEW_FILES, 0, TBSTATE_ENABLED, TBSTYLE_BUTTON},
106   {-1, 0, 0, 0, 0, 0, 0}   
107 };
108 BOOL g_bViewKeys;
109 BOOL g_bShowIDW;
110
111 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
112
113 /**************************************************************************
114 *  IShellView_Constructor
115 */
116 LPSHELLVIEW IShellView_Constructor( LPSHELLFOLDER pFolder, LPCITEMIDLIST pidl)
117 {       LPSHELLVIEW sv;
118         sv=(LPSHELLVIEW)HeapAlloc(GetProcessHeap(),0,sizeof(IShellView));
119         sv->ref=1;
120         sv->lpvtbl=&svvt;
121   
122         sv->mpidl       = ILClone(pidl);
123         sv->hMenu       = 0;
124         sv->pSFParent   = pFolder;
125         sv->uSelected = 0;
126         sv->aSelectedItems = NULL;
127
128         if(sv->pSFParent)
129           sv->pSFParent->lpvtbl->fnAddRef(sv->pSFParent);
130
131         TRACE(shell,"(%p)->(%p pidl=%p)\n",sv, pFolder, pidl);
132         shell32_ObjCount++;
133         return sv;
134 }
135 /**************************************************************************
136 *  helperfunctions for communication with ICommDlgBrowser
137 *
138 */
139 static BOOL IsInCommDlg(LPSHELLVIEW this)
140 {       return(this->pCommDlgBrowser != NULL);
141 }
142 static HRESULT IncludeObject(LPSHELLVIEW this, LPCITEMIDLIST pidl)
143 {       if ( IsInCommDlg(this) )
144         { TRACE(shell,"ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
145           return (this->pCommDlgBrowser->lpvtbl->fnIncludeObject(this->pCommDlgBrowser, this, pidl));
146         }
147         return S_OK;
148 }
149 static HRESULT OnDefaultCommand(LPSHELLVIEW this)
150 {       if (IsInCommDlg(this))
151         { TRACE(shell,"ICommDlgBrowser::OnDefaultCommand\n");
152           return (this->pCommDlgBrowser->lpvtbl->fnOnDefaultCommand(this->pCommDlgBrowser, this));
153         }
154         return S_FALSE;
155 }
156 static HRESULT OnStateChange(LPSHELLVIEW this, UINT uFlags)
157 {       if (IsInCommDlg(this))
158         { TRACE(shell,"ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
159           return (this->pCommDlgBrowser->lpvtbl->fnOnStateChange(this->pCommDlgBrowser, this, uFlags));
160         }
161         return S_FALSE;
162 }
163 static void SetStyle(LPSHELLVIEW this, DWORD dwAdd, DWORD dwRemove)
164 {       DWORD tmpstyle;
165
166         TRACE(shell,"(%p)\n", this);
167
168         tmpstyle = GetWindowLongA(this->hWndList, GWL_STYLE);
169         SetWindowLongA(this->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
170 }
171
172 static void CheckToolbar(LPSHELLVIEW this)
173 {       LRESULT result;
174
175         TRACE(shell,"\n");
176         
177         IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
178                 FCIDM_TB_SMALLICON, (this->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
179         IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
180                 FCIDM_TB_REPORTVIEW, (this->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
181         IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
182                 FCIDM_TB_SMALLICON, TRUE, &result);
183         IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
184                 FCIDM_TB_REPORTVIEW, TRUE, &result);
185         TRACE(shell,"--\n");
186 }
187
188 static void MergeToolBar(LPSHELLVIEW this)
189 {       LRESULT iStdBMOffset;
190         LRESULT iViewBMOffset;
191         TBADDBITMAP ab;
192         TBBUTTON tbActual[6];
193         int i;
194         enum
195         { IN_STD_BMP = 0x4000,
196           IN_VIEW_BMP = 0x8000,
197         } ;
198         static const TBBUTTON c_tbDefault[] =
199         { { STD_COPY | IN_STD_BMP, FCIDM_SHVIEW_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1},
200           { 0,  0,      TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 },
201           { VIEW_LARGEICONS | IN_VIEW_BMP, FCIDM_SHVIEW_BIGICON,        TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
202           { VIEW_SMALLICONS | IN_VIEW_BMP, FCIDM_SHVIEW_SMALLICON,      TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
203           { VIEW_LIST       | IN_VIEW_BMP, FCIDM_SHVIEW_LISTVIEW,       TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
204           { VIEW_DETAILS    | IN_VIEW_BMP, FCIDM_SHVIEW_REPORTVIEW,     TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
205         } ;
206
207         TRACE(shell,"\n");
208
209         ab.hInst = HINST_COMMCTRL;              /* hinstCommctrl */
210         ab.nID   = IDB_STD_SMALL_COLOR; /* std bitmaps */
211         IShellBrowser_SendControlMsg(this->pShellBrowser,FCW_TOOLBAR,
212                                  TB_ADDBITMAP, 8, (LPARAM)&ab, &iStdBMOffset);
213
214         TRACE(shell,"TB_ADDBITMAP returns %lx\n", iStdBMOffset);
215
216         ab.nID   = IDB_VIEW_SMALL_COLOR;        /* std view bitmaps */
217         IShellBrowser_SendControlMsg(this->pShellBrowser,FCW_TOOLBAR,
218                                  TB_ADDBITMAP, 8, (LPARAM)&ab, &iViewBMOffset);
219
220         TRACE(shell,"TB_ADDBITMAP returns %lx\n", iViewBMOffset);
221
222         for (i=0; i<6; ++i)
223         { tbActual[i] = c_tbDefault[i];
224           if (!(tbActual[i].fsStyle & TBSTYLE_SEP))
225           { if (tbActual[i].iBitmap & IN_VIEW_BMP)
226             { tbActual[i].iBitmap = (tbActual[i].iBitmap & ~IN_VIEW_BMP) + iViewBMOffset;
227             }
228             else if (tbActual[i].iBitmap & IN_STD_BMP)
229             { tbActual[i].iBitmap = (tbActual[i].iBitmap & ~IN_STD_BMP) + iStdBMOffset;
230             }
231           }
232         }
233
234         IShellBrowser_SetToolbarItems(this->pShellBrowser,tbActual, 6, FCT_MERGE);
235
236         CheckToolbar(this);
237         TRACE(shell,"--\n");
238
239 }
240
241 /**************************************************************************
242 * ShellView_CreateList()
243 *
244 */
245
246 BOOL ShellView_CreateList (LPSHELLVIEW this)
247 {       DWORD dwStyle;
248
249         TRACE(shell,"%p\n",this);
250
251         dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER |
252                   LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT;
253         switch (this->FolderSettings.ViewMode)
254         { case FVM_ICON:        dwStyle |= LVS_ICON;            break;
255           case FVM_DETAILS:     dwStyle |= LVS_REPORT;          break;
256           case FVM_SMALLICON:   dwStyle |= LVS_SMALLICON;       break;
257           case FVM_LIST:        dwStyle |= LVS_LIST;            break;
258           default:              dwStyle |= LVS_LIST;            break;
259         }
260         if (this->FolderSettings.fFlags && FWF_AUTOARRANGE)     dwStyle |= LVS_AUTOARRANGE;
261         /*if (this->FolderSettings.fFlags && FWF_DESKTOP); used from explorer*/
262         if (this->FolderSettings.fFlags && FWF_SINGLESEL)       dwStyle |= LVS_SINGLESEL;
263
264         this->hWndList=CreateWindowExA( WS_EX_CLIENTEDGE,
265                                           WC_LISTVIEWA,
266                                           NULL,
267                                           dwStyle,
268                                           0,0,0,0,
269                                           this->hWnd,
270                                           (HMENU)ID_LISTVIEW,
271                                           shell32_hInstance,
272                                           NULL);
273
274         if(!this->hWndList)
275           return FALSE;
276
277         /*  UpdateShellSettings(); */
278         return TRUE;
279 }
280 /**************************************************************************
281 * ShellView_InitList()
282 *
283 * NOTES
284 *  internal
285 */
286 int  nColumn1=120; /* width of column */
287 int  nColumn2=80;
288 int  nColumn3=170;
289 int  nColumn4=60;
290
291 BOOL ShellView_InitList(LPSHELLVIEW this)
292 {       LVCOLUMNA lvColumn;
293         CHAR        szString[50];
294
295         TRACE(shell,"%p\n",this);
296
297         ListView_DeleteAllItems(this->hWndList);
298
299         /*initialize the columns */
300         lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;      /*  |  LVCF_SUBITEM;*/
301         lvColumn.fmt = LVCFMT_LEFT;
302         lvColumn.pszText = szString;
303
304         lvColumn.cx = nColumn1;
305         strcpy(szString,"File");
306         /*LoadString32A(shell32_hInstance, IDS_COLUMN1, szString, sizeof(szString));*/
307         ListView_InsertColumnA(this->hWndList, 0, &lvColumn);
308
309         lvColumn.cx = nColumn2;
310         strcpy(szString,"Size");
311         ListView_InsertColumnA(this->hWndList, 1, &lvColumn);
312
313         lvColumn.cx = nColumn3;
314         strcpy(szString,"Type");
315         ListView_InsertColumnA(this->hWndList, 2, &lvColumn);
316
317         lvColumn.cx = nColumn4;
318         strcpy(szString,"Modified");
319         ListView_InsertColumnA(this->hWndList, 3, &lvColumn);
320
321         ListView_SetImageList(this->hWndList, ShellSmallIconList, LVSIL_SMALL);
322         ListView_SetImageList(this->hWndList, ShellBigIconList, LVSIL_NORMAL);
323   
324         return TRUE;
325 }
326 /**************************************************************************
327 * ShellView_CompareItems() 
328 *
329 * NOTES
330 *  internal, CALLBACK for DSA_Sort
331 */   
332 INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
333 {       int ret;
334         TRACE(shell,"pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
335
336         if(!lpData)
337           return 0;
338           
339         ret =  (int)((LPSHELLFOLDER)lpData)->lpvtbl->fnCompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2);  
340         TRACE(shell,"ret=%i\n",ret);
341         return ret;
342 }
343
344 /**************************************************************************
345 * ShellView_FillList()
346 *
347 * NOTES
348 *  internal
349 */   
350
351 static HRESULT ShellView_FillList(LPSHELLVIEW this)
352 {       LPENUMIDLIST    pEnumIDList;
353         LPITEMIDLIST    pidl;
354         DWORD           dwFetched;
355         UINT            i;
356         LVITEMA lvItem;
357         HRESULT         hRes;
358         HDPA            hdpa;
359
360         TRACE(shell,"%p\n",this);
361
362         /* get the itemlist from the shfolder*/  
363         hRes = this->pSFParent->lpvtbl->fnEnumObjects(this->pSFParent,this->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
364         if (hRes != S_OK)
365         { if (hRes==S_FALSE)
366             return(NOERROR);
367           return(hRes);
368         }
369
370         /* create a pointer array */    
371         hdpa = pDPA_Create(16);
372         if (!hdpa)
373         { return(E_OUTOFMEMORY);
374         }
375
376         /* copy the items into the array*/
377         while((S_OK == pEnumIDList->lpvtbl->fnNext(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
378         { if (pDPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
379           { SHFree(pidl);
380           } 
381         }
382
383         /*sort the array*/
384         pDPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)this->pSFParent);
385
386         /*turn the listview's redrawing off*/
387         SendMessageA(this->hWndList, WM_SETREDRAW, FALSE, 0); 
388
389         for (i=0; i < DPA_GetPtrCount(hdpa); ++i)       /* DPA_GetPtrCount is a macro*/
390         { pidl = (LPITEMIDLIST)DPA_GetPtr(hdpa, i);
391           if (IncludeObject(this, pidl) == S_OK)        /* in a commdlg this works as a filemask*/
392           { ZeroMemory(&lvItem, sizeof(lvItem));        /* create the listviewitem*/
393             lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;          /*set the mask*/
394             lvItem.iItem = ListView_GetItemCount(this->hWndList);       /*add the item to the end of the list*/
395             lvItem.lParam = (LPARAM) pidl;                              /*set the item's data*/
396             lvItem.pszText = LPSTR_TEXTCALLBACKA;                       /*get text on a callback basis*/
397             lvItem.iImage = I_IMAGECALLBACK;                            /*get the image on a callback basis*/
398             ListView_InsertItemA(this->hWndList, &lvItem);
399           }
400           else
401             SHFree(pidl);       /* the listview has the COPY*/
402         }
403
404         /*turn the listview's redrawing back on and force it to draw*/
405         SendMessageA(this->hWndList, WM_SETREDRAW, TRUE, 0);
406         InvalidateRect(this->hWndList, NULL, TRUE);
407         UpdateWindow(this->hWndList);
408
409         pEnumIDList->lpvtbl->fnRelease(pEnumIDList); /* destroy the list*/
410         pDPA_Destroy(hdpa);
411         
412         return S_OK;
413 }
414
415 /**************************************************************************
416 *  ShellView_OnCreate()
417 *
418 * NOTES
419 *  internal
420 */   
421 LRESULT ShellView_OnCreate(LPSHELLVIEW this)
422 { TRACE(shell,"%p\n",this);
423
424   if(ShellView_CreateList(this))
425   {  if(ShellView_InitList(this))
426      { ShellView_FillList(this);
427      }
428   }
429
430   return S_OK;
431 }
432 /**************************************************************************
433 *  ShellView_OnSize()
434 */   
435 LRESULT ShellView_OnSize(LPSHELLVIEW this, WORD wWidth, WORD wHeight)
436 {       TRACE(shell,"%p width=%u height=%u\n",this, wWidth,wHeight);
437
438         /*resize the ListView to fit our window*/
439         if(this->hWndList)
440         { MoveWindow(this->hWndList, 0, 0, wWidth, wHeight, TRUE);
441         }
442
443         return S_OK;
444 }
445 /**************************************************************************
446 * ShellView_BuildFileMenu()
447 */   
448 HMENU ShellView_BuildFileMenu(LPSHELLVIEW this)
449 {       CHAR    szText[MAX_PATH];
450         MENUITEMINFOA   mii;
451         int     nTools,i;
452         HMENU   hSubMenu;
453
454         TRACE(shell,"(%p) semi-stub\n",this);
455
456         hSubMenu = CreatePopupMenu();
457         if(hSubMenu)
458         { /*get the number of items in our global array*/
459           for(nTools = 0; g_Tools[nTools].idCommand != -1; nTools++){}
460
461           /*add the menu items*/
462           for(i = 0; i < nTools; i++)
463           { strcpy(szText, "dummy BuildFileMenu");
464       
465             ZeroMemory(&mii, sizeof(mii));
466             mii.cbSize = sizeof(mii);
467             mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
468
469             if(TBSTYLE_SEP != g_Tools[i].bStyle) /* no seperator*/
470             { mii.fType = MFT_STRING;
471               mii.fState = MFS_ENABLED;
472               mii.dwTypeData = szText;
473               mii.wID = g_Tools[i].idCommand;
474             }
475             else
476             { mii.fType = MFT_SEPARATOR;
477             }
478             /* tack this item onto the end of the menu */
479             InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
480           }
481         }
482         TRACE(shell,"-- return (menu=0x%x)\n",hSubMenu);
483         return hSubMenu;
484 }
485 /**************************************************************************
486 * ShellView_MergeFileMenu()
487 */   
488 void ShellView_MergeFileMenu(LPSHELLVIEW this, HMENU hSubMenu)
489 {       TRACE(shell,"(%p)->(submenu=0x%08x) stub\n",this,hSubMenu);
490
491         if(hSubMenu)
492         { /*insert this item at the beginning of the menu */
493           _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
494           _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
495
496         }
497         TRACE(shell,"--\n");    
498 }
499
500 /**************************************************************************
501 * ShellView_MergeViewMenu()
502 */   
503
504 void ShellView_MergeViewMenu(LPSHELLVIEW this, HMENU hSubMenu)
505 {       MENUITEMINFOA   mii;
506
507         TRACE(shell,"(%p)->(submenu=0x%08x)\n",this,hSubMenu);
508
509         if(hSubMenu)
510         { /*add a separator at the correct position in the menu*/
511           _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
512
513           ZeroMemory(&mii, sizeof(mii));
514           mii.cbSize = sizeof(mii);
515           mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;;
516           mii.fType = MFT_STRING;
517           mii.dwTypeData = "View";
518           mii.hSubMenu = LoadMenuIndirectA(&_Resource_Men_MENU_001_0_data);
519           InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
520         }
521 }
522 /**************************************************************************
523 * ShellView_UpdateMenu()
524 */
525 LRESULT ShellView_UpdateMenu(LPSHELLVIEW this, HMENU hMenu)
526 {       TRACE(shell,"(%p)->(menu=0x%08x)\n",this,hMenu);
527         CheckMenuItem(hMenu, IDM_VIEW_FILES, MF_BYCOMMAND | (g_bViewKeys ? MF_CHECKED: MF_UNCHECKED));
528
529         if(ShellView_CanDoIDockingWindow(this))
530         { EnableMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_ENABLED);
531           CheckMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | (g_bShowIDW ? MF_CHECKED: MF_UNCHECKED));
532         }
533         else
534         { EnableMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
535           CheckMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_UNCHECKED);
536         }
537         return S_OK;
538 }
539
540 /**************************************************************************
541 * ShellView_OnDeactivate()
542 *
543 * NOTES
544 *  internal
545 */   
546 void ShellView_OnDeactivate(LPSHELLVIEW this)
547 { TRACE(shell,"%p\n",this);
548   if(this->uState != SVUIA_DEACTIVATE)
549   { if(this->hMenu)
550     { IShellBrowser_SetMenuSB(this->pShellBrowser,0, 0, 0);
551       IShellBrowser_RemoveMenusSB(this->pShellBrowser,this->hMenu);
552       DestroyMenu(this->hMenu);
553       this->hMenu = 0;
554       }
555
556    this->uState = SVUIA_DEACTIVATE;
557    }
558 }
559
560 /**************************************************************************
561 * ShellView_OnActivate()
562 */   
563 LRESULT ShellView_OnActivate(LPSHELLVIEW this, UINT uState)
564 {       OLEMENUGROUPWIDTHS   omw = { {0, 0, 0, 0, 0, 0} };
565         MENUITEMINFOA         mii;
566         CHAR                szText[MAX_PATH];
567
568         TRACE(shell,"%p uState=%x\n",this,uState);    
569
570         /*don't do anything if the state isn't really changing */
571         if(this->uState == uState)
572         { return S_OK;
573         }
574
575         ShellView_OnDeactivate(this);
576
577         /*only do this if we are active */
578         if(uState != SVUIA_DEACTIVATE)
579         { /*merge the menus */
580           this->hMenu = CreateMenu();
581    
582           if(this->hMenu)
583           { IShellBrowser_InsertMenusSB(this->pShellBrowser, this->hMenu, &omw);
584             TRACE(shell,"-- after fnInsertMenusSB\n");    
585             /*build the top level menu get the menu item's text*/
586             strcpy(szText,"dummy 31");
587       
588             ZeroMemory(&mii, sizeof(mii));
589             mii.cbSize = sizeof(mii);
590             mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
591             mii.fType = MFT_STRING;
592             mii.fState = MFS_ENABLED;
593             mii.dwTypeData = szText;
594             mii.hSubMenu = ShellView_BuildFileMenu(this);
595
596             /*insert our menu into the menu bar*/
597             if(mii.hSubMenu)
598             { InsertMenuItemA(this->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
599             }
600
601             /*get the view menu so we can merge with it*/
602             ZeroMemory(&mii, sizeof(mii));
603             mii.cbSize = sizeof(mii);
604             mii.fMask = MIIM_SUBMENU;
605       
606             if(GetMenuItemInfoA(this->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
607             { ShellView_MergeViewMenu(this, mii.hSubMenu);
608             }
609
610             /*add the items that should only be added if we have the focus*/
611             if(SVUIA_ACTIVATE_FOCUS == uState)
612             { /*get the file menu so we can merge with it */
613               ZeroMemory(&mii, sizeof(mii));
614               mii.cbSize = sizeof(mii);
615               mii.fMask = MIIM_SUBMENU;
616       
617               if(GetMenuItemInfoA(this->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
618               { ShellView_MergeFileMenu(this, mii.hSubMenu);
619               }
620             }
621           TRACE(shell,"-- before fnSetMenuSB\n");      
622           IShellBrowser_SetMenuSB(this->pShellBrowser, this->hMenu, 0, this->hWnd);
623           }
624         }
625         this->uState = uState;
626         TRACE(shell,"--\n");    
627         return S_OK;
628 }
629
630 /**************************************************************************
631 *  ShellView_OnSetFocus()
632 *
633 * NOTES
634 *  internal
635 */
636 LRESULT ShellView_OnSetFocus(LPSHELLVIEW this)
637 {       TRACE(shell,"%p\n",this);
638         /* Tell the browser one of our windows has received the focus. This should always 
639         be done before merging menus (OnActivate merges the menus) if one of our 
640         windows has the focus.*/
641         IShellBrowser_OnViewWindowActive(this->pShellBrowser,this);
642         ShellView_OnActivate(this, SVUIA_ACTIVATE_FOCUS);
643
644         return 0;
645 }
646
647 /**************************************************************************
648 * ShellView_OnKillFocus()
649 */   
650 LRESULT ShellView_OnKillFocus(LPSHELLVIEW this)
651 {       TRACE(shell,"(%p) stub\n",this);
652         ShellView_OnActivate(this, SVUIA_ACTIVATE_NOFOCUS);
653         return 0;
654 }
655
656 /**************************************************************************
657 * ShellView_AddRemoveDockingWindow()
658 */   
659 BOOL ShellView_AddRemoveDockingWindow(LPSHELLVIEW this, BOOL bAdd)
660 {       BOOL    bReturn = FALSE;
661         HRESULT hr;
662         LPSERVICEPROVIDER       pSP;
663         LPDOCKINGWINDOWFRAME    pFrame;
664         
665         WARN(shell,"(%p)->(badd=0x%08x) semi-stub\n",this,bAdd);
666
667         /* get the browser's IServiceProvider */
668         hr = IShellBrowser_QueryInterface(this->pShellBrowser, (REFIID)&IID_IServiceProvider, (LPVOID*)&pSP);
669         if(SUCCEEDED(hr))
670         { /*get the IDockingWindowFrame pointer*/
671           hr = IServiceProvider_QueryService(pSP, (REFGUID)&SID_SShellBrowser, (REFIID)&IID_IDockingWindowFrame, (LPVOID*)&pFrame);
672           if(SUCCEEDED(hr))
673           { if(bAdd)
674             { hr = S_OK;
675               FIXME(shell,"no docking implemented\n");
676 #if 0
677               if(!this->pDockingWindow)
678               { /* create the toolbar object */
679                 this->pDockingWindow = DockingWindow_Constructor(this, this->hWnd);
680               }
681
682               if(this->pDockingWindow)
683               { /*add the toolbar object */
684                 hr = pFrame->lpvtbl->fnAddToolbar(pFrame, (IDockingWindow*)this->pDockingWindow, TOOLBAR_ID, 0);
685
686                 if(SUCCEEDED(hr))
687                 { bReturn = TRUE;
688                 }
689               }
690 #endif
691             }
692             else
693             { FIXME(shell,"no docking implemented\n");
694 #if 0
695               if(this->pDockingWindow)
696               { hr = pFrame->lpvtbl->fnRemoveToolbar(pFrame, (IDockingWindow*)this->pDockingWindow, DWFRF_NORMAL);
697
698                 if(SUCCEEDED(hr))
699                 { /* RemoveToolbar should release the toolbar object which will cause  */
700                   /*it to destroy itself. Our toolbar object is no longer valid at  */
701                   /*this point. */
702             
703                   this->pDockingWindow = NULL;
704                   bReturn = TRUE;
705                 }
706               }
707 #endif
708             }
709             pFrame->lpvtbl->fnRelease(pFrame);
710           }
711           IServiceProvider_Release(pSP);
712         }
713         return bReturn;
714 }
715
716 /**************************************************************************
717 * ShellView_CanDoIDockingWindow()
718 */   
719 BOOL ShellView_CanDoIDockingWindow(LPSHELLVIEW this)
720 {       BOOL bReturn = FALSE;
721         HRESULT hr;
722         LPSERVICEPROVIDER pSP;
723         LPDOCKINGWINDOWFRAME pFrame;
724         
725         FIXME(shell,"(%p) stub\n",this);
726         
727         /*get the browser's IServiceProvider*/
728         hr = IShellBrowser_QueryInterface(this->pShellBrowser, (REFIID)&IID_IServiceProvider, (LPVOID*)&pSP);
729         if(hr==S_OK)
730         { hr = IServiceProvider_QueryService(pSP, (REFGUID)&SID_SShellBrowser, (REFIID)&IID_IDockingWindowFrame, (LPVOID*)&pFrame);
731           if(SUCCEEDED(hr))
732           { bReturn = TRUE;
733             pFrame->lpvtbl->fnRelease(pFrame);
734           }
735           IServiceProvider_Release(pSP);
736         }
737         return bReturn;
738 }
739
740 /**************************************************************************
741 *  ShellView_UpdateShellSettings()
742 */
743 void ShellView_UpdateShellSettings(LPSHELLVIEW this)
744 {       FIXME(shell,"(%p) stub\n",this);
745         return ;
746 /*
747         SHELLFLAGSTATE       sfs;
748         HINSTANCE            hinstShell32;
749 */
750         /* Since SHGetSettings is not implemented in all versions of the shell, get the 
751         function address manually at run time. This allows the code to run on all 
752         platforms.*/
753 /*
754         ZeroMemory(&sfs, sizeof(sfs));
755 */
756         /* The default, in case any of the following steps fails, is classic Windows 95 
757         style.*/
758 /*
759         sfs.fWin95Classic = TRUE;
760
761         hinstShell32 = LoadLibrary("shell32.dll");
762         if(hinstShell32)
763         { PFNSHGETSETTINGSPROC pfnSHGetSettings;
764
765       pfnSHGetSettings = (PFNSHGETSETTINGSPROC)GetProcAddress(hinstShell32, "SHGetSettings");
766           if(pfnSHGetSettings)
767       { (*pfnSHGetSettings)(&sfs, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC);
768       }
769           FreeLibrary(hinstShell32);
770         }
771
772         DWORD dwExStyles = 0;
773
774         if(!sfs.fWin95Classic && !sfs.fDoubleClickInWebView)
775           dwExStyles |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT | LVS_EX_UNDERLINEHOT;
776
777         ListView_SetExtendedListViewStyle(this->hWndList, dwExStyles);
778 */
779 }
780
781 /**************************************************************************
782 *   ShellView_OnSettingChange()
783 */   
784 LRESULT ShellView_OnSettingChange(LPSHELLVIEW this, LPCSTR lpszSection)
785 {       TRACE(shell,"(%p) stub\n",this);
786 /*if(0 == lstrcmpi(lpszSection, "ShellState"))*/
787         { ShellView_UpdateShellSettings(this);
788           return 0;
789         }
790         return 0;
791 }
792 /**************************************************************************
793 * ShellView_OnCommand()
794 */   
795 LRESULT ShellView_OnCommand(LPSHELLVIEW this,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
796 {       TRACE(shell,"(%p)->(0x%08lx 0x%08lx 0x%08x) stub\n",this, dwCmdID, dwCmd, hwndCmd);
797         switch(dwCmdID)
798         { case IDM_VIEW_FILES:
799             g_bViewKeys = ! g_bViewKeys;
800             IShellView_Refresh(this);
801             break;
802
803           case IDM_VIEW_IDW:
804             g_bShowIDW = ! g_bShowIDW;
805             ShellView_AddRemoveDockingWindow(this, g_bShowIDW);
806             break;
807    
808           case IDM_MYFILEITEM:
809             MessageBeep(MB_OK);
810             break;
811
812           case FCIDM_SHVIEW_SMALLICON:
813             this->FolderSettings.ViewMode = FVM_SMALLICON;
814             SetStyle (this, LVS_SMALLICON, LVS_TYPEMASK);
815             break;
816
817           case FCIDM_SHVIEW_BIGICON:
818             this->FolderSettings.ViewMode = FVM_ICON;
819             SetStyle (this, LVS_ICON, LVS_TYPEMASK);
820             break;
821
822           case FCIDM_SHVIEW_LISTVIEW:
823             this->FolderSettings.ViewMode = FVM_LIST;
824             SetStyle (this, LVS_LIST, LVS_TYPEMASK);
825             break;
826
827           case FCIDM_SHVIEW_REPORTVIEW:
828             this->FolderSettings.ViewMode = FVM_DETAILS;
829             SetStyle (this, LVS_REPORT, LVS_TYPEMASK);
830             break;
831
832           default:
833             TRACE(shell,"-- COMMAND 0x%04lx unhandled\n", dwCmdID);
834         }
835         return 0;
836 }
837
838 /**************************************************************************
839 *   ShellView_GetSelections()
840 *
841 * RETURNS
842 *  number of selected items
843 */   
844 UINT ShellView_GetSelections(LPSHELLVIEW this)
845 {       LVITEMA lvItem;
846         UINT    i;
847
848
849         if (this->aSelectedItems)
850         { SHFree(this->aSelectedItems);
851         }
852
853         this->uSelected = ListView_GetSelectedCount(this->hWndList);
854         this->aSelectedItems = (LPITEMIDLIST*)SHAlloc(this->uSelected * sizeof(LPITEMIDLIST));
855
856         TRACE(shell,"selected=%i\n", this->uSelected);
857         
858         if(this->aSelectedItems)
859         { TRACE(shell,"-- Items selected =%u\n", this->uSelected);
860           ZeroMemory(&lvItem, sizeof(lvItem));
861           lvItem.mask = LVIF_STATE | LVIF_PARAM;
862           lvItem.stateMask = LVIS_SELECTED;
863           lvItem.iItem = 0;
864
865           i = 0;
866    
867           while(ListView_GetItemA(this->hWndList, &lvItem) && (i < this->uSelected))
868           { if(lvItem.state & LVIS_SELECTED)
869             { this->aSelectedItems[i] = (LPITEMIDLIST)lvItem.lParam;
870               i++;
871               TRACE(shell,"-- selected Item found\n");
872             }
873             lvItem.iItem++;
874           }
875         }
876         return this->uSelected;
877
878 }
879 /**************************************************************************
880 *   ShellView_DoContextMenu()
881 */   
882 void ShellView_DoContextMenu(LPSHELLVIEW this, WORD x, WORD y, BOOL fDefault)
883 {       UINT    uCommand;
884         DWORD   wFlags;
885         HMENU hMenu;
886         BOOL  fExplore = FALSE;
887         HWND  hwndTree = 0;
888         INT             nMenuIndex;
889         MENUITEMINFOA   mii;
890         LPCONTEXTMENU   pContextMenu = NULL;
891         CMINVOKECOMMANDINFO  cmi;
892         
893         TRACE(shell,"(%p)->(0x%08x 0x%08x 0x%08x) stub\n",this, x, y, fDefault);
894
895         /* look, what's selected and create a context menu object of it*/
896         if(ShellView_GetSelections(this))
897         { this->pSFParent->lpvtbl->fnGetUIObjectOf( this->pSFParent, this->hWndParent, this->uSelected,
898                                                     this->aSelectedItems, (REFIID)&IID_IContextMenu,
899                                                     NULL, (LPVOID *)&pContextMenu);
900    
901           if(pContextMenu)
902           { TRACE(shell,"-- pContextMenu\n");
903             hMenu = CreatePopupMenu();
904
905             if( hMenu )
906             { /* See if we are in Explore or Open mode. If the browser's tree
907                  is present, then we are in Explore mode.*/
908         
909               if(SUCCEEDED(IShellBrowser_GetControlWindow(this->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
910               { TRACE(shell,"-- explore mode\n");
911                 fExplore = TRUE;
912               }
913
914               wFlags = CMF_NORMAL | (this->uSelected != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
915
916               if (SUCCEEDED(pContextMenu->lpvtbl->fnQueryContextMenu( pContextMenu, hMenu, 0, MENU_OFFSET, MENU_MAX, wFlags )))
917               { if( fDefault )
918                 { TRACE(shell,"-- get menu default command\n");
919
920                   uCommand = nMenuIndex = 0;
921                   ZeroMemory(&mii, sizeof(mii));
922                   mii.cbSize = sizeof(mii);
923                   mii.fMask = MIIM_STATE | MIIM_ID;
924
925                   while(GetMenuItemInfoA(hMenu, nMenuIndex, TRUE, &mii))        /*find the default item in the menu*/
926                   { if(mii.fState & MFS_DEFAULT)
927                     { uCommand = mii.wID;
928                       break;
929                     }
930                     nMenuIndex++;
931                   }
932                 }
933                 else
934                 { TRACE(shell,"-- track popup\n");
935                   uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,this->hWnd,NULL);
936                 }               
937          
938                 if(uCommand > 0)
939                 { TRACE(shell,"-- uCommand=%u\n", uCommand);
940                   if (IsInCommDlg(this) && (((uCommand-MENU_OFFSET)==IDM_EXPLORE) || ((uCommand-MENU_OFFSET)==IDM_OPEN)))
941                   { TRACE(shell,"-- dlg: OnDefaultCommand\n");
942                     OnDefaultCommand(this);
943                   }
944                   else
945                   { TRACE(shell,"-- explore -- invoke command\n");
946                       ZeroMemory(&cmi, sizeof(cmi));
947                       cmi.cbSize = sizeof(cmi);
948                       cmi.hwnd = this->hWndParent;
949                       cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand - MENU_OFFSET);
950                       pContextMenu->lpvtbl->fnInvokeCommand(pContextMenu, &cmi);
951                   }
952                 }
953                 DestroyMenu(hMenu);
954               }
955             }
956             if (pContextMenu)
957               pContextMenu->lpvtbl->fnRelease(pContextMenu);
958           }
959         }
960         else    /* background context menu */
961         { hMenu = LoadMenuIndirectA(&_Resource_Men_MENU_002_0_data);
962           uCommand = TrackPopupMenu( GetSubMenu(hMenu,0),TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,this->hWnd,NULL);
963           ShellView_OnCommand(this, uCommand, 0,0);
964           DestroyMenu(hMenu);
965         }
966 }
967
968 /**************************************************************************
969 * ShellView_OnNotify()
970 */
971    
972 LRESULT ShellView_OnNotify(LPSHELLVIEW this, UINT CtlID, LPNMHDR lpnmh)
973 {       NM_LISTVIEW *lpnmlv = (NM_LISTVIEW*)lpnmh;
974         NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
975         LPITEMIDLIST pidl;
976         DWORD dwCursor; 
977         STRRET   str;  
978         UINT  uFlags;
979         IExtractIcon *pei;
980
981         TRACE(shell,"%p CtlID=%u lpnmh->code=%x\n",this,CtlID,lpnmh->code);
982
983         switch(lpnmh->code)
984         { case NM_SETFOCUS:
985             TRACE(shell,"-- NM_SETFOCUS %p\n",this);
986             ShellView_OnSetFocus(this);
987             break;
988
989           case NM_KILLFOCUS:
990             TRACE(shell,"-- NM_KILLFOCUS %p\n",this);
991             ShellView_OnDeactivate(this);
992             break;
993
994           case HDN_ENDTRACKA:
995             TRACE(shell,"-- HDN_ENDTRACK32A %p\n",this);
996             /*nColumn1 = ListView_GetColumnWidth(this->hWndList, 0);
997             nColumn2 = ListView_GetColumnWidth(this->hWndList, 1);*/
998             break;
999
1000           case LVN_DELETEITEM:
1001             TRACE(shell,"-- LVN_DELETEITEM %p\n",this);
1002             SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
1003             break;
1004
1005           case LVN_ITEMACTIVATE:
1006             TRACE(shell,"-- LVN_ITEMACTIVATE %p\n",this);
1007             OnStateChange(this, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1008             ShellView_DoContextMenu(this, 0, 0, TRUE);
1009             break;
1010
1011           case NM_RCLICK:
1012             TRACE(shell,"-- NM_RCLICK %p\n",this);
1013             dwCursor = GetMessagePos();
1014             ShellView_DoContextMenu(this, LOWORD(dwCursor), HIWORD(dwCursor), FALSE);
1015             break;
1016
1017           case LVN_GETDISPINFOA:
1018             TRACE(shell,"-- LVN_GETDISPINFO32A %p\n",this);
1019             pidl = (LPITEMIDLIST)lpdi->item.lParam;
1020
1021
1022             if(lpdi->item.iSubItem)               /*is the sub-item information being requested?*/
1023             { if(lpdi->item.mask & LVIF_TEXT)    /*is the text being requested?*/
1024               { if(_ILIsValue(pidl))    /*is this a value or a folder?*/
1025                 { switch (lpdi->item.iSubItem)
1026                   { case 1:     /* size */
1027                       _ILGetFileSize (pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
1028                       break;
1029                     case 2:     /* extension */
1030                       { char sTemp[64];
1031                         if (_ILGetExtension (pidl, sTemp, 64))
1032                         { if (!( HCR_MapTypeToValue(sTemp, sTemp, 64)
1033                                  && HCR_MapTypeToValue(sTemp, lpdi->item.pszText, lpdi->item.cchTextMax )))
1034                           { strncpy (lpdi->item.pszText, sTemp, lpdi->item.cchTextMax);
1035                             strncat (lpdi->item.pszText, "-file", lpdi->item.cchTextMax);
1036                           }
1037                         }
1038                         else    /* no extension found */
1039                         { lpdi->item.pszText[0]=0x00;
1040                         }    
1041                       }
1042                       break;
1043                     case 3:     /* date */
1044                       _ILGetFileDate (pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
1045                       break;
1046                   }
1047                 }
1048                 else  /*its a folder*/
1049                 { switch (lpdi->item.iSubItem)
1050                   { case 1:
1051                       strcpy(lpdi->item.pszText, "");
1052                       break;
1053                     case 2:
1054                       strncpy (lpdi->item.pszText, "Folder", lpdi->item.cchTextMax);
1055                       break;
1056                     case 3:  
1057                       _ILGetFileDate (pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
1058                       break;
1059                   }
1060                 }
1061                 TRACE(shell,"-- text=%s\n",lpdi->item.pszText);         
1062               }
1063             }
1064             else           /*the item text is being requested*/
1065             { if(lpdi->item.mask & LVIF_TEXT)      /*is the text being requested?*/
1066               { if(SUCCEEDED(this->pSFParent->lpvtbl->fnGetDisplayNameOf(this->pSFParent,pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &str)))
1067                 { if(STRRET_WSTR == str.uType)
1068                   { WideCharToLocal(lpdi->item.pszText, str.u.pOleStr, lpdi->item.cchTextMax);
1069                     SHFree(str.u.pOleStr);
1070                   }
1071                   else if(STRRET_CSTRA == str.uType)
1072                   { strncpy(lpdi->item.pszText, str.u.cStr, lpdi->item.cchTextMax);
1073                   }
1074                   else
1075                   { FIXME(shell,"type wrong\n");
1076                   }
1077                 }
1078                 TRACE(shell,"-- text=%s\n",lpdi->item.pszText);
1079               }
1080
1081               if(lpdi->item.mask & LVIF_IMAGE)          /*is the image being requested?*/
1082               { if(SUCCEEDED(this->pSFParent->lpvtbl->fnGetUIObjectOf(this->pSFParent,this->hWnd,1,
1083                                 (LPCITEMIDLIST*)&pidl, (REFIID)&IID_IExtractIcon, NULL, (LPVOID*)&pei)))
1084                 { pei->lpvtbl->fnGetIconLocation(pei, GIL_FORSHELL, NULL, 0, &lpdi->item.iImage, &uFlags);
1085                   pei->lpvtbl->fnRelease(pei);
1086                   TRACE(shell,"-- image=%x\n",lpdi->item.iImage);
1087                 }
1088               }
1089             }
1090             break;
1091
1092           case LVN_ITEMCHANGED:
1093             TRACE(shell,"-- LVN_ITEMCHANGED %p\n",this);
1094             ShellView_GetSelections(this);
1095             OnStateChange(this, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1096             break;
1097
1098           default:
1099             TRACE (shell,"-- %p WM_COMMAND %s unhandled\n", this, SPY_GetMsgName(lpnmh->code));
1100             break;;
1101         }
1102         return 0;
1103 }
1104
1105 /**************************************************************************
1106 *  ShellView_WndProc
1107 */
1108
1109 LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1110 { LPSHELLVIEW pThis = (LPSHELLVIEW)GetWindowLongA(hWnd, GWL_USERDATA);
1111   LPCREATESTRUCTA lpcs;
1112   DWORD dwCursor;
1113   
1114   TRACE(shell,"(hwnd=%x msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1115     
1116   switch (uMessage)
1117   { case WM_NCCREATE:
1118       { TRACE(shell,"-- WM_NCCREATE\n");
1119         lpcs = (LPCREATESTRUCTA)lParam;
1120         pThis = (LPSHELLVIEW)(lpcs->lpCreateParams);
1121         SetWindowLongA(hWnd, GWL_USERDATA, (LONG)pThis);
1122         pThis->hWnd = hWnd;        /*set the window handle*/
1123       }
1124       break;
1125    
1126    case WM_SIZE:
1127       TRACE(shell,"-- WM_SIZE\n");
1128       return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1129    
1130    case WM_SETFOCUS:
1131       TRACE(shell,"-- WM_SETFOCUS\n");   
1132       return ShellView_OnSetFocus(pThis);
1133  
1134    case WM_KILLFOCUS:
1135       TRACE(shell,"-- WM_KILLFOCUS\n");
1136           return ShellView_OnKillFocus(pThis);
1137
1138    case WM_CREATE:
1139       TRACE(shell,"-- WM_CREATE\n");
1140       return ShellView_OnCreate(pThis);
1141
1142    case WM_SHOWWINDOW:
1143       TRACE(shell,"-- WM_SHOWWINDOW\n");
1144       UpdateWindow(pThis->hWndList);
1145       break;
1146
1147    case WM_ACTIVATE:
1148       TRACE(shell,"-- WM_ACTIVATE\n");
1149       return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1150    
1151    case WM_COMMAND:
1152       TRACE(shell,"-- WM_COMMAND\n");
1153       return ShellView_OnCommand(pThis, GET_WM_COMMAND_ID(wParam, lParam), 
1154                                   GET_WM_COMMAND_CMD(wParam, lParam), 
1155                                   GET_WM_COMMAND_HWND(wParam, lParam));
1156    
1157    case WM_INITMENUPOPUP:
1158       TRACE(shell,"-- WM_INITMENUPOPUP\n");
1159       return ShellView_UpdateMenu(pThis, (HMENU)wParam);
1160    
1161    case WM_NOTIFY:
1162       TRACE(shell,"-- WM_NOTIFY\n");
1163       return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1164
1165    case WM_SETTINGCHANGE:
1166       TRACE(shell,"-- WM_SETTINGCHANGE\n");
1167       return ShellView_OnSettingChange(pThis,(LPCSTR)lParam);
1168
1169    case WM_PARENTNOTIFY:
1170       TRACE(shell,"-- WM_PARENTNOTIFY\n");
1171       if ( LOWORD(wParam) == WM_RBUTTONDOWN ) /* fixme: should not be handled here*/
1172       { dwCursor = GetMessagePos();
1173         ShellView_DoContextMenu(pThis, LOWORD(dwCursor), HIWORD(dwCursor), FALSE);
1174         return TRUE;
1175       }
1176       break;
1177
1178    default:
1179       TRACE(shell,"-- message %s unhandled\n", SPY_GetMsgName(uMessage));
1180       break;
1181   }
1182   return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1183 }
1184 /**************************************************************************
1185 *
1186 *
1187 *  The INTERFACE of the IShellView object
1188 *
1189 *
1190 ***************************************************************************
1191 *  IShellView_QueryInterface
1192 */
1193 static HRESULT WINAPI IShellView_QueryInterface(LPSHELLVIEW this,REFIID riid, LPVOID *ppvObj)
1194 { char    xriid[50];
1195   WINE_StringFromCLSID((LPCLSID)riid,xriid);
1196   TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
1197
1198   *ppvObj = NULL;
1199
1200   if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
1201   { *ppvObj = this; 
1202   }
1203   else if(IsEqualIID(riid, &IID_IShellView))  /*IShellView*/
1204   { *ppvObj = (IShellView*)this;
1205   }   
1206
1207   if(*ppvObj)
1208   { (*(LPSHELLVIEW*)ppvObj)->lpvtbl->fnAddRef(this);      
1209     TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1210     return S_OK;
1211   }
1212   TRACE(shell,"-- Interface: E_NOINTERFACE\n");
1213   return E_NOINTERFACE;
1214 }   
1215 /**************************************************************************
1216 *  IShellView::AddRef
1217 */
1218 static ULONG WINAPI IShellView_AddRef(LPSHELLVIEW this)
1219 {       TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
1220
1221         shell32_ObjCount++;
1222         return ++(this->ref);
1223 }
1224 /**************************************************************************
1225 *  IShellView_Release
1226 */
1227 static ULONG WINAPI IShellView_Release(LPSHELLVIEW this)
1228 {       TRACE(shell,"(%p)->()\n",this);
1229
1230         shell32_ObjCount--;
1231         if (!--(this->ref)) 
1232         { TRACE(shell," destroying IShellView(%p)\n",this);
1233
1234           if(this->pSFParent)
1235             this->pSFParent->lpvtbl->fnRelease(this->pSFParent);
1236
1237           if (this->aSelectedItems)
1238             SHFree(this->aSelectedItems);
1239
1240           if (this->pCommDlgBrowser)
1241             this->pCommDlgBrowser->lpvtbl->fnRelease(this->pCommDlgBrowser);
1242
1243           HeapFree(GetProcessHeap(),0,this);
1244           return 0;
1245         }
1246         return this->ref;
1247 }
1248 /**************************************************************************
1249 *  ShellView_GetWindow
1250 */
1251 static HRESULT WINAPI IShellView_GetWindow(LPSHELLVIEW this,HWND * phWnd)
1252 {       TRACE(shell,"(%p)\n",this);
1253         *phWnd = this->hWnd;
1254
1255         return S_OK;
1256 }
1257 static HRESULT WINAPI IShellView_ContextSensitiveHelp(LPSHELLVIEW this,BOOL fEnterMode)
1258 { FIXME(shell,"(%p) stub\n",this);
1259   return E_NOTIMPL;
1260 }
1261 /**************************************************************************
1262 * IShellView_TranslateAccelerator
1263 *
1264 * FIXME:
1265 *  use the accel functions
1266 */
1267 static HRESULT WINAPI IShellView_TranslateAccelerator(LPSHELLVIEW this,LPMSG lpmsg)
1268 {       FIXME(shell,"(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",this,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1269
1270         
1271         switch (lpmsg->message)
1272         { case WM_KEYDOWN:      TRACE(shell,"-- key=0x04%x",lpmsg->wParam) ;
1273         }
1274         return S_FALSE;
1275 }
1276 static HRESULT WINAPI IShellView_EnableModeless(LPSHELLVIEW this,BOOL fEnable)
1277 { FIXME(shell,"(%p) stub\n",this);
1278   return E_NOTIMPL;
1279 }
1280 static HRESULT WINAPI IShellView_UIActivate(LPSHELLVIEW this,UINT uState)
1281 {       CHAR    szName[MAX_PATH];
1282         LRESULT lResult;
1283         int     nPartArray[1] = {-1};
1284
1285         TRACE(shell,"(%p)->(state=%x) stub\n",this, uState);
1286         /*don't do anything if the state isn't really changing*/
1287         if(this->uState == uState)
1288         { return S_OK;
1289         }
1290
1291         /*OnActivate handles the menu merging and internal state*/
1292         ShellView_OnActivate(this, uState);
1293
1294         /*remove the docking window*/
1295         if(g_bShowIDW)
1296         { ShellView_AddRemoveDockingWindow(this, FALSE);
1297         }
1298
1299         /*only do this if we are active*/
1300         if(uState != SVUIA_DEACTIVATE)
1301         { /*update the status bar */
1302            strcpy(szName, "dummy32");
1303    
1304           this->pSFParent->lpvtbl->fnGetFolderPath( this->pSFParent,
1305                                                     szName + strlen(szName),
1306                                                     sizeof(szName) - strlen(szName));
1307
1308           /* set the number of parts */
1309           IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1310                                                         (LPARAM)nPartArray, &lResult);
1311
1312           /* set the text for the parts */
1313           IShellBrowser_SendControlMsg(this->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1314                                                         0, (LPARAM)szName, &lResult);
1315
1316           /*add the docking window if necessary */
1317           if(g_bShowIDW)
1318           { ShellView_AddRemoveDockingWindow(this, TRUE);
1319           }
1320         }
1321         return S_OK;
1322 }
1323 static HRESULT WINAPI IShellView_Refresh(LPSHELLVIEW this)
1324 {       TRACE(shell,"(%p)\n",this);
1325
1326         ListView_DeleteAllItems(this->hWndList);
1327         ShellView_FillList(this);
1328
1329         return S_OK;
1330 }
1331 static HRESULT WINAPI IShellView_CreateViewWindow(LPSHELLVIEW this, IShellView *lpPrevView,
1332                      LPCFOLDERSETTINGS lpfs, IShellBrowser * psb, RECT * prcView, HWND  *phWnd)
1333 {       WNDCLASSA wc;
1334 /*      LRESULT dwResult;*/
1335         *phWnd = 0;
1336
1337         
1338         TRACE(shell,"(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView,lpfs, psb, prcView, phWnd);
1339         TRACE(shell,"-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1340
1341         /*set up the member variables*/
1342         this->pShellBrowser = psb;
1343         this->FolderSettings = *lpfs;
1344
1345         /*get our parent window*/
1346         IShellBrowser_AddRef(this->pShellBrowser);
1347         IShellBrowser_GetWindow(this->pShellBrowser, &(this->hWndParent));
1348
1349         /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1350         this->pCommDlgBrowser=NULL;
1351         if ( SUCCEEDED (IShellBrowser_QueryInterface( this->pShellBrowser, 
1352                         (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &this->pCommDlgBrowser)))
1353         { TRACE(shell,"-- CommDlgBrowser\n");
1354         }
1355            
1356         /*if our window class has not been registered, then do so*/
1357         if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1358         { ZeroMemory(&wc, sizeof(wc));
1359           wc.style          = CS_HREDRAW | CS_VREDRAW;
1360           wc.lpfnWndProc    = (WNDPROC) ShellView_WndProc;
1361           wc.cbClsExtra     = 0;
1362           wc.cbWndExtra     = 0;
1363           wc.hInstance      = shell32_hInstance;
1364           wc.hIcon          = 0;
1365           wc.hCursor        = LoadCursorA (0, IDC_ARROWA);
1366           wc.hbrBackground  = (HBRUSH) (COLOR_WINDOW + 1);
1367           wc.lpszMenuName   = NULL;
1368           wc.lpszClassName  = SV_CLASS_NAME;
1369    
1370           if(!RegisterClassA(&wc))
1371             return E_FAIL;
1372         }
1373
1374         *phWnd = CreateWindowExA(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
1375                            prcView->left, prcView->top, prcView->right - prcView->left, prcView->bottom - prcView->top,
1376                            this->hWndParent, 0, shell32_hInstance, (LPVOID)this);
1377                            
1378         MergeToolBar(this);
1379         
1380         if(!*phWnd)
1381           return E_FAIL;
1382
1383         return S_OK;
1384 }
1385
1386 static HRESULT WINAPI IShellView_DestroyViewWindow(LPSHELLVIEW this)
1387 {       TRACE(shell,"(%p)\n",this);
1388
1389         /*Make absolutely sure all our UI is cleaned up.*/
1390         IShellView_UIActivate(this, SVUIA_DEACTIVATE);
1391         if(this->hMenu)
1392         { DestroyMenu(this->hMenu);
1393         }
1394         DestroyWindow(this->hWnd);
1395         IShellBrowser_Release(this->pShellBrowser);
1396         return S_OK;
1397 }
1398 static HRESULT WINAPI IShellView_GetCurrentInfo(LPSHELLVIEW this, LPFOLDERSETTINGS lpfs)
1399 {       TRACE(shell,"(%p)->(%p) vmode=%x flags=%x\n",this, lpfs, 
1400                 this->FolderSettings.ViewMode, this->FolderSettings.fFlags);
1401   
1402         if (lpfs)
1403         { *lpfs = this->FolderSettings;
1404           return NOERROR;
1405         }
1406         else
1407           return E_INVALIDARG;
1408 }
1409 static HRESULT WINAPI IShellView_AddPropertySheetPages(LPSHELLVIEW this, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1410 { FIXME(shell,"(%p) stub\n",this);
1411   return E_NOTIMPL;
1412 }
1413 static HRESULT WINAPI IShellView_SaveViewState(LPSHELLVIEW this)
1414 { FIXME(shell,"(%p) stub\n",this);
1415   return S_OK;
1416 }
1417 static HRESULT WINAPI IShellView_SelectItem(LPSHELLVIEW this, LPCITEMIDLIST pidlItem, UINT uFlags)
1418 { FIXME(shell,"(%p)->(pidl=%p, 0x%08x) stub\n",this, pidlItem, uFlags);
1419   return E_NOTIMPL;
1420 }
1421 static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW this, UINT uItem, REFIID riid, LPVOID *ppvOut)
1422 {       LPUNKNOWN       pObj = NULL; 
1423         char    xriid[50];
1424         
1425         WINE_StringFromCLSID((LPCLSID)riid,xriid);
1426         TRACE(shell,"(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",this, uItem, xriid, ppvOut);
1427
1428         *ppvOut = NULL;
1429         if(IsEqualIID(riid, &IID_IContextMenu))
1430         { ShellView_GetSelections(this);
1431           pObj =(LPUNKNOWN)IContextMenu_Constructor(this->pSFParent,this->aSelectedItems,this->uSelected);      
1432         }
1433         else if (IsEqualIID(riid, &IID_IDataObject))
1434         { ShellView_GetSelections(this);
1435           pObj =(LPUNKNOWN)IDataObject_Constructor(this->hWndParent, this->pSFParent,this->aSelectedItems,this->uSelected);
1436         }
1437
1438         TRACE(shell,"-- (%p)->(interface=%p)\n",this, ppvOut);
1439
1440         if(!pObj)
1441           return E_OUTOFMEMORY;
1442         *ppvOut = pObj;
1443         return S_OK;
1444 }