[Return to Library]  [TOC]  [PREV]  SECT--  [NEXT]  [INDEX] [Help]

5    Creating Internationalized X, Xt, and Motif Applications

This chapter discusses some of the internationalization features that are available for creating a graphical user interface. More specifically, this chapter addresses the following components:

This chapter assumes that you are already familiar with these components. For more complete information on them, refer to the following documents:

In addition to these documents, you can refer to reference pages for individual functions.

This chapter does not discuss internationalization features specific to the Common Desktop Environment. Refer to the Common Desktop Environment: Internationalization Programmer's Guide for information about using these features.


[Return to Library]  [TOC]  [PREV]  SECT--  [NEXT]  [INDEX] [Help]

5.1    Using Internationalization Features in the X Toolkit Intrinsics

The X Toolkit Intrinsics includes internationalization features related to the initialization process and resource management. The following sections describe these features. For complete information on using routines from the X Toolkit Intrinsics Library (libXt) in your applications, refer to X Window System Toolkit and the reference pages for individual components.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.1.1    Establishing a Locale with Xt Functions

An internationalized X application must parse resources in a locale-dependent manner. Therefore, an application must establish its locale before initializing the resource database. The XtSetLanguageProc() function registers a language procedure for setting the locale. By default, this function first calls the Standard C Library function setlocale() to set the locale and then calls the X Library functions XSupportsLocale() and XSetLocaleModifiers() to initialize the locale. An application that uses the X Toolkit routines must call XtSetLanguageProc(); otherwise, the locale is not set and other Xt routines do not behave in a locale-dependent manner. One of the most common ways to set locale is for applications to make the following call before calling XtAppInitialize():
XtSetLanguageProc(NULL,NULL,NULL);
After calling XtSetLanguageProc(), your application can then call one of the following Xt initialization functions:

These functions call XtDisplayInitialize(), which obtains the value of the xnlLanguage resource by parsing the command line and the RESOURCE_MANAGER property. The functions then pass this language value to the language procedure registered by the call to XtSetLanguageProc().


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.1.2    Using Font Set Resources with Xt Functions

The Xt routines support the XFontSet structure in place of the XFontStruct structure in any internationalized widgets that draw native-language text. The following resource attributes exist to support XFontSet:

The X Toolkit includes a converter that changes a preregistered string, such as -*-*-*-R-*-*-*-120-75-75-*-*-*-*, to a list of font sets in the structure (XFontSet). The converter should establish a default font set list so that, if the string cannot be converted to a valid font set list, there is a fallback to a valid font set.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.1.3    Filtering Events During Text Input with Xt Functions

Starting with Release 5 of the X Toolkit Intrinsics, the XtDispatchEvent() function was changed to call XFilterEvent(). This change allows an input method to intercept registered X events before being processed by an application that uses Xt routines.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.1.4    Including the Codeset Component of Locales with Xt Functions

Starting with Release 5 of the X Toolkit Intrinsics, an integral locale entity supports the codeset component, in addition to the language and territory components supported by earlier releases.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.2    Using Internationalization Features of the OSF/Motif and DECwindows Motif Toolkits

The chapter on internationalization features in the OSF/Motif Programmer's Guide discusses how you internationalize Motif applications. The following sections are a supplement to information in that chapter.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.2.1    Setting Language in a Motif Application

Most of the internationalization features in the OSF/Motif Toolkit (libXm) and the DECwindows Extensions to the OSF/Motif Toolkit (libDXm) are supported through features first introduced in Release 5 of the X Library (libX) and the X Toolkit (libXt). For example, to set locale and register a language procedure, you use the same set of functions and guidelines in a Motif application as described for an Xt application in Section 5.1.1. As is true for the X Toolkit library, the OSF/Motif and DECwindows Motif Toolkit libraries do not provide a default language procedure. Therefore, if your application fails to register and create a language procedure, the XmText and XmTextField widgets do not support the internationalization features discussed in subsequent sections; in other words, the widgets revert to behavior expected in releases earlier than the X Toolkit Release 5 and OSF/Motif Release 1.2.

The language for an application can be specified by:

Elements higher on the preceding list take precedence over lower elements. Note the following points:


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.2.2    Using Compound Strings and the XmText, XmTextField, and DXmCSText Widgets

The OSF/Motif XmText and XmTextField widgets provide internationalization features based on the X and X Toolkit Libraries. The widgets use the codeset of the current locale to encode text information that users enter and display. To display the data in the correct fonts, the widgets use the following search pattern to locate the fonts:

Items in the preceding list are in precedence order from highest to lowest; the widgets stop the search when an item higher on the list determines a font set.

The internationalization features available through the text widgets have changed on the following two dimensions:


Note

When users select the off-the-spot input style, an application window is enlarged to make room for the input status and preedit area (usually at the bottom of the window). Therefore, the off-the-spot input style requires that auto-resizing be enabled for any application in which that input style is used.

If you are writing an X or Motif application that will be used in Asian countries, do not use toolkit functions to disable auto-resize for your application.


You can use the following functions to create a compound string for codesets that include multiple character sets:


Note

Right-to-left display of language text, which is appropriate for languages such as Hebrew, is supported through the DXmCSText widget. The XmText and XmTextField widgets support only left-to-right displays.



