            IM Server Developers Kit - C Language Interface

                            Hidetoshi Tajima

                    X11R6 Xi18n Implementation Group

                              May 15, 1994

1.   Functions List

1.1.   Open IM Servive

XIMS IMOpenIM(Display display,...)

display                specifies the connection to the X server.
...                specifies the variable length argument list to set
                IMValues. For further information, see the Section 2
                "IMValues".

   IMOpenIM initializes the connection for the Input Method Service, and
also sets one or more IMValues which are specified by a variable length
argument list programming interface, and when succeeding to open the
connection, IMOpenIM allocates a new XIMS structure and returns it,
otherwise IMOpenIM returns NULL. XIMS is an opaque data structure to
abstract the Input Method Service.

   First, IMOpenIM initializes a preconnection method by which clients
can search for the IMserver. The convention of the preconnection varies
with the IMProtocol model as below, however, you don't have to pay much
attention to such difference, because IMOpenIM encapsulates it.

    Preconnection for R5 Ximp
        IMserver must create the selection owner window of the ATOM for
        the string, such as "_XIMP_%locale" or something, which are used
        by clients to search for the IMserver.
    Preconnection for R6 IMProtocol
        IMserver must create the selection owner window of the ATOM for
        the string, such as "@server=%im_name", and registers the ATOM
        with the list of "XIM_SERVERS" property of the default root
        window, which contains a list of ATOMs, each of which represents
        each available IMservers on the display.

   Second, IMOpenIM initialize a transport connection on which clients
and the IMserver can send and receive IMProtocols with each other. The
procedures to initialize the transport connection varies with the
transport mechanism as below, however, you don't have to pay any
attention to such difference, either, because IMOpenIM also encapsulates
it.

    Transport connection for X
        IMserver must intern a number of ATOMs for the properties which
        are used to set some IMserver specific feature and
        characteristic.
    Transport connection for TCP/IP
        IMserver must open a listening socket to wait for connection
        request from clients.

1.2.   Set IM Attributes

char *IMSetIMValues(XIMS ims,...)

ims                specifies the input method service.
...                specifies the variable length argument list to set
                IMValues.

   IMSetIMValues registers one or more IMValues, which are specified by
a variable length argument list programming interface, with the XIMS
structure. Note that IMOpenIM is also used to set all IMValues, and some
IMValues must be set when IMOpenIM is called.
   IMSetIMValues returns NULL if it succeeds to set all the IMValues,
otherwise, it returns the name of the first argument whose value could
not be registered.

1.3.   Get IM Attributes

char *IMGetIMValues(XIMS ims,...)

ims                specifies the input method service.
...                specifies the variable length argument list to get
                IMValues.

   IMGetIMValues gets one or more IMValues, which are specified by a
variable length argument list programming interface, from the XIMS
structure.
   IMGetIMValues returns NULL if it succeeds to get all the IMValues,
otherwise, it returns the name of the first argument whose value could
not be obtained.

1.4.   Close IM Service

void IMCloseIM(XIMS ims)

ims                specifies the input method service to be closed.

   IMCloseIM closes the connection which was opened by IMOpenIM.
IMCloseIM frees all the allocated data in the XIMS structure, then frees
the XIMS itself.

1.5.   Start Preediting

int IMPreeditStart(XIMS ims, XPointer im_protocol)

ims                specifies the input method service.
im_protocol        specifies the Input Protocol data.

   IMPreeditStart is used to start preeditting in case of Dynamic Event
Flow.

The structure for im_protocol varies with the IMProtocol models:

/* R5 Ximp */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
} XIMPPreeditStateStruct;

/* R6 IMProtocol */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;
} IMPreeditStateStruct;

1.6.   Stop Preediting

int IMPreeditEnd(XIMS ims, XPointer im_protocol)

ims                specifies the input method service.
im_protocol        specifies the Input Protocol data.

   IMPreeditEnd is used to stop preeditting in case of Dynamic Event
Flow. However, if you registered off-keys list using IMOffKeysList
IMValue, you might not need to use IMPreeditEnd, because IMdkit calls
IMPreeditEnd internally when it receives a key event matching one of
the registered off-keys. So, you are greatly encouraged to use
IMPreeditEnd only when you did *NOT* register any off-keys list.

