/*

  Copyright (c) 2003,2004 uim Project http://uim.freedesktop.org/

  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
  3. Neither the name of authors nor the names of its contributors
     may be used to endorse or promote products derived from this software
     without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  SUCH DAMAGE.
*/

// -*- C++ -*-
#ifndef _ximserver_h_included_
#define _ximserver_h_included_

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/keysymdef.h>
#include <stdio.h>
#include <list>
#include <vector>
#include <map>
#include <uim/uim.h>
#include <uim/uim-helper.h>


bool pretrans_register();
int connection_setup();
void main_loop();

//変換のサポート
// uString は文字列

// preeditの修飾
#define PE_NORMAL 0
#define PE_REVERSE 1
#define PE_UNDERLINE 2
#define PE_HILIGHT 4

typedef int uchar;
typedef std::list<uchar> uString;
struct pe_ustring{
    uString s;
    int stat;
};

// プリエディットの状態
// 生成と破棄はInputContextのコンストラクタ、デストラクタで行なわれる
class pe_stat {
public:
    pe_stat(class InputContext *);
    void clear();
    void new_segment(int s);
    void push_uchar(uchar );
    int get_char_count();
    int caret_pos;
    std::list<pe_ustring> ustrings; //文節に切られたもの。
    class InputContext *cont;
};

void print_ustring(uString *s);
void erase_ustring(uString *s);
void append_ustring(uString *d,uString *s);
void str_to_ustring(uString *d,char *s);// JIS or EUC

//
void init_converter();

void global_finalize(int );

// ユーザーインターフェースとか、
void init_convdisp();

// misc
int pad4(int );

// debug functions
void hex_dump(unsigned char *buf,int len);


// 動作オプション、主に起動時のコマンドラインオプションで決まる。
// クライアントとのやり取りを追跡する
#define OPT_TRACE 1
// XIMの通信も追跡する
#define OPT_TRACE_XIM 2


// byte order
#define BYTEORDER_UNKNOWN 0
#define LSB_FIRST 1
#define MSB_FIRST 2


// 
extern int host_byte_order;
extern int g_option_mask;
extern int scr_width,scr_height;

#define DO_NOTHING 0
#define COMMIT_RAW 1
#define UPDATE_MODE 2

// もとのイベントから変換を行なって同じ関数内で解放する
class keyState {
public:
    keyState(class keyEventX *);
    int key();
    int modifier();

    bool is_push();//キーを押したのか(離したのではなく)
    void print();
private:
    int mKey;
    int mModifier;
    bool m_bPush;
};

class XimIC;
class Convdisp;
class XimServer;
class InputContext {
public:
    InputContext(XimServer *, XimIC *, char *);
    ~InputContext();
    uim_context getUC();
    int pushKey(keyState *e);
    int getMode();
    void setMode(int mode);
    uString * clear();
    void setConvdisp(Convdisp *);
    void focusIn();
    void focusOut();
    XimIC *get_ic();
    XimServer *getServer();
    bool extra_input(char *s);
    void clear_preedit();
    void pushback_preedit_string(int attr, const char *str);
    void update_preedit();
    void candidate_activate(int nr, int display_limit);
    void candidate_select(int index);
    void candidate_deactivate();
    void update_prop_list(const char *str);
    void update_prop_label(const char *str);
public:
    static void commit_cb(void *, const char *);
    static void clear_cb(void *);
    static void pushback_cb(void *, int attr, const char *str);
    static void update_cb(void *);
    static void candidate_activate_cb(void *ptr, int nr, int index);
    static void candidate_select_cb(void *ptr, int index);
    static void candidate_deactivate_cb(void *ptr);
    static void update_prop_list_cb(void *ptr, const char *str);
    static void update_prop_label_cb(void *ptr, const char *str);
    static InputContext *focusedContext();
    static void deletefocusedContext();
protected:
    void commit_string(char *);
    XimIC *mXic;
    XimServer *mServer;
    pe_stat *m_pe;
    Convdisp *mConvdisp;
    uim_context mUc;
private:
    uim_context createUimContext(char *engine);
    static InputContext *mFocusedContext;    
};

class Locale {
public:
    virtual char *uStringToCtext(uString *us);
    virtual bool supportOverTheSpot();
};

Locale *getLocale(char *lang);

class XimServer {
public:
    XimServer(Locale *lc, char *name, char *lang);
    ~XimServer(){};
    InputContext *createContext(XimIC *);

    bool setupConnection();
    void setupNewConnection(XClientMessageEvent *ev);
    char *uStringToCtext(uString *js);
    void strToUstring(uString *d, const char *s);
    struct input_style *getInputStyles();
public:
    static XimServer *findServer(Window w);
    static Display *gDpy;
    static std::map<Window , XimServer *>gServerMap;
private:
    Locale *mLocale;
    Window mSelectionWin;
    Atom mServerAtom;
    char *mName, *mLang;
};

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