// -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-

//
//  Copyright (C) 2003 Takuro Ashie
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2, or (at your option)
//  any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

// Some codes are taken from Epiphany 0.8.2
// Copyright (C) 2000-2003 Marco Pesenti Gritti

// samples of nsISelection are:
//   content/base/src/nsDocumentViewer.cpp
//   layout/base/src/nsCaret.cpp


#include <kz-mozwrapper.h>
#include <gtkmozembed_internal.h>

#include <nsIInterfaceRequestorUtils.h>
#include <nsILocalFile.h>
#include <docshell/nsIDocShell.h>
#include <docshell/nsIDocShellTreeItem.h>
#include <docshell/nsIDocShellTreeOwner.h>
#include <docshell/nsIContentViewer.h>
#include <content/nsIContent.h>
#include <nsIDOMHTMLDocument.h>
#include <nsIDOMHTMLElement.h>
#include <nsIDOMHTMLImageElement.h>
#include <nsIDOMNSHTMLElement.h>  
#include <nsIDOMDocumentRange.h>
#include <nsIDOMNamedNodeMap.h>
#include <nsIDOMText.h>
#include <nsIDOMNodeList.h>
#include <nsIDOMNode.h>
#include <nsIClipboardCommands.h>
#include <nsLiteralString.h>
#include <nsString.h>
#include <nsEscape.h>
#include <nsIDOMElement.h>
#include <nsIDocument.h>
#include <nsIDOMDocumentType.h>
#include <nsIURI.h>
#include <nsIWebBrowserFocus.h>
#include <nsIWebPageDescriptor.h>
#include <nsIMarkupDocumentViewer.h>
#include <nsIDOMWindowInternal.h>
#include <nsIDOMWindowCollection.h>
#include <nsIChromeEventHandler.h>
#include <nsIDocShellHistory.h>
#include <nsIDocShellTreeNode.h>
#include <nsIScriptGlobalObject.h>
#include <nsISHistoryInternal.h>
#include <nsIHistoryEntry.h>
#include <nsICacheService.h>
#include <nsICacheSession.h>
#include <nsNetCID.h>
#include <nsIServiceManager.h>
#include <htmlparser/nsIParser.h>
#include <chardet/nsIDocumentCharsetInfo.h>
#include <nsIOutputStream.h>
#include <nsReadableUtils.h>
#include <necko/nsNetUtil.h>
#include <nsIWebBrowserPrint.h>
#if MOZILLA_SNAPSHOT > 16
#include <nsPresContext.h>
#else
#include <nsIPresContext.h>
#endif
#if MOZILLA_SNAPSHOT < 13
#include <nsIDeviceContext.h>
#endif
#include "nsUnicharUtils.h"
#include "kz-mozprogresslistener.h"
#include "utils.h"
#include "egg-pixbuf-thumbnail.h"

#ifdef HAVE_CONFIG_H
#	include "config.h"
#endif /* HAVE_CONFIG_H */

KzMozWrapper::KzMozWrapper () :
	mWebBrowser (nsnull),
	mEventReceiver (nsnull),
	mKzMozEmbed (nsnull),
	mSelectionWasCollapsed (PR_TRUE)
{
}


KzMozWrapper::~KzMozWrapper ()
{
}


nsresult
KzMozWrapper::Init (KzMozEmbed *kzembed)
{
	nsresult rv;
	
	mKzMozEmbed = kzembed;
	gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(mKzMozEmbed),
					getter_AddRefs(mWebBrowser));
	if (!mWebBrowser) return NS_ERROR_FAILURE;

	mWebBrowser->GetContentDOMWindow (getter_AddRefs (mDOMWindow));

	/* this codes was taken from Galeon-1.3.17 */
	/* This will instantiate an about:blank doc if necessary, but don't
	 * initialize for mozilla XUL dialogs, it breaks them */
	/* 
	 * 2004-09-19: removed the following codes 
	 *  because of inactivity of the gestures.
	 */ 
/*
	if (!(gtk_moz_embed_get_chrome_mask(GTK_MOZ_EMBED(kzembed)) &
	    GTK_MOZ_EMBED_FLAG_OPENASCHROME))
	{
		nsCOMPtr<nsIDOMDocument> domDocument;
		rv = mDOMWindow->GetDocument (getter_AddRefs(domDocument));
		if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
	}
*/
#if 1
	mKzMozEventListener = new KzMozEventListener();
	rv = mKzMozEventListener->Init (kzembed);
	if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
	GetListener();
	AttachListeners();
#endif
	return NS_OK;
}


nsresult
KzMozWrapper::GetListener (void)
{
  	if (mEventReceiver) return NS_ERROR_FAILURE;
//  	if (mEventTarget) return NS_ERROR_FAILURE;
	
  	nsCOMPtr<nsIDOMWindow> domWindowExternal;
  	mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindowExternal));
  
  	nsCOMPtr<nsIDOMWindowInternal> domWindow;
        domWindow = do_QueryInterface(domWindowExternal);

//	domWindow->GetWindowRoot(getter_AddRefs(mEventTarget));
	nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(domWindow));
  	if (!piWin) return NS_ERROR_FAILURE;

  	nsCOMPtr<nsIChromeEventHandler> chromeHandler;
#if MOZILLA_SNAPSHOT > 15
	chromeHandler = piWin->GetChromeEventHandler();
#else
	piWin->GetChromeEventHandler(getter_AddRefs(chromeHandler));	
#endif
  	mEventReceiver = do_QueryInterface(chromeHandler);
	if (!mEventReceiver) return NS_ERROR_FAILURE;

	return NS_OK;
}


nsresult
KzMozWrapper::AttachListeners(void)
{
  	if (!mEventReceiver) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMEventTarget> target;
	target = do_QueryInterface (mEventReceiver);

//	return mEventTarget->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
//						mKzMozEventListener, PR_FALSE);
	return target->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
			                mKzMozEventListener, PR_FALSE);
}


nsresult
KzMozWrapper::DetachListeners(void)
{
	if (!mEventReceiver) return NS_ERROR_FAILURE;
	
	nsCOMPtr<nsIDOMEventTarget> target;
	target = do_QueryInterface (mEventReceiver);
//	return mEventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
//					mKzMozEventListener, PR_FALSE);
	return target->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
					   mKzMozEventListener, PR_FALSE);
}


void
KzMozWrapper::Destroy (void)
{
	DetachListeners ();
	mKzMozEmbed = nsnull;
	mEventReceiver = nsnull;
	//mEventTarget = nsnull;
	mWebBrowser = nsnull;
}


//
// Our own methods
//

