More splitting of the Win16/32 internal filedlgproc window procedures
[wine] / dlls / commdlg / filedlg16.c
1 /*
2  * COMMDLG - File Dialogs
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include "windef.h"
26 #include "winnls.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "wine/winbase16.h"
30 #include "wine/winuser16.h"
31 #include "wine/unicode.h"
32 #include "commdlg.h"
33 #include "wine/debug.h"
34 #include "cderr.h"
35 #include "winternl.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
38
39 #include "cdlg.h"
40 #include "filedlg.h"
41
42 /***********************************************************************
43  *                              FILEDLG_CallWindowProc16          [internal]
44  *
45  *      Call the appropriate hook
46  */
47 static BOOL FILEDLG_CallWindowProc16(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
48                                    LPARAM lParam)
49 {
50     if (lfs->ofn16)
51     {
52         return (BOOL16) CallWindowProc16(
53           (WNDPROC16)lfs->ofn16->lpfnHook, HWND_16(lfs->hwnd),
54           (UINT16)wMsg, (WPARAM16)wParam, lParam);
55     }
56     return FALSE;
57 }
58
59 /***********************************************************************
60  *                              FILEDLG_WMInitDialog16            [internal]
61  *      The is a duplicate of the 32bit FILEDLG_WMInitDialog function 
62  *      The only differnce is that it calls FILEDLG_CallWindowProc16 
63  *      for a 16 bit Window Proc.
64  */
65
66 static LONG FILEDLG_WMInitDialog16(HWND hWnd, WPARAM wParam, LPARAM lParam)
67 {
68   int i, n;
69   WCHAR tmpstr[BUFFILE];
70   LPWSTR pstr, old_pstr;
71   LPOPENFILENAMEW ofn;
72   LFSPRIVATE lfs = (LFSPRIVATE) lParam;
73
74   if (!lfs) return FALSE;
75   SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
76   lfs->hwnd = hWnd;
77   ofn = lfs->ofnW;
78
79   TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
80
81   SetWindowTextW( hWnd, ofn->lpstrTitle );
82   /* read custom filter information */
83   if (ofn->lpstrCustomFilter)
84     {
85       pstr = ofn->lpstrCustomFilter;
86       n = 0;
87       TRACE("lpstrCustomFilter = %p\n", pstr);
88       while(*pstr)
89         {
90           old_pstr = pstr;
91           i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
92                                    (LPARAM)(ofn->lpstrCustomFilter) + n );
93           n += lstrlenW(pstr) + 1;
94           pstr += lstrlenW(pstr) + 1;
95           TRACE("add str=%s associated to %s\n",
96                 debugstr_w(old_pstr), debugstr_w(pstr));
97           SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
98           n += lstrlenW(pstr) + 1;
99           pstr += lstrlenW(pstr) + 1;
100         }
101     }
102   /* read filter information */
103   if (ofn->lpstrFilter) {
104         pstr = (LPWSTR) ofn->lpstrFilter;
105         n = 0;
106         while(*pstr) {
107           old_pstr = pstr;
108           i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
109                                        (LPARAM)(ofn->lpstrFilter + n) );
110           n += lstrlenW(pstr) + 1;
111           pstr += lstrlenW(pstr) + 1;
112           TRACE("add str=%s associated to %s\n",
113                 debugstr_w(old_pstr), debugstr_w(pstr));
114           SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
115           n += lstrlenW(pstr) + 1;
116           pstr += lstrlenW(pstr) + 1;
117         }
118   }
119   /* set default filter */
120   if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
121         ofn->nFilterIndex = 1;
122   SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
123   lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
124              (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
125   TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
126                         ofn->nFilterIndex, debugstr_w(tmpstr));
127   SetDlgItemTextW( hWnd, edt1, tmpstr );
128   /* get drive list */
129   *tmpstr = 0;
130   DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
131   /* read initial directory */
132   /* FIXME: Note that this is now very version-specific (See MSDN description of
133    * the OPENFILENAME structure).  For example under 2000/XP any path in the
134    * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
135    */
136   if (ofn->lpstrInitialDir != NULL)
137     {
138       int len;
139       lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
140       len = lstrlenW(tmpstr);
141       if (len > 0 && tmpstr[len-1] != '\\'  && tmpstr[len-1] != ':') {
142         tmpstr[len]='\\';
143         tmpstr[len+1]='\0';
144       }
145     }
146   else
147     *tmpstr = 0;
148   if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
149     *tmpstr = 0;
150     if (!FILEDLG_ScanDir(hWnd, tmpstr))
151       WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
152   }
153   /* select current drive in combo 2, omit missing drives */
154   {
155       char dir[MAX_PATH];
156       char str[4] = "a:\\";
157       GetCurrentDirectoryA( sizeof(dir), dir );
158       for(i = 0, n = -1; i < 26; i++)
159       {
160           str[0] = 'a' + i;
161           if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
162           if (toupper(str[0]) == toupper(dir[0])) break;
163       }
164   }
165   SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
166   if (!(ofn->Flags & OFN_SHOWHELP))
167     ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
168   if (ofn->Flags & OFN_HIDEREADONLY)
169     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
170   if (lfs->hook)
171       return (BOOL) FILEDLG_CallWindowProc16(lfs, WM_INITDIALOG, wParam, lfs->lParam);
172   return TRUE;
173 }
174
175 /***********************************************************************
176  *                              FILEDLG_WMMeasureItem16         [internal]
177  */
178 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
179 {
180     LPMEASUREITEMSTRUCT16 lpmeasure;
181
182     lpmeasure = MapSL(lParam);
183     lpmeasure->itemHeight = fldrHeight;
184     return TRUE;
185 }
186
187 /* ------------------ Dialog procedures ---------------------- */
188
189 /***********************************************************************
190  *           FileOpenDlgProc   (COMMDLG.6)
191  */
192 BOOL16 CALLBACK FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
193                                LPARAM lParam)
194 {
195     HWND hWnd = HWND_32(hWnd16);
196     LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
197     DRAWITEMSTRUCT dis;
198
199     TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
200     if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
201         {
202             LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc16(lfs, wMsg, wParam, lParam);
203             if (lRet)
204                 return lRet;         /* else continue message processing */
205         }
206     switch (wMsg)
207     {
208     case WM_INITDIALOG:
209         return FILEDLG_WMInitDialog16(hWnd, wParam, lParam);
210
211     case WM_MEASUREITEM:
212         return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
213
214     case WM_DRAWITEM:
215         FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
216         return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
217
218     case WM_COMMAND:
219         return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
220 #if 0
221     case WM_CTLCOLOR:
222          SetBkColor((HDC16)wParam, 0x00C0C0C0);
223          switch (HIWORD(lParam))
224          {
225          case CTLCOLOR_BTN:
226              SetTextColor((HDC16)wParam, 0x00000000);
227              return hGRAYBrush;
228         case CTLCOLOR_STATIC:
229              SetTextColor((HDC16)wParam, 0x00000000);
230              return hGRAYBrush;
231         }
232       break;
233 #endif
234     }
235     return FALSE;
236 }
237
238 /***********************************************************************
239  *           FileSaveDlgProc   (COMMDLG.7)
240  */
241 BOOL16 CALLBACK FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
242                                LPARAM lParam)
243 {
244  HWND hWnd = HWND_32(hWnd16);
245  LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
246  DRAWITEMSTRUCT dis;
247
248  TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
249  if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
250   {
251    LRESULT  lRet;
252    lRet = (BOOL16)FILEDLG_CallWindowProc16(lfs, wMsg, wParam, lParam);
253    if (lRet)
254     return lRet;         /* else continue message processing */
255   }
256   switch (wMsg) {
257    case WM_INITDIALOG:
258       return FILEDLG_WMInitDialog16(hWnd, wParam, lParam);
259
260    case WM_MEASUREITEM:
261       return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
262
263    case WM_DRAWITEM:
264       FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
265       return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
266
267    case WM_COMMAND:
268       return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
269   }
270
271   /*
272   case WM_CTLCOLOR:
273    SetBkColor((HDC16)wParam, 0x00C0C0C0);
274    switch (HIWORD(lParam))
275    {
276     case CTLCOLOR_BTN:
277      SetTextColor((HDC16)wParam, 0x00000000);
278      return hGRAYBrush;
279     case CTLCOLOR_STATIC:
280      SetTextColor((HDC16)wParam, 0x00000000);
281      return hGRAYBrush;
282    }
283    return FALSE;
284
285    */
286   return FALSE;
287 }
288
289 /* ------------------ APIs ---------------------- */
290
291 /***********************************************************************
292  *           GetOpenFileName   (COMMDLG.1)
293  *
294  * Creates a dialog box for the user to select a file to open.
295  *
296  * RETURNS
297  *    TRUE on success: user selected a valid file
298  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
299  *
300  * BUGS
301  *    unknown, there are some FIXME's left.
302  */
303 BOOL16 WINAPI GetOpenFileName16(
304                                 SEGPTR ofn /* [in/out] address of structure with data*/
305                                 )
306 {
307     HINSTANCE16 hInst;
308     BOOL bRet = FALSE;
309     LPOPENFILENAME16 lpofn = MapSL(ofn);
310     LFSPRIVATE lfs;
311     FARPROC16 ptr;
312
313     if (!lpofn || !FileDlg_Init()) return FALSE;
314
315     lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
316     if (lfs)
317     {
318         hInst = GetWindowWord( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
319         ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
320         bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
321                                          (DLGPROC16) ptr, (LPARAM) lfs);
322         FILEDLG_DestroyPrivate(lfs);
323     }
324
325     TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
326     return bRet;
327 }
328
329 /***********************************************************************
330  *           GetSaveFileName   (COMMDLG.2)
331  *
332  * Creates a dialog box for the user to select a file to save.
333  *
334  * RETURNS
335  *    TRUE on success: user enters a valid file
336  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
337  *
338  * BUGS
339  *    unknown. There are some FIXME's left.
340  */
341 BOOL16 WINAPI GetSaveFileName16(
342                                 SEGPTR ofn /* [in/out] addess of structure with data*/
343                                 )
344 {
345     HINSTANCE16 hInst;
346     BOOL bRet = FALSE;
347     LPOPENFILENAME16 lpofn = MapSL(ofn);
348     LFSPRIVATE lfs;
349     FARPROC16 ptr;
350
351     if (!lpofn || !FileDlg_Init()) return FALSE;
352
353     lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
354     if (lfs)
355     {
356         hInst = GetWindowWord( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
357         ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
358         bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
359                                          (DLGPROC16) ptr, (LPARAM) lfs);
360         FILEDLG_DestroyPrivate(lfs);
361     }
362
363     TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
364     return bRet;
365 }