#ifndef _Ime_INFO_H_
#define _Ime_INFO_H_

#include "imkey.h"

/** \brief The Encoding alias definition for exchange between LE and IME */
typedef enum {
    ENCODE_INVALID = -1,
    ENCODE_GB2312 = 0,
    ENCODE_GBK,
    ENCODE_GB18030,
    ENCODE_BIG5,
    ENCODE_BIG5HKSCS,
    ENCODE_EUCTW,
    ENCODE_EUCKR,
    ENCODE_EUCJP,
    ENCODE_EUCTH,
    ENCODE_UTF8,
    ENCODE_UTF16,
    ENCODE_UTF16BE,
    ENCODE_UTF16LE,
    ENCODE_UTF32,
    ENCODE_UCS4,
    ENCODE_UCS4LE,
    ENCODE_UCS4BE,
    ENCODES_NUM,
} ImeEncoding;

typedef struct {
    int keycode;        ///< virtual key code for the key just be pressed, please IME_VK_xxx
    int keychar;        ///< corresponding ASCII char value if the key press is an ASCII value. Valid for \n and [0x20-0x7E]
    int modifier;       ///< status for modify key and mouse buttons, reference IME_XXX_MASK definition
    int time_stamp;     ///< incremental integers (per client), time_stamp when the key press happened.
} ImeKeyRec;

typedef ImeKeyRec* ImeKey;  ///< Pointer type to ImeKeyRec

typedef unsigned    ImHandle;

typedef ImHandle    ImeInputContext;

typedef enum {
    ImeFeedbackDecoration = 0,  ///< common decoration, such as highlight, underline, etc
    ImeFeedbackForegroundRGB,   ///< decoration with foreground color
    ImeFeedbackBackgroundRGB    ///< decoration with background color
} ImeFeedbackType;

typedef enum {
    IME_SCOPE_SESSION = 0,
    IME_SCOPE_DESKTOP,
    IME_SCOPE_USER
} ImeScopeType;

/** \brief decoration/feedback for sub-string
*
* A feedback would specify decoration of all characters in a specific range of an string.
*/
typedef struct {
    ImeFeedbackType type;       ///< type of the decoration
    int             value;      ///< depending on type, value could be style, color
    int             start;      ///< starting position of the sub-string, (count start from 0)
    int             length;     ///< number of characters in the sub-string
} ImeFeedbackRec;

typedef ImeFeedbackRec* ImeFeedback;    ///< pointer type to ImeFeedbackRec

/** \brief possible values for ImeFeedbackRec::value when ImeFeedbackRec::type is ImeFeedbackDecoration */
typedef enum {
    IME_DECORATION_NORMAL       = 0,                                ///< No specitial decoration
    IME_DECORATION_REVERSE      = 1,                                ///< reverse
    IME_DECORATION_HIGHLIGHT    = (IME_DECORATION_REVERSE << 1),    ///< highligh
    IME_DECORATION_UNDERLINE    = (IME_DECORATION_HIGHLIGHT << 1),  ///< under_line
    IME_DECORATION_UNDERWAVE    = (IME_DECORATION_UNDERLINE << 1)   ///< under_line wave
} ImeDecorationStyle;

// values for type = ImeFeedbackForegroundRGB || ImeFeedbackBackgroundRGB
#define IME_RGB_COLOR(red, green, blue)     ((int)((red<<16) + (green<<8) + blue))
#define IME_RGB_COLOR_RED(color)            ((int)(color>>16))
#define IME_RGB_COLOR_GREEN(color)          ((int)((color>>8)&0x00ff))
#define IME_RGB_COLOR_BLUE(color)           ((int)(color&0x0000ff))

/** \brief Text with decorations
*
* A string could have multiple feedback to give it presentation. When IME sends these
* Decoration, it should make sure there is no conflicts among them. Otherwise, the
* exact decoration result is not defined. Please note that the sub-strings in
* different feedback could be overlaped as long as they do not conflicts with
* each other.
*/
typedef struct {
    unsigned char  *text;           ///< pointer to the text buffer
    unsigned int    count_feedbacks;///< number of feedbacks
    ImeFeedbackRec *feedbacks;      ///< feedback array
} ImeTextRec;

typedef ImeTextRec* ImeText;            ///< Pointer type to ImeTextRec

