# Language Engine Interface Specification 1.2

Draft

Draft Version 1.2
Oct 20 1999
Masaki Katakai

## Updates from SDK 1.0 Language Engine Interface Module

  - New concept Desktop to identify a user desktop. `if_OpenDesktop()` and `if_CloseDesktop()` are newly added to IF method.

  - SunIM uses new structure `IMText` for text representation, which is UTFCHAR based and now supports Color feedback.

  - SunIM uses new Event type `IMInputEvent` which does not depend on X event structure anymore.

    Instead of X Keysym, Language Engine module should use `IM_VK` IM keycode, also `IM_MASK` for event mask, which are defined in `SunIM.h`

  - Language Engine does not need to allocate `iml_session_t` in `if_CreateSC()`, which means that `iml_construct_session` and `iml_destruct_session()` had been removed, `if_CreateSC()` can allocate data per a session and return it.

  - `if_FilterEvent()` IF method had been removed.

  - `if_SetAuxValues()` IF method had been removed. New event type `IMAuxEvent` and `if_SendEvent()` can be used instead.

  - Enhancement IML functions for drawing Pre-edit

    - `iml_make_preedit_draw_with_chgpos_inst()` to specify change pos, change len and caret position

  - Enhancement IML functions for handling Luc

    - `iml_make_lookup_start_inst()` to specify `IMLookupStartCallbackStruct`
    - `iml_make_lookup_draw_inst()` to specify `IMLookupDrawCallbackStruct`

  - `iml_make_nop_inst()`, `iml_lookupString()` and `iml_make_reset_return_inst()` had been removed.

  - `iml_make_status_notify_inst()` had been changed to `iml_make_start_conversion_inst()` and `iml_make_end_conversion_inst()` .

  - TM had been removed

## Contents

  ABSTRACT
  SunIM Library Overview
    IF Method
    IML Method
    MM Method
  Programming Interface Overview
    C/C++ programming interface
    MT-Safe
    Locale Independent
  Language Engine Module
    Defining `if_GetIfInfo()` in your engine module
    Destination of Language Engine Module
  Object Downloading
    Defining ObjectDescriptor
  IF Method
    Opening and Closing an IF
    Setting and Querying IF values
    Opening and Closing User Desktop
    Creating and Destroying a Session Context
    Setting and Querying Session values
    Handling Focus
    Resetting a Session
    Handling Input Events
    Managing Desktop and Session
  IML Method
    IMText and IMFeedback
    Drawing Pre-edit
    Drawing Status
    Start and Stop Forwarding Event
    Handling Lookup Choice
    Committing Pre-edit
    Returning Key Event
    Reset-return Pre-edit
    Handling Aux
    Object Downloading
    Linking IML Instance at Tail of List
    Execute the commands
  MM Methods
    Allocate Area
    Free Area
  Example Code
    Template for Language Engine
    Sample for Japanese Language Engine
  Appendix A. Method Summary
    IF Method Summary
    IML Method Summary
    MM Method Summary
  Appendix B. IF Attribute and SC Attribute
    IF Attribute
    SC Attribute
    UI Attribute

## ABSTRACT

  This document describes how to develop Language Engine Modules to be connected to htt_server by using SunIM library. When you have written Language Engine Module once with SunIM library, the module will connect any client that supports Internet-Intranet Input Method(IIIM) protocol through htt_server. It would not be possible to create a program that can talk with IM client directly using IIIM protocol, however, SunIM library provides a useful set of programming interface (IML - Input Method Logic) to control various kinds of operation for input method, pre-edit drawing, status drawing, look-up-choice, object downloading etc.

## SunIM Library Overview

  SunIM library is a programming interface for language engine module. IM developer can use the interface to construct input engine that can connect with any client, can be platform independent Language Engine, can be multilingual Language Engine.

  SunIM library is independent from both htt_server and Language Engines, and constructed by three objects, Input Method Logic(IML), Interface(IF), Memory Manager(MM).

### IF Method

  Language Engine Module needs to define a set of functions, called IF Method, in it. These IF methods will be loaded by htt_server dynamically and will be invoked by htt_server when htt_server receives protocol associated with the Language Engine from IM client. For example, when an input field is created on the user desktop, `if_CreateSC()` IF method is invoked by htt_server. This IF method is resposible for creating a session, the Language Engine Module can do something. `if_SendEvent()` is invoked whenever any input event occurs on the client. The Language Engine Module can look into the event, then can do something for action, such as pre-edit drawing, pop up lookup choice and committing the pre-edit.

### IML Method

  IML Methods is a set of functions and is provided for Language Engines in order to control input method through htt_server. For example, language engine module can draw a pre-edit text and pop up a lookup choice window by calling the IML methods. `IMText` now supports Color feeback for each character.

### MM Method

  `MM Methods` is a set of functions for memory allocation and deallocation. These methods are contained in IML Methods.

## Programming Interface

### C/C++ programming interface

  SunIM library supports both C and C++ programming interfaces.

### MT-Safe

  IF methods defined in Language Engine Module should be MT-Safe. htt_server is now multi-threading per each IM connection.

  However, Language engine can specify the module will run multi-thread or single-thread. Please refer `IF_NEED_THREAD_LOCK` IF attribute.

### Locale Independent

  SunIM library only supports UNICODE based encoding.

  All IF methods and IML methods take `IMText` structure for the argument which are based on UNICODE encoding. Language Engine Module should not use any locale dependent routines in the module, for example, `setlocale()`.

## Language Engine Module

  The Language Engine Module is main part of a Language Engine, which will be loaded dynamically and can be executed by calling IF methods by htt_server.

