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