? Font3D_010905.diff
? Font3D_020905.diff
? Font3D_050905.diff
? obj/linux-glibc2.3.5-i386
Index: source/nan_definitions.mk
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/nan_definitions.mk,v
retrieving revision 1.73
diff -u -p -r1.73 nan_definitions.mk
--- source/nan_definitions.mk	18 Aug 2005 06:07:02 -0000	1.73
+++ source/nan_definitions.mk	5 Sep 2005 08:53:42 -0000
@@ -506,6 +506,6 @@ endif
 
 # Don't want to build the gameengine?
 ifeq ($(NAN_NO_KETSJI), true)
-   export NAN_JUST_BLENDERDYNAMIC=true
    export NAN_NO_OPENAL=true
+   export NAN_JUST_BLENDERDYNAMIC=true
 endif
Index: source/blender/blenkernel/BKE_font.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/BKE_font.h,v
retrieving revision 1.8
diff -u -p -r1.8 BKE_font.h
--- source/blender/blenkernel/BKE_font.h	29 Aug 2005 12:46:06 -0000	1.8
+++ source/blender/blenkernel/BKE_font.h	5 Sep 2005 08:53:42 -0000
@@ -56,6 +56,10 @@ int mat_to_sel(void);
 void font_duplilist(struct Object *par);
 int getselection(int *start, int *end);
 
+void chtoutf8(unsigned long c, char *o);
+void wcs2utf8s(char *dst, wchar_t *src);
+int wcsleninu8(wchar_t *src);
+int utf8towchar_(wchar_t *w, char *c);
 
 #endif
 
Index: source/blender/blenkernel/BKE_global.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/BKE_global.h,v
retrieving revision 1.32
diff -u -p -r1.32 BKE_global.h
--- source/blender/blenkernel/BKE_global.h	23 Aug 2005 13:16:01 -0000	1.32
+++ source/blender/blenkernel/BKE_global.h	5 Sep 2005 08:53:42 -0000
@@ -117,6 +117,11 @@ typedef struct Global {
 	/* Rob's variables */
 	int have_quicktime;
 	int ui_international;
+	int charstart;
+	int charmin;
+	int charmax;
+	struct VFont *selfont;
+	struct ListBase ttfdata;
 
     /* this variable is written to / read from FileGlobal->fileflags */
     int fileflags;
Index: source/blender/blenkernel/intern/blender.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/intern/blender.c,v
retrieving revision 1.34
diff -u -p -r1.34 blender.c
--- source/blender/blenkernel/intern/blender.c	28 Jul 2005 11:05:20 -0000	1.34
+++ source/blender/blenkernel/intern/blender.c	5 Sep 2005 08:53:42 -0000
@@ -217,6 +217,10 @@ void initglobals(void)
 #endif
 
 	clear_workob();	/* object.c */
+
+	G.charstart = 0x0000;
+	G.charmin = 0x0000;
+	G.charmax = 0xffff;
 }
 
 /***/
Index: source/blender/blenkernel/intern/font.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/intern/font.c,v
retrieving revision 1.24
diff -u -p -r1.24 font.c
--- source/blender/blenkernel/intern/font.c	4 Sep 2005 09:30:57 -0000	1.24
+++ source/blender/blenkernel/intern/font.c	5 Sep 2005 08:53:43 -0000
@@ -37,6 +37,7 @@
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
+#include <wchar.h>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -80,19 +81,151 @@ struct chartrans {
 	char dobreak;
 };
 
-void free_vfont(struct VFont *vf)
+/* UTF-8 <-> wchar transformations */
+void
+chtoutf8(unsigned long c, char *o)
+{
+	// Variables and initialization
+	memset(o, 0, 16);
+
+	// Create the utf-8 string
+	if (c < 0x80)
+	{
+		o[0] = (char) c;
+	}
+	else if (c < 0x800)
+	{
+		o[0] = (0xC0 | (c>>6));
+		o[1] = (0x80 | (c & 0x3f));
+	}
+	else if (c < 0x10000)
+	{
+		o[0] = (0xe0 | (c >> 12));
+		o[1] = (0x80 | (c >>6 & 0x3f));
+		o[2] = (0x80 | (c & 0x3f));
+	}
+	else if (c < 0x200000)
+	{
+	o[0] = (0xf0 | (c>>18));
+	o[1] = (0x80 | (c >>12 & 0x3f));
+	o[2] = (0x80 | (c >> 6 & 0x3f));
+	o[3] = (0x80 | (c & 0x3f));
+	}
+}
+
+void
+wcs2utf8s(char *dst, wchar_t *src)
+{
+	char ch[5];
+
+	while(*src)
+	{
+		memset(ch, 0, 5);
+		chtoutf8(*src++, ch);
+		strcat(dst, ch);
+	}
+}
+
+int
+wcsleninu8(wchar_t *src)
+{
+	char ch[16];
+	int len = 0;
+
+	while(*src)
+	{
+		memset(ch, 0, 16);
+		chtoutf8(*src++, ch);
+		len = len + strlen(ch);
+	}
+
+	return len;
+}
+
+int
+utf8slen(char *src)
+{
+	int size = 0, index = 0;
+	unsigned char c;
+	
+	c = src[index++];
+	while(c)
+	{    
+		if((c & 0x80) == 0)
+		{
+			index += 0;
+		}
+		else if((c & 0xe0) == 0xe0)
+		{
+			index += 2;
+		}
+		else
+		{
+			index += 1;
+		}
+		size += 1;
+		c = src[index++];		
+	}
+	
+	return size;
+}
+
+int utf8towchar_(wchar_t *w, char *c)
 {
-	int i;
+  int len=0;
+  if(w==NULL || c==NULL) return(0);
+  //printf("%s\n",c);
+  while(*c)
+  {
+    if(*c & 0x80)
+    {
+      if(*c & 0x40)
+      {
+        if(*c & 0x20)
+        {
+          if(*c & 0x10)
+          {
+            *w=(c[0] & 0x0f)<<18 | (c[1]&0x1f)<<12 | (c[2]&0x3f)<<6 | (c[3]&0x7f);
+            c++;
+          }
+          else
+            *w=(c[0] & 0x1f)<<12 | (c[1]&0x3f)<<6 | (c[2]&0x7f);
+          c++;
+        }
+        else
+          *w=(((c[0] &0x3f)<<6) | (c[1]&0x7f));
+        c++;
+      }
+      else
+        *w=(c[0] & 0x7f);
+    }
+    else
+      *w=(c[0] & 0x7f);
+
+    c++;
+    w++;
+    len++;
+  }
+  return len;
+}
 
