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

xi.c

/*
      Copyright (C) 1994,1995 Edward Der-Hua Liu, Hsin-Chu, Taiwan
*/

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <X11/keysym.h>
#include "xi.h"
#include "state.h"

#define K_REJECT (0)
#define K_ACCEPT (1)

#define MW_EVENTS (     KeyPressMask            |\
                  FocusChangeMask         |\
                  StructureNotifyMask     |\
                  ButtonPressMask         |\
                  ExposureMask            |\
                  PropertyChangeMask      |\
                  VisibilityChangeMask    \
            )


Display     *display;
GC    gc,cgc;           /*
                     gc  是给英文字型用的,
                     cgc 是给中文字型用的
                  */
Window      main_win;
Atom  xcin_atom;

extern      int     init_tab( int inmdno, int usenow);
/*
extern      int     lookup_key( KeySym ksym);
*/
extern      int     feedkey( int key);
/*
extern      int     feedkey_pp( int xkey, int kbstate);
extern  int       feedkey_pho( int xkey);
extern  char      going_key;
extern  char     *tsfname;
extern  char     *phokbm_name; 
*/
extern      int     feedkey_intcode( int key);
extern      int     feedkey_vocbox( int key);
/*
extern      char   *phrfname;
extern      char    InitVocBox( int usenow);
*/
extern      void    ClrSelArea();
extern      void    init_msg_channel();
/*
extern      void    init_phrase();
*/
extern      void    b52key( int inmdno, u_char *ch, u_char *out);
extern      void    write_reply( char *str, int len, int status);
/*
extern      void    init_tab_pho( int usenow);
extern      void    init_tab_pp( int usenow);
*/
extern      void    init_inter_code( int usenow);
extern      void    message_dispatch( XClientMessageEvent *ev);
extern      void    property_dispatch( XPropertyEvent *ev);

int   NowMax;
int   cursor_x = 0, cursor_y = 0;
int   show_keys[9]       = { 10 };
int   show_keys_n  =   1;
char  system_last_full =   1;
int   cur_show_keys      =   0;
int   ignore_cli_stat    =   0;
char  wildmode     = WILDMODE;
char  visual_bell  = VISUAL_BELL;
/*
char  pin_tsin     = PIN_TSIN;
*/
char   *tabfname[14] =  {  NULL, "pinyin.tab", 
                          "shuangpin.tab", 
                          "wubi.tab", 
                           "ziranma.tab" };
char   *showfname = NULL;
char   *display_name     = ":0";
char    tabdir[MAX_PATH_LENGTH]      = XCIN_DIR;
u_char      *hfstr[]     = { "[半形]" , "[全形]" };
u_char      cur_input_ch[2];
u_char      fullchar[]   =
      " !”#$%&’()*+,-./0123456789:;<=>?"
      "@ABCDEFGHIJKLMNOPQRSTUVWXYZ〔\〕^□"
      "‘abcdefghijklmnopqrstuvwxyz{|}~  ";

InmdState inmdstate      =
{
      0,    /* inp state */
      1     /* current in-method */
};

static      int         targe_inmd_key    =   1;
static      int         screen;
static      int         win_obscured;
static      int         s_width, s_height;
static      int         fwidth, fheight;
static      int         replied           =  0;
static      char        *xin_name;
static      char        *geomstr    =  GEOMSTR;
static      char        *AscFontName      =  OPT_XCIN_EFONT;
static      char        *Big5FontName     =  OPT_XCIN_CFONT;
static      char        hide_xcin   =  HIDE_XCIN;
static      char        xcin_length =  XCIN_LENGTH;
static  u_char          *lock;
static      u_char            cur_att;
static      u_char            statstr[]   = " 【英数】";
static      u_char            lockstr[]   = "  ";
static      u_char            tch[ROW_WIDTH][COLUMN_WIDTH]; /* store text */
static      u_char            tat[ROW_WIDTH][COLUMN_WIDTH]; /* color attribute */
static      u_char            tby[ROW_WIDTH][COLUMN_WIDTH]; /* indicate if it is 
                                             a chinese character
                                          */
static      Colormap    colormap;
static      XFontStruct     *afont, *cfont;
static      long        foreground, background;
static      Atom        wm_del_win;
static      Window            last_win    = 0;

static XSizeHints sizehints = {

  /*
   *
   *  这个 structure 记录了 xcin 启动的时候的一些「几何」资讯,
   *  包括了出现的位置、长度、高度、最小(大)长度、最小(大)高度等等,
   *  不过要注意的是,这些值在後面还会被更动,所以我们实际上看到的 xcin
   *  和这里所记录的还是不一样。
   *
  */
      PMinSize | PMaxSize | PResizeInc | PBaseSize | PWinGravity,

      0, 0, MCOL,  MROW,            /* x, y, width, height */

      0, 0,                   /* Min width, Min height */

      MCOL, MROW,             /* Max width, Max height */

      MCOL, MROW,             /* 
                                 Width increments, height increments 
                              */

      {0, 0}, {0, 0},               /* Aspect ratio - not used */

      2 * MARGIN, 2 * MARGIN,       /* base size */

      NorthWestGravity        /* gravity */

};

static struct {

  /*
  **  这个 structure 记录了 xcin 的颜色。
  **  fg_str 是前景颜色, bg_str 是背景颜色。
  */

      u_long      fg, bg;
      char  *fg_str, *bg_str;

} pc_color[]= {

  /*
  **  pc_color[0] 代表的是 xcin 本身的颜色,
  **  pc_color[1] 代表的是 xcin 输入区的颜色。
  */

      { 0, 0, FG_COLOR   , BG_COLOR},
      { 0, 0, IN_FG_COLOR, IN_BG_COLOR}

};

void change_window_name( char *str )
{
  /*
  **  这个 function 可以改 xcin 的 title,传入的参数 str 就是
  **  所欲更改的 title 。
  **
  **  本 function 是从 crxvt 里面抄过来的 :)
  **
  */

  XTextProperty name;

  if (XStringListToTextProperty(&str,1,&name) == 0) {

      error("cannot allocate window name");
      return;

  }

  XSetWMName(display,main_win,&name);
  XFree(name.value);

}

