Blender V5.0
editfont.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cerrno>
11#include <cstdlib>
12#include <cstring>
13#include <cwchar>
14#include <fcntl.h>
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_fileops.h"
19#include "BLI_listbase.h"
20#include "BLI_math_geom.h"
21#include "BLI_math_matrix.h"
22#include "BLI_math_vector.h"
23#include "BLI_path_utils.hh"
24#include "BLI_string.h"
26#include "BLI_utildefines.h"
27
28#include "DNA_curve_types.h"
29#include "DNA_object_types.h"
30#include "DNA_scene_types.h"
31#include "DNA_text_types.h"
32#include "DNA_vfont_types.h"
33
34#include "BKE_context.hh"
35#include "BKE_curve.hh"
36#include "BKE_global.hh"
37#include "BKE_layer.hh"
38#include "BKE_lib_id.hh"
39#include "BKE_library.hh"
40#include "BKE_main.hh"
41#include "BKE_object.hh"
42#include "BKE_report.hh"
43#include "BKE_vfont.hh"
44
45#include "BLI_string_utf8.h"
46
47#include "BLT_translation.hh"
48
49#include "DEG_depsgraph.hh"
51
52#include "RNA_access.hh"
53#include "RNA_define.hh"
54
55#include "WM_api.hh"
56#include "WM_types.hh"
57
58#include "ED_curve.hh"
59#include "ED_object.hh"
60#include "ED_outliner.hh"
61#include "ED_screen.hh"
62#include "ED_view3d.hh"
63
64#include "UI_interface.hh"
66
67#include "curve_intern.hh"
68
69#define MAXTEXT 32766
70
71static int kill_selection(Object *obedit, int ins);
72static char *font_select_to_buffer(Object *obedit);
73
74/* -------------------------------------------------------------------- */
77
78static char32_t findaccent(char32_t char1, const char code)
79{
80 char32_t new_char = 0;
81
82 if (char1 == 'a') {
83 if (code == '`') {
84 new_char = 224;
85 }
86 else if (code == 39) {
87 new_char = 225;
88 }
89 else if (code == '^') {
90 new_char = 226;
91 }
92 else if (code == '~') {
93 new_char = 227;
94 }
95 else if (code == '"') {
96 new_char = 228;
97 }
98 else if (code == 'o') {
99 new_char = 229;
100 }
101 else if (code == 'e') {
102 new_char = 230;
103 }
104 else if (code == '-') {
105 new_char = 170;
106 }
107 }
108 else if (char1 == 'c') {
109 if (code == ',') {
110 new_char = 231;
111 }
112 else if (code == '|') {
113 new_char = 162;
114 }
115 else if (code == 'o') {
116 new_char = 169;
117 }
118 }
119 else if (char1 == 'e') {
120 if (code == '`') {
121 new_char = 232;
122 }
123 else if (code == 39) {
124 new_char = 233;
125 }
126 else if (code == '^') {
127 new_char = 234;
128 }
129 else if (code == '"') {
130 new_char = 235;
131 }
132 }
133 else if (char1 == 'i') {
134 if (code == '`') {
135 new_char = 236;
136 }
137 else if (code == 39) {
138 new_char = 237;
139 }
140 else if (code == '^') {
141 new_char = 238;
142 }
143 else if (code == '"') {
144 new_char = 239;
145 }
146 }
147 else if (char1 == 'n') {
148 if (code == '~') {
149 new_char = 241;
150 }
151 }
152 else if (char1 == 'o') {
153 if (code == '`') {
154 new_char = 242;
155 }
156 else if (code == 39) {
157 new_char = 243;
158 }
159 else if (code == '^') {
160 new_char = 244;
161 }
162 else if (code == '~') {
163 new_char = 245;
164 }
165 else if (code == '"') {
166 new_char = 246;
167 }
168 else if (code == '/') {
169 new_char = 248;
170 }
171 else if (code == '-') {
172 new_char = 186;
173 }
174 else if (code == 'e') {
175 new_char = 339;
176 }
177 else if (code == 'c') {
178 new_char = 169;
179 }
180 else if (code == 'r') {
181 new_char = 174;
182 }
183 }
184 else if (char1 == 'r') {
185 if (code == 'o') {
186 new_char = 174;
187 }
188 }
189 else if (char1 == 's') {
190 if (code == 's') {
191 new_char = 167;
192 }
193 }
194 else if (char1 == 't') {
195 if (code == 'm') {
196 new_char = 8482;
197 }
198 }
199 else if (char1 == 'u') {
200 if (code == '`') {
201 new_char = 249;
202 }
203 else if (code == 39) {
204 new_char = 250;
205 }
206 else if (code == '^') {
207 new_char = 251;
208 }
209 else if (code == '"') {
210 new_char = 252;
211 }
212 }
213 else if (char1 == 'y') {
214 if (code == 39) {
215 new_char = 253;
216 }
217 else if (code == '"') {
218 new_char = 255;
219 }
220 }
221 else if (char1 == 'A') {
222 if (code == '`') {
223 new_char = 192;
224 }
225 else if (code == 39) {
226 new_char = 193;
227 }
228 else if (code == '^') {
229 new_char = 194;
230 }
231 else if (code == '~') {
232 new_char = 195;
233 }
234 else if (code == '"') {
235 new_char = 196;
236 }
237 else if (code == 'o') {
238 new_char = 197;
239 }
240 else if (code == 'e') {
241 new_char = 198;
242 }
243 }
244 else if (char1 == 'C') {
245 if (code == ',') {
246 new_char = 199;
247 }
248 }
249 else if (char1 == 'E') {
250 if (code == '`') {
251 new_char = 200;
252 }
253 else if (code == 39) {
254 new_char = 201;
255 }
256 else if (code == '^') {
257 new_char = 202;
258 }
259 else if (code == '"') {
260 new_char = 203;
261 }
262 }
263 else if (char1 == 'I') {
264 if (code == '`') {
265 new_char = 204;
266 }
267 else if (code == 39) {
268 new_char = 205;
269 }
270 else if (code == '^') {
271 new_char = 206;
272 }
273 else if (code == '"') {
274 new_char = 207;
275 }
276 }
277 else if (char1 == 'N') {
278 if (code == '~') {
279 new_char = 209;
280 }
281 }
282 else if (char1 == 'O') {
283 if (code == '`') {
284 new_char = 210;
285 }
286 else if (code == 39) {
287 new_char = 211;
288 }
289 else if (code == '^') {
290 new_char = 212;
291 }
292 else if (code == '~') {
293 new_char = 213;
294 }
295 else if (code == '"') {
296 new_char = 214;
297 }
298 else if (code == '/') {
299 new_char = 216;
300 }
301 else if (code == 'e') {
302 new_char = 141;
303 }
304 }
305 else if (char1 == 'U') {
306 if (code == '`') {
307 new_char = 217;
308 }
309 else if (code == 39) {
310 new_char = 218;
311 }
312 else if (code == '^') {
313 new_char = 219;
314 }
315 else if (code == '"') {
316 new_char = 220;
317 }
318 }
319 else if (char1 == 'Y') {
320 if (code == 39) {
321 new_char = 221;
322 }
323 }
324 else if (char1 == '1') {
325 if (code == '4') {
326 new_char = 188;
327 }
328 if (code == '2') {
329 new_char = 189;
330 }
331 }
332 else if (char1 == '3') {
333 if (code == '4') {
334 new_char = 190;
335 }
336 }
337 else if (char1 == ':') {
338 if (code == '-') {
339 new_char = 247;
340 }
341 }
342 else if (char1 == '-') {
343 if (code == ':') {
344 new_char = 247;
345 }
346 if (code == '|') {
347 new_char = 8224;
348 }
349 if (code == '+') {
350 new_char = 177;
351 }
352 }
353 else if (char1 == '|') {
354 if (code == '-') {
355 new_char = 8224;
356 }
357 if (code == '=') {
358 new_char = 8225;
359 }
360 }
361 else if (char1 == '=') {
362 if (code == '|') {
363 new_char = 8225;
364 }
365 }
366 else if (char1 == '+') {
367 if (code == '-') {
368 new_char = 177;
369 }
370 }
371
372 if (new_char) {
373 return new_char;
374 }
375 return char1;
376}
377
378static int insert_into_textbuf(Object *obedit, uintptr_t c)
379{
380 Curve *cu = static_cast<Curve *>(obedit->data);
381 EditFont *ef = cu->editfont;
382
383 if (ef->len < MAXTEXT - 1) {
384 int x;
385
386 for (x = ef->len; x > ef->pos; x--) {
387 ef->textbuf[x] = ef->textbuf[x - 1];
388 }
389 for (x = ef->len; x > ef->pos; x--) {
390 ef->textbufinfo[x] = ef->textbufinfo[x - 1];
391 }
392 ef->textbuf[ef->pos] = c;
393 ef->textbufinfo[ef->pos] = cu->curinfo;
394 ef->textbufinfo[ef->pos].kern = 0.0f;
395 ef->textbufinfo[ef->pos].mat_nr = obedit->actcol - 1;
396
397 ef->pos++;
398 ef->len++;
399 ef->textbuf[ef->len] = '\0';
400
401 return 1;
402 }
403 return 0;
404}
405
406static void text_update_edited(bContext *C, Object *obedit, const eEditFontMode mode)
407{
408 Curve *cu = static_cast<Curve *>(obedit->data);
409 EditFont *ef = cu->editfont;
410
411 BLI_assert(ef->len >= 0);
412
413 /* Run update first since it can move the cursor. */
414 if (mode == FO_EDIT) {
415 /* Re-tessellate. */
416 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
417 }
418 else {
419 /* Depsgraph runs above, but since we're not tagging for update, call directly. */
420 /* We need evaluated data here. */
423 }
424
425 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
426
428
429 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_SELECT);
431}
432
433static int kill_selection(Object *obedit, int ins) /* ins == new character len */
434{
435 Curve *cu = static_cast<Curve *>(obedit->data);
436 EditFont *ef = cu->editfont;
437 int selend, selstart, direction;
438 int getfrom;
439
440 direction = BKE_vfont_select_get(cu, &selstart, &selend);
441 if (direction) {
442 int size;
443 if (ef->pos >= selstart) {
444 ef->pos = selstart + ins;
445 }
446 if ((direction == -1) && ins) {
447 selstart += ins;
448 selend += ins;
449 }
450 getfrom = selend + 1;
451 size = ef->len - selend; /* This is equivalent to: `(ef->len - getfrom) + 1(null)`. */
452 memmove(ef->textbuf + selstart, ef->textbuf + getfrom, sizeof(*ef->textbuf) * size);
453 memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, sizeof(CharInfo) * size);
454 ef->len -= ((selend - selstart) + 1);
455 ef->selstart = ef->selend = 0;
456 }
457
458 return direction;
459}
460
462{
463 if (G.background) {
464 return;
465 }
466
468 return;
469 }
470 char *buf = font_select_to_buffer(obedit);
471 if (buf == nullptr) {
472 return;
473 }
474 WM_clipboard_text_set(buf, true);
475 MEM_freeN(buf);
476}
477
479
480/* -------------------------------------------------------------------- */
483
484static bool font_paste_wchar(Object *obedit,
485 const char32_t *str,
486 const size_t str_len,
487 /* Optional. */
488 const CharInfo *str_info)
489{
490 Curve *cu = static_cast<Curve *>(obedit->data);
491 EditFont *ef = cu->editfont;
492 int selend, selstart;
493
494 if (BKE_vfont_select_get(cu, &selstart, &selend) == 0) {
495 selstart = selend = 0;
496 }
497
498 /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
499 if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) {
500
501 kill_selection(obedit, 0);
502
503 if (str_len) {
504 int size = (ef->len * sizeof(*ef->textbuf)) - (ef->pos * sizeof(*ef->textbuf)) +
505 sizeof(*ef->textbuf);
506 memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
507 memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(*ef->textbuf));
508
509 memmove(ef->textbufinfo + ef->pos + str_len,
510 ef->textbufinfo + ef->pos,
511 (ef->len - ef->pos + 1) * sizeof(CharInfo));
512 if (str_info) {
513 const short mat_nr_max = std::max(0, obedit->totcol - 1);
514 const CharInfo *info_src = str_info;
515 CharInfo *info_dst = ef->textbufinfo + ef->pos;
516
517 for (int i = 0; i < str_len; i++, info_src++, info_dst++) {
518 *info_dst = *info_src;
519 CLAMP_MAX(info_dst->mat_nr, mat_nr_max);
520 }
521 }
522 else {
523 std::fill_n(ef->textbufinfo + ef->pos, str_len, CharInfo{});
524 }
525
526 ef->len += str_len;
527 ef->pos += str_len;
528 }
529
530 return true;
531 }
532
533 return false;
534}
535
536static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
537{
538 Object *obedit = CTX_data_edit_object(C);
539 bool retval;
540
541 int tmplen;
542
543 char32_t *mem = MEM_malloc_arrayN<char32_t>(str_len + 1, __func__);
544
545 tmplen = BLI_str_utf8_as_utf32(mem, str, str_len + 1);
546
547 retval = font_paste_wchar(obedit, mem, tmplen, nullptr);
548
549 MEM_freeN(mem);
550
551 return retval;
552}
553
555
556/* -------------------------------------------------------------------- */
559
560static char *font_select_to_buffer(Object *obedit)
561{
562 Curve *cu = static_cast<Curve *>(obedit->data);
563 int selstart, selend;
564 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
565 return nullptr;
566 }
567 EditFont *ef = cu->editfont;
568 const char32_t *text_buf = ef->textbuf + selstart;
569 const size_t text_buf_len = selend - selstart;
570
571 const size_t len_utf8 = BLI_str_utf32_as_utf8_len_ex(text_buf, text_buf_len + 1);
572 char *buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
573 BLI_str_utf32_as_utf8(buf, text_buf, len_utf8);
574 return buf;
575}
576
578
579/* -------------------------------------------------------------------- */
582
583static wmOperatorStatus paste_from_file(bContext *C, ReportList *reports, const char *filepath)
584{
585 Object *obedit = CTX_data_edit_object(C);
586 char *strp;
587 size_t filelen;
588 wmOperatorStatus retval;
589
590 strp = static_cast<char *>(BLI_file_read_text_as_mem(filepath, 1, &filelen));
591 if (strp == nullptr) {
592 BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filepath);
593 return OPERATOR_CANCELLED;
594 }
595 strp[filelen] = 0;
596
597 if (font_paste_utf8(C, strp, filelen)) {
598 text_update_edited(C, obedit, FO_EDIT);
599 retval = OPERATOR_FINISHED;
600 }
601 else {
602 BKE_reportf(reports, RPT_ERROR, "File too long %s", filepath);
603 retval = OPERATOR_CANCELLED;
604 }
605
606 MEM_freeN(strp);
607
608 return retval;
609}
610
612{
613 if (op->flag & OP_IS_INVOKE) {
615 return OPERATOR_CANCELLED;
616 }
617 }
618
619 std::string filepath = RNA_string_get(op->ptr, "filepath");
620 wmOperatorStatus retval = paste_from_file(C, op->reports, filepath.c_str());
621 return retval;
622}
623
625 wmOperator *op,
626 const wmEvent * /*event*/)
627{
628 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
629 return paste_from_file_exec(C, op);
630 }
631
633
635}
636
638{
639 /* identifiers */
640 ot->name = "Paste File";
641 ot->description = "Paste contents from file";
642 ot->idname = "FONT_OT_text_paste_from_file";
643
644 /* API callbacks. */
645 ot->exec = paste_from_file_exec;
646 ot->invoke = paste_from_file_invoke;
647 ot->poll = ED_operator_editfont;
648
649 /* flags */
651
652 /* properties */
660}
661
663
664/* -------------------------------------------------------------------- */
667
668static void text_insert_unicode_cancel(bContext *C, void *arg_block, void * /*arg2*/)
669{
670 uiBlock *block = static_cast<uiBlock *>(arg_block);
672}
673
674static void text_insert_unicode_confirm(bContext *C, void *arg_block, void *arg_string)
675{
676 uiBlock *block = static_cast<uiBlock *>(arg_block);
677 char *edit_string = static_cast<char *>(arg_string);
678
679 if (edit_string[0] == 0) {
680 /* Blank text is probably purposeful closure. */
682 return;
683 }
684
685 uint val = strtoul(edit_string, nullptr, 16);
686 if (val > 31 && val < 0x10FFFF) {
687 Object *obedit = CTX_data_edit_object(C);
688 if (obedit) {
689 const char32_t utf32[2] = {val, 0};
690 font_paste_wchar(obedit, utf32, 1, nullptr);
691 text_update_edited(C, obedit, FO_EDIT);
692 }
694 }
695 else {
696 /* Invalid. Clear text and keep dialog open. */
697 edit_string[0] = 0;
698 }
699}
700
701static uiBlock *wm_block_insert_unicode_create(bContext *C, ARegion *region, void *arg_string)
702{
703 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
704 char *edit_string = static_cast<char *>(arg_string);
705
708 const uiStyle *style = UI_style_get_dpi();
709 uiLayout &layout = blender::ui::block_layout(block,
712 0,
713 0,
714 200 * UI_SCALE_FAC,
715 UI_UNIT_Y,
716 0,
717 style);
718
719 uiItemL_ex(&layout, IFACE_("Insert Unicode Character"), ICON_NONE, true, false);
720 layout.label(RPT_("Enter a Unicode codepoint hex value"), ICON_NONE);
721
722 uiBut *text_but = uiDefBut(block,
724 0,
725 "",
726 0,
727 0,
728 100,
729 UI_UNIT_Y,
730 edit_string,
731 0,
732 7,
733 TIP_("Unicode codepoint hex value"));
735 /* Hitting Enter in the text input is treated the same as clicking the Confirm button. */
736 UI_but_func_set(text_but, text_insert_unicode_confirm, block, edit_string);
737
738 layout.separator();
739
740 /* Buttons. */
741
742#ifdef _WIN32
743 const bool windows_layout = true;
744#else
745 const bool windows_layout = false;
746#endif
747
748 uiBut *confirm = nullptr;
749 uiBut *cancel = nullptr;
750 uiLayout *split = &layout.split(0.0f, true);
751 split->column(false);
752
753 if (windows_layout) {
754 confirm = uiDefIconTextBut(
755 block, ButType::But, 0, 0, IFACE_("Insert"), 0, 0, 0, UI_UNIT_Y, nullptr, std::nullopt);
756 split->column(false);
757 }
758
759 cancel = uiDefIconTextBut(
760 block, ButType::But, 0, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, nullptr, std::nullopt);
761
762 if (!windows_layout) {
763 split->column(false);
764 confirm = uiDefIconTextBut(
765 block, ButType::But, 0, 0, IFACE_("Insert"), 0, 0, 0, UI_UNIT_Y, nullptr, std::nullopt);
766 }
767
768 UI_block_func_set(block, nullptr, nullptr, nullptr);
769 UI_but_func_set(confirm, text_insert_unicode_confirm, block, edit_string);
770 UI_but_func_set(cancel, text_insert_unicode_cancel, block, nullptr);
774
775 int bounds_offset[2];
776 bounds_offset[0] = layout.width() * -0.2f;
777 bounds_offset[1] = UI_UNIT_Y * 2.5;
778 UI_block_bounds_set_popup(block, 7 * UI_SCALE_FAC, bounds_offset);
779
780 return block;
781}
782
784 wmOperator * /*op*/,
785 const wmEvent * /*event*/)
786{
787 char *edit_string = MEM_malloc_arrayN<char>(24, __func__);
788 edit_string[0] = 0;
790 return OPERATOR_FINISHED;
791}
792
794{
795 /* identifiers */
796 ot->name = "Insert Unicode";
797 ot->description = "Insert Unicode Character";
798 ot->idname = "FONT_OT_text_insert_unicode";
799
800 /* API callbacks. */
802 ot->poll = ED_operator_editfont;
803
804 /* flags */
806}
807
809
810/* -------------------------------------------------------------------- */
813
815 const TextLine *firstline,
816 int totline,
817 const float offset[3])
818{
819 Main *bmain = CTX_data_main(C);
821 Scene *scene = CTX_data_scene(C);
822 ViewLayer *view_layer = CTX_data_view_layer(C);
823 Curve *cu;
824 Object *obedit;
825 Object *object;
826 const TextLine *tmp;
827 int nchars = 0, nbytes = 0;
828 char *s;
829 int a;
830 const float rot[3] = {0.0f, 0.0f, 0.0f};
831
832 obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, nullptr);
833 BKE_view_layer_synced_ensure(scene, view_layer);
834 object = BKE_view_layer_active_object_get(view_layer);
835
836 /* seems to assume view align ? TODO: look into this, could be an operator option. */
838
839 BKE_object_where_is_calc(depsgraph, scene, obedit);
840
841 add_v3_v3(obedit->loc, offset);
842
843 cu = static_cast<Curve *>(obedit->data);
845 id_us_plus(&cu->vfont->id);
846
847 for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) {
848 size_t nchars_line, nbytes_line;
849 nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
850 nchars += nchars_line + 1;
851 nbytes += nbytes_line + 1;
852 }
853
854 if (cu->str) {
855 MEM_freeN(cu->str);
856 }
857 if (cu->strinfo) {
858 MEM_freeN(cu->strinfo);
859 }
860
861 cu->str = MEM_malloc_arrayN<char>(nbytes + 4, "str");
862 cu->strinfo = MEM_calloc_arrayN<CharInfo>((nchars + 4), "strinfo");
863
864 cu->len = 0;
865 cu->len_char32 = nchars - 1;
866 cu->pos = 0;
867
868 s = cu->str;
869
870 for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
871 size_t nchars_line_dummy, nbytes_line;
872 nchars_line_dummy = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
873 (void)nchars_line_dummy;
874
875 memcpy(s, tmp->line, nbytes_line);
876 s += nbytes_line;
877 cu->len += nbytes_line;
878
879 if (tmp->next) {
880 *s = '\n';
881 s += 1;
882 cu->len += 1;
883 }
884 }
885
886 cu->pos = cu->len_char32;
887 *s = '\0';
888
890}
891
892void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
893{
894 Main *bmain = CTX_data_main(C);
896 float offset[3];
897 int linenum = 0;
898
899 if (!text || !text->lines.first) {
900 return;
901 }
902
903 if (split_lines) {
904 LISTBASE_FOREACH (const TextLine *, line, &text->lines) {
905 /* skip lines with no text, but still make space for them */
906 if (line->line[0] == '\0') {
907 linenum++;
908 continue;
909 }
910
911 /* do the translation */
912 offset[0] = 0;
913 offset[1] = -linenum;
914 offset[2] = 0;
915
916 if (rv3d) {
917 mul_mat3_m4_v3(rv3d->viewinv, offset);
918 }
919
920 txt_add_object(C, line, 1, offset);
921
922 linenum++;
923 }
924 }
925 else {
926 offset[0] = 0.0f;
927 offset[1] = 0.0f;
928 offset[2] = 0.0f;
929
931 static_cast<const TextLine *>(text->lines.first),
933 offset);
934 }
935
938}
939
941
942/* -------------------------------------------------------------------- */
945
947 {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
948 {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""},
949 {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""},
950 {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""},
951 {0, nullptr, 0, nullptr, nullptr},
952};
953
954static wmOperatorStatus set_style(bContext *C, const int style, const bool clear)
955{
956 Object *obedit = CTX_data_edit_object(C);
957 Curve *cu = static_cast<Curve *>(obedit->data);
958 EditFont *ef = cu->editfont;
959 int i, selstart, selend;
960
961 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
962 return OPERATOR_CANCELLED;
963 }
964
965 for (i = selstart; i <= selend; i++) {
966 if (clear) {
967 ef->textbufinfo[i].flag &= ~style;
968 }
969 else {
970 ef->textbufinfo[i].flag |= style;
971 }
972 }
973
974 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
976
977 return OPERATOR_FINISHED;
978}
979
981{
982 const int style = RNA_enum_get(op->ptr, "style");
983 const bool clear = RNA_boolean_get(op->ptr, "clear");
984
985 return set_style(C, style, clear);
986}
987
989{
990 /* identifiers */
991 ot->name = "Set Style";
992 ot->description = "Set font style";
993 ot->idname = "FONT_OT_style_set";
994
995 /* API callbacks. */
996 ot->exec = set_style_exec;
997 ot->poll = ED_operator_editfont;
998
999 /* flags */
1000 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1001
1002 /* properties */
1004 ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
1005 RNA_def_boolean(ot->srna, "clear", false, "Clear", "Clear style rather than setting it");
1006}
1007
1009
1010/* -------------------------------------------------------------------- */
1013
1015{
1016 Object *obedit = CTX_data_edit_object(C);
1017 Curve *cu = static_cast<Curve *>(obedit->data);
1018 int style, clear, selstart, selend;
1019
1020 style = RNA_enum_get(op->ptr, "style");
1021 cu->curinfo.flag ^= style;
1022 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1023 clear = (cu->curinfo.flag & style) == 0;
1024 return set_style(C, style, clear);
1025 }
1026 return OPERATOR_CANCELLED;
1027}
1028
1030{
1031 /* identifiers */
1032 ot->name = "Toggle Style";
1033 ot->description = "Toggle font style";
1034 ot->idname = "FONT_OT_style_toggle";
1035
1036 /* API callbacks. */
1037 ot->exec = toggle_style_exec;
1038 ot->poll = ED_operator_editfont;
1039
1040 /* flags */
1041 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1042
1043 /* properties */
1045 ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
1046}
1047
1049
1050/* -------------------------------------------------------------------- */
1053
1055{
1056 Object *obedit = CTX_data_edit_object(C);
1057 Curve *cu = static_cast<Curve *>(obedit->data);
1058 EditFont *ef = cu->editfont;
1059
1060 if (ef->len) {
1061 ef->selstart = 1;
1062 ef->selend = ef->len;
1063 ef->pos = ef->len;
1064
1067
1068 return OPERATOR_FINISHED;
1069 }
1070 return OPERATOR_CANCELLED;
1071}
1072
1074{
1075 /* identifiers */
1076 ot->name = "Select All";
1077 ot->description = "Select all text";
1078 ot->idname = "FONT_OT_select_all";
1079
1080 /* API callbacks. */
1081 ot->exec = font_select_all_exec;
1082 ot->poll = ED_operator_editfont;
1083
1084 /* flags */
1085 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1086}
1087
1089
1090/* -------------------------------------------------------------------- */
1093
1094static void copy_selection(Object *obedit)
1095{
1096 Curve *cu = static_cast<Curve *>(obedit->data);
1097 int selstart, selend;
1098
1099 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1100 EditFont *ef = cu->editfont;
1101 char *buf = nullptr;
1102 char32_t *text_buf;
1103 size_t len_utf8;
1104
1105 /* internal clipboard (for style) */
1107 ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
1108 BKE_vfont_clipboard_get(&text_buf, nullptr, &len_utf8, nullptr);
1109
1110 /* system clipboard */
1111 buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
1112 if (buf) {
1113 BLI_str_utf32_as_utf8(buf, text_buf, len_utf8 + 1);
1114 WM_clipboard_text_set(buf, false);
1115 MEM_freeN(buf);
1116 }
1117 }
1118}
1119
1121{
1122 Object *obedit = CTX_data_edit_object(C);
1123
1124 copy_selection(obedit);
1125
1126 return OPERATOR_FINISHED;
1127}
1128
1130{
1131 /* identifiers */
1132 ot->name = "Copy Text";
1133 ot->description = "Copy selected text to clipboard";
1134 ot->idname = "FONT_OT_text_copy";
1135
1136 /* API callbacks. */
1137 ot->exec = copy_text_exec;
1138 ot->poll = ED_operator_editfont;
1139}
1140
1142
1143/* -------------------------------------------------------------------- */
1146
1148{
1149 Object *obedit = CTX_data_edit_object(C);
1150 Curve *cu = static_cast<Curve *>(obedit->data);
1151 int selstart, selend;
1152
1153 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
1154 return OPERATOR_CANCELLED;
1155 }
1156
1157 copy_selection(obedit);
1158 kill_selection(obedit, 0);
1159
1160 text_update_edited(C, obedit, FO_EDIT);
1161
1162 return OPERATOR_FINISHED;
1163}
1164
1166{
1167 /* identifiers */
1168 ot->name = "Cut Text";
1169 ot->description = "Cut selected text to clipboard";
1170 ot->idname = "FONT_OT_text_cut";
1171
1172 /* API callbacks. */
1173 ot->exec = cut_text_exec;
1174 ot->poll = ED_operator_editfont;
1175
1176 /* flags */
1177 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1178}
1179
1181
1182/* -------------------------------------------------------------------- */
1185
1186static bool paste_selection(Object *obedit, ReportList *reports)
1187{
1188 char32_t *text_buf;
1189 CharInfo *info_buf;
1190 size_t len;
1191
1192 BKE_vfont_clipboard_get(&text_buf, &info_buf, nullptr, &len);
1193
1194 if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
1195 return true;
1196 }
1197
1198 BKE_report(reports, RPT_WARNING, "Text too long");
1199 return false;
1200}
1201
1203{
1204 const bool selection = RNA_boolean_get(op->ptr, "selection");
1205 Object *obedit = CTX_data_edit_object(C);
1206 wmOperatorStatus retval;
1207 size_t len_utf8;
1208 char32_t *text_buf;
1209
1210 /* Store both clipboards as UTF8 for comparison,
1211 * Give priority to the internal `vfont` clipboard with its #CharInfo text styles
1212 * as long as its synchronized with the systems clipboard. */
1213 struct {
1214 char *buf;
1215 int len;
1216 } clipboard_system = {nullptr}, clipboard_vfont = {nullptr};
1217
1218 /* No need for UTF8 validation as the conversion handles invalid sequences gracefully. */
1219 clipboard_system.buf = WM_clipboard_text_get(selection, false, &clipboard_system.len);
1220
1221 if (clipboard_system.buf == nullptr) {
1222 return OPERATOR_CANCELLED;
1223 }
1224
1225 BKE_vfont_clipboard_get(&text_buf, nullptr, &len_utf8, nullptr);
1226
1227 if (text_buf) {
1228 clipboard_vfont.buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
1229
1230 if (clipboard_vfont.buf == nullptr) {
1231 MEM_freeN(clipboard_system.buf);
1232 return OPERATOR_CANCELLED;
1233 }
1234
1235 BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
1236 }
1237
1238 if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
1240 }
1241 else {
1242 if ((clipboard_system.len <= MAXTEXT) &&
1243 font_paste_utf8(C, clipboard_system.buf, clipboard_system.len))
1244 {
1245 text_update_edited(C, obedit, FO_EDIT);
1246 retval = OPERATOR_FINISHED;
1247 }
1248 else {
1249 BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
1250 retval = OPERATOR_CANCELLED;
1251 }
1252
1253 /* free the existent clipboard buffer */
1255 }
1256
1257 if (retval != OPERATOR_CANCELLED) {
1258 text_update_edited(C, obedit, FO_EDIT);
1259 }
1260
1261 /* cleanup */
1262 if (clipboard_vfont.buf) {
1263 MEM_freeN(clipboard_vfont.buf);
1264 }
1265
1266 MEM_freeN(clipboard_system.buf);
1267
1268 return retval;
1269}
1270
1272{
1273 /* identifiers */
1274 ot->name = "Paste Text";
1275 ot->description = "Paste text from clipboard";
1276 ot->idname = "FONT_OT_text_paste";
1277
1278 /* API callbacks. */
1279 ot->exec = paste_text_exec;
1280 ot->poll = ED_operator_editfont;
1281
1282 /* flags */
1283 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1284
1285 /* properties */
1286 PropertyRNA *prop;
1287 prop = RNA_def_boolean(ot->srna,
1288 "selection",
1289 false,
1290 "Selection",
1291 "Paste text selected elsewhere rather than copied (X11/Wayland only)");
1293}
1294
1296
1297/* -------------------------------------------------------------------- */
1300
1302 {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
1303 {LINE_END, "LINE_END", 0, "Line End", ""},
1304 {TEXT_BEGIN, "TEXT_BEGIN", 0, "Text Begin", ""},
1305 {TEXT_END, "TEXT_END", 0, "Text End", ""},
1306 {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1307 {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1308 {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1309 {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1310 {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
1311 {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
1312 {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
1313 {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
1314 {0, nullptr, 0, nullptr, nullptr},
1315};
1316
1322static bool move_cursor_drop_select(Object *obedit, int dir)
1323{
1324 Curve *cu = static_cast<Curve *>(obedit->data);
1325 int selstart, selend;
1326 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
1327 return false;
1328 }
1329
1330 EditFont *ef = cu->editfont;
1331 if (dir == -1) {
1332 ef->pos = selstart;
1333 }
1334 else if (dir == 1) {
1335 ef->pos = selend + 1;
1336 }
1337 else {
1339 }
1340
1341 /* The caller must clear the selection. */
1342 return true;
1343}
1344
1345static wmOperatorStatus move_cursor(bContext *C, int type, const bool select)
1346{
1348 Object *obedit = CTX_data_edit_object(C);
1349 Curve *cu = static_cast<Curve *>(obedit->data);
1350 EditFont *ef = cu->editfont;
1351 int cursmove = -1;
1352
1353 if ((select) && (ef->selstart == 0)) {
1354 ef->selstart = ef->selend = ef->pos + 1;
1355 }
1356
1357 switch (type) {
1358 case LINE_BEGIN:
1359 cursmove = FO_LINE_BEGIN;
1360 break;
1361 case LINE_END:
1362 cursmove = FO_LINE_END;
1363 break;
1364
1365 case TEXT_BEGIN:
1366 ef->pos = 0;
1367 cursmove = FO_CURS;
1368 break;
1369
1370 case TEXT_END:
1371 ef->pos = ef->len;
1372 cursmove = FO_CURS;
1373 break;
1374
1375 case PREV_WORD: {
1376 if ((select == false) && move_cursor_drop_select(obedit, -1)) {
1377 cursmove = FO_CURS;
1378 }
1379 else {
1380 int pos = ef->pos;
1382 ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1383 ef->pos = pos;
1384 cursmove = FO_CURS;
1385 }
1386 break;
1387 }
1388
1389 case NEXT_WORD: {
1390 if ((select == false) && move_cursor_drop_select(obedit, 1)) {
1391 cursmove = FO_CURS;
1392 }
1393 else {
1394 int pos = ef->pos;
1396 ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1397 ef->pos = pos;
1398 cursmove = FO_CURS;
1399 }
1400 break;
1401 }
1402
1403 case PREV_CHAR: {
1404 if ((select == false) && move_cursor_drop_select(obedit, -1)) {
1405 cursmove = FO_CURS;
1406 }
1407 else {
1409 cursmove = FO_CURS;
1410 }
1411 break;
1412 }
1413 case NEXT_CHAR: {
1414 if ((select == false) && move_cursor_drop_select(obedit, 1)) {
1415 cursmove = FO_CURS;
1416 }
1417 else {
1419 cursmove = FO_CURS;
1420 }
1421 break;
1422 }
1423 case PREV_LINE:
1424 cursmove = FO_CURSUP;
1425 break;
1426
1427 case NEXT_LINE:
1428 cursmove = FO_CURSDOWN;
1429 break;
1430
1431 case PREV_PAGE:
1432 cursmove = FO_PAGEUP;
1433 break;
1434
1435 case NEXT_PAGE:
1436 cursmove = FO_PAGEDOWN;
1437 break;
1438 }
1439
1440 if (cursmove == -1) {
1441 return OPERATOR_CANCELLED;
1442 }
1443
1444 if (ef->pos > ef->len) {
1445 ef->pos = ef->len;
1446 }
1447 else if (ef->pos >= MAXTEXT) {
1448 ef->pos = MAXTEXT;
1449 }
1450 else if (ef->pos < 0) {
1451 ef->pos = 0;
1452 }
1453
1454 /* apply vertical cursor motion to position immediately
1455 * otherwise the selection will lag behind */
1456 if (FO_CURS_IS_MOTION(cursmove)) {
1458 cursmove = FO_CURS;
1459 }
1460
1461 if (select == 0) {
1462 if (ef->selstart) {
1463 ef->selstart = ef->selend = 0;
1465 }
1466 }
1467
1468 if (select) {
1469 ef->selend = ef->pos;
1471 }
1472
1473 text_update_edited(C, obedit, eEditFontMode(cursmove));
1474
1475 return OPERATOR_FINISHED;
1476}
1477
1479{
1480 int type = RNA_enum_get(op->ptr, "type");
1481
1482 return move_cursor(C, type, false);
1483}
1484
1486{
1487 /* identifiers */
1488 ot->name = "Move Cursor";
1489 ot->description = "Move cursor to position type";
1490 ot->idname = "FONT_OT_move";
1491
1492 /* API callbacks. */
1493 ot->exec = move_exec;
1494 ot->poll = ED_operator_editfont;
1495
1496 /* flags */
1497 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1498
1499 /* properties */
1500 RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
1501}
1502
1504
1505/* -------------------------------------------------------------------- */
1508
1510{
1511 int type = RNA_enum_get(op->ptr, "type");
1512
1513 return move_cursor(C, type, true);
1514}
1515
1517{
1518 /* identifiers */
1519 ot->name = "Move Select";
1520 ot->description = "Move the cursor while selecting";
1521 ot->idname = "FONT_OT_move_select";
1522
1523 /* API callbacks. */
1524 ot->exec = move_select_exec;
1525 ot->poll = ED_operator_editfont;
1526
1527 /* flags */
1528 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1529
1530 /* properties */
1531 RNA_def_enum(ot->srna,
1532 "type",
1534 LINE_BEGIN,
1535 "Type",
1536 "Where to move cursor to, to make a selection");
1537}
1538
1540
1541/* -------------------------------------------------------------------- */
1544
1546{
1547 Object *obedit = CTX_data_edit_object(C);
1548 Curve *cu = static_cast<Curve *>(obedit->data);
1549 EditFont *ef = cu->editfont;
1550 float kern, delta = RNA_float_get(op->ptr, "delta");
1551 int selstart, selend;
1552 bool changed = false;
1553
1554 const bool has_select = BKE_vfont_select_get(cu, &selstart, &selend);
1555 if (has_select) {
1556 selstart -= 1;
1557 }
1558 else {
1559 selstart = selend = ef->pos - 1;
1560 }
1561 selstart = max_ii(0, selstart);
1562
1563 for (int i = selstart; i <= selend; i++) {
1564 kern = ef->textbufinfo[i].kern + delta;
1565
1566 if (ef->textbufinfo[i].kern != kern) {
1567 ef->textbufinfo[i].kern = kern;
1568 changed = true;
1569 }
1570 }
1571
1572 if (changed) {
1573 text_update_edited(C, obedit, FO_EDIT);
1574
1575 return OPERATOR_FINISHED;
1576 }
1577 return OPERATOR_CANCELLED;
1578}
1579
1581{
1582 /* identifiers */
1583 ot->name = "Change Spacing";
1584 ot->description = "Change font spacing";
1585 ot->idname = "FONT_OT_change_spacing";
1586
1587 /* API callbacks. */
1588 ot->exec = change_spacing_exec;
1589 ot->poll = ED_operator_editfont;
1590
1591 /* flags */
1592 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1593
1594 /* properties */
1595 RNA_def_float(ot->srna,
1596 "delta",
1597 1.0,
1598 0.0,
1599 0.0,
1600 "Delta",
1601 "Amount to decrease or increase character spacing with",
1602 0.0,
1603 0.0);
1604}
1605
1607
1608/* -------------------------------------------------------------------- */
1611
1613{
1614 Object *obedit = CTX_data_edit_object(C);
1615 Curve *cu = static_cast<Curve *>(obedit->data);
1616 EditFont *ef = cu->editfont;
1617 int character, delta = RNA_int_get(op->ptr, "delta");
1618
1619 if (ef->pos <= 0) {
1620 return OPERATOR_CANCELLED;
1621 }
1622
1623 character = ef->textbuf[ef->pos - 1];
1624 character += delta;
1625 CLAMP(character, 0, 255);
1626
1627 if (character == ef->textbuf[ef->pos - 1]) {
1628 return OPERATOR_CANCELLED;
1629 }
1630
1631 ef->textbuf[ef->pos - 1] = character;
1632
1633 text_update_edited(C, obedit, FO_EDIT);
1634
1635 return OPERATOR_FINISHED;
1636}
1637
1639{
1640 /* identifiers */
1641 ot->name = "Change Character";
1642 ot->description = "Change font character code";
1643 ot->idname = "FONT_OT_change_character";
1644
1645 /* API callbacks. */
1646 ot->exec = change_character_exec;
1647 ot->poll = ED_operator_editfont;
1648
1649 /* flags */
1650 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1651
1652 /* properties */
1653 RNA_def_int(ot->srna,
1654 "delta",
1655 1,
1656 -255,
1657 255,
1658 "Delta",
1659 "Number to increase or decrease character code with",
1660 -255,
1661 255);
1662}
1663
1665
1666/* -------------------------------------------------------------------- */
1669
1671{
1672 Object *obedit = CTX_data_edit_object(C);
1673 Curve *cu = static_cast<Curve *>(obedit->data);
1674 EditFont *ef = cu->editfont;
1675
1676 insert_into_textbuf(obedit, '\n');
1677
1678 ef->selstart = ef->selend = 0;
1679
1680 text_update_edited(C, obedit, FO_EDIT);
1681
1682 return OPERATOR_FINISHED;
1683}
1684
1686{
1687 /* identifiers */
1688 ot->name = "Line Break";
1689 ot->description = "Insert line break at cursor position";
1690 ot->idname = "FONT_OT_line_break";
1691
1692 /* API callbacks. */
1693 ot->exec = line_break_exec;
1694 ot->poll = ED_operator_editfont;
1695
1696 /* flags */
1697 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1698}
1699
1701
1702/* -------------------------------------------------------------------- */
1705
1707 {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1708 {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1709 {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1710 {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1711 {DEL_SELECTION, "SELECTION", 0, "Selection", ""},
1712 {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""},
1713 {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""},
1714 {0, nullptr, 0, nullptr, nullptr},
1715};
1716
1718{
1719 Object *obedit = CTX_data_edit_object(C);
1720 Curve *cu = static_cast<Curve *>(obedit->data);
1721 EditFont *ef = cu->editfont;
1722 int selstart, selend, type = RNA_enum_get(op->ptr, "type");
1723 int range[2] = {0, 0};
1724 bool has_select = false;
1725
1726 if (ef->len == 0) {
1727 return OPERATOR_CANCELLED;
1728 }
1729
1730 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1731 if (type == DEL_NEXT_SEL) {
1732 type = DEL_SELECTION;
1733 }
1734 else if (type == DEL_PREV_SEL) {
1735 type = DEL_SELECTION;
1736 }
1737 has_select = true;
1738 }
1739 else {
1740 if (type == DEL_NEXT_SEL) {
1741 type = DEL_NEXT_CHAR;
1742 }
1743 else if (type == DEL_PREV_SEL) {
1744 type = DEL_PREV_CHAR;
1745 }
1746 }
1747
1748 switch (type) {
1749 case DEL_SELECTION:
1750 if (!kill_selection(obedit, 0)) {
1751 return OPERATOR_CANCELLED;
1752 }
1753 break;
1754 case DEL_PREV_CHAR:
1755 if (ef->pos <= 0) {
1756 return OPERATOR_CANCELLED;
1757 }
1758
1759 range[1] = ef->pos;
1761 range[0] = ef->pos;
1762 break;
1763 case DEL_NEXT_CHAR:
1764 if (ef->pos >= ef->len) {
1765 return OPERATOR_CANCELLED;
1766 }
1767
1768 range[0] = ef->pos;
1769 range[1] = ef->pos;
1770 BLI_str_cursor_step_next_utf32(ef->textbuf, ef->len, &range[1]);
1771 break;
1772 case DEL_NEXT_WORD: {
1773 int pos = ef->pos;
1775 ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1776 range[0] = ef->pos;
1777 range[1] = pos;
1778 break;
1779 }
1780
1781 case DEL_PREV_WORD: {
1782 int pos = ef->pos;
1784 ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1785 range[0] = pos;
1786 range[1] = ef->pos;
1787 ef->pos = pos;
1788 break;
1789 }
1790 default:
1791 return OPERATOR_CANCELLED;
1792 }
1793
1794 if (range[0] != range[1]) {
1795 BLI_assert(range[0] < range[1]);
1796 int len_remove = range[1] - range[0];
1797 int len_tail = ef->len - range[1];
1798 if (has_select) {
1799 for (int i = 0; i < 2; i++) {
1800 int *sel = i ? &ef->selend : &ef->selstart;
1801 if (*sel <= range[0]) {
1802 /* pass */
1803 }
1804 else if (*sel >= range[1]) {
1805 *sel -= len_remove;
1806 }
1807 else {
1808 BLI_assert(*sel < range[1]);
1809 /* pass */
1810 *sel = range[0];
1811 }
1812 }
1813 }
1814
1815 memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail);
1816 memmove(&ef->textbufinfo[range[0]],
1817 &ef->textbufinfo[range[1]],
1818 sizeof(*ef->textbufinfo) * len_tail);
1819
1820 ef->len -= len_remove;
1821 ef->textbuf[ef->len] = '\0';
1822
1824 }
1825
1826 text_update_edited(C, obedit, FO_EDIT);
1827
1828 return OPERATOR_FINISHED;
1829}
1830
1832{
1833 /* identifiers */
1834 ot->name = "Delete";
1835 ot->description = "Delete text by cursor position";
1836 ot->idname = "FONT_OT_delete";
1837
1838 /* API callbacks. */
1839 ot->exec = delete_exec;
1840 ot->poll = ED_operator_editfont;
1841
1842 /* flags */
1843 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1844
1845 /* properties */
1846 RNA_def_enum(ot->srna,
1847 "type",
1850 "Type",
1851 "Which part of the text to delete");
1852}
1853
1855
1856/* -------------------------------------------------------------------- */
1859
1861{
1862 Object *obedit = CTX_data_edit_object(C);
1863 char32_t *inserted_text;
1864 int a, len;
1865
1866 if (!RNA_struct_property_is_set(op->ptr, "text")) {
1867 return OPERATOR_CANCELLED;
1868 }
1869
1870 std::string inserted_utf8 = RNA_string_get(op->ptr, "text");
1871 len = BLI_strlen_utf8(inserted_utf8.c_str());
1872
1873 inserted_text = MEM_calloc_arrayN<char32_t>((len + 1), "FONT_insert_text");
1874 len = BLI_str_utf8_as_utf32(inserted_text, inserted_utf8.c_str(), MAXTEXT);
1875
1876 for (a = 0; a < len; a++) {
1877 insert_into_textbuf(obedit, inserted_text[a]);
1878 }
1879
1880 MEM_freeN(inserted_text);
1881
1882 kill_selection(obedit, len);
1883 text_update_edited(C, obedit, FO_EDIT);
1884
1885 return OPERATOR_FINISHED;
1886}
1887
1889{
1890 Object *obedit = CTX_data_edit_object(C);
1891 Curve *cu = static_cast<Curve *>(obedit->data);
1892 EditFont *ef = cu->editfont;
1893 static bool accentcode = false;
1894 const bool alt = event->modifier & KM_ALT;
1895 const bool shift = event->modifier & KM_SHIFT;
1896 const bool ctrl = event->modifier & KM_CTRL;
1897 char32_t insert_char_override = 0;
1898 char32_t inserted_text[2] = {0};
1899
1900 if (RNA_struct_property_is_set(op->ptr, "text")) {
1901 return insert_text_exec(C, op);
1902 }
1903
1904 if (RNA_struct_property_is_set(op->ptr, "accent")) {
1905 if (ef->len != 0 && ef->pos > 0) {
1906 accentcode = true;
1907 }
1908 return OPERATOR_FINISHED;
1909 }
1910
1911 if (event->type == EVT_BACKSPACEKEY) {
1912 if (alt && ef->len != 0 && ef->pos > 0) {
1913 accentcode = true;
1914 }
1915 return OPERATOR_PASS_THROUGH;
1916 }
1917
1918 /* Tab typically exit edit-mode, but we allow it to be typed using modifier keys. */
1919 if (event->type == EVT_TABKEY) {
1920 if ((alt || ctrl || shift) == 0) {
1921 return OPERATOR_PASS_THROUGH;
1922 }
1923 insert_char_override = '\t';
1924 }
1925
1926 if (insert_char_override || event->utf8_buf[0]) {
1927 if (insert_char_override) {
1928 /* Handle case like TAB ('\t'). */
1929 inserted_text[0] = insert_char_override;
1930 insert_into_textbuf(obedit, insert_char_override);
1931 text_update_edited(C, obedit, FO_EDIT);
1932 }
1933 else {
1934 BLI_assert(event->utf8_buf[0]);
1935 if (accentcode) {
1936 if (ef->pos > 0) {
1937 inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1],
1939 ef->textbuf[ef->pos - 1] = inserted_text[0];
1940 }
1941 accentcode = false;
1942 }
1943 else if (event->utf8_buf[0]) {
1944 inserted_text[0] = BLI_str_utf8_as_unicode_or_error(event->utf8_buf);
1945 insert_into_textbuf(obedit, inserted_text[0]);
1946 accentcode = false;
1947 }
1948 else {
1949 BLI_assert(0);
1950 }
1951
1952 kill_selection(obedit, 1);
1953 text_update_edited(C, obedit, FO_EDIT);
1954 }
1955 }
1956 else {
1957 return OPERATOR_PASS_THROUGH;
1958 }
1959
1960 if (inserted_text[0]) {
1961 /* Store as UTF8 in RNA string. */
1962 char inserted_utf8[8] = {0};
1963
1964 BLI_str_utf32_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8));
1965 RNA_string_set(op->ptr, "text", inserted_utf8);
1966 }
1967
1968 return OPERATOR_FINISHED;
1969}
1970
1972{
1973 /* identifiers */
1974 ot->name = "Insert Text";
1975 ot->description = "Insert text at cursor position";
1976 ot->idname = "FONT_OT_text_insert";
1977
1978 /* API callbacks. */
1979 ot->exec = insert_text_exec;
1980 ot->invoke = insert_text_invoke;
1981 ot->poll = ED_operator_editfont;
1982
1983 /* flags */
1984 ot->flag = OPTYPE_UNDO;
1985
1986 /* properties */
1987 RNA_def_string(ot->srna, "text", nullptr, 0, "Text", "Text to insert at the cursor position");
1989 ot->srna,
1990 "accent",
1991 false,
1992 "Accent Mode",
1993 "Next typed character will strike through previous, for special character input");
1994}
1995
1997
1998/* -------------------------------------------------------------------- */
2001
2002static int font_cursor_text_index_from_event(bContext *C, Object *obedit, const wmEvent *event)
2003{
2004 /* Calculate a plane from the text object's orientation. */
2005 float plane[4];
2007 plane, obedit->object_to_world().location(), obedit->object_to_world().ptr()[2]);
2008
2009 /* Convert Mouse location in region to 3D location in world space. */
2010 float mal_fl[2] = {float(event->mval[0]), float(event->mval[1])};
2011 float mouse_loc[3];
2012 ED_view3d_win_to_3d_on_plane(CTX_wm_region(C), plane, mal_fl, true, mouse_loc);
2013
2014 /* Convert to object space and scale by font size. */
2015 mul_m4_v3(obedit->world_to_object().ptr(), mouse_loc);
2016
2017 const blender::float2 cursor_location = {mouse_loc[0], mouse_loc[1]};
2018 return BKE_vfont_cursor_to_text_index(obedit, cursor_location);
2019}
2020
2021static void font_cursor_set_apply(bContext *C, const wmEvent *event)
2022{
2025 Curve *cu = static_cast<Curve *>(ob->data);
2026 EditFont *ef = cu->editfont;
2027 BLI_assert(ef->len >= 0);
2028
2029 const int string_offset = font_cursor_text_index_from_event(C, ob, event);
2030
2031 if (string_offset > ef->len || string_offset < 0) {
2032 return;
2033 }
2034
2035 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
2036
2038
2039 if (!ef->selboxes && (ef->selstart == 0)) {
2040 if (ef->pos == 0) {
2041 ef->selstart = ef->selend = 1;
2042 }
2043 else {
2044 ef->selstart = ef->selend = string_offset + 1;
2045 }
2046 }
2047 ef->selend = string_offset;
2048 ef->pos = string_offset;
2049
2050 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
2052}
2053
2055 wmOperator *op,
2056 const wmEvent *event)
2057{
2058 Object *obedit = CTX_data_active_object(C);
2059 Curve *cu = static_cast<Curve *>(obedit->data);
2060 EditFont *ef = cu->editfont;
2061
2062 font_cursor_set_apply(C, event);
2063 ef->selstart = 0;
2064 ef->selend = 0;
2066
2068}
2069
2071 wmOperator * /*op*/,
2072 const wmEvent *event)
2073{
2074 switch (event->type) {
2075 case LEFTMOUSE:
2076 if (event->val == KM_RELEASE) {
2077 font_cursor_set_apply(C, event);
2078 return OPERATOR_FINISHED;
2079 }
2080 break;
2081 case MIDDLEMOUSE:
2082 case RIGHTMOUSE:
2083 return OPERATOR_FINISHED;
2084 case MOUSEMOVE:
2085 font_cursor_set_apply(C, event);
2086 break;
2087 default: {
2088 break;
2089 }
2090 }
2092}
2093
2095{
2096 /* identifiers */
2097 ot->name = "Set Selection";
2098 ot->idname = "FONT_OT_selection_set";
2099 ot->description = "Set cursor selection";
2100
2101 /* API callbacks. */
2102 ot->invoke = font_selection_set_invoke;
2104 ot->poll = ED_operator_editfont;
2105}
2106
2108
2109/* -------------------------------------------------------------------- */
2112
2114{
2115 Object *obedit = CTX_data_edit_object(C);
2116 Curve *cu = static_cast<Curve *>(obedit->data);
2117 EditFont *ef = cu->editfont;
2118
2120 ef->pos = ef->selend;
2121
2122 /* XXX: Text object selection start is 1-based, unlike text processing elsewhere in Blender. */
2123 ef->selstart += 1;
2124
2126 text_update_edited(C, obedit, FO_CURS);
2127
2128 return OPERATOR_FINISHED;
2129}
2130
2132{
2133 /* identifiers */
2134 ot->name = "Select Word";
2135 ot->idname = "FONT_OT_select_word";
2136 ot->description = "Select word under cursor";
2137
2138 /* API callbacks. */
2139 ot->exec = font_select_word_exec;
2140 ot->poll = ED_operator_editfont;
2141}
2142
2144
2145/* -------------------------------------------------------------------- */
2148
2150{
2151 Object *obedit = CTX_data_active_object(C);
2152 Curve *cu = static_cast<Curve *>(obedit->data);
2153 int i;
2154
2155 if (cu->totbox < 256) {
2156 for (i = cu->totbox; i > cu->actbox; i--) {
2157 cu->tb[i] = cu->tb[i - 1];
2158 }
2159 cu->tb[cu->actbox] = cu->tb[cu->actbox - 1];
2160 cu->actbox++;
2161 cu->totbox++;
2162 }
2163
2164 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
2166 return OPERATOR_FINISHED;
2167}
2168
2170{
2171 /* identifiers */
2172 ot->name = "Add Text Box";
2173 ot->description = "Add a new text box";
2174 ot->idname = "FONT_OT_textbox_add";
2175
2176 /* API callbacks. */
2177 ot->exec = textbox_add_exec;
2179
2180 /* flags */
2181 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2182}
2183
2185
2186/* -------------------------------------------------------------------- */
2189
2191{
2192 Object *obedit = CTX_data_active_object(C);
2193 Curve *cu = static_cast<Curve *>(obedit->data);
2194 int i;
2195 int index = RNA_int_get(op->ptr, "index");
2196
2197 if (cu->totbox > 1) {
2198 for (i = index; i < cu->totbox; i++) {
2199 cu->tb[i] = cu->tb[i + 1];
2200 }
2201 cu->totbox--;
2202 if (cu->actbox >= index) {
2203 cu->actbox--;
2204 }
2205 }
2206
2207 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
2209
2210 return OPERATOR_FINISHED;
2211}
2212
2214{
2215 /* identifiers */
2216 ot->name = "Remove Text Box";
2217 ot->description = "Remove the text box";
2218 ot->idname = "FONT_OT_textbox_remove";
2219
2220 /* API callbacks. */
2221 ot->exec = textbox_remove_exec;
2223
2224 /* flags */
2225 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2226
2227 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
2228}
2229
2231
2232/* -------------------------------------------------------------------- */
2235
2237{
2238 Curve *cu = static_cast<Curve *>(obedit->data);
2239 EditFont *ef = cu->editfont;
2240
2241 if (ef == nullptr) {
2242 ef = cu->editfont = MEM_callocN<EditFont>("editfont");
2243
2244 ef->textbuf = static_cast<char32_t *>(
2245 MEM_callocN((MAXTEXT + 4) * sizeof(*ef->textbuf), "texteditbuf"));
2246 ef->textbufinfo = MEM_calloc_arrayN<CharInfo>((MAXTEXT + 4), "texteditbufinfo");
2247 }
2248
2249 /* Convert the original text to chat32_t. */
2250 if (cu->str) {
2251 int len_char32 = BLI_str_utf8_as_utf32(ef->textbuf, cu->str, MAXTEXT + 4);
2252 BLI_assert(len_char32 == cu->len_char32);
2253 ef->len = len_char32;
2254 BLI_assert(ef->len >= 0);
2255 }
2256
2257 /* Old files may not have this initialized (v2.34). Leaving zeroed is OK. */
2258 if (cu->strinfo) {
2259 memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
2260 }
2261
2262 ef->pos = cu->pos;
2263 ef->pos = std::min(ef->pos, ef->len);
2264
2265 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
2266
2267 /* Other vars */
2268 ef->selstart = cu->selstart;
2269 ef->selend = cu->selend;
2270
2271 /* text may have been modified by Python */
2273}
2274
2276{
2277 Curve *cu = static_cast<Curve *>(obedit->data);
2278 EditFont *ef = cu->editfont;
2279
2280 /* Free the old curve string */
2281 if (cu->str) {
2282 MEM_freeN(cu->str);
2283 }
2284
2285 /* Calculate the actual string length in UTF8 variable characters. */
2286 cu->len_char32 = ef->len;
2288
2289 /* Alloc memory for UTF8 variable char length string. */
2290 cu->str = MEM_malloc_arrayN<char>(cu->len + sizeof(char32_t), "str");
2291
2292 /* Copy the wchar to UTF8. */
2293 BLI_str_utf32_as_utf8(cu->str, ef->textbuf, cu->len + 1);
2294
2295 if (cu->strinfo) {
2296 MEM_freeN(cu->strinfo);
2297 }
2298 cu->strinfo = MEM_calloc_arrayN<CharInfo>((cu->len_char32 + 4), "texteditinfo");
2299 memcpy(cu->strinfo, ef->textbufinfo, cu->len_char32 * sizeof(CharInfo));
2300
2301 /* Other vars */
2302 cu->pos = ef->pos;
2303 cu->selstart = ef->selstart;
2304 cu->selend = ef->selend;
2305}
2306
2308{
2310}
2311
2313
2314/* -------------------------------------------------------------------- */
2317
2319 {CASE_LOWER, "LOWER", 0, "Lower", ""},
2320 {CASE_UPPER, "UPPER", 0, "Upper", ""},
2321 {0, nullptr, 0, nullptr, nullptr},
2322};
2323
2325{
2326 Object *obedit = CTX_data_edit_object(C);
2327 Curve *cu = static_cast<Curve *>(obedit->data);
2328 int selstart, selend;
2329
2330 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
2331 EditFont *ef = cu->editfont;
2332 char32_t *str = &ef->textbuf[selstart];
2333
2334 for (int len = (selend - selstart) + 1; len; len--, str++) {
2335 *str = (ccase == CASE_LOWER) ? BLI_str_utf32_char_to_lower(*str) :
2337 }
2338
2339 text_update_edited(C, obedit, FO_EDIT);
2340 }
2341
2342 return OPERATOR_FINISHED;
2343}
2344
2346{
2347 return set_case(C, RNA_enum_get(op->ptr, "case"));
2348}
2349
2351{
2352 PropertyRNA *prop;
2353
2354 /* identifiers */
2355 ot->name = "Set Case";
2356 ot->description = "Set font case";
2357 ot->idname = "FONT_OT_case_set";
2358
2359 /* API callbacks. */
2360 ot->exec = set_case_exec;
2361 ot->poll = ED_operator_editfont;
2362
2363 /* flags */
2364 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2365
2366 /* properties */
2367 prop = RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
2369}
2370
2372
2373/* -------------------------------------------------------------------- */
2376
2378{
2379 Object *obedit = CTX_data_edit_object(C);
2380 Curve *cu = static_cast<Curve *>(obedit->data);
2381 EditFont *ef = cu->editfont;
2382 int ccase = CASE_UPPER;
2383
2384 const char32_t *str = ef->textbuf;
2385 while (*str) {
2386 if (*str >= 'a' && *str <= 'z') {
2387 ccase = CASE_LOWER;
2388 break;
2389 }
2390
2391 str++;
2392 }
2393
2394 return set_case(C, ccase);
2395}
2396
2398{
2399 /* identifiers */
2400 ot->name = "Toggle Case";
2401 ot->description = "Toggle font case";
2402 ot->idname = "FONT_OT_case_toggle";
2403
2404 /* API callbacks. */
2405 ot->exec = toggle_case_exec;
2406 ot->poll = ED_operator_editfont;
2407
2408 /* flags */
2409 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2410}
2411
2412/* **************** Open Font ************** */
2413
2415{
2416 PropertyPointerRNA *pprop;
2417
2418 op->customdata = pprop = MEM_new<PropertyPointerRNA>("OpenPropertyPointerRNA");
2420}
2421
2422static void font_open_cancel(bContext * /*C*/, wmOperator *op)
2423{
2424 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2425 op->customdata = nullptr;
2426}
2427
2429{
2430 Main *bmain = CTX_data_main(C);
2431 VFont *font;
2432 PropertyPointerRNA *pprop;
2433 char filepath[FILE_MAX];
2434 RNA_string_get(op->ptr, "filepath", filepath);
2435
2436 font = BKE_vfont_load(bmain, filepath);
2437
2438 if (!font) {
2439 if (op->customdata) {
2440 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2441 }
2442 return OPERATOR_CANCELLED;
2443 }
2444
2445 if (!op->customdata) {
2447 }
2448
2449 /* hook into UI */
2450 pprop = static_cast<PropertyPointerRNA *>(op->customdata);
2451
2452 if (pprop->prop) {
2453 /* when creating new ID blocks, use is already 1, but RNA
2454 * pointer use also increases user, so this compensates it */
2455 id_us_min(&font->id);
2456
2457 PointerRNA idptr = RNA_id_pointer_create(&font->id);
2458 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, nullptr);
2459 RNA_property_update(C, &pprop->ptr, pprop->prop);
2460 }
2461
2462 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2463
2464 return OPERATOR_FINISHED;
2465}
2466
2468{
2469 VFont *vfont = nullptr;
2470 char filepath[FILE_MAX];
2471
2472 PointerRNA idptr;
2473 PropertyPointerRNA *pprop;
2474
2476
2477 /* hook into UI */
2478 pprop = static_cast<PropertyPointerRNA *>(op->customdata);
2479
2480 if (pprop->prop) {
2481 idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
2482 vfont = (VFont *)idptr.owner_id;
2483 }
2484
2485 PropertyRNA *prop_filepath = RNA_struct_find_property(op->ptr, "filepath");
2486 if (RNA_property_is_set(op->ptr, prop_filepath)) {
2487 return font_open_exec(C, op);
2488 }
2489
2490 if (vfont && !BKE_vfont_is_builtin(vfont)) {
2491 STRNCPY(filepath, vfont->filepath);
2492 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
2493 }
2494 else {
2495 STRNCPY(filepath, U.fontdir);
2496 BLI_path_slash_ensure(filepath, sizeof(filepath));
2497 /* The file selector will expand the blend-file relative prefix. */
2498 }
2499 RNA_property_string_set(op->ptr, prop_filepath, filepath);
2500
2502
2504}
2505
2507{
2508 /* identifiers */
2509 ot->name = "Open Font";
2510 ot->idname = "FONT_OT_open";
2511 ot->description = "Load a new font from a file";
2512
2513 /* API callbacks. */
2514 ot->exec = font_open_exec;
2515 ot->invoke = open_invoke;
2516 ot->cancel = font_open_cancel;
2517
2518 /* flags */
2519 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2520
2521 /* properties */
2529}
2530
2532
2533/* -------------------------------------------------------------------- */
2536
2538{
2539 VFont *builtin_font;
2540
2541 PropertyPointerRNA pprop;
2542
2544
2545 if (pprop.prop == nullptr) {
2546 BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
2547 return OPERATOR_CANCELLED;
2548 }
2549
2550 builtin_font = BKE_vfont_builtin_ensure();
2551
2552 PointerRNA idptr = RNA_id_pointer_create(&builtin_font->id);
2553 RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, nullptr);
2554 RNA_property_update(C, &pprop.ptr, pprop.prop);
2555
2556 return OPERATOR_FINISHED;
2557}
2558
2560{
2561 /* identifiers */
2562 ot->name = "Unlink";
2563 ot->idname = "FONT_OT_unlink";
2564 ot->description = "Unlink active font data-block";
2565
2566 /* API callbacks. */
2567 ot->exec = font_unlink_exec;
2568}
2569
2571 bContext *C,
2572 const int mval[2],
2573 /* NOTE: `params->deselect_all` is ignored as only one text-box is active at once. */
2575{
2577 Object *obedit = CTX_data_edit_object(C);
2578 Curve *cu = static_cast<Curve *>(obedit->data);
2579 /* bias against the active, in pixels, allows cycling */
2580 const float active_bias_px = 4.0f;
2581 const float mval_fl[2] = {float(mval[0]), float(mval[1])};
2582 const int i_actbox = max_ii(0, cu->actbox - 1);
2583 int i_iter, actbox_select = -1;
2584 const float dist = ED_view3d_select_dist_px();
2585 float dist_sq_best = dist * dist;
2586
2588
2590
2591 /* currently only select active */
2592 (void)params;
2593
2594 for (i_iter = 0; i_iter < cu->totbox; i_iter++) {
2595 int i = (i_iter + i_actbox) % cu->totbox;
2596 float dist_sq_min;
2597 int j, j_prev;
2598
2599 float obedit_co[4][3];
2600 float screen_co[4][2];
2601 rctf rect;
2602 int project_ok = 0;
2603
2604 BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect);
2605
2606 copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f);
2607 copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f);
2608 copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f);
2609 copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f);
2610
2611 for (j = 0; j < 4; j++) {
2613 vc.region, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK)
2614 {
2615 project_ok |= (1 << j);
2616 }
2617 }
2618
2619 dist_sq_min = dist_sq_best;
2620 for (j = 0, j_prev = 3; j < 4; j_prev = j++) {
2621 if ((project_ok & (1 << j)) && (project_ok & (1 << j_prev))) {
2622 const float dist_test_sq = dist_squared_to_line_segment_v2(
2623 mval_fl, screen_co[j_prev], screen_co[j]);
2624 dist_sq_min = std::min(dist_sq_min, dist_test_sq);
2625 }
2626 }
2627
2628 /* Bias in pixels to cycle selection. */
2629 if (i_iter == 0) {
2630 dist_sq_min += active_bias_px;
2631 }
2632
2633 if (dist_sq_min < dist_sq_best) {
2634 dist_sq_best = dist_sq_min;
2635 actbox_select = i + 1;
2636 }
2637 }
2638
2639 if (actbox_select != -1) {
2640 if (cu->actbox != actbox_select) {
2641 cu->actbox = actbox_select;
2643 /* TODO: support #ID_RECALC_SELECT. */
2644 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_SYNC_TO_EVAL);
2645 }
2646 return true;
2647 }
2648 return false;
2649}
2650
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_curve_editfont_free(Curve *cu)
Definition curve.cc:316
void BKE_curve_rect_from_textbox(const Curve *cu, const TextBox *tb, rctf *r_rect)
Definition curve.cc:5421
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void id_us_plus(ID *id)
Definition lib_id.cc:358
void id_us_min(ID *id)
Definition lib_id.cc:366
General operations, lookup, etc. for blender objects.
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
int BKE_vfont_select_get(const Curve *cu, int *r_start, int *r_end)
Definition vfont.cc:408
eEditFontMode
Definition BKE_vfont.hh:77
@ FO_PAGEUP
Definition BKE_vfont.hh:83
@ FO_EDIT
Definition BKE_vfont.hh:78
@ FO_CURSUP
Definition BKE_vfont.hh:80
@ FO_LINE_END
Definition BKE_vfont.hh:86
@ FO_LINE_BEGIN
Definition BKE_vfont.hh:85
@ FO_SELCHANGE
Definition BKE_vfont.hh:87
@ FO_CURS
Definition BKE_vfont.hh:79
@ FO_CURSDOWN
Definition BKE_vfont.hh:81
@ FO_PAGEDOWN
Definition BKE_vfont.hh:84
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, size_t len)
Definition vfont.cc:479
#define FO_CURS_IS_MOTION(mode)
Definition BKE_vfont.hh:91
VFont * BKE_vfont_load(Main *bmain, const char *filepath)
Definition vfont.cc:303
bool BKE_vfont_is_builtin(const VFont *vfont)
Definition vfont.cc:277
void BKE_vfont_select_clamp(Curve *cu)
Definition vfont.cc:447
void BKE_vfont_clipboard_get(char32_t **r_text_buf, CharInfo **r_info_buf, size_t *r_len_utf8, size_t *r_len_utf32)
Definition vfont.cc:509
VFont * BKE_vfont_builtin_ensure()
Definition vfont.cc:386
bool BKE_vfont_to_curve(Object *ob, eEditFontMode mode)
int BKE_vfont_cursor_to_text_index(Object *ob, const blender::float2 &cursor_location)
void BKE_vfont_clipboard_free()
Definition vfont.cc:471
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
void * BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size)
Definition storage.cc:511
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE int max_ii(int a, int b)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:217
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition math_geom.cc:291
void mul_m4_v3(const float M[4][4], float r[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void add_v3_v3(float r[3], const float a[3])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
bool BLI_str_cursor_step_prev_utf32(const char32_t *str, int str_maxlen, int *pos)
void BLI_str_cursor_step_utf32(const char32_t *str, int str_maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
@ STRCUR_DIR_NEXT
@ STRCUR_DIR_PREV
void BLI_str_cursor_step_bounds_utf32(const char32_t *str, int str_maxlen, int pos, int *r_start, int *r_end)
bool BLI_str_cursor_step_next_utf32(const char32_t *str, int str_maxlen, int *pos)
@ STRCUR_JUMP_DELIM
size_t size_t size_t BLI_str_utf32_as_utf8_len_ex(const char32_t *src, size_t src_maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char32_t BLI_str_utf32_char_to_lower(char32_t wc)
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
size_t size_t BLI_str_utf32_as_utf8(char *__restrict dst, const char32_t *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char32_t BLI_str_utf32_char_to_upper(char32_t wc)
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, const char *__restrict src_c, size_t dst_w_maxncpy) ATTR_NONNULL(1
unsigned int BLI_str_utf8_as_unicode_or_error(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL(1
unsigned int uint
#define CLAMP(a, b, c)
#define CLAMP_MAX(a, c)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_TEXT
#define RPT_(msgid)
#define TIP_(msgid)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition DNA_ID.h:688
@ CU_CHINFO_UNDERLINE
@ CU_CHINFO_BOLD
@ CU_CHINFO_ITALIC
@ CU_CHINFO_SMALLCAPS
Object is a sort of wrapper for general info.
@ OB_FONT
@ FILE_SORT_DEFAULT
@ FILE_SORT_ALPHA
@ FILE_SPECIAL
@ FILE_TYPE_TEXT
@ FILE_TYPE_FOLDER
@ FILE_TYPE_FTFONT
@ FILE_IMGDISPLAY
@ FILE_DEFAULTDISPLAY
#define UI_SCALE_FAC
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_outliner_select_sync_from_object_tag(bContext *C)
bool ED_operator_object_active_editable_font(bContext *C)
bool ED_operator_editfont(bContext *C)
float ED_view3d_select_dist_px()
@ V3D_PROJ_TEST_CLIP_BB
Definition ED_view3d.hh:280
eV3DProjStatus ED_view3d_project_float_object(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:256
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
bool ED_view3d_win_to_3d_on_plane(const ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
uiBut * uiDefIconTextBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_type, int retval, int icon, blender::StringRef str, int x, int y, short width, short height, void *poin, std::optional< blender::StringRef > tip)
#define UI_UNIT_Y
@ UI_BLOCK_NUMSELECT
@ UI_BLOCK_KEEP_OPEN
@ UI_BLOCK_NO_WIN_CLIP
void UI_block_theme_style_set(uiBlock *block, char theme_style)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_ACTIVATE_ON_INIT
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition interface.cc:653
const uiStyle * UI_style_get_dpi()
void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free, bool can_refresh)
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
void UI_but_drawflag_disable(uiBut *but, int flag)
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
@ UI_BLOCK_THEME_STYLE_POPUP
void UI_block_flag_enable(uiBlock *block, int flag)
@ UI_BUT_TEXT_LEFT
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_flag_enable(uiBut *but, int flag)
uiBut * uiItemL_ex(uiLayout *layout, blender::StringRef name, int icon, bool highlight, bool redalert)
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1121
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ WM_CAPABILITY_CLIPBOARD_PRIMARY
Definition WM_api.hh:189
@ FILE_OPENFILE
Definition WM_api.hh:1133
#define NC_GEOM
Definition WM_types.hh:393
@ KM_CTRL
Definition WM_types.hh:279
@ KM_ALT
Definition WM_types.hh:280
@ KM_SHIFT
Definition WM_types.hh:278
#define ND_DATA
Definition WM_types.hh:509
@ KM_RELEASE
Definition WM_types.hh:312
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
#define U
#define NEXT_CHAR(fmt)
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
@ CASE_LOWER
@ CASE_UPPER
@ DEL_SELECTION
@ DEL_PREV_WORD
@ DEL_PREV_SEL
@ DEL_PREV_CHAR
@ DEL_NEXT_WORD
@ DEL_NEXT_CHAR
@ DEL_NEXT_SEL
@ NEXT_LINE
@ TEXT_BEGIN
@ TEXT_END
@ LINE_BEGIN
@ PREV_WORD
@ PREV_LINE
@ PREV_CHAR
@ LINE_END
@ PREV_PAGE
@ NEXT_PAGE
@ NEXT_WORD
static uiBlock * wm_block_insert_unicode_create(bContext *C, ARegion *region, void *arg_string)
Definition editfont.cc:701
void FONT_OT_textbox_add(wmOperatorType *ot)
Definition editfont.cc:2169
static void font_open_cancel(bContext *, wmOperator *op)
Definition editfont.cc:2422
static wmOperatorStatus set_style_exec(bContext *C, wmOperator *op)
Definition editfont.cc:980
void FONT_OT_style_toggle(wmOperatorType *ot)
Definition editfont.cc:1029
void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
Definition editfont.cc:892
static wmOperatorStatus set_style(bContext *C, const int style, const bool clear)
Definition editfont.cc:954
void FONT_OT_text_copy(wmOperatorType *ot)
Definition editfont.cc:1129
static wmOperatorStatus font_select_all_exec(bContext *C, wmOperator *)
Definition editfont.cc:1054
void FONT_OT_line_break(wmOperatorType *ot)
Definition editfont.cc:1685
void FONT_OT_select_word(wmOperatorType *ot)
Definition editfont.cc:2131
static void copy_selection(Object *obedit)
Definition editfont.cc:1094
void FONT_OT_unlink(wmOperatorType *ot)
Definition editfont.cc:2559
static wmOperatorStatus delete_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1717
static void font_select_update_primary_clipboard(Object *obedit)
Definition editfont.cc:461
static int kill_selection(Object *obedit, int ins)
Definition editfont.cc:433
static void text_insert_unicode_confirm(bContext *C, void *arg_block, void *arg_string)
Definition editfont.cc:674
static wmOperatorStatus line_break_exec(bContext *C, wmOperator *)
Definition editfont.cc:1670
void ED_curve_editfont_make(Object *obedit)
Definition editfont.cc:2236
void FONT_OT_select_all(wmOperatorType *ot)
Definition editfont.cc:1073
void FONT_OT_move(wmOperatorType *ot)
Definition editfont.cc:1485
static bool font_paste_wchar(Object *obedit, const char32_t *str, const size_t str_len, const CharInfo *str_info)
Definition editfont.cc:484
bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params)
Definition editfont.cc:2570
static int font_cursor_text_index_from_event(bContext *C, Object *obedit, const wmEvent *event)
Definition editfont.cc:2002
static wmOperatorStatus change_spacing_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1545
static wmOperatorStatus paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition editfont.cc:624
#define MAXTEXT
Definition editfont.cc:69
static wmOperatorStatus change_character_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1612
void FONT_OT_text_cut(wmOperatorType *ot)
Definition editfont.cc:1165
static wmOperatorStatus cut_text_exec(bContext *C, wmOperator *)
Definition editfont.cc:1147
static wmOperatorStatus insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition editfont.cc:1888
void FONT_OT_change_spacing(wmOperatorType *ot)
Definition editfont.cc:1580
static wmOperatorStatus font_open_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2428
static void txt_add_object(bContext *C, const TextLine *firstline, int totline, const float offset[3])
Definition editfont.cc:814
void FONT_OT_text_insert_unicode(wmOperatorType *ot)
Definition editfont.cc:793
void ED_curve_editfont_load(Object *obedit)
Definition editfont.cc:2275
static wmOperatorStatus paste_from_file_exec(bContext *C, wmOperator *op)
Definition editfont.cc:611
void FONT_OT_change_character(wmOperatorType *ot)
Definition editfont.cc:1638
static const EnumPropertyItem style_items[]
Definition editfont.cc:946
void FONT_OT_delete(wmOperatorType *ot)
Definition editfont.cc:1831
void FONT_OT_textbox_remove(wmOperatorType *ot)
Definition editfont.cc:2213
static wmOperatorStatus paste_from_file(bContext *C, ReportList *reports, const char *filepath)
Definition editfont.cc:583
static wmOperatorStatus font_select_word_exec(bContext *C, wmOperator *)
Definition editfont.cc:2113
static wmOperatorStatus text_insert_unicode_invoke(bContext *C, wmOperator *, const wmEvent *)
Definition editfont.cc:783
static wmOperatorStatus set_case_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2345
static bool paste_selection(Object *obedit, ReportList *reports)
Definition editfont.cc:1186
static const EnumPropertyItem delete_type_items[]
Definition editfont.cc:1706
static void text_insert_unicode_cancel(bContext *C, void *arg_block, void *)
Definition editfont.cc:668
static wmOperatorStatus textbox_remove_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2190
void FONT_OT_open(wmOperatorType *ot)
Definition editfont.cc:2506
static wmOperatorStatus move_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1478
static wmOperatorStatus font_selection_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition editfont.cc:2054
void FONT_OT_text_paste_from_file(wmOperatorType *ot)
Definition editfont.cc:637
static wmOperatorStatus toggle_case_exec(bContext *C, wmOperator *)
Definition editfont.cc:2377
static char32_t findaccent(char32_t char1, const char code)
Definition editfont.cc:78
void FONT_OT_move_select(wmOperatorType *ot)
Definition editfont.cc:1516
static const EnumPropertyItem case_items[]
Definition editfont.cc:2318
static void text_update_edited(bContext *C, Object *obedit, const eEditFontMode mode)
Definition editfont.cc:406
static wmOperatorStatus set_case(bContext *C, int ccase)
Definition editfont.cc:2324
static wmOperatorStatus insert_text_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1860
static void font_cursor_set_apply(bContext *C, const wmEvent *event)
Definition editfont.cc:2021
static wmOperatorStatus copy_text_exec(bContext *C, wmOperator *)
Definition editfont.cc:1120
void FONT_OT_case_set(wmOperatorType *ot)
Definition editfont.cc:2350
static bool move_cursor_drop_select(Object *obedit, int dir)
Definition editfont.cc:1322
void FONT_OT_case_toggle(wmOperatorType *ot)
Definition editfont.cc:2397
void ED_curve_editfont_free(Object *obedit)
Definition editfont.cc:2307
static void font_ui_template_init(bContext *C, wmOperator *op)
Definition editfont.cc:2414
static wmOperatorStatus toggle_style_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1014
static char * font_select_to_buffer(Object *obedit)
Definition editfont.cc:560
void FONT_OT_selection_set(wmOperatorType *ot)
Definition editfont.cc:2094
void FONT_OT_text_paste(wmOperatorType *ot)
Definition editfont.cc:1271
static int insert_into_textbuf(Object *obedit, uintptr_t c)
Definition editfont.cc:378
static wmOperatorStatus paste_text_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1202
static wmOperatorStatus move_select_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1509
static wmOperatorStatus move_cursor(bContext *C, int type, const bool select)
Definition editfont.cc:1345
void FONT_OT_text_insert(wmOperatorType *ot)
Definition editfont.cc:1971
static wmOperatorStatus font_unlink_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2537
static wmOperatorStatus open_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition editfont.cc:2467
static wmOperatorStatus font_selection_set_modal(bContext *C, wmOperator *, const wmEvent *event)
Definition editfont.cc:2070
void FONT_OT_style_set(wmOperatorType *ot)
Definition editfont.cc:988
static const EnumPropertyItem move_type_items[]
Definition editfont.cc:1301
static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
Definition editfont.cc:536
static wmOperatorStatus textbox_add_exec(bContext *C, wmOperator *)
Definition editfont.cc:2149
#define rot(x, k)
#define str(s)
uint pos
#define select(A, B, C)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
static void clear(Message &msg)
Definition msgfmt.cc:213
bool material_active_index_set(Object *ob, int index)
void init_transform_on_add(Object *object, const float loc[3], const float rot[3])
uiLayout & block_layout(uiBlock *block, LayoutDirection direction, LayoutType type, int x, int y, int size, int em, int padding, const uiStyle *style)
VecBase< float, 2 > float2
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
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_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
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_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
struct VFont * vfont
struct CharInfo curinfo
struct TextBox * tb
struct EditFont * editfont
struct CharInfo * strinfo
char * str
CharInfo * textbufinfo
Definition BKE_vfont.hh:43
int selend
Definition BKE_vfont.hh:61
EditFontSelBox * selboxes
Definition BKE_vfont.hh:50
char32_t * textbuf
Definition BKE_vfont.hh:41
int selstart
Definition BKE_vfont.hh:61
Definition DNA_ID.h:414
void * first
float loc[3]
ID * owner_id
Definition RNA_types.hh:51
PropertyRNA * prop
Definition RNA_types.hh:146
float viewinv[4][4]
char * line
struct TextLine * next
ListBase lines
char filepath[1024]
RegionView3D * rv3d
Definition ED_view3d.hh:80
ARegion * region
Definition ED_view3d.hh:77
Object * obedit
Definition ED_view3d.hh:76
float xmax
float xmin
float ymax
float ymin
void label(blender::StringRef name, int icon)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
int width() const
uiLayout & split(float percentage, bool align)
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
char utf8_buf[6]
Definition WM_types.hh:771
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
uint len
size_t len_utf8
Definition vfont.cc:468
void WM_event_add_fileselect(bContext *C, wmOperator *op)
bool WM_operator_poll_or_report_error(bContext *C, wmOperatorType *ot, ReportList *reports)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_TABKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ MIDDLEMOUSE
@ EVT_BACKSPACEKEY
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
void WM_clipboard_text_set(const char *buf, bool selection)
char * WM_clipboard_text_get(bool selection, bool ensure_utf8, int *r_len)
eWM_CapabilitiesFlag WM_capabilities_flag()