Text3d: store number of characters and utf8 length separately
authorCampbell Barton <ideasman42@gmail.com>
Fri, 3 Jan 2014 06:04:42 +0000 (17:04 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 3 Jan 2014 06:08:23 +0000 (17:08 +1100)
EditFont's use of Curve.len was very confusing, in editmode it
represented the number of characters, in object mode the number of
bytes. add Curve.len_wchar and keep track of both.

Also don't convert the editmode text into utf8 on every keystroke.
Now this is done on exiting editmode or save - to match most other
object types.

This also fixes curves 'body_format' being reported with an invalid size.

source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/font.c
source/blender/blenloader/intern/versioning_260.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/curve/editfont.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesrna/intern/rna_curve.c

index f397e6be2c9da6f4342dcfe02fd11589713252f5..e2f86c266269f29d410523a8319df1f197b73b74 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         269
-#define BLENDER_SUBVERSION      7
+#define BLENDER_SUBVERSION      8
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
 #define BLENDER_MINSUBVERSION   0
index 76fc7350d19901befacefe60ca22f4c401e3366e..16cbcde01679c1665584ce92e507b4134fc17f40 100644 (file)
@@ -65,6 +65,11 @@ typedef struct EditFont {
        struct CharInfo *textbufinfo;
        
        float textcurs[4][2];
+
+       /* positional vars relative to the textbuf, textbufinfo (not utf8 bytes)
+        * a copy of these is kept in Curve, but use these in editmode */
+       int len, pos;
+       int selstart, selend;
        
 } EditFont;
 
@@ -80,7 +85,7 @@ struct VFont *BKE_vfont_load(struct Main *bmain, const char *name);
 bool BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode,
                         struct CharTrans **r_chartransdata);
 
-int BKE_vfont_select_get(struct Object *ob, int *start, int *end);
+int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
 
 #ifdef __cplusplus
 }
index 1c4560cd2b26377d751a03eb0ba640a03a354615..d1dde91feb67decec59c4bc83158697a857a6478 100644 (file)
@@ -190,7 +190,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
                cu->vfont->id.us += 4;
                cu->str = MEM_mallocN(12, "str");
                BLI_strncpy(cu->str, "Text", 12);
-               cu->len = cu->pos = 4;
+               cu->len = cu->len_wchar = cu->pos = 4;
                cu->strinfo = MEM_callocN(12 * sizeof(CharInfo), "strinfo new");
                cu->totbox = cu->actbox = 1;
                cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "textbox");
