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

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

GetOpenFileNameW fixes

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