]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
Add accelerator back to label in GetItemLabel
[wxWidgets.git] / src / msw / textctrl.cpp
index 381a2e3c2eca6188ff1cf1103797ee956e673974..974fa7a30d37309c3ef3fe47f7de7f0f0b84b8a4 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        msw/textctrl.cpp
+// Name:        src/msw/textctrl.cpp
 // Purpose:     wxTextCtrl
 // Author:      Julian Smart
 // Modified by:
 // Purpose:     wxTextCtrl
 // Author:      Julian Smart
 // Modified by:
     #include "wx/app.h"
     #include "wx/menu.h"
     #include "wx/math.h"
     #include "wx/app.h"
     #include "wx/menu.h"
     #include "wx/math.h"
+    #include "wx/module.h"
+    #include "wx/wxcrtvararg.h"
 #endif
 
 #endif
 
-#include "wx/module.h"
 #include "wx/sysopt.h"
 
 #if wxUSE_CLIPBOARD
 #include "wx/sysopt.h"
 
 #if wxUSE_CLIPBOARD
@@ -51,6 +52,7 @@
 
 #include "wx/msw/private.h"
 #include "wx/msw/winundef.h"
 
 #include "wx/msw/private.h"
 #include "wx/msw/winundef.h"
+#include "wx/msw/mslu.h"
 
 #include <string.h>
 #include <stdlib.h>
 
 #include <string.h>
 #include <stdlib.h>
     #include <richedit.h>
 #endif
 
     #include <richedit.h>
 #endif
 
-#include "wx/msw/missing.h"
-
 #endif // wxUSE_RICHEDIT
 
 #endif // wxUSE_RICHEDIT
 
+#include "wx/msw/missing.h"
+
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
@@ -135,9 +137,13 @@ public:
     UpdatesCountFilter(int& count)
         : m_count(count)
     {
     UpdatesCountFilter(int& count)
         : m_count(count)
     {
-        wxASSERT_MSG( m_count == -1, _T("wrong initial m_updatesCount value") );
+        wxASSERT_MSG( m_count == -1 || m_count == -2,
+                      _T("wrong initial m_updatesCount value") );
 
 
-        m_count = 0;
+        if (m_count != -2)
+            m_count = 0;
+        //else: we don't want to count how many update events we get as we're going
+        //      to ignore all of them
     }
 
     ~UpdatesCountFilter()
     }
 
     ~UpdatesCountFilter()
@@ -206,7 +212,7 @@ wxBEGIN_FLAGS( wxTextCtrlStyle )
     wxFLAGS_MEMBER(wxTE_CENTRE)
     wxFLAGS_MEMBER(wxTE_RIGHT)
     wxFLAGS_MEMBER(wxTE_DONTWRAP)
     wxFLAGS_MEMBER(wxTE_CENTRE)
     wxFLAGS_MEMBER(wxTE_RIGHT)
     wxFLAGS_MEMBER(wxTE_DONTWRAP)
-    wxFLAGS_MEMBER(wxTE_LINEWRAP)
+    wxFLAGS_MEMBER(wxTE_CHARWRAP)
     wxFLAGS_MEMBER(wxTE_WORDWRAP)
 
 wxEND_FLAGS( wxTextCtrlStyle )
     wxFLAGS_MEMBER(wxTE_WORDWRAP)
 
 wxEND_FLAGS( wxTextCtrlStyle )
@@ -227,11 +233,11 @@ wxEND_HANDLERS_TABLE()
 
 wxCONSTRUCTOR_6( wxTextCtrl , wxWindow* , Parent , wxWindowID , Id , wxString , Value , wxPoint , Position , wxSize , Size , long , WindowStyle)
 #else
 
 wxCONSTRUCTOR_6( wxTextCtrl , wxWindow* , Parent , wxWindowID , Id , wxString , Value , wxPoint , Position , wxSize , Size , long , WindowStyle)
 #else
-IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
 #endif
 
 
 #endif
 
 
-BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
     EVT_CHAR(wxTextCtrl::OnChar)
     EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
 
     EVT_CHAR(wxTextCtrl::OnChar)
     EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
 
@@ -286,7 +292,8 @@ wxTextCtrl::~wxTextCtrl()
     delete m_privateContextMenu;
 }
 
     delete m_privateContextMenu;
 }
 
-bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
+bool wxTextCtrl::Create(wxWindow *parent,
+                        wxWindowID id,
                         const wxString& value,
                         const wxPoint& pos,
                         const wxSize& size,
                         const wxString& value,
                         const wxPoint& pos,
                         const wxSize& size,
@@ -294,15 +301,31 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
                         const wxValidator& validator,
                         const wxString& name)
 {
                         const wxValidator& validator,
                         const wxString& name)
 {
-#ifdef __WXWINCE__
-    if ((style & wxBORDER_MASK) == 0)
-        style |= wxBORDER_SIMPLE;
-#endif
-
     // base initialization
     if ( !CreateControl(parent, id, pos, size, style, validator, name) )
         return false;
 
     // base initialization
     if ( !CreateControl(parent, id, pos, size, style, validator, name) )
         return false;
 
+    if ( !MSWCreateText(value, pos, size) )
+        return false;
+
+    return true;
+}
+
+// returns true if the platform should explicitly apply a theme border
+bool wxTextCtrl::CanApplyThemeBorder() const
+{
+#ifdef __WXWINCE__
+    return false;
+#else
+    // Standard text control already handles theming
+    return ((GetWindowStyle() & (wxTE_RICH|wxTE_RICH2)) != 0);
+#endif
+}
+
+bool wxTextCtrl::MSWCreateText(const wxString& value,
+                               const wxPoint& pos,
+                               const wxSize& size)
+{
     // translate wxWin style flags to MSW ones
     WXDWORD msStyle = MSWGetCreateWindowFlags();
 
     // translate wxWin style flags to MSW ones
     WXDWORD msStyle = MSWGetCreateWindowFlags();
 
@@ -311,7 +334,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
 
 #if defined(__POCKETPC__) || defined(__SMARTPHONE__)
     // A control that capitalizes the first letter
 
 #if defined(__POCKETPC__) || defined(__SMARTPHONE__)
     // A control that capitalizes the first letter
-    if (style & wxTE_CAPITALIZE)
+    if ( HasFlag(wxTE_CAPITALIZE) )
         windowClass = wxT("CAPEDIT");
 #endif
 
         windowClass = wxT("CAPEDIT");
 #endif
 
@@ -351,25 +374,28 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         // found (or if msw.inkedit != 0 and the InkEd.dll is present).
         // However, an application can veto ink edit controls by either specifying
         // msw.inkedit = 0 or by removing wxTE_RICH[2] from the style.
         // found (or if msw.inkedit != 0 and the InkEd.dll is present).
         // However, an application can veto ink edit controls by either specifying
         // msw.inkedit = 0 or by removing wxTE_RICH[2] from the style.
-        
+        //
         if ((wxSystemSettings::HasFeature(wxSYS_TABLET_PRESENT) || wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) != 0) &&
             !(wxSystemOptions::HasOption(wxT("msw.inkedit")) && wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) == 0))
         {
             if (wxRichEditModule::LoadInkEdit())
         if ((wxSystemSettings::HasFeature(wxSYS_TABLET_PRESENT) || wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) != 0) &&
             !(wxSystemOptions::HasOption(wxT("msw.inkedit")) && wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) == 0))
         {
             if (wxRichEditModule::LoadInkEdit())
-            {                
-                windowClass = INKEDIT_CLASS;                
+            {
+                windowClass = INKEDIT_CLASS;
+
+#if wxUSE_INKEDIT && wxUSE_RICHEDIT
                 m_isInkEdit = 1;
                 m_isInkEdit = 1;
-                
+#endif
+
                 // Fake rich text version for other calls
                 m_verRichEdit = 2;
             }
         }
 #endif
                 // Fake rich text version for other calls
                 m_verRichEdit = 2;
             }
         }
 #endif
