/*******************************************************************************
 * Copyright (c) 2000, 2016 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.ole.win32;

import java.io.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.*;
/**
 * OleClientSite provides a site to manage an embedded OLE Document within a container.
 *
 * <p>The OleClientSite provides the following capabilities:
 * <ul>
 *  <li>creates the in-place editor for a blank document or opening an existing OLE Document
 * 	<li>lays the editor out
 *	<li>provides a mechanism for activating and deactivating the Document
 *	<li>provides a mechanism for saving changes made to the document
 * </ul>
 *
 * <p>This object implements the OLE Interfaces IUnknown, IOleClientSite, IAdviseSink,
 * IOleInPlaceSite
 *
 * <p>Note that although this class is a subclass of <code>Composite</code>,
 * it does not make sense to add <code>Control</code> children to it,
 * or set a layout on it.
 * </p><p>
 * <dl>
 *	<dt><b>Styles</b> <dd>BORDER
 *	<dt><b>Events</b> <dd>Dispose, Move, Resize
 * </dl>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
 */
public class OleClientSite extends Composite {

	// Interfaces for this Ole Client Container
	private COMObject  iUnknown;
	COMObject  iOleClientSite;
	private COMObject  iAdviseSink;
	private COMObject  iOleInPlaceSite;
	private COMObject  iOleDocumentSite;

	protected GUID appClsid;
	private GUID objClsid;
	private int  refCount;

	// References to the associated Frame.
	protected OleFrame frame;

	// Access to the embedded/linked Ole Object
	protected IUnknown                  objIUnknown;
	protected IOleObject                 objIOleObject;
	protected IViewObject2             objIViewObject2;
	protected IOleInPlaceObject     objIOleInPlaceObject;
	protected IOleCommandTarget objIOleCommandTarget;
	protected IOleDocumentView    objDocumentView;

	// Related storage information
	protected IStorage tempStorage;     // IStorage interface of the receiver

	// Internal state and style information
	private int     aspect;    // the display aspect of the embedded object, e.g., DvaspectContent or DvaspectIcon
	private int     type;      // Indicates the type of client that can be supported inside this container
	private boolean isStatic;  // Indicates item's display is static, i.e., a bitmap, metafile, etc.
	boolean isActivated;

	private RECT borderWidths = new RECT();
	private RECT indent = new RECT();
	private boolean inUpdate = false;
	private boolean inInit = true;
	private boolean inDispose = false;

	private static final String WORDPROGID = "Word.Document"; //$NON-NLS-1$

	private Listener listener;

	static final int STATE_NONE = 0;
	static final int STATE_RUNNING = 1;
	static final int STATE_INPLACEACTIVE = 2;
	static final int STATE_UIACTIVE = 3;
	static final int STATE_ACTIVE = 4;
	int state = STATE_NONE;

protected OleClientSite(Composite parent, int style) {
	/*
	 * NOTE: this constructor should never be used by itself because it does
	 * not create an Ole Object
	 */
	super(parent, style);

	createCOMInterfaces();

	// install the Ole Frame for this Client Site
	while (parent != null) {
		if (parent instanceof OleFrame){
			frame = (OleFrame)parent;
			break;
		}
		parent = parent.getParent();
	}
	if (frame == null) OLE.error(SWT.ERROR_INVALID_ARGUMENT);
	frame.AddRef();

	aspect   = COM.DVASPECT_CONTENT;
	type     = COM.OLEEMBEDDED;
	isStatic = false;

	listener = new Listener() {
		private int nestedFocusEvents = 0;
		@Override
		public void handleEvent(Event e) {
			switch (e.type) {
			case SWT.Resize :
			case SWT.Move :    onResize(e); break;
			case SWT.Dispose : onDispose(e); break;
			case SWT.FocusIn:
				nestedFocusEvents++;
				onFocusIn(e);
				nestedFocusEvents--;
				if (nestedFocusEvents == 0)
					frame.onFocusIn(e);
				break;
			case SWT.FocusOut:
				nestedFocusEvents++;
				onFocusOut(e);
				nestedFocusEvents--;
				if (nestedFocusEvents == 0)
					frame.onFocusOut(e);
				break;
			case SWT.Paint:    onPaint(e); break;
			case SWT.Traverse: onTraverse(e); break;
			case SWT.KeyDown: /* required for traversal */ break;
			case SWT.Activate: isActivated = true; break;
			case SWT.Deactivate: isActivated = false; break;
			default :
				OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
			}
		}
	};

	frame.addListener(SWT.Resize, listener);
	frame.addListener(SWT.Move, listener);
	addListener(SWT.Dispose, listener);
	addListener(SWT.FocusIn, listener);
	addListener(SWT.FocusOut, listener);
	addListener(SWT.Paint, listener);
	addListener(SWT.Traverse, listener);
	addListener(SWT.KeyDown, listener);
	addListener(SWT.Activate, listener);
	addListener(SWT.Deactivate, listener);
}
/**
 * Create an OleClientSite child widget using the OLE Document type associated with the
 * specified file.  The OLE Document type is determined either through header information in the file
 * or through a Registry entry for the file extension. Use style bits to select a particular look
 * or set of properties.
 *
 * @param parent a composite widget; must be an OleFrame
 * @param style the bitwise OR'ing of widget styles
 * @param file the file that is to be opened in this OLE Document
 *
 * @exception IllegalArgumentException
 * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
 *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
 * @exception SWTException
 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
 *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
 *     <li>ERROR_CANNOT_OPEN_FILE when failed to open file
 *     <li>ERROR_INTERFACE_NOT_FOUND when unable to create callbacks for OLE Interfaces
 *     <li>ERROR_INVALID_CLASSID
 * </ul>
 */
public OleClientSite(Composite parent, int style, File file) {
	this(parent, style);
	try {

		if (file == null || file.isDirectory() || !file.exists())
			OLE.error(OLE.ERROR_INVALID_ARGUMENT);

		// Is there an associated CLSID?
		GUID fileClsid = new GUID();
		char[] fileName = (file.getAbsolutePath()+"\0").toCharArray();
		int result = COM.GetClassFile(fileName, fileClsid);
		if (result != COM.S_OK)	OLE.error(OLE.ERROR_INVALID_CLASSID, result);
		// associated CLSID may not be installed on this machine
		String progID = getProgID(fileClsid);
		if (progID == null)	OLE.error(OLE.ERROR_INVALID_CLASSID, result);

		appClsid = fileClsid;
		OleCreate(appClsid, fileClsid, fileName, file);
	} catch (SWTException e) {
		dispose();
		disposeCOMInterfaces();
		throw e;
	}
}
/**
 * Create an OleClientSite child widget to edit a blank document using the specified OLE Document
 * application.  Use style bits to select a particular look or set of properties.
 *
 * @param parent a composite widget; must be an OleFrame
 * @param style the bitwise OR'ing of widget styles
 * @param progId the unique program identifier of an OLE Document application;
 *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
 *               in the registry for the desired OLE Document (for example, the VersionIndependentProgID
 *               for Word is Word.Document)
 *
 * @exception IllegalArgumentException
 *<ul>
 *     <li>ERROR_NULL_ARGUMENT when the parent is null
 *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
 *</ul>
 * @exception SWTException
 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
 *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
 *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
 * </ul>
 */
public OleClientSite(Composite parent, int style, String progId) {
	this(parent, style);
	try {
		appClsid = getClassID(progId);
		if (appClsid == null)
			OLE.error(OLE.ERROR_INVALID_CLASSID);

		// Open a temporary storage object
		tempStorage = createTempStorage();

		// Create ole object with storage object
		long /*int*/[] address = new long /*int*/[1];
		/*
		* Bug in ICA Client 2.7. The creation of the IOleObject fails if the client
		* site is provided to OleCreate().  The fix is to detect that the program
		* id is an ICA Client and do not pass a client site to OleCreate().
		* IOleObject.SetClientSite() is called later on.
		*/
		long /*int*/ clientSite = isICAClient() ? 0 : iOleClientSite.getAddress();
		int result = COM.OleCreate(appClsid, COM.IIDIUnknown, COM.OLERENDER_DRAW, null, clientSite, tempStorage.getAddress(), address);
		if (result != COM.S_OK)
			OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);

		objIUnknown = new IUnknown(address[0]);

		// Init sinks
		addObjectReferences();

		if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state = STATE_RUNNING;

	} catch (SWTException e) {
		dispose();
		disposeCOMInterfaces();
		throw e;
	}
}
/**
 * Create an OleClientSite child widget to edit the specified file using the specified OLE Document
 * application.  Use style bits to select a particular look or set of properties.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>OleClientSite</code>. It is marked public only so that it
 * can be shared within the packages provided by SWT. It is not
 * available on all platforms, and should never be called from
 * application code.
 * </p>
 * @param parent a composite widget; must be an OleFrame
 * @param style the bitwise OR'ing of widget styles
 * @param progId the unique program identifier of am OLE Document application;
 *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
 *               in the registry for the desired OLE Document (for example, the VersionIndependentProgID
 *               for Word is Word.Document)
 * @param file the file that is to be opened in this OLE Document
 *
 * @exception IllegalArgumentException
 * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
 *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
 * @exception SWTException
 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
 *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
 *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
 *     <li>ERROR_CANNOT_OPEN_FILE when failed to open file
 * </ul>
 *
 * @noreference This method is not intended to be referenced by clients.
 */
