Updated.
[wine/multimedia.git] / dlls / commdlg / finddlg.c
blob44e0ee375a348f2f5ced0a8e3a45093ac97c7c15
1 /*
2 * COMMDLG - 16 bits Find & Replace Text 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
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "commdlg.h"
33 #include "wine/debug.h"
34 #include "cderr.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
38 #include "cdlg.h"
40 struct FRPRIVATE
42 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
43 HANDLE16 hResource16; /* handle for allocated resource 16 */
44 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
45 LPCVOID template; /* template for 32 bits resource */
46 BOOL find; /* TRUE if find dialog, FALSE if replace dialog */
47 FINDREPLACE16 *fr16;
50 #define LFRPRIVATE struct FRPRIVATE *
52 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
53 LPARAM lParam);
54 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
55 LPARAM lParam);
57 /***********************************************************************
58 * FINDDLG_Get16BitsTemplate [internal]
60 * Get a template (FALSE if failure) when 16 bits dialogs are used
61 * by a 16 bits application
62 * FIXME : no test was done for the user-provided template cases
64 BOOL FINDDLG_Get16BitsTemplate(LFRPRIVATE lfr)
66 LPFINDREPLACE16 fr16 = lfr->fr16;
68 if (fr16->Flags & FR_ENABLETEMPLATEHANDLE)
70 lfr->template = GlobalLock16(fr16->hInstance);
71 if (!lfr->template)
73 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
74 return FALSE;
77 else if (fr16->Flags & FR_ENABLETEMPLATE)
79 HANDLE16 hResInfo;
80 if (!(hResInfo = FindResource16(fr16->hInstance,
81 MapSL(fr16->lpTemplateName),
82 (LPSTR)RT_DIALOG)))
84 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
85 return FALSE;
87 if (!(lfr->hDlgTmpl16 = LoadResource16( fr16->hInstance, hResInfo )))
89 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
90 return FALSE;
92 lfr->hResource16 = lfr->hDlgTmpl16;
93 lfr->template = LockResource16(lfr->hResource16);
94 if (!lfr->template)
96 FreeResource16(lfr->hResource16);
97 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
98 return FALSE;
101 else
102 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
103 HRSRC hResInfo;
104 HGLOBAL hDlgTmpl32;
105 LPCVOID template32;
106 DWORD size;
107 HGLOBAL16 hGlobal16;
109 if (!(hResInfo = FindResourceA(COMDLG32_hInstance,
110 lfr->find ?
111 MAKEINTRESOURCEA(FINDDLGORD):MAKEINTRESOURCEA(REPLACEDLGORD),
112 (LPSTR)RT_DIALOG)))
114 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
115 return FALSE;
117 if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo )) ||
118 !(template32 = LockResource( hDlgTmpl32 )))
120 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
121 return FALSE;
123 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
124 hGlobal16 = GlobalAlloc16(0, size);
125 if (!hGlobal16)
127 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
128 ERR("alloc failure for %ld bytes\n", size);
129 return FALSE;
131 lfr->template = GlobalLock16(hGlobal16);
132 if (!lfr->template)
134 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
135 ERR("global lock failure for %x handle\n", hGlobal16);
136 GlobalFree16(hGlobal16);
137 return FALSE;
139 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)lfr->template);
140 lfr->hDlgTmpl16 = hGlobal16;
141 lfr->hGlobal16 = hGlobal16;
143 return TRUE;
147 /***********************************************************************
148 * FINDDLG_FreeResources [internal]
150 * Free resources allocated
152 void FINDDLG_FreeResources(LFRPRIVATE lfr)
154 /* free resources */
155 if (lfr->fr16->Flags & FR_ENABLETEMPLATEHANDLE)
156 GlobalUnlock16(lfr->fr16->hInstance);
157 if (lfr->hResource16)
159 GlobalUnlock16(lfr->hResource16);
160 FreeResource16(lfr->hResource16);
162 if (lfr->hGlobal16)
164 GlobalUnlock16(lfr->hGlobal16);
165 GlobalFree16(lfr->hGlobal16);
169 /***********************************************************************
170 * FindText (COMMDLG.11)
172 HWND16 WINAPI FindText16( SEGPTR find )
174 HANDLE16 hInst;
175 HWND16 ret = 0;
176 FARPROC16 ptr;
177 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
179 if (!lfr) return 0;
180 lfr->fr16 = MapSL(find);
181 lfr->find = TRUE;
182 if (FINDDLG_Get16BitsTemplate(lfr))
184 hInst = GetWindowLongA( HWND_32(lfr->fr16->hwndOwner), GWL_HINSTANCE);
185 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 13);
186 ret = CreateDialogIndirectParam16( hInst, lfr->template,
187 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
188 FINDDLG_FreeResources(lfr);
190 HeapFree(GetProcessHeap(), 0, lfr);
191 return ret;
195 /***********************************************************************
196 * ReplaceText (COMMDLG.12)
198 HWND16 WINAPI ReplaceText16( SEGPTR find )
200 HANDLE16 hInst;
201 HWND16 ret = 0;
202 FARPROC16 ptr;
203 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
205 if (!lfr) return 0;
207 * FIXME : We should do error checking on the lpFind structure here
208 * and make CommDlgExtendedError() return the error condition.
210 lfr->fr16 = MapSL(find);
211 lfr->find = FALSE;
212 if (FINDDLG_Get16BitsTemplate(lfr))
214 hInst = GetWindowLongA( HWND_32(lfr->fr16->hwndOwner), GWL_HINSTANCE);
215 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 14);
216 ret = CreateDialogIndirectParam16( hInst, lfr->template,
217 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
219 FINDDLG_FreeResources(lfr);
221 HeapFree(GetProcessHeap(), 0, lfr);
222 return ret;
226 /***********************************************************************
227 * FINDDLG_WMInitDialog [internal]
229 static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags,
230 LPSTR lpstrFindWhat, BOOL fUnicode)
232 SetWindowLongA(hWnd, DWL_USER, lParam);
233 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
235 * FIXME : If the initial FindWhat string is empty, we should disable the
236 * FindNext (IDOK) button. Only after typing some text, the button should be
237 * enabled.
239 if (fUnicode) SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
240 else SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
241 CheckRadioButton(hWnd, rad1, rad2, (*lpFlags & FR_DOWN) ? rad2 : rad1);
242 if (*lpFlags & (FR_HIDEUPDOWN | FR_NOUPDOWN)) {
243 EnableWindow(GetDlgItem(hWnd, rad1), FALSE);
244 EnableWindow(GetDlgItem(hWnd, rad2), FALSE);
246 if (*lpFlags & FR_HIDEUPDOWN) {
247 ShowWindow(GetDlgItem(hWnd, rad1), SW_HIDE);
248 ShowWindow(GetDlgItem(hWnd, rad2), SW_HIDE);
249 ShowWindow(GetDlgItem(hWnd, grp1), SW_HIDE);
251 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
252 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
253 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
254 if (*lpFlags & FR_HIDEWHOLEWORD)
255 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
256 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
257 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
258 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
259 if (*lpFlags & FR_HIDEMATCHCASE)
260 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
261 if (!(*lpFlags & FR_SHOWHELP)) {
262 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
263 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
265 ShowWindow(hWnd, SW_SHOWNORMAL);
266 return TRUE;
270 /***********************************************************************
271 * FINDDLG_WMCommand [internal]
273 static LRESULT FINDDLG_WMCommand(HWND hWnd, WPARAM wParam,
274 HWND hwndOwner, LPDWORD lpFlags,
275 LPSTR lpstrFindWhat, WORD wFindWhatLen,
276 BOOL fUnicode)
278 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
279 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
281 switch (wParam) {
282 case IDOK:
283 if (fUnicode)
284 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
285 else GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
286 if (IsDlgButtonChecked(hWnd, rad2))
287 *lpFlags |= FR_DOWN;
288 else *lpFlags &= ~FR_DOWN;
289 if (IsDlgButtonChecked(hWnd, chx1))
290 *lpFlags |= FR_WHOLEWORD;
291 else *lpFlags &= ~FR_WHOLEWORD;
292 if (IsDlgButtonChecked(hWnd, chx2))
293 *lpFlags |= FR_MATCHCASE;
294 else *lpFlags &= ~FR_MATCHCASE;
295 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
296 *lpFlags |= FR_FINDNEXT;
297 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
298 GetWindowLongA(hWnd, DWL_USER) );
299 return TRUE;
300 case IDCANCEL:
301 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
302 *lpFlags |= FR_DIALOGTERM;
303 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
304 GetWindowLongA(hWnd, DWL_USER) );
305 DestroyWindow(hWnd);
306 return TRUE;
307 case pshHelp:
308 /* FIXME : should lpfr structure be passed as an argument ??? */
309 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
310 return TRUE;
312 return FALSE;
316 /***********************************************************************
317 * FindTextDlgProc (COMMDLG.13)
319 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
320 LPARAM lParam)
322 HWND hWnd = HWND_32(hWnd16);
323 LPFINDREPLACE16 lpfr;
324 switch (wMsg) {
325 case WM_INITDIALOG:
326 lpfr=MapSL(lParam);
327 return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags),
328 MapSL(lpfr->lpstrFindWhat), FALSE);
329 case WM_COMMAND:
330 lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER));
331 return FINDDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
332 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
333 lpfr->wFindWhatLen, FALSE);
335 return FALSE;
339 /***********************************************************************
340 * REPLACEDLG_WMInitDialog [internal]
342 static LRESULT REPLACEDLG_WMInitDialog(HWND hWnd, LPARAM lParam,
343 LPDWORD lpFlags, LPSTR lpstrFindWhat,
344 LPSTR lpstrReplaceWith, BOOL fUnicode)
346 SetWindowLongA(hWnd, DWL_USER, lParam);
347 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
349 * FIXME : If the initial FindWhat string is empty, we should disable the FinNext /
350 * Replace / ReplaceAll buttons. Only after typing some text, the buttons should be
351 * enabled.
353 if (fUnicode)
355 SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
356 SetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith);
357 } else
359 SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
360 SetDlgItemTextA(hWnd, edt2, lpstrReplaceWith);
362 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
363 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
364 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
365 if (*lpFlags & FR_HIDEWHOLEWORD)
366 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
367 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
368 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
369 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
370 if (*lpFlags & FR_HIDEMATCHCASE)
371 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
372 if (!(*lpFlags & FR_SHOWHELP)) {
373 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
374 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
376 ShowWindow(hWnd, SW_SHOWNORMAL);
377 return TRUE;
381 /***********************************************************************
382 * REPLACEDLG_WMCommand [internal]
384 static LRESULT REPLACEDLG_WMCommand(HWND hWnd, WPARAM16 wParam,
385 HWND hwndOwner, LPDWORD lpFlags,
386 LPSTR lpstrFindWhat, WORD wFindWhatLen,
387 LPSTR lpstrReplaceWith, WORD wReplaceWithLen,
388 BOOL fUnicode)
390 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
391 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
393 switch (wParam) {
394 case IDOK:
395 if (fUnicode)
397 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
398 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
399 } else
401 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
402 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
404 if (IsDlgButtonChecked(hWnd, chx1))
405 *lpFlags |= FR_WHOLEWORD;
406 else *lpFlags &= ~FR_WHOLEWORD;
407 if (IsDlgButtonChecked(hWnd, chx2))
408 *lpFlags |= FR_MATCHCASE;
409 else *lpFlags &= ~FR_MATCHCASE;
410 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
411 *lpFlags |= FR_FINDNEXT;
412 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
413 GetWindowLongA(hWnd, DWL_USER) );
414 return TRUE;
415 case IDCANCEL:
416 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
417 *lpFlags |= FR_DIALOGTERM;
418 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
419 GetWindowLongA(hWnd, DWL_USER) );
420 DestroyWindow(hWnd);
421 return TRUE;
422 case psh1:
423 if (fUnicode)
425 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
426 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
427 } else
429 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
430 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
432 if (IsDlgButtonChecked(hWnd, chx1))
433 *lpFlags |= FR_WHOLEWORD;
434 else *lpFlags &= ~FR_WHOLEWORD;
435 if (IsDlgButtonChecked(hWnd, chx2))
436 *lpFlags |= FR_MATCHCASE;
437 else *lpFlags &= ~FR_MATCHCASE;
438 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM);
439 *lpFlags |= FR_REPLACE;
440 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
441 GetWindowLongA(hWnd, DWL_USER) );
442 return TRUE;
443 case psh2:
444 if (fUnicode)
446 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
447 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
448 } else
450 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
451 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
453 if (IsDlgButtonChecked(hWnd, chx1))
454 *lpFlags |= FR_WHOLEWORD;
455 else *lpFlags &= ~FR_WHOLEWORD;
456 if (IsDlgButtonChecked(hWnd, chx2))
457 *lpFlags |= FR_MATCHCASE;
458 else *lpFlags &= ~FR_MATCHCASE;
459 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM);
460 *lpFlags |= FR_REPLACEALL;
461 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
462 GetWindowLongA(hWnd, DWL_USER) );
463 return TRUE;
464 case pshHelp:
465 /* FIXME : should lpfr structure be passed as an argument ??? */
466 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
467 return TRUE;
469 return FALSE;
473 /***********************************************************************
474 * ReplaceTextDlgProc (COMMDLG.14)
476 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
477 LPARAM lParam)
479 HWND hWnd = HWND_32(hWnd16);
480 LPFINDREPLACE16 lpfr;
481 switch (wMsg) {
482 case WM_INITDIALOG:
483 lpfr=MapSL(lParam);
484 return REPLACEDLG_WMInitDialog(hWnd, lParam, &lpfr->Flags,
485 MapSL(lpfr->lpstrFindWhat),
486 MapSL(lpfr->lpstrReplaceWith), FALSE);
487 case WM_COMMAND:
488 lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER));
489 return REPLACEDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
490 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
491 lpfr->wFindWhatLen, MapSL(lpfr->lpstrReplaceWith),
492 lpfr->wReplaceWithLen, FALSE);
494 return FALSE;