@@ -4041,7 +4041,7 @@ void BKE_curve_material_index_remove(Curve *cu, int index)
        if (curvetype == OB_FONT) {
                struct CharInfo *info = cu->strinfo;
                int i;
-               for (i = cu->len - 1; i >= 0; i--, info++) {
+               for (i = cu->len_wchar - 1; i >= 0; i--, info++) {
                        if (info->mat_nr && info->mat_nr >= index) {
                                info->mat_nr--;
                        }
@@ -4068,7 +4068,7 @@ void BKE_curve_material_index_clear(Curve *cu)
        if (curvetype == OB_FONT) {
                struct CharInfo *info = cu->strinfo;
                int i;
-               for (i = cu->len - 1; i >= 0; i--, info++) {
+               for (i = cu->len_wchar - 1; i >= 0; i--, info++) {
                        info->mat_nr = 0;
                }
        }
index 90362c7a3ade9d3788f68dd27627cadd724e4d25..222251f6e5ee36ae2560f8fbf7a84f37453625bb 100644 (file)
@@ -457,25 +457,26 @@ static void buildchar(Main *bmain, Curve *cu, unsigned int character, CharInfo *
        }
 }
 
-int BKE_vfont_select_get(Object *ob, int *start, int *end)
+int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
 {
        Curve *cu = ob->data;
+       EditFont *ef = cu->editfont;
        
-       if (cu->editfont == NULL || ob->type != OB_FONT) return 0;
+       if ((ob->type != OB_FONT) || (ef == NULL)) return 0;
 
-       BLI_assert(cu->selstart >= 0 && cu->selstart <= cu->len + 1);
-       BLI_assert(cu->selend   >= 0 && cu->selend   <= cu->len + 1);
-       BLI_assert(cu->pos      >= 0 && cu->pos      <= cu->len);
+       BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1);
+       BLI_assert(ef->selend   >= 0 && ef->selend   <= ef->len + 1);
+       BLI_assert(ef->pos      >= 0 && ef->pos      <= ef->len);
 
-       if (cu->selstart == 0) return 0;
-       if (cu->selstart <= cu->selend) {
-               *start = cu->selstart - 1;
-               *end = cu->selend - 1;
+       if (ef->selstart == 0) return 0;
+       if (ef->selstart <= ef->selend) {
+               *r_start = ef->selstart - 1;
+               *r_end = ef->selend - 1;
                return 1;
        }
        else {
-               *start = cu->selend;
-               *end = cu->selstart - 2;
+               *r_start = ef->selend;
+               *r_end = ef->selstart - 2;
                return -1;
        }
 }
@@ -497,9 +498,10 @@ static float char_width(Curve *cu, VChar *che, CharInfo *info)
 bool BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode,
                         struct CharTrans **r_chartransdata)
 {
+       Curve *cu = ob->data;
+       EditFont *ef = cu->editfont;
        VFont *vfont, *oldvfont;
        VFontData *vfd = NULL;
-       Curve *cu;
        CharInfo *info = NULL, *custrinfo;
        TextBox *tb;
        VChar *che;
@@ -519,7 +521,6 @@ bool BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode,
        BLI_assert(ob->type == OB_FONT);
 
        /* Set font data */
-       cu = (Curve *) ob->data;
        vfont = cu->vfont;
 
        if (cu->str == NULL) return ok;
@@ -533,20 +534,18 @@ bool BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode,
        if (cu->ulheight == 0.0f)
                cu->ulheight = 0.05f;
        
-       if (cu->editfont) {
-               slen = cu->len;
-               mem = cu->editfont->textbuf;
-               custrinfo = cu->editfont->textbufinfo;
+       if (ef) {
+               slen = ef->len;
+               mem = ef->textbuf;
+               custrinfo = ef->textbufinfo;
        }
        else {
-               size_t utf8len;
-
-               utf8len = BLI_strlen_utf8(cu->str);
+               slen = cu->len_wchar;
 
                /* Create unicode string */
-               mem = MEM_mallocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
+               mem = MEM_mallocN(((slen + 1) * sizeof(wchar_t)), "convertedmem");
 
-               slen = BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1);
+               BLI_strncpy_wchar_from_utf8(mem, cu->str, slen + 1);
 
                if (cu->strinfo == NULL) {  /* old file */
                        cu->strinfo = MEM_callocN((slen + 4) * sizeof(CharInfo), "strinfo compat");
@@ -945,10 +944,8 @@ makebreak:
        }
 
        if (mode == FO_CURSUP || mode == FO_CURSDOWN || mode == FO_PAGEUP || mode == FO_PAGEDOWN) {
-               /* 2: curs up
-                * 3: curs down */
-               ct = chartransdata + cu->pos;
-               
+               ct = &chartransdata[ef->pos];
+
                if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) {
                        /* pass */
                }
@@ -964,7 +961,7 @@ makebreak:
                        }
                        cnr = ct->charnr;
                        /* seek for char with lnr en cnr */
-                       cu->pos = 0;
+                       ef->pos = 0;
                        ct = chartransdata;
                        for (i = 0; i < slen; i++) {
                                if (ct->linenr == lnr) {
@@ -975,21 +972,21 @@ makebreak:
                                else if (ct->linenr > lnr) {
                                        break;
                                }
-                               cu->pos++;
+                               ef->pos++;
                                ct++;
                        }
                }
        }
        
        /* cursor first */
-       if (cu->editfont) {
+       if (ef) {
                float si, co;
                
-               ct = chartransdata + cu->pos;
+               ct = &chartransdata[ef->pos];
                si = sinf(ct->rot);
                co = cosf(ct->rot);
 
-               f = cu->editfont->textcurs[0];
+               f = ef->textcurs[0];
                
                f[0] = cu->fsize * (-0.1f * co + ct->xof);
                f[1] = cu->fsize * ( 0.1f * si + ct->yof);
@@ -1071,8 +1068,7 @@ makebreak:
                                        mem[0] = ascii;
                                        mem[1] = 0;
                                        custrinfo[0] = *info;
-                                       cu->pos = 1;
-                                       cu->len = 1;
+                                       cu->len = cu->len_wchar = cu->pos = 1;
                                        mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
                                        outta = 1;
                                        cu->sepchar = 0;
@@ -1086,14 +1082,16 @@ makebreak:
 
 finally:
 
-       if (cu->editfont == NULL)
+       if (ef == NULL)
                MEM_freeN(mem);
 
-       if (r_chartransdata) {
-               *r_chartransdata = chartransdata;
-       }
-       else {
-               MEM_freeN(chartransdata);
+       if (chartransdata) {
+               if (ok && r_chartransdata) {
+                       *r_chartransdata = chartransdata;
+               }
+               else {
+                       MEM_freeN(chartransdata);
+               }
        }
 
        return ok;
index d63b72bc4c114714b93bc028fdf0032ff1df26fa..d8e3e02b196787bfbfacfc74057fe91ba2fb7e13 100644 (file)
@@ -2645,4 +2645,14 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
                        }
                }
        }
+
+       if (!MAIN_VERSION_ATLEAST(main, 269, 8)) {
+               Curve *cu;
+
+               for (cu = main->curve.first; cu; cu = cu->id.next) {
+                       if (cu->str) {
+                               cu->len_wchar = BLI_strlen_utf8(cu->str);
+                       }
+               }
+       }
 }
index 9ffe4dae82abdda77765821f317167487d437c87..beb8d584e41a6f30510cb9c09fcd31d5c4015265 100644 (file)
@@ -1664,12 +1664,8 @@ static void write_curves(WriteData *wd, ListBase *idbase)
                        if (cu->adt) write_animdata(wd, cu->adt);
                        
                        if (cu->vfont) {
-                               /* TODO, sort out 'cu->len', in editmode its character, object mode its bytes */
-                               size_t len_bytes;
-                               size_t len_chars = BLI_strlen_utf8_ex(cu->str, &len_bytes);
-
-                               writedata(wd, DATA, len_bytes + 1, cu->str);
-                               writestruct(wd, DATA, "CharInfo", len_chars + 1, cu->strinfo);
+                               writedata(wd, DATA, cu->len + 1, cu->str);
+                               writestruct(wd, DATA, "CharInfo", cu->len_wchar + 1, cu->strinfo);
                                writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);
                        }
                        else {
index 6bb6b2860470e9d1c5b01585d6568548e77c424e..3118dd69eb0ae53a4e47415a91873f44d2969a4d 100644 (file)
@@ -220,47 +220,24 @@ static char findaccent(char char1, unsigned int code)
        else return char1;
 }
 
