]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/strconv.cpp
Added settings.h include
[wxWidgets.git] / src / common / strconv.cpp
... / ...
CommitLineData
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
82WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc;
83
84// ============================================================================
85// implementation
86// ============================================================================
87
88#if wxUSE_WCHAR_T
89
90static 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
107static 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
126WXDLLEXPORT_DATA(wxMBConv) wxConvLibc;
127
128size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
129{
130 return wxMB2WC(buf, psz, n);
131}
132
133size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
134{
135 return wxWC2MB(buf, psz, n);
136}
137
138const 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
153const 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
172WXDLLEXPORT_DATA(wxMBConvFile) wxConvFile;
173
174// just use the libc conversion for now
175size_t wxMBConvFile::MB2WC(wchar_t *buf, const char *psz, size_t n) const
176{
177 return wxMB2WC(buf, psz, n);
178}
179
180size_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
191WXDLLEXPORT_DATA(wxMBConvGdk) wxConvGdk;
192
193#include <gdk/gdk.h>
194
195size_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
207size_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
225WXDLLEXPORT_DATA(wxMBConvUTF7) wxConvUTF7;
226
227#if 0
228static char utf7_setD[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
229 "abcdefghijklmnopqrstuvwxyz"
230 "0123456789'(),-./:?";
231static char utf7_setO[]="!\"#$%&*;<=>@[]^_`{|}";
232static char utf7_setB[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
233 "abcdefghijklmnopqrstuvwxyz"
234 "0123456789+/";
235#endif
236
237// TODO: write actual implementations of UTF-7 here
238size_t wxMBConvUTF7::MB2WC(wchar_t * WXUNUSED(buf),
239 const char * WXUNUSED(psz),
240 size_t WXUNUSED(n)) const
241{
242 return 0;
243}
244
245size_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
256WXDLLEXPORT_DATA(wxMBConvUTF8) wxConvUTF8;
257
258static wxUint32 utf8_max[]={0x7f,0x7ff,0xffff,0x1fffff,0x3ffffff,0x7fffffff,0xffffffff};
259
260size_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
309size_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
344WXDLLEXPORT_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
357static 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
381class wxCharacterSet
382{
383public:
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
392class ID_CharSet : public wxCharacterSet
393{
394public:
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
405class IC_CharSet : public wxCharacterSet
406{
407public:
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__
488class CP_CharSet : public wxCharacterSet
489{
490public:
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
505class EC_CharSet : public wxCharacterSet
506{
507public:
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
537static 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
562wxCSConv::wxCSConv(const wxChar *charset)
563{
564 m_name = (wxChar *) NULL;
565 m_cset = (wxCharacterSet *) NULL;
566 m_deferred = TRUE;
567 SetName(charset);
568}
569
570wxCSConv::~wxCSConv()
571{
572 if (m_name) free(m_name);
573 if (m_cset) delete m_cset;
574}
575
576void wxCSConv::SetName(const wxChar *charset)
577{
578 if (charset) {
579 m_name = wxStrdup(charset);
580 m_deferred = TRUE;
581 }
582}
583
584void 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
613size_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
628size_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
648class IC_CharSetConverter
649{
650public:
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
668class EC_CharSetConverter
669{
670public:
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
688WXDLLEXPORT_DATA(wxMBConv) wxConvLibc, wxConvFile;
689
690#endif // wxUSE_WCHAR_T
691
692