BLI: New functions specifically for word/sequence selection #107927

Merged
Harley Acheson merged 2 commits from Harley/blender:CursorStepBounds into main 2023-05-14 21:50:59 +02:00
6 changed files with 89 additions and 12 deletions

View File

@ -42,6 +42,24 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
eStrCursorJumpType jump,
bool use_init_step);
/**
* Word/Sequence Selection. Given a position within a string, return the start and end of the
* closest sequence of delimited characters. Generally a word, but could be a sequence of spaces.
*
* \param str: The string with a cursor position
* \param str_maxlen: The maximum characters to consider
* \param pos: The starting cursor position (probably moved on completion)
* \param r_start: returned start of word/sequence boundary (0-based)
* \param r_end: returned end of word/sequence boundary (0-based)
*/
void BLI_str_cursor_step_bounds_utf8(
const char *str, const size_t str_maxlen, int *pos, int *r_start, int *r_end);
void BLI_str_cursor_step_bounds_utf32(
const char32_t *str, const size_t str_maxlen, int *pos, int *r_start, int *r_end);
#ifdef __cplusplus
}
#endif

View File

@ -314,3 +314,52 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
BLI_assert_unreachable();
}
}
void BLI_str_cursor_step_bounds_utf8(
const char *str, const size_t str_maxlen, int *pos, int *start, int *end)
{
/* What type of characters are on either side of the current cursor position? */
const eStrCursorDelimType prev = (*pos > 0) ? cursor_delim_type_utf8(str, str_maxlen, *pos - 1) :
STRCUR_DELIM_NONE;
const eStrCursorDelimType next = (*pos < str_maxlen) ?
cursor_delim_type_utf8(str, str_maxlen, *pos) :
STRCUR_DELIM_NONE;
*start = *pos;
*end = *pos;
if (prev == next || ELEM(next, STRCUR_DELIM_WHITESPACE, STRCUR_DELIM_NONE)) {
/* Expand backward if we are between similar content, before whitespace, or at end. */
BLI_str_cursor_step_utf8(str, str_maxlen, start, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, false);
}
if (prev == next || ELEM(prev, STRCUR_DELIM_WHITESPACE, STRCUR_DELIM_NONE)) {
/* Expand forward if we are between similar content, after whitespace, or at beginning. */
BLI_str_cursor_step_utf8(str, str_maxlen, end, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, false);
}
/* Move cursor position to the end of selection. */
*pos = *end;
}
void BLI_str_cursor_step_bounds_utf32(
const char32_t *str, const size_t str_maxlen, int *pos, int *start, int *end)
{
/* What type of characters are on either side of the current cursor position? */
const eStrCursorDelimType prev = (*pos > 0) ? cursor_delim_type_unicode(str[*pos - 1]) :
STRCUR_DELIM_NONE;
const eStrCursorDelimType next = (*pos < str_maxlen) ? cursor_delim_type_unicode(str[*pos]) :
STRCUR_DELIM_NONE;
*start = *pos;
*end = *pos;
if (prev == next || ELEM(next, STRCUR_DELIM_WHITESPACE, STRCUR_DELIM_NONE)) {
/* Expand backward if we are between similar content, before whitespace, or at end. */
BLI_str_cursor_step_utf32(str, str_maxlen, start, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, false);
}
if (prev == next || ELEM(prev, STRCUR_DELIM_WHITESPACE, STRCUR_DELIM_NONE)) {
/* Expand forward if we are between similar content, after whitespace, or at beginning. */
BLI_str_cursor_step_utf32(str, str_maxlen, end, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, false);
}
/* Move cursor position to the end of selection. */
*pos = *end;
}

View File

@ -1920,9 +1920,18 @@ void FONT_OT_selection_set(struct wmOperatorType *ot)
static int font_select_word_exec(bContext *C, wmOperator *UNUSED(op))
{
move_cursor(C, NEXT_CHAR, false);
move_cursor(C, PREV_WORD, false);
move_cursor(C, NEXT_WORD, true);
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
BLI_str_cursor_step_bounds_utf32(ef->textbuf, ef->len, &ef->pos, &ef->selstart, &ef->selend);
/* XXX: Text object selection start is 1-based, unlike text processing elsewhere in Blender. */
ef->selstart += 1;
font_select_update_primary_clipboard(obedit);
text_update_edited(C, obedit, FO_CURS);
return OPERATOR_FINISHED;
}

View File

@ -3730,8 +3730,12 @@ static void ui_do_but_textedit(
/* only select a word in button if there was no selection before */
if (event->val == KM_DBL_CLICK && had_selection == false) {
ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_DELIM);
ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_DELIM);
int pos = (int)but->pos;
int selsta, selend;
BLI_str_cursor_step_bounds_utf8(data->str, strlen(data->str), &pos, &selsta, &selend);
but->pos = (short)pos;
but->selsta = (short)selsta;
but->selend = (short)selend;
retval = WM_UI_HANDLER_BREAK;
changed = true;
}

View File

@ -1258,9 +1258,7 @@ static int console_selectword_invoke(bContext *C, wmOperator *UNUSED(op), const
if (console_line_column_from_index(sc, pos, &cl, &offset, &n)) {
int sel[2] = {n, n};
BLI_str_cursor_step_utf8(cl->line, cl->len, &sel[0], STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
BLI_str_cursor_step_utf8(cl->line, cl->len, &sel[1], STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
BLI_str_cursor_step_bounds_utf8(cl->line, cl->len, &n, &sel[0], &sel[1]);
sel[0] = offset - sel[0];
sel[1] = offset - sel[1];

View File

@ -15,6 +15,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_math_base.h"
#include "BLI_string_cursor_utf8.h"
#include "BLT_translation.h"
@ -1577,11 +1578,9 @@ void TEXT_OT_select_line(wmOperatorType *ot)
static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
/* don't advance cursor before stepping */
const bool use_init_step = false;
txt_jump_left(text, false, use_init_step);
txt_jump_right(text, true, use_init_step);
BLI_str_cursor_step_bounds_utf8(
text->curl->line, text->curl->len, &text->selc, &text->curc, &text->selc);
text_update_cursor_moved(C);
text_select_update_primary_clipboard(text);