/////////////////////////////////////////////////////////////////////////////
-// Name: univ/textctrl.cpp
+// Name: src/univ/textctrl.cpp
// Purpose: wxTextCtrl
// Author: Vadim Zeitlin
// Modified by:
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
// ----------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "univtextctrl.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
// 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;
m_scrollRangeY = 0;
m_updateScrollbarX =
- m_updateScrollbarY = FALSE;
+ m_updateScrollbarY = false;
m_widthMax = -1;
m_lineLongest = 0;
// 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,
// caller got it wrong
wxFAIL_MSG( _T("this column is not in the start of the row!") );
- return FALSE;
+ return false;
}
#endif // 0
// ----------------------------------------------------------------------------
/*
- 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
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;
public:
wxTextCtrlCommandProcessor(wxTextCtrl *text)
{
- m_compressInserts = FALSE;
+ m_compressInserts = false;
m_text = text;
}
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; }
// 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;
};
m_selStart =
m_selEnd = -1;
- m_isModified = FALSE;
- m_isEditable = TRUE;
+ m_isModified = false;
+ m_isEditable = true;
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 single line controls
m_data.sdata = new wxTextSingleLineData;
}
-
+
#if wxUSE_TWO_WINDOWS
if ((style & wxBORDER_MASK) == 0)
style |= wxBORDER_SUNKEN;
if ( !wxControl::Create(parent, id, pos, size, style,
validator, name) )
{
- return FALSE;
+ return false;
}
SetCursor(wxCURSOR_IBEAM);
// 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);
wxSizeEvent sizeEvent(GetSize(), GetId());
GetEventHandler()->ProcessEvent(sizeEvent);
- return TRUE;
+ return true;
}
wxTextCtrl::~wxTextCtrl()
void wxTextCtrl::Clear()
{
- SetValue(_T(""));
+ SetValue(wxEmptyString);
}
bool wxTextCtrl::ReplaceLine(wxTextCoord line,
}
// the number of rows changed
- return TRUE;
+ return true;
}
}
else // no line wrap
}
// the number of rows didn't change
- return FALSE;
+ return false;
}
void wxTextCtrl::RemoveLine(wxTextCoord line)
// 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();
// we have the replacement line for this one
if ( ReplaceLine(line, lines[nReplaceLine]) )
{
- rowsNumberChanged = TRUE;
+ rowsNumberChanged = true;
}
UpdateMaxWidth(line);
{
// (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);
}
// even the line number changed
- rowsNumberChanged = TRUE;
+ rowsNumberChanged = true;
// update line to exit the loop
line = lineEnd + 1;
if ( nReplaceLine < nReplaceCount )
{
// even the line number changed
- rowsNumberChanged = TRUE;
+ rowsNumberChanged = true;
do
{
RefreshLineRange(lineEnd + 1, 0);
// the vert scrollbar might [dis]appear
- MData().m_updateScrollbarY = TRUE;
+ MData().m_updateScrollbarY = true;
}
// must recalculate it - will do later
// if necessary
OrderPositions(from, to);
- Replace(from, to, _T(""));
+ Replace(from, to, wxEmptyString);
}
void wxTextCtrl::WriteText(const wxString& text)
if ( !HasSelection() )
{
// no selection at all, hence no selection in this line
- return FALSE;
+ return false;
}
wxTextCoord lineStart, colStart;
if ( lineStart > line )
{
// this line is entirely above the selection
- return FALSE;
+ return false;
}
wxTextCoord lineEnd, colEnd;
if ( lineEnd < line )
{
// this line is entirely below the selection
- return FALSE;
+ return false;
}
if ( line == lineStart )
*end = GetLineLength(line);
}
- return TRUE;
+ return true;
}
// ----------------------------------------------------------------------------
void wxTextCtrl::MarkDirty()
{
- m_isModified = TRUE;
+ m_isModified = true;
}
void wxTextCtrl::DiscardEdits()
{
- m_isModified = FALSE;
+ m_isModified = false;
}
void wxTextCtrl::SetEditable(bool editable)
}
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];
// if they are out of range
if ( IsSingleLine() )
{
- return x > GetLastPosition() || y > 0 ? -1 : x;
+ return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
}
else // multiline
{
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
{
_T("XYToPosition() or PositionToXY() broken") );
#endif // WXDEBUG_TEXT
- return TRUE;
+ return true;
}
else // go further down
{
}
// beyond the last line
- return FALSE;
+ return false;
}
}
else // must really calculate col/line from pos
{
if ( !PositionToXY(pos, &col, &line) )
- return FALSE;
+ return false;
}
int hLine = GetLineHeight();
if ( yOut )
*yOut = y;
- return TRUE;
+ return true;
}
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
bool wxTextCtrl::DoCut()
{
if ( !HasSelection() )
- return FALSE;
+ return false;
Copy();
RemoveSelection();
- return TRUE;
+ return true;
}
void wxTextCtrl::Paste()
{
WriteText(text);
- return TRUE;
+ return true;
}
}
#endif // wxUSE_CLIPBOARD
- return FALSE;
+ return false;
}
// ----------------------------------------------------------------------------
}
// append the following insert commands to this one
- m_compressInserts = TRUE;
+ m_compressInserts = true;
// let the base class version will do the job normally
}
// 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
m_textDeleted = text->GetSelectionText();
text->RemoveSelection();
- return TRUE;
+ return true;
}
bool wxTextCtrlRemoveCommand::Undo(wxTextCtrl *text)
text->SetInsertionPoint(m_from > posLast ? posLast : m_from);
text->WriteText(m_textDeleted);
- return TRUE;
+ return true;
}
void wxTextCtrl::Undo()
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);
#endif // 0
MData().m_updateScrollbarX =
- MData().m_updateScrollbarY = TRUE;
+ MData().m_updateScrollbarY = true;
}
event.Skip();
wxString s(text);
wxTextCoord col;
- wxCoord wReal = -1;
+ wxCoord wReal = wxDefaultCoord;
switch ( HitTestLine(s, m_rectText.width, &col) )
{
/*
col--;
// recalc the width
- wReal = -1;
+ wReal = wxDefaultCoord;
}
//else: we can just see it
if ( colWordStart != col )
{
// will have to recalc the real width
- wReal = -1;
+ wReal = wxDefaultCoord;
col = colWordStart;
}
if ( widthReal )
{
- if ( wReal == -1 )
+ if ( wReal == wxDefaultCoord )
{
// calc it if not done yet
wReal = GetTextWidth(s.Truncate(col));
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
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,
rowInLine = 0;
if ( row < 0 )
- return FALSE;
+ return false;
int nLines = GetNumberOfLines();
if ( WrapLines() )
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;
}
if ( rowInLineOut )
*rowInLineOut = rowInLine;
- return TRUE;
+ return true;
}
// ----------------------------------------------------------------------------
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;
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
// just to suppress compiler warnings about using uninit vars below
charWidth = maxWidth = 0;
- showScrollbarX = FALSE;
+ showScrollbarX = false;
}
// calc the scrollbars ranges
SetScrollbars(charWidth, lineHeight,
scrollRangeX, scrollRangeY,
x, y,
- TRUE /* no refresh */);
+ true /* no refresh */);
if ( scrollRangeXOld )
{
}
MData().m_updateScrollbarX =
- MData().m_updateScrollbarY = FALSE;
+ MData().m_updateScrollbarY = false;
}
void wxTextCtrl::OnInternalIdle()
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() )
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,
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 */);
}
}
// 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;
{
ShowCaret();
- m_hasCaret = TRUE;
+ m_hasCaret = true;
}
}
bool wxTextCtrl::SetFont(const wxFont& font)
{
if ( !wxControl::SetFont(font) )
- return FALSE;
+ return false;
// and refresh everything, of course
InitInsertionPoint();
Refresh();
- return TRUE;
+ return true;
}
bool wxTextCtrl::Enable(bool enable)
{
if ( !wxTextCtrlBase::Enable(enable) )
- return FALSE;
+ return false;
if (FindFocus() == this && GetCaret() &&
((enable && !GetCaret()->IsVisible()) ||
(!enable && GetCaret()->IsVisible())))
ShowCaret(enable);
- return TRUE;
+ return true;
}
void wxTextCtrl::CreateCaret()
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
{
if ( newPos != INVALID_POS_VALUE )
{
// remember where the cursor original had been
- rememberAbscissa = TRUE;
+ rememberAbscissa = true;
}
}
}
if ( newPos != INVALID_POS_VALUE )
{
// remember where the cursor original had been
- rememberAbscissa = TRUE;
+ rememberAbscissa = true;
}
}
}
// inserting text can be undone
command = new wxTextCtrlInsertCommand(strArg);
- textChanged = TRUE;
+ textChanged = true;
}
}
else if ( (action == wxACTION_TEXT_PAGE_UP) ||
}
// 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++ )
}
// scroll vertically only
- Scroll(-1, y);
+ Scroll(wxDefaultCoord, y);
}
}
else if ( action == wxACTION_TEXT_SEL_WORD )
m_cmdProcessor->Submit(command);
// undoable commands always change text
- textChanged = TRUE;
+ textChanged = true;
}
else // no undoable command
{
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)
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) )
// 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
{
// we're only interested in key presses
if ( !pressed )
- return FALSE;
+ return false;
int keycode = event.GetKeyCode();
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;
{
consumer->PerformAction(action, -1, str);
- return TRUE;
+ return true;
}
return wxStdInputHandler::HandleKey(consumer, event, pressed);
}
// never refresh entirely
- return FALSE;
+ return false;
}
#endif // wxUSE_TEXTCTRL