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>wildebeest sequence</i> (how the Ibex Core gets onto the
31 client's computer, and how it knows where to download the initial
32 <t>.ibex</t> from) is not described in this document, since it
33 will be different 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"/>.
39 <section title="Key Concepts">
41 <definition term="The Core">
42 Ibex itself; the native code (or Java bytecode) that runs on
43 the client. This term does not include the <i>wildebeest</i>
44 or the <i>UI</i></definition>
46 <definition term="The UI / The Application">
47 a set of files (mostly XML, JavaScript, and PNG images)
48 bundled up in a zip archive, ending with the "..ibex"
49 extension. Together, these files specify the appearance and
50 behavior of the application's user interface. Sometimes
51 we'll refer to this as the ".ibex" to be clear that we're
52 talking about the actual zip archive, rather than its visual
53 appearance when rendered on the screen.</definition>
55 <definition term="The Server">
56 We will use the term "the server" to refer to any other
57 computer which the client makes XML-RPC or SOAP calls
58 to. Note that it is possible for the client and server to be
59 the same machine.</definition>
61 <definition term="The Wildebeest">
62 this is a very small piece of code that is downloaded the
63 first time a client uses Ibex. It downloads the Ibex core,
64 verifies its signature, and launches it with the appropriate
65 parameters indicating where to find the initial UI. The
66 Wildebeest works differently on every platform, and is outside
67 the scope of this document.</definition>
69 <definition term="put/write">
70 In ECMAscript, when you change the value of a property on an
71 object, you are <i>putting</i> to that property, or
72 <i>writing</i> to it. For example, the ECMAscript expression
73 "<t>foo.bar = 5</t>" <i>puts</i> the value 5 to the bar
74 property on object foo.</definition>
76 <definition term="get/read">
77 In ECMAscript, when you access the value of a property on an
78 object, you are <i>getting</i> that property, or
79 <i>reading</i> from it. For example, the ECMAscript
80 expression "<t>return (3 + foo.bar)</t>" <i>gets</i> the
81 value of bar property on object foo and then adds 3 to it
82 before returning the result.</definition>
84 <definition term="JavaScript">
85 We will use the terms JavaScript and ECMAScript
86 interchangeably in this document. The Ibex interpreter is not
87 completely ECMA-compliant, however (see <link
88 appendix="C"/> for details). </definition>
92 <section title="Surfaces">
94 Each top-level window in an Ibex UI is called a
95 <i>surface</i>. There are two kinds of surfaces: <i>frames</i>,
96 which usually have a platform-specific titlebar and border, and
97 <i>windows</i>, which never have any additional platform-specific
100 Whenever we refer to the size or position of a surface, we are
101 referring to the size or position of the UI-accessible portion of the
102 surface; this does not include any platform-specific decorations. This
103 means that if you set the position of a frame to (0,0), the
104 platform-specific titlebar will actually be off the screen on most
105 platforms (it will be above and to the left of the top-left corner of
108 Surfaces are not actual JavaScript objects; you cannot obtain a
109 reference to a surface. However, each surface is uniquely identified
110 by its <i>root box</i>, described in the next section.
114 <section title="Boxes">
116 A <i>box</i> is the fundamental unit from which all Ibex user
117 interfaces are built. Boxes can contain other boxes (known as
118 <i>children</i>). Each Surface has a single box associated with it
119 called the <i>root box</i>; the root box and its children (and its
120 children's children, and so on) form the surface's <i>box tree</i>.
122 There are three ways to think of a box: as a rendered visualization on
123 the screen (the "Visual Representation"), as a JavaScript object (the
124 "Object Representation"), and as an XML tag (the "XML
129 All three representations are equally valid, and being able to figure
130 out what an action in one representation would mean in terms of the other
131 two representations is crucial to a solid understanding of Ibex.
133 <section title="The Object Representation">
135 Each box is a full-fledged ECMAscript object, and can store key-value
136 pairs as properties. Some of these keys have special meaning, which
137 will be explained later. Each box's numeric properties hold its
142 <section title="The Visual Representation">
144 Each box occupies a rectangular region on the surface. The visual
145 appearance of a surface is created by rendering each box in its tree.
146 Unless the <t>clip</t> attribute is <t>false</t>, each box will
147 clip its childrens' visual representations to its own, so that the
148 children appear "confined to" the parent. Children are rendered after
149 their parents so they appear "on top of" their parents (they obscure
152 Each box has two major visual components, each with subcomponents:
157 A <b>path</b>, which consists of zero or more lines and
158 curves. The path may be filled with a color, gradient, or
159 texture, and may be stroked with a line of a given thickness
160 and color. If the path is not specified, it defaults to the
161 perimiter of the box.
164 The path has an associated <b>strokecolor</b>, which is a
167 The path has an associated <b>strokewidth</b>, which is a
168 number specifying the width of the stroke.
170 The path also has a <b>fill</b>, which is either a color, gradient, or
173 A single line of <b>text</b>, which can be rendered in
174 different fonts, colors, and sizes.
177 The text has an associated <b>font</b>, which currently can be
178 any font supported by the <link url="http://www.freetype.org"
179 text="FreeType2"/> library.
181 The text also has an associated <b>fontsize</b>
183 The text is drawn in an associated <b>textcolor</b>
187 These eight components plus the size of a box fully specify its
188 appearance. Every single box you see in Ibex is drawn only on the
189 basis of these components and its size.
193 <section title="The XML Representation">
195 A template (discussed in the next section) is an XML file which acts
196 as a blueprint for constructing a tree of boxes. We call this
197 construction process <i>applying</i>, since unlike
198 <i>instantiation</i>, you always apply a template to a pre-existing
199 box, and you can apply multiple templates to the same box. Each XML
200 tag corresponds to a single box, or to another template which will be
201 applied to that box. For example, a <t>scrollbar</t> template, when
202 applied, will construct a tree of boxes which has the visual
203 appearance and behavior of a scrollbar.
205 Although it is useful to think of the XML tags as being boxes, keep in
206 mind that the XML representation is only a blueprint for constructing
207 a tree of JavaScript objects. Once the template has been
208 instantiated, the XML is effectively "thrown away", and JavaScript code is
209 free to alter the boxes.
214 <section title="Templates">
216 Each template is an XML document whose root element
217 is <t><ibex></t>. Any text content of the root element is
218 ignored, and may safely be used for comments. The root element may
219 have any of the following elements as children, each of which may
220 appear no more than once, and which must appear in this order:
222 Here is a sample Ibex file:
225 <ibex xmlns="ibex.widget" xmlns:lib="ibex.lib">
226 This is a sample Ibex file. Text up here is ignored.
227 Copyright (C) 2004 Mustapha Mond.
229 // code here will be executed only once
232 <box id="container"/>
235 /* This has to be commented out or else it
236 will be treated as a script */
243 <heading title="Applying an XML Tag to a Box"/>
245 The following description of the box application is extremely detailed
246 and precise; it is intended for UI designers who need to know the
247 exact order in which each event happens. FIXME:
248 easier description. While this whole process sounds very
249 complex, it actually works pretty intuitively. The description below
250 is given in great detail since most applications will wind up being
251 unintentionally dependent on subtle features of this process.
252 However, most of the time you can just pretend that the XML tags and
253 the boxes are the same thing.
255 To apply an XML tag <t><b>X</b></t> to a box <t><b>B</b></t>, perform the following
256 operations, in this order:
258 <list type="ordered">
260 Allocate a fresh scope <t><b>s</b></t> whose parent scope is
263 Process each child element or text segment of <t><b>X</b></t> in the
264 order they appear in the document: For each <i>text
265 segment</i> <t><b>t</b></t>:
268 Treat <t><b>t</b></t> a JavaScript script, and execute it
269 with <t><b>s</b></t> as the root scope.
272 For each child element <t><b>x</b></t> of
276 Create a new box <t><b>b</b></t>.
278 If the name of tag <t><b>x</b></t> is not "<t>box</t>" (in the
279 default XML namespace), prepend the tag's namespace
280 identifier uri (if any) to the name of the tag, and use
281 the result as a key to retrieve a property from the root
282 stream (defined later). Interpret the resulting stream as
283 a template and apply that template to <t><b>b</b></t>.
285 (recursively) apply <t><b>x</b></t> to <t><b>b</b></t>.
287 If <t><b>x</b></t> has an <t>id</t> attribute, declare a variable
288 in <t><b>s</b></t> whose name is the value of the <t>id</t>
289 attribute, prefixed with the <t>$</t> character, and whose
290 value is <t><b>b</b></t>
292 Copy any <t>$</t>-variables created during the application
293 of <t><b>x</b></t> into scope <t><b>s</b></t>.
295 Append <t><b>b</b></t> as the last child of <t><b>b</b></t>.
298 Apply any attributes on <t><b>x</b></t> to <t><b>b</b></t>, except for
299 <t>id</t>. Since XML specifies that the order of attributes
300 cannot be significant, Ibex processes attributes in
301 alphabetical order by attribute name. For example, if
302 <t><b>x</b></t> has the attribute <t>foo="bar</t>", then the
303 equivalent of the statement <t>B.foo="bar";</t> will be
304 performed, with the following exceptions:
307 If the value portion of the attribute is the string
308 "<t>true</t>", put the boolean <t>true</t>. If the
309 value is "<t>false</t>", put the boolean <t>false</t>.
311 If the value is a valid ECMAscript number, put it as a
312 number (instead of a string).
314 If the value begins with a dollar sign (<t>$</t>),
315 retrieve the value of the corresponding variable in
316 <t><b>s</b></t> and use that value instead.
318 If the value begins with a dot (<t>.</t>), prepend the
319 attributes' namespace identifier uri (if any) and
320 interpret the remainder as a property to be retrieved from
321 the root stream (defined later).
325 The last two steps are referred to as the <i>initialization</i> of the
326 node. There are two important aspects of this ordering to be aware of:
328 <list type="unordered">
330 A given box will be fully initialized before its parent is
331 given a reference to that box. This way, parents can be
332 certain that they will never wind up accessing a box when it
333 is in a partially-initialized state.
335 Attributes are applied <i>after</i> scripts are run so that
336 the attributes will trigger any <i>traps</i> (defined later)
337 placed by the script.
343 <section title="Life Cycle of an Ibex Application">
345 A user begins by specifying the URL of an Ibex application run.
346 Usually this is done by visiting a web page which uses the
347 <i>wildebeest</i> to install the core if it is not already on the user's
348 machine, but you can also supply the URL on the command line.
350 The Ibex Core downloads the .ibex for the application, loads it, applies
351 the <t>main.ibex</t> template and renders it onto the screen, running
352 any associated ECMAscript code.
354 The user interacts with the application by clicking and moving the
355 mouse, and by pressing keys on the keyboard. These actions trigger
356 fragments of JavaScript code which are designated to handle events.
357 This JavaScript code can then relay important information back to the
358 server using XML-RPC or SOAP, or it can modify the structure and
359 properties of the user interface to change its appearance, thereby
360 giving feedback to the user.
363 DIAGRAM: graphic here showing the circular feedback cycle.
366 The Ibex core quits when the last remaining surface has been destroyed.
370 <!-- ----------------------------------------------------------------------- -->
371 <section title="Layout and Rendering">
373 The size and position of every other box is determined
374 by its properties, its childrens' sizes, and its parent's size and position.
375 Box layout and rendering happens in four phases: <i>packing</i>,
376 <i>constraining</i>, <i>placing</i>, and <i>rendering</i>. The Core is careful to only
377 perform a phase on a box if the box has changed in a way that
378 invalidates the work done the last time that phase was performed.
380 packing and constraining phases are performed in a single traversal of
381 the tree (packing is preorder, constraining is postorder), and the
382 placing and rendering phases are performed in a second traversal of
383 the tree (first placing, then rendering, both preorder).
385 For brevity, the rest of this chapter deals only with width and
386 columns. Height and rows is treated identically and independently.
387 Also, it is important to note that the term <i>minimum width</i> is
388 not the same thing as the property <t>minwidth</t>, although they
391 <section title="The size of the root box">
393 When the user resizes a window, Ibex changes the root box's
394 <t>maxwidth</t> and <t>maxheight</t> to match the size chosen by
395 the user and then determines the root box's size using the same sizing
396 rules it uses for other boxes.
398 Ibex will always attempt to prevent the
399 user from making the surface smaller than the root box's
400 <t>minwidth</t> and <t>minheight</t>. If the <t>hshrink</t> or
401 <t>vshrink</t> flag is set, Ibex will try to prevent the user from
402 resizing the surface at all. However, not all platforms give Ibex
403 enough control to do this.
407 <section title="The alignment point">
409 When talking about positioning, we will often refer to the
410 <i>alignment point</i>.
412 <list type="unordered">
414 If the <t>align</t> property is "<t>center</t>", then the
415 alignment point is the center of the box.
417 If the <t>align</t> property is "<t>topleft</t>",
418 "<t>bottomleft</t>", "<t>topright</t>", or
419 "<t>bottomright</t>", then the alignment point is
420 corresponding corner of the box.
422 If the <t>align</t> property is "<t>top</t>",
423 "<t>bottom</t>", "<t>right</t>", or "<t>left</t>", then
424 the alignment point is middle of the corresponding edge of the
431 When positioning a child box, the alignment point is determined by the
432 <i>parent's</i> <t>align</t> property. When positioning a visual
433 element (a texture, path, or text string) within a box, the alignment
434 point is determined by the <i>box's own</i> <t>align</t> property.
436 A simple way to think about this is that whenever there are two boxes
437 involved in the decision, you should use the parent's alignment point.
441 <section title="Packing">
443 of <i>cells</i> is created within the parent. If the parent's
444 <t>cols</t> property is set to 0, the cell grid has an infinite
445 number of columns. Either <t>cols</t> or <t>rows</t> must be
448 If a child's <t>visible</t> property is <t>false</t>, it does
449 not occupy any cells (and is not rendered). Otherwise, each child
450 occupies a rectangular set of cells <t>child.colspan</t> cells
451 wide and <t>child.rowspan</t> cells high.
453 The Core iterates over the cells in the grid in the following
454 order: if <t>rows</t> is 0, the Core iterates across each column
455 before proceeding to the next row; otherwise rows come before
456 columns. At each cell, the Core attempts to place the <i>first
457 remaining unplaced child's</i> top-left corner in that cell (with
458 the child occupying some set of cells extending down and to the
459 right of that cell). If the parent has a fixed number of columns
460 and the child's <t>colspan</t> exceeds that limit, the child is
461 placed in column zero regardless, but only occupies the available
462 set of cells (it does not "hang off the end" of the box).
464 <image url="image/layout.png"/>
469 <box id="2" rowspan="2" />
470 <box id="3" colspan="2" />
472 <box id="5" colspan="2" />
476 Notes on the layout example:
478 <list type="ordered">
480 Box '3' doesn't fit in the gap after '2', nor in the gaps either
481 side of '2' on the next row, hence it is pushed onto the 3rd row.
483 Box '4' would fit in the gaps around '2', but must be placed
484 <i>after</i> it's preceeding box, '3'.
490 <section title="Constraining">
492 <list type="ordered">
494 Each box's minimum width is computed recursively as the
500 The width of the box's <t>text</t> (after applying the
501 box's <t>transform</t>).
503 The width of the box's path (after applying the box's
504 <t>transform</t>) <i>if the box is <t>packed</t></i>.
506 The width of the bounding box enclosing the box's cells.
509 The minimum width of each cell is computed as the minimum
510 width of the box occupying it divided by the box's
513 If a box's <t>hshrink</t> property is set to
514 <t>true</t>, the box's maximum width is the same as its
515 minimum width; otherwise it is the box's
518 The maximum width of each cell is the <t>maxwidth</t> of
519 the box occupying it divided by the box's
526 <section title="Placing">
528 <list type="ordered">
530 Each column's <i>actual width</i> is set to the maximum
531 <i>minimum width</i> of all the cells in that column.
532 <b>NOTE:</b> although a column or row can be sized smaller
533 than its "minimum width" or larger than its "maximum width", a
534 box will <i>never</i> be smaller than its <t>minwidth</t> or
535 larger than its <t>maxwidth</t>.
537 Each column's maximum width is the largest maximum width of
538 the cells in that column, but no smaller than the column's
541 The <i>slack</i> is the difference between the parent's width
542 and the sum of its columns' actual width. The slack is
543 divided equally among the columns. Any column which has
544 exceeded its maximum width is set to its maximum width, and
545 the difference is returned to the slack. This process is
546 repeated until the slack is zero or all columns are at their
549 Next, the rows and columns are positioned within the parent
550 box. The rows and columns are transformed according to the
551 parent's <t>transform</t> property, and the bounding box of
552 the resulting cells are placed such that the cells' alignment
553 point coincides with the parent's alignment point (both
554 alignment points are determined by the parent's <t>align</t>
555 property). FIXME: diagram
557 <b>Packed boxes:</b> Each packed box's actual position
558 and size is then set to the aggregation of the actual sizes of
559 the cells it spans. If this size exceeds the box's maximum
560 width, the box is sized to its maximum width and centered
561 horizontally within the space occupied by its cells.
563 <b>Non-packed boxes</b>: each non-packed box is transformed
564 according to the parent's <t>transform</t> property and then
565 positioned so that its alignment point is <t>(child.x,
566 child.y)</t> pixels from the parent's alignment point (both
567 alignment points are determined by the parent's <t>align</t>
574 <section title="Rendering">
576 Boxes are rendered in a depth-first, pre-order traversal. Note that
577 this may cause a non-packed box to overlap its siblings.
579 <list type="ordered">
581 If the box's <t>transform</t> property is non-null, the
582 coordinate space is transformed accordingly for the rest of
583 this phase and for the rendering of all children.
585 If the box is packed and has a non-<t>null</t> path, the
586 path is translated such that the alignment point of the path's
587 bounding box coincides with the box's alignment point (both
588 alignment points are determined by the box's <t>align</t>
591 If a box has a path, that path is filled with the color,
592 gradient, or image specified by the <t>fill</t> property and
593 stroked with the color and width specified by the
594 <t>strokecolor</t> and <t>strokewidth</t> properties.
596 If the box has a non-null <t>text</t> attribute,
597 the text is rendered in <t>font</t> with size
598 <t>fontsize</t> and color <t>textcolor</t>. The text is
599 then translated such that the alignment point of the text's
600 bounding box coincides with the box's alignment point (both
601 alignment points are determined by the box's <t>align</t>
604 The box's children are rendered (pre-prder traversal).
612 <!-- ----------------------------------------------------------------------- -->
613 <section title="Box Properties">
615 <section title="Rendering Properties">
617 Every box has several special properties which control how it is
618 drawn. In general, if you put an
619 invalid value to a special property, no action will be taken -- the
622 <property name="strokecolor" type="string" default="clear">
623 If the value is a 5-character hex string (<t>#RGB</t>),
624 7-character hex string (<t>#RRGGBB</t>), 9-character hex
625 string (<t>#AARRGGBB</t>), the box's stroke color will be set
627 If the value is one of the <link url="http://www.color.org/ICC-1A_1999-04.PDF" text="ICC"/> colors
628 (the same set of color names supported by SVG), the stroke
629 color be set to that color.
630 If the value is <t>null</t>, the stroke color will be set to
631 clear (<t>#00000000</t>).
634 <property name="strokewidth" type="int" default="1">
635 The width (in pixels) to stroke the path with.
638 <property name="fill">
639 This property can be set to any of the values specified for
641 Alternatively, if the value written is an object, its stream
642 will be read and interpreted as a PNG, GIF, or JPEG image,
643 which will become the texture for this box, and the box's
644 <t>minwidth</t> and <t>minheight</t> properties will be
645 automatically set to the dimensions of the image.
648 <property name="path" type="string" default='""'>
649 The box's path. The grammar and feature set supported are
650 identical to that specified in <link
651 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
655 <property name="text" type="string" default='""'>
656 The box's text; writing <t>null</t> to this property sets it
660 <property name="font" type="stream" default=".ibex.font.sansserif">
661 When an object is written to this property, its stream is read
662 using the <link url="http://www.freetype.org" text="freetype2
663 library"/>, and the resulting font is used to render the
667 <property name="fontsize" type="number" default="10">
668 The size (in points) to render the text.
671 <property name="textcolor" type="number" default="black">
672 The color in which to render the font; accepts the same values as <t>strokecolor</t>.
677 <section title="Layout Properties">
679 <property name="shrink" type="boolean" default="false">
680 If set to <t>true</t>, this box will shrink
681 (horizontally/vertically/both) to the smallest size allowed by
682 its children and the bounding box of its path.
685 <property name="x" type="integer" default="varies">
686 If the box is a root box, this is the (x/y)-coordinate of the
687 surface; otherwise it is the distance between the parent's
688 alignment point and this box's alignment point.
691 <property name="globalx" type="integer" default="varies">
692 The distance between this box's (left/top) edge and the root
693 box's (left/top) edge. A put to this property has the same
694 effect as a put to the (<t>x</t>/<t>y</t>) property,
695 except that it is relative to the root box rather than to this
696 box's parent. FIXME is this fakeable? How is
700 <property name="minwidth" type="integer" default="0">
701 The desired minimum width and height.
704 <property name="maxwidth" type="integer" default="ibex.maxint">
705 The desired maximum width and height.
708 <property name="width" type="integer" default="varies">
709 When read, this is the (width/height) of this box. Writing to
710 this property is equivalent to writing to <i>both</i> the
711 minimum and maximum (width/height).
714 <property name="cols" type="integer" default="0">
715 The number of (columns/rows) in which to lay out the children of this
716 box. If set to zero, the number of (columns/rows) is unconstrained.
717 Either <t>rows</t> or <t>cols</t> must be zero. If
718 <t>0</t> is written to <t>cols</t> when <t>rows</t> is
719 <t>0</t>, the write is ignored. If a nonzero value is
720 written to <t>cols</t> when <t>rows</t> is nonzero,
721 <t>rows</t> is set to <t>0</t>, and vice versa.
724 <property name="colspan" type="integer" default="1">
725 The number of (columns/rows) that this box spans within its parent.
728 <property name="align" type="string" default="center">
729 Determines the box's alignment point for positioning its text,
730 texture, path, and children.
733 <property name="visible" type="boolean" default="true">
734 If set to false, this box will be rendered as if its width and
735 height were zero. If this is a root box, the associated surface
737 When reading from this property, the value
738 <t>false</t> will be returned if this box <i>or any of its
739 ancestors</i> is not visible. Thus it is possible to write
740 <t>true</t> to a box's <t>visible</t> property and then
741 read back <t>false</t>.
744 <property name="packed" type="boolean" default="true">
745 The layout strategy for this box.
750 <section title="Child Control Properties">
752 During a box initialization, script-private references to a box's
753 descendants with <t>id</t> attributes are placed on the box. These
754 references allow scripts on that box to easily refer to descendant
755 nodes created by the template in which the script appears. For
756 example, these two blocks of code have exactly the same effect:
760 <box id="foo"/> <box/>
761 $foo.color = "red"; var $foo = this[0];
766 The following special properties control how a box's children are laid
767 out. If a box has a non-null redirect target, reads and writes to these
768 properties will be forwarded to the redirect target.
770 The <t>redirect</t> attribute is very useful for hiding the
771 internal structure of a widget, and for allowing widgets to act as
772 "smart" containers for other widgets. For example, a menu widget might
773 have an invisible child as its redirect target; this way, when boxes
774 representing items on the menu are added as children of the menu
775 widget, they do not appear until the menu is pulled down.
777 <property name="numeric properties" type="int" default="">
778 The <i>n</i>th child of box <t>b</t> can be accessed by reading from
779 <t>b[n]</t>. The <i>n</i>th child can be removed by writing
780 <t>null</t> to <t>b[n]</t> (the child will become parentless). A
781 new child can be inserted <i>before</i> the <i>n</i>th child by
782 writing it to <t>b[n]</t>; if the value written is already a child of
783 <t>b</t>, it will be removed from <t>b</t> first. It is important
784 to note that this behavior is different from ECMAscript arrays --
785 writing a non-<t>null</t> value to <t>b[n]</t> does not eliminate
786 the <i>n</i>th child; it merely shifts it over one position.
787 <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
788 properties with the JavaScript <t>for..in</t> construct will
789 enumerate <i>only</i> the box's children and not any other properties.
792 <property name="clip" type="boolean" default="true">
793 If <t>true</t>, the visual representation of this box's
794 children will be clipped to the boundaries of this box.
795 <b>Note:</b> setting this property to <t>false</t> imposes a
796 substantial performance penalty.
799 <property name="numchildren" type="integer" default="0">
800 The number of children this box has.
803 <property name="redirect" type="box" default="thisbox">
804 Writing to this property sets the box's redirect
805 target. This property cannot be read from, and can only be
809 <property name="surface" type="" default="null">
810 If this box has a parent, this property returns
811 <t><i>parent</i>.surface</t>; otherwise it returns null.
812 This property is a simple building block that the widget
813 library uses to implement more complex functionality such as
814 focus control and popups.
819 <section title="Other Box Properties">
821 <property name="cursor" type="string" default="null">
822 The shape that the cursor should take when inside this
823 box. Valid values are: "<t>default </t> " , "<t>wait</t>",
824 "<t>crosshair</t>", "<t>text</t>", "<t>hand</t>", and
825 "<t>move</t>", as well as resizing cursors"<t>east</t>",
826 "<t>west</t>", "<t>north</t>", "<t>south</t>",
827 "<t>northwest</t>", "<t>northeast</t>",
828 "<t>southwest</t>", and "<t>southeast</t>". Note that on
829 some platforms, resize cursors for opposite directions (such
830 as <t>northwest</t> and <t>southeast</t> are the
832 If a box's cursor is <t>null</t>, its parent's cursor will
833 be used. If the root box's cursor is null, the
834 "<t>default</t>" cursor will be used.
837 <property name="mouse.x" type="integer" default="varies">
838 The (horizontal/vertical) distance between the mouse cursor and this
839 box's (left/top) edge. Puts to this property are ignored. This
840 value will not be updated if the mouse is outside the root
841 box of the surface and no button was pressed when it left.
844 <property name="mouse.inside" type="boolean" default="false">
845 True if the mouse is inside the rendered region of this box or
846 any of its children. This value will be false if the mouse is
847 inside a portion of this box which is covered up by one of
848 this box's siblings, or one of its ancestors' descendants. Puts
849 to this value are ignored.
852 <property name="static" type="object" default="N/A">
853 Reading from this property will return the parent scope used
854 to execute the <t><static/></t> block of the template
855 in which the currently-executing code resides.
858 <property name="thisbox" type="box" default=" ">
859 Returns a reference to the box itself.
860 If <t>null</t> is written to this property, and this box is
861 the root box of a surface, the box will be detached and the
862 surface destroyed. If this box has a parent, it will be
863 detached from its parent.
866 <property name="indexof()" type="function" default=" ">
867 This property is actually a function; invoking
868 <t>parent.indexof(child)</t> will return the numerical index
869 of <t>child</t> in <t>parent</t> if <t>child</t> is a
870 child of <t>parent</t> (or <t>parent</t>'s redirect
871 target), and <t>-1</t> otherwise. Writing to this property
875 <property name="childadded" type=" " default=" ">
877 These properties are meant to be trapped on FIXME defined later?. Placing a trap on
878 <t>childadded/childremoved</t> lets a box receive
879 notification when a child is added/removed. In either
880 situation, the child will be passed as an argument to the trap
881 function <i>after</i> the addition or removal has been
884 Note that if the parent's redirect target is set to another
885 box, these traps will only be invoked when children are
886 manipulated by reading and writing to the parent. Reads and
887 writes directly to the redirect target will <i>not</i> trigger
890 Note also that these traps are still triggered if a box's
891 <t>redirect</t> target is <i>null</i>. This is useful for
892 boxes that need to accept children and then relocate them
898 <section title="Notification Properties">
900 The following properties are used to notify a box of changes specific
901 to that particular box.
903 <property name="Enter">
904 The value <t>true</t> is written to this property when the mouse enters the box.
907 <property name="Leave">
908 The value <t>true</t> is written to this property when the mouse leaves the box.
911 <property name="SizeChange">
912 The value <t>true</t> is put to this property after the size
918 <section title="Root Box Properties">
920 The following special properties are only meaningful on the root box
923 <property name="Focused">
924 The value <t>true</t> is put to this property on the root box
925 when the surface gains the input focus, and <t>false</t> when
926 the surface loses the input focus. Reading from this value will
927 return <t>true</t> if the surface is focused and <t>false</t>
928 if it is not. Putting <t>true</t> to this property will
929 <i>not</i> cause the surface to "steal" the input focus from other
933 <property name="Maximized">
934 The value <t>true</t> is put to this property on the root box
935 when the surface is maximized, and <t>false</t> when the surface
936 is un-maximized. Reading from this value will return <t>true</t>
937 if the surface is maximized and <t>false</t> if it is
938 not. Putting <t>true</t> to this property will maximize the
939 window, and putting <t>false</t> to this property will
940 unmaximize the window.
941 Note that not all platforms support maximization.
944 <property name="Minimized">
945 The value <t>true</t> is put to this property on the root box
946 when the surface is minimized, and <t>false</t> when the surface
947 is unminimized. Reading from this value will return <t>true</t>
948 if the surface is minimized and <t>false</t> if it is
949 not. Putting <t>true</t> to this property will minimize the
950 window, and putting <t>false</t> will unminimize it.
953 <property name="Close">
954 When the user attempts to close a surface, the value
955 <t>true</t> will be put to this property. Scripts may trap
956 this property FIXME defined later? to
957 prevent the window from closing. Putting the value
958 <t>true</t> to this property on a root box has the same
959 effect as putting <t>null</t> to the <t>thisbox</t>
963 <property name="icon">
964 The surface's icon. This is usually displayed on the titlebar of a
965 window. The value should be the stream name of a PNG image. Note
966 that not all platforms support this property.
969 <property name="titlebar">
970 The surface's titlebar text. Note that not all platforms support
971 this property. Only ASCII characters 0x20-0x7F are permitted.
978 <!-- ----------------------------------------------------------------------- -->
979 <section title="Streams">
981 <section title="Every object has a stream...">
983 Every object has a <i>stream</i> associated with it. A stream is a
984 sequence of bytes that can be read or written to.
986 By default an object has an empty stream (zero bytes). However, some objects
987 (returned from special methods on the <t>ibex</t> object) have
988 streams yielding data read from an url, file, or a component of a zip
989 archive. In a future release, the stream associated with a box will
990 be an .ibex template which, when applied, will fully reconstitute the
995 <section title="...but streams are not objects">
997 Despite the ubiquity of streams, you cannot actually reference a
998 stream, since it is not an object. Instead, you simply reference the
999 object it belongs to. If you are familiar with Java, this is similar
1000 to how every Java object has a monitor associated with it, but you
1001 cannot directly manipulate the monitor (you can't pass around a
1002 reference to just the monitor).
1004 In the rest of the section we will sometimes refer to "getting
1005 properties from a stream" or "passing a stream to a function"; this is
1006 just shorthand for saying to perform those actions on the object the
1011 <section title="Creating Streams from URLs">
1013 You can create a stream from a URL by calling
1016 var r = ibex.stream.url("http://...");
1019 This will return an object whose stream draws data from the specified
1020 URL. Streams are loaded lazily whenever possible.
1024 <section title="Getting Substreams">
1026 Most stream objects let you access
1027 substreams using the usual JavaScript operators <t>[]</t> and
1028 <t>.</t>, as well as the <t>for..in</t> syntax.
1031 // r1 and r2 are equivalent but not equal (!=)
1032 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1033 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1038 <section title="The Root Stream">
1040 The empty-string property on the <t>ibex</t> object is called the
1041 <i>root stream</i>. You can access this object as <t>ibex..</t> or
1042 <t>ibex[""]</t>. Additionally, any expression which starts with a
1043 dot is treated as property to be retrieved from the root stream. The
1044 following three expressions are equivalent:
1054 <section title="Static Blocks">
1056 You can access variables within the static block of a template by
1057 appending a double period (<t>..</t>) and the variable name to the
1058 stream used to load that template:
1061 <!-- org/ibex/themes/monopoly/scrollbar.ibex -->
1065 ibex.log.print(org.ibex.themes.monopoly.scrollbar..foo); // prints "12"
1070 <section title="Formatting Streams">
1072 If you attempt to send a stream as part of an XML-RPC call, the
1073 stream will be read in its entirity, Base64-encoded, and transmitted
1074 as a <t><base64/></t> element.
1076 Ibex supports two special URL protocols. The first is <t>data:</t>,
1077 which inteprets the rest of the URL as a Base64 encoded sequence of
1078 bytes to use as a source. The other is <t>utf8:</t> which
1079 interpretets the rest of the string as a Unicode character sequence to
1080 be UTF-8 encoded as a string of bytes to use as a source.
1083 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1084 var r6 = ibex.stream.url("utf8:this is a test");
1087 You can read a UTF-8 encoded string from a stream like this:
1090 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:this is a test"));
1092 You can also parse XML from a stream using SAX like this:
1095 ibex.stream.xml.sax(
1096 ibex.stream.url("http://foo.com/foo.xml"),
1097 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1098 endElement : function(tagname) { ... },
1099 content : function(contentString) { ... }
1100 whitespace : function(whitespaceString) { ... }
1108 <!-- ----------------------------------------------------------------------- -->
1109 <section title="The Ibex object">
1111 The <t>ibex</t> object is present in the top-level scope of every
1112 script. It has the following properties:
1114 <heading title="General"/>
1116 <property name="ibex.box">
1117 reading from this property returns a new box
1119 <property name="ibex.clone(o)">
1120 creates a clone of object
1122 <property name="ibex.bless(s)">
1123 returns a blessed clone of stream
1126 <heading title="ECMA Library Objects"/>
1128 <property name="ibex.date">
1129 reading from this property returns a new date
1131 <property name="ibex.math">
1132 this object contains the ECMA math functions
1134 <property name="ibex.regexp(s)">
1135 return a regexp object corresponding to string <i>s</i>
1137 <property name="ibex.string">
1138 this object contains the ECMA string manipulation functions
1141 <heading title="Logging"/>
1143 <property name="ibex.log.debug(m, o)">
1144 log the debug message <i>m</i>, optionally dumping object
1148 <property name="ibex.log.info(m, o)">
1149 log the informational message <i>m</i>, optionally dumping
1153 <property name="ibex.log.warn(m, o)">
1154 log the warning message <i>m</i>, optionally dumping object
1158 <property name="ibex.log.error(m, o)">
1159 log the error message <i>m</i>, optionally dumping object
1163 <heading title="User Interface"/>
1165 <property name="ibex.ui.browser(u)">
1166 opens a new browser window with URL <i>u</i>
1169 <property name="ibex.ui.key.control">
1170 true if the control key is depressed
1173 <property name="ibex.ui.key.shift">
1174 true if the shift key is depressed
1177 <property name="ibex.ui.key.alt">
1178 true if the alt key is depressed
1181 <property name="ibex.ui.key.name.alt">
1182 the name of the "alt" key (usually either "alt", "meta", or
1186 <property name="ibex.ui.clipboard">
1187 the contents of the clipboard; can be read and written to
1190 <property name="ibex.ui.maxdim">
1191 the maximum dimension of any UI element; usually
1192 2<sup>31</sup>, but may be smaller
1195 <property name="ibex.ui.screen.width">
1196 the width of the screen, in pixels
1199 <property name="ibex.ui.screen.height">
1200 the height of the screen, in pixels
1203 <property name="ibex.ui.mouse.button">
1204 either 0, 1, 2, or 3, indicating the mouse button currently
1208 <property name="ibex.ui.frame">
1209 when a box is written to this property, it becomes the root
1213 <property name="ibex.ui.window">
1214 when a box is written to this property, it becomes the root
1218 <property name="ibex.ui.font.serif">
1219 an object whose stream is a a builtin serif font
1222 <property name="ibex.ui.font.sansserif">
1223 an object whose stream is a builtin sans-serif font
1226 <property name="ibex.ui.font.monospace">
1227 an object whose stream is a a builtin fixed-width font
1230 <heading title="Networking"/>
1232 <property name="ibex.net.http">
1236 <property name="ibex.net.rpc.xml(u)">
1237 return an XML-RPC call object with endpoint URL <i>u</i>
1240 <property name="ibex.net.rpc.soap(u,">
1241 return a SOAP call object with endpoint URL <i>u</i>,
1242 SoapAction <i>a</i>, and XML Namespace <i>n</i>
1245 <heading title="Threads"/>
1247 <property name="ibex.thread">
1248 when a function is written to this property, a new thread is
1252 <property name="ibex.thread.yield()">
1253 yield the current thread
1256 <property name="ibex.thread.sleep(n)">
1257 sleep for <i>n</i> milliseconds
1260 <heading title="Streams"/>
1262 <property name="ibex.stream.url(u)">
1263 returns a new object whose stream is drawn from URL <i>u</i>
1266 <property name="ibex.stream.unzip(s)">
1267 unpacks a zip archive from <i>s</i>'s stream
1270 <property name="ibex.stream.uncab(s)">
1271 unpacks a cab archive from <i>s</i>'s stream
1274 <property name="ibex.stream.cache(s,k)">
1275 valign=top>wraps a disk-backed read cache keyed on <i>k</i>
1276 around <i>s</i>'s stream
1279 <property name="ibex.stream.watch(s,f)">
1280 returns an object whose stream is drawn from <i>s</i>'s
1281 stream, but invokes <i>f(n,d)</i> as it is read from.
1284 <property name="ibex.stream.parse.xml(s, h)">
1285 Use SAX to parse the XML document on stream <i>s</i> with
1289 <property name="ibex.stream.parse.html(s, h)">
1290 Same as <t>parse.xml()</t>, but tries to fix broken HTML.
1293 <property name="ibex.stream.parse.utf8(s)">
1294 treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string
1297 <property name="ibex.stream.homedir">
1298 <t>ibex.stream.tempdir</t>
1301 <heading title="Cryptography"/>
1303 <property name="ibex.crypto.rsa(k,s)">
1304 <i>not implemented yet:</i> return a
1305 stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
1308 <property name="ibex.crypto.rc4(k,s)">
1309 <i>not implemented yet:</i> return a
1310 stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
1313 <property name="ibex.crypto.md5(s)">
1314 <i>not implemented yet:</i> immediately
1315 MD5-hash stream <i>s</i>
1318 <property name="ibex.crypto.sha1(s)">
1319 <i>not implemented yet:</i> immediately
1320 SHA1-hash stream <i>s</i>
1324 <!-- ----------------------------------------------------------------------- -->
1325 <section title="Traps">
1327 You can add a trap to a property by applying the <t>++=</t> operator
1328 to a function with one argument. The trap will be invoked whenever
1329 that property is written to.
1333 foo ++= function(z) {
1334 ibex.log.info("foo is " + z);
1339 If another script were to set the property "<t>foo</t>"
1340 on the box above to the value <t>5</t>, the function above would be
1341 invoked with the argument <t>5</t>. The function would then log
1342 the string "<t>foo is 5</t>".
1344 Within a trap, the expression <t>trapee</t> can be used to
1345 get a reference to the box on which the trap was placed.
1347 The expression <t>trapname</t> returns the name of the
1348 trap executing the current function. This is useful when a function
1349 is applied to multiple traps. For example:
1353 func ++= function(z) {
1354 ibex.log.info("called trap " + trapname);
1361 <section title="Removing Traps">
1363 You can remove a trap by using the <t>--=</t> operator with the same
1364 function you added as a trap:
1368 var myfunc = function(z) { /* ... */ }
1379 <heading title="Multiple Traps on the Same Property"/>
1381 When the property is <i>written</i> to, each of the trap functions placed
1382 on it will be invoked in the opposite order that they were placed on
1383 the box -- the most recently placed trap will execute first. This
1384 last-to-first execution of traps is called <i>cascading</i>. After the
1385 last trap is invoked, the value is stored on the box (remember, boxes
1386 are objects, so they can hold properties just like all other
1387 ECMAscript objects).
1389 <section title="Manual Cascades">
1391 There are two additional tricks you can use when placing traps. The
1392 first is a <i>manual cascade</i>. If you want to cascade to lower
1393 traps in the middle of a function, or you want to cascade with a
1394 different value than the value passed to you (in effect "lying" to
1395 lower traps), you can use <t>cascade</t>. For example:
1399 color ++= function(c) {
1400 ibex.log.info("refusing to change colors!");
1406 This effectively creates a box whose color cannot be changed, and
1407 which complains loudly if you try to do so.
1409 Do <i>not</i> try to do something like this:
1413 color ++= function(z) {
1414 color = "black"; // INFINITE LOOP! BAD!!!
1418 To prevent automatic cascading, return <t>true</t> from your function:
1422 color ++= function(z) {
1423 return true; // the box's color will not change
1430 <section title="Read Traps">
1432 The other trick is a <i>read-trap</i>. Read traps are just like normal
1433 traps, except that you use a function that takes zero arguments instead of one. Read traps
1434 also do not automatically cascade.
1438 doublewidth <t>++=</t> function() { return 2 * width; }
1442 If another script attempts to read from the <t>doublewidth</t>
1443 property on this box, the value it gets will be twice the actual width
1444 of the box. Note that
1445 the actual <t>doublewidth</t> property on the box never gets written
1446 to, since the trap does not cascade.
1448 You can manually cascade on read traps as well:
1452 text <t>++=</t> function() { return "my text is " + cascade; }
1456 Read traps are only rarely needed -- most of the time a write trap
1461 <heading title="Prohibited Traps"/>
1463 To prevent confusing and hard-to-debug behaviors, scripts may not
1464 place traps on any of the properties described in the sections
1465 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1466 section="Child-Control Properties"/>, or <link section="Other Box
1467 Properties"/> except for <t>childadded</t>,
1468 <t>childremoved</t> and <t>surface</t>. FIXME: remove?
1470 <heading title="Exceptions and Traps "/>
1472 If an uncaught exception is thrown from a trap, Ibex will log the
1473 exception, but will <i>not</i> propagate it to the code which
1474 triggered the trap. If the trap was a read trap, the value
1475 <t>null</t> will be returned.
1476 FIXME: is this right?
1478 <heading title="Architectural Significance of Traps"/>
1480 Traps are the backbone of Ibex. Since almost all UI programming is
1481 event/demand driven, traps eliminate the need for separate
1482 member/getter/setter declarations, often cutting the amount of typing
1483 you have to do to a third of what it would normally be.
1485 <section title="Cloning">
1487 <i>Cloning</i> is a companion technique for traps; together they can
1488 be used to simulate any sort of environment you might need. When you
1489 call <t>ibex.clone(o)</t>, Ibex returns a new object (called the
1490 <i>clone</i>) which compares with equality (<t>==</t>) to the
1491 original object. Furthermore, both objects are "equal" as keys in
1496 var theclone = ibex.clone(o);
1498 ibex.log.info(hash[theclone]); // prints "5"
1501 Any writes to properties on the clone will actually write to
1502 properties on the original object, and reads from properties on the
1503 clone will read properties on the original object. In fact, the only
1504 thing that can be used to distinguish the original from the clone is
1505 traps -- a trap placed on the clone is <i>not</i> placed on the
1506 original object as well.
1511 <!-- ----------------------------------------------------------------------- -->
1512 <section title="Threads">
1514 <section title="Contexts">
1516 From the perspective of an application writer, Ibex is strictly
1517 single-threaded. Ibex is always in exactly one of the following three
1520 <list type="unordered">
1522 <b>Rendering Context</b> -- (redrawing the screen)
1524 <b>Event Context</b> (executing javascript traps triggered by an event)
1526 <b>Thread Context</b> (executing a background thread spawned with <t>ibex.thread</t>)
1530 There are two important restrictions on what can be done in particular contexts:
1532 <list type="unordered">
1534 The <t>box.mouse</t> property and its subproperties
1535 (<t>x</t>, <t>y</t>, and <t>inside</t>) can only be read
1536 from within the Event Context, or in a thread context
1537 <i>after</i> a the <t>box.mouse</t> property on this box or
1538 an ancestor box has been written to.
1540 Blocking operations (anything that accesses the network or
1541 disk) can only be performed in the Thread Context.
1547 <section title="Background Threads">
1549 Ibex offers easy access to threads. Spawning a background thread is as
1550 simple as writing a function to the <t>ibex.thread</t> property:
1553 ibex.thread = function() {
1554 ibex.log.info("this is happening in a background thread!");
1558 The argument set passed to the function is currently undefined and is
1559 reserved for use in future versions of Ibex. Scripts should not
1560 depend on the number or content of these arguments.
1562 Ibex is <i>cooperatively multitasked</i>, so threads must not process
1563 for too long. This was a deliberate choice; cooperatively
1564 multitasked environments do not require complex locking primitives
1565 like mutexes and semaphores which are difficult for novices to
1566 understand. The disadvantage of cooperative multitasking is that one
1567 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1568 first, all blocking I/O operations <i>automatically</i> yield the CPU,
1569 so the overall user interface never becomes unresponsive because it is
1570 waiting for a disk or network transfer. Second, since Ibex is strictly
1571 a user interface platform, Ibex scripts are unlikely to perform highly
1572 compute-intensive operations that keep the CPU busy for more than a
1578 <section title="Events">
1580 Every execution of the Event Context begins with an event, which
1581 consists of a key/value pair, and a mouse position, which consists of
1582 an x and y coordinate. The possible keys are <t>_Press[1-3]</t>,
1583 <t>_Release[1-3]</t>, <t>_Click[1-3]</t>, <t>_DoubleClick[1-3]</t>,
1584 <t>_Move</t>, <t>_KeyPressed</t>, and <t>_KeyReleased</t>.
1586 Here are two example events:
1588 An event is triggered by writing the key to the value on a box. This
1589 triggers any trap handlers which may be present. Once these handlers
1590 have executed, Ibex figures out which child of the current box contains
1591 the mouse (taking into account that some boxes may cover up others)
1592 and writes the key and value to that box. If none of the box's
1593 children contain the mouse position, Ibex removes the leading
1594 underscore from the key name and writes the value to
1595 <i>that</i> property. Once all the traps on that property have
1596 executed, the value is written to the box's parent.
1598 Intuitively, Ibex delivers the underscored event to every box from the
1599 root to the target, and then delivers the non-underscored event to
1600 that same set of boxes in reverse order. So the event travels down
1601 the tree to the target, and then back up to the root. The following
1602 example prints out "first second third fourth" in that order.
1606 _Press1 ++= function(b) { ibex.log.info("first"); }
1607 Press1 ++= function(b) { ibex.log.info("fourth"); }
1609 _Press1 ++= function(b) { ibex.log.info("second"); }
1610 Press1 ++= function(b) { ibex.log.info("third"); }
1615 In general, you should use the <i>non-underscore</i> names to respond
1616 to user input and use the underscored names when you want to override
1617 child boxes' behavior or route events to particular boxes (for
1618 example, when implementing a focus protocol). This is why the
1619 underscored elements are delivered to parents before children (so
1620 parents can override their childrens' behavior), but non-underscored
1621 events are delivered to children before parents (since, visually, a
1622 mouse click is usually "intended" for the leaf box underneath the
1627 <heading title="Stopping the Process"/>
1629 At any point in this sequence, a trap handler can choose not to
1630 cascade (by returning <t>true</t> from the trap handler function).
1631 This will immediately cease the propagation of the event. This is how
1632 you would indicate that an event has been "handled".
1634 <heading title="Enter and Leave"/>
1636 Ibex will trigger the <t>Enter</t> and <t>Leave</t> properties as
1637 it walks down the tree, based on the position of the mouse (or the
1638 faked position if the <t>mouse</t> property has been written to).
1639 However, <t>Enter</t> and <t>Leave</t> are not events since they
1640 do not implicitly cascade up or down the tree.
1642 <section title="Listing of Events">
1644 <property name="Press1 / Press2 / Press3">
1645 Indicates that the use has pressed a mouse button. On
1646 platforms with three mouse buttons, the <i>middle</i> button
1647 is button 3 -- this ensures that applications written to only
1648 use two buttons (1 and 2) will work intuitively on three button
1652 <property name="Release1 / Release2 / Release3">
1653 Indicates that the use has released a mouse button.
1656 <property name="Click1 / Click2 / Click3">
1657 Indicates that the user has pressed and released the
1658 mouse button without moving the mouse much (exactly how
1659 much is platform-dependent).
1662 <property name="DoubleClick1 / DoubleClick2 / DoubleClick3">
1663 Indicates that the user has clicked the
1664 mouse button twice within a short period of time (exactly how long is platform-dependent).
1667 <property name="Move">
1668 Indicates that the mouse has moved while within this box, or that
1669 the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
1672 <property name="KeyPressed KeyReleased">
1673 A string is written to this property when a key is pressed or
1674 released If the key was any other key, a multi-character
1675 string describing the key will be put. For simplicity, we use
1676 the VK_ constants in the <link
1677 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1678 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1679 key is pressed or released, the string put will be the portion
1680 of its VK_ constant after the underscore, all in lower case.
1681 If the shift key was depressed immediately before the event
1682 took place, then the string will be capitalized. Special
1683 keynames are also capitalized; shift+home is reported as
1684 "<t>HOME</t>". Symbols are capitalized as they appear on the
1685 keyboard; for example, on an American QWERTY keyboard, shift+2
1686 is reported as "<t>@</t>". If the alt, meta, or command key
1687 was depressed immediately before this key was pressed, then
1688 the string will be prefixed with the string "<t>A-</t>". If
1689 the control key was depressed while this key was pressed, then
1690 the string will be prefixed with the string "<t>C-</t>". If
1691 both alt and control are depressed, the string is prefixed
1692 with "<t>C-A-</t>". Ibex does not distinguish between a key
1693 press resulting from the user physically pushing down a key,
1694 and a 'key press' resulting from the keyboard's typematic
1695 repeat. In the rare case that an application needs to
1696 distinguish between these two events, it should watch for
1697 KeyReleased messages and maintain an internal key-state
1705 <!-- ----------------------------------------------------------------------- -->
1706 <section title="Networking">
1708 <section title="XML-RPC">
1710 XML-RPC objects can be created by calling <t>ibex.net.rpc.xml(<i>XML-RPC
1711 URL</i>)</t>, and then invoking methods on that object. For example,
1714 Press1 += function(v) {
1715 ibex.thread = function() {
1716 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
1717 color.getTodaysColor("Friday");
1722 When the user clicks the first mouse button on this box, it will
1723 contact the server <t>xmlrpc.ibex.org</t>, route to the
1724 <t>/RPC2/</t> handler and invoke the <t>getTodaysColor()</t>
1725 method on the <t>color</t> object with a single string argument
1726 "<t>Friday</t>". The return value will be used to change the color
1727 of the box the user clicked on.
1729 Note that in this example we spawned a background thread to handle the
1730 request -- the <t>Press1</t> event is delivered in the foreground
1731 thread, and XML-RPC methods may only be invoked in background
1732 threads. This is to prevent the UI from "locking up" if the server
1733 takes a long time to reply.
1735 If the XML-RPC method faults, an object will be thrown with two
1736 properties: <t>faultCode</t> and <t>faultString</t>, as defined in
1737 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1738 Ibex encounters a network, transport, or session-layer error, it will
1739 throw a <t>String</t> object describing the error in a
1740 human-readable format. Scripts should not rely on the contents of
1741 this string having any special structure or significance.
1743 If an object with an associated non-empty stream is passed as an
1744 argument to an XML-RPC method, it will be sent as a <base64/>
1745 element. If a <base64/> element is found in the XML-RPC reply, it
1746 will be returned as an object with a stream drawn from that byte sequence.
1748 Each object returned by <t>ibex.net.rpc.xml()</t> represents a
1749 single HTTP connection. The connection will be held open until
1750 the object is garbage collected or the server closes the
1751 connection. If a second call is issued on the object before the
1752 first one returns (usually from a seperate thread), the two calls
1754 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1755 text="pipelined"/>. This can dramatically improve performance.
1757 Ibex supports HTTP Basic and Digest authentication. To use
1758 authentication, pass <t>ibex.net.rpc.xml()</t> a URL in the form
1759 <t>http[s]://user:password@hostname/</t>. Ibex will use Digest
1760 authentication if the server supports it; otherwise it will use
1761 Basic authentication. Please be aware that many XML-RPC server
1762 implementations contain a <link
1763 url="http://www.ibex.org/faq.html#auth" text="broken implementation of Basic authentication"/>.
1767 <section title="SOAP">
1769 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1771 <list type="ordered">
1773 <t>ibex.net.rpc.soap()</t> is used instead of
1774 <t>ibex.net.rpc.xml()</t>
1776 Instead of specifying just the URL of the service itself, you
1777 must specify the URL, the SOAPAction argument, and the
1780 The actual method invocation takes only one argument, which
1781 must be an object. This is necessary since SOAP arguments are
1782 specified by name, rather than ordering.
1786 SOAP faults are handled the same way as XML-RPC faults except that the
1787 capitalization of the <t>faultstring</t> and <t>faultcode</t>
1788 members is all lower-case, to match the SOAP spec. Here is a
1792 Press1 ++= function(v) {
1793 ibex.thread = function() {
1794 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
1796 "http://ibex.org/namespace"
1797 ).color.getTodaysColor( {
1804 As you can see, SOAP is much more verbose, yet does not offer
1805 substantially improved functionality. We recommend that XML-RPC be
1806 used whenever possible, and that SOAP be reserved for legacy
1809 The current Ibex SOAP stack does not support 'document style' or
1810 multi-ref (<t>href</t>) data structures.
1814 <section title="Security">
1816 Applications downloaded from the network (as opposed to those loaded
1817 from the filesystem) may only make certain kinds of connections to
1818 certain hosts. See Appendix A for a detailed description of the
1824 <!-- ----------------------------------------------------------------------- -->
1825 <section title="Error Handling">
1827 If the Ibex Core encounters an error while servicing a function call
1828 originating in JavaScript, the core will throw a string consisting of
1829 an error code followed by a colon, a space, and a descriptive message.
1833 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1836 The code should be used to determine how the program should respond to
1837 an error. The codes are organized in a hierarchy, so the
1838 string.startsWith() method can be used to determine if an error lies
1839 within a particular subhierarchy. The descriptive message portion of
1840 the string may be shown to the user.
1842 <property name="ibex.assertion.failed">
1845 <property name="ibex.io">
1846 General I/O exceptions
1848 <property name="ibex.io.encoding">
1849 Error translating between character encodings.
1851 <property name="ibex.io.zip">
1852 Attempted to access a corrupt zip archive.
1854 <property name="ibex.io.eof">
1855 End of file encountered unexpectedly
1857 <property name="ibex.net.security.prohibitedHost">
1858 A piece of untrusted Ibex code attempted to contact a
1859 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
1861 <property name="ibex.net.dns.temporaryFailure">
1862 An attempt to resolve a hostname failed but it is not known
1863 for certain that the hostname is invalid.
1865 <property name="ibex.net.dns.unknownHost">
1866 An attempt to resolve a hostname failed because the hostname
1869 <property name="ibex.net.socket.closed">
1870 A socket was closed unexpectedly.
1872 <property name="ibex.net.socket.connectionFailed">
1873 A connection could not be made to the remote host.
1875 <property name="ibex.net.url.malformed">
1876 Tried to parse a malformed URL.
1878 <property name="ibex.net.ssl">
1879 General SSL protocol errors.
1881 <property name="ibex.net.ssl.untrustedCertificate">
1882 The server's certificate was not signed by a CA trusted by Ibex.
1884 <property name="ibex.net.http.">
1885 Thrown when an HTTP error code is returned during an
1886 operation. The three characters <t><i>xyz</i></t> will be
1887 the three-digit HTTP status code.
1889 <property name="ibex.net.xmlrpc.null">
1890 The caller attempted to transmit the <t>null</t> value via XML-RPC.
1892 <property name="ibex.net.xmlrpc.circular">
1893 The caller attempted to transmit a circular data structure via XML-RPC.
1895 <property name="ibex.net.xmlrpc.specialObject">
1896 The caller attempted to transmit a "special" object via
1897 XML-RPC (for example, a Box or the Ibex object).
1899 <property name="ibex.null.put">
1900 A JavaScript attempted to put to a property on the <t>null</t> value
1902 <property name="ibex.null.get">
1903 A JavaScript attempted to get from a property on the <t>null</t> value
1905 <property name="ibex.null.call">
1906 A JavaScript attempted to call the <t>null</t> value
1909 If an exception is thrown inside a trap, the exception will propagate
1910 to the script that triggered the trap.
1912 If an uncaught exception is thrown while applying a template, or the
1913 requested template could not be found, an error will be logged and the
1914 box to which the template was being applied will be made invisible
1915 (<t>visible = false</t>). This ensures that half-applied widgets are
1916 never shown to the user.
1920 <!-- ----------------------------------------------------------------------- -->
1921 <section title="Advanced Topics">
1923 <section title="Re-routing events">
1925 At any point in the Event Context, you can write to the <t>mouse</t>
1926 property on any box. The value written should be an object with two
1927 properties, <t>x</t> and <t>y</t>. For example:
1930 _Press1 ++= function(p) {
1931 mouse = { x: 32, y: 77 };
1935 The coordinates specified are relative to the box whose <t>mouse</t>
1936 property is being written to. There is no need to supply the
1937 <t>inside</t> property; it is computed automatically. Writing to
1938 the <t>mouse</t> property causes Ibex to recompute the eventual
1939 target box, and also alter the values returned by <t>mouse.x</t>,
1940 <t>mouse.y</t>, and <t>mouse.inside</t> for any <i>descendants</i>
1941 of the current box. Writing to the <t>mouse</t> property also
1942 automatically prevents the event from returning to the box's parents
1943 -- it is equivalent to not cascading on the non-underscored event.
1944 This ensures that child boxes cannot trick their parent boxes into
1945 thinking that the mouse has moved.
1947 If you want the event to "skip over" the boxes between the trapee
1948 and the target, or if you want to re-route an event to a box which
1949 is not a descendant of the current box, simply write the value to
1950 the proper key on the target box.
1954 _KeyPressed = function(k) { ibex.log.info("first"); }
1955 KeyPressed = function(k) { ibex.log.info("sixth"); }
1956 $recipient.target = $target;
1957 <box id="recipient">
1958 _KeyPressed = function(k) {
1959 ibex.log.info("second");
1960 thisbox.target.KeyPressed = k;
1961 // inhibit cascade; keep event from going to $excluded
1964 KeyPressed = function(k) { ibex.log.info("fifth"); }
1966 _KeyPressed = function(k) {
1967 ibex.log.info("this never happens");
1972 _KeyPressed = function(k) { ibex.log.info("third"); }
1973 KeyPressed = function(k) { ibex.log.info("fourth"); }
1980 <section title="Synthesizing Your Own Events">
1982 You can create "fake events" by simply writing to the <t>mouse</t>
1983 property and then writing a value to one of the underscored properties
1984 on a box. This will have exactly the same effect as if the use had
1985 actually pressed a key, clicked a button, or moved the mouse -- they
1986 are indistinguishable.
1990 <section title="Ibex self-emulation">
1992 When the core first starts up, it clones the <t>ibex</t> object,
1993 creates a stream for the initial .ibex, and then places a trap on the
1994 cloned <t>ibex</t> object so that its empty-string property returns
1995 the .ibex stream. The cloned Ibex object is then passed as the third
1996 (optional) argument to <t>ibex.apply()</t>, making it the default
1997 <t>ibex</t> object for the scripts that are executed as part of the
1998 template instantiation.
2001 var new_ibex = ibex.clone(ibex);
2002 var stream = ibex.bless(ibex.stream.url("http://..."));
2003 new_ibex[""] ++= function() { return stream; }
2004 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2007 Note that we called <t>ibex.bless()</t> on the stream before tacking
2008 it on to the new Ibex object. The bless function returns a clone of
2009 the object passed to it, with a few traps which are explained below.
2010 Additionally, any sub-streams retrieved by accessing properties of the
2011 blessed stream will also automatically be blessed (blessed streams are
2014 Blessing a stream serves three purposes:
2016 <list type="unordered">
2018 Blessed clones always return the appropriate static block when
2019 their empty property is accessed; this ensures that references
2020 to the static blocks of other templates work properly.
2022 Blessed substreams can return their parent stream by accessing
2023 a hidden property which is reserved for internal use by Ibex.
2024 This ensures that Ibex can automatically add filename
2025 extensions where needed, according to the following rules:
2028 If the stream is a template to be applied, the string
2029 "<t>.ibex</t>" is appended.
2031 If the stream is an image, the string "<t>.png</t>" is
2032 appended. If no stream is found, "<t>.jpeg</t>" and
2033 "<t>.gif</t>" are tried, in that order.
2035 If the stream is an font, the string "<t>.ttf</t>" is
2039 Every call to <t>ibex.bless()</t> returns a different object
2040 (which happens to be a clone of the object passed to it) with
2041 a completely separate set of static blocks.
2045 Ibex can self-emulate by using <t>ibex.clone()</t> on the Ibex object;
2046 this technique is very similar to the use of ClassLoaders in
2047 Java. This is useful for a number of applications, including
2048 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2049 others. For example:
2052 var newLoadFunction = function(url) { /* ... */ };
2053 var new_ibex = ibex.clone(ibex);
2054 new_ibex.load ++= function() { return newLoadFunction; }
2055 ibex.apply(ibex.box, .main, new_ibex);
2060 <!-- ----------------------------------------------------------------------- -->
2061 <appendix title="Security Architecture and Considerations">
2063 Due to the expense and hassle imposed by the commercial PKI code
2064 signing architecture, and the fact that it <link
2065 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2066 really provide any security anyways"/>, Ibex user interfaces are
2067 distributed as unsigned, untrusted code. As such, they are handled
2068 very carefully by the Ibex Core, and assumed to be potentially
2071 Ibex's security architecture is divided into defenses against four
2072 major classes of attacks:
2074 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2076 Ibex user interfaces are run in an extremely restrictive sandbox. The
2077 environment does not provide primitives for accessing any data outside
2078 the Ibex core except via XML-RPC and SOAP calls. There are no
2079 facilities to allow Ibex user interfaces to access the client's
2080 operating system or to interact with other applications on the same
2081 host (unless they provide a public XML-RPC or SOAP interface).
2082 An Ibex script may only access a file on the user's hard disk if the
2083 user explicitly chooses that file from an "open file" or "save file"
2084 dialog. There is one exception to this rule: if all templates
2085 currently loaded in the Ibex core originated from the local
2086 filesystem, those templates can load additional .ibexs from the local
2089 The Ibex Core is written in Java, so it is not possible for
2090 scripts to perform buffer overflow attacks against the core
2093 Ibex applications may only read from the clipboard when the user
2094 middle-clicks (X11 paste), presses control-V (Windows paste), or
2095 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2096 "alt"). This ensures that Ibex applications are only granted access to
2097 data that other applications have placed on the clipboard when the user
2098 specifically indicates that that information should be made available
2099 to the Ibex application.
2101 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2103 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2104 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2105 regular TCP sockets.
2107 Ibex will not allow a script to connect to a non-public IP address
2108 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2109 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2110 1918"/>). There is one exception -- if all templates currently loaded
2111 in the core originated from the same IP address, those scripts may
2112 make calls to that IP address regardless of whether or not it is
2113 firewalled. If Ibex does not have access to a DNS resolver (because it
2114 is using a proxy which performs DNS lookups), Ibex will provide the
2115 proxy with the appropriate <link
2116 url="http://www.ibex.org/x-requestorigin.html"
2117 text="X-RequestOrigin"/> header that the proxy needs in order
2118 to maintain security.
2120 The only remaining possible attack is against a XML-RPC or SOAP
2121 service running on a firewalled host with a public address. Assigning
2122 such machines public IP addresses is a poor network security policy,
2123 and doing so squanders scarce public IPv4 addresses. As such, the onus
2124 is on the administrators of such machines to explicitly block access
2125 to clients reporting a <t>User-Agent:</t> header beginning with the
2126 three characters "<t>Ibex</t>".
2128 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2130 All top-level windows created by Ibex are <i>scarred</i> -- a stripe
2131 and a lock is drawn across the corner of the window. There is no way
2132 for a user interface to remove this scar. Ibex user interfaces may not
2133 create windows smaller than the size of the scar.
2135 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2137 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2138 for encryption. Ibex will attempt 128-bit encryption, but will
2139 negotiate down to 40-bit if the server does not support strong
2140 crypto. Ibex's SSL implementation is currently provided by <link
2141 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2142 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2145 All HTTPS connections must be authenticated by the server using a
2146 certificate whose name matches the domain name of the HTTPS URL. The
2147 certificate must be signed by a trusted root CA. Ibex trusts the same
2148 93 root CAs whose certificates are included as "trusted" in Microsoft
2149 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2150 against man-in-the-middle attacks; you should not trust this
2151 connection with any data you would not normally trust an SSL-enabled
2156 <!-- ----------------------------------------------------------------------- -->
2157 <appendix title="ECMAscript compliance">
2159 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2160 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2163 <section title="Omissions">
2165 The following ECMA features are not supported:
2167 <list type="unordered">
2169 The <t>undefined</t> value, <t>===</t>, and <t>!==</t>
2171 The <t>new</t> keyword (and ECMAScript object inheritance)
2174 <t>getter</t> and <t>setter</t>
2176 The ECMA <t>this</t> keyword.
2178 The <t>String</t>, <t>Number</t>, and <t>Boolean</t>
2179 classes. Note that <t>string</t>, <t>number</t>, and
2180 <t>boolean</t> values are supported, however.
2182 You may not <t>throw</t> the <t>null</t> value.
2186 Additionally, you must declare all root-scope variables (with
2187 <t>var</t>) before using them; failure to do so will result in an
2188 exception. Box properties are pre-defined in the scope that scripts
2193 <section title="Extensions">
2195 <list type="unordered">
2197 The token <t>..</t> is equivalent to <t>[""]</t>.
2203 Extended <t>catch</t> syntax. The following code:
2205 } catch(e propname "foo.bar.baz") {
2212 if (e.propname != null and e.propname >= "foo.bar.baz" and
2213 "foo.bar.baz/" > e.propname) {
2218 Multiple extended-catch blocks can appear at the end of a single try
2219 block. However, at most one non-extended catch block may appear, and
2220 if it does appear, it must be the last one.
2222 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2223 "<t>lt</t>" is be interpreted as <t><</t>, the lexical
2224 token "<t>gt</t>" is be interpreted as <t>></t>, and the
2225 token "<t>and</t>" is interpreted as <t>&&</t>.
2226 Thus these tokens cannot be used as variable names.
2228 The identifier <t>static</t> is a reserved word in
2229 ECMAScript, but not in Ibex.
2231 Ibex defines an additional reserved word, "<t>assert</t>",
2232 which will evaluate the expression which follows it, throwing
2233 a <t>ibex.assertion.failed</t> exception if the expression
2234 evaluates to <t>false</t>.
2236 To ensure that Ibex files appear the same in all text editors, tab
2237 characters are not allowed in Ibex files.
2241 Some useful tutorials include:
2243 <list type="unordered">
2246 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2247 text=" JavaScript 1.2 Reference"/>. Although this document is
2248 out of date, it is arguably the best guide available for free
2249 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2250 r1) to 1.5 were minimal, and many of them were <link
2251 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2254 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2255 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2256 and Paula Ferguson. The latest edition of this book covers
2257 JavaScript 1.5 (ECMA-262 r3).
2260 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2261 text="ECMA-262"/> specification. This is an extremely
2268 <!-- ----------------------------------------------------------------------- -->
2269 <appendix title="Logging and Command Line Invocation">
2271 Very early in the loading process, Ibex begins logging messages about
2272 what it is doing. Where this output is logged to differs by platform;
2273 currently it goes to standard output when running inside a JVM, and to
2274 <t>$TMPDIR\ibex-log.txt</t> on Win32 (where <t>$TMPDIR</t> is the
2275 value returned by <t>GetTempPath()</t>). The logs contain a lot of
2276 valuable debugging information and performance hints; if you are
2277 having trouble developing an Ibex application, be sure to check the
2280 If Ibex encounters a serious problem before it starts logging
2281 information, or if it is unable to open the log file, it will abort
2282 immediately with a critical abort, which will be displayed on the
2283 console for POSIX-native cores and in a dialog box for JVM-based and
2286 You can invoke Ibex directly from the command line during
2287 development. When using a JVM, the invocation format is:
2290 java -jar path-to-ibex-jar [-sv] source-location [initial-template]
2293 Where <t><i>path-to-ibex-jar</i></t> is the path to <t>ibex.jar</t>,
2294 which can be downloaded <link url="http://www.ibex.org/dist/ibex.jar" text="here"/>.
2296 On Win32, the invocation format is:
2299 ibex.exe [-v] source-location [initial-template]
2302 The file <t>ibex.exe</t> is placed in Windows' ActiveX cache
2303 directory the first time Ibex is used on the machine. The ActiveX
2304 cache location depends on what version of Windows you are using;
2305 on newer versions of Windows it is <t>C:\WINDOWS\DOWNLOADED
2306 PROGRAM FILES\</t>. You can also extract <t>ibex.exe</t> from
2307 <t>ibex.cab</t>, which is available <link
2308 url="http://www.ibex.org/dist/ibex.cab" text="here"/>.
2310 The <t><i>source-location</i></t> parameter can be either the path
2311 to an .ibex archive, the http url of an .ibex archive, or the path to a
2312 directory comprising an unpacked .ibex archive.
2314 The <t><i>initial-template</i></t> parameter is the stream name of
2315 a template to be used as the initial template. If ommitted, it
2316 defaults to <t>main</t>.
2318 The <t>-v</t> option causes Ibex to enable verbose logging; this will
2319 cause it to log <i>lots</i> of information to the log file. This
2320 option will also substantially decrease Ibex's performance.
2324 <!-- ----------------------------------------------------------------------- -->
2326 <appendix title="Grammars">
2328 <i>Grammar support is experimental in this release
2329 and may not work properly. It may change in incompatible ways or
2330 disappear completely from future releases</i>
2332 Grammars are defined with a statement in the following form:
2337 A grammar is really just another function; once defined you can't tell
2338 it apart from an ordinary function. A grammar takes one argument,
2339 which can be a string or stream. The argument is parsed and the
2340 result of executing the code block 'c' is returned.
2342 The property 'a' is read; if the value is a grammar, a new production
2343 rule (ie a new alternative, as with '<t>|</t>') is added to that grammar
2344 (this is a destructive update). This allows you to add productions to
2345 pre-existing grammars (for example, adding a new type of expression to
2346 a programming language by extending the 'expr' grammar). If the old
2347 value is not a grammar, the value is discarded and a new grammar
2350 The value 'b' is a pattern, which may consist of seven simple
2353 <list type="unordered">
2356 grouping parens <t>()</t>
2358 combinators: <t> | + * ?</t>
2360 references to other grammars
2363 The value 'c' and the braces surrounding it are an *optional* code
2364 block, in which the following identifiers are bound:
2366 <list type="unordered">
2368 The identifier 'whole' is bound to the string matched by the
2369 entire expression. If the code block is omitted it behaves
2370 as if it were "<t>{ return whole; }</t>".
2372 For every reference to another grammar which was matched in the
2373 pattern, the *name used to reference that other grammar* will
2374 be bound to the value returned by its code block. Here's an
2375 example of this important distinction:
2378 var foo ::= 'a' | 'b';
2380 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2383 On the last line, the identifier 'bar' serves two purposes: it
2384 pulls in the definition of the pattern *and* acts as a binder
2385 within the scope of the braces.
2387 If a reference is matched multiple times (either because it
2388 appears multiple times in the pattern or because the * or +
2389 operator was applied to it) then its name will be bound to an
2390 array containing the matches.
2394 Here is the metacircular definition of the grammar facility:
2397 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2398 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2399 char ::= '\0x0000'..'\0xffff'
2400 literal ::= '\'' char+ '\''
2401 | '\'' char '\'' '..' '\'' char '\''
2402 pattern ::= identifier
2409 | pattern '|' pattern
2414 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2415 Ibex is a trademark of Adam Megacz