static void Show_Xcin( void )
{
  /*
  **  让 xcin 的视窗变成「可见」(如果本来被隐藏起来的话)
  */

  XMapWindow(display, main_win);

  XRaiseWindow(display, main_win);

}


void p_err(char *fmt, ... )
{
  /*
  **  显示错误讯息并且结束 xcin 。
  */

  va_list args;

  va_start(args, fmt);
  fprintf(stderr,"%s:", xin_name);
  vfprintf(stderr, fmt, args);
  va_end(args);
  fprintf(stderr,"\n");
  exit(-1);

}

void error(char *fmt, ... )
{
  /*
  **  显示错误讯息但是不会结束 xcin 。
  */

  va_list args;

  va_start(args, fmt);
  fprintf(stderr,"%s: ", xin_name);
  vfprintf(stderr, fmt, args);
  va_end(args);
  fprintf(stderr,"\n");

}

static void alloc_pc_colors( void )
{
  /*
  **  这个函式的目的在於设定 xcin 的颜色,
  **  预设值放在 constant.h 。
  */

  XColor color;
  int i;

  for(i=0;i<2;i++) {

      if ( !XParseColor( display, colormap, pc_color[i].fg_str, &color))
            p_err( "invalid color %s", pc_color[i].fg_str);

      if ( !XAllocColor( display, colormap, &color))
            p_err("can't allocate color %s",pc_color[i].fg_str);

      pc_color[i].fg = color.pixel;

      if ( !XParseColor( display, colormap, pc_color[i].bg_str, &color))
            p_err( "invalid color %s", pc_color[i].bg_str);

      if ( !XAllocColor( display, colormap, &color))
            p_err( "can't allocate color %s", pc_color[i].bg_str);

      pc_color[i].bg = color.pixel;

  }

  foreground = pc_color[0].fg;
  background = pc_color[0].bg;

}


static void load_font( char *fnt_name, char *cfnt_name )
{

  /*
  **   这个 function 是用来载入字型,并且根据英文字型的大小来决定
  **   xcin 的长度及高度。
  **
  **   理论上来说,所使用的中文字型的宽度最好是英文字型的两倍。
  */

  int x, y, width, height;
  int flags;

  if ( !( afont = XLoadQueryFont( display, fnt_name)  ) )
      p_err( "Cannot load ascii font %s", fnt_name);

  if ( !( cfont = XLoadQueryFont( display, cfnt_name) ) )
      p_err( "Cannot load Chinese font %s", cfnt_name);

  fwidth  = sizehints.width_inc  = afont->max_bounds.width;
  fheight = sizehints.height_inc = afont->ascent + afont->descent;

  flags = XParseGeometry(geomstr,&x,&y,&width,&height);

  if ( flags & WidthValue) {
      sizehints.flags |= USSize;
  }
  if ( flags & HeightValue) {
      sizehints.flags |= USSize;
  }

  s_width  = sizehints.width;
  s_height = sizehints.height;

  sizehints.width = ( sizehints.width + xcin_length ) * sizehints.width_inc +
                  sizehints.base_width;

  sizehints.height = sizehints.height * sizehints.height_inc +
                  sizehints.base_height;

  sizehints.max_width  = 10 * sizehints.width ;
  sizehints.max_height = sizehints.min_height = sizehints.height;

  sizehints.min_width = 0;

  if ( flags & XValue ) {

      if ( flags & XNegative ) {

        x = DisplayWidth( display,screen ) + x - sizehints.width - 2;

        sizehints.win_gravity = NorthEastGravity;

      }

      sizehints.x = x;
      sizehints.flags |= USPosition;

  }

  if ( flags & YValue ) {

      if ( flags & YNegative ) {

        y = DisplayHeight( display,screen ) + y - sizehints.height - 2;

        sizehints.win_gravity = SouthWestGravity;

        if( ( flags&XValue ) && ( flags&XNegative ) )
            sizehints.win_gravity = SouthEastGravity;

      }

      sizehints.y = y;
      sizehints.flags |= USPosition;

  }

}

XClassHint class;

static void create_win( int argc, char **argv )
{

  /*
  **  这个 functino 就是根据前面的一些资讯来建构 xcin 的主视窗。
  */

  XWMHints  wmhints;
  XTextProperty name;

  main_win = XCreateSimpleWindow( display, DefaultRootWindow( display ),
                          sizehints.x,          sizehints.y,
                          sizehints.width,      sizehints.height,
                          1,
                          foreground,           background);

  class.res_name = xin_name;
  class.res_class = "xcin";
  wmhints.input = False;
  wmhints.initial_state = NormalState;
  wmhints.flags = InputHint | StateHint;

  if ( XStringListToTextProperty( &xin_name, 1, &name) == 0) {
      error( "cannot allocate window name" );
      return;
  }

  XSetWMProperties( display, main_win, &name, &name, argv, argc,
               &sizehints, &wmhints, &class);

  XFree( name.value );

  XSelectInput( display, main_win, MW_EVENTS);
 
  if ( !hide_xcin )
      XMapWindow( display, main_win);

}

static void XInErrorHandler( Display *dpy, XErrorEvent *event )
{
    p_err( "Warning, error event receieved\n" );
}


static void ostr( int x, int y, char *str, int len, u_char att )
{
  /*
  **  Output STRing ( English character ,在 xcin 上共示英文)
  */

  int       ix, iy;
  u_long    fg, bg;

  if ( !len ) len = strlen( str );

  memcpy( &tch[y][x], str, len);
  memset( &tat[y][x], att, len);
  bzero(  &tby[y][x],      len);

  ix = x * fwidth;
  iy = y * fheight + afont->ascent;

  fg = pc_color[att&0xf].fg;
  bg = pc_color[att&0xf].bg;

  XSetForeground( display, gc, fg);
  XSetBackground( display, gc, bg);

  XDrawImageString( display, main_win, gc, ix,iy, str, len);

}

