1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.dnd.OleEnumFORMATETC;
14 
15 import org.eclipse.swt.internal.ole.win32.COM;
16 import org.eclipse.swt.internal.ole.win32.OBJIDL;
17 import org.eclipse.swt.internal.ole.win32.extras;
18 import org.eclipse.swt.internal.win32.OS;
19 
20 final class OleEnumFORMATETC {
21 
22     private _IEnumFORMATETCImpl iEnumFORMATETC;
23 
24     private int refCount;
25     private int index;
26 
27     private FORMATETC*[] formats;
28 
29 this() {
30 
31     createCOMInterfaces();
32 
33 }
34 int AddRef() {
35     refCount++;
36     return refCount;
37 }
38 private void createCOMInterfaces() {
39     // register each of the interfaces that this object implements
40     iEnumFORMATETC = new _IEnumFORMATETCImpl( this );
41 }
42 private void disposeCOMInterfaces() {
43     iEnumFORMATETC = null;
44 }
45 IEnumFORMATETC getAddress() {
46     return iEnumFORMATETC;
47 }
48 private FORMATETC*[] getNextItems(int numItems){
49 
50     if (formats is null || numItems < 1) return null;
51 
52     int endIndex = index + numItems - 1;
53     if (endIndex > (formats.length - 1)) endIndex = cast(int)/*64bit*/formats.length - 1;
54     if (index > endIndex) return null;
55 
56     FORMATETC*[] items =  new FORMATETC*[endIndex - index + 1];
57     for (int i = 0; i < items.length; i++){
58         items[i] = formats[index];
59         index++;
60     }
61 
62     return items;
63 }
64 
65 package HRESULT Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
66     /* Retrieves the next celt items in the enumeration sequence.
67        If there are fewer than the requested number of elements left in the sequence,
68        it retrieves the remaining elements.
69        The number of elements actually retrieved is returned through pceltFetched
70        (unless the caller passed in NULL for that parameter).
71     */
72 
73     if (rgelt is null) return COM.E_INVALIDARG;
74     if (pceltFetched is null && celt !is 1) return COM.E_INVALIDARG;
75 
76     FORMATETC*[] nextItems = getNextItems(celt);
77     if (nextItems !is null) {
78         for (int i = 0; i < nextItems.length; i++) {
79             rgelt[i] = *nextItems[i];
80         }
81 
82         if (pceltFetched !is null)
83             *pceltFetched = cast(int)/*64bit*/nextItems.length;
84 
85         if (nextItems.length is celt) return COM.S_OK;
86 
87     } else {
88         if (pceltFetched !is null)
89             *pceltFetched = 0;
90         FORMATETC fInit;
91         COM.MoveMemory(rgelt, & fInit, FORMATETC.sizeof);
92 
93     }
94     return COM.S_FALSE;
95 }
96 private HRESULT QueryInterface(REFCIID riid, void** ppvObject) {
97 
98     if (riid is null || ppvObject is null) return COM.E_NOINTERFACE;
99 
100     if (COM.IsEqualGUID(riid, &COM.IIDIUnknown)) {
101         *ppvObject = cast(void*)cast(IUnknown)iEnumFORMATETC;
102         AddRef();
103         return COM.S_OK;
104     }
105     if (COM.IsEqualGUID(riid, &COM.IIDIEnumFORMATETC)) {
106         *ppvObject = cast(void*)cast(IEnumFORMATETC)iEnumFORMATETC;
107         AddRef();
108         return COM.S_OK;
109     }
110     *ppvObject = null;
111     return COM.E_NOINTERFACE;
112 }
113 int Release() {
114     refCount--;
115 
116     if (refCount is 0) {
117         disposeCOMInterfaces();
118         COM.CoFreeUnusedLibraries();
119     }
120 
121     return refCount;
122 }
123 private int Reset() {
124     //Resets the enumeration sequence to the beginning.
125     index = 0;
126     return COM.S_OK;
127 }
128 void setFormats(FORMATETC*[] newFormats) {
129     formats = newFormats;
130     index = 0;
131 }
132 private int Skip(int celt) {
133     //Skips over the next specified number of elements in the enumeration sequence.
134     if (celt < 1 ) return COM.E_INVALIDARG;
135 
136     index += celt;
137     if (index > (formats.length - 1)){
138         index = cast(int)/*64bit*/formats.length - 1;
139         return COM.S_FALSE;
140     }
141     return COM.S_OK;
142 }
143 }
144 
145 class _IEnumFORMATETCImpl : IEnumFORMATETC {
146 
147 
148     OleEnumFORMATETC    parent;
149     this(OleEnumFORMATETC   p) { parent = p; }
150 extern (Windows):
151     // interface of IUnknown
152     HRESULT QueryInterface(REFCIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
153     ULONG AddRef()  { return parent.AddRef(); }
154     ULONG Release() { return parent.Release(); }
155 
156     // interface of IEnumFORMATETC
157     HRESULT Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
158         return parent.Next(celt, rgelt, pceltFetched);
159     }
160     HRESULT Skip(ULONG celt) { return parent.Skip(celt); }
161     HRESULT Reset() { return parent.Reset(); }
162     HRESULT Clone(IEnumFORMATETC * ppenum) { return COM.E_NOTIMPL;}
163 }
164 
165