nsresult
KzMozWrapper::GetDocShell (nsIDocShell **aDocShell)
{
        if (!mWebBrowser) return NS_ERROR_FAILURE;

        nsCOMPtr<nsIDocShellTreeItem> browserAsItem;
        browserAsItem = do_QueryInterface(mWebBrowser);
        if (!browserAsItem) return NS_ERROR_FAILURE;

        // get the owner for that item
        nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
        browserAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
        if (!treeOwner) return NS_ERROR_FAILURE;

        // get the primary content shell as an item
        nsCOMPtr<nsIDocShellTreeItem> contentItem;
        treeOwner->GetPrimaryContentShell(getter_AddRefs(contentItem));
        if (!contentItem) return NS_ERROR_FAILURE;

        // QI that back to a docshell
        nsCOMPtr<nsIDocShell> DocShell;
        DocShell = do_QueryInterface(contentItem);
        if (!DocShell) return NS_ERROR_FAILURE;

        *aDocShell = DocShell.get();
        NS_IF_ADDREF(*aDocShell);

        return NS_OK;
}


nsresult
KzMozWrapper::GetDocument (nsIDOMDocument **aDOMDocument)
{
	nsCOMPtr<nsIDOMDocument> domDocument;
	
	return mDOMWindow->GetDocument (aDOMDocument);
}


nsresult
KzMozWrapper::GetMainDomDocument (nsIDOMDocument **aDOMDocument)
{
        nsresult rv;

        nsCOMPtr<nsIDocShell> DocShell;
        rv = GetDocShell(getter_AddRefs(DocShell));
        if (NS_FAILED(rv) || !DocShell) return NS_ERROR_FAILURE;

        nsCOMPtr<nsIContentViewer> contentViewer;
        rv = DocShell->GetContentViewer(getter_AddRefs(contentViewer));
        if (!NS_SUCCEEDED(rv) || !contentViewer) return NS_ERROR_FAILURE;

        return contentViewer->GetDOMDocument(aDOMDocument);
}


nsresult
KzMozWrapper::GetDOMWindow (nsIDOMWindow **aDOMWindow)
{
	nsresult rv;
	
	rv = mWebBrowser->GetContentDOMWindow (aDOMWindow);
	
	return rv;
}


nsresult
KzMozWrapper::GetContentViewer (nsIContentViewer **aViewer)
{
        g_return_val_if_fail(mWebBrowser, NS_ERROR_FAILURE);

        nsCOMPtr<nsIDocShell> ourDocShell(do_GetInterface(mWebBrowser));
        NS_ENSURE_TRUE(ourDocShell, NS_ERROR_FAILURE);
        return ourDocShell->GetContentViewer(aViewer);
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::GetSHistory (nsISHistory **aSHistory)
{
	nsresult rv;

	nsCOMPtr<nsIDocShell> DocShell;
	rv = GetDocShell (getter_AddRefs(DocShell));
	if (NS_FAILED(rv) || !DocShell) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (DocShell,
								   &rv);
	if (!ContentNav) return NS_ERROR_FAILURE;

	nsCOMPtr<nsISHistory> SessionHistory;
	rv = ContentNav->GetSessionHistory (getter_AddRefs (SessionHistory));
	if (!SessionHistory) return NS_ERROR_FAILURE;

	*aSHistory = SessionHistory.get();
	NS_IF_ADDREF (*aSHistory);

	return NS_OK;
}


nsresult
KzMozWrapper::GetSelection (nsISelection **selection)
{
	nsCOMPtr<nsIDOMWindow> domWindow;

	nsresult rv = GetFocusedDOMWindow (getter_AddRefs(domWindow));
	if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

	return domWindow->GetSelection(selection);
}


nsresult
KzMozWrapper::GetHtmlWithContents (nsISelection *selection, 
			 	   const gchar *storedir,
				   nsAString &string)
{
	nsCOMPtr<nsIDOMRange> range;
	selection->GetRangeAt(0, getter_AddRefs(range));
	if (!range) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMDocument> domDoc;
        nsresult rv = GetMainDomDocument(getter_AddRefs(domDoc));
        if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;
	
	nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(domDoc);
	if (!htmlDoc) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMHTMLElement> bodyElement;
	htmlDoc->GetBody(getter_AddRefs(bodyElement));

	if (!bodyElement) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMNode> bodyNode;
	bodyNode = do_QueryInterface(bodyElement);
	
	SetHTMLHeadSource(domDoc, storedir, string);

	HTMLSourceFromNode(domDoc, bodyNode, selection, range, storedir, string);

	string.Append(NS_LITERAL_STRING("\n</html>"));

	return NS_OK;
}


nsresult
KzMozWrapper::GetBodyString (nsAString &string)
{
	nsresult rv;
	nsCOMPtr<nsIDOMDocument> domDoc;
        rv = GetMainDomDocument(getter_AddRefs(domDoc));
        if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;
	
	nsCOMPtr<nsIContent> rootContent;
	nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(domDoc);
	if (htmlDoc)
	{
		nsCOMPtr<nsIDOMHTMLElement> bodyElement;
		htmlDoc->GetBody(getter_AddRefs(bodyElement));
		rootContent = do_QueryInterface(bodyElement);
	}

        // to avoid segfault with DetailedPreference, 
        // return if rootContent is NULL.
	if (!rootContent)
		return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootContent));
	nsCOMPtr<nsIDOMDocumentRange> docRange = do_QueryInterface(domDoc);
	if (!docRange)
		return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMRange> range;
	docRange->CreateRange(getter_AddRefs(range));
	if (!range)
		return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 11
	PRUint32 childcount;
	childcount = rootContent->GetChildCount();
#else
	PRInt32 childcount;
	rv = rootContent->ChildCount(childcount);
#endif
	range->SetStart(rootNode,0);
	range->SetEnd(rootNode,childcount);
	range->ToString(string);
	
	return NS_OK;
}


nsresult
KzMozWrapper::GetStringSelection (nsAString &string, gboolean backward)
{
	nsresult rv;
	nsCOMPtr<nsIDOMDocument> domDoc;
        rv = GetMainDomDocument(getter_AddRefs(domDoc));
        if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;
	
	nsCOMPtr<nsIContent> rootContent;
	nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(domDoc);
	if (htmlDoc)
	{
		nsCOMPtr<nsIDOMHTMLElement> bodyElement;
		htmlDoc->GetBody(getter_AddRefs(bodyElement));
		rootContent = do_QueryInterface(bodyElement);
	}

        // to avoid segfault with DetailedPreference, 
        // return if rootContent is NULL.
	if (!rootContent)
		return NS_ERROR_FAILURE;

	// Get root content node
	nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootContent));
	nsCOMPtr<nsIDOMDocumentRange> docRange = do_QueryInterface(domDoc);
	if (!docRange)
		return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMRange> range;
	docRange->CreateRange(getter_AddRefs(range));
	if (!range)
		return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 11
	PRUint32 childcount;
	childcount = rootContent->GetChildCount();
