Common Desktop Environment: Internationalization Programmer's Guide

# 4 Motif Dependencies

Contents of Chapter:

Locale Management

Font Management
  Font List Structure
  Font Lists Examples
  Font List Syntax

Drawing Localized Text
  Compound String Components
  Compound Strings and Font Lists
  Text and TextField Widgets and Font Lists

Inputting Localized Text
  Geometry Management
  Focus Management

Internationalized User Interface Language
  Programming for Internationalized User Interface Language
  default_charset Character Set in UIL
  Compound Strings in UIL

This chapter discusses tasks related to internationalizing with Motif.

## Locale Management

The term language environment refers to the set of localized data that the application needs to run correctly in the user-specified locale. A language environment supplies the rules associated with a specific language. In addition, the language environment consists of any externally stored data, such as localized strings or text used by the application. For example, the menu items displayed by an application might be stored in separate files for each language supported by the application. This type of data can be stored in resource files, User Interface Definition (UID) files, or message catalogs (on XPG3-compliant systems).

A single language environment is established when an application runs. The language environment in which an application operates is specified by the application user, often either by setting an environment variable (`LANG` or `LC_*` on POSIX-based systems) or by setting the xnlLanguage resource. The application then sets the language environment based on the user's specification. The application can do this by using the `setlocale()` function in a language procedure established by the `XtSetLanguageProc()` function. This causes Xt to cache a per-display language string that is used by the `XtResolvePathname()` function to find resource, bitmap, and User Interface Language (UIL) files.

An application that supplies a language procedure can either provide its own procedure or use an Xt default procedure. In either case, the application establishes the language procedure by calling the `XtSetLanguageProc()` function before initializing the toolkit and before loading the resource databases (such as by calling the `XtAppInitialize()` function). When a language procedure is installed, Xt calls it in the process of constructing the initial resource database. Xt uses the value returned by the language procedure as its per-display language string.

The default language procedure performs the following tasks:

- Sets the locale. This is done by using:

      setlocale(LC_ALL, language);

  where language is the value of the `xnlLanguage` resource, or the empty string ("") if the `xnlLanguage` resource is not set. When the `xnlLanguage` resource is not set, the locale is generally derived from an environment variable (`LANG` on POSIX-based systems).

- Calls the `XSupportsLocale()` function to verify that the locale just set is supported. If not, a warning message is issued and the locale is set to C.

- Calls the `XSetLocaleModifiers()` function specifying the empty string.

- Returns the value of the current locale. On ANSI C-based systems, this is the result of calling:

      setlocale(LC_ALL, NULL);

The application can use the default language procedure by making the call to the `XtSetLanguageProc()` function in the following manner:

    XtSetLanguageProc(NULL, NULL, NULL);
            .
            .
    toplevel = XtAppInitialize(...);

By default, Xt does not install any language procedure. If the application does not call the `XtSetLanguageProc()` function, Xt uses as its per-display language string the value of the `xnlLanguage` resource if it is set. If the `xnlLanguage` resource is not set, Xt derives the language string from the `LANG` environment variable.

Note: The per-display language string that results from this process is implementation-dependent, and Xt provides no public means of examining the language string once it is established.

By supplying its own language procedure, an application can use any procedure it wants for setting the language string.

## Font Management

The desktop uses font lists to display text. A font defines a set of glyphs that represent the characters in a given character set. A font set is a group of fonts that are needed to display text for a given locale or language. A font list is a list of fonts, font sets, or a combination of the two, that may be used. Motif has convenience functions to create a font list.

### Font List Structure

The desktop requires a font list for text display. A font list is a list of font structures, font sets, or both, each of which has a tag to identify it. A font set ensures that all characters in the current language can be displayed. With font structures, the responsibility for ensuring that all characters can be displayed rests with the programmer (including converting from the code set of the locale to glyph indexes).

Each entry in a font list is in the form of a {tag , element } pair, where element can be either a single font or a font set. The application can create a font list entry from either a single font or a font set. For example, the following code segment creates a font list entry for a font set:

    char font1[] =
            "-adobe-courier-medium-r-normal--10-100-75-75-M-60";
    font_list_entry = XmFontListEntryLoad (displayID, font1,
            XmFONT_IS_FONTSET, "font_tag");

The `XmFontListEntryLoad()` function loads a font or creates and loads a font set. The following are the four arguments to the function:

displayID
  Display on which the font list is to be used.

fontname
  A string that represents either a font name or a base font name list, depending on the nametype argument.