### Defining `if_GetIfInfo()` in your engine module

  `main()` is not needed in Language Engine Module. The module should define IF Method `if_methods_t` instead of `main()`, which will be called by htt_server when an action, such as IC creation, IC destruction, new user entered, changing input focus, key event that happens on clients.

  The detail of IF Method is described in the next section, IF Method.

  `if_methods_t` is defined as below:

      typedef struct _if_methods {
      	Bool if_OpenIF(iml_if_t * If);
      	Bool if_CloseIF(iml_if_t * If);
      	Bool if_GetIFValues(iml_if_t *, IMArgList, int);
      	Bool if_SetIFValues(iml_if_t *, IMArgList, int);
      	Bool if_OpenDesktop(iml_desktop_t *, IMArgList, int);
      	Bool if_CloseDesktop(iml_desktop_t *);
      	Bool if_CreateSC(iml_session_t *, IMArgList, int);
      	Bool if_GetSCValues(iml_session_t *, IMArgList, int);
      	Bool if_SetSCValues(iml_session_t *, IMArgList, int);
      	IMText *if_ResetSC(iml_session_t *);
      	void if_SetSCFocus(iml_session_t *);
      	void if_UnsetSCFocus(iml_session_t *);
      	void if_SendEvent(iml_session_t *, IMInputEvent *);
      } if_methods_t ;

  `if_GetIfInfo()` is the special method for SunIM library to retrieve the information of the Language Engines, such as the name of engine, the supported locales and objects and methodtable.

  The `if_methods_t` should be returned in as `IF_METHOD_TABLE` in `if_GetIfInfo()`. Also `IF_VERSION`, `IF_LE_NAME`, `IF_SUPPORTED_LOCALES` are required to define in `if_GetIfInfo`. `IF_SUPPORTED_OBJECTS` should be defined when the Language Engine use object downloading.

  `IF_NEED_THREAD_LOCK` is not required but when the Language Engine wants to lock and unlock the thread while executing the IF methods, the Language Engine should define the attribute `True`. The default value is `False`, which means the IF methods of the Language Engine should be MT-Safe.

  For more detail, please refer IF Attribute section of Appendix B. Also, the next selction Object Downloading describes how to specify object as `IMObjectDescriptorStruct`.

  Language Engine module should be shared library `.so` format in UNIX platform, and dynamic library `.DLL` format in Windows NT platform.

  Example

      /*
       * define If method prototype
       */
      static Bool if_template_OpenIF(iml_if_t *);
      static Bool if_template_CloseIF(iml_if_t *);
      static Bool if_template_GetIFValues(iml_if_t *, IMArgList, int);
      static Bool if_template_SetIFValues(iml_if_t *, IMArgList, int);
      static Bool if_template_OpenDesktop(iml_desktop_t *, IMArgList, int);
      static Bool if_template_CloseDesktop(iml_desktop_t *);
      static Bool if_template_CreateSC(iml_session_t *, IMArgList, int);
      static Bool if_template_DestroySC(iml_session_t *);
      static Bool if_template_GetSCValues(iml_session_t *, IMArgList, int);
      static Bool if_template_SetSCValues(iml_session_t *, IMArgList, int);
      static IMText *if_template_ResetSC(iml_session_t *);
      static void if_template_SetSCFocus(iml_session_t *);
      static void if_template_UnsetSCFocus(iml_session_t *);
      static void if_template_SendEvent(iml_session_t *, IMInputEvent * ev);

      /*
       * define if_methods_t
       */
      static if_methods_t if_methods = {
          if_template_OpenIF,
          if_template_CloseIF,
          if_template_GetIFValues,
          if_template_SetIFValues,
          if_template_OpenDesktop,
          if_template_CloseDesktop,
          if_template_CreateSC,
          if_template_DestroySC,
          if_template_GetSCValues,
          if_template_SetSCValues,
          if_template_ResetSC,
          if_template_SetSCFocus,
          if_template_UnsetSCFocus,
          if_template_SendEvent
      };

      UTFCHAR lename_string[] = {0x30b5, 0x30f3, 0x30d7, 0x30eb, 0x65e5,
      			   0x672c, 0x8a9e, 0x30a8, 0x30f3, 0x30b8,
      			   0x30f3, 0x0};

      UTFCHAR jahrn_string[] = {0x65e5, 0x672c, 0x8a9e, 0x0};

      static IMLEName lename = {
          "template", lename_string   /* LE id, HRN */
      };

      static IMLocale locales[] = {
          {"ja", jahrn_string},       /* locale id, HRN */
          NULL
      };

      IMObjectDescriptorStruct *objects = NULL;

      void init_objects();

      void
      if_GetIfInfo(
          IMArgList args,
          int num_args
      )
      {
          int i;

          init_objects();

          for (i = 0; i < num_args; i++, args++) {
              switch (args->id) {
                  case IF_VERSION:
                      args->value = (IMArgVal) "1.2";
                      break;
                  case IF_METHOD_TABLE:
                      args->value = (IMArgVal) & if_methods;
                      break;
                  case IF_LE_NAME:
                      args->value = (IMArgVal) & lename;
                      break;
                  case IF_SUPPORTED_LOCALES:
                      args->value = (IMArgVal) & locales;
                      break;
                  case IF_SUPPORTED_OBJECTS:
                      args->value = (IMArgVal) objects;
                      break;
                  case IF_NEED_THREAD_LOCK:
                      args->value = (IMArgVal) False;
                      break;
                  default:
                      break;
                  }
          }
      }

  When you use C++ for the Language Engine Module, the method should be define as ``export "C"'' for SunIM library

  Example

      extern "C" {
         void
         if_GetIfInfo(
             IMArgList args,
             int num_args
         )
         {
      	...
         }
      }

  For Windows NT platform, the `if_GetIFInfo()` should be defined as `extern __declspec(dllexport)` for `DLL`.

  Example

      #define EXPORT extern __declspec(dllexport)

      EXPORT void
      if_GetIfInfo()
      {
          /* ... */
      }

  And `.def` file is required for exporting the function.

  Example

      ; template.def

      LIBRARY template

      EXPORTS
      	if_GetIfInfo

  For more detail, especially how to build on Windows NT platform, please refer the example codes in the following directries. `sampleja2` is for example codes for C++ programming interface.

      	src/server/programs/language_engines/template

      	src/server/programs/language_engines/sampleja

      	src/server/programs/language_engines/sampleja2

### Destination of Language Engine Module

  The destination of Language Engine modules depends on imlplementation. The default locations for Solaris platform and Windows NT platform are defined as the following. The location can be specified `-ifpath_name` htt_server option, like

      	htt_server -ifpath_name /tmp/iiimf_test

  for Solaris platform. or

      	htt_server -ifpath_name c:\\temp\\iiimf_test

  for Windows NT platform.

  Solaris Platform
    `/usr/lib/im` is now base directory for IIIMF. The Language Engine Module should be located under

        	/usr/lib/im/leif

    for Solaris platform.

    IIIMF SDK 1.2 provides two sample Language Engine Modules under the directory, `sampleja.so` and `tempalte.so`.

  Windows platform
    For Windows NT platform, language engine module should be provided as `DLL` library. The Language Engine Module should be located under

        	D:\\WINNT\\System32\\iiimf

    for Windows NT platform. `sampleja.dll` is provided for example.

## Object Downloading

  Language engine module can send objects to IM client which works as Aux programs on the client side.

### Defining ObjectDescriptor

  Language engine module should define `IMObjectDescriptorStruct` if the language engine needs to use Aux object. The following fields are required for the definition.

  `char *leid`
    This field specifies the identifier for the language engine module, which should be same with the id of `IMLEName`.
  `IMObjectType type`
    Specifies a type of the object.

    `IM_DOWNLOADINGOBJECT_JARGUI_TYPE`
      Declares the object is GUI object and Java jar file format.
    `IM_DOWNLOADINGOBJECT_JARLWE_TYPE`
      Declares the object is LWE object and Java jar file format.
      Note:This feature isn't supported in this version.
    `IM_DOWNLOADINGOBJECT_CCDEF_TYPE`
      Declares the object is CCDEF syntax rule file. It requires `basepath` and `encoding` fields.
      Note:This feature isn't supported in this version.
    `IM_DOWNLOADINGOBJECT_BINGUI_TYPE`
      Declares the object is GUI object and binary file format. Only UNIX platform is supported and it's `.so` shared library format.
    `IM_DOWNLOADINGOBJECT_BINLWE_TYPE`
      Declares the object is LWE object and binary file format. Only UNIX platform is supported and it's `.so` shared library format.
      Note:This feature isn't supported in this version.

  `char **class_names`
    Specifies a list of class name that are included in the object. A jar file can contain multiple classes for the Aux. For example, "foo.bar.sample.SamplePanel" and "foo.bar.sample.SampleAux" can be specified.

    The name specified in this field will be used in `aux_name` field of `IMAuxStartCallbackStruct` , `IMAuxDrawCallbackStruct` and `IMAuxDoneCallbackStruct` at `iml_make_aux_start_inst()` , `iml_make_aux_draw_inst()` and `iml_make_aux_done_inst()` .

  `unsigned int count_names`
    Specifies the number of `class_names`. For the example above, this field should be `2`.

  `UTFCHAR *name`
    Specifies HRN(Human Readable Name) of the object
  `int name_length`
    Specifies the length of `name`

  `char *domain`
    Specifies reversed domain of vender who developed the object.
  `char *path`
    Speficies the location of the object.
  `char *scope`
    Speficies if the object can be used by the other language engine module. If the object is designed only for the language engine module, this field should be same with `leid` field. Otherwise, the object can be used by the others, this field is `generic`.
    Note:`generic` keyword will not work properly in this version. Use `leif` only.

  `char *basepath`
    Required if `type` is `IM_DOWNLOADINGOBJECT_CCDEF_TYPES`. Speficies the location of CCDEF syntax rule files.
    Note: `IM_DOWNLOADINGOBJECT_CCDEF_TYPES` isn't supported in this release.
  `char *encoding`
    Required if `type` is `IM_DOWNLOADINGOBJECT_CCDEF_TYPES`. Speficies the encoding of CCDEF syntax rule.
    Note: `IM_DOWNLOADINGOBJECT_CCDEF_TYPES` isn't supported in this release.

  `IMObjectDescriptorStruct` should be terminated by NULL and specified for `IF_SUPPORTED_OBJECTS` in `if_GetIfInfo` method.

