Replace() optimization for single line controls restored
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8575 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -488,116 +488,159 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
|
|
||||||
#else // 1 (new replacement code)
|
#else // 1 (new replacement code)
|
||||||
|
|
||||||
/*
|
if ( IsSingleLine() )
|
||||||
Join all the lines in the replacement range into one string, then
|
|
||||||
replace a part of it with the new text and break it into lines again.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// (1) join lines
|
|
||||||
wxString textOrig;
|
|
||||||
long line;
|
|
||||||
for ( line = lineStart; line <= lineEnd; line++ )
|
|
||||||
{
|
{
|
||||||
if ( line > lineStart )
|
// replace the part of the text with the new value
|
||||||
|
wxString valueNew(m_value, (size_t)from);
|
||||||
|
|
||||||
|
// remember it for later use
|
||||||
|
wxCoord startNewText = GetTextWidth(valueNew);
|
||||||
|
|
||||||
|
valueNew += text;
|
||||||
|
if ( (size_t)to < m_value.length() )
|
||||||
{
|
{
|
||||||
// from previous line
|
valueNew += m_value.c_str() + (size_t)to;
|
||||||
textOrig += _T('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textOrig += m_lines[line];
|
// OPT: is the following really ok? not sure any more now at 2 am...
|
||||||
}
|
|
||||||
|
|
||||||
// (2) replace text in the combined string
|
// we usually refresh till the end of line except of the most common case
|
||||||
wxString textNew(textOrig, colStart);
|
// when some text is appended to the end of the string in which case we
|
||||||
|
// refresh just it
|
||||||
|
wxCoord widthNewText;
|
||||||
|
|
||||||
// these values will be used to refresh the changed area below
|
if ( (size_t)from < m_value.length() )
|
||||||
wxCoord widthNewText, startNewText = GetTextWidth(textNew);
|
|
||||||
if ( (size_t)colStart == m_lines[lineStart].length() )
|
|
||||||
{
|
|
||||||
// text appended, refresh just enough to show the new text
|
|
||||||
widthNewText = GetTextWidth(text.BeforeFirst(_T('\n')));
|
|
||||||
}
|
|
||||||
else // text inserted, refresh till the end of line
|
|
||||||
{
|
|
||||||
widthNewText = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
textNew += text;
|
|
||||||
size_t toRel = (size_t)((to - from) + colStart); // adjust for index shift
|
|
||||||
if ( toRel < textOrig.length() )
|
|
||||||
textNew += textOrig.c_str() + toRel;
|
|
||||||
|
|
||||||
// (3) break it into lines
|
|
||||||
wxArrayString lines;
|
|
||||||
if ( textNew.empty() )
|
|
||||||
{
|
|
||||||
// special case: if the replacement string is empty we still want to
|
|
||||||
// have one (empty) string in the lines array but wxStringTokenize()
|
|
||||||
// won't put anything in it in this case, so do it ourselves
|
|
||||||
lines.Add(wxEmptyString);
|
|
||||||
}
|
|
||||||
else // break into lines normally
|
|
||||||
{
|
|
||||||
lines = wxStringTokenize(textNew, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nReplaceCount = lines.GetCount(),
|
|
||||||
nReplaceLine = 0;
|
|
||||||
|
|
||||||
// (4) merge into the array
|
|
||||||
|
|
||||||
size_t countOld = m_lines.GetCount();
|
|
||||||
|
|
||||||
// (4a) replace
|
|
||||||
for ( line = lineStart; line <= lineEnd; line++, nReplaceLine++ )
|
|
||||||
{
|
|
||||||
if ( nReplaceLine < nReplaceCount )
|
|
||||||
{
|
{
|
||||||
// we have the replacement line for this one
|
// refresh till the end of line
|
||||||
m_lines[line] = lines[nReplaceLine];
|
widthNewText = 0;
|
||||||
|
|
||||||
UpdateMaxWidth(line);
|
|
||||||
}
|
}
|
||||||
else // no more replacement lines
|
else // text appended, not replaced
|
||||||
{
|
{
|
||||||
// (4b) delete all extra lines
|
// refresh only the new text
|
||||||
while ( line <= lineEnd )
|
widthNewText = GetTextWidth(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_value = valueNew;
|
||||||
|
|
||||||
|
// force m_colLastVisible update
|
||||||
|
m_colLastVisible = -1;
|
||||||
|
|
||||||
|
// repaint
|
||||||
|
RefreshPixelRange(0, startNewText, widthNewText);
|
||||||
|
}
|
||||||
|
else // multiline
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Join all the lines in the replacement range into one string, then
|
||||||
|
replace a part of it with the new text and break it into lines again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// (1) join lines
|
||||||
|
wxString textOrig;
|
||||||
|
long line;
|
||||||
|
for ( line = lineStart; line <= lineEnd; line++ )
|
||||||
|
{
|
||||||
|
if ( line > lineStart )
|
||||||
{
|
{
|
||||||
m_lines.RemoveAt(line++);
|
// from previous line
|
||||||
|
textOrig += _T('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
textOrig += m_lines[line];
|
||||||
|
}
|
||||||
|
|
||||||
|
// (2) replace text in the combined string
|
||||||
|
wxString textNew(textOrig, colStart);
|
||||||
|
|
||||||
|
// these values will be used to refresh the changed area below
|
||||||
|
wxCoord widthNewText, startNewText = GetTextWidth(textNew);
|
||||||
|
if ( (size_t)colStart == m_lines[lineStart].length() )
|
||||||
|
{
|
||||||
|
// text appended, refresh just enough to show the new text
|
||||||
|
widthNewText = GetTextWidth(text.BeforeFirst(_T('\n')));
|
||||||
|
}
|
||||||
|
else // text inserted, refresh till the end of line
|
||||||
|
{
|
||||||
|
widthNewText = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textNew += text;
|
||||||
|
size_t toRel = (size_t)((to - from) + colStart); // adjust for index shift
|
||||||
|
if ( toRel < textOrig.length() )
|
||||||
|
textNew += textOrig.c_str() + toRel;
|
||||||
|
|
||||||
|
// (3) break it into lines
|
||||||
|
wxArrayString lines;
|
||||||
|
if ( textNew.empty() )
|
||||||
|
{
|
||||||
|
// special case: if the replacement string is empty we still want to
|
||||||
|
// have one (empty) string in the lines array but wxStringTokenize()
|
||||||
|
// won't put anything in it in this case, so do it ourselves
|
||||||
|
lines.Add(wxEmptyString);
|
||||||
|
}
|
||||||
|
else // break into lines normally
|
||||||
|
{
|
||||||
|
lines = wxStringTokenize(textNew, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nReplaceCount = lines.GetCount(),
|
||||||
|
nReplaceLine = 0;
|
||||||
|
|
||||||
|
// (4) merge into the array
|
||||||
|
|
||||||
|
size_t countOld = m_lines.GetCount();
|
||||||
|
|
||||||
|
// (4a) replace
|
||||||
|
for ( line = lineStart; line <= lineEnd; line++, nReplaceLine++ )
|
||||||
|
{
|
||||||
|
if ( nReplaceLine < nReplaceCount )
|
||||||
|
{
|
||||||
|
// we have the replacement line for this one
|
||||||
|
m_lines[line] = lines[nReplaceLine];
|
||||||
|
|
||||||
|
UpdateMaxWidth(line);
|
||||||
|
}
|
||||||
|
else // no more replacement lines
|
||||||
|
{
|
||||||
|
// (4b) delete all extra lines
|
||||||
|
while ( line <= lineEnd )
|
||||||
|
{
|
||||||
|
m_lines.RemoveAt(line++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// (4c) insert the new lines
|
// (4c) insert the new lines
|
||||||
while ( nReplaceLine < nReplaceCount )
|
while ( nReplaceLine < nReplaceCount )
|
||||||
{
|
{
|
||||||
m_lines.Insert(lines[nReplaceLine++], ++lineEnd);
|
m_lines.Insert(lines[nReplaceLine++], ++lineEnd);
|
||||||
|
|
||||||
UpdateMaxWidth(lineEnd);
|
UpdateMaxWidth(lineEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (5) now refresh the changed area
|
// (5) now refresh the changed area
|
||||||
RefreshPixelRange(lineStart, startNewText, widthNewText);
|
RefreshPixelRange(lineStart, startNewText, widthNewText);
|
||||||
if ( m_lines.GetCount() == countOld )
|
if ( m_lines.GetCount() == countOld )
|
||||||
{
|
{
|
||||||
// number of lines didn't change, refresh the updated lines and the
|
// number of lines didn't change, refresh the updated lines and the
|
||||||
// last one
|
// last one
|
||||||
if ( lineStart < lineEnd )
|
if ( lineStart < lineEnd )
|
||||||
RefreshLineRange(lineStart + 1, lineEnd);
|
RefreshLineRange(lineStart + 1, lineEnd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// number of lines did change, we need to refresh everything below the
|
// number of lines did change, we need to refresh everything below the
|
||||||
// start line
|
// start line
|
||||||
RefreshLineRange(lineStart + 1);
|
RefreshLineRange(lineStart + 1);
|
||||||
|
|
||||||
// the vert scrollbar might [dis]appear
|
// the vert scrollbar might [dis]appear
|
||||||
m_updateScrollbarY = TRUE;
|
m_updateScrollbarY = TRUE;
|
||||||
}
|
}
|
||||||
#endif // 0/1
|
#endif // 0/1
|
||||||
|
|
||||||
// update the (cached) last position
|
// update the (cached) last position
|
||||||
m_posLast += text.length() - to + from;
|
m_posLast += text.length() - to + from;
|
||||||
|
}
|
||||||
|
|
||||||
// update the current position: note that we always put the cursor at the
|
// update the current position: note that we always put the cursor at the
|
||||||
// end of the replacement text
|
// end of the replacement text
|
||||||
|
Reference in New Issue
Block a user