Authors: Mike McCormack <mike@codeweavers.com>, Aric Stewart <aric@codeweavers.com...
[wine] / dlls / shell32 / shlview.c
1 /*
2  *      ShellView
3  *
4  *      Copyright 1998,1999     <juergen.schmied@debitel.net>
5  *
6  * This is the view visualizing the data provied by the shellfolder.
7  * No direct access to data from pidls should be done from here.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * FIXME: The order by part of the background context menu should be
24  * buily according to the columns shown.
25  *
26  * FIXME: Load/Save the view state from/into the stream provied by
27  * the ShellBrowser
28  *
29  * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
30  *
31  * FIXME: ShellView_FillList: consider sort orders
32  *
33  * FIXME: implement the drag and drop in the old (msg-based) way
34  *
35  * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
36  * Release() ???
37  */
38
39 #include "config.h"
40 #include "wine/port.h"
41
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #define COBJMACROS
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
49
50 #include "windef.h"
51 #include "winerror.h"
52 #include "winbase.h"
53 #include "winnls.h"
54 #include "objbase.h"
55 #include "servprov.h"
56 #include "shlguid.h"
57 #include "wingdi.h"
58 #include "winuser.h"
59 #include "shlobj.h"
60 #include "undocshell.h"
61 #include "shresdef.h"
62 #include "wine/debug.h"
63
64 #include "docobj.h"
65 #include "pidl.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
68
69 WINE_DEFAULT_DEBUG_CHANNEL(shell);
70
71 typedef struct
72 {   BOOL    bIsAscending;
73     INT     nHeaderID;
74     INT     nLastHeaderID;
75 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
76
77 typedef struct
78 {
79         IShellViewVtbl*         lpVtbl;
80         DWORD                   ref;
81         IOleCommandTargetVtbl*  lpvtblOleCommandTarget;
82         IDropTargetVtbl*        lpvtblDropTarget;
83         IDropSourceVtbl*        lpvtblDropSource;
84         IViewObjectVtbl*        lpvtblViewObject;
85         IShellFolder*   pSFParent;
86         IShellFolder2*  pSF2Parent;
87         IShellBrowser*  pShellBrowser;
88         ICommDlgBrowser*        pCommDlgBrowser;
89         HWND            hWnd;           /* SHELLDLL_DefView */
90         HWND            hWndList;       /* ListView control */
91         HWND            hWndParent;
92         FOLDERSETTINGS  FolderSettings;
93         HMENU           hMenu;
94         UINT            uState;
95         UINT            cidl;
96         LPITEMIDLIST    *apidl;
97         LISTVIEW_SORT_INFO ListViewSortInfo;
98         ULONG                   hNotify;        /* change notification handle */
99         HANDLE          hAccel;
100 } IShellViewImpl;
101
102 static struct IShellViewVtbl svvt;
103
104 static struct IOleCommandTargetVtbl ctvt;
105 #define _IOleCommandTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblOleCommandTarget)))
106 #define _ICOM_THIS_From_IOleCommandTarget(class, name) class* This = (class*)(((char*)name)-_IOleCommandTarget_Offset);
107
108 static struct IDropTargetVtbl dtvt;
109 #define _IDropTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropTarget)))
110 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
111
112 static struct IDropSourceVtbl dsvt;
113 #define _IDropSource_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropSource)))
114 #define _ICOM_THIS_From_IDropSource(class, name) class* This = (class*)(((char*)name)-_IDropSource_Offset);
115
116 static struct IViewObjectVtbl vovt;
117 #define _IViewObject_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblViewObject)))
118 #define _ICOM_THIS_From_IViewObject(class, name) class* This = (class*)(((char*)name)-_IViewObject_Offset);
119
120 /* ListView Header ID's */
121 #define LISTVIEW_COLUMN_NAME 0
122 #define LISTVIEW_COLUMN_SIZE 1
123 #define LISTVIEW_COLUMN_TYPE 2
124 #define LISTVIEW_COLUMN_TIME 3
125 #define LISTVIEW_COLUMN_ATTRIB 4
126
127 /*menu items */
128 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
129 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
130 #define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
131
132 #define ID_LISTVIEW     2000
133
134 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
135
136 /*windowsx.h */
137 #define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
138 #define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
139 #define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
140
141 extern void WINAPI _InsertMenuItem (HMENU hmenu, UINT indexMenu, BOOL fByPosition,
142                         UINT wID, UINT fType, LPSTR dwTypeData, UINT fState);
143
144 /*
145   Items merged into the toolbar and and the filemenu
146 */
147 typedef struct
148 {  int   idCommand;
149    int   iImage;
150    int   idButtonString;
151    int   idMenuString;
152    BYTE  bState;
153    BYTE  bStyle;
154 } MYTOOLINFO, *LPMYTOOLINFO;
155
156 MYTOOLINFO Tools[] =
157 {
158 { FCIDM_SHVIEW_BIGICON,    0, 0, IDS_VIEW_LARGE,   TBSTATE_ENABLED, BTNS_BUTTON },
159 { FCIDM_SHVIEW_SMALLICON,  0, 0, IDS_VIEW_SMALL,   TBSTATE_ENABLED, BTNS_BUTTON },
160 { FCIDM_SHVIEW_LISTVIEW,   0, 0, IDS_VIEW_LIST,    TBSTATE_ENABLED, BTNS_BUTTON },
161 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
162 { -1, 0, 0, 0, 0, 0}
163 };
164
165 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
166
167 /**********************************************************
168  *      IShellView_Constructor
169  */
170 IShellView * IShellView_Constructor( IShellFolder * pFolder)
171 {       IShellViewImpl * sv;
172         sv=(IShellViewImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
173         sv->ref=1;
174         sv->lpVtbl=&svvt;
175         sv->lpvtblOleCommandTarget=&ctvt;
176         sv->lpvtblDropTarget=&dtvt;
177         sv->lpvtblDropSource=&dsvt;
178         sv->lpvtblViewObject=&vovt;
179
180         sv->pSFParent = pFolder;
181         if(pFolder) IShellFolder_AddRef(pFolder);
182         IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
183
184         TRACE("(%p)->(%p)\n",sv, pFolder);
185         return (IShellView *) sv;
186 }
187
188 /**********************************************************
189  *
190  * ##### helperfunctions for communication with ICommDlgBrowser #####
191  */
192 static BOOL IsInCommDlg(IShellViewImpl * This)
193 {       return(This->pCommDlgBrowser != NULL);
194 }
195
196 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
197 {
198         HRESULT ret = S_OK;
199
200         if ( IsInCommDlg(This) )
201         {
202           TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
203           ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
204           TRACE("--0x%08lx\n", ret);
205         }
206         return ret;
207 }
208
209 static HRESULT OnDefaultCommand(IShellViewImpl * This)
210 {
211         HRESULT ret = S_FALSE;
212
213         if (IsInCommDlg(This))
214         {
215           TRACE("ICommDlgBrowser::OnDefaultCommand\n");
216           ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
217           TRACE("--\n");
218         }
219         return ret;
220 }
221
222 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
223 {
224         HRESULT ret = S_FALSE;
225
226         if (IsInCommDlg(This))
227         {
228           TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
229           ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
230           TRACE("--\n");
231         }
232         return ret;
233 }
234 /**********************************************************
235  *      set the toolbar of the filedialog buttons
236  *
237  * - activates the buttons from the shellbrowser according to
238  *   the view state
239  */
240 static void CheckToolbar(IShellViewImpl * This)
241 {
242         LRESULT result;
243
244         TRACE("\n");
245
246         if (IsInCommDlg(This))
247         {
248           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
249                 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
250           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
251                 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
252           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
253                 FCIDM_TB_SMALLICON, TRUE, &result);
254           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
255                 FCIDM_TB_REPORTVIEW, TRUE, &result);
256         }
257 }
258
259 /**********************************************************
260  *
261  * ##### helperfunctions for initializing the view #####
262  */
263 /**********************************************************
264  *      change the style of the listview control
265  */
266 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
267 {
268         DWORD tmpstyle;
269
270         TRACE("(%p)\n", This);
271
272         tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
273         SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
274 }
275
276 /**********************************************************
277 * ShellView_CreateList()
278 *
279 * - creates the list view window
280 */
281 static BOOL ShellView_CreateList (IShellViewImpl * This)
282 {       DWORD dwStyle, dwExStyle;
283
284         TRACE("%p\n",This);
285
286         dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
287                   LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
288         dwExStyle = WS_EX_CLIENTEDGE;
289
290         switch (This->FolderSettings.ViewMode)
291         {
292           case FVM_ICON:        dwStyle |= LVS_ICON;            break;
293           case FVM_DETAILS:     dwStyle |= LVS_REPORT;          break;
294           case FVM_SMALLICON:   dwStyle |= LVS_SMALLICON;       break;
295           case FVM_LIST:        dwStyle |= LVS_LIST;            break;
296           default:              dwStyle |= LVS_LIST;            break;
297         }
298
299         if (This->FolderSettings.fFlags & FWF_AUTOARRANGE)      dwStyle |= LVS_AUTOARRANGE;
300         if (This->FolderSettings.fFlags & FWF_DESKTOP)
301           This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
302         if (This->FolderSettings.fFlags & FWF_SINGLESEL)        dwStyle |= LVS_SINGLESEL;
303         if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
304           dwExStyle &= ~WS_EX_CLIENTEDGE;
305
306         This->hWndList=CreateWindowExA( dwExStyle,
307                                         WC_LISTVIEWA,
308                                         NULL,
309                                         dwStyle,
310                                         0,0,0,0,
311                                         This->hWnd,
312                                         (HMENU)ID_LISTVIEW,
313                                         shell32_hInstance,
314                                         NULL);
315
316         if(!This->hWndList)
317           return FALSE;
318
319         This->ListViewSortInfo.bIsAscending = TRUE;
320         This->ListViewSortInfo.nHeaderID = -1;
321         This->ListViewSortInfo.nLastHeaderID = -1;
322
323        if (This->FolderSettings.fFlags & FWF_DESKTOP) {
324          if (0)  /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */
325            ListView_SetTextBkColor(This->hWndList, CLR_NONE);
326          else
327            ListView_SetTextBkColor(This->hWndList, GetSysColor(COLOR_DESKTOP));
328
329          ListView_SetTextColor(This->hWndList, RGB(255,255,255));
330        }
331
332         /*  UpdateShellSettings(); */
333         return TRUE;
334 }
335
336 /**********************************************************
337 * ShellView_InitList()
338 *
339 * - adds all needed columns to the shellview
340 */
341 static BOOL ShellView_InitList(IShellViewImpl * This)
342 {
343         LVCOLUMNA       lvColumn;
344         SHELLDETAILS    sd;
345         int     i;
346         char    szTemp[50];
347
348         TRACE("%p\n",This);
349
350         ListView_DeleteAllItems(This->hWndList);
351
352         lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
353         lvColumn.pszText = szTemp;
354
355         if (This->pSF2Parent)
356         {
357           for (i=0; 1; i++)
358           {
359             if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
360               break;
361             lvColumn.fmt = sd.fmt;
362             lvColumn.cx = sd.cxChar*8; /* chars->pixel */
363             StrRetToStrNA( szTemp, 50, &sd.str, NULL);
364             ListView_InsertColumnA(This->hWndList, i, &lvColumn);
365           }
366         }
367         else
368         {
369           FIXME("no SF2\n");
370         }
371
372         ListView_SetImageList(This->hWndList, ShellSmallIconList, LVSIL_SMALL);
373         ListView_SetImageList(This->hWndList, ShellBigIconList, LVSIL_NORMAL);
374
375         return TRUE;
376 }
377 /**********************************************************
378 * ShellView_CompareItems()
379 *
380 * NOTES
381 *  internal, CALLBACK for DSA_Sort
382 */
383 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
384 {
385         int ret;
386         TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
387
388         if(!lpData) return 0;
389
390         ret =  (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
391         TRACE("ret=%i\n",ret);
392         return ret;
393 }
394
395 /*************************************************************************
396  * ShellView_ListViewCompareItems
397  *
398  * Compare Function for the Listview (FileOpen Dialog)
399  *
400  * PARAMS
401  *     lParam1       [I] the first ItemIdList to compare with
402  *     lParam2       [I] the second ItemIdList to compare with
403  *     lpData        [I] The column ID for the header Ctrl to process
404  *
405  * RETURNS
406  *     A negative value if the first item should precede the second,
407  *     a positive value if the first item should follow the second,
408  *     or zero if the two items are equivalent
409  *
410  * NOTES
411  *      FIXME: function does what ShellView_CompareItems is supposed to do.
412  *      unify it and figure out how to use the undocumented first parameter
413  *      of IShellFolder_CompareIDs to do the job this function does and
414  *      move this code to IShellFolder.
415  *      make LISTVIEW_SORT_INFO obsolete
416  *      the way this function works is only usable if we had only
417  *      filesystemfolders  (25/10/99 jsch)
418  */
419 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
420 {
421     INT nDiff=0;
422     FILETIME fd1, fd2;
423     char strName1[MAX_PATH], strName2[MAX_PATH];
424     BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
425     LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
426     LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
427     LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
428
429
430     bIsFolder1 = _ILIsFolder(pItemIdList1);
431     bIsFolder2 = _ILIsFolder(pItemIdList2);
432     bIsBothFolder = bIsFolder1 && bIsFolder2;
433
434     /* When sorting between a File and a Folder, the Folder gets sorted first */
435     if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
436     {
437         nDiff = bIsFolder1 ? -1 : 1;
438     }
439     else
440     {
441         /* Sort by Time: Folders or Files can be sorted */
442
443         if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
444         {
445             _ILGetFileDateTime(pItemIdList1, &fd1);
446             _ILGetFileDateTime(pItemIdList2, &fd2);
447             nDiff = CompareFileTime(&fd2, &fd1);
448         }
449         /* Sort by Attribute: Folder or Files can be sorted */
450         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
451         {
452             _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
453             _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
454             nDiff = strcasecmp(strName1, strName2);
455         }
456         /* Sort by FileName: Folder or Files can be sorted */
457         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
458         {
459             /* Sort by Text */
460             _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
461             _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
462             nDiff = strcasecmp(strName1, strName2);
463         }
464         /* Sort by File Size, Only valid for Files */
465         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
466         {
467             nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
468         }
469         /* Sort by File Type, Only valid for Files */
470         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
471         {
472             /* Sort by Type */
473             _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
474             _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
475             nDiff = strcasecmp(strName1, strName2);
476         }
477     }
478     /*  If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
479
480     if(nDiff == 0)
481     {
482         _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
483         _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
484         nDiff = strcasecmp(strName1, strName2);
485     }
486
487     if(!pSortInfo->bIsAscending)
488     {
489         nDiff = -nDiff;
490     }
491
492     return nDiff;
493
494 }
495
496 /**********************************************************
497 *  LV_FindItemByPidl()
498 */
499 static int LV_FindItemByPidl(
500         IShellViewImpl * This,
501         LPCITEMIDLIST pidl)
502 {
503         LVITEMA lvItem;
504         ZeroMemory(&lvItem, sizeof(LVITEMA));
505         lvItem.mask = LVIF_PARAM;
506         for(lvItem.iItem = 0; ListView_GetItemA(This->hWndList, &lvItem); lvItem.iItem++)
507         {
508           LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
509           HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
510           if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
511           {
512             return lvItem.iItem;
513           }
514         }
515         return -1;
516 }
517
518 /**********************************************************
519 * LV_AddItem()
520 */
521 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
522 {
523         LVITEMA lvItem;
524
525         TRACE("(%p)(pidl=%p)\n", This, pidl);
526
527         ZeroMemory(&lvItem, sizeof(lvItem));    /* create the listview item*/
528         lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;      /*set the mask*/
529         lvItem.iItem = ListView_GetItemCount(This->hWndList);   /*add the item to the end of the list*/
530         lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl));                           /*set the item's data*/
531         lvItem.pszText = LPSTR_TEXTCALLBACKA;                   /*get text on a callback basis*/
532         lvItem.iImage = I_IMAGECALLBACK;                        /*get the image on a callback basis*/
533         return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
534 }
535
536 /**********************************************************
537 * LV_DeleteItem()
538 */
539 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
540 {
541         int nIndex;
542
543         TRACE("(%p)(pidl=%p)\n", This, pidl);
544
545         nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
546         return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
547 }
548
549 /**********************************************************
550 * LV_RenameItem()
551 */
552 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
553 {
554         int nItem;
555         LVITEMA lvItem;
556
557         TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
558
559         nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
560         if ( -1 != nItem )
561         {
562           ZeroMemory(&lvItem, sizeof(lvItem));  /* create the listview item*/
563           lvItem.mask = LVIF_PARAM;             /* only the pidl */
564           lvItem.iItem = nItem;
565           ListView_GetItemA(This->hWndList, &lvItem);
566
567           SHFree((LPITEMIDLIST)lvItem.lParam);
568           lvItem.mask = LVIF_PARAM;
569           lvItem.iItem = nItem;
570           lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew));      /* set the item's data */
571           ListView_SetItemA(This->hWndList, &lvItem);
572           ListView_Update(This->hWndList, nItem);
573           return TRUE;                                  /* FIXME: better handling */
574         }
575         return FALSE;
576 }
577 /**********************************************************
578 * ShellView_FillList()
579 *
580 * - gets the objectlist from the shellfolder
581 * - sorts the list
582 * - fills the list into the view
583 */
584
585 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
586 {
587     LPITEMIDLIST pidl = ptr;
588     IShellViewImpl *This = arg;
589     /* in a commdlg This works as a filemask*/
590     if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
591     SHFree(pidl);
592     return TRUE;
593 }
594
595 static HRESULT ShellView_FillList(IShellViewImpl * This)
596 {
597         LPENUMIDLIST    pEnumIDList;
598         LPITEMIDLIST    pidl;
599         DWORD           dwFetched;
600         HRESULT         hRes;
601         HDPA            hdpa;
602
603         TRACE("%p\n",This);
604
605         /* get the itemlist from the shfolder*/
606         hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
607         if (hRes != S_OK)
608         {
609           if (hRes==S_FALSE)
610             return(NOERROR);
611           return(hRes);
612         }
613
614         /* create a pointer array */
615         hdpa = DPA_Create(16);
616         if (!hdpa)
617         {
618           return(E_OUTOFMEMORY);
619         }
620
621         /* copy the items into the array*/
622         while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
623         {
624           if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
625           {
626             SHFree(pidl);
627           }
628         }
629
630         /* sort the array */
631         DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
632
633         /*turn the listview's redrawing off*/
634         SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
635
636         DPA_DestroyCallback( hdpa, fill_list, This );
637
638         /*turn the listview's redrawing back on and force it to draw*/
639         SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
640
641         IEnumIDList_Release(pEnumIDList); /* destroy the list*/
642
643         return S_OK;
644 }
645
646 /**********************************************************
647 *  ShellView_OnCreate()
648 */
649 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
650 {
651         IDropTarget* pdt;
652         SHChangeNotifyEntry ntreg;
653         IPersistFolder2 * ppf2 = NULL;
654
655         TRACE("%p\n",This);
656
657         if(ShellView_CreateList(This))
658         {
659           if(ShellView_InitList(This))
660           {
661             ShellView_FillList(This);
662           }
663         }
664
665         if (SUCCEEDED(IShellFolder_CreateViewObject(This->pSFParent, This->hWnd, &IID_IDropTarget, (LPVOID*)&pdt)))
666         {
667             RegisterDragDrop(This->hWnd, pdt);
668             IDropTarget_Release(pdt);
669         }
670
671         /* register for receiving notifications */
672         IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
673         if (ppf2)
674         {
675           IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
676           ntreg.fRecursive = TRUE;
677           This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
678           SHFree((LPITEMIDLIST)ntreg.pidl);
679           IPersistFolder2_Release(ppf2);
680         }
681
682         This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
683
684         return S_OK;
685 }
686
687 /**********************************************************
688  *      #### Handling of the menus ####
689  */
690
691 /**********************************************************
692 * ShellView_BuildFileMenu()
693 */
694 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
695 {       CHAR    szText[MAX_PATH];
696         MENUITEMINFOA   mii;
697         int     nTools,i;
698         HMENU   hSubMenu;
699
700         TRACE("(%p)\n",This);
701
702         hSubMenu = CreatePopupMenu();
703         if(hSubMenu)
704         { /*get the number of items in our global array*/
705           for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
706
707           /*add the menu items*/
708           for(i = 0; i < nTools; i++)
709           {
710             LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
711
712             ZeroMemory(&mii, sizeof(mii));
713             mii.cbSize = sizeof(mii);
714             mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
715
716             if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
717             {
718               mii.fType = MFT_STRING;
719               mii.fState = MFS_ENABLED;
720               mii.dwTypeData = szText;
721               mii.wID = Tools[i].idCommand;
722             }
723             else
724             {
725               mii.fType = MFT_SEPARATOR;
726             }
727             /* tack This item onto the end of the menu */
728             InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
729           }
730         }
731         TRACE("-- return (menu=%p)\n",hSubMenu);
732         return hSubMenu;
733 }
734 /**********************************************************
735 * ShellView_MergeFileMenu()
736 */
737 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
738 {       TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
739
740         if(hSubMenu)
741         { /*insert This item at the beginning of the menu */
742           _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
743           _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
744
745         }
746         TRACE("--\n");
747 }
748
749 /**********************************************************
750 * ShellView_MergeViewMenu()
751 */
752
753 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
754 {       MENUITEMINFOA   mii;
755
756         TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
757
758         if(hSubMenu)
759         { /*add a separator at the correct position in the menu*/
760           _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
761
762           ZeroMemory(&mii, sizeof(mii));
763           mii.cbSize = sizeof(mii);
764           mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
765           mii.fType = MFT_STRING;
766           mii.dwTypeData = "View";
767           mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
768           InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
769         }
770 }
771
772 /**********************************************************
773 *   ShellView_GetSelections()
774 *
775 * - fills the this->apidl list with the selected objects
776 *
777 * RETURNS
778 *  number of selected items
779 */
780 static UINT ShellView_GetSelections(IShellViewImpl * This)
781 {
782         LVITEMA lvItem;
783         UINT    i = 0;
784
785         if (This->apidl)
786         {
787           SHFree(This->apidl);
788         }
789
790         This->cidl = ListView_GetSelectedCount(This->hWndList);
791         This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
792
793         TRACE("selected=%i\n", This->cidl);
794
795         if(This->apidl)
796         {
797           TRACE("-- Items selected =%u\n", This->cidl);
798
799           ZeroMemory(&lvItem, sizeof(lvItem));
800           lvItem.mask = LVIF_STATE | LVIF_PARAM;
801           lvItem.stateMask = LVIS_SELECTED;
802
803           while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
804           {
805             if(lvItem.state & LVIS_SELECTED)
806             {
807               This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
808               i++;
809               TRACE("-- selected Item found\n");
810             }
811             lvItem.iItem++;
812           }
813         }
814         return This->cidl;
815
816 }
817
818 /**********************************************************
819  *      ShellView_OpenSelectedItems()
820  */
821 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
822 {
823         static UINT CF_IDLIST = 0;
824         HRESULT hr;
825         IDataObject* selection;
826         FORMATETC fetc;
827         STGMEDIUM stgm;
828         LPIDA pIDList;
829         LPCITEMIDLIST parent_pidl;
830         int i;
831
832         if (0 == ShellView_GetSelections(This))
833         {
834           return S_OK;
835         }
836         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
837                                         (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
838                                         0, (LPVOID *)&selection);
839         if (FAILED(hr))
840           return hr;
841
842         if (0 == CF_IDLIST)
843         {
844           CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
845         }
846         fetc.cfFormat = CF_IDLIST;
847         fetc.ptd = NULL;
848         fetc.dwAspect = DVASPECT_CONTENT;
849         fetc.lindex = -1;
850         fetc.tymed = TYMED_HGLOBAL;
851
852         hr = IDataObject_QueryGetData(selection, &fetc);
853         if (FAILED(hr))
854           return hr;
855
856         hr = IDataObject_GetData(selection, &fetc, &stgm);
857         if (FAILED(hr))
858           return hr;
859
860         pIDList = GlobalLock(stgm.u.hGlobal);
861
862         parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
863         for (i = pIDList->cidl; i > 0; --i)
864         {
865           LPCITEMIDLIST pidl;
866           SFGAOF attribs;
867
868           pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
869
870           attribs = SFGAO_FOLDER;
871           hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
872
873           if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
874           {
875             SHELLEXECUTEINFOA shexinfo;
876
877             shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
878             shexinfo.fMask = SEE_MASK_INVOKEIDLIST;     /* SEE_MASK_IDLIST is also possible. */
879             shexinfo.hwnd = NULL;
880             shexinfo.lpVerb = NULL;
881             shexinfo.lpFile = NULL;
882             shexinfo.lpParameters = NULL;
883             shexinfo.lpDirectory = NULL;
884             shexinfo.nShow = SW_NORMAL;
885             shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
886
887             ShellExecuteExA(&shexinfo);    /* Discard error/success info */
888
889             ILFree((LPITEMIDLIST)shexinfo.lpIDList);
890           }
891         }
892
893         GlobalUnlock(stgm.u.hGlobal);
894         ReleaseStgMedium(&stgm);
895
896         IDataObject_Release(selection);
897
898         return S_OK;
899 }
900
901 /**********************************************************
902  *      ShellView_DoContextMenu()
903  */
904 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
905 {       UINT    uCommand;
906         DWORD   wFlags;
907         HMENU   hMenu;
908         BOOL    fExplore = FALSE;
909         HWND    hwndTree = 0;
910         LPCONTEXTMENU   pContextMenu = NULL;
911         IContextMenu2 *pCM = NULL;
912         CMINVOKECOMMANDINFO     cmi;
913
914         TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
915
916         /* look, what's selected and create a context menu object of it*/
917         if( ShellView_GetSelections(This) )
918         {
919           IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
920                                         (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
921
922           if(pContextMenu)
923           {
924             TRACE("-- pContextMenu\n");
925             hMenu = CreatePopupMenu();
926
927             if( hMenu )
928             {
929               /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
930               if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
931               {
932                 TRACE("-- explore mode\n");
933                 fExplore = TRUE;
934               }
935
936               /* build the flags depending on what we can do with the selected item */
937               wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
938
939               /* let the ContextMenu merge its items in */
940               if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
941               {
942                 if (This->FolderSettings.fFlags & FWF_DESKTOP)
943                   SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
944
945                 if( bDefault )
946                 {
947                   TRACE("-- get menu default command\n");
948                   uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
949                 }
950                 else
951                 {
952                   TRACE("-- track popup\n");
953                   uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
954                 }
955
956                 if(uCommand > 0)
957                 {
958                   TRACE("-- uCommand=%u\n", uCommand);
959                   if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
960                   {
961                     TRACE("-- dlg: OnDefaultCommand\n");
962                     if (FAILED(OnDefaultCommand(This)))
963                     {
964                       ShellView_OpenSelectedItems(This);
965                     }
966                   }
967                   else
968                   {
969                     TRACE("-- explore -- invoke command\n");
970                     ZeroMemory(&cmi, sizeof(cmi));
971                     cmi.cbSize = sizeof(cmi);
972                     cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
973                     cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
974                     IContextMenu_InvokeCommand(pContextMenu, &cmi);
975                   }
976                 }
977                 DestroyMenu(hMenu);
978               }
979             }
980             if (pContextMenu)
981               IContextMenu_Release(pContextMenu);
982           }
983         }
984         else    /* background context menu */
985         {
986           hMenu = CreatePopupMenu();
987
988           pCM = ISvBgCm_Constructor(This->pSFParent);
989           IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
990
991           uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
992           DestroyMenu(hMenu);
993
994           TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
995
996           ZeroMemory(&cmi, sizeof(cmi));
997           cmi.cbSize = sizeof(cmi);
998           cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
999           cmi.hwnd = This->hWndParent;
1000           IContextMenu2_InvokeCommand(pCM, &cmi);
1001
1002           IContextMenu2_Release(pCM);
1003         }
1004 }
1005
1006 /**********************************************************
1007  *      ##### message handling #####
1008  */
1009
1010 /**********************************************************
1011 *  ShellView_OnSize()
1012 */
1013 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1014 {
1015         TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1016
1017         /*resize the ListView to fit our window*/
1018         if(This->hWndList)
1019         {
1020           MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1021         }
1022
1023         return S_OK;
1024 }
1025 /**********************************************************
1026 * ShellView_OnDeactivate()
1027 *
1028 * NOTES
1029 *  internal
1030 */
1031 static void ShellView_OnDeactivate(IShellViewImpl * This)
1032 {
1033         TRACE("%p\n",This);
1034
1035         if(This->uState != SVUIA_DEACTIVATE)
1036         {
1037           if(This->hMenu)
1038           {
1039             IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1040             IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1041             DestroyMenu(This->hMenu);
1042             This->hMenu = 0;
1043           }
1044
1045           This->uState = SVUIA_DEACTIVATE;
1046         }
1047 }
1048
1049 /**********************************************************
1050 * ShellView_OnActivate()
1051 */
1052 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1053 {       OLEMENUGROUPWIDTHS   omw = { {0, 0, 0, 0, 0, 0} };
1054         MENUITEMINFOA         mii;
1055         CHAR                szText[MAX_PATH];
1056
1057         TRACE("%p uState=%x\n",This,uState);
1058
1059         /*don't do anything if the state isn't really changing */
1060         if(This->uState == uState)
1061         {
1062           return S_OK;
1063         }
1064
1065         ShellView_OnDeactivate(This);
1066
1067         /*only do This if we are active */
1068         if(uState != SVUIA_DEACTIVATE)
1069         {
1070           /*merge the menus */
1071           This->hMenu = CreateMenu();
1072
1073           if(This->hMenu)
1074           {
1075             IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1076             TRACE("-- after fnInsertMenusSB\n");
1077
1078             /*build the top level menu get the menu item's text*/
1079             strcpy(szText,"dummy 31");
1080
1081             ZeroMemory(&mii, sizeof(mii));
1082             mii.cbSize = sizeof(mii);
1083             mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1084             mii.fType = MFT_STRING;
1085             mii.fState = MFS_ENABLED;
1086             mii.dwTypeData = szText;
1087             mii.hSubMenu = ShellView_BuildFileMenu(This);
1088
1089             /*insert our menu into the menu bar*/
1090             if(mii.hSubMenu)
1091             {
1092               InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1093             }
1094
1095             /*get the view menu so we can merge with it*/
1096             ZeroMemory(&mii, sizeof(mii));
1097             mii.cbSize = sizeof(mii);
1098             mii.fMask = MIIM_SUBMENU;
1099
1100             if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1101             {
1102               ShellView_MergeViewMenu(This, mii.hSubMenu);
1103             }
1104
1105             /*add the items that should only be added if we have the focus*/
1106             if(SVUIA_ACTIVATE_FOCUS == uState)
1107             {
1108               /*get the file menu so we can merge with it */
1109               ZeroMemory(&mii, sizeof(mii));
1110               mii.cbSize = sizeof(mii);
1111               mii.fMask = MIIM_SUBMENU;
1112
1113               if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1114               {
1115                 ShellView_MergeFileMenu(This, mii.hSubMenu);
1116               }
1117             }
1118             TRACE("-- before fnSetMenuSB\n");
1119             IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1120           }
1121         }
1122         This->uState = uState;
1123         TRACE("--\n");
1124         return S_OK;
1125 }
1126
1127 /**********************************************************
1128 *  ShellView_OnSetFocus()
1129 *
1130 */
1131 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1132 {
1133         TRACE("%p\n",This);
1134
1135         /* Tell the browser one of our windows has received the focus. This
1136         should always be done before merging menus (OnActivate merges the
1137         menus) if one of our windows has the focus.*/
1138
1139         IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1140         ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1141
1142         /* Set the focus to the listview */
1143         SetFocus(This->hWndList);
1144
1145         /* Notify the ICommDlgBrowser interface */
1146         OnStateChange(This,CDBOSC_SETFOCUS);
1147
1148         return 0;
1149 }
1150
1151 /**********************************************************
1152 * ShellView_OnKillFocus()
1153 */
1154 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1155 {
1156         TRACE("(%p) stub\n",This);
1157
1158         ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1159         /* Notify the ICommDlgBrowser */
1160         OnStateChange(This,CDBOSC_KILLFOCUS);
1161
1162         return 0;
1163 }
1164
1165 /**********************************************************
1166 * ShellView_OnCommand()
1167 *
1168 * NOTES
1169 *       the CmdID's are the ones from the context menu
1170 */
1171 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1172 {
1173         TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1174
1175         switch(dwCmdID)
1176         {
1177           case FCIDM_SHVIEW_SMALLICON:
1178             This->FolderSettings.ViewMode = FVM_SMALLICON;
1179             SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1180             CheckToolbar(This);
1181             break;
1182
1183           case FCIDM_SHVIEW_BIGICON:
1184             This->FolderSettings.ViewMode = FVM_ICON;
1185             SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1186             CheckToolbar(This);
1187             break;
1188
1189           case FCIDM_SHVIEW_LISTVIEW:
1190             This->FolderSettings.ViewMode = FVM_LIST;
1191             SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1192             CheckToolbar(This);
1193             break;
1194
1195           case FCIDM_SHVIEW_REPORTVIEW:
1196             This->FolderSettings.ViewMode = FVM_DETAILS;
1197             SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1198             CheckToolbar(This);
1199             break;
1200
1201           /* the menu-ID's for sorting are 0x30... see shrec.rc */
1202           case 0x30:
1203           case 0x31:
1204           case 0x32:
1205           case 0x33:
1206             This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1207             This->ListViewSortInfo.bIsAscending = TRUE;
1208             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1209             ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1210             break;
1211
1212           default:
1213             TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
1214         }
1215         return 0;
1216 }
1217
1218 /**********************************************************
1219 * ShellView_OnNotify()
1220 */
1221
1222 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1223 {       LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1224         NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1225         LPITEMIDLIST pidl;
1226
1227         TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1228
1229         switch(lpnmh->code)
1230         {
1231           case NM_SETFOCUS:
1232             TRACE("-- NM_SETFOCUS %p\n",This);
1233             ShellView_OnSetFocus(This);
1234             break;
1235
1236           case NM_KILLFOCUS:
1237             TRACE("-- NM_KILLFOCUS %p\n",This);
1238             ShellView_OnDeactivate(This);
1239             /* Notify the ICommDlgBrowser interface */
1240             OnStateChange(This,CDBOSC_KILLFOCUS);
1241             break;
1242
1243           case NM_CUSTOMDRAW:
1244             TRACE("-- NM_CUSTOMDRAW %p\n",This);
1245             return CDRF_DODEFAULT;
1246
1247           case NM_RELEASEDCAPTURE:
1248             TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1249             break;
1250
1251           case NM_CLICK:
1252             TRACE("-- NM_CLICK %p\n",This);
1253             break;
1254
1255           case NM_RCLICK:
1256             TRACE("-- NM_RCLICK %p\n",This);
1257             break;          
1258
1259           case HDN_ENDTRACKA:
1260             TRACE("-- HDN_ENDTRACKA %p\n",This);
1261             /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1262             nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1263             break;
1264
1265           case LVN_DELETEITEM:
1266             TRACE("-- LVN_DELETEITEM %p\n",This);
1267             SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
1268             break;
1269
1270           case LVN_DELETEALLITEMS:
1271             TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1272             return FALSE;
1273
1274           case LVN_INSERTITEM:
1275             TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1276             break;
1277
1278           case LVN_ITEMACTIVATE:
1279             TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1280             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1281             ShellView_DoContextMenu(This, 0, 0, TRUE);
1282             break;
1283
1284           case LVN_COLUMNCLICK:
1285             This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1286             if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1287             {
1288               This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1289             }
1290             else
1291             {
1292               This->ListViewSortInfo.bIsAscending = TRUE;
1293             }
1294             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1295
1296             ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1297             break;
1298
1299           case LVN_GETDISPINFOA:
1300           case LVN_GETDISPINFOW:
1301             TRACE("-- LVN_GETDISPINFO %p\n",This);
1302             pidl = (LPITEMIDLIST)lpdi->item.lParam;
1303
1304             if(lpdi->item.mask & LVIF_TEXT)     /* text requested */
1305             {
1306               if (This->pSF2Parent)
1307               {
1308                 SHELLDETAILS sd;
1309                 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1310                 if (lpnmh->code == LVN_GETDISPINFOA)
1311                 {
1312                     StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1313                     TRACE("-- text=%s\n",lpdi->item.pszText);
1314                 }
1315                 else /* LVN_GETDISPINFOW */
1316                 {
1317                     StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1318                     TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1319                 }
1320               }
1321               else
1322               {
1323                 FIXME("no SF2\n");
1324               }
1325             }
1326             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
1327             {
1328               lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1329             }
1330             break;
1331
1332           case LVN_ITEMCHANGED:
1333             TRACE("-- LVN_ITEMCHANGED %p\n",This);
1334             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1335             break;
1336
1337           case LVN_BEGINDRAG:
1338           case LVN_BEGINRDRAG:
1339             TRACE("-- LVN_BEGINDRAG\n");
1340
1341             if (ShellView_GetSelections(This))
1342             {
1343               IDataObject * pda;
1344               DWORD dwAttributes = SFGAO_CANLINK;
1345               DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1346
1347               if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1348               {
1349                   IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource);  /* own DropSource interface */
1350
1351                   if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1352                   {
1353                     if (dwAttributes & SFGAO_CANLINK)
1354                     {
1355                       dwEffect |= DROPEFFECT_LINK;
1356                     }
1357                   }
1358
1359                   if (pds)
1360                   {
1361                     DWORD dwEffect;
1362                     DoDragDrop(pda, pds, dwEffect, &dwEffect);
1363                   }
1364                   IDataObject_Release(pda);
1365               }
1366             }
1367             break;
1368
1369           case LVN_BEGINLABELEDITA:
1370             {
1371               DWORD dwAttr = SFGAO_CANRENAME;
1372               pidl = (LPITEMIDLIST)lpdi->item.lParam;
1373
1374               TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1375
1376               IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1377               if (SFGAO_CANRENAME & dwAttr)
1378               {
1379                 return FALSE;
1380               }
1381               return TRUE;
1382             }
1383
1384           case LVN_ENDLABELEDITA:
1385             {
1386               TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1387               if (lpdi->item.pszText)
1388               {
1389                 HRESULT hr;
1390                 WCHAR wszNewName[MAX_PATH];
1391                 LVITEMA lvItem;
1392
1393                 ZeroMemory(&lvItem, sizeof(LVITEMA));
1394                 lvItem.iItem = lpdi->item.iItem;
1395                 lvItem.mask = LVIF_PARAM;
1396                 ListView_GetItemA(This->hWndList, &lvItem);
1397
1398                 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1399                 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1400                     wszNewName[MAX_PATH-1] = 0;
1401                 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1402
1403                 if(SUCCEEDED(hr) && pidl)
1404                 {
1405                   lvItem.mask = LVIF_PARAM;
1406                   lvItem.lParam = (LPARAM)pidl;
1407                   ListView_SetItemA(This->hWndList, &lvItem);
1408                   return TRUE;
1409                 }
1410               }
1411               return FALSE;
1412             }
1413
1414           case LVN_KEYDOWN:
1415             {
1416             /*  MSG msg;
1417               msg.hwnd = This->hWnd;
1418               msg.message = WM_KEYDOWN;
1419               msg.wParam = plvKeyDown->wVKey;
1420               msg.lParam = 0;
1421               msg.time = 0;
1422               msg.pt = 0;*/
1423
1424               LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1425
1426               /* initiate a rename of the selected file or directory */
1427               if(plvKeyDown->wVKey == VK_F2)
1428               {
1429                 /* see how many files are selected */
1430                 int i = ListView_GetSelectedCount(This->hWndList);
1431
1432                 /* get selected item */
1433                 if(i == 1)
1434                 {
1435                   /* get selected item */
1436                   i = ListView_GetNextItem(This->hWndList, -1,
1437                         LVNI_SELECTED);
1438
1439                   ListView_EnsureVisible(This->hWndList, i, 0);
1440                   ListView_EditLabelA(This->hWndList, i);
1441                 }
1442               }
1443 #if 0
1444               TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1445 #endif
1446               else if(plvKeyDown->wVKey == VK_DELETE)
1447               {
1448                 UINT i;
1449                 int item_index;
1450                 LVITEMA item;
1451                 LPITEMIDLIST* pItems;
1452                 ISFHelper *psfhlp;
1453
1454                 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1455                         (LPVOID*)&psfhlp);
1456
1457                 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1458                   break;
1459
1460                 /* allocate memory for the pidl array */
1461                 pItems = HeapAlloc(GetProcessHeap(), 0,
1462                         sizeof(LPITEMIDLIST) * i);
1463
1464                 /* retrieve all selected items */
1465                 i = 0;
1466                 item_index = -1;
1467                 while(ListView_GetSelectedCount(This->hWndList) > i)
1468                 {
1469                   /* get selected item */
1470                   item_index = ListView_GetNextItem(This->hWndList,
1471                         item_index, LVNI_SELECTED);
1472                   item.iItem = item_index;
1473                   item.mask |= LVIF_PARAM;
1474                   ListView_GetItemA(This->hWndList, &item);
1475
1476                   /* get item pidl */
1477                   pItems[i] = (LPITEMIDLIST)item.lParam;
1478
1479                   i++;
1480                 }
1481
1482                 /* perform the item deletion */
1483                 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1484
1485                 /* free pidl array memory */
1486                 HeapFree(GetProcessHeap(), 0, pItems);
1487               }
1488               else
1489                 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1490             }
1491             break;
1492
1493           default:
1494             TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1495             break;
1496         }
1497         return 0;
1498 }
1499
1500 /**********************************************************
1501 * ShellView_OnChange()
1502 */
1503
1504 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1505 {
1506
1507         TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1508         switch(wEventId)
1509         {
1510           case SHCNE_MKDIR:
1511           case SHCNE_CREATE:
1512             LV_AddItem(This, Pidls[0]);
1513             break;
1514           case SHCNE_RMDIR:
1515           case SHCNE_DELETE:
1516             LV_DeleteItem(This, Pidls[0]);
1517             break;
1518           case SHCNE_RENAMEFOLDER:
1519           case SHCNE_RENAMEITEM:
1520             LV_RenameItem(This, Pidls[0], Pidls[1]);
1521             break;
1522           case SHCNE_UPDATEITEM:
1523             break;
1524         }
1525         return TRUE;
1526 }
1527 /**********************************************************
1528 *  ShellView_WndProc
1529 */
1530
1531 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1532 {
1533         IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1534         LPCREATESTRUCTA lpcs;
1535
1536         TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1537
1538         switch (uMessage)
1539         {
1540           case WM_NCCREATE:
1541             lpcs = (LPCREATESTRUCTA)lParam;
1542             pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1543             SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1544             pThis->hWnd = hWnd;        /*set the window handle*/
1545             break;
1546
1547           case WM_SIZE:         return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1548           case WM_SETFOCUS:     return ShellView_OnSetFocus(pThis);
1549           case WM_KILLFOCUS:    return ShellView_OnKillFocus(pThis);
1550           case WM_CREATE:       return ShellView_OnCreate(pThis);
1551           case WM_ACTIVATE:     return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1552           case WM_NOTIFY:       return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1553           case WM_COMMAND:      return ShellView_OnCommand(pThis,
1554                                         GET_WM_COMMAND_ID(wParam, lParam),
1555                                         GET_WM_COMMAND_CMD(wParam, lParam),
1556                                         GET_WM_COMMAND_HWND(wParam, lParam));
1557           case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1558
1559           case WM_CONTEXTMENU:  ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1560                                 return 0;
1561
1562           case WM_SHOWWINDOW:   UpdateWindow(pThis->hWndList);
1563                                 break;
1564
1565           case WM_GETDLGCODE:   return SendMessageA(pThis->hWndList,uMessage,0,0);
1566
1567           case WM_DESTROY:      
1568                                 RevokeDragDrop(pThis->hWnd);
1569                                 SHChangeNotifyDeregister(pThis->hNotify);
1570                                 break;
1571
1572           case WM_ERASEBKGND:
1573             if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1574                 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1575               return 1;
1576             break;
1577         }
1578
1579         return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1580 }
1581 /**********************************************************
1582 *
1583 *
1584 *  The INTERFACE of the IShellView object
1585 *
1586 *
1587 **********************************************************
1588 *  IShellView_QueryInterface
1589 */
1590 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1591 {
1592         IShellViewImpl *This = (IShellViewImpl *)iface;
1593
1594         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1595
1596         *ppvObj = NULL;
1597
1598         if(IsEqualIID(riid, &IID_IUnknown))
1599         {
1600           *ppvObj = This;
1601         }
1602         else if(IsEqualIID(riid, &IID_IShellView))
1603         {
1604           *ppvObj = (IShellView*)This;
1605         }
1606         else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1607         {
1608           *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1609         }
1610         else if(IsEqualIID(riid, &IID_IDropTarget))
1611         {
1612           *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1613         }
1614         else if(IsEqualIID(riid, &IID_IDropSource))
1615         {
1616           *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1617         }
1618         else if(IsEqualIID(riid, &IID_IViewObject))
1619         {
1620           *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1621         }
1622
1623         if(*ppvObj)
1624         {
1625           IUnknown_AddRef( (IUnknown*)*ppvObj );
1626           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1627           return S_OK;
1628         }
1629         TRACE("-- Interface: E_NOINTERFACE\n");
1630         return E_NOINTERFACE;
1631 }
1632
1633 /**********************************************************
1634 *  IShellView_AddRef
1635 */
1636 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1637 {
1638         IShellViewImpl *This = (IShellViewImpl *)iface;
1639         ULONG refCount = InterlockedIncrement(&This->ref);
1640
1641         TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1642
1643         return refCount;
1644 }
1645 /**********************************************************
1646 *  IShellView_Release
1647 */
1648 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1649 {
1650         IShellViewImpl *This = (IShellViewImpl *)iface;
1651         ULONG refCount = InterlockedDecrement(&This->ref);
1652
1653         TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1654
1655         if (!refCount)
1656         {
1657           TRACE(" destroying IShellView(%p)\n",This);
1658
1659           DestroyWindow(This->hWndList);
1660
1661           if(This->pSFParent)
1662             IShellFolder_Release(This->pSFParent);
1663
1664           if(This->pSF2Parent)
1665             IShellFolder2_Release(This->pSF2Parent);
1666
1667           if (This->apidl)
1668             SHFree(This->apidl);
1669
1670           HeapFree(GetProcessHeap(),0,This);
1671         }
1672         return refCount;
1673 }
1674
1675 /**********************************************************
1676 *  ShellView_GetWindow
1677 */
1678 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1679 {
1680         IShellViewImpl *This = (IShellViewImpl *)iface;
1681
1682         TRACE("(%p)\n",This);
1683
1684         *phWnd = This->hWnd;
1685
1686         return S_OK;
1687 }
1688
1689 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1690 {
1691         IShellViewImpl *This = (IShellViewImpl *)iface;
1692
1693         FIXME("(%p) stub\n",This);
1694
1695         return E_NOTIMPL;
1696 }
1697
1698 /**********************************************************
1699 * IShellView_TranslateAccelerator
1700 *
1701 * FIXME:
1702 *  use the accel functions
1703 */
1704 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1705 {
1706 #if 0
1707         IShellViewImpl *This = (IShellViewImpl *)iface;
1708
1709         FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1710 #endif
1711
1712         if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1713         {
1714           TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1715         }
1716         return S_FALSE; /* not handled */
1717 }
1718
1719 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1720 {
1721         IShellViewImpl *This = (IShellViewImpl *)iface;
1722
1723         FIXME("(%p) stub\n",This);
1724
1725         return E_NOTIMPL;
1726 }
1727
1728 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1729 {
1730         IShellViewImpl *This = (IShellViewImpl *)iface;
1731
1732 /*
1733         CHAR    szName[MAX_PATH];
1734 */
1735         LRESULT lResult;
1736         int     nPartArray[1] = {-1};
1737
1738         TRACE("(%p)->(state=%x) stub\n",This, uState);
1739
1740         /*don't do anything if the state isn't really changing*/
1741         if(This->uState == uState)
1742         {
1743           return S_OK;
1744         }
1745
1746         /*OnActivate handles the menu merging and internal state*/
1747         ShellView_OnActivate(This, uState);
1748
1749         /*only do This if we are active*/
1750         if(uState != SVUIA_DEACTIVATE)
1751         {
1752
1753 /*
1754           GetFolderPath is not a method of IShellFolder
1755           IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1756 */
1757           /* set the number of parts */
1758           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1759                                                         (LPARAM)nPartArray, &lResult);
1760
1761           /* set the text for the parts */
1762 /*
1763           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1764                                                         0, (LPARAM)szName, &lResult);
1765 */
1766         }
1767
1768         return S_OK;
1769 }
1770
1771 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1772 {
1773         IShellViewImpl *This = (IShellViewImpl *)iface;
1774
1775         TRACE("(%p)\n",This);
1776
1777         ListView_DeleteAllItems(This->hWndList);
1778         ShellView_FillList(This);
1779
1780         return S_OK;
1781 }
1782
1783 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1784         IShellView * iface,
1785         IShellView *lpPrevView,
1786         LPCFOLDERSETTINGS lpfs,
1787         IShellBrowser * psb,
1788         RECT * prcView,
1789         HWND  *phWnd)
1790 {
1791         IShellViewImpl *This = (IShellViewImpl *)iface;
1792
1793         WNDCLASSA wc;
1794         *phWnd = 0;
1795
1796
1797         TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1798         TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1799
1800         /*set up the member variables*/
1801         This->pShellBrowser = psb;
1802         This->FolderSettings = *lpfs;
1803
1804         /*get our parent window*/
1805         IShellBrowser_AddRef(This->pShellBrowser);
1806         IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1807
1808         /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1809         This->pCommDlgBrowser=NULL;
1810         if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1811                         (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1812         {
1813           TRACE("-- CommDlgBrowser\n");
1814         }
1815
1816         /*if our window class has not been registered, then do so*/
1817         if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1818         {
1819           ZeroMemory(&wc, sizeof(wc));
1820           wc.style              = CS_HREDRAW | CS_VREDRAW;
1821           wc.lpfnWndProc        = ShellView_WndProc;
1822           wc.cbClsExtra         = 0;
1823           wc.cbWndExtra         = 0;
1824           wc.hInstance          = shell32_hInstance;
1825           wc.hIcon              = 0;
1826           wc.hCursor            = LoadCursorA (0, (LPSTR)IDC_ARROW);
1827           wc.hbrBackground      = (HBRUSH) (COLOR_WINDOW + 1);
1828           wc.lpszMenuName       = NULL;
1829           wc.lpszClassName      = SV_CLASS_NAME;
1830
1831           if(!RegisterClassA(&wc))
1832             return E_FAIL;
1833         }
1834
1835         *phWnd = CreateWindowExA(0,
1836                                 SV_CLASS_NAME,
1837                                 NULL,
1838                                 WS_CHILD | WS_VISIBLE | WS_TABSTOP,
1839                                 prcView->left,
1840                                 prcView->top,
1841                                 prcView->right - prcView->left,
1842                                 prcView->bottom - prcView->top,
1843                                 This->hWndParent,
1844                                 0,
1845                                 shell32_hInstance,
1846                                 (LPVOID)This);
1847
1848         CheckToolbar(This);
1849
1850         if(!*phWnd) return E_FAIL;
1851
1852         return S_OK;
1853 }
1854
1855 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1856 {
1857         IShellViewImpl *This = (IShellViewImpl *)iface;
1858
1859         TRACE("(%p)\n",This);
1860
1861         /*Make absolutely sure all our UI is cleaned up.*/
1862         IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1863
1864         if(This->hMenu)
1865         {
1866           DestroyMenu(This->hMenu);
1867         }
1868
1869         DestroyWindow(This->hWnd);
1870         if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1871         if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1872
1873
1874         return S_OK;
1875 }
1876
1877 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1878 {
1879         IShellViewImpl *This = (IShellViewImpl *)iface;
1880
1881         TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1882                 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1883
1884         if (!lpfs) return E_INVALIDARG;
1885
1886         *lpfs = This->FolderSettings;
1887         return NOERROR;
1888 }
1889
1890 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1891 {
1892         IShellViewImpl *This = (IShellViewImpl *)iface;
1893
1894         FIXME("(%p) stub\n",This);
1895
1896         return E_NOTIMPL;
1897 }
1898
1899 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1900 {
1901         IShellViewImpl *This = (IShellViewImpl *)iface;
1902
1903         FIXME("(%p) stub\n",This);
1904
1905         return S_OK;
1906 }
1907
1908 static HRESULT WINAPI IShellView_fnSelectItem(
1909         IShellView * iface,
1910         LPCITEMIDLIST pidl,
1911         UINT uFlags)
1912 {
1913         IShellViewImpl *This = (IShellViewImpl *)iface;
1914         int i;
1915
1916         TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1917
1918         i = LV_FindItemByPidl(This, pidl);
1919
1920         if (i != -1)
1921         {
1922           LVITEMA lvItem;
1923
1924           if(uFlags & SVSI_ENSUREVISIBLE)
1925             ListView_EnsureVisible(This->hWndList, i, 0);
1926
1927           ZeroMemory(&lvItem, sizeof(LVITEMA));
1928           lvItem.mask = LVIF_STATE;
1929           lvItem.iItem = 0;
1930
1931           while(ListView_GetItemA(This->hWndList, &lvItem))
1932           {
1933             if (lvItem.iItem == i)
1934             {
1935               if (uFlags & SVSI_SELECT)
1936                 lvItem.state |= LVIS_SELECTED;
1937               else
1938                 lvItem.state &= ~LVIS_SELECTED;
1939
1940               if(uFlags & SVSI_FOCUSED)
1941                 lvItem.state &= ~LVIS_FOCUSED;
1942             }
1943             else
1944             {
1945               if (uFlags & SVSI_DESELECTOTHERS)
1946                 lvItem.state &= ~LVIS_SELECTED;
1947             }
1948             ListView_SetItemA(This->hWndList, &lvItem);
1949             lvItem.iItem++;
1950           }
1951
1952
1953           if(uFlags & SVSI_EDIT)
1954             ListView_EditLabelA(This->hWndList, i);
1955
1956         }
1957         return S_OK;
1958 }
1959
1960 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
1961 {
1962         IShellViewImpl *This = (IShellViewImpl *)iface;
1963
1964         TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
1965
1966         *ppvOut = NULL;
1967
1968         switch(uItem)
1969         {
1970           case SVGIO_BACKGROUND:
1971             *ppvOut = ISvBgCm_Constructor(This->pSFParent);
1972             break;
1973
1974           case SVGIO_SELECTION:
1975             ShellView_GetSelections(This);
1976             IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
1977             break;
1978         }
1979         TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
1980
1981         if(!*ppvOut) return E_OUTOFMEMORY;
1982
1983         return S_OK;
1984 }
1985
1986 static struct IShellViewVtbl svvt =
1987 {
1988         IShellView_fnQueryInterface,
1989         IShellView_fnAddRef,
1990         IShellView_fnRelease,
1991         IShellView_fnGetWindow,
1992         IShellView_fnContextSensitiveHelp,
1993         IShellView_fnTranslateAccelerator,
1994         IShellView_fnEnableModeless,
1995         IShellView_fnUIActivate,
1996         IShellView_fnRefresh,
1997         IShellView_fnCreateViewWindow,
1998         IShellView_fnDestroyViewWindow,
1999         IShellView_fnGetCurrentInfo,
2000         IShellView_fnAddPropertySheetPages,
2001         IShellView_fnSaveViewState,
2002         IShellView_fnSelectItem,
2003         IShellView_fnGetItemObject
2004 };
2005
2006
2007 /**********************************************************
2008  * ISVOleCmdTarget_QueryInterface (IUnknown)
2009  */
2010 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2011         IOleCommandTarget *     iface,
2012         REFIID                  iid,
2013         LPVOID*                 ppvObj)
2014 {
2015         _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface);
2016
2017         return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2018 }
2019
2020 /**********************************************************
2021  * ISVOleCmdTarget_AddRef (IUnknown)
2022  */
2023 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2024         IOleCommandTarget *     iface)
2025 {
2026         _ICOM_THIS_From_IOleCommandTarget(IShellFolder, iface);
2027
2028         return IShellFolder_AddRef((IShellFolder*)This);
2029 }
2030
2031 /**********************************************************
2032  * ISVOleCmdTarget_Release (IUnknown)
2033  */
2034 static ULONG WINAPI ISVOleCmdTarget_Release(
2035         IOleCommandTarget *     iface)
2036 {
2037         _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface);
2038
2039         return IShellFolder_Release((IShellFolder*)This);
2040 }
2041
2042 /**********************************************************
2043  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2044  */
2045 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2046         IOleCommandTarget *iface,
2047         const GUID* pguidCmdGroup,
2048         ULONG cCmds,
2049         OLECMD * prgCmds,
2050         OLECMDTEXT* pCmdText)
2051 {
2052     UINT i;
2053     _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface);
2054
2055     FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2056               This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2057
2058     if (!prgCmds)
2059         return E_POINTER;
2060     for (i = 0; i < cCmds; i++)
2061     {
2062         FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2063         prgCmds[i].cmdf = 0;
2064     }
2065     return OLECMDERR_E_UNKNOWNGROUP;
2066 }
2067
2068 /**********************************************************
2069  * ISVOleCmdTarget_Exec (IOleCommandTarget)
2070  *
2071  * nCmdID is the OLECMDID_* enumeration
2072  */
2073 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2074         IOleCommandTarget *iface,
2075         const GUID* pguidCmdGroup,
2076         DWORD nCmdID,
2077         DWORD nCmdexecopt,
2078         VARIANT* pvaIn,
2079         VARIANT* pvaOut)
2080 {
2081         _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface);
2082
2083         FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2084               This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2085
2086         if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2087            (nCmdID == 0x29) &&
2088            (nCmdexecopt == 4) && pvaOut)
2089            return S_OK;
2090         if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2091            (nCmdID == 9) &&
2092            (nCmdexecopt == 0))
2093            return 1;
2094
2095         return OLECMDERR_E_UNKNOWNGROUP;
2096 }
2097
2098 static IOleCommandTargetVtbl ctvt =
2099 {
2100         ISVOleCmdTarget_QueryInterface,
2101         ISVOleCmdTarget_AddRef,
2102         ISVOleCmdTarget_Release,
2103         ISVOleCmdTarget_QueryStatus,
2104         ISVOleCmdTarget_Exec
2105 };
2106
2107 /**********************************************************
2108  * ISVDropTarget implementation
2109  */
2110
2111 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2112         IDropTarget *iface,
2113         REFIID riid,
2114         LPVOID *ppvObj)
2115 {
2116         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2117
2118         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2119
2120         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2121 }
2122
2123 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2124 {
2125         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2126
2127         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2128
2129         return IShellFolder_AddRef((IShellFolder*)This);
2130 }
2131
2132 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2133 {
2134         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2135
2136         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2137
2138         return IShellFolder_Release((IShellFolder*)This);
2139 }
2140
2141 static HRESULT WINAPI ISVDropTarget_DragEnter(
2142         IDropTarget     *iface,
2143         IDataObject     *pDataObject,
2144         DWORD           grfKeyState,
2145         POINTL          pt,
2146         DWORD           *pdwEffect)
2147 {
2148
2149         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2150
2151         FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
2152
2153         return E_NOTIMPL;
2154 }
2155
2156 static HRESULT WINAPI ISVDropTarget_DragOver(
2157         IDropTarget     *iface,
2158         DWORD           grfKeyState,
2159         POINTL          pt,
2160         DWORD           *pdwEffect)
2161 {
2162         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2163
2164         FIXME("Stub: This=%p\n",This);
2165
2166         return E_NOTIMPL;
2167 }
2168
2169 static HRESULT WINAPI ISVDropTarget_DragLeave(
2170         IDropTarget     *iface)
2171 {
2172         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2173
2174         FIXME("Stub: This=%p\n",This);
2175
2176         return E_NOTIMPL;
2177 }
2178
2179 static HRESULT WINAPI ISVDropTarget_Drop(
2180         IDropTarget     *iface,
2181         IDataObject*    pDataObject,
2182         DWORD           grfKeyState,
2183         POINTL          pt,
2184         DWORD           *pdwEffect)
2185 {
2186         _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface);
2187
2188         FIXME("Stub: This=%p\n",This);
2189
2190         return E_NOTIMPL;
2191 }
2192
2193 static struct IDropTargetVtbl dtvt =
2194 {
2195         ISVDropTarget_QueryInterface,
2196         ISVDropTarget_AddRef,
2197         ISVDropTarget_Release,
2198         ISVDropTarget_DragEnter,
2199         ISVDropTarget_DragOver,
2200         ISVDropTarget_DragLeave,
2201         ISVDropTarget_Drop
2202 };
2203
2204 /**********************************************************
2205  * ISVDropSource implementation
2206  */
2207
2208 static HRESULT WINAPI ISVDropSource_QueryInterface(
2209         IDropSource *iface,
2210         REFIID riid,
2211         LPVOID *ppvObj)
2212 {
2213         _ICOM_THIS_From_IDropSource(IShellViewImpl, iface);
2214
2215         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2216
2217         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2218 }
2219
2220 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2221 {
2222         _ICOM_THIS_From_IDropSource(IShellViewImpl, iface);
2223
2224         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2225
2226         return IShellFolder_AddRef((IShellFolder*)This);
2227 }
2228
2229 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2230 {
2231         _ICOM_THIS_From_IDropSource(IShellViewImpl, iface);
2232
2233         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2234
2235         return IShellFolder_Release((IShellFolder*)This);
2236 }
2237 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2238         IDropSource *iface,
2239         BOOL fEscapePressed,
2240         DWORD grfKeyState)
2241 {
2242         _ICOM_THIS_From_IDropSource(IShellViewImpl, iface);
2243         TRACE("(%p)\n",This);
2244
2245         if (fEscapePressed)
2246           return DRAGDROP_S_CANCEL;
2247         else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2248           return DRAGDROP_S_DROP;
2249         else
2250           return NOERROR;
2251 }
2252
2253 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2254         IDropSource *iface,
2255         DWORD dwEffect)
2256 {
2257         _ICOM_THIS_From_IDropSource(IShellViewImpl, iface);
2258         TRACE("(%p)\n",This);
2259
2260         return DRAGDROP_S_USEDEFAULTCURSORS;
2261 }
2262
2263 static struct IDropSourceVtbl dsvt =
2264 {
2265         ISVDropSource_QueryInterface,
2266         ISVDropSource_AddRef,
2267         ISVDropSource_Release,
2268         ISVDropSource_QueryContinueDrag,
2269         ISVDropSource_GiveFeedback
2270 };
2271 /**********************************************************
2272  * ISVViewObject implementation
2273  */
2274
2275 static HRESULT WINAPI ISVViewObject_QueryInterface(
2276         IViewObject *iface,
2277         REFIID riid,
2278         LPVOID *ppvObj)
2279 {
2280         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2281
2282         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2283
2284         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2285 }
2286
2287 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2288 {
2289         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2290
2291         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2292
2293         return IShellFolder_AddRef((IShellFolder*)This);
2294 }
2295
2296 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2297 {
2298         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2299
2300         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2301
2302         return IShellFolder_Release((IShellFolder*)This);
2303 }
2304
2305 static HRESULT WINAPI ISVViewObject_Draw(
2306         IViewObject     *iface,
2307         DWORD dwDrawAspect,
2308         LONG lindex,
2309         void* pvAspect,
2310         DVTARGETDEVICE* ptd,
2311         HDC hdcTargetDev,
2312         HDC hdcDraw,
2313         LPCRECTL lprcBounds,
2314         LPCRECTL lprcWBounds,
2315         BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2316         ULONG_PTR dwContinue)
2317 {
2318
2319         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2320
2321         FIXME("Stub: This=%p\n",This);
2322
2323         return E_NOTIMPL;
2324 }
2325 static HRESULT WINAPI ISVViewObject_GetColorSet(
2326         IViewObject     *iface,
2327         DWORD dwDrawAspect,
2328         LONG lindex,
2329         void *pvAspect,
2330         DVTARGETDEVICE* ptd,
2331         HDC hicTargetDevice,
2332         LOGPALETTE** ppColorSet)
2333 {
2334
2335         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2336
2337         FIXME("Stub: This=%p\n",This);
2338
2339         return E_NOTIMPL;
2340 }
2341 static HRESULT WINAPI ISVViewObject_Freeze(
2342         IViewObject     *iface,
2343         DWORD dwDrawAspect,
2344         LONG lindex,
2345         void* pvAspect,
2346         DWORD* pdwFreeze)
2347 {
2348
2349         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2350
2351         FIXME("Stub: This=%p\n",This);
2352
2353         return E_NOTIMPL;
2354 }
2355 static HRESULT WINAPI ISVViewObject_Unfreeze(
2356         IViewObject     *iface,
2357         DWORD dwFreeze)
2358 {
2359
2360         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2361
2362         FIXME("Stub: This=%p\n",This);
2363
2364         return E_NOTIMPL;
2365 }
2366 static HRESULT WINAPI ISVViewObject_SetAdvise(
2367         IViewObject     *iface,
2368         DWORD aspects,
2369         DWORD advf,
2370         IAdviseSink* pAdvSink)
2371 {
2372
2373         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2374
2375         FIXME("Stub: This=%p\n",This);
2376
2377         return E_NOTIMPL;
2378 }
2379 static HRESULT WINAPI ISVViewObject_GetAdvise(
2380         IViewObject     *iface,
2381         DWORD* pAspects,
2382         DWORD* pAdvf,
2383         IAdviseSink** ppAdvSink)
2384 {
2385
2386         _ICOM_THIS_From_IViewObject(IShellViewImpl, iface);
2387
2388         FIXME("Stub: This=%p\n",This);
2389
2390         return E_NOTIMPL;
2391 }
2392
2393
2394 static struct IViewObjectVtbl vovt =
2395 {
2396         ISVViewObject_QueryInterface,
2397         ISVViewObject_AddRef,
2398         ISVViewObject_Release,
2399         ISVViewObject_Draw,
2400         ISVViewObject_GetColorSet,
2401         ISVViewObject_Freeze,
2402         ISVViewObject_Unfreeze,
2403         ISVViewObject_SetAdvise,
2404         ISVViewObject_GetAdvise
2405 };