## IF Method

  IF methods will be invoked by htt_server when htt_server receives protocol associated with the Language Engine from IM client.

### Opening and Closing an IF

  When htt_server receives a request of IM connection for the Language Engine, `if_OpenIF()` IF method is invoked to initialize the Language Engine. The Language Engine is able to do something for initialization in this method. These IF methods are only for Language Engine initialization, should not depends on any locale and any user information. The locale and user information of IM client will be usable after `if_OpenDesktop()` IF method is called. If Language Engine does not accept any connections or internal error happens so gives up to continue operation, `if_OpenIF()` should return `False`. Otherwise, it should return `True`.

  When htt_server does not need the Language Engine Interface (IF) opened by `if_OpenIF()` IF method any more, which indicates there is no user to use the Language Engine, `if_CloseIF()` IF method will be called.

  if_OpenIF()

        Bool (*if_OpenIF)(If)
        	iml_if_t *If;

  if_CloseIF()

        Bool (*if_CloseIF)(If)
        	iml_if_t *If;

  Example

      Bool
      if_template_OpenIF(
          iml_if_t * If
      )
      {
          /* initialization for the Language Engine */
          initialize_template();
      }

      Bool
      if_template_CloseIF(
          iml_if_t * If
      )
      {
          /* destruction for the Language Engine */
          close_template();
      }

### Setting and Querying IF values

  These IF methods are provided to query and set, modify IF attributes. However, there is no usable IF attributes in this release.
  if_GetIFValues()

        Bool (*if_GetIFValues)(If, args, n_args)
                iml_if_t   *If;
        	IMArgList  args;
        	int        n_args;

  if_SetIFValues()

        Bool (*if_SetIFValues)(If, args, n_args)
                iml_if_t   *If;
        	IMArgList  args;
        	int        n_args;

### Opening and Closing User Desktop

  As described above, Language Engine should support multi-user connection. A new concept, called a Desktop, is provided to identify the user environment. Desktop is identified by user name, host name and display id, which are represented in `iml_desktop_t` structure.

      typedef struct _iml_desktop_t {
          char *user_name;
          char *host_name;
          char *display_id;
          iml_if If;                          /* parent If */
          iml_inst_slot_t *free_slot_q1;      /* MM general */
          iml_inst_slot_t *free_slot_q2;      /* MM lookup */
          iml_session_list session_list;      /* list of child session */
          struct _iml_desktop_t *next;
          void *specific_data;                /* user deinfed */
      }   iml_desktop_t;

  Language Engine may want to know whether the connection is a first time or second, and may want to know user name of IM client to distinguish the behavior of the Language Engine and license management and etc. These two IF methods are provided for the purpose.

  When the user start to use the Language Engine, `if_OpenDesktop()` IF method is invoked. Language Engine can retrieve the client information such as user name, host name and display id from `iml_desktop_t` structure.

  Language Engine can check the license for the user and the host and if not acceptable, `if_OpenDesktop()` should return `False`, otherwise should return `True`.

  Also, the additional information of IM client can be checked by `IMArgList arg` and `int n_args`. The protocol type, client type, OS name, OS vendor and OS version of IM client are usable. The language engine module can use them if the information other than user name, host name and display id are needed for license management. The attributes are predefined. Please refer UI Attribute section of Appendix.

  When Language Engine may want to prepare allocated data per desktop, Language Engine can allocate and store its pointer to `desktop->specific_data`.

  When htt_server does not need the desktop any more, which indicates the user quits from the desktop, `if_CloseDesktop()` will be called. When Language Engine allocates and stores a data to `desktop->specific_data`, it should be freed in `if_CloseDesktop()` IF method.

  if_OpenDesktop()

        Bool (*if_OpenDesktop)(desktop, args, n_args)
        	iml_desktop_t *desktop;
        	IMArgList     args;
        	int           n_args;

  if_CloseDesktop()

        Bool (*if_CloseDesktop)(desktop)
        	iml_desktop_t *desktop;

  Example

      Bool
      if_template_OpenDesktop(
          iml_desktop_t * desktop,
          IMArgList     args,
          int           n_args
      )
      {
          Bool ret;
          int i;

          /*
           * Additional information of IM client
           */
          char *user_name, *host_name, *display_id, *protocol_type,
      	 *client_type, *os_name, *os_arch, *os_version;

          for (i = 0; i < n_args; i++, args++) {
              switch (args->id) {
                  case UI_USER_NAME: user_name=args->value; break;
                  case UI_HOST_NAME: host_name=args->value; break;
                  case UI_DISPLAY_ID: display_id=args->value; break;
                  case UI_PROTOCOL_TYPE: protocol_type=args->value; break;
                  case UI_CLIENT_TYPE: client_type=args->value; break;
                  case UI_OS_NAME: os_name=args->value; break;
                  case UI_OS_ARCH: os_arch=args->value; break;
                  case UI_OS_VERSION: os_version=args->value; break;
              }
          }

          /*
           * Language Engine can check a license for the user
           */
          ret = check_license(desktop->user_name, desktop->host_name);
          if(ret == True){
              MyDataPerDesktop *my_data_per_desktop = (MyDataPerDesktop *)
          	    malloc(sizeof(MyDataPerDesktop));
      	desktop->specific_data=(void*)my_data_per_desktop;
          }
          return ret;
      }

      Bool
      if_template_CloseDesktop(
          iml_desktop_t * desktop
      )
      {
          /*
           * desktop->specific_data can be used in any IF methods
           */
          MyDataPerDesktop *my_data_per_desktop = (MyDataPerDesktop *)
      		desktop->specific_data;
          /*
           * Language Engine can free the license for the user
           */
          free_license(desktop->user_name, desktop->host_name);
          return True;
      }

### Creating and Destroying a Session Context

  Session
    After `if_CreateSC()` is invoked, the communications between htt_server and a Language Engine will start. For example, there are two applications in the same desktop, A and B. A has three textfields, which means that A creates three ICs. B has two textedits, which means that B creates two ICs. Then, htt_server will manage five different communications(i.e. ICs) in total. And also, it does not matter which IC belongs to either A or B from htt_server's point of view.

    Here, a communication between htt_server and a IC is called a `Session`. The Session that is generated in the client and then a Language Engine has been connected will be the default one in the IC.

    It is important to understand the concept of Session for both IML and IF. Once the connection with a Language Engine is established, both IML and IF is identified by the Session `iml_session_t`and the content is exchanged between htt_server and the Language Engines.

  An input context is created on the client, `if_CreateSC()` is invoked. It's not required to create `iml_session_t` structure here, `iml_session_t` is created by SunIM library side, which means Language Engine does not need to call SDK1.0 based `iml_construct_session()` and `iml_destruct_session()`. The return value of this IF method should be `Bool`. If Language Engine wants to assigne specific data to the session, `s->specific_data` can be used.

  if_CreateSC()

        Bool (*if_CreateSC)(s, args, n_args)
        	iml_session_t *s;
        	IMArgList  args;
        	int        n_args;

  if_DestroySC()

        Bool (*if_DestroySC)(s)
        	iml_session_t *s;

  For example, Language Engine may want to adapt `MyDataPerSession` structure for each session. In this case, `MyDataPerSession` cab be assgined to `s->specific_data`, and which can be referred in any IF methods.

  When the session is acceptable, return `True`. Otherwise, return `False`.

  An IC is destroyed with a call to `if_DestroySC()`. When Language Engine allocates and returns data pointer at `if_CreateSC()` IF method, `s->specific_data` should be freed in `if_DestroySC()`.

  Example

      static Bool
      if_template_CreateSC(
          iml_session_t * s,
          IMArgList args,
          in t n_args
      )
      {
          /* will be stored as s->specific_data */
          MyDataPerSession *my_data_per_session = (MyDataPerSession *)
          	malloc(sizeof(MyDataPerSession));

          s->specific_data = (void*) my_data_per_session;

          return True;
      }

      static Bool
      if_template_GetSCValues(
          iml_session_t * s,
          IMArgList args,
          int n_args
      )
      {
          /* can be referred by s->specific_data in any IF methods */
          MyDataPerSession *my_data_per_session =
          	(MyDataPerSession *) s->specific_data;
      }

      static Bool
      if_template_DestroySC(
          iml_session_t * s
      )
      {
          /* should free in if_DestroySC */
          MyDataPerSession *my_data_per_session =
          	(MyDataPerSession *) s->specific_data;

          free(my_data_per_session);
      }