nametype
  A value that specifies whether the fontname argument refers to a font name or a base font name list.

tag
  A string that represents the tag for this font list entry.

If the nametype argument is `XmFONT_IS_FONTSET` , the `XmFontListEntryLoad()` function creates a font set in the current locale from the value in the fontname argument. The character sets of the fonts specified in the font set are dependent on the locale. If nametype is `XmFONT_IS_FONT` , the `XmFontListEntryLoad()` function opens the font found in fontname . In either case, the font or font set is placed into a font list entry.

The following code example creates a new font list and appends the entry`` `font_list_entry` to it:

    XmFontList font_list;
    XmFontListEntry font_list_entry;
            .
            .
    font_list = XmFontListAppendEntry (NULL, font_list_entry);
    XmFontListEntryFree (font_list_entry);

Once a font list has been created, the `XmFontListAppendEntry()` function adds a new entry to it. The following example uses the `XmFontListEntryCreate()` function to create a new font list entry for an existing font list.

    XFontSet font2;
    char *font_tag;
    XmFontListEntry font_list_entry2;
            .
            .
    font_list_entry2 = XmFontListEntryCreate (font_tag,
             XmFONT_IS_FONTSET, (XtPointer)font2);

The `font2` parameter specifies an `XFontSet` returned by the `XCreateFontSet()` function. The arguments to the `XmFontListEntryCreate()` function are `font_tag` , `XmFONT_IS_FONTSET` , and `font2` , which are the tag, type, and font, respectively. The tag and the font set are the {tag , element } pair of the font list entry.

To add this entry to the font list, use the `XmFontListAppendEntry()` function again, only this time, its first parameter specifies the existing font list.

    font_list = XmFontListAppendEntry(font_list, font_list_entry2);
    XmFontListEntryFree(font_list_entry2);

### Font Lists Examples

The syntax for specifying a font list in a resource file depends on whether the list contains fonts, font sets, or both.

#### Obtaining a Font

To obtain a font, specify a font and an optional font list element tag.

- If the tag is present, it should be preceded by an = (equal sign).

- If the tag is not present, do not use an = (equal sign).

Entries specifying more than one font are separated by a , (comma).

#### Obtaining a Font Set

To obtain a font set, specify a base font list and an optional font list element tag.

- If the tag is present, it should be preceded by a : (colon) instead of an = (equal sign).

- If the tag is not present, the colon must still be present as this is what distinguishes a font from a font set in the resource declaration.

Fonts specified in the base font list are separated by a ; (semicolon). Entries specifying more than one font set are separated by a , (comma).

#### Specifying a Font When the Font List Element Tag Is Absent

If the font list element tag is not present, the default `XmFONTLIST_DEFAULT_TAG` is used. Here are some examples.

- Specifying a font using the default font list element tag:

      *fontList: fixed
      *fontList: \
       -adobe-courier-medium-r-normal--10-100-75-75-M-60-iso8859-1

- Specifying a font list element tag:

      *fontList: fixed=ROMAN, 8x13bold=BOLD

- Specifying two fonts, one with the default font list element tag and one with an explicit tag:

      *fontList: fixed, 8x13bold=BOLD

#### Specifying a Font Set When the Font List Element Tag Is Absent

If the font list element tag is not present, the default `XmFONTLIST_DEFAULT_TAG` is used. Here are some examples of specifying a font set.

- Let Xlib select the fonts without specifying a font list element tag:

      *fontList: -dt-application-medium-r-normal-*-m*-*-*-*-m-*

- Let Xlib select the fonts and specify a font list element tag as MY_TAG:

      *fontList: -dt-application-medium-r-normal-*-m*-*-*-*-m*:MY_TAG

- Let Xlib select the fonts, specify a font list element tag for bold fonts, and use the default font list element tag for the others:

      *fontList:-dt-application-medium-r-normal-*-m*-*-*-*-m-*:,\
       -dt-application-medium-r-normal-style2-m*-*-*-*-m-*:BOLD

### Font List Syntax

The `XmFontList()` data type can contain one or more entries that are associated with one of the following elements:

`XFontStruct`
  An X font that can be used to draw text encoded in the charset of the font, that is, font-encoded text.

`XFontSet`
  A collection of `XFontStruct` fonts used to draw text encoded in a locale, that is, localized text.