-        
-        if (!m_isInkEdit)
+
+        if (!IsInkEdit())
         {
             if ( m_verRichEdit == 2 )
         {
             if ( m_verRichEdit == 2 )
-            {            
+            {
                 if ( wxRichEditModule::Load(wxRichEditModule::Version_41) )
                 {
                     // yes, class name for version 4.1 really is 5.0
                 if ( wxRichEditModule::Load(wxRichEditModule::Version_41) )
                 {
                     // yes, class name for version 4.1 really is 5.0
@@ -411,7 +437,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
                     m_verRichEdit = 0;
                 }
             }
                     m_verRichEdit = 0;
                 }
             }
-        } // !useInkEdit 
+        } // !useInkEdit
     }
 #endif // wxUSE_RICHEDIT
 
     }
 #endif // wxUSE_RICHEDIT
 
@@ -426,7 +452,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         valueWin = value;
     }
 
         valueWin = value;
     }
 
-    if ( !MSWCreateControl(windowClass, msStyle, pos, size, valueWin) )
+    if ( !MSWCreateControl(windowClass.wx_str(), msStyle, pos, size, valueWin) )
         return false;
 
 #if wxUSE_RICHEDIT
         return false;
 
 #if wxUSE_RICHEDIT
@@ -438,12 +464,12 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
             // Pass IEM_InsertText (0) as wParam, in order to have the ink always
             // converted to text.
             ::SendMessage(GetHwnd(), EM_SETINKINSERTMODE, 0, 0);
             // Pass IEM_InsertText (0) as wParam, in order to have the ink always
             // converted to text.
             ::SendMessage(GetHwnd(), EM_SETINKINSERTMODE, 0, 0);
-            
+
             // Make sure the mouse can be used for input
             ::SendMessage(GetHwnd(), EM_SETUSEMOUSEFORINPUT, 1, 0);
         }
 #endif
             // Make sure the mouse can be used for input
             ::SendMessage(GetHwnd(), EM_SETUSEMOUSEFORINPUT, 1, 0);
         }
 #endif
-        
+
         // enable the events we're interested in: we want to get EN_CHANGE as
         // for the normal controls
         LPARAM mask = ENM_CHANGE;
         // enable the events we're interested in: we want to get EN_CHANGE as
         // for the normal controls
         LPARAM mask = ENM_CHANGE;
@@ -463,7 +489,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
            // Windows XP, so if we're sure it works correctly under other
            // systems we could do this only for XP
            SetSize(-1, 1); // 1 is small enough to force vert scrollbar
            // Windows XP, so if we're sure it works correctly under other
            // systems we could do this only for XP
            SetSize(-1, 1); // 1 is small enough to force vert scrollbar
