X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1e6feb95a79834836e88143b15d9f424ebe79621..db71eb0640221199170ac9ea83371c2d467fa456:/src/univ/textctrl.cpp diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 98b53bda8a..5b1c204822 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -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 ///////////////////////////////////////////////////////////////////////////// /* @@ -44,10 +44,10 @@ 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. @@ -117,10 +117,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "univtextctrl.h" -#endif - #include "wx/wxprec.h" #ifdef __BORLANDC__ @@ -129,15 +125,19 @@ #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 + #include "wx/clipbrd.h" + #include "wx/textfile.h" #include "wx/caret.h" @@ -165,6 +165,33 @@ #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