/** \brief Preedit data with decoration and caret position */
typedef struct {
    int             caret;        ///< the caret lays just before which character
    ImeTextRec      preedit;      ///< the decorated text
    int             cl_start;     ///< the candidate list starting position, to locate the candidate list window position
} ImePreeditRec;

typedef ImePreeditRec* ImePreedit;      ///< Pointer type to ImePreeditRec

/** \brief bit mask to indicate whether or not current page is first page or last page. Used as value for ImeCandidatsRec::page_state */
typedef enum {
    ImeCandidatesFirstPage    = 1,            ///< is first page
    ImeCandidatesLastPage     = 2             ///< is last page
} ImeCandidatePageMask;

typedef struct {
    unsigned char  *title;          ///< title for the candidates, whether or not Aux support candidate area title is implementation depenedent.
    int             count;          ///< How many candidates here
    ImeText         candidates;     ///< Pointer array, 'count' items in the array.
    unsigned char  *numbers;        ///< numbering
    int             focus;          ///< current focused candidate, [0..count], 0 means no focused candidate
    int	            page_state;     ///< first/last page information, safe to set it to 0 for those IME do not know how many pages and current page.
    int             horizental;     ///< 1 to use horizental layout, 0 to use vertical layout, to make it compatible default vertical (0)
} ImeCandidatesRec;

typedef ImeCandidatesRec* ImeCandidates;  ///< Pointer type to ImeCandidatesRec

/*! \addtogroup Basic_Types */
/** \brief Propertyies type.
*
* Property could be used to construct GUI for user to specify their values.
*
* @note, Properties used only for configuration user preference, do not think
* about using this could help other things greatly.
*/
typedef enum {
    ImeProperty_String,     ///< String type, have length limits
    ImeProperty_Int,        ///< Integer type, have value limits
    ImeProperty_Float,      ///< float type, have value limits
    ImeProperty_Toggle,     ///< boolean, or [0,1] int value, value is int value, do not care range
    ImeProperty_Selection,  ///< select one from multiple strings. Range is char **, value is the selection idx.
} ImePropertyType;

/** \brief limits for the string length. (0, 0) means no limitation */
typedef struct {
    unsigned int min_length;    ///< minimum length
    unsigned int max_length;    ///< maximum length
} ImeStringPropertyRangeRec;

/** \brief limits for integer values. (0, 0) means no limitation */
typedef struct {
    int min;    ///< min value
    int max;    ///< max value
} ImeIntPropertyRange;

/** \brief  limits for float values, (0, 0) means no limits */
typedef struct {
    float min;  ///< min value
    float max;  ///< max value
} ImeFloatPropertyRangeRec;

/** \brief simple union for serveral range types */
typedef union {
    ImeIntPropertyRange	       int_range;         ///< integer value range
    ImeStringPropertyRangeRec  len_range;         ///< string len range
    ImeFloatPropertyRangeRec   float_range;       ///< float range
    char **                    multiString_range; ///< MultiString to select, the last string must be NULL
} ImePropertyRangeRec;

/** \brief union type for property values */
typedef union {
    int		int_value;      ///< int value
    float	float_value;    ///< float value
    char*	string_value;   ///< string value
} ImePropertyValueRec;

/** \brief standard property for configuration */
typedef struct  {
    int   		id;      ///< ??? maybe not needed???
    ImeEncoding		encode;  ///< encode for the following strings
    const char *	key;     ///< Path string looks like unix file path, for uniquely identify a property
    const char *	name;    ///< for display usage
    const char *	tip;     ///< simple description
    ImePropertyType 	type;    ///< type of the property
    ImePropertyRangeRec	range;   ///< range of the property
    ImePropertyValueRec	value;   ///< current value of the property
} ImePropertyRec;

typedef ImePropertyRec* ImeProperty; ///< Pointer type to ImePropertyRec

/** \brief Infact a property array with count information
*
* @note Please look at  ImeMethodsRec::ImmConfigIme()
*/
typedef struct {
    int           count;         ///< number of properties
    ImeProperty   properties;    ///< pointer to properties array
} ImePropertyListRec;

typedef ImePropertyListRec* ImePropertyList; ///< Pointer type to ImePropertyListRec
/**@}*/

