]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/textctrl.cpp
don't try to add emission hook if GtkWidget type is not loaded
[wxWidgets.git] / src / univ / textctrl.cpp
index 9d5bdc38c32e92f262a91dac07a689637c93affa..ff7515af56758b1cf4b71677593cae22aee4ea6f 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/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
 // ----------------------------------------------------------------------------
@@ -191,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;
@@ -201,7 +227,7 @@ static const size_t PAGE_OVERLAP_IN_LINES = 1;
 // ----------------------------------------------------------------------------
 
 // 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;
@@ -225,7 +251,7 @@ struct WXDLLEXPORT wxTextSingleLineData
 };
 
 // the data only used by multi line text controls
-struct WXDLLEXPORT wxTextMultiLineData
+struct wxTextMultiLineData
 {
     // the lines of text
     wxArrayString m_lines;
@@ -264,7 +290,7 @@ struct WXDLLEXPORT wxTextMultiLineData
         m_scrollRangeY = 0;
 
         m_updateScrollbarX =
-        m_updateScrollbarY = FALSE;
+        m_updateScrollbarY = false;
 
         m_widthMax = -1;
         m_lineLongest = 0;
@@ -274,7 +300,7 @@ struct WXDLLEXPORT wxTextMultiLineData
 };
 
 // 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,
@@ -361,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,
@@ -394,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
 
@@ -434,7 +460,7 @@ WX_DECLARE_OBJARRAY(wxWrappedLineData, 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
@@ -481,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
@@ -495,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;
@@ -522,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:
@@ -545,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:
@@ -562,7 +592,7 @@ class wxTextCtrlCommandProcessor : public wxCommandProcessor
 public:
     wxTextCtrlCommandProcessor(wxTextCtrl *text)
     {
-        m_compressInserts = FALSE;
+        m_compressInserts = false;
 
         m_text = text;
     }
@@ -571,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; }
@@ -591,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;
 };
@@ -600,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
@@ -620,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 =
@@ -631,9 +659,6 @@ void wxTextCtrl::Init()
     m_heightLine =
     m_widthAvg = -1;
 
-    // init wxScrollHelper
-    SetWindow(this);
-
     // init the undo manager
     m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
 
@@ -661,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 (?)
 
@@ -685,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);
@@ -721,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()
@@ -747,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()) )
     {
@@ -762,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
@@ -802,7 +834,7 @@ wxString wxTextCtrl::GetValue() const
 
 void wxTextCtrl::Clear()
 {
-    SetValue(_T(""));
+    SetValue(wxEmptyString);
 }
 
 bool wxTextCtrl::ReplaceLine(wxTextCoord line,
@@ -858,7 +890,7 @@ bool wxTextCtrl::ReplaceLine(wxTextCoord line,
             }
 
             // the number of rows changed
-            return TRUE;
+            return true;
         }
     }
     else // no line wrap
@@ -867,7 +899,7 @@ bool wxTextCtrl::ReplaceLine(wxTextCoord line,
     }
 
     // the number of rows didn't change
-    return FALSE;
+    return false;
 }
 
 void wxTextCtrl::RemoveLine(wxTextCoord line)
@@ -984,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();
@@ -1092,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);
@@ -1101,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);
@@ -1119,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;
@@ -1130,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
             {
@@ -1188,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
@@ -1230,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)
@@ -1413,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(),
@@ -1458,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);
     }
 }
 
@@ -1503,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;
@@ -1511,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;
@@ -1519,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 )
@@ -1544,7 +1580,7 @@ bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
             *end = GetLineLength(line);
     }
 
-    return TRUE;
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -1562,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)
@@ -1620,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];
@@ -1639,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
     {
@@ -1674,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
     {
@@ -1706,7 +1750,7 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
                               _T("XYToPosition() or PositionToXY() broken") );
 #endif // WXDEBUG_TEXT
 
-                return TRUE;
+                return true;
             }
             else // go further down
             {
@@ -1715,7 +1759,7 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
         }
 
         // beyond the last line
-        return FALSE;
+        return false;
     }
 }
 
@@ -1736,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) +
@@ -1787,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();
@@ -1816,7 +1862,7 @@ bool wxTextCtrl::PositionToLogicalXY(wxTextPos pos,
     if ( yOut )
         *yOut = y;
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrl::PositionToDeviceXY(wxTextPos pos,
@@ -1825,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
@@ -1848,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() )
     {
@@ -1968,7 +2016,8 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
     }
     //else: multiline but no scrollbars, hence nothing to do
 
-    ShowCaret();
+    if (showCaret)
+        ShowCaret();
 }
 
 // ----------------------------------------------------------------------------
@@ -2102,13 +2151,13 @@ void wxTextCtrl::Cut()
 bool wxTextCtrl::DoCut()
 {
     if ( !HasSelection() )
-        return FALSE;
+        return false;
 
     Copy();
 
     RemoveSelection();
 
-    return TRUE;
+    return true;
 }
 
 void wxTextCtrl::Paste()
@@ -2132,12 +2181,12 @@ bool wxTextCtrl::DoPaste()
         {
             WriteText(text);
 
-            return TRUE;
+            return true;
         }
     }
 #endif // wxUSE_CLIPBOARD
 
