]> git.saurik.com Git - wxWidgets.git/blame - src/msw/fdrepdlg.cpp
removed extra semicolons added by previous patch (patch 1429906)
[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
65571936 9// Licence: wxWindows licence
c41b00c9
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c41b00c9
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_FINDREPLDLG
28
29#ifndef WX_PRECOMP
30 #include "wx/intl.h"
31 #include "wx/log.h"
32#endif
33
660296aa 34#include "wx/msw/wrapcdlg.h"
c41b00c9
VZ
35#include "wx/fdrepdlg.h"
36
37// ----------------------------------------------------------------------------
38// functions prototypes
39// ----------------------------------------------------------------------------
40
761989ff 41LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
c41b00c9
VZ
42 WPARAM wParam, LPARAM lParam);
43
975b6bcf
VZ
44UINT_PTR CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
45 UINT uiMsg,
46 WPARAM wParam,
47 LPARAM lParam);
c41b00c9
VZ
48
49// ----------------------------------------------------------------------------
50// wxWin macros
51// ----------------------------------------------------------------------------
52
53IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
54
c41b00c9
VZ
55// ----------------------------------------------------------------------------
56// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
57// ----------------------------------------------------------------------------
58
59class WXDLLEXPORT wxFindReplaceDialogImpl
60{
61public:
62 wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, int flagsWX);
63 ~wxFindReplaceDialogImpl();
64
65 void InitFindWhat(const wxString& str);
66 void InitReplaceWith(const wxString& str);
67
68 void SubclassDialog(HWND hwnd);
69
70 static UINT GetFindDialogMessage() { return ms_msgFindDialog; }
71
72 // only for passing to ::FindText or ::ReplaceText
73 FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; }
74
14fca738 75 // set/query the "closed by user" flag
cbe874bd 76 void SetClosedByUser() { m_wasClosedByUser = true; }
14fca738
VZ
77 bool WasClosedByUser() const { return m_wasClosedByUser; }
78
c41b00c9
VZ
79private:
80 void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
81
82 // the owner of the dialog
83 HWND m_hwndOwner;
84
85 // the previous window proc of our owner
86 WNDPROC m_oldParentWndProc;
87
88 // the find replace data used by the dialog
89 FINDREPLACE m_findReplace;
90
cbe874bd 91 // true if the user closed us, false otherwise
14fca738
VZ
92 bool m_wasClosedByUser;
93
c41b00c9
VZ
94 // registered Message for Dialog
95 static UINT ms_msgFindDialog;
22f3361e
VZ
96
97 DECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl)
c41b00c9
VZ
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
cbe874bd 127 m_wasClosedByUser = false;
14fca738 128
c41b00c9
VZ
129 wxZeroMemory(m_findReplace);
130
761989ff 131 // translate the flags: first the dialog creation flags
c41b00c9
VZ
132
133 // always set this to be able to set the title
134 int flags = FR_ENABLEHOOK;
135
761989ff
VZ
136 int flagsDialog = dialog->GetWindowStyle();
137 if ( flagsDialog & wxFR_NOMATCHCASE)
c41b00c9 138 flags |= FR_NOMATCHCASE;
761989ff 139 if ( flagsDialog & wxFR_NOWHOLEWORD)
c41b00c9 140 flags |= FR_NOWHOLEWORD;
761989ff 141 if ( flagsDialog & wxFR_NOUPDOWN)
c41b00c9 142 flags |= FR_NOUPDOWN;
761989ff
VZ
143
144 // and now the flags governing the initial values of the dialogs controls
c41b00c9
VZ
145 if ( flagsWX & wxFR_DOWN)
146 flags |= FR_DOWN;
761989ff
VZ
147 if ( flagsWX & wxFR_MATCHCASE)
148 flags |= FR_MATCHCASE;
149 if ( flagsWX & wxFR_WHOLEWORD )
150 flags |= FR_WHOLEWORD;
c41b00c9
VZ
151
152 m_findReplace.lStructSize = sizeof(FINDREPLACE);
153 m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent());
154 m_findReplace.Flags = flags;
155
156 m_findReplace.lCustData = (LPARAM)dialog;
157 m_findReplace.lpfnHook = wxFindReplaceDialogHookProc;
158}
159
160void wxFindReplaceDialogImpl::InitString(const wxString& str,
161 LPTSTR *ppStr, WORD *pLen)
162{
163 size_t len = str.length() + 1;
164 if ( len < 80 )
165 {
166 // MSDN docs say that the buffer must be at least 80 chars
167 len = 80;
168 }
169
170 *ppStr = new wxChar[len];
171 wxStrcpy(*ppStr, str);
5c519b6c 172 *pLen = (WORD)len;
c41b00c9
VZ
173}
174
175void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
176{
177 InitString(str, &m_findReplace.lpstrFindWhat, &m_findReplace.wFindWhatLen);
178}
179
180void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
181{
182 InitString(str,
183 &m_findReplace.lpstrReplaceWith,
184 &m_findReplace.wReplaceWithLen);
185}
186
187void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
188{
189 m_hwndOwner = hwnd;
761989ff
VZ
190
191 // check that we don't subclass the parent twice: this would be a bad idea
192 // as then we'd have infinite recursion in wxFindReplaceWindowProc
4ff53d1b
VZ
193 wxCHECK_RET( wxGetWindowProc(hwnd) !=
194 wx_reinterpret_cast(void *, wxFindReplaceWindowProc),
cba1c2ca 195 _T("can't have more than one find dialog currently") );
975b6bcf 196
cba1c2ca
VZ
197 // set the new one and save the old as user data to allow access to it
198 // from wxFindReplaceWindowProc
199 m_oldParentWndProc = wxSetWindowProc(hwnd, wxFindReplaceWindowProc);
200
201 wxSetWindowUserData(hwnd, (void *)m_oldParentWndProc);
c41b00c9
VZ
202}
203
204wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
205{
206 delete [] m_findReplace.lpstrFindWhat;
207 delete [] m_findReplace.lpstrReplaceWith;
208
209 if ( m_hwndOwner )
210 {
975b6bcf
VZ
211 // undo subclassing
212 wxSetWindowProc(m_hwndOwner, m_oldParentWndProc);
c41b00c9
VZ
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 222{
ea392212
VZ
223#if wxUSE_UNICODE_MSLU
224 static unsigned long s_lastMsgFlags = 0;
225
226 // This flag helps us to identify the bogus ANSI message
227 // sent by UNICOWS.DLL (see below)
228 // while we're sending our message to the dialog
229 // we ignore possible messages sent in between
230 static bool s_blockMsg = false;
231#endif // wxUSE_UNICODE_MSLU
232
c41b00c9
VZ
233 if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
234 {
235 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
ea392212
VZ
236
237#if wxUSE_UNICODE_MSLU
238 // This is a hack for a MSLU problem: Versions up to 1.0.4011
239 // of UNICOWS.DLL send the correct UNICODE item after button press
240 // and a bogus ANSI mode item right after this, so lets ignore
241 // the second bogus message
ac9251e3 242 if ( wxUsingUnicowsDll() && s_lastMsgFlags == pFR->Flags )
ea392212
VZ
243 {
244 s_lastMsgFlags = 0;
245 return 0;
246 }
247 s_lastMsgFlags = pFR->Flags;
248#endif // wxUSE_UNICODE_MSLU
249
c41b00c9
VZ
250 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
251
252 // map flags from Windows
253 wxEventType evtType;
254
cbe874bd 255 bool replace = false;
c41b00c9
VZ
256 if ( pFR->Flags & FR_DIALOGTERM )
257 {
14fca738
VZ
258 // we have to notify the dialog that it's being closed by user and
259 // not deleted programmatically as it behaves differently in these
260 // 2 cases
261 dialog->GetImpl()->SetClosedByUser();
262
c41b00c9
VZ
263 evtType = wxEVT_COMMAND_FIND_CLOSE;
264 }
265 else if ( pFR->Flags & FR_FINDNEXT )
266 {
267 evtType = wxEVT_COMMAND_FIND_NEXT;
268 }
269 else if ( pFR->Flags & FR_REPLACE )
270 {
761989ff 271 evtType = wxEVT_COMMAND_FIND_REPLACE;
c41b00c9 272
cbe874bd 273 replace = true;
c41b00c9
VZ
274 }
275 else if ( pFR->Flags & FR_REPLACEALL )
276 {
761989ff 277 evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
c41b00c9 278
cbe874bd 279 replace = true;
c41b00c9
VZ
280 }
281 else
282 {
283 wxFAIL_MSG( _T("unknown find dialog event") );
284
285 return 0;
286 }
287
288 wxUint32 flags = 0;
289 if ( pFR->Flags & FR_DOWN )
290 flags |= wxFR_DOWN;
291 if ( pFR->Flags & FR_WHOLEWORD )
292 flags |= wxFR_WHOLEWORD;
293 if ( pFR->Flags & FR_MATCHCASE )
294 flags |= wxFR_MATCHCASE;
295
296 wxFindDialogEvent event(evtType, dialog->GetId());
761989ff 297 event.SetEventObject(dialog);
c41b00c9
VZ
298 event.SetFlags(flags);
299 event.SetFindString(pFR->lpstrFindWhat);
300 if ( replace )
301 {
302 event.SetReplaceString(pFR->lpstrReplaceWith);
303 }
304
ea392212
VZ
305#if wxUSE_UNICODE_MSLU
306 s_blockMsg = true;
307#endif // wxUSE_UNICODE_MSLU
308
8db37e06 309 dialog->Send(event);
ea392212
VZ
310
311#if wxUSE_UNICODE_MSLU
312 s_blockMsg = false;
313#endif // wxUSE_UNICODE_MSLU
c41b00c9 314 }
ea392212
VZ
315#if wxUSE_UNICODE_MSLU
316 else if ( !s_blockMsg )
317 s_lastMsgFlags = 0;
318#endif // wxUSE_UNICODE_MSLU
c41b00c9 319
975b6bcf 320 WNDPROC wndProc = (WNDPROC)wxGetWindowUserData(hwnd);
c41b00c9 321
761989ff
VZ
322 // sanity check
323 wxASSERT_MSG( wndProc != wxFindReplaceWindowProc,
324 _T("infinite recursion detected") );
325
c41b00c9 326 return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
761989ff 327}
c41b00c9
VZ
328
329// ----------------------------------------------------------------------------
330// Find/replace dialog hook proc
331// ----------------------------------------------------------------------------
332
975b6bcf
VZ
333UINT_PTR CALLBACK
334wxFindReplaceDialogHookProc(HWND hwnd,
335 UINT uiMsg,
336 WPARAM WXUNUSED(wParam),
337 LPARAM lParam)
c41b00c9
VZ
338{
339 if ( uiMsg == WM_INITDIALOG )
340 {
341 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
342 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
343
344 ::SetWindowText(hwnd, dialog->GetTitle());
345
346 // don't return FALSE from here or the dialog won't be shown
347 return TRUE;
348 }
349
350 return 0;
351}
352
353// ============================================================================
354// wxFindReplaceDialog implementation
355// ============================================================================
356
357// ----------------------------------------------------------------------------
358// wxFindReplaceDialog ctors/dtor
359// ----------------------------------------------------------------------------
360
361void wxFindReplaceDialog::Init()
362{
363 m_impl = NULL;
364 m_FindReplaceData = NULL;
365
366 // as we're created in the hidden state, bring the internal flag in sync
cbe874bd 367 m_isShown = false;
c41b00c9
VZ
368}
369
370wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
371 wxFindReplaceData *data,
761989ff
VZ
372 const wxString &title,
373 int flags)
208c5141 374 : wxFindReplaceDialogBase(parent, data, title, flags)
c41b00c9
VZ
375{
376 Init();
377
761989ff 378 (void)Create(parent, data, title, flags);
c41b00c9
VZ
379}
380
381wxFindReplaceDialog::~wxFindReplaceDialog()
382{
14fca738
VZ
383 // the dialog might have been already deleted if the user closed it
384 // manually but in this case we should have got a notification about it and
385 // the flagmust have been set
386 if ( !m_impl->WasClosedByUser() )
387 {
388 // if it wasn't, delete the dialog ourselves
389 if ( !::DestroyWindow(GetHwnd()) )
390 {
391 wxLogLastError(_T("DestroyWindow(find dialog)"));
392 }
393 }
394
761989ff 395 // unsubclass the parent
c41b00c9 396 delete m_impl;
761989ff
VZ
397
398 // prevent the base class dtor from trying to hide us!
cbe874bd 399 m_isShown = false;
761989ff 400
14fca738 401 // and from destroying our window [again]
44d5b352 402 m_hWnd = (WXHWND)NULL;
c41b00c9
VZ
403}
404
405bool wxFindReplaceDialog::Create(wxWindow *parent,
406 wxFindReplaceData *data,
761989ff
VZ
407 const wxString &title,
408 int flags)
c41b00c9 409{
761989ff 410 m_windowStyle = flags;
c41b00c9
VZ
411 m_FindReplaceData = data;
412 m_parent = parent;
413
414 SetTitle(title);
415
416 // we must have a parent as it will get the messages from us
417 return parent != NULL;
418}
419
c41b00c9
VZ
420// ----------------------------------------------------------------------------
421// wxFindReplaceData show/hide
422// ----------------------------------------------------------------------------
423
424bool wxFindReplaceDialog::Show(bool show)
425{
426 if ( !wxWindowBase::Show(show) )
427 {
428 // visibility status didn't change
cbe874bd 429 return false;
c41b00c9
VZ
430 }
431
432 // do we already have the dialog window?
433 if ( m_hWnd )
434 {
435 // yes, just use it
761989ff
VZ
436 (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
437
cbe874bd 438 return true;
c41b00c9
VZ
439 }
440
441 if ( !show )
442 {
443 // well, it doesn't exist which is as good as being hidden
cbe874bd 444 return true;
c41b00c9
VZ
445 }
446
cbe874bd 447 wxCHECK_MSG( m_FindReplaceData, false, _T("call Create() first!") );
c41b00c9
VZ
448
449 wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
450
761989ff 451 m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags());
c41b00c9
VZ
452
453 m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
454
761989ff
VZ
455 bool replace = HasFlag(wxFR_REPLACEDIALOG);
456 if ( replace )
c41b00c9 457 {
761989ff 458 m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString());
c41b00c9
VZ
459 }
460
461 // call the right function to show the dialog which does what we want
761989ff
VZ
462 FINDREPLACE *pFR = m_impl->GetPtrFindReplace();
463 HWND hwnd;
464 if ( replace )
465 hwnd = ::ReplaceText(pFR);
466 else
467 hwnd = ::FindText(pFR);
468
469 if ( !hwnd )
c41b00c9
VZ
470 {
471 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
472 ::CommDlgExtendedError());
473
474 delete m_impl;
475 m_impl = NULL;
476
cbe874bd 477 return false;
c41b00c9
VZ
478 }
479
480 // subclass parent window in order to get FINDMSGSTRING message
481 m_impl->SubclassDialog(GetHwndOf(m_parent));
482
761989ff 483 if ( !::ShowWindow(hwnd, SW_SHOW) )
c41b00c9
VZ
484 {
485 wxLogLastError(_T("ShowWindow(find dialog)"));
486 }
487
761989ff
VZ
488 m_hWnd = (WXHWND)hwnd;
489
cbe874bd 490 return true;
c41b00c9
VZ
491}
492
493// ----------------------------------------------------------------------------
494// wxFindReplaceDialog title handling
495// ----------------------------------------------------------------------------
496
497// we set the title of this dialog in our jook proc but for now don't crash in
498// the base class version because of m_hWnd == 0
499
500void wxFindReplaceDialog::SetTitle( const wxString& title)
501{
502 m_title = title;
503}
504
505wxString wxFindReplaceDialog::GetTitle() const
506{
507 return m_title;
508}
509
510// ----------------------------------------------------------------------------
511// wxFindReplaceDialog position/size
512// ----------------------------------------------------------------------------
513
514void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
515 int WXUNUSED(width), int WXUNUSED(height),
516 int WXUNUSED(sizeFlags))
517{
518 // ignore - we can't change the size of this standard dialog
519 return;
520}
521
522// NB: of course, both of these functions are completely bogus, but it's better
523// than nothing
524void wxFindReplaceDialog::DoGetSize(int *width, int *height) const
525{
526 // the standard dialog size
527 if ( width )
528 *width = 225;
529 if ( height )
530 *height = 324;
531}
532
533void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const
534{
535 // the standard dialog size
536 if ( width )
537 *width = 219;
538 if ( height )
539 *height = 299;
540}
541
542#endif // wxUSE_FINDREPLDLG
543