aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Font.cc
diff options
context:
space:
mode:
authorsimonb <simonb>2006-05-07 03:41:27 (GMT)
committersimonb <simonb>2006-05-07 03:41:27 (GMT)
commit520f552be79581be50156bb7785e7ef0ce946b07 (patch)
tree82edcbb794f6b89804a2a7f75e0122afcc074f94 /src/FbTk/Font.cc
parent0e9fa988ff41cc32a390f70443669a6df45f3e44 (diff)
downloadfluxbox-520f552be79581be50156bb7785e7ef0ce946b07.zip
fluxbox-520f552be79581be50156bb7785e7ef0ce946b07.tar.bz2
handle utf-8 strings properly.
use utf8 internally
Diffstat (limited to 'src/FbTk/Font.cc')
-rw-r--r--src/FbTk/Font.cc153
1 files changed, 12 insertions, 141 deletions
diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc
index 8d8fbec..42e33c1 100644
--- a/src/FbTk/Font.cc
+++ b/src/FbTk/Font.cc
@@ -71,6 +71,7 @@
71#include <typeinfo> 71#include <typeinfo>
72#include <langinfo.h> 72#include <langinfo.h>
73 73
74#include <errno.h>
74 75
75#ifdef HAVE_CSTDLIB 76#ifdef HAVE_CSTDLIB
76 #include <cstdlib> 77 #include <cstdlib>
@@ -87,68 +88,6 @@ namespace {
87#include <locale.h> 88#include <locale.h>
88#endif //HAVE_SETLOCALE 89#endif //HAVE_SETLOCALE
89 90
90#ifdef HAVE_ICONV
91/**
92 Recodes the text from one encoding to another
93 assuming cd is correct
94 @param cd the iconv type
95 @param msg text to be converted
96 @param size number of chars to convert
97 @return the recoded string, or 0 on failure
98*/
99char* recode(iconv_t cd,
100 const char *msg, size_t size) {
101
102 // If empty message, yes this can happen, return
103 if(strlen(msg) == 0 || size == 0)
104 return 0;
105
106 if(strlen(msg) < size)
107 size = strlen(msg);
108
109 size_t inbytesleft = size;
110 size_t outbytesleft = 4*inbytesleft;
111 char *new_msg = new char[outbytesleft];
112 char *new_msg_ptr = new_msg;
113 char *msg_ptr = strdup(msg);
114 char *orig_msg_ptr = msg_ptr; // msg_ptr modified in iconv call
115 size_t result = (size_t)(-1);
116
117#ifdef HAVE_CONST_ICONV
118 result = iconv(cd, (const char**)(&msg_ptr), &inbytesleft, &new_msg, &outbytesleft);
119#else
120 result = iconv(cd, &msg_ptr, &inbytesleft, &new_msg, &outbytesleft);
121#endif // HAVE_CONST_ICONV
122
123 if (result == (size_t)(-1)) {
124 // iconv can fail for three reasons
125 // 1) Invalid multibyte sequence is encountered in the input
126 // 2) An incomplete multibyte sequence
127 // 3) The output buffer has no more room for the next converted character.
128 // So we the delete new message and return original message
129 delete[] new_msg_ptr;
130 free(orig_msg_ptr);
131 return 0;
132 }
133 free(orig_msg_ptr);
134
135 *new_msg = '\0';
136
137 if(inbytesleft != 0) {
138 delete[] new_msg_ptr;
139 return 0;
140 }
141
142 return new_msg_ptr;
143}
144#else
145
146char *recode(int cd,
147 const char *msg, size_t size) {
148 return 0;
149}
150#endif // HAVE_ICONV
151
152// use to map <font1>|<font2>|<font3> => <fontthatworks> 91// use to map <font1>|<font2>|<font3> => <fontthatworks>
153typedef std::map<std::string, std::string> StringMap; 92typedef std::map<std::string, std::string> StringMap;
154typedef StringMap::iterator StringMapIt; 93typedef StringMap::iterator StringMapIt;
@@ -179,11 +118,6 @@ bool Font::s_multibyte = false;
179bool Font::s_utf8mode = false; 118bool Font::s_utf8mode = false;
180 119
181 120
182void Font::init() {
183 // must be set before the first XFontSet is created
184 setlocale(LC_CTYPE, "");
185}
186
187void Font::shutdown() { 121void Font::shutdown() {
188 122
189 FontCacheIt fit; 123 FontCacheIt fit;
@@ -203,12 +137,7 @@ Font::Font(const char *name):
203 m_fontimp(0), 137 m_fontimp(0),
204 m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())), 138 m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())),
205 m_shadow_offx(2), m_shadow_offy(2), 139 m_shadow_offx(2), m_shadow_offy(2),
206 m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display())), 140 m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display()))
207#ifdef HAVE_ICONV
208 m_iconv((iconv_t)(-1))
209#else
210 m_iconv(-1)
211#endif // HAVE_ICONV
212{ 141{
213 // MB_CUR_MAX returns the size of a char in the current locale 142 // MB_CUR_MAX returns the size of a char in the current locale
214 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte 143 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
@@ -224,35 +153,9 @@ Font::Font(const char *name):
224 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) { 153 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) {
225 s_utf8mode = true; 154 s_utf8mode = true;
226 } else if (locale_codeset != 0) { 155 } else if (locale_codeset != 0) {
227 // if locale isn't UTF-8 we try to 156 s_utf8mode = FbStringUtil::haveUTF8();
228 // create a iconv pointer so we can
229 // convert non utf-8 strings to utf-8
230
231#ifdef DEBUG
232 cerr<<"FbTk::Font: check UTF-8 convert for codeset = "<<locale_codeset<<endl;
233#endif // DEBUG
234
235#ifdef HAVE_ICONV
236 m_iconv = iconv_open("UTF-8", locale_codeset);
237 if(m_iconv == (iconv_t)(-1)) {
238 cerr<<"FbTk::Font: code error: from "<<locale_codeset<<" to: UTF-8"<<endl;
239 // if we failed with iconv then we can't convert
240 // the strings to utf-8, so we disable utf8 mode
241 s_utf8mode = false;
242 } else {
243 // success, we can now enable utf8mode
244 // and if antialias is on later we can recode
245 // the non utf-8 string to utf-8 and use utf-8
246 // drawing functions
247 s_utf8mode = true;
248 }
249#endif // HAVE_ICONV
250 } 157 }
251 158
252#ifdef DEBUG
253 cerr<<"FbTk::Font m_iconv = "<<m_iconv<<endl;
254#endif // DEBUG
255
256 if (name != 0) { 159 if (name != 0) {
257 load(name); 160 load(name);
258 } 161 }
@@ -260,10 +163,6 @@ Font::Font(const char *name):
260} 163}
261 164
262Font::~Font() { 165Font::~Font() {
263#ifdef HAVE_ICONV
264 if (m_iconv != (iconv_t)(-1))
265 iconv_close(m_iconv);
266#endif // HAVE_ICONV
267} 166}
268 167
269bool Font::load(const std::string &name) { 168bool Font::load(const std::string &name) {
@@ -333,18 +232,7 @@ bool Font::load(const std::string &name) {
333 return false; 232 return false;
334} 233}
335 234
336unsigned int Font::textWidth(const char * const text, unsigned int size) const { 235unsigned int Font::textWidth(const FbString &text, unsigned int size) const {
337#ifdef HAVE_ICONV
338 if (m_fontimp->utf8() && m_iconv != (iconv_t)(-1)) {
339 char* rtext = recode(m_iconv, text, size);
340 if (rtext != 0)
341 size = strlen(rtext);
342 unsigned int r = m_fontimp->textWidth(rtext ? rtext : text, size);
343 if (rtext != 0)
344 delete[] rtext;
345 return r;
346 }
347#endif // HAVE_ICONV
348 return m_fontimp->textWidth(text, size); 236 return m_fontimp->textWidth(text, size);
349} 237}
350 238
@@ -365,53 +253,36 @@ bool Font::validOrientation(FbTk::Orientation orient) {
365} 253}
366 254
367void Font::drawText(const FbDrawable &w, int screen, GC gc, 255void Font::drawText(const FbDrawable &w, int screen, GC gc,
368 const char *text, size_t len, int x, int y, 256 const FbString &text, size_t len, int x, int y,
369 Orientation orient) const { 257 Orientation orient) const {
370 if (text == 0 || len == 0) 258 if (text.empty() || len == 0)
371 return; 259 return;
372 260
373 char* rtext = 0;
374
375 // so we don't end up in a loop with m_shadow 261 // so we don't end up in a loop with m_shadow
376 static bool first_run = true; 262 static bool first_run = true;
377 263
378#ifdef HAVE_ICONV
379 if (m_fontimp->utf8() && m_iconv != (iconv_t)(-1) && first_run) {
380 rtext = recode(m_iconv, text, len);
381 if (rtext != 0) {
382 len = strlen(rtext);
383 // ok, we can't use utf8 mode since the string is invalid
384 }
385 }
386#endif // HAVE_ICONV
387
388 const char *real_text = rtext ? rtext : text;
389
390 // draw "effects" first 264 // draw "effects" first
391 if (first_run) { 265 if (first_run) {
392 if (m_shadow) { 266 if (m_shadow) {
393 FbTk::GContext shadow_gc(w); 267 FbTk::GContext shadow_gc(w);
394 shadow_gc.setForeground(m_shadow_color); 268 shadow_gc.setForeground(m_shadow_color);
395 first_run = false; 269 first_run = false;
396 drawText(w, screen, shadow_gc.gc(), real_text, len, 270 drawText(w, screen, shadow_gc.gc(), text, len,
397 x + m_shadow_offx, y + m_shadow_offy, orient); 271 x + m_shadow_offx, y + m_shadow_offy, orient);
398 first_run = true; 272 first_run = true;
399 } else if (m_halo) { 273 } else if (m_halo) {
400 FbTk::GContext halo_gc(w); 274 FbTk::GContext halo_gc(w);
401 halo_gc.setForeground(m_halo_color); 275 halo_gc.setForeground(m_halo_color);
402 first_run = false; 276 first_run = false;
403 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, orient); 277 drawText(w, screen, halo_gc.gc(), text, len, x + 1, y + 1, orient);
404 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, orient); 278 drawText(w, screen, halo_gc.gc(), text, len, x - 1, y + 1, orient);
405 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y - 1, orient); 279 drawText(w, screen, halo_gc.gc(), text, len, x - 1, y - 1, orient);
406 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y - 1, orient); 280 drawText(w, screen, halo_gc.gc(), text, len, x + 1, y - 1, orient);
407 first_run = true; 281 first_run = true;
408 } 282 }
409 } 283 }
410 284
411 m_fontimp->drawText(w, screen, gc, real_text, len, x, y, orient); 285 m_fontimp->drawText(w, screen, gc, text, len, x, y, orient);
412
413 if (rtext != 0)
414 delete[] rtext;
415 286
416} 287}
417 288