Blame src/input-gui.c

Packit Service a721b1
/* input-gui.c -- gui-based input method module.
Packit Service a721b1
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Packit Service a721b1
     National Institute of Advanced Industrial Science and Technology (AIST)
Packit Service a721b1
     Registration Number H15PRO112
Packit Service a721b1
Packit Service a721b1
   This file is part of the m17n library.
Packit Service a721b1
Packit Service a721b1
   The m17n library is free software; you can redistribute it and/or
Packit Service a721b1
   modify it under the terms of the GNU Lesser General Public License
Packit Service a721b1
   as published by the Free Software Foundation; either version 2.1 of
Packit Service a721b1
   the License, or (at your option) any later version.
Packit Service a721b1
Packit Service a721b1
   The m17n library is distributed in the hope that it will be useful,
Packit Service a721b1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a721b1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service a721b1
   Lesser General Public License for more details.
Packit Service a721b1
Packit Service a721b1
   You should have received a copy of the GNU Lesser General Public
Packit Service a721b1
   License along with the m17n library; if not, write to the Free
Packit Service a721b1
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit Service a721b1
   Boston, MA 02110-1301 USA.  */
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @addtogroup m17nInputMethodWin
Packit Service a721b1
    @brief Input method support on window systems.
Packit Service a721b1
Packit Service a721b1
    The input driver @c minput_gui_driver is provided for internal
Packit Service a721b1
    input methods that is useful on window systems.  It displays
Packit Service a721b1
    preedit text and status text at the inputting spot.  See the
Packit Service a721b1
    documentation of @c minput_gui_driver for more details.
Packit Service a721b1
Packit Service a721b1
    In the m17n-X library, the foreign input method of name @c Mxim is
Packit Service a721b1
    provided.  It uses XIM (X Input Method) as a background input
Packit Service a721b1
    engine.  The symbol @c Mxim has a property @c Minput_driver whose
Packit Service a721b1
    value is a pointer to the input driver @c minput_xim_driver.  See
Packit Service a721b1
    the documentation of @c minput_xim_driver for more details.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @addtogroup m17nInputMethodWin
Packit Service a721b1
    @brief ウィンドウシステム上の入力メソッドのサポート.
Packit Service a721b1
Packit Service a721b1
    入力ドライバ @c minput_gui_driver は、
Packit Service a721b1
    ウィンドウシステム上で用いられる内部入力メソッド用のドライバである。
Packit Service a721b1
    このドライバは入力スポットに preedit テキストと status 
Packit Service a721b1
    テキストを表示する。詳細については @c minput_gui_driver の説明を参照のこと。
Packit Service a721b1
Packit Service a721b1
    m17n-X ライブラリは、@c Mxim と言う名前を持つ外部入力メソッドを提供している。これは 
Packit Service a721b1
    XIM (X Input Method) をバックグラウンドの入力エンジンとして利用する。シンボル
Packit Service a721b1
    @c Mxim は @c Minput_driver というプロパティを持っており、その値は入力ドライバ 
Packit Service a721b1
    @c minput_xim_driver へのポインタである。 詳細については 
Packit Service a721b1
    @c minput_xim_driver の説明を参照のこと。  */
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
Packit Service a721b1
/*** @addtogroup m17nInternal
Packit Service a721b1
     @{ */
Packit Service a721b1
Packit Service a721b1
#include <string.h>
Packit Service a721b1
#include <ctype.h>
Packit Service a721b1
Packit Service a721b1
#include "config.h"
Packit Service a721b1
#include "m17n-gui.h"
Packit Service a721b1
#include "m17n-misc.h"
Packit Service a721b1
#include "internal.h"
Packit Service a721b1
#include "internal-gui.h"
Packit Service a721b1
#include "input.h"
Packit Service a721b1
Packit Service a721b1
typedef struct
Packit Service a721b1
{
Packit Service a721b1
  MDrawWindow win;
Packit Service a721b1
  MDrawMetric geometry;
Packit Service a721b1
  MDrawControl control;
Packit Service a721b1
  int mapped;
Packit Service a721b1
} MInputGUIWinInfo;
Packit Service a721b1
Packit Service a721b1
typedef struct
Packit Service a721b1
{
Packit Service a721b1
  MInputContextInfo *ic_info;
Packit Service a721b1
Packit Service a721b1
  MFrame *frame;
Packit Service a721b1
  /* <geometry>.x and <geometry>.y are not used.  */
Packit Service a721b1
  MInputGUIWinInfo client;
Packit Service a721b1
  /* In the following members, <geometry> is relative to <client>.  */
Packit Service a721b1
  MInputGUIWinInfo focus;
Packit Service a721b1
  MInputGUIWinInfo preedit;
Packit Service a721b1
  MInputGUIWinInfo status;
Packit Service a721b1
  MInputGUIWinInfo candidates;
Packit Service a721b1
} MInputGUIContextInfo;
Packit Service a721b1
Packit Service a721b1
static MFace *status_face;
Packit Service a721b1
static MFaceBoxProp face_box_prop;
Packit Service a721b1
Packit Service a721b1
static int
Packit Service a721b1
win_create_ic (MInputContext *ic)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info;
Packit Service a721b1
  MInputGUIArgIC *win_info = (MInputGUIArgIC *) ic->arg;
