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

xcin_chewing.c

/*
 $Id: xcin_chewing.c,v 1.3 2001/12/07 03:55:40 gugod Exp $
 this file is the interface between chewing and xcin
*/

/* 2001/12/7 ,gugod
  config.h is generated by xcin configure script.  which contain
  several important constant need by xcin internal structure.  (in
  module.h) These 3 lines is commonly used in other module.(see
  gen_inp.c and zh_hex.c in xcin)
 */
#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include "hash.h"
#include "global.h"
#include "chewingio.h"
#include "module.h"
#include "char.h"
#include "dict.h"
#include <X11/keysym.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

// the following keystate masks are defined by xcin
#define SHIFT_MASK (1)
#define CAPS_MASK (2)
#define CTRL_MASK (4)

#ifdef DEBUG
FILE *fp_g ;
#endif

int lifetime ;

int MakeInpinfo(inpinfo_t *inpinfo, ChewingOutput *pgo) ;
void Live()
{
  static time_t nowtime, lasttime = 0 ;

  nowtime = time(NULL) ;
  if(lasttime != 0) 
    lifetime += (nowtime - lasttime) ;
  lasttime = nowtime ;
}

void wch_to_str(wch_t *wchstr,int nWch,char *str)
{
  int i;

  str[0] = '\0';
  for(i=0;i<nWch;i++) {
    strcat( str, wchstr[i].s);
  }
}

int CallSetConfig(inpinfo_t *inpinfo, ChewingData *pgdata)
{
  ConfigData config ;
  int i ;

  config.selectAreaLen = inpinfo->xcin_wlen ;
  if (config.selectAreaLen == 0)
    config.selectAreaLen = 80 ;
  config.maxChiSymbolLen = 22 ;
  for(i=0; i<9; i++)
    config.selKey[i] = i + '1' ;
  config.selKey[9] = '0' ;
  SetConfig(pgdata, &config) ;
  return 0 ;
}

static int
ChewingInit(void *conf, char *objname, xcin_rc_t *xc)
{
  char *cmd[2], data_prefix[256], kb_type_str[256], truefilename[256], *p ;
  char sub_path[256];
  ChewingConf *cf = (ChewingConf *)conf ;

#ifdef DEBUG
  fp_g = fopen("debug.txt", "w") ;
#endif

  /* 2001/12/6 , gugod.
     Original code ,fp=open(..,"r"), to test if file exists, is now
     replaced by new xcin api : check_datafile.  open_file() is now
     open_data().  See new xcintools.h for detail.
  */
  snprintf(sub_path,256,"tab/");
  if (check_datafile("fonetree.dat", sub_path, xc, truefilename, 256) == True) {
    strncpy(data_prefix, truefilename, 256) ;
    // We only take the data_prefix path
    p = strrchr(data_prefix, '/') ;
    if(p) *p = '\0' ;
  }
  else {
    return False;
  }

  cmd[0] = objname ;
  cmd[1] = "KB_TYPE" ;
  kb_type_str[0] = '\0' ;

  /* 2001.12.6 , gugod
     xcin api change.
   */
  get_resource(xc,cmd,kb_type_str,200,2);

  cf->kb_type = KBStr2Num(kb_type_str) ;

  cf->inp_cname = strdup("ŭ") ; 
  cf->inp_ename = strdup("Chewing") ;
  ReadTree(data_prefix) ;
  InitChar(data_prefix) ;
  InitDict(data_prefix) ;
  ReadHash() ;
  Live() ;
  return True ;
}

