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