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