]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/textctrl.cpp
Rework the wxCusor ctor taking wx stock number to provide as many cursors as
[wxWidgets.git] / src / univ / textctrl.cpp
index 84f5c7d78b3380c656fb60b6e563ab558d73003b..487fb2fca0ec9a269704b69d02faa000d3e8c237 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        univ/textctrl.cpp
+// Name:        src/univ/textctrl.cpp
 // Purpose:     wxTextCtrl
 // Author:      Vadim Zeitlin
 // Modified by:
 // Purpose:     wxTextCtrl
 // Author:      Vadim Zeitlin
 // Modified by:
@@ -47,7 +47,7 @@
    is true in which case a single LINE may correspond to multiple ROWs.
 
    A text position is an unsigned int (which for reasons of compatibility is
    is true in which case a single LINE may correspond to multiple ROWs.
 
    A text position is an unsigned int (which for reasons of compatibility is
-   still a long) from 0 to GetLastPosition() inclusive. The positions
+   still a long as wxTextPos) from 0 to GetLastPosition() inclusive. The positions
    correspond to the gaps between the letters so the position 0 is just
    before the first character and the last position is the one beyond the last
    character. For an empty text control GetLastPosition() returns 0.
    correspond to the gaps between the letters so the position 0 is just
    before the first character and the last position is the one beyond the last
    character. For an empty text control GetLastPosition() returns 0.
 // headers
 // ----------------------------------------------------------------------------
 
 // headers
 // ----------------------------------------------------------------------------
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "univtextctrl.h"
-#endif
-
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 
 #if wxUSE_TEXTCTRL
 
 
 #if wxUSE_TEXTCTRL
 
-#include <ctype.h>
+#include "wx/textctrl.h"
 
 #ifndef WX_PRECOMP
     #include "wx/log.h"
 
 #ifndef WX_PRECOMP
     #include "wx/log.h"
-
     #include "wx/dcclient.h"
     #include "wx/validate.h"
     #include "wx/dcclient.h"
     #include "wx/validate.h"
-    #include "wx/textctrl.h"
+    #include "wx/dataobj.h"
 #endif
 
 #endif
 
+#include <ctype.h>
+
 #include "wx/clipbrd.h"
 
 #include "wx/textfile.h"
 #include "wx/clipbrd.h"
 
 #include "wx/textfile.h"
 
 #include "wx/cmdproc.h"
 
 
 #include "wx/cmdproc.h"
 
-#if wxUSE_CLIPBOARD
-#include "wx/dataobj.h"
-#endif
-
 // turn extra wxTextCtrl-specific debugging on/off
 #define WXDEBUG_TEXT
 
 // turn extra wxTextCtrl-specific debugging on/off
 #define WXDEBUG_TEXT
 
     #include "wx/tokenzr.h"
 #endif // WXDEBUG_TEXT_REPLACE
 
     #include "wx/tokenzr.h"
 #endif // WXDEBUG_TEXT_REPLACE
 
+// ----------------------------------------------------------------------------
+// wxStdTextCtrlInputHandler: this control handles only the mouse/kbd actions
+// common to Win32 and GTK, platform-specific things are implemented elsewhere
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxStdTextCtrlInputHandler : public wxStdInputHandler
+{
+public:
+    wxStdTextCtrlInputHandler(wxInputHandler *inphand);
+
+    virtual bool HandleKey(wxInputConsumer *consumer,
+                           const wxKeyEvent& event,
+                           bool pressed);
+    virtual bool HandleMouse(wxInputConsumer *consumer,
+                             const wxMouseEvent& event);
+    virtual bool HandleMouseMove(wxInputConsumer *consumer,
+                                 const wxMouseEvent& event);
+    virtual bool HandleFocus(wxInputConsumer *consumer, const wxFocusEvent& event);
+
+protected:
+    // get the position of the mouse click
+    static wxTextPos HitTest(const wxTextCtrl *text, const wxPoint& pos);
+
+    // capture data
+    wxTextCtrl *m_winCapture;
+};
+
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
@@ -197,7 +217,7 @@ static inline void OrderPositions(wxTextPos& from, wxTextPos& to)
 
 // the value which is never used for text position, even not -1 which is
 // sometimes used for some special meaning
 
 // the value which is never used for text position, even not -1 which is
 // sometimes used for some special meaning
