/////////////////////////////////////////////////////////////////////////////
-// 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
-
// turn extra wxTextCtrl-specific debugging on/off
#define WXDEBUG_TEXT
#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
// ----------------------------------------------------------------------------
// 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,
#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
// 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)
+IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
// ----------------------------------------------------------------------------
// 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
{
// create data object for single line controls
m_data.sdata = new wxTextSingleLineData;
}
-
+
#if wxUSE_TWO_WINDOWS
if ((style & wxBORDER_MASK) == 0)
style |= wxBORDER_SUNKEN;
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()) )
{
SetInsertionPoint(0);
}
- // TODO: should we generate the event or not, finally?
+ if ( flags & SetValue_SendEvent )
+ SendTextUpdatedEvent();
}
const wxArrayString& wxTextCtrl::GetLines() const
void wxTextCtrl::Clear()
{
- SetValue(_T(""));
+ SetValue(wxEmptyString);
}
bool wxTextCtrl::ReplaceLine(wxTextCoord line,
// if necessary
OrderPositions(from, to);
- Replace(from, to, _T(""));
+ Replace(from, to, wxEmptyString);
}
void wxTextCtrl::WriteText(const wxString& text)
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();
}
{
//this is called during DoGetBestSize
if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
-
- wxCHECK_MSG( (size_t)line < GetLineCount(), _T(""),
+
+ 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 ? wxDefaultCoord : x;
+ return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
}
else // multiline
{
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);
//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;
{
// 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
{
// 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;
{
// FIXME use renderer
caret = new wxCaret(this, 1, GetLineHeight());
-#ifndef __WXMSW__
- caret->SetBlinkTime(0);
-#endif // __WXMSW__
}
else
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
InitCommandEvent(event);
- event.SetString(GetValue());
GetEventHandler()->ProcessEvent(event);
// as the text changed...
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
event.Skip();
}
+/* static */
+wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+ static wxStdTextCtrlInputHandler s_handler(handlerDef);
+
+ return &s_handler;
+}
+
// ----------------------------------------------------------------------------
// wxStdTextCtrlInputHandler
// ----------------------------------------------------------------------------
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;