Back to index

im-sdk  12.3.91
guiIMPreNothing.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 "guiIMSts.h"
00045 #include "XimpIm.h"
00046 #include "xfactory.h"
00047 
00048 /* ChangePreedit Methods */
00049 static void
00050 create(XicCommon ic, XPointer call_data) {
00051   PreeditWin preedit = (PreeditWin)ic->gui_icpart->preedit;
00052   Display *display = ic->core.im->core.display;
00053   XWindowAttributes attr;
00054 
00055   if (!preedit) {
00056     SetupPreeditExt(ic);
00057     preedit = (PreeditWin)ic->gui_icpart->preedit;
00058   }
00059 
00060   if (preedit->parent != 0 && preedit->preedit_areas) {
00061     /* preedit window is already created  */
00062     return;
00063   }
00064 
00065   if (!(ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN)) return;
00066 
00067   XGetWindowAttributes(display, 
00068                      ic->core.client_window,
00069                      &attr);
00070   SetupPreeditWindow(ic, RootWindow(display,
00071                                 XScreenNumberOfScreen(attr.screen)));
00072   return;
00073 }
00074 
00075 static void
00076 set_window(XicCommon ic, XPointer call_data) {
00077   PreeditWin preedit = (PreeditWin)ic->gui_icpart->preedit;
00078   Display *display = ic->core.im->core.display;
00079   PreeditArea preedit_area;
00080 
00081   if (!preedit) {
00082     create(ic, NULL);
00083     preedit = (PreeditWin)ic->gui_icpart->preedit;
00084     if (!preedit) return;
00085   }
00086   preedit_area = (PreeditArea)(preedit->preedit_areas);
00087 
00088   if (preedit->active_areas == 1 && preedit_area[0].window) {
00089     XWindowAttributes win_att;
00090     XSizeHints  hints;
00091     XWMHints wm_hints;
00092     Window frame_window;
00093     int x_margin = 0, y_margin = 0;
00094     PreeditChars preedit_chars = (PreeditChars)&(preedit->preedit_chars);
00095     int wrap_width;
00096 
00097     if (preedit_chars->wchar_len == 0) return;
00098 
00099     frame_window = XFactoryGetFrameWindow(display,
00100                                      ic->core.client_window);
00101 
00102     if (XGetWindowAttributes(display, frame_window,
00103                           &win_att) > 0) {
00104       int x, y;
00105       unsigned int width = 0, height = 0;
00106       CacheRec *preedit_cache = (CacheRec*)&(preedit->preedit_cache);
00107 
00108       x = win_att.x;
00109       y = win_att.y;
00110       y += win_att.height;
00111 
00112       wrap_width = win_att.width;
00113 
00114       if (ic->core.input_style & XIMStatusNothing) {
00115        Window status_window;
00116        StatusWin status = (StatusWin)(ic->gui_icpart->status);
00117        XWindowAttributes swin_att;
00118 
00119        if (status && status->window) {
00120          status_window = XFactoryGetFrameWindow(display,
00121                                           status->window);
00122          if (XGetWindowAttributes(display, status_window,
00123                              &swin_att) > 0) {
00124            x = swin_att.x;
00125            x += swin_att.width;
00126 
00127            wrap_width -= swin_att.width;
00128          }
00129         }
00130       }
00131 
00132       if (!preedit->fontset) {
00133        SetPreeditFont(ic, NULL);
00134       }
00135       if (preedit->fontset) {
00136        XFontSetExtents *fse;
00137        fse = XExtentsOfFontSet(preedit->fontset);
00138        width = XwcTextEscapement(preedit->fontset,
00139                               preedit_chars->wchar,
00140                               preedit_chars->wchar_len);
00141        height = fse->max_logical_extent.height;
00142        if (wrap_width < fse->max_logical_extent.width * 5) {
00143          /* too small wrap_width, no more than 5 multibyte
00144             characters can be written in a line, not good */
00145          wrap_width = fse->max_logical_extent.width * 5;
00146        }
00147        /* adjust wrap_width to be mutibyte char boundary */
00148        wrap_width -= (wrap_width % fse->max_logical_extent.width);
00149       }
00150       /* avoid creating 0 width/height */
00151       if (width == 0) width = 15;
00152       if (height == 0) height = 15;
00153 
00154 #if SET_PREEDIT_XMARGIN
00155       /* calculate margin */
00156       x_margin = width/5;
00157 #endif
00158       y_margin = height/5;
00159 
00160       width += x_margin * 2;
00161 
00162 #ifdef MOVE_SPOTLOCATION
00163       if (XIMP_CHK_PRESPOTLMASK(ic)) {
00164        XPoint point;
00165        x = ic->core.preedit_attr.spot_location.x;
00166        y = ic->core.preedit_attr.spot_location.y;
00167        XFactoryGetLocationOnScreen(display,
00168                                 ic->core.focus_window, x, y, &point);
00169        if (preedit->fontset) {
00170          XFontSetExtents *fse;
00171          fse = XExtentsOfFontSet(preedit->fontset);
00172          if (fse) {
00173            int height = fse->max_logical_extent.height;
00174            point.y += height;
00175            wrap_width = fse->max_logical_extent.width * 40;
00176          }
00177        }
00178        x = point.x;
00179        y = point.y;
00180       }
00181 #endif
00182       if (width <= wrap_width) {
00183        /* can draw all chars in one line */
00184        preedit_area[0].x = x_margin;
00185        preedit_area[0].y = height - y_margin;
00186        preedit_area[0].char_offset = 0;
00187        preedit_area[0].char_len = preedit_chars->wchar_len;
00188 
00189         XFactoryAdjustPlacementInsideScreen(ic->core.im->core.display,
00190                                        preedit_area[0].window,
00191                                        x, y, width, height, &x, &y);
00192 
00193        if (preedit_area[0].active_lines != 0) {
00194          preedit_area[0].active_lines = 0;
00195        } else {
00196          if (preedit_cache->win_x == x &&
00197              preedit_cache->win_y == y &&
00198              preedit_cache->win_width == width &&
00199              preedit_cache->win_height == height) {
00200            return;
00201          }
00202        }
00203        hints.flags = PSize | PPosition;
00204        hints.x = x;
00205        hints.y = y;
00206        hints.width  = width;
00207        hints.height = height;
00208        XSetWMNormalHints(display, preedit_area[0].window, &hints);
00209        wm_hints.flags = InputHint;
00210        wm_hints.input = False;
00211        XSetWMHints(display, preedit_area[0].window, &wm_hints);
00212        XMoveResizeWindow(ic->core.im->core.display,
00213                        preedit_area[0].window,
00214                        x, y, width, height);
00215        /* data cache */
00216        preedit_cache->win_x = x;
00217        preedit_cache->win_y = y;
00218        preedit_cache->win_width = width;
00219        preedit_cache->win_height = height;
00220       } else {
00221        /* draw more than two lines */
00222        int left;
00223        wchar_t *wcstr;
00224        int n;
00225        PreeditLine preedit_line;
00226 
00227        if (preedit_area[0].alloc_lines == 0) {
00228          preedit_area[0].alloc_lines = 10;
00229          preedit_area[0].lines =
00230            (PreeditLine)Xmalloc(sizeof(PreeditLineRec) *
00231                              preedit_area[0].alloc_lines);
00232          if (!preedit_area[0].lines) return;
00233        }
00234 
00235        preedit_line = preedit_area[0].lines;
00236        left = preedit_chars->wchar_len;
00237        wcstr = preedit_chars->wchar;
00238        n = 0;
00239        while (left) {
00240          wchar_t *p = wcstr;
00241          int cur_width = 0;
00242          int i;
00243          for (i = 1; i <= left; i++) {
00244            cur_width += XwcTextEscapement(preedit->fontset, p++, 1);
00245            if (cur_width > wrap_width) break;
00246          }
00247          preedit_line[n].x = 0;
00248          preedit_line[n].y = height * (n + 1) - y_margin;
00249          preedit_line[n].char_offset = wcstr - preedit_chars->wchar;
00250          preedit_line[n].char_len = i - 1;
00251          n++;
00252          left -= (i - 1);
00253          wcstr += i - 1;
00254          if (left > 0) {
00255            if (n == preedit_area[0].alloc_lines) {
00256              preedit_area[0].alloc_lines += 10;
00257              preedit_area[0].lines =
00258               (PreeditLine)Xrealloc(preedit_area[0].lines,
00259                                   sizeof(PreeditLineRec) *
00260                                   preedit_area[0].alloc_lines);
00261              if (!preedit_area[0].lines) return;
00262              preedit_line = preedit_area[0].lines;
00263            } else {
00264              continue;
00265            }
00266          }
00267        }
00268        preedit_area[0].active_lines = n;
00269        height = height * n;
00270         XFactoryAdjustPlacementInsideScreen(ic->core.im->core.display,
00271                                        preedit_area[0].window,
00272                                        x, y, wrap_width, height, &x, &y);
00273        XMoveResizeWindow(ic->core.im->core.display,
00274                        preedit_area[0].window,
00275                        x, y, wrap_width, height);
00276       }
00277     }
00278   }
00279   return;
00280 }
00281 
00282 static void
00283 move(XicCommon ic, XPointer call_data) {
00284   /* nothing to do */
00285   return;
00286 }
00287 
00288 static PreeditCB preedit_nothing_methods[] = {
00289   create,                   /* PREEDIT_CREATE */
00290   set_window,               /* PREEDIT_WIN */
00291   SetPreeditForeground,            /* PREEDIT_FG */
00292   SetPreeditBackground,            /* PREEDIT_BG */
00293   SetPreeditFont,           /* PREEDIT_FONT */
00294   move,                            /* PREEDIT_MOVE */
00295   PreeditStart,                    /* PREEDIT_START */
00296   PreeditDrawText,          /* PREEDIT_DRAW */
00297   PreeditCaret,                    /* PREEDIT_CARET */
00298   PreeditDone,                     /* PREEDIT_DONE */
00299   DestroyPreedit            /* PREEDIT_DESTROY */
00300 };
00301 
00302 void
00303 ChangePreeditNothing(XIC xic, PreeditAttr reason, XPointer call_data) {
00304   XicCommon ic = (XicCommon)xic;
00305   if (reason > PREEDIT_DESTROY) return;
00306   preedit_nothing_methods[reason](ic, call_data);
00307   return;
00308 }