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