]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/accelcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / accelcmn.cpp
index a038c58d206b94e5be2cd2bb610d2bd63fddb86c..2b3165ec373150f250f4e6d7fd5c357b76f08d8a 100644 (file)
 #if wxUSE_ACCEL
 
 #ifndef WX_PRECOMP
-    #include "wx/string.h"
     #include "wx/accel.h"
+    #include "wx/string.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/crt.h"
 #endif //WX_PRECOMP
 
+wxAcceleratorTable wxNullAcceleratorTable;
+
 // ============================================================================
 // wxAcceleratorEntry implementation
 // ============================================================================
@@ -37,7 +42,7 @@
 static const struct wxKeyName
 {
     wxKeyCode code;
-    const wxChar *name;
+    const char *name;
 } wxKeyNames[] =
 {
     { WXK_DELETE, wxTRANSLATE("DEL") },
@@ -111,7 +116,7 @@ static const struct wxKeyName
 //
 // as accels can be either translated or not, check for both possibilities and
 // also compare case-insensitively as the key names case doesn't count
-static inline bool CompareAccelString(const wxString& str, const wxChar *accel)
+static inline bool CompareAccelString(const wxString& str, const char *accel)
 {
     return str.CmpNoCase(accel) == 0
 #if wxUSE_INTL
@@ -125,7 +130,7 @@ static inline bool CompareAccelString(const wxString& str, const wxChar *accel)
 //
 // first and last parameter specify the valid domain for "number" part
 static int IsNumberedAccelKey(const wxString& str,
-                              const wxChar *prefix,
+                              const char *prefix,
                               wxKeyCode prefixCode,
                               unsigned first,
                               unsigned last)
@@ -142,7 +147,7 @@ static int IsNumberedAccelKey(const wxString& str,
     {
         // this must be a mistake, chances that this is a valid name of another
         // key are vanishingly small
-        wxLogDebug(_T("Invalid key string \"%s\""), str.c_str());
+        wxLogDebug(wxT("Invalid key string \"%s\""), str.c_str());
         return 0;
     }
 
@@ -155,19 +160,23 @@ wxAcceleratorEntry::ParseAccel(const wxString& text, int *flagsOut, int *keyOut)
 {
     // the parser won't like trailing spaces
     wxString label = text;
-    label.Trim(true);  // the initial \t must be preserved so don't strip leading whitespaces
+    label.Trim(true);
 
-    // check for accelerators: they are given after '\t'
+    // For compatibility with the old wx versions which accepted (and actually
+    // even required) a TAB character in the string passed to this function we
+    // ignore anything up to the first TAB. Notice however that the correct
+    // input consists of just the accelerator itself and nothing else, this is
+    // done for compatibility and compatibility only.
     int posTab = label.Find(wxT('\t'));
     if ( posTab == wxNOT_FOUND )
-    {
-        return false;
-    }
+        posTab = 0;
+    else
+        posTab++;
 
     // parse the accelerator string
     int accelFlags = wxACCEL_NORMAL;
     wxString current;
-    for ( size_t n = (size_t)posTab + 1; n < label.length(); n++ )
+    for ( size_t n = (size_t)posTab; n < label.length(); n++ )
     {
         if ( (label[n] == '+') || (label[n] == '-') )
         {
@@ -177,6 +186,8 @@ wxAcceleratorEntry::ParseAccel(const wxString& text, int *flagsOut, int *keyOut)
                 accelFlags |= wxACCEL_ALT;
             else if ( CompareAccelString(current, wxTRANSLATE("shift")) )
                 accelFlags |= wxACCEL_SHIFT;
+            else if ( CompareAccelString(current, wxTRANSLATE("rawctrl")) )
+                accelFlags |= wxACCEL_RAW_CTRL;
             else // not a recognized modifier name
             {
                 // we may have "Ctrl-+", for example, but we still want to
@@ -256,7 +267,7 @@ wxAcceleratorEntry::ParseAccel(const wxString& text, int *flagsOut, int *keyOut)
     }
 
 
-    wxASSERT_MSG( keyCode, _T("logic error: should have key code here") );
+    wxASSERT_MSG( keyCode, wxT("logic error: should have key code here") );
 
     if ( flagsOut )
         *flagsOut = accelFlags;
@@ -269,9 +280,18 @@ wxAcceleratorEntry::ParseAccel(const wxString& text, int *flagsOut, int *keyOut)
 /* static */
 wxAcceleratorEntry *wxAcceleratorEntry::Create(const wxString& str)
 {
+    const wxString accelStr = str.AfterFirst('\t');
+    if ( accelStr.empty() )
+    {
+        // It's ok to pass strings not containing any accelerators at all to
+        // this function, wxMenuItem code does it and we should just return
+        // NULL in this case.
+        return NULL;
+    }
+
     int flags,
         keyCode;
-    if ( !ParseAccel(str, &flags, &keyCode) )
+    if ( !ParseAccel(accelStr, &flags, &keyCode) )
         return NULL;
 
     return new wxAcceleratorEntry(flags, keyCode);
@@ -282,26 +302,43 @@ bool wxAcceleratorEntry::FromString(const wxString& str)
     return ParseAccel(str, &m_flags, &m_keyCode);
 }
 
-wxString wxAcceleratorEntry::ToString() const
+namespace
+{
+
+wxString PossiblyLocalize(const wxString& str, bool localize)
+{
+    return localize ? wxGetTranslation(str) : str;
+}
+
+}
+
+wxString wxAcceleratorEntry::AsPossiblyLocalizedString(bool localized) const
 {
     wxString text;
 
     int flags = GetFlags();
     if ( flags & wxACCEL_ALT )
-        text += _("Alt-");
+        text += PossiblyLocalize(wxTRANSLATE("Alt+"), localized);
     if ( flags & wxACCEL_CTRL )
-        text += _("Ctrl-");
+        text += PossiblyLocalize(wxTRANSLATE("Ctrl+"), localized);
     if ( flags & wxACCEL_SHIFT )
-        text += _("Shift-");
-
+        text += PossiblyLocalize(wxTRANSLATE("Shift+"), localized);
+#if defined(__WXMAC__) || defined(__WXCOCOA__)
+    if ( flags & wxACCEL_RAW_CTRL )
+        text += PossiblyLocalize(wxTRANSLATE("RawCtrl+"), localized);
+#endif
+    
     const int code = GetKeyCode();
 
     if ( code >= WXK_F1 && code <= WXK_F12 )
-        text << _("F") << code - WXK_F1 + 1;
+        text << PossiblyLocalize(wxTRANSLATE("F"), localized)
+             << code - WXK_F1 + 1;
     else if ( code >= WXK_NUMPAD0 && code <= WXK_NUMPAD9 )
-        text << _("KP_") << code - WXK_NUMPAD0;
+        text << PossiblyLocalize(wxTRANSLATE("KP_"), localized)
+             << code - WXK_NUMPAD0;
     else if ( code >= WXK_SPECIAL1 && code <= WXK_SPECIAL20 )
-        text << _("SPECIAL") << code - WXK_SPECIAL1 + 1;
+        text << PossiblyLocalize(wxTRANSLATE("SPECIAL"), localized)
+             << code - WXK_SPECIAL1 + 1;
     else // check the named keys
     {
         size_t n;
@@ -310,7 +347,7 @@ wxString wxAcceleratorEntry::ToString() const
             const wxKeyName& kn = wxKeyNames[n];
             if ( code == kn.code )
             {
-                text << wxGetTranslation(kn.name);
+                text << PossiblyLocalize(kn.name, localized);
                 break;
             }
         }
@@ -320,9 +357,11 @@ wxString wxAcceleratorEntry::ToString() const
             // must be a simple key
             if (
 #if !wxUSE_UNICODE
-                 isascii(code) &&
+                 // we can't call wxIsalnum() for non-ASCII characters in ASCII
+                 // build as they're only defined for the ASCII range (or EOF)
+                 wxIsascii(code) &&
 #endif // ANSI
-                    wxIsalnum(code) )
+                    wxIsprint(code) )
             {
                 text << (wxChar)code;
             }