@@ -387,6 +387,12 @@ constexpr WrapBreak GetWrapBreakEx(unsigned int ch, bool isUtf8) noexcept {
387
387
}
388
388
389
389
void LineLayout::WrapLine (const Document *pdoc, Sci::Position posLineStart, Wrap wrapState, XYPOSITION wrapWidth, XYPOSITION wrapIndent_, bool partialLine) {
390
+ // Document wants document positions but simpler to work in line positions
391
+ // so take care of adding and subtracting line start in a lambda.
392
+ auto CharacterBoundary = [=](Sci::Position i, int moveDir) noexcept -> Sci::Position {
393
+ return pdoc->MovePositionOutsideChar (i + posLineStart, moveDir) - posLineStart;
394
+ };
395
+ // Calculate line start positions based upon width.
390
396
Sci::Position lastLineStart = 0 ;
391
397
XYPOSITION startOffset = wrapWidth;
392
398
Sci::Position p = 0 ;
@@ -409,8 +415,9 @@ void LineLayout::WrapLine(const Document *pdoc, Sci::Position posLineStart, Wrap
409
415
// backtrack to find lastGoodBreak
410
416
Sci::Position lastGoodBreak = p;
411
417
if (p > 0 ) {
412
- lastGoodBreak = pdoc-> MovePositionOutsideChar (p + posLineStart , -1 ) - posLineStart ;
418
+ lastGoodBreak = CharacterBoundary (p , -1 );
413
419
}
420
+ bool foundBreak = false ;
414
421
if (wrapState != Wrap::Char) {
415
422
Sci::Position pos = lastGoodBreak;
416
423
CharacterClass ccPrev = CharacterClass::space;
@@ -425,13 +432,15 @@ void LineLayout::WrapLine(const Document *pdoc, Sci::Position posLineStart, Wrap
425
432
while (pos > lastLineStart) {
426
433
// style boundary and space
427
434
if (wrapState != Wrap::WhiteSpace && (styles[pos - 1 ] != styles[pos])) {
435
+ foundBreak = true ;
428
436
break ;
429
437
}
430
438
if (IsBreakSpace (chars[pos - 1 ]) && !IsBreakSpace (chars[pos])) {
439
+ foundBreak = true ;
431
440
break ;
432
441
}
433
442
434
- const Sci::Position posBefore = pdoc-> MovePositionOutsideChar (pos + posLineStart - 1 , -1 ) - posLineStart ;
443
+ const Sci::Position posBefore = CharacterBoundary (pos - 1 , -1 );
435
444
if (wrapState == Wrap::Auto) {
436
445
// word boundary
437
446
// TODO: Unicode Line Breaking Algorithm https://www.unicode.org/reports/tr14/
@@ -466,14 +475,20 @@ void LineLayout::WrapLine(const Document *pdoc, Sci::Position posLineStart, Wrap
466
475
lastGoodBreak = pos;
467
476
}
468
477
}
469
- if (lastGoodBreak == lastLineStart) {
478
+ if (lastGoodBreak == lastLineStart || (isUtf8 && !foundBreak) ) {
470
479
// Try moving to start of last character
471
- if (p > 0 ) {
472
- lastGoodBreak = pdoc->MovePositionOutsideChar (p + posLineStart, -1 ) - posLineStart;
480
+ if (lastGoodBreak == lastLineStart && p > 0 ) {
481
+ lastGoodBreak = CharacterBoundary (p, -1 );
482
+ }
483
+ if (isUtf8 && lastGoodBreak != lastLineStart) {
484
+ const char *text = &chars[lastLineStart];
485
+ size_t lengthSegment = lastGoodBreak - lastLineStart;
486
+ lengthSegment = Document::DiscardLastCombinedCharacter (text, lengthSegment, maxLineLength - lastLineStart);
487
+ lastGoodBreak = lastLineStart + lengthSegment;
473
488
}
474
489
if (lastGoodBreak == lastLineStart) {
475
490
// Ensure at least one character on line.
476
- lastGoodBreak = pdoc-> MovePositionOutsideChar (lastGoodBreak + posLineStart + 1 , 1 ) - posLineStart ;
491
+ lastGoodBreak = CharacterBoundary (lastGoodBreak + 1 , 1 );
477
492
}
478
493
}
479
494
lastLineStart = lastGoodBreak;
0 commit comments