0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.ole.win32;
0011:
0012: import java.io.File;
0013: import java.io.FileOutputStream;
0014: import java.io.FileInputStream;
0015: import java.io.IOException;
0016: import org.eclipse.swt.*;
0017: import org.eclipse.swt.internal.C;
0018: import org.eclipse.swt.internal.Compatibility;
0019: import org.eclipse.swt.internal.ole.win32.*;
0020: import org.eclipse.swt.graphics.*;
0021: import org.eclipse.swt.widgets.*;
0022: import org.eclipse.swt.internal.win32.*;
0023:
0024: /**
0025: * OleClientSite provides a site to manage an embedded OLE Document within a container.
0026: *
0027: * <p>The OleClientSite provides the following capabilities:
0028: * <ul>
0029: * <li>creates the in-place editor for a blank document or opening an existing OLE Document
0030: * <li>lays the editor out
0031: * <li>provides a mechanism for activating and deactivating the Document
0032: * <li>provides a mechanism for saving changes made to the document
0033: * </ul>
0034: *
0035: * <p>This object implements the OLE Interfaces IUnknown, IOleClientSite, IAdviseSink,
0036: * IOleInPlaceSite
0037: *
0038: * <p>Note that although this class is a subclass of <code>Composite</code>,
0039: * it does not make sense to add <code>Control</code> children to it,
0040: * or set a layout on it.
0041: * </p><p>
0042: * <dl>
0043: * <dt><b>Styles</b> <dd>BORDER
0044: * <dt><b>Events</b> <dd>Dispose, Move, Resize
0045: * </dl>
0046: *
0047: */
0048: public class OleClientSite extends Composite {
0049:
0050: // Interfaces for this Ole Client Container
0051: private COMObject iUnknown;
0052: private COMObject iOleClientSite;
0053: private COMObject iAdviseSink;
0054: private COMObject iOleInPlaceSite;
0055: private COMObject iOleDocumentSite;
0056:
0057: protected GUID appClsid;
0058: private GUID objClsid;
0059: private int refCount;
0060:
0061: // References to the associated Frame.
0062: protected OleFrame frame;
0063:
0064: // Access to the embedded/linked Ole Object
0065: protected IUnknown objIUnknown;
0066: protected IOleObject objIOleObject;
0067: protected IViewObject2 objIViewObject2;
0068: protected IOleInPlaceObject objIOleInPlaceObject;
0069: protected IOleCommandTarget objIOleCommandTarget;
0070: protected IOleDocumentView objDocumentView;
0071:
0072: // Related storage information
0073: protected IStorage tempStorage; // IStorage interface of the receiver
0074:
0075: // Internal state and style information
0076: private int aspect; // the display aspect of the embedded object, e.g., DvaspectContent or DvaspectIcon
0077: private int type; // Indicates the type of client that can be supported inside this container
0078: private boolean isStatic; // Indicates item's display is static, i.e., a bitmap, metafile, etc.
0079:
0080: private RECT borderWidths = new RECT();
0081: private RECT indent = new RECT();
0082: private boolean inUpdate = false;
0083: private boolean inInit = true;
0084: private boolean inDispose = false;
0085:
0086: private static final String WORDPROGID = "Word.Document"; //$NON-NLS-1$
0087:
0088: private Listener listener;
0089:
0090: static final int STATE_NONE = 0;
0091: static final int STATE_RUNNING = 1;
0092: static final int STATE_INPLACEACTIVE = 2;
0093: static final int STATE_UIACTIVE = 3;
0094: static final int STATE_ACTIVE = 4;
0095: int state = STATE_NONE;
0096:
0097: protected OleClientSite(Composite parent, int style) {
0098: /*
0099: * NOTE: this constructor should never be used by itself because it does
0100: * not create an Ole Object
0101: */
0102: super (parent, style);
0103:
0104: createCOMInterfaces();
0105:
0106: // install the Ole Frame for this Client Site
0107: while (parent != null) {
0108: if (parent instanceof OleFrame) {
0109: frame = (OleFrame) parent;
0110: break;
0111: }
0112: parent = parent.getParent();
0113: }
0114: if (frame == null)
0115: OLE.error(SWT.ERROR_INVALID_ARGUMENT);
0116: frame.AddRef();
0117:
0118: aspect = COM.DVASPECT_CONTENT;
0119: type = COM.OLEEMBEDDED;
0120: isStatic = false;
0121:
0122: listener = new Listener() {
0123: public void handleEvent(Event e) {
0124: switch (e.type) {
0125: case SWT.Resize:
0126: case SWT.Move:
0127: onResize(e);
0128: break;
0129: case SWT.Dispose:
0130: onDispose(e);
0131: break;
0132: case SWT.FocusIn:
0133: onFocusIn(e);
0134: break;
0135: case SWT.FocusOut:
0136: onFocusOut(e);
0137: break;
0138: case SWT.Paint:
0139: onPaint(e);
0140: break;
0141: case SWT.Traverse:
0142: onTraverse(e);
0143: break;
0144: case SWT.KeyDown: /* required for traversal */
0145: break;
0146: default:
0147: OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
0148: }
0149: }
0150: };
0151:
0152: frame.addListener(SWT.Resize, listener);
0153: frame.addListener(SWT.Move, listener);
0154: addListener(SWT.Dispose, listener);
0155: addListener(SWT.FocusIn, listener);
0156: addListener(SWT.FocusOut, listener);
0157: addListener(SWT.Paint, listener);
0158: addListener(SWT.Traverse, listener);
0159: addListener(SWT.KeyDown, listener);
0160: }
0161:
0162: /**
0163: * Create an OleClientSite child widget using the OLE Document type associated with the
0164: * specified file. The OLE Document type is determined either through header information in the file
0165: * or through a Registry entry for the file extension. Use style bits to select a particular look
0166: * or set of properties.
0167: *
0168: * @param parent a composite widget; must be an OleFrame
0169: * @param style the bitwise OR'ing of widget styles
0170: * @param file the file that is to be opened in this OLE Document
0171: *
0172: * @exception IllegalArgumentException
0173: * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
0174: * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
0175: * @exception SWTException
0176: * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
0177: * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
0178: * <li>ERROR_CANNOT_OPEN_FILE when failed to open file
0179: * <li>ERROR_INTERFACE_NOT_FOUND when unable to create callbacks for OLE Interfaces
0180: * <li>ERROR_INVALID_CLASSID
0181: * </ul>
0182: */
0183: public OleClientSite(Composite parent, int style, File file) {
0184: this (parent, style);
0185: try {
0186:
0187: if (file == null || file.isDirectory() || !file.exists())
0188: OLE.error(OLE.ERROR_INVALID_ARGUMENT);
0189:
0190: // Is there an associated CLSID?
0191: appClsid = new GUID();
0192: char[] fileName = (file.getAbsolutePath() + "\0")
0193: .toCharArray();
0194: int result = COM.GetClassFile(fileName, appClsid);
0195: if (result != COM.S_OK)
0196: OLE.error(OLE.ERROR_INVALID_CLASSID, result);
0197: // associated CLSID may not be installed on this machine
0198: if (getProgramID() == null)
0199: OLE.error(OLE.ERROR_INVALID_CLASSID, result);
0200:
0201: // Open a temporary storage object
0202: tempStorage = createTempStorage();
0203:
0204: // Create ole object with storage object
0205: int /*long*/[] address = new int /*long*/[1];
0206: result = COM.OleCreateFromFile(appClsid, fileName,
0207: COM.IIDIUnknown, COM.OLERENDER_DRAW, null, 0,
0208: tempStorage.getAddress(), address);
0209: if (result != COM.S_OK)
0210: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0211:
0212: objIUnknown = new IUnknown(address[0]);
0213:
0214: // Init sinks
0215: addObjectReferences();
0216:
0217: if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK)
0218: state = STATE_RUNNING;
0219: } catch (SWTException e) {
0220: dispose();
0221: disposeCOMInterfaces();
0222: throw e;
0223: }
0224: }
0225:
0226: /**
0227: * Create an OleClientSite child widget to edit a blank document using the specified OLE Document
0228: * application. Use style bits to select a particular look or set of properties.
0229: *
0230: * @param parent a composite widget; must be an OleFrame
0231: * @param style the bitwise OR'ing of widget styles
0232: * @param progId the unique program identifier of am OLE Document application;
0233: * the value of the ProgID key or the value of the VersionIndependentProgID key specified
0234: * in the registry for the desired OLE Document (for example, the VersionIndependentProgID
0235: * for Word is Word.Document)
0236: *
0237: * @exception IllegalArgumentException
0238: *<ul>
0239: * <li>ERROR_NULL_ARGUMENT when the parent is null
0240: * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
0241: *</ul>
0242: * @exception SWTException
0243: * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
0244: * <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
0245: * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
0246: * </ul>
0247: */
0248: public OleClientSite(Composite parent, int style, String progId) {
0249: this (parent, style);
0250: try {
0251: appClsid = getClassID(progId);
0252: if (appClsid == null)
0253: OLE.error(OLE.ERROR_INVALID_CLASSID);
0254:
0255: // Open a temporary storage object
0256: tempStorage = createTempStorage();
0257:
0258: // Create ole object with storage object
0259: int /*long*/[] address = new int /*long*/[1];
0260: int result = COM.OleCreate(appClsid, COM.IIDIUnknown,
0261: COM.OLERENDER_DRAW, null, 0, tempStorage
0262: .getAddress(), address);
0263: if (result != COM.S_OK)
0264: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0265:
0266: objIUnknown = new IUnknown(address[0]);
0267:
0268: // Init sinks
0269: addObjectReferences();
0270:
0271: if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK)
0272: state = STATE_RUNNING;
0273:
0274: } catch (SWTException e) {
0275: dispose();
0276: disposeCOMInterfaces();
0277: throw e;
0278: }
0279: }
0280:
0281: /**
0282: * Create an OleClientSite child widget to edit the specified file using the specified OLE Document
0283: * application. Use style bits to select a particular look or set of properties.
0284: * <p>
0285: * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
0286: * API for <code>OleClientSite</code>. It is marked public only so that it
0287: * can be shared within the packages provided by SWT. It is not
0288: * available on all platforms, and should never be called from
0289: * application code.
0290: * </p>
0291: * @param parent a composite widget; must be an OleFrame
0292: * @param style the bitwise OR'ing of widget styles
0293: * @param progId the unique program identifier of am OLE Document application;
0294: * the value of the ProgID key or the value of the VersionIndependentProgID key specified
0295: * in the registry for the desired OLE Document (for example, the VersionIndependentProgID
0296: * for Word is Word.Document)
0297: * @param file the file that is to be opened in this OLE Document
0298: *
0299: * @exception IllegalArgumentException
0300: * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
0301: * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
0302: * @exception SWTException
0303: * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
0304: * <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
0305: * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
0306: * <li>ERROR_CANNOT_OPEN_FILE when failed to open file
0307: * </ul>
0308: */
0309: public OleClientSite(Composite parent, int style, String progId,
0310: File file) {
0311: this (parent, style);
0312: try {
0313: if (file == null || file.isDirectory() || !file.exists())
0314: OLE.error(OLE.ERROR_INVALID_ARGUMENT);
0315: appClsid = getClassID(progId);
0316: if (appClsid == null)
0317: OLE.error(OLE.ERROR_INVALID_CLASSID);
0318:
0319: // Are we opening this file with the preferred OLE object?
0320: char[] fileName = (file.getAbsolutePath() + "\0")
0321: .toCharArray();
0322: GUID fileClsid = new GUID();
0323: COM.GetClassFile(fileName, fileClsid);
0324:
0325: if (COM.IsEqualGUID(appClsid, fileClsid)) {
0326: // Using the same application that created file, therefore, use default mechanism.
0327: tempStorage = createTempStorage();
0328: // Create ole object with storage object
0329: int /*long*/[] address = new int /*long*/[1];
0330: int result = COM.OleCreateFromFile(appClsid, fileName,
0331: COM.IIDIUnknown, COM.OLERENDER_DRAW, null, 0,
0332: tempStorage.getAddress(), address);
0333: if (result != COM.S_OK)
0334: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0335: objIUnknown = new IUnknown(address[0]);
0336: } else {
0337: // Not using the same application that created file, therefore, copy from original file to a new storage file
0338: IStorage storage = null;
0339: if (COM.StgIsStorageFile(fileName) == COM.S_OK) {
0340: int /*long*/[] address = new int /*long*/[1];
0341: int mode = COM.STGM_READ | COM.STGM_TRANSACTED
0342: | COM.STGM_SHARE_EXCLUSIVE;
0343: int result = COM.StgOpenStorage(fileName, 0, mode,
0344: 0, 0, address); //Does an AddRef if successful
0345: if (result != COM.S_OK)
0346: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
0347: storage = new IStorage(address[0]);
0348: } else {
0349: // Original file is not a Storage file so copy contents to a stream in a new storage file
0350: int /*long*/[] address = new int /*long*/[1];
0351: int mode = COM.STGM_READWRITE | COM.STGM_DIRECT
0352: | COM.STGM_SHARE_EXCLUSIVE
0353: | COM.STGM_CREATE;
0354: int result = COM.StgCreateDocfile(null, mode
0355: | COM.STGM_DELETEONRELEASE, 0, address); // Increments ref count if successful
0356: if (result != COM.S_OK)
0357: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
0358: storage = new IStorage(address[0]);
0359: // Create a stream on the storage object.
0360: // Word does not follow the standard and does not use "CONTENTS" as the name of
0361: // its primary stream
0362: String streamName = "CONTENTS"; //$NON-NLS-1$
0363: GUID wordGUID = getClassID(WORDPROGID);
0364: if (wordGUID != null
0365: && COM.IsEqualGUID(appClsid, wordGUID))
0366: streamName = "WordDocument"; //$NON-NLS-1$
0367: address = new int /*long*/[1];
0368: result = storage.CreateStream(streamName, mode, 0,
0369: 0, address); // Increments ref count if successful
0370: if (result != COM.S_OK) {
0371: storage.Release();
0372: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
0373: }
0374: IStream stream = new IStream(address[0]);
0375: try {
0376: // Copy over data in file to named stream
0377: FileInputStream fileInput = new FileInputStream(
0378: file);
0379: int increment = 1024 * 4;
0380: byte[] buffer = new byte[increment];
0381: int count = 0;
0382: while ((count = fileInput.read(buffer)) > 0) {
0383: int /*long*/pv = COM.CoTaskMemAlloc(count);
0384: OS.MoveMemory(pv, buffer, count);
0385: result = stream.Write(pv, count, null);
0386: COM.CoTaskMemFree(pv);
0387: if (result != COM.S_OK) {
0388: fileInput.close();
0389: stream.Release();
0390: storage.Release();
0391: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE,
0392: result);
0393: }
0394: }
0395: fileInput.close();
0396: stream.Commit(COM.STGC_DEFAULT);
0397: stream.Release();
0398: } catch (IOException err) {
0399: stream.Release();
0400: storage.Release();
0401: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE);
0402: }
0403: }
0404:
0405: // Open a temporary storage object
0406: tempStorage = createTempStorage();
0407: // Copy over contents of file
0408: int result = storage.CopyTo(0, null, null, tempStorage
0409: .getAddress());
0410: storage.Release();
0411: if (result != COM.S_OK)
0412: OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
0413:
0414: // create ole client
0415: int /*long*/[] ppv = new int /*long*/[1];
0416: result = COM.CoCreateInstance(appClsid, 0,
0417: COM.CLSCTX_INPROC_HANDLER
0418: | COM.CLSCTX_INPROC_SERVER,
0419: COM.IIDIUnknown, ppv);
0420: if (result != COM.S_OK)
0421: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0422: objIUnknown = new IUnknown(ppv[0]);
0423: // get the persistent storage of the ole client
0424: ppv = new int /*long*/[1];
0425: result = objIUnknown.QueryInterface(
0426: COM.IIDIPersistStorage, ppv);
0427: if (result != COM.S_OK)
0428: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0429: IPersistStorage iPersistStorage = new IPersistStorage(
0430: ppv[0]);
0431: // load the contents of the file into the ole client site
0432: result = iPersistStorage.Load(tempStorage.getAddress());
0433: iPersistStorage.Release();
0434: if (result != COM.S_OK)
0435: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0436: }
0437:
0438: // Init sinks
0439: addObjectReferences();
0440:
0441: if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK)
0442: state = STATE_RUNNING;
0443:
0444: } catch (SWTException e) {
0445: dispose();
0446: disposeCOMInterfaces();
0447: throw e;
0448: }
0449: }
0450:
0451: protected void addObjectReferences() {
0452: //
0453: int /*long*/[] ppvObject = new int /*long*/[1];
0454: if (objIUnknown.QueryInterface(COM.IIDIPersist, ppvObject) == COM.S_OK) {
0455: IPersist objIPersist = new IPersist(ppvObject[0]);
0456: GUID tempid = new GUID();
0457: if (objIPersist.GetClassID(tempid) == COM.S_OK)
0458: objClsid = tempid;
0459: objIPersist.Release();
0460: }
0461:
0462: //
0463: ppvObject = new int /*long*/[1];
0464: int result = objIUnknown.QueryInterface(COM.IIDIViewObject2,
0465: ppvObject);
0466: if (result != COM.S_OK)
0467: OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
0468: objIViewObject2 = new IViewObject2(ppvObject[0]);
0469: objIViewObject2.SetAdvise(aspect, 0, iAdviseSink.getAddress());
0470:
0471: //
0472: ppvObject = new int /*long*/[1];
0473: result = objIUnknown.QueryInterface(COM.IIDIOleObject,
0474: ppvObject);
0475: if (result != COM.S_OK)
0476: OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
0477: objIOleObject = new IOleObject(ppvObject[0]);
0478: objIOleObject.SetClientSite(iOleClientSite.getAddress());
0479: int[] pdwConnection = new int[1];
0480: objIOleObject.Advise(iAdviseSink.getAddress(), pdwConnection);
0481: objIOleObject.SetHostNames("main", "main"); //$NON-NLS-1$ //$NON-NLS-2$
0482:
0483: // Notify the control object that it is embedded in an OLE container
0484: COM.OleSetContainedObject(objIUnknown.getAddress(), true);
0485:
0486: // Is OLE object linked or embedded?
0487: ppvObject = new int /*long*/[1];
0488: if (objIUnknown.QueryInterface(COM.IIDIOleLink, ppvObject) == COM.S_OK) {
0489: IOleLink objIOleLink = new IOleLink(ppvObject[0]);
0490: int /*long*/[] ppmk = new int /*long*/[1];
0491: if (objIOleLink.GetSourceMoniker(ppmk) == COM.S_OK) {
0492: IMoniker objIMoniker = new IMoniker(ppmk[0]);
0493: objIMoniker.Release();
0494: type = COM.OLELINKED;
0495: objIOleLink.BindIfRunning();
0496: } else {
0497: isStatic = true;
0498: }
0499: objIOleLink.Release();
0500: }
0501: }
0502:
0503: protected int AddRef() {
0504: refCount++;
0505: return refCount;
0506: }
0507:
0508: private int CanInPlaceActivate() {
0509: if (aspect == COM.DVASPECT_CONTENT && type == COM.OLEEMBEDDED)
0510: return COM.S_OK;
0511:
0512: return COM.S_FALSE;
0513: }
0514:
0515: private int ContextSensitiveHelp(int fEnterMode) {
0516: return COM.S_OK;
0517: }
0518:
0519: protected void createCOMInterfaces() {
0520:
0521: iUnknown = new COMObject(new int[] { 2, 0, 0 }) {
0522: public int /*long*/method0(int /*long*/[] args) {
0523: return QueryInterface(args[0], args[1]);
0524: }
0525:
0526: public int /*long*/method1(int /*long*/[] args) {
0527: return AddRef();
0528: }
0529:
0530: public int /*long*/method2(int /*long*/[] args) {
0531: return Release();
0532: }
0533: };
0534:
0535: iOleClientSite = new COMObject(new int[] { 2, 0, 0, 0, 3, 1, 0,
0536: 1, 0 }) {
0537: public int /*long*/method0(int /*long*/[] args) {
0538: return QueryInterface(args[0], args[1]);
0539: }
0540:
0541: public int /*long*/method1(int /*long*/[] args) {
0542: return AddRef();
0543: }
0544:
0545: public int /*long*/method2(int /*long*/[] args) {
0546: return Release();
0547: }
0548:
0549: public int /*long*/method3(int /*long*/[] args) {
0550: return SaveObject();
0551: }
0552:
0553: // method4 GetMoniker - not implemented
0554: public int /*long*/method5(int /*long*/[] args) {
0555: return GetContainer(args[0]);
0556: }
0557:
0558: public int /*long*/method6(int /*long*/[] args) {
0559: return ShowObject();
0560: }
0561:
0562: public int /*long*/method7(int /*long*/[] args) {
0563: return OnShowWindow((int) /*64*/args[0]);
0564: }
0565: // method8 RequestNewObjectLayout - not implemented
0566: };
0567:
0568: iAdviseSink = new COMObject(
0569: new int[] { 2, 0, 0, 2, 2, 1, 0, 0 }) {
0570: public int /*long*/method0(int /*long*/[] args) {
0571: return QueryInterface(args[0], args[1]);
0572: }
0573:
0574: public int /*long*/method1(int /*long*/[] args) {
0575: return AddRef();
0576: }
0577:
0578: public int /*long*/method2(int /*long*/[] args) {
0579: return Release();
0580: }
0581:
0582: public int /*long*/method3(int /*long*/[] args) {
0583: return OnDataChange(args[0], args[1]);
0584: }
0585:
0586: public int /*long*/method4(int /*long*/[] args) {
0587: return OnViewChange((int) /*64*/args[0],
0588: (int) /*64*/args[1]);
0589: }
0590:
0591: //method5 OnRename - not implemented
0592: public int /*long*/method6(int /*long*/[] args) {
0593: OnSave();
0594: return 0;
0595: }
0596:
0597: public int /*long*/method7(int /*long*/[] args) {
0598: return OnClose();
0599: }
0600: };
0601:
0602: iOleInPlaceSite = new COMObject(new int[] { 2, 0, 0, 1, 1, 0,
0603: 0, 0, 5, C.PTR_SIZEOF == 4 ? 2 : 1, 1, 0, 0, 0, 1 }) {
0604: public int /*long*/method0(int /*long*/[] args) {
0605: return QueryInterface(args[0], args[1]);
0606: }
0607:
0608: public int /*long*/method1(int /*long*/[] args) {
0609: return AddRef();
0610: }
0611:
0612: public int /*long*/method2(int /*long*/[] args) {
0613: return Release();
0614: }
0615:
0616: public int /*long*/method3(int /*long*/[] args) {
0617: return GetWindow(args[0]);
0618: }
0619:
0620: public int /*long*/method4(int /*long*/[] args) {
0621: return ContextSensitiveHelp((int) /*64*/args[0]);
0622: }
0623:
0624: public int /*long*/method5(int /*long*/[] args) {
0625: return CanInPlaceActivate();
0626: }
0627:
0628: public int /*long*/method6(int /*long*/[] args) {
0629: return OnInPlaceActivate();
0630: }
0631:
0632: public int /*long*/method7(int /*long*/[] args) {
0633: return OnUIActivate();
0634: }
0635:
0636: public int /*long*/method8(int /*long*/[] args) {
0637: return GetWindowContext(args[0], args[1], args[2],
0638: args[3], args[4]);
0639: }
0640:
0641: public int /*long*/method9(int /*long*/[] args) {
0642: if (args.length == 2) {
0643: return Scroll((int) /*64*/args[0],
0644: (int) /*64*/args[1]);
0645: } else {
0646: return Scroll_64(args[0]);
0647: }
0648: }
0649:
0650: public int /*long*/method10(int /*long*/[] args) {
0651: return OnUIDeactivate((int) /*64*/args[0]);
0652: }
0653:
0654: public int /*long*/method11(int /*long*/[] args) {
0655: return OnInPlaceDeactivate();
0656: }
0657:
0658: // method12 DiscardUndoState - not implemented
0659: // method13 DeactivateAndUndoChange - not implemented
0660: public int /*long*/method14(int /*long*/[] args) {
0661: return OnPosRectChange(args[0]);
0662: }
0663: };
0664:
0665: iOleDocumentSite = new COMObject(new int[] { 2, 0, 0, 1 }) {
0666: public int /*long*/method0(int /*long*/[] args) {
0667: return QueryInterface(args[0], args[1]);
0668: }
0669:
0670: public int /*long*/method1(int /*long*/[] args) {
0671: return AddRef();
0672: }
0673:
0674: public int /*long*/method2(int /*long*/[] args) {
0675: return Release();
0676: }
0677:
0678: public int /*long*/method3(int /*long*/[] args) {
0679: return ActivateMe(args[0]);
0680: }
0681: };
0682: }
0683:
0684: protected IStorage createTempStorage() {
0685: int /*long*/[] tempStorage = new int /*long*/[1];
0686: int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE
0687: | COM.STGM_DELETEONRELEASE;
0688: int result = COM
0689: .StgCreateDocfile(null, grfMode, 0, tempStorage);
0690: if (result != COM.S_OK)
0691: OLE.error(OLE.ERROR_CANNOT_CREATE_FILE, result);
0692: return new IStorage(tempStorage[0]);
0693: }
0694:
0695: /**
0696: * Deactivates an active in-place object and discards the object's undo state.
0697: */
0698: public void deactivateInPlaceClient() {
0699: if (objIOleInPlaceObject != null) {
0700: objIOleInPlaceObject.InPlaceDeactivate();
0701: }
0702: }
0703:
0704: private void deleteTempStorage() {
0705: //Destroy this item's contents in the temp root IStorage.
0706: if (tempStorage != null) {
0707: tempStorage.Release();
0708: }
0709: tempStorage = null;
0710: }
0711:
0712: protected void disposeCOMInterfaces() {
0713: if (iUnknown != null)
0714: iUnknown.dispose();
0715: iUnknown = null;
0716:
0717: if (iOleClientSite != null)
0718: iOleClientSite.dispose();
0719: iOleClientSite = null;
0720:
0721: if (iAdviseSink != null)
0722: iAdviseSink.dispose();
0723: iAdviseSink = null;
0724:
0725: if (iOleInPlaceSite != null)
0726: iOleInPlaceSite.dispose();
0727: iOleInPlaceSite = null;
0728:
0729: if (iOleDocumentSite != null)
0730: iOleDocumentSite.dispose();
0731: iOleDocumentSite = null;
0732: }
0733:
0734: /**
0735: * Requests that the OLE Document or ActiveX Control perform an action; actions are almost always
0736: * changes to the activation state.
0737: *
0738: * @param verb the operation that is requested. This is one of the OLE.OLEIVERB_ values
0739: *
0740: * @return an HRESULT value indicating the success of the operation request; OLE.S_OK indicates
0741: * success
0742: */
0743: public int doVerb(int verb) {
0744: // Not all OLE clients (for example PowerPoint) can be set into the running state in the constructor.
0745: // The fix is to ensure that the client is in the running state before invoking any verb on it.
0746: if (state == STATE_NONE) {
0747: if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK)
0748: state = STATE_RUNNING;
0749: }
0750: if (state == STATE_NONE || isStatic)
0751: return COM.E_FAIL;
0752:
0753: // See PR: 1FV9RZW
0754: RECT rect = new RECT();
0755: OS.GetClientRect(handle, rect);
0756: int result = objIOleObject.DoVerb(verb, null, iOleClientSite
0757: .getAddress(), 0, handle, rect);
0758:
0759: if (state != STATE_RUNNING && inInit) {
0760: updateStorage();
0761: inInit = false;
0762: }
0763: return result;
0764: }
0765:
0766: /**
0767: * Asks the OLE Document or ActiveX Control to execute a command from a standard
0768: * list of commands. The OLE Document or ActiveX Control must support the IOleCommandTarget
0769: * interface. The OLE Document or ActiveX Control does not have to support all the commands
0770: * in the standard list. To check if a command is supported, you can call queryStatus with
0771: * the cmdID.
0772: *
0773: * @param cmdID the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
0774: * commands
0775: * @param options the optional flags; these are the OLE.OLECMDEXECOPT_ values
0776: * @param in the argument for the command
0777: * @param out the return value of the command
0778: *
0779: * @return an HRESULT value; OLE.S_OK is returned if successful
0780: *
0781: */
0782: public int exec(int cmdID, int options, Variant in, Variant out) {
0783:
0784: if (objIOleCommandTarget == null) {
0785: int /*long*/[] address = new int /*long*/[1];
0786: if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget,
0787: address) != COM.S_OK)
0788: return OLE.ERROR_INTERFACE_NOT_FOUND;
0789: objIOleCommandTarget = new IOleCommandTarget(address[0]);
0790: }
0791:
0792: int /*long*/inAddress = 0;
0793: if (in != null) {
0794: inAddress = OS.GlobalAlloc(
0795: OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
0796: in.getData(inAddress);
0797: }
0798: int /*long*/outAddress = 0;
0799: if (out != null) {
0800: outAddress = OS.GlobalAlloc(OS.GMEM_FIXED
0801: | OS.GMEM_ZEROINIT, VARIANT.sizeof);
0802: out.getData(outAddress);
0803: }
0804:
0805: int result = objIOleCommandTarget.Exec(null, cmdID, options,
0806: inAddress, outAddress);
0807:
0808: if (inAddress != 0) {
0809: COM.VariantClear(inAddress);
0810: OS.GlobalFree(inAddress);
0811: }
0812: if (outAddress != 0) {
0813: out.setData(outAddress);
0814: COM.VariantClear(outAddress);
0815: OS.GlobalFree(outAddress);
0816: }
0817:
0818: return result;
0819: }
0820:
0821: IDispatch getAutomationObject() {
0822: int /*long*/[] ppvObject = new int /*long*/[1];
0823: if (objIUnknown.QueryInterface(COM.IIDIDispatch, ppvObject) != COM.S_OK)
0824: return null;
0825: return new IDispatch(ppvObject[0]);
0826: }
0827:
0828: protected GUID getClassID(String clientName) {
0829: // create a GUID struct to hold the result
0830: GUID guid = new GUID();
0831:
0832: // create a null terminated array of char
0833: char[] buffer = null;
0834: if (clientName != null) {
0835: int count = clientName.length();
0836: buffer = new char[count + 1];
0837: clientName.getChars(0, count, buffer, 0);
0838: }
0839: if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK) {
0840: int result = COM.CLSIDFromString(buffer, guid);
0841: if (result != COM.S_OK)
0842: return null;
0843: }
0844: return guid;
0845: }
0846:
0847: private int GetContainer(int /*long*/ppContainer) {
0848: /* Simple containers that do not support links to their embedded
0849: * objects probably do not need to implement this method. Instead,
0850: * they can return E_NOINTERFACE and set ppContainer to NULL.
0851: */
0852: if (ppContainer != 0)
0853: COM.MoveMemory(ppContainer, new int /*long*/[] { 0 },
0854: OS.PTR_SIZEOF);
0855: return COM.E_NOINTERFACE;
0856: }
0857:
0858: private SIZE getExtent() {
0859: SIZE sizel = new SIZE();
0860: // get the current size of the embedded OLENatives object
0861: if (objIOleObject != null) {
0862: if (objIViewObject2 != null
0863: && !COM.OleIsRunning(objIOleObject.getAddress())) {
0864: objIViewObject2.GetExtent(aspect, -1, null, sizel);
0865: } else {
0866: objIOleObject.GetExtent(aspect, sizel);
0867: }
0868: }
0869: return xFormHimetricToPixels(sizel);
0870: }
0871:
0872: public Rectangle getIndent() {
0873: return new Rectangle(indent.left, indent.right, indent.top,
0874: indent.bottom);
0875: }
0876:
0877: /**
0878: * Returns the program ID of the OLE Document or ActiveX Control.
0879: *
0880: * @return the program ID of the OLE Document or ActiveX Control
0881: */
0882: public String getProgramID() {
0883: if (appClsid != null) {
0884: int /*long*/[] lplpszProgID = new int /*long*/[1];
0885: if (COM.ProgIDFromCLSID(appClsid, lplpszProgID) == COM.S_OK) {
0886: int /*long*/hMem = lplpszProgID[0];
0887: int length = OS.GlobalSize(hMem);
0888: int /*long*/ptr = OS.GlobalLock(hMem);
0889: char[] buffer = new char[length];
0890: COM.MoveMemory(buffer, ptr, length);
0891: OS.GlobalUnlock(hMem);
0892: OS.GlobalFree(hMem);
0893:
0894: String result = new String(buffer);
0895: // remove null terminator
0896: int index = result.indexOf("\0");
0897: return result.substring(0, index);
0898: }
0899: }
0900: return null;
0901: }
0902:
0903: int ActivateMe(int /*long*/pViewToActivate) {
0904: if (pViewToActivate == 0) {
0905: int /*long*/[] ppvObject = new int /*long*/[1];
0906: if (objIUnknown.QueryInterface(COM.IIDIOleDocument,
0907: ppvObject) != COM.S_OK)
0908: return COM.E_FAIL;
0909: IOleDocument objOleDocument = new IOleDocument(ppvObject[0]);
0910: if (objOleDocument.CreateView(iOleInPlaceSite.getAddress(),
0911: 0, 0, ppvObject) != COM.S_OK)
0912: return COM.E_FAIL;
0913: objOleDocument.Release();
0914: objDocumentView = new IOleDocumentView(ppvObject[0]);
0915: } else {
0916: objDocumentView = new IOleDocumentView(pViewToActivate);
0917: objDocumentView.AddRef();
0918: objDocumentView
0919: .SetInPlaceSite(iOleInPlaceSite.getAddress());
0920: }
0921: objDocumentView.UIActivate(1);//TRUE
0922: RECT rect = getRect();
0923: objDocumentView.SetRect(rect);
0924: objDocumentView.Show(1);//TRUE
0925: return COM.S_OK;
0926: }
0927:
0928: protected int GetWindow(int /*long*/phwnd) {
0929: if (phwnd == 0)
0930: return COM.E_INVALIDARG;
0931: if (frame == null) {
0932: COM.MoveMemory(phwnd, new int /*long*/[] { 0 },
0933: OS.PTR_SIZEOF);
0934: return COM.E_NOTIMPL;
0935: }
0936:
0937: // Copy the Window's handle into the memory passed in
0938: COM.MoveMemory(phwnd, new int /*long*/[] { handle },
0939: OS.PTR_SIZEOF);
0940: return COM.S_OK;
0941: }
0942:
0943: RECT getRect() {
0944: Rectangle area = getClientArea();
0945: RECT rect = new RECT();
0946: rect.left = area.x;
0947: rect.top = area.y;
0948: rect.right = area.x + area.width;
0949: rect.bottom = area.y + area.height;
0950: return rect;
0951: }
0952:
0953: private int GetWindowContext(int /*long*/ppFrame,
0954: int /*long*/ppDoc, int /*long*/lprcPosRect,
0955: int /*long*/lprcClipRect, int /*long*/lpFrameInfo) {
0956: if (frame == null || ppFrame == 0)
0957: return COM.E_NOTIMPL;
0958:
0959: // fill in frame handle
0960: int /*long*/iOleInPlaceFrame = frame.getIOleInPlaceFrame();
0961: COM
0962: .MoveMemory(ppFrame,
0963: new int /*long*/[] { iOleInPlaceFrame },
0964: OS.PTR_SIZEOF);
0965: frame.AddRef();
0966:
0967: // null out document handle
0968: if (ppDoc != 0)
0969: COM.MoveMemory(ppDoc, new int /*long*/[] { 0 },
0970: OS.PTR_SIZEOF);
0971:
0972: // fill in position and clipping info
0973: RECT rect = getRect();
0974: if (lprcPosRect != 0)
0975: OS.MoveMemory(lprcPosRect, rect, RECT.sizeof);
0976: if (lprcClipRect != 0)
0977: OS.MoveMemory(lprcClipRect, rect, RECT.sizeof);
0978:
0979: // get frame info
0980: OLEINPLACEFRAMEINFO frameInfo = new OLEINPLACEFRAMEINFO();
0981: frameInfo.cb = OLEINPLACEFRAMEINFO.sizeof;
0982: frameInfo.fMDIApp = 0;
0983: frameInfo.hwndFrame = frame.handle;
0984: Shell shell = getShell();
0985: Menu menubar = shell.getMenuBar();
0986: if (menubar != null && !menubar.isDisposed()) {
0987: int /*long*/hwnd = shell.handle;
0988: int cAccel = (int) /*64*/OS.SendMessage(hwnd, OS.WM_APP,
0989: 0, 0);
0990: if (cAccel != 0) {
0991: int /*long*/hAccel = OS.SendMessage(hwnd,
0992: OS.WM_APP + 1, 0, 0);
0993: if (hAccel != 0) {
0994: frameInfo.cAccelEntries = cAccel;
0995: frameInfo.haccel = hAccel;
0996: }
0997: }
0998: }
0999: COM.MoveMemory(lpFrameInfo, frameInfo,
1000: OLEINPLACEFRAMEINFO.sizeof);
1001:
1002: return COM.S_OK;
1003: }
1004:
1005: public boolean isDirty() {
1006: /*
1007: * Note: this method must return true unless it is absolutely clear that the
1008: * contents of the Ole Document do not differ from the contents in the file
1009: * on the file system.
1010: */
1011:
1012: // Get access to the persistent storage mechanism
1013: int /*long*/[] address = new int /*long*/[1];
1014: if (objIOleObject.QueryInterface(COM.IIDIPersistFile, address) != COM.S_OK)
1015: return true;
1016: IPersistStorage permStorage = new IPersistStorage(address[0]);
1017: // Are the contents of the permanent storage different from the file?
1018: int result = permStorage.IsDirty();
1019: permStorage.Release();
1020: if (result == COM.S_FALSE)
1021: return false;
1022: return true;
1023: }
1024:
1025: public boolean isFocusControl() {
1026: checkWidget();
1027: int /*long*/focusHwnd = OS.GetFocus();
1028: if (objIOleInPlaceObject == null)
1029: return (handle == focusHwnd);
1030: int /*long*/[] phwnd = new int /*long*/[1];
1031: objIOleInPlaceObject.GetWindow(phwnd);
1032: while (focusHwnd != 0) {
1033: if (phwnd[0] == focusHwnd)
1034: return true;
1035: focusHwnd = OS.GetParent(focusHwnd);
1036: }
1037: return false;
1038: }
1039:
1040: private int OnClose() {
1041: return COM.S_OK;
1042: }
1043:
1044: private int OnDataChange(int /*long*/pFormatetc,
1045: int /*long*/pStgmed) {
1046: return COM.S_OK;
1047: }
1048:
1049: private void onDispose(Event e) {
1050: inDispose = true;
1051: if (state != STATE_NONE)
1052: doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE);
1053: deactivateInPlaceClient();
1054: releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame
1055: deleteTempStorage();
1056:
1057: // remove listeners
1058: removeListener(SWT.Dispose, listener);
1059: removeListener(SWT.FocusIn, listener);
1060: removeListener(SWT.Paint, listener);
1061: removeListener(SWT.Traverse, listener);
1062: removeListener(SWT.KeyDown, listener);
1063: frame.removeListener(SWT.Resize, listener);
1064: frame.removeListener(SWT.Move, listener);
1065:
1066: frame.Release();
1067: frame = null;
1068: }
1069:
1070: void onFocusIn(Event e) {
1071: if (inDispose)
1072: return;
1073: if (state != STATE_UIACTIVE)
1074: doVerb(OLE.OLEIVERB_SHOW);
1075: if (objIOleInPlaceObject == null)
1076: return;
1077: if (isFocusControl())
1078: return;
1079: int /*long*/[] phwnd = new int /*long*/[1];
1080: objIOleInPlaceObject.GetWindow(phwnd);
1081: if (phwnd[0] == 0)
1082: return;
1083: OS.SetFocus(phwnd[0]);
1084: }
1085:
1086: void onFocusOut(Event e) {
1087: }
1088:
1089: private int OnInPlaceActivate() {
1090: state = STATE_INPLACEACTIVE;
1091: frame.setCurrentDocument(this );
1092: if (objIOleObject == null)
1093: return COM.S_OK;
1094: int /*long*/[] ppvObject = new int /*long*/[1];
1095: if (objIOleObject.QueryInterface(COM.IIDIOleInPlaceObject,
1096: ppvObject) == COM.S_OK) {
1097: objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
1098: }
1099: return COM.S_OK;
1100: }
1101:
1102: private int OnInPlaceDeactivate() {
1103: if (objIOleInPlaceObject != null)
1104: objIOleInPlaceObject.Release();
1105: objIOleInPlaceObject = null;
1106: state = STATE_RUNNING;
1107: redraw();
1108: Shell shell = getShell();
1109: if (isFocusControl() || frame.isFocusControl()) {
1110: shell.traverse(SWT.TRAVERSE_TAB_NEXT);
1111: }
1112: return COM.S_OK;
1113: }
1114:
1115: private int OnPosRectChange(int /*long*/lprcPosRect) {
1116: Point size = getSize();
1117: setExtent(size.x, size.y);
1118: return COM.S_OK;
1119: }
1120:
1121: private void onPaint(Event e) {
1122: if (state == STATE_RUNNING || state == STATE_INPLACEACTIVE) {
1123: SIZE size = getExtent();
1124: Rectangle area = getClientArea();
1125: RECT rect = new RECT();
1126: if (getProgramID().startsWith("Excel.Sheet")) { //$NON-NLS-1$
1127: rect.left = area.x;
1128: rect.right = area.x + (area.height * size.cx / size.cy);
1129: rect.top = area.y;
1130: rect.bottom = area.y + area.height;
1131: } else {
1132: rect.left = area.x;
1133: rect.right = area.x + size.cx;
1134: rect.top = area.y;
1135: rect.bottom = area.y + size.cy;
1136: }
1137:
1138: int /*long*/pArea = OS.GlobalAlloc(COM.GMEM_FIXED
1139: | COM.GMEM_ZEROINIT, RECT.sizeof);
1140: OS.MoveMemory(pArea, rect, RECT.sizeof);
1141: COM.OleDraw(objIUnknown.getAddress(), aspect, e.gc.handle,
1142: pArea);
1143: OS.GlobalFree(pArea);
1144: }
1145: }
1146:
1147: private void onResize(Event e) {
1148: Rectangle area = frame.getClientArea();
1149: setBounds(borderWidths.left, borderWidths.top, area.width
1150: - borderWidths.left - borderWidths.right, area.height
1151: - borderWidths.top - borderWidths.bottom);
1152:
1153: setObjectRects();
1154: }
1155:
1156: private void OnSave() {
1157: }
1158:
1159: private int OnShowWindow(int fShow) {
1160: return COM.S_OK;
1161: }
1162:
1163: private int OnUIActivate() {
1164: if (objIOleInPlaceObject == null)
1165: return COM.E_FAIL;
1166: state = STATE_UIACTIVE;
1167: int /*long*/[] phwnd = new int /*long*/[1];
1168: if (objIOleInPlaceObject.GetWindow(phwnd) == COM.S_OK) {
1169: OS.SetWindowPos(phwnd[0], OS.HWND_TOP, 0, 0, 0, 0,
1170: OS.SWP_NOSIZE | OS.SWP_NOMOVE);
1171: }
1172: return COM.S_OK;
1173: }
1174:
1175: private int OnUIDeactivate(int fUndoable) {
1176: // currently, we are ignoring the fUndoable flag
1177: if (frame == null || frame.isDisposed())
1178: return COM.S_OK;
1179: state = STATE_INPLACEACTIVE;
1180: frame.SetActiveObject(0, 0);
1181: redraw();
1182: Shell shell = getShell();
1183: if (isFocusControl() || frame.isFocusControl()) {
1184: shell.traverse(SWT.TRAVERSE_TAB_NEXT);
1185: }
1186: Menu menubar = shell.getMenuBar();
1187: if (menubar == null || menubar.isDisposed())
1188: return COM.S_OK;
1189:
1190: int /*long*/shellHandle = shell.handle;
1191: OS.SetMenu(shellHandle, menubar.handle);
1192: return COM.OleSetMenuDescriptor(0, shellHandle, 0, 0, 0);
1193: }
1194:
1195: private void onTraverse(Event event) {
1196: switch (event.detail) {
1197: case SWT.TRAVERSE_ESCAPE:
1198: case SWT.TRAVERSE_RETURN:
1199: case SWT.TRAVERSE_TAB_NEXT:
1200: case SWT.TRAVERSE_TAB_PREVIOUS:
1201: case SWT.TRAVERSE_PAGE_NEXT:
1202: case SWT.TRAVERSE_PAGE_PREVIOUS:
1203: case SWT.TRAVERSE_MNEMONIC:
1204: event.doit = true;
1205: break;
1206: }
1207: }
1208:
1209: private int OnViewChange(int dwAspect, int lindex) {
1210: return COM.S_OK;
1211: }
1212:
1213: protected int QueryInterface(int /*long*/riid,
1214: int /*long*/ppvObject) {
1215:
1216: if (riid == 0 || ppvObject == 0)
1217: return COM.E_NOINTERFACE;
1218: GUID guid = new GUID();
1219: COM.MoveMemory(guid, riid, GUID.sizeof);
1220:
1221: if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
1222: COM.MoveMemory(ppvObject, new int /*long*/[] { iUnknown
1223: .getAddress() }, OS.PTR_SIZEOF);
1224: AddRef();
1225: return COM.S_OK;
1226: }
1227: if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) {
1228: COM.MoveMemory(ppvObject, new int /*long*/[] { iAdviseSink
1229: .getAddress() }, OS.PTR_SIZEOF);
1230: AddRef();
1231: return COM.S_OK;
1232: }
1233: if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) {
1234: COM
1235: .MoveMemory(ppvObject,
1236: new int /*long*/[] { iOleClientSite
1237: .getAddress() }, OS.PTR_SIZEOF);
1238: AddRef();
1239: return COM.S_OK;
1240: }
1241: if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) {
1242: COM
1243: .MoveMemory(ppvObject,
1244: new int /*long*/[] { iOleInPlaceSite
1245: .getAddress() }, OS.PTR_SIZEOF);
1246: AddRef();
1247: return COM.S_OK;
1248: }
1249: if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite)) {
1250: String progID = getProgramID();
1251: if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
1252: COM.MoveMemory(ppvObject,
1253: new int /*long*/[] { iOleDocumentSite
1254: .getAddress() }, OS.PTR_SIZEOF);
1255: AddRef();
1256: return COM.S_OK;
1257: }
1258: }
1259: COM.MoveMemory(ppvObject, new int /*long*/[] { 0 },
1260: OS.PTR_SIZEOF);
1261: return COM.E_NOINTERFACE;
1262: }
1263:
1264: /**
1265: * Returns the status of the specified command. The status is any bitwise OR'd combination of
1266: * SWTOLE.OLECMDF_SUPPORTED, SWTOLE.OLECMDF_ENABLED, SWTOLE.OLECMDF_LATCHED, SWTOLE.OLECMDF_NINCHED.
1267: * You can query the status of a command before invoking it with OleClientSite.exec. The
1268: * OLE Document or ActiveX Control must support the IOleCommandTarget to make use of this method.
1269: *
1270: * @param cmd the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
1271: * commands
1272: *
1273: * @return the status of the specified command or 0 if unable to query the OLE Object; these are the
1274: * OLE.OLECMDF_ values
1275: */
1276: public int queryStatus(int cmd) {
1277:
1278: if (objIOleCommandTarget == null) {
1279: int /*long*/[] address = new int /*long*/[1];
1280: if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget,
1281: address) != COM.S_OK)
1282: return 0;
1283: objIOleCommandTarget = new IOleCommandTarget(address[0]);
1284: }
1285:
1286: OLECMD olecmd = new OLECMD();
1287: olecmd.cmdID = cmd;
1288:
1289: int result = objIOleCommandTarget.QueryStatus(null, 1, olecmd,
1290: null);
1291:
1292: if (result != COM.S_OK)
1293: return 0;
1294:
1295: return olecmd.cmdf;
1296: }
1297:
1298: protected int Release() {
1299: refCount--;
1300:
1301: if (refCount == 0) {
1302: disposeCOMInterfaces();
1303: }
1304: return refCount;
1305: }
1306:
1307: protected void releaseObjectInterfaces() {
1308:
1309: if (objIOleInPlaceObject != null)
1310: objIOleInPlaceObject.Release();
1311: objIOleInPlaceObject = null;
1312:
1313: if (objIOleObject != null) {
1314: objIOleObject.Close(COM.OLECLOSE_NOSAVE);
1315: objIOleObject.Release();
1316: }
1317: objIOleObject = null;
1318:
1319: if (objDocumentView != null) {
1320: objDocumentView.Release();
1321: }
1322: objDocumentView = null;
1323:
1324: if (objIViewObject2 != null) {
1325: objIViewObject2.SetAdvise(aspect, 0, 0);
1326: objIViewObject2.Release();
1327: }
1328: objIViewObject2 = null;
1329:
1330: if (objIOleCommandTarget != null)
1331: objIOleCommandTarget.Release();
1332: objIOleCommandTarget = null;
1333:
1334: if (objIUnknown != null) {
1335: objIUnknown.Release();
1336: }
1337: objIUnknown = null;
1338:
1339: COM.CoFreeUnusedLibraries();
1340: }
1341:
1342: public boolean save(File file, boolean includeOleInfo) {
1343: if (includeOleInfo)
1344: return saveToStorageFile(file);
1345: return saveToTraditionalFile(file);
1346: }
1347:
1348: private boolean saveFromContents(int /*long*/address, File file) {
1349:
1350: boolean success = false;
1351:
1352: IStream tempContents = new IStream(address);
1353: tempContents.AddRef();
1354:
1355: try {
1356: FileOutputStream writer = new FileOutputStream(file);
1357:
1358: int increment = 1024 * 4;
1359: int /*long*/pv = COM.CoTaskMemAlloc(increment);
1360: int[] pcbWritten = new int[1];
1361: while (tempContents.Read(pv, increment, pcbWritten) == COM.S_OK
1362: && pcbWritten[0] > 0) {
1363: byte[] buffer = new byte[pcbWritten[0]];
1364: OS.MoveMemory(buffer, pv, pcbWritten[0]);
1365: writer.write(buffer); // Note: if file does not exist, this will create the file the
1366: // first time it is called
1367: success = true;
1368: }
1369: COM.CoTaskMemFree(pv);
1370:
1371: writer.close();
1372:
1373: } catch (IOException err) {
1374: }
1375:
1376: tempContents.Release();
1377:
1378: return success;
1379: }
1380:
1381: private boolean saveFromOle10Native(int /*long*/address, File file) {
1382:
1383: boolean success = false;
1384:
1385: IStream tempContents = new IStream(address);
1386: tempContents.AddRef();
1387:
1388: // The "\1Ole10Native" stream contains a DWORD header whose value is the length
1389: // of the native data that follows.
1390: int /*long*/pv = COM.CoTaskMemAlloc(4);
1391: int[] size = new int[1];
1392: int rc = tempContents.Read(pv, 4, null);
1393: OS.MoveMemory(size, pv, 4);
1394: COM.CoTaskMemFree(pv);
1395: if (rc == COM.S_OK && size[0] > 0) {
1396:
1397: // Read the data
1398: byte[] buffer = new byte[size[0]];
1399: pv = COM.CoTaskMemAlloc(size[0]);
1400: rc = tempContents.Read(pv, size[0], null);
1401: OS.MoveMemory(buffer, pv, size[0]);
1402: COM.CoTaskMemFree(pv);
1403:
1404: // open the file and write data into it
1405: try {
1406: FileOutputStream writer = new FileOutputStream(file);
1407: writer.write(buffer); // Note: if file does not exist, this will create the file
1408: writer.close();
1409:
1410: success = true;
1411: } catch (IOException err) {
1412: }
1413: }
1414: tempContents.Release();
1415:
1416: return success;
1417: }
1418:
1419: private int SaveObject() {
1420:
1421: updateStorage();
1422:
1423: return COM.S_OK;
1424: }
1425:
1426: /**
1427: * Saves the document to the specified file and includes OLE specific information. This method
1428: * must <b>only</b> be used for files that have an OLE Storage format. For example, a word file
1429: * edited with Word.Document should be saved using this method because there is formating information
1430: * that should be stored in the OLE specific Storage format.
1431: *
1432: * @param file the file to which the changes are to be saved
1433: *
1434: * @return true if the save was successful
1435: */
1436: private boolean saveToStorageFile(File file) {
1437: // The file will be saved using the formating of the current application - this
1438: // may not be the format of the application that was originally used to create the file
1439: // e.g. if an Excel file is opened in Word, the Word application will save the file in the
1440: // Word format
1441: // Note: if the file already exists, some applications will not overwrite the file
1442: // In these cases, you should delete the file first (probably save the contents of the file in case the
1443: // save fails)
1444: if (file == null || file.isDirectory())
1445: return false;
1446: if (!updateStorage())
1447: return false;
1448:
1449: // get access to the persistent storage mechanism
1450: int /*long*/[] address = new int /*long*/[1];
1451: if (objIOleObject.QueryInterface(COM.IIDIPersistStorage,
1452: address) != COM.S_OK)
1453: return false;
1454: IPersistStorage permStorage = new IPersistStorage(address[0]);
1455: try {
1456: address = new int /*long*/[1];
1457: char[] path = (file.getAbsolutePath() + "\0").toCharArray();
1458: int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE
1459: | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
1460: int result = COM.StgCreateDocfile(path, mode, 0, address); //Does an AddRef if successful
1461: if (result != COM.S_OK)
1462: return false;
1463: IStorage storage = new IStorage(address[0]);
1464: try {
1465: if (COM.OleSave(permStorage.getAddress(), storage
1466: .getAddress(), false) == COM.S_OK) {
1467: if (storage.Commit(COM.STGC_DEFAULT) == COM.S_OK) {
1468: return true;
1469: }
1470: }
1471: } finally {
1472: storage.Release();
1473: }
1474: } finally {
1475: permStorage.Release();
1476: }
1477: return false;
1478: }
1479:
1480: /**
1481: * Saves the document to the specified file. This method must be used for
1482: * files that do not have an OLE Storage format. For example, a bitmap file edited with MSPaint
1483: * should be saved using this method because bitmap is a standard format that does not include any
1484: * OLE specific data.
1485: *
1486: * @param file the file to which the changes are to be saved
1487: *
1488: * @return true if the save was successful
1489: */
1490: private boolean saveToTraditionalFile(File file) {
1491: // Note: if the file already exists, some applications will not overwrite the file
1492: // In these cases, you should delete the file first (probably save the contents of the file in case the
1493: // save fails)
1494: if (file == null || file.isDirectory())
1495: return false;
1496: if (!updateStorage())
1497: return false;
1498:
1499: int /*long*/[] address = new int /*long*/[1];
1500: // Look for a CONTENTS stream
1501: if (tempStorage
1502: .OpenStream(
1503: "CONTENTS", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
1504: return saveFromContents(address[0], file);
1505:
1506: // Look for Ole 1.0 object stream
1507: if (tempStorage
1508: .OpenStream(
1509: "\1Ole10Native", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
1510: return saveFromOle10Native(address[0], file);
1511:
1512: return false;
1513: }
1514:
1515: private int Scroll_64(int /*long*/scrollExtent) {
1516: return COM.S_OK;
1517: }
1518:
1519: private int Scroll(int scrollExtent_cx, int scrollExtent_cy) {
1520: return COM.S_OK;
1521: }
1522:
1523: void setBorderSpace(RECT newBorderwidth) {
1524: borderWidths = newBorderwidth;
1525: // readjust size and location of client site
1526: Rectangle area = frame.getClientArea();
1527: setBounds(borderWidths.left, borderWidths.top, area.width
1528: - borderWidths.left - borderWidths.right, area.height
1529: - borderWidths.top - borderWidths.bottom);
1530: setObjectRects();
1531: }
1532:
1533: private void setExtent(int width, int height) {
1534: // Resize the width and height of the embedded/linked OLENatives object
1535: // to the specified values.
1536:
1537: if (objIOleObject == null || isStatic || inUpdate)
1538: return;
1539: SIZE currentExtent = getExtent();
1540: if (width == currentExtent.cx && height == currentExtent.cy)
1541: return;
1542:
1543: SIZE newExtent = new SIZE();
1544: newExtent.cx = width;
1545: newExtent.cy = height;
1546: newExtent = xFormPixelsToHimetric(newExtent);
1547:
1548: // Get the server running first, then do a SetExtent, then show it
1549: boolean alreadyRunning = COM.OleIsRunning(objIOleObject
1550: .getAddress());
1551: if (!alreadyRunning)
1552: COM.OleRun(objIOleObject.getAddress());
1553:
1554: if (objIOleObject.SetExtent(aspect, newExtent) == COM.S_OK) {
1555: inUpdate = true;
1556: objIOleObject.Update();
1557: inUpdate = false;
1558: if (!alreadyRunning)
1559: // Close server if it wasn't already running upon entering this method.
1560: objIOleObject.Close(COM.OLECLOSE_SAVEIFDIRTY);
1561: }
1562: }
1563:
1564: public void setIndent(Rectangle newIndent) {
1565: indent = new RECT();
1566: indent.left = newIndent.x;
1567: indent.right = newIndent.width;
1568: indent.top = newIndent.y;
1569: indent.bottom = newIndent.height;
1570: }
1571:
1572: private void setObjectRects() {
1573: if (objIOleInPlaceObject == null)
1574: return;
1575: // size the object to fill the available space
1576: // leave a border
1577: RECT rect = getRect();
1578: objIOleInPlaceObject.SetObjectRects(rect, rect);
1579: }
1580:
1581: private int ShowObject() {
1582: /* Tells the container to position the object so it is visible to
1583: * the user. This method ensures that the container itself is
1584: * visible and not minimized.
1585: */
1586: return COM.S_OK;
1587: }
1588:
1589: /**
1590: * Displays a dialog with the property information for this OLE Object. The OLE Document or
1591: * ActiveX Control must support the ISpecifyPropertyPages interface.
1592: *
1593: * @param title the name that will appear in the titlebar of the dialog
1594: */
1595: public void showProperties(String title) {
1596:
1597: // Get the Property Page information from the OLE Object
1598: int /*long*/[] ppvObject = new int /*long*/[1];
1599: if (objIUnknown.QueryInterface(COM.IIDISpecifyPropertyPages,
1600: ppvObject) != COM.S_OK)
1601: return;
1602: ISpecifyPropertyPages objISPP = new ISpecifyPropertyPages(
1603: ppvObject[0]);
1604: CAUUID caGUID = new CAUUID();
1605: int result = objISPP.GetPages(caGUID);
1606: objISPP.Release();
1607: if (result != COM.S_OK)
1608: return;
1609:
1610: // create a frame in which to display the pages
1611: char[] chTitle = null;
1612: if (title != null) {
1613: chTitle = new char[title.length()];
1614: title.getChars(0, title.length(), chTitle, 0);
1615: }
1616: result = COM.OleCreatePropertyFrame(frame.handle, 10, 10,
1617: chTitle, 1, new int /*long*/[] { objIUnknown
1618: .getAddress() }, caGUID.cElems, caGUID.pElems,
1619: COM.LOCALE_USER_DEFAULT, 0, 0);
1620:
1621: // free the property page information
1622: COM.CoTaskMemFree(caGUID.pElems);
1623: }
1624:
1625: private boolean updateStorage() {
1626:
1627: if (tempStorage == null)
1628: return false;
1629:
1630: int /*long*/[] ppv = new int /*long*/[1];
1631: if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) != COM.S_OK)
1632: return false;
1633: IPersistStorage iPersistStorage = new IPersistStorage(ppv[0]);
1634:
1635: int result = COM.OleSave(iPersistStorage.getAddress(),
1636: tempStorage.getAddress(), true);
1637:
1638: if (result != COM.S_OK) {
1639: // OleSave will fail for static objects, so do what OleSave does.
1640: COM.WriteClassStg(tempStorage.getAddress(), objClsid);
1641: result = iPersistStorage.Save(tempStorage.getAddress(),
1642: true);
1643: }
1644:
1645: tempStorage.Commit(COM.STGC_DEFAULT);
1646: result = iPersistStorage.SaveCompleted(0);
1647: iPersistStorage.Release();
1648:
1649: return true;
1650: }
1651:
1652: private SIZE xFormHimetricToPixels(SIZE aSize) {
1653: // Return a new Size which is the pixel transformation of a
1654: // size in HIMETRIC units.
1655:
1656: int /*long*/hDC = OS.GetDC(0);
1657: int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
1658: int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
1659: OS.ReleaseDC(0, hDC);
1660: int cx = Compatibility.round(aSize.cx * xppi, 2540); // 2540 HIMETRIC units per inch
1661: int cy = Compatibility.round(aSize.cy * yppi, 2540);
1662: SIZE size = new SIZE();
1663: size.cx = cx;
1664: size.cy = cy;
1665: return size;
1666: }
1667:
1668: private SIZE xFormPixelsToHimetric(SIZE aSize) {
1669: // Return a new size which is the HIMETRIC transformation of a
1670: // size in pixel units.
1671:
1672: int /*long*/hDC = OS.GetDC(0);
1673: int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
1674: int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
1675: OS.ReleaseDC(0, hDC);
1676: int cx = Compatibility.round(aSize.cx * 2540, xppi); // 2540 HIMETRIC units per inch
1677: int cy = Compatibility.round(aSize.cy * 2540, yppi);
1678: SIZE size = new SIZE();
1679: size.cx = cx;
1680: size.cy = cy;
1681: return size;
1682: }
1683: }
|