From 498a1eeb8d044ef64815352ecabe4c223adf8c6a Mon Sep 17 00:00:00 2001
From: Ryan Norton <wxprojects@comcast.net>
Date: Thu, 21 Apr 2005 20:13:44 +0000
Subject: [PATCH] Add wxLaunchDefaultBrowser, note wxGetKeyState change

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33802 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |   2 +
 docs/latex/wx/function.tex |  13 ++++
 include/wx/utils.h         |   3 +
 src/common/utilscmn.cpp    | 140 +++++++++++++++++++++++++++++++++++++
 4 files changed, 158 insertions(+)

diff --git a/docs/changes.txt b/docs/changes.txt
index aeaf72176f..b9332dfc0b 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -5,9 +5,11 @@ wxWidgets Change Log - For more verbose changes, see the manual
 2.6.1
 -----
 All:
+- Added wxLaunchDefaultBrowser.
 
 wxMac:
 - Added support for launching 'APPL' bundles with wxExecute (usually they have a .app extension and are the ones that reside in the Applications folder).
+- Fixed a bug in wxGetKeyState where shift and some other keys were returning an incorrect state.
 
 2.6.0
 -----
diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex
index 1a1bb44e51..58e5964499 100644
--- a/docs/latex/wx/function.tex
+++ b/docs/latex/wx/function.tex
@@ -164,6 +164,7 @@ the corresponding topic.
 \helpref{wxIsNaN}{wxisnan}\\
 \helpref{wxIsWild}{wxiswild}\\
 \helpref{wxKill}{wxkill}\\
+\helpref{wxLaunchDefaultBrowser}{wxlaunchdefaultbrowser}\\
 \helpref{wxLEAVE\_CRIT\_SECT}{wxleavecritsect}\\
 \helpref{wxLoadUserResource}{wxloaduserresource}\\
 \helpref{wxLogDebug}{wxlogdebug}\\
@@ -2978,6 +2979,18 @@ frame or dialog containing it, or {\tt NULL}.
 <wx/window.h>
 
 
+\membersection{::wxLaunchDefaultBrowser}\label{wxlaunchdefaultbrowser}
+
+\func{bool}{wxLaunchDefaultBrowser}{\param{const wxString\& }{sUrl}}
+
+Launches the user's default browser and tells it to open the location at {\tt sUrl}.
+
+Returns true if the application was successfully launched.
+
+\wxheading{Include files}
+
+<wx/utils.h>
+
 \membersection{::wxLoadUserResource}\label{wxloaduserresource}
 
 \func{wxString}{wxLoadUserResource}{\param{const wxString\& }{resourceName}, \param{const wxString\& }{resourceType=``TEXT"}}
diff --git a/include/wx/utils.h b/include/wx/utils.h
index 30b4b59816..9c73ab4214 100644
--- a/include/wx/utils.h
+++ b/include/wx/utils.h
@@ -324,6 +324,9 @@ WXDLLIMPEXP_BASE bool wxHandleFatalExceptions(bool doit = true);
 
 #endif // wxUSE_ON_FATAL_EXCEPTION
 
+// Launch url in the user's default internet browser
+WXDLLIMPEXP_BASE bool wxLaunchDefaultBrowser(const wxString& url);
+
 // ----------------------------------------------------------------------------
 // Environment variables
 // ----------------------------------------------------------------------------
diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp
index 09369b63f3..bd2714f1eb 100644
--- a/src/common/utilscmn.cpp
+++ b/src/common/utilscmn.cpp
@@ -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
 // ----------------------------------------------------------------------------
-- 
2.50.0

