/*******************************************************************************
 * Copyright (c) 2003, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.browser;

import java.net.*;
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.C;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.ole.win32.*;
import org.eclipse.swt.widgets.*;

class IE extends WebBrowser {

	OleFrame frame;
	WebSite site;
	OleAutomation auto;
	OleListener domListener;
	OleAutomation[] documents = new OleAutomation[0];

	boolean back, forward, delaySetText, ignoreDispose, ignoreTraverse, performingInitialNavigate;
	boolean installFunctionsOnDocumentComplete, untrustedText, isRefresh, isAboutBlank;
	Point location;
	Point size;
	boolean addressBar = true, menuBar = true, statusBar = true, toolBar = true;
	long /*int*/ globalDispatch;
	String html, lastNavigateURL, uncRedirect;
	Object[] pendingText, pendingUrl;
	int style, lastKeyCode, lastCharCode;
	int lastMouseMoveX, lastMouseMoveY;

	static boolean Initialized;
	static int IEVersion, PDFCount;
	static String ProgId = "Shell.Explorer";	//$NON-NLS-1$

	static final int BeforeNavigate2 = 0xfa;
	static final int CommandStateChange = 0x69;
	static final int DocumentComplete = 0x103;
	static final int DownloadComplete = 0x68;
	static final int NavigateComplete2 = 0xfc;
	static final int NewWindow2 = 0xfb;
	static final int OnMenuBar = 0x100;
	static final int OnStatusBar = 0x101;
	static final int OnToolBar = 0xff;
	static final int OnVisible = 0xfe;
	static final int ProgressChange = 0x6c;
	static final int RegisterAsBrowser = 0x228;
	static final int StatusTextChange = 0x66;
	static final int TitleChange = 0x71;
	static final int WindowClosing = 0x107;
	static final int WindowSetHeight = 0x10b;
	static final int WindowSetLeft = 0x108;
	static final int WindowSetResizable = 0x106;
	static final int WindowSetTop = 0x109;
	static final int WindowSetWidth = 0x10a;
	static final int NavigateError = 0x10f;

	static final short CSC_NAVIGATEFORWARD = 1;
	static final short CSC_NAVIGATEBACK = 2;
	static final int INET_E_DEFAULT_ACTION = 0x800C0011;
	static final int INET_E_RESOURCE_NOT_FOUND = 0x800C0005;
	static final int READYSTATE_COMPLETE = 4;
	static final int URLPOLICY_ALLOW = 0x00;
	static final int URLPOLICY_DISALLOW = 0x03;
	static final int URLPOLICY_JAVA_PROHIBIT = 0x0;
	static final int URLPOLICY_JAVA_LOW = 0x00030000;
	static final int URLZONE_LOCAL_MACHINE = 0;
	static final int URLZONE_INTRANET = 1;
	static final int URLACTION_ACTIVEX_MIN = 0x00001200;
	static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
	static final int URLACTION_ACTIVEX_RUN = 0x00001200;
	static final int URLACTION_FEATURE_ZONE_ELEVATION = 0x00002101;
	static final int URLACTION_JAVA_MIN = 0x00001C00;
	static final int URLACTION_JAVA_MAX = 0x00001Cff;
	static final int URLACTION_SCRIPT_RUN = 0x00001400;
	
	static final int DISPID_AMBIENT_DLCONTROL = -5512;
	static final int DLCTL_DLIMAGES = 0x00000010;
	static final int DLCTL_VIDEOS = 0x00000020;
	static final int DLCTL_BGSOUNDS = 0x00000040;
	static final int DLCTL_NO_SCRIPTS = 0x00000080;
	static final int DLCTL_NO_JAVA = 0x00000100;
	static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
	static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
	static final int DLCTL_DOWNLOADONLY = 0x00000800;
	static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
	static final int DLCTL_RESYNCHRONIZE = 0x00002000;
	static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
	static final int DLCTL_FORCEOFFLINE = 0x10000000;
	static final int DLCTL_NO_CLIENTPULL = 0x20000000;
	static final int DLCTL_SILENT = 0x40000000;
	static final int DOCHOSTUIFLAG_THEME = 0x00040000;
	static final int DOCHOSTUIFLAG_NO3DBORDER  = 0x0000004;
	static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;
	
	static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
	static final String CLSID_SHELLEXPLORER1 = "{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}"; //$NON-NLS-1$
	static final int DEFAULT_IE_VERSION = 9000;
	static final String EXTENSION_PDF = ".pdf";	//$NON-NLS-1$
	static final String HTML_DOCUMENT = "HTML Document";	//$NON-NLS-1$
	static final int MAX_PDF = 20;
	static final char SEPARATOR_OS = System.getProperty ("file.separator").charAt (0); //$NON-NLS-1$
	static final String PROPERTY_IEVERSION = "org.eclipse.swt.browser.IEVersion"; //$NON-NLS-1$
	static final String VALUE_DEFAULT = "default"; //$NON-NLS-1$

	static final String EVENT_DOUBLECLICK = "dblclick"; //$NON-NLS-1$
	static final String EVENT_DRAGEND = "dragend";	//$NON-NLS-1$
	static final String EVENT_DRAGSTART = "dragstart";	//$NON-NLS-1$
	static final String EVENT_KEYDOWN = "keydown";	//$NON-NLS-1$
	static final String EVENT_KEYPRESS = "keypress";	//$NON-NLS-1$
	static final String EVENT_KEYUP = "keyup";	//$NON-NLS-1$
	static final String EVENT_MOUSEMOVE = "mousemove";	//$NON-NLS-1$
	static final String EVENT_MOUSEWHEEL = "mousewheel";	//$NON-NLS-1$
	static final String EVENT_MOUSEUP = "mouseup";	//$NON-NLS-1$
	static final String EVENT_MOUSEDOWN = "mousedown";	//$NON-NLS-1$
	static final String EVENT_MOUSEOUT = "mouseout";	//$NON-NLS-1$
	static final String EVENT_MOUSEOVER = "mouseover";	//$NON-NLS-1$
	static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
	static final String PROPERTY_ALTKEY = "altKey"; //$NON-NLS-1$
	static final String PROPERTY_BUTTON = "button"; //$NON-NLS-1$
	static final String PROPERTY_CTRLKEY = "ctrlKey"; //$NON-NLS-1$
	static final String PROPERTY_DOCUMENT = "Document"; //$NON-NLS-1$
	static final String PROPERTY_FROMELEMENT = "fromElement"; //$NON-NLS-1$
	static final String PROPERTY_KEYCODE = "keyCode"; //$NON-NLS-1$
	static final String PROPERTY_REPEAT = "repeat"; //$NON-NLS-1$
	static final String PROPERTY_RETURNVALUE = "returnValue"; //$NON-NLS-1$
	static final String PROPERTY_SCREENX = "screenX"; //$NON-NLS-1$
	static final String PROPERTY_SCREENY = "screenY"; //$NON-NLS-1$
	static final String PROPERTY_SHIFTKEY = "shiftKey"; //$NON-NLS-1$
	static final String PROPERTY_TOELEMENT = "toElement"; //$NON-NLS-1$
	static final String PROPERTY_TYPE = "type"; //$NON-NLS-1$
	static final String PROPERTY_WHEELDELTA = "wheelDelta"; //$NON-NLS-1$

	static {
		NativeClearSessions = new Runnable() {
			public void run() {
				if (OS.IsPPC) return;
				OS.InternetSetOption (0, OS.INTERNET_OPTION_END_BROWSER_SESSION, 0, 0);
			}
		};

		NativeGetCookie = new Runnable () {
			public void run () {
				if (OS.IsPPC) return;
				TCHAR url = new TCHAR (0, CookieUrl, true);
				TCHAR cookieData = new TCHAR (0, 8192);
				int[] size = new int[] {cookieData.length ()};
				if (!OS.InternetGetCookie (url, null, cookieData, size)) {
					/* original cookieData size was not large enough */
					size[0] /= TCHAR.sizeof;
					cookieData = new TCHAR (0, size[0]);
					if (!OS.InternetGetCookie (url, null, cookieData, size)) return;
				}
				String allCookies = cookieData.toString (0, size[0]);
				StringTokenizer tokenizer = new StringTokenizer (allCookies, ";"); //$NON-NLS-1$
				while (tokenizer.hasMoreTokens ()) {
					String cookie = tokenizer.nextToken ();
					int index = cookie.indexOf ('=');
					if (index != -1) {
						String name = cookie.substring (0, index).trim ();
						if (name.equals (CookieName)) {
							CookieValue = cookie.substring (index + 1).trim ();
							return;
						}
					}
				}
			}
		};

		NativeSetCookie = new Runnable () {
			public void run () {
				if (OS.IsPPC) return;
				TCHAR url = new TCHAR (0, CookieUrl, true);
				TCHAR value = new TCHAR (0, CookieValue, true);
				CookieResult = OS.InternetSetCookie (url, null, value);
			}
		};

		/*
		* Registry entry HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Version indicates
		* which version of IE is installed.  Check this value in order to determine version-specific
		* features that can be enabled.
		*/
		TCHAR key = new TCHAR (0, "Software\\Microsoft\\Internet Explorer", true);	//$NON-NLS-1$
		long /*int*/ [] phkResult = new long /*int*/ [1];
		if (OS.RegOpenKeyEx (OS.HKEY_LOCAL_MACHINE, key, 0, OS.KEY_READ, phkResult) == 0) {
			int [] lpcbData = new int [1];
			TCHAR buffer = new TCHAR (0, "Version", true); //$NON-NLS-1$
			int result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, (TCHAR) null, lpcbData);
			if (result == 0) {
				TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
				result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, lpData, lpcbData);
				if (result == 0) {
					String versionString = lpData.toString (0, lpData.strlen ());
					int index = versionString.indexOf ("."); //$NON-NLS-1$
					if (index != -1) {
						String majorString = versionString.substring (0, index);
						try {
							IEVersion = Integer.valueOf (majorString).intValue ();
						} catch (NumberFormatException e) {
							/* just continue, version-specific features will not be enabled */
						}
					}
				}
			}
			OS.RegCloseKey (phkResult [0]);
		}

		/*
		* Registry entry HKEY_CLASSES_ROOT\Shell.Explorer\CLSID indicates which version of
		* Shell.Explorer to use by default.  We usually want to use this value because it
		* typically points at the newest one that is available.  However it is possible for
		* this registry entry to be changed by another application to point at some other
		* Shell.Explorer version.
		*
		* The Browser depends on the Shell.Explorer version being at least Shell.Explorer.2.
		* If it is detected in the registry to be Shell.Explorer.1 then change the progId that
		* will be embedded to explicitly specify Shell.Explorer.2.
		*/
		key = new TCHAR (0, "Shell.Explorer\\CLSID", true);	//$NON-NLS-1$
		phkResult = new long /*int*/ [1];
		if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) == 0) {
			int [] lpcbData = new int [1];
			int result = OS.RegQueryValueEx (phkResult [0], null, 0, null, (TCHAR) null, lpcbData);
			if (result == 0) {
				TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
				result = OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData);
				if (result == 0) {
					String clsid = lpData.toString (0, lpData.strlen ());
					if (clsid.equals (CLSID_SHELLEXPLORER1)) {
						/* Shell.Explorer.1 is the default, ensure that Shell.Explorer.2 is available */
						key = new TCHAR (0, "Shell.Explorer.2", true);	//$NON-NLS-1$
						long /*int*/ [] phkResult2 = new long /*int*/ [1];
						if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult2) == 0) {
							/* specify that Shell.Explorer.2 is to be used */
							OS.RegCloseKey (phkResult2 [0]);
							ProgId = "Shell.Explorer.2";	//$NON-NLS-1$
						}
					}
				}
			}
			OS.RegCloseKey (phkResult [0]);
		}

		if (NativePendingCookies != null) {
			SetPendingCookies (NativePendingCookies);
		}
		NativePendingCookies = null;
	}