static int 
ChewingXimInit(void *conf, inpinfo_t *inpinfo)
{
  static char cchBuffer[MAX_PHONE_SEQ_LEN] ;
  ChewingConf *cf = (ChewingConf *)conf ;
  int i;

  inpinfo->iccf = calloc(1, sizeof(ChewingData)) ;
  
  InitChewing(inpinfo->iccf, cf) ;
  CallSetConfig(inpinfo, inpinfo->iccf) ;

  inpinfo->lcch = calloc(MAX_PHONE_SEQ_LEN, sizeof(wch_t)) ;
  inpinfo->lcch_grouping = calloc(MAX_PHONE_SEQ_LEN, sizeof(ubyte_t) );
  inpinfo->cch = cchBuffer ; // 2000.6.30

  inpinfo->inp_cname = cf->inp_cname;
  inpinfo->inp_ename = cf->inp_ename;
  inpinfo->area3_len = 2 * ZUIN_SIZE + 4;
  inpinfo->guimode = GUIMOD_LISTCHAR | GUIMOD_SELKEYSPOT;
  inpinfo->keystroke_len = 0;
  inpinfo->s_keystroke = calloc(3 + MAX_PHRASE_LEN, sizeof(wch_t)) ;

  inpinfo->mcch = calloc( MAX_CHOICE_BUF, sizeof(wch_t) );
  inpinfo->mcch_grouping = calloc( MAX_SELKEY, sizeof(ubyte_t) );
  inpinfo->n_mcch = 0;

  inpinfo->n_lcch = 0;
  inpinfo->edit_pos = 0;
  inpinfo->cch_publish.wch = (wchar_t)0;

  //  check_winsize(inpinfo, iccf);
  //  [yet] check winsize is under construction.

  inpinfo->n_selkey = 10;
  inpinfo->s_selkey = calloc( MAX_SELKEY, sizeof(wch_t) );

  for (i=0; i<9; i++) {
    inpinfo->s_selkey[i].wch  = (wchar_t)0;
    inpinfo->s_selkey[i].s[0] = i + '1';
  }
  inpinfo->s_selkey[9].wch  = (wchar_t)0;
  inpinfo->s_selkey[9].s[0] = '0';

  return True ;
}

void CommitString(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  int i ;

  memset(inpinfo->cch, 0, sizeof(wch_t)*MAX_PHONE_SEQ_LEN) ;
  for(i=0; i<pgo->nCommitStr; i++)
    strcat(inpinfo->cch, pgo->commitStr[i].s) ;
}

static unsigned int 
ChewingXimEnd(void *conf, inpinfo_t *inpinfo)
{
  ChewingOutput gOut ;
  int rtn ;

  // for debug 99/9/16
#ifdef DEBUG
  fprintf(fp_g, "XimEnd !\n") ;
  fflush(fp_g) ;
#endif
  // Commit String 2000.6.30
  OnKeyEnter(inpinfo->iccf, &gOut) ;
  rtn = MakeInpinfo(inpinfo, &gOut) ;
  free(inpinfo->iccf);
  free(inpinfo->s_keystroke);
  free(inpinfo->lcch);
  free(inpinfo->mcch);
  free(inpinfo->mcch_grouping);

  inpinfo->iccf = NULL;
  inpinfo->s_keystroke = NULL;
  inpinfo->lcch = NULL;

    // under construction
  return rtn ;
}      

void ShowChoose(inpinfo_t *inpinfo, ChoiceInfo *pci, ChewingOutput *pgo)
{
  int i,no,k,len;
  
  // for new xcin, there is no need to modify the lcch buffer
  // instead, we put phrase to choose in mcch
  no = pci->pageNo * pci->nChoicePerPage;
  len = 0;

  for(i=0;i<pci->nChoicePerPage; no++,i++) {

    // in the last page, no will exceed nTotalChoice
    if( no >= pci->nTotalChoice ) 
      break;
    // for each char in the phrase, copy to mcch
    for(k=0; pci->totalChoiceStr[no][k]!='\0'; k+=2) 
      memcpy(inpinfo->mcch[len++].s, &(pci->totalChoiceStr[no][k]), 2) ;
    // set grouping to the length of the phrase
    inpinfo->mcch_grouping[i+1] = k/2;
  }
  // i stores how many choices are available
  inpinfo->mcch_grouping[0] = i;

  // set pgstate according to pci->pageNo & pci->nPage
  if( pci->nPage == 1) {
    inpinfo->mcch_pgstate = MCCH_ONEPG;
  }
  else {
    if( pci->pageNo == 0 )
      inpinfo->mcch_pgstate = MCCH_BEGIN;
    else if( pci->pageNo == pci->nPage - 1)
      inpinfo->mcch_pgstate = MCCH_END;
    else
      inpinfo->mcch_pgstate = MCCH_MIDDLE;
  }

  inpinfo->n_mcch = len ;
}

