root/dwt/dnd/HTMLTransfer.d

Revision 320:da968414c383, 9.0 kB (checked in by Frank Benoit <benoit@tionex.de>, 2 months ago)

Merge changes SWT 3.4.1

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 dwt.dnd.HTMLTransfer;
14
15 import dwt.internal.ole.win32.COM;
16 import dwt.internal.ole.win32.OBJIDL;
17 import dwt.internal.win32.OS;
18
19 import dwt.dnd.ByteArrayTransfer;
20 import dwt.dnd.TransferData;
21 import dwt.dnd.DND;
22
23 import dwt.dwthelper.utils;
24 static import tango.text.Text;
25 alias tango.text.Text.Text!(char) StringBuffer;
26
27 /**
28  * The class <code>HTMLTransfer</code> provides a platform specific mechanism
29  * for converting text in HTML format represented as a java <code>String</code>
30  * to a platform specific representation of the data and vice versa.
31  *
32  * <p>An example of a java <code>String</code> containing HTML text is shown
33  * below:</p>
34  *
35  * <code><pre>
36  *     String htmlData = "<p>This is a paragraph of text.</p>";
37  * </code></pre>
38  *
39  * @see Transfer
40  */
41 public class HTMLTransfer : ByteArrayTransfer {
42
43     static HTMLTransfer _instance;
44     static const String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
45     static const int HTML_FORMATID;
46     static const String NUMBER = "00000000"; //$NON-NLS-1$
47     static const String HEADER = "Version:0.9\r\nStartHTML:"~NUMBER~"\r\nEndHTML:"~NUMBER~"\r\nStartFragment:"~NUMBER~"\r\nEndFragment:"~NUMBER~"\r\n";
48     static const String PREFIX = "<html><body><!--StartFragment-->"; //$NON-NLS-1$
49     static const String SUFFIX = "<!--EndFragment--></body></html>"; //$NON-NLS-1$
50     static const String StartFragment = "StartFragment:"; //$NON-NLS-1$
51     static const String EndFragment = "EndFragment:"; //$NON-NLS-1$
52
53 static this(){
54     HTML_FORMATID = registerType(HTML_FORMAT);
55 }
56
57 private this() {}
58
59 /**
60  * Returns the singleton instance of the HTMLTransfer class.
61  *
62  * @return the singleton instance of the HTMLTransfer class
63  */
64 public static HTMLTransfer getInstance () {
65     if( _instance is null ){
66         synchronized {
67             if( _instance is null ){
68                 _instance = new HTMLTransfer();
69             }
70         }
71     }
72     return _instance;
73 }
74
75 /**
76  * This implementation of <code>javaToNative</code> converts HTML-formatted text
77  * represented by a java <code>String</code> to a platform specific representation.
78  *
79  * @param object a java <code>String</code> containing HTML text
80  * @param transferData an empty <code>TransferData</code> object that will
81  *      be filled in on return with the platform specific format of the data
82  *
83  * @see Transfer#nativeToJava
84  */
85 public void javaToNative (Object object, TransferData transferData){
86     if (!checkHTML(object) || !isSupportedType(transferData)) {
87         DND.error(DND.ERROR_INVALID_DATA);
88     }
89     String string = ( cast(ArrayWrapperString)object ).array;
90     /* NOTE: CF_HTML uses UTF-8 encoding. */
91     int cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, StrToTCHARz(string), -1, null, 0, null, null);
92     if (cchMultiByte is 0) {
93         transferData.stgmedium = new STGMEDIUM();
94         transferData.result = COM.DV_E_STGMEDIUM;
95         return;
96     }
97     int startHTML = HEADER.length;
98     int startFragment = startHTML + PREFIX.length;
99     int endFragment = startFragment + cchMultiByte - 1;
100     int endHTML = endFragment + SUFFIX.length;
101
102     StringBuffer buffer = new StringBuffer(HEADER);
103     int maxLength = NUMBER.length;
104     //startHTML
105     int start = buffer.toString().indexOf(NUMBER);
106     String temp = Integer.toString(startHTML);
107     buffer.select(start + maxLength-temp.length, temp.length);
108     buffer.replace(temp);
109     buffer.select();
110
111     //endHTML
112     start = buffer.toString().indexOf(NUMBER, start);
113     temp = Integer.toString(endHTML);
114     buffer.select(start + maxLength-temp.length, temp.length);
115     buffer.replace( temp);
116     buffer.select();
117
118     //startFragment
119     start = buffer.toString().indexOf(NUMBER, start);
120     temp = Integer.toString(startFragment);
121     buffer.select(start + maxLength-temp.length, temp.length);
122     buffer.replace(temp);
123     buffer.select();
124     //endFragment
125     start = buffer.toString().indexOf(NUMBER, start);
126     temp = Integer.toString(endFragment);
127     buffer.select(start + maxLength-temp.length, temp.length);
128     buffer.replace(temp);
129     buffer.select();
130
131     buffer.append(PREFIX);
132     buffer.append(string);
133     buffer.append(SUFFIX);
134
135     auto wstrz = StrToTCHARz(OS.CP_UTF8,buffer.toString);
136     cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, null, 0, null, null);
137     auto lpMultiByteStr = cast(PCHAR) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
138     OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null);
139     transferData.stgmedium = new STGMEDIUM();
140     transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
141     transferData.stgmedium.unionField = lpMultiByteStr;
142     transferData.stgmedium.pUnkForRelease = null;
143     transferData.result = COM.S_OK;
144     return;
145 }
146
147 /**
148  * This implementation of <code>nativeToJava</code> converts a platform specific
149  * representation of HTML text to a java <code>String</code>.
150  *
151  * @param transferData the platform specific representation of the data to be converted
152  * @return a java <code>String</code> containing HTML text if the conversion was successful;
153  *      otherwise null
154  *
155  * @see Transfer#javaToNative
156  */
157 public Object nativeToJava(TransferData transferData){
158     if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
159     IDataObject data = transferData.pIDataObject;
160     data.AddRef();
161     STGMEDIUM* stgmedium = new STGMEDIUM();
162     FORMATETC* formatetc = transferData.formatetc;
163     stgmedium.tymed = COM.TYMED_HGLOBAL;
164     transferData.result = getData(data, formatetc, stgmedium);
165     data.Release();
166     if (transferData.result !is COM.S_OK) return null;
167     auto hMem = stgmedium.unionField;
168
169     try {
170         auto lpMultiByteStr = cast(PCHAR) OS.GlobalLock(hMem);
171         if (lpMultiByteStr is null) return null;
172         try {
173             /* NOTE: CF_HTML uses UTF-8 encoding.
174              * The MSDN documentation for MultiByteToWideChar states that dwFlags must be set to 0 for UTF-8.
175              * Otherwise, the function fails with ERROR_INVALID_FLAGS. */
176             auto cchWideChar  = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, null, 0);
177             if (cchWideChar is 0) return null;
178             wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
179             OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
180             String string = WCHARzToStr(lpWideCharStr.ptr);
181             int fragmentStart = 0, fragmentEnd = 0;
182             int start = string.indexOf(StartFragment) + StartFragment.length;
183             int end = start + 1;
184             while (end < string.length) {
185                 String s = string.substring(start, end);
186                 try {
187                     fragmentStart = Integer.parseInt(s);
188                     end++;
189                 } catch (NumberFormatException e) {
190                     break;
191                 }
192             }
193             start = string.indexOf(EndFragment) + EndFragment.length;
194             end = start + 1;
195             while (end < string.length) {
196                 String s = string.substring(start, end);
197                 try {
198                     fragmentEnd = Integer.parseInt(s);
199                     end++;
200                 } catch (NumberFormatException e) {
201                     break;
202                 }
203             }
204             if (fragmentEnd <= fragmentStart || fragmentEnd > OS.strlen(lpMultiByteStr)) return null;
205             cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr+fragmentStart, fragmentEnd - fragmentStart, lpWideCharStr.ptr, lpWideCharStr.length);
206             if (cchWideChar is 0) return null;
207             String s = TCHARsToStr( lpWideCharStr[ 0 .. cchWideChar ] );
208             /*
209              * Firefox includes <!--StartFragment --> in the fragment, so remove it.
210              */
211             String foxStart = "<!--StartFragment -->\r\n"; //$NON-NLS-1$
212             int prefix = s.indexOf(foxStart);
213             if (prefix !is -1) {
214                 prefix += foxStart.length;
215                 s = s.substring(prefix);
216             }
217             return new ArrayWrapperString(s);
218         } finally {
219             OS.GlobalUnlock(hMem);
220         }
221     } finally {
222         OS.GlobalFree(hMem);
223     }
224 }
225 protected int[] getTypeIds(){
226     return [HTML_FORMATID];
227 }
228 protected String[] getTypeNames(){
229     return [HTML_FORMAT];
230 }
231 bool checkHTML(Object object) {
232     if( auto ws = cast(ArrayWrapperString)object ){
233         return ws.array.length > 0;
234     }
235     return false;
236 }
237 protected bool validate(Object object) {
238     return checkHTML(object);
239 }
240 }
Note: See TracBrowser for help on using the browser.