typedef struct {
    int              version;            ///< IME's version. version%100 is minor version, version/100 is major version
    int              mt_safe;            ///< whether or not this IME is MultiThread safe.
    ImeEncoding      encoding;           ///< encoding used by all strings communicating with IMM, like preedit
    const char      *uuid;               ///< IME's English name.
    const char      *name;               ///< localized input method name, also in above encoding
    const char      *author;             ///< IME's author
    const char      *hinting;            ///< Simple descrition for the IME. Maybe displayed as StatusBar's button hinting.
    const char      *copyright;          ///< Copyright string
    const char      *icon_file;          ///< If relative path, to the dir of IME's so file. File format: XPM
    const char      *support_locales;    ///< locale the IME supports, string with different locales seperated by ',' .
    ImePropertyList  pl;                 ///< property list used to do standard configuration. could be NULL.
    void            *specific_data;      ///< IME's specific data. used for single so get into serveral IMEs.
} ImeInfoRec;

typedef ImeInfoRec  *ImeInfo;       ////< pointer type to ImeInfoRec

/*! \addtogroup Events Events between IME and Aux */
/*@{*/

/** \brief standard event/message type definition */
typedef enum {
    IME_EVENT_CUSTOM_DATA  = 0,    ///< custom defined user type event/data
    IME_EVENT_IMM_NOTIFY,          ///< Notification event from the status bar, Full/half punc, Configure Request, etc
    IME_EVENT_QUIT,                ///< UI quit event.
    IME_EVENT_EXPOSE,              ///< Show/Hide/Check status change event
    IME_EVENT_MOVE,                ///< Aux window move event
    IME_EVENT_PREEDIT_DATA,        ///< Preedit area data event
    IME_EVENT_PREEDIT_CARET_MOVE,  ///< Preedit area caret position event
    IME_EVENT_CANDI_DATA,          ///< Candidate area data event
    IME_EVENT_PROPERTY,            ///< Porperty message
    IME_EVENT_CANDI_PAGE,          ///< Candidate area page event
    IME_EVENT_CANDI_FOCUS,         ///< Candidate area focus event
    IME_EVENT_CANDI_SELECT,        ///< Candidate area selection event
    IME_EVENT_NONE
} ImeAuxEventType;

/** \brief Standard event head, also used for common event */
typedef struct {
    int		    type;           ///< could be values defined in ImeAuxEventType
    ImHandle	    peer;           ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext ic;             ///< the ic the communication is based on
    int		    param;          ///< semantic determined by type
} ImeEventHeadRec;

typedef ImeEventHeadRec* ImeEventHead;  ///< Pointer type to  ImeEventHeadRec

typedef enum {
    IMM_TRIGGER_FULL_HALF_SIMBOL = 0,   ///< Full/half simbol status,  0 == half, 1 == full
    IMM_TRIGGER_FULL_HALF_PUNC,         ///< Full/half punction status, 0 == half, 1 == full
    IMM_TRIGGER_LANGUAGE,               ///< Cn/En status, 0 == en, 1 == zh_CN
    IMM_TRIGGER_CONFIG_REQUEST          ///< Comes a configuration request from status bar
} ImmTriggerType;

/** \brief Standard notification from status bar, including full/half punc status, confige request, etc
*
* @note, if IME do not process this messages, please return IME_UNPROCESSED_EVENT。
*        This is important if you want to use default configuration UI by just providing
*        property list.
*/
typedef struct {
    int		    type;           ///< could be values defined in ImeAuxEventType
    ImHandle	    peer;           ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext ic;             ///< the ic the communication is based on
    ImmTriggerType  trigger;        ///< id represented different notification, see
    int             value;          ///< value of above trigger
} ImeEventImmNotifyRec;

typedef ImeEventImmNotifyRec* ImeEventImmNotify;

/** \brief Quit event, same as ImeEventHeadRec. type must be IME_EVENT_QUIT, param is the exit code from the Aux
*
*    UI notify IMM/IME that it will quit (send from UI to IME), or IME/IMM force UI quit (send from IME to UI)
*/
typedef ImeEventHeadRec     ImeQuitEventRec;
typedef ImeQuitEventRec*    ImeQuitEvent;    ///< Pointer type to ImeQuitEventRec

/** \brief Status definition for GUI status about show/hide, bit masks */
typedef enum {
    IMUI_STATE_SHOW         = 1,                        ///< whether GUI is show/hide
    IMUI_STATE_ENABLE       = (IMUI_STATE_SHOW <<1),    ///< whether the GUI element is enabled/disabled.
    IMUI_STATE_CHECK        = (IMUI_STATE_ENABLE<<1)    ///< whether or not the GUI element is checked (such as menu item)
} ImeUIStatusMask;

