source: trunk/src/comdlg32/filedlg95.c@ 4511

Last change on this file since 4511 was 4511, checked in by sandervl, 25 years ago

Merged with latest Wine version (Wine 20001002 level (10-21-2000))

File size: 78.3 KB
Line 
1/*
2 * COMMDLG - File Open Dialogs Win95 look and feel
3 *
4 * FIXME: lpstrCustomFilter not handled
5 *
6 * FIXME: if the size of lpstrFile (nMaxFile) is to small the first
7 * two bytes of lpstrFile should contain the needed size
8 *
9 * FIXME: algorithm for selecting the initial directory is too simple
10 *
11 * FIXME: add to recent docs
12 *
13 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
14 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING, OFN_EXTENSIONDIFFERENT,
15 * OFN_NOCHANGEDIR, OFN_NODEREFERENCELINKS, OFN_READONLYRETURN,
16 * OFN_NOTESTFILECREATE, OFN_OVERWRITEPROMPT, OFN_USEMONIKERS
17 *
18 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
19 *
20 *
21 */
22#ifdef __WIN32OS2__
23#include <windef.h>
24#include <winbase.h>
25#include <wingdi.h>
26#include <winuser.h>
27#include <heapstring.h>
28#include <misc.h>
29#include <win\shlwapi.h>
30
31#define MapHModuleSL(a) a
32#define MapHModuleLS(a) a
33
34#endif
35
36#include <ctype.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40
41#include "winbase.h"
42#include "ntddk.h"
43#include "wine/winestring.h"
44#include "ldt.h"
45#include "heap.h"
46#include "commdlg.h"
47#include "dlgs.h"
48#include "cdlg.h"
49#include "debugtools.h"
50#include "cderr.h"
51#include "tweak.h"
52#include "winnls.h"
53#include "shellapi.h"
54#include "shlguid.h"
55#include "filedlgbrowser.h"
56#include "shlwapi.h"
57#include "wine/obj_contextmenu.h"
58
59DEFAULT_DEBUG_CHANNEL(commdlg);
60
61/***********************************************************************
62 * Data structure and global variables
63 */
64typedef struct SFolder
65{
66 int m_iImageIndex; /* Index of picture in image list */
67 HIMAGELIST hImgList;
68 int m_iIndent; /* Indentation index */
69 LPITEMIDLIST pidlItem; /* absolute pidl of the item */
70
71} SFOLDER,*LPSFOLDER;
72
73typedef struct tagLookInInfo
74{
75 int iMaxIndentation;
76 UINT uSelectedItem;
77} LookInInfos;
78
79
80/***********************************************************************
81 * Defines and global variables
82 */
83
84/* Draw item constant */
85#define ICONWIDTH 18
86#define YTEXTOFFSET 2
87#define XTEXTOFFSET 3
88
89/* AddItem flags*/
90#define LISTEND -1
91
92/* SearchItem methods */
93#define SEARCH_PIDL 1
94#define SEARCH_EXP 2
95#define ITEM_NOTFOUND -1
96
97/* Undefined windows message sent by CreateViewObject*/
98#define WM_GETISHELLBROWSER WM_USER+7
99
100/* NOTE
101 * Those macros exist in windowsx.h. However, you can't really use them since
102 * they rely on the UNICODE defines and can't be use inside Wine itself.
103 */
104
105/* Combo box macros */
106#define CBAddString(hwnd,str) \
107 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
108
109#define CBInsertString(hwnd,str,pos) \
110 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
111
112#define CBDeleteString(hwnd,pos) \
113 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
114
115#define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
116 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
117
118#define CBGetItemDataPtr(hwnd,iItemId) \
119 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
120
121#define CBGetLBText(hwnd,iItemId,str) \
122 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
123
124#define CBGetCurSel(hwnd) \
125 SendMessageA(hwnd,CB_GETCURSEL,0,0);
126
127#define CBSetCurSel(hwnd,pos) \
128 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
129
130#define CBGetCount(hwnd) \
131 SendMessageA(hwnd,CB_GETCOUNT,0,0);
132#define CBShowDropDown(hwnd,show) \
133 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
134#define CBSetItemHeight(hwnd,index,height) \
135 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
136
137
138const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
139const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
140
141static const char defaultFilter[] = "*.*";
142
143/***********************************************************************
144 * Prototypes
145 */
146
147/* Internal functions used by the dialog */
148static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam);
149static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
150static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
151 BOOL FILEDLG95_OnOpen(HWND hwnd);
152static LRESULT FILEDLG95_InitUI(HWND hwnd);
153static void FILEDLG95_Clean(HWND hwnd);
154
155/* Functions used by the shell navigation */
156static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
157static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
158static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
159static void FILEDLG95_SHELL_Clean(HWND hwnd);
160static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd);
161
162/* Functions used by the filetype combo box */
163static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
164static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
165static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCSTR lpstrExt);
166static void FILEDLG95_FILETYPE_Clean(HWND hwnd);
167
168/* Functions used by the Look In combo box */
169static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo);
170static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
171static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
172static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
173static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
174static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
175static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
176 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
177static void FILEDLG95_LOOKIN_Clean(HWND hwnd);
178
179/* Miscellaneous tool functions */
180HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
181HRESULT GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
182IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
183LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
184LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
185
186/* Shell memory allocation */
187static void *MemAlloc(UINT size);
188static void MemFree(void *mem);
189
190BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos);
191HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
192HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode);
193HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
194BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed);
195static BOOL BrowseSelectedFolder(HWND hwnd);
196
197/***********************************************************************
198 * GetFileName95
199 *
200 * Creates an Open common dialog box that lets the user select
201 * the drive, directory, and the name of a file or set of files to open.
202 *
203 * IN : The FileOpenDlgInfos structure associated with the dialog
204 * OUT : TRUE on success
205 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
206 */
207BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos)
208{
209
210 LRESULT lRes;
211 LPCVOID template;
212 HRSRC hRes;
213 HANDLE hDlgTmpl = 0;
214
215 /* Create the dialog from a template */
216
217 if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(NEWFILEOPENORD),RT_DIALOGA)))
218 {
219 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
220 return FALSE;
221 }
222 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
223 !(template = LockResource( hDlgTmpl )))
224 {
225 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
226 return FALSE;
227 }
228 lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
229 (LPDLGTEMPLATEA) template,
230 fodInfos->ofnInfos->hwndOwner,
231 (DLGPROC) FileOpenDlgProc95,
232 (LPARAM) fodInfos);
233
234 /* Unable to create the dialog*/
235 if( lRes == -1)
236 return FALSE;
237
238 return lRes;
239}
240
241/***********************************************************************
242 * GetFileDialog95A
243 *
244 * Call GetFileName95 with this structure and clean the memory.
245 *
246 * IN : The OPENFILENAMEA initialisation structure passed to
247 * GetOpenFileNameA win api function (see filedlg.c)
248 */
249BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
250{
251
252 BOOL ret;
253 FileOpenDlgInfos *fodInfos;
254 HINSTANCE hInstance;
255 LPCSTR lpstrInitialDir = (LPCSTR)-1;
256 DWORD dwFlags = 0;
257
258 /* Initialise FileOpenDlgInfos structure*/
259 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
260 ZeroMemory(fodInfos, sizeof(FileOpenDlgInfos));
261
262 /* Pass in the original ofn */
263 fodInfos->ofnInfos = ofn;
264
265 /* Save original hInstance value */
266 hInstance = ofn->hInstance;
267 fodInfos->ofnInfos->hInstance = MapHModuleLS(ofn->hInstance);
268
269 dwFlags = ofn->Flags;
270 ofn->Flags = ofn->Flags|OFN_WINE;
271
272 /* Replace the NULL lpstrInitialDir by the current folder */
273 if(!ofn->lpstrInitialDir)
274 {
275 lpstrInitialDir = ofn->lpstrInitialDir;
276 ofn->lpstrInitialDir = MemAlloc(MAX_PATH);
277 GetCurrentDirectoryA(MAX_PATH,(LPSTR)ofn->lpstrInitialDir);
278 }
279
280 /* Initialise the dialog property */
281 fodInfos->DlgInfos.dwDlgProp = 0;
282 fodInfos->DlgInfos.hwndCustomDlg = (HWND)NULL;
283
284 switch(iDlgType)
285 {
286 case OPEN_DIALOG :
287 ret = GetFileName95(fodInfos);
288 break;
289 case SAVE_DIALOG :
290 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
291 ret = GetFileName95(fodInfos);
292 break;
293 default :
294 ret = 0;
295 }
296
297 if (lpstrInitialDir != (LPCSTR)-1)
298 {
299 MemFree((LPVOID)(ofn->lpstrInitialDir));
300 ofn->lpstrInitialDir = lpstrInitialDir;
301 }
302
303 ofn->Flags = dwFlags;
304 ofn->hInstance = hInstance;
305 MemFree((LPVOID)(fodInfos));
306 return ret;
307}
308
309/***********************************************************************
310 * GetFileDialog95W
311 *
312 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
313 * Call GetFileName95 with this structure and clean the memory.
314 *
315 * IN : The OPENFILENAMEW initialisation structure passed to
316 * GetOpenFileNameW win api function (see filedlg.c)
317 *
318 * FIXME:
319 * some more strings are needing to be convertet AtoW
320 */
321BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
322{
323 BOOL ret;
324 FileOpenDlgInfos *fodInfos;
325 HINSTANCE hInstance;
326 LPCSTR lpstrFilter = NULL;
327 LPSTR lpstrCustomFilter = NULL;
328#ifdef __WIN32OS2__
329 LPWSTR lpstrInitialDir = NULL;
330 LPWSTR lpstrTitle = NULL;
331#endif
332 LPWSTR lpstrFile = NULL;
333 DWORD dwFlags;
334
335 /* Initialise FileOpenDlgInfos structure*/
336 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
337 ZeroMemory(fodInfos, sizeof(FileOpenDlgInfos));
338
339 /* Pass in the original ofn */
340 fodInfos->ofnInfos = (LPOPENFILENAMEA) ofn;
341
342 /* Save hInstance */
343 hInstance = fodInfos->ofnInfos->hInstance;
344 fodInfos->ofnInfos->hInstance = MapHModuleLS(ofn->hInstance);
345
346 /* Save lpstrFilter */
347 if (ofn->lpstrFilter)
348 {
349 LPWSTR s;
350 LPSTR x,y;
351 int n;
352
353 lpstrFilter = fodInfos->ofnInfos->lpstrFilter;
354
355 /* filter is a list... title\0ext\0......\0\0 */
356 s = (LPWSTR)ofn->lpstrFilter;
357
358 while (*s)
359 s = s+lstrlenW(s)+1;
360 s++;
361 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
362 x = y = (LPSTR)MemAlloc(n);
363 s = (LPWSTR)ofn->lpstrFilter;
364 while (*s) {
365 lstrcpyWtoA(x,s);
366 x+=strlen(x)+1;
367 s+=lstrlenW(s)+1;
368 }
369 *x=0;
370 fodInfos->ofnInfos->lpstrFilter = (LPSTR)y;
371 }
372 /* Save lpstrCustomFilter */
373 if (ofn->lpstrCustomFilter)
374 {
375 LPWSTR s;
376 LPSTR x,y;
377 int n;
378
379 lpstrCustomFilter = fodInfos->ofnInfos->lpstrCustomFilter;
380 /* filter is a list... title\0ext\0......\0\0 */
381 s = (LPWSTR)ofn->lpstrCustomFilter;
382 while (*s)
383 s = s+lstrlenW(s)+1;
384 s++;
385 n = s - ofn->lpstrCustomFilter;
386 x = y = (LPSTR)MemAlloc(n);
387 s = (LPWSTR)ofn->lpstrCustomFilter;
388 while (*s) {
389 lstrcpyWtoA(x,s);
390 x+=strlen(x)+1;
391 s+=lstrlenW(s)+1;
392 }
393 *x=0;
394 fodInfos->ofnInfos->lpstrCustomFilter = (LPSTR)y;
395 }
396
397 /* Save Flags */
398 dwFlags = fodInfos->ofnInfos->Flags;
399 fodInfos->ofnInfos->Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
400
401 /* Initialise the dialog property */
402 fodInfos->DlgInfos.dwDlgProp = 0;
403
404 /* allocate ansi filename buffer */
405 lpstrFile = ofn->lpstrFile;
406 ofn->lpstrFile = MemAlloc(ofn->nMaxFile);
407
408#ifdef __WIN32OS2__
409 // convert initial dir & title (if necessary)
410 lpstrInitialDir = (LPWSTR)ofn->lpstrInitialDir;
411 if(lpstrInitialDir && *lpstrInitialDir != 0) {
412 ofn->lpstrInitialDir = MemAlloc(lstrlenW(ofn->lpstrInitialDir)+1);
413 lstrcpyWtoA((LPSTR)ofn->lpstrInitialDir, lpstrInitialDir);
414 }
415 else
416 /* Replace the NULL lpstrInitialDir by the current folder */
417 if(!lpstrInitialDir || *lpstrInitialDir == 0)
418 {
419 ofn->lpstrInitialDir = MemAlloc(MAX_PATH);
420 GetCurrentDirectoryA(MAX_PATH,(LPSTR)ofn->lpstrInitialDir);
421 }
422
423 lpstrTitle = (LPWSTR)ofn->lpstrTitle;
424 if(lpstrTitle) {
425 ofn->lpstrTitle = MemAlloc(lstrlenW(ofn->lpstrTitle)+1);
426 lstrcpyWtoA((LPSTR)ofn->lpstrTitle, lpstrTitle);
427 }
428
429#endif
430
431 switch(iDlgType)
432 {
433 case OPEN_DIALOG :
434 ret = GetFileName95(fodInfos);
435 break;
436 case SAVE_DIALOG :
437 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
438 ret = GetFileName95(fodInfos);
439 break;
440 default :
441 ret = 0;
442 }
443
444 /* Cleaning */
445 /* Restore Flags */
446 fodInfos->ofnInfos->Flags = dwFlags;
447
448 /* Restore lpstrFilter */
449 if (fodInfos->ofnInfos->lpstrFilter)
450 {
451 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrFilter));
452 fodInfos->ofnInfos->lpstrFilter = lpstrFilter;
453 }
454 if (fodInfos->ofnInfos->lpstrCustomFilter)
455 {
456 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrCustomFilter));
457 fodInfos->ofnInfos->lpstrCustomFilter = lpstrCustomFilter;
458 }
459
460 /* Restore hInstance */
461 fodInfos->ofnInfos->hInstance = hInstance;
462 MemFree((LPVOID)(fodInfos));
463
464 /* filename */
465 lstrcpynAtoW(lpstrFile, (LPCSTR)ofn->lpstrFile, ofn->nMaxFile);
466 MemFree(ofn->lpstrFile);
467 ofn->lpstrFile = lpstrFile;
468
469#ifdef __WIN32OS2__
470 //free converted initial dir & title strings
471 if(lpstrInitialDir) {
472 MemFree((LPVOID)ofn->lpstrInitialDir);
473 ofn->lpstrInitialDir = (LPCWSTR)lpstrInitialDir;
474 }
475 if(lpstrTitle) {
476 MemFree((LPVOID)ofn->lpstrTitle);
477 ofn->lpstrTitle = (LPCWSTR)lpstrTitle;
478 }
479#endif
480
481 return ret;
482}
483
484void ArrangeCtrlPositions( HWND hwndChildDlg, HWND hwndParentDlg)
485{
486
487 HWND hwndChild,hwndStc32;
488 RECT rectParent, rectChild, rectCtrl, rectStc32, rectTemp;
489 POINT ptMoveCtl;
490 POINT ptParentClient;
491
492 ptMoveCtl.x = ptMoveCtl.y = 0;
493 hwndStc32=GetDlgItem(hwndChildDlg,stc32);
494 GetClientRect(hwndParentDlg,&rectParent);
495 GetClientRect(hwndChildDlg,&rectChild);
496 if(hwndStc32)
497 {
498 GetWindowRect(hwndStc32,&rectStc32);
499 MapWindowPoints(0, hwndChildDlg,(LPPOINT)&rectStc32,2);
500 CopyRect(&rectTemp,&rectStc32);
501
502 SetRect(&rectStc32,rectStc32.left,rectStc32.top,rectStc32.left + (rectParent.right-rectParent.left),rectStc32.top+(rectParent.bottom-rectParent.top));
503 SetWindowPos(hwndStc32,0,rectStc32.left,rectStc32.top,rectStc32.right-rectStc32.left,rectStc32.bottom-rectStc32.top,SWP_NOMOVE|SWP_NOZORDER | SWP_NOACTIVATE);
504
505 if(rectStc32.right < rectTemp.right)
506 {
507 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
508 ptMoveCtl.x = 0;
509 }
510 else
511 {
512 ptMoveCtl.x = (rectStc32.right - rectTemp.right);
513 ptParentClient.x = max((rectParent.right-rectParent.left),((rectChild.right-rectChild.left)+rectStc32.right-rectTemp.right));
514 }
515 if(rectStc32.bottom < rectTemp.bottom)
516 {
517 ptParentClient.y = max((rectParent.bottom-rectParent.top),(rectChild.bottom-rectChild.top));
518 ptMoveCtl.y = 0;
519 }
520 else
521 {
522 ptMoveCtl.y = (rectStc32.bottom - rectTemp.bottom);
523 ptParentClient.y = max((rectParent.bottom-rectParent.top),((rectChild.bottom-rectChild.top)+rectStc32.bottom-rectTemp.bottom));
524 }
525 }
526 else
527 {
528 if( (GetWindow(hwndChildDlg,GW_CHILD)) == (HWND) NULL)
529 return;
530 SetRectEmpty(&rectTemp);
531 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
532 ptParentClient.y = (rectParent.bottom-rectParent.top) + (rectChild.bottom-rectChild.top);
533 ptMoveCtl.y = rectParent.bottom-rectParent.top;
534 ptMoveCtl.x=0;
535 }
536 SetRect(&rectParent,rectParent.left,rectParent.top,rectParent.left+ptParentClient.x,rectParent.top+ptParentClient.y);
537 AdjustWindowRectEx( &rectParent,GetWindowLongA(hwndParentDlg,GWL_STYLE),FALSE,GetWindowLongA(hwndParentDlg,GWL_EXSTYLE));
538
539 SetWindowPos(hwndChildDlg, 0, 0,0, ptParentClient.x,ptParentClient.y,
540 SWP_NOZORDER );
541 SetWindowPos(hwndParentDlg, 0, rectParent.left,rectParent.top, (rectParent.right- rectParent.left),
542 (rectParent.bottom-rectParent.top),SWP_NOMOVE | SWP_NOZORDER);
543
544 hwndChild = GetWindow(hwndChildDlg,GW_CHILD);
545 if(hwndStc32)
546 {
547 GetWindowRect(hwndStc32,&rectStc32);
548 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
549 }
550 else
551 SetRect(&rectStc32,0,0,0,0);
552
553 if (hwndChild )
554 {
555 do
556 {
557 if(hwndChild != hwndStc32)
558 {
559 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
560 continue;
561 GetWindowRect(hwndChild,&rectCtrl);
562 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
563
564 /*
565 Check the initial position of the controls relative to the initial
566 position and size of stc32 (before it is expanded).
567 */
568 if (rectCtrl.left >= rectTemp.right && rectCtrl.top >= rectTemp.bottom)
569 {
570 rectCtrl.left += ptMoveCtl.x;
571 rectCtrl.top += ptMoveCtl.y;
572 }
573 else if (rectCtrl.left >= rectTemp.right)
574 rectCtrl.left += ptMoveCtl.x;
575 else if (rectCtrl.top >= rectTemp.bottom)
576 rectCtrl.top += ptMoveCtl.y;
577
578 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
579 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
580 SWP_NOSIZE | SWP_NOZORDER );
581 }
582 }
583 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
584 }
585 hwndChild = GetWindow(hwndParentDlg,GW_CHILD);
586
587 if(hwndStc32)
588 {
589 GetWindowRect(hwndStc32,&rectStc32);
590 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
591 ptMoveCtl.x = rectStc32.left - 0;
592 ptMoveCtl.y = rectStc32.top - 0;
593 if (hwndChild )
594 {
595 do
596 {
597 if(hwndChild != hwndChildDlg)
598 {
599
600 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
601 continue;
602 GetWindowRect(hwndChild,&rectCtrl);
603 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
604
605 rectCtrl.left += ptMoveCtl.x;
606 rectCtrl.top += ptMoveCtl.y;
607
608 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
609 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
610 SWP_NOSIZE |SWP_NOZORDER );
611 }
612 }
613 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
614 }
615 }
616
617}
618
619
620HRESULT WINAPI FileOpenDlgProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
621{
622 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(GetParent(hwnd),FileOpenDlgInfosStr);
623 switch(uMsg)
624 {
625 case WM_INITDIALOG:
626 {
627 fodInfos = (FileOpenDlgInfos *)lParam;
628 lParam = (LPARAM) fodInfos->ofnInfos;
629 ArrangeCtrlPositions(hwnd,GetParent(hwnd));
630 if(fodInfos && (fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
631 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
632 return 0;
633 }
634 }
635 if(fodInfos && (fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook )
636 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
637 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
638}
639
640HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos,HWND hwnd)
641{
642 LPCVOID template;
643 HRSRC hRes;
644 HANDLE hDlgTmpl = 0;
645 HWND hChildDlg = 0;
646 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATE || fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
647 {
648 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
649 {
650 if( !(template = LockResource( fodInfos->ofnInfos->hInstance)))
651 {
652 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
653 return (HWND)NULL;
654 }
655
656 }
657 else
658 {
659 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos->hInstance),
660 (fodInfos->ofnInfos->lpTemplateName), RT_DIALOGA)))
661 {
662 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
663 return (HWND)NULL;
664 }
665 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos->hInstance),
666 hRes )) ||
667 !(template = LockResource( hDlgTmpl )))
668 {
669 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
670 return (HWND)NULL;
671 }
672 }
673
674 hChildDlg= CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,template,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
675 if(hChildDlg)
676 {
677 ShowWindow(hChildDlg,SW_SHOW);
678 return hChildDlg;
679 }
680 }
681 else if(fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK && fodInfos->ofnInfos->lpfnHook)
682 {
683 RECT rectHwnd;
684 DLGTEMPLATE tmplate;
685 GetClientRect(hwnd,&rectHwnd);
686 tmplate.style = WS_CHILD | WS_CLIPSIBLINGS;
687 tmplate.dwExtendedStyle = 0;
688 tmplate.cdit = 0;
689 tmplate.x = 0;
690 tmplate.y = 0;
691 tmplate.cx = rectHwnd.right-rectHwnd.left;
692 tmplate.cy = rectHwnd.bottom-rectHwnd.top;
693
694 return CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,&tmplate,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
695 }
696return (HWND)NULL;
697}
698
699/***********************************************************************
700* SendCustomDlgNotificationMessage
701*
702* Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
703*/
704
705HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode)
706{
707 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndParentDlg,FileOpenDlgInfosStr);
708 if(!fodInfos)
709 return 0;
710 if(fodInfos->DlgInfos.hwndCustomDlg)
711 {
712 OFNOTIFYA ofnNotify;
713 ofnNotify.hdr.hwndFrom=hwndParentDlg;
714 ofnNotify.hdr.idFrom=0;
715 ofnNotify.hdr.code = uCode;
716 ofnNotify.lpOFN = fodInfos->ofnInfos;
717 return SendMessageA(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify);
718 }
719 return TRUE;
720}
721
722/***********************************************************************
723* FILEDLG95_HandleCustomDialogMessages
724*
725* Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
726*/
727HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
728{
729 LPSTR lpstrFileSpec;
730 int reqSize;
731 char lpstrPath[MAX_PATH];
732 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
733 if(!fodInfos) return -1;
734
735 switch(uMsg)
736 {
737 case CDM_GETFILEPATH:
738 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
739 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFileNameA(lpstrPath);
740 if (lpstrFileSpec==lpstrPath)
741 {
742 char lpstrCurrentDir[MAX_PATH];
743 /* Prepend the current path */
744 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrCurrentDir);
745 if ((LPSTR)lParam!=NULL)
746 wsnprintfA((LPSTR)lParam,(int)wParam,"%s\\%s",lpstrCurrentDir,lpstrPath);
747 reqSize=strlen(lpstrCurrentDir)+1+strlen(lpstrPath)+1;
748 }
749 else
750 {
751 lstrcpynA((LPSTR)lParam,(LPSTR)lpstrPath,(int)wParam);
752 reqSize=strlen(lpstrPath);
753 }
754 /* return the required buffer size */
755 return reqSize;
756
757 case CDM_GETFOLDERPATH:
758 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrPath);
759 if ((LPSTR)lParam!=NULL)
760 lstrcpynA((LPSTR)lParam,lpstrPath,(int)wParam);
761 return strlen(lpstrPath);
762
763 case CDM_GETSPEC:
764 reqSize=GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
765 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFileNameA(lpstrPath);
766 if ((LPSTR)lParam!=NULL)
767 lstrcpynA((LPSTR)lParam, lpstrFileSpec, (int)wParam);
768 return strlen(lpstrFileSpec);
769
770 case CDM_SETCONTROLTEXT:
771 if ( 0 != lParam )
772 SetDlgItemTextA( hwnd, (UINT) wParam, (LPSTR) lParam );
773 return TRUE;
774
775 case CDM_HIDECONTROL:
776 case CDM_SETDEFEXT:
777 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
778 return -1;
779 }
780 return TRUE;
781}
782
783/***********************************************************************
784 * FileOpenDlgProc95
785 *
786 * File open dialog procedure
787 */
788HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
789{
790 switch(uMsg)
791 {
792 case WM_INITDIALOG:
793 /* Adds the FileOpenDlgInfos in the property list of the dialog
794 so it will be easily accessible through a GetPropA(...) */
795 SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) lParam);
796
797 FILEDLG95_OnWMInitDialog(hwnd, wParam, lParam);
798 ((FileOpenDlgInfos *)lParam)->DlgInfos.hwndCustomDlg =
799 CreateTemplateDialog((FileOpenDlgInfos *)lParam,hwnd);
800 SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE);
801 return 0;
802 case WM_COMMAND:
803 return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
804 case WM_DRAWITEM:
805 {
806 switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
807 {
808 case IDC_LOOKIN:
809 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
810 return TRUE;
811 }
812 }
813 return FALSE;
814
815 case WM_GETISHELLBROWSER:
816 return FILEDLG95_OnWMGetIShellBrowser(hwnd);
817
818 case WM_DESTROY:
819 RemovePropA(hwnd, FileOpenDlgInfosStr);
820 return FALSE;
821
822 case WM_NOTIFY:
823 {
824 LPNMHDR lpnmh = (LPNMHDR)lParam;
825 UINT stringId = -1;
826
827 /* set up the button tooltips strings */
828 if(TTN_GETDISPINFOA == lpnmh->code )
829 {
830 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
831 switch(lpnmh->idFrom )
832 {
833 /* Up folder button */
834 case FCIDM_TB_UPFOLDER:
835 stringId = IDS_UPFOLDER;
836 break;
837 /* New folder button */
838 case FCIDM_TB_NEWFOLDER:
839 stringId = IDS_NEWFOLDER;
840 break;
841 /* List option button */
842 case FCIDM_TB_SMALLICON:
843 stringId = IDS_LISTVIEW;
844 break;
845 /* Details option button */
846 case FCIDM_TB_REPORTVIEW:
847 stringId = IDS_REPORTVIEW;
848 break;
849 /* Desktop button */
850 case FCIDM_TB_DESKTOP:
851 stringId = IDS_TODESKTOP;
852 break;
853 default:
854 stringId = 0;
855 }
856 lpdi->hinst = COMMDLG_hInstance32;
857 lpdi->lpszText = (LPSTR) stringId;
858 }
859 return FALSE;
860 }
861 default :
862 if(uMsg >= CDM_FIRST && uMsg <= CDM_LAST)
863 return FILEDLG95_HandleCustomDialogMessages(hwnd, uMsg, wParam, lParam);
864 return FALSE;
865 }
866}
867
868/***********************************************************************
869 * FILEDLG95_OnWMInitDialog
870 *
871 * WM_INITDIALOG message handler
872 */
873static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam)
874{
875 LPITEMIDLIST pidlItemId;
876 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
877
878 TRACE("dir=%s file=%s\n",
879 fodInfos->ofnInfos->lpstrInitialDir, fodInfos->ofnInfos->lpstrFile);
880
881 /* Get the initial directory pidl */
882
883 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos->lpstrInitialDir)))
884 {
885 char path[MAX_PATH];
886
887 GetCurrentDirectoryA(MAX_PATH,path);
888 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder, path);
889
890 }
891
892 /* Initialise shell objects */
893 FILEDLG95_SHELL_Init(hwnd);
894
895 /* Initialise dialog UI */
896 FILEDLG95_InitUI(hwnd);
897
898 /* Initialize the Look In combo box*/
899 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
900
901 /* Initialize the filter combo box */
902 FILEDLG95_FILETYPE_Init(hwnd);
903
904 /* Browse to the initial directory */
905 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId, SBSP_ABSOLUTE);
906
907 /* Free pidlItem memory */
908 COMDLG32_SHFree(pidlItemId);
909
910 return TRUE;
911}
912/***********************************************************************
913 * FILEDLG95_Clean
914 *
915 * Regroups all the cleaning functions of the filedlg
916 */
917void FILEDLG95_Clean(HWND hwnd)
918{
919 FILEDLG95_FILETYPE_Clean(hwnd);
920 FILEDLG95_LOOKIN_Clean(hwnd);
921 FILEDLG95_SHELL_Clean(hwnd);
922}
923/***********************************************************************
924 * FILEDLG95_OnWMCommand
925 *
926 * WM_COMMAND message handler
927 */
928static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
929{
930 WORD wNotifyCode = HIWORD(wParam); /* notification code */
931 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
932 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
933
934 switch(wID)
935 {
936 /* OK button */
937 case IDOK:
938 if(FILEDLG95_OnOpen(hwnd))
939 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
940 break;
941 /* Cancel button */
942 case IDCANCEL:
943 FILEDLG95_Clean(hwnd);
944 EndDialog(hwnd, FALSE);
945 break;
946 /* Filetype combo box */
947 case IDC_FILETYPE:
948 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
949 break;
950 /* LookIn combo box */
951 case IDC_LOOKIN:
952 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
953 break;
954
955 /* --- toolbar --- */
956 /* Up folder button */
957 case FCIDM_TB_UPFOLDER:
958 FILEDLG95_SHELL_UpFolder(hwnd);
959 break;
960 /* New folder button */
961 case FCIDM_TB_NEWFOLDER:
962 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_NEWFOLDER);
963 break;
964 /* List option button */
965 case FCIDM_TB_SMALLICON:
966 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
967 break;
968 /* Details option button */
969 case FCIDM_TB_REPORTVIEW:
970 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
971 break;
972 /* Details option button */
973 case FCIDM_TB_DESKTOP:
974 FILEDLG95_SHELL_BrowseToDesktop(hwnd);
975 break;
976
977 case IDC_FILENAME:
978 break;
979
980 }
981 /* Do not use the listview selection anymore */
982 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
983 return 0;
984}
985
986/***********************************************************************
987 * FILEDLG95_OnWMGetIShellBrowser
988 *
989 * WM_GETISHELLBROWSER message handler
990 */
991static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
992{
993
994 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
995
996 TRACE("\n");
997
998 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
999
1000 return TRUE;
1001}
1002
1003
1004/***********************************************************************
1005 * FILEDLG95_InitUI
1006 *
1007 */
1008static LRESULT FILEDLG95_InitUI(HWND hwnd)
1009{
1010 TBBUTTON tbb[] =
1011 {
1012 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1013 {VIEW_PARENTFOLDER, FCIDM_TB_UPFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1014 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1015 {VIEW_NEWFOLDER+1, FCIDM_TB_DESKTOP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1016 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1017 {VIEW_NEWFOLDER, FCIDM_TB_NEWFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1018 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1019 {VIEW_LIST, FCIDM_TB_SMALLICON, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1020 {VIEW_DETAILS, FCIDM_TB_REPORTVIEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1021 };
1022 TBADDBITMAP tba[] =
1023 {
1024 { HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR },
1025 { COMDLG32_hInstance, 800 } // desktop icon
1026 };
1027
1028 RECT rectTB;
1029
1030 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1031
1032 TRACE("%p\n", fodInfos);
1033
1034 /* Get the hwnd of the controls */
1035 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
1036 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
1037 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
1038
1039 /* construct the toolbar */
1040 GetWindowRect(GetDlgItem(hwnd,IDC_TOOLBARSTATIC),&rectTB);
1041 MapWindowPoints( 0, hwnd,(LPPOINT)&rectTB,2);
1042
1043 fodInfos->DlgInfos.hwndTB = CreateWindowExA(0, TOOLBARCLASSNAMEA, (LPSTR) NULL,
1044 WS_CHILD | WS_GROUP | TBSTYLE_TOOLTIPS | CCS_NODIVIDER | CCS_NORESIZE,
1045 0, 0, 150, 26,
1046 hwnd, (HMENU) IDC_TOOLBAR, COMMDLG_hInstance32, NULL);
1047
1048 SetWindowPos(fodInfos->DlgInfos.hwndTB, 0,
1049 rectTB.left,rectTB.top, rectTB.right-rectTB.left, rectTB.bottom-rectTB.top,
1050 SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
1051
1052 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
1053
1054/* fixme: use TB_LOADIMAGES when implemented */
1055/* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1056 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBITMAP, (WPARAM) 12, (LPARAM) &tba[0]);
1057 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBITMAP, (WPARAM) 1, (LPARAM) &tba[1]);
1058
1059 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBUTTONSA, (WPARAM) 9,(LPARAM) &tbb);
1060 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_AUTOSIZE, 0, 0);
1061
1062 /* Set the window text with the text specified in the OPENFILENAME structure */
1063 if(fodInfos->ofnInfos->lpstrTitle)
1064 {
1065 SetWindowTextA(hwnd,fodInfos->ofnInfos->lpstrTitle);
1066 }
1067 else if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1068 {
1069 SetWindowTextA(hwnd,"Save");
1070 }
1071
1072 /* Initialise the file name edit control */
1073 if(fodInfos->ofnInfos->lpstrFile)
1074 {
1075 LPSTR lpstrFile = COMDLG32_PathFindFileNameA(fodInfos->ofnInfos->lpstrFile);
1076 SetDlgItemTextA(hwnd, IDC_FILENAME, lpstrFile);
1077 }
1078
1079 /* Must the open as read only check box be checked ?*/
1080 if(fodInfos->ofnInfos->Flags & OFN_READONLY)
1081 {
1082 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
1083 }
1084
1085 /* Must the open as read only check box be hid ?*/
1086 if(fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY)
1087 {
1088 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
1089 }
1090
1091 /* Must the help button be hid ?*/
1092 if (!(fodInfos->ofnInfos->Flags & OFN_SHOWHELP))
1093 {
1094 ShowWindow(GetDlgItem(hwnd, pshHelp), SW_HIDE);
1095 }
1096
1097 /* Resize the height, if open as read only checkbox ad help button
1098 are hidden */
1099 if ( (fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY) &&
1100 (!(fodInfos->ofnInfos->Flags & OFN_SHOWHELP)) )
1101 {
1102 RECT rectDlg, rectHelp, rectCancel;
1103 GetWindowRect(hwnd, &rectDlg);
1104 GetWindowRect(GetDlgItem(hwnd, pshHelp), &rectHelp);
1105 GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rectCancel);
1106 /* subtract the height of the help button plus the space between
1107 the help button and the cancel button to the height of the dialog */
1108 SetWindowPos(hwnd, 0, 0, 0, rectDlg.right-rectDlg.left,
1109 (rectDlg.bottom-rectDlg.top) - (rectHelp.bottom - rectCancel.bottom),
1110 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
1111 }
1112
1113 /* change Open to Save FIXME: use resources */
1114 if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1115 {
1116 SetDlgItemTextA(hwnd,IDOK,"&Save");
1117 SetDlgItemTextA(hwnd,IDC_LOOKINSTATIC,"Save &in");
1118 }
1119 return 0;
1120}
1121
1122/***********************************************************************
1123 * FILEDLG95_OnOpenMultipleFiles
1124 *
1125 * Handles the opening of multiple files.
1126 *
1127 * FIXME
1128 * check destination buffer size
1129 */
1130BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed)
1131{
1132 CHAR lpstrPathSpec[MAX_PATH] = "";
1133 LPSTR lpstrFile;
1134 UINT nCount, nSizePath;
1135 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1136
1137 TRACE("\n");
1138
1139 lpstrFile = fodInfos->ofnInfos->lpstrFile;
1140 lpstrFile[0] = '\0';
1141
1142 COMDLG32_SHGetPathFromIDListA( fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathSpec );
1143
1144 if ( !(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE) &&
1145 ( fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST))
1146 {
1147 LPSTR lpstrTemp = lpstrFileList;
1148
1149 for ( nCount = 0; nCount < nFileCount; nCount++ )
1150 {
1151 LPITEMIDLIST pidl;
1152
1153 pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder, lpstrTemp);
1154 if (!pidl)
1155 {
1156 CHAR lpstrNotFound[100];
1157 CHAR lpstrMsg[100];
1158 CHAR tmp[400];
1159
1160 LoadStringA(COMMDLG_hInstance32, IDS_FILENOTFOUND, lpstrNotFound, 100);
1161 LoadStringA(COMMDLG_hInstance32, IDS_VERIFYFILE, lpstrMsg, 100);
1162
1163 strcpy(tmp, lpstrTemp);
1164 strcat(tmp, "\n");
1165 strcat(tmp, lpstrNotFound);
1166 strcat(tmp, "\n");
1167 strcat(tmp, lpstrMsg);
1168
1169 MessageBoxA(hwnd, tmp, fodInfos->ofnInfos->lpstrTitle, MB_OK | MB_ICONEXCLAMATION);
1170 return FALSE;
1171 }
1172
1173 lpstrTemp += strlen(lpstrFileList) + 1;
1174 COMDLG32_SHFree(pidl);
1175 }
1176 }
1177
1178 nSizePath = strlen(lpstrPathSpec);
1179 strcpy( lpstrFile, lpstrPathSpec);
1180 memcpy( lpstrFile + nSizePath + 1, lpstrFileList, sizeUsed );
1181
1182 fodInfos->ofnInfos->nFileOffset = nSizePath + 1;
1183 fodInfos->ofnInfos->nFileExtension = 0;
1184
1185 /* clean and exit */
1186 FILEDLG95_Clean(hwnd);
1187 return EndDialog(hwnd,TRUE);
1188}
1189
1190/***********************************************************************
1191 * FILEDLG95_OnOpen
1192 *
1193 * Ok button WM_COMMAND message handler
1194 *
1195 * If the function succeeds, the return value is nonzero.
1196 */
1197#define ONOPEN_BROWSE 1
1198#define ONOPEN_OPEN 2
1199#define ONOPEN_SEARCH 3
1200static void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
1201{
1202 char strMsgTitle[MAX_PATH];
1203 char strMsgText [MAX_PATH];
1204 if (idCaption)
1205 LoadStringA(COMDLG32_hInstance, idCaption, strMsgTitle, sizeof(strMsgTitle));
1206 else
1207 strMsgTitle[0] = '\0';
1208 LoadStringA(COMDLG32_hInstance, idText, strMsgText, sizeof(strMsgText));
1209 MessageBoxA(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
1210}
1211
1212BOOL FILEDLG95_OnOpen(HWND hwnd)
1213{
1214 char * lpstrFileList;
1215 UINT nFileCount = 0;
1216 UINT sizeUsed = 0;
1217 BOOL ret = TRUE;
1218 char lpstrPathAndFile[MAX_PATH];
1219 char lpstrTemp[MAX_PATH];
1220 LPSHELLFOLDER lpsf = NULL;
1221 int nOpenAction;
1222 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1223
1224 TRACE("hwnd=0x%04x\n", hwnd);
1225
1226 /* get the files from the edit control */
1227 nFileCount = FILEDLG95_FILENAME_GetFileNames(hwnd, &lpstrFileList, &sizeUsed);
1228
1229 /* try if the user selected a folder in the shellview */
1230 if(nFileCount == 0)
1231 {
1232 BrowseSelectedFolder(hwnd);
1233 return FALSE;
1234 }
1235
1236 if(nFileCount > 1)
1237 {
1238 ret = FILEDLG95_OnOpenMultipleFiles(hwnd, lpstrFileList, nFileCount, sizeUsed);
1239 goto ret;
1240 }
1241
1242 TRACE("count=%u len=%u file=%s\n", nFileCount, sizeUsed, lpstrFileList);
1243
1244/*
1245 Step 1: Build a complete path name from the current folder and
1246 the filename or path in the edit box.
1247 Special cases:
1248 - the path in the edit box is a root path
1249 (with or without drive letter)
1250 - the edit box contains ".." (or a path with ".." in it)
1251*/
1252
1253 /* Get the current directory name */
1254 if (!COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathAndFile))
1255 {
1256 /* we are in a special folder, default to desktop */
1257 if(FAILED(COMDLG32_SHGetFolderPathA(hwnd, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, NULL, 0, lpstrPathAndFile)))
1258 {
1259 /* last fallback */
1260 GetCurrentDirectoryA(MAX_PATH, lpstrPathAndFile);
1261 }
1262 }
1263 COMDLG32_PathAddBackslashA(lpstrPathAndFile);
1264
1265 TRACE("current directory=%s\n", lpstrPathAndFile);
1266
1267 /* if the user specifyed a fully qualified path use it */
1268 if(COMDLG32_PathIsRelativeA(lpstrFileList))
1269 {
1270 strcat(lpstrPathAndFile, lpstrFileList);
1271 }
1272 else
1273 {
1274 /* does the path have a drive letter? */
1275 if (COMDLG32_PathGetDriveNumberA(lpstrFileList) == -1)
1276 strcpy(lpstrPathAndFile+2, lpstrFileList);
1277 else
1278 strcpy(lpstrPathAndFile, lpstrFileList);
1279 }
1280
1281 /* resolve "." and ".." */
1282 COMDLG32_PathCanonicalizeA(lpstrTemp, lpstrPathAndFile );
1283 strcpy(lpstrPathAndFile, lpstrTemp);
1284 TRACE("canon=%s\n", lpstrPathAndFile);
1285
1286 MemFree(lpstrFileList);
1287
1288/*
1289 Step 2: here we have a cleaned up path
1290
1291 We have to parse the path step by step to see if we have to browse
1292 to a folder if the path points to a directory or the last
1293 valid element is a directory.
1294
1295 valid variables:
1296 lpstrPathAndFile: cleaned up path
1297 */
1298
1299 nOpenAction = ONOPEN_BROWSE;
1300
1301 /* dont apply any checks with OFN_NOVALIDATE */
1302 if(!(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE))
1303 {
1304 LPSTR lpszTemp, lpszTemp1;
1305 LPITEMIDLIST pidl = NULL;
1306
1307 /* check for invalid chars */
1308 if(strpbrk(lpstrPathAndFile+3, "/:<>|") != NULL)
1309 {
1310 FILEDLG95_OnOpenMessage(hwnd, IDS_INVALID_FILENAME_TITLE, IDS_INVALID_FILENAME);
1311 ret = FALSE;
1312 goto ret;
1313 }
1314
1315 if (FAILED (COMDLG32_SHGetDesktopFolder(&lpsf))) return FALSE;
1316
1317 lpszTemp1 = lpszTemp = lpstrPathAndFile;
1318 while (lpszTemp1)
1319 {
1320 LPSHELLFOLDER lpsfChild;
1321 WCHAR lpwstrTemp[MAX_PATH];
1322 DWORD dwEaten, dwAttributes;
1323
1324 lpszTemp = COMDLG32_PathFindNextComponentA(lpszTemp);
1325 if (*lpszTemp)
1326 lstrcpynAtoW(lpwstrTemp, lpszTemp1, lpszTemp - lpszTemp1);
1327 else
1328 {
1329 lstrcpyAtoW(lpwstrTemp, lpszTemp1); /* last element */
1330 if(strpbrk(lpszTemp1, "*?") != NULL)
1331 {
1332 nOpenAction = ONOPEN_SEARCH;
1333 break;
1334 }
1335 }
1336 lpszTemp1 = lpszTemp;
1337
1338 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp), debugstr_a(lpszTemp), lpsf);
1339
1340 if(lstrlenW(lpwstrTemp)==2) COMDLG32_PathAddBackslashW(lpwstrTemp);
1341
1342 dwAttributes = SFGAO_FOLDER;
1343 if(FAILED(IShellFolder_ParseDisplayName(lpsf, hwnd, NULL, lpwstrTemp, &dwEaten, &pidl, &dwAttributes)))
1344 {
1345 if(*lpszTemp) /* points to trailing null for last path element */
1346 {
1347 if(fodInfos->ofnInfos->Flags & OFN_PATHMUSTEXIST)
1348 {
1349 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_PATHNOTEXISTING);
1350 break;
1351 }
1352 }
1353 else
1354 {
1355 if(fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST)
1356 {
1357 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
1358 break;
1359 }
1360 }
1361 /* change to the current folder */
1362 nOpenAction = ONOPEN_OPEN;
1363 break;
1364 }
1365 else
1366 {
1367 /* the path component is valid */
1368 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes, pidl);
1369 if(dwAttributes & SFGAO_FOLDER)
1370 {
1371 if(FAILED(IShellFolder_BindToObject(lpsf, pidl, 0, &IID_IShellFolder, (LPVOID*)&lpsfChild)))
1372 {
1373 ERR("bind to failed\n"); /* should not fail */
1374 break;
1375 }
1376 IShellFolder_Release(lpsf);
1377 lpsf = lpsfChild;
1378 lpsfChild = NULL;
1379 }
1380 else
1381 {
1382 TRACE("value\n");
1383
1384 /* end dialog, return value */
1385 nOpenAction = ONOPEN_OPEN;
1386 break;
1387 }
1388 COMDLG32_SHFree(pidl);
1389 pidl = NULL;
1390 }
1391 }
1392 if(pidl) COMDLG32_SHFree(pidl);
1393 }
1394
1395 /* path is valid, clean the edit box */
1396 SetDlgItemTextA(hwnd,IDC_FILENAME,"");
1397
1398/*
1399 Step 3: here we have a cleaned up and validated path
1400
1401 valid variables:
1402 lpsf: ShellFolder bound to the rightmost valid path component
1403 lpstrPathAndFile: cleaned up path
1404 nOpenAction: action to do
1405*/
1406 TRACE("end validate sf=%p\n", lpsf);
1407
1408 switch(nOpenAction)
1409 {
1410 case ONOPEN_SEARCH: /* set the current filter to the file mask and refresh */
1411 TRACE("ONOPEN_SEARCH %s\n", lpstrPathAndFile);
1412 {
1413 int iPos;
1414 LPSTR lpszTemp = COMDLG32_PathFindFileNameA(lpstrPathAndFile);
1415
1416 /* replace the current filter */
1417 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1418 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1419 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpszTemp)+1)*sizeof(WCHAR));
1420 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter, lpszTemp);
1421
1422 /* set the filter cb to the extension when possible */
1423 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB, lpszTemp)))
1424 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, iPos);
1425 }
1426 /* fall through */
1427 case ONOPEN_BROWSE: /* browse to the highest folder we could bind to */
1428 TRACE("ONOPEN_BROWSE\n");
1429 {
1430 IPersistFolder2 * ppf2;
1431 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf, &IID_IPersistFolder2, (LPVOID*)&ppf2)))
1432 {
1433 LPITEMIDLIST pidlCurrent;
1434 IPersistFolder2_GetCurFolder(ppf2, &pidlCurrent);
1435 IPersistFolder2_Release(ppf2);
1436 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent, fodInfos->ShellInfos.pidlAbsCurrent))
1437 {
1438 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidlCurrent, SBSP_ABSOLUTE);
1439 }
1440 else if( nOpenAction == ONOPEN_SEARCH )
1441 {
1442 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1443 }
1444 COMDLG32_SHFree(pidlCurrent);
1445 }
1446 }
1447 ret = FALSE;
1448 break;
1449 case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
1450 TRACE("ONOPEN_OPEN %s\n", lpstrPathAndFile);
1451 {
1452 /* add default extension */
1453 if (fodInfos->ofnInfos->lpstrDefExt)
1454 {
1455 if (! *COMDLG32_PathFindExtensionA(lpstrPathAndFile))
1456 {
1457 strcat(lpstrPathAndFile, ".");
1458 strcat(lpstrPathAndFile, fodInfos->ofnInfos->lpstrDefExt);
1459 }
1460 }
1461
1462 /* Check that size size of the file does not exceed buffer size */
1463 if(strlen(lpstrPathAndFile) < fodInfos->ofnInfos->nMaxFile)
1464 {
1465 LPSTR lpszTemp;
1466
1467 /* fill destination buffer */
1468 strcpy(fodInfos->ofnInfos->lpstrFile, lpstrPathAndFile);
1469
1470 /* set filename offset */
1471 lpszTemp = COMDLG32_PathFindFileNameA(lpstrPathAndFile);
1472 fodInfos->ofnInfos->nFileOffset = lpszTemp - lpstrPathAndFile;
1473
1474 /* set extension offset */
1475 lpszTemp = COMDLG32_PathFindExtensionA(lpstrPathAndFile);
1476 fodInfos->ofnInfos->nFileExtension = (*lpszTemp) ? lpszTemp - lpstrPathAndFile + 1 : 0;
1477
1478 /* set the lpstrFileTitle */
1479 if(fodInfos->ofnInfos->lpstrFileTitle)
1480 {
1481 LPSTR lpstrFileTitle = COMDLG32_PathFindFileNameA(lpstrPathAndFile);
1482 strncpy(fodInfos->ofnInfos->lpstrFileTitle, lpstrFileTitle, fodInfos->ofnInfos->nMaxFileTitle);
1483 }
1484
1485 FILEDLG95_Clean(hwnd);
1486 ret = EndDialog(hwnd, TRUE);
1487 }
1488 else
1489 {
1490 /* FIXME set error FNERR_BUFFERTOSMALL */
1491 FILEDLG95_Clean(hwnd);
1492 ret = EndDialog(hwnd, FALSE);
1493 }
1494 goto ret;
1495 }
1496 break;
1497 }
1498
1499ret:
1500 if(lpsf) IShellFolder_Release(lpsf);
1501 return ret;
1502}
1503
1504/***********************************************************************
1505 * FILEDLG95_SHELL_Init
1506 *
1507 * Initialisation of the shell objects
1508 */
1509static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1510{
1511 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1512
1513 TRACE("\n");
1514
1515 /*
1516 * Initialisation of the FileOpenDialogInfos structure
1517 */
1518
1519 /* Shell */
1520
1521 /*ShellInfos */
1522 fodInfos->ShellInfos.hwndOwner = hwnd;
1523
1524 /* Disable multi-select if flag not set */
1525 if (!(fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT))
1526 {
1527 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_SINGLESEL;
1528 }
1529 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1530 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1531
1532 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1533 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1534 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1535
1536 /* Construct the IShellBrowser interface */
1537 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1538
1539 return NOERROR;
1540}
1541
1542/***********************************************************************
1543 * FILEDLG95_SHELL_ExecuteCommand
1544 *
1545 * Change the folder option and refresh the view
1546 * If the function succeeds, the return value is nonzero.
1547 */
1548static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1549{
1550 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1551
1552 IContextMenu * pcm;
1553 TRACE("(0x%08x,%p)\n", hwnd, lpVerb);
1554
1555 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1556 SVGIO_BACKGROUND,
1557 &IID_IContextMenu,
1558 (LPVOID*)&pcm)))
1559 {
1560 CMINVOKECOMMANDINFO ci;
1561 ZeroMemory(&ci, sizeof(CMINVOKECOMMANDINFO));
1562 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1563 ci.lpVerb = lpVerb;
1564 ci.hwnd = hwnd;
1565
1566 IContextMenu_InvokeCommand(pcm, &ci);
1567 IContextMenu_Release(pcm);
1568 }
1569
1570 return FALSE;
1571}
1572
1573/***********************************************************************
1574 * FILEDLG95_SHELL_UpFolder
1575 *
1576 * Browse to the specified object
1577 * If the function succeeds, the return value is nonzero.
1578 */
1579static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1580{
1581 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1582
1583 TRACE("\n");
1584
1585 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1586 NULL,
1587 SBSP_PARENT)))
1588 {
1589 return TRUE;
1590 }
1591 return FALSE;
1592}
1593
1594/***********************************************************************
1595 * FILEDLG95_SHELL_BrowseToDesktop
1596 *
1597 * Browse to the Desktop
1598 * If the function succeeds, the return value is nonzero.
1599 */
1600static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd)
1601{
1602 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1603 LPITEMIDLIST pidl;
1604 HRESULT hres;
1605
1606 TRACE("\n");
1607
1608 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidl);
1609 hres = IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidl, SBSP_ABSOLUTE);
1610 COMDLG32_SHFree(pidl);
1611 return SUCCEEDED(hres);
1612}
1613/***********************************************************************
1614 * FILEDLG95_SHELL_Clean
1615 *
1616 * Cleans the memory used by shell objects
1617 */
1618static void FILEDLG95_SHELL_Clean(HWND hwnd)
1619{
1620 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1621
1622 TRACE("\n");
1623
1624 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
1625
1626 /* clean Shell interfaces */
1627 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1628 IShellView_Release(fodInfos->Shell.FOIShellView);
1629 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1630 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1631 if (fodInfos->Shell.FOIDataObject)
1632 IDataObject_Release(fodInfos->Shell.FOIDataObject);
1633}
1634
1635/***********************************************************************
1636 * FILEDLG95_FILETYPE_Init
1637 *
1638 * Initialisation of the file type combo box
1639 */
1640static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1641{
1642 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1643
1644 TRACE("\n");
1645
1646 if(fodInfos->ofnInfos->lpstrFilter)
1647 {
1648 int nFilters = 0; /* number of filters */
1649 LPSTR lpstrFilter;
1650 LPCSTR lpstrPos = fodInfos->ofnInfos->lpstrFilter;
1651
1652 for(;;)
1653 {
1654 /* filter is a list... title\0ext\0......\0\0
1655 * Set the combo item text to the title and the item data
1656 * to the ext
1657 */
1658 LPCSTR lpstrDisplay;
1659 LPSTR lpstrExt;
1660
1661 /* Get the title */
1662 if(! *lpstrPos) break; /* end */
1663 lpstrDisplay = lpstrPos;
1664 lpstrPos += strlen(lpstrPos) + 1;
1665
1666 /* Copy the extensions */
1667 if (! *lpstrPos) return E_FAIL; /* malformed filter */
1668 if (!(lpstrExt = (LPSTR) MemAlloc(strlen(lpstrPos)+1))) return E_FAIL;
1669 strcpy(lpstrExt,lpstrPos);
1670 lpstrPos += strlen(lpstrPos) + 1;
1671
1672 /* Add the item at the end of the combo */
1673 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB, lpstrDisplay);
1674 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB, nFilters, lpstrExt);
1675 nFilters++;
1676 }
1677 /*
1678 * Set the current filter to the one specified
1679 * in the initialisation structure
1680 * FIXME: lpstrCustomFilter not handled at all
1681 */
1682
1683 /* set default filter index */
1684 if(fodInfos->ofnInfos->nFilterIndex == 0 && fodInfos->ofnInfos->lpstrCustomFilter == NULL)
1685 fodInfos->ofnInfos->nFilterIndex = 1;
1686
1687 /* First, check to make sure our index isn't out of bounds. */
1688 if ( fodInfos->ofnInfos->nFilterIndex > nFilters )
1689 fodInfos->ofnInfos->nFilterIndex = nFilters;
1690
1691 /* Set the current index selection. */
1692 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, fodInfos->ofnInfos->nFilterIndex-1);
1693
1694 /* Get the corresponding text string from the combo box. */
1695 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1696 fodInfos->ofnInfos->nFilterIndex-1);
1697
1698 if ((INT)lpstrFilter == CB_ERR) /* control is empty */
1699 lpstrFilter = NULL;
1700
1701 if(lpstrFilter)
1702 {
1703 _strlwr(lpstrFilter); /* lowercase */
1704 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1705 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter, lpstrFilter);
1706 }
1707 }
1708 return NOERROR;
1709}
1710
1711/***********************************************************************
1712 * FILEDLG95_FILETYPE_OnCommand
1713 *
1714 * WM_COMMAND of the file type combo box
1715 * If the function succeeds, the return value is nonzero.
1716 */
1717static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1718{
1719 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1720
1721 switch(wNotifyCode)
1722 {
1723 case CBN_SELENDOK:
1724 {
1725 LPSTR lpstrFilter;
1726
1727 /* Get the current item of the filetype combo box */
1728 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1729
1730 /* set the current filter index - indexed from 1 */
1731 fodInfos->ofnInfos->nFilterIndex = iItem + 1;
1732
1733 /* Set the current filter with the current selection */
1734 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1735 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1736
1737 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1738 iItem);
1739 if((int)lpstrFilter != CB_ERR)
1740 {
1741 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1742 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,_strlwr(lpstrFilter));
1743 SendCustomDlgNotificationMessage(hwnd,CDN_TYPECHANGE);
1744 }
1745
1746 /* Refresh the actual view to display the included items*/
1747 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1748 }
1749 }
1750 return FALSE;
1751}
1752/***********************************************************************
1753 * FILEDLG95_FILETYPE_SearchExt
1754 *
1755 * searches for a extension in the filetype box
1756 */
1757static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCSTR lpstrExt)
1758{
1759 int i, iCount = CBGetCount(hwnd);
1760
1761 TRACE("%s\n", lpstrExt);
1762
1763 if(iCount != CB_ERR)
1764 {
1765 for(i=0;i<iCount;i++)
1766 {
1767 if(!strcasecmp(lpstrExt,(LPSTR)CBGetItemDataPtr(hwnd,i)))
1768 return i;
1769 }
1770 }
1771 return -1;
1772}
1773
1774/***********************************************************************
1775 * FILEDLG95_FILETYPE_Clean
1776 *
1777 * Clean the memory used by the filetype combo box
1778 */
1779static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1780{
1781 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1782 int iPos;
1783 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1784
1785 TRACE("\n");
1786
1787 /* Delete each string of the combo and their associated data */
1788 if(iCount != CB_ERR)
1789 {
1790 for(iPos = iCount-1;iPos>=0;iPos--)
1791 {
1792 MemFree((LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos));
1793 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1794 }
1795 }
1796 /* Current filter */
1797 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1798 MemFree(fodInfos->ShellInfos.lpstrCurrentFilter);
1799
1800}
1801
1802/***********************************************************************
1803 * FILEDLG95_LOOKIN_Init
1804 *
1805 * Initialisation of the look in combo box
1806 */
1807static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1808{
1809 IShellFolder *psfRoot, *psfDrives;
1810 IEnumIDList *lpeRoot, *lpeDrives;
1811 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1812
1813 LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
1814
1815 TRACE("\n");
1816
1817 liInfos->iMaxIndentation = 0;
1818
1819 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1820 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1821
1822 /* Initialise data of Desktop folder */
1823 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1824 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1825 COMDLG32_SHFree(pidlTmp);
1826
1827 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1828
1829 COMDLG32_SHGetDesktopFolder(&psfRoot);
1830
1831 if (psfRoot)
1832 {
1833 /* enumerate the contents of the desktop */
1834 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1835 {
1836 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1837 {
1838 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1839
1840 /* special handling for CSIDL_DRIVES */
1841 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1842 {
1843 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1844 {
1845 /* enumerate the drives */
1846 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1847 {
1848 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1849 {
1850 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1851 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1852 COMDLG32_SHFree(pidlAbsTmp);
1853 COMDLG32_SHFree(pidlTmp1);
1854 }
1855 IEnumIDList_Release(lpeDrives);
1856 }
1857 IShellFolder_Release(psfDrives);
1858 }
1859 }
1860 COMDLG32_SHFree(pidlTmp);
1861 }
1862 IEnumIDList_Release(lpeRoot);
1863 }
1864 }
1865
1866 IShellFolder_Release(psfRoot);
1867 COMDLG32_SHFree(pidlDrives);
1868 return NOERROR;
1869}
1870
1871/***********************************************************************
1872 * FILEDLG95_LOOKIN_DrawItem
1873 *
1874 * WM_DRAWITEM message handler
1875 */
1876static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1877{
1878 COLORREF crWin = GetSysColor(COLOR_WINDOW);
1879 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1880 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1881 RECT rectText;
1882 RECT rectIcon;
1883 SHFILEINFOA sfi;
1884 HIMAGELIST ilItemImage;
1885 int iIndentation;
1886 LPSFOLDER tmpFolder;
1887
1888
1889 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1890
1891 TRACE("\n");
1892
1893 if(pDIStruct->itemID == -1)
1894 return 0;
1895
1896 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1897 pDIStruct->itemID)))
1898 return 0;
1899
1900
1901 if(pDIStruct->itemID == liInfos->uSelectedItem)
1902 {
1903 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1904 0,
1905 &sfi,
1906 sizeof (SHFILEINFOA),
1907 SHGFI_PIDL | SHGFI_SMALLICON |
1908 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
1909 SHGFI_DISPLAYNAME );
1910 }
1911 else
1912 {
1913 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1914 0,
1915 &sfi,
1916 sizeof (SHFILEINFOA),
1917 SHGFI_PIDL | SHGFI_SMALLICON |
1918 SHGFI_SYSICONINDEX |
1919 SHGFI_DISPLAYNAME);
1920 }
1921
1922 /* Is this item selected ?*/
1923 if(pDIStruct->itemState & ODS_SELECTED)
1924 {
1925 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1926 SetBkColor(pDIStruct->hDC,crHighLight);
1927 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1928 }
1929 else
1930 {
1931 SetTextColor(pDIStruct->hDC,crText);
1932 SetBkColor(pDIStruct->hDC,crWin);
1933 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1934 }
1935
1936 /* Do not indent item if drawing in the edit of the combo*/
1937 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
1938 {
1939 iIndentation = 0;
1940 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1941 0,
1942 &sfi,
1943 sizeof (SHFILEINFOA),
1944 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
1945 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
1946
1947 }
1948 else
1949 {
1950 iIndentation = tmpFolder->m_iIndent;
1951 }
1952 /* Draw text and icon */
1953
1954 /* Initialise the icon display area */
1955 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
1956 rectIcon.top = pDIStruct->rcItem.top;
1957 rectIcon.right = rectIcon.left + ICONWIDTH;
1958 rectIcon.bottom = pDIStruct->rcItem.bottom;
1959
1960 /* Initialise the text display area */
1961 rectText.left = rectIcon.right;
1962 rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
1963 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
1964 rectText.bottom = pDIStruct->rcItem.bottom;
1965
1966
1967 /* Draw the icon from the image list */
1968 COMDLG32_ImageList_Draw(ilItemImage,
1969 sfi.iIcon,
1970 pDIStruct->hDC,
1971 rectIcon.left,
1972 rectIcon.top,
1973 ILD_TRANSPARENT );
1974
1975 /* Draw the associated text */
1976 if(sfi.szDisplayName)
1977 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
1978
1979
1980 return NOERROR;
1981}
1982
1983/***********************************************************************
1984 * FILEDLG95_LOOKIN_OnCommand
1985 *
1986 * LookIn combo box WM_COMMAND message handler
1987 * If the function succeeds, the return value is nonzero.
1988 */
1989static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
1990{
1991 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1992
1993 TRACE("%p\n", fodInfos);
1994
1995 switch(wNotifyCode)
1996 {
1997 case CBN_SELENDOK:
1998 {
1999 LPSFOLDER tmpFolder;
2000 int iItem;
2001
2002 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
2003
2004 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
2005 iItem)))
2006 return FALSE;
2007
2008
2009 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
2010 tmpFolder->pidlItem,
2011 SBSP_ABSOLUTE)))
2012 {
2013 return TRUE;
2014 }
2015 break;
2016 }
2017
2018 }
2019 return FALSE;
2020}
2021
2022/***********************************************************************
2023 * FILEDLG95_LOOKIN_AddItem
2024 *
2025 * Adds an absolute pidl item to the lookin combo box
2026 * returns the index of the inserted item
2027 */
2028static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
2029{
2030 LPITEMIDLIST pidlNext;
2031 SHFILEINFOA sfi;
2032 SFOLDER *tmpFolder;
2033 LookInInfos *liInfos;
2034
2035 TRACE("\n");
2036
2037 if(!pidl)
2038 return -1;
2039
2040 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
2041 return -1;
2042
2043 tmpFolder = MemAlloc(sizeof(SFOLDER));
2044 tmpFolder->m_iIndent = 0;
2045
2046 /* Calculate the indentation of the item in the lookin*/
2047 pidlNext = pidl;
2048 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
2049 {
2050 tmpFolder->m_iIndent++;
2051 }
2052
2053 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl); /* FIXME: memory leak*/
2054
2055 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
2056 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
2057
2058 sfi.dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
2059 COMDLG32_SHGetFileInfoA((LPSTR)pidl,
2060 0,
2061 &sfi,
2062 sizeof(sfi),
2063 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
2064 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES | SHGFI_ATTR_SPECIFIED);
2065
2066
2067 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
2068 {
2069 int iItemID;
2070
2071 /* Add the item at the end of the list */
2072 if(iInsertId < 0)
2073 {
2074 iItemID = CBAddString(hwnd,sfi.szDisplayName);
2075 }
2076 /* Insert the item at the iInsertId position*/
2077 else
2078 {
2079 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
2080 }
2081
2082 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
2083 return iItemID;
2084 }
2085
2086 MemFree( tmpFolder );
2087 return -1;
2088
2089}
2090
2091/***********************************************************************
2092 * FILEDLG95_LOOKIN_InsertItemAfterParent
2093 *
2094 * Insert an item below its parent
2095 */
2096static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
2097{
2098
2099 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
2100 int iParentPos;
2101
2102 TRACE("\n");
2103
2104 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
2105
2106 if(iParentPos < 0)
2107 {
2108 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
2109 }
2110
2111 /* Free pidlParent memory */
2112 COMDLG32_SHFree((LPVOID)pidlParent);
2113
2114 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
2115}
2116
2117/***********************************************************************
2118 * FILEDLG95_LOOKIN_SelectItem
2119 *
2120 * Adds an absolute pidl item to the lookin combo box
2121 * returns the index of the inserted item
2122 */
2123int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
2124{
2125 int iItemPos;
2126 LookInInfos *liInfos;
2127
2128 TRACE("\n");
2129
2130 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
2131
2132 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2133
2134 if(iItemPos < 0)
2135 {
2136 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
2137 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
2138 }
2139
2140 else
2141 {
2142 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2143 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
2144 {
2145 int iRemovedItem;
2146
2147 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
2148 break;
2149 if(iRemovedItem < iItemPos)
2150 iItemPos--;
2151 }
2152 }
2153
2154 CBSetCurSel(hwnd,iItemPos);
2155 liInfos->uSelectedItem = iItemPos;
2156
2157 return 0;
2158
2159}
2160
2161/***********************************************************************
2162 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2163 *
2164 * Remove the item with an expansion level over iExpansionLevel
2165 */
2166static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
2167{
2168 int iItemPos;
2169
2170 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2171
2172 TRACE("\n");
2173
2174 if(liInfos->iMaxIndentation <= 2)
2175 return -1;
2176
2177 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
2178 {
2179 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2180 COMDLG32_SHFree(tmpFolder->pidlItem);
2181 MemFree(tmpFolder);
2182 CBDeleteString(hwnd,iItemPos);
2183 liInfos->iMaxIndentation--;
2184
2185 return iItemPos;
2186 }
2187
2188 return -1;
2189}
2190
2191/***********************************************************************
2192 * FILEDLG95_LOOKIN_SearchItem
2193 *
2194 * Search for pidl in the lookin combo box
2195 * returns the index of the found item
2196 */
2197static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2198{
2199 int i = 0;
2200 int iCount = CBGetCount(hwnd);
2201
2202 TRACE("\n");
2203
2204 if (iCount != CB_ERR)
2205 {
2206 for(;i<iCount;i++)
2207 {
2208 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2209
2210 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2211 return i;
2212 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2213 return i;
2214 }
2215 }
2216
2217 return -1;
2218}
2219
2220/***********************************************************************
2221 * FILEDLG95_LOOKIN_Clean
2222 *
2223 * Clean the memory used by the lookin combo box
2224 */
2225static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2226{
2227 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2228 int iPos;
2229 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2230
2231 TRACE("\n");
2232
2233 /* Delete each string of the combo and their associated data */
2234 if (iCount != CB_ERR)
2235 {
2236 for(iPos = iCount-1;iPos>=0;iPos--)
2237 {
2238 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos);
2239 COMDLG32_SHFree(tmpFolder->pidlItem);
2240 MemFree(tmpFolder);
2241 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2242 }
2243 }
2244
2245 /* LookInInfos structure */
2246 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2247
2248}
2249/***********************************************************************
2250 * FILEDLG95_FILENAME_FillFromSelection
2251 *
2252 * fills the edit box from the cached DataObject
2253 */
2254void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd)
2255{
2256 FileOpenDlgInfos *fodInfos;
2257 LPITEMIDLIST pidl;
2258 UINT nFiles = 0, nFileToOpen, nFileSelected, nLength = 0;
2259 char lpstrTemp[MAX_PATH];
2260 LPSTR lpstrAllFile = NULL, lpstrCurrFile = NULL;
2261
2262 TRACE("\n");
2263 fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2264
2265 /* Count how many files we have */
2266 nFileSelected = GetNumSelected( fodInfos->Shell.FOIDataObject );
2267
2268 /* calculate the string length, count files */
2269 if (nFileSelected >= 1)
2270 {
2271 nLength += 3; /* first and last quotes, trailing \0 */
2272 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2273 {
2274 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2275
2276 if (pidl)
2277 {
2278 /* get the total length of the selected file names*/
2279 lpstrTemp[0] = '\0';
2280 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2281
2282 if ( ! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl) ) /* Ignore folders */
2283 {
2284 nLength += strlen( lpstrTemp ) + 3;
2285 nFiles++;
2286 }
2287 COMDLG32_SHFree( pidl );
2288 }
2289 }
2290 }
2291
2292 /* allocate the buffer */
2293 if (nFiles <= 1) nLength = MAX_PATH;
2294 lpstrAllFile = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength);
2295 lpstrAllFile[0] = '\0';
2296
2297 /* Generate the string for the edit control */
2298 if(nFiles >= 1)
2299 {
2300 lpstrCurrFile = lpstrAllFile;
2301 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2302 {
2303 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2304
2305 if (pidl)
2306 {
2307 /* get the file name */
2308 lpstrTemp[0] = '\0';
2309 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2310
2311 if (! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl)) /* Ignore folders */
2312 {
2313 if ( nFiles > 1)
2314 {
2315 *lpstrCurrFile++ = '\"';
2316 strcpy( lpstrCurrFile, lpstrTemp );
2317 lpstrCurrFile += strlen( lpstrTemp );
2318 strcpy( lpstrCurrFile, "\" " );
2319 lpstrCurrFile += 2;
2320 }
2321 else
2322 {
2323 strcpy( lpstrAllFile, lpstrTemp );
2324 }
2325 }
2326 COMDLG32_SHFree( (LPVOID) pidl );
2327 }
2328 }
2329 }
2330
2331 SetWindowTextA( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
2332 HeapFree(GetProcessHeap(),0, lpstrAllFile );
2333}
2334
2335
2336/* copied from shell32 to avoid linking to it */
2337static HRESULT COMDLG32_StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
2338{
2339 switch (src->uType)
2340 {
2341 case STRRET_WSTR:
2342 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
2343 COMDLG32_SHFree(src->u.pOleStr);
2344 break;
2345
2346 case STRRET_CSTRA:
2347 lstrcpynA((LPSTR)dest, src->u.cStr, len);
2348 break;
2349
2350 case STRRET_OFFSETA:
2351 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
2352 break;
2353
2354 default:
2355 FIXME("unknown type!\n");
2356 if (len)
2357 {
2358 *(LPSTR)dest = '\0';
2359 }
2360 return(FALSE);
2361 }
2362 return S_OK;
2363}
2364
2365/***********************************************************************
2366 * FILEDLG95_FILENAME_GetFileNames
2367 *
2368 * copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
2369 */
2370int FILEDLG95_FILENAME_GetFileNames (HWND hwnd, LPSTR * lpstrFileList, UINT * sizeUsed)
2371{
2372 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2373 UINT nStrCharCount = 0; /* index in src buffer */
2374 UINT nFileIndex = 0; /* index in dest buffer */
2375 UINT nFileCount = 0; /* number of files */
2376 UINT nStrLen = 0; /* length of string in edit control */
2377 LPSTR lpstrEdit; /* buffer for string from edit control */
2378
2379 TRACE("\n");
2380
2381 /* get the filenames from the edit control */
2382 nStrLen = SendMessageA(fodInfos->DlgInfos.hwndFileName, WM_GETTEXTLENGTH, 0, 0);
2383 lpstrEdit = MemAlloc(nStrLen+1);
2384 GetDlgItemTextA(hwnd, IDC_FILENAME, lpstrEdit, nStrLen+1);
2385
2386 TRACE("nStrLen=%u str=%s\n", nStrLen, lpstrEdit);
2387
2388 /* we might get single filename without any '"',
2389 * so we need nStrLen + terminating \0 + end-of-list \0 */
2390 *lpstrFileList = MemAlloc(nStrLen+2);
2391 *sizeUsed = 0;
2392
2393 /* build 0-delimited file list from filenames */
2394 while ( nStrCharCount <= nStrLen )
2395 {
2396 if ( lpstrEdit[nStrCharCount]=='"' )
2397 {
2398 nStrCharCount++;
2399 while ((lpstrEdit[nStrCharCount]!='"') && (nStrCharCount <= nStrLen))
2400 {
2401 (*lpstrFileList)[nFileIndex++] = lpstrEdit[nStrCharCount];
2402 (*sizeUsed)++;
2403 nStrCharCount++;
2404 }
2405 (*lpstrFileList)[nFileIndex++] = '\0';
2406 (*sizeUsed)++;
2407 nFileCount++;
2408 }
2409 nStrCharCount++;
2410 }
2411
2412 /* single, unquoted string */
2413 if ((nStrLen > 0) && (*sizeUsed == 0) )
2414 {
2415 strcpy(*lpstrFileList, lpstrEdit);
2416 nFileIndex = strlen(lpstrEdit) + 1;
2417 (*sizeUsed) = nFileIndex;
2418 nFileCount = 1;
2419 }
2420
2421 /* trailing \0 */
2422 (*lpstrFileList)[nFileIndex] = '\0';
2423 (*sizeUsed)++;
2424
2425 MemFree(lpstrEdit);
2426 return nFileCount;
2427}
2428
2429#define SETDefFormatEtc(fe,cf,med) \
2430{ \
2431 (fe).cfFormat = cf;\
2432 (fe).dwAspect = DVASPECT_CONTENT; \
2433 (fe).ptd =NULL;\
2434 (fe).tymed = med;\
2435 (fe).lindex = -1;\
2436};
2437
2438/*
2439 * DATAOBJECT Helper functions
2440 */
2441
2442/***********************************************************************
2443 * COMCTL32_ReleaseStgMedium
2444 *
2445 * like ReleaseStgMedium from ole32
2446 */
2447static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium)
2448{
2449 if(medium.pUnkForRelease)
2450 {
2451 IUnknown_Release(medium.pUnkForRelease);
2452 }
2453 else
2454 {
2455 GlobalUnlock(medium.u.hGlobal);
2456 GlobalFree(medium.u.hGlobal);
2457 }
2458}
2459
2460/***********************************************************************
2461 * GetPidlFromDataObject
2462 *
2463 * Return pidl(s) by number from the cached DataObject
2464 *
2465 * nPidlIndex=0 gets the fully qualified root path
2466 */
2467LPITEMIDLIST GetPidlFromDataObject ( IDataObject *doSelected, UINT nPidlIndex)
2468{
2469
2470 STGMEDIUM medium;
2471 FORMATETC formatetc;
2472 LPITEMIDLIST pidl = NULL;
2473
2474 TRACE("sv=%p index=%u\n", doSelected, nPidlIndex);
2475
2476 /* Set the FORMATETC structure*/
2477 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2478
2479 /* Get the pidls from IDataObject */
2480 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2481 {
2482 LPIDA cida = GlobalLock(medium.u.hGlobal);
2483 if(nPidlIndex <= cida->cidl)
2484 {
2485 pidl = COMDLG32_PIDL_ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[nPidlIndex]]));
2486 }
2487 COMCTL32_ReleaseStgMedium(medium);
2488 }
2489 return pidl;
2490}
2491
2492/***********************************************************************
2493 * GetNumSelected
2494 *
2495 * Return the number of selected items in the DataObject.
2496 *
2497*/
2498UINT GetNumSelected( IDataObject *doSelected )
2499{
2500 UINT retVal = 0;
2501 STGMEDIUM medium;
2502 FORMATETC formatetc;
2503
2504 TRACE("sv=%p\n", doSelected);
2505
2506 if (!doSelected) return 0;
2507
2508 /* Set the FORMATETC structure*/
2509 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2510
2511 /* Get the pidls from IDataObject */
2512 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2513 {
2514 LPIDA cida = GlobalLock(medium.u.hGlobal);
2515 retVal = cida->cidl;
2516 COMCTL32_ReleaseStgMedium(medium);
2517 return retVal;
2518 }
2519 return 0;
2520}
2521
2522/*
2523 * TOOLS
2524 */
2525
2526/***********************************************************************
2527 * GetName
2528 *
2529 * Get the pidl's display name (relative to folder) and
2530 * put it in lpstrFileName.
2531 *
2532 * Return NOERROR on success,
2533 * E_FAIL otherwise
2534 */
2535
2536HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2537{
2538 STRRET str;
2539 HRESULT hRes;
2540
2541 TRACE("sf=%p pidl=%p\n", lpsf, pidl);
2542
2543 if(!lpsf)
2544 {
2545 HRESULT hRes;
2546 COMDLG32_SHGetDesktopFolder(&lpsf);
2547 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2548 IShellFolder_Release(lpsf);
2549 return hRes;
2550 }
2551
2552 /* Get the display name of the pidl relative to the folder */
2553 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf, pidl, dwFlags, &str)))
2554 {
2555 return COMDLG32_StrRetToStrNA(lpstrFileName, MAX_PATH, &str, pidl);
2556 }
2557 return E_FAIL;
2558}
2559
2560/***********************************************************************
2561 * GetShellFolderFromPidl
2562 *
2563 * pidlRel is the item pidl relative
2564 * Return the IShellFolder of the absolute pidl
2565 */
2566IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2567{
2568 IShellFolder *psf = NULL,*psfParent;
2569
2570 TRACE("%p\n", pidlAbs);
2571
2572 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
2573 {
2574 psf = psfParent;
2575 if(pidlAbs && pidlAbs->mkid.cb)
2576 {
2577 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2578 {
2579 IShellFolder_Release(psfParent);
2580 return psf;
2581 }
2582 }
2583 /* return the desktop */
2584 return psfParent;
2585 }
2586 return NULL;
2587}
2588
2589/***********************************************************************
2590 * GetParentPidl
2591 *
2592 * Return the LPITEMIDLIST to the parent of the pidl in the list
2593 */
2594LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2595{
2596 LPITEMIDLIST pidlParent;
2597
2598 TRACE("%p\n", pidl);
2599
2600 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2601 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2602
2603 return pidlParent;
2604}
2605
2606/***********************************************************************
2607 * GetPidlFromName
2608 *
2609 * returns the pidl of the file name relative to folder
2610 * NULL if an error occured
2611 */
2612LPITEMIDLIST GetPidlFromName(IShellFolder *lpsf,LPCSTR lpcstrFileName)
2613{
2614 LPITEMIDLIST pidl;
2615 ULONG ulEaten;
2616 WCHAR lpwstrDirName[MAX_PATH];
2617
2618 TRACE("sf=%p file=%s\n", lpsf, lpcstrFileName);
2619
2620 if(!lpcstrFileName) return NULL;
2621
2622 MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpcstrFileName,-1,(LPWSTR)lpwstrDirName,MAX_PATH);
2623
2624 if(!lpsf)
2625 {
2626 COMDLG32_SHGetDesktopFolder(&lpsf);
2627 pidl = GetPidlFromName(lpsf, lpcstrFileName);
2628 IShellFolder_Release(lpsf);
2629 }
2630 else
2631 {
2632 IShellFolder_ParseDisplayName(lpsf, 0, NULL, (LPWSTR)lpwstrDirName, &ulEaten, &pidl, NULL);
2633 }
2634 return pidl;
2635}
2636
2637/*
2638*/
2639BOOL IsPidlFolder (LPSHELLFOLDER psf, LPITEMIDLIST pidl)
2640{
2641 ULONG uAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
2642 HRESULT ret;
2643
2644 TRACE("%p, %p\n", psf, pidl);
2645
2646 ret = IShellFolder_GetAttributesOf( psf, 1, &pidl, &uAttr );
2647
2648 TRACE("-- 0x%08lx 0x%08lx\n", uAttr, ret);
2649 /* see documentation shell 4.1*/
2650 return uAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
2651}
2652
2653/***********************************************************************
2654 * BrowseSelectedFolder
2655 */
2656static BOOL BrowseSelectedFolder(HWND hwnd)
2657{
2658 BOOL bBrowseSelFolder = FALSE;
2659 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2660
2661 TRACE("\n");
2662
2663 if (GetNumSelected(fodInfos->Shell.FOIDataObject) == 1)
2664 {
2665 LPITEMIDLIST pidlSelection;
2666
2667 /* get the file selected */
2668 pidlSelection = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, 1);
2669 if (IsPidlFolder (fodInfos->Shell.FOIShellFolder, pidlSelection))
2670 {
2671 if ( FAILED( IShellBrowser_BrowseObject( fodInfos->Shell.FOIShellBrowser,
2672 pidlSelection, SBSP_RELATIVE ) ) )
2673 {
2674 MessageBoxA( hwnd, "Path does not exist", fodInfos->ofnInfos->lpstrTitle,
2675 MB_OK | MB_ICONEXCLAMATION );
2676 }
2677
2678 bBrowseSelFolder = TRUE;
2679 }
2680 COMDLG32_SHFree( pidlSelection );
2681 }
2682
2683 return bBrowseSelFolder;
2684}
2685
2686/*
2687 * Memory allocation methods */
2688static void *MemAlloc(UINT size)
2689{
2690 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2691}
2692
2693static void MemFree(void *mem)
2694{
2695 if(mem)
2696 {
2697 HeapFree(GetProcessHeap(),0,mem);
2698 }
2699}
2700
Note: See TracBrowser for help on using the repository browser.