### Setting and Querying Session values

  These IF methods are provided to query and set, modify SC attributes.

  `if_GetSCValues()` IF method is used to set and modify SC attributes. `if_SetSCValues()` IF method is used to receive values of the SC attributes. Language Engine can use SC attribute and these IF methods for negotiation, such as Object Downloading, with IM client. For more detail, please refer SC Attribute section of Appendix B.

  if_GetSCValues()

        Bool (*if_GetSCValues)(s, args, n_args)
                iml_session_t   *s;
        	IMArgList       args;
        	int             n_args;

  if_SetSCValues()

        Bool (*if_SetSCValues)(s, args, n_args)
                iml_session_t   *s;
        	IMArgList       args;
        	int             n_args;

  Example

      Bool
      if_template_SetSCValues(
          iml_session_t * s,
          IMArgList args,
          int num_args
      )
      {
          int i;
          IMArg *p = args;

          for (i = 0; i < num_args; i++, p++) {
              switch (p->id) {
                  case SC_TRIGGER_ON_NOTIFY:
      		// conversion on
                      break;
                  case SC_TRIGGER_OFF_NOTIFY:
      		// conversion off
                      break;
                  case SC_REALIZE:
                      if(s->desktop->session_count == 1){
      			// can start IM pallet here
                      }
                      break;
                  default:
                      break;
                  }
          }
          return True;
      }

### Handling Focus

  When the input context on the client side gets and loses an input focus, these IF method is invoked.

  if_SetSCFocus()

        void (*if_SetSCFocus)(s)
        	iml_session_t *s;

  if_UnsetSCFocus()

        void (*if_UnsetSCFocus)(s)
        	iml_session_t *s;

### Resetting a Session

  If a client needs to reset the input context, this IF method is invoked with the associated session. This IF method should return the current pre-edit string if needed.

  if_ResetSC()

        IMText *(*if_ResetSC)(s)
        	iml_session_t *s;

### Handling Input Events

  When any event occurs on the client IC, this IF method is invoked with `IMInputEvent`, which contains any event of key event, string event, text event and aux event. Language Engine can find event type by checking `ev->type`.
  if_SendEvent()

        void (*if_SendEvent)(s, ev)
        	iml_session_t  *s;
        	IMInputEvent *ev;

  Receiving Key Event
    Every Key Event is passed in `if_SendEvent()` as `IMKeyListEvent`, which has a list of `IMKeyEventStruct` structure. The Language Engine can know which key was pressed on the client to check `IMKeyEventStruct` structure.

        int keyCode;		/* keycode, defined in SunIM.h */
        int keyChar;		/* keychar is defined */
        int modifier;		/* modifier */

    Example

        if(ev->type == IM_EventKeyList){
        	IMKeyListEvent *keylistevent=(IMKeyListEvent*)ev;
        	IMKeyEventStruct *key=(IMKeyEventStruct*)keylistevent->keylist;
        				/* a key event is used in this release */
        }

    For example, when 'a' is pressed on the client, the following values are passed to `if_SendEvent()` If method. `IM_VK_A` is a keycode which is defined in `SunIM.h`.

        keyCode  : IM_VK_A
        keyChar  : 'a'
        modifier : 0

    When Control+w is pressed, the following values are passed. `IM_CTRL_MASK` is defined in `SunIM.h` as well.

        keyCode  : IM_VK_W;
        keyChar  : 'w';
        modifier : IM_CTRL_MASK

  Returning a Key Event
    When a key event is not processed, which means the key event is not needed for the conversion, the Language Engine wants to back the event to the client. For example, the Language Engine will commit pre-edit string by enter key when the pre-edit string exists, however, when there is no pre-edit string, the Language Engine needs to return the key event of an enter key to the client.

    For this purpose, `iml_make_keypress_inst()` IML method is provided. The method returns a key event to the client. Please refer `iml_make_keypress_inst()` section of `IML method` .

  Receiving Aux Event
    Aux event are also passed in `if_SendEvent()` as `IMAuxEvent`. `IMAuxDrawCallbackStruct` can be retrieved from `aux` field of `IMAuxEvent`

    Example

        if(ev->type == IM_EventAux){
        	IMAuxEvent *auxevent=(IMAuxEvent*)ev;
        	IMAuxDrawCallbackStruct *draw=auxevent->aux;
        }

    Note that SDK1.0 based `if_SetAuxValues` If Method had been obsoleted.

### Managing Desktop and Session

  Language Engine may wants to know how many users are using the engine, how many sessions are opened. `desktop_list` and `session_list` are provided in `iml_if_t` and `iml_desktop_t` strucure for such purposes.

      iml_desktop_list If->desktop_list;

      iml_session_list desktop->session_list;

  Language Engine can retrieve the entry and look into the each desktop and session.

  Example

      Bool
      if_template_OpenDesktop(
          iml_desktop_t *desktop,
          IMArgList      args,
          int            n_args
      )
      {
          /*
      	list users who already used
          */
          iml_desktop_t *p = desktop->If->desktop_list;
          while(p) {
              printf("user name=%s host=%s\n",
                  p->user_name,
                  p->host_name);
              if(p->next) p = p->next;
              else break;
          }
          ...
      }

  `session_list` of desktop can be used as well.

  Example

          iml_session_t *p = s->desktop->session_list;
          while(p) {
              if(p->next) p = p->next;
              else break;
          }

## IML Method

  IML Method is a set of functions predefined in SunIM library to create `iml_inst` instance, which controls pre-edit drawing, status drawing, handling lookup choice and etc.

  Creating `iml_inst` instance does not mean to execute, send the command to the client. Each `iml_make_` IML methods only create `iml_inst` instance. `iml_execute()` is a IML method to execute, in other word, to send IML commands to the client. Thus, network connection does not occur until `iml_execute()` is called.

  There are some convention for each IML methods. Basically, `iml_make_*_start_inst()` IML methods are provided to tell start operation to the client. For example, when Language Engine wants to draw preedit, Language Engine should create `iml_inst` instance by `iml_make_preedit_start_inst()` then should call `iml_execute()` first. After `iml_execute()` is called, Language Engine can draw pre-edit with the `iml_inst` instance created by `iml_make_draw_preedit_inst()` IML methods.

  And `iml_make_*_done_inst()` IML methods are for stop the operations. When Language Engine does not need any drawing of the pre-edit string, LE should create `iml_inst` instance by `iml_make_preedit_done_inst()` and should call `iml_execute()`.

  The arguments of IML methods that represent string should be UTF-16 for multilocale support. `UTFCHAR` is for string. `IMText` is for string, its feedback and annotation. The feedback is now supported with Color representation in SunIM interface. Strings on pre-edit, status and lookup choice can be drawn with specified Color.