1.7.   Forward back KeyEvent

void IMForwardEvent(XIMS ims, XPointer im_protocol)

ims                specifies the input method service.
im_protocol        specifies the Input Protocol data.

   IMForwardEvent is used to send back a non-filtered
KeyPress/KeyRelease Event.
   The structure for im_protocol varies with the IMProtocol models:

/* R5 Ximp */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
    CARD32        keycode;
    CARD32        state;
    CARD32        time;
} XIMPKeyEventStruct;

/* R6 IMProtocol */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;                /* input context ID */
    BITMASK16        sync_bit;        /* precessed synchronously or not */
    CARD16        serial_number;
    XEvent        event;                /* X event to be filtered */
} IMForwardEventStruct;

1.8.   Commit Conversion String

void IMCommitString(XIMS ims, XPointer im_protocol)

ims                specifies the input method service.
im_protocol        specifies the Input Protocol data.

   IMCommitString is used to send a committed string, which may contain
a localized text converted by the IMserver.
   The structure for im_protocol varies with the IMProtocol models:

/* R5 Ximp */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
    char        *ctext;
} XIMPCommitStringStruct;

/* R6 IMProtocol */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;                /* input context ID */
    CARD16        flag;
        /* bit combination to tell the receiver what to do */
                #0001        : process it synchroously, return XIM_SYNC_REPLY
                #0002        : Lookup Chars
                #0004        : Lookup KeySym
                #0006        : Lookup Both = Lookup Chars and KeySym
         */
    KeySym        keysym;                /* returned keysym */
    char        *commit_string;        /* string to commit to XIM client */
} IMCommitStruct;

1.9.   Call Callback

int IMCallCallback(XIMS ims, XPointer im_protocol)

ims                specifies the input method service.
im_protocol        specifies the Input Protocol data.

   IMCallCallback is used for your IMserver to send a callback request
asynchronously with the previous IMProtocol request. The type of the
callback request must be set in the proper members of the im_protocol
data structure by your IMserver. In addition, it's up to you to declare
a new IMProtocol structure before you begin the callback requests.
   The structures for im_protocol varies with the IMProtocol models:

/* R6 IMProtocol */
   The type of the callback request must be set in major_code and
minor_code members in the IMProtocol structure, e.g., you can start
geometry management callback as follows;

        IMGeometryCBStruct geometry;
        ...
        geometry.major_code = XIM_GEOMETRY;
        geometry.connect_id = previous_request->any.connect_id;
        ...
        IMCallCallback(ims, (IMProtocol)&geometry);

   The structures for R6 IMProtocol callbacks contain:

/* for Geometry Callback */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;
} IMGeometryCBStruct;

/* for Preedit Callback */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;
    union {
        int        return_value;                        /* PreeditStart */
        XIMPreeditDrawCallbackStruct draw;        /* PreeditDraw */
        XIMPreeditCaretCallbackStruct caret;         /* PreeditCaret */
    } todo;
} IMPreeditCBStruct;

/* for Status Callback */
typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
    CARD16        icid;
    union {
        XIMStatusDrawCallbackStruct draw;
    } todo;
} IMStatusCBStruct;

   The structures for R5 Ximp callbacks contain:

/* for Geometry Callback */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
} XIMPAnyStruct;

/* for Preedit Callback */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
    union {
        int        return_value;                        /* PreeditStart */
        XIMPreeditDrawCallbackStruct draw;        /* PreeditDraw */
        XIMPreeditCaretCallbackStruct caret;         /* PreeditCaret */
    } todo;
} XIMPPreeditCBStruct;

/* for Status Callback */
typedef struct {
    INT32        type;
    CARD32        icid;
    Window        focus_win;
    long        fwin_sel_mask;
    CARD32        ximp_type_mask;
    Window        client_win;
    union {
        XIMStatusDrawCallbackStruct draw;        /* StatusDraw */
    } todo;
} XIMPStatusCBStruct;

2.   IMValues

2.1.   IMModifiers

   The IMModifiers argument, of type string, specifies the name of the
IMProtocol model. At the current release, only three names are accepted
by IMdkit.
        "Xi18n"                specifies the R6 standard IMProtocol model
        "XIMP"                specifies the R5 Ximp model.

   The IMModifiers argument must be set only once when IMOpenIM is