static void costr( int x, int y, char *str, int len, u_char att )
{
  /*
  **  Chinese Output STRing (在 xcin 上显示中文)
  */

  int ix, iy;
  int i;

  u_char *bp = &tby[y][x];
  u_long fg, bg;

  if ( !len ) len = strlen( str );
  memcpy( &tch[y][x], str, len);
  memset( &tat[y][x], att, len);

  for( i=0; i < len; i++)
    *(bp+i)= ( (i&1)? 0x20 : 0x40 );      /* 0:asc  0x20:CH1   0x40:CH2 */

  ix = x * fwidth;
  iy = y * fheight + cfont->ascent;
  fg = pc_color[att&0xf].fg;
  bg = pc_color[att&0xf].bg;

  XSetForeground( display, cgc, fg);
  XSetBackground( display, cgc, bg);

  for(i = 0; i < len; i++) str[i] -= 0x80;
  XDrawImageString16( display, main_win, cgc, ix,iy, (XChar2b *)str, len>>1);
  for(i = 0; i < len; i++) str[i] += 0x80;

}

static void restore( void )
{
  /*
  ** 复原 xcin 上的文字。
  */
  int y,i;
  int stx;
  int len;
  u_char catt,cbyte;
  u_char *p,*q,*str;
  GC tgc;
  u_long fg,bg;

  for( y = 0; y < MROW; y++) {
     p = &tat[y][0];
     q = &tby[y][0];
     stx = 0;
     len = 0;
     catt  = *p;
     cbyte = *q;

     while ( stx < MCOL ) {

      if ( cbyte & 0x60 ) cbyte |= 0x60;

      while (
            ( catt  == *p ) &&
            ( cbyte == ( *q & 0x60? *q | 0x60:*q ) ) &&
              len   + stx < MCOL
             ) {

            len++; p++; q++;

      }

      tgc = ( cbyte & 0x60 )? cgc : gc;
      fg  = pc_color[catt&0xf].fg;
      bg  = pc_color[catt&0xf].bg;

      XSetForeground( display, tgc, fg);
      XSetBackground( display, tgc, bg);

      if ( cbyte & 0x60 )
        {
                str = &tch[y][stx];
                for(i=0; i<len; i++) str[i] -= 0x80;
            XDrawImageString16( display, main_win, tgc, stx * fwidth,
                  y * fheight + cfont->ascent,
                  (XChar2b *) &tch[y][stx], len >> 1);
                for(i=0; i<len; i++) str[i] += 0x80;
      }
        else
            XDrawImageString(   display, main_win, tgc, stx * fwidth,
                  y * fheight + afont->ascent,
                  &tch[y][stx], len);

      stx   += len;
      len    = 0;
      catt   = *p;
      cbyte  = *q;

     } /* end of while ( stx < MCOL ) */

  } /* end of for( y = 0; y < MROW; y++) */

}

static void xputs( int x, int y, u_char *s, u_char att )
{
  /*
  ** 将游标移到 ( x , y ) 这个点并且显示 s 这个字串,
  ** 此处的 ( x , y ) 是指「第 x 个字」和「第 y 个字」的位置。
  */
  int  len = strlen( s );
  int  cl  = 0;
  char       ctyp;
  u_char *cp, *endp, *strp;
  u_char hb, lb;

  strp = cp = s;
  endp = s + len;
  cl   = 0;
  ctyp = 0;

  while ( cp < endp ) {
     hb = *cp;
     if ( ( hb >= 0x81 ) && ( hb <= 0xfe ) && ( cp + 1 < endp ) ) {

      lb = *( cp + 1 );

      if ( lb >= 0xA1 && lb <= 0xfe ) {

            if ( ctyp == 1 ) {

                  ostr( strp-s+x, y, strp, cl, att);
                  cl   = 0;
                  strp = cp;

            } /* end  if ( ctyp == 1 ) */

            cl   += 2;
            cp   += 2;
            ctyp  = 2;
            continue;

      } /* end  if ( ( ( lb >= 0x40 && ........  */

     } /* end  if ( ( hb >= 0x81 ) && .......... */

     if ( ctyp == 2 ) {
      costr( strp-s+x, y, strp, cl, att);
      cl   = 0;
      strp = cp;
     }

     cl++;
     cp++;
     ctyp = 1;

  }

  if ( ctyp == 1 )  ostr( strp - s + x, y, strp, cl, att);
  if ( ctyp == 2 ) costr( strp - s + x, y, strp, cl, att);

  return;

}


void xprintf(char *fmt, ... )
{
  /*
  **
  ** 在 xcin 的视窗上显示文字。
  **
  ** 这个函式和 xputs() 的不同点在於 xprintf() 可以接受像 %s %d
  ** 以接受字串或整数的输入,而 xputs() 则不行。
  **
  */

  va_list args;
  char        tmp[100];

  va_start( args, fmt);
  vsprintf( tmp, fmt, args);
  va_end( args );
  xputs( cursor_x, cursor_y, tmp, cur_att);
  cursor_x += strlen(tmp);

}


void gotoxy( int x, int y )
{
  /*
  ** 将 xcin 的输入点移到 ( x , y ) 这个点,以便使用 xprintf() 来
  ** 显示文字。
  **
  ** P.S. 此处的 ( x , y ) 是指「第 x 个字」和「第 y 个字」的位置,
  **    而不是「第 x 个像素」和「第 y 个像素」。
  */

  cursor_x = x;
  cursor_y = y;

}

void ClrShowArea( char x )
{
  char i;

  if ( x != 0 ) 
  {
      switch(CurInMethod)
      {
        case 10:
         gotoxy( 24, MROW - 1 );
           break;
        case 11:
         gotoxy( 16, MROW - 1 );
           break;
        default:
         gotoxy( 17 + 2 * NowMax, MROW-1);
           break;
      }
  }

  for( i = 0; i < COLUMN_WIDTH - cursor_x ; i++ )
     xprintf(" ");
}

