diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-24 06:48:54 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-24 06:48:54 +0300 |
commit | e0c9784b3d595bdc3d80f0d9f10f9588dfd11d67 (patch) | |
tree | 283b35a28f9ec3f4e7c430e231d2e49da572c8d7 /src/ui | |
parent | 3391e595259909a557d6d2d302f9b7a9d680c97a (diff) |
Cleanup
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/inputwidget.c | 341 |
1 files changed, 23 insertions, 318 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 525e2a33..93dbfa9d 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -196,19 +196,19 @@ struct Impl_InputWidget { | |||
196 | iWidget widget; | 196 | iWidget widget; |
197 | enum iInputMode mode; | 197 | enum iInputMode mode; |
198 | int inFlags; | 198 | int inFlags; |
199 | size_t maxLen; /* characters */ | 199 | size_t maxLen; /* characters */ |
200 | iArray lines; /* iInputLine[] */ | 200 | iArray lines; /* iInputLine[] */ |
201 | iString oldText; /* for restoring if edits cancelled */ | 201 | iString oldText; /* for restoring if edits cancelled */ |
202 | int lastUpdateWidth; | 202 | int lastUpdateWidth; |
203 | iString srcHint; | 203 | iString srcHint; |
204 | iString hint; | 204 | iString hint; |
205 | int leftPadding; | 205 | int leftPadding; |
206 | int rightPadding; | 206 | int rightPadding; |
207 | iInt2 cursor; /* cursor position: x = byte offset, y = line index */ | 207 | iInt2 cursor; /* cursor position: x = byte offset, y = line index */ |
208 | iInt2 prevCursor; /* previous cursor position */ | 208 | iInt2 prevCursor; /* previous cursor position */ |
209 | iRangei visWrapLines; /* which wrap lines are current visible */ | 209 | iRangei visWrapLines; /* which wrap lines are current visible */ |
210 | int minWrapLines, maxWrapLines; /* min/max number of visible lines allowed */ | 210 | int minWrapLines, maxWrapLines; /* min/max number of visible lines allowed */ |
211 | iRanges mark; | 211 | iRanges mark; /* TODO: would likely simplify things to use two Int2's for marking; no conversions needed */ |
212 | iRanges initialMark; | 212 | iRanges initialMark; |
213 | iArray undoStack; | 213 | iArray undoStack; |
214 | int font; | 214 | int font; |
@@ -325,34 +325,6 @@ static iRect contentBounds_InputWidget_(const iInputWidget *d) { | |||
325 | return bounds; | 325 | return bounds; |
326 | } | 326 | } |
327 | 327 | ||
328 | #if 0 | ||
329 | static void updateCursorLine_InputWidget_(iInputWidget *d) { | ||
330 | iWidget *w = as_Widget(d); | ||
331 | d->cursorLine = 0; | ||
332 | iConstForEach(Array, i, &d->lines) { | ||
333 | const iInputLine *line = i.value; | ||
334 | if (line->offset > d->cursor) { | ||
335 | break; | ||
336 | } | ||
337 | d->cursorLine = index_ArrayConstIterator(&i); | ||
338 | } | ||
339 | /* May need to scroll to keep the cursor visible. */ | ||
340 | iWidget *flow = findOverflowScrollable_Widget(w); | ||
341 | if (flow) { | ||
342 | const iRect rootRect = { rect_Root(w->root).pos, visibleSize_Root(w->root) }; | ||
343 | int yCursor = contentBounds_InputWidget_(d).pos.y + | ||
344 | lineHeight_Text(d->font) * (int) d->cursorLine; | ||
345 | const int margin = lineHeight_Text(d->font) * 3; | ||
346 | if (yCursor < top_Rect(rootRect) + margin) { | ||
347 | scrollOverflow_Widget(flow, top_Rect(rootRect) + margin - yCursor); | ||
348 | } | ||
349 | else if (yCursor > bottom_Rect(rootRect) - margin * 3 / 2) { | ||
350 | scrollOverflow_Widget(flow, bottom_Rect(rootRect) - margin * 3 / 2 - yCursor); | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | iLocalDef iBool isLastLine_InputWidget_(const iInputWidget *d, const iInputLine *line) { | 328 | iLocalDef iBool isLastLine_InputWidget_(const iInputWidget *d, const iInputLine *line) { |
357 | return (const void *) line == constBack_Array(&d->lines); | 329 | return (const void *) line == constBack_Array(&d->lines); |
358 | } | 330 | } |
@@ -441,8 +413,8 @@ static int visLineOffsetY_InputWidget_(const iInputWidget *d) { | |||
441 | return (line->wrapLines.start - d->visWrapLines.start) * lineHeight_Text(d->font); | 413 | return (line->wrapLines.start - d->visWrapLines.start) * lineHeight_Text(d->font); |
442 | } | 414 | } |
443 | 415 | ||
444 | static const iChar sensitiveChar_ = 0x25cf; /* black circle */ | 416 | static const iChar sensitiveChar_ = 0x25cf; /* black circle */ |
445 | static const char *sensitive_ = "\u25cf"; /* black circle */ | 417 | static const char *sensitive_ = "\u25cf"; |
446 | 418 | ||
447 | static iWrapText wrap_InputWidget_(const iInputWidget *d, int y) { | 419 | static iWrapText wrap_InputWidget_(const iInputWidget *d, int y) { |
448 | return (iWrapText){ | 420 | return (iWrapText){ |
@@ -472,9 +444,6 @@ static void updateVisible_InputWidget_(iInputWidget *d) { | |||
472 | const iInputLine *curLine = constAt_Array(&d->lines, d->cursor.y); | 444 | const iInputLine *curLine = constAt_Array(&d->lines, d->cursor.y); |
473 | const int cursorY = curLine->wrapLines.start + | 445 | const int cursorY = curLine->wrapLines.start + |
474 | relativeCursorCoord_InputWidget_(d).y / lineHeight_Text(d->font); | 446 | relativeCursorCoord_InputWidget_(d).y / lineHeight_Text(d->font); |
475 | // measureRange_Text(d->font, rangeSize_String(&curLine->text, d->cursor.x)) | ||
476 | // .advance.y / lineHeight_Text(d->font); | ||
477 | //int scrollY = d->visLineOffsetY / lineHeight_Text(d->font); | ||
478 | /* Scroll to cursor. */ | 447 | /* Scroll to cursor. */ |
479 | int delta = 0; | 448 | int delta = 0; |
480 | if (d->visWrapLines.end < cursorY + 1) { | 449 | if (d->visWrapLines.end < cursorY + 1) { |
@@ -486,36 +455,10 @@ static void updateVisible_InputWidget_(iInputWidget *d) { | |||
486 | d->visWrapLines.start += delta; | 455 | d->visWrapLines.start += delta; |
487 | d->visWrapLines.end += delta; | 456 | d->visWrapLines.end += delta; |
488 | iAssert(contains_Range(&d->visWrapLines, cursorY)); | 457 | iAssert(contains_Range(&d->visWrapLines, cursorY)); |
489 | // iAssert(d->visWrapLines.start >= 0); | ||
490 | // iAssert(d->visWrapLines.end <= totalWraps); | ||
491 | |||
492 | // d->visLineOffsetY = scrollY * lineHeight_Text(d->font); | ||
493 | #if 0 | ||
494 | // const int numContentLines = numContentLines_InputWidget_(d); | ||
495 | /* Expand or shrink the number of visible lines depending on how much content is available. */ | ||
496 | //d->visLines.end = d->visLines.start + iClamp(numContentLines, d->minVisLines, d->maxVisLines); | ||
497 | const int maxVisLines = iMin(d->maxVisLines, size_Array(&d->lines)); | ||
498 | d->visLines.end = d->visLines.start; | ||
499 | |||
500 | if (d->visLines.end > numContentLines) { | ||
501 | const int avail = d->visLines.start; | ||
502 | int offset = iMin(avail, d->visLines.end - numContentLines); | ||
503 | d->visLines.start -= offset; | ||
504 | d->visLines.end -= offset; | ||
505 | } | ||
506 | /* Keep the cursor visible. */ | ||
507 | if (d->cursor.y < d->visLines.start) { | ||
508 | scrollVisLines_InputWidget_(d, d->cursor.y - d->visLines.start); | ||
509 | } | ||
510 | if (d->cursor.y > d->visLines.end - 1) { | ||
511 | scrollVisLines_InputWidget_(d, d->cursor.y - d->visLines.end - 1); | ||
512 | } | ||
513 | #endif | ||
514 | } | 458 | } |
515 | 459 | ||
516 | static void showCursor_InputWidget_(iInputWidget *d) { | 460 | static void showCursor_InputWidget_(iInputWidget *d) { |
517 | d->cursorVis = 2; | 461 | d->cursorVis = 2; |
518 | // updateCursorLine_InputWidget_(d); | ||
519 | updateVisible_InputWidget_(d); | 462 | updateVisible_InputWidget_(d); |
520 | } | 463 | } |
521 | 464 | ||
@@ -542,7 +485,6 @@ static void updateSizeForFixedLength_InputWidget_(iInputWidget *d) { | |||
542 | } | 485 | } |
543 | 486 | ||
544 | static iString *text_InputWidget_(const iInputWidget *d) { | 487 | static iString *text_InputWidget_(const iInputWidget *d) { |
545 | //return newUnicodeN_String(constData_Array(&d->text), size_Array(&d->text)); | ||
546 | iString *text = new_String(); | 488 | iString *text = new_String(); |
547 | mergeLines_(&d->lines, text); | 489 | mergeLines_(&d->lines, text); |
548 | return text; | 490 | return text; |
@@ -558,99 +500,10 @@ static size_t length_InputWidget_(const iInputWidget *d) { | |||
558 | return len; | 500 | return len; |
559 | } | 501 | } |
560 | 502 | ||
561 | #if 0 | ||
562 | static iString *visText_InputWidget_(const iInputWidget *d) { | ||
563 | iString *text; | ||
564 | if (~d->inFlags & isSensitive_InputWidgetFlag) { | ||
565 | text = text_InputWidget_(d); | ||
566 | } | ||
567 | else { | ||
568 | text = new_String(); | ||
569 | // iAssert(d->length == length_InputWidget_(d)); | ||
570 | const size_t len = length_InputWidget_(d); | ||
571 | for (size_t i = 0; i < len; i++) { | ||
572 | appendCStr_String(text, sensitive_); | ||
573 | } | ||
574 | } | ||
575 | return text; | ||
576 | } | ||
577 | |||
578 | static void clearLines_InputWidget_(iInputWidget *d) { | ||
579 | iForEach(Array, i, &d->lines) { | ||
580 | deinit_InputLine(i.value); | ||
581 | } | ||
582 | clear_Array(&d->lines); | ||
583 | } | ||
584 | #endif | ||
585 | |||
586 | #if 0 | ||
587 | static void updateLines_InputWidget_(iInputWidget *d) { | ||
588 | d->lastUpdateWidth = d->widget.rect.size.x; | ||
589 | clearLines_InputWidget_(d); | ||
590 | if (d->maxLen) { | ||
591 | /* Everything on a single line. */ | ||
592 | iInputLine line; | ||
593 | init_InputLine(&line); | ||
594 | iString *u8 = visText_InputWidget_(d); | ||
595 | set_String(&line.text, u8); | ||
596 | line.len = length_String(u8); | ||
597 | delete_String(u8); | ||
598 | pushBack_Array(&d->lines, &line); | ||
599 | updateCursorLine_InputWidget_(d); | ||
600 | return; | ||
601 | } | ||
602 | /* Word-wrapped lines. */ | ||
603 | iString *u8 = visText_InputWidget_(d); | ||
604 | size_t charPos = 0; | ||
605 | iRangecc content = range_String(u8); | ||
606 | const int wrapWidth = contentBounds_InputWidget_(d).size.x; | ||
607 | while (wrapWidth > 0 && content.end != content.start) { | ||
608 | const char *endPos; | ||
609 | if (d->inFlags & isUrl_InputWidgetFlag) { | ||
610 | tryAdvanceNoWrap_Text(d->font, content, wrapWidth, &endPos); | ||
611 | } | ||
612 | else { | ||
613 | tryAdvance_Text(d->font, content, wrapWidth, &endPos); | ||
614 | } | ||
615 | const iRangecc part = (iRangecc){ content.start, endPos }; | ||
616 | iInputLine line; | ||
617 | init_InputLine(&line); | ||
618 | setRange_String(&line.text, part); | ||
619 | line.offset = charPos; | ||
620 | line.len = length_String(&line.text); | ||
621 | pushBack_Array(&d->lines, &line); | ||
622 | charPos += line.len; | ||
623 | content.start = endPos; | ||
624 | } | ||
625 | if (isEmpty_Array(&d->lines) || endsWith_String(u8, "\n")) { | ||
626 | /* Always at least one empty line. */ | ||
627 | iInputLine line; | ||
628 | init_InputLine(&line); | ||
629 | line.offset = charPos; | ||
630 | pushBack_Array(&d->lines, &line); | ||
631 | } | ||
632 | else { | ||
633 | iAssert(charPos == length_String(u8)); | ||
634 | } | ||
635 | delete_String(u8); | ||
636 | updateCursorLine_InputWidget_(d); | ||
637 | } | ||
638 | #endif | ||
639 | |||
640 | static int contentHeight_InputWidget_(const iInputWidget *d) { | 503 | static int contentHeight_InputWidget_(const iInputWidget *d) { |
641 | return size_Range(&d->visWrapLines) * lineHeight_Text(d->font); | 504 | return size_Range(&d->visWrapLines) * lineHeight_Text(d->font); |
642 | } | 505 | } |
643 | 506 | ||
644 | #if 0 | ||
645 | static int contentHeight_InputWidget_(const iInputWidget *d, iBool forLayout) { | ||
646 | int numLines = d->curVisLines; | ||
647 | if (forLayout) { | ||
648 | numLines = iMin(numLines, d->numLayoutLines); | ||
649 | } | ||
650 | return numLines * lineHeight_Text(d->font); | ||
651 | } | ||
652 | #endif | ||
653 | |||
654 | static void updateMetrics_InputWidget_(iInputWidget *d) { | 507 | static void updateMetrics_InputWidget_(iInputWidget *d) { |
655 | iWidget *w = as_Widget(d); | 508 | iWidget *w = as_Widget(d); |
656 | updateSizeForFixedLength_InputWidget_(d); | 509 | updateSizeForFixedLength_InputWidget_(d); |
@@ -701,7 +554,6 @@ static void updateAllLinesAndResizeHeight_InputWidget_(iInputWidget *d) { | |||
701 | updateLineRangesStartingFrom_InputWidget_(d, 0); | 554 | updateLineRangesStartingFrom_InputWidget_(d, 0); |
702 | updateVisible_InputWidget_(d); | 555 | updateVisible_InputWidget_(d); |
703 | if (oldWraps != numWrapLines_InputWidget_(d)) { | 556 | if (oldWraps != numWrapLines_InputWidget_(d)) { |
704 | // d->click.minHeight = contentHeight_InputWidget_(d, iFalse); | ||
705 | updateMetrics_InputWidget_(d); | 557 | updateMetrics_InputWidget_(d); |
706 | } | 558 | } |
707 | } | 559 | } |
@@ -716,7 +568,6 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
716 | setFlags_Widget(w, extraPadding_WidgetFlag, iTrue); | 568 | setFlags_Widget(w, extraPadding_WidgetFlag, iTrue); |
717 | #endif | 569 | #endif |
718 | init_Array(&d->lines, sizeof(iInputLine)); | 570 | init_Array(&d->lines, sizeof(iInputLine)); |
719 | //init_Array(&d->oldText, sizeof(iChar)); | ||
720 | init_String(&d->oldText); | 571 | init_String(&d->oldText); |
721 | init_Array(&d->lines, sizeof(iInputLine)); | 572 | init_Array(&d->lines, sizeof(iInputLine)); |
722 | init_String(&d->srcHint); | 573 | init_String(&d->srcHint); |
@@ -727,10 +578,7 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
727 | d->rightPadding = 0; | 578 | d->rightPadding = 0; |
728 | d->cursor = zero_I2(); | 579 | d->cursor = zero_I2(); |
729 | d->prevCursor = zero_I2(); | 580 | d->prevCursor = zero_I2(); |
730 | //d->lastCursor = 0; | ||
731 | //d->cursorLine = 0; | ||
732 | d->lastUpdateWidth = 0; | 581 | d->lastUpdateWidth = 0; |
733 | //d->verticalMoveX = -1; /* TODO: Use this. */ | ||
734 | d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag; | 582 | d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag; |
735 | if (deviceType_App() != desktop_AppDeviceType) { | 583 | if (deviceType_App() != desktop_AppDeviceType) { |
736 | d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag; | 584 | d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag; |
@@ -739,11 +587,9 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
739 | setMaxLen_InputWidget(d, maxLen); | 587 | setMaxLen_InputWidget(d, maxLen); |
740 | d->visWrapLines.start = 0; | 588 | d->visWrapLines.start = 0; |
741 | d->visWrapLines.end = 1; | 589 | d->visWrapLines.end = 1; |
742 | // d->visLineOffsetY = 0; | ||
743 | d->maxWrapLines = maxLen > 0 ? 1 : 20; /* TODO: Choose maximum dynamically? */ | 590 | d->maxWrapLines = maxLen > 0 ? 1 : 20; /* TODO: Choose maximum dynamically? */ |
744 | d->minWrapLines = 1; | 591 | d->minWrapLines = 1; |
745 | splitToLines_(&iStringLiteral(""), &d->lines); | 592 | splitToLines_(&iStringLiteral(""), &d->lines); |
746 | //d->maxLayoutLines = iInvalidSize; | ||
747 | setFlags_Widget(w, fixedHeight_WidgetFlag, iTrue); /* resizes its own height */ | 593 | setFlags_Widget(w, fixedHeight_WidgetFlag, iTrue); /* resizes its own height */ |
748 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | 594 | init_Click(&d->click, d, SDL_BUTTON_LEFT); |
749 | d->timer = 0; | 595 | d->timer = 0; |
@@ -751,7 +597,6 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
751 | d->buffered = NULL; | 597 | d->buffered = NULL; |
752 | d->backupPath = NULL; | 598 | d->backupPath = NULL; |
753 | d->backupTimer = 0; | 599 | d->backupTimer = 0; |
754 | //updateLines_InputWidget_(d); | ||
755 | updateMetrics_InputWidget_(d); | 600 | updateMetrics_InputWidget_(d); |
756 | } | 601 | } |
757 | 602 | ||
@@ -970,12 +815,8 @@ void setText_InputWidget(iInputWidget *d, const iString *text) { | |||
970 | #endif | 815 | #endif |
971 | } | 816 | } |
972 | clearUndo_InputWidget_(d); | 817 | clearUndo_InputWidget_(d); |
973 | //clear_Array(&d->text); | ||
974 | iString *nfcText = collect_String(copy_String(text)); | 818 | iString *nfcText = collect_String(copy_String(text)); |
975 | normalize_String(nfcText); | 819 | normalize_String(nfcText); |
976 | // iConstForEach(String, i, nfcText) { | ||
977 | // pushBack_Array(&d->text, &i.value); | ||
978 | // } | ||
979 | splitToLines_(nfcText, &d->lines); | 820 | splitToLines_(nfcText, &d->lines); |
980 | iAssert(!isEmpty_Array(&d->lines)); | 821 | iAssert(!isEmpty_Array(&d->lines)); |
981 | iForEach(Array, i, &d->lines) { | 822 | iForEach(Array, i, &d->lines) { |
@@ -993,8 +834,6 @@ void setText_InputWidget(iInputWidget *d, const iString *text) { | |||
993 | if (!isFocused_Widget(d)) { | 834 | if (!isFocused_Widget(d)) { |
994 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; | 835 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; |
995 | } | 836 | } |
996 | // updateLinesAndResize_InputWidget_(d); | ||
997 | // updateAllLinesAndResizeHeight_InputWidget_(d); | ||
998 | updateVisible_InputWidget_(d); | 837 | updateVisible_InputWidget_(d); |
999 | refresh_Widget(as_Widget(d)); | 838 | refresh_Widget(as_Widget(d)); |
1000 | } | 839 | } |
@@ -1018,7 +857,6 @@ static uint32_t cursorTimer_(uint32_t interval, void *w) { | |||
1018 | } | 857 | } |
1019 | 858 | ||
1020 | static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { | 859 | static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { |
1021 | /* TODO: Lazy linear position updates. */ | ||
1022 | if (pos.y < 0) { | 860 | if (pos.y < 0) { |
1023 | return 0; | 861 | return 0; |
1024 | } | 862 | } |
@@ -1031,7 +869,6 @@ static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { | |||
1031 | } | 869 | } |
1032 | 870 | ||
1033 | static iInt2 indexToCursor_InputWidget_(const iInputWidget *d, size_t index) { | 871 | static iInt2 indexToCursor_InputWidget_(const iInputWidget *d, size_t index) { |
1034 | /* TODO: Lazy linear position updates. */ | ||
1035 | /* TODO: The lines are sorted; this could use a binary search. */ | 872 | /* TODO: The lines are sorted; this could use a binary search. */ |
1036 | iConstForEach(Array, i, &d->lines) { | 873 | iConstForEach(Array, i, &d->lines) { |
1037 | const iInputLine *line = i.value; | 874 | const iInputLine *line = i.value; |
@@ -1059,7 +896,6 @@ void begin_InputWidget(iInputWidget *d) { | |||
1059 | } | 896 | } |
1060 | invalidateBuffered_InputWidget_(d); | 897 | invalidateBuffered_InputWidget_(d); |
1061 | setFlags_Widget(w, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); | 898 | setFlags_Widget(w, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); |
1062 | //setCopy_Array(&d->oldText, &d->text); | ||
1063 | mergeLines_(&d->lines, &d->oldText); | 899 | mergeLines_(&d->lines, &d->oldText); |
1064 | if (d->mode == overwrite_InputMode) { | 900 | if (d->mode == overwrite_InputMode) { |
1065 | d->cursor = zero_I2(); | 901 | d->cursor = zero_I2(); |
@@ -1068,15 +904,8 @@ void begin_InputWidget(iInputWidget *d) { | |||
1068 | d->cursor.y = iMin(d->cursor.y, size_Array(&d->lines) - 1); | 904 | d->cursor.y = iMin(d->cursor.y, size_Array(&d->lines) - 1); |
1069 | d->cursor.x = iMin(d->cursor.x, cursorLine_InputWidget_(d)->range.end); | 905 | d->cursor.x = iMin(d->cursor.x, cursorLine_InputWidget_(d)->range.end); |
1070 | } | 906 | } |
1071 | // updateCursorLine_InputWidget_(d); | ||
1072 | SDL_StartTextInput(); | 907 | SDL_StartTextInput(); |
1073 | setFlags_Widget(w, selected_WidgetFlag, iTrue); | 908 | setFlags_Widget(w, selected_WidgetFlag, iTrue); |
1074 | #if 0 | ||
1075 | if (d->maxLayoutLines != iInvalidSize) { | ||
1076 | /* This will extend beyond the arranged region. */ | ||
1077 | setFlags_Widget(w, keepOnTop_WidgetFlag, iTrue); | ||
1078 | } | ||
1079 | #endif | ||
1080 | showCursor_InputWidget_(d); | 909 | showCursor_InputWidget_(d); |
1081 | refresh_Widget(w); | 910 | refresh_Widget(w); |
1082 | d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); | 911 | d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); |
@@ -1099,7 +928,6 @@ void end_InputWidget(iInputWidget *d, iBool accept) { | |||
1099 | } | 928 | } |
1100 | enableEditorKeysInMenus_(iTrue); | 929 | enableEditorKeysInMenus_(iTrue); |
1101 | if (!accept) { | 930 | if (!accept) { |
1102 | //setCopy_Array(&d->text, &d->oldText); | ||
1103 | /* Overwrite the edited lines. */ | 931 | /* Overwrite the edited lines. */ |
1104 | splitToLines_(&d->oldText, &d->lines); | 932 | splitToLines_(&d->oldText, &d->lines); |
1105 | } | 933 | } |
@@ -1110,7 +938,6 @@ void end_InputWidget(iInputWidget *d, iBool accept) { | |||
1110 | setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse); | 938 | setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse); |
1111 | const char *id = cstr_String(id_Widget(as_Widget(d))); | 939 | const char *id = cstr_String(id_Widget(as_Widget(d))); |
1112 | if (!*id) id = "_"; | 940 | if (!*id) id = "_"; |
1113 | // updateLinesAndResize_InputWidget_(d); | ||
1114 | refresh_Widget(w); | 941 | refresh_Widget(w); |
1115 | postCommand_Widget(w, | 942 | postCommand_Widget(w, |
1116 | "input.ended id:%s enter:%d arg:%d", | 943 | "input.ended id:%s enter:%d arg:%d", |
@@ -1130,7 +957,6 @@ static void textOfLinesWasChanged_InputWidget_(iInputWidget *d, iRangei lineRang | |||
1130 | } | 957 | } |
1131 | 958 | ||
1132 | static void insertRange_InputWidget_(iInputWidget *d, iRangecc range) { | 959 | static void insertRange_InputWidget_(iInputWidget *d, iRangecc range) { |
1133 | iWidget *w = as_Widget(d); | ||
1134 | iRangecc nextRange = { range.end, range.end }; | 960 | iRangecc nextRange = { range.end, range.end }; |
1135 | const int firstModified = d->cursor.y; | 961 | const int firstModified = d->cursor.y; |
1136 | for (;; range = nextRange) { | 962 | for (;; range = nextRange) { |
@@ -1174,21 +1000,6 @@ static void insertRange_InputWidget_(iInputWidget *d, iRangecc range) { | |||
1174 | } | 1000 | } |
1175 | } | 1001 | } |
1176 | textOfLinesWasChanged_InputWidget_(d, (iRangei){ firstModified, d->cursor.y + 1 }); | 1002 | textOfLinesWasChanged_InputWidget_(d, (iRangei){ firstModified, d->cursor.y + 1 }); |
1177 | #if 0 | ||
1178 | else if (d->maxLen == 0 || d->cursor < d->maxLen) { | ||
1179 | if (d->cursor >= size_Array(&d->text)) { | ||
1180 | resize_Array(&d->text, d->cursor + 1); | ||
1181 | } | ||
1182 | set_Array(&d->text, d->cursor++, &chr); | ||
1183 | if (d->maxLen > 1 && d->cursor == d->maxLen) { | ||
1184 | iWidget *nextFocus = findFocusable_Widget(w, forward_WidgetFocusDir); | ||
1185 | setFocus_Widget(nextFocus == w ? NULL : nextFocus); | ||
1186 | } | ||
1187 | else if (d->maxLen == 1) { | ||
1188 | d->cursor = 0; | ||
1189 | } | ||
1190 | } | ||
1191 | #endif | ||
1192 | showCursor_InputWidget_(d); | 1003 | showCursor_InputWidget_(d); |
1193 | refresh_Widget(as_Widget(d)); | 1004 | refresh_Widget(as_Widget(d)); |
1194 | } | 1005 | } |
@@ -1223,52 +1034,11 @@ void setCursor_InputWidget(iInputWidget *d, iInt2 pos) { | |||
1223 | showCursor_InputWidget_(d); | 1034 | showCursor_InputWidget_(d); |
1224 | } | 1035 | } |
1225 | 1036 | ||
1226 | #if 0 | ||
1227 | static size_t indexForRelativeX_InputWidget_(const iInputWidget *d, int x, const iInputLine *line) { | ||
1228 | size_t index = line->range.start; | ||
1229 | if (x <= 0) { | ||
1230 | return index; | ||
1231 | } | ||
1232 | const char *endPos; | ||
1233 | tryAdvanceNoWrap_Text(d->font, range_String(&line->text), x, &endPos); | ||
1234 | if (endPos == constEnd_String(&line->text)) { | ||
1235 | index = line->range.end - 1; | ||
1236 | } | ||
1237 | else { | ||
1238 | #if 0 | ||
1239 | /* Need to know the actual character index. */ | ||
1240 | /* TODO: tryAdvance could tell us this directly with an extra return value */ | ||
1241 | iConstForEach(String, i, &line->text) { | ||
1242 | if (i.pos >= endPos) break; | ||
1243 | index++; | ||
1244 | } | ||
1245 | #endif | ||
1246 | index = line->range.start + (endPos - constBegin_String(&line->text)); | ||
1247 | } | ||
1248 | #if 0 | ||
1249 | if (!isLastLine_InputWidget_(d, line) && index == line->offset + line->len) { | ||
1250 | index = iMax(index - 1, line->offset); | ||
1251 | } | ||
1252 | #endif | ||
1253 | return iMax(index, line->range.start); | ||
1254 | } | ||
1255 | #endif | ||
1256 | |||
1257 | static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) { | 1037 | static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) { |
1258 | const iInputLine *line = cursorLine_InputWidget_(d); | 1038 | const iInputLine *line = cursorLine_InputWidget_(d); |
1259 | iRangecc text = range_String(&line->text); | 1039 | iInt2 relCoord = relativeCursorCoord_InputWidget_(d); |
1260 | // iWrapText wrapText = { | 1040 | int relLine = relCoord.y / lineHeight_Text(d->font); |
1261 | // .text = rangeSize_String(&line->text, d->cursor.x), | ||
1262 | // .maxWidth = width_Rect(contentBounds_InputWidget_(d)), | ||
1263 | // .mode = (d->inFlags & isUrl_InputWidgetFlag ? anyCharacter_WrapTextMode | ||
1264 | // : word_WrapTextMode), | ||
1265 | // }; | ||
1266 | //iInt2 relCoord = measure_WrapText(&wrapText, d->font).advance; | ||
1267 | iInt2 relCoord = relativeCursorCoord_InputWidget_(d); | ||
1268 | const int cursorWidth = measureN_Text(d->font, charPos_InputWidget_(d, d->cursor), 1).advance.x; | ||
1269 | int relLine = relCoord.y / lineHeight_Text(d->font); | ||
1270 | if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) { | 1041 | if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) { |
1271 | /* We can just change the cursor X value, but we'll have to check where the cursor lands. */ | ||
1272 | relCoord.y += dir * lineHeight_Text(d->font); | 1042 | relCoord.y += dir * lineHeight_Text(d->font); |
1273 | } | 1043 | } |
1274 | else if (dir < 0 && d->cursor.y > 0) { | 1044 | else if (dir < 0 && d->cursor.y > 0) { |
@@ -1278,7 +1048,6 @@ static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) | |||
1278 | } | 1048 | } |
1279 | else if (dir > 0 && d->cursor.y < size_Array(&d->lines) - 1) { | 1049 | else if (dir > 0 && d->cursor.y < size_Array(&d->lines) - 1) { |
1280 | d->cursor.y++; | 1050 | d->cursor.y++; |
1281 | line = cursorLine_InputWidget_(d); | ||
1282 | relCoord.y = 0; | 1051 | relCoord.y = 0; |
1283 | } | 1052 | } |
1284 | else if (dir == 0 && horiz != 0) { | 1053 | else if (dir == 0 && horiz != 0) { |
@@ -1296,15 +1065,13 @@ static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) | |||
1296 | else { | 1065 | else { |
1297 | d->cursor.x = endX_InputWidget_(d, d->cursor.y); | 1066 | d->cursor.x = endX_InputWidget_(d, d->cursor.y); |
1298 | } | 1067 | } |
1299 | /* | 1068 | if (wt.hitGlyphNormX_out > 0.5f && d->cursor.x < endX_InputWidget_(d, d->cursor.y)) { |
1300 | if (wrapText.hitGlyphNormX_out > 0.5f && d->cursor.x < endX_InputWidget_(d, d->cursor.y)) { | ||
1301 | iChar ch; | 1069 | iChar ch; |
1302 | int n = decodeBytes_MultibyteChar(wrapText.text.start + d->cursor.x, wrapText.text.end, &ch); | 1070 | int n = decodeBytes_MultibyteChar(wt.text.start + d->cursor.x, wt.text.end, &ch); |
1303 | if (n > 0) { | 1071 | if (ch != '\n' && n > 0) { |
1304 | d->cursor.x += n; | 1072 | d->cursor.x += n; |
1305 | } | 1073 | } |
1306 | }*/ | 1074 | } |
1307 | //showCursor_InputWidget_(d); | ||
1308 | setCursor_InputWidget(d, d->cursor); /* mark, show */ | 1075 | setCursor_InputWidget(d, d->cursor); /* mark, show */ |
1309 | return iTrue; | 1076 | return iTrue; |
1310 | } | 1077 | } |
@@ -1342,7 +1109,6 @@ static void contentsWereChanged_InputWidget_(iInputWidget *d) { | |||
1342 | if (d->validator) { | 1109 | if (d->validator) { |
1343 | d->validator(d, d->validatorContext); /* this may change the contents */ | 1110 | d->validator(d, d->validatorContext); /* this may change the contents */ |
1344 | } | 1111 | } |
1345 | // updateLinesAndResize_InputWidget_(d); | ||
1346 | if (d->inFlags & notifyEdits_InputWidgetFlag) { | 1112 | if (d->inFlags & notifyEdits_InputWidgetFlag) { |
1347 | postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d)))); | 1113 | postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d)))); |
1348 | } | 1114 | } |
@@ -1512,8 +1278,6 @@ static iInt2 coordCursor_InputWidget_(const iInputWidget *d, iInt2 coord) { | |||
1512 | static iBool copy_InputWidget_(iInputWidget *d, iBool doCut) { | 1278 | static iBool copy_InputWidget_(iInputWidget *d, iBool doCut) { |
1513 | if (!isEmpty_Range(&d->mark)) { | 1279 | if (!isEmpty_Range(&d->mark)) { |
1514 | const iRanges m = mark_InputWidget_(d); | 1280 | const iRanges m = mark_InputWidget_(d); |
1515 | // iString *str = collect_String(newUnicodeN_String(constAt_Array(&d->text, m.start), | ||
1516 | // size_Range(&m))); | ||
1517 | iString *str = collectNew_String(); | 1281 | iString *str = collectNew_String(); |
1518 | mergeLinesRange_(&d->lines, m, str); | 1282 | mergeLinesRange_(&d->lines, m, str); |
1519 | SDL_SetClipboardText( | 1283 | SDL_SetClipboardText( |
@@ -1544,22 +1308,11 @@ static void paste_InputWidget_(iInputWidget *d) { | |||
1544 | } | 1308 | } |
1545 | } | 1309 | } |
1546 | SDL_free(text); | 1310 | SDL_free(text); |
1547 | //iConstForEach(String, i, paste) { insertChar_InputWidget_(d, i.value); } | ||
1548 | insertRange_InputWidget_(d, range_String(paste)); | 1311 | insertRange_InputWidget_(d, range_String(paste)); |
1549 | contentsWereChanged_InputWidget_(d); | 1312 | contentsWereChanged_InputWidget_(d); |
1550 | } | 1313 | } |
1551 | } | 1314 | } |
1552 | 1315 | ||
1553 | #if 0 | ||
1554 | static iRanges lineRange_InputWidget_(const iInputWidget *d) { | ||
1555 | if (isEmpty_Array(&d->lines)) { | ||
1556 | return (iRanges){ 0, 0 }; | ||
1557 | } | ||
1558 | const iInputLine *line = line_InputWidget_(d, d->cursorLine); | ||
1559 | return (iRanges){ line->offset, line->offset + line->len }; | ||
1560 | } | ||
1561 | #endif | ||
1562 | |||
1563 | static void extendRange_InputWidget_(iInputWidget *d, size_t *index, int dir) { | 1316 | static void extendRange_InputWidget_(iInputWidget *d, size_t *index, int dir) { |
1564 | iInt2 pos = indexToCursor_InputWidget_(d, *index); | 1317 | iInt2 pos = indexToCursor_InputWidget_(d, *index); |
1565 | if (dir < 0) { | 1318 | if (dir < 0) { |
@@ -1617,7 +1370,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1617 | setText_InputWidget(d, text_InputWidget(d)); | 1370 | setText_InputWidget(d, text_InputWidget(d)); |
1618 | } | 1371 | } |
1619 | #endif | 1372 | #endif |
1620 | // updateLinesAndResize_InputWidget_(d); | ||
1621 | updateAllLinesAndResizeHeight_InputWidget_(d); | 1373 | updateAllLinesAndResizeHeight_InputWidget_(d); |
1622 | d->lastUpdateWidth = w->rect.size.x; | 1374 | d->lastUpdateWidth = w->rect.size.x; |
1623 | } | 1375 | } |
@@ -1880,9 +1632,8 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1880 | deleteMarked_InputWidget_(d); | 1632 | deleteMarked_InputWidget_(d); |
1881 | contentsWereChanged_InputWidget_(d); | 1633 | contentsWereChanged_InputWidget_(d); |
1882 | } | 1634 | } |
1883 | else if (!isEqual_I2(d->cursor, curMax)) {//} < size_Array(&d->text)) { | 1635 | else if (!isEqual_I2(d->cursor, curMax)) { |
1884 | pushUndo_InputWidget_(d); | 1636 | pushUndo_InputWidget_(d); |
1885 | //remove_Array(&d->text, d->cursor); | ||
1886 | deleteIndexRange_InputWidget_(d, (iRanges){ | 1637 | deleteIndexRange_InputWidget_(d, (iRanges){ |
1887 | cursorToIndex_InputWidget_(d, d->cursor), | 1638 | cursorToIndex_InputWidget_(d, d->cursor), |
1888 | cursorToIndex_InputWidget_(d, movedCursor_InputWidget_(d, d->cursor, +1, 0)) | 1639 | cursorToIndex_InputWidget_(d, movedCursor_InputWidget_(d, d->cursor, +1, 0)) |
@@ -1948,7 +1699,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1948 | case SDLK_RIGHT: { | 1699 | case SDLK_RIGHT: { |
1949 | const int dir = (key == SDLK_LEFT ? -1 : +1); | 1700 | const int dir = (key == SDLK_LEFT ? -1 : +1); |
1950 | if (mods & byLine_KeyModifier) { | 1701 | if (mods & byLine_KeyModifier) { |
1951 | //setCursor_InputWidget(d, dir < 0 ? lineFirst : lineLast); | ||
1952 | moveCursorByLine_InputWidget_(d, 0, dir); | 1702 | moveCursorByLine_InputWidget_(d, 0, dir); |
1953 | } | 1703 | } |
1954 | else if (mods & byWord_KeyModifier) { | 1704 | else if (mods & byWord_KeyModifier) { |
@@ -1995,7 +1745,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1995 | else if (ev->type == SDL_TEXTINPUT && isFocused_Widget(w)) { | 1745 | else if (ev->type == SDL_TEXTINPUT && isFocused_Widget(w)) { |
1996 | pushUndo_InputWidget_(d); | 1746 | pushUndo_InputWidget_(d); |
1997 | deleteMarked_InputWidget_(d); | 1747 | deleteMarked_InputWidget_(d); |
1998 | const int firstInsertLine = d->cursor.y; | ||
1999 | insertRange_InputWidget_(d, range_CStr(ev->text.text)); | 1748 | insertRange_InputWidget_(d, range_CStr(ev->text.text)); |
2000 | contentsWereChanged_InputWidget_(d); | 1749 | contentsWereChanged_InputWidget_(d); |
2001 | return iTrue; | 1750 | return iTrue; |
@@ -2006,12 +1755,12 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
2006 | iDeclareType(MarkPainter) | 1755 | iDeclareType(MarkPainter) |
2007 | 1756 | ||
2008 | struct Impl_MarkPainter { | 1757 | struct Impl_MarkPainter { |
2009 | iPaint *paint; | 1758 | iPaint * paint; |
2010 | const iInputWidget *d; | 1759 | const iInputWidget *d; |
2011 | iRect contentBounds; | 1760 | iRect contentBounds; |
2012 | const iInputLine *line; | 1761 | const iInputLine * line; |
2013 | iInt2 pos; | 1762 | iInt2 pos; |
2014 | iRanges mark; | 1763 | iRanges mark; |
2015 | }; | 1764 | }; |
2016 | 1765 | ||
2017 | static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int origin, int advance, | 1766 | static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int origin, int advance, |
@@ -2034,7 +1783,7 @@ static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int or | |||
2034 | iRect rect = { addX_I2(mp->pos, origin), init_I2(advance, lineHeight_Text(mp->d->font)) }; | 1783 | iRect rect = { addX_I2(mp->pos, origin), init_I2(advance, lineHeight_Text(mp->d->font)) }; |
2035 | if (mark.end < lineRange.end) { | 1784 | if (mark.end < lineRange.end) { |
2036 | /* Calculate where the mark ends. */ | 1785 | /* Calculate where the mark ends. */ |
2037 | const iRangecc markedPrefix = { //cstr, cstr + mark.end - lineRange.start }; | 1786 | const iRangecc markedPrefix = { |
2038 | wrappedText.start, | 1787 | wrappedText.start, |
2039 | wrappedText.start + mark.end - lineRange.start | 1788 | wrappedText.start + mark.end - lineRange.start |
2040 | }; | 1789 | }; |
@@ -2042,7 +1791,7 @@ static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int or | |||
2042 | } | 1791 | } |
2043 | if (mark.start > lineRange.start) { | 1792 | if (mark.start > lineRange.start) { |
2044 | /* Calculate where the mark starts. */ | 1793 | /* Calculate where the mark starts. */ |
2045 | const iRangecc unmarkedPrefix = { //cstr, cstr + mark.start - lineRange.start | 1794 | const iRangecc unmarkedPrefix = { |
2046 | wrappedText.start, | 1795 | wrappedText.start, |
2047 | wrappedText.start + mark.start - lineRange.start | 1796 | wrappedText.start + mark.start - lineRange.start |
2048 | }; | 1797 | }; |
@@ -2118,34 +1867,6 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
2118 | } | 1867 | } |
2119 | wrapText.wrapFunc = NULL; | 1868 | wrapText.wrapFunc = NULL; |
2120 | wrapText.context = NULL; | 1869 | wrapText.context = NULL; |
2121 | #if 0 | ||
2122 | iConstForEach(Array, i, &d->lines) { | ||
2123 | const iInputLine *line = i.value; | ||
2124 | const iBool isLast = index_ArrayConstIterator(&i) == size_Array(&d->lines) - 1; | ||
2125 | const iInputLine *nextLine = isLast ? NULL : (line + 1); | ||
2126 | const iRanges lineRange = { line->offset, | ||
2127 | nextLine ? nextLine->offset : size_Array(&d->text) }; | ||
2128 | if (isFocused && !isEmpty_Range(&d->mark)) { | ||
2129 | /* Draw the selected range. */ | ||
2130 | const iRanges mark = mark_InputWidget_(d); | ||
2131 | if (mark.start < lineRange.end && mark.end > lineRange.start) { | ||
2132 | const int m1 = maxWidth_TextMetrics(measureN_Text(d->font, | ||
2133 | cstr_String(&line->text), | ||
2134 | iMax(lineRange.start, mark.start) - line->offset)); | ||
2135 | const int m2 = maxWidth_TextMetrics(measureN_Text(d->font, | ||
2136 | cstr_String(&line->text), | ||
2137 | iMin(lineRange.end, mark.end) - line->offset)); | ||
2138 | fillRect_Paint(&p, | ||
2139 | (iRect){ addX_I2(drawPos, iMin(m1, m2)), | ||
2140 | init_I2(iMax(gap_UI / 3, iAbs(m2 - m1)), | ||
2141 | lineHeight_Text(d->font)) }, | ||
2142 | uiMarked_ColorId); | ||
2143 | } | ||
2144 | } | ||
2145 | drawRange_Text(d->font, drawPos, fg, range_String(&line->text)); | ||
2146 | drawPos.y += lineHeight_Text(d->font); | ||
2147 | } | ||
2148 | #endif | ||
2149 | } | 1870 | } |
2150 | unsetClip_Paint(&p); | 1871 | unsetClip_Paint(&p); |
2151 | /* Draw the insertion point. */ | 1872 | /* Draw the insertion point. */ |
@@ -2180,23 +1901,7 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
2180 | /* Bar cursor. */ | 1901 | /* Bar cursor. */ |
2181 | curSize = init_I2(gap_UI / 2, lineHeight_Text(d->font)); | 1902 | curSize = init_I2(gap_UI / 2, lineHeight_Text(d->font)); |
2182 | } | 1903 | } |
2183 | //const iInputLine *curLine = constCursorLine_InputWidget_(d); | ||
2184 | //const iString * text = &curLine->text; | ||
2185 | /* The bounds include visible characters, while advance includes whitespace as well. | ||
2186 | Normally only the advance is needed, but if the cursor is at a newline, the advance | ||
2187 | will have reset back to zero. */ | ||
2188 | //wrapText.text = range_String(text); | ||
2189 | //wrapText.hitChar = wrapText.text.start + d->cursor.x; | ||
2190 | //const int prefixSize = maxWidth_TextMetrics( | ||
2191 | //measure_WrapText(&wrapText, d->font); | ||
2192 | //const iInt2 advance = wrapText.hitAdvance_out; | ||
2193 | const iInt2 advance = relativeCursorCoord_InputWidget_(d); | 1904 | const iInt2 advance = relativeCursorCoord_InputWidget_(d); |
2194 | // const iInt2 curPos = addX_I2(addY_I2(contentBounds.pos, lineHeight_Text(d->font) | ||
2195 | // * d->cursorLine), | ||
2196 | // prefixSize + | ||
2197 | // (d->mode == insert_InputMode ? -curSize.x / 2 : | ||
2198 | // 0)); | ||
2199 | //printf("%d -> tm.advance: %d, %d\n", d->cursor.x, tm.advance.x, tm.advance.y); | ||
2200 | const iInt2 curPos = add_I2(addY_I2(topLeft_Rect(contentBounds), visLineOffsetY + | 1905 | const iInt2 curPos = add_I2(addY_I2(topLeft_Rect(contentBounds), visLineOffsetY + |
2201 | visWrapsAbove * lineHeight_Text(d->font)), | 1906 | visWrapsAbove * lineHeight_Text(d->font)), |
2202 | addX_I2(advance, | 1907 | addX_I2(advance, |
@@ -2204,7 +1909,7 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
2204 | const iRect curRect = { curPos, curSize }; | 1909 | const iRect curRect = { curPos, curSize }; |
2205 | fillRect_Paint(&p, curRect, uiInputCursor_ColorId); | 1910 | fillRect_Paint(&p, curRect, uiInputCursor_ColorId); |
2206 | if (d->mode == overwrite_InputMode) { | 1911 | if (d->mode == overwrite_InputMode) { |
2207 | /* The `gap_UI` offsets below are a hack. They are used because for some reason the | 1912 | /* The `gap_UI` offset below is a hack. They are used because for some reason the |
2208 | cursor rect and the glyph inside don't quite position like during `run_Text_()`. */ | 1913 | cursor rect and the glyph inside don't quite position like during `run_Text_()`. */ |
2209 | drawRange_Text(d->font, | 1914 | drawRange_Text(d->font, |
2210 | addX_I2(curPos, iMin(1, gap_UI / 8)), | 1915 | addX_I2(curPos, iMin(1, gap_UI / 8)), |