The following syntax is used by the string-to-`XmFontList` converter:

    XmFontList := <fontentry> {', 'fontentry}

    fontentry  := <fontname><fontid>
                | <baselist><fontsetid>

    baselist   := <fontname>{';'<fontname>}

    fontsetid  := ':'<string> | <defaultfontset>

    fontname   := <XLFD string>

    fontid     := '='<string> | <defaultfont>

    XLFD string := refer to XLFD Specification
    defaultfont := NULL
    defaultfontset := ':'NULL
    string    := any character from ISO646IRV, except newline

A `fontentry` with a given `XmFontList` can specify either a font or a font set. In either case, the ID (`fontid` or `fontsetid` ) can be referenced by a segment within a compound string (`XmString` ).

Both `defaultfont` and `defaultfontset` can define the default `fontentry`, yet there can only be one default per `XmFontList`.

The `XmFONTLIST_DEFAULT_TAG` identifier always references the default `fontentry` when `XmString` is drawn. If the default `fontentry` is not specified, the first `fontentry` is used to draw.

The resource converter operates under a single locale so that all font sets created are associated with the same locale.

Note: Some implementations reserve the code set name of a locale as a special charset ID (`fontsetid` and `fontid` ) within an `XmFontList` string. For this reason, application developers are cautioned not to use code set names if they want their applications to be portable across platforms.

## Drawing Localized Text

A compound string is a means of encoding text so that it can be displayed in many different fonts without changing anything in the program. The desktop uses compound strings to display all text except that in the `Text` and `TextField` widgets. This section explains the structure of a compound string, the interaction between it and a font list (which determines how the compound string is displayed), and focuses on those aspects that are important to the internationalization process.

### Compound String Components

A compound string is an internal encoding, consisting of tag-length-value segments. Semantically, a compound string has components that contain the text to be displayed, a tag (called a font list element tag) that is matched with an element of a font list, and an indicator denoting the direction in which it is to be displayed.

A compound string component can be one of the following four types:

- A font list element tag.

  - The font list element tag `XmFONTLIST_DEFAULT_TAG` indicates that the text is encoded in the code set of the current locale.

  - Other font list element tags are used later to match text with particular entries in a font list.

- A direction identifier.

- The text of the string. For internationalized applications, the text falls into two broad categories: either the text requires localized treatment or it does not.

- A separator.

The following describes each of the compound string components:

Font list element tag
  Indicates a string value that correlates the text component of a compound string to a font or a font set in a font list.

Direction
  Indicates the relationship between the order in which characters are entered on the keyboard and the order in which the characters are displayed on the screen. For example, the display order is left-to-right in English, French, German, and Italian, and right-to-left in Hebrew and Arabic.

Text
  Indicates the text to be displayed.

Separator
  Indicates a special form of a compound string component that has no value. It is used to separate other segments.

The desktop uses the specified font list element tag identified in the text component to display the compound string. A specified font list element tag is used until a new font list element tag is encountered. The desktop provides a special font list element tag, `XmFONTLIST_DEFAULT_TAG` , that matches a font that is correct for the current code set. It identifies the default entry in a font list. See "Compound Strings and Font Lists" for more information.

The direction segment of a compound string specifies the direction in which the text is displayed. Direction can be left-to-right or right-to-left.

#### Compound Strings and Resources

Compound strings are used to display all text except that in the `Text` and `TextField` widgets. The compound string is set into the appropriate widget resource so that it can be displayed. For example, the label for the`PushButton` widget is inherited from the `Label` widget, and the resource is `XmNlabelString` , which is of type `XmString` . This means that the resource expects a value that is a compound string. A compound string can be created with a program or defined in a resource file.

#### Setting a Compound String Programmatically

An application can set this resource programmatically by creating the compound string using the `XmStringCreateLocalized()` compound string convenience function.

This function creates a compound string in the encoding of the current locale and automatically sets the font list entry tag to `XmFONTLIST_DEFAULT_TAG`.

The following code segment shows one way to set the `XmNlabelString` resource for a push button using a program.

    #include <nl_types.h>
    Widget button;
    Args   args[10];
    int    n;
    XmString button_label;
    nl_msg my_catd;
    (void)XtSetLanguageProc(NULL,NULL,NULL);
            .
            .
    button_label = XmStringCreateLocalized (catgets(my_catd, 1, 1,
                     "default label"),
                     XmFONTLIST_DEFAULT_TAG);

    /* Create an argument list for the button */
    n = 0;
    XtSetArg (args[n], XmNlabelString, button_label); n++;

    /* Create and manage the button */
    button = XmCreatePushButton (toplevel, "button", args, n);
    XtManageChild (button);
    XmStringFree (button_label);

