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

MyDispatch.c

/* # skkinput (Simple Kana-Kanji Input)
 * MyDispatch.c --- Dispatch X Event
 * This file is part of skkinput.
 * Copyright (C) 1997
 * Takashi SAKAMOTO (sakamoto@yajima.kuis.kyoto-u.ac.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 <stdlib.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>

#include "MyDispatch.h"
#include "MyError.h"

#define MAX_EVENTTYPES        (10)

struct my_eventtable {
  Window dest_window ;
  Window src_window ;
  long event_mask ;
  int number_of_eventtypes ;
  int event_type[ MAX_EVENTTYPES ] ;
  struct my_eventtable *next ;
} ;

static struct my_eventtable *my_eventtable_listtop = NULL ;

/*
 *
 */
static struct my_eventtable *find_whether_myeventhandler_exists
( Window win )
{
  struct my_eventtable *node ;

  /* 指定されたウィンドウに対して、既にイベントハンドラは存在するのか? */
  for( node = my_eventtable_listtop ; node != NULL ; node = node->next ){
    if( node->src_window == win ){
      return node ;
    }
  }
  /* 何も見付からなかった場合。*/
  return NULL ;
}

static struct my_eventtable *alloc_myeventhandler( void )
{
  struct my_eventtable *node ;
  
  /* メモリを確保する…。*/
  if( ( node = malloc( sizeof( struct my_eventtable ) ) ) == NULL ){
    /* ここに来てしまったら、もうどうしようもないから終了する。*/
    fprintf( stderr, "Memory fault.\n" ) ;
    exit( 1 ) ;
  }
  node->src_window = node->dest_window = None ;
  node->event_mask = NoEventMask ;

  node->number_of_eventtypes = 0 ;

  node->next            = my_eventtable_listtop ;
  my_eventtable_listtop = node ;
  return node ;
}

/*
 * 自前のイベント処理が必要になった時に呼ばれる関数。 
 *------
 * 対象となるウィンドウ、奪うべきイベントの種類、その時のマスク。
 */
int add_myeventhandler
( Display *disp, Window src_win, Window dest_win,
  int event_type, long event_mask )
{
      struct my_eventtable *node ;
      int i ;

      if( ( node = find_whether_myeventhandler_exists( src_win ) ) != NULL ){
            /* 既にそのイベントは奪うように指示されているかもしれないから、*
             * チェックする  */
            for( i = 0 ; i < node->number_of_eventtypes ; i ++ ){
                  /* 既に登録済みでしょうか? */
                  if( node->event_type[ i ] == event_type )
                        return True ;
            }
            /* イベントを登録して、そのイベントを受け取るよう指示する。*/
            node->event_type[ node->number_of_eventtypes ++ ] = event_type ;
            node->event_mask |= event_mask ;
            XSelectInput( disp, src_win, node->event_mask ) ;
            return True ;
      }
      node = alloc_myeventhandler() ;
      node->src_window           = src_win ;
      node->dest_window          = dest_win ;
      node->event_mask           = event_mask ;
      node->event_type[ 0 ]      = event_type ;
      node->number_of_eventtypes = 1 ;
      XSelectInput( disp, src_win, event_mask ) ;
      return True ;
}

/*
 * 自前のイベント処理を停止する時に呼び出す関数。
 */
int remove_allmyeventhandler
( Display *disp, Window src_win )
{
      struct my_eventtable *node, *pNode ;
      /* そもそも中身が無いのじゃないかと疑ってみる。*/
      if( ( node = my_eventtable_listtop ) == NULL )
            return False ;
      
      pNode = NULL ;
      while( node != NULL ){
            /* 消去すべき event が見付かった場合…。*/
            if( node->src_window == src_win ){
                  if( pNode == NULL ){
                        /* 消去すべきものがリストの先頭だった場合。*/
                        my_eventtable_listtop = node->next ;
                        /* もはやイベントを受け取らないようにする。*/
                        XSafeSelectInput( disp, src_win, NoEventMask ) ;
                        /* メモリの解放。*/
                        free( node ) ;
                        return True ;
                  } else {
                        /* リストの途中だった場合。*/
                        pNode->next = node->next ;
                        /* もはやイベントを受け取らないようにする。*/
                        XSafeSelectInput( disp, src_win, NoEventMask ) ;
                        /* メモリの解放。*/
                        free( node ) ;
                        return True ;
                  }
            }
            pNode = node ;
            node  = node->next ;
      }
      /* そんなウィンドウは知りません。*/
      return False ;
}


/*
 * 自前のイベント処理を停止する時に呼び出す関数。
 */
int remove_myeventhandler
( Display *disp, Window src_win, int event_type, 
  unsigned long event_mask )
{
      struct my_eventtable *node, *pNode ;
      int i ;

      /* そもそも中身が無いのじゃないかと疑ってみる。*/
      if( ( node = my_eventtable_listtop ) == NULL )
            return False ;

      pNode = NULL ;
      while( node != NULL ){
            /* 消去すべき event が見付かった場合…。*/
            if( node->src_window == src_win ){
                  node->event_mask &= ~event_mask ;
                  for( i = 0 ; i < MAX_EVENTTYPES ; i ++ ){
                        if( node->event_type[ i ] == event_type )
                              node->event_type[ i ] = NO_EVENT_HANDLE ;
                  }
                  XSafeSelectInput( disp, src_win, node->event_mask ) ;
                  if( node->event_mask == NoEventMask ){
                        if( pNode == NULL ){
                              /* 消去すべきものがリストの先頭だった場合。*/
                              my_eventtable_listtop = node->next ;
                        } else {
                              /* リストの途中だった場合。*/
                              pNode->next = node->next ;
                        }
                  }
                  return True ;
            }
            pNode = node ;
            node  = node->next ;
      }
      /* そんなウィンドウは知りません。*/
      return False ;
}

/*
 * イベントを適切なウィジェットへと送り届ける関数。
 */
int mydispatch_event( Display *disp, XEvent *xevent )
{
      struct my_eventtable *node ;
      int i ;

      /* まず捜してみる。*/
      node = find_whether_myeventhandler_exists( xevent->xany.window ) ;
      /* 見付かった場合には…。*/
      if( node != NULL ){
            /* そのウィンドウに対して、どのイベントを取るかの指定がある筈な *
             * ので、それをチェックする。*/
            for( i = 0 ; i < node->number_of_eventtypes ; i ++ ){
                  /* 見付かりましたか? */
                  if( node->event_type[ i ] == xevent->type ){
                        if( xevent->type == KeyPress || xevent->type == KeyRelease ){
                              xevent->xkey.window    = node->dest_window ;
                              xevent->xkey.subwindow = None ;
                        } else {
                              xevent->xany.window = node->dest_window ;
                        }
                        XSafeSendEvent
                              ( disp, xevent->xany.window, False, NoEventMask, xevent ) ; 
                        break ;
                  }
            }
      } else {
            /* イベントを発行する。*/
            XtSafeDispatchEvent( xevent ) ;
      }
      return True ;
}


Generated by  Doxygen 1.6.0   Back to index