### IMText and IMFeedback

  `IMText` structure has the following fields. Each IML methods require `IMText` representation in the argument.

  `IMEncoding encoding`
    Always should be `0`, which means `UTF16_CODESET`.
  `unsigned int char_length`
    Specifies the length of the `text`.
  `UTFCHAR *text.utf_chars`
    Specifies the string which is UTF16.
  `IMFeedbackList *feedback`
    Specifies `IMFeedbackList` structure which represents the feedbacks of the `text.utf_chars`. `feedback` should have the same length of `text.utf_chars`. For example, if you specify `10` length of characters in `text.utf_chars`, `feedback` should have `10` length of `IMFeedbackList`. Each `IMFeedbackList` coresponds each character. A IMFeedbackList `feedback[3]` represents a feedback of the character `text.utf_chars[3]`.
  `unsigned int count_annotations`
    Specifies the number of `annotation`
    Note:annotation isn't supported in this version.
  `IMAnnotation *annotation`
    Specifies the annotation.
    Note:annotation isn't supported in this version.

  `IMFeedbackList` and `IMFeedback` can represend Color feedback for each character. `IMFeedbackList` structure is here,

  `unsigned int count_feedbacks`
    Specify the number of `IMFeedback`
  `IMFeedback *feedbacks`
    Specify the list of `IMFeedback` which has a pair of `IMFeedbackType` and its `value`.

  `IMFeedback` structure is the following, which has a pair of feeback `type` and `value`.

  `IMFeedbackType type`
    Specify the type of `IMFeedback`,
    `IM_DECORATION_FEEDBACK`
      Specify a decoration of a character into `value` field. The value should be any of `IMNormal`, `IMReverse`, `IMUnderline`. This type is required, and the other types are optional.
    `IM_FOREGROUND_RGB_FEEDBACK`
      Specify a foreground color into the `value` field which is a combination value of RGB. `IM_RGB_COLOR(RED,GREEN,BLUE)` macro is predefined. If the value is not specified, the default foreground color will be used on client side.
    `IM_BACKGROUND_RGB_FEEDBACK`
      Specify a background color into the `value` field which is a combination value of RGB. `IM_RGB_COLOR(RED,GREEN,BLUE)` macro is predefined. If the value is not specified, the default background color will be used on client side.
    `IM_UNDERLINE_RGB_FEEDBACK`
      Specify a underline color into the `value` field which is a combination value of RGB. `IM_RGB_COLOR(RED,GREEN,BLUE)` macro is predefined. Note that it's only effective when `IMUnderline` is specified with `IM_DECORATION_FEEDBACK`in the first element. If the value is not specified, the default foreground color will be used on client side.
      Note:This feature isn't supported in this version.``
  `int value`
    Specify a value corresponding with `IMFeedbackType`

  The following codes demonstrate how to specify color feedback in `IMText`. If you specify the IMText filled with color feedbacks to IML methods such as `iml_make_status_draw()` string can be drawn with color in client side.

  Example

      void
      SetFeedback(
          iml_session_t * s,
          IMText * text
      )
      {
          int i;
          IMFeedbackList *fbl;
          IMFeedback *fb;
          int size;

          size = text->char_length;
          text->feedback = (IMFeedbackList *) s->If->m->iml_new(s,
      				sizeof(IMFeedbackList) * size);

          /* set color for each character */
          for (i = 0; i < size; i++) {
              fbl = &text->feedback[i];
              fbl->count_feedbacks = 3;	/* IM_DECORATION_FEEDBACK,
      					 * IM_FOREGROUND_RGB_FEEDBACK,
      					 * IM_BACKGROUND_RGB_FEEDBACK */

              fbl->feedbacks = (IMFeedback *) s->If->m->iml_new(s,
      				sizeof(IMFeedback) * fbl->count_feedbacks);

              /*
              * normal decolation, IM_DECORATION_FEEDBACK is required in
              * the first element
              */
              fb = &fbl->feedbacks[0];
              IM_FEEDBACK_TYPE(fb) = IM_DECORATION_FEEDBACK;
              IM_FEEDBACK_VALUE(fb) = IMNormal;

              /* foreground is blue */
              fb = &fbl->feedbacks[1];
              IM_FEEDBACK_TYPE(fb) = IM_FOREGROUND_RGB_FEEDBACK;
              IM_FEEDBACK_VALUE(fb) = IM_RGB_COLOR(0, 0, 255);

              /* background is blue */
              fb = &fbl->feedbacks[2];
              IM_FEEDBACK_TYPE(fb) = IM_BACKGROUND_RGB_FEEDBACK;
              IM_FEEDBACK_VALUE(fb) = IM_RGB_COLOR(255, 255, 255);
          }
      }

  More examples are shown in sampleja

              src/server/programs/language_engines/sampleja

### Drawing Pre-edit

  The following IML methods are provided for control pre-edit string. First, Language Engine should call `iml_make_preedit_start_inst()` to create an `iml_inst` instance to start the pre-edit drawing. The instance should be executed by `iml_execute()` before `iml_make_preedit_draw_inst()` is called.

  To draw pre-edit string, `iml_make_preedit_draw_inst()` can be used.

  To replace the existing pre-edit string, `iml_make_preedit_draw_with_chgpos_inst()` can be used.

  When Language Engine wants to stop the pre-edit drawing, `iml_make_preedit_done_inst()` should be called to create an `iml_inst` and should be sent by `iml_execute()`.

  `iml_make_preedit_start_inst()`
    This method creates an `iml_inst` instance to start pre-edit drawing. Language Engine should create this `iml_inst` instance and send the instance by `iml_execute()` before `iml_make_preedit_draw_inst()` is called.

        iml_inst *(*iml_make_preedit_start_inst)(s)
        	iml_session_t *s;

  `iml_make_preedit_draw_inst()`
    This method creates an `iml_inst` instance to draw the preedit. It's the simplest way to create `iml_inst` instance for pre-edit drawing. At default, the caret position is moved to the end of entered pre-edit string.

        iml_inst *(*iml_make_preedit_draw_inst)(s, preedit)
        	iml_session_t *s;
        	IMText       *preedit;

  `iml_make_preedit_draw_with_chgpos_inst()`
    This method creates an `iml_inst` instance to replace, delete, insert the pre-edit string to the existing pre-edit string.
    `Text Deletion`
      When the `preedit` field contains 0 length of text data, it indicates the delete operation. The text to be deleted is then the current text in the buffer from position chg_first (starting at zero) on a character length of chg_length.

      When the `preedit` field contains possible length of text data, it indicates either insertion or replacement of text in the buffer.

    `Text Insertion`
      A `chg_length` value of zero indicates that text must be inserted right at the position specified by `chg_first`. A value of zero for `chg_first` specifies the first character in the buffer.
    `Text Replacement`
      A positive `chg_length` indicates that `chg_length` number of characters, starting at `chg_first` must be replaced by text, whose length is specified in the text field of the `preedit` data.
    `Moving Caret`
      The `caret` field identifies the character position before which the cursor should be placed - after modification to the preedit buffer by insertion/replacement/deletion has been completed. For example, if `caret` is zero, the cursor is at the beginning of the buffer. If the `caret` is one, the cursor is between the first and second character.

        iml_inst *(*iml_make_preedit_draw_with_chgpos_inst)(s, preedit, chg_first, chg_length, caret)
                iml_session_t *s;		/* session */
        	IMText        *preedit;		/* pre-edit string to be replaced */
        	int           chg_first;	/* start point to be changed */
        	int           chg_length;	/* length to be changed */
        	int           caret;		/* caret position */

  `iml_make_preedit_erase_inst()`
    This method creates an `iml_inst` instance to erase the existing pre-edit string entirely.

        iml_inst *(*iml_make_preedit_erase_inst)(s)
        	iml_session_t *s;	/* session */

  `iml_make_preedit_caret_inst()`
    This method creates an `iml_inst` instance to set position of caret. The pre-edit text will not be changed.

        iml_inst *(*iml_make_preedit_caret_inst)(s, caret)
        	iml_session_t *s;	/* session */
        	int caret;		/* caret position */

  `iml_make_preedit_done_inst()`
    This method creates an `iml_inst` instance to stop pre-edit drawing. Language Engine should create this `iml_inst` instance and send the instance by `iml_execute()` when pre-edit drawing is not needed anymore.

        iml_inst *(*iml_make_preedit_done_inst)(s)
        	iml_session_t *s;	/* session */