-static const wxTextPos INVALID_POS_VALUE = -2;
+static const wxTextPos INVALID_POS_VALUE = wxInvalidTextCoord;
 
 // overlap between pages (when using PageUp/Dn) in lines
 static const size_t PAGE_OVERLAP_IN_LINES = 1;
 
 // overlap between pages (when using PageUp/Dn) in lines
 static const size_t PAGE_OVERLAP_IN_LINES = 1;
@@ -207,7 +227,7 @@ static const size_t PAGE_OVERLAP_IN_LINES = 1;
 // ----------------------------------------------------------------------------
 
 // the data only used by single line text controls
 // ----------------------------------------------------------------------------
 
 // the data only used by single line text controls
-struct WXDLLEXPORT wxTextSingleLineData
+struct wxTextSingleLineData
 {
     // the position of the first visible pixel and the first visible column
     wxCoord m_ofsHorz;
 {
     // the position of the first visible pixel and the first visible column
     wxCoord m_ofsHorz;
@@ -231,7 +251,7 @@ struct WXDLLEXPORT wxTextSingleLineData
 };
 
 // the data only used by multi line text controls
 };
 
 // the data only used by multi line text controls
-struct WXDLLEXPORT wxTextMultiLineData
+struct wxTextMultiLineData
 {
     // the lines of text
     wxArrayString m_lines;
 {
     // the lines of text
     wxArrayString m_lines;
@@ -280,7 +300,7 @@ struct WXDLLEXPORT wxTextMultiLineData
 };
 
 // the data only used by multi line text controls in line wrap mode
 };
 
 // the data only used by multi line text controls in line wrap mode
