]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/fdrepdlg.cpp
blind fix for wxGIFDecoder::ReadGIF
[wxWidgets.git] / src / msw / fdrepdlg.cpp
index cb74cb9596e45cbaff7931c4ef206992d2f42214..13c4062c8c62c72d686db600e38beb28c8f3015f 100644 (file)
@@ -1,8 +1,8 @@
 /////////////////////////////////////////////////////////////////////////////
 // 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:
 // Copyright:   (c) Markus Greither
@@ -18,7 +18,7 @@
 // ----------------------------------------------------------------------------
 
 #ifdef __GNUG__
-    #pragma implementation "fdrepdlg.h"
+    #pragma implementation "mswfdrepdlg.h"
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
@@ -47,7 +47,7 @@
 // functions prototypes
 // ----------------------------------------------------------------------------
 
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
+LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
                                        WPARAM wParam, LPARAM lParam);
 
 UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
@@ -61,8 +61,6 @@ UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
 
 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
 
-IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent)
-
 // ----------------------------------------------------------------------------
 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
 // ----------------------------------------------------------------------------
@@ -83,6 +81,10 @@ public:
     // 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);
 
@@ -95,6 +97,9 @@ private:
     // 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;
 };
@@ -126,21 +131,30 @@ wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
     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());
@@ -180,15 +194,21 @@ void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
 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);
+
+    // 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()
@@ -206,8 +226,8 @@ wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
 // Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
 // ----------------------------------------------------------------------------
 
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
-                                       WPARAM wParam, LPARAM lParam)
+LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
+                                         WPARAM wParam, LPARAM lParam)
 {
     if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
     {
@@ -220,6 +240,11 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
         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();
+
             evtType = wxEVT_COMMAND_FIND_CLOSE;
         }
         else if ( pFR->Flags & FR_FINDNEXT )
@@ -228,13 +253,13 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
         }
         else if ( pFR->Flags & FR_REPLACE )
         {
-            evtType = wxEVT_COMMAND_REPLACE;
+            evtType = wxEVT_COMMAND_FIND_REPLACE;
 
             replace = TRUE;
         }
         else if ( pFR->Flags & FR_REPLACEALL )
         {
-            evtType = wxEVT_COMMAND_REPLACE_ALL;
+            evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
 
             replace = TRUE;
         }
@@ -254,6 +279,7 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
             flags |= wxFR_MATCHCASE;
 
         wxFindDialogEvent event(evtType, dialog->GetId());
+        event.SetEventObject(dialog);
         event.SetFlags(flags);
         event.SetFindString(pFR->lpstrFindWhat);
         if ( replace )
@@ -261,13 +287,17 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
             event.SetReplaceString(pFR->lpstrReplaceWith);
         }
 
-        (void)dialog->GetEventHandler()->ProcessEvent(event);
+        dialog->Send(event);
     }
 
     WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
 
+    // sanity check
+    wxASSERT_MSG( wndProc != wxFindReplaceWindowProc,
+                  _T("infinite recursion detected") );
+
     return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
-};
+}
 
 // ----------------------------------------------------------------------------
 // Find/replace dialog hook proc
@@ -311,23 +341,45 @@ void wxFindReplaceDialog::Init()
 
 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()
 {
+    // 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 flagmust 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;
+
+    // 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;
 
@@ -337,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
 // ----------------------------------------------------------------------------
@@ -363,7 +405,9 @@ bool wxFindReplaceDialog::Show(bool show)
     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 )
@@ -376,22 +420,25 @@ bool wxFindReplaceDialog::Show(bool show)
 
     wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
 
-    int flagsWX = m_FindReplaceData->GetFlags();
-
-    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());
@@ -405,11 +452,13 @@ bool wxFindReplaceDialog::Show(bool show)
     // 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)"));
     }
 
+    m_hWnd = (WXHWND)hwnd;
+
     return TRUE;
 }