tedious string copying changes
[blender.git] / source / blender / blenkernel / intern / font.c
index 45b52f5af8e350611d68c025bb63e3f523fdf7ac..5fdb9549179a9e27ca8b6cf5cf6ab3d4707d6e6c 100644 (file)
@@ -1,4 +1,4 @@
-/*  font.c     
+/*  font.c
  *  
  * 
  * $Id$
@@ -17,7 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <math.h>
 #include <stdlib.h>
 #include <wchar.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include <wctype.h>
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_vfontdata.h"
 
 #include "DNA_packedFile_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_object_types.h"
-#include "DNA_view3d_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 
 #include "BKE_utildefines.h"
-#include "BKE_bad_level_calls.h"
 
 #include "BKE_packedFile.h"
 
 #include "BKE_font.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
-#include "BKE_screen.h"
 #include "BKE_anim.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
 
-#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
-struct SelBox *selboxes= NULL;
+static ListBase ttfdata= {NULL, NULL};
 
 /* UTF-8 <-> wchar transformations */
 void
@@ -131,7 +123,7 @@ wcsleninu8(wchar_t *src)
        return len;
 }
 
-int
+static int
 utf8slen(char *src)
 {
        int size = 0, index = 0;
@@ -166,7 +158,7 @@ According to RFC 3629 "UTF-8, a transformation format of ISO 10646"
 (http://tools.ietf.org/html/rfc3629), the valid UTF-8 encoding are:
 
   Char. number range  |        UTF-8 octet sequence
-      (hexadecimal)    |              (binary)
+         (hexadecimal)    |              (binary)
    --------------------+---------------------------------------------
    0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
@@ -208,7 +200,7 @@ int utf8towchar(wchar_t *w, char *c)
                                *w = '?';
                        }
                } else
-                   *w=(c[0] & 0x7f);
+                       *w=(c[0] & 0x7f);
 
                c++;
                w++;
@@ -270,28 +262,50 @@ static PackedFile *get_builtin_packedfile(void)
        }
 }
 
