#include <stdio.h>

#include "le_info.h"
#include "le_session.h"

#include "le_aux_protocol.h"

#define IMM_SERVICE_VERSION 0x0101

ImeInfo le_get_ime_info(ImeInputContext);
ImeEncoding le_get_session_encoding(ImeInputContext);
ImmResult le_show_preedit(ImeInputContext);
ImmResult le_hide_preedit(ImeInputContext);
ImmResult le_update_preedit(ImeInputContext, ImePreedit);
ImmResult le_move_preedit_caret(ImeInputContext, int);
ImmResult le_show_candidates(ImeInputContext);
ImmResult le_hide_candidates(ImeInputContext);
ImmResult le_update_candidates(ImeInputContext, ImeCandidates);
ImmResult le_commit(ImeInputContext, unsigned char *);
ImHandle le_show_aux(ImeInputContext, const char *);
ImmResult le_hide_aux(ImeInputContext, ImHandle);
ImmResult le_send_aux_data(ImeEvent event);
void *le_get_ime_data(ImeInputContext, int);
ImmResult le_set_ime_data(ImeInputContext, int, void *);
void *le_load_user_profile(ImeInputContext, const char *, int *);
ImmResult le_free_user_profile(void *);
ImmResult le_save_user_profile(ImeInputContext, const char *, void *, int);
ImmResult le_beep(ImeInputContext, ImeBeepType);
ImeKeyType le_map_keyevent(ImeKey);
ImePropertyListRec *le_get_ime_properties(ImeInputContext);

ImmServicesRec le_services = {
    IMM_SERVICE_VERSION,	/* version */
    le_get_ime_info,		/* ImmGetImeInfo */
    le_get_session_encoding,	/* ImmGetClientEncoding */
    le_show_preedit,		/* ImmShowPreedit */
    le_hide_preedit,		/* ImmHidePreedit */
    le_update_preedit,		/* ImmUpdatePreedit */
    le_move_preedit_caret,	/* ImmMovePreeditCaret */
    le_show_candidates,		/* ImmShowCandidates */
    le_hide_candidates,		/* ImmHideCandidates */
    le_update_candidates,	/* ImmUpdateCandidates */
    le_commit,			/* ImmCommit */
    le_show_aux,		/* ImmStartAux */
    le_hide_aux,		/* ImmCloseAux */
    le_send_aux_data,		/* ImmSendUiMessage */
    le_get_ime_data,		/* ImmGetData */
    le_set_ime_data,		/* ImmGetData */
    le_load_user_profile,	/* ImmLoadUserProfile */
    le_free_user_profile,	/* ImmFreeUserProfile */
    le_save_user_profile,	/* ImmSaveUserProfile */
    le_beep,			/* ImmBeep */
    le_map_keyevent,		/* ImmPrefilterKey */
    le_get_ime_properties,	/* ImmGetPropertyList */
#if 0
    NULL,			/* ImmRegisterPreeditUI */
    NULL,			/* ImmRegisterCandidateUI */
    NULL,			/* ImmUnregisterPreeditUI */
    NULL,			/* ImmUnregisterCandidateUI */
    NULL,			/* ImmConfigIme */
    NULL,			/* ImmGetICAttribute */
    NULL,			/* ImmSetICAttribute */
    NULL,			/* ImmSendRegisterWords */
    NULL,			/* ImmLoadIcon */
    NULL			/* ImmFreeIcon */
#endif
};

ImeInfo le_get_ime_info(ImeInputContext ime_input_context)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    ImeModuleRec *ime_module = NULL;

    if (le_session_context == NULL)
        return (NULL);

    if (le_session_context->s == NULL)
        return (NULL);

    ime_module =
        (ImeModuleRec *)
        le_session_get_current_ime_module(le_session_context->s);
    if (ime_module == NULL)
        return (NULL);

    return (ime_module->info);
}

ImeEncoding le_get_session_encoding(ImeInputContext ime_input_context)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    iml_session_t *s = NULL;

    if (le_session_context == NULL)
        return (ENCODE_UTF8);

    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (ENCODE_UTF8);

    return (le_session_get_client_encoding(s));
}

#define COMPOSITE_STYLE 0