/** \brief page operations */
typedef enum {
    ImeCandidatesPageFirst,        ///< to first page
    ImeCandidatesPagePrevious,     ///< to previous page
    ImeCandidatesPageNext,         ///< to next page
    ImeCandidatesPageLast          ///< to last page
} ImePageOperation;

/** \brief Expose event, same as ImeEventHeadRec. type must be IME_EVENT_EXPOSE, param is from ImeUIStatusMask
*
* UI notify IMM/IME that its show/hide status changed, or IME/IMM command UI changeits show/hide status
*
* @note ImmServicesRec::ImmShowPreedit() and ImmServicesRec::ImmHidePreedit() are implemented by sending this
* event to preedit. So about the ImmServicesRec::ImmShowCandidates() and ImmServicesRec::ImmHideCandidates().
* So, Your owner-draw Preedit/Candidates area should response to these event.
* @note param should be combination of the ImeUIStatusMask
*/
typedef ImeEventHeadRec     ImeExposeEventRec;
typedef ImeExposeEventRec*  ImeExposeEvent;     ///< Pointer type to ImeExposeEventRec

typedef ImeEventHeadRec     ImeCandidateSelectEventRec;
typedef ImeEventHeadRec     ImeCandidatePageEventRec;

#define IME_MOVE_FREELY     (-65535)            ///< When used in ImeMoveEventRec, means UI determines the position/size

/** \brief Move Event type must be IME_EVENT_MOVE, param is not used.
*
* notify IMM/IME that its position/size changed, or IME/MM command UI change its position/size
*
* @note As Expose Event, ImmServicesRec::ImmShowPreedit() and ImmServicesRec::ImmHidePreedit() are implemented by sending this
* event to preedit. So about the ImmServicesRec::ImmShowCandidates() and ImmServicesRec::ImmHideCandidates().
* So, Your owner-draw Preedit/Candidates area should response to these event.
*/
typedef struct {
    int		    type;    ///< Must be IME_EVENT_MOVE
    ImHandle	    peer;    ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext ic;      ///< the ic the communication is based on
    int		    param;   ///< not used
    int		    left;    ///< window's left position in pixel, could be IME_MOVE_FREELY
    int             top;     ///< window's top position, in pixel, could be IME_MOVE_FREELY
    int             width;   ///< window's width, in pixel, could be IME_MOVE_FREELY
    int             height;  ///< window's height, in pixel, could be  IME_MOVE_FREELY
} ImeMoveEventRec;

typedef ImeMoveEventRec*    ImeMoveEvent;   ///< Pointer type to ImeMoveEventRec

/** \brief Preedit data event
*
* IME/IMM command Preedit-UI to change the preedit data
*
* @note owner-draw Preedit/Candidates area should response to these event,
* also they have to remember the ic handel and im handle to send back other request, such
* as page next request from the user.
*/
typedef struct {
    int		    type;    ///< IME_EVENT_PREEDIT_DATA
    ImHandle	    peer;    ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext ic;      ///< the ic the communication is based on
    int		    param;   ///< not used
    ImePreedit*     preedit; ///< data used to update the preedit-area
} ImePreeditDataEventRec;

typedef ImePreeditDataEventRec* ImePreeditDataEvent;    ///< Pointer type to ImePreeditDataEventRec

/** \brief Preedit caret move event, same as ImeEventHeadRec. type must be IME_EVENT_PREEDIT_CARET_MOVE, param is caret position
*
* Preedit-UI notify IME/IMM that caret position changed, or IME/IMM command Preedit-UI change its caret position
*/
typedef ImeEventHeadRec              ImePreeditCaretMoveEventRec;
typedef ImePreeditCaretMoveEventRec* ImePreeditCaretMoveEvent;   ///< Pointer type to ImePreeditCaretMoveEventRec

/** \brief Candidates data event
*
* IME/IMM command candidates-UI to update candidates-data
*/
typedef struct  {
    int		    type;       ///< IME_EVENT_CANDI_DATA
    ImHandle	    peer;       ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext ic;         ///< the ic the communication is based on
    int		    param;      ///< encoding id
    ImeCandidates   candidates; ///< new candidates to update the candidates area
} ImeCandidateDataEventRec;

typedef ImeCandidateDataEventRec* ImeCandidateDataEvent;    ///< Pointer type to ImeCandidateDataEventRec

