]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
Updated to Scintilla 1.67
[wxWidgets.git] / src / msw / textctrl.cpp
index 7f527da53ecafe6213aef0b90b6fa34a7a06a66d..9630d087b9419c51e38a90f5621387e9285cc570 100644 (file)
 // declarations
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "textctrl.h"
-#endif
-
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
@@ -43,6 +39,7 @@
 #endif
 
 #include "wx/module.h"
+#include "wx/sysopt.h"
 
 #if wxUSE_CLIPBOARD
     #include "wx/clipbrd.h"
 
 #if wxUSE_RICHEDIT
 
+#if wxUSE_INKEDIT
+#include "wx/dynlib.h"
+#endif
+
 // old mingw32 has richedit stuff directly in windows.h and doesn't have
 // richedit.h at all
 #if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
@@ -98,15 +99,30 @@ public:
     // load the richedit DLL for the specified version of rich edit
     static bool Load(Version version);
 
+#if wxUSE_INKEDIT
+    // load the InkEdit library
+    static bool LoadInkEdit();
+#endif
+
 private:
     // the handles to richedit 1.0 and 2.0 (or 3.0) DLLs
     static HINSTANCE ms_hRichEdit[Version_Max];
 
+#if wxUSE_INKEDIT
+    static wxDynamicLibrary ms_inkEditLib;
+    static bool             ms_inkEditLibLoadAttemped;
+#endif
+
     DECLARE_DYNAMIC_CLASS(wxRichEditModule)
 };
 
 HINSTANCE wxRichEditModule::ms_hRichEdit[Version_Max] = { NULL, NULL, NULL };
 
+#if wxUSE_INKEDIT
+wxDynamicLibrary wxRichEditModule::ms_inkEditLib;
+bool             wxRichEditModule::ms_inkEditLibLoadAttemped = false;
+#endif
+
 IMPLEMENT_DYNAMIC_CLASS(wxRichEditModule, wxModule)
 
 #endif // wxUSE_RICHEDIT
@@ -256,6 +272,10 @@ void wxTextCtrl::Init()
     m_verRichEdit = 0;
 #endif // wxUSE_RICHEDIT
 
+#if wxUSE_INKEDIT && wxUSE_RICHEDIT
+    m_isInkEdit = 0;
+#endif
+
     m_privateContextMenu = NULL;
     m_updatesCount = -1;
     m_isNativeCaretShown = true;
@@ -325,49 +345,76 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         m_verRichEdit = m_windowStyle & wxTE_RICH2 ? 2 : 1;
 #endif // wxUSE_UNICODE/!wxUSE_UNICODE
 
-        if ( m_verRichEdit == 2 )
+#if wxUSE_INKEDIT
+        // First test if we can load an ink edit control. Normally, all edit
+        // controls will be made ink edit controls if a tablet environment is
+        // 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::Load(wxRichEditModule::Version_41) )
+            if (wxRichEditModule::LoadInkEdit())
             {
-                // yes, class name for version 4.1 really is 5.0
-                windowClass = _T("RICHEDIT50W");
+                windowClass = INKEDIT_CLASS;
+
+#if wxUSE_INKEDIT && wxUSE_RICHEDIT
+                m_isInkEdit = 1;
+#endif
+
+                // Fake rich text version for other calls
+                m_verRichEdit = 2;
             }
-            else if ( wxRichEditModule::Load(wxRichEditModule::Version_2or3) )
-            {
-                windowClass = _T("RichEdit20")
+        }
+#endif
+
+        if (!IsInkEdit())
+        {
+            if ( m_verRichEdit == 2 )
+            {            
+                if ( wxRichEditModule::Load(wxRichEditModule::Version_41) )
+                {
+                    // yes, class name for version 4.1 really is 5.0
+                    windowClass = _T("RICHEDIT50W");
+                }
+                else if ( wxRichEditModule::Load(wxRichEditModule::Version_2or3) )
+                {
+                    windowClass = _T("RichEdit20")
 #if wxUSE_UNICODE
-                              _T("W");
+                                _T("W");
 #else // ANSI
-                              _T("A");
+                                _T("A");
 #endif // Unicode/ANSI
+                }
+                else // failed to load msftedit.dll and riched20.dll
+                {
+                    m_verRichEdit = 1;
+                }
             }
-            else // failed to load msftedit.dll and riched20.dll
-            {
-                m_verRichEdit = 1;
-            }
-        }
 
-        if ( m_verRichEdit == 1 )
-        {
-            if ( wxRichEditModule::Load(wxRichEditModule::Version_1) )
-            {
-                windowClass = _T("RICHEDIT");
-            }
-            else // failed to load any richedit control DLL
+            if ( m_verRichEdit == 1 )
             {
-                // only give the error msg once if the DLL can't be loaded
-                static bool s_errorGiven = false; // MT ok as only used by GUI
-
-                if ( !s_errorGiven )
+                if ( wxRichEditModule::Load(wxRichEditModule::Version_1) )
                 {
-                    wxLogError(_("Impossible to create a rich edit control, using simple text control instead. Please reinstall riched32.dll"));
-
-                    s_errorGiven = true;
+                    windowClass = _T("RICHEDIT");
                 }
+                else // failed to load any richedit control DLL
+                {
+                    // only give the error msg once if the DLL can't be loaded
+                    static bool s_errorGiven = false; // MT ok as only used by GUI
+
+                    if ( !s_errorGiven )
+                    {
+                        wxLogError(_("Impossible to create a rich edit control, using simple text control instead. Please reinstall riched32.dll"));
 
-                m_verRichEdit = 0;
+                        s_errorGiven = true;
+                    }
+
+                    m_verRichEdit = 0;
+                }
             }
-        }
+        } // !useInkEdit 
     }
 #endif // wxUSE_RICHEDIT
 
