]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/utilscmn.cpp
ANSI+Unicode compatibility fixes to wxArrayString
[wxWidgets.git] / src / common / utilscmn.cpp
index fdda0694d9103064310b468187270e78be9f88ed..21895181cb9d43ba640d1a2f30f6e3eaa82d5863 100644 (file)
@@ -72,7 +72,6 @@
     #include "wx/colordlg.h"
     #include "wx/fontdlg.h"
     #include "wx/notebook.h"
-    #include "wx/frame.h"
     #include "wx/statusbr.h"
 #endif // wxUSE_GUI
 
@@ -97,6 +96,7 @@
 #if defined(__WXMSW__)
     #include "wx/msw/private.h"
     #include "wx/msw/registry.h"
+    #include <shellapi.h> // needed for SHELLEXECUTEINFO
 #endif
 
 #if wxUSE_BASE
 // implementation
 // ============================================================================
 
-#if WXWIN_COMPATIBILITY_2_4
-
-wxChar *
-copystring (const wxChar *s)
-{
-    if (s == NULL) s = wxEmptyString;
-    size_t len = wxStrlen (s) + 1;
-
-    wxChar *news = new wxChar[len];
-    memcpy (news, s, len * sizeof(wxChar));    // Should be the fastest
-
-    return news;
-}
-
-#endif // WXWIN_COMPATIBILITY_2_4
-
-// ----------------------------------------------------------------------------
-// String <-> Number conversions (deprecated)
-// ----------------------------------------------------------------------------
-
-#if WXWIN_COMPATIBILITY_2_4
-
-WXDLLIMPEXP_DATA_BASE(const wxChar *) wxFloatToStringStr = wxT("%.2f");
-WXDLLIMPEXP_DATA_BASE(const wxChar *) wxDoubleToStringStr = wxT("%.2f");
-
-void
-StringToFloat (const wxChar *s, float *number)
-{
-    if (s && *s && number)
-        *number = (float) wxStrtod (s, (wxChar **) NULL);
-}
-
-void
-StringToDouble (const wxChar *s, double *number)
-{
-    if (s && *s && number)
-        *number = wxStrtod (s, (wxChar **) NULL);
-}
-
-wxChar *
-FloatToString (float number, const wxChar *fmt)
-{
-    static wxChar buf[256];
-
-    wxSprintf (buf, fmt, number);
-    return buf;
-}
-
-wxChar *
-DoubleToString (double number, const wxChar *fmt)
-{
-    static wxChar buf[256];
-
-    wxSprintf (buf, fmt, number);
-    return buf;
-}
-
-void
-StringToInt (const wxChar *s, int *number)
-{
-    if (s && *s && number)
-        *number = (int) wxStrtol (s, (wxChar **) NULL, 10);
-}
-
-void
-StringToLong (const wxChar *s, long *number)
-{
-    if (s && *s && number)
-        *number = wxStrtol (s, (wxChar **) NULL, 10);
-}
-
-wxChar *
-IntToString (int number)
-{
-    static wxChar buf[20];
-
-    wxSprintf (buf, wxT("%d"), number);
-    return buf;
-}
-
-wxChar *
-LongToString (long number)
-{
-    static wxChar buf[20];
-
-    wxSprintf (buf, wxT("%ld"), number);
-    return buf;
-}
-
-#endif // WXWIN_COMPATIBILITY_2_4
-
 // Array used in DecToHex conversion routine.
 static wxChar hexArray[] = wxT("0123456789ABCDEF");
 
@@ -231,6 +140,15 @@ void wxDecToHex(int dec, wxChar *buf)
     buf[2] = 0;
 }
 
+// Convert decimal integer to 2 characters
+void wxDecToHex(int dec, char* ch1, char* ch2)
+{
+    int firstDigit = (int)(dec/16.0);
+    int secondDigit = (int)(dec - (firstDigit*16.0));
+    (*ch1) = (char) hexArray[firstDigit];
+    (*ch2) = (char) hexArray[secondDigit];
+}
+
 // Convert decimal integer to 2-character hex string
 wxString wxDecToHex(int dec)
 {
@@ -287,20 +205,219 @@ wxString wxGetDataDir()
     return dir;
 }
 
