Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/Program.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | 950d84783eac |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
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.program.Program; | |
14 | |
15 import org.eclipse.swt.SWT; | |
16 import org.eclipse.swt.graphics.Image; | |
17 import org.eclipse.swt.graphics.ImageData; | |
18 import org.eclipse.swt.internal.win32.OS; | |
19 | |
20 import java.lang.all; | |
21 static import tango.text.convert.Utf; | |
22 | |
23 /** | |
24 * Instances of this class represent programs and | |
25 * their associated file extensions in the operating | |
26 * system. | |
27 * | |
28 * @see <a href="http://www.eclipse.org/swt/snippets/#program">Program snippets</a> | |
29 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
30 */ | |
31 public final class Program { | |
32 String name; | |
33 String command; | |
34 String iconName; | |
35 String extension; | |
36 static const String[] ARGUMENTS = ["%1"[], "%l", "%L"]; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
37 | |
38 /** | |
39 * Prevents uninitialized instances from being created outside the package. | |
40 */ | |
41 this () { | |
42 } | |
43 | |
44 static String assocQueryString (int assocStr, TCHAR[] key, bool expand) { | |
45 TCHAR[] pszOut = NewTCHARs(0, 1024); | |
46 uint[1] pcchOut; | |
47 pcchOut[0] = pszOut.length; | |
48 int flags = OS.ASSOCF_NOTRUNCATE | OS.ASSOCF_INIT_IGNOREUNKNOWN; | |
49 int result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); | |
50 if (result is OS.E_POINTER) { | |
51 pszOut = NewTCHARs(0, pcchOut [0]); | |
52 result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); | |
53 } | |
54 if (result is 0) { | |
55 if (!OS.IsWinCE && expand) { | |
56 int length_ = OS.ExpandEnvironmentStrings (pszOut.ptr, null, 0); | |
57 if (length_ !is 0) { | |
58 TCHAR[] lpDst = NewTCHARs (0, length_); | |
59 OS.ExpandEnvironmentStrings (pszOut.ptr, lpDst.ptr, length_); | |
60 return tango.text.convert.Utf.toString( lpDst[ 0 .. Math.max (0, length_ - 1) ] ); | |
61 } else { | |
62 return ""; | |
63 } | |
64 } else { | |
65 return tango.text.convert.Utf.toString( pszOut[ 0 .. Math.max (0, pcchOut [0] - 1)]); | |
66 } | |
67 } | |
68 return null; | |
69 } | |
70 | |
71 /** | |
72 * Finds the program that is associated with an extension. | |
73 * The extension may or may not begin with a '.'. Note that | |
74 * a <code>Display</code> must already exist to guarantee that | |
75 * this method returns an appropriate result. | |
76 * | |
77 * @param extension the program extension | |
78 * @return the program or <code>null</code> | |
79 * | |
80 */ | |
81 public static Program findProgram (String extension) { | |
82 // SWT extension: allow null string | |
83 //if (extension is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); | |
84 if (extension.length is 0) return null; | |
85 if (extension.charAt (0) !is '.') extension = "." ~ extension; //$NON-NLS-1$ | |
86 /* Use the character encoding for the default locale */ | |
87 TCHAR[] key = StrToTCHARs (0, extension, true); | |
88 Program program = null; | |
89 if (OS.IsWinCE) { | |
90 void*[1] phkResult; | |
91 if (OS.RegOpenKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) { | |
92 return null; | |
93 } | |
94 uint [1] lpcbData; | |
95 int result = OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr); | |
96 if (result is 0) { | |
97 TCHAR[] lpData = NewTCHARs (0, lpcbData [0] / TCHAR.sizeof); | |
98 result = OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr); | |
99 if (result is 0) program = getProgram ( TCHARzToStr( lpData.ptr ), extension); | |
100 } | |
101 OS.RegCloseKey (phkResult [0]); | |
102 } else { | |
103 String command = assocQueryString (OS.ASSOCSTR_COMMAND, key, true); | |
104 if (command !is null) { | |
105 String name = null; | |
106 if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYDOCNAME, key, false); | |
107 if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYAPPNAME, key, false); | |
108 if (name is null) name = ""; | |
109 String iconName = assocQueryString (OS.ASSOCSTR_DEFAULTICON, key, true); | |
110 if (iconName is null) iconName = ""; | |
111 program = new Program (); | |
112 program.name = name; | |
113 program.command = command; | |
114 program.iconName = iconName; | |
115 program.extension = extension; | |
116 } | |
117 } | |
118 return program; | |
119 } | |
120 | |
121 /** | |
122 * Answer all program extensions in the operating system. Note | |
123 * that a <code>Display</code> must already exist to guarantee | |
124 * that this method returns an appropriate result. | |
125 * | |
126 * @return an array of extensions | |
127 */ | |
128 public static String [] getExtensions () { | |
129 String [] extensions = new String [1024]; | |
130 /* Use the character encoding for the default locale */ | |
131 TCHAR[] lpName = NewTCHARs (0, 1024); | |
132 uint [1] lpcName; lpcName[0] = lpName.length; | |
133 FILETIME ft; | |
134 int dwIndex = 0, count = 0; | |
135 while (OS.RegEnumKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) { | |
136 String extension = TCHARsToStr( lpName[0 .. lpcName[0] ]); | |
137 lpcName [0] = lpName.length; | |
138 if (extension.length > 0 && extension.charAt (0) is '.') { | |
139 if (count is extensions.length) { | |
140 String[] newExtensions = new String[]( extensions.length + 1024 ); | |
141 System.arraycopy (extensions, 0, newExtensions, 0, extensions.length); | |
142 extensions = newExtensions; | |
143 } | |
144 extensions [count++] = extension; | |
145 } | |
146 dwIndex++; | |
147 } | |
148 if (count !is extensions.length) { | |
149 String[] newExtension = new String[]( count ); | |
150 System.arraycopy (extensions, 0, newExtension, 0, count); | |
151 extensions = newExtension; | |
152 } | |
153 return extensions; | |
154 } | |
155 | |
156 static String getKeyValue (String string, bool expand) { | |
157 /* Use the character encoding for the default locale */ | |
158 TCHAR[] key = StrToTCHARs (0, string, true); | |
159 void* [1] phkResult; | |
160 if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) { | |
161 return null; | |
162 } | |
163 String result = null; | |
164 uint [1] lpcbData; | |
165 if (OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr) is 0) { | |
166 result = ""; | |
167 int length_ = lpcbData [0] / TCHAR.sizeof; | |
168 if (length_ !is 0) { | |
169 /* Use the character encoding for the default locale */ | |
170 TCHAR[] lpData = NewTCHARs (0, length_); | |
171 if (OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr) is 0) { | |
172 if (!OS.IsWinCE && expand) { | |
173 length_ = OS.ExpandEnvironmentStrings (lpData.ptr, null, 0); | |
174 if (length_ !is 0) { | |
175 TCHAR[] lpDst = NewTCHARs (0, length_); | |
176 OS.ExpandEnvironmentStrings (lpData.ptr, lpDst.ptr, length_); | |
177 result = tango.text.convert.Utf.toString ( lpDst[0 .. Math.max (0, length_ - 1) ] ); | |
178 } | |
179 } else { | |
180 length_ = Math.max (0, lpData.length - 1); | |
181 result = tango.text.convert.Utf.toString ( lpData[0 .. length_]); | |
182 } | |
183 } | |
184 } | |
185 } | |
186 if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]); | |
187 return result; | |
188 } | |
189 | |
190 static Program getProgram (String key, String extension) { | |
191 | |
192 /* Name */ | |
193 String name = getKeyValue (key, false); | |
194 if (name is null || name.length is 0) { | |
195 name = key; | |
196 } | |
197 | |
198 /* Command */ | |
199 String DEFAULT_COMMAND = "\\shell"; //$NON-NLS-1$ | |
200 String defaultCommand = getKeyValue (key ~ DEFAULT_COMMAND, true); | |
201 if (defaultCommand is null || defaultCommand.length is 0) defaultCommand = "open"; //$NON-NLS-1$ | |
202 String COMMAND = "\\shell\\" ~ defaultCommand ~ "\\command"; //$NON-NLS-1$ | |
203 String command = getKeyValue (key ~ COMMAND, true); | |
204 if (command is null || command.length is 0) return null; | |
205 | |
206 /* Icon */ | |
207 String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$ | |
208 String iconName = getKeyValue (key ~ DEFAULT_ICON, true); | |
209 if (iconName is null) iconName = ""; //$NON-NLS-1$ | |
210 | |
211 /* Program */ | |
212 Program program = new Program (); | |
213 program.name = name; | |
214 program.command = command; | |
215 program.iconName = iconName; | |
216 program.extension = extension; | |
217 return program; | |
218 } | |
219 | |
220 /** | |
221 * Answers all available programs in the operating system. Note | |
222 * that a <code>Display</code> must already exist to guarantee | |
223 * that this method returns an appropriate result. | |
224 * | |
225 * @return an array of programs | |
226 */ | |
227 public static Program [] getPrograms () { | |
228 Program [] programs = new Program [1024]; | |
229 /* Use the character encoding for the default locale */ | |
230 TCHAR[] lpName = NewTCHARs (0, 1024); | |
231 uint [1] lpcName; lpcName[0] = lpName.length; | |
232 FILETIME ft; | |
233 int dwIndex = 0, count = 0; | |
234 while (OS.RegEnumKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) { | |
235 String path = tango.text.convert.Utf.toString ( lpName[0 .. lpcName [0]]); | |
236 lpcName [0] = lpName.length ; | |
237 Program program = getProgram (path, null); | |
238 if (program !is null) { | |
239 if (count is programs.length) { | |
240 Program [] newPrograms = new Program [programs.length + 1024]; | |
241 System.arraycopy (programs, 0, newPrograms, 0, programs.length); | |
242 programs = newPrograms; | |
243 } | |
244 programs [count++] = program; | |
245 } | |
246 dwIndex++; | |
247 } | |
248 if (count !is programs.length) { | |
249 Program [] newPrograms = new Program [count]; | |
250 System.arraycopy (programs, 0, newPrograms, 0, count); | |
251 programs = newPrograms; | |
252 } | |
253 return programs; | |
254 } | |
255 | |
256 /** | |
257 * Launches the operating system executable associated with the file or | |
258 * URL (http:// or https://). If the file is an executable then the | |
259 * executable is launched. Note that a <code>Display</code> must already | |
260 * exist to guarantee that this method returns an appropriate result. | |
261 * | |
262 * @param fileName the file or program name or URL (http:// or https://) | |
263 * @return <code>true</code> if the file is launched, otherwise <code>false</code> | |
264 * | |
265 * @exception IllegalArgumentException <ul> | |
266 * <li>ERROR_NULL_ARGUMENT when fileName is null</li> | |
267 * </ul> | |
268 */ | |
269 public static bool launch (String fileName) { | |
270 if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); | |
271 | |
272 /* Use the character encoding for the default locale */ | |
273 auto hHeap = OS.GetProcessHeap (); | |
274 TCHAR[] buffer = StrToTCHARs (0, fileName, true); | |
275 int byteCount = buffer.length * TCHAR.sizeof; | |
276 auto lpFile = cast(wchar*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
277 OS.MoveMemory (lpFile, buffer.ptr, byteCount); | |
278 SHELLEXECUTEINFO info; | |
279 info.cbSize = SHELLEXECUTEINFO.sizeof; | |
280 info.lpFile = lpFile; | |
281 info.nShow = OS.SW_SHOW; | |
282 bool result = cast(bool) OS.ShellExecuteEx (&info); | |
283 if (lpFile !is null) OS.HeapFree (hHeap, 0, lpFile); | |
284 return result; | |
285 } | |
286 | |
287 /** | |
288 * Executes the program with the file as the single argument | |
289 * in the operating system. It is the responsibility of the | |
290 * programmer to ensure that the file contains valid data for | |
291 * this program. | |
292 * | |
293 * @param fileName the file or program name | |
294 * @return <code>true</code> if the file is launched, otherwise <code>false</code> | |
295 * | |
296 * @exception IllegalArgumentException <ul> | |
297 * <li>ERROR_NULL_ARGUMENT when fileName is null</li> | |
298 * </ul> | |
299 */ | |
300 public bool execute (String fileName) { | |
301 if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); | |
302 int index = 0; | |
303 bool append = true; | |
304 String prefix = command, suffix = ""; //$NON-NLS-1$ | |
305 while (index < ARGUMENTS.length) { | |
306 int i = command.indexOf (ARGUMENTS [index]); | |
307 if (i !is -1) { | |
308 append = false; | |
309 prefix = command.substring (0, i); | |
310 suffix = command.substring (i + ARGUMENTS [index].length , command.length ); | |
311 break; | |
312 } | |
313 index++; | |
314 } | |
315 if (append) fileName = " \"" ~ fileName ~ "\""; | |
316 String commandLine = prefix ~ fileName ~ suffix; | |
317 auto hHeap = OS.GetProcessHeap (); | |
318 /* Use the character encoding for the default locale */ | |
319 TCHAR[] buffer = StrToTCHARs (0, commandLine, true); | |
320 int byteCount = buffer.length * TCHAR.sizeof; | |
321 auto lpCommandLine = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
322 OS.MoveMemory (lpCommandLine, buffer.ptr, byteCount); | |
323 STARTUPINFO lpStartupInfo; | |
324 lpStartupInfo.cb = STARTUPINFO.sizeof; | |
325 PROCESS_INFORMATION lpProcessInformation; | |
326 bool success = cast(bool) OS.CreateProcess (null, lpCommandLine, null, null, false, 0, null, null, &lpStartupInfo, &lpProcessInformation); | |
327 if (lpCommandLine !is null) OS.HeapFree (hHeap, 0, lpCommandLine); | |
328 if (lpProcessInformation.hProcess !is null) OS.CloseHandle (lpProcessInformation.hProcess); | |
329 if (lpProcessInformation.hThread !is null) OS.CloseHandle (lpProcessInformation.hThread); | |
330 return success; | |
331 } | |
332 | |
333 /** | |
334 * Returns the receiver's image data. This is the icon | |
335 * that is associated with the receiver in the operating | |
336 * system. | |
337 * | |
338 * @return the image data for the program, may be null | |
339 */ | |
340 public ImageData getImageData () { | |
341 if (extension !is null) { | |
342 SHFILEINFOW shfi; | |
343 int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON | OS.SHGFI_USEFILEATTRIBUTES; | |
344 TCHAR[] pszPath = StrToTCHARs (0, extension, true); | |
345 OS.SHGetFileInfo (pszPath.ptr, OS.FILE_ATTRIBUTE_NORMAL, &shfi, SHFILEINFO.sizeof, flags); | |
346 if (shfi.hIcon !is null) { | |
347 Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon); | |
348 ImageData imageData = image.getImageData (); | |
349 image.dispose (); | |
350 return imageData; | |
351 } | |
352 } | |
353 int nIconIndex = 0; | |
354 String fileName = iconName; | |
355 int index = iconName.indexOf (','); | |
356 if (index !is -1) { | |
357 fileName = iconName.substring (0, index); | |
358 String iconIndex = iconName.substring (index + 1, iconName.length ).trim (); | |
359 try { | |
360 nIconIndex = Integer.parseInt (iconIndex); | |
361 } catch (NumberFormatException e) {} | |
362 } | |
363 int length = fileName.length; | |
364 if (length !is 0 && fileName.charAt (0) is '\"') { | |
365 if (fileName.charAt (length - 1) is '\"') { | |
366 fileName = fileName.substring (1, length - 1); | |
367 } | |
368 } | |
369 /* Use the character encoding for the default locale */ | |
370 TCHAR[] lpszFile = StrToTCHARs (0, fileName, true); | |
371 HICON [1] phiconSmall, phiconLarge; | |
372 OS.ExtractIconEx (lpszFile.ptr, nIconIndex, phiconLarge.ptr, phiconSmall.ptr, 1); | |
373 if (phiconSmall [0] is null) return null; | |
374 Image image = Image.win32_new (null, SWT.ICON, phiconSmall [0]); | |
375 ImageData imageData = image.getImageData (); | |
376 image.dispose (); | |
377 return imageData; | |
378 } | |
379 | |
380 /** | |
381 * Returns the receiver's name. This is as short and | |
382 * descriptive a name as possible for the program. If | |
383 * the program has no descriptive name, this string may | |
384 * be the executable name, path or empty. | |
385 * | |
386 * @return the name of the program | |
387 */ | |
388 public String getName () { | |
389 return name; | |
390 } | |
391 | |
392 /** | |
393 * Compares the argument to the receiver, and returns true | |
394 * if they represent the <em>same</em> object using a class | |
395 * specific comparison. | |
396 * | |
397 * @param other the object to compare with this object | |
398 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise | |
399 * | |
400 * @see #hashCode() | |
401 */ | |
402 public override int opEquals(Object other) { | |
403 if (this is other) return true; | |
404 if ( auto program = cast(Program)other ) { | |
405 return name.equals(program.name) && command.equals(program.command) | |
406 && iconName.equals(program.iconName); | |
407 } | |
408 return false; | |
409 } | |
410 | |
411 /** | |
412 * Returns an integer hash code for the receiver. Any two | |
413 * objects that return <code>true</code> when passed to | |
414 * <code>equals</code> must return the same value for this | |
415 * method. | |
416 * | |
417 * @return the receiver's hash | |
418 * | |
419 * @see #equals(Object) | |
420 */ | |
421 public override hash_t toHash() { | |
422 return .toHash(name) ^ .toHash(command) ^ .toHash(iconName); | |
423 } | |
424 | |
425 /** | |
426 * Returns a string containing a concise, human-readable | |
427 * description of the receiver. | |
428 * | |
429 * @return a string representation of the program | |
430 */ | |
431 public String toString () { | |
432 return "Program {" ~ name ~ "}"; //$NON-NLS-1$ //$NON-NLS-2$ | |
433 } | |
434 | |
435 } |