static void dupIMText(ImeTextRec* dst, ImeTextRec* src)
{
    int i;

    if (src) {
        *dst = *src;
        if (src->text) {
            dst->text = (unsigned char*)strdup((char*)src->text);
        }
        if (src->feedbacks) {
            dst->feedbacks = (ImeFeedbackRec*)calloc(src->count_feedbacks,
                                                     sizeof(ImeFeedbackRec));
            for (i = 0; i <  src->count_feedbacks; ++i)
                dst->feedbacks[i] = src->feedbacks[i];
        }
    } else {
        memset(dst, 0, sizeof(ImeTextRec));
    }
}

static void dupPreedit(ImePreeditRec* dst, ImePreeditRec * src)
{
    *dst = *src;
    dupIMText(&dst->preedit, &src->preedit);
}

static void dupCandidates(ImeCandidatesRec* dst, ImeCandidatesRec*src)
{
    int i;

    *dst = *src;
    if (src->title) dst->title = (unsigned char*)strdup(src->title);
    if (src->numbers) dst->numbers = (unsigned char*)strdup(src->numbers);
    dst->candidates = NULL;
    if (src->count) {
        dst->candidates = (ImeTextRec*)calloc(src->count, sizeof(ImeTextRec));
        for (i=0; i < src->count; ++i) {
            dupIMText(&(dst->candidates[i]), &(src->candidates[i]));
        }
    }
}

void freeImPreeditInternal(ImePreeditRec* dst)
{
    if (dst->preedit.text) free(dst->preedit.text);
    if (dst->preedit.feedbacks) free(dst->preedit.feedbacks);
    memset(dst, 0, sizeof(ImePreeditRec));
}

void freeImCandidatesInternal(ImeCandidatesRec* dst)
{
    int i;

    if (dst->title) free(dst->title);
    if (dst->numbers) free(dst->numbers);
    if (dst->candidates) {
        for (i=0; i < dst->count; ++i) {
            if (dst->candidates[i].text) free(dst->candidates[i].text);
            if (dst->candidates[i].feedbacks) free(dst->candidates[i].feedbacks);
        }
        free(dst->candidates);
    }
    memset(dst, 0, sizeof(ImeCandidatesRec));
}

ImmResult le_show_preedit_atomic(ImeInputContext ime_input_context, int backup)
{
    iml_session_t *s = NULL;
    LeSessionContextRec *le_session_context = (LeSessionContextRec *) ime_input_context;

    if (le_session_context == NULL || (s =le_session_context->s) == NULL)
        return (IMM_FAIL);

    if (backup) le_session_context->preedit_show = 1;
    if (session_get_pc_aux_name(le_session_context)) {
        le_show_compositeaux_preedit_notify(s, session_get_pc_aux_name(le_session_context));
    } else {
        le_iml_preedit_start(s);
    }
    return (IMM_OK);
}

ImmResult le_show_preedit(ImeInputContext ime_input_context)
{
    le_show_preedit_atomic(ime_input_context, 1);
}

ImmResult le_hide_preedit_atomic(ImeInputContext ime_input_context, int backup)
{
    iml_session_t *s = NULL;
    LeSessionContextRec *le_session_context = (LeSessionContextRec *)ime_input_context;

    if (le_session_context == NULL || (s =le_session_context->s) == NULL)
        return (IMM_FAIL);

    if (backup) le_session_context->preedit_show = 0;

    if (session_get_pc_aux_name(le_session_context))
        le_hide_compositeaux_preedit_notify(s, session_get_pc_aux_name(le_session_context));
    else
        le_iml_preedit_enddraw(s);
    return (IMM_OK);
}

ImmResult le_hide_preedit(ImeInputContext ime_input_context)
{
    return le_hide_preedit_atomic(ime_input_context, 1);
}

