/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/fdrepdlg.cpp
// Purpose: wxFindReplaceDialog class
-// Author: Markus Greither
-// Modified by: 31.07.01: VZ: integrated into wxWindows
+// Author: Markus Greither and Vadim Zeitlin
+// Modified by:
// Created: 23/03/2001
-// RCS-ID:
+// RCS-ID: $Id$
// Copyright: (c) Markus Greither
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// headers
// ----------------------------------------------------------------------------
-#ifdef __GNUG__
- #pragma implementation "fdrepdlg.h"
-#endif
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_FINDREPLDLG
#ifndef WX_PRECOMP
+ #include "wx/msw/wrapcdlg.h"
#include "wx/intl.h"
#include "wx/log.h"
#endif
-#include "wx/msw/private.h"
-
-#if !defined(__WIN32__) || defined(__SALFORDC__) || defined(__WXWINE__)
- #include <commdlg.h>
-#endif
-
#include "wx/fdrepdlg.h"
+#include "wx/msw/mslu.h"
+
// ----------------------------------------------------------------------------
// functions prototypes
// ----------------------------------------------------------------------------
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
- WPARAM wParam, LPARAM lParam);
-
-UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
- UINT uiMsg,
- WPARAM wParam,
- LPARAM lParam);
+UINT_PTR CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
+ UINT uiMsg,
+ WPARAM wParam,
+ LPARAM lParam);
// ----------------------------------------------------------------------------
// wxWin macros
IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
-IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent)
-
// ----------------------------------------------------------------------------
// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
// ----------------------------------------------------------------------------
void InitFindWhat(const wxString& str);
void InitReplaceWith(const wxString& str);
- void SubclassDialog(HWND hwnd);
-
- static UINT GetFindDialogMessage() { return ms_msgFindDialog; }
-
// only for passing to ::FindText or ::ReplaceText
FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; }
+ // set/query the "closed by user" flag
+ void SetClosedByUser() { m_wasClosedByUser = true; }
+ bool WasClosedByUser() const { return m_wasClosedByUser; }
+
private:
- void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
+ // called from window procedure for ms_msgFindDialog
+ static bool FindMessageHandler(wxWindow *win,
+ WXUINT nMsg,
+ WPARAM wParam,
+ LPARAM lParam);
- // the owner of the dialog
- HWND m_hwndOwner;
+ // copy string str contents to ppStr and fill pLen with its length
+ void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
- // the previous window proc of our owner
- WNDPROC m_oldParentWndProc;
// the find replace data used by the dialog
FINDREPLACE m_findReplace;
+ // true if the user closed us, false otherwise
+ bool m_wasClosedByUser;
+
// registered Message for Dialog
static UINT ms_msgFindDialog;
+
+ wxDECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl);
};
UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;
if ( !ms_msgFindDialog )
{
- wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
+ wxLogLastError(wxT("RegisterWindowMessage(FINDMSGSTRING)"));
}
+
+ wxWindow::MSWRegisterMessageHandler
+ (
+ ms_msgFindDialog,
+ &wxFindReplaceDialogImpl::FindMessageHandler
+ );
}
- m_hwndOwner = NULL;
- m_oldParentWndProc = NULL;
+ m_wasClosedByUser = false;
wxZeroMemory(m_findReplace);
- // translate the flags
+ // translate the flags: first the dialog creation flags
// always set this to be able to set the title
int flags = FR_ENABLEHOOK;
- if ( flagsWX & wxFR_NOMATCHCASE)
+ int flagsDialog = dialog->GetWindowStyle();
+ if ( flagsDialog & wxFR_NOMATCHCASE)
flags |= FR_NOMATCHCASE;
- if ( flagsWX & wxFR_NOWHOLEWORD)
+ if ( flagsDialog & wxFR_NOWHOLEWORD)
flags |= FR_NOWHOLEWORD;
- if ( flagsWX & wxFR_NOUPDOWN)
+ if ( flagsDialog & wxFR_NOUPDOWN)
flags |= FR_NOUPDOWN;
+
+ // and now the flags governing the initial values of the dialogs controls
if ( flagsWX & wxFR_DOWN)
flags |= FR_DOWN;
+ if ( flagsWX & wxFR_MATCHCASE)
+ flags |= FR_MATCHCASE;
+ if ( flagsWX & wxFR_WHOLEWORD )
+ flags |= FR_WHOLEWORD;
m_findReplace.lStructSize = sizeof(FINDREPLACE);
m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent());
*ppStr = new wxChar[len];
wxStrcpy(*ppStr, str);
- *pLen = len;
+ *pLen = (WORD)len;
}
void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
&m_findReplace.wReplaceWithLen);
}
-void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
-{
- m_hwndOwner = hwnd;
- m_oldParentWndProc = (WNDPROC)::SetWindowLong
- (
- hwnd,
- GWL_WNDPROC,
- (LONG)FindReplaceWindowProc
- );
-
- // save it elsewhere to access it from FindReplaceWindowProc()
- (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)m_oldParentWndProc);
-}
-
wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
{
delete [] m_findReplace.lpstrFindWhat;
delete [] m_findReplace.lpstrReplaceWith;
-
- if ( m_hwndOwner )
- {
- ::SetWindowLong(m_hwndOwner, GWL_WNDPROC, (LONG)m_oldParentWndProc);
- }
}
// ----------------------------------------------------------------------------
-// Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
+// handler for FINDMSGSTRING message
// ----------------------------------------------------------------------------
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
- WPARAM wParam, LPARAM lParam)
+bool
+wxFindReplaceDialogImpl::FindMessageHandler(wxWindow * WXUNUSED(win),
+ WXUINT WXUNUSED_UNLESS_DEBUG(nMsg),
+ WPARAM WXUNUSED(wParam),
+ LPARAM lParam)
{
- if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
+#if wxUSE_UNICODE_MSLU
+ static unsigned long s_lastMsgFlags = 0;
+
+ // This flag helps us to identify the bogus ANSI message
+ // sent by UNICOWS.DLL (see below)
+ // while we're sending our message to the dialog
+ // we ignore possible messages sent in between
+ static bool s_blockMsg = false;
+#endif // wxUSE_UNICODE_MSLU
+
+ wxASSERT_MSG( nMsg == ms_msgFindDialog, wxT("unexpected message received") );
+
+ FINDREPLACE *pFR = (FINDREPLACE *)lParam;
+
+#if wxUSE_UNICODE_MSLU
+ // This is a hack for a MSLU problem: Versions up to 1.0.4011
+ // of UNICOWS.DLL send the correct UNICODE item after button press
+ // and a bogus ANSI mode item right after this, so let's ignore
+ // the second bogus message
+ if ( wxUsingUnicowsDll() && s_lastMsgFlags == pFR->Flags )
{
- FINDREPLACE *pFR = (FINDREPLACE *)lParam;
- wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
+ s_lastMsgFlags = 0;
+ return 0;
+ }
+ s_lastMsgFlags = pFR->Flags;
+#endif // wxUSE_UNICODE_MSLU
- // map flags from Windows
- wxEventType evtType;
+ wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
- bool replace = FALSE;
- if ( pFR->Flags & FR_DIALOGTERM )
- {
- evtType = wxEVT_COMMAND_FIND_CLOSE;
- }
- else if ( pFR->Flags & FR_FINDNEXT )
- {
- evtType = wxEVT_COMMAND_FIND_NEXT;
- }
- else if ( pFR->Flags & FR_REPLACE )
- {
- evtType = wxEVT_COMMAND_REPLACE;
+ // map flags from Windows
+ wxEventType evtType;
- replace = TRUE;
- }
- else if ( pFR->Flags & FR_REPLACEALL )
- {
- evtType = wxEVT_COMMAND_REPLACE_ALL;
+ bool replace = false;
+ if ( pFR->Flags & FR_DIALOGTERM )
+ {
+ // we have to notify the dialog that it's being closed by user and
+ // not deleted programmatically as it behaves differently in these
+ // 2 cases
+ dialog->GetImpl()->SetClosedByUser();
- replace = TRUE;
- }
- else
- {
- wxFAIL_MSG( _T("unknown find dialog event") );
+ evtType = wxEVT_COMMAND_FIND_CLOSE;
+ }
+ else if ( pFR->Flags & FR_FINDNEXT )
+ {
+ evtType = wxEVT_COMMAND_FIND_NEXT;
+ }
+ else if ( pFR->Flags & FR_REPLACE )
+ {
+ evtType = wxEVT_COMMAND_FIND_REPLACE;
- return 0;
- }
+ replace = true;
+ }
+ else if ( pFR->Flags & FR_REPLACEALL )
+ {
+ evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
- wxUint32 flags = 0;
- if ( pFR->Flags & FR_DOWN )
- flags |= wxFR_DOWN;
- if ( pFR->Flags & FR_WHOLEWORD )
- flags |= wxFR_WHOLEWORD;
- if ( pFR->Flags & FR_MATCHCASE )
- flags |= wxFR_MATCHCASE;
-
- wxFindDialogEvent event(evtType, dialog->GetId());
- event.SetFlags(flags);
- event.SetFindString(pFR->lpstrFindWhat);
- if ( replace )
- {
- event.SetReplaceString(pFR->lpstrReplaceWith);
- }
+ replace = true;
+ }
+ else
+ {
+ wxFAIL_MSG( wxT("unknown find dialog event") );
- (void)dialog->GetEventHandler()->ProcessEvent(event);
+ return 0;
}
- WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
+ wxUint32 flags = 0;
+ if ( pFR->Flags & FR_DOWN )
+ flags |= wxFR_DOWN;
+ if ( pFR->Flags & FR_WHOLEWORD )
+ flags |= wxFR_WHOLEWORD;
+ if ( pFR->Flags & FR_MATCHCASE )
+ flags |= wxFR_MATCHCASE;
+
+ wxFindDialogEvent event(evtType, dialog->GetId());
+ event.SetEventObject(dialog);
+ event.SetFlags(flags);
+ event.SetFindString(pFR->lpstrFindWhat);
+ if ( replace )
+ {
+ event.SetReplaceString(pFR->lpstrReplaceWith);
+ }
- return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
-};
+#if wxUSE_UNICODE_MSLU
+ s_blockMsg = true;
+#endif // wxUSE_UNICODE_MSLU
+
+ dialog->Send(event);
+
+#if wxUSE_UNICODE_MSLU
+ s_blockMsg = false;
+#endif // wxUSE_UNICODE_MSLU
+
+ return true;
+}
// ----------------------------------------------------------------------------
// Find/replace dialog hook proc
// ----------------------------------------------------------------------------
-UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
- UINT uiMsg,
- WPARAM WXUNUSED(wParam),
- LPARAM lParam)
+UINT_PTR CALLBACK
+wxFindReplaceDialogHookProc(HWND hwnd,
+ UINT uiMsg,
+ WPARAM WXUNUSED(wParam),
+ LPARAM lParam)
{
if ( uiMsg == WM_INITDIALOG )
{
FINDREPLACE *pFR = (FINDREPLACE *)lParam;
wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
- ::SetWindowText(hwnd, dialog->GetTitle());
+ ::SetWindowText(hwnd, dialog->GetTitle().t_str());
// don't return FALSE from here or the dialog won't be shown
return TRUE;
m_FindReplaceData = NULL;
// as we're created in the hidden state, bring the internal flag in sync
- m_isShown = FALSE;
+ m_isShown = false;
}
wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title)
- : m_FindReplaceData(data)
+ const wxString &title,
+ int flags)
+ : wxFindReplaceDialogBase(parent, data, title, flags)
{
Init();
- (void)Create(parent, data, title);
+ (void)Create(parent, data, title, flags);
}
wxFindReplaceDialog::~wxFindReplaceDialog()
{
- delete m_impl;
+ if ( m_impl )
+ {
+ // the dialog might have been already deleted if the user closed it
+ // manually but in this case we should have got a notification about it
+ // and the flag must have been set
+ if ( !m_impl->WasClosedByUser() )
+ {
+ // if it wasn't, delete the dialog ourselves
+ if ( !::DestroyWindow(GetHwnd()) )
+ {
+ wxLogLastError(wxT("DestroyWindow(find dialog)"));
+ }
+ }
+
+ // unsubclass the parent
+ delete m_impl;
+ }
+
+ // prevent the base class dtor from trying to hide us!
+ m_isShown = false;
+
+ // and from destroying our window [again]
+ m_hWnd = (WXHWND)NULL;
}
bool wxFindReplaceDialog::Create(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title)
+ const wxString &title,
+ int flags)
{
+ m_windowStyle = flags;
m_FindReplaceData = data;
m_parent = parent;
return parent != NULL;
}
-// ----------------------------------------------------------------------------
-// wxFindReplaceDialog data access
-// ----------------------------------------------------------------------------
-
-void wxFindReplaceDialog::SetData(wxFindReplaceData *data)
-{
- delete m_FindReplaceData;
- m_FindReplaceData = data;
-}
-
// ----------------------------------------------------------------------------
// wxFindReplaceData show/hide
// ----------------------------------------------------------------------------
if ( !wxWindowBase::Show(show) )
{
// visibility status didn't change
- return FALSE;
+ return false;
}
// do we already have the dialog window?
if ( m_hWnd )
{
// yes, just use it
- return ::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
+ (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
+
+ return true;
}
if ( !show )
{
// well, it doesn't exist which is as good as being hidden
- return TRUE;
+ return true;
}
- wxCHECK_MSG( m_FindReplaceData, FALSE, _T("call Create() first!") );
-
- wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
+ wxCHECK_MSG( m_FindReplaceData, false, wxT("call Create() first!") );
- int flagsWX = m_FindReplaceData->GetFlags();
+ wxASSERT_MSG( !m_impl, wxT("why don't we have the window then?") );
- m_impl = new wxFindReplaceDialogImpl(this, flagsWX);
+ m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags());
m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
- if ( flagsWX & wxFR_REPLACEDIALOG)
+ bool replace = HasFlag(wxFR_REPLACEDIALOG);
+ if ( replace )
{
- m_impl->InitFindWhat(m_FindReplaceData->GetReplaceString());
+ m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString());
}
// call the right function to show the dialog which does what we want
- HWND (*pfn)(FINDREPLACE *) = flagsWX & wxFR_REPLACEDIALOG ? ::ReplaceText
- : ::FindText;
- m_hWnd = (WXHWND)(*pfn)(m_impl->GetPtrFindReplace());
- if ( !m_hWnd )
+ FINDREPLACE *pFR = m_impl->GetPtrFindReplace();
+ HWND hwnd;
+ if ( replace )
+ hwnd = ::ReplaceText(pFR);
+ else
+ hwnd = ::FindText(pFR);
+
+ if ( !hwnd )
{
wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
::CommDlgExtendedError());
- delete m_impl;
- m_impl = NULL;
+ wxDELETE(m_impl);
- return FALSE;
+ return false;
}
- // subclass parent window in order to get FINDMSGSTRING message
- m_impl->SubclassDialog(GetHwndOf(m_parent));
-
- if ( !::ShowWindow((HWND)m_hWnd, SW_SHOW) )
+ if ( !::ShowWindow(hwnd, SW_SHOW) )
{
- wxLogLastError(_T("ShowWindow(find dialog)"));
+ wxLogLastError(wxT("ShowWindow(find dialog)"));
}
- return TRUE;
+ m_hWnd = (WXHWND)hwnd;
+
+ return true;
}
// ----------------------------------------------------------------------------
}
#endif // wxUSE_FINDREPLDLG
-