/*
  EIMILint.h
    EIMIL internal declarations.
*/

#ifndef _EIMILINT_H_
#define _EIMILINT_H_
#include <threaddef.h>

#define EIMIL_MAXERRMSG 1024

/********************************************************************************
			type definition.
 ********************************************************************************/

typedef struct EIMIL_attrs EIMIL_attrs;
typedef struct EIMIL_attr_template EIMIL_attr_template;
typedef struct EIMIL_element_template EIMIL_element_template;
typedef struct EIMIL_dictionary EIMIL_dictionary;
typedef struct EIMIL_XMLNS EIMIL_XMLNS;
typedef struct EIMIL_parser_state EIMIL_parser_state;
typedef struct EIMIL_engine_table EIMIL_engine_table;
typedef struct EIMIL_engine EIMIL_engine;
typedef struct EIMIL_cdata EIMIL_cdata;
typedef struct EIMIL_data EIMIL_data;
typedef struct EIMIL_journal EIMIL_journal;

enum EIMIL_TAG_TYPE {
	EIMIL_START_TAG,
	EIMIL_END_TAG,
	EIMIL_EMPTY_TAG,
	EIMIL_PI_TAG,
	EIMIL_DOCTYPE_TAG,
	EIMIL_COMMENT_TAG,
	EIMIL_CDATA_TAG,
	EIMIL_CHARDATA,
	EIMIL_INVALID_TAG
};

typedef int (*EIMIL_parser_function)(
    EIMIL_data*,
    EIMIL_attrs*,
    enum EIMIL_TAG_TYPE type,
    UTF8 *pchars,
    void** pprivate
);

struct EIMIL_attrs {
    UTF8 *name;
    Ebyte *val;
};

enum EIMIL_attr_template_option {
	EIMIL_attr_NORMAL,
	EIMIL_attr_REQUIRED,
	EIMIL_attr_IMPLIED,
	EIMIL_attr_FIXED,
};

struct EIMIL_attr_template {
    char *name;
    enum EIMIL_attr_template_option type;
    char *default_value;
};

enum EIMIL_element_template_option {
	EIMIL_element_single = (1 << 0),
	EIMIL_element_0or1,
	EIMIL_element_multiple,
	EIMIL_element_morethan1,
	EIMIL_element_option_mask = ((1 << 8) - 1),
	EIMIL_subelement_ordered = (1 << 8),
	EIMIL_allow_PCDATA = (1 << 9),
	EIMIL_PCDATA_TOKEN = (1 << 10),
	EIMIL_PCDATA_QUOTED_TOKEN = (1 << 11),
	EIMIL_element_lock_template = (1 << 12),
	EIMIL_element_EMPTY = (1 << 13)
};

struct EIMIL_element_template {
    const char *name;
    EIMIL_parser_function func;
    EIMIL_attr_template *attrtpls;
    const int option;
    EIMIL_element_template *subelems;
    void *private;
};
#define EIMIL_element_contain_pcdatap(pdt) ((pdt)->option | EIMIL_allow_PCDATA)

/*
  element template
 */

/*
  dictionary & parser_state.
 */

struct EIMIL_XMLNS {
    UTF8 *prefix;
    UTF8 *uri;
};

struct EIMIL_parser_state {
    int element_depth;
    unsigned char *buf;
    Ebyte *start;
    Ebyte *end;
    Ebyte *current;
    int lineno;

    int element_idx;
    EIMIL_element_template *pcet;
    EIMIL_element_template *psubet;

    const UTF8 *current_uri;

    int xmlns_alloced;
    int xmlns_entries;
    EIMIL_XMLNS *pxmlns;
};
#define EIMIL_SET_CURRENT_SUBELEMENT_TEMPLATE(pps, pet) \
 ((pps)->psubet = (pet))

enum EIMIL_ENGINE_STATUS {
	EIMIL_ENGINE_STATUS_SUCCESS = 0,
	EIMIL_ENGINE_STATUS_SUSPENDED,
	EIMIL_ENGINE_STATUS_INTERRUPTED,
	EIMIL_ENGINE_STATUS_SKIPPED,
	EIMIL_ENGINE_STATUS_ERROR
};

typedef enum EIMIL_ENGINE_STATUS
(*EIMIL_engine_execute_handler) (
    void *private
);

enum EIMIL_ENGINE_COMMAND {
	EIMIL_ENGINE_INSTANCIATE,
	EIMIL_ENGINE_DUPLICATE,
	EIMIL_ENGINE_DESTRUCT,
	EIMIL_ENGINE_UNINSTANCIATE
};
typedef void*
(*EIMIL_engine_handler) (
    enum EIMIL_ENGINE_COMMAND m,
    EIMIL_data *ped,
    void *class_private,
    void *handle_private
);

struct EIMIL_engine_table {
    UTF8 *classname;
    EIMIL_engine_handler handler;
    EIMIL_engine_execute_handler execute_handler;
    EIMIL_element_template *pet;
    UTF8 *uri;
};

struct EIMIL_engine {
    int idx;
    UTF8* name;
    EIMIL_engine_table *ptable;
    void *private;
};

struct EIMIL_cdata {
    EIMIL_parser_state ps;

    EIMIL_EVENT_PROC evproc;
    EIMIL_UICHANGE_PROC uiproc;
    EIMIL_OPISSUE_PROC opproc;

