diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-08-24 14:35:14 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-08-24 14:35:14 +0300 |
commit | eb732a09382d14aeac2fa17646d09a1f15bb2da3 (patch) | |
tree | a01f5d9541ecccb7c381de3a15ce3545a2ecc714 /src/ui/text.c | |
parent | b181150bad024e35a85386085efb096abd7d6901 (diff) |
Text: Character hit test vs. clusters
When multiple codepoints are in the same cluster, the hit test should only consider the first codepoint of the cluster, or otherwise the cursor is positioned somewhere in the middle of the cluster and not at the start.
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index a499d293..006a4d0b 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -1433,7 +1433,6 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1433 | iBool isFirst = iTrue; | 1433 | iBool isFirst = iTrue; |
1434 | const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); | 1434 | const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); |
1435 | const iBool checkHitChar = wrap && wrap->hitChar; | 1435 | const iBool checkHitChar = wrap && wrap->hitChar; |
1436 | //iBool wasCharHit = iFalse; | ||
1437 | while (!isEmpty_Range(&wrapRuns)) { | 1436 | while (!isEmpty_Range(&wrapRuns)) { |
1438 | if (isFirst) { | 1437 | if (isFirst) { |
1439 | isFirst = iFalse; | 1438 | isFirst = iFalse; |
@@ -1447,15 +1446,16 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1447 | if (wrap && (wrap->maxWidth > 0 || checkHitPoint)) { | 1446 | if (wrap && (wrap->maxWidth > 0 || checkHitPoint)) { |
1448 | const iBool isHitPointOnThisLine = (checkHitPoint && wrap->hitPoint.y >= orig.y + yCursor && | 1447 | const iBool isHitPointOnThisLine = (checkHitPoint && wrap->hitPoint.y >= orig.y + yCursor && |
1449 | wrap->hitPoint.y < orig.y + yCursor + d->height); | 1448 | wrap->hitPoint.y < orig.y + yCursor + d->height); |
1449 | iBool wasCharHit = iFalse; /* on this line */ | ||
1450 | float breakAdvance = -1.0f; | 1450 | float breakAdvance = -1.0f; |
1451 | iAssert(wrapPosRange.end == textLen); | 1451 | iAssert(wrapPosRange.end == textLen); |
1452 | /* Determine ends of wrapRuns and wrapVisRange. */ | 1452 | /* Determine ends of wrapRuns and wrapVisRange. */ |
1453 | for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { | 1453 | for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { |
1454 | const iAttributedRun *run = at_Array(&attrText.runs, runIndex); | 1454 | const iAttributedRun *run = at_Array(&attrText.runs, runIndex); |
1455 | if (run->flags.isLineBreak) { | 1455 | if (run->flags.isLineBreak) { |
1456 | if (checkHitChar && wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) { | 1456 | if (checkHitChar && |
1457 | wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) { | ||
1457 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); | 1458 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); |
1458 | // wasCharHit = iTrue; | ||
1459 | } | 1459 | } |
1460 | wrapPosRange.end = run->logical.start; | 1460 | wrapPosRange.end = run->logical.start; |
1461 | wrapResumePos = run->logical.end; | 1461 | wrapResumePos = run->logical.end; |
@@ -1479,9 +1479,10 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1479 | if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { | 1479 | if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { |
1480 | continue; | 1480 | continue; |
1481 | } | 1481 | } |
1482 | if (checkHitChar && wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) { | 1482 | if (checkHitChar && !wasCharHit && |
1483 | wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) { | ||
1483 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); | 1484 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); |
1484 | //wasCharHit = iTrue; | 1485 | wasCharHit = iTrue; /* variation selectors etc. have matching cluster */ |
1485 | } | 1486 | } |
1486 | /* Check if the hit point is on the left side of this line. */ | 1487 | /* Check if the hit point is on the left side of this line. */ |
1487 | if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) { | 1488 | if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) { |