#else
	PRInt32 childcount;
	rv = rootContent->ChildCount(childcount);
#endif
	
	nsCOMPtr<nsISelection> selection;

	mDOMWindow->GetSelection(getter_AddRefs(selection));

	if (backward)
	{
		if (selection)
		{
			nsCOMPtr<nsIDOMNode> endNode;
			PRInt32 endOffset;
			selection->CollapseToStart();
			selection->GetAnchorNode(getter_AddRefs(endNode));
			selection->GetAnchorOffset(&endOffset);
	
			range->SetEnd(endNode, endOffset);
		}
		else
		{
			range->SetEnd(rootNode, childcount);
		}
		range->SetStart(rootNode, 0);
	}
	else
	{
		if (selection)
		{
			nsCOMPtr<nsIDOMNode> endNode;
			PRInt32 endOffset;
			selection->GetAnchorNode(getter_AddRefs(endNode));
			selection->GetAnchorOffset(&endOffset);
	
			range->SetStart(endNode, endOffset + 1);
		}
		else
		{
			range->SetStart(rootNode, 0);
		}
		range->SetEnd(rootNode, childcount);
	}

	range->ToString(string);
	
	return NS_OK;
}


nsresult
KzMozWrapper::CanCutSelection (PRBool *result)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->CanCutSelection(result);
}


nsresult 
KzMozWrapper::CanCopySelection (PRBool *result)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->CanCopySelection(result);
}


nsresult
KzMozWrapper::CanPaste (PRBool *result)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->CanPaste(result);
}


nsresult
KzMozWrapper::CutSelection (void)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->CutSelection();
}


nsresult
KzMozWrapper::CopySelection (void)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->CopySelection();
}


nsresult
KzMozWrapper::Paste (void)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	return clipboard->Paste();
}