public void create(Composite parent, int style) {
	this.style = style;
	frame = new OleFrame(browser, SWT.NONE);

	try {
		site = new WebSite(frame, SWT.NONE, ProgId);
	} catch (SWTException e) {
		browser.dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);
	}

	if (!Initialized) {
		Initialized = true;
		int version = 0;
		String versionProperty = System.getProperty(PROPERTY_IEVERSION);
		if (versionProperty != null) {
			if (versionProperty.equalsIgnoreCase(VALUE_DEFAULT)) {
				version = -1;
			} else {
				try {
					version = Integer.valueOf(versionProperty).intValue();
				} catch (NumberFormatException e) {
					/* 
					 * An invalid value was specified for the IEVersion java property.  Ignore it
					 * and continue with the usual steps for determining the version to specify.
					 */
				}
			}
		}
		if (version == 0) {
			if (IEVersion != 0) {
				version = IEVersion * 1000;
			} else {
				version = DEFAULT_IE_VERSION;
			}
		}

		if (version != -1) {
			long /*int*/[] key = new long /*int*/[1];
			final TCHAR subkey = new TCHAR(0, "Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);	//$NON-NLS-1$
			if (OS.RegCreateKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, null, OS.REG_OPTION_VOLATILE, OS.KEY_WRITE | OS.KEY_QUERY_VALUE, 0, key, null) == 0) {
				TCHAR lpszFile = new TCHAR(0, OS.MAX_PATH);
				OS.GetModuleFileName(0, lpszFile, lpszFile.length());
				String path = lpszFile.toString(0, lpszFile.strlen());
				int index = path.lastIndexOf(SEPARATOR_OS);
				String executable = index != -1 ? path.substring(index + 1) : path;
				final TCHAR lpValueName = new TCHAR(0, executable, true);
				if (OS.RegQueryValueEx(key[0], lpValueName, 0, null, (int[])null, null) == OS.ERROR_FILE_NOT_FOUND) {
					if (OS.RegSetValueEx(key[0], lpValueName, 0, OS.REG_DWORD, new int[] {version}, 4) == 0) {
						parent.getDisplay().addListener(SWT.Dispose, new Listener() {			
							public void handleEvent(Event event) {
								long /*int*/[] key = new long /*int*/[1];
								if (OS.RegOpenKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, OS.KEY_WRITE, key) == 0) {
									OS.RegDeleteValue(key[0], lpValueName);
								}
							}
						});
					}
				}
				OS.RegCloseKey(key[0]);
			}
		}
	}

	site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
	auto = new OleAutomation(site);

	domListener = new OleListener() {
		public void handleEvent (OleEvent e) {
			handleDOMEvent(e);
		}
	};

	Listener listener = new Listener() {
		public void handleEvent(Event e) {
			switch (e.type) {
				case SWT.Dispose: {
					/* make this handler run after other dispose listeners */
					if (ignoreDispose) {
						ignoreDispose = false;
						break;
					}
					ignoreDispose = true;
					browser.notifyListeners (e.type, e);
					e.type = SWT.NONE;

					/* invoke onbeforeunload handlers */
					if (!browser.isClosing) {
						LocationListener[] oldLocationListeners = locationListeners;
						locationListeners = new LocationListener[0];
						site.ignoreAllMessages = true;
						execute ("window.location.href='about:blank'"); //$NON-NLS-1$
						site.ignoreAllMessages = false;
						locationListeners = oldLocationListeners;
					}

					/*
					* It is possible for the Browser's OLE frame to have been disposed
					* by a Dispose listener that was invoked by notifyListeners above,
					* so check for this before unhooking its DOM listeners.
					*/
					if (!frame.isDisposed ()) unhookDOMListeners(documents);

					for (int i = 0; i < documents.length; i++) {
						documents[i].dispose();
					}
					documents = null;

					Enumeration elements = functions.elements ();
					while (elements.hasMoreElements ()) {
						((BrowserFunction)elements.nextElement ()).dispose (false);
					}
					functions = null;

					lastNavigateURL = uncRedirect = null;
					domListener = null;
					if (auto != null) auto.dispose();
					auto = null;
					break;
				}
				case SWT.Resize: {
					frame.setBounds(browser.getClientArea());
					break;
				}
				case SWT.MouseWheel: {
					/* MouseWheel events come from the DOM */
					e.doit = false;
					break;
				}
				case SWT.FocusIn: {
					site.setFocus();
					break;
				}
				case SWT.Traverse: {
					/*
					 * Tabbing out of the browser can fail as a result of the WebSite
					 * control embedded within the Browser.  The workaround is to
					 * listen for traversals and re-perform the traversal on the
					 * appropriate control.
					 */
					if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS && e.widget instanceof WebSite) {
						/* otherwise will traverse to the Browser control */
						browser.traverse(SWT.TRAVERSE_TAB_PREVIOUS, e);
						e.doit = false;
					}
					/*
					 * Return traversals can sometimes come through TranslateAccelerator,
					 * depending on where focus is within the Browser.  Traversal
					 * events should always be triggered by a key event from the DOM,
					 * so if a Traversal from TranslateAccelerator is detected
					 * (e.doit == true) then stop its propagation.
					 */
					if (e.detail == SWT.TRAVERSE_RETURN && e.doit && e.widget instanceof Browser) {
						e.type = SWT.None;
						e.doit = false;
					}
					break;
				}
			}
		}
	};
	browser.addListener(SWT.Dispose, listener);
	browser.addListener(SWT.FocusIn, listener);
	browser.addListener(SWT.Resize, listener);
	browser.addListener(SWT.Traverse, listener);
	site.addListener(SWT.MouseWheel, listener);
	site.addListener(SWT.Traverse, listener);

	OleListener oleListener = new OleListener() {
		public void handleEvent(OleEvent event) {
			/* callbacks are asynchronous, auto could be disposed */
			if (auto != null) {
				switch (event.type) {
					case BeforeNavigate2: {
						isRefresh = false; /* refreshes do not come through here */

						/* don't send client events if the initial navigate to about:blank has not completed */
						if (performingInitialNavigate) break;

						Variant varResult = event.arguments[1];
						String url = varResult.getString();

						if (uncRedirect != null) {
							/*
							* Silently allow the navigate to proceed if the url is the first segment of a
							* UNC path being navigated to (initiated by the NavigateError listener to show
							* a name/password prompter), or if the url is the full UNC path (initiated by
							* the NavigateComplete listener to redirect from the UNC's first segment to its
 							* full path).
							*/
							if (uncRedirect.equals(url) || (uncRedirect.startsWith(url) && uncRedirect.indexOf('\\', 2) == url.length())) {
								Variant cancel = event.arguments[6];
								if (cancel != null) {
									long /*int*/ pCancel = cancel.getByRef();
									COM.MoveMemory(pCancel, new short[] {COM.VARIANT_FALSE}, 2);
								}
								isAboutBlank = false;
								break;
							} else {
								/*
								* This navigate does not correspond to the previously-initiated
								* UNC navigation so clear this state since it's no longer valid.
								*/
								uncRedirect = null;
							}
						}

						/*
						* Feature in IE.  For navigations on the local machine, BeforeNavigate2's url
						* field contains a string representation of the file path in a non-URL format.
						* In order to be consistent with the other Browser implementations, this
						* case is detected and the string is changed to be a proper url string.
						*/
						if (url.indexOf(":/") == -1 && url.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
							TCHAR filePath = new TCHAR(0, url, true);
							TCHAR urlResult = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
							int[] size = new int[] {urlResult.length()};
							if (!OS.IsWinCE && OS.UrlCreateFromPath(filePath, urlResult, size, 0) == COM.S_OK) {
								url = urlResult.toString(0, size[0]);
							} else {
								url = PROTOCOL_FILE + url.replace('\\', '/');
							}
						}

						/* Disallow local file system accesses if the browser content is untrusted */
						if (url.startsWith(PROTOCOL_FILE) && _getUrl().startsWith(ABOUT_BLANK) && untrustedText) {
							Variant cancel = event.arguments[6];
							if (cancel != null) {
								long /*int*/ pCancel = cancel.getByRef();
								COM.MoveMemory(pCancel, new short[] {COM.VARIANT_TRUE}, 2);
							}
							break;
						}

						LocationEvent newEvent = new LocationEvent(browser);
						newEvent.display = browser.getDisplay();
						newEvent.widget = browser;
						newEvent.location = url;
						newEvent.doit = true;
						for (int i = 0; i < locationListeners.length; i++) {
							locationListeners[i].changing(newEvent);
						}
						boolean doit = newEvent.doit && !browser.isDisposed(); 
						Variant cancel = event.arguments[6];
						if (cancel != null) {
							long /*int*/ pCancel = cancel.getByRef();
							COM.MoveMemory(pCancel, new short[] {doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
						}
						if (doit) {
							varResult = event.arguments[0];
							IDispatch dispatch = varResult.getDispatch();
							Variant variant = new Variant(auto); /* does not need to be disposed */
							IDispatch top = variant.getDispatch();
							if (top.getAddress() == dispatch.getAddress()) {
								isAboutBlank = url.startsWith(ABOUT_BLANK);
							}
						}
						break;
					}
					case CommandStateChange: {
						boolean enabled = false;
						Variant varResult = event.arguments[0];
						int command = varResult.getInt();
						varResult = event.arguments[1];
						enabled = varResult.getBoolean();
						switch (command) {
							case CSC_NAVIGATEBACK : back = enabled; break;
							case CSC_NAVIGATEFORWARD : forward = enabled; break;
						}
						break;
					}
					case DocumentComplete: {
						if (performingInitialNavigate) {
							/* this event marks the completion of the initial navigate to about:blank */
							performingInitialNavigate = false;

							/* if browser content has been provided by the client then set it now */
							if (pendingText != null) {
								setText((String)pendingText[0], ((Boolean)pendingText[1]).booleanValue());
							} else if (pendingUrl != null) {
								setUrl((String)pendingUrl[0], (String)pendingUrl[1], (String[])pendingUrl[2]);
							}
							pendingText = pendingUrl = null;
							break;
						}

						Variant varResult = event.arguments[0];
						IDispatch dispatch = varResult.getDispatch();

						varResult = event.arguments[1];
						String url = varResult.getString();
						/*
						* Feature in IE.  For navigations on the local machine, DocumentComplete's url
						* field contains a string representation of the file path in a non-URL format.
						* In order to be consistent with the other Browser implementations, this
						* case is detected and the string is changed to be a proper url string.
						*/
						if (url.indexOf(":/") == -1 && url.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
							TCHAR filePath = new TCHAR(0, url, true);
							TCHAR urlResult = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
							int[] size = new int[] {urlResult.length()};
							if (!OS.IsWinCE && OS.UrlCreateFromPath(filePath, urlResult, size, 0) == COM.S_OK) {
								url = urlResult.toString(0, size[0]);
							} else {
								url = PROTOCOL_FILE + url.replace('\\', '/');
							}
						}
						if (html != null && url.equals(ABOUT_BLANK)) {
							if (delaySetText) {
								delaySetText = false;
								browser.getDisplay().asyncExec(new Runnable() {
									public void run() {
										if (browser.isDisposed() || html == null) return;
										setHTML(html);
										html = null;
									}
								});
							} else {
								setHTML(html);
								html = null;
							}
						} else {
							Variant variant = new Variant(auto); /* does not need to be disposed */
							IDispatch top = variant.getDispatch();
							LocationEvent locationEvent = new LocationEvent(browser);
							locationEvent.display = browser.getDisplay();
							locationEvent.widget = browser;
							locationEvent.location = url;
							locationEvent.top = top.getAddress() == dispatch.getAddress();
							for (int i = 0; i < locationListeners.length; i++) {
								locationListeners[i].changed(locationEvent);
							}
							if (browser.isDisposed()) return;

							/*
							 * Note.  The completion of the page loading is detected as
							 * described in the MSDN article "Determine when a page is
							 * done loading in WebBrowser Control". 
							 */
							if (globalDispatch != 0 && dispatch.getAddress() == globalDispatch) {
								/* final document complete */
								globalDispatch = 0;

								/* re-install registered functions iff needed */
								IE ie = (IE)browser.webBrowser;
								if (ie.installFunctionsOnDocumentComplete) {
									ie.installFunctionsOnDocumentComplete = false;
									Enumeration elements = functions.elements ();
									while (elements.hasMoreElements ()) {
										BrowserFunction function = (BrowserFunction)elements.nextElement ();
										execute (function.functionString);
									}
								}

								ProgressEvent progressEvent = new ProgressEvent(browser);
								progressEvent.display = browser.getDisplay();
								progressEvent.widget = browser;
								for (int i = 0; i < progressListeners.length; i++) {
									progressListeners[i].completed(progressEvent);
								}
							}
						}
						break;
					}
					case DownloadComplete: {
						/*
						* IE feature.  Some events that swt relies on are not sent when
						* a page is refreshed (as opposed to being navigated to).  The
						* workaround is to use DownloadComplete as an opportunity to
						* do this work.   
						*/

						Enumeration elements = functions.elements ();
						while (elements.hasMoreElements ()) {
							BrowserFunction function = (BrowserFunction)elements.nextElement ();
							execute (function.functionString);
						}

						if (!isRefresh) break;
						isRefresh = false;

						/*
						* DocumentComplete is not received for refreshes, but clients may rely
						* on this event for tasks like hooking javascript listeners, so send the
						* event here.
						*/
						ProgressEvent progressEvent = new ProgressEvent(browser);
						progressEvent.display = browser.getDisplay();
						progressEvent.widget = browser;
						for (int i = 0; i < progressListeners.length; i++) {
							progressListeners[i].completed(progressEvent);
						}						

						break;
					}
					case NavigateComplete2: {
						jsEnabled = jsEnabledOnNextPage;

						Variant varResult = event.arguments[1];
						String url = varResult.getString();
						if (!performingInitialNavigate) {
							varResult = event.arguments[0];
							IDispatch dispatch = varResult.getDispatch();
							Variant variant = new Variant(auto); /* does not need to be disposed */
							IDispatch top = variant.getDispatch();
							if (top.getAddress() == dispatch.getAddress()) {
								isAboutBlank = url.startsWith(ABOUT_BLANK);
								lastNavigateURL = url;
							}
						}

						/*
						* Bug in Acrobat Reader.  Opening > MAX_PDF PDF files causes Acrobat to not
						* clean up its shells properly when the container Browser is disposed.
						* This results in Eclipse crashing at shutdown time because the leftover
						* shells have invalid references to unloaded Acrobat libraries.  The
						* workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
						* files have been opened.
						*/
						boolean isPDF = false;
						String path = null;
						try {
							path = new URL(url).getPath();
						} catch (MalformedURLException e) {
						}
						if (path != null) {
							int extensionIndex = path.lastIndexOf('.');
							if (extensionIndex != -1) {
								String extension = path.substring(extensionIndex);
								if (extension.equalsIgnoreCase(EXTENSION_PDF)) {
									isPDF = true;
									PDFCount++;
									if (PDFCount > MAX_PDF) {
										COM.FreeUnusedLibraries = false;
									}
								}
							}
						}

						if (uncRedirect != null) {
							if (uncRedirect.equals(url)) {
								/* full UNC path has been successfully navigated */
								uncRedirect = null;
								break;
							}
							if (uncRedirect.startsWith(url)) {
								/*
								* UNC first segment has been successfully navigated,
								* now redirect to the full UNC path.
								*/ 
								navigate(uncRedirect, null, null, true);
								break;
							}
							uncRedirect = null;
						}

						varResult = event.arguments[0];
						IDispatch dispatch = varResult.getDispatch();
						if (globalDispatch == 0) globalDispatch = dispatch.getAddress();
	
						OleAutomation webBrowser = varResult.getAutomation();
						Variant variant = new Variant(auto); /* does not need to be disposed */
						IDispatch top = variant.getDispatch();
						boolean isTop = top.getAddress() == dispatch.getAddress();
						if (isTop) {
							/* unhook DOM listeners and unref the last document(s) */
							unhookDOMListeners(documents);
							for (int i = 0; i < documents.length; i++) {
								documents[i].dispose();
							}
							documents = new OleAutomation[0];

							/* re-install registered functions */
							Enumeration elements = functions.elements ();
							while (elements.hasMoreElements ()) {
								BrowserFunction function = (BrowserFunction)elements.nextElement ();
								execute (function.functionString);
							}
						}
						if (!isPDF) {
							hookDOMListeners(webBrowser, isTop);
						}
						webBrowser.dispose();
						break;
					}
					case NavigateError: {
						if (uncRedirect != null) {
							/*
							* This is the second error attempting to reach this UNC path, so
							* it does not exist.  Don't override the default error handling.
							*/
							uncRedirect = null;
							break;
						}
						Variant varResult = event.arguments[1];
						final String url = varResult.getString();
						if (url.startsWith("\\\\")) { //$NON-NLS-1$
							varResult = event.arguments[3];
							int statusCode = varResult.getInt();
							if (statusCode == INET_E_RESOURCE_NOT_FOUND) {
								int index = url.indexOf('\\', 2);
								if (index != -1) {
									final String host = url.substring(0, index);
									Variant cancel = event.arguments[4];
									if (cancel != null) {
										long /*int*/ pCancel = cancel.getByRef();
										COM.MoveMemory(pCancel, new short[] {COM.VARIANT_TRUE}, 2);
									}
									browser.getDisplay().asyncExec(new Runnable() {
										public void run() {
											if (browser.isDisposed()) return;
											/*
											* Feature of IE.  When a UNC path ends with a '\' character IE
											* drops this character when providing the path as an argument
											* to some IE listeners.  Remove this character here too in
											* order to match these other listener argument values.
											*/
											if (url.endsWith("\\")) { //$NON-NLS-1$
												uncRedirect = url.substring(0, url.length() - 1);
											} else {
												uncRedirect = url;
											}
											navigate(host, null, null, true);
										}
									});
								}
							}
						}
						break;
					}
					case NewWindow2: {
						Variant cancel = event.arguments[1];
						long /*int*/ pCancel = cancel.getByRef();
						WindowEvent newEvent = new WindowEvent(browser);
						newEvent.display = browser.getDisplay();
						newEvent.widget = browser;
						newEvent.required = false;
						for (int i = 0; i < openWindowListeners.length; i++) {
							openWindowListeners[i].open(newEvent);
						}
						IE browser = null;
						if (newEvent.browser != null && newEvent.browser.webBrowser instanceof IE) {
							browser = (IE)newEvent.browser.webBrowser;
						}
						boolean doit = browser != null && !browser.browser.isDisposed();
						if (doit) {
							/*
							* When a Browser is opened in a new window, BrowserFunctions that are
							* installed in it in the NavigateComplete2 callback are not retained
							* through the loading of the page.  The workaround is to re-install
							* the functions when DocumentComplete is received. 
							*/
							browser.installFunctionsOnDocumentComplete = true;

							Variant variant = new Variant(browser.auto); /* does not need to be disposed */
							IDispatch iDispatch = variant.getDispatch();
							Variant ppDisp = event.arguments[0];
							long /*int*/ byref = ppDisp.getByRef();
							if (byref != 0) COM.MoveMemory(byref, new long /*int*/[] {iDispatch.getAddress()}, OS.PTR_SIZEOF);
						}
						if (newEvent.required) {
							COM.MoveMemory(pCancel, new short[]{doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
						}
						break;
					}
					case OnMenuBar: {
						Variant arg0 = event.arguments[0];
						menuBar = arg0.getBoolean();
						break;
					}
					case OnStatusBar: {
						Variant arg0 = event.arguments[0];
						statusBar = arg0.getBoolean();
						break;
					}
					case OnToolBar: {
						Variant arg0 = event.arguments[0];
						toolBar = arg0.getBoolean();
						/*
						* Feature in Internet Explorer.  OnToolBar FALSE is emitted 
						* when both tool bar, address bar and menu bar must not be visible.
						* OnToolBar TRUE is emitted when either of tool bar, address bar
						* or menu bar is visible.
						*/
						if (!toolBar) {
							addressBar = false;
							menuBar = false;
						}
						break;
					}
					case OnVisible: {
						Variant arg1 = event.arguments[0];
						boolean visible = arg1.getBoolean();
						WindowEvent newEvent = new WindowEvent(browser);
						newEvent.display = browser.getDisplay();
						newEvent.widget = browser;
						if (visible) {
							if (addressBar) {
								/*
								* Bug in Internet Explorer.  There is no distinct notification for
								* the address bar.  If neither address, menu or tool bars are visible,
								* OnToolBar FALSE is emitted. For some reason, querying the value of
								* AddressBar in this case returns true even though it should not be
								* set visible.  The workaround is to only query the value of AddressBar
								* when OnToolBar FALSE has not been emitted.
								*/
								int[] rgdispid = auto.getIDsOfNames(new String[] { "AddressBar" }); //$NON-NLS-1$
								Variant pVarResult = auto.getProperty(rgdispid[0]);
								if (pVarResult != null) {
									if (pVarResult.getType () == OLE.VT_BOOL) {
										addressBar = pVarResult.getBoolean ();
									}
									pVarResult.dispose ();
								}
							}
							newEvent.addressBar = addressBar;
							newEvent.menuBar = menuBar;
							newEvent.statusBar = statusBar;
							newEvent.toolBar = toolBar;
							newEvent.location = location;
							newEvent.size = size;
							for (int i = 0; i < visibilityWindowListeners.length; i++) {
								visibilityWindowListeners[i].show(newEvent);
							}
							location = null;
							size = null;
						} else {
							for (int i = 0; i < visibilityWindowListeners.length; i++) {
								visibilityWindowListeners[i].hide(newEvent);
							}
						}
						break;
					}
					case ProgressChange: {
						/* don't send client events if the initial navigate to about:blank has not completed */
						if (performingInitialNavigate) break;

						Variant arg1 = event.arguments[0];
						int nProgress = arg1.getType() != OLE.VT_I4 ? 0 : arg1.getInt(); // may be -1
						Variant arg2 = event.arguments[1];
						int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0 : arg2.getInt();
						ProgressEvent newEvent = new ProgressEvent(browser);
						newEvent.display = browser.getDisplay();
						newEvent.widget = browser;
						newEvent.current = nProgress;
						newEvent.total = nProgressMax;
						if (nProgress != -1) {
							for (int i = 0; i < progressListeners.length; i++) {
								progressListeners[i].changed(newEvent);
							}
						}
						break;
					}
					case StatusTextChange: {
						/* don't send client events if the initial navigate to about:blank has not completed */
						if (performingInitialNavigate) break;

						Variant arg1 = event.arguments[0];
						if (arg1.getType() == OLE.VT_BSTR) {
							String text = arg1.getString();
							StatusTextEvent newEvent = new StatusTextEvent(browser);
							newEvent.display = browser.getDisplay();
							newEvent.widget = browser;
							newEvent.text = text;
							for (int i = 0; i < statusTextListeners.length; i++) {
								statusTextListeners[i].changed(newEvent);
							}
						}
						break;
					}
					case TitleChange: {
						/* don't send client events if the initial navigate to about:blank has not completed */
						if (performingInitialNavigate) break;

						Variant arg1 = event.arguments[0];
						if (arg1.getType() == OLE.VT_BSTR) {
							String title = arg1.getString();
							TitleEvent newEvent = new TitleEvent(browser);
							newEvent.display = browser.getDisplay();
							newEvent.widget = browser;
							newEvent.title = title;
							for (int i = 0; i < titleListeners.length; i++) {
								titleListeners[i].changed(newEvent);
							}
						}
						break;
					}
					case WindowClosing: {
						/*
						* Disposing the Browser directly from this callback will crash if the
						* Browser has a text field with an active caret.  As a workaround fire
						* the Close event and dispose the Browser in an async block. 
						*/
						browser.getDisplay().asyncExec(new Runnable() {
							public void run() {
								if (browser.isDisposed()) return;
								WindowEvent newEvent = new WindowEvent(browser);
								newEvent.display = browser.getDisplay();
								newEvent.widget = browser;
								for (int i = 0; i < closeWindowListeners.length; i++) {
									closeWindowListeners[i].close(newEvent);
								}
								browser.dispose();
							}
						});
						Variant cancel = event.arguments[1];
						long /*int*/ pCancel = cancel.getByRef();
						Variant arg1 = event.arguments[0];
						boolean isChildWindow = arg1.getBoolean();
						COM.MoveMemory(pCancel, new short[]{isChildWindow ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
						break;
					}
					case WindowSetHeight: {
						if (size == null) size = new Point(0, 0);
						Variant arg1 = event.arguments[0];
						size.y = arg1.getInt();
						break;
					}
					case WindowSetLeft: {
						if (location == null) location = new Point(0, 0);
						Variant arg1 = event.arguments[0];
						location.x = arg1.getInt();
						break;
					}
					case WindowSetTop: {
						if (location == null) location = new Point(0, 0);
						Variant arg1 = event.arguments[0];
						location.y = arg1.getInt();
						break;
					}
					case WindowSetWidth: {
						if (size == null) size = new Point(0, 0);
						Variant arg1 = event.arguments[0];
						size.x = arg1.getInt();
						break;
					}
				}
			}
		}
	};
	site.addEventListener(BeforeNavigate2, oleListener);
	site.addEventListener(CommandStateChange, oleListener);
	site.addEventListener(DocumentComplete, oleListener);
	site.addEventListener(DownloadComplete, oleListener);
	site.addEventListener(NavigateComplete2, oleListener);
	site.addEventListener(NavigateError, oleListener);
	site.addEventListener(NewWindow2, oleListener);
	site.addEventListener(OnMenuBar, oleListener);
	site.addEventListener(OnStatusBar, oleListener);
	site.addEventListener(OnToolBar, oleListener);
	site.addEventListener(OnVisible, oleListener);
	site.addEventListener(ProgressChange, oleListener);
	site.addEventListener(StatusTextChange, oleListener);
	site.addEventListener(TitleChange, oleListener);
	site.addEventListener(WindowClosing, oleListener);
	site.addEventListener(WindowSetHeight, oleListener);
	site.addEventListener(WindowSetLeft, oleListener);
	site.addEventListener(WindowSetTop, oleListener);
	site.addEventListener(WindowSetWidth, oleListener);

	Variant variant = new Variant(true);
	auto.setProperty(RegisterAsBrowser, variant);
	variant.dispose();

	variant = new Variant(false);
	int[] rgdispid = auto.getIDsOfNames(new String[] {"RegisterAsDropTarget"}); //$NON-NLS-1$
	if (rgdispid != null) auto.setProperty(rgdispid[0], variant);
	variant.dispose();
}

public boolean back() {
	if (!back) return false;
	int[] rgdispid = auto.getIDsOfNames(new String[] { "GoBack" }); //$NON-NLS-1$
	Variant pVarResult = auto.invoke(rgdispid[0]);
	return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
}

public boolean close() {
	boolean result = true;
	int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
	int dispIdMember = rgdispid[0];
	Variant pVarResult = auto.getProperty(dispIdMember);
	if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
		if (pVarResult != null) pVarResult.dispose();
	} else {
		OleAutomation document = pVarResult.getAutomation();
		pVarResult.dispose();
		rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
		/* rgdispid != null implies HTML content */
		if (rgdispid != null) {
			dispIdMember = rgdispid[0];
			pVarResult = document.getProperty(dispIdMember);
			if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
				if (pVarResult != null) pVarResult.dispose();
			} else {
				OleAutomation window = pVarResult.getAutomation();
				pVarResult.dispose();
				rgdispid = window.getIDsOfNames(new String[]{"location"}); //$NON-NLS-1$
				dispIdMember = rgdispid[0];
				pVarResult = window.getProperty(dispIdMember);
				if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
					if (pVarResult != null) pVarResult.dispose();
				} else {
					OleAutomation location = pVarResult.getAutomation();
					pVarResult.dispose();
					LocationListener[] oldListeners = locationListeners;
					locationListeners = new LocationListener[0];
					rgdispid = location.getIDsOfNames(new String[]{"replace"}); //$NON-NLS-1$
					dispIdMember = rgdispid[0];
					Variant[] args = new Variant[] {new Variant("about:blank")}; //$NON-NLS-1$
					pVarResult = location.invoke(dispIdMember, args);
					if (pVarResult == null) {
						/* cancelled by user */
						result = false;
					} else {
						pVarResult.dispose();				
					}
					args[0].dispose();
					locationListeners = oldListeners;
					location.dispose();
				}
				window.dispose();
			}
		}
		document.dispose();
	}
	return result;
}

static Variant createSafeArray(String string) {
	/* Create a pointer and copy the data into it */
	byte[] bytes = string.getBytes();
	int length = bytes.length;
	long /*int*/ pvData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, length);
	C.memmove(pvData, bytes, length);
	int cElements1 = length;

	/* Create a SAFEARRAY in memory */
	long /*int*/ pSafeArray = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, SAFEARRAY.sizeof);
	SAFEARRAY safeArray = new SAFEARRAY();
	safeArray.cDims = 1;
	safeArray.fFeatures = OS.FADF_FIXEDSIZE;
	safeArray.cbElements = 1;
	safeArray.pvData = pvData;
	SAFEARRAYBOUND safeArrayBound = new SAFEARRAYBOUND(); 
	safeArray.rgsabound = safeArrayBound;
	safeArrayBound.cElements = cElements1;
	OS.MoveMemory (pSafeArray, safeArray, SAFEARRAY.sizeof);

	/* Return a Variant that holds the SAFEARRAY */
	long /*int*/ pVariant = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
	short vt = (short)(OLE.VT_ARRAY | OLE.VT_UI1);
	OS.MoveMemory(pVariant, new short[] {vt}, 2);
	OS.MoveMemory(pVariant + 8, new long /*int*/[] {pSafeArray}, C.PTR_SIZEOF);
	return new Variant(pVariant, (short)(OLE.VT_BYREF | OLE.VT_VARIANT));
}

