Update structure
[reactos.git] / reactos / dll / win32 / comdlg32 / finddlg.c
1 /*
2 * COMMDLG - 16 bits Find & Replace Text 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
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"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
37
38 #include "cdlg.h"
39 #include "cdlg16.h"
40
41 struct FRPRIVATE
42 {
43 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
44 HANDLE16 hResource16; /* handle for allocated resource 16 */
45 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
46 LPCVOID template; /* template for 32 bits resource */
47 BOOL find; /* TRUE if find dialog, FALSE if replace dialog */
48 FINDREPLACE16 *fr16;
49 };
50
51 #define LFRPRIVATE struct FRPRIVATE *
52
53 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
54 LPARAM lParam);
55 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
56 LPARAM lParam);
57
58 /***********************************************************************
59 * FINDDLG_Get16BitsTemplate [internal]
60 *
61 * Get a template (FALSE if failure) when 16 bits dialogs are used
62 * by a 16 bits application
63 * FIXME : no test was done for the user-provided template cases
64 */
65 static BOOL FINDDLG_Get16BitsTemplate(LFRPRIVATE lfr)
66 {
67 LPFINDREPLACE16 fr16 = lfr->fr16;
68
69 if (fr16->Flags & FR_ENABLETEMPLATEHANDLE)
70 {
71 lfr->template = GlobalLock16(fr16->hInstance);
72 if (!lfr->template)
73 {
74 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
75 return FALSE;
76 }
77 }
78 else if (fr16->Flags & FR_ENABLETEMPLATE)
79 {
80 HANDLE16 hResInfo;
81 if (!(hResInfo = FindResource16(fr16->hInstance,
82 MapSL(fr16->lpTemplateName),
83 (LPSTR)RT_DIALOG)))
84 {
85 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
86 return FALSE;
87 }
88 if (!(lfr->hDlgTmpl16 = LoadResource16( fr16->hInstance, hResInfo )))
89 {
90 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
91 return FALSE;
92 }
93 lfr->hResource16 = lfr->hDlgTmpl16;
94 lfr->template = LockResource16(lfr->hResource16);
95 if (!lfr->template)
96 {
97 FreeResource16(lfr->hResource16);
98 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
99 return FALSE;
100 }
101 }
102 else
103 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
104 HRSRC hResInfo;
105 HGLOBAL hDlgTmpl32;
106 LPCVOID template32;
107 DWORD size;
108 HGLOBAL16 hGlobal16;
109
110 if (!(hResInfo = FindResourceA(COMDLG32_hInstance,
111 lfr->find ?
112 MAKEINTRESOURCEA(FINDDLGORD):MAKEINTRESOURCEA(REPLACEDLGORD),
113 (LPSTR)RT_DIALOG)))
114 {
115 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
116 return FALSE;
117 }
118 if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo )) ||
119 !(template32 = LockResource( hDlgTmpl32 )))
120 {
121 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
122 return FALSE;
123 }
124 size = SizeofResource(COMDLG32_hInstance, hResInfo);
125 hGlobal16 = GlobalAlloc16(0, size);
126 if (!hGlobal16)
127 {
128 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
129 ERR("alloc failure for %ld bytes\n", size);
130 return FALSE;
131 }
132 lfr->template = GlobalLock16(hGlobal16);
133 if (!lfr->template)
134 {
135 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
136 ERR("global lock failure for %x handle\n", hGlobal16);
137 GlobalFree16(hGlobal16);
138 return FALSE;
139 }
140 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)lfr->template);
141 lfr->hDlgTmpl16 = hGlobal16;
142 lfr->hGlobal16 = hGlobal16;
143 }
144 return TRUE;
145 }
146
147
148 /***********************************************************************
149 * FINDDLG_FreeResources [internal]
150 *
151 * Free resources allocated
152 */
153 static void FINDDLG_FreeResources(LFRPRIVATE lfr)
154 {
155 /* free resources */
156 if (lfr->fr16->Flags & FR_ENABLETEMPLATEHANDLE)
157 GlobalUnlock16(lfr->fr16->hInstance);
158 if (lfr->hResource16)
159 {
160 GlobalUnlock16(lfr->hResource16);
161 FreeResource16(lfr->hResource16);
162 }
163 if (lfr->hGlobal16)
164 {
165 GlobalUnlock16(lfr->hGlobal16);
166 GlobalFree16(lfr->hGlobal16);
167 }
168 }
169
170 /***********************************************************************
171 * FindText (COMMDLG.11)
172 */
173 HWND16 WINAPI FindText16( SEGPTR find )
174 {
175 HANDLE16 hInst;
176 HWND16 ret = 0;
177 FARPROC16 ptr;
178 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
179
180 if (!lfr) return 0;
181 lfr->fr16 = MapSL(find);
182 lfr->find = TRUE;
183 if (FINDDLG_Get16BitsTemplate(lfr))
184 {
185 hInst = GetWindowLongPtrA( HWND_32(lfr->fr16->hwndOwner), GWLP_HINSTANCE);
186 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 13);
187 ret = CreateDialogIndirectParam16( hInst, lfr->template,
188 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
189 FINDDLG_FreeResources(lfr);
190 }
191 HeapFree(GetProcessHeap(), 0, lfr);
192 return ret;
193 }
194
195
196 /***********************************************************************
197 * ReplaceText (COMMDLG.12)
198 */
199 HWND16 WINAPI ReplaceText16( SEGPTR find )
200 {
201 HANDLE16 hInst;
202 HWND16 ret = 0;
203 FARPROC16 ptr;
204 LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
205
206 if (!lfr) return 0;
207 /*
208 * FIXME : We should do error checking on the lpFind structure here
209 * and make CommDlgExtendedError() return the error condition.
210 */
211 lfr->fr16 = MapSL(find);
212 lfr->find = FALSE;
213 if (FINDDLG_Get16BitsTemplate(lfr))
214 {
215 hInst = GetWindowLongPtrA( HWND_32(lfr->fr16->hwndOwner), GWLP_HINSTANCE);
216 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 14);
217 ret = CreateDialogIndirectParam16( hInst, lfr->template,
218 lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
219
220 FINDDLG_FreeResources(lfr);
221 }
222 HeapFree(GetProcessHeap(), 0, lfr);
223 return ret;
224 }
225
226
227 /***********************************************************************
228 * FINDDLG_WMInitDialog [internal]
229 */
230 static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags,
231 LPSTR lpstrFindWhat, BOOL fUnicode)
232 {
233 SetWindowLongPtrW(hWnd, DWLP_USER, lParam);
234 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
235 /*
236 * FIXME : If the initial FindWhat string is empty, we should disable the
237 * FindNext (IDOK) button. Only after typing some text, the button should be
238 * enabled.
239 */
240 if (fUnicode) SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
241 else SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
242 CheckRadioButton(hWnd, rad1, rad2, (*lpFlags & FR_DOWN) ? rad2 : rad1);
243 if (*lpFlags & (FR_HIDEUPDOWN | FR_NOUPDOWN)) {
244 EnableWindow(GetDlgItem(hWnd, rad1), FALSE);
245 EnableWindow(GetDlgItem(hWnd, rad2), FALSE);
246 }
247 if (*lpFlags & FR_HIDEUPDOWN) {
248 ShowWindow(GetDlgItem(hWnd, rad1), SW_HIDE);
249 ShowWindow(GetDlgItem(hWnd, rad2), SW_HIDE);
250 ShowWindow(GetDlgItem(hWnd, grp1), SW_HIDE);
251 }
252 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
253 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
254 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
255 if (*lpFlags & FR_HIDEWHOLEWORD)
256 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
257 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
258 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
259 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
260 if (*lpFlags & FR_HIDEMATCHCASE)
261 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
262 if (!(*lpFlags & FR_SHOWHELP)) {
263 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
264 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
265 }
266 ShowWindow(hWnd, SW_SHOWNORMAL);
267 return TRUE;
268 }
269
270
271 /***********************************************************************
272 * FINDDLG_WMCommand [internal]
273 */
274 static LRESULT FINDDLG_WMCommand(HWND hWnd, WPARAM wParam,
275 HWND hwndOwner, LPDWORD lpFlags,
276 LPSTR lpstrFindWhat, WORD wFindWhatLen,
277 BOOL fUnicode)
278 {
279 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
280 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
281
282 switch (wParam) {
283 case IDOK:
284 if (fUnicode)
285 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
286 else GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
287 if (IsDlgButtonChecked(hWnd, rad2))
288 *lpFlags |= FR_DOWN;
289 else *lpFlags &= ~FR_DOWN;
290 if (IsDlgButtonChecked(hWnd, chx1))
291 *lpFlags |= FR_WHOLEWORD;
292 else *lpFlags &= ~FR_WHOLEWORD;
293 if (IsDlgButtonChecked(hWnd, chx2))
294 *lpFlags |= FR_MATCHCASE;
295 else *lpFlags &= ~FR_MATCHCASE;
296 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
297 *lpFlags |= FR_FINDNEXT;
298 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
299 GetWindowLongPtrW(hWnd, DWLP_USER) );
300 return TRUE;
301 case IDCANCEL:
302 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
303 *lpFlags |= FR_DIALOGTERM;
304 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
305 GetWindowLongPtrW(hWnd, DWLP_USER) );
306 DestroyWindow(hWnd);
307 return TRUE;
308 case pshHelp:
309 /* FIXME : should lpfr structure be passed as an argument ??? */
310 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
311 return TRUE;
312 }
313 return FALSE;
314 }
315
316
317 /***********************************************************************
318 * FindTextDlgProc (COMMDLG.13)
319 */
320 BOOL16 CALLBACK FindTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
321 LPARAM lParam)
322 {
323 HWND hWnd = HWND_32(hWnd16);
324 LPFINDREPLACE16 lpfr;
325 switch (wMsg) {
326 case WM_INITDIALOG:
327 lpfr=MapSL(lParam);
328 return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags),
329 MapSL(lpfr->lpstrFindWhat), FALSE);
330 case WM_COMMAND:
331 lpfr=MapSL(GetWindowLongPtrW(hWnd, DWLP_USER));
332 return FINDDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
333 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
334 lpfr->wFindWhatLen, FALSE);
335 }
336 return FALSE;
337 }
338
339
340 /***********************************************************************
341 * REPLACEDLG_WMInitDialog [internal]
342 */
343 static LRESULT REPLACEDLG_WMInitDialog(HWND hWnd, LPARAM lParam,
344 LPDWORD lpFlags, LPSTR lpstrFindWhat,
345 LPSTR lpstrReplaceWith, BOOL fUnicode)
346 {
347 SetWindowLongPtrW(hWnd, DWLP_USER, lParam);
348 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
349 /*
350 * FIXME : If the initial FindWhat string is empty, we should disable the FinNext /
351 * Replace / ReplaceAll buttons. Only after typing some text, the buttons should be
352 * enabled.
353 */
354 if (fUnicode)
355 {
356 SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
357 SetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith);
358 } else
359 {
360 SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
361 SetDlgItemTextA(hWnd, edt2, lpstrReplaceWith);
362 }
363 CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
364 if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
365 EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
366 if (*lpFlags & FR_HIDEWHOLEWORD)
367 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
368 CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
369 if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
370 EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
371 if (*lpFlags & FR_HIDEMATCHCASE)
372 ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
373 if (!(*lpFlags & FR_SHOWHELP)) {
374 EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
375 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
376 }
377 ShowWindow(hWnd, SW_SHOWNORMAL);
378 return TRUE;
379 }
380
381
382 /***********************************************************************
383 * REPLACEDLG_WMCommand [internal]
384 */
385 static LRESULT REPLACEDLG_WMCommand(HWND hWnd, WPARAM16 wParam,
386 HWND hwndOwner, LPDWORD lpFlags,
387 LPSTR lpstrFindWhat, WORD wFindWhatLen,
388 LPSTR lpstrReplaceWith, WORD wReplaceWithLen,
389 BOOL fUnicode)
390 {
391 int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRINGA );
392 int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRINGA );
393
394 switch (wParam) {
395 case IDOK:
396 if (fUnicode)
397 {
398 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
399 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
400 } else
401 {
402 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
403 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
404 }
405 if (IsDlgButtonChecked(hWnd, chx1))
406 *lpFlags |= FR_WHOLEWORD;
407 else *lpFlags &= ~FR_WHOLEWORD;
408 if (IsDlgButtonChecked(hWnd, chx2))
409 *lpFlags |= FR_MATCHCASE;
410 else *lpFlags &= ~FR_MATCHCASE;
411 *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
412 *lpFlags |= FR_FINDNEXT;
413 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
414 GetWindowLongPtrW(hWnd, DWLP_USER) );
415 return TRUE;
416 case IDCANCEL:
417 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
418 *lpFlags |= FR_DIALOGTERM;
419 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
420 GetWindowLongPtrW(hWnd, DWLP_USER) );
421 DestroyWindow(hWnd);
422 return TRUE;
423 case psh1:
424 if (fUnicode)
425 {
426 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
427 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
428 } else
429 {
430 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
431 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
432 }
433 if (IsDlgButtonChecked(hWnd, chx1))
434 *lpFlags |= FR_WHOLEWORD;
435 else *lpFlags &= ~FR_WHOLEWORD;
436 if (IsDlgButtonChecked(hWnd, chx2))
437 *lpFlags |= FR_MATCHCASE;
438 else *lpFlags &= ~FR_MATCHCASE;
439 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM);
440 *lpFlags |= FR_REPLACE;
441 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
442 GetWindowLongPtrW(hWnd, DWLP_USER) );
443 return TRUE;
444 case psh2:
445 if (fUnicode)
446 {
447 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
448 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
449 } else
450 {
451 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
452 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
453 }
454 if (IsDlgButtonChecked(hWnd, chx1))
455 *lpFlags |= FR_WHOLEWORD;
456 else *lpFlags &= ~FR_WHOLEWORD;
457 if (IsDlgButtonChecked(hWnd, chx2))
458 *lpFlags |= FR_MATCHCASE;
459 else *lpFlags &= ~FR_MATCHCASE;
460 *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM);
461 *lpFlags |= FR_REPLACEALL;
462 SendMessageW( hwndOwner, uFindReplaceMessage, 0,
463 GetWindowLongPtrW(hWnd, DWLP_USER) );
464 return TRUE;
465 case pshHelp:
466 /* FIXME : should lpfr structure be passed as an argument ??? */
467 SendMessageA(hwndOwner, uHelpMessage, 0, 0);
468 return TRUE;
469 }
470 return FALSE;
471 }
472
473
474 /***********************************************************************
475 * ReplaceTextDlgProc (COMMDLG.14)
476 */
477 BOOL16 CALLBACK ReplaceTextDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
478 LPARAM lParam)
479 {
480 HWND hWnd = HWND_32(hWnd16);
481 LPFINDREPLACE16 lpfr;
482 switch (wMsg) {
483 case WM_INITDIALOG:
484 lpfr=MapSL(lParam);
485 return REPLACEDLG_WMInitDialog(hWnd, lParam, &lpfr->Flags,
486 MapSL(lpfr->lpstrFindWhat),
487 MapSL(lpfr->lpstrReplaceWith), FALSE);
488 case WM_COMMAND:
489 lpfr=MapSL(GetWindowLongPtrW(hWnd, DWLP_USER));
490 return REPLACEDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner),
491 &lpfr->Flags, MapSL(lpfr->lpstrFindWhat),
492 lpfr->wFindWhatLen, MapSL(lpfr->lpstrReplaceWith),
493 lpfr->wReplaceWithLen, FALSE);
494 }
495 return FALSE;
496 }