]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/webview_ie.cpp
Fix various gtk webkit warnings.
[wxWidgets.git] / src / msw / webview_ie.cpp
index 7838686bccfae3349d37dc8dcc558c67e9cccb57..2e4e7a2e758e1f5cbf5f6e07922c30d147ccc19f 100644 (file)
@@ -3,7 +3,7 @@
 // Purpose:     wxMSW wxWebViewIE class implementation for web view component
 // Author:      Marianne Gagnon
 // Id:          $Id$
-// Copyright:   (c) 2010 Marianne Gagnon
+// Copyright:   (c) 2010 Marianne Gagnon, Steven Lamerton
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
@@ -16,7 +16,7 @@
 
 #include "wx/msw/webview_ie.h"
 
-#if wxHAVE_WEB_BACKEND_IE
+#if wxUSE_WEBVIEW_IE
 
 #include <olectl.h>
 #include <oleidl.h>
 #include <exdisp.h>
 #include <mshtml.h>
 
+// Various definitions are missing from mingw
 #ifdef __MINGW32__
-// FIXME: Seems like MINGW does not have these, how to handle cleanly?
-#define DISPID_COMMANDSTATECHANGE   105
 typedef enum CommandStateChangeConstants {
     CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF,
     CSC_NAVIGATEFORWARD = 0x1,
     CSC_NAVIGATEBACK = 0x2
 } CommandStateChangeConstants;
 
-
-// FIXME: Seems like MINGW does not have these, how to handle cleanly?
-#define DISPID_NAVIGATECOMPLETE2    252
-#define DISPID_NAVIGATEERROR        271
-#define OLECMDID_OPTICAL_ZOOM  63
+#define DISPID_COMMANDSTATECHANGE 105
+#define DISPID_NAVIGATECOMPLETE2 252
+#define DISPID_NAVIGATEERROR 271
+#define DISPID_NEWWINDOW3 273
+#define OLECMDID_OPTICAL_ZOOM 63
 #define INET_E_ERROR_FIRST 0x800C0002L
 #define INET_E_INVALID_URL 0x800C0002L
 #define INET_E_NO_SESSION 0x800C0003L
@@ -67,6 +66,7 @@ typedef enum CommandStateChangeConstants {
 #define INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L
 #define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L
 
+#define REFRESH_NORMAL 0
 #define REFRESH_COMPLETELY 3
 #endif
 
@@ -93,6 +93,9 @@ bool wxWebViewIE::Create(wxWindow* parent,
     m_canNavigateBack = false;
     m_canNavigateForward = false;
     m_isBusy = false;
+    m_historyLoadingFromList = false;
+    m_historyEnabled = true;
+    m_historyPosition = -1;
 
     if (::CoCreateInstance(CLSID_WebBrowser, NULL,
                            CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
@@ -112,20 +115,17 @@ bool wxWebViewIE::Create(wxWindow* parent,
 
     SetBackgroundStyle(wxBG_STYLE_PAINT);
     SetDoubleBuffered(true);
+    LoadUrl(url);
     return true;
 }
 
 
 void wxWebViewIE::LoadUrl(const wxString& url)
 {
-    wxVariant out = m_ie.CallMethod("Navigate", (BSTR) url.wc_str(),
-                                    NULL, NULL, NULL, NULL);
-
-    // FIXME: why is out value null??
-    //(HRESULT)(out.GetLong()) == S_OK;
+    m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL);
 }
 
-void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
+void wxWebViewIE::SetPage(const wxString& html, const wxString&)
 {
     LoadUrl("about:blank");
 
@@ -134,11 +134,6 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
     // FIXME: calling wxYield is not elegant nor very reliable probably
     wxYield();
 
-    wxVariant documentVariant = m_ie.GetProperty("Document");
-    void* documentPtr = documentVariant.GetVoidPtr();
-
-    wxASSERT (documentPtr != NULL);
-
     // TODO: consider the "baseUrl" parameter if possible
     // TODO: consider encoding
     BSTR bstr = SysAllocString(html.wc_str());
@@ -153,8 +148,7 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
         param->bstrVal = bstr;
 
         hr = SafeArrayUnaccessData(psaStrings);
-
-        IHTMLDocument2* document = (IHTMLDocument2*)documentPtr;
+        IHTMLDocument2* document = GetDocument();
         document->write(psaStrings);
 
         // SafeArrayDestroy calls SysFreeString for each BSTR
@@ -169,34 +163,23 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
 
 wxString wxWebViewIE::GetPageSource()
 {
-    wxVariant documentVariant = m_ie.GetProperty("Document");
-    void* documentPtr = documentVariant.GetVoidPtr();
-
-    if (documentPtr == NULL)
-    {
-        return wxEmptyString;
-    }
-
-    IHTMLDocument2* document = (IHTMLDocument2*)documentPtr;
-
+    IHTMLDocument2* document = GetDocument();
     IHTMLElement *bodyTag = NULL;
     IHTMLElement *htmlTag = NULL;
-    document->get_body(&bodyTag);
-    wxASSERT(bodyTag != NULL);
+    BSTR bstr;
+    HRESULT hr = document->get_body(&bodyTag);
+    if(SUCCEEDED(hr))
+    {
+        hr = bodyTag->get_parentElement(&htmlTag);
+        if(SUCCEEDED(hr))
+        {
+            htmlTag->get_outerHTML(&bstr);
+            htmlTag->Release();
+        }
+        bodyTag->Release();
+    }
 
     document->Release();
-    bodyTag->get_parentElement(&htmlTag);
-    wxASSERT(htmlTag != NULL);
-
-    BSTR    bstr;
-    htmlTag->get_outerHTML(&bstr);
-
-    bodyTag->Release();
-    htmlTag->Release();
-
-    //wxMessageBox(wxString(bstr));
-
-    // TODO: check encoding
     return wxString(bstr);
 }
 
@@ -282,7 +265,6 @@ int wxWebViewIE::GetIETextZoom()
     wxASSERT (result == S_OK);
 
     int zoom = V_I4(&zoomVariant);
-   // wxMessageBox(wxString::Format("Zoom : %i", zoom));
     VariantClear (&zoomVariant);
 
     return zoom;
@@ -353,30 +335,89 @@ void wxWebViewIE::Print()
                          OLECMDEXECOPT_DODEFAULT, NULL, NULL);
 }
 
-void wxWebViewIE::GoBack()
+bool wxWebViewIE::CanGoBack()
 {
-    wxVariant out = m_ie.CallMethod("GoBack");
+    if(m_historyEnabled)
+        return m_historyPosition > 0;
+    else
+        return false;
+}
 
-    // FIXME: why is out value null??
-    //return (HRESULT)(out.GetLong()) == S_OK;
+bool wxWebViewIE::CanGoForward()
+{
+    if(m_historyEnabled)
+        return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
+    else
+        return false;
 }
 
-void wxWebViewIE::GoForward()
+void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebHistoryItem> item)
 {
-    wxVariant out = m_ie.CallMethod("GoForward");
+    int pos = -1;
+    for(unsigned int i = 0; i < m_historyList.size(); i++)
+    {
+        //We compare the actual pointers to find the correct item
+        if(m_historyList[i].get() == item.get())
+            pos = i;
+    }
+    wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()), 
+                 "invalid history item");
+    m_historyLoadingFromList = true;
+    LoadUrl(item->GetUrl());
+    m_historyPosition = pos;
+}
 
