Back to index

im-sdk  12.3.91
guiIMPreArea.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 
00046 /* ChangePreedit Methods */
00047 static void
00048 create(XicCommon ic, XPointer call_data) {
00049   PreeditWin preedit = (PreeditWin)ic->gui_icpart->preedit;
00050 
00051   if (!preedit) {
00052     SetupPreeditExt(ic);
00053     preedit = (PreeditWin)ic->gui_icpart->preedit;
00054   }
00055 
00056   if (preedit->parent != 0 && preedit->preedit_areas) {
00057     /* preedit window is already created  */
00058     return;
00059   }
00060 
00061   if (!(ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN)) return;
00062 
00063   SetupPreeditWindow(ic, ic->core.client_window);
00064   return;
00065 }
00066 
00067 static void
00068 set_window(XicCommon ic, XPointer call_data) {
00069   PreeditWin preedit = (PreeditWin)(ic->gui_icpart->preedit);
00070   PreeditArea preedit_area;
00071   CacheRec *preedit_cache;
00072   PreeditChars preedit_chars;
00073   XRectangle *ic_preedit_area;
00074   unsigned int width, height, max_width, max_height;
00075   XFontSetExtents *fse;
00076 
00077   if (!preedit) {
00078     create(ic, NULL);
00079     preedit = (PreeditWin)(ic->gui_icpart->preedit);
00080     if (!preedit) return;
00081   }
00082   if (!preedit->fontset) {
00083     SetPreeditFont(ic, NULL);
00084     if (!preedit->fontset) return;
00085   }
00086 
00087   preedit_chars = (PreeditChars)&(preedit->preedit_chars);
00088   if (preedit_chars->wchar_len == 0) return;
00089 
00090   preedit_area = (PreeditArea)(preedit->preedit_areas);
00091   if (preedit->active_areas != 1 || !preedit_area ||
00092       !preedit_area[0].window) {
00093     return;
00094   }
00095 
00096   fse = XExtentsOfFontSet(preedit->fontset);
00097   width = XwcTextEscapement(preedit->fontset,
00098                          preedit_chars->wchar,
00099                          preedit_chars->wchar_len);
00100   if (width == 0) width = 1;
00101   height = fse->max_ink_extent.height;
00102   if (height == 0) height = 1;
00103 
00104   ic_preedit_area = &ic->core.preedit_attr.area;
00105   max_width = (fse->max_ink_extent.width > ic_preedit_area->width) ?
00106     fse->max_ink_extent.width : ic_preedit_area->width;
00107   max_height = ic_preedit_area->height;
00108 
00109   preedit_area[0].configured = False;
00110   preedit_area[0].x = 0;
00111   preedit_area[0].char_offset = 0;
00112   preedit_area[0].char_len = preedit_chars->wchar_len;
00113   if (max_height < fse->max_ink_extent.height) {
00114     int height_diff;
00115     height_diff =
00116       (max_height - fse->max_ink_extent.height);
00117     height_diff += (height_diff & 1);
00118     preedit_area[0].y = (-fse->max_ink_extent.y) + (height_diff / 2);
00119   }
00120   else {
00121     preedit_area[0].y = (-fse->max_ink_extent.y);
00122   }
00123 
00124   if (width <= max_width) {
00125     preedit_area[0].active_lines = 0;
00126   }
00127   else if (max_height < fse->max_ink_extent.height) {
00128     /* draw latest characters only */
00129     preedit_area[0].active_lines = 0;
00130     preedit_area[0].x = max_width - width;
00131   }
00132   else {
00133     /* draw more than two lines */
00134     int left;
00135     wchar_t *wcstr;
00136     int n, prev_y, line_spacing;
00137     PreeditLine preedit_line;
00138     
00139     preedit_line = preedit_area[0].lines;
00140     left = preedit_chars->wchar_len;
00141     wcstr = preedit_chars->wchar;
00142     n = 0;
00143     line_spacing = (ic->core.preedit_attr.line_spacing > 0) ?
00144       ic->core.preedit_attr.line_spacing : height;
00145     prev_y = preedit_area[0].y - line_spacing;;
00146     while (left) {
00147       wchar_t *p = wcstr;
00148       int cur_width = 0;
00149       int i;
00150       if (n == preedit_area[0].alloc_lines) {
00151        preedit_area[0].alloc_lines += 10;
00152        if (!preedit_area[0].lines) {
00153          preedit_area[0].lines =
00154            (PreeditLine)Xmalloc(sizeof(PreeditLineRec) *
00155                              preedit_area[0].alloc_lines);
00156        }
00157        else {
00158          preedit_area[0].lines =
00159            (PreeditLine)Xrealloc(preedit_area[0].lines,
00160                               sizeof(PreeditLineRec) *
00161                               preedit_area[0].alloc_lines);
00162        }
00163        if (!preedit_area[0].lines) return;
00164        preedit_line = preedit_area[0].lines;
00165       }
00166       for (i = 1; i <= left; i++) {
00167        cur_width += XwcTextEscapement(preedit->fontset, p++, 1);
00168        if (cur_width > max_width) break;
00169       }
00170       preedit_line[n].x = 0;
00171       preedit_line[n].y = prev_y + line_spacing;
00172       preedit_line[n].char_offset = wcstr - preedit_chars->wchar;
00173       preedit_line[n].char_len = i - 1;
00174       prev_y = preedit_line[n].y;
00175       n++;
00176       left -= (i - 1);
00177       wcstr += i - 1;
00178     }
00179     preedit_area[0].active_lines = n;
00180     height = line_spacing * n;
00181     if (max_height < height) {
00182       int i;
00183       int height_diff = height - max_height;
00184       for (i = 0; i < n; ++i) {
00185        preedit_line[i].y -= height_diff;
00186       }
00187     }
00188   }
00189   if (max_width < width) width = max_width;
00190   // Is window size changed?
00191   if (preedit_area[0].win_config.x != ic_preedit_area->x ||
00192       preedit_area[0].win_config.y != ic_preedit_area->y ||
00193       preedit_area[0].win_config.width != ic_preedit_area->width ||
00194       preedit_area[0].win_config.height != ic_preedit_area->height) {
00195     XMoveResizeWindow(ic->core.im->core.display,
00196                     preedit_area[0].window,
00197                     ic_preedit_area->x, ic_preedit_area->y,
00198                     ic_preedit_area->width, ic_preedit_area->height);
00199     preedit_area[0].win_config.x = ic_preedit_area->x;
00200     preedit_area[0].win_config.y = ic_preedit_area->y;
00201     preedit_area[0].win_config.width = ic_preedit_area->width;
00202     preedit_area[0].win_config.height = ic_preedit_area->height;
00203     preedit_area[0].configured = True;
00204   }
00205   // Is preedit area not changed ?
00206   preedit_cache = (CacheRec*)&(preedit->preedit_cache);
00207   if (preedit_cache->win_x == preedit_area[0].x &&
00208       preedit_cache->win_y == preedit_area[0].y &&
00209       preedit_cache->win_width == width &&
00210       preedit_cache->win_height == height) {
00211     return;
00212   }
00213   preedit_area[0].configured = True;
00214   /* data cache */
00215   preedit_cache->win_x = preedit_area[0].x;
00216   preedit_cache->win_y = preedit_area[0].y;
00217   preedit_cache->win_width = width;
00218   preedit_cache->win_height = height;
00219   preedit_cache->font_set = preedit->fontset;
00220 
00221   return;
00222 }
00223 
00224 static void
00225 move(XicCommon ic, XPointer call_data) {
00226   /* nothing to do */
00227   return;
00228 }
00229 
00230 static PreeditCB preedit_area_methods[] = {
00231   create,                   /* PREEDIT_CREATE */
00232   set_window,               /* PREEDIT_WIN */
00233   SetPreeditForeground,            /* PREEDIT_FG */
00234   SetPreeditBackground,            /* PREEDIT_BG */
00235   SetPreeditFont,           /* PREEDIT_FONT */
00236   move,                            /* PREEDIT_MOVE */
00237   PreeditStart,                    /* PREEDIT_START */
00238   PreeditDrawText,          /* PREEDIT_DRAW */
00239   PreeditCaret,                    /* PREEDIT_CARET */
00240   PreeditDone,                     /* PREEDIT_DONE */
00241   DestroyPreedit            /* PREEDIT_DESTROY */
00242 };
00243 
00244 void
00245 ChangePreeditArea(XIC xic, PreeditAttr reason, XPointer call_data) {
00246   XicCommon ic = (XicCommon)xic;
00247   if (reason > PREEDIT_DESTROY) return;
00248   preedit_area_methods[reason](ic, call_data);
00249   return;
00250 }