]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
avoid leaking allocated tooltips
[wxWidgets.git] / src / msw / textctrl.cpp
index 0a8e54ea59d3f5459221219848a130458ae2b5bb..e6a2500f0579cff2b710fb44df750285f365dc29 100644 (file)
@@ -82,7 +82,7 @@
 // dummy value used for m_dropTarget, different from any valid pointer value
 // (which are all even under Windows) and NULL
 static wxDropTarget *
-    wxRICHTEXT_DEFAULT_DROPTARGET = wx_reinterpret_cast(wxDropTarget *, 1);
+    wxRICHTEXT_DEFAULT_DROPTARGET = reinterpret_cast<wxDropTarget *>(1);
 
 #endif // wxUSE_DRAG_AND_DROP && wxUSE_RICHEDIT
 
@@ -169,7 +169,7 @@ public:
 private:
     int& m_count;
 
-    DECLARE_NO_COPY_CLASS(UpdatesCountFilter)
+    wxDECLARE_NO_COPY_CLASS(UpdatesCountFilter);
 };
 
 // ----------------------------------------------------------------------------
@@ -248,6 +248,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
 
 BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
     EVT_CHAR(wxTextCtrl::OnChar)
+    EVT_KEY_DOWN(wxTextCtrl::OnKeyDown)
     EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
 
 #if wxUSE_RICHEDIT
@@ -423,7 +424,9 @@ bool wxTextCtrl::MSWCreateText(const wxString& value,
         }
 #endif
 
+#if wxUSE_INKEDIT
         if (!IsInkEdit())
