// FIXME memory leak
static Hash boxToCursor = new Hash(500, 3);
- static final Font DEFAULT_FONT = Font.getFont((Stream)Main.builtin.get(JS.S("fonts/vera/Vera.ttf")), 10);
+ static final Font DEFAULT_FONT;
+ static {
+ try { DEFAULT_FONT = Font.getFont(Main.builtin.get(JS.S("fonts/vera/Vera.ttf")), 10); }
+ catch(JSExn e) { throw new Error("Error loading default font: " + e); }
+ }
// Flags //////////////////////////////////////////////////////////////////////
case "date": return new JSDate(a, b, c, rest, nargs);
case "net.rpc.soap": return new SOAP(JS.toString(a), "", JS.toString(b), JS.toString(c));
// FIXME support object dumping
- case "log.debug": JS.debug(a== null ? "**null**" : a.toString()); return null;
- case "log.info": JS.info(a== null ? "**null**" : a.toString()); return null;
- case "log.warn": JS.warn(a== null ? "**null**" : a.toString()); return null;
- case "log.error": JS.error(a== null ? "**null**" : a.toString()); return null;
+ 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;
//#end
switch (nargs) {
// FEATURE: move this into builtin.xwar
public Blessing bless(JS b) throws JSExn { return new Ibex.Blessing(b, this, null, null); }
// FIXME: Does this really need to extends JS.Clone?
+ // FEATURE: Mandate that Blessings use only String keys?
public static class Blessing extends JS.Clone {
private Ibex ibex;
private Template t = null;
} catch (IOException f) { /* DELIBERATE */ }
return null;
}
- public JSScope getStatic() {
+ public JSScope getStatic() throws JSExn {
try {
if (t == null) {
+ // FEATURE: Might want to handle the ".t" part better
JS res = (JS) parent.get(JS.S(JS.toString(parentkey) + ".t"));
- t = Template.buildTemplate(res.unclone().toString(), res, ibex);
+ // FIXME: need a better description (Stream.toString())
+ t = Template.buildTemplate(JS.toString(parentkey), res, ibex);
}
- return t.staticScope;
+ return t != null ? t.staticScope : null;
} catch (Exception e) {
Log.error(this, e);
return null;
}
}
public JS call(JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
- // GROSS hack
- if (nargs != 1 && nargs != 9999) throw new JSExn("FIXME can only call with one arg");
+ if (nargs != 1) throw new JSExn("can only call a template with one arg");
getStatic();
if (t == null) throw new JSExn("No such template " + parentkey);
- if (nargs == 9999) /*return t;*/ throw new Error("FIXME"); // FIXME: 9999 stuff
if(!(a instanceof Box)) throw new JSExn("can only apply templates to boxes");
t.apply((Box)a);
return a;
}
+ // FEATURE: This is a gross hack
+ Template getTemplate() throws JSExn {
+ getStatic();
+ if (t == null) throw new JSExn("No such template " + JS.debugToString(parentkey));
+ return t;
+ }
}
}
final Ibex ibex = new Ibex(rr);
org.ibex.graphics.Surface.scarImage =
- Picture.load((Stream)Main.builtin.get(JS.S("org/ibex/core/builtin/scar.png")),
+ Picture.load(Main.builtin.get(JS.S("org/ibex/core/builtin/scar.png")),
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);
String id = null; ///< the id of this box
String redirect = null; ///< the id of the redirect target; only meaningful on a root node
- private String[] keys; ///< keys to be "put" to instances of this template; elements correspond to those of vals
+ private JS[] keys; ///< keys to be "put" to instances of this template; elements correspond to those of vals
private JS[] vals; ///< values to be "put" to instances of this template; elements correspond to those of keys
private String[] urikeys;
private String[] urivals;
for(int i=0; keys != null && i < keys.length; i++) {
if (keys[i] == null) continue;
- String key = keys[i];
+ JS key = keys[i];
JS val = vals[i];
if ("null".equals(val)) val = null;
// FIXME: should we be resolving all of these in the XML-parsing code?
}
}
- b.putAndTriggerTraps(JS.S(key), val);
+ b.putAndTriggerTraps(key, val);
}
}
InputStream is = Stream.getInputStream(s);
Ibex.Blessing b = Ibex.Blessing.getBlessing(s).parent;
while(b != null) {
- if(b.parentkey != null) initial_uri = b.parentkey + (initial_uri.equals("") ? "" : "." + initial_uri);
+ if(b.parentkey != null) initial_uri = JS.toString(b.parentkey) + (initial_uri.equals("") ? "" : "." + initial_uri);
b = b.parent;
}
initial_uri = "";
break;
}
+ // FIXME: This is all wrong
if (!("ibex://ui".equals(c.getUri()) && "box".equals(c.getLocalName()))) {
String tagname = (c.getUri().equals("") ? "" : (c.getUri() + ".")) + c.getLocalName();
// GROSS hack
try {
// GROSSER hack
// t.prev2 = (Template)t.ibex.resolveString(tagname, false).call(null, null, null, null, 9999);
- throw new Error("FIXME - 9999 thing"); // FIXME:9999 thing
+ if(t.prev2 != null) throw new Error("FIXME: t.prev2 != null");
+ t.prev2 = ((Ibex.Blessing)t.ibex.resolveString(tagname, false)).getTemplate();
} catch (Exception e) {
Log.error(Template.class, e);
}
return ((String)a).compareTo((String)b);
} });
- t.keys = new String[keys.size()];
+ t.keys = new JS[keys.size()];
t.vals = new JS[vals.size()];
- keys.copyInto(t.keys);
- vals.copyInto(t.vals);
-
+
// convert attributes to appropriate types and intern strings
for(int i=0; i<t.keys.length; i++) {
- t.keys[i] = t.keys[i].intern();
-
- String valString = t.vals[i].toString();
+ // FEATURE: Intern
+ t.keys[i] = JS.S((String)keys.elementAt(i));
+ String valString = (String) vals.elementAt(i);
if (valString.equals("true")) t.vals[i] = JS.T;
else if (valString.equals("false")) t.vals[i] = JS.F;
/** encapsulates a single font (a set of Glyphs) */
public class Font {
- private Font(Stream stream, int pointsize) { this.stream = stream; this.pointsize = pointsize; }
+ private Font(JS stream, int pointsize) { this.stream = stream; this.pointsize = pointsize; }
private static boolean glyphRenderingTaskIsScheduled = false;
public final int pointsize; ///< the size of the font
- public final Stream stream; ///< the stream from which this font was loaded
+ public final JS stream; ///< the stream from which this font was loaded
public int max_ascent; ///< the maximum ascent, in pixels
public int max_descent; ///< the maximum descent, in pixels
boolean latinCharsPreloaded = false; ///< true if a request to preload ASCII 32-127 has begun
static final Hashtable glyphsToBeCached = new Hashtable();
static final Hashtable glyphsToBeDisplayed = new Hashtable();
private static Cache fontCache = new Cache(100);
- public static Font getFont(Stream stream, int pointsize) {
+ 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));
return ret;
// FEATURE: use streams, not memoryfont's
// FEATURE: kerning pairs
private static final Runtime rt;
- private static Stream loadedStream;
+ private static JS loadedStream;
private static int loadedStreamAddr;
static {
private static void rtCheck() { if(rt.getState() != Runtime.PAUSED) throw new Error("Freetype exited " + rt.exitStatus()); }
- private static void loadFontByteStream(Stream res) {
+ private static void loadFontByteStream(JS res) {
if(loadedStream == res) return;
try {
- Log.info(Font.class, "loading font " + res);
+ Log.info(Font.class, "loading font " + JS.debugToString(res));
InputStream is = Stream.getInputStream(res);
byte[] fontstream = InputStreamToByteArray.convert(is);
rt.free(loadedStreamAddr);
/** turns a stream into a Picture.Source and passes it to the callback */
public static Picture load(final JS stream, final Task callback) {
+ if(stream == null) throw new NullPointerException();
Picture ret = (Picture)cache.get(stream);
- if (ret == null) cache.put(stream, ret = Platform.createPicture(stream));
+ if (ret == null) {
+ ret = Platform.createPicture(stream);
+ if(ret == null) throw new NullPointerException();
+ cache.put(stream, ret);
+ }
final Picture p = ret;
if (!ret.isLoaded && callback != null) {
+ // FEATURE: This is kind of ugly - shouldn't need a blessing
final Ibex.Blessing b = Ibex.Blessing.getBlessing(stream);
new java.lang.Thread() { public void run() {
InputStream in = null;
Platform.clipboardReadEnabled = false;
}
}
- public String toString() { return "Message [name=" + name + ", value=" + value + "]"; }
+ public String toString() { return "Message [name=" + name + ", value=" + JS.debugToString(value) + "]"; }
}
// 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); }
+ private static String taskDesc(Task t) { return t instanceof JS ? JS.debugToString((JS)t) : t.toString(); }
+ public static void add(Task t) { Log.debug(Scheduler.class, "scheduling " + taskDesc(t)); Scheduler.runnable.append(t); }
public static void init() { if (singleton == null) (singleton = Platform.getScheduler()).run(); }
private static Task current = null;
s._mousey = s.mousey;
}
}
- Log.debug(Scheduler.class, "performing " + current);
+ Log.debug(Scheduler.class, "performing " + taskDesc(current));
current.perform();
}
renderAll();