### Drawing Status

  To draw status field, the following IML method can be used. First, Language Engine should call `iml_make_status_start_inst()` to create an `iml_inst` instance to start the status drawing. The instance should be executed by `iml_execute()` before `iml_make_status_draw_inst()` is called. When Language Engine does not need any status drawing, an `iml_inst` instance created by `iml_make_status_down_inst()` should be executed by `iml_execute()`.

  `iml_make_status_start_inst()`
    This method creates an `iml_inst` instance to start status drawing. Language Engine should create this `iml_inst` instance and send the instance by `iml_execute()` before `iml_make_status_draw_inst()` is called.

        iml_inst *(*iml_make_status_start_inst)(s)
        	iml_session_t *s;	/* session */

  `iml_make_status_draw_inst()`
    This method creates an `iml_inst` instance to draw status string.

        iml_inst *(*iml_make_status_draw_inst)(s, status)
        	iml_session_t *s;	/* session */
        	IMText        *status;	/* status string */

  `iml_make_status_done_inst()`
    This method creates an `iml_inst` instance to stop status drawing. Language Engine should create this `iml_inst` instance and send the instance by `iml_execute()` when status drawing is not needed anymore.

        iml_inst *(*iml_make_status_done_inst)(s)
        	iml_session_t *s;	/* session */

### Start and Stop Forwarding Event

  After conversion is turned on, input events on the client associated with the session is being forwarded to the Language Engine through `if_SendEvent()` IF method. When Language Engine have not set `SC_TRIGGER_OFF_KEY` SC attribute in `if_SetSCValues()` IF method, Language Engine oughts to check the input event to find the off key, then if the input event is assigned for off key, Language Engine should send an `iml_inst` instance created by this method.

  `iml_make_start_conversion_inst()`

        iml_inst *(*iml_make_start_conversion_inst)(s)
        	iml_session_t *s;

  `iml_make_end_conversion_inst()`

        iml_inst *(*iml_make_end_conversion_inst)(s)
        	iml_session_t *s;

### Handling Lookup Choice

  To control lookup choice on the client side, the following IML methods are provided. First, Language Engine should create `iml_inst` instance to start lookup operation by `iml_make_lookup_start_inst()`, which takes `IMLookupStartCallbackStruct` structure.

  To display lookup with candidate, the `iml_inst` instance can be created by `iml_make_lookup_draw_inst()`, which takes `IMLookupDrawCallbackStruct` structure. by `iml_make_lookup_process_inst()`.

  After a candidate is selected on the lookup choice, Language Engine needs to create `iml_inst` instance to stop the lookup by `iml_make_lookup_done_inst()` IML method, then needs to send committed string by `iml_make_commit_inst()` IML method.

  `iml_make_lookup_start_inst()`
    This method creates an `iml_inst` instance to start lookup operation. This method needs `IMLookupStartCallbackStruct` structure as the argument. Language Engine specifies detail attributes, such as the number of row and column in `IMLookupStartCallbackStruct`.

        iml_inst *(*iml_make_lookup_start_inst)(s, start)
        	iml_session_t               *s;		/* session */
        	IMLookupStartCallbackStruct *start;	/* start data */

    Here are the fields of `IMLookupStartCallbackStruct`,

    `WhoIsMaster whoIsMaster`
      This field indicates the IMClient how the IMServer will handle the lookup choice operation. Only `IMIsMaster` is supported, which means the Language Engine needs to send a request to lookup draw every time the lookup candidates change.
    `int IMPreference.choice_per_window`
      This field specifies the number of lookup candidates to display in a lookup window at one time.
    `int IMPreference.ncolumns`
      This field specifies the number of columns of lookup candidates to display in a lookup window.
    `int IMPreference.nrows`
      This field specifies the number of rows of lookup candidates to display in a lookup window.
    `DrawUpDirection IMPreference.drawUpDirection`
      This field specifies the drawing direction of lookup candidates. `DrawUpHorizontally`(0) and `DrawUpVertically`(1) are supported.
    `WhoOwnsLabel IMPreference.whoOwnsLabel`
      This field indicates whether the lookup candidates will be labeled, the Language Engine or Client. Only `IMOwnsLabel` is supported, which means the Languane Engine is responsible for labeling the candidates in `IMLookupDrawCallbackStruct`.

    Example

            IMLookupStartCallbackStruct *start;

            start = (IMLookupStartCallbackStruct *) s->If->m->iml_new(s,
                sizeof(IMLookupStartCallbackStruct));
            start->whoIsMaster = IMIsMaster;

            start->IMPreference = (LayoutInfo *) s->If->m->iml_new(s,
                sizeof(LayoutInfo));

            start->IMPreference->choice_per_window = 6;
            start->IMPreference->ncolumns = 1;
            start->IMPreference->nrows = 6;
            start->IMPreference->drawUpDirection = DrawUpHorizontally;
            start->IMPreference->whoOwnsLabel = IMOwnsLabel;

            lp = s->If->m->iml_make_lookup_start_inst(s, start);
            s->If->m->iml_execute(s, &lp);

  `iml_make_lookup_draw_inst()`
    This method creates an `iml_inst` instance to display the lookup. This method can take `IMLookupDrawCallbackStruct` so that the Language Engine specifies detail attributes, such as label for each candidate, number of row and column and etc.

        iml_inst *(*iml_make_lookup_draw_inst)(s, draw)
        	iml_session_t              *s;	  	/* session */
        	IMLookupDrawCallbackStruct *draw;	/* draw data */

    Here are the fields of `IMLookupDrawCallbackStruct`,

    `int index_of_first_candidate`
      This field specifies index of the first candidate.
    `int index_of_last_candidate`
      This field specifies index of the last candidate.
    `int n_choices`
      This field specifies the number of choices of the lookup choice.
    `IMText *title`
      This field specifies title of the lookup choice as `IMText` structure.
    `IMChoiceObject *choices`
      This field specifies each candidate (`value`) and its label(`label`) as `IMChoiceObject` structure.
    `int max_len`
      This field specifies the maximum length of the candidates.
    `int index_of_current_candidate`
      This field specifies the index of current candidate, which is displayed as reversed on the lookup choice.

    Example

            IMLookupStartCallbackStruct *draw;
            IMText *candidates;
            IMText *label;
            int current_index;
            int max_len;

            draw = (IMLookupDrawCallbackStruct *) s->If->m->iml_new(s,
                sizeof(IMLookupDrawCallbackStruct));
            draw->index_of_first_candidate = 0;
            draw->index_of_last_candidate = 5;
            draw->n_choices = 6;

            draw->title = (IMText *) make_luc_title();

            draw->choices = (IMChoiceObject *) s->If->m->iml_new(s,
                draw->n_choices * sizeof(IMChoiceObject));

            for (i = 0; i < draw->n_choices; i++) {
                IMText *vt;		/* for value */
                IMText *lt;		/* for label */
                vt = draw->choices[i].value = candidates[i];
                lt = draw->choices[i].label = labels[i];
                if (max_len < vt->utf_char_length)
                    max_len = vt->utf_char_length;
            }

            draw->max_len = max_len;
            draw->index_of_current_candidate = current_index;

            lp = s->If->m->iml_make_lookup_draw_inst(s, draw);
            s->If->m->iml_execute(s, &lp);

  `iml_make_lookup_done_inst()`
    This method creates an `iml_inst` instance to stop the lookup. Language Engine should create this `iml_inst` instance and sends the command by `iml_execute()` when Language Engine want to stop the lookup operation.

        iml_inst *(*iml_make_lookup_done_inst)(s)
        	iml_session_t *s;

### Committing Pre-edit

  This method creates an `iml_inst` instance to enter strings to the client associated with the session. After pre-edit string is committed, Language Engine needs to create this `iml_inst` instance and send the command by `iml_execute()`.

  `IMText *text` is committed. Note that before committing the text, you need to erase the pre-edited strings.

  `iml_make_commit_inst()`

        iml_inst *(*iml_make_commit_inst)(s, text)
        	iml_session_t *s; /* session */
        	IMText *text;     /* string to be committed */

