1 <ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org" logo="ibex-logo.pdf">
3 <!-- ----------------------------------------------------------------------- -->
4 <section title="Introduction">
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 **
12 Ibex is a software platform based on the philosophy that the most
13 useful systems consist of both **statically typed** and
14 **dynamically typed** languages, working in concert.
18 - Statically typed languages (such as Java) are well suited for
19 high-performance, reliable, reusable code. Unfortunately
20 programs written in statically typed languages often take
21 longer to develop, and their commitment to a specific type
22 system makes interoperating with other languages cumbersome.
24 - Dynamically typed languages (such as JavaScript) typically
25 perform poorly (due to runtime checks and inadequate static
26 information for optimization), tend to admit more errors (due
27 to less static checking), and export APIs which are not
28 precisely defined (due to the huge number of possible
29 type/method combinations). However, writing programs in
30 dynamically typed languages is a much more rapid process, and
31 the implicit coercions in such languages make interoperability
32 between similar languages very easy.
36 The architectural incarnation of this philosophy is the Ibex Object
37 Model, a universal interface to dynamically typed languages. The
38 IOM serves as a common interface between statically typed languages
39 and dynamically typed languages both locally and over the network.
41 <section title="The Ibex Object Model">
43 The Ibex Object Model consists of three primitive types:
46 - __number__ -- a floating point number
47 - __string__ -- a unicode string
48 - __boolean__ -- either [[true]] or [[false]]
51 From these primitives, more complex structures can be built from
55 - __array__ -- a collection of objects indexed by a non-negative integer
56 - __hash__ -- a collection of objects indexed by objects (often strings)
59 Any of the following actions can be performed on an object:
62 - __get(key)__ -- attempts to retrieve the object indexed by
63 [[key]]. Returns an object.
65 - __put(key, val)__ -- attempts to add object [[val]] with key
66 [[key]] to an object. Does not return a value.
68 - __call(args)__ -- attempts to call the object as if it were a
69 function. The [[args]] value is a list of arguments. May or
70 may not return a value.
73 The keys of some objects may be enumerated by attempting to "call"
74 the object; the return value will be an array of the object's keys.
76 Finally, an object may be **coerced** to any of the three
77 primitive types, although this coercion may fail. Objects may
78 also be coerced to the **bytestream** type, which represents an
79 unbounded stream of octets. Dynamically typed code may not
80 explicitly manipulate bytestreams, although it can pass objects
81 to statically typed code which in turn coerces those objects to
84 Any of the above operations may **throw** an exception, which is
87 Any entity in the statically typed world which supports these
88 operations may expose itself to the dynamically typed world.
89 Furthermore, it can expect that any values passed to it will support
90 all of the operations shown above.
93 <section title="Namespaces">
95 - cover templates here with David's isomorphism?
98 <section title="Platforms Founded on the Ibex Object Model">
100 The remainder of this document describes the three major
101 systems founded on the Ibex Object Model:
104 - The Ibex User Interface
105 - The Ibex Persistent Storage Service
106 - The Ibex Mail Server
110 Currently, all four of these systems use Java as the statically
111 typed language and IbexScript (a derivitave of JavaScript) as
112 the dynamically typed language. However, since they interact
113 strictly via the Ibex Object Model, either component can be
114 rewritten in a different language.
118 <section title="Key Concepts">
120 <definition term="The Core">
121 Ibex itself; the native code (or Java bytecode) that runs on
122 the client. This term does not include the **Wildebeest**
123 or the **UI**</definition>
125 <definition term="The UI / The Application">
126 A set of files (mostly XML, JavaScript, and PNG images)
127 bundled up in a zip archive, ending with the "[[.ibex]]"
128 extension. Together, these files specify the appearance and
129 behavior of the application's user interface.
132 <definition term="The Server">
133 We will use the term "the server" to refer to any other
134 computer which the client makes XML-RPC or SOAP calls
135 to. Note that it is possible for the client and server to be
136 the same machine.</definition>
138 <definition term="Wildebeest">
139 This is a very small piece of code that is downloaded the
140 first time a client uses Ibex. It downloads the Ibex core,
141 verifies its signature, and launches it with the appropriate
142 parameters indicating where to find the initial UI.
143 Wildebeest works differently on every platform, and is outside
144 the scope of this document.</definition>
146 <definition term="put/write">
147 In ECMAscript, when you change the value of a property on an
148 object, you are **putting** to that property, or
149 **writing** to it. For example, the ECMAscript expression
150 "[[foo.bar = 5]]" **puts** the value 5 to the bar
151 property on object foo.</definition>
153 <definition term="get/read">
154 In ECMAscript, when you access the value of a property on an
155 object, you are **getting** that property, or
156 **reading** from it. For example, the ECMAscript
157 expression "[[return (3 + foo.bar)]]" **gets** the
158 value of bar property on object foo and then adds 3 to it
159 before returning the result.</definition>
161 <definition term="JavaScript">
162 We will use the terms JavaScript and ECMAScript
163 interchangeably in this document. The Ibex interpreter is not
164 completely ECMA-compliant, however (see <link
165 appendix="ECMAscript compliance"/> for details).
171 <section title="The Ibex User Interface">
172 <section title="Life Cycle of an Ibex Application">
174 <image url="lifecycle.pdf" caption="The Lifecycle of an Ibex Application"/>
176 A user typically begins an Ibex session by clicking on a link to
177 an Ibex application. This link serves the [[launch.html]] file
178 to the user's browser (1), which in turn downloads the appropriate
179 **Wildebeest** (2)-- currently either an ActiveX Control
180 (Win32/MSIE), XPInstaller (Mozilla), or Signed Applet (all
183 The Wildebeest downloads the appropriate core for the user's
184 machine and verifies its digital signature (3). It then launches
185 the core, which downloads the UI (4), (an [[.ibex]] archive),
186 loads it, applies the [[main.t]] template (found in the archive),
187 and renders it onto the screen, running any associated JavaScript
190 The user interacts with the application by clicking and moving the
191 mouse, and by pressing keys on the keyboard (5). These actions
192 trigger fragments of JavaScript code which are designated to
193 handle events. This JavaScript code can then relay important
194 information back to the server using XML-RPC or SOAP (5), or it
195 can modify the structure and properties of the user interface to
196 change its appearance, thereby giving feedback to the user.
198 The Ibex core quits when the last remaining surface has been destroyed.
203 <section title="Surfaces">
205 <image url="offscreen.pdf" width="2in"
206 caption="An Ibex surface positioned at (83,0)"/>
207 Each top-level window in an Ibex UI is called a
208 **surface**. There are two kinds of surfaces: **frames**,
209 which usually have a platform-specific titlebar and border, and
210 **windows**, which never have any additional platform-specific
213 Whenever we refer to the size or position
214 of a surface, we are referring to the size or position of the
215 UI-accessible portion of the surface; this does not include any
216 platform-specific decorations. This means that if you set the
217 position of a frame to (0,0), the platform-specific titlebar will
218 actually be off the screen on most platforms (it will be above and
219 to the left of the top-left corner of the screen).
221 Surfaces are not actual JavaScript objects; you cannot obtain a
222 reference to a surface. However, each surface is uniquely identified
223 by its **root box**, described in the next section.
227 <section title="Boxes">
229 A **box** is the fundamental unit from which all Ibex user
230 interfaces are built. Boxes can contain other boxes (referred to as
231 its **children**). Each surface has a single box associated with
232 it called the **root box**; the root box and its children (and
233 its children's children, and so on) form the surface's **box
236 There are three ways to think of a box:
239 As a rendered visualization on the screen (the "**Visual Representation**")
241 As a JavaScript object (the "**Object Representation**")
243 As as an XML tag (the "XML Template Representation").
247 <image url="threeviews.pdf" caption="The three representations of an Ibex box"/>
249 All three representations are equally valid, and being able to
250 figure out what an action in one representation would mean in terms
251 of the other two representations is crucial to a solid understanding
256 <section title="The XML Template Representation">
258 A template (discussed in the next section) is an XML file which acts
259 as a blueprint for constructing a tree of boxes. We call this
260 construction process **applying**, since unlike **instantiation** in
261 object-oriented programming systems, you always apply a template to
262 a pre-existing box, and you can apply multiple templates to the same
265 Each XML tag corresponds to a single box, or to another template
266 which will be applied to that box. For example, a [[scrollbar]]
267 template, when applied, will construct a tree of boxes which has the
268 visual appearance and behavior of a scrollbar.
270 Although it is useful to think of the XML tags as being boxes, keep
271 in mind that the XML representation is only a blueprint for
272 constructing a tree of JavaScript objects. Once the template has
273 been instantiated, the XML is effectively "thrown away", and
274 JavaScript code is free to alter the boxes. Once the process of
275 applying a template is complete, Ibex completely forgets the fact
276 that it has applied a particular template to a particular box. One
277 consequence of this approach is that if you think of templates as
278 classes, then Ibex has no equivalent for Java's [[instanceof]]
281 Each template is an XML document whose root element is
282 [[<ibex>]]. Here is a sample template file:
285 <ibex xmlns:lib="ibex.lib">
288 This is a cool widget.
291 // this code is executed only once
292 static = { instances : [] };
294 // this element applies the ibex.lib.focusable template
298 static.instances.push(thisbox);
299 <ui:box id="container"/>
308 The following two namespaces are predefined and need not be declared
311 <definition term="meta">
312 [[http://xmlns.ibex.org/meta]]
314 This will be referred to as the "[[meta]] namespace" in the
315 remainder of this document.
318 <definition term="ui">
319 [[http://xmlns.ibex.org/ui]]
321 This will be referred to as the "[[ui]] namespace" in the
322 remainder of this document.
325 Additionally, the default namespace for the document will be set to
326 the template's package FIXME.
328 <section title="Static Code">
330 If the root [[<ibex>]] element contains any non-whitespace
331 text content, this text is interpreted as JavaScript code and is
332 executed the first time the template is referenced. This code is
333 executed in a fresh scope containing two predefined properties:
335 <definition term="ibex">
336 The Ibex Object (described in <ref section="The Ibex Object"/>)
339 <definition term="static">
340 A reference to this template's **static object**, which is
341 initially [[null]]. The static object can be accessed (read
342 and written) from both static scripts as well as instance
343 scripts in a particular template. FIXME
347 <section title="Metadata">
349 Any immediate children of the root element which are in the
350 [[meta]] namespace are treated as metadata and are exempted from
351 the rest of the template application process. Currently only one
352 type of metadata element is defined:
355 [[<meta:doc>]]: structured documentation for the
361 <section title="Other Elements">
363 All remaining children of the root element are treated as elements
364 to be **applied** to the box, in the order in which they appear
365 in the file using the following procedure.
367 <remark text="While this process outlined below sounds very
368 complex, it actually works pretty intuitively. The
369 description below is given in great detail since
370 most applications will wind up being unintentionally
371 dependent on subtle features of this process.
372 However, most of the time you can just pretend that
373 the XML tags and the boxes are the same thing."/>
375 <heading title="Intuitive Description"/>
379 During a box initialization, script-private references to a
380 box's descendants with [[id]] attributes are placed on the
381 box. These references allow scripts on that box to easily refer
382 to descendant nodes created by the template in which the script
383 appears. For example, these two blocks of code have exactly the
388 <ui:box id="foo"/> <ui:box/>
389 $foo.color = "red"; var $foo = this[0];
394 <heading title="Precise Description"/>
396 To apply an XML tag [[__x__]] to a box [[__b__]], perform the following
397 operations, in this order:
399 <list type="ordered">
401 Allocate a fresh scope [[__s__]] whose parent scope is
404 Process each child element or text segment of [[__x__]]
405 in the order they appear in the document:
409 Treat each text segment [[__t__]] as JavaScript code
410 and execute it with [[__s__]] as the root scope.
412 For each child element [[__x'__]] of [[__x__]]:
415 Create a new box [[__b'__]].
417 If the name of tag [[__x'__]] is not
418 "[[box]]" in the [[ui]] namespace, prepend the
419 tag's namespace identifier uri (if any) to the name of
420 the tag, and use the result as a key to retrieve a
421 property from the root stream (defined later).
422 Interpret the resulting stream as a template and apply
423 that template to [[__b'__]].
425 (recursively) apply [[__x'__]] to [[__b'__]].
427 If [[__x'__]] has an [[id]] attribute, declare a variable
428 in [[__s__]] whose name is the value of the [[id]]
429 attribute, prefixed with the [[$]] character, and whose
432 Copy any [[$]]-variables created during the application
433 of [[__x'__]] into scope [[__s__]].
435 Append [[__b'__]] as the last child of [[__b__]].
439 Apply any attributes on [[__x__]] to [[__b__]], except for
440 [[id]]. Since XML specifies that the order of attributes
441 cannot be significant, Ibex processes attributes in
442 alphabetical order by attribute name. For example, if
443 [[__x__]] has the attribute [[foo="bar"]], then the
444 equivalent of the statement [[B.foo="bar";]] will be
445 performed, with the following exceptions:
448 If the value portion of the attribute is the string
449 "[[true]]", put the boolean [[true]]. If the
450 value is "[[false]]", put the boolean [[false]].
452 If the value is a valid ECMAscript number, put it as a
453 number (instead of a string).
455 If the value begins with a dollar sign ([[$]]),
456 retrieve the value of the corresponding variable in
457 [[__s__]] and use that value instead.
459 If the value begins with a dot ([[.]]), prepend the
460 attributes' namespace identifier uri (if any) and
461 interpret the remainder as a property to be retrieved from
462 the root stream (defined later).
466 <heading title="Initialization Invariants"/>
468 The last two steps are referred to as the **initialization** of the
469 node. There are two important aspects of this ordering to be aware of:
471 <list type="unordered">
473 A given box will be fully initialized before its parent is
474 given a reference to that box. This way, parents can be
475 certain that they will never wind up accessing a box when it
476 is in a partially-initialized state.
478 Attributes are applied **after** scripts are run so that
479 the attributes will trigger any **traps** (defined later)
480 placed by the script.
488 <!-- ----------------------------------------------------------------------- -->
489 <section title="Rendering">
491 FIXME: needs way, way, way more diagrams of nonrectangular boxes.
493 Each box occupies a region on the surface. The visual
494 appearance of a surface is created by rendering each box in its
495 tree. Unless the [[clip]] attribute is [[false]], each box will
496 clip its childrens' visual representations to its own, so that
497 the children appear "confined to" the parent. Children are
498 rendered after their parents so they appear "on top of" their
501 <heading title="Boxes Don't Have to Be Rectangular"/>
503 Until now we've tactily assumed that boxes are rectangular. In
504 fact, unlike its predecessor (XWT), Ibex boxes can be **any
505 shape at all**. We refer to the outline of a box as its path,
506 which may be composed of lines and curves (arcs and splines).
507 If the path is not set (or set to [[null]]), the box's path is
508 **implicitly** a rectangle.
510 A key step in understanding how Ibex works, and understanding
511 how operations on rectangular boxes generalize to arbitrary
512 boxes is to realize that "the path **is** the box". Just as a
513 rectangular box clips its children to the inside of the
514 rectangle, a circular box will clip its children to the inside
517 In fact, Ibex's integration of vector graphics with
518 constraint-based user interface layout runs quite deep -- boxes
519 which "contain" text are actually boxes whose outline path
520 **is** the actual letters of the text. This means that you can
521 assign children to a text-shaped box, and the children's
522 appearance will be cliped to the **inside** of the text letters.
524 The only time rectangular and non-rectangular boxes act
525 differently is when box packing takes place; when packing boxes,
526 Ibex only looks at the **bounding box** of a path (the smallest
527 rectangle that completely encloses the box's path). In the case
528 of rectangular boxes (which have not been rotated or sheared),
529 this bounding box happens to be exactly the same as the box's
530 path. So Ibex is actually treating these boxes the same, but
531 the chosen treatment favors rectangular boxes.
533 <section title="Visual Elements">
535 The appearance of a box consists of three visual elements: its
536 path, stroke, and fill.
538 <property name="path" type="string" default='""'>
539 A box's [[path]] consists of zero or more contours, each of
540 which consists of one or more lines, bezier curves (cubic or
541 quadradic), or generalized elliptic arcs. The grammar and
542 feature set supported are identical to that specified in <link
543 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
546 One of the most common sources of frustration when working with
547 text representations of vector paths, or programs that manipulate
548 them, is making a mistake when setting a transform which causes
549 the entire path to be off the screen. Since no part of the path
550 is visible, you have no idea which direction it went! To minimize
551 the chance of this happening, and generally make dealing with
552 vectors a more enjoyable experience, Ibex always **recenters** a
553 path. When you set a box's path (either by writing to its
554 [[path]] or [[text]] properties), Ibex translates the entire path
555 so that it is lined up with the X and Y axes, as close to the
556 origin as possible, in the positive-X, positive-Y quadrant. Ibex
557 will note this translation by setting the box's [[transform]] to
558 the transformation used to do this. If you do not desire this
559 behavior, just set the [[transform]] back to the identity
563 <property name="stroke" type="string" default="clear">
564 The color with which to stroke the path. Ibex paths may
565 only be stroked with a single color, solid line (not
566 dashed), of "hairline width" (meaning that the line is never more than one
567 antialiased pixel wide no matter what magnification it is
570 This property can be set to a 5-character hex string
571 ([[#RGB]]), 7-character hex string ([[#RRGGBB]]),
572 9-character hex string ([[#AARRGGBB]]), specifying the box's
573 hexadecimal color. Any other string is compared against the
574 <link url="http://www.color.org/ICC-1A_1999-04.PDF"
575 text="ICC"/> colors (the same set of color names supported
576 by SVG). If this property is set to [[null]], the stroke
577 color will be set to clear ([[#00000000]]).
579 Other vector formats (notably SVG and PDF) support "thick"
580 lines, dashed lines, lines stroked with a gradient or
581 texture, and an assortment of special caps and joins for
582 these thick lines (hairline lines do not need joins or
583 caps). Fortunately, all of these constructs can be
584 converted into **filled** paths rather easily, making it
585 possible for Ibex to support the same functionality with a
586 much simpler API (and more efficient rendering engine).
589 <property name="fill">
590 The graphic element with which to fill the path. This
591 property can be set to any of the values specified for
592 [[stroke]], as well as to a texture (an image) or a
593 gradient. Paths which self-intersect are filled according
594 to the SVG guidelines.
596 When an image (texture) is written to this property, the
597 box's [[minwidth]] and [[minheight]] properties will be
598 automatically set to the dimensions of the image (they can
599 be changed later if desired).
603 <section title="Text">
605 Ibex treats text exactly the same way it treats other paths.
606 Writing to the [[text]] property actually sets the box's path to
607 the outline of the rendered form of the text, and text is
608 subject to the same rotation, shearing, and scaling
609 transformations as all other boxes. You can even **read back**
610 the curves from which the text is composed by reading from the
611 [[path]] property (the string returned will be in SVG Path
612 syntax), modify it, and write it to the [[path]] property of
615 <property name="text" type="string" default='""'>
616 The box's text; writing [[null]] to this property sets it to
617 [[""]]. In order to help eliminate common chores when working
618 with text, Ibex will automatically take the following actions
619 when you write to the [[text]] property:
623 The text is converted to curves using the Freetype library,
624 and the resulting curve becomes the box's path.
626 If the box's [[strokecolor]] is [[null]], it is set to black
627 ([[#FF000000]]). When first created, a box has an invisible
628 stroke; automatically setting the stroke to a visible color
629 helps eliminate confusing errors. You can change the stroke
630 color back to clear after writing to the [[text]] property.
632 The box's [[aspect]] property is automatically set to the
633 correct aspect ratio for the chosen string in the chosen
634 font. This ensures that resizing will not warp the text.
637 <property name="font" type="stream" default=".ibex.ui.font.sansserif">
638 Fonts are rendered using the [[stroke]] assigned to the box,
639 using the font assigned to the [[font]] property. When an
640 object is written to this property, it is coerced to a stream which is interpreted using
641 the <link url="http://www.freetype.org" text="FreeType 2
642 library"/>, and the resulting font is used to render the box's
645 To choose the size of a font, just set the box's [[height]]
646 property to the desired height **in pixels**. Conversion
647 functions from points to pixels are available.
651 <section title="Transformations">
652 The [[transform]] property allows the user to specify an
653 arbitrary affine transformation to be applied to the box's path,
654 text, and children. The syntax and features supported are
655 identical to those described in <link
656 url="http://www.w3.org/TR/SVG11/coords.html" text="SVG 1.1,
657 section 7"/>, and include rotation, shearing, scaling, and
660 <property name="transform">
664 One tricky part about transformations is their interaction with
665 box packing and dimension properties. A box's size properties
666 (such as [[minwidth]] or [[height]]) are **always** measured in
667 the box's own coordinate space (ie after applying the box's
668 [[transform]]). This means that the sum of the [[width]]s of a
669 box's children may not be equal to the parent box's [[width]],
670 even if the children appear (on screen) to completely fill its
673 One other consequence of combining transformations with
674 constraint-based layout is that when a box is rotated, its width
675 and height are no longer completely independent (remember, the
676 box's width is measured in the rotated coordinate space). If a
677 box is turned at a 45 degree angle and then forced into a space
678 10 pixels wide, enlarging the box's width will force a reduction
679 in its height (in order to cram it in the 10 pixel space). In
680 situations like this, Ibex will first look to the box's
681 [[aspect]], if explicitly set, and obey that. If the box's
682 [[aspect]] is unspecified, Ibex will use the ratio between the
683 box's [[minwidth]] and [[minheight]] to guide the tradeoff. If
684 either of these properties is [[0]], Ibex will simply attempt to
685 make the ratio as close to [[1:1]] as possible.
687 When we talk about a box's **bounding box**, we are referring to
688 the smallest rectangle in the **parent's** coordinate space
689 which completely encloses the child box's path. This is the
690 only time we will deal with the size of a child using a
691 coordinate space other than its own.
694 <section title="Layout Properties">
696 We will cover the layout algorithm in detail in the next section,
697 but we introduce the properties at play here and give an intuition
700 <property name="packed" type="boolean" default="true">
701 The layout strategy for this box. If set to [[true]], the
702 box occupies no cells and is laid out independently of its
706 <property name="zoom" type="boolean" default="false">
707 This property controls the strategy Ibex uses for changing the
708 box's width and height in response to layout constraints.
710 If [[zoom]] is set to [[false]] (the default), then the box's
711 [[path]] will be altered by multiplying all the vertices by a
712 scaling factor in order to make the path's bounding box meet
713 the required constraints. The box's [[transform]] will not be
714 affected, and the scaling of the box's children will not be
717 If [[zoom]] is set to [[true]], the box's [[path]] will not be
718 altered in response to layout constraints; rather, its
719 [[transform]] will be altered in order to "zoom in" or "zoom
720 out" and bring all of the path's vertices within the desired
721 region. Since the box's [[transform]] also applies to its
722 descendants, they too will be magnified or reduced.
725 <property name="shrink" type="boolean" default="false">
726 If set to [[true]], this box will shrink
727 (horizontally/vertically/both) to the smallest size allowed by
728 its children and the bounding box of its path.
731 <property name="x y" type="integer" default="varies">
732 If the box is a root box, writing to these properties moves
733 the surface; reading from them returns the position of the
736 On non-root boxes, writing to these properties is a shorthand
737 for adding a [["translate(x, y)"]] to the box's [[transform]].
738 Reading from these properties will return FIXME.
741 <property name="minwidth minheight" type="integer" default="0">
742 The desired minimum width and height. See the [[zoom]]
743 property for a description of how the box is altered to meet
747 <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
748 The desired maximum width and height. See the [[zoom]]
749 property for a description of how the box is altered to meet
753 <property name="width height" type="integer">
754 When read, this is the current (width/height) of this box.
755 Writing to this property is equivalent to writing to
756 **both** the minimum and maximum (width/height).
759 <property name="cols rows" type="integer" default="0">
760 The number of (columns/rows) in which to lay out the children of this
761 box. If set to zero, the number of (columns/rows) is unconstrained.
762 Either [[rows]] or [[cols]] must be zero. If
763 [[0]] is written to [[cols]] when [[rows]] is
764 [[0]], the write is ignored. If a nonzero value is
765 written to [[cols]] when [[rows]] is nonzero,
766 [[rows]] is set to [[0]], and vice versa.
769 <property name="colspan rowspan" type="integer" default="1">
770 The number of (columns/rows) that this box spans within its parent.
773 <property name="aspect" type="float" default="0.0">
774 The width-to-height ratio constraint for this box; can be set
775 either as a floating point number ([[0.5]]) or a ratio
776 ([["1:2"]]). Setting this to [[0.0]] disables the ratio
779 Note packed boxes always **shrink** in order to satisfy aspect
780 constraints, while unpacked boxes always **grow** in order to
781 satisfy them -- even if this means growing larger than the box's
785 <property name="visible" type="boolean" default="true">
786 If set to [[false]], this box will be rendered as if its
787 width and height were zero. If this is a root box, the
788 associated surface will be hidden.
790 When reading from this property, the value [[false]] will
791 be returned if this box **or any of its ancestors** is not
792 visible. Thus it is possible to write [[true]] to a box's
793 [[visible]] property and then read back [[false]].
799 <section title="Layout Algorithm">
801 The size and position of every box is determined by its
802 properties, its childrens' sizes, and its parent's size and
803 position. Box layout and rendering happens in four phases:
804 **packing**, **constraining**, **placing**, and
805 **rendering**. The Core is careful to only perform a phase on
806 a box if the box has changed in a way that invalidates the work
807 done the last time that phase was performed. The packing and
808 constraining phases are performed in a single traversal of the
809 tree (packing is preorder, constraining is postorder), and the
810 placing and rendering phases are performed in a second traversal
811 of the tree (first placing, then rendering, both preorder).
813 For brevity, the rest of this chapter deals only with width and
814 columns. Height and rows is treated identically and independently.
815 Also, it is important to note that the term **minimum width** is
816 not the same thing as the property [[minwidth]], although they
819 <section title="Packing">
821 A grid of **cells** is created within the parent. If the
822 parent's [[cols]] property is set to 0, the cell grid has an
823 infinite number of columns. Either [[cols]] or [[rows]]
824 must be zero, but not both.
826 <heading title="Target Regions"/>
828 A box's target region is the portion of its parent which the
829 layout algorithm has determined that the box should occupy. A
830 box's target region is determined mainly by the value of its
833 <property name="pinned" type="box" default="null">
834 If a box's [[pinned]] property is [[null]], it is said to be
835 "unpinned" or "not pinned". In this case, the box's target
836 region will be the set of cells in its parent which it
839 If a box's [[pinned]] region is set to some other box, then
840 this box's target region will be the projection of that
841 other box's actual dimensions and position, projected onto
842 this box's parent. The net effect is that the pinned box
843 will "track" the size and position of the box it is pinned
844 to. A box may not be pinned to one of its descendants, nor
845 may boxes be pinned in a cycle (A is pinned to B, B is
846 pinned to C, and C is pinned to A).
849 If a child's [[visible]] property is [[false]], it does not
850 occupy any cells (and is not rendered). If a box's [[pinned]]
851 property (described below) is non-[[null]], it does not occupy
852 any cells and is exempt from the packing process. Otherwise,
853 each child occupies a rectangular set of cells [[child.colspan]]
854 cells wide and [[child.rowspan]] cells high.
856 The Core iterates over the cells in the grid in the following
857 order: if [[rows]] is 0, the Core iterates across each column
858 before proceeding to the next row; otherwise rows come before
859 columns. At each cell, the Core attempts to place the **first
860 remaining unplaced, packed child's** top-left corner in that
861 cell (with the child occupying some set of cells extending down
862 and to the right of that cell). If the parent has a fixed
863 number of columns and the child's [[colspan]] exceeds that
864 limit, the child is placed in column zero regardless, but only
865 occupies the available set of cells (it does not "hang off the
866 end" of the box). <image url="layout.pdf" width="1in"/>
871 <ui:box id="2" rowspan="2" />
872 <ui:box id="3" colspan="2" />
874 <ui:box id="5" colspan="2" />
880 <section title="Constraining">
881 Each box's minimum width is computed recursively as the
887 The width of its [[path]]
889 The sum of the widths of the bounding boxes enclosing its
890 children, when those children are sized to **their own**
893 The box's minimum **height** multiplied by its [[aspect]],
894 if its aspect is not [[0]] (unspecified).
897 If a box's [[hshrink]] property is set to
898 [[true]], the box's maximum width is the same as its
899 minimum width; otherwise it is the box's
903 <section title="Placing">
905 <heading title="Target Origin"/>
907 Once the box's size and the size and position of its target
908 region have been computed, the box is placed relative to its
909 **target origin**, which is determined by by the [[origin]]
912 <property name="origin" type="string" default="center">
913 Determines which corner of the box's target region should be
914 treated as the origin for layout purposes.
916 If the [[origin]] property is "[[center]]", then the
917 target origin is at the center of the target region.
919 If the [[origin]] property is "[[topleft]]",
920 "[[bottomleft]]", "[[topright]]", or "[[bottomright]]", then
921 the target origin is at the corresponding corner of the
924 If the [[origin]] property is "[[top]]", "[[bottom]]",
925 "[[right]]", or "[[left]]", then the target origin is middle
926 of the corresponding edge of the target region.
929 <property name="x y" type="number" default="0">
930 Determines the offset from the box's origin at which it will
934 If the box's [[hshrink]] property is not set, it is expanded to
935 its maximum width, but no larger than its parent's width.
937 Finally, if the child has a nonzero [[aspect]], one of its
938 dimensions (either width or height) will **grow** in order to
939 ensure that [[width == height * aspect]]. This may cause the
940 child to exceed the paren't size.
942 <heading title="Non-Packed Boxes with a transform"/>
944 First, the coordinate space in which the child is positioned is
945 translated so that the origin coincides with the
946 corner/edge/center of the box's parent corresponding to the
947 child's [[align]] property. The child's [[transform]] attribute
948 is applied to the coordinate space, and the child is positioned
949 in this transformed space with its aligment point at the origin.
951 The following diagram may be helpful:
955 <heading title="Packed Boxes"/>
957 Thoughout this section, when we refer to the [[minwidth]],
958 [[maxwidth]], or minimum width of a child box, we are referring
959 to the corresponding dimension of the child's **bounding box**
960 -- the smallest rectangle **in the parent's coordinate space**
961 that completely encloses the child's path.
963 Ibex formulates a set of constraints for placing a box's
964 **packed** children as follows:
967 A box's width can be no greater than the sum of the
970 The sum of a set of colums cannot be smaller than the
971 minimum width of a box that spans them.
973 The sum of the widths of the parents' columns will be at
974 least as large as the parent's width is (but possibly
978 Subject to these two unbreakable constraints, Ibex searches for
979 a solution which will optimize the following three goals,
980 prioritized from most important to least important:
983 (__Most Important__) The sum of all columns will be a close
984 to the parent's with as possible (ie as small as possible)
986 Ibex will attempt to make a set of columns no wider than
987 the [[maxwidth]] of a box spanning them.
989 Ibex will attempt to make all
990 columns the same width. (**least important**)
993 Each packed box is then placed within the set of cells that it
994 spans. Usually the box will exactly fill this rectangle; if it
995 does not (due to [[maxwidth]], minimum width, or aspect
996 constraints), the box's will be placed so that its alignment
997 point coincides with the alignment point of that rectangle of
1000 <heading title="The Size of the Root Box"/>
1002 When the user resizes a window, Ibex changes the root box's
1003 [[maxwidth]] and [[maxheight]] to match the size chosen by
1004 the user and then determines the root box's size using the same sizing
1005 rules it uses for other boxes.
1007 Ibex will always attempt to prevent the
1008 user from making the surface smaller than the root box's
1009 [[minwidth]] and [[minheight]]. If the [[hshrink]] or
1010 [[vshrink]] flag is set, Ibex will try to prevent the user from
1011 resizing the surface at all. However, not all platforms give Ibex
1012 enough control to do this.
1018 <!-- ----------------------------------------------------------------------- -->
1019 <section title="Box Properties">
1021 Each box is a full-fledged ECMAscript object, and can store
1022 key-value pairs as properties. Some of these keys have special
1023 meaning, which will be explained later. Each box's numeric
1024 properties hold its **child boxes**.
1026 <section title="Child Control Properties">
1028 <property name="redirect" type="box" default="thisbox">
1029 Writing to this property sets the box's redirect target. This
1030 property cannot be read from, and can only be written to if
1031 the value being written is a **descendant** of the current
1034 If a box has a non-null redirect target, reads and writes to
1035 any of the other properties in this section will be forwarded
1036 to the redirect target.
1038 The [[redirect]] attribute is very useful for hiding the
1039 internal structure of a widget, and for allowing widgets to act as
1040 "smart" containers for other widgets. For example, a menu widget might
1041 have an invisible child as its redirect target; this way, when boxes
1042 representing items on the menu are added as children of the menu
1043 widget, they do not appear until the menu is pulled down.
1046 <property name="numeric properties" type="int" default="">
1047 The **n**th child of box [[b]] can be accessed by reading from
1048 [[b[n]]]. The **n**th child can be removed by writing
1049 [[null]] to [[b[n]]] (the child will become parentless). A
1050 new child can be inserted **before** the **n**th child by
1051 writing it to [[b[n]]]; if the value written is already a child of
1052 [[b]], it will be removed from [[b]] first. It is important
1053 to note that this behavior is different from ECMAscript arrays --
1054 writing a non-[[null]] value to [[b[n]]] does not eliminate
1055 the **n**th child; it merely shifts it over one position.
1056 __Note:__ Unlike most JavaScript objects, enumerating a Box's
1057 properties with the JavaScript [[for..in]] construct will
1058 enumerate **only** the box's children and not any other properties.
1061 <property name="clip" type="boolean" default="true">
1062 If [[true]], the visual representation of this box's
1063 children will be clipped to the boundaries of this box.
1064 __Note:__ setting this property to [[false]] imposes a
1065 substantial performance penalty.
1068 <property name="numchildren" type="integer" default="0">
1069 The number of children this box has.
1073 <property name="surface" type="" default="null">
1074 If this box has a parent, this property returns
1075 [[**parent**.surface]]; otherwise it returns null.
1076 This property is a simple building block that the widget
1077 library uses to implement more complex functionality such as
1078 focus control and popups.
1083 <section title="Other Box Properties">
1085 <property name="cursor" type="string" default="null">
1086 The shape that the cursor should take when inside this
1087 box. Valid values are: "[[default]]" , "[[wait]]",
1088 "[[crosshair]]", "[[text]]", "[[hand]]", and
1089 "[[move]]", as well as resizing cursors"[[east]]",
1090 "[[west]]", "[[north]]", "[[south]]",
1091 "[[northwest]]", "[[northeast]]",
1092 "[[southwest]]", and "[[southeast]]". Note that on
1093 some platforms, resize cursors for opposite directions (such
1094 as [[northwest]] and [[southeast]] are the
1096 If a box's cursor is [[null]], its parent's cursor will
1097 be used. If the root box's cursor is null, the
1098 "[[default]]" cursor will be used.
1101 <property name="static" type="object" default="N/A">
1102 Reading from this property will return the parent scope used
1103 to execute the [[<static/>]] block of the template
1104 in which the currently-executing code resides.
1107 <property name="thisbox" type="box" default=" ">
1108 Returns a reference to the box itself.
1109 If [[null]] is written to this property, and this box is
1110 the root box of a surface, the box will be detached and the
1111 surface destroyed. If this box has a parent, it will be
1112 detached from its parent.
1115 <property name="indexof()" type="function" default=" ">
1116 This property is actually a function; invoking
1117 [[parent.indexof(child)]] will return the numerical index
1118 of [[child]] in [[parent]] if [[child]] is a
1119 child of [[parent]] (or [[parent]]'s redirect
1120 target), and [[-1]] otherwise. Writing to this property
1124 <property name="distanceto()" type="function" default=" ">
1125 This property is actually a function; invoking
1126 [[box.distanceto(otherbox)]] will return an object with two
1127 properties, [[x]] and [[y]], containing the horizontal
1128 and vertical distance between the two boxes (negative if
1129 [[otherbox]] is to the left of / above [[box]]). This
1130 can be used to determine the relative placement of two boxes
1131 on different branches of the box tree.
1136 <section title="Root Box Properties">
1138 The following special properties are only meaningful on the root box
1141 <property name="Focused">
1142 The value [[true]] is put to this property on the root box
1143 when the surface gains the input focus, and [[false]] when
1144 the surface loses the input focus. Reading from this value will
1145 return [[true]] if the surface is focused and [[false]]
1146 if it is not. Putting [[true]] to this property will
1147 **not** cause the surface to "steal" the input focus from other
1151 <property name="Maximized Minimized">
1152 The value [[true]] is put to this property on the root box
1153 when the surface is maximized/minimized, and [[false]] when
1154 the surface is un-maximized/minimized. Reading from this value
1155 will return [[true]] if the surface is maximized/minimized and
1156 [[false]] if it is not. Putting [[true]] to this property will
1157 maximize/minimize the window, and putting [[false]] to this
1158 property will unmaximize/unminimize the window.
1160 Note that not all platforms support maximization.
1163 <property name="Close">
1164 When the user attempts to close a surface, the value
1165 [[true]] will be put to this property. Scripts may trap
1166 this property to prevent the window from closing. Putting the
1168 [[true]] to this property on a root box has the same
1169 effect as putting [[null]] to the [[thisbox]]
1173 <property name="titlebar">
1174 The surface's titlebar text and icon. If a string is written
1175 to this property, the surface's titlebar text is set to that
1176 string; if a stream yielding an image is written, the
1177 surface's icon is set to that image. Note that not all
1178 platforms support this property. Only ASCII characters
1179 0x20-0x7F are permitted.
1187 <section title="Events">
1189 Every execution of the Event Context begins with an event, which
1190 consists of a key/value pair, and a mouse position, which consists of
1191 an x and y coordinate. The possible keys are [[_Press[1-3]]],
1192 [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]],
1193 [[_Move]], [[_KeyPressed]], and [[_KeyReleased]].
1195 Here are two example events:
1197 An event is triggered by writing the key to the value on a box. This
1198 triggers any trap handlers which may be present. Once these handlers
1199 have executed, Ibex figures out which child of the current box contains
1200 the mouse (taking into account that some boxes may cover up others)
1201 and writes the key and value to that box. If none of the box's
1202 children contain the mouse position, Ibex removes the leading
1203 underscore from the key name and writes the value to
1204 **that** property. Once all the traps on that property have
1205 executed, the value is written to the box's parent.
1207 Intuitively, Ibex delivers the underscored event to every box from the
1208 root to the target, and then delivers the non-underscored event to
1209 that same set of boxes in reverse order. So the event travels down
1210 the tree to the target, and then back up to the root. The following
1211 example prints out "first second third fourth" in that order.
1215 _Press1 ++= function(b) { ibex.log.info("first"); }
1216 Press1 ++= function(b) { ibex.log.info("fourth"); }
1218 _Press1 ++= function(b) { ibex.log.info("second"); }
1219 Press1 ++= function(b) { ibex.log.info("third"); }
1224 In general, you should use the **non-underscore** names to respond
1225 to user input and use the underscored names when you want to override
1226 child boxes' behavior or route events to particular boxes (for
1227 example, when implementing a focus protocol). This is why the
1228 underscored elements are delivered to parents before children (so
1229 parents can override their childrens' behavior), but non-underscored
1230 events are delivered to children before parents (since, visually, a
1231 mouse click is usually "intended" for the leaf box underneath the
1234 <heading title="Stopping the Process"/>
1236 At any point in this sequence, a trap handler can choose not to
1237 cascade (by returning [[true]] from the trap handler function).
1238 This will immediately cease the propagation of the event. This is how
1239 you would indicate that an event has been "handled".
1241 <heading title="Non-Propagating Events"/>
1243 Ibex uses the following events to notify a box about changes that
1244 only matter to that particular box. These events do not propagate
1245 either up or down the tree.
1247 <property name="Enter Leave">
1248 The value [[true]] is written to this property when the mouse (enters/leaves) the box.
1251 <property name="SizeChange">
1252 The value [[true]] is put to this property after the size
1253 of this box changes.
1256 <property name="ChildChange">
1257 When a child is added or removed, that child is written to
1258 this property. The write is always performed **after** the
1259 addition or removal, so these two cases can be distinguished
1260 by checking [[indexof(child)]].
1262 Note that if the parent's redirect target is set to another
1263 box, this trap will only be invoked when children are
1264 manipulated by reading and writing to the parent. Reads and
1265 writes directly to the redirect target will **not** trigger
1268 Note also that this traps is still triggered if a box's
1269 [[redirect]] target is **null**. This is useful for
1270 boxes that need to accept children and then relocate them
1274 <section title="Listing of Events">
1276 <property name="Press1 Press2 Press3">
1277 Indicates that the use has pressed a mouse button. On
1278 platforms with three mouse buttons, the **middle** button
1279 is button 3 -- this ensures that applications written to only
1280 use two buttons (1 and 2) will work intuitively on three button
1284 <property name="Release1 Release2 Release3">
1285 Indicates that the use has released a mouse button.
1288 <property name="Click1 Click2 Click3">
1289 Indicates that the user has pressed and released the
1290 mouse button without moving the mouse much (exactly how
1291 much is platform-dependent).
1294 <property name="DoubleClick1 DoubleClick2 DoubleClick3">
1295 Indicates that the user has clicked the
1296 mouse button twice within a short period of time (exactly how long is platform-dependent).
1299 <property name="Move">
1300 Indicates that the mouse has moved while within this box, or that
1301 the mouse while outside this box **if a button was pressed while within this box and has not yet been released**
1304 <property name="KeyPressed KeyReleased">
1306 A string is written to this property when a key is pressed or
1307 released If the key was any other key, a multi-character
1308 string describing the key will be put. For simplicity, we use
1309 the VK_ constants in the <link
1310 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1311 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1312 key is pressed or released, the string put will be the portion
1313 of its VK_ constant after the underscore, all in lower case.
1316 If the shift key was depressed immediately before the
1317 event took place, then the string will be capitalized. Special
1318 keynames are also capitalized; shift+home is reported as
1319 "[[HOME]]". Symbols are capitalized as they appear on the
1320 keyboard; for example, on an American QWERTY keyboard, shift+2
1321 is reported as "[[@]]".
1323 If the alt, meta, or command key was depressed immediately
1324 before this key was pressed, then the string will be prefixed
1325 with the string "[[A-]]". If the control key was depressed
1326 while this key was pressed, then the string will be prefixed
1327 with the string "[[C-]]". If both alt and control are
1328 depressed, the string is prefixed with "[[C-A-]]".
1330 Ibex does not distinguish between a key press resulting from
1331 the user physically pushing down a key, and a 'key press'
1332 resulting from the keyboard's typematic repeat. In the rare
1333 case that an application needs to distinguish between these
1334 two events, it should watch for KeyReleased messages and
1335 maintain an internal key-state vector.
1339 <section title="Re-routing events">
1341 At any point in the Event Context, you can write to the [[mouse]]
1342 property on any box. The value written should be an object with two
1343 properties, [[x]] and [[y]]. For example:
1346 _Press1 ++= function(p) {
1347 mouse = { x: 32, y: 77 };
1351 The coordinates specified are relative to the box whose [[mouse]]
1352 property is being written to. There is no need to supply the
1353 [[inside]] property; it is computed automatically. Writing to
1354 the [[mouse]] property causes Ibex to recompute the eventual
1355 target box, and also alter the values returned by [[mouse.x]],
1356 [[mouse.y]], and [[mouse.inside]] for any **descendants**
1357 of the current box. Writing to the [[mouse]] property also
1358 automatically prevents the event from returning to the box's parents
1359 -- it is equivalent to not cascading on the non-underscored event.
1360 This ensures that child boxes cannot trick their parent boxes into
1361 thinking that the mouse has moved.
1363 If you want the event to "skip over" the boxes between the trapee
1364 and the target, or if you want to re-route an event to a box which
1365 is not a descendant of the current box, simply write the value to
1366 the proper key on the target box.
1370 _KeyPressed = function(k) { ibex.log.info("first"); }
1371 KeyPressed = function(k) { ibex.log.info("sixth"); }
1372 $recipient.target = $target;
1373 <ui:box id="recipient">
1374 _KeyPressed = function(k) {
1375 ibex.log.info("second");
1376 thisbox.target.KeyPressed = k;
1377 // inhibit cascade; keep event from going to $excluded
1380 KeyPressed = function(k) { ibex.log.info("fifth"); }
1381 <ui:box id="excluded">
1382 _KeyPressed = function(k) {
1383 ibex.log.info("this never happens");
1387 <ui:box id="target">
1388 _KeyPressed = function(k) { ibex.log.info("third"); }
1389 KeyPressed = function(k) { ibex.log.info("fourth"); }
1396 <section title="Synthesizing Your Own Events">
1398 You can create "fake events" by simply writing to the [[mouse]]
1399 property and then writing a value to one of the underscored properties
1400 on a box. This will have exactly the same effect as if the use had
1401 actually pressed a key, clicked a button, or moved the mouse -- they
1402 are indistinguishable.
1409 <section title="Ibex Base Services">
1410 <!-- ----------------------------------------------------------------------- -->
1411 <section title="Streams">
1413 <heading title="Every object has a stream..."/>
1415 Every object has a **stream** associated with it. A stream is a
1416 sequence of bytes that can be read or written to.
1418 By default an object has an empty stream (zero bytes). However, some objects
1419 (returned from special methods on the [[ibex]] object) have
1420 streams yielding data read from an url, file, or a component of a zip
1421 archive. In a future release, the stream associated with a box will
1422 be an .ibex template which, when applied, will fully reconstitute the
1425 <heading title="...but streams are not objects"/>
1427 Despite the ubiquity of streams, you cannot actually reference a
1428 stream, since it is not an object. Instead, you simply reference the
1429 object it belongs to. If you are familiar with Java, this is similar
1430 to how every Java object has a monitor associated with it, but you
1431 cannot directly manipulate the monitor (you can't pass around a
1432 reference to just the monitor).
1434 In the rest of the section we will sometimes refer to "getting
1435 properties from a stream" or "passing a stream to a function"; this is
1436 just shorthand for saying to perform those actions on the object the
1439 <section title="Creating Streams from URLs">
1441 You can create a stream from a URL by calling
1444 var r = ibex.stream.url("http://...");
1447 This will return an object whose stream draws data from the specified
1448 URL. Streams are loaded lazily whenever possible.
1452 <section title="Getting Substreams">
1454 Most stream objects let you access
1455 substreams using the usual JavaScript operators [[[]]] and
1456 [[.]], as well as the [[for..in]] syntax.
1459 // r1 and r2 are equivalent but not equal (!=)
1460 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1461 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1466 <section title="The Root Stream">
1468 The empty-string property on the [[ibex]] object is called the
1469 **root stream**. You can access this object as [[ibex..]] or
1470 [[ibex[""]]]. Additionally, any expression which starts with a
1471 dot is treated as property to be retrieved from the root stream. The
1472 following three expressions are equivalent:
1482 <section title="Static Blocks">
1486 You can access variables within the static block of a template by
1487 appending a double period ([[..]]) and the variable name to the
1488 stream used to load that template:
1491 <!-- org/ibex/themes/linux/scrollbar.ibex -->
1495 ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
1500 <section title="Formatting Streams">
1502 If you attempt to send a stream as part of an XML-RPC call, the
1503 stream will be read in its entirity, Base64-encoded, and transmitted
1504 as a [[<base64/>]] element.
1506 Ibex supports two special URL protocols. The first is [[data:]],
1507 which inteprets the rest of the URL as a Base64 encoded sequence of
1508 bytes to use as a source. The other is [[utf8:]] which
1509 interpretets the rest of the string as a Unicode character sequence to
1510 be UTF-8 encoded as a string of bytes to use as a source.
1513 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1514 var r6 = ibex.stream.url("utf8:this is a test");
1517 You can read a UTF-8 encoded string from a stream like this:
1520 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
1522 You can also parse XML from a stream using SAX like this:
1525 ibex.stream.xml.sax(
1526 ibex.stream.url("http://foo.com/foo.xml"),
1527 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1528 endElement : function(tagname) { ... },
1529 content : function(contentString) { ... }
1530 whitespace : function(whitespaceString) { ... }
1538 <!-- ----------------------------------------------------------------------- -->
1539 <section title="The Ibex object">
1541 The [[ibex]] object is present in the top-level scope of every
1542 script. It has the following properties:
1544 <heading title="General"/>
1546 <property name="ibex.box">
1547 reading from this property returns a new box
1549 <property name="ibex.clone(o)">
1550 creates a clone of object
1552 <property name="ibex.bless(s)">
1553 returns a blessed clone of stream
1556 <heading title="ECMA Library Objects"/>
1558 <property name="ibex.date">
1559 reading from this property returns a new date
1561 <property name="ibex.math">
1562 this object contains the ECMA math functions
1564 <property name="ibex.regexp(s)">
1565 return a regexp object corresponding to string **s**
1567 <property name="ibex.string">
1568 this object contains the ECMA string manipulation functions
1571 <heading title="Logging"/>
1573 <property name="ibex.log.debug(m1, ... mn)">
1574 log the debug messages **m1** through **mn**.
1578 <property name="ibex.log.info(m1, ... mn)">
1579 log the info messages **m1** through **mn**.
1582 <property name="ibex.log.warn(m1, ... mn)">
1583 log the warning messages **m1** through **mn**.
1586 <property name="ibex.log.error(m1, ... mn)">
1587 log the error messages **m1** through **mn**.
1590 <heading title="User Interface"/>
1592 <property name="ibex.ui.browser(u)">
1593 opens a new browser window with URL **u**
1596 <property name="ibex.ui.key.control">
1597 true if the control key is depressed
1600 <property name="ibex.ui.key.shift">
1601 true if the shift key is depressed
1604 <property name="ibex.ui.key.alt">
1605 true if the alt key is depressed
1608 <property name="ibex.ui.key.name.alt">
1609 the name of the "alt" key (usually either "alt", "meta", or
1613 <property name="ibex.ui.clipboard">
1614 the contents of the clipboard; can be read and written to
1617 <property name="ibex.ui.maxdim">
1618 the maximum dimension of any UI element; usually
1619 2<sup>31</sup>, but may be smaller
1622 <property name="ibex.ui.screen.width">
1623 the width of the screen, in pixels
1626 <property name="ibex.ui.screen.height">
1627 the height of the screen, in pixels
1630 <property name="ibex.ui.mouse.button">
1631 either 0, 1, 2, or 3, indicating the mouse button currently
1635 <property name="ibex.ui.frame">
1636 when a box is written to this property, it becomes the root
1640 <property name="ibex.ui.window">
1641 when a box is written to this property, it becomes the root
1645 <property name="ibex.ui.font.serif">
1646 an object whose stream is a a builtin serif font
1649 <property name="ibex.ui.font.sansserif">
1650 an object whose stream is a builtin sans-serif font
1653 <property name="ibex.ui.font.monospace">
1654 an object whose stream is a a builtin fixed-width font
1657 <heading title="Networking"/>
1659 <property name="ibex.net.rpc.xml(u)">
1660 return an XML-RPC call object with endpoint URL **u**
1663 <property name="ibex.net.rpc.soap(u,">
1664 return a SOAP call object with endpoint URL **u**,
1665 SoapAction **a**, and XML Namespace **n**
1668 <heading title="Threads"/>
1670 <property name="ibex.thread">
1671 when a function is written to this property, a new thread is
1675 <property name="ibex.thread.yield()">
1676 yield the current thread
1679 <property name="ibex.thread.sleep(n)">
1680 sleep for **n** milliseconds
1683 <heading title="Streams"/>
1685 <property name="ibex.stream.url(u)">
1686 returns a new object whose stream is drawn from URL **u**
1689 <property name="ibex.stream.unzip(s)">
1690 unpacks a zip archive from **s**'s stream
1693 <property name="ibex.stream.uncab(s)">
1694 unpacks a cab archive from **s**'s stream
1697 <property name="ibex.stream.cache(s,k)">
1698 valign=top>wraps a disk-backed read cache keyed on **k**
1699 around **s**'s stream
1702 <property name="ibex.stream.watch(s,f)">
1703 returns an object whose stream is drawn from **s**'s
1704 stream, but invokes **f(n,d)** as it is read from.
1707 <property name="ibex.stream.parse.xml(s, h)">
1708 Use SAX to parse the XML document on stream **s** with
1712 <property name="ibex.stream.parse.html(s, h)">
1713 Same as [[parse.xml()]], but tries to fix broken HTML.
1716 <property name="ibex.stream.parse.utf8(s)">
1717 treat **s**'s stream as a string encoded as a UTF-8 byte stream and return the string
1720 <property name="ibex.stream.homedir">
1721 [[ibex.stream.tempdir]]
1724 <heading title="Cryptography"/>
1726 <property name="ibex.crypto.rsa(k,s)">
1727 **not implemented yet:** return a
1728 stream which rsa-decrypts stream **s** with key **k**
1731 <property name="ibex.crypto.rc4(k,s)">
1732 **not implemented yet:** return a
1733 stream which rc4-decrypts stream **s** with key **k**
1736 <property name="ibex.crypto.md5(s)">
1737 **not implemented yet:** immediately
1738 MD5-hash stream **s**
1741 <property name="ibex.crypto.sha1(s)">
1742 **not implemented yet:** immediately
1743 SHA1-hash stream **s**
1747 <!-- ----------------------------------------------------------------------- -->
1748 <section title="Traps">
1750 You can add a trap to a property by applying the [[++=]] operator
1751 to a function with one argument. The trap will be invoked whenever
1752 that property is written to.
1756 foo ++= function(z) {
1757 ibex.log.info("foo is " + z);
1762 If another script were to set the property "[[foo]]"
1763 on the box above to the value [[5]], the function above would be
1764 invoked with the argument [[5]]. The function would then log
1765 the string "[[foo is 5]]".
1767 Within a trap, the expression [[trapee]] can be used to
1768 get a reference to the box on which the trap was placed.
1770 The expression [[trapname]] returns the name of the
1771 trap executing the current function. This is useful when a function
1772 is applied to multiple traps. For example:
1776 func ++= function(z) {
1777 ibex.log.info("called trap " + trapname);
1784 <section title="Removing Traps">
1786 You can remove a trap by using the [[--=]] operator with the same
1787 function you added as a trap:
1791 var myfunc = function(z) { /* ... */ }
1802 <heading title="Multiple Traps on the Same Property"/>
1804 When the trapped property is **written** to, each of the trap
1805 functions placed on it will be invoked in the opposite order that
1806 they were placed on the box -- the most recently placed trap will
1807 execute first. This last-to-first execution of traps is called
1808 **cascading**. After the last trap is invoked, the value is
1809 stored on the box (remember, boxes are objects, so they can hold
1810 properties just like all other ECMAscript objects).
1812 <section title="Manual Cascades">
1814 There are two additional tricks you can use when placing traps. The
1815 first is a **manual cascade**. If you want to cascade to lower
1816 traps in the middle of a function, or you want to cascade with a
1817 different value than the value passed to you (in effect "lying" to
1818 lower traps), you can use [[cascade]]. For example:
1821 <ui:box color="black">
1822 color ++= function(c) {
1823 ibex.log.info("refusing to change colors!");
1829 This effectively creates a box whose color cannot be changed, and
1830 which complains loudly if you try to do so.
1832 Do **not** try to do something like this:
1835 <ui:box color="black">
1836 color ++= function(z) {
1837 color = "black"; // INFINITE LOOP! BAD!!!
1841 To prevent automatic cascading, return [[true]] from your function:
1844 <ui:box color="black">
1845 color ++= function(z) {
1846 return true; // the box's color will not change
1853 <section title="Read Traps">
1855 The other trick is a **read-trap**. Read traps are just like normal
1856 traps, except that you use a function that takes zero arguments instead of one. Read traps
1857 also do not automatically cascade.
1861 doublewidth [[++=]] function() { return 2 * width; }
1865 If another script attempts to read from the [[doublewidth]]
1866 property on this box, the value it gets will be twice the actual width
1867 of the box. Note that
1868 the actual [[doublewidth]] property on the box never gets written
1869 to, since the trap does not cascade.
1871 You can manually cascade on read traps as well:
1875 text [[++=]] function() { return "my text is " + cascade; }
1879 Read traps are only rarely needed -- most of the time a write trap
1884 <heading title="Prohibited Traps"/>
1886 To prevent confusing and hard-to-debug behaviors, scripts may not
1887 place traps on any of the properties described in the sections
1888 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1889 section="Child-Control Properties"/>, or <link section="Other Box
1890 Properties"/> except for [[childadded]],
1891 [[childremoved]] and [[surface]]. FIXME: remove?
1893 <heading title="Exceptions and Traps"/>
1895 If an uncaught exception is thrown from a trap, Ibex will log the
1896 exception, but will **not** propagate it to the code which
1897 triggered the trap. If the trap was a read trap, the value
1898 [[null]] will be returned.
1899 FIXME: is this right?
1901 <heading title="Architectural Significance of Traps"/>
1903 Traps are the backbone of Ibex. Since almost all UI programming is
1904 event/demand driven, traps eliminate the need for separate
1905 member/getter/setter declarations, often cutting the amount of typing
1906 you have to do to a third of what it would normally be.
1908 <section title="Cloning">
1910 **Cloning** is a companion technique for traps; together they can
1911 be used to simulate any sort of environment you might need. When you
1912 call [[ibex.clone(o)]], Ibex returns a new object (called the
1913 **clone**) which compares with equality ([[==]]) to the
1914 original object. Furthermore, both objects are "equal" as keys in
1919 var theclone = ibex.clone(o);
1921 ibex.log.info(hash[theclone]); // prints "5"
1924 Any writes to properties on the clone will actually write to
1925 properties on the original object, and reads from properties on the
1926 clone will read properties on the original object. In fact, the only
1927 thing that can be used to distinguish the original from the clone is
1928 traps -- a trap placed on the clone is **not** placed on the
1929 original object as well.
1934 <section title="Contexts">
1936 From the perspective of an application writer, Ibex is strictly
1937 single-threaded. Ibex is always in exactly one of the following three
1940 <list type="unordered">
1942 __Rendering Context__ -- (redrawing the screen)
1944 __Event Context__ (executing javascript traps triggered by an event)
1946 __Thread Context__ (executing a background thread spawned with [[ibex.thread]])
1950 There are two important restrictions on what can be done in particular contexts:
1952 <list type="unordered">
1954 The [[box.mouse]] property and its subproperties
1955 ([[x]], [[y]], and [[inside]]) can only be read
1956 from within the Event Context, or in a thread context
1957 **after** a the [[box.mouse]] property on this box or
1958 an ancestor box has been written to.
1960 Blocking operations (anything that accesses the network or
1961 disk) can only be performed in the Thread Context.
1967 <section title="Background Threads">
1969 Ibex offers easy access to threads. Spawning a background thread is as
1970 simple as writing a function to the [[ibex.thread]] property:
1973 ibex.thread = function() {
1974 ibex.log.info("this is happening in a background thread!");
1978 The argument set passed to the function is currently undefined and is
1979 reserved for use in future versions of Ibex. Scripts should not
1980 depend on the number or content of these arguments.
1982 Ibex is **cooperatively multitasked**, so threads must not process
1983 for too long. This was a deliberate choice; cooperatively
1984 multitasked environments do not require complex locking primitives
1985 like mutexes and semaphores which are difficult for novices to
1986 understand. The disadvantage of cooperative multitasking is that one
1987 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1988 first, all blocking I/O operations **automatically** yield the CPU,
1989 so the overall user interface never becomes unresponsive because it is
1990 waiting for a disk or network transfer. Second, since Ibex is strictly
1991 a user interface platform, Ibex scripts are unlikely to perform highly
1992 compute-intensive operations that keep the CPU busy for more than a
1997 <!-- ----------------------------------------------------------------------- -->
1998 <section title="Networking">
2000 <section title="XML-RPC">
2002 XML-RPC objects can be created by calling [[ibex.net.rpc.xml(**XML-RPC
2003 URL**)]], and then invoking methods on that object. For example,
2006 Press1 += function(v) {
2007 ibex.thread = function() {
2008 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
2009 color.getTodaysColor("Friday");
2014 When the user clicks the first mouse button on this box, it will
2015 contact the server [[xmlrpc.ibex.org]], route to the
2016 [[/RPC2/]] handler and invoke the [[getTodaysColor()]]
2017 method on the [[color]] object with a single string argument
2018 "[[Friday]]". The return value will be used to change the color
2019 of the box the user clicked on.
2021 Note that in this example we spawned a background thread to handle the
2022 request -- the [[Press1]] event is delivered in the foreground
2023 thread, and XML-RPC methods may only be invoked in background
2024 threads. This is to prevent the UI from "locking up" if the server
2025 takes a long time to reply.
2027 If the XML-RPC method faults, an object will be thrown with two
2028 properties: [[faultCode]] and [[faultString]], as defined in
2029 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
2030 Ibex encounters a network, transport, or session-layer error, it will
2031 throw a [[String]] object describing the error in a
2032 human-readable format. Scripts should not rely on the contents of
2033 this string having any special structure or significance.
2035 If an object with an associated non-empty stream is passed as an
2036 argument to an XML-RPC method, it will be sent as a <base64/>
2037 element. If a <base64/> element is found in the XML-RPC reply, it
2038 will be returned as an object with a stream drawn from that byte sequence.
2040 Each object returned by [[ibex.net.rpc.xml()]] represents a
2041 single HTTP connection. The connection will be held open until
2042 the object is garbage collected or the server closes the
2043 connection. If a second call is issued on the object before the
2044 first one returns (usually from a seperate thread), the two calls
2046 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
2047 text="pipelined"/>. This can dramatically improve performance.
2049 Ibex supports HTTP Basic and Digest authentication. To use
2050 authentication, pass [[ibex.net.rpc.xml()]] a URL in the form
2053 http[s]://user:password@hostname/
2056 Ibex will use Digest authentication if the server supports it;
2057 otherwise it will use Basic authentication. Please be aware that
2058 many XML-RPC server implementations contain a <link
2059 url="http://www.ibex.org/faq.html#auth" text="broken
2060 implementation of Basic authentication"/>.
2064 <section title="SOAP">
2066 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
2068 <list type="ordered">
2070 [[ibex.net.rpc.soap()]] is used instead of
2071 [[ibex.net.rpc.xml()]]
2073 Instead of specifying just the URL of the service itself, you
2074 must specify the URL, the SOAPAction argument, and the
2077 The actual method invocation takes only one argument, which
2078 must be an object. This is necessary since SOAP arguments are
2079 specified by name, rather than ordering.
2083 SOAP faults are handled the same way as XML-RPC faults except that the
2084 capitalization of the [[faultstring]] and [[faultcode]]
2085 members is all lower-case, to match the SOAP spec. Here is a
2089 Press1 ++= function(v) {
2090 ibex.thread = function() {
2091 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
2093 "http://ibex.org/namespace"
2094 ).color.getTodaysColor( {
2101 As you can see, SOAP is much more verbose, yet does not offer
2102 substantially improved functionality. We recommend that XML-RPC be
2103 used whenever possible, and that SOAP be reserved for legacy
2106 The current Ibex SOAP stack does not support 'document style' or
2107 multi-ref ([[href]]) data structures.
2111 <section title="Security">
2113 Applications downloaded from the network (as opposed to those loaded
2114 from the filesystem) may only make certain kinds of connections to
2115 certain hosts. See Appendix A for a detailed description of the
2121 <!-- ----------------------------------------------------------------------- -->
2122 <section title="Error Handling">
2124 If the Ibex Core encounters an error while servicing a function call
2125 originating in JavaScript, the core will throw a string consisting of
2126 an error code followed by a colon, a space, and a descriptive message.
2130 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
2133 The code should be used to determine how the program should respond to
2134 an error. The codes are organized in a hierarchy, so the
2135 string.startsWith() method can be used to determine if an error lies
2136 within a particular subhierarchy. The descriptive message portion of
2137 the string may be shown to the user.
2139 <property name="ibex.assertion.failed">
2142 <property name="ibex.io">
2143 General I/O exceptions
2145 <property name="ibex.io.encoding">
2146 Error translating between character encodings.
2148 <property name="ibex.io.zip">
2149 Attempted to access a corrupt zip archive.
2151 <property name="ibex.io.eof">
2152 End of file encountered unexpectedly
2154 <property name="ibex.net.security.prohibitedHost">
2155 A piece of untrusted Ibex code attempted to contact a
2156 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
2158 <property name="ibex.net.dns.temporaryFailure">
2159 An attempt to resolve a hostname failed but it is not known
2160 for certain that the hostname is invalid.
2162 <property name="ibex.net.dns.unknownHost">
2163 An attempt to resolve a hostname failed because the hostname
2166 <property name="ibex.net.socket.closed">
2167 A socket was closed unexpectedly.
2169 <property name="ibex.net.socket.connectionFailed">
2170 A connection could not be made to the remote host.
2172 <property name="ibex.net.url.malformed">
2173 Tried to parse a malformed URL.
2175 <property name="ibex.net.ssl">
2176 General SSL protocol errors.
2178 <property name="ibex.net.ssl.untrustedCertificate">
2179 The server's certificate was not signed by a CA trusted by Ibex.
2181 <property name="ibex.net.http.">
2182 Thrown when an HTTP error code is returned during an
2183 operation. The three characters [[**xyz**]] will be
2184 the three-digit HTTP status code.
2186 <property name="ibex.net.xmlrpc.null">
2187 The caller attempted to transmit the [[null]] value via XML-RPC.
2189 <property name="ibex.net.xmlrpc.circular">
2190 The caller attempted to transmit a circular data structure via XML-RPC.
2192 <property name="ibex.net.xmlrpc.specialObject">
2193 The caller attempted to transmit a "special" object via
2194 XML-RPC (for example, a Box or the Ibex object).
2196 <property name="ibex.null.put">
2197 A JavaScript attempted to put to a property on the [[null]] value
2199 <property name="ibex.null.get">
2200 A JavaScript attempted to get from a property on the [[null]] value
2202 <property name="ibex.null.call">
2203 A JavaScript attempted to call the [[null]] value
2206 If an exception is thrown inside a trap, the exception will propagate
2207 to the script that triggered the trap.
2209 If an uncaught exception is thrown while applying a template, or the
2210 requested template could not be found, an error will be logged and the
2211 box to which the template was being applied will be made invisible
2212 ([[visible = false]]). This ensures that half-applied widgets are
2213 never shown to the user.
2218 <section title="Ibex self-emulation">
2220 When the core first starts up, it clones the [[ibex]] object,
2221 creates a stream for the initial .ibex, and then places a trap on the
2222 cloned [[ibex]] object so that its empty-string property returns
2223 the .ibex stream. The cloned Ibex object is then passed as the third
2224 (optional) argument to [[ibex.apply()]], making it the default
2225 [[ibex]] object for the scripts that are executed as part of the
2226 template instantiation.
2229 var new_ibex = ibex.clone(ibex);
2230 var stream = ibex.bless(ibex.stream.url("http://..."));
2231 new_ibex[""] ++= function() { return stream; }
2232 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2235 Note that we called [[ibex.bless()]] on the stream before tacking
2236 it on to the new Ibex object. The bless function returns a clone of
2237 the object passed to it, with a few traps which are explained below.
2238 Additionally, any sub-streams retrieved by accessing properties of the
2239 blessed stream will also automatically be blessed (blessed streams are
2242 Blessing a stream serves three purposes:
2244 <list type="unordered">
2246 Blessed clones always return the appropriate static block when
2247 their empty property is accessed; this ensures that references
2248 to the static blocks of other templates work properly.
2250 Blessed substreams can return their parent stream by accessing
2251 a hidden property which is reserved for internal use by Ibex.
2252 This ensures that Ibex can automatically add filename
2253 extensions where needed, according to the following rules:
2256 If the stream is a template to be applied, the string
2257 "[[.ibex]]" is appended.
2259 If the stream is an image, the string "[[.png]]" is
2260 appended. If no stream is found, "[[.jpeg]]" and
2261 "[[.gif]]" are tried, in that order.
2263 If the stream is an font, the string "[[.ttf]]" is
2267 Every call to [[ibex.bless()]] returns a different object
2268 (which happens to be a clone of the object passed to it) with
2269 a completely separate set of static blocks.
2273 Ibex can self-emulate by using [[ibex.clone()]] on the Ibex object;
2274 this technique is very similar to the use of ClassLoaders in
2275 Java. This is useful for a number of applications, including
2276 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2277 others. For example:
2280 var newLoadFunction = function(url) { /* ... */ };
2281 var new_ibex = ibex.clone(ibex);
2282 new_ibex.load ++= function() { return newLoadFunction; }
2283 ibex.apply(ibex.box, .main, new_ibex);
2288 <!-- ----------------------------------------------------------------------- -->
2289 <appendix title="Security Architecture and Considerations">
2291 Due to the expense and hassle imposed by the commercial PKI code
2292 signing architecture, and the fact that it <link
2293 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2294 really provide any security anyways"/>, Ibex user interfaces are
2295 distributed as unsigned, untrusted code. As such, they are handled
2296 very carefully by the Ibex Core, and assumed to be potentially
2299 Ibex's security architecture is divided into defenses against four
2300 major classes of attacks:
2302 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2304 Ibex user interfaces are run in an extremely restrictive sandbox. The
2305 environment does not provide primitives for accessing any data outside
2306 the Ibex core except via XML-RPC and SOAP calls. There are no
2307 facilities to allow Ibex user interfaces to access the client's
2308 operating system or to interact with other applications on the same
2309 host (unless they provide a public XML-RPC or SOAP interface).
2310 An Ibex script may only access a file on the user's hard disk if the
2311 user explicitly chooses that file from an "open file" or "save file"
2312 dialog. There is one exception to this rule: if all templates
2313 currently loaded in the Ibex core originated from the local
2314 filesystem, those templates can load additional .ibexs from the local
2317 The Ibex Core is written in Java, so it is not possible for
2318 scripts to perform buffer overflow attacks against the core
2321 Ibex applications may only read from the clipboard when the user
2322 middle-clicks (X11 paste), presses control-V (Windows paste), or
2323 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2324 "alt"). This ensures that Ibex applications are only granted access to
2325 data that other applications have placed on the clipboard when the user
2326 specifically indicates that that information should be made available
2327 to the Ibex application.
2329 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2331 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2332 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2333 regular TCP sockets.
2335 Ibex will not allow a script to connect to a non-public IP address
2336 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2337 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2338 1918"/>). There is one exception -- if all templates currently loaded
2339 in the core originated from the same IP address, those scripts may
2340 make calls to that IP address regardless of whether or not it is
2341 firewalled. If Ibex does not have access to a DNS resolver (because it
2342 is using a proxy which performs DNS lookups), Ibex will provide the
2343 proxy with the appropriate <link
2344 url="http://www.ibex.org/x-requestorigin.html"
2345 text="X-RequestOrigin"/> header that the proxy needs in order
2346 to maintain security.
2348 The only remaining possible attack is against a XML-RPC or SOAP
2349 service running on a firewalled host with a public address. Assigning
2350 such machines public IP addresses is a poor network security policy,
2351 and doing so squanders scarce public IPv4 addresses. As such, the onus
2352 is on the administrators of such machines to explicitly block access
2353 to clients reporting a [[User-Agent:]] header beginning with the
2354 four characters "[[IBEX]]".
2356 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2358 All top-level windows created by Ibex are **scarred** -- a stripe
2359 and a lock is drawn across the corner of the window. There is no way
2360 for a user interface to remove this scar. Ibex user interfaces may not
2361 create windows smaller than the size of the scar.
2363 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2365 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2366 for encryption. Ibex will attempt 128-bit encryption, but will
2367 negotiate down to 40-bit if the server does not support strong
2368 crypto. Ibex's SSL implementation is currently provided by <link
2369 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2370 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2373 All HTTPS connections must be authenticated by the server using a
2374 certificate whose name matches the domain name of the HTTPS URL. The
2375 certificate must be signed by a trusted root CA. Ibex trusts the same
2376 93 root CAs whose certificates are included as "trusted" in Microsoft
2377 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2378 against man-in-the-middle attacks; you should not trust this
2379 connection with any data you would not normally trust an SSL-enabled
2384 <!-- ----------------------------------------------------------------------- -->
2385 <appendix title="ECMAscript compliance">
2387 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2388 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2391 <section title="Omissions">
2393 The following ECMA features are not supported:
2395 <list type="unordered">
2397 The [[undefined]] value, [[===]], and [[!==]]
2399 The [[new]] keyword (and ECMAScript object inheritance)
2402 [[getter]] and [[setter]]
2404 The ECMA [[this]] keyword.
2406 The [[String]], [[Number]], and [[Boolean]]
2407 classes. Note that [[string]], [[number]], and
2408 [[boolean]] values are supported, however.
2410 You may not [[throw]] the [[null]] value.
2414 Additionally, you must declare all root-scope variables (with
2415 [[var]]) before using them; failure to do so will result in an
2416 exception. Box properties are pre-defined in the scope that scripts
2421 <section title="Extensions">
2423 <list type="unordered">
2425 The token [[..]] is equivalent to [[[""]]].
2431 Extended [[catch]] syntax. The following code:
2433 } catch(e propname "foo.bar.baz") {
2440 if (e.propname != null and e.propname >= "foo.bar.baz" and
2441 "foo.bar.baz/" > e.propname) {
2446 Multiple extended-catch blocks can appear at the end of a single try
2447 block. However, at most one non-extended catch block may appear, and
2448 if it does appear, it must be the last one.
2450 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2451 "[[lt]]" is be interpreted as [[<]], the lexical
2452 token "[[gt]]" is be interpreted as [[>]], and the
2453 token "[[and]]" is interpreted as [[&&]].
2454 Thus these tokens cannot be used as variable names.
2456 The identifier [[static]] is a reserved word in
2457 ECMAScript, but not in Ibex.
2459 Ibex defines an additional reserved word, "[[assert]]",
2460 which will evaluate the expression which follows it, throwing
2461 a [[ibex.assertion.failed]] exception if the expression
2462 evaluates to [[false]].
2464 To ensure that Ibex files appear the same in all text editors, tab
2465 characters are not allowed in Ibex files.
2469 Some useful tutorials include:
2471 <list type="unordered">
2474 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2475 text=" JavaScript 1.2 Reference"/>. Although this document is
2476 out of date, it is arguably the best guide available for free
2477 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2478 r1) to 1.5 were minimal, and many of them were <link
2479 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2482 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2483 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2484 and Paula Ferguson. The latest edition of this book covers
2485 JavaScript 1.5 (ECMA-262 r3).
2488 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2489 text="ECMA-262"/> specification. This is an extremely
2496 <!-- ----------------------------------------------------------------------- -->
2497 <appendix title="Logging and Command Line Invocation">
2500 Usage: ibex [-lawp] [ url | file | directory ]
2501 -l [level] set logging level to { debug, info (default), warn, error, silent }
2502 -l rpc log all XML-RPC and SOAP conversations
2503 -l user@host email log to user@host
2504 -l host:port emit log to TCP socket
2505 -l [file] write log to a file on disk
2507 -w [window-id] reserved for libibex
2508 -p dump profiling information [not yet supported]
2511 If Ibex encounters a serious problem before it starts logging
2512 information, or if it is unable to open the log file, it will abort
2513 immediately with a critical abort, which will be displayed on the
2514 console for POSIX-native cores and in a dialog box for JVM-based and
2517 Note that Microsoft Windows does not provide any mechanism for
2518 redirecting standard input/output of an application which is not
2519 compiled as a "console application". Therefore, Ibex is compiled
2520 as a "console application", and will open a console window when
2521 invoked. To inhibit this console window, provide a logging
2522 destination (file, port, etc).
2524 The [[**source-location**]] parameter can be either the path
2525 to an [[.ibex]] archive, the http url of an [[.ibex]]
2526 archive, or the path to a directory comprising an unpacked
2529 The [[**initial-template**]] parameter is the stream name of
2530 a template to be used as the initial template. If ommitted, it
2531 defaults to [[main]].
2533 The [[-v]] option causes Ibex to enable verbose logging; this will
2534 cause it to log **lots** of information to the log file. This
2535 option will also substantially decrease Ibex's performance.
2539 <!-- ----------------------------------------------------------------------- -->
2541 <appendix title="Grammars">
2543 **Grammar support is experimental in this release
2544 and may not work properly. It may change in incompatible ways or
2545 disappear completely from future releases**
2547 Grammars are defined with a statement in the following form:
2552 A grammar is really just another function; once defined you can't tell
2553 it apart from an ordinary function. A grammar takes one argument,
2554 which can be a string or stream. The argument is parsed and the
2555 result of executing the code block 'c' is returned.
2557 The property 'a' is read; if the value is a grammar, a new production
2558 rule (ie a new alternative, as with '[[|]]') is added to that grammar
2559 (this is a destructive update). This allows you to add productions to
2560 pre-existing grammars (for example, adding a new type of expression to
2561 a programming language by extending the 'expr' grammar). If the old
2562 value is not a grammar, the value is discarded and a new grammar
2565 The value 'b' is a pattern, which may consist of seven simple
2568 <list type="unordered">
2571 grouping parens [[()]]
2573 combinators: [[ | + * ?]]
2575 references to other grammars
2578 The value 'c' and the braces surrounding it are an *optional* code
2579 block, in which the following identifiers are bound:
2581 <list type="unordered">
2583 The identifier 'whole' is bound to the string matched by the
2584 entire expression. If the code block is omitted it behaves
2585 as if it were "[[{ return whole; }]]".
2587 For every reference to another grammar which was matched in the
2588 pattern, the *name used to reference that other grammar* will
2589 be bound to the value returned by its code block. Here's an
2590 example of this important distinction:
2593 var foo ::= 'a' | 'b';
2595 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2598 On the last line, the identifier 'bar' serves two purposes: it
2599 pulls in the definition of the pattern *and* acts as a binder
2600 within the scope of the braces.
2602 If a reference is matched multiple times (either because it
2603 appears multiple times in the pattern or because the * or +
2604 operator was applied to it) then its name will be bound to an
2605 array containing the matches.
2609 Here is the metacircular definition of the grammar facility:
2612 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2613 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2614 char ::= '\0x0000'..'\0xffff'
2615 literal ::= '\'' char+ '\''
2616 | '\'' char '\'' '..' '\'' char '\''
2617 pattern ::= identifier
2624 | pattern '|' pattern
2629 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2630 Ibex is a trademark of Adam Megacz