source: trunk/src/comdlg32/finddlg32.cpp@ 2013

Last change on this file since 2013 was 1557, checked in by sandervl, 26 years ago

Wine 991031 update

File size: 17.9 KB
Line 
1/* $Id: finddlg32.cpp,v 1.2 1999-11-02 20:37:43 sandervl Exp $ */
2/*
3 * Common Dialog Boxes interface (32 bit) (990815)
4 * Find/Replace
5 *
6 * Copyright 1998,1999 Bertho A. Stultiens
7 */
8
9// ><DJR 17.05.99 Force to use C-interfaces for now to prevent CALLBACK definition compiler error
10#define CINTERFACE 1
11#include <os2win.h>
12#include "winuser.h"
13#include "commdlg.h"
14#include "cderr.h"
15#include "dlgs.h"
16#include "debugtools.h"
17#include <heapstring.h>
18
19DEFAULT_DEBUG_CHANNEL(commdlg)
20
21#include "cdlg.h"
22
23
24/*-----------------------------------------------------------------------*/
25
26static UINT FindReplaceMessage;
27static UINT HelpMessage;
28
29#define FR_MASK (FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD | FR_REPLACEALL | FR_REPLACE | FR_FINDNEXT | FR_DIALOGTERM)
30/* CRITICAL_SECTION COMDLG32_CritSect; */
31
32/* Notes:
33 * MS uses a critical section at a few locations. However, I fail to
34 * see the reason for this. Their comdlg32.dll has a few race conditions
35 * but _not_ at those places that are protected with the mutex (there are
36 * globals that seem to hold info for the wndproc).
37 *
38 * FindText32x/ReplaceText32x
39 * The find/replace calls are passed a structure that is _not_ used
40 * internally. There is a local copy that holds the running info to
41 * be able to combine xxx32A and xxx32W calls. The passed pointer is
42 * returned upon sendmessage. Apps wont break this way when they rely
43 * on the original pointer. This will work as long as the sizes of
44 * FINDREPLACE32A == FINDREPLACE32W. The local copy will also prevent
45 * the app to see the wine-specific extra flags to distinguish between
46 * A/W and Find/Replace.
47 */
48
49
50/***********************************************************************
51 * COMDLG32_FR_GetFlags [internal]
52 * Returns the button state that needs to be reported to the caller.
53 * RETURNS
54 * Current state of check and radio buttons
55 */
56static DWORD COMDLG32_FR_GetFlags(HWND hDlgWnd)
57{
58 DWORD flags = 0;
59 if(IsDlgButtonChecked(hDlgWnd, rad2) == BST_CHECKED)
60 flags |= FR_DOWN;
61 if(IsDlgButtonChecked(hDlgWnd, chx1) == BST_CHECKED)
62 flags |= FR_WHOLEWORD;
63 if(IsDlgButtonChecked(hDlgWnd, chx2) == BST_CHECKED)
64 flags |= FR_MATCHCASE;
65 return flags;
66}
67
68/***********************************************************************
69 * COMDLG32_FR_HandleWMCommand [internal]
70 * Handle WM_COMMAND messages...
71 */
72static void COMDLG32_FR_HandleWMCommand(HWND hDlgWnd, COMDLG32_FR_Data *pData, int Id, int NotifyCode)
73{
74 DWORD flag;
75
76 pData->user_fr.fra->Flags &= ~FR_MASK; /* Clear return flags */
77 if(pData->fr.Flags & FR_WINE_REPLACE) /* Replace always goes down... */
78 pData->user_fr.fra->Flags |= FR_DOWN;
79
80 if(NotifyCode == BN_CLICKED)
81 {
82 switch(Id)
83 {
84 case IDOK: /* Find Next */
85 if(GetDlgItemTextA(hDlgWnd, edt1, pData->fr.lpstrFindWhat, pData->fr.wFindWhatLen) > 0)
86 {
87 pData->user_fr.fra->Flags |= COMDLG32_FR_GetFlags(hDlgWnd) | FR_FINDNEXT;
88 if(pData->fr.Flags & FR_WINE_UNICODE)
89 {
90 lstrcpyAtoW(pData->user_fr.frw->lpstrFindWhat, pData->fr.lpstrFindWhat);
91 }
92 else
93 {
94 lstrcpyA(pData->user_fr.fra->lpstrFindWhat, pData->fr.lpstrFindWhat);
95 }
96 SendMessageA(pData->fr.hwndOwner, FindReplaceMessage, 0, (LPARAM)pData->user_fr.fra);
97 }
98 break;
99
100 case IDCANCEL:
101 pData->user_fr.fra->Flags |= COMDLG32_FR_GetFlags(hDlgWnd) | FR_DIALOGTERM;
102 SendMessageA(pData->fr.hwndOwner, FindReplaceMessage, 0, (LPARAM)pData->user_fr.fra);
103 DestroyWindow(hDlgWnd);
104 break;
105
106 case psh2: /* Replace All */
107 flag = FR_REPLACEALL;
108 goto Replace;
109
110 case psh1: /* Replace */
111 flag = FR_REPLACE;
112Replace:
113 if((pData->fr.Flags & FR_WINE_REPLACE)
114 && GetDlgItemTextA(hDlgWnd, edt1, pData->fr.lpstrFindWhat, pData->fr.wFindWhatLen) > 0)
115 {
116 pData->fr.lpstrReplaceWith[0] = 0; /* In case the next GetDlgItemText Fails */
117 GetDlgItemTextA(hDlgWnd, edt2, pData->fr.lpstrReplaceWith, pData->fr.wReplaceWithLen);
118 pData->user_fr.fra->Flags |= COMDLG32_FR_GetFlags(hDlgWnd) | flag;
119 if(pData->fr.Flags & FR_WINE_UNICODE)
120 {
121 lstrcpyAtoW(pData->user_fr.frw->lpstrFindWhat, pData->fr.lpstrFindWhat);
122 lstrcpyAtoW(pData->user_fr.frw->lpstrReplaceWith, pData->fr.lpstrReplaceWith);
123 }
124 else
125 {
126 lstrcpyA(pData->user_fr.fra->lpstrFindWhat, pData->fr.lpstrFindWhat);
127 lstrcpyA(pData->user_fr.fra->lpstrReplaceWith, pData->fr.lpstrReplaceWith);
128 }
129 SendMessageA(pData->fr.hwndOwner, FindReplaceMessage, 0, (LPARAM)pData->user_fr.fra);
130 }
131 break;
132
133 case pshHelp:
134 pData->user_fr.fra->Flags |= COMDLG32_FR_GetFlags(hDlgWnd);
135 SendMessageA(pData->fr.hwndOwner, HelpMessage, (WPARAM)hDlgWnd, (LPARAM)pData->user_fr.fra);
136 break;
137 }
138 }
139 else if(NotifyCode == EN_CHANGE && Id == edt1)
140 {
141 BOOL enable = SendDlgItemMessageA(hDlgWnd, edt1, WM_GETTEXTLENGTH, 0, 0) > 0;
142 EnableWindow(GetDlgItem(hDlgWnd, IDOK), enable);
143 if(pData->fr.Flags & FR_WINE_REPLACE)
144 {
145 EnableWindow(GetDlgItem(hDlgWnd, psh1), enable);
146 EnableWindow(GetDlgItem(hDlgWnd, psh2), enable);
147 }
148 }
149}
150
151/***********************************************************************
152 * COMDLG32_FindReplaceDlgProc [internal]
153 * [Find/Replace]Text32[A/W] window procedure.
154 */
155static BOOL CALLBACK COMDLG32_FindReplaceDlgProc(HWND hDlgWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
156{
157 COMDLG32_FR_Data *pdata = (COMDLG32_FR_Data *)GetPropA(hDlgWnd, (LPSTR)COMDLG32_Atom);
158 BOOL retval = TRUE;;
159
160 if(iMsg == WM_INITDIALOG)
161 {
162 pdata = (COMDLG32_FR_Data *)lParam;
163 if(!SetPropA(hDlgWnd, (LPSTR)COMDLG32_Atom, (HANDLE)pdata))
164 {
165 ERR("Could not Set prop; invent a gracefull exit?...\n");
166 DestroyWindow(hDlgWnd);
167 return FALSE;
168 }
169 SendDlgItemMessageA(hDlgWnd, edt1, EM_SETLIMITTEXT, (WPARAM)pdata->fr.wFindWhatLen, 0);
170 SendDlgItemMessageA(hDlgWnd, edt1, WM_SETTEXT, 0, (LPARAM)pdata->fr.lpstrFindWhat);
171 if(pdata->fr.Flags & FR_WINE_REPLACE)
172 {
173 SendDlgItemMessageA(hDlgWnd, edt2, EM_SETLIMITTEXT, (WPARAM)pdata->fr.wReplaceWithLen, 0);
174 SendDlgItemMessageA(hDlgWnd, edt2, WM_SETTEXT, 0, (LPARAM)pdata->fr.lpstrReplaceWith);
175 }
176
177 if(!(pdata->fr.Flags & FR_SHOWHELP))
178 ShowWindow(GetDlgItem(hDlgWnd, pshHelp), SW_HIDE);
179 if(pdata->fr.Flags & FR_HIDEUPDOWN)
180 {
181 ShowWindow(GetDlgItem(hDlgWnd, rad1), SW_HIDE);
182 ShowWindow(GetDlgItem(hDlgWnd, rad2), SW_HIDE);
183 ShowWindow(GetDlgItem(hDlgWnd, grp1), SW_HIDE);
184 }
185 else if(pdata->fr.Flags & FR_NOUPDOWN)
186 {
187 EnableWindow(GetDlgItem(hDlgWnd, rad1), FALSE);
188 EnableWindow(GetDlgItem(hDlgWnd, rad2), FALSE);
189 EnableWindow(GetDlgItem(hDlgWnd, grp1), FALSE);
190 }
191 else
192 {
193 SendDlgItemMessageA(hDlgWnd, rad1, BM_SETCHECK, pdata->fr.Flags & FR_DOWN ? 0 : BST_CHECKED, 0);
194 SendDlgItemMessageA(hDlgWnd, rad2, BM_SETCHECK, pdata->fr.Flags & FR_DOWN ? BST_CHECKED : 0, 0);
195 }
196
197 if(pdata->fr.Flags & FR_HIDEMATCHCASE)
198 ShowWindow(GetDlgItem(hDlgWnd, chx2), SW_HIDE);
199 else if(pdata->fr.Flags & FR_NOMATCHCASE)
200 EnableWindow(GetDlgItem(hDlgWnd, chx2), FALSE);
201 else
202 SendDlgItemMessageA(hDlgWnd, chx2, BM_SETCHECK, pdata->fr.Flags & FR_MATCHCASE ? BST_CHECKED : 0, 0);
203
204 if(pdata->fr.Flags & FR_HIDEWHOLEWORD)
205 ShowWindow(GetDlgItem(hDlgWnd, chx1), SW_HIDE);
206 else if(pdata->fr.Flags & FR_NOWHOLEWORD)
207 EnableWindow(GetDlgItem(hDlgWnd, chx1), FALSE);
208 else
209 SendDlgItemMessageA(hDlgWnd, chx1, BM_SETCHECK, pdata->fr.Flags & FR_WHOLEWORD ? BST_CHECKED : 0, 0);
210
211 /* We did the init here, now call the hook if requested */
212#ifdef __WIN32OS2__
213 //SvL: If hooked and hook returns TRUE, then show dialog
214 // -> if not hooked, just display it!
215 if(!(pdata->fr.Flags & FR_ENABLEHOOK) ||
216 pdata->fr.lpfnHook(hDlgWnd, iMsg, wParam, pdata->fr.lCustData))
217#else
218 if((pdata->fr.Flags & FR_ENABLEHOOK)
219 && pdata->fr.lpfnHook(hDlgWnd, iMsg, wParam, pdata->fr.lCustData))
220#endif
221 {
222 ShowWindow(hDlgWnd, SW_SHOWNORMAL);
223 UpdateWindow(hDlgWnd);
224 }
225 /* else the caller is responsible for showing */
226 return TRUE;
227 }
228
229 if(pdata && (pdata->fr.Flags & FR_ENABLEHOOK))
230 {
231 retval = pdata->fr.lpfnHook(hDlgWnd, iMsg, wParam, lParam);
232 }
233 else
234 retval = FALSE;
235
236 if(pdata && !retval)
237 {
238 retval = TRUE;
239 switch(iMsg)
240 {
241 case WM_COMMAND:
242 COMDLG32_FR_HandleWMCommand(hDlgWnd, pdata, LOWORD(wParam), HIWORD(wParam));
243 break;
244
245 case WM_CLOSE:
246 COMDLG32_FR_HandleWMCommand(hDlgWnd, pdata, IDCANCEL, BN_CLICKED);
247 break;
248
249 case WM_HELP:
250 /* Heeeeelp! */
251 FIXME("Got WM_HELP. Who is gonna supply it?\n");
252 break;
253
254 case WM_CONTEXTMENU:
255 /* Heeeeelp! */
256 FIXME("Got WM_CONTEXTMENU. Who is gonna supply it?\n");
257 break;
258 /* FIXME: Handle F1 help */
259
260 default:
261 retval = FALSE; /* We did not handle the message */
262 }
263 }
264
265 /* WM_DESTROY is a special case.
266 * We need to ensure that the allocated memory is freed just before
267 * the dialog is killed. We also need to remove the added prop.
268 */
269 if(iMsg == WM_DESTROY)
270 {
271 RemovePropA(hDlgWnd, (LPSTR)COMDLG32_Atom);
272 HeapFree(GetProcessHeap(), 0, pdata);
273 }
274
275 return retval;
276}
277
278/***********************************************************************
279 * COMDLG32_FR_CheckPartial [internal]
280 * Check various fault conditions in the supplied parameters that
281 * cause an extended error to be reported.
282 * RETURNS
283 * TRUE: Succes
284 * FALSE: Failure
285 */
286static BOOL COMDLG32_FR_CheckPartial(
287 LPFINDREPLACEA pfr, /* [in] Find structure */
288 BOOL Replace /* [in] True if called as replace */
289) {
290 if(!pfr)
291 {
292 COMDLG32_SetCommDlgExtendedError(CDERR_GENERALCODES);
293 return FALSE;
294 }
295
296 if(pfr->lStructSize != sizeof(FINDREPLACEA))
297 {
298 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
299 return FALSE;
300 }
301
302 if(!IsWindow(pfr->hwndOwner))
303 {
304 COMDLG32_SetCommDlgExtendedError(CDERR_DIALOGFAILURE);
305 return FALSE;
306 }
307
308#ifdef __WIN32OS2__
309 //SvL: Notepad set this to 32
310 if((!pfr->lpstrFindWhat)
311#else
312 if((pfr->wFindWhatLen < 80 || !pfr->lpstrFindWhat)
313#endif
314 ||(Replace && (pfr->wReplaceWithLen < 80 || !pfr->lpstrReplaceWith)))
315 {
316 COMDLG32_SetCommDlgExtendedError(FRERR_BUFFERLENGTHZERO);
317 return FALSE;
318 }
319
320 if((FindReplaceMessage = RegisterWindowMessageA(FINDMSGSTRING)) == 0)
321 {
322 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
323 return FALSE;
324 }
325 if((HelpMessage = RegisterWindowMessageA(HELPMSGSTRING)) == 0)
326 {
327 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
328 return FALSE;
329 }
330
331 if((pfr->Flags & FR_ENABLEHOOK) && !pfr->lpfnHook)
332 {
333 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
334 return FALSE;
335 }
336
337 if((pfr->Flags & (FR_ENABLETEMPLATE | FR_ENABLETEMPLATEHANDLE)) && !pfr->hInstance)
338 {
339 COMDLG32_SetCommDlgExtendedError(CDERR_NOHINSTANCE);
340 return FALSE;
341 }
342
343 if((pfr->Flags & FR_ENABLETEMPLATE) && !pfr->lpTemplateName)
344 {
345 COMDLG32_SetCommDlgExtendedError(CDERR_NOTEMPLATE);
346 return FALSE;
347 }
348
349 return TRUE;
350}
351
352/***********************************************************************
353 * COMDLG32_FR_DoFindReplace [internal]
354 * Actual load and creation of the Find/Replace dialog.
355 * RETURNS
356 * Window handle to created dialog:Succes
357 * NULL:Failure
358 */
359static HWND COMDLG32_FR_DoFindReplace(
360 COMDLG32_FR_Data *pdata /* [in] Internal data structure */
361) {
362 HWND hdlgwnd = 0;
363 HGLOBAL loadrc;
364 DWORD error;
365 LPDLGTEMPLATEW rcs;
366
367 TRACE("hInst=%08x, Flags=%08lx\n", pdata->fr.hInstance, pdata->fr.Flags);
368
369 if(!(pdata->fr.Flags & FR_ENABLETEMPLATEHANDLE))
370 {
371 HMODULE hmod = COMDLG32_hInstance;
372 HRSRC htemplate;
373 if(pdata->fr.Flags & FR_ENABLETEMPLATE)
374 {
375 hmod = (HMODULE)pdata->fr.hInstance;
376 if(pdata->fr.Flags & FR_WINE_UNICODE)
377 {
378 htemplate = FindResourceW(hmod, (LPWSTR)pdata->fr.lpTemplateName, (LPWSTR)RT_DIALOGA);
379 }
380 else
381 {
382 htemplate = FindResourceA(hmod, pdata->fr.lpTemplateName, (LPCSTR)RT_DIALOGA);
383 }
384 }
385 else
386 {
387 int rcid = pdata->fr.Flags & FR_WINE_REPLACE ? REPLACEDLGORD
388 : FINDDLGORD;
389 htemplate = FindResourceA(hmod, MAKEINTRESOURCEA(rcid), (LPCSTR)RT_DIALOGA);
390 }
391 if(!htemplate)
392 {
393 error = CDERR_FINDRESFAILURE;
394 goto cleanup;
395 }
396
397 loadrc = LoadResource(hmod, htemplate);
398 }
399 else
400 {
401 loadrc = (HGLOBAL)pdata->fr.hInstance;
402 }
403
404 if(!loadrc)
405 {
406 error = CDERR_LOADRESFAILURE;
407 goto cleanup;
408 }
409
410 if((rcs = (LPDLGTEMPLATEW)LockResource(loadrc)) == NULL)
411 {
412 error = CDERR_LOCKRESFAILURE;
413 goto cleanup;
414 }
415
416 hdlgwnd = CreateDialogIndirectParamA(COMDLG32_hInstance,
417 rcs,
418 pdata->fr.hwndOwner,
419 (DLGPROC)COMDLG32_FindReplaceDlgProc,
420 (LPARAM)pdata);
421 if(!hdlgwnd)
422 {
423 error = CDERR_DIALOGFAILURE;
424cleanup:
425 COMDLG32_SetCommDlgExtendedError(error);
426 HeapFree(GetProcessHeap(), 0, pdata);
427 }
428 return hdlgwnd;
429}
430
431/***********************************************************************
432 * FindText32A [COMDLG32.6]
433 * RETURNS
434 * Window handle to created dialog: Succes
435 * NULL: Failure
436 */
437HWND WINAPI FindTextA(
438 LPFINDREPLACEA pfr /* [in] Find/replace structure*/
439) {
440 COMDLG32_FR_Data *pdata;
441
442 dprintf(("FindTextA: LPFINDREPLACE=%p\n", pfr));
443
444 if(!COMDLG32_FR_CheckPartial(pfr, FALSE))
445 return 0;
446
447 if((pdata = (COMDLG32_FR_Data *)COMDLG32_AllocMem(sizeof(COMDLG32_FR_Data))) == NULL)
448 return 0; /* Error has been set */
449
450 pdata->user_fr.fra = pfr;
451 pdata->fr = *pfr;
452 return COMDLG32_FR_DoFindReplace(pdata);
453}
454
455/***********************************************************************
456 * ReplaceText32A [COMDLG32.19]
457 * RETURNS
458 * Window handle to created dialog: Succes
459 * NULL: Failure
460 */
461HWND WINAPI ReplaceTextA(
462 LPFINDREPLACEA pfr /* [in] Find/replace structure*/
463) {
464 COMDLG32_FR_Data *pdata;
465
466 dprintf(("ReplaceTextA: LPFINDREPLACE=%p\n", pfr));
467
468 if(!COMDLG32_FR_CheckPartial(pfr, TRUE))
469 return 0;
470
471 if((pdata = (COMDLG32_FR_Data *)COMDLG32_AllocMem(sizeof(COMDLG32_FR_Data))) == NULL)
472 return 0; /* Error has been set */
473
474 pdata->user_fr.fra = pfr;
475 pdata->fr = *pfr;
476 pdata->fr.Flags |= FR_WINE_REPLACE;
477 return COMDLG32_FR_DoFindReplace(pdata);
478}
479
480/***********************************************************************
481 * FinfText32W [COMDLG32.7]
482 * RETURNS
483 * Window handle to created dialog: Succes
484 * NULL: Failure
485 */
486HWND WINAPI FindTextW(
487 LPFINDREPLACEW pfr /* [in] Find/replace structure*/
488) {
489 COMDLG32_FR_Data *pdata;
490
491 dprintf(("FindTextW: LPFINDREPLACE=%p\n", pfr));
492
493 if(!COMDLG32_FR_CheckPartial((LPFINDREPLACEA)pfr, FALSE))
494 return 0;
495
496 if((pdata = (COMDLG32_FR_Data *)COMDLG32_AllocMem(sizeof(COMDLG32_FR_Data)
497 + pfr->wFindWhatLen)) == NULL)
498 return 0; /* Error has been set */
499
500 pdata->user_fr.frw = pfr;
501 pdata->fr = *(LPFINDREPLACEA)pfr; /* FINDREPLACEx have same size */
502 pdata->fr.Flags |= FR_WINE_UNICODE;
503 pdata->fr.lpstrFindWhat = (LPSTR)(((LPFINDREPLACEA)(pdata+1))+1); /* Set string pointer */
504 lstrcpynWtoA(pdata->fr.lpstrFindWhat, pfr->lpstrFindWhat, pfr->wFindWhatLen);
505 return COMDLG32_FR_DoFindReplace(pdata);
506}
507
508/***********************************************************************
509 * ReplaceTextW [COMDLG32.20]
510 * RETURNS
511 * Window handle to created dialog: Succes
512 * NULL: Failure
513 */
514HWND WINAPI ReplaceTextW(
515 LPFINDREPLACEW pfr /* [in] Find/replace structure*/
516) {
517 COMDLG32_FR_Data *pdata;
518
519 dprintf(("ReplaceTextW: LPFINDREPLACE=%p\n", pfr));
520
521 if(!COMDLG32_FR_CheckPartial((LPFINDREPLACEA)pfr, FALSE))
522 return 0;
523
524 if((pdata = (COMDLG32_FR_Data *)COMDLG32_AllocMem(sizeof(COMDLG32_FR_Data)
525 + pfr->wFindWhatLen
526 + pfr->wReplaceWithLen)) == NULL)
527
528 return 0; /* Error has been set */
529
530 pdata->user_fr.frw = pfr;
531 pdata->fr = *(LPFINDREPLACEA)pfr; /* FINDREPLACEx have same size */
532 pdata->fr.Flags |= FR_WINE_REPLACE | FR_WINE_UNICODE;
533 pdata->fr.lpstrFindWhat = (LPSTR)(((LPFINDREPLACEA)(pdata+1))+1); /* Set string pointers */
534 pdata->fr.lpstrReplaceWith = (LPSTR)(((LPFINDREPLACEA)(pdata+1))+1) + pfr->wFindWhatLen;
535 lstrcpynWtoA(pdata->fr.lpstrFindWhat, pfr->lpstrFindWhat, pfr->wFindWhatLen);
536 lstrcpynWtoA(pdata->fr.lpstrReplaceWith, pfr->lpstrReplaceWith, pfr->wReplaceWithLen);
537 return COMDLG32_FR_DoFindReplace(pdata);
538}
539
540
Note: See TracBrowser for help on using the repository browser.