Logo Search packages:      
Sourcecode: skkinput version File versions  Download package

XIMInputContext.c

/* # skkinput (Simple Kana-Kanji Input)
 *
 * This file is part of skkinput.
 * Copyright (C) 2002
 * Takashi SAKAMOTO (PXG01715@nifty.ne.jp)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with skkinput; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <sys/time.h>
#include "XIMInputContextP.h"
#include "XIMClient.h"
#include "XIMData.h" 
#include "commondef.h"
#include "OverWin.h"
#include "OffWin.h"
#include "OnWin.h"
#include "SeparateWin.h"
#include "MyDispatch.h"
#include "resrcs.h"
#include "FontMgr.h"
#include "HistMgr.h"

#define     DEFAULT_XIM_PREEDIT_LINESPACING           (14)
#define     DEFAULT_XIM_STATUS_LINESPACING            (14)

static      Boolean     ximInputContext_createFrame               (XIMInputContext*) ;
static      void  ximInputContext_onPreeditStart            (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onPreeditDraw       (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onPreeditCaret            (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onPreeditDone       (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onStatusStart       (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onStatusDraw        (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onStatusDone        (Widget, XtPointer, XtPointer) ;

static      void  ximInputContext_onKeyBackNotify     (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onEndNotify               (Widget, XtPointer, XtPointer) ;
static      void  ximInputContext_onTextNotify        (Widget, XtPointer, XtPointer) ;

static      Boolean     ximInputContext_packetToCombinep    (XIMPacket*) ;
static      XIMPacket*  ximInputContext_combineXimCommit(XIMInputContext*, XIMPacket*, XIMPacket*) ;

XIMInputContext*
XIMInputContext_Create (
      register XIMInputMethod*      pInputMethod,
      register int                        nID)
{
      register XIMInputContext*     pInputContext ;
      register int                        i ;

      pInputContext     = malloc (sizeof (XIMInputContext)) ;
      if (pInputContext == NULL)
            return      NULL ;

      pInputContext->m_pInputMethod       = pInputMethod ;
      pInputContext->m_pNext                    = NULL ;
      pInputContext->m_woID                     = nID ;
      pInputContext->m_ulAttributeMask    = 0L ;
      pInputContext->m_wgTopFrame               = NULL ;
      pInputContext->m_ulResetState       = XIMInitialState ;
      pInputContext->m_preeditState       = XIMPreeditDisable ;
      pInputContext->m_wndClient                = None ;
      pInputContext->m_wndFocus                 = None ;
      pInputContext->m_dwFilterEvents           = 0 ;
      pInputContext->m_uSyncStatus        = 0 ;
      pInputContext->m_dwInputStyle       = XIMStatusNothing | XIMPreeditNothing ;
      pInputContext->m_pNext                    = NULL ;
      pInputContext->m_fDestroy                 = False ;
      pInputContext->m_fFocus                   = False ;
      pInputContext->m_atPStdColormap           = None ;
      pInputContext->m_atSStdColormap           = None ;
      TQueue_Initialize     (&pInputContext->m_quePacketSpool,   sizeof (XIMPacket*)) ;
      TVarbuffer_Initialize (&pInputContext->m_vbufPFontSetName, sizeof (char)) ;
      TVarbuffer_Initialize (&pInputContext->m_vbufSFontSetName, sizeof (char)) ;
      pInputContext->m_ConvAttr.mask            = 0 ;

      /* フォントセットの初期化を行う。*/
      for (i = 0 ; i < NUMBER_OF_CHARSET ; i ++)
            pInputContext->m_fontset [i]  = NULL ;
      pInputContext->m_nFontHeight        = DEFAULT_XIM_PREEDIT_LINESPACING ;

      return      pInputContext ;
}     

void
XIMInputContext_Destroy (
      register XIMInputContext*     pThis)
{
      register XIMPacket**    ppPacket ;
      register int                  nPacket ;
      register Widget               gwClient ;

      ppPacket    = TQueue_GetData  (&pThis->m_quePacketSpool) ;
      nPacket           = TQueue_GetUsage (&pThis->m_quePacketSpool) ;
      while (nPacket -- > 0) 
            XIMPacket_Release (*ppPacket ++) ;

      TQueue_Uninitialize     (&pThis->m_quePacketSpool) ;
      TVarbuffer_Uninitialize (&pThis->m_vbufPFontSetName) ;
      TVarbuffer_Uninitialize (&pThis->m_vbufSFontSetName) ;

      gwClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      if (gwClient != NULL) {
            register Display* pDisplay    = XtDisplay (gwClient) ;
            register int            i ;

            /* フォントを解放する。*/
            for (i = 0 ; i < NUMBER_OF_CHARSET ; i ++){
                  fontMgr_FreeFont (pDisplay,  pThis->m_fontset [i]) ;
                  pThis->m_fontset [i]    = NULL ;
            }
      }

      if (pThis->m_wgTopFrame != NULL) {
            register Widget   wgFrame     = pThis->m_wgTopFrame ;
            XtRemoveCallback (wgFrame, XtNfixNotify,   ximInputContext_onTextNotify,   (XtPointer)pThis) ;
            XtRemoveCallback (wgFrame, XtNendNotify,   ximInputContext_onEndNotify,    (XtPointer)pThis) ;
            XtRemoveCallback (wgFrame, XtNkeybackNotify, ximInputContext_onKeyBackNotify, (XtPointer)pThis) ;

            if (XtIsSubclass (wgFrame, onthespotWinWidgetClass)) {
                  XtRemoveAllCallbacks (wgFrame, XtNpreeditStartCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNpreeditDrawCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNpreeditCaretCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNpreeditDoneCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNstatusStartCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNstatusDrawCallback) ;
                  XtRemoveAllCallbacks (wgFrame, XtNstatusDoneCallback) ;
            }
      }
      pThis->m_wgTopFrame                 = NULL ;

      free (pThis) ;
      return ;
}

void
XIMInputContext_SetNext (
      register XIMInputContext*     pThis,
      register XIMInputContext*     pNext)
{
      assert (pThis != NULL) ;
      pThis->m_pNext    = pNext ;
      return ;
}

XIMInputContext*
XIMInputContext_GetNext (
      register XIMInputContext*     pThis)
{
      assert (pThis != NULL) ;
      return      pThis->m_pNext ;
}

int
XIMInputContext_GetID (
      register XIMInputContext*     pThis)
{
      assert (pThis != NULL) ;
      return      pThis->m_woID ;
}

Boolean
XIMInputContext_Alivep (
      register XIMInputContext*     pThis)
{
      assert (pThis != NULL) ;
      return      !pThis->m_fDestroy ;
}

Boolean
XIMInputContext_ForwardEvent (
      register XIMInputContext*     pThis,
      register XEvent*              pXEvent)
{
#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext_ForwardEvent (%p, %p)\n", pThis, pXEvent) ;
#endif

      if (pXEvent->type != KeyPress) 
            return      True ;

      pXEvent->xkey.send_event      = True ;
      XtCallActionProc (pThis->m_wgTopFrame, "KeyDownEventHandler", pXEvent, (String*)NULL, (Cardinal)0) ;
      return      True ;
}