-
-static void update_string(Curve *cu)
-{
-       EditFont *ef = cu->editfont;
-       int len;
-
-       /* Free the old curve string */
-       MEM_freeN(cu->str);
-
-       /* Calculate the actual string length in UTF-8 variable characters */
-       len = BLI_wstrlen_utf8(ef->textbuf);
-
-       /* Alloc memory for UTF-8 variable char length string */
-       cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
-
-       /* Copy the wchar to UTF-8 */
-       BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, len + 1);
-
-       BLI_assert(wcslen(ef->textbuf) == cu->len);
-}
-
 static int insert_into_textbuf(Object *obedit, uintptr_t c)
 {
        Curve *cu = obedit->data;
+       EditFont *ef = cu->editfont;
        
-       if (cu->len < MAXTEXT - 1) {
-               EditFont *ef = cu->editfont;
+       if (ef->len < MAXTEXT - 1) {
                int x;
 
-               for (x = cu->len; x > cu->pos; x--) ef->textbuf[x] = ef->textbuf[x - 1];
-               for (x = cu->len; x > cu->pos; x--) ef->textbufinfo[x] = ef->textbufinfo[x - 1];
-               ef->textbuf[cu->pos] = c;
-               ef->textbufinfo[cu->pos] = cu->curinfo;
-               ef->textbufinfo[cu->pos].kern = 0;
-               ef->textbufinfo[cu->pos].mat_nr = obedit->actcol;
+               for (x = ef->len; x > ef->pos; x--) ef->textbuf[x] = ef->textbuf[x - 1];
+               for (x = ef->len; x > ef->pos; x--) ef->textbufinfo[x] = ef->textbufinfo[x - 1];
+               ef->textbuf[ef->pos] = c;
+               ef->textbufinfo[ef->pos] = cu->curinfo;
+               ef->textbufinfo[ef->pos].kern = 0;
+               ef->textbufinfo[ef->pos].mat_nr = obedit->actcol;
                                        
-               cu->pos++;
-               cu->len++;
-               ef->textbuf[cu->len] = '\0';
-
-               update_string(cu);
+               ef->pos++;
+               ef->len++;
+               ef->textbuf[ef->len] = '\0';
 
                return 1;
        }
@@ -273,10 +250,10 @@ static void text_update_edited(bContext *C, Scene *scene, Object *obedit, int re
        struct Main *bmain = CTX_data_main(C);
        Curve *cu = obedit->data;
        EditFont *ef = cu->editfont;
-       cu->curinfo = ef->textbufinfo[cu->pos ? cu->pos - 1 : 0];
+       cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
        
        if (obedit->totcol > 0) {
-               obedit->actcol = ef->textbufinfo[cu->pos ? cu->pos - 1 : 0].mat_nr;
+               obedit->actcol = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0].mat_nr;
 
                /* since this array is calloc'd, it can be 0 even though we try ensure
                 * (mat_nr > 0) almost everywhere */
@@ -285,13 +262,11 @@ static void text_update_edited(bContext *C, Scene *scene, Object *obedit, int re
                }
        }
 
-       if (mode == FO_EDIT)
-               update_string(cu);
-
        BKE_vfont_to_curve(bmain, scene, obedit, mode, NULL);
 
        if (recalc)
                DAG_id_tag_update(obedit->data, 0);
+
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
 }
 
@@ -381,17 +356,18 @@ static int paste_file(bContext *C, ReportList *reports, const char *filename)
        fclose(fp);
        strp[filelen] = 0;
 
-       if (cu->len + filelen < MAXTEXT) {
+       if (ef->len + filelen < MAXTEXT) {
                int tmplen;
                wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * filelen) + (4 * sizeof(wchar_t)), "temporary");
                tmplen = BLI_strncpy_wchar_from_utf8(mem, strp, filelen + 1);
                wcscat(ef->textbuf, mem);
                MEM_freeN(mem);
-               cu->len += tmplen;
-               cu->pos = cu->len;
+               ef->len += tmplen;
        }
        MEM_freeN(strp);
 
