]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/textctrl.cpp
Only account for WM frame extents in tlw size if WM supports _NET_FRAME_EXTENTS....
[wxWidgets.git] / src / univ / textctrl.cpp
index 5a336af029d3b1e7e2b9dbafb439bd236610f002..ee60b694c5edb7be872c94aba50f054df3a23808 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:
 
 #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
 // ----------------------------------------------------------------------------
@@ -203,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;
@@ -227,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;
@@ -276,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,
@@ -436,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
@@ -606,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
@@ -626,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 =
@@ -671,9 +696,18 @@ bool wxTextCtrl::Create(wxWindow *parent,
         // create data object for normal multiline or for controls with line
         // wrap as needed
         if ( style & wxHSCROLL )
         // 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
     {
@@ -716,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);
 
@@ -754,22 +788,25 @@ 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 ( value != GetValue() )
     {
     {
-        // nothing changed
-        return;
-    }
+        EventsSuppressor noeventsIf(this, !(flags & SetValue_SendEvent));
 
 
-    Replace(0, GetLastPosition(), value);
+        Replace(0, GetLastPosition(), value);
 
 
-    if ( IsSingleLine() )
+        if ( IsSingleLine() )
+        {
+            SetInsertionPoint(0);
+        }
+    }
+    else // nothing changed
     {
     {
-        SetInsertionPoint(0);
+        // still send event for consistency
+        if ( flags & SetValue_SendEvent )
+            SendTextUpdatedEvent();
     }
     }
-
-    // TODO: should we generate the event or not, finally?
 }
 
 const wxArrayString& wxTextCtrl::GetLines() const
 }
 
 const wxArrayString& wxTextCtrl::GetLines() const
@@ -1229,6 +1266,9 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
 
     // now call it to do the rest (not related to refreshing)
     ClearSelection();
 
     // now call it to do the rest (not related to refreshing)
     ClearSelection();
+
+    if ( EventsAllowed() )
+        SendTextUpdatedEvent();
 }
 
 void wxTextCtrl::Remove(wxTextPos from, wxTextPos to)
 }
 
 void wxTextCtrl::Remove(wxTextPos from, wxTextPos to)
@@ -1409,8 +1449,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();
     }
 
@@ -1926,7 +1970,7 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
                 {
                     // finding the last line is easy if each line has exactly
                     // one row
                 {
                     // finding the last line is easy if each line has exactly
                     // one row
-                    yEnd = yStart + rectText.height / GetLineHeight() - 1;
+                    yEnd = yStart + rectText.height / GetLineHeight();
                 }
 
                 if ( yEnd < y )
                 }
 
                 if ( yEnd < y )
@@ -2379,7 +2423,7 @@ void wxTextCtrl::UpdateTextRect()
             WData().m_rowFirstInvalid = 0;
 
             // increase timestamp: this means that the lines which had been
             WData().m_rowFirstInvalid = 0;
 
             // increase timestamp: this means that the lines which had been
-            // laid out before will be relayd out the next time LayoutLines()
+            // laid out before will be relaid out the next time LayoutLines()
             // is called because their timestamp will be smaller than the
             // current one
             WData().m_timestamp++;
             // is called because their timestamp will be smaller than the
             // current one
             WData().m_timestamp++;
@@ -2403,9 +2447,12 @@ void wxTextCtrl::UpdateLastVisible()
     {
         case wxTE_HT_BEYOND:
             // everything is visible
     {
         case wxTE_HT_BEYOND:
             // everything is visible
+            SData().m_ofsHorz = 0;
+
+            SData().m_colStart = 0;
             SData().m_colLastVisible = text.length();
 
             SData().m_colLastVisible = text.length();
 
-            // calc it below
+            // calculate it below
             SData().m_posLastVisible = -1;
             break;
 
             SData().m_posLastVisible = -1;
             break;
 
@@ -2683,7 +2730,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;
@@ -3223,7 +3270,7 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
    fine for vertical scrolling as all lines have the same height but is rather
    ugly for horizontal scrolling if proportional font is used. This is why we
    manually update and use SData().m_ofsHorz which contains the length of the string
    fine for vertical scrolling as all lines have the same height but is rather
    ugly for horizontal scrolling if proportional font is used. This is why we
    manually update and use SData().m_ofsHorz which contains the length of the string
-   which is hidden beyond the left borde. An important property of text
+   which is hidden beyond the left border. An important property of text
    controls using this kind of scrolling is that an entire number of characters
    is always shown and that parts of characters never appear on display -
    neither in the leftmost nor rightmost positions.
    controls using this kind of scrolling is that an entire number of characters
    is always shown and that parts of characters never appear on display -
    neither in the leftmost nor rightmost positions.
@@ -3238,7 +3285,7 @@ void wxTextCtrl::ShowHorzPosition(wxCoord pos)
 
     // pos is the logical position to show
 
 
     // pos is the logical position to show
 
-    // SData().m_ofsHorz is the fisrt logical position shown
+    // SData().m_ofsHorz is the first logical position shown
     if ( pos < SData().m_ofsHorz )
     {
         // scroll backwards
     if ( pos < SData().m_ofsHorz )
     {
         // scroll backwards
@@ -3573,8 +3620,12 @@ void wxTextCtrl::UpdateScrollbars()
 
         if ( scrollRangeXOld )
         {
 
         if ( scrollRangeXOld )
         {
-            x *= scrollRangeX - m_rectText.width / charWidth;
-            x /= scrollRangeXOld - m_rectText.width / charWidth;
+            const int w = m_rectText.width / charWidth;
+            if ( w != scrollRangeXOld )
+            {
+                x *= scrollRangeX - w;
+                x /= scrollRangeXOld - w;
+            }
             Scroll(x, y);
         }
 
             Scroll(x, y);
         }
 
@@ -3707,7 +3758,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
         {
@@ -4151,6 +4202,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
     // FIXME: is this really a bug in wxMSW?
     rectTextArea.width--;
 #endif // __WXMSW__
     // FIXME: is this really a bug in wxMSW?
     rectTextArea.width--;
 #endif // __WXMSW__
+    dc.DestroyClippingRegion();
     dc.SetClippingRegion(rectTextArea);
 
     // adjust for scrolling
     dc.SetClippingRegion(rectTextArea);
 
     // adjust for scrolling
@@ -4258,9 +4310,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
     {
@@ -4685,7 +4734,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
         int keycode = event.GetKeyCode();
 #if wxUSE_UNICODE
         wxChar unicode = event.GetUnicodeKey();
         int keycode = event.GetKeyCode();
 #if wxUSE_UNICODE
         wxChar unicode = event.GetUnicodeKey();
-#endif        
+#endif
         if ( keycode == WXK_RETURN )
         {
             if ( IsSingleLine() || (GetWindowStyle() & wxTE_PROCESS_ENTER) )
         if ( keycode == WXK_RETURN )
         {
             if ( IsSingleLine() || (GetWindowStyle() & wxTE_PROCESS_ENTER) )
@@ -4714,7 +4763,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
 
             return;
         }
 
             return;
         }
-#endif        
+#endif
     }
 #ifdef __WXDEBUG__
     // Ctrl-R refreshes the control in debug mode
     }
 #ifdef __WXDEBUG__
     // Ctrl-R refreshes the control in debug mode
@@ -4725,6 +4774,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
 // ----------------------------------------------------------------------------
@@ -4814,14 +4871,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;