public boolean execute(String script) {
	/* get IHTMLDocument2 */
	int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
	int dispIdMember = rgdispid[0];
	Variant pVarResult = auto.getProperty(dispIdMember);
	if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
		if (pVarResult != null) pVarResult.dispose ();
		return false;
	}
	OleAutomation document = pVarResult.getAutomation();
	pVarResult.dispose();

	/* get IHTMLWindow2 */
	rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
	if (rgdispid == null) {
		/* implies that browser's content is not a IHTMLDocument2 (eg.- acrobat reader) */
		document.dispose();
		return false;
	}
	dispIdMember = rgdispid[0];
	pVarResult = document.getProperty(dispIdMember);
	OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
	pVarResult.dispose();
	document.dispose();
	
	rgdispid = ihtmlWindow2.getIDsOfNames(new String[] { "execScript", "code" }); //$NON-NLS-1$  //$NON-NLS-2$
	Variant[] rgvarg = new Variant[1];
	rgvarg[0] = new Variant(script);
	int[] rgdispidNamedArgs = new int[1];
	rgdispidNamedArgs[0] = rgdispid[1];
	pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
	rgvarg[0].dispose();
	ihtmlWindow2.dispose();
	if (pVarResult == null) return false;
	pVarResult.dispose();
	return true;
}