called, and never be changed on the fly.

2.2.   IMServerWindow

   The IMServerWindow argument, of type Window, specifies the window
which identifies a method of preconnection with XIM clients. In addition
to this primary purpose, the IMServerWindow might be used for any other
purposes, which depends on the IMProtocol model to be used.
   If this argument is unspecified, a default window might be provided
by IMdkit, which depends on the IMProtocol model to be used, and if it
is specified, it must be done only once by either IMOpenIM or
IMSetIMValues, and never be changed on the fly.

2.3.   IMServerName

   The IMServerName argument, of type string, specifies the name of the
IMserver. This argument might be a part of the IMserver identifiers
by which XIM clients will search for the IMserver.
   The IMServerName argument must be set only once when IMOpenIM is
called, and never be changed on the fly.

2.4.   IMLocale

   The IMLocale argument, of type string, specifies a list of locales
the IMserver supports. This argument might be a part of the IMserver
identifiers which is used for XIM clients to search for the IMserver.
   The IMLocale argument must be set only once when IMOpenIM is called,
and never be changed on the fly.

2.5.   IMServerTransport

   The IMServerTransport argument, of type string, specifies the name
for the transport connection mechanism the IMserver uses. This argument
might be a part of the IMserver identifiers which is used for XIM
clients to search for the IMserver.
   The preregistered formats for this argument are as follows.(*1)

(*1) Reter to "The Input Method Protocol", Appendix B:
  The list of transport specific IM Server address format registered

TCP/IP Names
------------
   Syntax for Internet domain names:

        <TCP name> ::= "tcp/"<hostname>":"<ipportnumber>

           where <hostname> is either symbolic or numeric decimal form of
        the host machine name, and <ipportnumber> is the port on which
        the IMserver is listening for connections.

   Syntax for system internal domain names:

        <local name> ::= "locale/"<hostname>":"<pathname>

        where <pathname> is a path name of socket address.

DECnet Names
------------
   Syntax for DECnet names:

        <DECnet name> ::= "decnet/"<nodename>"::IMSERVER$"<objname>

        where <nodename> is either symbolic or numeric decimal form of
        the DECnet address, and <objname> is normal, case-insensitive
        DECnet object name.

X Names
-------
   Syntax for X names:

        <X name> ::= "X/"

   The IMServerTransport argument must be set only once when IMOpenIM is
called, and never be changed on the fly.

2.6.   IMInputStyles

   The IMInputStyles argument, of type XIMStyles, specifies a list of
the input styles the IMserver supports.
   If this argument is unspecified, a default list might be provided by
IMdkit, which depends on the IMProtocol model to be used, and it can be
set by either IMOpenIM or IMSetIMValues, but should not be changed on
the fly.

2.7.   IMProtocolHandler

   The IMProtocolHandler argument, of type IMProtoHandler, specifies the
callback function which is called each time when IMMainLoop receives an
IMProtocol input from XIM clients. The generic prototype of the
IMProtocolHandler function is;

typedef int (*IMProtoHandler)();

int ProtocolHandlerProc(ims, call_data)
XIMS ims;
XPointer call_data;

call_data        points to a IMProtocol structure.

2.8.   IMOnKeysList

   The IMOnKeysList argument, of type XIMTriggerKeys, specifies the list
of preediting start-keys for Dynamic Event Flow model. The IMOnKeysList
IMValue is mandatary for IMserver to support Dynamic Event Flow Model,
so that the IMlibrary can send the IMserver a request to start
preediting with the appearance of one of these registered on-keys.
   If the IMOnKeysList is left unspecified, no default will be provided,
and Static Event Flow model will be used.
   XIMTriggerKeys structure is defined by IMdkit as follows:

typedef struct {
    CARD32        keysym;
    CARD32        modifier;
    CARD32        modifier_mask;
} XIMTriggerKey;

typedef struct {
    unsigned short count_keys;
    XIMTriggerKey *keylist;
} XIMTriggerKeys;

2.9.   IMOffKeysList

   The IMOnKeysList argument, of type XIMTriggerKeys, specifies the list