nsresult
KzMozWrapper::SelectAll (void)
{
	nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
	
	return clipboard->SelectAll();
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::GetFocusedDOMWindow (nsIDOMWindow **aDOMWindow)
{
	nsresult rv;
	
	g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

	nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser, &rv);
	if (NS_FAILED(rv) || !focus) return NS_ERROR_FAILURE;

	rv = focus->GetFocusedWindow (aDOMWindow);
	if (NS_FAILED(rv))
		rv = mWebBrowser->GetContentDOMWindow (aDOMWindow);
	return rv;
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::GetWebNavigation (nsIWebNavigation **aWebNavigation)
{
	nsresult rv;

	nsCOMPtr<nsIDOMWindow> DOMWindow;
	rv = GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
	if (NS_FAILED(rv) || !DOMWindow) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIScriptGlobalObject> scriptGlobal = do_QueryInterface(DOMWindow);
	if (!scriptGlobal) return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 12
	nsIDocShell *docshell = scriptGlobal->GetDocShell();
	if (!docshell)
		return NS_ERROR_FAILURE;
#else	
	nsCOMPtr<nsIDocShell> docshell;
	if (NS_FAILED(scriptGlobal->GetDocShell(getter_AddRefs(docshell))))
		return NS_ERROR_FAILURE;
#endif
	nsCOMPtr<nsIWebNavigation> wn = do_QueryInterface (docshell, &rv);
	if (!wn || !NS_SUCCEEDED (rv)) return NS_ERROR_FAILURE;

	NS_IF_ADDREF(*aWebNavigation = wn);
	return NS_OK;
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::LoadDocument (nsISupports *aPageDescriptor,
			    PRUint32 aDisplayType)
{
	nsresult rv;

	nsCOMPtr<nsIWebNavigation> wn;
	rv = GetWebNavigation(getter_AddRefs(wn));
	if (!wn || !NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIWebPageDescriptor> wpd = do_QueryInterface(wn, &rv);
	if (!wpd || !NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;

	return wpd->LoadPage(aPageDescriptor, aDisplayType);
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::GetPageDescriptor (nsISupports **aPageDescriptor)
{
	nsresult rv;

	nsCOMPtr<nsIWebNavigation> wn;
	rv = GetWebNavigation(getter_AddRefs(wn));
	if (!wn || !NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIWebPageDescriptor> wpd = do_QueryInterface(wn, &rv);
	if (!wpd || !NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;

	return wpd->GetCurrentDescriptor(aPageDescriptor);
}


/* this function picked from galeon-1.3.11a. */
nsresult
KzMozWrapper::CopyHistoryTo (KzMozWrapper *dest, 
			     PRBool back_history, 
			     PRBool forward_history, 
			     PRBool set_current)
{
	nsresult rv;
	PRInt32 count, index;
	
	nsCOMPtr<nsISHistory> h_src;
	rv = GetSHistory (getter_AddRefs(h_src));
	if (NS_FAILED(rv) || !h_src) return NS_ERROR_FAILURE;

	h_src->GetCount (&count);
	h_src->GetIndex (&index);

	nsCOMPtr<nsISHistory> h_dest;
	rv = dest->GetSHistory (getter_AddRefs (h_dest));
	if (!NS_SUCCEEDED (rv) || (!h_dest)) return NS_ERROR_FAILURE;

	nsCOMPtr<nsISHistoryInternal> hi_dest = do_QueryInterface (h_dest);
	if (!hi_dest) return NS_ERROR_FAILURE;

	if (count) {
		nsCOMPtr<nsIHistoryEntry> he;
		nsCOMPtr<nsISHEntry> she;

		for (PRInt32 i = (back_history ? 0 : index + 1); 
		     i < (forward_history ? count : index + 1);
		     i++) 
		{

			rv = h_src->GetEntryAtIndex (i, PR_FALSE,
							 getter_AddRefs (he));
			if (!NS_SUCCEEDED(rv) || (!he))
				return NS_ERROR_FAILURE;

			she = do_QueryInterface (he);
			if (!she) return NS_ERROR_FAILURE;

			rv = hi_dest->AddEntry (she, PR_TRUE);
			if (!NS_SUCCEEDED(rv) || (!she))
				return NS_ERROR_FAILURE;
		}
		
		if (set_current)
		{
			nsCOMPtr<nsIDocShell> destDocShell;
			rv = dest->GetDocShell (getter_AddRefs(destDocShell));
			if (NS_FAILED(rv) || !destDocShell) return NS_ERROR_FAILURE;
		
			nsCOMPtr<nsIWebNavigation> wn_dest = do_QueryInterface (destDocShell, &rv);
			
			rv = wn_dest->GotoIndex(index);
			if (!NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;
		}
	}

	return NS_OK;
}


// picked from galeon-1.3.11a 
nsresult
KzMozWrapper::GetSHInfo (PRInt32 *count, PRInt32 *index)
{
	nsresult rv;

	nsCOMPtr<nsISHistory> SessionHistory;
	rv = GetSHistory (getter_AddRefs(SessionHistory));
	if (NS_FAILED(rv) || ! SessionHistory) return NS_ERROR_FAILURE;

	SessionHistory->GetCount (count);
	SessionHistory->GetIndex (index);	

	return NS_OK;
}


// picked from galeon-1.3.11a 
nsresult
KzMozWrapper::GetSHUrlAtIndex (PRInt32 index, nsCString &url)
{
	nsresult rv;

	nsCOMPtr<nsISHistory> SessionHistory;
	rv = GetSHistory (getter_AddRefs(SessionHistory));
	if (NS_FAILED(rv) || ! SessionHistory) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIHistoryEntry> he;
	rv = SessionHistory->GetEntryAtIndex (index, PR_FALSE,
						  getter_AddRefs (he));
	if (NS_FAILED(rv) || (!he)) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIURI> uri;
	rv = he->GetURI (getter_AddRefs(uri));
	if (NS_FAILED(rv) || (!uri)) return NS_ERROR_FAILURE;

	rv = uri->GetSpec(url);
	if (NS_FAILED(rv) || url.IsEmpty()) return NS_ERROR_FAILURE;

	return NS_OK;
}

// picked from galeon-1.3.11a 
nsresult
KzMozWrapper::GetSHTitleAtIndex (PRInt32 index, PRUnichar **title)
{
	nsresult rv;

	nsCOMPtr<nsISHistory> SessionHistory;
	rv = GetSHistory (getter_AddRefs(SessionHistory));
	if (NS_FAILED(rv) || ! SessionHistory) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIHistoryEntry> he;
	rv = SessionHistory->GetEntryAtIndex (index, PR_FALSE,
						  getter_AddRefs (he));
	if (!NS_SUCCEEDED(rv) || (!he)) return NS_ERROR_FAILURE;

	rv = he->GetTitle (title);
	if (!NS_SUCCEEDED(rv) || (!title)) return NS_ERROR_FAILURE;

	return NS_OK;
}


nsresult
KzMozWrapper::GetHistoryEntry (PRInt32 index, nsIHistoryEntry **he)
{
	nsresult rv;

	nsCOMPtr<nsISHistory> SessionHistory;
	rv = GetSHistory (getter_AddRefs(SessionHistory));
	if (NS_FAILED(rv) || ! SessionHistory) return NS_ERROR_FAILURE;

	rv = SessionHistory->GetEntryAtIndex (index, PR_FALSE,
					      he);
	return rv;
}


nsresult 
KzMozWrapper::GoHistoryIndex (gint index)
{
	nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface (mWebBrowser);
	if (!nav) return NS_ERROR_FAILURE;

	return nav->GotoIndex (index);
}


nsresult
KzMozWrapper::GetDocumentUrl (nsCString &url)
{
	nsresult rv;
	nsCOMPtr<nsIDOMWindow> domWindow;
	nsCOMPtr<nsIDOMDocument> DOMDocument;

	mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));

	rv = domWindow->GetDocument(getter_AddRefs(DOMDocument));
	if (NS_FAILED(rv) || !DOMDocument) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDocument> doc = do_QueryInterface(DOMDocument);
	if(!doc) return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 12
	nsIURI *uri;
	uri = doc->GetDocumentURI();
#elif MOZILLA_SNAPSHOT > 11
	nsIURI *uri;
	uri = doc->GetDocumentURL();
#else
	nsCOMPtr<nsIURI> uri;
	doc->GetDocumentURL(getter_AddRefs(uri));
#endif

	return uri->GetSpec(url);
}


nsresult
KzMozWrapper::ForceEncoding (const char *encoding)
{
        nsresult rv;

        nsCOMPtr<nsIContentViewer> contentViewer;
        rv = GetContentViewer(getter_AddRefs(contentViewer));
        if (!NS_SUCCEEDED(rv) || !contentViewer) return NS_ERROR_FAILURE;

        nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
        if (!mdv) return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 9
	rv = mdv->SetForceCharacterSet(nsDependentCString(encoding));
#else
	rv = mdv->SetForceCharacterSet(NS_ConvertUTF8toUCS2(encoding).get());
#endif

        return rv;
}

/*
 * This function is derived from galeon-1.3.12(mozilla/GaleonWrapper.cpp).
 *  Copyright (C) 2000 Marco Pesenti Gritti
 */

nsresult 
KzMozWrapper::GetEncoding (char **encoding, PRBool &forced)
{
	nsresult rv;

	nsCOMPtr<nsIDOMDocument> domDoc;
	rv = GetDocument (getter_AddRefs(domDoc));
	if (NS_FAILED (rv) || !domDoc) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc, &rv);
	if (NS_FAILED (rv) || !doc) return NS_ERROR_FAILURE;

	PRInt32 source;
#if MOZILLA_SNAPSHOT > 11
	source = doc->GetDocumentCharacterSetSource ();
#else
	rv = doc->GetDocumentCharacterSetSource (&source);
	if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
#endif
	if (source >= kCharsetFromParentForced)
	{
		forced = TRUE;
	}

	nsCOMPtr<nsIDocShell> ds;
	ds = do_GetInterface (mWebBrowser);
	if (!ds) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDocumentCharsetInfo> ci;
	rv = ds->GetDocumentCharsetInfo (getter_AddRefs (ci));
	if (NS_FAILED(rv) || !ci) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIAtom> atom;
	rv = ci->GetForcedCharset (getter_AddRefs (atom));
	if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
	if (atom)
	{
		nsCAutoString atomstr;
		atom->ToUTF8String (atomstr);

		if (atomstr.Length())
		{
			forced = TRUE;
		}
	}

#if MOZILLA_SNAPSHOT > 11
	const nsACString& charsetEnc = doc->GetDocumentCharacterSet ();
	if (charsetEnc.IsEmpty()) return NS_ERROR_FAILURE;
	*encoding = g_strdup (PromiseFlatCString(charsetEnc).get());

#elif MOZILLA_SNAPSHOT >= 10
	nsCAutoString charsetEnc;	
	rv = doc->GetDocumentCharacterSet (charsetEnc);
	if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

	*encoding = g_strdup (charsetEnc.get());
#else
	nsAutoString charsetEnc;
	rv = doc->GetDocumentCharacterSet (charsetEnc);
	if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

	*encoding = g_strdup (NS_ConvertUCS2toUTF8(charsetEnc).get());
#endif

	return NS_OK;
}


nsresult
KzMozWrapper::ResolveURI (nsIDOMDocument *domDoc,
			  const nsAString &origURI,
			  nsACString &URI)
{
        nsresult rv;

	nsIURI *baseURI;
	nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
#if MOZILLA_SNAPSHOT > 12
	baseURI = doc->GetBaseURI();
#elif MOZILLA_SNAPSHOT > 11
	baseURI = doc->GetBaseURL();
#elif MOZILLA_SNAPSHOT > 9
	rv = doc->GetBaseURL(&baseURI);
#else
	rv = doc->GetBaseURL(baseURI);
#endif	
	rv = baseURI->Resolve(NS_ConvertUCS2toUTF8(origURI), URI);
	
	return rv;
}


void 
KzMozWrapper::SetAttributes (nsIDOMNode *node, 
			     nsIDOMDocument *domDoc,
			     nsAString &aString)
{
	NS_NAMED_LITERAL_STRING(eq, "=");
	NS_NAMED_LITERAL_STRING(dq, "\"");
	NS_NAMED_LITERAL_STRING(sp, " ");
	
	nsCOMPtr<nsIDOMNamedNodeMap> attrs;
	node->GetAttributes(getter_AddRefs(attrs));
	if (!attrs) return;

	PRUint32 index, length;
	attrs->GetLength(&length);
	
	for (index = 0; index < length; index++)
	{
		nsCOMPtr<nsIDOMNode> attr;
		attrs->Item(index, getter_AddRefs(attr));
		nsAutoString name, value;
		attr->GetNodeName(name);
		attr->GetNodeValue(value);
		value.Assign(nsEscapeHTML2(value.get(),
					   value.Length()));
			
		aString += sp + name + eq;
		aString += dq + value + dq;
	}
}

void
KzMozWrapper::SetStartTag (const nsAString &tag,
			   nsIDOMDocument *domDoc,
			   nsAString &aString)
{
	NS_NAMED_LITERAL_STRING(lt, "<");
	NS_NAMED_LITERAL_STRING(gt, ">");
	NS_NAMED_LITERAL_STRING(cr, "\n");

	nsCOMPtr<nsIDOMNodeList> nodeList;
	domDoc->GetElementsByTagName(tag, getter_AddRefs(nodeList));
	
	if (!nodeList) return;

	PRUint32 index, length;
	nodeList->GetLength(&length);
	for (index = 0; index < length; index++)
	{
		nsCOMPtr<nsIDOMNode> child;
		nodeList->Item(index, getter_AddRefs(child));

		nsCOMPtr<nsIDOMHTMLElement> element;
		element = do_QueryInterface(child);
		if (!element) continue;
			
		nsAutoString name;
		element->GetTagName(name);
		ToLowerCase(name);
		aString += lt + name;
		SetAttributes(child, domDoc, aString);
		aString += gt + cr;
	}
}

void
KzMozWrapper::SetHTMLHeadSource (nsIDOMDocument *domDocument,
				 const gchar *storedir,
			         nsAString &aSource)
{
	NS_NAMED_LITERAL_STRING(dq, "\"");
	NS_NAMED_LITERAL_STRING(sp, " ");
	NS_NAMED_LITERAL_STRING(sl, "/");
	NS_NAMED_LITERAL_STRING(lt, "<");
	NS_NAMED_LITERAL_STRING(gt, ">");
	NS_NAMED_LITERAL_STRING(cr, "\n");
	NS_NAMED_LITERAL_STRING(dt, "!DOCTYPE");
	
	nsCOMPtr<nsIDOMNode> domNode;
	domNode = do_QueryInterface(domDocument);

	// <!DOCTYPE name PUBLIC "PiblicId" "SystemId">
	nsCOMPtr<nsIDOMDocumentType> docType;
	domDocument->GetDoctype(getter_AddRefs(docType));
	
	if (docType)
	{
		nsAutoString name, pubID, sysID;
		docType->GetName(name);
		docType->GetPublicId(pubID);
		docType->GetSystemId(sysID);
	
		aSource += lt;
		aSource += dt;
		aSource += sp + name +
			   sp + dq + pubID + dq +
			   sp + dq + sysID + dq + gt + cr;
	}		   

	// html node <html ...>
	SetStartTag(NS_LITERAL_STRING("html"), domDocument, aSource);

	nsCOMPtr<nsIDOMNodeList> headList;
	domDocument->GetElementsByTagName(NS_LITERAL_STRING("head"),
					  getter_AddRefs(headList));
	if (!headList) return;

	PRUint32 length;
	headList->GetLength(&length);
	if (!length) return;

	nsCOMPtr<nsIDOMNode> head;
	headList->Item(0, getter_AddRefs(head));

	HTMLSourceFromNode(domDocument, head, nsnull, nsnull,
			   storedir, aSource);
}

void
KzMozWrapper::HTMLSourceFromNode(nsIDOMDocument *domDoc,
				 nsIDOMNode *node,
				 nsISelection *selection,
				 nsIDOMRange *range,
				 const gchar *storedir, 
				 nsAString &string)
{
	nsAutoString tagname;
	NS_NAMED_LITERAL_STRING(lt, "<");
	NS_NAMED_LITERAL_STRING(gt, ">");
	NS_NAMED_LITERAL_STRING(eq, "=");
	NS_NAMED_LITERAL_STRING(dq, "\"");
	NS_NAMED_LITERAL_STRING(sp, " ");
	NS_NAMED_LITERAL_STRING(sl, "/");

	PRBool contains;
	if (selection)
	{
		selection->ContainsNode(node, PR_TRUE, &contains);
		// if node is not contained in seletion, ignore.
		if(!contains)
			return;
	}

	nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(node);
	if (element)
	{
		element->GetTagName(tagname);
		ToLowerCase(tagname);
		string += lt + tagname;
	
		char *relattr =  NULL;
		GetAttributeFromNode(node, NS_LITERAL_STRING("rel"), &relattr);
				
		nsCOMPtr<nsIDOMNamedNodeMap> attrs;
		node->GetAttributes(getter_AddRefs(attrs));
		if (attrs)
		{
			PRUint32 index, length;
			attrs->GetLength(&length);
			for (index = 0; index < length; index++)
			{
				nsCOMPtr<nsIDOMNode> attr;
				attrs->Item(index, getter_AddRefs(attr));
				nsAutoString name, value;
				attr->GetNodeName(name);
				attr->GetNodeValue(value);
				value.Assign(nsEscapeHTML2(value.get(),
							   value.Length()));
				
				string += sp + name + eq;

				// convert img src address to local file name
				if ((tagname.EqualsIgnoreCase("img") && 
				     name.EqualsIgnoreCase("src")) ||
				    (name.EqualsIgnoreCase("background")))
				{
					nsCAutoString uri; 
					nsAutoString localfile;
					ResolveURI(domDoc, value, uri);
					GetFileToLocal(uri, storedir,
						       "images", localfile);
					
					string += dq + localfile + dq;
				}
				else if (tagname.EqualsIgnoreCase("link") && 
				         name.EqualsIgnoreCase("href") &&
					 relattr && 
					 !strcasecmp(relattr, "stylesheet"))
				{
					nsCAutoString uri; 
					nsAutoString localfile;
					ResolveURI(domDoc, value, uri);
					
					GetFileToLocal(uri, storedir,
						       "css", localfile);
					
					string += dq + localfile + dq;
				}
				else if (tagname.EqualsIgnoreCase("a") && 
					 name.EqualsIgnoreCase("href"))
				{
					nsCAutoString uri;
					ResolveURI(domDoc, value, uri);
					string += dq + NS_ConvertUTF8toUCS2(uri) + dq;
				}
				else if (tagname.EqualsIgnoreCase("meta") && 
					 name.EqualsIgnoreCase("content"))
				{
					// change the encoding
					PRInt32 find, start, end;
					
					find = value.Find("charset=", PR_TRUE, 0, -1);
					if (find != kNotFound)
					{
						start = find + 8;
						end = value.FindCharInSet(";", start);
						if (end == kNotFound)	
							end = value.Length();
						value.Cut(start, end - start);
						value.Insert(NS_LITERAL_STRING("UTF-8"), start);
					}
					string += dq + value + dq;
				}
				else
				{
					string += dq + value + dq;
				}

			}
		}
		if (relattr) 
			g_free(relattr);

		// img,hr,br,input -> <img .. />,<hr />, <br />, <input .. /> 
		if (tagname.EqualsIgnoreCase("img") ||
		    tagname.EqualsIgnoreCase("hr") ||
		    tagname.EqualsIgnoreCase("br") ||
		    tagname.EqualsIgnoreCase("meta") ||
		    tagname.EqualsIgnoreCase("link") ||
		    tagname.EqualsIgnoreCase("input"))
			string += sp + sl + gt;
		else
			string += gt;
	}

	nsAutoString text;
	nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(node);
	if (textNode) // if it's a text node, get the text
	{
		nsCOMPtr<nsIDOMNode> startNode;
		nsCOMPtr<nsIDOMNode> endNode;
		
		if (range)
		{
			range->GetStartContainer(getter_AddRefs(startNode));
			range->GetEndContainer(getter_AddRefs(endNode));
		
			if (node == startNode && node == endNode)
			{
				PRInt32 startOffset, endOffset;
				range->GetStartOffset(&startOffset);
				range->GetEndOffset(&endOffset);
				textNode->SubstringData(startOffset,
							endOffset-startOffset,
							text);
			}
			else if (node == startNode)
			{
				PRInt32 startOffset;
				PRUint32 strLength;
				textNode->GetLength(&strLength);
				range->GetStartOffset(&startOffset);
				textNode->SubstringData(startOffset,
							strLength-startOffset,
							text);
			}
			else if (node == endNode)
			{
				PRInt32 endOffset;
				range->GetEndOffset(&endOffset);
				textNode->SubstringData(0,
							endOffset,
							text);
			}
			else 
			{
				textNode->GetData(text);
			}
		}
		else 
		{
			textNode->GetData(text);
		}
		text.Assign(nsEscapeHTML2(text.get(),
					  text.Length()));
				
		string += text;
	}

	nsCOMPtr<nsIDOMNodeList> childNodeList;
	node->GetChildNodes(getter_AddRefs(childNodeList));
	if (childNodeList)
	{
		PRUint32 index, length;
		childNodeList->GetLength(&length);
		for (index = 0; index < length; index++)
		{
			nsCOMPtr<nsIDOMNode> child;
			childNodeList->Item(index, getter_AddRefs(child));
			
			if (selection)
				selection->ContainsNode(child, PR_TRUE, &contains);
			else 
				contains = PR_TRUE;
			if (contains)
			{
				HTMLSourceFromNode(domDoc,
						   child, 
						   selection,
						   range,
						   storedir, 
						   string);
			}
		}
	}

	if (element)
	{
		if (!tagname.EqualsIgnoreCase("br") &&
		    !tagname.EqualsIgnoreCase("hr") &&
		    !tagname.EqualsIgnoreCase("input") &&
		    !tagname.EqualsIgnoreCase("img") &&
		    !tagname.EqualsIgnoreCase("meta") &&
		    !tagname.EqualsIgnoreCase("link"))
		{
			string += lt + sl + tagname + gt;
		}
	}
}

// this function is picked from galeon-1.3.13
nsresult
KzMozWrapper::GetCacheEntryDescriptor(const nsAString &aKey,
				      nsICacheEntryDescriptor **aCacheEntryDescriptor)
{
	nsresult rv;

	nsCOMPtr<nsICacheService> cacheService =
		do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
	if (NS_FAILED(rv) || !cacheService) return NS_ERROR_FAILURE;


	nsCOMPtr<nsICacheSession> cacheSession;
	rv = cacheService->CreateSession("HTTP",
					 nsICache::STORE_ANYWHERE,
					 nsICache::STREAM_BASED,
					 getter_AddRefs(cacheSession));
	if(NS_FAILED(rv) || !cacheSession) return NS_ERROR_FAILURE;

	cacheSession->SetDoomEntriesIfExpired(PR_FALSE);
		
	nsCOMPtr<nsICacheEntryDescriptor> cacheEntryDescriptor;
	rv = cacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(aKey).get(),
					  nsICache::ACCESS_READ,
					  nsICache::NON_BLOCKING,
					  aCacheEntryDescriptor);

	if (NS_FAILED(rv) || !aCacheEntryDescriptor)
	{
		rv = cacheService->CreateSession("FTP",
						 nsICache::STORE_ANYWHERE,
						 nsICache::STREAM_BASED,
						 getter_AddRefs(cacheSession));
		if(NS_FAILED(rv) || !cacheSession) return NS_ERROR_FAILURE;

		cacheSession->SetDoomEntriesIfExpired (PR_FALSE);
		
		return cacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(aKey).get(),
						    nsICache::ACCESS_READ,
						    nsICache::NON_BLOCKING,
						    aCacheEntryDescriptor);
	}

	return NS_OK;
}


void
KzMozWrapper::GetFileToLocal (const nsACString &URI,
			      const gchar *storedir,
			      const gchar *type, 
			      nsAString &LocalFile)
{
	nsresult rv;
	NS_NAMED_LITERAL_STRING(sl, "/");

	nsCOMPtr<nsICacheEntryDescriptor> cacheEntryDescriptor;
	rv = GetCacheEntryDescriptor(NS_ConvertUTF8toUCS2(URI),
				     getter_AddRefs(cacheEntryDescriptor));

	if (NS_SUCCEEDED(rv) && cacheEntryDescriptor)
	{
		PRUint32 dataSize = 0;
		nsCOMPtr<nsIInputStream> inStream;

		gchar *dir, *buf;
		gchar *uri = ToNewCString(URI);
		gchar *filename = create_filename_from_uri(uri);

		dir = g_strconcat(g_get_home_dir(),
				  "/.kazehakase/",
				  storedir, "/",
				  type, /* images or css */ 
				  "/",
				  filename,
				  NULL);

		cacheEntryDescriptor->GetDataSize(&dataSize);
		cacheEntryDescriptor->OpenInputStream(0, getter_AddRefs(inStream));

		buf = g_new0(gchar, dataSize);

		inStream->Read(buf, dataSize, &rv);
		inStream->Close();
		
		LocalFile.Assign(NS_ConvertUTF8toUCS2(type));
		LocalFile += sl;
		LocalFile.Append(NS_ConvertUTF8toUCS2(filename));

		nsCOMPtr<nsILocalFile> imageFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
		imageFile->InitWithPath(NS_ConvertUTF8toUCS2(dir));
		imageFile->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
		nsCOMPtr<nsIOutputStream> outStream;
		NS_NewLocalFileOutputStream(getter_AddRefs(outStream),
					    imageFile,
					    -1,
					    0600);
		outStream->Write(buf, dataSize, &rv);
		outStream->Close();

		g_free(filename);
		g_free(dir);
		g_free(buf);
		g_free(uri);
	}
}


nsresult
KzMozWrapper::Print (void)
{
	nsresult rv;
        nsCOMPtr<nsIPrintSettings> options;

	g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

	nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser, &rv));
	if (NS_FAILED(rv) || !print) return NS_ERROR_FAILURE;

	print->GetGlobalPrintSettings(getter_AddRefs(options));
	options->SetPaperSize(nsIPrintSettings::kPaperSizeNativeData);
	options->SetPrintSilent(PR_FALSE);
	
//	KzMozProgressListener *aProgress = new KzMozProgressListener();
	rv = print->Print(options, nsnull);

	return rv;
}

nsresult
KzMozWrapper::PrintPreview (void)
{
	nsresult rv;
        nsCOMPtr<nsIPrintSettings> options;

	g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

	nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser, &rv));
	if (NS_FAILED(rv) || !print) return NS_ERROR_FAILURE;

	print->GetGlobalPrintSettings(getter_AddRefs(options));
	options->SetPaperSize(nsIPrintSettings::kPaperSizeNativeData);
	rv = print->PrintPreview(options, mDOMWindow, nsnull);

	return rv;
}

