]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/textctrl.cpp
Fix setting the clipping region for a DC when the region is an
[wxWidgets.git] / src / univ / textctrl.cpp
index 98b53bda8a47bc6118e19f94746a0ddc3699620d..5b1c204822080ef4c658bf2f1f6c0d388327f817 100644 (file)
@@ -1,12 +1,12 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        univ/textctrl.cpp
+// Name:        src/univ/textctrl.cpp
 // Purpose:     wxTextCtrl
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     15.09.00
 // RCS-ID:      $Id$
-// Copyright:   (c) 2000 Vadim Zeitlin
-// Licence:     wxWindows license
+// Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 /*
 
    Everywhere in this file LINE refers to a logical line of text, and ROW to a
    physical line of text on the display. They are the same unless WrapLines()
-   is TRUE in which case a single LINE may correspond to multiple ROWs.
+   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.
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "univtextctrl.h"
-#endif
-
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 
 #if wxUSE_TEXTCTRL
 
+#include "wx/textctrl.h"
+
 #ifndef WX_PRECOMP
     #include "wx/log.h"
-
     #include "wx/dcclient.h"
     #include "wx/validate.h"
-    #include "wx/textctrl.h"
+    #include "wx/dataobj.h"
 #endif
 
+#include <ctype.h>
+
 #include "wx/clipbrd.h"
+
 #include "wx/textfile.h"
 
 #include "wx/caret.h"
     #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
 // ----------------------------------------------------------------------------
@@ -190,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
-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;
@@ -263,7 +290,7 @@ struct WXDLLEXPORT wxTextMultiLineData
         m_scrollRangeY = 0;
 
         m_updateScrollbarX =
-        m_updateScrollbarY = FALSE;
+        m_updateScrollbarY = false;
 
         m_widthMax = -1;
         m_lineLongest = 0;
@@ -360,14 +387,14 @@ public:
 
     // this code is unused any longer
 #if 0
-    // return TRUE if the column is in the start of the last row (hence the row
+    // return true if the column is in the start of the last row (hence the row
     // it is in is not wrapped)
     bool IsLastRow(wxTextCoord colRowStart) const
     {
         return colRowStart == GetRowStart(m_rowsStart.GetCount());
     }
 
-    // return TRUE if the column is the last column of the row starting in
+    // return true if the column is the last column of the row starting in
     // colRowStart
     bool IsLastColInRow(wxTextCoord colRowStart,
                         wxTextCoord colRowEnd,
@@ -393,7 +420,7 @@ public:
         // caller got it wrong
         wxFAIL_MSG( _T("this column is not in the start of the row!") );
 
-        return FALSE;
+        return false;
     }
 #endif // 0
 