public OleClientSite(Composite parent, int style, String progId, File file) {
	this(parent, style);
	try {
		if (file == null || file.isDirectory() || !file.exists()) OLE.error(OLE.ERROR_INVALID_ARGUMENT);
		appClsid = getClassID(progId);
		if (appClsid == null) OLE.error(OLE.ERROR_INVALID_CLASSID);

		// Are we opening this file with the preferred OLE object?
		char[] fileName = (file.getAbsolutePath()+"\0").toCharArray();
		GUID fileClsid = new GUID();
		COM.GetClassFile(fileName, fileClsid);

		OleCreate(appClsid, fileClsid, fileName, file);
	} catch (SWTException e) {
		dispose();
		disposeCOMInterfaces();
		throw e;
	}
}

void OleCreate(GUID appClsid, GUID fileClsid, char[] fileName, File file) {

	/* Bug in Windows. In some machines running Windows Vista and
	 * Office 2007, OleCreateFromFile() fails to open files from
	 * Office Word 97 - 2003 and in some other cases it fails to
	 * save files due to a lock. The fix is to detect this case and
	 * create the activeX using CoCreateInstance().
	 */
	boolean isOffice2007 = isOffice2007(true);
	if (!isOffice2007 && COM.IsEqualGUID(appClsid, fileClsid)){
		// Using the same application that created file, therefore, use default mechanism.
		tempStorage = createTempStorage();
		// Create ole object with storage object
		long /*int*/[] address = new long /*int*/[1];
		int result = COM.OleCreateFromFile(appClsid, fileName, COM.IIDIUnknown, COM.OLERENDER_DRAW, null, iOleClientSite.getAddress(), tempStorage.getAddress(), address);
		if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
		objIUnknown = new IUnknown(address[0]);
	} else {
		// Not using the same application that created file, therefore, copy from original file to a new storage file
		IStorage storage = null;
		if (COM.StgIsStorageFile(fileName) == COM.S_OK) {
			long /*int*/[] address = new long /*int*/[1];
			int mode = COM.STGM_READ | COM.STGM_TRANSACTED | COM.STGM_SHARE_EXCLUSIVE;
			int result = COM.StgOpenStorage(fileName, 0, mode, 0, 0, address); //Does an AddRef if successful
			if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
			storage = new IStorage(address[0]);
		} else {
			// Original file is not a Storage file so copy contents to a stream in a new storage file
			long /*int*/[] address = new long /*int*/[1];
			int mode = COM.STGM_READWRITE | COM.STGM_DIRECT | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
			int result = COM.StgCreateDocfile(null, mode | COM.STGM_DELETEONRELEASE, 0, address); // Increments ref count if successful
			if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
			storage = new IStorage(address[0]);
			// Create a stream on the storage object.
			// Word does not follow the standard and does not use "CONTENTS" as the name of
			// its primary stream
			String streamName = "CONTENTS"; //$NON-NLS-1$
			GUID wordGUID = getClassID(WORDPROGID);
			if (wordGUID != null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$
			if (isOffice2007) streamName = "Package"; //$NON-NLS-1$
			address = new long /*int*/[1];
			result = storage.CreateStream(streamName, mode, 0, 0, address); // Increments ref count if successful
			if (result != COM.S_OK) {
				storage.Release();
				OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
			}
			IStream stream = new IStream(address[0]);
			try {
				// Copy over data in file to named stream
				FileInputStream fileInput = new FileInputStream(file);
				int increment = 1024*4;
				byte[] buffer = new byte[increment];
				int count = 0;
				while((count = fileInput.read(buffer)) > 0){
					long /*int*/ pv = COM.CoTaskMemAlloc(count);
					OS.MoveMemory(pv, buffer, count);
					result = stream.Write(pv, count, null) ;
					COM.CoTaskMemFree(pv);
					if (result != COM.S_OK) {
						fileInput.close();
						stream.Release();
						storage.Release();
						OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
					}
				}
				fileInput.close();
				stream.Commit(COM.STGC_DEFAULT);
				stream.Release();
			} catch (IOException err) {
				stream.Release();
				storage.Release();
				OLE.error(OLE.ERROR_CANNOT_OPEN_FILE);
			}
		}

		// Open a temporary storage object
		tempStorage = createTempStorage();
		// Copy over contents of file
		int result = storage.CopyTo(0, null, null, tempStorage.getAddress());
		storage.Release();
		if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);

		// create ole client
		long /*int*/[] ppv = new long /*int*/[1];
		result = COM.CoCreateInstance(appClsid, 0, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, COM.IIDIUnknown, ppv);
		if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
		objIUnknown = new IUnknown(ppv[0]);
		// get the persistent storage of the ole client
		ppv = new long /*int*/[1];
		result = objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv);
		if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
		IPersistStorage iPersistStorage = new IPersistStorage(ppv[0]);
		// load the contents of the file into the ole client site
		result = iPersistStorage.Load(tempStorage.getAddress());
		iPersistStorage.Release();
		if (result != COM.S_OK)OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
	}

	// Init sinks
	addObjectReferences();

	if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state = STATE_RUNNING;
}
protected void addObjectReferences() {
	//
	long /*int*/[] ppvObject = new long /*int*/[1];
	if (objIUnknown.QueryInterface(COM.IIDIPersist, ppvObject) == COM.S_OK) {
		IPersist objIPersist = new IPersist(ppvObject[0]);
		GUID tempid = new GUID();
		if (objIPersist.GetClassID(tempid) == COM.S_OK)
			objClsid = tempid;
		objIPersist.Release();
	}

	//
	ppvObject = new long /*int*/[1];
	int result = objIUnknown.QueryInterface(COM.IIDIViewObject2, ppvObject);
	if (result != COM.S_OK)
		OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
	objIViewObject2 = new IViewObject2(ppvObject[0]);
	objIViewObject2.SetAdvise(aspect, 0, iAdviseSink.getAddress());

	//
	ppvObject = new long /*int*/[1];
	result = objIUnknown.QueryInterface(COM.IIDIOleObject, ppvObject);
	if (result != COM.S_OK)
		OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
	objIOleObject = new IOleObject(ppvObject[0]);
	/*
	 * Feature in Windows. Despite the fact that the clientSite was provided during the
	 * creation of the OleObject (which is required by WMP11 - see bug 173556),
	 * some applications choose to ignore this optional parameter (see bug 211663)
	 * during OleCreate. The fix is to check whether the clientSite has already been set
	 * and set it. Note that setting it twice can result in assert failures.
	 */
	long /*int*/[] ppvClientSite = new long /*int*/[1];
	result = objIOleObject.GetClientSite(ppvClientSite);
	if (ppvClientSite[0] == 0) {
		objIOleObject.SetClientSite(iOleClientSite.getAddress());
	} else {
		Release(); // GetClientSite performs an AddRef so we must release it.
	}
	int[] pdwConnection = new int[1];
	objIOleObject.Advise(iAdviseSink.getAddress(), pdwConnection);
	objIOleObject.SetHostNames("main", "main");  //$NON-NLS-1$ //$NON-NLS-2$

	// Notify the control object that it is embedded in an OLE container
	COM.OleSetContainedObject(objIUnknown.getAddress(), true);

	// Is OLE object linked or embedded?
	ppvObject = new long /*int*/[1];
	if (objIUnknown.QueryInterface(COM.IIDIOleLink, ppvObject) == COM.S_OK) {
		IOleLink objIOleLink = new IOleLink(ppvObject[0]);
		long /*int*/[] ppmk = new long /*int*/[1];
		if (objIOleLink.GetSourceMoniker(ppmk) == COM.S_OK) {
			IMoniker objIMoniker = new IMoniker(ppmk[0]);
			objIMoniker.Release();
			type = COM.OLELINKED;
			objIOleLink.BindIfRunning();
		} else {
			isStatic = true;
		}
		objIOleLink.Release();
	}
}
protected int AddRef() {
	refCount++;
	return refCount;
}
private int CanInPlaceActivate() {
	if (aspect == COM.DVASPECT_CONTENT && type == COM.OLEEMBEDDED)
		return COM.S_OK;

	return COM.S_FALSE;
}
private int ContextSensitiveHelp(int fEnterMode) {
	return COM.S_OK;
}
protected void createCOMInterfaces() {

	iUnknown = new COMObject(new int[]{2, 0, 0}){
		@Override
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		@Override
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		@Override
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
	};

	iOleClientSite = new COMObject(new int[]{2, 0, 0, 0, 3, 1, 0, 1, 0}){
		@Override
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		@Override
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		@Override
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		@Override
		public long /*int*/ method3(long /*int*/[] args) {return SaveObject();}
		// method4 GetMoniker - not implemented
		@Override
		public long /*int*/ method5(long /*int*/[] args) {return GetContainer(args[0]);}
		@Override
		public long /*int*/ method6(long /*int*/[] args) {return ShowObject();}
		@Override
		public long /*int*/ method7(long /*int*/[] args) {return OnShowWindow((int)/*64*/args[0]);}
		// method8 RequestNewObjectLayout - not implemented
	};

	iAdviseSink = new COMObject(new int[]{2, 0, 0, 2, 2, 1, 0, 0}){
		@Override
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		@Override
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		@Override
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		@Override
		public long /*int*/ method3(long /*int*/[] args) {return OnDataChange(args[0], args[1]);}
		@Override
		public long /*int*/ method4(long /*int*/[] args) {return OnViewChange((int)/*64*/args[0], (int)/*64*/args[1]);}
		//method5 OnRename - not implemented
		@Override
		public long /*int*/ method6(long /*int*/[] args) {OnSave();return 0;}
		@Override
		public long /*int*/ method7(long /*int*/[] args) {return OnClose();}
	};

	iOleInPlaceSite = new COMObject(new int[]{2, 0, 0, 1, 1, 0, 0, 0, 5, C.PTR_SIZEOF == 4 ? 2 : 1, 1, 0, 0, 0, 1}){
		@Override
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		@Override
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		@Override
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		@Override
		public long /*int*/ method3(long /*int*/[] args) {return GetWindow(args[0]);}
		@Override
		public long /*int*/ method4(long /*int*/[] args) {return ContextSensitiveHelp((int)/*64*/args[0]);}
		@Override
		public long /*int*/ method5(long /*int*/[] args) {return CanInPlaceActivate();}
		@Override
		public long /*int*/ method6(long /*int*/[] args) {return OnInPlaceActivate();}
		@Override
		public long /*int*/ method7(long /*int*/[] args) {return OnUIActivate();}
		@Override
		public long /*int*/ method8(long /*int*/[] args) {return GetWindowContext(args[0], args[1], args[2], args[3], args[4]);}
		@Override
		public long /*int*/ method9(long /*int*/[] args) {
			if (args.length == 2) {
				return Scroll((int)/*64*/args[0], (int)/*64*/args[1]);
			} else {
				return Scroll_64(args[0]);
			}
		}
		@Override
		public long /*int*/ method10(long /*int*/[] args) {return OnUIDeactivate((int)/*64*/args[0]);}
		@Override
		public long /*int*/ method11(long /*int*/[] args) {return OnInPlaceDeactivate();}
		// method12 DiscardUndoState - not implemented
		// method13 DeactivateAndUndoChange - not implemented
		@Override
		public long /*int*/ method14(long /*int*/[] args) {return OnPosRectChange(args[0]);}
	};

	iOleDocumentSite = new COMObject(new int[]{2, 0, 0, 1}){
		@Override
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		@Override
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		@Override
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		@Override
		public long /*int*/ method3(long /*int*/[] args) {return ActivateMe(args[0]);}
	};
}
protected IStorage createTempStorage() {
	long /*int*/[] tempStorage = new long /*int*/[1];
	int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_DELETEONRELEASE;
	int result = COM.StgCreateDocfile(null, grfMode, 0, tempStorage);
	if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_FILE, result);
	return new IStorage(tempStorage[0]);
}
/**
 * Deactivates an active in-place object and discards the object's undo state.
 */