Boolean
XIMInputContext_StartConversion (
      register XIMInputContext*     pThis)
{
      register Widget   wgClient ;

#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext_StartConversion (%p)\n", pThis) ;
#endif

      if (pThis->m_preeditState == XIMPreeditEnable)
            return      True ;

      /*    一番最初の変換動作の場合には Widget を作成する必要がある。
       */
      if (pThis->m_wgTopFrame == NULL) {
            if (!ximInputContext_createFrame (pThis))
                  return      False ;
      }
      pThis->m_preeditState   = XIMPreeditEnable ;
      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      XIMInputContext_Activate (pThis, True) ;
      pThis->m_fFocus   = True ;
      return      True ;
}

Boolean
XIMInputContext_EndConversion (
      register XIMInputContext*     pThis)
{
      register Widget   wgClient ;

#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext_StartConversion (%p)\n", pThis) ;
#endif
      if (pThis->m_preeditState == XIMPreeditDisable)
            return      False ;

      pThis->m_preeditState   = XIMPreeditDisable ;
      XIMInputContext_Activate (pThis, False) ;

      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      //XIMClient_PreeditStateChange (wgClient, pThis->m_pInputMethod, pThis) ;
      return      True ;
}

Boolean
XIMInputContext_ResetConversion (
      register XIMInputContext*     pThis)
{
      return      True ;
}

unsigned
XIMInputContext_GetSyncMode (
      register XIMInputContext*     pThis)
{
      assert (pThis != NULL) ;
      return      pThis->m_uSyncStatus ;
}

void
XIMInputContext_SetSyncMode (
      register XIMInputContext*     pThis,
      register unsigned             uMode)
{
      assert (pThis != NULL) ;
      assert ((uMode & XIMClientSync) || !(pThis->m_uSyncStatus & ~XIMClientSync)) ;
      pThis->m_uSyncStatus    |= uMode ;
      return ;
}

void
XIMInputContext_UnsetSyncMode (
      register XIMInputContext*     pThis,
      register unsigned             uMode)
{
      assert (pThis != NULL) ;

      pThis->m_uSyncStatus    &= ~uMode ;
      return ;
}

Boolean
XIMInputContext_SpoolPacket (
      register XIMInputContext*     pThis,
      XIMPacket*                          pPacket)
{
      /*    Spool されている直前の packet が XIM_COMMIT ならば、連結する。*/
      if (ximInputContext_packetToCombinep (pPacket)) {
            register XIMPacket**    ppSpooledPacket ;
            register int                  npSpooledPacket ;

            ppSpooledPacket   = TQueue_GetData  (&pThis->m_quePacketSpool) ;
            npSpooledPacket   = TQueue_GetUsage (&pThis->m_quePacketSpool) ;
            if (npSpooledPacket > 0) {
                  register XIMPacket*           pLastPacket ;

                  pLastPacket = *(ppSpooledPacket + npSpooledPacket - 1) ;
                  if (ximInputContext_packetToCombinep (pLastPacket)) {
                        register XIMPacket*     pNewPacket ;
                        pNewPacket  = ximInputContext_combineXimCommit (pThis, pLastPacket, pPacket) ;
                        if (pNewPacket == NULL)
                              return      False ;
                        XIMPacket_Release (pLastPacket) ;
                        *(ppSpooledPacket + npSpooledPacket - 1)  = pNewPacket ;
                        return      True ;
                  }
            }
      }

      if (! (TQueue_In (&pThis->m_quePacketSpool, &pPacket, 1)))
            return      False ;
      XIMPacket_AddRef (pPacket) ;
      return      True ;
}

XIMPacket*
XIMInputContext_GetSpooledPacket (
      register XIMInputContext*     pThis)
{
      XIMPacket*        pPacket ;
      register int      nOut ;

      nOut  = TQueue_Out (&pThis->m_quePacketSpool, &pPacket, 1) ;
      if (nOut <= 0)
            return      NULL ;
      return      pPacket ;
}

XIMPacket*
XIMInputContext_LookSpooledPacket (
      register XIMInputContext*     pThis)
{
      register TQueue*  pQueue ;

      assert (pThis != NULL) ;

      pQueue      = &pThis->m_quePacketSpool ;
      if (TQueue_GetUsage (pQueue) <= 0)
            return      NULL ;

      return      TQueue_GetData (pQueue) ;
}

int
XIMInputContext_GetNumberOfSpooledPacket (
      register XIMInputContext*     pThis)
{
      return      TQueue_GetUsage (&pThis->m_quePacketSpool) ;
}

Boolean
XIMInputContext_SetFocus (
      register XIMInputContext*     pThis)
{
      if (pThis->m_preeditState == XIMPreeditDisable)
            return      False ;

#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetFocus (%p, %d)\n",
                   pThis, pThis->m_woID) ;
#endif
      /*    setfocus */
      pThis->m_fFocus   = True ;
      if (pThis->m_wgTopFrame != NULL) 
            XIMInputContext_Activate (pThis, True) ;
      return      True ;
}

Boolean
XIMInputContext_UnsetFocus (
      register XIMInputContext*     pThis)
{
      if (pThis->m_preeditState == XIMPreeditDisable)
            return      False ;

#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_UnsetFocus (%p, %d)\n",
                   pThis, pThis->m_woID) ;
#endif
      /*    unsetfocus */
      pThis->m_fFocus   = False ;
      if (pThis->m_wgTopFrame != NULL) 
            XIMInputContext_Activate (pThis, False) ;
      return      True ;
}

Boolean
XIMInputContext_SetInputStyle (
      register XIMInputContext*     pThis,
      register XIMStyle             imstyle)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetInputStyle (%p, %d)\n",
                   pThis, imstyle) ;
#endif
      pThis->m_dwInputStyle         = imstyle ;
      pThis->m_ConvAttr.mask  |= CAInputStyle ;
      return      True ;
}

Boolean
XIMInputContext_SetClientWindow (
      register XIMInputContext*     pThis,
      register Window                     wndClient)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetClientWindow (%p, %x)\n",
                   pThis, wndClient) ;
#endif
      /*    client window は一度しか設定できない。*/
      if (pThis->m_wndClient != None)
            return      False ;
      pThis->m_wndClient      = wndClient ;
      return      True ;
}

Boolean
XIMInputContext_SetFocusWindow (
      register XIMInputContext*     pThis,
      register Window                     wndFocus)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetFocusWindow (%p, %x)\n",
                   pThis, wndFocus) ;
#endif
      if (!(pThis->m_ConvAttr.mask & CAFocusWindow) ||
            pThis->m_ConvAttr.value.focus_window != wndFocus) {
            pThis->m_ConvAttr.value.focus_window  = wndFocus ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;
                  ca.mask                             = CAFocusWindow ;
                  ca.value.focus_window   = wndFocus ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      pThis->m_ConvAttr.mask  |= CAFocusWindow ;
      return      True ;
}

Boolean
XIMInputContext_SetResetState (
      register XIMInputContext*     pThis,
      register XIMResetState        ulResetState)
{
      if (ulResetState != XIMInitialState && ulResetState != XIMPreserveState)
            return      False ;
      pThis->m_ulResetState   = ulResetState ;
      return      True ;
}