#### Setting a Compound String in a Defaults File

In an internationalized program, the label string for the button label should be obtained from an external source. For example, the button label can come from a resource file instead of the program. For this example, assume that the push button is a child of a Form widget called `form1` .

    *form1.button.labelString: Push Here

Here, the desktop's string-to-compound-string converter produces a compound string from the resource file text. This converter always uses `XmFONTLIST_DEFAULT_TAG`.

### Compound Strings and Font Lists

When the desktop displays a compound string, it associates each segment with a font or font set by means of the font list element tag for that segment. The application must have loaded the desired font or font set, created a font list that contains that font or font set and its associated font list element tag, and created the compound string segment with the same tag.

The desktop follows a set search procedure when it binds a compound string to a font list entry in this way:

1. The desktop searches the font list for an exact match with the font list element tag specified in the compound string. If it finds a match, the compound string is bound to that font list entry.

2. If this does not provide a binding between the compound string and the font list, the desktop binds the compound string to the first element in the font list, regardless of its font list element tag.

For backward compatibility, if an exact match is not found, a value of `XmFONTLIST_DEFAULT_TAG` in either a compound string or a font list matches the tag that results from creating a compound string or font list entry with a tag of `XmSTRING_DEFAULT_CHARSET` .

Figure 4-1 shows the relationships between a compound string, a font set, and a font list when the font list element tag is set to something other than `XmFONTLIST_DEFAULT_TAG` .

Figure 4-1 Relationships between compound strings, font sets, and font lists when the font list element tag is not XmFONTLIST_DEFAULT_TAG

The following example shows how to use a tag called `tagb`.

    XFontSet   *font1;
    XmFontListEntry font_list_entry;
    XmFontList font_list;
    XmString label_text;
    char**     missing;
    int        missing_cnt;
    char*      del_string;
    char *tagb;    /* Font list element tag */
    char *fontx;   /* Initialize to XLFD or font alias */
    char *button_label; /* Contains button label text */
            .
            .
    font1 = XCreateFontSet (XtDisplay(toplevel), fontx, & missing,
            & missing_cnt, & def_string);
    font_list_entry = XmFontListEntryCreate (tagb, XmFONT_IS_FONTSET,
            (XtPointer)font1);
    font_list = XmFontListAppendEntry (NULL, font_list_entry);
    XmFontListEntryFree (font_list_entry);

    label_text = XmStringCreate (button_label, tagb);

The`XCreateFontSet()` `` function loads the font set and the `XmFontListEntryCreate()` `` function creates a font list entry. The application must create an entry and append it to an existing font list or create a new font list. In either case, use the`XmFontListAppendEntry()` `` function. Because there is no font list in place, the preceding code example has a NULL value for the font list argument. The`XmFontListAppendEntry()` `` function creates a new font list called `font_list` with a single entry, `font_list_entry` . To add another entry to `font_list` , follow the same procedure but supply a nonnull font list argument.

Figure 4-2 shows the relationships between a compound string, a font set, and a font list when the font list element tag is set to `XmFONTLIST_DEFAULT_TAG` . In this case, the value field is locale text.

Figure 4-2 Relationships between compound strings, font sets, and font lists when a font list element tag is set to XmFONTLIST_DEFAULT_TAG

Here, the default tag points to Font_Set_C, which in turn identifies the fonts needed to display the characters in the language.

### Text and TextField Widgets and Font Lists

The `Text` and `TextField` widgets display text information. To do so, they must be able to select the correct font in which to display the information. The `Text` and `TextField` widgets follow a set search pattern to find the correct font as follows:

1. The widget searches the font list for an entry that is a font set and has a font list element tag of `XmFONTLIST_DEFAULT_TAG` . If a match is found, it uses that font list entry. No further searching occurs.

2. The widget searches the font list for an entry that specifies a font set. It uses the first one found.

3. If no font set is found, the widget uses the first font in the font list.

Using a font set ensures that there are glyphs for every character in the locale.

## Inputting Localized Text

In the system environment, the `VendorShell` widget class is enhanced to provide the interface to the input method. While the VendorShell class controls only one child widget in its geometry management, an extension has been added to the VendorShell class to enhance it for managing all components necessary in the interface to an input method. These components include the status area, preedit area, and the MainWindow area.