@@ -480,7 +507,7 @@ struct WXDLLEXPORT wxTextWrappedData : public wxTextMultiLineData
 // ----------------------------------------------------------------------------
 
 /*
-   We use custom versions of wxWindows command processor to implement undo/redo
+   We use custom versions of wxWidgets command processor to implement undo/redo
    as we want to avoid storing the backpointer to wxTextCtrl in wxCommand
    itself: this is a waste of memory as all commands in the given command
    processor always have the same associated wxTextCtrl and so it makes sense
@@ -494,12 +521,12 @@ struct WXDLLEXPORT wxTextWrappedData : public wxTextMultiLineData
 class wxTextCtrlCommand : public wxCommand
 {
 public:
-    wxTextCtrlCommand(const wxString& name) : wxCommand(TRUE, name) { }
+    wxTextCtrlCommand(const wxString& name) : wxCommand(true, name) { }
 
     // we don't use these methods as they don't make sense for us as we need a
     // wxTextCtrl to be applied
-    virtual bool Do() { wxFAIL_MSG(_T("shouldn't be called")); return FALSE; }
-    virtual bool Undo() { wxFAIL_MSG(_T("shouldn't be called")); return FALSE; }
+    virtual bool Do() { wxFAIL_MSG(_T("shouldn't be called")); return false; }
+    virtual bool Undo() { wxFAIL_MSG(_T("shouldn't be called")); return false; }
 
     // instead, our command processor uses these methods
     virtual bool Do(wxTextCtrl *text) = 0;
@@ -521,6 +548,8 @@ public:
 
     virtual bool CanUndo() const;
     virtual bool Do(wxTextCtrl *text);
+    virtual bool Do() { return wxTextCtrlCommand::Do(); }
+    virtual bool Undo() { return wxTextCtrlCommand::Undo(); }
     virtual bool Undo(wxTextCtrl *text);
 
 private:
@@ -544,6 +573,8 @@ public:
 
     virtual bool CanUndo() const;
     virtual bool Do(wxTextCtrl *text);
+    virtual bool Do() { return wxTextCtrlCommand::Do(); }
+    virtual bool Undo() { return wxTextCtrlCommand::Undo(); }
     virtual bool Undo(wxTextCtrl *text);
 
 private:
@@ -561,7 +592,7 @@ class wxTextCtrlCommandProcessor : public wxCommandProcessor
 public:
     wxTextCtrlCommandProcessor(wxTextCtrl *text)
     {
-        m_compressInserts = FALSE;
+        m_compressInserts = false;
 
         m_text = text;
     }
@@ -570,7 +601,7 @@ public:
     virtual void Store(wxCommand *command);
 
     // stop compressing insert commands when this is called
-    void StopCompressing() { m_compressInserts = FALSE; }
+    void StopCompressing() { m_compressInserts = false; }
 
     // accessors
     wxTextCtrl *GetTextCtrl() const { return m_text; }
@@ -590,7 +621,7 @@ private:
     // the control we're associated with
     wxTextCtrl *m_text;
 
-    // if the flag is TRUE we're compressing subsequent insert commands into
+    // if the flag is true we're compressing subsequent insert commands into
     // one so that the entire typing could be undone in one call to Undo()
     bool m_compressInserts;
 };
@@ -599,15 +630,13 @@ private:
 // implementation
 // ============================================================================
 
-BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
     EVT_CHAR(wxTextCtrl::OnChar)
 
     EVT_SIZE(wxTextCtrl::OnSize)
-
-    EVT_IDLE(wxTextCtrl::OnIdle)
 END_EVENT_TABLE()
 
-IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
 
 // ----------------------------------------------------------------------------
 // creation
@@ -619,8 +648,8 @@ void wxTextCtrl::Init()
     m_selStart =
     m_selEnd = -1;
 
-    m_isModified = FALSE;
-    m_isEditable = TRUE;
+    m_isModified = false;
+    m_isEditable = true;
 
     m_posLast =
     m_curPos =
@@ -630,9 +659,6 @@ void wxTextCtrl::Init()
     m_heightLine =
     m_widthAvg = -1;
 
-    // init wxScrollHelper
-    SetWindow(this);
-
     // init the undo manager
     m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
 
@@ -660,11 +686,9 @@ bool wxTextCtrl::Create(wxWindow *parent,
             style |= wxALWAYS_SHOW_SB;
         }
 
-        if ( style & wxTE_WORDWRAP )
-        {
-            // wrapping words means wrapping, hence no horz scrollbar
-            style &= ~wxHSCROLL;
-        }
+        // 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 (?)
 
@@ -684,10 +708,15 @@ bool wxTextCtrl::Create(wxWindow *parent,
         m_data.sdata = new wxTextSingleLineData;
     }
 
+#if wxUSE_TWO_WINDOWS
+    if ((style & wxBORDER_MASK) == 0)
+        style |= wxBORDER_SUNKEN;
+#endif
+
     if ( !wxControl::Create(parent, id, pos, size, style,
                             validator, name) )
     {
-        return FALSE;
+        return false;
     }
 
     SetCursor(wxCURSOR_IBEAM);
@@ -720,11 +749,14 @@ bool wxTextCtrl::Create(wxWindow *parent,
 
     // we can't show caret right now as we're not shown yet and so it would
     // result in garbage on the screen - we'll do it after first OnPaint()
-    m_hasCaret = FALSE;
+    m_hasCaret = false;
 
     CreateInputHandler(wxINP_HANDLER_TEXTCTRL);
 
-    return TRUE;
+    wxSizeEvent sizeEvent(GetSize(), GetId());
+    GetEventHandler()->ProcessEvent(sizeEvent);
+
+    return true;
 }
 
 wxTextCtrl::~wxTextCtrl()
@@ -746,7 +778,7 @@ wxTextCtrl::~wxTextCtrl()
 // set/get the value
 // ----------------------------------------------------------------------------
 
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
 {
     if ( IsSingleLine() && (value == GetValue()) )
     {
@@ -761,7 +793,8 @@ void wxTextCtrl::SetValue(const wxString& value)
         SetInsertionPoint(0);
     }
 
-    // TODO: should we generate the event or not, finally?
+    if ( flags & SetValue_SendEvent )
+        SendTextUpdatedEvent();
 }
 
 const wxArrayString& wxTextCtrl::GetLines() const
@@ -801,7 +834,7 @@ wxString wxTextCtrl::GetValue() const
 
 void wxTextCtrl::Clear()
 {
-    SetValue(_T(""));
+    SetValue(wxEmptyString);
 }
 
 bool wxTextCtrl::ReplaceLine(wxTextCoord line,
@@ -857,7 +890,7 @@ bool wxTextCtrl::ReplaceLine(wxTextCoord line,
             }
 
             // the number of rows changed
-            return TRUE;
+            return true;
         }
     }
     else // no line wrap
@@ -866,7 +899,7 @@ bool wxTextCtrl::ReplaceLine(wxTextCoord line,
     }
 
     // the number of rows didn't change
-    return FALSE;
+    return false;
 }
 
 void wxTextCtrl::RemoveLine(wxTextCoord line)
@@ -983,7 +1016,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
         //     as if it does we need to refresh everything below the changed
         //     text (it will be shifted...) and we can avoid it if there is no
         //     row relayout
-        bool rowsNumberChanged = FALSE;
+        bool rowsNumberChanged = false;
 
         // (1) join lines
         const wxArrayString& linesOld = GetLines();
@@ -1091,7 +1124,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
                 // we have the replacement line for this one
                 if ( ReplaceLine(line, lines[nReplaceLine]) )
                 {
-                    rowsNumberChanged = TRUE;
+                    rowsNumberChanged = true;
                 }
 
                 UpdateMaxWidth(line);
@@ -1100,13 +1133,13 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
             {
                 // (4b) delete all extra lines (note that we need to delete
                 //      them backwards because indices shift while we do it)
-                bool deletedLongestLine = FALSE;
+                bool deletedLongestLine = false;
                 for ( wxTextCoord lineDel = lineEnd; lineDel >= line; lineDel-- )
                 {
                     if ( lineDel == MData().m_lineLongest )
                     {
                         // we will need to recalc the max line width
-                        deletedLongestLine = TRUE;
+                        deletedLongestLine = true;
                     }
 
                     RemoveLine(lineDel);
@@ -1118,7 +1151,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
                 }
 
                 // even the line number changed
-                rowsNumberChanged = TRUE;
+                rowsNumberChanged = true;
 
                 // update line to exit the loop
                 line = lineEnd + 1;
@@ -1129,7 +1162,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
         if ( nReplaceLine < nReplaceCount )
         {
             // even the line number changed
-            rowsNumberChanged = TRUE;
+            rowsNumberChanged = true;
 
             do
             {
@@ -1187,7 +1220,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
             RefreshLineRange(lineEnd + 1, 0);
 
             // the vert scrollbar might [dis]appear
-            MData().m_updateScrollbarY = TRUE;
+            MData().m_updateScrollbarY = true;
         }
 
         // must recalculate it - will do later
@@ -1229,7 +1262,7 @@ void wxTextCtrl::Remove(wxTextPos from, wxTextPos to)
     // if necessary
     OrderPositions(from, to);
 
-    Replace(from, to, _T(""));
+    Replace(from, to, wxEmptyString);
 }
 
 void wxTextCtrl::WriteText(const wxString& text)
@@ -1412,6 +1445,10 @@ void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
     }
     else // valid sel range
     {
+        // remember the 'to' position as the current position, used to move the
+        // caret there later
+        wxTextPos toOrig = to;
+
         OrderPositions(from, to);
 
         wxCHECK_RET( to <= GetLastPosition(),
@@ -1457,8 +1494,8 @@ void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
         }
         //else: nothing to do
 
-        // the insertion point is put at the end of selection
-        DoSetInsertionPoint(to);
+        // the insertion point is put at the location where the caret was moved
+        DoSetInsertionPoint(toOrig);
     }
 }
 
@@ -1502,7 +1539,7 @@ bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
     if ( !HasSelection() )
     {
         // no selection at all, hence no selection in this line
-        return FALSE;
+        return false;
     }
 
     wxTextCoord lineStart, colStart;
@@ -1510,7 +1547,7 @@ bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
     if ( lineStart > line )
     {
         // this line is entirely above the selection
-        return FALSE;
+        return false;
     }
 
     wxTextCoord lineEnd, colEnd;
@@ -1518,7 +1555,7 @@ bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
     if ( lineEnd < line )
     {
         // this line is entirely below the selection
-        return FALSE;
+        return false;
     }
 
     if ( line == lineStart )
@@ -1543,7 +1580,7 @@ bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
             *end = GetLineLength(line);
     }
 
-    return TRUE;
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -1561,9 +1598,14 @@ bool wxTextCtrl::IsEditable() const
     return m_isEditable && IsEnabled();
 }
 
+void wxTextCtrl::MarkDirty()
+{
+    m_isModified = true;
+}
+
 void wxTextCtrl::DiscardEdits()
 {
-    m_isModified = FALSE;
+    m_isModified = false;
 }
 
 void wxTextCtrl::SetEditable(bool editable)
@@ -1619,7 +1661,10 @@ wxString wxTextCtrl::GetLineText(wxTextCoord line) const
     }
     else // multiline
     {
-        wxCHECK_MSG( (size_t)line < GetLineCount(), _T(""),
+        //this is called during DoGetBestSize
+        if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
+
+        wxCHECK_MSG( (size_t)line < GetLineCount(), wxEmptyString,
                      _T("line index out of range") );
 
         return GetLines()[line];
@@ -1638,7 +1683,7 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const
     // if they are out of range
     if ( IsSingleLine() )
     {
-        return x > GetLastPosition() || y > 0 ? -1 : x;
+        return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
     }
     else // multiline
     {
@@ -1673,14 +1718,14 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
     if ( IsSingleLine() )
     {
         if ( (size_t)pos > m_value.length() )
-            return FALSE;
+            return false;
 
         if ( x )
             *x = pos;
         if ( y )
             *y = 0;
 
-        return TRUE;
+        return true;
     }
     else // multiline
     {
@@ -1705,7 +1750,7 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
                               _T("XYToPosition() or PositionToXY() broken") );
 #endif // WXDEBUG_TEXT
 
-                return TRUE;
+                return true;
             }
             else // go further down
             {
@@ -1714,7 +1759,7 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
         }
 
         // beyond the last line
-        return FALSE;
+        return false;
     }
 }
 
@@ -1735,6 +1780,8 @@ wxTextCoord wxTextCtrl::GetRowsPerLine(wxTextCoord line) const
 wxTextCoord wxTextCtrl::GetRowCount() const
 {
     wxTextCoord count = GetLineCount();
+    if (count == 0)
+        return 0;
     if ( WrapLines() )
     {
         count = GetFirstRowOfLine(count - 1) +
@@ -1786,7 +1833,7 @@ bool wxTextCtrl::PositionToLogicalXY(wxTextPos pos,
     else // must really calculate col/line from pos
     {
         if ( !PositionToXY(pos, &col, &line) )
-            return FALSE;
+            return false;
     }
 
     int hLine = GetLineHeight();
@@ -1815,7 +1862,7 @@ bool wxTextCtrl::PositionToLogicalXY(wxTextPos pos,
     if ( yOut )
         *yOut = y;
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrl::PositionToDeviceXY(wxTextPos pos,
@@ -1824,13 +1871,13 @@ bool wxTextCtrl::PositionToDeviceXY(wxTextPos pos,
 {
     wxCoord x, y;
     if ( !PositionToLogicalXY(pos, &x, &y) )
-        return FALSE;
+        return false;
 
     // finally translate the logical text rect coords into physical client
     // coords
     CalcScrolledPosition(m_rectText.x + x, m_rectText.y + y, xOut, yOut);
 
-    return TRUE;
+    return true;
 }
 
 wxPoint wxTextCtrl::GetCaretPosition() const
@@ -1847,7 +1894,9 @@ wxPoint wxTextCtrl::GetCaretPosition() const
 // pos may be -1 to show the current position
 void wxTextCtrl::ShowPosition(wxTextPos pos)
 {
-    HideCaret();
+    bool showCaret = GetCaret() && GetCaret()->IsVisible();
+    if (showCaret)
+        HideCaret();
 
     if ( IsSingleLine() )
     {
@@ -1967,7 +2016,8 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
     }
     //else: multiline but no scrollbars, hence nothing to do
 
-    ShowCaret();
+    if (showCaret)
+        ShowCaret();
 }
 
 // ----------------------------------------------------------------------------
@@ -2101,13 +2151,13 @@ void wxTextCtrl::Cut()
 bool wxTextCtrl::DoCut()
 {
     if ( !HasSelection() )
-        return FALSE;
+        return false;
 
     Copy();
 
     RemoveSelection();
 
-    return TRUE;
+    return true;
 }
 
 void wxTextCtrl::Paste()
@@ -2131,12 +2181,12 @@ bool wxTextCtrl::DoPaste()
         {
             WriteText(text);
 
-            return TRUE;
+            return true;
         }
     }
 #endif // wxUSE_CLIPBOARD
 
-    return FALSE;
+    return false;
 }
 
 // ----------------------------------------------------------------------------
@@ -2176,7 +2226,7 @@ void wxTextCtrlCommandProcessor::Store(wxCommand *command)
         }
 
         // append the following insert commands to this one
-        m_compressInserts = TRUE;
+        m_compressInserts = true;
 
         // let the base class version will do the job normally
     }
@@ -2211,17 +2261,17 @@ bool wxTextCtrlInsertCommand::Do(wxTextCtrl *text)
     // and now do insert it
     text->WriteText(m_text);
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrlInsertCommand::Undo(wxTextCtrl *text)
 {
-    wxCHECK_MSG( CanUndo(), FALSE, _T("impossible to undo insert cmd") );
+    wxCHECK_MSG( CanUndo(), false, _T("impossible to undo insert cmd") );
 
     // remove the text from where we inserted it
     text->Remove(m_from, m_from + m_text.length());
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrlRemoveCommand::CanUndo() const
@@ -2236,7 +2286,7 @@ bool wxTextCtrlRemoveCommand::Do(wxTextCtrl *text)
     m_textDeleted = text->GetSelectionText();
     text->RemoveSelection();
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrlRemoveCommand::Undo(wxTextCtrl *text)
@@ -2247,7 +2297,7 @@ bool wxTextCtrlRemoveCommand::Undo(wxTextCtrl *text)
     text->SetInsertionPoint(m_from > posLast ? posLast : m_from);
     text->WriteText(m_textDeleted);
 
-    return TRUE;
+    return true;
 }
 
 void wxTextCtrl::Undo()
@@ -2311,7 +2361,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
             lines = 5;
         else if ( lines > 10 )
             lines = 10;
-        h *= 10;
+        h *= lines;
     }
 
     wxRect rectText;
@@ -2323,7 +2373,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
 
 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);
 
@@ -2426,7 +2476,7 @@ void wxTextCtrl::UpdateLastVisible()
     SData().m_colLastVisible += SData().m_colStart;
 
     wxLogTrace(_T("text"), _T("Last visible column/position is %d/%ld"),
-               SData().m_colLastVisible, SData().m_posLastVisible);
+               (int) SData().m_colLastVisible, (long) SData().m_posLastVisible);
 }
 
 void wxTextCtrl::OnSize(wxSizeEvent& event)
@@ -2444,7 +2494,7 @@ void wxTextCtrl::OnSize(wxSizeEvent& event)
 #endif // 0
 
         MData().m_updateScrollbarX =
-        MData().m_updateScrollbarY = TRUE;
+        MData().m_updateScrollbarY = true;
     }
 
     event.Skip();
@@ -2628,7 +2678,7 @@ size_t wxTextCtrl::GetPartOfWrappedLine(const wxChar* text,
 
     wxString s(text);
     wxTextCoord col;
-    wxCoord wReal = -1;
+    wxCoord wReal = wxDefaultCoord;
     switch ( HitTestLine(s, m_rectText.width, &col) )
     {
             /*
@@ -2653,12 +2703,12 @@ size_t wxTextCtrl::GetPartOfWrappedLine(const wxChar* text,
                     col--;
 
                     // recalc the width
-                    wReal = -1;
+                    wReal = wxDefaultCoord;
                 }
                 //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;
@@ -2672,7 +2722,7 @@ size_t wxTextCtrl::GetPartOfWrappedLine(const wxChar* text,
                         if ( colWordStart != col )
                         {
                             // will have to recalc the real width
-                            wReal = -1;
+                            wReal = wxDefaultCoord;
 
                             col = colWordStart;
                         }
@@ -2695,7 +2745,7 @@ size_t wxTextCtrl::GetPartOfWrappedLine(const wxChar* text,
 
     if ( widthReal )
     {
-        if ( wReal == -1 )
+        if ( wReal == wxDefaultCoord )
         {
             // calc it if not done yet
             wReal = GetTextWidth(s.Truncate(col));
@@ -2915,6 +2965,18 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTestLine(const wxString& line,
     return res;
 }
 
+wxTextCtrlHitTestResult wxTextCtrl::HitTest(const wxPoint& pt, long *pos) const
+{
+    wxTextCoord x, y;
+    wxTextCtrlHitTestResult rc = HitTest(pt, &x, &y);
+    if ( rc != wxTE_HT_UNKNOWN && pos )
+    {
+        *pos = XYToPosition(x, y);
+    }
+
+    return rc;
+}
+
 wxTextCtrlHitTestResult wxTextCtrl::HitTest(const wxPoint& pos,
                                             wxTextCoord *colOut,
                                             wxTextCoord *rowOut) const
@@ -2926,7 +2988,7 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTestLogical(const wxPoint& pos,
                                                    wxTextCoord *colOut,
                                                    wxTextCoord *rowOut) const
 {
-    return HitTest2(pos.y, pos.x, 0, rowOut, colOut, NULL, NULL, FALSE);
+    return HitTest2(pos.y, pos.x, 0, rowOut, colOut, NULL, NULL, false);
 }
 
 wxTextCtrlHitTestResult wxTextCtrl::HitTest2(wxCoord y0,
@@ -3130,7 +3192,7 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
                 rowInLine = 0;
 
     if ( row < 0 )
-        return FALSE;
+        return false;
 
     int nLines = GetNumberOfLines();
     if ( WrapLines() )
@@ -3153,13 +3215,13 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
         if ( line == nLines )
         {
             // the row is out of range
-            return FALSE;
+            return false;
         }
     }
     else // no line wrapping, everything is easy
     {
         if ( row >= nLines )
-            return FALSE;
+            return false;
 
         line = row;
     }
@@ -3169,7 +3231,7 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
     if ( rowInLineOut )
         *rowInLineOut = rowInLine;
 
-    return TRUE;
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -3314,7 +3376,7 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
         if ( dx > 0 )
         {
             // refresh the uncovered part on the left
-            Refresh(TRUE, &rect);
+            Refresh(true, &rect);
 
             // and now the area on the right
             rect.x = m_rectText.x + posLastVisible;
@@ -3327,7 +3389,7 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
             rect.width += m_rectText.width - posLastVisible;
         }
 
-        Refresh(TRUE, &rect);
+        Refresh(true, &rect);
 
         // I don't know exactly why is this needed here but without it we may
         // scroll the window again (from the same method) before the previously
@@ -3495,7 +3557,7 @@ void wxTextCtrl::UpdateScrollbars()
         // just to suppress compiler warnings about using uninit vars below
         charWidth = maxWidth = 0;
 
-        showScrollbarX = FALSE;
+        showScrollbarX = false;
     }
 
     // calc the scrollbars ranges
@@ -3532,7 +3594,7 @@ void wxTextCtrl::UpdateScrollbars()
         SetScrollbars(charWidth, lineHeight,
                       scrollRangeX, scrollRangeY,
                       x, y,
-                      TRUE /* no refresh */);
+                      true /* no refresh */);
 
         if ( scrollRangeXOld )
         {
@@ -3549,10 +3611,10 @@ void wxTextCtrl::UpdateScrollbars()
     }
 
     MData().m_updateScrollbarX =