### Returning Key Event

  This method creates an `iml_inst` instance to return a keyevent to the client associated with the session.

  When the language engine does not process the keyevent received at `if_SendEvent()` If Method, the language engine can return the keyevent to the client. For example, the language engine does not need arrow keys for the conversion but the client needs for the caret movement, the language engine needs to return the keyevent to the client by this IML methods.

  `iml_make_keypress_inst()`

        iml_inst *(*iml_make_keypress_inst)(s, IMKeyEventStruct *key)
        	iml_session_t     *s;   /* session */
        	IMKeyEventStruct  *key; /* key event to be returned */

### Handling Aux

  Language Engine can send own AUX modules to the client through htt_server. <-- by `iml_make_objectdownloading_inst()`. --> After sending AUX modules, Language Engine can controls the AUX by these methods. Each methods take `IMAuxStartCallbackStruct`,`IMAuxDrawCallbackStruct` and `IMAuxDoneCallbackStruct` as argument.

  `char *aux_name`
    Specifies `class name` for AUX. For Java AUX, this field should be class name which are defined in `IMObjectDescriptorStruct`.
  `int count_integer_values`
    specifies number of integer for `count_integer_values`. only `IMAuxDrawCallbackStruct`.
  `int *count_integer_values`
    specifies integer array. only `IMAuxDrawCallbackStruct`.
  `int count_string_values`
    specifies number of string for `string_values`. only `IMAuxDrawCallbackStruct`.
  `IMText *string_values`
    specifies string array as IMText format. only `IMAuxDrawCallbackStruct`.

  `iml_make_aux_start_inst()`
    This method creates an `iml_inst` instance to start AUX module. Language Engine needs to specify AUX id in `IMAuxStartCallbackStruct` structure.

        iml_inst *(*iml_make_aux_start_inst)(s, start)
        	iml_session_t            *s;      /* session */
        	IMAuxStartCallbackStruct *start;

  `iml_make_aux_draw_inst()`
    This method creates an `iml_inst` instance to control AUX module. Language Engine needs to specify AUX id and integer and string array in `IMAuxDrawCallbackStruct` structure.

        iml_inst *(*iml_make_aux_draw_inst)(s, draw)
        	iml_session_t           *s;      /* session */
        	IMAuxDrawCallbackStruct *draw;

  `iml_make_aux_done_inst()`
    This method creates an `iml_inst` instance to stop AUX. Language Engine needs to specify AUX id in `IMAuxDoneCallbackStruct` structure. Language Engine should create this `iml_inst` instance and send the instance by `iml_execute()` when AUX is not needed anymore.

        iml_inst *(*iml_make_aux_done_inst)(s, done)
        	iml_session_t           *s; /* session */
        	IMAuxDoneCallbackStruct *done;

  The events of actions on the AUX can be received by `if_SendEvent()` IF method. `IMInputEvent *ev` of its argument is set for `IMAuxEvent` structure.

### Linking IML Instance at Tail of List

  After creating of each `iml_inst`, Language Engine can execute the command by calling `iml_execute()`. However, multiple `iml_inst` can be stacked by this method, then can be executed by `iml_execute()`. This means that Language Engines does not have to call `iml_execute()` after each `iml_inst` creation.

  `iml_link_inst_tail()`

        iml_inst *(*iml_link_inst_tail)(rrv, lp)
        	iml_inst  **rrv;
        	iml_inst  *lp;

  Example

          iml_inst *rrv = NULL;
          iml_inst *lp;

          lp = s->If->m->iml_make_preedit_draw_inst(s, preedit_string);
          s->If->m->iml_link_inst_tail(&rrv, lp);

          lp = s->If->m->iml_make_status_draw_inst(s, status_string);
          s->If->m->iml_link_inst_tail(&rrv, lp);

          ...

          /*
      	execute commands created by
      		iml_make_preedit_draw_inst() and
      		iml_make_status_draw_inst()
          */
          s->If->m->iml_execute(s, &rrv);

### Execute the commands

  This method executes IML commands, which means sends actual protocol to the client associated with the session. The chain of `iml_inst` stacked by `iml_link_inst_tail()` method can be specified.

  `iml_execute()`

        iml_inst *(*iml_execute)(s, lp);
        	iml_session_t *s; /* session */
        	iml_inst    **lp;

## MM Methods

  The following four methods are provided for management of allocation and deallocation of memory, which are convenient for Language Engine interface. Note that these MM methods are part of IML methods.

### Allocate Area

  `iml_new()` allocates area for short-life-cycle, which means the area allocated by `iml_new()` are freed before the next IF methods is called. For example, when you allocates an area by `iml_new()` in `If_SetSCValues()`, you don't need to free the area at the end of the method because the area will be freed before next call of IF methods, such as `if_SendEvent()`. The argument takes a `iml_session_t* session` and the area to be allocated are associated with the session. So it's possible for Language Engine to manage the allocated area per session.

  Conversely, `iml_new2()` allocates area for long-life-cycle area, which is alive while the session is alive, will not be freed until the session is destroyed so that Language Engine can use the area through until the session is destroyed.

  `iml_new()`

        void *iml_new(s, size)
        	iml_session_t *s;
        	int size;

  `iml_new2()`

        void *iml_new2(s, size)
        	iml_session_t *s;
        	int size;

  Example

      	/*
      	   this area is alive until the session is
      	   destroyed or until iml_delete2() is called.
      	*/
      	char *long_life_area=(char*)s->If->m->iml_new2(s,1000);

      	/*
      	   this area is only alive in this method or
      	   until iml_delete() is called.
      	*/
      	char *short_life_area=(char*)s->If->m->iml_new(s,1000);

### Free Area

  To free the area allocated by `iml_new()` and `iml_new2()`, these methods can be used. `iml_delete()` MM method frees the area allocated by `iml_new()`. `iml_delete2()` MM method frees the area allocated by `iml_new2()`.

  However, normally LE does not need to call these method manually. the area alloced by `iml_new()` is freed by `iml_delete()` automatically in SunIM library before calling the next IF methods. the area alloced by `iml_new2()` is freed by `iml_delete2()` automatically at the session is destroyed.

  `iml_delete()`

        void iml_delete(s)
        	iml_session_t *s;

  `iml_delete2()`

        void iml_delete2(s)
        	iml_session_t *s;

## Example Code

  IIIMP SDK contains two example language engines.

### Template for Language Engine

  `template.c` is provided for the template. All If method are pre-defined so the IM developer can copy and modify it to create own Language Engine Module easily.

      	src/server/programs/language_engines/template.c

### Sample for Japanese Language Engine

  `sampleja.c` is also provided for IM developer. It's more complex but it's very useful. The pre-edit, status drawing, lookup choice operation are defined. For the keybind of `sampleja` sample Language Engine Module, please refer the `README` file on the directory.

      	src/server/programs/language_engines/sampleja

  And `sampleja2.cpp` is an example for C++ programming interface.

      	src/server/programs/language_engines/sampleja2

## Appendix A. Method Summary

### IF Method Summary

  IF Method
  Opening and closing an IF
  Bool | `if_OpenIF(iml_if_t *If)`
  Bool | `if_CloseIF(iml_if_t *If)`
  Setting and Querying IF Values
  Bool | `if_GetIFValues(iml_if_t *If, IMArgList args, int n_args)`
  Bool | `if_SetIFValues(iml_if_t *If, IMArgList args, int n_args)`
  Opening and Closing User Desktop
  Bool | `if_OpenDesktop(iml_desktop_t *desktop, IMArgList args, int n_args)`
  Bool | `if_CloseDesktop(iml_desktop_t *desktop)`
  Creating and Destroying a Session Context
  Bool | `if_CreateSC(iml_session_t *s, IMArgList args, int n_args)`
  Bool | `if_DestroySC(iml_session_t *s)`
  Setting and Querying SC Values
  Bool | `if_GetSCValues(iml_session_t *s, IMArgList args, int n_args)`
  Bool | `if_SetSCValues(iml_session_t *s, IMArgList args, int n_args)`
  Resetting a Session
  IMText* | `if_ResetSC(iml_session_t *s)`
  Handling Focus
  void | `if_SetSCFocus(iml_session_t *s)`
  void | `if_UnsetSCFocus(iml_session_t *s)`
  Handling Input Event
  void | `if_SendEvent(iml_session_t *s, IMInputEvent *ev)`

