]> git.saurik.com Git - wxWidgets.git/blame - src/msw/fdrepdlg.cpp
compilation fix: wxcrt.h, not crt.h
[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 6// Created: 23/03/2001
57bd4c60 7// RCS-ID: $Id$
c41b00c9 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
57bd4c60 30 #include "wx/msw/wrapcdlg.h"
c41b00c9
VZ
31 #include "wx/intl.h"
32 #include "wx/log.h"
33#endif
34
c41b00c9
VZ
35#include "wx/fdrepdlg.h"
36
ccddcbac
RD
37#include "wx/msw/mslu.h"
38
c41b00c9
VZ
39// ----------------------------------------------------------------------------
40// functions prototypes
41// ----------------------------------------------------------------------------
42
975b6bcf
VZ
43UINT_PTR CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
44 UINT uiMsg,
45 WPARAM wParam,
46 LPARAM lParam);
c41b00c9
VZ
47
48// ----------------------------------------------------------------------------
49// wxWin macros
50// ----------------------------------------------------------------------------
51
52IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
53
c41b00c9
VZ
54// ----------------------------------------------------------------------------
55// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
56// ----------------------------------------------------------------------------
57
58class WXDLLEXPORT wxFindReplaceDialogImpl
59{
60public:
61 wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, int flagsWX);
62 ~wxFindReplaceDialogImpl();
63
64 void InitFindWhat(const wxString& str);
65 void InitReplaceWith(const wxString& str);
66
c41b00c9
VZ
67 // only for passing to ::FindText or ::ReplaceText
68 FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; }
69
14fca738 70 // set/query the "closed by user" flag
cbe874bd 71 void SetClosedByUser() { m_wasClosedByUser = true; }
14fca738
VZ
72 bool WasClosedByUser() const { return m_wasClosedByUser; }
73
c41b00c9 74private:
5acec112
VZ
75 // called from window procedure for ms_msgFindDialog
76 static bool FindMessageHandler(wxWindow *win,
77 WXUINT nMsg,
78 WPARAM wParam,
79 LPARAM lParam);
c41b00c9 80
5acec112
VZ
81 // copy string str contents to ppStr and fill pLen with its length
82 void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
c41b00c9 83
c41b00c9
VZ
84
85 // the find replace data used by the dialog
86 FINDREPLACE m_findReplace;
87
cbe874bd 88 // true if the user closed us, false otherwise
14fca738
VZ
89 bool m_wasClosedByUser;
90
c41b00c9
VZ
91 // registered Message for Dialog
92 static UINT ms_msgFindDialog;
22f3361e
VZ
93
94 DECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl)
c41b00c9
VZ
95};
96
97UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;
98
99// ============================================================================
100// implementation
101// ============================================================================
102
103// ----------------------------------------------------------------------------
104// wxFindReplaceDialogImpl
105// ----------------------------------------------------------------------------
106
107wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
108 int flagsWX)
109{
110 // get the identifier for the find dialog message if we don't have it yet
111 if ( !ms_msgFindDialog )
112 {
113 ms_msgFindDialog = ::RegisterWindowMessage(FINDMSGSTRING);
114
115 if ( !ms_msgFindDialog )
116 {
117 wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
118 }
c41b00c9 119
5acec112
VZ
120 wxWindow::MSWRegisterMessageHandler
121 (
122 ms_msgFindDialog,
123 &wxFindReplaceDialogImpl::FindMessageHandler
124 );
125 }
c41b00c9 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
c41b00c9
VZ
187wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
188{
189 delete [] m_findReplace.lpstrFindWhat;
190 delete [] m_findReplace.lpstrReplaceWith;
c41b00c9
VZ
191}
192
193// ----------------------------------------------------------------------------
5acec112 194// handler for FINDMSGSTRING message
c41b00c9
VZ
195// ----------------------------------------------------------------------------
196
5acec112
VZ
197bool
198wxFindReplaceDialogImpl::FindMessageHandler(wxWindow * WXUNUSED(win),
199 WXUINT WXUNUSED_UNLESS_DEBUG(nMsg),
200 WPARAM WXUNUSED(wParam),
201 LPARAM lParam)
c41b00c9 202{
ea392212
VZ
203#if wxUSE_UNICODE_MSLU
204 static unsigned long s_lastMsgFlags = 0;
205
206 // This flag helps us to identify the bogus ANSI message
207 // sent by UNICOWS.DLL (see below)
208 // while we're sending our message to the dialog
209 // we ignore possible messages sent in between
210 static bool s_blockMsg = false;
211#endif // wxUSE_UNICODE_MSLU
212
5acec112
VZ
213 wxASSERT_MSG( nMsg == ms_msgFindDialog, _T("unexpected message received") );
214
215 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
ea392212
VZ
216
217#if wxUSE_UNICODE_MSLU
5acec112
VZ
218 // This is a hack for a MSLU problem: Versions up to 1.0.4011
219 // of UNICOWS.DLL send the correct UNICODE item after button press
220 // and a bogus ANSI mode item right after this, so lets ignore
221 // the second bogus message
222 if ( wxUsingUnicowsDll() && s_lastMsgFlags == pFR->Flags )
223 {
224 s_lastMsgFlags = 0;
225 return 0;
226 }
227 s_lastMsgFlags = pFR->Flags;
ea392212
VZ
228#endif // wxUSE_UNICODE_MSLU
229
5acec112 230 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
c41b00c9 231
5acec112
VZ
232 // map flags from Windows
233 wxEventType evtType;
c41b00c9 234
5acec112
VZ
235 bool replace = false;
236 if ( pFR->Flags & FR_DIALOGTERM )
237 {
238 // we have to notify the dialog that it's being closed by user and
239 // not deleted programmatically as it behaves differently in these
240 // 2 cases
241 dialog->GetImpl()->SetClosedByUser();
14fca738 242
5acec112
VZ
243 evtType = wxEVT_COMMAND_FIND_CLOSE;
244 }
245 else if ( pFR->Flags & FR_FINDNEXT )
246 {
247 evtType = wxEVT_COMMAND_FIND_NEXT;
248 }
249 else if ( pFR->Flags & FR_REPLACE )
250 {
251 evtType = wxEVT_COMMAND_FIND_REPLACE;
c41b00c9 252
5acec112
VZ
253 replace = true;
254 }
255 else if ( pFR->Flags & FR_REPLACEALL )
256 {
257 evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
c41b00c9 258
5acec112
VZ
259 replace = true;
260 }
261 else
262 {
263 wxFAIL_MSG( _T("unknown find dialog event") );
c41b00c9 264
5acec112
VZ
265 return 0;
266 }
c41b00c9 267
5acec112
VZ
268 wxUint32 flags = 0;
269 if ( pFR->Flags & FR_DOWN )
270 flags |= wxFR_DOWN;
271 if ( pFR->Flags & FR_WHOLEWORD )
272 flags |= wxFR_WHOLEWORD;
273 if ( pFR->Flags & FR_MATCHCASE )
274 flags |= wxFR_MATCHCASE;
275
276 wxFindDialogEvent event(evtType, dialog->GetId());
277 event.SetEventObject(dialog);
278 event.SetFlags(flags);
279 event.SetFindString(pFR->lpstrFindWhat);
280 if ( replace )
281 {
282 event.SetReplaceString(pFR->lpstrReplaceWith);
283 }
c41b00c9 284
ea392212 285#if wxUSE_UNICODE_MSLU
5acec112 286 s_blockMsg = true;
ea392212
VZ
287#endif // wxUSE_UNICODE_MSLU
288
5acec112 289 dialog->Send(event);
ea392212
VZ
290
291#if wxUSE_UNICODE_MSLU
5acec112 292 s_blockMsg = false;
ea392212 293#endif // wxUSE_UNICODE_MSLU
c41b00c9 294
5acec112 295 return true;
761989ff 296}
c41b00c9
VZ
297
298// ----------------------------------------------------------------------------
299// Find/replace dialog hook proc
300// ----------------------------------------------------------------------------
301
975b6bcf
VZ
302UINT_PTR CALLBACK
303wxFindReplaceDialogHookProc(HWND hwnd,
304 UINT uiMsg,
305 WPARAM WXUNUSED(wParam),
306 LPARAM lParam)
c41b00c9
VZ
307{
308 if ( uiMsg == WM_INITDIALOG )
309 {
310 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
311 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
312
313 ::SetWindowText(hwnd, dialog->GetTitle());
314
315 // don't return FALSE from here or the dialog won't be shown
316 return TRUE;
317 }
318
319 return 0;
320}
321
322// ============================================================================
323// wxFindReplaceDialog implementation
324// ============================================================================
325
326// ----------------------------------------------------------------------------
327// wxFindReplaceDialog ctors/dtor
328// ----------------------------------------------------------------------------
329
330void wxFindReplaceDialog::Init()
331{
332 m_impl = NULL;
333 m_FindReplaceData = NULL;
334
335 // as we're created in the hidden state, bring the internal flag in sync
cbe874bd 336 m_isShown = false;
c41b00c9
VZ
337}
338
339wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
340 wxFindReplaceData *data,
761989ff
VZ
341 const wxString &title,
342 int flags)
208c5141 343 : wxFindReplaceDialogBase(parent, data, title, flags)
c41b00c9
VZ
344{
345 Init();
346
761989ff 347 (void)Create(parent, data, title, flags);
c41b00c9
VZ
348}
349
350wxFindReplaceDialog::~wxFindReplaceDialog()
351{
14fca738
VZ
352 // the dialog might have been already deleted if the user closed it
353 // manually but in this case we should have got a notification about it and
354 // the flagmust have been set
355 if ( !m_impl->WasClosedByUser() )
356 {
357 // if it wasn't, delete the dialog ourselves
358 if ( !::DestroyWindow(GetHwnd()) )
359 {
360 wxLogLastError(_T("DestroyWindow(find dialog)"));
361 }
362 }
363
761989ff 364 // unsubclass the parent
c41b00c9 365 delete m_impl;
761989ff
VZ
366
367 // prevent the base class dtor from trying to hide us!
cbe874bd 368 m_isShown = false;
761989ff 369
14fca738 370 // and from destroying our window [again]
44d5b352 371 m_hWnd = (WXHWND)NULL;
c41b00c9
VZ
372}
373
374bool wxFindReplaceDialog::Create(wxWindow *parent,
375 wxFindReplaceData *data,
761989ff
VZ
376 const wxString &title,
377 int flags)
c41b00c9 378{
761989ff 379 m_windowStyle = flags;
c41b00c9
VZ
380 m_FindReplaceData = data;
381 m_parent = parent;
382
383 SetTitle(title);
384
385 // we must have a parent as it will get the messages from us
386 return parent != NULL;
387}
388
c41b00c9
VZ
389// ----------------------------------------------------------------------------
390// wxFindReplaceData show/hide
391// ----------------------------------------------------------------------------
392
393bool wxFindReplaceDialog::Show(bool show)
394{
395 if ( !wxWindowBase::Show(show) )
396 {
397 // visibility status didn't change
cbe874bd 398 return false;
c41b00c9
VZ
399 }
400
401 // do we already have the dialog window?
402 if ( m_hWnd )
403 {
404 // yes, just use it
761989ff
VZ
405 (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
406
cbe874bd 407 return true;
c41b00c9
VZ
408 }
409
410 if ( !show )
411 {
412 // well, it doesn't exist which is as good as being hidden
cbe874bd 413 return true;
c41b00c9
VZ
414 }
415
cbe874bd 416 wxCHECK_MSG( m_FindReplaceData, false, _T("call Create() first!") );
c41b00c9
VZ
417
418 wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
419
761989ff 420 m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags());
c41b00c9
VZ
421
422 m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
423
761989ff
VZ
424 bool replace = HasFlag(wxFR_REPLACEDIALOG);
425 if ( replace )
c41b00c9 426 {
761989ff 427 m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString());
c41b00c9
VZ
428 }
429
430 // call the right function to show the dialog which does what we want
761989ff
VZ
431 FINDREPLACE *pFR = m_impl->GetPtrFindReplace();
432 HWND hwnd;
433 if ( replace )
434 hwnd = ::ReplaceText(pFR);
435 else
436 hwnd = ::FindText(pFR);
437
438 if ( !hwnd )
c41b00c9
VZ
439 {
440 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
441 ::CommDlgExtendedError());
442
443 delete m_impl;
444 m_impl = NULL;
445
cbe874bd 446 return false;
c41b00c9
VZ
447 }
448
761989ff 449 if ( !::ShowWindow(hwnd, SW_SHOW) )
c41b00c9
VZ
450 {
451 wxLogLastError(_T("ShowWindow(find dialog)"));
452 }
453
761989ff
VZ
454 m_hWnd = (WXHWND)hwnd;
455
cbe874bd 456 return true;
c41b00c9
VZ
457}
458
459// ----------------------------------------------------------------------------
460// wxFindReplaceDialog title handling
461// ----------------------------------------------------------------------------
462
463// we set the title of this dialog in our jook proc but for now don't crash in
464// the base class version because of m_hWnd == 0
465
466void wxFindReplaceDialog::SetTitle( const wxString& title)
467{
468 m_title = title;
469}
470
471wxString wxFindReplaceDialog::GetTitle() const
472{
473 return m_title;
474}
475
476// ----------------------------------------------------------------------------
477// wxFindReplaceDialog position/size
478// ----------------------------------------------------------------------------
479
480void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
481 int WXUNUSED(width), int WXUNUSED(height),
482 int WXUNUSED(sizeFlags))
483{
484 // ignore - we can't change the size of this standard dialog
485 return;
486}
487
488// NB: of course, both of these functions are completely bogus, but it's better
489// than nothing
490void wxFindReplaceDialog::DoGetSize(int *width, int *height) const
491{
492 // the standard dialog size
493 if ( width )
494 *width = 225;
495 if ( height )
496 *height = 324;
497}
498
499void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const
500{
501 // the standard dialog size
502 if ( width )
503 *width = 219;
504 if ( height )
505 *height = 299;
506}
507
508#endif // wxUSE_FINDREPLDLG