public void deactivateInPlaceClient() {
	if (objIOleInPlaceObject != null) {
		objIOleInPlaceObject.InPlaceDeactivate();
	}
}
private void deleteTempStorage() {
	//Destroy this item's contents in the temp root IStorage.
	if (tempStorage != null){
		tempStorage.Release();
	}
	tempStorage = null;
}
protected void disposeCOMInterfaces() {
	if (iUnknown != null)
		iUnknown.dispose();
	iUnknown = null;

	if (iOleClientSite != null)
	iOleClientSite.dispose();
	iOleClientSite = null;

	if (iAdviseSink != null)
		iAdviseSink.dispose();
	iAdviseSink = null;

	if (iOleInPlaceSite != null)
		iOleInPlaceSite.dispose();
	iOleInPlaceSite = null;

	if (iOleDocumentSite != null)
		iOleDocumentSite.dispose();
	iOleDocumentSite = null;
}
/**
 * Requests that the OLE Document or ActiveX Control perform an action; actions are almost always
 * changes to the activation state.
 *
 * @param verb the operation that is requested.  This is one of the OLE.OLEIVERB_ values
 *
 * @return an HRESULT value indicating the success of the operation request; OLE.S_OK indicates
 *         success
 */
public int doVerb(int verb) {
	// Not all OLE clients (for example PowerPoint) can be set into the running state in the constructor.
	// The fix is to ensure that the client is in the running state before invoking any verb on it.
	if (state == STATE_NONE) {
		if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state = STATE_RUNNING;
	}
	if (state == STATE_NONE || isStatic)
		return COM.E_FAIL;

	// See PR: 1FV9RZW
	RECT rect = new RECT();
	OS.GetClientRect(handle, rect);
	int result = objIOleObject.DoVerb(verb, null, iOleClientSite.getAddress(), 0, handle, rect);

	if (state != STATE_RUNNING && inInit) {
		updateStorage();
		inInit = false;
	}
	return result;
}
/**
 * Asks the OLE Document or ActiveX Control to execute a command from a standard
 * list of commands. The OLE Document or ActiveX Control must support the IOleCommandTarget
 * interface.  The OLE Document or ActiveX Control does not have to support all the commands
 * in the standard list.  To check if a command is supported, you can call queryStatus with
 * the cmdID.
 *
 * @param cmdID the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
 *              commands
 * @param options the optional flags; these are the OLE.OLECMDEXECOPT_ values
 * @param in the argument for the command
 * @param out the return value of the command
 *
 * @return an HRESULT value; OLE.S_OK is returned if successful
 *
 */
