From: crawshaw Date: Fri, 7 Jan 2005 20:05:25 +0000 (+0000) Subject: make core compile with new js stuff and Task replacement class X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=0db31fc0dc88749cd8022790fd475df8b7b06c27 make core compile with new js stuff and Task replacement class darcs-hash:20050107200525-2eb37-087bb88a5a78b4dfca033654a999f7ce85924633.gz --- diff --git a/src/org/ibex/core/Box.java b/src/org/ibex/core/Box.java index 7a332ea..ce0b4e7 100644 --- a/src/org/ibex/core/Box.java +++ b/src/org/ibex/core/Box.java @@ -41,7 +41,7 @@ import org.ibex.graphics.*; * trigger a Surface.abort; if rendering were done in the same pass, * rendering work done prior to the Surface.abort would be wasted. */ -public final class Box extends JS.Obj implements Task { +public final class Box extends JS.Obj implements Callable { private static final JS.Method METHOD = new JS.Method(); @@ -58,7 +58,7 @@ public final class Box extends JS.Obj implements Task { //#define CHECKSET_STRING(prop) if ((value==null&&prop==null)||(value!=null&&JSU.toString(value).equals(prop))) break; prop=JSU.toString(value); // FIXME memory leak - static Hash boxToCursor = new Hash(500, 3); + static Basket.Map boxToCursor = new Basket.HashMap(500, 3); static final Font DEFAULT_FONT; static { @@ -147,13 +147,14 @@ public final class Box extends JS.Obj implements Task { public final int fontSize() { return font == null ? DEFAULT_FONT.pointsize : font.pointsize; } /** invoked when a resource needed to render ourselves finishes loading */ - public void perform() throws JSExn { - if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return; } + public Object run(Object o) throws JSExn { + if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return null; } if (texture.isLoaded) { setWidth(max(texture.width, minwidth), maxwidth); setHeight(max(texture.height, minheight), maxheight); dirty(); } else { JS res = texture.stream; texture = null; throw new JSExn("image not found: "+res.unclone()); } + return null; } // FEATURE: use cx2/cy2 format @@ -243,7 +244,8 @@ public final class Box extends JS.Obj implements Task { void resize(int x, int y, int width, int height) { if (x == this.x && y == this.y && width == this.width && height == this.height) return; - boolean sizechange = (this.width != width || this.height != height) && hasTrap(SIZECHANGE); + boolean sizechange = (this.width != width || this.height != height); + try { sizechange = sizechange && getTrap(SIZECHANGE) != null; } catch (JSExn e) {} int thisx = parent == null ? 0 : this.x; int thisy = parent == null ? 0 : this.y; Box who = (parent == null ? this : parent); @@ -259,7 +261,7 @@ public final class Box extends JS.Obj implements Task { this.width = width; this.height = height; this.x = x; this.y = y; dirty(); } - if (sizechange) putAndTriggerTrapsAndCatchExceptions(SIZECHANGE, T); + if (sizechange) putAndTriggerTrapsAndCatchExceptions(SIZECHANGE, JSU.T); } private float targetColumnSize = (float)0.0; @@ -445,20 +447,19 @@ public final class Box extends JS.Obj implements Task { // Methods to implement org.ibex.js.JS ////////////////////////////////////// - public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { - switch (nargs) { + public JS call(JS method, JS[] args) throws JSExn { + switch (args.length) { case 1: { //#switch(JSU.toString(method)) case "indexof": - Box b = (Box)a0; + Box b = (Box)args[0]; if (b.parent != this) return (redirect == null || redirect == this) ? - JSU.N(-1) : - redirect.callMethod(method, a0, a1, a2, rest, nargs); + JSU.N(-1) : redirect.call(method, args); return JSU.N(b.getIndexInParent()); case "distanceto": - Box b = (Box)a0; + Box b = (Box)args[0]; JS ret = new JS.Obj(); ret.put(JSU.S("x"), JSU.N(b.localToGlobalX(0) - localToGlobalX(0))); ret.put(JSU.S("y"), JSU.N(b.localToGlobalY(0) - localToGlobalY(0))); @@ -467,7 +468,7 @@ public final class Box extends JS.Obj implements Task { //#end } } - return super.callMethod(method, a0, a1, a2, rest, nargs); + return super.call(method, args); } public JS get(JS name) throws JSExn { @@ -512,7 +513,7 @@ public final class Box extends JS.Obj implements Task { case "minheight": return JSU.N(minheight); case "maxheight": return JSU.N(maxheight); case "clip": return JSU.B(test(CLIP)); - case "visible": return JSU.B(test(VISIBLE) && (parent == null || (parent.get(JSU.S("visible")) == T))); + case "visible": return JSU.B(test(VISIBLE) && (parent == null || (parent.get(JSU.S("visible")) == JSU.T))); case "packed": return JSU.B(test(PACKED)); case "globalx": return JSU.N(localToGlobalX(0)); case "globaly": return JSU.N(localToGlobalY(0)); @@ -523,14 +524,14 @@ public final class Box extends JS.Obj implements Task { throw new JSExn("you cannot read from the box.mouse property in background thread context"); return new Mouse(); case "numchildren": return redirect == null ? JSU.N(0) : redirect == this ? JSU.N(treeSize()) : redirect.get(JSU.S("numchildren")); - case "redirect": return redirect == null ? null : redirect == this ? T : redirect.get(JSU.S("redirect")); + case "redirect": return redirect == null ? null : redirect == this ? JSU.T : redirect.get(JSU.S("redirect")); case "Minimized": if (parent == null && getSurface() != null) return JSU.B(getSurface().minimized); default: return super.get(name); //#end throw new Error("unreachable"); // unreachable } - private class Mouse extends JS implements JS.Cloneable { + private class Mouse extends JS.Immutable implements JS.Cloneable { public JS get(JS key) throws JSExn { //#switch(JSU.toString(key)) case "x": return JSU.N(globalToLocalX(getSurface()._mousex)); @@ -539,7 +540,7 @@ public final class Box extends JS.Obj implements Task { // this might not get recomputed if we change mousex/mousey... case "inside": return JSU.B(test(MOUSEINSIDE)); //#end - return null; + return super.get(key); } } @@ -698,7 +699,7 @@ public final class Box extends JS.Obj implements Task { case "bottom": set(ALIGN_BOTTOM); case "left": set(ALIGN_LEFT); case "right": set(ALIGN_RIGHT); - default: JSU.log("invalid alignment \"" + JSU.debugToString(value) + "\""); + default: JSU.log("invalid alignment \"" + JSU.str(value) + "\""); //#end } @@ -729,7 +730,7 @@ public final class Box extends JS.Obj implements Task { if (texture == newtex) return; texture = newtex; fillcolor = 0; - if (texture != null && texture.isLoaded) perform(); + if (texture != null && texture.isLoaded) run(null); } dirty(); } @@ -748,12 +749,12 @@ public final class Box extends JS.Obj implements Task { boolean isinside = test(VISIBLE) && inside(x, y) && !obscured; if (!wasinside && isinside) { set(MOUSEINSIDE); - putAndTriggerTrapsAndCatchExceptions(JSU.S("Enter"), T); + putAndTriggerTrapsAndCatchExceptions(JSU.S("Enter"), JSU.T); } if (isinside && test(CURSOR)) getSurface().cursor = (String)boxToCursor.get(this); if (wasinside && !isinside) { clear(MOUSEINSIDE); - putAndTriggerTrapsAndCatchExceptions(JSU.S("Leave"), T); + putAndTriggerTrapsAndCatchExceptions(JSU.S("Leave"), JSU.T); } boolean found = false; @@ -936,10 +937,10 @@ public final class Box extends JS.Obj implements Task { try { putAndTriggerTraps(name, val); } catch (JSExn e) { - JSU.log("caught js exception while putting to trap \""+ JSU.debugToString(name)+"\""); + JSU.log("caught js exception while putting to trap \""+ JSU.str(name)+"\""); JSU.log(e); } catch (Exception e) { - JSU.log("caught exception while putting to trap \""+ JSU.debugToString(name)+"\""); + JSU.log("caught exception while putting to trap \""+ JSU.str(name)+"\""); JSU.log(e); } } diff --git a/src/org/ibex/core/Ibex.java b/src/org/ibex/core/Ibex.java index 57fe96d..a157239 100644 --- a/src/org/ibex/core/Ibex.java +++ b/src/org/ibex/core/Ibex.java @@ -45,14 +45,12 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { Sub(JS key) { this.key = key; } public void put(JS key, JS val) throws JSExn { Ibex.this.put(JSU.S(JSU.toString(this.key) + "." + JSU.toString(key)), val); } public JS get(JS key) throws JSExn { return Ibex.this.get(JSU.S(JSU.toString(this.key) + "." + JSU.toString(key))); } - public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { - return Ibex.this.callMethod(this.key, a0, a1, a2, rest, nargs); - } - public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { - return Ibex.this.callMethod(JSU.S(JSU.toString(this.key) + "." + JSU.toString(method)), a0, a1, a2, rest, nargs); + public JS call(JS[] args) throws JSExn { return Ibex.this.call(this.key, args); } + public JS call(JS method, JS[] args) throws JSExn { + return Ibex.this.call(JSU.S(JSU.toString(this.key) + "." + JSU.toString(method)), args); } } - private Cache subCache = new Cache(20); + private Cache subCache = new Cache(20, true); private Sub getSub(JS key) { Sub ret = (Sub)subCache.get(key); if (ret == null) subCache.put(key, ret = new Sub(key)); @@ -61,7 +59,7 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { public JS get(JS name) throws JSExn { // FIXME: SHouldn't need this (just trap [""]) - if (JS.isString(name) && JSU.toString(name).length() == 0) return rr; + if (JSU.isString(name) && JSU.toString(name).length() == 0) return rr; // FEATURE: Preprocessor hack to generate specialized JS instances (avoid all this string concatenation) //#switch(JSU.toString(name)) case "math": return ibexMath; @@ -82,10 +80,10 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { case "ui.browser": return METHOD; case "ui.mouse": return getSub(name); case "ui.mouse.button": - if (Surface.button1 && !Surface.button2 && !Surface.button3) return N(1); - else if (!Surface.button1 && Surface.button2 && !Surface.button3) return N(2); - else if (!Surface.button1 && !Surface.button2 && Surface.button3) return N(3); - else return ZERO; + if (Surface.button1 && !Surface.button2 && !Surface.button3) return JSU.N(1); + else if (!Surface.button1 && Surface.button2 && !Surface.button3) return JSU.N(2); + else if (!Surface.button1 && !Surface.button2 && Surface.button3) return JSU.N(3); + else return JSU.ZERO; case "ui.key": return getSub(name); case "ui.key.name": return getSub(name); case "ui.key.name.alt": return JSU.S(Platform.altKeyName()); @@ -93,10 +91,10 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { case "ui.key.control": return Surface.control ? JSU.T : JSU.F; case "ui.key.shift": return Surface.shift ? JSU.T : JSU.F; case "ui.clipboard": return JSU.S((String)Platform.getClipBoard()); - case "ui.maxdim": return N(Short.MAX_VALUE); + case "ui.maxdim": return JSU.N(Short.MAX_VALUE); case "ui.screen": return getSub(name); - case "ui.screen.width": return N(Platform.getScreenWidth()); - case "ui.screen.height": return N(Platform.getScreenHeight()); + case "ui.screen.width": return JSU.N(Platform.getScreenWidth()); + case "ui.screen.height": return JSU.N(Platform.getScreenHeight()); case "undocumented": return getSub(name); case "undocumented.initialOrigin": return JSU.S(Main.origin); case "undocumented.initialTemplate": return JSU.S(Main.initialTemplate); @@ -134,7 +132,7 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { public void put(JS name, JS value) throws JSExn { //#switch(JSU.toString(name)) - case "thread": Scheduler.add((Task)value); return; + case "thread": Scheduler.add((Callable)value); return; case "ui.clipboard": Platform.setClipBoard(JSU.toString(value)); return; case "ui.frame": Platform.createSurface((Box)value, true, true); return; case "ui.window": Platform.createSurface((Box)value, false, true); return; @@ -146,41 +144,45 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { throw new JSExn("attempted to put unknown property: ibex."+name); } - public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn { + public JS call(JS method, JS[] args) throws JSExn { try { - //#switch(JSU.toString(name)) - case "date": return new JSDate(a, b, c, rest, nargs); - case "net.rpc.soap": return new SOAP(JSU.toString(a), "", JSU.toString(b), JSU.toString(c)); + //#switch(JSU.toString(method)) + case "date": return new JSDate(args); + case "net.rpc.soap": return new SOAP( + args.length < 1 ? null : JSU.toString(args[0]), + "", + args.length < 2 ? null : JSU.toString(args[1]), + args.length < 3 ? null : JSU.toString(args[2])); // FIXME support object dumping - case "log.debug": JS.debug(a== null ? "**null**" : JS.debugToString(a)); return null; - case "log.info": JS.info(a== null ? "**null**" : JS.debugToString(a)); return null; - case "log.warn": JS.warn(a== null ? "**null**" : JS.debugToString(a)); return null; - case "log.error": JS.error(a== null ? "**null**" : JS.debugToString(a)); return null; + case "log.debug": JSU.debug(args.length < 1 ? "**null**" : JSU.str(args[0])); return null; + case "log.info": JSU.info(args.length < 1 ? "**null**" : JSU.str(args[0])); return null; + case "log.warn": JSU.warn(args.length < 1 ? "**null**" : JSU.str(args[0])); return null; + case "log.error": JSU.error(args.length < 1 ? "**null**" : JSU.str(args[0])); return null; //#end - switch (nargs) { + switch (args.length) { case 0: - //#switch(JSU.toString(name)) + //#switch(JSU.toString(method)) case "thread.yield": sleep(0); return null; //#end break; case 1: - //#switch(JSU.toString(name)) + //#switch(JSU.toString(method)) case "clone": - if(a == null) throw new JSExn("can't clone the null value"); - return ((JS)a).jsclone(); - case "bless": return bless((JS)a); - case "ui.browser": Platform.newBrowserWindow(JSU.toString(a)); return null; - case "stream.unzip": return a == null ? null : new Stream.Zip((Stream)a); + if(args[0] == null) throw new JSExn("can't clone the null value"); + return new JS.Clone((JS)args[0]); + case "bless": return bless((JS)args[0]); + case "ui.browser": Platform.newBrowserWindow(JSU.toString(args[0])); return null; + case "stream.unzip": return args[0] == null ? null : new Stream.Zip((Stream)args[0]); //case "stream.uncab": return a == null ? null : new Stream.Cab(a); case "stream.cache": - try { return a == null ? null : new Stream.CachedStream((Stream)a, "resources", true); } + try { return args[0] == null ? null : new Stream.CachedStream((Stream)args[0], "resources", true); } catch (Stream.NotCacheableException e) { throw new JSExn("this resource cannot be cached"); } case "stream.url": { - String url = JSU.toString(a); + String url = JSU.toString(args[0]); if (url.startsWith("http://")) return new Stream.HTTP(url); else if (url.startsWith("https://")) return new Stream.HTTP(url); - else if (url.startsWith("data:")) return new Stream.ByteArray(Base64.decode(url.substring(5)), null); + else if (url.startsWith("data:")) return new Stream.ByteArray(Encode.fromBase64(url.substring(5)), null); else if (url.startsWith("utf8:")) return new Stream.ByteArray(url.substring(5).getBytes(), null); else if (url.startsWith("file:")) { // FIXME @@ -188,47 +190,47 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { } throw new JSExn("invalid resource specifier " + url); } - case "thread.sleep": sleep(JS.toInt(a)); return null; - case "regexp": return new JSRegexp(a, null); - case "net.rpc.xml": return new XMLRPC(JSU.toString(a), ""); + case "thread.sleep": sleep(JSU.toInt(args[0])); return null; + case "regexp": return new JSRegexp(args[0], null); + case "net.rpc.xml": return new XMLRPC(JSU.toString(args[0]), ""); case "crypto.rsa": /* FEATURE */ return null; case "crypto.md5": /* FEATURE */ return null; case "crypto.sha1": /* FEATURE */ return null; case "crypto.rc4": /* FEATURE */ return null; case "stream.parse.html": throw new JSExn("not implemented yet"); //return null; - case "stream.parse.xml": if(a == null) return null; new XMLHelper(b).doParse(a); return null; + case "stream.parse.xml": if(args[0] == null) return null; new XMLHelper(args[1]).doParse(args[0]); return null; // FIXME backgrounding - case "stream.parse.utf8": if(a == null) return null; - try { return JSU.S(new String(InputStreamToByteArray.convert(a.getInputStream()))); } + case "stream.parse.utf8": if(args[0] == null) return null; + try { return JSU.S(new String(InputStreamToByteArray.convert(args[0].getInputStream()))); } catch (Exception e) { Log.warn(this, e); } //#end break; case 2: - //#switch(JSU.toString(name)) - case "stream.watch": return new Stream.ProgressWatcher((Stream)a, b); - case "regexp": return new JSRegexp(a, b); + //#switch(JSU.toString(method)) + case "stream.watch": return new Stream.ProgressWatcher((Stream)args[0], args[1]); + case "regexp": return new JSRegexp(args[0], args[1]); //#end case 3: - //#switch(JSU.toString(name)) - case "ui.font.height": return N(Font.getFont(a, JS.toInt(b)).textheight(JSU.toString(c))); + //#switch(JSU.toString(method)) + case "ui.font.height": return JSU.N(Font.getFont(args[0], JSU.toInt(args[1])).textheight(JSU.toString(args[3]))); case "ui.font.wait": throw new Error("FIXME: ibex.ui.font.wait not implemented"); - case "ui.font.width": return N(Font.getFont(a, JS.toInt(b)).textwidth(JSU.toString(c))); + case "ui.font.width": return JSU.N(Font.getFont(args[0], JSU.toInt(args[1])).textwidth(JSU.toString(args[3]))); //#end break; } } catch (RuntimeException e) { // FIXME: maybe JSExn should take a second argument, Exception - Log.warn(this, "ibex."+name+"() threw: " + e); - throw new JSExn("invalid argument for ibex object method "+name+"()"); + Log.warn(this, "ibex."+method+"() threw: " + e); + throw new JSExn("invalid argument for ibex object method "+method+"()"); } - throw new JSExn("invalid number of arguments ("+nargs+") for ibex object method "+name+"()"); + throw new JSExn("invalid number of arguments ("+args.length+") for ibex object method "+method+"()"); } public JS url2res(String url) throws JSExn { if (url.startsWith("http://")) return new Stream.HTTP(url); else if (url.startsWith("https://")) return new Stream.HTTP(url); - else if (url.startsWith("data:")) return new Stream.ByteArray(Base64.decode(url.substring(5)), null); + else if (url.startsWith("data:")) return new Stream.ByteArray(Encode.fromBase64(url.substring(5)), null); else if (url.startsWith("utf8:")) return new Stream.ByteArray(url.substring(5).getBytes(), null); else throw new JSExn("invalid resource specifier " + url); // FIXME support file:// via dialog boxes @@ -236,18 +238,18 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { public static void sleep(final int i) throws JSExn { try { - final JS.UnpauseCallback callback = JS.pause(); + final Pausable callback = JSU.pause(); // FEATURE use a single sleeper thread new Thread() { public void run() { try { Thread.sleep(i); } catch (InterruptedException e) { } Scheduler.add(callback); } }.start(); - } catch (JSU.NotPauseableException npe) { + } catch (Pausable.NotPausableException npe) { throw new JSExn("you cannot sleep or yield in the foreground thread"); } } - public static final JS ibexMath = new JS.Obj() { + public static final JS ibexMath = new JS.Immutable() { // FEATURE: find a cleaner way to do this private JS gs = /*new JSScope.Global();*/ null; // FIXME: Global scope public JS get(JS key) throws JSExn { @@ -257,16 +259,16 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { case "NaN": return METHOD; case "Infinity": return METHOD; //#end - return MATH.get(key); + return JSU.MATH.get(key); } - public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn { - //#switch(JSU.toString(name)) - case "isNaN": return gs.callMethod(name,a,b,c,rest,nargs); - case "isFinite": return gs.callMethod(name,a,b,c,rest,nargs); - case "NaN": return gs.callMethod(name,a,b,c,rest,nargs); - case "Infinity": return gs.callMethod(name,a,b,c,rest,nargs); + public JS call(JS method, JS[] args) throws JSExn { + //#switch(JSU.toString(method)) + case "isNaN": return gs.call(method, args); + case "isFinite": return gs.call(method, args); + case "NaN": return gs.call(method, args); + case "Infinity": return gs.call(method, args); //#end - return MATH.callMethod(name,a,b,c,rest,nargs); + return JSU.MATH.call(method, args); } }; @@ -286,19 +288,19 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { //#end return super.get(key); } - public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn { - //#switch(JSU.toString(name)) - case "parseInt": return gs.callMethod(name,a,b,c,rest,nargs); - case "parseFloat": return gs.callMethod(name,a,b,c,rest,nargs); - case "decodeURI": return gs.callMethod(name,a,b,c,rest,nargs); - case "decodeURIComponent": return gs.callMethod(name,a,b,c,rest,nargs); - case "encodeURI": return gs.callMethod(name,a,b,c,rest,nargs); - case "encodeURIComponent": return gs.callMethod(name,a,b,c,rest,nargs); - case "escape": return gs.callMethod(name,a,b,c,rest,nargs); - case "unescape": return gs.callMethod(name,a,b,c,rest,nargs); - case "fromCharCode": return gs.callMethod(name,a,b,c,rest,nargs); + public JS callMethod(JS method, JS[] args) throws JSExn { + //#switch(JSU.toString(method)) + case "parseInt": return gs.call(method, args); + case "parseFloat": return gs.call(method, args); + case "decodeURI": return gs.call(method, args); + case "decodeURIComponent": return gs.call(method, args); + case "encodeURI": return gs.call(method, args); + case "encodeURIComponent": return gs.call(method, args); + case "escape": return gs.call(method, args); + case "unescape": return gs.call(method, args); + case "fromCharCode": return gs.call(method, args); //#end - return super.callMethod(name,a,b,c,rest,nargs); + return super.call(method, args); } }; @@ -306,31 +308,41 @@ public final class Ibex extends JS.Obj implements JS.Cloneable { private class Wrapper extends XML.Exn { public JSExn wrapee; public Wrapper(JSExn jse) { super(""); wrapee = jse; } } private JS characters, whitespace, endElement, startElement; public XMLHelper(JS b) throws JSExn { - super(BUFFER_SIZE); + super(BUFFER_SIZE, true); startElement = b.getAndTriggerTraps(JSU.S("startElement")); endElement = b.getAndTriggerTraps(JSU.S("endElement")); characters = b.getAndTriggerTraps(JSU.S("characters")); whitespace = b.getAndTriggerTraps(JSU.S("whitespace")); } - public void startElement(XML.Element c) throws XML.Exn { try { - JS attrs = new JS.O(); + private final JS[] callargs1= new JS[1], callargs2= new JS[2], callargs3= new JS[3]; + public void startElement(Tree.Element c) throws XML.Exn { try { + Tree.Attributes a = c.getAttributes(); + JS attrs = new JS.Obj(); // FIXME attribute URIs? add an additional hash? - for(int i=0; i 0)) { - switch (JS.toString(val).charAt(0)) { + if (JSU.isString(val) && (JSU.toString(val).length() > 0)) { + switch (JSU.toString(val).charAt(0)) { case '$': val = pis.get(val); - if (val == null) throw new JSExn("unknown box id '"+JS.toString(vals[i])+"' referenced in XML attribute"); + if (val == null) throw new JSExn("unknown box id '"+JSU.str(vals[i])+"' referenced in XML attribute"); break; case '.': - val = ibex.resolveString(JS.toString(val).substring(1), false); + val = ibex.resolveString(JSU.toString(val).substring(1), false); // FIXME: url case // FIXME: should we be resolving all of these in the XML-parsing code? } @@ -141,12 +142,13 @@ public class Template { /** handles XML parsing; builds a Template tree as it goes */ static final class TemplateHelper extends XML { - String sourceName; + String sourceName; private int state = STATE_INITIAL; private static final int STATE_INITIAL = 0; private static final int STATE_IN_ROOT_NODE = 1; private static final int STATE_IN_TEMPLATE_NODE = 2; private static final int STATE_IN_META_NODE = 3; + private static final JS[] callempty = new JS[0]; StringBuffer static_content = null; int static_content_start = 0; @@ -157,41 +159,39 @@ public class Template { String initial_uri = ""; - public TemplateHelper(String sourceName, JS s, Ibex ibex) throws XML.Exn, IOException, JSExn { + public TemplateHelper(String sourceName, JS s, Ibex ibex) throws XML.Exn, IOException, JSExn { this.sourceName = sourceName; this.ibex = ibex; InputStream is = s.getInputStream(); Ibex.Blessing b = Ibex.Blessing.getBlessing(s).parent; while(b != null) { - if(b.parentkey != null) initial_uri = JS.toString(b.parentkey) + (initial_uri.equals("") ? "" : "." + initial_uri); + if(b.parentkey != null) initial_uri = JSU.toString(b.parentkey) + (initial_uri.equals("") ? "" : "." + initial_uri); b = b.parent; } initial_uri = ""; parse(new InputStreamReader(is)); JS staticScript = parseScript(static_content, static_content_start); - t.staticObject = new JS.O(); + t.staticObject = new JS.Obj(); JS staticScope = new PerInstantiationScope(null, ibex, null, t.staticObject); - if (staticScript != null) JS.cloneWithNewGlobalScope(staticScript, staticScope).call(null, null, null, null, 0); + if (staticScript != null) JSU.cloneWithNewGlobalScope(staticScript, staticScope).call(callempty); } private JS parseScript(StringBuffer content, int content_start) throws IOException { if (content == null) return null; String contentString = content.toString(); - if (contentString.trim().length() > 0) return JS.fromReader(sourceName, content_start, new StringReader(contentString)); + if (contentString.trim().length() > 0) return JSU.fromReader(sourceName, content_start, new StringReader(contentString)); return null; } - public void startElement(XML.Element c) throws XML.Exn { + public void startElement(Tree.Element c) throws XML.Exn { + Tree.Attributes a = c.getAttributes(); switch(state) { case STATE_IN_META_NODE: { meta++; return; } case STATE_INITIAL: if (!"ibex".equals(c.getLocalName())) throw new XML.Exn("root element was not ", XML.Exn.SCHEMA, getLine(), getCol()); - if (c.getAttrLen() != 0) + if (a.attrSize() != 0) throw new XML.Exn("root element must not have attributes", XML.Exn.SCHEMA, getLine(), getCol()); - if (c.getUri("ui") == null || "".equals(c.getUri("ui"))) c.addUri("ui", "ibex://ui"); - if (c.getUri("meta") == null || "".equals(c.getUri("meta"))) c.addUri("meta", "ibex://meta"); - if (c.getUri("") == null || "".equals(c.getUri(""))) c.addUri("", initial_uri); state = STATE_IN_ROOT_NODE; return; case STATE_IN_ROOT_NODE: @@ -219,15 +219,15 @@ public class Template { Log.error(Template.class, e); } } - - Hash urimap = c.getUriMap(); - t.urikeys = new String[urimap.size()]; - t.urivals = new String[urimap.size()]; - Enumeration uriEnumeration = urimap.keys(); + + Tree.Prefixes prefixes = c.getPrefixes(); + t.urikeys = new String[prefixes.pfxSize()]; + t.urivals = new String[prefixes.pfxSize()]; + int ii = 0; - while(uriEnumeration.hasMoreElements()) { - String key = (String)uriEnumeration.nextElement(); - String val = (String)urimap.get(key); + for (int i=0; i < prefixes.pfxSize(); i++) { + String key = prefixes.getPrefixKey(i); + String val = prefixes.getPrefixVal(i); if (val.equals("ibex://ui")) continue; if (val.equals("ibex://meta")) continue; t.urikeys[ii] = key; @@ -235,29 +235,30 @@ public class Template { t.urivals[ii] = val; ii++; } - - Vec keys = new Vec(c.getAttrLen()); - Vec vals = new Vec(c.getAttrLen()); + + // FIXME: 2-value Array + Basket.Array keys = new Basket.Array(a.attrSize()); + Basket.Array vals = new Basket.Array(a.attrSize()); // process attributes into Vecs, dealing with any XML Namespaces in the process - ATTR: for (int i=0; i < c.getAttrLen(); i++) { - if (c.getAttrKey(i).equals("id")) { - t.id = c.getAttrVal(i).toString().intern(); + ATTR: for (int i=0; i < a.attrSize(); i++) { + if (a.getKey(i).equals("id")) { + t.id = a.getVal(i).toString().intern(); continue ATTR; } // treat value starting with '.' as resource reference - String uri = c.getAttrUri(i); if (!uri.equals("")) uri = '.' + uri; - keys.addElement(c.getAttrKey(i)); - vals.addElement((c.getAttrVal(i).startsWith(".") ? uri : "") + c.getAttrVal(i)); + String uri = a.getUri(i); if (!uri.equals("")) uri = '.' + uri; + keys.add(a.getKey(i)); + vals.add((a.getVal(i).startsWith(".") ? uri : "") + a.getVal(i)); } if (keys.size() == 0) return; // sort the attributes lexicographically - Vec.sort(keys, vals, new Vec.CompareFunc() { public int compare(Object a, Object b) { - return ((String)a).compareTo((String)b); - } }); + Basket.Array.sort(keys, vals, new Basket.CompareFunc() { + public int compare(Object a, Object b) { return ((String)a).compareTo((String)b); } + }, 0, keys.size()); t.keys = new JS[keys.size()]; t.vals = new JS[vals.size()]; @@ -265,8 +266,8 @@ public class Template { // convert attributes to appropriate types and intern strings for(int i=0; i + private static Basket.Map fonts = new Basket.HashMap(); public static Font getFont(JS stream, int pointsize) { - Font ret = (Font)fontCache.get(stream, new Integer(pointsize)); - if (ret == null) fontCache.put(stream, new Integer(pointsize), ret = new Font(stream, pointsize)); + Basket.Map m = (Basket.Map)fonts.get(stream); + Font ret = null; + if (m != null) ret = (Font)m.get(new Integer(pointsize)); + else fonts.put(stream, m = new Basket.HashMap()); + if (ret == null) m.put(new Integer(pointsize), ret = new Font(stream, pointsize)); return ret; } @@ -88,7 +92,7 @@ public class Font { } // FEATURE do we really need to be caching sizes? - private static Cache sizeCache = new Cache(1000); + private static Cache sizeCache = new Cache(1000, true); public int textwidth(String s) { return (int)((textsize(s) >>> 32) & 0xffffffff); } public int textheight(String s) { return (int)(textsize(s) & 0xffffffffL); } public long textsize(String s) { @@ -99,18 +103,19 @@ public class Font { return ret; } - static final Task glyphRenderingTask = new Task() { public void perform() { + static final Callable glyphRenderingTask = new Callable() { public Object run(Object o) { // FIXME: this should be a low-priority task glyphRenderingTaskIsScheduled = false; - if (glyphsToBeCached.isEmpty()) return; + if (glyphsToBeCached.isEmpty()) return null; Glyph g = (Glyph)glyphsToBeCached.keys().nextElement(); - if (g == null) return; + if (g == null) return null; glyphsToBeCached.remove(g); Log.debug(Font.class, "glyphRenderingTask rendering " + g.c + " of " + g.font); g.render(); Log.debug(Glyph.class, " done rendering glyph " + g.c); glyphRenderingTaskIsScheduled = true; Scheduler.add(this); + return null; } }; @@ -139,7 +144,7 @@ public class Font { if(loadedStream == res) return; try { - Log.info(Font.class, "loading font " + JS.debugToString(res)); + Log.info(Font.class, "loading font " + JSU.str(res)); InputStream is = res.getInputStream(); byte[] fontstream = InputStreamToByteArray.convert(is); rt.free(loadedStreamAddr); diff --git a/src/org/ibex/graphics/HTML.java b/src/org/ibex/graphics/HTML.java index 39079a3..419c9d1 100644 --- a/src/org/ibex/graphics/HTML.java +++ b/src/org/ibex/graphics/HTML.java @@ -54,17 +54,17 @@ public class HTML { private static boolean withinLI = false; // FEATURE: This is ugly - private static class JS extends org.ibex.js.JS.O { + private static class JS extends org.ibex.js.JS.Obj { public void put(String key, Object value) throws JSExn { if(value instanceof String) put(JSU.S(key),JSU.S((String)value)); else if(value instanceof Number) put(JSU.S(key), JSU.N((Number)value)); - else if(value == null) put(JSU.S(key),null); + else if(value == null) put(JSU.S(key), (JS)null); else throw new Error("FIXME"); } public Object _get(String key) throws JSExn { org.ibex.js.JS js = get(JSU.S(key)); - if(JS.isInt(js)) return new Integer(JS.toInt(js)); - return JS.toString(js); + if(JSU.isInt(js)) return new Integer(JSU.toInt(js)); + return JSU.toString(js); } } diff --git a/src/org/ibex/graphics/Picture.java b/src/org/ibex/graphics/Picture.java index 3c9b22c..0a92677 100644 --- a/src/org/ibex/graphics/Picture.java +++ b/src/org/ibex/graphics/Picture.java @@ -22,7 +22,7 @@ public class Picture { public Picture() { this.stream = null; } public Picture(JS r) { this.stream = r; } - private static Cache cache = new Cache(100); ///< Picture, keyed by the Stream that loaded them + private static Cache cache = new Cache(100, true); ///< Picture, keyed by the Stream that loaded them public JS stream = null; ///< the stream we were loaded from public int width = -1; ///< the width of the image @@ -34,7 +34,7 @@ public class Picture { protected void loaded() { isLoaded = true; } /** turns a stream into a Picture.Source and passes it to the callback */ - public static Picture load(final JS stream, final Task callback) { + public static Picture load(final JS stream, final Callable callback) { if(stream == null) throw new NullPointerException(); Picture ret = (Picture)cache.get(stream); if (ret == null) { diff --git a/src/org/ibex/graphics/Surface.java b/src/org/ibex/graphics/Surface.java index a6b8447..6beebac 100644 --- a/src/org/ibex/graphics/Surface.java +++ b/src/org/ibex/graphics/Surface.java @@ -16,7 +16,7 @@ import org.ibex.core.*; // FIXME * Platform subclasses should include an inner class subclass of * Surface to return from the Platform._createSurface() method */ -public abstract class Surface extends PixelBuffer implements Task { +public abstract class Surface extends PixelBuffer implements Callable { // Static Data //////////////////////////////////////////////////////////////////////////////// @@ -96,13 +96,14 @@ public abstract class Surface extends PixelBuffer implements Task { if (button == 1) new Message("_Press1", T, root); else if (button == 2) new Message("_Press2", T, root); else if (button == 3) { - Scheduler.add(new Task() { public void perform() throws JSExn { + Scheduler.add(new Callable() { public Object run(Object o) throws JSExn { Platform.clipboardReadEnabled = true; try { root.putAndTriggerTraps(JSU.S("_Press3"), T); } finally { Platform.clipboardReadEnabled = false; } + return null; }}); } } @@ -135,9 +136,9 @@ public abstract class Surface extends PixelBuffer implements Task { private final static JS MOVE = JSU.S("_Move"); /** we enqueue ourselves in the Scheduler when we have a Move message to deal with */ - private Task mover = new Task() { - public void perform() { - if (mousex == newmousex && mousey == newmousey) return; + private Callable mover = new Callable() { + public Object run(Object o) { + if (mousex == newmousex && mousey == newmousey) return null; int oldmousex = mousex; mousex = newmousex; int oldmousey = mousey; mousey = newmousey; String oldcursor = cursor; cursor = "default"; @@ -145,6 +146,7 @@ public abstract class Surface extends PixelBuffer implements Task { if (oldmousex != mousex || oldmousey != mousey) root.putAndTriggerTrapsAndCatchExceptions(MOVE, T); if (!cursor.equals(oldcursor)) syncCursor(); + return null; } }; /** @@ -176,10 +178,11 @@ public abstract class Surface extends PixelBuffer implements Task { // FEATURE: can we avoid creating objects here? protected final void PosChange(final int x, final int y) { - Scheduler.add(new Task() { public void perform() throws JSExn { + Scheduler.add(new Callable() { public Object run(Object o) throws JSExn { root.x = x; root.y = y; root.putAndTriggerTrapsAndCatchExceptions(JSU.S("PosChange"), T); + return null; }}); } @@ -194,7 +197,7 @@ public abstract class Surface extends PixelBuffer implements Task { private boolean scheduled = false; public void Refresh() { if (!scheduled) Scheduler.add(this); scheduled = true; } - public void perform() { scheduled = false; Scheduler.renderAll(); } + public Object run(Object o) { scheduled = false; Scheduler.renderAll(); return null; } public final void setMaximized(boolean b) { if (b != maximized) _setMaximized(maximized = b); } public final void setMinimized(boolean b) { if (b != minimized) _setMinimized(minimized = b); } @@ -305,7 +308,7 @@ public abstract class Surface extends PixelBuffer implements Task { } // FEATURE: reinstate recycler - public class Message implements Task { + public class Message implements Callable { private Box boxContainingMouse; private JS value; @@ -318,32 +321,33 @@ public abstract class Surface extends PixelBuffer implements Task { Scheduler.add(this); } - public void perform() throws JSExn { + public Object run(Object o) throws JSExn { if (name.equals("_KeyPressed")) { - String value = JS.toString(this.value); + String value = JSU.toString(this.value); if (value.toLowerCase().endsWith("shift")) shift = true; else if (shift) value = value.toUpperCase(); if (value.toLowerCase().equals("alt")) alt = true; else if (alt) value = "A-" + value; if (value.toLowerCase().endsWith("control")) control = true; else if (control) value = "C-" + value; if (value.equals("C-v") || value.equals("A-v")) Platform.clipboardReadEnabled = true; this.value = JSU.S(value); } else if (name.equals("_KeyReleased")) { - String value = JS.toString(this.value); + String value = JSU.toString(this.value); if (value.toLowerCase().equals("alt")) alt = false; else if (value.toLowerCase().equals("control")) control = false; else if (value.toLowerCase().equals("shift")) shift = false; this.value = JSU.S(value); } else if (name.equals("_HScroll") || name.equals("_VScroll")) { // FIXME: technically points != pixels - if (JS.isInt(value)) - value = JSU.N(JS.toInt(value) * root.fontSize()); + if (JSU.isInt(value)) + value = JSU.N(JSU.toInt(value) * root.fontSize()); } try { boxContainingMouse.putAndTriggerTrapsAndCatchExceptions(JSU.S(name), value); } finally { Platform.clipboardReadEnabled = false; } + return null; } - public String toString() { return "Message [name=" + name + ", value=" + JS.debugToString(value) + "]"; } + public String toString() { return "Message [name=" + name + ", value=" + JSU.str(value) + "]"; } } diff --git a/src/org/ibex/plat/OpenGL.java b/src/org/ibex/plat/OpenGL.java index eee8c21..3d0e7cd 100644 --- a/src/org/ibex/plat/OpenGL.java +++ b/src/org/ibex/plat/OpenGL.java @@ -138,7 +138,7 @@ abstract class OpenGL { public void deleteTexture(final int tex) { // CHECKME: Is this safe to do from finalize()? // natDeleteTexture MUST be run from the message queue thread - Scheduler.add(new Task() { public void perform() { natDeleteTexture(tex); }}); + Scheduler.add(new Callable() { public Object run(Object o) { natDeleteTexture(tex); return null; }}); } private static abstract class GLPicture { diff --git a/src/org/ibex/plat/Platform.java b/src/org/ibex/plat/Platform.java index e9f6589..857a877 100644 --- a/src/org/ibex/plat/Platform.java +++ b/src/org/ibex/plat/Platform.java @@ -122,7 +122,7 @@ public abstract class Platform { ret.Refresh(); } try { - if (b.get(JSU.S("titlebar")) != null) ret.setTitleBarText(JS.toString(b.get(JSU.S("titlebar")))); + if (b.get(JSU.S("titlebar")) != null) ret.setTitleBarText(JSU.toString(b.get(JSU.S("titlebar")))); } catch (JSExn e) { Log.warn(Platform.class, e); }