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

Last change on this file since 1567 was 1556, checked in by sandervl, 26 years ago

Wine 991031 update

File size: 65.1 KB
Line 
1/* $Id: filedlg95.cpp,v 1.2 1999-11-02 20:37:42 sandervl 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 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
913 return 0;
914}
915
916/***********************************************************************
917 * FILEDLG95_OnWMGetIShellBrowser
918 *
919 * WM_GETISHELLBROWSER message handler
920 */
921static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
922{
923
924 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
925
926 TRACE("\n");
927
928 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
929
930 return TRUE;
931}
932
933
934/***********************************************************************
935 * FILEDLG95_InitUI
936 *
937 */
938static LRESULT FILEDLG95_InitUI(HWND hwnd)
939{
940 HIMAGELIST himlToolbar;
941 HICON hicon;
942 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
943
944 TRACE("%p\n", fodInfos);
945
946 /* Get the hwnd of the controls */
947 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
948 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
949 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
950
951 ShowWindow(GetDlgItem(hwnd,IDC_SHELLSTATIC),SW_HIDE);
952 /* Load the icons bitmaps */
953
954 if((himlToolbar = COMDLG32_ImageList_LoadImageA(COMDLG32_hInstance,
955 MAKEINTRESOURCEA(IDB_TOOLBAR),
956 0,
957 1,
958 CLR_DEFAULT,
959 IMAGE_BITMAP,
960 0)))
961 {
962 /* Up folder icon */
963 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,0,ILD_NORMAL)))
964 SendDlgItemMessageA(hwnd,IDC_UPFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
965 /* New folder icon */
966 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,1,ILD_NORMAL)))
967 SendDlgItemMessageA(hwnd,IDC_NEWFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
968 /* List view icon */
969 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,2,ILD_NORMAL)))
970 SendDlgItemMessageA(hwnd,IDC_LIST,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
971 /* Detail view icon */
972 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,3,ILD_NORMAL)))
973 SendDlgItemMessageA(hwnd,IDC_DETAILS,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
974 /* Cleanup */
975 COMDLG32_ImageList_Destroy(himlToolbar);
976 }
977
978
979
980 /* Set the window text with the text specified in the OPENFILENAME structure */
981 if(fodInfos->ofnInfos.lpstrTitle)
982 SetWindowTextA(hwnd,fodInfos->ofnInfos.lpstrTitle);
983
984 /* Initialise the file name edit control */
985 if(strlen(fodInfos->ofnInfos.lpstrFile))
986 {
987 SetDlgItemTextA(hwnd,IDC_FILENAME,fodInfos->ofnInfos.lpstrFile);
988 }
989 /* Must the open as read only check box be checked ?*/
990 if(fodInfos->ofnInfos.Flags & OFN_READONLY)
991 {
992 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
993 }
994 /* Must the open as read only check box be hid ?*/
995 if(fodInfos->ofnInfos.Flags & OFN_HIDEREADONLY)
996 {
997 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
998 }
999
1000 /* List View is selected by default */
1001 SendDlgItemMessageA(hwnd, IDC_LIST, BM_SETCHECK,(WPARAM) BST_CHECKED,0);
1002
1003 return 0;
1004}
1005
1006/***********************************************************************
1007 * FILEDLG95_OnOpen
1008 *
1009 * Ok button WM_COMMAND message handler
1010 *
1011 * If the function succeeds, the return value is nonzero.
1012 */
1013BOOL FILEDLG95_OnOpen(HWND hwnd)
1014{
1015 char lpstrSpecifiedByUser[MAX_PATH] = "";
1016 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1017 LPITEMIDLIST pidlSelection;
1018
1019 TRACE("\n");
1020
1021 /* Check if there is a selected item in the listview */
1022 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_USEVIEW)
1023 {
1024 pidlSelection = GetSelectedPidl(fodInfos->Shell.FOIShellView);
1025 GetName(fodInfos->Shell.FOIShellFolder,pidlSelection,SHGDN_NORMAL,lpstrSpecifiedByUser);
1026 COMDLG32_SHFree((LPVOID)pidlSelection);
1027 }
1028 else
1029 /* Get the text from the filename edit */
1030 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrSpecifiedByUser,MAX_PATH);
1031
1032 if(strlen(lpstrSpecifiedByUser))
1033 {
1034 LPSHELLFOLDER psfDesktop;
1035 LPITEMIDLIST browsePidl;
1036 LPSTR lpstrFileSpec;
1037 LPSTR lpstrTemp;
1038 char lpstrPathSpec[MAX_PATH] = "";
1039 char lpstrCurrentDir[MAX_PATH] = "";
1040 char lpstrPathAndFile[MAX_PATH] = "";
1041
1042 /* Separate the file spec from the path spec
1043 e.g.:
1044 lpstrSpecifiedByUser lpstrPathSpec lpstrFileSpec
1045 C:\TEXT1\TEXT2 C:\TEXT1 TEXT2
1046 */
1047 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser);
1048 strcpy(lpstrPathSpec,lpstrSpecifiedByUser);
1049 COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
1050
1051 /* Get the current directory name */
1052 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
1053 lpstrCurrentDir);
1054
1055 /* Create an absolute path name */
1056 if(lpstrSpecifiedByUser[1] != ':')
1057 {
1058 switch(lpstrSpecifiedByUser[0])
1059 {
1060 /* Add drive spec \TEXT => C:\TEXT */
1061 case '\\':
1062 {
1063 INT iCopy = 2;
1064 char lpstrTmp[MAX_PATH] = "";
1065 if(!strlen(lpstrPathSpec))
1066 iCopy = 3;
1067 strncpy(lpstrTmp,lpstrCurrentDir,iCopy);
1068 strcat(lpstrTmp,lpstrPathSpec);
1069 strcpy(lpstrPathSpec,lpstrTmp);
1070 }
1071 break;
1072 /* Go to parent ..\TEXT */
1073 case '.':
1074 {
1075 INT iSize;
1076 char lpstrTmp2[MAX_PATH] = "";
1077 LPSTR lpstrTmp = strrchr(lpstrCurrentDir,'\\');
1078 iSize = lpstrTmp - lpstrCurrentDir;
1079 strncpy(lpstrTmp2,lpstrCurrentDir,iSize + 1);
1080 if(strlen(lpstrSpecifiedByUser) <= 3)
1081 strcpy(lpstrFileSpec,"");
1082 if(strcmp(lpstrPathSpec,".."))
1083 strcat(lpstrTmp2,&lpstrPathSpec[3]);
1084 strcpy(lpstrPathSpec,lpstrTmp2);
1085 }
1086 break;
1087 default:
1088 {
1089 char lpstrTmp[MAX_PATH] = "";
1090 if(strcmp(&lpstrCurrentDir[strlen(lpstrCurrentDir)-1],"\\"))
1091 strcat(lpstrCurrentDir,"\\");
1092 strcpy(lpstrTmp,lpstrCurrentDir);
1093 strcat(lpstrTmp,lpstrPathSpec);
1094 strcpy(lpstrPathSpec,lpstrTmp);
1095 }
1096
1097 } /* end switch */
1098 }
1099
1100 if(strlen(lpstrPathSpec))
1101 {
1102 /* Browse to the right directory */
1103 COMDLG32_SHGetDesktopFolder(&psfDesktop);
1104 if((browsePidl = GetPidlFromName(psfDesktop,lpstrPathSpec)))
1105 {
1106 /* Browse to directory */
1107 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1108 browsePidl,
1109 SBSP_ABSOLUTE);
1110 COMDLG32_SHFree(browsePidl);
1111 }
1112 else
1113 {
1114 /* Path does not exist */
1115 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1116 {
1117 MessageBoxA(hwnd,
1118 "Path does not exist",
1119 fodInfos->ofnInfos.lpstrTitle,
1120 MB_OK | MB_ICONEXCLAMATION);
1121 return FALSE;
1122 }
1123 }
1124
1125 strcat(lpstrPathAndFile,lpstrPathSpec);
1126 IShellFolder_Release(psfDesktop);
1127 }
1128 else
1129 {
1130 strcat(lpstrPathAndFile,lpstrCurrentDir);
1131 }
1132
1133 /* Create the path and file string */
1134 COMDLG32_PathAddBackslashA(lpstrPathAndFile);
1135 strcat(lpstrPathAndFile,lpstrFileSpec);
1136
1137 /* Update the edit field */
1138 SetDlgItemTextA(hwnd,IDC_FILENAME,lpstrFileSpec);
1139 SendDlgItemMessageA(hwnd,IDC_FILENAME,EM_SETSEL,0,-1);
1140
1141 /* Don't go further if we dont have a file spec */
1142 if(!strlen(lpstrFileSpec) || !strcmp(lpstrFileSpec,lpstrPathSpec))
1143 return FALSE;
1144
1145 /* Time to check lpstrFileSpec */
1146 /* search => contains * or ? */
1147 /* browse => contains a directory name */
1148 /* file => contains a file name */
1149
1150 /* Check if this is a search */
1151 if(strchr(lpstrFileSpec,'*') || strchr(lpstrFileSpec,'?'))
1152 {
1153 int iPos;
1154
1155 /* Set the current filter with the current selection */
1156 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1157 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1158
1159 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFileSpec)+1)*2);
1160 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,
1161 (LPSTR)strlwr((LPSTR)lpstrFileSpec));
1162
1163 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1164
1165 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB,
1166 lpstrFileSpec)))
1167 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1168
1169 return FALSE;
1170 }
1171
1172 /* browse if the user specified a directory */
1173 if((browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1174 lpstrFileSpec)))
1175 {
1176 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
1177 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder,
1178 1,
1179 &browsePidl,
1180 &ulAttr);
1181
1182 /* Browse to directory */
1183 if(ulAttr)
1184 {
1185 if(FAILED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1186 browsePidl,
1187 SBSP_RELATIVE)))
1188 {
1189 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1190 {
1191 MessageBoxA(hwnd,
1192 "Path does not exist",
1193 fodInfos->ofnInfos.lpstrTitle,
1194 MB_OK | MB_ICONEXCLAMATION);
1195 COMDLG32_SHFree(browsePidl);
1196 return FALSE;
1197 }
1198 }
1199 COMDLG32_SHFree(browsePidl);
1200 return FALSE;
1201 }
1202 COMDLG32_SHFree(browsePidl);
1203 }
1204 else
1205 {
1206 /* File does not exist in current directory */
1207
1208 /* The selected file does not exist */
1209 /* Tell the user the selected does not exist */
1210 if(fodInfos->ofnInfos.Flags & OFN_FILEMUSTEXIST)
1211 {
1212 char lpstrNotFound[100];
1213 char lpstrMsg[100];
1214 char tmp[400];
1215
1216 LoadStringA(COMDLG32_hInstance,
1217 IDS_FILENOTFOUND,
1218 lpstrNotFound,
1219 100);
1220 LoadStringA(COMDLG32_hInstance,
1221 IDS_VERIFYFILE,
1222 lpstrMsg,
1223 100);
1224
1225 strcpy(tmp,fodInfos->ofnInfos.lpstrFile);
1226 strcat(tmp,"\n");
1227 strcat(tmp,lpstrNotFound);
1228 strcat(tmp,"\n");
1229 strcat(tmp,lpstrMsg);
1230
1231 MessageBoxA(hwnd,
1232 tmp,
1233 fodInfos->ofnInfos.lpstrTitle,
1234 MB_OK | MB_ICONEXCLAMATION);
1235 return FALSE;
1236 }
1237 /* Ask the user if he wants to create the file*/
1238 if(fodInfos->ofnInfos.Flags & OFN_CREATEPROMPT)
1239 {
1240 char tmp[100];
1241
1242 LoadStringA(COMDLG32_hInstance,IDS_CREATEFILE,tmp,100);
1243
1244 if(IDYES == MessageBoxA(hwnd,tmp,fodInfos->ofnInfos.lpstrTitle,
1245 MB_YESNO | MB_ICONQUESTION))
1246 {
1247 /* Create the file, clean and exit */
1248 FILEDLG95_Clean(hwnd);
1249 return EndDialog(hwnd,TRUE);
1250 }
1251 return FALSE;
1252 }
1253 }
1254
1255 /* Open the selected file */
1256
1257 /* Check file extension */
1258 if(!strrchr(lpstrPathAndFile,'.'))
1259 {
1260 /* if the file has no extension, append the selected
1261 extension of the filetype combo box */
1262 int iExt;
1263 LPSTR lpstrExt;
1264 iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1265 lpstrTemp = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iExt);
1266
1267 if((lpstrExt = strchr(lpstrTemp,';')))
1268 {
1269 int i = lpstrExt - lpstrTemp;
1270 lpstrExt = MemAlloc(i);
1271 strncpy(lpstrExt,&lpstrTemp[1],i-1);
1272 }
1273 else
1274 {
1275 lpstrExt = MemAlloc(strlen(lpstrTemp));
1276 strcpy(lpstrExt,&lpstrTemp[1]);
1277 }
1278
1279 if(!strcmp(&lpstrExt[1],"*") && fodInfos->ofnInfos.lpstrDefExt)
1280 {
1281 lpstrExt = MemAlloc(strlen(fodInfos->ofnInfos.lpstrDefExt)+2);
1282 strcat(lpstrExt,".");
1283 strcat(lpstrExt,(LPSTR) fodInfos->ofnInfos.lpstrDefExt);
1284 }
1285 strcat(lpstrPathAndFile,lpstrExt);
1286 }
1287 /* Check that size size of the file does not exceed buffer size */
1288 if(strlen(lpstrPathAndFile) > fodInfos->ofnInfos.nMaxFile)
1289 {
1290 /* set error FNERR_BUFFERTOSMALL */
1291 FILEDLG95_Clean(hwnd);
1292 return EndDialog(hwnd,FALSE);
1293 }
1294 strcpy(fodInfos->ofnInfos.lpstrFile,lpstrPathAndFile);
1295
1296 /* Set the lpstrFileTitle of the OPENFILENAME structure */
1297 if(fodInfos->ofnInfos.lpstrFileTitle)
1298 strncpy(fodInfos->ofnInfos.lpstrFileTitle,
1299 lpstrFileSpec,
1300 fodInfos->ofnInfos.nMaxFileTitle);
1301
1302 /* Check if the file is to be opened as read only */
1303 if(BST_CHECKED == SendDlgItemMessageA(hwnd,
1304 IDC_OPENREADONLY,
1305 BM_GETSTATE,0,0))
1306 SetFileAttributesA(fodInfos->ofnInfos.lpstrFile,
1307 FILE_ATTRIBUTE_READONLY);
1308
1309 /* nFileExtension and nFileOffset of OPENFILENAME structure */
1310 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'\\');
1311 fodInfos->ofnInfos.nFileOffset = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1312 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'.');
1313 fodInfos->ofnInfos.nFileExtension = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1314
1315
1316 /* clean and exit */
1317 FILEDLG95_Clean(hwnd);
1318 return EndDialog(hwnd,TRUE);
1319 }
1320
1321 return FALSE;
1322}
1323
1324/***********************************************************************
1325 * FILEDLG95_SHELL_Init
1326 *
1327 * Initialisation of the shell objects
1328 */
1329static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1330{
1331 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1332
1333 TRACE("\n");
1334
1335 /*
1336 * Initialisation of the FileOpenDialogInfos structure
1337 */
1338
1339 /* Shell */
1340
1341 fodInfos->Shell.FOIShellView = NULL;
1342 if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos->Shell.FOIShellFolder)))
1343 return E_FAIL;
1344
1345 /*ShellInfos */
1346 fodInfos->ShellInfos.hwndOwner = hwnd;
1347
1348 fodInfos->ShellInfos.folderSettings.fFlags = FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1349 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1350
1351 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1352 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1353 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1354
1355 /* Construct the IShellBrowser interface */
1356 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1357
1358 return NOERROR;
1359}
1360
1361/***********************************************************************
1362 * FILEDLG95_SHELL_ExecuteCommand
1363 *
1364 * Change the folder option and refresh the view
1365 * If the function succeeds, the return value is nonzero.
1366 */
1367static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1368{
1369 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1370
1371 IContextMenu * pcm;
1372 CMINVOKECOMMANDINFO ci;
1373 TRACE("\n");
1374
1375 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1376 SVGIO_BACKGROUND,
1377 &IID_IContextMenu,
1378 (LPVOID*)&pcm)))
1379 {
1380 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1381 ci.lpVerb = lpVerb;
1382 ci.hwnd = hwnd;
1383
1384 IContextMenu_InvokeCommand(pcm, &ci);
1385 IContextMenu_Release(pcm);
1386 }
1387
1388 return FALSE;
1389}
1390
1391/***********************************************************************
1392 * FILEDLG95_SHELL_UpFolder
1393 *
1394 * Browse to the specified object
1395 * If the function succeeds, the return value is nonzero.
1396 */
1397static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1398{
1399 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1400
1401 TRACE("\n");
1402
1403 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1404 NULL,
1405 SBSP_PARENT)))
1406 {
1407 return TRUE;
1408 }
1409 return FALSE;
1410}
1411
1412/***********************************************************************
1413 * FILEDLG95_SHELL_NewFolder
1414 *
1415 * Creates a new directory with New folder as name
1416 * If the function succeeds, the return value is nonzero.
1417 * FIXME: let the contextmenu (CMDSTR_NEWFOLDER) do this thing
1418 */
1419static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd)
1420{
1421 char lpstrDirName[MAX_PATH] = "New folder";
1422 BOOL bRes;
1423 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1424
1425 TRACE("\n");
1426
1427 if((bRes = CreateDirectoryA(lpstrDirName,NULL)))
1428 {
1429 LPITEMIDLIST pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,lpstrDirName);
1430 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1431 IShellView_SelectItem(fodInfos->Shell.FOIShellView,
1432 pidl,
1433 (SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
1434 |SVSI_FOCUSED|SVSI_SELECT));
1435 }
1436
1437
1438
1439 return bRes;
1440}
1441
1442/***********************************************************************
1443 * FILEDLG95_SHELL_Clean
1444 *
1445 * Cleans the memory used by shell objects
1446 */
1447static void FILEDLG95_SHELL_Clean(HWND hwnd)
1448{
1449 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1450
1451 TRACE("\n");
1452
1453 /* clean Shell interfaces */
1454 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1455 IShellView_Release(fodInfos->Shell.FOIShellView);
1456 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1457 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1458}
1459
1460/***********************************************************************
1461 * FILEDLG95_FILETYPE_Init
1462 *
1463 * Initialisation of the file type combo box
1464 */
1465static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1466{
1467 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1468
1469 TRACE("\n");
1470
1471 if(fodInfos->ofnInfos.lpstrFilter)
1472 {
1473 int iStrIndex = 0;
1474 int iPos = 0;
1475 LPSTR lpstrFilter;
1476 LPSTR lpstrTmp;
1477
1478 for(;;)
1479 {
1480 /* filter is a list... title\0ext\0......\0\0 */
1481 /* Set the combo item text to the title and the item data
1482 to the ext */
1483 char *lpstrExt = NULL;
1484 LPSTR lpstrExtTmp = NULL;
1485 /* Get the title */
1486 lpstrTmp = (LPSTR)(&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1487 if(!strlen(lpstrTmp))
1488 break;
1489 iStrIndex += strlen(lpstrTmp) +1;
1490 /* Get the extension */
1491 lpstrExtTmp = (LPSTR)(&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1492 if(!lpstrExtTmp)
1493 break;
1494
1495 lpstrExt = (LPSTR) MemAlloc(strlen(lpstrExtTmp)+1);
1496 if(!lpstrExt)
1497 break;
1498
1499 strcpy(lpstrExt,lpstrExtTmp);
1500
1501 iStrIndex += strlen(lpstrExt) +1;
1502
1503 /* Add the item at the end of the combo */
1504 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB,lpstrTmp);
1505 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos++,lpstrExt);
1506 }
1507 /* Set the current filter to the one specified
1508 in the initialisation structure */
1509 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,
1510 fodInfos->ofnInfos.nFilterIndex);
1511
1512 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1513 fodInfos->ofnInfos.nFilterIndex);
1514 if(lpstrFilter)
1515 {
1516 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFilter)+1)*2);
1517 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,strlwr(lpstrFilter));
1518 }
1519 }
1520 return NOERROR;
1521}
1522
1523/***********************************************************************
1524 * FILEDLG95_FILETYPE_OnCommand
1525 *
1526 * WM_COMMAND of the file type combo box
1527 * If the function succeeds, the return value is nonzero.
1528 */
1529static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1530{
1531 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1532
1533 switch(wNotifyCode)
1534 {
1535 case CBN_CLOSEUP:
1536 {
1537 LPSTR lpstrFilter;
1538
1539 /* Get the current item of the filetype combo box */
1540 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1541
1542 /* Set the current filter with the current selection */
1543 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1544 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1545
1546 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1547 iItem);
1548 if((INT)lpstrFilter != CB_ERR)
1549 {
1550 fodInfos->ShellInfos.lpstrCurrentFilter = (LPWSTR)MemAlloc((strlen(lpstrFilter)+1)*2);
1551 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,(LPSTR)strlwr((LPSTR)lpstrFilter));
1552 }
1553
1554 /* Refresh the actual view to display the included items*/
1555 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1556
1557 }
1558 }
1559 return FALSE;
1560}
1561/***********************************************************************
1562 * FILEDLG95_FILETYPE_SearchExt
1563 *
1564 * Search for pidl in the lookin combo box
1565 * returns the index of the found item
1566 */
1567static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt)
1568{
1569 int i = 0;
1570 int iCount = CBGetCount(hwnd);
1571
1572 TRACE("\n");
1573
1574 for(;i<iCount;i++)
1575 {
1576 LPSTR ext = (LPSTR) CBGetItemDataPtr(hwnd,i);
1577
1578 if(!stricmp(lpstrExt,ext))
1579 return i;
1580
1581 }
1582
1583 return -1;
1584}
1585
1586/***********************************************************************
1587 * FILEDLG95_FILETYPE_Clean
1588 *
1589 * Clean the memory used by the filetype combo box
1590 */
1591static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1592{
1593 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1594 int iPos;
1595 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1596
1597 TRACE("\n");
1598
1599 /* Delete each string of the combo and their associated data */
1600 for(iPos = iCount-1;iPos>=0;iPos--)
1601 {
1602 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos)));
1603 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1604 }
1605 /* Current filter */
1606 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1607 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1608
1609}
1610
1611/***********************************************************************
1612 * FILEDLG95_LOOKIN_Init
1613 *
1614 * Initialisation of the look in combo box
1615 */
1616static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1617{
1618 IShellFolder *psfRoot, *psfDrives;
1619 IEnumIDList *lpeRoot, *lpeDrives;
1620 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1621
1622 LookInInfos *liInfos = (LookInInfos*)MemAlloc(sizeof(LookInInfos));
1623
1624 TRACE("\n");
1625
1626 liInfos->iMaxIndentation = 0;
1627
1628 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1629 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1630
1631 /* Initialise data of Desktop folder */
1632 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1633 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1634 COMDLG32_SHFree(pidlTmp);
1635
1636 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1637
1638 COMDLG32_SHGetDesktopFolder(&psfRoot);
1639
1640 if (psfRoot)
1641 {
1642 /* enumerate the contents of the desktop */
1643 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1644 {
1645 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1646 {
1647 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1648
1649 /* special handling for CSIDL_DRIVES */
1650 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1651 {
1652 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1653 {
1654 /* enumerate the drives */
1655 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1656 {
1657 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1658 {
1659 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1660 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1661 COMDLG32_SHFree(pidlAbsTmp);
1662 COMDLG32_SHFree(pidlTmp1);
1663 }
1664 IEnumIDList_Release(lpeDrives);
1665 }
1666 IShellFolder_Release(psfDrives);
1667 }
1668 }
1669 COMDLG32_SHFree(pidlTmp);
1670 }
1671 IEnumIDList_Release(lpeRoot);
1672 }
1673 }
1674
1675 IShellFolder_Release(psfRoot);
1676 COMDLG32_SHFree(pidlDrives);
1677
1678 return NOERROR;
1679}
1680
1681/***********************************************************************
1682 * FILEDLG95_LOOKIN_DrawItem
1683 *
1684 * WM_DRAWITEM message handler
1685 */
1686static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1687{
1688 COLORREF crWin = GetSysColor(COLOR_WINDOW);
1689 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1690 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1691 RECT rectText;
1692 RECT rectIcon;
1693 SHFILEINFOA sfi;
1694 HIMAGELIST ilItemImage;
1695 int iIndentation;
1696 LPSFOLDER tmpFolder;
1697
1698
1699 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1700
1701 TRACE("\n");
1702
1703 if(pDIStruct->itemID == -1)
1704 return 0;
1705
1706 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1707 pDIStruct->itemID)))
1708 return 0;
1709
1710
1711 if(pDIStruct->itemID == liInfos->uSelectedItem)
1712 {
1713 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1714 0,
1715 &sfi,
1716 sizeof (SHFILEINFOA),
1717 SHGFI_PIDL | SHGFI_SMALLICON |
1718 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
1719 SHGFI_DISPLAYNAME );
1720 }
1721 else
1722 {
1723 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1724 0,
1725 &sfi,
1726 sizeof (SHFILEINFOA),
1727 SHGFI_PIDL | SHGFI_SMALLICON |
1728 SHGFI_SYSICONINDEX |
1729 SHGFI_DISPLAYNAME);
1730 }
1731
1732 /* Is this item selected ?*/
1733 if(pDIStruct->itemState & ODS_SELECTED)
1734 {
1735 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1736 SetBkColor(pDIStruct->hDC,crHighLight);
1737 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1738 }
1739 else
1740 {
1741 SetTextColor(pDIStruct->hDC,crText);
1742 SetBkColor(pDIStruct->hDC,crWin);
1743 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1744 }
1745
1746 /* Do not indent item if drawing in the edit of the combo*/
1747 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
1748 {
1749 iIndentation = 0;
1750 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1751 0,
1752 &sfi,
1753 sizeof (SHFILEINFOA),
1754 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
1755 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
1756
1757 }
1758 else
1759 {
1760 iIndentation = tmpFolder->m_iIndent;
1761 }
1762 /* Draw text and icon */
1763
1764 /* Initialise the icon display area */
1765 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
1766 rectIcon.top = pDIStruct->rcItem.top;
1767 rectIcon.right = rectIcon.left + ICONWIDTH;
1768 rectIcon.bottom = pDIStruct->rcItem.bottom;
1769
1770 /* Initialise the text display area */
1771 rectText.left = rectIcon.right;
1772 rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
1773 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
1774 rectText.bottom = pDIStruct->rcItem.bottom;
1775
1776
1777 /* Draw the icon from the image list */
1778 COMDLG32_ImageList_Draw(ilItemImage,
1779 sfi.iIcon,
1780 pDIStruct->hDC,
1781 rectIcon.left,
1782 rectIcon.top,
1783 ILD_TRANSPARENT );
1784
1785 /* Draw the associated text */
1786 if(sfi.szDisplayName)
1787 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
1788
1789
1790 return NOERROR;
1791}
1792
1793/***********************************************************************
1794 * FILEDLG95_LOOKIN_OnCommand
1795 *
1796 * LookIn combo box WM_COMMAND message handler
1797 * If the function succeeds, the return value is nonzero.
1798 */
1799static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
1800{
1801 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1802
1803 TRACE("\n");
1804
1805 switch(wNotifyCode)
1806 {
1807 case CBN_CLOSEUP:
1808 {
1809 LPSFOLDER tmpFolder;
1810 int iItem;
1811
1812 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
1813
1814 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
1815 iItem)))
1816 return FALSE;
1817
1818
1819 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1820 tmpFolder->pidlItem,
1821 SBSP_ABSOLUTE)))
1822 {
1823 return TRUE;
1824 }
1825 break;
1826 }
1827
1828 }
1829 return FALSE;
1830}
1831
1832/***********************************************************************
1833 * FILEDLG95_LOOKIN_AddItem
1834 *
1835 * Adds an absolute pidl item to the lookin combo box
1836 * returns the index of the inserted item
1837 */
1838static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
1839{
1840 LPITEMIDLIST pidlNext;
1841 SHFILEINFOA sfi;
1842 SFOLDER *tmpFolder = (SFOLDER*)MemAlloc(sizeof(SFOLDER));
1843 LookInInfos *liInfos;
1844
1845 TRACE("\n");
1846
1847 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
1848 return -1;
1849
1850 tmpFolder->m_iIndent = 0;
1851
1852 if(!pidl)
1853 return -1;
1854
1855 /* Calculate the indentation of the item in the lookin*/
1856 pidlNext = pidl;
1857 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
1858 {
1859 tmpFolder->m_iIndent++;
1860 }
1861
1862 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl);
1863
1864 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
1865 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
1866
1867 COMDLG32_SHGetFileInfoA((LPSTR)pidl,
1868 0,
1869 &sfi,
1870 sizeof(sfi),
1871 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
1872 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
1873
1874
1875 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
1876 {
1877 int iItemID;
1878 /* Add the item at the end of the list */
1879 if(iInsertId < 0)
1880 {
1881 iItemID = CBAddString(hwnd,sfi.szDisplayName);
1882 }
1883 /* Insert the item at the iInsertId position*/
1884 else
1885 {
1886 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
1887 }
1888
1889 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
1890 return iItemID;
1891 }
1892
1893 return -1;
1894
1895}
1896
1897/***********************************************************************
1898 * FILEDLG95_LOOKIN_InsertItemAfterParent
1899 *
1900 * Insert an item below its parent
1901 */
1902static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
1903{
1904
1905 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
1906 int iParentPos;
1907
1908 TRACE("\n");
1909
1910 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
1911
1912 if(iParentPos < 0)
1913 {
1914 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
1915 }
1916
1917 /* Free pidlParent memory */
1918 COMDLG32_SHFree((LPVOID)pidlParent);
1919
1920 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
1921}
1922
1923/***********************************************************************
1924 * FILEDLG95_LOOKIN_SelectItem
1925 *
1926 * Adds an absolute pidl item to the lookin combo box
1927 * returns the index of the inserted item
1928 */
1929int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
1930{
1931 int iItemPos;
1932 LookInInfos *liInfos;
1933
1934 TRACE("\n");
1935
1936 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
1937
1938 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1939
1940 if(iItemPos < 0)
1941 {
1942 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
1943 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
1944 }
1945
1946 else
1947 {
1948 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1949 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
1950 {
1951 int iRemovedItem;
1952
1953 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
1954 break;
1955 if(iRemovedItem < iItemPos)
1956 iItemPos--;
1957 }
1958 }
1959
1960 CBSetCurSel(hwnd,iItemPos);
1961 liInfos->uSelectedItem = iItemPos;
1962
1963 return 0;
1964
1965}
1966
1967/***********************************************************************
1968 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
1969 *
1970 * Remove the item with an expansion level over iExpansionLevel
1971 */
1972static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
1973{
1974 int iItemPos;
1975
1976 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1977
1978 TRACE("\n");
1979
1980 if(liInfos->iMaxIndentation <= 2)
1981 return -1;
1982
1983 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
1984 {
1985 SFOLDER *tmpFolder;
1986 tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1987 CBDeleteString(hwnd,iItemPos);
1988 liInfos->iMaxIndentation--;
1989
1990 return iItemPos;
1991 }
1992
1993 return -1;
1994}
1995
1996/***********************************************************************
1997 * FILEDLG95_LOOKIN_SearchItem
1998 *
1999 * Search for pidl in the lookin combo box
2000 * returns the index of the found item
2001 */
2002static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2003{
2004 int i = 0;
2005 int iCount = CBGetCount(hwnd);
2006
2007 TRACE("\n");
2008
2009 for(;i<iCount;i++)
2010 {
2011 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2012
2013 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2014 return i;
2015 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2016 return i;
2017
2018 }
2019
2020 return -1;
2021}
2022
2023/***********************************************************************
2024 * FILEDLG95_LOOKIN_Clean
2025 *
2026 * Clean the memory used by the lookin combo box
2027 */
2028static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2029{
2030 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2031 int iPos;
2032 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2033
2034 TRACE("\n");
2035
2036 /* Delete each string of the combo and their associated data */
2037 for(iPos = iCount-1;iPos>=0;iPos--)
2038 {
2039 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos)));
2040 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2041 }
2042 /* LookInInfos structure */
2043 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2044
2045}
2046/*
2047 * TOOLS
2048 */
2049
2050/***********************************************************************
2051 * GetName
2052 *
2053 * Get the pidl's display name (relative to folder) and
2054 * put it in lpstrFileName.
2055 *
2056 * Return NOERROR on success,
2057 * E_FAIL otherwise
2058 */
2059
2060HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2061{
2062 STRRET str;
2063 HRESULT hRes;
2064
2065 TRACE("%p %p\n", lpsf, pidl);
2066
2067 if(!lpsf)
2068 {
2069 HRESULT hRes;
2070 COMDLG32_SHGetDesktopFolder(&lpsf);
2071 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2072 IShellFolder_Release(lpsf);
2073 return hRes;
2074 }
2075
2076 /* Get the display name of the pidl relative to the folder */
2077 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf,
2078 pidl,
2079 dwFlags,
2080 &str)))
2081 {
2082 return StrRetToBufA(&str, pidl,lpstrFileName, MAX_PATH);
2083 }
2084 return E_FAIL;
2085}
2086
2087/***********************************************************************
2088 * GetShellFolderFromPidl
2089 *
2090 * pidlRel is the item pidl relative
2091 * Return the IShellFolder of the absolute pidl
2092 */
2093IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2094{
2095 IShellFolder *psf = NULL,*psfParent;
2096
2097 TRACE("%p\n", pidlAbs);
2098
2099 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
2100 {
2101 psf = psfParent;
2102 if(pidlAbs && pidlAbs->mkid.cb)
2103 {
2104 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2105 {
2106 IShellFolder_Release(psfParent);
2107 return psf;
2108 }
2109 }
2110 /* return the desktop */
2111 return psfParent;
2112 }
2113 return NULL;
2114}
2115
2116/***********************************************************************
2117 * GetParentPidl
2118 *
2119 * Return the LPITEMIDLIST to the parent of the pidl in the list
2120 */
2121LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2122{
2123 LPITEMIDLIST pidlParent;
2124
2125 TRACE("%p\n", pidl);
2126
2127 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2128 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2129
2130 return pidlParent;
2131}
2132
2133/***********************************************************************
2134 * GetPidlFromName
2135 *
2136 * returns the pidl of the file name relative to folder
2137 * NULL if an error occured
2138 */
2139LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName)
2140{
2141 LPITEMIDLIST pidl;
2142 ULONG ulEaten;
2143 wchar_t lpwstrDirName[MAX_PATH];
2144
2145
2146 TRACE("sf=%p file=%s\n", psf, lpcstrFileName);
2147
2148 if(!lpcstrFileName)
2149 return NULL;
2150
2151 MultiByteToWideChar(CP_ACP,
2152 MB_PRECOMPOSED,
2153 lpcstrFileName,
2154 -1,
2155 (LPWSTR)lpwstrDirName,
2156 MAX_PATH);
2157
2158 IShellFolder_ParseDisplayName(psf, 0,
2159 NULL,
2160 (LPWSTR)lpwstrDirName,
2161 &ulEaten,
2162 &pidl,
2163 NULL);
2164
2165 return pidl;
2166}
2167
2168/***********************************************************************
2169 * GetFileExtension
2170 *
2171 */
2172BOOL GetFileExtension(IShellFolder *psf,LPITEMIDLIST pidl,LPSTR lpstrFileExtension)
2173{
2174 char FileName[MAX_PATH];
2175 int result;
2176 char *pdest;
2177 int ch = '.';
2178
2179 if(SUCCEEDED(GetName(psf,pidl,SHGDN_NORMAL,FileName)))
2180 {
2181 if(!(pdest = strrchr( FileName, ch )))
2182 return FALSE;
2183
2184 result = pdest - FileName + 1;
2185 strcpy(lpstrFileExtension,&FileName[result]);
2186 return TRUE;
2187 }
2188 return FALSE;
2189}
2190
2191/*
2192 * Memory allocation methods */
2193char *MemAlloc(UINT size)
2194{
2195 return (char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2196}
2197
2198void MemFree(void *mem)
2199{
2200 if(mem)
2201 {
2202 HeapFree(GetProcessHeap(),0,mem);
2203 }
2204}
Note: See TracBrowser for help on using the repository browser.