UIL - The user interface language file format
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 by accessed by the various
Motif Resource Management (MRM) functions from within an
application program.
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 name by which the UIL module is known in
the UID file. This name is stored in the UID file for
later use in the retrieval of resources by the MRM. This
name is always stored in uppercase in the UID file. Indicates
whether names should be treated as case sensitive or
case insensitive. The default is case sensitive. The
case-sensitivity clause should be the first clause in the
module header, and in any case must precede any statement
that contains a name. If names are case sensitive in a UIL
module, UIL keywords in that module must be in lowercase.
Each name is stored in the UIL file in the same case as it
appears in the UIL module. If names are case insensitive,
then keywords can be in uppercase, lowercase, or mixed
case, and the uppercase equivalent of each name is stored
in the UID file. Specifies the default character set for
string literals in the module that do not explicitly set
their character set. The default character set, in the
absence of this clause is the codeset component of the
LANG environment variable, or the value of XmFALLBACK_CHARSET
if LANG is not set or has no codeset component.
The value of XmFALLBACK_CHARSET is defined by UIL
supplier, but is usually ISO8859-1 (equivalent to
ISO_LATIN1). Use of this clause turns off all localized
string literal processing turned on by the compiler flag
-s or the Uil_command_type data structure element use_setlocale_flag.
Indicates whether the widget or gadget form
of the control specified by widget_name is used by
default. By default the widget form is used, so the gadget
keyword is usually the only one used. The specified control
should be one that has both a widget and gadget version:
XmCascadeButton, XmLabel, XmPushButton, XmSeparator,
and XmToggleButton. The form of more than one control
can be specified by delimiting them with semicolons.
The gadget or widget form of an instance of a control can
be specified with the GADGET and WIDGET keywords in a particular
object declaration. Provides a way to name a
value expression or literal. The value name can then be
referred to by declarations that occur elsewhere in the
UIL module in any context where a value can be used. Values
can be forward referenced. Value sections are
described in more detail later in the reference page.
Defines the callback routines used by a widget and the
creation routines for user-defined widgets. These definitions
are used for error checking. Procedure sections are
described in more detail later in the reference page.
Provides a way 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. List sections are described in more detail
later in the reference page. Defines the objects that
make up the user interface of the application. You can
reference the object names 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. Object sections are described in more detail
later in the reference page. Defines a run-time binding
of data to names that appear in the UIL module. Identifier
sections are described in more detail later in the reference
page.
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 [Toc] [Back]
Comments can take one of two forms, as follows: The comment
is introduced with the sequence /* followed by the
text of the comment and terminated with the sequence */.
This form of comment can span multiple source lines. The
comment is introduced with an ! (exclamation point), followed
by the text of the comment and terminated by the end
of the source line.
Neither form of comment can be nested.
Value Sections [Toc] [Back]
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. A
value that you define as exported is stored in the UID
file as a named resource, and therefore can be referenced
by name in other UID files. When you define a value as
exported, MRM looks outside the module in which the
exported value is declared to get its value at run time.
A private value is a value that is not imported or
exported. A value that you define as private is not
stored as a distinct resource in the UID file. You can
reference a private value only in the UIL module containing
the value declaration. The value or object is directly
incorporated into anything in the UIL module that references
the declaration. A value that you define as
imported is one that is defined as a named resource in a
UID file. MRM resolves this declaration with the corresponding
exported declaration at application run time.
By default, values and objects are private. The following
is a list of the supported value types in UIL. ANY ARGUMENT
BOOLEAN COLOR COLOR_TABLE COMPOUND_STRING FLOAT FONT
FONT_TABLE FONTSET ICON INTEGER INTEGER_TABLE KEYSYM REASON
SINGLE_FLOAT STRING STRING_TABLE TRANSLATION_TABLE
WIDE_CHARACTER WIDGET
Procedure sections [Toc] [Back]
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])];
Use a procedure declaration to declare: A routine that can
be used as a callback routine for a widget The creation
function for a user-defined widget
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: No argument type or argument count
checking occurs. You can supply either 0 or 1 arguments in
the procedure reference. Checks that the argument count
is 0. Checks that the argument count is 1. Does not
check the argument type. Use the ANY type to prevent type
checking on procedure tags. Checks for one argument of
the specified type. Checks for one widget argument of the
specified widget class.
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 you to
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.)
List sections [Toc] [Back]
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 [Toc] [Back]
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.
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 in the OSF/Motif Programmer's Reference for
information about which arguments are supported by which
widgets. See Appendix C, also in the OSF/Motif Programmer's
Reference for information about what the valid value
type is for each built-in argument.
Callbacks List Structure [Toc] [Back]
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.
The third argument is the reason name you specified in the
callbacks list.
Controls List Structure [Toc] [Back]
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 in the Programmer's
Reference for a list of which widget types can be controlled
by which other widget types.
Procedures List Structure [Toc] [Back]
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.
Object Sections [Toc] [Back]
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}]
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.
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.
Identifier sections [Toc] [Back]
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.
Include directives [Toc] [Back]
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 character expression is 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 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. If you
do not supply a directory, the UIL compiler searches for
the include file in the directory of the main source file.
If the compiler does not find the include file there, the
compiler looks in the same directory as the source file.
If you supply a directory, the UIL compiler searches only
that directory for the file.
Names and Strings
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 caseinsensitive
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 list the reserved keywords, which are
not available for defining programmer defined names.
-----------------------------------------------
Reserved Keywords
-----------------------------------------------
ARGUMENTS CALLBACKS CONTROLS END
EXPORTED FALSE GADGET IDENTIFIER
INCLUDE LIST MODULE OFF
ON OBJECT PRIVATE PROCEDURE
PROCEDURES TRUE VALUE WIDGET
-----------------------------------------------
The following table list the UIL unreserved keywords.
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. Built-in argument
names (for example: XmNx, XmNheight) Built-in reason names
(for example: XmNactivateCallback, XmNhelpCallback) Character
set names (for example: ISO_LATIN1, ISO_HEBREW_LR)
Constant value names (for example: XmMENU_OPTION,
XmBROWSE_SELECT) Object types (for example: XmPushButton,
XmBulletinBoard)
------------------------------------------------------------
Unreserved Keywords
------------------------------------------------------------
ANY ARGUMENT ASCIZ_STRING_TABLE
ASCIZ_TABLE BACKGROUND BOOLEAN
CASE_INSENSITIVE CASE_SENSITIVE CHARACTER_SET
COLOR COLOR_TABLE COMPOUND_STRING
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 upper- 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.
Data Types [Toc] [Back]
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: String literal Integer literal
Boolean literal Floating-point literal
UIL also includes the data type ANY, which is used to turn
off compile time checking of data types.
String Literals [Toc] [Back]
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: A string
declared as 'string' is equivalent to
#cur_charset"string", where cur_charset will be the codeset
portion of the value of the LANG environment variable
if it is set or the value of XmFALLBACK_CHARSET if LANG is
not set or has no codeset component. By default XmFALLBACK_CHARSET
is ISO8859-1 (equivalent to ISO_LATIN1), but
vendors may define a different default. A string declared
as "string" is equivalent to #char_set"string" if you
specified char_set as the default character set for the
module. If no default character set has been specified for
the module, then if the -s option is provided to the uil
command or the use_setlocale_flag is set for the callable
compiler, Uil(), the string will be interpreted to be a
string in the current locale. This means that the string
is parsed in the locale of the user by calling setlocale
and its charset is XmFONTLIST_DEFAULT_TAG, and that if the
string is converted to a compound string, it is stored as
a locale encoded text segment. Otherwise, "string" is
equivalent to #cur_charset"string", where cur_charset is
interpreted as described for single quoted strings. A
string of the form "string" or #char_set"string" is stored
as a null-terminated string.
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: Character codes in the range 00...1F, 7F, and
80...9F are control characters including both bytes of
16-bit characters. The compiler flags these as illegal
characters. These sets are parsed from left to right. The
escape sequences for null-terminated strings are also supported
by these character sets. These sets are parsed
from right to left; for example, the string
#ISO_HEBREW"012345" generates a primitive string "543210"
with character set ISO_HEBREW. A DDIS descriptor for such
a string has this segment marked as being right_to_left.
The escape sequences for null-terminated strings are also
supported by these character sets, and the characters that
compose the escape sequences are in left-to-right order.
For example, you type \n, not n\. These sets are parsed
from left to right; for example, the string
#ISO_HEBREW_LR"012345" generates a primitive string
"012345" with character set ISO_HEBREW. A DDIS descriptor
for such a string marks this segment as being
left_to_right. The escape sequences for null-terminated
strings are also supported by these character sets. This
set is parsed from left to right. The escape sequences
for null-terminated strings are also supported by this
character set. Note that the \ (backslash) may be displayed
as a yen symbol.
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: Backspace Formfeed
Newline Carriage return Horizontal tab Vertical tab
Single quotation mark Double quotation mark Backslash
Character whose internal representation is given by integer
(in the range 0 to 255 decimal)
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 [Toc] [Back]
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 [Toc] [Back]
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
Declaration Data Type Used As Storage Requirements
Per Use
---------------------------------------------------------------------
In-line Null-terminated Null-terminated An allocation and
a reference
(within the module)
Private Null-terminated Null-terminated A reference
(within the module)
Exported Null-terminated Null-terminated A reference
(within the UID
hierarchy)
Imported Null-terminated Null-terminated A reference
(within the UID
hierarchy)
In-line Null-terminated Compound An allocation and
a reference
(within the module)
Private Null-terminated Compound An allocation and
a reference
(within the module)
Exported Null-terminated Compound A reference
(within the UID
hierarchy)
Imported Null-terminated Compound A reference
(within the UID
hierarchy)
In-line Compound Compound An allocation and
a reference
(within the module)
Private Compound Compound A reference
(within the module)
Exported Compound Compound A reference
(within the UID
hierarchy)
Imported Compound Compound A reference
(within the UID
hierarchy)
---------------------------------------------------------------------
Integer Literals [Toc] [Back]
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 long 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)
----------------------------------------------------------------
Boolean Literal [Toc] [Back]
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.
Data storage consumption for Boolean literals is the same
as that for integer literals.
Floating-Point Literal [Toc] [Back]
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 floatingpoint
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)
.1 E-1 (no decimal point or digits)
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.
The ANY Data Type [Toc] [Back]
The purpose of the ANY data type is to shut off the datatype
checking feature of the UIL compiler. You can use the
ANY data type for the following: Specifying the type of a
callback procedure tag Specifying the type of a userdefined
argument
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.
Expressions [Toc] [Back]
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: One of the operands is a compound string The
operands have different character set properties The
operands have different writing directions
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.
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. If
the operands are an integer and a boolean, the boolean is
converted to an integer. If the operands are an integer
and a floating-point, the integer is converted to an
floating-point. If the operands are a floating-point and
a boolean, the boolean is converted to a floating-point.
You can also explicitly convert the data type of a value
by using one of the conversion functions INTEGER, FLOAT or
SINGLE_FLOAT.
Functions [Toc] [Back]
UIL provides functions to generate the following types of
values: Character sets Keysyms Colors Pixmaps Single-precision,
floating-point numbers Double-precision, floatingpoint
numbers Fonts Fontsets Font tables Compound strings
Compound string tables ASCIZ (null-terminated) string
tables Wide character strings Widget class names Integer
tables Arguments Reasons Translation tables
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. 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.
The result of the CHARACTER_SET function is a character
set with the name string_expression and the
properties you specify. String_expression must be
a null-terminated string. You can optionally
include one or both of the following clauses to
specify properties for the resulting character set:
RIGHT_TO_LEFT = boolean_expression SIXTEEN_BIT =
boolean_expression
The RIGHT_TO_LEFT clause sets the default writing
direction of the string from right to left if
boolean_expression is True, and right to left otherwise.
The SIXTEEN_BIT clause allows the strings associated
with this character set to be interpreted as
16-bit characters if boolean_expression is True,
and 8-bit characters otherwise. The KEYSYM function
is used to specify a keysym for a mnemonic
resource. The string_literal must contain exactly
one character. The COLOR function supports the
definition of colors. Using the COLOR function, you
can designate a value to specify a color and then
use that value for arguments requiring a color
value. The string expression names the color you
want to define; the optional keywords FOREGROUND
and BACKGROUND identify how the color is to be displayed
on a monochrome device when the color is
used in the definition of a color table.
The UIL compiler does not have built-in color
names. Colors are a server-dependent attribute of
an object. Colors are defined on each server and
may have different red-green-blue (RGB) values on
each server. The string you specify as the color
argument must be recognized by the server on which
your application runs.
In a UID file, UIL represents a color as a character
string. MRM calls X translation routines that
convert a color string to the device-specific pixel
value. If you are running on a monochrome server,
all colors translate to black or white. If you are
on a color server, the color names translate to
their proper colors if the following conditions are
met: The color is defined. The color map is not
yet full.
If the color map is full, even valid colors translate
to black or white (foreground or background).
Interfaces do not, in general, specify colors for
widgets, so that the selection of colors can be
controlled by the user through the file.
To write an application that runs on both
monochrome and color devices, you need to specify
which colors in a color table (defined with the
COLOR_TABLE function) map to the background and
which colors map to the foreground. UIL lets you
use the COLOR function to designate this mapping in
the definition of the color. The following example
shows how to use the COLOR function to map the
color red to the background color on a monochrome
device:
VALUE c: COLOR ( 'red',BACKGROUND );
The mapping comes into play only when the MRM is
given a color and the application is to be displayed
on a monochrome device. In this case, each
color is considered to be in one of the following
three categories: The color is mapped to the background
color on the monochrome device. The color
is mapped to the foreground color on the monochrome
device. Monochrome mapping is undefined for this
color.
If the color is mapped to the foreground or background
color, MRM substitutes the foreground or
background color, respectively. If you do not
specify the monochrome mapping for a color, MRM
passes the color string to the Motif Toolkit for
mapping to the foreground or background color. The
three integers define the values for the red,
green, and blue components of the color, in that
order. The values of these components can range
from 0 to 65,535, inclusive.
In a UID file, UIL represents an RGB value as three
integers. MRM calls X translation routines that
convert the integers to the device-specific pixel
value. If you are running on a monochrome server,
all colors translate to black or white. If you are
on a color server, RGB values translate to their
proper colors if the colormap is not yet full. If
the colormap is full, values translate to black or
white (foreground or background). The color
expression is a previously defined color, a color
defined in line with the COLOR function, or the
phrase BACKGROUND COLOR or FOREGROUND COLOR. The
character can be any valid UIL character.
The COLOR_TABLE function provides a device-independent
way to specify a set of colors. The
COLOR_TABLE function accepts either previously
defined UIL color names or in line color definitions
(using the COLOR
|