-    // FIXME: why is out value null??
-    //return (HRESULT)(out.GetLong()) == S_OK;
+wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetBackwardHistory()
+{
+    wxVector<wxSharedPtr<wxWebHistoryItem> > backhist;
+    //As we don't have std::copy or an iterator constructor in the wxwidgets
+    //native vector we construct it by hand
+    for(int i = 0; i < m_historyPosition; i++)
+    {
+        backhist.push_back(m_historyList[i]);
+    }
+    return backhist;
+}
+
+wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetForwardHistory()
+{
+    wxVector<wxSharedPtr<wxWebHistoryItem> > forwardhist;
+    //As we don't have std::copy or an iterator constructor in the wxwidgets
+    //native vector we construct it by hand
+    for(int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++)
+    {
+        forwardhist.push_back(m_historyList[i]);
+    }
+    return forwardhist;
+}
+
+void wxWebViewIE::GoBack()
+{
+    LoadHistoryItem(m_historyList[m_historyPosition - 1]);
+}
+
+void wxWebViewIE::GoForward()
+{
+    LoadHistoryItem(m_historyList[m_historyPosition + 1]);
 }
 
 void wxWebViewIE::Stop()
 {
-    wxVariant out = m_ie.CallMethod("Stop");
+    m_ie.CallMethod("Stop");
+}
 
-    // FIXME: why is out value null??
-    //return (HRESULT)(out.GetLong()) == S_OK;
+void wxWebViewIE::ClearHistory()
+{
+    m_historyList.clear();
+    m_historyPosition = -1;
 }
 
