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