-int wxGetOsVersion(int *verMaj, int *verMin)
+bool wxIsPlatformLittleEndian()
+{
+    // Are we little or big endian? This method is from Harbison & Steele.
+    union
+    {
+        long l;
+        char c[sizeof(long)];
+    } u;
+    u.l = 1;
+
+    return u.c[0] == 1;
+}
+
+
+/*
+ * Class to make it easier to specify platform-dependent values
+ */
+
+wxArrayInt*  wxPlatform::sm_customPlatforms = NULL;
+
+void wxPlatform::Copy(const wxPlatform& platform)
+{
+    m_longValue = platform.m_longValue;
+    m_doubleValue = platform.m_doubleValue;
+    m_stringValue = platform.m_stringValue;
+}
+
+wxPlatform wxPlatform::If(int platform, long value)
+{
+    if (Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform wxPlatform::IfNot(int platform, long value)
+{
+    if (!Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform& wxPlatform::ElseIf(int platform, long value)
+{
+    if (Is(platform))
+        m_longValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::ElseIfNot(int platform, long value)
+{
+    if (!Is(platform))
+        m_longValue = value;
+    return *this;
+}
+
+wxPlatform wxPlatform::If(int platform, double value)
+{
+    if (Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform wxPlatform::IfNot(int platform, double value)
+{
+    if (!Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform& wxPlatform::ElseIf(int platform, double value)
+{
+    if (Is(platform))
+        m_doubleValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::ElseIfNot(int platform, double value)
+{
+    if (!Is(platform))
+        m_doubleValue = value;
+    return *this;
+}
+
+wxPlatform wxPlatform::If(int platform, const wxString& value)
+{
+    if (Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform wxPlatform::IfNot(int platform, const wxString& value)
+{
+    if (!Is(platform))
+        return wxPlatform(value);
+    else
+        return wxPlatform();
+}
+
+wxPlatform& wxPlatform::ElseIf(int platform, const wxString& value)
+{
+    if (Is(platform))
+        m_stringValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::ElseIfNot(int platform, const wxString& value)
+{
+    if (!Is(platform))
+        m_stringValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::Else(long value)
+{
+    m_longValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::Else(double value)
+{
+    m_doubleValue = value;
+    return *this;
+}
+
+wxPlatform& wxPlatform::Else(const wxString& value)
+{
+    m_stringValue = value;
+    return *this;
+}
+
+void wxPlatform::AddPlatform(int platform)
+{
+    if (!sm_customPlatforms)
+        sm_customPlatforms = new wxArrayInt;
+    sm_customPlatforms->Add(platform);
+}
+
+void wxPlatform::ClearPlatforms()
 {
-    // we want this function to work even if there is no wxApp
-    wxConsoleAppTraits traitsConsole;
-    wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
-    if ( ! traits )
-        traits = &traitsConsole;
-
-    wxToolkitInfo& info = traits->GetToolkitInfo();
-    if ( verMaj )
-        *verMaj = info.versionMajor;
-    if ( verMin )
-        *verMin = info.versionMinor;
-    return info.os;
+    delete sm_customPlatforms;
+    sm_customPlatforms = NULL;
+}
+
+/// Function for testing current platform
+
+bool wxPlatform::Is(int platform)
+{
+#ifdef __WXMSW__
+    if (platform == wxOS_WINDOWS)
+        return true;
+#endif
+#ifdef __WXWINCE__
+    if (platform == wxOS_WINDOWS_CE)
+        return true;
+#endif
+
+#if 0
+
+// FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
+
+#if defined(__WXWINCE__) && defined(__POCKETPC__)
+    if (platform == wxWinPocketPC)
+        return true;
+#endif
+#if defined(__WXWINCE__) && defined(__SMARTPHONE__)
+    if (platform == wxWinSmartPhone)
+        return true;
+#endif
+
+#endif
+
+#ifdef __WXGTK__
+    if (platform == wxPORT_GTK)
+        return true;
+#endif
+#ifdef __WXMAC__
+    if (platform == wxPORT_MAC)
+        return true;
+#endif
+#ifdef __WXX11__
+    if (platform == wxPORT_X11)
+        return true;
+#endif
+#ifdef __UNIX__
+    if (platform == wxOS_UNIX)
+        return true;
+#endif
+#ifdef __WXMGL__
+    if (platform == wxPORT_MGL)
+        return true;
+#endif
+#ifdef __OS2__
+    if (platform == wxOS_OS2)
+        return true;
+#endif
+#ifdef __WXPM__
+    if (platform == wxPORT_PM)
+        return true;
+#endif
+#ifdef __WXCOCOA__
+    if (platform == wxPORT_MAC)
+        return true;
+#endif
+
+    if (sm_customPlatforms && sm_customPlatforms->Index(platform) != wxNOT_FOUND)
+        return true;
+
+    return false;
 }
 
 // ----------------------------------------------------------------------------
@@ -448,24 +565,27 @@ static bool ReadAll(wxInputStream *is, wxArrayString& output)
 
     wxTextInputStream tis(*is);
 
-    bool cont = true;
-    while ( cont )
+    for ( ;; )
     {
         wxString line = tis.ReadLine();
+
+        // check for EOF before other errors as it's not really an error
         if ( is->Eof() )
+        {
+            // add the last, possibly incomplete, line
+            if ( !line.empty() )
+                output.Add(line);
             break;
+        }
 
+        // any other error is fatal
         if ( !*is )
-        {
-            cont = false;
-        }
-        else
-        {
-            output.Add(line);
-        }
+            return false;
+
+        output.Add(line);
     }
 
-    return cont;
+    return true;
 }
 #endif // wxUSE_STREAMS
 
@@ -519,18 +639,75 @@ long wxExecute(const wxString& command,
     return wxDoExecuteWithCapture(command, output, &error, flags);
 }
 
+// ----------------------------------------------------------------------------
+// wxApp::Yield() wrappers for backwards compatibility
+// ----------------------------------------------------------------------------
+
+bool wxYield()
+{
+    return wxTheApp && wxTheApp->Yield();
+}
+
+bool wxYieldIfNeeded()
+{
+    return wxTheApp && wxTheApp->Yield(true);
+}
+
+// Id generation
+static long wxCurrentId = 100;
+
+long wxNewId()
+{
+    // skip the part of IDs space that contains hard-coded values:
+    if (wxCurrentId == wxID_LOWEST)
+        wxCurrentId = wxID_HIGHEST + 1;
+
+    return wxCurrentId++;
+}
+
+long
+wxGetCurrentId(void) { return wxCurrentId; }
+
+void
+wxRegisterId (long id)
+{
+  if (id >= wxCurrentId)
+    wxCurrentId = id + 1;
+}
+
+#endif // wxUSE_BASE
+
+// ============================================================================
+// GUI-only functions from now on
+// ============================================================================
+
+#if wxUSE_GUI
+
 // ----------------------------------------------------------------------------
 // Launch default browser
 // ----------------------------------------------------------------------------
 
+#ifdef __WXCOCOA__
+// Private method in Objective-C++ source file.
+bool wxCocoaLaunchDefaultBrowser(const wxString& url, int flags);
+#endif
+
 bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
 {
     wxUnusedVar(flags);
 
     // set the scheme of url to http if it does not have one
+    // RR: This doesn't work if the url is just a local path
     wxString url(urlOrig);
-    if ( !wxURI(url).HasScheme() )
-        url.Prepend(wxT("http://"));
+    wxURI uri(url);
+    if ( !uri.HasScheme() )
+    {
+        if (wxFileExists(urlOrig))
+            url.Prepend( wxT("file://") );
+        else
+            url.Prepend(wxT("http://"));
+    }
+
 
 #if defined(__WXMSW__)
 
@@ -539,7 +716,13 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
     {
         // ShellExecuteEx() opens the URL in an existing window by default so
         // we can't use it if we need a new window
-        wxRegKey key(wxRegKey::HKCR, url.BeforeFirst(':') + _T("\\shell\\open"));
+        wxRegKey key(wxRegKey::HKCR, uri.GetScheme() + _T("\\shell\\open"));
+        if ( !key.Exists() )
+        {
+            // try default browser, it must be registered at least for http URLs
+            key.SetName(wxRegKey::HKCR, _T("http\\shell\\open"));
+        }
+
         if ( key.Exists() )
         {
             wxRegKey keyDDE(key, wxT("DDEExec"));
@@ -614,11 +797,15 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
 #endif // __WXDEBUG__
         return true;
     }
+#elif defined(__WXCOCOA__)
+    // NOTE: We need to call the real implementation from src/cocoa/utils.mm
+    // because the code must use Objective-C features.
+    return wxCocoaLaunchDefaultBrowser(url, flags);
 #elif defined(__WXMAC__)
     OSStatus err;
     ICInstance inst;
-    SInt32 startSel;
-    SInt32 endSel;
+    long int startSel;
+    long int endSel;
 
     err = ICStart(&inst, 'STKA'); // put your app creator code here
     if (err == noErr)
@@ -630,7 +817,7 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
         {
             ConstStr255Param hint = 0;
             startSel = 0;
-            endSel = url.Length();
+            endSel = url.length();
             err = ICLaunchURL(inst, hint, url.fn_str(), endSel, &startSel, &endSel);
             if (err != noErr)
                 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err);
@@ -643,11 +830,43 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
         wxLogDebug(wxT("ICStart error %d"), (int) err);
         return false;
     }
-#elif wxUSE_MIMETYPE
-    // Non-windows way
+#else
+    // (non-Mac, non-MSW)
+
+#ifdef __UNIX__
+
+    wxString desktop = wxTheApp->GetTraits()->GetDesktopEnvironment();
+
+    // GNOME and KDE desktops have some applications which should be always installed
+    // together with their main parts, which give us the
+    if (desktop == wxT("GNOME"))
+    {
+        wxArrayString errors;
+        wxArrayString output;
+
+        // gconf will tell us the path of the application to use as browser
+        long res = wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
+                              output, errors, wxEXEC_NODISABLE );
+        if (res >= 0 && errors.GetCount() == 0)
+        {
+            wxString cmd = output[0];
+            cmd << _T(' ') << url;
+            if (wxExecute(cmd))
+                return true;
+        }
+    }
+    else if (desktop == wxT("KDE"))
+    {
+        // kfmclient directly opens the given URL
+        if (wxExecute(wxT("kfmclient openURL ") + url))
+            return true;
+    }
+#endif
+
     bool ok = false;
     wxString cmd;
 
+#if wxUSE_MIMETYPE
     wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(_T("html"));
     if ( ft )
     {
@@ -657,6 +876,7 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
         ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
         delete ft;
     }
+#endif // wxUSE_MIMETYPE
 
     if ( !ok || cmd.empty() )
     {
@@ -681,59 +901,18 @@ bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags)
     return false;
 }
 
-// ----------------------------------------------------------------------------
-// wxApp::Yield() wrappers for backwards compatibility
-// ----------------------------------------------------------------------------
-
-bool wxYield()
-{
-    return wxTheApp && wxTheApp->Yield();
-}
-
-bool wxYieldIfNeeded()
-{
-    return wxTheApp && wxTheApp->Yield(true);
-}
-
-#endif // wxUSE_BASE
-
-// ============================================================================
-// GUI-only functions from now on
-// ============================================================================
-
-#if wxUSE_GUI
-
-// Id generation
-static long wxCurrentId = 100;
-
-long wxNewId()
-{
-    // skip the part of IDs space that contains hard-coded values:
-    if (wxCurrentId == wxID_LOWEST)
-        wxCurrentId = wxID_HIGHEST + 1;
-
-    return wxCurrentId++;
-}
-
-long
-wxGetCurrentId(void) { return wxCurrentId; }
-
-void
-wxRegisterId (long id)
-{
-  if (id >= wxCurrentId)
-    wxCurrentId = id + 1;
-}
-
-#if wxUSE_MENUS
-
 // ----------------------------------------------------------------------------
 // Menu accelerators related functions
 // ----------------------------------------------------------------------------
 
 wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
 {
+#if wxUSE_MENUS
     wxString s = wxMenuItem::GetLabelFromText(in);
+#else
+    wxString str(in);
+    wxString s = wxStripMenuCodes(str);
+#endif // wxUSE_MENUS
     if ( out )
     {
         // go smash their buffer if it's not big enough - I love char * params
@@ -741,7 +920,6 @@ wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
     }
     else
     {
-        // MYcopystring - for easier search...
         out = new wxChar[s.length() + 1];
         wxStrcpy(out, s.c_str());
     }
@@ -749,8 +927,10 @@ wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
     return out;
 }
 
-wxString wxStripMenuCodes(const wxString& in)
+wxString wxStripMenuCodes(const wxString& in, int flags)
 {
+    wxASSERT_MSG( flags, _T("this is useless to call without any flags") );
+
     wxString out;
 
     size_t len = in.length();
@@ -759,7 +939,7 @@ wxString wxStripMenuCodes(const wxString& in)
     for ( size_t n = 0; n < len; n++ )
     {
         wxChar ch = in[n];
-        if ( ch == _T('&') )
+        if ( (flags & wxStrip_Mnemonics) && ch == _T('&') )
         {
             // skip it, it is used to introduce the accel char (or to quote
             // itself in which case it should still be skipped): note that it
@@ -774,7 +954,7 @@ wxString wxStripMenuCodes(const wxString& in)
                 ch = in[n];
             }
         }
-        else if ( ch == _T('\t') )
+        else if ( (flags & wxStrip_Accel) && ch == _T('\t') )
         {
             // everything after TAB is accel string, exit the loop
             break;
@@ -786,8 +966,6 @@ wxString wxStripMenuCodes(const wxString& in)
     return out;
 }
 
-#endif // wxUSE_MENUS
-
 // ----------------------------------------------------------------------------
 // Window search functions
 // ----------------------------------------------------------------------------
@@ -822,12 +1000,12 @@ int
 wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
 {
 #if wxUSE_MENUS
-  wxMenuBar *menuBar = frame->GetMenuBar ();
-  if ( menuBar )
-      return menuBar->FindMenuItem (menuString, itemString);
+    wxMenuBar *menuBar = frame->GetMenuBar ();
+    if ( menuBar )
+        return menuBar->FindMenuItem (menuString, itemString);
 #endif // wxUSE_MENUS
 
-  return wxNOT_FOUND;
+    return wxNOT_FOUND;
 }
 
 // Try to find the deepest child that contains 'pt'.
@@ -869,16 +1047,16 @@ wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
 
     wxPoint pos = win->GetPosition();
     wxSize sz = win->GetSize();
-    if (win->GetParent())
+    if ( !win->IsTopLevel() && win->GetParent() )
     {
         pos = win->GetParent()->ClientToScreen(pos);
     }
 
     wxRect rect(pos, sz);
-    if (rect.Inside(pt))
+    if (rect.Contains(pt))
         return win;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
@@ -1004,7 +1182,7 @@ wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit, const wx
 
     wxColour colRet;
     wxColourDialog dialog(parent, &data);
-    if (!caption.IsEmpty())
+    if (!caption.empty())
         dialog.SetTitle(caption);
     if ( dialog.ShowModal() == wxID_OK )
     {
@@ -1029,7 +1207,7 @@ wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxStrin
 
     wxFont fontRet;
     wxFontDialog dialog(parent, data);
-    if (!caption.IsEmpty())
+    if (!caption.empty())
         dialog.SetTitle(caption);
     if ( dialog.ShowModal() == wxID_OK )
     {