]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wxchar.cpp
Correct names of some event binders
[wxWidgets.git] / src / common / wxchar.cpp
index c77dc9cec371ec528ff6eaed25156aa71478180c..e49acc8798eb2ec2e9516924720d8c49ee7fad57 100644 (file)
@@ -20,6 +20,8 @@
     #pragma hdrstop
 #endif
 
+#include "wx/wxchar.h"
+
 #define _ISOC9X_SOURCE 1 // to get vsscanf()
 #define _BSD_SOURCE    1 // to still get strdup()
 
 #endif
 
 #ifndef WX_PRECOMP
-    #include "wx/wxchar.h"
     #include "wx/string.h"
     #include "wx/hash.h"
+    #include "wx/utils.h"     // for wxMin and wxMax
+    #include "wx/log.h"
 #endif
-  #include "wx/utils.h"     // for wxMin and wxMax
 
 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
   #include <windef.h>
@@ -183,8 +185,27 @@ bool WXDLLEXPORT wxOKlibc()
 #endif
 
 // some limits of our implementation
-#define wxMAX_SVNPRINTF_ARGUMENTS         16
+#define wxMAX_SVNPRINTF_ARGUMENTS         64
 #define wxMAX_SVNPRINTF_FLAGBUFFER_LEN    32
+#define wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN   512
+
+// prefer snprintf over sprintf
+#if defined(__VISUALC__) || \
+        (defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
+    #define system_sprintf(buff, max, flags, data)      \
+        ::_snprintf(buff, max, flags, data)
+#elif defined(HAVE_SNPRINTF)
+    #define system_sprintf(buff, max, flags, data)      \
+        ::snprintf(buff, max, flags, data)
+#else       // NB: at least sprintf() should always be available
+    // since 'max' is not used in this case, wxVsnprintf() should always
+    // ensure that 'buff' is big enough for all common needs
+    // (see wxMAX_SVNPRINTF_FLAGBUFFER_LEN and wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN)
+    #define system_sprintf(buff, max, flags, data)      \
+        ::sprintf(buff, flags, data)
+
+    #define SYSTEM_SPRINTF_IS_UNSAFE
+#endif
 
 // the conversion specifiers accepted by wxVsnprintf_
 enum wxPrintfArgType {
@@ -278,7 +299,7 @@ public:
     //     thus could be safely declared as a char[] buffer, we want it to be wxChar
     //     so that in Unicode builds we can avoid to convert its contents to Unicode
     //     chars when copying it in user's buffer.
-    wxChar m_szFlags[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
+    char m_szFlags[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
 
 
 public:
@@ -317,7 +338,7 @@ void wxPrintfConvSpec::Init()
 
     // this character will never be removed from m_szFlags array and
     // is important when calling sprintf() in wxPrintfConvSpec::Process() !
-    m_szFlags[0] = wxT('%');
+    m_szFlags[0] = '%';
 }
 
 bool wxPrintfConvSpec::Parse(const wxChar *format)
@@ -356,13 +377,13 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('+'):
             case wxT('\''):
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('-'):
                 CHECK_PREC
                 m_bAlignLeft = true;
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('.'):
@@ -377,7 +398,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('h'):
                 ilen = -1;
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('l'):
@@ -387,20 +408,20 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
                 else
                 ilen = 1;
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('q'):
             case wxT('L'):
                 ilen = 2;
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('Z'):
                 ilen = 3;
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('*'):
@@ -421,7 +442,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
 
                 // save the * in our formatting buffer...
                 // will be replaced later by Process()
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 break;
 
             case wxT('1'): case wxT('2'): case wxT('3'):
@@ -433,7 +454,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
                     while ( (*m_pArgEnd >= wxT('0')) &&
                             (*m_pArgEnd <= wxT('9')) )
                     {
-                        m_szFlags[flagofs++] = (*m_pArgEnd);
+                        m_szFlags[flagofs++] = char(*m_pArgEnd);
                         len = len*10 + (*m_pArgEnd - wxT('0'));
                         m_pArgEnd++;
                     }
@@ -475,7 +496,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('x'):
             case wxT('X'):
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 m_szFlags[flagofs] = '\0';
                 if (ilen == 0)
                     m_type = wxPAT_INT;
@@ -503,7 +524,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('g'):
             case wxT('G'):
                 CHECK_PREC
-                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs++] = char(ch);
                 m_szFlags[flagofs] = '\0';
                 if (ilen == 2)
                     m_type = wxPAT_LONGDOUBLE;
@@ -514,6 +535,8 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
 
             case wxT('p'):
                 m_type = wxPAT_POINTER;
+                m_szFlags[flagofs++] = char(ch);
+                m_szFlags[flagofs] = '\0';
                 done = true;
                 break;
 
@@ -597,14 +620,14 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
 
 void wxPrintfConvSpec::ReplaceAsteriskWith(int width)
 {
-    wxChar temp[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
+    char temp[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
 
     // find the first * in our flag buffer
-    wxChar *pwidth = wxStrchr(m_szFlags, wxT('*'));
+    char *pwidth = strchr(m_szFlags, '*');
     wxASSERT(pwidth);
 
     // save what follows the * (the +1 is to skip the asterisk itself!)
-    wxStrcpy(temp, pwidth+1);
+    strcpy(temp, pwidth+1);
     if (width < 0)
     {
         pwidth[0] = wxT('-');
@@ -612,15 +635,14 @@ void wxPrintfConvSpec::ReplaceAsteriskWith(int width)
     }
 
     // replace * with the actual integer given as width
-#if wxUSE_UNICODE
-    int maxlen = (m_szFlags + wxMAX_SVNPRINTF_FLAGBUFFER_LEN - pwidth) / sizeof(wxChar);
-    int offset = ::swprintf(pwidth, maxlen, L"%d", abs(width));
-#else
-    int offset = ::sprintf(pwidth, "%d", abs(width));
+#ifndef SYSTEM_SPRINTF_IS_UNSAFE
+    int maxlen = (m_szFlags + wxMAX_SVNPRINTF_FLAGBUFFER_LEN - pwidth) /
+                        sizeof(*m_szFlags);
 #endif
+    int offset = system_sprintf(pwidth, maxlen, "%d", abs(width));
 
     // restore after the expanded * what was following it
-    wxStrcpy(pwidth+offset, temp);
+    strcpy(pwidth+offset, temp);
 }
 
 bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr)
@@ -675,7 +697,7 @@ bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr)
             break;
 
         case wxPAT_CHAR:
-            p->pad_char = va_arg(argptr, int);  // char is promoted to int when passed through '...'
+            p->pad_char = (char)va_arg(argptr, int);  // char is promoted to int when passed through '...'
             break;
         case wxPAT_WCHAR:
             p->pad_wchar = (wchar_t)va_arg(argptr, int);  // char is promoted to int when passed through '...'
@@ -711,17 +733,9 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
     // buffer to avoid dynamic memory allocation each time for small strings;
     // note that this buffer is used only to hold results of number formatting,
     // %s directly writes user's string in buf, without using szScratch
-#define wxSCRATCH_BUFFER_SIZE       512
-
-    wxChar szScratch[wxSCRATCH_BUFFER_SIZE];
+    char szScratch[wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN];
     size_t lenScratch = 0, lenCur = 0;
 
-#if wxUSE_UNICODE
-#define system_sprintf(buff, flags, data)      ::swprintf(buff, wxSCRATCH_BUFFER_SIZE, flags, data)
-#else
-#define system_sprintf                         ::sprintf
-#endif
-
 #define APPEND_CH(ch) \
                 { \
                     if ( lenCur == lenMax ) \
@@ -741,33 +755,33 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
     switch ( m_type )
     {
         case wxPAT_INT:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_int);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_int);
             break;
 
         case wxPAT_LONGINT:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_longint);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_longint);
             break;
 
 #if SIZEOF_LONG_LONG
         case wxPAT_LONGLONGINT:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_longlongint);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_longlongint);
             break;
 #endif // SIZEOF_LONG_LONG
 
         case wxPAT_SIZET:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_sizet);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_sizet);
             break;
 
         case wxPAT_LONGDOUBLE:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_longdouble);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_longdouble);
             break;
 
         case wxPAT_DOUBLE:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_double);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_double);
             break;
 
         case wxPAT_POINTER:
