// Created: 15.09.00
// RCS-ID: $Id$
// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
/*
Everywhere in this file LINE refers to a logical line of text, and ROW to a
physical line of text on the display. They are the same unless WrapLines()
- is TRUE in which case a single LINE may correspond to multiple ROWs.
+ is true in which case a single LINE may correspond to multiple ROWs.
A text position is an unsigned int (which for reasons of compatibility is
still a long) from 0 to GetLastPosition() inclusive. The positions
// headers
// ----------------------------------------------------------------------------
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "univtextctrl.h"
#endif
#if wxUSE_TEXTCTRL
+#include <ctype.h>
+
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/cmdproc.h"
+#if wxUSE_CLIPBOARD
+#include "wx/dataobj.h"
+#endif
+
// turn extra wxTextCtrl-specific debugging on/off
#define WXDEBUG_TEXT
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;
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:
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:
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;
};
EVT_CHAR(wxTextCtrl::OnChar)
EVT_SIZE(wxTextCtrl::OnSize)
-
- EVT_IDLE(wxTextCtrl::OnIdle)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
m_selStart =
m_selEnd = -1;
- m_isModified = FALSE;
- m_isEditable = TRUE;
+ m_isModified = false;
+ m_isEditable = true;
m_posLast =
m_curPos =
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
// 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;
+#endif
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);
- return TRUE;
+ wxSizeEvent sizeEvent(GetSize(), GetId());
+ GetEventHandler()->ProcessEvent(sizeEvent);
+
+ return true;
}
wxTextCtrl::~wxTextCtrl()
}
// 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 ( !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;
}
// ----------------------------------------------------------------------------
return m_isEditable && IsEnabled();
}
+void wxTextCtrl::MarkDirty()
+{
+ m_isModified = true;
+}
+
void wxTextCtrl::DiscardEdits()
{
- m_isModified = FALSE;
+ m_isModified = false;
}
void wxTextCtrl::SetEditable(bool editable)
}
else // multiline
{
+ //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") );
// if they are out of range
if ( IsSingleLine() )
{
- return x > GetLastPosition() || y > 0 ? -1 : x;
+ return x > GetLastPosition() || y > 0 ? wxDefaultCoord : 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
// 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() )
{
}
//else: multiline but no scrollbars, hence nothing to do
- ShowCaret();
+ if (showCaret)
+ ShowCaret();
}
// ----------------------------------------------------------------------------
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()
lines = 5;
else if ( lines > 10 )
lines = 10;
- h *= 10;
+ h *= lines;
}
wxRect rectText;
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)
#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::OnIdle(wxIdleEvent& event)
+void wxTextCtrl::OnInternalIdle()
{
// notice that single line text control never has scrollbars
if ( !IsSingleLine() &&
{
UpdateScrollbars();
}
-
- event.Skip();
+ wxControl::OnInternalIdle();
}
bool wxTextCtrl::SendAutoScrollEvents(wxScrollWinEvent& event) const
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;
// 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;
}
}
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;
- ShowCaret(enable);
+ if (FindFocus() == this && GetCaret() &&
+ ((enable && !GetCaret()->IsVisible()) ||
+ (!enable && GetCaret()->IsVisible())))
+ ShowCaret(enable);
- return TRUE;
+ return true;
}
void wxTextCtrl::CreateCaret()
caret->Move(GetCaretPosition());
// and show it there
- caret->Show(show);
+ if ((show && !caret->IsVisible()) ||
+ (!show && caret->IsVisible()))
+ caret->Show(show);
}
}
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
{
GetEventHandler()->ProcessEvent(event);
// as the text changed...
- m_isModified = TRUE;
+ m_isModified = true;
}
- return TRUE;
+ return true;
}
void wxTextCtrl::OnChar(wxKeyEvent& event)
{
// we're only interested in key presses
if ( !pressed )
- return FALSE;
+ return false;
int keycode = event.GetKeyCode();
{
consumer->PerformAction(action, -1, str);
- return TRUE;
+ return true;
}
return wxStdInputHandler::HandleKey(consumer, event, pressed);
return wxStdInputHandler::HandleMouseMove(consumer, event);
}
-bool wxStdTextCtrlInputHandler::HandleFocus(wxInputConsumer *consumer,
- const wxFocusEvent& event)
+bool
+wxStdTextCtrlInputHandler::HandleFocus(wxInputConsumer *consumer,
+ const wxFocusEvent& event)
{
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