void set_att( u_char att )
{
  /*
  ** 设定 xcin 上文字的颜色属性。
  */
  cur_att  = att;
}


void bell( int bell_kind )
{
  /*
  **
  ** 根据传入值 bell_kind 和 visual_bell 的值来决定要不要发出「哔」一声。
  **
  ** 1. visual_bell 之值为 3    ---> 安静无声
  ** 2. visual_bell 之值为 0    ---> 发出「哔」一声
  ** 3. visual_bell 之值为 1 或 2 ---> visual_bell == bell_kind ?
  **
  **                          1. Yes ---> 「哔」
  **                          2. No  ---> 不「哔」
  **
  */
  if ( visual_bell == 3 ) {
      XClearWindow( display, main_win);
      XFlush( display);
      restore();
  }

  else if ( visual_bell == 0 ) XBell( display, -50);

  else if ( visual_bell == bell_kind) XBell( display, -50);

}


static void show_target( u_char *s )
{
  /*
  ** 如果所传入的字串 s 为一个中文字则显示此中文字在 targe_inmd_key 
  ** 所指定的输入法的拆法。
  **
  ** 如果 targe_inmd_key 所指到的是注音、词音或是词库,则不做任何动作。
  **
  */
  u_char kk[200];

  memset( kk, ' ' , sizeof( kk ) );

  ClrShowArea( 1 );
 
  sprintf( kk, "%2X%2X      ", (u_int)s[0], (u_int)s[1]);

  switch ( targe_inmd_key ) {
      case 10:
          sprintf( kk, "%2X%2X      ", (u_int)s[0], (u_int)s[1]);
          break;
      case 11:
          kk[0] = 0;  /* Not show the target */
            break;
      default:
            b52key( targe_inmd_key, s, kk );
  }

  if ( CurInMethod == 10 )
     gotoxy( 25, MROW - 1 );
  else
     gotoxy( NowMax * 2 + 17, MROW - 1 );

  if ( kk[0] ) xprintf( "%s", kk );
}


static void putkey_b5( u_char *s )
{
  write_reply( s, 2, K_ACCEPT );
  replied = 1;
}

void sendkey_b5( u_char *s )
{
  cur_input_ch[0]  =  s[0];
  cur_input_ch[1]  =  s[1];
/*
  show_target( cur_input_ch );
*/
  putkey_b5( s );
}

void putstr( u_char *s )
{
  write_reply( s, strlen( s ), K_ACCEPT );
  replied = 1;
}

static void putfchr( char ch )
{
  char tt[3];
  int  ii = (int)( ch - ' ' ) << 1;

  tt[0] = fullchar[ii];
  tt[1] = fullchar[ii+1];
  tt[2] = 0;
  putstr( tt );
}

static void puthchr( char ch )
{
  char tt[2];

  tt[0] = ch;
  tt[1] = 0;
  putstr( tt );
}

static void no_out( void )
{
  write_reply( 0, 0, K_ACCEPT );
}

static void reject( void )
{
  write_reply( 0, 0, K_REJECT );
}


static int SwitchCurInMethod( int usenow )
{

  switch ( CurInMethod ) {
/*
     case 3:

      init_tab_pho( usenow );
      break;

     case 6:

      init_tab_pp( usenow );
      break;
*/
     case 10:

      init_inter_code( usenow );
      break;
/*
     case 11:

      if ( tabfname[11] ) {

          if ( InitVocBox( usenow ) == 1 )
            ClrShowArea( 1 );

      }
      else {

          CurInMethod=1;
          init_tab( CurInMethod, usenow );
      }

      break;
*/
     default:

      if ( tabfname[(int)CurInMethod] ) {

          if ( init_tab( CurInMethod, usenow ) == -1 ) {

               printf("Error loadling input method %d: %s\n",CurInMethod,
                          tabfname[(int)CurInMethod]);
            targe_inmd_key = 1;
            CurInMethod = 1;
            return -1;

          }

      }

  } /* end of switch ( CurInMethod ) */

  return 0;

}

static void show_halffull( void )
{
  ClrShowArea( 1 );
  gotoxy( 40, MROW - 1 );
  xprintf( "%s", lock );
  gotoxy(  9, MROW - 1 );
  xprintf( "%s", hfstr[HalfFull] );
}


void switch_active_client( InmdState *state, Window cli_win )
{
  last_win = cli_win;

  if ( ignore_cli_stat )
      ignore_cli_stat = 0;
  else
     if ( state->_CurInMethod )
      memcpy( &inmdstate, state, sizeof( inmdstate ) );

  if ( hide_xcin && ( EngChi || HalfFull ) )
     Show_Xcin();
  else if ( hide_xcin && !EngChi && !HalfFull )
     XUnmapWindow( display, main_win );

  gotoxy( 0, MROW - 1 );

  ClrShowArea( 0 );

  gotoxy( 0, MROW - 1 );

  if ( !EngChi ) xprintf( "%s", statstr );

  show_halffull();

  if ( EngChi ) SwitchCurInMethod( 1 );

  XFlush( display );

}

void close_xcin( Window cli_win )
{
  if ( hide_xcin && last_win == cli_win )
     XUnmapWindow( display, main_win );
}

void next_inp( void )
{
  int i;

  for( i = CurInMethod + 1; i != CurInMethod; i = ( i + 1 ) % 14 )
     if ( tabfname[i] ) {
      if ( i ) {
           CurInMethod = i;
           inmdstate.kb_state |= EngChiMask;
           if( SwitchCurInMethod( 1 ) == -1 ) continue;
           if ( hide_xcin )
              Show_Xcin();
      } else
      if ( EngChi ) {
            if ( hide_xcin && !HalfFull )
            XUnmapWindow( display, main_win );
            inmdstate.kb_state &= ~EngChiMask;
            gotoxy( 0, MROW - 1 );
            xprintf( "%s", statstr );
            gotoxy( 16, MROW - 1 ); /* clear prev inp */
            ClrShowArea( 0 );
            change_window_name( "English" );
            if ( hide_xcin && !HalfFull )
                  XUnmapWindow( display, main_win );
      } else
            continue;

      break;
     }

  if ( i == CurInMethod ) {
     CurInMethod = i;
     inmdstate.kb_state |= EngChiMask;
     SwitchCurInMethod( 1 );
     if ( hide_xcin )
      Show_Xcin();
  }

}

