summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-27 15:13:55 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-27 15:13:55 +0200
commite5fa60b6f5fbc79c13ac98f53911f1e34d6cee18 (patch)
treec719b9577b9f3cc758aeb71dec04ef1c1dcae5eb /src
parentdb7f835c320632ec4dea3b8baf5e21b62e2b75e1 (diff)
InputWidget: Select by word
IssueID #134
Diffstat (limited to 'src')
-rw-r--r--src/ui/inputwidget.c47
-rw-r--r--src/ui/util.c6
-rw-r--r--src/ui/util.h4
3 files changed, 48 insertions, 9 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index 12bef08b..5593b5b9 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -73,6 +73,7 @@ enum iInputWidgetFlag {
73 notifyEdits_InputWidgetFlag = iBit(5), 73 notifyEdits_InputWidgetFlag = iBit(5),
74 eatEscape_InputWidgetFlag = iBit(6), 74 eatEscape_InputWidgetFlag = iBit(6),
75 isMarking_InputWidgetFlag = iBit(7), 75 isMarking_InputWidgetFlag = iBit(7),
76 markWords_InputWidgetFlag = iBit(8),
76}; 77};
77 78
78struct Impl_InputWidget { 79struct Impl_InputWidget {
@@ -89,6 +90,7 @@ struct Impl_InputWidget {
89 size_t cursor; 90 size_t cursor;
90 size_t lastCursor; 91 size_t lastCursor;
91 iRanges mark; 92 iRanges mark;
93 iRanges initialMark;
92 iArray undoStack; 94 iArray undoStack;
93 int font; 95 int font;
94 iClick click; 96 iClick click;
@@ -664,6 +666,27 @@ static void paste_InputWidget_(iInputWidget *d) {
664 } 666 }
665} 667}
666 668
669static iChar at_InputWidget_(const iInputWidget *d, size_t pos) {
670 return *(const iChar *) constAt_Array(&d->text, pos);
671}
672
673static void extendRange_InputWidget_(iInputWidget *d, size_t *pos, int dir) {
674 const size_t textLen = size_Array(&d->text);
675 if (dir < 0 && *pos > 0) {
676 for ((*pos)--; *pos > 0; (*pos)--) {
677 if (isSelectionBreaking_Char(at_InputWidget_(d, *pos))) {
678 (*pos)++;
679 break;
680 }
681 }
682 }
683 if (dir > 0) {
684 for (; *pos < textLen && !isSelectionBreaking_Char(at_InputWidget_(d, *pos)); (*pos)++) {
685 /* continue */
686 }
687 }
688}
689
667static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { 690static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
668 iWidget *w = as_Widget(d); 691 iWidget *w = as_Widget(d);
669 if (isCommand_Widget(w, ev, "focus.gained")) { 692 if (isCommand_Widget(w, ev, "focus.gained")) {
@@ -733,7 +756,19 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
733 setFocus_Widget(w); 756 setFocus_Widget(w);
734 setCursor_InputWidget(d, coordIndex_InputWidget_(d, pos_Click(&d->click))); 757 setCursor_InputWidget(d, coordIndex_InputWidget_(d, pos_Click(&d->click)));
735 iZap(d->mark); 758 iZap(d->mark);
736 d->inFlags &= ~isMarking_InputWidgetFlag; 759 iZap(d->initialMark);
760 d->inFlags &= ~(isMarking_InputWidgetFlag | markWords_InputWidgetFlag);
761 if (d->click.count == 2) {
762 d->inFlags |= isMarking_InputWidgetFlag | markWords_InputWidgetFlag;
763 d->mark.start = d->mark.end = d->cursor;
764 extendRange_InputWidget_(d, &d->mark.start, -1);
765 extendRange_InputWidget_(d, &d->mark.end, +1);
766 d->initialMark = d->mark;
767 refresh_Widget(w);
768 }
769 if (d->click.count == 3) {
770 selectAll_InputWidget(d);
771 }
737 return iTrue; 772 return iTrue;
738 case aborted_ClickResult: 773 case aborted_ClickResult:
739 d->inFlags &= ~isMarking_InputWidgetFlag; 774 d->inFlags &= ~isMarking_InputWidgetFlag;
@@ -746,13 +781,15 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
746 d->mark.start = d->cursor; 781 d->mark.start = d->cursor;
747 } 782 }
748 d->mark.end = d->cursor; 783 d->mark.end = d->cursor;
784 if (d->inFlags & markWords_InputWidgetFlag) {
785 const iBool isFwd = d->mark.end >= d->mark.start;
786 extendRange_InputWidget_(d, &d->mark.end, isFwd ? +1 : -1);
787 d->mark.start = isFwd ? d->initialMark.start : d->initialMark.end;
788 }
749 refresh_Widget(w); 789 refresh_Widget(w);
750 return iTrue; 790 return iTrue;
751 case finished_ClickResult: 791 case finished_ClickResult:
752 if (d->click.count == 2) { 792 d->inFlags &= ~isMarking_InputWidgetFlag;
753 selectAll_InputWidget(d);
754 d->inFlags &= ~isMarking_InputWidgetFlag;
755 }
756 return iTrue; 793 return iTrue;
757 } 794 }
758 if (ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT && 795 if (ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT &&
diff --git a/src/ui/util.c b/src/ui/util.c
index 8074223b..19fba3a4 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -164,7 +164,7 @@ iRangei union_Rangei(iRangei a, iRangei b) {
164 return (iRangei){ iMin(a.start, b.start), iMax(a.end, b.end) }; 164 return (iRangei){ iMin(a.start, b.start), iMax(a.end, b.end) };
165} 165}
166 166
167static iBool isSelectionBreakingChar_(iChar c) { 167iBool isSelectionBreaking_Char(iChar c) {
168 return isSpace_Char(c) || (c == '@' || c == '-' || c == '/' || c == '\\' || c == ','); 168 return isSpace_Char(c) || (c == '@' || c == '-' || c == '/' || c == '\\' || c == ',');
169} 169}
170 170
@@ -173,7 +173,7 @@ static const char *moveBackward_(const char *pos, iRangecc bounds, int mode) {
173 while (pos > bounds.start) { 173 while (pos > bounds.start) {
174 int len = decodePrecedingBytes_MultibyteChar(pos, bounds.start, &ch); 174 int len = decodePrecedingBytes_MultibyteChar(pos, bounds.start, &ch);
175 if (len > 0) { 175 if (len > 0) {
176 if (mode & word_RangeExtension && isSelectionBreakingChar_(ch)) break; 176 if (mode & word_RangeExtension && isSelectionBreaking_Char(ch)) break;
177 if (mode & line_RangeExtension && ch == '\n') break; 177 if (mode & line_RangeExtension && ch == '\n') break;
178 pos -= len; 178 pos -= len;
179 } 179 }
@@ -187,7 +187,7 @@ static const char *moveForward_(const char *pos, iRangecc bounds, int mode) {
187 while (pos < bounds.end) { 187 while (pos < bounds.end) {
188 int len = decodeBytes_MultibyteChar(pos, bounds.end, &ch); 188 int len = decodeBytes_MultibyteChar(pos, bounds.end, &ch);
189 if (len > 0) { 189 if (len > 0) {
190 if (mode & word_RangeExtension && isSelectionBreakingChar_(ch)) break; 190 if (mode & word_RangeExtension && isSelectionBreaking_Char(ch)) break;
191 if (mode & line_RangeExtension && ch == '\n') break; 191 if (mode & line_RangeExtension && ch == '\n') break;
192 pos += len; 192 pos += len;
193 } 193 }
diff --git a/src/ui/util.h b/src/ui/util.h
index 9e00e495..2be38384 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -88,7 +88,9 @@ enum iRangeExtension {
88 bothStartAndEnd_RangeExtension = iBit(3), 88 bothStartAndEnd_RangeExtension = iBit(3),
89}; 89};
90 90
91void extendRange_Rangecc (iRangecc *, iRangecc bounds, int mode); 91void extendRange_Rangecc (iRangecc *, iRangecc bounds, int mode);
92
93iBool isSelectionBreaking_Char(iChar);
92 94
93/*-----------------------------------------------------------------------------------------------*/ 95/*-----------------------------------------------------------------------------------------------*/
94 96