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