+/* The vfont code */
+void free_vfont(struct VFont *vf)
+{
 	if (vf == 0) return;
 
 	if (vf->data) {
-		for (i = 0; i < MAX_VF_CHARS; i++){
-			while (vf->data->nurbsbase[i].first) {
-				Nurb *nu = vf->data->nurbsbase[i].first;
+		while(vf->data->characters.first)
+		{
+			VChar *che = vf->data->characters.first;
+			
+			while (che->nurbsbase.first) {
+				Nurb *nu = che->nurbsbase.first;
 				if (nu->bezt) MEM_freeN(nu->bezt);
-				BLI_freelinkN(&vf->data->nurbsbase[i], nu);
+				BLI_freelinkN(&che->nurbsbase, nu);
 			}
+	
+			BLI_freelinkN(&vf->data->characters, che);
 		}
 
 		MEM_freeN(vf->data);
@@ -131,6 +264,20 @@ static PackedFile *get_builtin_packedfil
 
 static VFontData *vfont_get_data(VFont *vfont)
 {
+	struct TmpFont *tmpfnt = NULL;
+	PackedFile *tpf;
+	
+	// Try finding the font from font list
+	tmpfnt = G.ttfdata.first;
+	
+	while(tmpfnt)
+	{
+		if(tmpfnt->vfont == vfont)
+			break;
+		tmpfnt = tmpfnt->next;
+	}
+	
+	// And then set the data	
 	if (!vfont->data) {
 		PackedFile *pf;
 		
@@ -139,8 +286,34 @@ static VFontData *vfont_get_data(VFont *
 		} else {
 			if (vfont->packedfile) {
 				pf= vfont->packedfile;
+				
+				// We need to copy a tmp font to memory unless it is already there
+				if(!tmpfnt)
+				{
+					tpf= MEM_callocN(sizeof(*tpf), "PackedFile");
+					tpf->data= MEM_mallocN(pf->size, "packFile");
+					tpf->size= pf->size;
+					memcpy(tpf->data, pf->data, pf->size);
+					
+					// 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);
+				}
 			} else {
 				pf= newPackedFile(vfont->name);
+				
+				if(!tmpfnt)
+				{
+					tpf= newPackedFile(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);
+				}
 			}
 			if(!pf) {
 				printf("Font file doesn't exist: %s\n", vfont->name);
@@ -170,7 +343,9 @@ VFont *load_vfont(char *name)
 	char filename[FILE_MAXFILE];
 	VFont *vfont= NULL;
 	PackedFile *pf;
+	PackedFile *tpf = NULL;	
 	int is_builtin;
+	struct TmpFont *tmpfnt;
 	
 	if (BLI_streq(name, "<builtin>")) {
 		strcpy(filename, name);
@@ -184,6 +359,8 @@ VFont *load_vfont(char *name)
 		BLI_splitdirstring(dir, filename);
 
 		pf= newPackedFile(name);
+		tpf= newPackedFile(name);		
+		
 		is_builtin= 0;
 	}
 
@@ -196,7 +373,7 @@ VFont *load_vfont(char *name)
 		vfd= BLI_vfontdata_from_freetypefont(pf);
 #else
 		vfd= BLI_vfontdata_from_psfont(pf);
-#endif			
+#endif
 		
 		if (vfd) {
 			vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
@@ -208,7 +385,18 @@ VFont *load_vfont(char *name)
 			if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
 				vfont->packedfile = pf;
 			}
+			
+			// Do not add <builtin> to temporary listbase
+			if(strcmp(filename, "<builtin>"))
+			{
+				tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
+				tmpfnt->pf= tpf;
+				tmpfnt->vfont= vfont;
+				BLI_addtail(&G.ttfdata, tmpfnt);
+			}			
 		}
+		
+		// Free the packed file
 		if (!vfont || vfont->packedfile != pf) {
 			freePackedFile(pf);
 		}
@@ -281,12 +469,13 @@ static void build_underline(Curve *cu, f
 
 }
 
-static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
+static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
 {
 	BezTriple *bezt1, *bezt2;
-	Nurb *nu1, *nu2;
+	Nurb *nu1 = NULL, *nu2 = NULL;
 	float *fp, fsize, shear, x, si, co;
-	VFontData *vfd;
+	VFontData *vfd = NULL;
+	VChar *che = NULL;
 	int i, sel=0;
 
 	vfd= vfont_get_data(which_vfont(cu, info));	
@@ -307,7 +496,20 @@ static void buildchar(Curve *cu, unsigne
 	si= (float)sin(rot);
 	co= (float)cos(rot);
 
-	nu1 = vfd->nurbsbase[ascii].first;
+	// Find the correct character from the font
+	che = vfd->characters.first;
+	while(che)
+	{
+		if(che->index == character)
+			break;
+		che = che->next;
+	}
+	
+	// Select the glyph data
+	if(che)
+		nu1 = che->nurbsbase.first;
+
+	// Create the character
 	while(nu1)
 	{
 		bezt1 = nu1->bezt;
@@ -419,7 +621,7 @@ struct chartrans *text_to_curve(Object *
 	float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
 	int i, slen, oldflag, j;
 	short cnr=0, lnr=0, wsnr= 0;
-	char ascii, *mem;
+	wchar_t *mem, *tmp, ascii;
 	int outta;
 	float vecyo[3], curofs;
 	CharInfo *info;
@@ -429,22 +631,39 @@ struct chartrans *text_to_curve(Object *
 	int curbox;
 	int selstart, selend;
 	SelBox *sb= NULL;	/* to please gcc */
+	VChar *che;
+	float twidth;
+	int utf8len;
 
 	/* renark: do calculations including the trailing '\0' of a string
 	   because the cursor can be at that location */
 
 	if(ob->type!=OB_FONT) return 0;
 
-	cu= ob->data;
-	mem= cu->str;
-	slen = strlen(mem);	
+	// Set font data
+	cu= (Curve *) ob->data;
+	vfont= cu->vfont;
+
+	if(cu->str == 0) return 0;
+	if(vfont == 0) return 0;
+
+	// Create unicode string
+	utf8len = utf8slen(cu->str);
+	tmp = mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
+	
+	utf8towchar_(mem, cu->str);
+
+	// Count the wchar_t string length
+	slen = wcslen(mem);
 
 	if (cu->ulheight == 0.0) cu->ulheight = 0.05;
-	if (cu->str==0) return 0;
 	if (cu->strinfo==NULL) {	/* old file */
 		cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat");
 	}
 
+	vfd= vfont_get_data(vfont);
+	if(!vfd) return 0;
+
 	/* calc offset and rotation of each char */
 	ct = chartransdata =
 		(struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
@@ -476,23 +695,64 @@ struct chartrans *text_to_curve(Object *
 	curbox= 0;
 	for (i = 0 ; i<=slen ; i++) {
 	makebreak:
-		ascii = cu->str[i];
+		// Characters in the list
+		che = vfd->characters.first;
+		ascii = mem[i];
 		info = &(cu->strinfo[i]);
 		vfont = which_vfont(cu, info);
+
+		// 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
+		if(che == NULL)
+		{
+			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
+
+
     	if (vfont==0) return 0;
     	if (vfont != oldvfont) {
     		vfd= vfont_get_data(vfont);
     		oldvfont = vfont;
     	}
     	if (!vfd) return 0;    	
-    	if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+vfd->width[ascii])*cu->fsize) > tb->w) {
-//     		fprintf(stderr, "linewidth exceeded: %c%c%c...\n", cu->str[i], cu->str[i+1], cu->str[i+2]);
-    		for (j=i; j && (cu->str[j] != '\n') && (cu->str[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
-    			if (cu->str[j]==' ' || cu->str[j]=='-') {
+
+	// The character wasn't found, propably ascii = 0, then the width shall be 0 as well
+	if(!che)
+	{
+		twidth = 0;
+	}
+	else
+	{
+		twidth = che->width;
+	}
+
+	// Calculate positions
+    	if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) {
+//     		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]=='-') {
 					ct -= (i-(j-1));
 					cnr -= (i-(j-1));
-					if (cu->str[j] == ' ') wsnr--;
-					if (cu->str[j] == '-') wsnr++;
+					if (mem[j] == ' ') wsnr--;
+					if (mem[j] == '-') wsnr++;
 					i = j-1;
 					xof = ct->xof;
 					ct[1].dobreak = 1;
@@ -500,7 +760,7 @@ struct chartrans *text_to_curve(Object *
 					goto makebreak;
     			}
     			if (chartransdata[j].dobreak) {
-//    				fprintf(stderr, "word too long: %c%c%c...\n", cu->str[j], cu->str[j+1], cu->str[j+2]);
+//    				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;
     				ct -= 1;
@@ -533,7 +793,12 @@ struct chartrans *text_to_curve(Object *
 				curbox++;
 				yof= cu->yof + tb->y/cu->fsize;
 			}
-			
+
+			if(ascii == '\n' || ascii == '\r')
+				xof = cu->xof;
+			else
+				xof= cu->xof + (tb->x/cu->fsize);
+
 			xof= cu->xof + (tb->x/cu->fsize);
 			lnr++;
 			cnr= 0;
@@ -566,7 +831,16 @@ struct chartrans *text_to_curve(Object *
 				wsfac = cu->wordspace; 
 				wsnr++;
 			} else wsfac = 1.0;
-			xof += (vfd->width[ascii]*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
+			// Set the width of the character
+			if(!che)
+			{
+				twidth = 0;
+			}
+			else
+			{
+				twidth = che->width;
+			}
+			xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
 			
 			if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w;
 		}
@@ -577,8 +851,9 @@ struct chartrans *text_to_curve(Object *
 	
 	cu->lines= 1;
 	ct= chartransdata;
-	for (i= 0; i<=slen; i++, mem++, ct++) {
-		ascii = *mem;
+	tmp = mem;
+	for (i= 0; i<=slen; i++, tmp++, ct++) {
+		ascii = *tmp;
 		if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
 	}	
 
@@ -608,9 +883,9 @@ struct chartrans *text_to_curve(Object *
 				if(linedata2[i]>1)
 					linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
 			for (i=0; i<=slen; i++) {
-				for (j=i; (cu->str[j]) && (cu->str[j]!='\n') && 
-				          (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
-//				if ((cu->str[j]!='\r') && (cu->str[j]!='\n') && (cu->str[j])) {
+				for (j=i; (mem[j]) && (mem[j]!='\n') && 
+				          (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++;
@@ -619,14 +894,14 @@ struct chartrans *text_to_curve(Object *
 		          (cu->tb[0].w != 0.0)) {
 			curofs= 0;
 			for (i=0; i<=slen; i++) {
-				for (j=i; (cu->str[j]) && (cu->str[j]!='\n') && 
-				          (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
-				if ((cu->str[j]!='\r') && (cu->str[j]!='\n') &&
+				for (j=i; (mem[j]) && (mem[j]!='\n') && 
+				          (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+				if ((mem[j]!='\r') && (mem[j]!='\n') &&
 				    ((chartransdata[j].dobreak!=0))) {
-				    if (cu->str[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
+				    if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
 					ct->xof+= curofs;
 				}
-				if (cu->str[i]=='\n' || cu->str[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
+				if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
 				ct++;
 			}			
 		}
@@ -685,9 +960,28 @@ struct chartrans *text_to_curve(Object *
 			for (i=0; i<=slen; i++, ct++) {
 				
 				/* rotate around centre character */
-				ascii = cu->str[i];
-				dtime= distfac*0.35f*vfd->width[ascii];	/* why not 0.5? */
-				dtime= distfac*0.0f*vfd->width[ascii];	/* why not 0.5? */
+				ascii = mem[i];
+				
+				// Find the character
+				che = vfd->characters.first;
+				while(che)		
+				{
+					if(che->index == ascii)
+						break;
+					che = che->next;
+				}
+	
+				if(che)
+				{
+					twidth = che->width;
+				}
+				else
+				{
+					twidth = 0;
+				}
+				
+				dtime= distfac*0.35f*twidth;	/* why not 0.5? */
+				dtime= distfac*0.0f*twidth;	/* why not 0.5? */
 				
 				ctime= timeofs + distfac*( ct->xof - minx);
 				CLAMP(ctime, 0.0, 1.0);
@@ -787,27 +1081,29 @@ struct chartrans *text_to_curve(Object *
 
 	if(mode==0) {
 		/* make nurbdata */
-		
+		unsigned long cha;
+
 		freeNurblist(&cu->nurb);
 		
 		ct= chartransdata;
 		if (cu->sepchar==0) {
     		for (i= 0; i<slen; i++) {
-    			ascii = cu->str[i];
+			cha = (unsigned long) 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;
     			}
-   				buildchar(cu, ascii, info, ct->xof, ct->yof, ct->rot, i);
+   				buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i);
    				if ((info->flag & CU_UNDERLINE) && (ascii != '\n') && (ascii != '\r')) {
    					uloverlap = 0;
-   					if ( (i<(slen-1)) && (cu->str[i+1] != '\n') && (cu->str[i+1] != '\r') &&
-   					     ((cu->str[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0)
+   					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)
    					   ) {
 	   					uloverlap = xtrax + 0.1;
 	   				}
-   					ulwidth = cu->fsize * ((vfd->width[ascii]* (1.0+(info->kern/40.0)))+uloverlap);
+					if(!che) twidth =0; else twidth=che->width;
+   					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, 
@@ -819,11 +1115,11 @@ struct chartrans *text_to_curve(Object *
 		else {
     		outta = 0;
     		for (i= 0; (i<slen) && (outta==0); i++) {
-    			ascii = cu->str[i];
+    			ascii = mem[i];
     			info = &(cu->strinfo[i]);
 				if (cu->sepchar == (i+1)) {
-					cu->str[0] = ascii;
-					cu->str[1] = 0;
+					mem[0] = ascii;
+					mem[1] = 0;
 					cu->strinfo[0]= *info;
 					cu->pos = 1;
 					cu->len = 1;
@@ -843,6 +1139,9 @@ struct chartrans *text_to_curve(Object *
 	if(mode==FO_DUPLI) {
 		return chartransdata;
 	}
+
+	if(mem)
+		MEM_freeN(mem);
 
 	MEM_freeN(chartransdata);
 	return 0;
Index: source/blender/blenlib/BLI_vfontdata.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenlib/BLI_vfontdata.h,v
retrieving revision 1.8
diff -u -p -r1.8 BLI_vfontdata.h
--- source/blender/blenlib/BLI_vfontdata.h	15 Jan 2004 20:34:53 -0000	1.8
+++ source/blender/blenlib/BLI_vfontdata.h	5 Sep 2005 08:53:43 -0000
@@ -41,17 +41,36 @@
 #include "DNA_listBase.h"
 
 struct PackedFile;
+struct VFont;
 
 #define MAX_VF_CHARS 256
 
 typedef struct VFontData {
-	ListBase nurbsbase[MAX_VF_CHARS];
-	float	    resol[MAX_VF_CHARS];
-	float	    width[MAX_VF_CHARS];
-	float	    *points[MAX_VF_CHARS];
-	char		name[128];
+	ListBase characters;
+	// ListBase nurbsbase[MAX_VF_CHARS];
+	// float	    resol[MAX_VF_CHARS];
+	// float	    width[MAX_VF_CHARS];
+	// float	    *points[MAX_VF_CHARS];
+	 char		name[128];	
 } VFontData;
 
+typedef struct VChar {
+	struct VChar    *next, *prev;
+ 	ListBase        nurbsbase;
+	unsigned long   index;
+	float           resol;
+	float           width;
+	float           *points;
+} VChar;
+
+struct TmpFont
+{
+	struct TmpFont *next, *prev;
+	struct PackedFile *pf;
+	struct VFont *vfont;
+};
+
+
 /**
  * Construct a new VFontData structure from 
  * PostScript font data in a PackedFile.
@@ -75,5 +94,10 @@ BLI_vfontdata_from_psfont(
 	VFontData*
 BLI_vfontdata_from_freetypefont(
 	struct PackedFile *pf);
+
+	int
+BLI_vfontchar_from_freetypefont(
+        struct VFont *vfont, unsigned long character);
+
 #endif
 
Index: source/blender/blenlib/intern/freetypefont.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenlib/intern/freetypefont.c,v
retrieving revision 1.10
diff -u -p -r1.10 freetypefont.c
--- source/blender/blenlib/intern/freetypefont.c	14 Mar 2005 20:10:22 -0000	1.10
+++ source/blender/blenlib/intern/freetypefont.c	5 Sep 2005 08:53:43 -0000
@@ -54,8 +54,10 @@
 
 #include "BIF_toolbox.h"
 
+#include "BKE_global.h"
 #include "BKE_utildefines.h"
 
+#include "DNA_vfont_types.h"
 #include "DNA_packedFile_types.h"
 #include "DNA_curve_types.h"
 
@@ -67,18 +69,264 @@ static FT_Library	library;
 static FT_Error		err;
 
 
-static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
 {
 	// Blender
-	VFontData *vfd;
 	struct Nurb *nu;
+	struct VChar *che;
 	struct BezTriple *bezt;
+	
+	// Freetype2
+	FT_GlyphSlot glyph;
+	FT_UInt glyph_index;
+	FT_Outline ftoutline;
+	const char *fontname;
+	float scale, height;
+	float dx, dy;
+	int i,j,k,l,m=0;
+	
+	// Variables
+	int *npoints;
+	int *onpoints;
+	
+	// adjust font size
+	height= ((double) face->bbox.yMax - (double) face->bbox.yMin);
+	if(height != 0.0)
+		scale = 1.0 / height;
+	else
+		scale = 1.0 / 1000.0;
+	
+	//	
+	// Generate the character 3D data
+	//
+	// Get the FT Glyph index and load the Glyph
+	glyph_index= FT_Get_Char_Index(face, charcode);
+	err= FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+	
+	// If loading succeeded, convert the FT glyph to the internal format
+	if(!err)
+	{
+		// First we create entry for the new character to the character list
+		che= (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
+		BLI_addtail(&vfd->characters, che);
+		
+		// Take some data for modifying purposes
+		glyph= face->glyph;
+		ftoutline= glyph->outline;
+		
+		// Set the width and character code
+		che->index= charcode;
+		che->width= glyph->advance.x * scale;
+		
+		// Start converting the FT data
+		npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
+		onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
+
+		// calculate total points of each contour
+		for(j = 0; j < ftoutline.n_contours; j++) {
+			if(j == 0)
+				npoints[j] = ftoutline.contours[j] + 1;
+			else
+				npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
+		}
+
+		// get number of on-curve points for beziertriples (including conic virtual on-points) 
+		for(j = 0; j < ftoutline.n_contours; j++) {
+			l = 0;
+			for(k = 0; k < npoints[j]; k++) {
+				if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+					if(ftoutline.tags[l] == FT_Curve_Tag_On)
+						onpoints[j]++;
+
+				if(k < npoints[j] - 1 )
+					if( ftoutline.tags[l]   == FT_Curve_Tag_Conic &&
+						ftoutline.tags[l+1] == FT_Curve_Tag_Conic)
+						onpoints[j]++;
+			}
+		}
+
+		//contour loop, bezier & conic styles merged
+		for(j = 0; j < ftoutline.n_contours; j++) {
+			// add new curve
+			nu  =  (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
+			bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
+			BLI_addtail(&che->nurbsbase, nu);
+
+			nu->type= CU_BEZIER+CU_2D;
+			nu->pntsu = onpoints[j];
+			nu->resolu= 8;
+			nu->flagu= 1;
+			nu->bezt = bezt;
+
+			//individual curve loop, start-end
+			for(k = 0; k < npoints[j]; k++) {
+				if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+				if(k == 0) m = l;
+					
+				//virtual conic on-curve points
+				if(k < npoints[j] - 1 )
+				{
+					if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+						dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
+						dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
+
+						//left handle
+						bezt->vec[0][0] = (dx +	(2 * ftoutline.points[l].x)* scale) / 3.0;
+						bezt->vec[0][1] = (dy +	(2 * ftoutline.points[l].y)* scale) / 3.0;
+
+						//midpoint (virtual on-curve point)
+						bezt->vec[1][0] = dx;
+						bezt->vec[1][1] = dy;
+
+						//right handle
+						bezt->vec[2][0] = (dx + (2 * ftoutline.points[l+1].x)* scale) / 3.0;
+						bezt->vec[2][1] = (dy +	(2 * ftoutline.points[l+1].y)* scale) / 3.0;
 
+						bezt->h1= bezt->h2= HD_ALIGN;
+						bezt++;
+					}
+				}
+
+				//on-curve points
+				if(ftoutline.tags[l] == FT_Curve_Tag_On) {
+					//left handle
+					if(k > 0) {
+						if(ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
+							bezt->vec[0][0] = ftoutline.points[l-1].x* scale;
+							bezt->vec[0][1] = ftoutline.points[l-1].y* scale;
+							bezt->h1= HD_FREE;
+						} else if(ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
+							bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x))* scale / 3.0;
+							bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y))* scale / 3.0;
+							bezt->h1= HD_FREE;
+						} else {
+							bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l-1].x)* scale / 3.0;
+							bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l-1].y)* scale / 3.0;
+							bezt->h1= HD_VECT;
+						}
+					} else { //first point on curve
+						if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
+							bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
+							bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
+							bezt->h1= HD_FREE;
+						} else if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
+							bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x))* scale / 3.0 ;
+							bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y))* scale / 3.0 ;
+							bezt->h1= HD_FREE;
+						} else {
+							bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x)* scale / 3.0;
+							bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y)* scale / 3.0;
+							bezt->h1= HD_VECT;
+						}
+					}
+
+					//midpoint (on-curve point)
+					bezt->vec[1][0] = ftoutline.points[l].x* scale;
+					bezt->vec[1][1] = ftoutline.points[l].y* scale;
+
+					//right handle
+					if(k < (npoints[j] - 1)) {
+						if(ftoutline.tags[l+1] == FT_Curve_Tag_Cubic) {
+							bezt->vec[2][0] = ftoutline.points[l+1].x* scale;
+							bezt->vec[2][1] = ftoutline.points[l+1].y* scale;
+							bezt->h2= HD_FREE;
+						} else if(ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+							bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l+1].x))* scale / 3.0;
+							bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l+1].y))* scale / 3.0;
+							bezt->h2= HD_FREE;
+						} else {
+							bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l+1].x)* scale / 3.0;
+							bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l+1].y)* scale / 3.0;
+							bezt->h2= HD_VECT;
+						}
+					} else { //last point on curve
+						if(ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
+							bezt->vec[2][0] = ftoutline.points[m].x* scale;
+							bezt->vec[2][1] = ftoutline.points[m].y* scale;
+							bezt->h2= HD_FREE;
+						} else if(ftoutline.tags[m] == FT_Curve_Tag_Conic) {
+							bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x))* scale / 3.0 ;
+							bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y))* scale / 3.0 ;
+							bezt->h2= HD_FREE;
+						} else {
+							bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[m].x)* scale / 3.0;
+							bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[m].y)* scale / 3.0;
+							bezt->h2= HD_VECT;
+						}
+					}
+
+					// get the handles that are aligned, tricky...
+					// DistVL2Dfl, check if the three beztriple points are on one line
+					// VecLenf, see if there's a distance between the three points
+					// VecLenf again, to check the angle between the handles 
+					// finally, check if one of them is a vector handle 
+					if((DistVL2Dfl(bezt->vec[0],bezt->vec[1],bezt->vec[2]) < 0.001) &&
+						(VecLenf(bezt->vec[0], bezt->vec[1]) > 0.0001) &&
+						(VecLenf(bezt->vec[1], bezt->vec[2]) > 0.0001) &&
+						(VecLenf(bezt->vec[0], bezt->vec[2]) > 0.0002) &&
+						(VecLenf(bezt->vec[0], bezt->vec[2]) > MAX2(VecLenf(bezt->vec[0], bezt->vec[1]), VecLenf(bezt->vec[1], bezt->vec[2]))) &&
+						bezt->h1 != HD_VECT && bezt->h2 != HD_VECT)
+					{
+						bezt->h1= bezt->h2= HD_ALIGN;
+					}
+					bezt++;
+				}
+			}
+		}
+	}
+	
+	if(npoints) MEM_freeN(npoints);
+	if(onpoints) MEM_freeN(onpoints);	
+}
+
+int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
+{
 	// Freetype2
-	FT_Face		face;
-	FT_GlyphSlot  glyph;
-	FT_UInt		glyph_index;
-	FT_Outline	ftoutline;
+	FT_Face face;
+	FT_UInt glyph_index;
+	struct TmpFont *tf;
+	
+	// Find the correct FreeType font
+	tf= G.ttfdata.first;
+	while(tf)
+	{
+		if(tf->vfont == vfont)
+			break;
+		tf= tf->next;		
+	}
+	
+	// What, no font found. Something strange here
+	if(!tf) return FALSE;
+	
+	// Load the font to memory
+	if(tf->pf)
+	{
+		err= FT_New_Memory_Face( library,
+			tf->pf->data,
+			tf->pf->size,
+			0,
+			&face);			
+	}
+	else
+		err= TRUE;
+		
+	// Read the char
+	freetypechar_to_vchar(face, charcode, vfont->data);
+	
+	// And everything went ok
+	return TRUE;
+}
+
+
+static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+{
+	// Variables
+	FT_Face face;
+	FT_ULong charcode = 0;
+	FT_UInt glyph_index;
+	const char *fontname;
+	VFontData *vfd;
+
 /*
     FT_CharMap  found = 0;
 	FT_CharMap  charmap;
@@ -86,10 +334,6 @@ static VFontData *objfnt_to_ftvfontdata(
 	FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
 	int         n;
 */
-	const char *fontname;
-	float scale, height;
-	float dx, dy;
-	int i, j, k, l, m =0;
 
 	// load the freetype font
 	err = FT_New_Memory_Face( library,
@@ -125,187 +369,18 @@ static VFontData *objfnt_to_ftvfontdata(
 	fontname = FT_Get_Postscript_Name(face);
 	strcpy(vfd->name, (fontname == NULL) ? "Fontname not available" : fontname);
 
-	// adjust font size
-	height = ((double) face->bbox.yMax - (double) face->bbox.yMin);
-
-	if(height != 0.0)
-		scale = 1.0 / height;
-	else
-		scale = 1.0 / 1000.0;
-
-	// extract generic ascii character range
-	for(i = myMIN_ASCII; i <= myMAX_ASCII; i++) {
-		int  *npoints = NULL;	//total points of each contour
-		int  *onpoints = NULL;	//num points on curve
-
-		glyph_index = FT_Get_Char_Index( face, i );
-		err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
-
-		if(!err) {
-			glyph = face->glyph;
-			ftoutline = glyph->outline;
-
-			vfd->width[i] = glyph->advance.x* scale;
-
-			npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
-			onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
-
-			// calculate total points of each contour
-			for(j = 0; j < ftoutline.n_contours; j++) {
-				if(j == 0)
-					npoints[j] = ftoutline.contours[j] + 1;
-				else
-					npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
-			}
-
-			// get number of on-curve points for beziertriples (including conic virtual on-points) 
-			for(j = 0; j < ftoutline.n_contours; j++) {
-				l = 0;
-				for(k = 0; k < npoints[j]; k++) {
-					if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
-
-					if(ftoutline.tags[l] == FT_Curve_Tag_On)
-						onpoints[j]++;
-
-					if(k < npoints[j] - 1 )
-						if( ftoutline.tags[l]   == FT_Curve_Tag_Conic &&
-							ftoutline.tags[l+1] == FT_Curve_Tag_Conic)
-							onpoints[j]++;
-				}
-			}
-
-			//contour loop, bezier & conic styles merged
-			for(j = 0; j < ftoutline.n_contours; j++) {
-				// add new curve
-				nu  =  (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
-				bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
-				BLI_addtail(&vfd->nurbsbase[i], nu);
-
-				nu->type= CU_BEZIER+CU_2D;
-				nu->pntsu = onpoints[j];
-				nu->resolu= 8;
-				nu->flagu= 1;
-				nu->bezt = bezt;
-
-				//individual curve loop, start-end
-				for(k = 0; k < npoints[j]; k++) {
-					if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
-					if(k == 0) m = l;
-					
-					//virtual conic on-curve points
-					if(k < npoints[j] - 1 )
-						if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
-							dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
-							dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
-
-							//left handle
-							bezt->vec[0][0] = (dx +	(2 * ftoutline.points[l].x)* scale) / 3.0;
-							bezt->vec[0][1] = (dy +	(2 * ftoutline.points[l].y)* scale) / 3.0;
-
-							//midpoint (virtual on-curve point)
-							bezt->vec[1][0] = dx;
-							bezt->vec[1][1] = dy;
-
-							//right handle
-							bezt->vec[2][0] = (dx + (2 * ftoutline.points[l+1].x)* scale) / 3.0;
-							bezt->vec[2][1] = (dy +	(2 * ftoutline.points[l+1].y)* scale) / 3.0;
-
-							bezt->h1= bezt->h2= HD_ALIGN;
-							bezt++;
-						}
-
-					//on-curve points
-					if(ftoutline.tags[l] == FT_Curve_Tag_On) {
-						//left handle
-						if(k > 0) {
-							if(ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
-								bezt->vec[0][0] = ftoutline.points[l-1].x* scale;
-								bezt->vec[0][1] = ftoutline.points[l-1].y* scale;
-								bezt->h1= HD_FREE;
-							} else if(ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
-								bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x))* scale / 3.0;
-								bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y))* scale / 3.0;
-								bezt->h1= HD_FREE;
-							} else {
-								bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l-1].x)* scale / 3.0;
-								bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l-1].y)* scale / 3.0;
-								bezt->h1= HD_VECT;
-							}
-						} else { //first point on curve
-							if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
-								bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
-								bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
-								bezt->h1= HD_FREE;
-							} else if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
-								bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x))* scale / 3.0 ;
-								bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y))* scale / 3.0 ;
-								bezt->h1= HD_FREE;
-							} else {
-								bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x)* scale / 3.0;
-								bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y)* scale / 3.0;
-								bezt->h1= HD_VECT;
-							}
-						}
-
-						//midpoint (on-curve point)
-						bezt->vec[1][0] = ftoutline.points[l].x* scale;
-						bezt->vec[1][1] = ftoutline.points[l].y* scale;
+	// Extract the first 256 character from TTF
+	charcode= FT_Get_First_Char(face, &glyph_index);
+	while(charcode < 256)
+	{
+		// Generate the font data
+		freetypechar_to_vchar(face, charcode, vfd);
 
-						//right handle
-						if(k < (npoints[j] - 1)) {
-							if(ftoutline.tags[l+1] == FT_Curve_Tag_Cubic) {
-								bezt->vec[2][0] = ftoutline.points[l+1].x* scale;
-								bezt->vec[2][1] = ftoutline.points[l+1].y* scale;
-								bezt->h2= HD_FREE;
-							} else if(ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
-								bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l+1].x))* scale / 3.0;
-								bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l+1].y))* scale / 3.0;
-								bezt->h2= HD_FREE;
-							} else {
-								bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l+1].x)* scale / 3.0;
-								bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l+1].y)* scale / 3.0;
-								bezt->h2= HD_VECT;
-							}
-						} else { //last point on curve
-							if(ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
-								bezt->vec[2][0] = ftoutline.points[m].x* scale;
-								bezt->vec[2][1] = ftoutline.points[m].y* scale;
-								bezt->h2= HD_FREE;
-							} else if(ftoutline.tags[m] == FT_Curve_Tag_Conic) {
-								bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x))* scale / 3.0 ;
-								bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y))* scale / 3.0 ;
-								bezt->h2= HD_FREE;
-							} else {
-								bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[m].x)* scale / 3.0;
-								bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[m].y)* scale / 3.0;
-								bezt->h2= HD_VECT;
-							}
-						}
-
-						// get the handles that are aligned, tricky...
-						// DistVL2Dfl, check if the three beztriple points are on one line
-						// VecLenf, see if there's a distance between the three points
-						// VecLenf again, to check the angle between the handles 
-						// finally, check if one of them is a vector handle 
-						if((DistVL2Dfl(bezt->vec[0],bezt->vec[1],bezt->vec[2]) < 0.001) &&
-							(VecLenf(bezt->vec[0], bezt->vec[1]) > 0.0001) &&
-							(VecLenf(bezt->vec[1], bezt->vec[2]) > 0.0001) &&
-							(VecLenf(bezt->vec[0], bezt->vec[2]) > 0.0002) &&
-							(VecLenf(bezt->vec[0], bezt->vec[2]) > MAX2(VecLenf(bezt->vec[0], bezt->vec[1]), VecLenf(bezt->vec[1], bezt->vec[2]))) &&
-							bezt->h1 != HD_VECT && bezt->h2 != HD_VECT)
-						{
-							bezt->h1= bezt->h2= HD_ALIGN;
-						}
-						bezt++;
-					}
-				}
-			}
-		}
-
-		if(npoints) MEM_freeN(npoints);
-		if(onpoints) MEM_freeN(onpoints);
+		// Next glyph
+		charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
 	}
-	return vfd;
+
+	return vfd;	
 }
 
 
@@ -391,6 +466,30 @@ VFontData *BLI_vfontdata_from_freetypefo
 	FT_Done_FreeType( library);
 	
 	return vfd;
+}
+
+int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
+{
+	int success = FALSE;
+
+	if(!vfont) return FALSE;
+
+	// Init Freetype
+	err = FT_Init_FreeType(&library);
+	if(err) {
+		error("Failed to load the Freetype font library");
+		return 0;
+	}
+
+	// Load the character
+	success = objchr_to_ftvfontdata(vfont, character);
+	if(success == FALSE) return FALSE;
+
+	// Free Freetype
+	FT_Done_FreeType(library);
+
+	// Ahh everything ok
+	return TRUE;
 }
 
 #endif // WITH_FREETYPE2
Index: source/blender/blenlib/intern/psfont.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenlib/intern/psfont.c,v
retrieving revision 1.8
diff -u -p -r1.8 psfont.c
--- source/blender/blenlib/intern/psfont.c	17 Jun 2005 21:04:26 -0000	1.8
+++ source/blender/blenlib/intern/psfont.c	5 Sep 2005 08:53:43 -0000
@@ -1956,6 +1956,7 @@ static VFontData *objfnt_to_vfontdata(ob
 	struct Nurb *nu;
 	struct BezTriple *bezt, *bez2;
 	float scale, dx, dy;
+	struct VChar *che;
 
 	if (!fnt || (fnt->type!=SP_TYPE)) {
 		return NULL;
@@ -1967,7 +1968,10 @@ static VFontData *objfnt_to_vfontdata(ob
 	for (i = 0; i < MAX_VF_CHARS; i++) {
 		cd = getchardesc(fnt, i);
 		if (cd && cd->data && cd->datalen) {
-			vfd->width[i] = scale * cd->movex;
+			che = (VChar *) MEM_callocN(sizeof(VChar), "objfnt_char");
+			BLI_addtail(&vfd->characters, che);
+			che->index = i;
+			che->width = scale * cd->movex;
 
 			_data = data = cd->data;
 
@@ -2015,7 +2019,7 @@ static VFontData *objfnt_to_vfontdata(ob
 					nu  =  (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
 					bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
 					if (nu != 0 && bezt != 0) {
-						BLI_addtail(&vfd->nurbsbase[i], nu);
+						BLI_addtail(&che->nurbsbase, nu);
 						nu->type= CU_BEZIER+CU_2D;
 						nu->pntsu = count;
 						nu->resolu= 8;
Index: source/blender/blenloader/intern/writefile.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/blenloader/intern/writefile.c,v
retrieving revision 1.56
diff -u -p -r1.56 writefile.c
--- source/blender/blenloader/intern/writefile.c	24 Aug 2005 20:37:25 -0000	1.56
+++ source/blender/blenloader/intern/writefile.c	5 Sep 2005 08:53:43 -0000
@@ -845,6 +845,13 @@ static void write_mballs(WriteData *wd, 
 	}
 }
 
+int amount_of_chars(char *str)
+{
+	// Since the data is saved as UTF-8 to the cu->str
+	// The cu->len is not same as the strlen(cu->str)
+	return strlen(str);
+}
+
 static void write_curves(WriteData *wd, ListBase *idbase)
 {
 	Curve *cu;
@@ -860,7 +867,7 @@ static void write_curves(WriteData *wd, 
 			writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
 
 			if(cu->vfont) {
-				writedata(wd, DATA, cu->len+1, cu->str);
+				writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str);
 				writestruct(wd, DATA, "CharInfo", cu->len, cu->strinfo);
 				writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);				
 			}
Index: source/blender/include/BIF_editfont.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/include/BIF_editfont.h,v
retrieving revision 1.15
diff -u -p -r1.15 BIF_editfont.h
--- source/blender/include/BIF_editfont.h	3 Jul 2005 17:35:31 -0000	1.15
+++ source/blender/include/BIF_editfont.h	5 Sep 2005 08:53:43 -0000
@@ -30,16 +30,26 @@
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
 
+#include <wchar.h>
+
 #ifndef BIF_EDITFONT_H
 #define BIF_EDITFONT_H
 
 struct Text;
 
 extern char *BIF_lorem;
-extern char *copybuf;
-extern char *copybufinfo;
+extern wchar_t *copybuf;
+extern wchar_t *copybufinfo;
+
+typedef struct unicodect
+{
+	char *name;
+	char *longname;
+	int   start;
+	int   end;
+} unicodect;
 
-void do_textedit(unsigned short event, short val, char _ascii);
+void do_textedit(unsigned short event, short val, unsigned long _ascii);
 void make_editText(void);
 void load_editText(void);
 void remake_editText(void);
Index: source/blender/include/BIF_interface.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/include/BIF_interface.h,v
retrieving revision 1.34
diff -u -p -r1.34 BIF_interface.h
--- source/blender/include/BIF_interface.h	15 Aug 2005 19:46:08 -0000	1.34
+++ source/blender/include/BIF_interface.h	5 Sep 2005 08:53:43 -0000
@@ -151,6 +151,7 @@ struct ScrArea;
 #define HSVCUBE (26<<9)
 #define PULLDOWN (27<<9)
 #define ROUNDBOX (28<<9)
+#define CHARTAB (29<<9)
 
 #define BUTTYPE	(31<<9)
 
Index: source/blender/include/butspace.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/include/butspace.h,v
retrieving revision 1.53
diff -u -p -r1.53 butspace.h
--- source/blender/include/butspace.h	29 Aug 2005 12:46:07 -0000	1.53
+++ source/blender/include/butspace.h	5 Sep 2005 08:53:43 -0000
@@ -408,6 +408,12 @@ enum {
 #define B_STYLETOSELU	2213
 #define B_STYLETOSELI	2214
 
+#define B_SETCHAR               2215
+#define B_SETUPCHAR             2216
+#define B_SETDOWNCHAR   	2217
+#define B_SETCAT                2218
+#define B_SETUNITEXT    	2219
+
 /* *********************** */
 #define B_ARMBUTS		2400
 
Index: source/blender/src/buttons_editing.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/buttons_editing.c,v
retrieving revision 1.195
diff -u -p -r1.195 buttons_editing.c
--- source/blender/src/buttons_editing.c	3 Sep 2005 17:22:29 -0000	1.195
+++ source/blender/src/buttons_editing.c	5 Sep 2005 08:53:44 -0000
@@ -86,6 +86,7 @@
 #include "BLI_arithb.h"
 #include "BLI_vfontdata.h"
 #include "BLI_editVert.h"
+#include "BLI_dynstr.h"
 
 #include "BSE_filesel.h"
 
@@ -159,6 +160,202 @@ short uv_calc_mapdir= 1, uv_calc_mapalig
 
 extern ListBase editNurb;
 
+/* *************************** Unicode Character Groups ****************** */
+unicodect uctabname[125] = {
+	{"All", "All", 0x0000, 0xffff},
+	{"Basic Latin", "Basic Latin", 0x0000, 0x007f},
+	{"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff}, 
+  			    
+	{"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
+	{"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F}, 
+	{"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
+			    
+	{"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
+	{"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
+			    
+	{"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
+	{"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
+	{"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
+			    
+	{"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
+	{"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
+			    
+	{"Armenian", "Armenian", 0x0530, 0x058f},
+	{"Hebrew", "Hebrew", 0x0590, 0x05ff},
+			    
+	
+	{"Arabic", "Arabic", 0x0600, 0x06ff},
+	{"Syriac", "Syriac", 0x0700, 0x074f},
+			    
+	{"Thaana", "Thaana", 0x0780, 0x07bf},
+	{"Devanagari", "Devanagari", 0x0900, 0x097f},
+			    
+	{"Bengali", "Bengali", 0x0980, 0x09ff},
+	{"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
+			    
+	{"Gujarati", "Gujarati", 0x0a80, 0x0aff},
+	{"Oriya", "Oriya", 0x0b00, 0x0b7f},
+			    
+	{"Tamil", "Tamil", 0x0b80, 0x0bff},
+	{"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
+			    
+	{"Kannada", "Kannada", 0x0c80, 0x0cff},
+	{"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
+			    
+	{"Sinhala", "Sinhala", 0x0d80, 0x0dff},
+	{"Thai", "Thai", 0x0e00, 0x0e7f},
+			    
+	{"Lao", "Lao", 0x0e80, 0x0eff},
+	{"Tibetan", "Tibetan", 0x0f00, 0x0fff},
+			    
+	{"Myanmar", "Myanmar", 0x1000, 0x109f},
+	{"Georgian", "Georgian", 0x10a0, 0x10ff},
+			    
+	{"Ethiopic", "Ethiopic", 0x1200, 0x137f},
+			    
+	{"Cherokee", "Cherokee", 0x13a0, 0x13ff},
+	{"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
+			    
+	{"Ogham", "Ogham", 0x1680, 0x169f},
+	{"Runic", "Runic", 0x16a0, 0x16ff},
+			    
+	{"Tagalog", "Tagalog", 0x1700, 0x171f},
+	{"Hanunoo", "Hanunoo", 0x1720, 0x173f},
+			    
+	{"Buhid", "Buhid", 0x1740, 0x175f},
+	{"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
+			    
+	{"Khmer", "Khmer", 0x1780, 0x17ff},
+	{"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
+
+	{"Mongolian", "Mongolian", 0x1800, 0x18af},
+			    
+	{"Limbu", "Limbu", 0x1900, 0x194f},
+	{"Tai Le", "Tai Le", 0x1950, 0x197f},
+			    
+	{"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
+			    
+			    
+	{"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
+	{"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
+			    
+	{"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
+	{"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
+			    
+	{"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
+	{"Numb. Forms", "Number Forms", 0x2150, 0x218f},
+			    
+	{"Arrows", "Arrows", 0x2190, 0x21ff},
+	{"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
+			   
+	{"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
+	{"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
+			    
+	{"OCR", "Optical Character Recognition", 0x2440, 0x245f},
+	{"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
+			    
+	{"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
+	{"BLock Elem.", "Block Elements", 0x2580, 0x259f},
+			    
+	{"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
+	{"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
+			    
+	{"Dingbats", "Dingbats", 0x2700, 0x27bf},
+	{"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
+			    
+	{"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
+	{"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
+			    
+	{"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
+	{"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
+			    
+	{"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
+	{"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
+			    
+	{"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
+			    
+	{"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
+			    
+	{"Hiragana", "Hiragana", 0x3040, 0x309f},
+	{"Katakana", "Katakana", 0x30a0, 0x30ff},
+	{"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
+			    
+	{"Bopomofo", "Bopomofo", 0x3100, 0x312f},
+	{"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
+
+	{"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
+	{"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
+	{"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
+			    
+	{"Kanbun", "Kanbun", 0x3190, 0x319f},
+			    
+			    
+			    
+	{"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
+			    
+	{"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
+	{"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
+			    
+	{"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
+			    
+	{"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
+	{"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
+			    
+	{"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
+	{"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
+	{"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
+	{"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
+	{"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
+	{"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
+	{"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
+	{"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
+	{"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
+	{"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
+
+	{"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
+			    
+	{"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
+	{"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
+
+	{"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
+			    
+	{"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
+			    
+	{"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
+			    
+	{"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
+	{"Specials", "Specials", 0xfff0, 0xffff},
+			    
+	{"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
+	{"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
+			    
+	{"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
+	{"Old Italic", "Old Italic", 0x10300, 0x1032f},
+			   
+	{"Gothic", "Gothic", 0x10330, 0x1034f},
+	{"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
+			    
+	{"Deseret", "Deseret", 0x10400, 0x1044f},
+	{"Shavian", "Shavian", 0x10450, 0x1047f},
+			    
+	{"Osmanya", "Osmanya", 0x10480, 0x104af},
+	{"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
+			    
+	{"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
+	{"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
+			    
+	{"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
+	{"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
+			    
+			    
+	{"Tags", "Tags", 0xe0000, 0xe007f},
+	{"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
+			    
+	{"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
+	{"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
+			
+};
+
 
 /* *************************** static functions prototypes ****************** */
 VFont *exist_vfont(char *str);
@@ -1268,6 +1465,11 @@ static void load_buts_vfont(char *name)
 	allqueue(REDRAWBUTSEDIT, 0);
 }
 
+static void set_unicode_text_fs(char *file)
+{
+	if (file > 0) paste_unicodeText(file); 
+}
+
 void do_fontbuts(unsigned short event)
 {
 	Curve *cu;
@@ -1275,6 +1477,9 @@ void do_fontbuts(unsigned short event)
 	Object *ob;
 	ScrArea *sa;
 	char str[80];
+	int ctevt;
+	char *ctmenu;
+	DynStr *ds;
 	int i, style=0;
 
 	ob= OBACT;
@@ -1422,6 +1627,74 @@ void do_fontbuts(unsigned short event)
 			}
 		}
 		break;
+		
+	case B_SETCHAR:
+		G.charmin = 0x0000;
+		G.charmax = 0xffff;
+		if(G.charstart < 0)
+			G.charstart = 0;	
+		if(G.charstart > (0xffff - 12*6))
+			G.charstart = 0xffff - (12*6);
+		allqueue(REDRAWBUTSEDIT, 0);
+		break;
+		
+	case B_SETUPCHAR:
+		G.charstart = G.charstart - (12*6);
+		if(G.charstart < 0)
+			G.charstart = 0;	
+		if(G.charstart < G.charmin)
+			G.charstart = G.charmin;
+		allqueue(REDRAWBUTSEDIT, 0);
+		break;
+		
+	case B_SETCAT:
+		// Create new dynamic string
+		ds = BLI_dynstr_new();
+		
+		// Fill the dynamic string with entries
+		for(i=0;i<104;i++)
+		{
+			BLI_dynstr_append(ds, "|");
+			BLI_dynstr_append(ds, uctabname[i].name);
+		}
+		
+		// Create the menu string from dyn string
+		ctmenu = BLI_dynstr_get_cstring(ds);
+		
+		// Call the popup menu
+		ctevt = pupmenu_col(ctmenu, 40);
+		G.charstart = uctabname[ctevt-1].start;
+		G.charmin = uctabname[ctevt-1].start;
+		G.charmax = uctabname[ctevt-1].end;
+
+		// Free all data
+		BLI_dynstr_free(ds);
+		MEM_freeN(ctmenu);
+
+		// And refresh
+		allqueue(REDRAWVIEW3D, 0);
+		allqueue(REDRAWBUTSEDIT, 0);
+		
+		break;	
+		
+	case B_SETDOWNCHAR:
+		G.charstart = G.charstart + (12*6);
+		if(G.charstart > (0xffff - 12*6))
+			G.charstart = 0xffff - (12*6);
+		if(G.charstart > G.charmax - 12*6)
+			G.charstart = G.charmax - 12*6;
+		allqueue(REDRAWBUTSEDIT, 0);
+		break;
+		
+	case B_SETUNITEXT:
+		sa= closest_bigger_area();
+		areawinset(sa->win);
+
+		if(ob==G.obedit) {
+			activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
+		}
+		break;		
+		
 	case B_TEXTONCURVE:
 		if(ob) {
 			cu= ob->data;
@@ -1436,6 +1709,32 @@ void do_fontbuts(unsigned short event)
 	}
 }
 
+static void editing_panel_char_type(Object *ob, Curve *cu)
+{
+	uiBlock *block;
+
+	block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
+	uiNewPanelTabbed("Font", "Editing");
+	if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
+		return;
+
+	// Set the selected font
+	G.selfont = cu->vfont;
+	
+	uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,	0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
+
+	// Unicode categorization selection button
+	uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
+	uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
+
+	// Character selection button
+	uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
+
+	// Buttons to change the max, min
+	uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
+	uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
+}
+
 static void editing_panel_font_type(Object *ob, Curve *cu)
 {
 	uiBlock *block;
@@ -3360,6 +3659,13 @@ void editing_panels()
 		editing_panel_links(ob); // no editmode!
 		editing_panel_curve_type(ob, cu);
 		editing_panel_font_type(ob, cu);
+
+#ifdef INTERNATIONAL
+		if(G.obedit)
+		{
+			editing_panel_char_type(ob, cu);
+		}
+#endif
 		editing_panel_modifiers(ob);
 		break;
 
Index: source/blender/src/editfont.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/editfont.c,v
retrieving revision 1.30
diff -u -p -r1.30 editfont.c
--- source/blender/src/editfont.c	29 Aug 2005 12:46:06 -0000	1.30
+++ source/blender/src/editfont.c	5 Sep 2005 08:53:44 -0000
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
+#include <wchar.h>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -86,7 +87,7 @@ int textediting=0;
 
 extern struct SelBox *selboxes;		/* from blenkernel/font.c */
 
-static char findaccent(char char1, char code)
+static char findaccent(char char1, unsigned int code)
 {
 	char new= 0;
 	
@@ -217,15 +218,25 @@ static char findaccent(char char1, char 
 	else return char1;
 }
 
-char *copybuf=NULL;
-char *copybufinfo=NULL;
+wchar_t *copybuf=NULL;
+wchar_t *copybufinfo=NULL;
 
-static char *textbuf=NULL;
+static wchar_t *textbuf=NULL;
 static CharInfo *textbufinfo=NULL;
-static char *oldstr=NULL;
+static wchar_t *oldstr=NULL;
 static CharInfo *oldstrinfo=NULL;
 
-static int insert_into_textbuf(Curve *cu, char c)
+void update_string(Curve *cu)
+{
+	int len;
+	
+	MEM_freeN(cu->str);
+	len = wcsleninu8(textbuf);
+	cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
+	wcs2utf8s(cu->str, textbuf);
+}
+
+static int insert_into_textbuf(Curve *cu, unsigned long c)
 {
 	if (cu->len<MAXTEXT-1) {
 		int x;
@@ -244,6 +255,8 @@ static int insert_into_textbuf(Curve *cu
 		cu->len++;
 		textbuf[cu->len]='\0';
 
+		update_string(cu);
+
 		return 1;
 	} else {
 		return 0;
@@ -280,16 +293,36 @@ void add_lorem(void)
 void load_3dtext_fs(char *file) 
 {
 	FILE *fp;
-	int c;
+	int filelen;
+	char *strp;
+	Curve *cu=G.obedit->data;
 
 	fp= fopen(file, "r");
 	if (!fp) return;
+
+	fseek(fp, 0L, SEEK_END);
+	filelen = ftell(fp);
+	fseek(fp, 0L, SEEK_SET);	
+
+	strp = MEM_callocN(filelen+4, "tempstr");	
+
+	filelen = fread(strp, 1, filelen, fp);
+	fclose(fp);
+	strp[filelen]= 0;
 	
-	while (!feof(fp)) {
-		c = fgetc(fp);
-		if (c!=EOF) insert_into_textbuf(OBACT->data, c);
+	if(cu->len+filelen<MAXTEXT)
+	{
+		int tmplen;
+		wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+		tmplen = utf8towchar_(mem, strp);
+		wcscat(textbuf, mem);
+		MEM_freeN(mem);
+		cu->len += tmplen;
+		cu->pos= cu->len;
 	}
-	fclose(fp);
+	MEM_freeN(strp);
+
+	update_string(cu);
 
 	DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
 	allqueue(REDRAWVIEW3D, 0);	
@@ -479,6 +512,7 @@ static int killselection(int ins)	/* 1 =
 
 	direction = getselection(&selstart, &selend);
 	if (direction) {
+		int size;
 		if (ins) offset = 1;
 		if (cu->pos >= selstart) cu->pos = selstart+offset;
 		if ((direction == -1) && ins) {
@@ -487,7 +521,8 @@ static int killselection(int ins)	/* 1 =
 		}
 		getfrom = selend+offset;
 		if (ins==0) getfrom++;
-		memmove(textbuf+selstart, textbuf+getfrom, (cu->len-selstart)+offset);
+		size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset*sizeof(wchar_t));
+		memmove(textbuf+selstart, textbuf+getfrom, size);
 		memmove(textbufinfo+selstart, textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
 		cu->len -= (selend-selstart)+offset;
 		cu->selstart = cu->selend = 0;
@@ -500,7 +535,7 @@ static void copyselection(void)
 	int selstart, selend;
 	
 	if (getselection(&selstart, &selend)) {
-		memcpy(copybuf, textbuf+selstart, (selend-selstart)+1);
+		memcpy(copybuf, textbuf+selstart, ((selend-selstart)+1)*sizeof(wchar_t));
 		copybuf[(selend-selstart)+1]=0;
 		memcpy(copybufinfo, textbufinfo+selstart, ((selend-selstart)+1)*sizeof(CharInfo));	
 	}
@@ -509,11 +544,12 @@ static void copyselection(void)
 static void pasteselection(void)
 {
 	Curve *cu= G.obedit->data;
-	int len= strlen(copybuf);
+	int len= wcslen(copybuf);
 	
 	if (len) {
-		memmove(textbuf+cu->pos+len, textbuf+cu->pos, cu->len-cu->pos+1);
-		memcpy(textbuf+cu->pos, copybuf, len);
+		int size = (cu->len * sizeof(wchar_t)) - (cu->pos*sizeof(wchar_t)) + sizeof(wchar_t);
+		memmove(textbuf+cu->pos+len, textbuf+cu->pos, size);
+		memcpy(textbuf+cu->pos, copybuf, len * sizeof(wchar_t));
 		
 		memmove(textbufinfo+cu->pos+len, textbufinfo+cu->pos, (cu->len-cu->pos+1)*sizeof(CharInfo));
 		memcpy(textbufinfo+cu->pos, copybufinfo, len*sizeof(CharInfo));	
@@ -564,12 +600,12 @@ int mat_to_sel(void) {
 	return 0;
 }
 
-void do_textedit(unsigned short event, short val, char _ascii)
+void do_textedit(unsigned short event, short val, unsigned long _ascii)
 {
 	Curve *cu;
 	static int accentcode= 0;
 	int x, doit=0, cursmove=0;
-	int ascii = _ascii;
+	unsigned long ascii = _ascii;
 	short kern;
 
 	cu= G.obedit->data;
@@ -608,7 +644,6 @@ void do_textedit(unsigned short event, s
 					else if(ascii=='>') ascii= 187;
 					else if(ascii=='<') ascii= 171;
 				}
-				
 				if(ascii==1001) {
 					int file, filelen;
 					char *strp;
@@ -627,9 +662,14 @@ void do_textedit(unsigned short event, s
 						read(file, strp, filelen);
 						close(file);
 						strp[filelen]= 0;
+
 						if(cu->len+filelen<MAXTEXT) {
-							strcat( textbuf, strp);
-							cu->len= strlen(textbuf);
+							int tmplen;
+							wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+							tmplen = utf8towchar_(mem, strp);
+							wcscat(textbuf, mem);
+							MEM_freeN(mem);
+							cu->len += tmplen;
 							cu->pos= cu->len;
 						}
 						MEM_freeN(strp);
@@ -644,6 +684,11 @@ void do_textedit(unsigned short event, s
 			
 			doit= 1;
 		}
+		else
+		{
+			insert_into_textbuf(cu, ascii);
+			doit = 1;
+		}
 	}
 	else if(val) {
 		cursmove= 0;
@@ -841,6 +886,7 @@ void do_textedit(unsigned short event, s
 			if ((G.qual & LR_SHIFTKEY)==0) {
 				if (cu->selstart) {
 					cu->selstart = cu->selend = 0;
+					update_string(cu);
 					text_to_curve(G.obedit, FO_SELCHANGE);
 					allqueue(REDRAWVIEW3D, 0);
 				}
@@ -860,6 +906,7 @@ void do_textedit(unsigned short event, s
 			G.obedit->actcol = textbufinfo[cu->pos-1].mat_nr;
 		}
 		allqueue(REDRAWBUTSEDIT, 0);
+		update_string(cu);
 		text_to_curve(G.obedit, cursmove);
 		if (cursmove && (G.qual & LR_SHIFTKEY)) {
 			cu->selend = cu->pos;
@@ -874,16 +921,64 @@ void do_textedit(unsigned short event, s
 	}
 }
 
+void paste_unicodeText(char *filename)
+{
+	Curve *cu;
+	int filelen, doit= 0;
+	char *strp;
+	FILE *fp = NULL;
+
+	fp= fopen(filename, "r");
+
+	if(fp) {
+		cu= G.obedit->data;
+
+		fseek( fp, 0L, SEEK_END );
+		filelen = ftell( fp );
+		fseek( fp, 0L, SEEK_SET );
+			
+		strp= MEM_mallocN(filelen+4, "tempstr");
+		//fread() instead of read(),
+		//because windows read() converts text to DOS \r\n linebreaks
+		//causing double linebreaks in the 3d text
+		filelen = fread(strp, 1, filelen, fp);
+		fclose(fp);
+		strp[filelen]= 0;
+
+
+		if(cu->len+filelen<MAXTEXT) 
+		{
+			int tmplen;
+			wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+			tmplen = utf8towchar_(mem, strp);
+//			mem =utf8s2wc(strp);
+			wcscat(textbuf, mem);
+			MEM_freeN(mem);
+//			cu->len = wcslen(textbuf);
+			cu->len += tmplen;
+			cu->pos= cu->len;
+		}
+		MEM_freeN(strp);
+		doit = 1;
+	}
+	if(doit) {
+		update_string(cu);
+		text_to_curve(G.obedit, 0);
+		DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+		allqueue(REDRAWVIEW3D, 0);
+		BIF_undo_push("Paste text");
+	}
+}
 
 void paste_editText(void)
 {
 	Curve *cu;
-	int file, filelen, doit= 0;
+	int filelen, doit= 0;
 	char *strp;
-
+  FILE *fp = NULL;
 
 #ifdef WIN32
-	file= open("C:\\windows\\temp\\cutbuf.txt", O_BINARY|O_RDONLY);
+	fp= fopen("C:\\windows\\temp\\cutbuf.txt", "r");
 
 //	The following is more likely to work on all Win32 installations.
 //	suggested by Douglas Toltzman. Needs windows include files...
@@ -900,26 +995,39 @@ void paste_editText(void)
 	}
 */
 #else
-	file= open("/tmp/.cutbuffer", O_BINARY|O_RDONLY);
+	fp= fopen("/tmp/.cutbuffer", "r");
 #endif
 
-	if(file>0) {
+	if(fp) {
 		cu= G.obedit->data;
-		filelen = BLI_filesize(file);
+		
+		fseek(fp, 0L, SEEK_END);		
+		filelen = ftell( fp );
+		fseek(fp, 0L, SEEK_SET);
 				
 		strp= MEM_mallocN(filelen+4, "tempstr");
-		read(file, strp, filelen);
-		close(file);
+		// fread() instead of read(),
+		// because windows read() converts text to DOS \r\n linebreaks
+		// causing double linebreaks in the 3d text
+		filelen = fread(strp, 1, filelen, fp);
+		fclose(fp);
 		strp[filelen]= 0;
+		
 		if(cu->len+filelen<MAXTEXT) {
-			strcat( textbuf, strp);
-			cu->len= strlen(textbuf);
-			cu->pos= cu->len;
+		  int tmplen;
+		  wchar_t *mem = MEM_callocN((sizeof(wchar_t) * filelen) + (4 * sizeof(wchar_t)), "temporary");
+		  tmplen = utf8towchar_(mem, strp);
+		  wcscat(textbuf, mem);
+		  MEM_freeN(mem);
+		  cu->len += tmplen;
+		  cu->pos= cu->len;
 		}
 		MEM_freeN(strp);
 		doit = 1;
 	}
 	if(doit) {
+		update_string(cu);
+		text_to_curve(G.obedit, 0);
 		DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
 		allqueue(REDRAWVIEW3D, 0);
 		BIF_undo_push("Paste text");
@@ -930,19 +1038,23 @@ void paste_editText(void)
 void make_editText(void)
 {
 	Curve *cu;
-
 	cu= G.obedit->data;
-	if(textbuf==NULL) textbuf= MEM_mallocN(MAXTEXT+4, "texteditbuf");
+	
+	if(textbuf==NULL) textbuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditbuf");
 	if(textbufinfo==NULL) textbufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditbufinfo");
-	if(copybuf==NULL) copybuf= MEM_callocN(MAXTEXT+4, "texteditcopybuf");
+	if(copybuf==NULL) copybuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditcopybuf");
 	if(copybufinfo==NULL) copybufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditcopybufinfo");	
-	BLI_strncpy(textbuf, cu->str, MAXTEXT);
-	cu->len= strlen(textbuf);
+	if(oldstr==NULL) oldstr= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "oldstrbuf");
+	
+  // Convert the original text to wchar_t
+  utf8towchar_(textbuf, cu->str);
+	wcscpy(oldstr, textbuf);
+		
+	cu->len= wcslen(textbuf);
 	
 	memcpy(textbufinfo, cu->strinfo, (cu->len)*sizeof(CharInfo));
-	oldstr= cu->str;
+	
 	oldstrinfo= cu->strinfo;
-	cu->str= textbuf;
 	cu->strinfo= textbufinfo;
 
 	if(cu->pos>cu->len) cu->pos= cu->len;
@@ -951,6 +1063,9 @@ void make_editText(void)
 		cu->curinfo = textbufinfo[cu->pos-1];
 	} else cu->curinfo = textbufinfo[0];
 	
+	// Convert to UTF-8
+	update_string(cu);
+	
 	DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
 	
 	textediting= 1;
@@ -969,8 +1084,8 @@ void load_editText(void)
 	MEM_freeN(oldstrinfo);
 	oldstrinfo= NULL;
 	
-	cu->str= MEM_mallocN(cu->len+4, "textedit");
-	strcpy(cu->str, textbuf);
+	update_string(cu);
+	
 	cu->strinfo= MEM_callocN((cu->len+4)*sizeof(CharInfo), "texteditinfo");
 	memcpy(cu->strinfo, textbufinfo, (cu->len)*sizeof(CharInfo));
 
@@ -1000,7 +1115,10 @@ void remake_editText(void)
 		
 	if(okee("Reload original text")==0) return;
 	
-	BLI_strncpy(textbuf, oldstr, MAXTEXT);
+	// Copy the oldstr to textbuf temporary global variable
+	wcscpy(textbuf, oldstr);
+
+	// Set the object length and position	
 	cu= G.obedit->data;
 	cu->len= strlen(textbuf);
 	if(cu->pos>cu->len) cu->pos= cu->len;
@@ -1055,7 +1173,7 @@ void to_upper(void)
 {
 	Curve *cu;
 	int len, ok;
-	char *str;
+	wchar_t *str;
 	
 	if(G.obedit==0) {
 		return;
@@ -1064,8 +1182,8 @@ void to_upper(void)
 	ok= 0;
 	cu= G.obedit->data;
 	
-	len= strlen(cu->str);
-	str= cu->str;
+	len= wcslen(textbuf);
+	str= textbuf;
 	while(len) {
 		if( *str>=97 && *str<=122) {
 			ok= 1;
@@ -1076,8 +1194,8 @@ void to_upper(void)
 	}
 	
 	if(ok==0) {
-		len= strlen(cu->str);
-		str= cu->str;
+		len= wcslen(textbuf);
+		str= textbuf;
 		while(len) {
 			if( *str>=65 && *str<=90) {
 				*str+= 32;
@@ -1089,6 +1207,8 @@ void to_upper(void)
 	DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
 	allqueue(REDRAWVIEW3D, 0);
 	BIF_undo_push("To upper");
+
+	update_string(cu);
 }
 
 
@@ -1099,9 +1219,10 @@ static void undoFont_to_editFont(void *s
 	Curve *cu= G.obedit->data;
 	char *str= strv;
 	
-	strncpy(textbuf, str+2, MAXTEXT);
+	utf8towchar_(textbuf, str);
+	
 	cu->pos= *((short *)str);
-	cu->len= strlen(textbuf);
+	cu->len= wcslen(textbuf);
 
 	memcpy(textbufinfo, str+2+cu->len+1, cu->len*sizeof(CharInfo));
 	cu->selstart = cu->selend = 0;
@@ -1117,7 +1238,8 @@ static void *editFont_to_undoFont(void)
 	
 	str= MEM_callocN(MAXTEXT+4+(MAXTEXT+4)*sizeof(CharInfo), "string undo");
 	
-	strncpy(str+2, textbuf, MAXTEXT);
+	wcs2utf8s(str, textbuf);
+	
 	*((short *)str)= cu->pos;
 	memcpy(str+2+cu->len+1, textbufinfo, cu->len*sizeof(CharInfo));
 	
Index: source/blender/src/interface.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/interface.c,v
retrieving revision 1.201
diff -u -p -r1.201 interface.c
--- source/blender/src/interface.c	3 Sep 2005 12:35:13 -0000	1.201
+++ source/blender/src/interface.c	5 Sep 2005 08:53:45 -0000
@@ -68,6 +68,8 @@
 #include "DNA_space_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_vec_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vfont_types.h"
 
 #include "BKE_blender.h"
 #include "BKE_utildefines.h"
@@ -2687,6 +2689,56 @@ static int ui_do_but_HSVCUBE(uiBut *but)
 	return but->retval;
 }
 
+#ifdef INTERNATIONAL
+
+static int ui_do_but_CHARTAB(uiBut *but)
+{
+        /* Variables */
+        short mval[2];
+        float sx, sy, ex, ey;
+        float width, height;
+        float butw, buth;
+        int x, y;
+        unsigned long cs;
+        unsigned long che;
+
+        /* Check the position */
+        uiGetMouse(mywinget(), mval);
+
+        /* Calculate the size of the button */
+        width = abs(but->x2 - but->x1);
+        height = abs(but->y2 - but->y1);
+
+        butw = floor(width / 12);
+        buth = floor(height / 6);
+
+        /* Initialize variables */
+        sx = but->x1;
+        ex = but->x1 + butw;
+        sy = but->y1 + height - buth;
+        ey = but->y1 + height;
+
+        cs = G.charstart;
+
+        /* And the character is */
+        x = (int) ((mval[0] / butw) - 0.5);
+        y = (int) (6 - ((mval[1] / buth) - 0.5));
+
+        che = cs + (y*12) + x;
+
+        if(che > G.charmax)
+                che = 0;
+
+        if(G.obedit)
+        {
+                do_textedit(0,0,che);
+        }
+
+        return but->retval;
+}
+
+#endif
+
 
 /* ************************************************ */
 
@@ -2925,6 +2977,12 @@ static int ui_do_button(uiBlock *block, 
 	case HSVCUBE:
 		retval= ui_do_but_HSVCUBE(but);
 		break;
+		
+#ifdef INTERNATIONAL
+	case CHARTAB:
+		retval= ui_do_but_CHARTAB(but);
+		break;
+#endif
 	}
 	
 	block->flag &= ~UI_BLOCK_BUSY;
@@ -3383,7 +3441,66 @@ static int ui_do_block(uiBlock *block, u
 			}
 		}
 		break;
+
+
+#ifdef INTERNATIONAL
+	//HACK to let the chartab button react to the mousewheel and PGUP/PGDN keys
+	case WHEELUPMOUSE:
+	case PAGEUPKEY:
+		for(but= block->buttons.first; but; but= but->next)
+		{
+			if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
+			{
+				G.charstart = G.charstart - (12*6);
+				if(G.charstart < 0)
+					G.charstart = 0;
+				if(G.charstart < G.charmin)
+					G.charstart = G.charmin;
+				ui_draw_but(but);
+
+				//Really nasty... to update the num button from the same butblock
+				for(bt= block->buttons.first; bt; bt= bt->next)
+				{
+					if(bt->type == NUM) {
+						ui_check_but(bt);
+						ui_draw_but(bt);
+					}
+				}
+				retval=UI_CONT;
+				break;
+			}
+		}
+		break;
 		
+	case WHEELDOWNMOUSE:
+	case PAGEDOWNKEY:
+		for(but= block->buttons.first; but; but= but->next)
+		{
+			if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
+			{
+				G.charstart = G.charstart + (12*6);
+				if(G.charstart > (0xffff - 12*6))
+					G.charstart = 0xffff - (12*6);
+				if(G.charstart > G.charmax - 12*6)
+					G.charstart = G.charmax - 12*6;
+				ui_draw_but(but);
+
+				for(bt= block->buttons.first; bt; bt= bt->next)
+				{
+					if(bt->type == NUM) {
+						ui_check_but(bt);
+						ui_draw_but(bt);
+					}
+				}
+				
+				but->flag |= UI_ACTIVE;
+				retval=UI_RETURN_OK;
+				break;
+			}
+		}
+		break;
+#endif
+				
 	case PADENTER:
 	case RETKEY:	// prevent treating this as mousemove. for example when you enter at popup 
 		if(block->flag & UI_BLOCK_LOOP) break;
Index: source/blender/src/interface_draw.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/interface_draw.c,v
retrieving revision 1.41
diff -u -p -r1.41 interface_draw.c
--- source/blender/src/interface_draw.c	15 Aug 2005 19:46:09 -0000	1.41
+++ source/blender/src/interface_draw.c	5 Sep 2005 08:53:45 -0000
@@ -1,3 +1,4 @@
+
 /**
  * $Id: interface_draw.c,v 1.41 2005/08/15 19:46:09 ton Exp $
  *
@@ -58,6 +59,7 @@
 #include "DNA_space_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_vec_types.h"
+#include "DNA_vfont_types.h"
 
 #include "BKE_blender.h"
 #include "BKE_utildefines.h"
@@ -79,6 +81,8 @@
 
 #include "BSE_view.h"
 
+#include "FTF_Api.h"
+
 #include "mydevice.h"
 #include "interface.h"
 #include "blendef.h"
@@ -1698,6 +1702,116 @@ static void ui_draw_but_HSVCUBE(uiBut *b
 	fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
 }
 
+#ifdef INTERNATIONAL
+static void ui_draw_but_CHARTAB(uiBut *but)
+{
+	/* Some local variables */
+	float sx, sy, ex, ey;
+	float width, height;
+	float butw, buth;
+	int x, y;
+	unsigned long cs;
+	wchar_t wstr[2];
+	unsigned char ustr[16];
+
+	/* Calculate the size of the button */
+	width = abs(but->x2 - but->x1);
+	height = abs(but->y2 - but->y1);
+	
+	butw = floor(width / 12);
+	buth = floor(height / 6);
+	
+	/* Initialize variables */
+	sx = but->x1;
+	ex = but->x1 + butw;
+	sy = but->y1 + height - buth;
+	ey = but->y1 + height;
+
+	cs = G.charstart;
+
+	/* Set the font */
+	if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+	{
+		char tmpStr[256];
+		strcpy(tmpStr, G.selfont->name);
+		BLI_convertstringcode(tmpStr, G.sce, 0);
+		FTF_SetFont(tmpStr, 0, 14.0);
+	}
+
+	/* Start drawing the button itself */
+	glShadeModel(GL_SMOOTH);
+
+	glColor3ub(200,  200,  200);
+	glRectf((but->x1), (but->y1), (but->x2), (but->y2));
+
+	glColor3ub(0,  0,  0);
+	for(y = 0; y < 6; y++)
+	{
+		// Do not draw more than the category allows
+		if(cs > G.charmax) break;
+
+		for(x = 0; x < 12; x++)
+		{
+			// Do not draw more than the category allows
+			if(cs > G.charmax) break;
+
+			// Draw one grid cell
+			glBegin(GL_LINE_LOOP);
+				glVertex2f(sx, sy);
+				glVertex2f(ex, sy);
+				glVertex2f(ex, ey);
+				glVertex2f(sx, ey);				
+			glEnd();	
+
+			// Draw character inside the cell
+			memset(wstr, 0, sizeof(wchar_t)*2);
+			memset(ustr, 0, 16);
+			
+			wstr[0] = cs;
+			wcs2utf8s(ustr, wstr);
+
+			if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+			{
+				float wid;
+				float llx, lly, llz, urx, ury, urz;
+				float dx, dy;
+				float px, py;
+	
+				// Calculate the position
+				wid = FTF_GetStringWidth(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+				FTF_GetBoundingBox(ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+				dx = urx-llx;
+				dy = ury-lly;
+
+				// This isn't fully functional since the but->aspect isn't working like I suspected
+				px = sx + ((butw/but->aspect)-dx)/2;
+				py = sy + ((buth/but->aspect)-dy)/2;
+
+				// Set the position and draw the character
+				ui_rasterpos_safe(px, py, but->aspect);
+				FTF_DrawString(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+			}
+			else
+			{
+				ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
+				BIF_DrawString(but->font, ustr, 0);
+			}
+	
+			// Calculate the next position and character
+			sx += butw; ex +=butw;
+			cs++;
+		}
+		/* Add the y position and reset x position */
+		sy -= buth; 
+		ey -= buth;
+		sx = but->x1;
+		ex = but->x1 + butw;
+	}	
+	glShadeModel(GL_FLAT);
+}
+
+#endif // INTERNATIONAL
+
 static void ui_draw_roundbox(uiBut *but)
 {
 	BIF_ThemeColorShade(but->themecol, but->a2);
@@ -1754,7 +1868,6 @@ void ui_set_embossfunc(uiBut *but, int d
 	// note: if you want aligning, adapt the call uiBlockEndAlign in interface.c 
 }
 
-
 void ui_draw_but(uiBut *but)
 {
 	double value;
@@ -1795,6 +1908,13 @@ void ui_draw_but(uiBut *but)
 	case HSVCUBE:
 		ui_draw_but_HSVCUBE(but);  // box for colorpicker, three types
 		break;
+
+#ifdef INTERNATIONAL
+	case CHARTAB:
+		value= ui_get_but_val(but);
+		ui_draw_but_CHARTAB(but);
+		break;
+#endif
 
 	case LINK:
 	case INLINK:
Index: source/blender/src/usiblender.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/usiblender.c,v
retrieving revision 1.89
diff -u -p -r1.89 usiblender.c
--- source/blender/src/usiblender.c	23 Aug 2005 20:04:10 -0000	1.89
+++ source/blender/src/usiblender.c	5 Sep 2005 08:53:45 -0000
@@ -78,6 +78,8 @@
 #include "BKE_packedFile.h"
 #include "BKE_utildefines.h"
 
+#include "BLI_vfontdata.h"
+
 #include "BIF_fsmenu.h"
 #include "BIF_gl.h"
 #include "BIF_interface.h"
@@ -291,9 +293,20 @@ int BIF_read_homefile(void)
 	char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
 	char *home= BLI_gethome();
 	int success;
+	struct TmpFont *tf;
 	
 	BLI_clean(home);
 
+	tf= G.ttfdata.first;
+	while(tf)
+	{
+		freePackedFile(tf->pf);
+		tf->pf = NULL;
+		tf->vfont = NULL;
+		tf= tf->next;
+	}
+	BLI_freelistN(&G.ttfdata);
+	
 #if 0
 //#ifdef _WIN32	// FULLSCREEN
 	static int screenmode = -1;
@@ -632,6 +645,17 @@ extern ListBase editelems;
 
 void exit_usiblender(void)
 {
+  struct TmpFont *tf;
+  tf= G.ttfdata.first;
+  while(tf)
+  {
+  	freePackedFile(tf->pf);
+  	tf->pf= NULL;
+  	tf->vfont= NULL;
+  	tf= tf->next;
+  }
+  BLI_freelistN(&G.ttfdata);
+
 	freeAllRad();
 	BKE_freecubetable();
 
