Skip to content

Commit 2dc2ecf

Browse files
committed
Add more quick exit in InsertAttrRuns
1 parent abf3ee5 commit 2dc2ecf

File tree

1 file changed

+54
-21
lines changed

1 file changed

+54
-21
lines changed

src/buffer/out/AttrRow.cpp

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -278,31 +278,64 @@ void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAtt
278278
{
279279
return S_OK;
280280
}
281-
// .. otherwise if we internally have a list of 2 and we're about to insert a single color
282-
// it's probable that we're just walking left-to-right through the row and changing each
283-
// cell one at a time.
284-
// e.g.
285-
// AAAAABBBBBBB
286-
// AAAAAABBBBBB
287-
// AAAAAAABBBBB
288-
// Check for that circumstance by seeing if we're inserting a single run of the
289-
// left side color right at the boundary and just adjust the counts in the existing
290-
// two elements in our internal list.
291-
else if (_list.size() == 2 && newAttrs.at(0).GetLength() == 1)
281+
// .. otherwise if we internally have a list of 2 or more and we're about to insert a single color
282+
// it's possible that we just walk left-to-right through the row and find a quick exit.
283+
else if (iStart > 0 && iStart == iEnd)
292284
{
293-
const auto left = _list.begin();
294-
if (iStart == left->GetLength() && NewAttr == left->GetAttributes())
285+
// First we try to find the run where the insertion happens, using lowerBound and upperBound to track
286+
// where we are curretly at.
287+
size_t lowerBound = 0;
288+
size_t upperBound = 0;
289+
for (size_t i = 0; i < _list.size(); i++)
295290
{
296-
const auto right = left + 1;
297-
left->IncrementLength();
298-
right->DecrementLength();
299-
300-
// If we just reduced the right half to zero, just erase it out of the list.
301-
if (right->GetLength() == 0)
291+
upperBound += _list.at(i).GetLength();
292+
if (iStart >= lowerBound && iStart < upperBound)
302293
{
303-
_list.erase(right);
294+
const auto curr = std::next(_list.begin(), i);
295+
296+
// The run that we try to insert into has the same color as the new one.
297+
// e.g.
298+
// AAAAABBBBBBBCCC
299+
// ^
300+
// AAAAABBBBBBBCCC
301+
//
302+
// 'B' is the new color and '^' represents where iStart is. We don't have to
303+
// do anything.
304+
if (curr->GetAttributes() == NewAttr)
305+
{
306+
return S_OK;
307+
}
308+
309+
// If the insertion happens at current run's lower boundary...
310+
if (iStart == lowerBound)
311+
{
312+
const auto prev = std::prev(curr, 1);
313+
// ... and the previous run has the same color as the new one, we can
314+
// just adjust the counts in the existing two elements in our internal list.
315+
// e.g.
316+
// AAAAABBBBBBBCCC
317+
// ^
318+
// AAAAAABBBBBBCCC
319+
//
320+
// Here 'A' is the new color.
321+
if (NewAttr == prev->GetAttributes())
322+
{
323+
prev->IncrementLength();
324+
curr->DecrementLength();
325+
326+
// If we just reduced the right half to zero, just erase it out of the list.
327+
if (curr->GetLength() == 0)
328+
{
329+
_list.erase(curr);
330+
}
331+
332+
return S_OK;
333+
}
334+
}
304335
}
305-
return S_OK;
336+
337+
// Advance one run in the _list.
338+
lowerBound = upperBound;
306339
}
307340
}
308341
}

0 commit comments

Comments
 (0)