2 * COMMDLG - File Dialogs
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
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.
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.
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
24 #include "wine/winbase16.h"
26 #include "wine/winuser16.h"
27 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
35 #include "filedlg31.h"
37 typedef struct tagFD16_PRIVATE
39 HANDLE16 hDlgTmpl16
; /* handle for resource 16 */
40 HANDLE16 hResource16
; /* handle for allocated resource 16 */
41 HANDLE16 hGlobal16
; /* 16 bits mem block (resources) */
42 OPENFILENAME16
*ofn16
; /* original structure if 16 bits dialog */
43 } FD16_PRIVATE
, *PFD16_PRIVATE
;
45 /************************************************************************
46 * FD16_MapOfnStruct16 [internal]
47 * map a 16 bits structure to an Unicode one
49 void FD16_MapOfnStruct16(LPOPENFILENAME16 ofn16
, LPOPENFILENAMEW ofnW
, BOOL open
)
52 /* first convert to linear pointers */
53 memset(&ofnA
, 0, sizeof(OPENFILENAMEA
));
54 ofnA
.lStructSize
= sizeof(OPENFILENAMEA
);
55 ofnA
.hwndOwner
= HWND_32(ofn16
->hwndOwner
);
56 ofnA
.hInstance
= HINSTANCE_32(ofn16
->hInstance
);
57 if (ofn16
->lpstrFilter
)
58 ofnA
.lpstrFilter
= MapSL(ofn16
->lpstrFilter
);
59 if (ofn16
->lpstrCustomFilter
)
60 ofnA
.lpstrCustomFilter
= MapSL(ofn16
->lpstrCustomFilter
);
61 ofnA
.nMaxCustFilter
= ofn16
->nMaxCustFilter
;
62 ofnA
.nFilterIndex
= ofn16
->nFilterIndex
;
63 ofnA
.lpstrFile
= MapSL(ofn16
->lpstrFile
);
64 ofnA
.nMaxFile
= ofn16
->nMaxFile
;
65 ofnA
.lpstrFileTitle
= MapSL(ofn16
->lpstrFileTitle
);
66 ofnA
.nMaxFileTitle
= ofn16
->nMaxFileTitle
;
67 ofnA
.lpstrInitialDir
= MapSL(ofn16
->lpstrInitialDir
);
68 ofnA
.lpstrTitle
= MapSL(ofn16
->lpstrTitle
);
69 ofnA
.Flags
= ofn16
->Flags
;
70 ofnA
.nFileOffset
= ofn16
->nFileOffset
;
71 ofnA
.nFileExtension
= ofn16
->nFileExtension
;
72 ofnA
.lpstrDefExt
= MapSL(ofn16
->lpstrDefExt
);
73 if (HIWORD(ofn16
->lpTemplateName
))
74 ofnA
.lpTemplateName
= MapSL(ofn16
->lpTemplateName
);
76 ofnA
.lpTemplateName
= (LPSTR
) ofn16
->lpTemplateName
; /* ressource number */
77 /* now calls the 32 bits Ansi to Unicode version to complete the job */
78 FD31_MapOfnStructA(&ofnA
, ofnW
, open
);
81 /***********************************************************************
82 * FD16_GetTemplate [internal]
84 * Get a template (FALSE if failure) when 16 bits dialogs are used
85 * by a 16 bits application
88 BOOL
FD16_GetTemplate(PFD31_DATA lfs
)
90 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
91 LPOPENFILENAME16 ofn16
= priv
->ofn16
;
93 HGLOBAL16 hGlobal16
= 0;
95 if (ofn16
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
96 priv
->hDlgTmpl16
= ofn16
->hInstance
;
97 else if (ofn16
->Flags
& OFN_ENABLETEMPLATE
)
100 if (!(hResInfo
= FindResource16(ofn16
->hInstance
,
101 MapSL(ofn16
->lpTemplateName
),
104 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
107 if (!(priv
->hDlgTmpl16
= LoadResource16( ofn16
->hInstance
, hResInfo
)))
109 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
112 priv
->hResource16
= priv
->hDlgTmpl16
;
115 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
121 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
122 lfs
->open
? "OPEN_FILE":"SAVE_FILE", (LPSTR
)RT_DIALOG
)))
124 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
127 if (!(hDlgTmpl32
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
128 !(template32
= LockResource( hDlgTmpl32
)))
130 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
133 size
= SizeofResource(COMDLG32_hInstance
, hResInfo
);
134 hGlobal16
= GlobalAlloc16(0, size
);
137 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE
);
138 ERR("alloc failure for %ld bytes\n", size
);
141 template = GlobalLock16(hGlobal16
);
144 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE
);
145 ERR("global lock failure for %x handle\n", hGlobal16
);
146 GlobalFree16(hGlobal16
);
149 ConvertDialog32To16((LPVOID
)template32
, size
, (LPVOID
)template);
150 priv
->hDlgTmpl16
= hGlobal16
;
151 priv
->hGlobal16
= hGlobal16
;
156 /************************************************************************
157 * FD16_Init [internal]
158 * called from the common 16/32 code to initialize 16 bit data
160 static BOOL CALLBACK
FD16_Init(LPARAM lParam
, PFD31_DATA lfs
, DWORD data
)
164 priv
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FD16_PRIVATE
));
165 lfs
->private1632
= priv
;
166 if (NULL
== lfs
->private1632
) return FALSE
;
168 priv
->ofn16
= MapSL(lParam
);
169 if (priv
->ofn16
->Flags
& OFN_ENABLEHOOK
)
170 if (priv
->ofn16
->lpfnHook
)
173 FD16_MapOfnStruct16(priv
->ofn16
, &lfs
->ofnW
, lfs
->open
);
175 if (! FD16_GetTemplate(lfs
)) return FALSE
;
180 /***********************************************************************
181 * FD16_CallWindowProc [internal]
183 * called from the common 16/32 code to call the appropriate hook
185 BOOL CALLBACK
FD16_CallWindowProc(PFD31_DATA lfs
, UINT wMsg
, WPARAM wParam
,
188 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
192 return (BOOL16
) CallWindowProc16(
193 (WNDPROC16
)priv
->ofn16
->lpfnHook
, HWND_16(lfs
->hwnd
),
194 (UINT16
)wMsg
, (WPARAM16
)wParam
, lParam
);
200 /***********************************************************************
201 * FD31_UpdateResult [internal]
202 * update the real client structures
204 static void CALLBACK
FD16_UpdateResult(PFD31_DATA lfs
)
206 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
207 LPOPENFILENAMEW ofnW
= &lfs
->ofnW
;
210 { /* we have to convert to short (8.3) path */
211 char tmp
[1024]; /* MAX_PATHNAME_LEN */
212 LPOPENFILENAME16 ofn16
= priv
->ofn16
;
213 char *dest
= MapSL(ofn16
->lpstrFile
);
215 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
216 tmp
, sizeof(tmp
), NULL
, NULL
))
217 tmp
[sizeof(tmp
)-1] = 0;
218 GetShortPathNameA(tmp
, dest
, ofn16
->nMaxFile
);
220 /* the same procedure as every year... */
221 if((bs16
= strrchr(dest
, '\\')) != NULL
)
222 ofn16
->nFileOffset
= bs16
- dest
+1;
224 ofn16
->nFileOffset
= 0;
225 ofn16
->nFileExtension
= 0;
226 while(dest
[ofn16
->nFileExtension
] != '.' && dest
[ofn16
->nFileExtension
] != '\0')
227 ofn16
->nFileExtension
++;
228 if (dest
[ofn16
->nFileExtension
] == '\0')
229 ofn16
->nFileExtension
= 0;
231 ofn16
->nFileExtension
++;
236 /***********************************************************************
237 * FD16_UpdateFileTitle [internal]
238 * update the real client structures
240 static void CALLBACK
FD16_UpdateFileTitle(PFD31_DATA lfs
)
242 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
243 LPOPENFILENAMEW ofnW
= &lfs
->ofnW
;
247 char *dest
= MapSL(priv
->ofn16
->lpstrFileTitle
);
248 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
249 dest
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
250 dest
[ofnW
->nMaxFileTitle
-1] = 0;
255 /***********************************************************************
256 * FD16_SendLbGetCurSel [internal]
257 * retrieve selected listbox item
259 static LRESULT CALLBACK
FD16_SendLbGetCurSel(PFD31_DATA lfs
)
261 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL16
, 0, 0);
265 /************************************************************************
266 * FD16_Destroy [internal]
267 * called from the common 16/32 code to cleanup 32 bit data
269 static void CALLBACK
FD16_Destroy(PFD31_DATA lfs
)
271 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
273 /* free resources for a 16 bits dialog */
276 if (priv
->hResource16
) FreeResource16(priv
->hResource16
);
279 GlobalUnlock16(priv
->hGlobal16
);
280 GlobalFree16(priv
->hGlobal16
);
282 FD31_FreeOfnW(&lfs
->ofnW
);
286 static void FD16_SetupCallbacks(PFD31_CALLBACKS callbacks
)
288 callbacks
->Init
= FD16_Init
;
289 callbacks
->CWP
= FD16_CallWindowProc
;
290 callbacks
->UpdateResult
= FD16_UpdateResult
;
291 callbacks
->UpdateFileTitle
= FD16_UpdateFileTitle
;
292 callbacks
->SendLbGetCurSel
= FD16_SendLbGetCurSel
;
293 callbacks
->Destroy
= FD16_Destroy
;
296 /***********************************************************************
297 * FD16_MapDrawItemStruct [internal]
298 * map a 16 bits drawitem struct to 32
300 static void FD16_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16
, LPDRAWITEMSTRUCT lpdis
)
302 lpdis
->CtlType
= lpdis16
->CtlType
;
303 lpdis
->CtlID
= lpdis16
->CtlID
;
304 lpdis
->itemID
= lpdis16
->itemID
;
305 lpdis
->itemAction
= lpdis16
->itemAction
;
306 lpdis
->itemState
= lpdis16
->itemState
;
307 lpdis
->hwndItem
= HWND_32(lpdis16
->hwndItem
);
308 lpdis
->hDC
= HDC_32(lpdis16
->hDC
);
309 lpdis
->rcItem
.right
= lpdis16
->rcItem
.right
;
310 lpdis
->rcItem
.left
= lpdis16
->rcItem
.left
;
311 lpdis
->rcItem
.top
= lpdis16
->rcItem
.top
;
312 lpdis
->rcItem
.bottom
= lpdis16
->rcItem
.bottom
;
313 lpdis
->itemData
= lpdis16
->itemData
;
317 /***********************************************************************
318 * FD16_WMMeasureItem16 [internal]
320 static LONG
FD16_WMMeasureItem(HWND16 hWnd
, WPARAM16 wParam
, LPARAM lParam
)
322 LPMEASUREITEMSTRUCT16 lpmeasure
;
324 lpmeasure
= MapSL(lParam
);
325 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
329 /* ------------------ Dialog procedures ---------------------- */
331 /***********************************************************************
332 * FileOpenDlgProc16 (COMMDLG.6)
334 BOOL16 CALLBACK
FileOpenDlgProc16(HWND16 hWnd16
, UINT16 wMsg
, WPARAM16 wParam
, LPARAM lParam
)
336 HWND hWnd
= HWND_32(hWnd16
);
337 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
340 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
341 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
343 LRESULT lRet
= (BOOL16
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
345 return lRet
; /* else continue message processing */
350 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
353 return FD16_WMMeasureItem(hWnd16
, wParam
, lParam
);
356 FD16_MapDrawItemStruct(MapSL(lParam
), &dis
);
357 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, FALSE
, &dis
);
360 return FD31_WMCommand(hWnd
, lParam
, HIWORD(lParam
),wParam
, lfs
);
363 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
364 switch (HIWORD(lParam
))
367 SetTextColor((HDC16
)wParam
, 0x00000000);
369 case CTLCOLOR_STATIC
:
370 SetTextColor((HDC16
)wParam
, 0x00000000);
379 /***********************************************************************
380 * FileSaveDlgProc16 (COMMDLG.7)
382 BOOL16 CALLBACK
FileSaveDlgProc16(HWND16 hWnd16
, UINT16 wMsg
, WPARAM16 wParam
, LPARAM lParam
)
384 HWND hWnd
= HWND_32(hWnd16
);
385 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
388 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
389 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
392 lRet
= (BOOL16
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
394 return lRet
; /* else continue message processing */
398 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
401 return FD16_WMMeasureItem(hWnd16
, wParam
, lParam
);
404 FD16_MapDrawItemStruct(MapSL(lParam
), &dis
);
405 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, TRUE
, &dis
);
408 return FD31_WMCommand(hWnd
, lParam
, HIWORD(lParam
), wParam
, lfs
);
413 SetBkColor((HDC16)wParam, 0x00C0C0C0);
414 switch (HIWORD(lParam))
417 SetTextColor((HDC16)wParam, 0x00000000);
419 case CTLCOLOR_STATIC:
420 SetTextColor((HDC16)wParam, 0x00000000);
429 /* ------------------ APIs ---------------------- */
431 /***********************************************************************
432 * GetOpenFileName (COMMDLG.1)
434 * Creates a dialog box for the user to select a file to open.
437 * TRUE on success: user selected a valid file
438 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
441 * unknown, there are some FIXME's left.
443 BOOL16 WINAPI
GetOpenFileName16(
444 SEGPTR ofn
/* [in/out] address of structure with data*/
449 LPOPENFILENAME16 lpofn
= MapSL(ofn
);
452 FD31_CALLBACKS callbacks
;
455 if (!lpofn
|| !FD31_Init()) return FALSE
;
457 FD16_SetupCallbacks(&callbacks
);
458 lfs
= FD31_AllocPrivate((LPARAM
) ofn
, OPEN_DIALOG
, &callbacks
, 0);
461 priv
= (PFD16_PRIVATE
) lfs
->private1632
;
462 hInst
= GetWindowWord( HWND_32(lpofn
->hwndOwner
), GWL_HINSTANCE
);
463 ptr
= GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR
) 6);
464 bRet
= DialogBoxIndirectParam16( hInst
, priv
->hDlgTmpl16
, lpofn
->hwndOwner
,
465 (DLGPROC16
) ptr
, (LPARAM
) lfs
);
466 FD31_DestroyPrivate(lfs
);
469 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn
->lpstrFile
));
473 /***********************************************************************
474 * GetSaveFileName (COMMDLG.2)
476 * Creates a dialog box for the user to select a file to save.
479 * TRUE on success: user enters a valid file
480 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
483 * unknown. There are some FIXME's left.
485 BOOL16 WINAPI
GetSaveFileName16(
486 SEGPTR ofn
/* [in/out] addess of structure with data*/
491 LPOPENFILENAME16 lpofn
= MapSL(ofn
);
494 FD31_CALLBACKS callbacks
;
497 if (!lpofn
|| !FD31_Init()) return FALSE
;
499 FD16_SetupCallbacks(&callbacks
);
500 lfs
= FD31_AllocPrivate((LPARAM
) ofn
, SAVE_DIALOG
, &callbacks
, 0);
503 priv
= (PFD16_PRIVATE
) lfs
->private1632
;
504 hInst
= GetWindowWord( HWND_32(lpofn
->hwndOwner
), GWL_HINSTANCE
);
505 ptr
= GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR
) 7);
506 bRet
= DialogBoxIndirectParam16( hInst
, priv
->hDlgTmpl16
, lpofn
->hwndOwner
,
507 (DLGPROC16
) ptr
, (LPARAM
) lfs
);
508 FD31_DestroyPrivate(lfs
);
511 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn
->lpstrFile
));