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