// these functions were picked from Galeon-1.3.17.

nsresult
KzMozWrapper::SetZoom (float aZoom, PRBool reflow)
{
	nsresult result;

	nsCOMPtr<nsIDocShell> DocShell;
	result = GetDocShell (getter_AddRefs(DocShell));
	if (NS_FAILED(result) || !DocShell) return NS_ERROR_FAILURE;

	if (reflow)
	{
		nsCOMPtr<nsIContentViewer> contentViewer;	
		result = DocShell->GetContentViewer (getter_AddRefs(contentViewer));
		if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE;

		nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer,
								  &result);
		if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE;

		return mdv->SetTextZoom (aZoom);
	}
	else
	{
		SetZoomOnDocshell (aZoom, DocShell);

		nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryInterface(DocShell));
		if (docShellNode)
		{
			PRInt32 i;
			PRInt32 n;
			docShellNode->GetChildCount(&n);
			for (i=0; i < n; i++) 
			{
				nsCOMPtr<nsIDocShellTreeItem> child;
				docShellNode->GetChildAt(i, getter_AddRefs(child));
				nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
				if (childAsShell) 
				{
					return SetZoomOnDocshell (aZoom, childAsShell);
				}
			}
		}
	}

	return NS_OK;
}

nsresult
KzMozWrapper::SetZoomOnDocshell (float aZoom, nsIDocShell *DocShell)
{
	nsresult result;
#if MOZILLA_SNAPSHOT > 16
	nsCOMPtr<nsPresContext> PresContext;
#else
	nsCOMPtr<nsIPresContext> PresContext;
#endif
	result = DocShell->GetPresContext (getter_AddRefs(PresContext));
	if (NS_FAILED(result) || !PresContext) return NS_ERROR_FAILURE;

#if MOZILLA_SNAPSHOT > 13
	nsIDeviceContext *DeviceContext(nsnull);
	DeviceContext = PresContext->DeviceContext();
	if (!DeviceContext) return NS_ERROR_FAILURE;
#else					
	nsCOMPtr<nsIDeviceContext> DeviceContext;
	result = PresContext->GetDeviceContext (getter_AddRefs(DeviceContext));
	if (NS_FAILED(result) || !DeviceContext) return NS_ERROR_FAILURE;
#endif

	return DeviceContext->SetTextZoom (aZoom);
}