Packit Service a721b1
  MFrame *frame = win_info->frame;
Packit Service a721b1
Packit Service a721b1
  if ((*minput_default_driver.create_ic) (ic) < 0)
Packit Service a721b1
    return -1;
Packit Service a721b1
Packit Service a721b1
  MSTRUCT_CALLOC (win_ic_info, MERROR_IM);
Packit Service a721b1
  win_ic_info->ic_info = (MInputContextInfo *) ic->info;
Packit Service a721b1
  win_ic_info->frame = frame;
Packit Service a721b1
  win_ic_info->client.win = win_info->client;
Packit Service a721b1
  (*frame->driver->window_geometry) (frame, win_info->client, win_info->client,
Packit Service a721b1
			 &win_ic_info->client.geometry);
Packit Service a721b1
  win_ic_info->focus.win = win_info->focus;
Packit Service a721b1
  (*frame->driver->window_geometry) (frame, win_info->focus, win_info->client,
Packit Service a721b1
			 &win_ic_info->focus.geometry);
Packit Service a721b1
Packit Service a721b1
  win_ic_info->preedit.win = (*frame->driver->create_window) (frame, win_info->client);
Packit Service a721b1
  win_ic_info->preedit.control.two_dimensional = 1;
Packit Service a721b1
  win_ic_info->preedit.control.as_image = 0;
Packit Service a721b1
  win_ic_info->preedit.control.with_cursor = 1;
Packit Service a721b1
  win_ic_info->preedit.control.cursor_width = 1;
Packit Service a721b1
  win_ic_info->preedit.control.enable_bidi = 1;
Packit Service a721b1
  win_ic_info->preedit.geometry.x = -1;
Packit Service a721b1
  win_ic_info->preedit.geometry.y = -1;
Packit Service a721b1
Packit Service a721b1
  win_ic_info->status.win = (*frame->driver->create_window) (frame, win_info->client);
Packit Service a721b1
  win_ic_info->status.control.as_image = 1;
Packit Service a721b1
  win_ic_info->status.control.enable_bidi = 1;
Packit Service a721b1
Packit Service a721b1
  win_ic_info->candidates.win = (*frame->driver->create_window) (frame, win_info->client);
Packit Service a721b1
  win_ic_info->candidates.control.as_image = 1;
Packit Service a721b1
Packit Service a721b1
  ic->info = win_ic_info;
Packit Service a721b1
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
win_destroy_ic (MInputContext *ic)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
Packit Service a721b1
  MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
Packit Service a721b1
  MFrame *frame = win_ic_info->frame;
Packit Service a721b1
Packit Service a721b1
  (*frame->driver->destroy_window) (frame, win_ic_info->preedit.win);
Packit Service a721b1
  (*frame->driver->destroy_window) (frame, win_ic_info->status.win);
Packit Service a721b1
  (*frame->driver->destroy_window) (frame, win_ic_info->candidates.win);
Packit Service a721b1
  ic->info = ic_info;
Packit Service a721b1
  (*minput_default_driver.destroy_ic) (ic);
Packit Service a721b1
  free (win_ic_info);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static int
Packit Service a721b1
win_filter (MInputContext *ic, MSymbol key, void *arg)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
Packit Service a721b1
  int ret;
Packit Service a721b1
Packit Service a721b1
  if (! ic
Packit Service a721b1
      || ! ic->active)
Packit Service a721b1
    return 0;
Packit Service a721b1
Packit Service a721b1
  if (key == Mnil && arg)
Packit Service a721b1
    {
Packit Service a721b1
      key = minput_event_to_key (win_ic_info->frame, arg);
Packit Service a721b1
      if (key == Mnil)
Packit Service a721b1
	return 1;
Packit Service a721b1
    }
Packit Service a721b1
  ic->info = win_ic_info->ic_info;
Packit Service a721b1
  ret = (*minput_default_driver.filter) (ic, key, arg);
Packit Service a721b1
  win_ic_info->ic_info = (MInputContextInfo *) ic->info;
Packit Service a721b1
  ic->info = win_ic_info;
Packit Service a721b1
  return ret;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
adjust_window_and_draw (MFrame *frame, MInputContext *ic, MText *mt, int type)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
Packit Service a721b1
  MDrawControl *control;
Packit Service a721b1
  MDrawWindow win;
Packit Service a721b1
  MDrawMetric *geometry, physical, logical;
