#ifndef LE_HH_
#define LE_HH_
#include <vector>
#include <string>
#include <SunIM.h>
#include <config.h>
#include <threaddef.h>
#include "basictype.hh"
#include "IMBasicObject.hh"

class IMInputContext;
class IMDesktop;

class LEContext;
class LEBase
{
    bool error;
    string dirname;
    string filename;
    string lename;
    u16string lename_hrn;
    IMLangList langlist;
    IMDescriptorList imdesclist;
    IMObjectWithDescList imobjectdesclist;

    bool sunim_default;
    if_methods_t *ifm;
    iml_if_t *iml_if;
    iml_if_t *iml_if_context;
    int iml_if_context_ref_count;
    bool need_thread_lock;
    bool need_reload;
    IMSyncObject leif_sync;

    IMSyncObject& get_leif_sync_object()
    { return leif_sync; }

    string get_lename(
	string &filename
    );

    void add_imobjectdesc(
	IMObjectDescriptorStruct *pol
    );
    bool loadif();
    iml_if_t* openif(
	const char* real_locale
    );
    bool closeif();

  public:
    const IMLangList* get_langlist();
    const IMDescriptorList *get_imdesclist();
    const IMObjectWithDescList *get_objectdesclist();
    LEContext* create_lecontext(
	IMInputContext *pic,
	const char* real_locale
    );
    void remove_lecontext(LEContext *lec);
    iml_if_t *get_iml_if()
    { return iml_if; }
    iml_methods_t *get_iml_methods()
    { return iml_if->m; }
    bool errorp() { return error; }
    bool reloadp() { return need_reload; }
    bool need_thread_lock_p() { return need_thread_lock; }

    bool reload();

    bool xsunim_p()
    { return (iml_if->xsunim == True); }

    bool open_iml_desktop(
	IMDesktop *pdesk,
	iml_desktop_t *piml_desk
    );
    bool close_iml_desktop(
	iml_desktop_t *piml_desk
    );

    LEBase(
	string &dirname,
	string &filename
    );

    enum BUILTIN_OPTION {
	    SUNIM_DEFAULT
    };
    LEBase(
	enum BUILTIN_OPTION option
    );
    ~LEBase();

  friend class LEContext;
};

class IMInputContext;
class IMLExec;
class LEContext
{
    // string locale;
    // u16string locale_hrn;
    LEBase *pbase;
    IMInputContext *pic;
    iml_if_t *iml_if;
    iml_session_t *s;
    iml_desktop_t *iml_desktop;
    bool error;

    bool need_thread_lock_p()
    { return pbase->need_thread_lock_p(); }
    IMSyncObject& get_leif_sync_object()
    { return pbase->get_leif_sync_object(); }

    void bind_imlexec(IMLExec *pimlex);
    bool set_values(IMArgList args, int num_args);
    bool realize();

  private:
    // LE context state.
    bool realized;

  public:
    bool errorp()
    { return error; }

    IMInputContext* get_inputcontext()
    { return pic; }

    iml_if_t* get_iml_if()
    { return iml_if; }

    iml_desktop_t* get_iml_desktop()
    { return iml_desktop; }

    LEBase* get_lebase()
    { return pbase; }

    bool send_event(
	IMLExec* pimlex,
	IMInputEvent* pimevent
    );
    bool send_event_getvalues(
	IMLExec* pimlex,
	IMInputEvent* pimevent
    );
    bool send_event_getvalues_finished(
	IMLExec* pimlex
    );
    bool toggle_conversion(
	IMLExec *pimlex,
	bool flag
    );
    bool reset(
	IMLExec *pimlex
    );
    bool toggle_focus(
	IMLExec *pimlex,
	bool flag
    );

    void destroy();
    bool destroy(
	IMLExec *pimlex
    );

    iml_session_t *get_iml_session ()
    { return s; }

  private:
    bool initialize();
    LEContext(
	IMInputContext *pic,
	LEBase *pbase,
	iml_if_t *iif
    );
    ~LEContext();

  friend class LEBase;
};

#endif /* not LE_HH_ */

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