-    MData().m_updateScrollbarY = FALSE;
+    MData().m_updateScrollbarY = false;
 }
 
-void wxTextCtrl::OnIdle(wxIdleEvent& event)
+void wxTextCtrl::OnInternalIdle()
 {
     // notice that single line text control never has scrollbars
     if ( !IsSingleLine() &&
@@ -3560,8 +3622,7 @@ void wxTextCtrl::OnIdle(wxIdleEvent& event)
     {
         UpdateScrollbars();
     }
-
-    event.Skip();
+    wxControl::OnInternalIdle();
 }
 
 bool wxTextCtrl::SendAutoScrollEvents(wxScrollWinEvent& event) const
@@ -3789,7 +3850,7 @@ void wxTextCtrl::RefreshTextRect(const wxRect& rectClient, bool textOnly)
     rect.Offset(m_rectText.GetPosition());
 
     // don't refresh beyond the text area unless we're refreshing the line wrap
-    // marks in which case textOnly is FALSE
+    // marks in which case textOnly is false
     if ( textOnly )
     {
         if ( rect.GetRight() > m_rectText.GetRight() )
@@ -3826,7 +3887,7 @@ void wxTextCtrl::RefreshTextRect(const wxRect& rectClient, bool textOnly)
     wxLogTrace(_T("text"), _T("Refreshing (%d, %d)-(%d, %d)"),
                rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
 
-    Refresh(TRUE, &rect);
+    Refresh(true, &rect);
 }
 
 void wxTextCtrl::RefreshLineWrapMarks(wxTextCoord rowFirst,
@@ -3840,7 +3901,7 @@ void wxTextCtrl::RefreshLineWrapMarks(wxTextCoord rowFirst,
         rectMarks.y = rowFirst*GetLineHeight();
         rectMarks.height = (rowLast - rowFirst)*GetLineHeight();
 
-        RefreshTextRect(rectMarks, FALSE /* don't limit to text area */);
+        RefreshTextRect(rectMarks, false /* don't limit to text area */);
     }
 }
 
@@ -4098,6 +4159,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();
+
     wxRect rectTextArea = GetRealTextArea();
     wxPoint pt = GetClientAreaOrigin();
     wxRect rectTextAreaAdjusted = rectTextArea;
@@ -4162,11 +4224,11 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
 
     // show caret first time only: we must show it after drawing the text or
     // the display can be corrupted when it's hidden
-    if ( !m_hasCaret && GetCaret() )
+    if ( !m_hasCaret && GetCaret() && (FindFocus() == this) )
     {
         ShowCaret();
 
-        m_hasCaret = TRUE;
+        m_hasCaret = true;
     }
 }
 
@@ -4177,7 +4239,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
 bool wxTextCtrl::SetFont(const wxFont& font)
 {
     if ( !wxControl::SetFont(font) )
-        return FALSE;
+        return false;
 
     // and refresh everything, of course
     InitInsertionPoint();
@@ -4197,17 +4259,20 @@ bool wxTextCtrl::SetFont(const wxFont& font)
 
     Refresh();
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrl::Enable(bool enable)
 {
     if ( !wxTextCtrlBase::Enable(enable) )
-        return FALSE;
+        return false;
 
-    ShowCaret(enable);
+    if (FindFocus() == this && GetCaret() &&
+        ((enable && !GetCaret()->IsVisible()) ||
+         (!enable && GetCaret()->IsVisible())))
+        ShowCaret(enable);
 
-    return TRUE;
+    return true;
 }
 
 void wxTextCtrl::CreateCaret()
@@ -4219,7 +4284,7 @@ void wxTextCtrl::CreateCaret()
         // FIXME use renderer
         caret = new wxCaret(this, 1, GetLineHeight());
 #ifndef __WXMSW__
-        caret->SetBlinkTime(0);
+        wxCaret::SetBlinkTime(0);
 #endif // __WXMSW__
     }
     else
@@ -4241,7 +4306,9 @@ void wxTextCtrl::ShowCaret(bool show)
         caret->Move(GetCaretPosition());
 
         // and show it there
-        caret->Show(show);
+        if ((show && !caret->IsVisible()) ||
+            (!show && caret->IsVisible()))
+            caret->Show(show);
     }
 }
 
