diff options
author | simonb <simonb> | 2006-05-07 03:41:27 (GMT) |
---|---|---|
committer | simonb <simonb> | 2006-05-07 03:41:27 (GMT) |
commit | 520f552be79581be50156bb7785e7ef0ce946b07 (patch) | |
tree | 82edcbb794f6b89804a2a7f75e0122afcc074f94 /src/FbTk/Font.cc | |
parent | 0e9fa988ff41cc32a390f70443669a6df45f3e44 (diff) | |
download | fluxbox-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.cc | 153 |
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 | */ | ||
99 | char* 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 | |||
146 | char *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> |
153 | typedef std::map<std::string, std::string> StringMap; | 92 | typedef std::map<std::string, std::string> StringMap; |
154 | typedef StringMap::iterator StringMapIt; | 93 | typedef StringMap::iterator StringMapIt; |
@@ -179,11 +118,6 @@ bool Font::s_multibyte = false; | |||
179 | bool Font::s_utf8mode = false; | 118 | bool Font::s_utf8mode = false; |
180 | 119 | ||
181 | 120 | ||
182 | void Font::init() { | ||
183 | // must be set before the first XFontSet is created | ||
184 | setlocale(LC_CTYPE, ""); | ||
185 | } | ||
186 | |||
187 | void Font::shutdown() { | 121 | void 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 | ||
262 | Font::~Font() { | 165 | Font::~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 | ||
269 | bool Font::load(const std::string &name) { | 168 | bool 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 | ||
336 | unsigned int Font::textWidth(const char * const text, unsigned int size) const { | 235 | unsigned 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 | ||
367 | void Font::drawText(const FbDrawable &w, int screen, GC gc, | 255 | void 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 | ||