make core compile with new js stuff and Task replacement class
authorcrawshaw <crawshaw@ibex.org>
Fri, 7 Jan 2005 20:05:25 +0000 (20:05 +0000)
committercrawshaw <crawshaw@ibex.org>
Fri, 7 Jan 2005 20:05:25 +0000 (20:05 +0000)
darcs-hash:20050107200525-2eb37-087bb88a5a78b4dfca033654a999f7ce85924633.gz

13 files changed:
src/org/ibex/core/Box.java
src/org/ibex/core/Ibex.java
src/org/ibex/core/LocalStorage.java
src/org/ibex/core/Main.java
src/org/ibex/core/Scheduler.java
src/org/ibex/core/Stream.java
src/org/ibex/core/Template.java
src/org/ibex/graphics/Font.java
src/org/ibex/graphics/HTML.java
src/org/ibex/graphics/Picture.java
src/org/ibex/graphics/Surface.java
src/org/ibex/plat/OpenGL.java
src/org/ibex/plat/Platform.java

index 7a332ea..ce0b4e7 100644 (file)
@@ -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);
         }
     }
index 57fe96d..a157239 100644 (file)
@@ -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<c.getAttrLen(); i++) attrs.put(JSU.S(c.getAttrKey(i)), JSU.S(c.getAttrVal(i)));
-                startElement.call(JSU.S(c.getLocalName()), attrs, JSU.S(c.getUri()), null, 3);
-        } catch (JSExn jse) { throw new Wrapper(jse); } }
+                for(int i=0; i<a.attrSize(); i++) attrs.put(JSU.S(a.getKey(i)), JSU.S(a.getVal(i)));
+                callargs3[0] = JSU.S(c.getLocalName());
+                callargs3[1] = attrs;
+                callargs3[2] = JSU.S(c.getUri());
+                startElement.call(callargs3);
+        } catch (JSExn jse) { throw new Wrapper(jse);
+        } finally { callargs3[0] = callargs3[1] = callargs3[2] = null; } }
 