[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.2.3    Internationalization Features of Widget Classes

The following widget classes support native-language input and display capabilities through the XmText and XmTextField widgets (see Section 5.2.2):


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3    Using Internationalization Features in the X Library

Starting with Release 5 of the libX11 library, the X Consortium defined new specifications for developing X clients that handle data for different locales. The new specifications are based on the ANSI C locale model, which configures the Standard C Library to process data in different native languages. These specifications provide interfaces for:

The following sections, which describe how to write an internationalized application with the X Library, cover the following topics:

To illustrate programming techniques, particularly those pertaining to text input, sections that discuss the preceding topics include excerpts from an application named ximdemo. The complete source file and an Imakefile for this application are provided on line in the directory $I18NPATH/usr/examples/ximdemo. You can read the source file, build the application, and run it to understand more fully how to apply the programming techniques being discussed.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.1    Using the X Library to Manage Locales

An internationalized X client uses the same locale announcement mechanism, the setlocale function in the Standard C Library, as other kinds of applications use. In addition, the X Library includes two additional functions to determine the locale and configure locale modifiers: XSupportsLocale() and XSetLocaleModifiers(). Table 5-1 provides brief descriptions of these functions. They are more fully described in the XSupportsLocale(3X11) and XSetLocaleModifiers(3X11) reference pages.


Table 5-1: Locale Announcement Functions in the X Library
FunctionDescription
XSupportsLocale()  Determines if the X Library supports the current locale. 
XSetLocaleModifiers()  Specifies a list of X modifiers for the current locale setting. This list is a null-terminated string where list elements use the format @category =value. The only standard category currently defined as a locale modifier is im, which identifies the input method. However, several im entries can appear on a modifier list when a locale supports more than one input method.

To provide default values on the local host system, the value defined for the XMODIFIERS environment variable is appended to the list of any modifiers supplied by the function call. For example, on Digital UNIX systems, the default value for the input method is DEC. The following command explicitly sets the XMODIFIERS variable to this value:


% setenv XMODIFIERS @im=DEC

In this example, the value @im=DEC is the string that would be appended to the modifier list specified on the call to XSetLocaleModifiers().

 


X Library functions operate according to current locale and locale-modifier settings or according to locale and locale modifier settings attached to objects that are supplied to the functions. There are five types of objects related to locale settings:

The locale and locale modifiers of these objects depend on the locale setting when the objects were created. Therefore, you can create objects for various languages and use them simultaneously to process data from different locales. This capability lets you develop multilingual X window applications. Adhere to the following rules when developing your application:

Example 5-1 shows how an X application sets or determines locale.


Example 5-1: Setting Locale in an X Windows Application
#include <stdio.h>
#include <X11/Xlocale.h>
#include <X11/Xlib.h>

.
.
.
#define DEFAULT_LOCALE "zh_TW.dechanyu" (1)
.
.
.
main(argc, argv) int argc; char *argv[]; {
.
.
.
immodifier[0] = '\0'; for(i=1; i<argc; i++) { if(!strcmp(argv[i], "-Root")) { best_style = XIMPreeditNothing; }
.
.
.
else if (!strcmp(argv[i], "-locale")) (2) locale = argv[++i]; else if (!strcmp(argv[i], "-immodifier")) { strcpy(immodifier, "@im="); strcat(immodifier, argv[++i]); } }
.
.
.
if(locale == NULL) locale = DEFAULT_LOCALE; (3) if(setlocale(LC_CTYPE, locale) == NULL) { fprintf(stderr, "Error : setlocale() !\n"); exit(0); } if (!XSupportsLocale()) { fprintf(stderr, "X does not support this locale"); exit(1); } if (XSetLocaleModifiers(immodifier) == NULL) { (void) fprintf(stderr, "%s: Warning : cannot set locale \ modifiers. \n", argv[0]); }
.
.
.

  1. Defines a constant to contain the setting for the default locale.

    In this example, the constant's value is explicitly set to zh_TW.dechanyu.

  2. Determines if a locale was specified on the application command line.

    The user can override the default locale by using the -locale option on the command line that runs this application.

  3. Sets locale to the value of the DEFAULT_LOCALE constant if the locale was not specified on the application command line.

    If this constant had been set to NULL rather than zh_TW.dechanyu, the default locale would be determined by the setting of the LANG environment variable for the process in which the application is run.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2    Displaying Text for Different Locales

Codesets for some locales, particularly those for Asian languages, require more than one X window font to display all the characters defined. To handle these codesets, the X Library supports the concept of a font set, which allows you to use more than one font to draw and measure text. The font set concept is implemented by the structure XFontSet, which replaces the structure XFontStruct that was supported by X Library releases earlier than Release 5.

A font set is bound to the locale with which it was created. The functions that draw and measure text interpret the text according to the locale of the font set and therefore map characters to their font glyphs correctly.

Digital's implementation of functions that draw and measure text allow you to use fonts with different encodings to display native-language text.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2.1    Creating and Manipulating Font Sets
Table 5-2 summarizes the functions that create and use font sets. For complete information on a function, refer to its reference page.
Table 5-2: X Library Functions That Create and Manipulate Font Sets
FunctionDescription
XCreateFontSet()  Creates a font set for a specified display. This function determines the codesets required for the current locale and loads a set of fonts to support those codesets. 
XFreeFontSet()  Frees a specified font set and any associated components, such as the base font name list, the font name list, the XFontStruct list, and XFontSetExtents
XFontsOfFontSet()  Returns a list of XFontStruct structures and font names for the given font set. 
XBaseFontNameListOfFontSet()  Returns the original base font name list supplied by the client when the font set was created. 
XLocaleOfFontSet  Returns the name of the locale bound to the specified font set. 

Example 5-2 shows the functions that create and use font sets.


Example 5-2: Creating and Using Font Sets in an X Windows Application

.
.
.
#define DEFAULT_FONT_NAME "-*-SCREEN-*-*-R-Normal--*-*, -*" (1)
.
.
.
char *base_font_name = NULL;
.
.
.
XFontSet font_set;
.
.
.
char **missing_list; int missing_count; char *def_string;
.
.
.
if (base_font_name == NULL) base_font_name = DEFAULT_FONT_NAME; (2) font_set = XCreateFontSet(display, base_font_name, &missing_list, &missing_count, &def_string);
.
.
.
/* * if there are charsets for which no fonts can be found, * print a warning message. */ if (missing_count > 0) { fprintf(stderr, "The following charsets are \ missing: \n"); for (i=0; i<missing_count; i++) fprintf(stderr, "%s \n", missing_list[i]); XFreeStringList(missing_list); }
.
.
.

  1. Defines the constant, DEFAULT_FONT_NAME, to contain the value of the the default base font name list.

    In this example, the default base font name list is set to -*-SCREEN-*-*-R-Normal--*-*, -*. For a default base font name list, you should specify a generic name (using wildcard fields as shown in the example) rather than a fully specified list of fonts. A fully specified font list works only for a particular locale, whereas a generic name can be the default for multiple locales.

  2. Determines whether the default base font name list was supplied on the command line.

    The user can override the default base font name list by using the -fs option on the application command line.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2.2    Obtaining Metrics for Font Sets
Table 5-3 summarizes the X Library functions that can query font set metrics and measure text.
Table 5-3: X Library Functions That Measure Text
FunctionDescription
XExtentsOfFontSet()  Returns an XFontSetExtents structure, which contains information about the bounding box of the fonts in the specified font sets. 
XmbTextEscapement(), XwcTextEscapement()  Calculate the escapement (in pixels) required to draw a given string by using the specified font set. 
XmbTextExtents(), XwcTextExtents()  Calculate the overall bounding box of the string's image and a logical bounding box for spacing purposes. These functions also return the value returned by XmbTextEscapement() and XwcTextEscapement(), respectively. 
XmbTextPerCharExtents(), XwcTextPerCharExtents()  Return the text dimensions of each character of the specified text according to the fonts loaded for the specified font set. 


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2.3    Drawing Text with Font Sets
Table 5-4 summarizes functions provided specifically for drawing text in different native languages. Unlike other X Library functions that draw text, the internationalized functions do the following:

These functions free applications from handling text encoding directly.


Table 5-4: X Library Functions That Draw Text
FunctionDescription
XmbDrawText(), XwcDrawText()  Draw text, using multiple font sets, and allow complex spacing and font set shifts between text strings.

Use these functions in place of their single-font counterparts, XDrawText() and XDrawText16().

 

XmbDrawString(), XwcDrawString()  Using one font set, draw only the specified text with the foreground pixel.

Use these functions in place of their single-font counterparts, XDrawString and XDrawString16.

 

XmbDrawImageString(), XwcDrawImageString()  Fill a destination rectangle with the background pixel; then draw the specified image text, using one font set, and paint that text with the foreground pixel.

Use these functions in place of their single-font counterparts, XDrawImageString() and XDrawImageString16().

 


Example 5-3 shows how internationalized functions draw text.


Example 5-3: Drawing Text in an X Windows Application
GC      Jxgc_on, Jxgc_off;
int     Jxcx, Jxcy;
int     Jxcx_offset=2, Jxcy_offset=2;
int     Jxsfont_w, Jxwfont_w, Jxfont_height;
XRectangle      *Jxfont_rect;
int     Jxw_width, Jxw_height;
#define Jxmax_line      10
int     Jxsize[Jxmax_line];
char    Jxbuff[Jxmax_line][128];
int     Jxline_no;
int     Jxline_height;

.
.
.
static int JxWriteText(display, client, font_set, len, string) Display *display; Window client; XFontSet font_set; int len; char *string; { int fy; XFillRectangle(display, client, Jxgc_off, Jxcx, Jxcy, Jxsfont_w, Jxfont_height); (1) if(len == 1 && (string[0] == LF || string[0] == TAB || string[0] == CR)) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, Jxw_width, Jxfont_height); } else { if(Jxcx >= (Jxw_width - Jxwfont_w) || (Jxsize[Jxline_no] + len) >= 256) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, Jxw_width, Jxfont_height); } strncpy(&Jxbuff[Jxline_no][Jxsize[Jxline_no]], string, len); Jxsize[Jxline_no] += len; fy = -Jxfont_rect->y + Jxcy; XmbDrawImageString(display, client, font_set, Jxgc_on, Jxcx, fy, string, len); (2) Jxcx += XmbTextEscapement(font_set, string, len); (3) if(Jxcx >= Jxw_width) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, \ Jxw_width, Jxfont_height); } } XFillRectangle(display, client, Jxgc_on, Jxcx, Jxcy, \ Jxsfont_w, Jxfont_height); }

  1. Displays a block-type cursor by using XFillRectangle().

  2. Displays a native-language string by using XmbDrawImageString().

    The string may contain both single-byte and multibyte characters.

  3. Calculates the position for drawing the next string with XmbTextEscapement().


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2.4    Handling Text With the X Output Method
The concept of a font set that is described in preceding sections was introduced in Version 5 of the X library. Version 6 of the X library implements the more generalized concepts of output methods and output contexts. Output methods and output contexts handle multiple fonts and context dependencies to enable bi-directional text and context-sensitive text display.