void toggle_halffull( void )
{
      inmdstate.kb_state ^= HalfFullMask;
      show_halffull();
}


void getch(KeySym ch, int state)
{
int res=0;
      replied=0;
      if (win_obscured && (EngChi||HalfFull)) {
              XRaiseWindow(display, main_win);
            win_obscured=0;
      }
#if   0
      printf("k:%x st:%x\n", ch, state);
#endif      0
        /*
      if ((state&(Mod1Mask|Mod5Mask)) && (state&ShiftMask)) {
            res=lookup_key(tolower(ch));
      } else 
        */
      if ( (ch==' ' || ch==0) && (state & ControlMask) ) 
        {
            inmdstate.kb_state^=EngChiMask;
            ClrSelArea();
            if (!EngChi) 
                {
                  gotoxy(0,MROW-1);
                  xprintf("%s",statstr);
                  gotoxy(16,MROW-1);
                  ClrShowArea( 0 );
                  change_window_name("English");
                  if (hide_xcin && !HalfFull)
                        XUnmapWindow(display, main_win);
            } 
                else 
                {
                  if (hide_xcin) Show_Xcin();
                  SwitchCurInMethod(1);
            }
            XFlush(display);
            no_out();
            return;
      } else
      if (ch==' '  && (state & ShiftMask)) {
            toggle_halffull();
            res=1;
            if (hide_xcin && !EngChi && !HalfFull)
                  XUnmapWindow(display, main_win);
            else if (hide_xcin && !EngChi && HalfFull)
                  Show_Xcin();
            goto return_s;
      } else
      if ( state & ControlMask && (state & (Mod1Mask|Mod5Mask)) ) {
            switch (ch) {
            int ttt;
            int last_CurInMethod;
                  case '1':
                  case '2':
                        case '3':
                  case '4':
                        case '6':
                  case '5':
                  case '7':
                  case '8':
                  case '9':
                  case '=':
                        if (ch=='=') ttt=12;
                        else
                              ttt=ch-'0';
                        if (!tabfname[ttt])
                              break;
                        inmdstate.kb_state |= EngChiMask;
                        last_CurInMethod = CurInMethod;
                        CurInMethod=ttt;
                        if( init_tab(CurInMethod,1) == -1) {
                              CurInMethod = last_CurInMethod;
                              break;
                        }
                        Show_Xcin();
                        break;
/*
                  case '3':
                        CurInMethod=3;
                        inmdstate.kb_state |= EngChiMask;
                        init_tab_pho(1);
                        Show_Xcin();
                        break;
                  case '6':
                        CurInMethod=6;
                        inmdstate.kb_state |= EngChiMask;
                        init_tab_pp(1);
                        Show_Xcin();
                        break;
*/
                  case '0':
                        CurInMethod=10;
                        inmdstate.kb_state |= EngChiMask;
                        init_inter_code(1);
                        ClrSelArea();
                        Show_Xcin();
                        break;
 /*
                  case '-':
                        if (!tabfname[11]) break;
                        last_CurInMethod = CurInMethod;
                        CurInMethod=11;
                        inmdstate.kb_state |= EngChiMask;
                        if ( InitVocBox(1) == -1 ) {
                           CurInMethod = last_CurInMethod;
                           break;
                        }
                        ClrSelArea();
                        Show_Xcin();
                        break;
                  case 'i':
                  case 'I':
                        cur_show_keys=(cur_show_keys+1)%show_keys_n;
                        targe_inmd_key=show_keys[cur_show_keys];
                        if (cur_input_ch[0]) {
                              show_target(cur_input_ch);
                        }
                        break;
*/
                  case 'R':
                  case 'r':
                        sendkey_b5(cur_input_ch);
                        return;
                  case 'M':
                  case 'm':
                        if (hide_xcin) {
                              Show_Xcin();
                              hide_xcin = 0;
                              lock = lockstr;
                        } else {
                              if (!EngChi && !HalfFull)
                                    XUnmapWindow(display, main_win);
                              hide_xcin = 1;
                              lock = "  ";
                        }
                        ClrShowArea( 1 );
                        gotoxy(40,MROW-1);
                        xprintf("%s",lock);
                        break;
            }
            XFlush(display);
            no_out();
            return;
      } else
      if (EngChi && ! (state & (ControlMask | Mod1Mask | Mod5Mask))
          && ch!=XK_Control_L) {
                  int shiftm=state & ShiftMask;
                  res = 0;
                  if (shiftm && ch!='<' && ch!='>' && ch>' ' &&ch<127 &&
                        ch!='*' && ch!='?' )  {
                        /*char tt[2];*/
                        if (state&LockMask && islower(ch))
                              ch-=0x20;
                        else
                        if (!(state&LockMask) && isupper(ch))
                              ch+=0x20;
                        if (HalfFull) putfchr(ch);
                        else puthchr(ch);
                        return;
                  }
                  switch (CurInMethod) {
/*
                  case 3:
                        res=feedkey_pho(ch);
                        break;
                  case 6:
                        res=feedkey_pp(ch, state);
                        break;
*/
                  case 10:
                        if (!shiftm) res=feedkey_intcode(ch);
                        break;
/*
                  case 11:
                        res=feedkey_vocbox(ch);
                        break;
*/
                  default:
                        if(shiftm && (ch=='>' || ch=='<')) {
                              res=feedkey(ch);
                              break;
                        }
                        res=feedkey(ch);
                        break;
                  }
      } else
#if   0
      if (((ch==XK_Control_L||ch==XK_Control_R) && (state&ShiftMask)) ||
            ((ch==XK_Shift_L||ch==XK_Shift_R) && (state&ControlMask)) ) {
#else
      if ((ch==XK_Control_L && state&ShiftMask) ||
            (ch==XK_Shift_L && state&ControlMask) ) {
#endif

            ClrSelArea();
            next_inp();
            res=1;
            goto return_s;
      }
      if ((!EngChi || !res) &&
            !(state&(ControlMask|Mod1Mask|Mod5Mask)) ) {
            /*u_char tt[3];*/
            if (HalfFull && ch>=' ' && ch<=0x7e) {
                  putfchr(ch);
            }
      }
return_s:
      if (!replied) {
            if (res)
                  no_out();
            else 
                  reject();
      }
      XFlush(display);
}

#define x_cx(x) (x/fwidth)
#define y_cy(y) (y/fheight)

void button_press(XButtonEvent *ev)
{
int cx,cy;
void change_xcin_font(char *fn, char *fnb5);

if (ev->button==Button1) {
      cx=x_cx(ev->x);
      cy=y_cy(ev->y);
      if (cy==MROW-1) {
            if (cx>=0 && cx<=8) next_inp();
            else
            if (cx>=9 && cx<=14) toggle_halffull();
            ignore_cli_stat=1;
      }
}

/*if (ev->button==Button2) {
      static i=0;

      if( i == 0 ) change_xcin_font("vga12x24","et24k");
      if( i == 1 ) change_xcin_font("vga8x15","et15");
      i = 1 - i;
}
*/ /* 这一段程式码是说按一下滑鼠右键可以线上切换字型,
      不过现阶段没有什麽太大用途所以取消。 */
}


void run_event()
{
  XEvent event;

for(;;) {
  XNextEvent(display,&event);

    switch(event.type) {
    case KeyPress:
      if (!hide_xcin)
      XRaiseWindow(display, main_win);
      break;
    case ClientMessage:
      if (event.xclient.message_type == xcin_atom ) {
            message_dispatch(&event.xclient);
      } else
      if (event.xclient.format == 32 && event.xclient.data.l[0] == wm_del_win)
            p_err("Quit");
      break;
    case PropertyNotify:
      property_dispatch(&event.xproperty);
      break;
#if   0
    case MappingNotify:
      XRefreshKeyboardMapping(&event.xmapping);
      break;
#endif      0
    case GraphicsExpose:
    case Expose:
      restore();
      break;
    case ButtonPress:
      button_press((XButtonEvent *) &event);
      break;
    case VisibilityNotify:
      {     XVisibilityEvent *eve=(XVisibilityEvent *)&event;
            if (eve->window==main_win &&
                (eve->state==VisibilityPartiallyObscured||
                 eve->state==VisibilityFullyObscured  ) )
                        win_obscured=1;
      }
      break;
    default:
/*    printf("Unknow event %d\n",event.type); */
      break;
    }
}

}




void change_xcin_font(char *fn, char *fnb5)
{
      XWindowChanges values;
      XGCValues gcv;
      XFontStruct *ctemp, *atemp;

      if( fnb5 && (ctemp=XLoadQueryFont(display, fnb5))==NULL) return;

      if( fn   && (atemp=XLoadQueryFont(display, fn))  ==NULL) return;

      if( fnb5 ) {
            XFreeFont(display, cfont);
            cfont=XLoadQueryFont(display, fnb5);
            gcv.font=cfont->fid;
            XChangeGC(display, cgc,GCFont,&gcv);
      }

      if( fn ) {
            XFreeFont(display, afont);
            afont=XLoadQueryFont(display, fn);
            gcv.font=afont->fid;
            XChangeGC(display, gc,GCFont,&gcv);
      }

      fwidth  = sizehints.width_inc  = afont->max_bounds.width;
      fheight = sizehints.height_inc = afont->ascent + afont->descent;

      values.width  = (s_width+xcin_length) * fwidth + sizehints.base_width;
      values.height = s_height * fheight + sizehints.base_height;

      sizehints.max_width  = 10 * values.width ;
      sizehints.max_height = sizehints.min_height = values.height;
      sizehints.min_width = 0;
      sizehints.flags &= ~PMaxSize;
      sizehints.flags &= ~PMinSize;

      XSetWMNormalHints(display,main_win,&sizehints);
      XConfigureWindow(display,main_win,CWWidth|CWHeight, &values);

      sizehints.flags |=  PMaxSize;
      sizehints.flags |=  PMinSize;
      XSetWMNormalHints(display,main_win,&sizehints);

}


/*----------------------------------------------------------------------------

        Main  Program.

----------------------------------------------------------------------------*/

void XResourceFile(int argc, char **argv);

void main(int argc, char **argv)
{
    int i;
    XGCValues gcv;
    char *d_name;

    puts("\n"
         "+----------- XCIN GB version 2.3.02 -----------+\n"
       "|                                              |\n"
         "|   by Edward Der-Hua Liu, Taiwan              |\n"
       "|                                              |\n"
       "|   with vvvv's XcinFix4.4                     |\n"
       "|                                              |\n"
       "|   with thhsieh's experimental modification.  |\n"
       "|                                              |\n"
         "+----------------------------------------------+\n");

    xin_name="xcin";
    if((d_name=getenv("DISPLAY")))
      display_name = d_name;

    XResourceFile(argc, argv);


    if(! (display = XOpenDisplay(display_name)))
      p_err("Cannot open display %s", display_name);


XSetErrorHandler((XErrorHandler)XInErrorHandler);

if (tabdir[strlen(tabdir)-1]!='/') strcat(tabdir,"/");
if ((CurInMethod<=0 || CurInMethod>11) ||
            (!tabfname[(int)CurInMethod]) ||
            init_tab( CurInMethod, 0 ) == -1 )
      CurInMethod=1;

/*
targe_inmd_key=CurInMethod;

if( showfname ) {
   if ( init_tab(14,0) != -1 )
      targe_inmd_key=14;
   else
      targe_inmd_key= 1;
}
*/

colormap = DefaultColormap(display,screen);
screen = DefaultScreen(display);
alloc_pc_colors();

bzero(tat, sizeof(tat));

load_font(AscFontName,Big5FontName);
create_win(argc,argv);

init_msg_channel();

XSetSelectionOwner(display, xcin_atom, main_win, CurrentTime);

set_att(0);
wm_del_win = XInternAtom(display,"WM_DELETE_WINDOW",False);
XSetWMProtocols(display,main_win,&wm_del_win,1);
gcv.foreground = foreground;
gcv.background = background;
gcv.font=afont->fid;
gc = XCreateGC(display,main_win,GCForeground|GCBackground|GCFont,&gcv);
gcv.font=cfont->fid;
cgc = XCreateGC(display,main_win,GCForeground|GCBackground|GCFont,&gcv);

if (!hide_xcin)
  lock= lockstr;
else
  lock= "  ";
SwitchCurInMethod(0);
gotoxy(0,MROW-1);
xprintf("%s",statstr);
show_halffull();
/*
init_phrase();
*/
change_window_name("English");
run_event();
return ;
}


/*----------------------------------------------------------------------------

        New Functions.

----------------------------------------------------------------------------*/

void *CallMemory(u_int n_elem, u_int size, char *func, int exitcode)
{
    void  *v=NULL;

    if((v=calloc(n_elem, size)) == NULL) {
        fprintf(stderr, "%s:  Cannot locate the memory with size: %ux%u.\n",
                        func, n_elem, size);

        if(exitcode)    exit(exitcode);
    }
    return  v;
}

/*---------------------------------------------------------------------------

        Initialization  Functions.

---------------------------------------------------------------------------*/

int GetHomeDir(char *homedir)
{
    char  *str;

    if(! (str=getenv("HOME")) && ! (str=getenv("home"))) {
        fprintf(stderr, "Cannot get the user HOME directory.\n");
        return  0;
    }
    else {
        sprintf(homedir, "%s/", str);
        return  1;
    }
}

void PrintHelpMessage(char *arg)
{
    fprintf(stderr,
"xcin: Unknown argument: %s\n"
"xcin: Valid args are (See README for details):\n", arg);

    fprintf(stderr,
"     -tabdir     table directory name.\n"
/*
"     -tsfname    TsIn file name.\n"
*/
"     -inmd       Input method: 1-11.\n"
/*
"     -phokbm     phonetic kbd (zo:01, et:eten, et26:et26, hsu:hsu's).\n"
*/
"     -fg         foreground color.\n"
"     -bg         background color.\n"
"     -infg       input area fg.\n"
"     -inbg       input area bg.\n"
"     -geometry   position of xcin +100-0.\n"
"     -g          position of xcin +100-0.\n"
"     -font       Ascii font name.\n"
"     -fnb5       Big5 font name.\n"
"     -display    display name.\n"
"     -in1        in method 1.\n"
"     -in2        in method 2.\n"
"     -in3        in method 3.\n"
"     -in4        in method 4.\n"
"     -in5        in method 5.\n"
"     -in6        in method 6.\n"
"     -in7        in method 7.\n"
"     -in8        in method 8 (eg) ar30.tab.\n"
"     -in9        in method 9.\n"
"     -vocbox     vocabulary box file name.\n"
"     -in12       in method 12.\n"
/*
"     -going      going:  0,1.\n"
*/
"     -phrase     phrase name.\n"
"     -vb         visual bell: 0,1,2,3.\n"
"     -hidden     hide xcin: 0,1.\n"
/*
"     -sinmd      show the input method.\n"
*/
"     -wild       use wildcard mode.\n"
"     -len        the length of xcin, compare to normal size, default is 0.\n"
/*
"     -pintsin    use pin-yin for tsin.\n"
*/
"     -last_full  send space when reach max keys and press space.\n");

    exit(1);
}

#define NOPTS  33

static XrmOptionDescRec OptTable[NOPTS] = {
    {"-bg",        ".bg",        XrmoptionSepArg, (XPointer)NULL},
    {"-fg",        ".fg",        XrmoptionSepArg, (XPointer)NULL},
    {"-font",      ".font",      XrmoptionSepArg, (XPointer)NULL},
    {"-fnb5",      ".fnb5",      XrmoptionSepArg, (XPointer)NULL},
    {"-geometry",  ".geometry",  XrmoptionSepArg, (XPointer)NULL},
    {"-g",         ".g",         XrmoptionSepArg, (XPointer)NULL},
    /*
    {"-going",     ".going",     XrmoptionSepArg, (XPointer)NULL},
    */
    {"-hidden",    ".hidden",    XrmoptionSepArg, (XPointer)NULL},
    {"-display",   ".display",   XrmoptionSepArg, (XPointer)NULL},
    {"-in1",       ".in1",       XrmoptionSepArg, (XPointer)NULL},
    {"-in2",       ".in2",       XrmoptionSepArg, (XPointer)NULL},
    {"-in3",       ".in3",       XrmoptionSepArg, (XPointer)NULL},
    {"-in4",       ".in4",       XrmoptionSepArg, (XPointer)NULL},
    {"-in5",       ".in5",       XrmoptionSepArg, (XPointer)NULL},
    {"-in6",       ".in6",       XrmoptionSepArg, (XPointer)NULL},
    {"-in7",       ".in7",       XrmoptionSepArg, (XPointer)NULL},
    {"-in8",       ".in8",       XrmoptionSepArg, (XPointer)NULL},
    {"-in9",       ".in9",       XrmoptionSepArg, (XPointer)NULL},
    {"-in12",      ".in12",      XrmoptionSepArg, (XPointer)NULL},
    {"-infg",      ".infg",      XrmoptionSepArg, (XPointer)NULL},
    {"-inbg",      ".inbg",      XrmoptionSepArg, (XPointer)NULL},
    {"-inmd",      ".inmd",      XrmoptionSepArg, (XPointer)NULL},
    {"-last_full", ".last_full", XrmoptionSepArg, (XPointer)NULL},
    {"-len",       ".len",       XrmoptionSepArg, (XPointer)NULL},
/*
    {"-phokbm",    ".phokbm",    XrmoptionSepArg, (XPointer)NULL},
*/
    {"-phrase",    ".phrase",    XrmoptionSepArg, (XPointer)NULL},
/*
    {"-pintsin",   ".pintsin",   XrmoptionSepArg, (XPointer)NULL},
    {"-sinmd",     ".sinmd",     XrmoptionSepArg, (XPointer)NULL},
*/
    {"-tabdir",    ".tabdir",    XrmoptionSepArg, (XPointer)NULL},
/*
    {"-tsfname",   ".tsfname",   XrmoptionSepArg, (XPointer)NULL},
*/
    {"-vb",        ".vb",        XrmoptionSepArg, (XPointer)NULL},
    {"-vocbox",    ".vocbox",    XrmoptionSepArg, (XPointer)NULL},
    {"-wild",      ".wild",      XrmoptionSepArg, (XPointer)NULL}
};

int ResourceValueInt(XrmDatabase xd, char *class_type, int init_value)
{
    char      rcs_value[MAX_PATH_LENGTH], *rcs_type;
    XrmValue  xrmvalue;

    if(XrmGetResource(xd, class_type, NULL, &rcs_type, &xrmvalue)) {
        strncpy(rcs_value, xrmvalue.addr, xrmvalue.size);
        rcs_value[xrmvalue.size] = '\0';
        return  atoi(rcs_value);
    }
    else
        return  init_value;
}

char *ResourceValueStr(XrmDatabase xd, char *class_type, char *init_value)
{
    char     *rcs_value, *rcs_type;
    XrmValue  xrmvalue;

    if(XrmGetResource(xd, class_type, NULL, &rcs_type, &xrmvalue)) {
        rcs_value = CallMemory(xrmvalue.size+1, sizeof(char),
                               "ResourceValueStr", 1);
        strncpy(rcs_value, xrmvalue.addr, xrmvalue.size);
        rcs_value[xrmvalue.size] = '\0';
        return  rcs_value;
    }
    else
        return  init_value;
}

XrmDatabase  xd;
void XResourceFile(int argc, char **argv)
{
    char         home[MAX_PATH_LENGTH],
                 rcname[MAX_PATH_LENGTH];

    XrmInitialize();
    GetHomeDir(home);

    sprintf(rcname, "%s%s", home, ".Xdefaults");
    XrmCombineFileDatabase(rcname, &xd, True);
    sprintf(rcname, "%s%s", home, ".Xresources");
    XrmCombineFileDatabase(rcname, &xd, True);

    XrmParseCommand(&xd, OptTable, NOPTS, "xcin", &argc, argv);
    if(argc != 1)
        PrintHelpMessage(argv[1]);

    pc_color[0].fg_str =
        ResourceValueStr(xd, "xcin.fg", pc_color[0].fg_str);
    pc_color[0].bg_str =
        ResourceValueStr(xd, "xcin.bg", pc_color[0].bg_str);
    pc_color[1].fg_str =
        ResourceValueStr(xd, "xcin.infg", pc_color[1].fg_str);
    pc_color[1].bg_str =
        ResourceValueStr(xd, "xcin.inbg", pc_color[1].bg_str);
    display_name =
        ResourceValueStr(xd, "xcin.display", display_name);
    AscFontName =
        ResourceValueStr(xd, "xcin.font", AscFontName);
    Big5FontName =
        ResourceValueStr(xd, "xcin.fnb5", Big5FontName);
    geomstr =
        ResourceValueStr(xd, "xcin.g", geomstr);
    geomstr =
        ResourceValueStr(xd, "xcin.geometry", geomstr);
/*
    going_key = (char)
        ResourceValueInt(xd, "xcin.going", going_key);
*/
    hide_xcin = (char)
        ResourceValueInt(xd, "xcin.hidden", hide_xcin);
    CurInMethod = (char)
        ResourceValueInt(xd, "xcin.inmd", CurInMethod);
/*
    showfname =
        ResourceValueStr(xd, "xcin.sinmd", showfname);
*/
    tabfname[1] =
        ResourceValueStr(xd, "xcin.in1", tabfname[1]);
    tabfname[2] =
        ResourceValueStr(xd, "xcin.in2", tabfname[2]);
    tabfname[3] = 
        ResourceValueStr(xd, "xcin.in3", tabfname[3]);
    tabfname[4] = 
        ResourceValueStr(xd, "xcin.in4", tabfname[4]);
    tabfname[5] =
        ResourceValueStr(xd, "xcin.in5", tabfname[5]);
    tabfname[6] =
        ResourceValueStr(xd, "xcin.in6", tabfname[6]);
    tabfname[7] =
        ResourceValueStr(xd, "xcin.in7", tabfname[7]);
    tabfname[8] =
        ResourceValueStr(xd, "xcin.in8", tabfname[8]);
    tabfname[9] =
        ResourceValueStr(xd, "xcin.in9", tabfname[9]);
    tabfname[11] =
        ResourceValueStr(xd, "xcin.vocbox", tabfname[11]);
    tabfname[12] =
        ResourceValueStr(xd, "xcin.in12", tabfname[12]);
    system_last_full =
        ResourceValueInt(xd, "xcin.last_full", system_last_full);
/*
    phokbm_name =
        ResourceValueStr(xd, "xcin.phokbm", phokbm_name);
    phrfname =
        ResourceValueStr(xd, "xcin.phrase", phrfname);
    pin_tsin = (char)
        ResourceValueInt(xd, "xcin.pintsin", pin_tsin);
*/
    strcpy(tabdir, 
      ResourceValueStr(xd, "xcin.tabdir", tabdir));
/*
    tsfname =
        ResourceValueStr(xd, "xcin.tsfname", tsfname);
*/
    visual_bell = (char)
        ResourceValueInt(xd, "xcin.vb", visual_bell);
    wildmode = (char)
        ResourceValueInt(xd, "xcin.wild", wildmode);
    xcin_length =
        ResourceValueInt(xd, "xcin.len", xcin_length);
/*
    phrfname =
        ResourceValueStr(xd, "xcin.phrase", phrfname);
*/
}


Generated by  Doxygen 1.6.0   Back to index