of preediing end-keys for Dynamic Event Flow model. The IMOffKeysList
IMValue is optional for IMserver to support Dynamic Event Flow Model.
   When it is specified, the IMlibrary can send the IMserver a request
to stop preediting with the appearance of one of these registered
off-keys, while it's unspecified, the IMserver calls IMPreeditEnd to
notify the IMlibrary to stop preeditting when the IMserver would like to
stop preeditring.
   If the IMOffKeysList is left unspecified, no default will be
provided.

2.10.   IMEncodingList

   The IMEncodingList argument, of type XIMEncodings, specifies the list
of encodings the IMserver supports. XIM client will be notified of this
argument immediately after it makes a connection with the IMserver.
   The IMEncdoingList argument is used to specify which encodings can be
used to exchange localized-text between the IMserver and XIM clients.
   If it's left unspecified, only "COMPOUND_TEXT" encoding will be used
as a fallback default.
   XIMEncodings structure is defined by IMdkit as follows:

typedef char *XIMEncoding;

typedef struct {
    unsigned short count_encodings;
    XIMEncoding *supported_encodings;
} XIMEncodings;

2.11.   IMFilterEventMask

   The IMFilterEventMask argument, of type long, specifies the events
which should be filtered by the IMserver during the preeditting is on
going.
   If it's left unspecified, KeyPressMask (1L<<0) will be fallback
default.

2.12.   IMProtocolDepend

   The IMProtocolDepend argument is used to specify special IM values
for each IMProtocol model, if any. This attribute is passed to
IMOpenIM, IMSetIMValues or IMGetIMValues as a nested variable length
list generated with XVaCreateNestedList(). At this release, the
names in the IMProtocolDepend list are defined only for R5 Ximp model,
as below.

2.12.1.   R5 Ximp dependent IM Values

XIMPVersion

   The XIMPVersion argument, of type string, specifies the version of R5
Ximp model.
        value                meaning
        ---------------------------------------------
        "3.5"                supports Ximp version 3.5 model
        "4.0"                supports Ximp version 4.0 model

XIMPType

   The XIMPVersion argument, pointer to a list of type unsigned long,
specifies a list of bitmask combinations, each of which indicates the
event flow model your IMserver supports. All possible values to be
appeared in the list are defined as follows.(*)

(*) Refer to "Protocol Specification for the Distributes Input System on
the X Window System, Version 11", which contains in X11R5 contribuion.

  XIMP_BE_TYPE1
        back-end type, which IMlibrary recognizes registered keys and
        notifies a server to start processing key events.
  XIMP_FE_TYPE1
        front-end type, which IMlibrary recognizes registered keys and
        notifies a server to start processing key events.
  XIMP_BE_TYPE2
        back-end type, which IMlibrary does not recognize any registered
        keys and. IMserver will always the first to process key events.
  XIMP_FE_TYPE2
        front-end type, which IMlibrary does not recognize any
        registered keys and. IMserver will always the first to process
        key events.
  XIMP_FE_TYPE3
        front-end type, which key events are always passed to both
        IMserver and IMlibrary. Both of them recognize registered keys.
  XIMP_SYNC_BE_TYPE1
        XIMP_BE_TYPE1 & KeyPress is transferred synchronously.
  XIMP_SYNC_BE_TYPE2
        XIMP_BE_TYPE2 & KeyPress is transferred synchronously.

XIMPExtension

   The XIMPExtension argument is used to set/unset the pre-registered
extensions to be valid. This list is also a nested variable length list
generated with XVaCreateNestedList(). At this release, the
pre-registered extensins appeared in the XIMPExtension list are defined
as below.

  XIMPExtStatusWin
        If it is appeared in the list, the XNExtXimp_StatusWindow input
        context        attribute is valid to set the status window. The
        attribute value        isn't evaluated.
  XIMPExtBackFront
        If it is appeared in the list, the XNExtXimp_Backfront input
        context is valid to select the front-end method or back-end
        method. The attribute value isn't evaluated.
  XIMPExtConversion
        If it is appeared in the list, the XNExtXimp_Conversion input
        context is valid to set the input mode. The attribute value
        isn't evaluated.

3.   X IMProtocol Strucutures

   For each X IMProtocol input, a corresponding structure is defined in
