/*
  iiimcfint.h
*/
#ifndef _IIIMCFINT_H_
#define _IIIMCFINT_H_
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef HAVE_NO_THREAD
#include <threaddef.h>
#endif
#include <iiimcf.h>
#include <EIMIL.h>

typedef struct IIIMCF_client_env IIIMCF_client_env;
typedef struct IIIMCF_client_conf IIIMCF_client_conf;

typedef struct IIIMCF_handle_rec IIIMCF_handle_rec;
typedef struct IIIMCF_context_rec IIIMCF_context_rec;
typedef struct IIIMCF_version_rec IIIMCF_version_rec;
typedef struct IIIMCF_attr_rec IIIMCF_attr_rec;
typedef struct IIIMCF_text_rec IIIMCF_text_rec;
typedef struct IIIMCF_text_property_value_rec IIIMCF_text_property_value_rec;
typedef struct IIIMCF_lookup_choice_rec IIIMCF_lookup_choice_rec;
typedef struct IIIMCF_language_rec IIIMCF_language_rec;
typedef struct IIIMCF_input_method_rec IIIMCF_input_method_rec;
typedef struct IIIMCF_event_rec IIIMCF_event_rec;
typedef struct IIIMCF_component_rec IIIMCF_component_rec;
typedef struct IIIMCF_downloaded_object_rec IIIMCF_downloaded_object_rec;
typedef struct IIIMCF_aux_rec IIIMCF_aux_rec;

typedef struct IIIMCF_ICAttribute_rec IIIMCF_ICAttribute_rec;

struct IIIMCF_client_conf {
    int         use_tls;                /* whether tls is used or not */
    char *      server_node;            /* server node name or address */
    char *      service;                /* service name or port number or unix path */
    char *      cert_file;              /* certificate  */
    char *      cert_key;               /* certificate key */
    char *      ca_file;                /* trusted CA */
    char *      ca_path;                /* trusted CA's path */
    IIIMCF_client_conf *next;
};

struct IIIMCF_client_env {
    char *	user_name;		/* User name */
    char *	password;		/* password (if exists). */
    char *	home_dir;		/* Home directory */
    char *	node;			/* client node name */

#if 0
    char *	server_node;		/* server node name or address */
    char *	service;		/* service name or port number */
#endif

    char *	type;			/* Application type */
    char *	os_name;		/* Operating system name */
    char *	os_arch;		/* Operating system architecture */
    char *	os_version;		/* Operating system version */
    char *	X_display_name;		/* X display name */
    char *	X_server_vendor;	/* X service vendor */

    IIIMCF_client_conf *pconf;           /* client config */
};

enum IIIMCF_PROTOCOL_VERSION_MASK {
	IIIMCF_VERSION_FLAGS_CATEGORY_MASK = 0x00FF,
	IIIMCF_VERSION_FLAGS_ITEM_MASK = 0xFF00,
	IIIMCF_VERSION_FLAGS_MASK = (IIIMCF_VERSION_FLAGS_CATEGORY_MASK
				     | IIIMCF_VERSION_FLAGS_ITEM_MASK)
};

struct IIIMCF_handle_rec {
    IIIMF_stream *pstream;
    IIIMP_data_s *data_s;
    IIIMCF_client_env *penv;
    int im_id;

    int num_input_methods;
    IIIMCF_input_method_rec **ppinput_methods;

    int num_langs;
    IIIMCF_language_rec **pplangs;

    int context_table_size;
    IIIMCF_context_rec **ppcontext_table;

    int object_descriptor_size;
    IIIMCF_object_descriptor *pobjdesc;

    IIIMCF_downloaded_object_rec *pdownloaded_objs;

    int num_on_keys;
    IIIMCF_keyevent *pon_keys;
    int num_off_keys;
    IIIMCF_keyevent *poff_keys;

    int num_of_hkprofiles;
    int curr_scope;
    int curr_profile_id;
    IIIMCF_hotkey_profile *phk_profile;

