diff options
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 |