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

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

several bugfixes in Wine file dialog

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