Packit Service a721b1
  int xoff = win_ic_info->focus.geometry.x;
Packit Service a721b1
  int yoff = win_ic_info->focus.geometry.y;
Packit Service a721b1
  int x0, x1, y0, y1;
Packit Service a721b1
  int len = mtext_nchars (mt);
Packit Service a721b1
Packit Service a721b1
  if (type == 0)
Packit Service a721b1
    {
Packit Service a721b1
      win = win_ic_info->preedit.win;
Packit Service a721b1
      control = &win_ic_info->preedit.control;
Packit Service a721b1
      geometry = &win_ic_info->preedit.geometry;
Packit Service a721b1
      len++;
Packit Service a721b1
    }
Packit Service a721b1
  else if (type == 1)
Packit Service a721b1
    {
Packit Service a721b1
      win = win_ic_info->status.win;
Packit Service a721b1
      control = &win_ic_info->status.control;
Packit Service a721b1
      geometry = &win_ic_info->status.geometry;
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      win = win_ic_info->candidates.win;
Packit Service a721b1
      control = &win_ic_info->candidates.control;
Packit Service a721b1
      geometry = &win_ic_info->candidates.geometry;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  mdraw_text_extents (frame, mt, 0, len, control, &physical, &logical, NULL);
Packit Service a721b1
  x0 = physical.x, x1 = x0 + physical.width;
Packit Service a721b1
  y0 = physical.y, y1 = y0 + physical.height;
Packit Service a721b1
  if (x0 > logical.x)
Packit Service a721b1
    x0 = logical.x;
Packit Service a721b1
  if (x1 < logical.x + logical.width)
Packit Service a721b1
    x1 = logical.x + logical.width;
Packit Service a721b1
  if (y0 > logical.y)
Packit Service a721b1
    y0 = logical.y;
Packit Service a721b1
  if (y1 < logical.y + logical.height)
Packit Service a721b1
    y1 = logical.y + logical.height;
Packit Service a721b1
  physical.width = x1 - x0;
Packit Service a721b1
  physical.height = y1 - y0;
Packit Service a721b1
  physical.x = xoff + ic->spot.x;
Packit Service a721b1
  if (physical.x + physical.width > win_ic_info->client.geometry.width)
Packit Service a721b1
    physical.x = win_ic_info->client.geometry.width - physical.width;
Packit Service a721b1
  if (type == 0)
Packit Service a721b1
    {
Packit Service a721b1
      if (len <= 1)
Packit Service a721b1
	{
Packit Service a721b1
	  physical.height = physical.width = 1;
Packit Service a721b1
	  physical.x = physical.y = -1;
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  if (y0 > - ic->spot.ascent)
Packit Service a721b1
	    {
Packit Service a721b1
	      physical.height += y0 + ic->spot.ascent;
Packit Service a721b1
	      y0 = - ic->spot.ascent;
Packit Service a721b1
	    }
Packit Service a721b1
	  if (y1 < ic->spot.descent)
Packit Service a721b1
	    {
Packit Service a721b1
	      physical.height += ic->spot.descent - y1;
Packit Service a721b1
	    }
Packit Service a721b1
	  physical.y = yoff + ic->spot.y + y0;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (type == 1)
Packit Service a721b1
    {
Packit Service a721b1
      physical.y = yoff + ic->spot.y + ic->spot.descent + 2;
Packit Service a721b1
      if (physical.y + physical.height > win_ic_info->client.geometry.height
Packit Service a721b1
	  && yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height >= 0)
Packit Service a721b1
	physical.y = yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height;
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      if (win_ic_info->status.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  /* We assume that status is already drawn.  */
Packit Service a721b1
	  if (win_ic_info->status.geometry.y < yoff + ic->spot.y)
Packit Service a721b1
	    /* As there was no lower room for status, candidates must also
Packit Service a721b1
	       be drawn upper.  */
Packit Service a721b1
	    physical.y = win_ic_info->status.geometry.y - 1 - physical.height;
Packit Service a721b1
	  else
Packit Service a721b1
	    {
Packit Service a721b1
	      /* There was a lower room for status.  */
Packit Service a721b1
	      physical.y = (win_ic_info->status.geometry.y
Packit Service a721b1
			    + win_ic_info->status.geometry.height
Packit Service a721b1
			    + 1);
Packit Service a721b1
	      if (physical.y + physical.height
Packit Service a721b1
		  > win_ic_info->client.geometry.height)
Packit Service a721b1
		/* But not for candidates.  */
Packit Service a721b1
		physical.y = (yoff + ic->spot.y - ic->spot.ascent - 1
Packit Service a721b1
			      - physical.height);
Packit Service a721b1
	    }
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  physical.y = yoff + ic->spot.y + ic->spot.descent + 2;
Packit Service a721b1
	  if ((physical.y + physical.height
Packit Service a721b1
	       > win_ic_info->client.geometry.height)
Packit Service a721b1
	      && (yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height
Packit Service a721b1
		  >= 0))
Packit Service a721b1
	    physical.y = (yoff + ic->spot.y - ic->spot.ascent - 2
Packit Service a721b1
			  - physical.height);
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  (*frame->driver->adjust_window) (frame, win, geometry, &physical);
Packit Service a721b1
  mdraw_text_with_control (frame, win, -x0, -y0, mt, 0, len, control);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
win_callback (MInputContext *ic, MSymbol command)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
Packit Service a721b1
  MFrame *frame = win_ic_info->frame;
Packit Service a721b1
Packit Service a721b1
  if (command == Minput_preedit_draw)
Packit Service a721b1
    {
Packit Service a721b1
      MText *mt;
Packit Service a721b1
      MFace *face = mface ();
Packit Service a721b1
Packit Service a721b1
      if (! win_ic_info->preedit.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->map_window) (frame, win_ic_info->preedit.win);
Packit Service a721b1
	  win_ic_info->preedit.mapped = 1;
Packit Service a721b1
	}
Packit Service a721b1
      win_ic_info->preedit.control.cursor_pos = ic->cursor_pos;
Packit Service a721b1
      if (ic->spot.fontsize)
Packit Service a721b1
	mface_put_prop (face, Msize, (void *) ic->spot.fontsize);
Packit Service a721b1
      mface_merge (face, mface_underline);
Packit Service a721b1
      mtext_push_prop (ic->preedit, 0, mtext_nchars (ic->preedit),
Packit Service a721b1
		       Mface, face);
Packit Service a721b1
      M17N_OBJECT_UNREF (face);
Packit Service a721b1
      if (ic->im->language != Mnil)
Packit Service a721b1
	mtext_put_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mlanguage,
Packit Service a721b1
			ic->im->language);
Packit Service a721b1
      if (ic->candidate_list && ic->candidate_show)
Packit Service a721b1
	mtext_push_prop (ic->preedit, ic->candidate_from, ic->candidate_to,
Packit Service a721b1
			 Mface, mface_reverse_video);
Packit Service a721b1
      if (mtext_nchars (ic->produced) == 0)
Packit Service a721b1
	mt = ic->preedit;
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  mt = mtext_dup (ic->produced);
Packit Service a721b1
	  mtext_cat (mt, ic->preedit);
Packit Service a721b1
	  win_ic_info->preedit.control.cursor_pos
Packit Service a721b1
	    += mtext_nchars (ic->produced);
Packit Service a721b1
	}
Packit Service a721b1
      adjust_window_and_draw (frame, ic, mt, 0);
Packit Service a721b1
      if (ic->candidate_list)
Packit Service a721b1
	mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface);
Packit Service a721b1
      mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface);
Packit Service a721b1
      if (mtext_nchars (ic->produced) != 0)
Packit Service a721b1
	M17N_OBJECT_UNREF (mt);
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_status_draw)
Packit Service a721b1
    {
Packit Service a721b1
      if (! win_ic_info->client.win)
Packit Service a721b1
	return;
Packit Service a721b1
      mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mface,
Packit Service a721b1
		      status_face);