public int exec(int cmdID, int options, Variant in, Variant out) {

	if (objIOleCommandTarget == null) {
		long /*int*/[] address = new long /*int*/[1];
		if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget, address) != COM.S_OK)
			return OLE.ERROR_INTERFACE_NOT_FOUND;
		objIOleCommandTarget = new IOleCommandTarget(address[0]);
	}

	long /*int*/ inAddress = 0;
	if (in != null){
		inAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
		in.getData(inAddress);
	}
	long /*int*/ outAddress = 0;
	if (out != null){
		outAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
		out.getData(outAddress);
	}

	int result = objIOleCommandTarget.Exec(null, cmdID, options, inAddress, outAddress);

	if (inAddress != 0){
		COM.VariantClear(inAddress);
		OS.GlobalFree(inAddress);
	}
	if (outAddress != 0) {
		out.setData(outAddress);
		COM.VariantClear(outAddress);
		OS.GlobalFree(outAddress);
	}

	return result;
}
IDispatch getAutomationObject() {
	long /*int*/[] ppvObject = new long /*int*/[1];
	if (objIUnknown.QueryInterface(COM.IIDIDispatch, ppvObject) != COM.S_OK)
		return null;
	return new IDispatch(ppvObject[0]);
}
protected GUID getClassID(String clientName) {
	// create a GUID struct to hold the result
	GUID guid = new GUID();

	// create a null terminated array of char
	char[] buffer = null;
	if (clientName != null) {
		int count = clientName.length();
		buffer = new char[count + 1];
		clientName.getChars(0, count, buffer, 0);
	}
	if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK){
		int result = COM.CLSIDFromString(buffer, guid);
		if (result != COM.S_OK) return null;
	}
	return guid;
}
private int GetContainer(long /*int*/ ppContainer) {
	/* Simple containers that do not support links to their embedded
	 * objects probably do not need to implement this method. Instead,
	 * they can return E_NOINTERFACE and set ppContainer to NULL.
	 */
	if (ppContainer != 0)
		COM.MoveMemory(ppContainer, new long /*int*/[]{0}, OS.PTR_SIZEOF);
	return COM.E_NOINTERFACE;
}
private SIZE getExtent() {
	SIZE sizel = new SIZE();
	// get the current size of the embedded OLENatives object
	if (objIOleObject != null) {
		if ( objIViewObject2 != null && !COM.OleIsRunning(objIOleObject.getAddress())) {
			objIViewObject2.GetExtent(aspect, -1, null, sizel);
		} else {
			objIOleObject.GetExtent(aspect, sizel);
		}
	}
	return xFormHimetricToPixels(sizel);
}
/**
 * Returns the indent value that would be used to compute the clipping area
 * of the active X object.
 *
 * NOTE: The indent value is no longer being used by the client site.
 *
 * @return the rectangle representing the indent
 */
public Rectangle getIndent() {
	return new Rectangle(indent.left, indent.right, indent.top, indent.bottom);
}
/**
 * Returns the program ID of the OLE Document or ActiveX Control.
 *
 * @return the program ID of the OLE Document or ActiveX Control
 */
