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