/** \brief event for propertis. Normally it is used inside IMM, but IME could also utilized this if possible. */
typedef struct {
    int		        type;    ///< IME_EVENT_PROPERTY
    ImHandle	        peer;    ///< to IME it's an Auxilary window handle, to Aux, it is an IME handle
    ImeInputContext     ic;      ///< the ic the communication is based on
    int		        param;   ///< encoding id
} ImePropertyEventRec;

typedef ImePropertyEventRec*    ImePropertyEvent;

/** \brief common user customized event/message
*
*  For user defined protocals, param could be used as user defined protocal number.
*/
typedef struct  {
    int		        type;    ///< IME_EVENT_CUSTOM_DATA
    ImHandle	        peer;    ///< to IME, it's an Auxilary window handle, to Aux, it is an IC handle
    ImeInputContext     ic;      ///< an handle of IME, only used by Auxilary window, IME would not care about this
    int		        param;   ///< Could be used as user defined protocal number
    int		        nInteger;///< how many integers to be transfer, any LE/BE related data should be transfer here
    int*	        integers;///< integer array
    int		        nBuf;    ///< how many byte buffer to be transfered
    int*	        buf_lens;///< buf len array for those buffers. If you are transfering string, please count the ending '\0'
    unsigned char**     bufs;    ///< buffer pointer's array
} ImeDataEventRec;

typedef ImeDataEventRec* ImeDataEvent;  ///< Pointer type to ImeDataEventRec

typedef union {
    int 		        type;                     ///< event type
    ImeEventHeadRec	        any_event;                ///< event head
    ImeQuitEventRec	        quit_event;               ///< Quit Event
    ImeCandidateSelectEventRec  candidate_select_event;   ///< candidate selection
    ImeCandidatePageEventRec    candidate_page_event;     ///< candidate page
    ImeMoveEventRec		move_event;               ///< Move Event
    ImeExposeEventRec	        expose_event;             ///< Expose Event
    ImeEventImmNotifyRec        notify_event;             ///< notification event from IMM
    ImePreeditDataEventRec	preedit_data_event;       ///< Preedit data event
    ImePreeditCaretMoveEventRec	preedit_caret_move_event; ///< Preedit caret moe event
    ImeCandidateDataEventRec	candidate_data_event;     ///< candidates data event
    ImeDataEventRec 		data_event;               ///< customized event
    ImePropertyEventRec         property_event;           ///< property_value for current ic user
} ImeEventRec;

typedef ImeEventRec*            ImeEvent;       ///<  Pointer type to ImeEventRec
/*@}*/

/** \brief Type of beeps */
typedef enum {
    ImeBeepWarning, ///< beep for warning
    ImeBeepError    ///< beep for an error
} ImeBeepType;

/** \brief some key value definition returned by ImmPrefilterKey */
typedef enum {
    IME_FILTERED_KEY_UNUSED = 0,
    IME_FILTERED_KEY_ESCAPE,
    IME_FILTERED_KEY_ENTER,
    IME_FILTERED_KEY_SPACEBAR,
    IME_FILTERED_KEY_PAGEUP,
    IME_FILTERED_KEY_PAGEDOWN,
    IME_FILTERED_KEY_INSERT,
    IME_FILTERED_KEY_DELETE,
    IME_FILTERED_KEY_BACKSPACE,
    IME_FILTERED_KEY_HOME,
    IME_FILTERED_KEY_END,
    IME_FILTERED_KEY_LEFT,
    IME_FILTERED_KEY_RIGHT,
    IME_FILTERED_KEY_UP,
    IME_FILTERED_KEY_DOWN,
} ImeKeyType;

typedef enum {
    IMM_OK                  = 0,      ///< Success
    IMM_FAIL                          ///< general fail
} ImmResult;