public String getProgramID(){
	return getProgID(appClsid);
}
String getProgID(GUID clsid) {
	if (clsid != null){
		long /*int*/[] lplpszProgID = new long /*int*/[1];
		if (COM.ProgIDFromCLSID(clsid, lplpszProgID) == COM.S_OK) {
			long /*int*/ hMem = lplpszProgID[0];
			int length = OS.GlobalSize(hMem);
			long /*int*/ ptr = OS.GlobalLock(hMem);
			char[] buffer = new char[length];
			COM.MoveMemory(buffer, ptr, length);
			OS.GlobalUnlock(hMem);
			OS.GlobalFree(hMem);

			String result = new String(buffer);
			// remove null terminator
			int index = result.indexOf("\0");
			return result.substring(0, index);
		}
	}
	return null;
}
int ActivateMe(long /*int*/ pViewToActivate) {
	if (pViewToActivate == 0) {
		long /*int*/[] ppvObject = new long /*int*/[1];
		if (objIUnknown.QueryInterface(COM.IIDIOleDocument, ppvObject) != COM.S_OK) return COM.E_FAIL;
		IOleDocument objOleDocument = new IOleDocument(ppvObject[0]);
		if (objOleDocument.CreateView(iOleInPlaceSite.getAddress(), 0, 0, ppvObject) != COM.S_OK) return COM.E_FAIL;
		objOleDocument.Release();
		objDocumentView = new IOleDocumentView(ppvObject[0]);
	} else {
		objDocumentView = new IOleDocumentView(pViewToActivate);
		objDocumentView.AddRef();
		objDocumentView.SetInPlaceSite(iOleInPlaceSite.getAddress());
	}
	objDocumentView.UIActivate(1);//TRUE
	RECT rect = getRect();
	objDocumentView.SetRect(rect);
	objDocumentView.Show(1);//TRUE
	return COM.S_OK;
}
protected int GetWindow(long /*int*/ phwnd) {
	if (phwnd == 0)
		return COM.E_INVALIDARG;
	if (frame == null) {
		COM.MoveMemory(phwnd, new long /*int*/[] {0}, OS.PTR_SIZEOF);
		return COM.E_NOTIMPL;
	}

	// Copy the Window's handle into the memory passed in
	COM.MoveMemory(phwnd, new long /*int*/[] {handle}, OS.PTR_SIZEOF);
	return COM.S_OK;
}
RECT getRect() {
	Rectangle area = DPIUtil.autoScaleUp(getClientArea()); // To Pixels
	RECT rect = new RECT();
	rect.left   = area.x;
	rect.top    = area.y;
	rect.right  = area.x + area.width;
	rect.bottom = area.y + area.height;
	return rect;
}
private int GetWindowContext(long /*int*/ ppFrame, long /*int*/ ppDoc, long /*int*/ lprcPosRect, long /*int*/ lprcClipRect, long /*int*/ lpFrameInfo) {
	if (frame == null || ppFrame == 0)
		return COM.E_NOTIMPL;

	// fill in frame handle
	long /*int*/ iOleInPlaceFrame = frame.getIOleInPlaceFrame();
	COM.MoveMemory(ppFrame, new long /*int*/[] {iOleInPlaceFrame}, OS.PTR_SIZEOF);
	frame.AddRef();

	// null out document handle
	if (ppDoc != 0) COM.MoveMemory(ppDoc, new long /*int*/[] {0}, OS.PTR_SIZEOF);

	// fill in position and clipping info
	RECT rect = getRect();
	if (lprcPosRect != 0) OS.MoveMemory(lprcPosRect, rect, RECT.sizeof);
	if (lprcClipRect != 0) OS.MoveMemory(lprcClipRect, rect, RECT.sizeof);

	// get frame info
	OLEINPLACEFRAMEINFO frameInfo = new OLEINPLACEFRAMEINFO();
	frameInfo.cb = OLEINPLACEFRAMEINFO.sizeof;
	frameInfo.fMDIApp = 0;
	frameInfo.hwndFrame = frame.handle;
	Shell shell = getShell();
	Menu menubar = shell.getMenuBar();
	if (menubar != null && !menubar.isDisposed()) {
		long /*int*/ hwnd = shell.handle;
		int cAccel = (int)/*64*/OS.SendMessage(hwnd, OS.WM_APP, 0, 0);
		if (cAccel != 0) {
			long /*int*/ hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
			if (hAccel != 0) {
				frameInfo.cAccelEntries = cAccel;
				frameInfo.haccel = hAccel;
			}
		}
	}
	COM.MoveMemory(lpFrameInfo, frameInfo, OLEINPLACEFRAMEINFO.sizeof);

	return COM.S_OK;
}
boolean isICAClient() {
	return getProgramID().startsWith("Citrix.ICAClient"); //$NON-NLS-1$
}
/**
 * Returns whether ole document is dirty by checking whether the content
 * of the file representing the document is dirty.
 *
 * @return <code>true</code> if the document has been modified,
 *         <code>false</code> otherwise.
 * @since 3.1
 */