+       ef->pos = ef->len;
+
        text_update_edited(C, scene, obedit, 1, FO_EDIT);
 
        return OPERATOR_FINISHED;
@@ -441,7 +417,7 @@ void FONT_OT_file_paste(wmOperatorType *ot)
 
 /******************* text to object operator ********************/
 
-static void txt_add_object(bContext *C, TextLine *firstline, int totline, float offset[3])
+static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3])
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
@@ -482,10 +458,10 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, float
        cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo");
 
        cu->len = 0;
+       cu->len_wchar = nchars - 1;
        cu->pos = 0;
 
        s = cu->str;
-       *s = '\0';
 
        for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
                size_t nbytes_line;
@@ -502,9 +478,11 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, float
                        cu->len += nbytes_line;
                }
 
-               cu->pos = cu->len;
        }
 
+       cu->pos = cu->len_wchar;
+       *s = '\0';
+
        WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit);
 }
 
@@ -561,18 +539,18 @@ static int kill_selection(Object *obedit, int ins)  /* 1 == new character */
        if (direction) {
                int size;
                if (ins) offset = 1;
-               if (cu->pos >= selstart) cu->pos = selstart + offset;
+               if (ef->pos >= selstart) ef->pos = selstart + offset;
                if ((direction == -1) && ins) {
                        selstart++;
                        selend++;
                }
                getfrom = selend + offset;
                if (ins == 0) getfrom++;
-               size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
+               size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
                memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
-               memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, ((cu->len - selstart) + offset) * sizeof(CharInfo));
-               cu->len -= ((selend - selstart) + 1);
-               cu->selstart = cu->selend = 0;
+               memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, ((ef->len - selstart) + offset) * sizeof(CharInfo));
+               ef->len -= ((selend - selstart) + 1);
+               ef->selstart = ef->selend = 0;
        }
 
        return(direction);
@@ -684,11 +662,12 @@ static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op))
        Scene *scene = CTX_data_scene(C);
        Object *obedit = CTX_data_edit_object(C);
        Curve *cu = obedit->data;
+       EditFont *ef = cu->editfont;
 