    int num_of_ns;
    IIIMCF_ns *pns;

    IIIMCF_component_rec *proot_component;

    int disable_automatic_connection_restoration;

    int server_protocol_version;

    IIIMCF_client_conf *pconf;

#ifndef HAVE_NO_THREAD
    THREAD_SYNC_OBJECT so;
    THREAD_ID_OBJECT thread_owner_id;
    int thread_lock_count;
#endif
};

enum IIIMCF_CONTEXT_STATE_FLAGS {
	IIIMCF_CONTEXT_PREEDIT_ENABLED = (1 << 0),
	IIIMCF_CONTEXT_LOOKUP_CHOICE_ENABLED = (1 << 1),
	IIIMCF_CONTEXT_STATUS_ENABLED = (1 << 2),
	IIIMCF_CONTEXT_COMMITTED_TEXT_ENABLED = (1 << 3),
	IIIMCF_CONTEXT_AUTOMATIC_TRIGGER_NOTIFY = (1 << 4),
	IIIMCF_CONTEXT_CONVERSION_MODE = (1 << 5),
	IIIMCF_CONTEXT_BROADCASTING = (1 << 6)
};

enum IIIMCF_attr_type {
	IIIMCF_ATTR_TYPE_NONE = 0,
	IIIMCF_ATTR_TYPE_STRING,
	IIIMCF_ATTR_TYPE_INTEGER,
	IIIMCF_ATTR_TYPE_POINTER
};

typedef struct {
    int idx;
    enum IIIMCF_attr_type type;
    union {
	int number;
	const char *str;
	void *ptr;
    } v;
} IIIMCF_attr_slot;

struct IIIMCF_attr_rec {
    int nprops;
    IIIMCF_attr_slot *pslots;
};

#define IIIMCF_MAX_FEEDBACK_NUM 8
struct IIIMCF_text_rec {
    int updated;
    int len;
    IIIMP_card16 *pu16;
    EIMIL_value *pv_mtext;

    /* only for buffer. */
    IIIMP_card32 pfeedback_ids[IIIMCF_MAX_FEEDBACK_NUM];
    IIIMP_card32 pfeedbacks[IIIMCF_MAX_FEEDBACK_NUM];
};

#if 0
struct IIIMCF_text_property_value_rec {
};
#endif

struct IIIMCF_lookup_choice_rec {
    int masterp;
    int choices_per_window;
    int rows;
    int cols;
    int direction;
    int label_owner;

    int size;
    int enabled_range_start;
    int enabled_range_end;
    int idx_first;
    int idx_last;
    int idx_current;
    int *pflags;
    IIIMCF_text_rec *plabels;
    IIIMCF_text_rec *pcandidates;
    IIIMCF_text_rec title;
};

struct IIIMCF_language_rec {
    char *lang_id;
    IIIMP_card16 *hrn;
};

struct IIIMCF_input_method_rec {
    int id;
    IIIMP_card16 *imname;
    IIIMP_card16 *domain;
    IIIMP_card16 *hrn;
    int num_langs;
    IIIMCF_language_rec **pplangs;
};

struct IIIMCF_ICAttribute_rec {
    char *lang_id;
    int imname_len;
    IIIMP_card16 *imname;
};

typedef struct {
    IIIMP_card16 *name;
    IIIMP_card32 index;
    int num_intvals;
    IIIMP_card32 *pintvals;
    int num_strvals;
    IIIMP_card16 **pstrs;
} IIIMCF_auxevent;

struct IIIMCF_event_rec {
    IIIMCF_event_type type;
    union {
	int number;
	IIIMCF_keyevent keyevent;
	IIIMCF_auxevent *pauxevent;
    } v;
    int state;
};

