52 if (
data ==
nullptr ||
data->runtime ==
nullptr) {
81 cursor_offset = std::clamp(cursor_offset, 0, text->character_count);
83 int2 cursor_position{0, 0};
85 if (cursor_offset < line.characters.size()) {
86 cursor_position.x = cursor_offset;
89 cursor_offset -= line.characters.size();
90 cursor_position.y += 1;
93 cursor_position.y = std::clamp(cursor_position.y, 0,
int(text->lines.size() - 1));
94 cursor_position.x = std::clamp(
95 cursor_position.x, 0,
int(text->lines[cursor_position.y].characters.size() - 1));
97 return cursor_position;
101 const int2 cursor_pos)
103 return text->lines[cursor_pos.y].characters[cursor_pos.x];
107 const int cursor_offset)
120 data->selection_start_offset = 0;
121 data->selection_end_offset = 0;
127 int sel_start_offset =
data->selection_start_offset;
128 int sel_end_offset =
data->selection_end_offset;
129 if (sel_start_offset > sel_end_offset) {
130 std::swap(sel_start_offset, sel_end_offset);
133 return IndexRange(sel_start_offset, sel_end_offset - sel_start_offset);
153 char *addr_start =
const_cast<char *
>(char_start.
str_ptr);
156 std::memmove(addr_start, addr_end,
BLI_strnlen(addr_end,
sizeof(
data->text)) + 1);
184 {
LINE_BEGIN,
"LINE_BEGIN", 0,
"Line Begin",
""},
185 {
LINE_END,
"LINE_END", 0,
"Line End",
""},
186 {
TEXT_BEGIN,
"TEXT_BEGIN", 0,
"Text Begin",
""},
187 {
TEXT_END,
"TEXT_END", 0,
"Text End",
""},
188 {
PREV_CHAR,
"PREVIOUS_CHARACTER", 0,
"Previous Character",
""},
189 {
NEXT_CHAR,
"NEXT_CHARACTER", 0,
"Next Character",
""},
190 {
PREV_WORD,
"PREVIOUS_WORD", 0,
"Previous Word",
""},
191 {
NEXT_WORD,
"NEXT_WORD", 0,
"Next Word",
""},
192 {
PREV_LINE,
"PREVIOUS_LINE", 0,
"Previous Line",
""},
193 {
NEXT_LINE,
"NEXT_LINE", 0,
"Next Line",
""},
194 {0,
nullptr, 0,
nullptr,
nullptr},
199 const seq::LineInfo &cur_line = text->lines[cursor_position.y];
201 if (cursor_position.x + offset > cur_line.
characters.size() - 1 &&
202 cursor_position.y < text->lines.size() - 1)
204 cursor_position.x = 0;
208 else if (cursor_position.x + offset < 0 && cursor_position.y > 0) {
210 cursor_position.x = text->lines[cursor_position.y].characters.size() - 1;
213 cursor_position.x += offset;
214 const int position_max = text->lines[cursor_position.y].characters.size() - 1;
215 cursor_position.x = std::clamp(cursor_position.x, 0, position_max);
217 return cursor_position;
222 const seq::LineInfo &cur_line = text->lines[cursor_position.y];
223 const int cur_pos_x = cur_line.
characters[cursor_position.x].position.x;
225 const int line_max = text->lines.size() - 1;
226 const int new_line_index = std::clamp(cursor_position.y + offset, 0, line_max);
229 if (cursor_position.y == new_line_index) {
230 return cursor_position;
234 int best_distance = std::numeric_limits<int>::max();
235 int best_character_index = 0;
237 for (
int i : new_line.
characters.index_range()) {
242 best_character_index = i;
246 cursor_position.x = best_character_index;
247 cursor_position.y = new_line_index;
248 return cursor_position;
253 const seq::LineInfo &cur_line = text->lines[cursor_position.y];
254 cursor_position.x = cur_line.
characters.size() - 1;
255 return cursor_position;
260 return ELEM(chr1,
' ',
'\t',
'\n') && !
ELEM(chr2,
' ',
'\t',
'\n');
267 while (cursor_position.x > 0 || cursor_position.y > 0) {
275 cursor_position = prev_cursor_pos;
277 return cursor_position;
282 const int maxline = text->lines.size() - 1;
283 const int maxchar = text->lines.last().characters.size() - 1;
285 while ((cursor_position.x < maxchar) || (cursor_position.y < maxline)) {
294 return cursor_position;
304 data->selection_start_offset =
data->cursor_offset;
323 cursor_position.x = 0;
329 cursor_position = {0, 0};
332 cursor_position.y = text->lines.size() - 1;
345 data->selection_end_offset =
data->cursor_offset;
349 data->cursor_offset ==
data->selection_start_offset)
363 ot->
idname =
"SEQUENCER_OT_text_cursor_move";
378 "Where to move cursor to, to make a selection");
381 ot->
srna,
"select_text",
false,
"Select Text",
"Select text while moving cursor");
395 if (text_str_len + buf_len + 1 >
sizeof(
data->text)) {
396 return selection_was_deleted;
400 char *cursor_addr =
const_cast<char *
>(cur_char.
str_ptr);
401 const size_t move_str_len =
BLI_strnlen(cursor_addr,
sizeof(
data->text)) + 1;
403 std::memmove(cursor_addr + buf_len, cursor_addr, move_str_len);
404 std::memcpy(cursor_addr, buf, buf_len);
406 data->cursor_offset += 1;
419 if (in_buf_len == 0) {
444 ot->
name =
"Insert Character";
446 ot->
idname =
"SEQUENCER_OT_text_insert";
458 ot->
srna,
"string",
nullptr, 512,
"String",
"String to be inserted at cursor position");
463 {
DEL_NEXT_SEL,
"NEXT_OR_SELECTION", 0,
"Next or Selection",
""},
464 {
DEL_PREV_SEL,
"PREVIOUS_OR_SELECTION", 0,
"Previous or Selection",
""},
465 {0,
nullptr, 0,
nullptr,
nullptr},
470 char *cursor_addr =
const_cast<char *
>(character.
str_ptr);
471 char *next_char_addr = cursor_addr + character.
byte_length;
472 std::memmove(cursor_addr, next_char_addr,
BLI_strnlen(next_char_addr,
sizeof(
data->text)) + 1);
489 if (
data->cursor_offset >= text->character_count) {
496 if (
data->cursor_offset == 0) {
501 data->cursor_offset -= 1;
511 ot->
name =
"Delete Character";
513 ot->
idname =
"SEQUENCER_OT_text_delete";
528 "Which part of the text to delete");
547 ot->
name =
"Insert Line Break";
549 ot->
idname =
"SEQUENCER_OT_text_line_break";
564 data->selection_end_offset =
data->runtime->character_count;
574 ot->
idname =
"SEQUENCER_OT_text_select_all";
591 strip->
flag &= ~SEQ_FLAG_TEXT_EDITING_ACTIVE;
604 ot->
name =
"Deselect All";
606 ot->
idname =
"SEQUENCER_OT_text_deselect_all";
620 strip->
flag &= ~SEQ_FLAG_TEXT_EDITING_ACTIVE;
635 ot->
idname =
"SEQUENCER_OT_text_edit_mode_toggle";
648 int best_cursor_offset = 0;
649 float best_distance = std::numeric_limits<float>::max();
656 best_cursor_offset = character.index;
661 return best_cursor_offset;
683 mouse_loc.x /= view_aspect;
685 mouse_loc -= view_offs;
696 bool make_selection =
false;
698 switch (event->
type) {
702 if (make_selection) {
703 data->selection_end_offset =
data->cursor_offset;
712 make_selection =
true;
714 data->selection_start_offset =
data->cursor_offset;
717 data->selection_end_offset =
data->cursor_offset;
743 strip->
flag &= ~SEQ_FLAG_TEXT_EDITING_ACTIVE;
760 ot->
idname =
"SEQUENCER_OT_text_cursor_set";
773 ot->
srna,
"select_text",
false,
"Select Text",
"Select text while moving cursor");
785 char clipboard_buf[
sizeof(
data->text)] = {0};
809 ot->
idname =
"SEQUENCER_OT_text_edit_copy";
828 if (clipboard_len == 0) {
833 const int max_str_len =
sizeof(
data->text) - (
STRNLEN(
data->text) + 1);
836 const int fillable_len = std::min(clipboard_len, max_str_len);
840 size_t valid_str_len;
844 char *cursor_addr =
const_cast<char *
>(cur_char.
str_ptr);
845 const size_t move_str_len =
BLI_strnlen(cursor_addr,
sizeof(
data->text)) + 1;
847 std::memmove(cursor_addr + valid_str_len, cursor_addr, move_str_len);
848 std::memcpy(cursor_addr, clipboard_buf, valid_str_len);
850 data->cursor_offset += extra_offset;
862 ot->
idname =
"SEQUENCER_OT_text_edit_paste";
893 ot->
idname =
"SEQUENCER_OT_text_edit_cut";
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
float BKE_scene_frame_get(const Scene *scene)
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strnlen_utf8_ex(const char *strc, size_t strc_maxlen, size_t *r_len_bytes) ATTR_NONNULL(1
@ SEQ_FLAG_TEXT_EDITING_ACTIVE
struct TextVarsRuntime TextVarsRuntime
bScreen * ED_screen_animation_no_scrub(const wmWindowManager *wm)
View2D * UI_view2d_fromcontext(const bContext *C)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr bool is_empty() const
float distance(VecOp< float, D >, VecOp< float, D >) RET
void MEM_freeN(void *vmemh)
blender::IndexRange strip_text_selection_range_get(const TextVars *data)
void SEQUENCER_OT_text_edit_copy(wmOperatorType *ot)
void SEQUENCER_OT_text_line_break(wmOperatorType *ot)
static bool text_insert(TextVars *data, const char *buf, const size_t buf_len)
static void cursor_set_by_mouse_position(const bContext *C, const wmEvent *event)
static wmOperatorStatus sequencer_text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_text_delete(wmOperatorType *ot)
void SEQUENCER_OT_text_edit_cut(wmOperatorType *ot)
static const EnumPropertyItem move_type_items[]
bool sequencer_text_editing_active_poll(bContext *C)
static wmOperatorStatus sequencer_text_edit_mode_toggle_exec(bContext *C, wmOperator *)
static const EnumPropertyItem delete_type_items[]
static void delete_character(const seq::CharInfo character, const TextVars *data)
static wmOperatorStatus sequencer_text_edit_paste_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_text_insert(wmOperatorType *ot)
void SEQUENCER_OT_text_deselect_all(wmOperatorType *ot)
bool sequencer_editing_initialized_and_active(bContext *C)
static wmOperatorStatus sequencer_text_edit_copy_exec(bContext *C, wmOperator *)
static int2 cursor_move_by_line(int2 cursor_position, const TextVarsRuntime *text, int offset)
static void text_editing_update(const bContext *C)
static const seq::CharInfo & character_at_cursor_offset_get(const TextVarsRuntime *text, const int cursor_offset)
void SEQUENCER_OT_text_select_all(wmOperatorType *ot)
static wmOperatorStatus sequencer_text_deselect_all_exec(bContext *C, wmOperator *)
static int2 cursor_move_line_end(int2 cursor_position, const TextVarsRuntime *text)
static bool sequencer_text_editing_poll(bContext *C)
static wmOperatorStatus sequencer_text_cursor_move_exec(bContext *C, wmOperator *op)
static wmOperatorStatus sequencer_text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
blender::int2 strip_text_cursor_offset_to_position(const TextVarsRuntime *text, int cursor_offset)
static wmOperatorStatus sequencer_text_delete_exec(bContext *C, wmOperator *op)
static void text_selection_cancel(TextVars *data)
static int2 cursor_move_next_word(int2 cursor_position, const TextVarsRuntime *text)
static int2 cursor_move_prev_word(int2 cursor_position, const TextVarsRuntime *text)
static bool is_whitespace_transition(char chr1, char chr2)
static wmOperatorStatus sequencer_text_insert_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_text_edit_paste(wmOperatorType *ot)
static void delete_selected_text(TextVars *data)
static int cursor_position_to_offset(const TextVarsRuntime *text, int2 cursor_position)
bool strip_point_image_isect(const Scene *scene, const Strip *strip, float point_view[2])
static const seq::CharInfo & character_at_cursor_pos_get(const TextVarsRuntime *text, const int2 cursor_pos)
static bool text_has_selection(const TextVars *data)
void SEQUENCER_OT_text_cursor_move(wmOperatorType *ot)
static int find_closest_cursor_offset(const TextVars *data, float2 mouse_loc)
static wmOperatorStatus sequencer_text_edit_cut_exec(bContext *C, wmOperator *)
static wmOperatorStatus sequencer_text_select_all_exec(bContext *C, wmOperator *)
static void text_edit_copy(const TextVars *data)
static wmOperatorStatus sequencer_text_line_break_exec(bContext *C, wmOperator *)
static int2 cursor_move_by_character(int2 cursor_position, const TextVarsRuntime *text, int offset)
void SEQUENCER_OT_text_cursor_set(wmOperatorType *ot)
void SEQUENCER_OT_text_edit_mode_toggle(wmOperatorType *ot)
static wmOperatorStatus sequencer_text_cursor_set_modal(bContext *C, wmOperator *, const wmEvent *event)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
CartesianBasis invert(const CartesianBasis &basis)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
float3x3 image_transform_matrix_get(const Scene *scene, const Strip *strip)
void relations_invalidate_cache_raw(Scene *scene, Strip *strip)
Strip * select_active_get(const Scene *scene)
bool time_strip_intersects_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
bool effects_can_render_text(const Strip *strip)
VecBase< float, 2 > float2
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
TextVarsRuntime * runtime
int selection_start_offset
Vector< CharInfo > characters
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_clipboard_text_set(const char *buf, bool selection)
char * WM_clipboard_text_get(bool selection, bool ensure_utf8, int *r_len)