-       if (cu->len) {
-               cu->selstart = 1;
-               cu->selend = cu->len;
-               cu->pos = cu->len;
+       if (ef->len) {
+               ef->selstart = 1;
+               ef->selend = ef->len;
+               ef->pos = ef->len;
 
                text_update_edited(C, scene, obedit, true, FO_SELCHANGE);
 
@@ -795,21 +774,21 @@ static int paste_selection(Object *obedit, ReportList *reports)
        EditFont *ef = cu->editfont;
        int len = wcslen(ef->copybuf);
 
-       /* Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT */
-       if (cu->len + len <= MAXTEXT) {
+       /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
+       if (ef->len + len <= MAXTEXT) {
 
                kill_selection(obedit, 0);
 
                if (len) {
-                       int size = (cu->len * sizeof(wchar_t)) - (cu->pos * sizeof(wchar_t)) + sizeof(wchar_t);
-                       memmove(ef->textbuf + cu->pos + len, ef->textbuf + cu->pos, size);
-                       memcpy(ef->textbuf + cu->pos, ef->copybuf, len * sizeof(wchar_t));
+                       int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t);
+                       memmove(ef->textbuf + ef->pos + len, ef->textbuf + ef->pos, size);
+                       memcpy(ef->textbuf + ef->pos, ef->copybuf, len * sizeof(wchar_t));
                
-                       memmove(ef->textbufinfo + cu->pos + len, ef->textbufinfo + cu->pos, (cu->len - cu->pos + 1) * sizeof(CharInfo));
-                       memcpy(ef->textbufinfo + cu->pos, ef->copybufinfo, len * sizeof(CharInfo));
+                       memmove(ef->textbufinfo + ef->pos + len, ef->textbufinfo + ef->pos, (ef->len - ef->pos + 1) * sizeof(CharInfo));
+                       memcpy(ef->textbufinfo + ef->pos, ef->copybufinfo, len * sizeof(CharInfo));
                
-                       cu->len += len;
-                       cu->pos += len;
+                       ef->len += len;
+                       ef->pos += len;
 
                        return 1;
                }
@@ -873,76 +852,76 @@ static int move_cursor(bContext *C, int type, int select)
 
        switch (type) {
                case LINE_BEGIN:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       while (cu->pos > 0) {
-                               if (ef->textbuf[cu->pos - 1] == '\n') break;
-                               if (ef->textbufinfo[cu->pos - 1].flag & CU_CHINFO_WRAP) break;
-                               cu->pos--;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       while (ef->pos > 0) {
+                               if (ef->textbuf[ef->pos - 1] == '\n') break;
+                               if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) break;
+                               ef->pos--;
                        }
                        cursmove = FO_CURS;
                        break;
                        
                case LINE_END:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       while (cu->pos < cu->len) {
-                               if (ef->textbuf[cu->pos] == 0) break;
-                               if (ef->textbuf[cu->pos] == '\n') break;
-                               if (ef->textbufinfo[cu->pos].flag & CU_CHINFO_WRAP) break;
-                               cu->pos++;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       while (ef->pos < ef->len) {
+                               if (ef->textbuf[ef->pos] == 0) break;
+                               if (ef->textbuf[ef->pos] == '\n') break;
+                               if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) break;
+                               ef->pos++;
                        }
                        cursmove = FO_CURS;
                        break;
 
                case PREV_WORD:
                {
-                       int pos = cu->pos;
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       BLI_str_cursor_step_wchar(ef->textbuf, cu->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
-                       cu->pos = pos;
+                       int pos = ef->pos;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
+                       ef->pos = pos;
                        cursmove = FO_CURS;
                        break;
                }
 
                case NEXT_WORD:
                {
-                       int pos = cu->pos;
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       BLI_str_cursor_step_wchar(ef->textbuf, cu->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
-                       cu->pos = pos;
+                       int pos = ef->pos;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
+                       ef->pos = pos;
                        cursmove = FO_CURS;
                        break;
                }
 
                case PREV_CHAR:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       cu->pos--;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       ef->pos--;
                        cursmove = FO_CURS;
                        break;
 
                case NEXT_CHAR:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
-                       cu->pos++;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
+                       ef->pos++;
                        cursmove = FO_CURS;
 
                        break;
 
                case PREV_LINE:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
                        cursmove = FO_CURSUP;
                        break;
                        
                case NEXT_LINE:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
                        cursmove = FO_CURSDOWN;
                        break;
 
                case PREV_PAGE:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
                        cursmove = FO_PAGEUP;
                        break;
 
                case NEXT_PAGE:
-                       if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
+                       if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1;
                        cursmove = FO_PAGEDOWN;
                        break;
        }
@@ -951,22 +930,21 @@ static int move_cursor(bContext *C, int type, int select)
                return OPERATOR_CANCELLED;
 
        if (select == 0) {
-               if (cu->selstart) {
+               if (ef->selstart) {
                        struct Main *bmain = CTX_data_main(C);
-                       cu->selstart = cu->selend = 0;
-                       update_string(cu);
+                       ef->selstart = ef->selend = 0;
                        BKE_vfont_to_curve(bmain, scene, obedit, FO_SELCHANGE, NULL);
                }
        }
 
-       if (cu->pos > cu->len) cu->pos = cu->len;
-       else if (cu->pos >= MAXTEXT) cu->pos = MAXTEXT;
-       else if (cu->pos < 0) cu->pos = 0;
+       if (ef->pos > ef->len) ef->pos = ef->len;
+       else if (ef->pos >= MAXTEXT) ef->pos = MAXTEXT;
+       else if (ef->pos < 0) ef->pos = 0;
 
        text_update_edited(C, scene, obedit, select, cursmove);
 
        if (select)
-               cu->selend = cu->pos;
+               ef->selend = ef->pos;
 
        return OPERATOR_FINISHED;
 }
@@ -1033,14 +1011,14 @@ static int change_spacing_exec(bContext *C, wmOperator *op)
        EditFont *ef = cu->editfont;
        int kern, delta = RNA_int_get(op->ptr, "delta");
 
-       kern = ef->textbufinfo[cu->pos - 1].kern;
+       kern = ef->textbufinfo[ef->pos - 1].kern;
        kern += delta;
        CLAMP(kern, -20, 20);
 
-       if (ef->textbufinfo[cu->pos - 1].kern == kern)
+       if (ef->textbufinfo[ef->pos - 1].kern == kern)
                return OPERATOR_CANCELLED;
 
-       ef->textbufinfo[cu->pos - 1].kern = kern;
+       ef->textbufinfo[ef->pos - 1].kern = kern;
 
        text_update_edited(C, scene, obedit, 1, FO_EDIT);
 
@@ -1075,17 +1053,17 @@ static int change_character_exec(bContext *C, wmOperator *op)
        EditFont *ef = cu->editfont;
        int character, delta = RNA_int_get(op->ptr, "delta");
 
-       if (cu->pos <= 0)
+       if (ef->pos <= 0)
                return OPERATOR_CANCELLED;
 
-       character = ef->textbuf[cu->pos - 1];
+       character = ef->textbuf[ef->pos - 1];
        character += delta;
        CLAMP(character, 0, 255);
 
-       if (character == ef->textbuf[cu->pos - 1])
+       if (character == ef->textbuf[ef->pos - 1])
                return OPERATOR_CANCELLED;
 
-       ef->textbuf[cu->pos - 1] = character;
+       ef->textbuf[ef->pos - 1] = character;
 
        text_update_edited(C, scene, obedit, 1, FO_EDIT);
 
@@ -1117,10 +1095,11 @@ static int line_break_exec(bContext *C, wmOperator *UNUSED(op))
        Scene *scene = CTX_data_scene(C);
        Object *obedit = CTX_data_edit_object(C);
        Curve *cu = obedit->data;
+       EditFont *ef = cu->editfont;
 
        insert_into_textbuf(obedit, '\n');
 
-       cu->selstart = cu->selend = 0;
+       ef->selstart = ef->selend = 0;
 
        text_update_edited(C, scene, obedit, 1, FO_EDIT);
 
@@ -1161,7 +1140,7 @@ static int delete_exec(bContext *C, wmOperator *op)
        EditFont *ef = cu->editfont;
        int x, selstart, selend, type = RNA_enum_get(op->ptr, "type");
 
-       if (cu->len == 0)
+       if (ef->len == 0)
                return OPERATOR_CANCELLED;
 
        if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
@@ -1175,7 +1154,7 @@ static int delete_exec(bContext *C, wmOperator *op)
 
        switch (type) {
                case DEL_ALL:
-                       cu->len = cu->pos = 0;
+                       ef->len = ef->pos = 0;
                        ef->textbuf[0] = 0;
                        break;
                case DEL_SELECTION:
@@ -1183,27 +1162,27 @@ static int delete_exec(bContext *C, wmOperator *op)
                                return OPERATOR_CANCELLED;
                        break;
                case DEL_PREV_CHAR:
-                       if (cu->pos <= 0)
+                       if (ef->pos <= 0)
                                return OPERATOR_CANCELLED;
 
-                       for (x = cu->pos; x <= cu->len; x++)
+                       for (x = ef->pos; x <= ef->len; x++)
                                ef->textbuf[x - 1] = ef->textbuf[x];
-                       for (x = cu->pos; x <= cu->len; x++)
+                       for (x = ef->pos; x <= ef->len; x++)
                                ef->textbufinfo[x - 1] = ef->textbufinfo[x];
 
-                       cu->pos--;
-                       ef->textbuf[--cu->len] = '\0';
+                       ef->pos--;
+                       ef->textbuf[--ef->len] = '\0';
                        break;
                case DEL_NEXT_CHAR:
-                       if (cu->pos >= cu->len)
+                       if (ef->pos >= ef->len)
                                return OPERATOR_CANCELLED;
 
-                       for (x = cu->pos; x < cu->len; x++)
+                       for (x = ef->pos; x < ef->len; x++)
                                ef->textbuf[x] = ef->textbuf[x + 1];
-                       for (x = cu->pos; x < cu->len; x++)
+                       for (x = ef->pos; x < ef->len; x++)
                                ef->textbufinfo[x] = ef->textbufinfo[x + 1];
 
-                       ef->textbuf[--cu->len] = '\0';
+                       ef->textbuf[--ef->len] = '\0';
                        break;
                default:
                        return OPERATOR_CANCELLED;
@@ -1279,7 +1258,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
                return insert_text_exec(C, op);
 
        if (RNA_struct_property_is_set(op->ptr, "accent")) {
-               if (cu->len != 0 && cu->pos > 0)
+               if (ef->len != 0 && ef->pos > 0)
                        accentcode = 1;
                return OPERATOR_FINISHED;
        }
@@ -1293,7 +1272,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
        }
        
        if (event_type == BACKSPACEKEY) {
-               if (alt && cu->len != 0 && cu->pos > 0)
+               if (alt && ef->len != 0 && ef->pos > 0)
                        accentcode = 1;
                return OPERATOR_PASS_THROUGH;
        }
@@ -1308,9 +1287,9 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
                {
 
                        if (accentcode) {
-                               if (cu->pos > 0) {
-                                       inserted_text[0] = findaccent(ef->textbuf[cu->pos - 1], ascii);
-                                       ef->textbuf[cu->pos - 1] = inserted_text[0];
+                               if (ef->pos > 0) {
+                                       inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii);
+                                       ef->textbuf[ef->pos - 1] = inserted_text[0];
                                }
                                accentcode = 0;
                        }
@@ -1473,34 +1452,48 @@ void make_editText(Object *obedit)
        }
        
        /* Convert the original text to wchar_t */
-       cu->len = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4); /* length is bogus */
+       BLI_assert(BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4) == cu->len_wchar);  /* length is bogus */
+       ef->len = cu->len_wchar;
 
-       memcpy(ef->textbufinfo, cu->strinfo, (cu->len) * sizeof(CharInfo));
+       memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
 
-       if (cu->pos > cu->len) cu->pos = cu->len;
+       if (ef->pos > ef->len) ef->pos = ef->len;
 
-       if (cu->pos)
-               cu->curinfo = ef->textbufinfo[cu->pos - 1];
-       else
-               cu->curinfo = ef->textbufinfo[0];
+       cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
 
-       /* Convert to UTF-8 */
-       update_string(cu);
+       /* Other vars */
+       ef->pos = cu->pos;
+       ef->selstart = cu->selstart;
+       ef->selend = cu->selend;
 }
 
 void load_editText(Object *obedit)
 {
        Curve *cu = obedit->data;
        EditFont *ef = cu->editfont;
-       
-       update_string(cu);
+
+       /* Free the old curve string */
+       MEM_freeN(cu->str);
+
+       /* Calculate the actual string length in UTF-8 variable characters */
+       cu->len_wchar = ef->len;
+       cu->len = BLI_wstrlen_utf8(ef->textbuf);
+
+       /* Alloc memory for UTF-8 variable char length string */
+       cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str");
+
+       /* Copy the wchar to UTF-8 */
+       BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1);
        
        if (cu->strinfo)
                MEM_freeN(cu->strinfo);
-       cu->strinfo = MEM_callocN((cu->len + 4) * sizeof(CharInfo), "texteditinfo");
-       memcpy(cu->strinfo, ef->textbufinfo, (cu->len) * sizeof(CharInfo));
+       cu->strinfo = MEM_callocN((cu->len_wchar + 4) * sizeof(CharInfo), "texteditinfo");
+       memcpy(cu->strinfo, ef->textbufinfo, cu->len_wchar * sizeof(CharInfo));
 
-       cu->len = strlen(cu->str);
+       /* Other vars */
+       cu->pos = ef->pos;
+       cu->selstart = ef->selstart;
+       cu->selend = ef->selend;
 }
 
 void free_editText(Object *obedit)
@@ -1763,15 +1756,14 @@ static void undoFont_to_editFont(void *strv, void *ecu, void *UNUSED(obdata))
        EditFont *ef = cu->editfont;
        char *str = strv;
 
-       cu->pos = *((short *)str);
-       cu->len = *((short *)(str + 2));
+       ef->pos = *((short *)str);
+       ef->len = *((short *)(str + 2));
 
-       memcpy(ef->textbuf, str + 4, (cu->len + 1) * sizeof(wchar_t));
-       memcpy(ef->textbufinfo, str + 4 + (cu->len + 1) * sizeof(wchar_t), cu->len * sizeof(CharInfo));
+       memcpy(ef->textbuf, str + 4, (ef->len + 1) * sizeof(wchar_t));
+       memcpy(ef->textbufinfo, str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->len * sizeof(CharInfo));
        
-       cu->selstart = cu->selend = 0;
-       
-       update_string(cu);
+       ef->selstart = ef->selend = 0;
+
 }
 
 static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
