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