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