@@ -1784,11 +1776,11 @@ static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
        str = MEM_callocN((MAXTEXT + 6) * sizeof(wchar_t) + (MAXTEXT + 4) * sizeof(CharInfo), "string undo");
 
        /* Copy the string and string information */
-       memcpy(str + 4, ef->textbuf, (cu->len + 1) * sizeof(wchar_t));
-       memcpy(str + 4 + (cu->len + 1) * sizeof(wchar_t), ef->textbufinfo, cu->len * sizeof(CharInfo));
+       memcpy(str + 4, ef->textbuf, (ef->len + 1) * sizeof(wchar_t));
+       memcpy(str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->textbufinfo, ef->len * sizeof(CharInfo));
 
-       *((short *)str) = cu->pos;
-       *((short *)(str + 2)) = cu->len;
+       *((short *)(str + 0)) = ef->pos;
+       *((short *)(str + 2)) = ef->len;
        
        return str;
 }
index 24035464259bcc4180a60164e34ed9d71247ecfa..ad6a3a77413c3f8b57809f183c5fecb06fb12a2a 100644 (file)
@@ -216,15 +216,25 @@ typedef struct Curve {
         * - strlen(cu->str) object-mode (bytes).
         * - BLI_strlen_utf8(cu->str) in edit-mode.
         * This should be cleaned up and some point, see 'write_curves' - campbell */
-       short len, lines, pos, spacemode;
+       short lines;
+       char spacemode, pad1;
        float spacing, linedist, shear, fsize, wordspace, ulpos, ulheight;
        float xof, yof;
        float linewidth;
 
+       int pad3;
+       int len_wchar;  /* number of characters (strinfo) */
+       int len;        /* number of bytes (str - utf8) */
        char *str;
        struct SelBox *selboxes;  /* runtime variable for drawing selections (editmode data) */
        struct EditFont *editfont;
        
+       /* copy of EditFont vars (wchar_t aligned),
+        * warning! don't use in editmode (storage only) */
+       int pos;
+       int selstart, selend;
+       int pad2;
+
        char family[24];
        struct VFont *vfont;
        struct VFont *vfontb;
@@ -237,8 +247,6 @@ typedef struct Curve {
        int totbox, actbox;
        struct TextBox *tb;
        
-       int selstart, selend;
-       
        struct CharInfo *strinfo;
        struct CharInfo curinfo;
 
index da5b6676cb9b36017a1105f11407c5f6ffdb2ab6..97c1725ff01cd7a611d7a322f40659e92fa2f253 100644 (file)
@@ -448,28 +448,29 @@ static void rna_Curve_body_get(PointerRNA *ptr, char *value)
 static int rna_Curve_body_length(PointerRNA *ptr)
 {
        Curve *cu = (Curve *)ptr->id.data;
-       return cu->editfont ? strlen(cu->str) : cu->len;
+       return cu->len;
 }
 
-/* TODO - check UTF & python play nice */
+/* TODO, how to handle editmode? */
 static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
 {
-       int len = strlen(value);
+       size_t len_bytes;
+       size_t len_chars = BLI_strlen_utf8_ex(value, &len_bytes);
+
        Curve *cu = (Curve *)ptr->id.data;
 
-       cu->len = cu->pos = len;
+       cu->len = len_bytes;
+       cu->pos = len_chars;
 
        if (cu->str)
                MEM_freeN(cu->str);
        if (cu->strinfo)
                MEM_freeN(cu->strinfo);
 
-       cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
-       /* don't know why this is +4, just duplicating load_editText() */
-       cu->strinfo = MEM_callocN((len + 4) * sizeof(CharInfo), "strinfo");
+       cu->str = MEM_mallocN(len_bytes + sizeof(wchar_t), "str");
+       cu->strinfo = MEM_callocN((len_chars + 4) * sizeof(CharInfo), "strinfo");
 
-       /*BLI_strncpy_wchar_as_utf8(cu->str, value, len + 1);  *//* value is not wchar_t */
-       BLI_strncpy(cu->str, value, len + 1);
+       BLI_strncpy(cu->str, value, len_bytes + 1);
 }
 
 static void rna_Nurb_update_cyclic_u(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -1021,7 +1022,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
        RNA_def_property_update(prop, 0, "rna_Curve_update_data");
 
        prop = RNA_def_property(srna, "body_format", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_collection_sdna(prop, NULL, "strinfo", "len");
+       RNA_def_property_collection_sdna(prop, NULL, "strinfo", "len_wchar");
        RNA_def_property_struct_type(prop, "TextCharacterFormat");
        RNA_def_property_ui_text(prop, "Character Info", "Stores the style of each character");