nsresult
KzMozWrapper::GetZoom (float *aZoom)
{
	nsresult result;

	nsCOMPtr<nsIDocShell> DocShell;
	result = GetDocShell (getter_AddRefs(DocShell));
	if (NS_FAILED(result) || !DocShell) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIContentViewer> contentViewer;	
	result = DocShell->GetContentViewer (getter_AddRefs(contentViewer));
	if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer,
								  &result);
	if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE;

	return mdv->GetTextZoom (aZoom);
}

nsresult
KzMozWrapper::SetImageZoom (float aZoom)
{
	nsresult rv;
	nsCOMPtr<nsIDOMDocument> domDoc;
        rv = GetMainDomDocument(getter_AddRefs(domDoc));
        if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMNodeList> nodeList;
	rv = domDoc->GetElementsByTagName(NS_LITERAL_STRING("img"),
					  getter_AddRefs(nodeList));
        if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;

	PRUint32 num;
	rv = nodeList->GetLength(&num);
	if (NS_FAILED(rv) || num < 1) return NS_ERROR_FAILURE;

	for (PRUint32 i = 0; i < num; i++)
	{
		nsCOMPtr<nsIDOMNode> node;
		rv = nodeList->Item(i, getter_AddRefs(node));
		if (NS_FAILED(rv) || !node) continue;
		nsCOMPtr<nsIDOMHTMLImageElement> img;
		img = do_QueryInterface(node);
		PRInt32 width = 0, height = 0;

		char *width_str =  NULL;
		GetAttributeFromNode(node, NS_LITERAL_STRING("width"),
				     &width_str);
		if (!width_str) continue;

		if (str_isdigit(width_str))
			width = atoi(width_str);
		g_free(width_str);
		
		char *height_str =  NULL;
		GetAttributeFromNode(node, NS_LITERAL_STRING("height"),
				     &height_str);
		if (!height_str) continue;
	
		if (str_isdigit(height_str))
			height = atoi(height_str);
		g_free(height_str);

		if (width == 0 || height == 0)
			continue;

		width = (PRInt32)(width * aZoom);
		height = (PRInt32)(height * aZoom);
		nsCOMPtr<nsIDOMElement> elm;
		elm = do_QueryInterface(node);
		nsAutoString style_value;
		gchar *v;
		v = g_strdup_printf("width: %dpx; height: %dpx;",
				    width, height);
		style_value.Assign(NS_ConvertUTF8toUCS2(v));
		elm->SetAttribute(NS_LITERAL_STRING("style"), style_value);
		g_free(v);
	}
	
	return NS_OK;
}