Boolean
XIMInputContext_SetPreeditState (
      register XIMInputContext*     pThis,
      register XIMPreeditState      ulPreeditState)
{
      if (ulPreeditState != XIMPreeditEnable && ulPreeditState != XIMPreeditDisable)
            return      False ;
      if (ulPreeditState != pThis->m_preeditState) {
            Widget      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
            if (ulPreeditState == XIMPreeditEnable) {
                  XIMClient_ControlEventFlow (wgClient, pThis->m_pInputMethod, pThis, True) ;
                  XIMInputContext_StartConversion (pThis) ;
            } else {
                  XIMClient_ControlEventFlow (wgClient, pThis->m_pInputMethod, pThis, False) ;
                  XIMInputContext_EndConversion (pThis) ;
            }
      }
      return      True ;
}

XIMStyle
XIMInputContext_GetInputStyle (
      register XIMInputContext*     pThis)
{
      return      pThis->m_dwInputStyle ;
}

Window
XIMInputContext_GetClientWindow (
      register XIMInputContext*     pThis)
{
      return      pThis->m_wndClient ;
}

Window
XIMInputContext_GetFocusWindow (
      register XIMInputContext*     pThis)
{
      return      pThis->m_wndFocus ;
}

CARD32
XIMInputContext_GetFilterEvents (
      register XIMInputContext*     pThis)
{
      return      pThis->m_dwFilterEvents ;
}

XIMResetState
XIMInputContext_GetResetState (
      register XIMInputContext*     pThis)
{
      return      pThis->m_ulResetState ;
}

XIMPreeditState
XIMInputContext_GetPreeditState (
      register XIMInputContext*     pThis)
{
      return      pThis->m_preeditState ;
}

Boolean
XIMInputContext_SetPreeditArea (
      register XIMInputContext*     pThis,
      register const XRectangle*    pRect)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext[%d]: SetPreeditArea (%d, %d, %d, %d)\n",
                   pThis->m_woID,
                   pRect->x, pRect->y, pRect->width, pRect->height) ;
#endif
#if 1
      if (pRect->width <= 0 || pRect->height <= 0)
            return      False ;
#endif
      if (! (pThis->m_ConvAttr.mask & CAClientArea) ||
            ! (pThis->m_ConvAttr.value.client_area.x == pRect->x &&
               pThis->m_ConvAttr.value.client_area.y == pRect->y &&
               pThis->m_ConvAttr.value.client_area.width  == pRect->width &&
               pThis->m_ConvAttr.value.client_area.height == pRect->height)) {
            pThis->m_ConvAttr.mask  |= CAClientArea ;
            pThis->m_ConvAttr.value.client_area = *pRect ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;
                  ca.mask                             = CAClientArea ;
                  ca.value.client_area    = *pRect ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditAreaNeeded (
      register XIMInputContext*     pThis,
      register const XRectangle*    pRect)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetPreeditAreaNeeded (%p, %p)\n",
                   pThis, pRect) ;
#endif
      /*    ClientAreaNeeded が入ると、ClientArea のサイズは
       *    こちらにひっぱられる。
       */
      if (! (pThis->m_ConvAttr.mask & CAClientAreaNeeded) ||
            ! (pThis->m_rcClientAreaNeeded.x == pRect->x &&
               pThis->m_rcClientAreaNeeded.y == pRect->y &&
               pThis->m_rcClientAreaNeeded.width  == pRect->width &&
               pThis->m_rcClientAreaNeeded.height == pRect->height)) {
            pThis->m_ConvAttr.mask  |= CAClientAreaNeeded ;
            pThis->m_rcClientAreaNeeded   = *pRect ;
      }
      return      True ;
}

Boolean
XIMInputContext_SetSpotLocation (
      register XIMInputContext*     pThis,
      register const XPoint*        pPos)
{
#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext_SetSpotLocation (%p, %d, %d)\n",
                   pThis, pPos->x, pPos->y) ;