public boolean forward() {
	if (!forward) return false;
	int[] rgdispid = auto.getIDsOfNames(new String[] { "GoForward" }); //$NON-NLS-1$
	Variant pVarResult = auto.invoke(rgdispid[0]);
	return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
}

public String getBrowserType () {
	return "ie"; //$NON-NLS-1$
}

String getDeleteFunctionString (String functionName) {
	return "window." + functionName + "=undefined"; //$NON-NLS-1$ //$NON-NLS-2$
}

public String getText() {
	/* get the document object */
	int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
	Variant pVarResult = auto.getProperty(rgdispid[0]);
	if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
		if (pVarResult != null) pVarResult.dispose ();
		return ""; //$NON-NLS-1$
	}
	OleAutomation document = pVarResult.getAutomation();
	pVarResult.dispose();

	/* get the html object */
	rgdispid = document.getIDsOfNames(new String[] {"documentElement"}); //$NON-NLS-1$
	if (rgdispid == null) {
		/* implies that the browser is displaying non-HTML content */
		document.dispose();
		return ""; //$NON-NLS-1$
	}
	pVarResult = document.getProperty(rgdispid[0]);
	document.dispose();
	if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
		if (pVarResult != null) pVarResult.dispose ();
		return ""; //$NON-NLS-1$
	}
	OleAutomation element = pVarResult.getAutomation();
	pVarResult.dispose();

	/* get its outerHTML property */
	rgdispid = element.getIDsOfNames(new String[] {"outerHTML"}); //$NON-NLS-1$
	pVarResult = element.getProperty(rgdispid[0]);
	element.dispose();
	if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
		if (pVarResult != null) pVarResult.dispose ();
		return ""; //$NON-NLS-1$
	}
	String result = pVarResult.getString();
	pVarResult.dispose();

	return result;
}