nsresult
KzMozWrapper::GetLinksFromWindow (nsIDOMWindow *domWindow,
				  GList **list,
				  nsISelection *selection, 
				  gboolean selected_only)
{
	nsresult rv;
	PRUint32 num = 0;
	gboolean flag = FALSE;

        // get frame window
        nsCOMPtr<nsIDOMWindowCollection> frames;
        domWindow->GetFrames(getter_AddRefs(frames));

        if (frames)
	{
		frames->GetLength(&num);
	}

	if (num != 0)
	{
		for (PRUint32 i = 0; i < num; i++)
		{
			nsCOMPtr<nsIDOMWindow> childWindow;
	                frames->Item(i, getter_AddRefs(childWindow));
	                rv = GetLinksFromWindow(childWindow, list,
					        selection, selected_only);
	        	if (NS_SUCCEEDED(rv))
				flag |= TRUE;
		}
	}
	else
	{
		nsCOMPtr<nsIDOMDocument> domDoc;
		domWindow->GetDocument(getter_AddRefs(domDoc));

		nsCOMPtr<nsIDOMNodeList> nodeList;
		rv = domDoc->GetElementsByTagName(NS_LITERAL_STRING("a"),
						  getter_AddRefs(nodeList));
	        if (NS_FAILED(rv) || !nodeList) return NS_ERROR_FAILURE;

		PRUint32 num;
		rv = nodeList->GetLength(&num);
		if (NS_FAILED(rv) || num < 1) return NS_ERROR_FAILURE;

		// store links to GList
		nsCOMPtr<nsIDOMNode> node;
		for (PRUint32 i = 0; i < num; i++)
		{
			rv = nodeList->Item(i, getter_AddRefs(node));
			if (NS_FAILED(rv) || !node) continue;

			// check whether the selection contains these nodes or not.
			if (selected_only)
			{
				PRBool contains;
				selection->ContainsNode(node, PR_TRUE, &contains);
				if (!contains) continue;
			}
			gchar *uri = NULL, *title = NULL;
			GetLinkAndTitleFromNode(domDoc, node,
					        &uri, &title);
			if (uri && *uri)
			{
				KzBookmark *link;
				link = kz_bookmark_new_with_attrs(title, uri, NULL);
				*list = g_list_append(*list, link);
			}
			g_free(uri);
			g_free(title);
			flag |= TRUE;
		}
	}

	return flag ? NS_OK : NS_ERROR_FAILURE;
}

