UIL(5) | File Formats Manual | UIL(5) |
UIL — The user interface language file format "user interface language" "UIL"
MODULE module_name [ NAMES = CASE_INSENSITIVE | CASE_SENSITIVE ] [ CHARACTER_SET = character_set ] [ OBJECTS = { widget_name = GADGET | WIDGET; [...] } ] { [ [ value_section ] | [ procedure_section ] | [ list_section ] | [ object_section ] | [ identifier_section ] [ ... ] ] } END MODULE;
The UIL language is used for describing the initial state of a user interface for a widget based application. UIL describes the widgets used in the interface, the resources of those widgets, and the callbacks of those widgets. The UIL file is compiled into a UID file using the command uil or by the callable compiler Uil(). The contents of the compiled UID file can then be accessed by the various Motif Resource Management (MRM) functions from within an application program.
The UID file is independent of the platform on which the Motif program will eventually be run. In other words, the same UID file can be used on any system that can run Motif.
A UIL file consists of a single complete module, described in the syntax description above, or, if the file is to be included in a larger UIL file, one complete "section," as described below. UIL uses five different kinds of sections: value, procedure, list, object, and identifier.
UIL is a free-form language. This means that high-level constructs such as object and value declarations do not need to begin in any particular column and can span any number of lines. Low-level constructs such as keywords and punctuation characters can also begin in any column; however, except for string literals and comments, they cannot span lines.
The UIL compiler accepts input lines up to 132 characters in length.
The UIL file can also contain comments and include directives, which are described along with the main elements of the UIL file format in the following sections.
Comments can take one of two forms, as follows:
Neither form of comment can be nested.
"UIL" "value section" A value section consists of the keyword VALUE followed by a sequence of value declarations. It has the following syntax:
VALUE value_name : [ EXPORTED | PRIVATE ] value_expression | IMPORTED value_type ;
Where value_expression is assigned to value_name or a value_type is assigned to an imported value name. A value declaration provides a way to name a value expression or literal. The value name can be referred to by declarations that occur later in the UIL module in any context where a value can be used. Values can be forward referenced. "IMPORTED" "EXPORTED" "PRIVATE"
By default, values and objects are private. The following is a list of the supported value types in UIL:
"UIL" "procedure section" A procedure section consists of the keyword PROCEDURE followed by a sequence of procedure declarations. It has the following syntax:
PROCEDURE
procedure_name [ ( [ value_type ]) ];
"UIL" "procedure declaration" Use a procedure declaration to declare
You can reference a procedure name in declarations that occur later in the UIL module in any context where a procedure can be used. Procedures can be forward referenced. You cannot use a name you used in another context as a procedure name.
In a procedure declaration, you have the option of specifying that a parameter will be passed to the corresponding callback routine at run time. This parameter is called the callback tag. You can specify the data type of the callback tag by putting the data type in parentheses following the procedure name. When you compile the module, the UIL compiler checks that the argument you specify in references to the procedure is of this type. Note that the data type of the callback tag must be one of the valid UIL data types. You can use a widget as a callback tag, as long as the widget is defined in the same widget hierarchy as the callback, that is they have a common ancestor that is in the same UIL hierarchy.
The following list summarizes how the UIL compiler checks argument type and argument count, depending on the procedure declaration.
While it is possible to use any UIL data type to specify the type of a tag in a procedure declaration, you must be able to represent that data type in the programming language you are using. Some data types (such as integer, Boolean, and string) are common data types recognized by most programming languages. Other UIL data types (such as string tables) are more complicated and may require that you set up an appropriate corresponding data structure in the application in order to pass a tag of that type to a callback routine.
You can also use a procedure declaration to specify the creation function for a user-defined widget. In this case, you specify no formal parameters. The procedure is invoked with the standard three arguments passed to all widget creation functions. (See the Motif Toolkit documentation for more information about widget creation functions.)
"UIL" "list section" A list section consists of the keyword LIST followed by a sequence of list declarations. It has the following syntax:
LIST
list_name: { list_item; [...] }
[...]
You can also use list sections to group together a set of arguments, controls (children), callbacks, or procedures for later use in the UIL module. Lists can contain other lists, so that you can set up a hierarchy to clearly show which arguments, controls, callbacks, and procedures are common to which widgets. You cannot mix the different types of lists; a list of a particular type cannot contain entries of a different list type or reference the name of a different list type. A list name is always private to the UIL module in which you declare the list and cannot be stored as a named resource in a UID file.
The additional list types are described in the following sections.
Arguments List Structure
"List types" "argument" "UIL" "arguments list" An arguments list defines which arguments are to be specified in the arguments list parameter when the creation routine for a particular object is called at run time. An arguments list also specifies the values for those arguments. Argument lists have the following syntax:
LIST
list_name: ARGUMENTS {
argument_name = value_expression;
[...] } [...]
The argument name must be either a built-in argument name or a user-defined argument name that is specified with the ARGUMENT function.
If you use a built-in argument name as an arguments list entry in an object definition, the UIL compiler checks the argument name to be sure that it is supported by the type of object that you are defining. If the same argument name appears more than once in a given arguments list, the last entry that uses that argument name supersedes all previous entries with that name, and the compiler issues a message.
Some arguments, such as XmNitems and XmNitemCount, are coupled by the UIL compiler. When you specify one of the arguments, the compiler also sets the other. The coupled argument is not available to you. "UIL" "coupled arguments" "Arguments" "coupled in UIL"
The Motif Toolkit and the X Toolkit (intrinsics) support constraint arguments. A constraint argument is one that is passed to children of an object, beyond those arguments normally available. For example, the Form widget grants a set of constraint arguments to its children. These arguments control the position of the children within the Form.
Unlike the arguments used to define the attributes of a particular widget, constraint arguments are used exclusively to define additional attributes of the children of a particular widget. These attributes affect the behavior of the children within their parent. To supply constraint arguments to the children, you include the arguments in the arguments list for the child.
See Appendix B for information about which arguments are supported by which widgets. See Appendix C for information about what the valid value type is for each built-in argument.
Callbacks List Structure "UIL" "callbacks list" "List types" "callback"
Use a callbacks list to define which callback reasons are to be processed by a particular widget at run time. Callback lists have the following syntax:
LIST list_name : CALLBACKS { reason_name = PROCEDURE procedure_name [ ( [ value_expression ] ) ]; | reason_name = procedure_list ; [...] } [...]
For Motif Toolkit widgets, the reason name must be a built-in reason name. For a user-defined widget, you can use a reason name that you previously specified using the REASON function. If you use a built-in reason in an object definition, the UIL compiler ensures that reason is supported by the type of object you are defining. Appendix B shows which reasons each object supports.
If the same reason appears more than once in a callbacks list, the last entry referring to that name supersedes all previous entries using the same reason, and the UIL compiler issues a diagnostic message.
If you specify a named value for the procedure argument (callback tag), the data type of the value must match the type specified for the callback tag in the corresponding procedure declaration. When specifying a widget name as a procedure value expression you must also specify the type of the widget and a space before the name of the widget.
Because the UIL compiler produces a UID file rather than an object module (.o), the binding of the UIL name to the address of the entry point to the procedure is not done by the loader, but is established at run time with the MRM function MrmRegisterNames. You call this function before fetching any objects, giving it both the UIL names and the procedure addresses of each callback. The name you register with MRM in the application program must match the name you specified for the procedure in the UIL module.
Each callback procedure receives three arguments. The first two arguments have the same form for each callback. The form of the third argument varies from object to object.
The first argument is the address of the data structure maintained by the Motif Toolkit for this object instance. This address is called the widget ID for this object.
The second argument is the address of the value you specified in the callbacks list for this procedure. If you do not specify an argument, the address is NULL. Note that, in the case where the value you specified is a string or an XmString, the value specified in the callbacks list already represents an address rather than an actual value. In the case of a simple string, for example, the value is the address of the first character of that string. In these cases, UIL does not add a level of indirection, and the second argument to the callback procedure is simply the value as specified in the callbacks list.
The third argument is the reason name you specified in the callbacks list.
Controls List Structure
"UIL" "controls list" A controls list defines which objects are children of, or controlled by, a particular object. Each entry in a controls list has the following syntax:
LIST
list_name: CONTROLS {
[child_name: ] [MANAGED | UNMANAGED] object_definition;
[...] }
[...]
If you specify the keyword MANAGED at run time, the object is created and managed; if you specify UNMANAGED at run time, the object is only created. Objects are managed by default.
You can use child_name to specify resources for the automatically created children of a particular control. Names for automatically created children are formed by appending Xm_ to the name of the child widget. This name is specified in the documentation for the parent widget.
Unlike the arguments list and the callbacks list, a controls list entry that is identical to a previous entry does not supersede the previous entry. At run time, each controls list entry causes a child to be created when the parent is created. If the same object definition is used for multiple children, multiple instances of the child are created at run time. See Appendix B for a list of which widget types can be controlled by which other widget types.
Procedures List Structure
You can specify multiple procedures for a callback reason in UIL by defining a procedures list. Just as with other list types, procedures lists can be defined in-line or in a list section and referenced by name.
If you define a reason more than once (for example, when the reason is defined both in a referenced procedures list and in the callbacks list for the object), previous definitions are overridden by the latest definition. The syntax for a procedures list is as follows:
LIST
list_name: PROCEDURES {
procedure_name [ ( [ value_expression ]) ];
[...] }
[...]
When specifying a widget name as a procedure value expression you must also specify the type of the widget and a space before the name of the widget.
"UIL" "object section" An object section consists of the keyword OBJECT followed by a sequence of object declarations. It has the following syntax:
OBJECT object_name:
[ EXPORTED | PRIVATE | IMPORTED ] object_type
[ PROCEDURE creation_function ]
[ object_name [ WIDGET | GADGET ] | {list_definitions } ]
"UIL" "object declaration" Use an object declaration to define the objects that are to be stored in the UID file. You can reference the object name in declarations that occur elsewhere in the UIL module in any context where an object name can be used (for example, in a controls list, as a symbolic reference to a widget ID, or as the tag_value argument for a callback procedure). Objects can be forward referenced; that is, you can declare an object name after you reference it. All references to an object name must be consistent with the type of the object, as specified in the object declaration. You can specify an object as exported, imported, or private.
The object definition can contain a sequence of lists that define the arguments, hierarchy, and callbacks for the widget. You can specify only one list of each type for an object. When you declare a user-defined widget, you must include a reference to the widget creation function for the user-defined widget.
Note: Several widgets in the Motif Toolkit actually consist of two linked widgets. For example, XmScrolledText and XmScrolledList each consist of children XmText and XmList widgets under a XmScrolledWindow widget. When such a widget is created, its resources are available to both of the underlying widgets. This can occasionally cause problems, as when the programmer wants a XmNdestroyCallback routine named to act when the widget is destroyed. In this case, the callback resource will be available to both sub-widgets, and will cause an error when the widget is destroyed. To avoid these problems, the programmer should separately create the parent and child widgets, rather than relying on these linked widgets.
Use the GADGET or WIDGET keyword to specify the object type or to override the default variant for this object type. You can use the Motif Toolkit name of an object type that has a gadget variant (for example, XmLabelGadget) as an attribute of an object declaration. The object_type can be any object type, including gadgets. You need to specify the GADGET or WIDGET keyword only in the declaration of an object, not when you reference the object. You cannot specify the GADGET or WIDGET keyword for a user-defined object; user-defined objects are always widgets.
"UIL" "identifiers" The identifier section allows you to define an identifier, a mechanism that achieves run-time binding of data to names that appear in a UIL module. The identifier section consists of the reserved keyword IDENTIFIER, followed by a list of names, each name followed by a semicolon.
IDENTIFIER identifier_name; [...;]
You can later use these names in the UIL module as either the value of an argument to a widget or the tag value to a callback procedure. At run time, you use the MRM functions MrmRegisterNames and MrmRegisterNamesInHierarchy to bind the identifier name with the data (or, in the case of callbacks, with the address of the data) associated with the identifier.
Each UIL module has a single name space; therefore, you cannot use a name you used for a value, object, or procedure as an identifier name in the same module.
The UIL compiler does not do any type checking on the use of identifiers in a UIL module. Unlike a UIL value, an identifier does not have a UIL type associated with it. Regardless of what particular type a widget argument or callback procedure tag is defined to be, you can use an identifier in that context instead of a value of the corresponding type.
To reference these identifier names in a UIL module, you use the name of the identifier wherever you want its value to be used.
"UIL" "include directive" The include directive incorporates the contents of a specified file into a UIL module. This mechanism allows several UIL modules to share common definitions. The syntax for the include directive is as follows:
INCLUDE FILE file_name;
The UIL compiler replaces the include directive with the contents of the include file and processes it as if these contents had appeared in the current UIL source file.
You can nest include files; that is, an include file can contain include directives. The UIL compiler can process up to 100 references (including the file containing the UIL module). Therefore, you can include up to 99 files in a single UIL module, including nested files. Each time a file is opened counts as a reference, so including the same file twice counts as two references.
The file_name is a simple string containing a file specification that identifies the file to be included. The rules for finding the specified file are similar to the rules for finding header, or .h files using the include directive, #include, with a quoted string in C. The UIL uses the -I option for specifying a search directory for include files.
Names can consist of any of the characters A to Z, a to z, 0 to 9, $ (dollar sign), and _ (underscore). Names cannot begin with a digit (0 to 9). The maximum length of a name is 31 characters.
UIL gives you a choice of either case-sensitive or case-insensitive names through a clause in the MODULE header. For example, if names are case sensitive, the names "sample" and "Sample" are distinct from each other. If names are case insensitive, these names are treated as the same name and can be used interchangeably. By default, UIL assumes names are case sensitive.
In CASE-INSENSITIVE mode, the compiler outputs all names in the UID file in uppercase form. In CASE-SENSITIVE mode, names appear in the UIL file exactly as they appear in the source.
The following table lists the reserved keywords, which are not available for defining programmer defined names. "UIL" "keywords" "UIL module" "keywords" "UIL specification file" "keywords" "Keywords"
Reserved Keywords | |||
ARGUMENTS | CALLBACKS | CONTROLS | END |
EXPORTED | FALSE | GADGET | IDENTIFIER |
INCLUDE | LIST | MODULE | OFF |
ON | OBJECT | PRIVATE | PROCEDURE |
PROCEDURES | TRUE | VALUE | WIDGET |
The UIL unreserved keywords are described in the following list and table. These keywords can be used as programmer defined names, however, if you use any keyword as a name, you cannot use the UIL-supplied usage of that keyword.
Unreserved Keywords | ||
ANY | ARGUMENT | ASCIZ_STRING_TABLE |
ASCIZ_TABLE | BACKGROUND | BOOLEAN |
CASE_INSENSITIVE | CASE_SENSITIVE | CHARACTER_SET |
COLOR | COLOR_TABLE | COMPOUND_STRING |
COMPOUND_STRING_COMPONENT | COMPOUND_STRING_TABLE | FILE |
FLOAT | FONT | FONT_TABLE |
FONTSET | FOREGROUND | ICON |
IMPORTED | INTEGER | INTEGER_TABLE |
KEYSYM | MANAGED | NAMES |
OBJECTS | REASON | RGB |
RIGHT_TO_LEFT | SINGLE_FLOAT | STRING |
STRING_TABLE | TRANSLATION_TABLE | UNMANAGED |
USER_DEFINED | VERSION | WIDE_CHARACTER |
WIDGET | XBITMAPFILE |
String literals can be composed of the uppercase and lowercase letters, digits, and punctuation characters. Spaces, tabs, and comments are special elements in the language. They are a means of delimiting other elements, such as two names. One or more of these elements can appear before or after any other element in the language. However, spaces, tabs, and comments that appear in string literals are treated as character sequences rather than delimiters.
"UIL" "literals" "UIL module" "literals" "UIL specification file" "literals" "Values" "literals"
UIL provides literals for several of the value types it supports. Some of the value types are not supported as literals (for example, pixmaps and string tables). You can specify values for these types by using functions described in the Functions section. UIL directly supports the following literal types:
UIL also includes the data type ANY, which is used to turn off compile time checking of data types.
"UIL" "string literals" "UIL module" "string literals" "UIL specification file" "string literals" "Values" "string literals"
A string literal is a sequence of zero or more 8-bit or 16-bit characters or a combination delimited by ' (single quotation marks) or " (double quotation marks). String literals can also contain multibyte characters delimited with double quotation marks. String literals can be no more than 2000 characters long.
A single-quoted string literal can span multiple source lines. To continue a single-quoted string literal, terminate the continued line with a \ (backslash). The literal continues with the first character on the next line.
Double-quoted string literals cannot span multiple source lines. (Because double-quoted strings can contain escape sequences and other special characters, you cannot use the backslash character to designate continuation of the string.) To build a string value that must span multiple source lines, use the concatenation operator described later in this section.
The syntax of a string literal is one of the following:
'[character_string]' [#char_set]"[character_string]"
Both string forms associate a character set with a string value. UIL uses the following rules to determine the character set and storage format for string literals:
If the char_set in a string specified in the form above is not a built-in charset, and is not a user-defined charset, the charset of the string will be set to XmFONTLIST_DEFAULT_TAG, and an informational message will be issued to the user to note that this substitution has been made.
The following table lists the character sets supported by the UIL compiler for string literals. Note that several UIL names map to the same character set. In some cases, the UIL name influences how string literals are read. For example, strings identified by a UIL character set name ending in _LR are read left-to-right. Names that end in a different number reflect different fonts (for example, ISO_LATIN1 or ISO_LATIN6). All character sets in this table are represented by 8 bits.
Supported Character Sets | |
UIL Name | Description |
ISO_LATIN1 | GL: ASCII, GR: Latin-1 Supplement |
ISO_LATIN2 | GL: ASCII, GR: Latin-2 Supplement |
ISO_ARABIC | GL: ASCII, GR: Latin-Arabic Supplement |
ISO_LATIN6 | GL: ASCII, GR: Latin-Arabic Supplement |
ISO_GREEK | GL: ASCII, GR: Latin-Greek Supplement |
ISO_LATIN7 | GL: ASCII, GR: Latin-Greek Supplement |
ISO_HEBREW | GL: ASCII, GR: Latin-Hebrew Supplement |
ISO_LATIN8 | GL: ASCII, GR: Latin-Hebrew Supplement |
ISO_HEBREW_LR | GL: ASCII, GR: Latin-Hebrew Supplement |
ISO_LATIN8_LR | GL: ASCII, GR: Latin-Hebrew Supplement |
JIS_KATAKANA | GL: JIS Roman, GR: JIS Katakana |
Following are the parsing rules for each of the character sets:
In addition to designating parsing rules for strings, character set information remains an attribute of a compound string. If the string is included in a string consisting of several concatenated segments, the character set information is included with that string segment. This gives the Motif Toolkit the information it needs to decipher the compound string and choose a font to display the string.
For an application interface displayed only in English, UIL lets you ignore the distinctions between the two uses of strings. The compiler recognizes by context when a string must be passed as a null-terminated string or as a compound string.
The UIL compiler recognizes enough about the various character sets to correctly parse string literals. The compiler also issues errors if you use a compound string in a context that supports only null-terminated strings.
Since the character set names are keywords, you must put them in lowercase if case-sensitive names are in force. If names are case insensitive, character set names can be uppercase, lowercase, or mixed case.
In addition to the built-in character sets recognized by UIL, you can define your own character sets with the CHARACTER_SET function. You can use the CHARACTER_SET function anywhere a character set can be specified.
String literals can contain characters with the eighth (high-order) bit set. You cannot type control characters (00-1F, 7F, and 80-9F) directly in a single-quoted string literal. However, you can represent these characters with escape sequences. The following list shows the escape sequences for special characters. "UIL" "escape sequences" "Escape sequences"
Note that escape sequences are processed literally in strings that are parsed in the current locale (localized strings).
The UIL compiler does not process newline characters in compound strings. The effect of a newline character in a compound string depends only on the character set of the string, and the result is not guaranteed to be a multiline string.
Compound String Literals
A compound string consists of a string of 8-bit, 16-bit, or multibyte characters, a named character set, and a writing direction. Its UIL data type is compound_string.
The writing direction of a compound string is implied by the character set specified for the string. You can explicitly set the writing direction for a compound string by using the COMPOUND_STRING function.
A compound string can consist of a sequence of concatenated compound strings, null-terminated strings, or a combination of both, each of which can have a different character set property and writing direction. Use the concatenation operator & (ampersand) to create a sequence of compound strings.
Each string in the sequence is stored, including the character set and writing direction information.
Generally, a string literal is stored in the UID file as a compound string when the literal consists of concatenated strings having different character sets or writing directions, or when you use the string to specify a value for an argument that requires a compound string value. If you want to guarantee that a string literal is stored as a compound string, you must use the COMPOUND_STRING function.
Data Storage Consumption for String Literals
The way a string literal is stored in the UID file depends on how you declare and use the string. The UIL compiler automatically converts a null-terminated string to a compound string if you use the string to specify the value of an argument that requires a compound string. However, this conversion is costly in terms of storage consumption.
PRIVATE, EXPORTED, and IMPORTED string literals require storage for a single allocation when the literal is declared; thereafter, storage is required for each reference to the literal. Literals declared in-line require storage for both an allocation and a reference.
The following table summarizes data storage consumption for string literals. The storage requirement for an allocation consists of a fixed portion and a variable portion. The fixed portion of an allocation is roughly the same as the storage requirement for a reference (a few bytes). The storage consumed by the variable portion depends on the size of the literal value (that is, the length of the string). To conserve storage space, avoid making string literal declarations that result in an allocation per use.
Data Storage Consumption for String Literals | |||
Storage Requirements | |||
Per Use | |||
An allocation and a reference (within the module) | |||
A reference (within the module) | |||
A reference (within the UID hierarchy) | |||
A reference (within the UID hierarchy) | |||
An allocation and a reference (within the module) | |||
An allocation and a reference (within the module) | |||
A reference (within the UID hierarchy) | |||
A reference (within the UID hierarchy) | |||
An allocation and a reference (within the module) | |||
A reference (within the module) | |||
A reference (within the UID hierarchy) | |||
A reference (within the UID hierarchy) |
"UIL" "integer literals" "UIL module" "integer literals" "UIL specification file" "integer literals" "Values" "integer literals"
An integer literal represents the value of a whole number. Integer literals have the form of an optional sign followed by one or more decimal digits. An integer literal must not contain embedded spaces or commas.
Integer literals are stored in the UID file as 32-bit integers. Exported and imported integer literals require a single allocation when the literal is declared; thereafter, a few bytes of storage are required for each reference to the literal. Private integer literals and those declared in-line require allocation and reference storage per use. To conserve storage space, avoid making integer literal declarations that result in an allocation per use.
The following table shows data storage consumption for integer literals.
Data Storage Consumption for Integer Literals | |
Declaration | Storage Requirements Per Use |
In-line | An allocation and a reference (within the module) |
Private | An allocation and a reference (within the module) |
Exported | A reference (within the UID hierarchy) |
Imported | A reference (within the UID hierarchy) |
"UIL" "Boolean literals" "UIL module" "Boolean literals" "UIL specification file" "Boolean literals" "Values" "Boolean literals" "Boolean literals" A Boolean literal represents the value True (reserved keyword TRUE or On) or False (reserved keyword FALSE or Off). These keywords are subject to case-sensitivity rules.
In a UID file, TRUE is represented by the integer value 1 and FALSE is represented by the integer value 0 (zero).
Data storage consumption for Boolean literals is the same as that for integer literals.
"UIL" "floating-point literals" "UIL module" "floating-point literals" "UIL specification file" "floating-point literals" "Values" "floating-point literals"
A floating-point literal represents the value of a real (or float) number. Floating-point literals have the following form:
[+|-][integer].integer[E|e[+|-]exponent]
For maximum portability, a floating-point literal can represent values in the range 1.0E-37 to 1.0E+37 with at least 6 significant digits. On many machines this range will be wider, with more significant digits. A floating-point literal must not contain embedded spaces or commas.
Floating-point literals are stored in the UID file as double-precision, floating-point numbers. The following table gives examples of valid and invalid floating-point notation for the UIL compiler.
Floating Point Literals | |
Valid Floating-Point Literals | Invalid Floating-Point Literals |
1.0 | 1e1 (no decimal point) |
3.1415E-2 (equals .031415) | 2.87 e6 (embedded blanks) |
-6.29e7 (equals -62900000) | 2.0e100 (out of range) |
Data storage consumption for floating-point literals is the same as that for integer literals.
"UIL" "ANY value" "UIL module" "ANY value" "UIL specification file" "ANY value" "Functions" "ANY value" "ANY value" The purpose of the ANY data type is to shut off the data-type checking feature of the UIL compiler. You can use the ANY data type for the following:
You can use the ANY data type when you need to use a type not supported by the UIL compiler or when you want the data-type restrictions imposed by the compiler to be relaxed. For example, you might want to define a widget having an argument that can accept different types of values, depending on run-time circumstances.
If you specify that an argument takes an ANY value, the compiler does not check the type of the value specified for that argument; therefore, you need to take care when specifying a value for an argument of type ANY. You could get unexpected results at run time if you pass a value having a data type that the widget does not support for that argument.
"UIL" "expressions" "expressions" UIL includes compile-time value expressions. These expressions can contain references to other UIL values, but cannot be forward referenced.
The following table lists the set of operators in UIL that allow you to create integer, real, and Boolean values based on other values defined with the UIL module. In the table, a precedence of 1 is the highest.
Valid Operators | |||
Operator | Operand Types | Meaning | Precedence |
~ | Boolean | NOT | 1 |
integer | One's complement | ||
- | float | Negate | 1 |
integer | Negate | ||
+ | float | NOP | 1 |
integer | NOP | ||
* | float,float | Multiply | 2 |
integer,integer | Multiply | ||
/ | float,float | Divide | 2 |
integer,integer | Divide | ||
+ | float,float | Add | 3 |
integer,integer | Add | ||
- | float,float | Subtract | 3 |
integer,integer | Subtract | ||
>> | integer,integer | Shift right | 4 |
<< | integer,integer | Shift left | 4 |
& | Boolean,Boolean | AND | 5 |
integer,integer | Bitwise AND | ||
string,string | Concatenate | ||
| | Boolean,Boolean | OR | 6 |
integer,integer | Bitwise OR | ||
^ | Boolean,Boolean | XOR | 6 |
integer,integer | Bitwise XOR |
A string can be either a single compound string or a sequence of compound strings. If the two concatenated strings have different properties (such as writing direction or character set), the result of the concatenation is a multisegment compound string.
The string resulting from the concatenation is a null-terminated string unless one or more of the following conditions exists:
Then the resulting string is a compound string. You cannot use imported or exported values as operands of the concatenation operator.
The result of each operator has the same type as its operands. You cannot mix types in an expression without using conversion routines.
You can use parentheses to override the normal precedence of operators. In a sequence of unary operators, the operations are performed in right-to-left order. For example, - + -A is equivalent to -(+(-A)). In a sequence of binary operators of the same precedence, the operations are performed in left-to-right order. For example, A*B/C*D is equivalent to ((A*B)/C)*D.
A value declaration gives a value a name. You cannot redefine the value of that name in a subsequent value declaration. You can use a value containing operators and functions anywhere you can use a value in a UIL module. You cannot use imported values as operands in expressions. "UIL" "data type conversions" "Data type" "conversions" "Conversions" "data type"
Several of the binary operators are defined for multiple data types. For example, the operator for multiplication (*) is defined for both floating-point and integer operands.
For the UIL compiler to perform these binary operations, both operands must be of the same type. If you supply operands of different data types, the UIL compiler automatically converts one of the operands to the type of the other according to the following conversions rules:
You can also explicitly convert the data type of a value by using one of the conversion functions INTEGER, FLOAT or SINGLE_FLOAT.
"UIL Functions" "UIL module" "functions" "UIL specification file" "functions" "Functions" UIL provides functions to generate the following types of values:
Remember that all examples in the following sections assume case-insensitive mode. Keywords are shown in uppercase letters to distinguish them from user-specified names, which are shown in lowercase letters. This use of uppercase letters is not required in case-insensitive mode. In case-sensitive mode, keywords must be in lowercase letters.
RIGHT_TO_LEFT = boolean_expression SIXTEEN_BIT = boolean_expression
VALUE c: COLOR ( 'red',BACKGROUND );
COLOR_TABLE( BACKGROUND COLOR = ' ', FOREGROUND COLOR = '*')
"Renditions" "Render Tables"
In addition to the string direction, each compound string carries a great deal of information about how its text is to be rendered. Each compound string contains a "tag," identifying the "rendition" to be used to draw that string. The rendition contains such information as the font, the size, the color, whether the text is to be underlined or crossed out, and the position and style of any tab stops. Many renditions are combined into a "render table," which is specified to any widget with the XmNrenderTable resource, and in the widget's controls list.
UIL implements render tables, renditions, tab lists, and tab stops as a special class of objects, in a form similar to the widget class. These objects are not themselves widgets or gadgets, but the format used by UIL to specify widget resources provides a convenient way to specify the qualities and dependencies of these objects.
For example, a render table, included in some widget's controls list, must also have a controls list in its specification, containing the names of its member renditions. Each rendition, in its specification, will contain an arguments list specifying such qualities as the font, the color, and whether the text is to be underlined. Any of the renditions may also control a tablist, which will itself control one or more tab stops.
Please refer to the Motif Programmer's Guide for a complete description of renditions and render tables, and for an example of how to use them in UIL.