@@ -4333,28 +4400,28 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
                                const wxString& strArg)
 {
     // has the text changed as result of this action?
-    bool textChanged = FALSE;
+    bool textChanged = false;
 
     // the remembered cursor abscissa for multiline text controls is usually
     // reset after each user action but for ones which do use it (UP and DOWN
     // for example) we shouldn't do it - as indicated by this flag
-    bool rememberAbscissa = FALSE;
+    bool rememberAbscissa = false;
 
     // the command this action corresponds to or NULL if this action doesn't
     // change text at all or can't be undone
     wxTextCtrlCommand *command = (wxTextCtrlCommand *)NULL;
 
     wxString action;
-    bool del = FALSE,
-         sel = FALSE;
+    bool del = false,
+         sel = false;
     if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_DEL, &action) )
     {
         if ( IsEditable() )
-            del = TRUE;
+            del = true;
     }
     else if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_SEL, &action) )
     {
-        sel = TRUE;
+        sel = true;
     }
     else // not selection nor delete action
     {
@@ -4394,7 +4461,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             if ( newPos != INVALID_POS_VALUE )
             {
                 // remember where the cursor original had been
-                rememberAbscissa = TRUE;
+                rememberAbscissa = true;
             }
         }
     }
@@ -4407,7 +4474,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             if ( newPos != INVALID_POS_VALUE )
             {
                 // remember where the cursor original had been
-                rememberAbscissa = TRUE;
+                rememberAbscissa = true;
             }
         }
     }