public String getUrl() {
	/*
	 * If the url is "" then return ABOUT_BLANK in order to be consistent
	 * with the other Browser implementations which auto-navigate to ABOUT_BLANK
	 * when opened.
	 */
	String result = _getUrl();
	return result.length() != 0 ? result : ABOUT_BLANK;
}

String _getUrl() {
	int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
	Variant pVarResult = auto.getProperty(rgdispid[0]);
	if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR) return ""; //$NON-NLS-1$
	String result = pVarResult.getString();
	pVarResult.dispose();
	return result;
}

public boolean isBackEnabled() {
	return back;
}

public boolean isForwardEnabled() {
	return forward;
}

public boolean isFocusControl () {
	return site.isFocusControl() || frame.isFocusControl();
}

boolean navigate(String url, String postData, String headers[], boolean silent) {
	int count = 1;
	if (postData != null) count++;
	if (headers != null) count++;
	Variant[] rgvarg = new Variant[count];
	int[] rgdispidNamedArgs = new int[count];
	int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL", "PostData", "Headers" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
	int index = 0;
	rgvarg[index] = new Variant(url);
	rgdispidNamedArgs[index++] = rgdispid[1];
	if (postData != null) {
		rgvarg[index] = createSafeArray(postData);
		rgdispidNamedArgs[index++] = rgdispid[2];
	}
	if (headers != null) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < headers.length; i++) {
			String current = headers[i];
			if (current != null) {
				int sep = current.indexOf(':');
				if (sep != -1) {
					String key = current.substring(0, sep).trim();
					String value = current.substring(sep + 1).trim();
					if (key.length() > 0 && value.length() > 0) {
						buffer.append(key);
						buffer.append(':');
						buffer.append(value);
						buffer.append("\r\n");
					}
				}
			}
		}
		rgvarg[index] = new Variant(buffer.toString());
		rgdispidNamedArgs[index++] = rgdispid[3];
	}
	boolean oldValue = false;
	if (silent && !OS.IsWinCE && IEVersion >= 7) {
		int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
		oldValue = hResult == COM.S_OK;
		OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
	}
	Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
	if (silent && !OS.IsWinCE && IEVersion >= 7) {
		OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
	}
	for (int i = 0; i < count; i++) {
		rgvarg[i].dispose();
	}
	if (pVarResult == null) return false;
	boolean result = pVarResult.getType() == OLE.VT_EMPTY;
	pVarResult.dispose();
	return result;
}

