1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-14 11:29:26 +01:00

changed the version number in the code to 3

This commit is contained in:
David Cuartielles 2006-01-03 14:33:49 +00:00
parent 601dafd7b6
commit e19bbdd548

View File

@ -1,1113 +1,1113 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* /*
Part of the Arduino project - http://arduino.berlios.de Part of the Arduino project - http://arduino.berlios.de
Based on processing http://www.processing.org Based on processing http://www.processing.org
Copyright (c) 2004-05 Ben Fry and Casey Reas Copyright (c) 2004-05 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
package processing.app; package processing.app;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.io.*; import java.io.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.*; import javax.swing.event.*;
import javax.swing.text.*; import javax.swing.text.*;
import javax.swing.undo.*; import javax.swing.undo.*;
import com.apple.mrj.*; import com.apple.mrj.*;
import com.ice.jni.registry.*; import com.ice.jni.registry.*;
/** /**
* The base class for the main Arduino application. * The base class for the main Arduino application.
* <P> * <P>
* Primary role of this class is for platform identification and * Primary role of this class is for platform identification and
* general interaction with the system (launching URLs, loading * general interaction with the system (launching URLs, loading
* files and images, etc) that comes from that. * files and images, etc) that comes from that.
*/ */
public class Base { public class Base {
static final int VERSION = 1; static final int VERSION = 3;
static final String VERSION_NAME = "0003 Alpha"; static final String VERSION_NAME = "0003 Alpha";
static public int platform; static public int platform;
// platform IDs for platform // platform IDs for platform
static final int WINDOWS = 1; static final int WINDOWS = 1;
static final int MACOS9 = 2; static final int MACOS9 = 2;
static final int MACOSX = 3; static final int MACOSX = 3;
static final int LINUX = 4; static final int LINUX = 4;
static final int OTHER = 0; static final int OTHER = 0;
// moved from PApplet // moved from PApplet
// in preperation of detaching the IDE from the // in preperation of detaching the IDE from the
// Arduino core classes // Arduino core classes
/** /**
* Current platform in use. * Current platform in use.
* <P> * <P>
* Equivalent to System.getProperty("os.name"), just used internally. * Equivalent to System.getProperty("os.name"), just used internally.
*/ */
static public String platformName = System.getProperty("os.name"); static public String platformName = System.getProperty("os.name");
static { static {
// figure out which operating system // figure out which operating system
// this has to be first, since editor needs to know // this has to be first, since editor needs to know
if (platformName.toLowerCase().indexOf("mac") != -1) { if (platformName.toLowerCase().indexOf("mac") != -1) {
// can only check this property if running on a mac // can only check this property if running on a mac
// on a pc it throws a security exception and kills the applet // on a pc it throws a security exception and kills the applet
// (but on the mac it does just fine) // (but on the mac it does just fine)
if (System.getProperty("mrj.version") != null) { // running on a mac if (System.getProperty("mrj.version") != null) { // running on a mac
platform = (platformName.equals("Mac OS X")) ? platform = (platformName.equals("Mac OS X")) ?
MACOSX : MACOS9; MACOSX : MACOS9;
} }
} else { } else {
String osname = System.getProperty("os.name"); String osname = System.getProperty("os.name");
if (osname.indexOf("Windows") != -1) { if (osname.indexOf("Windows") != -1) {
platform = WINDOWS; platform = WINDOWS;
} else if (osname.equals("Linux")) { // true for the ibm vm } else if (osname.equals("Linux")) { // true for the ibm vm
platform = LINUX; platform = LINUX;
} else { } else {
platform = OTHER; platform = OTHER;
} }
} }
} }
// used by split, all the standard whitespace chars // used by split, all the standard whitespace chars
// (uncludes unicode nbsp, that little bostage) // (uncludes unicode nbsp, that little bostage)
static final String WHITESPACE = " \t\n\r\f\u00A0"; static final String WHITESPACE = " \t\n\r\f\u00A0";
/** /**
* Path of filename opened on the command line, * Path of filename opened on the command line,
* or via the MRJ open document handler. * or via the MRJ open document handler.
*/ */
static String openedAtStartup; static String openedAtStartup;
Editor editor; Editor editor;
static public void main(String args[]) { static public void main(String args[]) {
// make sure that this is running on java 1.4 // make sure that this is running on java 1.4
//if (PApplet.javaVersion < 1.4f) { //if (PApplet.javaVersion < 1.4f) {
//System.err.println("no way man"); //System.err.println("no way man");
// Base.showError("Need to install Java 1.4", // Base.showError("Need to install Java 1.4",
// "This version of Arduino requires \n" + // "This version of Arduino requires \n" +
// "Java 1.4 or later to run properly.\n" + // "Java 1.4 or later to run properly.\n" +
// "Please visit java.com to upgrade.", null); // "Please visit java.com to upgrade.", null);
// } // }
// grab any opened file from the command line // grab any opened file from the command line
if (args.length == 1) { if (args.length == 1) {
Base.openedAtStartup = args[0]; Base.openedAtStartup = args[0];
} }
// register a temporary/early version of the mrj open document handler, // register a temporary/early version of the mrj open document handler,
// because the event may be lost (sometimes, not always) by the time // because the event may be lost (sometimes, not always) by the time
// that Editor is properly constructed. // that Editor is properly constructed.
MRJOpenDocumentHandler startupOpen = new MRJOpenDocumentHandler() { MRJOpenDocumentHandler startupOpen = new MRJOpenDocumentHandler() {
public void handleOpenFile(File file) { public void handleOpenFile(File file) {
// this will only get set once.. later will be handled // this will only get set once.. later will be handled
// by the Editor version of this fella // by the Editor version of this fella
if (Base.openedAtStartup == null) { if (Base.openedAtStartup == null) {
//System.out.println("handling outside open file: " + file); //System.out.println("handling outside open file: " + file);
Base.openedAtStartup = file.getAbsolutePath(); Base.openedAtStartup = file.getAbsolutePath();
} }
} }
}; };
MRJApplicationUtils.registerOpenDocumentHandler(startupOpen); MRJApplicationUtils.registerOpenDocumentHandler(startupOpen);
Base app = new Base(); Base app = new Base();
} }
public Base() { public Base() {
// set the look and feel before opening the window // set the look and feel before opening the window
try { try {
if (Base.isLinux()) { if (Base.isLinux()) {
// linux is by default (motif?) even uglier than metal // linux is by default (motif?) even uglier than metal
// actually, i'm using native menus, so they're ugly and // actually, i'm using native menus, so they're ugly and
// motif-looking. ick. need to fix this. // motif-looking. ick. need to fix this.
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} else { } else {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
// build the editor object // build the editor object
editor = new Editor(); editor = new Editor();
// get things rawkin // get things rawkin
editor.pack(); editor.pack();
// has to be here to set window size properly // has to be here to set window size properly
editor.restorePreferences(); editor.restorePreferences();
// show the window // show the window
editor.show(); editor.show();
// check for updates // check for updates
if (Preferences.getBoolean("update.check")) { if (Preferences.getBoolean("update.check")) {
new UpdateCheck(editor); new UpdateCheck(editor);
} }
} }
// ................................................................. // .................................................................
/** /**
* returns true if the Arduino is running on a Mac OS machine, * returns true if the Arduino is running on a Mac OS machine,
* specifically a Mac OS X machine because it doesn't un on OS 9 anymore. * specifically a Mac OS X machine because it doesn't un on OS 9 anymore.
*/ */
static public boolean isMacOS() { static public boolean isMacOS() {
return platform == MACOSX; return platform == MACOSX;
} }
/** /**
* returns true if running on windows. * returns true if running on windows.
*/ */
static public boolean isWindows() { static public boolean isWindows() {
return platform == WINDOWS; return platform == WINDOWS;
} }
/** /**
* true if running on linux. * true if running on linux.
*/ */
static public boolean isLinux() { static public boolean isLinux() {
return platform == LINUX; return platform == LINUX;
} }
// ................................................................. // .................................................................
static final int kDocumentsFolderType = static final int kDocumentsFolderType =
('d' << 24) | ('o' << 16) | ('c' << 8) | 's'; ('d' << 24) | ('o' << 16) | ('c' << 8) | 's';
static final int kPreferencesFolderType = static final int kPreferencesFolderType =
('p' << 24) | ('r' << 16) | ('e' << 8) | 'f'; ('p' << 24) | ('r' << 16) | ('e' << 8) | 'f';
static final int kDomainLibraryFolderType = static final int kDomainLibraryFolderType =
('d' << 24) | ('l' << 16) | ('i' << 8) | 'b'; ('d' << 24) | ('l' << 16) | ('i' << 8) | 'b';
static final short kUserDomain = -32763; static final short kUserDomain = -32763;
static public File getSettingsFolder() { static public File getSettingsFolder() {
File dataFolder = null; File dataFolder = null;
String pref = Preferences.get("settings.path"); String pref = Preferences.get("settings.path");
if (pref != null) { if (pref != null) {
dataFolder = new File(pref); dataFolder = new File(pref);
} else if (Base.isMacOS()) { } else if (Base.isMacOS()) {
// carbon folder constants // carbon folder constants
// http://developer.apple.com/documentation/Carbon/Reference // http://developer.apple.com/documentation/Carbon/Reference
// /Folder_Manager/folder_manager_ref/constant_6.html#/ // /Folder_Manager/folder_manager_ref/constant_6.html#/
// /apple_ref/doc/uid/TP30000238/C006889 // /apple_ref/doc/uid/TP30000238/C006889
// additional information found int the local file: // additional information found int the local file:
// /System/Library/Frameworks/CoreServices.framework // /System/Library/Frameworks/CoreServices.framework
// /Versions/Current/Frameworks/CarbonCore.framework/Headers/ // /Versions/Current/Frameworks/CarbonCore.framework/Headers/
// this is the 1.4 version.. but using 1.3 since i have the stubs // this is the 1.4 version.. but using 1.3 since i have the stubs
// import com.apple.eio.* // import com.apple.eio.*
//println(FileManager.findFolder(kUserDomain, //println(FileManager.findFolder(kUserDomain,
// kDomainLibraryFolderType)); // kDomainLibraryFolderType));
// not clear if i can write to this folder tho.. // not clear if i can write to this folder tho..
try { try {
/* /*
if (false) { if (false) {
// this is because the mrjtoolkit stubs don't have the // this is because the mrjtoolkit stubs don't have the
// thows exception around them // thows exception around them
new FileInputStream("ignored"); new FileInputStream("ignored");
} }
*/ */
// this method has to be dynamically loaded, because // this method has to be dynamically loaded, because
MRJOSType domainLibrary = new MRJOSType("dlib"); MRJOSType domainLibrary = new MRJOSType("dlib");
Method findFolderMethod = Method findFolderMethod =
MRJFileUtils.class.getMethod("findFolder", MRJFileUtils.class.getMethod("findFolder",
new Class[] { Short.TYPE, new Class[] { Short.TYPE,
MRJOSType.class }); MRJOSType.class });
File libraryFolder = (File) File libraryFolder = (File)
findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain), findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain),
domainLibrary }); domainLibrary });
dataFolder = new File(libraryFolder, "Arduino"); dataFolder = new File(libraryFolder, "Arduino");
} catch (Exception e) { } catch (Exception e) {
// this could be FileNotFound or NoSuchMethod // this could be FileNotFound or NoSuchMethod
//} catch (FileNotFoundException e) { //} catch (FileNotFoundException e) {
//e.printStackTrace(); //e.printStackTrace();
//System.exit(1); //System.exit(1);
showError("Problem getting data folder", showError("Problem getting data folder",
"Error getting the Arduino data folder.", e); "Error getting the Arduino data folder.", e);
} }
} else if (Base.isWindows()) { } else if (Base.isWindows()) {
// looking for Documents and Settings/blah/Application Data/Arduino // looking for Documents and Settings/blah/Application Data/Arduino
// this is just based on the other documentation, and eyeballing // this is just based on the other documentation, and eyeballing
// that part of the registry.. not confirmed by any msft/msdn docs. // that part of the registry.. not confirmed by any msft/msdn docs.
// HKEY_CURRENT_USER\Software\Microsoft // HKEY_CURRENT_USER\Software\Microsoft
// \Windows\CurrentVersion\Explorer\Shell Folders // \Windows\CurrentVersion\Explorer\Shell Folders
// Value Name: AppData // Value Name: AppData
// Value Type: REG_SZ // Value Type: REG_SZ
// Value Data: path // Value Data: path
try { try {
//RegistryKey topKey = Registry.getTopLevelKey("HKCU"); //RegistryKey topKey = Registry.getTopLevelKey("HKCU");
RegistryKey topKey = Registry.HKEY_CURRENT_USER; RegistryKey topKey = Registry.HKEY_CURRENT_USER;
String localKeyPath = String localKeyPath =
"Software\\Microsoft\\Windows\\CurrentVersion" + "Software\\Microsoft\\Windows\\CurrentVersion" +
"\\Explorer\\Shell Folders"; "\\Explorer\\Shell Folders";
RegistryKey localKey = topKey.openSubKey(localKeyPath); RegistryKey localKey = topKey.openSubKey(localKeyPath);
String appDataPath = cleanKey(localKey.getStringValue("AppData")); String appDataPath = cleanKey(localKey.getStringValue("AppData"));
//System.out.println("app data path is " + appDataPath); //System.out.println("app data path is " + appDataPath);
//System.exit(0); //System.exit(0);
//topKey.closeKey(); // necessary? //topKey.closeKey(); // necessary?
//localKey.closeKey(); //localKey.closeKey();
dataFolder = new File(appDataPath, "Arduino"); dataFolder = new File(appDataPath, "Arduino");
} catch (Exception e) { } catch (Exception e) {
showError("Problem getting data folder", showError("Problem getting data folder",
"Error getting the Arduino data folder.", e); "Error getting the Arduino data folder.", e);
} }
//return null; //return null;
} else { } else {
// otherwise make a .arduino directory int the user's home dir // otherwise make a .arduino directory int the user's home dir
File home = new File(System.getProperty("user.home")); File home = new File(System.getProperty("user.home"));
dataFolder = new File(home, ".arduino"); dataFolder = new File(home, ".arduino");
} }
// create the folder if it doesn't exist already // create the folder if it doesn't exist already
boolean result = true; boolean result = true;
if (!dataFolder.exists()) { if (!dataFolder.exists()) {
result = dataFolder.mkdirs(); result = dataFolder.mkdirs();
} }
if (!result) { if (!result) {
// try the fallback location // try the fallback location
System.out.println("Using fallback path for settings."); System.out.println("Using fallback path for settings.");
String fallback = Preferences.get("settings.path.fallback"); String fallback = Preferences.get("settings.path.fallback");
dataFolder = new File(fallback); dataFolder = new File(fallback);
if (!dataFolder.exists()) { if (!dataFolder.exists()) {
result = dataFolder.mkdirs(); result = dataFolder.mkdirs();
} }
} }
if (!result) { if (!result) {
showError("Settings issues", showError("Settings issues",
"Arduino cannot run because it could not\n" + "Arduino cannot run because it could not\n" +
"create a folder to store your settings.", null); "create a folder to store your settings.", null);
} }
return dataFolder; return dataFolder;
} }
static public File getSettingsFile(String filename) { static public File getSettingsFile(String filename) {
return new File(getSettingsFolder(), filename); return new File(getSettingsFolder(), filename);
} }
static public File getBuildFolder() { static public File getBuildFolder() {
String buildPath = Preferences.get("build.path"); String buildPath = Preferences.get("build.path");
if (buildPath != null) return new File(buildPath); if (buildPath != null) return new File(buildPath);
File folder = new File(getTempFolder(), "build"); File folder = new File(getTempFolder(), "build");
if (!folder.exists()) folder.mkdirs(); if (!folder.exists()) folder.mkdirs();
return folder; return folder;
} }
/** /**
* Get the path to the platform's temporary folder, by creating * Get the path to the platform's temporary folder, by creating
* a temporary temporary file and getting its parent folder. * a temporary temporary file and getting its parent folder.
*/ */
static public File getTempFolder() { static public File getTempFolder() {
try { try {
File ignored = File.createTempFile("ignored", null); File ignored = File.createTempFile("ignored", null);
String tempPath = ignored.getParent(); String tempPath = ignored.getParent();
ignored.delete(); ignored.delete();
return new File(tempPath); return new File(tempPath);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; // TODO could we *really* ever reach this? return null; // TODO could we *really* ever reach this?
} }
/* /*
static public void addBuildFolderToClassPath() { static public void addBuildFolderToClassPath() {
String path = getBuildFolder().getAbsolutePath(); String path = getBuildFolder().getAbsolutePath();
String jcp = System.getProperty("java.class.path"); String jcp = System.getProperty("java.class.path");
if (jcp.indexOf(path) == -1) { if (jcp.indexOf(path) == -1) {
System.setProperty("java.class.path", path + File.pathSeparator + jcp); System.setProperty("java.class.path", path + File.pathSeparator + jcp);
//return new File(getProcessingDataFolder(), "build"); //return new File(getProcessingDataFolder(), "build");
System.out.println("jcp is now " + System.out.println("jcp is now " +
System.getProperty("java.class.path")); System.getProperty("java.class.path"));
} }
} }
*/ */
static public File getDefaultSketchbookFolder() { static public File getDefaultSketchbookFolder() {
File sketchbookFolder = null; File sketchbookFolder = null;
if (Base.isMacOS()) { if (Base.isMacOS()) {
// looking for /Users/blah/Documents/Arduino // looking for /Users/blah/Documents/Arduino
// carbon folder constants // carbon folder constants
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/folder_manager_ref/constant_6.html#//apple_ref/doc/uid/TP30000238/C006889 // http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/folder_manager_ref/constant_6.html#//apple_ref/doc/uid/TP30000238/C006889
// additional information found int the local file: // additional information found int the local file:
// /System/Library/Frameworks/CoreServices.framework/Versions/Current/Frameworks/CarbonCore.framework/Headers/ // /System/Library/Frameworks/CoreServices.framework/Versions/Current/Frameworks/CarbonCore.framework/Headers/
// this is the 1.4 version.. but using 1.3 since i have the stubs // this is the 1.4 version.. but using 1.3 since i have the stubs
// import com.apple.eio.* // import com.apple.eio.*
//println(FileManager.findFolder(kUserDomain, //println(FileManager.findFolder(kUserDomain,
// kDomainLibraryFolderType)); // kDomainLibraryFolderType));
// not clear if i can write to this folder tho.. // not clear if i can write to this folder tho..
try { try {
MRJOSType domainDocuments = new MRJOSType("docs"); MRJOSType domainDocuments = new MRJOSType("docs");
//File libraryFolder = MRJFileUtils.findFolder(domainDocuments); //File libraryFolder = MRJFileUtils.findFolder(domainDocuments);
// for 77, try switching this to the user domain, just to be sure // for 77, try switching this to the user domain, just to be sure
Method findFolderMethod = Method findFolderMethod =
MRJFileUtils.class.getMethod("findFolder", MRJFileUtils.class.getMethod("findFolder",
new Class[] { Short.TYPE, new Class[] { Short.TYPE,
MRJOSType.class }); MRJOSType.class });
File documentsFolder = (File) File documentsFolder = (File)
findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain), findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain),
domainDocuments }); domainDocuments });
sketchbookFolder = new File(documentsFolder, "Arduino"); sketchbookFolder = new File(documentsFolder, "Arduino");
} catch (Exception e) { } catch (Exception e) {
showError("sketch folder problem", showError("sketch folder problem",
"Could not locate default sketch folder location.", e); "Could not locate default sketch folder location.", e);
} }
} else if (isWindows()) { } else if (isWindows()) {
// looking for Documents and Settings/blah/My Documents/Arduino // looking for Documents and Settings/blah/My Documents/Arduino
// (though using a reg key since it's different on other platforms) // (though using a reg key since it's different on other platforms)
// http://support.microsoft.com/?kbid=221837&sd=RMVP // http://support.microsoft.com/?kbid=221837&sd=RMVP
// The path to the My Documents folder is stored in the // The path to the My Documents folder is stored in the
// following registry key, where path is the complete path // following registry key, where path is the complete path
// to your storage location: // to your storage location:
// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
// Value Name: Personal // Value Name: Personal
// Value Type: REG_SZ // Value Type: REG_SZ
// Value Data: path // Value Data: path
try { try {
RegistryKey topKey = Registry.HKEY_CURRENT_USER; RegistryKey topKey = Registry.HKEY_CURRENT_USER;
String localKeyPath = String localKeyPath =
"Software\\Microsoft\\Windows\\CurrentVersion" + "Software\\Microsoft\\Windows\\CurrentVersion" +
"\\Explorer\\Shell Folders"; "\\Explorer\\Shell Folders";
RegistryKey localKey = topKey.openSubKey(localKeyPath); RegistryKey localKey = topKey.openSubKey(localKeyPath);
String personalPath = cleanKey(localKey.getStringValue("Personal")); String personalPath = cleanKey(localKey.getStringValue("Personal"));
//topKey.closeKey(); // necessary? //topKey.closeKey(); // necessary?
//localKey.closeKey(); //localKey.closeKey();
sketchbookFolder = new File(personalPath, "Arduino"); sketchbookFolder = new File(personalPath, "Arduino");
} catch (Exception e) { } catch (Exception e) {
showError("Problem getting documents folder", showError("Problem getting documents folder",
"Error getting the Arduino sketchbook folder.", e); "Error getting the Arduino sketchbook folder.", e);
} }
} else { } else {
// on linux (or elsewhere?) prompt the user for the location // on linux (or elsewhere?) prompt the user for the location
JFileChooser fc = new JFileChooser(); JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Select the folder where " + fc.setDialogTitle("Select the folder where " +
"Arduino programs should be stored..."); "Arduino programs should be stored...");
//fc.setSelectedFile(new File(sketchbookLocationField.getText())); //fc.setSelectedFile(new File(sketchbookLocationField.getText()));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returned = fc.showOpenDialog(new JDialog()); int returned = fc.showOpenDialog(new JDialog());
if (returned == JFileChooser.APPROVE_OPTION) { if (returned == JFileChooser.APPROVE_OPTION) {
//File file = fc.getSelectedFile(); //File file = fc.getSelectedFile();
//sketchbookLocationField.setText(file.getAbsolutePath()); //sketchbookLocationField.setText(file.getAbsolutePath());
sketchbookFolder = fc.getSelectedFile(); sketchbookFolder = fc.getSelectedFile();
} else { } else {
System.exit(0); System.exit(0);
} }
} }
// create the folder if it doesn't exist already // create the folder if it doesn't exist already
boolean result = true; boolean result = true;
if (!sketchbookFolder.exists()) { if (!sketchbookFolder.exists()) {
result = sketchbookFolder.mkdirs(); result = sketchbookFolder.mkdirs();
} }
if (!result) { if (!result) {
// try the fallback location // try the fallback location
System.out.println("Using fallback path for sketchbook."); System.out.println("Using fallback path for sketchbook.");
String fallback = Preferences.get("sketchbook.path.fallback"); String fallback = Preferences.get("sketchbook.path.fallback");
sketchbookFolder = new File(fallback); sketchbookFolder = new File(fallback);
if (!sketchbookFolder.exists()) { if (!sketchbookFolder.exists()) {
result = sketchbookFolder.mkdirs(); result = sketchbookFolder.mkdirs();
} }
} }
if (!result) { if (!result) {
showError("error", showError("error",
"Arduino cannot run because it could not\n" + "Arduino cannot run because it could not\n" +
"create a folder to store your sketchbook.", null); "create a folder to store your sketchbook.", null);
} }
return sketchbookFolder; return sketchbookFolder;
} }
static public String cleanKey(String what) { static public String cleanKey(String what) {
// jnireg seems to be reading the chars as bytes // jnireg seems to be reading the chars as bytes
// so maybe be as simple as & 0xff and then running through decoder // so maybe be as simple as & 0xff and then running through decoder
char c[] = what.toCharArray(); char c[] = what.toCharArray();
// if chars are in the tooHigh range, it's prolly because // if chars are in the tooHigh range, it's prolly because
// a byte from the jni registry was turned into a char // a byte from the jni registry was turned into a char
// and there was a sign extension. // and there was a sign extension.
// e.g. 0xFC (252, umlaut u) became 0xFFFC (65532). // e.g. 0xFC (252, umlaut u) became 0xFFFC (65532).
// but on a japanese system, maybe this is two-byte and ok? // but on a japanese system, maybe this is two-byte and ok?
int tooHigh = 65536 - 128; int tooHigh = 65536 - 128;
for (int i = 0; i < c.length; i++) { for (int i = 0; i < c.length; i++) {
if (c[i] >= tooHigh) c[i] &= 0xff; if (c[i] >= tooHigh) c[i] &= 0xff;
/* /*
if ((c[i] >= 32) && (c[i] < 128)) { if ((c[i] >= 32) && (c[i] < 128)) {
System.out.print(c[i]); System.out.print(c[i]);
} else { } else {
System.out.print("[" + PApplet.hex(c[i]) + "]"); System.out.print("[" + PApplet.hex(c[i]) + "]");
} }
*/ */
} }
//System.out.println(); //System.out.println();
return new String(c); return new String(c);
} }
// ................................................................. // .................................................................
/** /**
* Given the reference filename from the keywords list, * Given the reference filename from the keywords list,
* builds a URL and passes it to openURL. * builds a URL and passes it to openURL.
*/ */
static public void showReference(String referenceFile) { static public void showReference(String referenceFile) {
String currentDir = System.getProperty("user.dir"); String currentDir = System.getProperty("user.dir");
openURL(currentDir + File.separator + openURL(currentDir + File.separator +
"reference" + File.separator + "reference" + File.separator +
referenceFile + ".html"); referenceFile + ".html");
} }
/** /**
* Implements the cross-platform headache of opening URLs * Implements the cross-platform headache of opening URLs
*/ */
static public void openURL(String url) { static public void openURL(String url) {
//System.out.println("opening url " + url); //System.out.println("opening url " + url);
try { try {
if (Base.isWindows()) { if (Base.isWindows()) {
// this is not guaranteed to work, because who knows if the // this is not guaranteed to work, because who knows if the
// path will always be c:\progra~1 et al. also if the user has // path will always be c:\progra~1 et al. also if the user has
// a different browser set as their default (which would // a different browser set as their default (which would
// include me) it'd be annoying to be dropped into ie. // include me) it'd be annoying to be dropped into ie.
//Runtime.getRuntime().exec("c:\\progra~1\\intern~1\\iexplore " //Runtime.getRuntime().exec("c:\\progra~1\\intern~1\\iexplore "
// + currentDir // + currentDir
// the following uses a shell execute to launch the .html file // the following uses a shell execute to launch the .html file
// note that under cygwin, the .html files have to be chmodded +x // note that under cygwin, the .html files have to be chmodded +x
// after they're unpacked from the zip file. i don't know why, // after they're unpacked from the zip file. i don't know why,
// and don't understand what this does in terms of windows // and don't understand what this does in terms of windows
// permissions. without the chmod, the command prompt says // permissions. without the chmod, the command prompt says
// "Access is denied" in both cygwin and the "dos" prompt. // "Access is denied" in both cygwin and the "dos" prompt.
//Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" + //Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" +
// referenceFile + ".html"); // referenceFile + ".html");
if (url.startsWith("http://")) { if (url.startsWith("http://")) {
// open dos prompt, give it 'start' command, which will // open dos prompt, give it 'start' command, which will
// open the url properly. start by itself won't work since // open the url properly. start by itself won't work since
// it appears to need cmd // it appears to need cmd
Runtime.getRuntime().exec("cmd /c start " + url); Runtime.getRuntime().exec("cmd /c start " + url);
} else { } else {
// just launching the .html file via the shell works // just launching the .html file via the shell works
// but make sure to chmod +x the .html files first // but make sure to chmod +x the .html files first
// also place quotes around it in case there's a space // also place quotes around it in case there's a space
// in the user.dir part of the url // in the user.dir part of the url
Runtime.getRuntime().exec("cmd /c \"" + url + "\""); Runtime.getRuntime().exec("cmd /c \"" + url + "\"");
} }
} else if (Base.isMacOS()) { } else if (Base.isMacOS()) {
//com.apple.eio.FileManager.openURL(url); //com.apple.eio.FileManager.openURL(url);
if (!url.startsWith("http://")) { if (!url.startsWith("http://")) {
// prepend file:// on this guy since it's a file // prepend file:// on this guy since it's a file
url = "file://" + url; url = "file://" + url;
// replace spaces with %20 for the file url // replace spaces with %20 for the file url
// otherwise the mac doesn't like to open it // otherwise the mac doesn't like to open it
// can't just use URLEncoder, since that makes slashes into // can't just use URLEncoder, since that makes slashes into
// %2F characters, which is no good. some might say "useless" // %2F characters, which is no good. some might say "useless"
if (url.indexOf(' ') != -1) { if (url.indexOf(' ') != -1) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
char c[] = url.toCharArray(); char c[] = url.toCharArray();
for (int i = 0; i < c.length; i++) { for (int i = 0; i < c.length; i++) {
if (c[i] == ' ') { if (c[i] == ' ') {
sb.append("%20"); sb.append("%20");
} else { } else {
sb.append(c[i]); sb.append(c[i]);
} }
} }
url = sb.toString(); url = sb.toString();
} }
} }
com.apple.mrj.MRJFileUtils.openURL(url); com.apple.mrj.MRJFileUtils.openURL(url);
} else if (Base.isLinux()) { } else if (Base.isLinux()) {
// how's mozilla sound to ya, laddie? // how's mozilla sound to ya, laddie?
//Runtime.getRuntime().exec(new String[] { "mozilla", url }); //Runtime.getRuntime().exec(new String[] { "mozilla", url });
String browser = Preferences.get("browser"); String browser = Preferences.get("browser");
Runtime.getRuntime().exec(new String[] { browser, url }); Runtime.getRuntime().exec(new String[] { browser, url });
} else { } else {
System.err.println("unspecified platform"); System.err.println("unspecified platform");
} }
} catch (IOException e) { } catch (IOException e) {
Base.showWarning("Could not open URL", Base.showWarning("Could not open URL",
"An error occurred while trying to open\n" + url, e); "An error occurred while trying to open\n" + url, e);
} }
} }
/** /**
* Implements the other cross-platform headache of opening * Implements the other cross-platform headache of opening
* a folder in the machine's native file browser. * a folder in the machine's native file browser.
*/ */
static public void openFolder(File file) { static public void openFolder(File file) {
try { try {
String folder = file.getAbsolutePath(); String folder = file.getAbsolutePath();
if (Base.isWindows()) { if (Base.isWindows()) {
// doesn't work // doesn't work
//Runtime.getRuntime().exec("cmd /c \"" + folder + "\""); //Runtime.getRuntime().exec("cmd /c \"" + folder + "\"");
// works fine on winxp, prolly win2k as well // works fine on winxp, prolly win2k as well
Runtime.getRuntime().exec("explorer \"" + folder + "\""); Runtime.getRuntime().exec("explorer \"" + folder + "\"");
// not tested // not tested
//Runtime.getRuntime().exec("start explorer \"" + folder + "\""); //Runtime.getRuntime().exec("start explorer \"" + folder + "\"");
} else if (Base.isMacOS()) { } else if (Base.isMacOS()) {
openURL(folder); // handles char replacement, etc openURL(folder); // handles char replacement, etc
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* "No cookie for you" type messages. Nothing fatal or all that * "No cookie for you" type messages. Nothing fatal or all that
* much of a bummer, but something to notify the user about. * much of a bummer, but something to notify the user about.
*/ */
static public void showMessage(String title, String message) { static public void showMessage(String title, String message) {
if (title == null) title = "Message"; if (title == null) title = "Message";
JOptionPane.showMessageDialog(new Frame(), message, title, JOptionPane.showMessageDialog(new Frame(), message, title,
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
} }
/** /**
* Non-fatal error message with optional stack trace side dish. * Non-fatal error message with optional stack trace side dish.
*/ */
static public void showWarning(String title, String message, static public void showWarning(String title, String message,
Exception e) { Exception e) {
if (title == null) title = "Warning"; if (title == null) title = "Warning";
JOptionPane.showMessageDialog(new Frame(), message, title, JOptionPane.showMessageDialog(new Frame(), message, title,
JOptionPane.WARNING_MESSAGE); JOptionPane.WARNING_MESSAGE);
//System.err.println(e.toString()); //System.err.println(e.toString());
if (e != null) e.printStackTrace(); if (e != null) e.printStackTrace();
} }
/** /**
* Show an error message that's actually fatal to the program. * Show an error message that's actually fatal to the program.
* This is an error that can't be recovered. Use showWarning() * This is an error that can't be recovered. Use showWarning()
* for errors that allow P5 to continue running. * for errors that allow P5 to continue running.
*/ */
static public void showError(String title, String message, static public void showError(String title, String message,
Exception e) { Exception e) {
if (title == null) title = "Error"; if (title == null) title = "Error";
JOptionPane.showMessageDialog(new Frame(), message, title, JOptionPane.showMessageDialog(new Frame(), message, title,
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
if (e != null) e.printStackTrace(); if (e != null) e.printStackTrace();
System.exit(1); System.exit(1);
} }
// ................................................................... // ...................................................................
static public Image getImage(String name, Component who) { static public Image getImage(String name, Component who) {
Image image = null; Image image = null;
Toolkit tk = Toolkit.getDefaultToolkit(); Toolkit tk = Toolkit.getDefaultToolkit();
//if ((Base.platform == Base.MACOSX) || //if ((Base.platform == Base.MACOSX) ||
//(Base.platform == Base.MACOS9)) { //(Base.platform == Base.MACOS9)) {
image = tk.getImage("lib/" + name); image = tk.getImage("lib/" + name);
//} else { //} else {
//image = tk.getImage(who.getClass().getResource(name)); //image = tk.getImage(who.getClass().getResource(name));
//} //}
//image = tk.getImage("lib/" + name); //image = tk.getImage("lib/" + name);
//URL url = PdeApplet.class.getResource(name); //URL url = PdeApplet.class.getResource(name);
//image = tk.getImage(url); //image = tk.getImage(url);
//} //}
//MediaTracker tracker = new MediaTracker(applet); //MediaTracker tracker = new MediaTracker(applet);
MediaTracker tracker = new MediaTracker(who); //frame); MediaTracker tracker = new MediaTracker(who); //frame);
tracker.addImage(image, 0); tracker.addImage(image, 0);
try { try {
tracker.waitForAll(); tracker.waitForAll();
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
return image; return image;
} }
static public InputStream getStream(String filename) throws IOException { static public InputStream getStream(String filename) throws IOException {
//if (Base.platform == Base.MACOSX) { //if (Base.platform == Base.MACOSX) {
// macos doesn't seem to think that files in the lib folder // macos doesn't seem to think that files in the lib folder
// are part of the resources, unlike windows or linux. // are part of the resources, unlike windows or linux.
// actually, this is only the case when running as a .app, // actually, this is only the case when running as a .app,
// since it works fine from run.sh, but not Arduino.app // since it works fine from run.sh, but not Arduino.app
return new FileInputStream("lib/" + filename); return new FileInputStream("lib/" + filename);
//} //}
// all other, more reasonable operating systems // all other, more reasonable operating systems
//return cls.getResource(filename).openStream(); //return cls.getResource(filename).openStream();
//return Base.class.getResource(filename).openStream(); //return Base.class.getResource(filename).openStream();
} }
// ................................................................... // ...................................................................
static public byte[] grabFile(File file) throws IOException { static public byte[] grabFile(File file) throws IOException {
int size = (int) file.length(); int size = (int) file.length();
FileInputStream input = new FileInputStream(file); FileInputStream input = new FileInputStream(file);
byte buffer[] = new byte[size]; byte buffer[] = new byte[size];
int offset = 0; int offset = 0;
int bytesRead; int bytesRead;
while ((bytesRead = input.read(buffer, offset, size-offset)) != -1) { while ((bytesRead = input.read(buffer, offset, size-offset)) != -1) {
offset += bytesRead; offset += bytesRead;
if (bytesRead == 0) break; if (bytesRead == 0) break;
} }
input.close(); // weren't properly being closed input.close(); // weren't properly being closed
input = null; input = null;
return buffer; return buffer;
} }
static public void copyFile(File afile, File bfile) throws IOException { static public void copyFile(File afile, File bfile) throws IOException {
InputStream from = new BufferedInputStream(new FileInputStream(afile)); InputStream from = new BufferedInputStream(new FileInputStream(afile));
OutputStream to = new BufferedOutputStream(new FileOutputStream(bfile)); OutputStream to = new BufferedOutputStream(new FileOutputStream(bfile));
byte[] buffer = new byte[16 * 1024]; byte[] buffer = new byte[16 * 1024];
int bytesRead; int bytesRead;
while ((bytesRead = from.read(buffer)) != -1) { while ((bytesRead = from.read(buffer)) != -1) {
to.write(buffer, 0, bytesRead); to.write(buffer, 0, bytesRead);
} }
to.flush(); to.flush();
from.close(); // ?? from.close(); // ??
from = null; from = null;
to.close(); // ?? to.close(); // ??
to = null; to = null;
bfile.setLastModified(afile.lastModified()); // jdk13+ required bfile.setLastModified(afile.lastModified()); // jdk13+ required
//} catch (IOException e) { //} catch (IOException e) {
// e.printStackTrace(); // e.printStackTrace();
//} //}
} }
/** /**
* Grab the contents of a file as a string. * Grab the contents of a file as a string.
*/ */
static public String loadFile(File file) throws IOException { static public String loadFile(File file) throws IOException {
// empty code file.. no worries, might be getting filled up later // empty code file.. no worries, might be getting filled up later
if (file.length() == 0) return ""; if (file.length() == 0) return "";
InputStreamReader isr = new InputStreamReader(new FileInputStream(file)); InputStreamReader isr = new InputStreamReader(new FileInputStream(file));
BufferedReader reader = new BufferedReader(isr); BufferedReader reader = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
String line = null; String line = null;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
buffer.append(line); buffer.append(line);
buffer.append('\n'); buffer.append('\n');
} }
reader.close(); reader.close();
return buffer.toString(); return buffer.toString();
} }
/** /**
* Spew the contents of a String object out to a file. * Spew the contents of a String object out to a file.
*/ */
static public void saveFile(String str, static public void saveFile(String str,
File file) throws IOException { File file) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes()); ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
InputStreamReader isr = new InputStreamReader(bis); InputStreamReader isr = new InputStreamReader(bis);
BufferedReader reader = new BufferedReader(isr); BufferedReader reader = new BufferedReader(isr);
FileWriter fw = new FileWriter(file); FileWriter fw = new FileWriter(file);
PrintWriter writer = new PrintWriter(new BufferedWriter(fw)); PrintWriter writer = new PrintWriter(new BufferedWriter(fw));
String line = null; String line = null;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
writer.println(line); writer.println(line);
} }
writer.flush(); writer.flush();
writer.close(); writer.close();
} }
static public void copyDir(File sourceDir, static public void copyDir(File sourceDir,
File targetDir) throws IOException { File targetDir) throws IOException {
targetDir.mkdirs(); targetDir.mkdirs();
String files[] = sourceDir.list(); String files[] = sourceDir.list();
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
if (files[i].equals(".") || files[i].equals("..")) continue; if (files[i].equals(".") || files[i].equals("..")) continue;
File source = new File(sourceDir, files[i]); File source = new File(sourceDir, files[i]);
File target = new File(targetDir, files[i]); File target = new File(targetDir, files[i]);
if (source.isDirectory()) { if (source.isDirectory()) {
//target.mkdirs(); //target.mkdirs();
copyDir(source, target); copyDir(source, target);
target.setLastModified(source.lastModified()); target.setLastModified(source.lastModified());
} else { } else {
copyFile(source, target); copyFile(source, target);
} }
} }
} }
/** /**
* Remove all files in a directory and the directory itself. * Remove all files in a directory and the directory itself.
*/ */
static public void removeDir(File dir) { static public void removeDir(File dir) {
if (dir.exists()) { if (dir.exists()) {
removeDescendants(dir); removeDescendants(dir);
dir.delete(); dir.delete();
} }
} }
/** /**
* Recursively remove all files within a directory, * Recursively remove all files within a directory,
* used with removeDir(), or when the contents of a dir * used with removeDir(), or when the contents of a dir
* should be removed, but not the directory itself. * should be removed, but not the directory itself.
* (i.e. when cleaning temp files from lib/build) * (i.e. when cleaning temp files from lib/build)
*/ */
static public void removeDescendants(File dir) { static public void removeDescendants(File dir) {
if (!dir.exists()) return; if (!dir.exists()) return;
String files[] = dir.list(); String files[] = dir.list();
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
if (files[i].equals(".") || files[i].equals("..")) continue; if (files[i].equals(".") || files[i].equals("..")) continue;
File dead = new File(dir, files[i]); File dead = new File(dir, files[i]);
if (!dead.isDirectory()) { if (!dead.isDirectory()) {
if (!Preferences.getBoolean("compiler.save_build_files")) { if (!Preferences.getBoolean("compiler.save_build_files")) {
if (!dead.delete()) { if (!dead.delete()) {
// temporarily disabled // temporarily disabled
//System.err.println("couldn't delete " + dead); //System.err.println("couldn't delete " + dead);
} }
} }
} else { } else {
removeDir(dead); removeDir(dead);
//dead.delete(); //dead.delete();
} }
} }
} }
/** /**
* Calculate the size of the contents of a folder. * Calculate the size of the contents of a folder.
* Used to determine whether sketches are empty or not. * Used to determine whether sketches are empty or not.
* Note that the function calls itself recursively. * Note that the function calls itself recursively.
*/ */
static public int calcFolderSize(File folder) { static public int calcFolderSize(File folder) {
int size = 0; int size = 0;
String files[] = folder.list(); String files[] = folder.list();
// null if folder doesn't exist, happens when deleting sketch // null if folder doesn't exist, happens when deleting sketch
if (files == null) return -1; if (files == null) return -1;
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
if (files[i].equals(".") || (files[i].equals("..")) || if (files[i].equals(".") || (files[i].equals("..")) ||
files[i].equals(".DS_Store")) continue; files[i].equals(".DS_Store")) continue;
File fella = new File(folder, files[i]); File fella = new File(folder, files[i]);
if (fella.isDirectory()) { if (fella.isDirectory()) {
size += calcFolderSize(fella); size += calcFolderSize(fella);
} else { } else {
size += (int) fella.length(); size += (int) fella.length();
} }
} }
return size; return size;
} }
/** /**
* Equivalent to the one in PApplet, but static (die() is removed) * Equivalent to the one in PApplet, but static (die() is removed)
*/ */
static public String[] loadStrings(File file) { static public String[] loadStrings(File file) {
try { try {
FileInputStream input = new FileInputStream(file); FileInputStream input = new FileInputStream(file);
BufferedReader reader = BufferedReader reader =
new BufferedReader(new InputStreamReader(input)); new BufferedReader(new InputStreamReader(input));
String lines[] = new String[100]; String lines[] = new String[100];
int lineCount = 0; int lineCount = 0;
String line = null; String line = null;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
if (lineCount == lines.length) { if (lineCount == lines.length) {
String temp[] = new String[lineCount << 1]; String temp[] = new String[lineCount << 1];
System.arraycopy(lines, 0, temp, 0, lineCount); System.arraycopy(lines, 0, temp, 0, lineCount);
lines = temp; lines = temp;
} }
lines[lineCount++] = line; lines[lineCount++] = line;
} }
reader.close(); reader.close();
if (lineCount == lines.length) { if (lineCount == lines.length) {
return lines; return lines;
} }
// resize array to appropraite amount for these lines // resize array to appropraite amount for these lines
String output[] = new String[lineCount]; String output[] = new String[lineCount];
System.arraycopy(lines, 0, output, 0, lineCount); System.arraycopy(lines, 0, output, 0, lineCount);
return output; return output;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// STRINGS // STRINGS
/** /**
* Remove whitespace characters from the beginning and ending * Remove whitespace characters from the beginning and ending
* of a String. Works like String.trim() but includes the * of a String. Works like String.trim() but includes the
* unicode nbsp character as well. * unicode nbsp character as well.
*/ */
static public String trim(String str) { static public String trim(String str) {
return str.replace('\u00A0', ' ').trim(); return str.replace('\u00A0', ' ').trim();
/* /*
int left = 0; int left = 0;
int right = str.length() - 1; int right = str.length() - 1;
while ((left <= right) && while ((left <= right) &&
(WHITESPACE.indexOf(str.charAt(left)) != -1)) left++; (WHITESPACE.indexOf(str.charAt(left)) != -1)) left++;
if (left == right) return ""; if (left == right) return "";
while (WHITESPACE.indexOf(str.charAt(right)) != -1) --right; while (WHITESPACE.indexOf(str.charAt(right)) != -1) --right;
return str.substring(left, right-left+1); return str.substring(left, right-left+1);
*/ */
} }
/** /**
* Join an array of Strings together as a single String, * Join an array of Strings together as a single String,
* separated by the whatever's passed in for the separator. * separated by the whatever's passed in for the separator.
*/ */
static public String join(String str[], char separator) { static public String join(String str[], char separator) {
return join(str, String.valueOf(separator)); return join(str, String.valueOf(separator));
} }
/** /**
* Join an array of Strings together as a single String, * Join an array of Strings together as a single String,
* separated by the whatever's passed in for the separator. * separated by the whatever's passed in for the separator.
* <P> * <P>
* To use this on numbers, first pass the array to nf() or nfs() * To use this on numbers, first pass the array to nf() or nfs()
* to get a list of String objects, then use join on that. * to get a list of String objects, then use join on that.
* <PRE> * <PRE>
* e.g. String stuff[] = { "apple", "bear", "cat" }; * e.g. String stuff[] = { "apple", "bear", "cat" };
* String list = join(stuff, ", "); * String list = join(stuff, ", ");
* // list is now "apple, bear, cat"</PRE> * // list is now "apple, bear, cat"</PRE>
*/ */
static public String join(String str[], String separator) { static public String join(String str[], String separator) {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
for (int i = 0; i < str.length; i++) { for (int i = 0; i < str.length; i++) {
if (i != 0) buffer.append(separator); if (i != 0) buffer.append(separator);
buffer.append(str[i]); buffer.append(str[i]);
} }
return buffer.toString(); return buffer.toString();
} }
/** /**
* Split the provided String at wherever whitespace occurs. * Split the provided String at wherever whitespace occurs.
* Multiple whitespace (extra spaces or tabs or whatever) * Multiple whitespace (extra spaces or tabs or whatever)
* between items will count as a single break. * between items will count as a single break.
* <P> * <P>
* The whitespace characters are "\t\n\r\f", which are the defaults * The whitespace characters are "\t\n\r\f", which are the defaults
* for java.util.StringTokenizer, plus the unicode non-breaking space * for java.util.StringTokenizer, plus the unicode non-breaking space
* character, which is found commonly on files created by or used * character, which is found commonly on files created by or used
* in conjunction with Mac OS X (character 160, or 0x00A0 in hex). * in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
* <PRE> * <PRE>
* i.e. split("a b") -> { "a", "b" } * i.e. split("a b") -> { "a", "b" }
* split("a b") -> { "a", "b" } * split("a b") -> { "a", "b" }
* split("a\tb") -> { "a", "b" } * split("a\tb") -> { "a", "b" }
* split("a \t b ") -> { "a", "b" }</PRE> * split("a \t b ") -> { "a", "b" }</PRE>
*/ */
static public String[] split(String what) { static public String[] split(String what) {
return split(what, WHITESPACE); return split(what, WHITESPACE);
} }
/** /**
* Splits a string into pieces, using any of the chars in the * Splits a string into pieces, using any of the chars in the
* String 'delim' as separator characters. For instance, * String 'delim' as separator characters. For instance,
* in addition to white space, you might want to treat commas * in addition to white space, you might want to treat commas
* as a separator. The delimeter characters won't appear in * as a separator. The delimeter characters won't appear in
* the returned String array. * the returned String array.
* <PRE> * <PRE>
* i.e. split("a, b", " ,") -> { "a", "b" } * i.e. split("a, b", " ,") -> { "a", "b" }
* </PRE> * </PRE>
* To include all the whitespace possibilities, use the variable * To include all the whitespace possibilities, use the variable
* WHITESPACE, found in PConstants: * WHITESPACE, found in PConstants:
* <PRE> * <PRE>
* i.e. split("a | b", WHITESPACE + "|"); -> { "a", "b" }</PRE> * i.e. split("a | b", WHITESPACE + "|"); -> { "a", "b" }</PRE>
*/ */
static public String[] split(String what, String delim) { static public String[] split(String what, String delim) {
StringTokenizer toker = new StringTokenizer(what, delim); StringTokenizer toker = new StringTokenizer(what, delim);
String pieces[] = new String[toker.countTokens()]; String pieces[] = new String[toker.countTokens()];
int index = 0; int index = 0;
while (toker.hasMoreTokens()) { while (toker.hasMoreTokens()) {
pieces[index++] = toker.nextToken(); pieces[index++] = toker.nextToken();
} }
return pieces; return pieces;
} }
/** /**
* Split a string into pieces along a specific character. * Split a string into pieces along a specific character.
* Most commonly used to break up a String along tab characters. * Most commonly used to break up a String along tab characters.
* <P> * <P>
* This operates differently than the others, where the * This operates differently than the others, where the
* single delimeter is the only breaking point, and consecutive * single delimeter is the only breaking point, and consecutive
* delimeters will produce an empty string (""). This way, * delimeters will produce an empty string (""). This way,
* one can split on tab characters, but maintain the column * one can split on tab characters, but maintain the column
* alignments (of say an excel file) where there are empty columns. * alignments (of say an excel file) where there are empty columns.
*/ */
static public String[] split(String what, char delim) { static public String[] split(String what, char delim) {
// do this so that the exception occurs inside the user's // do this so that the exception occurs inside the user's
// program, rather than appearing to be a bug inside split() // program, rather than appearing to be a bug inside split()
if (what == null) return null; if (what == null) return null;
//return split(what, String.valueOf(delim)); // huh //return split(what, String.valueOf(delim)); // huh
char chars[] = what.toCharArray(); char chars[] = what.toCharArray();
int splitCount = 0; //1; int splitCount = 0; //1;
for (int i = 0; i < chars.length; i++) { for (int i = 0; i < chars.length; i++) {
if (chars[i] == delim) splitCount++; if (chars[i] == delim) splitCount++;
} }
// make sure that there is something in the input string // make sure that there is something in the input string
//if (chars.length > 0) { //if (chars.length > 0) {
// if the last char is a delimeter, get rid of it.. // if the last char is a delimeter, get rid of it..
//if (chars[chars.length-1] == delim) splitCount--; //if (chars[chars.length-1] == delim) splitCount--;
// on second thought, i don't agree with this, will disable // on second thought, i don't agree with this, will disable
//} //}
if (splitCount == 0) { if (splitCount == 0) {
String splits[] = new String[1]; String splits[] = new String[1];
splits[0] = new String(what); splits[0] = new String(what);
return splits; return splits;
} }
//int pieceCount = splitCount + 1; //int pieceCount = splitCount + 1;
String splits[] = new String[splitCount + 1]; String splits[] = new String[splitCount + 1];
int splitIndex = 0; int splitIndex = 0;
int startIndex = 0; int startIndex = 0;
for (int i = 0; i < chars.length; i++) { for (int i = 0; i < chars.length; i++) {
if (chars[i] == delim) { if (chars[i] == delim) {
splits[splitIndex++] = splits[splitIndex++] =
new String(chars, startIndex, i-startIndex); new String(chars, startIndex, i-startIndex);
startIndex = i + 1; startIndex = i + 1;
} }
} }
//if (startIndex != chars.length) { //if (startIndex != chars.length) {
splits[splitIndex] = splits[splitIndex] =
new String(chars, startIndex, chars.length-startIndex); new String(chars, startIndex, chars.length-startIndex);
//} //}
return splits; return splits;
} }
} }