#endif
      if (!(pThis->m_ConvAttr.mask & CASpotLocation) ||
            !(pThis->m_ConvAttr.value.spot_x == pPos->x &&
              pThis->m_ConvAttr.value.spot_y == pPos->y)) {
            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg          ca ;

                  ca.mask                 = CASpotLocation ;
                  ca.value.spot_x   = pPos->x ;
                  ca.value.spot_y   = pPos->y ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
            pThis->m_ConvAttr.value.spot_x      = pPos->x ;
            pThis->m_ConvAttr.value.spot_y      = pPos->y ;
            pThis->m_ConvAttr.mask  |= CASpotLocation ;
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditColormap (
      register XIMInputContext*     pThis,
      register Colormap             colormap)
{
      if (! (pThis->m_ConvAttr.mask & CAColormap) ||
            pThis->m_ConvAttr.value.colormap != colormap) {
            pThis->m_ConvAttr.mask  |= CAColormap ;
            pThis->m_ConvAttr.value.colormap    = colormap ;

            if (pThis->m_wgTopFrame) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                       = CAColormap ;
                  ca.value.colormap = colormap ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditStdColormap (
      register XIMInputContext*     pThis,
      register Atom                       atStdColormap)
{
      register Widget         gw                = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      register Display* pDisplay    = XtDisplay (gw) ;
      register Window         wndFocus ;
      XStandardColormap*      pStdColormap ;
      int                           nCount ;

#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetPreeditStdColormap (%p, %lx)\n",
                               pThis, atStdColormap) ;
#endif

      if (atStdColormap == None) 
            return      False ;

      wndFocus    = pThis->m_wndClient ;
      if (pThis->m_ConvAttr.mask & CAFocusWindow)
            wndFocus    = pThis->m_ConvAttr.value.focus_window ;
      if (wndFocus == None)
            return      False ;

      if (!XGetRGBColormaps (pDisplay, wndFocus, &pStdColormap, &nCount, atStdColormap))
            return      False ;

      pThis->m_atPStdColormap = atStdColormap ;

      /*    標準でない colormap が割り当てられていれば、それで十分。*/
      if (! (pThis->m_ConvAttr.mask & CAColormap) && nCount > 0) {
            register Colormap colormap    = pStdColormap->colormap ;
            pThis->m_ConvAttr.value.colormap    = colormap ;
            pThis->m_ConvAttr.mask                    |= CAColormap ;

            if (pThis->m_wgTopFrame) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                       = CAColormap ;
                  ca.value.colormap = colormap ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ; 
}

Boolean
XIMInputContext_SetPreeditForeground (
      register XIMInputContext*     pThis,
      register unsigned long        ulForeground)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetPreeditForeground (%p, %lx)\n",
                   pThis, ulForeground) ;
#endif
      if (! (pThis->m_ConvAttr.mask & CAForegroundPixel) ||
            pThis->m_ConvAttr.value.foreground != ulForeground) {
            pThis->m_ConvAttr.mask  |= CAForegroundPixel ;
            pThis->m_ConvAttr.value.foreground  = ulForeground ;
            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                       = CAForegroundPixel ;
                  ca.value.foreground     = ulForeground ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditBackground (
      register XIMInputContext*     pThis,
      register unsigned long        ulBackground)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetPreeditBackground (%p, %lx)\n",
                   pThis, ulBackground) ;
#endif
      if (! (pThis->m_ConvAttr.mask & CABackgroundPixel) ||
            pThis->m_ConvAttr.value.background != ulBackground) {
            pThis->m_ConvAttr.mask  |= CABackgroundPixel ;
            pThis->m_ConvAttr.value.background  = ulBackground ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                       = CABackgroundPixel ;
                  ca.value.background     = ulBackground ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditBackgroundPixmap (
      register XIMInputContext*     pThis,
      register Pixmap                     pixmap)
{
      return      True ;
}

Boolean
XIMInputContext_SetPreeditFontSet (
      register XIMInputContext*     pThis,
      register const char*          pBaseName,
      register int                        nBaseNameLength)
{
      register const char*    pPFontSetName ;
      register int                  nPFontSetName ;

      pPFontSetName     = TVarbuffer_GetBuffer (&pThis->m_vbufPFontSetName) ;
      nPFontSetName     = TVarbuffer_GetUsage  (&pThis->m_vbufPFontSetName) - 1 ;

      if (! (pThis->m_ConvAttr.mask & CAFonts) ||
            nPFontSetName != nBaseNameLength ||
            strncmp (pPFontSetName, pBaseName, nPFontSetName) != 0) {
            register Display*       pDisplay ;
            register Widget               wgClient ;
            register const char*    pFontSetName ;
            int                                 nHeight, nAscent ;

            /*    フォントの変更の必要がある。*/
            TVarbuffer_Clear (&pThis->m_vbufPFontSetName) ;
            TVarbuffer_Add (&pThis->m_vbufPFontSetName, pBaseName, nBaseNameLength) ;
            TVarbuffer_Add (&pThis->m_vbufPFontSetName, "\0", 1) ;

            pFontSetName      = TVarbuffer_GetBuffer (&pThis->m_vbufPFontSetName) ;
            assert (pThis->m_pInputMethod != NULL) ;
            wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
            assert (wgClient != NULL) ;
            pDisplay          = XtDisplay (wgClient) ;

#if defined (DEBUG) || 0
            fprintf (stderr, "PreeditFontSet => \"%s\"\n", pFontSetName) ;
#endif
            fontMgr_PrepareFontByName (pDisplay, pThis->m_fontset, (unsigned char*)pFontSetName) ;
            fontMgr_GetFontSetInfo (pThis->m_fontset, &nHeight, &nAscent) ;
            pThis->m_nFontHeight    = nHeight ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                       = CAFonts ;
                  ca.value.fontset  = pThis->m_fontset ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
            pThis->m_ConvAttr.mask  |= CAFonts ;
            pThis->m_ConvAttr.value.fontset     = pThis->m_fontset ;

            /*    フォントが変更されると line-spacing の情報は無効になる。*/
            pThis->m_ConvAttr.mask  &= ~CALineSpacing ;
      }
      return      True ;
}

Boolean
XIMInputContext_SetPreeditLineSpacing (
      register XIMInputContext*     pThis,
      register int                        nLineSpacing)
{
#if defined (DEBUG) || 0
      fprintf (stderr, "XIMInputContext_SetPreeditLineSpacing (%p, %d)\n",
                   pThis, nLineSpacing) ;
#endif
      if (! (pThis->m_ConvAttr.mask & CALineSpacing)) {
            pThis->m_ConvAttr.mask  |= CALineSpacing ;
            pThis->m_ConvAttr.value.linespacing = nLineSpacing ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                             = CALineSpacing ;
                  ca.value.linespacing    = nLineSpacing ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

/*
 *(関数名)
 *    virtual Boolean
XIMInputContext_SetPreeditCursor (Cursor cursor) ;
 *(コメント)
 *    Preedit Area のカーソルを設定する。
 */
Boolean
XIMInputContext_SetPreeditCursor (
      register XIMInputContext*     pThis,
      register Cursor                     cursor)
{
      return      False ;
}

/*
 *(関数名)
 *    virtual bool      GetPreeditArea (XRectangle* pArea) const ;
 *(コメント)
 *    Preedt Area の大きさを返す。
 *    …Client Window がリサイズを発行してくれないと Preedit Area
 *    の現在の大きさを正しく持つことはできない。
 *    この点…どう解決すべきか。(そもそもリサイズしたからって単純
 *    に領域を広げたくない場合もあるだろうし)
 */
Boolean
XIMInputContext_GetPreeditArea (
      register XIMInputContext*     pThis,
      register XRectangle*          pRect)
{
      assert (pThis != NULL) ;
      assert (pRect != NULL) ;

      /*
       *    PreeditArea を持たないのであれば、必要な領域を返す必要はない。
       */
      if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditNothing)
            return      True ;

      if (pThis->m_ConvAttr.mask & CAClientArea) {
            /*    既に表示領域が設定されている。*/
            memcpy (pRect, &pThis->m_ConvAttr.value.client_area, sizeof (XRectangle)) ;
      } else {
            if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditPosition){
                  register Display* pDisplay ;
                  register Window         wndFocus ;

                  /*
                   *    表示領域が設定されたことがない、
                   *          かつ
                   *    表示に必要な領域の設定もされたことがない
                   *
                   *    また、PreeditPosition のために AreaNeeded が設定されていると
                   *    いうわけではない。(PreeditArea なら AreaNeeded が設定されてい
                   *    る必要がある)
                   *
                   *    こういう場合には、Focus している Window の領域をとることにする。
                   */
                  wndFocus    = (pThis->m_wndFocus == None)? pThis->m_wndClient : pThis->m_wndFocus ;
                  if (wndFocus != None){
                        register Widget   wgClient ;
                        Window                  wndRoot ;
                        int                     iX, iY ;
                        unsigned int      iWidth, iHeight, iBorder, iDepth ;

                        wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
                        pDisplay    = XtDisplay (wgClient) ;
                        XGetGeometry (pDisplay, wndFocus, &wndRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &iDepth) ;
                        pRect->x          = 0 ;
                        pRect->y          = 0 ;
                        pRect->width      = iWidth ;
                        pRect->height     = iHeight ;
                  } else {
                        /*    Focus, Client Window もなく、ただ Area 情報を尋ねられてしまった…。*/
                        return      False ;
                  }
            } else {
                  /*
                   *    恐らくは PreeditArea (つまり Preedit 領域の Area 情報が必要で
                   *    ある)なので、AreaNeeded が設定されている。
                   *    この場合には AreaNeeded 分だけ確保されたものという仮定のもとに
                   *    値を返す。
                   */
                  if (pThis->m_ConvAttr.mask & CAClientAreaNeeded) {
                        memcpy (pRect, &pThis->m_rcClientAreaNeeded, sizeof (XRectangle)) ;
                  } else {
                        XIMInputContext_GetPreeditAreaNeeded (pThis, pRect) ;
                  }
            }
      }
      return      True ;
}

/*
 *(関数名)
 *    virtual bool      GetPreeditAreaNeeded (XRectangle* pArea) const ;
 *(コメント)
 *    必要とする Preedit Area の大きさをここで返さなければならない。
 *    どの程度の数値が妥当なのかは不明…。
 *    まず、最大値を入れてしまうべきなのか…それともこれだけは必要と
 *    いう最小値を入れてしまうべきなのか…。
 */
Boolean
XIMInputContext_GetPreeditAreaNeeded (
      register XIMInputContext*     pThis,
      register XRectangle*          pRect)
{
      assert (pThis != NULL) ;
      assert (pRect != NULL) ;

      /*
       *    RootWindowStyle ならば PreeditArea は存在しないので、AreaNeeded
       *    を返すことはできない。
       */
      if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditNothing)
            return      True ;

      /*
       *    必要とする領域をどうにか指定する。
       */
      if (pThis->m_ConvAttr.mask & CAClientAreaNeeded) {
            /*
             *    既に必要な領域が計算されている
             *          あるいは
             *    既に必要な領域がクライアントから設定されている
             *    場合には、その数字を使う。
             */
            memcpy (pRect, &pThis->m_rcClientAreaNeeded, sizeof (XRectangle)) ;
      } else {
            /*
             *    必要な領域サイズは計算されておらず、その数値はサーバ任せとなっている。
             */
            if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditArea){
                  register int      nLineSpacing ;
                  /*
                   *    PreeditArea の大きさをこちらで指定する必要がある…
                   *          もしくは
                   *    必要な大きさを申請するチャンスがある…
                   *    さて、どの程度要求するべきなのか?
                   */
                  nLineSpacing      = XIMInputContext_GetPreeditLineSpacing (pThis) ;
                  if ((pThis->m_dwInputStyle & XIMStatusMask) == XIMStatusArea &&
                        (pThis->m_ConvAttr.mask & CAStatusAreaNeeded)) {
                        pRect->x          = 0 ;
                        pRect->y          = 0 ;
                        pRect->width      = pThis->m_rcStatusAreaNeeded.width ;
                        pRect->height     = nLineSpacing ;
                  } else {
                        pRect->x          = 0 ;
                        pRect->y          = 0 ;
                        pRect->width      = nLineSpacing * 20 ;
                        pRect->height     = nLineSpacing * 20 ;
                  }
            } else {
                  /*
                   *    OverTheSpot Style の場合には設定しない…?
                   *    どうやら、ここに要求が来ることはなさそう。
                   */
                  register Window         wndFocus ;
                  wndFocus    = (pThis->m_wndFocus == None)? pThis->m_wndClient : pThis->m_wndFocus ;
                  if (wndFocus != None){
                        register Display* pDisplay ;
                        register Widget         wgClient ;
                        Window                  wndRoot ;
                        int                     iX, iY ;
                        unsigned int      iWidth, iHeight, iBorder, iDepth ;

                        wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
                        pDisplay    = XtDisplay (wgClient) ;
                        XGetGeometry (pDisplay, wndFocus, &wndRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &iDepth) ;
                        pRect->x          = 0 ;
                        pRect->y          = 0 ;
                        pRect->width      = iWidth ;
                        pRect->height     = iHeight ;
                  } else {
                        //    Focus, Client Window もなく、ただ Area 情報を尋ねられてしまった…。
                        return      False ;
                  }
            }
      }
      return      True ;
}

/*
 *(関数名)
 *    virtual const XPoint    GetSpotLocation () const ;
 *(コメント)
 *    現在の Composition Window の位置を返す。
 *    この Attribute は Status にはない。
 */
Boolean
XIMInputContext_GetSpotLocation (
      register XIMInputContext*     pThis,
      register XPoint*              pPos)
{
      assert (pThis != NULL) ;
      assert (pPos  != NULL) ;
      /*
       *    UIWindow から Text の Position を得る。
       *    ただし、RootWindowStyle の場合には SpotLocation は意味を持たない。
       *    XIMStyle & XIMPreeditPosition だった時には効果があるというところか?
       */
      if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditPosition &&
            (pThis->m_ConvAttr.mask & CASpotLocation)) {
            pPos->x     = pThis->m_ConvAttr.value.spot_x ;
            pPos->y     = pThis->m_ConvAttr.value.spot_y ;
      } else {
            pPos->x     = 0 ;
            pPos->y     = 0 ;
      }
      return      True ;
} 