    int num_engines;
    EIMIL_engine *pengine;
    int id_counter;
    THREAD_SYNC_OBJECT sync_object;
};

#define EIMIL_EVENT_QUEUESIZE 16
struct EIMIL_data {
    EIMIL_cdata *pcommon;
    int duplicated;
    char errstr[EIMIL_MAXERRMSG];

    /* context-dependent dictionary */
    EIMIL_dictionary *pdic;

    /* engine */
    void** pengine_context;

    /* UI */
    EIMIL_symbol *psym_uidata;

    /* commit */
    int commitnotify_numops;
    EIMIL_symbol **commitnotify_ops;

    /* event queue */
    EIMIL_value **pcur_ev;
    EIMIL_value **pqueue_ev;
    EIMIL_value *queueslots[EIMIL_EVENT_QUEUESIZE];

    /* journal */
    EIMIL_TID current_journal_id;
    EIMIL_journal *pjst;

    /* private */
    void *private;
};
#define EIMIL_JOURNAL_ID_MAX ((1 << 28) - 2)
#define EIMIL_JOURNAL_NONRECORD_TID (EIMIL_JOURNAL_ID_MAX + 1)
#define EIMIL_JOURNAL_EMPTY_TID 0

/* constitute ring buffer. */
struct EIMIL_journal {
    EIMIL_TID id;
    EIMIL_symbol *psym;
    EIMIL_value *pv;
    struct EIMIL_journal *next, *prev;
};
#define EIMIL_JOURNAL_EMPTY_SLOT(ej) ((ej).id == 0)

#ifdef __cplusplus
extern "C" {
#endif

extern EIMIL_symbol* EIMIL_intern_soft(
    EIMIL_dictionary *pdic,
    unsigned char *name
);

extern EIMIL_symbol* EIMIL_register_symbol(
    EIMIL_data *ped,
    EIMIL_dictionary *pdic,
    unsigned char *name,
    enum EIMIL_CATEGORY cat,
    enum EIMIL_TYPE type
);

extern EIMIL_symbol* EIMIL_lookup_symbol_internal(
    EIMIL_dictionary *pdic,
    CARD32BIT id
);

extern void EIMIL_destruct_symbol(
    EIMIL_symbol *psym
);

extern Ebyte* EIMIL_get_attr_cdata(
    Ebyte *val,
    UTF8 **result
);

extern Ebyte* EIMIL_get_attr_nmtoken(
    Ebyte *val,
    UTF8 **result
);

extern Ebyte* EIMIL_get_attr_nmtokens(
    Ebyte *val,
    UTF8 **result
);

extern void EIMIL_remove_attr(
    EIMIL_attrs *patr
);

extern int EIMIL_register_engine(
    const UTF8 *classname,
    EIMIL_element_template *pet,
    EIMIL_engine_handler handler,
    EIMIL_engine_execute_handler execute_handler,
    const UTF8 *uri
);

extern EIMIL_data* EIMIL_make_handle_data(
    EIMIL_cdata *pbase
);
extern char* EIMIL_class_to_pathname(
    char *classname
);
extern void EIMIL_destruct_mtext(
    EIMIL_mtext *pm
);
extern int EIMIL_journal_initialize(
    EIMIL_handle eh
);
extern void EIMIL_journal_free(
    EIMIL_handle eh
);
extern void EIMIL_set_error(
    EIMIL_data *pps,
    const char* fmt,
    ...
);
extern void EIMIL_set_outof_memory(
    EIMIL_data *pps
);
extern int EIMIL_parse_start(
    EIMIL_data *ped
);

extern EIMIL_dictionary* EIMIL_new_dictionary(
    int size,
    int id_req_p
);

extern void EIMIL_free_dictionary(
    EIMIL_dictionary *pdic
);
extern void EIMIL_free_dictionary_and_symbol(
    EIMIL_dictionary *pdic
);
extern EIMIL_dictionary* EIMIL_duplicate_dictionary(
    EIMIL_dictionary *psdic
);
extern EIMIL_symbol* EIMIL_register_symbol(
    EIMIL_data *ped,
    EIMIL_dictionary *pdic,
    unsigned char *name,
    enum EIMIL_CATEGORY cat,
    enum EIMIL_TYPE type
);

extern int EIMIL_toggle_preedit(
    EIMIL_data *ped,
    int flag
);

extern int EIMIL_update_preedit(
    EIMIL_data *ped
);

extern int EIMIL_toggle_lookup_choice(
    EIMIL_data *ped,
    int flag
);

extern int EIMIL_update_lookup_choice(
    EIMIL_data *ped
);

extern int EIMIL_reply_event(
    EIMIL_data *ped,
    EIMIL_value *pv_event
);

extern int EIMIL_queue_event(
    EIMIL_data *ped,
    EIMIL_value *pv_event
);

extern EIMIL_value* EIMIL_next_event(
    EIMIL_data *ped
);


extern void EIMIL_set_out_of_memory(
    EIMIL_data *ped
);

/* EIMILFile.c */

extern int EIMILFile_init();

/* PCE.c */

extern int PCE_init();

/* EIMILTextUtil.c */

extern int
EIMIL_mtext_diff(
    EIMIL_mtext *porig,
    EIMIL_mtext *pnew,
    IMDifferential *pdiff
);

#ifdef __cplusplus
}
#endif

#endif /* not _EIMILINT_H_ */

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