--- /dev/null
+<ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org">
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Introduction">
+
+ <i>
+ If you are reading the html version of this document and are
+ thinking of printing it out, you might be interested in the nicely
+ typeset <link url="reference.pdf" text="pdf version"/> produced
+ with LaTeX.
+ </i>
+
+ This document is a <b>reference</b>. It is not a
+ <b>specification</b> or a
+ <b>tutorial</b>.
+
+ This document does not guide the user gently through examples (as a
+ tutorial would), and it doesn't provide enough detail and formality
+ for a third party to construct a compatible re-implementation of the
+ Ibex Core (as a specification would).
+
+ Rather, the goal of this document is to completely describe every
+ aspect of the environment that the Ibex Core provides to client
+ applications, from the bottom up. If you want to be an Ibex expert,
+ this is the right document to read. It is assumed that you are already
+ familiar with XML and with either JavaScript or ECMAscript.
+
+ If you need to use or rely on some behavior you notice in the Ibex
+ Core, but which is not clearly defined here, please post to <link
+ url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
+
+ <section title="Key Concepts">
+
+ <definition term="The Core">
+ Ibex itself; the native code (or Java bytecode) that runs on
+ the client. This term does not include the <i>Wildebeest</i>
+ or the <i>UI</i></definition>
+
+ <definition term="The UI / The Application">
+ A set of files (mostly XML, JavaScript, and PNG images)
+ bundled up in a zip archive, ending with the "<t>.ibex</t>"
+ extension. Together, these files specify the appearance and
+ behavior of the application's user interface.
+ </definition>
+
+ <definition term="The Server">
+ We will use the term "the server" to refer to any other
+ computer which the client makes XML-RPC or SOAP calls
+ to. Note that it is possible for the client and server to be
+ the same machine.</definition>
+
+ <definition term="Wildebeest">
+ This is a very small piece of code that is downloaded the
+ first time a client uses Ibex. It downloads the Ibex core,
+ verifies its signature, and launches it with the appropriate
+ parameters indicating where to find the initial UI.
+ Wildebeest works differently on every platform, and is outside
+ the scope of this document.</definition>
+
+ <definition term="put/write">
+ In ECMAscript, when you change the value of a property on an
+ object, you are <i>putting</i> to that property, or
+ <i>writing</i> to it. For example, the ECMAscript expression
+ "<t>foo.bar = 5</t>" <i>puts</i> the value 5 to the bar
+ property on object foo.</definition>
+
+ <definition term="get/read">
+ In ECMAscript, when you access the value of a property on an
+ object, you are <i>getting</i> that property, or
+ <i>reading</i> from it. For example, the ECMAscript
+ expression "<t>return (3 + foo.bar)</t>" <i>gets</i> the
+ value of bar property on object foo and then adds 3 to it
+ before returning the result.</definition>
+
+ <definition term="JavaScript">
+ We will use the terms JavaScript and ECMAScript
+ interchangeably in this document. The Ibex interpreter is not
+ completely ECMA-compliant, however (see <link
+ appendix="ECMAscript compliance"/> for details).
+ </definition>
+
+ </section>
+
+ <section title="Life Cycle of an Ibex Application">
+
+ <image url="lifecycle.pdf" caption="The Lifecycle of an Ibex Application"/>
+
+ A user typically begins an Ibex session by clicking on a link to
+ an Ibex application. This link serves the {\tt launch.html} file
+ to the user's browser, which in turn downloads the appropriate
+ {\it Wildebeest} -- currently either an ActiveX Control
+ (Win32/MSIE), XPInstaller (Mozilla), or Signed Applet (all
+ others).
+
+ The Wildebeest downloads the appropriate core for the user's
+ machine and verifies its digital signature. It then launches the
+ core, which downloads the UI (an <t>.ibex</t> archive), loads it,
+ applies the <t>main.t</t> template (found in the archive), and
+ renders it onto the screen, running any associated JavaScript
+ code.
+
+ The user interacts with the application by clicking and moving the
+ mouse, and by pressing keys on the keyboard. These actions trigger
+ fragments of JavaScript code which are designated to handle events.
+ This JavaScript code can then relay important information back to the
+ server using XML-RPC or SOAP, or it can modify the structure and
+ properties of the user interface to change its appearance, thereby
+ giving feedback to the user.
+
+ The Ibex core quits when the last remaining surface has been destroyed.
+
+ </section>
+
+
+ <section title="Surfaces">
+
+ <image url="offscreen.pdf" width="2in"
+ caption="An Ibex surface positioned at (83,0)"/>
+ Each top-level window in an Ibex UI is called a
+ <i>surface</i>. There are two kinds of surfaces: <i>frames</i>,
+ which usually have a platform-specific titlebar and border, and
+ <i>windows</i>, which never have any additional platform-specific
+ decorations.
+
+ Whenever we refer to the size or position
+ of a surface, we are referring to the size or position of the
+ UI-accessible portion of the surface; this does not include any
+ platform-specific decorations. This means that if you set the
+ position of a frame to (0,0), the platform-specific titlebar will
+ actually be off the screen on most platforms (it will be above and
+ to the left of the top-left corner of the screen).
+
+ Surfaces are not actual JavaScript objects; you cannot obtain a
+ reference to a surface. However, each surface is uniquely identified
+ by its <i>root box</i>, described in the next section.
+
+ </section>
+
+ <section title="Boxes">
+
+ A <i>box</i> is the fundamental unit from which all Ibex user
+ interfaces are built. Boxes can contain other boxes (referred to as
+ its <i>children</i>). Each surface has a single box associated with
+ it called the <i>root box</i>; the root box and its children (and
+ its children's children, and so on) form the surface's <i>box
+ tree</i>.
+
+ There are three ways to think of a box:
+ <list>
+
+ As a rendered visualization on the screen (the "<i>Visual Representation</i>")
+
+ As a JavaScript object (the "<i>Object Representation</i>")
+
+ As as an XML tag (the "XML Template Representation").
+
+ </list>
+
+ <image url="threeviews.pdf" caption="The three representations of an Ibex box"/>
+
+ All three representations are equally valid, and being able to
+ figure out what an action in one representation would mean in terms
+ of the other two representations is crucial to a solid understanding
+ of Ibex.
+
+ </section>
+</section>
+
+<section title="The XML Template Representation">
+
+ A template (discussed in the next section) is an XML file which acts
+ as a blueprint for constructing a tree of boxes. We call this
+ construction process <i>applying</i>, since unlike
+ <i>instantiation</i> in object-oriented programming systems, you
+ always apply a template to a pre-existing box, and you can apply
+ multiple templates to the same box.
+
+ Each XML tag corresponds to a single box, or to another template
+ which will be applied to that box. For example, a <t>scrollbar</t>
+ template, when applied, will construct a tree of boxes which has the
+ visual appearance and behavior of a scrollbar.
+
+ Although it is useful to think of the XML tags as being boxes, keep
+ in mind that the XML representation is only a blueprint for
+ constructing a tree of JavaScript objects. Once the template has
+ been instantiated, the XML is effectively "thrown away", and
+ JavaScript code is free to alter the boxes. Once the process of
+ applying a template is complete, Ibex completely forgets the fact
+ that it has applied a particular template to a particular box. One
+ consequence of this approach is that if you think of templates as
+ classes, then Ibex has no equivalent for Java's <t>instanceof</t>
+ operator.
+
+ Each template is an XML document whose root element is
+ <t><ibex></t>. Here is a sample template file:
+
+ <pre>
+ <ibex xmlns:lib="ibex.lib">
+
+ <meta:doc>
+ This is a cool widget.
+ </meta:doc>
+
+ // this code is executed only once
+ static = { instances : [] };
+
+ // this element applies the ibex.lib.focusable template
+ <lib:focusable/>
+
+ <ui:box cols="5">
+ static.instances.push(thisbox);
+ <ui:box id="container"/>
+ <ui:checkbox/>
+ <ui:box>
+ <lib:scrollbar/>
+ </ui:box>
+ </ui:box>
+ </ibex>
+ </pre>
+
+ The following two namespaces are predefined and need not be declared
+ using <t>xmlns</t>:
+
+ <definition term="meta">
+ <t>http://xmlns.ibex.org/meta</t>
+
+ This will be referred to as the "<t>meta</t> namespace" in the
+ remainder of this document.
+ </definition>
+
+ <definition term="ui">
+ <t>http://xmlns.ibex.org/ui</t>
+
+ This will be referred to as the "<t>ui</t> namespace" in the
+ remainder of this document.
+ </definition>
+
+ Additionally, the default namespace for the document will be set to
+ the template's package FIXME.
+
+ <section title="Static Code">
+
+ If the root <t><ibex></t> element contains any non-whitespace
+ text content, this text is interpreted as JavaScript code and is
+ executed the first time the template is referenced. This code is
+ executed in a fresh scope containing two predefined properties:
+
+ <definition term="ibex">
+ The Ibex Object (described in <ref section="The Ibex Object"/>)
+ </definition>
+
+ <definition term="static">
+ A reference to this template's <i>static object</i>, which is
+ initially <t>null</t>. The static object can be accessed (read
+ and written) from both static scripts as well as instance
+ scripts in a particular template. FIXME
+ </definition>
+
+ </section>
+
+ <section title="Metadata">
+
+ Any immediate children of the root element which are in the
+ <t>meta</t> namespace are treated as metadata and are exempted from
+ the rest of the template application process. Currently only one
+ type of metadata element is defined:
+
+ <list>
+ <t><meta:doc></t>: structured documentation for the
+ template.
+ </list>
+
+ </section>
+
+ <section title="Other Elements">
+
+ All remaining children of the root element are treated as elements
+ to be <i>applied</i> to the box, in the order in which they appear
+ in the file using the following procedure.
+
+ <remark text="While this process outlined below sounds very
+ complex, it actually works pretty intuitively. The
+ description below is given in great detail since
+ most applications will wind up being unintentionally
+ dependent on subtle features of this process.
+ However, most of the time you can just pretend that
+ the XML tags and the boxes are the same thing."/>
+
+ <heading title="Intuitive Description"/>
+
+ ... FIXME
+
+ During a box initialization, script-private references to a
+ box's descendants with <t>id</t> attributes are placed on the
+ box. These references allow scripts on that box to easily refer
+ to descendant nodes created by the template in which the script
+ appears. For example, these two blocks of code have exactly the
+ same effect:
+
+ <pre>
+ <ui:box> <ui:box>
+ <ui:box id="foo"/> <ui:box/>
+ $foo.color = "red"; var $foo = this[0];
+ $foo.color = "red";
+ </ui:box> </ui:box>
+ </pre>
+
+ <heading title="Precise Description"/>
+
+ To apply an XML tag <t><b>x</b></t> to a box <t><b>b</b></t>, perform the following
+ operations, in this order:
+
+ <list type="ordered">
+
+ Allocate a fresh scope <t><b>s</b></t> whose parent scope is
+ <t><b>b</b></t>.
+
+ Process each child element or text segment of <t><b>x</b></t>
+ in the order they appear in the document:
+
+ <list>
+
+ Treat each text segment <t><b>t</b></t> as JavaScript code
+ and execute it with <t><b>s</b></t> as the root scope.
+
+ For each child element <t><b>x'</b></t> of <t><b>x</b></t>:
+
+ <list>
+ Create a new box <t><b>b'</b></t>.
+
+ If the name of tag <t><b>x'</b></t> is not
+ "<t>box</t>" in the <t>ui</t> namespace, prepend the
+ tag's namespace identifier uri (if any) to the name of
+ the tag, and use the result as a key to retrieve a
+ property from the root stream (defined later).
+ Interpret the resulting stream as a template and apply
+ that template to <t><b>b'</b></t>.
+
+ (recursively) apply <t><b>x'</b></t> to <t><b>b'</b></t>.
+
+ If <t><b>x'</b></t> has an <t>id</t> attribute, declare a variable
+ in <t><b>s</b></t> whose name is the value of the <t>id</t>
+ attribute, prefixed with the <t>$</t> character, and whose
+ value is <t><b>b'</b></t>
+
+ Copy any <t>$</t>-variables created during the application
+ of <t><b>x'</b></t> into scope <t><b>s</b></t>.
+
+ Append <t><b>b'</b></t> as the last child of <t><b>b</b></t>.
+ </list>
+ </list>
+
+ Apply any attributes on <t><b>x</b></t> to <t><b>b</b></t>, except for
+ <t>id</t>. Since XML specifies that the order of attributes
+ cannot be significant, Ibex processes attributes in
+ alphabetical order by attribute name. For example, if
+ <t><b>x</b></t> has the attribute <t>foo="bar"</t>, then the
+ equivalent of the statement <t>B.foo="bar";</t> will be
+ performed, with the following exceptions:
+
+ <list>
+ If the value portion of the attribute is the string
+ "<t>true</t>", put the boolean <t>true</t>. If the
+ value is "<t>false</t>", put the boolean <t>false</t>.
+
+ If the value is a valid ECMAscript number, put it as a
+ number (instead of a string).
+
+ If the value begins with a dollar sign (<t>$</t>),
+ retrieve the value of the corresponding variable in
+ <t><b>s</b></t> and use that value instead.
+
+ If the value begins with a dot (<t>.</t>), prepend the
+ attributes' namespace identifier uri (if any) and
+ interpret the remainder as a property to be retrieved from
+ the root stream (defined later).
+ </list>
+ </list>
+
+ <heading title="Initialization Invariants"/>
+
+ The last two steps are referred to as the <i>initialization</i> of the
+ node. There are two important aspects of this ordering to be aware of:
+
+ <list type="unordered">
+
+ A given box will be fully initialized before its parent is
+ given a reference to that box. This way, parents can be
+ certain that they will never wind up accessing a box when it
+ is in a partially-initialized state.
+
+ Attributes are applied <i>after</i> scripts are run so that
+ the attributes will trigger any <i>traps</i> (defined later)
+ placed by the script.
+
+ </list>
+
+ </section>
+
+</section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Layout and Rendering">
+
+ <section title="Visual Components">
+
+ Each box occupies a rectangular region on the surface. The visual
+ appearance of a surface is created by rendering each box in its tree.
+ Unless the <t>clip</t> attribute is <t>false</t>, each box will
+ clip its childrens' visual representations to its own, so that the
+ children appear "confined to" the parent. Children are rendered after
+ their parents so they appear "on top of" their parents.
+
+ Each box has two major visual components, each with subcomponents:
+
+ FIXME: diagram
+
+ <definition term="path">
+
+ A box's <t>path</t> consists of zero or more lines and curves.
+ The path may be filled with a color, gradient, or texture, and
+ may be stroked with a line of a given thickness and color. If
+ the path is not specified, it defaults to the perimiter of the
+ box. [<i>Note: Vector Graphics support (including the ability
+ to set the <t>path</t> property to anything other than the
+ default) is currently not implemented</i>].
+
+ A path also has:
+
+ <list>
+ an associated <t>strokecolor</t>, which is a color
+
+ an associated <t>strokewidth</t>, which is a number
+ specifying the width of the stroke. [<i>Note: Vector
+ Graphics support (including the <t>strokewidth</t>
+ property) is currently not implemented</i>]
+
+ a <t>fill</t>, which is either a color, gradient, or
+ texture
+ </list>
+ </definition>
+
+ <definition term="text">
+
+ Each box also has a single line of <t>text</t>, whose
+ appearance is determined by its:
+
+ <list>
+ associated <t>font</t>, which can be any font supported by
+ the <link url="http://www.freetype.org" text="FreeType2"/>
+ library.
+
+ an associated <t>fontsize</t> in <i>pixels</i>
+
+ an associated <t>textcolor</t>
+ </list>
+ </definition>
+
+ These eight components plus the size of a box fully specify its
+ appearance. Every single box you see in Ibex is drawn only on the
+ basis of these components and its size.
+ </section>
+
+ <section title="Size and Position">
+
+ The size and position of every box is determined by its
+ properties, its childrens' sizes, and its parent's size and
+ position. Box layout and rendering happens in four phases:
+ <i>packing</i>, <i>constraining</i>, <i>placing</i>, and
+ <i>rendering</i>. The Core is careful to only perform a phase on
+ a box if the box has changed in a way that invalidates the work
+ done the last time that phase was performed. The packing and
+ constraining phases are performed in a single traversal of the
+ tree (packing is preorder, constraining is postorder), and the
+ placing and rendering phases are performed in a second traversal
+ of the tree (first placing, then rendering, both preorder).
+
+ For brevity, the rest of this chapter deals only with width and
+ columns. Height and rows is treated identically and independently.
+ Also, it is important to note that the term <i>minimum width</i> is
+ not the same thing as the property <t>minwidth</t>, although they
+ are closely related.
+
+ <heading title="The Size of the Root Box"/>
+
+ When the user resizes a window, Ibex changes the root box's
+ <t>maxwidth</t> and <t>maxheight</t> to match the size chosen by
+ the user and then determines the root box's size using the same sizing
+ rules it uses for other boxes.
+
+ Ibex will always attempt to prevent the
+ user from making the surface smaller than the root box's
+ <t>minwidth</t> and <t>minheight</t>. If the <t>hshrink</t> or
+ <t>vshrink</t> flag is set, Ibex will try to prevent the user from
+ resizing the surface at all. However, not all platforms give Ibex
+ enough control to do this.
+
+ <image url="alignmentpoint.pdf" caption="The effect of alignment points on layout" width="3in"/>
+ <heading title="The alignment point"/>
+
+ When talking about positioning, we will often refer to the
+ <i>alignment point</i>.
+
+ If the <t>align</t> property is "<t>center</t>", then the
+ alignment point is the center of the box.
+
+ If the <t>align</t> property is "<t>topleft</t>",
+ "<t>bottomleft</t>", "<t>topright</t>", or
+ "<t>bottomright</t>", then the alignment point is
+ corresponding corner of the box.
+
+ If the <t>align</t> property is "<t>top</t>",
+ "<t>bottom</t>", "<t>right</t>", or "<t>left</t>", then
+ the alignment point is middle of the corresponding edge of the
+ box.
+
+ When positioning a child box, the alignment point is determined by
+ the <i>parent's</i> <t>align</t> property. When rendering a
+ visual element (a texture, path, or text string) within a box, the
+ alignment point is determined by the <i>box's own</i> <t>align</t>
+ property.
+
+ A simple way to think about this is that whenever there are two boxes
+ involved in the decision, you should use the parent's alignment point.
+
+ <section title="Packing">
+
+ A grid of <i>cells</i> is created within the parent. If the
+ parent's <t>cols</t> property is set to 0, the cell grid has an
+ infinite number of columns. Either <t>cols</t> or <t>rows</t>
+ must be zero, but not both.
+
+ If a child's <t>visible</t> property is <t>false</t>, it does
+ not occupy any cells (and is not rendered). Otherwise, each child
+ occupies a rectangular set of cells <t>child.colspan</t> cells
+ wide and <t>child.rowspan</t> cells high.
+
+ The Core iterates over the cells in the grid in the following
+ order: if <t>rows</t> is 0, the Core iterates across each column
+ before proceeding to the next row; otherwise rows come before
+ columns. At each cell, the Core attempts to place the <i>first
+ remaining unplaced child's</i> top-left corner in that cell
+ (with the child occupying some set of cells extending down and
+ to the right of that cell). If the parent has a fixed number of
+ columns and the child's <t>colspan</t> exceeds that limit, the
+ child is placed in column zero regardless, but only occupies the
+ available set of cells (it does not "hang off the end" of the
+ box). <image url="layout.pdf" width="1in"/>
+
+ <pre>
+ <ui:box cols="3">
+ <ui:box id="1" />
+ <ui:box id="2" rowspan="2" />
+ <ui:box id="3" colspan="2" />
+ <ui:box id="4" />
+ <ui:box id="5" colspan="2" />
+ </ui:box>
+
+
+
+ </pre>
+
+ </section>
+
+ <section title="Constraining">
+
+ Each box's minimum width is computed recursively as the
+ maximum of:
+
+ <list>
+ Its <t>minwidth</t>
+
+ The width of the box's <t>text</t> (after applying the
+ box's <t>transform</t>) [<i>Note: Vector Graphics support
+ (including the <t>transform</t> property) is currently not
+ implemented</i>].
+
+ The width of the box's path (after applying the box's
+ <t>transform</t>) <i>if the box is <t>packed</t></i>.
+
+ The width of the bounding box enclosing the box's cells.
+ </list>
+
+ The minimum width of each cell is computed as the minimum
+ width of the box occupying it divided by the box's
+ <t>colspan</t>.
+
+ If a box's <t>hshrink</t> property is set to
+ <t>true</t>, the box's maximum width is the same as its
+ minimum width; otherwise it is the box's
+ <t>maxwidth</t>.
+
+ The maximum width of each cell is the <t>maxwidth</t> of
+ the box occupying it divided by the box's
+ <t>colspan</t>.
+ </section>
+
+ <section title="Placing">
+
+ Each column's <i>actual width</i> is set to the maximum
+ <i>minimum width</i> of all the cells in that column.
+ <b>NOTE:</b> although a column or row can be sized smaller
+ than its "minimum width" or larger than its "maximum width", a
+ box will <i>never</i> be smaller than its <t>minwidth</t> or
+ larger than its <t>maxwidth</t>.
+
+ Each column's maximum width is the largest maximum width of
+ the cells in that column, but no smaller than the column's
+ minimum width.
+
+ A value <t>k</t> is chosen such that when each column's width
+ is set to <t>min(maximum width, max(minimum width, k))</t>,
+ the sum of all the column widths equals the parent's width.
+ If no such value exists, positive or negative infinity is used
+ (whichever is appropriate). Each column is then set to the
+ width dictated by <t>k</t>.
+
+ Next, the rows and columns are positioned within the parent
+ box. The rows and columns are transformed according to the
+ parent's <t>transform</t> property [<i>Note: Vector Graphics
+ support (including the <t>transform</t> property) is currently
+ not implemented</i>]., and the bounding box of the resulting
+ cells are placed such that the cells' alignment point
+ coincides with the parent's alignment point (both alignment
+ points are determined by the parent's <t>align</t> property).
+
+ <image url="grid.pdf" caption="Positioning grid cells"/>
+
+ <b>Packed boxes:</b> Each packed box's actual position
+ and size is then set to the aggregation of the actual sizes of
+ the cells it spans. If this size exceeds the box's maximum
+ width, the box is sized to its maximum width and centered
+ horizontally within the space occupied by its cells.
+
+ <b>Non-packed boxes</b>: each non-packed box is transformed
+ according to the parent's <t>transform</t> property and then
+ positioned so that its alignment point is <t>(child.x,
+ child.y)</t> pixels from the parent's alignment point (both
+ alignment points are determined by the parent's <t>align</t>
+ property).
+
+ </section>
+ </section>
+
+ <section title="Rendering">
+
+ Boxes are rendered in a depth-first, pre-order traversal. Note that
+ this may cause a non-packed box to overlap its siblings.
+
+ <list type="ordered">
+
+ If the box's <t>transform</t> property is non-null, the
+ coordinate space is transformed accordingly for the rest of
+ this phase and for the rendering of all children. [<i>Note:
+ Vector Graphics support (including the <t>transform</t>
+ property) is currently not implemented</i>].
+
+ If the box is packed and has a non-<t>null</t> path, the
+ path is translated such that the alignment point of the path's
+ bounding box coincides with the box's alignment point (both
+ alignment points are determined by the box's <t>align</t>
+ property).
+
+ If a box has a path, that path is filled with the color,
+ gradient, or image specified by the <t>fill</t> property and
+ stroked with the color and width specified by the
+ <t>strokecolor</t> and <t>strokewidth</t> properties.
+
+ If the box has a non-null <t>text</t> attribute,
+ the text is rendered in <t>font</t> with size
+ <t>fontsize</t> and color <t>textcolor</t>. The text is
+ then translated such that the alignment point of the text's
+ bounding box coincides with the box's alignment point (both
+ alignment points are determined by the box's <t>align</t>
+ property).
+
+ The box's children are rendered (pre-order traversal).
+
+ </list>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Box Properties">
+
+ Each box is a full-fledged ECMAscript object, and can store
+ key-value pairs as properties. Some of these keys have special
+ meaning, which will be explained later. Each box's numeric
+ properties hold its <i>child boxes</i>.
+
+ <section title="Rendering Properties">
+
+ Every box has several special properties which control how it is
+ drawn. In general, if you put an
+ invalid value to a special property, no action will be taken -- the
+ put will be ignored.
+
+ <property name="strokecolor" type="string" default="clear">
+
+ If the value is a 5-character hex string (<t>#RGB</t>),
+ 7-character hex string (<t>#RRGGBB</t>), 9-character hex
+ string (<t>#AARRGGBB</t>), the box's stroke color will be set
+ to that color.
+
+ If the value is one of the <link
+ url="http://www.color.org/ICC-1A_1999-04.PDF"
+ text="ICC"/> colors (the same set of color names
+ supported by SVG), the stroke color be set to that color.
+
+ If the value is <t>null</t>, the stroke color will be set
+ to clear (<t>#00000000</t>).
+ </property>
+
+ <property name="strokewidth" type="int" default="1">
+ The width (in pixels) to stroke the path with.
+ </property>
+
+ <property name="fill">
+ This property can be set to any of the values specified for
+ <t>strokecolor</t>.
+ Alternatively, if the value written is an object, its stream
+ will be read and interpreted as a PNG, GIF, or JPEG image,
+ which will become the texture for this box, and the box's
+ <t>minwidth</t> and <t>minheight</t> properties will be
+ automatically set to the dimensions of the image.
+ </property>
+
+ <property name="path" type="string" default='""'>
+ The box's path. The grammar and feature set supported are
+ identical to that specified in <link
+ url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
+ section 8"/>.
+ </property>
+
+ <property name="text" type="string" default='""'>
+ The box's text; writing <t>null</t> to this property sets it
+ to <t>""</t>.
+ </property>
+
+ <property name="textcolor" type="number" default="black">
+ The color in which to render the font; accepts the same values as <t>strokecolor</t>.
+ </property>
+
+ <property name="font" type="stream" default=".ibex.ui.font.sansserif">
+ When an object is written to this property, its stream is read
+ using the <link url="http://www.freetype.org" text="FreeType 2 library"/>,
+ and the resulting font is used to render the
+ box's <t>text</t>.
+ </property>
+
+ <property name="fontsize" type="number" default="10">
+ The size (in points) to render the text.
+ </property>
+
+ </section>
+
+ <section title="Layout Properties">
+
+ <property name="shrink" type="boolean" default="false">
+ If set to <t>true</t>, this box will shrink
+ (horizontally/vertically/both) to the smallest size allowed by
+ its children and the bounding box of its path.
+ </property>
+
+ <property name="x y" type="integer" default="varies">
+ If the box is a root box, this is the (x/y)-coordinate of the
+ surface; otherwise it is the distance between the parent's
+ alignment point and this box's alignment point.
+ </property>
+
+ <property name="minwidth minheight" type="integer" default="0">
+ The desired minimum width and height.
+ </property>
+
+ <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
+ The desired maximum width and height.
+ </property>
+
+ <property name="width height" type="integer">
+ When read, this is the current (width/height) of this box.
+ Writing to this property is equivalent to writing to
+ <i>both</i> the minimum and maximum (width/height).
+ </property>
+
+ <property name="cols rows" type="integer" default="0">
+ The number of (columns/rows) in which to lay out the children of this
+ box. If set to zero, the number of (columns/rows) is unconstrained.
+ Either <t>rows</t> or <t>cols</t> must be zero. If
+ <t>0</t> is written to <t>cols</t> when <t>rows</t> is
+ <t>0</t>, the write is ignored. If a nonzero value is
+ written to <t>cols</t> when <t>rows</t> is nonzero,
+ <t>rows</t> is set to <t>0</t>, and vice versa.
+ </property>
+
+ <property name="colspan rowspan" type="integer" default="1">
+ The number of (columns/rows) that this box spans within its parent.
+ </property>
+
+ <property name="align" type="string" default="center">
+ Determines the box's alignment point for positioning its text,
+ texture, path, and children.
+ </property>
+
+ <property name="visible" type="boolean" default="true">
+ If set to <t>false</t>, this box will be rendered as if its
+ width and height were zero. If this is a root box, the
+ associated surface will be hidden.
+
+ When reading from this property, the value <t>false</t> will
+ be returned if this box <i>or any of its ancestors</i> is not
+ visible. Thus it is possible to write <t>true</t> to a box's
+ <t>visible</t> property and then read back <t>false</t>.
+ </property>
+
+ <property name="packed" type="boolean" default="true">
+ The layout strategy for this box. If set to <t>true</t>, the
+ box occupies no cells and is laid out independently of its
+ siblings.
+ </property>
+
+ </section>
+
+ <section title="Child Control Properties">
+
+ <property name="redirect" type="box" default="thisbox">
+ Writing to this property sets the box's redirect target. This
+ property cannot be read from, and can only be written to if
+ the value being written is a <i>descendant</i> of the current
+ value.
+
+ If a box has a non-null redirect target, reads and writes to
+ any of the other properties in this section will be forwarded
+ to the redirect target.
+
+ The <t>redirect</t> attribute is very useful for hiding the
+ internal structure of a widget, and for allowing widgets to act as
+ "smart" containers for other widgets. For example, a menu widget might
+ have an invisible child as its redirect target; this way, when boxes
+ representing items on the menu are added as children of the menu
+ widget, they do not appear until the menu is pulled down.
+ </property>
+
+ <property name="numeric properties" type="int" default="">
+ The <i>n</i>th child of box <t>b</t> can be accessed by reading from
+ <t>b[n]</t>. The <i>n</i>th child can be removed by writing
+ <t>null</t> to <t>b[n]</t> (the child will become parentless). A
+ new child can be inserted <i>before</i> the <i>n</i>th child by
+ writing it to <t>b[n]</t>; if the value written is already a child of
+ <t>b</t>, it will be removed from <t>b</t> first. It is important
+ to note that this behavior is different from ECMAscript arrays --
+ writing a non-<t>null</t> value to <t>b[n]</t> does not eliminate
+ the <i>n</i>th child; it merely shifts it over one position.
+ <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
+ properties with the JavaScript <t>for..in</t> construct will
+ enumerate <i>only</i> the box's children and not any other properties.
+ </property>
+
+ <property name="clip" type="boolean" default="true">
+ If <t>true</t>, the visual representation of this box's
+ children will be clipped to the boundaries of this box.
+ <b>Note:</b> setting this property to <t>false</t> imposes a
+ substantial performance penalty.
+ </property>
+
+ <property name="numchildren" type="integer" default="0">
+ The number of children this box has.
+ </property>
+
+
+ <property name="surface" type="" default="null">
+ FIXME
+ If this box has a parent, this property returns
+ <t><i>parent</i>.surface</t>; otherwise it returns null.
+ This property is a simple building block that the widget
+ library uses to implement more complex functionality such as
+ focus control and popups.
+ </property>
+
+ </section>
+
+ <section title="Other Box Properties">
+
+ <property name="cursor" type="string" default="null">
+ The shape that the cursor should take when inside this
+ box. Valid values are: "<t>default</t>" , "<t>wait</t>",
+ "<t>crosshair</t>", "<t>text</t>", "<t>hand</t>", and
+ "<t>move</t>", as well as resizing cursors"<t>east</t>",
+ "<t>west</t>", "<t>north</t>", "<t>south</t>",
+ "<t>northwest</t>", "<t>northeast</t>",
+ "<t>southwest</t>", and "<t>southeast</t>". Note that on
+ some platforms, resize cursors for opposite directions (such
+ as <t>northwest</t> and <t>southeast</t> are the
+ same).
+ If a box's cursor is <t>null</t>, its parent's cursor will
+ be used. If the root box's cursor is null, the
+ "<t>default</t>" cursor will be used.
+ </property>
+
+ <property name="static" type="object" default="N/A">
+ Reading from this property will return the parent scope used
+ to execute the <t><static/></t> block of the template
+ in which the currently-executing code resides.
+ </property>
+
+ <property name="thisbox" type="box" default=" ">
+ Returns a reference to the box itself.
+ If <t>null</t> is written to this property, and this box is
+ the root box of a surface, the box will be detached and the
+ surface destroyed. If this box has a parent, it will be
+ detached from its parent.
+ </property>
+
+ <property name="indexof()" type="function" default=" ">
+ This property is actually a function; invoking
+ <t>parent.indexof(child)</t> will return the numerical index
+ of <t>child</t> in <t>parent</t> if <t>child</t> is a
+ child of <t>parent</t> (or <t>parent</t>'s redirect
+ target), and <t>-1</t> otherwise. Writing to this property
+ has no effect.
+ </property>
+
+ <property name="distanceto()" type="function" default=" ">
+ This property is actually a function; invoking
+ <t>box.distanceto(otherbox)</t> will return an object with two
+ properties, <t>x</t> and <t>y</t>, containing the horizontal
+ and vertical distance between the two boxes (negative if
+ <t>otherbox</t> is to the left of / above <t>box</t>). This
+ can be used to determine the relative placement of two boxes
+ on different branches of the box tree.
+ </property>
+
+ </section>
+
+ <section title="Root Box Properties">
+
+ The following special properties are only meaningful on the root box
+ of a surface.
+
+ <property name="Focused">
+ The value <t>true</t> is put to this property on the root box
+ when the surface gains the input focus, and <t>false</t> when
+ the surface loses the input focus. Reading from this value will
+ return <t>true</t> if the surface is focused and <t>false</t>
+ if it is not. Putting <t>true</t> to this property will
+ <i>not</i> cause the surface to "steal" the input focus from other
+ windows.
+ </property>
+
+ <property name="Maximized">
+ The value <t>true</t> is put to this property on the root box
+ when the surface is maximized, and <t>false</t> when the surface
+ is un-maximized. Reading from this value will return <t>true</t>
+ if the surface is maximized and <t>false</t> if it is
+ not. Putting <t>true</t> to this property will maximize the
+ window, and putting <t>false</t> to this property will
+ unmaximize the window.
+ Note that not all platforms support maximization.
+ </property>
+
+ <property name="Minimized">
+ The value <t>true</t> is put to this property on the root box
+ when the surface is minimized, and <t>false</t> when the surface
+ is unminimized. Reading from this value will return <t>true</t>
+ if the surface is minimized and <t>false</t> if it is
+ not. Putting <t>true</t> to this property will minimize the
+ window, and putting <t>false</t> will unminimize it.
+ </property>
+
+ <property name="Close">
+ When the user attempts to close a surface, the value
+ <t>true</t> will be put to this property. Scripts may trap
+ this property to prevent the window from closing. Putting the
+ value
+ <t>true</t> to this property on a root box has the same
+ effect as putting <t>null</t> to the <t>thisbox</t>
+ property.
+ </property>
+
+ <property name="icon">
+ The surface's icon. This is usually displayed on the titlebar of a
+ window. The value should be an object whose stream is a PNG image. Note
+ that not all platforms support this property.
+ </property>
+
+ <property name="titlebar">
+ The surface's titlebar text. Note that not all platforms support
+ this property. Only ASCII characters 0x20-0x7F are permitted.
+ </property>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Streams">
+
+ <heading title="Every object has a stream..."/>
+
+ Every object has a <i>stream</i> associated with it. A stream is a
+ sequence of bytes that can be read or written to.
+
+ By default an object has an empty stream (zero bytes). However, some objects
+ (returned from special methods on the <t>ibex</t> object) have
+ streams yielding data read from an url, file, or a component of a zip
+ archive. In a future release, the stream associated with a box will
+ be an .ibex template which, when applied, will fully reconstitute the
+ box's state.
+
+ <heading title="...but streams are not objects"/>
+
+ Despite the ubiquity of streams, you cannot actually reference a
+ stream, since it is not an object. Instead, you simply reference the
+ object it belongs to. If you are familiar with Java, this is similar
+ to how every Java object has a monitor associated with it, but you
+ cannot directly manipulate the monitor (you can't pass around a
+ reference to just the monitor).
+
+ In the rest of the section we will sometimes refer to "getting
+ properties from a stream" or "passing a stream to a function"; this is
+ just shorthand for saying to perform those actions on the object the
+ stream belongs to.
+
+ <section title="Creating Streams from URLs">
+
+ You can create a stream from a URL by calling
+
+ <pre>
+ var r = ibex.stream.url("http://...");
+ </pre>
+
+ This will return an object whose stream draws data from the specified
+ URL. Streams are loaded lazily whenever possible.
+
+ </section>
+
+ <section title="Getting Substreams">
+
+ Most stream objects let you access
+ substreams using the usual JavaScript operators <t>[]</t> and
+ <t>.</t>, as well as the <t>for..in</t> syntax.
+
+ <pre>
+ // r1 and r2 are equivalent but not equal (!=)
+ var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
+ var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
+ </pre>
+
+ </section>
+
+ <section title="The Root Stream">
+
+ The empty-string property on the <t>ibex</t> object is called the
+ <i>root stream</i>. You can access this object as <t>ibex..</t> or
+ <t>ibex[""]</t>. Additionally, any expression which starts with a
+ dot is treated as property to be retrieved from the root stream. The
+ following three expressions are equivalent:
+
+ <pre>
+ ibex..foo
+ ibex[""].foo
+ .foo
+ </pre>
+
+ </section>
+
+ <section title="Static Blocks">
+
+ FIXME
+
+ You can access variables within the static block of a template by
+ appending a double period (<t>..</t>) and the variable name to the
+ stream used to load that template:
+
+ <pre>
+ <!-- org/ibex/themes/linux/scrollbar.ibex -->
+ foo = 12;
+ ...
+ // elsewhere
+ ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
+ </pre>
+
+ </section>
+
+ <section title="Formatting Streams">
+
+ If you attempt to send a stream as part of an XML-RPC call, the
+ stream will be read in its entirity, Base64-encoded, and transmitted
+ as a <t><base64/></t> element.
+
+ Ibex supports two special URL protocols. The first is <t>data:</t>,
+ which inteprets the rest of the URL as a Base64 encoded sequence of
+ bytes to use as a source. The other is <t>utf8:</t> which
+ interpretets the rest of the string as a Unicode character sequence to
+ be UTF-8 encoded as a string of bytes to use as a source.
+
+ <pre>
+ var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
+ var r6 = ibex.stream.url("utf8:this is a test");
+ </pre>
+
+ You can read a UTF-8 encoded string from a stream like this:
+
+ <pre>
+ var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
+ </pre>
+ You can also parse XML from a stream using SAX like this:
+
+ <pre>
+ ibex.stream.xml.sax(
+ ibex.stream.url("http://foo.com/foo.xml"),
+ { beginElement : function(tagname, attributeKeyValuePairs) { ... },
+ endElement : function(tagname) { ... },
+ content : function(contentString) { ... }
+ whitespace : function(whitespaceString) { ... }
+ });
+ </pre>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="The Ibex object">
+
+ The <t>ibex</t> object is present in the top-level scope of every
+ script. It has the following properties:
+
+ <heading title="General"/>
+
+ <property name="ibex.box">
+ reading from this property returns a new box
+ </property>
+ <property name="ibex.clone(o)">
+ creates a clone of object
+ </property>
+ <property name="ibex.bless(s)">
+ returns a blessed clone of stream
+ </property>
+
+ <heading title="ECMA Library Objects"/>
+
+ <property name="ibex.date">
+ reading from this property returns a new date
+ </property>
+ <property name="ibex.math">
+ this object contains the ECMA math functions
+ </property>
+ <property name="ibex.regexp(s)">
+ return a regexp object corresponding to string <i>s</i>
+ </property>
+ <property name="ibex.string">
+ this object contains the ECMA string manipulation functions
+ </property>
+
+ <heading title="Logging"/>
+
+ <property name="ibex.log.debug(m1, ... mn)">
+ log the debug messages <i>m1</i> through <i>mn</i>.
+ <i>o</i>
+ </property>
+
+ <property name="ibex.log.info(m1, ... mn)">
+ log the info messages <i>m1</i> through <i>mn</i>.
+ </property>
+
+ <property name="ibex.log.warn(m1, ... mn)">
+ log the warning messages <i>m1</i> through <i>mn</i>.
+ </property>
+
+ <property name="ibex.log.error(m1, ... mn)">
+ log the error messages <i>m1</i> through <i>mn</i>.
+ </property>
+
+ <heading title="User Interface"/>
+
+ <property name="ibex.ui.browser(u)">
+ opens a new browser window with URL <i>u</i>
+ </property>
+
+ <property name="ibex.ui.key.control">
+ true if the control key is depressed
+ </property>
+
+ <property name="ibex.ui.key.shift">
+ true if the shift key is depressed
+ </property>
+
+ <property name="ibex.ui.key.alt">
+ true if the alt key is depressed
+ </property>
+
+ <property name="ibex.ui.key.name.alt">
+ the name of the "alt" key (usually either "alt", "meta", or
+ "option")
+ </property>
+
+ <property name="ibex.ui.clipboard">
+ the contents of the clipboard; can be read and written to
+ </property>
+
+ <property name="ibex.ui.maxdim">
+ the maximum dimension of any UI element; usually
+ 2<sup>31</sup>, but may be smaller
+ </property>
+
+ <property name="ibex.ui.screen.width">
+ the width of the screen, in pixels
+ </property>
+
+ <property name="ibex.ui.screen.height">
+ the height of the screen, in pixels
+ </property>
+
+ <property name="ibex.ui.mouse.button">
+ either 0, 1, 2, or 3, indicating the mouse button currently
+ being pressed
+ </property>
+
+ <property name="ibex.ui.frame">
+ when a box is written to this property, it becomes the root
+ box of a new window
+ </property>
+
+ <property name="ibex.ui.window">
+ when a box is written to this property, it becomes the root
+ box of a new frame
+ </property>
+
+ <property name="ibex.ui.font.serif">
+ an object whose stream is a a builtin serif font
+ </property>
+
+ <property name="ibex.ui.font.sansserif">
+ an object whose stream is a builtin sans-serif font
+ </property>
+
+ <property name="ibex.ui.font.monospace">
+ an object whose stream is a a builtin fixed-width font
+ </property>
+
+ <heading title="Networking"/>
+
+ <property name="ibex.net.rpc.xml(u)">
+ return an XML-RPC call object with endpoint URL <i>u</i>
+ </property>
+
+ <property name="ibex.net.rpc.soap(u,">
+ return a SOAP call object with endpoint URL <i>u</i>,
+ SoapAction <i>a</i>, and XML Namespace <i>n</i>
+ </property>
+
+ <heading title="Threads"/>
+
+ <property name="ibex.thread">
+ when a function is written to this property, a new thread is
+ forked to call it
+ </property>
+
+ <property name="ibex.thread.yield()">
+ yield the current thread
+ </property>
+
+ <property name="ibex.thread.sleep(n)">
+ sleep for <i>n</i> milliseconds
+ </property>
+
+ <heading title="Streams"/>
+
+ <property name="ibex.stream.url(u)">
+ returns a new object whose stream is drawn from URL <i>u</i>
+ </property>
+
+ <property name="ibex.stream.unzip(s)">
+ unpacks a zip archive from <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.uncab(s)">
+ unpacks a cab archive from <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.cache(s,k)">
+ valign=top>wraps a disk-backed read cache keyed on <i>k</i>
+ around <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.watch(s,f)">
+ returns an object whose stream is drawn from <i>s</i>'s
+ stream, but invokes <i>f(n,d)</i> as it is read from.
+ </property>
+
+ <property name="ibex.stream.parse.xml(s, h)">
+ Use SAX to parse the XML document on stream <i>s</i> with
+ handler <i>h</i>
+ </property>
+
+ <property name="ibex.stream.parse.html(s, h)">
+ Same as <t>parse.xml()</t>, but tries to fix broken HTML.
+ </property>
+
+ <property name="ibex.stream.parse.utf8(s)">
+ treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string
+ </property>
+
+ <property name="ibex.stream.homedir">
+ <t>ibex.stream.tempdir</t>
+ </property>
+
+ <heading title="Cryptography"/>
+
+ <property name="ibex.crypto.rsa(k,s)">
+ <i>not implemented yet:</i> return a
+ stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
+ </property>
+
+ <property name="ibex.crypto.rc4(k,s)">
+ <i>not implemented yet:</i> return a
+ stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
+ </property>
+
+ <property name="ibex.crypto.md5(s)">
+ <i>not implemented yet:</i> immediately
+ MD5-hash stream <i>s</i>
+ </property>
+
+ <property name="ibex.crypto.sha1(s)">
+ <i>not implemented yet:</i> immediately
+ SHA1-hash stream <i>s</i>
+ </property>
+
+</section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Traps">
+
+ You can add a trap to a property by applying the <t>++=</t> operator
+ to a function with one argument. The trap will be invoked whenever
+ that property is written to.
+
+ <pre>
+ <ui:box>
+ foo ++= function(z) {
+ ibex.log.info("foo is " + z);
+ }
+ </ui:box>
+ </pre>
+
+ If another script were to set the property "<t>foo</t>"
+ on the box above to the value <t>5</t>, the function above would be
+ invoked with the argument <t>5</t>. The function would then log
+ the string "<t>foo is 5</t>".
+
+ Within a trap, the expression <t>trapee</t> can be used to
+ get a reference to the box on which the trap was placed.
+
+ The expression <t>trapname</t> returns the name of the
+ trap executing the current function. This is useful when a function
+ is applied to multiple traps. For example:
+
+ <pre>
+ <ui:box>
+ func ++= function(z) {
+ ibex.log.info("called trap " + trapname);
+ }
+ foo ++= func;
+ bar ++= func;
+ </ui:box>
+ </pre>
+
+ <section title="Removing Traps">
+
+ You can remove a trap by using the <t>--=</t> operator with the same
+ function you added as a trap:
+
+ <pre>
+ <ui:box>
+ var myfunc = function(z) { /* ... */ }
+ // add the trap
+ func ++= myfunc;
+ // ...
+ // remove the trap
+ func --= myfunc;
+ </ui:box>
+ </pre>
+
+ </section>
+
+ <heading title="Multiple Traps on the Same Property"/>
+
+ When the trapped property is <i>written</i> to, each of the trap
+ functions placed on it will be invoked in the opposite order that
+ they were placed on the box -- the most recently placed trap will
+ execute first. This last-to-first execution of traps is called
+ <i>cascading</i>. After the last trap is invoked, the value is
+ stored on the box (remember, boxes are objects, so they can hold
+ properties just like all other ECMAscript objects).
+
+ <section title="Manual Cascades">
+
+ There are two additional tricks you can use when placing traps. The
+ first is a <i>manual cascade</i>. If you want to cascade to lower
+ traps in the middle of a function, or you want to cascade with a
+ different value than the value passed to you (in effect "lying" to
+ lower traps), you can use <t>cascade</t>. For example:
+
+ <pre>
+ <ui:box color="black">
+ color ++= function(c) {
+ ibex.log.info("refusing to change colors!");
+ cascade = "black";
+ }
+ </ui:box>
+ </pre>
+
+ This effectively creates a box whose color cannot be changed, and
+ which complains loudly if you try to do so.
+
+ Do <i>not</i> try to do something like this:
+
+ <pre>
+ <ui:box color="black">
+ color ++= function(z) {
+ color = "black"; // INFINITE LOOP! BAD!!!
+ }
+ </ui:box>
+ </pre>
+ To prevent automatic cascading, return <t>true</t> from your function:
+
+ <pre>
+ <ui:box color="black">
+ color ++= function(z) {
+ return true; // the box's color will not change
+ }
+ </ui:box>
+ </pre>
+
+ </section>
+
+ <section title="Read Traps">
+
+ The other trick is a <i>read-trap</i>. Read traps are just like normal
+ traps, except that you use a function that takes zero arguments instead of one. Read traps
+ also do not automatically cascade.
+
+ <pre>
+ <ui:box>
+ doublewidth <t>++=</t> function() { return 2 * width; }
+ </ui:box>
+ </pre>
+
+ If another script attempts to read from the <t>doublewidth</t>
+ property on this box, the value it gets will be twice the actual width
+ of the box. Note that
+ the actual <t>doublewidth</t> property on the box never gets written
+ to, since the trap does not cascade.
+
+ You can manually cascade on read traps as well:
+
+ <pre>
+ <ui:box>
+ text <t>++=</t> function() { return "my text is " + cascade; }
+ </ui:box>
+ </pre>
+
+ Read traps are only rarely needed -- most of the time a write trap
+ should be enough.
+
+ </section>
+
+ <heading title="Prohibited Traps"/>
+
+ To prevent confusing and hard-to-debug behaviors, scripts may not
+ place traps on any of the properties described in the sections
+ <link text="Box Layout Properties" section="Layout Properties"/>, <link
+ section="Child-Control Properties"/>, or <link section="Other Box
+ Properties"/> except for <t>childadded</t>,
+ <t>childremoved</t> and <t>surface</t>. FIXME: remove?
+
+ <heading title="Exceptions and Traps"/>
+
+ If an uncaught exception is thrown from a trap, Ibex will log the
+ exception, but will <i>not</i> propagate it to the code which
+ triggered the trap. If the trap was a read trap, the value
+ <t>null</t> will be returned.
+ FIXME: is this right?
+
+ <heading title="Architectural Significance of Traps"/>
+
+ Traps are the backbone of Ibex. Since almost all UI programming is
+ event/demand driven, traps eliminate the need for separate
+ member/getter/setter declarations, often cutting the amount of typing
+ you have to do to a third of what it would normally be.
+
+ <section title="Cloning">
+
+ <i>Cloning</i> is a companion technique for traps; together they can
+ be used to simulate any sort of environment you might need. When you
+ call <t>ibex.clone(o)</t>, Ibex returns a new object (called the
+ <i>clone</i>) which compares with equality (<t>==</t>) to the
+ original object. Furthermore, both objects are "equal" as keys in
+ hashtables, so:
+
+ <pre>
+ var hash = {};
+ var theclone = ibex.clone(o);
+ hash[o] = 5;
+ ibex.log.info(hash[theclone]); // prints "5"
+ </pre>
+
+ Any writes to properties on the clone will actually write to
+ properties on the original object, and reads from properties on the
+ clone will read properties on the original object. In fact, the only
+ thing that can be used to distinguish the original from the clone is
+ traps -- a trap placed on the clone is <i>not</i> placed on the
+ original object as well.
+
+ </section>
+
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Threads">
+
+ <section title="Contexts">
+
+ From the perspective of an application writer, Ibex is strictly
+ single-threaded. Ibex is always in exactly one of the following three
+ <i>contexts</i>:
+
+ <list type="unordered">
+
+ <b>Rendering Context</b> -- (redrawing the screen)
+
+ <b>Event Context</b> (executing javascript traps triggered by an event)
+
+ <b>Thread Context</b> (executing a background thread spawned with <t>ibex.thread</t>)
+
+ </list>
+
+ There are two important restrictions on what can be done in particular contexts:
+
+ <list type="unordered">
+
+ The <t>box.mouse</t> property and its subproperties
+ (<t>x</t>, <t>y</t>, and <t>inside</t>) can only be read
+ from within the Event Context, or in a thread context
+ <i>after</i> a the <t>box.mouse</t> property on this box or
+ an ancestor box has been written to.
+
+ Blocking operations (anything that accesses the network or
+ disk) can only be performed in the Thread Context.
+
+ </list>
+
+ </section>
+
+ <section title="Background Threads">
+
+ Ibex offers easy access to threads. Spawning a background thread is as
+ simple as writing a function to the <t>ibex.thread</t> property:
+
+ <pre>
+ ibex.thread = function() {
+ ibex.log.info("this is happening in a background thread!");
+ }
+ </pre>
+
+ The argument set passed to the function is currently undefined and is
+ reserved for use in future versions of Ibex. Scripts should not
+ depend on the number or content of these arguments.
+
+ Ibex is <i>cooperatively multitasked</i>, so threads must not process
+ for too long. This was a deliberate choice; cooperatively
+ multitasked environments do not require complex locking primitives
+ like mutexes and semaphores which are difficult for novices to
+ understand. The disadvantage of cooperative multitasking is that one
+ thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
+ first, all blocking I/O operations <i>automatically</i> yield the CPU,
+ so the overall user interface never becomes unresponsive because it is
+ waiting for a disk or network transfer. Second, since Ibex is strictly
+ a user interface platform, Ibex scripts are unlikely to perform highly
+ compute-intensive operations that keep the CPU busy for more than a
+ few milliseconds.
+
+ </section>
+</section>
+
+<section title="Events">
+
+ Every execution of the Event Context begins with an event, which
+ consists of a key/value pair, and a mouse position, which consists of
+ an x and y coordinate. The possible keys are <t>_Press[1-3]</t>,
+ <t>_Release[1-3]</t>, <t>_Click[1-3]</t>, <t>_DoubleClick[1-3]</t>,
+ <t>_Move</t>, <t>_KeyPressed</t>, and <t>_KeyReleased</t>.
+
+ Here are two example events:
+
+ An event is triggered by writing the key to the value on a box. This
+ triggers any trap handlers which may be present. Once these handlers
+ have executed, Ibex figures out which child of the current box contains
+ the mouse (taking into account that some boxes may cover up others)
+ and writes the key and value to that box. If none of the box's
+ children contain the mouse position, Ibex removes the leading
+ underscore from the key name and writes the value to
+ <i>that</i> property. Once all the traps on that property have
+ executed, the value is written to the box's parent.
+
+ Intuitively, Ibex delivers the underscored event to every box from the
+ root to the target, and then delivers the non-underscored event to
+ that same set of boxes in reverse order. So the event travels down
+ the tree to the target, and then back up to the root. The following
+ example prints out "first second third fourth" in that order.
+
+ <pre>
+ <ui:box>
+ _Press1 ++= function(b) { ibex.log.info("first"); }
+ Press1 ++= function(b) { ibex.log.info("fourth"); }
+ <ui:box>
+ _Press1 ++= function(b) { ibex.log.info("second"); }
+ Press1 ++= function(b) { ibex.log.info("third"); }
+ </ui:box>
+ </ui:box>
+ </pre>
+
+ In general, you should use the <i>non-underscore</i> names to respond
+ to user input and use the underscored names when you want to override
+ child boxes' behavior or route events to particular boxes (for
+ example, when implementing a focus protocol). This is why the
+ underscored elements are delivered to parents before children (so
+ parents can override their childrens' behavior), but non-underscored
+ events are delivered to children before parents (since, visually, a
+ mouse click is usually "intended" for the leaf box underneath the
+ cursor).
+
+ </section>
+
+ <heading title="Stopping the Process"/>
+
+ At any point in this sequence, a trap handler can choose not to
+ cascade (by returning <t>true</t> from the trap handler function).
+ This will immediately cease the propagation of the event. This is how
+ you would indicate that an event has been "handled".
+
+ <heading title="Non-Propagating Events"/>
+
+ Ibex uses the following events to notify a box about changes that
+ only matter to that particular box. These events do not propagate
+ either up or down the tree.
+
+ <property name="Enter Leave">
+ The value <t>true</t> is written to this property when the mouse (enters/leaves) the box.
+ </property>
+
+ <property name="SizeChange">
+ The value <t>true</t> is put to this property after the size
+ of this box changes.
+ </property>
+
+ <property name="ChildChange">
+ When a child is added or removed, that child is written to
+ this property. The write is always performed <i>after</i> the
+ addition or removal, so these two cases can be distinguished
+ by checking <t>indexof(child)</t>.
+
+ Note that if the parent's redirect target is set to another
+ box, this trap will only be invoked when children are
+ manipulated by reading and writing to the parent. Reads and
+ writes directly to the redirect target will <i>not</i> trigger
+ this trap.
+
+ Note also that this traps is still triggered if a box's
+ <t>redirect</t> target is <i>null</i>. This is useful for
+ boxes that need to accept children and then relocate them
+ elsewhere.
+ </property>
+
+ <section title="Listing of Events">
+
+ <property name="Press1 Press2 Press3">
+ Indicates that the use has pressed a mouse button. On
+ platforms with three mouse buttons, the <i>middle</i> button
+ is button 3 -- this ensures that applications written to only
+ use two buttons (1 and 2) will work intuitively on three button
+ platforms.
+ </property>
+
+ <property name="Release1 Release2 Release3">
+ Indicates that the use has released a mouse button.
+ </property>
+
+ <property name="Click1 Click2 Click3">
+ Indicates that the user has pressed and released the
+ mouse button without moving the mouse much (exactly how
+ much is platform-dependent).
+ </property>
+
+ <property name="DoubleClick1 DoubleClick2 DoubleClick3">
+ Indicates that the user has clicked the
+ mouse button twice within a short period of time (exactly how long is platform-dependent).
+ </property>
+
+ <property name="Move">
+ Indicates that the mouse has moved while within this box, or that
+ the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
+ </property>
+
+ <property name="KeyPressed KeyReleased">
+
+ A string is written to this property when a key is pressed or
+ released If the key was any other key, a multi-character
+ string describing the key will be put. For simplicity, we use
+ the VK_ constants in the <link
+ url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
+ text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
+ key is pressed or released, the string put will be the portion
+ of its VK_ constant after the underscore, all in lower case.
+
+ <list>
+ If the shift key was depressed immediately before the
+ event took place, then the string will be capitalized. Special
+ keynames are also capitalized; shift+home is reported as
+ "<t>HOME</t>". Symbols are capitalized as they appear on the
+ keyboard; for example, on an American QWERTY keyboard, shift+2
+ is reported as "<t>@</t>".
+
+ If the alt, meta, or command key was depressed immediately
+ before this key was pressed, then the string will be prefixed
+ with the string "<t>A-</t>". If the control key was depressed
+ while this key was pressed, then the string will be prefixed
+ with the string "<t>C-</t>". If both alt and control are
+ depressed, the string is prefixed with "<t>C-A-</t>".
+
+ Ibex does not distinguish between a key press resulting from
+ the user physically pushing down a key, and a 'key press'
+ resulting from the keyboard's typematic repeat. In the rare
+ case that an application needs to distinguish between these
+ two events, it should watch for KeyReleased messages and
+ maintain an internal key-state vector.
+ </list>
+ </property>
+
+ </section>
+
+</section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Networking">
+
+ <section title="XML-RPC">
+
+ XML-RPC objects can be created by calling <t>ibex.net.rpc.xml(<i>XML-RPC
+ URL</i>)</t>, and then invoking methods on that object. For example,
+
+ <pre>
+ Press1 += function(v) {
+ ibex.thread = function() {
+ color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
+ color.getTodaysColor("Friday");
+ }
+ }
+ </pre>
+
+ When the user clicks the first mouse button on this box, it will
+ contact the server <t>xmlrpc.ibex.org</t>, route to the
+ <t>/RPC2/</t> handler and invoke the <t>getTodaysColor()</t>
+ method on the <t>color</t> object with a single string argument
+ "<t>Friday</t>". The return value will be used to change the color
+ of the box the user clicked on.
+
+ Note that in this example we spawned a background thread to handle the
+ request -- the <t>Press1</t> event is delivered in the foreground
+ thread, and XML-RPC methods may only be invoked in background
+ threads. This is to prevent the UI from "locking up" if the server
+ takes a long time to reply.
+
+ If the XML-RPC method faults, an object will be thrown with two
+ properties: <t>faultCode</t> and <t>faultString</t>, as defined in
+ the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
+ Ibex encounters a network, transport, or session-layer error, it will
+ throw a <t>String</t> object describing the error in a
+ human-readable format. Scripts should not rely on the contents of
+ this string having any special structure or significance.
+
+ If an object with an associated non-empty stream is passed as an
+ argument to an XML-RPC method, it will be sent as a <base64/>
+ element. If a <base64/> element is found in the XML-RPC reply, it
+ will be returned as an object with a stream drawn from that byte sequence.
+
+ Each object returned by <t>ibex.net.rpc.xml()</t> represents a
+ single HTTP connection. The connection will be held open until
+ the object is garbage collected or the server closes the
+ connection. If a second call is issued on the object before the
+ first one returns (usually from a seperate thread), the two calls
+ will be <link
+ url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
+ text="pipelined"/>. This can dramatically improve performance.
+
+ Ibex supports HTTP Basic and Digest authentication. To use
+ authentication, pass <t>ibex.net.rpc.xml()</t> a URL in the form
+
+ <pre>
+ http[s]://user:password@hostname/
+ </pre>
+
+ Ibex will use Digest authentication if the server supports it;
+ otherwise it will use Basic authentication. Please be aware that
+ many XML-RPC server implementations contain a <link
+ url="http://www.ibex.org/faq.html#auth" text="broken
+ implementation of Basic authentication"/>.
+
+ </section>
+
+ <section title="SOAP">
+
+ SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
+
+ <list type="ordered">
+
+ <t>ibex.net.rpc.soap()</t> is used instead of
+ <t>ibex.net.rpc.xml()</t>
+
+ Instead of specifying just the URL of the service itself, you
+ must specify the URL, the SOAPAction argument, and the
+ namespace to use.
+
+ The actual method invocation takes only one argument, which
+ must be an object. This is necessary since SOAP arguments are
+ specified by name, rather than ordering.
+
+ </list>
+
+ SOAP faults are handled the same way as XML-RPC faults except that the
+ capitalization of the <t>faultstring</t> and <t>faultcode</t>
+ members is all lower-case, to match the SOAP spec. Here is a
+ SOAP example:
+
+ <pre>
+ Press1 ++= function(v) {
+ ibex.thread = function() {
+ color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
+ "GETTODAYSCOLOR",
+ "http://ibex.org/namespace"
+ ).color.getTodaysColor( {
+ whichday : Friday
+ } );
+ }
+ }
+ </pre>
+
+ As you can see, SOAP is much more verbose, yet does not offer
+ substantially improved functionality. We recommend that XML-RPC be
+ used whenever possible, and that SOAP be reserved for legacy
+ applications.
+
+ The current Ibex SOAP stack does not support 'document style' or
+ multi-ref (<t>href</t>) data structures.
+
+ </section>
+
+ <section title="Security">
+
+ Applications downloaded from the network (as opposed to those loaded
+ from the filesystem) may only make certain kinds of connections to
+ certain hosts. See Appendix A for a detailed description of the
+ security policy.
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Error Handling">
+
+ If the Ibex Core encounters an error while servicing a function call
+ originating in JavaScript, the core will throw a string consisting of
+ an error code followed by a colon, a space, and a descriptive message.
+ For example:
+
+ <pre>
+ "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
+ </pre>
+
+ The code should be used to determine how the program should respond to
+ an error. The codes are organized in a hierarchy, so the
+ string.startsWith() method can be used to determine if an error lies
+ within a particular subhierarchy. The descriptive message portion of
+ the string may be shown to the user.
+
+ <property name="ibex.assertion.failed">
+ an assertion failed
+ </property>
+ <property name="ibex.io">
+ General I/O exceptions
+ </property>
+ <property name="ibex.io.encoding">
+ Error translating between character encodings.
+ </property>
+ <property name="ibex.io.zip">
+ Attempted to access a corrupt zip archive.
+ </property>
+ <property name="ibex.io.eof">
+ End of file encountered unexpectedly
+ </property>
+ <property name="ibex.net.security.prohibitedHost">
+ A piece of untrusted Ibex code attempted to contact a
+ restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
+ </property>
+ <property name="ibex.net.dns.temporaryFailure">
+ An attempt to resolve a hostname failed but it is not known
+ for certain that the hostname is invalid.
+ </property>
+ <property name="ibex.net.dns.unknownHost">
+ An attempt to resolve a hostname failed because the hostname
+ was invalid.
+ </property>
+ <property name="ibex.net.socket.closed">
+ A socket was closed unexpectedly.
+ </property>
+ <property name="ibex.net.socket.connectionFailed">
+ A connection could not be made to the remote host.
+ </property>
+ <property name="ibex.net.url.malformed">
+ Tried to parse a malformed URL.
+ </property>
+ <property name="ibex.net.ssl">
+ General SSL protocol errors.
+ </property>
+ <property name="ibex.net.ssl.untrustedCertificate">
+ The server's certificate was not signed by a CA trusted by Ibex.
+ </property>
+ <property name="ibex.net.http.">
+ Thrown when an HTTP error code is returned during an
+ operation. The three characters <t><i>xyz</i></t> will be
+ the three-digit HTTP status code.
+ </property>
+ <property name="ibex.net.xmlrpc.null">
+ The caller attempted to transmit the <t>null</t> value via XML-RPC.
+ </property>
+ <property name="ibex.net.xmlrpc.circular">
+ The caller attempted to transmit a circular data structure via XML-RPC.
+ </property>
+ <property name="ibex.net.xmlrpc.specialObject">
+ The caller attempted to transmit a "special" object via
+ XML-RPC (for example, a Box or the Ibex object).
+ </property>
+ <property name="ibex.null.put">
+ A JavaScript attempted to put to a property on the <t>null</t> value
+ </property>
+ <property name="ibex.null.get">
+ A JavaScript attempted to get from a property on the <t>null</t> value
+ </property>
+ <property name="ibex.null.call">
+ A JavaScript attempted to call the <t>null</t> value
+ </property>
+
+ If an exception is thrown inside a trap, the exception will propagate
+ to the script that triggered the trap.
+
+ If an uncaught exception is thrown while applying a template, or the
+ requested template could not be found, an error will be logged and the
+ box to which the template was being applied will be made invisible
+ (<t>visible = false</t>). This ensures that half-applied widgets are
+ never shown to the user.
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Advanced Topics">
+
+ <section title="Re-routing events">
+
+ At any point in the Event Context, you can write to the <t>mouse</t>
+ property on any box. The value written should be an object with two
+ properties, <t>x</t> and <t>y</t>. For example:
+
+ <pre>
+ _Press1 ++= function(p) {
+ mouse = { x: 32, y: 77 };
+ }
+ </pre>
+
+ The coordinates specified are relative to the box whose <t>mouse</t>
+ property is being written to. There is no need to supply the
+ <t>inside</t> property; it is computed automatically. Writing to
+ the <t>mouse</t> property causes Ibex to recompute the eventual
+ target box, and also alter the values returned by <t>mouse.x</t>,
+ <t>mouse.y</t>, and <t>mouse.inside</t> for any <i>descendants</i>
+ of the current box. Writing to the <t>mouse</t> property also
+ automatically prevents the event from returning to the box's parents
+ -- it is equivalent to not cascading on the non-underscored event.
+ This ensures that child boxes cannot trick their parent boxes into
+ thinking that the mouse has moved.
+
+ If you want the event to "skip over" the boxes between the trapee
+ and the target, or if you want to re-route an event to a box which
+ is not a descendant of the current box, simply write the value to
+ the proper key on the target box.
+
+ <pre>
+ <ui:box>
+ _KeyPressed = function(k) { ibex.log.info("first"); }
+ KeyPressed = function(k) { ibex.log.info("sixth"); }
+ $recipient.target = $target;
+ <ui:box id="recipient">
+ _KeyPressed = function(k) {
+ ibex.log.info("second");
+ thisbox.target.KeyPressed = k;
+ // inhibit cascade; keep event from going to $excluded
+ return true;
+ }
+ KeyPressed = function(k) { ibex.log.info("fifth"); }
+ <ui:box id="excluded">
+ _KeyPressed = function(k) {
+ ibex.log.info("this never happens");
+ }
+ </ui:box>
+ </ui:box>
+ <ui:box id="target">
+ _KeyPressed = function(k) { ibex.log.info("third"); }
+ KeyPressed = function(k) { ibex.log.info("fourth"); }
+ </ui:box>
+ </ui:box>
+ </pre>
+
+ </section>
+
+ <section title="Synthesizing Your Own Events">
+
+ You can create "fake events" by simply writing to the <t>mouse</t>
+ property and then writing a value to one of the underscored properties
+ on a box. This will have exactly the same effect as if the use had
+ actually pressed a key, clicked a button, or moved the mouse -- they
+ are indistinguishable.
+
+ </section>
+
+ <section title="Ibex self-emulation">
+
+ When the core first starts up, it clones the <t>ibex</t> object,
+ creates a stream for the initial .ibex, and then places a trap on the
+ cloned <t>ibex</t> object so that its empty-string property returns
+ the .ibex stream. The cloned Ibex object is then passed as the third
+ (optional) argument to <t>ibex.apply()</t>, making it the default
+ <t>ibex</t> object for the scripts that are executed as part of the
+ template instantiation.
+
+ <pre>
+ var new_ibex = ibex.clone(ibex);
+ var stream = ibex.bless(ibex.stream.url("http://..."));
+ new_ibex[""] ++= function() { return stream; }
+ ibex.apply(ibex.box, new_ibex..main, new_ibex);
+ </pre>
+
+ Note that we called <t>ibex.bless()</t> on the stream before tacking
+ it on to the new Ibex object. The bless function returns a clone of
+ the object passed to it, with a few traps which are explained below.
+ Additionally, any sub-streams retrieved by accessing properties of the
+ blessed stream will also automatically be blessed (blessed streams are
+ <i>monadic</i>).
+
+ Blessing a stream serves three purposes:
+
+ <list type="unordered">
+
+ Blessed clones always return the appropriate static block when
+ their empty property is accessed; this ensures that references
+ to the static blocks of other templates work properly.
+
+ Blessed substreams can return their parent stream by accessing
+ a hidden property which is reserved for internal use by Ibex.
+ This ensures that Ibex can automatically add filename
+ extensions where needed, according to the following rules:
+
+ <list>
+ If the stream is a template to be applied, the string
+ "<t>.ibex</t>" is appended.
+
+ If the stream is an image, the string "<t>.png</t>" is
+ appended. If no stream is found, "<t>.jpeg</t>" and
+ "<t>.gif</t>" are tried, in that order.
+
+ If the stream is an font, the string "<t>.ttf</t>" is
+ appended.
+ </list>
+
+ Every call to <t>ibex.bless()</t> returns a different object
+ (which happens to be a clone of the object passed to it) with
+ a completely separate set of static blocks.
+
+ </list>
+
+ Ibex can self-emulate by using <t>ibex.clone()</t> on the Ibex object;
+ this technique is very similar to the use of ClassLoaders in
+ Java. This is useful for a number of applications, including
+ debuggers, IDEs, sandboxing untrusted code, remote-control, and
+ others. For example:
+
+ <pre>
+ var newLoadFunction = function(url) { /* ... */ };
+ var new_ibex = ibex.clone(ibex);
+ new_ibex.load ++= function() { return newLoadFunction; }
+ ibex.apply(ibex.box, .main, new_ibex);
+ </pre>
+ </section>
+</section>
+
+<!-- ----------------------------------------------------------------------- -->
+<appendix title="Security Architecture and Considerations">
+
+ Due to the expense and hassle imposed by the commercial PKI code
+ signing architecture, and the fact that it <link
+ url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
+ really provide any security anyways"/>, Ibex user interfaces are
+ distributed as unsigned, untrusted code. As such, they are handled
+ very carefully by the Ibex Core, and assumed to be potentially
+ malicious.
+
+ Ibex's security architecture is divided into defenses against four
+ major classes of attacks:
+
+ <heading title="Malicious UI attempts to acquire or alter data on the client"/>
+
+ Ibex user interfaces are run in an extremely restrictive sandbox. The
+ environment does not provide primitives for accessing any data outside
+ the Ibex core except via XML-RPC and SOAP calls. There are no
+ facilities to allow Ibex user interfaces to access the client's
+ operating system or to interact with other applications on the same
+ host (unless they provide a public XML-RPC or SOAP interface).
+ An Ibex script may only access a file on the user's hard disk if the
+ user explicitly chooses that file from an "open file" or "save file"
+ dialog. There is one exception to this rule: if all templates
+ currently loaded in the Ibex core originated from the local
+ filesystem, those templates can load additional .ibexs from the local
+ filesystem.
+
+ The Ibex Core is written in Java, so it is not possible for
+ scripts to perform buffer overflow attacks against the core
+ itself.
+
+ Ibex applications may only read from the clipboard when the user
+ middle-clicks (X11 paste), presses control-V (Windows paste), or
+ presses alt-V (Macintosh paste; the command key is mapped to Ibex
+ "alt"). This ensures that Ibex applications are only granted access to
+ data that other applications have placed on the clipboard when the user
+ specifically indicates that that information should be made available
+ to the Ibex application.
+
+ <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
+
+ Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
+ archives via HTTP; they cannot execute arbitrary HTTP GET's or open
+ regular TCP sockets.
+
+ Ibex will not allow a script to connect to a non-public IP address
+ (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
+ url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
+ 1918"/>). There is one exception -- if all templates currently loaded
+ in the core originated from the same IP address, those scripts may
+ make calls to that IP address regardless of whether or not it is
+ firewalled. If Ibex does not have access to a DNS resolver (because it
+ is using a proxy which performs DNS lookups), Ibex will provide the
+ proxy with the appropriate <link
+ url="http://www.ibex.org/x-requestorigin.html"
+ text="X-RequestOrigin"/> header that the proxy needs in order
+ to maintain security.
+
+ The only remaining possible attack is against a XML-RPC or SOAP
+ service running on a firewalled host with a public address. Assigning
+ such machines public IP addresses is a poor network security policy,
+ and doing so squanders scarce public IPv4 addresses. As such, the onus
+ is on the administrators of such machines to explicitly block access
+ to clients reporting a <t>User-Agent:</t> header beginning with the
+ four characters "<t>IBEX</t>".
+
+ <heading title="Malicious UI attempts to trick user into divulging secret information"/>
+
+ All top-level windows created by Ibex are <i>scarred</i> -- a stripe
+ and a lock is drawn across the corner of the window. There is no way
+ for a user interface to remove this scar. Ibex user interfaces may not
+ create windows smaller than the size of the scar.
+
+ <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
+
+ Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
+ for encryption. Ibex will attempt 128-bit encryption, but will
+ negotiate down to 40-bit if the server does not support strong
+ crypto. Ibex's SSL implementation is currently provided by <link
+ url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
+ url="http://www.bouncycastle.org" text="The Legion of the Bouncy
+ Castle."/>
+
+ All HTTPS connections must be authenticated by the server using a
+ certificate whose name matches the domain name of the HTTPS URL. The
+ certificate must be signed by a trusted root CA. Ibex trusts the same
+ 93 root CAs whose certificates are included as "trusted" in Microsoft
+ Internet Explorer 5.5 SP2. This provides a minimal level of protection
+ against man-in-the-middle attacks; you should not trust this
+ connection with any data you would not normally trust an SSL-enabled
+ web browser with.
+
+</appendix>
+
+<!-- ----------------------------------------------------------------------- -->
+<appendix title="ECMAscript compliance">
+
+ Ibex's scripts are written in a modified subset of ECMA-262, revision 3
+ (aka JavaScript 1.5). The interpreter strays from the spec in a few
+ ways.
+
+ <section title="Omissions">
+
+ The following ECMA features are not supported:
+
+ <list type="unordered">
+
+ The <t>undefined</t> value, <t>===</t>, and <t>!==</t>
+
+ The <t>new</t> keyword (and ECMAScript object inheritance)
+ <t>eval</t>
+
+ <t>getter</t> and <t>setter</t>
+
+ The ECMA <t>this</t> keyword.
+
+ The <t>String</t>, <t>Number</t>, and <t>Boolean</t>
+ classes. Note that <t>string</t>, <t>number</t>, and
+ <t>boolean</t> values are supported, however.
+
+ You may not <t>throw</t> the <t>null</t> value.
+
+ </list>
+
+ Additionally, you must declare all root-scope variables (with
+ <t>var</t>) before using them; failure to do so will result in an
+ exception. Box properties are pre-defined in the scope that scripts
+ are executed in.
+
+ </section>
+
+ <section title="Extensions">
+
+ <list type="unordered">
+
+ The token <t>..</t> is equivalent to <t>[""]</t>.
+
+ Trapping
+
+ Cloning
+
+ Extended <t>catch</t> syntax. The following code:
+ <pre>
+ } catch(e propname "foo.bar.baz") {
+ // ...
+ }
+ </pre>
+ Is equivalent to:
+ <pre>
+ } catch(e) {
+ if (e.propname != null and e.propname >= "foo.bar.baz" and
+ "foo.bar.baz/" > e.propname) {
+ // ...
+ }
+ }
+ </pre>
+ Multiple extended-catch blocks can appear at the end of a single try
+ block. However, at most one non-extended catch block may appear, and
+ if it does appear, it must be the last one.
+
+ Since Ibex ECMAscripts are wrapped in XML, the lexical token
+ "<t>lt</t>" is be interpreted as <t><</t>, the lexical
+ token "<t>gt</t>" is be interpreted as <t>></t>, and the
+ token "<t>and</t>" is interpreted as <t>&&</t>.
+ Thus these tokens cannot be used as variable names.
+
+ The identifier <t>static</t> is a reserved word in
+ ECMAScript, but not in Ibex.
+
+ Ibex defines an additional reserved word, "<t>assert</t>",
+ which will evaluate the expression which follows it, throwing
+ a <t>ibex.assertion.failed</t> exception if the expression
+ evaluates to <t>false</t>.
+
+ To ensure that Ibex files appear the same in all text editors, tab
+ characters are not allowed in Ibex files.
+
+ </list>
+
+ Some useful tutorials include:
+
+ <list type="unordered">
+
+ Netscape's <link
+ url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
+ text=" JavaScript 1.2 Reference"/>. Although this document is
+ out of date, it is arguably the best guide available for free
+ on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
+ r1) to 1.5 were minimal, and many of them were <link
+ url="ecmascriptcompliance" text="omitted"/> from Ibex.
+
+ O'Reilly's <link
+ url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
+ text=" JavaScript: The Definitive Guide"/>, by David Flanagan
+ and Paula Ferguson. The latest edition of this book covers
+ JavaScript 1.5 (ECMA-262 r3).
+
+ The official <link
+ url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
+ text="ECMA-262"/> specification. This is an extremely
+ technical document.
+
+ </list>
+ </section>
+</appendix>
+
+<!-- ----------------------------------------------------------------------- -->
+<appendix title="Logging and Command Line Invocation">
+
+ <pre>
+ Usage: ibex [-lawp] [ url | file | directory ]
+ -l [level] set logging level to { debug, info (default), warn, error, silent }
+ -l rpc log all XML-RPC and SOAP conversations
+ -l user@host email log to user@host
+ -l host:port emit log to TCP socket
+ -l [file] write log to a file on disk
+ -a check assertions
+ -w <window-id> reserved for libibex
+ -p dump profiling information [not yet supported]
+ </pre>
+
+ If Ibex encounters a serious problem before it starts logging
+ information, or if it is unable to open the log file, it will abort
+ immediately with a critical abort, which will be displayed on the
+ console for POSIX-native cores and in a dialog box for JVM-based and
+ Win32-native cores.
+
+ Note that Microsoft Windows does not provide any mechanism for
+ redirecting standard input/output of an application which is not
+ compiled as a "console application". Therefore, Ibex is compiled
+ as a "console application", and will open a console window when
+ invoked. To inhibit this console window, provide a logging
+ destination (file, port, etc).
+
+ The <t><i>source-location</i></t> parameter can be either the path
+ to an <t>.ibex</t> archive, the http url of an <t>.ibex</t>
+ archive, or the path to a directory comprising an unpacked
+ <t>.ibex</t> archive.
+
+ The <t><i>initial-template</i></t> parameter is the stream name of
+ a template to be used as the initial template. If ommitted, it
+ defaults to <t>main</t>.
+
+ The <t>-v</t> option causes Ibex to enable verbose logging; this will
+ cause it to log <i>lots</i> of information to the log file. This
+ option will also substantially decrease Ibex's performance.
+
+ </appendix>
+
+<!-- ----------------------------------------------------------------------- -->
+ <!--
+<appendix title="Grammars">
+
+ <i>Grammar support is experimental in this release
+ and may not work properly. It may change in incompatible ways or
+ disappear completely from future releases</i>
+
+ Grammars are defined with a statement in the following form:
+
+ <pre>
+ a ::= b { c }
+ </pre>
+ A grammar is really just another function; once defined you can't tell
+ it apart from an ordinary function. A grammar takes one argument,
+ which can be a string or stream. The argument is parsed and the
+ result of executing the code block 'c' is returned.
+
+ The property 'a' is read; if the value is a grammar, a new production
+ rule (ie a new alternative, as with '<t>|</t>') is added to that grammar
+ (this is a destructive update). This allows you to add productions to
+ pre-existing grammars (for example, adding a new type of expression to
+ a programming language by extending the 'expr' grammar). If the old
+ value is not a grammar, the value is discarded and a new grammar
+ object is created.
+
+ The value 'b' is a pattern, which may consist of seven simple
+ primitives:
+
+ <list type="unordered">
+ string literals
+
+ grouping parens <t>()</t>
+
+ combinators: <t> | + * ?</t>
+
+ references to other grammars
+ </list>
+
+ The value 'c' and the braces surrounding it are an *optional* code
+ block, in which the following identifiers are bound:
+
+ <list type="unordered">
+
+ The identifier 'whole' is bound to the string matched by the
+ entire expression. If the code block is omitted it behaves
+ as if it were "<t>{ return whole; }</t>".
+
+ For every reference to another grammar which was matched in the
+ pattern, the *name used to reference that other grammar* will
+ be bound to the value returned by its code block. Here's an
+ example of this important distinction:
+
+ <pre>
+ var foo ::= 'a' | 'b';
+ var bar ::= foo;
+ var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
+ </pre>
+
+ On the last line, the identifier 'bar' serves two purposes: it
+ pulls in the definition of the pattern *and* acts as a binder
+ within the scope of the braces.
+
+ If a reference is matched multiple times (either because it
+ appears multiple times in the pattern or because the * or +
+ operator was applied to it) then its name will be bound to an
+ array containing the matches.
+
+ </list>
+
+ Here is the metacircular definition of the grammar facility:
+
+ <pre>
+ grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
+ identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
+ char ::= '\0x0000'..'\0xffff'
+ literal ::= '\'' char+ '\''
+ | '\'' char '\'' '..' '\'' char '\''
+ pattern ::= identifier
+ | literal
+ | '(' pattern ')'
+ | pattern '+'
+ | pattern '?'
+ | pattern '*'
+ | pattern pattern
+ | pattern '|' pattern
+ </pre>
+ -->
+
+<i>
+Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
+Ibex is a trademark of Adam Megacz
+</i>
+
+</ibex-doc>
\ No newline at end of file