-        public void endElement(XML.Element c) throws XML.Exn { try {
-                endElement.call(JSU.S(c.getLocalName()), JSU.S(c.getUri()), null, null, 2);
-        } catch (JSExn jse) { throw new Wrapper(jse); } }
+        public void endElement(Tree.Element c) throws XML.Exn { try {
+                callargs2[0] = JSU.S(c.getLocalName());
+                callargs2[1] = JSU.S(c.getUri());
+                endElement.call(callargs2);
+        } catch (JSExn jse) { throw new Wrapper(jse); } finally { callargs2[0] = callargs2[1] = null; } }
 
         public void characters(char[] ch, int start, int length) throws XML.Exn { try {
-                characters.call(JSU.S(new String(ch, start, length)), null, null, null, 1);
-        } catch (JSExn jse) { throw new Wrapper(jse); } }
+                callargs1[0] = JSU.S(new String(ch, start, length));
+                characters.call(callargs1);
+        } catch (JSExn jse) { throw new Wrapper(jse); } finally { callargs1[0] = null; } }
 
         public void whitespace(char[] ch, int start, int length) throws XML.Exn { try {
-                whitespace.call(JSU.S(new String(ch, start, length)), null, null, null, 1);
-        } catch (JSExn jse) { throw new Wrapper(jse); } }
+                callargs1[0] = JSU.S(new String(ch, start, length));
+                whitespace.call(callargs1);
+        } catch (JSExn jse) { throw new Wrapper(jse); } finally { callargs1[0] = null; } }
 
         public void doParse(JS s) throws JSExn {
             try { 
@@ -356,18 +368,19 @@ public final class Ibex extends JS.Obj implements JS.Cloneable {
         public JS parentkey = null;
         public Blessing parent = null;
         public JS clonee;
-        private Hash cache = new Hash();
+        private Basket.Map cache = new Basket.HashMap(); 
         public Blessing(JS clonee, Ibex ibex, Blessing parent, JS parentkey) throws JSExn {
             this.clonee = clonee; this.ibex = ibex; this.parentkey = parentkey; this.parent = parent; }
         public JS get(JS key) throws JSExn {
-            if (JS.isString(key) && JSU.toString(key).equals("")) return getStatic();
+            if (JSU.isString(key) && JSU.toString(key).equals("")) return getStatic();
             if (cache.get(key) != null) return (JS)cache.get(key);
             JS ret = new Blessing(clonee.get(key), ibex, this, key);
             cache.put(key, ret);
             return ret;
         }
         public static Blessing getBlessing(JS js) {
-            while (js instanceof JS.Clone && !(js instanceof Blessing)) js = ((JS.Clone)js).getClonee();
+            // CHECKME: is unclone() good enough or do we need getClonee() in Cloneable?
+            while (js instanceof JS.Cloneable && !(js instanceof Blessing)) js = js.unclone();
             if (!(js instanceof Blessing)) return null;
             return (Blessing)js;
         }
@@ -399,26 +412,26 @@ public final class Ibex extends JS.Obj implements JS.Cloneable {
             }
         }
         private String description() {
-            String s = JS.debugToString(parentkey);
-            for(Blessing b = parent; b.parentkey != null; b = b.parent) s = JS.debugToString(b.parentkey) + "." + s;
+            String s = JSU.str(parentkey);
+            for(Blessing b = parent; b.parentkey != null; b = b.parent) s = JSU.str(b.parentkey) + "." + s;
             return s;
         }
-        public JS call(JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
-            if (nargs != 1) throw new JSExn("can only call a template with one arg");
+        public JS call(JS[] args) throws JSExn {
+            if (args.length != 1) throw new JSExn("can only call a template with one arg");
             getStatic();
-            if (t == null) throw new JSExn("No such template " + JS.debugToString(parentkey));
-            if(!(a instanceof Box)) throw new JSExn("can only apply templates to boxes");
-            t.apply((Box)a);
-            return a;
+            if (t == null) throw new JSExn("No such template " + JSU.str(parentkey));
+            if(!(args[0] instanceof Box)) throw new JSExn("can only apply templates to boxes");
+            t.apply((Box)args[0]);
+            return args[0];
         }
         // FEATURE: This is a gross hack
         Template getTemplate()  throws JSExn {
             getStatic();
-            if (t == null) throw new JSExn("No such template " + JS.debugToString(parentkey));
+            if (t == null) throw new JSExn("No such template " + JSU.str(parentkey));
             return t;
         }
         // JS:FIXME: Blessing shouldn't need to roll its own JS.Clone implementation
-        public InputStream getInputStream() throws IOException { return clonee.getInputStream(); }
+        public InputStream getInputStream() throws JSExn, IOException { return clonee.getInputStream(); }
     }
 
 }
index 07b2a88..0ad4826 100644 (file)
@@ -51,7 +51,7 @@ public class LocalStorage {
 
         public static java.io.File getCacheFileForKey(String key) {
             // FEATURE: be smarter here
-            return new java.io.File(cacheDir.getPath() + File.separatorChar + new String(Base64.encode(key.getBytes())));
+            return new java.io.File(cacheDir.getPath() + File.separatorChar + new String(Encode.toBase64(key.getBytes())));
         }
 
     }
index d925bc0..d35def1 100644 (file)
@@ -101,9 +101,15 @@ public class Main {
 
         org.ibex.graphics.Surface.scarImage =
             Picture.load(new Stream.FromInputStream(Encode.JavaSourceCode.decode(Scar.data)),
-                         new Task() { public void perform() throws JSExn, UnknownHostException {
-                             if (Log.on) Log.info(Main.class, "invoking initial template");
-                             ibex.resolveString(startupTemplate, false).call(new Box(), null, null, null, 1);
+                         new Callable() {
+                             private JS[] callargs = new JS[1];
+                             public Object run(Object o) throws JSExn,UnknownHostException {
+                                 if (Log.on) Log.info(Main.class, "invoking initial template");
+                                 try {
+                                     callargs[0] = new Box(); 
+                                     ibex.resolveString(startupTemplate, false).call(callargs);
+                                 } finally { callargs[0] = null; }
+                                 return null;
                          } });
 
         Scheduler.init();
index ee44c43..8fdb506 100644 (file)
@@ -17,10 +17,10 @@ public class Scheduler {
     // Public API Exposed to org.ibex /////////////////////////////////////////////////
 
     private static Scheduler singleton;
-    public static void add(Task t) { Log.debug(Scheduler.class, "scheduling " + t); Scheduler.runnable.append(t); }
+    public static void add(Callable t) { Log.debug(Scheduler.class, "scheduling " + t); Scheduler.runnable.append(t); }
     public static void init() { if (singleton == null) (singleton = Platform.getScheduler()).run(); }
 
-    private static Task current = null;
+    private static Callable current = null;
 
     private static volatile boolean rendering = false;
     private static volatile boolean again = false;
@@ -51,7 +51,7 @@ public class Scheduler {
 
     /**
      *  SCHEDULER INVARIANT: all scheduler implementations MUST invoke
-     *  Surface.renderAll() after performing a Task if no tasks remain
+     *  Surface.renderAll() after performing a Callable if no tasks remain
      *  in the queue.  A scheduler may choose to invoke
      *  Surface.renderAll() more often than that if it so chooses.
      */
@@ -64,7 +64,7 @@ public class Scheduler {
     protected static Queue runnable = new Queue(50);
     public void defaultRun() {
         while(true) {
-            current = (Task)runnable.remove(true);
+            current = (Callable)runnable.remove(true);
             try {
                 // FIXME hideous
                 synchronized(this) {
@@ -79,14 +79,14 @@ public class Scheduler {
                         }
                     }
                     Log.debug(Scheduler.class, "performing " + current);
-                    current.perform();
+                    current.run(null);
                 }
                 renderAll();
             } catch (JSExn e) {
                 Log.info(Scheduler.class, "a JavaScript thread spawned with ibex.thread() threw an exception:");
                 Log.info(Scheduler.class,e);
             } catch (Exception e) {
-                Log.info(Scheduler.class, "a Task threw an exception which was caught by the scheduler:");
+                Log.info(Scheduler.class, "a Callable threw an exception which was caught by the scheduler:");
                 Log.info(Scheduler.class, e);
             } catch (Throwable t) {
                 t.printStackTrace();
index 34b71d5..247540a 100644 (file)
@@ -26,7 +26,7 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
 
     // streams are "sealed" by default to prevent accidental object leakage
     public void put(Object key, Object val) { }
-    private Cache getCache = new Cache(100);
+    private Cache getCache = new Cache(100, true);
     protected JS _get(JS key) throws JSExn { return null; }
     public final JS get(JS key) throws JSExn {
         JS ret = (JS)getCache.get(key);
@@ -44,7 +44,7 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
         private String url;
         //public String toString() { return "Stream.HTTP:" + url; }
         public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
-        public JS _get(JS key) throws JSExn { return new HTTP(url + "/" + JS.toString(key)); }
+        public JS _get(JS key) throws JSExn { return new HTTP(url + "/" + JSU.toString(key)); }
         public String getCacheKey(Vec path) throws NotCacheableException { return url; }
         public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(null, null); }
     }
@@ -67,8 +67,8 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
         public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
         public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
         public JS _get(JS key) throws JSExn {
-            System.out.println("get: " + JS.debugToString(key));
-            return new File(path + java.io.File.separatorChar + JS.toString(key)); }
+            System.out.println("get: " + JSU.str(key));
+            return new File(path + java.io.File.separatorChar + JSU.toString(key)); }
     }
 
     /** "unwrap" a Zip archive */
@@ -82,7 +82,7 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
             this.path = path;
         }
         public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!zip:"; }
-        public JS _get(JS key) throws JSExn { return new Zip(parent, path==null?JS.toString(key):path+'/'+JS.toString(key)); }
+        public JS _get(JS key) throws JSExn { return new Zip(parent, path==null?JSU.toString(key):path+'/'+JSU.toString(key)); }
         public InputStream getInputStream() throws IOException {
             InputStream pis = parent.getInputStream();
             ZipInputStream zis = new ZipInputStream(pis);
@@ -122,6 +122,7 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
 
     /** shadow resource which replaces the graft */
     public static class ProgressWatcher extends Stream {
+        private final JS[] callargs = new JS[2];
         final Stream watchee;
         JS callback;
         public ProgressWatcher(Stream watchee, JS callback) { this.watchee = watchee; this.callback = callback; }
@@ -138,9 +139,16 @@ public abstract class Stream extends JS.Obj implements JS.Cloneable {
                     public int read(byte[] b, int off, int len) throws IOException {
                         int ret = super.read(b, off, len);
                         if (ret != 1) bytesDownloaded += ret;
-                        Scheduler.add(new Task() { public void perform() throws IOException, JSExn {
-                            callback.call(N(bytesDownloaded),
-                                          N(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0), null, null, 2);
+                        Scheduler.add(new Callable() {
+                            public Object run(Object o) throws IOException, JSExn {
+                                try {
+                                    int len = is instanceof KnownLength.KnownLengthInputStream ?
+                                                ((KnownLength.KnownLengthInputStream)is).getLength() : 0;
+                                    callargs[0] = JSU.N(bytesDownloaded);
+                                    callargs[1] = JSU.N(len);
+                                    callback.call(callargs);
+                                } finally { callargs[0] = callargs[1] = null; }
+                                return null;
                         } });
                         return ret;
                     }
index c2a7c2c..aca83ba 100644 (file)
@@ -77,6 +77,7 @@ public class Template {
         }
     }
 
+    private static final JS[] callempty = new JS[0];
     private void apply(Box b, PerInstantiationScope parentPis) throws JSExn, IOException {
         if (prev != null) prev.apply(b, null);
         if (prev2 != null) prev2.apply(b, null);
@@ -100,7 +101,7 @@ public class Template {
             b.putAndTriggerTraps(b.get(JSU.S("numchildren")), kid);
         }
 
-        if (script != null) JS.cloneWithNewGlobalScope(script, pis).call(null, null, null, null, 0);
+        if (script != null) JSU.cloneWithNewGlobalScope(script, pis).call(callempty);
 
         for(int i=0; keys != null && i < keys.length; i++) {
             if (keys[i] == null) continue;
@@ -109,14 +110,14 @@ public class Template {
 
             if ("null".equals(val)) val = null;
 
-            if (JS.isString(val) && (JS.toString(val).length() > 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 <ibex>", 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<t.keys.length; i++) {
                 // FEATURE: Intern
-                t.keys[i] = JSU.S((String)keys.elementAt(i));
-                String valString = (String) vals.elementAt(i);
+                t.keys[i] = JSU.S((String)keys.get(i));
+                String valString = (String) vals.get(i);
                 
                 if (valString.equals("true")) t.vals[i] = JSU.T;
                 else if (valString.equals("false")) t.vals[i] = JSU.F;
@@ -288,7 +289,7 @@ public class Template {
             }
         }
 
-        public void endElement(XML.Element c) throws XML.Exn, IOException {
+        public void endElement(Tree.Element c) throws XML.Exn, IOException {
             switch(state) {
                 case STATE_IN_META_NODE: if (--meta < 0) state = STATE_IN_ROOT_NODE; return;
                 case STATE_IN_ROOT_NODE: return;
@@ -330,7 +331,8 @@ public class Template {
         public void whitespace(char[] ch, int start, int length) throws XML.Exn { }
     }
 
-    private static class PerInstantiationScope extends JS.O {
+    // FIXME: david, get to work
+    private static class PerInstantiationScope extends JS.Obj {
         Ibex ibex = null;
         PerInstantiationScope parentBoxPis = null;
         JS myStatic = null;
@@ -350,8 +352,8 @@ public class Template {
             this.box = box;
         }
         public JS get(JS key) throws JSExn {
-            if(JS.isString(key)) {
-                String s = JS.toString(key);
+            if(JSU.isString(key)) {
+                String s = JSU.toString(key);
                 // JS:FIXME This is a hack
                 if (super.get(key) != null) return super.get(key);
                 if (s.equals("ibex")) return ibex;
@@ -363,8 +365,8 @@ public class Template {
         }
         // JS:FIXME: Everything below here should come from js.scope or something
         public void put(JS key, JS val) throws JSExn { if(box != null) box.putAndTriggerTraps(key,val); else super.put(key,val); }
-        public void addTrap(JS key, JSFunction f) throws JSExn { box.addTrap(key,f); }
-        public void delTrap(JS key, JSFunction f) throws JSExn { box.delTrap(key,f); }
+        public void addTrap(JS key, JS f) throws JSExn { box.addTrap(key,f); }
+        public void delTrap(JS key, JS f) throws JSExn { box.delTrap(key,f); }
     }
 
 }
index 8d525fb..6f1e69a 100644 (file)
@@ -49,10 +49,14 @@ public class Font {
 
     static final Hashtable glyphsToBeCached = new Hashtable();
     static final Hashtable glyphsToBeDisplayed = new Hashtable();
-    private static Cache fontCache = new Cache(100);
+    // HACK: replace with Cache<JS, int>
+    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);
index 39079a3..419c9d1 100644 (file)
@@ -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);
         }
     }
     
index 3c9b22c..0a92677 100644 (file)
@@ -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) {
index a6b8447..6beebac 100644 (file)
@@ -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) + "]"; }
     }
 
 
index eee8c21..3d0e7cd 100644 (file)
@@ -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 {
index e9f6589..857a877 100644 (file)
@@ -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);
         }