ImmResult le_update_preedit_atomic(ImeInputContext  ime_input_context,
                                  ImePreedit        ime_preedit,
                                  int               backup)
{
    int from_len, to_left, ret;
    ImeEncoding encoding;

    LeSessionContextRec *le_session_context = (LeSessionContextRec *)ime_input_context;

    if ((le_session_context == NULL) || (ime_preedit == NULL) || (le_session_context->s == NULL))
        return (IMM_FAIL);

    iml_session_t *s = (le_session_context->s);

    if (backup && (ime_preedit != &le_session_context->preedit_backup)) {
        freeImPreeditInternal(&le_session_context->preedit_backup);
        dupPreedit(&le_session_context->preedit_backup, ime_preedit);
    }

    encoding = le_session_get_current_ime_encoding(s);
    if (encoding == ENCODE_INVALID)
        return (IMM_FAIL);

    if (session_get_pc_aux_name(le_session_context)) {
        le_update_compositeaux_preedit_notify(le_session_context, 
                                              session_get_pc_aux_name(le_session_context), 
                                              ime_preedit);
        return (IMM_OK);
    }

    UTFCHAR tmp_buf[1024] = {0};
    UTFCHAR *tmp_ptr = tmp_buf;

    if (ime_preedit->preedit.text && ime_preedit->preedit.text[0]) {
        from_len = strlen(ime_preedit->preedit.text);
        to_left = 1024;
        memset(tmp_buf, 0, sizeof(UTFCHAR) * 1024);
        ret = Convert_Native_To_UTF16(encoding,
                                      ime_preedit->preedit.text,
                                      from_len,
                                      (char **) &tmp_ptr,
                                      (size_t *) & to_left);
        if (ret == -1)
            return (IMM_FAIL);
    }

    le_iml_preedit_start(s);
    le_iml_preedit_draw(s, tmp_buf, ime_preedit->caret);

    return (IMM_OK);
}

ImmResult le_update_preedit(ImeInputContext ime_input_context,
                            ImePreedit      ime_preedit)
{
    le_update_preedit_atomic(ime_input_context, ime_preedit, 1);
}

ImmResult le_move_preedit_caret(ImeInputContext ime_input_context,
                                int             index)
{
}

ImmResult le_show_candidates_atomic(ImeInputContext ime_input_context, int backup)
{
  LeSessionContextRec *le_session_context =
      (LeSessionContextRec *) ime_input_context;
  iml_session_t *s = NULL;
  LayoutInfo layout;
  int layout_type_vertical = 1;
  int layout_capacity = 10;
  int composite_style = 0;

  if (le_session_context == NULL)
      return (IMM_FAIL);

  s = (iml_session_t *) le_session_context->s;
  if (s == NULL)
      return (IMM_FAIL);

  if (backup) {
      le_session_context->candidates_show = 1;
  }

  if (session_get_pc_aux_name(le_session_context)) {
      le_show_compositeaux_candidates_notify(s, session_get_pc_aux_name(le_session_context));
      return (IMM_OK);
  }

  layout.choice_per_window = layout_capacity;
  if (layout_type_vertical) {
      layout.ncolumns = 1;
      layout.nrows = layout_capacity;
      layout.drawUpDirection = DrawUpVertically;
  } else {
      layout.ncolumns = layout_capacity;
      layout.nrows = 1;
      layout.drawUpDirection = DrawUpHorizontally;
  }

  le_iml_lookup_start(s, &layout);
  return (IMM_OK);
}

ImmResult le_show_candidates(ImeInputContext ime_input_context)
{
    le_show_candidates_atomic(ime_input_context, 1);
}

ImmResult le_hide_candidates_atomic(ImeInputContext ime_input_context, int backup)
{
    LeSessionContextRec *le_session_context = (LeSessionContextRec *) ime_input_context;
    iml_session_t *s = NULL;

    if (le_session_context == NULL)
        return (IMM_FAIL);

    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (IMM_FAIL);

    if (backup) {
        le_session_context->candidates_show = 0;
    }

    if (session_get_pc_aux_name(le_session_context)) {
        le_hide_compositeaux_candidates_notify(s, session_get_pc_aux_name(le_session_context));
        return (IMM_OK);
    }

    le_iml_lookup_enddraw(s);

    return (IMM_OK);
}

ImmResult le_hide_candidates(ImeInputContext ime_input_context)
{
    le_hide_candidates_atomic(ime_input_context, 1);
}

ImmResult le_update_candidates_atomic(ImeInputContext ime_input_context,
                                      ImeCandidates ime_candidates, int backup)
{
    UTFCHAR **lookup_strs;
    UTFCHAR **label_strs;

    int from_len, to_left, ret, i, num_candidates;
    ImeEncoding encoding;

    LeSessionContextRec *le_session_context = (LeSessionContextRec *)ime_input_context;

    if ((le_session_context == NULL) || ((le_session_context->s) == NULL) || (ime_candidates == NULL))
        return (IMM_FAIL);

    iml_session_t *s = le_session_context->s;

    if (backup && (ime_candidates != &le_session_context->candidates_backup)) {
        freeImCandidatesInternal(&le_session_context->candidates_backup);
        dupCandidates(&le_session_context->candidates_backup, ime_candidates);
    }

    num_candidates = ime_candidates->count;

    encoding = le_session_get_current_ime_encoding(s);
    if (encoding == ENCODE_INVALID)
        return (IMM_FAIL);

    if (session_get_pc_aux_name(le_session_context)) {
        le_update_compositeaux_candidates_notify(le_session_context, 
                                                 session_get_pc_aux_name(le_session_context), 
                                                 ime_candidates);
        return (IMM_OK);
    }

    lookup_strs = (UTFCHAR **) calloc(num_candidates, sizeof(UTFCHAR *));
    if (lookup_strs == NULL)
        return (IMM_FAIL);

    label_strs = (UTFCHAR **) calloc(num_candidates, sizeof(UTFCHAR *));
    if (label_strs == NULL)
        return (IMM_FAIL);

    UTFCHAR tmp_buf[1024], label_buf[64];
    UTFCHAR *tmp_ptr = tmp_buf;

    if (ime_candidates->numbers) {
        from_len = strlen(ime_candidates->numbers);
        to_left = 64 * sizeof(UTFCHAR);
        memset(tmp_buf, 0, to_left);
        tmp_ptr = label_buf;
        ret = Convert_Native_To_UTF16(encoding, ime_candidates->numbers,
                                      from_len, (char **) &tmp_ptr,
                                      (size_t *) & to_left);
    }

    for (i = 0; i < num_candidates; i++) {
        if (ime_candidates->candidates[i].text == NULL)
            continue;

        from_len = strlen(ime_candidates->candidates[i].text);
        to_left = 1024;
        memset(tmp_buf, 0, sizeof(UTFCHAR) * 1024);
        tmp_ptr = tmp_buf;
        ret = Convert_Native_To_UTF16(encoding,
                                      ime_candidates->candidates[i].text,
                                      from_len,
                                      (char **) &tmp_ptr,
                                      (size_t *) & to_left);
        if (ret == -1) {
            tmp_buf[0] = 0x20;
            tmp_buf[1] = 0;
        }

        lookup_strs[i] =
            (UTFCHAR *) calloc(1024 - to_left + 1, sizeof(UTFCHAR));
        if (lookup_strs[i] == NULL)
            continue;

        UTFCHARCpy(lookup_strs[i], tmp_buf);

        label_strs[i] = (UTFCHAR *) calloc(3, sizeof(UTFCHAR));
        if (label_strs[i] == NULL)
            continue;
        label_strs[i][0] =
            (ime_candidates->numbers) ? (label_buf[i]) : ('1' + i);
        label_strs[i][1] = '.';
        label_strs[i][2] = 0;
    }

    le_iml_lookup_draw(s, num_candidates, lookup_strs, NULL, label_strs,
                       NULL, NULL, NULL, 0,
                       (ime_candidates->horizental) ? 0 : 1);

    for (i = 0; i < num_candidates; i++) {
        if (lookup_strs[i])
            free((char *) lookup_strs[i]);
        if (label_strs[i])
            free((char *) label_strs[i]);
    }
    free((char *) lookup_strs);
    free((char *) label_strs);

    return (IMM_OK);
}

ImmResult le_update_candidates(ImeInputContext ime_input_context,
                               ImeCandidates ime_candidates)
{
    le_update_candidates_atomic(ime_input_context, ime_candidates, 1);
}

#if 0
ImmResult le_update_candidates_layout(ImeInputContext ime_input_context,
                                      ImeCandidatesLayout
                                      ime_candidates_layout)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    iml_session_t *s = NULL;
    LayoutInfo layout;

    if (le_session_context == NULL)
        return (IMM_FAIL);

    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (IMM_FAIL);

    layout.choice_per_window = ime_candidates_layout->capacity;
    if (ime_candidates_layout->direction == ImeCandidatesVertically) {
        layout.ncolumns = 1;
        layout.nrows = ime_candidates_layout->capacity;
        layout.drawUpDirection = DrawUpVertically;
    } else {
        layout.ncolumns = ime_candidates_layout->capacity;
        layout.nrows = 1;
        layout.drawUpDirection = DrawUpHorizontally;
    }

    le_iml_lookup_start(s, &layout);
    return (IMM_OK);
}
#endif

ImmResult le_commit(ImeInputContext ime_input_context,
                    unsigned char *commit_buf)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    iml_session_t *s = NULL;
    UTFCHAR tmp_buf[1024];
    UTFCHAR *tmp_ptr = tmp_buf;
    int from_len, to_left, ret;
    ImeEncoding encoding;

    if (le_session_context == NULL)
        return (IMM_FAIL);
    if (commit_buf == NULL)
        return (IME_FAIL);
#if 0
    if (ime_commit == NULL)
        return (IMM_FAIL);
#endif

    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (IMM_FAIL);

    encoding = le_session_get_current_ime_encoding(s);
    if (encoding == ENCODE_INVALID)
        return (IMM_FAIL);

    from_len = strlen(commit_buf);
    to_left = 1024;
    memset(tmp_buf, 0, sizeof(UTFCHAR) * 1024);
    ret = Convert_Native_To_UTF16(encoding,
                                  commit_buf,
                                  from_len,
                                  (char **) &tmp_ptr,
                                  (size_t *) & to_left);
    if (ret == -1)
        return (IMM_FAIL);

    le_iml_commit(s, tmp_buf);
    return (IMM_OK);
}

ImHandle le_show_aux(ImeInputContext ime_input_context,  const char *aux_name)
{
    iml_session_t *s = NULL;
    int command = COMMONAUX_SHOW_NOTIFY;
    LeSessionContextRec *le_session_context = (LeSessionContextRec *)ime_input_context;

    if (aux_name == NULL || le_session_context == NULL || ((s =le_session_context->s) == NULL))
        return (IMM_FAIL);

    DEBUG_printf("Show aux window %s for session 0x%x\n", aux_name, s);

    le_iml_aux_start(s, aux_name);

    le_iml_aux_draw(s, aux_name, 1, &command, 0, NULL, NULL);

    return (IMM_OK);
}

ImmResult le_hide_aux(ImeInputContext ime_input_context, ImHandle im_handle)
{
    iml_session_t *s = NULL;
    int command = COMMONAUX_HIDE_NOTIFY;
    unsigned char *aux_name = (unsigned char *) im_handle;
    LeSessionContextRec *le_session_context = (LeSessionContextRec *) ime_input_context;

    if (aux_name == NULL || le_session_context == NULL || ((s =le_session_context->s) == NULL))
        return (IMM_FAIL);

    DEBUG_printf("Show aux window %s for session 0x%x\n", aux_name, s);

    le_iml_aux_draw(s, aux_name, 1, &command, 0, NULL, NULL);

    return (IMM_OK);
}

ImmResult le_send_aux_data(ImeEvent event)
{
    return (IMM_OK);
}

void *le_get_ime_data(ImeInputContext ime_input_context, int scope)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;

    if (le_session_context == NULL)
        return (NULL);

    if (scope == IME_SCOPE_SESSION) {
        return (le_session_context->ime_session_data);
    } else if (scope == IME_SCOPE_DESKTOP) {
        return (le_session_context->ime_desktop_data);
    } else if (scope == IME_SCOPE_USER) {
        return (le_session_context->ime_user_data);
    }
#if 0
    iml_session_t *s = NULL;
    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (IMM_FAIL);

    return (le_session_context->ime_user_data);
#endif
}