-static VFontData *vfont_get_data(VFont *vfont)
+void free_ttfont(void)
+{
+       struct TmpFont *tf;
+
+       for(tf= ttfdata.first; tf; tf= tf->next) {
+               if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
+               tf->pf= NULL;
+               tf->vfont= NULL;
+       }
+       BLI_freelistN(&ttfdata);
+}
+
+struct TmpFont *vfont_find_tmpfont(VFont *vfont)
 {
        struct TmpFont *tmpfnt = NULL;
-       PackedFile *tpf;
        
        if(vfont==NULL) return NULL;
        
        // Try finding the font from font list
-       tmpfnt = G.ttfdata.first;
-       
+       tmpfnt = ttfdata.first;
        while(tmpfnt)
        {
                if(tmpfnt->vfont == vfont)
                        break;
                tmpfnt = tmpfnt->next;
        }
+       return tmpfnt;
+}
+
+static VFontData *vfont_get_data(VFont *vfont)
+{
+       struct TmpFont *tmpfnt = NULL;
+       PackedFile *tpf;
+       
+       if(vfont==NULL) return NULL;
+       
+       // Try finding the font from font list
+       tmpfnt = vfont_find_tmpfont(vfont);
        
        // And then set the data        
        if (!vfont->data) {
                PackedFile *pf;
                
-               if (BLI_streq(vfont->name, "<builtin>")) {
+               if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) {
                        pf= get_builtin_packedfile();
                } else {
                        if (vfont->packedfile) {
@@ -309,36 +323,32 @@ static VFontData *vfont_get_data(VFont *vfont)
                                        tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
                                        tmpfnt->pf= tpf;
                                        tmpfnt->vfont= vfont;
-                                       BLI_addtail(&G.ttfdata, tmpfnt);
+                                       BLI_addtail(&ttfdata, tmpfnt);
                                }
                        } else {
-                               pf= newPackedFile(vfont->name);
+                               pf= newPackedFile(NULL, vfont->name);
                                
                                if(!tmpfnt)
                                {
-                                       tpf= newPackedFile(vfont->name);
+                                       tpf= newPackedFile(NULL, vfont->name);
                                        
                                        // Add temporary packed file to globals
                                        tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
                                        tmpfnt->pf= tpf;
                                        tmpfnt->vfont= vfont;
-                                       BLI_addtail(&G.ttfdata, tmpfnt);
+                                       BLI_addtail(&ttfdata, tmpfnt);
                                }
                        }
                        if(!pf) {
                                printf("Font file doesn't exist: %s\n", vfont->name);
 
-                               strcpy(vfont->name, "<builtin>");
+                               strcpy(vfont->name, FO_BUILTIN_NAME);
                                pf= get_builtin_packedfile();
                        }
                }
                
                if (pf) {
-#ifdef WITH_FREETYPE2
                        vfont->data= BLI_vfontdata_from_freetypefont(pf);
-#else
-                       vfont->data= BLI_vfontdata_from_psfont(pf);
-#endif                 
                        if (pf != vfont->packedfile) {
                                freePackedFile(pf);
                        }
@@ -357,7 +367,7 @@ VFont *load_vfont(char *name)
        int is_builtin;
        struct TmpFont *tmpfnt;
        
-       if (BLI_streq(name, "<builtin>")) {
+       if (strcmp(name, FO_BUILTIN_NAME)==0) {
                strcpy(filename, name);
                
                pf= get_builtin_packedfile();
@@ -368,27 +378,24 @@ VFont *load_vfont(char *name)
                strcpy(dir, name);
                BLI_splitdirstring(dir, filename);
 
-               pf= newPackedFile(name);
-               tpf= newPackedFile(name);               
+               pf= newPackedFile(NULL, name);
+               tpf= newPackedFile(NULL, name);         
                
                is_builtin= 0;
        }
 
        if (pf) {
                VFontData *vfd;
-               
-               waitcursor(1);
 
-#ifdef WITH_FREETYPE2
                vfd= BLI_vfontdata_from_freetypefont(pf);
-#else
-               vfd= BLI_vfontdata_from_psfont(pf);
-#endif
-               
                if (vfd) {
                        vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
                        vfont->data = vfd;
-                       
+
+                       /* if there's a font name, use it for the ID name */
+                       if (strcmp(vfd->name, "")!=0) {
+                               BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2);
+                       }
                        BLI_strncpy(vfont->name, name, sizeof(vfont->name));
 
                        // if autopack is on store the packedfile in de font structure
@@ -396,13 +403,13 @@ VFont *load_vfont(char *name)
                                vfont->packedfile = pf;
                        }
                        
-                       // Do not add <builtin> to temporary listbase
-                       if(strcmp(filename, "<builtin>"))
+                       // Do not add FO_BUILTIN_NAME to temporary listbase
+                       if(strcmp(filename, FO_BUILTIN_NAME))
                        {
                                tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
                                tmpfnt->pf= tpf;
                                tmpfnt->vfont= vfont;
-                               BLI_addtail(&G.ttfdata, tmpfnt);
+                               BLI_addtail(&ttfdata, tmpfnt);
                        }                       
                }
                
@@ -411,7 +418,7 @@ VFont *load_vfont(char *name)
                        freePackedFile(pf);
                }
        
-               waitcursor(0);
+               //XXX waitcursor(0);
        }
        
        return vfont;
@@ -419,18 +426,40 @@ VFont *load_vfont(char *name)
 
 static VFont *which_vfont(Curve *cu, CharInfo *info)
 {
-       switch(info->flag & CU_STYLE) {
-               case CU_BOLD:
+       switch(info->flag & (CU_CHINFO_BOLD|CU_CHINFO_ITALIC)) {
+               case CU_CHINFO_BOLD:
                        if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
-               case CU_ITALIC:
+               case CU_CHINFO_ITALIC:
                        if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
-               case (CU_BOLD|CU_ITALIC):
+               case (CU_CHINFO_BOLD|CU_CHINFO_ITALIC):
                        if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
                default:
                        return(cu->vfont);
        }                       
 }
 
+VFont *get_builtin_font(void)
+{
+       VFont *vf;
+       
+       for (vf= G.main->vfont.first; vf; vf= vf->id.next)
+               if (strcmp(vf->name, FO_BUILTIN_NAME)==0)
+                       return vf;
+       
+       return load_vfont(FO_BUILTIN_NAME);
+}
+
+static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
+{
+       VChar *che= NULL;
+
+       for(che = vfd->characters.first; che; che = che->next) {
+               if(che->index == character)
+                       break;
+       }
+       return che; /* NULL if not found */
+}
+               
 static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr)
 {
        Nurb *nu2;
@@ -441,14 +470,14 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
        nu2->resolu= cu->resolu;
        nu2->bezt = NULL;
        nu2->knotsu = nu2->knotsv = NULL;
-       nu2->flag= 0;
+       nu2->flag= CU_2D;
        nu2->charidx = charidx+1000;
        if (mat_nr > 0) nu2->mat_nr= mat_nr-1;
        nu2->pntsu = 4;
        nu2->pntsv = 1;
        nu2->orderu = 4;
        nu2->orderv = 1;
-       nu2->flagu = CU_CYCLIC;
+       nu2->flagu = CU_NURB_CYCLIC;
 
        bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); 
        if (bp == 0){
@@ -474,7 +503,6 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
        nu2->bp[3].vec[2] = 0;  
        nu2->bp[3].vec[3] = 1.0;        
        
-       nu2->type = CU_2D;
        BLI_addtail(&(cu->nurb), nu2);  
 
 }
