From 60c84bbf51db184bfe01e35b0948edf6f49b2e76 Mon Sep 17 00:00:00 2001 From: Zankio Date: Sat, 3 Jun 2017 02:52:58 +0800 Subject: [PATCH] Add hime inputcontext plugin for linux version (#3129) Signed-off-by: Zankio (github: zankio) --- Telegram/Patches/qtbase_5_6_2.diff | 22414 ++++++++++++++++++- Telegram/SourceFiles/qt_static_plugins.cpp | 1 + Telegram/gyp/telegram_linux.gypi | 1 + 3 files changed, 22413 insertions(+), 3 deletions(-) diff --git a/Telegram/Patches/qtbase_5_6_2.diff b/Telegram/Patches/qtbase_5_6_2.diff index 236a4dbf2b..a5dfb90176 100644 --- a/Telegram/Patches/qtbase_5_6_2.diff +++ b/Telegram/Patches/qtbase_5_6_2.diff @@ -11252,8 +11252,22416 @@ index 0000000..f0c9202 +#endif + +#endif /* _XKBCOMMON_H_ */ +diff --git a/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.cpp b/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.cpp +new file mode 100644 +index 0000000..0ffc6f4 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.cpp +@@ -0,0 +1,341 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++// confliction of qt & x11 ++typedef unsigned int KeySym; ++struct Display; ++typedef unsigned int Window; ++typedef struct { ++ short x, y; ++} XPoint; ++ ++#include "include/util.h" ++#include "include/im-client/hime-im-client.h" ++#include "hime-imcontext-qt.h" ++ ++static WId focused_win; ++ ++#include ++ ++#if DEBUG ++FILE *out_fp; ++void __hime_dbg_(const char *fmt,...) ++{ ++ va_list args; ++ ++ if (!out_fp) { ++#if 0 ++ out_fp = fopen("/tmp/a.txt", "w"); ++#else ++ out_fp = stdout; ++#endif ++ } ++ ++ va_start(args, fmt); ++ vfprintf(out_fp, fmt, args); ++ fflush(out_fp); ++ va_end(args); ++} ++#endif ++ ++QHimePlatformInputContext::QHimePlatformInputContext() ++{ ++ dbg("QHimePlatformInputContext::QHimePlatformInputContext() \n"); ++ QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); ++ if(!native) ++ return; ++ Display *display = static_cast(native->nativeResourceForWindow("display", NULL)); ++ ++ if (!(hime_ch = hime_im_client_open(display))) { ++ perror("cannot open hime_ch"); ++ dbg("hime_im_client_open error\n"); ++ return; ++ } ++ ++ dbg("QHimePlatformInputContext succ\n"); ++} ++ ++QHimePlatformInputContext::~QHimePlatformInputContext() ++{ ++ if (hime_ch==NULL) ++ return; ++ hime_im_client_close(hime_ch); ++ hime_ch = NULL; ++} ++ ++ ++bool QHimePlatformInputContext::isValid() const ++{ ++ dbg("QHimePlatformInputContext::isValid()\n"); ++ return true; ++} ++ ++void QHimePlatformInputContext::invokeAction(QInputMethod::Action action, int cursorPosition) ++{ ++ dbg("QHimePlatformInputContext::invokeAction(n"); ++ // FIXME nop? remove me ++} ++ ++void QHimePlatformInputContext::commitPreedit() ++{ ++ dbg("QHimePlatformInputContext::commitPreedit\n"); ++ // use this to flush ++ int preedit_cursor_position=0; ++ int sub_comp_len; ++ char *str=NULL; ++ HIME_PREEDIT_ATTR att[HIME_PREEDIT_ATTR_MAX_N]; ++ hime_im_client_get_preedit(hime_ch, &str, att, &preedit_cursor_position, &sub_comp_len); ++ if (str) { ++ if (strlen(str) > 0) { ++ dbg("send enter to flush\n"); ++ send_key_press(0xff0d, 0); // Enter ++ } else { ++ dbg("empty string\n"); ++ } ++ ++ free(str); ++ update_preedit(); ++ } else { ++ dbg("no str\n"); ++ } ++} ++ ++ ++void QHimePlatformInputContext::reset() ++{ ++ dbg("QHimePlatformInputContext::reset()\n"); ++ if (hime_ch) { ++ hime_im_client_reset(hime_ch); ++ update_preedit(); ++ } ++} ++ ++void QHimePlatformInputContext::update(Qt::InputMethodQueries queries ) ++{ ++ dbg("QHimePlatformInputContext::update\n"); ++ QObject *input = qApp->focusObject(); ++ if (!input) ++ return; ++ ++ QInputMethodQueryEvent query(queries); ++ QGuiApplication::sendEvent(input, &query); ++ ++ if (queries & Qt::ImCursorRectangle) { ++ cursorMoved(); ++ } ++} ++ ++// this one is essential ++void QHimePlatformInputContext::commit() ++{ ++ dbg("QHimePlatformInputContext::commit()\n"); ++ commitPreedit(); ++} ++ ++ ++void QHimePlatformInputContext::setFocusObject(QObject* object) ++{ ++ dbg("QHimePlatformInputContext::setFocusObject\n"); ++ QWindow *window = qApp->focusWindow(); ++ if (!window) { ++ dbg("no window, focus out\n"); ++ focused_win = 0; ++ char *rstr = NULL; ++ hime_im_client_focus_out2(hime_ch, &rstr); ++ if (rstr) { ++ send_str(rstr); ++ } else { ++ dbg("no str in preedit\n"); ++ } ++ return; ++ } ++ ++ WId win = window->winId(); ++ ++ if (focused_win && win != focused_win) { ++ if (hime_ch) { ++ hime_im_client_focus_out(hime_ch); ++ } ++ } ++ ++ focused_win = win; ++ ++ if (hime_ch) { ++ hime_im_client_set_window(hime_ch, win); ++ hime_im_client_focus_in(hime_ch); ++ cursorMoved(); ++ } ++} ++ ++static int last_x=-1, last_y=-1; ++ ++void QHimePlatformInputContext::cursorMoved() ++{ ++ dbg(" QHimePlatformInputContext::cursorMoved()\n"); ++ ++ QWindow *inputWindow = qApp->focusWindow(); ++ if (!inputWindow) ++ return; ++ ++ QRect r = qApp->inputMethod()->cursorRectangle().toRect(); ++ if(!r.isValid()) ++ return; ++ ++ // hime server will clear the string if the cursor is moved, make sure the x,y is valid ++ int x = r.left(), y = r.bottom(); ++ if (x > inputWindow->width() || y > inputWindow->height() || x < 0 || y < 0) ++ return; ++ ++ if (hime_ch && (x != last_x || y != last_y)) { ++ last_x = x; last_y = y; ++ dbg("move cursor %d, %d\n", x, y); ++ hime_im_client_set_cursor_location(hime_ch, x, y); ++ } ++} ++ ++ ++ ++void QHimePlatformInputContext::update_preedit() ++{ ++ if (!hime_ch) ++ return; ++ QList attrList; ++// QString preedit_string; ++ int preedit_cursor_position=0; ++ int sub_comp_len; ++ char *str=NULL; ++ HIME_PREEDIT_ATTR att[HIME_PREEDIT_ATTR_MAX_N]; ++ int attN = hime_im_client_get_preedit(hime_ch, &str, att, &preedit_cursor_position, &sub_comp_len); ++ ++ int ret; ++ hime_im_client_set_flags(hime_ch, FLAG_HIME_client_handle_use_preedit, &ret); ++ ++ QObject *input = qApp->focusObject(); ++ ++ if (!input || !str) { ++ free(str); ++ return; ++ } ++ ++ ++#if DEBUG ++ dbg("update_preedit attN:%d '%s'\n", attN, str); ++#endif ++ ++ int i; ++ for(i=0; i < attN; i++) { ++ int ofs0 = att[i].ofs0; ++ int len = att[i].ofs1 - att[i].ofs0; ++ QTextCharFormat format; ++ ++ switch (att[i].flag) { ++ case HIME_PREEDIT_ATTR_FLAG_REVERSE: ++ { ++ QBrush brush; ++ QPalette palette; ++ palette = QGuiApplication::palette(); ++ format.setBackground(QBrush(QColor(palette.color(QPalette::Active, QPalette::Highlight)))); ++ format.setForeground(QBrush(QColor(palette.color(QPalette::Active, QPalette::HighlightedText)))); ++ } ++ break; ++ case HIME_PREEDIT_ATTR_FLAG_UNDERLINE: ++ { ++ format.setUnderlineStyle(QTextCharFormat::DashUnderline); ++ } ++ break; ++ default: ++ ; ++ } ++ ++ attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, ofs0, len, format)); ++ } ++ ++ attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, preedit_cursor_position, 1, 0)); ++ ++ QInputMethodEvent im_event (QString::fromUtf8(str), attrList); ++ send_event (im_event); ++ free(str); ++} ++ ++void QHimePlatformInputContext::send_event(QInputMethodEvent e) { ++ QObject *input = qApp->focusObject(); ++ if (!input) ++ return; ++ QCoreApplication::sendEvent(input, &e); ++} ++ ++void QHimePlatformInputContext::send_str(char *rstr) { ++ dbg("send_str %s\n", rstr); ++ QString inputText = QString::fromUtf8(rstr); ++ free(rstr); ++ QInputMethodEvent commit_event; ++ commit_event.setCommitString (inputText); ++ send_event (commit_event); ++} ++ ++bool QHimePlatformInputContext::send_key_press(quint32 keysym, quint32 state) { ++ dbg("send_key_press\n"); ++ char *rstr = NULL; ++ int result = hime_im_client_forward_key_press(hime_ch, keysym, state, &rstr); ++ ++ if (rstr) { ++ send_str(rstr); ++ } ++ ++ return result; ++} ++ ++bool QHimePlatformInputContext::filterEvent(const QEvent* event) ++{ ++ dbg("QHimePlatformInputContext::filterEvent\n"); ++ if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) { ++ goto ret; ++ } ++ ++ const QKeyEvent* keyEvent; ++ keyEvent = static_cast(event); ++ quint32 keysym ; ++ keysym = keyEvent->nativeVirtualKey(); ++ quint32 state; ++ state = keyEvent->nativeModifiers(); ++ ++ if (!inputMethodAccepted()) { ++ goto ret; ++ } ++ ++ QObject *input; ++ input = qApp->focusObject(); ++ ++ if (!input) { ++ goto ret; ++ } ++ ++ int result; ++ if (event->type() == QEvent::KeyPress) { ++ if (send_key_press(keysym, state)) { ++ update_preedit(); ++ return true; ++ } ++ } else { ++ char *rstr = NULL; ++ result = hime_im_client_forward_key_release(hime_ch, keysym, state, &rstr); ++ if (rstr) { ++ free(rstr); ++ } ++ ++ if (result) { ++ return true; ++ } ++ } ++ ++ret: ++ return QPlatformInputContext::filterEvent(event); ++} +diff --git a/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.h b/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.h +new file mode 100644 +index 0000000..784396f +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime-imcontext-qt.h +@@ -0,0 +1,34 @@ ++#ifndef HIME_QT5_IM_H ++#define HIME_QT5_IM_H ++ ++#include ++ ++class QInputMethodEvent; ++struct HIME_client_handle_S; ++ ++class QHimePlatformInputContext : public QPlatformInputContext ++{ ++ Q_OBJECT ++public: ++ QHimePlatformInputContext(); ++ virtual ~QHimePlatformInputContext(); ++ ++ virtual bool filterEvent(const QEvent* event); ++ virtual bool isValid() const; ++ virtual void invokeAction(QInputMethod::Action , int cursorPosition); ++ virtual void reset(); ++ virtual void commit(); ++ virtual void update(Qt::InputMethodQueries quries ); ++ virtual void setFocusObject(QObject* object); ++ ++private: ++ HIME_client_handle_S *hime_ch; ++ void send_event(QInputMethodEvent e); ++ void update_preedit(); ++ void cursorMoved(); ++ bool send_key_press(quint32 keysym, quint32 state); ++ void commitPreedit(); ++ void send_str(char *s); ++}; ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/hime-qt.cpp b/src/plugins/platforminputcontexts/hime/hime-qt.cpp +new file mode 100644 +index 0000000..c7786a8 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime-qt.cpp +@@ -0,0 +1,24 @@ ++#include ++ ++#include "hime-qt.h" ++#include "include/util.h" ++ ++#define HIMEID "hime" ++ ++ ++QStringList QHimePlatformInputContextPlugin::keys() const ++{ ++ dbg("QStringList QHimePlatformInputContextPlugin::keys()\n"); ++ return QStringList(QStringLiteral(HIMEID)); ++ ++} ++ ++QHimePlatformInputContext *QHimePlatformInputContextPlugin::create(const QString& system, const QStringList& paramList) ++{ ++ Q_UNUSED(paramList); ++ dbg("QHimePlatformInputContextPlugin::create()\n"); ++ ++ if (system.compare(system, QStringLiteral(HIMEID), Qt::CaseInsensitive) == 0) ++ return new QHimePlatformInputContext; ++ return 0; ++} +diff --git a/src/plugins/platforminputcontexts/hime/hime-qt.h b/src/plugins/platforminputcontexts/hime/hime-qt.h +new file mode 100644 +index 0000000..0e98a17 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime-qt.h +@@ -0,0 +1,19 @@ ++#ifndef HIME_QT5_PLUGIN_H ++#define HIME_QT5_PLUGIN_H ++ ++#include ++#include ++ ++#include "hime-imcontext-qt.h" ++ ++ ++class QHimePlatformInputContextPlugin : public QPlatformInputContextPlugin ++{ ++ Q_OBJECT ++public: ++ Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "hime.json") ++ QStringList keys() const; ++ QHimePlatformInputContext *create(const QString& system, const QStringList& paramList); ++}; ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/hime.json b/src/plugins/platforminputcontexts/hime/hime.json +new file mode 100644 +index 0000000..f737430 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime.json +@@ -0,0 +1,3 @@ ++{ ++ "Keys": [ "hime" ] ++} +diff --git a/src/plugins/platforminputcontexts/hime/hime.pro b/src/plugins/platforminputcontexts/hime/hime.pro +new file mode 100644 +index 0000000..cb0e098 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/hime.pro +@@ -0,0 +1,75 @@ ++TARGET = himeplatforminputcontextplugin ++ ++QT += dbus gui-private ++SOURCES += $$PWD/hime-imcontext-qt.cpp \ ++ $$PWD/hime-qt.cpp \ ++ $$PWD/include/gtab.c \ ++ $$PWD/include/pho.c \ ++ $$PWD/include/tsin-parse.c \ ++ $$PWD/include/im-client/hime-im-client.c \ ++ $$PWD/include/im-client/hime-send.c \ ++ $$PWD/include/hime-conf.c \ ++ $$PWD/include/IC.c \ ++ $$PWD/include/util.c \ ++ $$PWD/include/gtab-buf.c \ ++ $$PWD/include/im-srv.c \ ++ $$PWD/include/im-addr.c \ ++ $$PWD/include/hime.c \ ++ $$PWD/include/hime-crypt.c \ ++ $$PWD/include/lang.c \ ++ $$PWD/include/win1.c \ ++ $$PWD/include/tsin.c \ ++ $$PWD/include/win-save-phrase.c \ ++ $$PWD/include/IMdkit/lib/i18nX.c \ ++ $$PWD/include/IMdkit/lib/i18nClbk.c \ ++ $$PWD/include/IMdkit/lib/i18nPtHdr.c \ ++ $$PWD/include/IMdkit/lib/IMConn.c \ ++ $$PWD/include/IMdkit/lib/IMMethod.c \ ++ $$PWD/include/IMdkit/lib/i18nIMProto.c \ ++ $$PWD/include/IMdkit/lib/FrameMgr.c \ ++ $$PWD/include/IMdkit/lib/i18nIc.c \ ++ $$PWD/include/IMdkit/lib/i18nUtil.c \ ++ $$PWD/include/IMdkit/lib/i18nMethod.c \ ++ $$PWD/include/IMdkit/lib/i18nAttr.c ++ ++ ++HEADERS += $$PWD/hime-imcontext-qt.h \ ++ $$PWD/hime-qt.h \ ++ $$PWD/include/os-dep.h \ ++ $$PWD/include/pho-status.h \ ++ $$PWD/include/hime-gtk-compatible.h \ ++ $$PWD/include/pho.h \ ++ $$PWD/include/util.h \ ++ $$PWD/include/im-client/hime-im-client.h \ ++ $$PWD/include/im-client/hime-protocol.h \ ++ $$PWD/include/im-client/hime-im-client-attr.h \ ++ $$PWD/include/tsin-parse.h \ ++ $$PWD/include/im-srv.h \ ++ $$PWD/include/IC.h \ ++ $$PWD/include/gtab.h \ ++ $$PWD/include/hime-endian.h \ ++ $$PWD/include/hime-conf.h \ ++ $$PWD/include/lang.h \ ++ $$PWD/include/hime.h \ ++ $$PWD/include/win-save-phrase.h \ ++ $$PWD/include/config.h \ ++ $$PWD/include/gst.h \ ++ $$PWD/include/gtab-buf.h \ ++ $$PWD/include/IMdkit/lib/Xi18nX.h \ ++ $$PWD/include/IMdkit/lib/XimFunc.h \ ++ $$PWD/include/IMdkit/lib/FrameMgr.h \ ++ $$PWD/include/IMdkit/include/IMdkit.h \ ++ $$PWD/include/IMdkit/include/Xi18n.h \ ++ $$PWD/include/IMdkit/include/XimProto.h \ ++ $$PWD/include/tsin.h \ ++ $$PWD/include/win1.h ++ ++OTHER_FILES += $$PWD/hime.json ++ ++DEFINES += HIME_VERSION=\"\\\"0.9.10\\\"\" USE_XIM HIME_TABLE_DIR=\"\\\"/usr/local/share/hime/table\\\"\" HIME_BIN_DIR=\"\\\"/usr/local/bin\\\"\" ++CONFIG += link_pkgconfig ++PKGCONFIG += glib-2.0 gtk+-2.0 ++PLUGIN_TYPE = platforminputcontexts ++PLUGIN_EXTENDS = - ++PLUGIN_CLASS_NAME = QHimePlatformInputContextPlugin ++load(qt_plugin) +diff --git a/src/plugins/platforminputcontexts/hime/include/IC.c b/src/plugins/platforminputcontexts/hime/include/IC.c +new file mode 100644 +index 0000000..eee4d3c +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IC.c +@@ -0,0 +1,467 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++******************************************************************/ ++#include "hime.h" ++ ++#undef DEBUG ++ ++static IC *ic_list = (IC *)NULL; ++static IC *free_list = (IC *)NULL; ++ ++void move_IC_in_win(ClientState *cs); ++ ++static void free_IC_list(IC *list) ++{ ++ while (list) { ++ IC *next = list->next; ++ free(list); ++ list = next; ++ } ++} ++ ++void free_all_IC() ++{ ++ free_IC_list(ic_list); ++ free_IC_list(free_list); ++} ++ ++ ++static IC ++*NewIC() ++{ ++ static CARD16 icid = 0; ++ IC *rec; ++ ++ if (free_list != NULL) { ++ rec = free_list; ++ free_list = free_list->next; ++ } else { ++ rec = (IC *)malloc(sizeof(IC)); ++ } ++ ++ bzero(rec, sizeof(IC)); ++ rec->cs.input_style = InputStyleOverSpot; ++ rec->id = ++icid; ++ ++ rec->next = ic_list; ++ ic_list = rec; ++ return rec; ++} ++ ++IC *FindIC(CARD16 icid) ++{ ++ IC *rec = ic_list; ++ ++ while (rec != NULL) { ++ if (rec->id == icid) ++ return rec; ++ rec = rec->next; ++ } ++ ++ return NULL; ++} ++ ++void hide_in_win(ClientState *ic); ++ ++void DeleteIC(CARD16 icid) ++{ ++ IC *rec, *last; ++ ++ last = NULL; ++ for (rec = ic_list; rec != NULL; last = rec, rec = rec->next) { ++ if (rec->id == icid) { ++ ++ if (&rec->cs == current_CS) { ++ hide_in_win(&rec->cs); ++ } ++ ++ if (last != NULL) ++ last->next = rec->next; ++ else ++ ic_list = rec->next; ++ ++ rec->next = free_list; ++ free_list = rec; ++ return; ++ } ++ } ++ return; ++} ++ ++static int Is(char *attr, XICAttribute *attr_list) { ++ return !strcmp(attr, attr_list->name); ++} ++ ++extern Window root; ++extern Display *dpy; ++ ++ ++void move_in_win(ClientState *cs, int x, int y); ++void show_in_win(ClientState *cs); ++extern Window focus_win; ++void save_CS_temp_to_current(); ++ ++void load_IC(IC *rec) ++{ ++ ClientState *cs = &rec->cs; ++ Window win = cs->client_win; ++ ++ if (win == focus_win && !current_CS) { ++ current_CS = cs; ++ save_CS_temp_to_current(); ++ } ++ ++ if (win == focus_win) { ++ if (cs->im_state == HIME_STATE_DISABLED) ++ hide_in_win(cs); ++ else ++ if (cs->im_state != HIME_STATE_DISABLED) ++ show_in_win(cs); ++ } ++ ++ if (cs->input_style & InputStyleOnSpot) { ++ if (cs->im_state != HIME_STATE_DISABLED) ++ move_IC_in_win(cs); ++ } else ++ if (cs->input_style & InputStyleOverSpot) { ++ if (cs->im_state != HIME_STATE_DISABLED) ++ move_IC_in_win(cs); ++ } else ++ if (cs->input_style & InputStyleRoot) { ++ move_IC_in_win(cs); ++ } ++} ++ ++ ++static void ++StoreIC(IC *rec, IMChangeICStruct *call_data) ++{ ++ ClientState *cs = &rec->cs; ++ XICAttribute *ic_attr = call_data->ic_attr; ++ XICAttribute *pre_attr = call_data->preedit_attr; ++ XICAttribute *sts_attr = call_data->status_attr; ++ register int i; ++ ++ if (!current_CS) { ++ current_CS = cs; ++ save_CS_temp_to_current(); ++ } ++#if DEBUG && 0 ++ dbg(".... StoreIC\n"); ++#endif ++ for (i = 0; i < (int)call_data->ic_attr_num; i++, ic_attr++) { ++ if (Is (XNInputStyle, ic_attr)) { ++ INT32 input_style = *(INT32*)ic_attr->value; ++ ++ if (input_style & XIMPreeditCallbacks) { ++ cs->input_style = InputStyleOnSpot; ++ } else ++ if (input_style & XIMPreeditPosition) { ++ cs->input_style = InputStyleOverSpot; ++ } else ++ if (input_style & XIMPreeditNothing) { ++ cs->input_style = InputStyleRoot; ++ } ++ } ++ ++ else if (Is (XNClientWindow, ic_attr)) { ++ rec->cs.client_win = *(Window*)ic_attr->value; ++#if DEBUG ++ dbg("rec->client_win %x\n", cs->client_win); ++#endif ++ } ++ else if (Is (XNFocusWindow, ic_attr)) { ++ rec->focus_win = *(Window*)ic_attr->value; ++ } ++ else ++ fprintf(stderr, "Unknown attr: %s a\n", ic_attr->name); ++ } ++ ++ for (i = 0; i < (int)call_data->preedit_attr_num; i++, pre_attr++) { ++ if (Is (XNArea, pre_attr)) { ++ rec->pre_attr.area = *(XRectangle*)pre_attr->value; ++#if DEBUG ++ dbg("pre_attr->value: %d %d\n", rec->pre_attr.area.x, rec->pre_attr.area.y); ++#endif ++ } ++ else if (Is (XNAreaNeeded, pre_attr)) ++ rec->pre_attr.area_needed = *(XRectangle*)pre_attr->value; ++ ++ else if (Is (XNSpotLocation, pre_attr)) { ++ cs->spot_location = *(XPoint*)pre_attr->value; ++ move_IC_in_win(cs); ++ } ++ else if (Is (XNColormap, pre_attr)) ++ rec->pre_attr.cmap = *(Colormap*)pre_attr->value; ++ ++ else if (Is (XNStdColormap, pre_attr)) ++ rec->pre_attr.cmap = *(Colormap*)pre_attr->value; ++ ++ else if (Is (XNForeground, pre_attr)) ++ rec->pre_attr.foreground = *(CARD32*)pre_attr->value; ++ ++ else if (Is (XNBackground, pre_attr)) ++ rec->pre_attr.background = *(CARD32*)pre_attr->value; ++ ++ else if (Is (XNBackgroundPixmap, pre_attr)) ++ rec->pre_attr.bg_pixmap = *(Pixmap*)pre_attr->value; ++ ++ else if (Is (XNFontSet, pre_attr)) { ++ int str_length = strlen((char *)pre_attr->value); ++ ++ if (rec->pre_attr.base_font != NULL) { ++ if (Is (rec->pre_attr.base_font, pre_attr)) ++ continue; ++ XFree(rec->pre_attr.base_font); ++ } ++ rec->pre_attr.base_font = (char *)malloc(str_length + 1); ++ strcpy(rec->pre_attr.base_font, (char *)pre_attr->value); ++ ++ } else if (Is (XNLineSpace, pre_attr)) ++ rec->pre_attr.line_space = *(CARD32*)pre_attr->value; ++ ++ else if (Is (XNCursor, pre_attr)) ++ rec->pre_attr.cursor = *(Cursor*)pre_attr->value; ++ ++ else ++ fprintf(stderr, "Unknown attr: %s b\n", pre_attr->name); ++ } ++ ++ ++ for (i = 0; i < (int)call_data->status_attr_num; i++, sts_attr++) { ++ if (Is (XNArea, sts_attr)) { ++ rec->sts_attr.area = *(XRectangle*)sts_attr->value; ++ } ++ else if (Is (XNAreaNeeded, sts_attr)) { ++ rec->sts_attr.area_needed = *(XRectangle*)sts_attr->value; ++ } ++ else if (Is (XNColormap, sts_attr)) { ++ rec->sts_attr.cmap = *(Colormap*)sts_attr->value; ++ } ++ else if (Is (XNStdColormap, sts_attr)) { ++ rec->sts_attr.cmap = *(Colormap*)sts_attr->value; ++ } ++ else if (Is (XNForeground, sts_attr)) { ++ rec->sts_attr.foreground = *(CARD32*)sts_attr->value; ++ } ++ else if (Is (XNBackground, sts_attr)) ++ rec->sts_attr.background = *(CARD32*)sts_attr->value; ++ ++ else if (Is (XNBackgroundPixmap, sts_attr)) ++ rec->sts_attr.bg_pixmap = *(Pixmap*)sts_attr->value; ++ ++ else if (Is (XNFontSet, sts_attr)) { ++ int str_length = strlen((char *)sts_attr->value); ++ ++ if (rec->sts_attr.base_font != NULL) { ++ if (Is (rec->sts_attr.base_font, sts_attr)) ++ continue; ++ XFree(rec->sts_attr.base_font); ++ } ++ rec->sts_attr.base_font = (char *)malloc(str_length + 1); ++ strcpy(rec->sts_attr.base_font, (char *)sts_attr->value); ++ } else if (Is (XNLineSpace, sts_attr)) { ++ rec->sts_attr.line_space= *(CARD32*)sts_attr->value; ++ } ++ else if (Is (XNCursor, sts_attr)) ++ rec->sts_attr.cursor = *(Cursor*)sts_attr->value; ++ ++ else ++ fprintf(stderr, "Unknown attr: %s c\n", ic_attr->name); ++ } ++ ++ load_IC(rec); ++#if DEBUG && 0 ++ dbg("exit StoreIC\n"); ++#endif ++} ++ ++void CreateIC(IMChangeICStruct *call_data) ++{ ++ IC *rec; ++ ++ rec = NewIC(); ++ if (rec == NULL) ++ return; ++ ++ StoreIC(rec, call_data); ++ call_data->icid = rec->id; ++ load_IC(rec); ++#if DEBUG && 0 ++ dbg("CreateIC .. exit\n"); ++#endif ++ return; ++} ++ ++#if 0 ++void ++DestroyIC(call_data) ++IMChangeICStruct *call_data; ++{ ++ DeleteIC(call_data->icid); ++ return; ++} ++#endif ++ ++void SetIC(IMChangeICStruct * call_data) ++{ ++ IC *rec = FindIC(call_data->icid); ++ ++ if (rec == NULL) ++ return; ++ ++ load_IC(rec); ++ ++ StoreIC(rec, call_data); ++#if DEBUG ++ dbg(".... exit SetIC\n"); ++#endif ++ return; ++} ++ ++void GetIC(IMChangeICStruct *call_data) ++{ ++ XICAttribute *ic_attr = call_data->ic_attr; ++ XICAttribute *pre_attr = call_data->preedit_attr; ++ XICAttribute *sts_attr = call_data->status_attr; ++ register int i; ++ IC *rec = FindIC(call_data->icid); ++ ++ if (rec == NULL) ++ return; ++ ++ ClientState *cs = &rec->cs; ++ ++ for (i = 0; i < (int)call_data->ic_attr_num; i++, ic_attr++) { ++ if (Is (XNFilterEvents, ic_attr)) { ++ ic_attr->value = (void *)malloc(sizeof(CARD32)); ++ *(CARD32*)ic_attr->value = KeyPressMask|KeyReleaseMask; ++ ic_attr->value_length = sizeof(CARD32); ++ } ++ } ++ ++ /* preedit attributes */ ++ for (i = 0; i < (int)call_data->preedit_attr_num; i++, pre_attr++) { ++ if (Is (XNArea, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(XRectangle)); ++ *(XRectangle*)pre_attr->value = rec->pre_attr.area; ++ pre_attr->value_length = sizeof(XRectangle); ++#if DEBUG ++ dbg("pre_attr->value: %d %d\n", rec->pre_attr.area.x, rec->pre_attr.area.y); ++#endif ++ ++ } else if (Is (XNAreaNeeded, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(XRectangle)); ++ *(XRectangle*)pre_attr->value = rec->pre_attr.area_needed; ++ pre_attr->value_length = sizeof(XRectangle); ++ ++ } else if (Is (XNSpotLocation, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(XPoint)); ++ *(XPoint*)pre_attr->value = cs->spot_location; ++ pre_attr->value_length = sizeof(XPoint); ++#if DEBUG ++ dbg("over spot %d %d\n", cs->spot_location.x, cs->spot_location.y); ++#endif ++ } else if (Is (XNFontSet, pre_attr)) { ++ CARD16 base_len = (CARD16)strlen(rec->pre_attr.base_font); ++ int total_len = sizeof(CARD16) + (CARD16)base_len; ++ char *p; ++ ++ pre_attr->value = (void *)malloc(total_len); ++ p = (char *)pre_attr->value; ++ memmove(p, &base_len, sizeof(CARD16)); ++ p += sizeof(CARD16); ++ strncpy(p, rec->pre_attr.base_font, base_len); ++ pre_attr->value_length = total_len; ++ ++ } else if (Is (XNForeground, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(long)); ++ *(long*)pre_attr->value = rec->pre_attr.foreground; ++ pre_attr->value_length = sizeof(long); ++ ++ } else if (Is (XNBackground, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(long)); ++ *(long*)pre_attr->value = rec->pre_attr.background; ++ pre_attr->value_length = sizeof(long); ++ ++ } else if (Is (XNLineSpace, pre_attr)) { ++ pre_attr->value = (void *)malloc(sizeof(long)); ++#if 0 ++ *(long*)pre_attr->value = rec->pre_attr.line_space; ++#endif ++ *(long*)pre_attr->value = 18; ++ pre_attr->value_length = sizeof(long); ++ } ++ } ++ ++ /* status attributes */ ++ for (i = 0; i < (int)call_data->status_attr_num; i++, sts_attr++) { ++ if (Is (XNArea, sts_attr)) { ++ sts_attr->value = (void *)malloc(sizeof(XRectangle)); ++ *(XRectangle*)sts_attr->value = rec->sts_attr.area; ++ sts_attr->value_length = sizeof(XRectangle); ++ ++ } else if (Is (XNAreaNeeded, sts_attr)) { ++ sts_attr->value = (void *)malloc(sizeof(XRectangle)); ++ *(XRectangle*)sts_attr->value = rec->sts_attr.area_needed; ++ sts_attr->value_length = sizeof(XRectangle); ++ ++ } else if (Is (XNFontSet, sts_attr)) { ++ CARD16 base_len = (CARD16)strlen(rec->sts_attr.base_font); ++ int total_len = sizeof(CARD16) + (CARD16)base_len; ++ char *p; ++ ++ sts_attr->value = (void *)malloc(total_len); ++ p = (char *)sts_attr->value; ++ memmove(p, &base_len, sizeof(CARD16)); ++ p += sizeof(CARD16); ++ strncpy(p, rec->sts_attr.base_font, base_len); ++ sts_attr->value_length = total_len; ++ ++ } else if (Is (XNForeground, sts_attr)) { ++ sts_attr->value = (void *)malloc(sizeof(long)); ++ *(long*)sts_attr->value = rec->sts_attr.foreground; ++ sts_attr->value_length = sizeof(long); ++ ++ } else if (Is (XNBackground, sts_attr)) { ++ sts_attr->value = (void *)malloc(sizeof(long)); ++ *(long*)sts_attr->value = rec->sts_attr.background; ++ sts_attr->value_length = sizeof(long); ++ ++ } else if (Is (XNLineSpace, sts_attr)) { ++ sts_attr->value = (void *)malloc(sizeof(long)); ++#if 0 ++ *(long*)sts_attr->value = rec->sts_attr.line_space; ++#endif ++ *(long*)sts_attr->value = 18; ++ sts_attr->value_length = sizeof(long); ++ } ++ } ++} ++ ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/IC.h b/src/plugins/platforminputcontexts/hime/include/IC.h +new file mode 100644 +index 0000000..d659f36 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IC.h +@@ -0,0 +1,85 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++******************************************************************/ ++typedef struct { ++ XRectangle area; /* area */ ++ XRectangle area_needed; /* area needed */ ++ Colormap cmap; /* colormap */ ++ CARD32 foreground; /* foreground */ ++ CARD32 background; /* background */ ++ Pixmap bg_pixmap; /* background pixmap */ ++ char *base_font; /* base font of fontset */ ++ CARD32 line_space; /* line spacing */ ++ Cursor cursor; /* cursor */ ++} PreeditAttributes; ++ ++typedef struct { ++ XRectangle area; /* area */ ++ XRectangle area_needed; /* area needed */ ++ Colormap cmap; /* colormap */ ++ CARD32 foreground; /* foreground */ ++ CARD32 background; /* background */ ++ Pixmap bg_pixmap; /* background pixmap */ ++ char *base_font; /* base font of fontset */ ++ CARD32 line_space; /* line spacing */ ++ Cursor cursor; /* cursor */ ++} StatusAttributes; ++ ++typedef struct { ++ Window client_win; /* client window */ ++ INT32 input_style; /* input style */ ++ HIME_STATE_E im_state; ++ gboolean b_half_full_char; ++ gboolean fixed_pos; ++ gboolean b_hime_protocol; // TRUE : hime FALSE: XIM ++ gboolean b_raise_window; ++ gboolean use_preedit; ++ gboolean tsin_pho_mode; ++ short fixed_x, fixed_y; ++ short in_method; ++ XPoint spot_location; /* spot location, relative to client window */ ++#if USE_XIM ++ gboolean xim_preedit_started; ++#endif ++} ClientState; ++ ++ ++typedef struct _IC { ++#if USE_XIM ++ CARD16 id; /* ic id */ ++#endif ++ Window focus_win; /* focus window */ ++#if USE_XIM ++ char *resource_name; /* resource name */ ++ char *resource_class; /* resource class */ ++ PreeditAttributes pre_attr; /* preedit attributes */ ++ StatusAttributes sts_attr; /* status attributes */ ++#endif ++ ClientState cs; ++ struct _IC *next; ++} IC; +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/include/IMdkit.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/IMdkit.h +new file mode 100644 +index 0000000..6f8d673 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/IMdkit.h +@@ -0,0 +1,144 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef _IMdkit_h ++#define _IMdkit_h ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* IM Attributes Name */ ++#define IMModifiers "modifiers" ++#define IMServerWindow "serverWindow" ++#define IMServerName "serverName" ++#define IMServerTransport "serverTransport" ++#define IMLocale "locale" ++#define IMInputStyles "inputStyles" ++#define IMProtocolHandler "protocolHandler" ++#define IMOnKeysList "onKeysList" ++#define IMOffKeysList "offKeysList" ++#define IMEncodingList "encodingList" ++#define IMFilterEventMask "filterEventMask" ++#define IMProtocolDepend "protocolDepend" ++ ++/* Masks for IM Attributes Name */ ++#define I18N_IMSERVER_WIN 0x0001 /* IMServerWindow */ ++#define I18N_IM_NAME 0x0002 /* IMServerName */ ++#define I18N_IM_LOCALE 0x0004 /* IMLocale */ ++#define I18N_IM_ADDRESS 0x0008 /* IMServerTransport */ ++#define I18N_INPUT_STYLES 0x0010 /* IMInputStyles */ ++#define I18N_ON_KEYS 0x0020 /* IMOnKeysList */ ++#define I18N_OFF_KEYS 0x0040 /* IMOffKeysList */ ++#define I18N_IM_HANDLER 0x0080 /* IMProtocolHander */ ++#define I18N_ENCODINGS 0x0100 /* IMEncodingList */ ++#define I18N_FILTERMASK 0x0200 /* IMFilterEventMask */ ++#define I18N_PROTO_DEPEND 0x0400 /* IMProtoDepend */ ++ ++typedef struct ++{ ++ char *name; ++ XPointer value; ++} XIMArg; ++ ++typedef struct ++{ ++ CARD32 keysym; ++ CARD32 modifier; ++ CARD32 modifier_mask; ++} XIMTriggerKey; ++ ++typedef struct ++{ ++ unsigned short count_keys; ++ XIMTriggerKey *keylist; ++} XIMTriggerKeys; ++ ++typedef char *XIMEncoding; ++ ++typedef struct ++{ ++ unsigned short count_encodings; ++ XIMEncoding *supported_encodings; ++} XIMEncodings; ++ ++typedef struct _XIMS *XIMS; ++ ++typedef struct ++{ ++ void* (*setup) (Display *, XIMArg *); ++ Status (*openIM) (XIMS); ++ Status (*closeIM) (XIMS); ++ char* (*setIMValues) (XIMS, XIMArg *); ++ char* (*getIMValues) (XIMS, XIMArg *); ++ Status (*forwardEvent) (XIMS, XPointer); ++ Status (*commitString) (XIMS, XPointer); ++ int (*callCallback) (XIMS, XPointer); ++ int (*preeditStart) (XIMS, XPointer); ++ int (*preeditEnd) (XIMS, XPointer); ++ int (*syncXlib) (XIMS, XPointer); ++} IMMethodsRec, *IMMethods; ++ ++typedef struct ++{ ++ Display *display; ++ int screen; ++} IMCoreRec, *IMCore; ++ ++typedef struct _XIMS ++{ ++ IMMethods methods; ++ IMCoreRec core; ++ Bool sync; ++ void *protocol; ++} XIMProtocolRec; ++ ++/* ++ * X function declarations. ++ */ ++extern XIMS IMOpenIM (Display *, ...); ++extern Status IMCloseIM (XIMS); ++extern char *IMSetIMValues (XIMS, ...); ++extern char *IMGetIMValues (XIMS, ...); ++void IMForwardEvent (XIMS, XPointer); ++void IMCommitString (XIMS, XPointer); ++int IMCallCallback (XIMS, XPointer); ++int IMPreeditStart (XIMS, XPointer); ++int IMPreeditEnd (XIMS, XPointer); ++int IMSyncXlib (XIMS, XPointer); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* IMdkit_h */ +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/include/Xi18n.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/Xi18n.h +new file mode 100644 +index 0000000..aaf7768 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/Xi18n.h +@@ -0,0 +1,505 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef _Xi18n_h ++#define _Xi18n_h ++#include ++#include ++#include ++#include "XimProto.h" ++ ++/* ++ * Minor Protocol Number for Extension Protocol ++ */ ++#define XIM_EXTENSION 128 ++#define XIM_EXT_SET_EVENT_MASK (0x30) ++#define XIM_EXT_FORWARD_KEYEVENT (0x32) ++#define XIM_EXT_MOVE (0x33) ++#define COMMON_EXTENSIONS_NUM 3 ++ ++#include ++#include "IMdkit.h" ++ ++/* XI18N Valid Attribute Name Definition */ ++#define ExtForwardKeyEvent "extForwardKeyEvent" ++#define ExtMove "extMove" ++#define ExtSetEventMask "extSetEventMask" ++ ++/* ++ * Padding macro ++ */ ++#define IMPAD(length) ((4 - ((length)%4))%4) ++ ++/* ++ * Target Atom for Transport Connection ++ */ ++#define LOCALES "LOCALES" ++#define TRANSPORT "TRANSPORT" ++ ++#define I18N_OPEN 0 ++#define I18N_SET 1 ++#define I18N_GET 2 ++ ++typedef struct ++{ ++ char *transportname; ++ int namelen; ++ Bool (*checkAddr) (); ++} TransportSW; ++ ++typedef struct _XIMPending ++{ ++ unsigned char *p; ++ struct _XIMPending *next; ++} XIMPending; ++ ++typedef struct _XimProtoHdr ++{ ++ CARD8 major_opcode; ++ CARD8 minor_opcode; ++ CARD16 length; ++} XimProtoHdr; ++ ++typedef struct ++{ ++ CARD16 attribute_id; ++ CARD16 type; ++ CARD16 length; ++ char *name; ++} XIMAttr; ++ ++typedef struct ++{ ++ CARD16 attribute_id; ++ CARD16 type; ++ CARD16 length; ++ char *name; ++} XICAttr; ++ ++typedef struct ++{ ++ int attribute_id; ++ CARD16 name_length; ++ char *name; ++ int value_length; ++ void *value; ++ int type; ++} XIMAttribute; ++ ++typedef struct ++{ ++ int attribute_id; ++ CARD16 name_length; ++ char *name; ++ int value_length; ++ void *value; ++ int type; ++} XICAttribute; ++ ++typedef struct ++{ ++ int length; ++ char *name; ++} XIMStr; ++ ++typedef struct ++{ ++ CARD16 major_opcode; ++ CARD16 minor_opcode; ++ CARD16 length; ++ char *name; ++} XIMExt; ++ ++typedef struct _Xi18nClient ++{ ++ int connect_id; ++ CARD8 byte_order; ++ /* ++ '?': initial value ++ 'B': for Big-Endian ++ 'l': for little-endian ++ */ ++ int sync; ++ XIMPending *pending; ++ void *trans_rec; /* contains transport specific data */ ++ struct _Xi18nClient *next; ++} Xi18nClient; ++ ++typedef struct _Xi18nCore *Xi18n; ++ ++/* ++ * Callback Struct for XIM Protocol ++ */ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++} IMAnyStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD8 byte_order; ++ CARD16 major_version; ++ CARD16 minor_version; ++} IMConnectStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++} IMDisConnectStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ XIMStr lang; ++} IMOpenStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++} IMCloseStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 number; ++ XIMStr *extension; ++} IMQueryExtensionStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 number; ++ char **im_attr_list; ++} IMGetIMValuesStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD16 preedit_attr_num; ++ CARD16 status_attr_num; ++ CARD16 ic_attr_num; ++ XICAttribute *preedit_attr; ++ XICAttribute *status_attr; ++ XICAttribute *ic_attr; ++} IMChangeICStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++} IMDestroyICStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD16 length; ++ char *commit_string; ++} IMResetICStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++} IMChangeFocusStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ BITMASK16 sync_bit; ++ CARD16 serial_number; ++ XEvent event; ++} IMForwardEventStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD16 flag; ++ KeySym keysym; ++ char *commit_string; ++} IMCommitStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD32 flag; ++ CARD32 key_index; ++ CARD32 event_mask; ++} IMTriggerNotifyStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 encoding_number; ++ XIMStr *encoding; /* name information */ ++ CARD16 encoding_info_number; ++ XIMStr *encodinginfo; /* detailed information */ ++ CARD16 category; /* #0 for name, #1 for detail */ ++ INT16 enc_index; /* index of the encoding determined */ ++} IMEncodingNegotiationStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD32 flag; ++ CARD32 forward_event_mask; ++ CARD32 sync_event_mask; ++} IMSetEventMaskStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD32 filter_event_mask; ++ CARD32 intercept_event_mask; ++ CARD32 select_event_mask; ++ CARD32 forward_event_mask; ++ CARD32 sync_event_mask; ++} IMExtSetEventMaskStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ CARD16 x; ++ CARD16 y; ++} IMMoveStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ BITMASK16 flag; ++ CARD16 error_code; ++ CARD16 str_length; ++ CARD16 error_type; ++ char *error_detail; ++} IMErrorStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++} IMPreeditStateStruct; ++ ++/* Callbacks */ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++} IMGeometryCBStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ union ++ { ++ int return_value; /* PreeditStart */ ++ XIMPreeditDrawCallbackStruct draw; /* PreeditDraw */ ++ XIMPreeditCaretCallbackStruct caret; /* PreeditCaret */ ++ } todo; ++} IMPreeditCBStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ union ++ { ++ XIMStatusDrawCallbackStruct draw; /* StatusDraw */ ++ } todo; ++} IMStatusCBStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++ XIMStringConversionCallbackStruct strconv; ++} IMStrConvCBStruct; ++ ++typedef struct ++{ ++ int major_code; ++ int minor_code; ++ CARD16 connect_id; ++ CARD16 icid; ++} IMSyncXlibStruct; ++ ++typedef union _IMProtocol ++{ ++ int major_code; ++ IMAnyStruct any; ++ IMConnectStruct imconnect; ++ IMDisConnectStruct imdisconnect; ++ IMOpenStruct imopen; ++ IMCloseStruct imclose; ++ IMQueryExtensionStruct queryext; ++ IMGetIMValuesStruct getim; ++ IMEncodingNegotiationStruct encodingnego; ++ IMExtSetEventMaskStruct extsetevent; ++ IMMoveStruct extmove; ++ IMSetEventMaskStruct setevent; ++ IMChangeICStruct changeic; ++ IMDestroyICStruct destroyic; ++ IMResetICStruct resetic; ++ IMChangeFocusStruct changefocus; ++ IMCommitStruct commitstring; ++ IMForwardEventStruct forwardevent; ++ IMTriggerNotifyStruct triggernotify; ++ IMPreeditStateStruct preedit_state; ++ IMErrorStruct imerror; ++ IMGeometryCBStruct geometry_callback; ++ IMPreeditCBStruct preedit_callback; ++ IMStatusCBStruct status_callback; ++ IMStrConvCBStruct strconv_callback; ++ IMSyncXlibStruct sync_xlib; ++ long pad[32]; ++} IMProtocol; ++ ++typedef int (*IMProtoHandler) (XIMS, IMProtocol*); ++ ++#define DEFAULT_FILTER_MASK (KeyPressMask) ++ ++/* Xi18nAddressRec structure */ ++typedef struct _Xi18nAddressRec ++{ ++ Display *dpy; ++ CARD8 im_byteOrder; /* byte order 'B' or 'l' */ ++ /* IM Values */ ++ long imvalue_mask; ++ Window im_window; /* IMServerWindow */ ++ char *im_name; /* IMServerName */ ++ char *im_locale; /* IMLocale */ ++ char *im_addr; /* IMServerTransport */ ++ XIMStyles input_styles; /* IMInputStyles */ ++ XIMTriggerKeys on_keys; /* IMOnKeysList */ ++ XIMTriggerKeys off_keys; /* IMOffKeysList */ ++ XIMEncodings encoding_list; /* IMEncodingList */ ++ IMProtoHandler improto; /* IMProtocolHander */ ++ long filterevent_mask; /* IMFilterEventMask */ ++ /* XIM_SERVERS target Atoms */ ++ Atom selection; ++ Atom Localename; ++ Atom Transportname; ++ /* XIM/XIC Attr */ ++ int im_attr_num; ++ XIMAttr *xim_attr; ++ int ic_attr_num; ++ XICAttr *xic_attr; ++ CARD16 preeditAttr_id; ++ CARD16 statusAttr_id; ++ CARD16 separatorAttr_id; ++ /* XIMExtension List */ ++ int ext_num; ++ XIMExt extension[COMMON_EXTENSIONS_NUM]; ++ /* transport specific connection address */ ++ void *connect_addr; ++ /* actual data is defined: ++ XSpecRec in Xi18nX.h for X-based connection. ++ TransSpecRec in Xi18nTr.h for Socket-based connection. ++ */ ++ /* clients table */ ++ Xi18nClient *clients; ++ Xi18nClient *free_clients; ++} Xi18nAddressRec; ++ ++typedef struct _Xi18nMethodsRec ++{ ++ Bool (*begin) (XIMS); ++ Bool (*end) (XIMS); ++ Bool (*send) (XIMS, CARD16, unsigned char*, long); ++ Bool (*wait) (XIMS, CARD16, CARD8, CARD8); ++ Bool (*disconnect) (XIMS, CARD16); ++} Xi18nMethodsRec; ++ ++typedef struct _Xi18nCore ++{ ++ Xi18nAddressRec address; ++ Xi18nMethodsRec methods; ++} Xi18nCore; ++ ++#endif ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/include/XimProto.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/XimProto.h +new file mode 100644 +index 0000000..e3ed168 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/include/XimProto.h +@@ -0,0 +1,230 @@ ++/* $XConsortium: XimProto.h,v 1.2 94/01/20 18:02:24 rws Exp $ */ ++/****************************************************************** ++ ++ Copyright 1992, 1993, 1994 by FUJITSU LIMITED ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of FUJITSU LIMITED ++not be used in advertising or publicity pertaining to distribution ++of the software without specific, written prior permission. ++FUJITSU LIMITED makes no representations about the suitability of ++this software for any purpose. ++It is provided "as is" without express or implied warranty. ++ ++FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, ++INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO ++EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR ++CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF ++USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR ++OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Takashi Fujiwara FUJITSU LIMITED ++ fujiwara@a80.tech.yk.fujitsu.co.jp ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef _XIMPROTO_H ++#define _XIMPROTO_H ++ ++/* ++ * Default Preconnection selection target ++ */ ++#define XIM_SERVERS "XIM_SERVERS" ++#define XIM_LOCALES "LOCALES" ++#define XIM_TRANSPORT "TRANSPORT" ++ ++/* ++ * categories in XIM_SERVERS ++ */ ++#define XIM_SERVER_CATEGORY "@server=" ++#define XIM_LOCAL_CATEGORY "@locale=" ++#define XIM_TRANSPORT_CATEGORY "@transport=" ++ ++/* ++ * Xim implementation revision ++ */ ++#define PROTOCOLMAJORVERSION 0 ++#define PROTOCOLMINORVERSION 0 ++ ++/* ++ * Major Protocol number ++ */ ++#define XIM_CONNECT 1 ++#define XIM_CONNECT_REPLY 2 ++#define XIM_DISCONNECT 3 ++#define XIM_DISCONNECT_REPLY 4 ++ ++#define XIM_AUTH_REQUIRED 10 ++#define XIM_AUTH_REPLY 11 ++#define XIM_AUTH_NEXT 12 ++#define XIM_AUTH_SETUP 13 ++#define XIM_AUTH_NG 14 ++ ++#define XIM_ERROR 20 ++ ++#define XIM_OPEN 30 ++#define XIM_OPEN_REPLY 31 ++#define XIM_CLOSE 32 ++#define XIM_CLOSE_REPLY 33 ++#define XIM_REGISTER_TRIGGERKEYS 34 ++#define XIM_TRIGGER_NOTIFY 35 ++#define XIM_TRIGGER_NOTIFY_REPLY 36 ++#define XIM_SET_EVENT_MASK 37 ++#define XIM_ENCODING_NEGOTIATION 38 ++#define XIM_ENCODING_NEGOTIATION_REPLY 39 ++#define XIM_QUERY_EXTENSION 40 ++#define XIM_QUERY_EXTENSION_REPLY 41 ++#define XIM_SET_IM_VALUES 42 ++#define XIM_SET_IM_VALUES_REPLY 43 ++#define XIM_GET_IM_VALUES 44 ++#define XIM_GET_IM_VALUES_REPLY 45 ++ ++#define XIM_CREATE_IC 50 ++#define XIM_CREATE_IC_REPLY 51 ++#define XIM_DESTROY_IC 52 ++#define XIM_DESTROY_IC_REPLY 53 ++#define XIM_SET_IC_VALUES 54 ++#define XIM_SET_IC_VALUES_REPLY 55 ++#define XIM_GET_IC_VALUES 56 ++#define XIM_GET_IC_VALUES_REPLY 57 ++#define XIM_SET_IC_FOCUS 58 ++#define XIM_UNSET_IC_FOCUS 59 ++#define XIM_FORWARD_EVENT 60 ++#define XIM_SYNC 61 ++#define XIM_SYNC_REPLY 62 ++#define XIM_COMMIT 63 ++#define XIM_RESET_IC 64 ++#define XIM_RESET_IC_REPLY 65 ++ ++#define XIM_GEOMETRY 70 ++#define XIM_STR_CONVERSION 71 ++#define XIM_STR_CONVERSION_REPLY 72 ++#define XIM_PREEDIT_START 73 ++#define XIM_PREEDIT_START_REPLY 74 ++#define XIM_PREEDIT_DRAW 75 ++#define XIM_PREEDIT_CARET 76 ++#define XIM_PREEDIT_CARET_REPLY 77 ++#define XIM_PREEDIT_DONE 78 ++#define XIM_STATUS_START 79 ++#define XIM_STATUS_DRAW 80 ++#define XIM_STATUS_DONE 81 ++ ++/* ++ * values for the flag of XIM_ERROR ++ */ ++#define XIM_IMID_VALID 0x0001 ++#define XIM_ICID_VALID 0x0002 ++ ++/* ++ * XIM Error Code ++ */ ++#define XIM_BadAlloc 1 ++#define XIM_BadStyle 2 ++#define XIM_BadClientWindow 3 ++#define XIM_BadFocusWindow 4 ++#define XIM_BadArea 5 ++#define XIM_BadSpotLocation 6 ++#define XIM_BadColormap 7 ++#define XIM_BadAtom 8 ++#define XIM_BadPixel 9 ++#define XIM_BadPixmap 10 ++#define XIM_BadName 11 ++#define XIM_BadCursor 12 ++#define XIM_BadProtocol 13 ++#define XIM_BadForeground 14 ++#define XIM_BadBackground 15 ++#define XIM_LocaleNotSupported 16 ++#define XIM_BadSomething 999 ++ ++/* ++ * byte order ++ */ ++#define BIGENDIAN (CARD8) 0x42 /* MSB first */ ++#define LITTLEENDIAN (CARD8) 0x6c /* LSB first */ ++ ++/* ++ * values for the type of XIMATTR & XICATTR ++ */ ++#define XimType_SeparatorOfNestedList 0 ++#define XimType_CARD8 1 ++#define XimType_CARD16 2 ++#define XimType_CARD32 3 ++#define XimType_STRING8 4 ++#define XimType_Window 5 ++#define XimType_XIMStyles 10 ++#define XimType_XRectangle 11 ++#define XimType_XPoint 12 ++#define XimType_XFontSet 13 ++#define XimType_XIMOptions 14 ++#define XimType_XIMHotKeyTriggers 15 ++#define XimType_XIMHotKeyState 16 ++#define XimType_XIMStringConversion 17 ++#define XimType_XIMValuesList 18 ++#define XimType_NEST 0x7FFF ++ ++/* ++ * values for the category of XIM_ENCODING_NEGOTIATON_REPLY ++ */ ++#define XIM_Encoding_NameCategory 0 ++#define XIM_Encoding_DetailCategory 1 ++ ++/* ++ * value for the index of XIM_ENCODING_NEGOTIATON_REPLY ++ */ ++#define XIM_Default_Encoding_IDX -1 ++ ++/* ++ * value for the flag of XIM_FORWARD_EVENT, XIM_COMMIT ++ */ ++#define XimSYNCHRONUS 0x0001 ++#define XimLookupChars 0x0002 ++#define XimLookupKeySym 0x0004 ++#define XimLookupBoth 0x0006 ++ ++/* ++ * request packet header size ++ */ ++#define XIM_HEADER_SIZE \ ++ sizeof(CARD8) /* sizeof mejor-opcode */ \ ++ + sizeof(CARD8) /* sizeof minor-opcode */ \ ++ + sizeof(INT16) /* sizeof length */ ++ ++/* ++ * Client Message data size ++ */ ++#define XIM_CM_DATA_SIZE 20 ++ ++/* ++ * XIM data structure ++ */ ++typedef CARD16 BITMASK16; ++typedef CARD32 BITMASK32; ++typedef CARD32 EVENTMASK; ++ ++typedef CARD16 XIMID; /* Input Method ID */ ++typedef CARD16 XICID; /* Input Context ID */ ++ ++/* ++ * Padding macro ++ */ ++#define XIM_PAD(length) ((4 - ((length) % 4)) % 4) ++ ++#define XIM_SET_PAD(ptr, length) \ ++ { \ ++ register int Counter = XIM_PAD((int)length); \ ++ if (Counter) { \ ++ register char *Ptr = (char *)(ptr) + (length); \ ++ length += Counter; \ ++ for (; Counter; --Counter, ++Ptr) \ ++ *Ptr = '\0'; \ ++ } \ ++ } ++ ++#endif ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.c +new file mode 100644 +index 0000000..9b49794 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.c +@@ -0,0 +1,2466 @@ ++/****************************************************************** ++Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts, ++ ++ All Rights Reserved ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose and without fee is hereby granted, ++provided that the above copyright notice appear in all copies and that ++both that copyright notice and this permission notice appear in ++supporting documentation, and that the names of Digital or MIT not be ++used in advertising or publicity pertaining to distribution of the ++software without specific, written prior permission. ++ ++DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ++ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ++ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ++WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ++ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++SOFTWARE. ++ ++ Author: Hiroyuki Miyamoto Digital Equipment Corporation ++ miyamoto@jrd.dec.com ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#include "FrameMgr.h" ++ ++/* Convenient macro */ ++ ++#define _UNIT(n) ((int)(n) & 0xFF) ++#define _NUMBER(n) (((int)(n) >> 8) & 0xFF) ++ ++/* For byte swapping */ ++ ++#define Swap16(p, n) ((p)->byte_swap ? \ ++(((n) << 8 & 0xFF00) | \ ++ ((n) >> 8 & 0xFF) \ ++) : n) ++#define Swap32(p, n) ((p)->byte_swap ? \ ++ (((n) << 24 & 0xFF000000) | \ ++ ((n) << 8 & 0xFF0000) | \ ++ ((n) >> 8 & 0xFF00) | \ ++ ((n) >> 24 & 0xFF) \ ++ ) : n) ++#define Swap64(p, n) ((p)->byte_swap ? \ ++ (((n) << 56 & 0xFF00000000000000) | \ ++ ((n) << 40 & 0xFF000000000000) | \ ++ ((n) << 24 & 0xFF0000000000) | \ ++ ((n) << 8 & 0xFF00000000) | \ ++ ((n) >> 8 & 0xFF000000) | \ ++ ((n) >> 24 & 0xFF0000) | \ ++ ((n) >> 40 & 0xFF00) | \ ++ ((n) >> 56 & 0xFF) \ ++ ) : n) ++ ++/* Type definition */ ++ ++typedef struct _Iter *Iter; ++ ++typedef struct _FrameInst *FrameInst; ++ ++typedef union ++{ ++ int num; /* For BARRAY */ ++ FrameInst fi; /* For POINTER */ ++ Iter iter; /* For ITER */ ++} ExtraDataRec, *ExtraData; ++ ++typedef struct _Chain ++{ ++ ExtraDataRec d; ++ int frame_no; ++ struct _Chain *next; ++} ChainRec, *Chain; ++ ++typedef struct _ChainMgr ++{ ++ Chain top; ++ Chain tail; ++} ChainMgrRec, *ChainMgr; ++ ++typedef struct _ChainIter ++{ ++ Chain cur; ++} ChainIterRec, *ChainIter; ++ ++typedef struct _FrameIter ++{ ++ Iter iter; ++ Bool counting; ++ unsigned int counter; ++ int end; ++ struct _FrameIter* next; ++} FrameIterRec, *FrameIter; ++ ++typedef struct _FrameInst ++{ ++ XimFrame template; ++ ChainMgrRec cm; ++ int cur_no; ++} FrameInstRec; ++ ++typedef void (*IterStartWatchProc) (Iter it, void *client_data); ++ ++typedef struct _Iter ++{ ++ XimFrame template; ++ int max_count; ++ Bool allow_expansion; ++ ChainMgrRec cm; ++ int cur_no; ++ IterStartWatchProc start_watch_proc; ++ void *client_data; ++ Bool start_counter; ++} IterRec; ++ ++typedef struct _FrameMgr ++{ ++ XimFrame frame; ++ FrameInst fi; ++ char *area; ++ int idx; ++ Bool byte_swap; ++ int total_size; ++ FrameIter iters; ++} FrameMgrRec; ++ ++typedef union ++{ ++ int num; /* For BARRAY and PAD */ ++ struct ++ { /* For COUNTER_* */ ++ Iter iter; ++ Bool is_byte_len; ++ } counter; ++} XimFrameTypeInfoRec, *XimFrameTypeInfo; ++ ++/* Special values */ ++#define NO_VALUE -1 ++#define NO_VALID_FIELD -2 ++ ++static FrameInst FrameInstInit(XimFrame frame); ++static void FrameInstFree(FrameInst fi); ++static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info); ++static XimFrameType FrameInstPeekNextType(FrameInst fi, XimFrameTypeInfo info); ++static FmStatus FrameInstSetSize(FrameInst fi, int num); ++static FmStatus FrameInstSetIterCount(FrameInst fi, int num); ++static int FrameInstGetTotalSize(FrameInst fi); ++static void FrameInstReset(FrameInst fi); ++ ++static Iter IterInit(XimFrame frame, int count); ++static void IterFree(Iter it); ++static int FrameInstGetSize(FrameInst fi); ++static int IterGetSize(Iter it); ++static XimFrameType IterGetNextType(Iter it, XimFrameTypeInfo info); ++static XimFrameType IterPeekNextType(Iter it, XimFrameTypeInfo info); ++static FmStatus IterSetSize(Iter it, int num); ++static FmStatus IterSetIterCount(Iter it, int num); ++static int IterGetTotalSize(Iter it); ++static void IterReset(Iter it); ++static Bool IterIsLoopEnd(Iter it, Bool* myself); ++static void IterSetStartWatch(Iter it, IterStartWatchProc proc, void* client_data); ++static void _IterStartWatch(Iter it, void* client_data); ++ ++static ExtraData ChainMgrGetExtraData(ChainMgr cm, int frame_no); ++static ExtraData ChainMgrSetData(ChainMgr cm, int frame_no, ++ ExtraDataRec data); ++static Bool ChainIterGetNext(ChainIter ci, int* frame_no, ExtraData d); ++static int _FrameInstIncrement(XimFrame frame, int count); ++static int _FrameInstDecrement(XimFrame frame, int count); ++static int _FrameInstGetItemSize(FrameInst fi, int cur_no); ++static Bool FrameInstIsIterLoopEnd(FrameInst fi); ++ ++static FrameIter _FrameMgrAppendIter(FrameMgr fm, Iter it, int end); ++static FrameIter _FrameIterCounterIncr(FrameIter fitr, int i); ++static void _FrameMgrRemoveIter(FrameMgr fm, FrameIter it); ++static Bool _FrameMgrIsIterLoopEnd(FrameMgr fm); ++static Bool _FrameMgrProcessPadding(FrameMgr fm, FmStatus* status); ++ ++#define IterGetIterCount(it) ((it)->allow_expansion ? \ ++NO_VALUE : (it)->max_count) ++ ++#define IterFixIteration(it) ((it)->allow_expansion = False) ++ ++#define IterSetStarter(it) ((it)->start_counter = True) ++ ++#define ChainMgrInit(cm) (cm)->top = (cm)->tail = NULL ++#define ChainMgrFree(cm) \ ++{ \ ++ Chain tmp; \ ++ Chain cur = (cm)->top; \ ++ \ ++ while (cur) \ ++ { \ ++ tmp = cur->next; \ ++ Xfree (cur); \ ++ cur = tmp; \ ++ } \ ++} ++ ++#define ChainIterInit(ci, cm) \ ++{ \ ++ (ci)->cur = (cm)->top; \ ++} ++ ++/* ChainIterFree has nothing to do. */ ++#define ChainIterFree(ci) ++ ++#define FrameInstIsEnd(fi) ((fi)->template[(fi)->cur_no].type == EOL) ++ ++FrameMgr FrameMgrInit (XimFrame frame, char* area, Bool byte_swap) ++{ ++ FrameMgr fm; ++ ++ fm = (FrameMgr) Xmalloc (sizeof (FrameMgrRec)); ++ ++ fm->frame = frame; ++ fm->fi = FrameInstInit (frame); ++ fm->area = (char *) area; ++ fm->idx = 0; ++ fm->byte_swap = byte_swap; ++ fm->total_size = NO_VALUE; ++ fm->iters = NULL; ++ ++ return fm; ++} ++ ++void FrameMgrInitWithData (FrameMgr fm, ++ XimFrame frame, ++ void * area, ++ Bool byte_swap) ++{ ++ fm->frame = frame; ++ fm->fi = FrameInstInit (frame); ++ fm->area = (char *) area; ++ fm->idx = 0; ++ fm->byte_swap = byte_swap; ++ fm->total_size = NO_VALUE; ++} ++ ++void FrameMgrFree (FrameMgr fm) ++{ ++ FrameIter p, cur; ++ ++ p = fm->iters; ++ cur = p; ++ ++ while (p) ++ { ++ p = p->next; ++ Xfree (cur); ++ cur = p; ++ } ++ /*endwhile*/ ++ ++ FrameInstFree (fm->fi); ++ Xfree (fm); ++} ++ ++FmStatus FrameMgrSetBuffer (FrameMgr fm, void* area) ++{ ++ if (fm->area) ++ return FmBufExist; ++ fm->area = (char *) area; ++ return FmSuccess; ++} ++ ++FmStatus _FrameMgrPutToken (FrameMgr fm, void *data, int data_size) ++{ ++ XimFrameType type; ++ XimFrameTypeInfoRec info; ++ ++ if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size) ++ return FmNoMoreData; ++ /*endif*/ ++ ++ type = FrameInstGetNextType(fm->fi, &info); ++ ++ if (type & COUNTER_MASK) ++ { ++ unsigned long input_length; ++ ++ if (info.counter.is_byte_len) ++ { ++ if ((input_length = IterGetTotalSize (info.counter.iter)) ++ == NO_VALUE) ++ { ++ return FmCannotCalc; ++ } ++ /*endif*/ ++ } ++ else ++ { ++ if ((input_length = IterGetIterCount (info.counter.iter)) ++ == NO_VALUE) ++ { ++ return FmCannotCalc; ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ switch (type) ++ { ++ case COUNTER_BIT8: ++ *(CARD8 *) (fm->area + fm->idx) = input_length; ++ fm->idx++; ++ break; ++ ++ case COUNTER_BIT16: ++ *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, input_length); ++ fm->idx += 2; ++ break; ++ ++ case COUNTER_BIT32: ++ *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, input_length); ++ fm->idx += 4; ++ break; ++ ++#if defined(_NEED64BIT) ++ case COUNTER_BIT64: ++ *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, input_length); ++ fm->idx += 8; ++ break; ++#endif ++ default: ++ break; ++ } ++ /*endswitch*/ ++ _FrameMgrPutToken(fm, data, data_size); ++ return FmSuccess; ++ } ++ /*endif*/ ++ ++ switch (type) ++ { ++ case BIT8: ++ if (data_size == sizeof (unsigned char)) ++ { ++ unsigned long num = *(unsigned char *) data; ++ *(CARD8 *) (fm->area + fm->idx) = num; ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ unsigned long num = *(unsigned short *) data; ++ *(CARD8 *) (fm->area + fm->idx) = num; ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ unsigned long num = *(unsigned int *) data; ++ *(CARD8 *) (fm->area + fm->idx) = num; ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ unsigned long num = *(unsigned long *) data; ++ *(CARD8 *) (fm->area + fm->idx) = num; ++ } ++ else ++ { ++ ; /* Should never be reached */ ++ } ++ /*endif*/ ++ fm->idx++; ++ return FmSuccess; ++ ++ case BIT16: ++ if (data_size == sizeof (unsigned char)) ++ { ++ unsigned long num = *(unsigned char *) data; ++ *(CARD16*)(fm->area + fm->idx) = Swap16 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ unsigned long num = *(unsigned short *) data; ++ *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ unsigned long num = *(unsigned int *) data; ++ *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ unsigned long num = *(unsigned long *) data; ++ *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 2; ++ return FmSuccess; ++ ++ case BIT32: ++ if (data_size == sizeof (unsigned char)) ++ { ++ unsigned long num = *(unsigned char *) data; ++ *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ unsigned long num = *(unsigned short *) data; ++ *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ unsigned long num = *(unsigned int *) data; ++ *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ unsigned long num = *(unsigned long *) data; ++ *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 4; ++ return FmSuccess; ++ ++#if defined(_NEED64BIT) ++ case BIT64: ++ if (data_size == sizeof (unsigned char)) ++ { ++ unsigned long num = *(unsigned char *) data; ++ *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ unsigned long num = *(unsigned short *) data; ++ *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ unsigned long num = *(unsigned int *) data; ++ *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ unsigned long num = *(unsigned long *) data; ++ *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 4; ++ return FmSuccess; ++#endif ++ ++ case BARRAY: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ if (info.num > 0) ++ { ++ bcopy (*(char **) data, fm->area + fm->idx, info.num); ++ fm->idx += info.num; ++ } ++ /*endif*/ ++ return FmSuccess; ++ ++ case PADDING: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ fm->idx += info.num; ++ return _FrameMgrPutToken(fm, data, data_size); ++ ++ case ITER: ++ return FmInvalidCall; ++ ++ case EOL: ++ return FmEOD; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return (FmStatus) NULL; /* Should never be reached */ ++} ++ ++FmStatus _FrameMgrGetToken (FrameMgr fm , void* data, int data_size) ++{ ++ XimFrameType type; ++ static XimFrameTypeInfoRec info; /* memory */ ++ FrameIter fitr; ++ ++ if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size) ++ return FmNoMoreData; ++ /*endif*/ ++ ++ type = FrameInstGetNextType(fm->fi, &info); ++ ++ if (type & COUNTER_MASK) ++ { ++ int end=0; ++ FrameIter client_data; ++ ++ type &= ~COUNTER_MASK; ++ switch (type) ++ { ++ case BIT8: ++ end = *(CARD8 *) (fm->area + fm->idx); ++ break; ++ ++ case BIT16: ++ end = Swap16 (fm, *(CARD16 *) (fm->area + fm->idx)); ++ break; ++ ++ case BIT32: ++ end = Swap32 (fm, *(CARD32 *) (fm->area + fm->idx)); ++ break; ++ ++#if defined(_NEED64BIT) ++ case BIT64: ++ end = Swap64 (fm, *(CARD64 *) (fm->area + fm->idx)); ++ break; ++#endif ++ default: ++ break; ++ } ++ /*endswitch*/ ++ ++ if ((client_data = _FrameMgrAppendIter (fm, info.counter.iter, end))) ++ { ++ IterSetStarter (info.counter.iter); ++ IterSetStartWatch (info.counter.iter, ++ _IterStartWatch, ++ (void *) client_data); ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ type &= ~COUNTER_MASK; ++ switch (type) ++ { ++ case BIT8: ++ if (data_size == sizeof (unsigned char)) ++ { ++ *(unsigned char*) data = *(CARD8 *) (fm->area + fm->idx); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ *(unsigned short *) data = *(CARD8 *) (fm->area + fm->idx); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ *(unsigned int *) data = *(CARD8 *) (fm->area + fm->idx); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ *(unsigned long *) data = *(CARD8 *) (fm->area + fm->idx); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx++; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, 1/*BIT8*/))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ return FmSuccess; ++ ++ case BIT16: ++ if (data_size == sizeof (unsigned char)) ++ { ++ *(unsigned char *) data = ++ Swap16 (fm, *(CARD16 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ *(unsigned short *) data = ++ Swap16 (fm, *(CARD16 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ *(unsigned int *) data = ++ Swap16 (fm, *(CARD16 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ *(unsigned long *) data = ++ Swap16 (fm, *(CARD16 *) (fm->area + fm->idx)); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 2; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, 2/*BIT16*/))) ++ _FrameMgrRemoveIter(fm, fitr); ++ /*endif*/ ++ return FmSuccess; ++ ++ case BIT32: ++ if (data_size == sizeof (unsigned char)) ++ { ++ *(unsigned char *) data = ++ Swap32 (fm, *(CARD32 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ *(unsigned short *) data = ++ Swap32 (fm, *(CARD32 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ *(unsigned int *) data = ++ Swap32 (fm, *(CARD32 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ *(unsigned long *) data = ++ Swap32 (fm, *(CARD32 *) (fm->area + fm->idx)); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 4; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, 4/*BIT32*/))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ return FmSuccess; ++ ++#if defined(_NEED64BIT) ++ case BIT64: ++ if (data_size == sizeof (unsigned char)) ++ { ++ *(unsigned char *) data = ++ Swap64 (fm, *(CARD64 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned short)) ++ { ++ *(unsigned short *) data = ++ Swap64 (fm, *(CARD64 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned int)) ++ { ++ *(unsigned int *) data = ++ Swap64 (fm, *(CARD64 *) (fm->area + fm->idx)); ++ } ++ else if (data_size == sizeof (unsigned long)) ++ { ++ *(unsigned long *) data = ++ Swap64 (fm, *(CARD64 *) (fm->area + fm->idx)); ++ } ++ else ++ { ++ ; /* Should never reached */ ++ } ++ /*endif*/ ++ fm->idx += 8; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, 8/*BIT64*/))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ return FmSuccess; ++#endif ++ ++ case BARRAY: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ if (info.num > 0) ++ { ++ *(char **) data = fm->area + fm->idx; ++ ++ fm->idx += info.num; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, info.num))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ } ++ else ++ { ++ *(char **) data = NULL; ++ } ++ /*endif*/ ++ return FmSuccess; ++ ++ case PADDING: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ fm->idx += info.num; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, info.num))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ return _FrameMgrGetToken (fm, data, data_size); ++ ++ case ITER: ++ return FmInvalidCall; /* if comes here, it's a bug! */ ++ ++ case EOL: ++ return FmEOD; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return (FmStatus) NULL; /* Should never be reached */ ++} ++ ++FmStatus FrameMgrSetSize (FrameMgr fm, int barray_size) ++{ ++ if (FrameInstSetSize (fm->fi, barray_size) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ return FmNoMoreData; ++} ++ ++FmStatus FrameMgrSetIterCount (FrameMgr fm, int count) ++{ ++ if (FrameInstSetIterCount (fm->fi, count) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ return FmNoMoreData; ++} ++ ++FmStatus FrameMgrSetTotalSize (FrameMgr fm, int total_size) ++{ ++ fm->total_size = total_size; ++ return FmSuccess; ++} ++ ++int FrameMgrGetTotalSize (FrameMgr fm) ++{ ++ return FrameInstGetTotalSize (fm->fi); ++} ++ ++int FrameMgrGetSize (FrameMgr fm) ++{ ++ register int ret_size; ++ ++ ret_size = FrameInstGetSize (fm->fi); ++ if (ret_size == NO_VALID_FIELD) ++ return NO_VALUE; ++ /*endif*/ ++ return ret_size; ++} ++ ++FmStatus FrameMgrSkipToken (FrameMgr fm, int skip_count) ++{ ++ XimFrameType type; ++ XimFrameTypeInfoRec info; ++ register int i; ++ ++ if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size) ++ return FmNoMoreData; ++ /*endif*/ ++ for (i = 0; i < skip_count; i++) ++ { ++ type = FrameInstGetNextType (fm->fi, &info); ++ type &= ~COUNTER_MASK; ++ ++ switch (type) ++ { ++ case BIT8: ++ fm->idx++; ++ break; ++ ++ case BIT16: ++ fm->idx += 2; ++ break; ++ ++ case BIT32: ++ fm->idx += 4; ++ break; ++ ++ case BIT64: ++ fm->idx += 8; ++ break; ++ ++ case BARRAY: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ fm->idx += info.num; ++ break; ++ ++ case PADDING: ++ if (info.num == NO_VALUE) ++ return FmInvalidCall; ++ /*endif*/ ++ fm->idx += info.num; ++ return FrameMgrSkipToken (fm, skip_count); ++ ++ case ITER: ++ return FmInvalidCall; ++ ++ case EOL: ++ return FmEOD; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ } ++ /*endfor*/ ++ return FmSuccess; ++} ++ ++void FrameMgrReset (FrameMgr fm) ++{ ++ fm->idx = 0; ++ FrameInstReset (fm->fi); ++} ++ ++Bool FrameMgrIsIterLoopEnd (FrameMgr fm, FmStatus* status) ++{ ++ do ++ { ++ if (_FrameMgrIsIterLoopEnd (fm)) ++ return True; ++ /*endif*/ ++ } ++ while (_FrameMgrProcessPadding (fm, status)); ++ ++ return False; ++} ++ ++ ++/* Internal routines */ ++ ++static Bool _FrameMgrIsIterLoopEnd (FrameMgr fm) ++{ ++ return FrameInstIsIterLoopEnd (fm->fi); ++} ++ ++static Bool _FrameMgrProcessPadding (FrameMgr fm, FmStatus* status) ++{ ++ XimFrameTypeInfoRec info; ++ XimFrameType next_type = FrameInstPeekNextType (fm->fi, &info); ++ FrameIter fitr; ++ ++ if (next_type == PADDING) ++ { ++ if (info.num == NO_VALUE) ++ { ++ *status = FmInvalidCall; ++ return True; ++ } ++ /*endif*/ ++ next_type = FrameInstGetNextType (fm->fi, &info); ++ fm->idx += info.num; ++ if ((fitr = _FrameIterCounterIncr (fm->iters, info.num))) ++ _FrameMgrRemoveIter (fm, fitr); ++ /*endif*/ ++ *status = FmSuccess; ++ return True; ++ } ++ /*endif*/ ++ *status = FmSuccess; ++ return False; ++} ++ ++static FrameInst FrameInstInit (XimFrame frame) ++{ ++ FrameInst fi; ++ ++ fi = (FrameInst) Xmalloc (sizeof (FrameInstRec)); ++ ++ fi->template = frame; ++ fi->cur_no = 0; ++ ChainMgrInit (&fi->cm); ++ return fi; ++} ++ ++static void FrameInstFree (FrameInst fi) ++{ ++ ChainIterRec ci; ++ int frame_no; ++ ExtraDataRec d; ++ ++ ChainIterInit (&ci, &fi->cm); ++ ++ while (ChainIterGetNext (&ci, &frame_no, &d)) ++ { ++ register XimFrameType type; ++ type = fi->template[frame_no].type; ++ if (type == ITER) ++ { ++ if (d.iter) ++ IterFree (d.iter); ++ /*endif*/ ++ } ++ else if (type == POINTER) ++ { ++ if (d.fi) ++ FrameInstFree (d.fi); ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ ChainMgrFree (&fi->cm); ++ Xfree (fi); ++} ++ ++static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info) ++{ ++ XimFrameType ret_type; ++ ++ ret_type = fi->template[fi->cur_no].type; ++ ++ switch (ret_type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ case EOL: ++ fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no); ++ break; ++ ++ case COUNTER_BIT8: ++ case COUNTER_BIT16: ++ case COUNTER_BIT32: ++ case COUNTER_BIT64: ++ if (info) ++ { ++ register int offset, iter_idx; ++ ++ info->counter.is_byte_len = ++ (((long) fi->template[fi->cur_no].data & 0xFF)) == FmCounterByte; ++ offset = ((long) fi->template[fi->cur_no].data) >> 8; ++ iter_idx = fi->cur_no + offset; ++ if (fi->template[iter_idx].type == ITER) ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, iter_idx)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[iter_idx + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, iter_idx, dr); ++ } ++ /*endif*/ ++ info->counter.iter = d->iter; ++ } ++ else ++ { ++ /* Should never reach here */ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ break; ++ ++ case BARRAY: ++ if (info) ++ { ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ info->num = NO_VALUE; ++ else ++ info->num = d->num; ++ /*endif*/ ++ } ++ /*endif*/ ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ break; ++ ++ case PADDING: ++ if (info) ++ { ++ register int unit; ++ register int number; ++ register int size; ++ register int i; ++ ++ unit = _UNIT ((long) fi->template[fi->cur_no].data); ++ number = _NUMBER ((long) fi->template[fi->cur_no].data); ++ ++ i = fi->cur_no; ++ size = 0; ++ while (number > 0) ++ { ++ i = _FrameInstDecrement (fi->template, i); ++ size += _FrameInstGetItemSize (fi, i); ++ number--; ++ } ++ /*endwhile*/ ++ info->num = (unit - (size%unit))%unit; ++ } ++ /*endif*/ ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ break; ++ ++ case ITER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ XimFrameType sub_type; ++ ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[fi->cur_no + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, fi->cur_no, dr); ++ } ++ /*endif*/ ++ sub_type = IterGetNextType (d->iter, info); ++ if (sub_type == EOL) ++ { ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ ret_type = FrameInstGetNextType (fi, info); ++ } ++ else ++ { ++ ret_type = sub_type; ++ } ++ /*endif*/ ++ } ++ break; ++ ++ case POINTER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ XimFrameType sub_type; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ { ++ dr.fi = FrameInstInit (fi->template[fi->cur_no + 1].data); ++ d = ChainMgrSetData (&fi->cm, fi->cur_no, dr); ++ } ++ /*endif*/ ++ sub_type = FrameInstGetNextType (d->fi, info); ++ if (sub_type == EOL) ++ { ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ ret_type = FrameInstGetNextType (fi, info); ++ } ++ else ++ { ++ ret_type = sub_type; ++ } ++ /*endif*/ ++ } ++ break; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return ret_type; ++} ++ ++static XimFrameType FrameInstPeekNextType (FrameInst fi, XimFrameTypeInfo info) ++{ ++ XimFrameType ret_type; ++ ++ ret_type = fi->template[fi->cur_no].type; ++ ++ switch (ret_type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ case EOL: ++ break; ++ ++ case COUNTER_BIT8: ++ case COUNTER_BIT16: ++ case COUNTER_BIT32: ++ case COUNTER_BIT64: ++ if (info) ++ { ++ register int offset; ++ register int iter_idx; ++ ++ info->counter.is_byte_len = ++ (((long) fi->template[fi->cur_no].data) & 0xFF) == FmCounterByte; ++ offset = ((long)fi->template[fi->cur_no].data) >> 8; ++ iter_idx = fi->cur_no + offset; ++ if (fi->template[iter_idx].type == ITER) ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, iter_idx)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[iter_idx + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, iter_idx, dr); ++ } ++ /*endif*/ ++ info->counter.iter = d->iter; ++ } ++ else ++ { ++ /* Should not be reached here */ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ break; ++ ++ case BARRAY: ++ if (info) ++ { ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ info->num = NO_VALUE; ++ else ++ info->num = d->num; ++ /*endif*/ ++ } ++ /*endif*/ ++ break; ++ ++ case PADDING: ++ if (info) ++ { ++ register int unit; ++ register int number; ++ register int size; ++ register int i; ++ ++ unit = _UNIT ((long) fi->template[fi->cur_no].data); ++ number = _NUMBER ((long) fi->template[fi->cur_no].data); ++ ++ i = fi->cur_no; ++ size = 0; ++ while (number > 0) ++ { ++ i = _FrameInstDecrement (fi->template, i); ++ size += _FrameInstGetItemSize (fi, i); ++ number--; ++ } ++ /*endwhile*/ ++ info->num = (unit - (size%unit))%unit; ++ } ++ /*endif*/ ++ break; ++ ++ case ITER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ XimFrameType sub_type; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[fi->cur_no + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, fi->cur_no, dr); ++ } ++ /*endif*/ ++ sub_type = IterPeekNextType (d->iter, info); ++ if (sub_type == EOL) ++ ret_type = FrameInstPeekNextType (fi, info); ++ else ++ ret_type = sub_type; ++ /*endif*/ ++ } ++ break; ++ ++ case POINTER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ XimFrameType sub_type; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL) ++ { ++ dr.fi = FrameInstInit (fi->template[fi->cur_no + 1].data); ++ d = ChainMgrSetData (&fi->cm, fi->cur_no, dr); ++ } ++ /*endif*/ ++ sub_type = FrameInstPeekNextType (d->fi, info); ++ if (sub_type == EOL) ++ ret_type = FrameInstPeekNextType (fi, info); ++ else ++ ret_type = sub_type; ++ /*endif*/ ++ default: ++ break; ++ } ++ break; ++ } ++ /*endswitch*/ ++ return ret_type; ++} ++ ++static Bool FrameInstIsIterLoopEnd (FrameInst fi) ++{ ++ Bool ret = False; ++ ++ if (fi->template[fi->cur_no].type == ITER) ++ { ++ ExtraData d = ChainMgrGetExtraData (&fi->cm, fi->cur_no); ++ Bool yourself; ++ ++ if (d) ++ { ++ ret = IterIsLoopEnd (d->iter, &yourself); ++ if (ret && yourself) ++ fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no); ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ return (ret); ++} ++ ++static FrameIter _FrameMgrAppendIter (FrameMgr fm, Iter it, int end) ++{ ++ FrameIter p = fm->iters; ++ ++ while (p && p->next) ++ p = p->next; ++ /*endwhile*/ ++ ++ if (!p) ++ { ++ fm->iters = ++ p = (FrameIter) Xmalloc (sizeof (FrameIterRec)); ++ } ++ else ++ { ++ p->next = (FrameIter) Xmalloc (sizeof (FrameIterRec)); ++ p = p->next; ++ } ++ /*endif*/ ++ if (p) ++ { ++ p->iter = it; ++ p->counting = False; ++ p->counter = 0; ++ p->end = end; ++ p->next = NULL; ++ } ++ /*endif*/ ++ return (p); ++} ++ ++static void _FrameMgrRemoveIter (FrameMgr fm, FrameIter it) ++{ ++ FrameIter prev; ++ FrameIter p; ++ ++ prev = NULL; ++ p = fm->iters; ++ while (p) ++ { ++ if (p == it) ++ { ++ if (prev) ++ prev->next = p->next; ++ else ++ fm->iters = p->next; ++ /*endif*/ ++ Xfree (p); ++ break; ++ } ++ /*endif*/ ++ prev = p; ++ p = p->next; ++ } ++ /*endwhile*/ ++} ++ ++static FrameIter _FrameIterCounterIncr (FrameIter fitr, int i) ++{ ++ FrameIter p = fitr; ++ ++ while (p) ++ { ++ if (p->counting) ++ { ++ p->counter += i; ++ if (p->counter >= p->end) ++ { ++ IterFixIteration (p->iter); ++ return (p); ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ p = p->next; ++ } ++ /*endwhile*/ ++ return (NULL); ++} ++ ++static void _IterStartWatch (Iter it, void *client_data) ++{ ++ FrameIter p = (FrameIter) client_data; ++ p->counting = True; ++} ++ ++static FmStatus FrameInstSetSize (FrameInst fi, int num) ++{ ++ ExtraData d; ++ ExtraDataRec dr; ++ XimFrameType type; ++ register int i; ++ ++ i = 0; ++ while ((type = fi->template[i].type) != EOL) ++ { ++ switch (type) ++ { ++ case BARRAY: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.num = -1; ++ d = ChainMgrSetData (&fi->cm, i, dr); ++ } ++ /*endif*/ ++ if (d->num == NO_VALUE) ++ { ++ d->num = num; ++ return FmSuccess; ++ } ++ /*endif*/ ++ break; ++ case ITER: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[i + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, i, dr); ++ } ++ /*endif*/ ++ if (IterSetSize (d->iter, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ break; ++ ++ case POINTER: ++ if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit(fi->template[i + 1].data); ++ d = ChainMgrSetData(&fi->cm, i, dr); ++ } ++ /*endif*/ ++ if (FrameInstSetSize(d->fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ break; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ i = _FrameInstIncrement(fi->template, i); ++ } ++ /*endwhile*/ ++ return FmNoMoreData; ++} ++ ++static int FrameInstGetSize (FrameInst fi) ++{ ++ XimFrameType type; ++ register int i; ++ ExtraData d; ++ ExtraDataRec dr; ++ int ret_size; ++ ++ i = fi->cur_no; ++ while ((type = fi->template[i].type) != EOL) ++ { ++ switch (type) ++ { ++ case BARRAY: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ return d->num; ++ ++ case ITER: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[i + 1], NO_VALUE); ++ d = ChainMgrSetData (&fi->cm, i, dr); ++ } ++ /*endif*/ ++ ret_size = IterGetSize(d->iter); ++ if (ret_size != NO_VALID_FIELD) ++ return ret_size; ++ /*endif*/ ++ break; ++ ++ case POINTER: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (fi->template[i + 1].data); ++ d = ChainMgrSetData (&fi->cm, i, dr); ++ } ++ /*endif*/ ++ ret_size = FrameInstGetSize (d->fi); ++ if (ret_size != NO_VALID_FIELD) ++ return ret_size; ++ /*endif*/ ++ break; ++ default: ++ break; ++ } ++ /*endswitch*/ ++ i = _FrameInstIncrement (fi->template, i); ++ } ++ /*endwhile*/ ++ return NO_VALID_FIELD; ++} ++ ++static FmStatus FrameInstSetIterCount (FrameInst fi, int num) ++{ ++ ExtraData d; ++ ExtraDataRec dr; ++ register int i; ++ XimFrameType type; ++ ++ i = 0; ++ while ((type = fi->template[i].type) != EOL) ++ { ++ switch (type) ++ { ++ case ITER: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.iter = IterInit (&fi->template[i + 1], num); ++ (void)ChainMgrSetData (&fi->cm, i, dr); ++ return FmSuccess; ++ } ++ /*endif*/ ++ if (IterSetIterCount (d->iter, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ break; ++ ++ case POINTER: ++ if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (fi->template[i + 1].data); ++ d = ChainMgrSetData (&fi->cm, i, dr); ++ } ++ /*endif*/ ++ if (FrameInstSetIterCount (d->fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ break; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ i = _FrameInstIncrement (fi->template, i); ++ } ++ /*endwhile*/ ++ return FmNoMoreData; ++} ++ ++static int FrameInstGetTotalSize (FrameInst fi) ++{ ++ register int size; ++ register int i; ++ ++ size = 0; ++ i = 0; ++ ++ while (fi->template[i].type != EOL) ++ { ++ size += _FrameInstGetItemSize (fi, i); ++ i = _FrameInstIncrement (fi->template, i); ++ } ++ /*endwhile*/ ++ return size; ++} ++ ++static void FrameInstReset (FrameInst fi) ++{ ++ ChainIterRec ci; ++ int frame_no; ++ ExtraDataRec d; ++ ++ ChainIterInit (&ci, &fi->cm); ++ ++ while (ChainIterGetNext (&ci, &frame_no, &d)) ++ { ++ register XimFrameType type; ++ type = fi->template[frame_no].type; ++ if (type == ITER) ++ { ++ if (d.iter) ++ IterReset (d.iter); ++ /*endif*/ ++ } ++ else if (type == POINTER) ++ { ++ if (d.fi) ++ FrameInstReset (d.fi); ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ ++ fi->cur_no = 0; ++} ++ ++static Iter IterInit (XimFrame frame, int count) ++{ ++ Iter it; ++ register XimFrameType type; ++ ++ it = (Iter) Xmalloc (sizeof (IterRec)); ++ it->template = frame; ++ it->max_count = (count == NO_VALUE) ? 0 : count; ++ it->allow_expansion = (count == NO_VALUE); ++ it->cur_no = 0; ++ it->start_watch_proc = NULL; ++ it->client_data = NULL; ++ it->start_counter = False; ++ ++ type = frame->type; ++ if (type & COUNTER_MASK) ++ { ++ /* COUNTER_XXX cannot be an item of a ITER */ ++ Xfree (it); ++ return NULL; ++ } ++ /*endif*/ ++ ++ switch (type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ /* Do nothing */ ++ break; ++ ++ case BARRAY: ++ case ITER: ++ case POINTER: ++ ChainMgrInit (&it->cm); ++ break; ++ ++ default: ++ Xfree (it); ++ return NULL; /* This should never occur */ ++ } ++ /*endswitch*/ ++ return it; ++} ++ ++static void IterFree (Iter it) ++{ ++ switch (it->template->type) ++ { ++ case BARRAY: ++ ChainMgrFree (&it->cm); ++ break; ++ ++ case ITER: ++ { ++ ChainIterRec ci; ++ int count; ++ ExtraDataRec d; ++ ++ ChainIterInit (&ci, &it->cm); ++ while (ChainIterGetNext (&ci, &count, &d)) ++ IterFree (d.iter); ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ ChainMgrFree (&it->cm); ++ } ++ break; ++ ++ case POINTER: ++ { ++ ChainIterRec ci; ++ int count; ++ ExtraDataRec dr; ++ ++ ChainIterInit (&ci, &it->cm); ++ while (ChainIterGetNext (&ci, &count, &dr)) ++ FrameInstFree (dr.fi); ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ ChainMgrFree (&it->cm); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ Xfree (it); ++} ++ ++static Bool IterIsLoopEnd (Iter it, Bool *myself) ++{ ++ Bool ret = False; ++ *myself = False; ++ ++ if (!it->allow_expansion && (it->cur_no == it->max_count)) ++ { ++ *myself = True; ++ return True; ++ } ++ /*endif*/ ++ ++ if (it->template->type == POINTER) ++ { ++ ExtraData d = ChainMgrGetExtraData (&it->cm, it->cur_no); ++ if (d) ++ { ++ if (FrameInstIsIterLoopEnd (d->fi)) ++ { ++ ret = True; ++ } ++ else ++ { ++ if (FrameInstIsEnd (d->fi)) ++ { ++ it->cur_no++; ++ if (!it->allow_expansion && it->cur_no == it->max_count) ++ { ++ *myself = True; ++ ret = True; ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ else if (it->template->type == ITER) ++ { ++ ExtraData d = ChainMgrGetExtraData (&it->cm, it->cur_no); ++ if (d) ++ { ++ Bool yourself; ++ ++ if (IterIsLoopEnd (d->iter, &yourself)) ++ ret = True; ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ return ret; ++} ++ ++static XimFrameType IterGetNextType (Iter it, XimFrameTypeInfo info) ++{ ++ XimFrameType type = it->template->type; ++ ++ if (it->start_counter) ++ { ++ (*it->start_watch_proc) (it, it->client_data); ++ it->start_counter = False; ++ } ++ /*endif*/ ++ if (it->cur_no >= it->max_count) ++ { ++ if (it->allow_expansion) ++ it->max_count = it->cur_no + 1; ++ else ++ return EOL; ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ switch (type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ it->cur_no++; ++ return type; ++ ++ case BARRAY: ++ if (info) ++ { ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ info->num = NO_VALUE; ++ else ++ info->num = d->num; ++ /*endif*/ ++ } ++ /*endif*/ ++ it->cur_no++; ++ return BARRAY; ++ ++ case ITER: ++ { ++ XimFrameType ret_type; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ { ++ dr.iter = IterInit (it->template + 1, NO_VALUE); ++ d = ChainMgrSetData (&it->cm, it->cur_no, dr); ++ } ++ /*endif*/ ++ ++ ret_type = IterGetNextType (d->iter, info); ++ if (ret_type == EOL) ++ { ++ it->cur_no++; ++ ret_type = IterGetNextType (it, info); ++ } ++ /*endif*/ ++ return ret_type; ++ } ++ ++ case POINTER: ++ { ++ XimFrameType ret_type; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, it->cur_no, dr); ++ } ++ /*endif*/ ++ ++ ret_type = FrameInstGetNextType (d->fi, info); ++ if (ret_type == EOL) ++ { ++ it->cur_no++; ++ ret_type = IterGetNextType (it, info); ++ } ++ /*endif*/ ++ return ret_type; ++ } ++ ++ default: ++ return (XimFrameType) NULL; ++ } ++ /*endswitch*/ ++ return (XimFrameType) NULL; /* This should never occur */ ++} ++ ++static XimFrameType IterPeekNextType (Iter it, XimFrameTypeInfo info) ++{ ++ XimFrameType type = it->template->type; ++ ++ if (!it->allow_expansion && it->cur_no >= it->max_count) ++ return (EOL); ++ /*endif*/ ++ ++ switch (type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ return type; ++ ++ case BARRAY: ++ if (info) ++ { ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ info->num = NO_VALUE; ++ else ++ info->num = d->num; ++ /*endif*/ ++ } ++ /*endif*/ ++ return BARRAY; ++ ++ case ITER: ++ { ++ XimFrameType ret_type; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ { ++ dr.iter = IterInit (it->template + 1, NO_VALUE); ++ d = ChainMgrSetData (&it->cm, it->cur_no, dr); ++ } ++ /*endif*/ ++ ++ ret_type = IterPeekNextType (d->iter, info); ++ if (ret_type == EOL) ++ ret_type = IterPeekNextType (it, info); ++ /*endif*/ ++ return ret_type; ++ } ++ ++ case POINTER: ++ { ++ XimFrameType ret_type; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, it->cur_no, dr); ++ } ++ /*endif*/ ++ ++ ret_type = FrameInstPeekNextType (d->fi, info); ++ if (ret_type == EOL) ++ ret_type = IterPeekNextType (it, info); ++ /*endif*/ ++ return (ret_type); ++ } ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ /* Reaching here is a bug! */ ++ return (XimFrameType) NULL; ++} ++ ++static FmStatus IterSetSize (Iter it, int num) ++{ ++ XimFrameType type; ++ register int i; ++ ++ if (!it->allow_expansion && it->max_count == 0) ++ return FmNoMoreData; ++ /*endif*/ ++ ++ type = it->template->type; ++ switch (type) ++ { ++ case BARRAY: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ for (i = 0; i < it->max_count; i++) ++ { ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.num = NO_VALUE; ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ if (d->num == NO_VALUE) ++ { ++ d->num = num; ++ return FmSuccess; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (it->allow_expansion) ++ { ++ ExtraDataRec dr; ++ ++ dr.num = num; ++ ChainMgrSetData (&it->cm, it->max_count, dr); ++ it->max_count++; ++ ++ return FmSuccess; ++ } ++ /*endif*/ ++ } ++ return FmNoMoreData; ++ ++ case ITER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ for (i = 0; i < it->max_count; i++) ++ { ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.iter = IterInit (it->template + 1, NO_VALUE); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ if (IterSetSize (d->iter, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (it->allow_expansion) ++ { ++ ExtraDataRec dr; ++ ++ dr.iter = IterInit (it->template + 1, NO_VALUE); ++ ChainMgrSetData (&it->cm, it->max_count, dr); ++ it->max_count++; ++ ++ if (IterSetSize(dr.iter, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ return FmNoMoreData; ++ ++ case POINTER: ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ for (i = 0; i < it->max_count; i++) ++ { ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ if (FrameInstSetSize (d->fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (it->allow_expansion) ++ { ++ ExtraDataRec dr; ++ ++ dr.fi = FrameInstInit (it->template[1].data); ++ ChainMgrSetData (&it->cm, it->max_count, dr); ++ it->max_count++; ++ ++ if (FrameInstSetSize (dr.fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ return FmNoMoreData; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return FmNoMoreData; ++} ++ ++static int IterGetSize (Iter it) ++{ ++ register int i; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if (it->cur_no >= it->max_count) ++ return NO_VALID_FIELD; ++ /*endif*/ ++ ++ switch (it->template->type) ++ { ++ case BARRAY: ++ if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ return d->num; ++ ++ case ITER: ++ for (i = it->cur_no; i < it->max_count; i++) ++ { ++ int ret_size; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.iter = IterInit (it->template + 1, NO_VALUE); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ ret_size = IterGetSize (d->iter); ++ if (ret_size != NO_VALID_FIELD) ++ return ret_size; ++ /*endif*/ ++ } ++ /*endfor*/ ++ return NO_VALID_FIELD; ++ ++ case POINTER: ++ for (i = it->cur_no; i < it->max_count; i++) ++ { ++ int ret_size; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ ret_size = FrameInstGetSize (d->fi); ++ if (ret_size != NO_VALID_FIELD) ++ return ret_size; ++ /*endif*/ ++ } ++ /*endfor*/ ++ return NO_VALID_FIELD; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return NO_VALID_FIELD; ++} ++ ++static FmStatus IterSetIterCount (Iter it, int num) ++{ ++ register int i; ++ ++ if (it->allow_expansion) ++ { ++ it->max_count = num; ++ it->allow_expansion = False; ++ return FmSuccess; ++ } ++ /*endif*/ ++ ++ if (it->max_count == 0) ++ return FmNoMoreData; ++ /*endif*/ ++ ++ switch (it->template->type) ++ { ++ case ITER: ++ for (i = 0; i < it->max_count; i++) ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) ++ { ++ dr.iter = IterInit(it->template + 1, num); ++ (void)ChainMgrSetData(&it->cm, i, dr); ++ return FmSuccess; ++ } ++ /*endif*/ ++ if (IterSetIterCount(d->iter, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (it->allow_expansion) ++ { ++ ExtraDataRec dr; ++ ++ dr.iter = IterInit (it->template + 1, num); ++ ChainMgrSetData (&it->cm, it->max_count, dr); ++ it->max_count++; ++ ++ return FmSuccess; ++ } ++ /*endif*/ ++ break; ++ ++ case POINTER: ++ for (i = 0; i < it->max_count; i++) ++ { ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ if (FrameInstSetIterCount (d->fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (it->allow_expansion) ++ { ++ ExtraDataRec dr; ++ ++ dr.fi = FrameInstInit (it->template[1].data); ++ ChainMgrSetData (&it->cm, it->max_count, dr); ++ it->max_count++; ++ ++ if (FrameInstSetIterCount (dr.fi, num) == FmSuccess) ++ return FmSuccess; ++ /*endif*/ ++ } ++ /*endif*/ ++ break; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return FmNoMoreData; ++} ++ ++static int IterGetTotalSize (Iter it) ++{ ++ register int size, i; ++ XimFrameType type; ++ ++ if (it->allow_expansion) ++ return NO_VALUE; ++ /*endif*/ ++ if (it->max_count == 0) ++ return 0; ++ /*endif*/ ++ ++ size = 0; ++ type = it->template->type; ++ ++ switch (type) ++ { ++ case BIT8: ++ size = it->max_count; ++ break; ++ ++ case BIT16: ++ size = it->max_count*2; ++ break; ++ ++ case BIT32: ++ size = it->max_count*4; ++ break; ++ ++ case BIT64: ++ size = it->max_count*8; ++ break; ++ ++ case BARRAY: ++ for (i = 0; i < it->max_count; i++) ++ { ++ register int num; ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ if ((num = d->num) == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ size += num; ++ } ++ /*endfor*/ ++ break; ++ ++ case ITER: ++ for (i = 0; i < it->max_count; i++) ++ { ++ register int num; ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ if ((num = IterGetTotalSize (d->iter)) == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ size += num; ++ } ++ /*endfor*/ ++ break; ++ ++ case POINTER: ++ for (i = 0; i < it->max_count; i++) ++ { ++ register int num; ++ ExtraData d; ++ ExtraDataRec dr; ++ ++ if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL) ++ { ++ dr.fi = FrameInstInit (it->template[1].data); ++ d = ChainMgrSetData (&it->cm, i, dr); ++ } ++ /*endif*/ ++ if ((num = FrameInstGetTotalSize (d->fi)) == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ size += num; ++ } ++ /*endfor*/ ++ break; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return size; ++} ++ ++static void IterReset (Iter it) ++{ ++ ChainIterRec ci; ++ int count; ++ ExtraDataRec d; ++ ++ switch (it->template->type) ++ { ++ case ITER: ++ ChainIterInit (&ci, &it->cm); ++ while (ChainIterGetNext (&ci, &count, &d)) ++ IterReset (d.iter); ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ break; ++ ++ case POINTER: ++ ChainIterInit (&ci, &it->cm); ++ while (ChainIterGetNext (&ci, &count, &d)) ++ FrameInstReset (d.fi); ++ /*endwhile*/ ++ ChainIterFree (&ci); ++ break; ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ it->cur_no = 0; ++} ++ ++static void IterSetStartWatch (Iter it, ++ IterStartWatchProc proc, ++ void *client_data) ++{ ++ it->start_watch_proc = proc; ++ it->client_data = client_data; ++} ++ ++static ExtraData ChainMgrSetData (ChainMgr cm, ++ int frame_no, ++ ExtraDataRec data) ++{ ++ Chain cur = (Chain) Xmalloc (sizeof (ChainRec)); ++ ++ cur->frame_no = frame_no; ++ cur->d = data; ++ cur->next = NULL; ++ ++ if (cm->top == NULL) ++ { ++ cm->top = cm->tail = cur; ++ } ++ else ++ { ++ cm->tail->next = cur; ++ cm->tail = cur; ++ } ++ /*endif*/ ++ return &cur->d; ++} ++ ++static ExtraData ChainMgrGetExtraData (ChainMgr cm, int frame_no) ++{ ++ Chain cur; ++ ++ cur = cm->top; ++ ++ while (cur) ++ { ++ if (cur->frame_no == frame_no) ++ return &cur->d; ++ /*endif*/ ++ cur = cur->next; ++ } ++ /*endwhile*/ ++ return NULL; ++} ++ ++static Bool ChainIterGetNext (ChainIter ci, int *frame_no, ExtraData d) ++{ ++ if (ci->cur == NULL) ++ return False; ++ /*endif*/ ++ ++ *frame_no = ci->cur->frame_no; ++ *d = ci->cur->d; ++ ++ ci->cur = ci->cur->next; ++ ++ return True; ++} ++ ++static int _FrameInstIncrement (XimFrame frame, int count) ++{ ++ XimFrameType type; ++ ++ type = frame[count].type; ++ type &= ~COUNTER_MASK; ++ ++ switch (type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ case BARRAY: ++ case PADDING: ++ return count + 1; ++ ++ case POINTER: ++ return count + 2; ++ ++ case ITER: ++ return _FrameInstIncrement (frame, count + 1); ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return - 1; /* Error */ ++} ++ ++static int _FrameInstDecrement (XimFrame frame, int count) ++{ ++ register int i; ++ XimFrameType type; ++ ++ if (count == 0) ++ return - 1; /* cannot decrement */ ++ /*endif*/ ++ ++ if (count == 1) ++ return 0; /* BOGUS - It should check the contents of data */ ++ /*endif*/ ++ ++ type = frame[count - 2].type; ++ type &= ~COUNTER_MASK; ++ ++ switch (type) ++ { ++ case BIT8: ++ case BIT16: ++ case BIT32: ++ case BIT64: ++ case BARRAY: ++ case PADDING: ++ case PTR_ITEM: ++ return count - 1; ++ ++ case POINTER: ++ case ITER: ++ i = count - 3; ++ while (i >= 0) ++ { ++ if (frame[i].type != ITER) ++ return i + 1; ++ /*endif*/ ++ i--; ++ } ++ /*endwhile*/ ++ return 0; ++ default: ++ break; ++ } ++ /*enswitch*/ ++ return - 1; /* Error */ ++} ++ ++static int _FrameInstGetItemSize (FrameInst fi, int cur_no) ++{ ++ XimFrameType type; ++ ++ type = fi->template[cur_no].type; ++ type &= ~COUNTER_MASK; ++ ++ switch (type) ++ { ++ case BIT8: ++ return 1; ++ ++ case BIT16: ++ return 2; ++ ++ case BIT32: ++ return 4; ++ ++ case BIT64: ++ return 8; ++ ++ case BARRAY: ++ { ++ ExtraData d; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ if (d->num == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ return d->num; ++ } ++ ++ case PADDING: ++ { ++ register int unit; ++ register int number; ++ register int size; ++ register int i; ++ ++ unit = _UNIT ((long) fi->template[cur_no].data); ++ number = _NUMBER ((long) fi->template[cur_no].data); ++ ++ i = cur_no; ++ size = 0; ++ while (number > 0) ++ { ++ i = _FrameInstDecrement (fi->template, i); ++ size += _FrameInstGetItemSize (fi, i); ++ number--; ++ } ++ /*endwhile*/ ++ size = (unit - (size%unit))%unit; ++ return size; ++ } ++ ++ case ITER: ++ { ++ ExtraData d; ++ int sub_size; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ sub_size = IterGetTotalSize (d->iter); ++ if (sub_size == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ return sub_size; ++ } ++ ++ case POINTER: ++ { ++ ExtraData d; ++ int sub_size; ++ ++ if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL) ++ return NO_VALUE; ++ /*endif*/ ++ sub_size = FrameInstGetTotalSize (d->fi); ++ if (sub_size == NO_VALUE) ++ return NO_VALUE; ++ /*endif*/ ++ return sub_size; ++ } ++ ++ default: ++ break; ++ } ++ /*endswitch*/ ++ return NO_VALUE; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.h +new file mode 100644 +index 0000000..ce7ed50 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/FrameMgr.h +@@ -0,0 +1,131 @@ ++/****************************************************************** ++Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts, ++ ++ All Rights Reserved ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose and without fee is hereby granted, ++provided that the above copyright notice appear in all copies and that ++both that copyright notice and this permission notice appear in ++supporting documentation, and that the names of Digital or MIT not be ++used in advertising or publicity pertaining to distribution of the ++software without specific, written prior permission. ++ ++DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ++ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ++ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ++WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ++ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++SOFTWARE. ++ ++ Author: Hiroyuki Miyamoto Digital Equipment Corporation ++ miyamoto@jrd.dec.com ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef FRAMEMGR_H ++#define FRAMEMGR_H ++ ++#include ++#include ++#include ++ ++#if defined(VAXC) && !defined(__DECC) ++#define xim_externalref globalref ++#define xim_externaldef globaldef ++#else ++#define xim_externalref extern ++#define xim_externaldef ++#endif ++ ++/* Definitions for FrameMgr */ ++ ++#define COUNTER_MASK 0x10 ++ ++typedef enum ++{ ++ BIT8 = 0x1, /* {CARD8* | INT8*} */ ++ BIT16 = 0x2, /* {CARD16* | INT16*} */ ++ BIT32 = 0x3, /* {CARD32* | INT32*} */ ++ BIT64 = 0x4, /* {CARD64* | INT64*} */ ++ BARRAY = 0x5, /* int*, void* */ ++ ITER = 0x6, /* int* */ ++ POINTER = 0x7, /* specifies next item is a PTR_ITEM */ ++ PTR_ITEM = 0x8, /* specifies the item has a pointer */ ++ /* BOGUS - POINTER and PTR_ITEM ++ * In the current implementation, PTR_ITEM should be lead by ++ * POINTER. But actually, it's just redundant logically. Someone ++ * may remove this redundancy and POINTER from the enum member but he ++ * should also modify the logic in FrameMgr program. ++ */ ++ PADDING = 0x9, /* specifies that a padding is needed. ++ * This requires extra data in data field. ++ */ ++ EOL = 0xA, /* specifies the end of list */ ++ ++ COUNTER_BIT8 = COUNTER_MASK | 0x1, ++ COUNTER_BIT16 = COUNTER_MASK | 0x2, ++ COUNTER_BIT32 = COUNTER_MASK | 0x3, ++ COUNTER_BIT64 = COUNTER_MASK | 0x4 ++} XimFrameType; ++ ++/* Convenient macro */ ++#define _FRAME(a) {a, NULL} ++#define _PTR(p) {PTR_ITEM, (void *)p} ++/* PADDING's usage of data field ++ * B15-B8 : Shows the number of effective items. ++ * B7-B0 : Shows padding unit. ex) 04 shows 4 unit padding. ++ */ ++#define _PAD2(n) {PADDING, (void*)((n)<<8|2)} ++#define _PAD4(n) {PADDING, (void*)((n)<<8|4)} ++ ++#define FmCounterByte 0 ++#define FmCounterNumber 1 ++ ++#define _BYTE_COUNTER(type, offset) \ ++ {(COUNTER_MASK|type), (void*)((offset)<<8|FmCounterByte)} ++ ++#define _NUMBER_COUNTER(type, offset) \ ++ {(COUNTER_MASK|type), (void*)((offset)<<8|FmCounterNumber)} ++ ++typedef struct _XimFrame ++{ ++ XimFrameType type; ++ void* data; /* For PTR_ITEM and PADDING */ ++} XimFrameRec, *XimFrame; ++ ++typedef enum ++{ ++ FmSuccess, ++ FmEOD, ++ FmInvalidCall, ++ FmBufExist, ++ FmCannotCalc, ++ FmNoMoreData ++} FmStatus; ++ ++typedef struct _FrameMgr *FrameMgr; ++ ++FrameMgr FrameMgrInit(XimFrame frame, char* area, Bool byte_swap); ++void FrameMgrInitWithData(FrameMgr fm, XimFrame frame, void* area, ++ Bool byte_swap); ++void FrameMgrFree(FrameMgr fm); ++FmStatus FrameMgrSetBuffer(FrameMgr, void*); ++FmStatus _FrameMgrPutToken(FrameMgr, void*, int); ++FmStatus _FrameMgrGetToken(FrameMgr, void*, int); ++FmStatus FrameMgrSetSize(FrameMgr, int); ++FmStatus FrameMgrSetIterCount(FrameMgr, int); ++FmStatus FrameMgrSetTotalSize(FrameMgr, int); ++int FrameMgrGetTotalSize(FrameMgr); ++int FrameMgrGetSize(FrameMgr); ++FmStatus FrameMgrSkipToken(FrameMgr, int); ++void FrameMgrReset(FrameMgr); ++Bool FrameMgrIsIterLoopEnd(FrameMgr, FmStatus*); ++ ++#define FrameMgrPutToken(fm, obj) _FrameMgrPutToken((fm), &(obj), sizeof(obj)) ++#define FrameMgrGetToken(fm, obj) _FrameMgrGetToken((fm), &(obj), sizeof(obj)) ++ ++#endif /* FRAMEMGR_H */ +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMConn.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMConn.c +new file mode 100644 +index 0000000..44cd9e8 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMConn.c +@@ -0,0 +1,176 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#include ++#include "../include/IMdkit.h" ++#include ++ ++#define Va_start(a,b) va_start(a,b) ++ ++static void _IMCountVaList(va_list var, int *total_count) ++{ ++ char *attr; ++ ++ *total_count = 0; ++ ++ for (attr = va_arg (var, char*); attr; attr = va_arg (var, char*)) ++ { ++ (void)va_arg (var, XIMArg *); ++ ++(*total_count); ++ } ++ /*endfor*/ ++} ++ ++static void _IMVaToNestedList(va_list var, int max_count, XIMArg **args_return) ++{ ++ XIMArg *args; ++ char *attr; ++ ++ if (max_count <= 0) ++ { ++ *args_return = (XIMArg *) NULL; ++ return; ++ } ++ /*endif*/ ++ ++ args = (XIMArg *) malloc ((unsigned) (max_count + 1)*sizeof (XIMArg)); ++ *args_return = args; ++ if (!args) ++ return; ++ /*endif*/ ++ ++ for (attr = va_arg (var, char*); attr; attr = va_arg (var, char *)) ++ { ++ args->name = attr; ++ args->value = va_arg (var, XPointer); ++ args++; ++ } ++ /*endfor*/ ++ args->name = (char*)NULL; ++} ++ ++static char *_FindModifiers (XIMArg *args) ++{ ++ char *modifiers; ++ ++ while (args->name) ++ { ++ if (strcmp (args->name, IMModifiers) == 0) ++ { ++ modifiers = args->value; ++ return modifiers; ++ } ++ else ++ { ++ args++; ++ } ++ /*endif*/ ++ } ++ /*endwhile*/ ++ return NULL; ++} ++ ++XIMS _GetIMS (char *modifiers) ++{ ++ XIMS ims; ++ extern IMMethodsRec Xi18n_im_methods; ++ ++ if ((ims = (XIMS) malloc (sizeof (XIMProtocolRec))) == (XIMS) NULL) ++ return ((XIMS) NULL); ++ /*endif*/ ++ memset ((void *) ims, 0, sizeof (XIMProtocolRec)); ++ ++ if (modifiers == NULL ++ || ++ modifiers[0] == '\0' ++ || ++ strcmp (modifiers, "Xi18n") == 0) ++ { ++ ims->methods = &Xi18n_im_methods; ++ return ims; ++ } ++ /*endif*/ ++ XFree (ims); ++ return (XIMS) NULL; ++} ++ ++XIMS IMOpenIM (Display *display, ...) ++{ ++ va_list var; ++ int total_count; ++ XIMArg *args; ++ XIMS ims; ++ char *modifiers; ++ Status ret; ++ ++ Va_start (var, display); ++ _IMCountVaList (var, &total_count); ++ va_end (var); ++ ++ Va_start (var, display); ++ _IMVaToNestedList (var, total_count, &args); ++ va_end (var); ++ ++ modifiers = _FindModifiers (args); ++ ++ ims = _GetIMS (modifiers); ++ if (ims == (XIMS) NULL) ++ return (XIMS) NULL; ++ /*endif*/ ++ ++ ims->core.display = display; ++ ++ ims->protocol = (*ims->methods->setup) (display, args); ++ XFree (args); ++ if (ims->protocol == (void *) NULL) ++ { ++ XFree (ims); ++ return (XIMS) NULL; ++ } ++ /*endif*/ ++ ret = (ims->methods->openIM) (ims); ++ if (ret == False) ++ { ++ XFree (ims); ++ return (XIMS) NULL; ++ } ++ /*endif*/ ++ return (XIMS) ims; ++} ++ ++Status IMCloseIM (XIMS ims) ++{ ++ (ims->methods->closeIM) (ims); ++ XFree (ims); ++ return True; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMMethod.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMMethod.c +new file mode 100644 +index 0000000..ff3fb2a +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/IMMethod.c +@@ -0,0 +1,65 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include "../include/IMdkit.h" ++ ++/* Public Function */ ++void IMForwardEvent (XIMS ims, XPointer call_data) ++{ ++ (ims->methods->forwardEvent) (ims, call_data); ++} ++ ++void IMCommitString (XIMS ims, XPointer call_data) ++{ ++ (ims->methods->commitString) (ims, call_data); ++} ++ ++int IMCallCallback (XIMS ims, XPointer call_data) ++{ ++ return (ims->methods->callCallback) (ims, call_data); ++} ++ ++int IMPreeditStart (XIMS ims, XPointer call_data) ++{ ++ return (ims->methods->preeditStart) (ims, call_data); ++} ++ ++int IMPreeditEnd (XIMS ims, XPointer call_data) ++{ ++ return (ims->methods->preeditEnd) (ims, call_data); ++} ++ ++int IMSyncXlib(XIMS ims, XPointer call_data) ++{ ++ ims->sync = True; ++ return (ims->methods->syncXlib) (ims, call_data); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/Xi18nX.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/Xi18nX.h +new file mode 100644 +index 0000000..ff91b1a +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/Xi18nX.h +@@ -0,0 +1,52 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef _Xi18nTrX_h ++#define _Xi18nTrX_h ++ ++#define _XIM_PROTOCOL "_XIM_PROTOCOL" ++#define _XIM_XCONNECT "_XIM_XCONNECT" ++ ++#define XCM_DATA_LIMIT 20 ++ ++typedef struct _XClient ++{ ++ Window client_win; /* client window */ ++ Window accept_win; /* accept window */ ++} XClient; ++ ++typedef struct ++{ ++ Atom xim_request; ++ Atom connect_request; ++} XSpecRec; ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/XimFunc.h b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/XimFunc.h +new file mode 100644 +index 0000000..a9f4a04 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/XimFunc.h +@@ -0,0 +1,72 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#ifndef _XimFunc_h ++#define _XimFunc_h ++ ++/* i18nAttr.c */ ++void _Xi18nInitAttrList (Xi18n i18n_core); ++void _Xi18nInitExtension(Xi18n i18n_core); ++ ++/* i18nClbk.c */ ++int _Xi18nGeometryCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nPreeditStartCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nPreeditDrawCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nPreeditCaretCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nPreeditDoneCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nStatusStartCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nStatusDrawCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nStatusDoneCallback (XIMS ims, IMProtocol *call_data); ++int _Xi18nStringConversionCallback (XIMS ims, IMProtocol *call_data); ++ ++/* i18nIc.c */ ++void _Xi18nChangeIC (XIMS ims, IMProtocol *call_data, unsigned char *p, ++ int create_flag); ++void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p); ++ ++/* i18nUtil.c */ ++int _Xi18nNeedSwap (Xi18n i18n_core, CARD16 connect_id); ++Xi18nClient *_Xi18nNewClient(Xi18n i18n_core); ++Xi18nClient *_Xi18nFindClient (Xi18n i18n_core, CARD16 connect_id); ++void _Xi18nDeleteClient (Xi18n i18n_core, CARD16 connect_id); ++void _Xi18nSendMessage (XIMS ims, CARD16 connect_id, CARD8 major_opcode, ++ CARD8 minor_opcode, unsigned char *data, long length); ++void _Xi18nSendTriggerKey (XIMS ims, CARD16 connect_id); ++void _Xi18nSetEventMask (XIMS ims, CARD16 connect_id, CARD16 im_id, ++ CARD16 ic_id, CARD32 forward_mask, CARD32 sync_mask); ++ ++/* Xlib internal */ ++void _XRegisterFilterByType(Display*, Window, int, int, ++ Bool (*filter)(Display*, Window, XEvent*, XPointer), XPointer); ++void _XUnregisterFilter(Display*, Window, ++ Bool (*filter)(Display*, Window, XEvent*, XPointer), XPointer); ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nAttr.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nAttr.c +new file mode 100644 +index 0000000..1647639 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nAttr.c +@@ -0,0 +1,175 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "XimFunc.h" ++ ++typedef struct ++{ ++ char *name; ++ CARD16 type; ++} IMListOfAttr; ++ ++typedef struct ++{ ++ char *name; ++ CARD8 major_opcode; ++ CARD8 minor_opcode; ++} IMExtList; ++ ++IMListOfAttr Default_IMattr[] = ++{ ++ {XNQueryInputStyle, XimType_XIMStyles}, ++/* {XNQueryIMValuesList, XimType_XIMValuesList}, */ ++ {(char *) NULL, (CARD16) 0} ++}; ++ ++IMListOfAttr Default_ICattr[] = ++{ ++ {XNInputStyle, XimType_CARD32}, ++ {XNClientWindow, XimType_Window}, ++ {XNFocusWindow, XimType_Window}, ++ {XNFilterEvents, XimType_CARD32}, ++ {XNPreeditAttributes, XimType_NEST}, ++ {XNStatusAttributes, XimType_NEST}, ++ {XNFontSet, XimType_XFontSet}, ++ {XNArea, XimType_XRectangle}, ++ {XNAreaNeeded, XimType_XRectangle}, ++ {XNColormap, XimType_CARD32}, ++ {XNStdColormap, XimType_CARD32}, ++ {XNForeground, XimType_CARD32}, ++ {XNBackground, XimType_CARD32}, ++ {XNBackgroundPixmap, XimType_CARD32}, ++ {XNSpotLocation, XimType_XPoint}, ++ {XNLineSpace, XimType_CARD32}, ++ {XNPreeditState, XimType_CARD32}, ++ {XNSeparatorofNestedList, XimType_SeparatorOfNestedList}, ++ {(char *) NULL, 0} ++}; ++ ++IMExtList Default_Extension[] = ++{ ++ {"XIM_EXT_MOVE", XIM_EXTENSION, XIM_EXT_MOVE}, ++ {"XIM_EXT_SET_EVENT_MASK", XIM_EXTENSION, XIM_EXT_SET_EVENT_MASK}, ++ {"XIM_EXT_FORWARD_KEYEVENT", XIM_EXTENSION, XIM_EXT_FORWARD_KEYEVENT}, ++ {(char *) NULL, 0, 0} ++}; ++ ++static void CountAttrList(IMListOfAttr *attr, int *total_count) ++{ ++ *total_count = 0; ++ ++ while (attr->name != NULL) ++ { ++ attr++; ++ ++(*total_count); ++ } ++} ++ ++static XIMAttr *CreateAttrList (Xi18n i18n_core, ++ IMListOfAttr *attr, ++ int *total_count) ++{ ++ XIMAttr *args, *p; ++ unsigned int buf_size; ++ ++ CountAttrList(attr, total_count); ++ ++ buf_size = (unsigned) (*total_count + 1)*sizeof (XIMAttr); ++ args = (XIMAttr *) malloc (buf_size); ++ if (!args) ++ return (XIMAttr *) NULL; ++ /*endif*/ ++ memset (args, 0, buf_size); ++ ++ for (p = args; attr->name != NULL; attr++, p++) ++ { ++ p->name = attr->name; ++ p->length = strlen (attr->name); ++ p->type = (CARD16) attr->type; ++ p->attribute_id = XrmStringToQuark (p->name); ++ if (strcmp (p->name, XNPreeditAttributes) == 0) ++ i18n_core->address.preeditAttr_id = p->attribute_id; ++ else if (strcmp (p->name, XNStatusAttributes) == 0) ++ i18n_core->address.statusAttr_id = p->attribute_id; ++ else if (strcmp (p->name, XNSeparatorofNestedList) == 0) ++ i18n_core->address.separatorAttr_id = p->attribute_id; ++ /*endif*/ ++ } ++ /*endfor*/ ++ p->name = (char *) NULL; ++ ++ return args; ++} ++ ++void _Xi18nInitAttrList (Xi18n i18n_core) ++{ ++ XIMAttr *args; ++ int total_count; ++ ++ /* init IMAttr list */ ++ if (i18n_core->address.xim_attr) ++ XFree ((char *)i18n_core->address.xim_attr); ++ /*endif*/ ++ args = CreateAttrList (i18n_core, Default_IMattr, &total_count); ++ ++ i18n_core->address.im_attr_num = total_count; ++ i18n_core->address.xim_attr = (XIMAttr *)args; ++ ++ /* init ICAttr list */ ++ if (i18n_core->address.xic_attr) ++ XFree ((char *) i18n_core->address.xic_attr); ++ /*endif*/ ++ args = CreateAttrList (i18n_core, Default_ICattr, &total_count); ++ ++ i18n_core->address.ic_attr_num = total_count; ++ i18n_core->address.xic_attr = (XICAttr *) args; ++} ++ ++void _Xi18nInitExtension(Xi18n i18n_core) ++{ ++ register int i; ++ IMExtList *extensions = (IMExtList *) Default_Extension; ++ XIMExt *ext_list = (XIMExt *) i18n_core->address.extension; ++ ++ for (i = 0; extensions->name; i++, ext_list++, extensions++) ++ { ++ ext_list->major_opcode = extensions->major_opcode; ++ ext_list->minor_opcode = extensions->minor_opcode; ++ ext_list->name = extensions->name; ++ ext_list->length = strlen(ext_list->name); ++ } ++ /*endfor*/ ++ i18n_core->address.ext_num = i; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nClbk.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nClbk.c +new file mode 100644 +index 0000000..887d769 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nClbk.c +@@ -0,0 +1,513 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "FrameMgr.h" ++#include "XimFunc.h" ++ ++int _Xi18nGeometryCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec geometry_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMGeometryCBStruct *geometry_CB = ++ (IMGeometryCBStruct *) &call_data->geometry_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (geometry_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, geometry_CB->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_GEOMETRY, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_GEOMETRY is an asyncronous protocol, ++ so return immediately. */ ++ return True; ++} ++ ++int _Xi18nPreeditStartCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_start_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct*) &call_data->preedit_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (preedit_start_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage(ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, preedit_CB->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_PREEDIT_START, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ return True; ++} ++ ++int _Xi18nPreeditDrawCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_draw_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct *) &call_data->preedit_callback; ++ XIMPreeditDrawCallbackStruct *draw = ++ (XIMPreeditDrawCallbackStruct *) &preedit_CB->todo.draw; ++ CARD16 connect_id = call_data->any.connect_id; ++ register int feedback_count; ++ register int i; ++ BITMASK32 status = 0x0; ++ ++ if (draw->text->length == 0) ++ status = 0x00000001; ++ else if (draw->text->feedback[0] == 0) ++ status = 0x00000002; ++ /*endif*/ ++ ++ fm = FrameMgrInit (preedit_draw_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set length of preedit string */ ++ FrameMgrSetSize (fm, draw->text->length); ++ ++ /* set iteration count for list of feedback */ ++ for (i = 0; draw->text->feedback[i] != 0; i++) ++ ; ++ /*endfor*/ ++ feedback_count = i; ++ FrameMgrSetIterCount (fm, feedback_count); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, preedit_CB->icid); ++ FrameMgrPutToken (fm, draw->caret); ++ FrameMgrPutToken (fm, draw->chg_first); ++ FrameMgrPutToken (fm, draw->chg_length); ++ FrameMgrPutToken (fm, status); ++ FrameMgrPutToken (fm, draw->text->length); ++ FrameMgrPutToken (fm, draw->text->string); ++ for (i = 0; i < feedback_count; i++) ++ FrameMgrPutToken (fm, draw->text->feedback[i]); ++ /*endfor*/ ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_PREEDIT_DRAW, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_PREEDIT_DRAW is an asyncronous protocol, so return immediately. */ ++ return True; ++} ++ ++int _Xi18nPreeditCaretCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_caret_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct*) &call_data->preedit_callback; ++ XIMPreeditCaretCallbackStruct *caret = ++ (XIMPreeditCaretCallbackStruct *) &preedit_CB->todo.caret; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (preedit_caret_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, preedit_CB->icid); ++ FrameMgrPutToken (fm, caret->position); ++ FrameMgrPutToken (fm, caret->direction); ++ FrameMgrPutToken (fm, caret->style); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_PREEDIT_CARET, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ return True; ++} ++ ++int _Xi18nPreeditDoneCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_done_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct *) &call_data->preedit_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (preedit_done_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, preedit_CB->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_PREEDIT_DONE, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_PREEDIT_DONE is an asyncronous protocol, so return immediately. */ ++ return True; ++} ++ ++int _Xi18nStatusStartCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec status_start_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMStatusCBStruct *status_CB = ++ (IMStatusCBStruct*) &call_data->status_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (status_start_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, status_CB->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_STATUS_START, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_STATUS_START is an asyncronous protocol, so return immediately. */ ++ return True; ++} ++ ++int _Xi18nStatusDrawCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm = (FrameMgr)0; ++ extern XimFrameRec status_draw_text_fr[]; ++ extern XimFrameRec status_draw_bitmap_fr[]; ++ register int total_size = 0; ++ unsigned char *reply = NULL; ++ IMStatusCBStruct *status_CB = ++ (IMStatusCBStruct *) &call_data->status_callback; ++ XIMStatusDrawCallbackStruct *draw = ++ (XIMStatusDrawCallbackStruct *) &status_CB->todo.draw; ++ CARD16 connect_id = call_data->any.connect_id; ++ register int feedback_count; ++ register int i; ++ BITMASK32 status = 0x0; ++ ++ switch (draw->type) ++ { ++ case XIMTextType: ++ fm = FrameMgrInit (status_draw_text_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ if (draw->data.text->length == 0) ++ status = 0x00000001; ++ else if (draw->data.text->feedback[0] == 0) ++ status = 0x00000002; ++ /*endif*/ ++ ++ /* set length of status string */ ++ FrameMgrSetSize(fm, draw->data.text->length); ++ /* set iteration count for list of feedback */ ++ for (i = 0; draw->data.text->feedback[i] != 0; i++) ++ ; ++ /*endfor*/ ++ feedback_count = i; ++ FrameMgrSetIterCount (fm, feedback_count); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, status_CB->icid); ++ FrameMgrPutToken (fm, draw->type); ++ FrameMgrPutToken (fm, status); ++ FrameMgrPutToken (fm, draw->data.text->length); ++ FrameMgrPutToken (fm, draw->data.text->string); ++ for (i = 0; i < feedback_count; i++) ++ FrameMgrPutToken (fm, draw->data.text->feedback[i]); ++ /*endfor*/ ++ break; ++ ++ case XIMBitmapType: ++ fm = FrameMgrInit (status_draw_bitmap_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, status_CB->icid); ++ FrameMgrPutToken (fm, draw->data.bitmap); ++ break; ++ } ++ /*endswitch*/ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_STATUS_DRAW, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_STATUS_DRAW is an asyncronous protocol, so return immediately. */ ++ return True; ++} ++ ++int _Xi18nStatusDoneCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec status_done_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMStatusCBStruct *status_CB = ++ (IMStatusCBStruct *) &call_data->status_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (status_done_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, status_CB->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_STATUS_DONE, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_STATUS_DONE is an asyncronous protocol, so return immediately. */ ++ return True; ++} ++ ++int _Xi18nStringConversionCallback (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec str_conversion_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMStrConvCBStruct *call_back = ++ (IMStrConvCBStruct *) &call_data->strconv_callback; ++ XIMStringConversionCallbackStruct *strconv = ++ (XIMStringConversionCallbackStruct *) &call_back->strconv; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (str_conversion_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, connect_id); ++ FrameMgrPutToken (fm, call_back->icid); ++ FrameMgrPutToken (fm, strconv->position); ++ FrameMgrPutToken (fm, strconv->direction); ++ FrameMgrPutToken (fm, strconv->operation); ++ ++ _Xi18nSendMessage (ims, connect_id, ++ XIM_STR_CONVERSION, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ /* XIM_STR_CONVERSION is a syncronous protocol, ++ so should wait here for XIM_STR_CONVERSION_REPLY. */ ++ if (i18n_core->methods.wait (ims, ++ connect_id, ++ XIM_STR_CONVERSION_REPLY, ++ 0) == False) ++ { ++ return False; ++ } ++ /*endif*/ ++ return True; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIMProto.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIMProto.c +new file mode 100644 +index 0000000..618da9d +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIMProto.c +@@ -0,0 +1,773 @@ ++/****************************************************************** ++Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts, ++Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Copyright 1994, 1995 by Sun Microsystems, Inc. ++ ++ All Rights Reserved ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose and without fee is hereby granted, ++provided that the above copyright notice appear in all copies and that ++both that copyright notice and this permission notice appear in ++supporting documentation, and that the names of Digital or MIT not be ++used in advertising or publicity pertaining to distribution of the ++software without specific, written prior permission. ++ ++DIGITAL AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL WARRANTIES WITH REGARD ++TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ++FITNESS, IN NO EVENT SHALL DIGITAL AND HEWLETT-PACKARD COMPANY BE LIABLE ++FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hiroyuki Miyamoto Digital Equipment Corporation ++ miyamoto@jrd.dec.com ++ Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++/* Protocol Packet frames */ ++ ++#include "FrameMgr.h" ++ ++/* Data type definitions */ ++ ++static XimFrameRec ximattr_fr[] = ++{ ++ _FRAME(BIT16), /* attribute ID */ ++ _FRAME(BIT16), /* type of the value */ ++ _FRAME(BIT16), /* length of im-attribute */ ++ _FRAME(BARRAY), /* im-attribute */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec xicattr_fr[] = ++{ ++ _FRAME(BIT16), /* attribute ID */ ++ _FRAME(BIT16), /* type of the value */ ++ _FRAME(BIT16), /* length of ic-attribute */ ++ _FRAME(BARRAY), /* ic-attribute */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec ximattribute_fr[] = ++{ ++ _FRAME(BIT16), /* attribute ID */ ++ _FRAME(BIT16), /* value length */ ++ _FRAME(BARRAY), /* value */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec xicattribute_fr[] = ++{ ++ _FRAME(BIT16), /* attribute ID */ ++ _FRAME(BIT16), /* value length */ ++ _FRAME(BARRAY), /* value */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec ximtriggerkey_fr[] = ++{ ++ _FRAME(BIT32), /* keysym */ ++ _FRAME(BIT32), /* modifier */ ++ _FRAME(BIT32), /* modifier mask */ ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec encodinginfo_fr[] = ++{ ++ _FRAME(BIT16), /* length of encoding info */ ++ _FRAME(BARRAY), /* encoding info */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec str_fr[] = ++{ ++ _FRAME(BIT8), /* number of byte */ ++ _FRAME(BARRAY), /* string */ ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec xpcs_fr[] = ++{ ++ _FRAME(BIT16), /* length of string in bytes */ ++ _FRAME(BARRAY), /* string */ ++ _PAD4(2), ++}; ++ ++static XimFrameRec ext_fr[] = ++{ ++ _FRAME(BIT8), /* extension major-opcode */ ++ _FRAME(BIT8), /* extension minor-opcode */ ++ _FRAME(BIT16), /* length of extension name */ ++ _FRAME(BARRAY), /* extension name */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++static XimFrameRec inputstyle_fr[] = ++{ ++ _FRAME(BIT32), /* inputstyle */ ++ _FRAME(EOL), ++}; ++/* Protocol definitions */ ++ ++xim_externaldef XimFrameRec attr_head_fr[] = ++{ ++ _FRAME(BIT16), /* attribute id */ ++ _FRAME(BIT16), /* attribute length */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec short_fr[] = ++{ ++ _FRAME(BIT16), /* value */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec long_fr[] = ++{ ++ _FRAME(BIT32), /* value */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec xrectangle_fr[] = ++{ ++ _FRAME(BIT16), /* x */ ++ _FRAME(BIT16), /* y */ ++ _FRAME(BIT16), /* width */ ++ _FRAME(BIT16), /* height */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec xpoint_fr[] = ++{ ++ _FRAME(BIT16), /* x */ ++ _FRAME(BIT16), /* y */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec fontset_fr[] = ++{ ++ _FRAME(BIT16), /* length of base font name */ ++ _FRAME(BARRAY), /* base font name list */ ++ _PAD4(2), /* unused */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec input_styles_fr[] = ++{ ++ _FRAME(BIT16), /* number of list */ ++ _PAD4(1), /* unused */ ++ _FRAME(ITER), /* XIMStyle list */ ++ _FRAME(POINTER), ++ _PTR(inputstyle_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec packet_header_fr[] = ++{ ++ _FRAME(BIT8), /* major-opcode */ ++ _FRAME(BIT8), /* minor-opcode */ ++ _FRAME(BIT16), /* length */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec error_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _FRAME(BIT16), /* Error Code */ ++ _FRAME(BIT16), /* length of error detail */ ++ _FRAME(BIT16), /* type of error detail */ ++ _FRAME(BARRAY), /* error detail */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec connect_fr[] = ++{ ++ _FRAME(BIT8), /* byte order */ ++ _PAD2(1), /* unused */ ++ _FRAME(BIT16), /* client-major-protocol-version */ ++ _FRAME(BIT16), /* client-minor-protocol-version */ ++ _BYTE_COUNTER(BIT16, 1), /* length of client-auth-protocol-names */ ++ _FRAME(ITER), /* client-auth-protocol-names */ ++ _FRAME(POINTER), ++ _PTR(xpcs_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec connect_reply_fr[] = ++{ ++ _FRAME(BIT16), /* server-major-protocol-version */ ++ _FRAME(BIT16), /* server-minor-protocol-version */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec auth_required_fr[] = ++{ ++ _FRAME(BIT8), /* auth-protocol-index */ ++ _FRAME(BIT8), /* auth-data1 */ ++ _FRAME(BARRAY), /* auth-data2 */ ++ _PAD4(3), ++ _FRAME(EOL), ++}; ++ ++ ++xim_externaldef XimFrameRec auth_reply_fr[] = ++{ ++ _FRAME(BIT8), ++ _FRAME(BARRAY), ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec auth_next_fr[] = ++{ ++ _FRAME(BIT8), /* auth-data1 */ ++ _FRAME(BARRAY), /* auth-data2 */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec auth_setup_fr[] = ++{ ++ _BYTE_COUNTER(BIT16, 2), /* number of client-auth-protocol-names */ ++ _PAD4(1), /* unused */ ++ _FRAME(ITER), /* server-auth-protocol-names */ ++ _FRAME(POINTER), ++ _PTR(xpcs_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec auth_ng_fr[] = ++{ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec disconnect_fr[] = ++{ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec disconnect_reply_fr[] = ++{ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec open_fr[] = ++{ ++ _FRAME(POINTER), /* locale name */ ++ _PTR(str_fr), ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec open_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of IM attributes supported */ ++ _FRAME(ITER), /* IM attribute supported */ ++ _FRAME(POINTER), ++ _PTR(ximattr_fr), ++ _BYTE_COUNTER(BIT16, 2), /* number of IC attribute supported */ ++ _PAD4(1), /* unused */ ++ _FRAME(ITER), /* IC attribute supported */ ++ _FRAME(POINTER), ++ _PTR(xicattr_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec close_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _PAD4(1), /* unused */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec close_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _PAD4(1), /* unused */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec register_triggerkeys_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _PAD4(1), /* unused */ ++ _BYTE_COUNTER(BIT32, 1), /* byte length of on-keys */ ++ _FRAME(ITER), /* on-keys list */ ++ _FRAME(POINTER), ++ _PTR(ximtriggerkey_fr), ++ _BYTE_COUNTER(BIT32, 1), /* byte length of off-keys */ ++ _FRAME(ITER), /* off-keys list */ ++ _FRAME(POINTER), ++ _PTR(ximtriggerkey_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec trigger_notify_fr[] = ++{ ++ _FRAME(BIT16), /* input-mehotd-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* flag */ ++ _FRAME(BIT32), /* index of keys list */ ++ _FRAME(BIT32), /* client-select-event-mask */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec trigger_notify_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec set_event_mask_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* forward-event-mask */ ++ _FRAME(BIT32), /* synchronous-event-mask */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec encoding_negotiation_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of encodings listed by name */ ++ _FRAME(ITER), /* supported list of encoding in IM library */ ++ _FRAME(POINTER), ++ _PTR(str_fr), ++ _PAD4(1), ++ _BYTE_COUNTER(BIT16, 2), /* byte length of encodings listed by ++ detailed data */ ++ _PAD4(1), ++ _FRAME(ITER), /* list of encodings supported in the ++ IM library */ ++ _FRAME(POINTER), ++ _PTR(encodinginfo_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec encoding_negotiation_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* category of the encoding determined */ ++ _FRAME(BIT16), /* index of the encoding dterminated */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec query_extension_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of extensions supported ++ by the IM library */ ++ _FRAME(ITER), /* extensions supported by the IM library */ ++ _FRAME(POINTER), ++ _PTR(str_fr), ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec query_extension_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of extensions supported ++ by the IM server */ ++ _FRAME(ITER), /* list of extensions supported by the ++ IM server */ ++ _FRAME(POINTER), ++ _PTR(ext_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec get_im_values_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of im-attribute-id */ ++ _FRAME(ITER), /* im-attribute-id */ ++ _FRAME(BIT16), ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec get_im_values_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of im-attribute returned */ ++ _FRAME(ITER), /* im-attribute returned */ ++ _FRAME(POINTER), ++ _PTR(ximattribute_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec create_ic_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of ic-attributes */ ++ _FRAME(ITER), /* ic-attributes */ ++ _FRAME(POINTER), ++ _PTR(xicattribute_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec create_ic_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec destroy_ic_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec destroy_ic_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec set_ic_values_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _BYTE_COUNTER(BIT16, 2), /* byte length of ic-attributes */ ++ _PAD4(1), ++ _FRAME(ITER), /* ic-attribute */ ++ _FRAME(POINTER), ++ _PTR(xicattribute_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec set_ic_values_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec get_ic_values_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _BYTE_COUNTER(BIT16, 1), /* byte length of ic-attribute-id */ ++ _FRAME(ITER), /* ic-attribute */ ++ _FRAME(BIT16), ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec get_ic_values_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _BYTE_COUNTER(BIT16, 2), /* byte length of ic-attribute */ ++ _PAD4(1), ++ _FRAME(ITER), /* ic-attribute */ ++ _FRAME(POINTER), ++ _PTR(xicattribute_fr), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec set_ic_focus_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec unset_ic_focus_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec forward_event_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _FRAME(BIT16), /* sequence number */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec wire_keyevent_fr[] = { ++ _FRAME(BIT8), /* type */ ++ _FRAME(BIT8), /* detail */ ++ _FRAME(BIT16), /* serial number */ ++ _FRAME(BIT32), /* time */ ++ _FRAME(BIT32), /* root */ ++ _FRAME(BIT32), /* window */ ++ _FRAME(BIT32), /* subwindow */ ++ _FRAME(BIT16), /* rootX */ ++ _FRAME(BIT16), /* rootY */ ++ _FRAME(BIT16), /* X */ ++ _FRAME(BIT16), /* Y */ ++ _FRAME(BIT16), /* state */ ++ _FRAME(BIT8), /* sameScreen */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec sync_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec sync_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++#if 0 ++xim_externaldef XimFrameRec commit_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _FRAME(BIT16), /* byte length of committed string */ ++ _FRAME(BARRAY), /* committed string */ ++ _PAD4(1), ++ _BYTE_COUNTER(BIT16, 1), /* byte length of keysym */ ++ _FRAME(ITER), /* keysym */ ++ _FRAME(BIT32), ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++#endif ++ ++xim_externaldef XimFrameRec commit_chars_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _FRAME(BIT16), /* byte length of committed string */ ++ _FRAME(BARRAY), /* committed string */ ++ _PAD4(1), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec commit_both_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _PAD4(1), /* unused */ ++ _FRAME(BIT32), /* keysym */ ++ _FRAME(BIT16), /* byte length of committed string */ ++ _FRAME(BARRAY), /* committed string */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec reset_ic_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec reset_ic_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* byte length of committed string */ ++ _FRAME(BARRAY), /* committed string */ ++ _PAD4(2), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec geometry_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec str_conversion_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* XIMStringConversionPosition */ ++ _FRAME(BIT32), /* XIMStringConversionType */ ++ _FRAME(BIT32), /* XIMStringConversionOperation */ ++ _FRAME(BIT16), /* length to multiply the ++ XIMStringConversionType */ ++ _FRAME(BIT16), /* length of the string to be ++ substituted */ ++#if 0 ++ _FRAME(BARRAY), /* string */ ++ _PAD4(1), ++#endif ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec str_conversion_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* XIMStringConversionFeedback */ ++ _FRAME(BIT16), /* length of the retrieved string */ ++ _FRAME(BARRAY), /* retrieved string */ ++ _PAD4(2), ++ _BYTE_COUNTER(BIT16, 2), /* number of feedback array */ ++ _PAD4(1), ++ _FRAME(ITER), /* feedback array */ ++ _FRAME(BIT32), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_start_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_start_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* return value */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_draw_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* caret */ ++ _FRAME(BIT32), /* chg_first */ ++ _FRAME(BIT32), /* chg_length */ ++ _FRAME(BIT32), /* status */ ++ _FRAME(BIT16), /* length of preedit string */ ++ _FRAME(BARRAY), /* preedit string */ ++ _PAD4(2), ++ _BYTE_COUNTER(BIT16, 2), /* number of feedback array */ ++ _PAD4(1), ++ _FRAME(ITER), /* feedback array */ ++ _FRAME(BIT32), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_caret_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* position */ ++ _FRAME(BIT32), /* direction */ ++ _FRAME(BIT32), /* style */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_caret_reply_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* position */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec preedit_done_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec status_start_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec status_draw_text_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* type */ ++ _FRAME(BIT32), /* status */ ++ _FRAME(BIT16), /* length of status string */ ++ _FRAME(BARRAY), /* status string */ ++ _PAD4(2), ++ _BYTE_COUNTER(BIT16, 2), /* number of feedback array */ ++ _PAD4(1), ++ _FRAME(ITER), /* feedback array */ ++ _FRAME(BIT32), ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec status_draw_bitmap_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* type */ ++ _FRAME(BIT32), /* pixmap data */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec status_done_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec ext_set_event_mask_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT32), /* filter-event-mask */ ++ _FRAME(BIT32), /* intercept-event-mask */ ++ _FRAME(BIT32), /* select-event-mask */ ++ _FRAME(BIT32), /* forward-event-mask */ ++ _FRAME(BIT32), /* synchronous-event-mask */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec ext_forward_keyevent_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* flag */ ++ _FRAME(BIT16), /* sequence number */ ++ _FRAME(BIT8), /* xEvent.u.u.type */ ++ _FRAME(BIT8), /* keycode */ ++ _FRAME(BIT16), /* state */ ++ _FRAME(BIT32), /* time */ ++ _FRAME(BIT32), /* window */ ++ _FRAME(EOL), ++}; ++ ++xim_externaldef XimFrameRec ext_move_fr[] = ++{ ++ _FRAME(BIT16), /* input-method-ID */ ++ _FRAME(BIT16), /* input-context-ID */ ++ _FRAME(BIT16), /* X */ ++ _FRAME(BIT16), /* Y */ ++ _FRAME(EOL), ++}; +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIc.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIc.c +new file mode 100644 +index 0000000..47e74c5 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nIc.c +@@ -0,0 +1,1106 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "FrameMgr.h" ++#include "XimFunc.h" ++ ++#define IC_SIZE 64 ++ ++/* Set IC values */ ++static void SetCardAttribute (XICAttribute *value_ret, ++ char *p, ++ XICAttr *ic_attr, ++ int value_length, ++ int need_swap, ++ void **value_buf) ++{ ++ FrameMgr fm; ++ ++ /*endif*/ ++ if (value_length == sizeof (CARD8)) ++ { ++ memmove (*value_buf, p, value_length); ++ } ++ else if (value_length == sizeof (CARD16)) ++ { ++ INT16 value; ++ extern XimFrameRec short_fr[]; ++ ++ fm = FrameMgrInit (short_fr, (char *) p, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, value); ++ FrameMgrFree (fm); ++ memmove (*value_buf, &value, value_length); ++ } ++ else if (value_length == sizeof(CARD32)) ++ { ++ INT32 value; ++ extern XimFrameRec long_fr[]; ++ ++ fm = FrameMgrInit (long_fr, (char *) p, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, value); ++ FrameMgrFree (fm); ++ memmove (*value_buf, &value, value_length); ++ } ++ /*endif*/ ++ value_ret->attribute_id = ic_attr->attribute_id; ++ value_ret->name = ic_attr->name; ++ value_ret->name_length = ic_attr->length; ++ value_ret->type = ic_attr->type; ++ value_ret->value_length = value_length; ++ value_ret->value = *value_buf; ++ ++ *value_buf += value_length; ++} ++ ++static void SetFontAttribute (XICAttribute *value_ret, ++ char *p, ++ XICAttr *ic_attr, ++ int value_length, ++ int need_swap, ++ void **value_buf) ++{ ++ char *base_name; ++ CARD16 base_length; ++ FrameMgr fm; ++ extern XimFrameRec fontset_fr[]; ++ ++ fm = FrameMgrInit (fontset_fr, (char *) p, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, base_length); ++ FrameMgrSetSize (fm, base_length); ++ ++ /*endif*/ ++ FrameMgrGetToken (fm, base_name); ++ FrameMgrFree(fm); ++ strncpy ((char *) (*value_buf), base_name, base_length); ++ ((char *) *value_buf)[base_length] = (char) 0; ++ ++ value_ret->attribute_id = ic_attr->attribute_id; ++ value_ret->name = ic_attr->name; ++ value_ret->name_length = ic_attr->length; ++ value_ret->type = ic_attr->type; ++ value_ret->value_length = value_length; ++ value_ret->value = *value_buf; ++ ++ *value_buf += (base_length + 1); ++} ++ ++static void SetPointAttribute (XICAttribute *value_ret, ++ char *p, ++ XICAttr *ic_attr, ++ int value_length, ++ int need_swap, ++ void **value_buf) ++{ ++ XPoint *buf; ++ FrameMgr fm; ++ extern XimFrameRec xpoint_fr[]; ++ ++ buf = (XPoint *) (*value_buf); ++ ++ fm = FrameMgrInit (xpoint_fr, (char *) p, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, buf->x); ++ FrameMgrGetToken (fm, buf->y); ++ FrameMgrFree (fm); ++ ++ value_ret->attribute_id = ic_attr->attribute_id; ++ value_ret->name = ic_attr->name; ++ value_ret->name_length = ic_attr->length; ++ value_ret->type = ic_attr->type; ++ value_ret->value_length = value_length; ++ value_ret->value = (char *) buf; ++ ++ *value_buf += value_length; ++} ++ ++static void SetRectAttribute (XICAttribute *value_ret, ++ char *p, ++ XICAttr *ic_attr, ++ int value_length, ++ int need_swap, ++ void **value_buf) ++{ ++ XRectangle *buf; ++ FrameMgr fm; ++ extern XimFrameRec xrectangle_fr[]; ++ ++ buf = (XRectangle *) (*value_buf); ++ ++ fm = FrameMgrInit (xrectangle_fr, (char *) p, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, buf->x); ++ FrameMgrGetToken (fm, buf->y); ++ FrameMgrGetToken (fm, buf->width); ++ FrameMgrGetToken (fm, buf->height); ++ FrameMgrFree (fm); ++ ++ value_ret->attribute_id = ic_attr->attribute_id; ++ value_ret->name = ic_attr->name; ++ value_ret->name_length = ic_attr->length; ++ value_ret->type = ic_attr->type; ++ value_ret->value_length = value_length; ++ value_ret->value = (char *) buf; ++ ++ *value_buf += value_length; ++} ++ ++#if 0 ++static void SetHotKeyAttribute (XICAttribute *value_ret, ++ char *p, ++ XICAttr *ic_attr, ++ int value_length, ++ int need_swap, ++ void **value_buf) ++{ ++ INT32 list_number; ++ XIMTriggerKey *hotkeys; ++ ++ memmove (&list_number, p, sizeof(INT32)); p += sizeof(INT32); ++ ++ hotkeys = (XIMTriggerKey *) (*value_buf); ++ ++ memmove (hotkeys, p, list_number*sizeof (XIMTriggerKey)); ++ ++ value_ret->attribute_id = ic_attr->attribute_id; ++ value_ret->name = ic_attr->name; ++ value_ret->name_length = ic_attr->length; ++ value_ret->type = ic_attr->type; ++ value_ret->value_length = value_length; ++ value_ret->value = (char *) hotkeys; ++ ++ *value_buf += value_length; ++} ++#endif ++ ++/* get IC values */ ++static void GetAttrHeader (unsigned char *rec, ++ XICAttribute *list, ++ int need_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec attr_head_fr[]; ++ ++ fm = FrameMgrInit (attr_head_fr, (char *) rec, need_swap); ++ /* put data */ ++ FrameMgrPutToken (fm, list->attribute_id); ++ FrameMgrPutToken (fm, list->value_length); ++ FrameMgrFree (fm); ++} ++ ++static void GetCardAttribute (char *rec, XICAttribute *list, int need_swap) ++{ ++ FrameMgr fm; ++ unsigned char *recp = (unsigned char *) rec; ++ ++ GetAttrHeader (recp, list, need_swap); ++ recp += sizeof (CARD16)*2; ++ ++ if (list->value_length == sizeof (CARD8)) ++ { ++ memmove (recp, list->value, list->value_length); ++ } ++ else if (list->value_length == sizeof (CARD16)) ++ { ++ INT16 *value = (INT16 *) list->value; ++ extern XimFrameRec short_fr[]; ++ ++ fm = FrameMgrInit (short_fr, (char *) recp, need_swap); ++ /* put data */ ++ FrameMgrPutToken (fm, *value); ++ FrameMgrFree (fm); ++ } ++ else if (list->value_length == sizeof (CARD32)) ++ { ++ INT32 *value = (INT32 *) list->value; ++ extern XimFrameRec long_fr[]; ++ ++ fm = FrameMgrInit (long_fr, (char *) recp, need_swap); ++ /* put data */ ++ FrameMgrPutToken (fm, *value); ++ FrameMgrFree (fm); ++ } ++ /*endif*/ ++} ++ ++static void GetFontAttribute(char *rec, XICAttribute *list, int need_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec fontset_fr[]; ++ char *base_name = (char *) list->value; ++ unsigned char *recp = (unsigned char *) rec; ++ ++ GetAttrHeader (recp, list, need_swap); ++ recp += sizeof (CARD16)*2; ++ ++ fm = FrameMgrInit (fontset_fr, (char *)recp, need_swap); ++ /* put data */ ++ FrameMgrSetSize (fm, list->value_length); ++ FrameMgrPutToken (fm, list->value_length); ++ FrameMgrPutToken (fm, base_name); ++ FrameMgrFree (fm); ++} ++ ++static void GetRectAttribute (char *rec, XICAttribute *list, int need_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec xrectangle_fr[]; ++ XRectangle *rect = (XRectangle *) list->value; ++ unsigned char *recp = (unsigned char *) rec; ++ ++ GetAttrHeader (recp, list, need_swap); ++ recp += sizeof(CARD16)*2; ++ ++ fm = FrameMgrInit (xrectangle_fr, (char *) recp, need_swap); ++ /* put data */ ++ FrameMgrPutToken (fm, rect->x); ++ FrameMgrPutToken (fm, rect->y); ++ FrameMgrPutToken (fm, rect->width); ++ FrameMgrPutToken (fm, rect->height); ++ FrameMgrFree (fm); ++} ++ ++static void GetPointAttribute (char *rec, XICAttribute *list, int need_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec xpoint_fr[]; ++ XPoint *rect = (XPoint *) list->value; ++ unsigned char *recp = (unsigned char *) rec; ++ ++ GetAttrHeader (recp, list, need_swap); ++ recp += sizeof(CARD16)*2; ++ ++ fm = FrameMgrInit (xpoint_fr, (char *) recp, need_swap); ++ /* put data */ ++ FrameMgrPutToken (fm, rect->x); ++ FrameMgrPutToken (fm, rect->y); ++ FrameMgrFree (fm); ++} ++ ++static int ReadICValue (Xi18n i18n_core, ++ CARD16 icvalue_id, ++ int value_length, ++ void *p, ++ XICAttribute *value_ret, ++ CARD16 *number_ret, ++ int need_swap, ++ void **value_buf) ++{ ++ XICAttr *ic_attr = i18n_core->address.xic_attr; ++ int i; ++ ++ *number_ret = (CARD16) 0; ++ ++ for (i = 0; i < i18n_core->address.ic_attr_num; i++, ic_attr++) ++ { ++ if (ic_attr->attribute_id == icvalue_id) ++ break; ++ /*endif*/ ++ } ++ /*endfor*/ ++ switch (ic_attr->type) ++ { ++ case XimType_NEST: ++ { ++ int total_length = 0; ++ CARD16 attribute_ID; ++ INT16 attribute_length; ++ unsigned char *p1 = (unsigned char *) p; ++ CARD16 ic_len = 0; ++ CARD16 number; ++ FrameMgr fm; ++ extern XimFrameRec attr_head_fr[]; ++ ++ while (total_length < value_length) ++ { ++ fm = FrameMgrInit (attr_head_fr, (char *) p1, need_swap); ++ /* get data */ ++ FrameMgrGetToken (fm, attribute_ID); ++ FrameMgrGetToken (fm, attribute_length); ++ FrameMgrFree (fm); ++ p1 += sizeof (CARD16)*2; ++ ReadICValue (i18n_core, ++ attribute_ID, ++ attribute_length, ++ p1, ++ (value_ret + ic_len), ++ &number, ++ need_swap, ++ value_buf); ++ ic_len++; ++ *number_ret += number; ++ p1 += attribute_length; ++ p1 += IMPAD (attribute_length); ++ total_length += (CARD16) sizeof(CARD16)*2 ++ + (INT16) attribute_length ++ + IMPAD (attribute_length); ++ } ++ /*endwhile*/ ++ return ic_len; ++ } ++ ++ case XimType_CARD8: ++ case XimType_CARD16: ++ case XimType_CARD32: ++ case XimType_Window: ++ SetCardAttribute (value_ret, p, ic_attr, value_length, need_swap, value_buf); ++ *number_ret = (CARD16) 1; ++ return *number_ret; ++ ++ case XimType_XFontSet: ++ SetFontAttribute (value_ret, p, ic_attr, value_length, need_swap, value_buf); ++ *number_ret = (CARD16) 1; ++ return *number_ret; ++ ++ case XimType_XRectangle: ++ SetRectAttribute (value_ret, p, ic_attr, value_length, need_swap, value_buf); ++ *number_ret = (CARD16) 1; ++ return *number_ret; ++ ++ case XimType_XPoint: ++ SetPointAttribute(value_ret, p, ic_attr, value_length, need_swap, value_buf); ++ *number_ret = (CARD16) 1; ++ return *number_ret; ++ ++#if 0 ++ case XimType_XIMHotKeyTriggers: ++ SetHotKeyAttribute (value_ret, p, ic_attr, value_length, need_swap, value_buf); ++ *number_ret = (CARD16) 1; ++ return *number_ret; ++#endif ++ } ++ /*endswitch*/ ++ return 0; ++} ++ ++static XICAttribute *CreateNestedList (CARD16 attr_id, ++ XICAttribute *list, ++ int number, ++ int need_swap) ++{ ++ XICAttribute *nest_list = NULL; ++ register int i; ++ char *values = NULL; ++ char *valuesp; ++ int value_length = 0; ++ ++ if (number == 0) ++ return NULL; ++ /*endif*/ ++ for (i = 0; i < number; i++) ++ { ++ value_length += sizeof (CARD16)*2; ++ value_length += list[i].value_length; ++ value_length += IMPAD (list[i].value_length); ++ } ++ /*endfor*/ ++ if ((values = (char *) malloc (value_length)) == NULL) ++ return NULL; ++ /*endif*/ ++ memset (values, 0, value_length); ++ ++ valuesp = values; ++ for (i = 0; i < number; i++) ++ { ++ switch (list[i].type) ++ { ++ case XimType_CARD8: ++ case XimType_CARD16: ++ case XimType_CARD32: ++ case XimType_Window: ++ GetCardAttribute (valuesp, &list[i], need_swap); ++ break; ++ ++ case XimType_XFontSet: ++ GetFontAttribute (valuesp, &list[i], need_swap); ++ break; ++ ++ case XimType_XRectangle: ++ GetRectAttribute (valuesp, &list[i], need_swap); ++ break; ++ ++ case XimType_XPoint: ++ GetPointAttribute (valuesp, &list[i], need_swap); ++ break; ++ ++#if 0 ++ case XimType_XIMHotKeyTriggers: ++ GetHotKeyAttribute (valuesp, &list[i], need_swap); ++ break; ++#endif ++ } ++ /*endswitch*/ ++ valuesp += sizeof (CARD16)*2; ++ valuesp += list[i].value_length; ++ valuesp += IMPAD(list[i].value_length); ++ } ++ /*endfor*/ ++ ++ nest_list = (XICAttribute *) malloc (sizeof (XICAttribute)); ++ if (nest_list == NULL) ++ return NULL; ++ /*endif*/ ++ memset (nest_list, 0, sizeof (XICAttribute)); ++ nest_list->value = (void *) malloc (value_length); ++ if (nest_list->value == NULL) ++ return NULL; ++ /*endif*/ ++ memset (nest_list->value, 0, sizeof (value_length)); ++ ++ nest_list->attribute_id = attr_id; ++ nest_list->value_length = value_length; ++ memmove (nest_list->value, values, value_length); ++ ++ XFree (values); ++ return nest_list; ++} ++ ++static Bool IsNestedList (Xi18n i18n_core, CARD16 icvalue_id) ++{ ++ XICAttr *ic_attr = i18n_core->address.xic_attr; ++ int i; ++ ++ for (i = 0; i < i18n_core->address.ic_attr_num; i++, ic_attr++) ++ { ++ if (ic_attr->attribute_id == icvalue_id) ++ { ++ if (ic_attr->type == XimType_NEST) ++ return True; ++ /*endif*/ ++ return False; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ return False; ++} ++ ++static Bool IsSeparator (Xi18n i18n_core, CARD16 icvalue_id) ++{ ++ return (i18n_core->address.separatorAttr_id == icvalue_id); ++} ++ ++static int GetICValue (Xi18n i18n_core, ++ XICAttribute *attr_ret, ++ CARD16 *id_list, ++ int list_num) ++{ ++ XICAttr *xic_attr = i18n_core->address.xic_attr; ++ register int i; ++ register int j; ++ register int n; ++ ++ i = ++ n = 0; ++ if (IsNestedList (i18n_core, id_list[i])) ++ { ++ i++; ++ while (i < list_num && !IsSeparator (i18n_core, id_list[i])) ++ { ++ for (j = 0; j < i18n_core->address.ic_attr_num; j++) ++ { ++ if (xic_attr[j].attribute_id == id_list[i]) ++ { ++ attr_ret[n].attribute_id = xic_attr[j].attribute_id; ++ attr_ret[n].name_length = xic_attr[j].length; ++ attr_ret[n].name = malloc (xic_attr[j].length + 1); ++ strcpy(attr_ret[n].name, xic_attr[j].name); ++ attr_ret[n].type = xic_attr[j].type; ++ n++; ++ i++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endwhile*/ ++ } ++ else ++ { ++ for (j = 0; j < i18n_core->address.ic_attr_num; j++) ++ { ++ if (xic_attr[j].attribute_id == id_list[i]) ++ { ++ attr_ret[n].attribute_id = xic_attr[j].attribute_id; ++ attr_ret[n].name_length = xic_attr[j].length; ++ attr_ret[n].name = malloc (xic_attr[j].length + 1); ++ strcpy(attr_ret[n].name, xic_attr[j].name); ++ attr_ret[n].type = xic_attr[j].type; ++ n++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endif*/ ++ return n; ++} ++ ++static void SwapAttributes (XICAttribute *list, ++ int number){ ++ FrameMgr fm; ++ CARD16 c16; ++ extern XimFrameRec short_fr[]; ++ CARD32 c32; ++ extern XimFrameRec long_fr[]; ++ XPoint xpoint; ++ extern XimFrameRec xpoint_fr[]; ++ XRectangle xrect; ++ extern XimFrameRec xrectangle_fr[]; ++ int i; ++ ++ for (i = 0; i < number; ++i, ++list) { ++ if (list->value == NULL) ++ continue; ++ switch (list->type) { ++ case XimType_CARD16: ++ fm = FrameMgrInit (short_fr, (char *)list->value, 1); ++ FrameMgrGetToken (fm, c16); ++ memmove(list->value, &c16, sizeof(CARD16)); ++ FrameMgrFree (fm); ++ break; ++ case XimType_CARD32: ++ case XimType_Window: ++ fm = FrameMgrInit (long_fr, (char *)list->value, 1); ++ FrameMgrGetToken (fm, c32); ++ memmove(list->value, &c32, sizeof(CARD32)); ++ FrameMgrFree (fm); ++ break; ++ case XimType_XRectangle: ++ fm = FrameMgrInit (xrectangle_fr, (char *)list->value, 1); ++ FrameMgrGetToken (fm, xrect); ++ memmove(list->value, &xrect, sizeof(XRectangle)); ++ FrameMgrFree (fm); ++ break; ++ case XimType_XPoint: ++ fm = FrameMgrInit (xpoint_fr, (char *)list->value, 1); ++ FrameMgrGetToken (fm, xpoint); ++ memmove(list->value, &xpoint, sizeof(XPoint)); ++ FrameMgrFree (fm); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++/* called from CreateICMessageProc and SetICValueMessageProc */ ++void _Xi18nChangeIC (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p, ++ int create_flag) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ FmStatus status; ++ CARD16 byte_length; ++ register int total_size; ++ unsigned char *reply = NULL; ++ register int i; ++ register int attrib_num; ++ XICAttribute *attrib_list; ++ XICAttribute pre_attr[IC_SIZE]; ++ XICAttribute sts_attr[IC_SIZE]; ++ XICAttribute ic_attr[IC_SIZE]; ++ CARD16 preedit_ic_num = 0; ++ CARD16 status_ic_num = 0; ++ CARD16 ic_num = 0; ++ CARD16 connect_id = call_data->any.connect_id; ++ IMChangeICStruct *changeic = (IMChangeICStruct *) &call_data->changeic; ++ extern XimFrameRec create_ic_fr[]; ++ extern XimFrameRec create_ic_reply_fr[]; ++ extern XimFrameRec set_ic_values_fr[]; ++ extern XimFrameRec set_ic_values_reply_fr[]; ++ CARD16 input_method_ID; ++ ++ void *value_buf = NULL; ++ void *value_buf_ptr; ++ ++ register int total_value_length = 0; ++ ++ memset (pre_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ memset (sts_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ memset (ic_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ ++ if (create_flag == True) ++ { ++ fm = FrameMgrInit (create_ic_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, byte_length); ++ } ++ else ++ { ++ fm = FrameMgrInit (set_ic_values_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, changeic->icid); ++ FrameMgrGetToken (fm, byte_length); ++ } ++ /*endif*/ ++ attrib_list = (XICAttribute *) malloc (sizeof (XICAttribute)*IC_SIZE); ++ if (!attrib_list) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (attrib_list, 0, sizeof(XICAttribute)*IC_SIZE); ++ ++ attrib_num = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ { ++ void *value; ++ int value_length; ++ ++ FrameMgrGetToken (fm, attrib_list[attrib_num].attribute_id); ++ FrameMgrGetToken (fm, value_length); ++ FrameMgrSetSize (fm, value_length); ++ attrib_list[attrib_num].value_length = value_length; ++ FrameMgrGetToken (fm, value); ++ attrib_list[attrib_num].value = (void *) malloc (value_length + 1); ++ memmove (attrib_list[attrib_num].value, value, value_length); ++ ((char *)attrib_list[attrib_num].value)[value_length] = '\0'; ++ attrib_num++; ++ total_value_length += (value_length + 1); ++ } ++ /*endwhile*/ ++ ++ value_buf = (void *) malloc (total_value_length); ++ value_buf_ptr = value_buf; ++ ++ if (!value_buf) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ for (i = 0; i < attrib_num; i++) ++ XFree (attrib_list[i].value); ++ /*endfor*/ ++ XFree (attrib_list); ++ return; ++ } ++ /*endif*/ ++ ++ for (i = 0; i < attrib_num; i++) ++ { ++ CARD16 number; ++ ++ if (IsNestedList (i18n_core, attrib_list[i].attribute_id)) ++ { ++ if (attrib_list[i].attribute_id ++ == i18n_core->address.preeditAttr_id) ++ { ++ ReadICValue (i18n_core, ++ attrib_list[i].attribute_id, ++ attrib_list[i].value_length, ++ attrib_list[i].value, ++ &pre_attr[preedit_ic_num], ++ &number, ++ _Xi18nNeedSwap(i18n_core, connect_id), ++ &value_buf_ptr); ++ preedit_ic_num += number; ++ } ++ else if (attrib_list[i].attribute_id == i18n_core->address.statusAttr_id) ++ { ++ ReadICValue (i18n_core, ++ attrib_list[i].attribute_id, ++ attrib_list[i].value_length, ++ attrib_list[i].value, ++ &sts_attr[status_ic_num], ++ &number, ++ _Xi18nNeedSwap (i18n_core, connect_id), ++ &value_buf_ptr); ++ status_ic_num += number; ++ } ++ else ++ { ++ /* another nested list.. possible? */ ++ } ++ /*endif*/ ++ } ++ else ++ { ++ ReadICValue (i18n_core, ++ attrib_list[i].attribute_id, ++ attrib_list[i].value_length, ++ attrib_list[i].value, ++ &ic_attr[ic_num], ++ &number, ++ _Xi18nNeedSwap (i18n_core, connect_id), ++ &value_buf_ptr); ++ ic_num += number; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ for (i = 0; i < attrib_num; i++) ++ XFree (attrib_list[i].value); ++ /*endfor*/ ++ XFree (attrib_list); ++ ++ FrameMgrFree (fm); ++ ++ changeic->preedit_attr_num = preedit_ic_num; ++ changeic->status_attr_num = status_ic_num; ++ changeic->ic_attr_num = ic_num; ++ changeic->preedit_attr = pre_attr; ++ changeic->status_attr = sts_attr; ++ changeic->ic_attr = ic_attr; ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) { ++ XFree (value_buf); ++ return; ++ } ++ /*endif*/ ++ } ++ ++ XFree (value_buf); ++ ++ /*endif*/ ++ if (create_flag == True) ++ { ++ fm = FrameMgrInit (create_ic_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ } ++ else ++ { ++ fm = FrameMgrInit (set_ic_values_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ } ++ /*endif*/ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, changeic->icid); ++ ++ if (create_flag == True) ++ { ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_CREATE_IC_REPLY, ++ 0, ++ reply, ++ total_size); ++ } ++ else ++ { ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_SET_IC_VALUES_REPLY, ++ 0, ++ reply, ++ total_size); ++ } ++ /*endif*/ ++ if (create_flag == True) ++ { ++ int on_key_num = i18n_core->address.on_keys.count_keys; ++ int off_key_num = i18n_core->address.off_keys.count_keys; ++ ++ if (on_key_num == 0 && off_key_num == 0) ++ { ++ long mask; ++ ++ if (i18n_core->address.imvalue_mask & I18N_FILTERMASK) ++ mask = i18n_core->address.filterevent_mask; ++ else ++ mask = DEFAULT_FILTER_MASK; ++ /*endif*/ ++ /* static event flow is default */ ++ _Xi18nSetEventMask (ims, ++ connect_id, ++ input_method_ID, ++ changeic->icid, ++ mask, ++ ~mask); ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ FrameMgrFree (fm); ++ XFree(reply); ++} ++ ++/* called from GetICValueMessageProc */ ++void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ FmStatus status; ++ extern XimFrameRec get_ic_values_fr[]; ++ extern XimFrameRec get_ic_values_reply_fr[]; ++ CARD16 byte_length; ++ register int total_size; ++ unsigned char *reply = NULL; ++ XICAttribute *preedit_ret = NULL; ++ XICAttribute *status_ret = NULL; ++ register int i; ++ register int number; ++ int iter_count; ++ CARD16 *attrID_list; ++ XICAttribute pre_attr[IC_SIZE]; ++ XICAttribute sts_attr[IC_SIZE]; ++ XICAttribute ic_attr[IC_SIZE]; ++ CARD16 pre_count = 0; ++ CARD16 sts_count = 0; ++ CARD16 ic_count = 0; ++ IMChangeICStruct *getic = (IMChangeICStruct *) &call_data->changeic; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ memset (pre_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ memset (sts_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ memset (ic_attr, 0, sizeof (XICAttribute)*IC_SIZE); ++ ++ fm = FrameMgrInit (get_ic_values_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, getic->icid); ++ FrameMgrGetToken (fm, byte_length); ++ ++ attrID_list = (CARD16 *) malloc (sizeof (CARD16)*IC_SIZE); /* bogus */ ++ memset (attrID_list, 0, sizeof (CARD16)*IC_SIZE); ++ ++ number = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ FrameMgrGetToken (fm, attrID_list[number++]); ++ /*endwhile*/ ++ FrameMgrFree (fm); ++ ++ i = 0; ++ while (i < number) ++ { ++ int read_number; ++ ++ if (IsNestedList (i18n_core, attrID_list[i])) ++ { ++ if (attrID_list[i] == i18n_core->address.preeditAttr_id) ++ { ++ read_number = GetICValue (i18n_core, ++ &pre_attr[pre_count], ++ &attrID_list[i], ++ number); ++ i += read_number + 1; ++ pre_count += read_number; ++ } ++ else if (attrID_list[i] == i18n_core->address.statusAttr_id) ++ { ++ read_number = GetICValue (i18n_core, ++ &sts_attr[sts_count], ++ &attrID_list[i], ++ number); ++ i += read_number + 1; ++ sts_count += read_number; ++ } ++ else ++ { ++ /* another nested list.. possible? */ ++ } ++ /*endif*/ ++ } ++ else ++ { ++ read_number = GetICValue (i18n_core, ++ &ic_attr[ic_count], ++ &attrID_list[i], ++ number); ++ i += read_number; ++ ic_count += read_number; ++ } ++ /*endif*/ ++ } ++ /*endwhile*/ ++ getic->preedit_attr_num = pre_count; ++ getic->status_attr_num = sts_count; ++ getic->ic_attr_num = ic_count; ++ getic->preedit_attr = pre_attr; ++ getic->status_attr = sts_attr; ++ getic->ic_attr = ic_attr; ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ if (_Xi18nNeedSwap (i18n_core, connect_id)) ++ SwapAttributes(getic->ic_attr, getic->ic_attr_num); ++ } ++ /*endif*/ ++ iter_count = getic->ic_attr_num; ++ ++ preedit_ret = CreateNestedList (i18n_core->address.preeditAttr_id, ++ getic->preedit_attr, ++ getic->preedit_attr_num, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ if (preedit_ret) ++ iter_count++; ++ /*endif*/ ++ status_ret = CreateNestedList (i18n_core->address.statusAttr_id, ++ getic->status_attr, ++ getic->status_attr_num, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ if (status_ret) ++ iter_count++; ++ /*endif*/ ++ ++ fm = FrameMgrInit (get_ic_values_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set iteration count for list of ic_attribute */ ++ FrameMgrSetIterCount (fm, iter_count); ++ ++ /* set length of BARRAY item in xicattribute_fr */ ++ for (i = 0; i < (int) getic->ic_attr_num; i++) ++ FrameMgrSetSize (fm, ic_attr[i].value_length); ++ /*endfor*/ ++ ++ if (preedit_ret) ++ FrameMgrSetSize (fm, preedit_ret->value_length); ++ /*endif*/ ++ if (status_ret) ++ FrameMgrSetSize (fm, status_ret->value_length); ++ /*endif*/ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (reply == NULL) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, getic->icid); ++ ++ for (i = 0; i < (int) getic->ic_attr_num; i++) ++ { ++ FrameMgrPutToken (fm, ic_attr[i].attribute_id); ++ FrameMgrPutToken (fm, ic_attr[i].value_length); ++ FrameMgrPutToken (fm, ic_attr[i].value); ++ } ++ /*endfor*/ ++ if (preedit_ret) ++ { ++ FrameMgrPutToken (fm, preedit_ret->attribute_id); ++ FrameMgrPutToken (fm, preedit_ret->value_length); ++ FrameMgrPutToken (fm, preedit_ret->value); ++ } ++ /*endif*/ ++ if (status_ret) ++ { ++ FrameMgrPutToken (fm, status_ret->attribute_id); ++ FrameMgrPutToken (fm, status_ret->value_length); ++ FrameMgrPutToken (fm, status_ret->value); ++ } ++ /*endif*/ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_GET_IC_VALUES_REPLY, ++ 0, ++ reply, ++ total_size); ++ XFree (reply); ++ XFree (attrID_list); ++ ++ for (i = 0; i < (int) getic->ic_attr_num; i++) ++ { ++ if (getic->ic_attr[i].name) ++ XFree (getic->ic_attr[i].name); ++ /*endif*/ ++ if (getic->ic_attr[i].value) ++ XFree (getic->ic_attr[i].value); ++ /*endif*/ ++ } ++ /*endfor*/ ++ for (i = 0; i < (int) getic->preedit_attr_num; i++) ++ { ++ if (getic->preedit_attr[i].name) ++ XFree (getic->preedit_attr[i].name); ++ /*endif*/ ++ if (getic->preedit_attr[i].value) ++ XFree (getic->preedit_attr[i].value); ++ /*endif*/ ++ } ++ /*endfor*/ ++ for (i = 0; i < (int) getic->status_attr_num; i++) ++ { ++ if (getic->status_attr[i].name) ++ XFree (getic->status_attr[i].name); ++ /*endif*/ ++ if (getic->status_attr[i].value) ++ XFree (getic->status_attr[i].value); ++ /*endif*/ ++ } ++ /*endfor*/ ++ ++ if (preedit_ret) ++ { ++ XFree (preedit_ret->value); ++ XFree (preedit_ret); ++ } ++ /*endif*/ ++ if (status_ret) ++ { ++ XFree (status_ret->value); ++ XFree (status_ret); ++ } ++ /*endif*/ ++ FrameMgrFree (fm); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nMethod.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nMethod.c +new file mode 100644 +index 0000000..c8b43df +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nMethod.c +@@ -0,0 +1,1150 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#ifndef NEED_EVENTS ++#define NEED_EVENTS ++#endif ++#include ++#undef NEED_EVENTS ++#include "FrameMgr.h" ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "XimFunc.h" ++ ++extern Xi18nClient *_Xi18nFindClient (Xi18n, CARD16); ++ ++static void *xi18n_setup (Display *, XIMArg *); ++static Status xi18n_openIM (XIMS); ++static Status xi18n_closeIM (XIMS); ++static char *xi18n_setIMValues (XIMS, XIMArg *); ++static char *xi18n_getIMValues (XIMS, XIMArg *); ++static Status xi18n_forwardEvent (XIMS, XPointer); ++static Status xi18n_commit (XIMS, XPointer); ++static int xi18n_callCallback (XIMS, XPointer); ++static int xi18n_preeditStart (XIMS, XPointer); ++static int xi18n_preeditEnd (XIMS, XPointer); ++static int xi18n_syncXlib (XIMS, XPointer); ++ ++#ifndef XIM_SERVERS ++#define XIM_SERVERS "XIM_SERVERS" ++#endif ++static Atom XIM_Servers = None; ++ ++ ++IMMethodsRec Xi18n_im_methods = ++{ ++ xi18n_setup, ++ xi18n_openIM, ++ xi18n_closeIM, ++ xi18n_setIMValues, ++ xi18n_getIMValues, ++ xi18n_forwardEvent, ++ xi18n_commit, ++ xi18n_callCallback, ++ xi18n_preeditStart, ++ xi18n_preeditEnd, ++ xi18n_syncXlib, ++}; ++ ++extern Bool _Xi18nCheckXAddress (Xi18n, TransportSW *, char *); ++extern Bool _Xi18nCheckTransAddress (Xi18n, TransportSW *, char *); ++ ++TransportSW _TransR[] = ++{ ++ {"X", 1, _Xi18nCheckXAddress}, ++#ifdef TCPCONN ++ {"tcp", 3, _Xi18nCheckTransAddress}, ++ {"local", 5, _Xi18nCheckTransAddress}, ++#endif ++#ifdef DNETCONN ++ {"decnet", 6, _Xi18nCheckTransAddress}, ++#endif ++ {(char *) NULL, 0, (Bool (*) ()) NULL} ++}; ++ ++static Bool GetInputStyles (Xi18n i18n_core, XIMStyles **p_style) ++{ ++ Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address; ++ XIMStyles *p; ++ int i; ++ ++ p = &address->input_styles; ++ if ((*p_style = (XIMStyles *) malloc (sizeof (XIMStyles) ++ + p->count_styles*sizeof (XIMStyle))) ++ == NULL) ++ { ++ return False; ++ } ++ /*endif*/ ++ (*p_style)->count_styles = p->count_styles; ++ (*p_style)->supported_styles = (XIMStyle *) ((XPointer) *p_style + sizeof (XIMStyles)); ++ for (i = 0; i < (int) p->count_styles; i++) ++ (*p_style)->supported_styles[i] = p->supported_styles[i]; ++ /*endfor*/ ++ return True; ++} ++ ++static Bool GetOnOffKeys (Xi18n i18n_core, long mask, XIMTriggerKeys **p_key) ++{ ++ Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address; ++ XIMTriggerKeys *p; ++ int i; ++ ++ if (mask & I18N_ON_KEYS) ++ p = &address->on_keys; ++ else ++ p = &address->off_keys; ++ /*endif*/ ++ if ((*p_key = (XIMTriggerKeys *) malloc (sizeof(XIMTriggerKeys) ++ + p->count_keys*sizeof(XIMTriggerKey))) ++ == NULL) ++ { ++ return False; ++ } ++ /*endif*/ ++ (*p_key)->count_keys = p->count_keys; ++ (*p_key)->keylist = ++ (XIMTriggerKey *) ((XPointer) *p_key + sizeof(XIMTriggerKeys)); ++ for (i = 0; i < (int) p->count_keys; i++) ++ { ++ (*p_key)->keylist[i].keysym = p->keylist[i].keysym; ++ (*p_key)->keylist[i].modifier = p->keylist[i].modifier; ++ (*p_key)->keylist[i].modifier_mask = p->keylist[i].modifier_mask; ++ } ++ /*endfor*/ ++ return True; ++} ++ ++static Bool GetEncodings(Xi18n i18n_core, XIMEncodings **p_encoding) ++{ ++ Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address; ++ XIMEncodings *p; ++ int i; ++ ++ p = &address->encoding_list; ++ ++ if ((*p_encoding = (XIMEncodings *) malloc (sizeof (XIMEncodings) ++ + p->count_encodings*sizeof(XIMEncoding))) == NULL) ++ { ++ return False; ++ } ++ /*endif*/ ++ (*p_encoding)->count_encodings = p->count_encodings; ++ (*p_encoding)->supported_encodings = ++ (XIMEncoding *) ((XPointer)*p_encoding + sizeof (XIMEncodings)); ++ for (i = 0; i < (int) p->count_encodings; i++) ++ { ++ (*p_encoding)->supported_encodings[i] ++ = (char *) malloc (strlen (p->supported_encodings[i]) + 1); ++ strcpy ((*p_encoding)->supported_encodings[i], ++ p->supported_encodings[i]); ++ } ++ /*endif*/ ++ return True; ++} ++ ++static char *ParseArgs (Xi18n i18n_core, int mode, XIMArg *args) ++{ ++ Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address; ++ XIMArg *p; ++ ++ if (mode == I18N_OPEN || mode == I18N_SET) ++ { ++ for (p = args; p->name != NULL; p++) ++ { ++ if (strcmp (p->name, IMLocale) == 0) ++ { ++ if (address->imvalue_mask & I18N_IM_LOCALE) ++ return IMLocale; ++ /*endif*/ ++ address->im_locale = (char *) malloc (strlen (p->value) + 1); ++ if (!address->im_locale) ++ return IMLocale; ++ /*endif*/ ++ strcpy (address->im_locale, p->value); ++ address->imvalue_mask |= I18N_IM_LOCALE; ++ } ++ else if (strcmp (p->name, IMServerTransport) == 0) ++ { ++ if (address->imvalue_mask & I18N_IM_ADDRESS) ++ return IMServerTransport; ++ /*endif*/ ++ address->im_addr = (char *) malloc (strlen (p->value) + 1); ++ if (!address->im_addr) ++ return IMServerTransport; ++ /*endif*/ ++ strcpy(address->im_addr, p->value); ++ address->imvalue_mask |= I18N_IM_ADDRESS; ++ } ++ else if (strcmp (p->name, IMServerName) == 0) ++ { ++ if (address->imvalue_mask & I18N_IM_NAME) ++ return IMServerName; ++ /*endif*/ ++ address->im_name = (char *) malloc (strlen (p->value) + 1); ++ if (!address->im_name) ++ return IMServerName; ++ /*endif*/ ++ strcpy (address->im_name, p->value); ++ address->imvalue_mask |= I18N_IM_NAME; ++ } ++ else if (strcmp (p->name, IMServerWindow) == 0) ++ { ++ if (address->imvalue_mask & I18N_IMSERVER_WIN) ++ return IMServerWindow; ++ /*endif*/ ++ address->im_window = (Window) p->value; ++ address->imvalue_mask |= I18N_IMSERVER_WIN; ++ } ++ else if (strcmp (p->name, IMInputStyles) == 0) ++ { ++ if (address->imvalue_mask & I18N_INPUT_STYLES) ++ return IMInputStyles; ++ /*endif*/ ++ address->input_styles.count_styles = ++ ((XIMStyles*)p->value)->count_styles; ++ address->input_styles.supported_styles = ++ (XIMStyle *) malloc (sizeof (XIMStyle)*address->input_styles.count_styles); ++ if (address->input_styles.supported_styles == (XIMStyle *) NULL) ++ return IMInputStyles; ++ /*endif*/ ++ memmove (address->input_styles.supported_styles, ++ ((XIMStyles *) p->value)->supported_styles, ++ sizeof (XIMStyle)*address->input_styles.count_styles); ++ address->imvalue_mask |= I18N_INPUT_STYLES; ++ } ++ else if (strcmp (p->name, IMProtocolHandler) == 0) ++ { ++ address->improto = (IMProtoHandler) p->value; ++ address->imvalue_mask |= I18N_IM_HANDLER; ++ } ++ else if (strcmp (p->name, IMOnKeysList) == 0) ++ { ++ if (address->imvalue_mask & I18N_ON_KEYS) ++ return IMOnKeysList; ++ /*endif*/ ++ address->on_keys.count_keys = ++ ((XIMTriggerKeys *) p->value)->count_keys; ++ address->on_keys.keylist = ++ (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->on_keys.count_keys); ++ if (address->on_keys.keylist == (XIMTriggerKey *) NULL) ++ return IMOnKeysList; ++ /*endif*/ ++ memmove (address->on_keys.keylist, ++ ((XIMTriggerKeys *) p->value)->keylist, ++ sizeof (XIMTriggerKey)*address->on_keys.count_keys); ++ address->imvalue_mask |= I18N_ON_KEYS; ++ } ++ else if (strcmp (p->name, IMOffKeysList) == 0) ++ { ++ if (address->imvalue_mask & I18N_OFF_KEYS) ++ return IMOffKeysList; ++ /*endif*/ ++ address->off_keys.count_keys = ++ ((XIMTriggerKeys *) p->value)->count_keys; ++ address->off_keys.keylist = ++ (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->off_keys.count_keys); ++ if (address->off_keys.keylist == (XIMTriggerKey *) NULL) ++ return IMOffKeysList; ++ /*endif*/ ++ memmove (address->off_keys.keylist, ++ ((XIMTriggerKeys *) p->value)->keylist, ++ sizeof (XIMTriggerKey)*address->off_keys.count_keys); ++ address->imvalue_mask |= I18N_OFF_KEYS; ++ } ++ else if (strcmp (p->name, IMEncodingList) == 0) ++ { ++ if (address->imvalue_mask & I18N_ENCODINGS) ++ return IMEncodingList; ++ /*endif*/ ++ address->encoding_list.count_encodings = ++ ((XIMEncodings *) p->value)->count_encodings; ++ address->encoding_list.supported_encodings = ++ (XIMEncoding *) malloc (sizeof (XIMEncoding)*address->encoding_list.count_encodings); ++ if (address->encoding_list.supported_encodings ++ == (XIMEncoding *) NULL) ++ { ++ return IMEncodingList; ++ } ++ /*endif*/ ++ memmove (address->encoding_list.supported_encodings, ++ ((XIMEncodings *) p->value)->supported_encodings, ++ sizeof (XIMEncoding)*address->encoding_list.count_encodings); ++ address->imvalue_mask |= I18N_ENCODINGS; ++ } ++ else if (strcmp (p->name, IMFilterEventMask) == 0) ++ { ++ if (address->imvalue_mask & I18N_FILTERMASK) ++ return IMFilterEventMask; ++ /*endif*/ ++ address->filterevent_mask = (long) p->value; ++ address->imvalue_mask |= I18N_FILTERMASK; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ if (mode == I18N_OPEN) ++ { ++ /* check mandatory IM values */ ++ if (!(address->imvalue_mask & I18N_IM_LOCALE)) ++ { ++ /* locales must be set in IMOpenIM */ ++ return IMLocale; ++ } ++ /*endif*/ ++ if (!(address->imvalue_mask & I18N_IM_ADDRESS)) ++ { ++ /* address must be set in IMOpenIM */ ++ return IMServerTransport; ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ else if (mode == I18N_GET) ++ { ++ for (p = args; p->name != NULL; p++) ++ { ++ if (strcmp (p->name, IMLocale) == 0) ++ { ++ p->value = (char *) malloc (strlen (address->im_locale) + 1); ++ if (!p->value) ++ return IMLocale; ++ /*endif*/ ++ strcpy (p->value, address->im_locale); ++ } ++ else if (strcmp (p->name, IMServerTransport) == 0) ++ { ++ p->value = (char *) malloc (strlen (address->im_addr) + 1); ++ if (!p->value) ++ return IMServerTransport; ++ /*endif*/ ++ strcpy (p->value, address->im_addr); ++ } ++ else if (strcmp (p->name, IMServerName) == 0) ++ { ++ if (address->imvalue_mask & I18N_IM_NAME) ++ { ++ p->value = (char *) malloc (strlen (address->im_name) + 1); ++ if (!p->value) ++ return IMServerName; ++ /*endif*/ ++ strcpy (p->value, address->im_name); ++ } ++ else ++ { ++ return IMServerName; ++ } ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMServerWindow) == 0) ++ { ++ if (address->imvalue_mask & I18N_IMSERVER_WIN) ++ *((Window *) (p->value)) = address->im_window; ++ else ++ return IMServerWindow; ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMInputStyles) == 0) ++ { ++ if (GetInputStyles (i18n_core, ++ (XIMStyles **) p->value) == False) ++ { ++ return IMInputStyles; ++ } ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMProtocolHandler) == 0) ++ { ++ if (address->imvalue_mask & I18N_IM_HANDLER) ++ *((IMProtoHandler *) (p->value)) = address->improto; ++ else ++ return IMProtocolHandler; ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMOnKeysList) == 0) ++ { ++ if (address->imvalue_mask & I18N_ON_KEYS) ++ { ++ if (GetOnOffKeys (i18n_core, ++ I18N_ON_KEYS, ++ (XIMTriggerKeys **) p->value) == False) ++ { ++ return IMOnKeysList; ++ } ++ /*endif*/ ++ } ++ else ++ { ++ return IMOnKeysList; ++ } ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMOffKeysList) == 0) ++ { ++ if (address->imvalue_mask & I18N_OFF_KEYS) ++ { ++ if (GetOnOffKeys (i18n_core, ++ I18N_OFF_KEYS, ++ (XIMTriggerKeys **) p->value) == False) ++ { ++ return IMOffKeysList; ++ } ++ /*endif*/ ++ } ++ else ++ { ++ return IMOffKeysList; ++ } ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMEncodingList) == 0) ++ { ++ if (address->imvalue_mask & I18N_ENCODINGS) ++ { ++ if (GetEncodings (i18n_core, ++ (XIMEncodings **) p->value) == False) ++ { ++ return IMEncodingList; ++ } ++ /*endif*/ ++ } ++ else ++ { ++ return IMEncodingList; ++ } ++ /*endif*/ ++ } ++ else if (strcmp (p->name, IMFilterEventMask) == 0) ++ { ++ if (address->imvalue_mask & I18N_FILTERMASK) ++ *((long *) (p->value)) = address->filterevent_mask; ++ else ++ return IMFilterEventMask; ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endif*/ ++ return NULL; ++} ++ ++static int CheckIMName (Xi18n i18n_core) ++{ ++ char *address = i18n_core->address.im_addr; ++ int i; ++ ++ for (i = 0; _TransR[i].transportname; i++) ++ { ++ while (*address == ' ' || *address == '\t') ++ address++; ++ /*endwhile*/ ++ if (strncmp (address, ++ _TransR[i].transportname, ++ _TransR[i].namelen) == 0 ++ && ++ address[_TransR[i].namelen] == '/') ++ { ++ if (_TransR[i].checkAddr (i18n_core, ++ &_TransR[i], ++ address + _TransR[i].namelen + 1) == True) ++ { ++ return True; ++ } ++ /*endif*/ ++ return False; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ return False; ++} ++ ++static int SetXi18nSelectionOwner(Xi18n i18n_core) ++{ ++ Display *dpy = i18n_core->address.dpy; ++ Window ims_win = i18n_core->address.im_window; ++ Window root = RootWindow (dpy, DefaultScreen (dpy)); ++ Atom realtype; ++ int realformat; ++ unsigned long bytesafter; ++ long *data=NULL; ++ unsigned long length; ++ Atom atom; ++ int i; ++ int found; ++ int forse = False; ++ char buf[256]; ++ ++ (void)snprintf(buf, 256, "@server=%s", i18n_core->address.im_name); ++ if ((atom = XInternAtom(dpy, buf, False)) == 0) ++ return False; ++ i18n_core->address.selection = atom; ++ ++ if (XIM_Servers == None) ++ XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False); ++ /*endif*/ ++ XGetWindowProperty (dpy, ++ root, ++ XIM_Servers, ++ 0L, ++ 1000000L, ++ False, ++ XA_ATOM, ++ &realtype, ++ &realformat, ++ &length, ++ &bytesafter, ++ (unsigned char **) (&data)); ++ if (realtype != None && (realtype != XA_ATOM || realformat != 32)) { ++ if (data != NULL) ++ XFree ((char *) data); ++ return False; ++ } ++ ++ found = False; ++ for (i = 0; i < length; i++) { ++ if (data[i] == atom) { ++ Window owner; ++ found = True; ++ if ((owner = XGetSelectionOwner (dpy, atom)) != ims_win) { ++ if (owner == None || forse == True) ++ XSetSelectionOwner (dpy, atom, ims_win, CurrentTime); ++ else ++ return False; ++ } ++ break; ++ } ++ } ++ ++ if (found == False) { ++ XSetSelectionOwner (dpy, atom, ims_win, CurrentTime); ++ XChangeProperty (dpy, ++ root, ++ XIM_Servers, ++ XA_ATOM, ++ 32, ++ PropModePrepend, ++ (unsigned char *) &atom, ++ 1); ++ } ++ else { ++ /* ++ * We always need to generate the PropertyNotify to the Root Window ++ */ ++ XChangeProperty (dpy, ++ root, ++ XIM_Servers, ++ XA_ATOM, ++ 32, ++ PropModePrepend, ++ (unsigned char *) data, ++ 0); ++ } ++ if (data != NULL) ++ XFree ((char *) data); ++ ++ /* Intern "LOCALES" and "TRANSOPORT" Target Atoms */ ++ i18n_core->address.Localename = XInternAtom (dpy, LOCALES, False); ++ i18n_core->address.Transportname = XInternAtom (dpy, TRANSPORT, False); ++ return (XGetSelectionOwner (dpy, atom) == ims_win); ++} ++ ++static int DeleteXi18nAtom(Xi18n i18n_core) ++{ ++ Display *dpy = i18n_core->address.dpy; ++ Window root = RootWindow (dpy, DefaultScreen (dpy)); ++ Atom realtype; ++ int realformat; ++ unsigned long bytesafter; ++ long *data=NULL; ++ unsigned long length; ++ Atom atom; ++ int i, ret; ++ int found; ++ char buf[256]; ++ ++ (void)snprintf(buf, 256, "@server=%s", i18n_core->address.im_name); ++ if ((atom = XInternAtom(dpy, buf, False)) == 0) ++ return False; ++ i18n_core->address.selection = atom; ++ ++ if (XIM_Servers == None) ++ XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False); ++ XGetWindowProperty (dpy, ++ root, ++ XIM_Servers, ++ 0L, ++ 1000000L, ++ False, ++ XA_ATOM, ++ &realtype, ++ &realformat, ++ &length, ++ &bytesafter, ++ (unsigned char **) (&data)); ++ if (realtype != XA_ATOM || realformat != 32) { ++ if (data != NULL) ++ XFree ((char *) data); ++ return False; ++ } ++ ++ found = False; ++ for (i = 0; i < length; i++) { ++ if (data[i] == atom) { ++ found = True; ++ break; ++ } ++ } ++ ++ if (found == True) { ++ for (i=i+1; iaddress.dpy = dpy; ++ ++ if (ParseArgs (i18n_core, I18N_OPEN, args) != NULL) ++ { ++ XFree (i18n_core); ++ return NULL; ++ } ++ /*endif*/ ++ if (*(char *) &endian) ++ i18n_core->address.im_byteOrder = 'l'; ++ else ++ i18n_core->address.im_byteOrder = 'B'; ++ /*endif*/ ++ ++ /* install IMAttr and ICAttr list in i18n_core */ ++ _Xi18nInitAttrList (i18n_core); ++ ++ /* install IMExtension list in i18n_core */ ++ _Xi18nInitExtension (i18n_core); ++ ++ return i18n_core; ++} ++ ++static void ReturnSelectionNotify (Xi18n i18n_core, XSelectionRequestEvent *ev) ++{ ++ XEvent event; ++ Display *dpy = i18n_core->address.dpy; ++ char buf[4096]; ++ ++ event.type = SelectionNotify; ++ event.xselection.requestor = ev->requestor; ++ event.xselection.selection = ev->selection; ++ event.xselection.target = ev->target; ++ event.xselection.time = ev->time; ++ event.xselection.property = ev->property; ++ if (ev->target == i18n_core->address.Localename) ++ { ++ snprintf (buf, 4096, "@locale=%s", i18n_core->address.im_locale); ++ } ++ else if (ev->target == i18n_core->address.Transportname) ++ { ++ snprintf (buf, 4096, "@transport=%s", i18n_core->address.im_addr); ++ } ++ /*endif*/ ++ XChangeProperty (dpy, ++ event.xselection.requestor, ++ ev->target, ++ ev->target, ++ 8, ++ PropModeReplace, ++ (unsigned char *) buf, ++ strlen (buf)); ++ XSendEvent (dpy, event.xselection.requestor, False, NoEventMask, &event); ++ XFlush (i18n_core->address.dpy); ++} ++ ++static Bool WaitXSelectionRequest (Display *dpy, ++ Window win, ++ XEvent *ev, ++ XPointer client_data) ++{ ++ XIMS ims = (XIMS) client_data; ++ Xi18n i18n_core = ims->protocol; ++ ++ if (((XSelectionRequestEvent *) ev)->selection ++ == i18n_core->address.selection) ++ { ++ ReturnSelectionNotify (i18n_core, (XSelectionRequestEvent *) ev); ++ return True; ++ } ++ /*endif*/ ++ return False; ++} ++ ++static Status xi18n_openIM(XIMS ims) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Display *dpy = i18n_core->address.dpy; ++ ++ if (!CheckIMName (i18n_core) ++ || ++ !SetXi18nSelectionOwner (i18n_core) ++ || ++ !i18n_core->methods.begin (ims)) ++ { ++ XFree (i18n_core->address.im_name); ++ XFree (i18n_core->address.im_locale); ++ XFree (i18n_core->address.im_addr); ++ XFree (i18n_core); ++ return False; ++ } ++ /*endif*/ ++ ++ _XRegisterFilterByType (dpy, ++ i18n_core->address.im_window, ++ SelectionRequest, ++ SelectionRequest, ++ WaitXSelectionRequest, ++ (XPointer)ims); ++ XFlush(dpy); ++ return True; ++} ++ ++static Status xi18n_closeIM(XIMS ims) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Display *dpy = i18n_core->address.dpy; ++ ++ DeleteXi18nAtom(i18n_core); ++ if (!i18n_core->methods.end (ims)) ++ return False; ++ ++ _XUnregisterFilter (dpy, ++ i18n_core->address.im_window, ++ WaitXSelectionRequest, ++ (XPointer)ims); ++ XFree (i18n_core->address.im_name); ++ XFree (i18n_core->address.im_locale); ++ XFree (i18n_core->address.im_addr); ++ XFree (i18n_core); ++ return True; ++} ++ ++static char *xi18n_setIMValues (XIMS ims, XIMArg *args) ++{ ++ Xi18n i18n_core = ims->protocol; ++ char *ret; ++ ++ if ((ret = ParseArgs (i18n_core, I18N_SET, args)) != NULL) ++ return ret; ++ /*endif*/ ++ return NULL; ++} ++ ++static char *xi18n_getIMValues (XIMS ims, XIMArg *args) ++{ ++ Xi18n i18n_core = ims->protocol; ++ char *ret; ++ ++ if ((ret = ParseArgs (i18n_core, I18N_GET, args)) != NULL) ++ return ret; ++ /*endif*/ ++ return NULL; ++} ++ ++static void EventToWireEvent (XEvent *ev, xEvent *event, ++ CARD16 *serial, Bool byte_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec wire_keyevent_fr[]; ++ extern XimFrameRec short_fr[]; ++ BYTE b; ++ CARD16 c16; ++ CARD32 c32; ++ ++ *serial = (CARD16)(ev->xany.serial >> 16); ++ switch (ev->type) { ++ case KeyPress: ++ case KeyRelease: ++ { ++ XKeyEvent *kev = (XKeyEvent*)ev; ++ /* create FrameMgr */ ++ fm = FrameMgrInit(wire_keyevent_fr, (char *)(&(event->u)), byte_swap); ++ ++ /* set values */ ++ b = (BYTE)kev->type; FrameMgrPutToken(fm, b); ++ b = (BYTE)kev->keycode; FrameMgrPutToken(fm, b); ++ c16 = (CARD16)(kev->serial & (unsigned long)0xffff); ++ FrameMgrPutToken(fm, c16); ++ c32 = (CARD32)kev->time; FrameMgrPutToken(fm, c32); ++ c32 = (CARD32)kev->root; FrameMgrPutToken(fm, c32); ++ c32 = (CARD32)kev->window; FrameMgrPutToken(fm, c32); ++ c32 = (CARD32)kev->subwindow; FrameMgrPutToken(fm, c32); ++ c16 = (CARD16)kev->x_root; FrameMgrPutToken(fm, c16); ++ c16 = (CARD16)kev->y_root; FrameMgrPutToken(fm, c16); ++ c16 = (CARD16)kev->x; FrameMgrPutToken(fm, c16); ++ c16 = (CARD16)kev->y; FrameMgrPutToken(fm, c16); ++ c16 = (CARD16)kev->state; FrameMgrPutToken(fm, c16); ++ b = (BYTE)kev->same_screen; FrameMgrPutToken(fm, b); ++ } ++ break; ++ default: ++ /* create FrameMgr */ ++ fm = FrameMgrInit(short_fr, (char *)(&(event->u.u.sequenceNumber)), ++ byte_swap); ++ c16 = (CARD16)(ev->xany.serial & (unsigned long)0xffff); ++ FrameMgrPutToken(fm, c16); ++ break; ++ } ++ /* free FrameMgr */ ++ FrameMgrFree(fm); ++} ++ ++static Status xi18n_forwardEvent (XIMS ims, XPointer xp) ++{ ++ Xi18n i18n_core = ims->protocol; ++ IMForwardEventStruct *call_data = (IMForwardEventStruct *)xp; ++ FrameMgr fm; ++ extern XimFrameRec forward_event_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ unsigned char *replyp; ++ CARD16 serial; ++ int event_size; ++ Xi18nClient *client; ++ ++ client = (Xi18nClient *) _Xi18nFindClient (i18n_core, call_data->connect_id); ++ ++ /* create FrameMgr */ ++ fm = FrameMgrInit (forward_event_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, call_data->connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ event_size = sizeof (xEvent); ++ reply = (unsigned char *) malloc (total_size + event_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, ++ call_data->connect_id, ++ XIM_ERROR, ++ 0, ++ 0, ++ 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size + event_size); ++ FrameMgrSetBuffer (fm, reply); ++ replyp = reply; ++ ++ call_data->sync_bit = 1; /* always sync */ ++ client->sync = True; ++ ++ FrameMgrPutToken (fm, call_data->connect_id); ++ FrameMgrPutToken (fm, call_data->icid); ++ FrameMgrPutToken (fm, call_data->sync_bit); ++ ++ replyp += total_size; ++ EventToWireEvent (&(call_data->event), ++ (xEvent *) replyp, ++ &serial, ++ _Xi18nNeedSwap (i18n_core, call_data->connect_id)); ++ ++ FrameMgrPutToken (fm, serial); ++ ++ _Xi18nSendMessage (ims, ++ call_data->connect_id, ++ XIM_FORWARD_EVENT, ++ 0, ++ reply, ++ total_size + event_size); ++ ++ XFree (reply); ++ FrameMgrFree (fm); ++ ++ return True; ++} ++ ++static Status xi18n_commit (XIMS ims, XPointer xp) ++{ ++ Xi18n i18n_core = ims->protocol; ++ IMCommitStruct *call_data = (IMCommitStruct *)xp; ++ FrameMgr fm; ++ extern XimFrameRec commit_chars_fr[]; ++ extern XimFrameRec commit_both_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ CARD16 str_length; ++ ++ call_data->flag |= XimSYNCHRONUS; /* always sync */ ++ ++ if (!(call_data->flag & XimLookupKeySym) ++ && ++ (call_data->flag & XimLookupChars)) ++ { ++ fm = FrameMgrInit (commit_chars_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, call_data->connect_id)); ++ ++ /* set length of STRING8 */ ++ str_length = strlen (call_data->commit_string); ++ FrameMgrSetSize (fm, str_length); ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, ++ call_data->connect_id, ++ XIM_ERROR, ++ 0, ++ 0, ++ 0); ++ return False; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ str_length = FrameMgrGetSize (fm); ++ FrameMgrPutToken (fm, call_data->connect_id); ++ FrameMgrPutToken (fm, call_data->icid); ++ FrameMgrPutToken (fm, call_data->flag); ++ FrameMgrPutToken (fm, str_length); ++ FrameMgrPutToken (fm, call_data->commit_string); ++ } ++ else ++ { ++ fm = FrameMgrInit (commit_both_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, call_data->connect_id)); ++ /* set length of STRING8 */ ++ str_length = strlen (call_data->commit_string); ++ if (str_length > 0) ++ FrameMgrSetSize (fm, str_length); ++ /*endif*/ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, ++ call_data->connect_id, ++ XIM_ERROR, ++ 0, ++ 0, ++ 0); ++ return False; ++ } ++ /*endif*/ ++ FrameMgrSetBuffer (fm, reply); ++ FrameMgrPutToken (fm, call_data->connect_id); ++ FrameMgrPutToken (fm, call_data->icid); ++ FrameMgrPutToken (fm, call_data->flag); ++ FrameMgrPutToken (fm, call_data->keysym); ++ if (str_length > 0) ++ { ++ str_length = FrameMgrGetSize (fm); ++ FrameMgrPutToken (fm, str_length); ++ FrameMgrPutToken (fm, call_data->commit_string); ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ _Xi18nSendMessage (ims, ++ call_data->connect_id, ++ XIM_COMMIT, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ return True; ++} ++ ++static int xi18n_callCallback (XIMS ims, XPointer xp) ++{ ++ IMProtocol *call_data = (IMProtocol *)xp; ++ switch (call_data->major_code) ++ { ++ case XIM_GEOMETRY: ++ return _Xi18nGeometryCallback (ims, call_data); ++ ++ case XIM_PREEDIT_START: ++ return _Xi18nPreeditStartCallback (ims, call_data); ++ ++ case XIM_PREEDIT_DRAW: ++ return _Xi18nPreeditDrawCallback (ims, call_data); ++ ++ case XIM_PREEDIT_CARET: ++ return _Xi18nPreeditCaretCallback (ims, call_data); ++ ++ case XIM_PREEDIT_DONE: ++ return _Xi18nPreeditDoneCallback (ims, call_data); ++ ++ case XIM_STATUS_START: ++ return _Xi18nStatusStartCallback (ims, call_data); ++ ++ case XIM_STATUS_DRAW: ++ return _Xi18nStatusDrawCallback (ims, call_data); ++ ++ case XIM_STATUS_DONE: ++ return _Xi18nStatusDoneCallback (ims, call_data); ++ ++ case XIM_STR_CONVERSION: ++ return _Xi18nStringConversionCallback (ims, call_data); ++ } ++ /*endswitch*/ ++ return False; ++} ++ ++/* preeditStart and preeditEnd are used only for Dynamic Event Flow. */ ++static int xi18n_preeditStart (XIMS ims, XPointer xp) ++{ ++ IMProtocol *call_data = (IMProtocol *)xp; ++ Xi18n i18n_core = ims->protocol; ++ IMPreeditStateStruct *preedit_state = ++ (IMPreeditStateStruct *) &call_data->preedit_state; ++ long mask; ++ int on_key_num = i18n_core->address.on_keys.count_keys; ++ int off_key_num = i18n_core->address.off_keys.count_keys; ++ ++ if (on_key_num == 0 && off_key_num == 0) ++ return False; ++ /*endif*/ ++ if (i18n_core->address.imvalue_mask & I18N_FILTERMASK) ++ mask = i18n_core->address.filterevent_mask; ++ else ++ mask = DEFAULT_FILTER_MASK; ++ /*endif*/ ++ _Xi18nSetEventMask (ims, ++ preedit_state->connect_id, ++ preedit_state->connect_id, ++ preedit_state->icid, ++ mask, ++ ~mask); ++ return True; ++} ++ ++static int xi18n_preeditEnd (XIMS ims, XPointer xp) ++{ ++ IMProtocol *call_data = (IMProtocol *)xp; ++ Xi18n i18n_core = ims->protocol; ++ int on_key_num = i18n_core->address.on_keys.count_keys; ++ int off_key_num = i18n_core->address.off_keys.count_keys; ++ IMPreeditStateStruct *preedit_state; ++ ++ preedit_state = (IMPreeditStateStruct *) &call_data->preedit_state; ++ ++ if (on_key_num == 0 && off_key_num == 0) ++ return False; ++ /*endif*/ ++ ++ _Xi18nSetEventMask (ims, ++ preedit_state->connect_id, ++ preedit_state->connect_id, ++ preedit_state->icid, ++ 0, ++ 0); ++ return True; ++} ++ ++static int xi18n_syncXlib (XIMS ims, XPointer xp) ++{ ++ IMProtocol *call_data = (IMProtocol *)xp; ++ Xi18n i18n_core = ims->protocol; ++ IMSyncXlibStruct *sync_xlib; ++ ++ extern XimFrameRec sync_fr[]; ++ FrameMgr fm; ++ CARD16 connect_id = call_data->any.connect_id; ++ int total_size; ++ unsigned char *reply; ++ ++ sync_xlib = (IMSyncXlibStruct *) &call_data->sync_xlib; ++ fm = FrameMgrInit (sync_fr, NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ total_size = FrameMgrGetTotalSize(fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return False; ++ } ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ /* input input-method ID */ ++ FrameMgrPutToken (fm, connect_id); ++ /* input input-context ID */ ++ FrameMgrPutToken (fm, sync_xlib->icid); ++ _Xi18nSendMessage (ims, connect_id, XIM_SYNC, 0, reply, total_size); ++ ++ FrameMgrFree (fm); ++ XFree(reply); ++ return True; ++} ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nPtHdr.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nPtHdr.c +new file mode 100644 +index 0000000..17e41b7 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nPtHdr.c +@@ -0,0 +1,1906 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#include ++#ifndef NEED_EVENTS ++#define NEED_EVENTS ++#endif ++#include ++#undef NEED_EVENTS ++#include "FrameMgr.h" ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "XimFunc.h" ++ ++#ifdef XIM_DEBUG ++#include ++ ++static void DebugLog(char * msg) ++{ ++ fprintf(stderr, msg); ++} ++#endif ++ ++extern Xi18nClient *_Xi18nFindClient (Xi18n, CARD16); ++ ++static void DiscardQueue (XIMS ims, CARD16 connect_id) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient *client = (Xi18nClient *) _Xi18nFindClient (i18n_core, ++ connect_id); ++ ++ if (client != NULL) { ++ client->sync = False; ++ while (client->pending != NULL) { ++ XIMPending* pending = client->pending; ++ ++ client->pending = pending->next; ++ ++ XFree(pending->p); ++ XFree(pending); ++ } ++ } ++} ++ ++static void DiscardAllQueue(XIMS ims) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient* client = i18n_core->address.clients; ++ ++ while (client != NULL) { ++ if (client->sync) { ++ DiscardQueue(ims, client->connect_id); ++ } ++ client = client->next; ++ } ++} ++ ++static void GetProtocolVersion (CARD16 client_major, ++ CARD16 client_minor, ++ CARD16 *server_major, ++ CARD16 *server_minor) ++{ ++ *server_major = client_major; ++ *server_minor = client_minor; ++} ++ ++static void ConnectMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec connect_fr[], connect_reply_fr[]; ++ register int total_size; ++ CARD16 server_major_version, server_minor_version; ++ unsigned char *reply = NULL; ++ IMConnectStruct *imconnect = ++ (IMConnectStruct*) &call_data->imconnect; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++ fm = FrameMgrInit (connect_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, imconnect->byte_order); ++ FrameMgrGetToken (fm, imconnect->major_version); ++ FrameMgrGetToken (fm, imconnect->minor_version); ++ ++ FrameMgrFree (fm); ++ ++ GetProtocolVersion (imconnect->major_version, ++ imconnect->minor_version, ++ &server_major_version, ++ &server_minor_version); ++#ifdef PROTOCOL_RICH ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++#endif /* PROTOCOL_RICH */ ++ ++ fm = FrameMgrInit (connect_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, server_major_version); ++ FrameMgrPutToken (fm, server_minor_version); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_CONNECT_REPLY, ++ 0, ++ reply, ++ total_size); ++ ++ FrameMgrFree (fm); ++ XFree (reply); ++} ++ ++static void DisConnectMessageProc (XIMS ims, IMProtocol *call_data) ++{ ++ Xi18n i18n_core = ims->protocol; ++ unsigned char *reply = NULL; ++ CARD16 connect_id = call_data->any.connect_id; ++ ++#ifdef PROTOCOL_RICH ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++#endif /* PROTOCOL_RICH */ ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_DISCONNECT_REPLY, ++ 0, ++ reply, ++ 0); ++ ++ i18n_core->methods.disconnect (ims, connect_id); ++} ++ ++static void OpenMessageProc(XIMS ims, IMProtocol *call_data, unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec open_fr[]; ++ extern XimFrameRec open_reply_fr[]; ++ unsigned char *reply = NULL; ++ int str_size; ++ register int i, total_size; ++ CARD16 connect_id = call_data->any.connect_id; ++ int str_length; ++ char *name; ++ IMOpenStruct *imopen = (IMOpenStruct *) &call_data->imopen; ++ ++ fm = FrameMgrInit (open_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, str_length); ++ FrameMgrSetSize (fm, str_length); ++ FrameMgrGetToken (fm, name); ++ imopen->lang.length = str_length; ++ imopen->lang.name = malloc (str_length + 1); ++ strncpy (imopen->lang.name, name, str_length); ++ imopen->lang.name[str_length] = (char) 0; ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ if ((i18n_core->address.imvalue_mask & I18N_ON_KEYS) ++ || ++ (i18n_core->address.imvalue_mask & I18N_OFF_KEYS)) ++ { ++ _Xi18nSendTriggerKey (ims, connect_id); ++ } ++ /*endif*/ ++ XFree (imopen->lang.name); ++ ++ fm = FrameMgrInit (open_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set iteration count for list of imattr */ ++ FrameMgrSetIterCount (fm, i18n_core->address.im_attr_num); ++ ++ /* set length of BARRAY item in ximattr_fr */ ++ for (i = 0; i < i18n_core->address.im_attr_num; i++) ++ { ++ str_size = strlen (i18n_core->address.xim_attr[i].name); ++ FrameMgrSetSize (fm, str_size); ++ } ++ /*endfor*/ ++ /* set iteration count for list of icattr */ ++ FrameMgrSetIterCount (fm, i18n_core->address.ic_attr_num); ++ /* set length of BARRAY item in xicattr_fr */ ++ for (i = 0; i < i18n_core->address.ic_attr_num; i++) ++ { ++ str_size = strlen (i18n_core->address.xic_attr[i].name); ++ FrameMgrSetSize (fm, str_size); ++ } ++ /*endfor*/ ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ /* input input-method ID */ ++ FrameMgrPutToken (fm, connect_id); ++ ++ for (i = 0; i < i18n_core->address.im_attr_num; i++) ++ { ++ str_size = FrameMgrGetSize (fm); ++ FrameMgrPutToken (fm, i18n_core->address.xim_attr[i].attribute_id); ++ FrameMgrPutToken (fm, i18n_core->address.xim_attr[i].type); ++ FrameMgrPutToken (fm, str_size); ++ FrameMgrPutToken (fm, i18n_core->address.xim_attr[i].name); ++ } ++ /*endfor*/ ++ for (i = 0; i < i18n_core->address.ic_attr_num; i++) ++ { ++ str_size = FrameMgrGetSize (fm); ++ FrameMgrPutToken (fm, i18n_core->address.xic_attr[i].attribute_id); ++ FrameMgrPutToken (fm, i18n_core->address.xic_attr[i].type); ++ FrameMgrPutToken (fm, str_size); ++ FrameMgrPutToken (fm, i18n_core->address.xic_attr[i].name); ++ } ++ /*endfor*/ ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_OPEN_REPLY, ++ 0, ++ reply, ++ total_size); ++ ++ FrameMgrFree (fm); ++ XFree (reply); ++} ++ ++static void CloseMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec close_fr[]; ++ extern XimFrameRec close_reply_fr[]; ++ unsigned char *reply = NULL; ++ register int total_size; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (close_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ FrameMgrGetToken (fm, input_method_ID); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ fm = FrameMgrInit (close_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_ERROR, ++ 0, ++ 0, ++ 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_CLOSE_REPLY, ++ 0, ++ reply, ++ total_size); ++ ++ FrameMgrFree (fm); ++ XFree (reply); ++} ++ ++static XIMExt *MakeExtensionList (Xi18n i18n_core, ++ XIMStr *lib_extension, ++ int number, ++ int *reply_number) ++{ ++ XIMExt *ext_list; ++ XIMExt *im_ext = (XIMExt *) i18n_core->address.extension; ++ int im_ext_len = i18n_core->address.ext_num; ++ int i; ++ int j; ++ ++ *reply_number = 0; ++ ++ if (number == 0) ++ { ++ /* query all extensions */ ++ *reply_number = im_ext_len; ++ } ++ else ++ { ++ for (i = 0; i < im_ext_len; i++) ++ { ++ for (j = 0; j < (int) number; j++) ++ { ++ if (strcmp (lib_extension[j].name, im_ext[i].name) == 0) ++ { ++ (*reply_number)++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endfor*/ ++ } ++ /*endif*/ ++ ++ if (!(*reply_number)) ++ return NULL; ++ /*endif*/ ++ ext_list = (XIMExt *) malloc (sizeof (XIMExt)*(*reply_number)); ++ if (!ext_list) ++ return NULL; ++ /*endif*/ ++ memset (ext_list, 0, sizeof (XIMExt)*(*reply_number)); ++ ++ if (number == 0) ++ { ++ /* query all extensions */ ++ for (i = 0; i < im_ext_len; i++) ++ { ++ ext_list[i].major_opcode = im_ext[i].major_opcode; ++ ext_list[i].minor_opcode = im_ext[i].minor_opcode; ++ ext_list[i].length = im_ext[i].length; ++ ext_list[i].name = malloc (im_ext[i].length + 1); ++ strcpy (ext_list[i].name, im_ext[i].name); ++ } ++ /*endfor*/ ++ } ++ else ++ { ++ int n = 0; ++ ++ for (i = 0; i < im_ext_len; i++) ++ { ++ for (j = 0; j < (int)number; j++) ++ { ++ if (strcmp (lib_extension[j].name, im_ext[i].name) == 0) ++ { ++ ext_list[n].major_opcode = im_ext[i].major_opcode; ++ ext_list[n].minor_opcode = im_ext[i].minor_opcode; ++ ext_list[n].length = im_ext[i].length; ++ ext_list[n].name = malloc (im_ext[i].length + 1); ++ strcpy (ext_list[n].name, im_ext[i].name); ++ n++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endfor*/ ++ } ++ /*endif*/ ++ return ext_list; ++} ++ ++static void QueryExtensionMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ FmStatus status; ++ extern XimFrameRec query_extension_fr[]; ++ extern XimFrameRec query_extension_reply_fr[]; ++ unsigned char *reply = NULL; ++ int str_size; ++ register int i; ++ register int number; ++ register int total_size; ++ int byte_length; ++ int reply_number = 0; ++ XIMExt *ext_list; ++ IMQueryExtensionStruct *query_ext = ++ (IMQueryExtensionStruct *) &call_data->queryext; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (query_extension_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, byte_length); ++ query_ext->extension = (XIMStr *) malloc (sizeof (XIMStr)*10); ++ memset (query_ext->extension, 0, sizeof (XIMStr)*10); ++ number = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ { ++ char *name; ++ int str_length; ++ ++ FrameMgrGetToken (fm, str_length); ++ FrameMgrSetSize (fm, str_length); ++ query_ext->extension[number].length = str_length; ++ FrameMgrGetToken (fm, name); ++ query_ext->extension[number].name = malloc (str_length + 1); ++ strncpy (query_ext->extension[number].name, name, str_length); ++ query_ext->extension[number].name[str_length] = (char) 0; ++ number++; ++ } ++ /*endwhile*/ ++ query_ext->number = number; ++ ++#ifdef PROTOCOL_RICH ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++#endif /* PROTOCOL_RICH */ ++ ++ FrameMgrFree (fm); ++ ++ ext_list = MakeExtensionList (i18n_core, ++ query_ext->extension, ++ number, ++ &reply_number); ++ ++ for (i = 0; i < number; i++) ++ XFree (query_ext->extension[i].name); ++ /*endfor*/ ++ XFree (query_ext->extension); ++ ++ fm = FrameMgrInit (query_extension_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set iteration count for list of extensions */ ++ FrameMgrSetIterCount (fm, reply_number); ++ ++ /* set length of BARRAY item in ext_fr */ ++ for (i = 0; i < reply_number; i++) ++ { ++ str_size = strlen (ext_list[i].name); ++ FrameMgrSetSize (fm, str_size); ++ } ++ /*endfor*/ ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_ERROR, ++ 0, ++ 0, ++ 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ ++ for (i = 0; i < reply_number; i++) ++ { ++ str_size = FrameMgrGetSize (fm); ++ FrameMgrPutToken (fm, ext_list[i].major_opcode); ++ FrameMgrPutToken (fm, ext_list[i].minor_opcode); ++ FrameMgrPutToken (fm, str_size); ++ FrameMgrPutToken (fm, ext_list[i].name); ++ } ++ /*endfor*/ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_QUERY_EXTENSION_REPLY, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ for (i = 0; i < reply_number; i++) ++ XFree (ext_list[i].name); ++ /*endfor*/ ++ XFree ((char *) ext_list); ++} ++ ++static void SyncReplyMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec sync_reply_fr[]; ++ CARD16 connect_id = call_data->any.connect_id; ++ Xi18nClient *client; ++ CARD16 input_method_ID; ++ CARD16 input_context_ID; ++ ++ client = (Xi18nClient *)_Xi18nFindClient (i18n_core, connect_id); ++ fm = FrameMgrInit (sync_reply_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, input_context_ID); ++ FrameMgrFree (fm); ++ ++ client->sync = False; ++ ++ if (ims->sync == True) { ++ ims->sync = False; ++ if (i18n_core->address.improto) { ++ call_data->sync_xlib.major_code = XIM_SYNC_REPLY; ++ call_data->sync_xlib.minor_code = 0; ++ call_data->sync_xlib.connect_id = input_method_ID; ++ call_data->sync_xlib.icid = input_context_ID; ++ i18n_core->address.improto(ims, call_data); ++ } ++ } ++} ++ ++static void GetIMValueFromName (Xi18n i18n_core, ++ CARD16 connect_id, ++ char *buf, ++ char *name, ++ int *length) ++{ ++ register int i; ++ ++ if (strcmp (name, XNQueryInputStyle) == 0) ++ { ++ XIMStyles *styles = (XIMStyles *) &i18n_core->address.input_styles; ++ ++ *length = sizeof (CARD16)*2; /* count_styles, unused */ ++ *length += styles->count_styles*sizeof (CARD32); ++ ++ if (buf != NULL) ++ { ++ FrameMgr fm; ++ extern XimFrameRec input_styles_fr[]; ++ unsigned char *data = NULL; ++ int total_size; ++ ++ fm = FrameMgrInit (input_styles_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set iteration count for list of input_style */ ++ FrameMgrSetIterCount (fm, styles->count_styles); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ data = (unsigned char *) malloc (total_size); ++ if (!data) ++ return; ++ /*endif*/ ++ memset (data, 0, total_size); ++ FrameMgrSetBuffer (fm, data); ++ ++ FrameMgrPutToken (fm, styles->count_styles); ++ for (i = 0; i < (int) styles->count_styles; i++) ++ FrameMgrPutToken (fm, styles->supported_styles[i]); ++ /*endfor*/ ++ memmove (buf, data, total_size); ++ FrameMgrFree (fm); ++ ++ /* ADDED BY SUZHE */ ++ free (data); ++ /* ADDED BY SUZHE */ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ else if (strcmp (name, XNQueryIMValuesList) == 0) { ++ } ++} ++ ++static XIMAttribute *MakeIMAttributeList (Xi18n i18n_core, ++ CARD16 connect_id, ++ CARD16 *list, ++ int *number, ++ int *length) ++{ ++ XIMAttribute *attrib_list; ++ int list_num; ++ XIMAttr *attr = i18n_core->address.xim_attr; ++ int list_len = i18n_core->address.im_attr_num; ++ register int i; ++ register int j; ++ int value_length; ++ int number_ret = 0; ++ ++ *length = 0; ++ list_num = 0; ++ for (i = 0; i < *number; i++) ++ { ++ for (j = 0; j < list_len; j++) ++ { ++ if (attr[j].attribute_id == list[i]) ++ { ++ list_num++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endfor*/ ++ attrib_list = (XIMAttribute *) malloc (sizeof (XIMAttribute)*list_num); ++ if (!attrib_list) ++ return NULL; ++ /*endif*/ ++ memset (attrib_list, 0, sizeof (XIMAttribute)*list_num); ++ number_ret = list_num; ++ list_num = 0; ++ for (i = 0; i < *number; i++) ++ { ++ for (j = 0; j < list_len; j++) ++ { ++ if (attr[j].attribute_id == list[i]) ++ { ++ attrib_list[list_num].attribute_id = attr[j].attribute_id; ++ attrib_list[list_num].name_length = attr[j].length; ++ attrib_list[list_num].name = attr[j].name; ++ attrib_list[list_num].type = attr[j].type; ++ GetIMValueFromName (i18n_core, ++ connect_id, ++ NULL, ++ attr[j].name, ++ &value_length); ++ attrib_list[list_num].value_length = value_length; ++ attrib_list[list_num].value = (void *) malloc (value_length); ++ memset(attrib_list[list_num].value, 0, value_length); ++ GetIMValueFromName (i18n_core, ++ connect_id, ++ attrib_list[list_num].value, ++ attr[j].name, ++ &value_length); ++ *length += sizeof (CARD16)*2; ++ *length += value_length; ++ *length += IMPAD (value_length); ++ list_num++; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endfor*/ ++ *number = number_ret; ++ return attrib_list; ++} ++ ++static void GetIMValuesMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ FmStatus status; ++ extern XimFrameRec get_im_values_fr[]; ++ extern XimFrameRec get_im_values_reply_fr[]; ++ CARD16 byte_length; ++ int list_len, total_size; ++ unsigned char *reply = NULL; ++ int iter_count; ++ register int i; ++ register int j; ++ int number; ++ CARD16 *im_attrID_list; ++ char **name_list; ++ CARD16 name_number; ++ XIMAttribute *im_attribute_list; ++ IMGetIMValuesStruct *getim = (IMGetIMValuesStruct *)&call_data->getim; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ /* create FrameMgr */ ++ fm = FrameMgrInit (get_im_values_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, byte_length); ++ im_attrID_list = (CARD16 *) malloc (sizeof (CARD16)*20); ++ memset (im_attrID_list, 0, sizeof (CARD16)*20); ++ name_list = (char **)malloc(sizeof(char *) * 20); ++ memset(name_list, 0, sizeof(char *) * 20); ++ number = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ { ++ FrameMgrGetToken (fm, im_attrID_list[number]); ++ number++; ++ } ++ FrameMgrFree (fm); ++ ++ name_number = 0; ++ for (i = 0; i < number; i++) { ++ for (j = 0; j < i18n_core->address.im_attr_num; j++) { ++ if (i18n_core->address.xim_attr[j].attribute_id == ++ im_attrID_list[i]) { ++ name_list[name_number++] = ++ i18n_core->address.xim_attr[j].name; ++ break; ++ } ++ } ++ } ++ getim->number = name_number; ++ getim->im_attr_list = name_list; ++ XFree (name_list); ++ ++ ++#ifdef PROTOCOL_RICH ++ if (i18n_core->address.improto) { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ } ++#endif /* PROTOCOL_RICH */ ++ ++ im_attribute_list = MakeIMAttributeList (i18n_core, ++ connect_id, ++ im_attrID_list, ++ &number, ++ &list_len); ++ if (im_attrID_list) ++ XFree (im_attrID_list); ++ /*endif*/ ++ ++ fm = FrameMgrInit (get_im_values_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ iter_count = number; ++ ++ /* set iteration count for list of im_attribute */ ++ FrameMgrSetIterCount (fm, iter_count); ++ ++ /* set length of BARRAY item in ximattribute_fr */ ++ for (i = 0; i < iter_count; i++) ++ FrameMgrSetSize (fm, im_attribute_list[i].value_length); ++ /*endfor*/ ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ ++ for (i = 0; i < iter_count; i++) ++ { ++ FrameMgrPutToken (fm, im_attribute_list[i].attribute_id); ++ FrameMgrPutToken (fm, im_attribute_list[i].value_length); ++ FrameMgrPutToken (fm, im_attribute_list[i].value); ++ } ++ /*endfor*/ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_GET_IM_VALUES_REPLY, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree (reply); ++ ++ for (i = 0; i < iter_count; i++) ++ XFree(im_attribute_list[i].value); ++ XFree (im_attribute_list); ++} ++ ++static void CreateICMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ _Xi18nChangeIC (ims, call_data, p, True); ++} ++ ++static void SetICValuesMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ _Xi18nChangeIC (ims, call_data, p, False); ++} ++ ++static void GetICValuesMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ _Xi18nGetIC (ims, call_data, p); ++} ++ ++static void SetICFocusMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec set_ic_focus_fr[]; ++ IMChangeFocusStruct *setfocus; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ /* some buggy xim clients do not send XIM_SYNC_REPLY for synchronous ++ * events. In such case, xim server is waiting for XIM_SYNC_REPLY ++ * forever. So the xim server is blocked to waiting sync reply. ++ * It prevents further input. ++ * Usually it happens when a client calls XSetICFocus() with another ic ++ * before passing an event to XFilterEvent(), where the event is needed ++ * by the old focused ic to sync its state. ++ * To avoid such problem, remove the whole clients queue and set them ++ * as asynchronous. ++ * ++ * See: ++ * http://bugs.freedesktop.org/show_bug.cgi?id=7869 ++ */ ++ DiscardAllQueue(ims); ++ ++ setfocus = (IMChangeFocusStruct *) &call_data->changefocus; ++ ++ fm = FrameMgrInit (set_ic_focus_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, setfocus->icid); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++static void UnsetICFocusMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec unset_ic_focus_fr[]; ++ IMChangeFocusStruct *unsetfocus; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id); ++ ++ /* some buggy clients unset focus ic before the ic answer the sync reply, ++ * so the xim server may be blocked to waiting sync reply. To avoid ++ * this problem, remove the client queue and set it asynchronous ++ * ++ * See: SetICFocusMessageProc ++ */ ++ if (client != NULL && client->sync) { ++ DiscardQueue(ims, client->connect_id); ++ } ++ ++ unsetfocus = (IMChangeFocusStruct *) &call_data->changefocus; ++ ++ fm = FrameMgrInit (unset_ic_focus_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, unsetfocus->icid); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++static void DestroyICMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec destroy_ic_fr[]; ++ extern XimFrameRec destroy_ic_reply_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMDestroyICStruct *destroy = ++ (IMDestroyICStruct *) &call_data->destroyic; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (destroy_ic_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, destroy->icid); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ fm = FrameMgrInit (destroy_ic_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, destroy->icid); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_DESTROY_IC_REPLY, ++ 0, ++ reply, ++ total_size); ++ XFree(reply); ++ FrameMgrFree (fm); ++} ++ ++static void ResetICMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec reset_ic_fr[]; ++ extern XimFrameRec reset_ic_reply_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMResetICStruct *resetic = ++ (IMResetICStruct *) &call_data->resetic; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (reset_ic_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, resetic->icid); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ /* create FrameMgr */ ++ fm = FrameMgrInit (reset_ic_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set length of STRING8 */ ++ FrameMgrSetSize (fm, resetic->length); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, resetic->icid); ++ FrameMgrPutToken(fm, resetic->length); ++ FrameMgrPutToken (fm, resetic->commit_string); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_RESET_IC_REPLY, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree(reply); ++} ++ ++static int WireEventToEvent (Xi18n i18n_core, ++ xEvent *event, ++ CARD16 serial, ++ XEvent *ev, ++ Bool byte_swap) ++{ ++ FrameMgr fm; ++ extern XimFrameRec wire_keyevent_fr[]; ++ BYTE b; ++ CARD16 c16; ++ CARD32 c32; ++ int ret = False; ++ ++ /* create FrameMgr */ ++ fm = FrameMgrInit(wire_keyevent_fr, (char *)(&(event->u)), byte_swap); ++ ++ ++ /* get & set type */ ++ FrameMgrGetToken(fm, b); ++ ev->type = (unsigned int)b; ++ /* get detail */ ++ FrameMgrGetToken(fm, b); ++ /* get & set serial */ ++ FrameMgrGetToken(fm, c16); ++ ev->xany.serial = (unsigned long)c16; ++ ev->xany.serial |= serial << 16; ++ ev->xany.send_event = False; ++ ev->xany.display = i18n_core->address.dpy; ++ ++ /* Remove SendEvent flag from event type to emulate KeyPress/Release */ ++ ev->type &= 0x7F; ++ ++ switch (ev->type) { ++ case KeyPress: ++ case KeyRelease: ++ { ++ XKeyEvent *kev = (XKeyEvent*)ev; ++ ++ /* set keycode (detail) */ ++ kev->keycode = (unsigned int)b; ++ ++ /* get & set values */ ++ FrameMgrGetToken(fm, c32); kev->time = (Time)c32; ++ FrameMgrGetToken(fm, c32); kev->root = (Window)c32; ++ FrameMgrGetToken(fm, c32); kev->window = (Window)c32; ++ FrameMgrGetToken(fm, c32); kev->subwindow = (Window)c32; ++ FrameMgrGetToken(fm, c16); kev->x_root = (int)c16; ++ FrameMgrGetToken(fm, c16); kev->y_root = (int)c16; ++ FrameMgrGetToken(fm, c16); kev->x = (int)c16; ++ FrameMgrGetToken(fm, c16); kev->y = (int)c16; ++ FrameMgrGetToken(fm, c16); kev->state = (unsigned int)c16; ++ FrameMgrGetToken(fm, b); kev->same_screen = (Bool)b; ++ } ++ ret = True; ++ break; ++ default: ++ break; ++ } ++ /* free FrameMgr */ ++ FrameMgrFree(fm); ++ return ret; ++} ++ ++static void ForwardEventMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec forward_event_fr[]; ++ xEvent wire_event; ++ IMForwardEventStruct *forward = ++ (IMForwardEventStruct*) &call_data->forwardevent; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (forward_event_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, forward->icid); ++ FrameMgrGetToken (fm, forward->sync_bit); ++ FrameMgrGetToken (fm, forward->serial_number); ++ p += sizeof (CARD16)*4; ++ memmove (&wire_event, p, sizeof (xEvent)); ++ ++ FrameMgrFree (fm); ++ ++ if (WireEventToEvent (i18n_core, ++ &wire_event, ++ forward->serial_number, ++ &forward->event, ++ _Xi18nNeedSwap (i18n_core, connect_id)) == True) ++ { ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++static void ExtForwardKeyEventMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec ext_forward_keyevent_fr[]; ++ CARD8 type, keycode; ++ CARD16 state; ++ CARD32 ev_time, window; ++ IMForwardEventStruct *forward = ++ (IMForwardEventStruct *) &call_data->forwardevent; ++ XEvent *ev = (XEvent *) &forward->event; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (ext_forward_keyevent_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, forward->icid); ++ FrameMgrGetToken (fm, forward->sync_bit); ++ FrameMgrGetToken (fm, forward->serial_number); ++ FrameMgrGetToken (fm, type); ++ FrameMgrGetToken (fm, keycode); ++ FrameMgrGetToken (fm, state); ++ FrameMgrGetToken (fm, ev_time); ++ FrameMgrGetToken (fm, window); ++ ++ FrameMgrFree (fm); ++ ++ if (type != KeyPress) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ ++ /* make a faked keypress event */ ++ ev->type = (int)type; ++ ev->xany.send_event = True; ++ ev->xany.display = i18n_core->address.dpy; ++ ev->xany.serial = (unsigned long) forward->serial_number; ++ ((XKeyEvent *) ev)->keycode = (unsigned int) keycode; ++ ((XKeyEvent *) ev)->state = (unsigned int) state; ++ ((XKeyEvent *) ev)->time = (Time) ev_time; ++ ((XKeyEvent *) ev)->window = (Window) window; ++ ((XKeyEvent *) ev)->root = DefaultRootWindow (ev->xany.display); ++ ((XKeyEvent *) ev)->x = 0; ++ ((XKeyEvent *) ev)->y = 0; ++ ((XKeyEvent *) ev)->x_root = 0; ++ ((XKeyEvent *) ev)->y_root = 0; ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++static void ExtMoveMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec ext_move_fr[]; ++ IMMoveStruct *extmove = ++ (IMMoveStruct*) & call_data->extmove; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (ext_move_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, extmove->icid); ++ FrameMgrGetToken (fm, extmove->x); ++ FrameMgrGetToken (fm, extmove->y); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++static void ExtensionMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ switch (call_data->any.minor_code) ++ { ++ case XIM_EXT_FORWARD_KEYEVENT: ++ ExtForwardKeyEventMessageProc (ims, call_data, p); ++ break; ++ ++ case XIM_EXT_MOVE: ++ ExtMoveMessageProc (ims, call_data, p); ++ break; ++ } ++ /*endswitch*/ ++} ++ ++static void TriggerNotifyMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec trigger_notify_fr[], trigger_notify_reply_fr[]; ++ register int total_size; ++ unsigned char *reply = NULL; ++ IMTriggerNotifyStruct *trigger = ++ (IMTriggerNotifyStruct *) &call_data->triggernotify; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ CARD32 flag; ++ ++ fm = FrameMgrInit (trigger_notify_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, trigger->icid); ++ FrameMgrGetToken (fm, trigger->flag); ++ FrameMgrGetToken (fm, trigger->key_index); ++ FrameMgrGetToken (fm, trigger->event_mask); ++ /* ++ In order to support Front End Method, this event_mask must be saved ++ per clients so that it should be restored by an XIM_EXT_SET_EVENT_MASK ++ call when preediting mode is reset to off. ++ */ ++ ++ flag = trigger->flag; ++ ++ FrameMgrFree (fm); ++ ++ fm = FrameMgrInit (trigger_notify_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, trigger->icid); ++ ++ /* NOTE: ++ XIM_TRIGGER_NOTIFY_REPLY should be sent before XIM_SET_EVENT_MASK ++ in case of XIM_TRIGGER_NOTIFY(flag == ON), while it should be ++ sent after XIM_SET_EVENT_MASK in case of ++ XIM_TRIGGER_NOTIFY(flag == OFF). ++ */ ++ if (flag == 0) ++ { ++ /* on key */ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_TRIGGER_NOTIFY_REPLY, ++ 0, ++ reply, ++ total_size); ++ IMPreeditStart (ims, (XPointer)call_data); ++ } ++ /*endif*/ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++ ++ if (flag == 1) ++ { ++ /* off key */ ++ IMPreeditEnd (ims, (XPointer) call_data); ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_TRIGGER_NOTIFY_REPLY, ++ 0, ++ reply, ++ total_size); ++ } ++ /*endif*/ ++ FrameMgrFree (fm); ++ XFree (reply); ++} ++ ++static INT16 ChooseEncoding (Xi18n i18n_core, ++ IMEncodingNegotiationStruct *enc_nego) ++{ ++ Xi18nAddressRec *address = (Xi18nAddressRec *) & i18n_core->address; ++ XIMEncodings *p; ++ int i, j; ++ int enc_index=0; ++ ++ p = (XIMEncodings *) &address->encoding_list; ++ for (i = 0; i < (int) p->count_encodings; i++) ++ { ++ for (j = 0; j < (int) enc_nego->encoding_number; j++) ++ { ++ if (strcmp (p->supported_encodings[i], ++ enc_nego->encoding[j].name) == 0) ++ { ++ enc_index = j; ++ break; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++ } ++ /*endfor*/ ++ ++ return (INT16) enc_index; ++#if 0 ++ return (INT16) XIM_Default_Encoding_IDX; ++#endif ++} ++ ++static void EncodingNegotiatonMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ FmStatus status; ++ CARD16 byte_length; ++ extern XimFrameRec encoding_negotiation_fr[]; ++ extern XimFrameRec encoding_negotiation_reply_fr[]; ++ register int i, total_size; ++ unsigned char *reply = NULL; ++ IMEncodingNegotiationStruct *enc_nego = ++ (IMEncodingNegotiationStruct *) &call_data->encodingnego; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (encoding_negotiation_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ FrameMgrGetToken (fm, input_method_ID); ++ ++ /* get ENCODING STR field */ ++ FrameMgrGetToken (fm, byte_length); ++ if (byte_length > 0) ++ { ++ enc_nego->encoding = (XIMStr *) malloc (sizeof (XIMStr)*10); ++ memset (enc_nego->encoding, 0, sizeof (XIMStr)*10); ++ i = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ { ++ char *name; ++ int str_length; ++ ++ FrameMgrGetToken (fm, str_length); ++ FrameMgrSetSize (fm, str_length); ++ enc_nego->encoding[i].length = str_length; ++ FrameMgrGetToken (fm, name); ++ enc_nego->encoding[i].name = malloc (str_length + 1); ++ strncpy (enc_nego->encoding[i].name, name, str_length); ++ enc_nego->encoding[i].name[str_length] = '\0'; ++ i++; ++ } ++ /*endwhile*/ ++ enc_nego->encoding_number = i; ++ } ++ /*endif*/ ++ /* get ENCODING INFO field */ ++ FrameMgrGetToken (fm, byte_length); ++ if (byte_length > 0) ++ { ++ enc_nego->encodinginfo = (XIMStr *) malloc (sizeof (XIMStr)*10); ++ memset (enc_nego->encoding, 0, sizeof (XIMStr)*10); ++ i = 0; ++ while (FrameMgrIsIterLoopEnd (fm, &status) == False) ++ { ++ char *name; ++ int str_length; ++ ++ FrameMgrGetToken (fm, str_length); ++ FrameMgrSetSize (fm, str_length); ++ enc_nego->encodinginfo[i].length = str_length; ++ FrameMgrGetToken (fm, name); ++ enc_nego->encodinginfo[i].name = malloc (str_length + 1); ++ strncpy (enc_nego->encodinginfo[i].name, name, str_length); ++ enc_nego->encodinginfo[i].name[str_length] = '\0'; ++ i++; ++ } ++ /*endwhile*/ ++ enc_nego->encoding_info_number = i; ++ } ++ /*endif*/ ++ ++ enc_nego->enc_index = ChooseEncoding (i18n_core, enc_nego); ++ enc_nego->category = 0; ++ ++#ifdef PROTOCOL_RICH ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++#endif /* PROTOCOL_RICH */ ++ ++ FrameMgrFree (fm); ++ ++ fm = FrameMgrInit (encoding_negotiation_reply_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, input_method_ID); ++ FrameMgrPutToken (fm, enc_nego->category); ++ FrameMgrPutToken (fm, enc_nego->enc_index); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_ENCODING_NEGOTIATION_REPLY, ++ 0, ++ reply, ++ total_size); ++ XFree (reply); ++ ++ /* free data for encoding list */ ++ if (enc_nego->encoding) ++ { ++ for (i = 0; i < (int) enc_nego->encoding_number; i++) ++ XFree (enc_nego->encoding[i].name); ++ /*endfor*/ ++ XFree (enc_nego->encoding); ++ } ++ /*endif*/ ++ if (enc_nego->encodinginfo) ++ { ++ for (i = 0; i < (int) enc_nego->encoding_info_number; i++) ++ XFree (enc_nego->encodinginfo[i].name); ++ /*endfor*/ ++ XFree (enc_nego->encodinginfo); ++ } ++ /*endif*/ ++ FrameMgrFree (fm); ++} ++ ++void PreeditStartReplyMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_start_reply_fr[]; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct *) &call_data->preedit_callback; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (preedit_start_reply_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, preedit_CB->icid); ++ FrameMgrGetToken (fm, preedit_CB->todo.return_value); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto (ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++void PreeditCaretReplyMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec preedit_caret_reply_fr[]; ++ IMPreeditCBStruct *preedit_CB = ++ (IMPreeditCBStruct *) &call_data->preedit_callback; ++ XIMPreeditCaretCallbackStruct *caret = ++ (XIMPreeditCaretCallbackStruct *) & preedit_CB->todo.caret; ++ CARD16 connect_id = call_data->any.connect_id; ++ CARD16 input_method_ID; ++ ++ fm = FrameMgrInit (preedit_caret_reply_fr, ++ (char *) p, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ /* get data */ ++ FrameMgrGetToken (fm, input_method_ID); ++ FrameMgrGetToken (fm, preedit_CB->icid); ++ FrameMgrGetToken (fm, caret->position); ++ ++ FrameMgrFree (fm); ++ ++ if (i18n_core->address.improto) ++ { ++ if (!(i18n_core->address.improto(ims, call_data))) ++ return; ++ /*endif*/ ++ } ++ /*endif*/ ++} ++ ++void StrConvReplyMessageProc (XIMS ims, ++ IMProtocol *call_data, ++ unsigned char *p) ++{ ++ return; ++} ++ ++static void AddQueue (Xi18nClient *client, unsigned char *p) ++{ ++ XIMPending *new; ++ XIMPending *last; ++ ++ if ((new = (XIMPending *) malloc (sizeof (XIMPending))) == NULL) ++ return; ++ /*endif*/ ++ new->p = p; ++ new->next = (XIMPending *) NULL; ++ if (!client->pending) ++ { ++ client->pending = new; ++ } ++ else ++ { ++ for (last = client->pending; last->next; last = last->next) ++ ; ++ /*endfor*/ ++ last->next = new; ++ } ++ /*endif*/ ++ return; ++} ++ ++static void ProcessQueue (XIMS ims, CARD16 connect_id) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient *client = (Xi18nClient *) _Xi18nFindClient (i18n_core, ++ connect_id); ++ ++ while (client->sync == False && client->pending) ++ { ++ XimProtoHdr *hdr = (XimProtoHdr *) client->pending->p; ++ unsigned char *p1 = (unsigned char *) (hdr + 1); ++ IMProtocol call_data; ++ ++ call_data.major_code = hdr->major_opcode; ++ call_data.any.minor_code = hdr->minor_opcode; ++ call_data.any.connect_id = connect_id; ++ ++ switch (hdr->major_opcode) ++ { ++ case XIM_FORWARD_EVENT: ++ ForwardEventMessageProc(ims, &call_data, p1); ++ break; ++ } ++ /*endswitch*/ ++ XFree (hdr); ++ { ++ XIMPending *old = client->pending; ++ ++ client->pending = old->next; ++ XFree (old); ++ } ++ } ++ /*endwhile*/ ++ return; ++} ++ ++ ++void _Xi18nMessageHandler (XIMS ims, ++ CARD16 connect_id, ++ unsigned char *p, ++ Bool *delete) ++{ ++ XimProtoHdr *hdr = (XimProtoHdr *)p; ++ unsigned char *p1 = (unsigned char *)(hdr + 1); ++ IMProtocol call_data; ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient *client; ++ ++ client = (Xi18nClient *) _Xi18nFindClient (i18n_core, connect_id); ++ if (hdr == (XimProtoHdr *) NULL) ++ return; ++ /*endif*/ ++ ++ memset (&call_data, 0, sizeof(IMProtocol)); ++ ++ call_data.major_code = hdr->major_opcode; ++ call_data.any.minor_code = hdr->minor_opcode; ++ call_data.any.connect_id = connect_id; ++ ++ switch (call_data.major_code) ++ { ++ case XIM_CONNECT: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_CONNECT\n"); ++#endif ++ ConnectMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_DISCONNECT: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_DISCONNECT\n"); ++#endif ++ DisConnectMessageProc (ims, &call_data); ++ break; ++ ++ case XIM_OPEN: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_OPEN\n"); ++#endif ++ OpenMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_CLOSE: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_CLOSE\n"); ++#endif ++ CloseMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_QUERY_EXTENSION: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_QUERY_EXTENSION\n"); ++#endif ++ QueryExtensionMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_GET_IM_VALUES: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_GET_IM_VALUES\n"); ++#endif ++ GetIMValuesMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_CREATE_IC: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_CREATE_IC\n"); ++#endif ++ CreateICMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_SET_IC_VALUES: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_SET_IC_VALUES\n"); ++#endif ++ SetICValuesMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_GET_IC_VALUES: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_GET_IC_VALUES\n"); ++#endif ++ GetICValuesMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_SET_IC_FOCUS: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_SET_IC_FOCUS\n"); ++#endif ++ SetICFocusMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_UNSET_IC_FOCUS: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_UNSET_IC_FOCUS\n"); ++#endif ++ UnsetICFocusMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_DESTROY_IC: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_DESTROY_IC\n"); ++#endif ++ DestroyICMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_RESET_IC: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_RESET_IC\n"); ++#endif ++ ResetICMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_FORWARD_EVENT: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_FORWARD_EVENT\n"); ++#endif ++ if (client->sync == True) ++ { ++ AddQueue (client, p); ++ *delete = False; ++ } ++ else ++ { ++ ForwardEventMessageProc (ims, &call_data, p1); ++ } ++ break; ++ ++ case XIM_EXTENSION: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_EXTENSION\n"); ++#endif ++ ExtensionMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_SYNC: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_SYNC\n"); ++#endif ++ break; ++ ++ case XIM_SYNC_REPLY: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_SYNC_REPLY\n"); ++#endif ++ SyncReplyMessageProc (ims, &call_data, p1); ++ ProcessQueue (ims, connect_id); ++ break; ++ ++ case XIM_TRIGGER_NOTIFY: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_TRIGGER_NOTIFY\n"); ++#endif ++ TriggerNotifyMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_ENCODING_NEGOTIATION: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_ENCODING_NEGOTIATION\n"); ++#endif ++ EncodingNegotiatonMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_PREEDIT_START_REPLY: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_PREEDIT_START_REPLY\n"); ++#endif ++ PreeditStartReplyMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_PREEDIT_CARET_REPLY: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_PREEDIT_CARET_REPLY\n"); ++#endif ++ PreeditCaretReplyMessageProc (ims, &call_data, p1); ++ break; ++ ++ case XIM_STR_CONVERSION_REPLY: ++#ifdef XIM_DEBUG ++ DebugLog("-- XIM_STR_CONVERSION_REPLY\n"); ++#endif ++ StrConvReplyMessageProc (ims, &call_data, p1); ++ break; ++ } ++ /*endswitch*/ ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nUtil.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nUtil.c +new file mode 100644 +index 0000000..ff8970e +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nUtil.c +@@ -0,0 +1,276 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "FrameMgr.h" ++#include "XimFunc.h" ++ ++Xi18nClient *_Xi18nFindClient (Xi18n, CARD16); ++ ++int ++_Xi18nNeedSwap (Xi18n i18n_core, CARD16 connect_id) ++{ ++ CARD8 im_byteOrder = i18n_core->address.im_byteOrder; ++ Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id); ++ ++ return (client->byte_order != im_byteOrder); ++} ++ ++Xi18nClient *_Xi18nNewClient(Xi18n i18n_core) ++{ ++ static CARD16 connect_id = 0; ++ int new_connect_id; ++ Xi18nClient *client; ++ ++ if (i18n_core->address.free_clients) ++ { ++ client = i18n_core->address.free_clients; ++ i18n_core->address.free_clients = client->next; ++ new_connect_id = client->connect_id; ++ } ++ else ++ { ++ client = (Xi18nClient *) malloc (sizeof (Xi18nClient)); ++ new_connect_id = ++connect_id; ++ } ++ /*endif*/ ++ memset (client, 0, sizeof (Xi18nClient)); ++ client->connect_id = new_connect_id; ++ client->pending = (XIMPending *) NULL; ++ client->sync = False; ++ client->byte_order = '?'; /* initial value */ ++ memset (&client->pending, 0, sizeof (XIMPending *)); ++ client->next = i18n_core->address.clients; ++ i18n_core->address.clients = client; ++ ++ return (Xi18nClient *) client; ++} ++ ++Xi18nClient *_Xi18nFindClient (Xi18n i18n_core, CARD16 connect_id) ++{ ++ Xi18nClient *client = i18n_core->address.clients; ++ ++ while (client) ++ { ++ if (client->connect_id == connect_id) ++ return client; ++ /*endif*/ ++ client = client->next; ++ } ++ /*endwhile*/ ++ return NULL; ++} ++ ++void _Xi18nDeleteClient (Xi18n i18n_core, CARD16 connect_id) ++{ ++ Xi18nClient *target = _Xi18nFindClient (i18n_core, connect_id); ++ Xi18nClient *ccp; ++ Xi18nClient *ccp0; ++ ++ for (ccp = i18n_core->address.clients, ccp0 = NULL; ++ ccp != NULL; ++ ccp0 = ccp, ccp = ccp->next) ++ { ++ if (ccp == target) ++ { ++ if (ccp0 == NULL) ++ i18n_core->address.clients = ccp->next; ++ else ++ ccp0->next = ccp->next; ++ /*endif*/ ++ /* put it back to free list */ ++ target->next = i18n_core->address.free_clients; ++ i18n_core->address.free_clients = target; ++ return; ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++} ++ ++void _Xi18nSendMessage (XIMS ims, ++ CARD16 connect_id, ++ CARD8 major_opcode, ++ CARD8 minor_opcode, ++ unsigned char *data, ++ long length) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec packet_header_fr[]; ++ unsigned char *reply_hdr = NULL; ++ int header_size; ++ unsigned char *reply = NULL; ++ unsigned char *replyp; ++ int reply_length; ++ long p_len = length/4; ++ ++ fm = FrameMgrInit (packet_header_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ header_size = FrameMgrGetTotalSize (fm); ++ reply_hdr = (unsigned char *) malloc (header_size); ++ if (reply_hdr == NULL) ++ { ++ _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0); ++ return; ++ } ++ /*endif*/ ++ FrameMgrSetBuffer (fm, reply_hdr); ++ ++ /* put data */ ++ FrameMgrPutToken (fm, major_opcode); ++ FrameMgrPutToken (fm, minor_opcode); ++ FrameMgrPutToken (fm, p_len); ++ ++ reply_length = header_size + length; ++ reply = (unsigned char *) malloc (reply_length); ++ replyp = reply; ++ memmove (reply, reply_hdr, header_size); ++ replyp += header_size; ++ memmove (replyp, data, length); ++ ++ i18n_core->methods.send (ims, connect_id, reply, reply_length); ++ ++ XFree (reply); ++ XFree (reply_hdr); ++ FrameMgrFree (fm); ++} ++ ++void _Xi18nSendTriggerKey (XIMS ims, CARD16 connect_id) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec register_triggerkeys_fr[]; ++ XIMTriggerKey *on_keys = i18n_core->address.on_keys.keylist; ++ XIMTriggerKey *off_keys = i18n_core->address.off_keys.keylist; ++ int on_key_num = i18n_core->address.on_keys.count_keys; ++ int off_key_num = i18n_core->address.off_keys.count_keys; ++ unsigned char *reply = NULL; ++ register int i, total_size; ++ CARD16 im_id; ++ ++ if (on_key_num == 0 && off_key_num == 0) ++ return; ++ /*endif*/ ++ ++ fm = FrameMgrInit (register_triggerkeys_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ /* set iteration count for on-keys list */ ++ FrameMgrSetIterCount (fm, on_key_num); ++ /* set iteration count for off-keys list */ ++ FrameMgrSetIterCount (fm, off_key_num); ++ ++ /* get total_size */ ++ total_size = FrameMgrGetTotalSize (fm); ++ ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ return; ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ /* Right now XIM_OPEN_REPLY hasn't been sent to this new client, so ++ the input-method-id is still invalid, and should be set to zero... ++ Reter to $(XC)/lib/X11/imDefLkup.c:_XimRegisterTriggerKeysCallback ++ */ ++ im_id = 0; ++ FrameMgrPutToken (fm, im_id); /* input-method-id */ ++ for (i = 0; i < on_key_num; i++) ++ { ++ FrameMgrPutToken (fm, on_keys[i].keysym); ++ FrameMgrPutToken (fm, on_keys[i].modifier); ++ FrameMgrPutToken (fm, on_keys[i].modifier_mask); ++ } ++ /*endfor*/ ++ for (i = 0; i < off_key_num; i++) ++ { ++ FrameMgrPutToken (fm, off_keys[i].keysym); ++ FrameMgrPutToken (fm, off_keys[i].modifier); ++ FrameMgrPutToken (fm, off_keys[i].modifier_mask); ++ } ++ /*endfor*/ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_REGISTER_TRIGGERKEYS, ++ 0, ++ reply, ++ total_size); ++ FrameMgrFree (fm); ++ XFree(reply); ++} ++ ++void _Xi18nSetEventMask (XIMS ims, ++ CARD16 connect_id, ++ CARD16 im_id, ++ CARD16 ic_id, ++ CARD32 forward_mask, ++ CARD32 sync_mask) ++{ ++ Xi18n i18n_core = ims->protocol; ++ FrameMgr fm; ++ extern XimFrameRec set_event_mask_fr[]; ++ unsigned char *reply = NULL; ++ register int total_size; ++ ++ fm = FrameMgrInit (set_event_mask_fr, ++ NULL, ++ _Xi18nNeedSwap (i18n_core, connect_id)); ++ ++ total_size = FrameMgrGetTotalSize (fm); ++ reply = (unsigned char *) malloc (total_size); ++ if (!reply) ++ return; ++ /*endif*/ ++ memset (reply, 0, total_size); ++ FrameMgrSetBuffer (fm, reply); ++ ++ FrameMgrPutToken (fm, im_id); /* input-method-id */ ++ FrameMgrPutToken (fm, ic_id); /* input-context-id */ ++ FrameMgrPutToken (fm, forward_mask); ++ FrameMgrPutToken (fm, sync_mask); ++ ++ _Xi18nSendMessage (ims, ++ connect_id, ++ XIM_SET_EVENT_MASK, ++ 0, ++ reply, ++ total_size); ++ ++ FrameMgrFree (fm); ++ XFree(reply); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nX.c b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nX.c +new file mode 100644 +index 0000000..87df6b4 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/IMdkit/lib/i18nX.c +@@ -0,0 +1,497 @@ ++/****************************************************************** ++ ++ Copyright 1994, 1995 by Sun Microsystems, Inc. ++ Copyright 1993, 1994 by Hewlett-Packard Company ++ ++Permission to use, copy, modify, distribute, and sell this software ++and its documentation for any purpose is hereby granted without fee, ++provided that the above copyright notice appear in all copies and ++that both that copyright notice and this permission notice appear ++in supporting documentation, and that the name of Sun Microsystems, Inc. ++and Hewlett-Packard not be used in advertising or publicity pertaining to ++distribution of the software without specific, written prior permission. ++Sun Microsystems, Inc. and Hewlett-Packard make no representations about ++the suitability of this software for any purpose. It is provided "as is" ++without express or implied warranty. ++ ++SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL ++WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY ++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc. ++ ++ This version tidied and debugged by Steve Underwood May 1999 ++ ++******************************************************************/ ++ ++#include ++#include ++#include "FrameMgr.h" ++#include "../include/IMdkit.h" ++#include "../include/Xi18n.h" ++#include "Xi18nX.h" ++#include "XimFunc.h" ++ ++extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16); ++extern Xi18nClient *_Xi18nNewClient(Xi18n); ++extern void _Xi18nDeleteClient(Xi18n, CARD16); ++static Bool WaitXConnectMessage(Display*, Window, ++ XEvent*, XPointer); ++static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer); ++ ++static XClient *NewXClient (Xi18n i18n_core, Window new_client) ++{ ++ Display *dpy = i18n_core->address.dpy; ++ Xi18nClient *client = _Xi18nNewClient (i18n_core); ++ XClient *x_client; ++ ++ x_client = (XClient *) malloc (sizeof (XClient)); ++ x_client->client_win = new_client; ++ x_client->accept_win = XCreateSimpleWindow (dpy, ++ DefaultRootWindow(dpy), ++ 0, ++ 0, ++ 1, ++ 1, ++ 1, ++ 0, ++ 0); ++ client->trans_rec = x_client; ++ return ((XClient *) x_client); ++} ++ ++static unsigned char *ReadXIMMessage (XIMS ims, ++ XClientMessageEvent *ev, ++ int *connect_id) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient *client = i18n_core->address.clients; ++ XClient *x_client = NULL; ++ FrameMgr fm; ++ extern XimFrameRec packet_header_fr[]; ++ unsigned char *p = NULL; ++ unsigned char *p1; ++ ++ while (client != NULL) { ++ x_client = (XClient *) client->trans_rec; ++ if (x_client->accept_win == ev->window) { ++ *connect_id = client->connect_id; ++ break; ++ } ++ client = client->next; ++ } ++ ++ if (ev->format == 8) { ++ /* ClientMessage only */ ++ XimProtoHdr *hdr = (XimProtoHdr *) ev->data.b; ++ unsigned char *rec = (unsigned char *) (hdr + 1); ++ register int total_size; ++ CARD8 major_opcode; ++ CARD8 minor_opcode; ++ CARD16 length; ++ extern int _Xi18nNeedSwap (Xi18n, CARD16); ++ ++ if (client->byte_order == '?') ++ { ++ if (hdr->major_opcode != XIM_CONNECT) ++ return (unsigned char *) NULL; /* can do nothing */ ++ client->byte_order = (CARD8) rec[0]; ++ } ++ ++ fm = FrameMgrInit (packet_header_fr, ++ (char *) hdr, ++ _Xi18nNeedSwap (i18n_core, *connect_id)); ++ total_size = FrameMgrGetTotalSize (fm); ++ /* get data */ ++ FrameMgrGetToken (fm, major_opcode); ++ FrameMgrGetToken (fm, minor_opcode); ++ FrameMgrGetToken (fm, length); ++ FrameMgrFree (fm); ++ ++ if ((p = (unsigned char *) malloc (total_size + length * 4)) == NULL) ++ return (unsigned char *) NULL; ++ ++ p1 = p; ++ memmove (p1, &major_opcode, sizeof (CARD8)); ++ p1 += sizeof (CARD8); ++ memmove (p1, &minor_opcode, sizeof (CARD8)); ++ p1 += sizeof (CARD8); ++ memmove (p1, &length, sizeof (CARD16)); ++ p1 += sizeof (CARD16); ++ memmove (p1, rec, length * 4); ++ } ++ else if (ev->format == 32) { ++ /* ClientMessage and WindowProperty */ ++ unsigned long length = (unsigned long) ev->data.l[0]; ++ Atom atom = (Atom) ev->data.l[1]; ++ int return_code; ++ Atom actual_type_ret; ++ int actual_format_ret; ++ unsigned long bytes_after_ret; ++ unsigned char *prop; ++ unsigned long nitems; ++ ++ return_code = XGetWindowProperty (i18n_core->address.dpy, ++ x_client->accept_win, ++ atom, ++ 0L, ++ length, ++ True, ++ AnyPropertyType, ++ &actual_type_ret, ++ &actual_format_ret, ++ &nitems, ++ &bytes_after_ret, ++ &prop); ++ if (return_code != Success || actual_format_ret == 0 || nitems == 0) { ++ if (return_code == Success) ++ XFree (prop); ++ return (unsigned char *) NULL; ++ } ++ if (length != nitems) ++ length = nitems; ++ if (actual_format_ret == 16) ++ length *= 2; ++ else if (actual_format_ret == 32) ++ length *= 4; ++ ++ /* if hit, it might be an error */ ++ if ((p = (unsigned char *) malloc (length)) == NULL) ++ return (unsigned char *) NULL; ++ ++ memmove (p, prop, length); ++ XFree (prop); ++ } ++ return (unsigned char *) p; ++} ++ ++static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev) ++{ ++ Xi18n i18n_core = ims->protocol; ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ XEvent event; ++ Display *dpy = i18n_core->address.dpy; ++ Window new_client = ev->data.l[0]; ++ CARD32 major_version = ev->data.l[1]; ++ CARD32 minor_version = ev->data.l[2]; ++ XClient *x_client = NewXClient (i18n_core, new_client); ++ ++ if (ev->window != i18n_core->address.im_window) ++ return; /* incorrect connection request */ ++ /*endif*/ ++ if (major_version != 0 || minor_version != 0) ++ { ++ major_version = ++ minor_version = 0; ++ /* Only supporting only-CM & Property-with-CM method */ ++ } ++ /*endif*/ ++ _XRegisterFilterByType (dpy, ++ x_client->accept_win, ++ ClientMessage, ++ ClientMessage, ++ WaitXIMProtocol, ++ (XPointer)ims); ++ event.xclient.type = ClientMessage; ++ event.xclient.display = dpy; ++ event.xclient.window = new_client; ++ event.xclient.message_type = spec->connect_request; ++ event.xclient.format = 32; ++ event.xclient.data.l[0] = x_client->accept_win; ++ event.xclient.data.l[1] = major_version; ++ event.xclient.data.l[2] = minor_version; ++ event.xclient.data.l[3] = XCM_DATA_LIMIT; ++ ++ XSendEvent (dpy, ++ new_client, ++ False, ++ NoEventMask, ++ &event); ++ XFlush (dpy); ++} ++ ++static Bool Xi18nXBegin (XIMS ims) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Display *dpy = i18n_core->address.dpy; ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ ++ spec->xim_request = XInternAtom (i18n_core->address.dpy, ++ _XIM_PROTOCOL, ++ False); ++ spec->connect_request = XInternAtom (i18n_core->address.dpy, ++ _XIM_XCONNECT, ++ False); ++ ++ _XRegisterFilterByType (dpy, ++ i18n_core->address.im_window, ++ ClientMessage, ++ ClientMessage, ++ WaitXConnectMessage, ++ (XPointer)ims); ++ return True; ++} ++ ++static Bool Xi18nXEnd(XIMS ims) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Display *dpy = i18n_core->address.dpy; ++ ++ _XUnregisterFilter (dpy, ++ i18n_core->address.im_window, ++ WaitXConnectMessage, ++ (XPointer)ims); ++ return True; ++} ++ ++static char *MakeNewAtom (CARD16 connect_id, char *atomName) ++{ ++ static int sequence = 0; ++ ++ sprintf (atomName, ++ "_server%d_%d", ++ connect_id, ++ ((sequence > 20) ? (sequence = 0) : sequence++)); ++ return atomName; ++} ++ ++static Bool Xi18nXSend (XIMS ims, ++ CARD16 connect_id, ++ unsigned char *reply, ++ long length) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id); ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ XClient *x_client = (XClient *) client->trans_rec; ++ XEvent event; ++ ++ event.type = ClientMessage; ++ event.xclient.window = x_client->client_win; ++ event.xclient.message_type = spec->xim_request; ++ ++ if (length > XCM_DATA_LIMIT) ++ { ++ Atom atom; ++ char atomName[16]; ++ Atom actual_type_ret; ++ int actual_format_ret; ++ int return_code; ++ unsigned long nitems_ret; ++ unsigned long bytes_after_ret; ++ unsigned char *win_data; ++ ++ event.xclient.format = 32; ++ atom = XInternAtom (i18n_core->address.dpy, ++ MakeNewAtom (connect_id, atomName), ++ False); ++ return_code = XGetWindowProperty (i18n_core->address.dpy, ++ x_client->client_win, ++ atom, ++ 0L, ++ 10000L, ++ False, ++ XA_STRING, ++ &actual_type_ret, ++ &actual_format_ret, ++ &nitems_ret, ++ &bytes_after_ret, ++ &win_data); ++ if (return_code != Success) ++ return False; ++ /*endif*/ ++ if (win_data) ++ XFree ((char *) win_data); ++ /*endif*/ ++ XChangeProperty (i18n_core->address.dpy, ++ x_client->client_win, ++ atom, ++ XA_STRING, ++ 8, ++ PropModeAppend, ++ (unsigned char *) reply, ++ length); ++ event.xclient.data.l[0] = length; ++ event.xclient.data.l[1] = atom; ++ } ++ else ++ { ++ unsigned char buffer[XCM_DATA_LIMIT]; ++ int i; ++ ++ event.xclient.format = 8; ++ ++ /* Clear unused field with NULL */ ++ memmove(buffer, reply, length); ++ for (i = length; i < XCM_DATA_LIMIT; i++) ++ buffer[i] = (char) 0; ++ /*endfor*/ ++ length = XCM_DATA_LIMIT; ++ memmove (event.xclient.data.b, buffer, length); ++ } ++ XSendEvent (i18n_core->address.dpy, ++ x_client->client_win, ++ False, ++ NoEventMask, ++ &event); ++ XFlush (i18n_core->address.dpy); ++ return True; ++} ++ ++static Bool CheckCMEvent (Display *display, XEvent *event, XPointer xi18n_core) ++{ ++ Xi18n i18n_core = (Xi18n) ((void *) xi18n_core); ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ ++ if ((event->type == ClientMessage) ++ && ++ (event->xclient.message_type == spec->xim_request)) ++ { ++ return True; ++ } ++ /*endif*/ ++ return False; ++} ++ ++static Bool Xi18nXWait (XIMS ims, ++ CARD16 connect_id, ++ CARD8 major_opcode, ++ CARD8 minor_opcode) ++{ ++ Xi18n i18n_core = ims->protocol; ++ XEvent event; ++ Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id); ++ XClient *x_client = (XClient *) client->trans_rec; ++ ++ for (;;) ++ { ++ unsigned char *packet; ++ XimProtoHdr *hdr; ++ int connect_id_ret; ++ ++ XIfEvent (i18n_core->address.dpy, ++ &event, ++ CheckCMEvent, ++ (XPointer) i18n_core); ++ if (event.xclient.window == x_client->accept_win) ++ { ++ if ((packet = ReadXIMMessage (ims, ++ (XClientMessageEvent *) & event, ++ &connect_id_ret)) ++ == (unsigned char*) NULL) ++ { ++ return False; ++ } ++ /*endif*/ ++ hdr = (XimProtoHdr *)packet; ++ ++ if ((hdr->major_opcode == major_opcode) ++ && ++ (hdr->minor_opcode == minor_opcode)) ++ { ++ return True; ++ } ++ else if (hdr->major_opcode == XIM_ERROR) ++ { ++ return False; ++ } ++ /*endif*/ ++ } ++ /*endif*/ ++ } ++ /*endfor*/ ++} ++ ++static Bool Xi18nXDisconnect (XIMS ims, CARD16 connect_id) ++{ ++ Xi18n i18n_core = ims->protocol; ++ Display *dpy = i18n_core->address.dpy; ++ Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id); ++ XClient *x_client = (XClient *) client->trans_rec; ++ ++ XDestroyWindow (dpy, x_client->accept_win); ++ _XUnregisterFilter (dpy, ++ x_client->accept_win, ++ WaitXIMProtocol, ++ (XPointer)ims); ++ XFree (x_client); ++ _Xi18nDeleteClient (i18n_core, connect_id); ++ return True; ++} ++ ++Bool _Xi18nCheckXAddress (Xi18n i18n_core, ++ TransportSW *transSW, ++ char *address) ++{ ++ XSpecRec *spec; ++ ++ if (!(spec = (XSpecRec *) malloc (sizeof (XSpecRec)))) ++ return False; ++ /*endif*/ ++ ++ i18n_core->address.connect_addr = (XSpecRec *) spec; ++ i18n_core->methods.begin = Xi18nXBegin; ++ i18n_core->methods.end = Xi18nXEnd; ++ i18n_core->methods.send = Xi18nXSend; ++ i18n_core->methods.wait = Xi18nXWait; ++ i18n_core->methods.disconnect = Xi18nXDisconnect; ++ return True; ++} ++ ++static Bool WaitXConnectMessage (Display *dpy, ++ Window win, ++ XEvent *ev, ++ XPointer client_data) ++{ ++ XIMS ims = (XIMS)client_data; ++ Xi18n i18n_core = ims->protocol; ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ ++ if (((XClientMessageEvent *) ev)->message_type ++ == spec->connect_request) ++ { ++ ReadXConnectMessage (ims, (XClientMessageEvent *) ev); ++ return True; ++ } ++ /*endif*/ ++ return False; ++} ++ ++static Bool WaitXIMProtocol (Display *dpy, ++ Window win, ++ XEvent *ev, ++ XPointer client_data) ++{ ++ extern void _Xi18nMessageHandler (XIMS, CARD16, unsigned char *, Bool *); ++ XIMS ims = (XIMS) client_data; ++ Xi18n i18n_core = ims->protocol; ++ XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr; ++ Bool delete = True; ++ unsigned char *packet; ++ int connect_id; ++ ++ if (((XClientMessageEvent *) ev)->message_type ++ == spec->xim_request) ++ { ++ if ((packet = ReadXIMMessage (ims, ++ (XClientMessageEvent *) ev, ++ &connect_id)) ++ == (unsigned char *) NULL) ++ { ++ return False; ++ } ++ /*endif*/ ++ _Xi18nMessageHandler (ims, connect_id, packet, &delete); ++ if (delete == True) ++ XFree (packet); ++ /*endif*/ ++ return True; ++ } ++ /*endif*/ ++ return False; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/config.h b/src/plugins/platforminputcontexts/hime/include/config.h +new file mode 100644 +index 0000000..2e9289e +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/config.h +@@ -0,0 +1 @@ ++#define GETTEXT_PACKAGE "hime" +diff --git a/src/plugins/platforminputcontexts/hime/include/gst.h b/src/plugins/platforminputcontexts/hime/include/gst.h +new file mode 100644 +index 0000000..3fecd34 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/gst.h +@@ -0,0 +1,63 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++typedef struct { ++ struct CHPHO *chpho; ++ int c_idx, c_len; ++ int ph_sta; // phrase start ++ int sel_pho; ++// int save_frm, save_to; ++ int current_page; ++ int startf; ++ gboolean full_match; ++ gboolean tsin_half_full; ++ gboolean tsin_buffer_editing; ++ gboolean ctrl_pre_sel; ++ struct PRE_SEL *pre_sel; ++ int pre_selN; ++ int last_cursor_idx; ++ int pho_menu_idx; ++// int pho_sel_menu_idx; ++} TSIN_ST; ++extern TSIN_ST tss; ++ ++typedef enum { ++ SAME_PHO_QUERY_none = 0, ++ SAME_PHO_QUERY_gtab_input = 1, ++ SAME_PHO_QUERY_pho_select = 2, ++} SAME_PHO_QUERY; ++ ++typedef struct { ++ int ityp3_pho; ++ int cpg, maxi; ++ int start_idx, stop_idx; ++ char typ_pho[4]; ++ char inph[8]; ++ SAME_PHO_QUERY same_pho_query_state; ++} PHO_ST; ++extern PHO_ST poo; ++ ++#define MAX_TAB_KEY_NUM64_6 (10) ++ ++typedef struct { ++ int S1, E1, last_idx, wild_page, pg_idx, total_matchN, sel1st_i; ++ u_int64_t kval; ++ gboolean last_full, wild_mode, spc_pressed, invalid_spc, more_pg, gtab_buf_select; ++ short defselN, exa_match, ci, gbufN, gbuf_cursor; ++ KeySym inch[MAX_TAB_KEY_NUM64_6]; ++} GTAB_ST; ++extern GTAB_ST ggg; +diff --git a/src/plugins/platforminputcontexts/hime/include/gtab-buf.c b/src/plugins/platforminputcontexts/hime/include/gtab-buf.c +new file mode 100644 +index 0000000..462931e +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/gtab-buf.c +@@ -0,0 +1,1146 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "gtab.h" ++#include "hime-conf.h" ++#include "hime-endian.h" ++#include "pho.h" ++#include "tsin.h" ++#include "tsin-parse.h" ++#include "win-save-phrase.h" ++#include "gtab-buf.h" ++#include "gst.h" ++ ++void disp_gbuf(), ClrIn(), clear_after_put(); ++gboolean gtab_phrase_on(); ++int page_len(); ++void show_win_gtab(); ++void disp_selection0(gboolean phrase_selected, gboolean force_disp); ++void disp_gtab_sel(char *s); ++void add_cache(int start, int usecount, TSIN_PARSE *out, short match_phr_N, short no_match_ch_N, int tc_len); ++int ch_pos_find(char *ch, int pos); ++void inc_gtab_usecount(char *str), ClrSelArea(); ++void lookup_gtabn(char *ch, char *out); ++char *htmlspecialchars(char *s, char out[]); ++void hide_gtab_pre_sel(); ++gboolean gtab_vertical_select_on(); ++ ++extern gboolean key_press_alt, key_press_ctrl; ++ ++extern gboolean test_mode; ++ ++GEDIT *gbuf; ++extern char **seltab; ++extern int ph_key_sz; ++ ++void extract_gtab_key(int start, int len, void *out) ++{ ++ int i; ++ ++ char *p=(char *)out; ++ if (ph_key_sz==4) { ++ for(i=0; i < len; i++) { ++ u_int k = gbuf[i+start].keys[0]; ++ memcpy(p, &k, sizeof(k)); ++ p+=sizeof(k); ++ } ++ } else { ++ for(i=0; i < len; i++) { ++ memcpy(p, &gbuf[i+start].keys[0], sizeof(u_int64_t)); ++ p+=sizeof(u_int64_t); ++ } ++ } ++} ++ ++void extract_gbuf_str(int start, int len, char *out) ++{ ++ int i; ++ out[0]=0; ++ for(i=0;i= 'A' && *s<='Z') || (*s >= 'a' && *s<='z') || strchr("-_'", *s))) ++ break; ++ } else ++ if (sz==2) { ++ char *p; ++ for (p=latin_chars; *p; p+=2) ++ if (!memcmp(p, s, 2)) ++ break; ++ if (!(*p)) ++ break; ++ } else ++ if (sz>=3) ++ break; ++ s+=sz; ++ } ++ ++ if (*s) ++ return 0; ++ return strlen(bf); ++} ++ ++static char *gen_buf_str(int start, gboolean add_spc) ++{ ++ int i; ++ char *out = tmalloc(char, 1); ++ int outN=0; ++ ++ gboolean last_en_word = FALSE; ++ for(i=start;i%s", tsin_cursor_color, spec); ++ else ++ sprintf(www, "%s", spec); ++ t = www; ++ } ++ ++ len = strlen(t); ++ out = trealloc(out, char, outN+len+1); ++ memcpy(out + outN, t, len); ++ outN+=len; ++ out[outN] = 0; ++ } ++ ++ return out; ++} ++ ++ ++void disp_label_edit(char *str); ++ ++static void free_pgbuf(GEDIT *p) ++{ ++ int i; ++ for(i=0; i < p->selN; i++) ++ free(p->sel[i]); ++ free(p->sel); ++ p->ch = NULL; ++ p->sel=NULL; ++ p->flag = 0; ++} ++ ++ ++static void free_gbuf(int idx) ++{ ++ free_pgbuf(&gbuf[idx]); ++} ++ ++ ++static void clear_gtab_buf_all() ++{ ++ int i; ++ for(i=0;iusecount - ((GITEM *)aa)->usecount; ++ if (d) ++ return d; ++ ++ return ((GITEM *)aa)->org_seq - ((GITEM *)bb)->org_seq; ++} ++ ++void hide_row2_if_necessary(); ++ ++unich_t auto_end_punch[] = ", . ? : ; ! [ ] 「 」 , 。 ? ; : 、 ~ ! ( )"; ++GEDIT *insert_gbuf_cursor(char **sel, int selN, u_int64_t key, gboolean b_gtab_en_no_spc) ++{ ++ hide_row2_if_necessary(); ++ ++ if (!sel || !selN) ++ return NULL; ++// dbg("insert_gbuf_cursor %x\n", key); ++ ++ gbuf=trealloc(gbuf, GEDIT, ggg.gbufN+2); ++ ++ GEDIT *pbuf = &gbuf[ggg.gbuf_cursor]; ++ ++ if (ggg.gbuf_cursor < ggg.gbufN) ++ memmove(&gbuf[ggg.gbuf_cursor+1], &gbuf[ggg.gbuf_cursor], sizeof(GEDIT) * (ggg.gbufN - ggg.gbuf_cursor)); ++ ++ ggg.gbuf_cursor++; ++ ggg.gbufN++; ++ ++ bzero(pbuf, sizeof(GEDIT)); ++ bzero(gbuf+ggg.gbufN, sizeof(GEDIT)); ++ ++ GITEM *items = tmalloc(GITEM, selN); ++ ++ int i; ++ for(i=0; i < selN; i++) { ++ items[i].s = sel[i]; ++ items[i].org_seq = i; ++ items[i].usecount = get_gtab_use_count(sel[i]); ++ } ++ qsort(items, selN, sizeof(GITEM), qcmp_gitem); ++ ++ for(i=0; i < selN; i++) ++ sel[i] = items[i].s; ++ ++ pbuf->ch = sel[0]; ++ pbuf->sel = sel; ++ pbuf->selN = selN; ++ pbuf->c_sel = 0; ++ pbuf->keys[0] = key; ++ pbuf->keysN=1; ++ pbuf->flag = b_gtab_en_no_spc ? FLAG_CHPHO_GTAB_BUF_EN_NO_SPC:0; ++ ++ if (hime_punc_auto_send && ggg.gbufN==ggg.gbuf_cursor && selN==1 && strstr(_(auto_end_punch), sel[0])) { ++ char_play(pbuf->ch); ++ output_gbuf(); ++ } else { ++ gtab_parse(); ++ disp_gbuf(); ++ char_play(pbuf->ch); ++ } ++ ++ free(items); ++ return pbuf; ++} ++ ++ ++void set_gbuf_c_sel(int v) ++{ ++ GEDIT *pbuf = cursor_gbuf(); ++ ++ pbuf->c_sel = v + ggg.pg_idx; ++ pbuf->ch = pbuf->sel[pbuf->c_sel]; ++// dbg("zzzsel v:%d %d %s\n",v, pbuf->c_sel,pbuf->ch); ++ pbuf->flag |= FLAG_CHPHO_FIXED; ++ ggg.gtab_buf_select = 0; ++ ggg.more_pg = 0; ++ disp_gtab_sel(""); ++ gtab_parse(); ++ disp_gbuf(); ++// dbg("zzzsel v:%d\n", pbuf->c_sel); ++} ++ ++GEDIT *insert_gbuf_cursor1(char *s, u_int64_t key, gboolean b_gtab_en_no_spc) ++{ ++ if (!gtab_phrase_on()) ++ return NULL; ++ ++// dbg("insert_gbuf_cursor1 %s %x\n", s, key); ++ char **sel = tmalloc(char *, 1); ++ sel[0] = strdup(s); ++ GEDIT *e = insert_gbuf_cursor(sel, 1, key, b_gtab_en_no_spc); ++ clear_after_put(); ++ return e; ++} ++ ++void insert_gbuf_cursor_phrase(char *s, void *key, int N) ++{ ++ u_int *key32 = (u_int *)key; ++ u_int64_t *key64 = (u_int64_t *)key; ++ ++ int i; ++ for(i=0; i < N; i++) { ++ char ch[CH_SZ+1]; ++ int n = utf8cpy(ch, s); ++ u_int64_t v = ph_key_sz==4?key32[i]:key64[i]; ++ GEDIT *e = insert_gbuf_cursor1(ch, v, TRUE); ++ e->flag |= FLAG_CHPHO_FIXED; ++ s+=n; ++ } ++} ++ ++static int key_N(u_int64_t k) ++{ ++ int n=0; ++ int mask = (1 << KeyBits) - 1; ++ ++ while (k) { ++ k>>=mask; ++ n++; ++ } ++ ++ return n; ++} ++ ++static int qcmp_key_N(const void *aa, const void *bb) ++{ ++ u_int64_t a = *((u_int64_t *)aa); ++ u_int64_t b = *((u_int64_t *)bb); ++ ++ return key_N(a) - key_N(b); ++} ++ ++ ++void insert_gbuf_nokey(char *s) ++{ ++ if (!gtab_phrase_on()) ++ return; ++ ++// dbg("insert_gbuf_nokey\n"); ++ ++ int i; ++ u_int64_t keys[32]; ++ int keysN=0; ++ int sz = utf8_sz(s); ++ ++ keys[0]=0; ++ if (cur_inmd->tbl64) { ++ for(i=0; i < cur_inmd->DefChars; i++) { ++ if (!memcmp(cur_inmd->tbl64[i].ch, s, sz)) { ++ u_int64_t t; ++ memcpy(&t, cur_inmd->tbl64[i].key, sizeof(u_int64_t)); ++ keys[keysN++] = t; ++ } ++ } ++ } else ++ if (cur_inmd->tbl) { ++ for(i=0; i < cur_inmd->DefChars; i++) { ++ if (!memcmp(cur_inmd->tbl[i].ch, s, sz)) { ++ u_int t; ++ memcpy(&t, cur_inmd->tbl[i].key, sizeof(u_int)); ++ keys[keysN++] = t; ++ } ++ } ++ } ++ ++ qsort(keys, keysN, sizeof(u_int64_t), qcmp_key_N); ++ ++ GEDIT *e = insert_gbuf_cursor1(s, keys[0], TRUE); ++ if (keysN > 8) ++ keysN = 8; ++ ++ memcpy(e->keys, keys, sizeof(u_int64_t) * keysN); ++ e->keysN = keysN; ++} ++ ++void insert_gbuf_cursor1_cond(char *s, u_int64_t key, gboolean valid_key) ++{ ++ if (valid_key) ++ insert_gbuf_cursor1(s, key, FALSE); ++ else ++ insert_gbuf_nokey(s); ++} ++ ++void insert_gbuf_cursor_char(char ch) ++{ ++ char t[2]; ++ t[0]=ch; ++ t[1]=0; ++ insert_gbuf_cursor1(t, 0, TRUE); ++} ++ ++gboolean gtab_has_input(); ++void hide_win_gtab(); ++ ++int gtab_buf_delete_ex(gboolean auto_hide) ++{ ++ if (ggg.gbuf_cursor==ggg.gbufN) ++ return 0; ++ ++ if (test_mode) ++ return 1; ++ ++ if (ggg.gtab_buf_select) ++ clear_gbuf_sel(); ++ ++ free_gbuf(ggg.gbuf_cursor); ++ memmove(&gbuf[ggg.gbuf_cursor], &gbuf[ggg.gbuf_cursor+1], sizeof(GEDIT) * (ggg.gbufN - ggg.gbuf_cursor -1)); ++ ggg.gbufN--; ++ disp_gbuf(); ++ ++ if (hime_pop_up_win && !gtab_has_input() && auto_hide) ++ hide_win_gtab(); ++ ++ return 1; ++} ++ ++int gtab_buf_delete() ++{ ++ return gtab_buf_delete_ex(TRUE); ++} ++ ++ ++gboolean gtab_has_input(); ++void hide_win_gtab(); ++ ++int gtab_buf_backspace_ex(gboolean auto_hide) ++{ ++ if (!ggg.gbuf_cursor) { ++ return ggg.gbufN>0; ++ } ++ ggg.gbuf_cursor--; ++ gtab_buf_delete_ex(auto_hide); ++ ++ if (hime_pop_up_win && !gtab_has_input() && auto_hide) ++ hide_win_gtab(); ++ ++ return 1; ++} ++ ++int gtab_buf_backspace() ++{ ++ return gtab_buf_backspace_ex(TRUE); ++} ++ ++ ++void gtab_buf_backspaceN(int n) ++{ ++ int i; ++ for(i=0; i < n; i++) ++ gtab_buf_backspace_ex(FALSE); ++} ++ ++extern int more_pg; ++ ++void gtab_disp_sel() ++{ ++ int idx = ggg.gbuf_cursor==ggg.gbufN ? ggg.gbuf_cursor-1:ggg.gbuf_cursor; ++ GEDIT *pbuf=&gbuf[idx]; ++ ++ int i; ++ for(i=0; i < cur_inmd->M_DUP_SEL; i++) { ++ int v = i + ggg.pg_idx; ++ if (v >= pbuf->selN) ++ seltab[i][0]=0; ++ else ++ strcpy(seltab[i], pbuf->sel[v]); ++ } ++ ++ if (pbuf->selN > page_len()) ++ ggg.more_pg = 1; ++ disp_selection0(FALSE, TRUE); ++ show_win_gtab(); ++} ++ ++ ++int show_buf_select() ++{ ++ if (!ggg.gbufN) ++ return 0; ++ ++ int idx = ggg.gbuf_cursor==ggg.gbufN ? ggg.gbuf_cursor-1:ggg.gbuf_cursor; ++ GEDIT *pbuf=&gbuf[idx]; ++ ggg.gtab_buf_select = 1; ++ ggg.total_matchN = pbuf->selN; ++ ggg.pg_idx = 0; ++ ++ gtab_disp_sel(); ++ hide_gtab_pre_sel(); ++ ++ return 1; ++} ++ ++void gbuf_prev_pg() ++{ ++ ggg.pg_idx -= page_len(); ++ if (ggg.pg_idx < 0) ++ ggg.pg_idx = 0; ++ ++ gtab_disp_sel(); ++} ++ ++void gbuf_next_pg() ++{ ++ ggg.pg_idx += page_len(); ++ if (ggg.pg_idx >= ggg.total_matchN) ++ ggg.pg_idx = 0; ++ ++ gtab_disp_sel(); ++} ++ ++#include "im-client/hime-im-client-attr.h" ++ ++int get_DispInArea_str(char *out); ++ ++int gtab_get_preedit(char *str, HIME_PREEDIT_ATTR attr[], int *pcursor, int *sub_comp_len) ++{ ++ int i=0; ++ int strN=0; ++ int attrN=0; ++ int ch_N=0; ++ ++// dbg("gtab_get_preedit\n"); ++ str[0]=0; ++ *pcursor=0; ++ ++ *sub_comp_len = ggg.ci > 0; ++#if 1 ++ if (ggg.gbufN && !hime_edit_display_ap_only()) ++ *sub_comp_len|=4; ++#endif ++ gboolean ap_only = hime_edit_display_ap_only(); ++ ++ if (gtab_phrase_on()) { ++ attr[0].flag=HIME_PREEDIT_ATTR_FLAG_UNDERLINE; ++ attr[0].ofs0=0; ++ ++ if (ggg.gbufN) ++ attrN=1; ++ ++ gboolean last_is_en_word = FALSE; ++ for(i=0; i < ggg.gbufN; i++) { ++ char *s = gbuf[i].ch; ++ char tt[MAX_CIN_PHR+2]; ++ ++ if (en_word_len(s) && !(gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)) { ++ if (last_is_en_word) { ++ strcpy(tt, " "); ++ strcat(tt, s); ++ s = tt; ++ } ++ last_is_en_word = TRUE; ++ } else { ++ last_is_en_word = FALSE; ++ } ++ ++ int len = strlen(s); ++ int N = utf8_str_N(s); ++ ch_N+=N; ++ if (i < ggg.gbuf_cursor) ++ *pcursor+=N; ++ if (ap_only && i==ggg.gbuf_cursor) { ++ attr[1].ofs0=*pcursor; ++ attr[1].ofs1=*pcursor+N; ++ attr[1].flag=HIME_PREEDIT_ATTR_FLAG_REVERSE; ++ attrN++; ++ } ++ ++ if (hime_display_on_the_spot_key() && i==ggg.gbuf_cursor) ++ strN += get_DispInArea_str(str+strN); ++ ++ memcpy(str+strN, s, len); ++ strN+=len; ++ } ++ } ++ ++ ++ if (hime_display_on_the_spot_key() && i==ggg.gbuf_cursor) ++ strN += get_DispInArea_str(str+strN); ++ ++ str[strN]=0; ++ ++ attr[0].ofs1 = ch_N; ++ return attrN; ++} ++ ++extern GtkWidget *gwin_gtab; ++void gtab_reset() ++{ ++ if (!gwin_gtab) ++ return; ++ clear_gtab_buf_all(); ++ clear_gbuf_sel(); ++ ClrIn(); ++ return; ++} ++ ++int ch_to_gtab_keys(INMD *tinmd, char *ch, u_int64_t keys[]); ++ ++void save_gtab_buf_phrase_idx(int idx0, int len) ++{ ++ WSP_S wsp[MAX_PHRASE_LEN]; ++ ++ bzero(wsp, sizeof(wsp)); ++ int i; ++ for(i=0; i < len; i++) { ++ u8cpy(wsp[i].ch, gbuf[idx0 + i].ch); ++ u_int64_t key = gbuf[idx0 + i].keys[0]; ++ ++ if (!key) { ++ u_int64_t keys[64]; ++ int keysN = ch_to_gtab_keys(cur_inmd, wsp[i].ch, keys); ++ if (keysN) ++ key = keys[0]; ++ } ++ ++ wsp[i].key = key; ++ } ++ ++ create_win_save_phrase(wsp, len); ++} ++ ++void save_gtab_buf_phrase(KeySym key) ++{ ++ int len = key - '0'; ++ int idx0 = ggg.gbuf_cursor - len; ++ int idx1 = ggg.gbuf_cursor - 1; ++ ++ if (idx0 < 0 || idx0 > idx1) ++ return; ++ ++ save_gtab_buf_phrase_idx(idx0, len); ++} ++ ++gboolean save_gtab_buf_shift_enter() ++{ ++ if (!ggg.gbufN) ++ return 0; ++ int idx0 = 0; ++ if (ggg.gbufN != ggg.gbuf_cursor) ++ idx0 = ggg.gbuf_cursor; ++ int len = ggg.gbufN - idx0; ++ if (len > MAX_PHRASE_LEN) ++ return 0; ++ ++ save_gtab_buf_phrase_idx(idx0, len); ++ gbuf_cursor_end(); ++ return 1; ++} ++ ++ ++void load_tsin_db0(char *infname, gboolean is_gtab_i); ++gboolean init_tsin_table_fname(INMD *p, char *fname); ++ ++void init_tsin_table() ++{ ++ char fname[256]; ++ if (!current_CS) ++ return; ++ ++ init_tsin_table_fname(&inmd[current_CS->in_method], fname); ++ load_tsin_db0(fname, TRUE); ++} ++ ++extern u_char scanphr_e(int chpho_idx, int plen, gboolean pho_incr, int *rselN); ++void init_pre_sel(); ++void clear_sele(); ++void set_sele_text(int tN, int i, char *text, int len); ++void get_win_gtab_geom(); ++void disp_selections(int x, int y); ++ ++gboolean use_tsin_sel_win(); ++void init_tsin_selection_win(); ++ ++static int gtab_pre_select_phrase_len; ++ ++void disp_gtab_pre_sel(char *s); ++extern GtkWidget *gwin1; ++ ++void gtab_scan_pre_select(gboolean b_incr) ++{ ++ if (!gtab_phrase_pre_select) ++ return; ++// dbg("gtab_scan_pre_select\n"); ++ ++ tss.pre_selN = 0; ++ ++ hide_gtab_pre_sel(); ++ ++ if (!gtab_cursor_end() || !ggg.gbufN) ++ return; ++ ++ init_tsin_table(); ++ init_pre_sel(); ++ ++ int Maxlen = ggg.gbufN; ++ if (Maxlen > MAX_PHRASE_LEN) ++ Maxlen = MAX_PHRASE_LEN; ++ ++ int len, selN, max_len=-1, max_selN; ++ for(len=1; len <= Maxlen; len++) { ++ int idx = ggg.gbufN - len; ++ if (gbuf[idx].flag & FLAG_CHPHO_PHRASE_TAIL) ++ break; ++ int mlen = scanphr_e(ggg.gbufN - len, len, b_incr, &selN); ++ if (mlen) { ++ max_len = len; ++ max_selN = selN; ++ } ++ } ++ ++// dbg("max_len:%d max_selN:%d\n", max_len, max_selN); ++ ++ if (max_len < 0 || max_selN >= strlen(cur_inmd->selkey) * 2) { ++ tss.pre_selN = 0; ++ return; ++ } ++ ++ gtab_pre_select_phrase_len = max_len; ++ ++ scanphr_e(ggg.gbufN - max_len, max_len, b_incr, &selN); ++ ++// dbg("selN:%d %d\n", selN, tss.pre_selN); ++ ++ if (selN==1 && tss.pre_sel[0].len==max_len) { ++ char out[MAX_PHRASE_LEN * CH_SZ + 1]; ++ extract_gbuf_str(ggg.gbufN - max_len, max_len, out); ++ if (!strcmp(out, tss.pre_sel[0].str)) ++ return; ++ } ++ ++// dbg("selN %d %d\n",selN, tss.pre_selN); ++ ++ if (use_tsin_sel_win()) { ++ if (gwin1) ++ clear_sele(); ++ else ++ init_tsin_selection_win(); ++ ++ int i; ++ for(i=0;i%c%s%s", hime_sel_key_color, cur_inmd->selkey[i], tss.pre_sel[i].str, br); ++ else ++ sprintf(ts, "%c%s%s", cur_inmd->selkey[i], tss.pre_sel[i].str, br); ++ strcat(tt, ts); ++ if (!gtab_vertical_select_on() && i < tss.pre_selN-1) ++ strcat(tt, " "); ++ } ++ ++// dbg("tt %s\n", tt); ++ disp_gtab_pre_sel(tt); ++} ++ ++ ++int shift_key_idx(char *s, KeySym xkey); ++ ++gboolean gtab_pre_select_idx(int c) ++{ ++ if (c < 0) ++ return FALSE; ++ if (c >= tss.pre_selN) ++ return TRUE; ++ ++#if 0 ++ dbg("c %d %s ggg.gbuf_cursor:%d,%d\n", c, tss.pre_sel[c].str, ++ ggg.gbuf_cursor, ggg.gbufN); ++#endif ++ ++ gtab_buf_backspaceN(gtab_pre_select_phrase_len); ++ int len = tss.pre_sel[c].len; ++ insert_gbuf_cursor_phrase(tss.pre_sel[c].str, tss.pre_sel[c].phkey, len); ++ gbuf[ggg.gbufN-1].flag |= FLAG_CHPHO_PHRASE_TAIL; ++ ++ hide_gtab_pre_sel(); ++ if (hime_pop_up_win) ++ hide_win_gtab(); ++ ++ return TRUE; ++} ++ ++gboolean gtab_pre_select_shift(KeySym key, int kbstate) ++{ ++// dbg("gtab_pre_select_shift %c\n", key); ++ if (!gtab_phrase_pre_select || !tss.pre_selN) ++ return FALSE; ++ ++ int c = shift_key_idx(cur_inmd->selkey, key); ++ return gtab_pre_select_idx(c); ++} ++ ++void tsin_toggle_eng_ch(); ++ ++int feedkey_gtab_release(KeySym xkey, int kbstate) ++{ ++ switch (xkey) { ++ case XK_Control_L: ++ case XK_Control_R: ++ if (key_press_ctrl && tss.pre_selN) { ++ if (!test_mode) { ++ tss.ctrl_pre_sel = TRUE; ++ } ++ key_press_ctrl = FALSE; ++ return 1; ++ } else ++ return 0; ++#if 1 ++ case XK_Shift_L: ++ case XK_Shift_R: ++// dbg("release xkey %x\n", xkey); ++ if (((tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift) || ++ (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL && xkey == XK_Shift_L) || ++ (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR && xkey == XK_Shift_R)) && ++ key_press_alt) { ++ if (!test_mode) { ++ tsin_toggle_eng_ch(); ++ } ++ key_press_alt = FALSE; ++ return 1; ++ } else ++ return 0; ++#endif ++ default: ++ return 0; ++ } ++} ++ ++#include "win1.h" ++ ++void gtab_set_win1_cb() ++{ ++ set_win1_cb((cb_selec_by_idx_t)gtab_pre_select_idx, NULL, NULL); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/gtab-buf.h b/src/plugins/platforminputcontexts/hime/include/gtab-buf.h +new file mode 100644 +index 0000000..6ee7803 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/gtab-buf.h +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++typedef struct { ++ char *ch; ++ char **sel; ++ int selN; ++ u_short flag; ++ u_char c_sel; ++ char plen, keysN; ++ u_int64_t keys[8]; ++} GEDIT; ++ ++extern GEDIT *gbuf; ++extern short gbufN; ++ ++void insert_gbuf_nokey(char *s); ++void insert_gbuf_cursor1_cond(char *s, u_int64_t key, gboolean valid_key); ++GEDIT *insert_gbuf_cursor(char **sel, int selN, u_int64_t key, gboolean b_gtab_en_no_spc); +diff --git a/src/plugins/platforminputcontexts/hime/include/gtab.c b/src/plugins/platforminputcontexts/hime/include/gtab.c +new file mode 100644 +index 0000000..708fa06 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/gtab.c +@@ -0,0 +1,1832 @@ ++/* Copyright (C) 2004-2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include "hime.h" ++#include "gtab.h" ++#include "pho.h" ++#include "hime-conf.h" ++#include "hime-endian.h" ++#include "gtab-buf.h" ++#include "tsin.h" ++#include "gst.h" ++ ++extern gboolean test_mode; ++gboolean gtab_phrase_on(); ++gboolean gtab_disp_partial_match_on(), gtab_vertical_select_on(), gtab_pre_select_on(), gtab_unique_auto_send_on(), gtab_press_full_auto_send_on(); ++void init_seltab(char ***p); ++ ++extern gboolean key_press_alt, key_press_ctrl; ++ ++extern GtkWidget *gwin_gtab; ++void hide_gtab_pre_sel(); ++void gtab_scan_pre_select(gboolean); ++ ++extern GTAB_space_pressed_E _gtab_space_auto_first; ++extern char *TableDir; ++ ++extern INMD *cur_inmd; ++extern char **seltab; ++ ++extern char str_key_codes[128]; ++void disp_pho_sel(char *s); ++ ++#define gtab_full_space_auto_first (_gtab_space_auto_first & (GTAB_space_auto_first_any|GTAB_space_auto_first_full)) ++#define AUTO_SELECT_BY_PHRASE (gtab_phrase_on()) ++ ++gboolean use_tsin_sel_win() ++{ ++ return gtab_vertical_select_on() && gtab_phrase_pre_select; ++} ++ ++ ++static gboolean gtab_pre_select_or_partial_on() ++{ ++ return gtab_pre_select_on() || (cur_inmd->flag&FLAG_GTAB_DISP_PARTIAL_MATCH)!=0; ++} ++ ++gboolean same_query_show_pho_win() ++{ ++ return poo.same_pho_query_state != SAME_PHO_QUERY_none; ++} ++ ++gboolean hime_edit_display_ap_only(); ++gboolean gtab_has_input() ++{ ++ int i; ++ ++ for(i=0; i < MAX_TAB_KEY_NUM64_6; i++) ++ if (ggg.inch[i]) ++ return TRUE; ++ ++ if (same_query_show_pho_win()) ++ return TRUE; ++ ++ if (ggg.gtab_buf_select) ++ return TRUE; ++ ++ if (ggg.gbufN && !hime_edit_display_ap_only()) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++#define tblch(i) tblch2(cur_inmd, i) ++ ++int load_phr_ch(INMD *inm, u_char *ch, char *tt) ++{ ++ int phrno =((int)(ch[0])<<16)|((int)ch[1]<<8)|ch[2]; ++ int ofs = inm->phridx[phrno], ofs1 = inm->phridx[phrno+1]; ++ ++// dbg("load_phr j:%d %d %d %d\n", j, phrno, ofs, ofs1); ++ int len = ofs1 - ofs; ++ ++ if (len > MAX_CIN_PHR || len <= 0) { ++ dbg("phrae error %d\n", len); ++ strcpy(tt,"err"); ++ return 0; ++ } ++ ++ memcpy(tt, inm->phrbuf + ofs, len); ++ tt[len]=0; ++ return len; ++} ++ ++static void load_phr(int j, char *tt) ++{ ++ u_char *ch = tblch(j); ++ ++ load_phr_ch(cur_inmd, ch, tt); ++} ++ ++static int qcmp_strlen(const void *aa, const void *bb) ++{ ++ char *a = *((char **)aa), *b = *((char **)bb); ++ ++ return strlen(a) - strlen(b); ++} ++ ++void set_key_codes_label(char *s, int better); ++void set_page_label(char *s); ++ ++static void clear_page_label() ++{ ++ set_page_label(""); ++} ++ ++int gtab_key2name(INMD *tinmd, u_int64_t key, char *t, int *rtlen); ++ ++ ++int ch_to_gtab_keys(INMD *tinmd, char *ch, u_int64_t keys[]) ++{ ++ int n = utf8_str_N(ch); ++ gboolean phrase = n > 1 || !(ch[0] & 0x80); ++ int i, keysN=0; ++ for(i=0; i < tinmd->DefChars; i++) { ++ char *chi = (char *)tblch2(tinmd, i); ++ ++ if (phrase) { ++ if ((chi[0] & 0x80)) ++ continue; ++ char tstr[512]; ++ load_phr_ch(tinmd, (u_char *)chi, tstr); ++ if (strcmp(tstr, ch)) ++ continue; ++ } else { ++ if (!(chi[0] & 0x80)) ++ continue; ++ if (!utf8_eq(chi, ch)) ++ continue; ++ } ++ ++ u_int64_t key = CONVT2(tinmd, i); ++ keys[keysN++] = key; ++ } ++ return keysN; ++} ++ ++void lookup_gtabn(char *ch, char *out) ++{ ++ char outbuf[512]; ++ char *tbuf[128]; ++ int tbufN=0; ++ INMD *tinmd = &inmd[default_input_method]; ++ ++ if (!tinmd->DefChars) ++ tinmd = cur_inmd; ++ ++ if (!tinmd) ++ return; ++ ++ gboolean need_disp = FALSE; ++ ++ if (!out) { ++ out = outbuf; ++ need_disp = TRUE; ++ } ++ ++ out[0]=0; ++ ++ ++ int min_klen = 100; ++ u_int64_t keys[64]; ++ int keysN = ch_to_gtab_keys(tinmd, ch, keys); ++ ++ int i; ++ for(i=0; i < keysN; i++) { ++ int tlen, klen; ++ char t[CH_SZ * 10 + 1]; ++ ++ klen = gtab_key2name(tinmd, keys[i], t, &tlen); ++ ++ if (klen < min_klen) ++ min_klen = klen; ++ ++ t[tlen]=0; ++ ++ tbuf[tbufN] = strdup(t); ++ tbufN++; ++ } ++ ++ ++ qsort(tbuf, tbufN, sizeof(char *), qcmp_strlen); ++ out[0]=0; ++ ++ for(i=0; i < tbufN; i++) { ++#define MAX_DISP_MATCH 40 ++ if (strlen(out) < MAX_DISP_MATCH) { ++ strcat(out, tbuf[i]); ++ if (i < tbufN-1) ++ strcat(out, " |"); ++ } ++ ++ free(tbuf[i]); ++ } ++ ++ if (!out[0] || !need_disp) ++ return; ++ ++ ++ set_key_codes_label(out, ggg.ci > min_klen); ++ void set_key_codes_label_pho(char *s); ++ set_key_codes_label_pho(out); ++} ++ ++void lookup_gtab(char *ch) ++{ ++ char tt[CH_SZ+1]; ++ utf8cpy(tt, ch); ++ lookup_gtabn(tt, NULL); ++} ++ ++ ++void lookup_gtab_out(char *ch, char *out) ++{ ++ char tt[CH_SZ+1]; ++ utf8cpy(tt, ch); ++ lookup_gtabn(tt, out); ++} ++ ++void free_gtab() ++{ ++ int i; ++ ++ for(i=0; i < inmdN; i++) { ++ INMD *inp = &inmd[i]; ++ free(inp->tbl); inp->tbl = NULL; ++ free(inp->tbl64); inp->tbl64 = NULL; ++ free(inp->phridx); inp->phridx = NULL; ++ free(inp->phrbuf); inp->phrbuf = NULL; ++ free(inp->keyname_lookup); inp->keyname_lookup = NULL; ++ } ++ ++ free(inmd); ++} ++ ++ ++char *b1_cat(char *s, char c) ++{ ++ char t[2]; ++ t[0]=c; ++ t[1]=0; ++ ++ return strcat(s, t); ++} ++ ++ ++char *bch_cat(char *s, char *ch) ++{ ++ char t[CH_SZ + 1]; ++ int len = u8cpy(t, ch); ++ t[len]=0; ++ ++ return strcat(s, t); ++} ++ ++ ++void disp_gtab_sel(char *s); ++ ++void ClrSelArea() ++{ ++ disp_gtab_sel(""); ++// hide_gtab_pre_sel(); ++} ++ ++ ++void disp_gtab(char *); ++void clear_gtab_input_error_color(); ++ ++static void clr_seltab() ++{ ++ int i; ++ if (!seltab) ++ return; ++ ++ for(i=0; i < MAX_SELKEY; i++) ++ seltab[i][0]=0; ++} ++ ++void clear_gtab_in_area(), hide_win_gtab(); ++void ClrIn() ++{ ++ bzero(ggg.inch,sizeof(ggg.inch)); ++ clr_seltab(); ++ ggg.total_matchN=ggg.pg_idx=ggg.more_pg=ggg.wild_mode=ggg.wild_page=ggg.last_idx=ggg.defselN=ggg.exa_match= ++ ggg.spc_pressed=ggg.ci=ggg.invalid_spc=0; ++ ++ ggg.sel1st_i=MAX_SELKEY-1; ++ ++ clear_gtab_in_area(); ++ ggg.last_idx = 0; ++ ++ if (hime_pop_up_win && !gtab_has_input() && !tss.pre_selN) ++ hide_win_gtab(); ++ ++ clear_gtab_input_error_color(); ++ clear_page_label(); ++// hide_gtab_pre_sel(); ++} ++ ++ ++void hide_win_pho(); ++ ++void close_gtab_pho_win() ++{ ++ if (test_mode) ++ return; ++ if (same_query_show_pho_win()) { ++ poo.same_pho_query_state = SAME_PHO_QUERY_none; ++ hide_win_pho(); ++ if (hime_pop_up_win && (str_key_codes[0]!='\0')) ++ hide_win_gtab(); ++ } ++} ++ ++void gtab_disp_empty(char *tt, int N); ++extern int win_gtab_max_key_press; ++ ++static void DispInArea() ++{ ++ int i; ++ ++// hide_gtab_pre_sel(); ++ ++// dbg("sel1st:%d\n", ggg.sel1st_i); ++ if (hime_display_on_the_spot_key()) { ++ if (hime_pop_up_win && gwin_gtab && GTK_WIDGET_VISIBLE(gwin_gtab) && poo.same_pho_query_state == SAME_PHO_QUERY_none) ++ hide_win_gtab(); ++ return; ++ } ++ ++ char tt[128]; ++ int ttN=0; ++ ++ if (win_gtab_max_key_press < ggg.ci) ++ win_gtab_max_key_press = ggg.ci; ++ ++ for(i=0;ikeyname[ggg.inch[i] * CH_SZ]; ++ int len; ++ if (*p & 0x80) ++ len=utf8cpy(tt+ttN, p); ++ else { ++ len = strlen(p); ++ strcpy(tt+ttN, p); ++ } ++ ++ ttN+=len; ++ } ++ ++ tt[ttN]=0; ++ ++ gtab_disp_empty(tt, win_gtab_max_key_press - i); ++ ++ disp_gtab(tt); ++} ++ ++int get_DispInArea_str(char *out) ++{ ++ int outN=0, i; ++ for(i=0;ikeyname[ggg.inch[i] * CH_SZ]; ++ if (*p & 0x80) ++ outN+=u8cpy(out+outN, p); ++ else { ++ int len = strlen(p); ++ memcpy(out+outN, p, len); ++ outN+=len; ++ } ++ } ++ ++#if 0 ++ if (outN) { ++ hide_gtab_pre_sel(); ++ } ++#endif ++ ++ out[outN]=0; ++// dbg("get_DispInArea_str\n", out); ++ return outN; ++} ++ ++ ++void set_gtab_input_method_name(char *s); ++void case_inverse(KeySym *xkey, int shift_m); ++ ++extern unich_t *fullchar[]; ++ ++void start_gtab_pho_query(char *utf8); ++ ++void clear_after_put() ++{ ++ ClrIn(); ++ ClrSelArea(); ++} ++ ++void add_to_tsin_buf_str(char *str); ++gboolean init_in_method(int in_no); ++void hide_win_kbm(); ++ ++void hide_row2_if_necessary() ++{ ++ if ((!ggg.wild_mode && gtab_hide_row2) || !gtab_disp_key_codes) { ++ set_key_codes_label(NULL, 0); ++ } ++} ++ ++static void putstr_inp(char *p) ++{ ++ clear_page_label(); ++ ++// dbg("gtab_hide_row2 %d\n", gtab_hide_row2); ++ hide_row2_if_necessary(); ++ ++ char_play(p); ++ ++ int to_tsin = (cur_inmd->flag & FLAG_GTAB_SYM_KBM) && inmd[default_input_method].method_type==method_type_TSIN && tss.c_len; ++ ++ if (utf8_str_N(p) > 1 || !(p[0]&128)) { ++ if ((gtab_disp_key_codes && !gtab_hide_row2) || ggg.wild_mode) ++ lookup_gtabn(p, NULL); ++ if (to_tsin) { ++ add_to_tsin_buf_str(p); ++ } ++ else ++ send_text(p); ++ } ++ else { ++ if (poo.same_pho_query_state == SAME_PHO_QUERY_gtab_input) { ++ poo.same_pho_query_state = SAME_PHO_QUERY_pho_select; ++ start_gtab_pho_query(p); ++ ++ ClrIn(); ++ ClrSelArea(); ++ return; ++ } ++ ++ if ((gtab_disp_key_codes && !gtab_hide_row2) || ggg.wild_mode) ++ lookup_gtab(p); ++ ++ if (to_tsin) ++ add_to_tsin_buf_str(p); ++ else ++ send_utf8_ch(p); ++ } ++ ++ clear_after_put(); ++ ++ if ((cur_inmd->flag & FLAG_GTAB_SYM_KBM)) { ++ extern int win_kbm_inited, hime_show_win_kbm; ++ init_in_method(default_input_method); ++ if (win_kbm_inited && !hime_show_win_kbm) ++ hide_win_kbm(); ++ } ++} ++ ++ ++#define swap(a,b) { tt=a; a=b; b=tt; } ++ ++static u_int vmask[]= ++{ 0, ++ (0x3f<<24), ++ (0x3f<<24)|(0x3f<<18), ++ (0x3f<<24)|(0x3f<<18)|(0x3f<<12), ++ (0x3f<<24)|(0x3f<<18)|(0x3f<<12)|(0x3f<<6), ++ (0x3f<<24)|(0x3f<<18)|(0x3f<<12)|(0x3f<<6)|0x3f ++}; ++ ++ ++static u_int vmask_7[]= ++{ 0, ++ (0x7f<<21), ++ (0x7f<<21)|(0x7f<<14), ++ (0x7f<<21)|(0x7f<<14)|(0x7f<<7), ++ (0x7f<<21)|(0x7f<<14)|(0x7f<<7)|0x7f, ++}; ++ ++#define KKK ((u_int64_t)0x3f) ++ ++ ++static u_int64_t vmask64[]= ++{ 0, ++ (KKK<<54), ++ (KKK<<54)|(KKK<<48), ++ (KKK<<54)|(KKK<<48)|(KKK<<42), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30)|(KKK<<24), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30)|(KKK<<24)|(KKK<<18), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30)|(KKK<<24)|(KKK<<18)|(KKK<<12), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30)|(KKK<<24)|(KKK<<18)|(KKK<<12)|(KKK<<6), ++ (KKK<<54)|(KKK<<48)|(KKK<<42)|(KKK<<36)|(KKK<<30)|(KKK<<24)|(KKK<<18)|(KKK<<12)|(KKK<<6)|KKK ++}; ++ ++ ++#define KKK7 ((u_int64_t)0x7f) ++ ++static u_int64_t vmask64_7[]= ++{ 0, ++ (KKK7<<56), ++ (KKK7<<56)|(KKK7<<49), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35)|(KKK7<<28), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35)|(KKK7<<28)|(KKK7<<21), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35)|(KKK7<<28)|(KKK7<<21)|(KKK7<<14), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35)|(KKK7<<28)|(KKK7<<21)|(KKK7<<14)|(KKK7<<7), ++ (KKK7<<56)|(KKK7<<49)|(KKK7<<42)|(KKK7<<35)|(KKK7<<28)|(KKK7<<21)|(KKK7<<14)|(KKK7<<7)|KKK7, ++}; ++ ++ ++#define KEY_N (cur_inmd->max_keyN) ++ ++static gboolean load_seltab(int tblidx, int seltabidx) ++{ ++ u_char *tbl_ch = tblch(tblidx); ++ if (tbl_ch[0] < 0x80) { ++ load_phr(tblidx, seltab[seltabidx]); ++ return TRUE; ++ } ++ ++ int len = u8cpy(seltab[seltabidx], (char *)tbl_ch); ++ seltab[seltabidx][len] = 0; ++ ++ return FALSE; ++} ++ ++ ++static char* load_tblidx(int tblidx) ++{ ++ char tt[MAX_CIN_PHR]; ++ u_char *tbl_ch = tblch(tblidx); ++ if (tbl_ch[0] < 0x80) { ++ load_phr(tblidx, tt); ++ } else { ++ int len = u8cpy(tt, (char *)tbl_ch); ++ tt[len] = 0; ++ } ++ ++ return strdup(tt); ++} ++ ++ ++void set_gtab_input_error_color(); ++static void bell_err() ++{ ++ if (test_mode) ++ return; ++ ++ bell(); ++ set_gtab_input_error_color(); ++} ++ ++gboolean cmp_inmd_idx(regex_t *reg, int idx) ++{ ++ u_int64_t kk=CONVT2(cur_inmd, idx); ++ char ts[32]; ++ int tsN=0; ++ ++ ts[tsN++]= ' '; ++ ++ int i; ++ for(i=0; i < KEY_N; i++) { ++ char c = (kk >> (LAST_K_bitN - i*cur_inmd->keybits)) & cur_inmd->kmask; ++ if (!c) ++ break; ++ ts[tsN++] = c + '0'; ++ } ++ ++ ts[tsN++]= ' '; ++ ts[tsN]=0; ++ ++ return regexec(reg, ts, 0, 0, 0); ++} ++ ++int page_len() ++{ ++ return (_gtab_space_auto_first & GTAB_space_auto_first_any) ? ++ cur_inmd->M_DUP_SEL+1:cur_inmd->M_DUP_SEL; ++} ++ ++static void page_no_str(char tstr[]) ++{ ++ if (ggg.wild_mode || ggg.gtab_buf_select) { ++ int pgN = (ggg.total_matchN + cur_inmd->M_DUP_SEL - 1) / cur_inmd->M_DUP_SEL; ++ if (pgN < 2) ++ return; ++ ++ int pg = ggg.gtab_buf_select ? ggg.pg_idx : ggg.wild_page; ++ sprintf(tstr, "%d/%d", pg /cur_inmd->M_DUP_SEL + 1, pgN); ++ } else { ++ int pgN = (ggg.E1 - ggg.S1 + page_len() - 1) /page_len(); ++ ++ if (pgN < 2) ++ return; ++ ++ sprintf(tstr, "%d/%d", (ggg.pg_idx - ggg.S1)/page_len()+1, pgN); ++ } ++} ++ ++char *htmlspecialchars(char *s, char out[]) ++{ ++ struct { ++ char c; ++ char *str; ++ } chs[]= {{'>',"gt"}, {'<',"lt"}, {'&',"amp"} ++#if 0 ++ , {' ',"nbsp"} ++#endif ++ }; ++ int chsN=sizeof(chs)/sizeof(chs[0]); ++ ++ int outn=0; ++ while (*s) { ++ int sz = utf8_sz(s); ++ int i; ++ for(i=0; iM_DUP_SEL + ofs-1; max_i>=0; max_i--) ++ if (seltab[max_i][0]) ++ break; ++ ++ for(i=ofs; i<= max_i; i++) { ++ if (seltab[i][0]) { ++ char selback[MAX_CIN_PHR+16]; ++ htmlspecialchars(seltab[i], selback); ++ ++ utf8cpy(uu, &cur_inmd->selkey[i - ofs]); ++ char vvv[16]; ++ char www[1024]; ++ if (hime_win_color_use) ++ sprintf(www, "%s", hime_sel_key_color, htmlspecialchars(uu, vvv)); ++ else ++ sprintf(www, "%s", htmlspecialchars(uu, vvv)); ++ strcat(tt, www); ++ ++ if (gtab_vertical_select_on()) ++ strcat(tt, " "); ++ ++ if (phrase_selected && i==ggg.sel1st_i) { ++ strcat(tt, ""); ++ strcat(strcat(tt, selback), " "); ++ strcat(tt, ""); ++ } else { ++ char uu[MAX_CIN_PHR]; ++ ++ if (gtab_vertical_select_on()) { ++ utf8cpy_bytes(uu, selback, 120); ++ strcat(tt, uu); ++ } else { ++ char *p = selback; ++ ++ static char *skip[]={"http://", "ftp://", "https://", NULL}; ++ ++ int j; ++ for(j=0; skip[j]; j++) ++ if (!strncmp(seltab[i], skip[j], strlen(skip[j]))) { ++ p+=strlen(skip[j]); ++ break; ++ } ++ ++ utf8cpy_bytes(uu, p, 6 * 3); ++ strcat(strcat(tt, uu), " "); ++ } ++ } ++ ++ if (gtab_vertical_select_on()) ++ strcat(tt, "\n"); ++ } else { ++ extern gboolean b_use_full_space; ++ ++ if (!gtab_vertical_select_on() && gtab_disp_partial_match_on()) { ++ if (b_use_full_space) ++ strcat(tt, "   "); ++ else { ++ strcat(tt, " "); ++ } ++ } ++ } ++ } ++ ++ if (gtab_vertical_select_on() && pgstr[0]) { ++ char tstr2[16]; ++ sprintf(tstr2, "(%s)", pgstr); ++ strcat(tt, tstr2); ++ } ++ ++ int len = strlen(tt); ++ if (len && tt[len-1] == '\n') ++ tt[len-1] = 0; ++ ++ if (gtab_pre_select_or_partial_on() || ggg.wild_mode || ggg.spc_pressed || ggg.last_full || force_disp) { ++ disp_gtab_sel(tt); ++ } ++} ++ ++ ++void disp_selection(gboolean phrase_selected) ++{ ++ disp_selection0(phrase_selected, FALSE); ++} ++ ++void wildcard() ++{ ++ int i,t, wild_ofs=0; ++ int found=0; ++ regex_t reg; ++ ++ ClrSelArea(); ++ clr_seltab(); ++ /* printf("wild %d %d %d %d\n", ggg.inch[0], ggg.inch[1], ggg.inch[2], ggg.inch[3]); */ ++ ggg.defselN=0; ++ char regstr[32]; ++ int regstrN=0; ++ ++ regstr[regstrN++]=' '; ++ ++ for(i=0; i < KEY_N; i++) { ++ if (!ggg.inch[i]) ++ break; ++ if (ggg.inch[i] == cur_inmd->WILD_STAR) { ++ regstr[regstrN++]='.'; ++ regstr[regstrN++]='*'; ++ } else ++ if (ggg.inch[i] == cur_inmd->WILD_QUES) { ++ regstr[regstrN++]='.'; ++ } else { ++ char c = ggg.inch[i] + '0'; // start from '0' ++ if (strchr("*.\\()[]", c)) ++ regstr[regstrN++] = '\\'; ++ regstr[regstrN++]=c; ++ } ++ } ++ ++ regstr[regstrN++]=' '; ++ regstr[regstrN]=0; ++ ++// dbg("regstr %s\n", regstr); ++ ++ if (regcomp(®, regstr, 0)) { ++ dbg("regcomp failed\n"); ++ return; ++ } ++ ++ for(t=0; t< cur_inmd->DefChars && ggg.defselN < cur_inmd->M_DUP_SEL; t++) { ++ if (cmp_inmd_idx(®, t)) ++ continue; ++ ++ if (wild_ofs >= ggg.wild_page) { ++ load_seltab(t, ggg.defselN); ++ ggg.defselN++; ++ } else ++ wild_ofs++; ++ ++ found=1; ++ } /* for t */ ++ ++ ++ if (!found) { ++ bell_err(); ++ } else ++ if (!ggg.wild_page) { ++ ggg.total_matchN = 0; ++ ++ for(t=0; t< cur_inmd->DefChars; t++) ++ if (!cmp_inmd_idx(®, t)) ++ ggg.total_matchN++; ++ ++ } ++ ++ if (ggg.total_matchN > cur_inmd->M_DUP_SEL) ++ ggg.more_pg = 1; ++ ++ regfree(®); ++ disp_selection(FALSE); ++} ++ ++static char *ptr_selkey(KeySym key) ++{ ++ if (key>= XK_KP_0 && key<= XK_KP_9) ++ key-= XK_KP_0 - '0'; ++ return strchr(cur_inmd->selkey, key); ++} ++ ++ ++void init_gtab_pho_query_win(); ++int feedkey_pho(KeySym xkey, int state); ++ ++void set_gtab_target_displayed() ++{ ++ close_gtab_pho_win(); ++} ++ ++gboolean is_gtab_query_mode() ++{ ++ return poo.same_pho_query_state == SAME_PHO_QUERY_pho_select; ++} ++ ++void reset_gtab_all() ++{ ++ if (!cur_inmd) ++ return; ++ ++ ClrIn(); ++ ClrSelArea(); ++} ++ ++ ++static gboolean has_wild_card() ++{ ++ int i; ++ ++ for(i=0; i < cur_inmd->MaxPress; i++) ++ if (ggg.inch[i]>= cur_inmd->WILD_QUES) { ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static void proc_wild_disp() ++{ ++ DispInArea(); ++ ggg.wild_page = 0; ++ wildcard(); ++ disp_selection(0); ++} ++ ++gboolean full_char_proc(KeySym keysym); ++void insert_gbuf_cursor_char(char ch); ++gboolean gtab_pre_select_shift(KeySym key, int kbstate); ++ ++gboolean shift_char_proc(KeySym key, int kbstate) ++{ ++ if (key >= 127) ++ return FALSE; ++ ++#if 0 ++ if (kbstate & LockMask) { ++ if (key >= 'a' && key <= 'z') ++ key-=0x20; ++ } else { ++ if (key >= 'A' && key <= 'Z') ++ key+=0x20; ++ } ++#endif ++ ++ if (gtab_pre_select_shift(key, kbstate)) ++ return TRUE; ++ ++ if (current_CS->b_half_full_char) ++ return full_char_proc(key); ++ ++ if (ggg.gbufN) ++ insert_gbuf_cursor_char(key); ++ else ++ send_ascii(key); ++ ++ return TRUE; ++} ++ ++extern GtkWidget *gwin_pho; ++gboolean feed_phrase(KeySym ksym, int state); ++int gtab_buf_backspace(); ++gboolean output_gbuf(); ++int show_buf_select(); ++void gbuf_next_pg(), gbuf_prev_pg(); ++void show_win_gtab(); ++int gbuf_cursor_left(); ++int gbuf_cursor_right(); ++int gbuf_cursor_home(); ++int gbuf_cursor_end(); ++int gtab_buf_delete(); ++void set_gbuf_c_sel(int v); ++void set_gtab_user_head(); ++KeySym keypad_proc(KeySym xkey); ++void save_gtab_buf_phrase(KeySym key); ++gboolean save_gtab_buf_shift_enter(); ++gboolean win_sym_page_up(), win_sym_page_down(); ++u_int64_t vmaskci; ++gboolean gtab_pre_select_idx(int c); ++void save_CS_current_to_temp(); ++void tsin_set_eng_ch(int nmod); ++ ++gboolean feedkey_gtab(KeySym key, int kbstate) ++{ ++ int i,j=0; ++ int inkey=0; ++ char *pselkey= NULL; ++ gboolean phrase_selected = FALSE; ++ char seltab_phrase[MAX_SELKEY]; ++ gboolean is_keypad = FALSE; ++ gboolean shift_m = (kbstate & ShiftMask) > 0; ++// gboolean ctrl_m = (kbstate & ControlMask) > 0; ++ gboolean capslock_on = (kbstate & LockMask); ++ ++ bzero(seltab_phrase, sizeof(seltab_phrase)); ++ ++// dbg("uuuuu %x %x shift,ctrl:%d,%d\n", key, kbstate, shift_m, ctrl_m); ++ ++ if (!cur_inmd) ++ return 0; ++ ++ gboolean is_dayi = !strncmp(cur_inmd->filename, "dayi", 4); ++ ++ if ((tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_CapsLock) && ++ (key == XK_Caps_Lock)){ ++ // The CapLock status may be incorrect when XK_Caps_Lock is pressed. ++ gboolean new_tsin_pho_mode = ! gdk_keymap_get_caps_lock_state(gdk_keymap_get_default()); ++ if (current_CS->tsin_pho_mode != new_tsin_pho_mode) { ++ current_CS->tsin_pho_mode = new_tsin_pho_mode; ++ save_CS_current_to_temp(); ++ tsin_set_eng_ch(new_tsin_pho_mode); ++ } ++ } ++ ++ if ((kbstate & (Mod1Mask|Mod4Mask|Mod5Mask|ControlMask))==ControlMask ++ && key>='1' && key<='9' && ggg.gbufN) { ++ save_gtab_buf_phrase(key); ++ return 1; ++ } ++ ++ if (ggg.gbufN && key==XK_Tab) ++ return 1; ++ ++ if ((key==XK_Shift_L||key==XK_Shift_R) && !key_press_alt) { ++ key_press_alt = TRUE; ++ key_press_ctrl = FALSE; ++ } else if ((key==XK_Control_L||key==XK_Control_R) && !key_press_ctrl && tss.pre_selN) { ++ key_press_alt = FALSE; ++ key_press_ctrl = TRUE; ++ return TRUE; ++ } else { ++ key_press_alt = FALSE; ++ key_press_ctrl = FALSE; ++ } ++ ++ if (kbstate & (Mod1Mask|Mod4Mask|Mod5Mask|ControlMask)) { ++ return 0; ++ } ++ ++ if (poo.same_pho_query_state == SAME_PHO_QUERY_pho_select) ++ return feedkey_pho(key, 0); ++ ++ if (poo.same_pho_query_state == SAME_PHO_QUERY_none && gwin_pho && ++ GTK_WIDGET_VISIBLE(gwin_pho)) ++ hide_win_pho(); ++ ++ if (!tsin_pho_mode()) { ++ if (key < 0x20 || key>=0x7f) ++ goto shift_proc; ++ ++ if (capslock_on && hime_capslock_lower) ++ case_inverse((KeySym *)&key, shift_m); ++ ++ if (ggg.gbufN) ++ insert_gbuf_cursor_char(key); ++ else ++ send_ascii(key); ++ ++ return 1; ++ } ++ ++ ++ int lcase; ++ lcase = tolower(key); ++ int ucase; ++ ucase = toupper(key); ++ if (key < 127 && cur_inmd->keymap[key]) { ++ if (key < 'A' || key > 'z' || (key > 'Z' && key < 'a') ) ++ goto shift_proc; ++ if (cur_inmd->keymap[lcase] != cur_inmd->keymap[ucase]) ++ goto next; ++ } ++ ++ ++shift_proc: ++ if (shift_m && !strchr(cur_inmd->selkey, key) && !ggg.more_pg && key>=' ' && key < 0x7e && ++ key!='*' && (key!='?' || (gtab_shift_phrase_key && !ggg.ci))) { ++ if (gtab_shift_phrase_key) { ++ if (tss.pre_selN && shift_char_proc(key, kbstate)) ++ return TRUE; ++ if (feed_phrase(key, kbstate)) ++ return TRUE; ++ } else { ++ if (!cur_inmd->keymap[key] || (lcase != ucase && ++ cur_inmd->keymap[lcase]==cur_inmd->keymap[ucase])) ++ return shift_char_proc(key, kbstate); ++ } ++ } ++ ++ gboolean has_wild; ++ has_wild = FALSE; ++ ++ switch (key) { ++ case XK_BackSpace: ++ ggg.last_idx=0; ++ ggg.spc_pressed=0; ++ ggg.sel1st_i=MAX_SELKEY-1; ++ clear_gtab_input_error_color(); ++ hide_gtab_pre_sel(); ++ ++ if (ggg.ci==0) { ++ if (AUTO_SELECT_BY_PHRASE) ++ return gtab_buf_backspace(); ++ else ++ return 0; ++ } ++ ++ if (ggg.ci>0) ++ ggg.inch[--ggg.ci]=0; ++ ++ if (has_wild_card()) { ++ proc_wild_disp(); ++ return 1; ++ } ++ ++ ++ ggg.wild_mode=0; ++ ggg.invalid_spc = FALSE; ++ if (ggg.ci==1 && cur_inmd->use_quick) { ++ int i; ++ clr_seltab(); ++ for(i=0;iM_DUP_SEL;i++) ++ utf8cpy(seltab[i], (char *)cur_inmd->qkeys->quick1[ggg.inch[0]-1][i]); ++ ++ ggg.defselN=cur_inmd->M_DUP_SEL; ++ DispInArea(); ++ goto Disp_opt; ++ } else ++ if (ggg.ci==2 && cur_inmd->use_quick) { ++ int i; ++ clr_seltab(); ++ for(i=0;iM_DUP_SEL;i++) ++ utf8cpy(seltab[i], (char *)cur_inmd->qkeys->quick2[ggg.inch[0]-1][ggg.inch[1]-1][i]); ++ ++ ggg.defselN=cur_inmd->M_DUP_SEL; ++ DispInArea(); ++ goto Disp_opt; ++ } ++ ++ break; ++ case XK_KP_Enter: ++ case XK_Return: ++ if (AUTO_SELECT_BY_PHRASE) { ++ hide_gtab_pre_sel(); ++ if (shift_m) { ++ return save_gtab_buf_shift_enter(); ++ } else ++ return output_gbuf(); ++ } ++ else ++ return 0; ++ case XK_Up: ++ if (gtab_has_input()) ++ return TRUE; ++ return FALSE; ++ case XK_Down: ++ case XK_KP_Down: ++ if (AUTO_SELECT_BY_PHRASE) ++ return show_buf_select(); ++ else ++ return 0; ++ case XK_Escape: ++ hide_gtab_pre_sel(); ++ if (ggg.gtab_buf_select) { ++ ggg.gtab_buf_select = 0; ++ reset_gtab_all(); ++ ClrSelArea(); ++ if (hime_pop_up_win && !gtab_has_input()) ++ hide_win_gtab(); ++ return 1; ++ } ++ ClrSelArea(); ++ close_gtab_pho_win(); ++ if (ggg.ci) { ++ reset_gtab_all(); ++ return 1; ++ } else { ++ if (ggg.gbufN) { ++ set_gtab_user_head(); ++ return 1; ++ } ++ ClrIn(); ++ return 0; ++ } ++ case XK_Prior: ++ case XK_KP_Prior: ++ case XK_KP_Subtract: ++ if (ggg.wild_mode) { ++ if (ggg.wild_page >= cur_inmd->M_DUP_SEL) ggg.wild_page-=cur_inmd->M_DUP_SEL; ++ wildcard(); ++ return 1; ++ } else ++ if (ggg.more_pg) { ++ if (ggg.gtab_buf_select) { ++ gbuf_prev_pg(); ++ return 1; ++ } ++ ++ ggg.pg_idx -= page_len(); ++ if (ggg.pg_idx < ggg.S1) ++ ggg.pg_idx = ggg.S1; ++ ++ goto next_pg; ++ } ++ ++ if (key==XK_KP_Subtract) ++ goto keypad_proc; ++ ++ return win_sym_page_up(); ++ case XK_Next: ++ case XK_KP_Next: ++ case XK_KP_Add: ++ if (ggg.more_pg) { ++ if (ggg.gtab_buf_select) { ++ gbuf_next_pg(); ++ return 1; ++ } ++next_page: ++// dbg("more...\n"); ++ ggg.pg_idx += page_len(); ++ if (ggg.pg_idx >=ggg.E1) ++ ggg.pg_idx = ggg.S1; ++ goto next_pg; ++ } else { ++ if (key==XK_KP_Add) ++ goto keypad_proc; ++ if (win_sym_page_down()) ++ return TRUE; ++ if (!ggg.gtab_buf_select && ggg.gbufN && AUTO_SELECT_BY_PHRASE) ++ return show_buf_select(); ++ return FALSE; ++ } ++ case ' ': ++ hide_gtab_pre_sel(); ++ ++ if (ggg.invalid_spc && gtab_invalid_key_in) ++ ClrIn(); ++ ++ if (!gtab_invalid_key_in && ggg.spc_pressed && ggg.invalid_spc) { ++ ClrIn(); ++ return 1; ++ } ++ ++ has_wild = has_wild_card(); ++ ++// dbg("ggg.wild_mode:%d ggg.more_pg:%d ggg.ci:%d has_wild:%d\n", ggg.wild_mode, ggg.more_pg, ggg.ci, has_wild); ++ ++ if (ggg.wild_mode) { ++ // request from tetralet ++ if (!ggg.wild_page && ggg.total_matchN < cur_inmd->M_DUP_SEL) { ++ ggg.sel1st_i = 0; ++ goto direct_select; ++ } ++ ++ ggg.wild_page += cur_inmd->M_DUP_SEL; ++ if (ggg.wild_page >= ggg.total_matchN) ++ ggg.wild_page=0; ++ ++ wildcard(); ++ ggg.spc_pressed = TRUE; ++ return 1; ++ } else ++ if (ggg.more_pg && !(_gtab_space_auto_first & GTAB_space_auto_first_any)) { ++ if (ggg.gtab_buf_select) { ++ gbuf_next_pg(); ++ return 1; ++ } ++ else ++ goto next_page; ++ } else ++ if (ggg.ci==0) { ++ if (current_CS->b_half_full_char) ++ return full_char_proc(key); ++ ++ if (ggg.gbufN) { ++ output_gbuf(); ++ } else ++ return 0; ++ } else ++ if (!has_wild) { ++// dbg("iii %d ggg.defselN:%d %d\n", ggg.sel1st_i, ggg.defselN, cur_inmd->M_DUP_SEL); ++ if (_gtab_space_auto_first == GTAB_space_auto_first_any && seltab[0][0] && ++ ggg.sel1st_i==MAX_SELKEY-1) { ++ ggg.sel1st_i = 0; ++ } ++ ++ if (_gtab_space_auto_first == GTAB_space_auto_first_nofull && ggg.exa_match > 1 ++ && !AUTO_SELECT_BY_PHRASE && gtab_dup_select_bell) ++ bell(); ++ ++ if (seltab[ggg.sel1st_i][0]) { ++// dbg("ggg.last_full %d %d\n", ggg.last_full,ggg.spc_pressed); ++ if (gtab_full_space_auto_first || ggg.spc_pressed) { ++direct_select: ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) { ++// dbg("ins ggg.kval %x\n", ggg.kval); ++ insert_gbuf_cursor1_cond(seltab[ggg.sel1st_i], ggg.kval, ggg.exa_match); ++ } ++ else ++ putstr_inp(seltab[ggg.sel1st_i]); /* select 1st */ ++ return 1; ++ } ++ } ++ } ++ ++ ggg.last_full=0; ++ ggg.spc_pressed=1; ++// dbg("spc_pressed=1\n"); ++ ++ if (has_wild) { ++ ggg.wild_page=0; ++ ggg.wild_mode=1; ++ wildcard(); ++ return 1; ++ } ++ ++ break; ++ case '?': ++ case '*': ++ if ((!gtab_que_wild_card && key == '?') || (!gtab_que_wild_card_asterisk && key == '*')) { ++ inkey=cur_inmd->keymap[key]; ++ if ((inkey && (inkey!=cur_inmd->WILD_QUES && inkey!=cur_inmd->WILD_STAR)) || ptr_selkey(key)) ++ goto next; ++ if (AUTO_SELECT_BY_PHRASE && ggg.gbufN) { ++ insert_gbuf_cursor_char(key); ++ return 1; ++ } else { ++ if (current_CS->b_half_full_char) ++ return full_char_proc(key); ++ else ++ return 0; ++ } ++ } ++ if (tss.pre_selN && shift_char_proc(key, kbstate)) ++ return TRUE; ++ ++ // if (current_CS->b_half_full_char) ++ // return full_char_proc(key); ++ ++ inkey=cur_inmd->keymap[key]; ++ if ((inkey && (inkey!=cur_inmd->WILD_STAR && inkey!=cur_inmd->WILD_QUES)) || ptr_selkey(key)) { ++// dbg("%d %d\n", inkey, cur_inmd->WILD_STAR); ++ goto next; ++ } ++ if (ggg.ci< cur_inmd->MaxPress) { ++ ggg.inch[ggg.ci++]=inkey; ++ DispInArea(); ++ ++ if (hime_pop_up_win) ++ show_win_gtab(); ++ ++ ggg.total_matchN = 0; ++ ggg.wild_page=0; ++ ggg.wild_mode=1; ++ wildcard(); ++ return 1; ++ } ++ return 0; ++ case XK_Left: ++ case XK_KP_Left: ++ return gbuf_cursor_left(); ++ case XK_Right: ++ case XK_KP_Right: ++ return gbuf_cursor_right(); ++ case XK_Home: ++ case XK_KP_Home: ++ return gbuf_cursor_home(); ++ case XK_End: ++ case XK_KP_End: ++ return gbuf_cursor_end(); ++ case XK_Delete: ++ case XK_KP_Delete: ++ return gtab_buf_delete(); ++ case XK_Shift_L: ++ case XK_Shift_R: ++ case XK_Control_R: ++ case XK_Control_L: ++ case XK_Alt_L: ++ case XK_Alt_R: ++ case XK_Caps_Lock: ++ return 0; ++ case '`': ++ if (gtab_pho_query && !cur_inmd->keymap[key]) { ++ poo.same_pho_query_state = SAME_PHO_QUERY_gtab_input; ++ reset_gtab_all(); ++ disp_gtab_sel(_("輸入要查的同音字,接著在注音視窗選字")); ++ if (hime_pop_up_win) ++ show_win_gtab(); ++ disp_pho_sel(""); ++ init_gtab_pho_query_win(); ++ return 1; ++ } ++ default: ++next: ++ ++ if (key < 0x7f) ++ inkey= cur_inmd->keymap[key]; ++ else ++ inkey = 0; ++ ++ if (shift_m && !inkey && !tss.ctrl_pre_sel && ++ tss.pre_selN && shift_char_proc(key, kbstate)) ++ return TRUE; ++ ++ clear_gtab_input_error_color(); ++ ++ if (ggg.invalid_spc && gtab_invalid_key_in) { ++ ClrIn(); ++ } ++ if (key>=XK_KP_0 && key<=XK_KP_9) { ++ if (!ggg.ci) { ++ if (ggg.gbufN) { ++ insert_gbuf_cursor_char(key - XK_KP_0 + '0'); ++ return 1; ++ } else ++ return 0; ++ } ++ if (is_dayi) { ++ key = key - XK_KP_0 + '0'; ++ is_keypad = TRUE; ++ } ++ } ++ ++ int keypad; ++keypad_proc: ++ keypad = keypad_proc(key); ++ if (keypad) { ++ if (!ggg.ci) { ++ if (ggg.gbufN) { ++ insert_gbuf_cursor_char(keypad); ++ return 1; ++ } else ++ return 0; ++ } ++ } ++ char *pendkey = strchr(cur_inmd->endkey, key); ++ ++ pselkey=ptr_selkey(key); ++ ++ if (!pselkey && (key < 32 || key > 0x7e) && (gtab_full_space_auto_first || ggg.spc_pressed)) { ++// dbg("%x %x ggg.sel1st_i:%d '%c'\n", pselkey, key, ggg.sel1st_i, seltab[ggg.sel1st_i][0]); ++ if (seltab[ggg.sel1st_i][0]) { ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ insert_gbuf_cursor1_cond(seltab[ggg.sel1st_i], ggg.kval, ggg.exa_match); ++ else ++ putstr_inp(seltab[ggg.sel1st_i]); /* select 1st */ ++ } ++ ++ return 0; ++ } ++ ++ ++ ++// dbg("ggg.spc_pressed %d %d %d is_keypad:%d\n", ggg.spc_pressed, ggg.last_full, cur_inmd->MaxPress, is_keypad); ++ ++#if 1 // for dayi, testcase : 6 space keypad6 ++ int vv = pselkey - cur_inmd->selkey; ++ if (pselkey && tss.pre_selN && !ggg.gtab_buf_select && (tss.ctrl_pre_sel|| ++ ((!inkey||ggg.spc_pressed||is_keypad)&&! gtab_disp_partial_match_on() && !gtab_pre_select_on()))) { ++ if (gtab_pre_select_idx(vv)) ++ return TRUE; ++ } else ++ if (( (ggg.spc_pressed||ggg.last_full||is_keypad) ||(ggg.wild_mode && (!inkey ||pendkey)) || ggg.gtab_buf_select) && pselkey) { ++ if ((_gtab_space_auto_first & GTAB_space_auto_first_any) && !ggg.wild_mode) ++ vv++; ++ ++ if (vv<0) ++ vv=9; ++ ++ if (seltab[vv][0]) { ++ if (AUTO_SELECT_BY_PHRASE && !same_query_show_pho_win()) { ++ if (ggg.gtab_buf_select && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ set_gbuf_c_sel(vv); ++ else ++ insert_gbuf_cursor1_cond(seltab[vv], ggg.kval, ggg.exa_match); ++ } ++ else { ++ putstr_inp(seltab[vv]); ++ } ++ ++ if (hime_pop_up_win && !gtab_has_input()) ++ hide_win_gtab(); ++ ++ return 1; ++ } ++ } ++#endif ++ ++// dbg("iii %x sel1st_i:%d auto:%d\n", pselkey, ggg.sel1st_i, AUTO_SELECT_BY_PHRASE); ++ if (seltab[ggg.sel1st_i][0] && !ggg.wild_mode && ++ (gtab_full_space_auto_first||ggg.spc_pressed||ggg.last_full) ) { ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ insert_gbuf_cursor1_cond(seltab[ggg.sel1st_i], ggg.kval, ggg.exa_match); ++ else ++ putstr_inp(seltab[ggg.sel1st_i]); /* select 1st */ ++ } ++#if 0 ++ if (key > 0x7f) { ++ return 0; ++ } ++#endif ++ ++ ggg.spc_pressed=0; ++ ++ // for cj & boshiamy to input digits ++ if (!ggg.ci && !inkey) { ++ if (current_CS->b_half_full_char) ++ return full_char_proc(key); ++ else { ++ if (ggg.gbufN && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) { ++ insert_gbuf_cursor_char(key); ++ return 1; ++ } ++ else ++ return 0; ++ } ++ } ++ ++ if (ggg.wild_mode && inkey>=1 && ggg.ci< cur_inmd->MaxPress) { ++ ggg.inch[ggg.ci++]=inkey; ++ if (hime_pop_up_win) ++ show_win_gtab(); ++ proc_wild_disp(); ++ return 1; ++ } ++ ++ if (inkey>=1 && ggg.ci< cur_inmd->MaxPress) { ++ ggg.inch[ggg.ci++]=inkey; ++ hide_gtab_pre_sel(); ++ ++ if (hime_pop_up_win) ++ show_win_gtab(); ++ ggg.last_full=0; ++ ++ if (cur_inmd->use_quick && !pendkey) { ++ if (ggg.ci==1) { ++ int i; ++ for(i=0;i < cur_inmd->M_DUP_SEL; i++) { ++ utf8cpy(seltab[i], (char *)&cur_inmd->qkeys->quick1[inkey-1][i]); ++ } ++ ++ ggg.defselN=cur_inmd->M_DUP_SEL; ++ DispInArea(); ++ goto Disp_opt; ++ } else ++ if (ggg.ci==2 && !pselkey) { ++ int i; ++ for(i=0;i < cur_inmd->M_DUP_SEL; i++) { ++ utf8cpy(seltab[i], (char *)&cur_inmd->qkeys->quick2[ggg.inch[0]-1][inkey-1][i]); ++ } ++ ++ ggg.defselN=cur_inmd->M_DUP_SEL; ++ DispInArea(); ++ goto Disp_opt; ++ } ++ } ++ } else ++ if (ggg.ci == cur_inmd->MaxPress && !pselkey) { ++ bell(); ++ return 1; ++ } ++ ++ ++ if (inkey) { ++ for(i=0; i < MAX_TAB_KEY_NUM64_6; i++) ++ if (ggg.inch[i]>=cur_inmd->WILD_QUES) { ++ DispInArea(); ++ if (ggg.ci==cur_inmd->MaxPress) { ++ ggg.wild_mode=1; ++ ggg.wild_page=0; ++ wildcard(); ++ } ++ ++ return 1; ++ } ++ } else { ++ if (!pselkey) { ++ if (current_CS->b_half_full_char) ++ return full_char_proc(key); ++ else { ++ if (key>=' ' && key<0x7f && AUTO_SELECT_BY_PHRASE && ggg.gbufN) ++ insert_gbuf_cursor_char(key); ++ else ++ return 0; ++ } ++ } ++ ++ if (ggg.defselN) { ++ goto YYYY; ++ } ++ } ++ } /* switch */ ++ ++ ++ if (ggg.ci==0) { ++ ClrSelArea(); ++ ClrIn(); ++ return 1; ++ } ++ ++ ggg.invalid_spc = FALSE; ++ char *pendkey = NULL; ++ pendkey = strchr(cur_inmd->endkey, key); ++ ++ DispInArea(); ++ ++ ggg.kval=0; ++ ++ for(i=0; i < Max_tab_key_num; i++) { ++ ggg.kval|= (u_int64_t)ggg.inch[i] << (KeyBits * (Max_tab_key_num - 1 - i)); ++ } ++ ++#if 1 ++ if (ggg.last_idx) ++ ggg.S1=ggg.last_idx; ++ else ++#endif ++ ggg.S1=cur_inmd->idx1[ggg.inch[0]]; ++ ++// dbg("--------- ch:%d %d val %llx ggg.S1:%d\n", ggg.inch[0], Max_tab_key_num, ggg.kval, ggg.S1); ++ ++ int oE1; ++ oE1=cur_inmd->idx1[ggg.inch[0]+1]; ++ if (cur_inmd->keybits==6) ++ vmaskci = cur_inmd->key64 ? vmask64[ggg.ci]:vmask[ggg.ci]; ++ else ++ vmaskci = cur_inmd->key64 ? vmask64_7[ggg.ci]:vmask_7[ggg.ci]; ++ ++ gtab_scan_pre_select(TRUE); ++ ++ while ((CONVT2(cur_inmd, ggg.S1) & vmaskci) != ggg.kval && ++ CONVT2(cur_inmd, ggg.S1) < ggg.kval && ggg.S1MaxPress, ++ vmaskci, ggg.kval, ggg.ci, ++ ((CONVT2(cur_inmd, ggg.S1) & vmaskci)!=ggg.kval), ggg.S1); ++#endif ++ ++ if ((CONVT2(cur_inmd, ggg.S1) & vmaskci)!=ggg.kval || (ggg.wild_mode && ggg.defselN) || ++ ((/* ggg.ci==cur_inmd->MaxPress|| */ ggg.spc_pressed) && ggg.defselN && ++ (pselkey && ( pendkey || ggg.spc_pressed)) ) ) { ++YYYY: ++ ++ if ((pselkey || ggg.wild_mode) && ggg.defselN) { ++ int vv = pselkey - cur_inmd->selkey; ++ ++ if ((_gtab_space_auto_first & GTAB_space_auto_first_any) && !ggg.wild_mode ++ && ggg.exa_match && (!cur_inmd->use_quick || ggg.ci!=2)) ++ vv++; ++ ++ if (vv<0) ++ vv=9; ++ ++ if (seltab[vv][0]) { ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ insert_gbuf_cursor1_cond(seltab[vv], ggg.kval, ggg.exa_match); ++ else ++ putstr_inp(seltab[vv]); ++ return 1; ++ } ++ } ++ ++ if (pselkey && !ggg.defselN) ++ return 0; ++ ++ if (gtab_invalid_key_in) { ++ if (ggg.spc_pressed) { ++ bell_err(); ++ ggg.invalid_spc = TRUE; ++// dbg("ggg.invalid_spc\n"); ++ } else { ++ seltab[0][0]=0; ++ ClrSelArea(); ++ } ++ } else { ++ if (gtab_dup_select_bell) ++ bell(); ++ ++ if (ggg.ci>0) ++ ggg.inch[--ggg.ci]=0; ++ } ++ ++ ggg.last_idx=0; ++ DispInArea(); ++ return 1; ++ } ++ ++//refill: ++ ++ j=ggg.S1; ++ while(CONVT2(cur_inmd, j)==ggg.kval && j page_len()) { ++ if ((_gtab_space_auto_first & GTAB_space_auto_first_any) || ggg.spc_pressed || pendkey || ++ (ggg.ci==cur_inmd->MaxPress && (_gtab_space_auto_first & GTAB_space_auto_first_full))) ++ ggg.more_pg = 1; ++ } ++ ++ if (ggg.ci < cur_inmd->MaxPress && !ggg.spc_pressed && !pendkey && !ggg.more_pg) { ++ j = ggg.S1; ++ ggg.exa_match=0; ++ clr_seltab(); ++ int match_cnt=0; ++ ++ while (CONVT2(cur_inmd, j)==ggg.kval && ggg.exa_match <= page_len()) { ++ seltab_phrase[ggg.exa_match] = load_seltab(j, ggg.exa_match); ++ match_cnt++; ++ ggg.exa_match++; ++ j++; ++ } ++ ++ ggg.defselN=ggg.exa_match; ++// dbg("--- ggg.exa_match %d\n", ggg.exa_match); ++ ++ if (ggg.defselN > page_len()) ++ ggg.defselN--; ++ ++ int shiftb=(KEY_N - 1 -ggg.ci) * KeyBits; ++ ++// if (gtab_disp_partial_match_on) ++ while((CONVT2(cur_inmd, j) & vmaskci)==ggg.kval && jkeycol[(CONVT2(cur_inmd, j)>>shiftb) & cur_inmd->kmask]; ++ u_char *tbl_ch = tblch(j); ++ ++ if (gtab_disp_partial_match_on() && (!seltab[fff][0] || seltab_phrase[fff] || ++ (bchcmp(seltab[fff], tbl_ch)>0 && fff > ggg.exa_match))) { ++ seltab_phrase[fff] = load_seltab(j, fff); ++ ggg.defselN++; ++ } ++ ++ match_cnt++; ++#if 0 ++ dbg("jj %d", fff); utf8_putchar(seltab[fff]); dbg("\n"); ++#endif ++ j++; ++ } ++ ++ if (gtab_unique_auto_send_on()) { ++ char *first_str=NULL; ++ for(i=0; i < page_len(); i++) { ++ if (!seltab[i][0]) ++ continue; ++ if (!first_str) ++ first_str = seltab[i]; ++ } ++ ++ if (match_cnt==1 && first_str) { ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ insert_gbuf_nokey(first_str); ++ else ++ putstr_inp(first_str); ++ return 1; ++ } ++ } ++ } else { ++// dbg("more %d %d skip_end:%d\n", ggg.more_pg, ggg.total_matchN, cur_inmd->flag&FLAG_PHRASE_AUTO_SKIP_ENDKEY); ++next_pg: ++ ggg.defselN=0; ++ clr_seltab(); ++ if (pendkey && (!(cur_inmd->flag&FLAG_PHRASE_AUTO_SKIP_ENDKEY) || !AUTO_SELECT_BY_PHRASE || ggg.ci==1)) { ++// dbg("spc_pressed = 1\n"); ++ ggg.spc_pressed = 1; ++ } ++ ++ if (ggg.ci==cur_inmd->MaxPress) ++ ggg.last_full=1; ++ int full_send = gtab_press_full_auto_send_on() && ggg.last_full; ++ ++// dbg("flag %d\n",!(pendkey && (cur_inmd->flag&FLAG_PHRASE_AUTO_SKIP_ENDKEY))); ++ if (AUTO_SELECT_BY_PHRASE && !(pendkey && (cur_inmd->flag&FLAG_PHRASE_AUTO_SKIP_ENDKEY)) ++ && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input && ++ (ggg.spc_pressed||full_send)) { ++ j = ggg.S1; ++ int selN=0; ++ char **sel = NULL; ++ ++// puts("kkkkkkkkkkk"); ++ while(jMaxPress || ggg.spc_pressed) { ++ ggg.sel1st_i=0; ++// dbg("ggg.sel1st_i %d %d %d\n", ggg.ci, cur_inmd->MaxPress, ggg.spc_pressed); ++ } ++ } ++ } ++ ++ ggg.exa_match = ggg.defselN; ++// dbg("ggg.defselN %d\n", ggg.defselN); ++ ++ ++ if (ggg.defselN==1 && !ggg.more_pg) { ++ if (ggg.spc_pressed || full_send || gtab_unique_auto_send_on()) { ++ if (AUTO_SELECT_BY_PHRASE && poo.same_pho_query_state != SAME_PHO_QUERY_gtab_input) ++ insert_gbuf_cursor1_cond(seltab[0], ggg.kval, ggg.exa_match); ++ else ++ putstr_inp(seltab[0]); ++ return 1; ++ } ++ } else ++ if (!ggg.defselN) { ++ bell_err(); ++// ggg.spc_pressed=0; ++// if (gtab_invalid_key_in) ++ { ++ ggg.invalid_spc = TRUE; ++ return TRUE; ++ } ++ ++ return TRUE; ++ } else ++ if (!ggg.more_pg) { ++ if (gtab_dup_select_bell && (gtab_disp_partial_match_on() || gtab_pre_select_or_partial_on())) { ++ if (ggg.spc_pressed || gtab_full_space_auto_first || (ggg.last_full && gtab_press_full_auto_send_on())) ++ bell(); ++ } ++ } ++ } ++ ++Disp_opt: ++ if (gtab_disp_partial_match_on() || gtab_pre_select_or_partial_on() || ((ggg.exa_match > 1 || ggg.more_pg) && ++ (ggg.spc_pressed || gtab_press_full_auto_send_on() || ++ (ggg.ci==cur_inmd->MaxPress && (_gtab_space_auto_first & GTAB_space_auto_first_full))) ) ) { ++ disp_selection(phrase_selected); ++ } ++ ++ return 1; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/gtab.h b/src/plugins/platforminputcontexts/hime/include/gtab.h +new file mode 100644 +index 0000000..a30b937 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/gtab.h +@@ -0,0 +1,167 @@ ++/* Copyright (C) 2004-2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++typedef enum { ++ GTAB_space_auto_first_none=0, // use the value set by .cin ++ GTAB_space_auto_first_any=1, // boshiamy, dayi ++ GTAB_space_auto_first_full=2, // simplex ++ GTAB_space_auto_first_nofull=4, // windows ar30 cj ++ GTAB_space_auto_first_dayi=8 // dayi: input:2 select:1 ++} GTAB_space_pressed_E; ++ ++typedef struct { ++ u_char key[4]; /* If I use u_long key, the struc size will be 8 */ ++ u_char ch[CH_SZ]; ++} ITEM; ++ ++typedef struct { ++ u_char key[8]; /* If I use u_long key, the struc size will be 8 */ ++ u_char ch[CH_SZ]; ++} ITEM64; ++ ++typedef struct { ++ char quick1[46][10][CH_SZ]; ++ char quick2[46][46][10][CH_SZ]; ++} QUICK_KEYS; ++ ++ ++enum { ++ FLAG_KEEP_KEY_CASE=1, ++ FLAG_GTAB_SYM_KBM=2, // auto close, auto switch to default input method ++ FLAG_PHRASE_AUTO_SKIP_ENDKEY=4, ++ FLAG_AUTO_SELECT_BY_PHRASE=8, ++ FLAG_GTAB_DISP_PARTIAL_MATCH=0x10, ++ FLAG_GTAB_DISP_FULL_MATCH=0x20, ++ FLAG_GTAB_VERTICAL_SELECTION=0x40, ++ FLAG_GTAB_PRESS_FULL_AUTO_SEND=0x80, ++ FLAG_GTAB_UNIQUE_AUTO_SEND=0x100, ++}; ++ ++enum { ++ GTAB_OPTION_AUTO=0, ++ GTAB_OPTION_YES=1, ++ GTAB_OPTION_NO=2, ++}; ++ ++ ++#define MAX_SELKEY 16 ++ ++struct TableHead { ++ int version; ++ u_int flag; ++ char cname[32]; /* prompt */ ++ char selkey[12]; /* select keys */ ++ GTAB_space_pressed_E space_style; ++ int KeyS; /* number of keys needed */ ++ int MaxPress; /* Max len of keystroke ar30:4 changjei:5 */ ++ int M_DUP_SEL; /* how many keys used to select */ ++ int DefC; /* Defined characters */ ++ QUICK_KEYS qkeys; ++ ++ union { ++ struct { ++ char endkey[99]; ++ char keybits; ++ char selkey2[10]; ++ }; ++ ++ char dummy[128]; // for future use ++ }; ++}; ++ ++ ++#define KeyBits1(inm) (inm->keybits) ++#define KeyBits (cur_inmd->keybits) ++#define MAX_GTAB_KEYS (1<last_k_bitn) ++ ++#define KEY_MASK ((1<keybits)-1); ++ ++ ++#define GTAB_LIST "gtab.list" ++ ++#if 1 ++#define NEED_SWAP (__BYTE_ORDER == __BIG_ENDIAN && 0) ++#else ++#define NEED_SWAP (1) ++#endif ++ ++#define tblch2(inm, i) (inm->key64 ? inm->tbl64[i].ch:inm->tbl[i].ch) ++#define Max_tab_key_num1(inm) (inm->key64 ? MAX_TAB_KEY_NUM641(inm) : MAX_TAB_KEY_NUM1(inm)) ++#define Max_tab_key_num Max_tab_key_num1(cur_inmd) +diff --git a/src/plugins/platforminputcontexts/hime/include/hime-conf.c b/src/plugins/platforminputcontexts/hime/include/hime-conf.c +new file mode 100644 +index 0000000..527ed91 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime-conf.c +@@ -0,0 +1,246 @@ ++/* Copyright (C) 2010 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include ++#include ++#include ++ ++#if !CLIENT_LIB ++char *TableDir=HIME_TABLE_DIR; ++GKeyFile *hime_omni_config = NULL; ++#define HIME_CONF "/hime.conf" ++ ++void init_TableDir() ++{ ++ char *dname; ++ if ((dname=getenv("HIME_TABLE_DIR"))) { ++ TableDir = dname; ++ return; ++ } ++} ++ ++ ++void get_hime_dir(char *tt) ++{ ++ char *home = getenv("HOME"); ++ if (!home) ++ home = ""; ++ strcpy(tt,home); ++ strcat(tt,"/.config/hime"); ++} ++ ++void init_omni_config(void) ++{ ++ char omni_config_fname[256]; ++ int len; ++ GError *error = NULL; ++ ++ if (hime_omni_config) ++ return; ++ ++ memset(omni_config_fname, 0, 256); ++ get_hime_dir(omni_config_fname); ++ len = strlen(omni_config_fname); ++ snprintf(omni_config_fname + len, 256 - len, HIME_CONF); ++ ++ hime_omni_config = g_key_file_new(); ++ /* Ignore error */ ++ g_key_file_load_from_file(hime_omni_config, omni_config_fname, 0, &error); ++} ++ ++void free_omni_config(void) ++{ ++ if (hime_omni_config) { ++ g_key_file_free(hime_omni_config); ++ hime_omni_config = NULL; ++ } ++} ++ ++void save_omni_config(void) ++{ ++ char omni_config_fname[256]; ++ int len; ++ FILE *f; ++ gchar *buff; ++ gsize bufflen; ++ GError *error = NULL; ++ ++ if (NULL == hime_omni_config) ++ return; ++ ++ memset(omni_config_fname, 0, 256); ++ get_hime_dir(omni_config_fname); ++ len = strlen(omni_config_fname); ++ snprintf(omni_config_fname + len, 256 - len, HIME_CONF); ++ f = fopen(omni_config_fname, "w"); ++ if (f) { ++ buff = g_key_file_to_data(hime_omni_config, &bufflen, &error); ++ if (NULL == buff) ++ return; ++ fwrite(buff, 1, bufflen, f); ++ fclose(f); ++ g_free(buff); ++ } ++} ++ ++gboolean get_hime_user_fname(char *name, char fname[]) ++{ ++ get_hime_dir(fname); ++ strcat(strcat(fname,"/"),name); ++ return !access(fname, R_OK); ++// dbg("get_hime_user_fname %s %s\n", name, fname); ++} ++ ++void get_hime_conf_fname(char *name, char fname[]) ++{ ++ get_hime_dir(fname); ++ strcat(strcat(fname,"/config/"),name); ++} ++ ++void get_hime_user_or_sys_fname(char *name, char fname[]) ++{ ++ if (!getenv("HIME_TABLE_DIR")) { ++ if (get_hime_user_fname(name, fname)) ++ return; ++ } ++ ++ get_sys_table_file_name(name, fname); ++} ++ ++void get_hime_conf_str(char *name, char **rstr, char *default_str) ++{ ++ char fname[MAX_HIME_STR]; ++ char out[256]; ++ ++ if (*rstr) ++ free(*rstr); ++ ++ *rstr = g_key_file_get_string(hime_omni_config, "HIME", name, NULL); ++ if (NULL != *rstr) { ++ return; ++ } ++ ++ /* Compatible for previous configuration */ ++ get_hime_conf_fname(name, fname); ++ ++ FILE *fp; ++ ++ if ((fp=fopen(fname, "rb")) == NULL) { ++ *rstr = strdup(default_str); ++ return; ++ } ++ ++ myfgets(out, sizeof(out), fp); ++ int len = strlen(out); ++ if (len && out[len-1]=='\n') ++ out[len-1] = 0; ++ ++ fclose(fp); ++ ++ *rstr = strdup(out); ++} ++ ++void get_hime_conf_fstr(char *name, char rstr[], char *default_str) ++{ ++ char *tt = NULL; ++ get_hime_conf_str(name, &tt, default_str); ++ strcpy(rstr, tt); ++ free(tt); ++} ++ ++int get_hime_conf_int(char *name, int default_value) ++{ ++ char tt[32]; ++ char default_value_str[MAX_HIME_STR]; ++ ++ sprintf(default_value_str, "%d", default_value); ++ get_hime_conf_fstr(name, tt, default_value_str); ++ ++ return atoi(tt); ++} ++ ++ ++void save_hime_conf_str(char *name, char *str) ++{ ++ FILE *fp; ++ char fname[256]; ++ ++ g_key_file_set_value(hime_omni_config, "HIME", name, str); ++ ++ /* Compatible for previous configuration */ ++ get_hime_conf_fname(name, fname); ++ ++ if ((fp=fopen(fname,"wb"))==NULL) { ++ p_err("cannot create %s", fname); ++ } ++ ++ fprintf(fp, "%s", str); ++ fclose(fp); ++} ++ ++ ++void save_hime_conf_int(char *name, int val) ++{ ++ char tt[16]; ++ ++ sprintf(tt, "%d", val); ++ save_hime_conf_str(name, tt); ++} ++ ++void get_sys_table_file_name(char *name, char *fname) ++{ ++ sprintf(fname, "%s/%s", TableDir, name); ++} ++#endif /* !CLIENT_LIB */ ++ ++char *get_hime_xim_name() ++{ ++ char *xim_name; ++ ++ if ((xim_name=getenv("XMODIFIERS"))) { ++ static char find[] = "@im="; ++ static char sstr[32]; ++ char *p = strstr(xim_name, find); ++ ++ if (p==NULL) return "hime"; ++ ++ p += strlen(find); ++ strncpy(sstr, p, sizeof(sstr)); ++ sstr[sizeof(sstr) - 1]=0; ++ ++ if ((p=strchr(sstr, '.'))) ++ *p=0; ++ ++// dbg("Try to use name from XMODIFIERS=@im=%s\n", sstr); ++ return sstr; ++ } ++ ++ return "hime"; ++} ++ ++Atom get_hime_atom(Display *dpy) ++{ ++ char *xim_name = get_hime_xim_name(); ++ char tt[128]; ++ ++ snprintf(tt, sizeof(tt), "HIME_ATOM_%s", xim_name); ++ ++ Atom atom = XInternAtom(dpy, tt, False); ++ ++ return atom; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/hime-conf.h b/src/plugins/platforminputcontexts/hime/include/hime-conf.h +new file mode 100644 +index 0000000..4ef79f1 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime-conf.h +@@ -0,0 +1,159 @@ ++#define CHANGE_FONT_SIZE "change font size" ++#define GB_OUTPUT_TOGGLE "gb output toggle" ++#define SIM_OUTPUT_TOGGLE "gb output sim" ++#define TRAD_OUTPUT_TOGGLE "gb output trad" ++#define KBM_TOGGLE "kbm toggle" ++#define UPDATE_TRAY "update tray" ++#define RELOAD_TSIN_DB "reload tsin db" ++#define HIME_EXIT_MESSAGE "hime exit" ++ ++ ++#define HIME_SETUP_WINDOW_TYPE_UTILITY "hime-setup-window-type-utility" ++#define HIME_FONT_SIZE "hime-font-size" ++#define HIME_FONT_NAME "hime-font-name" ++#define HIME_FONT_SIZE_TSIN_PRESEL "hime-font-size-tsin-presel" ++#define HIME_FONT_SIZE_SYMBOL "hime-font-size-symbol" ++#define HIME_FONT_SIZE_TSIN_PHO_IN "hime-font-size-tsin-pho-in" ++#define HIME_FONT_SIZE_GTAB_IN "hime-font-size-gtab-in" ++#define HIME_FONT_SIZE_PHO_NEAR "hime-font-size-pho-near" ++#define HIME_FONT_SIZE_WIN_KBM "hime-font-size-win-kbm" ++#define HIME_FONT_SIZE_WIN_KBM_EN "hime-font-size-win-kbm-en" ++#define HIME_INPUT_STYLE "hime-input-style" ++#define HIME_ROOT_X "hime-root-x" ++#define HIME_ROOT_Y "hime-root-y" ++#define HIME_POP_UP_WIN "hime-pop-up-win" ++#define HIME_ICON_DIR "hime-icon-dir" ++#define HIME_INNER_FRAME "hime-inner-frame" ++#define HIME_INIT_IM_ENABLED "hime-init-im-enabled" ++#define HIME_INIT_FULL_MODE "hime-init-full-mode" ++#define HIME_BELL_VOLUME "hime-bell-volume" ++#define HIME_SOUND_PLAY_OVERLAP "hime-sound-play-overlap" ++#define HIME_ENABLE_CTRL_ALT_SWITCH "hime-enable-ctrl-alt-switch" ++#define HIME_EDIT_DISPLAY "hime-edit-display" ++#define HIME_BELL_OFF "hime-bell-off" ++#define HIME_ON_THE_SPOT_KEY "hime-on-the-spot-key" ++#define HIME_TRAY_HF_WIN_KBM "hime-tray-hf-win-kbm" ++#define HIME_SINGLE_STATE "hime-single-state" ++#define HIME_PUNC_AUTO_SEND "hime-punc-auto-send" ++ ++#define HIME_IM_TOGGLE_KEYS "hime-im-toggle-keys" ++#define DEFAULT_INPUT_METHOD "default-input-method" ++// #define LEFT_RIGHT_BUTTON_TIPS "left-right-button-tips" ++#define HIME_STR_IM_CYCLE "hime-str-im-cycle" ++#define HIME_REMOTE_CLIENT "hime-remote-client" ++#define HIME_SHIFT_SPACE_ENG_FULL "hime-shift-space-eng-full" ++#define HIME_STATUS_TRAY "hime-status-tray" ++#define HIME_WIN_COLOR_FG "hime-win-color-fg" ++#define HIME_WIN_COLOR_BG "hime-win-color-bg" ++#define HIME_WIN_COLOR_USE "hime-win-color-use" ++#define HIME_CAPSLOCK_LOWER "hime-capslock-lower" ++#define HIME_ENG_PHRASE_ENABLED "hime-eng-phrase-enabled" ++#define HIME_WIN_SYM_CLICK_CLOSE "hime-win-sym-click-close" ++#define HIME_SEL_KEY_COLOR "hime-sel-key-color" ++#define HIME_TRAY_DISPLAY "hime-tray-display" ++ ++#define GTAB_DUP_SELECT_BELL "gtab-dup-select-bell" ++#define GTAB_SPACE_AUTO_FIRST "gtab-space-auto-first" ++#define GTAB_AUTO_SELECT_BY_PHRASE "gtab-auto-select-by_phrase" ++#define GTAB_PRE_SELECT "gtab-pre-select" ++#define GTAB_PHRASE_PRE_SELECT "gtab-phrase-pre-select" ++#define GTAB_PRESS_FULL_AUTO_SEND "gtab-press-full-auto-send" ++#define GTAB_DISP_PARTIAL_MATCH "gtab-disp-partial-match" ++#define GTAB_DISP_KEY_CODES "gtab-disp-key-codes" ++#define GTAB_DISP_IM_NAME "gtab-disp-im-name" ++#define GTAB_INVALID_KEY_IN "gtab-invalid-key-in" ++#define GTAB_SHIFT_PHRASE_KEY "gtab-shift-phrase-key" ++#define GTAB_HIDE_ROW2 "gtab-hide-row2" ++#define GTAB_IN_ROW1 "gtab-in-row1" ++#define GTAB_VERTICAL_SELECT "gtab-vertical-select" ++#define GTAB_UNIQUE_AUTO_SEND "gtab-unique-auto-send" ++#define GTAB_QUE_WILD_CARD "gtab-que-wild-card" ++#define GTAB_QUE_WILD_CARD_ASTERISK "gtab-que-wild-card-asterisk" ++#define GTAB_PHO_QUERY "gtab-pho-query" ++#define GTAB_PHRASE_PRE_SELECT "gtab-phrase-pre-select" ++#define GTAB_IN_AREA_BUTTON "gtab-in-area-button" ++ ++ ++#define TSIN_PHRASE_PRE_SELECT "tsin-phrase-pre-select" ++#define TSIN_CHINESE_ENGLISH_TOGGLE_KEY "tsin-chinese-english-toggle_key" ++#define TSIN_SPACE_OPT "tsin-space-opt" ++#define TSIN_BUFFER_SIZE "tsin-buffer-size" ++#define TSIN_PHRASE_LINE_COLOR "tsin-phrase-line-color" ++#define TSIN_CURSOR_COLOR "tsin-cursor-color" ++#define TSIN_TONE_CHAR_INPUT "tsin-tone-char-input" ++#define TSIN_TAB_PHRASE_END "tsin-tab-phrase-end" ++#define TSIN_TAIL_SELECT_KEY "tsin-tail-select-key" ++#define TSIN_BUFFER_EDITING_MODE "tsin-buffer-editing-mode" ++#define TSIN_USE_PHO_NEAR "tsin-use-pho-near" ++ ++#define PHO_HIDE_ROW2 "pho-hide-row2" ++#define PHO_IN_ROW1 "pho-in-row1" ++ ++ ++#define PHONETIC_KEYBOARD "phonetic-keyboard2" ++#define PHONETIC_KEYBOARD_BAK "phonetic-keyboard-bak" ++ ++#define PHONETIC_CHAR_DYNAMIC_SEQUENCE "phonetic-char-dynamic-sequence" ++#define PHONETIC_HUGE_TAB "phonetic-huge-tab" ++#define PHONETIC_SPEAK "phonetic-speak" ++#define PHONETIC_SPEAK_SEL "phonetic-speak-sel" ++ ++extern int hime_setup_window_type_utility, ++ hime_font_size, hime_font_size_tsin_presel, hime_font_size_symbol, ++ hime_font_size_tsin_pho_in, hime_font_size_pho_near, ++ hime_font_size_gtab_in, hime_font_size_win_kbm, hime_font_size_win_kbm_en, ++ hime_inner_frame, hime_single_state, ++ hime_remote_client, ++ gtab_disp_key_codes, gtab_disp_im_name, hime_shift_space_eng_full, ++ gtab_invalid_key_in, gtab_hide_row2, gtab_in_row1, ++ hime_capslock_lower, pho_hide_row2, pho_in_row1, ++ hime_eng_phrase_enabled, hime_win_sym_click_close, ++ gtab_que_wild_card, gtab_que_wild_card_asterisk, gtab_pho_query, ++ hime_bell_volume, hime_sound_play_overlap, hime_enable_ctrl_alt_switch, hime_on_the_spot_key; ++ ++extern int default_input_method; ++// extern int left_right_button_tips; ++extern int gtab_dup_select_bell; ++extern int gtab_space_auto_first; ++extern int gtab_auto_select_by_phrase; ++extern int hime_im_toggle_keys; ++extern int gtab_pre_select, gtab_phrase_pre_select; ++extern int gtab_press_full_auto_send; ++extern int gtab_disp_partial_match; ++extern int gtab_shift_phrase_key, gtab_in_area_button; ++extern int gtab_vertical_select, gtab_unique_auto_send; ++extern int tsin_buffer_size; ++extern int hime_input_style, hime_root_x, hime_root_y, hime_pop_up_win; ++extern int hime_status_tray, hime_show_win_kbm, hime_tray_hf_win_kbm; ++extern int hime_punc_auto_send; ++ ++extern int tsin_phrase_pre_select; ++extern int tsin_chinese_english_toggle_key; ++extern int tsin_tab_phrase_end, tsin_tail_select_key; ++extern int tsin_buffer_editing_mode; ++extern int tsin_use_pho_near; ++ ++extern int phonetic_char_dynamic_sequence; ++extern int phonetic_huge_tab, phonetic_speak; ++extern char *phonetic_speak_sel; ++extern int tsin_space_opt, tsin_tone_char_input; ++ ++extern char *tsin_phrase_line_color, *tsin_cursor_color, *hime_font_name, *hime_sel_key_color, *hime_icon_dir; ++extern unich_t eng_full_str[], eng_half_str[], cht_full_str[]; ++extern char *eng_color_full_str, *eng_color_half_str, *cht_color_full_str; ++extern char *hime_win_color_fg, *hime_win_color_bg; ++extern int hime_win_color_use, hime_bell_off; ++extern int hime_init_im_enabled, hime_init_full_mode; ++extern int hime_edit_display, hime_tray_display; ++extern char *pho_kbm_name, *pho_selkey, *hime_str_im_cycle; ++extern int pho_candicate_col_N, pho_candicate_R2L; ++ ++gboolean get_hime_user_fname(char *name, char fname[]); ++void get_hime_conf_str(char *name, char **rstr, char *default_str); ++void get_hime_conf_fstr(char *name, char rstr[], char *default_str); ++void save_hime_conf_str(char *name, char *str); ++void save_hime_conf_int(char *name, int val); ++void load_settings(); ++void save_omni_config(void); ++void free_omni_config(void); ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/hime-crypt.c b/src/plugins/platforminputcontexts/hime/include/hime-crypt.c +new file mode 100644 +index 0000000..f35b4f4 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime-crypt.c +@@ -0,0 +1,36 @@ ++/* Copyright (C) 2009 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "im-client/hime-protocol.h" ++ ++static int __hime_rand__(u_int *next) ++{ ++ *next = *next * 1103515245 + 12345; ++ return((unsigned)(*next/65536) % 32768); ++} ++ ++void __hime_enc_mem(u_char *p, int n, ++ HIME_PASSWD *passwd, u_int *seed) ++{ ++ int i; ++ ++ for(i=0; i < n; i++) { ++ int v = __hime_rand__(seed) % __HIME_PASSWD_N_; ++ p[i]^=passwd->passwd[v]; ++ } ++} ++ +diff --git a/src/plugins/platforminputcontexts/hime/include/hime-endian.h b/src/plugins/platforminputcontexts/hime/include/hime-endian.h +new file mode 100644 +index 0000000..fe5970e +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime-endian.h +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2009 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#define swap_ch(a, b) do { char t; t = *(a); *(a) = *(b); *(b) = t; } while (0) ++ ++#define swap_byte_2(pp) do { char *p=(char *)pp; swap_ch(p, p+1); } while (0) ++#define swap_byte_4(pp) do { char *p=(char *)pp; swap_ch(p, p+3); swap_ch(p+1, p+2); } while (0) ++#define swap_byte_8(pp) do { char *p=(char *)pp; swap_ch(p, p+7); swap_ch(p+1, p+6); swap_ch(p+2, p+5); swap_ch(p+3, p+4);} while (0) ++ ++#if __BYTE_ORDER == __BIG_ENDIAN ++//#warning "big endian" ++#define to_hime_endian_2(pp) swap_byte_2(pp) ++#define to_hime_endian_4(pp) swap_byte_4(pp) ++#define to_hime_endian_8(pp) swap_byte_8(pp) ++#else ++#define to_hime_endian_2(pp) do { } while (0) ++#define to_hime_endian_4(pp) do { } while (0) ++#define to_hime_endian_8(pp) do { } while (0) ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/hime-gtk-compatible.h b/src/plugins/platforminputcontexts/hime/include/hime-gtk-compatible.h +new file mode 100644 +index 0000000..cc4ea9c +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime-gtk-compatible.h +@@ -0,0 +1,139 @@ ++#if !GTK_CHECK_VERSION(2,13,4) ++#define gtk_widget_get_window(x) (x)->window ++#define gtk_color_selection_dialog_get_color_selection(x) (x)->colorsel ++#endif ++ ++#if !GTK_CHECK_VERSION(2,15,0) ++#define gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip ++#endif ++ ++#if !GTK_CHECK_VERSION(2,16,0) ++#include ++#include ++#define gdk_keymap_get_caps_lock_state(x) get_caps_lock_state() ++#endif ++ ++#if GTK_CHECK_VERSION(2,17,5) ++#undef GTK_WIDGET_NO_WINDOW ++#define GTK_WIDGET_NO_WINDOW !gtk_widget_get_has_window ++#undef GTK_WIDGET_SET_FLAGS ++#define GTK_WIDGET_SET_FLAGS(x,y) gtk_widget_set_can_default(x,1) ++#endif ++ ++#if GTK_CHECK_VERSION(2,17,7) ++#undef GTK_WIDGET_VISIBLE ++#define GTK_WIDGET_VISIBLE gtk_widget_get_visible ++#endif ++ ++#if GTK_CHECK_VERSION(2,17,10) ++#undef GTK_WIDGET_DRAWABLE ++#define GTK_WIDGET_DRAWABLE gtk_widget_is_drawable ++#endif ++ ++#if GTK_CHECK_VERSION(2,19,5) ++#undef GTK_WIDGET_REALIZED ++#define GTK_WIDGET_REALIZED gtk_widget_get_realized ++#endif ++ ++#if GTK_CHECK_VERSION(2,21,8) ++#undef GDK_DISPLAY ++#define GDK_DISPLAY() GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) ++#endif ++ ++#if GTK_CHECK_VERSION(2,24,0) ++#define gdk_window_lookup_for_display gdk_x11_window_lookup_for_display ++#define gtk_combo_box_new_text gtk_combo_box_text_new ++#define gtk_combo_box_append_text gtk_combo_box_text_append_text ++#define gtk_widget_hide_all gtk_widget_hide ++#endif ++ ++#if GTK_CHECK_VERSION(2,90,0) ++#undef GTK_CHECK_CAST ++#define GTK_CHECK_CAST G_TYPE_CHECK_INSTANCE_CAST ++#undef GDK_DRAWABLE_XID ++#define GDK_DRAWABLE_XID GDK_WINDOW_XID ++#undef GDK_DRAWABLE_XDISPLAY ++#define GDK_DRAWABLE_XDISPLAY GDK_WINDOW_XDISPLAY ++#define gtk_hseparator_new() gtk_separator_new(GTK_ORIENTATION_HORIZONTAL) ++#define gtk_vseparator_new() gtk_separator_new(GTK_ORIENTATION_VERTICAL) ++#endif ++ ++#if !GTK_CHECK_VERSION(2,91,0) ++#define gdk_error_trap_pop_ignored gdk_error_trap_pop ++#define gtk_widget_get_preferred_size(x,y,z) gtk_widget_size_request(x,z) ++#define gtk_widget_set_halign(x,y); ++#endif ++ ++#if GTK_CHECK_VERSION(2,91,0) ++#define GTK_OBJECT ++#define gdk_drawable_get_screen gdk_window_get_screen ++#endif ++ ++#if !GTK_CHECK_VERSION(2,91,1) ++#define gtk_window_set_has_resize_grip(x,y); ++#define gtk_widget_set_hexpand(x,y); ++#define gtk_widget_set_vexpand(x,y); ++#endif ++ ++#if !GTK_CHECK_VERSION(2,91,2) ++#define gtk_grid_set_column_homogeneous(x,y); ++#define gtk_grid_set_row_homogeneous(x,y); ++#define gtk_orientable_set_orientation(x,y); ++#endif ++ ++#if GTK_CHECK_VERSION(2,91,2) ++#undef GTK_BOX ++#define GTK_BOX GTK_GRID ++#define gtk_hbox_new(x,y) gtk_grid_new() ++#define gtk_vbox_new(x,y) gtk_grid_new() ++#define gtk_box_pack_end(v,w,x,y,z) gtk_container_add(GTK_CONTAINER(v),w) ++#define gtk_box_pack_start(v,w,x,y,z) gtk_container_add(GTK_CONTAINER(v),w) ++#endif ++ ++#ifndef GTK_COMBO_BOX_TEXT ++#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX ++#endif ++ ++#if !GTK_CHECK_VERSION(2,91,6) ++#define gtk_widget_override_font gtk_widget_modify_font ++#endif ++ ++#if GTK_CHECK_VERSION(2,91,6) ++#define GDK_WINDOW_XWINDOW GDK_WINDOW_XID ++#endif ++ ++#if GTK_CHECK_VERSION(3,3,2) ++#undef GTK_TABLE ++#define GTK_TABLE GTK_GRID ++#define gtk_table_attach_defaults(u,v,w,x,y,z) gtk_grid_attach(u,v,w,y,1,1) ++#define gtk_table_new(x,y,z) gtk_grid_new() ++#endif ++ ++#if GTK_CHECK_VERSION(3,3,18) ++#define GTK_COLOR_SELECTION_DIALOG GTK_COLOR_CHOOSER_DIALOG ++#define GTK_COLOR_SELECTION GTK_COLOR_CHOOSER ++#endif ++ ++#if GTK_CHECK_VERSION(3,9,8) ++#define gtk_image_menu_item_set_image(a,b) NULL ++#endif ++ ++#if GTK_CHECK_VERSION(3,9,10) ++#define gtk_button_new_from_stock(x) gtk_button_new_from_icon_name(x,GTK_ICON_SIZE_BUTTON) ++#define GTK_STOCK_CANCEL "gtk-cancel" ++#define GTK_STOCK_OK "gtk-ok" ++#define GTK_STOCK_QUIT "gtk-quit" ++#define GTK_STOCK_SAVE "gtk-save" ++#define GTK_STOCK_OPEN "gtk-open" ++#define GTK_STOCK_CLOSE "gtk-close" ++#define GTK_STOCK_DELETE "gtk-delete" ++#define GTK_STOCK_FIND "gtk-find" ++#endif ++ ++#if GTK_CHECK_VERSION(3,13,4) ++#define gtk_window_set_has_resize_grip(x,y); ++#endif ++ ++#ifndef PANGO_VERSION_CHECK ++#define PANGO_VERSION_CHECK(x,y,z) FALSE ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/hime.c b/src/plugins/platforminputcontexts/hime/include/hime.c +new file mode 100644 +index 0000000..1c17c59 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime.c +@@ -0,0 +1,702 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "config.h" ++#include "gtab.h" ++#include ++#if HIME_i18n_message ++#include ++#endif ++ ++Window root; ++Display *dpy; ++ ++int win_xl, win_yl; ++int win_x, win_y; // actual win x/y ++int dpy_xl, dpy_yl; ++Window xim_xwin; ++ ++extern unich_t *fullchar[]; ++gboolean win_kbm_inited; ++char *get_hime_xim_name(); ++ ++char *half_char_to_full_char(KeySym xkey) ++{ ++ if (xkey < ' ' || xkey > 127) ++ return NULL; ++ return _(fullchar[xkey-' ']); ++} ++ ++static void start_inmd_window() ++{ ++ GtkWidget *win = gtk_window_new (GTK_WINDOW_TOPLEVEL); ++ gtk_widget_realize (win); ++ xim_xwin = GDK_WINDOW_XWINDOW(gtk_widget_get_window(win)); ++ dbg("xim_xwin %x\n", xim_xwin); ++} ++ ++#if USE_XIM ++char *lc; ++ ++static XIMStyle Styles[] = { ++#if 1 ++ XIMPreeditCallbacks|XIMStatusCallbacks, //OnTheSpot ++ XIMPreeditCallbacks|XIMStatusArea, //OnTheSpot ++ XIMPreeditCallbacks|XIMStatusNothing, //OnTheSpot ++#endif ++ XIMPreeditPosition|XIMStatusArea, //OverTheSpot ++ XIMPreeditPosition|XIMStatusNothing, //OverTheSpot ++ XIMPreeditPosition|XIMStatusNone, //OverTheSpot ++#if 1 ++ XIMPreeditArea|XIMStatusArea, //OffTheSpot ++ XIMPreeditArea|XIMStatusNothing, //OffTheSpot ++ XIMPreeditArea|XIMStatusNone, //OffTheSpot ++#endif ++ XIMPreeditNothing|XIMStatusNothing, //Root ++ XIMPreeditNothing|XIMStatusNone, //Root ++}; ++static XIMStyles im_styles; ++ ++#if 1 ++static XIMTriggerKey trigger_keys[] = { ++ {XK_space, ControlMask, ControlMask}, ++ {XK_space, ShiftMask, ShiftMask}, ++ {XK_space, Mod1Mask, Mod1Mask}, // Alt ++ {XK_space, Mod4Mask, Mod4Mask}, // Windows ++}; ++#endif ++ ++/* Supported Encodings */ ++static XIMEncoding chEncodings[] = { ++ "COMPOUND_TEXT", ++ 0 ++}; ++static XIMEncodings encodings; ++ ++int xim_ForwardEventHandler(IMForwardEventStruct *call_data); ++ ++XIMS current_ims; ++extern void toggle_im_enabled(); ++ ++ ++int MyTriggerNotifyHandler(IMTriggerNotifyStruct *call_data) ++{ ++// dbg("MyTriggerNotifyHandler %d %x\n", call_data->key_index, call_data->event_mask); ++ ++ if (call_data->flag == 0) { /* on key */ ++// db(g("trigger %d\n", call_data->key_index); ++ if ((call_data->key_index == 0 && hime_im_toggle_keys==Control_Space) || ++ (call_data->key_index == 3 && hime_im_toggle_keys==Shift_Space) || ++ (call_data->key_index == 6 && hime_im_toggle_keys==Alt_Space) || ++ (call_data->key_index == 9 && hime_im_toggle_keys==Windows_Space) ++ ) { ++ toggle_im_enabled(); ++ } ++ return True; ++ } else { ++ /* never happens */ ++ return False; ++ } ++} ++ ++#if 0 ++void switch_IC_index(int index); ++#endif ++void CreateIC(IMChangeICStruct *call_data); ++void DeleteIC(CARD16 icid); ++void SetIC(IMChangeICStruct * call_data); ++void GetIC(IMChangeICStruct *call_data); ++int xim_hime_FocusIn(IMChangeFocusStruct *call_data); ++int xim_hime_FocusOut(IMChangeFocusStruct *call_data); ++ ++int hime_ProtoHandler(XIMS ims, IMProtocol *call_data) ++{ ++// dbg("hime_ProtoHandler %x ims\n", ims); ++ ++ current_ims = ims; ++ ++ switch (call_data->major_code) { ++ case XIM_OPEN: ++#define MAX_CONNECT 20000 ++ { ++ IMOpenStruct *pimopen=(IMOpenStruct *)call_data; ++ ++ if (pimopen->connect_id > MAX_CONNECT - 1) ++ return True; ++ ++#if DEBUG && 0 ++ dbg("open lang %s connectid:%d\n", pimopen->lang.name, pimopen->connect_id); ++#endif ++ return True; ++ } ++ case XIM_CLOSE: ++#if DEBUG && 0 ++ dbg("XIM_CLOSE\n"); ++#endif ++ return True; ++ case XIM_CREATE_IC: ++#if DEBUG && 0 ++ dbg("CREATE_IC\n"); ++#endif ++ CreateIC((IMChangeICStruct *)call_data); ++ return True; ++ case XIM_DESTROY_IC: ++ { ++ IMChangeICStruct *pimcha=(IMChangeICStruct *)call_data; ++#if DEBUG && 0 ++ dbg("DESTROY_IC %d\n", pimcha->icid); ++#endif ++ DeleteIC(pimcha->icid); ++ } ++ return True; ++ case XIM_SET_IC_VALUES: ++#if DEBUG && 0 ++ dbg("SET_IC\n"); ++#endif ++ SetIC((IMChangeICStruct *)call_data); ++ return True; ++ case XIM_GET_IC_VALUES: ++#if DEBUG && 0 ++ dbg("GET_IC\n"); ++#endif ++ GetIC((IMChangeICStruct *)call_data); ++ return True; ++ case XIM_FORWARD_EVENT: ++#if DEBUG && 0 ++ dbg("XIM_FORWARD_EVENT\n"); ++#endif ++ return xim_ForwardEventHandler((IMForwardEventStruct *)call_data); ++ case XIM_SET_IC_FOCUS: ++#if DEBUG && 0 ++ dbg("XIM_SET_IC_FOCUS\n"); ++#endif ++ return xim_hime_FocusIn((IMChangeFocusStruct *)call_data); ++ case XIM_UNSET_IC_FOCUS: ++#if DEBUG && 0 ++ dbg("XIM_UNSET_IC_FOCUS\n"); ++#endif ++ return xim_hime_FocusOut((IMChangeFocusStruct *)call_data); ++ case XIM_RESET_IC: ++#if DEBUG && 0 ++ dbg("XIM_UNSET_IC_FOCUS\n"); ++#endif ++ return True; ++ case XIM_TRIGGER_NOTIFY: ++#if DEBUG && 0 ++ dbg("XIM_TRIGGER_NOTIFY\n"); ++#endif ++ MyTriggerNotifyHandler((IMTriggerNotifyStruct *)call_data); ++ return True; ++ case XIM_PREEDIT_START_REPLY: ++#if DEBUG && 1 ++ dbg("XIM_PREEDIT_START_REPLY\n"); ++#endif ++ return True; ++ case XIM_PREEDIT_CARET_REPLY: ++#if DEBUG && 1 ++ dbg("XIM_PREEDIT_CARET_REPLY\n"); ++#endif ++ return True; ++ case XIM_STR_CONVERSION_REPLY: ++#if DEBUG && 1 ++ dbg("XIM_STR_CONVERSION_REPLY\n"); ++#endif ++ return True; ++ default: ++ printf("Unknown major code.\n"); ++ break; ++ } ++ ++ return True; ++} ++ ++ ++void open_xim() ++{ ++ XIMTriggerKeys triggerKeys; ++ ++ im_styles.supported_styles = Styles; ++ im_styles.count_styles = sizeof(Styles)/sizeof(Styles[0]); ++ ++ triggerKeys.count_keys = sizeof(trigger_keys)/sizeof(trigger_keys[0]); ++ triggerKeys.keylist = trigger_keys; ++ ++ encodings.count_encodings = sizeof(chEncodings)/sizeof(XIMEncoding) - 1; ++ encodings.supported_encodings = chEncodings; ++ ++ char *xim_name = get_hime_xim_name(); ++ ++ XIMS xims = IMOpenIM(dpy, ++ IMServerWindow, xim_xwin, //input window ++ IMModifiers, "Xi18n", //X11R6 protocol ++ IMServerName, xim_name, //XIM server name ++ IMLocale, lc, ++ IMServerTransport, "X/", //Comm. protocol ++ IMInputStyles, &im_styles, //faked styles ++ IMEncodingList, &encodings, ++ IMProtocolHandler, hime_ProtoHandler, ++ IMFilterEventMask, KeyPressMask|KeyReleaseMask, ++ IMOnKeysList, &triggerKeys, ++ NULL); ++ ++ if (xims == NULL) { ++ p_err("IMOpenIM '%s' failed. Maybe another XIM server is running.\n", ++ xim_name); ++ } ++} ++ ++#endif // if USE_XIM ++ ++void load_tsin_db(); ++void load_tsin_conf(), load_settings(), load_tab_pho_file(); ++ ++void disp_hide_tsin_status_row(), update_win_kbm_inited(); ++void change_tsin_line_color(), change_win0_style(), change_tsin_color(); ++void change_win_gtab_style(); ++#if TRAY_ENABLED ++void update_item_active_all(); ++#endif ++void destroy_inmd_menu(); ++void load_gtab_list(gboolean); ++void change_win1_font(); ++void set_wselkey(char *s); ++void create_win_gtab(); ++ ++#if TRAY_ENABLED ++void disp_tray_icon(); ++#endif ++gboolean init_in_method(int in_no); ++#include "im-client/hime-protocol.h" ++#include "im-srv.h" ++ ++static int get_in_method_by_filename(char filename[]) ++{ ++ int i, in_method = 0; ++ gboolean found = FALSE; ++ for(i=0; i < inmdN; i++) { ++ if (strcmp(filename, inmd[i].filename)) ++ continue; ++ found = TRUE; ++ in_method = i; ++ break; ++ } ++ if (!found) ++ in_method = default_input_method; ++ return in_method; ++} ++ ++static void reload_data() ++{ ++ dbg("reload_data\n"); ++// Save input method state before reload ++ char temp_inmd_filenames[hime_clientsN][128]; ++ HIME_STATE_E temp_CS_im_states[hime_clientsN]; ++ char temp_current_CS_inmd_filename[128] = ""; ++ HIME_STATE_E temp_current_CS_im_state = 0; ++ if (current_CS) { ++ temp_current_CS_im_state = current_CS->im_state; ++ strcpy(temp_current_CS_inmd_filename, inmd[current_CS->in_method].filename); ++ } ++ int c; ++ for(c=0;cim_state; ++ strcpy(temp_inmd_filenames[c], inmd[cs->in_method].filename); ++ } ++ free_omni_config(); ++ load_settings(); ++ if (current_method_type()==method_type_TSIN) ++ set_wselkey(pho_selkey); ++ ++// load_tsin_db(); ++ change_win0_style(); ++ change_win1_font(); ++ create_win_gtab(); ++ change_win_gtab_style(); ++// change_win_pho_style(); ++ load_tab_pho_file(); ++ change_tsin_color(); ++ update_win_kbm_inited(); ++ ++ destroy_inmd_menu(); ++ load_gtab_list(TRUE); ++ ++#if TRAY_ENABLED ++ update_item_active_all(); ++#endif ++ ++// Load input method state after reload, which may change inmd ++ // load clientstate properties back ++ for(c=0;cim_state = HIME_STATE_CHINESE; ++ hime_clients[c].cs->in_method = get_in_method_by_filename(temp_inmd_filenames[c]); ++ init_in_method(hime_clients[c].cs->in_method); ++ if (temp_CS_im_states[c] == HIME_STATE_DISABLED) ++ toggle_im_enabled(); ++ hime_clients[c].cs->im_state = temp_CS_im_states[c]; ++ } ++ current_CS->im_state = HIME_STATE_CHINESE; ++ init_in_method(get_in_method_by_filename(temp_current_CS_inmd_filename)); ++ if (temp_current_CS_im_state == HIME_STATE_DISABLED) ++ toggle_im_enabled(); ++ current_CS->im_state = temp_current_CS_im_state; ++} ++ ++void change_tsin_font_size(); ++void change_gtab_font_size(); ++void change_pho_font_size(); ++void change_win_sym_font_size(); ++void change_win_gtab_style(); ++extern gboolean win_kbm_on; ++extern void change_module_font_size(); ++ ++static void change_font_size() ++{ ++ load_settings(); ++ change_tsin_font_size(); ++ change_gtab_font_size(); ++ change_pho_font_size(); ++ change_win_sym_font_size(); ++ change_win0_style(); ++ change_win_gtab_style(); ++ update_win_kbm_inited(); ++ change_win1_font(); ++// change_win_pho_style(); ++ change_module_font_size(); ++} ++ ++static int xerror_handler(Display *d, XErrorEvent *eve) ++{ ++ return 0; ++} ++ ++Atom hime_atom; ++ ++void toggle_gb_output(); ++ ++void cb_trad_sim_toggle() ++{ ++ toggle_gb_output(); ++#if TRAY_ENABLED ++ disp_tray_icon(); ++#endif ++} ++void execute_message(char *message), show_win_kbm(), hide_win_kbm(); ++void disp_win_kbm_capslock_init(); ++ ++extern int hime_show_win_kbm; ++void kbm_open_close(GtkButton *checkmenuitem, gboolean b_show) ++{ ++ hime_show_win_kbm=b_show; ++ ++ if (hime_show_win_kbm) { ++ show_win_kbm(); ++ disp_win_kbm_capslock_init(); ++ } else ++ hide_win_kbm(); ++} ++ ++void kbm_toggle() ++{ ++ win_kbm_inited = 1; ++ kbm_open_close(NULL, ! hime_show_win_kbm); ++} ++ ++ ++void reload_tsin_db(); ++void do_exit(); ++ ++void message_cb(char *message) ++{ ++ void sim_output(); // FIXME ++ void trad_output(); // FIXME ++// dbg("message '%s'\n", message); ++ ++ /* TODO: rewrite the mess with case() ? */ ++ if (!strcmp(message, CHANGE_FONT_SIZE)) { ++ change_font_size(); ++ } else ++ if (!strcmp(message, GB_OUTPUT_TOGGLE)) { ++ cb_trad_sim_toggle(); ++#if TRAY_ENABLED ++ update_item_active_all(); ++#endif ++ } else ++ if (!strcmp(message, SIM_OUTPUT_TOGGLE)) { ++ sim_output(); ++#if TRAY_ENABLED ++ disp_tray_icon(); ++ update_item_active_all(); ++#endif ++ } else ++ if (!strcmp(message, TRAD_OUTPUT_TOGGLE)) { ++ trad_output(); ++#if TRAY_ENABLED ++ disp_tray_icon(); ++ update_item_active_all(); ++#endif ++ } else ++ if (!strcmp(message, KBM_TOGGLE)) { ++ kbm_toggle(); ++ } else ++ if (strstr(message, "#hime_message")) { ++ execute_message(message); ++ } else ++#if TRAY_ENABLED ++ if (!strcmp(message, UPDATE_TRAY)) { ++ disp_tray_icon(); ++ } else ++#endif ++ if (!strcmp(message, RELOAD_TSIN_DB)) { ++ reload_tsin_db(); ++ } else ++ if (!strcmp(message, HIME_EXIT_MESSAGE)) { ++ do_exit(); ++ } else ++ reload_data(); ++} ++ ++static GdkFilterReturn my_gdk_filter(GdkXEvent *xevent, ++ GdkEvent *event, ++ gpointer data) ++{ ++ XEvent *xeve = (XEvent *)xevent; ++#if 0 ++ dbg("a zzz %d\n", xeve->type); ++#endif ++ ++ // only very old WM will enter this ++ if (xeve->type == FocusIn || xeve->type == FocusOut) { ++#if 0 ++ dbg("focus %s\n", xeve->type == FocusIn ? "in":"out"); ++#endif ++ return GDK_FILTER_REMOVE; ++ } ++ ++#if USE_XIM ++ if (XFilterEvent(xeve, None) == True) ++ return GDK_FILTER_REMOVE; ++#endif ++ ++ return GDK_FILTER_CONTINUE; ++} ++ ++void init_atom_property() ++{ ++ hime_atom = get_hime_atom(dpy); ++ XSetSelectionOwner(dpy, hime_atom, xim_xwin, CurrentTime); ++} ++ ++void hide_win0(); ++void destroy_win0(); ++void destroy_win1(); ++void destroy_win_gtab(); ++void free_pho_mem(),free_tsin(),free_all_IC(), free_gtab(), free_phrase(); ++#if TRAY_ENABLED ++void destroy_tray(); ++#endif ++ ++void do_exit() ++{ ++ dbg("----------------- do_ exit ----------------\n"); ++ ++ free_pho_mem(); ++ free_tsin(); ++#if USE_XIM ++ free_all_IC(); ++#endif ++ free_gtab(); ++ free_phrase(); ++ ++#if 1 ++ destroy_win0(); ++ destroy_win1(); ++ destroy_win_gtab(); ++#endif ++ ++#if TRAY_ENABLED ++ destroy_tray(); ++#endif ++ ++ free_omni_config(); ++ gtk_main_quit(); ++} ++ ++void sig_do_exit(int sig) ++{ ++ do_exit(); ++} ++ ++void load_phrase(), init_TableDir(); ++void init_tray(), exec_setup_scripts(); ++void init_hime_im_serv(Window win); ++void init_tray_double(); ++ ++#if TRAY_UNITY ++void init_tray_appindicator(); ++#endif ++ ++gboolean delayed_start_cb(gpointer data) ++{ ++#if TRAY_ENABLED ++ if (hime_status_tray) { ++ if (hime_tray_display == HIME_TRAY_DISPLAY_SINGLE) ++ init_tray(); ++ else if (hime_tray_display == HIME_TRAY_DISPLAY_DOUBLE) ++ init_tray_double(); ++#if TRAY_UNITY ++ else if (hime_tray_display == HIME_TRAY_DISPLAY_APPINDICATOR) ++ init_tray_appindicator(); ++#endif ++ } ++#endif ++ ++ dbg("after init_tray\n"); ++ ++ return FALSE; ++} ++ ++void get_dpy_xyl() ++{ ++ dpy_xl = gdk_screen_width(), dpy_yl = gdk_screen_height(); ++} ++ ++void screen_size_changed(GdkScreen *screen, gpointer user_data) ++{ ++ get_dpy_xyl(); ++} ++ ++#include "lang.h" ++ ++extern int destroy_window; ++ ++int main(int argc, char **argv) ++{ ++ char *destroy = getenv("HIME_DESTROY_WINDOW"); ++ if (destroy) ++ destroy_window = atoi(destroy); ++// printf("HIME_DESTROY_WINDOW=%d\n",destroy_window); ++ ++ gtk_init (&argc, &argv); ++ ++ signal(SIGCHLD, SIG_IGN); ++ signal(SIGPIPE, SIG_IGN); ++ ++ if (getenv("HIME_DAEMON")) { ++ daemon(1,1); ++#if FREEBSD ++ setpgid(0, getpid()); ++#else ++ setpgrp(); ++#endif ++ } ++ ++ set_is_chs(); ++ ++ char *lc_ctype = getenv("LC_CTYPE"); ++ char *lc_all = getenv("LC_ALL"); ++ char *lang = getenv("LANG"); ++ if (!lc_ctype && lang) ++ lc_ctype = lang; ++ ++ if (lc_all) ++ lc_ctype = lc_all; ++ ++ if (!lc_ctype) ++ lc_ctype = "zh_TW.Big5"; ++ dbg("hime get env LC_CTYPE=%s LC_ALL=%s LANG=%s\n", lc_ctype, lc_all, lang); ++ ++#if USE_XIM ++ char *t = strchr(lc_ctype, '.'); ++ if (t) { ++ int len = t - lc_ctype; ++#if MAC_OS || FREEBSD ++ lc = strdup(lc_ctype); ++ lc[len] = 0; ++#else ++ lc = g_strndup(lc_ctype, len); ++#endif ++ } ++ else ++ lc = lc_ctype; ++ ++ dbg("hime XIM will use %s as the default encoding\n", lc_ctype); ++#endif ++ ++ if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "-h")) ) { ++#if GIT_HAVE ++ p_err(" version %s (git %s)\n", HIME_VERSION, GIT_HASH); ++#else ++ p_err(" version %s\n", HIME_VERSION); ++#endif ++ } ++ ++ init_TableDir(); ++ load_settings(); ++ load_gtab_list(TRUE); ++ ++ ++#if HIME_i18n_message ++ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); ++ textdomain(GETTEXT_PACKAGE); ++#endif ++ ++ dbg("after gtk_init\n"); ++ ++ dpy = GDK_DISPLAY(); ++ root=DefaultRootWindow(dpy); ++ get_dpy_xyl(); ++ g_signal_connect(gdk_screen_get_default(),"size-changed", G_CALLBACK(screen_size_changed), NULL); ++ ++ dbg("display width:%d height:%d\n", dpy_xl, dpy_yl); ++ ++ start_inmd_window(); ++ ++#if USE_XIM ++ open_xim(); ++#endif ++ ++ gdk_window_add_filter(NULL, my_gdk_filter, NULL); ++ ++ init_atom_property(); ++ signal(SIGINT, sig_do_exit); ++ signal(SIGHUP, sig_do_exit); ++ // disable the io handler abort ++ // void *olderr = ++ XSetErrorHandler((XErrorHandler)xerror_handler); ++ ++ init_hime_im_serv(xim_xwin); ++ ++ exec_setup_scripts(); ++ ++ g_timeout_add(200, delayed_start_cb, NULL); // Old setting is 5000 here. ++ ++ dbg("before gtk_main\n"); ++ ++ disp_win_kbm_capslock_init(); ++ ++ gtk_main(); ++ ++ return 0; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/hime.h b/src/plugins/platforminputcontexts/hime/include/hime.h +new file mode 100644 +index 0000000..047cc12 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/hime.h +@@ -0,0 +1,181 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include "os-dep.h" ++#include ++#include ++#include "IMdkit/include/IMdkit.h" ++#include "IMdkit/include/Xi18n.h" ++#if HIME_i18n_message ++#include ++#define _(STRING) gettext(STRING) ++#else ++#define _(STRING) (STRING) ++#endif ++ ++#define N_(STRING) (STRING) ++ ++#include "hime-gtk-compatible.h" ++ ++typedef enum { ++ HIME_STATE_DISABLED = 0, ++ HIME_STATE_ENG_FULL = 1, ++ HIME_STATE_CHINESE = 2 ++} HIME_STATE_E; ++ ++/* change 3 to 4 if you want to use 4-byte UTF-8 characters, but you must ++ regenerate *.gtab tsin ++*/ ++#define CH_SZ (4) ++ ++ ++#include "IC.h" ++ ++#if CLIENT_LIB ++#define p_err __hime_p_err ++#define zmalloc __hime_zmalloc ++#endif ++ ++#include "util.h" ++ ++#define tmalloc(type,n) (type*)malloc(sizeof(type) * (n)) ++void *zmalloc(int n); ++void *memdup(void *p, int n); ++#define tzmalloc(type,n) (type*)zmalloc(sizeof(type) * (n)) ++#define trealloc(p,type,n) (type*)realloc(p, sizeof(type) * (n+1)) ++#define tmemdup(p,type,n) (type*)memdup(p, sizeof(type) * n) ++extern Display *dpy; ++ ++extern char *TableDir; ++extern GtkWidget *gwin0; ++extern GdkWindow *gdkwin0; ++extern Window xwin0; ++extern Window root; ++void loadIC(); ++IC *FindIC(CARD16 icid); ++extern ClientState *current_CS; ++ ++enum { ++ InputStyleOverSpot = 1, ++ InputStyleRoot = 2, ++ InputStyleOnSpot = 4 ++}; ++ ++typedef enum { ++ Control_Space=0, ++ Shift_Space=1, ++ Alt_Space=2, ++ Windows_Space=3, ++} IM_TOGGLE_KEYS; ++ ++enum { ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_None=0, ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_CapsLock=1, ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Tab=2, ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift=4, ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL=8, ++ TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR=16, ++}; ++ ++typedef enum { ++ TSIN_SPACE_OPT_SELECT_CHAR = 1, ++ TSIN_SPACE_OPT_INPUT = 2, ++} TSIN_SPACE_OPT; ++ ++enum { ++ HIME_EDIT_DISPLAY_OVER_THE_SPOT=1, ++ HIME_EDIT_DISPLAY_ON_THE_SPOT=2, ++ HIME_EDIT_DISPLAY_BOTH=4, ++}; ++ ++#if TRAY_ENABLED ++enum { ++ HIME_TRAY_DISPLAY_SINGLE=1, ++ HIME_TRAY_DISPLAY_DOUBLE=2, ++ HIME_TRAY_DISPLAY_APPINDICATOR=3, ++}; ++#endif ++ ++#define HIME_SEL_KEY_COLOR_DEFAULT "blue" ++#define TSIN_CURSOR_COLOR_DEFAULT "blue" ++ ++#define ROW_ROW_SPACING (2) ++ ++ ++#define MAX_HIME_STR (256) ++ ++#define PHO_KBM "phokbm" ++ ++extern int win_xl, win_yl; ++extern int win_x, win_y; // actual win x/y ++extern int current_in_win_x, current_in_win_y; // request x/y ++extern int dpy_xl, dpy_yl; ++ ++extern int hime_font_size; ++ ++void big5_utf8(char *s, char out[]); ++void utf8_big5(char *s, char out[]); ++gint inmd_switch_popup_handler (GtkWidget *widget, GdkEvent *event); ++ ++#include "hime-conf.h" ++ ++#define bchcpy(a,b) memcpy(a,b, CH_SZ) ++#define bchcmp(a,b) memcmp(a,b, CH_SZ) ++ ++int utf8_sz(char *s); ++int utf8cpy(char *t, char *s); ++int u8cpy(char *t, char *s); ++int utf8_tlen(char *s, int N); ++void utf8_putchar(char *s); ++void utf8_putcharn(char *s, int n); ++gboolean utf8_eq(char *a, char *b); ++gboolean utf8_str_eq(char *a, char *b, int len); ++void utf8cpyN(char *t, char *s, int N); ++int utf8_str_N(char *str); ++void utf8cpyn(char *t, char *s, int n); ++void utf8cpy_bytes(char *t, char *s, int n); ++char *myfgets(char *buf, int bufN, FILE *fp); ++void get_hime_dir(char *tt); ++Atom get_hime_atom(Display *dpy); ++void get_sys_table_file_name(char *name, char *fname); ++char *half_char_to_full_char(KeySym xkey); ++void send_text(char *text); ++void send_utf8_ch(char *bchar); ++void send_ascii(char key); ++void bell(); ++void set_label_font_size(GtkWidget *label, int size); ++void send_hime_message(Display *dpy, char *s); ++void check_CS(); ++gint64 current_time(); ++void get_win_size(GtkWidget *win, int *width, int *height); ++void change_win_fg_bg(GtkWidget *win, GtkWidget *label); ++void set_no_focus(GtkWidget *win); ++void change_win_bg(GtkWidget *win); ++gboolean hime_edit_display_ap_only(); ++gboolean hime_display_on_the_spot_key(); ++void char_play(char *utf8); ++void skip_utf8_sigature(FILE *fp); ++ ++#define BITON(flag, bit) ((flag) & (bit)) ++ ++typedef int usecount_t; ++ ++#define MAX_CIN_PHR (100*CH_SZ + 1) +diff --git a/src/plugins/platforminputcontexts/hime/include/im-addr.c b/src/plugins/platforminputcontexts/hime/include/im-addr.c +new file mode 100644 +index 0000000..642b34a +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-addr.c +@@ -0,0 +1,95 @@ ++/* Copyright (C) 2009 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include "hime.h" ++ ++char *get_hime_xim_name(); ++ ++void get_hime_im_srv_sock_path(char *outstr, int outstrN) ++{ ++ char *disp = getenv("DISPLAY"); ++ int my_uid = getuid(); ++ ++ if (!disp || !strcmp(disp, ":0")) ++ disp = ":0.0"; ++ ++ char tdisp[64]; ++ strcpy(tdisp, disp); ++ ++ if (!strchr(disp, ':')) ++ strcat(tdisp, ":0"); ++ if (!strchr(disp, '.')) ++ strcat(tdisp, ".0"); ++ ++ char my_dir[128]; ++ ++ struct passwd *pw = getpwuid(my_uid); ++ snprintf(my_dir, sizeof(my_dir), "%s/.hime-%s", g_get_tmp_dir(), pw->pw_name); ++ struct stat st; ++ ++ if (stat(my_dir, &st) < 0) ++ mkdir(my_dir, 0700); ++ else { ++ if (st.st_uid != my_uid) { ++ fprintf(stderr, "please check the permission of dir %s\n", my_dir); ++ return; ++ } ++ } ++ ++ snprintf(outstr,outstrN, "%s/socket-%s-%s", my_dir, tdisp, get_hime_xim_name()); ++} ++ ++ ++Atom get_hime_addr_atom(Display *dpy) ++{ ++ if (!dpy) { ++ dbg("dpy is null\n"); ++ return 0; ++ } ++ ++ char *xim_name = get_hime_xim_name(); ++ char tt[128]; ++ ++ snprintf(tt, sizeof(tt), "HIME_ADDR_ATOM_%s", xim_name); ++ ++ Atom atom = XInternAtom(dpy, tt, False); ++ ++ return atom; ++} ++ ++ ++ ++Atom get_hime_sockpath_atom(Display *dpy) ++{ ++ if (!dpy) { ++ dbg("dpy is null\n"); ++ return 0; ++ } ++ ++ char *xim_name = get_hime_xim_name(); ++ char tt[128]; ++ ++ snprintf(tt, sizeof(tt), "HIME_SOCKPATH_ATOM_%s", xim_name); ++ ++ Atom atom = XInternAtom(dpy, tt, False); ++ ++ return atom; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client-attr.h b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client-attr.h +new file mode 100644 +index 0000000..ea7369c +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client-attr.h +@@ -0,0 +1,9 @@ ++#define HIME_PREEDIT_ATTR_FLAG_UNDERLINE 1 ++#define HIME_PREEDIT_ATTR_FLAG_REVERSE 2 ++#define HIME_PREEDIT_ATTR_MAX_N 64 ++#define HIME_PREEDIT_MAX_STR 512 ++ ++typedef struct { ++ int flag; ++ short ofs0, ofs1; // ofs : bytes offset ++} HIME_PREEDIT_ATTR; +diff --git a/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.c b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.c +new file mode 100644 +index 0000000..fa67248 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.c +@@ -0,0 +1,815 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../hime.h" ++#include "hime-protocol.h" ++#include "hime-im-client.h" ++#define DBG 0 ++static int flags_backup; ++ ++Atom get_hime_sockpath_atom(Display *dpy); ++static void save_old_sigaction_single(int signo, struct sigaction *act) ++{ ++ sigaction(signo, NULL, act); ++ ++ if (act->sa_handler != SIG_IGN) { ++ signal(signo, SIG_IGN); ++ } ++} ++ ++static void restore_old_sigaction_single(int signo, struct sigaction *act) ++{ ++ if (act->sa_handler != SIG_IGN) ++ signal(signo, act->sa_handler); ++} ++char *get_hime_im_srv_sock_path(); ++Atom get_hime_addr_atom(Display *dpy); ++ ++Window find_hime_window(Display *dpy) ++{ ++ Atom hime_addr_atom = get_hime_addr_atom(dpy); ++ if (!hime_addr_atom) ++ return FALSE; ++ return XGetSelectionOwner(dpy, hime_addr_atom); ++} ++ ++int is_special_user; ++ ++static HIME_client_handle *hime_im_client_reopen(HIME_client_handle *hime_ch, Display *dpy) ++{ ++// dbg("hime_im_client_reopen\n"); ++ int dbg_msg = getenv("HIME_CONNECT_MSG_ON") != NULL; ++ int sockfd=0; ++ int servlen; ++// char *addr; ++ Server_IP_port srv_ip_port; ++#if DEBUG ++ u_char *pp; ++#endif ++ ++ int uid = getuid(); ++ if (uid > 0 && uid < 500) { ++ is_special_user = TRUE; ++ } ++ ++ int tcp = FALSE; ++ HIME_client_handle *handle; ++ int rstatus; ++ ++// dbg("hime_im_client_reopen\n"); ++ if (!dpy) { ++ dbg("null disp %d\n", hime_ch->fd); ++ goto next; ++ } ++ ++ Atom hime_addr_atom = get_hime_addr_atom(dpy); ++ Window hime_win = None; ++ ++ ++#define MAX_TRY 3 ++ int loop; ++ ++ if (!is_special_user) ++ for(loop=0; loop < MAX_TRY; loop++) { ++ if ((hime_win=find_hime_window(dpy))!=None || getenv("HIME_IM_CLIENT_NO_AUTO_EXEC")) ++ break; ++ static time_t exec_time; ++ ++ if (time(NULL) - exec_time > 1 /* && count < 5 */) { ++ time(&exec_time); ++ dbg("XGetSelectionOwner: old version of hime or hime is not running ??\n"); ++ static char execbin[]=HIME_BIN_DIR"/hime"; ++ dbg("... try to start a new hime server %s\n", execbin); ++ ++ int pid; ++ ++ if ((pid=fork())==0) { ++ setenv("HIME_DAEMON", "", TRUE); ++ execl(execbin, "hime", NULL); ++ } else { ++ int status; ++ // hime will daemon() ++ waitpid(pid, &status, 0); ++ } ++ } ++ } ++ ++ if (loop == MAX_TRY || hime_win == None) { ++ goto next; ++ } ++ ++ Atom actual_type; ++ int actual_format; ++ u_long nitems,bytes_after; ++ char *message_sock = NULL; ++ Atom hime_sockpath_atom = get_hime_sockpath_atom(dpy); ++ ++// printf("hime_sockpath_atom %d\n", hime_sockpath_atom); ++ ++ if (!hime_sockpath_atom || XGetWindowProperty(dpy, hime_win, hime_sockpath_atom, 0, 64, ++ False, AnyPropertyType, &actual_type, &actual_format, ++ &nitems,&bytes_after,(u_char **)&message_sock) != Success) { ++#if DBG || 1 ++ dbg("XGetWindowProperty 2: old version of hime or hime is not running ??\n"); ++#endif ++ goto next; ++ } ++ ++ Server_sock_path srv_sock_path; ++ srv_sock_path.sock_path[0] = 0; ++ if (message_sock) { ++ memcpy(&srv_sock_path, message_sock, sizeof(srv_sock_path)); ++ XFree(message_sock); ++ } else ++ goto next; ++ ++ struct sockaddr_un serv_addr; ++ bzero((char *) &serv_addr,sizeof(serv_addr)); ++ serv_addr.sun_family = AF_UNIX; ++ char sock_path[UNIX_PATH_MAX]; ++ ++ if (srv_sock_path.sock_path[0]) { ++ strcpy(sock_path, srv_sock_path.sock_path); ++ } ++ else { ++ get_hime_im_srv_sock_path(sock_path, sizeof(sock_path)); ++ } ++ ++// addr = sock_path; ++ strcpy(serv_addr.sun_path, sock_path); ++#ifdef SUN_LEN ++ servlen = SUN_LEN(&serv_addr); ++#else ++ servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); ++#endif ++ ++ if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { ++ perror("cannot open socket"); ++ goto tcp; ++ } ++ ++ if (connect(sockfd, (struct sockaddr *)&serv_addr, servlen) < 0) { ++ close(sockfd); ++ sockfd = 0; ++ goto tcp; ++ } ++ ++ if (dbg_msg) ++ dbg("connected to unix socket addr %s\n", sock_path); ++ goto next; ++ ++ char *message; ++ ++tcp: ++ message = NULL; ++ ++ if (!hime_addr_atom || XGetWindowProperty(dpy, hime_win, hime_addr_atom, 0, 64, ++ False, AnyPropertyType, &actual_type, &actual_format, ++ &nitems,&bytes_after,(u_char **)&message) != Success) { ++#if DBG || 1 ++ dbg("XGetWindowProperty: old version of hime or hime is not running ??\n"); ++#endif ++ goto next; ++ } ++ ++ if (message) { ++ memcpy(&srv_ip_port, message, sizeof(srv_ip_port)); ++ XFree(message); ++ } else ++ goto next; ++ ++ ++// dbg("im server tcp port %d\n", ntohs(srv_ip_port.port)); ++ ++ struct sockaddr_in in_serv_addr; ++ bzero((char *) &in_serv_addr, sizeof(in_serv_addr)); ++ ++ in_serv_addr.sin_family = AF_INET; ++ in_serv_addr.sin_addr.s_addr = srv_ip_port.ip; ++ in_serv_addr.sin_port = srv_ip_port.port; ++ servlen = sizeof(in_serv_addr); ++ ++ ++ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ++ perror("cannot open socket"); ++ goto next; ++ } ++ ++ dbg("sock %d\n", sockfd); ++ ++ if (connect(sockfd, (struct sockaddr *)&in_serv_addr, servlen) < 0) { ++ dbg("hime_im_client_open cannot open: ") ; ++ perror(""); ++ close(sockfd); ++ sockfd = 0; ++ goto next; ++ } ++ ++#if DEBUG ++ pp = (u_char *)&srv_ip_port.ip; ++ if (dbg_msg) ++ dbg("hime client connected to server %d.%d.%d.%d:%d\n", ++ pp[0], pp[1], pp[2], pp[3], ntohs(srv_ip_port.port)); ++#endif ++ ++ tcp = TRUE; ++ ++next: ++ if (!hime_ch) ++ handle = tzmalloc(HIME_client_handle, 1); ++ else { ++ handle = hime_ch; ++ } ++ ++ if (sockfd < 0) ++ sockfd = 0; ++ ++ if (sockfd > 0) { ++ handle->fd = sockfd; ++ if (tcp) { ++ if (!handle->passwd) ++ handle->passwd = malloc(sizeof(HIME_PASSWD)); ++ memcpy(handle->passwd, &srv_ip_port.passwd, sizeof(srv_ip_port.passwd)); ++ } else { ++ if (handle->passwd) { ++ free(handle->passwd); handle->passwd = NULL; ++ } ++ } ++ } ++ ++ if (handle->fd) { ++ if (BITON(handle->flag, FLAG_HIME_client_handle_has_focus)) ++ hime_im_client_focus_in(handle); ++ ++ hime_im_client_set_flags(handle, flags_backup, &rstatus); ++ } ++ ++ return handle; ++} ++ ++ ++static void validate_handle(HIME_client_handle *hime_ch) ++{ ++ if (hime_ch->fd > 0) ++ return; ++ if (is_special_user) ++ return; ++ ++ hime_im_client_reopen(hime_ch, hime_ch->disp); ++} ++ ++ ++HIME_client_handle *hime_im_client_open(Display *disp) ++{ ++// dbg("hime_im_client_open\n"); ++ HIME_client_handle *handle = hime_im_client_reopen(NULL, disp); ++ handle->disp = disp; ++ return handle; ++} ++ ++void hime_im_client_close(HIME_client_handle *handle) ++{ ++ if (!handle) ++ return; ++ if (handle->fd > 0) ++ close(handle->fd); ++ free(handle->passwd); ++ free(handle); ++} ++ ++static int gen_req(HIME_client_handle *handle, u_int req_no, HIME_req *req) ++{ ++ validate_handle(handle); ++ ++ if (!handle->fd) ++ return 0; ++ ++ handle->seq++; ++ ++ bzero(req, sizeof(HIME_req)); ++ ++ req->req_no = req_no; ++ to_hime_endian_4(&req->req_no); ++ ++ req->client_win = handle->client_win; ++ to_hime_endian_4(&req->client_win); ++ ++ req->input_style = handle->input_style; ++ to_hime_endian_4(&req->input_style); ++ ++ req->spot_location.x = handle->spot_location.x; ++ req->spot_location.y = handle->spot_location.y; ++ to_hime_endian_2(&req->spot_location.x); ++ to_hime_endian_2(&req->spot_location.y); ++ ++ return 1; ++} ++ ++static void error_proc(HIME_client_handle *handle, char *msg) ++{ ++ if (!handle->fd) ++ return; ++ ++ perror(msg); ++ close(handle->fd); ++ handle->fd = 0; ++ usleep(100000); ++} ++ ++typedef struct { ++ struct sigaction apipe; ++} SAVE_ACT; ++static void save_old_sigaction(SAVE_ACT *save_act) ++{ ++ save_old_sigaction_single(SIGPIPE, &save_act->apipe); ++} ++static void restore_old_sigaction(SAVE_ACT *save_act) ++{ ++ restore_old_sigaction_single(SIGPIPE, &save_act->apipe); ++} ++static int handle_read(HIME_client_handle *handle, void *ptr, int n) ++{ ++ int fd = handle->fd; ++ ++ if (!fd) ++ return 0; ++ ++ SAVE_ACT save_act; ++ save_old_sigaction(&save_act); ++ int r = read(fd, ptr, n); ++ ++#if (DBG || 1) ++ if (r < 0) ++ perror("handle_read"); ++#endif ++ ++ restore_old_sigaction(&save_act); ++ ++ if (r<=0) ++ return r; ++ if (handle->passwd) ++ __hime_enc_mem((u_char *)ptr, n, handle->passwd, &handle->passwd->seed); ++ return r; ++} ++ ++static int handle_write(HIME_client_handle *handle, void *ptr, int n) ++{ ++ int fd = handle->fd; ++ ++ if (!fd) ++ return 0; ++ ++ u_char *tmp = malloc(n); ++ memcpy(tmp, ptr, n); ++ ++ if (handle->passwd) ++ __hime_enc_mem(tmp, n, handle->passwd, &handle->passwd->seed); ++ ++ SAVE_ACT save_act; ++#if 1 ++ save_old_sigaction(&save_act); ++#endif ++ int r = write(fd, tmp, n); ++#if 1 ++ restore_old_sigaction(&save_act); ++#endif ++ free(tmp); ++ ++ return r; ++} ++ ++void hime_im_client_focus_in(HIME_client_handle *handle) ++{ ++ if (!handle) ++ return; ++ if (is_special_user) ++ return; ++ ++ HIME_req req; ++// dbg("hime_im_client_focus_in\n"); ++ handle->flag |= FLAG_HIME_client_handle_has_focus; ++ ++ if (!gen_req(handle, HIME_req_focus_in, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_focus_in error"); ++ } ++ ++ hime_im_client_set_cursor_location(handle, handle->spot_location.x, ++ handle->spot_location.y); ++} ++ ++ ++void hime_im_client_focus_out(HIME_client_handle *handle) ++{ ++ if (!handle) ++ return; ++ if (is_special_user) ++ return; ++ ++ HIME_req req; ++// dbg("hime_im_client_focus_out\n"); ++ handle->flag &= ~FLAG_HIME_client_handle_has_focus; ++ ++ if (!gen_req(handle, HIME_req_focus_out, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_focus_out error"); ++ } ++} ++ ++void hime_im_client_focus_out2(HIME_client_handle *handle, char **rstr) ++{ ++ HIME_req req; ++ HIME_reply reply; ++ ++ if (rstr) ++ *rstr = NULL; ++ ++ if (!handle) ++ return; ++ ++ if (is_special_user) ++ return; ++ ++#if DBG ++ dbg("hime_im_client_focus_out2\n"); ++#endif ++ handle->flag &= ~FLAG_HIME_client_handle_has_focus; ++ ++ if (!gen_req(handle, HIME_req_focus_out2, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_focus_out error"); ++ } ++ ++ bzero(&reply, sizeof(reply)); ++ if (handle_read(handle, &reply, sizeof(reply)) <=0) { ++ error_proc(handle, "cannot read reply from hime server"); ++ return; ++ } ++ ++ to_hime_endian_4(&reply.datalen); ++ to_hime_endian_4(&reply.flag); ++ ++ if (reply.datalen > 0) { ++ *rstr = (char *)malloc(reply.datalen); ++ if (handle_read(handle, *rstr, reply.datalen) <= 0) { ++ free(*rstr); *rstr = NULL; ++ error_proc(handle, "cannot read reply str from hime server"); ++ return; ++ } ++ } ++ ++// dbg("hime_im_client_forward_key_event %x\n", reply.flag); ++ ++ return; ++} ++ ++static int hime_im_client_forward_key_event(HIME_client_handle *handle, ++ HIME_req_t event_type, ++ KeySym key, u_int state, ++ char **rstr) ++{ ++ HIME_reply reply; ++ HIME_req req; ++ ++ *rstr = NULL; ++ ++ if (is_special_user) { ++ return 0; ++ } ++ ++ if (!gen_req(handle, event_type, &req)) ++ return 0; ++ ++ req.keyeve.key = key; ++ to_hime_endian_4(&req.keyeve.key); ++ req.keyeve.state = state; ++ to_hime_endian_4(&req.keyeve.state); ++ ++ ++ if (handle_write(handle, &req, sizeof(req)) <= 0) { ++ error_proc(handle, "cannot write to hime server"); ++ return FALSE; ++ } ++ ++ bzero(&reply, sizeof(reply)); ++ if (handle_read(handle, &reply, sizeof(reply)) <=0) { ++ error_proc(handle, "cannot read reply from hime server"); ++ return FALSE; ++ } ++ ++ to_hime_endian_4(&reply.datalen); ++ to_hime_endian_4(&reply.flag); ++ ++ if (reply.datalen > 0) { ++ *rstr = (char *)malloc(reply.datalen); ++ if (handle_read(handle, *rstr, reply.datalen) <= 0) { ++ free(*rstr); *rstr = NULL; ++ error_proc(handle, "cannot read reply str from hime server"); ++ return FALSE; ++ } ++ } ++ ++// dbg("hime_im_client_forward_key_event %x\n", reply.flag); ++ ++ return reply.flag; ++} ++ ++ ++// return TRUE if the key is accepted ++int hime_im_client_forward_key_press(HIME_client_handle *handle, ++ KeySym key, u_int state, ++ char **rstr) ++{ ++ int flag; ++ if (!handle) ++ return 0; ++ // in case client didn't send focus in event ++ if (!BITON(handle->flag, FLAG_HIME_client_handle_has_focus)) { ++ hime_im_client_focus_in(handle); ++ handle->flag |= FLAG_HIME_client_handle_has_focus; ++ hime_im_client_set_cursor_location(handle, handle->spot_location.x, ++ handle->spot_location.y); ++ } ++ ++// dbg("hime_im_client_forward_key_press\n"); ++ flag = hime_im_client_forward_key_event( ++ handle, HIME_req_key_press, key, state, rstr); ++ ++ return ((flag & HIME_reply_key_processed) !=0); ++} ++ ++ ++// return TRUE if the key is accepted ++int hime_im_client_forward_key_release(HIME_client_handle *handle, ++ KeySym key, u_int state, ++ char **rstr) ++{ ++ int flag; ++ if (!handle) ++ return 0; ++ handle->flag |= FLAG_HIME_client_handle_has_focus; ++// dbg("hime_im_client_forward_key_release\n"); ++ flag = hime_im_client_forward_key_event( ++ handle, HIME_req_key_release, key, state, rstr); ++ return ((flag & HIME_reply_key_processed) !=0); ++} ++ ++ ++void hime_im_client_set_cursor_location(HIME_client_handle *handle, int x, int y) ++{ ++ if (!handle) ++ return; ++ if (is_special_user) ++ return; ++ ++// dbg("hime_im_client_set_cursor_location %d %d,%d\n", handle->flag, x, y); ++ ++ HIME_req req; ++ handle->spot_location.x = x; ++ handle->spot_location.y = y; ++ ++ if (!BITON(handle->flag, FLAG_HIME_client_handle_has_focus)) ++ return; ++ ++ if (!gen_req(handle, HIME_req_set_cursor_location, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_set_cursor_location error"); ++ } ++} ++ ++// in win32, if win is NULL, this means hime_im_client_set_cursor_location(x,y) is screen position ++void hime_im_client_set_window(HIME_client_handle *handle, Window win) ++{ ++ if (!handle) ++ return; ++// dbg("hime_im_client_set_window %x\n", win); ++ ++ if (is_special_user) ++ return; ++ if (!win) ++ return; ++ handle->client_win = win; ++ ++// For chrome ++// hime_im_client_set_cursor_location(handle, handle->spot_location.x, handle->spot_location.y); ++} ++ ++void hime_im_client_set_flags(HIME_client_handle *handle, int flags, int *ret_flag) ++{ ++ HIME_req req; ++ ++#if DBG ++ dbg("hime_im_client_set_flags\n"); ++#endif ++ ++ if (!handle) ++ return; ++ ++ if (is_special_user) ++ return; ++ ++ if (!gen_req(handle, HIME_req_set_flags, &req)) ++ return; ++ ++ req.flag |= flags; ++ ++ flags_backup = req.flag; ++ ++#if DBG ++ dbg("hime_im_client_set_flags b\n"); ++#endif ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_set_flags error"); ++ } ++ ++#if DBG ++ dbg("hime_im_client_set_flags c\n"); ++#endif ++ ++ if (handle_read(handle, ret_flag, sizeof(int)) <= 0) { ++ error_proc(handle, "cannot read reply str from hime server"); ++ } ++} ++ ++ ++void hime_im_client_clear_flags(HIME_client_handle *handle, int flags, int *ret_flag) ++{ ++ HIME_req req; ++ ++ if (!handle) ++ return; ++ ++ if (is_special_user) ++ return; ++ ++ if (!gen_req(handle, HIME_req_set_flags, &req)) ++ return; ++ ++ req.flag &= ~flags; ++ ++ flags_backup = req.flag; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_set_flags error"); ++ } ++ ++ if (handle_read(handle, ret_flag, sizeof(int)) <= 0) { ++ error_proc(handle, "cannot read reply str from hime server"); ++ } ++} ++ ++ ++int hime_im_client_get_preedit(HIME_client_handle *handle, char **str, HIME_PREEDIT_ATTR att[], int *cursor ,int *sub_comp_len) ++{ ++ *str=NULL; ++ if (!handle) ++ return 0; ++ ++ if (is_special_user) ++ return 0; ++ ++ int attN, tcursor, str_len; ++#if DBG ++ dbg("hime_im_client_get_preedit\n"); ++#endif ++ HIME_req req; ++ if (!gen_req(handle, HIME_req_get_preedit, &req)) { ++err_ret: ++#if DBG ++ dbg("aaaaaaaaaaaaa %x\n", str); ++#endif ++ if (cursor) ++ *cursor=0; ++ *str=strdup(""); ++ return 0; ++ } ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_get_preedit error"); ++ goto err_ret; ++ } ++ ++ str_len=-1; // str_len includes \0 ++ if (handle_read(handle, &str_len, sizeof(str_len))<=0) ++ goto err_ret; // including \0 ++ ++ *str = (char *)malloc(str_len); ++ ++ if (handle_read(handle, *str, str_len)<=0) ++ goto err_ret; ++#if DBG ++ dbg("hime_im_client_get_preedit len:%d '%s' \n", str_len, *str); ++#endif ++ attN = -1; ++ if (handle_read(handle, &attN, sizeof(attN))<=0) { ++ goto err_ret; ++ } ++ ++// dbg("attrN:%d\n", attN); ++ ++ if (attN>0 && handle_read(handle, att, sizeof(HIME_PREEDIT_ATTR)*attN)<=0) { ++ goto err_ret; ++ } ++ ++ ++ tcursor=0; ++ if (handle_read(handle, &tcursor, sizeof(tcursor))<=0) { ++ goto err_ret; ++ } ++ ++ if (cursor) ++ *cursor = tcursor; ++ ++ int tsub_comp_len; ++ tsub_comp_len=0; ++ if (handle_read(handle, &tsub_comp_len, sizeof(tsub_comp_len))<=0) { ++ goto err_ret; ++ } ++ if (sub_comp_len) ++ *sub_comp_len = tsub_comp_len; ++ ++#if DBG ++ dbg("jjjjjjjjj %d tcursor:%d\n", attN, tcursor); ++#endif ++ return attN; ++} ++ ++ ++ ++void hime_im_client_reset(HIME_client_handle *handle) ++{ ++ if (!handle) ++ return; ++ ++ if (is_special_user) ++ return; ++ ++ HIME_req req; ++#if DBG ++ dbg("hime_im_client_reset\n"); ++#endif ++ if (!gen_req(handle, HIME_req_reset, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_reset error"); ++ } ++} ++ ++ ++void hime_im_client_message(HIME_client_handle *handle, char *message) ++{ ++ HIME_req req; ++ short len; ++#if DBG ++ dbg("hime_im_client_message\n"); ++#endif ++ if (!gen_req(handle, HIME_req_message, &req)) ++ return; ++ ++ if (handle_write(handle, &req, sizeof(req)) <=0) { ++ error_proc(handle,"hime_im_client_message error 1"); ++ } ++ ++ len = strlen(message)+1; ++ if (handle_write(handle, &len, sizeof(len)) <=0) { ++ error_proc(handle,"hime_im_client_message error 2"); ++ } ++ ++ if (handle_write(handle, message, len) <=0) { ++ error_proc(handle,"hime_im_client_message error 2"); ++ } ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.h b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.h +new file mode 100644 +index 0000000..54d8f44 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-client/hime-im-client.h +@@ -0,0 +1,96 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef HIME_IM_CLIENT_H ++#define HIME_IM_CLIENT_H ++ ++#ifndef _XSERVER64 ++#define _XSERVER64 ++#endif ++ ++struct HIME_PASSWD; ++ ++typedef struct HIME_client_handle_S { ++ int fd; ++ Window client_win; /* client window */ ++ u_int input_style; /* input style */ ++ XPoint spot_location; /* spot location */ ++// below is private data, don't modify them. ++ u_int flag; ++ Display *disp; ++ struct HIME_PASSWD *passwd; ++ u_int seq; ++} HIME_client_handle; ++ ++enum { ++ FLAG_HIME_client_handle_has_focus = 1, ++ FLAG_HIME_client_handle_use_preedit = 2, ++ FLAG_HIME_client_handle_raise_window = 0x1000 // for mozilla, dirty fix ++}; ++ ++enum { ++ FLAG_HIME_srv_ret_status_use_pop_up = 1 // If this is used, we don't need the dirty fix ++}; ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++HIME_client_handle *hime_im_client_open(Display *disp); ++void hime_im_client_close(HIME_client_handle *handle); ++void hime_im_client_focus_in(HIME_client_handle *handle); ++void hime_im_client_focus_out(HIME_client_handle *handle); ++void hime_im_client_focus_out2(HIME_client_handle *handle, char **rstr); ++void hime_im_client_set_window(HIME_client_handle *handle, Window win); ++void hime_im_client_set_cursor_location(HIME_client_handle *handle, ++ int x, int y); ++/* rstr returns UTF-8 encoded string, you should use 'free()' to free the ++ memory. ++ ++ return boolean: ++ FALSE : the key is rejected, should use client's own result(ASCII key). ++ TRUE : the key is accepted, translated result is in rstr. ++ */ ++int hime_im_client_forward_key_press(HIME_client_handle *handle, ++ KeySym key, u_int state, ++ char **rstr); ++// return some state bits instead of TRUE/FALSE ++int hime_im_client_forward_key_press2(HIME_client_handle *handle, ++ KeySym key, u_int state, ++ char **rstr); ++int hime_im_client_forward_key_release(HIME_client_handle *handle, ++ KeySym key, u_int state, ++ char **rstr); ++ ++void hime_im_client_set_flags(HIME_client_handle *handle, int flags, int *ret_flags); ++void hime_im_client_clear_flags(HIME_client_handle *handle, int flags, int *ret_flags); ++ ++void hime_im_client_reset(HIME_client_handle *handle); ++void hime_im_client_message(HIME_client_handle *handle, char *message); ++ ++#include "hime-im-client-attr.h" ++int hime_im_client_get_preedit(HIME_client_handle *handle, char **str, HIME_PREEDIT_ATTR att[], int *cursor, int *sub_comp_len); ++ ++Window find_hime_window(Display *dpy); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/im-client/hime-protocol.h b/src/plugins/platforminputcontexts/hime/include/im-client/hime-protocol.h +new file mode 100644 +index 0000000..b7b4ee3 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-client/hime-protocol.h +@@ -0,0 +1,95 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include "../hime-endian.h" ++ ++#define UNIX_PATH_MAX 108 ++ ++typedef enum { ++ HIME_req_key_press = 1, ++ HIME_req_key_release = 2, ++ HIME_req_focus_in = 4, ++ HIME_req_focus_out = 8, ++ HIME_req_set_cursor_location = 0x10, ++ HIME_req_set_flags = 0x20, ++ HIME_req_get_preedit = 0x40, ++ HIME_req_reset = 0x80, ++ HIME_req_focus_out2 = 0x100, ++ HIME_req_message = 0x200, ++ HIME_req_test_key_press = 0x400, ++ HIME_req_test_key_release = 0x800, ++} HIME_req_t; ++ ++ ++typedef struct { ++#if 0 ++ KeySym key; ++#else ++ u_int key; ++#endif ++ u_int state; ++} KeyEvent; ++ ++typedef struct { ++ short x, y; ++} HIMEpoint; ++ ++ ++typedef struct { ++ u_int req_no; // to make the im server stateless, more is better ++ u_int client_win; ++ u_int flag; ++ u_int input_style; ++ HIMEpoint spot_location; ++ ++ union { ++ KeyEvent keyeve; ++ char dummy[32]; // for future expansion ++ }; ++} HIME_req; ++ ++ ++enum { ++ HIME_reply_key_processed = 1, ++ HIME_reply_key_state_disabled = 2, ++}; ++ ++ ++typedef struct { ++ u_int flag; ++ u_int datalen; // '\0' shoule be counted if data is string ++} HIME_reply; ++ ++ ++#define __HIME_PASSWD_N_ (31) ++ ++typedef struct HIME_PASSWD { ++ u_int seed; ++ u_char passwd[__HIME_PASSWD_N_]; ++} HIME_PASSWD; ++ ++typedef struct { ++ u_int ip; ++ u_short port; ++ HIME_PASSWD passwd; ++} Server_IP_port; ++ ++typedef struct { ++ char sock_path[UNIX_PATH_MAX]; ++} Server_sock_path; ++void __hime_enc_mem(u_char *p, int n, HIME_PASSWD *passwd, u_int *seed); +diff --git a/src/plugins/platforminputcontexts/hime/include/im-client/hime-send.c b/src/plugins/platforminputcontexts/hime/include/im-client/hime-send.c +new file mode 100644 +index 0000000..0b22fba +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-client/hime-send.c +@@ -0,0 +1,26 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "../hime.h" ++#include "hime-im-client.h" ++ ++void send_hime_message(Display *dpy, char *s) ++{ ++ HIME_client_handle *handle = hime_im_client_open(dpy); ++ hime_im_client_message(handle, s); ++ hime_im_client_close(handle); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/im-srv.c b/src/plugins/platforminputcontexts/hime/include/im-srv.c +new file mode 100644 +index 0000000..ac50497 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-srv.c +@@ -0,0 +1,293 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hime.h" ++#include "im-client/hime-protocol.h" ++#include "im-srv.h" ++#include ++ ++int im_sockfd, im_tcp_sockfd; ++Atom get_hime_sockpath_atom(Display *dpy); ++Server_IP_port srv_ip_port; ++static Window prop_win; ++static Atom addr_atom; ++ ++void gdk_input_remove (gint tag); ++ ++ ++void get_hime_im_srv_sock_path(char *outstr, int outstrN); ++void process_client_req(int fd); ++ ++static gboolean cb_read_hime_client_data(GIOChannel *source, GIOCondition condition, gpointer data) ++{ ++ int fd=GPOINTER_TO_INT(data); ++ ++ process_client_req(fd); ++ return TRUE; ++} ++ ++Atom get_hime_addr_atom(Display *dpy); ++ ++static void gen_passwd_idx() ++{ ++ srv_ip_port.passwd.seed = (rand() >> 1) % __HIME_PASSWD_N_; ++ ++ Server_IP_port tsrv_ip_port = srv_ip_port; ++ ++ to_hime_endian_4(&srv_ip_port.passwd.seed); ++ XChangeProperty(dpy, prop_win , addr_atom, XA_STRING, 8, ++ PropModeReplace, (unsigned char *)&tsrv_ip_port, sizeof(srv_ip_port)); ++ ++ XSync(GDK_DISPLAY(), FALSE); ++} ++ ++ ++ ++static gboolean cb_new_hime_client(GIOChannel *source, GIOCondition condition, gpointer data) ++{ ++ Connection_type type=(Connection_type) GPOINTER_TO_INT(data); ++#if 0 ++ dbg("im-srv: cb_new_hime_client %s\n", type==Connection_type_unix ? "unix":"tcp"); ++#endif ++ int newsockfd; ++ socklen_t clilen; ++ ++ if (type==Connection_type_unix) { ++ struct sockaddr_un cli_addr; ++ ++ bzero(&cli_addr, sizeof(cli_addr)); ++ clilen=0; ++ newsockfd = accept(im_sockfd,(struct sockaddr *) & cli_addr, &clilen); ++ } else ++ { ++ struct sockaddr_in cli_addr; ++ ++ bzero(&cli_addr, sizeof(cli_addr)); ++ clilen=sizeof(cli_addr); ++ newsockfd = accept(im_tcp_sockfd,(struct sockaddr *) & cli_addr, &clilen); ++ } ++ ++ if (newsockfd < 0) { ++ perror("accept"); ++ return FALSE; ++ } ++ ++// dbg("newsockfd %d\n", newsockfd); ++ ++ if (newsockfd >= hime_clientsN - 1) { ++ int prev_hime_clientsN = hime_clientsN, c; ++ hime_clientsN = newsockfd + 1; ++ hime_clients = trealloc(hime_clients, HIME_ENT, hime_clientsN); ++ // Initialize clientstate in useless hime_clients for recognition ++ for(c=prev_hime_clientsN;ch_addr_list[0], hent->h_length); ++#else ++ struct ifaddrs *ifaddr = NULL, *ifa; ++ int family; ++ ++ if (getifaddrs(&ifaddr) == -1) { ++ perror("getifaddrs"); ++ exit(EXIT_FAILURE); ++ } ++ ++ for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { ++ if (!ifa->ifa_addr) ++ continue; ++ ++ family = ifa->ifa_addr->sa_family; ++ if (family == AF_INET) { ++ struct sockaddr_in *padd=(struct sockaddr_in *)ifa->ifa_addr; ++ char *ipaddr = inet_ntoa(padd->sin_addr); ++ if (!strcmp(ipaddr, "127.0.0.1")) ++ continue; ++ dbg("ip addr %s\n", ipaddr); ++ memcpy(ip, &padd->sin_addr.s_addr, INET_ADDRSTRLEN); ++ break; ++ } ++ } ++ ++ freeifaddrs(ifaddr); ++#endif ++ return 0; ++} ++ ++ ++ ++void start_pipe_svr(); ++ ++void init_hime_im_serv(Window win) ++{ ++ dbg("init_hime_im_serv\n"); ++ ++ int servlen; ++ prop_win = win; ++ struct sockadd_un; ++ struct sockaddr_un serv_addr; ++ ++ // unix socket ++ bzero(&serv_addr,sizeof(serv_addr)); ++ serv_addr.sun_family = AF_UNIX; ++ char sock_path[UNIX_PATH_MAX]; ++ get_hime_im_srv_sock_path(sock_path, sizeof(sock_path)); ++ strcpy(serv_addr.sun_path, sock_path); ++ ++#ifdef SUN_LEN ++ servlen = SUN_LEN (&serv_addr); ++#else ++ servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); ++#endif ++ ++ dbg("-- %s\n",serv_addr.sun_path); ++ struct stat st; ++ ++ if (!stat(serv_addr.sun_path, &st)) { ++ if (unlink(serv_addr.sun_path) < 0) { ++ char tt[512]; ++ snprintf(tt, sizeof(tt), "unlink error %s", serv_addr.sun_path); ++ perror(tt); ++ } ++ } ++ ++ ++ if ((im_sockfd = socket(AF_UNIX,SOCK_STREAM,0)) < 0) { ++ perror("cannot open unix socket"); ++ exit(-1); ++ } ++ ++ if (bind(im_sockfd, (struct sockaddr *) &serv_addr, servlen) < 0) { ++ perror("cannot bind"); ++ exit(-1); ++ } ++ ++ listen(im_sockfd,2); ++ ++ dbg("im_sockfd:%d\n", im_sockfd); ++ ++ g_io_add_watch(g_io_channel_unix_new(im_sockfd), G_IO_IN, cb_new_hime_client, ++ GINT_TO_POINTER(Connection_type_unix)); ++ ++ Display *dpy = GDK_DISPLAY(); ++ ++ Server_sock_path srv_sockpath; ++ strcpy(srv_sockpath.sock_path, sock_path); ++ Atom sockpath_atom = get_hime_sockpath_atom(dpy); ++ XChangeProperty(dpy, prop_win , sockpath_atom, XA_STRING, 8, ++ PropModeReplace, (unsigned char *)&srv_sockpath, sizeof(srv_sockpath)); ++ ++ addr_atom = get_hime_addr_atom(dpy); ++ XSetSelectionOwner(dpy, addr_atom, win, CurrentTime); ++ ++ if (!hime_remote_client) { ++ dbg("connection via TCP is disabled\n"); ++ return; ++ } ++ ++ // tcp socket ++ if (get_ip_address(&srv_ip_port.ip) < 0) ++ return; ++ ++ if ((im_tcp_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ++ perror("cannot open tcp socket"); ++ exit(-1); ++ } ++ ++// dbg("socket succ\n"); ++ ++ struct sockaddr_in serv_addr_tcp; ++ u_short port; ++ ++ for(port=9999; port < 20000; port++) ++ { ++ // tcp socket ++ bzero(&serv_addr_tcp, sizeof(serv_addr_tcp)); ++ serv_addr_tcp.sin_family = AF_INET; ++ ++ serv_addr_tcp.sin_addr.s_addr = htonl(INADDR_ANY); ++ serv_addr_tcp.sin_port = htons(port); ++ if (bind(im_tcp_sockfd, (struct sockaddr *) &serv_addr_tcp, sizeof(serv_addr_tcp)) == 0) ++ break; ++ } ++ ++ srv_ip_port.port = serv_addr_tcp.sin_port; ++ dbg("server port bind to %s:%d\n", inet_ntoa(serv_addr_tcp.sin_addr), port); ++ time_t t; ++ srand(time(&t)); ++ ++ int i; ++ for(i=0; i < __HIME_PASSWD_N_; i++) { ++ srv_ip_port.passwd.passwd[i] = (rand()>>2) & 0xff; ++ } ++ ++ if (listen(im_tcp_sockfd, 5) < 0) { ++ perror("cannot listen: "); ++ exit(1); ++ } ++ ++ dbg("after listen\n"); ++ ++ ++ gen_passwd_idx(); ++ ++ g_io_add_watch(g_io_channel_unix_new(im_tcp_sockfd), G_IO_IN, cb_new_hime_client, ++ GINT_TO_POINTER(Connection_type_tcp)); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/im-srv.h b/src/plugins/platforminputcontexts/hime/include/im-srv.h +new file mode 100644 +index 0000000..4bd9657 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/im-srv.h +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++typedef enum { ++ Connection_type_unix = 1, ++ Connection_type_tcp = 2 ++} Connection_type; ++ ++typedef struct { ++ ClientState *cs; ++ int tag; ++ u_int seed; ++ Connection_type type; ++ int fd; ++} HIME_ENT; ++ ++extern HIME_ENT *hime_clients; ++extern int hime_clientsN; ++extern Server_IP_port srv_ip_port; +diff --git a/src/plugins/platforminputcontexts/hime/include/lang.c b/src/plugins/platforminputcontexts/hime/include/lang.c +new file mode 100644 +index 0000000..d7035e8 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/lang.c +@@ -0,0 +1,47 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "lang.h" ++ ++gboolean is_chs; ++char *tsin32_f="tsin32"; ++ ++void set_is_chs() ++{ ++ char *lc_ctype = getenv("LC_CTYPE"); ++ char *lc_all = getenv("LC_ALL"); ++ char *lang = getenv("LANG"); ++ if (!lc_ctype && lang) ++ lc_ctype = lang; ++ ++ if (lc_all) ++ lc_ctype = lc_all; ++ ++ if (!lc_ctype) ++ lc_ctype = "zh_TW.Big5"; ++ dbg("hime get env LC_CTYPE=%s LC_ALL=%s LANG=%s\n", lc_ctype, lc_all, lang); ++ ++ if (strstr(lc_ctype, "zh_CN") || 0) { ++ is_chs = TRUE; ++ } ++ ++ if (is_chs) { ++ tsin32_f = "s-tsin32"; ++ dbg("is simplified chinese\n"); ++ } ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/lang.h b/src/plugins/platforminputcontexts/hime/include/lang.h +new file mode 100644 +index 0000000..c54a2b6 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/lang.h +@@ -0,0 +1,3 @@ ++extern gboolean is_chs; ++extern char *tsin32_f; ++void set_is_chs(); +diff --git a/src/plugins/platforminputcontexts/hime/include/os-dep.h b/src/plugins/platforminputcontexts/hime/include/os-dep.h +new file mode 100644 +index 0000000..1b2fb01 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/os-dep.h +@@ -0,0 +1,18 @@ ++#ifndef OS_DEP_H ++#define OS_DEP_H ++ ++typedef char unich_t; ++void unix_exec(char *fmt,...); ++ ++#include ++#include ++#include ++ ++#include ++#if GLIB_CHECK_VERSION(2,29,8) ++#define G_CONST_RETURN const ++#endif ++ ++#include ++ ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/pho-status.h b/src/plugins/platforminputcontexts/hime/include/pho-status.h +new file mode 100644 +index 0000000..f31f8a4 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/pho-status.h +@@ -0,0 +1,7 @@ ++enum { ++ PHO_STATUS_REJECT=1, ++ PHO_STATUS_OK=2, ++ PHO_STATUS_OK_NEW=4, ++ PHO_STATUS_PINYIN_LEFT=8, ++ PHO_STATUS_TONE=16, ++}; +diff --git a/src/plugins/platforminputcontexts/hime/include/pho.c b/src/plugins/platforminputcontexts/hime/include/pho.c +new file mode 100644 +index 0000000..bcefa8c +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/pho.c +@@ -0,0 +1,869 @@ ++/* Copyright (C) 1994-2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "pho.h" ++#include ++#include ++#include "gtab.h" ++#include "gst.h" ++#include "pho-status.h" ++ ++PHO_ST poo; ++ ++extern PHO_ITEM *ch_pho; ++ ++PHOKBM phkbm; ++extern int text_pho_N; ++gboolean b_hsu_kbm; ++extern PIN_JUYIN *pin_juyin; ++int pin_juyinN; ++ ++gboolean full_char_proc(KeySym keysym); ++void hide_win_pho(); ++void ClrSelArea(); ++ ++#define MAX_HASH_PHO 27 ++u_short hash_pho[MAX_HASH_PHO+1]; ++ ++static char typ_pho_len[]={5, 2, 4, 3}; ++ ++gboolean same_query_show_pho_win(); ++ ++gboolean typ_pho_empty() ++{ ++ return !poo.typ_pho[0] &&!poo.typ_pho[1] &&!poo.typ_pho[2] &&!poo.typ_pho[3]; ++} ++ ++gboolean pho_has_input() ++{ ++ return !typ_pho_empty() || same_query_show_pho_win(); ++} ++ ++phokey_t pho2key(char typ_pho[]) ++{ ++ phokey_t key=typ_pho[0]; ++ int i; ++ ++ if (key==BACK_QUOTE_NO) ++ return (BACK_QUOTE_NO<<9) | typ_pho[1]; ++ ++ for(i=1; i < 4; i++) { ++ key = typ_pho[i] | (key << typ_pho_len[i]) ; ++ } ++ ++ return key; ++} ++ ++void key_typ_pho(phokey_t phokey, u_char rtyp_pho[]) ++{ ++ rtyp_pho[3] = phokey & 7; ++ phokey >>= 3; ++ rtyp_pho[2] = phokey & 0xf; ++ phokey >>=4; ++ rtyp_pho[1] = phokey & 0x3; ++ phokey >>=2; ++ rtyp_pho[0] = phokey; ++} ++ ++ ++void mask_key_typ_pho(phokey_t *key) ++{ ++ if (poo.typ_pho[0] == BACK_QUOTE_NO) ++ return; ++ if (!poo.typ_pho[0]) *key &= ~(31<<9); ++ if (!poo.typ_pho[1]) *key &= ~(3<<7); ++ if (!poo.typ_pho[2]) *key &= ~(15<<3); ++ if (!poo.typ_pho[3]) *key &= ~(7); ++} ++ ++#define TKBM 0 ++#define MIN_M_PHO 5 ++ ++static void find_match_phos(u_char mtyp_pho[4], int *mcount, int newkey) ++{ ++ int vv; ++ phokey_t key = pho2key(poo.typ_pho); ++ ++ mask_key_typ_pho(&key); ++#if TKBM ++ dbg("-------------------- %d --", poo.typ_pho[3]); ++ prph(key); ++ dbg("\n"); ++#endif ++ for (vv = hash_pho[(int)poo.typ_pho[0]]; vv < hash_pho[(int)poo.typ_pho[0]+1]; vv++) { ++ phokey_t ttt=idx_pho[vv].key; ++ ++ if (newkey!=' ' && !poo.typ_pho[3]) ++ mask_key_typ_pho(&ttt); ++ ++ if (ttt > key) ++ break; ++ ++ int count = 0; ++ ++ int i; ++ for(i=idx_pho[vv].start; i < idx_pho[vv+1].start; i++) { ++ if (utf8_sz(pho_idx_str(i)) > 1) { ++#if 0 ++ utf8_putchar(ch_pho[i].ch); ++ dbg(" "); ++#endif ++ count++; ++ } ++ } ++ ++ if (*mcount < count) { ++ *mcount = count; ++ memcpy(mtyp_pho, poo.typ_pho, sizeof(poo.typ_pho)); ++#if TKBM ++ dbg("count %d\n", count); ++#endif ++ if (*mcount > MIN_M_PHO) ++ break; ++ } ++ } ++} ++ ++gboolean inph_typ_pho_pinyin(int newkey); ++ ++static int typ_pho_status() ++{ ++ return poo.typ_pho[3] ? PHO_STATUS_OK_NEW:PHO_STATUS_OK; ++} ++ ++int inph_typ_pho(KeySym newkey) ++{ ++ int i; ++ int insert = -1; ++ ++ if (pin_juyin) { ++ return inph_typ_pho_pinyin(newkey); ++ } ++ ++ if (poo.typ_pho[0]==BACK_QUOTE_NO) { ++ poo.typ_pho[1]=(char)newkey; ++ poo.inph[1]=newkey; ++ return PHO_STATUS_OK; ++ } ++ ++ int max_in_idx; ++ for(max_in_idx=3; max_in_idx>=0 && !poo.typ_pho[max_in_idx]; max_in_idx--); ++ ++ // try insert mode first ++ if (insert < 0) ++ for(i=0; i < 3; i++) { ++ char num = phkbm.phokbm[(int)newkey][i].num; ++ int typ = phkbm.phokbm[(int)newkey][i].typ; ++ ++ if (num && !poo.inph[typ] && typ>max_in_idx) { ++ poo.inph[typ] = newkey; ++ poo.typ_pho[typ] = num; ++#if TKBM ++ dbg("insert typ %d\n", typ); ++#endif ++ insert = typ; ++ break; ++ } ++ } ++ ++ if (insert < 0) { ++ // then overwrite mode ++ for(i=0; i < 3; i++) { ++ char num = phkbm.phokbm[newkey][i].num; ++ int typ = phkbm.phokbm[newkey][i].typ; ++ ++ if (num) { ++ poo.inph[typ] = newkey; ++ poo.typ_pho[typ] = num; ++ insert = typ; ++ break; ++ } ++ } ++ } ++ ++// dbg("newkey %c\n", newkey); ++ ++ int mcount = 0; ++ u_char mtyp_pho[4]; ++ ++ int a; ++ ++ for(a=0; a < 3; a++) { ++ char num = phkbm.phokbm[(int)poo.inph[0]][a].num; ++ char typ = phkbm.phokbm[(int)poo.inph[0]][a].typ; ++ ++ if (typ == 3) ++ continue; ++ ++ if (num) { ++ if (typ==2 && poo.typ_pho[0] && !poo.typ_pho[2]) ++ poo.typ_pho[0] = 0; ++ poo.typ_pho[(int)typ] = num; ++#if TKBM ++ dbg("%d num %d\n",a, num); ++#endif ++ find_match_phos(mtyp_pho, &mcount, newkey); ++ } ++ ++ for(i=0; i < 3; i++) { ++ char num = phkbm.phokbm[(int)poo.inph[2]][i].num; ++ char typ = phkbm.phokbm[(int)poo.inph[2]][i].typ; ++ ++ if (!num) ++ break; ++ ++ if (typ!=2) ++ continue; ++ ++ poo.typ_pho[(int)typ] = num; ++ ++ find_match_phos(mtyp_pho, &mcount, newkey); ++ ++ if (mcount > MIN_M_PHO) { ++ return typ_pho_status(); ++ } ++ } ++ ++ ++ find_match_phos(mtyp_pho, &mcount, newkey); ++ ++ if (mcount > MIN_M_PHO) { ++ return typ_pho_status(); ++ } ++ } ++ ++ if (mcount) { ++ memcpy(poo.typ_pho, mtyp_pho, sizeof(poo.typ_pho)); ++ return typ_pho_status(); ++ } ++ ++ return PHO_STATUS_REJECT; ++} ++ ++ ++void clrin_pho() ++{ ++ bzero(poo.typ_pho,sizeof(poo.typ_pho)); ++ bzero(poo.inph,sizeof(poo.inph)); ++ poo.maxi=poo.ityp3_pho=0; ++ poo.cpg=0; ++ ++ if (hime_pop_up_win && !same_query_show_pho_win()) ++ hide_win_pho(); ++} ++ ++void disp_pho(int index, char *phochar); ++void clr_in_area_pho() ++{ ++ int i; ++ ++ clrin_pho(); ++ for(i=0; i < text_pho_N; i++) ++ disp_pho(i, " "); ++} ++ ++ ++static void disp_in_area_pho() ++{ ++ int i; ++ ++ text_pho_N = pin_juyin?7:4; ++ if (pin_juyin) { ++ for(i=0;icount - a->count; ++} ++ ++void disp_pho_sel(char *s); ++ ++static void ClrPhoSelArea() ++{ ++ disp_pho_sel(""); ++} ++ ++ ++extern char *TableDir; ++extern char phofname[128]; ++ ++gboolean get_start_stop_idx(phokey_t key, int *start_i, int *stop_i) ++{ ++ int typ_pho0 = key >> 9; ++ int vv=hash_pho[typ_pho0]; ++ ++ while (vv=key) break; ++ else ++ vv++; ++ } ++ ++ if (vv >= idxnum_pho || idx_pho[vv].key != key) ++ return FALSE; ++ ++ *start_i=idx_pho[vv].start; ++ *stop_i=idx_pho[vv+1].start; ++ ++ return TRUE; ++} ++ ++// given the pho key & the utf8 char, return the idx in ch_pho ++int ch_key_to_ch_pho_idx(phokey_t phkey, char *utf8) ++{ ++ int start_i, stop_i; ++ ++ get_start_stop_idx(phkey, &start_i, &stop_i); ++ ++ int i; ++ for(i=start_i; i> 9 == i) ++ hash_pho[i]=ttt; ++ else { ++ continue; ++ } ++ ++ while (ttt < idxnum_pho && idx_pho[ttt].key >> 9 == i) ++ ttt++; ++ } ++ ++ for(i=MAX_HASH_PHO; !hash_pho[i]; i--) ++ hash_pho[i]=idxnum_pho; ++ ++ char kbmfname[MAX_HIME_STR]; ++ FILE *fr; ++ ++ free(pin_juyin); ++ pin_juyin = NULL; ++ ++ if (!strstr(pho_kbm_name, "pinyin")) { ++ text_pho_N = 4; ++ } else { ++ load_pin_juyin(); ++ } ++ ++ if (strcmp(pho_kbm_name, "hsu")) ++ b_hsu_kbm = FALSE; ++ else ++ b_hsu_kbm = TRUE; ++ ++ char pho_kbm_name_kbm[128]; ++ ++ strcat(strcpy(pho_kbm_name_kbm, pho_kbm_name), ".kbm"); ++ dbg("phokbm_name: %s\n", pho_kbm_name_kbm); ++ ++ get_sys_table_file_name(pho_kbm_name_kbm, kbmfname); ++ ++ if ((fr=fopen(kbmfname,"rb"))==NULL) ++ p_err("Cannot open %s", kbmfname); ++ ++ dbg("kbmfname %s\n", kbmfname); ++ ++ fread(&phkbm,sizeof(phkbm),1,fr); ++ fclose (fr); ++ phkbm.selkeyN = strlen(pho_selkey); ++ ++ dbg("pho_selkey %s\n", pho_selkey); ++ ++ recreate_win1_if_nessary(); ++#if 0 ++ for(i='A'; i <= 'z'; i++) ++ dbg("%c %d %d\n", i, phkbm.phokbm[i][0].num, phkbm.phokbm[i][0].typ); ++#endif ++} ++ ++ ++void show_win_pho(); ++ ++void init_tab_pho() ++{ ++ if (!ch_pho) { ++ load_tab_pho_file(); ++ } ++ ++ show_win_pho(); ++ clr_in_area_pho(); ++} ++ ++static char *pho_idx_str_markup(int ii) ++{ ++ char *pho_str = pho_idx_str(ii); ++ if (!strcmp(pho_str, "<")) ++ pho_str = "<"; ++ else ++ if (!strcmp(pho_str, ">")) ++ pho_str = ">"; ++ return pho_str; ++} ++ ++ ++gboolean shift_char_proc(KeySym key, int kbstate); ++gboolean pre_punctuation(KeySym xkey); ++void pho_play(phokey_t key); ++void close_gtab_pho_win(); ++gboolean pre_punctuation_hsu(KeySym xkey); ++void case_inverse(KeySym *xkey, int shift_m); ++ ++int feedkey_pho(KeySym xkey, int kbstate) ++{ ++ int ctyp = 0; ++ static unsigned int vv, ii; ++ static phokey_t key; ++ char *pp=NULL; ++ char kno; ++ int i,j,jj=0,kk=0; ++ char out_buffer[512]; ++ int out_bufferN; ++ int shift_m=kbstate&ShiftMask; ++ int ctrl_m=kbstate&ControlMask; ++ ++ if (ctrl_m) ++ return 0; ++ ++ ++ if (kbstate&LockMask) { ++ if (xkey >= 0x7e || xkey < ' ') ++ return FALSE; ++ if (hime_capslock_lower) ++ case_inverse(&xkey, shift_m); ++ send_ascii(xkey); ++ return 1; ++ } ++ ++ if (xkey >= 'A' && xkey <='Z' && poo.typ_pho[0]!=BACK_QUOTE_NO) ++ xkey+=0x20; ++ ++ switch (xkey) { ++ case XK_Escape: ++ if (typ_pho_empty()) ++ return 0; ++ ClrPhoSelArea(); ++ clr_in_area_pho(); ++ if (is_gtab_query_mode()) ++ close_gtab_pho_win(); ++ return 1; ++ case XK_BackSpace: ++ poo.ityp3_pho=0; ++ for(j=3;j>=0;j--) if (poo.typ_pho[j]) { ++ poo.typ_pho[j]=0; ++ if (typ_pho_empty()) { ++ ClrSelArea(); ++ clr_in_area_pho(); ++ return 1; ++ } ++ break; ++ } ++ ++ if (j<0) ++ return 0; ++ ++ goto llll3; ++ case '<': ++ if (!poo.ityp3_pho) { ++ return pre_punctuation(xkey); ++ } ++ if (poo.cpg >= phkbm.selkeyN) ++ poo.cpg -= phkbm.selkeyN; ++ goto proc_state; ++ case ' ': ++ if (!poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2]) { ++ if (current_CS->b_half_full_char) ++ return full_char_proc(xkey); ++ return 0; ++ } ++ ++// dbg("poo.ityp3_pho %d\n", poo.ityp3_pho); ++ if (!poo.ityp3_pho) { ++ poo.ityp3_pho = TRUE; ++ goto lll1; ++ } ++ ++ ii = poo.start_idx+ poo.cpg + phkbm.selkeyN; ++ ++ if (ii < poo.stop_idx) { ++ poo.cpg += phkbm.selkeyN; ++ dbg("spc pool.cpg %d\n", poo.cpg); ++ } else { ++ if (poo.cpg) { ++ poo.cpg=0; ++ ii=poo.start_idx; ++ } else { ++ putkey_pho(key, poo.start_idx); ++ return 1; ++ } ++ } ++ ++ goto disp; ++ default: ++ if (xkey >= 127 || xkey < ' ') ++ return 0; ++ ++ if (shift_m) { ++// return shift_char_proc(xkey, kbstate); ++ if (pre_punctuation(xkey)) ++ return 1; ++ return 0; ++ } ++ ++// dbg("poo.maxi:%d %d\n", poo.maxi, poo.cpg); ++ ++ if ((pp=strchr(pho_selkey, xkey)) && poo.maxi && poo.ityp3_pho) { ++ int c=pp-pho_selkey; ++ ++ if (c=key) ++ break; ++ else ++ vv++; ++ } ++ ++// dbg("vv %d %d\n", vv, idxnum_pho); ++ ++ if (ttt > key || (poo.ityp3_pho && idx_pho[vv].key != key) ) { ++// dbg("not found\n"); ++ while (jj<4) { ++ while(kk<3) ++ if (phkbm.phokbm[(int)poo.inph[jj]][kk].num ) { ++ ++ if (kk) { ++ ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk-1].typ; ++ poo.typ_pho[ctyp]=0; ++ } ++ ++ kno=phkbm.phokbm[(int)poo.inph[jj]][kk].num; ++ ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk].typ; ++ poo.typ_pho[ctyp]=kno; ++ kk++; ++ goto llll2; ++ } ++ else ++ kk++; ++ jj++; ++ kk=1; ++ } ++ ++ bell(); ++ poo.ityp3_pho=poo.typ_pho[3]=0; ++ disp_in_area_pho(); ++ return 1; ++ } ++ ++proc_state: ++ disp_in_area_pho(); ++ poo.start_idx = ii = idx_pho[vv].start; ++ poo.stop_idx = idx_pho[vv+1].start; ++ ++// dbg("poo.start_idx: %d %d\n", poo.start_idx, poo.stop_idx); ++ ++ if (poo.typ_pho[0]==L_BRACKET_NO||poo.typ_pho[0]==R_BRACKET_NO || (poo.typ_pho[0]==BACK_QUOTE_NO && poo.typ_pho[1])) ++ poo.ityp3_pho = 1; ++ ++ ii+=poo.cpg; ++ ++ if (poo.ityp3_pho && poo.stop_idx - poo.start_idx==1) { ++ putkey_pho(key, ii); ++ poo.maxi=poo.ityp3_pho=0; ++ return 1; ++ } ++ ++disp: ++ i=0; ++ out_bufferN=0; ++ out_buffer[0]=0; ++ ++ if (poo.ityp3_pho) { ++// dbg("poo.cpg %d\n", poo.cpg); ++ ++ while(i< phkbm.selkeyN && ii < poo.stop_idx) { ++ char tt[512]; ++ sprintf(tt, "%c", ++ hime_sel_key_color, pho_selkey[i]); ++ int ttlen = strlen(tt); ++ memcpy(out_buffer+out_bufferN, tt, ttlen); ++ out_bufferN+=ttlen; ++// strcat(out_buffer, tt); ++ char *pho_str = pho_idx_str_markup(ii); ++ int len = strlen(pho_str); ++ memcpy(&out_buffer[out_bufferN], pho_str, len); ++ out_bufferN+=len; ++ out_buffer[out_bufferN++] = ' '; ++ ++ ii++; ++ i++; ++ } ++ ++ char *tt = poo.cpg ? "<" : " "; ++ int ttlen = strlen(tt); ++ memcpy(out_buffer+out_bufferN, tt, ttlen); ++ out_bufferN+=ttlen; ++ ++ if (ii < poo.stop_idx) { ++ out_buffer[out_bufferN++] = poo.cpg ? '\\' : ' '; ++ tt = ">"; ++ ttlen = strlen(tt); ++ memcpy(out_buffer+out_bufferN, tt, ttlen); ++ out_bufferN+=strlen(tt); ++ } ++ ++ poo.maxi=i; ++ } else { ++ while(i ++#include "hime.h" ++#include "pho.h" ++#include "tsin.h" ++#include "hime-conf.h" ++#include ++#include "tsin-parse.h" ++#include "gtab-buf.h" ++#include "gst.h" ++ ++#define DBG (0) ++extern gboolean tsin_is_gtab; ++extern int ph_key_sz; ++void add_cache(int start, int usecount, TSIN_PARSE *out, short match_phr_N, short no_match_ch_N, int tc_len); ++void extract_gtab_key(int start, int len, void *out); ++gboolean check_gtab_fixed_mismatch(int idx, char *mtch, int plen); ++void mask_tone(phokey_t *pho, int plen, char *tone_mask); ++ ++static int tsin_parse_len; ++ ++void set_tsin_parse_len(int len) ++{ ++ tsin_parse_len = len; ++} ++ ++static char *c_pinyin_set; ++ ++int tsin_parse_recur(int start, TSIN_PARSE *out, ++ short *r_match_phr_N, short *r_no_match_ch_N) ++{ ++ int plen; ++ double bestscore = -1; ++ int bestusecount = 0; ++ *r_match_phr_N = 0; ++ *r_no_match_ch_N = tsin_parse_len - start; ++ ++ ++ for(plen=1; start + plen <= tsin_parse_len && plen <= MAX_PHRASE_LEN; plen++) { ++#if DBG ++ dbg("---- aa st:%d hh plen:%d ", start, plen);utf8_putchar(tss.chpho[start].ch); dbg("\n"); ++#endif ++ if (plen > 1) { ++ if (tsin_is_gtab) { ++ if (gbuf[start+plen-1].flag & FLAG_CHPHO_PHRASE_USER_HEAD) ++ break; ++ } else ++ if (tss.chpho[start+plen-1].flag & FLAG_CHPHO_PHRASE_USER_HEAD) ++ break; ++ } ++ ++ phokey_t pp[MAX_PHRASE_LEN + 1]; ++ u_int pp32[MAX_PHRASE_LEN + 1]; ++ u_int64_t pp64[MAX_PHRASE_LEN + 1]; ++ int sti, edi; ++ TSIN_PARSE pbest[MAX_PH_BF_EXT+1]; ++#define MAXV 1000 ++ int maxusecount = 5-MAXV; ++ int remlen; ++ short match_phr_N=0, no_match_ch_N = plen; ++ void *ppp; ++ ++ if (ph_key_sz==2) ++ ppp=pp; ++ else if (ph_key_sz==4) ++ ppp=pp32; ++ else ++ ppp=pp64; ++ ++ bzero(pbest, sizeof(TSIN_PARSE) * tsin_parse_len); ++ ++ pbest[0].len = plen; ++ pbest[0].start = start; ++ int i, ofs; ++ ++ if (tsin_is_gtab) ++ for(ofs=i=0; i < plen; i++) ++ ofs += utf8cpy((char *)pbest[0].str + ofs, gbuf[start + i].ch); ++ else ++ for(ofs=i=0; i < plen; i++) ++ ofs += utf8cpy((char *)pbest[0].str + ofs, tss.chpho[start + i].ch); ++ ++#if DBG ++ dbg("st:%d hh plen:%d ", start, plen);utf8_putchar(tss.chpho[start].ch); dbg("\n"); ++#endif ++ ++ if (tsin_is_gtab) ++ extract_gtab_key(start, plen, ppp); ++ else { ++ extract_pho(start, plen, (phokey_t *)ppp); ++ if (c_pinyin_set) ++ mask_tone(pp, plen, c_pinyin_set + start); ++ } ++ ++#if DBG ++ for(i=0; i < plen; i++) { ++ prph(pp[i]); dbg("%d", c_pinyin_set[i+start]); ++ } ++ dbg("\n"); ++#endif ++ ++ char *pinyin_set = c_pinyin_set ? c_pinyin_set+start:NULL; ++ if (!tsin_seek(ppp, plen, &sti, &edi, pinyin_set)) { ++// dbg("tsin_seek not found...\n"); ++ if (plen > 1) ++ break; ++ goto next; ++ } ++ ++ phokey_t mtk[MAX_PHRASE_LEN]; ++ u_int mtk32[MAX_PHRASE_LEN]; ++ u_int64_t mtk64[MAX_PHRASE_LEN]; ++ void *pho; ++ ++ if (ph_key_sz==2) ++ pho=mtk; ++ else if (ph_key_sz==4) ++ pho=mtk32; ++ else ++ pho=mtk64; ++ ++ for (;sti < edi; sti++) { ++ char mtch[MAX_PHRASE_LEN*CH_SZ+1]; ++ char match_len; ++ usecount_t usecount; ++ ++ load_tsin_entry(sti, &match_len, &usecount, pho, (u_char *)mtch); ++ ++ if (match_len < plen) ++ continue; ++ ++ if (tsin_is_gtab) { ++ if (check_gtab_fixed_mismatch(start, mtch, plen)) ++ continue; ++ } else ++ if (check_fixed_mismatch(start, mtch, plen)) ++ continue; ++ ++ if (usecount < 0) ++ usecount = 0; ++ ++ int i; ++ if (ph_key_sz==2) { ++ if (c_pinyin_set) { ++// mask_tone(pp, plen, c_pinyin_set + start); ++ mask_tone(mtk, plen, c_pinyin_set + start); ++ } ++ for(i=0;i < plen;i++) ++ if (mtk[i]!=pp[i]) ++ break; ++ } else if (ph_key_sz==4) { ++ for(i=0;i < plen;i++) ++ if (mtk32[i]!=pp32[i]) ++ break; ++ } else { ++ for(i=0;i < plen;i++) ++ if (mtk64[i]!=pp64[i]) ++ break; ++ } ++ ++ if (i < plen) ++ continue; ++ ++ if (match_len > plen) { ++ continue; ++ } ++ ++ if (usecount <= maxusecount) ++ continue; ++ ++ pbest[0].len = plen; ++ maxusecount = usecount; ++ utf8cpyN((char *)pbest[0].str, mtch, plen); ++ pbest[0].flag |= FLAG_TSIN_PARSE_PHRASE; ++ ++ match_phr_N = 1; ++ no_match_ch_N = 0; ++#if DBG ++ utf8_putcharn(mtch, plen); ++ dbg(" plen %d usecount:%d ", plen, usecount); ++ utf8_putcharn(mtch, plen); ++ dbg("\n"); ++#endif ++ } ++ ++ ++next: ++ ++#if 0 ++ if (!match_phr_N) { ++ if (tsin_is_gtab) { ++ if (!(gbuf[start].ch[0] & 0x80)) ++ no_match_ch_N = 0; ++ } else ++ if (!(tss.chpho[start].ch[0] & 0x80)) ++ no_match_ch_N = 0; ++ } ++#else ++// dbg("no_match_ch_N %d\n", no_match_ch_N); ++#endif ++ ++ remlen = tsin_parse_len - (start + plen); ++ ++ ++ if (remlen) { ++ int next = start + plen; ++ CACHE *pca; ++ ++ short smatch_phr_N, sno_match_ch_N; ++ int uc; ++ ++ if ((pca = cache_lookup(next))) { ++ uc = pca->usecount; ++ smatch_phr_N = pca->match_phr_N; ++ sno_match_ch_N = pca->no_match_ch_N; ++ memcpy(&pbest[1], pca->best, (tsin_parse_len - next) * sizeof(TSIN_PARSE)); ++ } else { ++ uc = tsin_parse_recur(next, &pbest[1], &smatch_phr_N, &sno_match_ch_N); ++// dbg(" gg %d\n", smatch_phr_N); ++ add_cache(next, uc, &pbest[1], smatch_phr_N, sno_match_ch_N, tsin_parse_len); ++ } ++ ++ match_phr_N += smatch_phr_N; ++ no_match_ch_N += sno_match_ch_N; ++ maxusecount += uc; ++ } ++ ++ ++ double score = log((double)maxusecount + MAXV) / ++ (pow((double)match_phr_N, 10)+ 1.0E-6) / (pow((double)no_match_ch_N, 20) + 1.0E-6); ++ ++#if DBG ++ dbg("st:%d plen:%d zz muse:%d ma:%d noma:%d score:%.4e %.4e\n", start, plen, ++ maxusecount, match_phr_N, no_match_ch_N, score, bestscore); ++#endif ++ if (score > bestscore) { ++#if DBG ++ dbg("is best org %.4e\n", bestscore); ++#endif ++ bestscore = score; ++ memcpy(out, pbest, sizeof(TSIN_PARSE) * (tsin_parse_len - start)); ++ ++#if DBG ++ dbg(" str:%d ", start); ++ int i; ++ for(i=0; i < tsin_parse_len - start; i++) { ++ utf8_putcharn((char *)out[i].str, out[i].len); ++ } ++ dbg("\n"); ++#endif ++ ++ bestusecount = maxusecount; ++ *r_match_phr_N = match_phr_N; ++ *r_no_match_ch_N = no_match_ch_N; ++ } ++ } ++ ++ if (bestusecount < 0) ++ bestusecount = 0; ++ ++ return bestusecount; ++} ++ ++void disp_ph_sta_idx(int idx); ++ ++void free_cache(), load_tsin_db(); ++void tsin_parse() ++{ ++ TSIN_PARSE out[MAX_PH_BF_EXT+1]; ++ bzero(out, sizeof(out)); ++ ++ int i, ofsi; ++ ++ if (tss.c_len <= 1) ++ return; ++ ++ load_tsin_db(); ++ ++ set_tsin_parse_len(tss.c_len); ++ ++ init_cache(tss.c_len); ++ ++ char pinyin_set[MAX_PH_BF_EXT]; ++ c_pinyin_set = pin_juyin?pinyin_set:NULL; ++ get_chpho_pinyin_set(pinyin_set); ++ ++ short smatch_phr_N, sno_match_ch_N; ++ tsin_parse_recur(0, out, &smatch_phr_N, &sno_match_ch_N); ++ ++#if 0 ++ puts("vvvvvvvvvvvvvvvv"); ++ for(i=0; i < tss.c_len; i++) { ++ printf("%d:", out[i].len); ++ utf8_putcharn(out[i].str, out[i].len); ++ } ++ dbg("\n"); ++#endif ++ ++ for(i=0; i < tss.c_len; i++) ++ tss.chpho[i].flag &= ~(FLAG_CHPHO_PHRASE_HEAD|FLAG_CHPHO_PHRASE_BODY); ++ ++ for(ofsi=i=0; out[i].len; i++) { ++ int j, ofsj; ++ int psta = ofsi; ++ ++ if (out[i].flag & FLAG_TSIN_PARSE_PHRASE) ++ tss.chpho[ofsi].flag |= FLAG_CHPHO_PHRASE_HEAD; ++ ++ for(ofsj=j=0; j < out[i].len; j++) { ++ ofsj += utf8cpy(tss.chpho[ofsi].cha, (char *)&out[i].str[ofsj]); ++// tss.chpho[ofsi].ch = tss.chpho[ofsi].cha; ++ ++ tss.chpho[ofsi].flag |= FLAG_CHPHO_PHRASE_BODY; ++ if (out[i].flag & FLAG_TSIN_PARSE_PHRASE) ++ tss.chpho[ofsi].psta = psta; ++ ++ ofsi++; ++ } ++ } ++ ++ int ph_sta_idx = tss.ph_sta; ++ if (tss.chpho[tss.c_len-1].psta>=0 && tss.c_len - tss.chpho[tss.c_len-1].psta > 1) { ++ ph_sta_idx = tss.chpho[tss.c_len-1].psta; ++ } ++ ++#if 1 ++ disp_ph_sta_idx(ph_sta_idx); ++#endif ++ ++#if 0 ++ for(i=0;i ++ ++#include "hime.h" ++#include "pho.h" ++#include "tsin.h" ++#include "hime-conf.h" ++#include "tsin-parse.h" ++#include "win-save-phrase.h" ++#include "gst.h" ++#include "gtab.h" ++#include "pho-status.h" ++ ++extern int ph_key_sz; ++extern GtkWidget *gwin1; ++gboolean key_press_alt, key_press_ctrl; ++extern gboolean b_hsu_kbm; ++extern gboolean test_mode; ++ ++extern char *pho_chars[]; ++ ++TSIN_ST tss; ++ ++gboolean typ_pho_empty(); ++void mask_tone(phokey_t *pho, int plen, char *tone_off); ++ ++extern u_short hash_pho[]; ++extern PHOKBM phkbm; ++ ++extern int hashidx[TSIN_HASH_N]; ++// gboolean eng_ph=TRUE; // english(FALSE) <-> pho(juyin, TRUE) ++ ++void clrin_pho(), hide_win0(); ++void show_tsin_stat(); ++void save_CS_current_to_temp(); ++ ++gboolean tsin_pho_mode() ++{ ++ return current_CS && current_CS->tsin_pho_mode; ++} ++ ++void set_tsin_pho_mode0(ClientState *cs) ++{ ++ if (!cs) ++ return; ++ cs->tsin_pho_mode = 1; ++ save_CS_current_to_temp(); ++} ++ ++void set_tsin_pho_mode() ++{ ++ set_tsin_pho_mode0(current_CS); ++ show_tsin_stat(); ++} ++ ++gboolean tsin_cursor_end() ++{ ++ return tss.c_idx==tss.c_len; ++} ++ ++gboolean tsin_has_input(); ++static void clrin_pho_tsin() ++{ ++ clrin_pho(); ++ ++ if (!tsin_has_input() && hime_pop_up_win) ++ hide_win0(); ++} ++ ++gboolean pho_has_input(); ++gboolean hime_edit_display_ap_only(); ++ ++gboolean tsin_has_input() ++{ ++ gboolean v = (!hime_edit_display_ap_only() && tss.c_len) || pho_has_input(); ++// dbg("tsin_has_input %d\n", v); ++ return v; ++} ++ ++ ++void disp_char(int index, char *ch); ++ ++static void disp_char_chbuf(int idx) ++{ ++// dbg("disp_char_chbuf %d '%s' '%s'\n", idx, tss.chpho[idx].ch, tss.chpho[idx].cha); ++ disp_char(idx, tss.chpho[idx].ch); ++} ++ ++static void init_chpho_i(int i) ++{ ++// dbg("init_chpho_i %d\n", i); ++ tss.chpho[i].ch = tss.chpho[i].cha; ++ tss.chpho[i].ch[0]=' '; ++ tss.chpho[i].ch[1]=0; ++ tss.chpho[i].flag=0; ++ tss.chpho[i].psta=-1; ++} ++ ++void clr_tsin_cursor(int index); ++ ++static void clrcursor() ++{ ++ clr_tsin_cursor(tss.c_idx); ++} ++ ++void set_cursor_tsin(int index); ++ ++void drawcursor() ++{ ++ clr_tsin_cursor(tss.last_cursor_idx); ++ tss.last_cursor_idx = tss.c_idx; ++ ++ if (!tss.c_len) ++ return; ++ ++ if (tss.c_idx == tss.c_len) { ++ if (!tsin_pho_mode()) { ++ if (tss.tsin_half_full) { ++ disp_char(tss.c_idx," "); ++ set_cursor_tsin(tss.c_idx); ++ } else { ++ disp_char(tss.c_idx, " "); ++ set_cursor_tsin(tss.c_idx); ++ } ++ } ++ } ++ else { ++ set_cursor_tsin(tss.c_idx); ++ } ++} ++ ++void chpho_extract(CHPHO *chph, int len, phokey_t *pho, char *ch) ++{ ++ int i; ++ int ofs=0; ++ ch[0]=0; ++ ++ for(i=0; i < len; i++) { ++ if (pho) ++ pho[i] = chph[i].pho; ++ ++ char *str = chph[i].ch; ++ strcat(ch + ofs, str); ++ ofs+=strlen(str); ++ } ++// dbg("chpho_extract %s\n", ch); ++} ++ ++// in tsin db, # of phokey = # of character, use this to extract only the first characer ++static void chpho_extract_cha(CHPHO *chph, int len, phokey_t *pho, char *ch) ++{ ++ int i; ++ int ofs=0; ++ ++ for(i=0; i < len; i++) { ++ if (pho) ++ pho[i] = chph[i].pho; ++ ofs += u8cpy(ch + ofs, chph[i].ch); ++ } ++ ++ ch[ofs]=0; ++// dbg("chpho_extract %s\n", ch); ++} ++ ++void chpho_get_str(int idx, int len, char *ch) ++{ ++ int ofs=0, i; ++ for(i=0; i < len; i++) { ++ int u8len = u8cpy(&ch[ofs], tss.chpho[idx+i].ch); ++ ofs+=u8len; ++ } ++ ++ ch[ofs]=0; ++} ++ ++ ++void inc_pho_count(phokey_t key, int ch_idx); ++int ch_key_to_ch_pho_idx(phokey_t phkey, char *big5); ++void inc_dec_tsin_use_count(void *pho, char *ch, int prlen); ++void lookup_gtabn(char *ch, char *); ++ ++static void putbuf(int len) ++{ ++ u_char tt[CH_SZ * (MAX_PH_BF_EXT+1) + 1]; ++ int i,idx; ++ ++// dbg("putbuf:%d\n", len); ++#if 1 ++ // update phrase reference count ++ if (len >= 2) { ++ for(i=0; i < len; i++) { ++// dbg("flag %d %x\n", i, tss.chpho[i].flag); ++ if (!BITON(tss.chpho[i].flag, FLAG_CHPHO_PHRASE_HEAD)) { ++ continue; ++ } ++ ++ int j; ++ for(j=i+1; j < len; j++) ++ if (tss.chpho[j].psta != i) ++ break; ++ ++ int phrlen = j - i; ++ if (phrlen < 1) ++ continue; ++ ++ phokey_t pho[MAX_PHRASE_LEN]; ++ char ch[MAX_PHRASE_LEN * CH_SZ * 2]; ++ ++ chpho_extract(&tss.chpho[i], phrlen, pho, ch); ++ ++ inc_dec_tsin_use_count(pho, ch, phrlen); ++ } ++ } ++#endif ++ ++ for(idx=i=0;i 1) { ++ int pho_idx = ch_key_to_ch_pho_idx(tss.chpho[i].pho, tss.chpho[i].ch); ++ if (pho_idx >= 0) ++ inc_pho_count(tss.chpho[i].pho, pho_idx); ++ } ++ ++ memcpy(&tt[idx], tss.chpho[i].ch, len); ++ idx += len; ++ } ++ ++ tt[idx]=0; ++ send_text((char *)tt); ++ lookup_gtabn((char *)tt, NULL); ++} ++ ++ ++void hide_char(int index); ++ ++static void prbuf() ++{ ++ int i; ++ ++// dbg("prbuf\n"); ++ for(i=0;i MAX_PHRASE_LEN) ++ return; ++ ++ int i; ++ for(i=save_frm;i<=save_to;i++) { ++ if (tss.chpho[i].pho) ++ continue; ++ phokey_t tpho[32]; ++ tpho[0]=0; ++ ++ utf8_pho_keys(tss.chpho[i].ch, tpho); ++ ++ if (!tpho[0]) ++ return; ++ ++ tss.chpho[i].pho = tpho[0]; ++ } ++ ++ if (!save_phrase_to_db2(&tss.chpho[save_frm], len)) { ++ bell(); ++ } ++ ++ tss.ph_sta=-1; ++ move_cursor_end(); ++ return; ++} ++ ++ ++static void set_fixed(int idx, int len) ++{ ++ int i; ++ for(i=idx; i < idx+len; i++) { ++ tss.chpho[i].flag |= FLAG_CHPHO_FIXED; ++ tss.chpho[i].flag &= ~FLAG_CHPHO_PHRASE_USER_HEAD; ++ } ++} ++ ++#define PH_SHIFT_N (tsin_buffer_size - 1) ++ ++static void shift_ins() ++{ ++ int j; ++// dbg("shift_ins()\n"); ++ ++ if (!tss.c_idx && tss.c_len >= PH_SHIFT_N) { ++ tss.c_len--; ++ } ++ else ++ if (tss.c_len >= PH_SHIFT_N) { ++ int ofs; ++ ++ // set it fixed so that it will not cause partial phrase in the beginning ++ int fixedlen = tss.c_len - 10; ++ if (fixedlen <= 0) ++ fixedlen = 1; ++ set_fixed(0, fixedlen); ++ ++ ofs = 1; ++ putbuf(ofs); ++ ++ tss.ph_sta-=ofs; ++ for(j=0; j < tss.c_len - ofs; j++) { ++ tss.chpho[j] = tss.chpho[j+ofs]; ++#if 0 ++ if (!(tss.chpho[j].flag & FLAG_CHPHO_PHO_PHRASE)) ++ tss.chpho[j].ch = tss.chpho[j].cha; ++#endif ++ } ++ tss.c_idx-=ofs; ++ tss.c_len-=ofs; ++ prbuf(); ++ } ++ ++ ++ init_chpho_i(tss.c_len); ++ ++ if (tss.c_idx < tss.c_len) { ++ for(j=tss.c_len-1; j>=tss.c_idx; j--) { ++ tss.chpho[j+1] = tss.chpho[j]; ++#if 0 ++ if (!(tss.chpho[j+1].flag & FLAG_CHPHO_PHO_PHRASE)) { ++ tss.chpho[j+1].ch = tss.chpho[j+1].cha; ++// dbg("copy %d %s\n", j+1, tss.chpho[j+1].ch); ++ } ++#endif ++ } ++ } ++ ++ tss.c_len++; ++ compact_win0(); ++ ++#if 0 ++ prbuf(); ++ dbg("leave shift_ins\n"); ++#endif ++} ++ ++ ++static void put_u8_char(int pho_idx, phokey_t key, gboolean b_tone) ++{ ++ shift_ins(); ++ int is_phrase; ++ char *str = pho_idx_str2(pho_idx, &is_phrase); ++ ++ init_chpho_i(tss.c_idx); ++ ++// dbg("put_b5_char %d] %d\n", tss.c_idx, b_tone); ++ ++ if (is_phrase) { ++ dbg("is_phrase %s\n", str); ++ tss.chpho[tss.c_idx].ch = str; ++ tss.chpho[tss.c_idx].flag |= FLAG_CHPHO_PHO_PHRASE; ++ } ++ else { ++ bzero(tss.chpho[tss.c_idx].cha, sizeof(tss.chpho[0].cha)); ++ bchcpy(tss.chpho[tss.c_idx].cha, str); ++ tss.chpho[tss.c_idx].ch = tss.chpho[tss.c_idx].cha; ++// dbg("wwww %s\n",tss.chpho[tss.c_idx].ch); ++ } ++ ++ if (b_tone) ++ tss.chpho[tss.c_idx].flag |= FLAG_CHPHO_PINYIN_TONE; ++ ++ disp_char_chbuf(tss.c_idx); ++ ++ tss.chpho[tss.c_idx].pho=key; ++ tss.c_idx++; ++ ++#if 0 ++ if (tss.c_idx < tss.c_len) { ++ prbuf(); ++ } ++#endif ++} ++ ++ ++#define MAX_PHRASE_SEL_N 10 ++ ++static u_char selstr[MAX_PHRASE_SEL_N][MAX_PHRASE_LEN * CH_SZ]; ++static u_char sellen[MAX_PHRASE_SEL_N]; ++ ++static u_short phrase_count; ++static u_short pho_count; ++ ++static gboolean chpho_eq_pho(int idx, phokey_t *phos, int len) ++{ ++ int i; ++ ++ for(i=0; i < len; i++) ++ if (tss.chpho[idx+i].pho != phos[i]) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++ ++char *get_chpho_pinyin_set(char *set_arr) ++{ ++ if (!pin_juyin) ++ return NULL; ++ int i; ++ for(i=0; i < tss.c_len; i++) { ++ if (tss.chpho[i].flag & FLAG_CHPHO_PINYIN_TONE) ++ set_arr[i]=TRUE; ++ else ++ set_arr[i]=FALSE; ++ ++// dbg("pin %d] %d\n", i, set_arr[i]); ++ } ++ return set_arr; ++} ++ ++ ++static void get_sel_phrase0(int selidx, gboolean eqlen) ++{ ++ int sti,edi; ++ u_char len, mlen; ++ ++ mlen=tss.c_len-selidx; ++ ++ if (!mlen) ++ return; ++ ++ if (mlen > MAX_PHRASE_LEN) ++ mlen=MAX_PHRASE_LEN; ++ ++ phokey_t pp[MAX_PHRASE_LEN + 1]; ++ extract_pho(selidx, mlen, pp); ++ ++ char *pinyin_s = NULL; ++ char pinyin_set[MAX_PH_BF_EXT]; ++ ++ if (pin_juyin) ++ pinyin_s = get_chpho_pinyin_set(pinyin_set) + selidx; ++ ++ if (!tsin_seek(pp, 2, &sti, &edi, pinyin_s)) ++ return; ++ ++ while (sti < edi && phrase_count < phkbm.selkeyN) { ++ phokey_t stk[MAX_PHRASE_LEN]; ++ usecount_t usecount; ++ u_char stch[MAX_PHRASE_LEN * CH_SZ + 1]; ++ ++ load_tsin_entry(sti, (char *)&len, &usecount, stk, stch); ++ mask_tone(stk, mlen, pinyin_s); ++ ++ if ((eqlen && len!=mlen) || (!eqlen && len > mlen) || len==1) { ++ sti++; ++ continue; ++ } ++ ++ if (chpho_eq_pho(selidx, stk, len)) { ++ sellen[phrase_count]=len; ++ utf8cpyN((char *)selstr[phrase_count++], (char *)stch, len); ++ } ++ ++ sti++; ++ } ++} ++ ++static void get_sel_phrase_end() ++{ ++ int stidx = tss.c_idx - 5; ++ if (stidx < 0) ++ stidx = 0; ++ ++ phrase_count = 0; ++ int i; ++ for(i=stidx; i < tss.c_len - 1; i++) { ++ get_sel_phrase0(i, TRUE); ++ } ++} ++ ++static void get_sel_phrase() ++{ ++ phrase_count = 0; ++ get_sel_phrase0(tss.c_idx, FALSE); ++} ++ ++static void get_sel_pho() ++{ ++ int idx = tss.c_idx==tss.c_len?tss.c_idx-1:tss.c_idx; ++ phokey_t key = tss.chpho[idx].pho; ++ ++ if (!key) ++ return; ++ ++ char need_mask = pin_juyin && !(tss.chpho[idx].flag & FLAG_CHPHO_PINYIN_TONE); ++// dbg("need_mask %d\n", need_mask); ++ ++ int i=hash_pho[key>>9]; ++ phokey_t ttt; ++ ++ while (i=key) ++ break; ++ i++; ++ } ++ ++ if (ttt!=key) { ++ return; ++ } ++ ++ tss.startf = idx_pho[i].start; ++ int end; ++ ++ if (need_mask) { ++ while (ikey) ++ break; ++ i++; ++ } ++ end = idx_pho[i].start; ++// dbg("end %d\n", i); ++ } else ++ end = idx_pho[i+1].start; ++ ++ pho_count = end - tss.startf; ++// dbg("pho_count %d\n", pho_count); ++} ++ ++ ++void clear_sele(); ++void set_sele_text(int tN, int i, char *text, int len); ++void disp_arrow_up(), disp_arrow_down(); ++void disp_tsin_select(int index); ++ ++static void disp_current_sel_page() ++{ ++ int i; ++ ++ clear_sele(); ++ ++ for(i=0; i < phkbm.selkeyN; i++) { ++ int idx = tss.current_page + i; ++ ++ if (idx < phrase_count) { ++ int tlen = utf8_tlen((char *)selstr[i], sellen[i]); ++ set_sele_text(phrase_count + pho_count, i, (char *)selstr[i], tlen); ++ } else ++ if (idx < phrase_count + pho_count) { ++ int v = idx - phrase_count + tss.startf; ++ char *tstr = pho_idx_str(v); ++ set_sele_text(phrase_count + pho_count, i, tstr, -1); ++ } else ++ break; ++ } ++ ++ if (tss.current_page + phkbm.selkeyN < phrase_count + pho_count) { ++ disp_arrow_down(); ++ } ++ ++ if (tss.current_page > 0) ++ disp_arrow_up(); ++ ++ disp_tsin_select(tss.c_idx==tss.c_len?tss.c_idx-1:tss.c_idx); ++} ++ ++static int fetch_user_selection(int val, char **seltext, int *is_pho_phrase) ++{ ++ int idx = tss.current_page + val; ++ int len = 0; ++ ++ *is_pho_phrase = FALSE; ++ if (idx < phrase_count) { ++ len = sellen[idx]; ++ *seltext = (char *)selstr[idx]; ++ } else ++ if (idx < phrase_count + pho_count) { ++ int v = idx - phrase_count + tss.startf; ++ *seltext = pho_idx_str2(v, is_pho_phrase); ++ len = utf8_str_N(*seltext); ++ } ++ ++ return len; ++} ++ ++ ++void extract_pho(int chpho_idx, int plen, phokey_t *pho) ++{ ++ int i; ++ ++ for(i=0; i < plen; i++) { ++ pho[i] = tss.chpho[chpho_idx + i].pho; ++ } ++} ++ ++ ++gboolean check_fixed_mismatch(int chpho_idx, char *mtch, int plen) ++{ ++ int j; ++ char *p = mtch; ++ ++ for(j=0; j < plen; j++) { ++ int u8sz = utf8_sz(p); ++ if (!(tss.chpho[chpho_idx+j].flag & FLAG_CHPHO_FIXED)) ++ continue; ++ ++ if (memcmp(tss.chpho[chpho_idx+j].ch, p, u8sz)) ++ return TRUE; ++ ++ p+= u8sz; ++ } ++ ++ return FALSE; ++} ++ ++#if 0 ++static u_char scanphr(int chpho_idx, int plen, gboolean pho_incr) ++{ ++ return scanphr_e(chpho_idx, plen, pho_incr, NULL); ++} ++#endif ++ ++void hide_selections_win(); ++ ++void disp_pre_sel_page() ++{ ++ int i; ++ ++ if (!tsin_phrase_pre_select) { ++ return; ++ } ++ ++ if (!tss.pre_selN) ++ return; ++ ++ clear_sele(); ++ ++ for(i=0; i < tss.pre_selN; i++) { ++ int tlen = utf8_tlen(tss.pre_sel[i].str, tss.pre_sel[i].len); ++ ++ set_sele_text(tss.pre_selN, i, tss.pre_sel[i].str, tlen); ++ } ++ ++#if 0 ++ dbg("tss.ph_sta:%d\n", tss.ph_sta); ++#endif ++ disp_tsin_select(tss.ph_sta); ++} ++ ++static void close_selection_win() ++{ ++ hide_selections_win(); ++ tss.current_page=tss.sel_pho=tss.ctrl_pre_sel = 0; ++ tss.pre_selN = 0; ++} ++ ++void show_button_pho(gboolean bshow); ++ ++void show_win_gtab(); ++void tsin_set_eng_ch(int nmod) ++{ ++// dbg("tsin_set_eng_ch %d\n", nmod); ++ if (current_CS) { ++ current_CS->tsin_pho_mode = nmod; ++ save_CS_current_to_temp(); ++ } ++ ++ if (current_method_type()==method_type_TSIN) { ++ show_tsin_stat(); ++ drawcursor(); ++ ++ if (!tsin_pho_mode()) ++ clrin_pho_tsin(); ++ ++ show_button_pho(tsin_pho_mode()); ++ } ++ else ++ show_win_gtab(); ++ ++ show_tsin_stat(); ++} ++ ++void tsin_toggle_eng_ch() ++{ ++// dbg("tsin_toggle_eng_ch\n"); ++ compact_win0(); ++ tsin_set_eng_ch(!tsin_pho_mode()); ++} ++ ++ ++#if USE_TSIN ++void tsin_toggle_half_full() ++{ ++ tss.tsin_half_full^=1; ++ key_press_alt = FALSE; ++ drawcursor(); ++#if TRAY_ENABLED ++ disp_tray_icon(); ++#endif ++} ++#endif ++ ++ ++#if 0 ++static char ochars[]="<,>.?/:;\"'{[}]_-+=|\\~`"; ++#else ++static char ochars[]="<,>.?/:;\"'{[}]_-+=|\\"; ++#endif ++ ++void hide_pre_sel() ++{ ++ tss.pre_selN = 0; ++ hide_selections_win(); ++} ++ ++ ++static void call_tsin_parse() ++{ ++ prbuf(); ++ tsin_parse(); ++ prbuf(); ++} ++ ++void disp_ph_sta_idx(int idx) ++{ ++} ++ ++void disp_ph_sta() ++{ ++ disp_ph_sta_idx(tss.ph_sta); ++} ++ ++void ch_pho_cpy(CHPHO *pchpho, char *utf8, phokey_t *phos, int len) ++{ ++ int i; ++ ++ for(i=0; i < len; i++) { ++ int len = utf8cpy(pchpho[i].cha, utf8); ++ utf8+=len; ++ pchpho[i].pho = phos[i]; ++ pchpho[i].flag &= ~FLAG_CHPHO_PHO_PHRASE; ++ } ++} ++ ++ ++void set_chpho_ch(CHPHO *pchpho, char *utf8, int len, gboolean is_pho_phrase) ++{ ++ int i; ++ ++ for(i=0; i < len; i++) { ++ int u8len; ++ if (is_pho_phrase) { ++ pchpho[i].ch = utf8; ++ pchpho[i].flag |= FLAG_CHPHO_PHO_PHRASE; ++ } else { ++ u8len = utf8cpy(pchpho[i].cha, utf8); ++ pchpho[i].ch = pchpho[i].cha; ++ pchpho[i].flag &= ~FLAG_CHPHO_PHO_PHRASE; ++ } ++ ++ utf8+=u8len; ++ } ++} ++ ++ ++gboolean add_to_tsin_buf(char *str, phokey_t *pho, int len) ++{ ++ int i; ++ ++ if (tss.c_idx < 0 || tss.c_len + len >= MAX_PH_BF_EXT) ++ return 0; ++ ++ if (tss.c_idx < tss.c_len) { ++ for(i=tss.c_len-1; i >= tss.c_idx; i--) { ++ tss.chpho[i+len] = tss.chpho[i]; ++ } ++ } ++ ++ ch_pho_cpy(&tss.chpho[tss.c_idx], str, pho, len); ++ ++ if (tss.c_idx == tss.c_len) ++ tss.c_idx +=len; ++ ++ tss.c_len+=len; ++ ++ clrin_pho_tsin(); ++ disp_in_area_pho_tsin(); ++ ++ prbuf(); ++ ++ set_fixed(tss.c_idx, len); ++#if 1 ++ for(i=1;i < len; i++) { ++ tss.chpho[tss.c_idx+i].psta= tss.c_idx; ++ } ++#endif ++#if 0 ++ if (len > 0) ++ tss.chpho[tss.c_idx].flag |= FLAG_CHPHO_PHRASE_HEAD; ++#endif ++ drawcursor(); ++ disp_ph_sta(); ++ hide_pre_sel(); ++ tss.ph_sta=-1; ++ ++ if (hime_pop_up_win) ++ show_win0(); ++ ++ return TRUE; ++} ++ ++#if 1 ++static void set_phrase_link(int idx, int len) ++{ ++ int j; ++ ++ if (len < 1) ++ return; ++ ++ for(j=1;j < len; j++) { ++ tss.chpho[idx+j].psta=idx; ++ } ++ ++ tss.chpho[idx].flag |= FLAG_CHPHO_PHRASE_HEAD; ++} ++#endif ++ ++ ++// should be used only if it is a real phrase ++gboolean add_to_tsin_buf_phsta(char *str, phokey_t *pho, int len) ++{ ++ int idx = tss.ph_sta; ++#if 0 ++ dbg("idx:%d tss.ph_sta:%d tss.ph_sta_last:%d tss.c_idx:%d tss.c_len:%d\n", ++ idx, tss.ph_sta, tss.ph_sta_last, tss.c_idx, tss.c_len); ++#endif ++ if (idx < 0) ++ return 0; ++ ++ if (idx + len >= MAX_PH_BF_EXT) ++ flush_tsin_buffer(); ++ ++ if (tss.c_idx < tss.c_len) { ++ int avlen = tss.c_idx - tss.ph_sta; ++// dbg("avlen:%d %d\n", avlen, len); ++ if (avlen < len) { ++ int d = len - avlen; ++ ++ memmove(&tss.chpho[tss.c_idx + d], &tss.chpho[tss.c_idx], sizeof(CHPHO) * (tss.c_len - tss.c_idx)); ++ tss.c_len += d; ++ } ++ } else ++ tss.c_len = idx + len; ++ ++ ch_pho_cpy(&tss.chpho[idx], str, pho, len); ++ set_chpho_ch(&tss.chpho[idx], str, len, FALSE); ++ set_fixed(idx, len); ++ tss.chpho[idx].flag |= FLAG_CHPHO_PHRASE_USER_HEAD; ++ tss.c_idx=idx + len; ++ tss.chpho[tss.c_idx - 1].flag |= FLAG_CHPHO_PHRASE_TAIL; ++ ++ clrin_pho_tsin(); ++ disp_in_area_pho_tsin(); ++ ++ prbuf(); ++#if 1 ++ set_phrase_link(idx, len); ++#endif ++ drawcursor(); ++ disp_ph_sta(); ++ hide_pre_sel(); ++ tss.ph_sta=-1; ++ call_tsin_parse(); ++ ++ return 1; ++} ++ ++ ++void add_to_tsin_buf_str(char *str) ++{ ++ char *pp = str; ++ char *endp = pp+strlen(pp); ++ int N = 0; ++ ++ ++ while (*pp) { ++ int u8sz = utf8_sz(pp); ++ N++; ++ pp += u8sz; ++ ++ if (pp >= endp) // bad utf8 string ++ break; ++ } ++ ++ dbg("add_to_tsin_buf_str %s %d\n",str, N); ++ ++ phokey_t pho[MAX_PHRASE_LEN]; ++ bzero(pho, sizeof(pho)); ++ add_to_tsin_buf(str, pho, N); ++} ++ ++int tsin_pho_sel(int c); ++ ++int tsin_sele_by_idx(int c) ++{ ++ if (tss.sel_pho) { ++ tsin_pho_sel(c); ++ return 0; ++ } ++ ++ int len = tss.pre_sel[c].len; ++ ++#if 0 ++ dbg("eqlenN:%d %d\n", c, tss.pre_selN); ++#endif ++ ++ if (c >= tss.pre_selN) ++ return 0; ++ ++ tss.full_match = FALSE; ++ gboolean b_added = add_to_tsin_buf_phsta(tss.pre_sel[c].str, (phokey_t*)tss.pre_sel[c].phkey, len); ++ ++ return b_added; ++} ++ ++static char shift_sele[]="!@#$%^&*()asdfghjkl:zxcvbnm<>?qwertyuiop"; ++static char noshi_sele[]="1234567890asdfghjkl;zxcvbnm,./qwertyuiop"; ++int shift_key_idx(char *s, KeySym xkey) ++{ ++ if (xkey >= 0x7f) ++ return -1; ++ ++ if (isupper(xkey)) ++ xkey = xkey - 'A' + 'a'; ++ ++// dbg("pre_sel_handler aa\n"); ++ ++ char *p; ++ if (!(p=strchr(shift_sele, xkey))) ++ return -1; ++ ++ int c = p - shift_sele; ++ char noshi = noshi_sele[c]; ++ ++ if (!(p=strchr(s, noshi))) ++ return -1; ++ ++ c = p - s; ++ return c; ++} ++ ++ ++static gboolean pre_sel_handler(KeySym xkey) ++{ ++ if (!tss.pre_selN || !tsin_phrase_pre_select) ++ return FALSE; ++ ++ int c = shift_key_idx(pho_selkey, xkey); ++ if (c < 0) { ++ close_selection_win(); ++ return FALSE; ++ } ++ return tsin_sele_by_idx(c); ++} ++ ++static gboolean pre_punctuation_sub(KeySym xkey, char shift_punc[], unich_t *chars[]) ++{ ++ char *p; ++ if (xkey > 0x7e) ++ return FALSE; ++ ++ if ((p=strchr(shift_punc, xkey))) { ++ int c = p - shift_punc; ++ char *pchar = _(chars[c]); ++ ++ if (current_method_type() == method_type_PHO) { ++ char tt[CH_SZ+1]; ++ utf8cpy(tt, pchar); ++ send_text(tt); ++ } else { ++ phokey_t keys[64]; ++ keys[0]=0; ++ utf8_pho_keys(pchar, keys); ++ add_to_tsin_buf(pchar, &keys[0], 1); ++ if (hime_punc_auto_send && tsin_cursor_end()) ++ flush_tsin_buffer(); ++ } ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++gboolean pre_punctuation(KeySym xkey) ++{ ++ static char shift_punc[]="<>?:\"{}!_()"; ++ static unich_t *chars[] = { ",", "。", "?", ":", ";", "「", "」", "!", "——", "(", ")" }; ++ return pre_punctuation_sub(xkey, shift_punc, chars); ++} ++ ++static char hsu_punc[]=",./;'"; ++gboolean pre_punctuation_hsu(KeySym xkey) ++{ ++ static unich_t *chars[] = { ",", "。", "?", ";", "、" }; ++ return pre_punctuation_sub(xkey, hsu_punc, chars); ++} ++ ++ ++int inph_typ_pho(KeySym newkey); ++ ++KeySym keypad_proc(KeySym xkey) ++{ ++ if (xkey <= XK_KP_9 && xkey >= XK_KP_0) ++ xkey=xkey-XK_KP_0+'0'; ++ else { ++ switch (xkey) { ++ case XK_KP_Add: ++ xkey = '+'; ++ break; ++ case XK_KP_Subtract: ++ xkey = '-'; ++ break; ++ case XK_KP_Multiply: ++ xkey = '*'; ++ break; ++ case XK_KP_Divide: ++ xkey = '/'; ++ break; ++ case XK_KP_Decimal: ++ xkey = '.'; ++ break; ++ default: ++ return 0; ++ } ++ } ++ ++ return xkey; ++} ++ ++static int cursor_left() ++{ ++// dbg("cursor left %d %d\n", tss.c_idx, tss.c_len); ++ close_selection_win(); ++ if (tss.c_idx) { ++ clrcursor(); ++ tss.c_idx--; ++ drawcursor(); ++ return 1; ++ } ++ // Thanks to PCMan.bbs@bbs.sayya.org for the suggestion ++ return tss.c_len; ++} ++static int cursor_right() ++{ ++// dbg("cursor right %d %d\n", tss.c_idx, tss.c_len); ++ close_selection_win(); ++ if (tss.c_idx < tss.c_len) { ++ clrcursor(); ++ tss.c_idx++; ++ drawcursor(); ++ return 1; ++ } ++ ++ return tss.c_len; ++} ++ ++void tsin_scan_pre_select(gboolean b_incr); ++ ++static int cursor_backspace() ++{ ++ close_selection_win(); ++ poo.ityp3_pho=0; ++ tss.pre_selN = 0; ++ gboolean pho_cleared; ++ pho_cleared=FALSE; ++ int j; ++ ++ if (pin_juyin) { ++ for(j=sizeof(poo.inph)-1;j>=0;j--) { ++ if (poo.inph[j]) { ++ poo.inph[j]=0; ++ pho_cleared = TRUE; ++ if (j==0) ++ clrin_pho(); ++ break; ++ } ++ } ++ } else { ++ for(j=3;j>=0;j--) ++ if (poo.typ_pho[j]) { ++ poo.typ_pho[j]=0; ++ poo.inph[j]=0; ++ pho_cleared = TRUE; ++ break; ++ } ++ } ++ ++ if (pho_cleared) { ++// dbg("pho cleared %d %d %d\n",tss.c_len, hime_pop_up_win, typ_pho_empty()); ++ if (typ_pho_empty()) ++ bzero(poo.inph, sizeof(poo.inph)); ++ ++ disp_in_area_pho_tsin(); ++ tsin_scan_pre_select(TRUE); ++ ++ if (!tss.c_len && hime_pop_up_win && typ_pho_empty()) ++ hide_win0(); ++ return 1; ++ } ++ ++ if (!tss.c_idx) ++ return 0; ++ ++ clrcursor(); ++ tss.c_idx--; ++// pst=k=tss.chpho[tss.c_idx].psta; ++ ++ int k; ++ for(k=tss.c_idx;k=tss.c_len) ++ return FALSE; ++ tss.c_idx++; ++ return cursor_backspace(); ++} ++ ++void case_inverse(KeySym *xkey, int shift_m); ++void pho_play(phokey_t key); ++ ++int tsin_pho_sel(int c) ++{ ++ char *sel_text; ++ int is_pho_phrase; ++ int len = fetch_user_selection(c, &sel_text, &is_pho_phrase); ++ int sel_idx = tss.c_idx; ++ if (tss.c_idx == tss.c_len) ++ sel_idx = tss.c_len - len; ++ ++ set_chpho_ch(&tss.chpho[sel_idx], sel_text, len, is_pho_phrase); ++ ++ set_fixed(sel_idx, len); ++ ++ call_tsin_parse(); ++ ++ if (tss.c_idx + len == tss.c_len) { ++ tss.ph_sta = -1; ++// draw_ul(tss.c_idx, tss.c_len); ++ } ++ ++ if (len) { ++ prbuf(); ++ tss.current_page=tss.sel_pho=poo.ityp3_pho=0; ++ if (len == 1) { ++ hide_selections_win(); ++ tss.ph_sta = -1; ++ return 0; ++ } ++ else ++ tss.ph_sta=-1; ++ ++ hide_selections_win(); ++ } ++ ++ return 1; ++} ++ ++ ++gboolean tsin_page_up() ++{ ++ if (!tss.sel_pho) ++ return tss.c_len; ++ ++ tss.current_page = tss.current_page - phkbm.selkeyN; ++ if (tss.current_page < 0) ++ tss.current_page = 0; ++ ++ tss.pho_menu_idx = 0; ++ disp_current_sel_page(); ++ return TRUE; ++} ++ ++gboolean tsin_page_down() ++{ ++ if (!tss.sel_pho) ++ return tss.c_len; ++ ++ tss.pho_menu_idx = 0; ++ tss.current_page = tss.current_page + phkbm.selkeyN; ++ if (tss.current_page >= phrase_count + pho_count) ++ tss.current_page = 0; ++ ++ disp_current_sel_page(); ++ ++ return TRUE; ++} ++ ++void open_select_pho() ++{ ++ if (tss.c_idx==tss.c_len) { ++ get_sel_phrase_end(); ++ } else ++ get_sel_phrase(); ++ ++ get_sel_pho(); ++ tss.sel_pho=1; ++ tss.pho_menu_idx = tss.current_page = 0; ++ disp_current_sel_page(); ++} ++ ++gboolean win_sym_page_up(), win_sym_page_down(); ++ ++static void tsin_create_win_save_phrase(int idx0, int len) ++{ ++ WSP_S wsp[MAX_PHRASE_LEN]; ++ int i; ++ for(i=0;itsin_pho_mode != new_tsin_pho_mode) { ++ close_selection_win(); ++ tsin_set_eng_ch(new_tsin_pho_mode); ++ } ++ } ++ ++ if (kbstate & (Mod1Mask|Mod4Mask|Mod5Mask)) { ++// dbg("ret\n"); ++ return 0; ++ } ++ ++ // Shift has autorepeat on win32 ++ if ((xkey==XK_Shift_L||xkey==XK_Shift_R) && !key_press_alt) { ++// dbg("feedkey_pp\n"); ++ key_press_alt = TRUE; ++ key_press_ctrl = FALSE; ++ } else ++ if ((xkey==XK_Control_L||xkey==XK_Control_R) && !key_press_ctrl && tss.pre_selN) { ++// dbg("feedkey_pp\n"); ++ key_press_ctrl = TRUE; ++ key_press_alt = FALSE; ++ return TRUE; ++ } else { ++ key_press_alt = FALSE; ++ key_press_ctrl = FALSE; ++ } ++ ++ if (!tsin_pho_mode() && !tss.c_len && hime_pop_up_win && xkey!=XK_Caps_Lock) { ++ hide_win0(); ++ gboolean is_ascii = (xkey>=' ' && xkey<0x7f) && !ctrl_m; ++ ++ if (caps_eng_tog && is_ascii) { ++ if (hime_capslock_lower) ++ case_inverse(&xkey, shift_m); ++ send_ascii(xkey); ++ return 1; ++ } ++ else { ++ if (tss.tsin_half_full && is_ascii) { ++ send_text(half_char_to_full_char(xkey)); ++ return 1; ++ } ++ else { ++ return 0; ++ } ++ } ++ } ++ ++ int o_sel_pho = tss.sel_pho; ++ close_win_pho_near(); ++ ++ switch (xkey) { ++ case XK_Escape: ++ tsin_reset_in_pho0(); ++ if (typ_pho_empty()) { ++ if (!tss.c_len) ++ return 0; ++ if (!o_sel_pho && tsin_tab_phrase_end) { ++ goto tab_phrase_end; ++ } ++ } ++ tsin_reset_in_pho(); ++ return 1; ++ case XK_Return: ++ case XK_KP_Enter: ++ if (shift_m) { ++ if (!tss.c_len) ++ return 0; ++ int idx0 = tss.c_idx; ++ if (tss.c_len == tss.c_idx) ++ idx0 = 0; ++ int len = tss.c_len - idx0; ++ if (len > MAX_PHRASE_LEN) ++ return 0; ++ tsin_create_win_save_phrase(idx0, len); ++ move_cursor_end(); ++ return 1; ++ } else { ++ if (tss.sel_pho) { ++ tsin_sele_by_idx(tss.pho_menu_idx); ++ } else { ++ if (tss.c_len) ++ flush_tsin_buffer(); ++ else ++ if (typ_pho_empty()) ++ return 0; ++ } ++ return 1; ++ } ++ case XK_Home: ++ case XK_KP_Home: ++ close_selection_win(); ++ if (!tss.c_len) ++ return 0; ++ clrcursor(); ++ tss.c_idx=0; ++ drawcursor(); ++ return 1; ++ case XK_End: ++ case XK_KP_End: ++ close_selection_win(); ++ if (!tss.c_len) ++ return 0; ++ move_cursor_end(); ++ return 1; ++ case XK_Left: ++ case XK_KP_Left: ++ return cursor_left(); ++ case XK_Right: ++ case XK_KP_Right: ++ return cursor_right(); ++ case XK_Caps_Lock: ++ if (caps_eng_tog) { ++#if 0 ++ close_selection_win(); ++ tsin_toggle_eng_ch(); ++#endif ++ return 1; ++ } else ++ return 0; ++ case XK_Tab: ++ close_selection_win(); ++ if (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Tab) { ++ tsin_toggle_eng_ch(); ++ return 1; ++ } ++ ++ if (tsin_tab_phrase_end && tss.c_len > 1) { ++tab_phrase_end: ++ if (tss.c_idx==tss.c_len) ++ tss.chpho[tss.c_idx-1].flag |= FLAG_CHPHO_PHRASE_USER_HEAD; ++ else ++ tss.chpho[tss.c_idx].flag |= FLAG_CHPHO_PHRASE_USER_HEAD; ++ call_tsin_parse(); ++ return 1; ++ } else { ++ if (tss.c_len) { ++ flush_tsin_buffer(); ++ return 1; ++ } ++ } ++ return 0; ++ case XK_Delete: ++ case XK_KP_Delete: ++ return cursor_delete(); ++ case XK_BackSpace: ++ return cursor_backspace(); ++ case XK_Up: ++ case XK_KP_Up: ++ if (!tss.sel_pho) { ++ if (tsin_use_pho_near && tss.c_len && tss.c_idx == tss.c_len) { ++ int idx = tss.c_len-1; ++ phokey_t pk = tss.chpho[idx].pho; ++ ++ if (pk) { ++ void create_win_pho_near(phokey_t pho); ++ create_win_pho_near(pk); ++ } ++ ++ return 1; ++ } ++ ++ return tss.c_len>0; ++ } ++ ++ int N; ++ N = phrase_count + pho_count - tss.current_page; ++ if (N > phkbm.selkeyN) ++ N = phkbm.selkeyN; ++ if (tss.pho_menu_idx == 0) ++ tsin_page_up(); ++ else { ++ tss.pho_menu_idx--; ++ if (tss.pho_menu_idx < 0) ++ tss.pho_menu_idx = N-1; ++ disp_current_sel_page(); ++ } ++ return 1; ++ case XK_Prior: ++ case XK_KP_Prior: ++ case XK_KP_Subtract: ++ if (!tss.sel_pho && tss.c_len && xkey == XK_KP_Subtract) { ++ add_to_tsin_buf_str("-"); ++ return TRUE; ++ } else { ++ if (tss.c_len && !tss.sel_pho) ++ return win_sym_page_up(); ++ if (tsin_page_up()) ++ return TRUE; ++ return win_sym_page_up(); ++ } ++ case XK_space: ++ if (!tss.c_len && !poo.ityp3_pho && !poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2] ++ && tss.tsin_half_full) { ++ send_text(" "); /* Full width space */ ++ return 1; ++ } ++ ++ if (tsin_space_opt == TSIN_SPACE_OPT_INPUT && !poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2] && !poo.ityp3_pho && !tss.sel_pho) { ++ if (tss.c_len) ++ flush_tsin_buffer(); ++ ++ close_selection_win(); ++ goto asc_char; ++ } ++ ++ if (!tsin_pho_mode()) ++ goto asc_char; ++ case XK_Down: ++ case XK_KP_Down: ++ if (xkey==XK_space && !poo.ityp3_pho && (poo.typ_pho[0]||poo.typ_pho[1]||poo.typ_pho[2])) { ++ kno=0; ++#if 1 ++ ctyp=3; ++// status = inph_typ_pho(xkey); ++#endif ++ goto llll1; ++ } ++ ++change_char: ++ if (!tss.c_len) ++ return 0; ++ ++ idx = tss.c_idx==tss.c_len ? tss.c_idx - 1 : tss.c_idx; ++ if (!tss.chpho[idx].pho) ++ return 1; ++ ++ if (!tss.sel_pho) { ++ open_select_pho(); ++ } else { ++ int N = phrase_count + pho_count - tss.current_page; ++ if (N > phkbm.selkeyN) ++ N = phkbm.selkeyN; ++ if (tss.pho_menu_idx == N-1 || xkey == XK_space) ++ tsin_page_down(); ++ else { ++ tss.pho_menu_idx = (tss.pho_menu_idx+1) % N; ++ disp_current_sel_page(); ++ } ++ } ++ return 1; ++ case XK_Next: ++ case XK_KP_Next: ++ case XK_KP_Add: ++ if (!tss.sel_pho && tss.c_len && xkey == XK_KP_Add) { ++ add_to_tsin_buf_str("+"); ++ return TRUE; ++ } else { ++ if (tss.c_len && !tss.sel_pho) ++ return win_sym_page_down(); ++ if (tsin_page_down()) ++ return TRUE; ++ return win_sym_page_down(); ++ } ++ case '\'': // single quote ++ if (phkbm.phokbm[xkey][0].num && !pin_juyin) ++ goto other_keys; ++ else { ++ return pre_punctuation_hsu(xkey); ++ } ++ case 'q': ++ case 'Q': ++ if (b_hsu_kbm && tsin_pho_mode()) ++ goto change_char; ++ default: ++other_keys: ++ if ((kbstate & ControlMask)) { ++ if (xkey=='u') { ++ if (tss.c_len) { ++ clear_tsin_buffer(); ++ if (hime_pop_up_win) ++ hide_win0(); ++ return 1; ++ } else ++ return 0; ++ } else if (tsin_buffer_editing_mode && xkey == 'e') { //ctrl+e only works when user enabled tsin_buffer_editing_mode ++ //toggler ++ tss.tsin_buffer_editing ^= 1; ++ return 1; ++ } else if (xkey>='1' && xkey<='9') { ++ if (!tss.c_len) ++ return 0; ++ if (!tss.c_idx) ++ return 1; ++ ++ int len = xkey - '0'; ++ int idx0 = tss.c_idx - len; ++ ++ if (idx0 < 0) ++ return 1; ++ ++ tsin_create_win_save_phrase(idx0, len); ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++ ++ char xkey_lcase = xkey; ++ if ('A' <= xkey && xkey <= 'Z') { ++ xkey_lcase = tolower(xkey); ++ } ++ ++ ++ if (tsin_buffer_editing_mode && xkey == '\\') { ++ tss.tsin_buffer_editing ^= 1; ++ if (tss.tsin_buffer_editing && tss.c_idx==tss.c_len) ++ cursor_left(); ++ return TRUE; ++ } ++ ++ if (!tss.c_len) ++ tss.tsin_buffer_editing = FALSE; ++ ++ if (tss.tsin_buffer_editing && !tss.sel_pho) { ++ if (xkey_lcase=='h' || xkey_lcase=='j') ++ return cursor_left(); ++ else ++ if (xkey_lcase=='l' || xkey_lcase=='k') ++ return cursor_right(); ++ else ++ if (xkey_lcase=='x') ++ return cursor_delete(); ++ else ++ return TRUE; ++ } ++ ++ if (xkey >= XK_KP_0 && xkey<=XK_KP_9) ++ xkey_lcase = xkey - XK_KP_0 + '0'; ++ ++ gboolean use_pre_sel; ++ use_pre_sel = tss.pre_selN && !tss.sel_pho && xkey < 127 && !phkbm.phokbm[xkey][0].num; ++ ++ char *pp; ++ if ((pp=strchr(pho_selkey,xkey_lcase)) && (tss.sel_pho || tss.ctrl_pre_sel || use_pre_sel)) { ++ int c=pp-pho_selkey; ++ ++ if (tss.sel_pho) { ++ if (tsin_pho_sel(c)) ++ return 1; ++ } else ++ if (tss.ctrl_pre_sel || use_pre_sel) { ++ tss.ctrl_pre_sel = FALSE; ++ if (tsin_sele_by_idx(c)) ++ return TRUE; ++ else { ++ close_selection_win(); ++ } ++ } ++ ++ goto scan_it; ++ } ++ ++ tss.sel_pho=tss.current_page=0; ++ } ++ ++ KeySym key_pad; ++ key_pad = keypad_proc(xkey); ++ ++ if (!xkey || (xkey > 0x7e && !key_pad)) ++ return 0; ++ ++ if (key_pad && !tss.c_len && !tss.tsin_half_full) ++ return 0; ++ ++ if (!tsin_pho_mode() || (poo.typ_pho[0]!=BACK_QUOTE_NO && (shift_m || key_pad || ++ (!phkbm.phokbm[xkey][0].num && !phkbm.phokbm[xkey][0].typ)))) { ++ if (tsin_pho_mode() && !shift_m && strchr(hsu_punc, xkey) && !phkbm.phokbm[xkey][0].num) { ++ if (pre_punctuation_hsu(xkey)) ++ return 1; ++ } ++ ++ if (key_pad) ++ xkey = key_pad; ++asc_char: ++ if (shift_m) { ++ if (pre_sel_handler(xkey)) { ++ call_tsin_parse(); ++ return 1; ++ } ++ ++ if (tsin_pho_mode() && pre_punctuation(xkey)) ++ return 1; ++ } ++ ++ if (shift_m && tsin_pho_mode()) { ++ char *ppp=strchr(ochars,xkey); ++ ++ if (!(kbstate&LockMask) && ppp && !((ppp-ochars) & 1)) ++ xkey=*(ppp+1); ++ ++ } else { ++ if (!tsin_pho_mode() && caps_eng_tog && hime_capslock_lower) { ++ case_inverse(&xkey, shift_m); ++ } ++ } ++ ++ if (xkey > 127) ++ return 0; ++ char tstr[CH_SZ + 1]; ++ bzero(tstr, sizeof(tstr)); ++ ++ u_char tt=xkey; ++ ++ if (tss.tsin_half_full) { ++ strcpy(tstr, half_char_to_full_char(xkey)); ++ } else { ++ tstr[0] = tt; ++ } ++ ++ if (!tss.c_len) { ++ send_text(tstr); ++ return 1; ++ } ++ ++ shift_ins(); ++ ++ memcpy(tss.chpho[tss.c_idx].ch, tstr, CH_SZ); ++ ++ set_fixed(tss.c_idx, 1); ++ phokey_t tphokeys[32]; ++ tphokeys[0]=0; ++ utf8_pho_keys(tss.chpho[tss.c_idx].ch, tphokeys); ++ ++ disp_char_chbuf(tss.c_idx); ++ tss.chpho[tss.c_idx].pho=tphokeys[0]; ++ tss.c_idx++; ++ if (tss.c_idx < tss.c_len) ++ prbuf(); ++ ++ if (hime_pop_up_win) ++ show_win0(); ++ ++ drawcursor(); ++ return 1; ++ } ++ ++ ++ if (xkey > 127) { ++ return 0; ++ } ++ ++ // for hsu & et26 ++ if (xkey >= 'A' && xkey <='Z' && poo.typ_pho[0]!=BACK_QUOTE_NO) ++ xkey+=0x20; ++// printf("bbbb %c\n", xkey); ++ ++llll1: ++ status = inph_typ_pho(xkey); ++ if (hime_pop_up_win) ++ show_win0(); ++ ++ if (poo.typ_pho[3] || (status&PHO_STATUS_OK_NEW)) ++ ctyp = 3; ++ ++// dbg("status %d %d\n", status, ctyp); ++ jj=0; ++ kk=1; ++llll2: ++ if (ctyp==3) { ++ poo.ityp3_pho=1; /* last key is entered */ ++ ++ if (!tsin_tone_char_input && !poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2]) { ++ clrin_pho_tsin(); ++ dbg("no pho input\n"); ++ return TRUE; ++ } ++ } ++ ++ disp_in_area_pho_tsin(); ++ ++ key = pho2key(poo.typ_pho); ++ ++ pho_play(key); ++ ++ int vv=hash_pho[(int)poo.typ_pho[0]]; ++ ++ phokey_t ttt=0xffff; ++ while (vv=key) break; ++ else ++ vv++; ++ } ++#if 0 ++ printf("aaaa vv:%d idxnum_pho:%d ttt:%x key:%x\n",vv, idxnum_pho, ttt, key); ++#endif ++ if (!pin_juyin && (ttt > key || (poo.ityp3_pho && idx_pho[vv].key!=key))) { ++ while (jj<4) { ++ while(kk<3) ++ if (phkbm.phokbm[(int)poo.inph[jj]][kk].num ) { ++ if (kk) { ++ ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk-1].typ; ++ poo.typ_pho[(int)ctyp]=0; ++ } ++ kno=phkbm.phokbm[(int)poo.inph[jj]][kk].num; ++ ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk].typ; ++ poo.typ_pho[(int)ctyp]=kno; ++ kk++; ++ goto llll2; ++ } else kk++; ++ jj++; ++ kk=1; ++ } ++ ++ bell(); poo.ityp3_pho=poo.typ_pho[3]=0; ++ disp_in_area_pho_tsin(); ++// dbg("not found ...\n"); ++ return 1; ++ } ++ ++ if (poo.typ_pho[0]==L_BRACKET_NO||poo.typ_pho[0]==R_BRACKET_NO || (poo.typ_pho[0]==BACK_QUOTE_NO && poo.typ_pho[1])) ++ poo.ityp3_pho = 1; ++ ++ if (key==0 || !poo.ityp3_pho) { ++ if (key) ++ tsin_scan_pre_select(TRUE); ++// dbg("ret a\n"); ++ return 1; ++ } ++ ++ ii=idx_pho[vv].start; ++ poo.start_idx=ii; ++ poo.stop_idx = idx_pho[vv+1].start; ++#if 0 ++ printf("%x %x %d vv:%d idxnum_pho:%d-->", ttt, key, poo.start_idx, vv, idxnum_pho); ++ utf8_putchar(pho_idx_str(poo.start_idx)); ++ puts("<---"); ++#endif ++ ++ if (!tss.c_len && poo.typ_pho[0]==BACK_QUOTE_NO && poo.stop_idx - poo.start_idx == 1) ++ send_text(pho_idx_str(poo.start_idx)); // it's ok since ,. are 3 byte, last one \0 ++ else ++ put_u8_char(poo.start_idx, key, (status&PHO_STATUS_TONE)>0); ++ ++ call_tsin_parse(); ++ ++ disp_ph_sta(); ++ if (status & PHO_STATUS_PINYIN_LEFT) { ++ poo.ityp3_pho=0; ++ disp_in_area_pho_tsin(); ++ } else { ++ clrin_pho_tsin(); ++ clr_in_area_pho_tsin(); ++ } ++ drawcursor(); ++ hide_pre_sel(); ++ ++scan_it: ++ tsin_scan_pre_select(FALSE); ++ ++ return 1; ++} ++ ++ ++int feedkey_pp_release(KeySym xkey, int kbstate) ++{ ++ switch (xkey) { ++ case XK_Shift_L: ++ case XK_Shift_R: ++// dbg("release xkey %x\n", xkey); ++ if (((tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift) || ++ (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL && xkey == XK_Shift_L) || ++ (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR && xkey == XK_Shift_R)) && ++ key_press_alt) { ++ if (!test_mode) { ++ close_selection_win(); ++ tsin_toggle_eng_ch(); ++ } ++ key_press_alt = FALSE; ++ return 1; ++ } else ++ return 0; ++ case XK_Control_L: ++ case XK_Control_R: ++ if (key_press_ctrl && tss.pre_selN) { ++ if (!test_mode) ++ tss.ctrl_pre_sel = TRUE; ++ key_press_ctrl = FALSE; ++ return 1; ++ } else ++ return 0; ++ default: ++ return 0; ++ } ++} ++ ++ ++void tsin_remove_last() ++{ ++ if (!tss.c_len) ++ return; ++ tss.c_len--; ++ tss.c_idx--; ++} ++ ++ ++gboolean save_phrase_to_db2(CHPHO *chph, int len) ++{ ++ phokey_t pho[MAX_PHRASE_LEN]; ++ char ch[MAX_PHRASE_LEN * CH_SZ * 2]; ++ ++ chpho_extract_cha(chph, len, pho, ch); ++ ++ return save_phrase_to_db(pho, ch, len, 1); ++} ++ ++#include "im-client/hime-im-client-attr.h" ++ ++ ++int tsin_get_preedit(char *str, HIME_PREEDIT_ATTR attr[], int *cursor, int *comp_flag) ++{ ++ int i; ++ int tn=0; ++ int attrN=0; ++#if DEBUG && 0 ++ dbg("tsin_get_preedit\n"); ++#endif ++ ++ gboolean ap_only = hime_edit_display_ap_only(); ++ ++ for(i=0; i=HIME_PREEDIT_MAX_STR-4*CH_SZ-1) ++ goto fin; ++ if (i==tss.c_idx && hime_display_on_the_spot_key()) { ++ tn += get_in_area_pho_tsin_str(str+tn); ++ } ++ ++ strcpy(str+tn, tss.chpho[i].ch); ++ tn+=strlen(tss.chpho[i].ch); ++ } ++ ++fin: ++ str[tn]=0; ++ ++ if (i==tss.c_idx && hime_display_on_the_spot_key()) ++ get_in_area_pho_tsin_str(str+tn); ++ ++#if DEBUG && 0 ++ dbg("'%s'\n", str); ++#endif ++ if (tss.c_len) { ++ attr[0].flag=HIME_PREEDIT_ATTR_FLAG_UNDERLINE; ++ attr[0].ofs0=0; ++ attr[0].ofs1=tss.c_len; ++ attrN++; ++ ++ ++ // for firefox 4 ++ if (ap_only && tss.c_idx < tss.c_len) { ++ attr[1].ofs0=tss.c_idx; ++ attr[1].ofs1=tss.c_idx+1; ++ attr[1].flag=HIME_PREEDIT_ATTR_FLAG_REVERSE; ++ attrN++; ++ } ++ } ++ ++ *cursor = tss.c_idx; ++ *comp_flag = !typ_pho_empty(); ++ if (gwin1 && GTK_WIDGET_VISIBLE(gwin1)) ++ *comp_flag|=2; ++#if 1 ++ if (tss.c_len && !ap_only) ++ *comp_flag|=4; ++#endif ++ ++ return attrN; ++} ++ ++int tsin_reset() ++{ ++// dbg("tsin_reset\n"); ++ if (!gwin0) ++ return 0; ++ int v = tss.c_len > 0; ++ tsin_reset_in_pho0(); ++ clear_tsin_buffer(); ++ ++ return v; ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/tsin.h b/src/plugins/platforminputcontexts/hime/include/tsin.h +new file mode 100644 +index 0000000..0055e42 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/tsin.h +@@ -0,0 +1,68 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++extern int phcount; ++extern int hashidx[]; ++//extern int *phidx; ++//extern FILE *fph; ++ ++typedef struct CHPHO { ++ char *ch; ++ char cha[CH_SZ+1]; ++ phokey_t pho; ++ u_short flag; ++ char psta; // phrase start index ++} CHPHO; ++ ++enum { ++ FLAG_CHPHO_FIXED=1, // user selected the char, so it should not be changed ++ FLAG_CHPHO_PHRASE_HEAD=2, ++ FLAG_CHPHO_PHRASE_USER_HEAD=4, ++ FLAG_CHPHO_PHRASE_VOID=8, ++ FLAG_CHPHO_PHRASE_BODY=16, ++ FLAG_CHPHO_PHO_PHRASE=32, ++ FLAG_CHPHO_PINYIN_TONE=64, ++ FLAG_CHPHO_GTAB_BUF_EN_NO_SPC=128, ++ FLAG_CHPHO_PHRASE_TAIL=0x100, ++}; ++ ++void extract_pho(int chpho_idx, int plen, phokey_t *pho); ++gboolean tsin_seek(void *pho, int plen, int *r_sti, int *r_edi, char *tone_off); ++void load_tsin_entry(int idx, char *len, usecount_t *usecount, void *pho, u_char *ch); ++gboolean check_fixed_mismatch(int chpho_idx, char *mtch, int plen); ++gboolean tsin_pho_mode(); ++char *get_chpho_pinyin_set(char *set_arr); ++ ++#define TSIN_GTAB_KEY "!!!!gtab-keys" ++ ++typedef struct { ++ char signature[32]; ++ int version, flag; ++ int keybits, maxkey; ++ char keymap[128]; ++} TSIN_GTAB_HEAD; ++ ++typedef struct PRE_SEL { ++ u_int64_t phkey[MAX_PHRASE_LEN]; // gtab 4-byte is actually stored as u_int not u_int64_t ++// int phidx; ++ char str[MAX_PHRASE_LEN*CH_SZ+1]; ++ int len; ++ usecount_t usecount; ++} PRE_SEL; ++ ++extern gboolean tsin_is_gtab; ++extern int ph_key_sz; +diff --git a/src/plugins/platforminputcontexts/hime/include/util.c b/src/plugins/platforminputcontexts/hime/include/util.c +new file mode 100644 +index 0000000..0d81b1b +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/util.c +@@ -0,0 +1,150 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include ++ ++#if !CLIENT_LIB && DEBUG ++static FILE *out_fp; ++#endif ++ ++void p_err(char *fmt,...) ++{ ++ va_list args; ++ char out[4096]; ++ ++ va_start(args, fmt); ++ vsprintf(out, fmt, args); ++ va_end(args); ++ ++ fprintf(stderr, "%s\n", out); ++ ++#if DEBUG && 1 ++ abort(); ++#else ++ if (getenv("HIME_ERR_COREDUMP")) ++ abort(); ++ exit(-1); ++#endif ++} ++ ++#if !CLIENT_LIB && DEBUG ++static void init_out_fp() ++{ ++ if (!out_fp) { ++ if (getenv("HIME_DBG_TMP") || 0) { ++ char fname[64]; ++ sprintf(fname, "%s/himedbg-%d-%d", g_get_tmp_dir(), getuid(), getpid()); ++ out_fp = fopen(fname, "w"); ++ } ++ ++ if (!out_fp) ++ out_fp = stdout; ++ } ++} ++#endif ++ ++#if !CLIENT_LIB ++void dbg_time(char *fmt,...) ++{ ++#if DEBUG ++ va_list args; ++ time_t t; ++ ++ init_out_fp(); ++ ++ time(&t); ++ struct tm *ltime = localtime(&t); ++ dbg("%02d:%02d:%02d ", ltime->tm_hour, ltime->tm_min, ltime->tm_sec); ++ ++ va_start(args, fmt); ++ vfprintf(out_fp, fmt, args); ++ fflush(out_fp); ++ va_end(args); ++#endif ++} ++#endif ++ ++#if DEBUG ++void __hime_dbg_(char *fmt,...) ++{ ++ va_list args; ++ ++ init_out_fp(); ++ ++ va_start(args, fmt); ++ vfprintf(out_fp, fmt, args); ++ fflush(out_fp); ++ va_end(args); ++} ++#endif ++ ++char *sys_err_strA() ++{ ++ return (char *)strerror(errno); ++} ++ ++void *zmalloc(int n) ++{ ++ void *p = malloc(n); ++ bzero(p, n); ++ return p; ++} ++#if !HIME_IME ++ ++void *memdup(void *p, int n) ++{ ++ if (!p || !n) ++ return NULL; ++ void *q; ++ q = malloc(n); ++ memcpy(q, p, n); ++ return q; ++} ++ ++// can handle eol with \n \r \n\r \r\n ++char *myfgets(char *buf, int bufN, FILE *fp) ++{ ++ char *out = buf; ++// int rN = 0; ++ while (!feof(fp) && out - buf < bufN) { ++ char a, b; ++ a = 0; ++ if (fread(&a, 1, 1, fp) != 1) ++ break; ++ if (a =='\n') { ++ b = 0; ++ if (fread(&b, 1, 1, fp)==1) ++ if (b!='\r') ++ fseek(fp, -1, SEEK_CUR); ++ break; ++ } else ++ if (a =='\r') { ++ b = 0; ++ if (fread(&b, 1, 1, fp)==1) ++ if (b!='\n') ++ fseek(fp, -1, SEEK_CUR); ++ break; ++ } ++ ++ *(out++) = a; ++ } ++ ++ *out = 0; ++ return buf; ++} ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/util.h b/src/plugins/platforminputcontexts/hime/include/util.h +new file mode 100644 +index 0000000..62fbfc9 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/util.h +@@ -0,0 +1,12 @@ ++void p_err(char *fmt,...); ++ ++#ifndef DEBUG ++#define DEBUG 0 ++#endif ++ ++#if DEBUG ++void __hime_dbg_(char *fmt,...); ++#define dbg(fmt,...) __hime_dbg_("%s:%d: " fmt, __func__, __LINE__, ## __VA_ARGS__) ++#else ++#define dbg(...) do {} while (0) ++#endif +diff --git a/src/plugins/platforminputcontexts/hime/include/win-save-phrase.c b/src/plugins/platforminputcontexts/hime/include/win-save-phrase.c +new file mode 100644 +index 0000000..3e54b17 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/win-save-phrase.c +@@ -0,0 +1,226 @@ ++/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "pho.h" ++#include "win-save-phrase.h" ++#include "gtab.h" ++ ++extern int c_len; ++extern gboolean test_mode; ++ ++ ++typedef struct { ++ WSP_S *mywsp; ++ int mywspN; ++ GtkWidget *label_countdown, *win; ++ int countdown, countdown_handle; ++} SAVE_SESS; ++ ++static void wsp_str(WSP_S *wsp, int wspN, char *out) ++{ ++ int i; ++ int ofs=0; ++ ++ for(i=0;imywsp); sess->mywsp=NULL; ++ free(sess); ++} ++ ++ ++static gboolean close_win_save_phrase(GtkWidget *widget, gpointer data) ++{ ++ SAVE_SESS *sess = (SAVE_SESS *)data; ++ ++ g_source_remove(sess->countdown_handle); ++ gtk_widget_destroy(sess->win); ++ free_mywsp(sess); ++ return TRUE; ++} ++ ++#if 0 ++static gint delete_event( GtkWidget *widget, ++ GdkEvent *event, ++ gpointer data) ++{ ++ free_mywsp(data); ++ return FALSE; ++} ++#endif ++ ++extern int ph_key_sz; ++ ++static gboolean cb_ok(GtkWidget *widget, gpointer data) ++{ ++ SAVE_SESS *sess = (SAVE_SESS *)data; ++ g_source_remove(sess->countdown_handle); ++ ++ int i; ++ phokey_t pho[MAX_PHRASE_LEN]; ++ u_int pho32[MAX_PHRASE_LEN]; ++ u_int64_t pho64[MAX_PHRASE_LEN]; ++ char tt[512]; ++ void *dat = NULL; ++ wsp_str(sess->mywsp, sess->mywspN, tt); ++ ++ if (ph_key_sz==2) { ++ for(i=0;imywspN;i++) ++ pho[i] = sess->mywsp[i].key; ++ dat = pho; ++ } ++ else ++ if (ph_key_sz==4) { ++ for(i=0;i< sess->mywspN;i++) { ++ pho32[i] = sess->mywsp[i].key; ++ } ++ dat = pho32; ++ } ++ else ++ if (ph_key_sz==8) { ++ for(i=0;i< sess->mywspN;i++) ++ pho64[i] = sess->mywsp[i].key; ++ dat = pho64; ++ } ++ ++ save_phrase_to_db(dat, tt, sess->mywspN, 1); ++ ++ gtk_widget_destroy(sess->win); ++ ++ free_mywsp(sess); ++ return TRUE; ++} ++ ++static void disp_countdown(SAVE_SESS *sess) ++{ ++ char tt[64]; ++ ++ sprintf(tt, _("%d 秒後自動加入"), sess->countdown); ++ gtk_label_set_text(GTK_LABEL(sess->label_countdown), tt); ++} ++ ++ ++gboolean timeout_countdown(gpointer data) ++{ ++ SAVE_SESS *sess = (SAVE_SESS *)data; ++ ++ if (!sess->countdown) { ++ cb_ok(NULL, data); ++ return FALSE; ++ } ++ ++ sess->countdown--; ++ disp_countdown(sess); ++ return TRUE; ++} ++ ++ ++void create_win_save_phrase(WSP_S *wsp, int wspN) ++{ ++ if (!wspN) ++ return; ++ ++ SAVE_SESS *sess = tzmalloc(SAVE_SESS, 1); ++ ++ GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); ++ gtk_window_set_has_resize_grip(GTK_WINDOW(main_window), FALSE); ++ sess->win = main_window; ++ ++ gtk_window_set_default_size(GTK_WINDOW (main_window), 20, 10); ++ ++ gtk_window_set_title(GTK_WINDOW(main_window), _("加片語到詞庫")); ++ ++#if 0 ++ g_signal_connect (G_OBJECT (main_window), "delete_event", ++ G_CALLBACK (delete_event), sess); ++#endif ++ ++ GtkWidget *vbox = gtk_vbox_new (FALSE, 0); ++ gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox), GTK_ORIENTATION_VERTICAL); ++ gtk_container_add (GTK_CONTAINER (main_window), vbox); ++ ++ char tt[512]; ++ tt[0] = 0; ++ wsp_str(wsp, wspN, tt); ++ ++ gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new(tt), FALSE, FALSE, 0); ++ ++ int i; ++ for(i=0; imywsp = tmemdup(wsp, WSP_S, wspN); ++ sess->mywspN = wspN; ++ ++ GtkWidget *hbox_cancel_ok = gtk_hbox_new (FALSE, 10); ++ gtk_box_pack_start (GTK_BOX (vbox), hbox_cancel_ok , FALSE, FALSE, 5); ++ ++ GtkWidget *button_ok = gtk_button_new_from_stock (GTK_STOCK_OK); ++ gtk_box_pack_start (GTK_BOX (hbox_cancel_ok), button_ok, TRUE, TRUE, 5); ++ ++ GtkWidget *button_cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL); ++ gtk_box_pack_start (GTK_BOX (hbox_cancel_ok), button_cancel, TRUE, TRUE, 0); ++ ++ sess->label_countdown = gtk_label_new(NULL); ++ gtk_box_pack_start (GTK_BOX (vbox), sess->label_countdown, FALSE, FALSE, 5); ++ ++ gtk_widget_realize(main_window); ++ set_no_focus(main_window); ++ ++// dbg("mmmmmmmmmmmmm\n"); ++ ++ GTK_WIDGET_SET_FLAGS (button_ok, GTK_CAN_DEFAULT); ++ gtk_widget_grab_default (button_ok); ++ ++ ++#if 1 ++// dbg("main_window %x\n", main_window); ++ g_signal_connect (G_OBJECT (button_cancel), "clicked", ++ G_CALLBACK (close_win_save_phrase), ++ sess); ++ ++ g_signal_connect (G_OBJECT (button_ok), "clicked", ++ G_CALLBACK (cb_ok), ++ sess); ++#endif ++ ++ gtk_window_present(GTK_WINDOW(main_window)); ++ gtk_window_set_keep_above(GTK_WINDOW(main_window), TRUE); ++// gtk_window_set_modal(GTK_WINDOW(main_window), TRUE); ++ ++ sess->countdown = 3; ++ disp_countdown(sess); ++ sess->countdown_handle = g_timeout_add(1000, timeout_countdown, sess); ++ gtk_widget_show_all(main_window); ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/win-save-phrase.h b/src/plugins/platforminputcontexts/hime/include/win-save-phrase.h +new file mode 100644 +index 0000000..4af2578 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/win-save-phrase.h +@@ -0,0 +1,7 @@ ++typedef struct { ++ u_int64_t key; ++ char ch[CH_SZ]; ++ GtkWidget *opt; ++} WSP_S; ++ ++void create_win_save_phrase(WSP_S *wsp, int wspN); +diff --git a/src/plugins/platforminputcontexts/hime/include/win1.c b/src/plugins/platforminputcontexts/hime/include/win1.c +new file mode 100644 +index 0000000..5f9959a +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/win1.c +@@ -0,0 +1,432 @@ ++/* Copyright (C) 2004-2012 Edward Der-Hua Liu, Hsin-Chu, Taiwan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation version 2.1 ++ * of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hime.h" ++#include "pho.h" ++#include "gst.h" ++#include "win1.h" ++ ++GtkWidget *gwin1; ++static GtkWidget *frame; ++static char wselkey[16]; ++static int wselkeyN; ++//Window xwin1; ++ ++#define SELEN (15) ++ ++static GtkWidget *labels_sele[SELEN], *labels_seleR[SELEN]; ++static GtkWidget *eve_sele[SELEN], *eve_seleR[SELEN]; ++static GtkWidget *arrow_up, *arrow_down; ++ ++void hide_selections_win(); ++static cb_page_ud_t cb_page_up, cb_page_down; ++static int c_config; ++ ++static int current_config() ++{ ++ return (tsin_tail_select_key<<9) | (pho_candicate_col_N<<5) | wselkeyN << 1| ++ pho_candicate_R2L; ++} ++ ++static int idx_to_x(int tN, int i) ++{ ++ if (tN > pho_candicate_col_N) ++ tN = pho_candicate_col_N; ++ ++ int x = i % tN; ++ if (pho_candicate_R2L) ++ x = tN - 1 - x; ++ return x; ++} ++ ++static gboolean button_scroll_event_tsin(GtkWidget *widget,GdkEventScroll *event, gpointer user_data) ++{ ++ switch (event->direction) { ++ case GDK_SCROLL_UP: ++ if (cb_page_up) ++ cb_page_up(); ++ break; ++ case GDK_SCROLL_DOWN: ++ if (cb_page_down) ++ cb_page_down(); ++ break; ++ default: ++ break; ++ } ++ ++ return TRUE; ++} ++ ++ ++ ++void create_win1() ++{ ++ if (gwin1) ++ return; ++ ++ gwin1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); ++ gtk_window_set_has_resize_grip(GTK_WINDOW(gwin1), FALSE); ++ gtk_widget_realize (gwin1); ++ ++ set_no_focus(gwin1); ++ ++ g_signal_connect (G_OBJECT (gwin1), "scroll-event", G_CALLBACK (button_scroll_event_tsin), NULL); ++} ++ ++ ++void change_win1_font(), force_preedit_shift(); ++ ++ ++static cb_selec_by_idx_t cb_sele_by_idx; ++ ++static void mouse_button_callback( GtkWidget *widget,GdkEventButton *event, gpointer data) ++{ ++ int v; ++ switch (event->button) { ++ case 1: ++ v = GPOINTER_TO_INT(data); ++ if (cb_sele_by_idx) ++ cb_sele_by_idx(v); ++ force_preedit_shift(); ++ break; ++ } ++} ++ ++ ++static void cb_arrow_up (GtkWidget *button, gpointer user_data) ++{ ++ if (cb_page_up) ++ cb_page_up(); ++} ++static void cb_arrow_down (GtkWidget *button, gpointer user_data) ++{ ++ if (cb_page_down) ++ cb_page_down(); ++} ++ ++void set_win1_cb(cb_selec_by_idx_t sele_by_idx, cb_page_ud_t page_up, cb_page_ud_t page_down) ++{ ++ cb_sele_by_idx = sele_by_idx; ++ cb_page_up = page_up; ++ cb_page_down = page_down; ++} ++ ++void create_win1_gui() ++{ ++ if (frame) ++ return; ++// dbg("create_win1_gui %s\n", wselkey); ++ ++ frame = gtk_frame_new(NULL); ++ gtk_container_add (GTK_CONTAINER(gwin1), frame); ++ ++ GtkWidget *vbox_top = gtk_vbox_new (FALSE, 0); ++ gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox_top), GTK_ORIENTATION_VERTICAL); ++ gtk_container_add (GTK_CONTAINER(frame), vbox_top); ++ ++ GtkWidget *eve_box_up = gtk_event_box_new(); ++ gtk_event_box_set_visible_window (GTK_EVENT_BOX(eve_box_up), FALSE); ++ gtk_box_pack_start (GTK_BOX (vbox_top), eve_box_up, FALSE, FALSE, 0); ++ arrow_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_IN); ++ gtk_container_add(GTK_CONTAINER(eve_box_up), arrow_up); ++ g_signal_connect (G_OBJECT (eve_box_up), "button-press-event", ++ G_CALLBACK (cb_arrow_up), NULL); ++ ++ int c_rowN = (wselkeyN + pho_candicate_col_N - 1) / pho_candicate_col_N * pho_candicate_col_N; ++ int tablecolN = pho_candicate_col_N; ++ ++ if (!tsin_tail_select_key) ++ tablecolN *= 2; ++ ++ c_config = current_config(); ++ ++ GtkWidget *table = gtk_table_new(c_rowN, tablecolN, FALSE); ++ gtk_box_pack_start (GTK_BOX (vbox_top), table, FALSE, FALSE, 0); ++ ++ int i; ++ for(i=0; i < wselkeyN; i++) ++ { ++ int y = i/pho_candicate_col_N; ++ int x = idx_to_x(SELEN+1, i); ++ ++ if (!tsin_tail_select_key) ++ x*=2; ++ ++ GtkWidget *align = gtk_alignment_new(0,0,0,0); ++ gtk_table_attach_defaults(GTK_TABLE(table),align, x,x+1,y,y+1); ++ GtkWidget *event_box_pho = gtk_event_box_new(); ++ gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box_pho), FALSE); ++ GtkWidget *label = gtk_label_new(NULL); ++ gtk_container_add (GTK_CONTAINER (event_box_pho), label); ++ labels_sele[i] = label; ++ eve_sele[i] = event_box_pho; ++ gtk_container_add (GTK_CONTAINER (align), event_box_pho); ++ gtk_label_set_justify(GTK_LABEL(labels_sele[i]),GTK_JUSTIFY_LEFT); ++ set_label_font_size(labels_sele[i], hime_font_size_tsin_presel); ++ g_signal_connect(G_OBJECT(event_box_pho),"button-press-event", ++ G_CALLBACK(mouse_button_callback), GINT_TO_POINTER(i)); ++ ++ if (!tsin_tail_select_key) { ++ GtkWidget *alignR = gtk_alignment_new(0,0,0,0); ++ gtk_table_attach_defaults(GTK_TABLE(table), alignR, x+1,x+2,y,y+1); ++ GtkWidget *event_box_phoR = gtk_event_box_new(); ++ gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box_phoR), FALSE); ++ GtkWidget *labelR = gtk_label_new(NULL); ++ gtk_container_add (GTK_CONTAINER (event_box_phoR), labelR); ++ labels_seleR[i] = labelR; ++ eve_seleR[i] = event_box_phoR; ++ gtk_container_add (GTK_CONTAINER (alignR), event_box_phoR); ++ gtk_label_set_justify(GTK_LABEL(labels_sele[i]),GTK_JUSTIFY_LEFT); ++ set_label_font_size(labels_seleR[i], hime_font_size_tsin_presel); ++ g_signal_connect(G_OBJECT(event_box_phoR),"button-press-event", ++ G_CALLBACK(mouse_button_callback), GINT_TO_POINTER(i)); ++ } ++ } ++ ++ GtkWidget *eve_box_down = gtk_event_box_new(); ++ gtk_event_box_set_visible_window (GTK_EVENT_BOX(eve_box_down), FALSE); ++ gtk_box_pack_start (GTK_BOX (vbox_top), eve_box_down, FALSE, FALSE, 0); ++ arrow_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN); ++ gtk_container_add(GTK_CONTAINER(eve_box_down), arrow_down); ++ g_signal_connect (G_OBJECT (eve_box_down), "button-press-event", ++ G_CALLBACK (cb_arrow_down), NULL); ++ ++ gtk_widget_show_all(gwin1); ++// gdk_flush(); ++ gtk_widget_hide(gwin1); ++ ++ change_win1_font(); ++} ++ ++void init_tsin_selection_win() ++{ ++ create_win1(); ++ create_win1_gui(); ++} ++ ++void clear_sele() ++{ ++ int i; ++ ++ if (!gwin1) ++ return; ++ ++ for(i=0; i < wselkeyN; i++) { ++ gtk_widget_hide(labels_sele[i]); ++ if (labels_seleR[i]) ++ gtk_widget_hide(labels_seleR[i]); ++ } ++ ++ gtk_widget_hide(arrow_up); ++ gtk_widget_hide(arrow_down); ++ hide_selections_win(); ++} ++ ++char *htmlspecialchars(char *s, char out[]); ++ ++void set_sele_text(int tN, int i, char *text, int len) ++{ ++ if (len < 0) ++ len=strlen(text); ++ ++ char tt[128]; ++ char utf8[128]; ++ ++ memcpy(utf8, text, len); ++ utf8[len]=0; ++ char uu[32], selma[128]; ++ ++ char cc[2]; ++ cc[0]=wselkey[i]; ++ cc[1]=0; ++ char ul[128]; ++ ul[0]=0; ++ ++#if 0 ++ if (tss.sel_pho && i==tss.pho_menu_idx) ++ strcpy(ul, " foreground=\"yellow\" background=\"black\""); ++ else ++ sprintf(ul, "foreground=\"%s\"", hime_sel_key_color); ++#endif ++ if (tss.sel_pho && i==tss.pho_menu_idx) { ++ if (hime_win_color_use) ++ sprintf(ul, "foreground=\"white\" background=\"%s\"", tsin_cursor_color); ++ else ++ strcpy(ul, "foreground=\"white\" background=\""TSIN_CURSOR_COLOR_DEFAULT"\""); ++ } else { ++ if (hime_win_color_use) ++ sprintf(ul, "foreground=\"%s\"", hime_sel_key_color); ++ else ++ strcpy(ul, "foreground=\""HIME_SEL_KEY_COLOR_DEFAULT"\""); ++ } ++ ++ sprintf(selma, "%s", ul, htmlspecialchars(cc, uu)); ++ ++ int x = idx_to_x(tN, i); ++ char *sep= x?" ":""; ++ ++ if (tsin_tail_select_key) { ++ char vv[128]; ++ snprintf(tt, sizeof(tt), "%s%s%s", sep, htmlspecialchars(utf8, vv), selma); ++ } else { ++ gtk_label_set_text(GTK_LABEL(labels_seleR[i]), utf8); ++ gtk_widget_show(labels_seleR[i]); ++ snprintf(tt, sizeof(tt), "%s%s",sep, selma); ++ } ++ ++ gtk_widget_show(labels_sele[i]); ++// dbg("tt %s\n", tt); ++ gtk_label_set_markup(GTK_LABEL(labels_sele[i]), tt); ++} ++ ++void raise_tsin_selection_win() ++{ ++ if (gwin1 && GTK_WIDGET_VISIBLE(gwin1)) ++ gtk_window_present(GTK_WINDOW(gwin1)); ++} ++ ++ ++void getRootXY(Window win, int wx, int wy, int *tx, int *ty); ++void disp_selections(int x, int y) ++{ ++ if (!gwin1) ++ p_err("disp_selections !gwin1"); ++ ++ if (y < 0) { ++ int tx; ++ if (hime_edit_display_ap_only()) ++ getRootXY(current_CS->client_win, current_CS->spot_location.x, current_CS->spot_location.y, &tx, &y); ++ else ++ y = win_y + win_yl; ++ } ++ ++ ++ int win1_xl, win1_yl; ++ get_win_size(gwin1, &win1_xl, &win1_yl); ++ ++ if (x < 0) { ++ x = win_x + win_xl - win1_xl; ++ if (x < win_x) ++ x = win_x; ++ } ++ ++ if (x + win1_xl > dpy_xl) ++ x = dpy_xl - win1_xl; ++ ++ if (y + win1_yl > dpy_yl) ++ y = win_y - win1_yl; ++ ++ gtk_window_move(GTK_WINDOW(gwin1), x, y); ++ ++ if (!GTK_WIDGET_VISIBLE(gwin1)) { ++ gtk_widget_show(gwin1); ++ } ++} ++ ++void hide_selections_win() ++{ ++ if (!gwin1) ++ return; ++ gtk_widget_hide(gwin1); ++} ++ ++void disp_arrow_up() ++{ ++ gtk_widget_show(arrow_up); ++} ++ ++void disp_arrow_down() ++{ ++ gtk_widget_show(arrow_down); ++} ++ ++#if USE_TSIN ++void destroy_win1() ++{ ++ if (!gwin1) ++ return; ++ gtk_widget_destroy(gwin1); ++ frame=NULL; ++ gwin1 = NULL; ++} ++#endif ++ ++void change_win1_font() ++{ ++ int i; ++ if (!frame) ++ return; ++ ++ GdkColor fg; ++ gdk_color_parse(hime_win_color_fg, &fg); ++#if GTK_CHECK_VERSION(2,91,6) ++ GdkRGBA rgbfg; ++ gdk_rgba_parse(&rgbfg, gdk_color_to_string(&fg)); ++#endif ++ ++ for(i=0; i < wselkeyN; i++) { ++ set_label_font_size(labels_sele[i], hime_font_size_tsin_presel); ++ set_label_font_size(labels_seleR[i], hime_font_size_tsin_presel); ++#if !GTK_CHECK_VERSION(2,91,6) ++ if (labels_sele[i]) ++ gtk_widget_modify_fg(labels_sele[i], GTK_STATE_NORMAL, hime_win_color_use?&fg:NULL); ++ if (labels_seleR[i]) ++ gtk_widget_modify_fg(labels_seleR[i], GTK_STATE_NORMAL, hime_win_color_use?&fg:NULL); ++#else ++ if (labels_sele[i]) ++ gtk_widget_override_color(labels_sele[i], GTK_STATE_FLAG_NORMAL, hime_win_color_use?&rgbfg:NULL); ++ if (labels_seleR[i]) ++ gtk_widget_override_color(labels_seleR[i], GTK_STATE_FLAG_NORMAL, hime_win_color_use?&rgbfg:NULL); ++#endif ++ change_win_bg(eve_sele[i]); ++ if (eve_seleR[i]) ++ change_win_bg(eve_seleR[i]); ++ } ++ ++ change_win_bg(gwin1); ++} ++ ++void recreate_win1_if_nessary() ++{ ++// dbg("%x %x\n", current_config(), c_config); ++ ++ if (!gwin1) ++ return; ++ ++ if (current_config() != c_config) { ++ c_config = current_config(); ++// dbg("destroy frame\n"); ++ bzero(labels_sele, sizeof(labels_sele)); ++ bzero(labels_seleR, sizeof(labels_seleR)); ++ bzero(eve_sele, sizeof(eve_sele)); ++ bzero(eve_seleR, sizeof(eve_seleR)); ++ gtk_widget_destroy(frame); frame = NULL; ++ create_win1_gui(); ++ } ++} ++ ++ ++void set_wselkey(char *s) ++{ ++ if (strcmp (wselkey, s)) ++ { ++ memset (wselkey, 0x00, 16); ++ memcpy (wselkey, s, strlen (s)); ++ wselkeyN = strlen (s); ++ recreate_win1_if_nessary (); ++ } ++} +diff --git a/src/plugins/platforminputcontexts/hime/include/win1.h b/src/plugins/platforminputcontexts/hime/include/win1.h +new file mode 100644 +index 0000000..1907861 +--- /dev/null ++++ b/src/plugins/platforminputcontexts/hime/include/win1.h +@@ -0,0 +1,3 @@ ++typedef void (*cb_selec_by_idx_t)(int); ++typedef void (*cb_page_ud_t)(); ++void set_win1_cb(cb_selec_by_idx_t selc_by_idx, cb_page_ud_t cb_page_up, cb_page_ud_t cb_page_down); diff --git a/src/plugins/platforminputcontexts/platforminputcontexts.pro b/src/plugins/platforminputcontexts/platforminputcontexts.pro -index faea54b..e31be7c 100644 +index faea54b..0f96509 100644 --- a/src/plugins/platforminputcontexts/platforminputcontexts.pro +++ b/src/plugins/platforminputcontexts/platforminputcontexts.pro @@ -1,7 +1,8 @@ @@ -11261,8 +33669,8 @@ index faea54b..e31be7c 100644 qtHaveModule(dbus) { -!mac:!win32:SUBDIRS += ibus -+# Patch: Adding fcitx input context plugin to our static build. -+!mac:!win32:SUBDIRS += ibus fcitx ++# Patch: Adding fcitx/hime input context plugin to our static build. ++!mac:!win32:SUBDIRS += ibus fcitx hime } contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose diff --git a/Telegram/SourceFiles/qt_static_plugins.cpp b/Telegram/SourceFiles/qt_static_plugins.cpp index 1d4896a637..b975c7a84e 100644 --- a/Telegram/SourceFiles/qt_static_plugins.cpp +++ b/Telegram/SourceFiles/qt_static_plugins.cpp @@ -36,4 +36,5 @@ Q_IMPORT_PLUGIN(QNetworkManagerEnginePlugin) Q_IMPORT_PLUGIN(QComposePlatformInputContextPlugin) Q_IMPORT_PLUGIN(QIbusPlatformInputContextPlugin) Q_IMPORT_PLUGIN(QFcitxPlatformInputContextPlugin) +Q_IMPORT_PLUGIN(QHimePlatformInputContextPlugin) #endif // Q_OS_WIN | Q_OS_MAC | Q_OS_LINUX diff --git a/Telegram/gyp/telegram_linux.gypi b/Telegram/gyp/telegram_linux.gypi index b8866ec214..2c464928ff 100644 --- a/Telegram/gyp/telegram_linux.gypi +++ b/Telegram/gyp/telegram_linux.gypi @@ -56,6 +56,7 @@ 'composeplatforminputcontextplugin', 'ibusplatforminputcontextplugin', 'fcitxplatforminputcontextplugin', + 'himeplatforminputcontextplugin', 'liblzma.a', 'libopenal.a', 'libavformat.a',