2003/09/21 10:26:53
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:36:05 +0000 (07:36 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:36:05 +0000 (07:36 +0000)
darcs-hash:20040130073605-2ba56-2ea857d984104433a980345567169c914c18cbbe.gz

13 files changed:
Makefile
src/org/xwt/Box.java.pp
src/org/xwt/HTTP.java
src/org/xwt/Main.java
src/org/xwt/Platform.java
src/org/xwt/Res.java
src/org/xwt/Template.java
src/org/xwt/Trap.java
src/org/xwt/Weak.java [deleted file]
src/org/xwt/XWT.java
src/org/xwt/js/CompiledFunctionImpl.java
src/org/xwt/js/JS.java
src/org/xwt/js/Parser.java

index 7d0cb52..d3a6b13 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -116,7 +116,7 @@ jpeg_sources    += jquant1.c jquant2.c jerror.c jutils.c jmemnobs.c jmemmgr.c
 upstream/jpeg-6b/build-$(target)/libjpeg.a: .install_jpeg-6b_$(target)
 java_objects := $(nonplat_java_sources:build/java/%.java=build/$(platform)/%.java.o)
 
-build/$(platform)/$(platform).ar: $(java_objects) build/$(platform)/org/xwt/plat/$(platform).cc.o build/$(platform)/org/xwt/builtin.res.o build/$(platform)/freetype.res.o $(plat_java_sources:build/java/%.java=build/$(platform)/%.java.o)
+build/$(platform)/$(platform).ar: $(java_objects) build/$(platform)/org/xwt/plat/$(platform).cc.o build/$(platform)/builtin.o $(plat_java_sources:build/java/%.java=build/$(platform)/%.java.o)
        @echo -e "\n\033[1marchiving             .o -> .a\033[0m"
        mkdir -p build/$(platform)
        upstream/install/bin/$(target)-ar rc $@ $?
index 245a2c1..eb8c0c0 100644 (file)
@@ -105,6 +105,7 @@ public final class Box extends JS.Scope {
      *  changes.
      */
     static int FONT_CHANGED_FLAG = 0x00000100;
+    static int ISROOT_FLAG       = 0x00000200;
 
     static int ALIGN_FLAG        = 0x00000000;
     static int FIXEDASPECT_FLAG  = 0x00000000;
@@ -477,7 +478,6 @@ public final class Box extends JS.Scope {
             // FIXME: clipping
             char c = text.charAt(i);
             Glyph g = Glyph.getGlyph(font, fontsize, c);
-            System.out.println("rendering glyph for " + c + " as " + g + " @ " + (x+hpad) + ", " + (y+vpad));
            buf.drawPicture(g.p,
                             x + hpad,
                             y + vpad + g.max_ascent - g.baseline,
@@ -512,7 +512,9 @@ public final class Box extends JS.Scope {
                 Template t = Template.buildTemplate(res.getInputStream(), "fromResource");
                 if (ThreadMessage.suspendThread()) try {
                     JS.Callable callback = args.length() < 2 ? null : (Callable)args.elementAt(1);
-                    t.apply(this, null, null, callback, 0, t.numUnits());
+
+                    // FIXME!!! needs to be xwt.apply(template, box)
+                    t.apply(this, null, null, callback, 0, t.numUnits(), null);
                 } finally {
                     ThreadMessage.resumeThread();
                 }
@@ -527,7 +529,8 @@ public final class Box extends JS.Scope {
                 } else {
                     if (ThreadMessage.suspendThread()) try {
                         JS.Callable callback = args.length() < 2 ? null : (Callable)args.elementAt(1);
-                        t.apply(this, null, null, callback, 0, t.numUnits());
+                        // FIXME!!! needs to be xwt.apply(template, box)
+                        t.apply(this, null, null, callback, 0, t.numUnits(), null);
                     } finally {
                         ThreadMessage.resumeThread();
                     }
@@ -649,17 +652,9 @@ public final class Box extends JS.Scope {
         String name = (String)name_;
         if (name.equals("")) return null;
 
-        // See if we're reading back the function value of a trap
-        if (name.charAt(0) == '_') {
-            if (name.charAt(1) == '_') name = name.substring(2);
-            else name = name.substring(1);
-            Trap t = Trap.getTrap(this, name);
-            return t == null ? null : t.f;
-        }
-        
         // See if we're triggering a trap
         Trap t = traps == null || ignoretraps ? null : (Trap)traps.get(name);
-        if (t != null && t.isreadtrap) return t.perform(Trap.emptyargs);
+        if (t != null) return t.perform();
 
         // Check for a special handler
         SpecialBoxProperty gph = (SpecialBoxProperty)SpecialBoxProperty.specialBoxProperties.get(name);
@@ -677,6 +672,10 @@ public final class Box extends JS.Scope {
         return ret;
     }
 
+    public void addTrap(Object name, Object value) { Trap.addTrap(this, name, ((JS.CompiledFunction)value)); }
+    public void delTrap(Object name, Object value) { Trap.delTrap(this, name, ((JS.CompiledFunction)value)); }
+
+
     /**
      *  Scriptable.put()
      *  @param ignoretraps if set, no traps will be triggered (set when 'cascade' reaches the bottom of the trap stack)
@@ -692,10 +691,7 @@ public final class Box extends JS.Scope {
         if (!ignoretraps && traps != null) {
             Trap t = (Trap)traps.get(name);
             if (t != null) {
-                JS.Array arg = new JS.Array();
-                arg.addElement(value);
-                t.perform(arg);
-                arg.setElementAt(null, 0);
+                t.perform(value);
                 return;
             }
         }
@@ -706,25 +702,6 @@ public final class Box extends JS.Scope {
         SpecialBoxProperty gph = (SpecialBoxProperty)SpecialBoxProperty.specialBoxProperties.get(name);
         if (gph != null) { gph.put(name, this, value); return; }
 
-        if (name.charAt(0) == '_') {
-            if (value != null && !(value instanceof JS.Callable)) {
-                if (Log.on) Log.logJS(this, "attempt to put a non function value (" + value + ") to " + name);
-            } else if (value != null && !(value instanceof JS.CompiledFunction)) {
-                if (Log.on) Log.logJS(this, "attempt to put a non-compiled function value (" + value + ") to " + name);
-            } else if (name.charAt(1) == '_') {
-                name = name.substring(2).intern();
-                Trap t = Trap.getTrap(this, name);
-                if (t != null) t.delete();
-                if (value != null) Trap.addTrap(this, name, ((JS.CompiledFunction)value), true, rp);
-            } else {
-                name = name.substring(1).intern();
-                Trap t = Trap.getTrap(this, name);
-                if (t != null) t.delete();
-                if (value != null) Trap.addTrap(this, name, ((JS.CompiledFunction)value), false, rp);
-            }
-            return;
-        }
-
         super.put(name, value);
     }
 
@@ -1312,10 +1289,13 @@ public final class Box extends JS.Scope {
             specialBoxProperties.put("DoubleClick3", mouseEventHandler);
 
             specialBoxProperties.put("root", new SpecialBoxProperty() {
+                    public void put(Box b, Object value) {
+                        if (stob(value)) b.flags |= ISROOT_FLAG;
+                        else b.flags &= ~ISROOT_FLAG;
+                    }
                     public Object get(Box b) {
-                        if (b.getRoot() == null) return null;
-                        else if (b.parent == null) return b;
-                        else return b.getRoot().getRootProxy();
+                        if (b.parent == null || ((b.flags & ISROOT_FLAG) != 0)) return b;
+                        else return get(b.parent);
                     } });
 
             specialBoxProperties.put("Minimized", new SpecialBoxProperty() {
index 3dc73da..a5c7114 100644 (file)
@@ -774,7 +774,7 @@ public class HTTP {
                 MessageQueue.add(new Message() {
                         public void perform() {
                             Box b = new Box();
-                            Template.getTemplate("org.xwt.builtin.proxy_authorization", null).apply(b, null, null, null, 0, 0);
+                            Template.getTemplate("org.xwt.builtin.proxy_authorization", null).apply(b, null, null, null, 0, 0, null);
                             b.put("realm", realm);
                             b.put("proxyIP", proxyIP);
                         }
index 4f7ec28..d55d9bb 100644 (file)
@@ -73,10 +73,12 @@ public class Main {
             Surface.scarPicture = Platform.createPicture(png.getData(), png.getWidth(), png.getHeight());
 
             String initialTemplate = "main";
+            Res initialRR = null;
 
             if (args.length > startargs) {
                 if (args[startargs].startsWith("http://")) {
                     if (Log.on) Log.log(Main.class, "downloading xwar");
+                    initialRR = Res.stringToRes("file:" + args[startargs] + "!");
                     origin = args[startargs];
                     initialTemplate = "org.xwt.builtin.splash";
 
@@ -90,9 +92,10 @@ public class Main {
                     File f = new File(args[startargs]);
                     origin = "file:" + f.getAbsolutePath();
                     if (f.isDirectory()) {
-                        Resources.loadDirectory(f);
+                        initialRR = Res.stringToRes("file:" + args[startargs]);
                         Surface.scarAllSurfacesFromNowOn = true;
                     } else {
+                        initialRR = Res.stringToRes("file:" + args[startargs] + "!");
                         initialTemplate = "org.xwt.builtin.splash";
                     }
 
@@ -102,14 +105,22 @@ public class Main {
             
             if (Log.on) Log.log(Main.class, "instantiating " + initialTemplate);
             final String initialTemplate_f = initialTemplate;
+            final Res initialRR_f = initialRR;
             ThreadMessage.newthread(new JS.Callable() {
                     public Object call(JS.Array args) throws JS.Exn {
                         Box b = new Box();
-                        Template.getTemplate(initialTemplate_f, null).apply(b, null, null, null, 0, 0);
-                        doneInitializing = true;
-                        if (Surface.allSurfaces.size() == 0) {
-                            Log.log(this, "exiting because all surfaces are gone");
-                            Platform.exit();
+                        try {
+                            Template t = Template.buildTemplate(Res.stringToRes("file:.").getInputStream(), "RESOURCE");
+                            t.apply(b, (Vec)null, (Vec)null, (JS.Callable)null, 0, 0, initialRR_f);
+                            //FIXME
+                            //Template.getTemplate(initialTemplate_f, null).apply(b, (Vec)null, (Vec)null, (JS.Callable)null, 0, 0, initialRR_f);
+                            doneInitializing = true;
+                            if (Surface.allSurfaces.size() == 0) {
+                                Log.log(this, "exiting because all surfaces are gone");
+                                Platform.exit();
+                            }
+                        } catch (Exception e) {
+                            Log.log(Main.class, e);
                         }
                         return null;
                     }
index 30b46e1..049404e 100644 (file)
@@ -170,13 +170,6 @@ public class Platform {
     /** returns the maximum number of threads that the XWT engine can create without adversely affecting the host OS */
     protected int _maxThreads() { return 25; }
 
-    /** creates a weak reference */
-    protected org.xwt.Weak _getWeak(final Object o) {
-        return new org.xwt.Weak() {
-                public Object get() { return o; }
-            };
-    }
-
         /** Called once XWT is initialized and the application is running. */
         protected void _running() {}
     
@@ -275,9 +268,6 @@ public class Platform {
     /** returns a list of all platform-specific fonts available */
     public static String[] listFonts() { return platform._listFonts(); }
 
-    /** creates a weak reference */
-    public static org.xwt.Weak getWeak(Object o) { return platform._getWeak(o); }
-
     /** opens a connection to the resource identified by URL u, and returns an InputStream */
     public static InputStream urlToInputStream(URL u) throws IOException { return platform._urlToInputStream(u); }
 
index b956931..402f2d6 100644 (file)
@@ -17,6 +17,19 @@ public abstract class Res extends JS {
 
     private Hash refCache = null;
     public Object get(Object key) {
+        if ("".equals(key)) {
+            try {
+                Res who = this;
+                //who = addExtension(".xwt");
+                // FIXME: cache templates by the Res that created them, not their nodename
+                Template.buildTemplate(who.getInputStream(), "Resource");
+                // FIXME: return the static here
+                return null;
+            } catch (IOException e) {
+                Log.logJS(this, e);
+                return null;
+            }
+        }
         Object ret = refCache == null ? null : refCache.get(key);
         if (ret != null) return ret;
         ret = new Ref(this, key);
index ee0bea5..11bb1fc 100644 (file)
@@ -165,7 +165,7 @@ public class Template {
      *  @param pboxes a vector of all box parents on which to put $-references
      *  @param ptemplates a vector of the nodeNames to recieve private references on the pboxes
      */
-    void apply(Box b, Vec pboxes, Vec ptemplates, JS.Callable callback, int numerator, int denominator) {
+    void apply(Box b, Vec pboxes, Vec ptemplates, JS.Callable callback, int numerator, int denominator, Res resourceRoot) {
 
         int original_numerator = numerator;
 
@@ -192,13 +192,13 @@ public class Template {
 
         for(int i=0; _preapply != null && i<_preapply.length; i++)
             if (_preapply[i] != null) {
-                _preapply[i].apply(b, null, null, callback, numerator, denominator);
+                _preapply[i].apply(b, null, null, callback, numerator, denominator, resourceRoot);
                 numerator += _preapply[i].numUnits();
             }
 
         for (int i=0; children != null && i<children.length; i++) {
             Box newkid = new Box();
-            children[i].apply(newkid, pboxes, ptemplates, callback, numerator, denominator);
+            children[i].apply(newkid, pboxes, ptemplates, callback, numerator, denominator, resourceRoot);
             b.put(Integer.MAX_VALUE, newkid);
             numerator += children[i].numUnits();
         }
@@ -208,7 +208,7 @@ public class Template {
         if (redirect != null && !"self".equals(redirect)) redir = (Box)b.get("$" + redirect);
 
         if (script != null) try {
-            script.call(new JS.Array(), b);
+            script.call(new JS.Array(), new PerInstantiationScope(b, resourceRoot));
         } catch (JS.Exn e) {
             if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e.getMessage());
         }
@@ -233,7 +233,7 @@ public class Template {
 
         for(int i=0; _postapply != null && i<_postapply.length; i++)
             if (_postapply[i] != null) {
-                _postapply[i].apply(b, null, null, callback, numerator, denominator);
+                _postapply[i].apply(b, null, null, callback, numerator, denominator, resourceRoot);
                 numerator += _postapply[i].numUnits();
             }
 
@@ -269,99 +269,6 @@ public class Template {
         for(int i=0; _postapply != null && i<_postapply.length; i++) if (_postapply[i] != null) _postapply[i].gatherPreserves(v);
     }
 
-    /** adds a theme mapping, retemplatizing as needed */
-    public static void retheme(JS.Callable callback) {
-        /*
-        XWF.flushXWFs();
-
-        // clear changed marker and relink
-        Template[] t = new Template[cache.size()];
-        Enumeration e = cache.elements();
-        for(int i=0; e.hasMoreElements(); i++) t[i] = (Template)e.nextElement();
-        for(int i=0; i<t.length; i++) {
-            t[i].changed = false;
-            t[i].numunits = -1;
-            t[i].link(true);
-        }
-
-        for(int i=0; i<Surface.allSurfaces.size(); i++) {
-            Box b = ((Surface)Surface.allSurfaces.elementAt(i)).root;
-            if (b != null) reapply(b);
-        }
-
-        if (callback != null)
-            try {
-                JS.Array args = new JS.Array();
-                args.addElement(new Double(1.0));
-                args.addElement(new Double(1.0));
-                callback.call(args);
-            } catch (JS.Exn ex) {
-                if (Log.on) Log.log(Template.class, "WARNING: uncaught ecmascript exception: " + ex.getMessage());
-            }
-        */
-    }
-
-    /** template reapplication procedure */
-    private static void reapply(Box b) {
-
-        Log.log(Template.class, "Template.reapply() not implemented");
-        /*
-        // Ref 7.5.1: check if we need to retemplatize
-        boolean retemplatize = false;
-        if (b.templatename != null) {
-            Template t = getTemplate(b.templatename, b.importlist);
-            if (t != b.template) retemplatize = true;
-            b.template = t;
-        }
-        if (b.template != null && b.template.changed) retemplatize = true;
-
-        if (retemplatize) {
-
-            // Ref 7.5.2: "Preserve all properties on the box mentioned in the <preserve> elements of any
-            //             of the templates which would be applied in step 7."
-            Vec keys = new Vec();
-            b.template.gatherPreserves(keys);
-            Object[] vals = new Object[keys.size()];
-            for(int i=0; i<keys.size(); i++) vals[i] = b.get(((String)keys.elementAt(i)), null);
-            
-            // Ref 7.5.3: "Remove and save all children of the box, or its redirect target, if it has one"
-            Box[] kids = null;
-            if (b.redirect != null) {
-                kids = new Box[b.redirect.numChildren()];
-                for(int i=b.redirect.numChildren() - 1; i >= 0; i--) {
-                    kids[i] = b.redirect.getChild(i);
-                    kids[i].remove();
-                }
-            }
-            
-            // Ref 7.5.4: "Set the box's redirect target to self"
-            b.redirect = b;
-            
-            // Ref 7.5.5: "Remove all of the box's immediate children"
-            for(Box cur = b.getChild(b.numChildren() - 1); cur != null;) {
-                Box oldcur = cur;
-                cur = cur.prevSibling();
-                oldcur.remove();
-            }
-            
-            // Ref 7.5.6: "Remove all traps set by scripts run during the application of any template to this box"
-            Trap.removeAllTrapsByBox(b);
-            
-            // Ref 7.5.7: "Apply the template to the box according to the usual application procedure"
-            b.template.apply(b, null, null, null, 0, 1);
-            
-            // Ref 7.5.8: "Re-add the saved children which were removed in step 3"
-            for(int i=0; kids != null && i<kids.length; i++) b.put(Integer.MAX_VALUE, null, kids[i]);
-            
-            // Ref 7.5.9: "Re-put any property values which were preserved in step 2"
-            for(int i=0; i<keys.size(); i++) b.put((String)keys.elementAt(i), null, vals[i]);
-        }        
-
-        // Recurse
-        for(Box j = b.getChild(0); j != null; j = j.nextSibling()) reapply(j);
-        */
-    }
-
     /** runs statics, resolves string references to other templates into actual Template instance references, and sets <tt>change</tt> as needed */
     void link() { link(false); }
 
@@ -701,6 +608,35 @@ public class Template {
         }
     }
 
+    private static class PerInstantiationScope extends JS.Scope {
+        Res resourceRoot = null;
+        public PerInstantiationScope(Scope parentScope, Res resourceRoot) {
+            super(parentScope);
+            this.resourceRoot = resourceRoot;
+        }
+        public boolean isTransparent() { return true; }
+        public boolean has(Object key) { return false; }
+        public void declare(String s) { super.declare(s); }
+        public Object get(Object key) {
+            // FIXME: access statics here
+            if (Box.SpecialBoxProperty.specialBoxProperties.get(key) == null &&
+                !super.has(key)) {
+                Object ret = resourceRoot.get(key);
+                if (ret != null) return ret;
+                throw new JS.Exn("must declare " + key + " before using it!");
+            }
+            return super.get(key);
+        }
+        public void put(Object key, Object val) {
+            // FIXME: access statics here
+            if (Box.SpecialBoxProperty.specialBoxProperties.get(key) == null &&
+                !super.has(key)) {
+                throw new JS.Exn("must declare " + key + " before using it!");
+            }
+            super.put(key, val);
+        }
+    }
+
 }
 
 
index 5f803cb..3e6302b 100644 (file)
@@ -15,9 +15,6 @@ public class Trap {
 
     // Static Data //////////////////////////////////////////////////////////////
 
-    /** a vector of weak references to all instances of Trap; used for retheming */
-    private static Hashtable allTraps = new Hashtable(1000);
-
     /** List of properties that cannot be trapped */
     private static final Hash PROHIBITED = new Hash(120, 3);
 
@@ -32,34 +29,20 @@ public class Trap {
         for(int i=0; i<p.length; i++) PROHIBITED.put(p[i], Boolean.TRUE);
     };
 
-    private static Object dummy = new Object();
-
 
     // Instance Members ////////////////////////////////////////////////////////
 
     /** the box on which this trap was placed */
     private Box trapee = null;
 
-    /** If this trap was actually placed on a root proxy, this is a reference to the proxy */
-    private JS rp = null;
-    
     /** the function for this trap */
     JS.CompiledFunction f = null;
 
-    /** the name of the property that this trap was placed on */
-    private String name = null;
-
     /** the next trap down the trap stack */
     private Trap next = null;
 
-    /** true if this is a read-trap */
-    boolean isreadtrap = false;
-
-    /** The nodeName of the Template whose script placed the trap. See Template.nodeName for more detail. */
-    private String placerNodeName = null;
-
-    /** our weak reference in the allTraps Hash */
-    private Weak myWeak = Platform.getWeak(this);
+    /** the property that the trap was placed on */
+    private Object name = null;
 
 
     // Static Methods //////////////////////////////////////////////////////////////////////////
@@ -69,140 +52,90 @@ public class Trap {
      *  @param trapee the box to place the trap on
      *  @param name the name of the property to trap on
      *  @param f the function to place as a trap
-     *  @param isreadtrap true iff this is a read (double-underscore) trap
-     *  @param rp if this trap is being placed via a rootproxy, this is that proxy object.
      */
-    static void addTrap(Box trapee, String name, JS.CompiledFunction f, boolean isreadtrap, JS rp) {
-
-        if (PROHIBITED.get(name) != null || name.startsWith("xwt_")) {
-            Log.log(Trap.class, "Error: you cannot place traps on special property \"" + name + "\"");
-            return;
-        }
-
-        // find out what script is currently running
-        JS.CompiledFunction placer = JS.Thread.fromJavaThread(java.lang.Thread.currentThread()).getCurrentCompiledFunction();
-        if (placer == null) { Log.log(Trap.class, "placer is null"); return; }
-        String placerNodeName = placer.getSourceName();
+    static void addTrap(Box trapee, Object name, JS.CompiledFunction f) {
+        if (trapee.traps == null) trapee.traps = new Hash(10, 3);
 
         // check if this script has already placed a trap on this property
-        if (trapee.traps == null) trapee.traps = new Hash(10, 3);
-        for(Trap t = (Trap)trapee.traps.get(name); t != null; t = t.next) if (t.placerNodeName.equals(placerNodeName)) return;
+        for(Trap t = (Trap)trapee.traps.get(name); t != null; t = t.next)
+            if (t.f == f) return;
         
         // actually place the trap
         Trap t = new Trap();
         t.next = (Trap)trapee.traps.get(name);
         trapee.traps.put(name, t);
         t.trapee = trapee;
-        t.f = f;
-        t.placerNodeName = placerNodeName;
-        t.rp = rp;
         t.name = name;
-        t.isreadtrap = isreadtrap;
-
-        // make sure that the surface knows when we place traps on these two properties (slightly inelegant)
-        if (trapee.surface != null && (name.equals("KeyPressed") || name.equals("KeyReleased"))) {
-            trapee.surface.keywatchers.removeElement(trapee);
-            trapee.surface.keywatchers.addElement(trapee);
-        }
+        t.f = f;
     }
 
-    /** returns the function placed as a trap on property <code>name</code> of box <code>b</code> by the currently-running script */
-    public static Trap getTrap(Box b, String name) {
-        if (b.traps == null) return null;
-
-        String currentFunctionNodeName = JS.Thread.fromJavaThread(java.lang.Thread.currentThread()).getCurrentCompiledFunction().getSourceName();
-        for(Trap cur = (Trap)b.traps.get(name); cur != null; cur = cur.next)
-            if (cur.placerNodeName.equals(currentFunctionNodeName))
-                return cur;
 
-        return null;
+    /**
+     *  deletes a trap.
+     *  @param trapee the box to remove the trap from
+     *  @param name the name of the property to trap on
+     *  @param f the function to remove
+     */
+    static void delTrap(Box trapee, Object name, JS.CompiledFunction f) {
+        if (trapee.traps != null) {
+            Trap t = (Trap)trapee.traps.get(name);
+            if (t.f == f) {
+                trapee.traps.put(name, t.next);
+                return;
+            }
+            for(; t.next != null; t = t.next)
+                if (t.next.f == f) {
+                    t.next = t.next.next;
+                    return;
+                }
+        }
+        Log.logJS("warning: tried to remove a trap that had not been placed");
     }
 
+
     // Instance Methods //////////////////////////////////////////////////////////////////////////
 
-    private Trap() { allTraps.put(myWeak, dummy); }
+    private Trap() { }
 
     /** the empty object, used for get-traps */
     public static JS.Array emptyargs = new JS.Array();
 
-    /** perform this trap -- arg.length == 0 if this is a get; otherwise it contains a single element to be put */
-    public Object perform(JS.Array jsArrayArgs) throws JS.Exn {
-        // TrapContext tc = TrapContext.get();
-        if (jsArrayArgs == null) jsArrayArgs = emptyargs;
-        TrapArgs args = new TrapArgs(this,jsArrayArgs);
-
-        // invoke the trap function
-        try {
-            if (!isreadtrap && args.length() == 0) return cascade(args);
-
-            if (f == null) {
-                if (Log.verbose) Log.log(this, "debug: reclaimed a dangling trap on property " + name);
-                Object ret = cascade(args);
-                delete();
-                return ret;
-            }
-            
-            Object ret = f.call(args);
-            
-            // autocascade if required
-            if(args.length() > 0 && !isreadtrap && !args.cascadeHappened) cascade(args);
-            
-            return ret;
-            
-        } finally {
-        
-        }
+    public Object perform() throws JS.Exn {
+        if (f.getNumFormalArgs() > 0) return cascade();
+        return f.call(new TrapArgs(this));
     }
     
-    public Object cascade(JS.Array args) {
-        // if we've hit the end of the trap stack, just do a put(,,,true)
-        if (next == null) {
-            if (args.length() == 0) return trapee.get(name, true);
-            trapee.put(name, args.elementAt(0), true);
-            return null;
-        }
-        return next.perform(args);
+    public void perform(Object val) throws JS.Exn {
+        if (f.getNumFormalArgs()== 0) cascade(val);
+        f.call(new TrapArgs(this, val));
+    }
+    
+    public Object cascade() {
+        if (next != null) return next.perform();
+        return trapee.get(name, true);
     }
 
-    /** removes this trap */
-    public void delete() {
-        for(Trap last = null, cur = (Trap)trapee.traps.get(name); cur != null; last = cur, cur = cur.next) {
-            if (cur != this) continue;
-            else if (last != null) last.next = cur.next;
-            else if (cur.next == null) trapee.traps.remove(name);
-            else trapee.traps.put(name, cur.next);
-        }
-        /* FIXME
-        if (trapee.surface != null && !trapee.is_trapped("KeyPressed") && !trapee.is_trapped("KeyReleased"))
-            trapee.surface.keywatchers.removeElement(trapee);
-        */
-        allTraps.remove(myWeak);
+    public void cascade(Object val) {
+        if (next != null) next.perform(val);
+        trapee.put(name, val, true);
     }
-    
+
     private static class TrapArgs extends JS.Array {
-        public boolean cascadeHappened;
         private Trap t;
-        public TrapArgs(Trap t,JS.Array args) {
-            int size = args.length();
-            setSize(size);
-            for(int i=0;i<args.length();i++) setElementAt(args.elementAt(i),i);
-            cascadeHappened = false;
-            this.t = t;
-        }
+        public TrapArgs(Trap t) { this.t = t; }
+        public TrapArgs(Trap t, Object value) { this.t = t; addElement(value); }
         
+        public void put(Object key, Object val) {
+            if (key.equals("cascade")) t.cascade(val);
+            else super.put(key, val);
+        }
+
         public Object get(Object key) {
             // common case
             if(!(key instanceof String)) return super.get(key);
-            
-            if(key.equals("trapee")) return t.trapee;
-            if(key.equals("trapname")) return t.name;
-            // FIXME: GETCALL when its available
-            if(key.equals("cascade")) return new JS.Callable() {
-                public Object call(JS.Array args) {
-                    if(args.length() != 0) cascadeHappened = true;
-                    return t.cascade(args);
-                }
-            };
+            if (key.equals("trapee")) return t.trapee;
+            if (key.equals("trapname")) return t.name;
+            if (key.equals("cascade")) return t.cascade();
             return super.get(key);
         }
     }
diff --git a/src/org/xwt/Weak.java b/src/org/xwt/Weak.java
deleted file mode 100644 (file)
index dc82fed..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.xwt;
-
-/** Encapsulates a weak reference; MSJVM and NSJVM don't use the standard Java2 java.lang.ref.WeakReference class */
-public interface Weak {
-
-    public Object get();
-
-}
index 0329a60..7e7e5fe 100644 (file)
@@ -12,6 +12,8 @@ import org.bouncycastle.util.encoders.Base64;
 /** Singleton class that provides all functionality in the xwt.* namespace */
 public final class XWT extends JS.Obj {
 
+    public Res resourceRoot = null;
+
     public static final XWT singleton = new XWT();
     private final JS xwtMath = new XWTMath();
     private final JS xwtString = new XWTString();
@@ -74,24 +76,6 @@ public final class XWT extends JS.Obj {
             return Res.stringToRes(args.elementAt(0).toString());
         }});
 
-        super.put("theme", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
-                if (args.length() != 2) return null;
-                if (args.elementAt(0) == null || args.elementAt(1) == null) return null;
-                for(int i=1; i<args.length(); i++) {
-                    if (args.elementAt(i) instanceof String) {
-                        String from = (String)args.elementAt(0);
-                        String to = (String)args.elementAt(i);
-                        if (Log.on) Log.log(this, "retheming from " + from + " to " + to);
-                        Resources.mapFrom.addElement(from);
-                        Resources.mapTo.addElement(to);
-                    }
-                }
-                JS.Callable callback = args.elementAt(args.length() - 1) instanceof JS.Callable ?
-                    (JS.Callable)args.elementAt(args.length() - 1) : null;
-                Template.retheme(callback);
-                return null;
-        }});
-            
         super.put("println", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
             if (args.length() != 1) return null;
             if (Log.on) Log.logJS(this, (args.elementAt(0) == null ? "**null**" : args.elementAt(0).toString()));
@@ -153,7 +137,7 @@ public final class XWT extends JS.Obj {
             Box ret = new Box();
             if (!(args.length() == 0 || args.elementAt(0) == null))
                 Template.getTemplate(args.elementAt(0).toString(),
-                                     Template.defaultImportList).apply(ret, null, null, callback, 0, 1);
+                                     Template.defaultImportList).apply(ret, null, null, callback, 0, 1, resourceRoot);
             for(int i=1; i<args.length(); i++)
                 if (args.elementAt(i) instanceof Box)
                     ret.put(ret.numChildren(), (Box)args.elementAt(i));
index 5771060..83b9b75 100644 (file)
@@ -10,6 +10,9 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
 
     // Fields and Accessors ///////////////////////////////////////////////
 
+    /** the number of formal arguments */
+    int numFormalArgs = 0;
+
     /** the source code file that this block was drawn from */
     private String sourceName;
     public String getSourceName() throws JS.Exn { return sourceName; }
@@ -323,7 +326,28 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                 break;
             }
             
-            
+            case ASSIGN_SUB: case ASSIGN_ADD: {
+                Object val = t.pop();
+                Object old = t.pop();
+                Object key = t.pop();
+                Object obj = t.peek();
+                if (obj instanceof org.xwt.Box && val instanceof CompiledFunction) {
+                    if (curOP == ASSIGN_ADD) {
+                        ((org.xwt.Box)obj).addTrap(key, val);
+                    } else {
+                        ((org.xwt.Box)obj).delTrap(key, val);
+                    }
+                    // skip over the "normal" implementation of +=/-=
+                    pc += ((Integer)arg[pc]).intValue() - 1;
+                } else {
+                    // use the "normal" implementation
+                    t.push(key);
+                    t.push(old);
+                    t.push(arg);
+                }
+                break;
+            }
+
             case ADD: {
                 int count = ((Number)arg[pc]).intValue();
                 if(count < 2) throw new Error("this should never happen");
@@ -333,31 +357,31 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                     Object left = t.pop();
                     if(left instanceof String || right instanceof String) t.push(JS.toString(left).concat(JS.toString(right)));
                     else t.push(new Double(JS.toDouble(left) + JS.toDouble(right)));
-                    break;
-                }
-                Object[] args = new Object[count];
-                while(--count >= 0) args[count] = t.pop();
-                if(args[0] instanceof String) {
-                    StringBuffer sb = new StringBuffer(64);
-                    for(int i=0;i<args.length;i++) sb.append(JS.toString(args[i]));
-                    t.push(sb.toString());
                 } else {
-                    int numStrings = 0;
-                    for(int i=0;i<args.length;i++) if(args[i] instanceof String) numStrings++;
-                    if(numStrings == 0) {
-                        double d = 0.0;
-                        for(int i=0;i<args.length;i++) d += JS.toDouble(args[i]);
-                        t.push(new Double(d));
-                    } else {
-                        double d=0.0;
-                        int i=0;
-                        do {
-                            d += JS.toDouble(args[i++]);
-                        } while(!(args[i] instanceof String));
+                    Object[] args = new Object[count];
+                    while(--count >= 0) args[count] = t.pop();
+                    if(args[0] instanceof String) {
                         StringBuffer sb = new StringBuffer(64);
-                        sb.append(JS.toString(new Double(d)));
-                        while(i < args.length) sb.append(JS.toString(args[i++]));
+                        for(int i=0;i<args.length;i++) sb.append(JS.toString(args[i]));
                         t.push(sb.toString());
+                    } else {
+                        int numStrings = 0;
+                        for(int i=0;i<args.length;i++) if(args[i] instanceof String) numStrings++;
+                        if(numStrings == 0) {
+                            double d = 0.0;
+                            for(int i=0;i<args.length;i++) d += JS.toDouble(args[i]);
+                            t.push(new Double(d));
+                        } else {
+                            double d=0.0;
+                            int i=0;
+                            do {
+                                d += JS.toDouble(args[i++]);
+                            } while(!(args[i] instanceof String));
+                            StringBuffer sb = new StringBuffer(64);
+                            sb.append(JS.toString(new Double(d)));
+                            while(i < args.length) sb.append(JS.toString(args[i++]));
+                            t.push(sb.toString());
+                        }
                     }
                 }
                 break;
index 853a973..5104bce 100644 (file)
@@ -157,6 +157,7 @@ public abstract class JS {
 
     /** a Callable which was compiled from JavaScript code */
     public static class CompiledFunction extends CompiledFunctionImpl {
+        public int getNumFormalArgs() { return numFormalArgs; }
         CompiledFunction(String sourceName, int firstLine, Reader sourceCode, Scope scope) throws IOException {
             super(sourceName, firstLine, sourceCode, scope);
         }
index cf0fdec..323d1dc 100644 (file)
@@ -268,6 +268,7 @@ class Parser extends Lexer implements ByteCodes {
             }
             consume(RP);
 
+            b2.numFormalArgs = numArgs + 1;
             b2.add(parserLine, POP);                                      // pop off the arguments array
             b2.add(parserLine, POP);                                      // pop off TOPSCOPE
             
@@ -309,14 +310,19 @@ class Parser extends Lexer implements ByteCodes {
             tok = -1;
         switch(tok) {
         case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH: case ASSIGN_RSH: case ASSIGN_URSH:
-        case ASSIGN_ADD: case ASSIGN_SUB: case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: {
+        case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: {
             b.add(parserLine, GET_PRESERVE);
             startExpr(b,  precedence[tok]);
+            int size = b.size();
+            if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) {
+                b.add(parserLine, tok);
+            }
             // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc) 
             b.add(parserLine, tok - 1, tok-1==ADD ? new Integer(2) : null);
             b.add(parserLine, PUT);
             b.add(parserLine, SWAP);
             b.add(parserLine, POP);
+            if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) b.set(size, tok, new Integer(b.size() - size));
             break;
         }
         case INC: case DEC: { // postfix
@@ -408,7 +414,12 @@ class Parser extends Lexer implements ByteCodes {
             break;
         }
         case DOT: {
-            consume(NAME);
+            // support foo..bar syntax for foo[""].bar
+            if (peekToken() == DOT) {
+                string = "";
+            } else {
+                consume(NAME);
+            }
             b.add(parserLine, LITERAL, string);
             continueExprAfterAssignable(b,minPrecedence);
             break;