]> git.saurik.com Git - wxWidgets.git/blame - src/msw/fdrepdlg.cpp
changed Replace and Remove to always use EM_REPLACESEL instead of
[wxWidgets.git] / src / msw / fdrepdlg.cpp
CommitLineData
c41b00c9
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/fdrepdlg.cpp
3// Purpose: wxFindReplaceDialog class
8db37e06
VZ
4// Author: Markus Greither and Vadim Zeitlin
5// Modified by:
c41b00c9
VZ
6// Created: 23/03/2001
7// RCS-ID:
8// Copyright: (c) Markus Greither
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
8db37e06 21 #pragma implementation "mswfdrepdlg.h"
c41b00c9
VZ
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#if wxUSE_FINDREPLDLG
32
33#ifndef WX_PRECOMP
34 #include "wx/intl.h"
35 #include "wx/log.h"
36#endif
37
38#include "wx/msw/private.h"
39
40#if !defined(__WIN32__) || defined(__SALFORDC__) || defined(__WXWINE__)
41 #include <commdlg.h>
42#endif
43
44#include "wx/fdrepdlg.h"
45
46// ----------------------------------------------------------------------------
47// functions prototypes
48// ----------------------------------------------------------------------------
49
761989ff 50LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
c41b00c9
VZ
51 WPARAM wParam, LPARAM lParam);
52
53UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
54 UINT uiMsg,
55 WPARAM wParam,
56 LPARAM lParam);
57
58// ----------------------------------------------------------------------------
59// wxWin macros
60// ----------------------------------------------------------------------------
61
62IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
63
c41b00c9
VZ
64// ----------------------------------------------------------------------------
65// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
66// ----------------------------------------------------------------------------
67
68class WXDLLEXPORT wxFindReplaceDialogImpl
69{
70public:
71 wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, int flagsWX);
72 ~wxFindReplaceDialogImpl();
73
74 void InitFindWhat(const wxString& str);
75 void InitReplaceWith(const wxString& str);
76
77 void SubclassDialog(HWND hwnd);
78
79 static UINT GetFindDialogMessage() { return ms_msgFindDialog; }
80
81 // only for passing to ::FindText or ::ReplaceText
82 FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; }
83
84private:
85 void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
86
87 // the owner of the dialog
88 HWND m_hwndOwner;
89
90 // the previous window proc of our owner
91 WNDPROC m_oldParentWndProc;
92
93 // the find replace data used by the dialog
94 FINDREPLACE m_findReplace;
95
96 // registered Message for Dialog
97 static UINT ms_msgFindDialog;
98};
99
100UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;
101
102// ============================================================================
103// implementation
104// ============================================================================
105
106// ----------------------------------------------------------------------------
107// wxFindReplaceDialogImpl
108// ----------------------------------------------------------------------------
109
110wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
111 int flagsWX)
112{
113 // get the identifier for the find dialog message if we don't have it yet
114 if ( !ms_msgFindDialog )
115 {
116 ms_msgFindDialog = ::RegisterWindowMessage(FINDMSGSTRING);
117
118 if ( !ms_msgFindDialog )
119 {
120 wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
121 }
122 }
123
124 m_hwndOwner = NULL;
125 m_oldParentWndProc = NULL;
126
127 wxZeroMemory(m_findReplace);
128
761989ff 129 // translate the flags: first the dialog creation flags
c41b00c9
VZ
130
131 // always set this to be able to set the title
132 int flags = FR_ENABLEHOOK;
133
761989ff
VZ
134 int flagsDialog = dialog->GetWindowStyle();
135 if ( flagsDialog & wxFR_NOMATCHCASE)
c41b00c9 136 flags |= FR_NOMATCHCASE;
761989ff 137 if ( flagsDialog & wxFR_NOWHOLEWORD)
c41b00c9 138 flags |= FR_NOWHOLEWORD;
761989ff 139 if ( flagsDialog & wxFR_NOUPDOWN)
c41b00c9 140 flags |= FR_NOUPDOWN;
761989ff
VZ
141
142 // and now the flags governing the initial values of the dialogs controls
c41b00c9
VZ
143 if ( flagsWX & wxFR_DOWN)
144 flags |= FR_DOWN;
761989ff
VZ
145 if ( flagsWX & wxFR_MATCHCASE)
146 flags |= FR_MATCHCASE;
147 if ( flagsWX & wxFR_WHOLEWORD )
148 flags |= FR_WHOLEWORD;
c41b00c9
VZ
149
150 m_findReplace.lStructSize = sizeof(FINDREPLACE);
151 m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent());
152 m_findReplace.Flags = flags;
153
154 m_findReplace.lCustData = (LPARAM)dialog;
155 m_findReplace.lpfnHook = wxFindReplaceDialogHookProc;
156}
157
158void wxFindReplaceDialogImpl::InitString(const wxString& str,
159 LPTSTR *ppStr, WORD *pLen)
160{
161 size_t len = str.length() + 1;
162 if ( len < 80 )
163 {
164 // MSDN docs say that the buffer must be at least 80 chars
165 len = 80;
166 }
167
168 *ppStr = new wxChar[len];
169 wxStrcpy(*ppStr, str);
170 *pLen = len;
171}
172
173void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
174{
175 InitString(str, &m_findReplace.lpstrFindWhat, &m_findReplace.wFindWhatLen);
176}
177
178void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
179{
180 InitString(str,
181 &m_findReplace.lpstrReplaceWith,
182 &m_findReplace.wReplaceWithLen);
183}
184
185void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
186{
187 m_hwndOwner = hwnd;
761989ff
VZ
188
189 // check that we don't subclass the parent twice: this would be a bad idea
190 // as then we'd have infinite recursion in wxFindReplaceWindowProc
191 WNDPROC oldParentWndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
192
193 if ( oldParentWndProc != wxFindReplaceWindowProc )
194 {
195 // save old wnd proc elsewhere to access it from
196 // wxFindReplaceWindowProc
197 m_oldParentWndProc = oldParentWndProc;
198 (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)oldParentWndProc);
199
200 // and set the new one
201 (void)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wxFindReplaceWindowProc);
202 }
c41b00c9
VZ
203}
204
205wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
206{
207 delete [] m_findReplace.lpstrFindWhat;
208 delete [] m_findReplace.lpstrReplaceWith;
209
210 if ( m_hwndOwner )
211 {
212 ::SetWindowLong(m_hwndOwner, GWL_WNDPROC, (LONG)m_oldParentWndProc);
213 }
214}
215
216// ----------------------------------------------------------------------------
217// Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
218// ----------------------------------------------------------------------------
219
761989ff
VZ
220LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
221 WPARAM wParam, LPARAM lParam)
c41b00c9
VZ
222{
223 if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
224 {
225 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
226 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
227
228 // map flags from Windows
229 wxEventType evtType;
230
231 bool replace = FALSE;
232 if ( pFR->Flags & FR_DIALOGTERM )
233 {
234 evtType = wxEVT_COMMAND_FIND_CLOSE;
235 }
236 else if ( pFR->Flags & FR_FINDNEXT )
237 {
238 evtType = wxEVT_COMMAND_FIND_NEXT;
239 }
240 else if ( pFR->Flags & FR_REPLACE )
241 {
761989ff 242 evtType = wxEVT_COMMAND_FIND_REPLACE;
c41b00c9
VZ
243
244 replace = TRUE;
245 }
246 else if ( pFR->Flags & FR_REPLACEALL )
247 {
761989ff 248 evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
c41b00c9
VZ
249
250 replace = TRUE;
251 }
252 else
253 {
254 wxFAIL_MSG( _T("unknown find dialog event") );
255
256 return 0;
257 }
258
259 wxUint32 flags = 0;
260 if ( pFR->Flags & FR_DOWN )
261 flags |= wxFR_DOWN;
262 if ( pFR->Flags & FR_WHOLEWORD )
263 flags |= wxFR_WHOLEWORD;
264 if ( pFR->Flags & FR_MATCHCASE )
265 flags |= wxFR_MATCHCASE;
266
267 wxFindDialogEvent event(evtType, dialog->GetId());
761989ff 268 event.SetEventObject(dialog);
c41b00c9
VZ
269 event.SetFlags(flags);
270 event.SetFindString(pFR->lpstrFindWhat);
271 if ( replace )
272 {
273 event.SetReplaceString(pFR->lpstrReplaceWith);
274 }
275
8db37e06 276 dialog->Send(event);
c41b00c9
VZ
277 }
278
279 WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
280
761989ff
VZ
281 // sanity check
282 wxASSERT_MSG( wndProc != wxFindReplaceWindowProc,
283 _T("infinite recursion detected") );
284
c41b00c9 285 return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
761989ff 286}
c41b00c9
VZ
287
288// ----------------------------------------------------------------------------
289// Find/replace dialog hook proc
290// ----------------------------------------------------------------------------
291
292UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
293 UINT uiMsg,
294 WPARAM WXUNUSED(wParam),
295 LPARAM lParam)
296{
297 if ( uiMsg == WM_INITDIALOG )
298 {
299 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
300 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
301
302 ::SetWindowText(hwnd, dialog->GetTitle());
303
304 // don't return FALSE from here or the dialog won't be shown
305 return TRUE;
306 }
307
308 return 0;
309}
310
311// ============================================================================
312// wxFindReplaceDialog implementation
313// ============================================================================
314
315// ----------------------------------------------------------------------------
316// wxFindReplaceDialog ctors/dtor
317// ----------------------------------------------------------------------------
318
319void wxFindReplaceDialog::Init()
320{
321 m_impl = NULL;
322 m_FindReplaceData = NULL;
323
324 // as we're created in the hidden state, bring the internal flag in sync
325 m_isShown = FALSE;
326}
327
328wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
329 wxFindReplaceData *data,
761989ff
VZ
330 const wxString &title,
331 int flags)
c41b00c9
VZ
332 : m_FindReplaceData(data)
333{
334 Init();
335
761989ff 336 (void)Create(parent, data, title, flags);
c41b00c9
VZ
337}
338
339wxFindReplaceDialog::~wxFindReplaceDialog()
340{
761989ff 341 // unsubclass the parent
c41b00c9 342 delete m_impl;
761989ff
VZ
343
344 // prevent the base class dtor from trying to hide us!
345 m_isShown = FALSE;
346
347 // and from destroying our window
348 m_hWnd = NULL;
c41b00c9
VZ
349}
350
351bool wxFindReplaceDialog::Create(wxWindow *parent,
352 wxFindReplaceData *data,
761989ff
VZ
353 const wxString &title,
354 int flags)
c41b00c9 355{
761989ff 356 m_windowStyle = flags;
c41b00c9
VZ
357 m_FindReplaceData = data;
358 m_parent = parent;
359
360 SetTitle(title);
361
362 // we must have a parent as it will get the messages from us
363 return parent != NULL;
364}
365
366// ----------------------------------------------------------------------------
367// wxFindReplaceDialog data access
368// ----------------------------------------------------------------------------
369
370void wxFindReplaceDialog::SetData(wxFindReplaceData *data)
371{
372 delete m_FindReplaceData;
373 m_FindReplaceData = data;
374}
375
376// ----------------------------------------------------------------------------
377// wxFindReplaceData show/hide
378// ----------------------------------------------------------------------------
379
380bool wxFindReplaceDialog::Show(bool show)
381{
382 if ( !wxWindowBase::Show(show) )
383 {
384 // visibility status didn't change
385 return FALSE;
386 }
387
388 // do we already have the dialog window?
389 if ( m_hWnd )
390 {
391 // yes, just use it
761989ff
VZ
392 (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
393
394 return TRUE;
c41b00c9
VZ
395 }
396
397 if ( !show )
398 {
399 // well, it doesn't exist which is as good as being hidden
400 return TRUE;
401 }
402
403 wxCHECK_MSG( m_FindReplaceData, FALSE, _T("call Create() first!") );
404
405 wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
406
761989ff 407 m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags());
c41b00c9
VZ
408
409 m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
410
761989ff
VZ
411 bool replace = HasFlag(wxFR_REPLACEDIALOG);
412 if ( replace )
c41b00c9 413 {
761989ff 414 m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString());
c41b00c9
VZ
415 }
416
417 // call the right function to show the dialog which does what we want
761989ff
VZ
418 FINDREPLACE *pFR = m_impl->GetPtrFindReplace();
419 HWND hwnd;
420 if ( replace )
421 hwnd = ::ReplaceText(pFR);
422 else
423 hwnd = ::FindText(pFR);
424
425 if ( !hwnd )
c41b00c9
VZ
426 {
427 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
428 ::CommDlgExtendedError());
429
430 delete m_impl;
431 m_impl = NULL;
432
433 return FALSE;
434 }
435
436 // subclass parent window in order to get FINDMSGSTRING message
437 m_impl->SubclassDialog(GetHwndOf(m_parent));
438
761989ff 439 if ( !::ShowWindow(hwnd, SW_SHOW) )
c41b00c9
VZ
440 {
441 wxLogLastError(_T("ShowWindow(find dialog)"));
442 }
443
761989ff
VZ
444 m_hWnd = (WXHWND)hwnd;
445
c41b00c9
VZ
446 return TRUE;
447}
448
449// ----------------------------------------------------------------------------
450// wxFindReplaceDialog title handling
451// ----------------------------------------------------------------------------
452
453// we set the title of this dialog in our jook proc but for now don't crash in
454// the base class version because of m_hWnd == 0
455
456void wxFindReplaceDialog::SetTitle( const wxString& title)
457{
458 m_title = title;
459}
460
461wxString wxFindReplaceDialog::GetTitle() const
462{
463 return m_title;
464}
465
466// ----------------------------------------------------------------------------
467// wxFindReplaceDialog position/size
468// ----------------------------------------------------------------------------
469
470void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
471 int WXUNUSED(width), int WXUNUSED(height),
472 int WXUNUSED(sizeFlags))
473{
474 // ignore - we can't change the size of this standard dialog
475 return;
476}
477
478// NB: of course, both of these functions are completely bogus, but it's better
479// than nothing
480void wxFindReplaceDialog::DoGetSize(int *width, int *height) const
481{
482 // the standard dialog size
483 if ( width )
484 *width = 225;
485 if ( height )
486 *height = 324;
487}
488
489void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const
490{
491 // the standard dialog size
492 if ( width )
493 *width = 219;
494 if ( height )
495 *height = 299;
496}
497
498#endif // wxUSE_FINDREPLDLG
499