Blender  V2.93
editfont.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <wchar.h>
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "BLI_blenlib.h"
33 #include "BLI_math.h"
34 #include "BLI_string_cursor_utf8.h"
35 #include "BLI_utildefines.h"
36 
37 #include "DNA_curve_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_text_types.h"
41 #include "DNA_vfont_types.h"
42 
43 #include "BKE_context.h"
44 #include "BKE_curve.h"
45 #include "BKE_font.h"
46 #include "BKE_lib_id.h"
47 #include "BKE_main.h"
48 #include "BKE_object.h"
49 #include "BKE_report.h"
50 
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
53 
54 #include "RNA_access.h"
55 #include "RNA_define.h"
56 
57 #include "WM_api.h"
58 #include "WM_types.h"
59 
60 #include "ED_curve.h"
61 #include "ED_object.h"
62 #include "ED_outliner.h"
63 #include "ED_screen.h"
64 #include "ED_view3d.h"
65 
66 #include "UI_interface.h"
67 
68 #include "curve_intern.h"
69 
70 #define MAXTEXT 32766
71 
72 static int kill_selection(Object *obedit, int ins);
73 
76 /* -------------------------------------------------------------------- */
80 static char32_t findaccent(char32_t char1, uint code)
81 {
82  char32_t new = 0;
83 
84  if (char1 == 'a') {
85  if (code == '`') {
86  new = 224;
87  }
88  else if (code == 39) {
89  new = 225;
90  }
91  else if (code == '^') {
92  new = 226;
93  }
94  else if (code == '~') {
95  new = 227;
96  }
97  else if (code == '"') {
98  new = 228;
99  }
100  else if (code == 'o') {
101  new = 229;
102  }
103  else if (code == 'e') {
104  new = 230;
105  }
106  else if (code == '-') {
107  new = 170;
108  }
109  }
110  else if (char1 == 'c') {
111  if (code == ',') {
112  new = 231;
113  }
114  else if (code == '|') {
115  new = 162;
116  }
117  else if (code == 'o') {
118  new = 169;
119  }
120  }
121  else if (char1 == 'e') {
122  if (code == '`') {
123  new = 232;
124  }
125  else if (code == 39) {
126  new = 233;
127  }
128  else if (code == '^') {
129  new = 234;
130  }
131  else if (code == '"') {
132  new = 235;
133  }
134  }
135  else if (char1 == 'i') {
136  if (code == '`') {
137  new = 236;
138  }
139  else if (code == 39) {
140  new = 237;
141  }
142  else if (code == '^') {
143  new = 238;
144  }
145  else if (code == '"') {
146  new = 239;
147  }
148  }
149  else if (char1 == 'n') {
150  if (code == '~') {
151  new = 241;
152  }
153  }
154  else if (char1 == 'o') {
155  if (code == '`') {
156  new = 242;
157  }
158  else if (code == 39) {
159  new = 243;
160  }
161  else if (code == '^') {
162  new = 244;
163  }
164  else if (code == '~') {
165  new = 245;
166  }
167  else if (code == '"') {
168  new = 246;
169  }
170  else if (code == '/') {
171  new = 248;
172  }
173  else if (code == '-') {
174  new = 186;
175  }
176  else if (code == 'e') {
177  new = 339;
178  }
179  else if (code == 'c') {
180  new = 169;
181  }
182  else if (code == 'r') {
183  new = 174;
184  }
185  }
186  else if (char1 == 'r') {
187  if (code == 'o') {
188  new = 174;
189  }
190  }
191  else if (char1 == 's') {
192  if (code == 's') {
193  new = 167;
194  }
195  }
196  else if (char1 == 't') {
197  if (code == 'm') {
198  new = 8482;
199  }
200  }
201  else if (char1 == 'u') {
202  if (code == '`') {
203  new = 249;
204  }
205  else if (code == 39) {
206  new = 250;
207  }
208  else if (code == '^') {
209  new = 251;
210  }
211  else if (code == '"') {
212  new = 252;
213  }
214  }
215  else if (char1 == 'y') {
216  if (code == 39) {
217  new = 253;
218  }
219  else if (code == '"') {
220  new = 255;
221  }
222  }
223  else if (char1 == 'A') {
224  if (code == '`') {
225  new = 192;
226  }
227  else if (code == 39) {
228  new = 193;
229  }
230  else if (code == '^') {
231  new = 194;
232  }
233  else if (code == '~') {
234  new = 195;
235  }
236  else if (code == '"') {
237  new = 196;
238  }
239  else if (code == 'o') {
240  new = 197;
241  }
242  else if (code == 'e') {
243  new = 198;
244  }
245  }
246  else if (char1 == 'C') {
247  if (code == ',') {
248  new = 199;
249  }
250  }
251  else if (char1 == 'E') {
252  if (code == '`') {
253  new = 200;
254  }
255  else if (code == 39) {
256  new = 201;
257  }
258  else if (code == '^') {
259  new = 202;
260  }
261  else if (code == '"') {
262  new = 203;
263  }
264  }
265  else if (char1 == 'I') {
266  if (code == '`') {
267  new = 204;
268  }
269  else if (code == 39) {
270  new = 205;
271  }
272  else if (code == '^') {
273  new = 206;
274  }
275  else if (code == '"') {
276  new = 207;
277  }
278  }
279  else if (char1 == 'N') {
280  if (code == '~') {
281  new = 209;
282  }
283  }
284  else if (char1 == 'O') {
285  if (code == '`') {
286  new = 210;
287  }
288  else if (code == 39) {
289  new = 211;
290  }
291  else if (code == '^') {
292  new = 212;
293  }
294  else if (code == '~') {
295  new = 213;
296  }
297  else if (code == '"') {
298  new = 214;
299  }
300  else if (code == '/') {
301  new = 216;
302  }
303  else if (code == 'e') {
304  new = 141;
305  }
306  }
307  else if (char1 == 'U') {
308  if (code == '`') {
309  new = 217;
310  }
311  else if (code == 39) {
312  new = 218;
313  }
314  else if (code == '^') {
315  new = 219;
316  }
317  else if (code == '"') {
318  new = 220;
319  }
320  }
321  else if (char1 == 'Y') {
322  if (code == 39) {
323  new = 221;
324  }
325  }
326  else if (char1 == '1') {
327  if (code == '4') {
328  new = 188;
329  }
330  if (code == '2') {
331  new = 189;
332  }
333  }
334  else if (char1 == '3') {
335  if (code == '4') {
336  new = 190;
337  }
338  }
339  else if (char1 == ':') {
340  if (code == '-') {
341  new = 247;
342  }
343  }
344  else if (char1 == '-') {
345  if (code == ':') {
346  new = 247;
347  }
348  if (code == '|') {
349  new = 8224;
350  }
351  if (code == '+') {
352  new = 177;
353  }
354  }
355  else if (char1 == '|') {
356  if (code == '-') {
357  new = 8224;
358  }
359  if (code == '=') {
360  new = 8225;
361  }
362  }
363  else if (char1 == '=') {
364  if (code == '|') {
365  new = 8225;
366  }
367  }
368  else if (char1 == '+') {
369  if (code == '-') {
370  new = 177;
371  }
372  }
373 
374  if (new) {
375  return new;
376  }
377  return char1;
378 }
379 
380 static int insert_into_textbuf(Object *obedit, uintptr_t c)
381 {
382  Curve *cu = obedit->data;
383  EditFont *ef = cu->editfont;
384 
385  if (ef->len < MAXTEXT - 1) {
386  int x;
387 
388  for (x = ef->len; x > ef->pos; x--) {
389  ef->textbuf[x] = ef->textbuf[x - 1];
390  }
391  for (x = ef->len; x > ef->pos; x--) {
392  ef->textbufinfo[x] = ef->textbufinfo[x - 1];
393  }
394  ef->textbuf[ef->pos] = c;
395  ef->textbufinfo[ef->pos] = cu->curinfo;
396  ef->textbufinfo[ef->pos].kern = 0;
397  ef->textbufinfo[ef->pos].mat_nr = obedit->actcol;
398 
399  ef->pos++;
400  ef->len++;
401  ef->textbuf[ef->len] = '\0';
402 
403  return 1;
404  }
405  return 0;
406 }
407 
408 static void text_update_edited(bContext *C, Object *obedit, int mode)
409 {
410  Curve *cu = obedit->data;
411  EditFont *ef = cu->editfont;
412 
413  BLI_assert(ef->len >= 0);
414 
415  /* run update first since it can move the cursor */
416  if (mode == FO_EDIT) {
417  /* re-tesselllate */
418  DEG_id_tag_update(obedit->data, 0);
419  }
420  else {
421  /* depsgraph runs above, but since we're not tagging for update, call direct */
422  /* We need evaluated data here. */
425  }
426 
427  cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
428 
429  if (obedit->totcol > 0) {
430  obedit->actcol = cu->curinfo.mat_nr;
431 
432  /* since this array is calloc'd, it can be 0 even though we try ensure
433  * (mat_nr > 0) almost everywhere */
434  if (obedit->actcol < 1) {
435  obedit->actcol = 1;
436  }
437  }
438 
441 }
442 
443 static int kill_selection(Object *obedit, int ins) /* 1 == new character */
444 {
445  Curve *cu = obedit->data;
446  EditFont *ef = cu->editfont;
447  int selend, selstart, direction;
448  int offset = 0;
449  int getfrom;
450 
451  direction = BKE_vfont_select_get(obedit, &selstart, &selend);
452  if (direction) {
453  int size;
454  if (ins) {
455  offset = 1;
456  }
457  if (ef->pos >= selstart) {
458  ef->pos = selstart + offset;
459  }
460  if ((direction == -1) && ins) {
461  selstart++;
462  selend++;
463  }
464  getfrom = selend + offset;
465  if (ins == 0) {
466  getfrom++;
467  }
468  size = (ef->len * sizeof(*ef->textbuf)) - (selstart * sizeof(*ef->textbuf)) +
469  (offset * sizeof(*ef->textbuf));
470  memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
471  memmove(ef->textbufinfo + selstart,
472  ef->textbufinfo + getfrom,
473  ((ef->len - selstart) + offset) * sizeof(CharInfo));
474  ef->len -= ((selend - selstart) + 1);
475  ef->selstart = ef->selend = 0;
476  }
477 
478  return direction;
479 }
480 
483 /* -------------------------------------------------------------------- */
487 /* text_update_edited(C, scene, obedit, 1, FO_EDIT); */
488 static bool font_paste_wchar(Object *obedit,
489  const char32_t *str,
490  const size_t str_len,
491  /* optional */
492  struct CharInfo *str_info)
493 {
494  Curve *cu = obedit->data;
495  EditFont *ef = cu->editfont;
496  int selend, selstart;
497 
498  if (BKE_vfont_select_get(obedit, &selstart, &selend) == 0) {
499  selstart = selend = 0;
500  }
501 
502  /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
503  if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) {
504 
505  kill_selection(obedit, 0);
506 
507  if (str_len) {
508  int size = (ef->len * sizeof(*ef->textbuf)) - (ef->pos * sizeof(*ef->textbuf)) +
509  sizeof(*ef->textbuf);
510  memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
511  memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(*ef->textbuf));
512 
513  memmove(ef->textbufinfo + ef->pos + str_len,
514  ef->textbufinfo + ef->pos,
515  (ef->len - ef->pos + 1) * sizeof(CharInfo));
516  if (str_info) {
517  memcpy(ef->textbufinfo + ef->pos, str_info, str_len * sizeof(CharInfo));
518  }
519  else {
520  memset(ef->textbufinfo + ef->pos, '\0', str_len * sizeof(CharInfo));
521  }
522 
523  ef->len += str_len;
524  ef->pos += str_len;
525  }
526 
527  return true;
528  }
529 
530  return false;
531 }
532 
533 static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
534 {
535  Object *obedit = CTX_data_edit_object(C);
536  bool retval;
537 
538  int tmplen;
539 
540  char32_t *mem = MEM_mallocN((sizeof(*mem) * (str_len + 1)), __func__);
541 
542  tmplen = BLI_str_utf8_as_utf32(mem, str, str_len + 1);
543 
544  retval = font_paste_wchar(obedit, mem, tmplen, NULL);
545 
546  MEM_freeN(mem);
547 
548  return retval;
549 }
550 
553 /* -------------------------------------------------------------------- */
557 static int paste_from_file(bContext *C, ReportList *reports, const char *filename)
558 {
559  Object *obedit = CTX_data_edit_object(C);
560  char *strp;
561  size_t filelen;
562  int retval;
563 
564  strp = BLI_file_read_text_as_mem(filename, 1, &filelen);
565  if (strp == NULL) {
566  BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename);
567  return OPERATOR_CANCELLED;
568  }
569  strp[filelen] = 0;
570 
571  if (font_paste_utf8(C, strp, filelen)) {
572  text_update_edited(C, obedit, FO_EDIT);
573  retval = OPERATOR_FINISHED;
574  }
575  else {
576  BKE_reportf(reports, RPT_ERROR, "File too long %s", filename);
577  retval = OPERATOR_CANCELLED;
578  }
579 
580  MEM_freeN(strp);
581 
582  return retval;
583 }
584 
586 {
587  char *path;
588  int retval;
589 
590  path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
591  retval = paste_from_file(C, op->reports, path);
592  MEM_freeN(path);
593 
594  return retval;
595 }
596 
597 static int paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
598 {
599  if (RNA_struct_property_is_set(op->ptr, "filepath")) {
600  return paste_from_file_exec(C, op);
601  }
602 
604 
605  return OPERATOR_RUNNING_MODAL;
606 }
607 
609 {
610  /* identifiers */
611  ot->name = "Paste File";
612  ot->description = "Paste contents from file";
613  ot->idname = "FONT_OT_text_paste_from_file";
614 
615  /* api callbacks */
619 
620  /* flags */
622 
623  /* properties */
626  FILE_SPECIAL,
631 }
632 
635 /* -------------------------------------------------------------------- */
639 static void txt_add_object(bContext *C,
640  const TextLine *firstline,
641  int totline,
642  const float offset[3])
643 {
644  Main *bmain = CTX_data_main(C);
647  ViewLayer *view_layer = CTX_data_view_layer(C);
648  Curve *cu;
649  Object *obedit;
650  Base *base;
651  const struct TextLine *tmp;
652  int nchars = 0, nbytes = 0;
653  char *s;
654  int a;
655  const float rot[3] = {0.0f, 0.0f, 0.0f};
656 
657  obedit = BKE_object_add(bmain, view_layer, OB_FONT, NULL);
658  base = view_layer->basact;
659 
660  /* seems to assume view align ? TODO - look into this, could be an operator option */
662 
664 
665  add_v3_v3(obedit->loc, offset);
666 
667  cu = obedit->data;
669  id_us_plus(&cu->vfont->id);
670 
671  for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) {
672  size_t nchars_line, nbytes_line;
673  nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
674  nchars += nchars_line + 1;
675  nbytes += nbytes_line + 1;
676  }
677 
678  if (cu->str) {
679  MEM_freeN(cu->str);
680  }
681  if (cu->strinfo) {
682  MEM_freeN(cu->strinfo);
683  }
684 
685  cu->str = MEM_mallocN(nbytes + 4, "str");
686  cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo");
687 
688  cu->len = 0;
689  cu->len_char32 = nchars - 1;
690  cu->pos = 0;
691 
692  s = cu->str;
693 
694  for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
695  size_t nbytes_line;
696 
697  nbytes_line = BLI_strcpy_rlen(s, tmp->line);
698 
699  s += nbytes_line;
700  cu->len += nbytes_line;
701 
702  if (tmp->next) {
703  nbytes_line = BLI_strcpy_rlen(s, "\n");
704 
705  s += nbytes_line;
706  cu->len += nbytes_line;
707  }
708  }
709 
710  cu->pos = cu->len_char32;
711  *s = '\0';
712 
714 }
715 
716 void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
717 {
718  Main *bmain = CTX_data_main(C);
720  const TextLine *line;
721  float offset[3];
722  int linenum = 0;
723 
724  if (!text || !text->lines.first) {
725  return;
726  }
727 
728  if (split_lines) {
729  for (line = text->lines.first; line; line = line->next) {
730  /* skip lines with no text, but still make space for them */
731  if (line->line[0] == '\0') {
732  linenum++;
733  continue;
734  }
735 
736  /* do the translation */
737  offset[0] = 0;
738  offset[1] = -linenum;
739  offset[2] = 0;
740 
741  if (rv3d) {
742  mul_mat3_m4_v3(rv3d->viewinv, offset);
743  }
744 
745  txt_add_object(C, line, 1, offset);
746 
747  linenum++;
748  }
749  }
750  else {
751  offset[0] = 0.0f;
752  offset[1] = 0.0f;
753  offset[2] = 0.0f;
754 
755  txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset);
756  }
757 
760 }
761 
764 /* -------------------------------------------------------------------- */
768 static const EnumPropertyItem style_items[] = {
769  {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
770  {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""},
771  {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""},
772  {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""},
773  {0, NULL, 0, NULL, NULL},
774 };
775 
776 static int set_style(bContext *C, const int style, const bool clear)
777 {
778  Object *obedit = CTX_data_edit_object(C);
779  Curve *cu = obedit->data;
780  EditFont *ef = cu->editfont;
781  int i, selstart, selend;
782 
783  if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
784  return OPERATOR_CANCELLED;
785  }
786 
787  for (i = selstart; i <= selend; i++) {
788  if (clear) {
789  ef->textbufinfo[i].flag &= ~style;
790  }
791  else {
792  ef->textbufinfo[i].flag |= style;
793  }
794  }
795 
796  DEG_id_tag_update(obedit->data, 0);
798 
799  return OPERATOR_FINISHED;
800 }
801 
803 {
804  const int style = RNA_enum_get(op->ptr, "style");
805  const bool clear = RNA_boolean_get(op->ptr, "clear");
806 
807  return set_style(C, style, clear);
808 }
809 
811 {
812  /* identifiers */
813  ot->name = "Set Style";
814  ot->description = "Set font style";
815  ot->idname = "FONT_OT_style_set";
816 
817  /* api callbacks */
820 
821  /* flags */
823 
824  /* properties */
825  RNA_def_enum(
826  ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
827  RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it");
828 }
829 
832 /* -------------------------------------------------------------------- */
837 {
838  Object *obedit = CTX_data_edit_object(C);
839  Curve *cu = obedit->data;
840  int style, clear, selstart, selend;
841 
842  if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
843  return OPERATOR_CANCELLED;
844  }
845 
846  style = RNA_enum_get(op->ptr, "style");
847 
848  cu->curinfo.flag ^= style;
849  clear = (cu->curinfo.flag & style) == 0;
850 
851  return set_style(C, style, clear);
852 }
853 
855 {
856  /* identifiers */
857  ot->name = "Toggle Style";
858  ot->description = "Toggle font style";
859  ot->idname = "FONT_OT_style_toggle";
860 
861  /* api callbacks */
864 
865  /* flags */
867 
868  /* properties */
869  RNA_def_enum(
870  ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
871 }
872 
875 /* -------------------------------------------------------------------- */
880 {
881  Object *obedit = CTX_data_edit_object(C);
882  Curve *cu = obedit->data;
883  EditFont *ef = cu->editfont;
884 
885  if (ef->len) {
886  ef->selstart = 1;
887  ef->selend = ef->len;
888  ef->pos = ef->len;
889 
891 
892  return OPERATOR_FINISHED;
893  }
894  return OPERATOR_CANCELLED;
895 }
896 
898 {
899  /* identifiers */
900  ot->name = "Select All";
901  ot->description = "Select all text";
902  ot->idname = "FONT_OT_select_all";
903 
904  /* api callbacks */
907 
908  /* flags */
910 }
911 
914 /* -------------------------------------------------------------------- */
918 static void copy_selection(Object *obedit)
919 {
920  int selstart, selend;
921 
922  if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
923  Curve *cu = obedit->data;
924  EditFont *ef = cu->editfont;
925  char *buf = NULL;
926  char32_t *text_buf;
927  size_t len_utf8;
928 
929  /* internal clipboard (for style) */
931  ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
932  BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
933 
934  /* system clipboard */
935  buf = MEM_mallocN(len_utf8 + 1, __func__);
936  if (buf) {
937  BLI_str_utf32_as_utf8(buf, text_buf, len_utf8 + 1);
938  WM_clipboard_text_set(buf, false);
939  MEM_freeN(buf);
940  }
941  }
942 }
943 
945 {
946  Object *obedit = CTX_data_edit_object(C);
947 
948  copy_selection(obedit);
949 
950  return OPERATOR_FINISHED;
951 }
952 
954 {
955  /* identifiers */
956  ot->name = "Copy Text";
957  ot->description = "Copy selected text to clipboard";
958  ot->idname = "FONT_OT_text_copy";
959 
960  /* api callbacks */
963 }
964 
967 /* -------------------------------------------------------------------- */
972 {
973  Object *obedit = CTX_data_edit_object(C);
974  int selstart, selend;
975 
976  if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
977  return OPERATOR_CANCELLED;
978  }
979 
980  copy_selection(obedit);
981  kill_selection(obedit, 0);
982 
983  text_update_edited(C, obedit, FO_EDIT);
984 
985  return OPERATOR_FINISHED;
986 }
987 
989 {
990  /* identifiers */
991  ot->name = "Cut Text";
992  ot->description = "Cut selected text to clipboard";
993  ot->idname = "FONT_OT_text_cut";
994 
995  /* api callbacks */
996  ot->exec = cut_text_exec;
998 
999  /* flags */
1001 }
1002 
1005 /* -------------------------------------------------------------------- */
1009 static bool paste_selection(Object *obedit, ReportList *reports)
1010 {
1011  char32_t *text_buf;
1012  CharInfo *info_buf;
1013  size_t len;
1014 
1015  BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len);
1016 
1017  if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
1018  return true;
1019  }
1020 
1021  BKE_report(reports, RPT_WARNING, "Text too long");
1022  return false;
1023 }
1024 
1026 {
1027  Object *obedit = CTX_data_edit_object(C);
1028  int retval;
1029  size_t len_utf8;
1030  char32_t *text_buf;
1031 
1032  /* Store both clipboards as utf8 for comparison,
1033  * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
1034  * as long as its synchronized with the systems clipboard. */
1035  struct {
1036  char *buf;
1037  int len;
1038  } clipboard_system = {NULL}, clipboard_vfont = {NULL};
1039 
1040  clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len);
1041 
1042  if (clipboard_system.buf == NULL) {
1043  return OPERATOR_CANCELLED;
1044  }
1045 
1046  BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
1047 
1048  if (text_buf) {
1049  clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__);
1050 
1051  if (clipboard_vfont.buf == NULL) {
1052  MEM_freeN(clipboard_system.buf);
1053  return OPERATOR_CANCELLED;
1054  }
1055 
1056  BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
1057  }
1058 
1059  if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
1060  retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1061  }
1062  else {
1063  if ((clipboard_system.len <= MAXTEXT) &&
1064  font_paste_utf8(C, clipboard_system.buf, clipboard_system.len)) {
1065  text_update_edited(C, obedit, FO_EDIT);
1066  retval = OPERATOR_FINISHED;
1067  }
1068  else {
1069  BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
1070  retval = OPERATOR_CANCELLED;
1071  }
1072 
1073  /* free the existent clipboard buffer */
1075  }
1076 
1077  if (retval != OPERATOR_CANCELLED) {
1078  text_update_edited(C, obedit, FO_EDIT);
1079  }
1080 
1081  /* cleanup */
1082  if (clipboard_vfont.buf) {
1083  MEM_freeN(clipboard_vfont.buf);
1084  }
1085 
1086  MEM_freeN(clipboard_system.buf);
1087 
1088  return retval;
1089 }
1090 
1092 {
1093  /* identifiers */
1094  ot->name = "Paste Text";
1095  ot->description = "Paste text from clipboard";
1096  ot->idname = "FONT_OT_text_paste";
1097 
1098  /* api callbacks */
1099  ot->exec = paste_text_exec;
1101 
1102  /* flags */
1104 }
1105 
1108 /* -------------------------------------------------------------------- */
1113  {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
1114  {LINE_END, "LINE_END", 0, "Line End", ""},
1115  {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1116  {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1117  {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1118  {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1119  {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
1120  {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
1121  {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
1122  {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
1123  {0, NULL, 0, NULL, NULL},
1124 };
1125 
1126 static int move_cursor(bContext *C, int type, const bool select)
1127 {
1129  Object *obedit = CTX_data_edit_object(C);
1130  Curve *cu = obedit->data;
1131  EditFont *ef = cu->editfont;
1132  int cursmove = -1;
1133 
1134  if ((select) && (ef->selstart == 0)) {
1135  ef->selstart = ef->selend = ef->pos + 1;
1136  }
1137 
1138  switch (type) {
1139  case LINE_BEGIN:
1140  while (ef->pos > 0) {
1141  if (ef->textbuf[ef->pos - 1] == '\n') {
1142  break;
1143  }
1144  if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) {
1145  break;
1146  }
1147  ef->pos--;
1148  }
1149  cursmove = FO_CURS;
1150  break;
1151 
1152  case LINE_END:
1153  while (ef->pos < ef->len) {
1154  if (ef->textbuf[ef->pos] == 0) {
1155  break;
1156  }
1157  if (ef->textbuf[ef->pos] == '\n') {
1158  break;
1159  }
1160  if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) {
1161  break;
1162  }
1163  ef->pos++;
1164  }
1165  cursmove = FO_CURS;
1166  break;
1167 
1168  case PREV_WORD: {
1169  int pos = ef->pos;
1171  ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1172  ef->pos = pos;
1173  cursmove = FO_CURS;
1174  break;
1175  }
1176 
1177  case NEXT_WORD: {
1178  int pos = ef->pos;
1180  ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1181  ef->pos = pos;
1182  cursmove = FO_CURS;
1183  break;
1184  }
1185 
1186  case PREV_CHAR:
1187  ef->pos--;
1188  cursmove = FO_CURS;
1189  break;
1190 
1191  case NEXT_CHAR:
1192  ef->pos++;
1193  cursmove = FO_CURS;
1194 
1195  break;
1196 
1197  case PREV_LINE:
1198  cursmove = FO_CURSUP;
1199  break;
1200 
1201  case NEXT_LINE:
1202  cursmove = FO_CURSDOWN;
1203  break;
1204 
1205  case PREV_PAGE:
1206  cursmove = FO_PAGEUP;
1207  break;
1208 
1209  case NEXT_PAGE:
1210  cursmove = FO_PAGEDOWN;
1211  break;
1212  }
1213 
1214  if (cursmove == -1) {
1215  return OPERATOR_CANCELLED;
1216  }
1217 
1218  if (ef->pos > ef->len) {
1219  ef->pos = ef->len;
1220  }
1221  else if (ef->pos >= MAXTEXT) {
1222  ef->pos = MAXTEXT;
1223  }
1224  else if (ef->pos < 0) {
1225  ef->pos = 0;
1226  }
1227 
1228  /* apply vertical cursor motion to position immediately
1229  * otherwise the selection will lag behind */
1230  if (FO_CURS_IS_MOTION(cursmove)) {
1232  cursmove = FO_CURS;
1233  }
1234 
1235  if (select == 0) {
1236  if (ef->selstart) {
1237  ef->selstart = ef->selend = 0;
1239  }
1240  }
1241 
1242  if (select) {
1243  ef->selend = ef->pos;
1244  }
1245 
1246  text_update_edited(C, obedit, cursmove);
1247 
1248  return OPERATOR_FINISHED;
1249 }
1250 
1251 static int move_exec(bContext *C, wmOperator *op)
1252 {
1253  int type = RNA_enum_get(op->ptr, "type");
1254 
1255  return move_cursor(C, type, false);
1256 }
1257 
1259 {
1260  /* identifiers */
1261  ot->name = "Move Cursor";
1262  ot->description = "Move cursor to position type";
1263  ot->idname = "FONT_OT_move";
1264 
1265  /* api callbacks */
1266  ot->exec = move_exec;
1268 
1269  /* flags */
1271 
1272  /* properties */
1273  RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
1274 }
1275 
1278 /* -------------------------------------------------------------------- */
1283 {
1284  int type = RNA_enum_get(op->ptr, "type");
1285 
1286  return move_cursor(C, type, true);
1287 }
1288 
1290 {
1291  /* identifiers */
1292  ot->name = "Move Select";
1293  ot->description = "Move the cursor while selecting";
1294  ot->idname = "FONT_OT_move_select";
1295 
1296  /* api callbacks */
1299 
1300  /* flags */
1302 
1303  /* properties */
1304  RNA_def_enum(ot->srna,
1305  "type",
1307  LINE_BEGIN,
1308  "Type",
1309  "Where to move cursor to, to make a selection");
1310 }
1311 
1314 /* -------------------------------------------------------------------- */
1319 {
1320  Object *obedit = CTX_data_edit_object(C);
1321  Curve *cu = obedit->data;
1322  EditFont *ef = cu->editfont;
1323  int kern, delta = RNA_int_get(op->ptr, "delta");
1324  int selstart, selend;
1325  bool changed = false;
1326 
1327  const bool has_select = BKE_vfont_select_get(obedit, &selstart, &selend);
1328  if (has_select) {
1329  selstart -= 1;
1330  }
1331  else {
1332  selstart = selend = ef->pos - 1;
1333  }
1334  selstart = max_ii(0, selstart);
1335 
1336  for (int i = selstart; i <= selend; i++) {
1337  kern = ef->textbufinfo[i].kern + delta;
1338  CLAMP(kern, -20, 20);
1339 
1340  if (ef->textbufinfo[i].kern != kern) {
1341  ef->textbufinfo[i].kern = kern;
1342  changed = true;
1343  }
1344  }
1345 
1346  if (changed) {
1347  text_update_edited(C, obedit, FO_EDIT);
1348 
1349  return OPERATOR_FINISHED;
1350  }
1351  return OPERATOR_CANCELLED;
1352 }
1353 
1355 {
1356  /* identifiers */
1357  ot->name = "Change Spacing";
1358  ot->description = "Change font spacing";
1359  ot->idname = "FONT_OT_change_spacing";
1360 
1361  /* api callbacks */
1364 
1365  /* flags */
1367 
1368  /* properties */
1369  RNA_def_int(ot->srna,
1370  "delta",
1371  1,
1372  -20,
1373  20,
1374  "Delta",
1375  "Amount to decrease or increase character spacing with",
1376  -20,
1377  20);
1378 }
1379 
1382 /* -------------------------------------------------------------------- */
1387 {
1388  Object *obedit = CTX_data_edit_object(C);
1389  Curve *cu = obedit->data;
1390  EditFont *ef = cu->editfont;
1391  int character, delta = RNA_int_get(op->ptr, "delta");
1392 
1393  if (ef->pos <= 0) {
1394  return OPERATOR_CANCELLED;
1395  }
1396 
1397  character = ef->textbuf[ef->pos - 1];
1398  character += delta;
1399  CLAMP(character, 0, 255);
1400 
1401  if (character == ef->textbuf[ef->pos - 1]) {
1402  return OPERATOR_CANCELLED;
1403  }
1404 
1405  ef->textbuf[ef->pos - 1] = character;
1406 
1407  text_update_edited(C, obedit, FO_EDIT);
1408 
1409  return OPERATOR_FINISHED;
1410 }
1411 
1413 {
1414  /* identifiers */
1415  ot->name = "Change Character";
1416  ot->description = "Change font character code";
1417  ot->idname = "FONT_OT_change_character";
1418 
1419  /* api callbacks */
1422 
1423  /* flags */
1425 
1426  /* properties */
1427  RNA_def_int(ot->srna,
1428  "delta",
1429  1,
1430  -255,
1431  255,
1432  "Delta",
1433  "Number to increase or decrease character code with",
1434  -255,
1435  255);
1436 }
1437 
1440 /* -------------------------------------------------------------------- */
1445 {
1446  Object *obedit = CTX_data_edit_object(C);
1447  Curve *cu = obedit->data;
1448  EditFont *ef = cu->editfont;
1449 
1450  insert_into_textbuf(obedit, '\n');
1451 
1452  ef->selstart = ef->selend = 0;
1453 
1454  text_update_edited(C, obedit, FO_EDIT);
1455 
1456  return OPERATOR_FINISHED;
1457 }
1458 
1460 {
1461  /* identifiers */
1462  ot->name = "Line Break";
1463  ot->description = "Insert line break at cursor position";
1464  ot->idname = "FONT_OT_line_break";
1465 
1466  /* api callbacks */
1467  ot->exec = line_break_exec;
1469 
1470  /* flags */
1472 }
1473 
1476 /* -------------------------------------------------------------------- */
1481  {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1482  {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1483  {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1484  {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1485  {DEL_SELECTION, "SELECTION", 0, "Selection", ""},
1486  {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""},
1487  {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""},
1488  {0, NULL, 0, NULL, NULL},
1489 };
1490 
1492 {
1493  Object *obedit = CTX_data_edit_object(C);
1494  Curve *cu = obedit->data;
1495  EditFont *ef = cu->editfont;
1496  int selstart, selend, type = RNA_enum_get(op->ptr, "type");
1497  int range[2] = {0, 0};
1498  bool has_select = false;
1499 
1500  if (ef->len == 0) {
1501  return OPERATOR_CANCELLED;
1502  }
1503 
1504  if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
1505  if (type == DEL_NEXT_SEL) {
1506  type = DEL_SELECTION;
1507  }
1508  else if (type == DEL_PREV_SEL) {
1509  type = DEL_SELECTION;
1510  }
1511  has_select = true;
1512  }
1513  else {
1514  if (type == DEL_NEXT_SEL) {
1515  type = DEL_NEXT_CHAR;
1516  }
1517  else if (type == DEL_PREV_SEL) {
1518  type = DEL_PREV_CHAR;
1519  }
1520  }
1521 
1522  switch (type) {
1523  case DEL_SELECTION:
1524  if (!kill_selection(obedit, 0)) {
1525  return OPERATOR_CANCELLED;
1526  }
1527  break;
1528  case DEL_PREV_CHAR:
1529  if (ef->pos <= 0) {
1530  return OPERATOR_CANCELLED;
1531  }
1532 
1533  range[0] = ef->pos - 1;
1534  range[1] = ef->pos;
1535 
1536  ef->pos--;
1537  break;
1538  case DEL_NEXT_CHAR:
1539  if (ef->pos >= ef->len) {
1540  return OPERATOR_CANCELLED;
1541  }
1542 
1543  range[0] = ef->pos;
1544  range[1] = ef->pos + 1;
1545  break;
1546  case DEL_NEXT_WORD: {
1547  int pos = ef->pos;
1549  ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1550  range[0] = ef->pos;
1551  range[1] = pos;
1552  break;
1553  }
1554 
1555  case DEL_PREV_WORD: {
1556  int pos = ef->pos;
1558  ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1559  range[0] = pos;
1560  range[1] = ef->pos;
1561  ef->pos = pos;
1562  break;
1563  }
1564  default:
1565  return OPERATOR_CANCELLED;
1566  }
1567 
1568  if (range[0] != range[1]) {
1569  BLI_assert(range[0] < range[1]);
1570  int len_remove = range[1] - range[0];
1571  int len_tail = ef->len - range[1];
1572  if (has_select) {
1573  for (int i = 0; i < 2; i++) {
1574  int *sel = i ? &ef->selend : &ef->selstart;
1575  if (*sel <= range[0]) {
1576  /* pass */
1577  }
1578  else if (*sel >= range[1]) {
1579  *sel -= len_remove;
1580  }
1581  else if (*sel < range[1]) {
1582  /* pass */
1583  *sel = range[0];
1584  }
1585  }
1586  }
1587 
1588  memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail);
1589  memmove(&ef->textbufinfo[range[0]],
1590  &ef->textbufinfo[range[1]],
1591  sizeof(*ef->textbufinfo) * len_tail);
1592 
1593  ef->len -= len_remove;
1594  ef->textbuf[ef->len] = '\0';
1595 
1596  BKE_vfont_select_clamp(obedit);
1597  }
1598 
1599  text_update_edited(C, obedit, FO_EDIT);
1600 
1601  return OPERATOR_FINISHED;
1602 }
1603 
1605 {
1606  /* identifiers */
1607  ot->name = "Delete";
1608  ot->description = "Delete text by cursor position";
1609  ot->idname = "FONT_OT_delete";
1610 
1611  /* api callbacks */
1612  ot->exec = delete_exec;
1614 
1615  /* flags */
1617 
1618  /* properties */
1619  RNA_def_enum(ot->srna,
1620  "type",
1622  DEL_PREV_CHAR,
1623  "Type",
1624  "Which part of the text to delete");
1625 }
1626 
1629 /* -------------------------------------------------------------------- */
1634 {
1635  Object *obedit = CTX_data_edit_object(C);
1636  char *inserted_utf8;
1637  char32_t *inserted_text;
1638  int a, len;
1639 
1640  if (!RNA_struct_property_is_set(op->ptr, "text")) {
1641  return OPERATOR_CANCELLED;
1642  }
1643 
1644  inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
1645  len = BLI_strlen_utf8(inserted_utf8);
1646 
1647  inserted_text = MEM_callocN(sizeof(char32_t) * (len + 1), "FONT_insert_text");
1648  len = BLI_str_utf8_as_utf32(inserted_text, inserted_utf8, MAXTEXT);
1649 
1650  for (a = 0; a < len; a++) {
1651  insert_into_textbuf(obedit, inserted_text[a]);
1652  }
1653 
1654  MEM_freeN(inserted_text);
1655  MEM_freeN(inserted_utf8);
1656 
1657  kill_selection(obedit, 1);
1658  text_update_edited(C, obedit, FO_EDIT);
1659 
1660  return OPERATOR_FINISHED;
1661 }
1662 
1663 static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1664 {
1665  Object *obedit = CTX_data_edit_object(C);
1666  Curve *cu = obedit->data;
1667  EditFont *ef = cu->editfont;
1668  static int accentcode = 0;
1669  uintptr_t ascii = event->ascii;
1670  int alt = event->alt, shift = event->shift, ctrl = event->ctrl;
1671  int event_type = event->type, event_val = event->val;
1672  char32_t inserted_text[2] = {0};
1673 
1674  if (RNA_struct_property_is_set(op->ptr, "text")) {
1675  return insert_text_exec(C, op);
1676  }
1677 
1678  if (RNA_struct_property_is_set(op->ptr, "accent")) {
1679  if (ef->len != 0 && ef->pos > 0) {
1680  accentcode = 1;
1681  }
1682  return OPERATOR_FINISHED;
1683  }
1684 
1685  /* tab should exit editmode, but we allow it to be typed using modifier keys */
1686  if (event_type == EVT_TABKEY) {
1687  if ((alt || ctrl || shift) == 0) {
1688  return OPERATOR_PASS_THROUGH;
1689  }
1690 
1691  ascii = 9;
1692  }
1693 
1694  if (event_type == EVT_BACKSPACEKEY) {
1695  if (alt && ef->len != 0 && ef->pos > 0) {
1696  accentcode = 1;
1697  }
1698  return OPERATOR_PASS_THROUGH;
1699  }
1700 
1701  if (event_val && (ascii || event->utf8_buf[0])) {
1702  /* handle case like TAB (== 9) */
1703  if ((ascii > 31 && ascii < 254 && ascii != 127) || (ELEM(ascii, 13, 10)) || (ascii == 8) ||
1704  (event->utf8_buf[0])) {
1705 
1706  if (accentcode) {
1707  if (ef->pos > 0) {
1708  inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii);
1709  ef->textbuf[ef->pos - 1] = inserted_text[0];
1710  }
1711  accentcode = 0;
1712  }
1713  else if (event->utf8_buf[0]) {
1714  inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf);
1715  ascii = inserted_text[0];
1716  insert_into_textbuf(obedit, ascii);
1717  accentcode = 0;
1718  }
1719  else if (ascii) {
1720  insert_into_textbuf(obedit, ascii);
1721  accentcode = 0;
1722  }
1723  else {
1724  BLI_assert(0);
1725  }
1726 
1727  kill_selection(obedit, 1);
1728  text_update_edited(C, obedit, FO_EDIT);
1729  }
1730  else {
1731  inserted_text[0] = ascii;
1732  insert_into_textbuf(obedit, ascii);
1733  text_update_edited(C, obedit, FO_EDIT);
1734  }
1735  }
1736  else {
1737  return OPERATOR_PASS_THROUGH;
1738  }
1739 
1740  if (inserted_text[0]) {
1741  /* store as utf8 in RNA string */
1742  char inserted_utf8[8] = {0};
1743 
1744  BLI_str_utf32_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8));
1745  RNA_string_set(op->ptr, "text", inserted_utf8);
1746  }
1747 
1748  /* reset property? */
1749  if (event_val == 0) {
1750  accentcode = 0;
1751  }
1752 
1753  return OPERATOR_FINISHED;
1754 }
1755 
1757 {
1758  /* identifiers */
1759  ot->name = "Insert Text";
1760  ot->description = "Insert text at cursor position";
1761  ot->idname = "FONT_OT_text_insert";
1762 
1763  /* api callbacks */
1767 
1768  /* flags */
1769  ot->flag = OPTYPE_UNDO;
1770 
1771  /* properties */
1772  RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
1774  ot->srna,
1775  "accent",
1776  0,
1777  "Accent Mode",
1778  "Next typed character will strike through previous, for special character input");
1779 }
1780 
1783 /* -------------------------------------------------------------------- */
1788 {
1789  Object *obedit = CTX_data_active_object(C);
1790  Curve *cu = obedit->data;
1791  int i;
1792 
1793  if (cu->totbox < 256) {
1794  for (i = cu->totbox; i > cu->actbox; i--) {
1795  cu->tb[i] = cu->tb[i - 1];
1796  }
1797  cu->tb[cu->actbox] = cu->tb[cu->actbox - 1];
1798  cu->actbox++;
1799  cu->totbox++;
1800  }
1801 
1802  DEG_id_tag_update(obedit->data, 0);
1804  return OPERATOR_FINISHED;
1805 }
1806 
1808 {
1809  /* identifiers */
1810  ot->name = "Add Text Box";
1811  ot->description = "Add a new text box";
1812  ot->idname = "FONT_OT_textbox_add";
1813 
1814  /* api callbacks */
1817 
1818  /* flags */
1820 }
1821 
1824 /* -------------------------------------------------------------------- */
1829 {
1830  Object *obedit = CTX_data_active_object(C);
1831  Curve *cu = obedit->data;
1832  int i;
1833  int index = RNA_int_get(op->ptr, "index");
1834 
1835  if (cu->totbox > 1) {
1836  for (i = index; i < cu->totbox; i++) {
1837  cu->tb[i] = cu->tb[i + 1];
1838  }
1839  cu->totbox--;
1840  if (cu->actbox >= index) {
1841  cu->actbox--;
1842  }
1843  }
1844 
1845  DEG_id_tag_update(obedit->data, 0);
1847 
1848  return OPERATOR_FINISHED;
1849 }
1850 
1852 {
1853  /* identifiers */
1854  ot->name = "Remove Text Box";
1855  ot->description = "Remove the text box";
1856  ot->idname = "FONT_OT_textbox_remove";
1857 
1858  /* api callbacks */
1861 
1862  /* flags */
1864 
1865  RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
1866 }
1867 
1870 /* -------------------------------------------------------------------- */
1875 {
1876  Curve *cu = obedit->data;
1877  EditFont *ef = cu->editfont;
1878  int len_char32;
1879 
1880  if (ef == NULL) {
1881  ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont");
1882 
1883  ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(*ef->textbuf), "texteditbuf");
1884  ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
1885  }
1886 
1887  /* Convert the original text to chat32_t. */
1888  len_char32 = BLI_str_utf8_as_utf32(ef->textbuf, cu->str, MAXTEXT + 4);
1889  BLI_assert(len_char32 == cu->len_char32);
1890  ef->len = len_char32;
1891  BLI_assert(ef->len >= 0);
1892 
1893  memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
1894 
1895  ef->pos = cu->pos;
1896  if (ef->pos > ef->len) {
1897  ef->pos = ef->len;
1898  }
1899 
1900  cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
1901 
1902  /* Other vars */
1903  ef->selstart = cu->selstart;
1904  ef->selend = cu->selend;
1905 
1906  /* text may have been modified by Python */
1907  BKE_vfont_select_clamp(obedit);
1908 }
1909 
1911 {
1912  Curve *cu = obedit->data;
1913  EditFont *ef = cu->editfont;
1914 
1915  /* Free the old curve string */
1916  MEM_freeN(cu->str);
1917 
1918  /* Calculate the actual string length in UTF-8 variable characters */
1919  cu->len_char32 = ef->len;
1921 
1922  /* Alloc memory for UTF-8 variable char length string */
1923  cu->str = MEM_mallocN(cu->len + sizeof(char32_t), "str");
1924 
1925  /* Copy the wchar to UTF-8 */
1926  BLI_str_utf32_as_utf8(cu->str, ef->textbuf, cu->len + 1);
1927 
1928  if (cu->strinfo) {
1929  MEM_freeN(cu->strinfo);
1930  }
1931  cu->strinfo = MEM_callocN((cu->len_char32 + 4) * sizeof(CharInfo), "texteditinfo");
1932  memcpy(cu->strinfo, ef->textbufinfo, cu->len_char32 * sizeof(CharInfo));
1933 
1934  /* Other vars */
1935  cu->pos = ef->pos;
1936  cu->selstart = ef->selstart;
1937  cu->selend = ef->selend;
1938 }
1939 
1941 {
1942  BKE_curve_editfont_free((Curve *)obedit->data);
1943 }
1944 
1947 /* -------------------------------------------------------------------- */
1951 static const EnumPropertyItem case_items[] = {
1952  {CASE_LOWER, "LOWER", 0, "Lower", ""},
1953  {CASE_UPPER, "UPPER", 0, "Upper", ""},
1954  {0, NULL, 0, NULL, NULL},
1955 };
1956 
1957 static int set_case(bContext *C, int ccase)
1958 {
1959  Object *obedit = CTX_data_edit_object(C);
1960  Curve *cu = obedit->data;
1961  EditFont *ef = cu->editfont;
1962  char32_t *str;
1963  int len;
1964  int selstart, selend;
1965 
1966  if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
1967  len = (selend - selstart) + 1;
1968  str = &ef->textbuf[selstart];
1969  while (len) {
1970  if (*str >= 'a' && *str <= 'z') {
1971  *str -= 32;
1972  }
1973  len--;
1974  str++;
1975  }
1976 
1977  if (ccase == CASE_LOWER) {
1978  len = (selend - selstart) + 1;
1979  str = &ef->textbuf[selstart];
1980  while (len) {
1981  if (*str >= 'A' && *str <= 'Z') {
1982  *str += 32;
1983  }
1984  len--;
1985  str++;
1986  }
1987  }
1988 
1989  text_update_edited(C, obedit, FO_EDIT);
1990  }
1991 
1992  return OPERATOR_FINISHED;
1993 }
1994 
1996 {
1997  return set_case(C, RNA_enum_get(op->ptr, "case"));
1998 }
1999 
2001 {
2002  /* identifiers */
2003  ot->name = "Set Case";
2004  ot->description = "Set font case";
2005  ot->idname = "FONT_OT_case_set";
2006 
2007  /* api callbacks */
2008  ot->exec = set_case_exec;
2010 
2011  /* flags */
2013 
2014  /* properties */
2015  RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
2016 }
2017 
2020 /* -------------------------------------------------------------------- */
2025 {
2026  Object *obedit = CTX_data_edit_object(C);
2027  Curve *cu = obedit->data;
2028  EditFont *ef = cu->editfont;
2029  char32_t *str;
2030  int ccase = CASE_UPPER;
2031 
2032  str = ef->textbuf;
2033  while (*str) {
2034  if (*str >= 'a' && *str <= 'z') {
2035  ccase = CASE_LOWER;
2036  break;
2037  }
2038 
2039  str++;
2040  }
2041 
2042  return set_case(C, ccase);
2043 }
2044 
2046 {
2047  /* identifiers */
2048  ot->name = "Toggle Case";
2049  ot->description = "Toggle font case";
2050  ot->idname = "FONT_OT_case_toggle";
2051 
2052  /* api callbacks */
2055 
2056  /* flags */
2058 }
2059 
2060 /* **************** Open Font ************** */
2061 
2063 {
2064  PropertyPointerRNA *pprop;
2065 
2066  op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
2068 }
2069 
2071 {
2072  MEM_freeN(op->customdata);
2073  op->customdata = NULL;
2074 }
2075 
2077 {
2078  struct Main *bmain = CTX_data_main(C);
2079  VFont *font;
2080  PropertyPointerRNA *pprop;
2081  PointerRNA idptr;
2082  char filepath[FILE_MAX];
2083  RNA_string_get(op->ptr, "filepath", filepath);
2084 
2085  font = BKE_vfont_load(bmain, filepath);
2086 
2087  if (!font) {
2088  if (op->customdata) {
2089  MEM_freeN(op->customdata);
2090  }
2091  return OPERATOR_CANCELLED;
2092  }
2093 
2094  if (!op->customdata) {
2095  font_ui_template_init(C, op);
2096  }
2097 
2098  /* hook into UI */
2099  pprop = op->customdata;
2100 
2101  if (pprop->prop) {
2102  /* when creating new ID blocks, use is already 1, but RNA
2103  * pointer use also increases user, so this compensates it */
2104  id_us_min(&font->id);
2105 
2106  RNA_id_pointer_create(&font->id, &idptr);
2107  RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
2108  RNA_property_update(C, &pprop->ptr, pprop->prop);
2109  }
2110 
2111  MEM_freeN(op->customdata);
2112 
2113  return OPERATOR_FINISHED;
2114 }
2115 
2116 static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2117 {
2118  VFont *vfont = NULL;
2119  const char *path;
2120 
2121  PointerRNA idptr;
2122  PropertyPointerRNA *pprop;
2123 
2124  font_ui_template_init(C, op);
2125 
2126  /* hook into UI */
2127  pprop = op->customdata;
2128 
2129  if (pprop->prop) {
2130  idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
2131  vfont = (VFont *)idptr.owner_id;
2132  }
2133 
2134  path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->filepath : U.fontdir;
2135 
2136  if (RNA_struct_property_is_set(op->ptr, "filepath")) {
2137  return font_open_exec(C, op);
2138  }
2139 
2140  RNA_string_set(op->ptr, "filepath", path);
2142 
2143  return OPERATOR_RUNNING_MODAL;
2144 }
2145 
2147 {
2148  /* identifiers */
2149  ot->name = "Open Font";
2150  ot->idname = "FONT_OT_open";
2151  ot->description = "Load a new font from a file";
2152 
2153  /* api callbacks */
2154  ot->exec = font_open_exec;
2155  ot->invoke = open_invoke;
2157 
2158  /* flags */
2160 
2161  /* properties */
2164  FILE_SPECIAL,
2165  FILE_OPENFILE,
2169 }
2170 
2173 /* -------------------------------------------------------------------- */
2178 {
2179  VFont *builtin_font;
2180 
2181  PointerRNA idptr;
2182  PropertyPointerRNA pprop;
2183 
2185 
2186  if (pprop.prop == NULL) {
2187  BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
2188  return OPERATOR_CANCELLED;
2189  }
2190 
2191  builtin_font = BKE_vfont_builtin_get();
2192 
2193  RNA_id_pointer_create(&builtin_font->id, &idptr);
2194  RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL);
2195  RNA_property_update(C, &pprop.ptr, pprop.prop);
2196 
2197  return OPERATOR_FINISHED;
2198 }
2199 
2201 {
2202  /* identifiers */
2203  ot->name = "Unlink";
2204  ot->idname = "FONT_OT_unlink";
2205  ot->description = "Unlink active font data-block";
2206 
2207  /* api callbacks */
2209 }
2210 
2215  bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
2216 {
2218  Object *obedit = CTX_data_edit_object(C);
2219  Curve *cu = obedit->data;
2220  ViewContext vc;
2221  /* bias against the active, in pixels, allows cycling */
2222  const float active_bias_px = 4.0f;
2223  const float mval_fl[2] = {UNPACK2(mval)};
2224  const int i_actbox = max_ii(0, cu->actbox - 1);
2225  int i_iter, actbox_select = -1;
2226  const float dist = ED_view3d_select_dist_px();
2227  float dist_sq_best = dist * dist;
2228 
2230 
2232 
2233  /* currently only select active */
2234  (void)extend;
2235  (void)deselect;
2236  (void)toggle;
2237 
2238  for (i_iter = 0; i_iter < cu->totbox; i_iter++) {
2239  int i = (i_iter + i_actbox) % cu->totbox;
2240  float dist_sq_min;
2241  int j, j_prev;
2242 
2243  float obedit_co[4][3];
2244  float screen_co[4][2];
2245  rctf rect;
2246  int project_ok = 0;
2247 
2248  BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect);
2249 
2250  copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f);
2251  copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f);
2252  copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f);
2253  copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f);
2254 
2255  for (j = 0; j < 4; j++) {
2257  vc.region, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK) {
2258  project_ok |= (1 << j);
2259  }
2260  }
2261 
2262  dist_sq_min = dist_sq_best;
2263  for (j = 0, j_prev = 3; j < 4; j_prev = j++) {
2264  if ((project_ok & (1 << j)) && (project_ok & (1 << j_prev))) {
2265  const float dist_test_sq = dist_squared_to_line_segment_v2(
2266  mval_fl, screen_co[j_prev], screen_co[j]);
2267  if (dist_sq_min > dist_test_sq) {
2268  dist_sq_min = dist_test_sq;
2269  }
2270  }
2271  }
2272 
2273  /* Bias in pixels to cycle selection. */
2274  if (i_iter == 0) {
2275  dist_sq_min += active_bias_px;
2276  }
2277 
2278  if (dist_sq_min < dist_sq_best) {
2279  dist_sq_best = dist_sq_min;
2280  actbox_select = i + 1;
2281  }
2282  }
2283 
2284  if (actbox_select != -1) {
2285  if (cu->actbox != actbox_select) {
2286  cu->actbox = actbox_select;
2288  }
2289  return true;
2290  }
2291  return false;
2292 }
2293 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:769
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
Definition: curve.c:5546
void BKE_curve_editfont_free(struct Curve *cu)
Definition: curve.c:346
bool BKE_vfont_is_builtin(struct VFont *vfont)
Definition: font.c:222
void BKE_vfont_select_clamp(struct Object *ob)
Definition: font.c:657
bool BKE_vfont_to_curve(struct Object *ob, int mode)
Definition: font.c:1743
int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end)
Definition: font.c:617
struct VFont * BKE_vfont_load(struct Main *bmain, const char *filepath)
Definition: font.c:315
struct VFont * BKE_vfont_builtin_get(void)
Definition: font.c:412
void BKE_vfont_clipboard_set(const char32_t *text_buf, const struct CharInfo *info_buf, const size_t len)
void BKE_vfont_clipboard_free(void)
Definition: font.c:1761
void BKE_vfont_clipboard_get(char32_t **r_text_buf, struct CharInfo **r_info_buf, size_t *r_len_utf8, size_t *r_len_utf32)
Definition: font.c:1799
void id_us_min(struct ID *id)
Definition: lib_id.c:297
void id_us_plus(struct ID *id)
Definition: lib_id.c:288
General operations, lookup, etc. for blender objects.
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object.c:3653
struct Object * BKE_object_add(struct Main *bmain, struct ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
void * BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size)
Definition: storage.c:508
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:338
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:794
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])
#define FILE_MAX
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:201
void BLI_str_cursor_step_utf32(const char32_t *str, size_t maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
@ STRCUR_DIR_NEXT
@ STRCUR_DIR_PREV
@ STRCUR_JUMP_DELIM
size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL()
Definition: string_utf8.c:344
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL()
Definition: string_utf8.c:357
unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONNULL()
Definition: string_utf8.c:533
size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_NONNULL()
Definition: string_utf8.c:755
size_t BLI_str_utf32_as_utf8(char *__restrict dst, const char32_t *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string_utf8.c:717
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) ATTR_NONNULL()
Definition: string_utf8.c:684
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNPACK2(a)
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ 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_SPECIAL
@ FILE_TYPE_TEXT
@ FILE_TYPE_FOLDER
@ FILE_TYPE_FTFONT
@ FILE_OPENFILE
@ FILE_DEFAULTDISPLAY
#define FO_CURS
#define FO_CURS_IS_MOTION(mode)
#define FO_CURSDOWN
#define FO_CURSUP
#define FO_PAGEUP
#define FO_EDIT
#define FO_PAGEDOWN
#define FO_SELCHANGE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_object_base_init_transform_on_add(struct Object *object, const float loc[3], const float rot[3])
Definition: object_add.c:319
void ED_outliner_select_sync_from_object_tag(struct bContext *C)
Definition: outliner_sync.c:56
bool ED_operator_editfont(struct bContext *C)
Definition: screen_ops.c:589
bool ED_operator_object_active_editable_font(struct bContext *C)
Definition: screen_ops.c:391
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
Definition: space_view3d.c:190
@ V3D_PROJ_TEST_CLIP_BB
Definition: ED_view3d.h:194
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *region, const float co[3], float r_co[2], const eV3DProjTest flag)
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:176
float ED_view3d_select_dist_px(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
#define C
Definition: RandGen.cpp:39
void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop)
#define WM_FILESEL_RELPATH
Definition: WM_api.h:533
#define WM_FILESEL_FILEPATH
Definition: WM_api.h:537
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NA_ADDED
Definition: WM_types.h:464
#define NC_OBJECT
Definition: WM_types.h:280
#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
Definition: curve_intern.h:40
@ DEL_PREV_WORD
Definition: curve_intern.h:39
@ DEL_PREV_SEL
Definition: curve_intern.h:42
@ DEL_PREV_CHAR
Definition: curve_intern.h:37
@ DEL_NEXT_WORD
Definition: curve_intern.h:38
@ DEL_NEXT_CHAR
Definition: curve_intern.h:36
@ DEL_NEXT_SEL
Definition: curve_intern.h:41
@ NEXT_LINE
Definition: curve_intern.h:53
@ LINE_BEGIN
Definition: curve_intern.h:46
@ PREV_WORD
Definition: curve_intern.h:50
@ PREV_LINE
Definition: curve_intern.h:52
@ PREV_CHAR
Definition: curve_intern.h:48
@ LINE_END
Definition: curve_intern.h:47
@ PREV_PAGE
Definition: curve_intern.h:54
@ NEXT_PAGE
Definition: curve_intern.h:55
@ NEXT_WORD
Definition: curve_intern.h:51
@ CASE_LOWER
Definition: curve_intern.h:44
@ CASE_UPPER
Definition: curve_intern.h:44
Scene scene
const Depsgraph * depsgraph
static int set_case(bContext *C, int ccase)
Definition: editfont.c:1957
void FONT_OT_textbox_add(wmOperatorType *ot)
Definition: editfont.c:1807
void FONT_OT_style_toggle(wmOperatorType *ot)
Definition: editfont.c:854
void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
Definition: editfont.c:716
static void text_update_edited(bContext *C, Object *obedit, int mode)
Definition: editfont.c:408
void FONT_OT_text_copy(wmOperatorType *ot)
Definition: editfont.c:953
static bool font_paste_wchar(Object *obedit, const char32_t *str, const size_t str_len, struct CharInfo *str_info)
Definition: editfont.c:488
void FONT_OT_line_break(wmOperatorType *ot)
Definition: editfont.c:1459
static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: editfont.c:2116
static void font_open_cancel(bContext *UNUSED(C), wmOperator *op)
Definition: editfont.c:2070
static void copy_selection(Object *obedit)
Definition: editfont.c:918
void FONT_OT_unlink(wmOperatorType *ot)
Definition: editfont.c:2200
static int paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: editfont.c:597
static int kill_selection(Object *obedit, int ins)
Definition: editfont.c:443
void ED_curve_editfont_make(Object *obedit)
Definition: editfont.c:1874
void FONT_OT_select_all(wmOperatorType *ot)
Definition: editfont.c:897
static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:879
static int change_spacing_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1318
void FONT_OT_move(wmOperatorType *ot)
Definition: editfont.c:1258
static int change_character_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1386
static int toggle_style_exec(bContext *C, wmOperator *op)
Definition: editfont.c:836
static int paste_from_file_exec(bContext *C, wmOperator *op)
Definition: editfont.c:585
static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: editfont.c:1663
#define MAXTEXT
Definition: editfont.c:70
static int paste_text_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1025
void FONT_OT_text_cut(wmOperatorType *ot)
Definition: editfont.c:988
static int set_style_exec(bContext *C, wmOperator *op)
Definition: editfont.c:802
static int move_select_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1282
void FONT_OT_change_spacing(wmOperatorType *ot)
Definition: editfont.c:1354
static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:2024
static void txt_add_object(bContext *C, const TextLine *firstline, int totline, const float offset[3])
Definition: editfont.c:639
void ED_curve_editfont_load(Object *obedit)
Definition: editfont.c:1910
void FONT_OT_change_character(wmOperatorType *ot)
Definition: editfont.c:1412
static const EnumPropertyItem style_items[]
Definition: editfont.c:768
void FONT_OT_delete(wmOperatorType *ot)
Definition: editfont.c:1604
void FONT_OT_textbox_remove(wmOperatorType *ot)
Definition: editfont.c:1851
static int copy_text_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:944
static bool paste_selection(Object *obedit, ReportList *reports)
Definition: editfont.c:1009
static const EnumPropertyItem delete_type_items[]
Definition: editfont.c:1480
void FONT_OT_open(wmOperatorType *ot)
Definition: editfont.c:2146
void FONT_OT_text_paste_from_file(wmOperatorType *ot)
Definition: editfont.c:608
void FONT_OT_move_select(wmOperatorType *ot)
Definition: editfont.c:1289
static const EnumPropertyItem case_items[]
Definition: editfont.c:1951
static int insert_text_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1633
static int font_open_exec(bContext *C, wmOperator *op)
Definition: editfont.c:2076
static int font_unlink_exec(bContext *C, wmOperator *op)
Definition: editfont.c:2177
static int textbox_remove_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1828
static int move_cursor(bContext *C, int type, const bool select)
Definition: editfont.c:1126
static int delete_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1491
static int set_style(bContext *C, const int style, const bool clear)
Definition: editfont.c:776
void FONT_OT_case_set(wmOperatorType *ot)
Definition: editfont.c:2000
void FONT_OT_case_toggle(wmOperatorType *ot)
Definition: editfont.c:2045
static int paste_from_file(bContext *C, ReportList *reports, const char *filename)
Definition: editfont.c:557
static int set_case_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1995
void ED_curve_editfont_free(Object *obedit)
Definition: editfont.c:1940
static void font_ui_template_init(bContext *C, wmOperator *op)
Definition: editfont.c:2062
void FONT_OT_text_paste(wmOperatorType *ot)
Definition: editfont.c:1091
static int insert_into_textbuf(Object *obedit, uintptr_t c)
Definition: editfont.c:380
static int line_break_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:1444
void FONT_OT_text_insert(wmOperatorType *ot)
Definition: editfont.c:1756
static int textbox_add_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:1787
static int move_exec(bContext *C, wmOperator *op)
Definition: editfont.c:1251
static char32_t findaccent(char32_t char1, uint code)
Definition: editfont.c:80
bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
Definition: editfont.c:2214
void FONT_OT_style_set(wmOperatorType *ot)
Definition: editfont.c:810
static int cut_text_exec(bContext *C, wmOperator *UNUSED(op))
Definition: editfont.c:971
static const EnumPropertyItem move_type_items[]
Definition: editfont.c:1112
static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
Definition: editfont.c:533
#define rot(x, k)
#define str(s)
size_t len_utf8
Definition: font.c:1758
uint pos
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void clear(Message *msg)
Definition: msgfmt.c:294
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
Definition: rna_access.c:3673
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3641
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2317
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:6514
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:6685
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
Definition: rna_access.c:6527
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3675
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
_W64 unsigned int uintptr_t
Definition: stdint.h:122
struct Object * object
struct VFont * vfont
int len_char32
struct CharInfo curinfo
struct TextBox * tb
int selstart
struct EditFont * editfont
struct CharInfo * strinfo
char * str
int selend
Definition: BKE_font.h:59
int pos
Definition: BKE_font.h:58
int len
Definition: BKE_font.h:58
char32_t * textbuf
Definition: BKE_font.h:48
int selstart
Definition: BKE_font.h:59
struct CharInfo * textbufinfo
Definition: BKE_font.h:49
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
float loc[3]
void * data
struct ID * owner_id
Definition: RNA_types.h:50
struct PropertyRNA * prop
Definition: RNA_types.h:57
PointerRNA ptr
Definition: RNA_types.h:56
float viewinv[4][4]
char * line
struct TextLine * next
ListBase lines
char filepath[1024]
struct ARegion * region
Definition: ED_view3d.h:80
struct Object * obedit
Definition: ED_view3d.h:79
struct RegionView3D * rv3d
Definition: ED_view3d.h:83
struct Base * basact
char utf8_buf[6]
Definition: WM_types.h:589
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
uint len
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_TABKEY
@ EVT_BACKSPACEKEY
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, short action, short flag, short display, short sort)
void WM_clipboard_text_set(const char *buf, bool selection)
Definition: wm_window.c:1778
char * WM_clipboard_text_get(bool selection, int *r_len)
Definition: wm_window.c:1765