+
+static bool wxIsLocaleUtf8()
+{
+ // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
+ // because a) it may be unavailable in some builds and b) has slightly
+ // different semantics (default locale instead of current)
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+ // GNU libc provides current character set this way (this conforms to
+ // Unix98)
+ const char *charset = nl_langinfo(CODESET);
+ if ( charset )
+ {
+ // "UTF-8" is used by modern glibc versions, but test other variants
+ // as well, just in case:
+ if ( strcmp(charset, "UTF-8") == 0 ||
+ strcmp(charset, "utf-8") == 0 ||
+ strcmp(charset, "UTF8") == 0 ||
+ strcmp(charset, "utf8") == 0 )
+ {
+ return true;
+ }
+ }
+#endif
+
+ // check if we're running under the "C" locale: it is 7bit subset
+ // of UTF-8, so it can be safely used with the UTF-8 build:
+ const char *lc_ctype = setlocale(LC_CTYPE, NULL);
+ if ( lc_ctype &&
+ (strcmp(lc_ctype, "C") == 0 || strcmp(lc_ctype, "POSIX") == 0) )
+ {
+ return true;
+ }
+
+ // we don't know what charset libc is using, so assume the worst
+ // to be safe:
+ return false;
+}
+
+void wxUpdateLocaleIsUtf8()
+{
+#if wxUSE_UTF8_LOCALE_ONLY
+ if ( !wxIsLocaleUtf8() )
+ {
+ wxLogFatalError(_T("This program requires UTF-8 locale to run."));
+ }
+#else // !wxUSE_UTF8_LOCALE_ONLY
+ wxLocaleIsUtf8 = wxIsLocaleUtf8();
+#endif
+}
+
+#endif // wxUSE_UNICODE_UTF8
+
+// ============================================================================
+// wx wrappers for CRT functions
+// ============================================================================
+
+#if wxUSE_UNICODE_WCHAR
+ #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callW
+#elif wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
+ #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) \
+ return_kw wxLocaleIsUtf8 ? callA : callW
+#else // ANSI or UTF8 only
+ #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callA
+#endif
+
+int wxPuts(const wxString& s)
+{
+ CALL_ANSI_OR_UNICODE(return,
+ wxCRT_PutsA(s.mb_str()),
+ wxCRT_PutsW(s.wc_str()));
+}
+
+int wxFputs(const wxString& s, FILE *stream)
+{
+ CALL_ANSI_OR_UNICODE(return,
+ wxCRT_FputsA(s.mb_str(), stream),
+ wxCRT_FputsW(s.wc_str(), stream));
+}
+
+int wxFputc(const wxUniChar& c, FILE *stream)
+{
+#if !wxUSE_UNICODE // FIXME-UTF8: temporary, remove this with ANSI build
+ return wxCRT_FputcA((char)c, stream);
+#else
+ CALL_ANSI_OR_UNICODE(return,
+ wxCRT_FputsA(c.AsUTF8(), stream),
+ wxCRT_FputcW((wchar_t)c, stream));
+#endif
+}
+
+void wxPerror(const wxString& s)
+{
+#ifdef wxCRT_PerrorW
+ CALL_ANSI_OR_UNICODE(wxEMPTY_PARAMETER_VALUE,
+ wxCRT_PerrorA(s.mb_str()),
+ wxCRT_PerrorW(s.wc_str()));
+#else
+ wxCRT_PerrorA(s.mb_str());
+#endif
+}
+
+wchar_t *wxFgets(wchar_t *s, int size, FILE *stream)
+{
+ wxCHECK_MSG( s, NULL, "empty buffer passed to wxFgets()" );
+
+ wxCharBuffer buf(size - 1);
+ // FIXME: this reads too little data if wxConvLibc uses UTF-8 ('size' wide
+ // characters may be encoded by up to 'size'*4 bytes), but what
+ // else can we do?
+ if ( wxFgets(buf.data(), size, stream) == NULL )
+ return NULL;
+
+ if ( wxConvLibc.ToWChar(s, size, buf, wxNO_LEN) == wxCONV_FAILED )
+ return NULL;
+
+ return s;
+}
+
+// ----------------------------------------------------------------------------
+// wxScanf() and friends
+// ----------------------------------------------------------------------------
+
+#ifndef __VISUALC__
+int wxVsscanf(const char *str, const char *format, va_list ap)
+ { return wxCRT_VsscanfA(str, format, ap); }
+int wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap)
+ { return wxCRT_VsscanfW(str, format, ap); }
+int wxVsscanf(const wxCharBuffer& str, const char *format, va_list ap)
+ { return wxCRT_VsscanfA(str, format, ap); }
+int wxVsscanf(const wxWCharBuffer& str, const wchar_t *format, va_list ap)
+ { return wxCRT_VsscanfW(str, format, ap); }
+int wxVsscanf(const wxString& str, const char *format, va_list ap)
+ { return wxCRT_VsscanfA(str.mb_str(), format, ap); }
+int wxVsscanf(const wxString& str, const wchar_t *format, va_list ap)
+ { return wxCRT_VsscanfW(str.wc_str(), format, ap); }
+int wxVsscanf(const wxCStrData& str, const char *format, va_list ap)
+ { return wxCRT_VsscanfA(str.AsCharBuf(), format, ap); }
+int wxVsscanf(const wxCStrData& str, const wchar_t *format, va_list ap)
+ { return wxCRT_VsscanfW(str.AsWCharBuf(), format, ap); }
+#endif // !__VISUALC__