typedef struct {
    int        version;     ///< API version of the IMM services. version%100 is minor version. version/100 is major version.

    ImeInfo    (*ImmGetImeInfo)(ImeInputContext ic);

    ImeEncoding(*ImmGetSessionEncoding)(ImeInputContext ic);


    ImmResult  (*ImmShowPreedit)(ImeInputContext ic);

    ImmResult  (*ImmHidePreedit)(ImeInputContext ic);

    ImmResult  (*ImmUpdatePreedit)(ImeInputContext ic, ImePreedit preedit_data);

    ImmResult  (*ImmMovePreeditCaret)(ImeInputContext ic, int idx);

    ImmResult  (*ImmShowCandidates)(ImeInputContext ic);

    ImmResult  (*ImmHideCandidates)(ImeInputContext ic);

    ImmResult  (*ImmUpdateCandidates)(ImeInputContext ic, ImeCandidates candi);

    ImmResult  (*ImmCommit)(ImeInputContext ic, unsigned char* commit_text);


    ImHandle   (*ImmStartUI)(ImeInputContext ic, const char* aux_name);

    ImmResult  (*ImmCloseUI)(ImeInputContext ic, ImHandle aux_handle);

    ImmResult  (*ImmSendUiMessage)(ImeEvent event);


    void*      (*ImmGetData)(ImeInputContext ic, int scope); // "scope" please ref ImeScopeType

    ImmResult  (*ImmSetData)(ImeInputContext ic, int scope, void* pdata);


    void*      (*ImmLoadUserProfile)(ImeInputContext ic, const char* category, int* psz);

    ImmResult  (*ImmFreeUserProfile)(void* buf);

    ImmResult  (*ImmSaveUserProfile)(ImeInputContext ic, const char* category, void* buf, int sz);


    ImmResult  (*ImmBeep)(ImeInputContext ic, ImeBeepType ime_beep_type);

    ImeKeyType (*ImmPrefilterKey)(ImeKey key);

    ImePropertyListRec* (*ImmGetPropertyList)(ImeInputContext ic);

} ImmServicesRec;

typedef ImmServicesRec*     ImmServices;            ///< Pointer type to ImmServicesRec


typedef enum {
    IME_OK                  = 0,        ///< success
    IME_FAIL,                           ///< general error
    IME_UNUSED_KEY,                     ///< return by ImeProcessKeyEvent()
    IME_INVALID_KEY,                    ///< unexpected key, should not return to application, normally ring a bell
    IME_UNPROCESSED_EVENT,              ///< a event is not cared by the ime, IMM may continue processing, like some StatusEvent
    IME_UNSUPPORT_VERSION,              ///< error version
    IME_WRONG_ARGS,                     ///< error in args
    IME_FIRST_CUSTOM_ERROR   = 1000     ///< user could define his own error using error larger than this.
} ImeResult;

typedef struct {
    int        version;                 ///< API verion. version%100 as minor version. version/100 is major version.

    ImeResult  (*ImeInitialize)(ImeInfo ime_info);
    ImeResult  (*ImeDestroy)(ImeInfo ime_info);

    ImeResult  (*ImeProcessKeyEvent)(ImeInputContext ic, ImeKey ime_key);
    ImeResult  (*ImeProcessUIEvent)(ImeInputContext ic, ImeEvent event);

    ImeResult  (*ImeCreateSession)(ImeInputContext ic);

    ImeResult  (*ImeDestroySession)(ImeInputContext ic);

    ImeResult  (*ImeFocusIn)(ImeInputContext ic);

    ImeResult  (*ImeFocusOut)(ImeInputContext ic);

    ImeResult  (*ImeAttachUser)(ImeInputContext ic);

    ImeResult  (*ImeDetachUser)(ImeInputContext ic);

    ImeResult  (*ImeAttachDesktop)(ImeInputContext ic);

    ImeResult  (*ImeDetachDesktop)(ImeInputContext ic);

    const char*(*ImeGetErrorMessage)(int error_id);

} ImeMethodsRec;

typedef ImeMethodsRec*  ImeMethods;     ///< Pointer to ImeMethodsRec

#if defined(__CPLUSPLUS__) || defined(__cplusplus)
extern "C"
#endif
ImeResult RegisterIME(ImmServices srvs, ImeInfo* ppinfo, ImeMethods* pmthds, int argc, char **argv);


typedef struct {
    int        version;
    ImmResult  (*ImmSendImeMessage)(ImeEvent event);
    ImmResult  (*ImmCommit)(unsigned char* commit_text, ImeEncoding enc);
} ImmServicesUiRec;

typedef ImmServicesUiRec* ImmServicesUi;

typedef struct {
    int        version;
    ImeResult  (*ImUiInitialize)(ImmServicesUi pservices);
    ImeResult  (*ImUiDestroy)();
    ImeResult  (*ImUiProcessEvent)(ImeEvent event);
} ImUiMethodsRec;

typedef ImUiMethodsRec*  ImUiMethods;

#endif /* _Ime_INFO_H_ */
