]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/fdrepdlg.cpp
check that the version of __sync_sub_and_fetch that returns a value is supported...
[wxWidgets.git] / src / msw / fdrepdlg.cpp
index ca6e4e533fa417ef0e8ad0e5b2a7f2db533afe1f..61441c27820ed96876eb365e5d275bc2d9d97345 100644 (file)
@@ -1,10 +1,10 @@
 /////////////////////////////////////////////////////////////////////////////
 // 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 wxFindReplaceWindowProc(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
@@ -61,14 +51,6 @@ UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
 
 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
 
-IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent)
-
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_NEXT)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE_ALL)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_CLOSE)
-
 // ----------------------------------------------------------------------------
 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
 // ----------------------------------------------------------------------------
@@ -82,27 +64,34 @@ public:
     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;
+
+    DECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl)
 };
 
 UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;
@@ -127,10 +116,15 @@ wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
         {
             wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
         }
+
+        wxWindow::MSWRegisterMessageHandler
+                  (
+                    ms_msgFindDialog,
+                    &wxFindReplaceDialogImpl::FindMessageHandler
+                  );
     }
 
-    m_hwndOwner = NULL;
-    m_oldParentWndProc = NULL;
+    m_wasClosedByUser = false;
 
     wxZeroMemory(m_findReplace);
 
@@ -175,7 +169,7 @@ void wxFindReplaceDialogImpl::InitString(const wxString& str,
 
     *ppStr = new wxChar[len];
     wxStrcpy(*ppStr, str);
-    *pLen = len;
+    *pLen = (WORD)len;
 }
 
 void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
@@ -190,133 +184,133 @@ void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
                &m_findReplace.wReplaceWithLen);
 }
 
-void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
-{
-    m_hwndOwner = hwnd;
-
-    // check that we don't subclass the parent twice: this would be a bad idea
-    // as then we'd have infinite recursion in wxFindReplaceWindowProc
-    WNDPROC oldParentWndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
-
-    if ( oldParentWndProc != wxFindReplaceWindowProc )
-    {
-        // save old wnd proc elsewhere to access it from
-        // wxFindReplaceWindowProc
-        m_oldParentWndProc = oldParentWndProc;
-        (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)oldParentWndProc);
-
-        // and set the new one
-        (void)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wxFindReplaceWindowProc);
-    }
-}
-
 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 wxFindReplaceWindowProc(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, _T("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 lets 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_FIND_REPLACE;
+    // map flags from Windows
+    wxEventType evtType;
 
-            replace = TRUE;
-        }
-        else if ( pFR->Flags & FR_REPLACEALL )
-        {
-            evtType = wxEVT_COMMAND_FIND_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.SetEventObject(dialog);
-        event.SetFlags(flags);
-        event.SetFindString(pFR->lpstrFindWhat);
-        if ( replace )
-        {
-            event.SetReplaceString(pFR->lpstrReplaceWith);
-        }
+        replace = true;
+    }
+    else
+    {
+        wxFAIL_MSG( _T("unknown find dialog event") );
 
-        // TODO: should we copy the strings to dialog->GetData() as well?
+        return 0;
+    }
 
-        if ( !dialog->GetEventHandler()->ProcessEvent(event) )
-        {
-            // the event is not propagated upwards to the parent automatically
-            // because the dialog is a top level window, so do it manually as
-            // in 9 cases of 10 the message must be processed by the dialog
-            // owner and not the dialog itself
-            (void)dialog->GetParent()->GetEventHandler()->ProcessEvent(event);
-        }
+    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);
     }
 
-    WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
+#if wxUSE_UNICODE_MSLU
+    s_blockMsg = true;
+#endif // wxUSE_UNICODE_MSLU
+
+    dialog->Send(event);
 
-    // sanity check
-    wxASSERT_MSG( wndProc != wxFindReplaceWindowProc,
-                  _T("infinite recursion detected") );
+#if wxUSE_UNICODE_MSLU
+    s_blockMsg = false;
+#endif // wxUSE_UNICODE_MSLU
 
-    return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
+    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().wx_str());
 
         // don't return FALSE from here or the dialog won't be shown
         return TRUE;
@@ -325,15 +319,6 @@ UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
     return 0;
 }
 
-// ----------------------------------------------------------------------------
-// wxFindReplaceData
-// ----------------------------------------------------------------------------
-
-void wxFindReplaceData::Init()
-{
-    m_Flags = 0;
-}
-
 // ============================================================================
 // wxFindReplaceDialog implementation
 // ============================================================================
@@ -348,14 +333,14 @@ void wxFindReplaceDialog::Init()
     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,
                                          int flags)
-                   : m_FindReplaceData(data)
+                   : wxFindReplaceDialogBase(parent, data, title, flags)
 {
     Init();
 
@@ -364,14 +349,29 @@ wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
 
 wxFindReplaceDialog::~wxFindReplaceDialog()
 {
-    // unsubclass the parent
-    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(_T("DestroyWindow(find dialog)"));
+            }
+        }
+
+        // unsubclass the parent
+        delete m_impl;
+    }
 
     // prevent the base class dtor from trying to hide us!
-    m_isShown = FALSE;
+    m_isShown = false;
 
-    // and from destroying our window
-    m_hWnd = NULL;
+    // and from destroying our window [again]
+    m_hWnd = (WXHWND)NULL;
 }
 
 bool wxFindReplaceDialog::Create(wxWindow *parent,
@@ -389,16 +389,6 @@ bool wxFindReplaceDialog::Create(wxWindow *parent,
     return parent != NULL;
 }
 
-// ----------------------------------------------------------------------------
-// wxFindReplaceDialog data access
-// ----------------------------------------------------------------------------
-
-void wxFindReplaceDialog::SetData(wxFindReplaceData *data)
-{
-    delete m_FindReplaceData;
-    m_FindReplaceData = data;
-}
-
 // ----------------------------------------------------------------------------
 // wxFindReplaceData show/hide
 // ----------------------------------------------------------------------------
@@ -408,7 +398,7 @@ bool wxFindReplaceDialog::Show(bool show)
     if ( !wxWindowBase::Show(show) )
     {
         // visibility status didn't change
-        return FALSE;
+        return false;
     }
 
     // do we already have the dialog window?
@@ -417,16 +407,16 @@ bool wxFindReplaceDialog::Show(bool show)
         // yes, just use it
         (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
 
-        return TRUE;
+        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!") );
+    wxCHECK_MSG( m_FindReplaceData, false, _T("call Create() first!") );
 
     wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
 
@@ -456,12 +446,9 @@ bool wxFindReplaceDialog::Show(bool show)
         delete m_impl;
         m_impl = NULL;
 
-        return FALSE;
+        return false;
     }
 
-    // subclass parent window in order to get FINDMSGSTRING message
-    m_impl->SubclassDialog(GetHwndOf(m_parent));
-
     if ( !::ShowWindow(hwnd, SW_SHOW) )
     {
         wxLogLastError(_T("ShowWindow(find dialog)"));
@@ -469,7 +456,7 @@ bool wxFindReplaceDialog::Show(bool show)
 
     m_hWnd = (WXHWND)hwnd;
 
-    return TRUE;
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -522,4 +509,3 @@ void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const
 }
 
 #endif // wxUSE_FINDREPLDLG
-