@@ -141,25 +141,13 @@ ROW::ROW(wchar_t* charsBuffer, uint16_t* charOffsetsBuffer, uint16_t rowWidth, c
141
141
_attr{ rowWidth, fillAttribute },
142
142
_columnCount{ rowWidth }
143
143
{
144
- if (_chars.data ())
144
+ SetBuffers (charsBuffer, charOffsetsBuffer, rowWidth, fillAttribute);
145
+ if (charsBuffer)
145
146
{
146
147
_init ();
147
148
}
148
149
}
149
150
150
- void swap (ROW& lhs, ROW& rhs) noexcept
151
- {
152
- std::swap (lhs._charsBuffer , rhs._charsBuffer );
153
- std::swap (lhs._charsHeap , rhs._charsHeap );
154
- std::swap (lhs._chars , rhs._chars );
155
- std::swap (lhs._charOffsets , rhs._charOffsets );
156
- std::swap (lhs._attr , rhs._attr );
157
- std::swap (lhs._columnCount , rhs._columnCount );
158
- std::swap (lhs._lineRendition , rhs._lineRendition );
159
- std::swap (lhs._wrapForced , rhs._wrapForced );
160
- std::swap (lhs._doubleBytePadded , rhs._doubleBytePadded );
161
- }
162
-
163
151
void ROW::SetWrapForced (const bool wrap) noexcept
164
152
{
165
153
_wrapForced = wrap;
@@ -200,6 +188,19 @@ RowTextIterator ROW::End() const noexcept
200
188
return { _chars, _charOffsets, _columnCount };
201
189
}
202
190
191
+ void ROW::SetBuffers (wchar_t * charsBuffer, uint16_t * charOffsetsBuffer, uint16_t rowWidth, const TextAttribute& fillAttribute) noexcept
192
+ {
193
+ _charsBuffer = charsBuffer;
194
+ _charsHeap.reset ();
195
+ _chars = { charsBuffer, rowWidth };
196
+ _charOffsets = { charOffsetsBuffer, ::base::strict_cast<size_t >(rowWidth) + 1u };
197
+ _attr = { rowWidth, fillAttribute };
198
+ _columnCount = rowWidth;
199
+ _lineRendition = LineRendition::SingleWidth;
200
+ _wrapForced = false ;
201
+ _doubleBytePadded = false ;
202
+ }
203
+
203
204
// Routine Description:
204
205
// - Sets all properties of the ROW to default values
205
206
// Arguments:
@@ -223,78 +224,6 @@ void ROW::_init() noexcept
223
224
std::iota (_charOffsets.begin (), _charOffsets.end (), uint16_t { 0 });
224
225
}
225
226
226
- // Routine Description:
227
- // - resizes ROW to new width
228
- // Arguments:
229
- // - charsBuffer - a new backing buffer to use for _charsBuffer
230
- // - charOffsetsBuffer - a new backing buffer to use for _charOffsets
231
- // - rowWidth - the new width, in cells
232
- // - fillAttribute - the attribute to use for any newly added, trailing cells
233
- void ROW::Resize (wchar_t * charsBuffer, uint16_t * charOffsetsBuffer, uint16_t rowWidth, const TextAttribute& fillAttribute)
234
- {
235
- // A default-constructed ROW has no cols/chars to copy.
236
- // It can be detected by the lack of a _charsBuffer (among others).
237
- //
238
- // Otherwise, this block figures out how much we can copy into the new `rowWidth`.
239
- uint16_t colsToCopy = 0 ;
240
- uint16_t charsToCopy = 0 ;
241
- if (_charsBuffer)
242
- {
243
- colsToCopy = std::min (rowWidth, _columnCount);
244
- // Safety: colsToCopy is [0, _columnCount].
245
- charsToCopy = _uncheckedCharOffset (colsToCopy);
246
- // Safety: colsToCopy is [0, _columnCount] due to colsToCopy != 0.
247
- for (; colsToCopy != 0 && _uncheckedIsTrailer (colsToCopy); --colsToCopy)
248
- {
249
- }
250
- }
251
-
252
- // If we grow the row width, we have to append a bunch of whitespace.
253
- // `trailingWhitespace` stores that amount.
254
- // Safety: The preceding block left colsToCopy in the range [0, rowWidth].
255
- const uint16_t trailingWhitespace = rowWidth - colsToCopy;
256
-
257
- // Allocate memory for the new `_chars` array.
258
- // Use the provided charsBuffer if possible, otherwise allocate a `_charsHeap`.
259
- std::unique_ptr<wchar_t []> charsHeap;
260
- std::span chars{ charsBuffer, rowWidth };
261
- const std::span charOffsets{ charOffsetsBuffer, ::base::strict_cast<size_t >(rowWidth) + 1u };
262
- if (const uint16_t charsCapacity = charsToCopy + trailingWhitespace; charsCapacity > rowWidth)
263
- {
264
- charsHeap = std::make_unique_for_overwrite<wchar_t []>(charsCapacity);
265
- chars = { charsHeap.get (), charsCapacity };
266
- }
267
-
268
- // Copy chars and charOffsets over.
269
- {
270
- const auto it = std::copy_n (_chars.begin (), charsToCopy, chars.begin ());
271
- std::fill_n (it, trailingWhitespace, L' ' );
272
- }
273
- {
274
- const auto it = std::copy_n (_charOffsets.begin (), colsToCopy, charOffsets.begin ());
275
- // The _charOffsets array is 1 wider than newWidth indicates.
276
- // This is because the extra column contains the past-the-end index into _chars.
277
- iota_n (it, trailingWhitespace + 1u , charsToCopy);
278
- }
279
-
280
- _charsBuffer = charsBuffer;
281
- _charsHeap = std::move (charsHeap);
282
- _chars = chars;
283
- _charOffsets = charOffsets;
284
- _columnCount = rowWidth;
285
-
286
- // .resize_trailing_extent() doesn't work if the vector is empty,
287
- // since there's no trailing item that could be extended.
288
- if (_attr.empty ())
289
- {
290
- _attr = { rowWidth, fillAttribute };
291
- }
292
- else
293
- {
294
- _attr.resize_trailing_extent (rowWidth);
295
- }
296
- }
297
-
298
227
void ROW::TransferAttributes (const til::small_rle<TextAttribute, uint16_t , 1 >& attr, til::CoordType newWidth)
299
228
{
300
229
_attr = attr;
@@ -711,6 +640,34 @@ catch (...)
711
640
{
712
641
row.SetDoubleBytePadded (colEnd < row._columnCount );
713
642
}
643
+
644
+ if constexpr (false )
645
+ {
646
+ auto it = row._charOffsets .begin ();
647
+ uint16_t expected = 0 ;
648
+
649
+ for (const auto & s : til::utf16_iterator{ row.GetText () })
650
+ {
651
+ const auto wide = til::at (s, 0 ) < 0x80 ? false : IsGlyphFullWidth (s);
652
+
653
+ if (*it != expected)
654
+ {
655
+ __debugbreak ();
656
+ }
657
+ ++it;
658
+
659
+ if (wide )
660
+ {
661
+ if (*it != (expected | CharOffsetsTrailer))
662
+ {
663
+ __debugbreak ();
664
+ }
665
+ ++it;
666
+ }
667
+
668
+ expected = gsl::narrow_cast<uint16_t >(expected + s.size ());
669
+ }
670
+ }
714
671
}
715
672
716
673
// This function represents the slow path of ReplaceCharacters(),
0 commit comments