public boolean isDirty() {
	/*
	 *  Note: this method must return true unless it is absolutely clear that the
	 * contents of the Ole Document do not differ from the contents in the file
	 * on the file system.
	 */

	// Get access to the persistent storage mechanism
	long /*int*/[] address = new long /*int*/[1];
	if (objIOleObject.QueryInterface(COM.IIDIPersistFile, address) != COM.S_OK)
		return true;
	IPersistFile permStorage = new IPersistFile(address[0]);
	// Are the contents of the permanent storage different from the file?
	int result = permStorage.IsDirty();
	permStorage.Release();
	if (result == COM.S_FALSE) return false;
	return true;
}
@Override
public boolean isFocusControl () {
	checkWidget ();
	long /*int*/ focusHwnd = OS.GetFocus();
	if (objIOleInPlaceObject == null) return (handle == focusHwnd);
	long /*int*/[] phwnd = new long /*int*/[1];
	objIOleInPlaceObject.GetWindow(phwnd);
	while (focusHwnd != 0) {
		if (phwnd[0] == focusHwnd) return true;
		focusHwnd = OS.GetParent(focusHwnd);
	}
	return false;
}
private boolean isOffice2007(boolean program) {
	String programID = getProgramID();
	if (programID == null) return false;
	if (program) {
		int lastDot = programID.lastIndexOf('.');
		if (lastDot != -1) {
			programID = programID.substring(0, lastDot);
			GUID guid = getClassID(programID);
			programID = getProgID(guid);
			if (programID == null) return false;
		}
	}
	if (programID.equals("Word.Document.12")) return true; //$NON-NLS-1$
	if (programID.equals("Excel.Sheet.12")) return true; //$NON-NLS-1$
	if (programID.equals("PowerPoint.Show.12")) return true; //$NON-NLS-1$
	return false;
}
private int OnClose() {
	return COM.S_OK;
}
private int OnDataChange(long /*int*/ pFormatetc, long /*int*/ pStgmed) {
	return COM.S_OK;
}
private void onDispose(Event e) {
	inDispose = true;

	// remove listeners
	removeListener(SWT.Dispose, listener);
	removeListener(SWT.FocusIn, listener);
	removeListener(SWT.FocusOut, listener);
	removeListener(SWT.Paint, listener);
	removeListener(SWT.Traverse, listener);
	removeListener(SWT.KeyDown, listener);

	if (state != STATE_NONE)
		doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE);
	deactivateInPlaceClient();
	releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame
	deleteTempStorage();

	frame.removeListener(SWT.Resize, listener);
	frame.removeListener(SWT.Move, listener);

	frame.Release();
	frame = null;
}
void onFocusIn(Event e) {
	if (inDispose) return;
	if (state != STATE_UIACTIVE) {
		long /*int*/[] ppvObject = new long /*int*/[1];
		if (objIUnknown.QueryInterface(COM.IIDIOleInPlaceObject, ppvObject) == COM.S_OK) {
			IOleInPlaceObject objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
			objIOleInPlaceObject.Release();
			doVerb(OLE.OLEIVERB_SHOW);
		}
	}
	if (objIOleInPlaceObject == null) return;
	if (isFocusControl()) return;
	long /*int*/[] phwnd = new long /*int*/[1];
	objIOleInPlaceObject.GetWindow(phwnd);
	if (phwnd[0] == 0) return;
	OS.SetFocus(phwnd[0]);
}
void onFocusOut(Event e) {
}
private int OnInPlaceActivate() {
	state = STATE_INPLACEACTIVE;
	frame.setCurrentDocument(this);
	if (objIOleObject == null)
		return COM.S_OK;
	long /*int*/[] ppvObject = new long /*int*/[1];
	if (objIOleObject.QueryInterface(COM.IIDIOleInPlaceObject, ppvObject) == COM.S_OK) {
		objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
	}
	return COM.S_OK;
}
private int OnInPlaceDeactivate() {
	if (objIOleInPlaceObject != null) objIOleInPlaceObject.Release();
	objIOleInPlaceObject = null;
	state = STATE_RUNNING;
	redraw();
	Shell shell = getShell();
	if (isFocusControl() || frame.isFocusControl()) {
		shell.traverse(SWT.TRAVERSE_TAB_NEXT);
	}
	return COM.S_OK;
}
private int OnPosRectChange(long /*int*/ lprcPosRect) {
	Point size = DPIUtil.autoScaleUp(getSize()); // To Pixels
	setExtent(size.x, size.y);
	return COM.S_OK;
}
private void onPaint(Event e) {
	if (state == STATE_RUNNING || state == STATE_INPLACEACTIVE) {
		SIZE size = getExtent();
		Rectangle area = DPIUtil.autoScaleUp(getClientArea()); // To Pixels
		RECT rect = new RECT();
		if (getProgramID().startsWith("Excel.Sheet")) { //$NON-NLS-1$
			rect.left = area.x; rect.right = area.x + (area.height * size.cx / size.cy);
			rect.top = area.y; rect.bottom = area.y + area.height;
		} else {
			rect.left = area.x; rect.right = area.x + size.cx;
			rect.top = area.y; rect.bottom = area.y + size.cy;
		}

		long /*int*/ pArea = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, RECT.sizeof);
		OS.MoveMemory(pArea, rect, RECT.sizeof);
		COM.OleDraw(objIUnknown.getAddress(), aspect, e.gc.handle, pArea);
		OS.GlobalFree(pArea);
	}
}
private void onResize(Event e) {
	setBounds();
}
private void OnSave() {
}
private int OnShowWindow(int fShow) {
	return COM.S_OK;
}
private int OnUIActivate() {
	if (objIOleInPlaceObject == null) return COM.E_FAIL;
	state = STATE_UIACTIVE;
	long /*int*/[] phwnd = new long /*int*/[1];
	if (objIOleInPlaceObject.GetWindow(phwnd) == COM.S_OK) {
		OS.SetWindowPos(phwnd[0], OS.HWND_TOP, 0, 0, 0, 0, OS.SWP_NOSIZE | OS.SWP_NOMOVE);
	}
	return COM.S_OK;
}
int OnUIDeactivate(int fUndoable) {
	// currently, we are ignoring the fUndoable flag
	if (frame == null || frame.isDisposed()) return COM.S_OK;
	state = STATE_INPLACEACTIVE;
	frame.SetActiveObject(0,0);
	redraw();
	Shell shell = getShell();
	if (isFocusControl() || frame.isFocusControl()) {
		shell.traverse(SWT.TRAVERSE_TAB_NEXT);
	}
	Menu menubar = shell.getMenuBar();
	if (menubar == null || menubar.isDisposed())
		return COM.S_OK;

	long /*int*/ shellHandle = shell.handle;
	OS.SetMenu(shellHandle, menubar.handle);
	return COM.OleSetMenuDescriptor(0, shellHandle, 0, 0, 0);
}
private void onTraverse(Event event) {
	switch (event.detail) {
		case SWT.TRAVERSE_ESCAPE:
		case SWT.TRAVERSE_RETURN:
		case SWT.TRAVERSE_TAB_NEXT:
		case SWT.TRAVERSE_TAB_PREVIOUS:
		case SWT.TRAVERSE_PAGE_NEXT:
		case SWT.TRAVERSE_PAGE_PREVIOUS:
		case SWT.TRAVERSE_MNEMONIC:
			event.doit = true;
			break;
	}
}
private int OnViewChange(int dwAspect, int lindex) {
	return COM.S_OK;
}
protected int QueryInterface(long /*int*/ riid, long /*int*/ ppvObject) {

	if (riid == 0 || ppvObject == 0)
		return COM.E_NOINTERFACE;
	GUID guid = new GUID();
	COM.MoveMemory(guid, riid, GUID.sizeof);

	if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iUnknown.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iAdviseSink.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iOleClientSite.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iOleInPlaceSite.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite )) {
		String progID = getProgramID();
		if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
			COM.MoveMemory(ppvObject, new long /*int*/[] {iOleDocumentSite.getAddress()}, OS.PTR_SIZEOF);
			AddRef();
			return COM.S_OK;
		}
	}
	COM.MoveMemory(ppvObject, new long /*int*/[] {0}, OS.PTR_SIZEOF);
	return COM.E_NOINTERFACE;
}
/**
 * Returns the status of the specified command.  The status is any bitwise OR'd combination of
 * SWTOLE.OLECMDF_SUPPORTED, SWTOLE.OLECMDF_ENABLED, SWTOLE.OLECMDF_LATCHED, SWTOLE.OLECMDF_NINCHED.
 * You can query the status of a command before invoking it with OleClientSite.exec.  The
 * OLE Document or ActiveX Control must support the IOleCommandTarget to make use of this method.
 *
 * @param cmd the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
 *            commands
 *
 * @return the status of the specified command or 0 if unable to query the OLE Object; these are the
 *			  OLE.OLECMDF_ values
 */
