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