@@ -4434,7 +4501,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             // inserting text can be undone
             command = new wxTextCtrlInsertCommand(strArg);
 
-            textChanged = TRUE;
+            textChanged = true;
         }
     }
     else if ( (action == wxACTION_TEXT_PAGE_UP) ||
@@ -4451,7 +4518,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             }
 
             // remember where the cursor original had been
-            rememberAbscissa = TRUE;
+            rememberAbscissa = true;
 
             bool goUp = action == wxACTION_TEXT_PAGE_UP;
             for ( size_t line = 0; line < count; line++ )
@@ -4498,7 +4565,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             }
 
             // scroll vertically only
-            Scroll(-1, y);
+            Scroll(wxDefaultCoord, y);
         }
     }
     else if ( action == wxACTION_TEXT_SEL_WORD )
@@ -4613,7 +4680,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
         m_cmdProcessor->Submit(command);
 
         // undoable commands always change text
-        textChanged = TRUE;
+        textChanged = true;
     }
     else // no undoable command
     {
@@ -4626,14 +4693,13 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
 
         wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
         InitCommandEvent(event);
-        event.SetString(GetValue());
         GetEventHandler()->ProcessEvent(event);
 
         // as the text changed...
-        m_isModified = TRUE;
+        m_isModified = true;
     }
 