### IML Method Summary

  IML Method
  Drawing Preedit
  iml_inst* | `iml_make_preedit_start_inst(iml_session_t *s)`
  iml_inst* | `iml_make_preedit_draw_inst(iml_session_t *s, IMText *preedit)`
  iml_inst* | `iml_make_preedit_caret_inst(iml_session_t *s, int caret)`
  iml_inst* | `iml_make_preedit_draw_with_chgpos_inst(iml_session_t *s, IMText *preedit, int chg_first, int chg_length, int caret)`
  iml_inst* | `iml_make_preedit_erase_inst(iml_session_t *s)`
  iml_inst* | `iml_make_preedit_done_inst(iml_session_t *s)`
  Drawing Status String
  iml_inst* | `iml_make_status_start_inst(iml_session_t *s)`
  iml_inst* | `iml_make_status_draw_inst(iml_session_t *s, IMText *status)`
  iml_inst* | `iml_make_status_done_inst(iml_session_t *s)`
  Handling Lookup Choice
  iml_inst* | `iml_make_lookup_start_inst(iml_session_t *s, IMLookupStartCallbackStruct *ls)`
  iml_inst* | `iml_make_lookup_draw_inst(iml_session_t *s, IMLookupDrawCallbackStruct *ld);`
  iml_inst* | `iml_make_lookup_done_inst(iml_session_t *s)`
  Committing Text
  iml_inst* | `iml_make_commit_inst(iml_session_t *s, IMText *text)`
  Returning KeyEvent
  iml_inst* | `iml_make_keypress_inst(iml_session_t *s, IMKeyEventStruct *key)`
  Handling Aux
  iml_inst* | `iml_make_aux_start_inst(iml_session_t *s, IMAuxStartCallbackStruct *start)`
  iml_inst* | `iml_make_aux_draw_inst(iml_session_t *s, IMAuxDrawCallbackStruct *draw)`
  iml_inst* | `iml_make_aux_done_inst(iml_session_t *s, IMAuxDoneCallbackStruct *done)`
  Start and Stop forwarding event
  iml_inst* | `iml_make_start_conversion_inst(iml_session_t *s)`
  iml_inst* | `iml_make_end_conversion_inst(iml_session_t *s)`
  -->
  Linking and Execute Commands
  iml_inst* | `iml_link_inst_tail(iml_inst **rrv, iml_inst *lp)`
  iml_inst* | `iml_execute(iml_session_t *s, iml_inst** lp)`

### MM Method Summary

  MM Method
  Allocates Area
  void* | `iml_new(iml_session_t *s, int size)`
  void* | `iml_new2(iml_session_t *s, int size)`
  Free Area
  void | `iml_delete(iml_session_t *s)`
  void | `iml_delete2(iml_session_t *s)`

## Appendix B. IF Attribute and SC Attribute

  IF, SC and UI attributes are defined as `int` by enum.

### IF Attribute

  IF Attributes
  `IF_VERSION` | `required in if_GetIfInfo()` | Specifies the version of SunIM library. It takes `char*` and `_IF_VERSION_` is predefined in `SunIM` header.
  `IF_METHOD_TABLE` | `required in if_GetIfInfo()` | Specifies the address of the method table. It takes `if_methods_t*`.
  `IF_LE_NAME` | `required in if_GetIfInfo()` | Specifies the name of Language Engine Module. It takes `IMLEName` structure, which can represent id and human readable name of the Language Engine.
  `IF_SUPPORTED_LOCALES` | `required in if_GetIfInfo()` | Specifies supported locales by the Language Engine. It takes null terminated array of `IMLocale` structure. The id and human readable name of the locale can be represented.
  `IF_SUPPORTED_OBJECTS` | `optional in if_GetIfInfo()` | Specifies supported object descripters by the Language Engine. It takes null terminated array of `IMObjectDescriptorStruct` structure.
  `IF_NEED_THREAD_LOCK` | `optional in if_GetIfInfo()` | Specifies `True` or `False` whether the LE is MT-safe or not. `False` is the default. When the attribute is set as `True`, SunIM locks the thread while each IF method is processing and unlocks after IF method is returned.

  `G` = used in `if_GetIFValues()`
  `S` = used in `if_SetIFValues()`
  `G/S` = used in both `if_GetIFValues()`/`if_SetIFValues()`

### SC Attribute

  SC Attributes
  `SC_SUPPORTED_CHARACTER_SUBSETS` | `G` | Specifies supported character subsets for the Language Engine. It takes null terminated array of `int`. The values of each character subsets are described in IM Attribute ID and Appendix B. Values for Character Subsets . Note:This attribute isn't implemented.

  `SC_REALIZE`

  `S`

  Notifies just after the session is created. For example, Language Engine wants to start Aux utility like pallet, LE can use this notification to create `iml_inst` of `iml_make_aux_start_inst()` and call `iml_execute()`.

  Note that After the notification, LE can make `iml_inst` and call `iml_execute()`. In other words, LE can not create any `iml_inst` until this notification is received.

  `SC_TRIGGER_ON_NOTIFY` | `S` | Notifies starting of forward event from the client. For example, Language Engine can know the conversion is turned ON on the client by this notification. It's only for notification so the value is always `NULL` in `if_SetSCValues()` IF method.

  `G` = used in `if_GetSCValues()`
  `S` = used in `if_SetSCValues()`
  `G/S` = used in both `if_GetSCValues()`/`if_SetSCValues()`

### UI Attribute

  UI Attributes
  `UI_USER_NAME` | `` | user name who is using the IM client. When Java client, `System.getProperty("user.name")` will be returned. When Solaris platform, `getpwuid(getuid())->pw_name` will be returned.
  `UI_HOST_NAME` | `` | host name of IM client
  `UI_DISPLAY_ID` | `` | If the client is X, the value of `DisplayName(display)` will be returned. If the client is Java, `":0.0"` will always be returned.
  `UI_PROTOCOL_TYPE` | `` | protocol type of IM client. `"IIIMP"` is for IIIM protocol, `"XIMP"` is XIM protocol or `"XIMCP"` if X11R6 XIMP protocol.
  `UI_CLIENT_TYPE` | `` | client type of IM client. `"JAVA"` is for Java client, or `"X"` is for X client.
  `UI_XSERVER_VENDOR` | `` | Only available if `UI_PROTOCOL_TYPE` is `XIMP` and `XIMCP`. The vendor name of X server on where IM client is running can be checked. The value of `ServerVendor(display)` will be returned.
  `UI_OS_NAME` | `` | The name of operation system. For example, the IM client is running on Solaris platform, `"SunOS"` is returned. The value of `System.getProperty("os.name")` will be returned when `UI_CLIENT_TYPE` is `JAVA`. The value of `sysinfo()` with `SI_SYSNAME` will be returned when `UI_CLIENT_TYPE` is `X`.

  `UI_OS_ARCH`

  ``

  The architecture of the operation system. For example, the IM client is running on Solaris SPARC platform, `"sparc"` is returned. On Solaris Intel platform, `"x86"` is returned. The value of `System.getProperty("os.arch")` will be returned when `UI_CLIENT_TYPE` is `JAVA`. The value of `sysinfo()` with `SI_RELEASE` will be returned when `UI_CLIENT_TYPE` is `X`. However, `"i86pc"` will be changed to `"x86"` for the compatibility for Java client.

  `UI_OS_VERSION` | `` | The version of the operation system. For example, the IM client is running on Solaris 7, `"5.7"` is returned. The value of `System.getProperty("os.version")` will be returned when `UI_CLIENT_TYPE` is `JAVA`. The value of `sysinfo()` with `SI_RELEASE` will be returned when `UI_CLIENT_TYPE` is `X`.

Sun Microsystems, Inc. All Rights Reserved.