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:
Vadim Zeitlin
2000-10-12 09:09:49 +00:00
parent 5abcba0bef
commit b7cdbb0e4c
4 changed files with 170 additions and 8 deletions

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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)