public header files of IMdkit. <X11/Ximd/Xi18n.h> defines all IMProtocol
structures for R6 standard IMProtocol model, and <X11/Ximd/Ximp.h>
defines all for R5 Ximp model.

3.1.   R6 IMProtocol

3.1.1. IMProtocol union data structure
   In R6 standard IMProtocol model, all the event structures have the
following common members:

typedef struct {
    int major_code;        /* major code of last IMProtocol */
    int minor_code;        /* minor code of last IMProtocol */
    CARD16 connect_id;        /* client connection ID */
} IMAnyStruct;

   The major_code and minor_code specify the IMProtocol type constant
name that uniquely identifies itself.
   In addition to the individual structures declared for each IMProtocol
type, the IMProtocol structure is a union of the individual structures
declared for each IMProtocol type. Depending on the type, you should
access members of each IMProtocol by using the IMProtocol union.

typedef union _IMProtocol {
    int        major_code;
    IMAnyStruct any;
    IMConnectStruct imconnect;
    IMDisConnectStruct imdisconnect;
    IMOpenStruct imopen;
    IMCloseStruct imclose;
    IMQueryExtensionStruct queryext;
    IMGetIMValuesStruct getim;
    IMEncodingNegotiationStruct encodingnego;
    IMExtSetEventMaskStruct extsetevent;
    IMExtForwardKeyEventStruct extforward;
    IMExtMoveStruct extmove;
    IMSetEventMaskStruct setevent;
    IMChangeICStruct changeic;
    IMDestroyICStruct destroyic;
    IMResetICStruct resetic;
    IMChangeFocusStruct changefocus;
    IMCommitStruct commitstring;
    IMForwardEventStruct forwardevent;
    IMTriggerNotifyStruct triggernotify;
    IMErrorStruct imerror;
    IMGeometryCBStruct geometry_callback;
    IMPreeditCBStruct preedit_callback;
    IMStatusCBStruct status_callback;
    long pad[32];
} IMProtocol;

   The first two entries of any IMProtocol structure are always the
major_code and minor_code members, which specifies the IMProtocol type.
The third member is the connect_id member, just provided for IMdkit
internal use to distinguish a client from each other.

3.1.2. Protocol Processing

   Some of IMProtocol requests sent by the IMlibrary are processed
internally by IMdkit without passing them to your IMservers, because
IMdkit can determin the answer to such IMProtocol requests only by
using the IMValues which you have set in the XIMS structure.
   At this release, the following four IMProtocol requests is processed
in IMdkit itself, and wouldn't forward to your IMserver:
        o XIM_CONNECT                -> XIM_CONNECT_REPLY
        o XIM_DISCONNECT        -> XIM_DISCONNECT_REPLY
        o XIM_QUERY_EXTENSION        -> XIM_QUERY_EXTENSION_REPLY
        o XIM_GET_IM_VALUES        -> XIM_GET_IM_VALUES_REPLY
   So, you don't have to know the details of the corresponding
IMProtocol structures for these IMProtocol requests.

   On the other hand, you will need to deal with the following requests
for yourselves:
        o XIM_OPEN
        o XIM_CLOSE
        o XIM_SET_IC_FOCUS and XIM_UNSET_IC_FOCUS
        o XIM_DESTROY_IC
        o XIM_RESET_IC
        o XIM_CREATE_IC, XIM_SET_IC_VALUES and XIM_GET_IC_VALUES
        o XIM_TRIGGER_NOTIFY
        o XIM_FORWARD_EVENT
   However, you don't have to receive any raw packets, but can receive
the corresponding IMProtocol structures in your IMProtocolHandler
callback function. Further, you don't have to send a reply for
yourselves, but IMdkit will send a reply soon after your
IMProtocolHandler returns. If your IMProtocolHandler returns True,
IMdkit will send the proper reply to the previous request, and if it
returns False, IMdkit will send XIM_ERROR reply to the XIM client.
   The following IMProtocol structures are what you will actually
receive instead of IMProtocol requests in your IMProtocolHandler
function.

IMOpenStruct
------------
   The IMOpenStruct structure is used for XIM_OPEN and XIM_OPEN_REPLY
requests. The structure contains:

