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