[UP]
The UI language
 ui:a
 ui:alist-value and ui:alist-item
 ui:application
 ui:button
 ui:checkbox
 ui:cond
 ui:context
 ui:default
 ui:dialog
 ui:dyn-enum-value and ui:dyn-enum-item
 ui:dynamic
 ui:encode
 ui:enum-value and ui:enum-item
 ui:enumerate
 ui:enumeration and ui:enum
 ui:false
 ui:file
 ui:form
 ui:if
 ui:iflang
 ui:ifvar
 ui:imagebutton
 ui:iter-*
 ui:iterate
 ui:page
 ui:param
 ui:popup
 ui:radio
 ui:richbutton
 ui:select
 ui:server-popup
 ui:special
 ui:string-value
 ui:template
 ui:text and ui:password
 ui:textarea
 ui:translate
 ui:true
 ui:use
 ui:variable
 t:*, q:*, and p:*
 l:*
 $param
 $[expr]
 Dot notation (v1.v2)
   
Bracket expressions $[...]

Bracket expressions allow the UI developer to access dialog variables from page or template definitions (where the dollar character is recognized as meta symbol). For example, $[v] would expand to the current value of the dialog variable v. Of course, this works only if this variable is a string variable, as it would be unclear what to do with a non-string value (e.g. an enumeration).

So far, so simple. In recent versions of WDialog, the brackets cannot only contain variable names but whole expressions that are computed when the bracket is expanded. For instance, the expression $[size(v)] expands to the number of characters the string v consists of. There are a number of functions that can be applied to variables (see below). The syntax of function calls always includes parantheses, so v is a variable, and v() is a function call. Functions may have several arguments, separated by commas, e.g. f(x1,x2,x3).

Of course, the size function is not only reasonable for strings. We can also define the size of enumerator values, and of associative lists. Because of this it is allowed to write $[size(v)] when v is an enumerator or alist. In general, the intermediate values during evaluation may be of any type that can be stored in a dialog variable; however the resulting value must be a string as the result is inserted into the XML tree[1]. Typing is dynamic, and although the functions usually only accept certain types as arguments it is not tried to verify that by a type checker.

It is not only possible to access variables, but also template parameters. The dollar character must prefix the parameter name, e.g. $p. Braces are allowed, and even output encodings can be specified: ${p} and ${p/html} are legal expressions. The parameters are evaluated to strings (as if they would occur in attribute context). A number of UI meta elements are expanded allowing one to mix template-level and dialog-level evaluation strategies. For example, the template t2 expands to the size of the expanded template t1:

<ui:template name="t1">
  This is a text
</ui:template>

<ui:template name="t2" from-caller="which">
  <ui:default param="which"><ui:use template="t1"/></ui:default>
  $[size($which)]
</ui:template>

The expanded text is 14, the number of characters in t1.

We have mentioned variables, functions, parameters. Is it possible to include constant values into bracket expressions? Yes, but the current implementation is limited to numbers, e.g. $[add(n,2)]. It is not (yet) possible to include arbitrary string constants or any non-string constants. These may be added later.

Another important syntactic note: Bracket expressions must not contain white space! They are not even recognized by the parser if they do.

Now the list of functions that are defined by default:

  • size(expr): If expr is a string, this function returns the number of characters. If expr is an enumerator or associative list, this function returns the number of elements.

  • add(num1,...,numN): Adds all the numbers passed as arguments and returns the sum.

  • sub(num1,...,numN): Subtracts the second and all following arguments from the first argument, and returns the difference.

  • mul(num1,...,numN): Multiplies all the numbers passed as arugments and returns the product.

  • div(num1,...,numN): Divides the first number through the second number and all following numbers (in turn), and returns the quotient.

  • assoc(alist,str): Looks up the str argument in the associative list alist, and returns the value that corresponds to the str key. Of course, str must be a string. It is an error if str does not occur in alist.

  • nth(alist,num): Returns the numth value of the associative list alist, i.e. num is the ordinal number of the value to return. The first value has the ordinal number 0. It is an error if num is greater or equal than the number of elements of alist.

  • translate(dynenum,str): Returns the external value that corresponds to the internal value str in the dynamic enumerator dynenum. It is an error if str does not occur as internal value in dynenum.

  • translate(enum(name),str): Returns the external value that corresponds to the internal value str in the declared enumerator type name (i.e. the name in a ui:enumeration declaration). It is an error if str does not occur as internal value in the enumeration. See below for explanations of the enum form.

  • rev_translate(dynenum,str): Returns the (first) internal value that corresponds to the external value str in the dynamic enumerator dynenum. It is an error if str does not occur as external value in dynenum.

  • rev_translate(enum(name),str): Returns the (first) internal value that corresponds to the external value str in the declared enumerator type enum (i.e. the name in a ui:enumeration declaration). It is an error if str does not occur as external value in the enumeration. See below for explanations of the enum form.

  • substring(str,num1): Returns the substring of str starting at character position num1 until the end of the string.

  • substring(str,num1,num2): Returns the substring of str starting at character position num1 with length num2 (the length can be negative).

  • concat(str1,...,strN): Concatenates the strings str1 to strN.

  • height(str): Returns the number of lines the string str consists of. A line is separated from the next one by either LF, CR, or CRLF bytes. The number of lines is the number of these line separators plus 1.

  • width(str): Returns the number of characters the longest line in string str consists of. The line separator is not counted for the width.

  • var(str): Returns the contents of the dialog variable called str.

  • dialog(): Returns the name of the current dialog.

  • page(): Returns the name of the current page.

  • language(): Returns the current language, or "" if none is selected.

Furthermore, there are the following special forms:

  • type(var): Returns the name of the type of the variable var. The argument is not expanded before evaluation of the form, but taken literally, e.g. type(x) returns the type of the variable x, and not the type of the variable whose name is stored in the variable x. The return value is a string:

    • "string" is the type name of string variables

    • "dialog" is the type name of dialog variables

    • "dynamic-enumerator" is the type name of dynamic enumerator variables

    • The name of the enumeration is the type name of enumerator variables

    The type name is what the ui:variable element declares with the type argument.

    It does not matter whether the variable is associative or not.

  • is_associative(var): Returns whether the type of the variable var is associative or not. Like the type form, the argument is taken literally. The return value is either the string "yes" or "no".

  • default(var): Returns the default value used to initialize the variable var when the dialog object is created. Like the type form, the argument is taken literally. The return value is a value of appropriate type.

  • enum(name): Returns the declaration of the enumeration enum as a dynamically enumerated value. The argument is taken literally.

Numbers are represented as decimal strings.

As strings can contain multi-byte characters, the question arises whether the string functions take the number of bytes or the number of characters as "position" or "length". Of course, characters are counted, so the user does not have to take care of the character encoding.


[1]
It may be possible to also allow XML tree types here, but such types do not occur in the rest of the UI language. This is an interesting idea for a future extension of the language, though.