nsresult 
KzMozWrapper::GetAttributeFromNode (nsIDOMNode *node, const nsAString& attr, char **value)
{
     	nsresult result;

	nsCOMPtr<nsIDOMNamedNodeMap> attributes;
	result = node->GetAttributes(getter_AddRefs(attributes));
	if (!NS_SUCCEEDED (result) || !attributes) return NS_ERROR_FAILURE;

	nsCOMPtr<nsIDOMNode> attrNode;
	result = attributes->GetNamedItem (attr, getter_AddRefs(attrNode));
	if (!NS_SUCCEEDED(result) || !attrNode)  return NS_ERROR_FAILURE;

	nsAutoString nodeValue;

	result = attrNode->GetNodeValue(nodeValue);
	if (!NS_SUCCEEDED(result))  return NS_ERROR_FAILURE;

	*value = ToNewCString(nodeValue);
	return NS_OK;
}

nsresult
KzMozWrapper::GetLinkFromNode (nsIDOMDocument *domDoc, nsIDOMNode *node,
		               gchar **url)
{
	if (url) *url = NULL;

	// get url
	char *hrefattr =  NULL;
	GetAttributeFromNode(node, NS_LITERAL_STRING("href"), &hrefattr);
	if (!hrefattr) return NS_ERROR_FAILURE;	

	nsAutoString hrefa;
	hrefa.AssignWithConversion(hrefattr);

	nsCString hrefc,linkc;
	hrefc.AssignWithConversion(hrefa);

	nsIURI *baseURI;
	nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
	if (!doc) return NS_ERROR_FAILURE;
	nsresult rv;
#if MOZILLA_SNAPSHOT > 12
	baseURI = doc->GetBaseURI();
#elif MOZILLA_SNAPSHOT > 11
	baseURI = doc->GetBaseURL();
#elif MOZILLA_SNAPSHOT > 9
	rv = doc->GetBaseURL(&baseURI);
#else
	rv = doc->GetBaseURL(baseURI);
#endif	
	rv = baseURI->Resolve(hrefc,linkc);

	*url = ToNewCString(linkc);

	g_free(hrefattr);

	return NS_OK;
}

nsresult
KzMozWrapper::GetLinkAndTitleFromNode (nsIDOMDocument *domDoc, nsIDOMNode *node,
			               gchar **url, gchar **title)
{
	nsresult rv;

	if (title) *title = NULL;
	if (url) *url = NULL;

	// get url
	GetLinkFromNode(domDoc, node, url);

	// get title
	nsCOMPtr<nsIDOMNamedNodeMap> attributes;
	node->GetAttributes(getter_AddRefs(attributes));

	nsCOMPtr<nsIDOMNode> hrefNode;
	attributes->GetNamedItem(NS_LITERAL_STRING("href"), getter_AddRefs(hrefNode));
	if (!hrefNode) return NS_ERROR_FAILURE;

	nsAutoString linkhtml;
	nsCOMPtr<nsIDOMNSHTMLElement> nsElement;

	nsElement = do_QueryInterface(node);
	if (!nsElement) return NS_ERROR_FAILURE;

	rv = nsElement->GetInnerHTML(linkhtml);
	if (NS_SUCCEEDED(rv) &&
	    NS_ConvertUCS2toUTF8(linkhtml).get()) 
	{
		*title = g_strdup(NS_ConvertUCS2toUTF8(linkhtml).get());
	}

	return NS_OK;
}

