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

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

merged with latest wine code

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