Blender V4.3
string_cursor_utf8.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <stdio.h>
10#include <stdlib.h>
11
12#include "BLI_string_utf8.h"
13#include "BLI_utildefines.h"
14
15#include "BLI_string_cursor_utf8.h" /* own include */
16
17#include "BLI_strict_flags.h" /* Keep last. */
18
41
43{
44 switch (uch) {
45 case ',':
46 case '.':
47 case 0x2026: /* Horizontal ellipsis. */
48 case 0x3002: /* CJK full width full stop. */
49 case 0xFF0C: /* CJK full width comma. */
50 case 0xFF61: /* CJK half width full stop. */
51 return STRCUR_DELIM_PUNCT;
52
53 case '{':
54 case '}':
55 case '[':
56 case ']':
57 case '(':
58 case ')':
59 case 0x3010: /* CJK full width left black lenticular bracket. */
60 case 0x3011: /* CJK full width right black lenticular bracket. */
61 case 0xFF08: /* CJK full width left parenthesis. */
62 case 0xFF09: /* CJK full width right parenthesis. */
63 return STRCUR_DELIM_BRACE;
64
65 case '+':
66 case '-':
67 case '=':
68 case '~':
69 case '%':
70 case '/':
71 case '<':
72 case '>':
73 case '^':
74 case '*':
75 case '&':
76 case '|':
77 case 0x2014: /* Em dash. */
78 case 0x300A: /* CJK full width left double angle bracket. */
79 case 0x300B: /* CJK full width right double angle bracket. */
80 case 0xFF0F: /* CJK full width solidus (forward slash). */
81 case 0xFF5E: /* CJK full width tilde. */
83
84 case '\'':
85 case '\"':
86 case '`':
87 case 0xB4: /* Acute accent. */
88 case 0x2018: /* Left single quotation mark. */
89 case 0x2019: /* Right single quotation mark. */
90 case 0x201C: /* Left double quotation mark. */
91 case 0x201D: /* Right double quotation mark. */
92 return STRCUR_DELIM_QUOTE;
93
94 case ' ':
95 case '\t':
96 case '\n':
98
99 case '\\':
100 case '@':
101 case '#':
102 case '$':
103 case ':':
104 case ';':
105 case '?':
106 case '!':
107 case 0xA3: /* Pound sign. */
108 case 0x80: /* Euro sign. */
109 case 0x3001: /* CJK ideographic comma. */
110 case 0xFF01: /* CJK full width exclamation mark. */
111 case 0xFF64: /* CJK half width ideographic comma. */
112 case 0xFF65: /* Katakana half width middle dot. */
113 case 0xFF1A: /* CJK full width colon. */
114 case 0xFF1B: /* CJK full width semicolon. */
115 case 0xFF1F: /* CJK full width question mark. */
116 /* case '_': */ /* special case, for python */
117 return STRCUR_DELIM_OTHER;
118
119 default:
120 break;
121 }
122 return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */
123}
124
126 const int ch_utf8_len,
127 const int pos)
128{
129 BLI_assert(ch_utf8_len >= 0);
130 /* for full unicode support we really need to have large lookup tables to figure
131 * out what's what in every possible char set - and python, glib both have these. */
132 size_t index = (size_t)pos;
133 uint uch = BLI_str_utf8_as_unicode_step_or_error(ch_utf8, (size_t)ch_utf8_len, &index);
134 return cursor_delim_type_unicode(uch);
135}
136
137bool BLI_str_cursor_step_next_utf8(const char *str, const int str_maxlen, int *pos)
138{
139 /* NOTE: Keep in sync with #BLI_str_cursor_step_next_utf32. */
140 BLI_assert(str_maxlen >= 0);
141 BLI_assert(*pos >= 0);
142
143 if (*pos >= str_maxlen) {
144 return false;
145 }
146 const char *str_end = str + (str_maxlen + 1);
147 const char *str_pos = str + *pos;
148 const char *str_next = str_pos;
149 do {
150 str_next = BLI_str_find_next_char_utf8(str_next, str_end);
151 } while ((str_next < str_end) && (str_next[0] != 0) &&
152 (BLI_str_utf8_char_width_or_error(str_next) == 0));
153 *pos += (int)(str_next - str_pos);
154 if (*pos > str_maxlen) {
155 *pos = str_maxlen;
156 }
157
158 return true;
159}
160
161bool BLI_str_cursor_step_prev_utf8(const char *str, const int str_maxlen, int *pos)
162{
163 /* NOTE: Keep in sync with #BLI_str_cursor_step_prev_utf32. */
164 BLI_assert(str_maxlen >= 0);
165 BLI_assert(*pos >= 0);
166
167 if ((*pos > 0) && (*pos <= str_maxlen)) {
168 const char *str_pos = str + *pos;
169 const char *str_prev = str_pos;
170 do {
171 str_prev = BLI_str_find_prev_char_utf8(str_prev, str);
172 } while ((str_prev > str) && (BLI_str_utf8_char_width_or_error(str_prev) == 0));
173 *pos -= (int)(str_pos - str_prev);
174 return true;
175 }
176
177 return false;
178}
179
181 const int str_maxlen,
182 int *pos,
183 eStrCursorJumpDirection direction,
185 bool use_init_step)
186{
187 BLI_assert(str_maxlen >= 0);
188 const int pos_orig = *pos;
189
190 if (direction == STRCUR_DIR_NEXT) {
191 if (use_init_step) {
193 }
194 else {
196 }
197
198 if (jump != STRCUR_JUMP_NONE) {
199 const eStrCursorDelimType delim_type = (*pos < str_maxlen) ?
200 cursor_delim_type_utf8(str, str_maxlen, *pos) :
202 /* jump between special characters (/,\,_,-, etc.),
203 * look at function cursor_delim_type() for complete
204 * list of special character, ctr -> */
205 while (*pos < str_maxlen) {
206 if (BLI_str_cursor_step_next_utf8(str, str_maxlen, pos)) {
207 if (*pos == str_maxlen) {
208 break;
209 }
210 if ((jump != STRCUR_JUMP_ALL) &&
211 (delim_type != cursor_delim_type_utf8(str, str_maxlen, *pos)))
212 {
213 break;
214 }
215 }
216 else {
217 break; /* unlikely but just in case */
218 }
219 }
220 }
221 }
222 else if (direction == STRCUR_DIR_PREV) {
223 if (use_init_step) {
225 }
226 else {
228 }
229
230 if (jump != STRCUR_JUMP_NONE) {
231 const eStrCursorDelimType delim_type = (*pos > 0) ? cursor_delim_type_utf8(
232 str, str_maxlen, *pos - 1) :
234 /* jump between special characters (/,\,_,-, etc.),
235 * look at function cursor_delim_type() for complete
236 * list of special character, ctr -> */
237 while (*pos > 0) {
238 const int pos_prev = *pos;
239 if (BLI_str_cursor_step_prev_utf8(str, str_maxlen, pos)) {
240 if ((jump != STRCUR_JUMP_ALL) &&
241 (delim_type != cursor_delim_type_utf8(str, str_maxlen, *pos)))
242 {
243 /* left only: compensate for index/change in direction */
244 if ((pos_orig - *pos) >= 1) {
245 *pos = pos_prev;
246 }
247 break;
248 }
249 }
250 else {
251 break;
252 }
253 }
254 }
255 }
256 else {
258 }
259}
260
261bool BLI_str_cursor_step_next_utf32(const char32_t *str, const int str_maxlen, int *pos)
262{
263 /* NOTE: Keep in sync with #BLI_str_cursor_step_next_utf8. */
264 BLI_assert(str_maxlen >= 0);
265 BLI_assert(*pos >= 0);
266
267 if (*pos >= str_maxlen) {
268 return false;
269 }
270 do {
271 (*pos)++;
272 } while ((*pos < str_maxlen) && (str[*pos] != 0) && (BLI_wcwidth_or_error(str[*pos]) == 0));
273
274 return true;
275}
276
277bool BLI_str_cursor_step_prev_utf32(const char32_t *str, const int str_maxlen, int *pos)
278{
279 /* NOTE: Keep in sync with #BLI_str_cursor_step_prev_utf8. */
280 BLI_assert(str_maxlen >= 0);
281 BLI_assert(*pos >= 0);
282 UNUSED_VARS_NDEBUG(str_maxlen);
283
284 if (*pos <= 0) {
285 return false;
286 }
287 do {
288 (*pos)--;
289 } while ((*pos > 0) && (BLI_wcwidth_or_error(str[*pos]) == 0));
290
291 return true;
292}
293
294void BLI_str_cursor_step_utf32(const char32_t *str,
295 const int str_maxlen,
296 int *pos,
297 eStrCursorJumpDirection direction,
299 bool use_init_step)
300{
301 BLI_assert(str_maxlen >= 0);
302 const int pos_orig = *pos;
303
304 if (direction == STRCUR_DIR_NEXT) {
305 if (use_init_step) {
307 }
308 else {
310 }
311
312 if (jump != STRCUR_JUMP_NONE) {
313 const eStrCursorDelimType delim_type = (*pos < str_maxlen) ?
316 /* jump between special characters (/,\,_,-, etc.),
317 * look at function cursor_delim_type_unicode() for complete
318 * list of special character, ctr -> */
319 while (*pos < str_maxlen) {
320 if (BLI_str_cursor_step_next_utf32(str, str_maxlen, pos)) {
321 if ((jump != STRCUR_JUMP_ALL) &&
322 (delim_type != cursor_delim_type_unicode((uint)str[*pos])))
323 {
324 break;
325 }
326 }
327 else {
328 break; /* unlikely but just in case */
329 }
330 }
331 }
332 }
333 else if (direction == STRCUR_DIR_PREV) {
334 if (use_init_step) {
336 }
337 else {
339 }
340
341 if (jump != STRCUR_JUMP_NONE) {
342 const eStrCursorDelimType delim_type = (*pos > 0) ?
343 cursor_delim_type_unicode((uint)str[(*pos) - 1]) :
345 /* jump between special characters (/,\,_,-, etc.),
346 * look at function cursor_delim_type() for complete
347 * list of special character, ctr -> */
348 while (*pos > 0) {
349 const int pos_prev = *pos;
350 if (BLI_str_cursor_step_prev_utf32(str, str_maxlen, pos)) {
351 if ((jump != STRCUR_JUMP_ALL) &&
352 (delim_type != cursor_delim_type_unicode((uint)str[*pos])))
353 {
354 /* left only: compensate for index/change in direction */
355 if ((pos_orig - *pos) >= 1) {
356 *pos = pos_prev;
357 }
358 break;
359 }
360 }
361 else {
362 break;
363 }
364 }
365 }
366 }
367 else {
369 }
370}
371
373 const char *str, const int str_maxlen, const int pos, int *r_start, int *r_end)
374{
375 BLI_assert(str_maxlen >= 0);
376 BLI_assert(pos >= 0 && pos <= str_maxlen);
377 /* Identify the type of characters are on either side of the current cursor position. */
378 const eStrCursorDelimType prev = (pos > 0) ? cursor_delim_type_utf8(str, str_maxlen, pos - 1) :
380 const eStrCursorDelimType next = (pos < str_maxlen) ?
381 cursor_delim_type_utf8(str, str_maxlen, pos) :
383 *r_start = pos;
384 *r_end = pos;
385
386 if (prev != STRCUR_DELIM_NONE) {
387 if ((prev <= next) || (next == STRCUR_DELIM_NONE)) {
388 /* Expand backward if we are between similar content. */
390 str, str_maxlen, r_start, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, false);
391 }
392 }
393 if (next != STRCUR_DELIM_NONE) {
394 if ((next <= prev) || (prev == STRCUR_DELIM_NONE)) {
395 /* Expand forward if we are between similar content. */
397 }
398 }
399}
400
402 const char32_t *str, const int str_maxlen, const int pos, int *r_start, int *r_end)
403{
404 BLI_assert(str_maxlen >= 0);
405 BLI_assert(pos >= 0 && pos <= str_maxlen);
406 /* Identify the type of characters are on either side of the current cursor position. */
407 const eStrCursorDelimType prev = (pos > 0) ? cursor_delim_type_unicode(str[pos - 1]) :
409 const eStrCursorDelimType next = (pos < str_maxlen) ? cursor_delim_type_unicode(str[pos]) :
411 *r_start = pos;
412 *r_end = pos;
413
414 if (prev != STRCUR_DELIM_NONE) {
415 if ((prev <= next) || (next == STRCUR_DELIM_NONE)) {
416 /* Expand backward if we are between similar content. */
418 str, str_maxlen, r_start, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, false);
419 }
420 }
421 if (next != STRCUR_DELIM_NONE) {
422 if ((next <= prev) || (prev == STRCUR_DELIM_NONE)) {
423 /* Expand forward if we are between similar content. */
425 }
426 }
427}
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
eStrCursorJumpDirection
@ STRCUR_DIR_NEXT
@ STRCUR_DIR_PREV
@ STRCUR_JUMP_ALL
@ STRCUR_JUMP_NONE
@ STRCUR_JUMP_DELIM
const char const char * BLI_str_find_next_char_utf8(const char *p, const char *str_end) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
int BLI_str_utf8_char_width_or_error(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int unsigned int BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p, size_t p_len, size_t *__restrict index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
const char * BLI_str_find_prev_char_utf8(const char *p, const char *str_start) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
size_t size_t int BLI_wcwidth_or_error(char32_t ucs) ATTR_WARN_UNUSED_RESULT
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
void jump(const btVector3 &v=btVector3(0, 0, 0))
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define str(s)
static ulong * next
void BLI_str_cursor_step_utf32(const char32_t *str, const int str_maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
static eStrCursorDelimType cursor_delim_type_unicode(const uint uch)
void BLI_str_cursor_step_bounds_utf32(const char32_t *str, const int str_maxlen, const int pos, int *r_start, int *r_end)
bool BLI_str_cursor_step_next_utf8(const char *str, const int str_maxlen, int *pos)
eStrCursorDelimType
@ STRCUR_DELIM_OTHER
@ STRCUR_DELIM_BRACE
@ STRCUR_DELIM_QUOTE
@ STRCUR_DELIM_WHITESPACE
@ STRCUR_DELIM_ALPHANUMERIC
@ STRCUR_DELIM_PUNCT
@ STRCUR_DELIM_NONE
@ STRCUR_DELIM_OPERATOR
static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8, const int ch_utf8_len, const int pos)
void BLI_str_cursor_step_utf8(const char *str, const int str_maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
bool BLI_str_cursor_step_prev_utf32(const char32_t *str, const int str_maxlen, int *pos)
void BLI_str_cursor_step_bounds_utf8(const char *str, const int str_maxlen, const int pos, int *r_start, int *r_end)
bool BLI_str_cursor_step_next_utf32(const char32_t *str, const int str_maxlen, int *pos)
bool BLI_str_cursor_step_prev_utf8(const char *str, const int str_maxlen, int *pos)