+#endif // wxUSE_UNICODE_WCHAR
+
+#if wxUSE_UNICODE_UTF8
+/* static */
+wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
+                                               const wxMBConv& conv)
+{
+    // anything to do?
+    if ( !psz || nLength == 0 )
+        return SubstrBufFromMB("", 0);
+
+    // if psz is already in UTF-8, we don't have to do the roundtrip to
+    // wchar_t* and back:
+    if ( conv.IsUTF8() )
+    {
+        // we need to validate the input because UTF8 iterators assume valid
+        // UTF-8 sequence and psz may be invalid:
+        if ( wxStringOperations::IsValidUtf8String(psz, nLength) )
+        {
+            return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz), nLength);
+        }
+        // else: do the roundtrip through wchar_t*
+    }
+
+    if ( nLength == npos )
+        nLength = wxNO_LEN;
+
+    // first convert to wide string:
+    size_t wcLen;
+    wxWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
+    if ( !wcLen )
+        return SubstrBufFromMB("", 0);
+
+    // and then to UTF-8:
+    SubstrBufFromMB buf(ConvertStr(wcBuf, wcLen, wxMBConvUTF8()));
+    // widechar -> UTF-8 conversion isn't supposed to ever fail:
+    wxASSERT_MSG( buf.data, _T("conversion to UTF-8 failed") );
+
+    return buf;
+}
+#endif // wxUSE_UNICODE_UTF8
+
+#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE