Back to index

im-sdk  12.3.91
menu.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <X11/Xmd.h>
00005 #include <gtk/gtk.h>
00006 #include <gdk/gdkx.h>
00007 #include <gdk/gdkkeysyms.h>
00008 #include <canna/jrkanji.h>
00009 #include <canna/mfdef.h>
00010 #include "SunIM.h"
00011 #include "xaux_common.h"
00012 #include "xaux_ext_common.h"
00013 #include "iiimpAux.h"
00014 #include "cannadef.h"
00015 
00016 #define       FLABEL_FORMAT "%s [%d/%d]"
00017 #define DATA_FATTACHED      "auxmenu-frame-attached"
00018 #define       DATA_ATTACHED "auxmenu-attached"
00019 #define DATA_ENTRY   "auxmenu-entry"
00020 #define       DATA_TREEVIEW "auxmenu-treeview"
00021 #define       DATA_FRAME    "auxmenu-frame"
00022 #define       DATA_LABEL    "auxmenu-label"
00023 #define       DATA_FTITLE   "auxmenu-frame-title"
00024 #define       DATA_BEGIN_ITEM      "auxmenu-begin-of-item"
00025 #define       DATA_CUR_ITEM "auxmenu-current-item"
00026 #define       DATA_END_ITEM "auxmenu-end-of-item"
00027 #define       DATA_PAGE_MAX "auxmenu-page-max-item"
00028 
00029 #ifdef DEBUG
00030 #define       ENTER  fprintf(stderr, "%s: enter.\n", __FUNCTION__)
00031 #define       LEAVE  fprintf(stderr, "%s: leave.\n", __FUNCTION__)
00032 #else
00033 #define       ENTER
00034 #define       LEAVE
00035 #endif
00036 
00037 extern void DEBUG_printf(const char *format, ...);
00038 
00039 xaux_class_t xaux_class = {
00040     .classname = "com.OpenI18N.leif.CannaLE.menu",
00041     .index = 0,
00042     .extexec = XAUX_EXT_DIR "auxmenu",
00043     .sowin = (Window)0,
00044     .clientwin = (Window)0,
00045     .extwin = (Window)0,
00046     .atom_classname = (Atom)0,
00047     .atom_clientwin = (Atom)0,
00048     .atom_sowin = (Atom)0,
00049     .atom_extwin = (Atom)0,
00050     .atom_sx = { (Atom)0 },
00051     .atom_sx_num = 32,
00052     .atom_sx_idx = 0,
00053     .atom_xs = { (Atom)0 },
00054     .atom_xs_num = 32,
00055     .atom_xs_idx = 0,
00056     .utfname = NULL,
00057 };
00058 GtkWidget *auxwindow;
00059 
00060 static GdkEvent *
00061 translate_key_event(int keycode, int modifier, gboolean press)
00062 {
00063     GdkKeymap *keymap = gdk_keymap_get_for_display(gtk_widget_get_display(auxwindow));
00064     GdkKeymapKey *keys;
00065     GdkEvent *event = gdk_event_new((press ? GDK_KEY_PRESS : GDK_KEY_RELEASE));
00066     gint n_keys;
00067 
00068     event->key.type = (press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
00069     event->key.state = 0;
00070     if (modifier & IM_SHIFT_MASK) {
00071        event->key.state |= GDK_SHIFT_MASK;
00072     }
00073     if (modifier & IM_CTRL_MASK) {
00074        event->key.state |= GDK_CONTROL_MASK;
00075     }
00076     if (modifier & IM_ALT_MASK) {
00077        event->key.state |= GDK_MOD1_MASK;
00078     }
00079     switch (keycode) {
00080        case IM_VK_BACK_SPACE:
00081            event->key.keyval = GDK_BackSpace;
00082            break;
00083        case IM_VK_UP:
00084            event->key.keyval = GDK_Up;
00085            break;
00086        case IM_VK_DOWN:
00087            event->key.keyval = GDK_Down;
00088            break;
00089        case IM_VK_LEFT:
00090            event->key.keyval = GDK_Left;
00091            break;
00092        case IM_VK_RIGHT:
00093            event->key.keyval = GDK_Right;
00094            break;
00095        case IM_VK_PAGE_UP:
00096            event->key.keyval = GDK_Page_Up;
00097            break;
00098        case IM_VK_PAGE_DOWN:
00099            event->key.keyval = GDK_Page_Down;
00100            break;
00101        case IM_VK_CLEAR:
00102            event->key.keyval = GDK_Clear;
00103            break;
00104        case IM_VK_SPACE:
00105            event->key.keyval = GDK_space;
00106            break;
00107        case IM_VK_END:
00108            event->key.keyval = GDK_End;
00109            break;
00110        case IM_VK_HOME:
00111            event->key.keyval = GDK_Home;
00112            break;
00113        case IM_VK_COMMA:
00114            event->key.keyval = GDK_comma;
00115            break;
00116        case IM_VK_MINUS:
00117            event->key.keyval = GDK_minus;
00118            break;
00119        case IM_VK_PERIOD:
00120            event->key.keyval = GDK_period;
00121            break;
00122        case IM_VK_SLASH:
00123            event->key.keyval = GDK_slash;
00124            break;
00125        case IM_VK_SEMICOLON:
00126            event->key.keyval = GDK_semicolon;
00127            break;
00128        case IM_VK_EQUALS:
00129            event->key.keyval = GDK_equal;
00130            break;
00131        case IM_VK_OPEN_BRACKET:
00132            event->key.keyval = GDK_bracketleft;
00133            break;
00134        case IM_VK_BACK_SLASH:
00135            event->key.keyval = GDK_backslash;
00136            break;
00137        case IM_VK_CLOSE_BRACKET:
00138            event->key.keyval = GDK_bracketright;
00139            break;
00140        case IM_VK_MULTIPLY:
00141            event->key.keyval = GDK_KP_Multiply;
00142            break;
00143        case IM_VK_ADD:
00144            event->key.keyval = GDK_KP_Add;
00145            break;
00146        case IM_VK_SEPARATER:
00147            event->key.keyval = GDK_KP_Separator;
00148            break;
00149        case IM_VK_SUBTRACT:
00150            event->key.keyval = GDK_KP_Subtract;
00151            break;
00152        case IM_VK_DECIMAL:
00153            event->key.keyval = GDK_KP_Decimal;
00154            break;
00155        case IM_VK_DIVIDE:
00156            event->key.keyval = GDK_KP_Divide;
00157            break;
00158        case IM_VK_DELETE:
00159            event->key.keyval = GDK_Delete;
00160            break;
00161        default:
00162            if (keycode >= IM_VK_0 && keycode <= IM_VK_9) {
00163               event->key.keyval = GDK_0 + keycode - IM_VK_0;
00164            } else if (keycode >= IM_VK_A && keycode <= IM_VK_Z) {
00165               event->key.keyval = GDK_a + keycode - IM_VK_A;
00166            } else if (keycode >= IM_VK_NUMPAD0 && keycode <= IM_VK_NUMPAD9) {
00167               event->key.keyval = GDK_KP_0 + keycode - IM_VK_NUMPAD0;
00168            }
00169            break;
00170     }
00171     if (event->key.keyval != 0) {
00172        gdk_keymap_get_entries_for_keyval(keymap, event->key.keyval, &keys, &n_keys);
00173        if (n_keys) {
00174            event->key.hardware_keycode = keys[0].keycode;
00175 
00176            g_free(keys);
00177        }
00178     }
00179 
00180     return event;
00181 }
00182 
00183 static void
00184 change_focus(GtkWidget *widget, int focus)
00185 {
00186     GdkEvent *event;
00187 
00188     if (widget != NULL) {
00189        g_object_ref(widget);
00190        event = gdk_event_new(GDK_FOCUS_CHANGE);
00191        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
00192        event->focus_change.type = GDK_FOCUS_CHANGE;
00193        event->focus_change.window = widget->window;
00194        if (widget->window)
00195            g_object_ref(widget->window);
00196        if (focus == 0) {
00197            /* unfocus */
00198            event->focus_change.in = FALSE;
00199        } else {
00200            /* focus */
00201            event->focus_change.in = TRUE;
00202        }
00203        gtk_widget_event(widget, event);
00204        g_object_notify(G_OBJECT(widget), "has_focus");
00205        g_object_unref(widget);
00206        gdk_event_free(event);
00207     }
00208 }
00209 
00210 static void
00211 send_key_event(int im,
00212               int ic,
00213               xaux_class_t *xc,
00214               int keycode,
00215               int modifier,
00216               int translated)
00217 {
00218     aux_ext_data_t data;
00219     int integer_list[INT_END];
00220 
00221     integer_list[INT_AUXMODE] = AUX_UPDATE_KEY;
00222     integer_list[INT_KEYCODE] = keycode;
00223     integer_list[INT_KEYMOD] = modifier;
00224     integer_list[INT_TRANSLATEDCODE] = translated;
00225 
00226     DEBUG_printf("keycode = %d\n", keycode);
00227     data.im = im;
00228     data.ic = ic;
00229     data.integer_count = INT_END;
00230     data.integer_list = integer_list;
00231     data.string_count = 0;
00232     data.string_list = NULL;
00233     data.string_ptr = NULL;
00234     data.point.x = 0;
00235     data.point.y = 0;
00236 
00237     if (xc != NULL)
00238        xaux_ext_SetValue(GDK_DISPLAY(), xc, &data);
00239     XFlush(GDK_DISPLAY());
00240 }
00241 
00242 static void
00243 send_aux_event(int im,
00244               int ic,
00245               xaux_class_t *xc,
00246               int auxmode)
00247 {
00248     aux_ext_data_t data;
00249     int integer_list[INT_END];
00250 
00251     integer_list[INT_AUXMODE] = auxmode;
00252 
00253     data.im = im;
00254     data.ic = ic;
00255     data.integer_count = INT_END;
00256     data.integer_list = integer_list;
00257     data.string_count = 0;
00258     data.string_list = NULL;
00259     data.string_ptr = NULL;
00260     data.point.x = 0;
00261     data.point.y = 0;
00262 
00263     if (xc != NULL)
00264        xaux_ext_SetValue(GDK_DISPLAY(), xc, &data);
00265     XFlush(GDK_DISPLAY());
00266 }
00267 
00268 static void
00269 set_position(GtkWidget *widget)
00270 {
00271     GtkRequisition requisition;
00272     GdkScreen *screen, *pointer_screen;
00273     gint x, y;
00274 
00275     ENTER;
00276 
00277     screen = gtk_widget_get_screen(widget);
00278     gdk_display_get_pointer(gdk_screen_get_display(screen),
00279                          &pointer_screen, &x, &y, NULL);
00280 
00281     gtk_widget_size_request(widget, &requisition);
00282     if (pointer_screen != screen) {
00283        /* Pointer is on a different screen; roughly center the
00284         * menu on the screen. If someone was using multiscreen
00285         * + Xinerama together they'd probably want something
00286         * fancier; but that is likely to be vanishingly rare.
00287         */
00288        x = MAX(0, (gdk_screen_get_width(screen) - requisition.width) / 2);
00289        y = MAX(0, (gdk_screen_get_height(screen) - requisition.height) / 2);
00290     }
00291 
00292     gtk_window_move(GTK_WINDOW(widget), x, y);
00293 
00294     LEAVE;
00295 }
00296 
00297 static gboolean
00298 update_entry_count(guint current)
00299 {
00300     GtkWidget *frame = g_object_get_data(G_OBJECT(auxwindow), DATA_FRAME);
00301     GtkWidget *label;
00302     gchar *str;
00303     gchar *title = g_object_get_data(G_OBJECT(auxwindow), DATA_FTITLE);
00304     guint beginitem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_BEGIN_ITEM));
00305     guint enditem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_END_ITEM));
00306 
00307     if (current > enditem)
00308        return FALSE;
00309 
00310     str = g_strdup_printf(FLABEL_FORMAT, title, current + beginitem, enditem);
00311     label = gtk_frame_get_label_widget(GTK_FRAME(frame));
00312     gtk_label_set_text(GTK_LABEL(label), str);
00313     g_free(str);
00314 
00315     return TRUE;
00316 }
00317 
00318 static void
00319 update_menu(GtkWidget              *widget,
00320            int                     count,
00321            const aux_ext_string_t *string_list)
00322 {
00323     GtkListStore *store;
00324     GtkTreeIter iter;
00325     GtkCellRenderer *renderer;
00326     GtkTreeViewColumn *column;
00327     GtkTreePath *path;
00328     GdkRectangle rect;
00329     GtkRequisition requisition;
00330     int i;
00331     gchar *item;
00332 
00333     g_object_set_data(G_OBJECT(auxwindow), DATA_PAGE_MAX, GUINT_TO_POINTER(count / 2));
00334 
00335     /* remove the old columns first */
00336     while (1) {
00337        column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00338        if (column != NULL)
00339            gtk_tree_view_remove_column(GTK_TREE_VIEW(widget), column);
00340        else
00341            break;
00342     }
00343 
00344     /* create new columns */
00345     store = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
00346     for (i = 1; i < count; i += 2) {
00347        gtk_list_store_append(store, &iter);
00348        string_list[i].ptr[string_list[i].length] = 0;
00349        string_list[i].ptr[string_list[i].length+1] = 0;
00350        item = g_utf16_to_utf8((gunichar2 *)string_list[i].ptr, -1, NULL, NULL, NULL);
00351 
00352        DEBUG_printf("*** %d: item = %s (%d)\n", i / 2 + 1, item, string_list[i].length);
00353 
00354        gtk_list_store_set(store, &iter, 0, i / 2 + 1, 1, item, -1);
00355        g_free(item);
00356     }
00357     gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store));
00358 
00359     for (i = 0; i < 2; i++) {
00360        renderer = gtk_cell_renderer_text_new();
00361        column = gtk_tree_view_column_new_with_attributes("", renderer, "text", i, NULL);
00362        gtk_tree_view_column_set_resizable(column, TRUE);
00363        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
00364        gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
00365     }
00366 
00367     g_object_unref(G_OBJECT(store));
00368 
00369     /* enforce to select first item */
00370     path = gtk_tree_path_new_first();
00371     column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00372     gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00373     gtk_tree_path_free(path);
00374 
00375     /* recalculate the window size */
00376     gdk_window_get_frame_extents(auxwindow->window, &rect);
00377     gtk_widget_size_request(auxwindow, &requisition);
00378 
00379     if (requisition.width < rect.width || requisition.height < rect.height)
00380        gtk_window_resize(GTK_WINDOW(auxwindow), requisition.width, requisition.height);
00381 }
00382 
00383 static void
00384 update_dictmenu(GtkWidget              *widget,
00385               int                     count,
00386               const aux_ext_string_t *string_list)
00387 {
00388     GtkListStore *store;
00389     GtkTreeIter iter;
00390     GtkCellRenderer *renderer;
00391     GtkTreeViewColumn *column;
00392     GtkTreePath *path;
00393     GdkRectangle rect;
00394     GtkRequisition requisition;
00395     int i;
00396     guchar *item, *fitem;
00397     gboolean flag;
00398 
00399     g_object_set_data(G_OBJECT(auxwindow), DATA_PAGE_MAX, GUINT_TO_POINTER(count / 2));
00400 
00401     /* remove the old columns first */
00402     while (1) {
00403        column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00404        if (column != NULL)
00405            gtk_tree_view_remove_column(GTK_TREE_VIEW(widget), column);
00406        else
00407            break;
00408     }
00409 
00410     /* create new columns */
00411     store = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_BOOLEAN);
00412     for (i = 0; i < count; i += 2) {
00413        gtk_list_store_append(store, &iter);
00414        string_list[i].ptr[string_list[i].length] = 0;
00415        string_list[i].ptr[string_list[i].length+1] = 0;
00416        string_list[i+1].ptr[string_list[i+1].length] = 0;
00417        string_list[i+1].ptr[string_list[i+1].length+1] = 0;
00418        fitem = g_utf16_to_utf8((gunichar2 *)string_list[i].ptr, -1, NULL, NULL, NULL);
00419        item = g_utf16_to_utf8((gunichar2 *)string_list[i+1].ptr, -1, NULL, NULL, NULL);
00420        if (fitem[0] == 0xe2 && fitem[1] == 0x97 && fitem[2] == 0x8e)
00421            flag = TRUE;
00422        else
00423            flag = FALSE;
00424        gtk_list_store_set(store, &iter, 0, flag, 1, item, 2, FALSE, -1);
00425        g_free(item);
00426     }
00427     gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store));
00428 
00429     /* column 0 */
00430     renderer = gtk_cell_renderer_toggle_new();
00431     column = gtk_tree_view_column_new_with_attributes("", renderer, "active", 0, NULL);
00432     gtk_tree_view_column_set_resizable(column, TRUE);
00433     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
00434     gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
00435     /* column 1 */
00436     renderer = gtk_cell_renderer_text_new();
00437     column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
00438     gtk_tree_view_column_set_resizable(column, TRUE);
00439     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
00440     gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
00441 
00442     g_object_unref(G_OBJECT(store));
00443 
00444     /* enforce to select first item */
00445     path = gtk_tree_path_new_first();
00446     column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00447     gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00448     gtk_tree_path_free(path);
00449 
00450     /* recalculate the window size */
00451     gdk_window_get_frame_extents(auxwindow->window, &rect);
00452     gtk_widget_size_request(auxwindow, &requisition);
00453 
00454     if (requisition.width < rect.width || requisition.height < rect.height)
00455        gtk_window_resize(GTK_WINDOW(auxwindow), requisition.width, requisition.height);
00456 }
00457 
00458 static void
00459 move_menu_position(gint pos)
00460 {
00461     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00462     GtkTreePath *path;
00463     GtkTreeViewColumn *column;
00464     guint offset = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_BEGIN_ITEM));
00465 
00466     g_return_if_fail((pos - offset) >= 0);
00467 
00468     path = gtk_tree_path_new_from_indices(pos - offset, -1);
00469     column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00470     gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00471     gtk_tree_path_free(path);
00472 }
00473 
00474 static void
00475 update_menu_position(int           keycode,
00476                    int           modifier,
00477                    int           translated,
00478                    int           im,
00479                    int           ic,
00480                    xaux_class_t *xc,
00481                    gboolean      numericalkey)
00482 {
00483     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00484     GtkTreeViewColumn *column;
00485     GtkTreePath *path = NULL;
00486     GtkTreeModel *model;
00487     GtkTreeIter iter;
00488     GtkTreeSelection *sel;
00489     gint num = 0, beginitem, enditem, pagemax, idx, i;
00490 
00491     pagemax = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_PAGE_MAX));
00492     beginitem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_BEGIN_ITEM));
00493     enditem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_END_ITEM));
00494 
00495     model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
00496     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
00497     switch (keycode) {
00498        case IM_VK_UP:
00499            if(gtk_tree_selection_get_selected(sel, NULL, &iter)) {
00500               path = gtk_tree_model_get_path(model, &iter);
00501               idx = gtk_tree_path_get_indices(path)[0];
00502               if (idx == 0) {
00503                   if (beginitem > 1) {
00504                      /* back to the previous page. */
00505                      send_key_event(im, ic, xc, IM_VK_LEFT, 0, CANNA_KEY_Left);
00506                      return;
00507                   }
00508               }
00509               if (gtk_tree_path_prev(path)) {
00510                   column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00511                   gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00512               }
00513            } else {
00514               path = gtk_tree_path_new_first();
00515               column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00516               gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00517            }
00518            idx = gtk_tree_path_get_indices(path)[0];
00519            update_entry_count(idx);
00520            gtk_tree_path_free(path);
00521            break;
00522        case IM_VK_DOWN:
00523            if (gtk_tree_selection_get_selected(sel, NULL, &iter)) {
00524               path = gtk_tree_model_get_path(model, &iter);
00525               idx = gtk_tree_path_get_indices(path)[0];
00526               if ((idx + 1) >= pagemax) {
00527                   if (enditem >= (beginitem + pagemax)) {
00528                      /*
00529                       * current position in the server should be the begin of item.
00530                       * so just sending Rollup key should works.
00531                       */
00532                      send_key_event(im, ic, xc, IM_VK_PAGE_DOWN, 0, CANNA_KEY_Rollup);
00533                   }
00534                   return;
00535               }
00536               gtk_tree_path_next(path);
00537            } else {
00538               path = gtk_tree_path_new_first();
00539            }
00540            column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00541            gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00542            idx = gtk_tree_path_get_indices(path)[0];
00543            update_entry_count(idx);
00544            gtk_tree_path_free(path);
00545            break;
00546        case IM_VK_ENTER:
00547            if (gtk_tree_selection_get_selected(sel, NULL, &iter)) {
00548               model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
00549               gtk_tree_model_get(model, &iter, 0, &num, -1);
00550               if (num >= 0 && num <= 9) {
00551                   if (numericalkey) {
00552                      send_key_event(im, ic, xc, IM_VK_0 + num, 0, IM_VK_0 + num);
00553                   } else {
00554                      /* use cursor key and enter key instead of numerical shortcut key */
00555                      for (i = 0; i < num - 1; i++) {
00556                          send_aux_event(im, ic, xc, AUX_FORCE_NOT_UPDATE_STATE);
00557                          send_key_event(im, ic, xc, IM_VK_RIGHT, 0, CANNA_KEY_Right);
00558                      }
00559                      send_key_event(im, ic, xc, keycode, 0, translated);
00560                   }
00561               }
00562            }
00563            break;
00564        case IM_VK_BACK_SPACE:
00565            send_key_event(im, ic, xc, keycode, 0, translated);
00566            break;
00567        default:
00568            if ((modifier & IM_CTRL_MASK && keycode == IM_VK_G) ||
00569               keycode == IM_VK_ESCAPE) {
00570               /* cancel */
00571               send_key_event(im, ic, xc, IM_VK_G, modifier, '');
00572            } else if (keycode >= IM_VK_0 && keycode <= IM_VK_9) {
00573               if (numericalkey) {
00574                   send_key_event(im, ic, xc, keycode, 0, '0' + keycode - IM_VK_0);
00575               } else {
00576                   /* use cursor key and enter key instead of numerical shortcut key */
00577                   for (i = 0; i < (keycode - IM_VK_0) - 1; i++) {
00578                      send_key_event(im, ic, xc, IM_VK_RIGHT, 0, CANNA_KEY_Right);
00579                   }
00580                   send_key_event(im, ic, xc, IM_VK_ENTER, 0, 0x0D);
00581               }
00582            }
00583            break;
00584     }
00585 }
00586 
00587 static void
00588 update_codeinput_position(int           keycode,
00589                        int           modifier,
00590                        int           translated,
00591                        int           im,
00592                        int           ic,
00593                        xaux_class_t *xc)
00594 {
00595     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
00596     GdkEvent *eventp, *eventr;
00597     GString *str;
00598     int i;
00599 
00600     eventp = translate_key_event(keycode, modifier, TRUE);
00601     eventr = translate_key_event(keycode, modifier, FALSE);
00602 
00603     str = g_string_new(gtk_entry_get_text(GTK_ENTRY(widget)));
00604     if ((keycode == IM_VK_BACK_SPACE && str->len == 0) ||
00605        keycode == IM_VK_ESCAPE ||
00606        (keycode == IM_VK_G && modifier & IM_CTRL_MASK)) {
00607        /* cancel */
00608        send_key_event(im, ic, xc, IM_VK_G, IM_CTRL_MASK, '');
00609     } else if (keycode == IM_VK_ENTER) {
00610        for (i = 0; i < str->len; i++) {
00611            send_key_event(im, ic, xc, str->str[i], 0, str->str[i]);
00612        }
00613        send_key_event(im, ic, xc, keycode, 0, translated);
00614     } else if (eventp->key.keyval == 0) {
00615        /* nothing here */
00616     } else if (keycode >= IM_VK_G && keycode <= IM_VK_Z && ((modifier | IM_SHIFT_MASK) ^ IM_SHIFT_MASK) == 0) {
00617        /* nothing here */
00618     } else {
00619        /* send pseudo key event to the widget */
00620        eventp->key.window = eventr->key.window = widget->window;
00621        if (widget->window) {
00622            g_object_ref(widget->window);
00623            g_object_ref(widget->window);
00624        }
00625        /* prefers capital letter for code input */
00626        if (keycode >= IM_VK_A && keycode <= IM_VK_F) {
00627            eventp->key.keyval = eventr->key.keyval = GDK_A + eventp->key.keyval - GDK_a;
00628        }
00629        gtk_widget_event(widget, eventp);
00630        gtk_widget_event(widget, eventr);
00631     }
00632 
00633     gdk_event_free(eventp);
00634     gdk_event_free(eventr);
00635     g_string_free(str, TRUE);
00636 }
00637 
00638 static void
00639 update_dictmenu_state(int           im,
00640                     int           ic,
00641                     xaux_class_t *xc,
00642                     int           direction)
00643 {
00644     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00645     GtkTreePath *path;
00646     GtkTreeModel *model;
00647     GtkTreeIter iter;
00648     guint pagemax = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_PAGE_MAX));
00649     gboolean changed = FALSE;
00650     int i;
00651 
00652     path = gtk_tree_path_new_first();
00653     model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
00654     while (gtk_tree_path_get_indices(path)[0] < pagemax) {
00655        if (gtk_tree_model_get_iter(model, &iter, path)) {
00656            gtk_tree_model_get(model, &iter, 2, &changed, -1);
00657            if (changed) {
00658               send_key_event(im, ic, xc, IM_VK_SPACE, 0, IM_VK_SPACE);
00659            }
00660            send_key_event(im, ic, xc, IM_VK_RIGHT, 0, CANNA_KEY_Right);
00661        }
00662        gtk_tree_path_next(path);
00663     }
00664     gtk_tree_path_free(path);
00665 
00666     if (direction < 0) {
00667        for (i = 0; i <= pagemax; i++)
00668            send_key_event(im, ic, xc, IM_VK_LEFT, 0, CANNA_KEY_Left);
00669     }
00670     send_aux_event(im, ic, xc, AUX_FORCE_UPDATE_STATE);
00671 }
00672 
00673 static void
00674 update_dictmenu_position(int           keycode,
00675                       int           modifier,
00676                       int           translated,
00677                       int           im,
00678                       int           ic,
00679                       xaux_class_t *xc)
00680 {
00681     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00682     GtkTreeViewColumn *column;
00683     GtkTreePath *path;
00684     GtkTreeModel *model;
00685     GtkTreeIter iter;
00686     GtkTreeSelection *sel;
00687     int beginitem, enditem, pagemax, idx;
00688     gboolean use = FALSE, changed = FALSE;
00689 
00690     pagemax = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_PAGE_MAX));
00691     beginitem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_BEGIN_ITEM));
00692     enditem = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(auxwindow), DATA_END_ITEM));
00693 
00694     model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
00695     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
00696     switch (keycode) {
00697        case IM_VK_UP:
00698            if(gtk_tree_selection_get_selected(sel, NULL, &iter)) {
00699               path = gtk_tree_model_get_path(model, &iter);
00700               idx = gtk_tree_path_get_indices(path)[0];
00701               if (idx == 0) {
00702                   if (beginitem > 1) {
00703                      /* back to the previous page. */
00704                      update_dictmenu_state(im, ic, xc, -1);
00705                      return;
00706                   }
00707               }
00708               if (gtk_tree_path_prev(path)) {
00709                   column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00710                   gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00711               }
00712            } else {
00713               path = gtk_tree_path_new_first();
00714               column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00715               gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00716            }
00717            idx = gtk_tree_path_get_indices(path)[0];
00718            update_entry_count(idx);
00719            gtk_tree_path_free(path);
00720            break;
00721        case IM_VK_DOWN:
00722            if (gtk_tree_selection_get_selected(sel, NULL, &iter)) {
00723               path = gtk_tree_model_get_path(model, &iter);
00724               idx = gtk_tree_path_get_indices(path)[0];
00725               if ((idx + 1) >= pagemax) {
00726                   if (enditem >= (beginitem + pagemax)) {
00727                      /*
00728                       * current position in the server should be the begin of item.
00729                       */
00730                      update_dictmenu_state(im, ic, xc, 1);
00731                   }
00732                   return;
00733               }
00734               gtk_tree_path_next(path);
00735            } else {
00736               path = gtk_tree_path_new_first();
00737            }
00738            column = gtk_tree_view_get_column(GTK_TREE_VIEW(widget), 0);
00739            gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, column, FALSE);
00740            idx = gtk_tree_path_get_indices(path)[0];
00741            update_entry_count(idx);
00742            gtk_tree_path_free(path);
00743            break;
00744        case IM_VK_ENTER:
00745            update_dictmenu_state(im, ic, xc, 1);
00746            send_key_event(im, ic, xc, IM_VK_ENTER, 0, 0x0D);
00747            break;
00748        case IM_VK_SPACE:
00749            gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, &column);
00750            model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
00751            if (gtk_tree_model_get_iter(model, &iter, path)) {
00752               gtk_tree_model_get(model, &iter, 0, &use, 2, &changed, -1);
00753               use ^= 1;
00754               changed ^= 1;
00755               gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, use, 2, changed, -1);
00756            }
00757            gtk_tree_path_free(path);
00758            break;
00759        case IM_VK_BACK_SPACE:
00760            send_key_event(im, ic, xc, keycode, 0, translated);
00761            break;
00762        default:
00763            if ((modifier & IM_CTRL_MASK && keycode == IM_VK_G) ||
00764               keycode == IM_VK_ESCAPE) {
00765               /* cancel */
00766               send_key_event(im, ic, xc, IM_VK_BACK_SPACE, 0, 0x08);
00767            }
00768            break;
00769     }
00770 }
00771 
00772 static void
00773 update_server_position(int           keycode,
00774                      int           modifier,
00775                      int           translated,
00776                      int           im,
00777                      int           ic,
00778                      xaux_class_t *xc)
00779 {
00780     GtkWidget *widget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
00781     GdkEvent *eventp, *eventr;
00782     GString *str;
00783     int i;
00784 
00785     eventp = translate_key_event(keycode, modifier, TRUE);
00786     eventr = translate_key_event(keycode, modifier, FALSE);
00787 
00788     str = g_string_new(gtk_entry_get_text(GTK_ENTRY(widget)));
00789     if ((keycode == IM_VK_BACK_SPACE && str->len == 0) ||
00790        keycode == IM_VK_ESCAPE ||
00791        (keycode == IM_VK_G && modifier & IM_CTRL_MASK)) {
00792        /* cancel */
00793        send_key_event(im, ic, xc, IM_VK_BACK_SPACE, 0, 0x08);
00794     } else if (keycode == IM_VK_ENTER) {
00795        for (i = 0; i < str->len; i++) {
00796            send_key_event(im, ic, xc, str->str[i], 0, str->str[i]);
00797        }
00798        send_key_event(im, ic, xc, keycode, 0, translated);
00799     } else if (eventp->key.keyval == 0) {
00800        /* nothing here */
00801     } else {
00802        /* send pseudo key event to the widget */
00803        eventp->key.window = eventr->key.window = widget->window;
00804        if (widget->window) {
00805            g_object_ref(widget->window);
00806            g_object_ref(widget->window);
00807        }
00808        gtk_widget_event(widget, eventp);
00809        gtk_widget_event(widget, eventr);
00810     }
00811 
00812     gdk_event_free(eventp);
00813     gdk_event_free(eventr);
00814     g_string_free(str, TRUE);
00815 }
00816 
00817 static void
00818 update_wordregist_position(int           keycode,
00819                         int           modifier,
00820                         int           translated,
00821                         int           im,
00822                         int           ic,
00823                         xaux_class_t *xc)
00824 {
00825     /*
00826      * basically all of key event should be passed through cannaserver -
00827      * some keys needs to be translated, though
00828      */
00829     switch(keycode) {
00830        case IM_VK_BACK_SPACE:
00831            translated = 0x08;
00832            break;
00833        case IM_VK_ESCAPE:
00834            translated = 0x1B;
00835            break;
00836        default:
00837            if (keycode == IM_VK_G && (modifier & IM_CTRL_MASK)) {
00838               translated = '';
00839            }
00840            break;
00841     }
00842     send_key_event(im, ic, xc, keycode, modifier, translated);
00843 }
00844 
00845 static void
00846 label_keyevent(int           keycode,
00847               int           modifier,
00848               int           translated,
00849               int           im,
00850               int           ic,
00851               xaux_class_t *xc)
00852 {
00853     /*
00854      * basically all of key event should be passed through cannaserver -
00855      * some keys needs to be translated, though
00856      */
00857     switch(keycode) {
00858        case IM_VK_BACK_SPACE:
00859            translated = 0x08;
00860            break;
00861        case IM_VK_ESCAPE:
00862            translated = 0x1B;
00863            break;
00864        default:
00865            if (keycode == IM_VK_G && (modifier & IM_CTRL_MASK)) {
00866               translated = '';
00867            }
00868            break;
00869     }
00870     send_key_event(im, ic, xc, keycode, modifier, translated);
00871 }
00872 
00873 static void
00874 unknown_keyevent(int           keycode,
00875                int           modifier,
00876                int           translated,
00877                int           im,
00878                int           ic,
00879                xaux_class_t *xc)
00880 {
00881     /* always cancel */
00882     send_key_event(im, ic, xc, IM_VK_G, IM_CTRL_MASK, '');
00883 }
00884 
00885 static GdkFilterReturn
00886 event_handler(GdkXEvent *gdk_xevent,
00887               GdkEvent *event,
00888               gpointer data)
00889 {
00890     XEvent *xevent = (XEvent *)gdk_xevent;
00891 
00892     if (xevent->type == ClientMessage) {
00893        xaux_ext_process_client_message(GDK_DISPLAY(), (XClientMessageEvent *)xevent);
00894     }
00895 
00896     return GDK_FILTER_CONTINUE;
00897 }
00898 
00899 Bool
00900 xaux_ext_Draw(xaux_class_t   *xc,
00901              aux_ext_data_t *aux_ext_data)
00902 {
00903     int mode, i, len;
00904     GtkWidget *widget, *fwidget, *frame, *flabel;
00905     gchar *item, *p, *pp, *value = NULL;
00906     static gboolean update_win_pos = FALSE;
00907 
00908     ENTER;
00909 
00910     if (aux_ext_data->integer_count > 0) {
00911        mode = aux_ext_data->integer_list[INT_STATE];
00912        switch (aux_ext_data->integer_list[INT_AUXMODE]) {
00913            case AUX_UPDATE_STATE:
00914               frame = g_object_get_data(G_OBJECT(auxwindow), DATA_FRAME);
00915               flabel = gtk_frame_get_label_widget(GTK_FRAME(frame));
00916               fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_FATTACHED);
00917               widget = g_object_get_data(G_OBJECT(auxwindow), DATA_ATTACHED);
00918 
00919               /* unfocus before removing the widget */
00920               change_focus(fwidget, 0);
00921 
00922               if (widget != NULL) {
00923                   gtk_container_remove(GTK_CONTAINER(auxwindow), widget);
00924               }
00925               if (fwidget != NULL) {
00926                   gtk_container_remove(GTK_CONTAINER(frame), fwidget);
00927               }
00928               widget = NULL;
00929               fwidget = NULL;
00930 
00931               DEBUG_printf("*** mode = %d\n", mode);
00932               DEBUG_printf("*** items = %d/(%d-%d)\n",
00933                           aux_ext_data->integer_list[INT_CURPOS],
00934                           aux_ext_data->integer_list[INT_BEGINPOS],
00935                           aux_ext_data->integer_list[INT_CANDCOUNT]);
00936 
00937               switch (mode) {
00938                   case CANNA_MODE_HexMode:
00939                      if (aux_ext_data->string_count > 0) {
00940                          gchar *item;
00941 
00942                          fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
00943                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length] = 0;
00944                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length+1] = 0;
00945                          item = g_utf16_to_utf8((gunichar2 *)aux_ext_data->string_list[0].ptr, -1, NULL, NULL, NULL);
00946                          gtk_entry_set_text(GTK_ENTRY(fwidget), "");
00947                          gtk_entry_set_max_length(GTK_ENTRY(fwidget), 4);
00948                          gtk_label_set_text(GTK_LABEL(flabel), item);
00949                          g_free(item);
00950                          widget = frame;
00951                      }
00952                      break;
00953                   case CANNA_MODE_TourokuHinshiMode:
00954                   case CANNA_MODE_TourokuDicMode:
00955                      if (aux_ext_data->integer_list[INT_CANDCOUNT] == 0)
00956                          goto label;
00957                   case CANNA_MODE_ExtendMode:
00958                   menu:
00959                      if (aux_ext_data->string_count > 0) {
00960                          fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00961                          g_object_set_data(G_OBJECT(auxwindow), DATA_FTITLE, "Menu");
00962                          g_object_set_data(G_OBJECT(auxwindow),
00963                                          DATA_BEGIN_ITEM,
00964                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_BEGINPOS]));
00965                          g_object_set_data(G_OBJECT(auxwindow),
00966                                          DATA_CUR_ITEM,
00967                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_CURPOS]));
00968                          g_object_set_data(G_OBJECT(auxwindow),
00969                                          DATA_END_ITEM,
00970                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_CANDCOUNT]));
00971                          update_menu(fwidget, aux_ext_data->string_count, aux_ext_data->string_list);
00972                          move_menu_position(aux_ext_data->integer_list[INT_CURPOS]);
00973                          update_entry_count(aux_ext_data->integer_list[INT_CURPOS] - aux_ext_data->integer_list[INT_BEGINPOS]);
00974                          widget = frame;
00975                      }
00976                      break;
00977                   case CANNA_MODE_MountDicMode:
00978                      if (aux_ext_data->string_count > 0) {
00979                          fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_TREEVIEW);
00980                          g_object_set_data(G_OBJECT(auxwindow), DATA_FTITLE, "Menu");
00981                          g_object_set_data(G_OBJECT(auxwindow),
00982                                          DATA_BEGIN_ITEM,
00983                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_BEGINPOS]));
00984                          g_object_set_data(G_OBJECT(auxwindow),
00985                                          DATA_CUR_ITEM,
00986                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_CURPOS]));
00987                          g_object_set_data(G_OBJECT(auxwindow),
00988                                          DATA_END_ITEM,
00989                                          GUINT_TO_POINTER(aux_ext_data->integer_list[INT_CANDCOUNT]));
00990                          update_dictmenu(fwidget, aux_ext_data->string_count, aux_ext_data->string_list);
00991                          move_menu_position(aux_ext_data->integer_list[INT_CURPOS]);
00992                          update_entry_count(aux_ext_data->integer_list[INT_CURPOS] - aux_ext_data->integer_list[INT_BEGINPOS]);
00993                          widget = frame;
00994                      }
00995                      break;
00996                   case CANNA_MODE_ChangingServerMode:
00997                      if (aux_ext_data->string_count > 0) {
00998                          fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
00999                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length] = 0;
01000                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length+1] = 0;
01001                          item = g_utf16_to_utf8((gunichar2 *)aux_ext_data->string_list[0].ptr, -1, NULL, NULL, NULL);
01002                          /* find the value */
01003                          p = rindex(item, '[');
01004                          pp = rindex(item, ']');
01005                          if (p != NULL && pp != NULL) {
01006                             value = g_strndup(p + 1, pp - p - 1);
01007                             *p = 0;
01008                             gtk_entry_set_text(GTK_ENTRY(fwidget), value);
01009                             len = strlen(value);
01010                          } else {
01011                             len = 0;
01012                          }
01013                          gtk_entry_set_max_length(GTK_ENTRY(fwidget), 0);
01014                          gtk_frame_set_label(GTK_FRAME(frame), item);
01015                          /*
01016                           * this is bad hack. but no way to wrap it on here.
01017                           * send a request to remove the current value to cannaserver first
01018                           */
01019                          for (i = 0; i < len; i++) {
01020                             send_key_event(aux_ext_data->im,
01021                                           aux_ext_data->ic,
01022                                           xc, IM_VK_RIGHT, 0, CANNA_KEY_Right);
01023                             send_key_event(aux_ext_data->im,
01024                                           aux_ext_data->ic,
01025                                           xc, IM_VK_BACK_SPACE, 0, 0x08);
01026                          }
01027                          if (item != NULL)
01028                             g_free(item);
01029                          if (value != NULL)
01030                             g_free(value);
01031                          widget = frame;
01032                      }
01033                      break;
01034                   case CANNA_MODE_TourokuMode:
01035                      if (aux_ext_data->string_count > 0) {
01036                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length] = 0;
01037                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length+1] = 0;
01038                          item = g_utf16_to_utf8((gunichar2 *)aux_ext_data->string_list[0].ptr, -1, NULL, NULL, NULL);
01039                          p = rindex(item, '(');
01040                          if (p != NULL && strncmp(p, "(y/n)", 5) == 0) {
01041                             widget = g_object_get_data(G_OBJECT(auxwindow), DATA_LABEL);
01042                             gtk_label_set_label(GTK_LABEL(widget), item);
01043                          } else {
01044                             p = rindex(item, '[');
01045                             pp = rindex(item, ']');
01046                             if (p != NULL && pp != NULL) {
01047                                 value = g_strndup(p + 1, pp - p - 1);
01048                                 *p = 0;
01049                                 fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
01050                                 widget = frame;
01051                                 if (value != NULL)
01052                                    gtk_entry_set_text(GTK_ENTRY(fwidget), value);
01053                                 gtk_entry_set_max_length(GTK_ENTRY(fwidget), 0);
01054                                 gtk_frame_set_label(GTK_FRAME(frame), item);
01055                             } else {
01056                                 widget = g_object_get_data(G_OBJECT(auxwindow), DATA_LABEL);
01057                                 gtk_label_set_label(GTK_LABEL(widget), item);
01058                             }
01059                          }
01060                          if (value != NULL)
01061                             g_free(value);
01062                          if (item != NULL)
01063                             g_free(item);
01064                      }
01065                      break;
01066                   case CANNA_MODE_DeleteDicMode:
01067                      if (aux_ext_data->string_count > 0) {
01068                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length] = 0;
01069                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length+1] = 0;
01070                          item = g_utf16_to_utf8((gunichar2 *)aux_ext_data->string_list[0].ptr, -1, NULL, NULL, NULL);
01071                          p = rindex(item, '[');
01072                          pp = rindex(item, ']');
01073                          if (p != NULL && pp != NULL) {
01074                             value = g_strndup(p + 1, pp - p - 1);
01075                             *p = 0;
01076                             fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_ENTRY);
01077                             widget = frame;
01078                             if (value != NULL)
01079                                 gtk_entry_set_text(GTK_ENTRY(fwidget), value);
01080                             gtk_entry_set_max_length(GTK_ENTRY(fwidget), 0);
01081                             gtk_frame_set_label(GTK_FRAME(frame), item);
01082                          } else if (aux_ext_data->integer_list[INT_CANDCOUNT] > 0) {
01083                             g_free(item);
01084                             goto menu;
01085                          } else {
01086                             widget = g_object_get_data(G_OBJECT(auxwindow), DATA_LABEL);
01087                             gtk_label_set_label(GTK_LABEL(widget), item);
01088                          }
01089                          if (value != NULL)
01090                             g_free(value);
01091                          if (item != NULL)
01092                             g_free(item);
01093                      }
01094                      break;
01095                   case CANNA_MODE_HenkanMethodMode:
01096                      widget = g_object_get_data(G_OBJECT(auxwindow), DATA_LABEL);
01097                      gtk_label_set_label(GTK_LABEL(widget), "not implemented yet. please hit any key to be back");
01098                      break;
01099                   default:
01100                   label:
01101                      if (aux_ext_data->string_count > 0) {
01102                          widget = g_object_get_data(G_OBJECT(auxwindow), DATA_LABEL);
01103                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length] = 0;
01104                          aux_ext_data->string_list[0].ptr[aux_ext_data->string_list[0].length+1] = 0;
01105                          item = g_utf16_to_utf8((gunichar2 *)aux_ext_data->string_list[0].ptr, -1, NULL, NULL, NULL);
01106                          gtk_label_set_label(GTK_LABEL(widget), item);
01107                          g_free(item);
01108                      }
01109                      break;
01110               }
01111               if (fwidget != NULL) {
01112                   gtk_container_add(GTK_CONTAINER(frame), fwidget);
01113                   change_focus(fwidget, 1);
01114               }
01115               if (widget != NULL) {
01116                   gtk_container_add(GTK_CONTAINER(auxwindow), widget);
01117                   if (!update_win_pos) {
01118                      set_position(auxwindow);
01119                      update_win_pos = TRUE;
01120                   }
01121                   gtk_widget_show_all(auxwindow);
01122               } else {
01123                   gtk_widget_hide_all(auxwindow);
01124                   update_win_pos = FALSE;
01125               }
01126               g_object_set_data(G_OBJECT(auxwindow), DATA_FATTACHED, fwidget);
01127               g_object_set_data(G_OBJECT(auxwindow), DATA_ATTACHED, widget);
01128               break;
01129            case AUX_UPDATE_KEY:
01130               switch (mode) {
01131                   case CANNA_MODE_HexMode:
01132                      update_codeinput_position(aux_ext_data->integer_list[INT_KEYCODE],
01133                                             aux_ext_data->integer_list[INT_KEYMOD],
01134                                             aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01135                                             aux_ext_data->im,
01136                                             aux_ext_data->ic,
01137                                             xc);
01138                      break;
01139                   case CANNA_MODE_ExtendMode:
01140                   case CANNA_MODE_TourokuHinshiMode:
01141                      if (aux_ext_data->integer_list[INT_CANDCOUNT] == 0) {
01142                          label_keyevent(aux_ext_data->integer_list[INT_KEYCODE],
01143                                       aux_ext_data->integer_list[INT_KEYMOD],
01144                                       aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01145                                       aux_ext_data->im,
01146                                       aux_ext_data->ic,
01147                                       xc);
01148                          break;
01149                      }
01150                   case CANNA_MODE_TourokuDicMode:
01151                      update_menu_position(aux_ext_data->integer_list[INT_KEYCODE],
01152                                         aux_ext_data->integer_list[INT_KEYMOD],
01153                                         aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01154                                         aux_ext_data->im,
01155                                         aux_ext_data->ic,
01156                                         xc, (mode == CANNA_MODE_TourokuHinshiMode ? FALSE : TRUE));
01157                      break;
01158                   case CANNA_MODE_MountDicMode:
01159                      update_dictmenu_position(aux_ext_data->integer_list[INT_KEYCODE],
01160                                            aux_ext_data->integer_list[INT_KEYMOD],
01161                                            aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01162                                            aux_ext_data->im,
01163                                            aux_ext_data->ic,
01164                                            xc);
01165                      break;
01166                   case CANNA_MODE_ChangingServerMode:
01167                      update_server_position(aux_ext_data->integer_list[INT_KEYCODE],
01168                                           aux_ext_data->integer_list[INT_KEYMOD],
01169                                           aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01170                                           aux_ext_data->im,
01171                                           aux_ext_data->ic,
01172                                           xc);
01173                      break;
01174                   case CANNA_MODE_TourokuMode:
01175                      update_wordregist_position(aux_ext_data->integer_list[INT_KEYCODE],
01176                                              aux_ext_data->integer_list[INT_KEYMOD],
01177                                              aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01178                                              aux_ext_data->im,
01179                                              aux_ext_data->ic,
01180                                              xc);
01181                      break;
01182                   case CANNA_MODE_DeleteDicMode:
01183                      if (aux_ext_data->integer_list[INT_CANDCOUNT] == 0) {
01184                          update_wordregist_position(aux_ext_data->integer_list[INT_KEYCODE],
01185                                                  aux_ext_data->integer_list[INT_KEYMOD],
01186                                                  aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01187                                                  aux_ext_data->im,
01188                                                  aux_ext_data->ic,
01189                                                  xc);
01190                      } else {
01191                          update_menu_position(aux_ext_data->integer_list[INT_KEYCODE],
01192                                            aux_ext_data->integer_list[INT_KEYMOD],
01193                                            aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01194                                            aux_ext_data->im,
01195                                            aux_ext_data->ic,
01196                                            xc, TRUE);
01197                      }
01198                      break;
01199                   case CANNA_MODE_HenkanMethodMode:
01200                      unknown_keyevent(aux_ext_data->integer_list[INT_KEYCODE],
01201                                     aux_ext_data->integer_list[INT_KEYMOD],
01202                                     aux_ext_data->integer_list[INT_TRANSLATEDCODE],
01203                                     aux_ext_data->im,
01204                                     aux_ext_data->ic,
01205                                     xc);
01206                      break;
01207                   default:
01208                      break;
01209               }
01210               break;
01211            case AUX_FOCUS_CHANGE:
01212               fwidget = g_object_get_data(G_OBJECT(auxwindow), DATA_FATTACHED);
01213               change_focus(fwidget, aux_ext_data->integer_list[INT_STATE]);
01214               if (aux_ext_data->integer_list[INT_STATE] == 0) {
01215                   gtk_widget_hide_all(auxwindow);
01216               }
01217               break;
01218            case AUX_FORCE_SAVE_STATE:
01219               switch (aux_ext_data->integer_list[INT_STATE]) {
01220                   case CANNA_MODE_HexMode:
01221                   case CANNA_MODE_ExtendMode:
01222                   case CANNA_MODE_MountDicMode:
01223                   case CANNA_MODE_ChangingServerMode:
01224                   case CANNA_MODE_HenkanMethodMode:
01225                   case CANNA_MODE_DeleteDicMode:
01226                   case CANNA_MODE_TourokuHinshiMode:
01227                   case CANNA_MODE_TourokuDicMode:
01228                      /* FIXME: imlement me */
01229                      break;
01230                   case CANNA_MODE_TourokuMode:
01231                      break;
01232                   default:
01233                      break;
01234               }
01235               break;
01236        }
01237     } else {
01238        gtk_widget_hide_all(auxwindow);
01239     }
01240 
01241     LEAVE;
01242 
01243     return True;
01244 }
01245 
01246 Bool
01247 xaux_ext_Done(xaux_class_t   *xc,
01248              aux_ext_data_t *aux_ext_data)
01249 {
01250 #if 0
01251     gtk_main_quit();
01252 #endif
01253 
01254     return True;
01255 }
01256 
01257 int
01258 main(int argc, char **argv)
01259 {
01260     GtkWidget *frame;
01261     GtkWidget *treeview;
01262     GtkWidget *label;
01263     GtkWidget *entry;
01264     GtkWidget *flabel;
01265 
01266     ENTER;
01267 
01268     gtk_init(&argc, &argv);
01269 
01270     auxwindow = gtk_window_new(GTK_WINDOW_POPUP);
01271     gtk_window_set_policy(GTK_WINDOW(auxwindow), TRUE, TRUE, FALSE);
01272     gtk_window_set_resizable(GTK_WINDOW(auxwindow), FALSE);
01273     gtk_window_set_modal(GTK_WINDOW(auxwindow), TRUE);
01274     gtk_widget_add_events(auxwindow, GDK_BUTTON_PRESS_MASK);
01275     gtk_widget_add_events(auxwindow, GDK_BUTTON_RELEASE_MASK);
01276     gtk_widget_add_events(auxwindow, GDK_KEY_PRESS_MASK);
01277     gtk_widget_add_events(auxwindow, GDK_KEY_RELEASE_MASK);
01278     gtk_widget_add_events(auxwindow, GDK_POINTER_MOTION_MASK);
01279     gtk_container_set_border_width(GTK_CONTAINER(auxwindow), 2);
01280 
01281     gtk_window_set_accept_focus(GTK_WINDOW(auxwindow), FALSE);
01282     gtk_widget_realize(auxwindow);
01283     gtk_window_set_accept_focus(GTK_WINDOW(auxwindow), FALSE);
01284 
01285     /* for debug */
01286     label = gtk_label_new(NULL);
01287 
01288     /* for frame */
01289     frame = gtk_frame_new(NULL);
01290     flabel = gtk_label_new(NULL);
01291     gtk_frame_set_label_widget(GTK_FRAME(frame), flabel);
01292     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
01293 
01294     /* for menu */
01295     treeview = gtk_tree_view_new();
01296     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
01297     gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview));
01298     gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
01299 
01300     /* for entry */
01301     entry = gtk_entry_new();
01302 
01303     /* do g_object_ref() to avoid destroying the object after gtk_container_remove() */
01304     g_object_ref(G_OBJECT(label));
01305     g_object_ref(G_OBJECT(frame));
01306     g_object_ref(G_OBJECT(treeview));
01307     g_object_ref(G_OBJECT(entry));
01308 
01309     /* store the widgets into auxwindow's data */
01310     g_object_set_data(G_OBJECT(auxwindow), DATA_LABEL, (gpointer)label);
01311     g_object_set_data(G_OBJECT(auxwindow), DATA_FRAME, (gpointer)frame);
01312     g_object_set_data(G_OBJECT(auxwindow), DATA_TREEVIEW, (gpointer)treeview);
01313     g_object_set_data(G_OBJECT(auxwindow), DATA_ENTRY, (gpointer)entry);
01314     g_object_set_data(G_OBJECT(auxwindow), DATA_ATTACHED, (gpointer)NULL);
01315     g_object_set_data(G_OBJECT(auxwindow), DATA_FATTACHED, (gpointer)NULL);
01316 
01317     /* register aux class */
01318     xaux_ext_init_classes(GDK_DISPLAY(), &xaux_class, GDK_WINDOW_XWINDOW(auxwindow->window));
01319 
01320     gdk_window_add_filter(auxwindow->window, event_handler, NULL);
01321 
01322     g_signal_connect(G_OBJECT(auxwindow),
01323                    "destroy", gtk_main_quit, NULL);
01324     g_signal_connect(G_OBJECT(auxwindow),
01325                    "delete-event", gtk_main_quit, NULL);
01326 
01327     gtk_main();
01328 
01329     LEAVE;
01330 
01331     return 0;
01332 }
01333