-            lenScratch = system_sprintf(szScratch, m_szFlags, p->pad_pointer);
+            lenScratch = system_sprintf(szScratch, wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN, m_szFlags, p->pad_pointer);
             break;
 
         case wxPAT_CHAR:
@@ -921,9 +935,9 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
         case wxPAT_LONGDOUBLE:
         case wxPAT_DOUBLE:
         case wxPAT_POINTER:
-#if wxUSE_STRUTILS
+            wxASSERT(lenScratch < wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN);
+#if !wxUSE_UNICODE
             {
-                wxASSERT(lenScratch >= 0 && lenScratch < wxSCRATCH_BUFFER_SIZE);
                 if (lenMax < lenScratch)
                 {
                     // fill output buffer and then return -1
@@ -935,7 +949,39 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
             }
 #else
             {
-                APPEND_STR(szScratch);
+                // Copy the char scratch to the wide output. This requires
+                // conversion, but we can optimise by making use of the fact
+                // that we are formatting numbers, this should mean only 7-bit
+                // ascii characters are involved.
+                wxChar *bufptr = buf;
+                const wxChar *bufend = buf + lenMax;
+                const char *scratchptr = szScratch;
+
+                // Simply copy each char to a wxChar, stopping on the first
+                // null or non-ascii byte. Checking '(signed char)*scratchptr
+                // > 0' is an extra optimisation over '*scratchptr != 0 &&
+                // isascii(*scratchptr)', though it assumes signed char is
+                // 8-bit 2 complement.
+                while ((signed char)*scratchptr > 0 && bufptr != bufend)
+                    *bufptr++ = *scratchptr++;
+
+                if (bufptr == bufend)
+                    return -1;
+
+                lenCur += bufptr - buf;
+
+                // check if the loop stopped on a non-ascii char, if yes then
+                // fall back to wxMB2WX
+                if (*scratchptr)
+                {
+                    size_t len = wxMB2WX(bufptr, scratchptr, bufend - bufptr);
+
+                    if (len && len != (size_t)(-1))
+                        if (bufptr[len - 1])
+                            return -1;
+                        else
+                            lenCur += len;
+                }
             }
 #endif
             break;