public void refresh() {
	uncRedirect = null;

	/*
	* Bug in Acrobat Reader.  Opening > MAX_PDF PDF files causes Acrobat to not
	* clean up its shells properly when the container Browser is disposed.
	* This results in Eclipse crashing at shutdown time because the leftover
	* shells have invalid references to unloaded Acrobat libraries.  The
	* workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
	* files have been opened.
	*/
	String url = _getUrl();
	int extensionIndex = url.lastIndexOf('.');
	if (extensionIndex != -1) {
		String extension = url.substring(extensionIndex);
		if (extension.equalsIgnoreCase (EXTENSION_PDF)) {
			PDFCount++;
			if (PDFCount > MAX_PDF) {
				COM.FreeUnusedLibraries = false;
			}
		}
	}

	isRefresh = true;
	int[] rgdispid = auto.getIDsOfNames(new String[] { "Refresh" }); //$NON-NLS-1$
	auto.invoke(rgdispid[0]);
}

void setHTML (String string) {
	int charCount = string.length();
	char[] chars = new char[charCount];
	string.getChars(0, charCount, chars, 0);
	int byteCount = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, null, 0, null, null);
	/*
	* Internet Explorer appears to treat the data loaded with 
	* nsIPersistStreamInit.Load as if it were encoded using the default
	* local charset.  There does not seem to be an API to set the
	* desired charset explicitly in this case.  The fix is to
	* prepend the UTF-8 Byte Order Mark signature to the data.
	*/
	byte[] UTF8BOM = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
	long /*int*/ hGlobal = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, UTF8BOM.length + byteCount);
	if (hGlobal != 0) {
		OS.MoveMemory(hGlobal, UTF8BOM, UTF8BOM.length);
		OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, hGlobal + UTF8BOM.length, byteCount, null, null);							
		long /*int*/ [] ppstm = new long /*int*/ [1];
		/* 
		* CreateStreamOnHGlobal is called with the flag fDeleteOnRelease.
		* If the call succeeds the buffer hGlobal is freed automatically
		* when the IStream object is released. If the call fails, free the
		* buffer hGlobal.
		*/
		if (OS.CreateStreamOnHGlobal(hGlobal, true, ppstm) == OS.S_OK) {
			int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
			Variant pVarResult = auto.getProperty(rgdispid[0]);
			IDispatch dispatchDocument = pVarResult.getDispatch();
			long /*int*/ [] ppvObject = new long /*int*/ [1];
			int result = dispatchDocument.QueryInterface(COM.IIDIPersistStreamInit, ppvObject);
			if (result == OS.S_OK) {
				IPersistStreamInit persistStreamInit = new IPersistStreamInit(ppvObject[0]);
				if (persistStreamInit.InitNew() == OS.S_OK) {
					persistStreamInit.Load(ppstm[0]);
				}
				persistStreamInit.Release();
			}
			pVarResult.dispose();
			IUnknown stream = new IUnknown(ppstm[0]);
			stream.Release();
		} else {
			OS.GlobalFree(hGlobal);
		}
	}
}