+#endif // wxUSE_INKEDIT
         {
             if ( m_verRichEdit == 2 )
             {
@@ -483,9 +486,19 @@ bool wxTextCtrl::MSWCreateText(const wxString& value,
         valueWin = value;
     }
 
+    // suppress events sent during control creation: we're called either from
+    // the ctor and then we shouldn't generate any events for compatibility
+    // with the other ports, or from SetWindowStyleFlag() and then we shouldn't
+    // generate the events because our text doesn't really change, the fact
+    // that we (sometimes) need to recreate the control is just an
+    // implementation detail
+    m_updatesCount = -2;
+
     if ( !MSWCreateControl(windowClass.wx_str(), msStyle, pos, size, valueWin) )
         return false;
 
+    m_updatesCount = -1;
+
 #if wxUSE_RICHEDIT
     if (IsRich())
     {
@@ -784,10 +797,12 @@ wxString wxTextCtrl::GetRange(long from, long to) const
                    encoding = font.GetEncoding();
                 }
 
+#if wxUSE_INTL
                 if ( encoding == wxFONTENCODING_SYSTEM )
                 {
                     encoding = wxLocale::GetSystemEncoding();
                 }
+#endif // wxUSE_INTL
 
                 if ( encoding == wxFONTENCODING_SYSTEM )
                 {
@@ -845,8 +860,9 @@ wxString wxTextCtrl::GetRange(long from, long to) const
     else
 #endif // wxUSE_RICHEDIT
     {
-        // retrieve all text
-        str = wxGetWindowText(GetHWND());
+        // retrieve all text: wxTextEntry method works even for multiline
+        // controls and must be used for single line ones to account for hints
+        str = wxTextEntry::GetValue();
 
         // need only a range?
         if ( from < to )
@@ -869,7 +885,7 @@ void wxTextCtrl::DoSetValue(const wxString& value, int flags)
     // comparing it with the old one (chances are that it will be different
     // anyhow, this comparison is there to avoid flicker for small single-line
     // edit controls mostly)
-    if ( (value.length() > 0x400) || (value != GetValue()) )
+    if ( (value.length() > 0x400) || (value != DoGetValue()) )
     {
         DoWriteText(value, flags /* doesn't include SelectionOnly here */);
 
@@ -899,7 +915,7 @@ void wxTextCtrl::DoSetValue(const wxString& value, int flags)
 // TODO: using memcpy() would improve performance a lot for big amounts of text
 
 DWORD CALLBACK
-wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
+wxRichEditStreamIn(DWORD_PTR dwCookie, BYTE *buf, LONG cb, LONG *pcb)
 {
     *pcb = 0;
 
@@ -974,21 +990,19 @@ wxTextCtrl::StreamIn(const wxString& value,
 
     const size_t len = conv.MB2WC(NULL, value.mb_str(), value.length());
 
-#if wxUSE_WCHAR_T
-    wxWCharBuffer wchBuf(len);
+    if (len == wxCONV_FAILED)
+        return false;
+
+    wxWCharBuffer wchBuf(len); // allocates one extra character
     wchar_t *wpc = wchBuf.data();
-#else
-    wchar_t *wchBuf = (wchar_t *)malloc((len + 1)*sizeof(wchar_t));
-    wchar_t *wpc = wchBuf;
-#endif
 
-    conv.MB2WC(wpc, value.mb_str(), value.length());
+    conv.MB2WC(wpc, value.mb_str(), len + 1);
 #endif // wxUSE_UNICODE_MSLU
 
     // finally, stream it in the control
     EDITSTREAM eds;
     wxZeroMemory(eds);
-    eds.dwCookie = (DWORD)&wpc;
+    eds.dwCookie = (DWORD_PTR)&wpc;
     // the cast below is needed for broken (very) old mingw32 headers
     eds.pfnCallback = (EDITSTREAMCALLBACK)wxRichEditStreamIn;
 
@@ -1066,7 +1080,8 @@ wxTextCtrl::StreamOut(wxFontEncoding encoding, bool selectionOnly) const
         // conversion but what else can we do)
         wxCSConv conv(encoding);
         size_t lenNeeded = conv.WC2MB(NULL, wchBuf, 0);
-        if ( lenNeeded++ )
+
+        if ( lenNeeded != wxCONV_FAILED && lenNeeded++ )
         {
             conv.WC2MB(wxStringBuffer(out, lenNeeded), wchBuf, lenNeeded);
         }
@@ -1299,6 +1314,13 @@ void wxTextCtrl::DoSetSelection(long from, long to, int flags)
 #if wxUSE_RICHEDIT
     if ( IsRich() )
     {
+        // if from and to are both -1, it means (in wxWidgets) that all text
+        // should be selected, translate this into Windows convention
+        if ( (from == -1) && (to == -1) )
+        {
+            from = 0;
+        }
+
         CHARRANGE range;
         range.cpMin = from;
         range.cpMax = to;
@@ -1833,6 +1855,35 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     event.Skip();
 }
 
+void wxTextCtrl::OnKeyDown(wxKeyEvent& event)
+{
+    // richedit control doesn't send WM_PASTE, WM_CUT and WM_COPY messages
+    // when Ctrl-V, X or C is pressed and this prevents wxClipboardTextEvent
+    // from working. So we work around it by intercepting these shortcuts
+    // ourselves and emitting clipboard events (which richedit will handle,
+    // so everything works as before, including pasting of rich text):
+    if ( event.GetModifiers() == wxMOD_CONTROL && IsRich() )
+    {
+        switch ( event.GetKeyCode() )
+        {
+            case 'C':
+                Copy();
+                return;
+            case 'X':
+                Cut();
+                return;
+            case 'V':
+                Paste();
+                return;
+            default:
+                break;
+        }
+    }
+
+    // no, we didn't process it
+    event.Skip();
+}
+
 WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
     WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
@@ -1869,7 +1920,7 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
                 else // !editable
                 {
                     // NB: use "=", not "|=" as the base class version returns
-                    //     the same flags is this state as usual (i.e.
+                    //     the same flags in the disabled state as usual (i.e.
                     //     including DLGC_WANTMESSAGE). This is strange (how
                     //     does it work in the native Win32 apps?) but for now
                     //     live with it.
@@ -1877,13 +1928,6 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
                 }
             }
             break;
-
-        case WM_CUT:
-        case WM_COPY:
-        case WM_PASTE:
-            if ( HandleClipboardEvent(nMsg) )
-                lRc = 0;
-            break;
     }
 
     return lRc;
@@ -1928,17 +1972,6 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
 {
     switch ( param )
     {
-        case EN_SETFOCUS:
-        case EN_KILLFOCUS:
-            {
-                wxFocusEvent event(param == EN_KILLFOCUS ? wxEVT_KILL_FOCUS
-                                                         : wxEVT_SET_FOCUS,
-                                   m_windowId);
-                event.SetEventObject(this);
-                HandleWindowEvent(event);
-            }
-            break;
-
         case EN_CHANGE:
             SendUpdateEvent();
             break;
@@ -1954,7 +1987,9 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
             }
             break;
 
-            // the other edit notification messages are not processed
+            // the other edit notification messages are not processed (or, in
+            // the case of EN_{SET/KILL}FOCUS were already handled at WM_SET/
+            // KILLFOCUS level)
         default:
             return false;
     }
@@ -2067,15 +2102,12 @@ void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
 
 void wxTextCtrl::OnDelete(wxCommandEvent& WXUNUSED(event))
 {
-    long from, to;
-    GetSelection(& from, & to);
-    if (from != -1 && to != -1)
-        Remove(from, to);
+    RemoveSelection();
 }
 
 void wxTextCtrl::OnSelectAll(wxCommandEvent& WXUNUSED(event))
 {
-    SetSelection(-1, -1);
+    SelectAll();
 }
 
 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
@@ -2105,14 +2137,12 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
 
 void wxTextCtrl::OnUpdateDelete(wxUpdateUIEvent& event)
 {
-    long from, to;
-    GetSelection(& from, & to);
-    event.Enable(from != -1 && to != -1 && from != to && IsEditable()) ;
+    event.Enable( HasSelection() && IsEditable() );
 }
 
 void wxTextCtrl::OnUpdateSelectAll(wxUpdateUIEvent& event)
 {
-    event.Enable(GetLastPosition() > 0);
+    event.Enable( !IsEmpty() );
 }
 
 void wxTextCtrl::OnContextMenu(wxContextMenuEvent& event)
@@ -2420,7 +2450,7 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
         cf.yHeight = 20*font.GetPointSize(); // 1 pt = 20 twips
         cf.bCharSet = lf.lfCharSet;
         cf.bPitchAndFamily = lf.lfPitchAndFamily;
-        wxStrncpy( cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName) );
+        wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
 
         // also deal with underline/italic/bold attributes: note that we must
         // always set CFM_ITALIC &c bits in dwMask, even if we don't set the
@@ -2792,10 +2822,8 @@ bool wxRichEditModule::Load(Version version)
 // load the InkEdit library
 bool wxRichEditModule::LoadInkEdit()
 {
-    static wxDynamicLibrary ms_inkEditLib;
-    static bool             ms_inkEditLibLoadAttemped;
     if (ms_inkEditLibLoadAttemped)
-        ms_inkEditLib.IsLoaded();
+        return ms_inkEditLib.IsLoaded();
 
     ms_inkEditLibLoadAttemped = true;