blob: 29ec0bdd779a59bd5987c696f4d8454980880b38 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.program;
import org.eclipse.swt.internal.carbon.CFRange;
import org.eclipse.swt.internal.carbon.LSApplicationParameters;
import org.eclipse.swt.internal.carbon.OS;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* Instances of this class represent programs and
* their associated file extensions in the operating
* system.
*/
public final class Program {
String name;
byte[] fsRef;
/**
* Prevents uninitialized instances from being created outside the package.
*/
Program () {
}
/**
* Finds the program that is associated with an extension.
* The extension may or may not begin with a '.'. Note that
* a <code>Display</code> must already exist to guarantee that
* this method returns an appropriate result.
*
* @param extension the program extension
* @return the program or <code>null</code>
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT when extension is null</li>
* </ul>
*/
public static Program findProgram (String extension) {
if (extension == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
if (extension.length () == 0) return null;
char[] chars;
if (extension.charAt (0) != '.') {
chars = new char[extension.length()];
extension.getChars(0, chars.length, chars, 0);
} else {
chars = new char[extension.length() - 1];
extension.getChars(1, extension.length(), chars, 0);
}
int ext = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, chars, chars.length);
Program program = null;
if (ext != 0) {
byte[] fsRef = new byte[80];
if (OS.LSGetApplicationForInfo(OS.kLSUnknownType, OS.kLSUnknownCreator, ext, OS.kLSRolesAll, fsRef, null) == OS.noErr) {
program = getProgram(fsRef);
}
OS.CFRelease(ext);
}
return program;
}
/**
* Answer all program extensions in the operating system. Note
* that a <code>Display</code> must already exist to guarantee
* that this method returns an appropriate result.
*
* @return an array of extensions
*/
public static String [] getExtensions () {
return new String [] {
// From System-Declared Uniform Type Identifiers
".txt",
".rtf",
".html",
".htm",
".xml",
".c",
".m",
".cp", ".cpp", ".c++", ".cc", ".cxx",
".mm",
".h",
".hpp",
".h++",
".hxx",
".java",
".jav",
".s",
".r",
".defs",
".mig",
".exp",
".js",
".jscript",
".javascript",
".sh",
".command",
".csh",
".pl",
".pm",
".py",
".rb",
".rbw",
".php",
".php3",
".php4",
".ph3",
".ph4",
".phtml",
".jnlp",
".applescript",
".scpt",
".o",
".exe",
".dll",
".class",
".jar",
".qtz",
".gtar",
".tar",
".gz",
".gzip",
".tgz",
".hqx",
".bin",
".vcf",
".vcard",
".jpg",
".jpeg",
".jp2",
".tif",
".tiff",
".pic",
".pct",
".pict",
".pntg",
".png",
".xbm",
".qif",
".qtif",
".icns",
".mov",
".qt",
".avi",
".vfw",
".mpg",
".mpeg",
".m75",
".m15",
".mp4",
".3gp",
".3gpp",
".3g2",
".3gp2",
".mp3",
".m4a",
".m4p",
".m4b",
".au",
".ulw",
".snd",
".aifc",
".aiff",
".aif",
".caf",
".bundle",
".app",
".plugin",
".mdimporter",
".wdgt",
".cpio",
".zip",
".framework",
".rtfd",
".dfont",
".otf",
".ttf",
".ttc",
".suit",
".pfb",
".pfa",
".icc",
".icm",
".pf",
".pdf",
".ps",
".eps",
".psd",
".ai",
".gif",
".bmp",
".ico",
".doc",
".xls",
".ppt",
".wav",
".wave",
".asf",
".wm",
".wmv",
".wmp",
".wma",
".asx",
".wmx",
".wvx",
".wax",
".key",
".kth",
".tga",
".sgi",
".exr",
".fpx",
".jfx",
".efx",
".sd2",
".rm",
".ram",
".ra",
".smil",
".sit",
".sitx",
// Others
".plist",
".nib",
".lproj",
// iChat
".iPhoto",
// iChat
".iChat",
".chat",
// acrobat reader
".rmf",
".xfdf",
".fdf",
// Chess
".game",
".pgn",
// iCal
".ics",
".vcs",
".aplmodel",
".icbu",
".icalevent",
".icaltodo",
// Mail
".mailhold",
".mbox",
".imapmbox",
".emlx",
".mailextract",
// Sherlock
".sherlock",
// Stickies
".tpl",
// System Preferences
".prefPane",
".sliderSaver",
".saver",
// Console
".log",
// Grapher
".gcx",
};
}
/**
* Answers all available programs in the operating system. Note
* that a <code>Display</code> must already exist to guarantee
* that this method returns an appropriate result.
*
* @return an array of programs
*/
public static Program [] getPrograms () {
Hashtable bundles = new Hashtable();
String[] extensions = getExtensions();
byte[] fsRef = new byte[80];
for (int i = 0; i < extensions.length; i++) {
String extension = extensions[i];
char[] chars = new char[extension.length() - 1];
extension.getChars(1, extension.length(), chars, 0);
int ext = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, chars, chars.length);
if (ext != 0) {
if (OS.LSGetApplicationForInfo(OS.kLSUnknownType, OS.kLSUnknownCreator, ext, OS.kLSRolesAll, fsRef, null) == OS.noErr) {
Program program = getProgram(fsRef);
if (program != null && bundles.get(program.getName()) == null) {
bundles.put(program.getName(), program);
fsRef = new byte[80];
}
}
if (OS.VERSION >= 0x1040) {
int utis = OS.UTTypeCreateAllIdentifiersForTag(OS.kUTTagClassFilenameExtension(), ext, 0);
if (utis != 0) {
int utiCount = OS.CFArrayGetCount(utis);
for (int j = 0; j < utiCount; j++) {
int uti = OS.CFArrayGetValueAtIndex(utis, j);
if (uti != 0) {
int apps = OS.LSCopyAllRoleHandlersForContentType(uti, OS.kLSRolesAll);
if (apps != 0) {
int appCount = OS.CFArrayGetCount(apps);
for (int k = 0; k < appCount; k++) {
int app = OS.CFArrayGetValueAtIndex(apps, k);
if (app != 0) {;
if (OS.LSFindApplicationForInfo(OS.kLSUnknownCreator, app, 0, fsRef, null) == OS.noErr) {
Program program = getProgram(fsRef);
if (program != null && bundles.get(program.getName()) == null) {
bundles.put(program.getName(), program);
fsRef = new byte[80];
}
}
}
}
OS.CFRelease(apps);
}
}
}
OS.CFRelease(utis);
}
}
OS.CFRelease(ext);
}
}
int count = 0;
Program[] programs = new Program[bundles.size()];
Enumeration values = bundles.elements();
while (values.hasMoreElements()) {
programs[count++] = (Program)values.nextElement();
}
return programs;
}
/**
* Launches the executable associated with the file in
* the operating system. If the file is an executable,
* then the executable is launched. Note that a <code>Display</code>
* must already exist to guarantee that this method returns
* an appropriate result.
*
* @param fileName the file or program name
* @return <code>true</code> if the file is launched, otherwise <code>false</code>
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT when fileName is null</li>
* </ul>
*/
public static boolean launch (String fileName) {
if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
int rc = -1;
if (fileName.indexOf(':') == -1) fileName = "file://" + fileName;
char[] chars = new char[fileName.length()];
fileName.getChars(0, chars.length, chars, 0);
int str = OS.CFStringCreateWithCharacters(0, chars, chars.length);
if (str != 0) {
int escapedStr = OS.CFURLCreateStringByAddingPercentEscapes(OS.kCFAllocatorDefault, str, 0, 0, OS.kCFStringEncodingUTF8);
if (escapedStr != 0) {
int url = OS.CFURLCreateWithString(OS.kCFAllocatorDefault, escapedStr, 0);
if (url != 0) {
rc = OS.LSOpenCFURLRef(url, null);
OS.CFRelease(url);
}
OS.CFRelease(escapedStr);
}
OS.CFRelease(str);
}
return rc == OS.noErr;
}
/**
* Executes the program with the file as the single argument
* in the operating system. It is the responsibility of the
* programmer to ensure that the file contains valid data for
* this program.
*
* @param fileName the file or program name
* @return <code>true</code> if the file is launched, otherwise <code>false</code>
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT when fileName is null</li>
* </ul>
*/
public boolean execute (String fileName) {
if (fileName == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (OS.VERSION < 0x1040) return launch(fileName);
int rc = -1;
int fsRefPtr = OS.NewPtr(fsRef.length);
if (fsRefPtr != 0) {
OS.memcpy(fsRefPtr, fsRef, fsRef.length);
LSApplicationParameters params = new LSApplicationParameters();
params.version = 0;
params.flags = 0;
params.application = fsRefPtr;
if (fileName.length() == 0) {
rc = OS.LSOpenApplication(params, null);
} else {
if (fileName.indexOf(':') == -1) fileName = "file://" + fileName;
char[] chars = new char[fileName.length()];
fileName.getChars(0, chars.length, chars, 0);
int str = OS.CFStringCreateWithCharacters(0, chars, chars.length);
if (str != 0) {
int escapedStr = OS.CFURLCreateStringByAddingPercentEscapes(OS.kCFAllocatorDefault, str, 0, 0, OS.kCFStringEncodingUTF8);
if (escapedStr != 0) {
int urls = OS.CFArrayCreateMutable(OS.kCFAllocatorDefault, 1, 0);
if (urls != 0) {
int url = OS.CFURLCreateWithString(OS.kCFAllocatorDefault, escapedStr, 0);
if (url != 0) {
OS.CFArrayAppendValue(urls, url);
rc = OS.LSOpenURLsWithRole(urls, OS.kLSRolesAll, 0, params, null, 0);
}
OS.CFRelease(urls);
}
OS.CFRelease(escapedStr);
}
OS.CFRelease(str);
}
}
OS.DisposePtr(fsRefPtr);
}
return rc == OS.noErr;
}
ImageData createImageFromFamily (int family, int type, int maskType, int width, int height) {
int dataHandle = OS.NewHandle (0);
int result = OS.GetIconFamilyData (family, type, dataHandle);
if (result != OS.noErr) {
OS.DisposeHandle (dataHandle);
return null;
}
int maskHandle = OS.NewHandle (0);
result = OS.GetIconFamilyData (family, maskType, maskHandle);
if (result != OS.noErr) {
OS.DisposeHandle (maskHandle);
OS.DisposeHandle (dataHandle);
return null;
}
int dataSize = OS.GetHandleSize (dataHandle);
OS.HLock (dataHandle);
OS.HLock (maskHandle);
int[] iconPtr = new int [1];
int[] maskPtr = new int [1];
OS.memcpy (iconPtr, dataHandle, 4);
OS.memcpy (maskPtr, maskHandle, 4);
byte[] data = new byte[dataSize];
OS.memcpy (data, iconPtr [0], dataSize);
byte[] alphaData = new byte[width * height];
OS.memcpy(alphaData, maskPtr[0], alphaData.length);
OS.HUnlock (maskHandle);
OS.HUnlock (dataHandle);
OS.DisposeHandle (maskHandle);
OS.DisposeHandle (dataHandle);
ImageData image = new ImageData(width, height, 32, new PaletteData(0xFF0000, 0xFF00, 0xFF), 4, data);
image.alphaData = alphaData;
return image;
}
/**
* Returns the receiver's image data. This is the icon
* that is associated with the receiver in the operating
* system.
*
* @return the image data for the program, may be null
*/
public ImageData getImageData () {
int[] iconRef = new int[1];
OS.GetIconRefFromFileInfo(fsRef, 0, null, 0, 0, 0, iconRef, null);
int[] family = new int[1];
int rc = OS.IconRefToIconFamily(iconRef[0], OS.kSelectorAlLAvailableData, family);
OS.ReleaseIconRef(iconRef[0]);
if (rc != OS.noErr) return null;
// ImageData result = createImageFromFamily(family[0], OS.kLarge32BitData, OS.kLarge8BitMask, 32, 32);
ImageData result = createImageFromFamily(family[0], OS.kSmall32BitData, OS.kSmall8BitMask, 16, 16);
OS.DisposeHandle(family[0]);
if (result == null) {
RGB[] rgbs = new RGB[] {
new RGB(0xff, 0xff, 0xff),
new RGB(0x5f, 0x5f, 0x5f),
new RGB(0x80, 0x80, 0x80),
new RGB(0xC0, 0xC0, 0xC0),
new RGB(0xDF, 0xDF, 0xBF),
new RGB(0xFF, 0xDF, 0x9F),
new RGB(0x00, 0x00, 0x00),
};
result = new ImageData(16, 16, 4, new PaletteData(rgbs) );
result.transparentPixel = 6; // use black for transparency
String[] p= {
"CCCCCCCCGGG",
"CFAAAAACBGG",
"CAAAAAACFBG",
"CAAAAAACBBB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CAAAAAAAAEB",
"CDDDDDDDDDB",
"CBBBBBBBBBB",
};
for (int y= 0; y < p.length; y++) {
for (int x= 0; x < 11; x++) {
result.setPixel(x+3, y+1, p[y].charAt(x)-'A');
}
}
}
return result;
}
/**
* Returns the receiver's name. This is as short and
* descriptive a name as possible for the program. If
* the program has no descriptive name, this string may
* be the executable name, path or empty.
*
* @return the name of the program
*/
public String getName () {
return name;
}
static Program getProgram(byte[] fsRef) {
String name = "";
int[] namePtr = new int[1];
OS.LSCopyDisplayNameForRef(fsRef, namePtr);
if (namePtr[0] != 0) {
int length = OS.CFStringGetLength(namePtr[0]);
if (length != 0) {
char[] buffer= new char[length];
CFRange range = new CFRange();
range.length = length;
OS.CFStringGetCharacters(namePtr[0], range, buffer);
name = new String(buffer);
}
OS.CFRelease(namePtr[0]);
}
Program program = new Program();
program.fsRef = fsRef;
program.name = name;
return program;
}
/**
* Compares the argument to the receiver, and returns true
* if they represent the <em>same</em> object using a class
* specific comparison.
*
* @param other the object to compare with this object
* @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
*
* @see #hashCode()
*/
public boolean equals(Object other) {
if (this == other) return true;
if (other instanceof Program) {
final Program program = (Program) other;
return name.equals(program.name);
}
return false;
}
/**
* Returns an integer hash code for the receiver. Any two
* objects that return <code>true</code> when passed to
* <code>equals</code> must return the same value for this
* method.
*
* @return the receiver's hash
*
* @see #equals(Object)
*/
public int hashCode() {
return name.hashCode();
}
/**
* Returns a string containing a concise, human-readable
* description of the receiver.
*
* @return a string representation of the program
*/
public String toString () {
return "Program {" + name + "}";
}
}