Packit Service a721b1
      if (ic->im->language != Mnil)
Packit Service a721b1
	mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mlanguage,
Packit Service a721b1
			ic->im->language);
Packit Service a721b1
      adjust_window_and_draw (frame, ic, ic->status, 1);
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_candidates_draw)
Packit Service a721b1
    {
Packit Service a721b1
      MPlist *group;
Packit Service a721b1
      MText *mt;
Packit Service a721b1
      int i, len;
Packit Service a721b1
      int from, to;
Packit Service a721b1
Packit Service a721b1
      if (! ic->candidate_list || ! ic->candidate_show)
Packit Service a721b1
	{
Packit Service a721b1
	  if (win_ic_info->candidates.mapped)
Packit Service a721b1
	    {
Packit Service a721b1
	      (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win);
Packit Service a721b1
	      win_ic_info->candidates.mapped = 0;
Packit Service a721b1
	    }
Packit Service a721b1
	  return;
Packit Service a721b1
	}
Packit Service a721b1
Packit Service a721b1
      if (! win_ic_info->candidates.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->map_window) (frame, win_ic_info->candidates.win);
Packit Service a721b1
	  win_ic_info->candidates.mapped = 1;
Packit Service a721b1
	}
Packit Service a721b1
Packit Service a721b1
      i = 0;
Packit Service a721b1
      group = ic->candidate_list;
Packit Service a721b1
      while (1)