To draw locale-dependent text, the application needs to know which fonts are required for that text, how the text can be separated into its components, and which font is required for each of those components. Version 6 of the X library therefore incorporates the following objects to address this problem:

The following table summarizes the X library functions related to XOM and XOC. For more information on these functions, refer to their reference pages.


Table 5-5: X Library Functions for Output Method and Context
FunctionDescription
XOpenOM()  Opens an output method to match the current locale and modifiers specification. The function returns an XOM object to which the current locale and modifiers are bound. 
XCloseOM()  Closes the specified output method. 
XSetOMValues()  Sets an output method's attributes. 
XGetOMValues()  Gets the properties or features of the specified output method. 
XDisplayOfOM()  Returns the display associated with the specified output method. 
XLocaleOfOM()  Returns the locale associated with the specified output method. 
XCreateOC()  Creates an output context within the specified output method. 
XOMOfOC()  Returns the output method associated with the specified output context. 
XSetOCValues()  Sets the values of the XOC object. 
XGetOCValues()  Gets the values of the XOC object. 
XDestroyOC()  Destroys the specified output context. 


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.2.5    Converting Between Different Font Set Encodings
X fonts may be available in different encodings for the following reasons:

Font-encoding divergence from one system to another causes problems for applications that you run on different kinds of systems. Therefore, Digital's implementation of the functions for text drawing and measurement incorporates a mechanism to convert between different font encodings. For conversion to take place, you must design your application so that it can determine the base font name list appropriate for the run-time environment. The application can obtain the base font name list from a resource file or through an option the user specifies on the command line. For example, in the command line to run the ximdemo application, the user can include the -fs option to specify a base font name list.