When the input method requires a status area or a preedit area or both, the `VendorShell` widget automatically instantiates the status and preedit areas and manages their geometry layout. Any status area or preedit area is managed by the `VendorShell` widget internally and is not accessible by the client. The widget instantiated as the child of the `VendorShell` widget is called the MainWindow area.

The input method to be used by the `VendorShell` widget is determined by the `XmNinputMethod` resource; for example, `@im=alt` . The default value of Null indicates to choose the default input method associated with the locale at the time that VendorShell is created. As such, the user can affect which input method is selected by either setting the locale, setting the `XmNinputMethod` resource, or setting both. The locale name is concatenated with the `XmNinputMethod` resource to determine the input method name. The locale name must not be specified in this resource. The modifier name for the `XmNinputMethod` resource needs to be in the form `@im=` modifier , where modifier is the string used to qualify which input method is selected.

The `VendorShell` widget can support multiple widgets that can share the input method. Yet only one widget can have the keyboard focus (for example, receive key press events and send them to an input method) at any given time. To support multiple widgets (such as `Text` widgets), the widgets need to be descendants of the `VendorShell` widget.

Note: The `VendorShell` widget class is a superclass of the `TransientShell` and `TopLevelShell` widget classes. As such, an instantiation of a `TopLevelShell` or a `DialogShell` is essentially an instantiation of a `VendorShell` widget class.

The `VendorShell` widget behaves as an input manager only if one of its descendants is an `XmText[Field]` instance. As soon as an `XmText[Field]` instance is created as a descendant of the `VendorShell` widget, `VendorShell` creates the necessary areas required by the particular input methods dictated by the current locale. Even if an `XmText[Field]` instance is not mapped but just created, VendorShell has the geometry management behavior as described previously.

A `VendorShell` widget does the following:

- Enables applications to process multibyte character input and output that is supported by the locales installed in the system.

- Manages an input method instance as defined in the `XmIm` reference functions.

- Supports preediting within a preedit area in either OffTheSpot, OverTheSpot, Root, or None mode. Localized text can be entered into any `Text` child widget in a multiple `Text` children widget tree by changing the focus.

- Provides geometry management for descendant child widgets.

### Geometry Management

The `VendorShell` widget provides geometry management and focus management for the input method's user interface components, as necessary. If the locale warrants it (for example, if the locale is a Japanese Extended UNIX Code (EUC) locale), the `VendorShell` widget automatically allocates and manages the geometry of any required preedit area or status area or both.

Depending on the current preediting being done, an auxiliary area may be required. If so, the `VendorShell` widget also instantiates and manages the auxiliary area. Typically, the child of the `VendorShell` widget is a container widget (such as the `XmBulletinBoard` or `XmRowColumn` widgets) that can manage multiple `Text` and `TextField` widgets, which allow multibyte character input from the user. In this scenario, all `Text` widgets share the same input method.

Note: The status, preedit, and auxiliary areas are not accessible to the application programmer. For example, it is not intended for the application programmer to access the window ID of the status area. The user does not need to worry about the instantiation or management of these components as they are managed as required by the `VendorShell` widget class.

The application programmer has some control over the behavior of the input method user interface components through `XmNpreeditType` resources of the `VendorShell` widget class. See "Input Methods" for a description of OffTheSpot and OverTheSpot modes.

Geometry management extends to all input method user interface components. When the application program window (a `TopLevelShell` widget) is resized, the input method user interface components are resized accordingly, and the preedited strings in them are rearranged as required. Of course, this assumes that the shell window has a resize policy of True.

When the `VendorShell` widget is created, if a specific input method requires a status area, preedit area, or both, the size of the VendorShell considers the areas required by these components. The extra areas required by the preedit and status areas are part of the `VendorShell` widget's area. They are also managed by the `VendorShell` widget, if resizing is necessary.

Because of the potential instantiation of these areas (status and preedit), depending on the input method currently being used, the size of the `VendorShell` widget area does not necessarily grow or shrink to accommodate exactly the size of its child. The size of the `VendorShell` widget area grows or shrinks to accommodate both its child's geometry and the geometry of these input method user interface areas. There may be a difference (for example, of 20 pixels) in height between the `VendorShell` widget and its child widget (the MainWindow area). The width geometry is not affected by the input method user interface components.

In summary, the requested size of the child is honored if possible; the actual size of the `VendorShell` may be larger than its child.

