]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/utilscmn.cpp
Add wxLaunchDefaultBrowser, note wxGetKeyState change
[wxWidgets.git] / src / common / utilscmn.cpp
index 09369b63f3151bef006dc88747bd6543bdb3d0b7..bd2714f1eb326b5924ffa59b24c008db988240fb 100644 (file)
@@ -60,6 +60,9 @@
 
 #include "wx/process.h"
 #include "wx/txtstrm.h"
+#include "wx/uri.h"
+#include "wx/mimetype.h"
+#include "wx/config.h"
 
 #if defined(__WXWINCE__) && wxUSE_DATETIME
 #include "wx/datetime.h"
@@ -524,6 +527,143 @@ long wxExecute(const wxString& command,
     return wxDoExecuteWithCapture(command, output, &error, flags);
 }
 
+// ----------------------------------------------------------------------------
+// Launch default browser
+// ----------------------------------------------------------------------------
+
+bool wxLaunchDefaultBrowser(const wxString& url)
+{
+    wxString finalurl = url;
+
+    //if it isn't a full url, try appending http:// to it
+    if(wxURI(url).IsReference())
+        finalurl = wxString(wxT("http://")) + url;
+
+#ifdef __WINDOWS__
+    wxString command;
+
+    // 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() )
+    {
+        wxRegKey keyDDE(key, wxT("DDEExec"));
+        if ( keyDDE.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;
+                 }
+              }
+           }
+        }
+    }
+
+      //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 <url> (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
+      }
+
+#else
+    // 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) 
+    {
+        if( wxExecute (cmd, wxEXEC_ASYNC) == -1 )
+        {
+            wxLogError(_T("Failed to launch application for wxLaunchDefaultBrowser"));
+            return false;
+        }
+    }
+    else
+      return false;
+#endif
+
+    //success - hopefully
+    return true;
+}
+
 // ----------------------------------------------------------------------------
 // wxApp::Yield() wrappers for backwards compatibility
 // ----------------------------------------------------------------------------