+void wxWebViewIE::EnableHistory(bool enable)
+{
+    m_historyEnabled = enable;
+    m_historyList.clear();
+    m_historyPosition = -1;
+}
 
 void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
 {
@@ -439,10 +480,166 @@ wxString wxWebViewIE::GetCurrentURL()
 
 wxString wxWebViewIE::GetCurrentTitle()
 {
-    wxVariant out = m_ie.GetProperty("LocationName");
+    IHTMLDocument2* document = GetDocument();
+    BSTR title;
 
-    wxASSERT(out.GetType() == "string");
-    return out.GetString();
+    document->get_nameProp(&title);
+    document->Release();
+    return wxString(title);
+}
+
+bool wxWebViewIE::CanCut()
+{
+    return CanExecCommand("Cut");
+}
+
+bool wxWebViewIE::CanCopy()
+{
+    return CanExecCommand("Copy");
+}
+bool wxWebViewIE::CanPaste()
+{
+    return CanExecCommand("Paste");
+}
+
+void wxWebViewIE::Cut()
+{
+    ExecCommand("Cut");
+}
+
+void wxWebViewIE::Copy()
+{
+    ExecCommand("Copy");
+}
+
+void wxWebViewIE::Paste()
+{
+    ExecCommand("Paste");
+}
+
+bool wxWebViewIE::CanUndo()
+{
+    return CanExecCommand("Undo");
+}
+bool wxWebViewIE::CanRedo()
+{
+    return CanExecCommand("Redo");
+}
+
+void wxWebViewIE::Undo()
+{
+    ExecCommand("Undo");
+}
+
+void wxWebViewIE::Redo()
+{
+    ExecCommand("Redo");
+}
+
+void wxWebViewIE::SetEditable(bool enable)
+{
+    IHTMLDocument2* document = GetDocument();
+    if( enable )
+        document->put_designMode(SysAllocString(L"On"));
+    else
+        document->put_designMode(SysAllocString(L"Off"));
+
+    document->Release();
+}
+
+bool wxWebViewIE::IsEditable()
+{
+    IHTMLDocument2* document = GetDocument();
+    BSTR mode;
+    document->get_designMode(&mode);
+    if(wxString(mode) == "On")
+        return true;
+    else
+        return false;
+
+    document->Release();
+}
+
+void wxWebViewIE::SelectAll()
+{
+    ExecCommand("SelectAll");
+}
+
+bool wxWebViewIE::HasSelection()
+{
+    IHTMLDocument2* document = GetDocument();
+    IHTMLSelectionObject* selection;
+    BSTR type;
+    HRESULT hr = document->get_selection(&selection);
+    if(SUCCEEDED(hr))
+    {
+        selection->get_type(&type);
+        selection->Release();
+    }
+    document->Release();
+    return wxString(type) != "None";
+}
+
+void wxWebViewIE::DeleteSelection()
+{
+    ExecCommand("Delete");
+}
+
+wxString wxWebViewIE::GetSelectedText()
+{
+    IHTMLDocument2* document = GetDocument();
+    IHTMLSelectionObject* selection;
+    wxString selected;
+    HRESULT hr = document->get_selection(&selection);
+    if(SUCCEEDED(hr))
+    {
+        IDispatch* disrange;
+        hr = selection->createRange(&disrange);
+        if(SUCCEEDED(hr))
+        {
+            IHTMLTxtRange* range;
+            hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
+            if(SUCCEEDED(hr))
+            {
+                BSTR text;
+                range->get_text(&text);
+                selected = wxString(text);
+                range->Release();
+            }
+            disrange->Release();
+        }
+        selection->Release();
+    }
+    document->Release();
+    return selected;
+}
+
+bool wxWebViewIE::CanExecCommand(wxString command)
+{
+    IHTMLDocument2* document = GetDocument();
+    VARIANT_BOOL enabled;
+
+    document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled);
+    document->Release();
+
+    return (enabled == VARIANT_TRUE);
+}
+
+void wxWebViewIE::ExecCommand(wxString command)
+{
+    IHTMLDocument2* document = GetDocument();
+    document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL);
+    document->Release();
+}
+
+IHTMLDocument2* wxWebViewIE::GetDocument()
+{
+    wxVariant variant = m_ie.GetProperty("Document");
+    IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr();
+
+    wxASSERT(document);
+
+    return document;
 }
 
 void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
@@ -499,7 +696,32 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
 
         case DISPID_DOCUMENTCOMPLETE:
         {
+            //Only send a complete even if we are actually finished, this brings
+            //the event in to line with webkit
+            READYSTATE rs;
+            m_webBrowser->get_ReadyState( &rs );
+            if(rs != READYSTATE_COMPLETE)
+                break;
+
             wxString url = evt[1].GetString();
+
+            //As we are complete we also add to the history list, but not if the
+            //page is not the main page, ie it is a subframe
+            if(m_historyEnabled && !m_historyLoadingFromList && url == GetCurrentURL())
+            {
+                //If we are not at the end of the list, then erase everything
+                //between us and the end before adding the new page
+                if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
+                {
+                    m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
+                                        m_historyList.end());
+                }
+                wxSharedPtr<wxWebHistoryItem> item(new wxWebHistoryItem(url, GetCurrentTitle()));
+                m_historyList.push_back(item);
+                m_historyPosition++;
+            }
+            //Reset as we are done now
+            m_historyLoadingFromList = false;
             // TODO: set target parameter if possible
             wxString target = wxEmptyString;
             wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
@@ -658,11 +880,21 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
             }
             break;
         }
-        case DISPID_NEWWINDOW2:
+        case DISPID_NEWWINDOW3:
         {
-            wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
-            // Cancel the attempt to open a new window
-            *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
+            wxString url = evt[4].GetString();
+
+            wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
+                                       GetId(), url, wxEmptyString, true);
+            event.SetEventObject(this);
+            HandleWindowEvent(event);
+
+            //If we veto the event then we cancel the new window
+            if (event.IsVetoed())
+            {
+                wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
+                *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE;
+            }
             break;
         }
     }