-    return FALSE;
+    return false;
 }
 
 // ----------------------------------------------------------------------------
@@ -2177,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
     }
@@ -2212,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
@@ -2237,7 +2286,7 @@ bool wxTextCtrlRemoveCommand::Do(wxTextCtrl *text)
     m_textDeleted = text->GetSelectionText();
     text->RemoveSelection();
 
-    return TRUE;
+    return true;
 }
 
 bool wxTextCtrlRemoveCommand::Undo(wxTextCtrl *text)
@@ -2248,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()
@@ -2312,7 +2361,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
             lines = 5;
         else if ( lines > 10 )
             lines = 10;
-        h *= 10;
+        h *= lines;
     }
 
     wxRect rectText;
@@ -2324,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);
 
@@ -2427,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)
@@ -2445,7 +2494,7 @@ void wxTextCtrl::OnSize(wxSizeEvent& event)
 #endif // 0
 
         MData().m_updateScrollbarX =
-        MData().m_updateScrollbarY = TRUE;
+        MData().m_updateScrollbarY = true;
     }
 
     event.Skip();
@@ -2629,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) )
     {
             /*
@@ -2654,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;
@@ -2673,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;
                         }
@@ -2696,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));
@@ -2916,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
@@ -2927,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,
@@ -3131,7 +3192,7 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
                 rowInLine = 0;
 
     if ( row < 0 )
-        return FALSE;
+        return false;
 
     int nLines = GetNumberOfLines();
     if ( WrapLines() )
@@ -3154,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;
     }
@@ -3170,7 +3231,7 @@ bool wxTextCtrl::GetLineAndRow(wxTextCoord row,
     if ( rowInLineOut )
         *rowInLineOut = rowInLine;
 
-    return TRUE;
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -3315,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;
@@ -3328,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
@@ -3496,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
@@ -3533,7 +3594,7 @@ void wxTextCtrl::UpdateScrollbars()
         SetScrollbars(charWidth, lineHeight,
                       scrollRangeX, scrollRangeY,
                       x, y,
-                      TRUE /* no refresh */);
+                      true /* no refresh */);
 
         if ( scrollRangeXOld )
         {
@@ -3550,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() &&
@@ -3561,8 +3622,7 @@ void wxTextCtrl::OnIdle(wxIdleEvent& event)
     {
         UpdateScrollbars();
     }
-
-    event.Skip();
+    wxControl::OnInternalIdle();
 }
 
 bool wxTextCtrl::SendAutoScrollEvents(wxScrollWinEvent& event) const
@@ -3672,7 +3732,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
-            posCount = wxSTRING_MAXLEN;
+            posCount = wxString::npos;
         }
         else // last line
         {
@@ -3790,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() )
@@ -3827,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,
@@ -3841,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 */);
     }
 }
 
@@ -4099,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;
@@ -4163,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;
     }
 }
 
@@ -4178,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();
@@ -4198,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,9 +4283,6 @@ void wxTextCtrl::CreateCaret()
     {
         // FIXME use renderer
         caret = new wxCaret(this, 1, GetLineHeight());
-#ifndef __WXMSW__
-        caret->SetBlinkTime(0);
-#endif // __WXMSW__
     }
     else
     {
@@ -4242,7 +4303,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);
     }
 }
 
@@ -4334,28 +4397,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
     {
@@ -4395,7 +4458,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             if ( newPos != INVALID_POS_VALUE )
             {
                 // remember where the cursor original had been
-                rememberAbscissa = TRUE;
+                rememberAbscissa = true;
             }
         }
     }
@@ -4408,7 +4471,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             if ( newPos != INVALID_POS_VALUE )
             {
                 // remember where the cursor original had been
-                rememberAbscissa = TRUE;
+                rememberAbscissa = true;
             }
         }
     }
@@ -4435,7 +4498,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) ||
@@ -4452,7 +4515,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++ )
@@ -4499,7 +4562,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
             }
 
             // scroll vertically only
-            Scroll(-1, y);
+            Scroll(wxDefaultCoord, y);
         }
     }
     else if ( action == wxACTION_TEXT_SEL_WORD )
@@ -4614,7 +4677,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
         m_cmdProcessor->Submit(command);
 
         // undoable commands always change text
-        textChanged = TRUE;
+        textChanged = true;
     }
     else // no undoable command
     {
@@ -4627,14 +4690,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)
@@ -4643,6 +4705,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) )
@@ -4664,6 +4729,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
@@ -4674,6 +4747,14 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     event.Skip();
 }
 
+/* static */
+wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdTextCtrlInputHandler s_handler(handlerDef);
+
+    return &s_handler;
+}
+
 // ----------------------------------------------------------------------------
 // wxStdTextCtrlInputHandler
 // ----------------------------------------------------------------------------
@@ -4703,13 +4784,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();
 
@@ -4763,14 +4844,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;
 
@@ -4820,22 +4899,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();
@@ -4851,7 +4930,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() )
     {
@@ -4864,10 +4943,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 )
@@ -4881,19 +4960,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