-           SetSize(size);
+           SetInitialSize(size);
         }
         else if ( m_windowStyle & wxTE_AUTO_URL )
         {
         }
         else if ( m_windowStyle & wxTE_AUTO_URL )
         {
@@ -528,9 +554,6 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
     // styles which we alaways add by default
     if ( style & wxTE_MULTILINE )
     {
     // styles which we alaways add by default
     if ( style & wxTE_MULTILINE )
     {
-        wxASSERT_MSG( !(style & wxTE_PROCESS_ENTER),
-                      wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
-
         msStyle |= ES_MULTILINE | ES_WANTRETURN;
         if ( !(style & wxTE_NO_VSCROLL) )
         {
         msStyle |= ES_MULTILINE | ES_WANTRETURN;
         if ( !(style & wxTE_NO_VSCROLL) )
         {
@@ -592,6 +615,62 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 
 void wxTextCtrl::SetWindowStyleFlag(long style)
 {
 
 void wxTextCtrl::SetWindowStyleFlag(long style)
 {
+    // changing the alignment of the control dynamically works under Win2003
+    // (but not older Windows version: it seems to work under some versions of
+    // XP but not other ones, and we have no way to determine it so be
+    // conservative here) and only for plain EDIT controls (not RICH ones) and
+    // we have to recreate the control to make it always work
+    if ( IsRich() || wxGetWinVersion() < wxWinVersion_2003 )
+    {
+        const long alignMask = wxTE_LEFT | wxTE_CENTRE | wxTE_RIGHT;
+        if ( (style & alignMask) != (GetWindowStyle() & alignMask) )
+        {
+            const wxString value = GetValue();
+            const wxPoint pos = GetPosition();
+            const wxSize size = GetSize();
+
+            // delete the old window
+            HWND hwnd = GetHwnd();
+            DissociateHandle();
+            ::DestroyWindow(hwnd);
+
+            // create the new one with the updated flags
+            m_windowStyle = style;
+            MSWCreateText(value, pos, size);
+
+            // and make sure it has the same attributes as before
+            if ( m_hasFont )
+            {
+                // calling SetFont(m_font) would do nothing as the code would
+                // notice that the font didn't change, so force it to believe
+                // that it did
+                wxFont font = m_font;
+                m_font = wxNullFont;
+                SetFont(font);
+            }
+
+            if ( m_hasFgCol )
+            {
+                wxColour colFg = m_foregroundColour;
+                m_foregroundColour = wxNullColour;
+                SetForegroundColour(colFg);
+            }
+
+            if ( m_hasBgCol )
+            {
+                wxColour colBg = m_backgroundColour;
+                m_backgroundColour = wxNullColour;
+                SetBackgroundColour(colBg);
+            }
+
+            // note that text styles are lost but this is probably not a big
+            // problem: if you use styles, you probably don't use nor change
+            // alignment flags anyhow
+
+            return;
+        }
+    }
+
 #if wxUSE_RICHEDIT
     // we have to deal with some styles separately because they can't be
     // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed
 #if wxUSE_RICHEDIT
     // we have to deal with some styles separately because they can't be
     // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed
@@ -613,6 +692,15 @@ void wxTextCtrl::SetWindowStyleFlag(long style)
 // set/get the controls text
 // ----------------------------------------------------------------------------
 
 // set/get the controls text
 // ----------------------------------------------------------------------------
 
+bool wxTextCtrl::IsEmpty() const
+{
+    // this is an optimization for multiline controls containing a lot of text
+    if ( IsMultiLine() && GetNumberOfLines() != 1 )
+        return false;
+
+    return wxTextCtrlBase::IsEmpty();
+}
+
 wxString wxTextCtrl::GetValue() const
 {
     // range 0..-1 is special for GetRange() and means to retrieve all text
 wxString wxTextCtrl::GetValue() const
 {
     // range 0..-1 is special for GetRange() and means to retrieve all text
@@ -736,7 +824,7 @@ wxString wxTextCtrl::GetRange(long from, long to) const
     return str;
 }
 
     return str;
 }
 
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
 {
     // if the text is long enough, it's faster to just set it instead of first
     // comparing it with the old one (chances are that it will be different
 {
     // if the text is long enough, it's faster to just set it instead of first
     // comparing it with the old one (chances are that it will be different
@@ -744,22 +832,27 @@ void wxTextCtrl::SetValue(const wxString& value)
     // edit controls mostly)
     if ( (value.length() > 0x400) || (value != GetValue()) )
     {
     // edit controls mostly)
     if ( (value.length() > 0x400) || (value != GetValue()) )
     {
-        DoWriteText(value, false /* not selection only */);
+        DoWriteText(value, flags /* doesn't include SelectionOnly here */);
+
+        // mark the control as being not dirty - we changed its text, not the
+        // user
+        DiscardEdits();
 
         // for compatibility, don't move the cursor when doing SetValue()
         SetInsertionPoint(0);
     }
     else // same text
     {
 
         // for compatibility, don't move the cursor when doing SetValue()
         SetInsertionPoint(0);
     }
     else // same text
     {
+        // still reset the modified flag even if the value didn't really change
+        // because now it comes from the program and not the user (and do it
+        // before generating the event so that the event handler could get the
+        // expected value from IsModified())
+        DiscardEdits();
+
         // still send an event for consistency
         // still send an event for consistency
-        SendUpdateEvent();
+        if (flags & SetValue_SendEvent)
+            SendUpdateEvent();
     }
     }
-
-    // we should reset the modified flag even if the value didn't really change
-
-    // mark the control as being not dirty - we changed its text, not the
-    // user
-    DiscardEdits();
 }
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
 }
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
@@ -840,7 +933,7 @@ wxTextCtrl::StreamIn(const wxString& value,
 #else // !wxUSE_UNICODE_MSLU
     wxCSConv conv(encoding);
 
 #else // !wxUSE_UNICODE_MSLU
     wxCSConv conv(encoding);
 
-    const size_t len = conv.MB2WC(NULL, value, value.length());
+    const size_t len = conv.MB2WC(NULL, value.mb_str(), value.length());
 
 #if wxUSE_WCHAR_T
     wxWCharBuffer wchBuf(len);
 
 #if wxUSE_WCHAR_T
     wxWCharBuffer wchBuf(len);
@@ -850,7 +943,7 @@ wxTextCtrl::StreamIn(const wxString& value,
     wchar_t *wpc = wchBuf;
 #endif
 
     wchar_t *wpc = wchBuf;
 #endif
 
-    conv.MB2WC(wpc, value, value.length());
+    conv.MB2WC(wpc, value.mb_str(), value.length());
 #endif // wxUSE_UNICODE_MSLU
 
     // finally, stream it in the control
 #endif // wxUSE_UNICODE_MSLU
 
     // finally, stream it in the control
@@ -956,8 +1049,9 @@ void wxTextCtrl::WriteText(const wxString& value)
     DoWriteText(value);
 }
 
     DoWriteText(value);
 }
 
-void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
+void wxTextCtrl::DoWriteText(const wxString& value, int flags)
 {
 {
+    bool selectionOnly = (flags & SetValue_SelectionOnly) != 0;
     wxString valueDos;
     if ( m_windowStyle & wxTE_MULTILINE )
         valueDos = wxTextFile::Translate(value, wxTextFileType_Dos);
     wxString valueDos;
     if ( m_windowStyle & wxTE_MULTILINE )
         valueDos = wxTextFile::Translate(value, wxTextFileType_Dos);
@@ -1021,13 +1115,16 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
         // we generate exactly one of them by ignoring all but the first one in
         // SendUpdateEvent() and generating one ourselves if we hadn't got any
         // notifications from Windows
         // we generate exactly one of them by ignoring all but the first one in
         // SendUpdateEvent() and generating one ourselves if we hadn't got any
         // notifications from Windows
+        if ( !(flags & SetValue_SendEvent) )
+            m_updatesCount = -2;        // suppress any update event
+
         UpdatesCountFilter ucf(m_updatesCount);
 
         ::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
                       // EM_REPLACESEL takes 1 to indicate the operation should be redoable
         UpdatesCountFilter ucf(m_updatesCount);
 
         ::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
                       // EM_REPLACESEL takes 1 to indicate the operation should be redoable
-                      selectionOnly ? 1 : 0, (LPARAM)valueDos.c_str());
+                      selectionOnly ? 1 : 0, (LPARAM)valueDos.wx_str());
 
 
-        if ( !ucf.GotUpdate() )
+        if ( !ucf.GotUpdate() && (flags & SetValue_SendEvent) )
         {
             SendUpdateEvent();
         }
         {
             SendUpdateEvent();
         }
@@ -1181,7 +1278,8 @@ void wxTextCtrl::SetInsertionPointEnd()
     // if it doesn't actually move the caret anywhere and so the simple fact of
     // doing it results in horrible flicker when appending big amounts of text
     // to the control in a few chunks (see DoAddText() test in the text sample)
     // if it doesn't actually move the caret anywhere and so the simple fact of
     // doing it results in horrible flicker when appending big amounts of text
     // to the control in a few chunks (see DoAddText() test in the text sample)
-    if ( GetInsertionPoint() == GetLastPosition() )
+    const wxTextPos lastPosition = GetLastPosition();
+    if ( GetInsertionPoint() == lastPosition )
     {
         return;
     }
     {
         return;
     }
@@ -1197,7 +1295,7 @@ void wxTextCtrl::SetInsertionPointEnd()
     else // !RichEdit 1.0
 #endif // wxUSE_RICHEDIT
     {
     else // !RichEdit 1.0
 #endif // wxUSE_RICHEDIT
     {
-        pos = GetLastPosition();
+        pos = lastPosition;
     }
 
     SetInsertionPoint(pos);
     }
 
     SetInsertionPoint(pos);
@@ -1355,9 +1453,9 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret)
 // Working with files
 // ----------------------------------------------------------------------------
 
 // Working with files
 // ----------------------------------------------------------------------------
 
-bool wxTextCtrl::LoadFile(const wxString& file)
+bool wxTextCtrl::DoLoadFile(const wxString& file, int fileType)
 {
 {
-    if ( wxTextCtrlBase::LoadFile(file) )
+    if ( wxTextCtrlBase::DoLoadFile(file, fileType) )
     {
         // update the size limit if needed
         AdjustSpaceLimit();
     {
         // update the size limit if needed
         AdjustSpaceLimit();
@@ -1377,7 +1475,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value)
     // Set selection and remove it
     DoSetSelection(from, to, false /* don't scroll caret into view */);
 
     // Set selection and remove it
     DoSetSelection(from, to, false /* don't scroll caret into view */);
 
-    DoWriteText(value, true /* selection only */);
+    DoWriteText(value);
 }
 
 void wxTextCtrl::Remove(long from, long to)
 }
 
 void wxTextCtrl::Remove(long from, long to)
@@ -1732,18 +1830,17 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
 // kbd input processing
 // ----------------------------------------------------------------------------
 
 // kbd input processing
 // ----------------------------------------------------------------------------
 
-bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg)
+bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* msg)
 {
 {
-    MSG *msg = (MSG *)pMsg;
-
     // check for our special keys here: if we don't do it and the parent frame
     // uses them as accelerators, they wouldn't work at all, so we disable
     // usual preprocessing for them
     if ( msg->message == WM_KEYDOWN )
     {
     // check for our special keys here: if we don't do it and the parent frame
     // uses them as accelerators, they wouldn't work at all, so we disable
     // usual preprocessing for them
     if ( msg->message == WM_KEYDOWN )
     {
-        WORD vkey = (WORD) msg->wParam;
-        if ( (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN )
+        const WPARAM vkey = msg->wParam;
+        if ( HIWORD(msg->lParam) & KF_ALTDOWN )
         {
         {
+            // Alt-Backspace is accelerator for "Undo"
             if ( vkey == VK_BACK )
                 return false;
         }
             if ( vkey == VK_BACK )
                 return false;
         }
@@ -1761,6 +1858,9 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg)
                     // fall through
 
                 case 0:
                     // fall through
 
                 case 0:
+                    if ( IsMultiLine() && vkey == VK_RETURN )
+                        return false;
+                    // fall through
                 case 2:
                     break;
 
                 case 2:
                     break;
 
@@ -1789,7 +1889,7 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg)
         }
     }
 
         }
     }
 
-    return wxControl::MSWShouldPreProcessMessage(pMsg);
+    return wxControl::MSWShouldPreProcessMessage(msg);
 }
 
 void wxTextCtrl::OnChar(wxKeyEvent& event)
 }
 
 void wxTextCtrl::OnChar(wxKeyEvent& event)
@@ -1797,16 +1897,15 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     switch ( event.GetKeyCode() )
     {
         case WXK_RETURN:
     switch ( event.GetKeyCode() )
     {
         case WXK_RETURN:
-            if ( !HasFlag(wxTE_MULTILINE) )
             {
                 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
                 InitCommandEvent(event);
                 event.SetString(GetValue());
                 if ( GetEventHandler()->ProcessEvent(event) )
             {
                 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
                 InitCommandEvent(event);
                 event.SetString(GetValue());
                 if ( GetEventHandler()->ProcessEvent(event) )
+                if ( !HasFlag(wxTE_MULTILINE) )
                     return;
                     return;
+                //else: multiline controls need Enter for themselves
             }
             }
-            //else: multiline controls need Enter for themselves
-
             break;
 
         case WXK_TAB:
             break;
 
         case WXK_TAB:
@@ -1855,41 +1954,53 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
 {
     WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
 
 {
     WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
 
-    if ( nMsg == WM_GETDLGCODE )
+    switch ( nMsg )
     {
     {
-        // we always want the chars and the arrows: the arrows for navigation
-        // and the chars because we want Ctrl-C to work even in a read only
-        // control
-        long lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS;
+        case WM_GETDLGCODE:
+            {
+                // we always want the chars and the arrows: the arrows for
+                // navigation and the chars because we want Ctrl-C to work even
+                // in a read only control
+                long lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS;
 
 
-        if ( IsEditable() )
-        {
-            // we may have several different cases:
-            // 1. normal case: both TAB and ENTER are used for dlg navigation
-            // 2. ctrl which wants TAB for itself: ENTER is used to pass to the
-            //    next control in the dialog
-            // 3. ctrl which wants ENTER for itself: TAB is used for dialog
-            //    navigation
-            // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to go
-            //    to the next control
-
-            // the multiline edit control should always get <Return> for itself
-            if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) )
-                lDlgCode |= DLGC_WANTMESSAGE;
-
-            if ( HasFlag(wxTE_PROCESS_TAB) )
-                lDlgCode |= DLGC_WANTTAB;
-
-            lRc |= lDlgCode;
-        }
-        else // !editable
-        {
-            // NB: use "=", not "|=" as the base class version returns the
-            //     same flags is this 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.
-            lRc = lDlgCode;
-        }
+                if ( IsEditable() )
+                {
+                    // we may have several different cases:
+                    // 1. normal: both TAB and ENTER are used for navigation
+                    // 2. ctrl wants TAB for itself: ENTER is used to pass to
+                    //    the next control in the dialog
+                    // 3. ctrl wants ENTER for itself: TAB is used for dialog
+                    //    navigation
+                    // 4. ctrl wants both TAB and ENTER: Ctrl-ENTER is used to
+                    //    go to the next control (we need some way to do it)
+
+                    // multiline controls should always get ENTER for themselves
+                    if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) )
+                        lDlgCode |= DLGC_WANTMESSAGE;
+
+                    if ( HasFlag(wxTE_PROCESS_TAB) )
+                        lDlgCode |= DLGC_WANTTAB;
+
+                    lRc |= lDlgCode;
+                }
+                else // !editable
+                {
+                    // NB: use "=", not "|=" as the base class version returns
+                    //     the same flags is this 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.
+                    lRc = lDlgCode;
+                }
+            }
+            break;
+
+        case WM_CUT:
+        case WM_COPY:
+        case WM_PASTE:
+            if ( HandleClipboardEvent(nMsg) )
+                lRc = 0;
+            break;
     }
 
     return lRc;
     }
 
     return lRc;
@@ -1920,6 +2031,11 @@ bool wxTextCtrl::SendUpdateEvent()
             // we hadn't updated the control ourselves, this event comes from
             // the user, don't need to ignore it nor update the count
             break;
             // we hadn't updated the control ourselves, this event comes from
             // the user, don't need to ignore it nor update the count
             break;
+
+        case -2:
+            // the control was updated programmatically and we do NOT want to
+            // send events
+            return false;
     }
 
     wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
     }
 
     wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
@@ -2513,11 +2629,23 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
         }
     }
 
         }
     }
 
