/* # skkinput (Simple Kana-Kanji Input)
 * MyError.c --- Handle X Error Events
 * 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 <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>

static int error_occured ;
static int error_type ;
static int ignore_flag ;

/*
 * エラー情報を自前で処理する関数。
 */
static int myErrorHandler
( Display *disp, XErrorEvent *xee )
{
  /* エラー情報を抜き出す。*/
  error_occured = True ;
  error_type    = xee->error_code ;

  /* 無視する状態なら…。*/
  if( ignore_flag )
    return False ;

  fprintf( stderr, "XError Event is received.\n" ) ;
  fprintf( stderr, "serial        = %ld\n", xee->serial ) ;
  fprintf( stderr, "error_code    = %d\n",  xee->error_code ) ;
  fprintf( stderr, "request_code  = %d\n",  xee->request_code ) ;
  fprintf( stderr, "minor_code    = %d\n",  xee->minor_code ) ;
  fprintf( stderr, "resource_id   = %ld\n", xee->resourceid ) ;
  fprintf( stderr, "any.window    = %lu\n", ( ( XEvent * )xee )->xany.window ) ;

#if 1
  while( 1 ) ;
#else
  exit ( 1 ) ;
#endif
}

void initialize_myerrorhandler( void )
{
  error_type  = 0 ;
  ignore_flag = False ;
  XSetErrorHandler( myErrorHandler ) ;
  return ;
}

/*
 * 実際にウィンドウが存在するかどうかを確認するために利用する関数。
 */
int  IsWindowExist( Display *disp, Window win )
{
  int original_value = ignore_flag ;
  XWindowAttributes xwa ;
  int ret ;

  ignore_flag   = True ;
  ret = XGetWindowAttributes
    ( disp, win, &xwa ) ;
  ignore_flag   = original_value ;
  return ( ret ) ;
}

/*
 * 実際にウィンドウが存在するかどうかを確認するために利用する関数。
 */
int  isWindowExistIfExistsGetXWA
( Display *disp, Window win, XWindowAttributes *xwa )
{
  int original_value = ignore_flag ;
  int ret ;
  ignore_flag   = True ;
  ret = XGetWindowAttributes
    ( disp, win, xwa ) ;
#if 0
  printf( "ret: %d, width: %d, height: %d\n", ret, xwa->width, xwa->height ) ;
  printf( "all_event_masks = %ld, your_event_mask = %ld, map_state = %d, ",
	  xwa->all_event_masks, xwa->your_event_mask, xwa->map_state ) ;
#endif
  ignore_flag   = original_value ;
  return ( ret ) ;
}

/*
 * X エラーイベントが発生したかどうかをチェックする関数。
 */
int xerror_occured( void )
{
  return error_occured ;
}

/*
 * エラーが発生したかどうかを忘れる関数。
 */
void xerror_clearflag( void )
{
  error_occured = False ;
  return ;
}

/*
 * X イベントキューをフラッシュする関数。
 */
int XSafeSync( Display *disp, int flag )
{
  int original_value = ignore_flag ;
  ignore_flag = True ;
  XSync( disp, flag ) ;
  ignore_flag = original_value ;
  return True ;
}

/*
 * X イベントキューをフラッシュする関数。
 */
int XSafeFlush( Display *disp )
{
  int original_value = ignore_flag ;
  ignore_flag = True ;
  XFlush( disp ) ;
  ignore_flag = original_value ;
  return True ;
}

/*
 * X イベントキューを見て、次にディスパッチすべきイベントを得る関数。
 */
void XtSafeAppNextEvent
( XtAppContext app_context, XEvent *event_return )
{
  int original_value = ignore_flag ;
  ignore_flag = True ;
  XtAppNextEvent( app_context, event_return ) ;
  ignore_flag = original_value ;
  return ;
}

Status XSafeSendEvent
( Display *disp, Window win, Bool propagate, 
  long event_mask, XEvent *event_send )
{
  int original_value = ignore_flag ;
  Status ret ;
  ignore_flag = True ;
  ret = XSendEvent( disp, win, propagate, event_mask, event_send ) ;
  ignore_flag = original_value ;
  return ret ;
}

int XtSafeDispatchEvent( XEvent *xevent )
{
  int errorflag ;
  int original_value = ignore_flag ;

  ignore_flag   = True ;
  error_occured = False ;
  XtDispatchEvent( xevent ) ;
  errorflag     = error_occured ;
  ignore_flag   = original_value ;
  return ( !errorflag ) ;
}

void XSafeSelectInput( Display *disp, Window win, long event_mask )
{
  int original_value = ignore_flag ;
  ignore_flag   = True ;
  XSelectInput( disp, win, event_mask ) ;
  ignore_flag   = original_value ;
  return ;
}

void XSafeDestroyWindow( Display *disp, Window win )
{
  int original_value = ignore_flag ;
  ignore_flag   = True ;
  XDestroyWindow( disp, win ) ;
  ignore_flag   = original_value ;
  return ;
}

void XSafeGetWindowProperty
( Display *disp, Window win, Atom property, long loffset, long llength,
  Bool delete, Atom req_type, Atom *actual_type_return,
  int *actual_format_return, 
  unsigned long *nitems_return, unsigned long *bytes_after_return,
  unsigned char **prop_return )
{
  int original_value = ignore_flag ;
  ignore_flag   = True ;
  XGetWindowProperty
    ( disp, win, property, loffset, llength, delete, req_type,
      actual_type_return, actual_format_return,
      nitems_return, bytes_after_return, prop_return ) ;
  ignore_flag   = original_value ;
  return ;
}

void XSafeChangeProperty
( Display *disp, Window win, Atom property, Atom type, int format,
  int mode, unsigned char *data, int nelements )
{
  int original_value = ignore_flag ;
  ignore_flag   = True ;
  XChangeProperty
    ( disp, win, property, type, format, mode, data, nelements ) ;
  ignore_flag   = original_value ;
  return ;
}

void XtSafeDestroyApplicationContext( XtAppContext app_context )
{
  int original_value = ignore_flag ;
  ignore_flag   = True ;
  XtDestroyApplicationContext( app_context ) ;
  ignore_flag   = original_value ;
  return ;
}
