Back to index

im-sdk  12.3.91
gtkiiimwin.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 
00004 #ifdef HAVE_CONFIG_H
00005 #include "config.h"
00006 #endif
00007 
00008 #include "gtkiiimwin.h"
00009 #include "gtkflatbutton.h"
00010 #include "imlabel.h"
00011 
00012 #define MAX_CANDIDATE_COUNT  32
00013 #define MAX_LABELSTRING_LEN  (8*1024)
00014 
00015 #define WINDOW_GAP_VERTICAL    2
00016 #define WINDOW_GAP_HORIZENTAL  2
00017 
00018 #define MIN_PREEDIT_WIDTH      160
00019 //for horizental display
00020 #define MIN_CANDIDATES_WIDTH   200
00021 //for vertical display
00022 #define MIN_CANDIDATES_HEIGHT  120
00023 
00024 #define _(a)  (a)
00025 
00026 typedef struct {
00027     GtkWidget *             iiimPCWinSysMenu;
00028     GSList *                RootWindow_group;
00029     GtkWidget *             RootWindow;
00030     GtkWidget *             ClassicCompositeFollow;
00031     GtkWidget *             TraditionalStyle;
00032     GtkWidget *             ModernCanidatesHorizental;
00033     GtkWidget *             CustomizeStyle;
00034     GtkWidget *             _________1;
00035     GtkWidget *                 ShowSystemMenu;
00036     GtkWidget *                 FollowCursor;
00037     GtkWidget *                 GroupPreeditCandidates;
00038     GtkWidget *             _________2;
00039     GtkWidget *                 CandidatesDirection;
00040     GtkWidget *                 CandidatesDirection_menu;
00041     GSList *                        CandidatesHorizental_group;
00042     GtkWidget *                     CandidatesHorizental;
00043     GtkWidget *                     CandidatesVertical;
00044     GtkWidget *                 CandidateTitlePosition;
00045     GtkWidget *                 CandidateTitlePosition_menu;
00046     GSList *                        AboveCandidates_group;
00047     GtkWidget *                     AboveCandidates;
00048     GtkWidget *                     BelowCandidates;
00049     GtkWidget *                 CandidatesPosition;
00050     GtkWidget *                 CandidatesPosition_menu;
00051     GSList *                        CandidatesFollowIme_group;
00052     GtkWidget *                     CandidatesFollowIme;
00053     GtkWidget *                     CandidatesStickPreedit;
00054     GtkWidget *                     CandidatesFollowCaret;
00055     GtkWidget *                     CandidatesRight2Preedit;
00056     GtkWidget *             _________3;
00057     GtkWidget *                 ShowPageControl;
00058     GtkWidget *                 IgnorCandidatesTitle;
00059 } TPCOptionMenu;
00060 
00061 typedef struct _tagRealIIimPCWin {
00062     TPCStyleOption  style;
00063 
00064     TPCOptionMenu*  pMenu;
00065     int             poping_up;
00066 
00067     GtkWidget*      dragging_area;
00068     GtkWidget*      preeditWin;
00069     GtkWidget*      preeditLabel;
00070 
00071     GtkWidget*      candidatesWin;
00072     GtkWidget*      candidatesTitleLabel;
00073     GtkWidget*      candidatesLabels[MAX_CANDIDATE_COUNT];
00074 
00075     GtkWidget*      sysMenuButton;
00076     GtkWidget*      buttonPageRequest[4];
00077 
00078     GtkWidget*      pageButtonBox;
00079     GtkWidget*      candidatesPackBox;
00080     GtkWidget*      candidatesTitleBox;
00081 
00082     int             cursor_x, cursor_y, cursor_w, cursor_h;
00083     int             preeditShow, preeditRealShow;
00084     int             preeditCaret;
00085     int             preeditCandidateCaret;
00086     char            bufPreedit[MAX_LABELSTRING_LEN];
00087 
00088     int             candidatesCount;
00089     int             candidatesShow, candidatesRealShow;
00090     char            bufCandidateTitle[MAX_LABELSTRING_LEN];
00091     char            bufCandidates[MAX_CANDIDATE_COUNT][MAX_LABELSTRING_LEN];
00092 
00093     TIIimPCWinCallback  process_style_change;
00094     TIIimPCWinCallback  process_page_request;
00095     TIIimPCWinCallback  process_select_request;
00096     TIIimPCWinCallback  process_position_change;
00097 
00098     int             firstCandidat, currentCandidateInWindow, totalCandidates;
00099     int             dragging, drag_x_start, drag_y_start, drag_x_save, drag_y_save;
00100 } TRealIIimPCWin;
00101 
00102 static GdkCursor*       s_moving_cursor = NULL;
00103 
00104 static GdkCursor*
00105 getMovingCursor(void)
00106 {
00107     if (s_moving_cursor == NULL) {
00108         s_moving_cursor = gdk_cursor_new(GDK_FLEUR);
00109         gdk_cursor_ref(s_moving_cursor);
00110     }
00111     return s_moving_cursor;
00112 }
00113 
00114 static TPCOptionMenu*   create_iiimPCWinSysMenu (TRealIIimPCWin* pc);
00115 static void             getPreeditBox(TRealIIimPCWin* pc, int idx, int *px, int *py, int *pw, int *ph);
00116 static void             updateMenuStates(TRealIIimPCWin* pc);
00117 static void             updateMenuActivates(TRealIIimPCWin* pc);
00118 static void           adjustCandidateWindow(TRealIIimPCWin* pc, int candx, int candy, int candw, int candh);
00119 static int            adjustPCWindows(TRealIIimPCWin* pc, int predx, int predy, int predw, int predh);
00120 static void             updatePreeditData(TIIimPCWin vpc, const char* label, int caret, int candidate_start, int nfbs, ImeFeedbackRec* fbs);
00121 static void             updateCandidatesData(TIIimPCWin vpc, int num, const char* candidates[], const char* title,
00122                                              int firstIdx, int focusIdx, int total,
00123                                              int *p_fb_counts, ImeFeedbackRec **pfbs);
00124 
00125 static gboolean         onMouseButtonPress(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
00126 static gboolean         onWindowPointerMove(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
00127 static gboolean         onMouseButtonRelease(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
00128 
00129 static gboolean         on_SystemMenu_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
00130 
00131 static TPCStyleAtomic predefinedStyles[] = {
00132   { // PC_STYLE_CUSTOM
00133       1,      /* showSystemBar */
00134       1,      /* followCursor */
00135       0,      /* composite */
00136       1,      /* showPageControl */
00137       1,      /* ignoreCandidateTitle */
00138       0,      /* candidateVertical */
00139       CANDIDATES_POSITION_IME,      /* candidatePosition */
00140       TITLE_ABOVE_CANDIDATES
00141   },
00142 
00143   { //PC_STYLE_ROOT
00144       1,      /* showSystemBar */
00145       0,      /* followCursor */
00146       1,      /* composite */
00147       1,      /* showPageControl */
00148       0,      /* ignoreCandidateTitle */
00149       0,      /* candidateVertical */
00150       CANDIDATES_POSITION_PREEDIT_STARTS,   /* candidatePosition */
00151       TITLE_ABOVE_CANDIDATES                /* candidateTitlePosition */
00152   },
00153 
00154   { //PC_STYLE_CLASSIC
00155       1,      /* showSystemBar */
00156       1,      /* followCursor */
00157       1,      /* composite */
00158       1,      /* showPageControl */
00159       1,      /* ignoreCandidateTitle */
00160       0,      /* candidateVertical */
00161       CANDIDATES_POSITION_PREEDIT_STARTS,   /* candidatePosition */
00162       TITLE_ABOVE_CANDIDATES                /* candidateTitlePosition */
00163   },
00164 
00165   { //PC_STYLE_TRADITIONAL
00166       1,      /* showSystemBar */
00167       1,      /* followCursor */
00168       0,      /* composite */
00169       1,      /* showPageControl */
00170       0,      /* ignoreCandidateTitle */
00171       1,      /* candidateVertical */
00172       CANDIDATES_POSITION_PREEDIT_RIGHT,    /* candidatePosition */
00173       TITLE_ABOVE_CANDIDATES                /* candidateTitlePosition */
00174   },
00175 
00176   { //PC_STYLE_MODERN
00177       1,      /* showSystemBar */
00178       1,      /* followCursor */
00179       0,      /* composite */
00180       1,      /* showPageControl */
00181       1,      /* ignoreCandidateTitle */
00182       0,      /* candidateVertical */
00183       CANDIDATES_POSITION_IME,              /* candidatePosition */
00184       TITLE_BELOW_CANDIDATES                /* candidateTitlePosition */
00185   }
00186 };
00187 
00188 static const char *pgop_icon_horizental_names[] = {
00189   "LeftMostTriangle.png",
00190   "LeftTriangle.png",
00191   "RightTriangle.png",
00192   "RightMostTriangle.png"
00193 };
00194 
00195 static const char *pgop_icon_vertical_names[] = {
00196   "UpMostTriangle.png",
00197   "UpTriangle.png",
00198   "DownTriangle.png",
00199   "DownMostTriangle.png"
00200 };
00201 
00202 static const char *pgop_desc[] = {
00203     "First Page",
00204     "Prev Page",
00205     "Next Page",
00206     "Last Page"
00207 };
00208 
00209 static TPCStyleAtomic*
00210 pc_get_atomic_style(TRealIIimPCWin *pc)
00211 {
00212     TPCStyleAtomic* prs=NULL;
00213 
00214     if (pc->style.type > PC_STYLE_CUSTOM && pc->style.type <= PC_STYLE_MODERN) {
00215         prs = &predefinedStyles[pc->style.type];
00216     } else {
00217         prs = &pc->style.customOption;
00218     }
00219     return prs;
00220 }
00221 
00222 static int
00223 get_pc_candidates_position(TRealIIimPCWin *pc)
00224 {
00225     return pc_get_atomic_style(pc)->candidatePosition;
00226 }
00227 
00228 static int
00229 is_pc_candidates_vertical(TRealIIimPCWin *pc)
00230 {
00231     TPCStyleAtomic* prs = pc_get_atomic_style(pc);
00232     return (!prs->composite && prs->candidateVertical);
00233 }
00234 
00235 static int
00236 is_pc_show_page_buttons(TRealIIimPCWin *pc)
00237 {
00238     return pc_get_atomic_style(pc)->showPageControl;
00239 }
00240 
00241 static int
00242 is_pc_show_candidates_title(TRealIIimPCWin *pc)
00243 {
00244     return !(pc_get_atomic_style(pc)->ignoreCandidateTitle);
00245 }
00246 
00247 static
00248 is_pc_show_sys_button(TRealIIimPCWin *pc)
00249 {
00250   return pc_get_atomic_style(pc)->showSystemBar;
00251 }
00252 
00253 static int
00254 is_pc_follow_cursor(TRealIIimPCWin *pc)
00255 {
00256     return pc_get_atomic_style(pc)->followCursor;
00257 }
00258 
00259 static int
00260 is_pc_candidates_title_left_or_upper(TRealIIimPCWin *pc)
00261 {
00262     TPCStyleAtomic* prs = pc_get_atomic_style(pc);
00263     return ((!prs->composite) && (prs->candidateTitlePosition == TITLE_LEFT2_CANDIDATES));
00264 }
00265 
00266 static int
00267 is_pc_composite(TRealIIimPCWin *pc)
00268 {
00269     return (pc_get_atomic_style(pc)->composite);
00270 }
00271 
00272 static gboolean
00273 on_PageRequest_press_event             (GtkWidget       *widget,
00274                                         GdkEventButton  *event,
00275                                         gpointer         user_data)
00276 {
00277     int pgop;
00278     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00279 
00280     if (pc) {
00281         /*
00282         if (!is_pc_composite(pc)) {
00283             gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), TRUE); //make sure window size do not decrease
00284         }
00285         if (!is_pc_composite(pc) && !is_pc_candidates_vertical(pc)) {
00286             gtk_window_set_resizable(GTK_WINDOW(pc->candidatesWin), TRUE); //make sure window size do not decrease
00287         }
00288         */
00289 
00290         for (pgop=PC_PAGE_FIRST; pgop <= PC_PAGE_LAST; ++pgop) {
00291             if (widget == pc->buttonPageRequest[pgop]) {
00292                 DEBUG_printf("%s Requested\n", pgop_desc[pgop]);
00293                 if (pc->process_page_request != NULL)
00294                     pc->process_page_request(pc, pgop);
00295             }
00296         }
00297     }
00298 }
00299 
00300 static void
00301 pc_draw_dragging_frame(TRealIIimPCWin *pc, int pos_x, int pos_y, int w, int h)
00302 {
00303     GdkGC *xor_gc;
00304     GdkGCValues values;
00305     GdkWindow *root_window;
00306 
00307     values.foreground = (pc->preeditWin->style->white);
00308 
00309     values.function = GDK_XOR;
00310     values.subwindow_mode = GDK_INCLUDE_INFERIORS;
00311 
00312     root_window = gtk_widget_get_root_window (pc->preeditWin);
00313 
00314     xor_gc = gdk_gc_new_with_values (root_window, &values,
00315                                      GDK_GC_FOREGROUND | GDK_GC_FUNCTION | GDK_GC_SUBWINDOW);
00316 
00317     gdk_draw_rectangle (root_window, xor_gc, FALSE, pos_x, pos_y, w, h);
00318     gdk_gc_unref (xor_gc);
00319 }
00320 
00321 static void
00322 pcDraggingMove(TRealIIimPCWin *pc, GdkEventMotion *event)
00323 {
00324     int predx, predy, predw, predh;
00325 
00326     predx = pc->drag_x_start;
00327     predy = pc->drag_y_start;
00328     predw = pc->preeditWin->allocation.width;
00329     predh = pc->preeditWin->allocation.height;
00330 
00331     /* remove the old dragging frame */
00332     pc_draw_dragging_frame(pc, predx, predy, predw, predh);
00333 
00334     /* draw the new dragging frame */
00335     predx += (event->x_root - pc->drag_x_save);
00336     predy += (event->y_root - pc->drag_y_save);
00337     pc_draw_dragging_frame(pc, predx, predy, predw, predh);
00338 
00339     /* save the curent dragging pointer position */
00340     pc->drag_x_start = predx;
00341     pc->drag_y_start = predy;
00342     pc->drag_x_save = event->x_root;
00343     pc->drag_y_save = event->y_root;
00344 }
00345 
00346 static void
00347 pcDraggingEnd(TRealIIimPCWin *pc, GdkEventButton* event)
00348 {
00349     int predx, predy, predw, predh, styleChange = 0;
00350     TPCStyleOption pcstyle = pc->style;
00351 
00352     gdk_pointer_ungrab(event->time);
00353 
00354     predx = pc->drag_x_start;
00355     predy = pc->drag_y_start;
00356     predw = pc->preeditWin->allocation.width;
00357     predh = pc->preeditWin->allocation.height;
00358 
00359     /* remove the old dragging frame */
00360     pc_draw_dragging_frame(pc, predx, predy, predw, predh);
00361 
00362     predx += (event->x_root - pc->drag_x_save);
00363     predy += (event->y_root - pc->drag_y_save);
00364 
00365     movePreedit(pc, predx, predy - WINDOW_GAP_VERTICAL - 10, 1, 10);
00366 
00367     if (pc->style.type != PC_STYLE_CUSTOM ||
00368             (pc->style.type != PC_STYLE_ROOT && pc->style.customOption.followCursor != 0)) {
00369 
00370         if (pc->style.type > PC_STYLE_CUSTOM && pc->style.type <= PC_STYLE_MODERN) {
00371             pcstyle.customOption = predefinedStyles[pc->style.type];
00372         }
00373         pcstyle.type = PC_STYLE_CUSTOM;
00374         pcstyle.customOption.followCursor = 0;
00375         styleChange = 1;
00376     }
00377 
00378     if (pc->process_position_change)
00379         pc->process_position_change(pc, 0);
00380     if (styleChange && pc->process_style_change)
00381          pc->process_style_change(pc, (int)&pcstyle);
00382 }
00383 
00384 static void
00385 pcDraggingBegin(TRealIIimPCWin *pc, GdkEventButton* event)
00386 {
00387     int predx, predy, predw, predh;
00388 
00389     gtk_window_get_position(GTK_WINDOW(pc->preeditWin), &predx, &predy);
00390     predw = pc->preeditWin->allocation.width;
00391     predh = pc->preeditWin->allocation.height;
00392 
00393     /* begin dragging */
00394     pc->drag_x_start = predx;
00395     pc->drag_y_start = predy;
00396     pc->drag_x_save  = event->x_root;
00397     pc->drag_y_save  = event->y_root;
00398 
00399     /* Grab the cursor to prevent losing events. */
00400     gdk_pointer_grab (pc->preeditWin->window,
00401                       FALSE,
00402                       GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
00403                       NULL,
00404                       getMovingCursor(),
00405                       event->time);
00406 
00407     pc_draw_dragging_frame(pc, predx, predy, predw, predh);
00408 }
00409 
00410 static gboolean
00411 onMouseButtonPress(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
00412 {
00413     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00414 
00415     if (pc &&  event->button <= 1) {
00416         DEBUG_printf("Dragging start from position (%lf, %lf)\n", event->x_root, event->y_root);
00417         pc->dragging = 1;
00418         pcDraggingBegin(pc, event);
00419     } else if (pc) {
00420         on_SystemMenu_press_event(widget, event, user_data); //poping_up on right click
00421     }
00422 
00423     return FALSE;
00424 }
00425 
00426 static gboolean
00427 onWindowPointerMove(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
00428 {
00429     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00430     if (pc) {
00431         if ((event->state & GDK_BUTTON1_MASK) != 0 && pc->dragging) {
00432             DEBUG_printf("PC Dragging to new position (%lf, %lf)\n", event->x_root, event->y_root);
00433             pcDraggingMove(pc, event);
00434         }
00435         return TRUE;
00436     }
00437     return FALSE;
00438 }
00439 
00440 static gboolean
00441 onMouseButtonRelease(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
00442 {
00443     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00444     if (pc && event->button <= 1) {
00445         DEBUG_printf("PC Dragging end at position (%lf, %lf)\n", event->x_root, event->y_root);
00446         if (pc->dragging != 0) {
00447             pc->dragging = 0;
00448             pcDraggingEnd(pc, event);
00449             return TRUE;
00450         }
00451     }
00452     return FALSE;
00453 }
00454 
00455 static gboolean
00456 on_DraggingArea_expose_event           (GtkWidget       *widget,
00457                                         GdkEventExpose  *event,
00458                                         gpointer         user_data)
00459 {
00460   int left, right, top, bottom;
00461   GdkColor lightcolor = {0, 255*256, 255*256, 255*256};
00462   GdkColor darkcolor = {0, 32*256, 32*256, 32*256};
00463   GdkGCValues gcvalues;
00464 
00465   g_return_val_if_fail (widget != NULL, FALSE);
00466   g_return_val_if_fail (event != NULL, FALSE);
00467 
00468   if (event->count > 0) return FALSE;
00469 
00470   gdk_window_clear_area (widget->window,
00471                          0,
00472                          0,
00473                          widget->allocation.width,
00474                          widget->allocation.height);
00475 
00476   gdk_gc_get_values  ( widget->style->fg_gc[widget->state], &gcvalues);
00477 
00478   gdk_window_clear_area (widget->window,
00479                          0,
00480                          0,
00481                          widget->allocation.width,
00482                          widget->allocation.height);
00483 
00484 
00485      left = widget->allocation.width/2 - 3;
00486      right = widget->allocation.width/2;
00487      for (; left <= right; left += 3) {
00488          top = 2;
00489          bottom = widget->allocation.height - 3;
00490          for (; top <= bottom; top += 3 ) {
00491              gdk_gc_set_rgb_fg_color ( widget->style->fg_gc[widget->state], &lightcolor );
00492              gdk_draw_line (widget->window,
00493                             widget->style->fg_gc[widget->state],
00494                             left, top, left, top);
00495              gdk_gc_set_rgb_fg_color ( widget->style->fg_gc[widget->state], &darkcolor );
00496              gdk_draw_line (widget->window,
00497                             widget->style->fg_gc[widget->state],
00498                             left+1, top+1, left+1, top+1);
00499          }
00500      }
00501 
00502   gdk_gc_set_values  ( widget->style->fg_gc[widget->state],  &gcvalues, GDK_GC_FOREGROUND);
00503     /*
00504      gdk_draw_line (widget->window,
00505                     widget->style->fg_gc[widget->state],
00506                     widget->allocation.width/2,
00507                     2,
00508                     widget->allocation.width/2,
00509                     widget->allocation.height-2);
00510     */
00511 
00512 }
00513 
00514 
00515 static gboolean
00516 on_OuterFrame_expose_event             (GtkWidget       *widget,
00517                                         GdkEventExpose  *event,
00518                                         gpointer         user_data)
00519 {
00520   GdkGCValues gcvalues;
00521   //GdkColor linecolor = {0, 155*256, 174*256, 185*256};
00522   GdkColor linecolor = {0, 78*256, 87*256, 93*256};
00523   GdkColor lightcolor = {0, 245*256, 244*256, 237*256};
00524   GdkColor darkcolor = {0, 166*256, 166*256, 152*256};
00525   //GdkColor darkcolor = {0, 196*256, 196*256, 184*256};
00526 
00527   g_return_val_if_fail (widget != NULL, FALSE);
00528   g_return_val_if_fail (event != NULL, FALSE);
00529 
00530   if (event->count > 0) return FALSE;
00531 
00532   gdk_window_clear_area (widget->window,
00533                          0,
00534                          0,
00535                          widget->allocation.width,
00536                          widget->allocation.height);
00537 
00538   gdk_gc_get_values  ( widget->style->fg_gc[widget->state], &gcvalues);
00539   gdk_gc_set_rgb_fg_color ( widget->style->fg_gc[widget->state], &linecolor );
00540 
00541   gdk_draw_rectangle (widget->window,
00542                  widget->style->fg_gc[widget->state],
00543                  FALSE,
00544                  0,
00545                  0,
00546                  widget->allocation.width-1,
00547                  widget->allocation.height-1);
00548 
00549   gdk_gc_set_rgb_fg_color ( widget->style->fg_gc[widget->state], &lightcolor );
00550 
00551   gdk_draw_line (widget->window,
00552                  widget->style->fg_gc[widget->state],
00553                  1,
00554                  1,
00555                  widget->allocation.width-2,
00556                  1);
00557 
00558   gdk_draw_line (widget->window,
00559                  widget->style->fg_gc[widget->state],
00560                  1,
00561                  1,
00562                  1,
00563                  widget->allocation.height-2);
00564 
00565   gdk_gc_set_rgb_fg_color ( widget->style->fg_gc[widget->state], &darkcolor );
00566 
00567   gdk_draw_line (widget->window,
00568                  widget->style->fg_gc[widget->state],
00569                  widget->allocation.width-2,
00570                  1,
00571                  widget->allocation.width-2,
00572                  widget->allocation.height-2);
00573 
00574   gdk_draw_line (widget->window,
00575                  widget->style->fg_gc[widget->state],
00576                  1,
00577                  widget->allocation.height-2,
00578                  widget->allocation.width-2,
00579                  widget->allocation.height-2);
00580 
00581   gdk_gc_set_values  ( widget->style->fg_gc[widget->state],  &gcvalues, GDK_GC_FOREGROUND);
00582 
00583   return FALSE;
00584 }
00585 
00586 static gboolean
00587 on_SystemMenu_press_event              (GtkWidget       *widget,
00588                                         GdkEventButton  *event,
00589                                         gpointer         user_data)
00590 {
00591     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00592     if (pc) {
00593         if (event->type == GDK_BUTTON_PRESS) {
00594             if (pc->pMenu == NULL)
00595                 pc->pMenu = create_iiimPCWinSysMenu(pc);
00596 
00597             GdkEventButton *bevent = (GdkEventButton *) event;
00598             pc->poping_up = 0;
00599             updateMenuActivates(pc);
00600             updateMenuStates(pc);
00601             pc->poping_up = 1;
00602             gtk_menu_popup (GTK_MENU (pc->pMenu->iiimPCWinSysMenu),
00603                             NULL, NULL, NULL, NULL,
00604                             bevent->button, bevent->time);
00605 
00606             return TRUE;
00607         }
00608     }
00609 
00610     return FALSE;
00611 }
00612 
00613 
00614 static gboolean
00615 on_Candidate_press_event               (GtkWidget       *widget,
00616                                         GdkEventButton  *event,
00617                                         gpointer         user_data)
00618 {
00619     int i;
00620     TRealIIimPCWin *pc = (TRealIIimPCWin*)user_data;
00621 
00622     if (pc) {
00623         for (i=0; i < pc-> candidatesCount; ++i) {
00624             if (pc->candidatesLabels[i] == widget) {
00625                 DEBUG_printf("Candidate #%d selected\n", i);
00626                 if (pc->process_select_request != NULL)
00627                     pc->process_select_request(pc, i);
00628             }
00629         }
00630     }
00631 }
00632 
00633 static void
00634 pc_create_sys_button_dragging_area(TRealIIimPCWin* pc, GtkWidget* parent_box)
00635 {
00636     GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
00637     gtk_box_pack_start (GTK_BOX(parent_box), vbox, FALSE, FALSE, 0);
00638     gtk_widget_show(vbox);
00639 
00640         pc->sysMenuButton = gtk_flat_button_new ();
00641         gtk_box_pack_start (GTK_BOX (vbox), pc->sysMenuButton, FALSE, FALSE, 0);
00642         gtk_flat_button_set_alignment(GTK_FLAT_BUTTON(pc->sysMenuButton), 0.5, 0.5);
00643         GTK_WIDGET_UNSET_FLAGS (pc->sysMenuButton, GTK_CAN_FOCUS);
00644         if (is_pc_show_sys_button(pc)) gtk_widget_show(pc->sysMenuButton);
00645 
00646             GtkWidget* imageSysMenuButton = (GtkWidget *)create_pixmap(pc->preeditWin, "SysBar.png");
00647             gtk_container_add (GTK_CONTAINER (pc->sysMenuButton), imageSysMenuButton);
00648             gtk_misc_set_padding(GTK_MISC(imageSysMenuButton), 0, 0);
00649             gtk_widget_show(imageSysMenuButton);
00650             g_signal_connect ((gpointer) pc->sysMenuButton, "button_press_event", G_CALLBACK (on_SystemMenu_press_event), pc);
00651 
00652         pc->dragging_area = gtk_drawing_area_new();
00653         gtk_widget_set_events(pc->dragging_area, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
00654         gtk_box_pack_start (GTK_BOX (vbox), pc->dragging_area, TRUE, TRUE, 0);
00655         gtk_widget_set_size_request(pc->dragging_area, 10, 10);
00656         gtk_widget_show(pc->dragging_area);
00657 
00658         g_signal_connect ((gpointer)pc->dragging_area, "expose_event",  G_CALLBACK(on_DraggingArea_expose_event), pc);
00659         //g_signal_connect_after ((gpointer)pc->preeditWin, "realize",  G_CALLBACK(after_pc_dragging_area_realized), pc);
00660 }
00661 
00662 static void
00663 pc_create_page_buttons(TRealIIimPCWin* pc, GtkWidget* parent_box)
00664 {
00665     int pgop;
00666     GtkWidget *inner_page_box, *image_page_button, *vseperator;
00667 
00668     pc->pageButtonBox = gtk_hbox_new(FALSE, 0);
00669     gtk_box_pack_start (GTK_BOX (parent_box), pc->pageButtonBox, FALSE, FALSE, 0);
00670     if (is_pc_show_page_buttons(pc))
00671         gtk_widget_show(pc->pageButtonBox);
00672     else
00673         gtk_widget_hide(pc->pageButtonBox);
00674 
00675       vseperator = gtk_vseparator_new ();
00676       if (is_pc_candidates_vertical(pc))
00677           gtk_box_pack_end(GTK_BOX(pc->pageButtonBox), vseperator, FALSE, FALSE, 1);
00678       else
00679           gtk_box_pack_start(GTK_BOX(pc->pageButtonBox), vseperator, FALSE, FALSE, 1);
00680       gtk_widget_show(vseperator);
00681 
00682 
00683       if (is_pc_candidates_vertical(pc))
00684           inner_page_box = gtk_vbox_new (FALSE, 0);
00685       else
00686           inner_page_box = gtk_hbox_new (FALSE, 0);
00687       gtk_box_pack_start(GTK_BOX(pc->pageButtonBox), inner_page_box, FALSE, FALSE, 0);
00688       gtk_widget_show(inner_page_box);
00689 
00690         for (pgop=1; pgop <= 2; ++pgop) { //never show first page button and last page button
00691             pc->buttonPageRequest[pgop] = gtk_flat_button_new ();
00692             gtk_box_pack_start(GTK_BOX(inner_page_box), pc->buttonPageRequest[pgop], FALSE, FALSE, 0);
00693             gtk_flat_button_set_alignment(GTK_FLAT_BUTTON(pc->buttonPageRequest[pgop]), 0.5, 0.5);
00694             GTK_WIDGET_UNSET_FLAGS (pc->buttonPageRequest[pgop], GTK_CAN_FOCUS);
00695             gtk_widget_show(pc->buttonPageRequest[pgop]);
00696             g_signal_connect ((gpointer)pc->buttonPageRequest[pgop], "button_press_event",
00697                               G_CALLBACK (on_PageRequest_press_event),
00698                               pc);
00699 
00700                 if (is_pc_candidates_vertical(pc))
00701                     image_page_button = (GtkWidget*)create_pixmap (pc->preeditWin, pgop_icon_vertical_names[pgop]);
00702                 else
00703                     image_page_button = (GtkWidget*)create_pixmap (pc->preeditWin, pgop_icon_horizental_names[pgop]);
00704                 gtk_container_add (GTK_CONTAINER(pc->buttonPageRequest[pgop]), image_page_button);
00705                 gtk_misc_set_padding(GTK_MISC(image_page_button), 0, 0);
00706                 gtk_widget_show(image_page_button);
00707         }
00708 }
00709 
00710 static GtkWidget*      // return the inner most widget as a container
00711 pc_create_window_frames(TRealIIimPCWin* pc, GtkWidget* window)
00712 {
00713     GtkWidget *outerFrame;
00714     GtkWidget *innerFrame;
00715 
00716     outerFrame = gtk_frame_new (NULL);
00717     gtk_container_add(GTK_CONTAINER(window), outerFrame);
00718     gtk_frame_set_shadow_type (GTK_FRAME (outerFrame), GTK_SHADOW_NONE);
00719     gtk_widget_show(outerFrame);
00720     g_signal_connect ((gpointer) outerFrame, "expose_event", G_CALLBACK (on_OuterFrame_expose_event), pc);
00721 
00722       innerFrame = gtk_frame_new (NULL);
00723       gtk_container_add (GTK_CONTAINER (outerFrame), innerFrame);
00724       gtk_frame_set_shadow_type (GTK_FRAME (innerFrame), GTK_SHADOW_NONE);
00725       gtk_widget_show(innerFrame);
00726 
00727     return innerFrame;
00728 }
00729 
00730 static void
00731 pc_create_candidate_title_box(TRealIIimPCWin* pc, GtkWidget* parent_box)
00732 {
00733     GtkWidget* title_seperator;
00734 
00735     if (is_pc_candidates_vertical(pc)) {
00736         pc->candidatesTitleBox = gtk_vbox_new (FALSE, 0);
00737         title_seperator = gtk_vseparator_new();
00738     } else {
00739         pc->candidatesTitleBox = gtk_hbox_new (FALSE, 0);
00740         title_seperator = gtk_vseparator_new();
00741     }
00742     if (is_pc_candidates_title_left_or_upper(pc))
00743         gtk_box_pack_start(GTK_BOX(parent_box), pc->candidatesTitleBox, FALSE, FALSE, 2);
00744     else
00745         gtk_box_pack_end(GTK_BOX(parent_box), pc->candidatesTitleBox, FALSE, FALSE, 2);
00746     gtk_widget_hide(pc->candidatesTitleBox);
00747 
00748       if (is_pc_candidates_title_left_or_upper(pc))
00749           gtk_box_pack_end(GTK_BOX(pc->candidatesTitleBox), title_seperator, FALSE, FALSE, 0);
00750       else
00751           gtk_box_pack_start(GTK_BOX(pc->candidatesTitleBox), title_seperator, FALSE, FALSE, 0);
00752       gtk_widget_show(title_seperator);
00753 
00754       pc->candidatesTitleLabel = gtk_label_new ("");
00755       gtk_box_pack_start (GTK_BOX (pc->candidatesTitleBox), pc->candidatesTitleLabel, FALSE, FALSE, 2);
00756       gtk_misc_set_alignment (GTK_MISC (pc->candidatesTitleLabel), 0.5, 0.5);
00757       /*gtk_label_set_justify (GTK_LABEL (pc->candidatesTitleLabel), GTK_JUSTIFY_RIGHT);
00758       gtk_misc_set_padding (GTK_MISC (pc->candidatesTitleLabel), 1, 1);*/
00759       gtk_widget_show(pc->candidatesTitleLabel);
00760 }
00761 
00762 static void
00763 pc_create_preedit_label(TRealIIimPCWin* pc, GtkWidget* parent_box)
00764 {
00765     pc->preeditLabel = im_label_new ("");
00766     gtk_box_pack_start (GTK_BOX (parent_box), pc->preeditLabel, TRUE, TRUE, 0);
00767     gtk_misc_set_alignment (GTK_MISC (pc->preeditLabel), 0, 0.5);
00768     gtk_misc_set_padding (GTK_MISC (pc->preeditLabel), 5, 5);
00769     gtk_widget_show(pc->preeditLabel);
00770 }
00771 
00772 static void
00773 pc_create_composite_windows(TRealIIimPCWin* pc)
00774 {
00775     GtkWidget *window_frame;
00776     GtkWidget *outer_vbox;
00777     GtkWidget *upper_hbox;
00778     GtkWidget *preedit_candidate_seperator;
00779     GtkWidget *lower_hbox;
00780     GtkWidget *candidates_padding_area;
00781 
00782     pc->preeditWin = gtk_window_new (GTK_WINDOW_POPUP);
00783     gtk_widget_realize(pc->preeditWin);
00784     gtk_window_set_type_hint (GTK_WINDOW (pc->preeditWin), GDK_WINDOW_TYPE_HINT_UTILITY);
00785     gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), FALSE);
00786 
00787       window_frame = pc_create_window_frames(pc, pc->preeditWin);
00788 
00789         outer_vbox = gtk_vbox_new (FALSE, 0);
00790         gtk_container_add (GTK_CONTAINER (window_frame), outer_vbox);
00791         gtk_widget_show(outer_vbox);
00792 
00793           upper_hbox = gtk_hbox_new (FALSE, 0);
00794           gtk_box_pack_start (GTK_BOX (outer_vbox), upper_hbox, FALSE, FALSE, 0);
00795           gtk_widget_show(upper_hbox);
00796 
00797             pc_create_sys_button_dragging_area(pc, upper_hbox);
00798             pc_create_preedit_label(pc, upper_hbox);
00799             pc_create_candidate_title_box(pc, upper_hbox);
00800             pc_create_page_buttons(pc, upper_hbox);
00801 
00802           preedit_candidate_seperator = gtk_hseparator_new ();
00803           gtk_box_pack_start (GTK_BOX (outer_vbox), preedit_candidate_seperator, FALSE, FALSE, 0);
00804           gtk_widget_show(preedit_candidate_seperator);
00805 
00806           lower_hbox = gtk_hbox_new(FALSE, 0);
00807           gtk_box_pack_start (GTK_BOX (outer_vbox), lower_hbox, FALSE, FALSE, 0);
00808           gtk_widget_show(lower_hbox);
00809 
00810             pc->candidatesPackBox = gtk_hbox_new(FALSE, 0);
00811             gtk_box_pack_start(GTK_BOX (lower_hbox), pc->candidatesPackBox, FALSE, FALSE, 0);
00812             gtk_widget_show(pc->candidatesPackBox);
00813 
00814             candidates_padding_area = gtk_label_new(" ");
00815             gtk_box_pack_end (GTK_BOX (lower_hbox), candidates_padding_area, TRUE, TRUE, 1);
00816             gtk_widget_show(candidates_padding_area);
00817 }
00818 
00819 static void
00820 pc_create_seperate_preedit_window(TRealIIimPCWin* pc)
00821 {
00822     GtkWidget *window_frame;
00823     GtkWidget *preedit_box;
00824 
00825     pc->preeditWin = gtk_window_new (GTK_WINDOW_POPUP);
00826     gtk_widget_realize(pc->preeditWin);
00827     gtk_window_set_type_hint(GTK_WINDOW(pc->preeditWin), GDK_WINDOW_TYPE_HINT_UTILITY);
00828     gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), FALSE);
00829 
00830       window_frame = pc_create_window_frames(pc, pc->preeditWin);
00831 
00832         preedit_box = gtk_hbox_new (FALSE, 0);
00833         gtk_container_add (GTK_CONTAINER (window_frame), preedit_box);
00834         gtk_widget_show(preedit_box);
00835 
00836           pc_create_sys_button_dragging_area(pc, preedit_box);
00837           pc_create_preedit_label(pc, preedit_box);
00838 }
00839 
00840 static void
00841 pc_create_seperate_candidates_window(TRealIIimPCWin* pc)
00842 {
00843     GtkWidget *window_frame;
00844     GtkWidget *candi_win_box;
00845     GtkWidget *candidates_padding_area;
00846     GtkWidget *lower_box;
00847 
00848     pc->candidatesWin = gtk_window_new (GTK_WINDOW_POPUP);
00849     gtk_widget_realize(pc->candidatesWin);
00850     gtk_window_set_type_hint (GTK_WINDOW (pc->candidatesWin), GDK_WINDOW_TYPE_HINT_UTILITY);
00851     gtk_window_set_resizable(GTK_WINDOW(pc->candidatesWin), FALSE);
00852 
00853       window_frame = pc_create_window_frames(pc, pc->candidatesWin);
00854 
00855       if (!is_pc_candidates_vertical(pc)) {
00856         candi_win_box = gtk_hbox_new (FALSE, 0);
00857         gtk_container_add (GTK_CONTAINER(window_frame), candi_win_box);
00858         gtk_widget_show(candi_win_box);
00859 
00860           pc_create_candidate_title_box(pc, candi_win_box);
00861 
00862           pc->candidatesPackBox = gtk_hbox_new (FALSE, 0);
00863           gtk_box_pack_start (GTK_BOX (candi_win_box), pc->candidatesPackBox, FALSE, FALSE, 0);
00864           gtk_widget_show(pc->candidatesPackBox);
00865 
00866           candidates_padding_area = gtk_label_new(" ");
00867           gtk_box_pack_start (GTK_BOX(candi_win_box), candidates_padding_area, TRUE, TRUE, 1);
00868           gtk_widget_show(candidates_padding_area);
00869 
00870           pc_create_page_buttons(pc, candi_win_box);
00871 
00872       } else {
00873         candi_win_box = gtk_vbox_new (FALSE, 0);
00874         gtk_container_add (GTK_CONTAINER (window_frame), candi_win_box);
00875         gtk_widget_show(candi_win_box);
00876 
00877           pc_create_candidate_title_box(pc, candi_win_box);
00878 
00879           lower_box = gtk_hbox_new (FALSE, 0);
00880           gtk_box_pack_start(GTK_BOX(candi_win_box), lower_box, FALSE, FALSE, 0);
00881           gtk_widget_show(lower_box);
00882 
00883             pc_create_page_buttons(pc, lower_box);
00884 
00885             pc->candidatesPackBox = gtk_vbox_new (FALSE, 0);
00886             gtk_box_pack_start(GTK_BOX(lower_box), pc->candidatesPackBox, FALSE, FALSE, 0);
00887             gtk_widget_show(pc->candidatesPackBox);
00888     }
00889 }
00890 
00891 static void
00892 restoreInternalData(TRealIIimPCWin* pc)
00893 {
00894     int i;
00895     const char* cls[MAX_CANDIDATE_COUNT];
00896 
00897 
00898     for (i=0; i < MAX_CANDIDATE_COUNT; ++i)
00899         cls[i] = pc->bufCandidates[i];
00900 
00901     updatePreeditData(pc, pc->bufPreedit, pc->preeditCaret, pc->preeditCandidateCaret, 0, 0);
00902 
00903     updateCandidatesData(pc, pc->candidatesCount, cls, pc->bufCandidateTitle,
00904                          pc->firstCandidat, pc->currentCandidateInWindow, pc->totalCandidates,
00905                          NULL, NULL);
00906 
00907     movePreedit(pc, pc->cursor_x, pc->cursor_y, pc->cursor_w, pc->cursor_h);
00908 
00909     if (pc->preeditShow)
00910         showPreedit(pc);
00911 
00912     if (pc->candidatesShow)
00913         showCandidates(pc);
00914 }
00915 
00916 static void
00917 adjustCandidateWindowAtomic(TRealIIimPCWin* pc,
00918                             int candx, int candy, int candw, int candh,
00919                             int predx, int predy, int predw, int predh)
00920 {
00921     if (is_pc_composite(pc)) return;
00922 
00923     int  newx, newy, sw, sh, cand_idx;
00924 
00925     sw = gdk_screen_get_width  ( gtk_widget_get_screen(pc->preeditWin) );
00926     sh = gdk_screen_get_height ( gtk_widget_get_screen(pc->preeditWin) );
00927 
00928     if (CANDIDATES_POSITION_PREEDIT_RIGHT == get_pc_candidates_position(pc) ) {
00929         newx = predx + predw + WINDOW_GAP_VERTICAL;
00930         newy = predy;
00931 
00932         if (newx + candw > sw) {
00933             newy = predy + predh + WINDOW_GAP_VERTICAL;
00934             if (newy + candh > sh)
00935                 newy = predy - WINDOW_GAP_VERTICAL - candh;
00936             if (newy < 0) newy = 0;
00937 
00938             newx = sw - candw - WINDOW_GAP_VERTICAL;
00939         }
00940         if (newx < 0) newx = 0;
00941 
00942         if (newy + candh > sh)
00943            newy = sh - candh;
00944         if (newy < 0) newy = 0;
00945 
00946         if (newx != candx || newy != candy)
00947             gtk_window_move(GTK_WINDOW(pc->candidatesWin), newx, newy);
00948 
00949     } else {
00950         switch ( get_pc_candidates_position(pc) ) {
00951             case CANDIDATES_POSITION_PREEDIT_CARET:
00952                 cand_idx = pc->preeditCaret; break;
00953             case CANDIDATES_POSITION_IME:
00954                 cand_idx = pc->preeditCandidateCaret; break;
00955             default:
00956                 cand_idx = 0;
00957         }
00958         getPreeditBox(pc, cand_idx, &predx, &predy, &predw, &predh);
00959 
00960         gtk_widget_translate_coordinates(pc->candidatesPackBox, pc->candidatesWin, 0, 0, &newx, &newy);
00961 
00962         newx = predx - newx;
00963         if (newx + candw > sw)
00964             newx = sw - candw;
00965         if (newx < 0) newx = 0;
00966 
00967         if (predy < pc->cursor_y) {
00968             newy = predy - candh - WINDOW_GAP_VERTICAL;
00969         } else {
00970             newy = predy + predh + WINDOW_GAP_VERTICAL;
00971             if (newy + candh > sh)
00972                 newy = pc->cursor_y - candh - WINDOW_GAP_VERTICAL;
00973         }
00974 
00975         if (newy < 0) newy = 0;
00976 
00977         if (newx != candx || newy != candy)
00978             gtk_window_move(GTK_WINDOW(pc->candidatesWin), newx, newy);
00979     }
00980 }
00981 
00982 static void
00983 adjustCandidateWindow(TRealIIimPCWin* pc,
00984                       int candx, int candy, int candw, int candh)
00985 {
00986     int predx, predy, predw, predh;
00987 
00988     gtk_window_get_position(GTK_WINDOW(pc->preeditWin), &predx, &predy);
00989     predw = pc->preeditWin->allocation.width;
00990     predh = pc->preeditWin->allocation.height;
00991     adjustCandidateWindowAtomic(pc, candx, candy, candw, candh, predx, predy, predw, predh);
00992 }
00993 
00994 static int
00995 adjustPCWindows(TRealIIimPCWin* pc, int predx, int predy, int predw, int predh)
00996 {
00997     int newx, newy, sw, sh, candx, candy, candw, candh;
00998 
00999     newx = pc->cursor_x;
01000     newy = pc->cursor_y + WINDOW_GAP_VERTICAL + pc->cursor_h;
01001 
01002     sw = gdk_screen_get_width  ( gtk_widget_get_screen(pc->preeditWin) );
01003     sh = gdk_screen_get_height ( gtk_widget_get_screen(pc->preeditWin) );
01004 
01005     if (newx + predw > sw)
01006          newx = sw - predw - WINDOW_GAP_HORIZENTAL;
01007     if (newx < 0)
01008         newx = 0;
01009     if (newy + predh > sh)
01010         newy = pc->cursor_y - predh - WINDOW_GAP_VERTICAL;
01011     if (newy < 0) newy = 0;
01012 
01013     if (newx != predx || newy != predy) {
01014         gtk_window_move(GTK_WINDOW(pc->preeditWin), newx, newy);
01015         DEBUG_printf("++++++++++Move preedit window to new position, waiting for next configuration change!\n");
01016         return 0; //waiting for next configure event
01017     }
01018 
01019     if (!is_pc_composite(pc)) {
01020         DEBUG_printf("++++++++++Try to recalculate new candiates window position!\n");
01021         gtk_window_get_position(GTK_WINDOW(pc->candidatesWin), &candx, &candy);
01022         adjustCandidateWindowAtomic(pc,
01023                                     candx, candy, pc->candidatesWin->allocation.width, pc->candidatesWin->allocation.height,
01024                                     predx, predy, predw, predh);
01025     }
01026 
01027     return 1;
01028 }
01029 
01030 static gboolean
01031 on_preeditWin_configure_event          (GtkWidget       *widget,
01032                                         GdkEventConfigure *event,
01033                                         gpointer         user_data)
01034 {
01035     DEBUG_printf("+++++++++++++++++++preedit window configuration changed!!! (x,y,w,h)=(%d,%d,%d,%d)\n",
01036                                      event->x, event->y, event->width, event->height);
01037 
01038     TRealIIimPCWin* pc = (TRealIIimPCWin*)user_data;
01039     adjustPCWindows(pc, event->x, event->y, event->width, event->height);
01040     return FALSE;
01041 }
01042 
01043 static gboolean
01044 on_candidateswin_configure_event       (GtkWidget       *widget,
01045                                         GdkEventConfigure *event,
01046                                         gpointer         user_data)
01047 {
01048     DEBUG_printf("        ----------candidates window configuration changed!!! (x,y,w,h)=(%d,%d,%d,%d)\n",
01049                                     event->x, event->y, event->width, event->height);
01050 
01051     TRealIIimPCWin* pc = (TRealIIimPCWin*)user_data;
01052     adjustCandidateWindow(pc, event->x, event->y, event->width, event->height);
01053     return FALSE;
01054 }
01055 
01056 static void
01057 createWindows(TRealIIimPCWin* pc)
01058 {
01059     if (is_pc_composite(pc)) {
01060         pc_create_composite_windows(pc);
01061     } else {
01062         pc_create_seperate_preedit_window(pc);
01063         pc_create_seperate_candidates_window(pc);
01064     }
01065 
01066     restoreInternalData(pc);
01067 
01068     g_signal_connect((gpointer)pc->preeditWin,
01069                      "button_press_event",
01070                      G_CALLBACK (onMouseButtonPress),
01071                      pc);
01072 
01073     g_signal_connect((gpointer)pc->preeditWin,
01074                      "button_release_event",
01075                      G_CALLBACK (onMouseButtonRelease),
01076                      pc);
01077 
01078     g_signal_connect((gpointer)pc->preeditWin,
01079                      "motion-notify-event",
01080                      G_CALLBACK (onWindowPointerMove),
01081                      pc);
01082 
01083     g_signal_connect ((gpointer)pc->preeditWin,
01084                       "configure_event",
01085                       G_CALLBACK (on_preeditWin_configure_event),
01086                       pc);
01087 
01088     if (pc->candidatesWin) {
01089         g_signal_connect ((gpointer)pc->candidatesWin ,
01090                           "configure_event",
01091                           G_CALLBACK (on_candidateswin_configure_event),
01092                           pc);
01093     }
01094 }
01095 
01096 static void destroyWindows(TRealIIimPCWin* pc)
01097 {
01098     int i = 0;
01099 
01100     if (pc) {
01101         if (pc->preeditWin) gtk_widget_hide_all(pc->preeditWin);
01102         if (pc->candidatesWin) gtk_widget_hide_all(pc->candidatesWin);
01103 
01104         for (i=0; i < MAX_CANDIDATE_COUNT; ++i) {
01105             if (pc->candidatesLabels[i]) gtk_widget_destroy(pc->candidatesLabels[i]);
01106             pc->candidatesLabels[i] = NULL;
01107         }
01108         for (i=0; i < 4; ++i) {
01109             if (pc->buttonPageRequest[i]) gtk_widget_destroy(pc->buttonPageRequest[i]);
01110             pc->buttonPageRequest[i] = NULL;
01111         }
01112 
01113         if (pc->dragging_area) gtk_widget_destroy(pc->dragging_area);
01114         pc->dragging_area = NULL;
01115 
01116         if (pc->preeditLabel) gtk_widget_destroy(pc->preeditLabel);
01117         pc->preeditLabel = NULL;
01118 
01119         if (pc->candidatesTitleLabel) gtk_widget_destroy(pc->candidatesTitleLabel);
01120         pc->candidatesTitleLabel = NULL;
01121 
01122         if (pc->candidatesTitleBox) gtk_widget_destroy(pc->candidatesTitleBox);
01123         pc->candidatesTitleBox = NULL;
01124 
01125         if (pc->candidatesPackBox) gtk_widget_destroy(pc->candidatesPackBox);
01126         pc->candidatesPackBox = NULL;
01127 
01128         if (pc->sysMenuButton) gtk_widget_destroy(pc->sysMenuButton);
01129         pc->sysMenuButton = NULL;
01130 
01131         if (pc->pageButtonBox) gtk_widget_destroy(pc->pageButtonBox);
01132         pc->pageButtonBox = NULL;
01133 
01134         if (pc->candidatesWin) gtk_widget_destroy(pc->candidatesWin);
01135         pc->candidatesWin = NULL;
01136         if (pc->preeditWin) gtk_widget_destroy(pc->preeditWin);
01137         pc->preeditWin = NULL;
01138 
01139         pc->preeditRealShow = 0;
01140         pc->candidatesRealShow = 0;
01141     }
01142 }
01143 
01144 static void freePCSysMenu(TPCOptionMenu* pMenu);
01145 
01146 void freePreeditCandidatesWindows(TIIimPCWin vpc)
01147 {
01148     TRealIIimPCWin* pc = (TRealIIimPCWin*)vpc;
01149     if (pc) {
01150         if (pc->pMenu) freePCSysMenu(pc->pMenu);
01151         pc->pMenu = NULL;
01152         destroyWindows(pc);
01153         free(pc);
01154     }
01155 }
01156 
01157 TIIimPCWin createStockPreeditCandidatesWindows(int stockStyle)
01158 {
01159     TRealIIimPCWin* pc = (TRealIIimPCWin*)calloc(1, sizeof(TRealIIimPCWin));
01160     pc->cursor_x = pc->cursor_y = 0x80000000; //move to almost the center bottom
01161 
01162     if (stockStyle < PC_STYLE_CUSTOM || stockStyle > PC_STYLE_MODERN)
01163         stockStyle = PC_STYLE_MODERN;
01164     pc->style.type = stockStyle;
01165     pc->style.customOption = predefinedStyles[stockStyle];
01166 
01167     createWindows(pc);
01168 
01169     return pc;
01170 }
01171 
01172 TIIimPCWin createPreeditCandidatesWindows(TPCStyleAtomic* pstyle)
01173 {
01174     TRealIIimPCWin* pc = (TRealIIimPCWin*)calloc(1, sizeof(TRealIIimPCWin));
01175     pc->cursor_x = pc->cursor_y = 0x80000000; //move to almost the center bottom
01176 
01177     if (pstyle == NULL) {
01178         pc->style.type = PC_STYLE_MODERN;
01179         pc->style.customOption = predefinedStyles[pc->style.type];
01180     } else {
01181         pc->style.type = PC_STYLE_CUSTOM;
01182         pc->style.customOption = *pstyle;
01183     }
01184 
01185     createWindows(pc);
01186 
01187     return pc;
01188 }
01189 
01190 void recreateWindows(TIIimPCWin vpc, TPCStyleOption* pstyle)
01191 {
01192     DEBUG_printf("recreating windows...");
01193     TRealIIimPCWin* pc = (TRealIIimPCWin*) vpc;
01194 
01195     if (pstyle == NULL) {
01196         pc->style.type = PC_STYLE_CUSTOM;
01197         pc->style.customOption = predefinedStyles[pc->style.type];
01198     } else {
01199         pc->style = *pstyle;
01200     }
01201     destroyWindows(pc);
01202     createWindows(pc);
01203     DEBUG_printf("done!\n");
01204 }
01205 
01206 void showPreedit(TIIimPCWin vpc)
01207 {
01208     TRealIIimPCWin* pc = vpc;
01209 
01210     pc->preeditShow = 1;
01211     if (im_label_get_text_length(IM_LABEL(pc->preeditLabel)) == 0) {
01212         gtk_widget_hide (pc->preeditWin);
01213         pc->preeditRealShow = 0;
01214         if (is_pc_composite(pc))
01215             gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), FALSE);
01216     } else {
01217         if (pc->preeditRealShow > 1) {
01218             if (is_pc_composite(pc))
01219                 gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), TRUE);
01220         } else  {
01221             pc->preeditRealShow = 1;
01222             movePreedit(pc, pc->cursor_x, pc->cursor_y, pc->cursor_w, pc->cursor_h);
01223             gtk_widget_show(pc->preeditWin);
01224         }
01225     }
01226 }
01227 
01228 void hidePreedit(TIIimPCWin vpc)
01229 {
01230     TRealIIimPCWin* pc = vpc;
01231 
01232     if (pc->poping_up != 1) {
01233         pc->preeditShow = 0;
01234         pc->preeditRealShow = 0;
01235 
01236         gtk_widget_hide (pc->preeditWin);
01237         updatePreeditData(vpc, "", 0, 0, 0, NULL);
01238         if (is_pc_composite(pc)) {
01239             gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), FALSE);
01240         }
01241     }
01242 }
01243 
01244 static void
01245 getPreeditBox(TRealIIimPCWin* pc, int idx, int *px, int *py, int *pw, int *ph)
01246 {
01247     int sx, sy;
01248 
01249     im_label_get_caret_rect(IM_LABEL(pc->preeditLabel), idx, px, py, pw, ph);
01250     DEBUG_printf("Pango rect of label at index %d is (xywh) (%d %d %d %d)", idx, *px, *py, *pw, *ph);
01251 
01252     gtk_widget_translate_coordinates(pc->preeditLabel, pc->preeditWin, 0, 0, &sx, &sy);
01253     *px += sx;
01254 
01255     gtk_window_get_position(GTK_WINDOW(pc->preeditWin), &sx, &sy);
01256     *px += sx;
01257     *py = sy;
01258     *ph = pc->preeditWin->allocation.height;
01259 
01260     DEBUG_printf("screen (%d %d)\n", *px, *py);
01261 }
01262 
01263 
01264 void movePreedit(TIIimPCWin vpc, int cursor_x, int cursor_y, int cursor_w, int cursor_h)
01265 {
01266     TRealIIimPCWin* pc = vpc;
01267     int predx, predy, predw, predh;
01268 
01269     int sw = gdk_screen_get_width  ( gtk_widget_get_screen(pc->preeditWin) );
01270     int sh = gdk_screen_get_height ( gtk_widget_get_screen(pc->preeditWin) );
01271 
01272     if (pc && pc->preeditWin) {
01273         if (cursor_x == 0x80000000)
01274             cursor_x = sw/2 - 100;
01275         if (cursor_y == 0x80000000)
01276             cursor_y = sh - 180;
01277 
01278         pc->cursor_x = cursor_x;
01279         pc->cursor_y = cursor_y;
01280         pc->cursor_w = cursor_w;
01281         pc->cursor_h = cursor_h;
01282 
01283         gtk_window_get_position(GTK_WINDOW(pc->preeditWin), &predx, &predy);
01284         adjustPCWindows(pc, predx, predy, pc->preeditWin->allocation.width, pc->preeditWin->allocation.height);
01285     }
01286 }
01287 
01288 void movePreeditCaret(TIIimPCWin vpc, int caret)
01289 {
01290     int candx, candy, candw, candh;
01291 
01292     TRealIIimPCWin* pc = vpc;
01293     if (pc && pc->preeditLabel) {
01294         pc->preeditCaret = caret;
01295         im_label_set_caret_index (IM_LABEL(pc->preeditLabel), caret);
01296 
01297         if (pc->candidatesWin) {
01298             gtk_window_get_position(GTK_WINDOW(pc->candidatesWin), &candx, &candy);
01299             adjustCandidateWindow(pc, candx, candy, pc->candidatesWin->allocation.width, pc->candidatesWin->allocation.height);
01300         }
01301     }
01302 }
01303 
01304 void setPreeditCandidateStart(TIIimPCWin vpc, int candidate_start)
01305 {
01306     int candx, candy, candw, candh;
01307 
01308     TRealIIimPCWin* pc = vpc;
01309     if (pc) {
01310         pc->preeditCandidateCaret = candidate_start;
01311         if (pc->candidatesWin) {
01312             gtk_window_get_position(GTK_WINDOW(pc->candidatesWin), &candx, &candy);
01313             adjustCandidateWindow(pc, candx, candy, pc->candidatesWin->allocation.width, pc->candidatesWin->allocation.height);
01314         }
01315     }
01316 }
01317 
01318 static const char *s_escape_lt = "&lt;";
01319 static const char *s_escape_gt = "&gt;";
01320 static const char *s_escape_amp = "&amp;";
01321 #define s_escape_lt_len  4
01322 #define s_escape_gt_len  4
01323 #define s_escape_amp_len 5
01324 
01325 static char color_span_start[256];
01326 static char*color_span_end="</span>";
01327 
01328 //suppose no embeded feedbacks and only foregroundcolor feedbacks
01329 //painful in programming in C, C++ is better, if dealing with embeded feedbacks.
01330 //dst != NULL, src != 0
01331 static void
01332 my_escape_text(char dst[], const char* src, int nfbs, ImeFeedbackRec* fbs, int dst_byte_len)
01333 {
01334     char* p = dst;
01335     const char *pchar;
01336     int idx, current_fb=0, charlen;
01337 
01338     for (idx = current_fb = 0; *src != 0 && dst_byte_len > 1; ++idx) { //leave one for max utf8 len
01339         if (current_fb < nfbs && idx == fbs[current_fb].start) { //starting tag
01340             snprintf(color_span_start, 256, "<span color=\"#%06X\">", (fbs[current_fb].value & 0x00FFFFFF));
01341             charlen = strlen(color_span_start);
01342             if (dst_byte_len <= charlen)
01343                 break;
01344             strcpy(p, color_span_start);
01345             dst_byte_len -= charlen;
01346             p += charlen;
01347         }
01348 
01349         //copy the char
01350         if (*src == '<') {
01351             charlen = s_escape_lt_len;
01352             pchar = s_escape_lt;
01353             ++src;
01354         } else if (*src == '&') {
01355             charlen = s_escape_amp_len;
01356             pchar = s_escape_amp;
01357             ++src;
01358         } else {
01359             pchar = src;
01360             src = g_utf8_next_char(src);
01361             charlen = src - pchar;
01362         }
01363 
01364         if (dst_byte_len > charlen) {
01365             strncpy(p, pchar, charlen);
01366             p += charlen;
01367             dst_byte_len -= charlen;
01368         } else {
01369             break;
01370         }
01371 
01372         if ((current_fb < nfbs) && (idx == fbs[current_fb].start + fbs[current_fb].length - 1)) { //ending tag
01373             charlen = strlen(color_span_end);
01374             if (dst_byte_len <= charlen)
01375                 break;
01376             strcpy(p, color_span_end);
01377             dst_byte_len -= charlen;
01378             p += charlen;
01379             for(++current_fb; current_fb < nfbs &&  fbs[current_fb].start <= idx; ++current_fb)
01380                 ;
01381         }
01382     }
01383     *p = 0;
01384 }
01385 
01386 static void
01387 updatePreeditData(TIIimPCWin vpc, const char* label, int caret, int candidate_start, int nfbs, ImeFeedbackRec* fbs)
01388 {
01389     const char* src;
01390     char * dst;
01391     int i, sz;
01392     TRealIIimPCWin* pc = vpc;
01393 
01394 /*
01395     if (strncmp(label, "v v v v", 7) == 0) {
01396         gtk_main_quit();
01397         return;
01398     }
01399 */
01400     if (pc && pc->preeditLabel) {
01401         pc->preeditCaret = caret;
01402         pc->preeditCandidateCaret = candidate_start;
01403         if (label != pc->bufPreedit) {
01404             pc->bufPreedit[0] = 0;
01405             pc->bufPreedit[MAX_LABELSTRING_LEN-1] = 0;
01406             my_escape_text(pc->bufPreedit, label, nfbs, fbs, MAX_LABELSTRING_LEN-7);
01407             DEBUG_printf("+++++++++++++++++|escaped string %s for %s|++++++++++++++++\n", pc->bufPreedit, label);
01408         }
01409 
01410         pc->preeditCandidateCaret = candidate_start;
01411         im_label_set_markup(IM_LABEL(pc->preeditLabel), pc->bufPreedit);
01412         im_label_set_caret_index (IM_LABEL(pc->preeditLabel), caret);
01413     }
01414 }
01415 
01416 void
01417 updatePreedit(TIIimPCWin vpc, const char* label, int caret, int candidate_start, int nfbs, ImeFeedbackRec* fbs)
01418 {
01419     TRealIIimPCWin* pc = vpc;
01420 
01421     updatePreeditData(vpc, label, caret, candidate_start, nfbs, fbs);
01422 
01423     if (pc->bufPreedit[0] != 0 && pc->preeditShow && pc->preeditRealShow == 1)
01424         pc->preeditRealShow = 2;
01425 
01426     if (pc->preeditShow)
01427         showPreedit(pc);
01428 }
01429 
01430 void showCandidates(TIIimPCWin vpc)
01431 {
01432     int i;
01433     TRealIIimPCWin* pc = vpc;
01434 
01435     pc->candidatesShow = 1;
01436 
01437     if (pc->candidatesCount == 0) {
01438         if (!is_pc_composite(pc))
01439             gtk_widget_hide(pc->candidatesWin);
01440         pc->candidatesRealShow = 0;
01441         gtk_widget_hide(pc->candidatesPackBox);
01442     } else {
01443         if (pc->candidatesRealShow > 1) { 
01444             if (!is_pc_composite(pc) && !is_pc_candidates_vertical(pc))
01445                 gtk_window_set_resizable(GTK_WINDOW(pc->candidatesWin), TRUE);
01446         } else {
01447             pc->candidatesRealShow = 1;
01448             gtk_widget_show(pc->candidatesPackBox);
01449             if (!is_pc_composite(pc) && !is_pc_candidates_vertical(pc))
01450                 gtk_window_set_resizable(GTK_WINDOW(pc->candidatesWin), FALSE);
01451             if (!is_pc_composite(pc))
01452                 gtk_widget_show(pc->candidatesWin);
01453         }
01454     }
01455 
01456     if (is_pc_show_candidates_title(pc) && pc->bufCandidateTitle[0] != 0)
01457         gtk_widget_show(pc->candidatesTitleBox);
01458     else
01459         gtk_widget_hide(pc->candidatesTitleBox);
01460 
01461     if (is_pc_show_page_buttons(pc))
01462         gtk_widget_show(pc->pageButtonBox);
01463     else
01464         gtk_widget_hide(pc->pageButtonBox);
01465 }
01466 
01467 static void
01468 updateCandidatesData(TIIimPCWin vpc, 
01469                      int num, const char* candidates[], const char* title, 
01470                      int firstIdx, int focusIdx, int total, 
01471                      int *p_fb_counts, ImeFeedbackRec **pfbs)
01472 {
01473     int i, len;
01474     TRealIIimPCWin* pc = vpc;
01475 
01476     pc->firstCandidat = firstIdx;
01477     pc->currentCandidateInWindow = focusIdx;
01478     pc->totalCandidates = total;
01479 
01480     //gtk_widget_set_sensitive(pc->buttonPageRequest[0], (firstIdx > 0));
01481     gtk_widget_set_sensitive(pc->buttonPageRequest[1], (firstIdx > 0));
01482     gtk_widget_set_sensitive(pc->buttonPageRequest[2], (firstIdx+num < total));
01483     //gtk_widget_set_sensitive(pc->buttonPageRequest[3], (firstIdx+num < total));
01484 
01485     if (title != pc->bufCandidateTitle) {
01486         pc->bufCandidateTitle[0] = 0;
01487         if (title) {
01488             char* escape_str = g_markup_escape_text(title, strlen(title));
01489             strncpy(pc->bufCandidateTitle, escape_str, MAX_LABELSTRING_LEN-1);
01490             g_free(escape_str);
01491         }
01492     }
01493     gtk_label_set_markup(GTK_LABEL(pc->candidatesTitleLabel), pc->bufCandidateTitle);
01494 
01495     pc->candidatesCount = (num <= MAX_CANDIDATE_COUNT)?(num):(MAX_CANDIDATE_COUNT);
01496     for (i=0; i < pc->candidatesCount; ++i) {
01497         if (pc->bufCandidates[i] != candidates[i]) {
01498             pc->bufCandidates[i][0] = 0;
01499             pc->bufCandidates[i][MAX_LABELSTRING_LEN-1] = 0;
01500             if (candidates[i])
01501                 my_escape_text(pc->bufCandidates[i], candidates[i],
01502                                (p_fb_counts)?(p_fb_counts[i]):0,
01503                                (pfbs)?(pfbs[i]):(NULL), MAX_LABELSTRING_LEN-7);
01504         }
01505 
01506         if (pc->candidatesLabels[i] == NULL) {
01507             pc->candidatesLabels[i] = gtk_flat_button_new();
01508             gtk_flat_button_set_alignment(GTK_FLAT_BUTTON(pc->candidatesLabels[i]), 0, 0.5);
01509             gtk_box_pack_start (GTK_BOX (pc->candidatesPackBox), pc->candidatesLabels[i], TRUE, TRUE, 0);
01510             GTK_WIDGET_UNSET_FLAGS (pc->candidatesLabels[i], GTK_CAN_FOCUS);
01511             g_signal_connect ((gpointer)pc->candidatesLabels[i], "button_press_event", G_CALLBACK (on_Candidate_press_event), pc);
01512         }
01513 
01514         gtk_widget_show(pc->candidatesLabels[i]);
01515         gtk_flat_button_set_label(GTK_FLAT_BUTTON(pc->candidatesLabels[i]), pc->bufCandidates[i]);
01516         gtk_widget_show(pc->candidatesLabels[i]);
01517     }
01518 
01519     for (; i < MAX_CANDIDATE_COUNT; ++i) {
01520         pc->bufCandidates[i][0] = 0;
01521         if (pc->candidatesLabels[i] != NULL) {
01522             gtk_flat_button_set_label(GTK_FLAT_BUTTON(pc->candidatesLabels[i]), pc->bufCandidates[i]);
01523             gtk_widget_hide(pc->candidatesLabels[i]);
01524         }
01525     }
01526 }
01527 
01528 void hideCandidates(TIIimPCWin vpc)
01529 {
01530     int i;
01531     TRealIIimPCWin* pc = vpc;
01532 
01533     if (pc->poping_up != 1) {
01534         pc->candidatesShow = 0;
01535         pc->candidatesRealShow = 0;
01536 
01537         gtk_widget_hide(pc->pageButtonBox);
01538         gtk_widget_hide(pc->candidatesTitleBox);
01539         gtk_widget_hide(pc->candidatesPackBox);
01540         updateCandidatesData(pc, 0, NULL, NULL, 0, 0, 0, 0, NULL);
01541         if (!is_pc_composite(pc)) {
01542             gtk_widget_hide(pc->candidatesWin);
01543             if (!is_pc_candidates_vertical(pc))
01544                 gtk_window_set_resizable(GTK_WINDOW(pc->candidatesWin), FALSE);
01545         }
01546     }
01547 }
01548 
01549 void
01550 updateCandidates(TIIimPCWin vpc, 
01551                  int num, const char* candidates[], const char* title, 
01552                  int firstIdx, int focusIdx, int total, 
01553                  int *p_fb_counts, ImeFeedbackRec **pfbs)
01554 {
01555     TRealIIimPCWin* pc = vpc;
01556 
01557     updateCandidatesData(vpc, num, candidates, title, firstIdx, focusIdx, total, p_fb_counts, pfbs);
01558 
01559     if (is_pc_composite(pc) && pc->preeditShow && pc->preeditRealShow == 1) {
01560         pc->preeditRealShow = 2;
01561         showPreedit(pc);
01562         //gtk_window_set_resizable(GTK_WINDOW(pc->preeditWin), TRUE);
01563     }
01564    
01565     if (!is_pc_composite(pc) && num >0 && pc->candidatesRealShow == 1)
01566         pc->candidatesRealShow = 2;
01567 
01568     if (pc->candidatesShow)
01569         showCandidates(vpc);
01570 }
01571 
01572 static void
01573 updateMenuActivates(TRealIIimPCWin* pc)
01574 {
01575     TPCOptionMenu* pMenu = pc->pMenu;
01576 
01577     GTK_CHECK_MENU_ITEM (pMenu->RootWindow)->active                  = (pc->style.type == PC_STYLE_ROOT);
01578     GTK_CHECK_MENU_ITEM (pMenu->ClassicCompositeFollow)->active      = (pc->style.type == PC_STYLE_CLASSIC);
01579     GTK_CHECK_MENU_ITEM (pMenu->TraditionalStyle)->active        = (pc->style.type == PC_STYLE_TRADITIONAL);
01580     GTK_CHECK_MENU_ITEM (pMenu->ModernCanidatesHorizental)->active   = (pc->style.type == PC_STYLE_MODERN);
01581     GTK_CHECK_MENU_ITEM (pMenu->CustomizeStyle)->active              = (pc->style.type == PC_STYLE_CUSTOM);
01582 
01583     GTK_CHECK_MENU_ITEM (pMenu->ShowSystemMenu)->active              = pc->style.customOption.showSystemBar;
01584     GTK_CHECK_MENU_ITEM (pMenu->FollowCursor)->active                = pc->style.customOption.followCursor;
01585     GTK_CHECK_MENU_ITEM (pMenu->GroupPreeditCandidates)->active      = pc->style.customOption.composite;
01586 
01587     GTK_CHECK_MENU_ITEM (pMenu->CandidatesHorizental)->active        = !pc->style.customOption.candidateVertical;
01588     GTK_CHECK_MENU_ITEM (pMenu->CandidatesVertical)->active          = pc->style.customOption.candidateVertical;
01589 
01590     GTK_CHECK_MENU_ITEM (pMenu->AboveCandidates)->active             = (pc->style.customOption.candidateTitlePosition == TITLE_ABOVE_CANDIDATES);
01591     GTK_CHECK_MENU_ITEM (pMenu->BelowCandidates)->active             = (pc->style.customOption.candidateTitlePosition != TITLE_ABOVE_CANDIDATES);
01592 
01593     GTK_CHECK_MENU_ITEM (pMenu->CandidatesFollowIme)->active         = (pc->style.customOption.candidatePosition == CANDIDATES_POSITION_IME);
01594     GTK_CHECK_MENU_ITEM (pMenu->CandidatesStickPreedit)->active      = (pc->style.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_STARTS);
01595     GTK_CHECK_MENU_ITEM (pMenu->CandidatesFollowCaret)->active       = (pc->style.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_CARET);
01596     GTK_CHECK_MENU_ITEM (pMenu->CandidatesRight2Preedit)->active     = (pc->style.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_RIGHT);
01597 
01598     GTK_CHECK_MENU_ITEM (pMenu->ShowPageControl)->active             = pc->style.customOption.showPageControl;
01599     GTK_CHECK_MENU_ITEM (pMenu->IgnorCandidatesTitle)->active        = pc->style.customOption.ignoreCandidateTitle;
01600 }
01601 
01602 static void
01603 updateMenuStates(TRealIIimPCWin* pc)
01604 {
01605     TPCOptionMenu* pMenu = pc->pMenu;
01606 
01607     gtk_widget_set_sensitive(pMenu->ShowSystemMenu, (pc->style.type == PC_STYLE_CUSTOM));
01608     gtk_widget_set_sensitive(pMenu->FollowCursor, (pc->style.type == PC_STYLE_CUSTOM));
01609     gtk_widget_set_sensitive(pMenu->GroupPreeditCandidates, (pc->style.type == PC_STYLE_CUSTOM));
01610 
01611     gtk_widget_set_sensitive(pMenu->CandidatesDirection, (pc->style.type == PC_STYLE_CUSTOM && !pc->style.customOption.composite));
01612     gtk_widget_set_sensitive(pMenu->CandidateTitlePosition, (pc->style.type == PC_STYLE_CUSTOM && !pc->style.customOption.composite));
01613     gtk_widget_set_sensitive(pMenu->CandidatesPosition, (pc->style.type == PC_STYLE_CUSTOM && !pc->style.customOption.composite));
01614 
01615     gtk_widget_set_sensitive(pMenu->ShowPageControl, (pc->style.type == PC_STYLE_CUSTOM));
01616     gtk_widget_set_sensitive(pMenu->IgnorCandidatesTitle, (pc->style.type == PC_STYLE_CUSTOM));
01617 }
01618 
01619 static void
01620 on_PCMenuItem_activate               (GtkMenuItem     *menuitem,
01621                                       gpointer         user_data)
01622 {
01623     int changed = 1;
01624     TRealIIimPCWin* pc = user_data;
01625     TPCOptionMenu* pMenu = pc->pMenu;
01626 
01627     if (pc == NULL)
01628         return;
01629 
01630     TPCStyleOption pcstyle = pc->style;
01631 
01632     if (GTK_WIDGET(menuitem) == pMenu->RootWindow) {
01633         if (pcstyle.type == PC_STYLE_ROOT) changed = 0;
01634         pcstyle.type = PC_STYLE_ROOT;
01635 
01636     } else if (GTK_WIDGET(menuitem) == pMenu->ClassicCompositeFollow) {
01637         if (pcstyle.type == PC_STYLE_CLASSIC) changed = 0;
01638         pcstyle.type = PC_STYLE_CLASSIC;
01639 
01640     } else if (GTK_WIDGET(menuitem) == pMenu->TraditionalStyle) {
01641         if (pcstyle.type == PC_STYLE_TRADITIONAL) changed = 0;
01642         pcstyle.type = PC_STYLE_TRADITIONAL;
01643 
01644     } else if (GTK_WIDGET(menuitem) == pMenu->ModernCanidatesHorizental) {
01645         if (pcstyle.type == PC_STYLE_MODERN) changed = 0;
01646         pcstyle.type = PC_STYLE_MODERN;
01647 
01648     }  else if (GTK_WIDGET(menuitem) == pMenu->CustomizeStyle) {
01649         if (pcstyle.type == PC_STYLE_CUSTOM) changed = 0;
01650         pcstyle.type = PC_STYLE_CUSTOM;
01651 
01652     } else if (GTK_WIDGET(menuitem) == pMenu->ShowSystemMenu) {
01653         pcstyle.customOption.showSystemBar = !(pcstyle.customOption.showSystemBar);
01654 
01655     } else if (GTK_WIDGET(menuitem) == pMenu->FollowCursor) {
01656         pcstyle.customOption.followCursor = !(pcstyle.customOption.followCursor);
01657 
01658     } else if (GTK_WIDGET(menuitem) == pMenu->GroupPreeditCandidates) {
01659         pcstyle.customOption.composite = !(pcstyle.customOption.composite);
01660 
01661     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesHorizental) {
01662         if (pcstyle.customOption.candidateVertical == 0) changed = 0;
01663         pcstyle.customOption.candidateVertical = 0;
01664 
01665     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesVertical) {
01666         if (pcstyle.customOption.candidateVertical == 1) changed = 0;
01667         pcstyle.customOption.candidateVertical = 1;
01668 
01669     } else if (GTK_WIDGET(menuitem) == pMenu->AboveCandidates) {
01670         if (pcstyle.customOption.candidateTitlePosition == TITLE_ABOVE_CANDIDATES) changed = 0;
01671         pcstyle.customOption.candidateTitlePosition = TITLE_ABOVE_CANDIDATES;
01672 
01673     } else if (GTK_WIDGET(menuitem) == pMenu->BelowCandidates) {
01674         if (pcstyle.customOption.candidateTitlePosition != TITLE_ABOVE_CANDIDATES) changed = 0;
01675         pcstyle.customOption.candidateTitlePosition = TITLE_BELOW_CANDIDATES;
01676 
01677     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesFollowIme) {
01678         if (pcstyle.customOption.candidatePosition == CANDIDATES_POSITION_IME) changed = 0;
01679         pcstyle.customOption.candidatePosition = CANDIDATES_POSITION_IME;
01680 
01681     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesStickPreedit) {
01682         if (pcstyle.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_STARTS) changed = 0;
01683         pcstyle.customOption.candidatePosition = CANDIDATES_POSITION_PREEDIT_STARTS;
01684 
01685     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesFollowCaret) {
01686         if (pcstyle.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_CARET) changed = 0;
01687         pcstyle.customOption.candidatePosition = CANDIDATES_POSITION_PREEDIT_CARET;
01688 
01689     } else if (GTK_WIDGET(menuitem) == pMenu->CandidatesRight2Preedit) {
01690         if (pcstyle.customOption.candidatePosition == CANDIDATES_POSITION_PREEDIT_RIGHT) changed = 0;
01691         pcstyle.customOption.candidatePosition = CANDIDATES_POSITION_PREEDIT_RIGHT;
01692 
01693     } else if (GTK_WIDGET(menuitem) == pMenu->ShowPageControl) {
01694         pcstyle.customOption.showPageControl = !(pcstyle.customOption.showPageControl);
01695 
01696     } else if (GTK_WIDGET(menuitem) == pMenu->IgnorCandidatesTitle) {
01697         pcstyle.customOption.ignoreCandidateTitle = !(pcstyle.customOption.ignoreCandidateTitle);
01698 
01699     } else {
01700         changed = 0;
01701     }
01702 
01703     if (changed) {
01704         if (pc->process_style_change)
01705              pc->process_style_change(pc, (int)&pcstyle);
01706     }
01707 }
01708 
01709 static void
01710 setMenuActivateCallbacks(TRealIIimPCWin* pc, TPCOptionMenu* pMenu)
01711 {
01712   g_signal_connect ((gpointer) pMenu->RootWindow, "activate",
01713                     G_CALLBACK (on_PCMenuItem_activate),
01714                     pc);
01715   g_signal_connect ((gpointer) pMenu->ClassicCompositeFollow, "activate",
01716                     G_CALLBACK (on_PCMenuItem_activate),
01717                     pc);
01718   g_signal_connect ((gpointer) pMenu->TraditionalStyle, "activate",
01719                     G_CALLBACK (on_PCMenuItem_activate),
01720                     pc);
01721   g_signal_connect ((gpointer) pMenu->ModernCanidatesHorizental, "activate",
01722                     G_CALLBACK (on_PCMenuItem_activate),
01723                     pc);
01724   g_signal_connect ((gpointer) pMenu->CustomizeStyle, "activate",
01725                     G_CALLBACK (on_PCMenuItem_activate),
01726                     pc);
01727   g_signal_connect ((gpointer) pMenu->ShowSystemMenu, "activate",
01728                     G_CALLBACK (on_PCMenuItem_activate),
01729                     pc);
01730   g_signal_connect ((gpointer) pMenu->FollowCursor, "activate",
01731                     G_CALLBACK (on_PCMenuItem_activate),
01732                     pc);
01733   g_signal_connect ((gpointer) pMenu->GroupPreeditCandidates, "activate",
01734                     G_CALLBACK (on_PCMenuItem_activate),
01735                     pc);
01736   g_signal_connect ((gpointer) pMenu->CandidatesDirection, "activate",
01737                     G_CALLBACK (on_PCMenuItem_activate),
01738                     pc);
01739   g_signal_connect ((gpointer) pMenu->CandidatesHorizental, "activate",
01740                     G_CALLBACK (on_PCMenuItem_activate),
01741                     pc);
01742   g_signal_connect ((gpointer) pMenu->CandidatesVertical, "activate",
01743                     G_CALLBACK (on_PCMenuItem_activate),
01744                     pc);
01745   g_signal_connect ((gpointer) pMenu->AboveCandidates, "activate",
01746                     G_CALLBACK (on_PCMenuItem_activate),
01747                     pc);
01748   g_signal_connect ((gpointer) pMenu->BelowCandidates, "activate",
01749                     G_CALLBACK (on_PCMenuItem_activate),
01750                     pc);
01751   g_signal_connect ((gpointer) pMenu->CandidatesFollowIme, "activate",
01752                     G_CALLBACK (on_PCMenuItem_activate),
01753                     pc);
01754   g_signal_connect ((gpointer) pMenu->CandidatesStickPreedit, "activate",
01755                     G_CALLBACK (on_PCMenuItem_activate),
01756                     pc);
01757   g_signal_connect ((gpointer) pMenu->CandidatesFollowCaret, "activate",
01758                     G_CALLBACK (on_PCMenuItem_activate),
01759                     pc);
01760   g_signal_connect ((gpointer) pMenu->CandidatesRight2Preedit, "activate",
01761                     G_CALLBACK (on_PCMenuItem_activate),
01762                     pc);
01763   g_signal_connect ((gpointer) pMenu->ShowPageControl, "activate",
01764                     G_CALLBACK (on_PCMenuItem_activate),
01765                     pc);
01766   g_signal_connect ((gpointer) pMenu->IgnorCandidatesTitle, "activate",
01767                     G_CALLBACK (on_PCMenuItem_activate),
01768                     pc);
01769 }
01770 
01771 static void
01772 on_PCSysMenu_popdown           (GtkMenuShell *menushell,
01773                                 gpointer     user_data)
01774 {
01775     TRealIIimPCWin* pc = user_data;
01776 
01777     if (pc) pc->poping_up = 2;
01778 }
01779 
01780 #if defined(LE_ZH_TW) || defined(LE_ZH_HK)
01781 static char *pc_msg_menuitem_root_style = "固定輸入視窗 (輸入框不跟隨游標移動)";
01782 static char *pc_msg_menuitem_classic_style = "典型 (輸入框跟隨游標移動)";
01783 static char *pc_msg_menuitem_traditional_style = "傳統 (右側豎排候選)";
01784 static char *pc_msg_menuitem_modern_style = "現代 (下部橫排候選)";
01785 static char *pc_msg_menuitem_custom_style = "使用者自行定義";
01786 static char *pc_msg_menuitem_show_sysbutton = "顯示選單按鈕";
01787 static char *pc_msg_menuitem_follow_cursor = "跟隨游標";
01788 static char *pc_msg_menuitem_composite = "組合";
01789 static char *pc_msg_menu_candidates_direction = "候選排列方式";
01790 static char *pc_msg_menuitem_candidates_vertical = "豎排";
01791 static char *pc_msg_menuitem_candidates_horizental = "橫排";
01792 static char *pc_msg_menu_candidates_title_position = "候選標題位置";
01793 static char *pc_msg_menuitem_candidates_title_left = "候選左側或上方";
01794 static char *pc_msg_menuitem_candidates_title_right = "候選右側或下方";
01795 static char *pc_msg_menu_candidates_position = "候選視窗位置";
01796 static char *pc_msg_menuitem_candidates_ime = "輸入法決定";
01797 static char *pc_msg_menuitem_candidates_stick = "編輯視窗起始位置";
01798 static char *pc_msg_menuitem_candidates_right = "編輯視窗右側";
01799 static char *pc_msg_menuitem_candidates_follow_cursor = "跟隨編輯視窗游標";
01800 static char *pc_msg_menuitem_show_page_controls = "顯示捲頁元件";
01801 static char *pc_msg_menuitem_ignore_candidates_title = "隱藏候選標題";
01802 #else
01803 static char *pc_msg_menuitem_root_style = "固定(组合,不跟随光标)";
01804 static char *pc_msg_menuitem_classic_style = "经典(组合,跟随光标)";
01805 static char *pc_msg_menuitem_traditional_style = "传统(右侧竖排候选)";
01806 static char *pc_msg_menuitem_modern_style = "现代(下部横排候选)";
01807 static char *pc_msg_menuitem_custom_style = "自定义";
01808 static char *pc_msg_menuitem_show_sysbutton = "显示菜单按钮";
01809 static char *pc_msg_menuitem_follow_cursor = "光标跟随";
01810 static char *pc_msg_menuitem_composite = "组合";
01811 static char *pc_msg_menu_candidates_direction = "候选排列方式";
01812 static char *pc_msg_menuitem_candidates_vertical = "竖排";
01813 static char *pc_msg_menuitem_candidates_horizental = "横排";
01814 static char *pc_msg_menu_candidates_title_position = "候选标题位置";
01815 static char *pc_msg_menuitem_candidates_title_left = "候选左侧或上方";
01816 static char *pc_msg_menuitem_candidates_title_right = "候选右侧或下方";
01817 static char *pc_msg_menu_candidates_position = "候选窗口位置";
01818 static char *pc_msg_menuitem_candidates_ime = "输入法决定";
01819 static char *pc_msg_menuitem_candidates_stick = "编辑窗口起始位置";
01820 static char *pc_msg_menuitem_candidates_right = "编辑窗口右侧";
01821 static char *pc_msg_menuitem_candidates_follow_cursor = "跟随编辑窗口光标";
01822 static char *pc_msg_menuitem_show_page_controls = "显示翻页控件";
01823 static char *pc_msg_menuitem_ignore_candidates_title = "隐藏候选标题";
01824 #endif
01825 
01826 static void
01827 freePCSysMenu(TPCOptionMenu* pMenu) 
01828 {
01829     if (pMenu) {
01830         if (pMenu->iiimPCWinSysMenu) gtk_widget_destroy(GTK_WIDGET(pMenu->iiimPCWinSysMenu));
01831         pMenu->iiimPCWinSysMenu = NULL;
01832         free(pMenu);
01833     }
01834 }
01835 
01836 static TPCOptionMenu*
01837 create_iiimPCWinSysMenu (TRealIIimPCWin* pc)
01838 {
01839   TPCOptionMenu* pMenu = (TPCOptionMenu* )calloc(1, sizeof(TPCOptionMenu));
01840 
01841   pMenu->iiimPCWinSysMenu = gtk_menu_new ();
01842   GTK_WIDGET_UNSET_FLAGS(pMenu->iiimPCWinSysMenu, GTK_CAN_FOCUS);
01843   gtk_container_set_border_width (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), 2);
01844 
01845   pMenu->RootWindow = gtk_radio_menu_item_new_with_mnemonic (pMenu->RootWindow_group, pc_msg_menuitem_root_style);
01846   pMenu->RootWindow_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->RootWindow));
01847   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->RootWindow);
01848   gtk_widget_show(pMenu->RootWindow);
01849 
01850   pMenu->ClassicCompositeFollow = gtk_radio_menu_item_new_with_mnemonic (pMenu->RootWindow_group, pc_msg_menuitem_classic_style);
01851   pMenu->RootWindow_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->ClassicCompositeFollow));
01852   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->ClassicCompositeFollow);
01853   gtk_widget_show(pMenu->ClassicCompositeFollow);
01854 
01855   pMenu->TraditionalStyle = gtk_radio_menu_item_new_with_mnemonic (pMenu->RootWindow_group, pc_msg_menuitem_traditional_style);
01856   pMenu->RootWindow_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->TraditionalStyle));
01857   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->TraditionalStyle);
01858   gtk_widget_show(pMenu->TraditionalStyle);
01859 
01860   pMenu->ModernCanidatesHorizental = gtk_radio_menu_item_new_with_mnemonic (pMenu->RootWindow_group, pc_msg_menuitem_modern_style);
01861   pMenu->RootWindow_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->ModernCanidatesHorizental));
01862   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->ModernCanidatesHorizental);
01863   gtk_widget_show(pMenu->ModernCanidatesHorizental);
01864 
01865   pMenu->CustomizeStyle = gtk_radio_menu_item_new_with_mnemonic (pMenu->RootWindow_group, pc_msg_menuitem_custom_style);
01866   pMenu->RootWindow_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CustomizeStyle));
01867   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->CustomizeStyle);
01868   gtk_widget_show(pMenu->CustomizeStyle);
01869 
01870   pMenu->_________1 = gtk_separator_menu_item_new ();
01871   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->_________1);
01872   gtk_widget_set_sensitive (pMenu->_________1, FALSE);
01873   gtk_widget_show(pMenu->_________1);
01874 
01875   pMenu->ShowSystemMenu = gtk_check_menu_item_new_with_mnemonic (pc_msg_menuitem_show_sysbutton);
01876   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->ShowSystemMenu);
01877   gtk_widget_show(pMenu->ShowSystemMenu);
01878 
01879   pMenu->FollowCursor = gtk_check_menu_item_new_with_mnemonic (pc_msg_menuitem_follow_cursor);
01880   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->FollowCursor);
01881   gtk_widget_show(pMenu->FollowCursor);
01882 
01883   pMenu->GroupPreeditCandidates = gtk_check_menu_item_new_with_mnemonic (pc_msg_menuitem_composite);
01884   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->GroupPreeditCandidates);
01885   gtk_widget_show(pMenu->GroupPreeditCandidates);
01886 
01887   pMenu->_________2 = gtk_separator_menu_item_new ();
01888   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->_________2);
01889   gtk_widget_set_sensitive (pMenu->_________2, FALSE);
01890   gtk_widget_show(pMenu->_________2);
01891 
01892   pMenu->CandidatesDirection = gtk_menu_item_new_with_mnemonic (pc_msg_menu_candidates_direction);
01893   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->CandidatesDirection);
01894   gtk_widget_show(pMenu->CandidatesDirection);
01895 
01896   pMenu->CandidatesDirection_menu = gtk_menu_new ();
01897   gtk_menu_item_set_submenu (GTK_MENU_ITEM (pMenu->CandidatesDirection), pMenu->CandidatesDirection_menu);
01898   gtk_widget_show(pMenu->CandidatesDirection_menu);
01899 
01900       pMenu->CandidatesHorizental = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesHorizental_group, pc_msg_menuitem_candidates_horizental);
01901       pMenu->CandidatesHorizental_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesHorizental));
01902       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesDirection_menu), pMenu->CandidatesHorizental);
01903       gtk_widget_show(pMenu->CandidatesHorizental);
01904 
01905       pMenu->CandidatesVertical = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesHorizental_group, pc_msg_menuitem_candidates_vertical);
01906       pMenu->CandidatesHorizental_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesVertical));
01907       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesDirection_menu), pMenu->CandidatesVertical);
01908       gtk_widget_show(pMenu->CandidatesVertical);
01909 
01910   pMenu->CandidateTitlePosition = gtk_menu_item_new_with_mnemonic (pc_msg_menu_candidates_title_position);
01911   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->CandidateTitlePosition);
01912   gtk_widget_show(pMenu->CandidateTitlePosition);
01913 
01914   pMenu->CandidateTitlePosition_menu = gtk_menu_new ();
01915   gtk_menu_item_set_submenu (GTK_MENU_ITEM (pMenu->CandidateTitlePosition), pMenu->CandidateTitlePosition_menu);
01916   gtk_widget_show(pMenu->CandidateTitlePosition_menu);
01917 
01918       pMenu->AboveCandidates = gtk_radio_menu_item_new_with_mnemonic (pMenu->AboveCandidates_group, pc_msg_menuitem_candidates_title_left);
01919       pMenu->AboveCandidates_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->AboveCandidates));
01920       gtk_container_add (GTK_CONTAINER (pMenu->CandidateTitlePosition_menu), pMenu->AboveCandidates);
01921       gtk_widget_show(pMenu->AboveCandidates);
01922 
01923       pMenu->BelowCandidates = gtk_radio_menu_item_new_with_mnemonic (pMenu->AboveCandidates_group, pc_msg_menuitem_candidates_title_right);
01924       pMenu->AboveCandidates_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->BelowCandidates));
01925       gtk_container_add (GTK_CONTAINER (pMenu->CandidateTitlePosition_menu), pMenu->BelowCandidates);
01926       gtk_widget_show(pMenu->BelowCandidates);
01927 
01928   pMenu->CandidatesPosition = gtk_menu_item_new_with_mnemonic (pc_msg_menu_candidates_position);
01929   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->CandidatesPosition);
01930   gtk_widget_show(pMenu->CandidatesPosition);
01931 
01932   pMenu->CandidatesPosition_menu = gtk_menu_new ();
01933   gtk_menu_item_set_submenu (GTK_MENU_ITEM (pMenu->CandidatesPosition), pMenu->CandidatesPosition_menu);
01934   gtk_widget_show(pMenu->CandidatesPosition_menu);
01935 
01936       pMenu->CandidatesFollowIme = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesFollowIme_group, pc_msg_menuitem_candidates_ime);
01937       pMenu->CandidatesFollowIme_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesFollowIme));
01938       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesPosition_menu), pMenu->CandidatesFollowIme);
01939       gtk_widget_show(pMenu->CandidatesFollowIme);
01940 
01941       pMenu->CandidatesStickPreedit = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesFollowIme_group, pc_msg_menuitem_candidates_stick);
01942       pMenu->CandidatesFollowIme_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesStickPreedit));
01943       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesPosition_menu), pMenu->CandidatesStickPreedit);
01944       gtk_widget_show(pMenu->CandidatesStickPreedit);
01945 
01946 
01947       pMenu->CandidatesFollowCaret = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesFollowIme_group, pc_msg_menuitem_candidates_follow_cursor);
01948       pMenu->CandidatesFollowIme_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesFollowCaret));
01949       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesPosition_menu), pMenu->CandidatesFollowCaret);
01950       gtk_widget_show(pMenu->CandidatesFollowCaret);
01951 
01952       pMenu->CandidatesRight2Preedit = gtk_radio_menu_item_new_with_mnemonic (pMenu->CandidatesFollowIme_group, pc_msg_menuitem_candidates_right);
01953       pMenu->CandidatesFollowIme_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (pMenu->CandidatesRight2Preedit));
01954       gtk_container_add (GTK_CONTAINER (pMenu->CandidatesPosition_menu), pMenu->CandidatesRight2Preedit);
01955       gtk_widget_show(pMenu->CandidatesRight2Preedit);
01956 
01957   pMenu->_________3 = gtk_separator_menu_item_new ();
01958   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->_________3);
01959   gtk_widget_set_sensitive (pMenu->_________3, FALSE);
01960   gtk_widget_show(pMenu->_________3);
01961 
01962   pMenu->ShowPageControl = gtk_check_menu_item_new_with_mnemonic (pc_msg_menuitem_show_page_controls);
01963   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->ShowPageControl);
01964   gtk_widget_show(pMenu->ShowPageControl);
01965 
01966   pMenu->IgnorCandidatesTitle = gtk_check_menu_item_new_with_mnemonic (pc_msg_menuitem_ignore_candidates_title);
01967   gtk_container_add (GTK_CONTAINER (pMenu->iiimPCWinSysMenu), pMenu->IgnorCandidatesTitle);
01968   gtk_widget_show(pMenu->IgnorCandidatesTitle);
01969 
01970   pc->pMenu = pMenu;
01971   updateMenuActivates(pc);
01972   updateMenuStates(pc);
01973   setMenuActivateCallbacks(pc, pMenu);
01974 
01975   g_signal_connect ((gpointer) GTK_MENU_SHELL(pMenu->iiimPCWinSysMenu), "deactivate",
01976                     G_CALLBACK (on_PCSysMenu_popdown),
01977                     pc);
01978 
01979   return pMenu;
01980 }
01981 
01982 
01983 void
01984 getPCCursorPosition(TIIimPCWin vpc, int *pcursor_x, int *pcursor_y, int *pcursor_w, int* pcursor_h)
01985 {
01986     TRealIIimPCWin *pc = (TRealIIimPCWin *)vpc;
01987     *pcursor_x = pc->cursor_x;
01988     *pcursor_y = pc->cursor_y;
01989     *pcursor_w = pc->cursor_w;
01990     *pcursor_h = pc->cursor_h;
01991     return;
01992     //gtk_window_get_position(GTK_WINDOW(pc->preeditWin), px, py);
01993 }
01994 
01995 void registerStyleChangeCallback(TIIimPCWin vpc, TIIimPCWinCallback callback)
01996 {
01997     TRealIIimPCWin *pc = (TRealIIimPCWin *)vpc;
01998     pc->process_style_change = callback;
01999 }
02000 
02001 void registerPageCallback(TIIimPCWin vpc, TIIimPCWinCallback callback)
02002 {
02003     TRealIIimPCWin *pc = (TRealIIimPCWin *)vpc;
02004     pc->process_page_request = callback;
02005 }
02006 
02007 void registerSelectionCallback(TIIimPCWin vpc, TIIimPCWinCallback callback)
02008 {
02009     TRealIIimPCWin *pc = (TRealIIimPCWin *)vpc;
02010     pc->process_select_request = callback;
02011 }
02012 
02013 void registerMoveCallback(TIIimPCWin vpc, TIIimPCWinCallback callback)
02014 {
02015     TRealIIimPCWin *pc = (TRealIIimPCWin *)vpc;
02016     pc->process_position_change = callback;
02017 }
02018 
02019 TPCStyleOption* getStyles(TIIimPCWin vpc)
02020 {
02021     return  &((TRealIIimPCWin *)vpc)->style;
02022 }
02023 
02024 int isPCFollowCursor(TIIimPCWin vpc)
02025 {
02026     return is_pc_follow_cursor((TRealIIimPCWin *)vpc);
02027 }
02028 
02029 int is_pc_preedit_show(TIIimPCWin vpc)
02030 {
02031     return  ((TRealIIimPCWin *)vpc)->preeditShow;
02032 }
02033 
02034 int is_pc_candidates_show(TIIimPCWin vpc)
02035 {
02036     return  ((TRealIIimPCWin *)vpc)->candidatesShow;
02037 }
02038 
02039 
02040