X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ba555d51b00e2acf5d148b6445206556853ef5f3..6f841509cecded593e8e7c20d4a9e23ed29e5fa1:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index d0676caa7f..2d371b9fa4 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -256,8 +256,7 @@ wxString::wxString(const void *pStart, const void *pEnd) wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) { // first get necessary size - - size_t nLen = conv.MB2WC((wchar_t *) NULL, psz, 0); + size_t nLen = psz ? conv.MB2WC((wchar_t *) NULL, psz, 0) : 0; // nLength is number of *Unicode* characters here! if (nLen > nLength) @@ -279,8 +278,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) wxString::wxString(const wchar_t *pwz) { // first get necessary size - - size_t nLen = wxWC2MB((char *) NULL, pwz, 0); + size_t nLen = pwz ? wxWC2MB((char *) NULL, pwz, 0) : 0; // empty? if ( nLen != 0 ) { @@ -1187,8 +1185,8 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) if (s.Len() < min_width) s.Pad(min_width - s.Len(), _T(' '), adj_left); *this += s; - done = TRUE; } + done = TRUE; break; case _T('n'): if (ilen == 0) { @@ -1627,6 +1625,21 @@ void wxArrayString::Alloc(size_t nSize) m_nCount = 0; } +// minimizes the memory usage by freeing unused memory +void wxArrayString::Shrink() +{ + // only do it if we have some memory to free + if( m_nCount < m_nSize ) { + // allocates exactly as much memory as we need + wxChar **pNew = new wxChar *[m_nCount]; + + // copy data to new location + memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *)); + delete [] m_pItems; + m_pItems = pNew; + } +} + // searches the array for an item (forward or backwards) int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const { @@ -1788,6 +1801,8 @@ void wxArrayString::DoSort() // MBConv // ============================================================================ +WXDLLEXPORT_DATA(wxMBConv *) wxConv_current = &wxConv_libc; + // ---------------------------------------------------------------------------- // standard libc conversion // ---------------------------------------------------------------------------- @@ -1825,7 +1840,7 @@ size_t wxMBConv_file::WC2MB(char *buf, const wchar_t *psz, size_t n) const // standard gdk conversion // ---------------------------------------------------------------------------- -#ifdef __WXGTK__ +#if defined(__WXGTK__) && (GTK_MINOR_VERSION > 0) WXDLLEXPORT_DATA(wxMBConv_gdk) wxConv_gdk; #include @@ -1853,7 +1868,7 @@ size_t wxMBConv_gdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const } return len; } -#endif +#endif // GTK > 1.0 // ---------------------------------------------------------------------------- // UTF-7 @@ -1893,33 +1908,215 @@ size_t wxMBConv_UTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const // specified character set // ---------------------------------------------------------------------------- -// TODO: write actual implementation of character set conversion here +class wxCharacterSet +{ +public: + wxArrayString names; + wchar_t *data; +}; + +#ifndef WX_PRECOMP + #include "wx/dynarray.h" + #include "wx/filefn.h" + #include "wx/textfile.h" + #include "wx/tokenzr.h" + #include "wx/utils.h" +#endif + +WX_DECLARE_OBJARRAY(wxCharacterSet, wxCSArray); +#include "wx/arrimpl.cpp" +WX_DEFINE_OBJARRAY(wxCSArray); + +static wxCSArray wxCharsets; + +static void wxLoadCharacterSets(void) +{ + static bool already_loaded = FALSE; + + if (already_loaded) return; + +#if defined(__UNIX__) + // search through files in /usr/share/i18n/charmaps + wxString fname; + for (fname = ::wxFindFirstFile(_T("/usr/share/i18n/charmaps/*")); + !fname.IsEmpty(); + fname = ::wxFindNextFile()) { + wxTextFile cmap(fname); + if (cmap.Open()) { + wxCharacterSet *cset = new wxCharacterSet; + wxString comchar,escchar; + bool in_charset = FALSE; + + // wxFprintf(stderr,_T("Loaded: %s\n"),fname.c_str()); + + wxString line; + for (line = cmap.GetFirstLine(); + !cmap.Eof(); + line = cmap.GetNextLine()) { + // wxFprintf(stderr,_T("line contents: %s\n"),line.c_str()); + wxStringTokenizer token(line); + wxString cmd = token.GetNextToken(); + if (cmd == comchar) { + if (token.GetNextToken() == _T("alias")) { + wxStringTokenizer names(token.GetNextToken(),_T("/")); + wxString name; + while (!(name = names.GetNextToken()).IsEmpty()) + cset->names.Add(name); + } + } + else if (cmd == _T("")) + cset->names.Add(token.GetNextToken()); + else if (cmd == _T("")) + comchar = token.GetNextToken(); + else if (cmd == _T("")) + escchar = token.GetNextToken(); + else if (cmd == _T("")) { + delete cset; + cset = (wxCharacterSet *) NULL; + break; // we don't support multibyte charsets ourselves (yet) + } + else if (cmd == _T("CHARMAP")) { + cset->data = (wchar_t *)calloc(256, sizeof(wchar_t)); + in_charset = TRUE; + } + else if (cmd == _T("END")) { + if (token.GetNextToken() == _T("CHARMAP")) + in_charset = FALSE; + } + else if (in_charset) { + // format: /x00 NULL (NUL) + // /x41 LATIN CAPITAL LETTER A + wxString hex = token.GetNextToken(); + // skip whitespace (why doesn't wxStringTokenizer do this?) + while (wxIsEmpty(hex) && token.HasMoreTokens()) hex = token.GetNextToken(); + wxString uni = token.GetNextToken(); + // skip whitespace again + while (wxIsEmpty(uni) && token.HasMoreTokens()) uni = token.GetNextToken(); + + if ((hex.GetChar(0) == escchar) && (hex.GetChar(1) == _T('x')) && + (uni.Left(2) == _T("=0) { + unsigned long uni1 = ::wxHexToDec(uni.Mid(2,2)); + unsigned long uni2 = ::wxHexToDec(uni.Mid(4,2)); + cset->data[pos] = (uni1 << 16) | uni2; + // wxFprintf(stderr,_T("char %02x mapped to %04x (%c)\n"),pos,cset->data[pos],cset->data[pos]); + } + } + } + } + if (cset) { + cset->names.Shrink(); + wxCharsets.Add(cset); + } + } + } +#endif + wxCharsets.Shrink(); + already_loaded = TRUE; +} + +static wxCharacterSet *wxFindCharacterSet(const wxChar *charset) +{ + if (!charset) return (wxCharacterSet *)NULL; + wxLoadCharacterSets(); + for (size_t n=0; n4) { + if (wxString(charset,4) == _T("8859")) { + codeset << _T("8859-"); + if (*charset == _T('-')) charset++; + } + } + } + codeset << charset; + codeset.MakeUpper(); + m_name = wxStrdup(codeset.c_str()); + m_deferred = TRUE; +#endif + } +} + +void wxCSConv::LoadNow() +{ +// wxPrintf(_T("Conversion request\n")); + if (m_deferred) { + if (!m_name) { +#ifdef __UNIX__ + wxChar *lang = wxGetenv(_T("LANG")); + wxChar *dot = lang ? wxStrchr(lang, _T('.')) : (wxChar *)NULL; + if (dot) SetName(dot+1); +#endif + } + m_cset = wxFindCharacterSet(m_name); + m_deferred = FALSE; + } } size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { - if (buf && !data) { - // latin-1 (direct) - for (size_t c=0; c<=n; c++) - buf[c] = psz[c]; + ((wxCSConv *)this)->LoadNow(); // discard constness + if (buf) { + if (m_cset) { + for (size_t c=0; cdata[psz[c]]; + } else { + // latin-1 (direct) + for (size_t c=0; c0xff) ? '?' : psz[c]; + ((wxCSConv *)this)->LoadNow(); // discard constness + if (buf) { + if (m_cset) { + for (size_t c=0; cdata[n] != psz[c]); n++); + buf[c] = (n>0xff) ? '?' : n; + } + } else { + // latin-1 (direct) + for (size_t c=0; c0xff) ? '?' : psz[c]; + } + return n; } - return n; + return wcslen(psz); } -