diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2010-09-08 18:17:21 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2010-09-08 18:17:21 (GMT) |
commit | 690d926ac444243611cd875fb84fabb4e6db2cf2 (patch) | |
tree | c8ef84056b295071f9a9207ffea5393c6cf4ad4d /src/FbTk/FbString.cc | |
parent | 1e8fe2bc14856fa16508686a28a85e72cb0e422c (diff) | |
download | fluxbox-690d926ac444243611cd875fb84fabb4e6db2cf2.zip fluxbox-690d926ac444243611cd875fb84fabb4e6db2cf2.tar.bz2 |
introduced FbTk::BidiString
a 'BidiString' holds both the logical content and the visual reordered
version of the content of a string. this helps to reduce the number of
calls to reorder the string before drawing it (as introduced in the patch
from Ken Bloom) and to be more consistent in menus and textboxes (drawing
cursors and underlining text).
Diffstat (limited to 'src/FbTk/FbString.cc')
-rw-r--r-- | src/FbTk/FbString.cc | 150 |
1 files changed, 96 insertions, 54 deletions
diff --git a/src/FbTk/FbString.cc b/src/FbTk/FbString.cc index 2190a76..79b773a 100644 --- a/src/FbTk/FbString.cc +++ b/src/FbTk/FbString.cc | |||
@@ -62,8 +62,86 @@ using std::cerr; | |||
62 | using std::endl; | 62 | using std::endl; |
63 | #endif // DEBUG | 63 | #endif // DEBUG |
64 | 64 | ||
65 | namespace { | ||
66 | |||
67 | #ifdef HAVE_FRIBIDI | ||
68 | FbTk::FbString makeVisualFromLogical(const FbTk::FbString& src) { | ||
69 | |||
70 | FriBidiCharType base = FRIBIDI_TYPE_N; | ||
71 | |||
72 | // reuse allocated memory for reencoding / reordering | ||
73 | static std::vector<FriBidiChar> us; | ||
74 | static std::vector<FriBidiChar> out_us; | ||
75 | static FbTk::FbString result; | ||
76 | |||
77 | const size_t S = src.size() + 1; | ||
78 | const size_t S4 = S * 4; | ||
79 | |||
80 | if (us.capacity() < S) | ||
81 | us.reserve(S); | ||
82 | if (out_us.capacity() < S) | ||
83 | out_us.reserve(S); | ||
84 | if (result.capacity() < S4) | ||
85 | result.reserve(S4); | ||
86 | |||
87 | us.resize(S); | ||
88 | FriBidiStrIndex len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, | ||
89 | const_cast<char*>(src.c_str()), S - 1, | ||
90 | &us[0]); | ||
91 | |||
92 | out_us.resize(S); | ||
93 | fribidi_log2vis(&us[0], len, &base, &out_us[0], NULL, NULL, NULL); | ||
94 | |||
95 | result.resize(S4); | ||
96 | len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, &out_us[0], len, &result[0]); | ||
97 | result.resize(len); // trim to currently used chars | ||
98 | |||
99 | return result; | ||
100 | } | ||
101 | |||
102 | #endif | ||
103 | |||
104 | } // end of anonymous namespace | ||
105 | |||
106 | |||
65 | namespace FbTk { | 107 | namespace FbTk { |
66 | 108 | ||
109 | |||
110 | BiDiString::BiDiString(const FbString& logical) | ||
111 | #ifdef HAVE_FRIBIDI | ||
112 | : m_visual_dirty(false) | ||
113 | #endif | ||
114 | { | ||
115 | if (!logical.empty()) | ||
116 | setLogical(logical); | ||
117 | } | ||
118 | |||
119 | const FbString& BiDiString::setLogical(const FbString& logical) { | ||
120 | m_logical = logical; | ||
121 | #if HAVE_FRIBIDI | ||
122 | if (m_logical.empty()) { | ||
123 | m_visual_dirty = false; | ||
124 | m_visual.clear(); | ||
125 | } else { | ||
126 | m_visual_dirty = true; | ||
127 | } | ||
128 | #endif | ||
129 | } | ||
130 | |||
131 | const FbString& BiDiString::visual() const { | ||
132 | #if HAVE_FRIBIDI | ||
133 | if (m_visual_dirty) { | ||
134 | m_visual = ::makeVisualFromLogical(logical()); | ||
135 | } | ||
136 | m_visual_dirty = false; | ||
137 | return m_visual; | ||
138 | #else | ||
139 | return m_logical; | ||
140 | #endif | ||
141 | } | ||
142 | |||
143 | |||
144 | |||
67 | namespace FbStringUtil { | 145 | namespace FbStringUtil { |
68 | 146 | ||
69 | enum ConvType { FB2X = 0, X2FB, LOCALE2FB, FB2LOCALE, CONVSIZE }; | 147 | enum ConvType { FB2X = 0, X2FB, LOCALE2FB, FB2LOCALE, CONVSIZE }; |
@@ -128,7 +206,6 @@ void shutdown() { | |||
128 | 206 | ||
129 | 207 | ||
130 | 208 | ||
131 | #ifdef HAVE_ICONV | ||
132 | /** | 209 | /** |
133 | Recodes the text from one encoding to another | 210 | Recodes the text from one encoding to another |
134 | assuming cd is correct | 211 | assuming cd is correct |
@@ -137,7 +214,9 @@ void shutdown() { | |||
137 | @param size number of BYTES to convert | 214 | @param size number of BYTES to convert |
138 | @return the recoded string, or 0 on failure | 215 | @return the recoded string, or 0 on failure |
139 | */ | 216 | */ |
217 | string recode(iconv_t cd, const string &in) { | ||
140 | 218 | ||
219 | #ifdef HAVE_ICONV | ||
141 | /** | 220 | /** |
142 | --NOTE-- | 221 | --NOTE-- |
143 | In the "C" locale, this will strip any high-bit characters | 222 | In the "C" locale, this will strip any high-bit characters |
@@ -145,8 +224,6 @@ void shutdown() { | |||
145 | then you need to set your locale to something UTF-8, OR something | 224 | then you need to set your locale to something UTF-8, OR something |
146 | ISO8859-1. | 225 | ISO8859-1. |
147 | */ | 226 | */ |
148 | string recode(iconv_t cd, | ||
149 | const string &in) { | ||
150 | 227 | ||
151 | // If empty message, yes this can happen, return | 228 | // If empty message, yes this can happen, return |
152 | if (in.empty()) | 229 | if (in.empty()) |
@@ -163,18 +240,18 @@ string recode(iconv_t cd, | |||
163 | size_t inbytesleft = insize; | 240 | size_t inbytesleft = insize; |
164 | size_t outbytesleft = outsize; | 241 | size_t outbytesleft = outsize; |
165 | 242 | ||
243 | #ifdef HAVE_CONST_ICONV | ||
244 | const char* in_ptr = in.data(); | ||
245 | #else | ||
166 | char * in_ptr = const_cast<char *>(in.data()); | 246 | char * in_ptr = const_cast<char *>(in.data()); |
247 | #endif | ||
167 | size_t result = (size_t)(-1); | 248 | size_t result = (size_t)(-1); |
168 | bool again = true; | 249 | bool again = true; |
169 | 250 | ||
170 | while (again) { | 251 | while (again) { |
171 | again = false; | 252 | again = false; |
172 | 253 | ||
173 | #ifdef HAVE_CONST_ICONV | ||
174 | result = iconv(cd, (const char**)(&in_ptr), &inbytesleft, &out_ptr, &outbytesleft); | ||
175 | #else | ||
176 | result = iconv(cd, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft); | 254 | result = iconv(cd, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft); |
177 | #endif // HAVE_CONST_ICONV | ||
178 | 255 | ||
179 | if (result == (size_t)(-1)) { | 256 | if (result == (size_t)(-1)) { |
180 | switch(errno) { | 257 | switch(errno) { |
@@ -213,13 +290,10 @@ string recode(iconv_t cd, | |||
213 | free(out); | 290 | free(out); |
214 | 291 | ||
215 | return ret; | 292 | return ret; |
216 | } | ||
217 | #else | 293 | #else |
218 | string recode(int cd, | ||
219 | const string &str) { | ||
220 | return str; | 294 | return str; |
221 | } | ||
222 | #endif // HAVE_ICONV | 295 | #endif // HAVE_ICONV |
296 | } | ||
223 | 297 | ||
224 | FbString XStrToFb(const string &src) { | 298 | FbString XStrToFb(const string &src) { |
225 | return recode(iconv_convs[X2FB], src); | 299 | return recode(iconv_convs[X2FB], src); |
@@ -249,59 +323,19 @@ bool haveUTF8() { | |||
249 | } | 323 | } |
250 | 324 | ||
251 | 325 | ||
252 | #ifdef HAVE_FRIBIDI | ||
253 | |||
254 | FbString BidiLog2Vis (const FbString& src) { | ||
255 | |||
256 | FriBidiCharType base = FRIBIDI_TYPE_N; | ||
257 | |||
258 | // reuse allocated memory for reencoding / reordering | ||
259 | static std::vector<FriBidiChar> us; | ||
260 | static std::vector<FriBidiChar> out_us; | ||
261 | static FbString result; | ||
262 | |||
263 | const size_t S = src.size() + 1; | ||
264 | const size_t S4 = S * 4; | ||
265 | |||
266 | if (us.capacity() < S) | ||
267 | us.reserve(S); | ||
268 | if (out_us.capacity() < S) | ||
269 | out_us.reserve(S); | ||
270 | if (result.capacity() < S4) | ||
271 | result.reserve(S4); | ||
272 | |||
273 | us.resize(S); | ||
274 | FriBidiStrIndex len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, | ||
275 | const_cast<char*>(src.c_str()), S - 1, | ||
276 | &us[0]); | ||
277 | |||
278 | out_us.resize(S); | ||
279 | fribidi_log2vis(&us[0], len, &base, &out_us[0], NULL, NULL, NULL); | ||
280 | |||
281 | result.resize(S4); | ||
282 | len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, &out_us[0], len, &result[0]); | ||
283 | result.resize(len); // trim to currently used chars | ||
284 | |||
285 | return result; | ||
286 | } | ||
287 | |||
288 | #endif | ||
289 | |||
290 | } // end namespace StringUtil | 326 | } // end namespace StringUtil |
291 | 327 | ||
292 | StringConvertor::StringConvertor(EncodingTarget target): | ||
293 | #ifdef HAVE_ICONV | 328 | #ifdef HAVE_ICONV |
294 | m_iconv((iconv_t)(-1)) { | 329 | StringConvertor::StringConvertor(EncodingTarget target) : m_iconv((iconv_t)(-1)) { |
295 | if (target == ToLocaleStr) | 330 | if (target == ToLocaleStr) |
296 | m_destencoding = FbStringUtil::locale_codeset; | 331 | m_destencoding = FbStringUtil::locale_codeset; |
297 | else | 332 | else |
298 | m_destencoding = "UTF-8"; | 333 | m_destencoding = "UTF-8"; |
299 | } | 334 | } |
300 | #else | 335 | #else |
301 | m_iconv(-1) {} | 336 | StringConvertor::StringConvertor(EncodingTarget target) { } |
302 | #endif | 337 | #endif |
303 | 338 | ||
304 | |||
305 | StringConvertor::~StringConvertor() { | 339 | StringConvertor::~StringConvertor() { |
306 | #ifdef HAVE_ICONV | 340 | #ifdef HAVE_ICONV |
307 | if (m_iconv != ((iconv_t)-1)) | 341 | if (m_iconv != ((iconv_t)-1)) |
@@ -329,7 +363,7 @@ bool StringConvertor::setSource(const string &encoding) { | |||
329 | #endif | 363 | #endif |
330 | } | 364 | } |
331 | 365 | ||
332 | string StringConvertor::recode(const string &src) { | 366 | FbString StringConvertor::recode(const string &src) { |
333 | #ifdef HAVE_ICONV | 367 | #ifdef HAVE_ICONV |
334 | return FbStringUtil::recode(m_iconv, src); | 368 | return FbStringUtil::recode(m_iconv, src); |
335 | #else | 369 | #else |
@@ -337,5 +371,13 @@ string StringConvertor::recode(const string &src) { | |||
337 | #endif | 371 | #endif |
338 | } | 372 | } |
339 | 373 | ||
374 | void StringConvertor::reset() { | ||
375 | #ifdef HAVE_ICONV | ||
376 | if (m_iconv != ((iconv_t)-1)) | ||
377 | iconv_close(m_iconv); | ||
378 | m_iconv = ((iconv_t)(-1)); | ||
379 | #endif | ||
380 | } | ||
381 | |||
340 | 382 | ||
341 | } // end namespace FbTk | 383 | } // end namespace FbTk |