struct IIIMCF_component_rec {
    IIIMCF_handle_rec *ph;
    char *name;
    IIIMCF_attr attr;
    IIIMCF_component_interface func;
    IIIMCF_component_rec *pparent;
    IIIMCF_component_rec *pchild;
    IIIMCF_component_rec *pnext;
    IIIMCF_component_rec *pprev;
};

struct IIIMCF_downloaded_object_rec {
    const IIIMCF_object_descriptor *pod;
    IIIMCF_downloaded_object_rec *pnext;
    union {
	IIIMP_card16 *str;
	IIIMP_card8 *pbin;
    } v;
};

struct IIIMCF_aux_rec {
    IIIMP_card16 *name;
    IIIMP_card32 index;

    int mode;

    int num_strvals;
    IIIMP_card16 **pstrs;
    int num_intvals;
    IIIMP_card32 *pintvals;

    IIIMCF_aux_rec *pnext;
};

struct IIIMCF_context_rec {
    IIIMCF_handle_rec *ph;
    int ic_id;

    IIIMCF_context_rec *pnext;

    int state_flag;

    int preedit_caret_position;
    IIIMCF_text_rec preedit_text;
    IIIMCF_lookup_choice_rec lookup_choice;
    IIIMCF_text_rec status_text;
    IIIMCF_text_rec committed_text;

    IIIMCF_aux_rec *paux;

    int state_change_flag;

    /* event queue */
    int evqueue_size;
    IIIMCF_event_rec **ppev_pro;
    IIIMCF_event_rec **ppev_con;
    IIIMCF_event_rec **ppevqueue;

    /* dispatchment state */
    IIIMCF_component_rec *pcurrent_component;

    /* IC attribute */
    IIIMCF_ICAttribute_rec icattr;

    /* user-defined attr */
    IIIMCF_attr attr;

#ifdef IIIMCF_EVENT_STACK
    /* event stack */
    int evstack_size;
    IIIMCF_event_rec **ppevstack;
    IIIMCF_event_rec **ppev_sp;
#endif
};

/* macros */

#define IIIMCF_IS_CONNECTED(ph) (((ph)->im_id) >= 0)
#define IIIMCF_IS_IC_INVALID(pc) (((pc)->ic_id) < 0)
#define IIIMCF_IS_ENABLED(pc, flag) ((pc)->state_flag & (flag))
#define IIIMCF_IS_STATE_CHANGED(pc, flag) ((pc)->state_change_flag & (flag))
#define IIIMCF_SET_STATE(pc, flag) ((pc)->state_flag |= (flag))
#define IIIMCF_SET_STATE_CHANGE(pc, flag) ((pc)->state_change_flag |= (flag))
#define IIIMCF_RESET_STATE(pc, flag) ((pc)->state_flag &= (~(flag)))
#define IIIMCF_RESET_STATE_CHANGE(pc, flag) ((pc)->state_change_flag &= (~(flag)))
#define IIIMCF_IS_BROADCASTING(pc) IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_BROADCASTING)
#define IIIMCF_IS_PREEDIT_IN_PROGRESS(pc) (((pc)->preedit_text.len) > 0 ? 1 : 0)
#define IIIMCF_IS_VALID_TEXT(pt) ((pt)->pv_mtext)
#define IIIMCF_IS_VALID_LOOKUP_CHOICE(pl) (((pl)->size) > 0)

#define IIIMCF_IS_STATIC_EVENT_FLOW(ph) ((ph)->num_on_keys == 0)

#define IIIMCF_IS_KEYEVENT_EQUAL(X, Y) (((X).keycode == (Y).keycode) \
                                        /* && ((X).keychar == (Y).keychar) */ \
                                        && ((X).modifier == (Y).modifier))

#define IIIMCF_LOCK_HANDLE(ph) iiimcf_lock_handle(ph);
#define IIIMCF_UNLOCK_HANDLE(ph) iiimcf_unlock_handle(ph);

/* internal functions */

