Port of part of the Interface code to 2.50.
[blender.git] / source / blender / editors / interface / text.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is written by Rob Haarsma (phase)
21  *
22  * Contributor(s): none yet.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /* XXX 2.50 this file must be cleanup still, using globals etc. */
28
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_listBase.h"
35 #include "DNA_userdef_types.h"
36 #include "DNA_vec_types.h"
37
38 #include "BKE_global.h"         /* G */
39 #include "BKE_utildefines.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_linklist.h"       /* linknode */
43
44 #include "BIF_gl.h"
45 #include "UI_text.h"
46
47 #include "ED_datafiles.h"
48
49 #include "BMF_Api.h"
50
51 #ifdef WITH_ICONV
52 #include "iconv.h"
53
54 void string_to_utf8(char *original, char *utf_8, char *code)
55 {
56         size_t inbytesleft=strlen(original);
57         size_t outbytesleft=512;
58         size_t rv=0;
59         iconv_t cd;
60         
61         cd=iconv_open("UTF-8", code);
62
63         if (cd == (iconv_t)(-1)) {
64                 printf("iconv_open Error");
65                 *utf_8='\0';
66                 return ;
67         }
68         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
69         if (rv == (size_t) -1) {
70                 printf("iconv Error\n");
71                 return ;
72         }
73         *utf_8 = '\0';
74         iconv_close(cd);
75 }
76 #endif // WITH_ICONV
77
78 #ifdef INTERNATIONAL
79 #include "FTF_Api.h"
80
81 static struct LANGMenuEntry *langmenu= 0;
82 static int tot_lang = 0;
83
84 #endif // INTERNATIONAL
85
86 void UI_RasterPos(float x, float y)
87 {
88 #ifdef INTERNATIONAL
89         FTF_SetPosition(x, y);
90 #endif // INTERNATIONAL
91 }
92
93 void UI_SetScale(float aspect)
94 {
95 #ifdef INTERNATIONAL
96         FTF_SetScale(aspect);
97 #endif // INTERNATIONAL
98 }
99
100 void ui_text_init_userdef(void)
101 {
102 #ifdef INTERNATIONAL
103         if(U.transopts & USER_DOTRANSLATE)
104                 start_interface_font();
105         else
106                 G.ui_international= FALSE;
107 #else // INTERNATIONAL
108         G.ui_international= FALSE;
109 #endif
110 }
111
112 int UI_DrawString(BMF_Font* font, char *str, int translate)
113 {
114 #ifdef INTERNATIONAL
115         if(G.ui_international == TRUE) {
116                 if(translate)
117                 {
118 #ifdef WITH_ICONV
119                         if(translate & CONVERT_TO_UTF8) {
120                                 char utf_8[512];
121
122                                 struct LANGMenuEntry *lme;
123                                 lme = find_language(U.language);
124
125                                 if (lme !=NULL) {
126                                         if (!strcmp(lme->code, "ja_JP"))
127                                                 string_to_utf8(str, utf_8, "Shift_JIS");        /* Japanese */
128                                         else if (!strcmp(lme->code, "zh_CN"))
129                                                 string_to_utf8(str, utf_8, "GB2312");           /* Chinese */
130                                 }
131         
132                                 return FTF_DrawString(utf_8, FTF_INPUT_UTF8);
133                         }
134                         else
135 #endif // WITH_ICONV
136                                 return FTF_DrawString(str, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
137                 }
138                 else
139                         return FTF_DrawString(str, FTF_NO_TRANSCONV | FTF_INPUT_UTF8);
140         } else {
141                 return BMF_DrawString(font, str);
142         }
143 #else // INTERNATIONAL
144         return BMF_DrawString(font, str);
145 #endif
146 }
147
148 float UI_GetStringWidth(BMF_Font* font, char *str, int translate)
149 {
150         float rt;
151
152 #ifdef INTERNATIONAL
153         if(G.ui_international == TRUE)
154                 if(translate && (U.transopts & USER_TR_BUTTONS))
155                         rt= FTF_GetStringWidth(str, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
156                 else
157                         rt= FTF_GetStringWidth(str, FTF_NO_TRANSCONV | FTF_INPUT_UTF8);
158         else
159                 rt= BMF_GetStringWidth(font, str);
160 #else
161         rt= BMF_GetStringWidth(font, str);
162 #endif
163
164         return rt;
165 }
166
167 void UI_GetBoundingBox(struct BMF_Font* font, char* str, int translate, rctf *bbox)
168 {
169 #ifdef INTERNATIONAL
170         float dummy;
171         if(G.ui_international == TRUE)
172                 if(translate && (U.transopts & USER_TR_BUTTONS))
173                         FTF_GetBoundingBox(str, &bbox->xmin, &bbox->ymin, &dummy, &bbox->xmax, &bbox->ymax, &dummy, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
174                 else
175                         FTF_GetBoundingBox(str, &bbox->xmin, &bbox->ymin, &dummy, &bbox->xmax, &bbox->ymax, &dummy, FTF_NO_TRANSCONV | FTF_INPUT_UTF8);
176         else
177                 BMF_GetStringBoundingBox(font, str, &bbox->xmin, &bbox->ymin, &bbox->xmax, &bbox->ymax);
178 #else
179         BMF_GetStringBoundingBox(font, str, &bbox->xmin, &bbox->ymin, &bbox->xmax, &bbox->ymax);
180 #endif
181 }
182
183 #ifdef INTERNATIONAL
184
185 char *fontsize_pup(void)
186 {
187         static char string[1024];
188         char formatstring[1024];
189
190         strcpy(formatstring, "Choose Font Size: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d");
191
192         sprintf(string, formatstring,
193                         "Font Size:   8",               8,
194                         "Font Size:   9",               9,
195                         "Font Size:  10",               10,
196                         "Font Size:  11",               11,
197                         "Font Size:  12",               12,
198                         "Font Size:  13",               13,
199                         "Font Size:  14",               14,
200                         "Font Size:  15",               15,
201                         "Font Size:  16",               16
202                );
203
204         return (string);
205 }
206
207
208 char *language_pup(void)
209 {
210         struct LANGMenuEntry *lme = langmenu;
211         static char string[1024];
212         static char tmp[1024];
213
214         if(tot_lang == 0)
215                 sprintf(string, "Choose Language: %%t|Language:  English %%x0");
216         else {
217                 sprintf(string, "Choose Language: %%t");
218                 while(lme) {
219                         sprintf(tmp, "|Language:  %s %%x%d", lme->language, lme->id);
220                         strcat(string, tmp);
221                         lme= lme->next;
222                 }
223         }
224
225         return string;
226 }
227
228 struct LANGMenuEntry *find_language(short langid)
229 {
230         struct LANGMenuEntry *lme = langmenu;
231
232         while(lme) {
233                 if(lme->id == langid)
234                         return lme;
235
236                 lme=lme->next;
237         }
238         return NULL;
239 }
240
241
242 void lang_setlanguage(void) 
243 {
244         struct LANGMenuEntry *lme;
245
246         lme = find_language(U.language);
247         if(lme) FTF_SetLanguage(lme->code);
248         else FTF_SetLanguage("en_US");
249 }
250
251 /* called from fileselector */
252 void set_interface_font(char *str) 
253 {
254
255         /* this test needed because fileselect callback can happen after disable AA fonts */
256         if(U.transopts & USER_DOTRANSLATE) {
257                 if(FTF_SetFont((unsigned char*)str, 0, U.fontsize)) {
258                         lang_setlanguage();
259                         
260                         if(strlen(str) < FILE_MAXDIR) strcpy(U.fontname, str);
261                         G.ui_international = TRUE;
262                 } 
263                 else {
264                         U.fontname[0]= 0;
265                         FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
266                         G.ui_international = TRUE;      // this case will switch to standard font
267                         /* XXX 2.50 bad call okee("Invalid font selection - reverting to built-in font."); */
268                 }
269                 /* XXX 2.50 bad call allqueue(REDRAWALL, 0); */
270         }
271 }
272
273 void start_interface_font(void) 
274 {
275         int result = 0;
276
277         if(U.transopts & USER_USETEXTUREFONT)
278                 FTF_SetMode(FTF_TEXTUREFONT);
279         else
280                 FTF_SetMode(FTF_PIXMAPFONT);
281         
282         if(U.fontsize && U.fontname[0] ) { // we have saved user settings + fontpath
283                 
284                 // try loading font from U.fontname = full path to font in usersettings
285                 result = FTF_SetFont((unsigned char*)U.fontname, 0, U.fontsize);
286         }
287         else if(U.fontsize) {   // user settings, default
288                 result = FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
289         }
290         
291         if(result==0) {         // use default
292                 U.language= 0;
293                 U.fontsize= 11;
294                 U.encoding= 0;
295                 U.fontname[0]= 0;
296                 result = FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
297         }
298
299         if(result) {
300                 lang_setlanguage();
301
302                 G.ui_international = TRUE;
303         } 
304         else {
305                 printf("no font found for international support\n");
306                 G.ui_international = FALSE;
307                 U.transopts &= ~USER_DOTRANSLATE;
308                 U.fontsize = 0;
309         }
310
311         /* XXX 2.50 bad call allqueue(REDRAWALL, 0); */
312 }
313
314 static char *first_dpointchar(char *string) 
315 {
316         char *dpointchar;
317         
318         dpointchar= strchr(string, ':');        
319
320         return dpointchar;
321 }
322
323
324 static void splitlangline(char *line, struct LANGMenuEntry *lme)
325 {
326         char *dpointchar= first_dpointchar(line);
327
328         if (dpointchar) {
329                 lme->code= BLI_strdup(dpointchar+1);
330                 *(dpointchar)=0;
331                 lme->language= BLI_strdup(line);
332         } else {
333                 /* XXX 2.50 bad call error("Invalid language file"); */
334         }
335 }
336
337
338 static void puplang_insert_entry(char *line)
339 {
340         struct LANGMenuEntry *lme, *prev;
341         int sorted = 0;
342
343         prev= NULL;
344         lme= langmenu;
345
346         for (; lme; prev= lme, lme= lme->next) {
347                 if (lme->line) {
348                         if (BLI_streq(line, lme->line)) {
349                                 return;
350                         } else if (sorted && strcmp(line, lme->line)<0) {
351                                 break;
352                         }
353                 }
354         }
355         
356         lme= MEM_mallocN(sizeof(*lme), "lme");
357         lme->line = BLI_strdup(line);
358         splitlangline(line, lme);
359         lme->id = tot_lang;
360         tot_lang++;
361
362         if (prev) {
363                 lme->next= prev->next;
364                 prev->next= lme;
365         } else {
366                 lme->next= langmenu;
367                 langmenu= lme;
368         }
369 }
370
371
372 int read_languagefile(void) 
373 {
374         char name[FILE_MAXDIR+FILE_MAXFILE];
375         LinkNode *l, *lines;
376         
377         /* .Blanguages, http://www.blender3d.org/cms/Installation_Policy.352.0.html*/
378 #if defined (__APPLE__) || (WIN32)
379         BLI_make_file_string("/", name, BLI_gethome(), ".Blanguages");
380 #else
381         BLI_make_file_string("/", name, BLI_gethome(), ".blender/.Blanguages");
382 #endif
383
384         lines= BLI_read_file_as_lines(name);
385
386         if(lines == NULL) {
387                 /* If not found in home, try current dir 
388                  * (Resources folder of app bundle on OS X) */
389 #if defined (__APPLE__)
390                 char *bundlePath = BLI_getbundle();
391                 strcpy(name, bundlePath);
392                 strcat(name, "/Contents/Resources/.Blanguages");
393 #else
394                 /* Check the CWD. Takes care of the case where users
395                  * unpack blender tarball; cd blender-dir; ./blender */
396                 strcpy(name, ".blender/.Blanguages");
397 #endif
398                 lines= BLI_read_file_as_lines(name);
399
400                 if(lines == NULL) {
401                         /* If not found in .blender, try current dir */
402                         strcpy(name, ".Blanguages");
403                         lines= BLI_read_file_as_lines(name);
404                         if(lines == NULL) {
405                                 if(G.f & G_DEBUG) printf("File .Blanguages not found\n");
406                                 return 0;
407                         }
408                 }
409         }
410
411         for (l= lines; l; l= l->next) {
412                 char *line= l->link;
413                         
414                 if (!BLI_streq(line, "")) {
415                         puplang_insert_entry(line);
416                 }
417         }
418
419         BLI_free_file_lines(lines);
420
421         return 1;
422 }
423
424
425 void free_languagemenu(void)
426 {
427         struct LANGMenuEntry *lme= langmenu;
428
429         while (lme) {
430                 struct LANGMenuEntry *n= lme->next;
431
432                 if (lme->line) MEM_freeN(lme->line);
433                 if (lme->language) MEM_freeN(lme->language);
434                 if (lme->code) MEM_freeN(lme->code);
435                 MEM_freeN(lme);
436
437                 lme= n;
438         }
439 }
440
441 #endif /* INTERNATIONAL */
442