Back to index

im-sdk  12.3.91
guiIMPrePos.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 #include "xiiimp.h"
00043 #include "guiIMPre.h"
00044 #include "XimpIm.h"
00045 #include "trace_message.h"
00046 
00047 #if 0 /* 4281121: htt_xbe dumps core in DestroyFilter() at client is exiting */
00048 static Bool
00049 DestroyFilter(Display *d /*unused*/,
00050              Window w /* unused */,
00051              XEvent *ev, XPointer client_data) {
00052   /* focus window is destroyed, so preedit windows, which
00053      are children of the focus window, has been destroyed already
00054    */
00055   XicCommon ic = (XicCommon)client_data;
00056   PreeditWin preedit;
00057 
00058   if (ic->gui_icpart) {
00059     preedit = (PreeditWin)ic->gui_icpart->preedit;
00060   } else {
00061     return False;
00062   }
00063   /* unselect focus win mask */
00064   ic->ximp_icpart->proto4_mask &= ~XIMP_FOCUS_WIN_MASK4;
00065 
00066   /* discard preedit win data */
00067   if (!preedit) return True;
00068 
00069   if (preedit->preedit_areas) Xfree(preedit->preedit_areas);
00070   preedit->preedit_areas = 0;
00071   preedit->alloc_areas = 0;
00072   preedit->active_areas = 0;
00073   return True;
00074 }
00075 #endif /* 0 */
00076 
00077 /* ChangePreedit Methods */
00078 static void
00079 create(XicCommon ic, XPointer call_data) {
00080   PreeditWin preedit = (PreeditWin)ic->gui_icpart->preedit;
00081 
00082   TRACE_MESSAGE('p', ("iiimpPrePos:create\n"));
00083   if (!preedit) {
00084     SetupPreeditExt(ic);
00085     preedit = (PreeditWin)ic->gui_icpart->preedit;
00086   }
00087 
00088   if (!XIMP_CHK_FOCUSWINMASK(ic)) return;
00089 
00090   if (preedit->parent == ic->core.focus_window &&
00091       preedit->preedit_areas) {
00092     /* same parent window */
00093     return;
00094   }
00095 
00096   SetupPreeditWindow(ic, ic->core.focus_window);
00097 #if 0 /* 4281121: htt_xbe dumps core in DestroyFilter() at client is exiting */
00098   /* register destroy filter for focus_window */
00099   _XRegisterFilterByType(ic->core.im->core.display, ic->core.focus_window,
00100                       DestroyNotify, DestroyNotify,
00101                       DestroyFilter, (XPointer)ic);
00102 #endif /* 0 */
00103   return;
00104 }
00105 
00106 #if !defined(OLD_SET_WINDOW)
00107 
00108 static int
00109 preedit_line_num(unsigned short * wcstr_width, int len,
00110                int area_width, int first_line_x_offset) {
00111   int i;
00112   int max_line_width;
00113   int line_width;
00114   int line_width_new;
00115   int line_num;
00116 
00117   for (i = 0, line_num = 0; i < len; line_num++) {
00118     if (0 == line_num) {
00119       max_line_width = (area_width - first_line_x_offset);
00120     } else {
00121       max_line_width = area_width;
00122     }
00123     line_width = 0;
00124     for (; i < len; i++) {
00125       line_width_new = (line_width + *(wcstr_width + i));
00126       if (max_line_width < line_width_new) {
00127        if ((0 == line_width) && (area_width < line_width_new)) {
00128          /* If the width of a character is wider than area_width,
00129           * it consists one line.
00130           */
00131          i += 1;
00132        }
00133        break;
00134       }
00135       line_width = line_width_new;
00136     }
00137   }
00138 
00139   return line_num;
00140 }
00141 
00142 static int
00143 preedit_line_num_rev(unsigned short * wcstr_width, int len, int area_width) {
00144   int i;
00145   int line_width;
00146   int line_width_new;
00147   int line_num;
00148 
00149   for (i = (len - 1), line_num = 0; 0 <= i; line_num++) {
00150     line_width = 0;
00151     for (; 0 <= i; --i) {
00152       line_width_new = (line_width + *(wcstr_width + i));
00153       if (area_width < line_width_new) {
00154        if (0 == line_width) {
00155          /* If the width of a character is wider than area_width,
00156           * it consists one line.
00157           */
00158          i -= 1;
00159        }
00160        break;
00161       }
00162       line_width = line_width_new;
00163     }
00164   }
00165 
00166   return line_num;
00167 }
00168 
00169 static Bool
00170 PreeditWindowChanged(XicCommon ic, PreeditArea preedit_area) {
00171     int char_offset;
00172     int char_len;
00173     int char_offset_backup;
00174     int char_len_backup;
00175     int i;
00176     int j;
00177     PreeditWin preedit;
00178     PreeditChars preedit_chars;
00179     PreeditChars preedit_chars_backup;
00180     wchar_t * wc;
00181     wchar_t * wc_backup;
00182     IMFeedbackList *fbl;
00183     IMFeedbackList *fbl_backup;
00184     IMFeedback  *fb;
00185     IMFeedback  *fb_backup;
00186     XIMFeedback *xfb;
00187     XIMFeedback *xfb_backup;
00188 
00189     preedit = ic->gui_icpart->preedit;
00190     preedit_chars = &(preedit->preedit_chars);
00191     preedit_chars_backup = &(preedit->preedit_chars_backup);
00192 
00193     if (((NULL == preedit_chars->feedback) &&
00194         (NULL != preedit_chars_backup->feedback)) ||
00195        ((NULL != preedit_chars->feedback) &&
00196         (NULL == preedit_chars_backup->feedback))) {
00197       return True;
00198     }
00199 
00200     char_offset = preedit_area->char_offset;
00201     char_len = preedit_area->char_len;
00202 
00203     char_offset_backup = preedit_area->char_offset_backup;
00204     char_len_backup = preedit_area->char_len_backup;
00205 
00206     wc = (preedit_chars->wchar + char_offset);
00207     wc_backup = (preedit_chars_backup->wchar + char_offset_backup);
00208 
00209     fbl = (preedit_chars->feedback_list + char_offset);
00210     fbl_backup = (preedit_chars_backup->feedback_list + char_offset_backup);
00211 
00212     xfb = (preedit_chars->feedback + char_offset);
00213     xfb_backup = (preedit_chars_backup->feedback + char_offset_backup);
00214 
00215     for (i = 0; i < preedit_area->char_len; i++) {
00216       if (*(wc + i) != *(wc_backup + i)) {
00217        return True;
00218       }
00219 
00220       if (*(xfb + i) != *(xfb_backup + i)) {
00221        return True;
00222       }
00223 
00224       if (fbl->count_feedbacks != fbl_backup->count_feedbacks) {
00225        return True;
00226       }
00227 
00228       fb = fbl->feedbacks;
00229       fb_backup = fbl_backup->feedbacks;
00230 
00231       for (j = 0; j < fbl->count_feedbacks; j++) {
00232        if (((fb + j)->type != (fb_backup + j)->type) ||
00233            ((fb + j)->value != (fb_backup + j)->value)) {
00234          return True;
00235        }
00236       }
00237     }
00238 
00239     return False;
00240 }
00241 
00242 static void
00243 ConfigurePreeditWindow(XicCommon ic, PreeditArea preedit_area,
00244                      int x, int y, int width, int height) {
00245   XWindowChanges changes;
00246   int  mask;
00247   mask = None;
00248 
00249   if (preedit_area->win_config.x != x) {
00250     mask |= CWX;
00251     changes.x = x;
00252     preedit_area->win_config.x = x;
00253   }
00254   if (preedit_area->win_config.y != y) {
00255     mask |= CWY;
00256     changes.y = y;
00257     preedit_area->win_config.y = y;
00258   }
00259   if (preedit_area->win_config.height != height) {
00260     mask |= CWHeight;
00261     changes.height = height;
00262     if (preedit_area->win_config.height < height) {
00263       XIC_GUI(ic, preedit)->discard_expose_event = True;
00264     }
00265     preedit_area->win_config.height = height;
00266   }
00267   if (preedit_area->win_config.width != width) {
00268     mask |= CWWidth;
00269     changes.width = width;
00270     if (preedit_area->win_config.width < width) {
00271       XIC_GUI(ic, preedit)->discard_expose_event = True;
00272     }
00273     preedit_area->win_config.width = width;
00274   }
00275   if (None != mask) {
00276     XConfigureWindow(ic->core.im->core.display, preedit_area->window,
00277                    mask, &changes);
00278     preedit_area->configured = True;
00279   } else if (True == PreeditWindowChanged(ic, preedit_area)) {
00280     /* force UpdatePreedit() to update preedit */
00281     preedit_area->configured = True;
00282   }
00283 
00284   return;
00285 }
00286 
00287 static int
00288 set_window_forward(XicCommon ic, int len,
00289                  int area_width, int area_x, int first_line_x_offset,
00290                  int spot_loc_x, int spot_loc_y,
00291                  int line_spacing) {
00292   PreeditWin preedit;
00293   PreeditArea preedit_area;
00294   PreeditChars preedit_chars;
00295   unsigned short * wcstr_width;
00296   int i;
00297   int max_line_width;
00298   int line_width;
00299   int line_width_new;
00300   int line_height;
00301   int line_num;
00302   XFontSetExtents *fse;
00303   int font_logical_height;
00304   int char_offset;
00305   int x;
00306   int y;
00307 
00308   preedit = ic->gui_icpart->preedit;
00309   preedit_area = preedit->preedit_areas;
00310   preedit_chars = &(preedit->preedit_chars);
00311   wcstr_width = preedit_chars->wchar_width;
00312   fse = preedit->fse;
00313   font_logical_height = (-fse->max_ink_extent.y);
00314   line_height = (fse->max_logical_extent.height + 1);
00315 
00316   for (i = 0, line_num = 0; i < len; line_num++) {
00317     char_offset = i;
00318 
00319     if (0 == line_num) {
00320       max_line_width = (area_width - first_line_x_offset);
00321       x = spot_loc_x;
00322     } else {
00323       max_line_width = area_width;
00324       x = area_x;
00325     }
00326     y = spot_loc_y - font_logical_height + (line_spacing * line_num);
00327 
00328     line_width = 0;
00329     for (; i < len; i++) {
00330       line_width_new = (line_width + *(wcstr_width + i));
00331       if (max_line_width < line_width_new) {
00332        if ((0 == line_width) && (area_width < line_width_new)) {
00333          /* If the width of a character is wider than area_width,
00334           * it consists one line.
00335           */
00336          i += 1;
00337          line_width = max_line_width;
00338        }
00339        break;
00340       }
00341       line_width = line_width_new;
00342     }
00343 
00344     if (preedit->alloc_areas <= line_num) {
00345       if (False == NewPreeditWindow(ic)) return line_num;
00346       preedit_area = preedit->preedit_areas;
00347     }
00348 
00349     preedit_area[line_num].x = 0;
00350     preedit_area[line_num].y = font_logical_height;
00351     preedit_area[line_num].char_offset_backup =
00352            preedit_area[line_num].char_offset;
00353     preedit_area[line_num].char_len_backup = preedit_area[line_num].char_len;
00354     preedit_area[line_num].char_offset = char_offset;
00355     preedit_area[line_num].char_len = (i - char_offset);
00356 
00357     if ((0 == line_width) || (0 == line_height)) {
00358       UnmapPreeditWindow(ic, preedit_area + line_num);
00359     } else {
00360       ConfigurePreeditWindow(ic, preedit_area + line_num,
00361                           x, y, line_width, line_height);
00362     }
00363   }
00364 
00365   return line_num;
00366 }
00367 
00368 static int
00369 set_window_backward(XicCommon ic, int len,
00370                   int area_width, int area_height, int area_x, int area_y,
00371                   int spot_loc_y, int line_spacing, int line_num) {
00372   PreeditWin preedit;
00373   PreeditArea preedit_area;
00374   PreeditChars preedit_chars;
00375   unsigned short * wcstr_width;
00376   int i;
00377   int line_width;
00378   int line_width_new;
00379   int line_height;
00380   int area_height_low;
00381   XFontSetExtents *fse;
00382   int font_logical_height;
00383   int char_tail;
00384   int x;
00385   int y;
00386   int num;
00387 
00388   preedit = ic->gui_icpart->preedit;
00389   preedit_chars = &(preedit->preedit_chars);
00390   wcstr_width = preedit_chars->wchar_width;
00391   fse = preedit->fse;
00392   font_logical_height = (-fse->max_ink_extent.y);
00393   line_height = (fse->max_logical_extent.height + 1);
00394 
00395   x = area_x;
00396 
00397   while (preedit->alloc_areas <= line_num) {
00398     if (False == NewPreeditWindow(ic)) return 0;
00399   }
00400   preedit_area = preedit->preedit_areas;
00401 
00402   area_height_low = ((area_height + area_y) -
00403                    (spot_loc_y - (-fse->max_logical_extent.y)));
00404   area_height_low = (line_spacing * (area_height_low / line_spacing));
00405   y = (spot_loc_y + area_height_low - font_logical_height);
00406 
00407   for (i = (len - 1), num = (line_num - 1); (0 <= i) && (0 <= num); --num) {
00408     char_tail = i;
00409 
00410     y -= line_spacing;
00411 
00412     line_width = 0;
00413     for (; 0 <= i; --i) {
00414       line_width_new = (line_width + *(wcstr_width + i));
00415       if (area_width < line_width_new) {
00416        if (0 == line_width) {
00417          /* If the width of a character is wider than area_width,
00418           * it consists one line.
00419           */
00420          i -= 1;
00421          line_width = area_width;
00422        }
00423        break;
00424       }
00425       line_width = line_width_new;
00426     }
00427 
00428     x = (area_x + area_width - line_width);
00429 
00430     preedit_area[num].x = 0;
00431     preedit_area[num].y = font_logical_height;
00432     preedit_area[num].char_offset_backup = preedit_area[num].char_offset;
00433     preedit_area[num].char_len_backup = preedit_area[num].char_len;
00434     preedit_area[num].char_offset = (i + 1);
00435     preedit_area[num].char_len = (char_tail - i);
00436 
00437     if ((0 == line_width) || (0 == line_height)) {
00438       UnmapPreeditWindow(ic, preedit_area + num);
00439     } else {
00440       ConfigurePreeditWindow(ic, preedit_area + num,
00441                           x, y, line_width, line_height);
00442     }
00443   }
00444 
00445   return line_num;
00446 }
00447 
00448 static int
00449 set_window_full(XicCommon ic, int len,
00450               int area_width, int area_x,
00451               int spot_loc_x, int spot_loc_y,
00452               int line_spacing) {
00453   int line_num;
00454 
00455   spot_loc_y = (spot_loc_y - (line_spacing * (spot_loc_y / line_spacing)));
00456 
00457   line_num = set_window_forward(ic, len, area_width, area_x, area_x,
00458                             area_x, spot_loc_y, line_spacing);
00459 
00460   return line_num;
00461 }
00462 
00463 static void
00464 set_window(XicCommon ic, XPointer call_data) {
00465   PreeditWin preedit;
00466   PreeditArea preedit_area;
00467   PreeditChars preedit_chars;
00468   XPoint * spot_location;
00469   XRectangle * preedit_attr_area;
00470   XFontSetExtents *fse;
00471   int line_spacing;
00472   int font_logical_height;
00473   int x, y, height = 0;
00474   int area_width;
00475   int area_height;
00476   int first_line_x_offset;
00477   int len;
00478   wchar_t *wcstr;
00479   unsigned short *wcstr_width;
00480   int line_num;
00481 
00482   if (!XIMP_CHK_FOCUSWINMASK(ic)) return;
00483 
00484   preedit = (PreeditWin)ic->gui_icpart->preedit;
00485 
00486   if (NULL == preedit) {
00487     create(ic, NULL);
00488     preedit = (PreeditWin)ic->gui_icpart->preedit;
00489     if (NULL == preedit) return;
00490   }
00491 
00492   preedit_area = preedit->preedit_areas;
00493   preedit_chars = &(preedit->preedit_chars);
00494 
00495   if (preedit_chars->wchar_len == 0) return;
00496 
00497   if (NULL == preedit->fontset) {
00498     SetPreeditFont(ic, NULL);
00499     if (NULL == preedit->fontset) return;
00500   }
00501 
00502   spot_location = &(ic->core.preedit_attr.spot_location);
00503   preedit_attr_area = &(ic->core.preedit_attr.area);
00504 
00505   height = 0;
00506 
00507   fse = preedit->fse;
00508   font_logical_height = fse->max_logical_extent.height;
00509   height = font_logical_height;
00510   height += (fse->max_ink_extent.height + fse->max_ink_extent.y);
00511 
00512   if (spot_location->x > preedit_attr_area->x) {
00513     x = spot_location->x;
00514   } else {
00515     x = preedit_attr_area->x;
00516   }
00517   y = (spot_location->y - font_logical_height);
00518 
00519   /* calculate area width */
00520   if (XIMP_CHK_PREAREAMASK(ic)) {
00521     area_width = preedit_attr_area->width;
00522     area_height = preedit_attr_area->height;
00523     first_line_x_offset = (spot_location->x - preedit_attr_area->x);
00524 
00525   } else {
00526     area_width = XIC_GUI(ic, preedit)->client_window_width;
00527     area_height = XIC_GUI(ic, preedit)->client_window_height;
00528     first_line_x_offset = spot_location->x;
00529   }
00530 
00531   TRACE_MESSAGE('p', ("set_window: width=%d height=%d\n",
00532               area_width, area_height));
00533 
00534   if (XIMP_CHK_PRELINESPMASK(ic)) {
00535     line_spacing = ic->core.preedit_attr.line_spacing;
00536     if (line_spacing > area_height)
00537       /* line_spacing is too large */
00538       line_spacing = font_logical_height;
00539   } else {
00540     line_spacing = font_logical_height;
00541   }
00542 
00543   len = preedit_chars->wchar_len;
00544   wcstr = preedit_chars->wchar;
00545   wcstr_width = preedit_chars->wchar_width;
00546 
00547   line_num = preedit_line_num(wcstr_width, preedit_chars->wchar_len,
00548                            area_width, first_line_x_offset);
00549 
00550   if ((line_spacing * line_num) <=
00551       ((area_height + preedit_attr_area->y) -
00552        (spot_location->y - font_logical_height))) {
00553     set_window_forward(ic, len, area_width, preedit_attr_area->x,
00554                      first_line_x_offset, 
00555                      spot_location->x, spot_location->y, line_spacing);
00556   } else {
00557     line_num = preedit_line_num_rev(wcstr_width, len, area_width);
00558     if ((line_spacing * line_num) <= area_height) {
00559       set_window_backward(ic, len, area_width, area_height,
00560                        preedit_attr_area->x, preedit_attr_area->y,
00561                        spot_location->y, line_spacing, line_num);
00562     } else {
00563       set_window_full(ic, len, area_width,
00564                     preedit_attr_area->x,
00565                     spot_location->x, spot_location->y, line_spacing);
00566     }
00567   }
00568   preedit->active_areas = line_num;
00569 
00570   return;
00571 }
00572 #else /* OLD_SET_WINDOW */
00573 
00574 static void
00575 set_window(XicCommon ic, XPointer call_data) {
00576   PreeditWin preedit = (PreeditWin)ic->gui_icpart->preedit;
00577   PreeditArea preedit_area;
00578   PreeditChars preedit_chars;
00579 
00580   /* This is necessary to avoid erasing botom parts of preedit lines */
00581   int bottom_margin;
00582 
00583   if (!preedit) {
00584     create(ic, NULL);
00585     preedit = (PreeditWin)ic->gui_icpart->preedit;
00586     if (!preedit) return;
00587   }
00588   preedit_area = (PreeditArea)(preedit->preedit_areas);
00589 
00590   if (!XIMP_CHK_FOCUSWINMASK(ic)) return;
00591 
00592   preedit_chars = (PreeditChars)&(preedit->preedit_chars);
00593   if (preedit_chars->wchar_len == 0) return;
00594 
00595   if (!preedit->fontset) {
00596     SetPreeditFont(ic, NULL);
00597   }
00598   /* Nothing to do until fontset is ready */
00599   if (preedit->fontset) {
00600     XFontSetExtents *fse;
00601     CacheRec *preedit_cache = (CacheRec*)&(preedit->preedit_cache);
00602     int x, y, width = 0, height = 0;
00603     int wrap_width, wrap_xmargin;
00604 
00605     width = XwcTextEscapement(preedit->fontset,
00606                            preedit_chars->wchar,
00607                            preedit_chars->wchar_len);
00608 
00609 #if 0
00610     fse = XExtentsOfFontSet(preedit->fontset);
00611 #else /* !0 */
00612     fse = preedit->fse;
00613 #endif /* !0 */
00614     height = fse->max_logical_extent.height;
00615     height += (fse->max_ink_extent.height + fse->max_ink_extent.y);
00616 
00617     if (ic->core.preedit_attr.spot_location.x >
00618        ic->core.preedit_attr.area.x) {
00619       x = ic->core.preedit_attr.spot_location.x;
00620     } else {
00621       x = ic->core.preedit_attr.area.x;
00622     }
00623     y = ic->core.preedit_attr.spot_location.y;
00624     y -= fse->max_logical_extent.height;
00625 
00626     TRACE_MESSAGE('p', ("set_window: width=%d height=%d\n", width, height));
00627 
00628     bottom_margin = fse->max_logical_extent.height/4;
00629 
00630     /* calculate wrap width */
00631     if (XIMP_CHK_PREAREAMASK(ic)) {
00632       wrap_width = ic->core.preedit_attr.area.width;
00633     } else {
00634       wrap_width = XIC_GUI(ic, preedit)->client_window_width;
00635 #if 0
00636       XWindowAttributes fwin_attr;
00637       XGetWindowAttributes(ic->core.im->core.display,
00638                         ic->core.focus_window,
00639                         &fwin_attr);
00640       wrap_width = fwin_attr.width;
00641 #endif /* 0 */
00642     }
00643 
00644     wrap_xmargin = wrap_width > fse->max_logical_extent.width ?
00645                      (fse->max_logical_extent.width)/4 : 1;
00646 
00647     if (x + width + wrap_xmargin <= wrap_width) {
00648       /* can draw all chars in one window */
00649       preedit->active_areas = 1;
00650       preedit_area[0].x = 0;
00651       preedit_area[0].y = fse->max_logical_extent.height - bottom_margin;
00652       preedit_area[0].char_offset = 0;
00653       preedit_area[0].char_len = preedit_chars->wchar_len;
00654 
00655       if (preedit_cache->win_x == x &&
00656          preedit_cache->win_y == y &&
00657          preedit_cache->win_width == width &&
00658          preedit_cache->win_height == height) {
00659        return;
00660       }
00661       if (width == 0 || height == 0) {
00662        UnmapPreeditWindow(ic, preedit_area + 0);
00663       } else {
00664 #if 0
00665        XMoveResizeWindow(ic->core.im->core.display,
00666                        preedit_area[0].window,
00667                        x, y + bottom_margin, width, height);
00668 #endif /* 0 */
00669        XWindowChanges changes;
00670        int    mask;
00671        mask = None;
00672        if (preedit_cache->win_x != x) {
00673               mask |= CWX;
00674               changes.x = x;
00675        }
00676        if (preedit_cache->win_y != y) {
00677               mask |= CWY;
00678               changes.y = (y + bottom_margin);
00679        }
00680        if (preedit_cache->win_height != height) {
00681               mask |= CWHeight;
00682               changes.height = height;
00683               if (preedit_area[0].win_config.height < height) {
00684                 XIC_GUI(ic, preedit)->discard_expose_event = True;
00685               }
00686        }
00687        if (preedit_cache->win_width != width) {
00688               mask |= CWWidth;
00689               changes.width = width;
00690               if (preedit_area[0].win_config.width < width) {
00691                 XIC_GUI(ic, preedit)->discard_expose_event = True;
00692               }
00693        }
00694        if (None != mask) {
00695          XConfigureWindow(ic->core.im->core.display, preedit_area[0].window,
00696                         mask, &changes);
00697          preedit_area[0].configured = True;
00698        }
00699        preedit_area[0].win_config.x = x;
00700        preedit_area[0].win_config.y = y;
00701        preedit_area[0].win_config.height = height;
00702        preedit_area[0].win_config.width = width;
00703       }
00704       /* data cache */
00705       preedit_cache->win_x = x;
00706       preedit_cache->win_y = y;
00707       preedit_cache->win_width = width;
00708       preedit_cache->win_height = height;
00709     } else {
00710       /* draw more than two windows */
00711       int left;
00712       wchar_t *wcstr;
00713       int n;
00714 
00715       /* initial values */
00716       left = preedit_chars->wchar_len;
00717       wcstr = preedit_chars->wchar;
00718       n = 0;
00719       while (left) {
00720        wchar_t *p = wcstr;
00721        int cur_width = 0, prev_width;
00722        int i;
00723        if (n == 0) {
00724          if (ic->core.preedit_attr.spot_location.x >
00725              ic->core.preedit_attr.area.x) {
00726            x = ic->core.preedit_attr.spot_location.x;
00727          } else {
00728            x = ic->core.preedit_attr.area.x;
00729          }
00730        } else {
00731          x = ic->core.preedit_attr.area.x + wrap_xmargin;
00732        }
00733        prev_width = XwcTextEscapement(preedit->fontset,
00734                                    wcstr, 1);
00735        for (i = 1; i <= left; i++) {
00736          cur_width += XwcTextEscapement(preedit->fontset, p++, 1);
00737          if (x + cur_width + wrap_xmargin > wrap_width) break;
00738          prev_width = cur_width;
00739        }
00740        if (!XIMP_CHK_PRELINESPMASK(ic))
00741          ic->core.preedit_attr.line_spacing = fse->max_logical_extent.height;
00742        y = ic->core.preedit_attr.spot_location.y - 
00743          fse->max_logical_extent.height +
00744          ic->core.preedit_attr.line_spacing * n;
00745 
00746        TRACE_MESSAGE('p', ("set_window: prev_width=%d height=%d\n",
00747                          prev_width, height));
00748 
00749        preedit_area[n].x = 0;
00750        preedit_area[n].y = fse->max_logical_extent.height - bottom_margin;
00751        preedit_area[n].char_offset = wcstr - preedit_chars->wchar;
00752        preedit_area[n].char_len = i - 1;
00753        if (prev_width == 0 || height == 0) {
00754          UnmapPreeditWindow(ic, preedit_area + n);
00755        } else {
00756 #if 0
00757          XMoveResizeWindow(ic->core.im->core.display,
00758                          preedit_area[n].window,
00759                          x, y + bottom_margin, prev_width, height);
00760 #endif /* 0 */
00761          XWindowChanges changes;
00762          int  mask;
00763          mask = None;
00764          if (preedit_area[n].win_config.x != x) {
00765            mask |= CWX;
00766            changes.x = x;
00767          }
00768          if (preedit_area[n].win_config.y != y) {
00769            mask |= CWY;
00770            changes.y = (y + bottom_margin);
00771          }
00772          if (preedit_area[n].win_config.height != height) {
00773            mask |= CWHeight;
00774            changes.height = height;
00775            if (preedit_area[n].win_config.height < height) {
00776              XIC_GUI(ic, preedit)->discard_expose_event = True;
00777            }
00778          }
00779          if (preedit_area[n].win_config.width != prev_width) {
00780            mask |= CWWidth;
00781            changes.width = prev_width;
00782            if (preedit_area[n].win_config.width < prev_width) {
00783              XIC_GUI(ic, preedit)->discard_expose_event = True;
00784            }
00785          }
00786          if (None != mask) {
00787            XConfigureWindow(ic->core.im->core.display, preedit_area[n].window,
00788                           mask, &changes);
00789            preedit_area[n].configured = True;
00790          }
00791          preedit_area[n].win_config.x = x;
00792          preedit_area[n].win_config.y = y;
00793          preedit_area[n].win_config.height = height;
00794          preedit_area[n].win_config.width = prev_width;
00795        }
00796        n++;
00797        left -= (i - 1);
00798        wcstr += i - 1;
00799        /* need to create a new preedit window */
00800        if (left > 0) {
00801          if (n == preedit->alloc_areas) {
00802            if (!NewPreeditWindow(ic)) return;
00803            preedit_area = preedit->preedit_areas;
00804          } else {
00805            continue;
00806          }
00807        }
00808       }       /* end of while loop */
00809       preedit->active_areas = n;
00810 
00811       /* clear cache */
00812       preedit_cache->win_x = -1;
00813       preedit_cache->win_y = -1;
00814       preedit_cache->win_width = -1;
00815       preedit_cache->win_height = -1;
00816     }
00817   }
00818   return;
00819 }
00820 #endif /* OLD_SET_WINDOW */
00821 
00822 static void
00823 move(XicCommon ic, XPointer call_data) {
00824   set_window(ic, NULL);
00825   if (NULL != XIC_GUI(ic, preedit)) {
00826     XIC_GUI(ic, preedit)->discard_expose_event = False;
00827   }
00828   return;
00829 }
00830 
00831 static PreeditCB preedit_pos_methods[] = {
00832   create,                   /* PREEDIT_CREATE */
00833   set_window,               /* PREEDIT_WIN */
00834   SetPreeditForeground,            /* PREEDIT_FG */
00835   SetPreeditBackground,            /* PREEDIT_BG */
00836   SetPreeditFont,           /* PREEDIT_FONT */
00837   move,                            /* PREEDIT_MOVE */
00838   PreeditStart,                    /* PREEDIT_START */
00839   PreeditDrawText,          /* PREEDIT_DRAW */
00840   PreeditCaret,                    /* PREEDIT_CARET */
00841   PreeditDone,                     /* PREEDIT_DONE */
00842   DestroyPreedit            /* PREEDIT_DESTROY */
00843 };
00844 
00845 void
00846 ChangePreeditPosition(XIC xic, PreeditAttr reason, XPointer call_data) {
00847   XicCommon ic = (XicCommon)xic;
00848   if (reason > PREEDIT_DESTROY) return;
00849   preedit_pos_methods[reason](ic, call_data);
00850   return;
00851 }