001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.program;
011:
012: import org.eclipse.swt.internal.*;
013: import org.eclipse.swt.internal.win32.*;
014: import org.eclipse.swt.*;
015: import org.eclipse.swt.graphics.*;
016:
017: import java.io.IOException;
018:
019: /**
020: * Instances of this class represent programs and
021: * their associated file extensions in the operating
022: * system.
023: */
024: public final class Program {
025: String name;
026: String command;
027: String iconName;
028:
029: /**
030: * Prevents uninitialized instances from being created outside the package.
031: */
032: Program() {
033: }
034:
035: /**
036: * Finds the program that is associated with an extension.
037: * The extension may or may not begin with a '.'. Note that
038: * a <code>Display</code> must already exist to guarantee that
039: * this method returns an appropriate result.
040: *
041: * @param extension the program extension
042: * @return the program or <code>null</code>
043: *
044: * @exception IllegalArgumentException <ul>
045: * <li>ERROR_NULL_ARGUMENT when extension is null</li>
046: * </ul>
047: */
048: public static Program findProgram(String extension) {
049: if (extension == null)
050: SWT.error(SWT.ERROR_NULL_ARGUMENT);
051: if (extension.length() == 0)
052: return null;
053: if (extension.charAt(0) != '.')
054: extension = "." + extension; //$NON-NLS-1$
055: /* Use the character encoding for the default locale */
056: TCHAR key = new TCHAR(0, extension, true);
057: int[] phkResult = new int[1];
058: if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ,
059: phkResult) != 0) {
060: return null;
061: }
062: Program program = null;
063: int[] lpcbData = new int[1];
064: int result = OS.RegQueryValueEx(phkResult[0], null, 0, null,
065: (TCHAR) null, lpcbData);
066: if (result == 0) {
067: TCHAR lpData = new TCHAR(0, lpcbData[0] / TCHAR.sizeof);
068: result = OS.RegQueryValueEx(phkResult[0], null, 0, null,
069: lpData, lpcbData);
070: if (result == 0)
071: program = getProgram(lpData
072: .toString(0, lpData.strlen()));
073: }
074: OS.RegCloseKey(phkResult[0]);
075: return program;
076: }
077:
078: /**
079: * Answer all program extensions in the operating system. Note
080: * that a <code>Display</code> must already exist to guarantee
081: * that this method returns an appropriate result.
082: *
083: * @return an array of extensions
084: */
085: public static String[] getExtensions() {
086: String[] extensions = new String[1024];
087: /* Use the character encoding for the default locale */
088: TCHAR lpName = new TCHAR(0, 1024);
089: int[] lpcName = new int[] { lpName.length() };
090: FILETIME ft = new FILETIME();
091: int dwIndex = 0, count = 0;
092: while (OS.RegEnumKeyEx(OS.HKEY_CLASSES_ROOT, dwIndex, lpName,
093: lpcName, null, null, null, ft) != OS.ERROR_NO_MORE_ITEMS) {
094: String extension = lpName.toString(0, lpcName[0]);
095: lpcName[0] = lpName.length();
096: if (extension.length() > 0 && extension.charAt(0) == '.') {
097: if (count == extensions.length) {
098: String[] newExtensions = new String[extensions.length + 1024];
099: System.arraycopy(extensions, 0, newExtensions, 0,
100: extensions.length);
101: extensions = newExtensions;
102: }
103: extensions[count++] = extension;
104: }
105: dwIndex++;
106: }
107: if (count != extensions.length) {
108: String[] newExtension = new String[count];
109: System.arraycopy(extensions, 0, newExtension, 0, count);
110: extensions = newExtension;
111: }
112: return extensions;
113: }
114:
115: static String getKeyValue(String string, boolean expand) {
116: /* Use the character encoding for the default locale */
117: TCHAR key = new TCHAR(0, string, true);
118: int[] phkResult = new int[1];
119: if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ,
120: phkResult) != 0) {
121: return null;
122: }
123: String result = null;
124: int[] lpcbData = new int[1];
125: if (OS.RegQueryValueEx(phkResult[0], (TCHAR) null, 0, null,
126: (TCHAR) null, lpcbData) == 0) {
127: result = "";
128: int length = lpcbData[0] / TCHAR.sizeof;
129: if (length != 0) {
130: /* Use the character encoding for the default locale */
131: TCHAR lpData = new TCHAR(0, length);
132: if (OS.RegQueryValueEx(phkResult[0], null, 0, null,
133: lpData, lpcbData) == 0) {
134: if (!OS.IsWinCE && expand) {
135: length = OS.ExpandEnvironmentStrings(lpData,
136: null, 0);
137: if (length != 0) {
138: TCHAR lpDst = new TCHAR(0, length);
139: OS.ExpandEnvironmentStrings(lpData, lpDst,
140: length);
141: result = lpDst.toString(0, Math.max(0,
142: length - 1));
143: }
144: } else {
145: length = Math.max(0, lpData.length() - 1);
146: result = lpData.toString(0, length);
147: }
148: }
149: }
150: }
151: if (phkResult[0] != 0)
152: OS.RegCloseKey(phkResult[0]);
153: return result;
154: }
155:
156: static Program getProgram(String key) {
157:
158: /* Name */
159: String name = getKeyValue(key, false);
160: if (name == null || name.length() == 0) {
161: name = key;
162: }
163:
164: /* Command */
165: String DEFAULT_COMMAND = "\\shell"; //$NON-NLS-1$
166: String defaultCommand = getKeyValue(key + DEFAULT_COMMAND, true);
167: if (defaultCommand == null || defaultCommand.length() == 0)
168: defaultCommand = "open"; //$NON-NLS-1$
169: String COMMAND = "\\shell\\" + defaultCommand + "\\command"; //$NON-NLS-1$
170: String command = getKeyValue(key + COMMAND, true);
171: if (command == null || command.length() == 0)
172: return null;
173:
174: /* Icon */
175: String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$
176: String iconName = getKeyValue(key + DEFAULT_ICON, true);
177: if (iconName == null)
178: iconName = ""; //$NON-NLS-1$
179:
180: Program program = new Program();
181: program.name = name;
182: program.command = command;
183: program.iconName = iconName;
184: return program;
185: }
186:
187: /**
188: * Answers all available programs in the operating system. Note
189: * that a <code>Display</code> must already exist to guarantee
190: * that this method returns an appropriate result.
191: *
192: * @return an array of programs
193: */
194: public static Program[] getPrograms() {
195: Program[] programs = new Program[1024];
196: /* Use the character encoding for the default locale */
197: TCHAR lpName = new TCHAR(0, 1024);
198: int[] lpcName = new int[] { lpName.length() };
199: FILETIME ft = new FILETIME();
200: int dwIndex = 0, count = 0;
201: while (OS.RegEnumKeyEx(OS.HKEY_CLASSES_ROOT, dwIndex, lpName,
202: lpcName, null, null, null, ft) != OS.ERROR_NO_MORE_ITEMS) {
203: String path = lpName.toString(0, lpcName[0]);
204: lpcName[0] = lpName.length();
205: Program program = getProgram(path);
206: if (program != null) {
207: if (count == programs.length) {
208: Program[] newPrograms = new Program[programs.length + 1024];
209: System.arraycopy(programs, 0, newPrograms, 0,
210: programs.length);
211: programs = newPrograms;
212: }
213: programs[count++] = program;
214: }
215: dwIndex++;
216: }
217: if (count != programs.length) {
218: Program[] newPrograms = new Program[count];
219: System.arraycopy(programs, 0, newPrograms, 0, count);
220: programs = newPrograms;
221: }
222: return programs;
223: }
224:
225: /**
226: * Launches the executable associated with the file in
227: * the operating system. If the file is an executable,
228: * then the executable is launched. Note that a <code>Display</code>
229: * must already exist to guarantee that this method returns
230: * an appropriate result.
231: *
232: * @param fileName the file or program name
233: * @return <code>true</code> if the file is launched, otherwise <code>false</code>
234: *
235: * @exception IllegalArgumentException <ul>
236: * <li>ERROR_NULL_ARGUMENT when fileName is null</li>
237: * </ul>
238: */
239: public static boolean launch(String fileName) {
240: if (fileName == null)
241: SWT.error(SWT.ERROR_NULL_ARGUMENT);
242:
243: /* Use the character encoding for the default locale */
244: int hHeap = OS.GetProcessHeap();
245: TCHAR buffer = new TCHAR(0, fileName, true);
246: int byteCount = buffer.length() * TCHAR.sizeof;
247: int lpFile = OS
248: .HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
249: OS.MoveMemory(lpFile, buffer, byteCount);
250: SHELLEXECUTEINFO info = new SHELLEXECUTEINFO();
251: info.cbSize = SHELLEXECUTEINFO.sizeof;
252: info.lpFile = lpFile;
253: info.nShow = OS.SW_SHOW;
254: boolean result = OS.ShellExecuteEx(info);
255: if (lpFile != 0)
256: OS.HeapFree(hHeap, 0, lpFile);
257: return result;
258: }
259:
260: /**
261: * Executes the program with the file as the single argument
262: * in the operating system. It is the responsibility of the
263: * programmer to ensure that the file contains valid data for
264: * this program.
265: *
266: * @param fileName the file or program name
267: * @return <code>true</code> if the file is launched, otherwise <code>false</code>
268: *
269: * @exception IllegalArgumentException <ul>
270: * <li>ERROR_NULL_ARGUMENT when fileName is null</li>
271: * </ul>
272: */
273: public boolean execute(String fileName) {
274: if (fileName == null)
275: SWT.error(SWT.ERROR_NULL_ARGUMENT);
276: boolean quote = true;
277: String prefix = command, suffix = ""; //$NON-NLS-1$
278: int index = command.indexOf("%1"); //$NON-NLS-1$
279: if (index != -1) {
280: int count = 0;
281: int i = index + 2, length = command.length();
282: while (i < length) {
283: if (command.charAt(i) == '"')
284: count++;
285: i++;
286: }
287: quote = count % 2 == 0;
288: prefix = command.substring(0, index);
289: suffix = command.substring(index + 2, length);
290: }
291: if (quote)
292: fileName = " \"" + fileName + "\""; //$NON-NLS-1$ //$NON-NLS-2$
293: try {
294: Compatibility.exec(prefix + fileName + suffix);
295: } catch (IOException e) {
296: return false;
297: }
298: return true;
299: }
300:
301: /**
302: * Returns the receiver's image data. This is the icon
303: * that is associated with the receiver in the operating
304: * system.
305: *
306: * @return the image data for the program, may be null
307: */
308: public ImageData getImageData() {
309: int nIconIndex = 0;
310: String fileName = iconName;
311: int index = iconName.indexOf(',');
312: if (index != -1) {
313: fileName = iconName.substring(0, index);
314: String iconIndex = iconName.substring(index + 1,
315: iconName.length()).trim();
316: try {
317: nIconIndex = Integer.parseInt(iconIndex);
318: } catch (NumberFormatException e) {
319: }
320: }
321: /* Use the character encoding for the default locale */
322: TCHAR lpszFile = new TCHAR(0, fileName, true);
323: int[] phiconSmall = new int[1], phiconLarge = null;
324: OS.ExtractIconEx(lpszFile, nIconIndex, phiconLarge,
325: phiconSmall, 1);
326: if (phiconSmall[0] == 0)
327: return null;
328: Image image = Image.win32_new(null, SWT.ICON, phiconSmall[0]);
329: ImageData imageData = image.getImageData();
330: image.dispose();
331: return imageData;
332: }
333:
334: /**
335: * Returns the receiver's name. This is as short and
336: * descriptive a name as possible for the program. If
337: * the program has no descriptive name, this string may
338: * be the executable name, path or empty.
339: *
340: * @return the name of the program
341: */
342: public String getName() {
343: return name;
344: }
345:
346: /**
347: * Compares the argument to the receiver, and returns true
348: * if they represent the <em>same</em> object using a class
349: * specific comparison.
350: *
351: * @param other the object to compare with this object
352: * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
353: *
354: * @see #hashCode()
355: */
356: public boolean equals(Object other) {
357: if (this == other)
358: return true;
359: if (other instanceof Program) {
360: final Program program = (Program) other;
361: return name.equals(program.name)
362: && command.equals(program.command)
363: && iconName.equals(program.iconName);
364: }
365: return false;
366: }
367:
368: /**
369: * Returns an integer hash code for the receiver. Any two
370: * objects that return <code>true</code> when passed to
371: * <code>equals</code> must return the same value for this
372: * method.
373: *
374: * @return the receiver's hash
375: *
376: * @see #equals(Object)
377: */
378: public int hashCode() {
379: return name.hashCode() ^ command.hashCode()
380: ^ iconName.hashCode();
381: }
382:
383: /**
384: * Returns a string containing a concise, human-readable
385: * description of the receiver.
386: *
387: * @return a string representation of the program
388: */
389: public String toString() {
390: return "Program {" + name + "}"; //$NON-NLS-1$ //$NON-NLS-2$
391: }
392:
393: }
|