1. added wxStringTokenize
2. some multiline wxTextCtrl code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8534 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// Name: wx/tokenzr.h
|
||||
// Purpose: String tokenizer - a C++ replacement for strtok(3)
|
||||
// Author: Guilhem Lavaux
|
||||
// Modified by: Vadim Zeitlin
|
||||
// Modified by: (or rather rewritten by) Vadim Zeitlin
|
||||
// Created: 04/22/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Guilhem Lavaux
|
||||
@@ -117,4 +117,15 @@ protected:
|
||||
bool m_hasMore; // do we have more (possible empty) tokens?
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// convenience function which returns all tokens at once
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// the function takes the same parameters as wxStringTokenizer ctor and returns
|
||||
// the array containing all tokens
|
||||
wxArrayString WXDLLEXPORT
|
||||
wxStringTokenize(const wxString& str,
|
||||
const wxString& delims = wxDEFAULT_DELIMITERS,
|
||||
wxStringTokenizerMode mode = wxTOKEN_DEFAULT);
|
||||
|
||||
#endif // _WX_TOKENZRH
|
||||
|
@@ -294,12 +294,15 @@ protected:
|
||||
void OnSize(wxSizeEvent& event);
|
||||
|
||||
private:
|
||||
// the value (may be only part of it for the multiline controls)
|
||||
wxString m_value;
|
||||
|
||||
// the initially specified control size
|
||||
wxSize m_sizeInitial;
|
||||
|
||||
// the entire control (only used for single line controls)
|
||||
wxString m_value;
|
||||
|
||||
// the lines of text (only used for multiline controls)
|
||||
wxArrayString m_lines;
|
||||
|
||||
// current position
|
||||
long m_curPos,
|
||||
m_curLine,
|
||||
|
@@ -196,3 +196,21 @@ wxString wxStringTokenizer::GetNextToken()
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxArrayString wxStringTokenize(const wxString& str,
|
||||
const wxString& delims,
|
||||
wxStringTokenizerMode mode)
|
||||
{
|
||||
wxArrayString tokens;
|
||||
wxStringTokenizer tk(str, delimes, mode);
|
||||
while ( tk.HasMoreTokens() )
|
||||
{
|
||||
tokens.Add(GetNextToken());
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
@@ -154,15 +154,35 @@ bool wxTextCtrl::SetFont(const wxFont& font)
|
||||
|
||||
void wxTextCtrl::SetValue(const wxString& value)
|
||||
{
|
||||
if ( m_value == value )
|
||||
if ( IsSingleLine() && (m_value == value) )
|
||||
{
|
||||
// nothing changed
|
||||
return;
|
||||
}
|
||||
|
||||
Replace(0, GetLastPosition(), value);
|
||||
}
|
||||
|
||||
wxString wxTextCtrl::GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
wxString value;
|
||||
if ( IsSingleLine() )
|
||||
{
|
||||
value = m_value;
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
size_t count = m_lines.GetCount();
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
if ( n )
|
||||
value += _T('\n');
|
||||
|
||||
value += m_lines[n];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void wxTextCtrl::Clear()
|
||||
@@ -170,11 +190,120 @@ void wxTextCtrl::Clear()
|
||||
SetValue(_T(""));
|
||||
}
|
||||
|
||||
/*
|
||||
Replace() works line by line: in the range [from, to] we have the starting
|
||||
line in which we replace the text in [from, last one ? to : end of line],
|
||||
the last one (which may be the same as the first one) and some number
|
||||
(possibly 0) of intermediate ones).
|
||||
*/
|
||||
void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
||||
{
|
||||
wxCHECK_RET( from >= 0 && to >= 0 && from <= to && to <= GetLastPosition(),
|
||||
_T("invalid range in wxTextCtrl::Replace") );
|
||||
long colStart, colEnd,
|
||||
lineStart, lineEnd;
|
||||
|
||||
if ( (from > to) ||
|
||||
!PositionToXY(from, &colStart, &lineStart) ||
|
||||
!PositionToXY(to, &colEnd, &lineEnd) )
|
||||
{
|
||||
wxFAIL_MSG(_T("invalid range in wxTextCtrl::Replace"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// break the replacement text into lines
|
||||
wxArrayString lines = wxStringTokenize(text, _T("\n"),
|
||||
wxTOKEN_RET_EMPTY_ALL);
|
||||
|
||||
// first deal with the starting line: (1) take the part before the text
|
||||
// being replaced
|
||||
wxString lineFirstOrig = GetLineText(lineStart);
|
||||
wxString lineFirst(lineFirstOrig, colStart);
|
||||
|
||||
// (2) add the text which replaces this part
|
||||
if ( !lines.IsEmpty() )
|
||||
{
|
||||
lineFirst += lines[0u];
|
||||
}
|
||||
|
||||
// (3) and add the text which is left if we replace text only in this line
|
||||
if ( lineEnd == lineStart )
|
||||
{
|
||||
wxASSERT_MSG((size_t)colEnd < lineFirstOrig.length(), _T("logic bug"));
|
||||
|
||||
lineFirst += lineFirstOrig.c_str() + (size_t)colEnd;
|
||||
}
|
||||
|
||||
// (4) modify the line and refresh the part of the window which changed
|
||||
if ( IsSingleLine() )
|
||||
{
|
||||
m_value = lineFirst;
|
||||
|
||||
// consistency check: when replacing text in a single line control, we
|
||||
// shouldn't have more than one line
|
||||
wxASSERT_MSG(lines.GetCount() <= 1,
|
||||
_T("can't have more than one line in this wxTextCtrl"));
|
||||
|
||||
// nothing more can happen to us
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
m_lines[lineStart] = lineFirst;
|
||||
}
|
||||
|
||||
// now replace all intermediate lines entirely and refresh
|
||||
size_t nReplaceLine = 1,
|
||||
nReplaceCount = lines.GetCount();
|
||||
for ( long line = lineStart + 1; line < lineEnd; line++ )
|
||||
{
|
||||
if ( nReplaceLine < nReplaceCount )
|
||||
{
|
||||
// replace line
|
||||
m_lines[line] = lines[nReplaceLine++];
|
||||
}
|
||||
else // no more replacement text - remove line
|
||||
{
|
||||
// optimization: remove not only this line but all the next ones as
|
||||
// well
|
||||
|
||||
// adjust the index by the number of lines removed
|
||||
lineEnd -= lineEnd - line;
|
||||
|
||||
// and remove them
|
||||
while ( line < lineEnd )
|
||||
{
|
||||
m_lines.RemoveAt(line++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there are still lines left in the replacement text, insert them
|
||||
// before modifying the last line
|
||||
while ( nReplaceLine < nReplaceCount - 1 ) // OPT: insert all at once?
|
||||
{
|
||||
// insert line and adjust for index change by incrementing lineEnd
|
||||
m_lines.Insert(lines[nReplaceLine++], lineEnd++);
|
||||
}
|
||||
|
||||
// now deal with the last line: (1) replace its beginning with the end of
|
||||
// the replacement text
|
||||
wxString lineLast;
|
||||
if ( nReplaceLine < nReplaceCount )
|
||||
{
|
||||
wxASSERT_MSG(nReplaceCount == nReplaceCount - 1, _T("logic error"));
|
||||
|
||||
lineLast = lines[nReplaceLine];
|
||||
}
|
||||
|
||||
// (2) add the tail of the old last line if anything is left
|
||||
wxString lineLastOrig = GetLineText(lineEnd);
|
||||
if ( (size_t)colEnd < lineLastOrig.length() )
|
||||
{
|
||||
lineLast += lineLastOrig.c_str() + (size_t)colEnd;
|
||||
}
|
||||
|
||||
m_lines[lineEnd] = lineLast;
|
||||
|
||||
#if 0 // single line only
|
||||
// replace the part of the text with the new value
|
||||
wxString valueNew(m_value, (size_t)from);
|
||||
|
||||
@@ -221,6 +350,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
||||
RefreshPixelRange(0, startNewText, widthNewText);
|
||||
|
||||
// TODO: and the affected parts of the next line(s)
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
void wxTextCtrl::Remove(long from, long to)
|
||||
|
Reference in New Issue
Block a user