]> git.saurik.com Git - wxWidgets.git/blob - src/common/strconv.cpp
new and improved wxSTC
[wxWidgets.git] / src / common / strconv.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: strconv.cpp
3 // Purpose: Unicode conversion classes
4 // Author: Ove Kaaven, Robert Roebling, Vadim Zeitlin
5 // Modified by:
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Ove Kaaven, Robert Roebling, Vadim Zeitlin
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "strconv.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifdef __WXMSW__
32 #include "wx/msw/private.h"
33 #endif
34
35 #include <errno.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <stdlib.h>
39
40 #ifdef __SALFORDC__
41 #include <clib.h>
42 #endif
43
44 #ifdef HAVE_ICONV_H
45 #include <iconv.h>
46 #endif
47 #ifdef HAVE_LANGINFO_H
48 #include <langinfo.h>
49 #endif
50
51 #ifdef __WXMSW__
52 #include <windows.h>
53 #endif
54
55 #include "wx/debug.h"
56 #include "wx/strconv.h"
57
58 #ifdef WORDS_BIGENDIAN
59 #define BSWAP_UCS4(str, len)
60 #define BSWAP_UCS2(str, len)
61 #else
62 #define BSWAP_UCS4(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT32_SWAP_ALWAYS(str[_c]); }
63 #define BSWAP_UCS2(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT16_SWAP_ALWAYS(str[_c]); }
64 #define WC_NEED_BSWAP
65 #endif
66 #define BSWAP_UTF32(str, len) BSWAP_UCS4(str, len)
67 #define BSWAP_UTF16(str, len) BSWAP_UCS2(str, len)
68
69 #if SIZEOF_WCHAR_T == 4
70 #define WC_NAME "UCS4"
71 #define WC_BSWAP BSWAP_UCS4
72 #elif SIZEOF_WCHAR_T == 2
73 #define WC_NAME "UTF16"
74 #define WC_BSWAP BSWAP_UTF16
75 #define WC_UTF16
76 #endif
77
78 // ----------------------------------------------------------------------------
79 // globals
80 // ----------------------------------------------------------------------------
81
82 WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc;
83
84 // ============================================================================
85 // implementation
86 // ============================================================================
87
88 #if wxUSE_WCHAR_T
89
90 static size_t encode_utf16(wxUint32 input,wxUint16*output)
91 {
92 if (input<=0xffff) {
93 if (output) *output++ = input;
94 return 1;
95 } else
96 if (input>=0x110000) {
97 return (size_t)-1;
98 } else {
99 if (output) {
100 *output++ = (input >> 10)+0xd7c0;
101 *output++ = (input&0x3ff)+0xdc00;
102 }
103 return 2;
104 }
105 }
106
107 static size_t decode_utf16(wxUint16*input,wxUint32&output)
108 {
109 if ((*input<0xd800) || (*input>0xdfff)) {
110 output = *input;
111 return 1;
112 } else
113 if ((input[1]<0xdc00) || (input[1]>=0xdfff)) {
114 output = *input;
115 return (size_t)-1;
116 } else {
117 output = ((input[0] - 0xd7c0) << 10) + (input[1] - 0xdc00);
118 return 2;
119 }
120 }
121
122 // ----------------------------------------------------------------------------
123 // wxMBConv
124 // ----------------------------------------------------------------------------
125
126 WXDLLEXPORT_DATA(wxMBConv) wxConvLibc;
127
128 size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
129 {
130 return wxMB2WC(buf, psz, n);
131 }
132
133 size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
134 {
135 return wxWC2MB(buf, psz, n);
136 }
137
138 const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const
139 {
140 if (psz)
141 {
142 size_t nLen = MB2WC((wchar_t *) NULL, psz, 0);
143 if (nLen == (size_t)-1)
144 return wxWCharBuffer((wchar_t *) NULL);
145 wxWCharBuffer buf(nLen);
146 MB2WC((wchar_t *)(const wchar_t *) buf, psz, nLen);
147 return buf;
148 }
149 else
150 return wxWCharBuffer((wchar_t *) NULL);
151 }
152
153 const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *psz) const
154 {
155 if (psz)
156 {
157 size_t nLen = WC2MB((char *) NULL, psz, 0);
158 if (nLen == (size_t)-1)
159 return wxCharBuffer((char *) NULL);
160 wxCharBuffer buf(nLen);
161 WC2MB((char *)(const char *) buf, psz, nLen);
162 return buf;
163 }
164 else
165 return wxCharBuffer((char *) NULL);
166 }
167
168 // ----------------------------------------------------------------------------
169 // standard file conversion
170 // ----------------------------------------------------------------------------
171
172 WXDLLEXPORT_DATA(wxMBConvFile) wxConvFile;
173
174 // just use the libc conversion for now
175 size_t wxMBConvFile::MB2WC(wchar_t *buf, const char *psz, size_t n) const
176 {
177 return wxMB2WC(buf, psz, n);
178 }
179
180 size_t wxMBConvFile::WC2MB(char *buf, const wchar_t *psz, size_t n) const
181 {
182 return wxWC2MB(buf, psz, n);
183 }
184
185 // ----------------------------------------------------------------------------
186 // standard gdk conversion
187 // ----------------------------------------------------------------------------
188
189 #ifdef __WXGTK12__
190
191 WXDLLEXPORT_DATA(wxMBConvGdk) wxConvGdk;
192
193 #include <gdk/gdk.h>
194
195 size_t wxMBConvGdk::MB2WC(wchar_t *buf, const char *psz, size_t n) const
196 {
197 if (buf) {
198 return gdk_mbstowcs((GdkWChar *)buf, psz, n);
199 } else {
200 GdkWChar *nbuf = new GdkWChar[n=strlen(psz)];
201 size_t len = gdk_mbstowcs(nbuf, psz, n);
202 delete [] nbuf;
203 return len;
204 }
205 }
206
207 size_t wxMBConvGdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const
208 {
209 char *mbstr = gdk_wcstombs((GdkWChar *)psz);
210 size_t len = mbstr ? strlen(mbstr) : 0;
211 if (buf) {
212 if (len > n) len = n;
213 memcpy(buf, psz, len);
214 if (len < n) buf[len] = 0;
215 }
216 return len;
217 }
218
219 #endif // GTK > 1.0
220
221 // ----------------------------------------------------------------------------
222 // UTF-7
223 // ----------------------------------------------------------------------------
224
225 WXDLLEXPORT_DATA(wxMBConvUTF7) wxConvUTF7;
226
227 #if 0
228 static char utf7_setD[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
229 "abcdefghijklmnopqrstuvwxyz"
230 "0123456789'(),-./:?";
231 static char utf7_setO[]="!\"#$%&*;<=>@[]^_`{|}";
232 static char utf7_setB[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
233 "abcdefghijklmnopqrstuvwxyz"
234 "0123456789+/";
235 #endif
236
237 // TODO: write actual implementations of UTF-7 here
238 size_t wxMBConvUTF7::MB2WC(wchar_t * WXUNUSED(buf),
239 const char * WXUNUSED(psz),
240 size_t WXUNUSED(n)) const
241 {
242 return 0;
243 }
244
245 size_t wxMBConvUTF7::WC2MB(char * WXUNUSED(buf),
246 const wchar_t * WXUNUSED(psz),
247 size_t WXUNUSED(n)) const
248 {
249 return 0;
250 }
251
252 // ----------------------------------------------------------------------------
253 // UTF-8
254 // ----------------------------------------------------------------------------
255
256 WXDLLEXPORT_DATA(wxMBConvUTF8) wxConvUTF8;
257
258 static wxUint32 utf8_max[]={0x7f,0x7ff,0xffff,0x1fffff,0x3ffffff,0x7fffffff,0xffffffff};
259
260 size_t wxMBConvUTF8::MB2WC(wchar_t *buf, const char *psz, size_t n) const
261 {
262 size_t len = 0;
263
264 while (*psz && ((!buf) || (len<n))) {
265 unsigned char cc=*psz++, fc=cc;
266 unsigned cnt;
267 for (cnt=0; fc&0x80; cnt++) fc<<=1;
268 if (!cnt) {
269 // plain ASCII char
270 if (buf) *buf++=cc;
271 len++;
272 } else {
273 cnt--;
274 if (!cnt) {
275 // invalid UTF-8 sequence
276 return (size_t)-1;
277 } else {
278 unsigned ocnt=cnt-1;
279 wxUint32 res=cc&(0x3f>>cnt);
280 while (cnt--) {
281 cc = *psz++;
282 if ((cc&0xC0)!=0x80) {
283 // invalid UTF-8 sequence
284 return (size_t)-1;
285 }
286 res=(res<<6)|(cc&0x3f);
287 }
288 if (res<=utf8_max[ocnt]) {
289 // illegal UTF-8 encoding
290 return (size_t)-1;
291 }
292 #ifdef WC_UTF16
293 size_t pa = encode_utf16(res, buf);
294 if (pa == (size_t)-1)
295 return (size_t)-1;
296 if (buf) buf+=pa;
297 len+=pa;
298 #else
299 if (buf) *buf++=res;
300 len++;
301 #endif
302 }
303 }
304 }
305 if (buf && (len<n)) *buf = 0;
306 return len;
307 }
308
309 size_t wxMBConvUTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const
310 {
311 size_t len = 0;
312
313 while (*psz && ((!buf) || (len<n))) {
314 wxUint32 cc;
315 #ifdef WC_UTF16
316 size_t pa = decode_utf16(psz,cc);
317 psz += (pa == (size_t)-1) ? 1 : pa;
318 #else
319 cc=(*psz++)&0x7fffffff;
320 #endif
321 unsigned cnt;
322 for (cnt=0; cc>utf8_max[cnt]; cnt++);
323 if (!cnt) {
324 // plain ASCII char
325 if (buf) *buf++=cc;
326 len++;
327 } else {
328 len+=cnt+1;
329 if (buf) {
330 *buf++=(-128>>cnt)|((cc>>(cnt*6))&(0x3f>>cnt));
331 while (cnt--)
332 *buf++=0x80|((cc>>(cnt*6))&0x3f);
333 }
334 }
335 }
336 if (buf && (len<n)) *buf = 0;
337 return len;
338 }
339
340 // ----------------------------------------------------------------------------
341 // specified character set
342 // ----------------------------------------------------------------------------
343
344 WXDLLEXPORT_DATA(wxCSConv) wxConvLocal((const wxChar *)NULL);
345
346 #include "wx/encconv.h"
347 #include "wx/fontmap.h"
348
349 // TODO: add some tables here
350 // - perhaps common encodings to common codepages (for Win32)
351 // - perhaps common encodings to objects ("UTF8" -> wxConvUTF8)
352 // - move wxEncodingConverter meat in here
353
354 #ifdef __WIN32__
355 #include "wx/msw/registry.h"
356 // this should work if M$ Internet Exploiter is installed
357 static long CharsetToCodepage(const wxChar *name)
358 {
359 if (!name) return GetACP();
360 long CP=-1;
361 wxString cn(name);
362 do {
363 wxString path(wxT("MIME\\Database\\Charset\\"));
364 path += cn;
365 wxRegKey key(wxRegKey::HKCR,path);
366
367 /* two cases: either there's an AliasForCharset string,
368 * or there are Codepage and InternetEncoding dwords.
369 * The InternetEncoding gives us the actual encoding,
370 * the Codepage just says which Windows character set to
371 * use when displaying the data.
372 */
373 if (key.QueryValue(wxT("InternetEncoding"),&CP)) break;
374 // no encoding, see if it's an alias
375 if (!key.QueryValue(wxT("AliasForCharset"),cn)) break;
376 } while (1);
377 return CP;
378 }
379 #endif
380
381 class wxCharacterSet
382 {
383 public:
384 const wxChar*cname;
385 wxCharacterSet(const wxChar*name) : cname(name) {}
386 virtual ~wxCharacterSet() {}
387 virtual size_t MB2WC(wchar_t*buf, const char*psz, size_t n) { return (size_t)-1; }
388 virtual size_t WC2MB(char*buf, const wchar_t*psz, size_t n) { return (size_t)-1; }
389 virtual bool usable() { return FALSE; }
390 };
391
392 class ID_CharSet : public wxCharacterSet
393 {
394 public:
395 wxMBConv*work;
396 ID_CharSet(const wxChar*name,wxMBConv*cnv) : wxCharacterSet(name), work(cnv) {}
397 size_t MB2WC(wchar_t*buf, const char*psz, size_t n)
398 { return work ? work->MB2WC(buf,psz,n) : (size_t)-1; }
399 size_t WC2MB(char*buf, const wchar_t*psz, size_t n)
400 { return work ? work->WC2MB(buf,psz,n) : (size_t)-1; }
401 bool usable() { return work!=NULL; }
402 };
403
404 #ifdef HAVE_ICONV_H
405 class IC_CharSet : public wxCharacterSet
406 {
407 public:
408 iconv_t m2w, w2m;
409 IC_CharSet(const wxChar*name) : wxCharacterSet(name), m2w((iconv_t)-1), w2m((iconv_t)-1) {}
410 ~IC_CharSet() {
411 if (m2w!=(iconv_t)-1) iconv_close(m2w);
412 if (w2m!=(iconv_t)-1) iconv_close(w2m);
413 }
414 void LoadM2W() { if (m2w==(iconv_t)-1) m2w=iconv_open(WC_NAME,wxConvLibc.cWX2MB(cname)); }
415 void LoadW2M() { if (w2m==(iconv_t)-1) w2m=iconv_open(wxConvLibc.cWX2MB(cname),WC_NAME); }
416 size_t MB2WC(wchar_t*buf, const char*psz, size_t n) {
417 LoadM2W();
418 size_t inbuf = strlen(psz);
419 size_t outbuf = n*SIZEOF_WCHAR_T;
420 size_t res, cres;
421 fprintf(stderr,"IC Convert to WC using %s\n",(const char*)wxConvLibc.cWX2MB(cname));
422 if (buf) {
423 // have destination buffer, convert there
424 cres = iconv(m2w,&psz,&inbuf,(char**)&buf,&outbuf);
425 res = n-(outbuf/SIZEOF_WCHAR_T);
426 // convert to native endianness
427 WC_BSWAP(buf, res)
428 } else {
429 // no destination buffer... convert using temp buffer
430 // to calculate destination buffer requirement
431 wchar_t tbuf[8];
432 res = 0;
433 do {
434 buf = tbuf; outbuf = 8*SIZEOF_WCHAR_T;
435 cres = iconv(m2w,&psz,&inbuf,(char**)&buf,&outbuf);
436 res += 8-(outbuf/SIZEOF_WCHAR_T);
437 } while ((cres==(size_t)-1) && (errno==E2BIG));
438 }
439 if (cres==(size_t)-1) return (size_t)-1;
440 return res;
441 }
442 size_t WC2MB(char*buf, const wchar_t*psz, size_t n) {
443 LoadW2M();
444 #if defined(__BORLANDC__) && (__BORLANDC__ > 0x530)
445 size_t inbuf = std::wcslen(psz);
446 #else
447 size_t inbuf = ::wcslen(psz);
448 #endif
449 size_t outbuf = n;
450 size_t res, cres;
451 fprintf(stderr,"IC Convert from WC using %s\n",(const char*)wxConvLibc.cWX2MB(cname));
452 #ifdef WC_NEED_BSWAP
453 // need to copy to temp buffer to switch endianness
454 // this absolutely doesn't rock!
455 // (no, doing WC_BSWAP twice on the original buffer won't help, as it
456 // could be in read-only memory, or be accessed in some other thread)
457 wchar_t*tmpbuf=(wchar_t*)malloc((inbuf+1)*SIZEOF_WCHAR_T);
458 memcpy(tmpbuf,psz,(inbuf+1)*SIZEOF_WCHAR_T);
459 WC_BSWAP(tmpbuf, inbuf)
460 psz=tmpbuf;
461 #endif
462 if (buf) {
463 // have destination buffer, convert there
464 cres = iconv(w2m,(const char**)&psz,&inbuf,&buf,&outbuf);
465 res = n-outbuf;
466 } else {
467 // no destination buffer... convert using temp buffer
468 // to calculate destination buffer requirement
469 char tbuf[16];
470 res = 0;
471 do {
472 buf = tbuf; outbuf = 16;
473 cres = iconv(w2m,(const char**)&psz,&inbuf,&buf,&outbuf);
474 res += 16 - outbuf;
475 } while ((cres==(size_t)-1) && (errno==E2BIG));
476 }
477 #ifdef WC_NEED_BSWAP
478 free(tmpbuf);
479 #endif
480 if (cres==(size_t)-1) return (size_t)-1;
481 return res;
482 }
483 bool usable() { return TRUE; }
484 };
485 #endif
486
487 #ifdef __WIN32__
488 class CP_CharSet : public wxCharacterSet
489 {
490 public:
491 long CodePage;
492 CP_CharSet(const wxChar*name) : wxCharacterSet(name), CodePage(CharsetToCodepage(name)) {}
493 size_t MB2WC(wchar_t*buf, const char*psz, size_t n) {
494 size_t len = MultiByteToWideChar(CodePage,0,psz,-1,buf,buf?n:0);
495 return len?len:(size_t)-1;
496 }
497 size_t WC2MB(char*buf, const wchar_t*psz, size_t n) {
498 size_t len = WideCharToMultiByte(CodePage,0,psz,-1,buf,buf?n:0,NULL,NULL);
499 return len?len:(size_t)-1;
500 }
501 bool usable() { return CodePage!=-1; }
502 };
503 #endif
504
505 class EC_CharSet : public wxCharacterSet
506 {
507 public:
508 // temporarily just use wxEncodingConverter stuff,
509 // so that it works while a better implementation is built
510 wxFontEncoding enc;
511 wxEncodingConverter m2w, w2m;
512 EC_CharSet(const wxChar*name) : wxCharacterSet(name), enc(wxFONTENCODING_SYSTEM)
513 {
514 if (name) enc = wxTheFontMapper->CharsetToEncoding(name, FALSE);
515 m2w.Init(enc, wxFONTENCODING_UNICODE);
516 w2m.Init(wxFONTENCODING_UNICODE, enc);
517 }
518 size_t MB2WC(wchar_t*buf, const char*psz, size_t n) {
519 size_t inbuf = strlen(psz);
520 fprintf(stderr,"EC Convert to WC using %d\n",enc);
521 if (buf) m2w.Convert(psz,buf);
522 return inbuf;
523 }
524 size_t WC2MB(char*buf, const wchar_t*psz, size_t n) {
525 #if defined(__BORLANDC__) && (__BORLANDC__ > 0x530)
526 size_t inbuf = std::wcslen(psz);
527 #else
528 size_t inbuf = ::wcslen(psz);
529 #endif
530 fprintf(stderr,"EC Convert from WC using %d\n",enc);
531 if (buf) w2m.Convert(psz,buf);
532 return inbuf;
533 }
534 bool usable() { return (enc!=wxFONTENCODING_SYSTEM) && (enc!=wxFONTENCODING_DEFAULT); }
535 };
536
537 static wxCharacterSet *wxGetCharacterSet(const wxChar *name)
538 {
539 wxCharacterSet *cset = NULL;
540 if (name) {
541 if (!wxStricmp(name, wxT("UTF8")) || !wxStricmp(name, wxT("UTF-8"))) {
542 cset = new ID_CharSet(name, &wxConvUTF8);
543 } else {
544 #ifdef HAVE_ICONV_H
545 cset = new IC_CharSet(name); // may not take NULL
546 #endif
547 }
548 }
549 if (cset && cset->usable()) return cset;
550 if (cset) delete cset;
551 #ifdef __WIN32__
552 cset = new CP_CharSet(name); // may take NULL
553 if (cset->usable()) return cset;
554 #endif
555 if (cset) delete cset;
556 cset = new EC_CharSet(name);
557 if (cset->usable()) return cset;
558 delete cset;
559 return NULL;
560 }
561
562 wxCSConv::wxCSConv(const wxChar *charset)
563 {
564 m_name = (wxChar *) NULL;
565 m_cset = (wxCharacterSet *) NULL;
566 m_deferred = TRUE;
567 SetName(charset);
568 }
569
570 wxCSConv::~wxCSConv()
571 {
572 if (m_name) free(m_name);
573 if (m_cset) delete m_cset;
574 }
575
576 void wxCSConv::SetName(const wxChar *charset)
577 {
578 if (charset) {
579 m_name = wxStrdup(charset);
580 m_deferred = TRUE;
581 }
582 }
583
584 void wxCSConv::LoadNow()
585 {
586 // wxPrintf(wxT("Conversion request\n"));
587 if (m_deferred) {
588 if (!m_name) {
589 #ifdef __UNIX__
590 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
591 // GNU libc provides current character set this way
592 char*alang = nl_langinfo(CODESET);
593 if (alang) SetName(wxConvLibc.cMB2WX(alang));
594 else
595 #endif
596 // if we can't get at the character set directly,
597 // try to see if it's in the environment variables
598 // (in most cases this won't work, but I was out of ideas)
599 {
600 wxChar *lang = wxGetenv(wxT("LC_ALL"));
601 if (!lang) lang = wxGetenv(wxT("LC_CTYPE"));
602 if (!lang) lang = wxGetenv(wxT("LANG"));
603 wxChar *dot = lang ? wxStrchr(lang, wxT('.')) : (wxChar *)NULL;
604 if (dot) SetName(dot+1);
605 }
606 #endif
607 }
608 m_cset = wxGetCharacterSet(m_name);
609 m_deferred = FALSE;
610 }
611 }
612
613 size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
614 {
615 ((wxCSConv *)this)->LoadNow(); // discard constness
616 if (m_cset)
617 return m_cset->MB2WC(buf, psz, n);
618
619 // latin-1 (direct)
620 size_t len=strlen(psz);
621 if (buf) {
622 for (size_t c=0; c<=len; c++)
623 buf[c] = (unsigned char)(psz[c]);
624 }
625 return len;
626 }
627
628 size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
629 {
630 ((wxCSConv *)this)->LoadNow(); // discard constness
631 if (m_cset)
632 return m_cset->WC2MB(buf, psz, n);
633
634 // latin-1 (direct)
635 #if defined(__BORLANDC__) && (__BORLANDC__ > 0x530)
636 size_t len=std::wcslen(psz);
637 #else
638 size_t len=::wcslen(psz);
639 #endif
640 if (buf) {
641 for (size_t c=0; c<=len; c++)
642 buf[c] = (psz[c]>0xff) ? '?' : psz[c];
643 }
644 return len;
645 }
646
647 #ifdef HAVE_ICONV_H
648 class IC_CharSetConverter
649 {
650 public:
651 iconv_t cnv;
652 IC_CharSetConverter(IC_CharSet*from,IC_CharSet*to) {
653 cnv=iconv_open(wxConvLibc.cWX2MB(to->cname),wxConvLibc.cWX2MB(from->cname));
654 }
655 ~IC_CharSetConverter() {
656 if (cnv!=(iconv_t)-1) iconv_close(cnv);
657 }
658 size_t Convert(char*buf, const char*psz, size_t n) {
659 size_t inbuf = strlen(psz);
660 size_t outbuf = n;
661 size_t res = iconv(cnv,&psz,&inbuf,&buf,&outbuf);
662 if (res==(size_t)-1) return (size_t)-1;
663 return n-outbuf;
664 }
665 };
666 #endif
667
668 class EC_CharSetConverter
669 {
670 public:
671 wxEncodingConverter cnv;
672 EC_CharSetConverter(EC_CharSet*from,EC_CharSet*to) {
673 cnv.Init(from->enc,to->enc);
674 }
675 size_t Convert(char*buf, const char*psz, size_t n) {
676 size_t inbuf = strlen(psz);
677 if (buf) cnv.Convert(psz,buf);
678 return inbuf;
679 }
680 };
681
682 #else // !wxUSE_WCHAR_T
683
684 // ----------------------------------------------------------------------------
685 // stand-ins in absence of wchar_t
686 // ----------------------------------------------------------------------------
687
688 WXDLLEXPORT_DATA(wxMBConv) wxConvLibc, wxConvFile;
689
690 #endif // wxUSE_WCHAR_T
691
692