The requests to specify the geometry of the `VendorShell` widget and its child are honored as long as they do not conflict with each other or are within the constraint of the `VendorShell` widget's ability to resize. When they do conflict, the child's widget geometry request has higher precedence. For example, if the size of the child widget is specified as 100x100, the size of VendorShell is also specified as 100x100. The resulting VendorShell has a size of 100x120, while its child widget gets a size of 100x100. If the size of the child widget is not specified, the VendorShell shrinks its child widget if necessary to honor its own size specification. For example, if the size of VendorShell is specified as 100x100 and no size is specified for its child, the child widget has a size of 100x80. If the `VendorShell` widget is disabled from resizing, regardless of what the geometry request of its child is, the `VendorShell` widget honors only its own geometry specification.

### Focus Management

Languages with large numbers of characters (such as Japanese and Chinese) require an input method that allows the user to compose characters in that language interactively. This is because, for these languages, there are many more characters than can be reasonably mapped to a terminal keyboard.

The interactive process of composing characters in such languages is called preediting . The preediting itself is handled by the input method. However, the user interface of the preediting is determined by the system environment. An interface needs to exist between the input method and the system environment. This is done through the `VendorShell` widget of the system environment.

Figure 4-3 illustrates a case with Japanese preediting. The string shown in reverse video is the string in preediting. This string can be moved across different windows by giving focus to the particular window. However, only one preediting session can occur at one time.

Figure 4-3 Japanese preediting example

For an example of focus management, suppose a `TopLevelShell` widget (a subclass of the `VendorShell` widget) has an `XmBulletinBoard` widget child (MainWindow area), which has five `XmText` widgets as children. Assume the locale requires the preedit area, and assume the OverTheSpot mode is specified. Because the `VendorShell` widget manages only one instance of an input method, you can run only one preedit area at a time inside the `TopLevelShell` widget. If the focus is moved from one `Text` widget to another, the current preedit string under construction is also moved on top of the `Text` widget that currently has focus. Processing of keys to the old `Text` widget is suspended temporarily. Subsequent interface of the input method, such as the delivery of the string at preedit completion, is made to the new, focused `Text` widget.

The string being preedited can be moved to the location of the focus; for example, by clicking the mouse.

A string that the end user is finished preediting and that is already confirmed cannot be reconverted. Once the string is composed, it is committed. Committing a string means that it is moved from the preedit area to the focus point of the client.

## Internationalized User Interface Language

The capability to parse a multibyte character string as a string literal has been added to the User Interface Language (UIL). Creation of a UIL file is performed by using the characteristics of the target language and writing the User Interface Definition (UID) file.

### Programming for Internationalized User Interface Language

The UIL compiler parses nonstandard charsets as locale text. This requires the UIL compiler to be run in the same locale as any locale text.

If the locale text of a widget requires a font set (more than one font), the font set must be specified within the resource file. The font parameter does not support font sets.

To use a specific language with UIL, a UIL file is written according to characteristics of the target language and compiled into a UID file. The UIL file that contains localized text needs to be compiled in the locale in which it is to run.

#### String Literals

The following shows examples of literal strings. The cur_charset value is always set to the default_charset value, which allows the string literal to contain locale text.

To set locale text in the string literal with the default_charset value, enter the following:

    XmNlabelString = 'XXXXXX';

OR

    XmNlabelString = #default_charset"XXXXXX";

Compile the UIL file with the `LANG` environment variable matching the encoding of the locale text. Otherwise, the string literal is not compiled properly.

#### Font Sets

The font set cannot be set through UIL source programming. Whenever the font set is required, you must set it in the resource file as the following example shows:

    *fontList: -*-r-*-20-*:

#### Font Lists

UIL has three functions that are used to create font lists: `FONT` , `FONTSET` , and `FONT_TABLE` . The `FONT` and `FONTSET` functions create font list entries. The `FONT_TABLE` function creates a font list from these font list entries.

The `FONT` function creates a font list entry containing a font specification. The argument is a string representing an XLFD font name. The `FONTSET` function creates a font list entry containing a font set specification. The argument is a comma-separated list of XLFD font names representing a base name font list.

Both `FONT` and `FONTSET` have optional `CHARACTER_SET` declaration parameters that specify the font list element tag for the font list entry. In both cases, if no `CHARACTER_SET` declaration parameter is specified, UIL determines the font list element tag as follows:

- If the module contains no `CHARACTER_SET` declaration and if the `uil` command was called with the `-s` option or the `Uil()` function was started with use_setlocale_flag set, the font list element tag is `XmFONTLIST_DEFAULT_TAG` .