The conversion mechanism for font encoding is available only when your application uses the internationalized text drawing functions in the X Library. The conversion mechanism is not available with the primitive text drawing functions, such as XDrawText() and XDrawString().


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.3    Handling Interclient Communication

When designing applications for use with different languages and in different countries, you cannot assume that only Latin-1 or ASCII text strings are used for interclient communication. The X Library therefore contains functions that can handle text strings from any language for interclient communication. Table 5-6 summarizes these functions.
Table 5-6: X Library Functions for Interclient Communication
FunctionDescription
XmbSetWMProperties()  Provides a single programming interface for setting essential window properties.

Your application uses these properties to communicate with other clients, particularly window and session managers. For example, the functions have arguments for window and icon names and these names can contain multibyte characters in some locales.

 

XmbTextListToTextProperty(), XwcTextListToTextProperty()  Convert text encoded in the current locale to text properties of type STRING or COMPOUND_TEXT
XmbTextPropertyToTextList(), XwcTextPropertyToTextList()  Convert text properties of type STRING or COMPOUND_TEXT to a list of multibyte-character or wide-character strings. 
XwcFreeStringList()  Frees the memory allocated by XwcTextPropertyToTextList()
XDefaultString()  Queries the default string that is substituted when a character cannot be converted.

When conversion routines encounter a string with a character that cannot be converted, they substitute a locale-dependent default string. The XDefaultString() function queries that default string.

 


Example 5-4 shows interclient communication in an X application.


Example 5-4: Communicating with Other Clients in an X Windows Application

.
.
.
if (!strcmp(locale,"zh_TW.dechanyu")) { strcpy(title, "XIM F|n/"); } else if (!strcmp(locale, "zh_CN.dechanzi")) { strcpy(title, "XIM J>76"); } else if (!strncmp(locale, "ja_JP", 5)) { strcpy(title, "XIM %G%b"); } else if (!strcmp(locale, "ko_KR.deckorean")) { strcpy(title, "XIM 5%8p"); } else if (!strcmp(locale, "th_TH.TACTIS")) { strcpy(title, "XIM !RCJR8T5"); } else { strcpy(title, "XIM Demo") (1) } XmbSetWMProperties(display, window, title, title, NULL, \ 0, NULL, NULL, NULL); (2)
.
.
.

  1. Inserts native-language text in quoted arguments to the strcmp() and strcpy() functions.

    In this example, the text is for a window title. Text strings are explictly specified in the function calls for the sake of simplicity. In practice, X applications extract such text strings from locale-specific resource or User-Interface Language (UIL) files.

  2. Passes the text to the XmbSetWMProperties() function to parse the title, using the locale, and to set the window manager's property accordingly.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.4    Handling Localized Resource Databases

As is also true for font sets, the locale of an X resource file depends on the locale setting when the file was created. Therefore, when a resource file or string is loaded to create a resource database, the file or string is parsed in the current locale. Table 5-7 summarizes the X Library functions that handle localized resource databases.
Table 5-7: X Library Functions That Handle Localized Resource Databases
FunctionDescription
XrmLocaleOfDatabase()  Returns the name of the locale bound to the specified database. 
XrmGetFileDatabase()  Opens the specified file, creates a new resource database, and loads it with the specifications read from the file.

The file is parsed in the current locale.

 

XrmGetStringDatabase()  Creates a new resource database and stores the resources that are specified in a null-terminated string.

The string is parsed in the current locale.

 

XrmPutLineResource()  Adds a single resource entry to the specified database.

The entry string is parsed in the locale of the database.

 

XrmPutFileDatabase()  Stores a copy of the specified database in the specified file.

The file is written in the locale of the database.

 

XResourceManagerString()  Converts the RESOURCE_MANAGER property from encoding of type STRING to the encoding of the current locale.