#ifdef __cplusplus
extern "C" {
#endif

/* iiimcf.c */
extern IIIMP_card16* iiimcf_make_string(
    const IIIMP_card16 *str,
    int len
);
extern int iiimcf_string_length(
    const IIIMP_card16 *str
);
extern IIIMP_card16* iiimcf_duplicate_string(
    const IIIMP_card16 *str
);

extern void iiimcf_lock_handle(
    IIIMCF_handle_rec *ph
);
extern void iiimcf_unlock_handle(
    IIIMCF_handle_rec *ph
);

extern IIIMF_status iiimcf_register_trigger_keys(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_register_hotkeys(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_setimvalues(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_connect(
    IIIMCF_handle_rec *ph
);

extern IIIMF_status iiimcf_send_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes,
    int deletep
);

extern IIIMF_status iiimcf_receive_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message **ppmes
);

extern void iiimcf_unregister_langs(
    int n,
    IIIMCF_language_rec **ppl
);

/* input-method.c */

extern IIIMF_status iiimcf_unregister_input_method_list(
    int n,
    IIIMCF_input_method_rec **ppi
);

extern IIIMF_status iiimcf_register_input_method_list(
    IIIMCF_handle_rec *ph,
    IIIMP_inputmethod_descriptor *piiimp_imlist
);

/* attr.c */
/* NO INTERNAL FUNCTION */

/* commit.c */
extern IIIMF_status iiimcf_commit_string(
    IIIMCF_context_rec *pc,
    IIIMP_message *pstr
);

/* context.c */
extern IIIMCF_context_rec* iiimcf_lookup_context(
    IIIMCF_handle_rec *ph,
    IIIMP_card16 ic_id
);

extern IIIMF_status iiimcf_cleanup_context(
    IIIMCF_handle_rec *ph,
    int destroyp
);

extern IIIMF_status iiimcf_enable_context(
    IIIMCF_context_rec *pc
);

/* event.c */
extern IIIMF_status iiimcf_store_event(
    IIIMCF_context_rec *pc,
    IIIMCF_event_rec *pe
);

extern IIIMCF_event_rec* iiimcf_get_event(
    IIIMCF_context_rec *pc,
    int removep
);

extern IIIMCF_event_rec* iiimcf_make_event(
    IIIMCF_event_type type
);

extern IIIMF_status iiimcf_store_simple_event(
    IIIMCF_context_rec *pc,
    IIIMCF_event_type type
);

extern IIIMF_status iiimcf_delete_event_storage(
    IIIMCF_context_rec *pc
);

extern IIIMF_status iiimcf_receive_forwarded_event(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_broadcast_event(
    IIIMCF_context_rec *pc,
    IIIMCF_event_rec *pe
);

/* lookup_choice.c */

extern IIIMF_status iiimcf_lookup_choice_start(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_update_lookup_choice(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_process_lookup_choice(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_lookup_choice_done(
    IIIMCF_context_rec *pc
);

extern void iiimcf_destruct_lookup_choice(
    IIIMCF_lookup_choice_rec *pl
);

/* message.c */
extern IIIMF_status iiimcf_process_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_wait_message(
    IIIMCF_handle_rec *ph,
    IIIMCF_context_rec *pc,
    int opcode,
    IIIMP_message **ppmes
);

extern IIIMF_status iiimcf_request_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message *pmes,
    IIIMCF_context_rec *pc,
    int opcode,
    IIIMP_message **ppmes
);

/* preedit.c */
extern IIIMF_status iiimcf_toggle_preedit(
    IIIMCF_context_rec *pc,
    int flag
);

extern IIIMF_status iiimcf_update_preedit(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

/* status.c */
extern IIIMF_status iiimcf_toggle_status(
    IIIMCF_context_rec *pc,
    int flag
);

extern IIIMF_status iiimcf_update_status(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

/* trigger.c */
extern IIIMF_status iiimcf_receive_trigger_notify(
    IIIMCF_context_rec *pc,
    int flag
);

extern IIIMF_status iiimcf_receive_hotkey_notify(
    IIIMCF_context_rec *pc
);

extern IIIMF_status iiimcf_process_trigger_keyevent(
    IIIMCF_context_rec *pc,
    IIIMCF_keyevent *pkev
);

extern IIIMF_status iiimcf_forward_trigger_notify(
    IIIMCF_context_rec *pc,
    int flag
);

extern IIIMF_status iiimcf_process_hotkey_keyevent(
    IIIMCF_context_rec *pc,
    IIIMCF_keyevent *pkev
);

extern IIIMF_status iiimcf_forward_hotkey_notify(
    IIIMCF_context_rec *pc,
    int hotkey_id,
    int ikev
);

/* aux.c */
extern IIIMF_status iiimcf_enable_aux(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_update_aux_draw(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_disable_aux(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_forward_aux_setvalues(
    IIIMCF_context_rec *pc,
    IIIMCF_event_rec *pe
);

extern IIIMF_status iiimcf_forward_aux_getvalues(
    IIIMCF_context_rec *pc,
    IIIMCF_event_rec *pe
);

extern void iiimcf_delete_all_aux_data(
    IIIMCF_context_rec *pc
);

extern void iiimcf_delete_aux_event(
    IIIMCF_event_rec *pe
);

/* text.c */
extern IIIMF_status iiimcf_destruct_text(
    IIIMCF_text_rec *pt
);

extern IIIMF_status iiimcf_construct_text_from_UTF8(
    const unsigned char *pstr,
    IIIMCF_text_rec *pt
);

extern IIIMF_status iiimcf_convert_iiimp_string_to_text(
    IIIMP_string *pstr,
    IIIMCF_text_rec *pt
);

extern IIIMF_status iiimcf_convert_iiimp_text_to_text(
    IIIMP_text *ptext,
    IIIMCF_text_rec *pt
);

extern IIIMF_status iiimcf_convert_iiimp_contents_to_text(
    IIIMP_contents *pcon,
    IIIMCF_text_rec *pt
);

extern IIIMF_status iiimcf_update_text_by_preedit_draw(
    IIIMCF_text_rec *pbase,
    IIIMP_message *pmes
);

extern IIIMF_status iiimcf_append_contents_to_text(
    IIIMCF_text_rec *pbase,
    IIIMP_contents *pcon
);

/* IIIMPEIMIL.c */
extern EIMIL_value* EIMIL_construct_mtext_from_iiimp_text(
    IIIMP_text *pimt
);

extern EIMIL_value* EIMIL_construct_mtext_from_iiimp_string(
    IIIMP_string *pstr
);

extern EIMIL_value* EIMIL_construct_mtext_from_iiimp_contents(
    IIIMP_contents *pimc
);

extern int EIMIL_update_mtext_by_preedit_draw_message(
    EIMIL_value *pbase,
    IIIMP_message *pmes,
    EIMIL_value **ppv_result
);

/* component.c */
extern IIIMF_status iiimcf_register_predefined_components(
    IIIMCF_handle_rec *ph
);

extern void iiimcf_delete_all_components(
    IIIMCF_handle_rec *ph
);

/* object.c */
extern void iiimcf_delete_all_downloaded_objects(
    IIIMCF_handle_rec *ph
);

/* clientenv.c */
extern IIIMF_status iiimcf_create_client_env(
    IIIMCF_attr attr,
    IIIMCF_client_env **ppenv
);

extern IIIMF_status iiimcf_delete_client_env(
    IIIMCF_client_env *penv
);

extern IIIMF_status iiimcf_create_im_connect_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message **ppmes
);

extern IIIMF_status iiimcf_create_client_descriptor_message(
    IIIMCF_handle_rec *ph,
    IIIMP_message **ppmes
);

#ifdef __cplusplus
}
#endif

#endif /* _IIIMCFINT_H_ */

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