- Otherwise, the font list element tag is the code set component of the `LANG` environment variable, if it is set in the UIL compilation environment; or it is the value of `XmFALLBACK_CHARSET` if the `LANG` environment variable is not set or has no code set.

The `FONT_TABLE` function creates a font list from a comma-separated list of font list entries created by `FONT` or `FONTSET` . The resulting font list can be used as the value of a font list resource. If a single font list entry is supplied as the value for such a resource, UIL converts the entry to a font list.

#### Creating Resource Files

If necessary, set the input method-related resources in the resource file as shown in the following example:

    *preeditType: OverTheSpot, OffTheSpot, Root, or None

#### Setting the Environment

For a locale-sensitive application, set the UID file to the appropriate directory. Set the `UIDPATH` or `XAPPLRESDIR` environment variable to the appropriate value.

For example, to run the `uil_sample` program with an English environment (`LANG` environment variable is `en_US` ), set `uil_sample.uid` with Latin characters at the `$HOME/en_US` directory, or set `uil_sample.uid` to a directory and set the `UIDPATH` environment variable to the full path name of the `uil_sample.uid` file.

To run the `uil_sample` program with a Japanese environment (`LANG` environment variable is `ja_JP` ), create a `uil_sample.uid` file with Japanese (multibyte) characters at the `$HOME/ja_JP` directory, or place `uil_sample.uid` to a unique directory and set the `UIDPATH` environment variable to the full path name of the `uil_sample.uid` file. The following list specifies the possible variables:

%U
  Specifies the UID file string.

%N
  Specifies the class name of the application.

%L
  Specifies the value of the `xnlLanguage` resource or `LC_CTYPE` category.

%l
  Specifies the language component of the `xnlLanguage` resource or the `LC_CTYPE` category.

If the `XAPPLRESDIR` environment variable is set, the `MrmOpenHierarchy()` function searches the UID file in the following order:

1. UID file path name

2. `$UIDPATH`

3. %U

4. `$XAPPLRESDIR/`%L`/uid/`%N`/`%U

5. `$XAPPLRESDIR/`%l`/uid/`%N`/`%U

6. `$XAPPLRESDIR/uid/`%N`/`%U

7. `$XAPPLRESDIR/`%L`/uid/`%U

8. `$XAPPLRESDIR/`%l`/uid/`%U

9. `$XAPPLRESDIR/uid/`%U

10. `$HOME/uid/`%U

11. `$HOME/`%U

12. `/usr/lib/X11/`%L`/uid/`%N`/`%U

13. `/usr/lib/X11/`%l`/uid/`%N`/`%U

14. `/usr/lib/X11/uid/`%N`/`%U

15. `/usr/lib/X11/`%L`/uid/`%U

16. `/usr/lib/X11/`%l`/uid/`%U

17. `/usr/lib/X11/uid/`%U

18. `/usr/include/X11/uid/`%U

If the `XAPPLRESDIR` environment variable is not set, the `MrmOpenHierarchy()` function uses `$HOME` instead of the `XAPPLRESDIR` environment variable.

### default_charset Character Set in UIL

With the default_charset string literal, any characters can be set as a valid string literal. For example, if the `LANG` environment variable is `el_GR` , the string literal with default_charset can contain any Greek character. If the `LANG` environment variable is `ja_JP` , the default_charset string literal can contain any Japanese character encoded in Japanese EUC.

If no character set is set to a string literal, the character set of the string literal is set as cur_charset. And, in the system environment, the cur_charset value is always set as default_charset.

#### Example: uil_sample

Figure 4-4 shows a UIL sample program on English and Japanese environments.

Figure 4-4 Sample UIL program on English and Japanese environments