public int queryStatus(int cmd) {

	if (objIOleCommandTarget == null) {
		long /*int*/[] address = new long /*int*/[1];
		if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget, address) != COM.S_OK)
			return 0;
		objIOleCommandTarget = new IOleCommandTarget(address[0]);
	}

	OLECMD olecmd = new OLECMD();
	olecmd.cmdID = cmd;

	int result = objIOleCommandTarget.QueryStatus(null, 1, olecmd, null);

	if (result != COM.S_OK) return 0;

	return olecmd.cmdf;
}
protected int Release() {
	refCount--;

	if (refCount == 0) {
		disposeCOMInterfaces();
	}
	return refCount;
}
protected void releaseObjectInterfaces() {

	if (objIOleInPlaceObject!= null)
		objIOleInPlaceObject.Release();
	objIOleInPlaceObject = null;

	if (objIOleObject != null) {
		objIOleObject.Close(COM.OLECLOSE_NOSAVE);
		objIOleObject.Release();
	}
	objIOleObject = null;

	if (objDocumentView != null){
		objDocumentView.Release();
	}
	objDocumentView = null;

	if (objIViewObject2 != null) {
		objIViewObject2.SetAdvise(aspect, 0, 0);
		objIViewObject2.Release();
	}
	objIViewObject2 = null;

	if (objIOleCommandTarget != null)
		objIOleCommandTarget.Release();
	objIOleCommandTarget = null;

	if (objIUnknown != null){
		objIUnknown.Release();
	}
	objIUnknown = null;

	if (COM.FreeUnusedLibraries) {
		COM.CoFreeUnusedLibraries();
	}
}
/**
 * Saves the document to the specified file and includes OLE specific information if specified.
 * This method must <b>only</b> be used for files that have an OLE Storage format.  For example,
 * a word file edited with Word.Document should be saved using this method because there is
 * formating information that should be stored in the OLE specific Storage format.
 *
 * @param file the file to which the changes are to be saved
 * @param includeOleInfo the flag to indicate whether OLE specific information should be saved.
 *
 * @return true if the save was successful
 */
public boolean save(File file, boolean includeOleInfo) {
	/*
	* Bug in Office 2007. Saving Office 2007 documents to compound file storage object
	* causes the output file to be corrupted. The fix is to detect Office 2007 documents
	* using the program ID and save only the content of the 'Package' stream.
	*/
	if (isOffice2007(false)) {
		return saveOffice2007(file);
	}
	if (includeOleInfo)
		return saveToStorageFile(file);
	return saveToTraditionalFile(file);
}
private boolean saveFromContents(long /*int*/ address, File file) {

	boolean success = false;

	IStream tempContents = new IStream(address);
	tempContents.AddRef();

	try {
		FileOutputStream writer = new FileOutputStream(file);

		int increment = 1024 * 4;
		long /*int*/ pv = COM.CoTaskMemAlloc(increment);
		int[] pcbWritten = new int[1];
		while (tempContents.Read(pv, increment, pcbWritten) == COM.S_OK && pcbWritten[0] > 0) {
			byte[] buffer = new byte[ pcbWritten[0]];
			OS.MoveMemory(buffer, pv, pcbWritten[0]);
			writer.write(buffer); // Note: if file does not exist, this will create the file the
			                      // first time it is called
			success = true;
		}
		COM.CoTaskMemFree(pv);

		writer.close();

	} catch (IOException err) {
	}

	tempContents.Release();

	return success;
}
private boolean saveFromOle10Native(long /*int*/ address, File file) {

	boolean success = false;

	IStream tempContents = new IStream(address);
	tempContents.AddRef();

	// The "\1Ole10Native" stream contains a DWORD header whose value is the length
	// of the native data that follows.
	long /*int*/ pv = COM.CoTaskMemAlloc(4);
	int[] size = new int[1];
	int rc = tempContents.Read(pv, 4, null);
	OS.MoveMemory(size, pv, 4);
	COM.CoTaskMemFree(pv);
	if (rc == COM.S_OK && size[0] > 0) {

		// Read the data
		byte[] buffer = new byte[size[0]];
		pv = COM.CoTaskMemAlloc(size[0]);
		rc = tempContents.Read(pv, size[0], null);
		OS.MoveMemory(buffer, pv, size[0]);
		COM.CoTaskMemFree(pv);

		// open the file and write data into it
		try {
			FileOutputStream writer = new FileOutputStream(file);
			writer.write(buffer); // Note: if file does not exist, this will create the file
			writer.close();

			success = true;
		} catch (IOException err) {
		}
	}
	tempContents.Release();

	return success;
}
private int SaveObject() {

	updateStorage();

	return COM.S_OK;
}
private boolean saveOffice2007(File file) {
	if (file == null || file.isDirectory()) return false;
	if (!updateStorage()) return false;
	boolean result = false;

	/* Excel fails to open the package stream when the PersistStorage is not in hands off mode */
	long /*int*/[] ppv = new long /*int*/[1];
	IPersistStorage iPersistStorage = null;
	if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) == COM.S_OK) {
		iPersistStorage = new IPersistStorage(ppv[0]);
		tempStorage.AddRef();
		iPersistStorage.HandsOffStorage();
	}
	long /*int*/[] address = new long /*int*/[1];
	int grfMode = COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE;
	if (tempStorage.OpenStream("Package", 0, grfMode, 0, address) == COM.S_OK) { //$NON-NLS-1$
		result = saveFromContents(address[0], file);
	}
	if (iPersistStorage != null) {
		iPersistStorage.SaveCompleted(tempStorage.getAddress());
		tempStorage.Release();
		iPersistStorage.Release();
	}
	return result;
}
/**
 * Saves the document to the specified file and includes OLE specific information.  This method
 * must <b>only</b> be used for files that have an OLE Storage format.  For example, a word file
 * edited with Word.Document should be saved using this method because there is formating information
 * that should be stored in the OLE specific Storage format.
 *
 * @param file the file to which the changes are to be saved
 *
 * @return true if the save was successful
 */
private boolean saveToStorageFile(File file) {
	// The file will be saved using the formating of the current application - this
	// may not be the format of the application that was originally used to create the file
	// e.g. if an Excel file is opened in Word, the Word application will save the file in the
	// Word format
	// Note: if the file already exists, some applications will not overwrite the file
	// In these cases, you should delete the file first (probably save the contents of the file in case the
	// save fails)
	if (file == null || file.isDirectory()) return false;
	if (!updateStorage()) return false;

	// get access to the persistent storage mechanism
	long /*int*/[] address = new long /*int*/[1];
	if (objIOleObject.QueryInterface(COM.IIDIPersistStorage, address) != COM.S_OK) return false;
	IPersistStorage permStorage = new IPersistStorage(address[0]);
	try {
		address = new long /*int*/[1];
		char[] path = (file.getAbsolutePath()+"\0").toCharArray();
		int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
		int result = COM.StgCreateDocfile(path, mode, 0, address); //Does an AddRef if successful
		if (result != COM.S_OK) return false;
		IStorage storage =  new IStorage(address[0]);
		try {
			if (COM.OleSave(permStorage.getAddress(), storage.getAddress(), false) == COM.S_OK) {
				if (storage.Commit(COM.STGC_DEFAULT) == COM.S_OK) {
					return true;
				}
			}
		} finally {
			storage.Release();
		}
	} finally {
		permStorage.Release();
	}
	return false;
}
/**
 * Saves the document to the specified file.  This method must be used for
 * files that do not have an OLE Storage format.  For example, a bitmap file edited with MSPaint
 * should be saved using this method because bitmap is a standard format that does not include any
 * OLE specific data.
 *
 * @param file the file to which the changes are to be saved
 *
 * @return true if the save was successful
 */