void ShowText(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  memset(inpinfo->lcch, 0, sizeof(wch_t)*MAX_PHONE_SEQ_LEN) ;
  memcpy(inpinfo->lcch, pgo->chiSymbolBuf, sizeof(wch_t) * pgo->chiSymbolBufLen) ;
  inpinfo->n_lcch = pgo->chiSymbolBufLen ;
}

void ShowInterval(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  int i, k, begin, len, count, nGroup ;
  int label[MAX_PHONE_SEQ_LEN] ;

  if( pgo->chiSymbolBufLen == 0) {
    inpinfo->lcch_grouping[0] = 0 ;
    return ;
  }

  // set label
  for(count=0; count<pgo->chiSymbolBufLen; count++)
    label[count] = count ;

  for(i=0; i<pgo->nDispInterval; i++) {
    len = pgo->dispInterval[i].to - pgo->dispInterval[i].from ;

    if( len > 1) {
      for(k=pgo->dispInterval[i].from; k<pgo->dispInterval[i].to; k++)
      label[k] = count ;
      count++ ;
    }
  }

  // begin to set lcch_grouping by the label
  nGroup = 0 ;
  begin = 0 ;
  for(i=1; i<pgo->chiSymbolBufLen; i++) {
    if( label[i] != label[begin] ) {
      inpinfo->lcch_grouping[++nGroup] = ( i - begin ) ;
      begin = i ;
    }
  }
  inpinfo->lcch_grouping[++nGroup] = ( i - begin ) ;
  inpinfo->lcch_grouping[0] = nGroup ;
}

void ShowStateAndZuin(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  int i, a , len = 0;

  memset( inpinfo->s_keystroke, 0, sizeof(wch_t)*(3 + MAX_PHRASE_LEN)) ;
  if(pgo->bShowMsg) {
    memcpy( inpinfo->s_keystroke, pgo->showMsg, sizeof(wch_t)*pgo->showMsgLen) ;
    inpinfo->keystroke_len = pgo->showMsgLen ;
  }
  else {
    if(pgo->bChiSym)
      strcpy( inpinfo->s_keystroke[0].s, "") ;
    else
      strcpy( inpinfo->s_keystroke[0].s, "^") ;
    
    inpinfo->s_keystroke[1].s[0] = ' ' ;
    for(i=0,a=2; i<ZUIN_SIZE; i++) 
      if(pgo->zuinBuf[i].s[0] != '\0') {
      inpinfo->s_keystroke[a++].wch = pgo->zuinBuf[i].wch ;
        ++ len;
      }
    inpinfo->keystroke_len = len;
  }
}

void SetCursor(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  inpinfo->edit_pos = pgo->chiSymbolCursor;
}

int MakeInpinfo(inpinfo_t *inpinfo, ChewingOutput *pgo)
{
  int rtnValue = 0 ;

  if(pgo->keystrokeRtn & KEYSTROKE_ABSORB)
    rtnValue |= IMKEY_ABSORB ;
  if(pgo->keystrokeRtn & KEYSTROKE_IGNORE)
    rtnValue |= IMKEY_IGNORE ;
  if(pgo->keystrokeRtn & KEYSTROKE_BELL)
    rtnValue |= IMKEY_BELL ;
  if(pgo->keystrokeRtn & KEYSTROKE_COMMIT) {
    rtnValue |= IMKEY_COMMIT ;
    CommitString(inpinfo, pgo) ;
  }

  if(pgo->pci->nPage != 0) { // in selection mode
    ShowChoose(inpinfo,pgo->pci,pgo) ;
    inpinfo->guimode &= ~GUIMOD_LISTCHAR; 
  }
  else { // not in selection mode
    ShowText(inpinfo, pgo) ;
    ShowInterval(inpinfo, pgo) ; // kpchen 2000.2.9
    inpinfo->guimode |= GUIMOD_LISTCHAR;
  }
  ShowStateAndZuin(inpinfo, pgo) ;
  SetCursor(inpinfo, pgo) ;
  return rtnValue ;
}

