diff options
Diffstat (limited to 'src/FbTk/FbString.cc')
-rw-r--r-- | src/FbTk/FbString.cc | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/FbTk/FbString.cc b/src/FbTk/FbString.cc new file mode 100644 index 0000000..a88b237 --- /dev/null +++ b/src/FbTk/FbString.cc | |||
@@ -0,0 +1,207 @@ | |||
1 | // FbString.cc for fluxbox | ||
2 | // Copyright (c) 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) | ||
3 | // Copyright (c) 2006 Simon Bowden (rathnor at fluxbox dot org) | ||
4 | // | ||
5 | // Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | // copy of this software and associated documentation files (the "Software"), | ||
7 | // to deal in the Software without restriction, including without limitation | ||
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | // and/or sell copies of the Software, and to permit persons to whom the | ||
10 | // Software is furnished to do so, subject to the following conditions: | ||
11 | // | ||
12 | // The above copyright notice and this permission notice shall be included in | ||
13 | // all copies or substantial portions of the Software. | ||
14 | // | ||
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | // DEALINGS IN THE SOFTWARE. | ||
22 | |||
23 | // $Id$ | ||
24 | |||
25 | #ifdef HAVE_CERRNO | ||
26 | #include <cerrno> | ||
27 | #else | ||
28 | #include <errno.h> | ||
29 | #endif | ||
30 | |||
31 | #include "FbString.hh" | ||
32 | #include "config.h" | ||
33 | |||
34 | #ifdef HAVE_ICONV | ||
35 | #include <iconv.h> | ||
36 | #endif // HAVE_ICONV | ||
37 | #include <langinfo.h> | ||
38 | #include <locale.h> | ||
39 | |||
40 | #include <iostream> | ||
41 | using namespace std; | ||
42 | |||
43 | namespace FbTk { | ||
44 | |||
45 | namespace FbStringUtil { | ||
46 | |||
47 | enum ConvType { FB2X = 0, X2FB, LOCALE2FB, FB2LOCALE, CONVSIZE }; | ||
48 | |||
49 | #ifdef HAVE_ICONV | ||
50 | static iconv_t *iconv_convs = 0; | ||
51 | #else | ||
52 | static int iconv_convs[CONVSIZE]; | ||
53 | #endif // HAVE_ICONV | ||
54 | |||
55 | /// Initialise all of the iconv conversion descriptors | ||
56 | void init() { | ||
57 | iconv_convs = new iconv_t[CONVSIZE]; | ||
58 | |||
59 | setlocale(LC_CTYPE, ""); | ||
60 | |||
61 | #ifdef HAVE_ICONV | ||
62 | #ifdef CODESET | ||
63 | std::string locale_codeset = nl_langinfo(CODESET); | ||
64 | #else // openbsd doesnt have this (yet?) | ||
65 | std::string locale_codeset = ""; | ||
66 | std::string locale = setlocale(LC_CTYPE, NULL); | ||
67 | size_t pos = locale.find('.'); | ||
68 | if (pos != std::string::npos) | ||
69 | locale_codeset = locale.substr(pos); | ||
70 | #endif // CODESET | ||
71 | |||
72 | #ifdef DEBUG | ||
73 | cerr<<"FbTk::FbString: setup converts for local codeset = "<<locale_codeset<<endl; | ||
74 | #endif // DEBUG | ||
75 | |||
76 | iconv_convs[FB2X] = iconv_open("ISO8859-1", "UTF-8"); | ||
77 | iconv_convs[X2FB] = iconv_open("UTF-8", "ISO8859-1"); | ||
78 | iconv_convs[FB2LOCALE] = iconv_open(locale_codeset.c_str(), "UTF-8"); | ||
79 | iconv_convs[LOCALE2FB] = iconv_open("UTF-8", locale_codeset.c_str()); | ||
80 | #else | ||
81 | for (int i=0; i < CONVSIZE; ++i) | ||
82 | iconv_convs[i] = 0; | ||
83 | #endif // HAVE_ICONV | ||
84 | |||
85 | } | ||
86 | |||
87 | void shutdown() { | ||
88 | #ifdef HAVE_ICONV | ||
89 | for (int i=0; i < CONVSIZE; ++i) | ||
90 | if (iconv_convs[i] != (iconv_t)(-1)) | ||
91 | iconv_close(iconv_convs[i]); | ||
92 | #endif // HAVE_ICONV | ||
93 | |||
94 | delete[] iconv_convs; | ||
95 | |||
96 | } | ||
97 | |||
98 | |||
99 | |||
100 | |||
101 | #ifdef HAVE_ICONV | ||
102 | /** | ||
103 | Recodes the text from one encoding to another | ||
104 | assuming cd is correct | ||
105 | @param cd the iconv type | ||
106 | @param msg text to be converted, **NOT** necessarily NULL terminated | ||
107 | @param size number of BYTES to convert | ||
108 | @return the recoded string, or 0 on failure | ||
109 | */ | ||
110 | std::string recode(iconv_t cd, | ||
111 | const std::string &in) { | ||
112 | |||
113 | // If empty message, yes this can happen, return | ||
114 | if (in.empty()) | ||
115 | return ""; | ||
116 | |||
117 | size_t insize = in.size(); | ||
118 | size_t outsize = insize; | ||
119 | char * out = (char *) malloc(outsize * sizeof(char)); // need realloc | ||
120 | char * outptr = out; | ||
121 | |||
122 | size_t inbytesleft = insize; | ||
123 | size_t outbytesleft = outsize; | ||
124 | |||
125 | char * in_ptr = const_cast<char *>(in.data()); | ||
126 | size_t result = (size_t)(-1); | ||
127 | bool again = true; | ||
128 | |||
129 | while (again) { | ||
130 | again = false; | ||
131 | result = iconv(cd, &in_ptr, &inbytesleft, &outptr, &outbytesleft); | ||
132 | if (result == (size_t)(-1)) { | ||
133 | switch(errno) { | ||
134 | case EILSEQ: | ||
135 | // Try skipping a byte | ||
136 | in_ptr++; | ||
137 | inbytesleft--; | ||
138 | again = true; | ||
139 | case EINVAL: | ||
140 | break; | ||
141 | case E2BIG: | ||
142 | // need more space! | ||
143 | outsize += insize; | ||
144 | out = (char *) realloc(out, outsize*sizeof(char)); | ||
145 | if (out != NULL) | ||
146 | again = true; | ||
147 | outbytesleft += insize; | ||
148 | outptr = out + outsize - outbytesleft; | ||
149 | break; | ||
150 | default: | ||
151 | // something else broke | ||
152 | perror("iconv"); | ||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | // copy to our return string | ||
159 | std::string ret; | ||
160 | ret.append(out, outsize - outbytesleft); | ||
161 | |||
162 | // reset the conversion descriptor | ||
163 | iconv(cd, NULL, NULL, NULL, NULL); | ||
164 | |||
165 | if (out) | ||
166 | free(out); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | #else | ||
171 | std::string recode(int cd, | ||
172 | const std::string &str) { | ||
173 | return str; | ||
174 | } | ||
175 | #endif // HAVE_ICONV | ||
176 | |||
177 | FbString XStrToFb(const std::string &src) { | ||
178 | return recode(iconv_convs[X2FB], src); | ||
179 | } | ||
180 | |||
181 | std::string FbStrToX(const FbString &src) { | ||
182 | return recode(iconv_convs[FB2X], src); | ||
183 | } | ||
184 | |||
185 | |||
186 | /// Handle thislocale string encodings (strings coming from userspace) | ||
187 | FbString LocaleStrToFb(const std::string &src) { | ||
188 | return recode(iconv_convs[LOCALE2FB], src); | ||
189 | } | ||
190 | |||
191 | std::string FbStrToLocale(const FbString &src) { | ||
192 | return recode(iconv_convs[FB2LOCALE], src); | ||
193 | } | ||
194 | |||
195 | bool haveUTF8() { | ||
196 | #ifdef HAVE_ICONV | ||
197 | if (iconv_convs[LOCALE2FB] != ((iconv_t)(-1))) | ||
198 | return true; | ||
199 | #endif // HAVE_ICONV | ||
200 | |||
201 | return false; | ||
202 | } | ||
203 | |||
204 | |||
205 | }; // end namespace StringUtil | ||
206 | |||
207 | }; // end namespace FbTk | ||