-    return TRUE;
+    return true;
 }
 
 void wxTextCtrl::OnChar(wxKeyEvent& event)
@@ -4642,6 +4708,9 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     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) )
@@ -4663,6 +4732,14 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
             // 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
@@ -4673,6 +4750,14 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     event.Skip();
 }
 
+/* static */
+wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdTextCtrlInputHandler s_handler(handlerDef);
+
+    return &s_handler;
+}
+
 // ----------------------------------------------------------------------------
 // wxStdTextCtrlInputHandler
 // ----------------------------------------------------------------------------
@@ -4702,13 +4787,13 @@ wxTextPos wxStdTextCtrlInputHandler::HitTest(const wxTextCtrl *text,
     return pos;
 }
 
-bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
+bool wxStdTextCtrlInputHandler::HandleKey(wxInputConsumer *consumer,
                                           const wxKeyEvent& event,
                                           bool pressed)
 {
     // we're only interested in key presses
     if ( !pressed )
-        return FALSE;
+        return false;
 
     int keycode = event.GetKeyCode();
 
@@ -4762,14 +4847,12 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
             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:
-        case WXK_PRIOR:
             action << wxACTION_TEXT_PAGE_UP;
             break;
 
@@ -4819,22 +4902,22 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
 
     if ( (action != wxACTION_NONE) && (action != wxACTION_TEXT_PREFIX_SEL) )
     {
-        control->PerformAction(action, -1, str);
+        consumer->PerformAction(action, -1, str);
 
-        return TRUE;
+        return true;
     }
 
-    return wxStdInputHandler::HandleKey(control, event, pressed);
+    return wxStdInputHandler::HandleKey(consumer, event, pressed);
 }
 
-bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
+bool wxStdTextCtrlInputHandler::HandleMouse(wxInputConsumer *consumer,
                                             const wxMouseEvent& event)
 {
     if ( event.LeftDown() )
     {
         wxASSERT_MSG( !m_winCapture, _T("left button going down twice?") );
 
-        wxTextCtrl *text = wxStaticCast(control, wxTextCtrl);
+        wxTextCtrl *text = wxStaticCast(consumer->GetInputWindow(), wxTextCtrl);
 
         m_winCapture = text;
         m_winCapture->CaptureMouse();
@@ -4850,7 +4933,7 @@ bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
     else if ( event.LeftDClick() )
     {
         // select the word the cursor is on
-        control->PerformAction(wxACTION_TEXT_SEL_WORD);
+        consumer->PerformAction(wxACTION_TEXT_SEL_WORD);
     }
     else if ( event.LeftUp() )
     {
@@ -4863,10 +4946,10 @@ bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
         }
     }
 
-    return wxStdInputHandler::HandleMouse(control, event);
+    return wxStdInputHandler::HandleMouse(consumer, event);
 }
 
-bool wxStdTextCtrlInputHandler::HandleMouseMove(wxControl *control,
+bool wxStdTextCtrlInputHandler::HandleMouseMove(wxInputConsumer *consumer,
                                                 const wxMouseEvent& event)
 {
     if ( m_winCapture )
@@ -4880,19 +4963,31 @@ bool wxStdTextCtrlInputHandler::HandleMouseMove(wxControl *control,
         }
     }
 
-    return wxStdInputHandler::HandleMouseMove(control, event);
+    return wxStdInputHandler::HandleMouseMove(consumer, event);
 }
 
-bool wxStdTextCtrlInputHandler::HandleFocus(wxControl *control,
-                                            const wxFocusEvent& event)
+bool
+wxStdTextCtrlInputHandler::HandleFocus(wxInputConsumer *consumer,
+                                       const wxFocusEvent& event)
 {
-    wxTextCtrl *text = wxStaticCast(control, wxTextCtrl);
+    wxTextCtrl *text = wxStaticCast(consumer->GetInputWindow(), wxTextCtrl);
 
     // the selection appearance changes depending on whether we have the focus
     text->RefreshSelection();
 
+    if (event.GetEventType() == wxEVT_SET_FOCUS)
+    {
+        if (text->GetCaret() && !text->GetCaret()->IsVisible())
+            text->ShowCaret();
+    }
+    else
+    {
+        if (text->GetCaret() && text->GetCaret()->IsVisible())
+            text->HideCaret();
+    }
+
     // never refresh entirely
-    return FALSE;
+    return false;
 }
 
 #endif // wxUSE_TEXTCTRL