static unsigned int
ChewingKeystroke(void *conf, inpinfo_t *inpinfo, keyinfo_t *keyinfo)
{
  KeySym keysym = keyinfo->keysym;
  ChewingOutput gOut ;
  int rtn ;
  static KeySym last_key = 0;

  Live() ;

  // set Chinese / English mode by keystate
  if( keyinfo->keystate & CAPS_MASK ) { // uppercase
    SetChiEngMode( inpinfo->iccf, SYMBOL_MODE);
  }
  else {  // lower case 
    SetChiEngMode( inpinfo->iccf, CHINESE_MODE);
  }
#ifdef DEBUG
      fprintf(fp_g,"ChewingKeystoke\n\t\tkeystate=%d,keysym=%ld\n", keyinfo->keystate, keysym);
#endif

  // by lckung 2001.10.23
  // change case if capslock is on
  if( GetChiEngMode( inpinfo->iccf) == SYMBOL_MODE) {
      if( isupper(keysym) && !(keyinfo->keystate & SHIFT_MASK) )
            keysym = tolower(keysym);
  }

#ifdef DEBUG
      fprintf(fp_g,"Aft ChewingKeystoke\n\t\tkeystate=%d,keysym=%ld\n", keyinfo->keystate, keysym);
#endif

  // check no ctrl key was pressed
  if(keyinfo->keystate >= 0 && !(keyinfo->keystate & CTRL_MASK) ) {
    switch(keysym) {
    case XK_Escape:
      OnKeyEsc(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Return:
      OnKeyEnter(inpinfo->iccf, &gOut) ;
      inpinfo->n_mcch = 0;
      break ;
    case XK_Delete:
      OnKeyDel(inpinfo->iccf, &gOut) ;
      break ;
    case XK_BackSpace:
      OnKeyBackspace(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Up:
      OnKeyUp(inpinfo->iccf, &gOut);
      break ;
    case XK_Down:
      OnKeyDown(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Left:
      OnKeyLeft(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Right:
      OnKeyRight(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Home:
      OnKeyHome(inpinfo->iccf, &gOut);
      break;
    case XK_End:
      OnKeyEnd(inpinfo->iccf, &gOut);
      break;

    case XK_Tab:
      if( last_key == XK_Tab) // double click TAB
      OnKeyDblTab(inpinfo->iccf, &gOut);
      else
      OnKeyTab(inpinfo->iccf, &gOut) ;
      break ;
    case XK_Caps_Lock:
      OnKeyCapslock(inpinfo->iccf, &gOut) ;
      break ;
    default:
      OnKeyDefault(inpinfo->iccf,keysym,&gOut ) ;
      break ;
    }
  }
  
  else if(keyinfo->keystate & CTRL_MASK) {  // Ctrl-key Mask
  // We need to fill the 'gOut' variable for output.
    if(keysym <= '9' && keysym >= '0') 
      OnKeyCtrlNum(inpinfo->iccf,keysym,&gOut) ;    
    else
      OnKeyCtrlDefault(inpinfo->iccf,&gOut) ;
  }


  last_key = keysym;
  rtn = MakeInpinfo(inpinfo, &gOut) ;
  return rtn ;
}

static int 
ChewingShowKeystroke(void *conf, simdinfo_t *simdinfo)
{
  simdinfo->s_keystroke = NULL;
  return False;
}                              

static char zh_chewing_comments[] = 
"This is a very smart phonetic input method module.\n"
"By Lu-chuan Kung <lckung@iis.sinica.edu.tw> and\n"
"And Kang-pen Chen <kpchen@iis.sinica.edu.tw>.\n";

static char *zh_chewing_valid_objname[] = { "chewing", NULL };
     
module_t module_ptr = {
  { MTYPE_IM,                             /* module_type */
    "zh_chewing",                   /* name */
    MODULE_VERSION,                       /* version */
    zh_chewing_comments },                /* comments */
  zh_chewing_valid_objname,               /* valid_objname */
  sizeof(ChewingConf),                    /* conf_size */
  ChewingInit,                            /* init */
  ChewingXimInit,                   /* xim_init */
  ChewingXimEnd,                    /* xim_end */
  ChewingKeystroke,                       /* keystroke */
  ChewingShowKeystroke,                   /* show_keystroke */
  NULL
};

Generated by  Doxygen 1.6.0   Back to index