X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d6a7c33aeacae9e30eca4cebdf92755a24e636bb..cc1487e53905bd534dba2099d33ac2142cec7818:/src/common/utilscmn.cpp?ds=inline diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index b98e0b2d5c..eadd15283b 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: utilscmn.cpp +// Name: src/common/utilscmn.cpp // Purpose: Miscellaneous utility functions and classes // Author: Julian Smart // Modified by: @@ -17,17 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) && !defined(__EMX__) -// Some older compilers (such as EMX) cannot handle -// #pragma interface/implementation correctly, iff -// #pragma implementation is used in _two_ translation -// units (as created by e.g. event.cpp compiled for -// libwx_base and event.cpp compiled for libwx_gui_core). -// So we must not use those pragmas for those compilers in -// such files. - #pragma implementation "utils.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -73,7 +62,7 @@ #include #include -#if !defined(__WATCOMC__) +#if !wxONLY_WATCOM_EARLIER_THAN(1,4) #if !(defined(_MSC_VER) && (_MSC_VER > 800)) #include #endif @@ -83,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 @@ -93,6 +81,13 @@ #include "wx/msw/wince/time.h" #endif +#ifdef __WXMAC__ +#include "wx/mac/private.h" +#ifndef __DARWIN__ +#include "InternetConfig.h" +#endif +#endif + #if !defined(__MWERKS__) && !defined(__WXWINCE__) #include #include @@ -100,6 +95,8 @@ #if defined(__WXMSW__) #include "wx/msw/private.h" + #include "wx/msw/registry.h" + #include // needed for SHELLEXECUTEINFO #endif #if wxUSE_BASE @@ -108,11 +105,6 @@ // common data // ---------------------------------------------------------------------------- -#if WXWIN_COMPATIBILITY_2_2 - const wxChar *wxInternalErrorStr = wxT("wxWidgets Internal Error"); - const wxChar *wxFatalErrorStr = wxT("wxWidgets Fatal Error"); -#endif // WXWIN_COMPATIBILITY_2_2 - // ============================================================================ // implementation // ============================================================================ @@ -122,13 +114,13 @@ wxChar * copystring (const wxChar *s) { - if (s == NULL) s = wxEmptyString; - size_t len = wxStrlen (s) + 1; + 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 + wxChar *news = new wxChar[len]; + memcpy (news, s, len * sizeof(wxChar)); // Should be the fastest - return news; + return news; } #endif // WXWIN_COMPATIBILITY_2_4 @@ -145,65 +137,65 @@ 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); + 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); + if (s && *s && number) + *number = wxStrtod (s, (wxChar **) NULL); } wxChar * FloatToString (float number, const wxChar *fmt) { - static wxChar buf[256]; + static wxChar buf[256]; - wxSprintf (buf, fmt, number); - return buf; + wxSprintf (buf, fmt, number); + return buf; } wxChar * DoubleToString (double number, const wxChar *fmt) { - static wxChar buf[256]; + static wxChar buf[256]; - wxSprintf (buf, fmt, number); - return buf; + wxSprintf (buf, fmt, number); + return buf; } void StringToInt (const wxChar *s, int *number) { - if (s && *s && number) - *number = (int) wxStrtol (s, (wxChar **) NULL, 10); + 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); + if (s && *s && number) + *number = wxStrtol (s, (wxChar **) NULL, 10); } wxChar * IntToString (int number) { - static wxChar buf[20]; + static wxChar buf[20]; - wxSprintf (buf, wxT("%d"), number); - return buf; + wxSprintf (buf, wxT("%d"), number); + return buf; } wxChar * LongToString (long number) { - static wxChar buf[20]; + static wxChar buf[20]; - wxSprintf (buf, wxT("%ld"), number); - return buf; + wxSprintf (buf, wxT("%ld"), number); + return buf; } #endif // WXWIN_COMPATIBILITY_2_4 @@ -214,29 +206,29 @@ static wxChar hexArray[] = wxT("0123456789ABCDEF"); // Convert 2-digit hex number to decimal int wxHexToDec(const wxString& buf) { - int firstDigit, secondDigit; + int firstDigit, secondDigit; - if (buf.GetChar(0) >= wxT('A')) - firstDigit = buf.GetChar(0) - wxT('A') + 10; - else - firstDigit = buf.GetChar(0) - wxT('0'); + if (buf.GetChar(0) >= wxT('A')) + firstDigit = buf.GetChar(0) - wxT('A') + 10; + else + firstDigit = buf.GetChar(0) - wxT('0'); - if (buf.GetChar(1) >= wxT('A')) - secondDigit = buf.GetChar(1) - wxT('A') + 10; - else - secondDigit = buf.GetChar(1) - wxT('0'); + if (buf.GetChar(1) >= wxT('A')) + secondDigit = buf.GetChar(1) - wxT('A') + 10; + else + secondDigit = buf.GetChar(1) - wxT('0'); - return (firstDigit & 0xF) * 16 + (secondDigit & 0xF ); + return (firstDigit & 0xF) * 16 + (secondDigit & 0xF ); } // Convert decimal integer to 2-character hex string void wxDecToHex(int dec, wxChar *buf) { - int firstDigit = (int)(dec/16.0); - int secondDigit = (int)(dec - (firstDigit*16.0)); - buf[0] = hexArray[firstDigit]; - buf[1] = hexArray[secondDigit]; - buf[2] = 0; + int firstDigit = (int)(dec/16.0); + int secondDigit = (int)(dec - (firstDigit*16.0)); + buf[0] = hexArray[firstDigit]; + buf[1] = hexArray[secondDigit]; + buf[2] = 0; } // Convert decimal integer to 2-character hex string @@ -311,6 +303,195 @@ int wxGetOsVersion(int *verMaj, int *verMin) return info.os; } +/* + * 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() +{ + delete sm_customPlatforms; + sm_customPlatforms = NULL; +} + +/// Function for testing current platform + +bool wxPlatform::Is(int platform) +{ +#ifdef __WXMSW__ + if (platform == wxMSW) + return true; +#endif +#ifdef __WXWINCE__ + if (platform == wxWinCE) + return true; +#endif +#if defined(__WXWINCE__) && defined(__POCKETPC__) + if (platform == wxWinPocketPC) + return true; +#endif +#if defined(__WXWINCE__) && defined(__SMARTPHONE__) + if (platform == wxWinSmartPhone) + return true; +#endif +#ifdef __WXGTK__ + if (platform == wxGTK) + return true; +#endif +#ifdef __WXMAC__ + if (platform == wxMac) + return true; +#endif +#ifdef __WXX11__ + if (platform == wxX11) + return true; +#endif +#ifdef __UNIX__ + if (platform == wxUnix) + return true; +#endif +#ifdef __WXMGL__ + if (platform == wxMGL) + return true; +#endif +#ifdef __WXOS2__ + if (platform == wxOS2) + return true; +#endif +#ifdef __WXCOCOA__ + if (platform == wxCocoa) + return true; +#endif + + if (sm_customPlatforms && sm_customPlatforms->Index(platform) != wxNOT_FOUND) + return true; + + return false; +} + // ---------------------------------------------------------------------------- // network and user id functions // ---------------------------------------------------------------------------- @@ -531,142 +712,162 @@ long wxExecute(const wxString& command, // Launch default browser // ---------------------------------------------------------------------------- -bool wxLaunchDefaultBrowser(const wxString& url) +bool wxLaunchDefaultBrowser(const wxString& urlOrig, int flags) { - wxString finalurl = url; + wxUnusedVar(flags); - //if it isn't a full url, try appending http:// to it - if(wxURI(url).IsReference()) - finalurl = wxString(wxT("http://")) + url; + // set the scheme of url to http if it does not have one + wxString url(urlOrig); + if ( !wxURI(url).HasScheme() ) + url.Prepend(wxT("http://")); -#ifdef __WINDOWS__ - wxString command; +#if defined(__WXMSW__) - // ShellExecute() always opens in the same window, - // so do it manually for new window (from Mahogany) - wxRegKey key(wxRegKey::HKCR, url.BeforeFirst(':') + wxT("\\shell\\open")); - if ( key.Exists() ) +#if wxUSE_IPC + if ( flags & wxBROWSER_NEW_WINDOW ) { - wxRegKey keyDDE(key, wxT("DDEExec")); - if ( keyDDE.Exists() ) + // 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")); + if ( key.Exists() ) { - wxString ddeTopic = wxRegKey(keyDDE, wxT("topic")); - - // we only know the syntax of WWW_OpenURL DDE request - if ( ddeTopic == wxT("WWW_OpenURL") ) - { - wxString ddeCmd = keyDDE; - - // this is a bit naive but should work as -1 can't appear - // elsewhere in the DDE topic, normally - if ( ddeCmd.Replace(wxT("-1"), wxT("0"), - FALSE /* only first occurence */) == 1 ) - { - // and also replace the parameters - if ( ddeCmd.Replace(wxT("%1"), url, FALSE) == 1 ) - { - // magic incantation understood by wxMSW - command << wxT("WX_DDE#") - << wxRegKey(key, wxT("command")).QueryDefaultValue() << wxT('#') - << wxRegKey(keyDDE, wxT("application")).QueryDefaultValue() - << wxT('#') << ddeTopic << wxT('#') - << ddeCmd; - } - } - } + wxRegKey keyDDE(key, wxT("DDEExec")); + if ( keyDDE.Exists() ) + { + const wxString ddeTopic = wxRegKey(keyDDE, wxT("topic")); + + // we only know the syntax of WWW_OpenURL DDE request for IE, + // optimistically assume that all other browsers are compatible + // with it + wxString ddeCmd; + bool ok = ddeTopic == wxT("WWW_OpenURL"); + if ( ok ) + { + ddeCmd = keyDDE.QueryDefaultValue(); + ok = !ddeCmd.empty(); + } + + if ( ok ) + { + // for WWW_OpenURL, the index of the window to open the URL + // in is -1 (meaning "current") by default, replace it with + // 0 which means "new" (see KB article 160957) + ok = ddeCmd.Replace(wxT("-1"), wxT("0"), + false /* only first occurence */) == 1; + } + + if ( ok ) + { + // and also replace the parameters: the topic should + // contain a placeholder for the URL + ok = ddeCmd.Replace(wxT("%1"), url, false) == 1; + } + + if ( ok ) + { + // try to send it the DDE request now but ignore the errors + wxLogNull noLog; + + const wxString ddeServer = wxRegKey(keyDDE, wxT("application")); + if ( wxExecuteDDE(ddeServer, ddeTopic, ddeCmd) ) + return true; + + // this is not necessarily an error: maybe browser is + // simply not running, but no matter, in any case we're + // going to launch it using ShellExecuteEx() below now and + // we shouldn't try to open a new window if we open a new + // browser anyhow + } + } } } +#endif // wxUSE_IPC - //Try wxExecute - if it doesn't work or the regkey stuff - //above failed, fallback to opening the file in the same - //browser window - if ( command.empty() || wxExecute(command) == -1) - { - // CYGWIN and MINGW may have problems - so load ShellExecute - // dynamically - typedef HINSTANCE (*LPShellExecute)(HWND hwnd, const wxChar* lpOperation, - const wxChar* lpFile, - const wxChar* lpParameters, - const wxChar* lpDirectory, - INT nShowCmd); - - HINSTANCE hShellDll = ::LoadLibrary(wxT("shell32.dll")); - if(hShellDll == NULL) - return false; - - LPShellExecute lpShellExecute = - (LPShellExecute) ::GetProcAddress(hShellDll, - wxString::Format(wxT("ShellExecute%s"), -#ifdef __WXUNICODE__ - wxT("W") -#else - wxT("A") -#endif - ) - ); - if(lpShellExecute == NULL) - return false; - - // Windows sometimes doesn't open the browser correctly when using mime - // types, so do ShellExecute - i.e. start (from James Carroll) - unsigned int nResult = (int) (*lpShellExecute)(NULL, NULL, finalurl.c_str(), - NULL, wxT(""), SW_SHOWNORMAL); - - // Unload Shell32.dll - ::FreeLibrary(hShellDll); - - // Hack for Firefox (returns file not found for some reason) - // from Angelo Mandato's wxHyperlinksCtrl - // HINSTANCE_ERROR == 32 - if (nResult <= HINSTANCE_ERROR && nResult != SE_ERR_FNF) - return false; - - # ifdef __WXDEBUG__ - // Log something if SE_ERR_FNF happens - if(nResult == SE_ERR_FNF) - wxLogDebug(wxT("Got SE_ERR_FNF from ShellExecute - maybe FireFox")); - # endif - } + WinStruct sei; + sei.lpFile = url.c_str(); + sei.lpVerb = _T("open"); + sei.nShow = SW_SHOWNORMAL; -#else -#if wxUSE_MIMETYPE - // Non-windows way - wxFileType *ft = - wxTheMimeTypesManager->GetFileTypeFromExtension (_T("html")); - if (!ft) - { - wxLogError(_T("No default application can open .html extension")); - return false; - } - - wxString mt; - ft->GetMimeType(&mt); - - wxString cmd; - bool ok = - ft->GetOpenCommand (&cmd, - wxFileType::MessageParameters (finalurl.c_str(), - _T(""))); - delete ft; - - if (ok) + ::ShellExecuteEx(&sei); + + const int nResult = (int) sei.hInstApp; + + // Firefox returns file not found for some reason, so make an exception + // for it + if ( nResult > 32 || nResult == SE_ERR_FNF ) { - if( wxExecute (cmd, wxEXEC_ASYNC) == -1 ) +#ifdef __WXDEBUG__ + // Log something if SE_ERR_FNF happens + if ( nResult == SE_ERR_FNF ) + wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?")); +#endif // __WXDEBUG__ + return true; + } +#elif defined(__WXMAC__) + OSStatus err; + ICInstance inst; + SInt32 startSel; + SInt32 endSel; + + err = ICStart(&inst, 'STKA'); // put your app creator code here + if (err == noErr) + { +#if !TARGET_CARBON + err = ICFindConfigFile(inst, 0, NULL); +#endif + if (err == noErr) { - wxLogError(_T("Failed to launch application for wxLaunchDefaultBrowser")); - return false; + ConstStr255Param hint = 0; + startSel = 0; + endSel = url.length(); + err = ICLaunchURL(inst, hint, url.fn_str(), endSel, &startSel, &endSel); + if (err != noErr) + wxLogDebug(wxT("ICLaunchURL error %d"), (int) err); } + ICStop(inst); + return true; } else - return false; -#else - return false; -#endif //!wxUSE_MIMETYPE + { + wxLogDebug(wxT("ICStart error %d"), (int) err); + return false; + } +#elif wxUSE_MIMETYPE + // Non-windows way + bool ok = false; + wxString cmd; -#endif + wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(_T("html")); + if ( ft ) + { + wxString mt; + ft->GetMimeType(&mt); - //success - hopefully - return true; + ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url)); + delete ft; + } + + if ( !ok || cmd.empty() ) + { + // fallback to checking for the BROWSER environment variable + cmd = wxGetenv(wxT("BROWSER")); + if ( !cmd.empty() ) + cmd << _T(' ') << url; + } + + ok = ( !cmd.empty() && wxExecute(cmd) ); + if (ok) + return ok; + + // no file type for HTML extension + wxLogError(_T("No default application configured for HTML files.")); + +#endif // !wxUSE_MIMETYPE && !__WXMSW__ + + wxLogSysError(_T("Failed to open URL \"%s\" in default browser."), + url.c_str()); + + return false; } // ---------------------------------------------------------------------------- @@ -713,15 +914,18 @@ wxRegisterId (long id) 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 @@ -774,8 +978,6 @@ wxString wxStripMenuCodes(const wxString& in) return out; } -#endif // wxUSE_MENUS - // ---------------------------------------------------------------------------- // Window search functions // ---------------------------------------------------------------------------- @@ -810,12 +1012,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'. @@ -857,7 +1059,7 @@ 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); } @@ -865,8 +1067,8 @@ wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt) wxRect rect(pos, sz); if (rect.Inside(pt)) return win; - else - return NULL; + + return NULL; } wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt) @@ -981,7 +1183,7 @@ wxString wxGetPasswordFromUser(const wxString& message, #if wxUSE_COLOURDLG -wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit) +wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit, const wxString& caption) { wxColourData data; data.SetChooseFull(true); @@ -992,6 +1194,8 @@ wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit) wxColour colRet; wxColourDialog dialog(parent, &data); + if (!caption.empty()) + dialog.SetTitle(caption); if ( dialog.ShowModal() == wxID_OK ) { colRet = dialog.GetColourData().GetColour(); @@ -1005,7 +1209,7 @@ wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit) #if wxUSE_FONTDLG -wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit) +wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxString& caption) { wxFontData data; if ( fontInit.Ok() ) @@ -1015,6 +1219,8 @@ wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit) wxFont fontRet; wxFontDialog dialog(parent, data); + if (!caption.empty()) + dialog.SetTitle(caption); if ( dialog.ShowModal() == wxID_OK ) { fontRet = dialog.GetFontData().GetChosenFont(); @@ -1109,4 +1315,3 @@ bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) ) #endif // !wxGTK #endif // wxUSE_GUI -