Add PrintSetup dialog and support for hooks and templates.
[wine] / dlls / commdlg / filedlg.c
1 /*
2  * COMMDLG - File Dialogs
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  */
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include "windef.h"
12 #include "winbase.h"
13 #include "wingdi.h"
14 #include "wine/winbase16.h"
15 #include "wine/winuser16.h"
16 #include "ldt.h"
17 #include "heap.h"
18 #include "commdlg.h"
19 #include "dialog.h"
20 #include "dlgs.h"
21 #include "module.h"
22 #include "drive.h"
23 #include "debugtools.h"
24 #include "winproc.h"
25 #include "cderr.h"
26 #include "tweak.h"
27
28 DEFAULT_DEBUG_CHANNEL(commdlg);
29
30 #include "cdlg.h"
31
32 static HICON16 hFolder = 0;
33 static HICON16 hFolder2 = 0;
34 static HICON16 hFloppy = 0;
35 static HICON16 hHDisk = 0;
36 static HICON16 hCDRom = 0;
37 static HICON16 hNet = 0;
38 static int fldrHeight = 0;
39 static int fldrWidth = 0;
40
41 static const char defaultfilter[]=" \0\0";
42 #define OFN_PROP "FILEDLG_OFN_LPARAM"
43
44 /***********************************************************************
45  *
46  * Windows 3.1 OpenFileName/SaveFileName dialog
47  *
48  */
49
50 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
51                                  LPARAM lParam);
52 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
53                                  LPARAM lParam);
54
55 /***********************************************************************
56  *                              FileDlg_Init                    [internal]
57  */
58 static BOOL FileDlg_Init(void)
59 {
60     static BOOL initialized = 0;
61     CURSORICONINFO *fldrInfo;
62     
63     if (!initialized) {
64         if (!hFolder) hFolder = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FOLDER));
65         if (!hFolder2) hFolder2 = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FOLDER2));
66         if (!hFloppy) hFloppy = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FLOPPY));
67         if (!hHDisk) hHDisk = LoadIcon16(0, MAKEINTRESOURCE16(OIC_HDISK));
68         if (!hCDRom) hCDRom = LoadIcon16(0, MAKEINTRESOURCE16(OIC_CDROM));
69         if (!hNet) hNet = LoadIcon16(0, MAKEINTRESOURCE16(OIC_NETWORK));
70         if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
71             hHDisk == 0 || hCDRom == 0 || hNet == 0)
72         {
73             ERR("Error loading icons !\n");
74             return FALSE;
75         }
76         fldrInfo = (CURSORICONINFO *) GlobalLock16( hFolder2 );
77         if (!fldrInfo)
78         {       
79             ERR("Error measuring icons !\n");
80             return FALSE;
81         }
82         fldrHeight = fldrInfo -> nHeight;
83         fldrWidth = fldrInfo -> nWidth;
84         GlobalUnlock16( hFolder2 );
85         initialized = TRUE;
86     }
87     return TRUE;
88 }
89
90 /***********************************************************************
91  *           FileOpenDlgProc [internal]
92  *
93  * FIXME: Convert to real 32-bit message processing
94  */
95 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
96                                       WPARAM wParam, LPARAM lParam)
97 {
98     UINT16 msg16;
99     MSGPARAM16 mp16;
100
101     mp16.lParam = lParam;
102     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
103                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
104         return 0;
105     mp16.lResult = FileOpenDlgProc16( (HWND16)hDlg, msg16, 
106                                       mp16.wParam, mp16.lParam );
107     
108     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
109     return mp16.lResult;
110 }
111
112 /***********************************************************************
113  *           FileSaveDlgProc [internal]
114  *
115  * FIXME: Convert to real 32-bit message processing
116  */
117 static LRESULT WINAPI FileSaveDlgProc(HWND hDlg, UINT msg,
118                                       WPARAM wParam, LPARAM lParam)
119 {
120     UINT16 msg16;
121     MSGPARAM16 mp16;
122
123     mp16.lParam = lParam;
124     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
125                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
126         return 0;
127     mp16.lResult = FileSaveDlgProc16( (HWND16)hDlg, msg16, 
128                                       mp16.wParam, mp16.lParam );
129     
130     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
131     return mp16.lResult;
132 }
133
134 /***********************************************************************
135  *           GetOpenFileName16   (COMMDLG.1)
136  *
137  * Creates a dialog box for the user to select a file to open.
138  *
139  * RETURNS
140  *    TRUE on success: user selected a valid file
141  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
142  *
143  * BUGS
144  *    unknown, there are some FIXME's left.
145  */
146 BOOL16 WINAPI GetOpenFileName16( 
147                                 SEGPTR ofn /* addess of structure with data*/
148                                 )
149 {
150     HINSTANCE hInst;
151     HANDLE hDlgTmpl = 0, hResInfo;
152     BOOL bRet = FALSE, win32Format = FALSE;
153     HWND hwndDialog;
154     LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
155     LPCVOID template;
156     char defaultopen[]="Open File";
157     char *str=0,*str1=0;
158
159     if (!lpofn || !FileDlg_Init()) return FALSE;
160
161     if (lpofn->Flags & OFN_WINE) {
162             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
163             {
164                 if (!(template = LockResource( MapHModuleSL(lpofn->hInstance ))))
165                 {
166                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
167                     return FALSE;
168                 }
169             }
170             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
171             {
172                 if (!(hResInfo = FindResourceA(MapHModuleSL(lpofn->hInstance),
173                                                 PTR_SEG_TO_LIN(lpofn->lpTemplateName), RT_DIALOGA)))
174                 {
175                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
176                     return FALSE;
177                 }
178                 if (!(hDlgTmpl = LoadResource( MapHModuleSL(lpofn->hInstance),
179                                                  hResInfo )) ||
180                     !(template = LockResource( hDlgTmpl )))
181                 {
182                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
183                     return FALSE;
184                 }
185             } else {
186                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "OPEN_FILE", RT_DIALOGA)))
187                 {
188                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
189                     return FALSE;
190                 }
191                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
192                     !(template = LockResource( hDlgTmpl )))
193                 {
194                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
195                     return FALSE;
196                 }
197             }
198             win32Format = TRUE;
199     } else {
200             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
201             {
202                 if (!(template = LockResource16( lpofn->hInstance )))
203                 {
204                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
205                     return FALSE;
206                 }
207             }
208             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
209             {
210                 if (!(hResInfo = FindResource16(lpofn->hInstance,
211                                                 lpofn->lpTemplateName,
212                                                 RT_DIALOG16)))
213                 {
214                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
215                     return FALSE;
216                 }
217                 if (!(hDlgTmpl = LoadResource16( lpofn->hInstance, hResInfo )) ||
218                     !(template = LockResource16( hDlgTmpl )))
219                 {
220                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
221                     return FALSE;
222                 }
223             } else {
224                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "OPEN_FILE", RT_DIALOGA)))
225                 {
226                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
227                     return FALSE;
228                 }
229                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
230                     !(template = LockResource( hDlgTmpl )))
231                 {
232                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
233                     return FALSE;
234                 }
235                 win32Format = TRUE;
236             }
237     }
238
239     hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
240
241     if (!(lpofn->lpstrFilter))
242       {
243        str = SEGPTR_ALLOC(sizeof(defaultfilter));
244        TRACE("Alloc %p default for Filetype in GetOpenFileName\n",str);
245        memcpy(str,defaultfilter,sizeof(defaultfilter));
246        lpofn->lpstrFilter=SEGPTR_GET(str);
247       }
248
249     if (!(lpofn->lpstrTitle))
250       {
251        str1 = SEGPTR_ALLOC(strlen(defaultopen)+1);
252        TRACE("Alloc %p default for Title in GetOpenFileName\n",str1);
253        strcpy(str1,defaultopen);
254        lpofn->lpstrTitle=SEGPTR_GET(str1);
255       }
256
257     /* FIXME: doesn't handle win32 format correctly yet */
258     hwndDialog = DIALOG_CreateIndirect( hInst, template, win32Format,
259                                         lpofn->hwndOwner,
260                                         (DLGPROC16)FileOpenDlgProc,
261                                         ofn, WIN_PROC_32A );
262     if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpofn->hwndOwner );
263
264     if (str1)
265       {
266        TRACE("Freeing %p default for Title in GetOpenFileName\n",str1);
267         SEGPTR_FREE(str1);
268        lpofn->lpstrTitle=0;
269       }
270
271     if (str)
272       {
273        TRACE("Freeing %p default for Filetype in GetOpenFileName\n",str);
274         SEGPTR_FREE(str);
275        lpofn->lpstrFilter=0;
276       }
277
278     if (hDlgTmpl) {
279             if (lpofn->Flags & OFN_WINE)
280                     FreeResource( hDlgTmpl );
281             else
282                     FreeResource16( hDlgTmpl );
283     }
284
285     TRACE("return lpstrFile='%s' !\n", 
286            (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
287     return bRet;
288 }
289
290
291 /***********************************************************************
292  *           GetSaveFileName   (COMMDLG.2)
293  *
294  * Creates a dialog box for the user to select a file to save.
295  *
296  * RETURNS
297  *    TRUE on succes: user enters a valid file
298  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
299  *
300  * BUGS
301  *    unknown. There are some FIXME's left.
302  */
303 BOOL16 WINAPI GetSaveFileName16( 
304                                 SEGPTR ofn /* addess of structure with data*/
305                                 )
306 {
307     HINSTANCE hInst;
308     HANDLE hDlgTmpl = 0;
309     BOOL bRet = FALSE, win32Format = FALSE;
310     LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
311     LPCVOID template;
312     HWND hwndDialog;
313     char defaultsave[]="Save as";
314     char *str =0,*str1=0;
315
316     if (!lpofn || !FileDlg_Init()) return FALSE;
317
318     if (lpofn->Flags & OFN_WINE) {
319             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
320             {
321                 if (!(template = LockResource( MapHModuleSL(lpofn->hInstance ))))
322                 {
323                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
324                     return FALSE;
325                 }
326             }
327             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
328             {
329                 HANDLE hResInfo;
330                 if (!(hResInfo = FindResourceA(MapHModuleSL(lpofn->hInstance),
331                                                  PTR_SEG_TO_LIN(lpofn->lpTemplateName),
332                                                  RT_DIALOGA)))
333                 {
334                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
335                     return FALSE;
336                 }
337                 if (!(hDlgTmpl = LoadResource(MapHModuleSL(lpofn->hInstance),
338                                                 hResInfo)) ||
339                     !(template = LockResource(hDlgTmpl)))
340                 {
341                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
342                     return FALSE;
343                 }
344                 win32Format= TRUE;
345             } else {
346                 HANDLE hResInfo;
347                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "SAVE_FILE", RT_DIALOGA)))
348                 {
349                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
350                     return FALSE;
351                 }
352                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
353                     !(template = LockResource( hDlgTmpl )))
354                 {
355                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
356                     return FALSE;
357                 }
358                 win32Format = TRUE;
359             }
360     } else {
361             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
362             {
363                 if (!(template = LockResource16( lpofn->hInstance )))
364                 {
365                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
366                     return FALSE;
367                 }
368             }
369             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
370             {
371                 HANDLE16 hResInfo;
372                 if (!(hResInfo = FindResource16(lpofn->hInstance,
373                                                 lpofn->lpTemplateName,
374                                                 RT_DIALOG16)))
375                 {
376                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
377                     return FALSE;
378                 }
379                 if (!(hDlgTmpl = LoadResource16( lpofn->hInstance, hResInfo )) ||
380                     !(template = LockResource16( hDlgTmpl )))
381                 {
382                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
383                     return FALSE;
384                 }
385         } else {
386                 HANDLE hResInfo;
387                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "SAVE_FILE", RT_DIALOGA)))
388                 {
389                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
390                     return FALSE;
391                 }
392                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
393                     !(template = LockResource( hDlgTmpl )))
394                 {
395                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
396                     return FALSE;
397                 }
398                 win32Format = TRUE;
399         }
400     }
401
402     hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
403
404     if (!(lpofn->lpstrFilter))
405       {
406        str = SEGPTR_ALLOC(sizeof(defaultfilter));
407        TRACE("Alloc default for Filetype in GetSaveFileName\n");
408        memcpy(str,defaultfilter,sizeof(defaultfilter));
409        lpofn->lpstrFilter=SEGPTR_GET(str);
410       }
411
412     if (!(lpofn->lpstrTitle))
413       {
414        str1 = SEGPTR_ALLOC(sizeof(defaultsave)+1);
415        TRACE("Alloc default for Title in GetSaveFileName\n");
416        strcpy(str1,defaultsave);
417        lpofn->lpstrTitle=SEGPTR_GET(str1);
418       }
419
420     hwndDialog = DIALOG_CreateIndirect( hInst, template, win32Format,
421                                         lpofn->hwndOwner,
422                                         (DLGPROC16)FileSaveDlgProc,
423                                         ofn, WIN_PROC_32A );
424     if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpofn->hwndOwner );
425
426     if (str1)
427       {
428        TRACE("Freeing %p default for Title in GetSaveFileName\n",str1);
429         SEGPTR_FREE(str1);
430        lpofn->lpstrTitle=0;
431       }
432  
433     if (str)
434       {
435        TRACE("Freeing %p default for Filetype in GetSaveFileName\n",str);
436         SEGPTR_FREE(str);
437        lpofn->lpstrFilter=0;
438       }
439     
440     if (hDlgTmpl) {
441             if (lpofn->Flags & OFN_WINE)
442                     FreeResource( hDlgTmpl );
443             else
444                     FreeResource16( hDlgTmpl );
445     }
446
447     TRACE("return lpstrFile='%s' !\n", 
448             (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
449     return bRet;
450 }
451
452 /***********************************************************************
453  *                              FILEDLG_StripEditControl        [internal]
454  * Strip pathnames off the contents of the edit control.
455  */
456 static void FILEDLG_StripEditControl(HWND16 hwnd)
457 {
458     char temp[512], *cp;
459
460     GetDlgItemTextA( hwnd, edt1, temp, sizeof(temp) );
461     cp = strrchr(temp, '\\');
462     if (cp != NULL) {
463         strcpy(temp, cp+1);
464     }
465     cp = strrchr(temp, ':');
466     if (cp != NULL) {
467         strcpy(temp, cp+1);
468     }
469     /* FIXME: shouldn't we do something with the result here? ;-) */
470 }
471
472 /***********************************************************************
473  *                              FILEDLG_ScanDir                 [internal]
474  */
475 static BOOL FILEDLG_ScanDir(HWND16 hWnd, LPSTR newPath)
476 {
477     char                buffer[512];
478          char*                  str = buffer;
479     int                         drive;
480     HWND                hlb;
481
482     lstrcpynA(buffer, newPath, sizeof(buffer));
483
484     if (str[0] && (str[1] == ':')) {
485         drive = toupper(str[0]) - 'A';
486         str += 2;
487         if (!DRIVE_SetCurrentDrive(drive)) 
488                           return FALSE;
489     } else {
490                  drive = DRIVE_GetCurrentDrive();
491          }
492
493     if (str[0] && !DRIVE_Chdir(drive, str)) {
494                  return FALSE;
495     }
496
497     GetDlgItemTextA(hWnd, edt1, buffer, sizeof(buffer));
498     if ((hlb = GetDlgItem(hWnd, lst1)) != 0) {
499                  char*  scptr; /* ptr on semi-colon */
500                  char*  filter = buffer;
501
502                  TRACE("Using filter %s\n", filter);
503                  SendMessageA(hlb, LB_RESETCONTENT, 0, 0);
504                  while (filter) {
505                          scptr = strchr(filter, ';');
506                          if (scptr)     *scptr = 0;
507                          TRACE("Using file spec %s\n", filter);
508                          if (SendMessageA(hlb, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
509                                  return FALSE;
510                          if (scptr) *scptr = ';';
511                          filter = (scptr) ? (scptr + 1) : 0;
512                  }
513          }
514
515     strcpy(buffer, "*.*");
516     return DlgDirListA(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
517 }
518
519 /***********************************************************************
520  *                              FILEDLG_GetFileType             [internal]
521  */
522
523 static LPSTR FILEDLG_GetFileType(LPSTR cfptr, LPSTR fptr, WORD index)
524 {
525   int n, i;
526   i = 0;
527   if (cfptr)
528     for ( ;(n = strlen(cfptr)) != 0; i++) 
529       {
530         cfptr += n + 1;
531         if (i == index)
532           return cfptr;
533         cfptr += strlen(cfptr) + 1;
534       }
535   if (fptr)
536     for ( ;(n = strlen(fptr)) != 0; i++) 
537       {
538         fptr += n + 1;
539         if (i == index)
540           return fptr;
541         fptr += strlen(fptr) + 1;
542     }
543   return "*.*"; /* FIXME */
544 }
545
546 /***********************************************************************
547  *                              FILEDLG_WMDrawItem              [internal]
548  */
549 static LONG FILEDLG_WMDrawItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam,int savedlg)
550 {
551     LPDRAWITEMSTRUCT16 lpdis = (LPDRAWITEMSTRUCT16)PTR_SEG_TO_LIN(lParam);
552     char *str;
553     HICON16 hIcon;
554     COLORREF oldText = 0, oldBk = 0;
555
556     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
557     {
558         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
559         SendMessage16(lpdis->hwndItem, LB_GETTEXT16, lpdis->itemID, 
560                       (LPARAM)SEGPTR_GET(str));
561
562         if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
563         {
564             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
565             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
566         }
567         if (savedlg)
568             SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
569
570         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + 1,
571                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
572                   &(lpdis->rcItem), str, strlen(str), NULL);
573
574         if (lpdis->itemState & ODS_SELECTED)
575             DrawFocusRect16( lpdis->hDC, &(lpdis->rcItem) );
576
577         if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
578         {
579             SetBkColor( lpdis->hDC, oldBk );
580             SetTextColor( lpdis->hDC, oldText );
581         }
582         SEGPTR_FREE(str);
583         return TRUE;
584     }
585
586     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
587     {
588         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
589         SendMessage16(lpdis->hwndItem, LB_GETTEXT16, lpdis->itemID, 
590                       (LPARAM)SEGPTR_GET(str));
591
592         if (lpdis->itemState & ODS_SELECTED)
593         {
594             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
595             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
596         }
597         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
598                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
599                   &(lpdis->rcItem), str, strlen(str), NULL);
600
601         if (lpdis->itemState & ODS_SELECTED)
602             DrawFocusRect16( lpdis->hDC, &(lpdis->rcItem) );
603
604         if (lpdis->itemState & ODS_SELECTED)
605         {
606             SetBkColor( lpdis->hDC, oldBk );
607             SetTextColor( lpdis->hDC, oldText );
608         }
609         DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
610         SEGPTR_FREE(str);
611         return TRUE;
612     }
613     if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
614     {
615         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
616         SendMessage16(lpdis->hwndItem, CB_GETLBTEXT16, lpdis->itemID, 
617                       (LPARAM)SEGPTR_GET(str));
618         switch(DRIVE_GetType( str[2] - 'a' ))
619         {
620         case TYPE_FLOPPY:  hIcon = hFloppy; break;
621         case TYPE_CDROM:   hIcon = hCDRom; break;
622         case TYPE_NETWORK: hIcon = hNet; break;
623         case TYPE_HD:
624         default:           hIcon = hHDisk; break;
625         }
626         if (lpdis->itemState & ODS_SELECTED)
627         {
628             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
629             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
630         }
631         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
632                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
633                   &(lpdis->rcItem), str, strlen(str), NULL);
634
635         if (lpdis->itemState & ODS_SELECTED)
636         {
637             SetBkColor( lpdis->hDC, oldBk );
638             SetTextColor( lpdis->hDC, oldText );
639         }
640         DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
641         SEGPTR_FREE(str);
642         return TRUE;
643     }
644     return FALSE;
645 }
646
647 /***********************************************************************
648  *                              FILEDLG_WMMeasureItem           [internal]
649  */
650 static LONG FILEDLG_WMMeasureItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
651 {
652     LPMEASUREITEMSTRUCT16 lpmeasure;
653     
654     lpmeasure = (LPMEASUREITEMSTRUCT16)PTR_SEG_TO_LIN(lParam);
655     lpmeasure->itemHeight = fldrHeight;
656     return TRUE;
657 }
658
659 /***********************************************************************
660  *                              FILEDLG_HookCallChk             [internal]
661  */
662 static int FILEDLG_HookCallChk(LPOPENFILENAME16 lpofn)
663 {
664  if (lpofn)
665   if (lpofn->Flags & OFN_ENABLEHOOK)
666    if (lpofn->lpfnHook)
667     return 1;
668  return 0;   
669
670
671 /***********************************************************************
672  *                              FILEDLG_CallWindowProc             [internal]
673  *
674  * Adapt the structures back for win32 calls so the callee can read lpCustData
675  */
676 static BOOL FILEDLG_CallWindowProc(LPOPENFILENAME16 lpofn,HWND hwnd,
677         UINT wMsg,WPARAM wParam,LPARAM lParam
678
679 ) {
680         BOOL            needstruct;
681         BOOL          result = FALSE;
682         WINDOWPROCTYPE  ProcType;               /* Type of Hook Function to be called. */
683
684         /* TRUE if lParam points to the OPENFILENAME16 Structure */
685         needstruct = (PTR_SEG_TO_LIN(lParam) == lpofn);
686
687         ProcType   = (lpofn->Flags & OFN_WINE)
688                      ? (lpofn->Flags & OFN_UNICODE)             /* 32-Bit call to GetOpenFileName */
689                        ? WIN_PROC_32W : WIN_PROC_32A
690                      : WIN_PROC_16;                             /* 16-Bit call to GetOpenFileName */
691
692         if (!(lpofn->Flags & OFN_WINE))
693                 /* Call to 16-Bit Hooking function... No Problem at all. */
694                 return (BOOL)CallWindowProc16(
695                         (WNDPROC16)lpofn->lpfnHook,hwnd,(UINT16)wMsg,(WPARAM16)wParam,lParam
696                 );
697         /* |OFN_WINE32 */
698         if (needstruct)
699         {
700            /* Parameter lParam points to lpofn... Convert Structure Data... */
701            if (lpofn->Flags & OFN_UNICODE)
702            {
703                 OPENFILENAMEW ofnw;
704
705                 /* FIXME: probably needs more converted */
706                 ofnw.lCustData = lpofn->lCustData;
707                 return (BOOL)CallWindowProcW(
708                          (WNDPROC)lpofn->lpfnHook,hwnd,wMsg,wParam,(LPARAM)&ofnw
709                 );
710            }
711            else /* ! |OFN_UNICODE */
712            {
713                 OPENFILENAMEA ofna;
714
715                 /* FIXME: probably needs more converted */
716                 ofna.lCustData = lpofn->lCustData;
717                 return (BOOL)CallWindowProcA(
718                         (WNDPROC)lpofn->lpfnHook,hwnd,wMsg,wParam,(LPARAM)&ofna
719                 );
720            }
721         }
722         else /* ! needstruct */
723         {
724                 HWINDOWPROC     hWindowProc=NULL;
725
726                 if (WINPROC_SetProc(&hWindowProc, (WNDPROC16)lpofn->lpfnHook, ProcType, WIN_PROC_WINDOW))
727                 {
728                     /* Call Window Procedure converting 16-Bit Type Parameters to 32-Bit Type Parameters */
729                     result = CallWindowProc16( (WNDPROC16)hWindowProc,
730                                                       hwnd, wMsg, wParam, lParam );
731
732                     result = LOWORD(result);
733
734                     WINPROC_FreeProc( hWindowProc, WIN_PROC_WINDOW );
735                 }
736
737                 return result;
738
739         }
740 }
741
742
743 /***********************************************************************
744  *                              FILEDLG_WMInitDialog            [internal]
745  */
746
747 static LONG FILEDLG_WMInitDialog(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
748 {
749   int i, n;
750   LPOPENFILENAME16 lpofn;
751   char tmpstr[512];
752   LPSTR pstr, old_pstr;
753   SetPropA(hWnd,OFN_PROP,lParam);
754   lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(lParam);
755   if (lpofn->lpstrTitle) SetWindowText16( hWnd, lpofn->lpstrTitle );
756   /* read custom filter information */
757   if (lpofn->lpstrCustomFilter)
758     {
759       pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter);
760       n = 0;
761       TRACE("lpstrCustomFilter = %p\n", pstr);
762       while(*pstr)
763         {
764           old_pstr = pstr;
765           i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING16, 0,
766                                    (LPARAM)lpofn->lpstrCustomFilter + n );
767           n += strlen(pstr) + 1;
768           pstr += strlen(pstr) + 1;
769           TRACE("add str='%s' "
770                           "associated to '%s'\n", old_pstr, pstr);
771           SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA16, i, (LPARAM)pstr);
772           n += strlen(pstr) + 1;
773           pstr += strlen(pstr) + 1;
774         }
775     }
776   /* read filter information */
777   if (lpofn->lpstrFilter) {
778         pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
779         n = 0;
780         while(*pstr) {
781           old_pstr = pstr;
782           i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING16, 0,
783                                        (LPARAM)lpofn->lpstrFilter + n );
784           n += strlen(pstr) + 1;
785           pstr += strlen(pstr) + 1;
786           TRACE("add str='%s' "
787                           "associated to '%s'\n", old_pstr, pstr);
788           SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA16, i, (LPARAM)pstr);
789           n += strlen(pstr) + 1;
790           pstr += strlen(pstr) + 1;
791         }
792   }
793   /* set default filter */
794   if (lpofn->nFilterIndex == 0 && lpofn->lpstrCustomFilter == (SEGPTR)NULL)
795         lpofn->nFilterIndex = 1;
796   SendDlgItemMessage16(hWnd, cmb1, CB_SETCURSEL16, lpofn->nFilterIndex - 1, 0);    
797   lstrcpynA(tmpstr, FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter),
798              PTR_SEG_TO_LIN(lpofn->lpstrFilter), lpofn->nFilterIndex - 1),512);
799   TRACE("nFilterIndex = %ld, SetText of edt1 to '%s'\n", 
800                         lpofn->nFilterIndex, tmpstr);
801   SetDlgItemTextA( hWnd, edt1, tmpstr );
802   /* get drive list */
803   *tmpstr = 0;
804   DlgDirListComboBoxA(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
805   /* read initial directory */
806   if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) 
807     {
808       int len;
809       lstrcpynA(tmpstr, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir), 511);
810       len=strlen(tmpstr);
811       if (len > 0 && tmpstr[len-1] != '\\'  && tmpstr[len-1] != ':') {
812         tmpstr[len]='\\';
813         tmpstr[len+1]='\0';
814       }
815     }
816   else
817     *tmpstr = 0;
818   if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
819     *tmpstr = 0;
820     if (!FILEDLG_ScanDir(hWnd, tmpstr))
821       WARN("Couldn't read initial directory %s!\n",tmpstr);
822   }
823   /* select current drive in combo 2, omit missing drives */
824   for(i=0, n=-1; i<=DRIVE_GetCurrentDrive(); i++)
825     if (DRIVE_IsValid(i))                  n++;
826   SendDlgItemMessage16(hWnd, cmb2, CB_SETCURSEL16, n, 0);
827   if (!(lpofn->Flags & OFN_SHOWHELP))
828     ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
829   if (lpofn->Flags & OFN_HIDEREADONLY)
830     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
831   if (FILEDLG_HookCallChk(lpofn))
832      return (BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,WM_INITDIALOG,wParam,lParam );
833   else  
834      return TRUE;
835 }
836
837 /***********************************************************************
838  *                              FILEDLG_WMCommand               [internal]
839  */
840 BOOL in_update=FALSE;
841
842 static LRESULT FILEDLG_WMCommand(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
843 {
844   LONG lRet;
845   LPOPENFILENAME16 lpofn;
846   OPENFILENAME16 ofn2;
847   char tmpstr[512], tmpstr2[512];
848   LPSTR pstr, pstr2;
849   UINT16 control,notification;
850
851   /* Notifications are packaged differently in Win32 */
852   control = wParam;
853   notification = HIWORD(lParam);
854     
855   lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
856   switch (control)
857     {
858     case lst1: /* file list */
859       FILEDLG_StripEditControl(hWnd);
860       if (notification == LBN_DBLCLK)
861         goto almost_ok;
862       lRet = SendDlgItemMessage16(hWnd, lst1, LB_GETCURSEL16, 0, 0);
863       if (lRet == LB_ERR) return TRUE;
864       if ((pstr = SEGPTR_ALLOC(512)))
865       {
866           SendDlgItemMessage16(hWnd, lst1, LB_GETTEXT16, lRet,
867                                (LPARAM)SEGPTR_GET(pstr));
868           SetDlgItemTextA( hWnd, edt1, pstr );
869           SEGPTR_FREE(pstr);
870       }
871       if (FILEDLG_HookCallChk(lpofn))
872        FILEDLG_CallWindowProc(lpofn,hWnd,
873                   RegisterWindowMessageA( LBSELCHSTRING ),
874                   control, MAKELONG(lRet,CD_LBSELCHANGE));       
875       /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD, CD_LBSELNOITEMS */                  
876       return TRUE;
877     case lst2: /* directory list */
878       FILEDLG_StripEditControl(hWnd);
879       if (notification == LBN_DBLCLK)
880         {
881           lRet = SendDlgItemMessage16(hWnd, lst2, LB_GETCURSEL16, 0, 0);
882           if (lRet == LB_ERR) return TRUE;
883           pstr = SEGPTR_ALLOC(512);
884           SendDlgItemMessage16(hWnd, lst2, LB_GETTEXT16, lRet,
885                              (LPARAM)SEGPTR_GET(pstr));
886           strcpy( tmpstr, pstr );
887           SEGPTR_FREE(pstr);
888           if (tmpstr[0] == '[')
889             {
890               tmpstr[strlen(tmpstr) - 1] = 0;
891               strcpy(tmpstr,tmpstr+1);
892             }
893           strcat(tmpstr, "\\");
894           goto reset_scan;
895         }
896       return TRUE;
897     case cmb1: /* file type drop list */
898       if (notification == CBN_SELCHANGE) 
899         {
900           *tmpstr = 0;
901           goto reset_scan;
902         }
903       return TRUE;
904     case chx1:
905       return TRUE;
906     case pshHelp:
907       return TRUE;
908     case cmb2: /* disk drop list */
909       FILEDLG_StripEditControl(hWnd);
910       lRet = SendDlgItemMessage16(hWnd, cmb2, CB_GETCURSEL16, 0, 0L);
911       if (lRet == LB_ERR) return 0;
912       pstr = SEGPTR_ALLOC(512);
913       SendDlgItemMessage16(hWnd, cmb2, CB_GETLBTEXT16, lRet,
914                            (LPARAM)SEGPTR_GET(pstr));
915       sprintf(tmpstr, "%c:", pstr[2]);
916       SEGPTR_FREE(pstr);
917       if (notification != CBN_SELCHANGE) return TRUE;
918     reset_scan:
919       lRet = SendDlgItemMessage16(hWnd, cmb1, CB_GETCURSEL16, 0, 0);
920       if (lRet == LB_ERR)
921         return TRUE;
922       pstr = (LPSTR)SendDlgItemMessage16(hWnd, cmb1, CB_GETITEMDATA16, lRet, 0);
923       TRACE("Selected filter : %s\n", pstr);
924       SetDlgItemTextA( hWnd, edt1, pstr );
925       FILEDLG_ScanDir(hWnd, tmpstr);
926       in_update=TRUE;
927     case IDOK:
928     almost_ok:
929       ofn2=*lpofn; /* for later restoring */
930       GetDlgItemTextA( hWnd, edt1, tmpstr, sizeof(tmpstr) );
931       pstr = strrchr(tmpstr, '\\');
932       if (pstr == NULL)
933         pstr = strrchr(tmpstr, ':');
934       if (strchr(tmpstr,'*') != NULL || strchr(tmpstr,'?') != NULL)
935         {
936           /* edit control contains wildcards */
937           if (pstr != NULL)
938             {
939               lstrcpynA(tmpstr2, pstr+1, 512);
940               *(pstr+1) = 0;
941             }
942           else
943             {
944               strcpy(tmpstr2, tmpstr);
945               *tmpstr=0;
946             }
947           TRACE("tmpstr=%s, tmpstr2=%s\n", tmpstr, tmpstr2);
948           SetDlgItemTextA( hWnd, edt1, tmpstr2 );
949           FILEDLG_ScanDir(hWnd, tmpstr);
950           return TRUE;
951         }
952       /* no wildcards, we might have a directory or a filename */
953       /* try appending a wildcard and reading the directory */
954       pstr2 = tmpstr + strlen(tmpstr);
955       if (pstr == NULL || *(pstr+1) != 0)
956         strcat(tmpstr, "\\");
957       lRet = SendDlgItemMessage16(hWnd, cmb1, CB_GETCURSEL16, 0, 0);
958       if (lRet == LB_ERR) return TRUE;
959       lpofn->nFilterIndex = lRet + 1;
960       TRACE("lpofn->nFilterIndex=%ld\n", lpofn->nFilterIndex);
961       lstrcpynA(tmpstr2, 
962              FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter),
963                                  PTR_SEG_TO_LIN(lpofn->lpstrFilter),
964                                  lRet), sizeof(tmpstr2));
965       SetDlgItemTextA( hWnd, edt1, tmpstr2 );
966       if (!in_update)
967       /* if ScanDir succeeds, we have changed the directory */
968       if (FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
969       /* if not, this must be a filename */
970       *pstr2 = 0;
971       if (pstr != NULL)
972         {
973           /* strip off the pathname */
974           *pstr = 0;
975           SetDlgItemTextA( hWnd, edt1, pstr + 1 );
976           lstrcpynA(tmpstr2, pstr+1, sizeof(tmpstr2) );
977           /* Should we MessageBox() if this fails? */
978           if (!FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
979           strcpy(tmpstr, tmpstr2);
980         }
981       else SetDlgItemTextA( hWnd, edt1, tmpstr );
982 #if 0
983       ShowWindow16(hWnd, SW_HIDE);   /* this should not be necessary ?! (%%%) */
984 #endif
985       {
986         int lenstr2;
987         int drive = DRIVE_GetCurrentDrive();
988         tmpstr2[0] = 'A'+ drive;
989         tmpstr2[1] = ':';
990         tmpstr2[2] = '\\';
991         lstrcpynA(tmpstr2 + 3, DRIVE_GetDosCwd(drive), 507);
992         lenstr2=strlen(tmpstr2);
993         if (lenstr2 > 3)
994            tmpstr2[lenstr2++]='\\';
995         lstrcpynA(tmpstr2+lenstr2, tmpstr, 512-lenstr2);
996         if (lpofn->lpstrFile)
997           lstrcpynA(PTR_SEG_TO_LIN(lpofn->lpstrFile), tmpstr2,lpofn->nMaxFile);
998       }
999       lpofn->nFileOffset = strrchr(tmpstr2,'\\') - tmpstr2 +1;
1000       lpofn->nFileExtension = 0;
1001       while(tmpstr2[lpofn->nFileExtension] != '.' && tmpstr2[lpofn->nFileExtension] != '\0')
1002         lpofn->nFileExtension++;
1003       if (tmpstr2[lpofn->nFileExtension] == '\0')
1004         lpofn->nFileExtension = 0;
1005       else
1006         lpofn->nFileExtension++;
1007
1008       if(in_update)
1009        {
1010          if (FILEDLG_HookCallChk(lpofn))
1011            FILEDLG_CallWindowProc(lpofn,hWnd,
1012                                   RegisterWindowMessageA( LBSELCHSTRING ),
1013                                   control, MAKELONG(lRet,CD_LBSELCHANGE));
1014
1015          in_update = FALSE;
1016          return TRUE;
1017        }
1018       if (PTR_SEG_TO_LIN(lpofn->lpstrFileTitle) != NULL) 
1019         {
1020           lRet = SendDlgItemMessage16(hWnd, lst1, LB_GETCURSEL16, 0, 0);
1021           SendDlgItemMessage16(hWnd, lst1, LB_GETTEXT16, lRet,
1022                                lpofn->lpstrFileTitle );
1023         }
1024       if (FILEDLG_HookCallChk(lpofn))
1025       {
1026        lRet= (BOOL16)FILEDLG_CallWindowProc(lpofn,
1027                hWnd, RegisterWindowMessageA( FILEOKSTRING ), 0, lParam );
1028        if (lRet)       
1029        {
1030          *lpofn=ofn2; /* restore old state */
1031 #if 0
1032          ShowWindow16(hWnd, SW_SHOW);               /* only if above (%%%) SW_HIDE used */
1033 #endif         
1034          break;
1035        }
1036       }
1037       if ((lpofn->Flags & OFN_ALLOWMULTISELECT) && (lpofn->Flags & OFN_EXPLORER)) {
1038          if (lpofn->lpstrFile) {
1039             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile);
1040             LPSTR ptr = strrchr(str, '\\');
1041             str[strlen(str) + 1] = '\0';
1042             *ptr = 0;
1043          }
1044       }
1045       EndDialog(hWnd, TRUE);
1046       return TRUE;
1047     case IDCANCEL:
1048       EndDialog(hWnd, FALSE);
1049       return TRUE;
1050     }
1051   return FALSE;
1052 }
1053
1054 /***********************************************************************
1055  *           FileOpenDlgProc16   (COMMDLG.6)
1056  */
1057 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1058                                LPARAM lParam)
1059 {  
1060  LPOPENFILENAME16 lpofn =(LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
1061  
1062  if (wMsg!=WM_INITDIALOG)
1063   if (FILEDLG_HookCallChk(lpofn))
1064   {
1065    LRESULT  lRet=(BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,wMsg,wParam,lParam);
1066    if (lRet)   
1067     return lRet;         /* else continue message processing */
1068   }             
1069   switch (wMsg)
1070     {
1071     case WM_INITDIALOG:
1072       return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1073     case WM_MEASUREITEM:
1074       return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1075     case WM_DRAWITEM:
1076       return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE);
1077     case WM_COMMAND:
1078       return FILEDLG_WMCommand(hWnd, wParam, lParam);
1079 #if 0
1080     case WM_CTLCOLOR:
1081       SetBkColor((HDC16)wParam, 0x00C0C0C0);
1082       switch (HIWORD(lParam))
1083         {
1084         case CTLCOLOR_BTN:
1085           SetTextColor((HDC16)wParam, 0x00000000);
1086           return hGRAYBrush;
1087         case CTLCOLOR_STATIC:
1088           SetTextColor((HDC16)wParam, 0x00000000);
1089           return hGRAYBrush;
1090         }
1091       break;
1092 #endif
1093     }
1094   return FALSE;
1095 }
1096
1097 /***********************************************************************
1098  *           FileSaveDlgProc16   (COMMDLG.7)
1099  */
1100 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1101                                LPARAM lParam)
1102 {
1103  LPOPENFILENAME16 lpofn =(LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
1104  
1105  if (wMsg!=WM_INITDIALOG)
1106   if (FILEDLG_HookCallChk(lpofn))
1107   {
1108    LRESULT  lRet=(BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,wMsg,wParam,lParam);
1109    if (lRet)   
1110     return lRet;         /* else continue message processing */
1111   }             
1112   switch (wMsg) {
1113    case WM_INITDIALOG:
1114       return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1115       
1116    case WM_MEASUREITEM:
1117       return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1118     
1119    case WM_DRAWITEM:
1120       return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE);
1121
1122    case WM_COMMAND:
1123       return FILEDLG_WMCommand(hWnd, wParam, lParam);
1124   }
1125   
1126   /*
1127   case WM_CTLCOLOR:
1128    SetBkColor((HDC16)wParam, 0x00C0C0C0);
1129    switch (HIWORD(lParam))
1130    {
1131     case CTLCOLOR_BTN:
1132      SetTextColor((HDC16)wParam, 0x00000000);
1133      return hGRAYBrush;
1134     case CTLCOLOR_STATIC:
1135      SetTextColor((HDC16)wParam, 0x00000000);
1136      return hGRAYBrush;
1137    }
1138    return FALSE;
1139    
1140    */
1141   return FALSE;
1142 }
1143
1144 static BOOL Commdlg_GetFileNameA( BOOL16 (CALLBACK *dofunction)(SEGPTR x),
1145                                       LPOPENFILENAMEA ofn )
1146 {
1147         BOOL16 ret;
1148         LPOPENFILENAME16 ofn16 = SEGPTR_ALLOC(sizeof(OPENFILENAME16));
1149
1150         memset(ofn16,'\0',sizeof(*ofn16));
1151         ofn16->lStructSize = sizeof(*ofn16);
1152         ofn16->hwndOwner = ofn->hwndOwner;
1153         ofn16->hInstance = MapHModuleLS(ofn->hInstance);
1154         if (ofn->lpstrFilter) {
1155                 LPSTR   s,x;
1156
1157                 /* filter is a list...  title\0ext\0......\0\0 */
1158                 s = (LPSTR)ofn->lpstrFilter;
1159                 while (*s)
1160                         s = s+strlen(s)+1;
1161                 s++;
1162                 x = (LPSTR)SEGPTR_ALLOC(s-ofn->lpstrFilter);
1163                 memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
1164                 ofn16->lpstrFilter = SEGPTR_GET(x);
1165         }
1166         if (ofn->lpstrCustomFilter) {
1167                 LPSTR   s,x;
1168
1169                 /* filter is a list...  title\0ext\0......\0\0 */
1170                 s = (LPSTR)ofn->lpstrCustomFilter;
1171                 while (*s)
1172                         s = s+strlen(s)+1;
1173                 s++;
1174                 x = SEGPTR_ALLOC(s-ofn->lpstrCustomFilter);
1175                 memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
1176                 ofn16->lpstrCustomFilter = SEGPTR_GET(x);
1177         }
1178         ofn16->nMaxCustFilter = ofn->nMaxCustFilter;
1179         ofn16->nFilterIndex = ofn->nFilterIndex;
1180         if (ofn->nMaxFile)
1181             ofn16->lpstrFile = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFile));
1182         ofn16->nMaxFile = ofn->nMaxFile;
1183         ofn16->nMaxFileTitle = ofn->nMaxFileTitle;
1184         if (ofn16->nMaxFileTitle)
1185             ofn16->lpstrFileTitle = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFileTitle));
1186         if (ofn->lpstrInitialDir)
1187             ofn16->lpstrInitialDir = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrInitialDir));
1188         if (ofn->lpstrTitle)
1189             ofn16->lpstrTitle = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrTitle));
1190         ofn16->Flags = ofn->Flags|OFN_WINE;
1191         ofn16->nFileOffset = ofn->nFileOffset;
1192         ofn16->nFileExtension = ofn->nFileExtension;
1193         if (ofn->lpstrDefExt)
1194             ofn16->lpstrDefExt = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrDefExt));
1195         ofn16->lCustData = ofn->lCustData;
1196         ofn16->lpfnHook = (LPOFNHOOKPROC16)ofn->lpfnHook;
1197
1198         if (ofn->lpTemplateName)
1199             ofn16->lpTemplateName = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpTemplateName));
1200
1201         ret = dofunction(SEGPTR_GET(ofn16));
1202
1203         ofn->nFileOffset = ofn16->nFileOffset;
1204         ofn->nFileExtension = ofn16->nFileExtension;
1205         if (ofn16->lpstrFilter)
1206             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFilter));
1207         if (ofn16->lpTemplateName)
1208             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpTemplateName));
1209         if (ofn16->lpstrDefExt)
1210             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrDefExt));
1211         if (ofn16->lpstrTitle)
1212             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrTitle));
1213         if (ofn16->lpstrInitialDir)
1214             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrInitialDir));
1215         if (ofn16->lpstrCustomFilter)
1216             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrCustomFilter));
1217
1218         if (ofn16->lpstrFile) 
1219           {
1220             LPCSTR      src = PTR_SEG_TO_LIN(ofn16->lpstrFile);
1221             LPSTR       dst = ofn->lpstrFile;
1222
1223             if ((ofn->Flags & OFN_ALLOWMULTISELECT) && (ofn->Flags & OFN_EXPLORER)) {
1224                /* FIXME(EPP): I tried to use:
1225                 * memcpy(ofn->lpstrFile, PTR_SEG_TO_LIN(ofn16->lpstrFile, ofn->nMaxFile)
1226                 * but it did crash with winamp 2.21, so copy string by string
1227                 */
1228                int      len;
1229                do {
1230                   strcpy(dst, src);
1231                   len = strlen(dst) + 1;        /* strlen(dst) == strlen(src) */
1232                   dst += len;
1233                   src += len;
1234                } while (len > 1);
1235             } else {
1236                strcpy(dst, src);
1237             }
1238             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFile));
1239           }
1240
1241         if (ofn16->lpstrFileTitle) 
1242           {
1243             if (ofn->lpstrFileTitle)
1244                 strcpy(ofn->lpstrFileTitle,
1245                         PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1246             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1247           }
1248         SEGPTR_FREE(ofn16);
1249         return ret;
1250 }
1251
1252 static BOOL Commdlg_GetFileNameW( BOOL16 (CALLBACK *dofunction)(SEGPTR x), 
1253                                       LPOPENFILENAMEW ofn )
1254 {
1255         BOOL16 ret;
1256         LPOPENFILENAME16 ofn16 = SEGPTR_ALLOC(sizeof(OPENFILENAME16));
1257
1258         memset(ofn16,'\0',sizeof(*ofn16));
1259         ofn16->lStructSize = sizeof(*ofn16);
1260         ofn16->hwndOwner = ofn->hwndOwner;
1261         ofn16->hInstance = MapHModuleLS(ofn->hInstance);
1262         if (ofn->lpstrFilter) {
1263                 LPWSTR  s;
1264                 LPSTR   x,y;
1265                 int     n;
1266
1267                 /* filter is a list...  title\0ext\0......\0\0 */
1268                 s = (LPWSTR)ofn->lpstrFilter;
1269                 while (*s)
1270                         s = s+lstrlenW(s)+1;
1271                 s++;
1272                 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
1273                 x = y = (LPSTR)SEGPTR_ALLOC(n);
1274                 s = (LPWSTR)ofn->lpstrFilter;
1275                 while (*s) {
1276                         lstrcpyWtoA(x,s);
1277                         x+=lstrlenA(x)+1;
1278                         s+=lstrlenW(s)+1;
1279                 }
1280                 *x=0;
1281                 ofn16->lpstrFilter = SEGPTR_GET(y);
1282 }
1283         if (ofn->lpstrCustomFilter) {
1284                 LPWSTR  s;
1285                 LPSTR   x,y;
1286                 int     n;
1287
1288                 /* filter is a list...  title\0ext\0......\0\0 */
1289                 s = (LPWSTR)ofn->lpstrCustomFilter;
1290                 while (*s)
1291                         s = s+lstrlenW(s)+1;
1292                 s++;
1293                 n = s - ofn->lpstrCustomFilter;
1294                 x = y = (LPSTR)SEGPTR_ALLOC(n);
1295                 s = (LPWSTR)ofn->lpstrCustomFilter;
1296                 while (*s) {
1297                         lstrcpyWtoA(x,s);
1298                         x+=lstrlenA(x)+1;
1299                         s+=lstrlenW(s)+1;
1300                 }
1301                 *x=0;
1302                 ofn16->lpstrCustomFilter = SEGPTR_GET(y);
1303         }
1304         ofn16->nMaxCustFilter = ofn->nMaxCustFilter;
1305         ofn16->nFilterIndex = ofn->nFilterIndex;
1306         if (ofn->nMaxFile) 
1307            ofn16->lpstrFile = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFile));
1308         ofn16->nMaxFile = ofn->nMaxFile;
1309         ofn16->nMaxFileTitle = ofn->nMaxFileTitle;
1310         if (ofn->nMaxFileTitle)
1311                 ofn16->lpstrFileTitle = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFileTitle));
1312         if (ofn->lpstrInitialDir)
1313                 ofn16->lpstrInitialDir = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrInitialDir));
1314         if (ofn->lpstrTitle)
1315                 ofn16->lpstrTitle = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrTitle));
1316         ofn16->Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
1317         ofn16->nFileOffset = ofn->nFileOffset;
1318         ofn16->nFileExtension = ofn->nFileExtension;
1319         if (ofn->lpstrDefExt)
1320                 ofn16->lpstrDefExt = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrDefExt));
1321         ofn16->lCustData = ofn->lCustData;
1322         ofn16->lpfnHook = (LPOFNHOOKPROC16)ofn->lpfnHook;
1323         if (ofn->lpTemplateName) 
1324                 ofn16->lpTemplateName = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpTemplateName));
1325         ret = dofunction(SEGPTR_GET(ofn16));
1326
1327         ofn->nFileOffset = ofn16->nFileOffset;
1328         ofn->nFileExtension = ofn16->nFileExtension;
1329         if (ofn16->lpstrFilter)
1330                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFilter));
1331         if (ofn16->lpTemplateName)
1332                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpTemplateName));
1333         if (ofn16->lpstrDefExt)
1334                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrDefExt));
1335         if (ofn16->lpstrTitle)
1336                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrTitle));
1337         if (ofn16->lpstrInitialDir)
1338                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrInitialDir));
1339         if (ofn16->lpstrCustomFilter)
1340                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrCustomFilter));
1341
1342         if (ofn16->lpstrFile)
1343           {
1344             LPCSTR      src = PTR_SEG_TO_LIN(ofn16->lpstrFile);
1345             LPWSTR      dst = ofn->lpstrFile;
1346
1347             if ((ofn->Flags & OFN_ALLOWMULTISELECT) && (ofn->Flags & OFN_EXPLORER)) {
1348                int      len;
1349                do {
1350                   lstrcpyAtoW(dst, src);
1351                   dst += lstrlenW(dst) + 1;
1352                   src += (len = strlen(src) + 1);
1353                } while (len > 1);
1354             } else {
1355                lstrcpyAtoW(ofn->lpstrFile,PTR_SEG_TO_LIN(ofn16->lpstrFile));
1356             }
1357             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFile));
1358           }
1359
1360         if (ofn16->lpstrFileTitle) {
1361             if (ofn->lpstrFileTitle)
1362                 lstrcpyAtoW(ofn->lpstrFileTitle,
1363                         PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1364             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1365         }
1366         SEGPTR_FREE(ofn16);
1367         return ret;
1368 }
1369 /***********************************************************************
1370  *            GetOpenFileNameA  (COMDLG32.10)
1371  *
1372  * Creates a dialog box for the user to select a file to open.
1373  *
1374  * RETURNS
1375  *    TRUE on succes: user enters a valid file
1376  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1377  *
1378  */
1379 BOOL WINAPI GetOpenFileNameA(
1380         LPOPENFILENAMEA ofn) /* address of init structure */
1381 {
1382     BOOL  newlook;
1383     
1384     /* some flags don't allow to match the TWEAK_WineLook */
1385     if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1386     {
1387       newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1388     }
1389     else
1390     {
1391       /* no special flags set, we can match the TWEAK_WineLook */
1392       newlook = (TWEAK_WineLook>WIN31_LOOK) ? TRUE : FALSE;
1393     }
1394
1395     if (newlook)
1396     {
1397         return GetFileDialog95A(ofn, OPEN_DIALOG);
1398     }
1399     else
1400     {
1401        BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetOpenFileName16;
1402        return Commdlg_GetFileNameA(dofunction,ofn);
1403     }
1404 }
1405
1406 /***********************************************************************
1407  *            GetOpenFileNameW (COMDLG32.11)
1408  *
1409  * Creates a dialog box for the user to select a file to open.
1410  *
1411  * RETURNS
1412  *    TRUE on succes: user enters a valid file
1413  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1414  *
1415  */
1416 BOOL WINAPI GetOpenFileNameW(
1417         LPOPENFILENAMEW ofn) /* address of init structure */
1418 {
1419     BOOL  newlook;
1420     
1421     /* some flags don't allow to match the TWEAK_WineLook */
1422     if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1423     {
1424       newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1425     }
1426     else
1427     {
1428       /* no special flags set, we can match the TWEAK_WineLook */
1429       newlook = (TWEAK_WineLook>WIN31_LOOK) ? TRUE : FALSE;
1430     }
1431
1432     if (newlook)
1433     {
1434         return GetFileDialog95W(ofn, OPEN_DIALOG);
1435     }
1436     else
1437     {
1438        BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetOpenFileName16;
1439        return Commdlg_GetFileNameW(dofunction,ofn);
1440     }
1441 }
1442
1443 /***********************************************************************
1444  *            GetSaveFileNameA  (COMDLG32.12)
1445  *
1446  * Creates a dialog box for the user to select a file to save.
1447  *
1448  * RETURNS
1449  *    TRUE on succes: user enters a valid file
1450  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1451  *
1452  */
1453 BOOL WINAPI GetSaveFileNameA(
1454         LPOPENFILENAMEA ofn) /* address of init structure */
1455 {
1456     BOOL  newlook;
1457     
1458     /* some flags don't allow to match the TWEAK_WineLook */
1459     if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1460     {
1461       newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1462     }
1463     else
1464     {
1465       /* no special flags set, we can match the TWEAK_WineLook */
1466       newlook = (TWEAK_WineLook>WIN31_LOOK) ? TRUE : FALSE;
1467     }
1468
1469     if (newlook)
1470     {
1471         return GetFileDialog95A(ofn, SAVE_DIALOG);
1472     } 
1473     else
1474     {
1475         BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetSaveFileName16;
1476         return Commdlg_GetFileNameA(dofunction,ofn);
1477     }
1478 }
1479
1480 /***********************************************************************
1481  *            GetSaveFileNameW  (COMDLG32.13)
1482  *
1483  * Creates a dialog box for the user to select a file to save.
1484  *
1485  * RETURNS
1486  *    TRUE on succes: user enters a valid file
1487  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1488  *
1489  */
1490 BOOL WINAPI GetSaveFileNameW(
1491         LPOPENFILENAMEW ofn) /* address of init structure */
1492 {
1493     BOOL  newlook;
1494     
1495     /* some flags don't allow to match the TWEAK_WineLook */
1496     if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1497     {
1498       newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1499     }
1500     else
1501     {
1502       /* no special flags set, we can match the TWEAK_WineLook */
1503       newlook = (TWEAK_WineLook>WIN31_LOOK) ? TRUE : FALSE;
1504     }
1505
1506     if (newlook)
1507     {
1508         return GetFileDialog95W(ofn, SAVE_DIALOG);
1509     } 
1510     else
1511     {
1512         BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetSaveFileName16;
1513         return Commdlg_GetFileNameW(dofunction,ofn);
1514     }
1515 }