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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 static 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 static 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 %d 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(template32
, size
, 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 lfs
->ofnW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*lfs
->ofnW
));
174 FD16_MapOfnStruct16(priv
->ofn16
, lfs
->ofnW
, lfs
->open
);
176 if (! FD16_GetTemplate(lfs
)) return FALSE
;
181 /***********************************************************************
182 * FD16_CallWindowProc [internal]
184 * called from the common 16/32 code to call the appropriate hook
186 static BOOL CALLBACK
FD16_CallWindowProc(PFD31_DATA lfs
, UINT wMsg
, WPARAM wParam
,
189 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
193 return (BOOL16
) CallWindowProc16(
194 (WNDPROC16
)priv
->ofn16
->lpfnHook
, HWND_16(lfs
->hwnd
),
195 (UINT16
)wMsg
, (WPARAM16
)wParam
, lParam
);
201 /***********************************************************************
202 * FD31_UpdateResult [internal]
203 * update the real client structures
205 static void CALLBACK
FD16_UpdateResult(PFD31_DATA lfs
)
207 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
208 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
211 { /* we have to convert to short (8.3) path */
212 char tmp
[1024]; /* MAX_PATHNAME_LEN */
213 LPOPENFILENAME16 ofn16
= priv
->ofn16
;
214 char *dest
= MapSL(ofn16
->lpstrFile
);
216 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
217 tmp
, sizeof(tmp
), NULL
, NULL
))
218 tmp
[sizeof(tmp
)-1] = 0;
219 GetShortPathNameA(tmp
, dest
, ofn16
->nMaxFile
);
221 /* the same procedure as every year... */
222 if((bs16
= strrchr(dest
, '\\')) != NULL
)
223 ofn16
->nFileOffset
= bs16
- dest
+1;
225 ofn16
->nFileOffset
= 0;
226 ofn16
->nFileExtension
= 0;
227 while(dest
[ofn16
->nFileExtension
] != '.' && dest
[ofn16
->nFileExtension
] != '\0')
228 ofn16
->nFileExtension
++;
229 if (dest
[ofn16
->nFileExtension
] == '\0')
230 ofn16
->nFileExtension
= 0;
232 ofn16
->nFileExtension
++;
237 /***********************************************************************
238 * FD16_UpdateFileTitle [internal]
239 * update the real client structures
241 static void CALLBACK
FD16_UpdateFileTitle(PFD31_DATA lfs
)
243 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
244 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
248 char *dest
= MapSL(priv
->ofn16
->lpstrFileTitle
);
249 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
250 dest
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
251 dest
[ofnW
->nMaxFileTitle
-1] = 0;
256 /***********************************************************************
257 * FD16_SendLbGetCurSel [internal]
258 * retrieve selected listbox item
260 static LRESULT CALLBACK
FD16_SendLbGetCurSel(PFD31_DATA lfs
)
262 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL16
, 0, 0);
266 /************************************************************************
267 * FD16_Destroy [internal]
268 * called from the common 16/32 code to cleanup 32 bit data
270 static void CALLBACK
FD16_Destroy(PFD31_DATA lfs
)
272 PFD16_PRIVATE priv
= (PFD16_PRIVATE
) lfs
->private1632
;
274 /* free resources for a 16 bits dialog */
277 if (priv
->hResource16
) FreeResource16(priv
->hResource16
);
280 GlobalUnlock16(priv
->hGlobal16
);
281 GlobalFree16(priv
->hGlobal16
);
283 FD31_FreeOfnW(lfs
->ofnW
);
284 HeapFree(GetProcessHeap(), 0, lfs
->ofnW
);
288 static void FD16_SetupCallbacks(PFD31_CALLBACKS callbacks
)
290 callbacks
->Init
= FD16_Init
;
291 callbacks
->CWP
= FD16_CallWindowProc
;
292 callbacks
->UpdateResult
= FD16_UpdateResult
;
293 callbacks
->UpdateFileTitle
= FD16_UpdateFileTitle
;
294 callbacks
->SendLbGetCurSel
= FD16_SendLbGetCurSel
;
295 callbacks
->Destroy
= FD16_Destroy
;
298 /***********************************************************************
299 * FD16_MapDrawItemStruct [internal]
300 * map a 16 bits drawitem struct to 32
302 static void FD16_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16
, LPDRAWITEMSTRUCT lpdis
)
304 lpdis
->CtlType
= lpdis16
->CtlType
;
305 lpdis
->CtlID
= lpdis16
->CtlID
;
306 lpdis
->itemID
= lpdis16
->itemID
;
307 lpdis
->itemAction
= lpdis16
->itemAction
;
308 lpdis
->itemState
= lpdis16
->itemState
;
309 lpdis
->hwndItem
= HWND_32(lpdis16
->hwndItem
);
310 lpdis
->hDC
= HDC_32(lpdis16
->hDC
);
311 lpdis
->rcItem
.right
= lpdis16
->rcItem
.right
;
312 lpdis
->rcItem
.left
= lpdis16
->rcItem
.left
;
313 lpdis
->rcItem
.top
= lpdis16
->rcItem
.top
;
314 lpdis
->rcItem
.bottom
= lpdis16
->rcItem
.bottom
;
315 lpdis
->itemData
= lpdis16
->itemData
;
319 /***********************************************************************
320 * FD16_WMMeasureItem16 [internal]
322 static LONG
FD16_WMMeasureItem(HWND16 hWnd
, WPARAM16 wParam
, LPARAM lParam
)
324 LPMEASUREITEMSTRUCT16 lpmeasure
;
326 lpmeasure
= MapSL(lParam
);
327 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
331 /* ------------------ Dialog procedures ---------------------- */
333 /***********************************************************************
334 * FileOpenDlgProc (COMMDLG.6)
336 BOOL16 CALLBACK
FileOpenDlgProc16(HWND16 hWnd16
, UINT16 wMsg
, WPARAM16 wParam
, LPARAM lParam
)
338 HWND hWnd
= HWND_32(hWnd16
);
339 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
342 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
343 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
345 LRESULT lRet
= (BOOL16
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
347 return lRet
; /* else continue message processing */
352 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
355 return FD16_WMMeasureItem(hWnd16
, wParam
, lParam
);
358 FD16_MapDrawItemStruct(MapSL(lParam
), &dis
);
359 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, FALSE
, &dis
);
362 return FD31_WMCommand(hWnd
, lParam
, HIWORD(lParam
),wParam
, lfs
);
365 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
366 switch (HIWORD(lParam
))
369 SetTextColor((HDC16
)wParam
, 0x00000000);
371 case CTLCOLOR_STATIC
:
372 SetTextColor((HDC16
)wParam
, 0x00000000);
381 /***********************************************************************
382 * FileSaveDlgProc (COMMDLG.7)
384 BOOL16 CALLBACK
FileSaveDlgProc16(HWND16 hWnd16
, UINT16 wMsg
, WPARAM16 wParam
, LPARAM lParam
)
386 HWND hWnd
= HWND_32(hWnd16
);
387 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
390 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
391 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
394 lRet
= (BOOL16
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
396 return lRet
; /* else continue message processing */
400 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
403 return FD16_WMMeasureItem(hWnd16
, wParam
, lParam
);
406 FD16_MapDrawItemStruct(MapSL(lParam
), &dis
);
407 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, TRUE
, &dis
);
410 return FD31_WMCommand(hWnd
, lParam
, HIWORD(lParam
), wParam
, lfs
);
415 SetBkColor((HDC16)wParam, 0x00C0C0C0);
416 switch (HIWORD(lParam))
419 SetTextColor((HDC16)wParam, 0x00000000);
421 case CTLCOLOR_STATIC:
422 SetTextColor((HDC16)wParam, 0x00000000);
431 /* ------------------ APIs ---------------------- */
433 /***********************************************************************
434 * GetOpenFileName (COMMDLG.1)
436 * Creates a dialog box for the user to select a file to open.
439 * TRUE on success: user selected a valid file
440 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
443 * unknown, there are some FIXME's left.
445 BOOL16 WINAPI
GetOpenFileName16(
446 SEGPTR ofn
/* [in/out] address of structure with data*/
451 LPOPENFILENAME16 lpofn
= MapSL(ofn
);
454 FD31_CALLBACKS callbacks
;
457 if (!lpofn
|| !FD31_Init()) return FALSE
;
459 FD16_SetupCallbacks(&callbacks
);
460 lfs
= FD31_AllocPrivate((LPARAM
) ofn
, OPEN_DIALOG
, &callbacks
, 0);
463 priv
= (PFD16_PRIVATE
) lfs
->private1632
;
464 hInst
= GetWindowLongPtrA( HWND_32(lpofn
->hwndOwner
), GWLP_HINSTANCE
);
465 ptr
= GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR
) 6);
466 bRet
= DialogBoxIndirectParam16( hInst
, priv
->hDlgTmpl16
, lpofn
->hwndOwner
,
467 (DLGPROC16
) ptr
, (LPARAM
) lfs
);
468 FD31_DestroyPrivate(lfs
);
471 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn
->lpstrFile
));
475 /***********************************************************************
476 * GetSaveFileName (COMMDLG.2)
478 * Creates a dialog box for the user to select a file to save.
481 * TRUE on success: user enters a valid file
482 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
485 * unknown. There are some FIXME's left.
487 BOOL16 WINAPI
GetSaveFileName16(
488 SEGPTR ofn
/* [in/out] addess of structure with data*/
493 LPOPENFILENAME16 lpofn
= MapSL(ofn
);
496 FD31_CALLBACKS callbacks
;
499 if (!lpofn
|| !FD31_Init()) return FALSE
;
501 FD16_SetupCallbacks(&callbacks
);
502 lfs
= FD31_AllocPrivate((LPARAM
) ofn
, SAVE_DIALOG
, &callbacks
, 0);
505 priv
= (PFD16_PRIVATE
) lfs
->private1632
;
506 hInst
= GetWindowLongPtrA( HWND_32(lpofn
->hwndOwner
), GWLP_HINSTANCE
);
507 ptr
= GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR
) 7);
508 bRet
= DialogBoxIndirectParam16( hInst
, priv
->hDlgTmpl16
, lpofn
->hwndOwner
,
509 (DLGPROC16
) ptr
, (LPARAM
) lfs
);
510 FD31_DestroyPrivate(lfs
);
513 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn
->lpstrFile
));