typedef struct {
    int length;
    char *name;
} XIMStr;

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    XIMStr lang;
} IMOpenStruct;

   Your IMserver should check lang field to know which language service
is required by the new client, which is identified with connect_id
member.

IMCloseStruct
-------------
   The IMCloseStruct structure is used for XIM_CLOSE and XIM_CLOSE_REPLY
requests. The structure contains:

typedef struct {
    int                major_code;
    int                minor_code;
    CARD16        connect_id;
} IMCloseStruct;

   Your IMserver should check connect_id member to know which input
method connection should be closed.

IMChangeFocusStruct
-------------------
   The IMChangeFocusStruct structure is used for XIM_SET_IC_FOCUS and
XIM_UNSET_IC_FOCUS requests. The structure contains:

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;        /* input context ID to change focus */
} IMChangeFocusStruct;

   Your IMserver should check icid member to know which input context
should be focusd or unfocusd.

IMDestroyICStruct
-----------------
   The IMDestroyICStruct structure is used for XIM_DESTROY_IC and
request. The structure contains:

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;        /* input context ID to destroy */
} IMDestroyICStruct;

   Your IMserver should check icid member to know which input context
should be destroyed.

IMResetICStruct
---------------
   The IMResetICStruct structure is used for XIM_RESET_IC request. The
structure contains:

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;        /* input context ID to reset */
    CARD16 length;        /* length of committed string below */
    char *commit_string; /* string to commit to XIM client */
} IMResetICStruct;

   Your IMserver should check icid member to know which input context
should be reset.

IMChangeICStruct
----------------
   The IMChangeICStruct structure is used for XIM_CREATE_IC,
XIM_SET_IC_VALUES and XIM_GET_IC_VALUES requests. The structures
contain:

/*
 *  value type for IC defined in XimProto.h
 */
#define        XimType_SeparatorOfNestedList         0
#define        XimType_CARD8                         1
#define        XimType_CARD16                         2
#define        XimType_CARD32                         3
#define        XimType_STRING8                         4
#define        XimType_Window                         5
#define        XimType_XIMStyles                10
#define        XimType_XRectangle                11
#define        XimType_XPoint                        12
#define XimType_XFontSet                13
#define XimType_XIMOptions                14
#define XimType_XIMHotKeyTriggers        15
#define XimType_XIMHotKeyState                16
#define XimType_XIMStringConversion        17
#define        XimType_NEST                        0x7fff

typedef struct {
    int attribute_id;        /* ID for this IC */
    CARD16 name_length;        /* length of IC name below */
    char *name;                /* IC name */
    int value_length;        /* length of IC value below */
    void *value;        /* IC value */
    int type;                /* value type for IC, see above */
} XICAttribute;

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;
        /* input context ID:
           for each CREATE, different ID is expected to be returned.
           for each SET, it shows the ID to set.
           for each GET, it shows the ID to get.
         */
    CARD16 preedit_attr_num;        /* number of preedit_attr list below */
    CARD16 status_attr_num;        /* number of preedit_attr list below */
    CARD16 ic_attr_num;                /* number of ic_attr list below */
    XICAttribute *preedit_attr;        /* IC values for preedit attribute */
    XICAttribute *status_attr;        /* IC values for status attribute */
    XICAttribute *ic_attr;        /* IC values for other attributes */
} IMChangeICStruct;

   When XIM_SET_IC_VALUES or XIM_GET_IC_VALUES, your IMserver should
check icid member to know which input context should be specified. When
XIM_CREATE_IC, your IMserver should set icid member to identify the
input context newly created.

IMTriggerNotifyStruct
---------------------
   The IMTriggerNotifyStruct structure is used for XIM_TRIGGER_NOTIFY
request. The structure contains:

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;
    CARD32 flag;
    CARD32 key_index;
    CARD32 event_mask;
} IMTriggerNotifyStruct;

IMForwardEventStruct
--------------------
   The IMForwardEventStruct structure is used for XIM_FORWARD_EVENT
request. The structure contains:

typedef struct {
    int major_code;
    int minor_code;
    CARD16 connect_id;
    CARD16 icid;        /* input context ID */
    BITMASK16 sync_bit;        /* precessed synchronously or not */
    CARD16 serial_number;
    XEvent event;        /* X event to be filtered */
} IMForwardEventStruct;

