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:
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).
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.
XSetLocaleModifiers()
function specifying the empty string.
setlocale(LC_ALL, NULL);
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.
By supplying its own language procedure, an application can use any procedure it wants for setting the language string.
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:
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);
XmFONTLIST_DEFAULT_TAG
is used. Here are some examples.
*fontList: fixed
*fontList: \
-adobe-courier-medium-r-normal--10-100-75-75-M-60-iso8859-1
*fontList: fixed=ROMAN, 8x13bold=BOLD
*fontList: fixed, 8x13bold=BOLD
XmFONTLIST_DEFAULT_TAG
is used. Here are some examples of specifying a font set.
*fontList: -dt-application-medium-r-normal-*-m*-*-*-*-m-*
*fontList: -dt-application-medium-r-normal-*-m*-*-*-*-m*:MY_TAG
*fontList:-dt-application-medium-r-normal-*-m*-*-*-*-m-*:,\
-dt-application-medium-r-normal-style2-m*-*-*-*-m-*:BOLD
XmFontList()
data type can contain one or more entries that are associated with one of the following elements:
XFontStruct
XFontSet
XFontStruct
fonts used to draw text encoded in a locale, that is, localized text.
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.
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.
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.A compound string component can be one of the following four types:
XmFONTLIST_DEFAULT_TAG
indicates that the text is encoded in the code set of the current locale.
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.
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. 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);
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
. The desktop follows a set search procedure when it binds a compound string to a font list entry in this way:
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 .
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.
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 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:
XmFONTLIST_DEFAULT_TAG
. If a match is found, it uses that font list entry. No further searching occurs.
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.
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:
XmIm
reference functions.
Text
child widget in a multiple Text
children widget tree by changing the focus.
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.
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.
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.
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.
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.
*fontList: -*-r-*-20-*:
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:
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
.
XmFALLBACK_CHARSET
if the LANG
environment variable is not set or has no code set.
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.
*preeditType: OverTheSpot, OffTheSpot, Root, or None
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:
xnlLanguage
resource or LC_CTYPE category.
xnlLanguage
resource or the LC_CTYPE
category.
XAPPLRESDIR
environment variable is set, the MrmOpenHierarchy()
function searches the UID file in the following order:
$UIDPATH
$XAPPLRESDIR/
%L/uid/
%N/
%U
$XAPPLRESDIR/
%l/uid/
%N/
%U
$XAPPLRESDIR/uid/
%N/
%U
$XAPPLRESDIR/
%L/uid/
%U
$XAPPLRESDIR/
%l/uid/
%U
$XAPPLRESDIR/uid/
%U
$HOME/uid/
%U
$HOME/
%U
/usr/lib/X11/
%L/uid/
%N/
%U
/usr/lib/X11/
%l/uid/
%N/
%U
/usr/lib/X11/uid/
%N/
%U
/usr/lib/X11/
%L/uid/
%U
/usr/lib/X11/
%l/uid/
%U
/usr/lib/X11/uid/
%U
/usr/include/X11/uid/
%U
XAPPLRESDIR
environment variable is not set, the MrmOpenHierarchy()
function uses $HOME
instead of the XAPPLRESDIR
environment variable.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.
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}
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:
The syntax of a string literal is one of the following:
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.
-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
.
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.
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.