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