/*
 *(関数名)
 *    virtual const Colormap& GetPreeditColormap () const ;
 *(コメント)
 *    PreeditArea の現在の Colormap を得る。
 *    デフォルトは当然のことながら、
 *          DefaultColormap (display, 0)
 *    を使っている。
 */
Colormap
XIMInputContext_GetPreeditColormap (
      register XIMInputContext*     pThis)
{
      if (! (pThis->m_ConvAttr.mask & CAColormap)) 
            return      None ;
      return      pThis->m_ConvAttr.value.colormap ;
}

/*
 *(関数名)
 *    virtual const Colormap& GetPreeditColormap () const ;
 *(コメント)
 *    PreeditArea の Standard Colormap を得る。
 *    デフォルトは当然のことながら、
 *          DefaultColormap (display, 0)
 *    を使っている。
 */
Atom
XIMInputContext_GetPreeditStdColormap (
      register XIMInputContext*     pThis)
{
      return      pThis->m_atPStdColormap ;
}

unsigned long
XIMInputContext_GetPreeditForeground (
      register XIMInputContext*     pThis)
{
      if (! (pThis->m_ConvAttr.mask & CAForegroundPixel)) {
            /* What to do? */
      }
      return      pThis->m_ConvAttr.value.foreground ;
}

unsigned long
XIMInputContext_GetPreeditBackground (
      register XIMInputContext*     pThis)
{
      if (! (pThis->m_ConvAttr.mask & CABackgroundPixel)) {
            /* What to do? */
      }
      return      pThis->m_ConvAttr.value.background ;
}

Pixmap
XIMInputContext_GetPreeditBackgroundPixmap (
      register XIMInputContext*     pThis)
{
      if (! (pThis->m_ConvAttr.mask & CABackgroundPixmap)) {
            /* What to do? */
      }
      return      pThis->m_ConvAttr.value.background_pixmap ;
}

const char*
XIMInputContext_GetPreeditFontSet (
      register XIMInputContext*     pThis)
{
      return      TVarbuffer_GetBuffer (&pThis->m_vbufPFontSetName) ;
}

int   
XIMInputContext_GetPreeditLineSpacing (
      register XIMInputContext*     pThis)
{
      assert (pThis != NULL) ;

      if (! (pThis->m_ConvAttr.mask & (CALineSpacing | CAFonts)))
            return      DEFAULT_XIM_PREEDIT_LINESPACING ;

      if (pThis->m_ConvAttr.mask & CALineSpacing)
            return      pThis->m_ConvAttr.value.linespacing ;

      return      pThis->m_nFontHeight ;
}

Cursor
XIMInputContext_GetPreeditCursor (
      register XIMInputContext*     pThis)
{
      if (! (pThis->m_ConvAttr.mask & CACursor)) 
            return      None ;
      return      pThis->m_ConvAttr.value.cursor ;
}

/*
 *    Status 側の Interface
 */
Boolean
XIMInputContext_SetStatusArea (
      register XIMInputContext*     pThis,
      register const XRectangle*    pRect)
{
#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext[%d]: SetStatusArea (%d, %d, %d, %d)\n",
                   pThis->m_woID,
                   pRect->x, pRect->y, pRect->width, pRect->height) ;
