Correct usage of a scratch array in X11DRV_PolyBezier.
[wine/multimedia.git] / dlls / commdlg / filedlg95.c
blob10cec946202cc3f8a6b2ad97911ecc14af45064f
1 /*
2 * COMMDLG - File Open Dialogs Win95 look and feel
4 */
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "winbase.h"
9 #include "ldt.h"
10 #include "heap.h"
11 #include "commdlg.h"
12 #include "dlgs.h"
13 #include "cdlg.h"
14 #include "debugtools.h"
15 #include "cderr.h"
16 #include "tweak.h"
17 #include "winnls.h"
18 #include "shellapi.h"
19 #include "tchar.h"
20 #include "filedlgbrowser.h"
21 #include "wine/obj_contextmenu.h"
23 DEFAULT_DEBUG_CHANNEL(commdlg)
26 /***********************************************************************
27 * Data structure and global variables
29 typedef struct SFolder
31 int m_iImageIndex; /* Index of picture in image list */
32 HIMAGELIST hImgList;
33 int m_iIndent; /* Indentation index */
34 LPITEMIDLIST pidlItem; /* absolute pidl of the item */
36 } SFOLDER,*LPSFOLDER;
38 typedef struct tagLookInInfo
40 int iMaxIndentation;
41 UINT uSelectedItem;
42 } LookInInfos;
45 /***********************************************************************
46 * Defines and global variables
49 /* Draw item constant */
50 #define ICONWIDTH 18
51 #define YTEXTOFFSET 2
52 #define XTEXTOFFSET 3
54 /* AddItem flags*/
55 #define LISTEND -1
57 /* SearchItem methods */
58 #define SEARCH_PIDL 1
59 #define SEARCH_EXP 2
60 #define ITEM_NOTFOUND -1
62 /* Undefined windows message sent by CreateViewObject*/
63 #define WM_GETISHELLBROWSER WM_USER+7
65 /* NOTE
66 * Those macros exist in windowsx.h. However, you can't really use them since
67 * they rely on the UNICODE defines and can't be use inside Wine itself.
70 /* Combo box macros */
71 #define CBAddString(hwnd,str) \
72 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
74 #define CBInsertString(hwnd,str,pos) \
75 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
77 #define CBDeleteString(hwnd,pos) \
78 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
80 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
81 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
83 #define CBGetItemDataPtr(hwnd,iItemId) \
84 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
86 #define CBGetLBText(hwnd,iItemId,str) \
87 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
89 #define CBGetCurSel(hwnd) \
90 SendMessageA(hwnd,CB_GETCURSEL,0,0);
92 #define CBSetCurSel(hwnd,pos) \
93 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
95 #define CBGetCount(hwnd) \
96 SendMessageA(hwnd,CB_GETCOUNT,0,0);
97 #define CBShowDropDown(hwnd,show) \
98 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
99 #define CBSetItemHeight(hwnd,index,height) \
100 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
103 const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
104 const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
106 static const char defaultFilter[] = "*.*";
108 /***********************************************************************
109 * Prototypes
112 /* Internal functions used by the dialog */
113 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam);
114 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
115 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
116 BOOL FILEDLG95_OnOpen(HWND hwnd);
117 static LRESULT FILEDLG95_InitUI(HWND hwnd);
118 static void FILEDLG95_Clean(HWND hwnd);
120 /* Functions used by the shell object */
121 static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
122 static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
123 static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
124 static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd);
125 static void FILEDLG95_SHELL_Clean(HWND hwnd);
127 /* Functions used by the filetype combo box */
128 static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
129 static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
130 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt);
131 static void FILEDLG95_FILETYPE_Clean(HWND hwnd);
133 /* Functions used by the Look In combo box */
134 static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo);
135 static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
136 static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
137 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
138 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
139 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
140 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
141 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
142 static void FILEDLG95_LOOKIN_Clean(HWND hwnd);
144 /* Miscellaneous tool functions */
145 HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
146 HRESULT GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
147 IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
148 LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
149 LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
151 /* Shell memory allocation */
152 void *MemAlloc(UINT size);
153 void MemFree(void *mem);
155 BOOL WINAPI GetOpenFileName95(FileOpenDlgInfos *fodInfos);
156 BOOL WINAPI GetSaveFileName95(FileOpenDlgInfos *fodInfos);
157 HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
159 /***********************************************************************
160 * GetOpenFileName95
162 * Creates an Open common dialog box that lets the user select
163 * the drive, directory, and the name of a file or set of files to open.
165 * IN : The FileOpenDlgInfos structure associated with the dialog
166 * OUT : TRUE on success
167 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
169 BOOL WINAPI GetOpenFileName95(FileOpenDlgInfos *fodInfos)
172 LRESULT lRes;
173 LPCVOID template;
174 HRSRC hRes;
175 HANDLE hDlgTmpl = 0;
177 /* Create the dialog from a template */
179 if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATEHANDLE)
181 if (!(template = LockResource( MapHModuleSL(fodInfos->ofnInfos.hInstance ))))
183 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
184 return FALSE;
187 else if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATE)
189 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos.hInstance),
190 (fodInfos->ofnInfos.lpTemplateName), RT_DIALOGA)))
192 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
193 return FALSE;
195 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos.hInstance),
196 hRes )) ||
197 !(template = LockResource( hDlgTmpl )))
199 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
200 return FALSE;
203 else
205 if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(IDD_OPENDIALOG),RT_DIALOGA)))
207 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
208 return FALSE;
210 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
211 !(template = LockResource( hDlgTmpl )))
213 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
214 return FALSE;
218 lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
219 (LPDLGTEMPLATEA) template,
220 fodInfos->ofnInfos.hwndOwner,
221 (DLGPROC) FileOpenDlgProc95,
222 (LPARAM) fodInfos);
224 /* Unable to create the dialog*/
225 if( lRes == -1)
226 return FALSE;
228 return lRes;
231 /***********************************************************************
232 * GetSaveFileName95
234 * Creates an Save as common dialog box that lets the user select
235 * the drive, directory, and the name of a file or set of files to open.
237 * IN : The FileOpenDlgInfos structure associated with the dialog
238 * OUT : TRUE on success
239 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
241 BOOL WINAPI GetSaveFileName95(FileOpenDlgInfos *fodInfos)
244 LRESULT lRes;
245 LPCVOID template;
246 HRSRC hRes;
247 HANDLE hDlgTmpl = 0;
249 /* Create the dialog from a template */
251 if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATEHANDLE)
253 if (!(template = LockResource( MapHModuleSL(fodInfos->ofnInfos.hInstance ))))
255 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
256 return FALSE;
259 else if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATE)
261 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos.hInstance),
262 (fodInfos->ofnInfos.lpTemplateName), RT_DIALOGA)))
264 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
265 return FALSE;
267 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos.hInstance),
268 hRes )) ||
269 !(template = LockResource( hDlgTmpl )))
271 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
272 return FALSE;
275 else
277 if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(IDD_SAVEDIALOG),RT_DIALOGA)))
279 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
280 return FALSE;
282 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
283 !(template = LockResource( hDlgTmpl )))
285 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
286 return FALSE;
289 lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
290 (LPDLGTEMPLATEA) template,
291 fodInfos->ofnInfos.hwndOwner,
292 (DLGPROC) FileOpenDlgProc95,
293 (LPARAM) fodInfos);
294 /* Unable to create the dialog*/
295 if( lRes == -1)
296 return FALSE;
298 return lRes;
301 /***********************************************************************
302 * GetFileDialog95A
304 * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
305 * Call GetOpenFileName95 with this structure and clean the memory.
307 * IN : The OPENFILENAMEA initialisation structure passed to
308 * GetOpenFileNameA win api function (see filedlg.c)
310 BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
313 BOOL ret;
314 FileOpenDlgInfos *fodInfos;
316 /* Initialise FileOpenDlgInfos structure*/
317 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
318 memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn)); fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
319 fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
320 fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
321 if (ofn->lpstrFilter)
323 LPSTR s,x;
325 /* filter is a list... title\0ext\0......\0\0 */
326 s = (LPSTR)ofn->lpstrFilter;
327 while (*s)
328 s = s+strlen(s)+1;
329 s++;
330 x = (LPSTR)MemAlloc(s-ofn->lpstrFilter);
331 memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
332 fodInfos->ofnInfos.lpstrFilter = (LPSTR)x;
334 if (ofn->lpstrCustomFilter)
336 LPSTR s,x;
338 /* filter is a list... title\0ext\0......\0\0 */
339 s = (LPSTR)ofn->lpstrCustomFilter;
340 while (*s)
341 s = s+strlen(s)+1;
342 s++;
343 x = MemAlloc(s-ofn->lpstrCustomFilter);
344 memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
345 fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)x;
347 fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
348 if(ofn->nFilterIndex)
349 fodInfos->ofnInfos.nFilterIndex = --ofn->nFilterIndex;
350 if (ofn->nMaxFile)
352 fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
353 strcpy((LPSTR)fodInfos->ofnInfos.lpstrFile,ofn->lpstrFile);
355 fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
356 fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
357 if (fodInfos->ofnInfos.nMaxFileTitle)
358 fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
359 if (ofn->lpstrInitialDir)
361 fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(strlen(ofn->lpstrInitialDir)+1);
362 strcpy((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,ofn->lpstrInitialDir);
365 if (ofn->lpstrTitle)
367 fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(strlen(ofn->lpstrTitle)+1);
368 strcpy((LPSTR)fodInfos->ofnInfos.lpstrTitle,ofn->lpstrTitle);
371 fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE;
372 fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
373 fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
374 if (ofn->lpstrDefExt)
376 fodInfos->ofnInfos.lpstrDefExt = MemAlloc(strlen(ofn->lpstrDefExt)+1);
377 strcpy((LPSTR)fodInfos->ofnInfos.lpstrDefExt,ofn->lpstrDefExt);
379 fodInfos->ofnInfos.lCustData = ofn->lCustData;
380 fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
382 if (ofn->lpTemplateName)
384 /* template don't work - using normal dialog */
385 /* fodInfos->ofnInfos.lpTemplateName = MemAlloc(strlen(ofn->lpTemplateName));
386 strcpy((LPSTR)fodInfos->ofnInfos.lpTemplateName,ofn->lpTemplateName);*/
387 fodInfos->ofnInfos.Flags &= ~OFN_ENABLETEMPLATEHANDLE;
388 fodInfos->ofnInfos.Flags &= ~OFN_ENABLETEMPLATE;
389 FIXME("File dialog 95 template not implemented\n");
393 /* Replace the NULL lpstrInitialDir by the current folder */
394 if(!ofn->lpstrInitialDir)
396 fodInfos->ofnInfos.lpstrInitialDir = MemAlloc(MAX_PATH);
397 GetCurrentDirectoryA(MAX_PATH,(LPSTR)fodInfos->ofnInfos.lpstrInitialDir);
400 /* Initialise the dialog property */
401 fodInfos->DlgInfos.dwDlgProp = 0;
403 switch(iDlgType)
405 case OPEN_DIALOG :
406 ret = GetOpenFileName95(fodInfos);
407 break;
408 case SAVE_DIALOG :
409 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
410 ret = GetSaveFileName95(fodInfos);
411 break;
412 default :
413 ret = 0;
416 ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
417 ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
418 if (fodInfos->ofnInfos.lpstrFilter)
419 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
420 if (fodInfos->ofnInfos.lpTemplateName)
421 MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
422 if (fodInfos->ofnInfos.lpstrDefExt)
423 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
424 if (fodInfos->ofnInfos.lpstrTitle)
425 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
426 if (fodInfos->ofnInfos.lpstrInitialDir)
427 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
428 if (fodInfos->ofnInfos.lpstrCustomFilter)
429 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
431 if (fodInfos->ofnInfos.lpstrFile)
433 strcpy(ofn->lpstrFile,fodInfos->ofnInfos.lpstrFile);
434 MemFree((LPVOID)fodInfos->ofnInfos.lpstrFile);
436 if (fodInfos->ofnInfos.lpstrFileTitle)
438 if (ofn->lpstrFileTitle)
439 strcpy(ofn->lpstrFileTitle,
440 fodInfos->ofnInfos.lpstrFileTitle);
441 MemFree((LPVOID)fodInfos->ofnInfos.lpstrFileTitle);
444 MemFree((LPVOID)(fodInfos));
445 return ret;
448 /***********************************************************************
449 * GetFileDialog95W
451 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
452 * Call GetOpenFileName95 with this structure and clean the memory.
454 * IN : The OPENFILENAMEW initialisation structure passed to
455 * GetOpenFileNameW win api function (see filedlg.c)
457 BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
459 BOOL ret;
460 FileOpenDlgInfos *fodInfos;
462 /* Initialise FileOpenDlgInfos structure*/
463 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
464 memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn));
465 fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
466 fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
467 fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
468 if (ofn->lpstrFilter)
470 LPWSTR s;
471 LPSTR x,y;
472 int n;
474 /* filter is a list... title\0ext\0......\0\0 */
475 s = (LPWSTR)ofn->lpstrFilter;
477 while (*s)
478 s = s+lstrlenW(s)+1;
479 s++;
480 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
481 x = y = (LPSTR)MemAlloc(n);
482 s = (LPWSTR)ofn->lpstrFilter;
483 while (*s) {
484 lstrcpyWtoA(x,s);
485 x+=lstrlenA(x)+1;
486 s+=lstrlenW(s)+1;
488 *x=0;
489 fodInfos->ofnInfos.lpstrFilter = (LPSTR)y;
491 if (ofn->lpstrCustomFilter) {
492 LPWSTR s;
493 LPSTR x,y;
494 int n;
496 /* filter is a list... title\0ext\0......\0\0 */
497 s = (LPWSTR)ofn->lpstrCustomFilter;
498 while (*s)
499 s = s+lstrlenW(s)+1;
500 s++;
501 n = s - ofn->lpstrCustomFilter;
502 x = y = (LPSTR)MemAlloc(n);
503 s = (LPWSTR)ofn->lpstrCustomFilter;
504 while (*s) {
505 lstrcpyWtoA(x,s);
506 x+=lstrlenA(x)+1;
507 s+=lstrlenW(s)+1;
509 *x=0;
510 fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)y;
512 fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
513 fodInfos->ofnInfos.nFilterIndex = ofn->nFilterIndex;
514 if (ofn->nMaxFile)
515 fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
516 fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
517 fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
518 if (ofn->nMaxFileTitle)
519 fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
520 if (ofn->lpstrInitialDir)
522 fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrInitialDir)+1);
523 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,ofn->lpstrInitialDir);
525 if (ofn->lpstrTitle)
527 fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrTitle)+1);
528 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrTitle,ofn->lpstrTitle);
530 fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
531 fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
532 fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
533 if (ofn->lpstrDefExt)
535 fodInfos->ofnInfos.lpstrDefExt = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrDefExt)+1);
536 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrDefExt,ofn->lpstrDefExt);
538 fodInfos->ofnInfos.lCustData = ofn->lCustData;
539 fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
540 if (ofn->lpTemplateName)
542 fodInfos->ofnInfos.lpTemplateName = (LPSTR)MemAlloc(lstrlenW(ofn->lpTemplateName)+1);
543 lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpTemplateName,ofn->lpTemplateName);
545 /* Initialise the dialog property */
546 fodInfos->DlgInfos.dwDlgProp = 0;
548 switch(iDlgType)
550 case OPEN_DIALOG :
551 ret = GetOpenFileName95(fodInfos);
552 break;
553 case SAVE_DIALOG :
554 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
555 ret = GetSaveFileName95(fodInfos);
556 break;
557 default :
558 ret = 0;
561 /* Cleaning */
562 ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
563 ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
564 if (fodInfos->ofnInfos.lpstrFilter)
565 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
566 if (fodInfos->ofnInfos.lpTemplateName)
567 MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
568 if (fodInfos->ofnInfos.lpstrDefExt)
569 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
570 if (fodInfos->ofnInfos.lpstrTitle)
571 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
572 if (fodInfos->ofnInfos.lpstrInitialDir)
573 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
574 if (fodInfos->ofnInfos.lpstrCustomFilter)
575 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
577 if (fodInfos->ofnInfos.lpstrFile) {
578 lstrcpyAtoW(ofn->lpstrFile,(fodInfos->ofnInfos.lpstrFile));
579 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFile));
582 if (fodInfos->ofnInfos.lpstrFileTitle) {
583 if (ofn->lpstrFileTitle)
584 lstrcpyAtoW(ofn->lpstrFileTitle,
585 (fodInfos->ofnInfos.lpstrFileTitle));
586 MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFileTitle));
588 MemFree((LPVOID)(fodInfos));
589 return ret;
594 /***********************************************************************
595 * FileOpenDlgProc95
597 * File open dialog procedure
599 HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
602 switch(uMsg)
604 case WM_INITDIALOG :
605 return FILEDLG95_OnWMInitDialog(hwnd, wParam, lParam);
606 case WM_COMMAND:
607 return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
608 case WM_DRAWITEM:
610 switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
612 case IDC_LOOKIN:
613 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
614 return TRUE;
617 return FALSE;
619 case WM_GETISHELLBROWSER:
620 return FILEDLG95_OnWMGetIShellBrowser(hwnd);
622 case WM_DESTROY:
623 RemovePropA(hwnd, FileOpenDlgInfosStr);
625 default :
626 return FALSE;
630 /***********************************************************************
631 * FILEDLG95_OnWMInitDialog
633 * WM_INITDIALOG message handler
635 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam)
637 LPITEMIDLIST pidlItemId;
638 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
640 TRACE("\n");
642 /* Adds the FileOpenDlgInfos in the property list of the dialog
643 so it will be easily accessible through a GetPropA(...) */
644 SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) fodInfos);
646 /* Make sure the common control DLL is loaded */
647 InitCommonControls();
649 /* Initialise shell objects */
650 FILEDLG95_SHELL_Init(hwnd);
652 /* Initialise dialog UI */
653 FILEDLG95_InitUI(hwnd);
655 /* Initialize the Look In combo box*/
656 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
658 /* Initialize the filter combo box */
659 FILEDLG95_FILETYPE_Init(hwnd);
661 /* Get the initial directory pidl */
663 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos.lpstrInitialDir)))
665 char path[MAX_PATH];
667 GetCurrentDirectoryA(MAX_PATH,path);
668 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
669 path);
673 /* Browse to the initial directory */
674 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId,SBSP_RELATIVE);
676 /* Free pidlItem memory */
677 COMDLG32_SHFree(pidlItemId);
679 return TRUE;
681 /***********************************************************************
682 * FILEDLG95_Clean
684 * Regroups all the cleaning functions of the filedlg
686 void FILEDLG95_Clean(HWND hwnd)
688 FILEDLG95_FILETYPE_Clean(hwnd);
689 FILEDLG95_LOOKIN_Clean(hwnd);
690 FILEDLG95_SHELL_Clean(hwnd);
692 /***********************************************************************
693 * FILEDLG95_OnWMCommand
695 * WM_COMMAND message handler
697 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
699 WORD wNotifyCode = HIWORD(wParam); /* notification code */
700 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
701 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
703 switch(wID)
705 /* OK button */
706 case IDOK:
707 FILEDLG95_OnOpen(hwnd);
708 break;
709 /* Cancel button */
710 case IDCANCEL:
711 FILEDLG95_Clean(hwnd);
712 EndDialog(hwnd, FALSE);
713 break;
714 /* Filetype combo box */
715 case IDC_FILETYPE:
716 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
717 break;
718 /* LookIn combo box */
719 case IDC_LOOKIN:
720 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
721 break;
722 /* Up folder button */
723 case IDC_UPFOLDER:
724 FILEDLG95_SHELL_UpFolder(hwnd);
725 break;
726 /* List option button */
727 case IDC_LIST:
728 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
729 break;
730 /* Details option button */
731 case IDC_DETAILS:
732 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
733 break;
734 /* New folder button */
735 case IDC_NEWFOLDER:
736 FILEDLG95_SHELL_NewFolder(hwnd);
737 break;
739 case IDC_FILENAME:
740 break;
743 /* Do not use the listview selection anymore */
744 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
745 return 0;
748 /***********************************************************************
749 * FILEDLG95_OnWMGetIShellBrowser
751 * WM_GETISHELLBROWSER message handler
753 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
756 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
758 TRACE("\n");
760 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
762 return TRUE;
766 /***********************************************************************
767 * FILEDLG95_InitUI
770 static LRESULT FILEDLG95_InitUI(HWND hwnd)
772 HIMAGELIST himlToolbar;
773 HICON hicon;
774 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
776 TRACE("%p\n", fodInfos);
778 /* Get the hwnd of the controls */
779 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
780 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
781 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
783 ShowWindow(GetDlgItem(hwnd,IDC_SHELLSTATIC),SW_HIDE);
784 /* Load the icons bitmaps */
786 if((himlToolbar = COMDLG32_ImageList_LoadImageA(COMMDLG_hInstance32,
787 MAKEINTRESOURCEA(IDB_TOOLBAR),
790 CLR_DEFAULT,
791 IMAGE_BITMAP,
792 0)))
794 /* Up folder icon */
795 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,0,ILD_NORMAL)))
796 SendDlgItemMessageA(hwnd,IDC_UPFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
797 /* New folder icon */
798 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,1,ILD_NORMAL)))
799 SendDlgItemMessageA(hwnd,IDC_NEWFOLDER,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
800 /* List view icon */
801 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,2,ILD_NORMAL)))
802 SendDlgItemMessageA(hwnd,IDC_LIST,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
803 /* Detail view icon */
804 if((hicon = COMDLG32_ImageList_GetIcon(himlToolbar,3,ILD_NORMAL)))
805 SendDlgItemMessageA(hwnd,IDC_DETAILS,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)hicon);
806 /* Cleanup */
807 COMDLG32_ImageList_Destroy(himlToolbar);
812 /* Set the window text with the text specified in the OPENFILENAME structure */
813 if(fodInfos->ofnInfos.lpstrTitle)
814 SetWindowTextA(hwnd,fodInfos->ofnInfos.lpstrTitle);
816 /* Initialise the file name edit control */
817 if(strlen(fodInfos->ofnInfos.lpstrFile))
819 SetDlgItemTextA(hwnd,IDC_FILENAME,fodInfos->ofnInfos.lpstrFile);
821 /* Must the open as read only check box be checked ?*/
822 if(fodInfos->ofnInfos.Flags & OFN_READONLY)
824 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
826 /* Must the open as read only check box be hid ?*/
827 if(fodInfos->ofnInfos.Flags & OFN_HIDEREADONLY)
829 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
832 return 0;
835 /***********************************************************************
836 * FILEDLG95_OnOpen
838 * Ok button WM_COMMAND message handler
840 * If the function succeeds, the return value is nonzero.
842 BOOL FILEDLG95_OnOpen(HWND hwnd)
844 char lpstrSpecifiedByUser[MAX_PATH] = "";
845 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
846 LPITEMIDLIST pidlSelection;
848 TRACE("\n");
850 /* Check if there is a selected item in the listview */
851 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_USEVIEW)
853 pidlSelection = GetSelectedPidl(fodInfos->Shell.FOIShellView);
854 GetName(fodInfos->Shell.FOIShellFolder,pidlSelection,SHGDN_NORMAL,lpstrSpecifiedByUser);
855 COMDLG32_SHFree((LPVOID)pidlSelection);
857 else
858 /* Get the text from the filename edit */
859 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrSpecifiedByUser,MAX_PATH);
861 if(strlen(lpstrSpecifiedByUser))
863 LPSHELLFOLDER psfDesktop;
864 LPITEMIDLIST browsePidl;
865 LPSTR lpstrFileSpec;
866 LPSTR lpstrTemp;
867 char lpstrPathSpec[MAX_PATH] = "";
868 char lpstrCurrentDir[MAX_PATH] = "";
869 char lpstrPathAndFile[MAX_PATH] = "";
871 /* Separate the file spec from the path spec
872 e.g.:
873 lpstrSpecifiedByUser lpstrPathSpec lpstrFileSpec
874 C:\TEXT1\TEXT2 C:\TEXT1 TEXT2
876 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser);
877 strcpy(lpstrPathSpec,lpstrSpecifiedByUser);
878 COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
880 /* Get the current directory name */
881 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
882 lpstrCurrentDir);
884 /* Create an absolute path name */
885 if(lpstrSpecifiedByUser[1] != ':')
887 switch(lpstrSpecifiedByUser[0])
889 /* Add drive spec \TEXT => C:\TEXT */
890 case '\\':
892 INT iCopy = 2;
893 char lpstrTmp[MAX_PATH] = "";
894 if(!strlen(lpstrPathSpec))
895 iCopy = 3;
896 strncpy(lpstrTmp,lpstrCurrentDir,iCopy);
897 strcat(lpstrTmp,lpstrPathSpec);
898 strcpy(lpstrPathSpec,lpstrTmp);
900 break;
901 /* Go to parent ..\TEXT */
902 case '.':
904 INT iSize;
905 char lpstrTmp2[MAX_PATH] = "";
906 LPSTR lpstrTmp = strrchr(lpstrCurrentDir,'\\');
907 iSize = lpstrTmp - lpstrCurrentDir;
908 strncpy(lpstrTmp2,lpstrCurrentDir,iSize + 1);
909 if(strlen(lpstrSpecifiedByUser) <= 3)
910 strcpy(lpstrFileSpec,"");
911 if(strcmp(lpstrPathSpec,".."))
912 strcat(lpstrTmp2,&lpstrPathSpec[3]);
913 strcpy(lpstrPathSpec,lpstrTmp2);
915 break;
916 default:
918 char lpstrTmp[MAX_PATH] = "";
919 if(strcmp(&lpstrCurrentDir[strlen(lpstrCurrentDir)-1],"\\"))
920 strcat(lpstrCurrentDir,"\\");
921 strcpy(lpstrTmp,lpstrCurrentDir);
922 strcat(lpstrTmp,lpstrPathSpec);
923 strcpy(lpstrPathSpec,lpstrTmp);
926 } /* end switch */
929 if(strlen(lpstrPathSpec))
931 /* Browse to the right directory */
932 COMDLG32_SHGetDesktopFolder(&psfDesktop);
933 if((browsePidl = GetPidlFromName(psfDesktop,lpstrPathSpec)))
935 /* Browse to directory */
936 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
937 browsePidl,
938 SBSP_ABSOLUTE);
939 COMDLG32_SHFree(browsePidl);
941 else
943 /* Path does not exist */
944 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
946 MessageBoxA(hwnd,
947 "Path does not exist",
948 fodInfos->ofnInfos.lpstrTitle,
949 MB_OK | MB_ICONEXCLAMATION);
950 return FALSE;
954 strcat(lpstrPathAndFile,lpstrPathSpec);
955 IShellFolder_Release(psfDesktop);
957 else
959 strcat(lpstrPathAndFile,lpstrCurrentDir);
962 /* Create the path and file string */
963 COMDLG32_PathAddBackslashA(lpstrPathAndFile);
964 strcat(lpstrPathAndFile,lpstrFileSpec);
966 /* Update the edit field */
967 SetDlgItemTextA(hwnd,IDC_FILENAME,lpstrFileSpec);
968 SendDlgItemMessageA(hwnd,IDC_FILENAME,EM_SETSEL,0,-1);
970 /* Don't go further if we dont have a file spec */
971 if(!strlen(lpstrFileSpec) || !strcmp(lpstrFileSpec,lpstrPathSpec))
972 return FALSE;
974 /* Time to check lpstrFileSpec */
975 /* search => contains * or ? */
976 /* browse => contains a directory name */
977 /* file => contains a file name */
979 /* Check if this is a search */
980 if(strchr(lpstrFileSpec,'*') || strchr(lpstrFileSpec,'?'))
982 int iPos;
984 /* Set the current filter with the current selection */
985 if(fodInfos->ShellInfos.lpstrCurrentFilter)
986 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
988 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFileSpec)+1)*2);
989 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,
990 (LPSTR)strlwr((LPSTR)lpstrFileSpec));
992 IShellView_Refresh(fodInfos->Shell.FOIShellView);
994 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB,
995 lpstrFileSpec)))
996 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
998 return FALSE;
1001 /* browse if the user specified a directory */
1002 if((browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1003 lpstrFileSpec)))
1005 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
1006 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder,
1008 &browsePidl,
1009 &ulAttr);
1011 /* Browse to directory */
1012 if(ulAttr)
1014 if(FAILED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1015 browsePidl,
1016 SBSP_RELATIVE)))
1018 if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1020 MessageBoxA(hwnd,
1021 "Path does not exist",
1022 fodInfos->ofnInfos.lpstrTitle,
1023 MB_OK | MB_ICONEXCLAMATION);
1024 COMDLG32_SHFree(browsePidl);
1025 return FALSE;
1028 COMDLG32_SHFree(browsePidl);
1029 return FALSE;
1031 COMDLG32_SHFree(browsePidl);
1033 else
1035 /* File does not exist in current directory */
1037 /* The selected file does not exist */
1038 /* Tell the user the selected does not exist */
1039 if(fodInfos->ofnInfos.Flags & OFN_FILEMUSTEXIST)
1041 char lpstrNotFound[100];
1042 char lpstrMsg[100];
1043 char tmp[400];
1045 LoadStringA(COMMDLG_hInstance32,
1046 IDS_FILENOTFOUND,
1047 lpstrNotFound,
1048 100);
1049 LoadStringA(COMMDLG_hInstance32,
1050 IDS_VERIFYFILE,
1051 lpstrMsg,
1052 100);
1054 strcpy(tmp,fodInfos->ofnInfos.lpstrFile);
1055 strcat(tmp,"\n");
1056 strcat(tmp,lpstrNotFound);
1057 strcat(tmp,"\n");
1058 strcat(tmp,lpstrMsg);
1060 MessageBoxA(hwnd,
1061 tmp,
1062 fodInfos->ofnInfos.lpstrTitle,
1063 MB_OK | MB_ICONEXCLAMATION);
1064 return FALSE;
1066 /* Ask the user if he wants to create the file*/
1067 if(fodInfos->ofnInfos.Flags & OFN_CREATEPROMPT)
1069 char tmp[100];
1071 LoadStringA(COMMDLG_hInstance32,IDS_CREATEFILE,tmp,100);
1073 if(IDYES == MessageBoxA(hwnd,tmp,fodInfos->ofnInfos.lpstrTitle,
1074 MB_YESNO | MB_ICONQUESTION))
1076 /* Create the file, clean and exit */
1077 FILEDLG95_Clean(hwnd);
1078 return EndDialog(hwnd,TRUE);
1080 return FALSE;
1084 /* Open the selected file */
1086 /* Check file extension */
1087 if(!strrchr(lpstrPathAndFile,'.'))
1089 /* if the file has no extension, append the selected
1090 extension of the filetype combo box */
1091 int iExt;
1092 LPSTR lpstrExt;
1093 iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1094 lpstrTemp = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iExt);
1096 if((lpstrExt = strchr(lpstrTemp,';')))
1098 int i = lpstrExt - lpstrTemp;
1099 lpstrExt = MemAlloc(i);
1100 strncpy(lpstrExt,&lpstrTemp[1],i-1);
1102 else
1104 lpstrExt = MemAlloc(strlen(lpstrTemp));
1105 strcpy(lpstrExt,&lpstrTemp[1]);
1108 if(!strcmp(&lpstrExt[1],"*") && fodInfos->ofnInfos.lpstrDefExt)
1110 lpstrExt = MemAlloc(strlen(fodInfos->ofnInfos.lpstrDefExt)+2);
1111 strcat(lpstrExt,".");
1112 strcat(lpstrExt,(LPSTR) fodInfos->ofnInfos.lpstrDefExt);
1114 strcat(lpstrPathAndFile,lpstrExt);
1116 /* Check that size size of the file does not exceed buffer size */
1117 if(strlen(lpstrPathAndFile) > fodInfos->ofnInfos.nMaxFile)
1119 /* set error FNERR_BUFFERTOSMALL */
1120 FILEDLG95_Clean(hwnd);
1121 return EndDialog(hwnd,FALSE);
1123 strcpy(fodInfos->ofnInfos.lpstrFile,lpstrPathAndFile);
1125 /* Set the lpstrFileTitle of the OPENFILENAME structure */
1126 if(fodInfos->ofnInfos.lpstrFileTitle)
1127 strncpy(fodInfos->ofnInfos.lpstrFileTitle,
1128 lpstrFileSpec,
1129 fodInfos->ofnInfos.nMaxFileTitle);
1131 /* Check if the file is to be opened as read only */
1132 if(BST_CHECKED == SendDlgItemMessageA(hwnd,
1133 IDC_OPENREADONLY,
1134 BM_GETSTATE,0,0))
1135 SetFileAttributesA(fodInfos->ofnInfos.lpstrFile,
1136 FILE_ATTRIBUTE_READONLY);
1138 /* nFileExtension and nFileOffset of OPENFILENAME structure */
1139 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'\\');
1140 fodInfos->ofnInfos.nFileOffset = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1141 lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'.');
1142 fodInfos->ofnInfos.nFileExtension = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1145 /* clean and exit */
1146 FILEDLG95_Clean(hwnd);
1147 return EndDialog(hwnd,TRUE);
1150 return FALSE;
1153 /***********************************************************************
1154 * FILEDLG95_SHELL_Init
1156 * Initialisation of the shell objects
1158 static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1160 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1162 TRACE("\n");
1165 * Initialisation of the FileOpenDialogInfos structure
1168 /* Shell */
1170 fodInfos->Shell.FOIShellView = NULL;
1171 if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos->Shell.FOIShellFolder)))
1172 return E_FAIL;
1174 /*ShellInfos */
1175 fodInfos->ShellInfos.hwndOwner = hwnd;
1177 fodInfos->ShellInfos.folderSettings.fFlags = FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1178 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1180 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1181 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1182 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1184 /* Construct the IShellBrowser interface */
1185 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1187 return NOERROR;
1190 /***********************************************************************
1191 * FILEDLG95_SHELL_ExecuteCommand
1193 * Change the folder option and refresh the view
1194 * If the function succeeds, the return value is nonzero.
1196 static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1198 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1200 IContextMenu * pcm;
1201 CMINVOKECOMMANDINFO ci;
1202 TRACE("\n");
1204 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1205 SVGIO_BACKGROUND,
1206 &IID_IContextMenu,
1207 (LPVOID*)&pcm)))
1209 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1210 ci.lpVerb = lpVerb;
1211 ci.hwnd = hwnd;
1213 IContextMenu_InvokeCommand(pcm, &ci);
1214 IContextMenu_Release(pcm);
1217 return FALSE;
1220 /***********************************************************************
1221 * FILEDLG95_SHELL_UpFolder
1223 * Browse to the specified object
1224 * If the function succeeds, the return value is nonzero.
1226 static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1228 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1230 TRACE("\n");
1232 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1233 NULL,
1234 SBSP_PARENT)))
1236 return TRUE;
1238 return FALSE;
1241 /***********************************************************************
1242 * FILEDLG95_SHELL_NewFolder
1244 * Creates a new directory with New folder as name
1245 * If the function succeeds, the return value is nonzero.
1246 * FIXME: let the contextmenu (CMDSTR_NEWFOLDER) do this thing
1248 static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd)
1250 char lpstrDirName[MAX_PATH] = "New folder";
1251 BOOL bRes;
1252 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1254 TRACE("\n");
1256 if((bRes = CreateDirectoryA(lpstrDirName,NULL)))
1258 LPITEMIDLIST pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,lpstrDirName);
1259 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1260 IShellView_SelectItem(fodInfos->Shell.FOIShellView,
1261 pidl,
1262 (SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
1263 |SVSI_FOCUSED|SVSI_SELECT));
1268 return bRes;
1271 /***********************************************************************
1272 * FILEDLG95_SHELL_Clean
1274 * Cleans the memory used by shell objects
1276 static void FILEDLG95_SHELL_Clean(HWND hwnd)
1278 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1280 TRACE("\n");
1282 /* clean Shell interfaces */
1283 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1284 IShellView_Release(fodInfos->Shell.FOIShellView);
1285 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1286 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1289 /***********************************************************************
1290 * FILEDLG95_FILETYPE_Init
1292 * Initialisation of the file type combo box
1294 static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1296 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1298 TRACE("\n");
1300 if(fodInfos->ofnInfos.lpstrFilter)
1302 int iStrIndex = 0;
1303 int iPos = 0;
1304 LPSTR lpstrFilter;
1305 LPSTR lpstrTmp;
1307 for(;;)
1309 /* filter is a list... title\0ext\0......\0\0 */
1310 /* Set the combo item text to the title and the item data
1311 to the ext */
1312 char *lpstrExt = NULL;
1313 LPSTR lpstrExtTmp = NULL;
1314 /* Get the title */
1315 lpstrTmp = (&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1316 if(!strlen(lpstrTmp))
1317 break;
1318 iStrIndex += strlen(lpstrTmp) +1;
1319 /* Get the extension */
1320 lpstrExtTmp = (&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1321 if(!lpstrExtTmp)
1322 break;
1324 lpstrExt = (LPSTR) MemAlloc(strlen(lpstrExtTmp)+1);
1325 if(!lpstrExt)
1326 break;
1328 strcpy(lpstrExt,lpstrExtTmp);
1330 iStrIndex += strlen(lpstrExt) +1;
1332 /* Add the item at the end of the combo */
1333 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB,lpstrTmp);
1334 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos++,lpstrExt);
1336 /* Set the current filter to the one specified
1337 in the initialisation structure */
1338 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,
1339 fodInfos->ofnInfos.nFilterIndex);
1341 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1342 fodInfos->ofnInfos.nFilterIndex);
1343 if(lpstrFilter)
1345 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1346 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,strlwr(lpstrFilter));
1349 return NOERROR;
1352 /***********************************************************************
1353 * FILEDLG95_FILETYPE_OnCommand
1355 * WM_COMMAND of the file type combo box
1356 * If the function succeeds, the return value is nonzero.
1358 static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1360 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1362 switch(wNotifyCode)
1364 case CBN_CLOSEUP:
1366 LPSTR lpstrFilter;
1368 /* Get the current item of the filetype combo box */
1369 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1371 /* Set the current filter with the current selection */
1372 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1373 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1375 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1376 iItem);
1377 if(lpstrFilter)
1379 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1380 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,(LPSTR)strlwr((LPSTR)lpstrFilter));
1383 /* Refresh the actual view to display the included items*/
1384 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1388 return FALSE;
1390 /***********************************************************************
1391 * FILEDLG95_FILETYPE_SearchExt
1393 * Search for pidl in the lookin combo box
1394 * returns the index of the found item
1396 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt)
1398 int i = 0;
1399 int iCount = CBGetCount(hwnd);
1401 TRACE("\n");
1403 for(;i<iCount;i++)
1405 LPSTR ext = (LPSTR) CBGetItemDataPtr(hwnd,i);
1407 if(!_stricmp(lpstrExt,ext))
1408 return i;
1412 return -1;
1415 /***********************************************************************
1416 * FILEDLG95_FILETYPE_Clean
1418 * Clean the memory used by the filetype combo box
1420 static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1422 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1423 int iPos;
1424 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1426 TRACE("\n");
1428 /* Delete each string of the combo and their associated data */
1429 for(iPos = iCount-1;iPos>=0;iPos--)
1431 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos)));
1432 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1434 /* Current filter */
1435 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1436 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1440 /***********************************************************************
1441 * FILEDLG95_LOOKIN_Init
1443 * Initialisation of the look in combo box
1445 static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1447 IShellFolder *psfRoot, *psfDrives;
1448 IEnumIDList *lpeRoot, *lpeDrives;
1449 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1451 LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
1453 TRACE("\n");
1455 liInfos->iMaxIndentation = 0;
1457 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1458 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1460 /* Initialise data of Desktop folder */
1461 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1462 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1463 COMDLG32_SHFree(pidlTmp);
1465 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1467 COMDLG32_SHGetDesktopFolder(&psfRoot);
1469 if (psfRoot)
1471 /* enumerate the contents of the desktop */
1472 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1474 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1476 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1478 /* special handling for CSIDL_DRIVES */
1479 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1481 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1483 /* enumerate the drives */
1484 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1486 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1488 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1489 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1490 COMDLG32_SHFree(pidlAbsTmp);
1491 COMDLG32_SHFree(pidlTmp1);
1493 IEnumIDList_Release(lpeDrives);
1495 IShellFolder_Release(psfDrives);
1498 COMDLG32_SHFree(pidlTmp);
1500 IEnumIDList_Release(lpeRoot);
1504 IShellFolder_Release(psfRoot);
1505 COMDLG32_SHFree(pidlDrives);
1507 return NOERROR;
1510 /***********************************************************************
1511 * FILEDLG95_LOOKIN_DrawItem
1513 * WM_DRAWITEM message handler
1515 static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1517 COLORREF crWin = GetSysColor(COLOR_WINDOW);
1518 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1519 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1520 RECT rectText;
1521 RECT rectIcon;
1522 SHFILEINFOA sfi;
1523 HIMAGELIST ilItemImage;
1524 int iIndentation;
1525 LPSFOLDER tmpFolder;
1528 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1530 TRACE("\n");
1532 if(pDIStruct->itemID == -1)
1533 return 0;
1535 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1536 pDIStruct->itemID)))
1537 return 0;
1540 if(pDIStruct->itemID == liInfos->uSelectedItem)
1542 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1544 &sfi,
1545 sizeof (SHFILEINFOA),
1546 SHGFI_PIDL | SHGFI_SMALLICON |
1547 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
1548 SHGFI_DISPLAYNAME );
1550 else
1552 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1554 &sfi,
1555 sizeof (SHFILEINFOA),
1556 SHGFI_PIDL | SHGFI_SMALLICON |
1557 SHGFI_SYSICONINDEX |
1558 SHGFI_DISPLAYNAME);
1561 /* Is this item selected ?*/
1562 if(pDIStruct->itemState & ODS_SELECTED)
1564 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1565 SetBkColor(pDIStruct->hDC,crHighLight);
1566 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1568 else
1570 SetTextColor(pDIStruct->hDC,crText);
1571 SetBkColor(pDIStruct->hDC,crWin);
1572 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1575 /* Do not indent item if drawing in the edit of the combo*/
1576 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
1578 iIndentation = 0;
1579 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1581 &sfi,
1582 sizeof (SHFILEINFOA),
1583 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
1584 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
1587 else
1589 iIndentation = tmpFolder->m_iIndent;
1591 /* Draw text and icon */
1593 /* Initialise the icon display area */
1594 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
1595 rectIcon.top = pDIStruct->rcItem.top;
1596 rectIcon.right = rectIcon.left + ICONWIDTH;
1597 rectIcon.bottom = pDIStruct->rcItem.bottom;
1599 /* Initialise the text display area */
1600 rectText.left = rectIcon.right;
1601 rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
1602 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
1603 rectText.bottom = pDIStruct->rcItem.bottom;
1606 /* Draw the icon from the image list */
1607 COMDLG32_ImageList_Draw(ilItemImage,
1608 sfi.iIcon,
1609 pDIStruct->hDC,
1610 rectIcon.left,
1611 rectIcon.top,
1612 ILD_TRANSPARENT );
1614 /* Draw the associated text */
1615 if(sfi.szDisplayName)
1616 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
1619 return NOERROR;
1622 /***********************************************************************
1623 * FILEDLG95_LOOKIN_OnCommand
1625 * LookIn combo box WM_COMMAND message handler
1626 * If the function succeeds, the return value is nonzero.
1628 static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
1630 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1632 TRACE("\n");
1634 switch(wNotifyCode)
1636 case CBN_CLOSEUP:
1638 LPSFOLDER tmpFolder;
1639 int iItem;
1641 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
1643 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
1644 iItem)))
1645 return FALSE;
1648 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1649 tmpFolder->pidlItem,
1650 SBSP_ABSOLUTE)))
1652 return TRUE;
1654 break;
1658 return FALSE;
1661 /***********************************************************************
1662 * FILEDLG95_LOOKIN_AddItem
1664 * Adds an absolute pidl item to the lookin combo box
1665 * returns the index of the inserted item
1667 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
1669 LPITEMIDLIST pidlNext;
1670 SHFILEINFOA sfi;
1671 SFOLDER *tmpFolder = MemAlloc(sizeof(SFOLDER));
1672 LookInInfos *liInfos;
1674 TRACE("\n");
1676 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
1677 return -1;
1679 tmpFolder->m_iIndent = 0;
1681 if(!pidl)
1682 return -1;
1684 /* Calculate the indentation of the item in the lookin*/
1685 pidlNext = pidl;
1686 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
1688 tmpFolder->m_iIndent++;
1691 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl);
1693 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
1694 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
1696 COMDLG32_SHGetFileInfoA((LPSTR)pidl,
1698 &sfi,
1699 sizeof(sfi),
1700 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
1701 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
1704 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
1706 int iItemID;
1707 /* Add the item at the end of the list */
1708 if(iInsertId < 0)
1710 iItemID = CBAddString(hwnd,sfi.szDisplayName);
1712 /* Insert the item at the iInsertId position*/
1713 else
1715 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
1718 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
1719 return iItemID;
1722 return -1;
1726 /***********************************************************************
1727 * FILEDLG95_LOOKIN_InsertItemAfterParent
1729 * Insert an item below its parent
1731 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
1734 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
1735 int iParentPos;
1737 TRACE("\n");
1739 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
1741 if(iParentPos < 0)
1743 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
1746 /* Free pidlParent memory */
1747 COMDLG32_SHFree((LPVOID)pidlParent);
1749 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
1752 /***********************************************************************
1753 * FILEDLG95_LOOKIN_SelectItem
1755 * Adds an absolute pidl item to the lookin combo box
1756 * returns the index of the inserted item
1758 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
1760 int iItemPos;
1761 LookInInfos *liInfos;
1763 TRACE("\n");
1765 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
1767 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1769 if(iItemPos < 0)
1771 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
1772 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
1775 else
1777 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1778 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
1780 int iRemovedItem;
1782 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
1783 break;
1784 if(iRemovedItem < iItemPos)
1785 iItemPos--;
1789 CBSetCurSel(hwnd,iItemPos);
1790 liInfos->uSelectedItem = iItemPos;
1792 return 0;
1796 /***********************************************************************
1797 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
1799 * Remove the item with an expansion level over iExpansionLevel
1801 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
1803 int iItemPos;
1805 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
1807 TRACE("\n");
1809 if(liInfos->iMaxIndentation <= 2)
1810 return -1;
1812 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
1814 SFOLDER *tmpFolder;
1815 tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
1816 CBDeleteString(hwnd,iItemPos);
1817 liInfos->iMaxIndentation--;
1819 return iItemPos;
1822 return -1;
1825 /***********************************************************************
1826 * FILEDLG95_LOOKIN_SearchItem
1828 * Search for pidl in the lookin combo box
1829 * returns the index of the found item
1831 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
1833 int i = 0;
1834 int iCount = CBGetCount(hwnd);
1836 TRACE("\n");
1838 for(;i<iCount;i++)
1840 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
1842 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
1843 return i;
1844 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
1845 return i;
1849 return -1;
1852 /***********************************************************************
1853 * FILEDLG95_LOOKIN_Clean
1855 * Clean the memory used by the lookin combo box
1857 static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
1859 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1860 int iPos;
1861 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
1863 TRACE("\n");
1865 /* Delete each string of the combo and their associated data */
1866 for(iPos = iCount-1;iPos>=0;iPos--)
1868 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos)));
1869 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
1871 /* LookInInfos structure */
1872 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
1876 * TOOLS
1879 /***********************************************************************
1880 * GetName
1882 * Get the pidl's display name (relative to folder) and
1883 * put it in lpstrFileName.
1885 * Return NOERROR on success,
1886 * E_FAIL otherwise
1889 HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
1891 STRRET str;
1892 HRESULT hRes;
1894 TRACE("%p %p\n", lpsf, pidl);
1896 if(!lpsf)
1898 HRESULT hRes;
1899 COMDLG32_SHGetDesktopFolder(&lpsf);
1900 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
1901 IShellFolder_Release(lpsf);
1902 return hRes;
1905 /* Get the display name of the pidl relative to the folder */
1906 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf,
1907 pidl,
1908 dwFlags,
1909 &str)))
1911 return COMDLG32_StrRetToBufA(&str, pidl,lpstrFileName, MAX_PATH);
1913 return E_FAIL;
1916 /***********************************************************************
1917 * GetShellFolderFromPidl
1919 * pidlRel is the item pidl relative
1920 * Return the IShellFolder of the absolute pidl
1922 IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
1924 IShellFolder *psf = NULL,*psfParent;
1926 TRACE("%p\n", pidlAbs);
1928 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
1930 psf = psfParent;
1931 if(pidlAbs && pidlAbs->mkid.cb)
1933 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
1935 IShellFolder_Release(psfParent);
1936 return psf;
1939 /* return the desktop */
1940 return psfParent;
1942 return NULL;
1945 /***********************************************************************
1946 * GetParentPidl
1948 * Return the LPITEMIDLIST to the parent of the pidl in the list
1950 LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
1952 LPITEMIDLIST pidlParent;
1954 TRACE("%p\n", pidl);
1956 pidlParent = COMDLG32_PIDL_ILClone(pidl);
1957 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
1959 return pidlParent;
1962 /***********************************************************************
1963 * GetPidlFromName
1965 * returns the pidl of the file name relative to folder
1966 * NULL if an error occured
1968 LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName)
1970 LPITEMIDLIST pidl;
1971 ULONG ulEaten;
1972 wchar_t lpwstrDirName[MAX_PATH];
1975 TRACE("sf=%p file=%s\n", psf, lpcstrFileName);
1977 if(!lpcstrFileName)
1978 return NULL;
1980 MultiByteToWideChar(CP_ACP,
1981 MB_PRECOMPOSED,
1982 lpcstrFileName,
1983 -1,
1984 (LPWSTR)lpwstrDirName,
1985 MAX_PATH);
1987 IShellFolder_ParseDisplayName(psf, 0,
1988 NULL,
1989 (LPWSTR)lpwstrDirName,
1990 &ulEaten,
1991 &pidl,
1992 NULL);
1994 return pidl;
1997 /***********************************************************************
1998 * GetFileExtension
2001 BOOL GetFileExtension(IShellFolder *psf,LPITEMIDLIST pidl,LPSTR lpstrFileExtension)
2003 char FileName[MAX_PATH];
2004 int result;
2005 char *pdest;
2006 int ch = '.';
2008 if(SUCCEEDED(GetName(psf,pidl,SHGDN_NORMAL,FileName)))
2010 if(!(pdest = strrchr( FileName, ch )))
2011 return FALSE;
2013 result = pdest - FileName + 1;
2014 strcpy(lpstrFileExtension,&FileName[result]);
2015 return TRUE;
2017 return FALSE;
2021 * Memory allocation methods */
2022 void *MemAlloc(UINT size)
2024 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2027 void MemFree(void *mem)
2029 if(mem)
2031 HeapFree(GetProcessHeap(),0,mem);