@@ -486,11 +514,12 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
        float *fp, fsize, shear, x, si, co;
        VFontData *vfd = NULL;
        VChar *che = NULL;
-       int i, sel=0;
+       int i;
 
        vfd= vfont_get_data(which_vfont(cu, info));     
        if (!vfd) return;
 
+       /*
        if (cu->selend < cu->selstart) {
                if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
                        sel= 1;
@@ -499,6 +528,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
                if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
                        sel= 1;
        }
+       */
 
        /* make a copy at distance ofsx,ofsy with shear*/
        fsize= cu->fsize;
@@ -506,14 +536,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
        si= (float)sin(rot);
        co= (float)cos(rot);
 
-       // Find the correct character from the font
-       che = vfd->characters.first;
-       while(che)
-       {
-               if(che->index == character)
-                       break;
-               che = che->next;
-       }
+       che= find_vfont_char(vfd, character);
        
        // Select the glyph data
        if(che)
@@ -580,9 +603,23 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
                        }
                        bezt2 = nu2->bezt;
 
+                       if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
+                               const float sca= cu->smallcaps_scale;
+                               for (i= nu2->pntsu; i > 0; i--) {
+                                       fp= bezt2->vec[0];
+                                       fp[0] *= sca;
+                                       fp[1] *= sca;
+                                       fp[3] *= sca;
+                                       fp[4] *= sca;
+                                       fp[6] *= sca;
+                                       fp[7] *= sca;
+                                       bezt2++;
+                               }
+                       }
+                       bezt2 = nu2->bezt;
+
                        for (i= nu2->pntsu; i > 0; i--) {
                                fp= bezt2->vec[0];
-
                                fp[0]= (fp[0]+ofsx)*fsize;
                                fp[1]= (fp[1]+ofsy)*fsize;
                                fp[3]= (fp[3]+ofsx)*fsize;
@@ -599,13 +636,11 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
        }
 }
 
-int getselection(int *start, int *end)
+int BKE_font_getselection(Object *ob, int *start, int *end)
 {
-       Curve *cu;
-       
-       if (G.obedit==NULL || G.obedit->type != OB_FONT) return 0;
+       Curve *cu= ob->data;
        
-       cu= G.obedit->data;
+       if (cu->editfont==NULL || ob->type != OB_FONT) return 0;
 
        if (cu->selstart == 0) return 0;
        if (cu->selstart <= cu->selend) {
@@ -620,30 +655,37 @@ int getselection(int *start, int *end)
        }
 }
 