In the following sample program, LLL indicates locale text, which can be Japanese, Korean, Traditional Chinese, Greek, French, or others.

    uil_sample.uil
    !
    !      sample uil file - uil_sample.uil
    !
    !          C source file - uil_sample.c
    !
    !              Resource file - uil-sample.resource
    !
    module Test
            version = 'v1.0'
            names = case_sensitive
            objects = {
                XmPushButton = gadget;
            }
    !************************************
    !      declare callback procedure
    !************************************
    procedure
            exit_CB;
    !***************************************************************
    !      declare BulletinBoard as parent of PushButton and Text
    !***************************************************************
    object
            bb : XmBulletinBoard {
                arguments{
                    XmNwidth = 500;
                    XmNheight = 200;
                };
                controls{
                    XmPushButton pb1;
                    XmText text1;
                };
            };
    !****************************
    !      declare PushButton
    !****************************
    object
            pb1 : XmPushButton {
                arguments{
                    XmNlabelString = #Normal "LLLexit buttonLLL";
                    XmNx = 50;
                    XmNy = 50;
                };
                callbacks{
                    XmNactivateCallback = procedure exit_CB;
                };
            };
    !*********************
    !      declare Text
    !*********************
            text1 : XmText {
                arguments{
                    XmNx = 50;
                    XmNy = 150;
                 };
            };
    end module;
    *
    *          C source file - uil_sample.c
    *
    */
    #include <Mrm/MrmAppl.h>
    #include <locale.h>
    void exit_CB();
    static     MrmHierarchy   hierarchy;
    static     MrmType *class;

    /******************************************/
    /*      specify the UID hierarchy list */
    /*****************************************/
    static     char *aray_file[]=
                         {"uil_sample.uid"
                         };
    static     int num_file = (sizeof aray_file / sizeof
    aray_file[0]);
    /******************************************************/
    /*     define the mapping between UIL procedure names */
    /*     and their addresses           */
    /******************************************************/
    static     MRMRegisterArg reglist[]={
                         {"exit_CB",(caddr_t) exit_CB}

### Compound Strings in UIL

Three mechanisms exist for specifying strings in UIL files:

- As string literals, which may be stored in UID files as either null-terminated strings or compound strings

- As compound strings

- As wide character strings

Both string literals and compound strings consist of text, a character set, and a writing direction. For string literals and for compound strings with no explicit direction, UIL infers the writing direction from the character set. The UIL concatenation operator (&) concatenates both string literals and compound strings.

Regardless of whether UIL stores string literals in UID files as null-terminated strings or as compound strings, it stores information about each string's character set and writing direction along with the text. In general, UIL stores string literals or string expressions as compound strings in UID files under the following conditions:

- When a string expression consists of two or more literals with different character sets or writing directions

- When the literal or expression is used as a value that has a compound string data type (such as the value of a resource whose data type is compound string)

UIL recognizes a number of keywords specifying character sets. UIL associates parsing rules, including parsing direction and whether characters have 8 or 16 bits, for each character set it recognizes. It is also possible to define a character set using the UIL `CHARACTER_SET` function.

The syntax of a string literal is one of the following:

- '[character_string]'
- [#char_set]
- "[character_string]"

For each syntax, the character set of the string is determined as follows:

- For a string declared as 'character_string ' , the character set is the code set component of the `LANG` environment variable, if it is set in the UIL compilation environment; or it is the value of `XmFALLBACK_CHARSET` if the `LANG` environment variable is not set or has no code set. By default, the value of `XmFALLBACK_CHARSET` is ISO8859-1, but vendors may supply different values.

- For a string declared as #char_set "string", the character set is char_set.

- For a string declared as " character _ string " , the character set depends on whether the module has a `CHARACTER_SET` clause and whether the UIL compiler's `use_setlocale_flag` is set.

  - If the module has a `CHARACTER_SET` clause, the character set is the one specified in that clause.

  - If the module has no `CHARACTER_SET` clause but the`` `uil` `` command was started with the `-s` option, or if the`` `Uil()` `` function was started with `use_setlocale_flag set` , UIL calls the`` `setlocale()` `` function and parses the string in the current locale. The character set of the resulting string is `XmFONTLIST_DEFAULT_TAG` .

  - If the module has no `CHARACTER_SET` clause and the `uil` command was started without the `-s` option, or if the`` `Uil()` `` function was started without `use_setlocale_flag` , the character set is the code set component of the `LANG` environment variable, if it is set in the UIL compilation environment, or the character set is the value of `XmFALLBACK_CHARSET` if `LANG` is not set or has no code set.

UIL always stores a string specified using the `COMPOUND_STRING` function as a compound string. This function takes as arguments a string expression and optional specifications of a character set, direction, and whether to append a separator to the string. If no character set or direction is specified, UIL derives it from the string expression, as described in the preceding section.

Note: Certain predefined escape sequences, beginning with a \ (backslash), may be displayed in string literals, with the following exceptions:
-- A string in single quotation marks can span multiple lines, with each new line character escaped by a backslash. A string in double quotation marks cannot span multiple lines.
-- Escape sequences are processed literally inside a string that is parsed in the current locale (a localized string).

Generated with CERN WebMaker