-    if (pf.dwMask != 0)
+#if wxUSE_RICHEDIT2
+    if ( m_verRichEdit > 1 )
+    {
+        if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+        {
+            // Use RTL paragraphs in RTL mode to get proper layout
+            pf.dwMask |= PFM_RTLPARA;
+            pf.wEffects |= PFE_RTLPARA;
+        }
+    }
+#endif // wxUSE_RICHEDIT2
+
+    if ( pf.dwMask )
     {
         // do format the selection
         bool ok = ::SendMessage(GetHwnd(), EM_SETPARAFORMAT,
     {
         // do format the selection
         bool ok = ::SendMessage(GetHwnd(), EM_SETPARAFORMAT,
-            0, (LPARAM) &pf) != 0;
+                                0, (LPARAM) &pf) != 0;
         if ( !ok )
         {
             wxLogDebug(_T("SendMessage(EM_SETPARAFORMAT, 0) failed"));
         if ( !ok )
         {
             wxLogDebug(_T("SendMessage(EM_SETPARAFORMAT, 0) failed"));
@@ -2771,9 +2899,9 @@ bool wxRichEditModule::LoadInkEdit()
     static bool             ms_inkEditLibLoadAttemped;
     if (ms_inkEditLibLoadAttemped)
         ms_inkEditLib.IsLoaded();
     static bool             ms_inkEditLibLoadAttemped;
     if (ms_inkEditLibLoadAttemped)
         ms_inkEditLib.IsLoaded();
-    
+
     ms_inkEditLibLoadAttemped = true;
     ms_inkEditLibLoadAttemped = true;
-    
+
     wxLogNull logNull;
     return ms_inkEditLib.Load(wxT("inked"));
 }
     wxLogNull logNull;
     return ms_inkEditLib.Load(wxT("inked"));
 }