ImmResult le_set_ime_data(ImeInputContext ime_input_context, int scope,
                          void *pdata)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;

    if (le_session_context == NULL)
        return (IMM_FAIL);

    if (scope == IME_SCOPE_SESSION) {
        le_session_context->ime_session_data = pdata;
    } else if (scope == IME_SCOPE_DESKTOP) {
        le_session_context->ime_desktop_data = pdata;
    } else if (scope == IME_SCOPE_USER) {
        le_session_context->ime_user_data = pdata;
    }
    return (IMM_OK);
}

void *le_load_user_profile(ImeInputContext ic, const char *category,
                           int *psz)
{
    return (NULL);
}

ImmResult le_free_user_profile(void *buf)
{
    return (IMM_OK);
}

ImmResult le_save_user_profile(ImeInputContext ic, const char *category,
                               void *buf, int sz)
{
    return (IMM_OK);
}

ImmResult le_beep(ImeInputContext ime_input_context,
                  ImeBeepType ime_beep_type)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    iml_session_t *s = NULL;

    if (le_session_context == NULL)
        return (IMM_FAIL);

    s = (iml_session_t *) le_session_context->s;
    if (s == NULL)
        return (IMM_FAIL);

    le_beep_paletteaux_notify(s, ime_beep_type);
    return (IMM_OK);
}

ImeKeyType le_map_keyevent(ImeKey ime_key)
{
    int keycode = ime_key->keycode;
    int keychar = ime_key->keychar;
    int modifier = ime_key->modifier;

    DEBUG_printf
        ("le_map_keyevent: keycode: 0x%x, keychar:0x%x, modifier: 0x%x\n",
         keycode, keychar, modifier);

    /* Normal Alphameric key */
    if ((keycode >= IME_VK_COMMA && keycode <= IME_VK_CLOSE_BRACKET) ||
	(keycode >= IME_VK_AMPERSAND && keycode <= IME_VK_UNDERSCORE) ||
        (keycode == IME_VK_QUOTE) || (keycode == IME_VK_BACK_QUOTE)) {
        if (!(modifier & IME_CTRL_MASK) &&
            !(modifier & IME_META_MASK) &&
            !(modifier & IME_ALT_MASK) &&
	    !(modifier & IME_ALT_GRAPH_MASK))
            return (keychar);
    }

    /* Special key */
    if (modifier == 0) {
        switch (keycode) {
        case IME_VK_ESCAPE:
            return (IME_FILTERED_KEY_ESCAPE);
        case IME_VK_ENTER:
            return (IME_FILTERED_KEY_ENTER);
        case IME_VK_SPACE:
            return (IME_FILTERED_KEY_SPACEBAR);
        case IME_VK_PAGE_UP:
            return (IME_FILTERED_KEY_PAGEUP);
        case IME_VK_PAGE_DOWN:
            return (IME_FILTERED_KEY_PAGEDOWN);
        case IME_VK_INSERT:
            return (IME_FILTERED_KEY_INSERT);
        case IME_VK_DELETE:
            return (IME_FILTERED_KEY_DELETE);
        case IME_VK_BACK_SPACE:
            return (IME_FILTERED_KEY_BACKSPACE);
        case IME_VK_HOME:
            return (IME_FILTERED_KEY_HOME);
        case IME_VK_END:
            return (IME_FILTERED_KEY_END);
        case IME_VK_LEFT:
            return (IME_FILTERED_KEY_LEFT);
        case IME_VK_RIGHT:
            return (IME_FILTERED_KEY_RIGHT);
        case IME_VK_UP:
            return (IME_FILTERED_KEY_UP);
        case IME_VK_DOWN:
            return (IME_FILTERED_KEY_DOWN);
        }
    }
    return (IME_FILTERED_KEY_UNUSED);
}

ImePropertyListRec *le_get_ime_properties(ImeInputContext ime_input_context)
{
    LeSessionContextRec *le_session_context =
        (LeSessionContextRec *) ime_input_context;
    ImePropertyListRec *pl;

    if (le_session_context == NULL)
        return (NULL);
    if (le_session_context->s == NULL)
        return (NULL);

    pl = (ImePropertyListRec *)
	le_session_get_current_ime_module_property_list(le_session_context->s);

    return (pl);
}