This function converts encoding in the same way encoding is converted by the XmbTextPropertyToTextList() function.

 



[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5    Handling Text Input with the X Input Method

When developing internationalized X applications, programmers must be able to request data input in different locales from the same keyboard. The X Library incorporates two abstractions, or objects, that address this problem:


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.1    Opening and Closing an Input Method
To use an input method, an application must first call XOpenIM(). This function establishes a connection to the input method for the current locale and locale modifiers. The function returns an XIM object to which the current locale and locale modifiers are bound. The binding of the locale and modifiers to the XIM object occurs when the call executes and cannot be changed dynamically.

When the input method is no longer required, the application closes the XIM object with a call to XCloseIM().

Two other functions are available to obtain information about an XIM object:

In Digital's implementation of input methods, the input method opened by the XOpenIM() function is determined from the following (in order of highest to lowest priority):

If XOpenIM() cannot obtain the input method from the preceding sources, the fallback is to support only ISO Latin-1 input. The XOpenIM() call fails under the following conditions: Example 5-5 shows how to open and close an input method.


Example 5-5: Opening and Closing an Input Method in an X Windows Application
main(argc, argv)
int     argc;
char    *argv[];
        {
        Display                 *display;

.
.
.
XIM im;
.
.
.
char *res_file = NULL;
.
.
.
XrmDatabase rdb = NULL;
.
.
.
preedcb_cd.win = client; if(res_file) { printf("Set Database : file name = %s\n", res_file); rdb = XrmGetFileDatabase(res_file); (1) } if((im = XOpenIM(display, rdb, NULL, NULL)) == NULL) { printf("Error : XOpenIM() !\n"); (2) exit(0); }
.
.
.
XCloseIM(im); (3)
.
.
.

  1. Passes the resource database rdb to XOpenIM() for looking up resources that are private to an input method.

    You can specify resource databases created in the application by the internationalized Xt functions.

  2. Checks if the input method has been opened successfully.

  3. Closes the input method.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.2    Querying Input Method Values
Behavior of input methods in some areas is vendor defined. For example, different implementations of an input method may support different combinations of user interaction styles. To help you develop portable applications, the X Library includes the XGetIMValues() function to determine the attributes of an input method. Currently, only the XNQueryInputStyle attribute is defined, and this attribute specifies the user interaction styles supported by an input method.

Example 5-6 shows how to use the XGetIMValues() function with the XNQueryInputStyle attribute to obtain information for an input method.


Example 5-6: Obtaining the User Interaction Styles for an Input Method
main(argc, argv)
int     argc;
char    *argv[];
        {
        Display                 *display;

.
.
.
int i, n;
.
.
.
XIMStyles *im_styles; XIMStyle xim_mode=0; XIMStyle best_style = XIMPreeditCallbacks; XIM im;
.
.
.
XIMStyle app_supported_styles;
.
.
.
for(i=1; i<argc; i++) { if(!strcmp(argv[i], "-Root")) { best_style = XIMPreeditNothing; } else if (!strcmp(argv[i], "-Cb")) { best_style = XIMPreeditCallbacks; (1) }
.
.
.
/* set flags for the styles our application can support */ app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditCallbacks; (2) app_supported_styles |= XIMStatusNone | XIMStatusNothing; XGetIMValues(im, XNQueryInputStyle, &im_styles, NULL); n = 1; (3) if(im_styles != (XIMStyles *)NULL) { for(i=0; i<im_styles->count_styles; i++) { xim_mode = im_styles->supported_styles[i]; if((xim_mode & app_supported_styles) == xim_mode) { /* if we can handle it */ n = 0; if (xim_mode & best_style) /* pick user selected style */ break; (4) } } } if(n) { printf("warning : Unsupport InputStyle. or No IMserver.\n"); exit (0); }
.
.
.

  1. Determines if the user specified a preferred interaction style on the application command line.

    In the ximdemo application, users can use the -Root and -Cb options to specify the interaction styles. These options represent the only two styles supported by this particular application. The -Root option specifies the style to be Root Window; this style requires minimal interaction between the client and the input server. The -Cb option specifies a style where preediting is handled by callbacks. This style enables on-the-spot preediting.

  2. Defines the app_supported_styles bitmask to specify the two interaction styles that the application can support.

  3. Calls XGetIMValues() to query interaction styles.

    The call returns the interaction styles to the im_styles parameter.

  4. Selects the interaction style that the input method supports and the application can handle properly.

    The interaction style specified by the user takes precedence; otherwise, the application selects the last interaction style in the returned style list.

Supported interaction styles for an input method can vary from one locale to another. Refer to the user guides provided with Digital UNIX language variant subsets to find out what interaction styles are supported for a particular input method.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.3    Creating and Using Contexts for an Input Method
Just as the X Server can maintain multiple windows for a display, an application can create multiple contexts for an input method. The X Library contains the function XCreateIC() to create an object for input context (XIC). The XIC object maintains a number of attributes that you can set and obtain through other functions. Among these attributes are:

To destroy an XIC object, call the XDestroyIC() function.

Example 5-7 shows how to use the XCreateIC() and XDestroyIC() functions.


Example 5-7: Creating and Destroying an Input Method Context in an X Windows Application

.
.
.
Display *display;
.
.
.
Window root, window, client;
.
.
.
XIMStyle xim_mode=0;
.
.
.
XIM im; XIC ic;
.
.
.
XVaNestedList preedit_attr, status_attr; XIMCallback ximapicb[10]; char immodifier[100]; preedcb_data preedcb_cd;
.
.
.
window = XCreateSimpleWindow(display, root, 0, 0, W_WIDTH, W_HEIGHT, 2, bpixel, fpixel);
.
.
.
client = JxCreateTextWindow(display, window, 0, 0, W_WIDTH-2, W_HEIGHT-2, 1, bpixel, fpixel, font_set, &font_height);
.
.
.
if (xim_mode & XIMPreeditCallbacks) { ximapicb[0].client_data = (XPointer)NULL; ximapicb[0].callback = (XIMProc)api_preedit_start_cb; ximapicb[1].client_data = (XPointer)(&preedcb_cd); ximapicb[1].callback = (XIMProc)api_preedit_done_cb; ximapicb[2].client_data = (XPointer)(&preedcb_cd); ximapicb[2].callback = (XIMProc)api_preedit_draw_cb; ximapicb[3].client_data = (XPointer)NULL; ximapicb[3].callback = (XIMProc)api_preedit_caret_cb; nestlist = XVaCreateNestedList(10, XNPreeditStartCallback, &ximapicb[0], XNPreeditDoneCallback, &ximapicb[1], XNPreeditDrawCallback, &ximapicb[2], XNPreeditCaretCallback, &ximapicb[3], NULL); (1) } if (xim_mode & XIMPreeditCallbacks) { (2) ic = XCreateIC(im, XNInputStyle, xim_mode, XNClientWindow, window, XNFocusWindow, client, XNPreeditAttributes, nestlist, NULL); (3) } else { /* preedit nothing */ ic = XCreateIC(im, XNInputStyle, xim_mode, XNClientWindow, window, XNFocusWindow, client, NULL ); (4) } if(ic == NULL) { (5) printf("Error : XCreateIC() !\n"); XCloseIM(im); exit(0); }
.
.
.
exit: XDestroyIC(ic); (6)

  1. Calls the function XVaCreateNestedList() to create a nested argument list for preediting and status attributes.

    The attributes XNPreeditAttributes and XNStatusAttributes contain a list of subordinate attributes. Your application must create a nested list to contain the subordinate attributes before setting or querying them.

  2. Specifies XIC attributes.

    Your application must always specify some XIC attributes when creating an XIC object. The XNInputStyle attribute is mandatory; requirements for other attributes depend on the interaction style.

  3. Registers callbacks for on-the-spot interaction style.

    When the interaction style is on the spot, your application must register all callbacks when creating the XIC object.

    Your application does not have to set the XNClientWindow attribute when creating the XIC, but must set this attribute before using the XIC. If the XIC is used before XNClientWindow is set, results are unpredictable.

  4. Sets the interaction style, client window, and focus window attributes for the root-window style.

    These are the only attributes your application needs to set at XIC creation time when the interaction style is root window.

  5. Specifies actions when XIC creation fails.

    The call to XCreateIC() fails (returns NULL) under the following conditions:

  6. Closes the XIC.

Table 5-8 lists and summarizes the functions available for managing an XIC object.


Table 5-8: X Library Functions That Manage Input Context (XIC)
FunctionDescription
XSetICFocus()  Enables keyboard events to be directed to the input method.

You must call this function when the focus window of an XIC receives input focus; otherwise, keyboard events are not directed to the input method.

 

XUnsetICFocus()  Prevents keyboard events from being directed to the input method.

Call this function when the focus window of an XIC loses focus.

 

XmbResetIC(), XwcResetIC()  Reset the XIC to its initial state.

Any input pending on that XIC is deleted. These functions return either the current preedit string or NULL, depending on the implementation of the input server.

 

XIMOfIC()  Returns the XIM associated with the specified XIC. 
XSetICValues()  Sets attributes to a specified XIC. 
XGetICValues()  Queries attributes from a specified XIC. 


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.4    Providing Preediting Callbacks for the On-the-Spot Input Style
If your application supports the on-the-spot interaction style, you have to provide a set of preediting callbacks. There are a number of callbacks associated with XIC. Example 5-8 shows these callbacks.


Example 5-8: Using Preediting Callbacks in an X Windows Application

.
.
.
int Jxsize[Jxmax_line]; char Jxbuff[Jxmax_line][128]; int Jxline_no; int Jxline_height; int sav_cx, sav_cy; int sav_w_width, w_height; int sav_size[Jxmax_line]; int sav_line_no; char preedit_buffer[12]; void save_value() { int i; sav_cx = Jxcx; sav_cy = Jxcy; sav_line_no = Jxline_no; for (i=0; i< Jxmax_line; i++) sav_size[i] = Jxsize[i]; } void restore_value() { int i; Jxcx = sav_cx; Jxcy = sav_cy; Jxline_no = sav_line_no; for (i=0; i< Jxmax_line; i++) Jxsize[i] = sav_size[i]; } int api_preedit_start_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XPointer calldata; { int len; len = 12; /* save up the values */ save_value(); (1) return(len); (2) } void api_preedit_done_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XPointer calldata; { preedcb_data *cd = (preedcb_data *)clientdata; /* restore up the values */ restore_value(); (3) /* convenient handling */ JxRedisplayText(cd->dpy, cd->win, cd->fset); return; } void api_preedit_draw_cb( ic, clientdata, calldata) XIC ic; XPointer clientdata; XIMPreeditDrawCallbackStruct *calldata; { preedcb_data *cd = (preedcb_data *)clientdata; int count; char *reset_str; if (calldata->text) { if (calldata->text->encoding_is_wchar) (4) { } else { count = strlen(calldata->text->string.multi_byte); if (count > 12) { /* preedit string > max preedit buffer */ reset_str = XmbResetIC(ic); (5) XFillRectangle(cd->dpy, cd->win, Jxgc_off, Jxcx, Jxcy, Jxw_width*13, Jxfont_height); /* clear the preedit area */ restore_value(); if (reset_str) XFree(reset_str); return; } if (!calldata->chg_length) { /* insert character */ if (!calldata->chg_first) { /* insert in first character in preedit buffer */ strncpy(&preedit_buffer[0],calldata->text->string.multi_byte, count); restore_value(); } else { /* Not Yet Implemented */ } } else { /* replace character */ if (!calldata->chg_first) { /* replace from first character in pre-edit buffer */ strncpy(&preedit_buffer[0],calldata->text->string.multi_byte, count); restore_value(); } else { /* Not Yet Implemented */ } } XFillRectangle(cd->dpy, cd->win, Jxgc_off, Jxcx, Jxcy, Jxw_width*13, Jxfont_height); /* clear the preedit area */ JxWriteText(cd->dpy, cd->win, cd->fset, count, preedit_buffer); } } else { /* should delete preedit buffer */ /* Not yet implemented */ } return; } void api_preedit_caret_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XIMPreeditCaretCallbackStruct *calldata; { /* Not yet implemented */ return; }
.
.
.

  1. Saves the current drawing position.

    As part of the operation of drawing preediting strings, this application saves the current drawing position as the value of the PreeditStartCallback attribute. Once the preediting is complete, the application erases the preediting string and restores the original drawing position.

  2. Returns the length of the preediting string.

    The value of 12 bytes is an arbitrary number to limit the length of the string. The value should match the size of the preediting buffer. This application declares the preediting buffer (preedit_buffer) to be a 12-byte character array.

  3. Restores the drawing position and redraws the text buffer.

  4. Handles wide-character encoding.

    This example assumes that the preediting string is in multibyte encoding. However, your application should handle both multibyte and wide-character encoding. Wide-character encoding is preferable because information, such as character position, is returned in the XIMPreeditDrawCallbackStruct structure as the number of characters rather than the number of bytes.

    In Digital's implementation of X windows, you can specify the encoding of preediting and status strings in a resource database that is passed to the XOpenIM() function. The resources associated with these strings are:

    Specify wchar as the encoding to indicate that wide-character encoding is used.

  5. Clears the preediting string when its size exceeds 12 bytes.

    The size of the string is obtained from the PreeditDrawCallback attribute. Without processing the string returned on the call to XmbResetIC(), the application simply frees the string with a call to Xfree().


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.5    Filtering Events for an Input Method
An input method has to receive events before the events are processed by the application. The application has to pass to the input method not only KeyPress/KeyRelease events but other events as well. The X Library contains the XfilterEvent() function to pass events to an input method. Use this function, along with related functions, as follows:

  1. Obtain a mask for the events to be passed to the input method by calling the XGetICValues() function with the XNFilterEvents argument.

  2. Register the event types with the XSelectInput() function.

  3. In the main loop of the program, usually right after the call to XNextEvent(), call XFilterEvent() to pass the event to the input method.

    A return status of True indicates that the input method has filtered the event and it needs no further processing by the application.

Example 5-9 shows the preceding process.


Example 5-9: Filtering Events for an Input Method in an X Windows Application

.
.
.
long im_event_mask;
.
.
.
XGetICValues(ic, XNFilterEvents, &im_event_mask, NULL); mask = StructureNotifyMask | FocusChangeMask | ExposureMask; XSelectInput(display, window, mask); mask = ExposureMask | KeyPressMask | FocusChangeMask | im_event_mask; XSelectInput(display, client, mask);
.
.
.
for(;;) { XNextEvent(display, &event); if(XFilterEvent(&event, NULL) == True) continue; (1) switch(event.type ) { /* dispatch event */
.
.
.
} }
.
.
.

  1. Filters the event.

    Note that the function XtDispatchEvent() calls XFilterEvent(). Therefore, you could replace the for loop as shown in this example with a call to XtAppMainLoop().


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.6    Obtaining Composed Strings from the Keyboard
You use the XmbLookupString() or XwcLookupString() function in your X application to obtain native-language characters and key symbols. Your application has to take into account the complexity of some input methods, which require several keystrokes to compose a single character. Therefore, expect that a composed character or string may not be returned on every call to one of these functions.

Example 5-10 shows how to get keyboard input in an X application.


Example 5-10: Obtaining Keyboard Input in an X Windows Application

.
.
.
XEvent event;
.
.
.
int len = 128; char string[128]; KeySym keysym; int count;
.
.
.
for(;;) { XNextEvent(display, &event); if(XFilterEvent(&event, NULL) == True) continue; switch(event.type ) { case FocusIn :
(1) if(event.xany.window == window) XSetInputFocus(display, client, RevertToParent, CurrentTime); else if(event.xany.window == client) { XSetICFocus(ic); } break; case FocusOut : (1) if(event.xany.window == client) { XUnsetICFocus(ic); } break; case Expose : if(event.xany.window == client) JxRedisplayText(display, client, font_set); break; case KeyPress : (2) count = XmbLookupString(ic, (XKeyPressedEvent *)&event, string, len, &keysym, NULL); if( count == 1 && string[0] == (0x1F&'c')) { /* exit */ goto exit; } if( count > 0 ) { (3) JxWriteText(display, client, font_set, count, string); } break; case MappingNotify : XRefreshKeyboardMapping( (XMappingEvent *)&event); break; case DestroyNotify : printf("Error : DestroyEvent !\n"); break; } }

  1. Handles FocusIn and FocusOut events.

    In this example, one XIC is associated with a focus window. On Digital systems, some input servers require focus change information to update the status area. Therefore, each FocusIn event calls XSetICFocus() and each FocusOut event calls XUnsetICFocus().

    Your application can also use one XIC for several focus windows. In this case, you do not need to call XSetICFocus() for every focus change event, but you do have to set the XNFocusWindow attribute of the XIC.

  2. Handles KeyPress events.

    Make sure that your application passes only KeyPress events to XmbLookupString() or XwcLookupString(). Results are undefined if you pass KeyRelease events to these functions.

    For simplicity in this example, the status field in the call to XmbLookupString() is NULL. Your own application should check for the status return and respond appropriately. For example, if the status return is XBufferOverflow, your application might try to allocate more memory for the buffer.

  3. Processes the string when one is returned.

    XmbLookupString() returns the size of the composed string (in bytes).


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.5.7    Handling Failure of the Input Method Server
The XNDestroyCallback resources for an input method and an input method context were introduced in X11R6. These resources, which are triggered by failure of the input method server, close the XIM and XIC objects for a client application. If a client application continues to run without detecting server failure and then closing the XIC and XIM objects, results are unpredictable.

Example 5-11 shows how to register the XNDestroyCallback resource for the XIM object and how to close the XIM in the event of server failure.


Example 5-11: Handling Failure of the Input Method Server
static void     _imDestroyCallback();  (1)

.
.
.
Bool IMS_Connected = False; XIMCallback cb; (2)
.
.
.
if((im = XOpenIM(display, rdb, NULL, NULL)) == NULL) { printf("Error : XOpenIM() !\n"); exit(0); } else { IMS_Connected = True; cb.client_data = (XPointer) &IMS_Connected; cb.callback = (XIMProc) _imDestroyCallback; XSetIMValues(im, XNDestroyCallback, &cb, NULL); (3) }
.
.
.
case KeyPress : if (IMS_Connected) count = XmbLookupString(ic, (XKeyPressedEvent *)&event, string, len, &keysym, NULL); else count = XLookupString((XKeyPressedEvent *)&event, string, len, &keysym, NULL); (4)
.
.
.
static void _imDestroyCallback(im, client_data, call_data) XIM im; XPointer client_data; XPointer call_data; { Bool *Connected = (Bool *)client_data; *Connected =3D False; (5) }

  1. Declare the function that closes the XIM if the input method server (IMS) fails for any reason.

  2. Declare the IMS_Connected variable to specify whether the input method server is still connected and the cb structure to contain client information needed for resource registration.

  3. If the call to open the XIM fails, print an error message and exit. Otherwise, set the IMS_Connected variable to True, fill the cb structure with appropriate client data, and call the XSetIMValues() function to register the XNDestroyCallback resource for the XIM.

  4. If the input method server is running, use the XmbLookupString() function to process user input; otherwise, use the XLookupString() function.

  5. Specify the prototype for the function that closes the XIM in the event that the input method server fails.

Note that the ximdemo program is very simple and uses only one input method context. In this case, there is no need to explicitly close the XIC when the input method server fails. The following example shows the prototype for a callback function that would close an XIC:
static void icDestroyCallback(ic, client_data, call_data)
XIC ic;
XPointer client_data;
XPointer call_data;


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

5.3.6    Using X Library Features: A Summary

The following list of steps for processing native-language input summarizes the information presented in preceding sections on the X Library. For your convenience, the step description also notes when programming with X Toolkit Intrinsics (Xt) functions differs from programming with X Library functions. Refer to Section 5.1 for discussion of internationalization features of the X Toolkit Intrinsics.

  1. Call setlocale() to bind to the current locale.

    You can accomplish the same result by registering an initialization callback function with XtSetLanguageProc().

  2. Call XSupportsLocale() to verify that X supports the current locale.

  3. Either call XSetLocaleModifier() or set the XMODIFIERS environment variable to define the input method being used.

  4. Call XOpenIM() to connect to the selected input method.

    If you are writing a widget, you can skip this step and assume that a valid XIM will be passed to the widget as a resource.

  5. Call XGetIMValues() to query the interaction styles supported by the input method.

    When writing a widget, do this step in the initialization method.

  6. Create a window to associate with an XIC.

    When using Xt functions, create a widget.

  7. Call XCreateFontSet() to create a font set for this window.

    If you are using Xt functions and have created a widget, use the value set for XtDefaultFontSet.

  8. Choose an interaction style from the supported values obtained by the application and pass this value as an argument to XCreateIC().

    If you are using XIMPreeditCallbacks, you must write the callback routines and register them on the call to XCreateIC().

  9. Call XGetICValues() to query the XNFilterEvents attribute and register the event that the input method needs from the focus window.

  10. Call XFilterEvent() in the main event loop before dispatching an event.

    If the call returns True, you can discard the event.

    If programming with routines from the X Intrinsics (Xt) Library, use XtDispatchEvent().

  11. In the main event loop, set and unset input focus when the focus window receives FocusIn and FocusOut events.

    If programming with routines from the X Intrinsics (Xt) Library, use an event handler or a translation/action table to track focus events.

  12. For unfiltered KeyPress events, call XmbLookupString() or XwcLookupString() to obtain key symbols and the composed string.

    You can draw the string with the internationalized functions for text drawing.