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