#endif

      if (! (pThis->m_ConvAttr.mask & CAStatusArea) ||
            ! (pThis->m_ConvAttr.value.status_area.x == pRect->x &&
               pThis->m_ConvAttr.value.status_area.y == pRect->y &&
               pThis->m_ConvAttr.value.status_area.width  == pRect->width &&
               pThis->m_ConvAttr.value.status_area.height == pRect->height)) {
            pThis->m_ConvAttr.mask  |= CAStatusArea ;
            pThis->m_ConvAttr.value.status_area = *pRect ;

            if (pThis->m_wgTopFrame != NULL) {
                  struct ConvAttrsMesg    ca ;

                  ca.mask                             = CAStatusArea ;
                  ca.value.status_area    = *pRect ;
                  XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
            }
      }
      return      True ;
}

Boolean
XIMInputContext_SetStatusAreaNeeded (
      register XIMInputContext*     pThis,
      register const XRectangle*    pRect)
{
      /*    ClientAreaNeeded が入ると、ClientArea のサイズは
       *    こちらにひっぱられる。
       */
#if defined (DEBUG)
      fprintf (stderr, "XIMInputContext[%d]: SetStatusAreaNeeded (%d, %d, %d, %d)\n",
                   pThis->m_woID,
                   pRect->x, pRect->y, pRect->width, pRect->height) ;
#endif
      if (! (pThis->m_ConvAttr.mask & CAStatusAreaNeeded) ||
            ! (pThis->m_rcStatusAreaNeeded.x == pRect->x &&
               pThis->m_rcStatusAreaNeeded.y == pRect->y &&
               pThis->m_rcStatusAreaNeeded.width  == pRect->width &&
               pThis->m_rcStatusAreaNeeded.height == pRect->height)) {
            pThis->m_ConvAttr.mask  |= CAStatusAreaNeeded ;
            pThis->m_rcStatusAreaNeeded   = *pRect ;
      }
      return      True ;
}

Boolean
XIMInputContext_SetStatusColormap (
      register XIMInputContext*     pThis,
      register Colormap             colormap)
{
      /*    currently not implemented. */
      return      True ;
}

Boolean
XIMInputContext_SetStatusStdColormap (
      register XIMInputContext*     pThis,
      register Atom                       atStdColormap)
{
      /*    currently not implemented. */
      return      True ; 
}

Boolean
XIMInputContext_SetStatusForeground (
      register XIMInputContext*     pThis,
      register unsigned long        ulForeground)
{
      /*    currently not implemented. */
      return      True ;
}

Boolean
XIMInputContext_SetStatusBackground (
      register XIMInputContext*     pThis,
      register unsigned long        ulBackground)
{
      /*    currently not implemented. */
      return      True ;
}

Boolean
XIMInputContext_SetStatusBackgroundPixmap (
      register XIMInputContext*     pThis,
      register Pixmap                     pixmap)
{
      /*    currently not implemented. */
      return      True ;
}

/*    Status 領域は今は何もしていないので設定は不可能。
 */
Boolean
XIMInputContext_SetStatusFontSet (
      register XIMInputContext*     pThis,
      register const char*          pBaseName,
      register int                        nBaseNameLength)
{
      /*    currently not implemented. */
      return      True ;
}

Boolean
XIMInputContext_SetStatusLineSpacing (
      register XIMInputContext*     pThis,
      register int                        nLineSpacing)
{
      /*    currently not implemented. */
      return      True ;
}

Boolean
XIMInputContext_SetStatusCursor (
      register XIMInputContext*     pThis,
      register Cursor                     cursor)
{
      /*    currently not implemented. */
      return      True ;
}

/*
 *(関数名)
 *    virtual bool      GetStatusArea (XRectangle* pArea) const ;
 *(コメント)
 *    Preedt Area の大きさを返す。
 *    …Client Window がリサイズを発行してくれないと Status Area
 *    の現在の大きさを正しく持つことはできない。
 *    この点…どう解決すべきか。(そもそもリサイズしたからって単純
 *    に領域を広げたくない場合もあるだろうし)
 */
Boolean
XIMInputContext_GetStatusArea (
      register XIMInputContext*     pThis,
      register XRectangle*          pRect)
{
      assert (pThis != NULL) ;
      assert (pRect != NULL) ;
      if ((pThis->m_dwInputStyle & XIMStatusMask) == XIMStatusNothing)
            return      False ;

      if (pThis->m_ConvAttr.mask & CAStatusArea) {
            memcpy (pRect, &pThis->m_ConvAttr.value.status_area, sizeof (XRectangle)) ;
      } else {
            if ((pThis->m_dwInputStyle & XIMStatusMask) == XIMStatusArea &&
                  (pThis->m_ConvAttr.mask & CAStatusAreaNeeded)) {
                  memcpy (pRect, &pThis->m_rcStatusAreaNeeded, sizeof (XRectangle)) ;
            } else {
                  register int      nLineSpacing ;

                  pRect->x    = 0 ;
                  pRect->y    = 0 ;
                  nLineSpacing      = XIMInputContext_GetStatusLineSpacing (pThis) ;
                  if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditPosition){
                        /*    そもそも line spacing って設定されてないから、ここは修正する
                         *    必要がある。*/
                        pRect->width      = nLineSpacing * 80 / 2 ;
                  } else {
                        pRect->width      = nLineSpacing * 7 / 2 ;
                  }
                  pRect->height     = nLineSpacing ;
            }
      }
      return      True ;
}

/*
 *(関数名)
 *    virtual bool      GetStatusAreaNeeded (XRectangle* pArea) const ;
 *(コメント)
 *    必要とする Status Area の大きさをここで返さなければならない。
 *    どの程度の数値が妥当なのかは不明…。
 *    まず、最大値を入れてしまうべきなのか…それともこれだけは必要と
 *    いう最小値を入れてしまうべきなのか…。
 */
Boolean
XIMInputContext_GetStatusAreaNeeded (
      register XIMInputContext*     pThis,
      register XRectangle*          pRect)
{
      assert (pThis != NULL) ;
      if ((pThis->m_dwInputStyle & XIMStatusMask) == XIMStatusNothing)
            return      False ;
      if (pThis->m_ConvAttr.mask & CAStatusAreaNeeded) {
            memcpy (pRect, &pThis->m_rcStatusAreaNeeded, sizeof (XRectangle)) ;
      } else {
            register int      nLineSpacing ;
            pRect->x          = 0 ;
            pRect->y          = 0 ;

            nLineSpacing      = XIMInputContext_GetStatusLineSpacing (pThis) ;
            if ((pThis->m_dwInputStyle & XIMPreeditMask) == XIMPreeditPosition){
                  pRect->width      = nLineSpacing * 80 / 2 ;
            } else {
                  pRect->width      = nLineSpacing * 7 / 2 ;
            }
            pRect->height     = nLineSpacing ;
      }
      return      True ;
}

/*
 *(関数名)
 *    virtual const Colormap& GetStatusColormap () const ;
 *(コメント)
 *    StatusArea の現在の Colormap を得る。
 *    デフォルトは当然のことながら、
 *          DefaultColormap (display, 0)
 *    を使っている。
 */
Colormap
XIMInputContext_GetStatusColormap (
      register XIMInputContext*     pThis)
{
      return      None ;
}

/*
 *(関数名)
 *    virtual const Colormap& GetStatusColormap () const ;
 *(コメント)
 *    StatusArea の Standard Colormap を得る。
 *    デフォルトは当然のことながら、
 *          DefaultColormap (display, 0)
 *    を使っている。
 */
