]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wxchar.cpp
!__WX_DC_BLIT_FIXED__ case
[wxWidgets.git] / src / common / wxchar.cpp
index c77dc9cec371ec528ff6eaed25156aa71478180c..10bcd27cb4d7007742c2336e05f97922aaa84347 100644 (file)
@@ -20,6 +20,8 @@
     #pragma hdrstop
 #endif
 
     #pragma hdrstop
 #endif
 
+#include "wx/wxchar.h"
+
 #define _ISOC9X_SOURCE 1 // to get vsscanf()
 #define _BSD_SOURCE    1 // to still get strdup()
 
 #define _ISOC9X_SOURCE 1 // to get vsscanf()
 #define _BSD_SOURCE    1 // to still get strdup()
 
 #endif
 
 #ifndef WX_PRECOMP
 #endif
 
 #ifndef WX_PRECOMP
-    #include "wx/wxchar.h"
     #include "wx/string.h"
     #include "wx/hash.h"
     #include "wx/string.h"
     #include "wx/hash.h"
+    #include "wx/utils.h"     // for wxMin and wxMax
+    #include "wx/log.h"
 #endif
 #endif
-  #include "wx/utils.h"     // for wxMin and wxMax
 
 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
   #include <windef.h>
 
 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
   #include <windef.h>
@@ -185,6 +187,70 @@ bool WXDLLEXPORT wxOKlibc()
 // some limits of our implementation
 #define wxMAX_SVNPRINTF_ARGUMENTS         16
 #define wxMAX_SVNPRINTF_FLAGBUFFER_LEN    32
 // some limits of our implementation
 #define wxMAX_SVNPRINTF_ARGUMENTS         16
 #define wxMAX_SVNPRINTF_FLAGBUFFER_LEN    32