private boolean saveToTraditionalFile(File file) {
	// Note: if the file already exists, some applications will not overwrite the file
	// In these cases, you should delete the file first (probably save the contents of the file in case the
	// save fails)
	if (file == null || file.isDirectory())
		return false;
	if (!updateStorage())
		return false;

	long /*int*/[] address = new long /*int*/[1];
	// Look for a CONTENTS stream
	if (tempStorage.OpenStream("CONTENTS", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
		return saveFromContents(address[0], file);

	// Look for Ole 1.0 object stream
	if (tempStorage.OpenStream("\1Ole10Native", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
		return saveFromOle10Native(address[0], file);

	return false;
}
private int Scroll_64(long /*int*/ scrollExtent) {
	return COM.S_OK;
}
private int Scroll(int scrollExtent_cx, int scrollExtent_cy) {
	return COM.S_OK;
}
void setBorderSpace(RECT newBorderwidth) {
	borderWidths = newBorderwidth;
	// readjust size and location of client site
	setBounds();
}
void setBounds() {
	Rectangle area = DPIUtil.autoScaleUp(frame.getClientArea()); // To Pixels
	setBounds(DPIUtil.autoScaleDown(borderWidths.left),
		      DPIUtil.autoScaleDown(borderWidths.top),
			  DPIUtil.autoScaleDown(area.width - borderWidths.left - borderWidths.right),
			  DPIUtil.autoScaleDown(area.height - borderWidths.top - borderWidths.bottom));
	setObjectRects();
}
private void setExtent(int width, int height){
	// Resize the width and height of the embedded/linked OLENatives object
	// to the specified values.

	if (objIOleObject == null || isStatic || inUpdate) return;
	SIZE currentExtent = getExtent();
	if (width == currentExtent.cx && height == currentExtent.cy) return;

	SIZE newExtent = new SIZE();
	newExtent.cx = width; newExtent.cy = height;
	newExtent = xFormPixelsToHimetric(newExtent);

   // Get the server running first, then do a SetExtent, then show it
	boolean alreadyRunning = COM.OleIsRunning(objIOleObject.getAddress());
	if (!alreadyRunning)
		COM.OleRun(objIOleObject.getAddress());

	if (objIOleObject.SetExtent(aspect, newExtent) == COM.S_OK){
		inUpdate = true;
		objIOleObject.Update();
		inUpdate = false;
		if (!alreadyRunning)
			// Close server if it wasn't already running upon entering this method.
			objIOleObject.Close(COM.OLECLOSE_SAVEIFDIRTY);
	}
}
/**
 * The indent value is no longer being used by the client site.
 *
 * @param newIndent the rectangle representing the indent amount
 */
public void setIndent(Rectangle newIndent) {
	indent = new RECT();
	indent.left = newIndent.x;
	indent.right = newIndent.width;
	indent.top = newIndent.y;
	indent.bottom = newIndent.height;
}
private void setObjectRects() {
	if (objIOleInPlaceObject == null) return;
	// size the object to fill the available space
	// leave a border
	RECT rect = getRect();
	objIOleInPlaceObject.SetObjectRects(rect, rect);
}

private int ShowObject() {
	/* Tells the container to position the object so it is visible to
	 * the user. This method ensures that the container itself is
	 * visible and not minimized.
	 */
	setBounds();
	return COM.S_OK;
}
/**
 * Displays a dialog with the property information for this OLE Object.  The OLE Document or
 * ActiveX Control must support the ISpecifyPropertyPages interface.
 *
 * @param title the name that will appear in the titlebar of the dialog
 */
public void showProperties(String title) {

	// Get the Property Page information from the OLE Object
	long /*int*/[] ppvObject = new long /*int*/[1];
	if (objIUnknown.QueryInterface(COM.IIDISpecifyPropertyPages, ppvObject) != COM.S_OK) return;
	ISpecifyPropertyPages objISPP = new ISpecifyPropertyPages(ppvObject[0]);
	CAUUID caGUID = new CAUUID();
	int result = objISPP.GetPages(caGUID);
	objISPP.Release();
	if (result != COM.S_OK) return;

	// create a frame in which to display the pages
	char[] chTitle = null;
	if (title != null) {
		chTitle = new char[title.length()];
		title.getChars(0, title.length(), chTitle, 0);
	}
	result = COM.OleCreatePropertyFrame(frame.handle, 10, 10, chTitle, 1, new long /*int*/[] {objIUnknown.getAddress()}, caGUID.cElems, caGUID.pElems, COM.LOCALE_USER_DEFAULT, 0, 0);

	// free the property page information
	COM.CoTaskMemFree(caGUID.pElems);
}
private boolean updateStorage() {

	if (tempStorage == null) return false;

	long /*int*/[] ppv = new long /*int*/[1];
	if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) != COM.S_OK) return false;
	IPersistStorage iPersistStorage = new IPersistStorage(ppv[0]);

	int result = COM.OleSave(iPersistStorage.getAddress(), tempStorage.getAddress(), true);

	if (result != COM.S_OK){
		// OleSave will fail for static objects, so do what OleSave does.
		COM.WriteClassStg(tempStorage.getAddress(), objClsid);
		result = iPersistStorage.Save(tempStorage.getAddress(), true);
	}

	tempStorage.Commit(COM.STGC_DEFAULT);
	result = iPersistStorage.SaveCompleted(0);
	iPersistStorage.Release();

	return true;
}
private SIZE xFormHimetricToPixels(SIZE aSize) {
	// Return a new Size which is the pixel transformation of a
	// size in HIMETRIC units.

	long /*int*/ hDC = OS.GetDC(0);
	int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
	int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
	OS.ReleaseDC(0, hDC);
	int cx = Compatibility.round(aSize.cx * xppi, 2540); // 2540 HIMETRIC units per inch
	int cy = Compatibility.round(aSize.cy * yppi, 2540);
	SIZE size = new SIZE();
	size.cx = cx;
	size.cy = cy;
	return size;
}
private SIZE xFormPixelsToHimetric(SIZE aSize) {
	// Return a new size which is the HIMETRIC transformation of a
	// size in pixel units.

	long /*int*/ hDC = OS.GetDC(0);
	int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
	int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
	OS.ReleaseDC(0, hDC);
	int cx = Compatibility.round(aSize.cx * 2540, xppi); // 2540 HIMETRIC units per inch
	int cy = Compatibility.round(aSize.cy * 2540, yppi);
	SIZE size = new SIZE();
	size.cx = cx;
	size.cy = cy;
	return size;
}
}
