source: trunk/src/comdlg32/filedlg95.cpp@ 1689

Last change on this file since 1689 was 1677, checked in by phaller, 26 years ago

Fix: fixes in file open dialogs

File size: 64.8 KB
Line 
1/* $Id: filedlg95.cpp,v 1.3 1999-11-09 22:38:57 phaller Exp $ */
2/*
3 * COMMDLG - File Open Dialogs Win95 look and feel
4 *
5 */
6#include <ctype.h>
7#include <stdlib.h>
8#include <string.h>
9#ifdef __WIN32OS2__
10// ><DJR 17.05.99 Force to use C-interfaces for now to prevent CALLBACK definition compiler error
11#define CINTERFACE 1
12#include <os2win.h>
13#else
14#include "winbase.h"
15#include "tweak.h"
16#endif
17#include "ldt.h"
18#include "heap.h"
19#include "commdlg.h"
20#include "dlgs.h"
21#include "cdlg.h"
22#include "debugtools.h"
23#include "cderr.h"
24#include "winnls.h"
25#include "shellapi.h"
26#include "tchar.h"
27#include "filedlgbrowser.h"
28#include "wine/obj_contextmenu.h"
29
30#ifdef __WIN32OS2__
31#include <heapstring.h>
32
33#define MapHModuleSL(a) a
34#define MapHModuleLS(a) a
35#endif
36
37DEFAULT_DEBUG_CHANNEL(commdlg)
38
39
40/***********************************************************************
41 * Data structure and global variables
42 */
43typedef struct SFolder
44{
45 int m_iImageIndex; /* Index of picture in image list */
46 HIMAGELIST hImgList;
47 int m_iIndent; /* Indentation index */
48 LPITEMIDLIST pidlItem; /* absolute pidl of the item */
49
50} SFOLDER,*LPSFOLDER;
51
52typedef struct tagLookInInfo
53{
54 int iMaxIndentation;
55 UINT uSelectedItem;
56} LookInInfos;
57
58
59/***********************************************************************
60 * Defines and global variables
61 */
62
63/* Draw item constant */
64#define ICONWIDTH 18
65#define YTEXTOFFSET 2
66#define XTEXTOFFSET 3
67
68/* AddItem flags*/
69#define LISTEND -1
70
71/* SearchItem methods */
72#define SEARCH_PIDL 1
73#define SEARCH_EXP 2
74#define ITEM_NOTFOUND -1
75
76/* Undefined windows message sent by CreateViewObject*/
77#define WM_GETISHELLBROWSER WM_USER+7
78
79/* NOTE
80 * Those macros exist in windowsx.h. However, you can't really use them since
81 * they rely on the UNICODE defines and can't be use inside Wine itself.
82 */
83
84/* Combo box macros */
85#define CBAddString(hwnd,str) \
86 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
87
88#define CBInsertString(hwnd,str,pos) \
89 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
90
91#define CBDeleteString(hwnd,pos) \
92 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
93
94#define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
95 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
96
97#define CBGetItemDataPtr(hwnd,iItemId) \
98 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
99
100#define CBGetLBText(hwnd,iItemId,str) \
101 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
102
103#define CBGetCurSel(hwnd) \
104 SendMessageA(hwnd,CB_GETCURSEL,0,0);
105
106#define CBSetCurSel(hwnd,pos) \
107 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
108
109#define CBGetCount(hwnd) \
110 SendMessageA(hwnd,CB_GETCOUNT,0,0);
111#define CBShowDropDown(hwnd,show) \
112 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
113#define CBSetItemHeight(hwnd,index,height) \
114 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
115
116
117const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
118const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
119
120static const char defaultFilter[] = "*.*";
121
122/***********************************************************************
123 * Prototypes
124 */
125
126/* Internal functions used by the dialog */
127static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam);
128static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
129static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
130 BOOL FILEDLG95_OnOpen(HWND hwnd);
131static LRESULT FILEDLG95_InitUI(HWND hwnd);
132static void FILEDLG95_Clean(HWND hwnd);
133
134/* Functions used by the shell object */
135static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
136static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
137static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
138static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd);
139static void FILEDLG95_SHELL_Clean(HWND hwnd);
140
141/* Functions used by the filetype combo box */
142static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
143static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
144static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt);
145static void FILEDLG95_FILETYPE_Clean(HWND hwnd);
146
147/* Functions used by the Look In combo box */
148static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo);
149static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
150static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
151static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
152static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
153static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
154static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
155 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
156static void FILEDLG95_LOOKIN_Clean(HWND hwnd);
157
158/* Miscellaneous tool functions */
159HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
160HRESULT GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
161IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
162LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
163LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
164
165/* Shell memory allocation */
166char *MemAlloc(UINT size);
167void MemFree(void *mem);
168
169BOOL WINAPI GetOpenFileName95(FileOpenDlgInfos *fodInfos);
170BOOL WINAPI GetSaveFileName95(FileOpenDlgInfos *fodInfos);
171HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
172
173/***********************************************************************
174 * GetOpenFileName95
175 *
176 * Creates an Open common dialog box that lets the user select
177 * the drive, directory, and the name of a file or set of files to open.
178 *
179 * IN : The FileOpenDlgInfos structure associated with the dialog
180 * OUT : TRUE on success
181 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
182 */
183BOOL WINAPI GetOpenFileName95(FileOpenDlgInfos *fodInfos)
184{
185
186 LRESULT lRes;
187 LPCVOID templateDlg;
188 HRSRC hRes;
189 HANDLE hDlgTmpl = 0;
190
191 /* Create the dialog from a template */
192
193 if(!(hRes = FindResourceA(COMDLG32_hInstance,MAKEINTRESOURCEA(IDD_OPENDIALOG),RT_DIALOGA)))
194 {
195 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
196 return FALSE;
197 }
198 if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hRes )) ||
199 !(templateDlg = LockResource( hDlgTmpl )))
200 {
201 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
202 return FALSE;
203 }
204 lRes = DialogBoxIndirectParamA(COMDLG32_hInstance,
205 (LPDLGTEMPLATEA) templateDlg,
206 fodInfos->ofnInfos.hwndOwner,
207 (DLGPROC) FileOpenDlgProc95,
208 (LPARAM) fodInfos);
209
210 /* Unable to create the dialog*/
211 if( lRes == -1)
212 return FALSE;
213
214 return lRes;
215}
216
217/***********************************************************************
218 * GetSaveFileName95
219 *
220 * Creates an Save as common dialog box that lets the user select
221 * the drive, directory, and the name of a file or set of files to open.
222 *
223 * IN : The FileOpenDlgInfos structure associated with the dialog
224 * OUT : TRUE on success
225 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
226 */
227BOOL WINAPI GetSaveFileName95(FileOpenDlgInfos *fodInfos)
228{
229
230 LRESULT lRes;
231 LPCVOID templateDlg;
232 HRSRC hRes;
233 HANDLE hDlgTmpl = 0;
234
235 /* Create the dialog from a template */
236
237 if(!(hRes = FindResourceA(COMDLG32_hInstance,MAKEINTRESOURCEA(IDD_SAVEDIALOG),RT_DIALOGA)))
238 {
239 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
240 return FALSE;
241 }
242 if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hRes )) ||
243 !(templateDlg = LockResource( hDlgTmpl )))
244 {
245 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
246 return FALSE;
247 }
248 lRes = DialogBoxIndirectParamA(COMDLG32_hInstance,
249 (LPDLGTEMPLATEA) templateDlg,
250 fodInfos->ofnInfos.hwndOwner,
251 (DLGPROC) FileOpenDlgProc95,
252 (LPARAM) fodInfos);
253 /* Unable to create the dialog*/
254 if( lRes == -1)
255 return FALSE;
256
257 return lRes;
258}
259
260/***********************************************************************
261 * GetFileDialog95A
262 *
263 * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
264 * Call GetOpenFileName95 with this structure and clean the memory.
265 *
266 * IN : The OPENFILENAMEA initialisation structure passed to
267 * GetOpenFileNameA win api function (see filedlg.c)
268 */
269BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
270{
271
272 BOOL ret;
273 FileOpenDlgInfos *fodInfos;
274
275 /* Initialise FileOpenDlgInfos structure*/
276 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
277 memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn)); fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
278 fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
279 fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
280 if (ofn->lpstrFilter)
281 {
282 LPSTR s,x;
283
284 /* filter is a list... title\0ext\0......\0\0 */
285 s = (LPSTR)ofn->lpstrFilter;
286 while (*s)
287 s = s+strlen(s)+1;
288 s++;
289 x = (LPSTR)MemAlloc(s-ofn->lpstrFilter);
290 memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
291 fodInfos->ofnInfos.lpstrFilter = (LPSTR)x;
292 }
293 if (ofn->lpstrCustomFilter)
294 {
295 LPSTR s,x;
296
297 /* filter is a list... title\0ext\0......\0\0 */
298 s = (LPSTR)ofn->lpstrCustomFilter;
299 while (*s)
300 s = s+strlen(s)+1;
301 s++;
302 x = MemAlloc(s-ofn->lpstrCustomFilter);
303 memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
304 fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)x;
305 }
306 fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
307 if(ofn->nFilterIndex)
308 fodInfos->ofnInfos.nFilterIndex = --ofn->nFilterIndex;
309 if (ofn->nMaxFile)
310 {
311 fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
312 strcpy((LPSTR)fodInfos->ofnInfos.lpstrFile,ofn->lpstrFile);
313 }
314 fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
315 fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
316 if (fodInfos->ofnInfos.nMaxFileTitle)
317 fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
318 if (ofn->lpstrInitialDir)
319 {
320 fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(strlen(ofn->lpstrInitialDir)+1);
321 strcpy((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,ofn->lpstrInitialDir);
322 }
323
324 if (ofn->lpstrTitle)
325 {
326 fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(strlen(ofn->lpstrTitle)+1);
327 strcpy((LPSTR)fodInfos->ofnInfos.lpstrTitle,ofn->lpstrTitle);
328 }
329
330 fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE;
331 fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
332 fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
333 if (ofn->lpstrDefExt)
334 {
335 fodInfos->ofnInfos.lpstrDefExt = MemAlloc(strlen(ofn->lpstrDefExt)+1);
336 strcpy((LPSTR)fodInfos->ofnInfos.lpstrDefExt,ofn->lpstrDefExt);
337 }
338 fodInfos->ofnInfos.lCustData = ofn->lCustData;
339 fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
340
341 if (ofn->lpTemplateName)
342 {
343 fodInfos->ofnInfos.lpTemplateName = ofn->lpTemplateName;
344 }
345
346 /* Replace the NULL lpstrInitialDir by the current folder */
347 if(!ofn->lpstrInitialDir)
348 {
349 fodInfos->ofnInfos.lpstrInitialDir = MemAlloc(MAX_PATH);
350 GetCurrentDirectoryA(MAX_PATH,(LPSTR)fodInfos->ofnInfos.lpstrInitialDir);
351 }
352
353 /* Initialise the dialog property */
354 fodInfos->DlgInfos.dwDlgProp = 0;
355
356 switch(iDlgType)
357 {
358 case OPEN_DIALOG :
359 ret = GetOpenFileName95(fodInfos);
360 break;
361 case SAVE_DIALOG :
362 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
363 ret = GetSaveFileName95(fodInfos);
364 break;
365 default :
366 ret = 0;
367 }
368
369 ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
370 ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
371 if (fodInfos->ofnInfos.lpstrFilter)
372 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
373 if (fodInfos->ofnInfos.lpTemplateName)
374 MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
375 if (fodInfos->ofnInfos.lpstrDefExt)
376 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
377 if (fodInfos->ofnInfos.lpstrTitle)
378 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
379 if (fodInfos->ofnInfos.lpstrInitialDir)
380 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
381 if (fodInfos->ofnInfos.lpstrCustomFilter)
382 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
383
384 if (fodInfos->ofnInfos.lpstrFile)
385 {
386 strcpy(ofn->lpstrFile,fodInfos->ofnInfos.lpstrFile);
387 MemFree((LPVOID)fodInfos->ofnInfos.lpstrFile);
388 }
389 if (fodInfos->ofnInfos.lpstrFileTitle)
390 {
391 if (ofn->lpstrFileTitle)
392 strcpy(ofn->lpstrFileTitle,
393 fodInfos->ofnInfos.lpstrFileTitle);
394 MemFree((LPVOID)fodInfos->ofnInfos.lpstrFileTitle);
395 }
396
397 MemFree((LPVOID)(fodInfos));
398 return ret;
399}
400
401/***********************************************************************
402 * GetFileDialog95W
403 *
404 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
405 * Call GetOpenFileName95 with this structure and clean the memory.
406 *
407 * IN : The OPENFILENAMEW initialisation structure passed to
408 * GetOpenFileNameW win api function (see filedlg.c)
409 */
410BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
411{
412 BOOL ret;
413 FileOpenDlgInfos *fodInfos;
414
415 /* Initialise FileOpenDlgInfos structure*/
416 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
417 memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn));
418 fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
419 fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
420 fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
421 if (ofn->lpstrFilter)
422 {
423 LPWSTR s;
424 LPSTR x,y;
425 int n;
426
427 /* filter is a list... title\0ext\0......\0\0 */
428 s = (LPWSTR)ofn->lpstrFilter;
429
430 while (*s)
431 s = s+lstrlenW(s)+1;
432 s++;
433 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
434 x = y = (LPSTR)MemAlloc(n);
435 s = (LPWSTR)ofn->lpstrFilter;
436 while (*s) {
437 lstrcpyWtoA(x,s);
438 x+=lstrlenA(x)+1;
439 s+=lstrlenW(s)+1;
440 }
441 *x=0;
442 fodInfos->ofnInfos.lpstrFilter = (LPSTR)y;
443 }
444 if (ofn->lpstrCustomFilter) {
445 LPWSTR s;
446 LPSTR x,y;
447 int n;
448
449 /* filter is a list... title\0ext\0......\0\0 */
450 s = (LPWSTR)ofn->lpstrCustomFilter;
451 while (*s)
452 s = s+lstrlenW(s)+1;
453 s++;
454 n = s - ofn->lpstrCustomFilter;
455 x = y = (LPSTR)MemAlloc(n);
456 s = (LPWSTR)ofn->lpstrCustomFilter;
457 while (*s) {
458 lstrcpyWtoA(x,s);
459 x+=lstrlenA(x)+1;
460 s+=lstrlenW(s)+1;
461 }
462 *x=0;
463 fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)y;
464 }
465 fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
466 fodInfos->ofnInfos.nFilterIndex = ofn->nFilterIndex;
467 if (ofn->nMaxFile)
468 fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
469 fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
470 fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
471 if (ofn->nMaxFileTitle)
472 fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
473 if (ofn->lpstrInitialDir)
474 {
475 fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrInitialDir)+1);
476 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,(LPWSTR)ofn->lpstrInitialDir);
477 }
478 if (ofn->lpstrTitle)
479 {
480 fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrTitle)+1);
481 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrTitle,(LPWSTR)ofn->lpstrTitle);
482 }
483 fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
484 fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
485 fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
486 if (ofn->lpstrDefExt)
487 {
488 fodInfos->ofnInfos.lpstrDefExt = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrDefExt)+1);
489 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrDefExt,(LPWSTR)ofn->lpstrDefExt);
490 }
491 fodInfos->ofnInfos.lCustData = ofn->lCustData;
492 fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
493 if (ofn->lpTemplateName)
494 {
495 fodInfos->ofnInfos.lpTemplateName = (LPSTR)MemAlloc(lstrlenW(ofn->lpTemplateName)+1);
496 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpTemplateName,(LPWSTR)ofn->lpTemplateName);
497 }
498 /* Initialise the dialog property */
499 fodInfos->DlgInfos.dwDlgProp = 0;
500
501 switch(iDlgType)
502 {
503 case OPEN_DIALOG :
504 ret = GetOpenFileName95(fodInfos);
505 break;
506 case SAVE_DIALOG :
507 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
508 ret = GetSaveFileName95(fodInfos);
509 break;
510 default :
511 ret = 0;
512 }
513
514 /* Cleaning */
515 ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
516 ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
517 if (fodInfos->ofnInfos.lpstrFilter)
518 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
519 if (fodInfos->ofnInfos.lpTemplateName)
520 MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
521 if (fodInfos->ofnInfos.lpstrDefExt)
522 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
523 if (fodInfos->ofnInfos.lpstrTitle)
524 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
525 if (fodInfos->ofnInfos.lpstrInitialDir)
526 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
527 if (fodInfos->ofnInfos.lpstrCustomFilter)
528 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
529
530 if (fodInfos->ofnInfos.lpstrFile) {
531 lstrcpyAtoW(ofn->lpstrFile,(fodInfos->ofnInfos.lpstrFile));
532 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFile));
533 }
534
535 if (fodInfos->ofnInfos.lpstrFileTitle) {
536 if (ofn->lpstrFileTitle)
537 lstrcpyAtoW(ofn->lpstrFileTitle,
538 (fodInfos->ofnInfos.lpstrFileTitle));
539 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFileTitle));
540 }
541 MemFree((LPVOID)(fodInfos));
542 return ret;
543
544}
545
546void ArrangeCtrlPositions( HWND hwndChildDlg, HWND hwndParentDlg)
547{
548
549 HWND hwndChild,hwndStc32;
550 RECT rectParent,rectChild,rectCtrl,rectStc32;
551 POINT ptMoveCtl;
552 HDWP handle;
553 POINT ptParentClient;
554
555 ptMoveCtl.x = ptMoveCtl.y = 0;
556 hwndStc32=GetDlgItem(hwndChildDlg,stc32);
557 GetClientRect(hwndParentDlg,&rectParent);
558 GetClientRect(hwndChildDlg,&rectChild);
559 if(hwndStc32)
560 {
561 RECT rectTemp;
562 GetWindowRect(hwndStc32,&rectStc32);
563 MapWindowPoints(0, hwndChildDlg,(LPPOINT)&rectStc32,2);
564 CopyRect(&rectTemp,&rectStc32);
565
566 SetRect(&rectStc32,rectStc32.left,rectStc32.top,rectStc32.left + (rectParent.right-rectParent.left),rectStc32.top+(rectParent.bottom-rectParent.top));
567 SetWindowPos(hwndStc32,0,rectStc32.left,rectStc32.top,rectStc32.right-rectStc32.left,rectStc32.bottom-rectStc32.top,SWP_NOMOVE|SWP_NOZORDER | SWP_NOACTIVATE);
568 if(rectStc32.right < rectTemp.right)
569 {
570 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
571 ptMoveCtl.x = 0;
572 }
573 else
574 {
575 ptMoveCtl.x = (rectStc32.right - rectTemp.right);
576 ptParentClient.x = max((rectParent.right-rectParent.left),((rectChild.right-rectChild.left)+rectStc32.right-rectTemp.right));
577 }
578 if(rectStc32.bottom < rectTemp.bottom)
579 {
580 ptParentClient.y = max((rectParent.bottom-rectParent.top),(rectChild.bottom-rectChild.top));
581 ptMoveCtl.y = 0;
582 }
583 else
584 {
585 ptMoveCtl.y = (rectStc32.bottom - rectTemp.bottom);
586 ptParentClient.y = max((rectParent.bottom-rectParent.top),((rectChild.bottom-rectChild.top)+rectStc32.bottom-rectTemp.bottom));
587 }
588 }
589 else
590 {
591 if( (GetWindow(hwndChildDlg,GW_CHILD)) == (HWND) NULL)
592 return;
593 ptParentClient.x = rectParent.right-rectParent.left;
594 ptParentClient.y = (rectParent.bottom-rectParent.top) + (rectChild.bottom-rectChild.top);
595 ptMoveCtl.y = rectParent.bottom-rectParent.top;
596 ptMoveCtl.x=0;
597 }
598 SetRect(&rectParent,rectParent.left,rectParent.top,rectParent.left+ptParentClient.x,rectParent.top+ptParentClient.y);
599 AdjustWindowRectEx( &rectParent,GetWindowLongA(hwndParentDlg,GWL_STYLE),FALSE,GetWindowLongA(hwndParentDlg,GWL_EXSTYLE));
600
601 SetWindowPos(hwndChildDlg, 0, 0,0, ptParentClient.x,ptParentClient.y,
602 SWP_NOZORDER );
603 SetWindowPos(hwndParentDlg, 0, rectParent.left,rectParent.top, (rectParent.right- rectParent.left),
604 (rectParent.bottom-rectParent.top),SWP_NOMOVE | SWP_NOZORDER);
605
606 hwndChild = GetWindow(hwndChildDlg,GW_CHILD);
607 handle = BeginDeferWindowPos( 1 );
608 if(hwndStc32)
609 {
610 GetWindowRect(hwndStc32,&rectStc32);
611 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
612 }
613 else
614 SetRect(&rectStc32,0,0,0,0);
615 if (hwndChild && handle)
616 {
617 do
618 {
619 if(hwndChild != hwndStc32)
620 {
621 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
622 continue;
623 GetWindowRect(hwndChild,&rectCtrl);
624 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
625 if(rectCtrl.top > rectStc32.top)
626 {
627
628 if(ptMoveCtl.x > 0)
629 rectCtrl.left += ptMoveCtl.x;
630 rectCtrl.top += ptMoveCtl.y;
631 handle = DeferWindowPos(handle, hwndChild, 0, rectCtrl.left, rectCtrl.top,
632 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
633 SWP_NOSIZE | SWP_NOZORDER );
634 }
635 }
636 }
637 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL && handle);
638 }
639 if(handle)
640 EndDeferWindowPos( handle );
641 handle = BeginDeferWindowPos( 1 );
642 hwndChild = GetWindow(hwndParentDlg,GW_CHILD);
643 if(hwndStc32)
644 {
645 GetWindowRect(hwndStc32,&rectStc32);
646 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
647 ptMoveCtl.x = rectStc32.left - 0;
648 ptMoveCtl.y = rectStc32.top - 0;
649 if (hwndChild && handle)
650 {
651 do
652 {
653 if(hwndChild != hwndChildDlg)
654 {
655
656 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
657 continue;
658 GetWindowRect(hwndChild,&rectCtrl);
659 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
660
661 rectCtrl.left += ptMoveCtl.x;
662 rectCtrl.top += ptMoveCtl.y;
663
664 handle = DeferWindowPos( handle, hwndChild, 0, rectCtrl.left, rectCtrl.top,
665 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
666 SWP_NOSIZE |SWP_NOZORDER );
667 }
668 }
669 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
670 }
671 if(handle)
672 EndDeferWindowPos( handle );
673 }
674
675}
676
677
678HRESULT WINAPI FileOpenDlgProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
679{
680 static WNDPROC procUserHook=NULL;
681 switch(uMsg)
682 {
683 case WM_INITDIALOG:
684 {
685 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *)lParam;
686 procUserHook=NULL;
687 lParam = (LPARAM) &fodInfos->ofnInfos;
688 ArrangeCtrlPositions(hwnd,GetParent(hwnd));
689 if(fodInfos->ofnInfos.Flags & OFN_ENABLEHOOK)
690 procUserHook = (WNDPROC) fodInfos->ofnInfos.lpfnHook;
691 if(procUserHook)
692 return CallWindowProcA(procUserHook,hwnd,uMsg,wParam,lParam);
693 return 0;
694 } }
695 if(procUserHook)
696 return CallWindowProcA(procUserHook,hwnd,uMsg,wParam,lParam);
697 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
698}
699
700HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos,HWND hwnd)
701{
702 LPCVOID templateDlg;
703 HRSRC hRes;
704 HANDLE hDlgTmpl = 0;
705 HWND hChildDlg = 0;
706 if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATE || fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATEHANDLE)
707 {
708 if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATEHANDLE)
709 {
710 if( !(templateDlg = LockResource( fodInfos->ofnInfos.hInstance)))
711 {
712 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
713 return (HWND)NULL;
714 }
715
716 }
717 else
718 {
719 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos.hInstance),
720 (fodInfos->ofnInfos.lpTemplateName), RT_DIALOGA)))
721 {
722 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
723 return (HWND)NULL;
724 }
725 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos.hInstance),
726 hRes )) ||
727 !(templateDlg = LockResource( hDlgTmpl )))
728 {
729 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
730 return (HWND)NULL;
731 }
732 }
733
734 hChildDlg= CreateDialogIndirectParamA(fodInfos->ofnInfos.hInstance,(LPCDLGTEMPLATEA)templateDlg,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
735 if(hChildDlg)
736 {
737 ShowWindow(hChildDlg,SW_SHOW);
738 return hChildDlg;
739 }
740 }
741 else if(fodInfos->ofnInfos.Flags & OFN_ENABLEHOOK && fodInfos->ofnInfos.lpfnHook)
742 {
743 RECT rectHwnd;
744 DLGTEMPLATE tmplate;
745 GetClientRect(hwnd,&rectHwnd);
746 tmplate.style = WS_CHILD | WS_CLIPSIBLINGS;
747 tmplate.dwExtendedStyle = 0;
748 tmplate.cdit = 0;
749 tmplate.x = 0;
750 tmplate.y = 0;
751 tmplate.cx = rectHwnd.right-rectHwnd.left;
752 tmplate.cy = rectHwnd.bottom-rectHwnd.top;
753
754 return CreateDialogIndirectParamA(fodInfos->ofnInfos.hInstance,&tmplate,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
755 }
756return (HWND)NULL;
757}
758
759/***********************************************************************
760 * FileOpenDlgProc95
761 *
762 * File open dialog procedure
763 */
764HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
765{
766
767 switch(uMsg)
768 {
769 case WM_INITDIALOG :
770 CreateTemplateDialog((FileOpenDlgInfos *)lParam,hwnd);
771 return FILEDLG95_OnWMInitDialog(hwnd, wParam, lParam);
772 case WM_COMMAND:
773 return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
774 case WM_DRAWITEM:
775 {
776 switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
777 {
778 case IDC_LOOKIN:
779 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
780 return TRUE;
781 }
782 }
783 return FALSE;
784
785 case WM_GETISHELLBROWSER:
786 return FILEDLG95_OnWMGetIShellBrowser(hwnd);
787
788 case WM_DESTROY:
789 RemovePropA(hwnd, FileOpenDlgInfosStr);
790
791 default :
792 return FALSE;
793 }
794}
795
796/***********************************************************************
797 * FILEDLG95_OnWMInitDialog
798 *
799 * WM_INITDIALOG message handler
800 */
801static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam)
802{
803 LPITEMIDLIST pidlItemId;
804 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
805
806 TRACE("\n");
807
808 /* Adds the FileOpenDlgInfos in the property list of the dialog
809 so it will be easily accessible through a GetPropA(...) */
810 SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) fodInfos);
811
812#ifndef __WIN32OS2__
813 /* Make sure the common control DLL is loaded */
814 InitCommonControls();
815#endif
816
817 /* Initialise shell objects */
818 FILEDLG95_SHELL_Init(hwnd);
819
820 /* Initialise dialog UI */
821 FILEDLG95_InitUI(hwnd);
822
823 /* Initialize the Look In combo box*/
824 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
825
826 /* Initialize the filter combo box */
827 FILEDLG95_FILETYPE_Init(hwnd);
828
829 /* Get the initial directory pidl */
830
831 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos.lpstrInitialDir)))
832 {
833 char path[MAX_PATH];
834
835 GetCurrentDirectoryA(MAX_PATH,path);
836 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
837 path);
838
839 }
840
841 /* Browse to the initial directory */
842 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId,SBSP_RELATIVE);
843
844 /* Free pidlItem memory */
845 COMDLG32_SHFree(pidlItemId);
846
847 return TRUE;
848}
849/***********************************************************************
850 * FILEDLG95_Clean
851 *
852 * Regroups all the cleaning functions of the filedlg
853 */
854void FILEDLG95_Clean(HWND hwnd)
855{
856 FILEDLG95_FILETYPE_Clean(hwnd);
857 FILEDLG95_LOOKIN_Clean(hwnd);
858 FILEDLG95_SHELL_Clean(hwnd);
859}
860/***********************************************************************
861 * FILEDLG95_OnWMCommand
862 *
863 * WM_COMMAND message handler
864 */
865static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
866{
867 WORD wNotifyCode = HIWORD(wParam); /* notification code */
868 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
869 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
870
871 switch(wID)
872 {
873 /* OK button */
874 case IDOK:
875 FILEDLG95_OnOpen(hwnd);
876 break;
877 /* Cancel button */
878 case IDCANCEL:
879 FILEDLG95_Clean(hwnd);
880 EndDialog(hwnd, FALSE);
881 break;
882 /* Filetype combo box */
883 case IDC_FILETYPE:
884 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
885 break;
886 /* LookIn combo box */
887 case IDC_LOOKIN:
888 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
889 break;
890 /* Up folder button */
891 case IDC_UPFOLDER:
892 FILEDLG95_SHELL_UpFolder(hwnd);
893 break;
894 /* List option button */
895 case IDC_LIST:
896 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
897 break;
898 /* Details option button */
899 case IDC_DETAILS:
900 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
901 break;
902 /* New folder button */
903 case IDC_NEWFOLDER:
904 FILEDLG95_SHELL_NewFolder(hwnd);
905 break;
906
907 case IDC_FILENAME:
908 break;
909
910 }
911 /* Do not use the listview selection anymore */
912
913 // @@@PH 1999/11/09
914 if (fodInfos != NULL)
915 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
916
917 return 0;
918}
919
920/***********************************************************************
921 * FILEDLG95_OnWMGetIShellBrowser
922 *
923 * WM_GETISHELLBROWSER message handler
924 */
925static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
926{
927
928 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
929
930 TRACE("\n");
931
932 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
933
934 return TRUE;
935}
936
937
938/***********************************************************************
939 * FILEDLG95_InitUI
940 *
941 */
942static LRESULT FILEDLG95_InitUI(HWND hwnd)
943{
944 HIMAGELIST himlToolbar;
945 HICON hicon;
946 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
947
948 TRACE("%p\n", fodInfos);
949
950 /* Get the hwnd of the controls */
951 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
952 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
953 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
954
955 ShowWindow(GetDlgItem(hwnd,IDC_SHELLSTATIC),SW_HIDE);
956 /* Load the icons bitmaps */
957
958 if((himlToolbar = COMDLG32_ImageList_LoadImageA(COMDLG32_hInstance,
959 MAKEINTRESOURCEA(IDB_TOOLBAR),
960 0,
961 1,
962 CLR_DEFAULT,
963 IMAGE_BITMAP,
964 0)))
965 {
966 /* Up folder icon */
967 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,0,ILD_NORMAL)))
968 SendDlgItemMessageA(hwnd,IDC_UPFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
969 /* New folder icon */
970 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,1,ILD_NORMAL)))
971 SendDlgItemMessageA(hwnd,IDC_NEWFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
972 /* List view icon */
973 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,2,ILD_NORMAL)))
974 SendDlgItemMessageA(hwnd,IDC_LIST,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
975 /* Detail view icon */
976 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,3,ILD_NORMAL)))
977 SendDlgItemMessageA(hwnd,IDC_DETAILS,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
978 /* Cleanup */
979 COMDLG32_ImageList_Destroy(himlToolbar);
980 }
981
982
983
984 /* Set the window text with the text specified in the OPENFILENAME structure */
985 if(fodInfos->ofnInfos.lpstrTitle)
986 SetWindowTextA(hwnd,fodInfos->ofnInfos.lpstrTitle);
987
988 /* Initialise the file name edit control */
989 if(strlen(fodInfos->ofnInfos.lpstrFile))
990 {
991 SetDlgItemTextA(hwnd,IDC_FILENAME,fodInfos->ofnInfos.lpstrFile);
992 }
993 /* Must the open as read only check box be checked ?*/
994 if(fodInfos->ofnInfos.Flags & OFN_READONLY)
995 {
996 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
997 }
998 /* Must the open as read only check box be hid ?*/
999 if(fodInfos->ofnInfos.Flags & OFN_HIDEREADONLY)
1000 {
1001 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
1002 }
1003
1004 /* List View is selected by default */
1005 SendDlgItemMessageA(hwnd, IDC_LIST, BM_SETCHECK,(WPARAM) BST_CHECKED,0);
1006
1007 return 0;
1008}
1009
1010/***********************************************************************
1011 * FILEDLG95_OnOpen
1012 *
1013 * Ok button WM_COMMAND message handler
1014 *
1015 * If the function succeeds, the return value is nonzero.
1016 */
1017BOOL FILEDLG95_OnOpen(HWND hwnd)
1018{
1019 char lpstrSpecifiedByUser[MAX_PATH] = "";
1020 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1021 LPITEMIDLIST pidlSelection;
1022
1023 TRACE("\n");
1024
1025 /* Check if there is a selected item in the listview */
1026 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_USEVIEW)
1027 {
1028 pidlSelection = GetSelectedPidl(fodInfos->Shell.FOIShellView);
1029 GetName(fodInfos->Shell.FOIShellFolder,pidlSelection,SHGDN_NORMAL,lpstrSpecifiedByUser);
1030 COMDLG32_SHFree((LPVOID)pidlSelection);
1031 }
1032 else
1033 /* Get the text from the filename edit */
1034 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrSpecifiedByUser,MAX_PATH);
1035
1036 if(strlen(lpstrSpecifiedByUser))
1037 {
1038 LPSHELLFOLDER psfDesktop;
1039 LPITEMIDLIST browsePidl;
1040 LPSTR lpstrFileSpec;
1041 LPSTR lpstrTemp;
1042 char lpstrPathSpec[MAX_PATH] = "";
1043 char lpstrCurrentDir[MAX_PATH] = "";
1044 char lpstrPathAndFile[MAX_PATH] = "";
1045
1046 /* Separate the file spec from the path spec
1047 e.g.:
1048 lpstrSpecifiedByUser lpstrPathSpec lpstrFileSpec
1049 C:\TEXT1\TEXT2 C:\TEXT1 TEXT2
1050 */
1051 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser);
1052 strcpy(lpstrPathSpec,lpstrSpecifiedByUser);
1053 COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
1054
1055 /* Get the current directory name */
1056 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
1057 lpstrCurrentDir);
1058
1059 /* Create an absolute path name */
1060 if(lpstrSpecifiedByUser[1] != ':')
1061 {
1062 switch(lpstrSpecifiedByUser[0])
1063 {
1064 /* Add drive spec \TEXT => C:\TEXT */
1065 case '\\':
1066 {
1067 INT iCopy = 2;
1068 char lpstrTmp[MAX_PATH] = "";
1069 if(!strlen(lpstrPathSpec))
1070 iCopy = 3;
1071 strncpy(lpstrTmp,lpstrCurrentDir,iCopy);
1072 strcat(lpstrTmp,lpstrPathSpec);
1073 strcpy(lpstrPathSpec,lpstrTmp);
1074 }
1075 break;
1076 /* Go to parent ..\TEXT */
1077 case '.':
1078 {
1079 INT iSize;
1080 char lpstrTmp2[MAX_PATH] = "";
1081 LPSTR lpstrTmp = strrchr(lpstrCurrentDir,'\\');
1082 iSize = lpstrTmp - lpstrCurrentDir;
1083 strncpy(lpstrTmp2,lpstrCurrentDir,iSize + 1);
1084 if(strlen(lpstrSpecifiedByUser) <= 3)
1085 strcpy(lpstrFileSpec,"");
1086 if(strcmp(lpstrPathSpec,".."))
1087 strcat(lpstrTmp2,&lpstrPathSpec[3]);
1088 strcpy(lpstrPathSpec,lpstrTmp2);
1089 }
1090 break;
1091 default:
1092 {
1093 char lpstrTmp[MAX_PATH] = "";
1094 if(strcmp(&lpstrCurrentDir[strlen(lpstrCurrentDir)-1],"\\"))
1095 strcat(lpstrCurrentDir,"\\");
1096 strcpy(lpstrTmp,lpstrCurrentDir);
1097 strcat(lpstrTmp,lpstrPathSpec);
1098 strcpy(lpstrPathSpec,lpstrTmp);
1099 }
1100
1101 } /* end switch */
1102 }
1103
1104 if(strlen(lpstrPathSpec))
1105 {
1106 /* Browse to the right directory */
1107 COMDLG32_SHGetDesktopFolder(&psfDesktop);
1108 if((browsePidl = GetPidlFromName(psfDesktop,lpstrPathSpec)))
1109 {
1110 /* Browse to directory */
1111 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1112 browsePidl,
1113 SBSP_ABSOLUTE);
1114 COMDLG32_SHFree(browsePidl);
1115 }
1116 else
1117 {
1118 /* Path does not exist */
1119 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1120 {
1121 MessageBoxA(hwnd,
1122 "Path does not exist",
1123 fodInfos->ofnInfos.lpstrTitle,
1124 MB_OK | MB_ICONEXCLAMATION);
1125 return FALSE;
1126 }
1127 }
1128
1129 strcat(lpstrPathAndFile,lpstrPathSpec);
1130 IShellFolder_Release(psfDesktop);
1131 }
1132 else
1133 {
1134 strcat(lpstrPathAndFile,lpstrCurrentDir);
1135 }
1136
1137 /* Create the path and file string */
1138 COMDLG32_PathAddBackslashA(lpstrPathAndFile);
1139 strcat(lpstrPathAndFile,lpstrFileSpec);
1140
1141 /* Update the edit field */
1142 SetDlgItemTextA(hwnd,IDC_FILENAME,lpstrFileSpec);
1143 SendDlgItemMessageA(hwnd,IDC_FILENAME,EM_SETSEL,0,-1);
1144
1145 /* Don't go further if we dont have a file spec */
1146 if(!strlen(lpstrFileSpec) || !strcmp(lpstrFileSpec,lpstrPathSpec))
1147 return FALSE;
1148
1149 /* Time to check lpstrFileSpec */
1150 /* search => contains * or ? */
1151 /* browse => contains a directory name */
1152 /* file => contains a file name */
1153
1154 /* Check if this is a search */
1155 if(strchr(lpstrFileSpec,'*') || strchr(lpstrFileSpec,'?'))
1156 {
1157 int iPos;
1158
1159 /* Set the current filter with the current selection */
1160 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1161 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1162
1163 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFileSpec)+1)*2);
1164 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,
1165 (LPSTR)strlwr((LPSTR)lpstrFileSpec));
1166
1167 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1168
1169 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB,
1170 lpstrFileSpec)))
1171 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1172
1173 return FALSE;
1174 }
1175
1176 /* browse if the user specified a directory */
1177 if((browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1178 lpstrFileSpec)))
1179 {
1180 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
1181 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder,
1182 1,
1183 &browsePidl,
1184 &ulAttr);
1185
1186 /* Browse to directory */
1187 if(ulAttr)
1188 {
1189 if(FAILED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1190 browsePidl,
1191 SBSP_RELATIVE)))
1192 {
1193 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1194 {
1195 MessageBoxA(hwnd,
1196 "Path does not exist",
1197 fodInfos->ofnInfos.lpstrTitle,
1198 MB_OK | MB_ICONEXCLAMATION);
1199 COMDLG32_SHFree(browsePidl);
1200 return FALSE;
1201 }
1202 }
1203 COMDLG32_SHFree(browsePidl);
1204 return FALSE;
1205 }
1206 COMDLG32_SHFree(browsePidl);
1207 }
1208 else
1209 {
1210 /* File does not exist in current directory */
1211
1212 /* The selected file does not exist */
1213 /* Tell the user the selected does not exist */
1214 if(fodInfos->ofnInfos.Flags & OFN_FILEMUSTEXIST)
1215 {
1216 char lpstrNotFound[100];
1217 char lpstrMsg[100];
1218 char tmp[400];
1219
1220 LoadStringA(COMDLG32_hInstance,
1221 IDS_FILENOTFOUND,
1222 lpstrNotFound,
1223 100);
1224 LoadStringA(COMDLG32_hInstance,
1225 IDS_VERIFYFILE,
1226 lpstrMsg,
1227 100);
1228
1229 strcpy(tmp,fodInfos->ofnInfos.lpstrFile);
1230 strcat(tmp,"\n");
1231 strcat(tmp,lpstrNotFound);
1232 strcat(tmp,"\n");
1233 strcat(tmp,lpstrMsg);
1234
1235 MessageBoxA(hwnd,
1236 tmp,
1237 fodInfos->ofnInfos.lpstrTitle,
1238 MB_OK | MB_ICONEXCLAMATION);
1239 return FALSE;
1240 }
1241 /* Ask the user if he wants to create the file*/
1242 if(fodInfos->ofnInfos.Flags & OFN_CREATEPROMPT)
1243 {
1244 char tmp[100];
1245
1246 LoadStringA(COMDLG32_hInstance,IDS_CREATEFILE,tmp,100);
1247
1248 if(IDYES == MessageBoxA(hwnd,tmp,fodInfos->ofnInfos.lpstrTitle,
1249 MB_YESNO | MB_ICONQUESTION))
1250 {
1251 /* Create the file, clean and exit */
1252 FILEDLG95_Clean(hwnd);
1253 return EndDialog(hwnd,TRUE);
1254 }
1255 return FALSE;
1256 }
1257 }
1258
1259 /* Open the selected file */
1260
1261 /* Check file extension */
1262 if(!strrchr(lpstrPathAndFile,'.'))
1263 {
1264 /* if the file has no extension, append the selected
1265 extension of the filetype combo box */
1266 int iExt;
1267 LPSTR lpstrExt;
1268 iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1269 lpstrTemp = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iExt);
1270
1271 if((lpstrExt = strchr(lpstrTemp,';')))
1272 {
1273 int i = lpstrExt - lpstrTemp;
1274 lpstrExt = MemAlloc(i);
1275 strncpy(lpstrExt,&lpstrTemp[1],i-1);
1276 }
1277 else
1278 {
1279 lpstrExt = MemAlloc(strlen(lpstrTemp));
1280 strcpy(lpstrExt,&lpstrTemp[1]);
1281 }
1282
1283 if(!strcmp(&lpstrExt[1],"*") && fodInfos->ofnInfos.lpstrDefExt)
1284 {
1285 lpstrExt = MemAlloc(strlen(fodInfos->ofnInfos.lpstrDefExt)+2);
1286 strcat(lpstrExt,".");
1287 strcat(lpstrExt,(LPSTR) fodInfos->ofnInfos.lpstrDefExt);
1288 }
1289 strcat(lpstrPathAndFile,lpstrExt);
1290 }
1291 /* Check that size size of the file does not exceed buffer size */
1292 if(strlen(lpstrPathAndFile) > fodInfos->ofnInfos.nMaxFile)
1293 {
1294 /* set error FNERR_BUFFERTOSMALL */
1295 FILEDLG95_Clean(hwnd);
1296 return EndDialog(hwnd,FALSE);
1297 }
1298 strcpy(fodInfos->ofnInfos.lpstrFile,lpstrPathAndFile);
1299
1300 /* Set the lpstrFileTitle of the OPENFILENAME structure */
1301 if(fodInfos->ofnInfos.lpstrFileTitle)
1302 strncpy(fodInfos->ofnInfos.lpstrFileTitle,
1303 lpstrFileSpec,
1304 fodInfos->ofnInfos.nMaxFileTitle);
1305
1306 /* Check if the file is to be opened as read only */
1307 if(BST_CHECKED == SendDlgItemMessageA(hwnd,
1308 IDC_OPENREADONLY,
1309 BM_GETSTATE,0,0))
1310 SetFileAttributesA(fodInfos->ofnInfos.lpstrFile,
1311 FILE_ATTRIBUTE_READONLY);
1312
1313 /* nFileExtension and nFileOffset of OPENFILENAME structure */
1314 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'\\');
1315 fodInfos->ofnInfos.nFileOffset = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1316 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'.');
1317 fodInfos->ofnInfos.nFileExtension = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1318
1319
1320 /* clean and exit */
1321 FILEDLG95_Clean(hwnd);
1322 return EndDialog(hwnd,TRUE);
1323 }
1324
1325 return FALSE;
1326}
1327
1328/***********************************************************************
1329 * FILEDLG95_SHELL_Init
1330 *
1331 * Initialisation of the shell objects
1332 */
1333static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1334{
1335 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1336
1337 TRACE("\n");
1338
1339 /*
1340 * Initialisation of the FileOpenDialogInfos structure
1341 */
1342
1343 /* Shell */
1344
1345 fodInfos->Shell.FOIShellView = NULL;
1346 if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos->Shell.FOIShellFolder)))
1347 return E_FAIL;
1348
1349 /*ShellInfos */
1350 fodInfos->ShellInfos.hwndOwner = hwnd;
1351
1352 fodInfos->ShellInfos.folderSettings.fFlags = FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1353 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1354
1355 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1356 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1357 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1358
1359 /* Construct the IShellBrowser interface */
1360 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1361
1362 return NOERROR;
1363}
1364
1365/***********************************************************************
1366 * FILEDLG95_SHELL_ExecuteCommand
1367 *
1368 * Change the folder option and refresh the view
1369 * If the function succeeds, the return value is nonzero.
1370 */
1371static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1372{
1373 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1374
1375 IContextMenu * pcm;
1376 CMINVOKECOMMANDINFO ci;
1377 TRACE("\n");
1378
1379 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1380 SVGIO_BACKGROUND,
1381 &IID_IContextMenu,
1382 (LPVOID*)&pcm)))
1383 {
1384 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1385 ci.lpVerb = lpVerb;
1386 ci.hwnd = hwnd;
1387
1388 IContextMenu_InvokeCommand(pcm, &ci);
1389 IContextMenu_Release(pcm);
1390 }
1391
1392 return FALSE;
1393}
1394
1395/***********************************************************************
1396 * FILEDLG95_SHELL_UpFolder
1397 *
1398 * Browse to the specified object
1399 * If the function succeeds, the return value is nonzero.
1400 */
1401static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1402{
1403 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1404
1405 TRACE("\n");
1406
1407 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1408 NULL,
1409 SBSP_PARENT)))
1410 {
1411 return TRUE;
1412 }
1413 return FALSE;
1414}
1415
1416/***********************************************************************
1417 * FILEDLG95_SHELL_NewFolder
1418 *
1419 * Creates a new directory with New folder as name
1420 * If the function succeeds, the return value is nonzero.
1421 * FIXME: let the contextmenu (CMDSTR_NEWFOLDER) do this thing
1422 */
1423static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd)
1424{
1425 char lpstrDirName[MAX_PATH] = "New folder";
1426 BOOL bRes;
1427 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1428
1429 TRACE("\n");
1430
1431 if((bRes = CreateDirectoryA(lpstrDirName,NULL)))
1432 {
1433 LPITEMIDLIST pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,lpstrDirName);
1434 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1435 IShellView_SelectItem(fodInfos->Shell.FOIShellView,
1436 pidl,
1437 (SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
1438 |SVSI_FOCUSED|SVSI_SELECT));
1439 }
1440
1441
1442
1443 return bRes;
1444}
1445
1446/***********************************************************************
1447 * FILEDLG95_SHELL_Clean
1448 *
1449 * Cleans the memory used by shell objects
1450 */
1451static void FILEDLG95_SHELL_Clean(HWND hwnd)
1452{
1453 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1454
1455 TRACE("\n");
1456
1457 /* clean Shell interfaces */
1458 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1459 IShellView_Release(fodInfos->Shell.FOIShellView);
1460 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1461 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1462}
1463
1464/***********************************************************************
1465 * FILEDLG95_FILETYPE_Init
1466 *
1467 * Initialisation of the file type combo box
1468 */
1469static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1470{
1471 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1472
1473 TRACE("\n");
1474
1475 if(fodInfos->ofnInfos.lpstrFilter)
1476 {
1477 int iStrIndex = 0;
1478 int iPos = 0;
1479 LPSTR lpstrFilter;
1480 LPSTR lpstrTmp;
1481
1482 for(;;)
1483 {
1484 /* filter is a list... title\0ext\0......\0\0 */
1485 /* Set the combo item text to the title and the item data
1486 to the ext */
1487 char *lpstrExt = NULL;
1488 LPSTR lpstrExtTmp = NULL;
1489 /* Get the title */
1490 lpstrTmp = (LPSTR)(&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1491 if(!strlen(lpstrTmp))
1492 break;
1493 iStrIndex += strlen(lpstrTmp) +1;
1494 /* Get the extension */
1495 lpstrExtTmp = (LPSTR)(&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1496 if(!lpstrExtTmp)
1497 break;
1498
1499 lpstrExt = (LPSTR) MemAlloc(strlen(lpstrExtTmp)+1);
1500 if(!lpstrExt)
1501 break;
1502
1503 strcpy(lpstrExt,lpstrExtTmp);
1504
1505 iStrIndex += strlen(lpstrExt) +1;
1506
1507 /* Add the item at the end of the combo */
1508 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB,lpstrTmp);
1509 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos++,lpstrExt);
1510 }
1511 /* Set the current filter to the one specified
1512 in the initialisation structure */
1513 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,
1514 fodInfos->ofnInfos.nFilterIndex);
1515
1516 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1517 fodInfos->ofnInfos.nFilterIndex);
1518 if(lpstrFilter)
1519 {
1520 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFilter)+1)*2);
1521 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,strlwr(lpstrFilter));
1522 }
1523 }
1524 return NOERROR;
1525}
1526
1527/***********************************************************************
1528 * FILEDLG95_FILETYPE_OnCommand
1529 *
1530 * WM_COMMAND of the file type combo box
1531 * If the function succeeds, the return value is nonzero.
1532 */
1533static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1534{
1535 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1536
1537 switch(wNotifyCode)
1538 {
1539 case CBN_CLOSEUP:
1540 {
1541 LPSTR lpstrFilter;
1542
1543 /* Get the current item of the filetype combo box */
1544 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1545
1546 /* Set the current filter with the current selection */
1547 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1548 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1549
1550 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1551 iItem);
1552 if((INT)lpstrFilter != CB_ERR)
1553 {
1554 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFilter)+1)*2);
1555 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,(LPSTR)strlwr((LPSTR)lpstrFilter));
1556 }
1557
1558 /* Refresh the actual view to display the included items*/
1559 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1560
1561 }
1562 }
1563 return FALSE;
1564}
1565/***********************************************************************
1566 * FILEDLG95_FILETYPE_SearchExt
1567 *
1568 * Search for pidl in the lookin combo box
1569 * returns the index of the found item
1570 */
1571static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt)
1572{
1573 int i = 0;
1574 int iCount = CBGetCount(hwnd);
1575
1576 TRACE("\n");
1577
1578 for(;i<iCount;i++)
1579 {
1580 LPSTR ext = (LPSTR) CBGetItemDataPtr(hwnd,i);
1581
1582 if(!stricmp(lpstrExt,ext))
1583 return i;
1584
1585 }
1586
1587 return -1;
1588}
1589
1590/***********************************************************************
1591 * FILEDLG95_FILETYPE_Clean
1592 *
1593 * Clean the memory used by the filetype combo box
1594 */
1595static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1596{
1597 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1598 int iPos;
1599 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1600
1601 TRACE("\n");
1602
1603 /* Delete each string of the combo and their associated data */
1604 for(iPos = iCount-1;iPos>=0;iPos--)
1605 {
1606 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos)));
1607 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1608 }
1609 /* Current filter */
1610 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1611 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1612
1613}
1614
1615/***********************************************************************
1616 * FILEDLG95_LOOKIN_Init
1617 *
1618 * Initialisation of the look in combo box
1619 */
1620static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1621{
1622 IShellFolder *psfRoot, *psfDrives;
1623 IEnumIDList *lpeRoot, *lpeDrives;
1624 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1625
1626 LookInInfos *liInfos = (LookInInfos*)MemAlloc(sizeof(LookInInfos));
1627
1628 TRACE("\n");
1629
1630 liInfos->iMaxIndentation = 0;
1631
1632 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1633 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1634
1635 /* Initialise data of Desktop folder */
1636 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1637 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1638 COMDLG32_SHFree(pidlTmp);
1639
1640 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1641
1642 COMDLG32_SHGetDesktopFolder(&psfRoot);
1643
1644 if (psfRoot)
1645 {
1646 /* enumerate the contents of the desktop */
1647 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1648 {
1649 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1650 {
1651 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1652
1653 /* special handling for CSIDL_DRIVES */
1654 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1655 {
1656 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1657 {
1658 /* enumerate the drives */
1659 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1660 {
1661 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1662 {
1663 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1664 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1665 COMDLG32_SHFree(pidlAbsTmp);
1666 COMDLG32_SHFree(pidlTmp1);
1667 }
1668 IEnumIDList_Release(lpeDrives);
1669 }
1670 IShellFolder_Release(psfDrives);
1671 }
1672 }
1673 COMDLG32_SHFree(pidlTmp);
1674 }
1675 IEnumIDList_Release(lpeRoot);
1676 }
1677 }
1678
1679 IShellFolder_Release(psfRoot);
1680 COMDLG32_SHFree(pidlDrives);
1681
1682 return NOERROR;
1683}
1684
1685/***********************************************************************
1686 * FILEDLG95_LOOKIN_DrawItem
1687 *
1688 * WM_DRAWITEM message handler
1689 */
1690static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1691{
1692 COLORREF crWin = GetSysColor(COLOR_WINDOW);
1693 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1694 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1695 RECT rectText;
1696 RECT rectIcon;
1697 SHFILEINFOA sfi;
1698 HIMAGELIST ilItemImage;
1699 int iIndentation;
1700 LPSFOLDER tmpFolder;
1701
1702
1703 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1704
1705 TRACE("\n");
1706
1707 if(pDIStruct->itemID == -1)
1708 return 0;
1709
1710 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1711 pDIStruct->itemID)))
1712 return 0;
1713
1714
1715 if(pDIStruct->itemID == liInfos->uSelectedItem)
1716 {
1717 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1718 0,
1719 &sfi,
1720 sizeof (SHFILEINFOA),
1721 SHGFI_PIDL | SHGFI_SMALLICON |
1722 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
1723 SHGFI_DISPLAYNAME );
1724 }
1725 else
1726 {
1727 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1728 0,
1729 &sfi,
1730 sizeof (SHFILEINFOA),
1731 SHGFI_PIDL | SHGFI_SMALLICON |
1732 SHGFI_SYSICONINDEX |
1733 SHGFI_DISPLAYNAME);
1734 }
1735
1736 /* Is this item selected ?*/
1737 if(pDIStruct->itemState & ODS_SELECTED)
1738 {
1739 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1740 SetBkColor(pDIStruct->hDC,crHighLight);
1741 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1742 }
1743 else
1744 {
1745 SetTextColor(pDIStruct->hDC,crText);
1746 SetBkColor(pDIStruct->hDC,crWin);
1747 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1748 }
1749
1750 /* Do not indent item if drawing in the edit of the combo*/
1751 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
1752 {
1753 iIndentation = 0;
1754 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1755 0,
1756 &sfi,
1757 sizeof (SHFILEINFOA),
1758 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
1759 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
1760
1761 }
1762 else
1763 {
1764 iIndentation = tmpFolder->m_iIndent;
1765 }
1766 /* Draw text and icon */
1767
1768 /* Initialise the icon display area */
1769 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
1770 rectIcon.top = pDIStruct->rcItem.top;
1771 rectIcon.right = rectIcon.left + ICONWIDTH;
1772 rectIcon.bottom = pDIStruct->rcItem.bottom;
1773
1774 /* Initialise the text display area */
1775 rectText.left = rectIcon.right;
1776 rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
1777 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
1778 rectText.bottom = pDIStruct->rcItem.bottom;
1779
1780
1781 /* Draw the icon from the image list */
1782 COMDLG32_ImageList_Draw(ilItemImage,
1783 sfi.iIcon,
1784 pDIStruct->hDC,
1785 rectIcon.left,
1786 rectIcon.top,
1787 ILD_TRANSPARENT );
1788
1789 /* Draw the associated text */
1790 if(sfi.szDisplayName)
1791 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
1792
1793
1794 return NOERROR;
1795}
1796
1797/***********************************************************************
1798 * FILEDLG95_LOOKIN_OnCommand
1799 *
1800 * LookIn combo box WM_COMMAND message handler
1801 * If the function succeeds, the return value is nonzero.
1802 */
1803static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
1804{
1805 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1806
1807 TRACE("\n");
1808
1809 switch(wNotifyCode)
1810 {
1811 case CBN_CLOSEUP:
1812 {
1813 LPSFOLDER tmpFolder;
1814 int iItem;
1815
1816 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
1817
1818 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
1819 iItem)))
1820 return FALSE;
1821
1822
1823 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1824 tmpFolder->pidlItem,
1825 SBSP_ABSOLUTE)))
1826 {
1827 return TRUE;
1828 }
1829 break;
1830 }
1831
1832 }
1833 return FALSE;
1834}
1835
1836/***********************************************************************
1837 * FILEDLG95_LOOKIN_AddItem
1838 *
1839 * Adds an absolute pidl item to the lookin combo box
1840 * returns the index of the inserted item
1841 */
1842static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
1843{
1844 LPITEMIDLIST pidlNext;
1845 SHFILEINFOA sfi;
1846 SFOLDER *tmpFolder = (SFOLDER*)MemAlloc(sizeof(SFOLDER));
1847 LookInInfos *liInfos;
1848
1849 TRACE("\n");
1850
1851 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
1852 return -1;
1853
1854 tmpFolder->m_iIndent = 0;
1855
1856 if(!pidl)
1857 return -1;
1858
1859 /* Calculate the indentation of the item in the lookin*/
1860 pidlNext = pidl;
1861 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
1862 {
1863 tmpFolder->m_iIndent++;
1864 }
1865
1866 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl);
1867
1868 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
1869 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
1870
1871 COMDLG32_SHGetFileInfoA((LPSTR)pidl,
1872 0,
1873 &sfi,
1874 sizeof(sfi),
1875 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
1876 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
1877
1878
1879 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
1880 {
1881 int iItemID;
1882 /* Add the item at the end of the list */
1883 if(iInsertId < 0)
1884 {
1885 iItemID = CBAddString(hwnd,sfi.szDisplayName);
1886 }
1887 /* Insert the item at the iInsertId position*/
1888 else
1889 {
1890 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
1891 }
1892
1893 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
1894 return iItemID;
1895 }
1896
1897 return -1;
1898
1899}
1900
1901/***********************************************************************
1902 * FILEDLG95_LOOKIN_InsertItemAfterParent
1903 *
1904 * Insert an item below its parent
1905 */
1906static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
1907{
1908
1909 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
1910 int iParentPos;
1911
1912 TRACE("\n");
1913
1914 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
1915
1916 if(iParentPos < 0)
1917 {
1918 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
1919 }
1920
1921 /* Free pidlParent memory */
1922 COMDLG32_SHFree((LPVOID)pidlParent);
1923
1924 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
1925}
1926
1927/***********************************************************************
1928 * FILEDLG95_LOOKIN_SelectItem
1929 *
1930 * Adds an absolute pidl item to the lookin combo box
1931 * returns the index of the inserted item
1932 */
1933int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
1934{
1935 int iItemPos;
1936 LookInInfos *liInfos;
1937
1938 TRACE("\n");
1939
1940 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
1941
1942 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1943
1944 if(iItemPos < 0)
1945 {
1946 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
1947 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
1948 }
1949
1950 else
1951 {
1952 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1953 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
1954 {
1955 int iRemovedItem;
1956
1957 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
1958 break;
1959 if(iRemovedItem < iItemPos)
1960 iItemPos--;
1961 }
1962 }
1963
1964 CBSetCurSel(hwnd,iItemPos);
1965 liInfos->uSelectedItem = iItemPos;
1966
1967 return 0;
1968
1969}
1970
1971/***********************************************************************
1972 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
1973 *
1974 * Remove the item with an expansion level over iExpansionLevel
1975 */
1976static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
1977{
1978 int iItemPos;
1979
1980 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1981
1982 TRACE("\n");
1983
1984 if(liInfos->iMaxIndentation <= 2)
1985 return -1;
1986
1987 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
1988 {
1989 SFOLDER *tmpFolder;
1990 tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1991 CBDeleteString(hwnd,iItemPos);
1992 liInfos->iMaxIndentation--;
1993
1994 return iItemPos;
1995 }
1996
1997 return -1;
1998}
1999
2000/***********************************************************************
2001 * FILEDLG95_LOOKIN_SearchItem
2002 *
2003 * Search for pidl in the lookin combo box
2004 * returns the index of the found item
2005 */
2006static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2007{
2008 int i = 0;
2009 int iCount = CBGetCount(hwnd);
2010
2011 TRACE("\n");
2012
2013 for(;i<iCount;i++)
2014 {
2015 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2016
2017 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2018 return i;
2019 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2020 return i;
2021
2022 }
2023
2024 return -1;
2025}
2026
2027/***********************************************************************
2028 * FILEDLG95_LOOKIN_Clean
2029 *
2030 * Clean the memory used by the lookin combo box
2031 */
2032static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2033{
2034 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2035 int iPos;
2036 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2037
2038 TRACE("\n");
2039
2040 /* Delete each string of the combo and their associated data */
2041 for(iPos = iCount-1;iPos>=0;iPos--)
2042 {
2043 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos)));
2044 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2045 }
2046 /* LookInInfos structure */
2047 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2048
2049}
2050/*
2051 * TOOLS
2052 */
2053
2054/***********************************************************************
2055 * GetName
2056 *
2057 * Get the pidl's display name (relative to folder) and
2058 * put it in lpstrFileName.
2059 *
2060 * Return NOERROR on success,
2061 * E_FAIL otherwise
2062 */
2063
2064HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2065{
2066 STRRET str;
2067 HRESULT hRes;
2068
2069 TRACE("%p %p\n", lpsf, pidl);
2070
2071 if(!lpsf)
2072 {
2073 HRESULT hRes;
2074 COMDLG32_SHGetDesktopFolder(&lpsf);
2075 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2076 IShellFolder_Release(lpsf);
2077 return hRes;
2078 }
2079
2080 /* Get the display name of the pidl relative to the folder */
2081 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf,
2082 pidl,
2083 dwFlags,
2084 &str)))
2085 {
2086 return StrRetToBufA(&str, pidl,lpstrFileName, MAX_PATH);
2087 }
2088 return E_FAIL;
2089}
2090
2091/***********************************************************************
2092 * GetShellFolderFromPidl
2093 *
2094 * pidlRel is the item pidl relative
2095 * Return the IShellFolder of the absolute pidl
2096 */
2097IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2098{
2099 IShellFolder *psf = NULL,*psfParent;
2100
2101 TRACE("%p\n", pidlAbs);
2102
2103 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
2104 {
2105 psf = psfParent;
2106 if(pidlAbs && pidlAbs->mkid.cb)
2107 {
2108 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2109 {
2110 IShellFolder_Release(psfParent);
2111 return psf;
2112 }
2113 }
2114 /* return the desktop */
2115 return psfParent;
2116 }
2117 return NULL;
2118}
2119
2120/***********************************************************************
2121 * GetParentPidl
2122 *
2123 * Return the LPITEMIDLIST to the parent of the pidl in the list
2124 */
2125LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2126{
2127 LPITEMIDLIST pidlParent;
2128
2129 TRACE("%p\n", pidl);
2130
2131 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2132 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2133
2134 return pidlParent;
2135}
2136
2137/***********************************************************************
2138 * GetPidlFromName
2139 *
2140 * returns the pidl of the file name relative to folder
2141 * NULL if an error occured
2142 */
2143LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName)
2144{
2145 LPITEMIDLIST pidl;
2146 ULONG ulEaten;
2147 wchar_t lpwstrDirName[MAX_PATH];
2148
2149
2150 TRACE("sf=%p file=%s\n", psf, lpcstrFileName);
2151
2152 if(!lpcstrFileName)
2153 return NULL;
2154
2155 MultiByteToWideChar(CP_ACP,
2156 MB_PRECOMPOSED,
2157 lpcstrFileName,
2158 -1,
2159 (LPWSTR)lpwstrDirName,
2160 MAX_PATH);
2161
2162 IShellFolder_ParseDisplayName(psf, 0,
2163 NULL,
2164 (LPWSTR)lpwstrDirName,
2165 &ulEaten,
2166 &pidl,
2167 NULL);
2168
2169 return pidl;
2170}
2171
2172/***********************************************************************
2173 * GetFileExtension
2174 *
2175 */
2176BOOL GetFileExtension(IShellFolder *psf,LPITEMIDLIST pidl,LPSTR lpstrFileExtension)
2177{
2178 char FileName[MAX_PATH];
2179 int result;
2180 char *pdest;
2181 int ch = '.';
2182
2183 if(SUCCEEDED(GetName(psf,pidl,SHGDN_NORMAL,FileName)))
2184 {
2185 if(!(pdest = strrchr( FileName, ch )))
2186 return FALSE;
2187
2188 result = pdest - FileName + 1;
2189 strcpy(lpstrFileExtension,&FileName[result]);
2190 return TRUE;
2191 }
2192 return FALSE;
2193}
2194
2195/*
2196 * Memory allocation methods */
2197char *MemAlloc(UINT size)
2198{
2199 return (char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2200}
2201
2202void MemFree(void *mem)
2203{
2204 if(mem)
2205 {
2206 HeapFree(GetProcessHeap(),0,mem);
2207 }
2208}
Note: See TracBrowser for help on using the repository browser.