Packit Service a721b1
	{
Packit Service a721b1
	  if (mplist_key (group) == Mtext)
Packit Service a721b1
	    len = mtext_len (mplist_value (group));
Packit Service a721b1
	  else
Packit Service a721b1
	    len = mplist_length (mplist_value (group));
Packit Service a721b1
	  if (i + len > ic->candidate_index)
Packit Service a721b1
	    break;
Packit Service a721b1
	  i += len;
Packit Service a721b1
	  group = mplist_next (group);
Packit Service a721b1
	}
Packit Service a721b1
Packit Service a721b1
      mt = mtext ();
Packit Service a721b1
      if (mplist_key (group) == Mtext)
Packit Service a721b1
	{
Packit Service a721b1
	  MText *candidates = (MText *) mplist_value (group);
Packit Service a721b1
Packit Service a721b1
	  from = (ic->candidate_index - i) * 2 + 1;
Packit Service a721b1
	  to = from + 1;
Packit Service a721b1
	  for (i = 0; i < len; i++)
Packit Service a721b1
	    {
Packit Service a721b1
	      mtext_cat_char (mt, ' ');
Packit Service a721b1
	      mtext_cat_char (mt, mtext_ref_char (candidates, i));
Packit Service a721b1
	    }
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  MPlist *pl;
Packit Service a721b1
Packit Service a721b1
	  for (pl = (MPlist *) mplist_value (group);
Packit Service a721b1
	       i < ic->candidate_index && mplist_key (pl) != Mnil;
Packit Service a721b1
	       i++, pl = mplist_next (pl))
Packit Service a721b1
	    {
Packit Service a721b1
	      mtext_cat_char (mt, ' ');
Packit Service a721b1
	      mtext_cat (mt, (MText *) mplist_value (pl));
Packit Service a721b1
	    }
Packit Service a721b1
	  from = mtext_nchars (mt) + 1;
Packit Service a721b1
	  to = from + mtext_nchars ((MText *) mplist_value (pl));
Packit Service a721b1
	  for (; mplist_key (pl) != Mnil; pl = mplist_next (pl))
Packit Service a721b1
	    {
Packit Service a721b1
	      mtext_cat_char (mt, ' ');
Packit Service a721b1
	      mtext_cat (mt, (MText *) mplist_value (pl));
Packit Service a721b1
	    }
Packit Service a721b1
	}
Packit Service a721b1
      mtext_cat_char (mt, ' ');
Packit Service a721b1
      mtext_push_prop (mt, 0, mtext_nchars (mt), Mface, status_face);
Packit Service a721b1
      mtext_push_prop (mt, from, to, Mface, mface_reverse_video);
Packit Service a721b1
      if (ic->im->language != Mnil)
Packit Service a721b1
	mtext_put_prop (mt, 0, mtext_nchars (mt), Mlanguage, ic->im->language);
Packit Service a721b1
      adjust_window_and_draw (frame, ic, mt, 2);
