diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-27 14:18:06 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-27 14:18:41 +0200 |
commit | db7f835c320632ec4dea3b8baf5e21b62e2b75e1 (patch) | |
tree | bc0d497c8152b55b04c62fccb98d394ff8cd57fa /src/ui/util.c | |
parent | 2a4f5d0f67fcd1412968ef967ed3009469a46b90 (diff) |
DocumentWidget: Advanced text selection
Double click to select by word, triple click by paragraph.
IssueID #134
Diffstat (limited to 'src/ui/util.c')
-rw-r--r-- | src/ui/util.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/ui/util.c b/src/ui/util.c index cb9006f6..8074223b 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -164,6 +164,60 @@ 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 | ||
167 | static iBool isSelectionBreakingChar_(iChar c) { | ||
168 | return isSpace_Char(c) || (c == '@' || c == '-' || c == '/' || c == '\\' || c == ','); | ||
169 | } | ||
170 | |||
171 | static const char *moveBackward_(const char *pos, iRangecc bounds, int mode) { | ||
172 | iChar ch; | ||
173 | while (pos > bounds.start) { | ||
174 | int len = decodePrecedingBytes_MultibyteChar(pos, bounds.start, &ch); | ||
175 | if (len > 0) { | ||
176 | if (mode & word_RangeExtension && isSelectionBreakingChar_(ch)) break; | ||
177 | if (mode & line_RangeExtension && ch == '\n') break; | ||
178 | pos -= len; | ||
179 | } | ||
180 | else break; | ||
181 | } | ||
182 | return pos; | ||
183 | } | ||
184 | |||
185 | static const char *moveForward_(const char *pos, iRangecc bounds, int mode) { | ||
186 | iChar ch; | ||
187 | while (pos < bounds.end) { | ||
188 | int len = decodeBytes_MultibyteChar(pos, bounds.end, &ch); | ||
189 | if (len > 0) { | ||
190 | if (mode & word_RangeExtension && isSelectionBreakingChar_(ch)) break; | ||
191 | if (mode & line_RangeExtension && ch == '\n') break; | ||
192 | pos += len; | ||
193 | } | ||
194 | else break; | ||
195 | } | ||
196 | return pos; | ||
197 | } | ||
198 | |||
199 | void extendRange_Rangecc(iRangecc *d, iRangecc bounds, int mode) { | ||
200 | if (!d->start) return; | ||
201 | if (d->end >= d->start) { | ||
202 | if (mode & bothStartAndEnd_RangeExtension) { | ||
203 | d->start = moveBackward_(d->start, bounds, mode); | ||
204 | d->end = moveForward_(d->end, bounds, mode); | ||
205 | } | ||
206 | else { | ||
207 | d->end = moveForward_(d->end, bounds, mode); | ||
208 | } | ||
209 | } | ||
210 | else { | ||
211 | if (mode & bothStartAndEnd_RangeExtension) { | ||
212 | d->start = moveForward_(d->start, bounds, mode); | ||
213 | d->end = moveBackward_(d->end, bounds, mode); | ||
214 | } | ||
215 | else { | ||
216 | d->end = moveBackward_(d->end, bounds, mode); | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
167 | /*----------------------------------------------------------------------------------------------*/ | 221 | /*----------------------------------------------------------------------------------------------*/ |
168 | 222 | ||
169 | iBool isFinished_Anim(const iAnim *d) { | 223 | iBool isFinished_Anim(const iAnim *d) { |