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 org.eclipse.swt.dnd.FileTransfer;
14 
15 import org.eclipse.swt.internal.gtk.OS;
16 import org.eclipse.swt.dnd.ByteArrayTransfer;
17 import org.eclipse.swt.dnd.TransferData;
18 import org.eclipse.swt.dnd.DND;
19 import java.lang.all;
20 
21 /**
22  * The class <code>FileTransfer</code> provides a platform specific mechanism
23  * for converting a list of files represented as a java <code>String[]</code> to a
24  * platform specific representation of the data and vice versa.
25  * Each <code>String</code> in the array contains the absolute path for a single
26  * file or directory.
27  *
28  * <p>An example of a java <code>String[]</code> containing a list of files is shown
29  * below:</p>
30  *
31  * <code><pre>
32  *     File file1 = new File("C:\temp\file1");
33  *     File file2 = new File("C:\temp\file2");
34  *     String[] fileData = new String[2];
35  *     fileData[0] = file1.getAbsolutePath();
36  *     fileData[1] = file2.getAbsolutePath();
37  * </code></pre>
38  *
39  * @see Transfer
40  */
41 public class FileTransfer : ByteArrayTransfer {
42 
43     private static FileTransfer _instance;
44     private static const String URI_LIST = "text/uri-list"; //$NON-NLS-1$
45     private static const int URI_LIST_ID;
46     private static const String separator = "\r\n";
47 
48 static this(){
49     URI_LIST_ID = registerType(URI_LIST);
50     _instance = new FileTransfer();
51 }
52 
53 private this() {}
54 
55 /**
56  * Returns the singleton instance of the FileTransfer class.
57  *
58  * @return the singleton instance of the FileTransfer class
59  */
60 public static FileTransfer getInstance () {
61     return _instance;
62 }
63 
64 /**
65  * This implementation of <code>javaToNative</code> converts a list of file names
66  * represented by a java <code>String[]</code> to a platform specific representation.
67  * Each <code>String</code> in the array contains the absolute path for a single
68  * file or directory.
69  *
70  * @param object a java <code>String[]</code> containing the file names to be converted
71  * @param transferData an empty <code>TransferData</code> object that will
72  *      be filled in on return with the platform specific format of the data
73  *
74  * @see Transfer#nativeToJava
75  */
76 public override void javaToNative(Object object, TransferData transferData) {
77     transferData.result = 0;
78     if (!checkFile(object) || !isSupportedType(transferData)) {
79         DND.error(DND.ERROR_INVALID_DATA);
80     }
81     String[] files = (cast(ArrayWrapperString2)object).array;
82     char[] buffer;
83     for (int i = 0; i < files.length; i++) {
84         String string = files[i];
85         if (string.ptr is null) continue;
86         if (string.length is 0) continue;
87         GError* error;
88         auto localePtr = OS.g_filename_from_utf8(string.ptr, -1, null, null, &error);
89         if (error !is null || localePtr is null) continue;
90         auto uriPtr = OS.g_filename_to_uri(localePtr, null, &error);
91         OS.g_free(localePtr);
92         if (error !is null || uriPtr is null) continue;
93         String temp = fromStringz( uriPtr )._idup();
94         OS.g_free(uriPtr);
95         size_t newLength = (i > 0) ? buffer.length+separator.length+temp.length :  temp.length;
96         auto newBuffer = new char[newLength];
97         size_t offset = 0;
98         if (i > 0) {
99             System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
100             offset +=  buffer.length;
101             System.arraycopy(separator, 0, newBuffer, offset, separator.length);
102             offset += separator.length;
103         }
104         System.arraycopy(temp, 0, newBuffer, offset, temp.length);
105         buffer = newBuffer;
106     }
107     if (buffer.length is 0) return;
108     char* ptr = cast(char*)OS.g_malloc(buffer.length+1);
109     ptr[ 0 .. buffer.length ] = buffer;
110     ptr[ buffer.length ] = '\0';
111     transferData.pValue = ptr;
112     transferData.length = cast(int)/*64bit*/buffer.length;
113     transferData.format = 8;
114     transferData.result = 1;
115 }
116 /**
117  * This implementation of <code>nativeToJava</code> converts a platform specific
118  * representation of a list of file names to a java <code>String[]</code>.
119  * Each String in the array contains the absolute path for a single file or directory.
120  *
121  * @param transferData the platform specific representation of the data to be converted
122  * @return a java <code>String[]</code> containing a list of file names if the conversion
123  *      was successful; otherwise null
124  *
125  * @see Transfer#javaToNative
126  */
127 public override Object nativeToJava(TransferData transferData) {
128     if ( !isSupportedType(transferData) ||  transferData.pValue is null ||  transferData.length <= 0 ) return null;
129     auto temp = transferData.pValue[ 0 .. transferData.length ];
130     char*[] files;
131     int offset = 0;
132     for (int i = 0; i < temp.length - 1; i++) {
133         if (temp[i] is '\r' && temp[i+1] is '\n') {
134             int size =  i - offset;
135             char* file = cast(char*)OS.g_malloc(size + 1);
136             file[ 0 .. size ] = temp[ offset .. offset+size ];
137             file[ size ] = '\0';
138             files ~= file;
139             offset = i + 2;
140         }
141     }
142     if (offset < temp.length - 2) {
143         auto size =  temp.length - offset;
144         char* file = cast(char*)OS.g_malloc(size + 1);
145         file[ 0 .. size ] = temp[ offset .. offset+size ];
146         file[ size ] = '\0';
147         files ~= file;
148     }
149     String[] fileNames;
150     for (int i = 0; i < files.length; i++) {
151         GError* error;
152         auto localePtr = OS.g_filename_from_uri(files[i], null, &error);
153         OS.g_free(files[i]);
154         if (error !is null || localePtr is null) continue;
155         auto utf8Ptr = OS.g_filename_to_utf8(localePtr, -1, null, null, &error);
156         OS.g_free(localePtr);
157         if (error !is null || utf8Ptr is null) continue;
158         String buffer = fromStringz( utf8Ptr )._idup();
159         OS.g_free(utf8Ptr);
160         String name = buffer;
161         String[] newFileNames = new String[]( fileNames.length + 1 );
162         System.arraycopy(fileNames, 0, newFileNames, 0, fileNames.length);
163         newFileNames[fileNames.length] = name;
164         fileNames = newFileNames;
165     }
166     if (fileNames.length is 0) return null;
167     return new ArrayWrapperString2( fileNames );
168 }
169 
170 protected override int[] getTypeIds(){
171     return [URI_LIST_ID];
172 }
173 
174 protected override String[] getTypeNames(){
175     return [URI_LIST];
176 }
177 
178 bool checkFile(Object object) {
179     if( object is null ) return false;
180     ArrayWrapperString2 arr = cast(ArrayWrapperString2)object;
181     if( arr is null ) return false;
182     if( arr.array.length is 0 ) return false;
183 
184     String[] strings = arr.array;
185     for (int i = 0; i < strings.length; i++) {
186         if (strings[i] is null || strings[i].length is 0) return false;
187     }
188     return true;
189 }
190 
191 protected override bool validate(Object object) {
192     return checkFile(object);
193 }
194 }