public boolean setText(final String html, boolean trusted) {
	/*
	* If the browser is navigating to about:blank in response to its first
	* setUrl() invocation then delay setting this text content until the
	* navigate has completed.  about:blank will be re-navigated to in order
	* to ensure that all expected client events are sent.
	*/
	if (performingInitialNavigate) {
		pendingText = new Object[] {html, new Boolean (trusted)};
		pendingUrl = null;
		return true;
	}

	/*
	* If the html field is non-null then the about:blank page is already being
	* loaded from a previous setText() invocation, so no Stop or Navigate is
	* required.  Just set the html that is to be shown.
	*/
	boolean blankLoading = this.html != null;
	this.html = html;
	untrustedText = !trusted;
	if (blankLoading) return true;

	/*
	* Navigate to the blank page and insert the given html when
	* receiving the next DocumentComplete notification.  See the
	* MSDN article "Loading HTML content from a Stream".
	* 
	* Note.  Stop any pending request.  This is required to avoid displaying a
	* blank page as a result of consecutive calls to setUrl and/or setText.  
	* The previous request would otherwise render the new html content and
	* reset the html field before the browser actually navigates to the blank
	* page as requested below.
	* 
	* Feature in Internet Explorer.  Stopping pending requests when no request
	* is pending causes a default page 'Action cancelled' to be displayed.  The
	* workaround is to not invoke 'stop' when no request has been set since
	* that instance was created.
	*/

	/*
	* Stopping the loading of a page causes DocumentComplete events from previous
	* requests to be received before the DocumentComplete for this page.  In such
	* cases we must be sure to not set the html into the browser too soon, since
	* doing so could result in its page being cleared out by a subsequent
	* DocumentComplete.  The Browser's ReadyState can be used to determine whether
	* these extra events will be received or not.
	*/
	if (_getUrl().length() != 0) {
		int[] rgdispid = auto.getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
		Variant pVarResult = auto.getProperty(rgdispid[0]);
		if (pVarResult == null) return false;
		delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
		pVarResult.dispose();
		rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
		auto.invoke(rgdispid[0]);
	}

	int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
	Variant[] rgvarg = new Variant[1];
	rgvarg[0] = new Variant(ABOUT_BLANK);
	int[] rgdispidNamedArgs = new int[1];
	rgdispidNamedArgs[0] = rgdispid[1];
	boolean oldValue = false;
	if (!OS.IsWinCE && IEVersion >= 7) {
		int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
		oldValue = hResult == COM.S_OK;
		OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
	}
	Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
	if (!OS.IsWinCE && IEVersion >= 7) {
		OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
	}
	rgvarg[0].dispose();
	if (pVarResult == null) return false;
	boolean result = pVarResult.getType() == OLE.VT_EMPTY;
	pVarResult.dispose();
	return result;
}

public boolean setUrl(String url, String postData, String headers[]) {
	html = uncRedirect = null;

	/*
	* If the browser has not shown any content yet then first navigate to
	* about:blank to work around IE bug http://support.microsoft.com/kb/320153,
	* then navigate to the requested url once about:blank has loaded.
	*/
	if (_getUrl().length() == 0 && !ABOUT_BLANK.equalsIgnoreCase(url)) {
		pendingText = null;
		pendingUrl = new Object[] {url, postData, headers};
		performingInitialNavigate = true;
		navigate (ABOUT_BLANK, null, null, true);
		return true;
	}

	/*
	* Bug in Internet Explorer.  For some reason, Navigating to an xml document before
	* a previous Navigate has completed will leave the Browser in a bad state if the
	* Navigate to the xml document does not complete.  This bad state causes a GP when
	* the parent window is eventually disposed.  The workaround is to issue a Stop before
	* navigating to any xml document. 
	*/
	if (url.endsWith(".xml")) {	//$NON-NLS-1$
		int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
		auto.invoke(rgdispid[0]);
	}
	return navigate(url, postData, headers, false);
}

public void stop() {
	/*
	* If the browser has not completed its initial navigate to about:blank
	* then do not issue Stop here, as this will display the IE error page.
	* Just clear the pending url and text fields so that any pending content
	* will not be set into the browser when the about:blank navigate completes.
	*/
	if (performingInitialNavigate) {
		pendingText = pendingUrl = null;
		return;
	}

	/*
	* Feature of IE.  Invoking Stop in IE before any content has been shown
	* displays a Navigation Cancelled error page.  The workaround is to not
	* invoke Stop if no content has been shown yet. 
	*/
	if (_getUrl().length() == 0) return;

	/*
	* Ensure that isAboutBlank is set accurately since Stop can be issued at
	* any stage in the page load cycle.
	*/
	isAboutBlank = getUrl().startsWith(ABOUT_BLANK);

	uncRedirect = null;
	int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
	auto.invoke(rgdispid[0]);
}

boolean translateMnemonics () {
	return false;
}