Packit Service a721b1
      M17N_OBJECT_UNREF (mt);
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_set_spot)
Packit Service a721b1
    {
Packit Service a721b1
      minput_callback (ic, Minput_preedit_draw);
Packit Service a721b1
      minput_callback (ic, Minput_status_draw);
Packit Service a721b1
      minput_callback (ic, Minput_candidates_draw);
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_toggle)
Packit Service a721b1
    {
Packit Service a721b1
      if (ic->active)
Packit Service a721b1
	{
Packit Service a721b1
	  minput_callback (ic, Minput_preedit_done);
Packit Service a721b1
	  minput_callback (ic, Minput_status_done);
Packit Service a721b1
	  minput_callback (ic, Minput_candidates_done);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  minput_callback (ic, Minput_preedit_start);
Packit Service a721b1
	  minput_callback (ic, Minput_status_start);
Packit Service a721b1
	  minput_callback (ic, Minput_candidates_start);
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_preedit_start)
Packit Service a721b1
    {
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_preedit_done)
Packit Service a721b1
    {
Packit Service a721b1
      if (win_ic_info->preedit.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->unmap_window) (frame, win_ic_info->preedit.win);
Packit Service a721b1
	  win_ic_info->preedit.mapped = 0;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_status_start)
Packit Service a721b1
    {
Packit Service a721b1
      if (! win_ic_info->status.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->map_window) (frame, win_ic_info->status.win);
Packit Service a721b1
	  win_ic_info->status.mapped = 1;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_status_done)
Packit Service a721b1
    {
Packit Service a721b1
      if (win_ic_info->status.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->unmap_window) (frame, win_ic_info->status.win);
Packit Service a721b1
	  win_ic_info->status.mapped = 0;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_candidates_start)
Packit Service a721b1
    {
Packit Service a721b1
      if (! win_ic_info->candidates.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->map_window) (frame, win_ic_info->candidates.win);
Packit Service a721b1
	  win_ic_info->candidates.mapped = 1;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_candidates_done)
Packit Service a721b1
    {
Packit Service a721b1
      if (win_ic_info->candidates.mapped)
Packit Service a721b1
	{
Packit Service a721b1
	  (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win);
Packit Service a721b1
	  win_ic_info->candidates.mapped = 0;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (command == Minput_reset)
Packit Service a721b1
    {
Packit Service a721b1
      MInputCallbackFunc func;
Packit Service a721b1
Packit Service a721b1
      if (minput_default_driver.callback_list
Packit Service a721b1
	  && (func = ((MInputCallbackFunc)
Packit Service a721b1
		      mplist_get_func (minput_default_driver.callback_list,
Packit Service a721b1
				       Minput_reset))))
Packit Service a721b1
	{
Packit Service a721b1
	  MInputContextInfo *ic_info
Packit Service a721b1
	    = (MInputContextInfo *) win_ic_info->ic_info;
Packit Service a721b1
	  ic->info = ic_info;
Packit Service a721b1
	  (func) (ic, Minput_reset);
Packit Service a721b1
	  ic->info = win_ic_info;
Packit Service a721b1
	}
Packit Service a721b1
      if (ic->preedit_changed)
Packit Service a721b1
	minput_callback (ic, Minput_preedit_draw);
Packit Service a721b1
      if (ic->status_changed)
Packit Service a721b1
	minput_callback (ic, Minput_status_draw);
Packit Service a721b1
      if (ic->candidates_changed)
Packit Service a721b1
	minput_callback (ic, Minput_candidates_draw);
Packit Service a721b1
    }
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static int
Packit Service a721b1
win_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
Packit Service a721b1
{
Packit Service a721b1
  MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
Packit Service a721b1
  MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
Packit Service a721b1
  int ret;
Packit Service a721b1
Packit Service a721b1
  ic->info = ic_info;
Packit Service a721b1
  ret = (*minput_default_driver.lookup) (ic, key, arg, mt);
Packit Service a721b1
  ic->info = win_ic_info;
Packit Service a721b1
  return ret;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
minput__win_init ()
Packit Service a721b1
{
Packit Service a721b1
  minput_gui_driver = minput_default_driver;
Packit Service a721b1
Packit Service a721b1
  minput_gui_driver.create_ic = win_create_ic;
Packit Service a721b1
  minput_gui_driver.destroy_ic = win_destroy_ic;
Packit Service a721b1
  minput_gui_driver.filter = win_filter;
Packit Service a721b1
  minput_gui_driver.lookup = win_lookup;
Packit Service a721b1
  {
Packit Service a721b1
    MPlist *plist = mplist ();
Packit Service a721b1
Packit Service a721b1
    minput_gui_driver.callback_list = plist;
Packit Service a721b1
    mplist_put_func (plist, Minput_preedit_start, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_preedit_draw, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_preedit_done, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_status_start, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_status_draw, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_status_done, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_candidates_start, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_candidates_draw, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_candidates_done, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_set_spot, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_toggle, M17N_FUNC (win_callback));
Packit Service a721b1
    mplist_put_func (plist, Minput_reset, M17N_FUNC (win_callback));
Packit Service a721b1
  }
Packit Service a721b1
#if 0
Packit Service a721b1
  /* This will make the caller of minput_method_open() pazzled.  */
Packit Service a721b1
  minput_driver = &minput_gui_driver;
Packit Service a721b1
#endif
Packit Service a721b1
Packit Service a721b1
  face_box_prop.width = 1;
Packit Service a721b1
  face_box_prop.color_top = face_box_prop.color_left
Packit Service a721b1
    = face_box_prop.color_bottom = face_box_prop.color_right
Packit Service a721b1
    = msymbol ("black");
Packit Service a721b1
  face_box_prop.inner_hmargin = face_box_prop.inner_vmargin = 2;
Packit Service a721b1
  face_box_prop.outer_hmargin = face_box_prop.outer_vmargin = 1;
Packit Service a721b1
  status_face = mface ();
Packit Service a721b1
  mface_put_prop (status_face, Mbox, &face_box_prop);
Packit Service a721b1
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
minput__win_fini ()
Packit Service a721b1
{
Packit Service a721b1
  M17N_OBJECT_UNREF (status_face);
Packit Service a721b1
  if (minput_gui_driver.callback_list)
Packit Service a721b1
    {
Packit Service a721b1
      M17N_OBJECT_UNREF (minput_gui_driver.callback_list);
Packit Service a721b1
      minput_gui_driver.callback_list = NULL;
Packit Service a721b1
    }
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
/* External API */
Packit Service a721b1
Packit Service a721b1
/*** @addtogroup m17nInputMethodWin */
Packit Service a721b1
/*** @{ */
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Input driver for internal input methods on window systems.
Packit Service a721b1
Packit Service a721b1
    The input driver @c minput_gui_driver is for internal input
Packit Service a721b1
    methods to be used on window systems.
Packit Service a721b1
Packit Service a721b1
    It creates sub-windows for a preedit text and a status text, and
Packit Service a721b1
    displays them at the input spot set by the function
Packit Service a721b1
    minput_set_spot ().
Packit Service a721b1
Packit Service a721b1
    The macro M17N_INIT () set the variable @c minput_driver to the
Packit Service a721b1
    pointer to this driver so that all internal input methods use it.
Packit Service a721b1
Packit Service a721b1
    Therefore, unless @c minput_driver is changed from the default,
Packit Service a721b1
    the driver dependent arguments to the functions whose name begin
Packit Service a721b1
    with minput_ must are treated as follows.
Packit Service a721b1
Packit Service a721b1
    The argument $ARG of the function minput_open_im () is ignored.
Packit Service a721b1
Packit Service a721b1
    The argument $ARG of the function minput_create_ic () must be a
Packit Service a721b1
    pointer to the structure @c MInputGUIArgIC.  See the documentation
Packit Service a721b1
    of @c MInputGUIArgIC for more details.
Packit Service a721b1
Packit Service a721b1
    If the argument $KEY of function minput_filter () is @c Mnil, the
Packit Service a721b1
    argument $ARG must be a pointer to the object of type @c XEvent.
Packit Service a721b1
    In that case, $KEY is generated from $ARG.
Packit Service a721b1
Packit Service a721b1
    The argument $ARG of the function minput_lookup () must be the
Packit Service a721b1
    same one as that of the function minput_filter (). */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief ウィンドウシステムの内部入力メソッド用入力ドライバ.
Packit Service a721b1
Packit Service a721b1
    入力ドライバ @c minput_gui_driver
Packit Service a721b1
    は、ウィンドウシステム上で用いられる入力メソッド用ドライバである。
Packit Service a721b1
Packit Service a721b1
    このドライバは、関数 minput_set_spot () によって設定された入力スポットに
Packit Service a721b1
    preedit テキスト用のサブウィンドウと status 
Packit Service a721b1
    テキスト用のサブウィンドウを作り、それぞれを表示する。
Packit Service a721b1
Packit Service a721b1
    マクロ M17N_INIT () は変数 @c minput_driver 
Packit Service a721b1
    をこのドライバへのポインタに設定し、全ての内部入力メソッドがこのドライバを使うようにする。
Packit Service a721b1
Packit Service a721b1
    したがって、@c minput_driver がデフォルト値のままであれば、minput_ 
Packit Service a721b1
    で始まる名前を持つ関数の引数のうちドライバ依存のものは以下のようになる。
Packit Service a721b1
Packit Service a721b1
    関数 minput_open_im () の引数 $ARG は無視される。
Packit Service a721b1
Packit Service a721b1
    関数 minput_create_ic () の引数 $ARG は構造体 @c MInputGUIArgIC 
Packit Service a721b1
    へのポインタでなくてはならない。詳細については @c MInputGUIArgIC 
Packit Service a721b1
    の説明を参照のこと。
Packit Service a721b1
Packit Service a721b1
    関数 minput_filter () の引数 $ARG が @c Mnil の場合、 $ARG は @c
Packit Service a721b1
    XEvent 型のオブジェクトへのポインタでなくてはならない。この場合 
Packit Service a721b1
    $KEY は $ARG から生成される。
Packit Service a721b1
Packit Service a721b1
    関数 minput_lookup () の引数 $ARG は関数 minput_filter () の引数 
Packit Service a721b1
    $ARG と同じでなくてはならない。 */
Packit Service a721b1
Packit Service a721b1
MInputDriver minput_gui_driver;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol of the name "xim".
Packit Service a721b1
Packit Service a721b1
    The variable Mxim is a symbol of name "xim".  It is a name of the
Packit Service a721b1
    input method driver #minput_xim_driver.  */ 
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "xim"を名前として持つシンボル .
Packit Service a721b1
Packit Service a721b1
    変数 Mxim は"xim"を名前として持つシンボルである。"xim" 
Packit Service a721b1
    は入力メソッドドライバ #minput_xim_driver の名前である。  */ 
Packit Service a721b1
Packit Service a721b1
MSymbol Mxim;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Convert an event to an input key.
Packit Service a721b1
Packit Service a721b1
    The minput_event_to_key () function returns the input key
Packit Service a721b1
    corresponding to event $EVENT on $FRAME by a window system
Packit Service a721b1
    dependent manner.
Packit Service a721b1
Packit Service a721b1
    In the m17n-X library, $EVENT must be a pointer to the structure
Packit Service a721b1
    @c XKeyEvent, and it is handled as below.
Packit Service a721b1
Packit Service a721b1
    At first, the keysym name of $EVENT is acquired by the function @c
Packit Service a721b1
    XKeysymToString.  Then, the name is modified as below.
Packit Service a721b1
Packit Service a721b1
    If the name is one of "a" .. "z" and $EVENT has a Shift modifier,
Packit Service a721b1
    the name is converted to "A" .. "Z" respectively, and the Shift
Packit Service a721b1
    modifier is cleared.
Packit Service a721b1
Packit Service a721b1
    If the name is one byte length and $EVENT has a Control modifier,
Packit Service a721b1
    the byte is bitwise anded by 0x1F and the Control modifier is
Packit Service a721b1
    cleared.
Packit Service a721b1
Packit Service a721b1
    If $EVENT still has modifiers, the name is preceded by "S-"
Packit Service a721b1
    (Shift), "C-" (Control), "M-" (Meta), "A-" (Alt), "G-" (AltGr),
Packit Service a721b1
    "s-" (Super), and "H-" (Hyper) in this order.
Packit Service a721b1
Packit Service a721b1
    For instance, if the keysym name is "a" and the event has Shift,
Packit Service a721b1
    Meta, and Hyper modifiers, the resulting name is "M-H-A".
Packit Service a721b1
Packit Service a721b1
    At last, a symbol who has the name is returned.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief イベントを入力キーに変換する.
Packit Service a721b1
Packit Service a721b1
    関数 minput_event_to_key () は、$FRAME のイベント $EVENT 
Packit Service a721b1
    に対応する入力キーを返す。ここでの「対応」はウィンドウシステムに依存する。
Packit Service a721b1
Packit Service a721b1
    m17n-X ライブラリの場合には、$EVENT は 構造体 @c XKeyEvent 
Packit Service a721b1
    へのポインタであり、次のように処理される。
Packit Service a721b1
Packit Service a721b1
    まず、関数 @c XKeysymToString によって、$EVENT の keysym 
Packit Service a721b1
    名を取得し、次いで以下の変更を加える。
Packit Service a721b1
Packit Service a721b1
    名前が "a" .. "z" のいずれかであって $EVENT に Shift 
Packit Service a721b1
    モディファイアがあれば、名前はそれぞれ "A" .. "Z" に変換され、Shift 
Packit Service a721b1
    モディファイアは取り除かれる。
Packit Service a721b1
Packit Service a721b1
    名前が1バイト長で $EVENT に Control モディファイアがあれば、名前と
Packit Service a721b1
    0x1F とをビット単位で and 演算し、Control モディファイアは取り除かれる。
Packit Service a721b1
Packit Service a721b1
    それでも $EVENT にまだモディファイアがあれば、名前の前にそれぞれ
Packit Service a721b1
    "S-" (Shift), "C-" (Control), "M-" (Meta), "A-" (Alt), , "G-" (AltGr),
Packit Service a721b1
    "s-" (Super), "H-" (Hyper)がこの順番で付く。
Packit Service a721b1
    
Packit Service a721b1
    たとえば、keysym 名が "a" でイベントが Shift, Meta, and Hyper 
Packit Service a721b1
    モディファイアを持てば、得られる名前は "M-H-A" である。
Packit Service a721b1
Packit Service a721b1
    最後にその名前を持つシンボルを返す。*/
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
minput_event_to_key (MFrame *frame, void *event)
Packit Service a721b1
{
Packit Service a721b1
  int modifiers;
Packit Service a721b1
  MSymbol key;
Packit Service a721b1
  char *name, *str;
Packit Service a721b1
Packit Service a721b1
  M_CHECK_READABLE (frame, MERROR_IM, Mnil);
Packit Service a721b1
  key = (*frame->driver->parse_event) (frame, event, &modifiers);
Packit Service a721b1
  if (! modifiers)
Packit Service a721b1
    return key;
Packit Service a721b1
Packit Service a721b1
  name = msymbol_name (key);
Packit Service a721b1
  str = alloca (strlen (name) + 2 * 8 + 1);
Packit Service a721b1
  str[0] = '\0';
Packit Service a721b1
  if (modifiers & MINPUT_KEY_SHIFT_MODIFIER)
Packit Service a721b1
    strcat (str, "S-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_CONTROL_MODIFIER)
Packit Service a721b1
    strcat (str, "C-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_META_MODIFIER)
Packit Service a721b1
    strcat (str, "M-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_ALT_MODIFIER)
Packit Service a721b1
    strcat (str, "A-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_ALTGR_MODIFIER)
Packit Service a721b1
    strcat (str, "G-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_SUPER_MODIFIER)
Packit Service a721b1
    strcat (str, "s-");
Packit Service a721b1
  if (modifiers & MINPUT_KEY_HYPER_MODIFIER)
Packit Service a721b1
    strcat (str, "H-");
Packit Service a721b1
  strcat (str, name);
Packit Service a721b1
Packit Service a721b1
  return msymbol (str);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
Packit Service a721b1
/*
Packit Service a721b1
  Local Variables:
Packit Service a721b1
  coding: euc-japan
Packit Service a721b1
  End:
Packit Service a721b1
*/