diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/inputwidget.c | 65 | ||||
-rw-r--r-- | src/ui/text.c | 22 | ||||
-rw-r--r-- | src/ui/text.h | 1 |
3 files changed, 38 insertions, 50 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 38c93f93..3a774b89 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -178,28 +178,17 @@ struct Impl_InputWidget { | |||
178 | enum iInputMode mode; | 178 | enum iInputMode mode; |
179 | int inFlags; | 179 | int inFlags; |
180 | size_t maxLen; /* characters */ | 180 | size_t maxLen; /* characters */ |
181 | // size_t maxLayoutLines; | ||
182 | // iArray text; /* iChar[] */ | ||
183 | // iArray oldText; /* iChar[] */ | ||
184 | size_t length; /* current length in characters */ | ||
185 | iArray lines; /* iInputLine[] */ | 181 | iArray lines; /* iInputLine[] */ |
186 | //iArray oldLines; /* iInputLine[], for restoring if edits cancelled */ | ||
187 | iString oldText; /* for restoring if edits cancelled */ | 182 | iString oldText; /* for restoring if edits cancelled */ |
188 | int lastUpdateWidth; | 183 | int lastUpdateWidth; |
189 | iString srcHint; | 184 | iString srcHint; |
190 | iString hint; | 185 | iString hint; |
191 | int leftPadding; | 186 | int leftPadding; |
192 | int rightPadding; | 187 | int rightPadding; |
193 | // size_t cursor; /* offset from beginning */ | ||
194 | // size_t lastCursor; | ||
195 | // size_t cursorLine; | ||
196 | iInt2 cursor; /* cursor position: x = byte offset, y = line index */ | 188 | iInt2 cursor; /* cursor position: x = byte offset, y = line index */ |
197 | iInt2 prevCursor; /* previous cursor position */ | 189 | iInt2 prevCursor; /* previous cursor position */ |
198 | // int verticalMoveX; | ||
199 | iRangei visWrapLines; /* which wrap lines are current visible */ | 190 | iRangei visWrapLines; /* which wrap lines are current visible */ |
200 | // int visLineOffsetY; /* vertical offset of first visible line (pixels) */ | ||
201 | int minWrapLines, maxWrapLines; /* min/max number of visible lines allowed */ | 191 | int minWrapLines, maxWrapLines; /* min/max number of visible lines allowed */ |
202 | // int scrollY; /* wrap lines */ | ||
203 | iRanges mark; | 192 | iRanges mark; |
204 | iRanges initialMark; | 193 | iRanges initialMark; |
205 | iArray undoStack; | 194 | iArray undoStack; |
@@ -356,12 +345,16 @@ static int visLineOffsetY_InputWidget_(const iInputWidget *d) { | |||
356 | return (line->wrapLines.start - d->visWrapLines.start) * lineHeight_Text(d->font); | 345 | return (line->wrapLines.start - d->visWrapLines.start) * lineHeight_Text(d->font); |
357 | } | 346 | } |
358 | 347 | ||
348 | static const iChar sensitiveChar_ = 0x25cf; /* black circle */ | ||
349 | static const char *sensitive_ = "\u25cf"; /* black circle */ | ||
350 | |||
359 | static iWrapText wrap_InputWidget_(const iInputWidget *d, int y) { | 351 | static iWrapText wrap_InputWidget_(const iInputWidget *d, int y) { |
360 | return (iWrapText){ | 352 | return (iWrapText){ |
361 | .text = range_String(&line_InputWidget_(d, y)->text), | 353 | .text = range_String(&line_InputWidget_(d, y)->text), |
362 | .maxWidth = width_Rect(contentBounds_InputWidget_(d)), | 354 | .maxWidth = width_Rect(contentBounds_InputWidget_(d)), |
363 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode | 355 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode |
364 | : word_WrapTextMode), | 356 | : word_WrapTextMode), |
357 | .overrideChar = (d->inFlags & isSensitive_InputWidgetFlag ? sensitiveChar_ : 0), | ||
365 | }; | 358 | }; |
366 | } | 359 | } |
367 | 360 | ||
@@ -469,8 +462,7 @@ static size_t length_InputWidget_(const iInputWidget *d) { | |||
469 | return len; | 462 | return len; |
470 | } | 463 | } |
471 | 464 | ||
472 | static const char *sensitive_ = "\u25cf"; /* black circle */ | 465 | #if 0 |
473 | |||
474 | static iString *visText_InputWidget_(const iInputWidget *d) { | 466 | static iString *visText_InputWidget_(const iInputWidget *d) { |
475 | iString *text; | 467 | iString *text; |
476 | if (~d->inFlags & isSensitive_InputWidgetFlag) { | 468 | if (~d->inFlags & isSensitive_InputWidgetFlag) { |
@@ -478,15 +470,15 @@ static iString *visText_InputWidget_(const iInputWidget *d) { | |||
478 | } | 470 | } |
479 | else { | 471 | else { |
480 | text = new_String(); | 472 | text = new_String(); |
481 | iAssert(d->length == length_InputWidget_(d)); | 473 | // iAssert(d->length == length_InputWidget_(d)); |
482 | for (size_t i = 0; i < d->length; i++) { | 474 | const size_t len = length_InputWidget_(d); |
475 | for (size_t i = 0; i < len; i++) { | ||
483 | appendCStr_String(text, sensitive_); | 476 | appendCStr_String(text, sensitive_); |
484 | } | 477 | } |
485 | } | 478 | } |
486 | return text; | 479 | return text; |
487 | } | 480 | } |
488 | 481 | ||
489 | #if 0 | ||
490 | static void clearLines_InputWidget_(iInputWidget *d) { | 482 | static void clearLines_InputWidget_(iInputWidget *d) { |
491 | iForEach(Array, i, &d->lines) { | 483 | iForEach(Array, i, &d->lines) { |
492 | deinit_InputLine(i.value); | 484 | deinit_InputLine(i.value); |
@@ -1134,20 +1126,6 @@ static size_t indexForRelativeX_InputWidget_(const iInputWidget *d, int x, const | |||
1134 | } | 1126 | } |
1135 | #endif | 1127 | #endif |
1136 | 1128 | ||
1137 | iDeclareType(LineMover) | ||
1138 | |||
1139 | struct Impl_LineMover { | ||
1140 | iInputWidget *d; | ||
1141 | int dir; | ||
1142 | int x; | ||
1143 | }; | ||
1144 | |||
1145 | static iBool findXBreaks_LineMover_(iWrapText *wrap, iRangecc wrappedText, | ||
1146 | int origin, int advance, iBool isBaseRTL) { | ||
1147 | iUnused(isBaseRTL); | ||
1148 | |||
1149 | } | ||
1150 | |||
1151 | static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) { | 1129 | static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) { |
1152 | const iInputLine *line = cursorLine_InputWidget_(d); | 1130 | const iInputLine *line = cursorLine_InputWidget_(d); |
1153 | iRangecc text = range_String(&line->text); | 1131 | iRangecc text = range_String(&line->text); |
@@ -1400,6 +1378,7 @@ static iInt2 coordCursor_InputWidget_(const iInputWidget *d, iInt2 coord) { | |||
1400 | .maxWidth = width_Rect(bounds), | 1378 | .maxWidth = width_Rect(bounds), |
1401 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode : word_WrapTextMode), | 1379 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode : word_WrapTextMode), |
1402 | .hitPoint = relCoord, | 1380 | .hitPoint = relCoord, |
1381 | .overrideChar = (d->inFlags & isSensitive_InputWidgetFlag ? sensitiveChar_ : 0), | ||
1403 | }; | 1382 | }; |
1404 | const iRangei visLines = visibleLineRange_InputWidget_(d); | 1383 | const iRangei visLines = visibleLineRange_InputWidget_(d); |
1405 | for (size_t y = visLines.start; y < visLines.end; y++) { | 1384 | for (size_t y = visLines.start; y < visLines.end; y++) { |
@@ -1710,14 +1689,15 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1710 | return iTrue; | 1689 | return iTrue; |
1711 | case SDLK_RETURN: | 1690 | case SDLK_RETURN: |
1712 | case SDLK_KP_ENTER: | 1691 | case SDLK_KP_ENTER: |
1713 | if (mods == KMOD_SHIFT || (d->maxLen == 0 && | 1692 | if (~d->inFlags & isSensitive_InputWidgetFlag && d->maxLen == 0) { |
1714 | ~d->inFlags & isUrl_InputWidgetFlag && | 1693 | if (mods == KMOD_SHIFT || (~d->inFlags & isUrl_InputWidgetFlag && |
1715 | d->inFlags & enterKeyInsertsLineFeed_InputWidgetFlag)) { | 1694 | d->inFlags & enterKeyInsertsLineFeed_InputWidgetFlag)) { |
1716 | pushUndo_InputWidget_(d); | 1695 | pushUndo_InputWidget_(d); |
1717 | deleteMarked_InputWidget_(d); | 1696 | deleteMarked_InputWidget_(d); |
1718 | insertChar_InputWidget_(d, '\n'); | 1697 | insertChar_InputWidget_(d, '\n'); |
1719 | contentsWereChanged_InputWidget_(d); | 1698 | contentsWereChanged_InputWidget_(d); |
1720 | return iTrue; | 1699 | return iTrue; |
1700 | } | ||
1721 | } | 1701 | } |
1722 | if (d->inFlags & enterKeyEnabled_InputWidgetFlag) { | 1702 | if (d->inFlags & enterKeyEnabled_InputWidgetFlag) { |
1723 | d->inFlags |= enterPressed_InputWidgetFlag; | 1703 | d->inFlags |= enterPressed_InputWidgetFlag; |
@@ -1973,8 +1953,10 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
1973 | : isFocused /*&& !isEmpty_Array(&d->lines)*/ ? uiInputTextFocused_ColorId | 1953 | : isFocused /*&& !isEmpty_Array(&d->lines)*/ ? uiInputTextFocused_ColorId |
1974 | : uiInputText_ColorId; | 1954 | : uiInputText_ColorId; |
1975 | iWrapText wrapText = { | 1955 | iWrapText wrapText = { |
1976 | .maxWidth = width_Rect(contentBounds), | 1956 | .maxWidth = width_Rect(contentBounds), |
1977 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode : word_WrapTextMode) | 1957 | .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode |
1958 | : word_WrapTextMode), | ||
1959 | .overrideChar = (d->inFlags & isSensitive_InputWidgetFlag ? sensitiveChar_ : 0), | ||
1978 | }; | 1960 | }; |
1979 | const iRangei visLines = visibleLineRange_InputWidget_(d); | 1961 | const iRangei visLines = visibleLineRange_InputWidget_(d); |
1980 | const int visLineOffsetY = visLineOffsetY_InputWidget_(d); | 1962 | const int visLineOffsetY = visLineOffsetY_InputWidget_(d); |
@@ -1995,6 +1977,7 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
1995 | .contentBounds = contentBounds, | 1977 | .contentBounds = contentBounds, |
1996 | .mark = mark_InputWidget_(d) | 1978 | .mark = mark_InputWidget_(d) |
1997 | }; | 1979 | }; |
1980 | iAssert(~d->inFlags & isSensitive_InputWidgetFlag || size_Range(&visLines) == 1); | ||
1998 | for (size_t vis = visLines.start; vis < visLines.end; vis++) { | 1981 | for (size_t vis = visLines.start; vis < visLines.end; vis++) { |
1999 | const iInputLine *line = constAt_Array(&d->lines, vis); | 1982 | const iInputLine *line = constAt_Array(&d->lines, vis); |
2000 | wrapText.text = range_String(&line->text); | 1983 | wrapText.text = range_String(&line->text); |
@@ -2061,7 +2044,7 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
2061 | else { | 2044 | else { |
2062 | cursorChar = range_CStr(" "); | 2045 | cursorChar = range_CStr(" "); |
2063 | } | 2046 | } |
2064 | curSize = addX_I2(measureRange_Text(d->font, ch ? cursorChar : range_CStr("_")).bounds.size, | 2047 | curSize = addX_I2(measureRange_Text(d->font, ch ? cursorChar : range_CStr("0")).bounds.size, |
2065 | iMin(2, gap_UI / 4)); | 2048 | iMin(2, gap_UI / 4)); |
2066 | } | 2049 | } |
2067 | else { | 2050 | else { |
diff --git a/src/ui/text.c b/src/ui/text.c index 27ed80ab..bbfd71b8 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -795,7 +795,7 @@ struct Impl_AttributedRun { | |||
795 | 795 | ||
796 | iDeclareType(AttributedText) | 796 | iDeclareType(AttributedText) |
797 | iDeclareTypeConstructionArgs(AttributedText, iRangecc text, size_t maxLen, iFont *font, | 797 | iDeclareTypeConstructionArgs(AttributedText, iRangecc text, size_t maxLen, iFont *font, |
798 | iColor fgColor, int baseDir) | 798 | iColor fgColor, int baseDir, iChar overrideChar) |
799 | 799 | ||
800 | struct Impl_AttributedText { | 800 | struct Impl_AttributedText { |
801 | iRangecc source; /* original source text */ | 801 | iRangecc source; /* original source text */ |
@@ -813,8 +813,9 @@ struct Impl_AttributedText { | |||
813 | }; | 813 | }; |
814 | 814 | ||
815 | iDefineTypeConstructionArgs(AttributedText, | 815 | iDefineTypeConstructionArgs(AttributedText, |
816 | (iRangecc text, size_t maxLen, iFont *font, iColor fgColor, int baseDir), | 816 | (iRangecc text, size_t maxLen, iFont *font, iColor fgColor, |
817 | text, maxLen, font, fgColor, baseDir) | 817 | int baseDir, iChar overrideChar), |
818 | text, maxLen, font, fgColor, baseDir, overrideChar) | ||
818 | 819 | ||
819 | static const char *sourcePtr_AttributedText_(const iAttributedText *d, int logicalPos) { | 820 | static const char *sourcePtr_AttributedText_(const iAttributedText *d, int logicalPos) { |
820 | const int *logToSource = constData_Array(&d->logicalToSourceOffset); | 821 | const int *logToSource = constData_Array(&d->logicalToSourceOffset); |
@@ -859,7 +860,7 @@ static enum iFontId fontId_Text_(const iFont *font) { | |||
859 | return (enum iFontId) (font - text_.fonts); | 860 | return (enum iFontId) (font - text_.fonts); |
860 | } | 861 | } |
861 | 862 | ||
862 | static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir) { | 863 | static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iChar overrideChar) { |
863 | iAssert(isEmpty_Array(&d->runs)); | 864 | iAssert(isEmpty_Array(&d->runs)); |
864 | size_t length = 0; | 865 | size_t length = 0; |
865 | /* Prepare the UTF-32 logical string. */ { | 866 | /* Prepare the UTF-32 logical string. */ { |
@@ -867,6 +868,9 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir) { | |||
867 | iChar u32; | 868 | iChar u32; |
868 | int len = decodeBytes_MultibyteChar(ch, d->source.end, &u32); | 869 | int len = decodeBytes_MultibyteChar(ch, d->source.end, &u32); |
869 | if (len <= 0) break; | 870 | if (len <= 0) break; |
871 | if (overrideChar) { | ||
872 | u32 = overrideChar; | ||
873 | } | ||
870 | pushBack_Array(&d->logical, &u32); | 874 | pushBack_Array(&d->logical, &u32); |
871 | length++; | 875 | length++; |
872 | if (length == d->maxLen) { | 876 | if (length == d->maxLen) { |
@@ -1025,7 +1029,7 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir) { | |||
1025 | } | 1029 | } |
1026 | 1030 | ||
1027 | void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont *font, iColor fgColor, | 1031 | void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont *font, iColor fgColor, |
1028 | int baseDir) { | 1032 | int baseDir, iChar overrideChar) { |
1029 | d->source = text; | 1033 | d->source = text; |
1030 | d->maxLen = maxLen ? maxLen : iInvalidSize; | 1034 | d->maxLen = maxLen ? maxLen : iInvalidSize; |
1031 | d->font = font; | 1035 | d->font = font; |
@@ -1038,7 +1042,7 @@ void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont | |||
1038 | init_Array(&d->logicalToSourceOffset, sizeof(int)); | 1042 | init_Array(&d->logicalToSourceOffset, sizeof(int)); |
1039 | d->bidiLevels = NULL; | 1043 | d->bidiLevels = NULL; |
1040 | d->isBaseRTL = iFalse; | 1044 | d->isBaseRTL = iFalse; |
1041 | prepare_AttributedText_(d, baseDir); | 1045 | prepare_AttributedText_(d, baseDir, overrideChar); |
1042 | } | 1046 | } |
1043 | 1047 | ||
1044 | void deinit_AttributedText(iAttributedText *d) { | 1048 | void deinit_AttributedText(iAttributedText *d) { |
@@ -1189,7 +1193,7 @@ static void cacheTextGlyphs_Font_(iFont *d, const iRangecc text) { | |||
1189 | iArray glyphIndices; | 1193 | iArray glyphIndices; |
1190 | init_Array(&glyphIndices, sizeof(uint32_t)); | 1194 | init_Array(&glyphIndices, sizeof(uint32_t)); |
1191 | iAttributedText attrText; | 1195 | iAttributedText attrText; |
1192 | init_AttributedText(&attrText, text, 0, d, (iColor){}, 0); | 1196 | init_AttributedText(&attrText, text, 0, d, (iColor){}, 0, 0); |
1193 | /* We use AttributedText here so the font lookup matches the behavior during text drawing -- | 1197 | /* We use AttributedText here so the font lookup matches the behavior during text drawing -- |
1194 | glyphs may be selected from a font that's different than `d`. */ | 1198 | glyphs may be selected from a font that's different than `d`. */ |
1195 | const iChar *logicalText = constData_Array(&attrText.logical); | 1199 | const iChar *logicalText = constData_Array(&attrText.logical); |
@@ -1367,14 +1371,14 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1367 | float yCursor = 0.0f; | 1371 | float yCursor = 0.0f; |
1368 | float xCursorMax = 0.0f; | 1372 | float xCursorMax = 0.0f; |
1369 | const iBool isMonospaced = d->isMonospaced; | 1373 | const iBool isMonospaced = d->isMonospaced; |
1374 | iWrapText *wrap = args->wrap; | ||
1370 | iAssert(args->text.end >= args->text.start); | 1375 | iAssert(args->text.end >= args->text.start); |
1371 | /* Split the text into a number of attributed runs that specify exactly which | 1376 | /* Split the text into a number of attributed runs that specify exactly which |
1372 | font is used and other attributes such as color. (HarfBuzz shaping is done | 1377 | font is used and other attributes such as color. (HarfBuzz shaping is done |
1373 | with one specific font.) */ | 1378 | with one specific font.) */ |
1374 | iAttributedText attrText; | 1379 | iAttributedText attrText; |
1375 | init_AttributedText(&attrText, args->text, args->maxLen, d, get_Color(args->color), | 1380 | init_AttributedText(&attrText, args->text, args->maxLen, d, get_Color(args->color), |
1376 | args->baseDir); | 1381 | args->baseDir, wrap ? wrap->overrideChar : 0); |
1377 | iWrapText *wrap = args->wrap; | ||
1378 | if (wrap) { | 1382 | if (wrap) { |
1379 | wrap->baseDir = attrText.isBaseRTL ? -1 : +1; | 1383 | wrap->baseDir = attrText.isBaseRTL ? -1 : +1; |
1380 | /* TODO: Duplicated args? */ | 1384 | /* TODO: Duplicated args? */ |
diff --git a/src/ui/text.h b/src/ui/text.h index 322d2938..71776dca 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -211,6 +211,7 @@ struct Impl_WrapText { | |||
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 | iChar overrideChar; /* use this for all characters instead of the real ones */ | ||
214 | int baseDir; /* set to +1 for LTR, -1 for RTL */ | 215 | int baseDir; /* set to +1 for LTR, -1 for RTL */ |
215 | iInt2 hitPoint; /* sets hitChar_out */ | 216 | iInt2 hitPoint; /* sets hitChar_out */ |
216 | const char *hitChar; /* sets hitAdvance_out */ | 217 | const char *hitChar; /* sets hitAdvance_out */ |