// -*- C++ -*- private include file for SKK
#ifndef _skkconv_h_included_
#define _skkconv_h_included_

#include "kkconv.h"
#include "rkconv.h"
#include "gtkdispatch.h"

// SKKStat::convstat
#define STATE_DIRECT 0
#define STATE_KANJI 1
#define STATE_OKURI 2
#define STATE_CONVERTING 3
#define STATE_WAITING 4
#define STATE_LATIN 5

#define SKK_UPDATE_PREEDIT 256
#define SKK_COMMIT_PENDING 512
#define SKK_CREATE_CCONTEXT 1024
#define SKK_CANCEL_CHILD 2048
#define SKK_FORWARD_CHILD 4096

extern atom_t A_skk_share_dic;
extern atom_t A_skk_personal_dic;
extern atom_t A_skk_learn_dic;

extern atom_t A_skk_widelatin_mode;
extern atom_t A_skk_toggle_hirakata;
extern atom_t A_skk_begin_latin_conv;

class SKKDic;
class SKKContext;

class SKKConv : public KKConv{
public:
    virtual ~SKKConv();
    //
    char **getIcon();
    void onPushIcon();
    virtual char *getModeName(int );
    //
    void init();
    RKMap *get_map(int mode);
    SKKDic *get_dic();
    KKContext *createContext(XimIC *ic);
private:
    SKKDic *dic;
    RKMap *hira_map;
    RKMap *kata_map;
};

class SKKDic;

// SKKの変換状態を扱う
struct SKKStat{
public:
    ~SKKStat();
    void init(SKKConv *);
    int proc_key(keyState *k);
    void setMode(int mode);
    void flush();
    void cancel();
    
    jstring_t head,okuri;
    jstring_t *pending;
    cchar okuri_head;
    Candidates *cands;
    int convstat;
    int mode;
    
    RKConv *rkConv;
    SKKConv *conv;
    SKKDic *dic;
private:
    int proc_raw_mode(keyState *k);
    int proc_wide_mode(keyState *k);
    int proc_no_conv(keyState *k);
    int proc_conv(keyState *k);
    
    // called by proc_conv();
    int proc_kanji_state(keyState *k);
    int proc_okuri_state(keyState *k);
    int proc_converting_state(keyState *k);
    int proc_latin_state(keyState *k);
    
    int do_conv();
};

// don't reuse instance of this object
struct SKKChildContext{
    SKKChildContext(SKKConv *,SKKChildContext *parent,SKKStat *s);
    
    int pushKey(keyState *);
    bool extra_input(jstring_t *);
    SKKChildContext *get_parent_context();
    void cancel_child();
    void commit_child(jstring_t *s);
    int get_current_level();
    
    SKKStat stat;
    jstring_t pre,post;
    jstring_t learn;
    
private:
    void init();
    int proc_edit_key(keyState *,int);
    
    SKKChildContext *parent_context;
};

class SKKChildWindow : public WidgetIf{
public:
    SKKChildWindow(SKKConv *,SKKContext *);
    virtual ~SKKChildWindow();
    
    void key_press(GtkWidget *w,GdkEventKey *e);
    void resize(GtkWidget *,int ,int);
    void clicked(GtkWidget *);
    void expose(GtkWidget *);
    void activate(GtkWidget *w,gpointer p);
    
    int pushKey(keyState *);
    void open(SKKStat *);
    void close();
    bool extra_input(jstring_t *s);
private:
    void init_win();
    void add_input_mode(GtkWidget *w,char *l,int m);
    void draw();
    int draw_preedit(int x);
    void draw_text_entry();
    void clear_preedit();
    int draw_cchar(cchar c, int x,int y,int e);
    void update_mode();
    SKKChildContext *get_current_context();
    void set_current_context(SKKChildContext *);
    void commit_to_parent();
    void cancel_current();

    SKKConv *m_skkConv;
    SKKContext *m_skkContext;
    SKKChildContext *m_context;//現在のChildContext
    GtkWidget *m_win;
    GtkWidget *m_text;
    GdkPixmap *m_pix;
    GtkWidget *m_commit_button;
    GtkWidget *m_cancel_button;
    GtkWidget *m_stat_menu;
};

class SKKContext : public KKContext{
public:
    SKKContext(SKKConv *,XimIC *);
    virtual ~SKKContext();
    //
    void OnUpdatePe(pe_stat *);
    int pushKey(keyState *);
    int getMode();
    void setMode(int );
    void commit_child(jstring_t *);
    void cancel_child();
    jstring_t *clear();
    void candidate_selected(int n);
    bool extra_input(jstring_t *s);
private:
    void create_child_context();

    SKKChildWindow *m_child;
    SKKStat mStat;  //SKKの変換状態
};

class SKKDic{
public:
    SKKDic(){};
    virtual ~SKKDic(){};
    virtual Candidates *getCandidates(SKKStat *)=0;
    virtual void commit(SKKStat *,jstring_t *)=0;
protected:
};

SKKDic *createSKKDic();

void initSkk();

#endif
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 */
