Release 20030408.
[wine/gsoc-2012-control.git] / dlls / commdlg / finddlg.c
blob4a80a00646c3bc6c985003f73ac2403b901db63b
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 <stdlib.h>
24 #include <string.h>
25 #include "winbase.h"
26 #include "wine/winbase16.h"
27 #include "wine/winuser16.h"
28 #include "commdlg.h"
29 #include "wine/debug.h"
30 #include "cderr.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
34 #include "cdlg.h"
36 struct FRPRIVATE
38 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
39 HANDLE16 hResource16; /* handle for allocated resource 16 */
40 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
41 LPCVOID template; /* template for 32 bits resource */
42 BOOL find; /* TRUE if find dialog, FALSE if replace dialog */
43 FINDREPLACE16 *fr16;
46 #define LFRPRIVATE struct FRPRIVATE *
48 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
49 LPARAM lParam);
50 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
51 LPARAM lParam);
53 /***********************************************************************
54 * FINDDLG_Get16BitsTemplate [internal]
56 * Get a template (FALSE if failure) when 16 bits dialogs are used
57 * by a 16 bits application
58 * FIXME : no test was done for the user-provided template cases
60 BOOL FINDDLG_Get16BitsTemplate(LFRPRIVATE lfr)
62 LPFINDREPLACE16 fr16 = lfr->fr16;
64 if (fr16->Flags & FR_ENABLETEMPLATEHANDLE)
66 lfr->template = GlobalLock16(fr16->hInstance);
67 if (!lfr->template)
69 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
70 return FALSE;
73 else if (fr16->Flags & FR_ENABLETEMPLATE)
75 HANDLE16 hResInfo;
76 if (!(hResInfo = FindResource16(fr16->hInstance,
77 MapSL(fr16->lpTemplateName),
78 RT_DIALOGA)))
80 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
81 return FALSE;
83 if (!(lfr->hDlgTmpl16 = LoadResource16( fr16->hInstance, hResInfo )))
85 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
86 return FALSE;
88 lfr->hResource16 = lfr->hDlgTmpl16;
89 lfr->template = LockResource16(lfr->hResource16);
90 if (!lfr->template)
92 FreeResource16(lfr->hResource16);
93 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
94 return FALSE;
97 else
98 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
99 HRSRC hResInfo;
100 HGLOBAL hDlgTmpl32;
101 LPCVOID template32;
102 DWORD size;
103 HGLOBAL16 hGlobal16;
105 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
106 lfr->find ?
107 MAKEINTRESOURCEA(FINDDLGORD):MAKEINTRESOURCEA(REPLACEDLGORD),
108 RT_DIALOGA)))
110 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
111 return FALSE;
113 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
114 !(template32 = LockResource( hDlgTmpl32 )))
116 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
117 return FALSE;
119 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
120 hGlobal16 = GlobalAlloc16(0, size);
121 if (!hGlobal16)
123 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
124 ERR("alloc failure for %ld bytes\n", size);
125 return FALSE;
127 lfr->template = GlobalLock16(hGlobal16);
128 if (!lfr->template)
130 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
131 ERR("global lock failure for %x handle\n", hGlobal16);
132 GlobalFree16(hGlobal16);
133 return FALSE;
135 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)lfr->template);
136 lfr->hDlgTmpl16 = hGlobal16;
137 lfr->hGlobal16 = hGlobal16;
139 return TRUE;
143 /***********************************************************************
144 * FINDDLG_FreeResources [internal]
146 * Free resources allocated
148 void FINDDLG_FreeResources(LFRPRIVATE lfr)
150 /* free resources */
151 if (lfr->fr16->Flags & FR_ENABLETEMPLATEHANDLE)
152 GlobalUnlock16(lfr->fr16->hInstance);
153 if (lfr->hResource16)
155 GlobalUnlock16(lfr->hResource16);
156 FreeResource16(lfr->hResource16);
158 if (lfr->hGlobal16)
160 GlobalUnlock16(lfr->hGlobal16);
161 GlobalFree16(lfr->hGlobal16);
165 /***********************************************************************
166 * FindText (COMMDLG.11)
168 HWND16 WINAPI FindText16( SEGPTR find )
170 HANDLE16 hInst;
171 HWND16 ret = 0;
172 FARPROC16 ptr;
173 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
175 if (!lfr) return 0;
176 lfr->fr16 = MapSL(find);
177 lfr->find = TRUE;
178 if (FINDDLG_Get16BitsTemplate(lfr))
180 hInst = GetWindowLongA( HWND_32(lfr->fr16->hwndOwner), GWL_HINSTANCE);
181 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 13);
182 ret = CreateDialogIndirectParam16( hInst, lfr->template,
183 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
184 FINDDLG_FreeResources(lfr);
186 HeapFree(GetProcessHeap(), 0, lfr);
187 return ret;
191 /***********************************************************************
192 * ReplaceText (COMMDLG.12)
194 HWND16 WINAPI ReplaceText16( SEGPTR find )
196 HANDLE16 hInst;
197 HWND16 ret = 0;
198 FARPROC16 ptr;
199 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
201 if (!lfr) return 0;
203 * FIXME : We should do error checking on the lpFind structure here
204 * and make CommDlgExtendedError() return the error condition.
206 lfr->fr16 = MapSL(find);
207 lfr->find = FALSE;
208 if (FINDDLG_Get16BitsTemplate(lfr))
210 hInst = GetWindowLongA( HWND_32(lfr->fr16->hwndOwner), GWL_HINSTANCE);
211 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 14);
212 ret = CreateDialogIndirectParam16( hInst, lfr->template,
213 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
215 FINDDLG_FreeResources(lfr);
217 HeapFree(GetProcessHeap(), 0, lfr);
218 return ret;
222 /***********************************************************************
223 * FINDDLG_WMInitDialog [internal]
225 static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags,
226 LPSTR lpstrFindWhat, BOOL fUnicode)
228 SetWindowLongA(hWnd, DWL_USER, lParam);
229 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
231 * FIXME : If the initial FindWhat string is empty, we should disable the
232 * FindNext (IDOK) button. Only after typing some text, the button should be
233 * enabled.
235 if (fUnicode) SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
236 else SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
237 CheckRadioButton(hWnd, rad1, rad2, (*lpFlags & FR_DOWN) ? rad2 : rad1);
238 if (*lpFlags & (FR_HIDEUPDOWN | FR_NOUPDOWN)) {
239 EnableWindow(GetDlgItem(hWnd, rad1), FALSE);
240 EnableWindow(GetDlgItem(hWnd, rad2), FALSE);
242 if (*lpFlags & FR_HIDEUPDOWN) {
243 ShowWindow(GetDlgItem(hWnd, rad1), SW_HIDE);
244 ShowWindow(GetDlgItem(hWnd, rad2), SW_HIDE);
245 ShowWindow(GetDlgItem(hWnd, grp1), SW_HIDE);
247 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
248 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
249 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
250 if (*lpFlags & FR_HIDEWHOLEWORD)
251 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
252 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
253 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
254 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
255 if (*lpFlags & FR_HIDEMATCHCASE)
256 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
257 if (!(*lpFlags & FR_SHOWHELP)) {
258 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
259 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
261 ShowWindow(hWnd, SW_SHOWNORMAL);
262 return TRUE;
266 /***********************************************************************
267 * FINDDLG_WMCommand [internal]
269 static LRESULT FINDDLG_WMCommand(HWND hWnd, WPARAM wParam,
270 HWND hwndOwner, LPDWORD lpFlags,
271 LPSTR lpstrFindWhat, WORD wFindWhatLen,
272 BOOL fUnicode)
274 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
275 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
277 switch (wParam) {
278 case IDOK:
279 if (fUnicode)
280 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
281 else GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
282 if (IsDlgButtonChecked(hWnd, rad2))
283 *lpFlags |= FR_DOWN;
284 else *lpFlags &= ~FR_DOWN;
285 if (IsDlgButtonChecked(hWnd, chx1))
286 *lpFlags |= FR_WHOLEWORD;
287 else *lpFlags &= ~FR_WHOLEWORD;
288 if (IsDlgButtonChecked(hWnd, chx2))
289 *lpFlags |= FR_MATCHCASE;
290 else *lpFlags &= ~FR_MATCHCASE;
291 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
292 *lpFlags |= FR_FINDNEXT;
293 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
294 GetWindowLongA(hWnd, DWL_USER) );
295 return TRUE;
296 case IDCANCEL:
297 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
298 *lpFlags |= FR_DIALOGTERM;
299 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
300 GetWindowLongA(hWnd, DWL_USER) );
301 DestroyWindow(hWnd);
302 return TRUE;
303 case pshHelp:
304 /* FIXME : should lpfr structure be passed as an argument ??? */
305 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
306 return TRUE;
308 return FALSE;
312 /***********************************************************************
313 * FindTextDlgProc (COMMDLG.13)
315 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
316 LPARAM lParam)
318 HWND hWnd = HWND_32(hWnd16);
319 LPFINDREPLACE16 lpfr;
320 switch (wMsg) {
321 case WM_INITDIALOG:
322 lpfr=MapSL(lParam);
323 return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags),
324 MapSL(lpfr->lpstrFindWhat), FALSE);
325 case WM_COMMAND:
326 lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER));
327 return FINDDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
328 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
329 lpfr->wFindWhatLen, FALSE);
331 return FALSE;
335 /***********************************************************************
336 * REPLACEDLG_WMInitDialog [internal]
338 static LRESULT REPLACEDLG_WMInitDialog(HWND hWnd, LPARAM lParam,
339 LPDWORD lpFlags, LPSTR lpstrFindWhat,
340 LPSTR lpstrReplaceWith, BOOL fUnicode)
342 SetWindowLongA(hWnd, DWL_USER, lParam);
343 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
345 * FIXME : If the initial FindWhat string is empty, we should disable the FinNext /
346 * Replace / ReplaceAll buttons. Only after typing some text, the buttons should be
347 * enabled.
349 if (fUnicode)
351 SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
352 SetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith);
353 } else
355 SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
356 SetDlgItemTextA(hWnd, edt2, lpstrReplaceWith);
358 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
359 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
360 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
361 if (*lpFlags & FR_HIDEWHOLEWORD)
362 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
363 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
364 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
365 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
366 if (*lpFlags & FR_HIDEMATCHCASE)
367 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
368 if (!(*lpFlags & FR_SHOWHELP)) {
369 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
370 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
372 ShowWindow(hWnd, SW_SHOWNORMAL);
373 return TRUE;
377 /***********************************************************************
378 * REPLACEDLG_WMCommand [internal]
380 static LRESULT REPLACEDLG_WMCommand(HWND hWnd, WPARAM16 wParam,
381 HWND hwndOwner, LPDWORD lpFlags,
382 LPSTR lpstrFindWhat, WORD wFindWhatLen,
383 LPSTR lpstrReplaceWith, WORD wReplaceWithLen,
384 BOOL fUnicode)
386 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
387 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
389 switch (wParam) {
390 case IDOK:
391 if (fUnicode)
393 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
394 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
395 } else
397 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
398 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
400 if (IsDlgButtonChecked(hWnd, chx1))
401 *lpFlags |= FR_WHOLEWORD;
402 else *lpFlags &= ~FR_WHOLEWORD;
403 if (IsDlgButtonChecked(hWnd, chx2))
404 *lpFlags |= FR_MATCHCASE;
405 else *lpFlags &= ~FR_MATCHCASE;
406 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
407 *lpFlags |= FR_FINDNEXT;
408 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
409 GetWindowLongA(hWnd, DWL_USER) );
410 return TRUE;
411 case IDCANCEL:
412 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
413 *lpFlags |= FR_DIALOGTERM;
414 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
415 GetWindowLongA(hWnd, DWL_USER) );
416 DestroyWindow(hWnd);
417 return TRUE;
418 case psh1:
419 if (fUnicode)
421 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
422 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
423 } else
425 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
426 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
428 if (IsDlgButtonChecked(hWnd, chx1))
429 *lpFlags |= FR_WHOLEWORD;
430 else *lpFlags &= ~FR_WHOLEWORD;
431 if (IsDlgButtonChecked(hWnd, chx2))
432 *lpFlags |= FR_MATCHCASE;
433 else *lpFlags &= ~FR_MATCHCASE;
434 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM);
435 *lpFlags |= FR_REPLACE;
436 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
437 GetWindowLongA(hWnd, DWL_USER) );
438 return TRUE;
439 case psh2:
440 if (fUnicode)
442 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
443 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
444 } else
446 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
447 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
449 if (IsDlgButtonChecked(hWnd, chx1))
450 *lpFlags |= FR_WHOLEWORD;
451 else *lpFlags &= ~FR_WHOLEWORD;
452 if (IsDlgButtonChecked(hWnd, chx2))
453 *lpFlags |= FR_MATCHCASE;
454 else *lpFlags &= ~FR_MATCHCASE;
455 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM);
456 *lpFlags |= FR_REPLACEALL;
457 SendMessageA(hwndOwner, uFindReplaceMessage, 0,
458 GetWindowLongA(hWnd, DWL_USER) );
459 return TRUE;
460 case pshHelp:
461 /* FIXME : should lpfr structure be passed as an argument ??? */
462 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
463 return TRUE;
465 return FALSE;
469 /***********************************************************************
470 * ReplaceTextDlgProc (COMMDLG.14)
472 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
473 LPARAM lParam)
475 HWND hWnd = HWND_32(hWnd16);
476 LPFINDREPLACE16 lpfr;
477 switch (wMsg) {
478 case WM_INITDIALOG:
479 lpfr=MapSL(lParam);
480 return REPLACEDLG_WMInitDialog(hWnd, lParam, &lpfr->Flags,
481 MapSL(lpfr->lpstrFindWhat),
482 MapSL(lpfr->lpstrReplaceWith), FALSE);
483 case WM_COMMAND:
484 lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER));
485 return REPLACEDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
486 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
487 lpfr->wFindWhatLen, MapSL(lpfr->lpstrReplaceWith),
488 lpfr->wReplaceWithLen, FALSE);
490 return FALSE;