@@ -386,13 +433,25 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         return false;
 
 #if wxUSE_RICHEDIT
-    if ( IsRich() )
+    if (IsRich())
     {
+#if wxUSE_INKEDIT
+        if (IsInkEdit())
+        {
+            // 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
+        
         // enable the events we're interested in: we want to get EN_CHANGE as
         // for the normal controls
         LPARAM mask = ENM_CHANGE;
 
-        if ( GetRichVersion() == 1 )
+        if (GetRichVersion() == 1 && !IsInkEdit())
         {
             // we also need EN_MSGFILTER for richedit 1.0 for the reasons
             // explained in its handler
@@ -813,7 +872,10 @@ wxTextCtrl::StreamIn(const wxString& value,
                   (selectionOnly ? SFF_SELECTION : 0),
                   (LPARAM)&eds);
 
-    wxASSERT_MSG( ucf.GotUpdate(), _T("EM_STREAMIN didn't send EN_UPDATE?") );
+    // It's okay for EN_UPDATE to not be sent if the selection is empty and
+    // the text is empty, otherwise warn the programmer about it.
+    wxASSERT_MSG( ucf.GotUpdate() || ( !HasSelection() && value.empty() ),
+                  _T("EM_STREAMIN didn't send EN_UPDATE?") );
 
     if ( eds.dwError )
     {
@@ -965,7 +1027,8 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
         UpdatesCountFilter ucf(m_updatesCount);
 
         ::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
-                      0, (LPARAM)valueDos.c_str());
+                      // EM_REPLACESEL takes 1 to indicate the operation should be redoable
+                      selectionOnly ? 1 : 0, (LPARAM)valueDos.c_str());
 
         if ( !ucf.GotUpdate() )
         {
@@ -1261,10 +1324,14 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret)
         // ES_DISABLENOSCROLL
         //
         // this is very ugly but I don't see any other way to make this work
+        long style = 0;
         if ( GetRichVersion() > 1 )
         {
             if ( !HasFlag(wxTE_NOHIDESEL) )
             {
+                // setting ECO_NOHIDESEL also sets WS_VISIBLE and possibly
+                // others, remember the style so we can reset it later if needed
+                style = ::GetWindowLong(GetHwnd(), GWL_STYLE);
                 ::SendMessage(GetHwnd(), EM_SETOPTIONS,
                               ECOOP_OR, ECO_NOHIDESEL);
             }
@@ -1280,6 +1347,8 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret)
         {
             ::SendMessage(GetHwnd(), EM_SETOPTIONS,
                           ECOOP_AND, ~ECO_NOHIDESEL);
+            if ( style != ::GetWindowLong(GetHwnd(), GWL_STYLE) )
+                ::SetWindowLong(GetHwnd(), GWL_STYLE, style);
         }
 #endif // wxUSE_RICHEDIT
     }
@@ -1731,16 +1800,15 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     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) )
+                if ( !HasFlag(wxTE_MULTILINE) )
                     return;
+                //else: multiline controls need Enter for themselves
             }
-            //else: multiline controls need Enter for themselves
-
             break;
 
         case WXK_TAB:
@@ -1963,7 +2031,7 @@ wxSize wxTextCtrl::DoGetBestSize() const
     int hText = cy;
     if ( m_windowStyle & wxTE_MULTILINE )
     {
-        hText *= wxMax(wxMin(GetNumberOfLines(), 10), 2); 
+        hText *= wxMax(wxMin(GetNumberOfLines(), 10), 2);
     }
     //else: for single line control everything is ok
 
@@ -2524,7 +2592,7 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
 
     if ( changeSel )
     {
-        DoSetSelection(position, position, false /* don't scroll caret into view */);
+        DoSetSelection(position, position+1, false /* don't scroll caret into view */);
     }
 
     // get the selection formatting
@@ -2654,6 +2722,10 @@ void wxRichEditModule::OnExit()
             ms_hRichEdit[i] = NULL;
         }
     }
+#if wxUSE_INKEDIT
+    if (ms_inkEditLib.IsLoaded())
+        ms_inkEditLib.Unload();
+#endif
 }
 
 /* static */
@@ -2693,6 +2765,23 @@ bool wxRichEditModule::Load(Version version)
     return true;
 }
 
+#if wxUSE_INKEDIT
+// load the InkEdit library
+bool wxRichEditModule::LoadInkEdit()
+{
+    static wxDynamicLibrary ms_inkEditLib;
+    static bool             ms_inkEditLibLoadAttemped;
+    if (ms_inkEditLibLoadAttemped)
+        ms_inkEditLib.IsLoaded();
+    
+    ms_inkEditLibLoadAttemped = true;
+    
+    wxLogNull logNull;
+    return ms_inkEditLib.Load(wxT("inked"));
+}
+#endif
+
+
 #endif // wxUSE_RICHEDIT
 
 #endif // wxUSE_TEXTCTRL && !(__SMARTPHONE__ && __WXWINCE__)