Atom
XIMInputContext_GetStatusStdColormap (
      register XIMInputContext*     pThis)
{
      return      None ;
}

unsigned long
XIMInputContext_GetStatusForeground (
      register XIMInputContext*     pThis)
{
      /*    not implemented, both status and peedit must have the same value? */
      return      XIMInputContext_GetPreeditForeground (pThis) ;
}

unsigned long
XIMInputContext_GetStatusBackground (
      register XIMInputContext*     pThis)
{
      /*    not implemented, both status and peedit must have the same value? */
      return      XIMInputContext_GetPreeditBackground (pThis) ;
}

Pixmap
XIMInputContext_GetStatusBackgroundPixmap (
      register XIMInputContext*     pThis)
{
      return      XIMInputContext_GetPreeditBackgroundPixmap (pThis) ;
}

const char*
XIMInputContext_GetStatusFontSet (
      register XIMInputContext*     pThis)
{
      return      NULL ;      /* I have no status fontset. */ 
}

/*
 *
 */
int
XIMInputContext_GetStatusLineSpacing (
      register XIMInputContext*     pThis)
{
      /* Hmmm... I don't know what to do. So, I return the same value
       * with preedit line spacing. */
      return      XIMInputContext_GetPreeditLineSpacing (pThis) ;
}

Cursor
XIMInputContext_GetStatusCursor (
      register XIMInputContext*     pThis)
{
      return      XIMInputContext_GetPreeditCursor (pThis) ;
}

Boolean
XIMInputContext_SetAttributes (
      register XIMInputContext*     pThis)
{
      struct ConvAttrsMesg    ca ;

      /*    Preedit/Status の両方を同時に設定する。skkinput3 では片方ずつ
       *    だったけれども。
       */
      memcpy (&ca, &pThis->m_ConvAttr, sizeof (struct ConvAttrsMesg)) ;
      ca.mask     &= ~(CAInputStyle | CAClientAreaNeeded | CAStatusAreaNeeded) ;
      XtVaSetValues (pThis->m_wgTopFrame, XtNconversionAttribute, &ca, NULL) ;
      return      True ;
}

Boolean
XIMInputContext_Activate (
      register XIMInputContext*           pThis,
      register Boolean                    fActive)
{
      assert (pThis != NULL) ;
      assert (pThis->m_wgTopFrame != NULL) ;

      /*    むう。どうするか?
       */
      return      True ;
}

Boolean
ximInputContext_createFrame (
      register XIMInputContext*     pThis)
{
      register Widget   wgFrame, wgClient ;
      register Window   wndFocus ;
      Arg                     rArg [12] ;
      register int      nArg ;
      register const char*          strClassName ;
      register WidgetClass          pClass ;
      register HistoryListNode*     histNode ;

      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      nArg        = 0 ;
      XtSetArg (rArg [nArg], XtNmappedWhenManaged,    False) ; nArg ++ ;
      XtSetArg (rArg [nArg], XtNclientWindow,               pThis->m_wndClient) ; nArg ++ ;
      if (! (pThis->m_ConvAttr.mask & CAFocusWindow)) {
            wndFocus    = pThis->m_wndClient ;
      } else {
            wndFocus    = pThis->m_ConvAttr.value.focus_window ;
      }
      XtSetArg (rArg [nArg], XtNinput,          False) ;    nArg ++ ;

      switch (pThis->m_dwInputStyle & XIMPreeditMask) {
      case  XIMPreeditPosition:
            strClassName      = "overthespot" ;
            pClass                  = overthespotWinWidgetClass ;
            break ;
      case  XIMPreeditArea:
            strClassName      = "offthespot" ;
            pClass                  = offthespotWinWidgetClass ;
            break ;
            /*    sorry, this code is not implemented yet. */
      case  XIMPreeditCallbacks:
            strClassName      = "onthespot" ;
            pClass                  = onthespotWinWidgetClass ;
            break ;
      case  XIMPreeditNothing:
      case  XIMPreeditNone:
      default:
            strClassName      = "separate" ;
            pClass                  = separateWinWidgetClass ;
            break ;
      }
      histNode    = history_setup (0, pThis->m_wndClient) ;

      wgFrame           = XtVaCreateWidget
            (strClassName, pClass, wgClient, 
             XtNmappedWhenManaged,  False, 
             XtNclientWindow,       pThis->m_wndClient,
             XtNconversionHistory,  histNode, 
             XtNprobeWindow,        None,
             XtNinput,                    False,
             NULL) ;
      if (wgFrame == NULL) {
            if (histNode != NULL)
                  free (histNode) ;
            return      False ;
      }
      pThis->m_wgTopFrame     = wgFrame ;

      add_myeventhandler (XtDisplay (wgClient), pThis->m_wndClient, XtWindow (wgFrame), NO_EVENT_HANDLE, StructureNotifyMask ) ;
      XtCallCallbacks (XtParent (wgClient), XtNsetupInputWindowNotify, wgFrame) ;

      XtAddCallback (wgFrame, XtNtextNotify,     ximInputContext_onTextNotify,    (XtPointer)pThis) ;
      XtAddCallback (wgFrame, XtNendNotify,      ximInputContext_onEndNotify,     (XtPointer)pThis) ;
      XtAddCallback (wgFrame, XtNkeybackNotify,ximInputContext_onKeyBackNotify, (XtPointer)pThis) ;

      if (pClass == onthespotWinWidgetClass) {
            XtAddCallback (wgFrame, XtNpreeditStartCallback, ximInputContext_onPreeditStart, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNpreeditDrawCallback, ximInputContext_onPreeditDraw, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNpreeditCaretCallback, ximInputContext_onPreeditCaret, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNpreeditDoneCallback, ximInputContext_onPreeditDone, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNstatusStartCallback, ximInputContext_onStatusStart, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNstatusDrawCallback, ximInputContext_onStatusDraw, (XtPointer)pThis) ;
            XtAddCallback (wgFrame, XtNstatusDoneCallback, ximInputContext_onStatusDone, (XtPointer)pThis) ;
      }

      XIMInputContext_SetAttributes (pThis) ;
      XtRealizeWidget (wgFrame) ;
      XFlush (XtDisplay (wgFrame)) ;
      return      True ;
}

/*    XIM_COMMIT のパケット同士は連結するのだが、改行だけのパケットは
 *    つないではいけない。つなぐと「改行」が入らなくなる実装があるので。
 *    Spool する前の段階で「改行」のみのパケットをわざわざ生成している。
 */
Boolean
ximInputContext_packetToCombinep (
      register XIMPacket*                 pPacket)
{
      XIMData                             imData ;
      int                                 nMajor ;
      register unsigned int   uBitMask ;

      assert (pPacket != NULL) ;

      XIMPacket_GetHeader (pPacket, &nMajor, NULL) ;
      if (nMajor != XIM_COMMIT) 
            return      False ;
      XIMData_Initialize (&imData, XIMPacket_GetData (pPacket), XIMPacket_GetEndian (pPacket)) ;
      XIMData_Forward8  (&imData, XIM_HEADER_SIZE + 2 + 2) ;
      uBitMask    = XIMData_GetCard16 (&imData) ;
      return      (uBitMask & 4)? False : True ;
}

