/////////////////////////////////////////////////////////////////////////////
-// Name: univ/textctrl.cpp
+// Name: src/univ/textctrl.cpp
// Purpose: wxTextCtrl
// Author: Vadim Zeitlin
// Modified by:
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
// ----------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "univtextctrl.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#if wxUSE_TEXTCTRL
-#include <ctype.h>
+#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/cmdproc.h"
-#if wxUSE_CLIPBOARD
-#include "wx/dataobj.h"
-#endif
+#if wxDEBUG_LEVEL >= 2
+ // turn extra wxTextCtrl-specific debugging on/off
+ #define WXDEBUG_TEXT
-// 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
#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
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// 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
-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;
// ----------------------------------------------------------------------------
// the data only used by single line text controls
-struct WXDLLEXPORT wxTextSingleLineData
+struct wxTextSingleLineData
{
// the position of the first visible pixel and the first visible column
wxCoord m_ofsHorz;
};
// the data only used by multi line text controls
-struct WXDLLEXPORT wxTextMultiLineData
+struct wxTextMultiLineData
{
// the lines of text
wxArrayString m_lines;
};
// 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,
// 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;
}
#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
// 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;
// implementation
// ============================================================================
-BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
EVT_CHAR(wxTextCtrl::OnChar)
EVT_SIZE(wxTextCtrl::OnSize)
END_EVENT_TABLE()
-IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
-
// ----------------------------------------------------------------------------
// creation
// ----------------------------------------------------------------------------
m_isModified = false;
m_isEditable = true;
+ m_wrapLines = false;
m_posLast =
m_curPos =
m_heightLine =
m_widthAvg = -1;
- // init wxScrollHelper
- SetWindow(this);
-
// init the undo manager
m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
style |= wxALWAYS_SHOW_SB;
}
- // wxTE_WORDWRAP is 0 for now so we don't need the code below
-#if 0
- if ( style & wxTE_WORDWRAP )
- {
- // wrapping words means wrapping, hence no horz scrollbar
- style &= ~wxHSCROLL;
- }
-#endif // 0
+ // 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 (?)
// create data object for normal multiline or for controls with line
// wrap as needed
if ( style & wxHSCROLL )
+ {
m_data.mdata = new wxTextMultiLineData;
- else
+ }
+ else // we must wrap lines if we don't have horizontal scrollbar
+ {
+ // NB: we can't rely on HasFlag(wxHSCROLL) as the flags can change
+ // later and even wxWindow::Create() itself temporarily resets
+ // wxHSCROLL in wxUniv, so remember that we have a wrapped data
+ // and not just a multi line data in a separate variable
+ m_wrapLines = true;
m_data.wdata = new wxTextWrappedData;
+ }
}
else
{
// 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();
SetValue(value);
- SetBestSize(size);
+ SetInitialSize(size);
m_isEditable = !(style & wxTE_READONLY);
// set/get the value
// ----------------------------------------------------------------------------
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
{
- if ( IsSingleLine() && (value == GetValue()) )
+ if ( value != GetValue() )
{
- // nothing changed
- return;
- }
+ EventsSuppressor noeventsIf(this, !(flags & SetValue_SendEvent));
- Replace(0, GetLastPosition(), value);
+ Replace(0, GetLastPosition(), value);
- if ( IsSingleLine() )
+ if ( IsSingleLine() )
+ {
+ SetInsertionPoint(0);
+ }
+ }
+ else // nothing changed
{
- SetInsertionPoint(0);
+ // still send event for consistency
+ if ( flags & SetValue_SendEvent )
+ SendTextUpdatedEvent();
}
-
- // TODO: should we generate the event or not, finally?
}
const wxArrayString& wxTextCtrl::GetLines() const
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];
}
}
void wxTextCtrl::Clear()
{
- SetValue(_T(""));
+ SetValue(wxEmptyString);
}
bool wxTextCtrl::ReplaceLine(wxTextCoord line,
!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();
+
+ SendTextUpdatedEventIfAllowed();
}
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)
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
void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
{
// selecting till -1 is the same as selecting to the end
- if ( to == -1 && from != -1 )
+ if ( to == -1 )
{
+ // and selecting (-1, -1) range is the same as selecting everything, by
+ // convention
+ if ( from == -1 )
+ from = 0;
to = GetLastPosition();
}
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;
}
//this is called during DoGetBestSize
if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
- wxCHECK_MSG( (size_t)line < GetLineCount(), _T(""),
- _T("line index out of range") );
+ wxCHECK_MSG( (size_t)line < GetLineCount(), wxEmptyString,
+ wxT("line index out of range") );
return GetLines()[line];
}
// if they are out of range
if ( IsSingleLine() )
{
- return x > GetLastPosition() || y > 0 ? wxDefaultCoord : x;
+ return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
}
else // multiline
{
#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);
{
// finding the last line is easy if each line has exactly
// one row
- yEnd = yStart + rectText.height / GetLineHeight() - 1;
+ yEnd = yStart + rectText.height / GetLineHeight();
}
if ( yEnd < y )
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();
}
WData().m_rowFirstInvalid = 0;
// increase timestamp: this means that the lines which had been
- // laid out before will be relayd out the next time LayoutLines()
+ // laid out before will be relaid out the next time LayoutLines()
// is called because their timestamp will be smaller than the
// current one
WData().m_timestamp++;
{
case wxTE_HT_BEYOND:
// everything is visible
+ SData().m_ofsHorz = 0;
+
+ SData().m_colStart = 0;
SData().m_colLastVisible = text.length();
- // calc it below
+ // calculate it below
SData().m_posLastVisible = -1;
break;
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:
//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;
}
// 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
fine for vertical scrolling as all lines have the same height but is rather
ugly for horizontal scrolling if proportional font is used. This is why we
manually update and use SData().m_ofsHorz which contains the length of the string
- which is hidden beyond the left borde. An important property of text
+ which is hidden beyond the left border. An important property of text
controls using this kind of scrolling is that an entire number of characters
is always shown and that parts of characters never appear on display -
neither in the leftmost nor rightmost positions.
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
- // SData().m_ofsHorz is the fisrt logical position shown
+ // SData().m_ofsHorz is the first logical position shown
if ( pos < SData().m_ofsHorz )
{
// scroll backwards
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);
{
// 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
{
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
{
// FIXME use renderer
caret = new wxCaret(this, 1, GetLineHeight());
-#ifndef __WXMSW__
- caret->SetBlinkTime(0);
-#endif // __WXMSW__
}
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);
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) )
}
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) )
// skip event.Skip() below
return;
}
+#if wxUSE_UNICODE
+ else if (unicode > 0)
+ {
+ PerformAction(wxACTION_TEXT_INSERT, -1, unicode);
+
+ return;
+ }
+#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();
}
+/* static */
+wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+ static wxStdTextCtrlInputHandler s_handler(handlerDef);
+
+ return &s_handler;
+}
+
// ----------------------------------------------------------------------------
// wxStdTextCtrlInputHandler
// ----------------------------------------------------------------------------
wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
: wxStdInputHandler(inphand)
{
- m_winCapture = (wxTextCtrl *)NULL;
+ m_winCapture = NULL;
}
/* static */
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;
{
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;
}
}