+#define wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN   512
+
+
+// wxVsnprintf() needs to use a *system* implementation of swnprintf()
+// in order to perform some internal tasks.
+// NB: we cannot just use wxSnprintf() because for some systems it maybe
+//     implemented later in this file using wxVsnprintf() and that would
+//     result in an endless recursion and thus in a stack overflow
+#if wxUSE_UNICODE
+    #if defined(__WINDOWS__) && !defined(HAVE_SWPRINTF)
+        // all compilers under Windows should have swprintf()
+        #define HAVE_SWPRINTF
+    #endif
+
+    // NB: MSVC 6 has only non-standard swprintf() declaration and while MSVC 7
+    //     and 7.1 do have the standard one, it's completely broken unless
+    //     /Zc:wchar_t is used while the other one works so use it instead, and
+    //     only VC8 has a working standard-compliant swprintf()
+    #if defined(__WXWINCE__) || \
+        (defined(__VISUALC__) && __VISUALC__ < 1400) || \
+        defined(__GNUWIN32__) || \
+        defined(__BORLANDC__)
+        #ifndef HAVE_BROKEN_SWPRINTF_DECL
+            #define HAVE_BROKEN_SWPRINTF_DECL
+        #endif
+    #endif
+
+    // problem: on some systems swprintf takes the 'max' argument while on
+    // others it doesn't
+    #if defined(HAVE_BROKEN_SWPRINTF_DECL)
+        // like when using sprintf(), since 'max' is not used, wxVsnprintf()
+        // should always ensure that 'buff' is big enough for all common needs
+        #define system_sprintf(buff, max, flags, data)      \
+            ::swprintf(buff, flags, data)
+
+        #define SYSTEM_SPRINTF_IS_UNSAFE
+    #else
+        #if !defined(HAVE_SWPRINTF)
+            #error wxVsnprintf() needs a system swprintf() implementation!
+        #endif
+
+        #define system_sprintf(buff, max, flags, data)      \
+            ::swprintf(buff, max, flags, data)
+    #endif
+#else // !wxUSE_UNICODE
+    #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
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+
 
 // the conversion specifiers accepted by wxVsnprintf_
 enum wxPrintfArgType {
 
 // the conversion specifiers accepted by wxVsnprintf_
 enum wxPrintfArgType {
@@ -336,7 +402,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
 #define CHECK_PREC \
         if (in_prec && !prec_dot) \
         { \
 #define CHECK_PREC \
         if (in_prec && !prec_dot) \
         { \
-            m_szFlags[flagofs++] = '.'; \
+            m_szFlags[flagofs++] = wxT('.'); \
             prec_dot = true; \
         }
 
             prec_dot = true; \
         }
 
@@ -476,7 +542,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('X'):
                 CHECK_PREC
                 m_szFlags[flagofs++] = ch;
             case wxT('X'):
                 CHECK_PREC
                 m_szFlags[flagofs++] = ch;
-                m_szFlags[flagofs] = '\0';
+                m_szFlags[flagofs] = wxT('\0');
                 if (ilen == 0)
                     m_type = wxPAT_INT;
                 else if (ilen == -1)
                 if (ilen == 0)
                     m_type = wxPAT_INT;
                 else if (ilen == -1)
@@ -504,7 +570,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
             case wxT('G'):
                 CHECK_PREC
                 m_szFlags[flagofs++] = ch;
             case wxT('G'):
                 CHECK_PREC
                 m_szFlags[flagofs++] = ch;
-                m_szFlags[flagofs] = '\0';
+                m_szFlags[flagofs] = wxT('\0');
                 if (ilen == 2)
                     m_type = wxPAT_LONGDOUBLE;
                 else
                 if (ilen == 2)
                     m_type = wxPAT_LONGDOUBLE;
                 else
@@ -514,6 +580,8 @@ bool wxPrintfConvSpec::Parse(const wxChar *format)
 
             case wxT('p'):
                 m_type = wxPAT_POINTER;
 
             case wxT('p'):
                 m_type = wxPAT_POINTER;
+                m_szFlags[flagofs++] = ch;
+                m_szFlags[flagofs] = '\0';
                 done = true;
                 break;
 
                 done = true;
                 break;
 
@@ -612,12 +680,11 @@ void wxPrintfConvSpec::ReplaceAsteriskWith(int width)
     }
 
     // replace * with the actual integer given as 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(wxChar);
 #endif
 #endif
+    int offset = system_sprintf(pwidth, maxlen, wxT("%d"), abs(width));
 
     // restore after the expanded * what was following it
     wxStrcpy(pwidth+offset, temp);
 
     // restore after the expanded * what was following it
     wxStrcpy(pwidth+offset, temp);
@@ -675,7 +742,7 @@ bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr)
             break;
 
         case wxPAT_CHAR:
             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 '...'
             break;
         case wxPAT_WCHAR:
             p->pad_wchar = (wchar_t)va_arg(argptr, int);  // char is promoted to int when passed through '...'
@@ -711,17 +778,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
     // 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];
+    wxChar szScratch[wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN];
     size_t lenScratch = 0, lenCur = 0;
 
     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 ) \
 #define APPEND_CH(ch) \
                 { \
                     if ( lenCur == lenMax ) \
@@ -741,33 +800,33 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
     switch ( m_type )
     {
         case wxPAT_INT:
     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:
             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:
             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:
             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:
             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:
             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:
             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:
             break;
 
         case wxPAT_CHAR:
@@ -908,6 +967,10 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
             return -1;
     }
 
             return -1;
     }
 
+#ifdef HAVE_BROKEN_SWPRINTF_DECL
+    wxUnusedVar(lenScratch);    // avoid dummy warnings
+#endif
+
     // if we used system's sprintf() then we now need to append the s_szScratch
     // buffer to the given one...
     switch (m_type)
     // if we used system's sprintf() then we now need to append the s_szScratch
     // buffer to the given one...
     switch (m_type)
@@ -923,7 +986,7 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
         case wxPAT_POINTER:
 #if wxUSE_STRUTILS
             {
         case wxPAT_POINTER:
 #if wxUSE_STRUTILS
             {
-                wxASSERT(lenScratch >= 0 && lenScratch < wxSCRATCH_BUFFER_SIZE);
+                wxASSERT( /* lenScratch >= 0 && */ lenScratch < wxMAX_SVNPRINTF_SCRATCHBUFFER_LEN);
                 if (lenMax < lenScratch)
                 {
                     // fill output buffer and then return -1
                 if (lenMax < lenScratch)
                 {
                     // fill output buffer and then return -1