summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/inputwidget.c43
-rw-r--r--src/ui/text.c19
-rw-r--r--src/ui/text.h14
3 files changed, 51 insertions, 25 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index a5e8cf43..f7d41a44 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -1090,8 +1090,13 @@ static iBool findXBreaks_LineMover_(iWrapText *wrap, iRangecc wrappedText,
1090static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir) { 1090static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir) {
1091 const iInputLine *line = cursorLine_InputWidget_(d); 1091 const iInputLine *line = cursorLine_InputWidget_(d);
1092 iRangecc text = range_String(&line->text); 1092 iRangecc text = range_String(&line->text);
1093 iInt2 relCoord = measureRange_Text(d->font, (iRangecc){ text.start, 1093 iWrapText wrapText = {
1094 text.start + d->cursor.x }).advance; 1094 .text = rangeSize_String(&line->text, d->cursor.x),
1095 .maxWidth = width_Rect(contentBounds_InputWidget_(d)),
1096 .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode
1097 : word_WrapTextMode),
1098 };
1099 iInt2 relCoord = measure_WrapText(&wrapText, d->font).advance;
1095 const int cursorWidth = measureN_Text(d->font, charPos_InputWidget_(d, d->cursor), 1).advance.x; 1100 const int cursorWidth = measureN_Text(d->font, charPos_InputWidget_(d, d->cursor), 1).advance.x;
1096 int relLine = relCoord.y / lineHeight_Text(d->font); 1101 int relLine = relCoord.y / lineHeight_Text(d->font);
1097 if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) { 1102 if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) {
@@ -1111,13 +1116,8 @@ static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir) {
1111 else { 1116 else {
1112 return iFalse; 1117 return iFalse;
1113 } 1118 }
1114 iWrapText wrapText = { 1119 wrapText.text = range_String(&cursorLine_InputWidget_(d)->text);
1115 .text = range_String(&cursorLine_InputWidget_(d)->text), 1120 wrapText.hitPoint = addY_I2(relCoord, 1); //arelCddX_I2(relCoord, cursorWidth),
1116 .maxWidth = width_Rect(contentBounds_InputWidget_(d)),
1117 .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode
1118 : word_WrapTextMode),
1119 .hitPoint = addY_I2(relCoord, 1), //arelCddX_I2(relCoord, cursorWidth),
1120 };
1121 measure_WrapText(&wrapText, d->font); 1121 measure_WrapText(&wrapText, d->font);
1122 iAssert(wrapText.hitChar_out); 1122 iAssert(wrapText.hitChar_out);
1123 d->cursor.x = wrapText.hitChar_out - wrapText.text.start; 1123 d->cursor.x = wrapText.hitChar_out - wrapText.text.start;
@@ -1129,7 +1129,8 @@ static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir) {
1129 d->cursor.x += n; 1129 d->cursor.x += n;
1130 } 1130 }
1131 }*/ 1131 }*/
1132 showCursor_InputWidget_(d); 1132 //showCursor_InputWidget_(d);
1133 setCursor_InputWidget(d, d->cursor);
1133 return iTrue; 1134 return iTrue;
1134 1135
1135#if 0 1136#if 0
@@ -1896,20 +1897,28 @@ static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int or
1896 wrappedText.end - cstr + mp->line->range.start 1897 wrappedText.end - cstr + mp->line->range.start
1897 }; 1898 };
1898 if (mark.end <= lineRange.start || mark.start >= lineRange.end) { 1899 if (mark.end <= lineRange.start || mark.start >= lineRange.end) {
1900 mp->pos.y += lineHeight_Text(mp->d->font);
1899 return iTrue; /* outside of mark */ 1901 return iTrue; /* outside of mark */
1900 } 1902 }
1901 iRect rect = { addX_I2(mp->pos, origin), init_I2(advance, lineHeight_Text(mp->d->font)) }; 1903 iRect rect = { addX_I2(mp->pos, origin), init_I2(advance, lineHeight_Text(mp->d->font)) };
1902 if (mark.end < lineRange.end) { 1904 if (mark.end < lineRange.end) {
1903 /* Calculate where the mark ends. */ 1905 /* Calculate where the mark ends. */
1904 const iRangecc markedPrefix = { cstr, cstr + mark.end - lineRange.start }; 1906 const iRangecc markedPrefix = { //cstr, cstr + mark.end - lineRange.start };
1907 wrappedText.start,
1908 wrappedText.start + mark.end - lineRange.start
1909 };
1905 rect.size.x = measureRange_Text(mp->d->font, markedPrefix).advance.x; 1910 rect.size.x = measureRange_Text(mp->d->font, markedPrefix).advance.x;
1906 } 1911 }
1907 if (mark.start > lineRange.start) { 1912 if (mark.start > lineRange.start) {
1908 /* Calculate where the mark starts. */ 1913 /* Calculate where the mark starts. */
1909 const iRangecc unmarkedPrefix = { cstr, cstr + mark.start - lineRange.start }; 1914 const iRangecc unmarkedPrefix = { //cstr, cstr + mark.start - lineRange.start
1915 wrappedText.start,
1916 wrappedText.start + mark.start - lineRange.start
1917 };
1910 adjustEdges_Rect(&rect, 0, 0, 0, measureRange_Text(mp->d->font, unmarkedPrefix).advance.x); 1918 adjustEdges_Rect(&rect, 0, 0, 0, measureRange_Text(mp->d->font, unmarkedPrefix).advance.x);
1911 } 1919 }
1912 rect.size.x = iMax(gap_UI / 3, rect.size.x); 1920 rect.size.x = iMax(gap_UI / 3, rect.size.x);
1921 mp->pos.y += lineHeight_Text(mp->d->font);
1913 fillRect_Paint(mp->paint, rect, uiMarked_ColorId); 1922 fillRect_Paint(mp->paint, rect, uiMarked_ColorId);
1914 return iTrue; 1923 return iTrue;
1915} 1924}
@@ -2041,11 +2050,11 @@ static void draw_InputWidget_(const iInputWidget *d) {
2041 /* The bounds include visible characters, while advance includes whitespace as well. 2050 /* The bounds include visible characters, while advance includes whitespace as well.
2042 Normally only the advance is needed, but if the cursor is at a newline, the advance 2051 Normally only the advance is needed, but if the cursor is at a newline, the advance
2043 will have reset back to zero. */ 2052 will have reset back to zero. */
2044 wrapText.text = range_String(text); 2053 wrapText.text = range_String(text);
2045 wrapText.text.end = wrapText.text.start + d->cursor.x; 2054 wrapText.hitChar = wrapText.text.start + d->cursor.x;
2046 iAssert(wrapText.text.end <= constEnd_String(text));
2047 //const int prefixSize = maxWidth_TextMetrics( 2055 //const int prefixSize = maxWidth_TextMetrics(
2048 const iTextMetrics tm = measure_WrapText(&wrapText, d->font); 2056 measure_WrapText(&wrapText, d->font);
2057 const iInt2 advance = wrapText.hitAdvance_out;
2049 // const iInt2 curPos = addX_I2(addY_I2(contentBounds.pos, lineHeight_Text(d->font) 2058 // const iInt2 curPos = addX_I2(addY_I2(contentBounds.pos, lineHeight_Text(d->font)
2050 // * d->cursorLine), 2059 // * d->cursorLine),
2051 // prefixSize + 2060 // prefixSize +
@@ -2054,7 +2063,7 @@ static void draw_InputWidget_(const iInputWidget *d) {
2054 //printf("%d -> tm.advance: %d, %d\n", d->cursor.x, tm.advance.x, tm.advance.y); 2063 //printf("%d -> tm.advance: %d, %d\n", d->cursor.x, tm.advance.x, tm.advance.y);
2055 const iInt2 curPos = add_I2(addY_I2(topLeft_Rect(contentBounds), visLineOffsetY + 2064 const iInt2 curPos = add_I2(addY_I2(topLeft_Rect(contentBounds), visLineOffsetY +
2056 visWrapsAbove * lineHeight_Text(d->font)), 2065 visWrapsAbove * lineHeight_Text(d->font)),
2057 addX_I2(tm.advance, 2066 addX_I2(advance,
2058 (d->mode == insert_InputMode ? -curSize.x / 2 : 0))); 2067 (d->mode == insert_InputMode ? -curSize.x / 2 : 0)));
2059 const iRect curRect = { curPos, curSize }; 2068 const iRect curRect = { curPos, curSize };
2060 fillRect_Paint(&p, curRect, uiInputCursor_ColorId); 2069 fillRect_Paint(&p, curRect, uiInputCursor_ColorId);
diff --git a/src/ui/text.c b/src/ui/text.c
index d6a45c69..ce383ccf 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -1380,8 +1380,9 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1380 /* TODO: Duplicated args? */ 1380 /* TODO: Duplicated args? */
1381 iAssert(equalRange_Rangecc(wrap->text, args->text)); 1381 iAssert(equalRange_Rangecc(wrap->text, args->text));
1382 /* Initialize the wrap range. */ 1382 /* Initialize the wrap range. */
1383 wrap->wrapRange_ = args->text; 1383 wrap->wrapRange_ = args->text;
1384 wrap->hitChar_out = NULL; 1384 wrap->hitAdvance_out = zero_I2();
1385 wrap->hitChar_out = NULL;
1385 wrap->hitGlyphNormX_out = 0.0f; 1386 wrap->hitGlyphNormX_out = 0.0f;
1386 } 1387 }
1387 const iChar *logicalText = constData_Array(&attrText.logical); 1388 const iChar *logicalText = constData_Array(&attrText.logical);
@@ -1427,6 +1428,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1427 const int layoutBound = (wrap ? wrap->maxWidth : 0); 1428 const int layoutBound = (wrap ? wrap->maxWidth : 0);
1428 iBool isFirst = iTrue; 1429 iBool isFirst = iTrue;
1429 const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); 1430 const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2());
1431 const iBool checkHitChar = wrap && wrap->hitChar;
1430 while (!isEmpty_Range(&wrapRuns)) { 1432 while (!isEmpty_Range(&wrapRuns)) {
1431 if (isFirst) { 1433 if (isFirst) {
1432 isFirst = iFalse; 1434 isFirst = iFalse;
@@ -1446,6 +1448,11 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1446 for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { 1448 for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) {
1447 const iAttributedRun *run = at_Array(&attrText.runs, runIndex); 1449 const iAttributedRun *run = at_Array(&attrText.runs, runIndex);
1448 if (run->flags.isLineBreak) { 1450 if (run->flags.isLineBreak) {
1451 if (checkHitChar) {
1452 if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) {
1453 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor);
1454 }
1455 }
1449 wrapPosRange.end = run->logical.start; 1456 wrapPosRange.end = run->logical.start;
1450 wrapResumePos = run->logical.end; 1457 wrapResumePos = run->logical.end;
1451 wrapRuns.end = runIndex; 1458 wrapRuns.end = runIndex;
@@ -1468,6 +1475,11 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1468 if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { 1475 if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) {
1469 continue; 1476 continue;
1470 } 1477 }
1478 if (checkHitChar) {
1479 if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) {
1480 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor);
1481 }
1482 }
1471 /* Check if the hit point is on the left side of this line. */ 1483 /* Check if the hit point is on the left side of this line. */
1472 if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) { 1484 if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) {
1473 wrap->hitChar_out = sourcePtr_AttributedText_(&attrText, logPos); 1485 wrap->hitChar_out = sourcePtr_AttributedText_(&attrText, logPos);
@@ -1723,6 +1735,9 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1723 wrapPosRange.start = wrapResumePos; 1735 wrapPosRange.start = wrapResumePos;
1724 wrapPosRange.end = textLen; 1736 wrapPosRange.end = textLen;
1725 } 1737 }
1738 if (checkHitChar && wrap->hitChar == args->text.end) {
1739 wrap->hitAdvance_out = init_I2(xCursor, yCursor);
1740 }
1726 if (endsWith_Rangecc(args->text, "\n")) { 1741 if (endsWith_Rangecc(args->text, "\n")) {
1727 /* FIXME: This is a kludge, the wrap loop should handle this case, too. */ 1742 /* FIXME: This is a kludge, the wrap loop should handle this case, too. */
1728 /* The last wrap is an empty newline wrap. */ 1743 /* The last wrap is an empty newline wrap. */
diff --git a/src/ui/text.h b/src/ui/text.h
index a82da22c..322d2938 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -206,15 +206,17 @@ enum iWrapTextMode {
206 206
207struct Impl_WrapText { 207struct Impl_WrapText {
208 /* arguments */ 208 /* arguments */
209 iRangecc text; 209 iRangecc text;
210 int maxWidth; 210 int maxWidth;
211 enum iWrapTextMode mode; 211 enum iWrapTextMode mode;
212 iBool (*wrapFunc)(iWrapText *, iRangecc wrappedText, int origin, int advance, iBool isBaseRTL); 212 iBool (*wrapFunc)(iWrapText *, iRangecc wrappedText, int origin, int advance, iBool isBaseRTL);
213 void * context; 213 void * context;
214 int baseDir; /* set to +1 for LTR, -1 for RTL */ 214 int baseDir; /* set to +1 for LTR, -1 for RTL */
215 iInt2 hitPoint; 215 iInt2 hitPoint; /* sets hitChar_out */
216 const char *hitChar; /* sets hitAdvance_out */
216 /* output */ 217 /* output */
217 const char *hitChar_out; 218 const char *hitChar_out;
219 iInt2 hitAdvance_out;
218 float hitGlyphNormX_out; /* normalized X inside the glyph */ 220 float hitGlyphNormX_out; /* normalized X inside the glyph */
219 /* internal */ 221 /* internal */
220 iRangecc wrapRange_; 222 iRangecc wrapRange_;