mirror of
https://github.com/processing/processing4.git
synced 2026-02-03 21:59:20 +01:00
X move structure of app/application dirs around a bit X make a new 'dist' function for building X save window position (only during session) of sketch run window X shouldn't substitute f's for: "Univers76.vlw.gz"; X need lots of testing--this changes lots of things X fixed commentsCodec which was mangling things o present mode doesn't work for draw() X tested, seems to be fine? X console - convert tabs to spaces o line wrapping (but save info for resize? noo..) X fix to line numbers being off for KjcEngine exception highlights X changed error color slightly for console to fit status error X size() not being called in setup is gonna cause lots of headaches X hack: put exception handler around setup and re-call if necessary X linefeeds were wrong in BApplet
1105 lines
31 KiB
Java
1105 lines
31 KiB
Java
import java.awt.*; // for window, temporary
|
|
import java.awt.event.*; // also for window
|
|
import java.io.*;
|
|
|
|
import java.net.*; // the start of a bad joke
|
|
|
|
import com.oroinc.text.regex.*;
|
|
|
|
|
|
// always compile to lib directory
|
|
// always make .java in current directory
|
|
// can copy over (and delete) later for export
|
|
// fix line number offset so that public class can be on a new line
|
|
// re-enable system err catching (after lib fixes)
|
|
|
|
// doesn't really need to extend kjc.Main anymore,
|
|
// since reportTrouble doesn't actually do any good
|
|
|
|
public class KjcEngine extends PdeEngine {
|
|
static String TEMP_CLASS = "Temporary";
|
|
static final String EXTENDS = "extends BApplet ";
|
|
static final String EXTENDS_KJC = "extends KjcApplet ";
|
|
|
|
static final int COMPILING = 1;
|
|
static final int RUNNING = 2;
|
|
int messageMode;
|
|
|
|
static final String imports[] = {
|
|
"java.applet", "java.awt", "java.awt.image", "java.awt.event",
|
|
"java.io", "java.net", "java.text", "java.util", "java.util.zip"
|
|
};
|
|
|
|
String tempClass;
|
|
String tempFilename;
|
|
String tempClassFilename;
|
|
PdeException exception;
|
|
|
|
PrintStream leechErr;
|
|
KjcMessageStream messageStream;
|
|
|
|
String program;
|
|
//PdeEditor editor;
|
|
String buildPath;
|
|
|
|
boolean running;
|
|
KjcApplet applet;
|
|
//Window window;
|
|
|
|
Process process;
|
|
static int portnum = 8192;
|
|
ServerSocket umbilical;
|
|
boolean usingExternal;
|
|
|
|
|
|
public KjcEngine(PdeEditor editor,
|
|
String program, String buildPath,
|
|
String dataPath) {
|
|
super(editor);
|
|
|
|
this.program = program;
|
|
this.buildPath = buildPath;
|
|
//this.buildPath = "lib" + File.separator + "build";
|
|
//this.editor = editor;
|
|
|
|
// only run cleanup if using the applications temp dir
|
|
//if (buildPath.endsWith("build")) cleanup();
|
|
|
|
File buildDir = new File(buildPath);
|
|
if (dataPath != null) {
|
|
File dataDir = new File(dataPath);
|
|
if (dataDir.exists()) {
|
|
PdeEditor.copyDir(dataDir, buildDir);
|
|
/*
|
|
String files[] = dataDir.list();
|
|
for (int i = 0; i < files.length; i++) {
|
|
File sourceFile = new File(dataDir, files[i]);
|
|
if (sourceFile.isDirectory()) continue; // may fix in future
|
|
File targetFile = new File(buildDir, files[i]);
|
|
//System.err.println("source is " + sourceFile +
|
|
// " target is " + targetFile);
|
|
PdeEditor.copyFile(sourceFile, targetFile);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
usingExternal = PdeBase.getBoolean("play.external", false);
|
|
|
|
/*
|
|
// what are the chances of this working on the mac?
|
|
// one in ninety nine? one in a 667 megahertz?
|
|
File dir = new File(".");
|
|
String list[] = dir.list();
|
|
for (int i = 0; i < list.length; i++) {
|
|
if (list[i].indexOf(TEMP_CLASS) == 0) {
|
|
//System.out.println("culprit1: " + list[i]);
|
|
File deadMan = new File(dir, list[i]);
|
|
deadMan.delete();
|
|
}
|
|
}
|
|
dir = new File("lib");
|
|
list = dir.list();
|
|
for (int i = 0; i < list.length; i++) {
|
|
if (list[i].indexOf(TEMP_CLASS) == 0) {
|
|
//System.out.println("culprit2: " + list[i]);
|
|
File deadMan = new File(dir, list[i]);
|
|
deadMan.delete();
|
|
}
|
|
}
|
|
*/
|
|
//dir = new File(buildPath);
|
|
}
|
|
|
|
|
|
static final int BEGINNER = 0;
|
|
static final int INTERMEDIATE = 1;
|
|
static final int ADVANCED = 2;
|
|
|
|
// writes .java file into buildPath
|
|
public String writeJava(String name, boolean kjc) {
|
|
//System.out.println("writing java");
|
|
try {
|
|
int programType = BEGINNER;
|
|
|
|
// remove (encode) comments temporarily
|
|
program = commentsCodec(program /*, true*/);
|
|
|
|
// insert 'f' for all floats
|
|
// shouldn't substitute f's for: "Univers76.vlw.gz";
|
|
if (PdeBase.getBoolean("compiler.substitute_f", true)) {
|
|
/*
|
|
a = 0.2 * 3
|
|
(3.)
|
|
(.3 * 6)
|
|
(.30*7)
|
|
|
|
next to white space \s or math ops +-/*()
|
|
|
|
*/
|
|
program = substipoot(program, "([\\s\\+\\-\\/\\*\\(\\)])(\\d+\\.\\d*)([\\s\\+\\-\\/\\*\\(\\)])", "$1$2f$3");
|
|
program = substipoot(program, "([\\s\\+\\-\\/\\*\\(\\)])(\\d*\\.\\d+)([\\s\\+\\-\\/\\*\\(\\)])", "$1$2f$3");
|
|
|
|
/*
|
|
// allow 3. to work (also allows x.x too)
|
|
program = substipoot(program, "(\\d+\\.\\d*)(\\D)", "$1f$2");
|
|
program = substipoot(program, "(\\d+\\.\\d*)ff", "$1f");
|
|
|
|
// allow .3 to work (also allows x.x)
|
|
program = substipoot(program, "(\\d*\\.\\d+)(\\D)", "$1f$2");
|
|
program = substipoot(program, "(\\d*\\.\\d+)ff", "$1f");
|
|
*/
|
|
}
|
|
|
|
// allow int(3.75) instead of just (int)3.75
|
|
if (PdeBase.getBoolean("compiler.enhanced_casting", true)) {
|
|
program = substipoot(program, "([^A-Za-z0-9_])byte\\((.*)\\)", "$1(byte)($2)");
|
|
program = substipoot(program, "([^A-Za-z0-9_])char\\((.*)\\)", "$1(char)($2)");
|
|
program = substipoot(program, "([^A-Za-z0-9_])int\\((.*)\\)", "$1(int)($2)");
|
|
program = substipoot(program, "([^A-Za-z0-9_])float\\((.*)\\)", "$1(float)($2)");
|
|
}
|
|
|
|
if (PdeBase.getBoolean("compiler.color_datatype", true)) {
|
|
// so that regexp works correctly in this strange edge case
|
|
if (program.indexOf("color") == 0) program = " " + program;
|
|
program = substipoot(program,
|
|
"([^A-Za-z0-9_])color([^A-Za-z0-9_\\(])", "$1int$2");
|
|
//program = substipoot(program, "([^A-Za-z0-9_])color\\((.*)\\)", "$1(int)($2)");
|
|
}
|
|
|
|
if (PdeBase.getBoolean("compiler.inline_web_colors", true)) {
|
|
// convert "= #cc9988" into "= 0xffcc9988"
|
|
//program = substipoot(program, "(=\\s*)\\#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])", "$1 0xff$2$3$4");
|
|
program = substipoot(program, "#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])", "0xff$1$2$3");
|
|
}
|
|
|
|
if ((program.indexOf("void setup()") != -1) ||
|
|
(program.indexOf("void loop()") != -1) ||
|
|
(program.indexOf("void draw()") != -1)) {
|
|
programType = INTERMEDIATE;
|
|
}
|
|
|
|
int index = program.indexOf("public class");
|
|
if (index != -1) {
|
|
programType = ADVANCED;
|
|
// kjc will get pissed off if i call the .java file
|
|
// something besides the name of the class.. so here goes
|
|
String s = program.substring(index + "public class".length()).trim();
|
|
index = s.indexOf(' ');
|
|
name = s.substring(0, index);
|
|
tempClass = name;
|
|
|
|
// and we're running inside
|
|
if (kjc) { // if running inside processing...
|
|
index = program.indexOf(EXTENDS); // ...and extends BApplet
|
|
if (index != -1) { // just extends object
|
|
String left = program.substring(0, index);
|
|
String right = program.substring(index + EXTENDS.length());
|
|
// replace with 'extends KjcApplet'
|
|
program = left + ((usingExternal) ? EXTENDS : EXTENDS_KJC) + right;
|
|
}
|
|
}
|
|
}
|
|
tempFilename = name + ".java";
|
|
tempClassFilename = name + ".class";
|
|
|
|
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(buildPath + File.separator + tempFilename))));
|
|
|
|
//String eol = System.getProperties().getProperty("line.separator");
|
|
|
|
if (programType < ADVANCED) {
|
|
// spew out a bunch of java imports
|
|
for (int i = 0; i < imports.length; i++) {
|
|
writer.print("import " + imports[i] + ".*; ");
|
|
if (!kjc) writer.println();
|
|
}
|
|
if (!kjc) writer.println();
|
|
|
|
writer.print("public class " + name + " extends " +
|
|
((kjc && !usingExternal) ? "KjcApplet" : "BApplet") + " {");
|
|
}
|
|
if (programType == BEGINNER) {
|
|
if (!kjc) writer.println();
|
|
|
|
// first determine the size of the program
|
|
PatternMatcher matcher = new Perl5Matcher();
|
|
PatternCompiler compiler = new Perl5Compiler();
|
|
Pattern pattern = null;
|
|
|
|
// hack so that the regexp below works
|
|
if (program.indexOf("size(") == 0) program = " " + program;
|
|
|
|
try {
|
|
//pattern = compiler.compile("\ssize\(\d+),\s*(\d+)\)\;");
|
|
//pattern = compiler.compile("^[^A-Za-z0-9_]+size\\(\\s*(\\d+),\\s*(\\d+)\\s*\\);");
|
|
pattern =
|
|
compiler.compile("^([^A-Za-z0-9_]+)(size\\(\\s*\\d+,\\s*\\d+\\s*\\);)");
|
|
|
|
} catch (MalformedPatternException e){
|
|
System.err.println("Bad pattern.");
|
|
System.err.println(e.getMessage());
|
|
System.exit(1);
|
|
}
|
|
|
|
//PatternMatcher matcher = new Perl5Matcher();
|
|
String sizeInfo = "";
|
|
PatternMatcherInput input =
|
|
new PatternMatcherInput(program);
|
|
if (matcher.contains(input, pattern)) {
|
|
MatchResult result = matcher.getMatch();
|
|
//int wide = Integer.parseInt(result.group(1).toString());
|
|
//int high = Integer.parseInt(result.group(2).toString());
|
|
sizeInfo = "void setup() { " + result.group(0) + " } ";
|
|
|
|
} else {
|
|
// no size() defined, make it 100x100
|
|
}
|
|
|
|
// remove references to size()
|
|
// this winds up removing every reference to size()
|
|
// not really intended, but will help things work
|
|
Perl5Substitution subst =
|
|
new Perl5Substitution("$1", Perl5Substitution.INTERPOLATE_ALL);
|
|
program = Util.substitute(matcher, pattern, subst, program,
|
|
Util.SUBSTITUTE_ALL);
|
|
//System.out.println(program);
|
|
|
|
writer.print(sizeInfo);
|
|
writer.print("void draw() {");
|
|
}
|
|
|
|
// decode comments to bring them back
|
|
program = commentsCodec(program /*, false*/);
|
|
|
|
// spew the actual program
|
|
// this should really add extra indents,
|
|
// especially when not in kjc mode (!kjc == export)
|
|
|
|
// things will be one line off if there's an error in the code
|
|
if (!kjc) writer.println();
|
|
|
|
writer.println(program);
|
|
//System.out.println(program);
|
|
|
|
if (programType == BEGINNER) {
|
|
writer.println("}");
|
|
}
|
|
if (programType < ADVANCED) {
|
|
writer.print("}");
|
|
}
|
|
|
|
writer.flush();
|
|
writer.close();
|
|
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return name;
|
|
}
|
|
|
|
//static char encodeTable[] = new char[127];
|
|
//static char decodeTable[] = new char[127];
|
|
static char rotateTable[] = new char[127];
|
|
static {
|
|
int rot = (123 - 65) / 2;
|
|
for (int i = 65; i < 123; i++) {
|
|
rotateTable[i] = (char) (((i - 65 + rot) % (rot*2)) + 65); // : (char)i;
|
|
}
|
|
|
|
//for (int i = 33; i < 127; i++) {
|
|
//rotateTable[i] = //Character.isAlpha((char)i) ?
|
|
//(char) (((i - 33 + rot) % 94) + 33) : (char)i;
|
|
|
|
//encodeTable[i] = (char) (i+1);
|
|
//decodeTable[i] = (char) (i-1);
|
|
//encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33);
|
|
//decodeTable[i] = encodeTable[i];
|
|
//encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33);
|
|
//decodeTable[i] = (char) (((i + 33 + rot) % 94) + 33);
|
|
//System.out.println((int) decodeTable[i]);
|
|
//}
|
|
}
|
|
|
|
protected String commentsCodec(String program /*, boolean encode*/) {
|
|
// need to preprocess class to remove comments
|
|
// so tthat they don't fool this crappy parsing below
|
|
char p[] = program.toCharArray();
|
|
boolean insideComment = false;
|
|
boolean eolComment = false;
|
|
boolean slash = false;
|
|
for (int i = 0; i < p.length; i++) {
|
|
if (insideComment) {
|
|
if (eolComment &&
|
|
((p[i] == '\r') || (p[i] == '\n'))) {
|
|
insideComment = false;
|
|
slash = false;
|
|
|
|
} else if (!eolComment &&
|
|
(p[i] == '*') &&
|
|
(i != (p.length-1)) &&
|
|
(p[i+1] == '/')) {
|
|
insideComment = false;
|
|
slash = false;
|
|
|
|
} else {
|
|
//if ((p[i] > 32) && (p[i] < 127)) {
|
|
if ((p[i] >= 0x30) && (p[i] < 127)) {
|
|
p[i] = rotateTable[p[i]];
|
|
//p[i] = encode ? encodeTable[p[i]] : decodeTable[p[i]];
|
|
}
|
|
//p[i] = ' ';
|
|
}
|
|
} else { // not yet inside a comment
|
|
if (p[i] == '/') {
|
|
if (slash) {
|
|
insideComment = true;
|
|
eolComment = true;
|
|
} else {
|
|
slash = true;
|
|
}
|
|
} else if (p[i] == '*') {
|
|
if (slash) {
|
|
insideComment = true;
|
|
eolComment = false;
|
|
}
|
|
} else {
|
|
slash = false;
|
|
}
|
|
}
|
|
}
|
|
//System.out.println(new String(p));
|
|
return new String(p);
|
|
}
|
|
|
|
protected String substipoot(String what, String incoming, String outgoing) {
|
|
PatternMatcher matcher = new Perl5Matcher();
|
|
PatternCompiler compiler = new Perl5Compiler();
|
|
Pattern pattern = null;
|
|
|
|
try {
|
|
pattern = compiler.compile(incoming);
|
|
|
|
} catch (MalformedPatternException e){
|
|
System.err.println("Bad pattern.");
|
|
System.err.println(e.getMessage());
|
|
System.exit(1);
|
|
}
|
|
|
|
Perl5Substitution subst =
|
|
new Perl5Substitution(outgoing, Perl5Substitution.INTERPOLATE_ALL);
|
|
return Util.substitute(matcher, pattern, subst, what,
|
|
Util.SUBSTITUTE_ALL);
|
|
}
|
|
|
|
//public void finalize() {
|
|
//System.out.println("finalizing KjcEngine");
|
|
//}
|
|
|
|
boolean newMessage;
|
|
|
|
public void message(String s) {
|
|
if (messageMode == COMPILING) {
|
|
//System.out.println("leech2: " + new String(b, offset, length));
|
|
//String s = new String(b, offset, length);
|
|
//if (s.indexOf(tempFilename) == 0) {
|
|
String fullTempFilename = buildPath + File.separator + tempFilename;
|
|
if (s.indexOf(fullTempFilename) == 0) {
|
|
String s1 = s.substring(fullTempFilename.length() + 1);
|
|
int colon = s1.indexOf(':');
|
|
int lineNumber = Integer.parseInt(s1.substring(0, colon));
|
|
//System.out.println("pde / line number: " + lineNumber);
|
|
|
|
//String s2 = s1.substring(colon + 2);
|
|
int err = s1.indexOf("error:");
|
|
if (err != -1) {
|
|
//err += "error:".length();
|
|
String description = s1.substring(err + "error:".length());
|
|
description = description.trim();
|
|
//exception = new PdeException(description, lineNumber-2);
|
|
exception = new PdeException(description, lineNumber-1);
|
|
editor.error(exception);
|
|
|
|
} else {
|
|
System.err.println("i suck: " + s);
|
|
}
|
|
|
|
} else {
|
|
System.err.println("don't understand: " + s);
|
|
}
|
|
} else if (messageMode == RUNNING) {
|
|
//if (s.indexOf("MAKE WAY") != -1) {
|
|
//System.out.println("new message coming");
|
|
//newMessage = true;
|
|
|
|
//} else {
|
|
if (newMessage) {
|
|
//System.out.println("making msg of " + s);
|
|
exception = new PdeException(s); // type of java ex
|
|
//System.out.println("setting ex type to " + s);
|
|
newMessage = false;
|
|
} else {
|
|
int index = s.indexOf(tempFilename);
|
|
//System.out.println("> " + s);
|
|
if (index != -1) {
|
|
int len = tempFilename.length();
|
|
String lineNumberStr = s.substring(index + len + 1);
|
|
index = lineNumberStr.indexOf(')');
|
|
lineNumberStr = lineNumberStr.substring(0, index);
|
|
//System.err.println("error line is: " + lineNumberStr);
|
|
try {
|
|
exception.line = Integer.parseInt(lineNumberStr) - 1; //2;
|
|
//System.out.println("exception in RUNNING");
|
|
editor.error(exception);
|
|
} catch (NumberFormatException e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else if ((index = s.indexOf(tempClass)) != -1) {
|
|
// code to check for:
|
|
// at Temporary_484_3845.loop(Compiled Code)
|
|
// would also probably get:
|
|
// at Temporary_484_3845.loop
|
|
// which (i believe) is used by the mac and/or jview
|
|
String functionStr = s.substring(index + tempClass.length() + 1);
|
|
index = functionStr.indexOf('(');
|
|
if (index != -1) {
|
|
functionStr = functionStr.substring(0, index);
|
|
}
|
|
exception = new PdeException(//"inside \"" + functionStr + "()\": " +
|
|
exception.getMessage() +
|
|
" inside " + functionStr + "() " +
|
|
"[add Compiler.disable() to setup()]");
|
|
editor.error(exception);
|
|
// this will fall through in tihs example:
|
|
// at Temporary_4636_9696.pootie(Compiled Code)
|
|
// at Temporary_4636_9696.loop(Temporary_4636_9696.java:24)
|
|
// because pootie() (re)sets the exception title
|
|
// and throws it, but then the line number gets set
|
|
// because of the line that comes after
|
|
}
|
|
//System.out.println("got it " + s);
|
|
}
|
|
} else {
|
|
System.out.println("message mode not set");
|
|
}
|
|
}
|
|
|
|
|
|
//public void error(Exception e) {
|
|
//newMessage = true;
|
|
//e.printStackTrace(leechErr);
|
|
//}
|
|
|
|
|
|
//public void reportTrouble(PositionedError trouble) {
|
|
//System.out.println("trubber: " + trouble);
|
|
//}
|
|
|
|
|
|
public boolean compileJava() throws PdeException {
|
|
String args[] = new String[2];
|
|
//args[0] = "-dlib";
|
|
//args[1] = tempFilename;
|
|
args[0] = "-d" + buildPath;
|
|
args[1] = buildPath + File.separator + tempFilename;
|
|
//System.out.println("args = " + args[0] + " " + args[1]);
|
|
|
|
// this will catch and parse errors during compilation
|
|
// or should this be in the constructor?
|
|
messageStream = new KjcMessageStream(this);
|
|
leechErr = new PrintStream(messageStream);
|
|
//PrintStream systemErr = System.err;
|
|
System.setErr(leechErr); // NEED THIS
|
|
|
|
messageMode = COMPILING;
|
|
|
|
//boolean success = compile(args);
|
|
boolean success = at.dms.kjc.Main.compile(args);
|
|
|
|
// end of compilation error checking
|
|
//System.setErr(systemErr);
|
|
System.setErr(PdeEditorConsole.consoleErr);
|
|
//System.err.println("success = " + success);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
// part of PdeEngine
|
|
public void start(Point windowLocation) throws PdeException {
|
|
int numero1 = (int) (Math.random() * 10000);
|
|
int numero2 = (int) (Math.random() * 10000);
|
|
tempClass = TEMP_CLASS + "_" + numero1 + "_" + numero2;
|
|
//System.out.println("KjcEngine.started");
|
|
writeJava(tempClass, true);
|
|
//System.err.println("KjcEngine wrote java");
|
|
//System.out.println("thread active count is " + Thread.activeCount());
|
|
|
|
|
|
//System.out.println("starting");
|
|
|
|
/*
|
|
if (!success) {
|
|
if (exception != null) {
|
|
throw exception;
|
|
} else {
|
|
throw new PdeException("KjcEngine.start uncaught problem [1]");
|
|
}
|
|
} else if (exception != null) {
|
|
throw new PdeException("KjcEngine.start uncaught problem [2]");
|
|
}
|
|
*/
|
|
//System.setErr(PdeEditorConsole.systemErr);
|
|
boolean result = compileJava();
|
|
//System.setErr(PdeEditorConsole.consoleErr);
|
|
if (!result) return;
|
|
//System.err.println("compiling failed.. was error caught? ");
|
|
//System.err.println(exception);
|
|
//if (!success) return;
|
|
|
|
//System.out.println("done compiling");
|
|
|
|
//System.err.println("system err is working");
|
|
|
|
messageMode = RUNNING;
|
|
Frame frame = editor.frame;
|
|
Point parentLoc = frame.getLocation();
|
|
Insets parentInsets = frame.getInsets();
|
|
|
|
int x1 = parentLoc.x - 20;
|
|
//int y1 = parentLoc.y + parentInsets.top; // for Window version
|
|
int y1 = parentLoc.y; // + parentInsets.top;
|
|
|
|
// then instantiate class poo using class.forName
|
|
try {
|
|
if (PdeBase.getBoolean("play.external", false)) {
|
|
String cmd = PdeBase.get("play.externalCommand");
|
|
|
|
//System.out.println(
|
|
process = Runtime.getRuntime().exec(/*"cmd /c " +*/ cmd + " " + tempClass +
|
|
" " + x1 + " " + y1);
|
|
new KjcMessageSiphon(process.getInputStream(),
|
|
process.getErrorStream(), leechErr);
|
|
|
|
//tempClass + " " + portnum);
|
|
//umbilical = new ServerSocket(portnum);
|
|
//umbilical.accept();
|
|
//portnum++;
|
|
|
|
//InputStream is = process.getErrorStream();
|
|
//InputStream is = process.getInputStream();
|
|
//while (true) {
|
|
//System.out.print((char) is.read());
|
|
//}
|
|
|
|
} else {
|
|
// temporarily disabled
|
|
//KjcClassLoader loader = new KjcClassLoader(buildPath);
|
|
//Class c = loader.loadClass(tempClass);
|
|
Class c = Class.forName(tempClass);
|
|
|
|
applet = (KjcApplet) c.newInstance();
|
|
//((KjcApplet)applet).errStream = leechErr;
|
|
applet.setEngine(this);
|
|
applet.init();
|
|
applet.start();
|
|
|
|
if (editor.presenting) {
|
|
window = new Window(new Frame());
|
|
} else {
|
|
window = new Frame(); // gonna use ugly windows instead
|
|
((Frame)window).setResizable(false);
|
|
window.pack(); // to get a peer, size set later, need for insets
|
|
|
|
window.addWindowListener(new WindowAdapter() {
|
|
public void windowClosing(WindowEvent e) {
|
|
//System.exit(0);
|
|
editor.doClose();
|
|
}
|
|
});
|
|
}
|
|
if (!(window instanceof Frame)) y1 += parentInsets.top;
|
|
window.add(applet);
|
|
|
|
// @#$((* java 1.3
|
|
// removed because didn't seem to be needed anymore
|
|
// also, was causing offset troubles
|
|
/*
|
|
window.addMouseListener(applet);
|
|
window.addMouseMotionListener(applet);
|
|
window.addKeyListener(applet);
|
|
*/
|
|
|
|
Dimension screen =
|
|
Toolkit.getDefaultToolkit().getScreenSize();
|
|
|
|
//System.out.println(SystemColor.windowBorder.toString());
|
|
|
|
//window.setLayout(new BorderLayout());
|
|
window.setLayout(null);
|
|
if (editor.presenting) {
|
|
window.setBounds((screen.width - applet.width) / 2,
|
|
(screen.height - applet.height) / 2,
|
|
applet.width, applet.height);
|
|
applet.setBounds(0, 0, applet.width, applet.height);
|
|
|
|
} else {
|
|
Insets insets = window.getInsets();
|
|
//System.out.println(insets);
|
|
int mw = PdeBase.getInteger("run.window.width.minimum", 120);
|
|
int mh = PdeBase.getInteger("run.window.height.minimum", 120);
|
|
int ww = Math.max(applet.width, mw) + insets.left + insets.right;
|
|
int wh = Math.max(applet.height, mh) + insets.top + insets.bottom;
|
|
window.setBounds(x1 - ww, y1, ww, wh);
|
|
|
|
Color windowBgColor =
|
|
PdeBase.getColor("run.window.bgcolor", SystemColor.control);
|
|
//new Color(102, 102, 102));
|
|
window.setBackground(windowBgColor);
|
|
//window.setBackground(SystemColor.windowBorder);
|
|
//window.setBackground(SystemColor.control);
|
|
|
|
applet.setBounds((ww - applet.width)/2,
|
|
insets.top + ((wh-insets.top-insets.bottom) -
|
|
applet.height)/2, ww, wh);
|
|
/*
|
|
window.setBounds(x1 - applet.width, y1,
|
|
//parentLoc.x - (applet.width + 20),
|
|
//parentLoc.y + parentInsets.top,
|
|
applet.width, applet.height);
|
|
*/
|
|
}
|
|
|
|
//new WindowDragger(window, applet.height);
|
|
/*
|
|
window.add(new MouseMotionAdapter() {
|
|
int px, py;
|
|
|
|
public mouseDragged(MouseEvent e) {
|
|
}
|
|
});
|
|
*/
|
|
|
|
/*
|
|
window.addWindowListener(new WindowAdapter() {
|
|
public void windowOpened(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowClosing(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowClosed(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowIconified(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowDeiconified(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowActivated(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void windowDeactivated(WindowEvent e) {
|
|
System.out.println(e);
|
|
}
|
|
});
|
|
*/
|
|
|
|
/*
|
|
window.addComponentListener(new ComponentAdapter() {
|
|
public void componentResized(ComponentEvent e) {
|
|
Frame f = (Frame) e.getComponent(); // me
|
|
Rectangle bounds = f.getBounds();
|
|
Insets insets = f.getInsets();
|
|
System.out.println(insets);
|
|
|
|
if ((bounds.x == -insets.left) &&
|
|
(bounds.y == -insets.bottom)) { // half-assed maximizing
|
|
|
|
Dimension screen =
|
|
Toolkit.getDefaultToolkit().getScreenSize();
|
|
|
|
//System.out.println(f.getInsets());
|
|
//System.out.println(e.getComponent().getClass());
|
|
System.out.println("asking for bounds " +
|
|
(screen.height + insets.top + insets.bottom));
|
|
f.setBounds(-insets.left, -insets.top,
|
|
screen.width + insets.left + insets.right,
|
|
screen.height + insets.top + insets.bottom);
|
|
|
|
f.doLayout();
|
|
// center the applet in the window
|
|
|
|
}
|
|
System.out.println(e);
|
|
}
|
|
|
|
public void componentMoved(ComponentEvent e) {
|
|
//System.out.println(e);
|
|
}
|
|
|
|
public void componentShown(ComponentEvent e) {
|
|
//System.out.println(e);
|
|
}
|
|
|
|
public void componentHidden(ComponentEvent e) {
|
|
//System.out.println(e);
|
|
}
|
|
});
|
|
|
|
window.add(applet, BorderLayout.CENTER);
|
|
window.add(new Label(), BorderLayout.NORTH);
|
|
window.add(new Label(), BorderLayout.SOUTH);
|
|
window.add(new Label(), BorderLayout.EAST);
|
|
window.add(new Label(), BorderLayout.WEST);
|
|
*/
|
|
|
|
//window.pack();
|
|
applet.setVisible(true); // no effect
|
|
if (windowLocation != null) {
|
|
window.setLocation(windowLocation);
|
|
}
|
|
window.show();
|
|
applet.requestFocus(); // necessary for key events
|
|
}
|
|
running = true;
|
|
|
|
//while (running) { }
|
|
// since this is already contained in a thread
|
|
//applet.run();
|
|
|
|
//need to parse this code to give a decent error message
|
|
|
|
//internal error
|
|
//java.lang.NullPointerException
|
|
// at ProcessingApplet.colorMode(ProcessingApplet.java:652)
|
|
// at Temporary_203_1176.setup(Temporary_203_1176.java:3)
|
|
|
|
} catch (Exception e) {
|
|
// this will pass through to the first part of message
|
|
// this handles errors that happen inside setup()
|
|
newMessage = true;
|
|
e.printStackTrace(leechErr);
|
|
//if (exception != null) throw exception;
|
|
}
|
|
}
|
|
|
|
|
|
//public void front() { // part of PdeEngine
|
|
//window.toFront();
|
|
//}
|
|
|
|
|
|
protected void cleanup() {
|
|
File buildDir = new File(buildPath);
|
|
if (!buildDir.exists()) buildDir.mkdirs();
|
|
|
|
String list[] = buildDir.list();
|
|
for (int i = 0; i < list.length; i++) {
|
|
if (list[i].equals("..") || list[i].equals("."))
|
|
continue;
|
|
//System.out.println("removing: " + buildDir + " " + list[i]);
|
|
//deadMan.delete();
|
|
new File(buildDir, list[i]).delete();
|
|
}
|
|
|
|
/*
|
|
try {
|
|
//System.out.println("cleaning up");
|
|
File file = new File("lib/" + tempClassFilename);
|
|
//File file = new File(tempClassDir, tempClassFilename);
|
|
if (file.exists()) file.delete();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
try {
|
|
File file = new File(tempFilename);
|
|
//File file = new File(tempDir, tempFilename);
|
|
if (file.exists()) file.delete();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
public void stop() { // part of PdeEngine
|
|
//System.out.println("PdeEngine.stop");
|
|
running = false;
|
|
|
|
//System.out.println();
|
|
//System.out.println("* stopping");
|
|
|
|
// in case stop is called during compilation
|
|
if (applet != null) applet.stop();
|
|
//if (window != null) window.hide();
|
|
|
|
// above avoids NullPointerExceptions
|
|
// but still threading is too complex, and so
|
|
// some boogers are being left behind
|
|
|
|
applet = null;
|
|
//window = null;
|
|
|
|
if (process != null) { // running externally
|
|
//System.out.println("killing external process");
|
|
//process.destroy();
|
|
|
|
//System.out.println("cutting umbilical cord");
|
|
try {
|
|
FileOutputStream fos = new FileOutputStream("die");
|
|
fos.close();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
//try {
|
|
//umbilical.close();
|
|
//umbilical = null;
|
|
//} catch (IOException e) {
|
|
//e.printStackTrace();w
|
|
//}
|
|
}
|
|
|
|
cleanup();
|
|
|
|
//System.gc();
|
|
//System.out.println("* stopped");
|
|
|
|
//System.out.println("thread count: " + Thread.activeCount());
|
|
//System.out.println();
|
|
//System.out.println();
|
|
}
|
|
|
|
|
|
public void close() { // part of PdeEngine
|
|
//if (window != null) window.hide();
|
|
if (window != null) {
|
|
//System.err.println("disposing window");
|
|
window.dispose();
|
|
window = null;
|
|
}
|
|
}
|
|
|
|
|
|
//public void inform(String message) {
|
|
//System.out.println("informing: " + message);
|
|
//}
|
|
}
|
|
|
|
|
|
class KjcClassLoader extends ClassLoader {
|
|
String basePath;
|
|
|
|
public KjcClassLoader(String basePath) {
|
|
this.basePath = basePath;
|
|
}
|
|
|
|
public synchronized Class loadClass(String className, boolean resolveIt)
|
|
throws ClassNotFoundException {
|
|
|
|
Class result;
|
|
byte classData[];
|
|
|
|
// Check the loaded class cache
|
|
result = findLoadedClass(className);
|
|
if (result != null) {
|
|
// Return a cached class
|
|
return result;
|
|
}
|
|
|
|
// Check with the primordial class loader
|
|
try {
|
|
result = super.findSystemClass(className);
|
|
// Return a system class
|
|
return result;
|
|
} catch (ClassNotFoundException e) { }
|
|
|
|
// Don't attempt to load a system file except through
|
|
// the primordial class loader
|
|
if (className.startsWith("java.")) {
|
|
throw new ClassNotFoundException();
|
|
}
|
|
|
|
// Try to load it from the basePath directory.
|
|
classData = getTypeFromBasePath(className);
|
|
if (classData == null) {
|
|
System.out.println("KjcClassLoader - Can't load class: " + className);
|
|
throw new ClassNotFoundException();
|
|
}
|
|
|
|
// Parse it
|
|
result = defineClass(className, classData, 0, classData.length);
|
|
if (result == null) {
|
|
System.out.println("KjcClassLoader - Class format error: " +
|
|
className);
|
|
throw new ClassFormatError();
|
|
}
|
|
|
|
if (resolveIt) {
|
|
resolveClass(result);
|
|
}
|
|
|
|
// Return class from basePath directory
|
|
return result;
|
|
}
|
|
|
|
private byte[] getTypeFromBasePath(String typeName) {
|
|
FileInputStream fis;
|
|
String fileName = basePath + File.separatorChar +
|
|
typeName.replace('.', File.separatorChar) + ".class";
|
|
|
|
try {
|
|
fis = new FileInputStream(fileName);
|
|
} catch (FileNotFoundException e) {
|
|
return null;
|
|
}
|
|
|
|
BufferedInputStream bis = new BufferedInputStream(fis);
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
|
try {
|
|
int c = bis.read();
|
|
while (c != -1) {
|
|
out.write(c);
|
|
c = bis.read();
|
|
}
|
|
} catch (IOException e) {
|
|
return null;
|
|
}
|
|
return out.toByteArray();
|
|
}
|
|
}
|
|
|
|
|
|
class KjcMessageSiphon implements Runnable {
|
|
InputStream input, error;
|
|
PrintStream leechErr;
|
|
Thread thread;
|
|
|
|
public KjcMessageSiphon(InputStream input, InputStream error,
|
|
PrintStream leechErr) {
|
|
this.input = input;
|
|
this.error = error;
|
|
|
|
thread = new Thread(this);
|
|
thread.start();
|
|
}
|
|
|
|
public void run() {
|
|
while (Thread.currentThread() == thread) {
|
|
try {
|
|
if (error.available() > 0) {
|
|
while (error.available() > 0) {
|
|
System.out.print((char)error.read());
|
|
}
|
|
error = null; // get out
|
|
throw new Exception();
|
|
}
|
|
|
|
while (input.available() > 0) {
|
|
System.out.print((char)input.read());
|
|
}
|
|
Thread.sleep(100);
|
|
|
|
/*
|
|
int c = error.read();
|
|
if (c == -1) {
|
|
error = null; // get out
|
|
throw new Exception();
|
|
}
|
|
System.out.print((char)c);
|
|
Thread.sleep(5);
|
|
*/
|
|
} catch (Exception e) {
|
|
if ((error != null) && (leechErr != null)) {
|
|
System.out.println("KjcMessageSiphon err " + e);
|
|
}
|
|
thread.stop();
|
|
thread = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class KjcMessageStream extends OutputStream {
|
|
KjcEngine parent;
|
|
|
|
public KjcMessageStream(KjcEngine parent) {
|
|
this.parent = parent;
|
|
}
|
|
|
|
public void close() { }
|
|
|
|
public void flush() { }
|
|
|
|
public void write(byte b[]) {
|
|
System.out.println("leech1: " + new String(b));
|
|
}
|
|
|
|
public void write(byte b[], int offset, int length) {
|
|
//System.out.println("leech2: " + new String(b));
|
|
parent.message(new String(b, offset, length));
|
|
}
|
|
|
|
public void write(int b) {
|
|
System.out.println("leech3: '" + ((char)b) + "'");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
class WindowDragger implements MouseListener, MouseMotionListener {
|
|
Window window;
|
|
int minY;
|
|
boolean inside;
|
|
|
|
int lastX, lastY;
|
|
|
|
// if drag starts outside window, this will break.. easy to fix
|
|
|
|
public WindowDragger(Window window, int minY) {
|
|
this.window = window;
|
|
this.minY = minY;
|
|
|
|
window.addMouseListener(this);
|
|
window.addMouseMotionListener(this);
|
|
}
|
|
|
|
public void mouseClicked(MouseEvent e) { }
|
|
|
|
public void mousePressed(MouseEvent e) {
|
|
lastX = e.getX();
|
|
lastY = e.getY();
|
|
inside = (lastY > minY);
|
|
System.out.println("inside = " + inside);
|
|
}
|
|
|
|
public void mouseReleased(MouseEvent e) { }
|
|
public void mouseEntered(MouseEvent e) { }
|
|
public void mouseExited(MouseEvent e) { }
|
|
|
|
public void mouseDragged(MouseEvent e) {
|
|
if (!inside) return;
|
|
|
|
System.out.println("inside, dragging");
|
|
Point location = window.getLocation();
|
|
int newX = e.getX();
|
|
int newY = e.getY();
|
|
window.setLocation(location.x + (newX-lastX),
|
|
location.y + (newY-lastY));
|
|
lastX = newX;
|
|
lastY = newY;
|
|
}
|
|
|
|
public void mouseMoved(MouseEvent e) { }
|
|
}
|
|
*/
|