XIMPacket*
ximInputContext_combineXimCommit (
      register XIMInputContext*     pThis,
      register XIMPacket*                 pSrcPacket1,
      register XIMPacket*                 pSrcPacket2)
{
      register XIMPacket*     pPacket ;
      XIMData                 imSrc ;
      register int      nctext, nctotal, nIndex ;
      CARD16                  uMask ;

      assert (pThis != NULL) ;
      assert (pSrcPacket1 != NULL) ;
      assert (pSrcPacket2 != NULL) ;

      pPacket     = XIMPacket_Create (XIMPacket_GetEndian (pSrcPacket1)) ;
      if (pPacket == NULL)
            return      NULL ;
#if defined (DEBUG)
      fprintf (stderr, "Combine X_COMMIT\n") ;
      fprintf (stderr, "Packet1:\n") ;
      XIMPacket_Show (pSrcPacket1) ;
      fprintf (stderr, "Packet2:\n") ;
      XIMPacket_Show (pSrcPacket2) ;
#endif
      XIMPacket_SetHeader (pPacket, XIM_COMMIT, 0) ;
      XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID  (pThis->m_pInputMethod)) ;
      XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pThis)) ;
      XIMPacket_SetInputContext (pPacket, pThis) ;
      XIMPacket_SetSyncMode  (pPacket, XIMPacket_GetSyncMode (pSrcPacket1)) ;
      XIMPacket_GetCard16    (pSrcPacket1, XIM_HEADER_SIZE + 2 + 2, &uMask) ;
      XIMPacket_AddBitmask16 (pPacket, uMask) ;
      nIndex      = XIMPacket_GetDataSize (pPacket) ;
      XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;

      XIMData_Initialize (&imSrc, XIMPacket_GetData (pSrcPacket1), XIMPacket_GetEndian (pSrcPacket1)) ;
      XIMData_Forward8  (&imSrc, XIM_HEADER_SIZE) ;
      XIMData_Forward16 (&imSrc, 3 /* IMID + IMIC + Bitmask16 */) ;
      nctext      = XIMData_GetCard16 (&imSrc) ;
      nctotal     = nctext ;
      XIMPacket_AddString8 (pPacket, XIMData_GetHead (&imSrc), nctext) ;

      XIMData_Initialize (&imSrc, XIMPacket_GetData (pSrcPacket2), XIMPacket_GetEndian (pSrcPacket2)) ;
      XIMData_Forward8  (&imSrc, XIM_HEADER_SIZE) ;
      XIMData_Forward16 (&imSrc, 3 /* IMID + IMIC + Bitmask16 */) ;
      nctext      = XIMData_GetCard16 (&imSrc) ;
      nctotal     += nctext ;
      XIMPacket_AddString8 (pPacket, XIMData_GetHead (&imSrc), nctext) ;
      XIMPacket_AddPad (pPacket, nctotal) ;
      XIMPacket_SetCard16 (pPacket, nIndex, nctotal) ;
      XIMPacket_SetLength (pPacket) ;
#if defined (DEBUG)
      fprintf (stderr, "Result Packet:\n") ;
      XIMPacket_Show (pPacket) ;
#endif
      return      pPacket ;
}

void
ximInputContext_onKeyBackNotify (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext *) closure ;
      register XEvent*              pEvent      = (XEvent*) call_data ;
      register Widget                     wgClient ;

      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      XIMClient_ForwardEvent (wgClient, pThis->m_pInputMethod, pThis, pEvent) ;
      return ;
}

void
ximInputContext_onEndNotify (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext *) closure ;
      register Widget                     wgClient ;

      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;

      if (call_data != NULL)
            history_close (XtDisplay (wgClient), call_data) ;

#if defined (DEBUG)
      fprintf (stderr, "ximInputMethod_onEndNotify (%p)\n", pThis) ;
#endif
      XIMClient_ControlEventFlow (wgClient, pThis->m_pInputMethod, pThis, False) ;
      XIMInputContext_EndConversion (pThis) ;
      pThis->m_wgTopFrame     = NULL ;
      return ;
}

void
ximInputContext_onTextNotify (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext *) closure ;
      register struct myChar*       pText       = (struct myChar*)call_data ;
      register Widget                     wgClient ;

      wgClient    = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      XIMClient_CommitString (wgClient, pThis->m_pInputMethod, pThis, pText) ;
      return ;
}

void
ximInputContext_onPreeditStart (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

#if defined (DEBUG) || 0
      fprintf (stderr, "ximInputContext_onPreeditStart (%p, %p, %p)\n",
                   wgFrame, closure, call_data) ;
#endif
      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WritePreeditStart (wgClient, nInputMethodID, pThis) ;
      return ;
}

void
ximInputContext_onPreeditDraw (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;
      register const TOnTheSpotDrawArg*   pArg ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

#if defined (DEBUG) || 0
      fprintf (stderr, "ximInputContext_onPreeditDraw (%p, %p, %p)\n",
                   wgFrame, closure, call_data) ;
#endif

      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      pArg              = (const TOnTheSpotDrawArg *)call_data ;
      assert (wgClient != NULL) ;
      assert (pArg     != NULL) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WritePreeditDraw (wgClient, nInputMethodID, pThis, pArg) ;
      return ;
}

void
ximInputContext_onPreeditCaret (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;
      register const TOnTheSpotDrawArg*   pArg ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

#if defined (DEBUG) || 0
      fprintf (stderr, "ximInputContext_onPreeditCaret (%p, %p, %p)\n",
                   wgFrame, closure, call_data) ;
#endif
      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      pArg              = (const TOnTheSpotDrawArg *)call_data ;
      assert (wgClient != NULL) ;
      assert (pArg     != NULL) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WritePreeditCaret (wgClient, nInputMethodID, pThis, pArg) ;
      return ;
}

void
ximInputContext_onPreeditDone (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

#if defined (DEBUG) || 0
      fprintf (stderr, "ximInputContext_onPreeditDone (%p, %p, %p)\n",
                   wgFrame, closure, call_data) ;
#endif
      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WritePreeditDone (wgClient, nInputMethodID, pThis) ;
      return ;
}

void
ximInputContext_onStatusStart (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WriteStatusStart (wgClient, nInputMethodID, pThis) ;
      return ;
}

void
ximInputContext_onStatusDraw (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;
      register const TOnTheSpotDrawArg*   pArg ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      pArg              = (const TOnTheSpotDrawArg *)call_data ;
      assert (wgClient != NULL) ;
      assert (pArg     != NULL) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WriteStatusDraw (wgClient, nInputMethodID, pThis, pArg) ;
      return ;
}

void
ximInputContext_onStatusDone (
      register Widget         wgFrame,
      register XtPointer      closure,
      register XtPointer      call_data)
{
      register XIMInputContext*     pThis = (XIMInputContext*) closure ;
      register Widget                     wgClient ;
      register int                        nInputMethodID ;

      assert (wgFrame != NULL) ;
      assert (pThis   != NULL) ;

      wgClient          = XIMInputMethod_GetClient (pThis->m_pInputMethod) ;
      nInputMethodID    = XIMInputMethod_GetID (pThis->m_pInputMethod) ;
      XIMClient_WriteStatusDone (wgClient, nInputMethodID, pThis) ;
      return ;
}


Generated by  Doxygen 1.6.0   Back to index