void handleDOMEvent (OleEvent e) {
	if (e.arguments == null || e.arguments.length == 0) return; /* for IE5 */

	Variant arg = e.arguments[0];
	OleAutomation event = arg.getAutomation();
	int[] rgdispid = event.getIDsOfNames(new String[]{ PROPERTY_TYPE });
	int dispIdMember = rgdispid[0];
	Variant pVarResult = event.getProperty(dispIdMember);
	String eventType = pVarResult.getString();
	pVarResult.dispose();

	if (eventType.equals(EVENT_KEYDOWN)) {
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		lastKeyCode = translateKey (pVarResult.getInt());
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames (new String[] {PROPERTY_RETURNVALUE});
		pVarResult = event.getProperty (rgdispid[0]);
		boolean consume = pVarResult != null && pVarResult.getType () == OLE.VT_BOOL && !pVarResult.getBoolean ();
		pVarResult.dispose ();

		MSG msg = new MSG ();
		int flags = OS.PM_NOYIELD | (consume ? OS.PM_REMOVE : OS.PM_NOREMOVE);
		if (OS.PeekMessage (msg, frame.handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
			/* a keypress will be received for this key so don't send KeyDown here */
			event.dispose();
			return;
		}

		if (consume) {
			/* 
			 * an event should not be sent if another listener has vetoed the
			 * KeyDown (this is for non-character cases like arrow keys, etc.)
			 */
			event.dispose();
			return;
		}

		/* if this is a repeating key then an event should not be fired for it */
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_REPEAT });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		boolean repeating = pVarResult.getBoolean();
		pVarResult.dispose();
		if (repeating) {
			event.dispose();
			return;
		}

		int mask = 0;
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.ALT;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.CTRL;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
		pVarResult.dispose();

		Event keyEvent = new Event ();
		keyEvent.widget = browser;
		keyEvent.type = SWT.KeyDown;
		keyEvent.keyCode = lastKeyCode;
		keyEvent.stateMask = mask;
		keyEvent.stateMask &= ~lastKeyCode;		/* remove current keydown if it's a state key */
		/*
		* keypress events are not received for Backspace, Enter, Delete and
		* Tab, so KeyDown events are sent for them here.  Set the KeyDown
		* event's character field and IE's lastCharCode field for these keys
		* so that the Browser's key events are consistent with other controls.
		*/
		switch (lastKeyCode) {
			case SWT.BS: lastCharCode = keyEvent.character = SWT.BS; break;
			case SWT.CR: lastCharCode = keyEvent.character = SWT.CR; break;
			case SWT.DEL: lastCharCode = keyEvent.character = SWT.DEL; break;
			case SWT.TAB: lastCharCode = keyEvent.character = SWT.TAB; break;
		}

		if (!sendKeyEvent(keyEvent)) {
			rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
			dispIdMember = rgdispid[0];
			Variant pVarFalse = new Variant(false);
			event.setProperty(dispIdMember, pVarFalse);
			pVarFalse.dispose();
		}

		/*
		* Pressing F5 refreshes the current page.  If this is about to happen
		* then set isRefresh to true so that received IE events will be treated
		* accordingly.
		*/
		if (lastKeyCode == SWT.F5) isRefresh = true;

		event.dispose();
		return;
	}

	if (eventType.equals(EVENT_KEYPRESS)) {
		int mask = 0;
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.CTRL;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.ALT;
		pVarResult.dispose();

		/* in the keypress event the keyCode actually corresponds to the character code */
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		lastCharCode = pVarResult.getInt();
		pVarResult.dispose();

		/*
		* WebSite.TranslateAccelerator() explicitly does not translate OS.VK_RETURN
		* keys, so the PeekMessage check in the keydown handler always allows a
		* KeyDown to be sent for this key.  However, keydown and keypress events are 
		* both sometimes received for OS.VK_RETURN, depending on the page's focus
		* control.  To handle this, do not send a KeyDown for CR or LF here since
		* one is always sent for it from the keydown handler.
		*/
		if (lastCharCode == SWT.CR || lastCharCode == SWT.LF) {
			event.dispose();
			return;
		}

		Event keyEvent = new Event ();
		keyEvent.widget = browser;
		keyEvent.type = SWT.KeyDown;
		keyEvent.keyCode = lastKeyCode;
		keyEvent.character = (char)lastCharCode;
		keyEvent.stateMask = mask;
		if (!sendKeyEvent(keyEvent)) {
			rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
			dispIdMember = rgdispid[0];
			Variant pVarFalse = new Variant(false);
			event.setProperty(dispIdMember, pVarFalse);
			pVarFalse.dispose();
		}

		event.dispose();
		return;
	}

	if (eventType.equals(EVENT_KEYUP)) {
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		int keyCode = translateKey (pVarResult.getInt());
		pVarResult.dispose();

		/*
		* if a key code could not be determined for this key then it's a
		* key for which key events are not sent (eg.- the Windows key)
		*/
		if (keyCode == 0) {
			lastKeyCode = lastCharCode = 0;
			event.dispose();
			return;
		}

		if (keyCode != lastKeyCode) {
			/* keyup does not correspond to the last keydown */
			lastKeyCode = keyCode;
			lastCharCode = 0;
		}

		int mask = 0;
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.CTRL;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.ALT;
		pVarResult.dispose();

		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
		pVarResult.dispose();

		Event keyEvent = new Event ();
		keyEvent.widget = browser;
		keyEvent.type = SWT.KeyUp;
		keyEvent.keyCode = lastKeyCode;
		keyEvent.character = (char)lastCharCode;
		keyEvent.stateMask = mask;
		switch (lastKeyCode) {
			case SWT.SHIFT:
			case SWT.CONTROL:
			case SWT.ALT:
			case SWT.COMMAND: {
				keyEvent.stateMask |= lastKeyCode;
			}
		}
		browser.notifyListeners (keyEvent.type, keyEvent);
		if (!keyEvent.doit) {
			rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
			dispIdMember = rgdispid[0];
			Variant pVarFalse = new Variant(false);
			event.setProperty(dispIdMember, pVarFalse);
			pVarFalse.dispose();
		}

		lastKeyCode = lastCharCode = 0;
		event.dispose();
		return;
	}
	
	/*
	 * Feature in IE. MouseOver/MouseOut events are fired any time the mouse enters
	 * or exits any element within the Browser.  To ensure that SWT events are only
	 * fired for mouse movements into or out of the Browser, do not fire an event if
	 * the element being exited (on MouseOver) or entered (on MouseExit) is within
	 * the Browser.
	 */
	if (eventType.equals(EVENT_MOUSEOVER)) {
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_FROMELEMENT });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
		pVarResult.dispose();
		if (isInternal) {
			event.dispose();
			return;
		}
	}
	if (eventType.equals(EVENT_MOUSEOUT)) {
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_TOELEMENT });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
		pVarResult.dispose();
		if (isInternal) {
			event.dispose();
			return;
		}
	}

	int mask = 0;
	Event newEvent = new Event();
	newEvent.widget = browser;

	/*
	 * The position of mouse events is received in screen-relative coordinates
	 * in order to handle pages with frames, since frames express their event
	 * coordinates relative to themselves rather than relative to their top-
	 * level page.  Convert screen-relative coordinates to be browser-relative.
	 */
	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENX });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	int screenX = pVarResult.getInt();
	pVarResult.dispose();

	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENY });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	int screenY = pVarResult.getInt();
	pVarResult.dispose();
	
	Point position = new Point(screenX, screenY);
	position = browser.getDisplay().map(null, browser, position);
	newEvent.x = position.x; newEvent.y = position.y;

	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	if (pVarResult.getBoolean()) mask |= SWT.CTRL;
	pVarResult.dispose();

	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	if (pVarResult.getBoolean()) mask |= SWT.ALT;
	pVarResult.dispose();

	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
	pVarResult.dispose();

	newEvent.stateMask = mask;

	rgdispid = event.getIDsOfNames(new String[] { PROPERTY_BUTTON });
	dispIdMember = rgdispid[0];
	pVarResult = event.getProperty(dispIdMember);
	int button = pVarResult.getInt();
	pVarResult.dispose();
	switch (button) {
		case 1: button = 1; break;
		case 2: button = 3; break;
		case 4: button = 2; break;
	}

	if (eventType.equals(EVENT_MOUSEDOWN)) {
		newEvent.type = SWT.MouseDown;
		newEvent.button = button;
		newEvent.count = 1;
	} else if (eventType.equals(EVENT_MOUSEUP) || eventType.equals(EVENT_DRAGEND)) {
		newEvent.type = SWT.MouseUp;
		newEvent.button = button != 0 ? button : 1;	/* button assumed to be 1 for dragends */
		newEvent.count = 1;
		switch (newEvent.button) {
			case 1: newEvent.stateMask |= SWT.BUTTON1; break;
			case 2: newEvent.stateMask |= SWT.BUTTON2; break;
			case 3: newEvent.stateMask |= SWT.BUTTON3; break;
			case 4: newEvent.stateMask |= SWT.BUTTON4; break;
			case 5: newEvent.stateMask |= SWT.BUTTON5; break;
		}
	} else if (eventType.equals(EVENT_MOUSEWHEEL)) {
		newEvent.type = SWT.MouseWheel;
		rgdispid = event.getIDsOfNames(new String[] { PROPERTY_WHEELDELTA });
		dispIdMember = rgdispid[0];
		pVarResult = event.getProperty(dispIdMember);
		newEvent.count = pVarResult.getInt () / 120 * 3;
		pVarResult.dispose();
	} else if (eventType.equals(EVENT_MOUSEMOVE)) {
		/*
		* Feature in IE.  Spurious and redundant mousemove events are often received.  The workaround
		* is to not fire MouseMove events whose x and y values match the last MouseMove.  
		*/
		if (newEvent.x == lastMouseMoveX && newEvent.y == lastMouseMoveY) {
			event.dispose();
			return;
		}
		newEvent.type = SWT.MouseMove;
		lastMouseMoveX = newEvent.x; lastMouseMoveY = newEvent.y;
	} else if (eventType.equals(EVENT_MOUSEOVER)) {
		newEvent.type = SWT.MouseEnter;
	} else if (eventType.equals(EVENT_MOUSEOUT)) {
		newEvent.type = SWT.MouseExit;
	} else if (eventType.equals(EVENT_DRAGSTART)) {
		newEvent.type = SWT.DragDetect;
		newEvent.button = 1;	/* button assumed to be 1 for dragstarts */
		newEvent.stateMask |= SWT.BUTTON1;
	}

	event.dispose();
	browser.notifyListeners(newEvent.type, newEvent);

	if (eventType.equals(EVENT_DOUBLECLICK)) {
		newEvent = new Event ();
		newEvent.widget = browser;
		newEvent.type = SWT.MouseDoubleClick;
		newEvent.x = position.x; newEvent.y = position.y;
		newEvent.stateMask = mask;
		newEvent.type = SWT.MouseDoubleClick;
		newEvent.button = 1; /* dblclick only comes for button 1 and does not set the button property */
		newEvent.count = 2;
		browser.notifyListeners (newEvent.type, newEvent);	
	}
}

void hookDOMListeners(OleAutomation webBrowser, final boolean isTop) {
	int[] rgdispid = webBrowser.getIDsOfNames(new String[] { PROPERTY_DOCUMENT });
	int dispIdMember = rgdispid[0];
	Variant pVarResult = webBrowser.getProperty(dispIdMember);
	if (pVarResult == null) return;
	if (pVarResult.getType() == COM.VT_EMPTY) {
		pVarResult.dispose();
		return;
	}
	final OleAutomation document = pVarResult.getAutomation();
	pVarResult.dispose();

	/*
	 * In some cases, such as setting the Browser's content from a string,
	 * NavigateComplete2 is received multiple times for a top-level document.
	 * For cases like this, any previously-hooked DOM listeners must be
	 * removed from the document before hooking the new set of listeners,
	 * otherwise multiple sets of events will be received.  
	 */
	unhookDOMListeners (new OleAutomation[] {document});

	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
	site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
	/* ensure that enter/exit are only fired once, by the top-level document */
	if (isTop) {
		site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
		site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
	}

	OleAutomation[] newDocuments = new OleAutomation[documents.length + 1];
	System.arraycopy(documents, 0, newDocuments, 0, documents.length);
	newDocuments[documents.length] = document;
	documents = newDocuments;
}

void unhookDOMListeners(OleAutomation[] documents) {
	char[] buffer = (COM.IIDIHTMLDocumentEvents2 + '\0').toCharArray();
	GUID guid = new GUID();
	if (COM.IIDFromString(buffer, guid) == COM.S_OK) {
		for (int i = 0; i < documents.length; i++) {
			OleAutomation document = documents[i];
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
			site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
		}
	}
}
}