-class WXDLLEXPORT wxWrappedLineData
+class wxWrappedLineData
 {
     // these functions set all our values, so give them access to them
 friend void wxTextCtrl::LayoutLine(wxTextCoord line,
 {
     // these functions set all our values, so give them access to them
 friend void wxTextCtrl::LayoutLine(wxTextCoord line,
@@ -440,7 +460,7 @@ WX_DECLARE_OBJARRAY(wxWrappedLineData, wxArrayWrappedLinesData);
 #include "wx/arrimpl.cpp"
 WX_DEFINE_OBJARRAY(wxArrayWrappedLinesData);
 
 #include "wx/arrimpl.cpp"
 WX_DEFINE_OBJARRAY(wxArrayWrappedLinesData);
 
-struct WXDLLEXPORT wxTextWrappedData : public wxTextMultiLineData
+struct wxTextWrappedData : public wxTextMultiLineData
 {
     // the width of the column to the right of the text rect used for the
     // indicator mark display for the wrapped lines
 {
     // the width of the column to the right of the text rect used for the
     // indicator mark display for the wrapped lines
@@ -610,13 +630,13 @@ private:
 // implementation
 // ============================================================================
 
 // implementation
 // ============================================================================
 
-BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
     EVT_CHAR(wxTextCtrl::OnChar)
 
     EVT_SIZE(wxTextCtrl::OnSize)
 END_EVENT_TABLE()
 
     EVT_CHAR(wxTextCtrl::OnChar)
 
     EVT_SIZE(wxTextCtrl::OnSize)
 END_EVENT_TABLE()
 
-IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
 
 // ----------------------------------------------------------------------------
 // creation
 
 // ----------------------------------------------------------------------------
 // creation
@@ -630,6 +650,7 @@ void wxTextCtrl::Init()
 
     m_isModified = false;
     m_isEditable = true;
 
     m_isModified = false;
     m_isEditable = true;
+    m_wrapLines = false;
 
     m_posLast =
     m_curPos =
 
     m_posLast =
     m_curPos =
@@ -639,9 +660,6 @@ void wxTextCtrl::Init()
     m_heightLine =
     m_widthAvg = -1;
 
     m_heightLine =
     m_widthAvg = -1;
 
-    // init wxScrollHelper
-    SetWindow(this);
-
     // init the undo manager
     m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
 
     // init the undo manager
     m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
 
@@ -669,23 +687,27 @@ bool wxTextCtrl::Create(wxWindow *parent,
             style |= wxALWAYS_SHOW_SB;
         }
 
             style |= wxALWAYS_SHOW_SB;
         }
 
-        // wxTE_WORDWRAP is 0 for now so we don't need the code below
-#if 0
-        if ( style & wxTE_WORDWRAP )
-        {
-            // wrapping words means wrapping, hence no horz scrollbar
-            style &= ~wxHSCROLL;
-        }
-#endif // 0
+        // wrapping style: wxTE_DONTWRAP == wxHSCROLL so if it's _not_ given,
+        // we won't have horizontal scrollbar automatically, no need to do
+        // anything
 
         // TODO: support wxTE_NO_VSCROLL (?)
 
         // create data object for normal multiline or for controls with line
         // wrap as needed
         if ( style & wxHSCROLL )
 
         // TODO: support wxTE_NO_VSCROLL (?)
 
         // create data object for normal multiline or for controls with line
         // wrap as needed
         if ( style & wxHSCROLL )
+        {
             m_data.mdata = new wxTextMultiLineData;
             m_data.mdata = new wxTextMultiLineData;
-        else
+        }
+        else // we must wrap lines if we don't have horizontal scrollbar
+        {
+            // NB: we can't rely on HasFlag(wxHSCROLL) as the flags can change
+            //     later and even wxWindow::Create() itself temporarily resets
+            //     wxHSCROLL in wxUniv, so remember that we have a wrapped data
+            //     and not just a multi line data in a separate variable
+            m_wrapLines = true;
             m_data.wdata = new wxTextWrappedData;
             m_data.wdata = new wxTextWrappedData;
+        }
     }
     else
     {
     }
     else
     {
@@ -695,7 +717,7 @@ bool wxTextCtrl::Create(wxWindow *parent,
         // create data object for single line controls
         m_data.sdata = new wxTextSingleLineData;
     }
         // create data object for single line controls
         m_data.sdata = new wxTextSingleLineData;
     }
-    
+
 #if wxUSE_TWO_WINDOWS
     if ((style & wxBORDER_MASK) == 0)
         style |= wxBORDER_SUNKEN;
 #if wxUSE_TWO_WINDOWS
     if ((style & wxBORDER_MASK) == 0)
         style |= wxBORDER_SUNKEN;
@@ -728,7 +750,7 @@ bool wxTextCtrl::Create(wxWindow *parent,
 
     RecalcFontMetrics();
     SetValue(value);
 
     RecalcFontMetrics();
     SetValue(value);
-    SetBestSize(size);
+    SetInitialSize(size);
 
     m_isEditable = !(style & wxTE_READONLY);
 
 
     m_isEditable = !(style & wxTE_READONLY);
 
@@ -766,7 +788,7 @@ wxTextCtrl::~wxTextCtrl()
 // set/get the value
 // ----------------------------------------------------------------------------
 
 // set/get the value
 // ----------------------------------------------------------------------------
 
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
 {
     if ( IsSingleLine() && (value == GetValue()) )
     {
 {
     if ( IsSingleLine() && (value == GetValue()) )
     {
@@ -781,7 +803,8 @@ void wxTextCtrl::SetValue(const wxString& value)
         SetInsertionPoint(0);
     }
 
         SetInsertionPoint(0);
     }
 
-    // TODO: should we generate the event or not, finally?
+    if ( flags & SetValue_SendEvent )
+        SendTextUpdatedEvent();
 }
 
 const wxArrayString& wxTextCtrl::GetLines() const
 }
 
 const wxArrayString& wxTextCtrl::GetLines() const
@@ -821,7 +844,7 @@ wxString wxTextCtrl::GetValue() const
 
 void wxTextCtrl::Clear()
 {
 
 void wxTextCtrl::Clear()
 {
-    SetValue(_T(""));
+    SetValue(wxEmptyString);
 }
 
 bool wxTextCtrl::ReplaceLine(wxTextCoord line,
 }
 
 bool wxTextCtrl::ReplaceLine(wxTextCoord line,
@@ -1249,7 +1272,7 @@ void wxTextCtrl::Remove(wxTextPos from, wxTextPos to)
     // if necessary
     OrderPositions(from, to);
 
     // if necessary
     OrderPositions(from, to);
 
-    Replace(from, to, _T(""));
+    Replace(from, to, wxEmptyString);
 }
 
 void wxTextCtrl::WriteText(const wxString& text)
 }
 
 void wxTextCtrl::WriteText(const wxString& text)
@@ -1421,8 +1444,12 @@ wxString wxTextCtrl::GetSelectionText() const
 void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
 {
     // selecting till -1 is the same as selecting to the end
 void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
 {
     // selecting till -1 is the same as selecting to the end
-    if ( to == -1 && from != -1 )
+    if ( to == -1 )
     {
     {
+        // and selecting (-1, -1) range is the same as selecting everything, by
+        // convention
+        if ( from == -1 )
+            from = 0;
         to = GetLastPosition();
     }
 
         to = GetLastPosition();
     }
 
@@ -1650,8 +1677,8 @@ wxString wxTextCtrl::GetLineText(wxTextCoord line) const
     {
         //this is called during DoGetBestSize
         if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
     {
         //this is called during DoGetBestSize
         if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
-       
-        wxCHECK_MSG( (size_t)line < GetLineCount(), _T(""),
+
+        wxCHECK_MSG( (size_t)line < GetLineCount(), wxEmptyString,
                      _T("line index out of range") );
 
         return GetLines()[line];
                      _T("line index out of range") );
 
         return GetLines()[line];
@@ -1670,7 +1697,7 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const
     // if they are out of range
     if ( IsSingleLine() )
     {
     // if they are out of range
     if ( IsSingleLine() )
     {
-        return x > GetLastPosition() || y > 0 ? wxDefaultCoord : x;
+        return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
     }
     else // multiline
     {
     }
     else // multiline
     {
@@ -2360,7 +2387,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
 
 void wxTextCtrl::UpdateTextRect()
 {
 
 void wxTextCtrl::UpdateTextRect()
 {
-    wxRect rectTotal(wxPoint(0, 0), GetClientSize());
+    wxRect rectTotal(GetClientSize());
     wxCoord *extraSpace = WrapLines() ? &WData().m_widthMark : NULL;
     m_rectText = GetRenderer()->GetTextClientArea(this, rectTotal, extraSpace);
 
     wxCoord *extraSpace = WrapLines() ? &WData().m_widthMark : NULL;
     m_rectText = GetRenderer()->GetTextClientArea(this, rectTotal, extraSpace);
 
@@ -2695,7 +2722,7 @@ size_t wxTextCtrl::GetPartOfWrappedLine(const wxChar* text,
                 //else: we can just see it
 
                 // wrap at any character or only at words boundaries?
                 //else: we can just see it
 
                 // wrap at any character or only at words boundaries?
-                if ( !(GetWindowStyle() & wxTE_LINEWRAP) )
+                if ( !(GetWindowStyle() & wxTE_CHARWRAP) )
                 {
                     // find the (last) not word char before this word
                     wxTextCoord colWordStart;
                 {
                     // find the (last) not word char before this word
                     wxTextCoord colWordStart;
@@ -3719,7 +3746,7 @@ void wxTextCtrl::RefreshTextRange(wxTextPos start, wxTextPos end)
         {
             // intermediate line or the last one but we need to refresh it
             // until the end anyhow - do it
         {
             // intermediate line or the last one but we need to refresh it
             // until the end anyhow - do it
-            posCount = wxSTRING_MAXLEN;
+            posCount = wxString::npos;
         }
         else // last line
         {
         }
         else // last line
         {
@@ -4146,7 +4173,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
     // the update region is in window coords and text area is in the client
     // ones, so it must be shifted before computing intersection
     wxRegion rgnUpdate = GetUpdateRegion();
     // the update region is in window coords and text area is in the client
     // ones, so it must be shifted before computing intersection
     wxRegion rgnUpdate = GetUpdateRegion();
-    
+
     wxRect rectTextArea = GetRealTextArea();
     wxPoint pt = GetClientAreaOrigin();
     wxRect rectTextAreaAdjusted = rectTextArea;
     wxRect rectTextArea = GetRealTextArea();
     wxPoint pt = GetClientAreaOrigin();
     wxRect rectTextAreaAdjusted = rectTextArea;
@@ -4270,9 +4297,6 @@ void wxTextCtrl::CreateCaret()
     {
         // FIXME use renderer
         caret = new wxCaret(this, 1, GetLineHeight());
     {
         // FIXME use renderer
         caret = new wxCaret(this, 1, GetLineHeight());
-#ifndef __WXMSW__
-        caret->SetBlinkTime(0);
-#endif // __WXMSW__
     }
     else
     {
     }
     else
     {
@@ -4680,7 +4704,6 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
 
         wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
         InitCommandEvent(event);
 
         wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
         InitCommandEvent(event);
-        event.SetString(GetValue());
         GetEventHandler()->ProcessEvent(event);
 
         // as the text changed...
         GetEventHandler()->ProcessEvent(event);
 
         // as the text changed...
@@ -4696,6 +4719,9 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     if ( !event.HasModifiers() )
     {
         int keycode = event.GetKeyCode();
     if ( !event.HasModifiers() )
     {
         int keycode = event.GetKeyCode();
+#if wxUSE_UNICODE
+        wxChar unicode = event.GetUnicodeKey();
+#endif
         if ( keycode == WXK_RETURN )
         {
             if ( IsSingleLine() || (GetWindowStyle() & wxTE_PROCESS_ENTER) )
         if ( keycode == WXK_RETURN )
         {
             if ( IsSingleLine() || (GetWindowStyle() & wxTE_PROCESS_ENTER) )
@@ -4717,6 +4743,14 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
             // skip event.Skip() below
             return;
         }
             // skip event.Skip() below
             return;
         }
+#if wxUSE_UNICODE
+        else if (unicode > 0)
+        {
+            PerformAction(wxACTION_TEXT_INSERT, -1, unicode);
+
+            return;
+        }
+#endif
     }
 #ifdef __WXDEBUG__
     // Ctrl-R refreshes the control in debug mode
     }
 #ifdef __WXDEBUG__
     // Ctrl-R refreshes the control in debug mode
@@ -4727,6 +4761,14 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     event.Skip();
 }
 
     event.Skip();
 }
 
+/* static */
+wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdTextCtrlInputHandler s_handler(handlerDef);
+
+    return &s_handler;
+}
+
 // ----------------------------------------------------------------------------
 // wxStdTextCtrlInputHandler
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxStdTextCtrlInputHandler
 // ----------------------------------------------------------------------------
@@ -4816,14 +4858,12 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxInputConsumer *consumer,
             break;
 
         case WXK_PAGEDOWN:
             break;
 
         case WXK_PAGEDOWN:
-        case WXK_NEXT:
             // we don't map Ctrl-PgUp/Dn to anything special - what should it
             // to? for now, it's the same as without control
             action << wxACTION_TEXT_PAGE_DOWN;
             break;
 
         case WXK_PAGEUP:
             // we don't map Ctrl-PgUp/Dn to anything special - what should it
             // to? for now, it's the same as without control
             action << wxACTION_TEXT_PAGE_DOWN;
             break;
 
         case WXK_PAGEUP:
-        case WXK_PRIOR:
             action << wxACTION_TEXT_PAGE_UP;
             break;
 
             action << wxACTION_TEXT_PAGE_UP;
             break;