2
* $Id: editfont.c 19983 2009-04-29 19:13:32Z genscher $
4
* ***** BEGIN GPL LICENSE BLOCK *****
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software Foundation,
18
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21
* All rights reserved.
23
* The Original Code is: all of this file.
25
* Contributor(s): none yet.
27
* ***** END GPL LICENSE BLOCK *****
45
#include "MTC_matrixops.h"
47
#include "MEM_guardedalloc.h"
49
#include "BLI_blenlib.h"
50
#include "BLI_arithb.h"
52
#include "DNA_curve_types.h"
53
#include "DNA_object_types.h"
54
#include "DNA_vfont_types.h"
55
#include "DNA_scene_types.h"
56
#include "DNA_text_types.h"
57
#include "DNA_view3d_types.h"
58
#include "DNA_userdef_types.h"
60
#include "BKE_depsgraph.h"
62
#include "BKE_object.h"
63
#include "BKE_global.h"
65
#include "BKE_utildefines.h"
67
#include "BIF_editfont.h"
68
#include "BIF_editmode_undo.h"
69
#include "BIF_toolbox.h"
70
#include "BIF_space.h"
71
#include "BIF_mywindow.h"
73
#include "BDR_editobject.h"
81
/* -- prototypes --------*/
82
VFont *get_builtin_font(void);
86
extern struct SelBox *selboxes; /* from blenkernel/font.c */
88
static char findaccent(char char1, unsigned int code)
93
if(code=='`') new= 224;
94
else if(code==39) new= 225;
95
else if(code=='^') new= 226;
96
else if(code=='~') new= 227;
97
else if(code=='"') new= 228;
98
else if(code=='o') new= 229;
99
else if(code=='e') new= 230;
100
else if(code=='-') new= 170;
102
else if(char1=='c') {
103
if(code==',') new= 231;
104
if(code=='|') new= 162;
106
else if(char1=='e') {
107
if(code=='`') new= 232;
108
else if(code==39) new= 233;
109
else if(code=='^') new= 234;
110
else if(code=='"') new= 235;
112
else if(char1=='i') {
113
if(code=='`') new= 236;
114
else if(code==39) new= 237;
115
else if(code=='^') new= 238;
116
else if(code=='"') new= 239;
118
else if(char1=='n') {
119
if(code=='~') new= 241;
121
else if(char1=='o') {
122
if(code=='`') new= 242;
123
else if(code==39) new= 243;
124
else if(code=='^') new= 244;
125
else if(code=='~') new= 245;
126
else if(code=='"') new= 246;
127
else if(code=='/') new= 248;
128
else if(code=='-') new= 186;
129
else if(code=='e') new= 143;
131
else if(char1=='s') {
132
if(code=='s') new= 167;
134
else if(char1=='u') {
135
if(code=='`') new= 249;
136
else if(code==39) new= 250;
137
else if(code=='^') new= 251;
138
else if(code=='"') new= 252;
140
else if(char1=='y') {
141
if(code==39) new= 253;
142
else if(code=='"') new= 255;
144
else if(char1=='A') {
145
if(code=='`') new= 192;
146
else if(code==39) new= 193;
147
else if(code=='^') new= 194;
148
else if(code=='~') new= 195;
149
else if(code=='"') new= 196;
150
else if(code=='o') new= 197;
151
else if(code=='e') new= 198;
153
else if(char1=='C') {
154
if(code==',') new= 199;
156
else if(char1=='E') {
157
if(code=='`') new= 200;
158
else if(code==39) new= 201;
159
else if(code=='^') new= 202;
160
else if(code=='"') new= 203;
162
else if(char1=='I') {
163
if(code=='`') new= 204;
164
else if(code==39) new= 205;
165
else if(code=='^') new= 206;
166
else if(code=='"') new= 207;
168
else if(char1=='N') {
169
if(code=='~') new= 209;
171
else if(char1=='O') {
172
if(code=='`') new= 210;
173
else if(code==39) new= 211;
174
else if(code=='^') new= 212;
175
else if(code=='~') new= 213;
176
else if(code=='"') new= 214;
177
else if(code=='/') new= 216;
178
else if(code=='e') new= 141;
180
else if(char1=='U') {
181
if(code=='`') new= 217;
182
else if(code==39) new= 218;
183
else if(code=='^') new= 219;
184
else if(code=='"') new= 220;
186
else if(char1=='Y') {
187
if(code==39) new= 221;
189
else if(char1=='1') {
190
if(code=='4') new= 188;
191
if(code=='2') new= 189;
193
else if(char1=='3') {
194
if(code=='4') new= 190;
196
else if(char1==':') {
197
if(code=='-') new= 247;
199
else if(char1=='-') {
200
if(code==':') new= 247;
201
if(code=='|') new= 135;
202
if(code=='+') new= 177;
204
else if(char1=='|') {
205
if(code=='-') new= 135;
206
if(code=='=') new= 136;
208
else if(char1=='=') {
209
if(code=='|') new= 136;
211
else if(char1=='+') {
212
if(code=='-') new= 177;
219
wchar_t *copybuf=NULL;
220
wchar_t *copybufinfo=NULL;
222
static wchar_t *textbuf=NULL;
223
static CharInfo *textbufinfo=NULL;
224
static wchar_t *oldstr=NULL;
225
static CharInfo *oldstrinfo=NULL;
227
void update_string(Curve *cu)
231
// Free the old curve string
234
// Calculate the actual string length in UTF-8 variable characters
235
len = wcsleninu8(textbuf);
237
// Alloc memory for UTF-8 variable char length string
238
cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
240
// Copy the wchar to UTF-8
241
wcs2utf8s(cu->str, textbuf);
244
static int insert_into_textbuf(Curve *cu, uintptr_t c)
246
if (cu->len<MAXTEXT-1) {
249
for(x= cu->len; x>cu->pos; x--) textbuf[x]= textbuf[x-1];
250
for(x= cu->len; x>cu->pos; x--) textbufinfo[x]= textbufinfo[x-1];
252
textbufinfo[cu->pos] = cu->curinfo;
253
textbufinfo[cu->pos].kern = 0;
254
if (G.obedit->actcol>0)
255
textbufinfo[cu->pos].mat_nr = G.obedit->actcol;
257
textbufinfo[cu->pos].mat_nr = 0;
261
textbuf[cu->len]='\0';
275
Curve *cu=G.obedit->data;
276
static char* lastlorem;
283
i= rand()/(RAND_MAX/6)+4;
285
for (p2=p; *p2 && i; p2++) {
286
insert_into_textbuf(cu, *p2);
290
if (strlen(lastlorem)<5) lastlorem = BIF_lorem;
292
insert_into_textbuf(cu, '\n');
293
insert_into_textbuf(cu, '\n');
294
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
295
allqueue(REDRAWVIEW3D, 0);
298
void load_3dtext_fs(char *file)
303
Curve *cu=G.obedit->data;
305
fp= fopen(file, "r");
308
fseek(fp, 0L, SEEK_END);
310
fseek(fp, 0L, SEEK_SET);
312
strp = MEM_callocN(filelen+4, "tempstr");
314
filelen = fread(strp, 1, filelen, fp);
318
if(cu->len+filelen<MAXTEXT)
321
wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
322
tmplen = utf8towchar(mem, strp);
323
wcscat(textbuf, mem);
332
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
333
allqueue(REDRAWVIEW3D, 0);
336
VFont *get_builtin_font(void)
340
for (vf= G.main->vfont.first; vf; vf= vf->id.next)
341
if (BLI_streq(vf->name, "<builtin>"))
344
return load_vfont("<builtin>");
348
void txt_export_to_object(struct Text *text)
352
struct TextLine *tmp;
354
// char sdir[FILE_MAXDIR];
355
// char sfile[FILE_MAXFILE];
357
if(!text || !text->lines.first) return;
361
if (G.obedit && G.obedit->type==OB_FONT) return;
362
check_editmode(OB_FONT);
366
base_init_from_view3d(BASACT, G.vd);
367
G.obedit= BASACT->object;
368
where_is_object(G.obedit);
373
// renames object, careful with long filenames.
376
//ID *find_id(char *type, char *name)
377
BLI_split_dirfile(text->name, sdir, sfile);
378
// rename_id((ID *)G.obedit, sfile);
379
rename_id((ID *)cu, sfile);
383
cu->vfont= get_builtin_font();
386
tmp= text->lines.first;
387
while(cu->len<MAXTEXT && tmp) {
388
nchars += strlen(tmp->line) + 1;
392
if(cu->str) MEM_freeN(cu->str);
393
if(cu->strinfo) MEM_freeN(cu->strinfo);
395
cu->str= MEM_mallocN(nchars+4, "str");
396
cu->strinfo= MEM_callocN((nchars+4)*sizeof(CharInfo), "strinfo");
397
cu->totbox= cu->actbox= 1;
398
cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
399
cu->tb[0].w = cu->tb[0].h = 0.0;
401
tmp= text->lines.first;
402
strcpy(cu->str, tmp->line);
403
cu->len= strlen(tmp->line);
408
while(cu->len<MAXTEXT && tmp) {
409
strcat(cu->str, "\n");
410
strcat(cu->str, tmp->line);
411
cu->len+= strlen(tmp->line) + 1;
417
exit_editmode(EM_FREEDATA|EM_WAITCURSOR);
419
allqueue(REDRAWVIEW3D, 0);
423
void txt_export_to_objects(struct Text *text)
427
struct TextLine *curline;
430
float offset[3] = {0.0,0.0,0.0};
432
if(!text || !text->lines.first) return;
436
if (G.obedit && G.obedit->type==OB_FONT) return;
437
check_editmode(OB_FONT);
439
curline = text->lines.first;
441
/*skip lines with no text, but still make space for them*/
442
if(curline->line[0] == '\0'){
444
curline = curline->next;
451
base_init_from_view3d(BASACT, G.vd);
452
G.obedit= BASACT->object;
453
where_is_object(G.obedit);
455
/* Do the translation */
457
offset[1] = -linenum;
460
Mat4Mul3Vecfl(G.vd->viewinv,offset);
462
G.obedit->loc[0] += offset[0];
463
G.obedit->loc[1] += offset[1];
464
G.obedit->loc[2] += offset[2];
465
/* End Translation */
469
cu->vfont= get_builtin_font();
472
nchars = strlen(curline->line) + 1;
474
if(cu->str) MEM_freeN(cu->str);
475
if(cu->strinfo) MEM_freeN(cu->strinfo);
477
cu->str= MEM_mallocN(nchars+4, "str");
478
cu->strinfo= MEM_callocN((nchars+4)*sizeof(CharInfo), "strinfo");
479
cu->totbox= cu->actbox= 1;
480
cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
481
cu->tb[0].w = cu->tb[0].h = 0.0;
483
strcpy(cu->str, curline->line);
484
cu->len= strlen(curline->line);
488
exit_editmode(EM_FREEDATA|EM_WAITCURSOR);
491
curline = curline->next;
493
BIF_undo_push("Add Text as Objects");
494
allqueue(REDRAWVIEW3D, 0);
497
static short next_word(Curve *cu)
500
for (s=cu->pos; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
501
(cu->str[s]!=1) && (cu->str[s]!='\r'); s++);
502
if (cu->str[s]) return(s+1); else return(s);
505
static short prev_word(Curve *cu)
509
if (cu->pos==0) return(0);
510
for (s=cu->pos-2; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
511
(cu->str[s]!=1) && (cu->str[s]!='\r'); s--);
512
if (cu->str[s]) return(s+1); else return(s);
517
static int killselection(int ins) /* 1 == new character */
519
int selend, selstart, direction;
520
Curve *cu= G.obedit->data;
524
direction = getselection(&selstart, &selend);
528
if (cu->pos >= selstart) cu->pos = selstart+offset;
529
if ((direction == -1) && ins) {
533
getfrom = selend+offset;
534
if (ins==0) getfrom++;
535
size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset*sizeof(wchar_t));
536
memmove(textbuf+selstart, textbuf+getfrom, size);
537
memmove(textbufinfo+selstart, textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
538
cu->len -= (selend-selstart)+offset;
539
cu->selstart = cu->selend = 0;
544
static void copyselection(void)
546
int selstart, selend;
548
if (getselection(&selstart, &selend)) {
549
memcpy(copybuf, textbuf+selstart, ((selend-selstart)+1)*sizeof(wchar_t));
550
copybuf[(selend-selstart)+1]=0;
551
memcpy(copybufinfo, textbufinfo+selstart, ((selend-selstart)+1)*sizeof(CharInfo));
555
static void pasteselection(void)
557
Curve *cu= G.obedit->data;
559
int len= wcslen(copybuf);
561
// Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT
562
if(cu->len + len <= MAXTEXT)
565
int size = (cu->len * sizeof(wchar_t)) - (cu->pos*sizeof(wchar_t)) + sizeof(wchar_t);
566
memmove(textbuf+cu->pos+len, textbuf+cu->pos, size);
567
memcpy(textbuf+cu->pos, copybuf, len * sizeof(wchar_t));
569
memmove(textbufinfo+cu->pos+len, textbufinfo+cu->pos, (cu->len-cu->pos+1)*sizeof(CharInfo));
570
memcpy(textbufinfo+cu->pos, copybufinfo, len*sizeof(CharInfo));
578
error("Text too long");
582
int style_to_sel(int style, int toggle)
584
int selstart, selend;
588
if (G.obedit && (G.obedit->type == OB_FONT)) {
591
if (getselection(&selstart, &selend)) {
592
for (i=selstart; i<=selend; i++) {
594
textbufinfo[i].flag &= ~style;
596
textbufinfo[i].flag |= style;
605
int mat_to_sel(void) {
606
int selstart, selend;
610
if (G.obedit && (G.obedit->type == OB_FONT)) {
613
if (getselection(&selstart, &selend)) {
614
for (i=selstart; i<=selend; i++) {
615
textbufinfo[i].mat_nr = G.obedit->actcol;
623
void do_textedit(unsigned short event, short val, uintptr_t _ascii)
626
static int accentcode= 0;
627
int x, doit=0, cursmove=0;
628
uintptr_t ascii = _ascii;
635
/* handle case like TAB (TAB==9) */
636
if( (ascii > 31 && ascii < 254 && ascii != 127) || (ascii==13) || (ascii==10) || (ascii==8)) {
639
if(cu->pos>0) textbuf[cu->pos-1]= findaccent(textbuf[cu->pos-1], ascii);
642
else if(cu->len<MAXTEXT-1) {
643
if(G.qual & LR_ALTKEY ) {
645
/* might become obsolete, apple has default values for this, other OS's too? */
647
if(ascii=='t') ascii= 137;
648
else if(ascii=='c') ascii= 169;
649
else if(ascii=='f') ascii= 164;
650
else if(ascii=='g') ascii= 176;
651
else if(ascii=='l') ascii= 163;
652
else if(ascii=='r') ascii= 174;
653
else if(ascii=='s') ascii= 223;
654
else if(ascii=='v') ascii= 1001;
655
else if(ascii=='y') ascii= 165;
656
else if(ascii=='.') ascii= 138;
657
else if(ascii=='1') ascii= 185;
658
else if(ascii=='2') ascii= 178;
659
else if(ascii=='3') ascii= 179;
660
else if(ascii=='%') ascii= 139;
661
else if(ascii=='?') ascii= 191;
662
else if(ascii=='!') ascii= 161;
663
else if(ascii=='x') ascii= 215;
664
else if(ascii=='>') ascii= 187;
665
else if(ascii=='<') ascii= 171;
671
/* this should be solved by clipboard support */
672
#ifdef __WIN32_DISABLED
673
file= open("C:\\windows\\temp\\cutbuf", O_BINARY|O_RDONLY);
675
file= open("/tmp/.cutbuffer", O_BINARY|O_RDONLY);
679
filelen = BLI_filesize(file);
681
strp= MEM_mallocN(filelen+4, "tempstr");
682
read(file, strp, filelen);
686
if(cu->len+filelen<MAXTEXT) {
688
wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
689
tmplen = utf8towchar(mem, strp);
690
wcscat(textbuf, mem);
699
insert_into_textbuf(cu, ascii);
709
insert_into_textbuf(cu, ascii);
718
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
719
while(cu->pos<cu->len) {
720
if( textbuf[cu->pos]==0) break;
721
if( textbuf[cu->pos]=='\n') break;
722
if( textbufinfo[cu->pos].flag & CU_WRAP ) break;
729
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
731
if( textbuf[cu->pos-1]=='\n') break;
732
if( textbufinfo[cu->pos-1].flag & CU_WRAP ) break;
739
if(G.qual & LR_CTRLKEY) {
740
insert_into_textbuf(cu, 1);
741
if (textbuf[cu->pos]!='\n') insert_into_textbuf(cu, '\n');
744
insert_into_textbuf(cu, '\n');
746
cu->selstart = cu->selend = 0;
751
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
752
if (G.qual & LR_CTRLKEY) {
753
cu->pos= next_word(cu);
756
else if (G.qual & LR_ALTKEY) {
757
kern = textbufinfo[cu->pos-1].kern;
759
if (kern>20) kern = 20;
760
textbufinfo[cu->pos-1].kern = kern;
771
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
772
if (G.qual & LR_CTRLKEY) {
773
cu->pos= prev_word(cu);
776
else if (G.qual & LR_ALTKEY) {
777
kern = textbufinfo[cu->pos-1].kern;
779
if (kern<-20) kern = -20;
780
textbufinfo[cu->pos-1].kern = kern;
790
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
791
if(G.qual & LR_ALTKEY) {
792
if (cu->pos && textbuf[cu->pos - 1] < 255) {
793
textbuf[cu->pos - 1]++;
797
else cursmove=FO_CURSUP;
801
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
806
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
807
if(G.qual & LR_ALTKEY) {
808
if (cu->pos && textbuf[cu->pos - 1] > 1) {
809
textbuf[cu->pos - 1]--;
813
else cursmove= FO_CURSDOWN;
817
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
818
cursmove=FO_PAGEDOWN;
823
if(G.qual & LR_ALTKEY) {
824
if(cu->pos>0) accentcode= 1;
826
else if (G.qual & LR_CTRLKEY) {
827
cu->len = cu->pos = 0;
832
if (killselection(0)==0) {
834
for(x=cu->pos;x<=cu->len;x++) textbuf[x-1]= textbuf[x];
835
for(x=cu->pos;x<=cu->len;x++) textbufinfo[x-1]= textbufinfo[x];
837
textbuf[--cu->len]='\0';
847
if (killselection(0)==0) {
848
if(cu->pos<cu->len) {
849
for(x=cu->pos;x<cu->len;x++) textbuf[x]= textbuf[x+1];
850
for(x=cu->pos;x<cu->len;x++) textbufinfo[x]= textbufinfo[x+1];
851
textbuf[--cu->len]='\0';
859
if (G.qual & LR_CTRLKEY) {
860
cu->curinfo.flag ^= CU_ITALIC;
861
if (style_to_sel(CU_ITALIC, cu->curinfo.flag & CU_ITALIC)) doit= 1;
862
allqueue(REDRAWBUTSEDIT, 0);
867
if (G.qual & LR_CTRLKEY) {
868
cu->curinfo.flag ^= CU_BOLD;
869
if (style_to_sel(CU_BOLD, cu->curinfo.flag & CU_BOLD)) doit= 1;
870
allqueue(REDRAWBUTSEDIT, 0);
875
if (G.qual & LR_CTRLKEY) {
876
cu->curinfo.flag ^= CU_UNDERLINE;
877
if (style_to_sel(CU_UNDERLINE, cu->curinfo.flag & CU_UNDERLINE)) doit= 1;
878
allqueue(REDRAWBUTSEDIT, 0);
883
if (G.qual & LR_CTRLKEY) {
891
if (G.qual & LR_CTRLKEY) {
897
if (G.qual & LR_CTRLKEY) {
906
if ((G.qual & LR_SHIFTKEY)==0) {
908
cu->selstart = cu->selend = 0;
910
text_to_curve(G.obedit, FO_SELCHANGE);
911
allqueue(REDRAWVIEW3D, 0);
914
if(cu->pos>cu->len) cu->pos= cu->len;
915
else if(cu->pos>=MAXTEXT) cu->pos= MAXTEXT;
916
else if(cu->pos<0) cu->pos= 0;
919
if(doit || cursmove) {
922
cu->curinfo = textbufinfo[cu->pos-1];
923
} else cu->curinfo = textbufinfo[0];
925
if (G.obedit->totcol>0) {
926
G.obedit->actcol = textbufinfo[cu->pos-1].mat_nr;
928
allqueue(REDRAWBUTSEDIT, 0);
930
text_to_curve(G.obedit, cursmove);
931
if (cursmove && (G.qual & LR_SHIFTKEY)) {
932
cu->selend = cu->pos;
933
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
936
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
939
BIF_undo_push("Textedit");
940
allqueue(REDRAWVIEW3D, 0);
944
void paste_unicodeText(char *filename)
946
Curve *cu= G.obedit->data;
947
int filelen, doit= 0;
951
fp= fopen(filename, "r");
955
fseek( fp, 0L, SEEK_END );
956
filelen = ftell( fp );
957
fseek( fp, 0L, SEEK_SET );
959
strp= MEM_mallocN(filelen+4, "tempstr");
960
//fread() instead of read(),
961
//because windows read() converts text to DOS \r\n linebreaks
962
//causing double linebreaks in the 3d text
963
filelen = fread(strp, 1, filelen, fp);
968
if(cu->len+filelen<MAXTEXT)
971
wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
972
tmplen = utf8towchar(mem, strp);
973
// mem =utf8s2wc(strp);
974
wcscat(textbuf, mem);
984
text_to_curve(G.obedit, 0);
985
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
986
allqueue(REDRAWVIEW3D, 0);
987
BIF_undo_push("Paste text");
991
void paste_editText(void)
993
Curve *cu= G.obedit->data;
994
int filelen, doit= 0;
999
fp= fopen("C:\\windows\\temp\\cutbuf.txt", "r");
1001
// The following is more likely to work on all Win32 installations.
1002
// suggested by Douglas Toltzman. Needs windows include files...
1004
char tempFileName[MAX_PATH];
1006
static const char cutbufname[]="cutbuf.txt";
1008
if ((pathlen=GetTempPath(sizeof(tempFileName),tempFileName)) > 0 &&
1009
pathlen + sizeof(cutbufname) <= sizeof(tempFileName))
1011
strcat(tempFileName,cutbufname);
1012
file= open(tempFileName, O_BINARY|O_RDONLY);
1016
fp= fopen("/tmp/.cutbuffer", "r");
1021
fseek(fp, 0L, SEEK_END);
1022
filelen = ftell( fp );
1023
fseek(fp, 0L, SEEK_SET);
1025
strp= MEM_mallocN(filelen+4, "tempstr");
1026
// fread() instead of read(),
1027
// because windows read() converts text to DOS \r\n linebreaks
1028
// causing double linebreaks in the 3d text
1029
filelen = fread(strp, 1, filelen, fp);
1033
if(cu->len+filelen<MAXTEXT) {
1035
wchar_t *mem = MEM_callocN((sizeof(wchar_t) * filelen) + (4 * sizeof(wchar_t)), "temporary");
1036
tmplen = utf8towchar(mem, strp);
1037
wcscat(textbuf, mem);
1047
text_to_curve(G.obedit, 0);
1048
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1049
allqueue(REDRAWVIEW3D, 0);
1050
BIF_undo_push("Paste text");
1055
void make_editText(void)
1060
if(textbuf==NULL) textbuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditbuf");
1061
if(textbufinfo==NULL) textbufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditbufinfo");
1062
if(copybuf==NULL) copybuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditcopybuf");
1063
if(copybufinfo==NULL) copybufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditcopybufinfo");
1064
if(oldstr==NULL) oldstr= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "oldstrbuf");
1066
// Convert the original text to wchar_t
1067
utf8towchar(textbuf, cu->str);
1068
wcscpy(oldstr, textbuf);
1070
cu->len= wcslen(textbuf);
1072
memcpy(textbufinfo, cu->strinfo, (cu->len)*sizeof(CharInfo));
1074
oldstrinfo= cu->strinfo;
1075
cu->strinfo= textbufinfo;
1077
if(cu->pos>cu->len) cu->pos= cu->len;
1080
cu->curinfo = textbufinfo[cu->pos-1];
1081
} else cu->curinfo = textbufinfo[0];
1086
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1089
BIF_undo_push("Original");
1093
void load_editText(void)
1101
MEM_freeN(oldstrinfo);
1106
cu->strinfo= MEM_callocN((cu->len+4)*sizeof(CharInfo), "texteditinfo");
1107
memcpy(cu->strinfo, textbufinfo, (cu->len)*sizeof(CharInfo));
1109
cu->len= strlen(cu->str);
1111
/* this memory system is weak... */
1113
MEM_freeN(textbufinfo);
1118
MEM_freeN(selboxes);
1124
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1129
void remake_editText(void)
1133
if(okee("Reload original text")==0) return;
1135
// Copy the oldstr to textbuf temporary global variable
1136
wcscpy(textbuf, oldstr);
1138
// Set the object length and position
1140
cu->len= wcslen(textbuf);
1141
if(cu->pos>cu->len) cu->pos= cu->len;
1145
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1146
allqueue(REDRAWVIEW3D, 0);
1148
BIF_undo_push("Reload");
1152
void free_editText(void)
1154
if(oldstr) MEM_freeN(oldstr);
1155
if(oldstrinfo) MEM_freeN(oldstrinfo);
1156
if(textbuf) MEM_freeN(textbuf);
1157
textbuf = oldstr = NULL;
1158
textbufinfo = oldstrinfo = NULL;
1163
void add_primitiveFont(int dummy_argument)
1167
if (G.obedit && G.obedit->type==OB_FONT) return;
1168
check_editmode(OB_FONT);
1170
add_object_draw(OB_FONT);
1171
base_init_from_view3d(BASACT, G.vd);
1173
where_is_object(BASACT->object);
1175
cu= BASACT->object->data;
1177
cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font();
1178
cu->vfont->id.us+=4;
1179
cu->str= MEM_mallocN(12, "str");
1180
strcpy(cu->str, "Text");
1182
cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo");
1183
cu->totbox= cu->actbox= 1;
1184
cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
1185
cu->tb[0].w = cu->tb[0].h = 0.0;
1187
if (U.flag & USER_ADD_EDITMODE)
1188
enter_editmode(EM_WAITCURSOR);
1190
allqueue(REDRAWALL, 0);
1206
len= wcslen(textbuf);
1209
if( *str>=97 && *str<=122) {
1218
len= wcslen(textbuf);
1221
if( *str>=65 && *str<=90) {
1228
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1229
allqueue(REDRAWVIEW3D, 0);
1230
BIF_undo_push("To upper");
1236
/* **************** undo for font object ************** */
1238
static void undoFont_to_editFont(void *strv)
1240
Curve *cu= G.obedit->data;
1243
cu->pos= *((short *)str);
1244
cu->len= *((short *)(str+2));
1246
memcpy(textbuf, str+4, (cu->len+1)*sizeof(wchar_t));
1247
memcpy(textbufinfo, str+4 + (cu->len+1)*sizeof(wchar_t), cu->len*sizeof(CharInfo));
1249
cu->selstart = cu->selend = 0;
1250
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1254
allqueue(REDRAWVIEW3D, 0);
1257
static void *editFont_to_undoFont(void)
1259
Curve *cu= G.obedit->data;
1262
// The undo buffer includes [MAXTEXT+6]=actual string and [MAXTEXT+4]*sizeof(CharInfo)=charinfo
1263
str= MEM_callocN((MAXTEXT+6)*sizeof(wchar_t) + (MAXTEXT+4)*sizeof(CharInfo), "string undo");
1265
// Copy the string and string information
1266
memcpy(str+4, textbuf, (cu->len+1)*sizeof(wchar_t));
1267
memcpy(str+4 + (cu->len+1)*sizeof(wchar_t), textbufinfo, cu->len*sizeof(CharInfo));
1269
*((short *)str)= cu->pos;
1270
*((short *)(str+2))= cu->len;
1275
static void free_undoFont(void *strv)
1280
/* and this is all the undo system needs to know */
1281
void undo_push_font(char *name)
1283
undo_editmode_push(name, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);