1 <ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org">
3 <!-- ----------------------------------------------------------------------- -->
4 <section title="Preface">
7 If you are reading the html version of this document and are
8 thinking of printing it out, you might be interested in the nicely
9 typeset <link url="reference.pdf" text="pdf version"/> produced
13 This document is a <b>reference</b>. It is not a
14 <b>specification</b> or a
17 This document does not guide the user gently through examples (as a
18 tutorial would), and it doesn't provide enough detail and formality
19 for a third party to construct a compatible re-implementation of the
20 Ibex Core (as a specification would).
22 Rather, the goal of this document is to completely describe every
23 aspect of the environment that the Ibex Core provides to client
24 applications, from the bottom up. If you want to be an Ibex expert,
25 this is the right document to read. It is assumed that you are already
26 familiar with XML and with either JavaScript or ECMAscript. If
27 you are not familiar with ECMAscript, some reference materials are
28 provided in <link appendix="G"/>
30 The <i>shoehorn sequence</i> (how the Ibex Core gets onto the
31 client's computer, and how it knows where to download the initial .ibex
32 from) is not described in this document, since it will be different
33 for every platform that Ibex is ported to.
35 If you need to use or rely on some behavior you notice in the Ibex
36 Core, but which is not clearly defined here, please post to <link
37 url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
41 <!-- ----------------------------------------------------------------------- -->
42 <section title="Key Concepts">
44 <section title="Definitions">
46 <definition term="The Core">
47 Ibex itself; the native code (or Java bytecode) that runs on
48 the client. This term does not include the <i>shoehorn</i>
49 or the <i>UI</i></definition>
51 <definition term="The UI / The Application">
52 a set of files (mostly XML, JavaScript, and PNG images)
53 bundled up in a zip archive, ending with the "..ibex"
54 extension. Together, these files specify the appearance and
55 behavior of the application's user interface. Sometimes
56 we'll refer to this as the ".ibex" to be clear that we're
57 talking about the actual zip archive, rather than its visual
58 appearance when rendered on the screen.</definition>
60 <definition term="The Server">
61 We will use the term "the server" to refer to any other
62 computer which the client makes XML-RPC or SOAP calls
63 to. Note that it is possible for the client and server to be
64 the same machine.</definition>
66 <definition term="The Shoehorn">
67 this is a very small piece of code that is downloaded the
68 first time a client uses Ibex. It downloads the Ibex core,
69 verifies its signature, and launches it with the appropriate
70 parameters indicating where to find the initial UI. The
71 Shoehorn works differently on every platform, and is outside
72 the scope of this document.</definition>
74 <definition term="put/write">
75 In ECMAscript, when you change the value of a property on an
76 object, you are <i>putting</i> to that property, or
77 <i>writing</i> to it. For example, the ECMAscript expression
78 "<tt>foo.bar = 5</tt>" <i>puts</i> the value 5 to the bar
79 property on object foo.</definition>
81 <definition term="get/read">
82 In ECMAscript, when you access the value of a property on an
83 object, you are <i>getting</i> that property, or
84 <i>reading</i> from it. For example, the ECMAscript
85 expression "<tt>return (3 + foo.bar)</tt>" <i>gets</i> the
86 value of bar property on object foo and then adds 3 to it
87 before returning the result.</definition>
89 <definition term="JavaScript">
90 We will use the terms JavaScript and ECMAScript
91 interchangeably in this document. The Ibex interpreter is not
92 completely ECMA-compliant, however (see <link
93 appendix="C"/> for details). </definition>
97 <section title="Surfaces">
99 Each top-level window in an Ibex UI is called a
100 <i>surface</i>. There are two kinds of surfaces: <i>frames</i>, which
101 usually have a platform-specific titlebar and border, and
102 <i>windows</i>, which never have any additional platform-specific
105 Whenever we refer to the size or position of a surface, we are
106 referring to the size or position of the UI-accessible portion of the
107 surface; this does not include any platform-specific decorations. This
108 means that if you set the position of a frame to (0,0), the
109 platform-specific titlebar will actually be off the screen on most
110 platforms (it will be above and to the left of the top-left corner of
113 Surfaces are not actual JavaScript objects; you cannot obtain a
114 reference to a surface. However, each surface is uniquely identified
115 by its <i>root box</i>, described in the next section.
119 <section title="Boxes">
121 A <i>box</i> is the fundamental unit from which all Ibex user
122 interfaces are built. Boxes can contain other boxes (known as
123 <i>children</i>). Each Surface has a single box associated with it
124 called the <i>root box</i>; the root box and its children (and its
125 children's children, and so on) form the surface's <i>box tree</i>.
127 There are three ways to think of a box: as a rendered visualization on
128 the screen (the "Visual Representation"), as a JavaScript object (the
129 "Object Representation"), and as an XML tag (the "XML
134 All three representations are equally valid, and being able to figure
135 out what an action in one representation would mean in terms of the other
136 two representations is crucial to a solid understanding of Ibex.
140 <section title="The Object Representation">
142 Each box is a full-fledged ECMAscript object, and can store key-value
143 pairs as properties. Some of these keys have special meaning, which
144 will be explained later. Each box's numeric properties hold its
149 <section title="The Visual Representation">
151 Each box occupies a rectangular region on the surface. The visual
152 appearance of a surface is created by rendering each box in its tree.
153 Unless the <tt>clip</tt> attribute is <tt>false</tt>, each box will
154 clip its childrens' visual representations to its own, so that the
155 children appear "confined to" the parent. Children are rendered after
156 their parents so they appear "on top of" their parents (they obscure
159 Each box has two major visual components, each with subcomponents:
164 A <b>path</b>, which consists of zero or more lines and
165 curves. The path may be filled with a color, gradient, or
166 texture, and may be stroked with a line of a given thickness
167 and color. If the path is not specified, it defaults to the
168 perimiter of the box.
171 The path has an associated <b>strokecolor</b>, which is a
174 The path has an associated <b>strokewidth</b>, which is a
175 number specifying the width of the stroke.
177 The path also has a <b>fill</b>, which is either a color, gradient, or
180 A single line of <b>text</b>, which can be rendered in
181 different fonts, colors, and sizes.
184 The text has an associated <b>font</b>, which currently can be
185 any font supported by the <link url="http://www.freetype.org"
186 text="FreeType2"/> library.
188 The text also has an associated <b>fontsize</b>
190 The text is drawn in an associated <b>textcolor</b>
194 These eight components plus the size of a box fully specify its
195 appearance. Every single box you see in Ibex is drawn only on the
196 basis of these components and its size.
200 <section title="The XML Representation">
202 A template (discussed in the next section) is an XML file which acts
203 as a blueprint for constructing a tree of boxes. We call this
204 construction process <i>applying</i>, since unlike
205 <i>instantiation</i>, you always apply a template to a pre-existing
206 box, and you can apply multiple templates to the same box. Each XML
207 tag corresponds to a single box, or to another template which will be
208 applied to that box. For example, a <tt>scrollbar</tt> template, when
209 applied, will construct a tree of boxes which has the visual
210 appearance and behavior of a scrollbar.
212 Although it is useful to think of the XML tags as being boxes, keep in
213 mind that the XML representation is only a blueprint for constructing
214 a tree of JavaScript objects. Once the template has been
215 instantiated, the XML is effectively "thrown away", and JavaScript code is
216 free to alter the boxes.
220 <section title="Templates">
222 Each template is an XML document whose root element
223 is <tt><ibex></tt>. Any text content of the root element is
224 ignored, and may safely be used for comments. The root element may
225 have any of the following elements as children, each of which may
226 appear no more than once, and which must appear in this order:
228 Here is a sample Ibex file:
231 <ibex xmlns="ibex.widget" xmlns:lib="ibex.lib">
232 This is a sample Ibex file. Text up here is ignored.
233 Copyright (C) 2004 Mustapha Mond.
235 // code here will be executed only once
238 <box id="container"/>
241 /* This has to be commented out or else it
242 will be treated as a script */
251 <section title="Applying an XML tag to a box">
253 The following description of the box application is extremely detailed
254 and precise; it is intended for UI designers who need to know the
255 exact order in which each event happens. FIXME:
256 easier description. While this whole process sounds very
257 complex, it actually works pretty intuitively. The description below
258 is given in great detail since most applications will wind up being
259 unintentionally dependent on subtle features of this process.
260 However, most of the time you can just pretend that the XML tags and
261 the boxes are the same thing.
263 To apply an XML tag <b>X</b> to a box <b>B</b>, perform the following
264 operations, in this order:
266 <list type="ordered">
268 Allocate a fresh scope <b>s</b> whose parent scope is
271 Process each child element or text segment of <b>X</b> in the
272 order they appear in the document: For each <i>text
273 segment</i> <b>t</b>:
276 Treat <b>t</b> a JavaScript script, and execute it
277 with <b>s</b> as the root scope.
280 For each <i>child element</i> <b>x</b> of <b>X</b>:
283 Create a new box <b>b</b>.
285 If the name of tag <b>x</b> is not "<tt>box</tt>" (in the
286 default XML namespace), prepend the tag's namespace
287 identifier uri (if any) to the name of the tag, and use
288 the result as a key to retrieve a property from the root
289 stream (defined later). Interpret the resulting stream as
290 a template and apply that template to <b>b</b>.
292 (recursively) apply <b>x</b> to <b>b</b>.
294 If <b>x</b> has an <tt>id</tt> attribute, declare a variable
295 in <b>s</b> whose name is the value of the <tt>id</tt>
296 attribute, prefixed with the <tt>$</tt> character, and whose
299 Copy any <tt>$</tt>-variables created during the application
300 of <b>x</b> into scope <b>s</b>.
302 Append <b>b</b> as the last child of <b>B</b>.
305 Apply any attributes on <b>X</b> to <b>B</b>, except for
306 <tt>id</tt>. Since XML specifies that the order of attributes
307 cannot be significant, Ibex processes attributes in
308 alphabetical order by attribute name. For example, if
309 <b>X</b> has the attribute <tt>foo="bar</tt>", then the
310 equivalent of the statement <tt>B.foo="bar";</tt> will be
311 performed, with the following exceptions:
314 If the value portion of the attribute is the string
315 "<tt>true</tt>", put the boolean <tt>true</tt>. If the
316 value is "<tt>false</tt>", put the boolean <tt>false</tt>.
318 If the value is a valid ECMAscript number, put it as a
319 number (instead of a string).
321 If the value begins with a dollar sign (<tt>$</tt>),
322 retrieve the value of the corresponding variable in
323 <b>s</b> and use that value instead.
325 If the value begins with a dot (<tt>.</tt>), prepend the
326 attributes' namespace identifier uri (if any) and
327 interpret the remainder as a property to be retrieved from
328 the root stream (defined later).
332 The last two steps are referred to as the <i>initialization</i> of the
333 node. There are two important aspects of this ordering to be aware of:
335 <list type="unordered">
337 A given box will be fully initialized before its parent is
338 given a reference to that box. This way, parents can be
339 certain that they will never wind up accessing a box when it
340 is in a partially-initialized state.
342 Attributes are applied <i>after</i> scripts are run so that
343 the attributes will trigger any <i>traps</i> (defined later)
344 placed by the script.
350 <section title="Life Cycle of an Ibex Application">
352 A user begins by specifying the URL of an Ibex application run.
353 Usually this is done by visiting a web page which uses the
354 <i>shoehorn</i> to install the core if it is not already on the user's
355 machine, but you can also supply the URL on the command line.
357 The Ibex Core downloads the .ibex for the application, loads it, applies
358 the <tt>main.ibex</tt> template and renders it onto the screen, running
359 any associated ECMAscript code.
361 The user interacts with the application by clicking and moving the
362 mouse, and by pressing keys on the keyboard. These actions trigger
363 fragments of JavaScript code which are designated to handle events.
364 This JavaScript code can then relay important information back to the
365 server using XML-RPC or SOAP, or it can modify the structure and
366 properties of the user interface to change its appearance, thereby
367 giving feedback to the user.
370 DIAGRAM: graphic here showing the circular feedback cycle.
373 The Ibex core quits when the last remaining surface has been destroyed.
378 <!-- ----------------------------------------------------------------------- -->
379 <section title="Layout and Rendering">
381 The size and position of every other box is determined
382 by its properties, its childrens' sizes, and its parent's size and position.
383 Box layout and rendering happens in four phases: <i>packing</i>,
384 <i>constraining</i>, <i>placing</i>, and <i>rendering</i>. The Core is careful to only
385 perform a phase on a box if the box has changed in a way that
386 invalidates the work done the last time that phase was performed.
388 packing and constraining phases are performed in a single traversal of
389 the tree (packing is preorder, constraining is postorder), and the
390 placing and rendering phases are performed in a second traversal of
391 the tree (first placing, then rendering, both preorder).
393 For brevity, the rest of this chapter deals only with width and
394 columns. Height and rows is treated identically and independently.
395 Also, it is important to note that the term <i>minimum width</i> is
396 not the same thing as the property <tt>minwidth</tt>, although they
399 <section title="The size of the root box">
401 When the user resizes a window, Ibex changes the root box's
402 <tt>maxwidth</tt> and <tt>maxheight</tt> to match the size chosen by
403 the user and then determines the root box's size using the same sizing
404 rules it uses for other boxes.
406 Ibex will always attempt to prevent the
407 user from making the surface smaller than the root box's
408 <tt>minwidth</tt> and <tt>minheight</tt>. If the <tt>hshrink</tt> or
409 <tt>vshrink</tt> flag is set, Ibex will try to prevent the user from
410 resizing the surface at all. However, not all platforms give Ibex
411 enough control to do this.
415 <section title="The alignment point">
417 When talking about positioning, we will often refer to the
418 <i>alignment point</i>.
420 <list type="unordered">
422 If the <tt>align</tt> property is "<tt>center</tt>", then the
423 alignment point is the center of the box.
425 If the <tt>align</tt> property is "<tt>topleft</tt>",
426 "<tt>bottomleft</tt>", "<tt>topright</tt>", or
427 "<tt>bottomright</tt>", then the alignment point is
428 corresponding corner of the box.
430 If the <tt>align</tt> property is "<tt>top</tt>",
431 "<tt>bottom</tt>", "<tt>right</tt>", or "<tt>left</tt>", then
432 the alignment point is middle of the corresponding edge of the
439 When positioning a child box, the alignment point is determined by the
440 <i>parent's</i> <tt>align</tt> property. When positioning a visual
441 element (a texture, path, or text string) within a box, the alignment
442 point is determined by the <i>box's own</i> <tt>align</tt> property.
444 A simple way to think about this is that whenever there are two boxes
445 involved in the decision, you should use the parent's alignment point.
449 <section title="Packing">
451 of <i>cells</i> is created within the parent. If the parent's
452 <tt>cols</tt> property is set to 0, the cell grid has an infinite
453 number of columns. Either <tt>cols</tt> or <tt>rows</tt> must be
456 If a child's <tt>visible</tt> property is <tt>false</tt>, it does
457 not occupy any cells (and is not rendered). Otherwise, each child
458 occupies a rectangular set of cells <tt>child.colspan</tt> cells
459 wide and <tt>child.rowspan</tt> cells high.
461 The Core iterates over the cells in the grid in the following
462 order: if <tt>rows</tt> is 0, the Core iterates across each column
463 before proceeding to the next row; otherwise rows come before
464 columns. At each cell, the Core attempts to place the <i>first
465 remaining unplaced child's</i> top-left corner in that cell (with
466 the child occupying some set of cells extending down and to the
467 right of that cell). If the parent has a fixed number of columns
468 and the child's <tt>colspan</tt> exceeds that limit, the child is
469 placed in column zero regardless, but only occupies the available
470 set of cells (it does not "hang off the end" of the box).
472 <img src="image/layout.png"/>
477 <box id="2" rowspan="2" />
478 <box id="3" colspan="2" />
480 <box id="5" colspan="2" />
484 Notes on the layout example:
486 <list type="ordered">
488 Box '3' doesn't fit in the gap after '2', nor in the gaps either
489 side of '2' on the next row, hence it is pushed onto the 3rd row.
491 Box '4' would fit in the gaps around '2', but must be placed
492 <i>after</i> it's preceeding box, '3'.
498 <section title="Constraining">
500 <list type="ordered">
502 Each box's minimum width is computed recursively as the
506 Its <tt>minwidth</tt>
508 The width of the box's <tt>text</tt> (after applying the
509 box's <tt>transform</tt>).
511 The width of the box's path (after applying the box's
512 <tt>transform</tt>) <i>if the box is <tt>packed</tt></i>.
514 The width of the bounding box enclosing the box's cells.
517 The minimum width of each cell is computed as the minimum
518 width of the box occupying it divided by the box's
521 If a box's <tt>hshrink</tt> property is set to
522 <tt>true</tt>, the box's maximum width is the same as its
523 minimum width; otherwise it is the box's
526 The maximum width of each cell is the <tt>maxwidth</tt> of
527 the box occupying it divided by the box's
534 <section title="Placing">
536 <list type="ordered">
538 Each column's <i>actual width</i> is set to the maximum
539 <i>minimum width</i> of all the cells in that column.
540 <b>NOTE:</b> although a column or row can be sized smaller
541 than its "minimum width" or larger than its "maximum width", a
542 box will <i>never</i> be smaller than its <tt>minwidth</tt> or
543 larger than its <tt>maxwidth</tt>.
545 Each column's maximum width is the largest maximum width of
546 the cells in that column, but no smaller than the column's
549 The <i>slack</i> is the difference between the parent's width
550 and the sum of its columns' actual width. The slack is
551 divided equally among the columns. Any column which has
552 exceeded its maximum width is set to its maximum width, and
553 the difference is returned to the slack. This process is
554 repeated until the slack is zero or all columns are at their
557 Next, the rows and columns are positioned within the parent
558 box. The rows and columns are transformed according to the
559 parent's <tt>transform</tt> property, and the bounding box of
560 the resulting cells are placed such that the cells' alignment
561 point coincides with the parent's alignment point (both
562 alignment points are determined by the parent's <tt>align</tt>
563 property). FIXME: diagram
565 <b>Packed boxes:</b> Each packed box's actual position
566 and size is then set to the aggregation of the actual sizes of
567 the cells it spans. If this size exceeds the box's maximum
568 width, the box is sized to its maximum width and centered
569 horizontally within the space occupied by its cells.
570 <b>Non-packed boxes</b>: each non-packed box is transformed
571 according to the parent's <tt>transform</tt> property and then
572 positioned so that its alignment point is <tt>(child.x,
573 child.y)</tt> pixels from the parent's alignment point (both
574 alignment points are determined by the parent's <tt>align</tt>
581 <section title="Rendering">
583 Boxes are rendered in a depth-first, pre-order traversal. Note that
584 this may cause a non-packed box to overlap its siblings.
586 <list type="ordered">
588 If the box's <tt>transform</tt> property is non-null, the
589 coordinate space is transformed accordingly for the rest of
590 this phase and for the rendering of all children.
592 If the box is packed and has a non-<tt>null</tt> path, the
593 path is translated such that the alignment point of the path's
594 bounding box coincides with the box's alignment point (both
595 alignment points are determined by the box's <tt>align</tt>
598 If a box has a path, that path is filled with the color,
599 gradient, or image specified by the <tt>fill</tt> property and
600 stroked with the color and width specified by the
601 <tt>strokecolor</tt> and <tt>strokewidth</tt> properties.
603 If the box has a non-<tt>null</tt> <tt>text</tt> attribute,
604 the text is rendered in <tt>font</tt> with size
605 <tt>fontsize</tt> and color <tt>textcolor</tt>. The text is
606 then translated such that the alignment point of the text's
607 bounding box coincides with the box's alignment point (both
608 alignment points are determined by the box's <tt>align</tt>
611 The box's children are rendered (pre-prder traversal).
619 <!-- ----------------------------------------------------------------------- -->
620 <section title="Box Properties">
622 <section title="Rendering Properties">
624 Every box has several special properties which control how it is
625 drawn. In general, if you put an
626 invalid value to a special property, no action will be taken -- the
629 <property name="strokecolor" type="string" default="clear">
630 If the value is a 5-character hex string (<tt>#RGB</tt>),
631 7-character hex string (<tt>#RRGGBB</tt>), 9-character hex
632 string (<tt>#AARRGGBB</tt>), the box's stroke color will be set
634 If the value is one of the <link url="http://www.color.org/ICC-1A_1999-04.PDF" text="ICC"/> colors
635 (the same set of color names supported by SVG), the stroke
636 color be set to that color.
637 If the value is <tt>null</tt>, the stroke color will be set to
638 clear (<tt>#00000000</tt>).
641 <property name="strokewidth" type="int" default="1">
642 The width (in pixels) to stroke the path with.
645 <property term="fill">
646 This property can be set to any of the values specified for
647 <tt>strokecolor</tt>.
648 Alternatively, if the value written is an object, its stream
649 will be read and interpreted as a PNG, GIF, or JPEG image,
650 which will become the texture for this box, and the box's
651 <tt>minwidth</tt> and <tt>minheight</tt> properties will be
652 automatically set to the dimensions of the image.
655 <property name="path" type="string" default="""">
656 The box's path. The grammar and feature set
657 supported are identical to that specified in <link url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1, section
661 <property name="text" type="string" default="""">
662 The box's text; writing <tt>null</tt> to this property sets it
666 <property name="font" type="stream" default=".ibex.font.sansserif">
667 When an object is written to this property, its stream is read
668 using the <link url="http://www.freetype.org" text="freetype2
669 library"/>, and the resulting font is used to render the
673 <property name="fontsize" type="number" default="10">
674 The size (in points) to render the text.
677 <property name="textcolor" type="number" default="black">
678 The color in which to render the font; accepts the same values as <tt>strokecolor</tt>.
683 <section title="Layout Properties">
685 <property name="shrink" type="boolean" default="false">
686 If set to <tt>true</tt>, this box will shrink
687 (horizontally/vertically/both) to the smallest size allowed by
688 its children and the bounding box of its path.
691 <property name="x" type="integer" default="varies">
692 If the box is a root box, this is the (x/y)-coordinate of the
693 surface; otherwise it is the distance between the parent's
694 alignment point and this box's alignment point.
697 <property name="globalx" type="integer" default="varies">
698 The distance between this box's (left/top) edge and the root
699 box's (left/top) edge. A put to this property has the same
700 effect as a put to the (<tt>x</tt>/<tt>y</tt>) property,
701 except that it is relative to the root box rather than to this
702 box's parent. FIXME is this fakeable? How is
706 <property name="minwidth" type="integer" default="0">
707 The desired minimum width and height.
710 <property name="maxwidth" type="integer" default="ibex.maxint">
711 The desired maximum width and height.
714 <property name="width" type="integer" default="varies">
715 When read, this is the (width/height) of this box. Writing to
716 this property is equivalent to writing to <i>both</i> the
717 minimum and maximum (width/height).
720 <property name="cols" type="integer" default="0">
721 The number of (columns/rows) in which to lay out the children of this
722 box. If set to zero, the number of (columns/rows) is unconstrained.
723 Either <tt>rows</tt> or <tt>cols</tt> must be zero. If
724 <tt>0</tt> is written to <tt>cols</tt> when <tt>rows</tt> is
725 <tt>0</tt>, the write is ignored. If a nonzero value is
726 written to <tt>cols</tt> when <tt>rows</tt> is nonzero,
727 <tt>rows</tt> is set to <tt>0</tt>, and vice versa.
730 <property name="colspan" type="integer" default="1">
731 The number of (columns/rows) that this box spans within its parent.
734 <property name="align" type="string" default="center">
735 Determines the box's alignment point for positioning its text,
736 texture, path, and children.
739 <property name="visible" type="boolean" default="true">
740 If set to false, this box will be rendered as if its width and
741 height were zero. If this is a root box, the associated surface
743 When reading from this property, the value
744 <tt>false</tt> will be returned if this box <i>or any of its
745 ancestors</i> is not visible. Thus it is possible to write
746 <tt>true</tt> to a box's <tt>visible</tt> property and then
747 read back <tt>false</tt>.
750 <property name="packed" type="boolean" default="true">
751 The layout strategy for this box.
756 <section title="Child Control Properties">
758 During a box initialization, script-private references to a box's
759 descendants with <tt>id</tt> attributes are placed on the box. These
760 references allow scripts on that box to easily refer to descendant
761 nodes created by the template in which the script appears. For
762 example, these two blocks of code have exactly the same effect:
766 <box id="foo"/> <box/>
767 $foo.color = "red"; var $foo = this[0];
772 The following special properties control how a box's children are laid
773 out. If a box has a non-null redirect target, reads and writes to these
774 properties will be forwarded to the redirect target.
776 The <tt>redirect</tt> attribute is very useful for hiding the
777 internal structure of a widget, and for allowing widgets to act as
778 "smart" containers for other widgets. For example, a menu widget might
779 have an invisible child as its redirect target; this way, when boxes
780 representing items on the menu are added as children of the menu
781 widget, they do not appear until the menu is pulled down.
783 <property name="numeric properties" type="int" default="">
784 The <i>n</i>th child of box <tt>b</tt> can be accessed by reading from
785 <tt>b[n]</tt>. The <i>n</i>th child can be removed by writing
786 <tt>null</tt> to <tt>b[n]</tt> (the child will become parentless). A
787 new child can be inserted <i>before</i> the <i>n</i>th child by
788 writing it to <tt>b[n]</tt>; if the value written is already a child of
789 <tt>b</tt>, it will be removed from <tt>b</tt> first. It is important
790 to note that this behavior is different from ECMAscript arrays --
791 writing a non-<tt>null</tt> value to <tt>b[n]</tt> does not eliminate
792 the <i>n</i>th child; it merely shifts it over one position.
793 <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
794 properties with the JavaScript <tt>for..in</tt> construct will
795 enumerate <i>only</i> the box's children and not any other properties.
798 <property name="clip" type="boolean" default="true">
799 If <tt>true</tt>, the visual representation of this box's
800 children will be clipped to the boundaries of this box.
801 <b>Note:</b> setting this property to <tt>false</tt> imposes a
802 substantial performance penalty.
805 <property name="numchildren" type="integer" default="0">
806 The number of children this box has.
809 <property name="redirect" type="box" default="thisbox">
810 Writing to this property sets the box's redirect
811 target. This property cannot be read from, and can only be
815 <property name="surface" type="" default="null">
816 If this box has a parent, this property returns
817 <tt><i>parent</i>.surface</tt>; otherwise it returns null.
818 This property is a simple building block that the widget
819 library uses to implement more complex functionality such as
820 focus control and popups.
825 <section title="Other Box Properties">
827 <property name="cursor" type="string" default="null">
828 The shape that the cursor should take when inside this
829 box. Valid values are: "<tt>default </tt> " , "<tt>wait</tt>",
830 "<tt>crosshair</tt>", "<tt>text</tt>", "<tt>hand</tt>", and
831 "<tt>move</tt>", as well as resizing cursors"<tt>east</tt>",
832 "<tt>west</tt>", "<tt>north</tt>", "<tt>south</tt>",
833 "<tt>northwest</tt>", "<tt>northeast</tt>",
834 "<tt>southwest</tt>", and "<tt>southeast</tt>". Note that on
835 some platforms, resize cursors for opposite directions (such
836 as <tt>northwest</tt> and <tt>southeast</tt> are the
838 If a box's cursor is <tt>null</tt>, its parent's cursor will
839 be used. If the root box's cursor is null, the
840 "<tt>default</tt>" cursor will be used.
843 <property name="mouse.x" type="integer" default="varies">
844 The (horizontal/vertical) distance between the mouse cursor and this
845 box's (left/top) edge. Puts to this property are ignored. This
846 value will not be updated if the mouse is outside the root
847 box of the surface and no button was pressed when it left.
850 <property name="mouse.inside" type="boolean" default="false">
851 True if the mouse is inside the rendered region of this box or
852 any of its children. This value will be false if the mouse is
853 inside a portion of this box which is covered up by one of
854 this box's siblings, or one of its ancestors' descendants. Puts
855 to this value are ignored.
858 <property name="static" type="object" default="N/A">
859 Reading from this property will return the parent scope used
860 to execute the <tt><static/></tt> block of the template
861 in which the currently-executing code resides.
864 <property name="thisbox" type="box" default=" ">
865 Returns a reference to the box itself.
866 If <tt>null</tt> is written to this property, and this box is
867 the root box of a surface, the box will be detached and the
868 surface destroyed. If this box has a parent, it will be
869 detached from its parent.
872 <property name="indexof()" type="function" default=" ">
873 This property is actually a function; invoking
874 <tt>parent.indexof(child)</tt> will return the numerical index
875 of <tt>child</tt> in <tt>parent</tt> if <tt>child</tt> is a
876 child of <tt>parent</tt> (or <tt>parent</tt>'s redirect
877 target), and <tt>-1</tt> otherwise. Writing to this property
881 <property name="childadded" type=" " default=" ">
883 These properties are meant to be trapped on FIXME defined later?. Placing a trap on
884 <tt>childadded/childremoved</tt> lets a box receive
885 notification when a child is added/removed. In either
886 situation, the child will be passed as an argument to the trap
887 function <i>after</i> the addition or removal has been
890 Note that if the parent's redirect target is set to another
891 box, these traps will only be invoked when children are
892 manipulated by reading and writing to the parent. Reads and
893 writes directly to the redirect target will <i>not</i> trigger
896 Note also that these traps are still triggered if a box's
897 <tt>redirect</tt> target is <i>null</i>. This is useful for
898 boxes that need to accept children and then relocate them
904 <section title="Notification Properties">
906 The following properties are used to notify a box of changes specific
907 to that particular box.
909 <property name="Enter">
910 The value <tt>true</tt> is written to this property when the mouse enters the box.
913 <property name="Leave">
914 The value <tt>true</tt> is written to this property when the mouse leaves the box.
917 <property name="SizeChange">
918 The value <tt>true</tt> is put to this property after the size
924 <section title="Root Box Properties">
926 The following special properties are only meaningful on the root box
929 <property name="Focused">
930 The value <tt>true</tt> is put to this property on the root box
931 when the surface gains the input focus, and <tt>false</tt> when
932 the surface loses the input focus. Reading from this value will
933 return <tt>true</tt> if the surface is focused and <tt>false</tt>
934 if it is not. Putting <tt>true</tt> to this property will
935 <i>not</i> cause the surface to "steal" the input focus from other
939 <property name="Maximized">
940 The value <tt>true</tt> is put to this property on the root box
941 when the surface is maximized, and <tt>false</tt> when the surface
942 is un-maximized. Reading from this value will return <tt>true</tt>
943 if the surface is maximized and <tt>false</tt> if it is
944 not. Putting <tt>true</tt> to this property will maximize the
945 window, and putting <tt>false</tt> to this property will
946 unmaximize the window.
947 Note that not all platforms support maximization.
950 <property name="Minimized">
951 The value <tt>true</tt> is put to this property on the root box
952 when the surface is minimized, and <tt>false</tt> when the surface
953 is unminimized. Reading from this value will return <tt>true</tt>
954 if the surface is minimized and <tt>false</tt> if it is
955 not. Putting <tt>true</tt> to this property will minimize the
956 window, and putting <tt>false</tt> will unminimize it.
959 <property name="Close">
960 When the user attempts to close a surface, the value
961 <tt>true</tt> will be put to this property. Scripts may trap
962 this property FIXME defined later? to
963 prevent the window from closing. Putting the value
964 <tt>true</tt> to this property on a root box has the same
965 effect as putting <tt>null</tt> to the <tt>thisbox</tt>
969 <property name="icon">
970 The surface's icon. This is usually displayed on the titlebar of a
971 window. The value should be the stream name of a PNG image. Note
972 that not all platforms support this property.
975 <property name="titlebar">
976 The surface's titlebar text. Note that not all platforms support
977 this property. Only ASCII characters 0x20-0x7F are permitted.
984 <!-- ----------------------------------------------------------------------- -->
985 <section title="Streams">
987 <section title="Every object has a stream...">
989 Every object has a <i>stream</i> associated with it. A stream is a
990 sequence of bytes that can be read or written to.
992 By default an object has an empty stream (zero bytes). However, some objects
993 (returned from special methods on the <tt>ibex</tt> object) have
994 streams yielding data read from an url, file, or a component of a zip
995 archive. In a future release, the stream associated with a box will
996 be an .ibex template which, when applied, will fully reconstitute the
1001 <section title="...but streams are not objects">
1003 Despite the ubiquity of streams, you cannot actually reference a
1004 stream, since it is not an object. Instead, you simply reference the
1005 object it belongs to. If you are familiar with Java, this is similar
1006 to how every Java object has a monitor associated with it, but you
1007 cannot directly manipulate the monitor (you can't pass around a
1008 reference to just the monitor).
1010 In the rest of the section we will sometimes refer to "getting
1011 properties from a stream" or "passing a stream to a function"; this is
1012 just shorthand for saying to perform those actions on the object the
1017 <section title="Creating Streams from URLs">
1019 You can create a stream from a URL by calling
1022 var r = ibex.stream.url("http://...");
1025 This will return an object whose stream draws data from the specified
1026 URL. Streams are loaded lazily whenever possible.
1030 <section title="Getting Substreams">
1032 Most stream objects let you access
1033 substreams using the usual JavaScript operators <tt>[]</tt> and
1034 <tt>.</tt>, as well as the <tt>for..in</tt> syntax.
1037 // r1 and r2 are equivalent but not equal (!=)
1038 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1039 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1044 <section title="The Root Stream">
1046 The empty-string property on the <tt>ibex</tt> object is called the
1047 <i>root stream</i>. You can access this object as <tt>ibex..</tt> or
1048 <tt>ibex[""]</tt>. Additionally, any expression which starts with a
1049 dot is treated as property to be retrieved from the root stream. The
1050 following three expressions are equivalent:
1060 <section title="Static Blocks">
1062 You can access variables within the static block of a template by
1063 appending a double period (<tt>..</tt>) and the variable name to the
1064 stream used to load that template:
1067 <!-- org/ibex/themes/monopoly/scrollbar.ibex -->
1071 ibex.log.print(org.ibex.themes.monopoly.scrollbar..foo); // prints "12"
1076 <section title="Formatting Streams">
1078 If you attempt to send a stream as part of an XML-RPC call, the
1079 stream will be read in its entirity, Base64-encoded, and transmitted
1080 as a <tt><base64/></tt> element.
1082 Ibex supports two special URL protocols. The first is <tt>data:</tt>,
1083 which inteprets the rest of the URL as a Base64 encoded sequence of
1084 bytes to use as a source. The other is <tt>utf8:</tt> which
1085 interpretets the rest of the string as a Unicode character sequence to
1086 be UTF-8 encoded as a string of bytes to use as a source.
1089 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1090 var r6 = ibex.stream.url("utf8:this is a test");
1093 You can read a UTF-8 encoded string from a stream like this:
1096 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:this is a test"));
1098 You can also parse XML from a stream using SAX like this:
1101 ibex.stream.xml.sax(ibex.stream.url("http://foo.com/foo.xml"),
1102 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1103 endElement : function(tagname) { ... },
1104 content : function(contentString) { ... }
1105 whitespace : function(whitespaceString) { ... }
1113 <!-- ----------------------------------------------------------------------- -->
1114 <section title="The Ibex object">
1116 The <tt>ibex</tt> object is present in the top-level scope of every
1117 script. It has the following properties:
1119 <section title="General">
1121 <property name="ibex.box">
1122 reading from this property returns a new box
1124 <property name="ibex.clone(o)">
1125 creates a clone of object
1127 <property name="ibex.bless(s)">
1128 returns a blessed clone of stream
1133 <section title="ECMA Library Objects">
1135 <property name="ibex.date">
1136 reading from this property returns a new date
1138 <property name="ibex.math">
1139 this object contains the ECMA math functions
1141 <property name="ibex.regexp(s)">
1142 return a regexp object corresponding to string <i>s</i>
1144 <property name="ibex.string">
1145 this object contains the ECMA string manipulation functions
1150 <section title="Logging">
1152 <property name="ibex.log.debug(m, o)">
1153 log the debug message <i>m</i>, optionally dumping object
1157 <property name="ibex.log.info(m, o)">
1158 log the informational message <i>m</i>, optionally dumping
1162 <property name="ibex.log.warn(m, o)">
1163 log the warning message <i>m</i>, optionally dumping object
1167 <property name="ibex.log.error(m, o)">
1168 log the error message <i>m</i>, optionally dumping object
1175 <!-- ----------------------------------------------------------------------- -->
1176 <section title="User Interface">
1178 <property name="ibex.ui.browser(u)">
1179 opens a new browser window with URL <i>u</i>
1182 <property name="ibex.ui.key.control">
1183 true if the control key is depressed
1186 <property name="ibex.ui.key.shift">
1187 true if the shift key is depressed
1190 <property name="ibex.ui.key.alt">
1191 true if the alt key is depressed
1194 <property name="ibex.ui.key.name.alt">
1195 the name of the "alt" key (usually either "alt", "meta", or
1199 <property name="ibex.ui.clipboard">
1200 the contents of the clipboard; can be read and written to
1203 <property name="ibex.ui.maxdim">
1204 the maximum dimension of any UI element; usually
1205 2<sup>31</sup>, but may be smaller
1208 <property name="ibex.ui.screen.width">
1209 the width of the screen, in pixels
1212 <property name="ibex.ui.screen.height">
1213 the height of the screen, in pixels
1216 <property name="ibex.ui.mouse.button">
1217 either 0, 1, 2, or 3, indicating the mouse button currently
1221 <property name="ibex.ui.frame">
1222 when a box is written to this property, it becomes the root
1226 <property name="ibex.ui.window">
1227 when a box is written to this property, it becomes the root
1231 <property name="ibex.ui.font.serif">
1232 an object whose stream is a a builtin serif font
1235 <property name="ibex.ui.font.sansserif">
1236 an object whose stream is a builtin sans-serif font
1239 <property name="ibex.ui.font.monospace">
1240 an object whose stream is a a builtin fixed-width font
1243 <section title="Networking">
1245 <property name="ibex.net.http">
1249 <property name="ibex.net.rpc.xml(u)">
1250 return an XML-RPC call object with endpoint URL <i>u</i>
1253 <property name="ibex.net.rpc.soap(u,">
1254 return a SOAP call object with endpoint URL <i>u</i>,
1255 SoapAction <i>a</i>, and XML Namespace <i>n</i>
1260 <section title="Threads">
1262 <property name="ibex.thread">
1263 when a function is written to this property, a new thread is
1267 <property name="ibex.thread.yield()">
1268 yield the current thread
1271 <property name="ibex.thread.sleep(n)">
1272 sleep for <i>n</i> milliseconds
1277 <section title="Streams">
1279 <property name="ibex.stream.url(u)">
1280 returns a new object whose stream is drawn from URL <i>u</i>
1283 <property name="ibex.stream.unzip(s)">
1284 unpacks a zip archive from <i>s</i>'s stream
1287 <property name="ibex.stream.uncab(s)">
1288 unpacks a cab archive from <i>s</i>'s stream
1291 <property name="ibex.stream.cache(s,k)">
1292 valign=top>wraps a disk-backed read cache keyed on <i>k</i>
1293 around <i>s</i>'s stream
1296 <property name="ibex.stream.watch(s,f)">
1297 returns an object whose stream is drawn from <i>s</i>'s
1298 stream, but invokes <i>f(n,d)</i> as it is read from.
1301 <property name="ibex.stream.parse.xml(s, h)">
1302 Use SAX to parse the XML document on stream <i>s</i> with
1306 <property name="ibex.stream.parse.html(s, h)">
1307 Same as <tt>parse.xml()</tt>, but tries to fix broken HTML.
1310 <property name="ibex.stream.parse.utf8(s)">
1311 treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string
1314 <property name="ibex.stream.homedir">
1315 <tt>ibex.stream.tempdir</tt>
1320 <section title="Cryptography">
1322 <property name="ibex.crypto.rsa(k,s)">
1323 <i>not implemented yet:</i> return a
1324 stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
1327 <property name="ibex.crypto.rc4(k,s)">
1328 <i>not implemented yet:</i> return a
1329 stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
1332 <property name="ibex.crypto.md5(s)">
1333 <i>not implemented yet:</i> immediately
1334 MD5-hash stream <i>s</i>
1337 <property name="ibex.crypto.sha1(s)">
1338 <i>not implemented yet:</i> immediately
1339 SHA1-hash stream <i>s</i>
1345 <!-- ----------------------------------------------------------------------- -->
1346 <section title="Traps">
1348 <section title="Simple Traps">
1350 You can add a trap to a property by applying the <tt>++=</tt> operator
1351 to a function with one argument. The trap will be invoked whenever
1352 that property is written to.
1356 foo ++= function(z) {
1357 ibex.log.info("foo is " + z);
1362 If another script were to set the property "<tt>foo</tt>"
1363 on the box above to the value <tt>5</tt>, the function above would be
1364 invoked with the argument <tt>5</tt>. The function would then log
1365 the string "<tt>foo is 5</tt>".
1367 Within a trap, the expression <tt>trapee</tt> can be used to
1368 get a reference to the box on which the trap was placed.
1370 The expression <tt>trapname</tt> returns the name of the
1371 trap executing the current function. This is useful when a function
1372 is applied to multiple traps. For example:
1376 func ++= function(z) {
1377 ibex.log.info("called trap " + trapname);
1386 <section title="Removing Traps">
1388 You can remove a trap by using the <tt>--=</tt> operator with the same
1389 function you added as a trap:
1393 var myfunc = function(z) { /* ... */ }
1404 <section title="Multiple Traps on the Same Property">
1406 When the property is <i>written</i> to, each of the trap functions placed
1407 on it will be invoked in the opposite order that they were placed on
1408 the box -- the most recently placed trap will execute first. This
1409 last-to-first execution of traps is called <i>cascading</i>. After the
1410 last trap is invoked, the value is stored on the box (remember, boxes
1411 are objects, so they can hold properties just like all other
1412 ECMAscript objects).
1416 <section title="Manual Cascades">
1418 There are two additional tricks you can use when placing traps. The
1419 first is a <i>manual cascade</i>. If you want to cascade to lower
1420 traps in the middle of a function, or you want to cascade with a
1421 different value than the value passed to you (in effect "lying" to
1422 lower traps), you can use <tt>cascade</tt>. For example:
1426 color ++= function(c) {
1427 ibex.log.info("refusing to change colors!");
1433 This effectively creates a box whose color cannot be changed, and
1434 which complains loudly if you try to do so.
1436 Do <i>not</i> try to do something like this:
1440 color ++= function(z) {
1441 color = "black"; // INFINITE LOOP! BAD!!!
1445 To prevent automatic cascading, return <tt>true</tt> from your function:
1449 color ++= function(z) {
1450 return true; // the box's color will not change
1457 <section title="Read Traps">
1459 The other trick is a <i>read-trap</i>. Read traps are just like normal
1460 traps, except that you use a function that takes zero arguments instead of one. Read traps
1461 also do not automatically cascade.
1465 doublewidth <tt>++=</tt> function() { return 2 * width; }
1469 If another script attempts to read from the <tt>doublewidth</tt>
1470 property on this box, the value it gets will be twice the actual width
1471 of the box. Note that
1472 the actual <tt>doublewidth</tt> property on the box never gets written
1473 to, since the trap does not cascade.
1475 You can manually cascade on read traps as well:
1479 text <tt>++=</tt> function() { return "my text is " + cascade; }
1483 Read traps are only rarely needed -- most of the time a write trap
1488 <section title="Prohibited Traps">
1490 To prevent confusing and hard-to-debug behaviors, scripts may not
1491 place traps on any of the properties described in the sections
1492 <link section="Box Layout Properties"/>, <link
1493 section="Child-Control Properties"/>, or <link section="Other Box
1494 Properties"/> except for <tt>childadded</tt>,
1495 <tt>childremoved</tt> and <tt>surface</tt>. FIXME: remove?
1499 <section title="Exceptions and Traps ">
1501 If an uncaught exception is thrown from a trap, Ibex will log the
1502 exception, but will <i>not</i> propagate it to the code which
1503 triggered the trap. If the trap was a read trap, the value
1504 <tt>null</tt> will be returned.
1505 FIXME: is this right?
1508 <section title="Architectural Significance of Traps">
1510 Traps are the backbone of Ibex. Since almost all UI programming is
1511 event/demand driven, traps eliminate the need for separate
1512 member/getter/setter declarations, often cutting the amount of typing
1513 you have to do to a third of what it would normally be.
1516 <section title="Cloning">
1518 <i>Cloning</i> is a companion technique for traps; together they can
1519 be used to simulate any sort of environment you might need. When you
1520 call <tt>ibex.clone(o)</tt>, Ibex returns a new object (called the
1521 <i>clone</i>) which compares with equality (<tt>==</tt>) to the
1522 original object. Furthermore, both objects are "equal" as keys in
1527 var theclone = ibex.clone(o);
1529 ibex.log.info(hash[theclone]); // prints "5"
1532 Any writes to properties on the clone will actually write to
1533 properties on the original object, and reads from properties on the
1534 clone will read properties on the original object. In fact, the only
1535 thing that can be used to distinguish the original from the clone is
1536 traps -- a trap placed on the clone is <i>not</i> placed on the
1537 original object as well.
1541 <section title="Ibex self-emulation">
1543 When the core first starts up, it clones the <tt>ibex</tt> object,
1544 creates a stream for the initial .ibex, and then places a trap on the
1545 cloned <tt>ibex</tt> object so that its empty-string property returns
1546 the .ibex stream. The cloned Ibex object is then passed as the third
1547 (optional) argument to <tt>ibex.apply()</tt>, making it the default
1548 <tt>ibex</tt> object for the scripts that are executed as part of the
1549 template instantiation.
1552 var new_ibex = ibex.clone(ibex);
1553 var stream = ibex.bless(ibex.stream.url("http://..."));
1554 new_ibex[""] ++= function() { return stream; }
1555 ibex.apply(ibex.box, new_ibex..main, new_ibex);
1558 Note that we called <tt>ibex.bless()</tt> on the stream before tacking
1559 it on to the new Ibex object. The bless function returns a clone of
1560 the object passed to it, with a few traps which are explained below.
1561 Additionally, any sub-streams retrieved by accessing properties of the
1562 blessed stream will also automatically be blessed (blessed streams are
1565 Blessing a stream serves three purposes:
1567 <list type="unordered">
1569 Blessed clones always return the appropriate static block when
1570 their empty property is accessed; this ensures that references
1571 to the static blocks of other templates work properly.
1573 Blessed substreams can return their parent stream by accessing
1574 a hidden property which is reserved for internal use by Ibex.
1575 This ensures that Ibex can automatically add filename
1576 extensions where needed, according to the following rules:
1579 If the stream is a template to be applied, the string
1580 "<tt>.ibex</tt>" is appended.
1582 If the stream is an image, the string "<tt>.png</tt>" is
1583 appended. If no stream is found, "<tt>.jpeg</tt>" and
1584 "<tt>.gif</tt>" are tried, in that order.
1586 If the stream is an font, the string "<tt>.ttf</tt>" is
1590 Every call to <tt>ibex.bless()</tt> returns a different object
1591 (which happens to be a clone of the object passed to it) with
1592 a completely separate set of static blocks.
1596 Ibex can self-emulate by using <tt>ibex.clone()</tt> on the Ibex object;
1597 this technique is very similar to the use of ClassLoaders in
1598 Java. This is useful for a number of applications, including
1599 debuggers, IDEs, sandboxing untrusted code, remote-control, and
1600 others. For example:
1603 var newLoadFunction = function(url) { /* ... */ };
1604 var new_ibex = ibex.clone(ibex);
1605 new_ibex.load ++= function() { return newLoadFunction; }
1606 ibex.apply(ibex.box, .main, new_ibex);
1612 <!-- ----------------------------------------------------------------------- -->
1613 <section title="Contexts and Threading">
1615 <section title="Contexts">
1617 From the perspective of an application writer, Ibex is strictly
1618 single-threaded. Ibex is always in exactly one of the following three
1621 <list type="unordered">
1623 <b>Rendering Context</b> -- (redrawing the screen)
1625 <b>Event Context</b> (executing javascript traps triggered by an event)
1627 <b>Thread Context</b> (executing a background thread spawned with <tt>ibex.thread</tt>)
1631 There are two important restrictions on what can be done in particular contexts:
1633 <list type="unordered">
1635 The <tt>box.mouse</tt> property and its subproperties
1636 (<tt>x</tt>, <tt>y</tt>, and <tt>inside</tt>) can only be read
1637 from within the Event Context, or in a thread context
1638 <i>after</i> a the <tt>box.mouse</tt> property on this box or
1639 an ancestor box has been written to.
1641 Blocking operations (anything that accesses the network or
1642 disk) can only be performed in the Thread Context.
1648 <section title="Background Threads">
1650 Ibex offers easy access to threads. Spawning a background thread is as
1651 simple as writing a function to the <tt>ibex.thread</tt> property:
1654 ibex.thread = function() {
1655 ibex.log.info("this is happening in a background thread!");
1659 The argument set passed to the function is currently undefined and is
1660 reserved for use in future versions of Ibex. Scripts should not
1661 depend on the number or content of these arguments.
1663 Ibex is <i>cooperatively multitasked</i>, so threads must not process
1664 for too long. This was a deliberate choice; cooperatively
1665 multitasked environments do not require complex locking primitives
1666 like mutexes and semaphores which are difficult for novices to
1667 understand. The disadvantage of cooperative multitasking is that one
1668 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1669 first, all blocking I/O operations <i>automatically</i> yield the CPU,
1670 so the overall user interface never becomes unresponsive because it is
1671 waiting for a disk or network transfer. Second, since Ibex is strictly
1672 a user interface platform, Ibex scripts are unlikely to perform highly
1673 compute-intensive operations that keep the CPU busy for more than a
1678 <section title="Events">
1680 Every execution of the Event Context begins with an event, which
1681 consists of a key/value pair, and a mouse position, which consists of
1682 an x and y coordinate. The possible keys are <tt>_Press[1-3]</tt>,
1683 <tt>_Release[1-3]</tt>, <tt>_Click[1-3]</tt>, <tt>_DoubleClick[1-3]</tt>,
1684 <tt>_Move</tt>, <tt>_KeyPressed</tt>, and <tt>_KeyReleased</tt>.
1686 Here are two example events:
1688 An event is triggered by writing the key to the value on a box. This
1689 triggers any trap handlers which may be present. Once these handlers
1690 have executed, Ibex figures out which child of the current box contains
1691 the mouse (taking into account that some boxes may cover up others)
1692 and writes the key and value to that box. If none of the box's
1693 children contain the mouse position, Ibex removes the leading
1694 underscore from the key name and writes the value to
1695 <i>that</i> property. Once all the traps on that property have
1696 executed, the value is written to the box's parent.
1698 Intuitively, Ibex delivers the underscored event to every box from the
1699 root to the target, and then delivers the non-underscored event to
1700 that same set of boxes in reverse order. So the event travels down
1701 the tree to the target, and then back up to the root. The following
1702 example prints out "first second third fourth" in that order.
1706 _Press1 ++= function(b) { ibex.log.info("first"); }
1707 Press1 ++= function(b) { ibex.log.info("fourth"); }
1709 _Press1 ++= function(b) { ibex.log.info("second"); }
1710 Press1 ++= function(b) { ibex.log.info("third"); }
1715 In general, you should use the <i>non-underscore</i> names to respond
1716 to user input and use the underscored names when you want to override
1717 child boxes' behavior or route events to particular boxes (for
1718 example, when implementing a focus protocol). This is why the
1719 underscored elements are delivered to parents before children (so
1720 parents can override their childrens' behavior), but non-underscored
1721 events are delivered to children before parents (since, visually, a
1722 mouse click is usually "intended" for the leaf box underneath the
1727 <section title="Stopping the Process">
1729 At any point in this sequence, a trap handler can choose not to
1730 cascade (by returning <tt>true</tt> from the trap handler function).
1731 This will immediately cease the propagation of the event. This is how
1732 you would indicate that an event has been "handled".
1736 <section title="Re-routing events">
1738 At any point in the Event Context, you can write to the <tt>mouse</tt>
1739 property on any box. The value written should be an object with two
1740 properties, <tt>x</tt> and <tt>y</tt>. For example:
1743 _Press1 ++= function(p) {
1744 mouse = { x: 32, y: 77 };
1748 The coordinates specified are relative to the box whose <tt>mouse</tt>
1749 property is being written to. There is no need to supply the
1750 <tt>inside</tt> property; it is computed automatically. Writing to
1751 the <tt>mouse</tt> property causes Ibex to recompute the eventual
1752 target box, and also alter the values returned by <tt>mouse.x</tt>,
1753 <tt>mouse.y</tt>, and <tt>mouse.inside</tt> for any <i>descendants</i>
1754 of the current box. Writing to the <tt>mouse</tt> property also
1755 automatically prevents the event from returning to the box's parents
1756 -- it is equivalent to not cascading on the non-underscored event.
1757 This ensures that child boxes cannot trick their parent boxes into
1758 thinking that the mouse has moved.
1760 If you want the event to "skip over" the boxes between the trapee
1761 and the target, or if you want to re-route an event to a box which
1762 is not a descendant of the current box, simply write the value to
1763 the proper key on the target box.
1767 _KeyPressed = function(k) { ibex.log.info("first"); }
1768 KeyPressed = function(k) { ibex.log.info("sixth"); }
1769 $recipient.target = $target;
1770 <box id="recipient">
1771 _KeyPressed = function(k) {
1772 ibex.log.info("second");
1773 thisbox.target.KeyPressed = k;
1774 // inhibit cascade to keep the event from going to $excluded
1777 KeyPressed = function(k) { ibex.log.info("fifth"); }
1779 _KeyPressed = function(k) { ibex.log.info("this never happens"); }
1783 _KeyPressed = function(k) { ibex.log.info("third"); }
1784 KeyPressed = function(k) { ibex.log.info("fourth"); }
1791 <section title="Synthesizing Your Own Events">
1793 You can create "fake events" by simply writing to the <tt>mouse</tt>
1794 property and then writing a value to one of the underscored properties
1795 on a box. This will have exactly the same effect as if the use had
1796 actually pressed a key, clicked a button, or moved the mouse -- they
1797 are indistinguishable.
1801 <section title="Enter and Leave">
1803 Ibex will trigger the <tt>Enter</tt> and <tt>Leave</tt> properties as
1804 it walks down the tree, based on the position of the mouse (or the
1805 faked position if the <tt>mouse</tt> property has been written to).
1806 However, <tt>Enter</tt> and <tt>Leave</tt> are not events since they
1807 do not implicitly cascade up or down the tree.
1811 <section title="Detailed Description of Events">
1813 <property name="Press1 / Press2 / Press3">
1814 Indicates that the use has pressed a mouse button. On
1815 platforms with three mouse buttons, the <i>middle</i> button
1816 is button 3 -- this ensures that applications written to only
1817 use two buttons (1 and 2) will work intuitively on three button
1821 <property name="Release1 / Release2 / Release3">
1822 Indicates that the use has released a mouse button.
1825 <property name="Click1 / Click2 / Click3">
1826 Indicates that the user has pressed and released the
1827 mouse button without moving the mouse much (exactly how
1828 much is platform-dependent).
1831 <property name="DoubleClick1 / DoubleClick2 / DoubleClick3">
1832 Indicates that the user has clicked the
1833 mouse button twice within a short period of time (exactly how long is platform-dependent).
1836 <property name="Move">
1837 Indicates that the mouse has moved while within this box, or that
1838 the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
1841 <property name="KeyPressed KeyReleased">
1842 A string is written to this property when a key is pressed or
1843 released If the key was any other key, a multi-character
1844 string describing the key will be put. For simplicity, we use
1845 the VK_ constants in the <link
1846 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1847 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1848 key is pressed or released, the string put will be the portion
1849 of its VK_ constant after the underscore, all in lower case.
1850 If the shift key was depressed immediately before the event
1851 took place, then the string will be capitalized. Special
1852 keynames are also capitalized; shift+home is reported as
1853 "<tt>HOME</tt>". Symbols are capitalized as they appear on the
1854 keyboard; for example, on an American QWERTY keyboard, shift+2
1855 is reported as "<tt>@</tt>". If the alt, meta, or command key
1856 was depressed immediately before this key was pressed, then
1857 the string will be prefixed with the string "<tt>A-</tt>". If
1858 the control key was depressed while this key was pressed, then
1859 the string will be prefixed with the string "<tt>C-</tt>". If
1860 both alt and control are depressed, the string is prefixed
1861 with "<tt>C-A-</tt>". Ibex does not distinguish between a key
1862 press resulting from the user physically pushing down a key,
1863 and a 'key press' resulting from the keyboard's typematic
1864 repeat. In the rare case that an application needs to
1865 distinguish between these two events, it should watch for
1866 KeyReleased messages and maintain an internal key-state
1874 <!-- ----------------------------------------------------------------------- -->
1875 <section title="Networking">
1877 <section title="XML-RPC">
1879 XML-RPC objects can be created by calling <tt>ibex.net.rpc.xml(<i>XML-RPC
1880 URL</i>)</tt>, and then invoking methods on that object. For example,
1883 Press1 += function(v) {
1884 ibex.thread = function() {
1885 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").color.getTodaysColor("Friday");
1890 When the user clicks the first mouse button on this box, it will
1891 contact the server <tt>xmlrpc.ibex.org</tt>, route to the
1892 <tt>/RPC2/</tt> handler and invoke the <tt>getTodaysColor()</tt>
1893 method on the <tt>color</tt> object with a single string argument
1894 "<tt>Friday</tt>". The return value will be used to change the color
1895 of the box the user clicked on.
1897 Note that in this example we spawned a background thread to handle the
1898 request -- the <tt>Press1</tt> event is delivered in the foreground
1899 thread, and XML-RPC methods may only be invoked in background
1900 threads. This is to prevent the UI from "locking up" if the server
1901 takes a long time to reply.
1903 If the XML-RPC method faults, an object will be thrown with two
1904 properties: <tt>faultCode</tt> and <tt>faultString</tt>, as defined in
1905 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1906 Ibex encounters a network, transport, or session-layer error, it will
1907 throw a <tt>String</tt> object describing the error in a
1908 human-readable format. Scripts should not rely on the contents of
1909 this string having any special structure or significance.
1911 If an object with an associated non-empty stream is passed as an
1912 argument to an XML-RPC method, it will be sent as a <base64/>
1913 element. If a <base64/> element is found in the XML-RPC reply, it
1914 will be returned as an object with a stream drawn from that byte sequence.
1916 Each object returned by <tt>ibex.net.rpc.xml()</tt> represents a
1917 single HTTP connection. The connection will be held open until
1918 the object is garbage collected or the server closes the
1919 connection. If a second call is issued on the object before the
1920 first one returns (usually from a seperate thread), the two calls
1922 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1923 text="pipelined"/>. This can dramatically improve performance.
1925 Ibex supports HTTP Basic and Digest authentication. To use
1926 authentication, pass <tt>ibex.net.rpc.xml()</tt> a URL in the form
1927 <tt>http[s]://user:password@hostname/</tt>. Ibex will use Digest
1928 authentication if the server supports it; otherwise it will use
1929 Basic authentication. Please be aware that many XML-RPC server
1930 implementations contain a <link
1931 url="http://www.ibex.org/faq.html#auth" text="broken implementation of Basic authentication"/>.
1935 <section title="SOAP">
1937 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1939 <list type="ordered">
1941 <tt>ibex.net.rpc.soap()</tt> is used instead of
1942 <tt>ibex.net.rpc.xml()</tt>
1944 Instead of specifying just the URL of the service itself, you
1945 must specify the URL, the SOAPAction argument, and the
1948 The actual method invocation takes only one argument, which
1949 must be an object. This is necessary since SOAP arguments are
1950 specified by name, rather than ordering.
1954 SOAP faults are handled the same way as XML-RPC faults except that the
1955 capitalization of the <tt>faultstring</tt> and <tt>faultcode</tt>
1956 members is all lower-case, to match the SOAP spec. Here is a
1960 Press1 ++= function(v) {
1961 ibex.thread = function() {
1962 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP", // endpoint
1963 "GETTODAYSCOLOR", // SOAPAction header
1964 "http://ibex.org/namespace" // namespace for SOAP-ENV
1965 ).color.getTodaysColor( {
1972 As you can see, SOAP is much more verbose, yet does not offer
1973 substantially improved functionality. We recommend that XML-RPC be
1974 used whenever possible, and that SOAP be reserved for legacy
1977 The current Ibex SOAP stack does not support 'document style' or
1978 multi-ref (<tt>href</tt>) data structures.
1982 <section title="Security">
1984 Applications downloaded from the network (as opposed to those loaded
1985 from the filesystem) may only make certain kinds of connections to
1986 certain hosts. See Appendix A for a detailed description of the
1992 <!-- ----------------------------------------------------------------------- -->
1993 <section title="Error Handling">
1995 If the Ibex Core encounters an error while servicing a function call
1996 originating in JavaScript, the core will throw a string consisting of
1997 an error code followed by a colon, a space, and a descriptive message.
2001 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
2004 The code should be used to determine how the program should respond to
2005 an error. The codes are organized in a hierarchy, so the
2006 string.startsWith() method can be used to determine if an error lies
2007 within a particular subhierarchy. The descriptive message portion of
2008 the string may be shown to the user.
2010 <property name="ibex.assertion.failed">
2013 <property name="ibex.io">
2014 General I/O exceptions
2016 <property name="ibex.io.encoding">
2017 Error translating between character encodings.
2019 <property name="ibex.io.zip">
2020 Attempted to access a corrupt zip archive.
2022 <property name="ibex.io.eof">
2023 End of file encountered unexpectedly
2025 <property name="ibex.net.security.prohibitedHost">
2026 A piece of untrusted Ibex code attempted to contact a
2027 restricted host. See <ref appendix="Security Architecture and Considerations"/> for details.
2029 <property name="ibex.net.dns.temporaryFailure">
2030 An attempt to resolve a hostname failed but it is not known
2031 for certain that the hostname is invalid.
2033 <property name="ibex.net.dns.unknownHost">
2034 An attempt to resolve a hostname failed because the hostname
2037 <property name="ibex.net.socket.closed">
2038 A socket was closed unexpectedly.
2040 <property name="ibex.net.socket.connectionFailed">
2041 A connection could not be made to the remote host.
2043 <property name="ibex.net.url.malformed">
2044 Tried to parse a malformed URL.
2046 <property name="ibex.net.ssl">
2047 General SSL protocol errors.
2049 <property name="ibex.net.ssl.untrustedCertificate">
2050 The server's certificate was not signed by a CA trusted by Ibex.
2052 <property name="ibex.net.http.">
2053 Thrown when an HTTP error code is returned during an
2054 operation. The three characters <tt><i>xyz</i></tt> will be
2055 the three-digit HTTP status code.
2057 <property name="ibex.net.xmlrpc.null">
2058 The caller attempted to transmit the <tt>null</tt> value via XML-RPC.
2060 <property name="ibex.net.xmlrpc.circular">
2061 The caller attempted to transmit a circular data structure via XML-RPC.
2063 <property name="ibex.net.xmlrpc.specialObject">
2064 The caller attempted to transmit a "special" object via
2065 XML-RPC (for example, a Box or the Ibex object).
2067 <property name="ibex.null.put">
2068 A JavaScript attempted to put to a property on the <tt>null</tt> value
2070 <property name="ibex.null.get">
2071 A JavaScript attempted to get from a property on the <tt>null</tt> value
2073 <property name="ibex.null.call">
2074 A JavaScript attempted to call the <tt>null</tt> value
2077 If an exception is thrown inside a trap, the exception will propagate
2078 to the script that triggered the trap.
2080 If an uncaught exception is thrown while applying a template, or the
2081 requested template could not be found, an error will be logged and the
2082 box to which the template was being applied will be made invisible
2083 (<tt>visible = false</tt>). This ensures that half-applied widgets are
2084 never shown to the user.
2088 <!-- ----------------------------------------------------------------------- -->
2089 <appendix title="Security Architecture and Considerations">
2091 Due to the expense and hassle imposed by the commercial PKI code
2092 signing architecture, and the fact that it <link
2093 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2094 really provide any security anyways"/>, Ibex user interfaces are
2095 distributed as unsigned, untrusted code. As such, they are handled
2096 very carefully by the Ibex Core, and assumed to be potentially
2099 Ibex's security architecture is divided into defenses against four
2100 major classes of attacks:
2102 <section title="Malicious UI attempts to acquire or alter data on the client">
2104 Ibex user interfaces are run in an extremely restrictive sandbox. The
2105 environment does not provide primitives for accessing any data outside
2106 the Ibex core except via XML-RPC and SOAP calls. There are no
2107 facilities to allow Ibex user interfaces to access the client's
2108 operating system or to interact with other applications on the same
2109 host (unless they provide a public XML-RPC or SOAP interface).
2110 An Ibex script may only access a file on the user's hard disk if the
2111 user explicitly chooses that file from an "open file" or "save file"
2112 dialog. There is one exception to this rule: if all templates
2113 currently loaded in the Ibex core originated from the local
2114 filesystem, those templates can load additional .ibexs from the local
2117 The Ibex Core is written in Java, so it is not possible for
2118 scripts to perform buffer overflow attacks against the core
2121 Ibex applications may only read from the clipboard when the user
2122 middle-clicks (X11 paste), presses control-V (Windows paste), or
2123 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2124 "alt"). This ensures that Ibex applications are only granted access to
2125 data that other applications have placed on the clipboard when the user
2126 specifically indicates that that information should be made available
2127 to the Ibex application.
2131 <section title="Malicious UI attempts to use client to circumvent firewalls">
2133 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2134 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2135 regular TCP sockets.
2137 Ibex will not allow a script to connect to a non-public IP address
2138 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2139 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2140 1918"/>). There is one exception -- if all templates currently loaded
2141 in the core originated from the same IP address, those scripts may
2142 make calls to that IP address regardless of whether or not it is
2143 firewalled. If Ibex does not have access to a DNS resolver (because it
2144 is using a proxy which performs DNS lookups), Ibex will provide the
2145 proxy with the appropriate <link
2146 url="http://www.ibex.org/x-requestorigin.html"
2147 text="X-RequestOrigin"/> header that the proxy needs in order
2148 to maintain security.
2150 The only remaining possible attack is against a XML-RPC or SOAP
2151 service running on a firewalled host with a public address. Assigning
2152 such machines public IP addresses is a poor network security policy,
2153 and doing so squanders scarce public IPv4 addresses. As such, the onus
2154 is on the administrators of such machines to explicitly block access
2155 to clients reporting a <tt>User-Agent:</tt> header beginning with the
2156 three characters "<tt>Ibex</tt>".
2160 <section title="Malicious UI attempts to trick user into divulging secret information">
2162 All top-level windows created by Ibex are <i>scarred</i> -- a stripe
2163 and a lock is drawn across the corner of the window. There is no way
2164 for a user interface to remove this scar. Ibex user interfaces may not
2165 create windows smaller than the size of the scar.
2169 <section title="Malicious network attempts to snoop or man-in-the-middle transactions">
2171 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2172 for encryption. Ibex will attempt 128-bit encryption, but will
2173 negotiate down to 40-bit if the server does not support strong
2174 crypto. Ibex's SSL implementation is currently provided by <link
2175 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2176 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2179 All HTTPS connections must be authenticated by the server using a
2180 certificate whose name matches the domain name of the HTTPS URL. The
2181 certificate must be signed by a trusted root CA. Ibex trusts the same
2182 93 root CAs whose certificates are included as "trusted" in Microsoft
2183 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2184 against man-in-the-middle attacks; you should not trust this
2185 connection with any data you would not normally trust an SSL-enabled
2192 <!-- ----------------------------------------------------------------------- -->
2193 <appendix title="ECMAscript compliance">
2195 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2196 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2199 <section title="Omissions">
2201 The following ECMA features are not supported:
2203 <list type="unordered">
2205 The <tt>undefined</tt> value, <tt>===</tt>, and <tt>!==</tt>
2207 The <tt>new</tt> keyword (and ECMAScript object inheritance)
2210 <tt>getter</tt> and <tt>setter</tt>
2212 The ECMA <tt>this</tt> keyword.
2214 The <tt>String</tt>, <tt>Number</tt>, and <tt>Boolean</tt>
2215 classes. Note that <tt>string</tt>, <tt>number</tt>, and
2216 <tt>boolean</tt> values are supported, however.
2218 You may not <tt>throw</tt> the <tt>null</tt> value.
2222 Additionally, you must declare all root-scope variables (with
2223 <tt>var</tt>) before using them; failure to do so will result in an
2224 exception. Box properties are pre-defined in the scope that scripts
2231 <section title="Extensions">
2233 <list type="unordered">
2235 The token <tt>..</tt> is equivalent to <tt>[""]</tt>.
2241 Extended <tt>catch</tt> syntax. The following code:
2243 } catch(e propname "foo.bar.baz") {
2250 if (e.propname != null && e.propname >= "foo.bar.baz" && e.propname < "foo.bar.baz/") {
2255 Multiple extended-catch blocks can appear at the end of a single try
2256 block. However, at most one non-extended catch block may appear, and
2257 if it does appear, it must be the last one.
2259 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2260 "<tt>lt</tt>" is be interpreted as <tt><</tt>, the lexical
2261 token "<tt>gt</tt>" is be interpreted as <tt>></tt>, and the
2262 token "<tt>and</tt>" is interpreted as <tt>&&</tt>.
2263 Thus these tokens cannot be used as variable names.
2265 The identifier <tt>static</tt> is a reserved word in
2266 ECMAScript, but not in Ibex.
2268 Ibex defines an additional reserved word, "<tt>assert</tt>",
2269 which will evaluate the expression which follows it, throwing
2270 a <tt>ibex.assertion.failed</tt> exception if the expression
2271 evaluates to <tt>false</tt>.
2273 To ensure that Ibex files appear the same in all text editors, tab
2274 characters are not allowed in Ibex files.
2278 Some useful tutorials include:
2280 <list type="unordered">
2283 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2284 text=" JavaScript 1.2 Reference"/>. Although this document is
2285 out of date, it is arguably the best guide available for free
2286 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2287 r1) to 1.5 were minimal, and many of them were <link
2288 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2291 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2292 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2293 and Paula Ferguson. The latest edition of this book covers
2294 JavaScript 1.5 (ECMA-262 r3).
2297 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2298 text="ECMA-262"/> specification. This is an extremely
2304 <!-- ----------------------------------------------------------------------- -->
2305 <appendix title="Logging and Command Line Invocation">
2307 Very early in the loading process, Ibex begins logging messages about
2308 what it is doing. Where this output is logged to differs by platform;
2309 currently it goes to standard output when running inside a JVM, and to
2310 <tt>$TMPDIR\ibex-log.txt</tt> on Win32 (where <tt>$TMPDIR</tt> is the
2311 value returned by <tt>GetTempPath()</tt>). The logs contain a lot of
2312 valuable debugging information and performance hints; if you are
2313 having trouble developing an Ibex application, be sure to check the
2316 If Ibex encounters a serious problem before it starts logging
2317 information, or if it is unable to open the log file, it will abort
2318 immediately with a critical abort, which will be displayed on the
2319 console for POSIX-native cores and in a dialog box for JVM-based and
2322 You can invoke Ibex directly from the command line during
2323 development. When using a JVM, the invocation format is:
2326 java -jar <i>path-to-ibex-jar</i> [-sv] <i>source-location</i> [<i>initial-template</i>]
2329 Where <tt><i>path-to-ibex-jar</i></tt> is the path to <tt>ibex.jar</tt>,
2330 which can be downloaded <link url="http://www.ibex.org/dist/ibex.jar" text="here"/>.
2332 On Win32, the invocation format is:
2335 ibex.exe [-v] <i>source-location</i> [<i>initial-template</i>]
2338 The file <tt>ibex.exe</tt> is placed in Windows' ActiveX cache
2339 directory the first time Ibex is used on the machine. The ActiveX
2340 cache location depends on what version of Windows you are using;
2341 on newer versions of Windows it is <tt>C:\WINDOWS\DOWNLOADED
2342 PROGRAM FILES\</tt>. You can also extract <tt>ibex.exe</tt> from
2343 <tt>ibex.cab</tt>, which is available <link
2344 url="http://www.ibex.org/dist/ibex.cab" text="here"/>.
2346 The <tt><i>source-location</i></tt> parameter can be either the path
2347 to an .ibex archive, the http url of an .ibex archive, or the path to a
2348 directory comprising an unpacked .ibex archive.
2350 The <tt><i>initial-template</i></tt> parameter is the stream name of
2351 a template to be used as the initial template. If ommitted, it
2352 defaults to <tt>main</tt>.
2354 The <tt>-v</tt> option causes Ibex to enable verbose logging; this will
2355 cause it to log <i>lots</i> of information to the log file. This
2356 option will also substantially decrease Ibex's performance.
2360 <!-- ----------------------------------------------------------------------- -->
2362 <appendix title="Grammars">
2364 <i>Grammar support is experimental in this release
2365 and may not work properly. It may change in incompatible ways or
2366 disappear completely from future releases</i>
2368 Grammars are defined with a statement in the following form:
2373 A grammar is really just another function; once defined you can't tell
2374 it apart from an ordinary function. A grammar takes one argument,
2375 which can be a string or stream. The argument is parsed and the
2376 result of executing the code block 'c' is returned.
2378 The property 'a' is read; if the value is a grammar, a new production
2379 rule (ie a new alternative, as with '<tt>|</tt>') is added to that grammar
2380 (this is a destructive update). This allows you to add productions to
2381 pre-existing grammars (for example, adding a new type of expression to
2382 a programming language by extending the 'expr' grammar). If the old
2383 value is not a grammar, the value is discarded and a new grammar
2386 The value 'b' is a pattern, which may consist of seven simple
2389 <list type="unordered">
2392 grouping parens <tt>()</tt>
2394 combinators: <tt> | + * ?</tt>
2396 references to other grammars
2399 The value 'c' and the braces surrounding it are an *optional* code
2400 block, in which the following identifiers are bound:
2402 <list type="unordered">
2404 The identifier 'whole' is bound to the string matched by the
2405 entire expression. If the code block is omitted it behaves
2406 as if it were "<tt>{ return whole; }</tt>".
2408 For every reference to another grammar which was matched in the
2409 pattern, the *name used to reference that other grammar* will
2410 be bound to the value returned by its code block. Here's an
2411 example of this important distinction:
2414 var foo ::= 'a' | 'b';
2416 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2419 On the last line, the identifier 'bar' serves two purposes: it
2420 pulls in the definition of the pattern *and* acts as a binder
2421 within the scope of the braces.
2423 If a reference is matched multiple times (either because it
2424 appears multiple times in the pattern or because the * or +
2425 operator was applied to it) then its name will be bound to an
2426 array containing the matches.
2430 Here is the metacircular definition of the grammar facility:
2433 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2434 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2435 char ::= '\0x0000'..'\0xffff'
2436 literal ::= '\'' char+ '\''
2437 | '\'' char '\'' '..' '\'' char '\''
2438 pattern ::= identifier
2445 | pattern '|' pattern
2450 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2451 Ibex is a trademark of Adam Megacz