3.2.   R5 Ximp IMProtocol

3.2.1. XIMProtocol union data structure

   In R5 Ximp IMProtocol model, all the event structures have the
following common members:

typedef struct {
    INT32 type;                /* message type */
    CARD32 icid;        /* input context ID */
    Window focus_win;        /* focus window */
    long fwin_sel_mask; /* focus window select-mask */
    CARD32 ximp_type_mask; /* Ximp event flow type */
    Window client_win;        /* client window */
} XIMPAnyStruct;

   The type member specifies the Ximp IMProtocol type constant name that
uniquely identies itself.
   In addition to the individual structures declared for each Ximp
XIMProtocol type, the Ximp IMProtocol structure is a union of the
individual structures declared for each Ximp IMProtocol type. Depending
on the type, you should access members of each Ximp IMProtocol by using
the XIMProtocol union.

typedef union _IMPProtocol {
    int                                type;
    XIMPAnyStruct                any;
    XIMPKeyEventStruct                keyevent;
    XIMPICValuesStruct                create;
    XIMPICValuesStruct                setvalue;
    XIMPICValuesStruct                getvalue;
    XIMPAnyStruct                destroy;
    XIMPAnyStruct                regkey;
    XIMPAnyStruct                setfocus;
    XIMPAnyStruct                unsetfocus;
    XIMPClientWindowStruct        clientwin;
    XIMPFocusWindowStruct        focuswin;
    XIMPMoveStruct                move;
    XIMPEventMaskNotifyStruct        evmasknotify;
    XIMPExtensionStruct                extension;
    XIMPReadPropStruct                readprop;
    XIMPResetStruct                reset;
    XIMPCommitStringStruct        commitstring;
    XIMPErrorStruct                error;
    XIMPAnyStruct                geometry_cb;
    XIMPPreeditCBStruct                preedit_cb;
    XIMPStatusCBStruct                status_cb;
    long                        pad[24];
} IMPProtocol;

   The first entry of any XIMProtocol structure is always the
type member, which specifies the Ximp IMProtocol type.

4.   Writing IMservers

When writing an IMserver that uses the IMdkit, you should make sure that
your IMserver performs the following:

   1. Include <X11/Xlib.h> in your IMserver programs.

   2. Include <X11/Ximd/IMdkit.h>. This header file defines all the
   necessary data types and IMdkit functions that you need to use.

   3. Include <X11/Ximd/Xi18n.h> for R6 standard IMProtocol, or
   <X11/Ximd/Ximp.h> for R5 Ximp IMProtocol, respectively.

   4. Call the IMOpenIM function with all the necessary IMValues to
   initialize the connection. The names of each IMValues have a global
   symbol that begins with IM to help catch spelling errors. For
   example, IMModifiers is defined for the XIMProtocol model, and
   IMLocale is defined for the locale resource. For further information,
   see "Section 1.1 Open IM Service" and Section 2 "IMValues"

   5. To set additional IMValues or override the existing IMValues you
   set by IMOpenIM, use IMSetIMValues. You can also use IMGetIMValues to
   look up at existing IMValues. Note that some of IMValues must be set
   at the IM service creation time, and never be changed by
   IMSetIMValues.

   6. You must set the IMProtocol callback routine by the
   IMProtocolHandler argument with IMOpenIM or IMSetIMValues functions.
   This callback is called whenever the IMProtocol is delivered by XIM
   clients.

   7. Now you should select all the necessary X events for your windows
   with XSelectInput function, and map the windows with XMapWindow
   function, then sit in a loop processing events as follows.

    for (;;) {
        XEvent event;
        XNextEvent(your_display, &event);
        if (XFilterEvent(&event, NULL) == True)
          continue;
        YourXEventHandler(&event);
    }

   Here, all the IMProtocols you need are passed to your IMProtocol
   callback routine by X Filtering mechanism of XFilterEvent function,
   and all unfiltered X events you want are passed to YourXEventHandler
   function above.

   8. Link your IMserver with libXimd (the IMdkit library) and libX11
   (the core X library). The following provides a sample command line:

        cc -o sampleIM sampleIM.c -lXimd -lX11
