#include "wx/cmdproc.h"
-// turn extra wxTextCtrl-specific debugging on/off
-#define WXDEBUG_TEXT
+#if wxDEBUG_LEVEL >= 2
+ // turn extra wxTextCtrl-specific debugging on/off
+ #define WXDEBUG_TEXT
-// turn wxTextCtrl::Replace() debugging on (slows down code a *lot*!)
-#define WXDEBUG_TEXT_REPLACE
-
-#ifndef __WXDEBUG__
- #undef WXDEBUG_TEXT
- #undef WXDEBUG_TEXT_REPLACE
-#endif
+ // turn wxTextCtrl::Replace() debugging on (slows down code a *lot*!)
+ #define WXDEBUG_TEXT_REPLACE
+#endif // wxDEBUG_LEVEL >= 2
// wxStringTokenize only needed for debug checks
#ifdef WXDEBUG_TEXT_REPLACE
// ----------------------------------------------------------------------------
// names of text ctrl commands
-#define wxTEXT_COMMAND_INSERT _T("insert")
-#define wxTEXT_COMMAND_REMOVE _T("remove")
+#define wxTEXT_COMMAND_INSERT wxT("insert")
+#define wxTEXT_COMMAND_REMOVE wxT("remove")
// the value which is never used for text position, even not -1 which is
// sometimes used for some special meaning
// for the first one)
wxTextCoord GetRowStart(wxTextCoord row) const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return row ? m_rowsStart[row - 1] : 0;
}
// be given to us)
wxTextCoord GetRowLength(wxTextCoord row, wxTextCoord lenLine) const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
// note that m_rowsStart[row] is the same as GetRowStart(row + 1) (but
// slightly more efficient) and lenLine is the same as the start of the
// return the width of the row in pixels
wxCoord GetRowWidth(wxTextCoord row) const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowsWidth[row];
}
// return the number of rows
size_t GetRowCount() const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowsStart.GetCount() + 1;
}
// return the number of additional (i.e. after the first one) rows
size_t GetExtraRowCount() const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowsStart.GetCount();
}
// return the first row of this line
wxTextCoord GetFirstRow() const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowFirst;
}
// return the first row of the next line
wxTextCoord GetNextRow() const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowFirst + m_rowsStart.GetCount() + 1;
}
// this just provides direct access to m_rowsStart aerray for efficiency
wxTextCoord GetExtraRowStart(wxTextCoord row) const
{
- wxASSERT_MSG( IsValid(), _T("this line hadn't been laid out") );
+ wxASSERT_MSG( IsValid(), wxT("this line hadn't been laid out") );
return m_rowsStart[row];
}
: GetRowStart(n + 1);
wxASSERT_MSG( colRowEnd < colNextRowStart,
- _T("this column is not in this row at all!") );
+ wxT("this column is not in this row at all!") );
return colRowEnd == colNextRowStart - 1;
}
}
// caller got it wrong
- wxFAIL_MSG( _T("this column is not in the start of the row!") );
+ wxFAIL_MSG( wxT("this column is not in the start of the row!") );
return false;
}
// 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(wxT("shouldn't be called")); return false; }
+ virtual bool Undo() { wxFAIL_MSG(wxT("shouldn't be called")); return false; }
// instead, our command processor uses these methods
virtual bool Do(wxTextCtrl *text) = 0;
// we might support it but it's quite useless and other ports don't
// support it anyhow
wxASSERT_MSG( !(style & wxTE_PASSWORD),
- _T("wxTE_PASSWORD can't be used with multiline ctrls") );
+ wxT("wxTE_PASSWORD can't be used with multiline ctrls") );
}
RecalcFontMetrics();
void wxTextCtrl::DoSetValue(const wxString& value, int flags)
{
- if ( IsSingleLine() && (value == GetValue()) )
+ if ( value != GetValue() )
{
- // nothing changed
- return;
- }
+ EventsSuppressor noeventsIf(this, !(flags & SetValue_SendEvent));
- Replace(0, GetLastPosition(), value);
+ Replace(0, GetLastPosition(), value);
- if ( IsSingleLine() )
+ if ( IsSingleLine() )
+ {
+ SetInsertionPoint(0);
+ }
+ }
+ else // nothing changed
{
- SetInsertionPoint(0);
+ // still send event for consistency
+ if ( flags & SetValue_SendEvent )
+ SendTextUpdatedEvent();
}
-
- if ( flags & SetValue_SendEvent )
- SendTextUpdatedEvent();
}
const wxArrayString& wxTextCtrl::GetLines() const
return MData().m_lines.GetCount();
}
-wxString wxTextCtrl::GetValue() const
+wxString wxTextCtrl::DoGetValue() const
{
// for multiline controls we don't always store the total value but only
// recompute it when asked - and to invalidate it we just empty it in
size_t count = lines.GetCount();
for ( size_t n = 1; n < count; n++ )
{
- self->m_value << _T('\n') << lines[n];
+ self->m_value << wxT('\n') << lines[n];
}
}
!PositionToXY(from, &colStart, &lineStart) ||
!PositionToXY(to, &colEnd, &lineEnd) )
{
- wxFAIL_MSG(_T("invalid range in wxTextCtrl::Replace"));
+ wxFAIL_MSG(wxT("invalid range in wxTextCtrl::Replace"));
return;
}
if ( line > lineStart )
{
// from the previous line
- textOrig += _T('\n');
+ textOrig += wxT('\n');
}
textOrig += linesOld[line];
if ( (size_t)colStart == linesOld[lineStart].length() )
{
// text appended, refresh just enough to show the new text
- widthNewText = GetTextWidth(text.BeforeFirst(_T('\n')));
+ widthNewText = GetTextWidth(text.BeforeFirst(wxT('\n')));
}
else // text inserted, refresh till the end of line
{
for ( const wxChar *p = textNew.c_str(); ; p++ )
{
// end of line/text?
- if ( !*p || *p == _T('\n') )
+ if ( !*p || *p == wxT('\n') )
{
lines.Add(wxString(curLineStart, p));
if ( !*p )
#ifdef WXDEBUG_TEXT_REPLACE
// (3a) all empty tokens should be counted as replacing with "foo" and
// with "foo\n" should have different effects
- wxArrayString lines2 = wxStringTokenize(textNew, _T("\n"),
+ wxArrayString lines2 = wxStringTokenize(textNew, wxT("\n"),
wxTOKEN_RET_EMPTY_ALL);
if ( lines2.IsEmpty() )
}
wxASSERT_MSG( lines.GetCount() == lines2.GetCount(),
- _T("Replace() broken") );
+ wxT("Replace() broken") );
for ( size_t n = 0; n < lines.GetCount(); n++ )
{
- wxASSERT_MSG( lines[n] == lines2[n], _T("Replace() broken") );
+ wxASSERT_MSG( lines[n] == lines2[n], wxT("Replace() broken") );
}
#endif // WXDEBUG_TEXT_REPLACE
#ifdef WXDEBUG_TEXT_REPLACE
// optimized code above should give the same result as straightforward
// computation in the beginning
- wxASSERT_MSG( GetValue() == textTotalNew, _T("error in Replace()") );
+ wxASSERT_MSG( GetValue() == textTotalNew, wxT("error in Replace()") );
#endif // WXDEBUG_TEXT_REPLACE
// update the current position: note that we always put the cursor at the
// now call it to do the rest (not related to refreshing)
ClearSelection();
+
+ if ( EventsAllowed() )
+ SendTextUpdatedEvent();
}
void wxTextCtrl::Remove(wxTextPos from, wxTextPos to)
void wxTextCtrl::SetInsertionPoint(wxTextPos pos)
{
wxCHECK_RET( pos >= 0 && pos <= GetLastPosition(),
- _T("insertion point position out of range") );
+ wxT("insertion point position out of range") );
// don't do anything if it didn't change
if ( pos != m_curPos )
void wxTextCtrl::MoveInsertionPoint(wxTextPos pos)
{
wxASSERT_MSG( pos >= 0 && pos <= GetLastPosition(),
- _T("DoSetInsertionPoint() can only be called with valid pos") );
+ wxT("DoSetInsertionPoint() can only be called with valid pos") );
m_curPos = pos;
PositionToXY(m_curPos, &m_curCol, &m_curRow);
}
// more probable reason of this would be to forget to update m_posLast
- wxASSERT_MSG( pos == m_posLast, _T("bug in GetLastPosition()") );
+ wxASSERT_MSG( pos == m_posLast, wxT("bug in GetLastPosition()") );
#endif // WXDEBUG_TEXT
pos = m_posLast;
{
// take the end of the first line
sel = GetLines()[lineStart].c_str() + colStart;
- sel += _T('\n');
+ sel += wxT('\n');
// all intermediate ones
for ( wxTextCoord line = lineStart + 1; line < lineEnd; line++ )
{
- sel << GetLines()[line] << _T('\n');
+ sel << GetLines()[line] << wxT('\n');
}
// and the start of the last one
OrderPositions(from, to);
wxCHECK_RET( to <= GetLastPosition(),
- _T("invalid range in wxTextCtrl::SetSelection") );
+ wxT("invalid range in wxTextCtrl::SetSelection") );
if ( from != m_selStart || to != m_selEnd )
{
m_selStart = from;
m_selEnd = to;
- wxLogTrace(_T("text"), _T("Selection range is %ld-%ld"),
+ wxLogTrace(wxT("text"), wxT("Selection range is %ld-%ld"),
m_selStart, m_selEnd);
// refresh only the part of text which became (un)selected if
{
if ( IsSingleLine() )
{
- wxASSERT_MSG( line == 0, _T("invalid GetLineLength() parameter") );
+ wxASSERT_MSG( line == 0, wxT("invalid GetLineLength() parameter") );
return m_value.length();
}
else // multiline
{
wxCHECK_MSG( (size_t)line < GetLineCount(), -1,
- _T("line index out of range") );
+ wxT("line index out of range") );
return GetLines()[line].length();
}
{
if ( IsSingleLine() )
{
- wxASSERT_MSG( line == 0, _T("invalid GetLineLength() parameter") );
+ wxASSERT_MSG( line == 0, wxT("invalid GetLineLength() parameter") );
return m_value;
}
if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
wxCHECK_MSG( (size_t)line < GetLineCount(), wxEmptyString,
- _T("line index out of range") );
+ wxT("line index out of range") );
return GetLines()[line];
}
#ifdef WXDEBUG_TEXT
wxASSERT_MSG( XYToPosition(pos - posCur, nLine) == pos,
- _T("XYToPosition() or PositionToXY() broken") );
+ wxT("XYToPosition() or PositionToXY() broken") );
#endif // WXDEBUG_TEXT
return true;
wxCoord xCaret, yCaret;
if ( !PositionToDeviceXY(m_curPos, &xCaret, &yCaret) )
{
- wxFAIL_MSG( _T("Caret can't be beyond the text!") );
+ wxFAIL_MSG( wxT("Caret can't be beyond the text!") );
}
return wxPoint(xCaret, yCaret);
bool wxTextCtrlInsertCommand::Undo(wxTextCtrl *text)
{
- wxCHECK_MSG( CanUndo(), false, _T("impossible to undo insert cmd") );
+ wxCHECK_MSG( CanUndo(), false, wxT("impossible to undo insert cmd") );
// remove the text from where we inserted it
text->Remove(m_from, m_from + m_text.length());
void wxTextCtrl::Undo()
{
// the caller must check it
- wxASSERT_MSG( CanUndo(), _T("can't call Undo() if !CanUndo()") );
+ wxASSERT_MSG( CanUndo(), wxT("can't call Undo() if !CanUndo()") );
m_cmdProcessor->Undo();
}
void wxTextCtrl::Redo()
{
// the caller must check it
- wxASSERT_MSG( CanRedo(), _T("can't call Undo() if !CanUndo()") );
+ wxASSERT_MSG( CanRedo(), wxT("can't call Undo() if !CanUndo()") );
m_cmdProcessor->Redo();
}
case wxTE_HT_BELOW:
*/
default:
- wxFAIL_MSG(_T("unexpected HitTestLine() return value"));
+ wxFAIL_MSG(wxT("unexpected HitTestLine() return value"));
// fall through
case wxTE_HT_ON_TEXT:
// SData().m_colStart, we need an absolute offset into string
SData().m_colLastVisible += SData().m_colStart;
- wxLogTrace(_T("text"), _T("Last visible column/position is %d/%ld"),
+ wxLogTrace(wxT("text"), wxT("Last visible column/position is %d/%ld"),
(int) SData().m_colLastVisible, (long) SData().m_posLastVisible);
}
wxTextCoord col,
wxTextCoord *colRowStart) const
{
- wxASSERT_MSG( WrapLines(), _T("shouldn't be called") );
+ wxASSERT_MSG( WrapLines(), wxT("shouldn't be called") );
const wxWrappedLineData& lineData = WData().m_linesData[line];
*colRowStart = lineData.GetRowStart(row);
// this can't happen, of course
- wxASSERT_MSG( *colRowStart <= col, _T("GetRowInLine() is broken") );
+ wxASSERT_MSG( *colRowStart <= col, wxT("GetRowInLine() is broken") );
}
return row;
void wxTextCtrl::LayoutLines(wxTextCoord lineLast) const
{
- wxASSERT_MSG( WrapLines(), _T("should only be used for line wrapping") );
+ wxASSERT_MSG( WrapLines(), wxT("should only be used for line wrapping") );
// if we were called, some line was dirty and if it was dirty we must have
// had m_rowFirstInvalid set to something too
wxTextCoord lineFirst = WData().m_rowFirstInvalid;
- wxASSERT_MSG( lineFirst != -1, _T("nothing to layout?") );
+ wxASSERT_MSG( lineFirst != -1, wxT("nothing to layout?") );
wxTextCoord rowFirst, rowCur;
if ( lineFirst )
wxCoord *widthReal) const
{
// this function is slow, it shouldn't be called unless really needed
- wxASSERT_MSG( WrapLines(), _T("shouldn't be called") );
+ wxASSERT_MSG( WrapLines(), wxT("shouldn't be called") );
wxString s(text);
wxTextCoord col;
case wxTE_HT_BELOW:
*/
default:
- wxFAIL_MSG(_T("unexpected HitTestLine() return value"));
+ wxFAIL_MSG(wxT("unexpected HitTestLine() return value"));
// fall through
case wxTE_HT_ON_TEXT:
}
// this is not supposed to happen
- wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") );
+ wxASSERT_MSG( matchDir, wxT("logic error in wxTextCtrl::HitTest") );
if ( matchDir == Match_Right )
col++;
dc.GetTextExtent(text, &width2, NULL);
wxASSERT_MSG( (width1 <= x) && (x < width2),
- _T("incorrect HitTestLine() result") );
+ wxT("incorrect HitTestLine() result") );
}
else // we return last char
{
- wxASSERT_MSG( x >= width1, _T("incorrect HitTestLine() result") );
+ wxASSERT_MSG( x >= width1, wxT("incorrect HitTestLine() result") );
}
}
#endif // WXDEBUG_TEXT
void wxTextCtrl::ShowHorzPosition(wxCoord pos)
{
- wxASSERT_MSG( IsSingleLine(), _T("doesn't work for multiline") );
+ wxASSERT_MSG( IsSingleLine(), wxT("doesn't work for multiline") );
// pos is the logical position to show
void wxTextCtrl::ScrollText(wxTextCoord col)
{
wxASSERT_MSG( IsSingleLine(),
- _T("ScrollText() is for single line controls only") );
+ wxT("ScrollText() is for single line controls only") );
// never scroll beyond the left border
if ( col < 0 )
void wxTextCtrl::RecalcMaxWidth()
{
- wxASSERT_MSG( !IsSingleLine(), _T("only used for multiline") );
+ wxASSERT_MSG( !IsSingleLine(), wxT("only used for multiline") );
MData().m_widthMax = -1;
(void)GetMaxWidth();
}
}
- wxASSERT_MSG( MData().m_widthMax != -1, _T("should have at least 1 line") );
+ wxASSERT_MSG( MData().m_widthMax != -1, wxT("should have at least 1 line") );
return MData().m_widthMax;
}
void wxTextCtrl::UpdateScrollbars()
{
- wxASSERT_MSG( !IsSingleLine(), _T("only used for multiline") );
+ wxASSERT_MSG( !IsSingleLine(), wxT("only used for multiline") );
wxSize size = GetRealTextArea().GetSize();
if ( scrollRangeXOld )
{
- x *= scrollRangeX - m_rectText.width / charWidth;
- x /= scrollRangeXOld - m_rectText.width / charWidth;
+ const int w = m_rectText.width / charWidth;
+ if ( w != scrollRangeXOld )
+ {
+ x *= scrollRangeX - w;
+ x /= scrollRangeXOld - w;
+ }
Scroll(x, y);
}
void wxTextCtrl::RefreshLineRange(wxTextCoord lineFirst, wxTextCoord lineLast)
{
wxASSERT_MSG( lineFirst <= lineLast || !lineLast,
- _T("no lines to refresh") );
+ wxT("no lines to refresh") );
wxRect rect;
// rect.x is already 0
// lineFirst may be beyond the last line only if we refresh till
// the end, otherwise it's illegal
wxASSERT_MSG( lineFirst == GetNumberOfLines() && !lineLast,
- _T("invalid line range") );
+ wxT("invalid line range") );
rowFirst = GetRowAfterLine(lineFirst - 1);
}
void wxTextCtrl::RefreshTextRange(wxTextPos start, wxTextPos end)
{
wxCHECK_RET( start != -1 && end != -1,
- _T("invalid RefreshTextRange() arguments") );
+ wxT("invalid RefreshTextRange() arguments") );
// accept arguments in any order as it is more conenient for the caller
OrderPositions(start, end);
wxString text = GetLineText(line);
wxASSERT_MSG( (size_t)start <= text.length() && count,
- _T("invalid RefreshColRange() parameter") );
+ wxT("invalid RefreshColRange() parameter") );
RefreshPixelRange(line,
GetTextWidth(text.Left((size_t)start)),
if ( rect.y < m_rectText.y )
rect.y = m_rectText.y;
- wxLogTrace(_T("text"), _T("Refreshing (%d, %d)-(%d, %d)"),
+ wxLogTrace(wxT("text"), wxT("Refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
Refresh(true, &rect);
{
wxString textShown;
if ( IsPassword() )
- textShown = wxString(_T('*'), text.length());
+ textShown = wxString(wxT('*'), text.length());
else
textShown = text;
if ( (ht == wxTE_HT_BEYOND) || (ht == wxTE_HT_BELOW) )
{
- wxASSERT_MSG( line <= lineEnd, _T("how did we get that far?") );
+ wxASSERT_MSG( line <= lineEnd, wxT("how did we get that far?") );
if ( line == lineEnd )
{
}
// calculate the text coords on screen
- wxASSERT_MSG( colStart >= colRowStart, _T("invalid string part") );
+ wxASSERT_MSG( colStart >= colRowStart, wxT("invalid string part") );
wxCoord ofsStart = GetTextWidth(
textLine.Mid(colRowStart,
colStart - colRowStart));
// do draw the text
renderer->DrawTextLine(dc, text, rectText, selStart, selEnd,
GetStateFlags());
- wxLogTrace(_T("text"), _T("Line %ld: positions %ld-%ld redrawn."),
+ wxLogTrace(wxT("text"), wxT("Line %ld: positions %ld-%ld redrawn."),
line, colStart, colEnd);
}
}
void wxTextCtrl::DoDrawLineWrapMarks(wxDC& dc, const wxRect& rectUpdate)
{
wxASSERT_MSG( WrapLines() && WData().m_widthMark,
- _T("shouldn't be called at all") );
+ wxT("shouldn't be called at all") );
wxRenderer *renderer = GetRenderer();
// FIXME: is this really a bug in wxMSW?
rectTextArea.width--;
#endif // __WXMSW__
+ dc.DestroyClippingRegion();
dc.SetClippingRegion(rectTextArea);
// adjust for scrolling
else
{
// read only controls don't have the caret
- caret = (wxCaret *)NULL;
+ caret = NULL;
}
// SetCaret() will delete the old caret if any
wxTextPos wxTextCtrl::GetPositionAbove()
{
wxCHECK_MSG( !IsSingleLine(), INVALID_POS_VALUE,
- _T("can't move cursor vertically in a single line control") );
+ wxT("can't move cursor vertically in a single line control") );
// move the cursor up by one ROW not by one LINE: this means that
// we should really use HitTest() and not just go to the same
wxTextPos wxTextCtrl::GetPositionBelow()
{
wxCHECK_MSG( !IsSingleLine(), INVALID_POS_VALUE,
- _T("can't move cursor vertically in a single line control") );
+ wxT("can't move cursor vertically in a single line control") );
// see comments for wxACTION_TEXT_UP
wxPoint pt = GetCaretPosition() - m_rectText.GetPosition();
// 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;
+ wxTextCtrlCommand *command = NULL;
wxString action;
bool del = false,
if ( textChanged )
{
- wxASSERT_MSG( IsEditable(), _T("non editable control changed?") );
+ wxASSERT_MSG( IsEditable(), wxT("non editable control changed?") );
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
InitCommandEvent(event);
}
else // interpret <Enter> normally: insert new line
{
- PerformAction(wxACTION_TEXT_INSERT, -1, _T('\n'));
+ PerformAction(wxACTION_TEXT_INSERT, -1, wxT('\n'));
}
}
else if ( keycode < 255 && isprint(keycode) )
}
#endif
}
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
// Ctrl-R refreshes the control in debug mode
else if ( event.ControlDown() && event.GetKeyCode() == 'r' )
Refresh();
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
event.Skip();
}
wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
: wxStdInputHandler(inphand)
{
- m_winCapture = (wxTextCtrl *)NULL;
+ m_winCapture = NULL;
}
/* static */
{
if ( event.LeftDown() )
{
- wxASSERT_MSG( !m_winCapture, _T("left button going down twice?") );
+ wxASSERT_MSG( !m_winCapture, wxT("left button going down twice?") );
wxTextCtrl *text = wxStaticCast(consumer->GetInputWindow(), wxTextCtrl);
m_winCapture->ShowCaret();
m_winCapture->ReleaseMouse();
- m_winCapture = (wxTextCtrl *)NULL;
+ m_winCapture = NULL;
}
}