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