-struct chartrans *text_to_curve(Object *ob, int mode) 
+static float char_width(Curve *cu, VChar *che, CharInfo *info)
+{
+       // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
+       if(che == NULL) {
+               return 0.0f;
+       }
+       else if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
+               return che->width * cu->smallcaps_scale;
+       }
+       else {
+               return che->width;
+       }
+}
+
+struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) 
 {
        VFont *vfont, *oldvfont;
        VFontData *vfd= NULL;
-       Curve *cu, *cucu;
-       struct chartrans *chartransdata=NULL, *ct;
-       float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy;
-       float cmat[3][3], timeofs, si, co, sizefac;
-       float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
-       int i, slen, oldflag, j;
-       short cnr=0, lnr=0, wsnr= 0;
-       wchar_t *mem, *tmp, ascii;
-       int outta;
-       float vecyo[3], curofs;
-       CharInfo *info;
-       float wsfac;
-       float ulwidth, uloverlap;
+       Curve *cu;
+       CharInfo *info, *custrinfo;
        TextBox *tb;
+       VChar *che;
+       struct chartrans *chartransdata=NULL, *ct;
+       float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
+       float twidth, maxlen= 0;
+       int i, slen, j;
        int curbox;
        int selstart, selend;
-       SelBox *sb= NULL;       /* to please gcc */
-       VChar *che;
-       float twidth;
        int utf8len;
+       short cnr=0, lnr=0, wsnr= 0;
+       wchar_t *mem, *tmp, ascii;
 
        /* renark: do calculations including the trailing '\0' of a string
           because the cursor can be at that location */
@@ -653,9 +695,9 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        // Set font data
        cu= (Curve *) ob->data;
        vfont= cu->vfont;
-
-       if(cu->str == 0) return 0;
-       if(vfont == 0) return 0;
+       
+       if(cu->str == NULL) return 0;
+       if(vfont == NULL) return 0;
 
        // Create unicode string
        utf8len = utf8slen(cu->str);
@@ -666,19 +708,23 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        // Count the wchar_t string length
        slen = wcslen(mem);
 
-       if (cu->ulheight == 0.0) cu->ulheight = 0.05;
-       if (cu->strinfo==NULL) {        /* old file */
-               cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat");
-       }
-       if (cu->tb==NULL) {
+       if (cu->ulheight == 0.0) 
+               cu->ulheight = 0.05;
+       
+       if (cu->strinfo==NULL)  /* old file */
+               cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat");
+       
+       custrinfo= cu->strinfo;
+       if (cu->editfont)
+               custrinfo= cu->editfont->textbufinfo;
+       
+       if (cu->tb==NULL)
                cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat");
-       }
 
        vfd= vfont_get_data(vfont);
 
        /* The VFont Data can not be found */
-       if(!vfd)
-       {
+       if(!vfd) {
                if(mem)
                        MEM_freeN(mem); 
                return 0;
@@ -690,10 +736,10 @@ struct chartrans *text_to_curve(Object *ob, int mode)
 
        /* We assume the worst case: 1 character per line (is freed at end anyway) */
 
-       linedata= MEM_mallocN(sizeof(float)*(slen+2),"buildtext2");
-       linedata2= MEM_mallocN(sizeof(float)*(slen+2),"buildtext3");
-       linedata3= MEM_callocN(sizeof(float)*(slen+2),"buildtext4");    
-       linedata4= MEM_callocN(sizeof(float)*(slen+2),"buildtext5");            
+       linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
+       linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
+       linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");        
+       linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");                
        
        linedist= cu->linedist;
        
@@ -704,12 +750,12 @@ struct chartrans *text_to_curve(Object *ob, int mode)
 
        oldvfont = NULL;
 
-       for (i=0; i<slen; i++) cu->strinfo[i].flag &= ~CU_WRAP;
+       for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK);
 
-       if (selboxes) MEM_freeN(selboxes);
-       selboxes = NULL;
-       if (getselection(&selstart, &selend))
-               selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
+       if (cu->selboxes) MEM_freeN(cu->selboxes);
+       cu->selboxes = NULL;
+       if (BKE_font_getselection(ob, &selstart, &selend))
+               cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
 
        tb = &(cu->tb[0]);
        curbox= 0;
@@ -717,41 +763,36 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        makebreak:
                // Characters in the list
                che = vfd->characters.first;
+               info = &(custrinfo[i]);
                ascii = mem[i];
-               info = &(cu->strinfo[i]);
+               if(info->flag & CU_CHINFO_SMALLCAPS) {
+                       ascii = towupper(ascii);
+                       if(mem[i] != ascii) {
+                               mem[i]= ascii;
+                               info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
+                       }
+               }
+
                vfont = which_vfont(cu, info);
                
                if(vfont==NULL) break;
-               
-               // Find the character
-               while(che)
-               {
-                       if(che->index == ascii)
-                               break;
-                       che = che->next;
-               }
 
-#ifdef WITH_FREETYPE2
-               // The character wasn't in the current curve base so load it
-               // But if the font is <builtin> then do not try loading since whole font is in the memory already
-               if(che == NULL && strcmp(vfont->name, "<builtin>"))
-               {
+               che= find_vfont_char(vfd, ascii);
+
+               /*
+                * The character wasn't in the current curve base so load it
+                * But if the font is FO_BUILTIN_NAME then do not try loading since
+                * whole font is in the memory already
+                */
+               if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) {
                        BLI_vfontchar_from_freetypefont(vfont, ascii);
                }
 
-               // Try getting the character again from the list
-               che = vfd->characters.first;
-               while(che)
-               {
-                       if(che->index == ascii)
-                               break;
-                       che = che->next;
-               }
-#endif
+               /* Try getting the character again from the list */
+               che= find_vfont_char(vfd, ascii);
 
                /* No VFont found */
-               if (vfont==0) 
-               {
+               if (vfont==0) {
                        if(mem)
                                MEM_freeN(mem);
                        MEM_freeN(chartransdata);
@@ -764,26 +805,17 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                }
 
                /* VFont Data for VFont couldn't be found */
-               if (!vfd)
-               {
+               if (!vfd) {
                        if(mem)
                                MEM_freeN(mem);
                        MEM_freeN(chartransdata);
                        return 0;
                }
 
-               // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
-               if(!che)
-               {
-                       twidth = 0;
-               }
-               else
-               {
-                       twidth = che->width;
-               }
+               twidth = char_width(cu, che, info);
 
                // Calculate positions
-               if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) {
+               if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) {
        //              fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
                        for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
                                if (mem[j]==' ' || mem[j]=='-') {
@@ -794,13 +826,13 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                                        i = j-1;
                                        xof = ct->xof;
                                        ct[1].dobreak = 1;
-                                       cu->strinfo[i+1].flag |= CU_WRAP;
+                                       custrinfo[i+1].flag |= CU_CHINFO_WRAP;
                                        goto makebreak;
                                }
                                if (chartransdata[j].dobreak) {
        //                              fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
                                        ct->dobreak= 1;
-                                       cu->strinfo[i+1].flag |= CU_WRAP;
+                                       custrinfo[i+1].flag |= CU_CHINFO_WRAP;
                                        ct -= 1;
                                        cnr -= 1;
                                        i--;
@@ -824,8 +856,8 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                        linedata4[lnr]= wsnr;
                        
                        if ( (tb->h != 0.0) &&
-                            ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize))) &&
-                            (cu->totbox > (curbox+1)) ) {
+                                ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) &&
+                                (cu->totbox > (curbox+1)) ) {
                                maxlen= 0;
                                tb++;
                                curbox++;
@@ -843,6 +875,8 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                        wsnr= 0;
                }
                else if(ascii==9) {     /* TAB */
+                       float tabfac;
+                       
                        ct->xof= xof;
                        ct->yof= yof;
                        ct->linenr= lnr;
@@ -853,13 +887,16 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                        xof= cu->xof+tabfac;
                }
                else {
+                       SelBox *sb= NULL;
+                       float wsfac;
+
                        ct->xof= xof;
                        ct->yof= yof;
                        ct->linenr= lnr;
                        ct->charnr= cnr++;
 
-                       if (selboxes && (i>=selstart) && (i<=selend)) {
-                               sb = &(selboxes[i-selstart]);
+                       if (cu->selboxes && (i>=selstart) && (i<=selend)) {
+                               sb = &(cu->selboxes[i-selstart]);
                                sb->y = yof*cu->fsize-linedist*cu->fsize*0.1;
                                sb->h = linedist*cu->fsize;
                                sb->w = xof*cu->fsize;
@@ -868,25 +905,20 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                        if (ascii==32) {
                                wsfac = cu->wordspace; 
                                wsnr++;
-                       } else wsfac = 1.0;
+                       } 
+                       else wsfac = 1.0;
+                       
                        // Set the width of the character
-                       if(!che)
-                       {
-                               twidth = 0;
-                       }
-                       else
-                       {
-                               twidth = che->width;
-                       }
+                       twidth = char_width(cu, che, info);
+
                        xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
                        
-                       if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w;
+                       if (sb) 
+                               sb->w = (xof*cu->fsize) - sb->w;
                }
                ct++;
        }
        
-
-       
        cu->lines= 1;
        ct= chartransdata;
        tmp = mem;
@@ -916,27 +948,27 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                                ct++;
                        }
                } else if((cu->spacemode==CU_FLUSH) &&
-                         (cu->tb[0].w != 0.0)) {
+                                 (cu->tb[0].w != 0.0)) {
                        for(i=0;i<lnr;i++)
                                if(linedata2[i]>1)
                                        linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
                        for (i=0; i<=slen; i++) {
                                for (j=i; (mem[j]) && (mem[j]!='\n') && 
-                                         (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+                                                 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
 //                             if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
                                        ct->xof+= ct->charnr*linedata[ct->linenr];
 //                             }
                                ct++;
                        }
-               } else if((cu->spacemode==CU_JUSTIFY) &&
-                         (cu->tb[0].w != 0.0)) {
-                       curofs= 0;
+               } 
+               else if((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0)) {
+                       float curofs= 0.0f;
                        for (i=0; i<=slen; i++) {
                                for (j=i; (mem[j]) && (mem[j]!='\n') && 
-                                         (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+                                                 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
                                if ((mem[j]!='\r') && (mem[j]!='\n') &&
-                                   ((chartransdata[j].dobreak!=0))) {
-                                   if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
+                                       ((chartransdata[j].dobreak!=0))) {
+                                       if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
                                        ct->xof+= curofs;
                                }
                                if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
@@ -946,21 +978,25 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        }
        
        /* TEXT ON CURVE */
-       if(cu->textoncurve) {
-               cucu= cu->textoncurve->data;
+       /* Note: Only OB_CURVE objects could have a path  */
+       if(cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
+               Curve *cucu= cu->textoncurve->data;
+               int oldflag= cucu->flag;
                
-               oldflag= cucu->flag;
                cucu->flag |= (CU_PATH+CU_FOLLOW);
                
-               if(cucu->path==NULL) makeDispListCurveTypes(cu->textoncurve, 0);
+               if(cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0);
                if(cucu->path) {
-                       float imat[4][4], imat3[3][3];
-                       Mat4Invert(imat, ob->obmat);
-                       Mat3CpyMat4(imat3, imat);
+                       float distfac, imat[4][4], imat3[3][3], cmat[3][3];
+                       float minx, maxx, miny, maxy;
+                       float timeofs, sizefac;
+                       
+                       invert_m4_m4(imat, ob->obmat);
+                       copy_m3_m4(imat3, imat);
 
-                       Mat3CpyMat4(cmat, cu->textoncurve->obmat);
-                       Mat3MulMat3(cmat, cmat, imat3);
-                       sizefac= Normalize(cmat[0])/cu->fsize;
+                       copy_m3_m4(cmat, cu->textoncurve->obmat);
+                       mul_m3_m3m3(cmat, cmat, imat3);
+                       sizefac= normalize_v3(cmat[0])/cu->fsize;
                        
                        minx=miny= 1.0e20f;
                        maxx=maxy= -1.0e20f;
@@ -999,27 +1035,15 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                        
                        ct= chartransdata;
                        for (i=0; i<=slen; i++, ct++) {
+                               float ctime, dtime, vec[4], tvec[4], rotvec[3];
+                               float si, co;
                                
                                /* rotate around center character */
                                ascii = mem[i];
-                               
-                               // Find the character
-                               che = vfd->characters.first;
-                               while(che)              
-                               {
-                                       if(che->index == ascii)
-                                               break;
-                                       che = che->next;
-                               }
+
+                               che= find_vfont_char(vfd, ascii);
        
-                               if(che)
-                               {
-                                       twidth = che->width;
-                               }
-                               else
-                               {
-                                       twidth = 0;
-                               }
+                               twidth = char_width(cu, che, info);
                                
                                dtime= distfac*0.35f*twidth;    /* why not 0.5? */
                                dtime= distfac*0.5f*twidth;     /* why not 0.5? */
@@ -1029,10 +1053,10 @@ struct chartrans *text_to_curve(Object *ob, int mode)
 
                                /* calc the right loc AND the right rot separately */
                                /* vec, tvec need 4 items */
-                               where_on_path(cu->textoncurve, ctime, vec, tvec);
-                               where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec);
+                               where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
+                               where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL);
                                
-                               VecMulf(vec, sizefac);
+                               mul_v3_fl(vec, sizefac);
                                
                                ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
 
@@ -1049,12 +1073,12 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                }
        }
 
-       if (selboxes) {
+       if (cu->selboxes) {
                ct= chartransdata;
                for (i=0; i<=selend; i++, ct++) {
                        if (i>=selstart) {
-                               selboxes[i-selstart].x = ct->xof*cu->fsize;
-                               selboxes[i-selstart].y = ct->yof*cu->fsize;                             
+                               cu->selboxes[i-selstart].x = ct->xof*cu->fsize;
+                               cu->selboxes[i-selstart].y = ct->yof*cu->fsize;                         
                        }
                }
        }
@@ -1090,12 +1114,14 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        }
        
        /* cursor first */
-       if(ob==G.obedit) {
+       if(cu->editfont) {
+               float si, co;
+               
                ct= chartransdata+cu->pos;
                si= (float)sin(ct->rot);
                co= (float)cos(ct->rot);
                                
-               f= G.textcurs[0];
+               f= cu->editfont->textcurs[0];
                
                f[0]= cu->fsize*(-0.1f*co + ct->xof);
                f[1]= cu->fsize*(0.1f*si + ct->yof);
@@ -1122,74 +1148,70 @@ struct chartrans *text_to_curve(Object *ob, int mode)
                return NULL;
        }
 
-       if(mode==0) {
+       if(mode == FO_EDIT) {
                /* make nurbdata */
-               unsigned long cha;
-
                freeNurblist(&cu->nurb);
                
                ct= chartransdata;
                if (cu->sepchar==0) {
-               for (i= 0; i<slen; i++) {
-                       cha = (uintptr_t) mem[i];
-                       info = &(cu->strinfo[i]);
-                       if (info->mat_nr > (ob->totcol)) {
-                               /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
-                               info->mat_nr = 0;
-                       }
+                       for (i= 0; i<slen; i++) {
+                               unsigned long cha = (uintptr_t) mem[i];
+                               info = &(custrinfo[i]);
+                               if (info->mat_nr > (ob->totcol)) {
+                                       /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
+                                       info->mat_nr = 0;
+                               }
                                // We do not want to see any character for \n or \r
                                if(cha != '\n' && cha != '\r')
                                        buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i);
-                               if ((info->flag & CU_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
-                                       uloverlap = 0;
+                               
+                               if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
+                                       float ulwidth, uloverlap= 0.0f;
+                                       
                                        if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
-                                            ((mem[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0)
-                                          ) {
+                                                ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0)
+                                                ) {
                                                uloverlap = xtrax + 0.1;
                                        }
                                        // Find the character, the characters has to be in the memory already 
                                        // since character checking has been done earlier already.
-                                       che = vfd->characters.first;
-                                       while(che)
-                                       {
-                                               if(che->index == cha)
-                                                       break;
-                                               che = che->next;
-                                       }
+                                       che= find_vfont_char(vfd, cha);
 
-                                       if(!che) twidth =0; else twidth=che->width;
+                                       twidth = char_width(cu, che, info);
                                        ulwidth = cu->fsize * ((twidth* (1.0+(info->kern/40.0)))+uloverlap);
                                        build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize, 
-                                                       ct->xof*cu->fsize + ulwidth, 
-                                                       ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize, 
-                                                       i, info->mat_nr);
+                                                                       ct->xof*cu->fsize + ulwidth, 
+                                                                       ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize, 
+                                                                       i, info->mat_nr);
                                }
-                       ct++;
-               }
+                               ct++;
+                       }
                }
                else {
-               outta = 0;
-               for (i= 0; (i<slen) && (outta==0); i++) {
-                       ascii = mem[i];
-                       info = &(cu->strinfo[i]);
+                       int outta = 0;
+                       for (i= 0; (i<slen) && (outta==0); i++) {
+                               ascii = mem[i];
+                               info = &(custrinfo[i]);
                                if (cu->sepchar == (i+1)) {
+                                       float vecyo[3];
+
+                                       vecyo[0]= ct->xof;
+                                       vecyo[1]= ct->yof;
+                                       vecyo[2]= 0.0f;
+
                                        mem[0] = ascii;
                                        mem[1] = 0;
-                                       cu->strinfo[0]= *info;
+                                       custrinfo[0]= *info;
                                        cu->pos = 1;
                                        cu->len = 1;
-                                       vecyo[0] = ct->xof;
-                                       vecyo[1] = ct->yof;
-                                       vecyo[2] = 0;
-                                       Mat4MulVecfl(ob->obmat, vecyo);
-                                       VECCOPY(ob->loc, vecyo);
+                                       mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
                                        outta = 1;
                                        cu->sepchar = 0;
                                }
-                       ct++;
+                               ct++;
+                       }
                }
        }
-       }
 
        if(mode==FO_DUPLI) {
                MEM_freeN(mem);