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

rkc.c

/* Copyright 1992 NEC Corporation, Tokyo, Japan.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of NEC
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission.  NEC Corporation makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 
 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 
 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
 * PERFORMANCE OF THIS SOFTWARE. 
 */

#if !defined(lint) && !defined(__CODECENTER__)
static char rcs_id[] = "$Id: rkc.c,v 1.12 2003/09/24 15:01:07 aida_s Exp $";
#endif

/*
 * MODIFICATION HISTORY
 *    S000  funahasi@oa2      Fri Oct  2 20:14:13 JST 1992
 *          - debug用関数 RkThrough()のために protocolを追加
 *    S001  funahasi@oa2      Tue Oct 13 15:40:08 JST 1992
 *          - version2.x以前のサーバに接続している時 RkQueryDic()が -1
 *            を返すよう仕様を変更
 *    S002  funahasi@oa2      Thu Nov  5 13:22:49 JST 1992
 *          - RkQueryDic()の引き数に user名を指定出来るよう仕様を変更
 *          - fixed bug RkBgnBun()で旧サーバに接続している場合,modeから
 *            コード変換部分だけを取り出す処理を修正
 *    S003  funahasi@oa2      Fri Nov 13 01:19:52 JST 1992
 *          - fixed bug version1.1のサーバに接続出来ない
 *            rkc_get_yomi()を行っているのが原因
 *          - RkwSetAppName()が無かったので追加
 *          - fixed bug version2.1のサーバに接続出来ない
 *            rkc_set_app_name()を行っているのが原因
 *    S004  funahasi@oa2      Fri Dec  4 02:04:38 JST 1992
 *          - cannastat, cshosのために rkcの内部関数を呼び出す
 *            インタフェースを追加
 *    S005  funahasi@oa2      Thu Feb 18 12:18:41 JST 1993
 *          - fixed bug Rk[w]GetKanjiList()が仕様と異なっている.
 */

/* LINTLIBRARY */

#include    "sglobal.h" 
#include    "rkcw.h"
#include    "canna/RK.h"
#include    "rkc.h"
#include "conf.h"
#include "RKindep/ecfuncs.h"

#include    <sys/types.h>
#include    <pwd.h>
#include    <grp.h>
#include    <signal.h>
#include    <unistd.h>
      
/* CX:      コンテクストテーブル
 *    必要なレコードだけをmallocで作成する。
 *    ^^^^^^^^^^^^^^^^^^
 */

/*********************************************************************
 *                      wchar_t replace begin                        *
 *********************************************************************/
#ifdef wchar_t
# error "wchar_t is already defined"
#endif
#define wchar_t cannawc

static RkcContext *RkcCX[MAX_CX] ;

#define RkcFree free
#define BUSY      1

#define AUTO_YOMI_SIZE  512

static short
rkc_call_flag = 0x00   ; /* RkInitializeが呼ばれてRkFinalizeが呼ばれるまで */
                   /* BUSYビットが立っている                   */

static short ProtocolMinor = 0 ;
static short ProtocolMajor = 0;
static int ServerFD = 0;                              /* S004 */

extern struct rkcproto wideproto;
#ifdef USE_EUC_PROTOCOL
extern struct rkcproto eucproto;
static struct rkcproto *RKCP = &eucproto;
#else /* !USE_EUC_PROTOCOL */
static struct rkcproto *RKCP = &wideproto;
#endif /* !USE_EUC_PROTOCOL */

static short PROTOCOL = 0 ;

static char ConnectIrohaServerName[ MAX_HOSTNAME + 1 ];
static char *ServerNameSpecified;
static RkcConfigErrorProc config_error_handler;

/*
 * サポートするプロトコルのリスト
 * この順にプロトコルを使用し,サーバに接続しようとする
 */
static char *ProtoVerTbl[] = {
    W_VERSION,/* サーバと同じメジャー番号の時は、サーバの
                                    バージョンのプロトコルを使っている。*/
    "2.1",    /* サーバよりメジャー番号が小さい時は、
              小さい方のプロトコルを使う。(ここはマクロにした方がよいね)*/ 
#ifdef USE_EUC_PROTOCOL
    E_VERSION,    /* ver1.2 */
    "1.0",
#endif
    "",
};

static struct {
  Ushort cbuf[CBUFSIZE];
  char buffer[BUFSIZE];
  wchar_t wbuf[CBUFSIZE];
} rkc; /* general buffer。ただし、RkwXXX のなかだけで使うことにしよう。*/

/*
 * クライアント・コンテクストユーティリティ関数
 */


/*
 * 新しいコンテクストを作成する。
 */
static
RkcContext  *
newCC()
{
    register RkcContext *cx ;
    register int i ;

    for( i = 0; i < MAX_CX; i++) {
      if( !RkcCX[ i ] ) {
          cx = (RkcContext *)malloc( sizeof( RkcContext ) ) ;
          if( cx ) {
            cx->client = i ;
            cx->bun = (RkcBun *)NULL ;
            cx->Fkouho = (Ushort *)NULL ;
            cx->lastyomi = (Ushort *)NULL ;
            cx->curbun = cx->maxbun = cx->bgnflag = cx->maxyomi = 0 ;
            RkcCX[ i ] = cx ;
          }
          return( cx ) ;
      }
    }
    return( (RkcContext *)NULL ) ;
}

/*
 * 指定された文節から最終文節までの先頭候補または、候補列の領域を解放する
 */
static
void
freeBUN(cx, from)
register RkcContext *cx ;
register int          from ;
{
    register RkcBun *bun ;

    for( ; from < cx->maxbun; from++ ) {
      bun = &cx->bun[ from ] ;
      if( bun->flags == NUMBER_KOUHO ) {
          /* 第一候補しか入っていない文節は、実際にはmallocしたわけではなく
           * サーバから通知された各文節の第一候補列の中へのポインタを
           * 設定しているだけだからフリーしない。
           */
          RkcFree( (char *)bun->kanji ) ;
          bun->kanji = (Ushort *)NULL ;
          bun->curcand = bun->maxcand = 0 ;
          bun->flags = NOTHING_KOUHO ;
      }
    }
}

/*
 * 指定されたコンテクストを解放する。
 */
static
void
freeCC( clientcx )
int clientcx ;
{
    register RkcContext     *cx ;

    if( (0 <= clientcx) && (clientcx < MAX_CX) ) {
      cx = RkcCX[ clientcx ] ;
      if( cx->bun ) {
          freeBUN( cx, 0 ) ;
          RkcFree( (char *)cx->bun ) ;
          cx->bun = (RkcBun *)NULL ;
      }
      RkcFree( (char *)cx->Fkouho ) ;
      cx->Fkouho = (Ushort *)NULL ;
      RkcFree( (char *)cx->lastyomi );
      cx->lastyomi = (Ushort *)NULL;
      cx->curbun = cx->maxbun = 0 ;
      cx->bgnflag = 0 ;
      RkcFree( (char *)cx ) ;
      cx = (RkcContext *)NULL ;
      RkcCX[ clientcx ] = (RkcContext *)NULL ;
    }
}

/*
 * コンテクスト番号に対応したコンテクストを取得する。
 * (クライアント側)
 */
#define NOCHECK    0
#define CHECK        1
static
RkcContext *
getCC( clientcx, type )
int   clientcx, type ;
{
    register RkcContext     *cx = (RkcContext *)NULL ;

    if( (0 <= clientcx) && (clientcx < MAX_CX) ) {
        cx = RkcCX[clientcx];
      if (cx)
          if( (type == CHECK) && (cx->bgnflag != BUSY) )
            /* 変換中の時,maxbunは最低1である */
            cx = (RkcContext *)NULL ;
    }
    return( cx ) ;
}

int RkwSetUserInfo pro((char *, char *, char *));

static RkUserInfo *uinfo;

int
RkwSetUserInfo(user, group, topdir)
char *user, *group, *topdir;
{
  if (user && group && topdir) {
    uinfo = (RkUserInfo *)malloc(sizeof(RkUserInfo));
    if (uinfo) {
      uinfo->uname = user;
      uinfo->gname = group;
      uinfo->topdir = topdir;
      return 1;
    }
  }
  return 0;
}

static char *
FindLogname()
{
  if (uinfo)
    return uinfo->uname;
  else {
    char *username = NULL, *getenv(), *getlogin();
  
    struct passwd *pass = getpwuid(getuid());
    if( pass )
    username = pass->pw_name;
    if (username == NULL){
      if ( (username = getlogin()) == NULL ) {  
        if( (username = getenv( "LOGNAME" )) == NULL ) {
          username = getenv( "USER" );
        }
      }
    }
    return( username );
  }
  return (char *)NULL;
}

static char *
FindGroupname()
{
  if (uinfo)
    return uinfo->gname;
  else {
    struct group *gr = getgrgid(getgid()) ;
    if (gr && gr->gr_name) {
      return gr->gr_name;
    } 
    else{
      return (char *)NULL;
    }
  }
  return (char *)NULL;
}
/*
 *  RkwInitialize ()
 *
 *  Description:
 *  -----------
 *  かな漢字変換の初期化
 *
 *  Returns:
 *  -------
 *  0 or -1
 */
int
RkwInitialize( hostname ) /* とりあえずrkcの場合は、引き数を無視する */
char *hostname ;
{
    register int    i;
    register long  server ;
    register RkcContext *cx ;
    char *username, *data ;

    if( rkc_call_flag == BUSY )
            return( 0 );      

    rkc_configure();
    if (config_error_handler)
      (*config_error_handler)(RkcErrorBuf_get(&rkc_errors));
    if (ServerNameSpecified) {
        free(ServerNameSpecified);
      ServerNameSpecified = (char *)0;
    }
    ConnectIrohaServerName[0] = '\0';
    if( hostname && (unsigned)strlen(hostname) > 0 &&
#ifdef __EMX__
          !_fnisabs( hostname ) &&
#else
          hostname[0] != '/' &&
#endif
       (ServerNameSpecified = malloc(strlen(hostname) + 1))) {
        strcpy(ServerNameSpecified, hostname);
    }

    if( (ServerFD = rkc_Connect_Iroha_Server( ConnectIrohaServerName )) < 0 ) { /* S004 */
      errno = EPIPE ;
        goto init_err;
    }

    /* ユーザ名を取得する */
    username = FindLogname() ;

    if( !username || !(data = malloc( strlen(username) + strlen(W_VERSION)+2 )))
          goto init_err;

    /* コンテクストを初期化する */
    for( i=0; i < MAX_CX; i++)
      RkcCX[ i ] = (RkcContext *)NULL ;

    /* コンテクストを作成する */
    if( (cx = newCC()) == (RkcContext *)NULL ) {
        RkcFree(data);
        goto init_err;
    }

    /* 最初はワイドキャラベースのプロトコルを使用する */
    for( i = 0; *ProtoVerTbl[i]; i++ ){
      strcpy( data, ProtoVerTbl[i] );
      strcat( data, ":" );
      strcat( data, username );
      ProtocolMajor = *ProtoVerTbl[i] - '0'; /* Majorが1桁たけ対応 */
        PROTOCOL = (ProtocolMajor > 1);

#ifdef USE_EUC_PROTOCOL
      RKCP = PROTOCOL > 0 ? &wideproto : &eucproto;
#endif

        /* サーバに初期化を要求し、サーバのコンテクストを取得する */
      if ((server = (*RKCP->initialize)( data )) < 0) {
          /* 既にコンテクストを確保しているので、それを解放する */
          if( (ServerFD = rkc_Connect_Iroha_Server( ConnectIrohaServerName )) < 0 ) { /* S004 */
            freeCC( cx->client ) ;
            RkcFree(data);
            errno = EPIPE ;
            goto init_err;
          }
          continue;
      }
      break;
    }
    RkcFree(data);

    if (!*ProtoVerTbl[i]) {
      freeCC(cx->client);
      errno = EPIPE;
      (void)close(ServerFD);
      goto init_err;
    }

    /* サーバのマイナーバージョンを得る */
    ProtocolMinor = 
      (short)((unsigned long)(server & 0xffff0000) >> (unsigned)0x10);

    /* サーバから取得したコンテクスト番号を入れる */
    cx->server = server & 0x0000ffff ;
    rkc_call_flag = BUSY ;

    /* プロトコルバージョンが 3.2 以上だったらグループ名を通知する */
    if (canna_version(ProtocolMajor, ProtocolMinor) > canna_version(3, 1)) {
      char *gname = FindGroupname();

      if (gname) {
      (*RKCP->notice_group_name)(cx, gname);
      }
    }
    return( cx->client ) ;
 init_err:
    rkc_config_fin();
    return -1;
}

/*
 *  RkwFinalize ()
 *
 *  Description:
 *  -----------
 *  かな漢字変換の終了
 */
void
RkwFinalize()
{
    register int i ;

    if( rkc_call_flag != BUSY )
            return;

    /* 全コンテクストを解放する
     *          変換中のコンテクストはどうするのか ?
     */
    for( i = 0; i < MAX_CX; i++ ){
      if( RkcCX[ i ] ) {
          freeCC( i ) ;
      }
    } 

    (*RKCP->finalize)();

    ProtocolMinor = 0 ;
    rkc_call_flag = 0 ;
    ProtocolMajor = 0;
    if (ServerNameSpecified) {
      free(ServerNameSpecified);
      ServerNameSpecified = (char *)0;
    }
    ConnectIrohaServerName[0] = '\0';

    if (uinfo) {
      free((char *)uinfo);
    }
    rkc_config_fin();
}

/*
 *  RkwCloseContext ()
 *
 *  Description:
 *  -----------
 *  コンテクストの開放
 *
 *  Input:
 *  -----
 *  cxnum
 *
 *  Returns:
 *  -------
 *  0 or -1
 */
int
RkwCloseContext(cxnum)
int cxnum ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx || (rkc_call_flag != BUSY) )
      return( -1 ) ;

    if ((*RKCP->close_context)(cx) == -1)
      return( -1 ) ;

    freeCC( cxnum ) ;
    return( 0 );
}
/* 
 * KillServer 
 *
 * Version 3.3 以前のサーバには送らない 戻り値 OLDSRV = -110
 * Version 3.3 のサーバには送る 
 *
 */
int
RkwKillServer()
{
/*
  Protocol Version 3.3 からサポート。それ以前のサーバへは送ってはいけない。
*/

  if (canna_version(ProtocolMajor, ProtocolMinor) > canna_version(3, 2)) {
    return (*RKCP->killserver)();
  }
  return OLDSRV;

/* Protocol Version 3.3 */

}

/*
 *  RkwCreateContext ()
 *
 *  Description:
 *  -----------
 *  新しいコンテクストの作成
 *
 *  Returns:
 *  -------
 *  コンテクスト番号 or -1
 */
int
RkwCreateContext()
{
    register int    server ;
    register RkcContext *cx ;

    if( rkc_call_flag != BUSY )
      return( -1 ) ;

    /* コンテクストを作成する */
    if( (cx = newCC()) == (RkcContext *)NULL )
      return( -1 ) ;

    if ((server = (*RKCP->create_context)()) == -1) {
      /* 既にコンテクストを確保しているので、それを解放する */
      freeCC( cx->client ) ;
      return( -1 ) ;
    }

    cx->server = server ;
    return( cx->client ) ;
}

/*
 *  RkwCreateContext ()
 *
 *  Description:
 *  -----------
 *  新しいコンテクストの作成
 *
 *  Input:
 *  -----
 *  src_cx
 *
 *  Returns:
 *  -------
 *  コンテクスト番号 or -1
 */
int
RkwDuplicateContext( src_cx )
int src_cx ;
{
    register RkcContext *cx_dest, *cx_src = getCC( src_cx, NOCHECK ) ;
    register int  dest_cx ;

    if( !cx_src || (rkc_call_flag != BUSY) )
      return( -1 ) ;

    /* コンテクストを作成する */
    if( (cx_dest = newCC()) == (RkcContext *)NULL )
      return( -1 ) ;

    if ((dest_cx = (*RKCP->duplicate_context)(cx_src)) == -1) {
      /* 既にコンテクストを確保しているので、それを解放する */
      freeCC( cx_dest->client ) ;
      return( -1 ) ;
    }

    cx_dest->server = dest_cx ;
    return( cx_dest->client ) ;
}

/*
 *  RkwGetDicList ()
 *
 *  Description:
 *  -----------
 *  辞書リストに追加できる辞書名の取得
 *
 *  Input:
 *  -----
 *  cxnum
 *
 *  Returns:
 *  -------
 *  辞書名の個数 or -1
 */
int
RkwGetDicList(cxnum, dicnames, max)
int cxnum ;
char *dicnames ;
int max ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx )
      return( -1 ) ;

    if( max <= 0 ) 
      return( 0 ) ;
    else if( !dicnames ) {
      return (*RKCP->dictionary_list)(cx, rkc.buffer, BUFSIZE);
    }
    return (*RKCP->dictionary_list)(cx, dicnames, max);
}

static int
_RkwDefineDic( cxnum, dicname, wordrec )  /* 単語登録 */
int cxnum ;
char *dicname ;
Ushort *wordrec ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx )
      return( -1 ) ;

    return (*RKCP->define_dic)(cx, dicname, wordrec);
}

/*
 *  RkwDefineDic ()
 *
 *  Description:
 *  -----------
 *  単語登録
 *
 *  Input:
 *  -----
 *  cxnum
 *
 *  Returns:
 *  -------
 *  コンテクスト番号 or -1
 */
int
RkwDefineDic(cxnum, dicname, wordrec)
int cxnum;
char *dicname;
wchar_t *wordrec;
{
    if( !dicname || !wordrec )
      return( -1 ) ;

    wchar2ushort(wordrec, wcharstrlen(wordrec), rkc.cbuf, CBUFSIZE);
    return _RkwDefineDic(cxnum, dicname, rkc.cbuf);
}

static int
_RkwDeleteDic( cxnum, dicname, wordrec )    /* 単語削除 */
int cxnum ;
char *dicname ;
Ushort *wordrec ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx )
      return( -1 ) ;

    return (*RKCP->delete_dic)(cx, dicname, wordrec);
}

int
RkwDeleteDic(cxnum, dicname, wordrec)
int cxnum;
char *dicname;
wchar_t *wordrec;
{
  if( !dicname || !wordrec ) return -1;

  wchar2ushort(wordrec, wcharstrlen(wordrec), rkc.cbuf, CBUFSIZE);
  return _RkwDeleteDic(cxnum, dicname, rkc.cbuf);
}

int
RkwMountDic(cxnum, dicname, mode)
int cxnum, mode ;
char *dicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !dicname || !cx )
      return( -1 ) ;

    return (*RKCP->mount_dictionary)(cx, dicname, mode);
}

int
RkwRemountDic(cxnum, dicname, where)
int cxnum, where  ;
char *dicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !dicname || !cx )
      return( -1 ) ;

    return (*RKCP->remount_dictionary)(cx, dicname, where);
}

int
RkwUnmountDic(cxnum, dicname)
int cxnum ;
char *dicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !dicname || !cx )
      return( -1 ) ;

    return (*RKCP->umount_dictionary)(cx, dicname);
}

int
RkwGetMountList(cxnum, dicnames_return, max)
int cxnum, max ;
char *dicnames_return ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx )
      return( -1 ) ;

    if( !dicnames_return ) {
        return (*RKCP->mount_list)(cx, rkc.buffer, BUFSIZE);
    } else if( max <= 0 )
      return( 0 ) ;

    return (*RKCP->mount_list)(cx, dicnames_return, max);
}

int
RkwSetDicPath( cxnum, path ) /* サーチパスを設定 */
int cxnum ;
char *path ;
/* ARGSUSED */
{
    return( 0 ) ;
}

/*
 * StoreFirstKouho
 *    カレント文節から最終文節までの先頭候補を求め、格納する
 */
static void
StoreFirstKouho( cx, bun_max )
register RkcContext *cx ;
int bun_max ;
{
    /* ここは、よく考えないと構造まで変えた意味が無くなるし
     *       後でえらい目に遭うかも知れない
     */
    register      int         i ;
    register      RkcBun            *bun ;
    register      Ushort      *kouhobuf ;

    /* カレント文節から最終文節までの候補を解放する */      
    freeBUN( cx, cx->curbun ) ; 

    /* ここには、rkc_*(rkcConvert.c)で第一候補列が格納されている */
    kouhobuf = cx->Fkouho ;

    /* ゼロ文節から最終文節までの第一候補のポインタを設定する */
    for( i = 0; i < bun_max; i++ ) {
      bun = &cx->bun[ i ] ;
      /* カレント文節までの文節で候補一覧を既に取得している文節は、
       * ポインタの再設定はしない。
       */
      if( bun->flags != NUMBER_KOUHO ) {
          bun->kanji = kouhobuf ;
          bun->curcand = 0 ;        /*  文節0文節1文節2文節3文節4@@ */
          bun->maxcand = 1 ;        /*  ↑       ↑   ↑   ↑     ↑    */
          bun->flags = FIRST_KOUHO ;      /*    bun->kaji         */
      }
      kouhobuf += ushortstrlen( (Ushort *)kouhobuf)+1 ;
    }
    cx->maxbun = bun_max ;
}

/*
 *    連文節変換開始
 */
static int  
_RkwBgnBun(cxnum, yomi, maxyomi, mode)
int cxnum, maxyomi, mode ; 
Ushort *yomi ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;
    int nbun, mask;                             /* S002 */

    if( (maxyomi <= 0) || !cx )
      return( -1 ) ;

    /* RkBgnBunだけは、BUSYフラグが立っていると入ってはいけない */
    if( cx->bgnflag == BUSY )
      return( -1 ) ;

    /* 旧サーバに接続している場合,modeからコード変換部分だけを取り出す */
    if( ProtocolMajor < 3 ){
        int code;

      for( code = mode, mask = 0L; code ; code >>= RK_XFERBITS ){
          if( (code & RK_XFERMASK) == RK_CTRLHENKAN ){
            break;
          }
          mask = (mask << RK_XFERBITS) | RK_XFERMASK;
      }
      mode &= mask;                             /* S002 */
    }

    /* maxyomiの文節数だけアロケートしておく */
    /* これ以上の文節数は存在しないはず */

    cx->curbun = cx->maxbun = 0 ;
    if( yomi != NULL ){
      if( !(cx->bun = (RkcBun *)calloc( maxyomi, sizeof(RkcBun) )) )
          return( -1 ) ;
      cx->lastyomi = (Ushort *)NULL;
      nbun = (*RKCP->convert)(cx, yomi, maxyomi, mode);
      if( nbun <= 0 ) {                   
          RkcFree( (char *)cx->bun ) ;
          cx->bun = (RkcBun *)NULL ;
          return( -1 ) ;
      }
      StoreFirstKouho( cx, nbun ) ;
    } else {
      if( !(cx->bun = (RkcBun *)calloc( AUTO_YOMI_SIZE, sizeof(RkcBun) )) )
          return( -1 ) ;
      if( !(cx->lastyomi = (Ushort *)malloc( CBUFSIZE )) ) {
          RkcFree( (char *)cx->bun );
          cx->bun = (RkcBun *)NULL ;
          return( -1 ) ;
      }

      nbun = (*RKCP->autoconv)(cx, maxyomi, mode);
      if( nbun < 0 ) {                    
          RkcFree( (char *)cx->bun ) ;
          cx->bun = (RkcBun *)NULL ;
          RkcFree( (char *)cx->lastyomi );
          cx->lastyomi = (Ushort *)NULL;
          return( -1 ) ;
      }
      *(cx->lastyomi) = ( Ushort )0;
    }
    cx->bgnflag = BUSY ;
    return( nbun ) ;
}

int
RkwBgnBun(cxnum, yomi, maxyomi, mode)
int cxnum;
wchar_t *yomi;
int maxyomi;
int mode;
{
    int len;

    if (yomi) {
      len = wchar2ushort(yomi, maxyomi, rkc.cbuf, CBUFSIZE);
      return _RkwBgnBun(cxnum, rkc.cbuf, len, mode);
    }
    else {  /* 自動変換開始 */
      return _RkwBgnBun(cxnum, (Ushort *)NULL, maxyomi, mode);
    }
}

int
RkwEndBun( cxnum, mode )
int cxnum, mode ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    int ret ;

    if( cx ) {
      /*
       * rkc_convert_endで学習すべき候補をサーバに知らせる
       */
      if ((ret = (*RKCP->convert_end)(cx, mode )) >= 0) {
          freeBUN( cx, 0 ) ;
          RkcFree( (char *)cx->bun ) ;
          RkcFree( (char *)cx->Fkouho ) ;
          cx->bun = (RkcBun *)NULL ;
          cx->Fkouho = (Ushort *)NULL ;
          cx->curbun = cx->maxbun = 0 ;
          cx->bgnflag = 0 ;

          RkcFree( (char *)cx->lastyomi );
          cx->lastyomi = (Ushort *)NULL;
          cx->maxyomi = 0;
      }
      return( ret ) ;
    }

    return( 0 ) ;
}

/* LoadKouho
 *    必要に応じて全候補を読み出す
 */
static
int
LoadKouho( cx )
register RkcContext      *cx ;
{
    register RkcBun     *bun = &cx->bun[ cx->curbun ] ;
    int           ret ;

    if( bun->flags == FIRST_KOUHO ) {
      /*    候補を全て読み出す。
       *    読み出しに失敗したら、先頭候補しかないふりをする
       */
      if ((ret = (*RKCP->get_kanji_list)(cx)) >= 0) {
          /* 読みだし成功 */
          bun->curcand = 0 ;
          bun->maxcand = ret ;
      } else if( errno == EPIPE )
          return( -1 ) ;

      bun->flags = NUMBER_KOUHO ;
    }
    return( 0 ) ;
}

int
RkwXfer(cxnum, knum)
int cxnum, knum ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    register RkcBun      *bun ;

    if( cx ) {
      bun = &cx->bun[cx->curbun];
      if( LoadKouho( cx ) < 0 )
          return( -1 ) ;
      if ( 0 <= knum && knum < bun->maxcand ) 
          bun->curcand = knum;
      return( bun->curcand );
    }
    return( 0 );
}

int
RkwNfer(cxnum)
int cxnum ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    register RkcBun      *bun ;

    if( cx ) {
      bun = &cx->bun[ cx->curbun ]; 
      if( LoadKouho( cx ) < 0 )
          return( -1 ) ;
      bun->curcand = bun->maxcand - 1; /* 読みは、最後にある(0オリジン) */
      return( bun->curcand ) ;
    }
    return( 0 );
}

int
RkwNext(cxnum)
int cxnum ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    register RkcBun      *bun ;

    if( cx ) {
      bun = &cx->bun[ cx->curbun ]; 
      if( LoadKouho( cx ) < 0 )
          return( -1 ) ;
      if ( ++bun->curcand > bun->maxcand-1 )
          bun->curcand = 0;
      return( bun->curcand ) ;
    }
    return( 0 ) ;
}

int
RkwPrev(cxnum)
int cxnum ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    register RkcBun      *bun ;

    if( cx ) {
      bun = &cx->bun[ cx->curbun ];
      if( LoadKouho( cx ) < 0 )
          return( -1 ) ;
      if ( --bun->curcand < 0 )
          bun->curcand = bun->maxcand-1 ; /* 0オリジン */
      return( bun->curcand ) ;
    }
    return( 0 );
}

static
Ushort *
SeekKouho( bun, to )
register RkcBun     *bun ;
register int          to ;
{
    register int    i ;
    Ushort   *src_yomi ;

    src_yomi = bun->kanji ;
    for( i = 0; i < to; i++ )
      src_yomi += ushortstrlen( (Ushort *)src_yomi ) + 1 ;

    return( src_yomi ) ;
}

static int
_RkwGetKanji( cxnum, kanji, maxkanji )
int cxnum, maxkanji ;
Ushort *kanji ;
{
    RkcContext              *cx = getCC( cxnum, CHECK ) ;
    RkcBun            *bun ;
    register Ushort  *src_kouho ;

    if( cx ){
      bun = &cx->bun[ cx->curbun ] ;
                       /* 読みしかない場合は読みを返す */
      src_kouho = SeekKouho( bun, (bun->maxcand ? bun->curcand : 0) ) ;
      if( ushortstrlen( (Ushort *)src_kouho ) > maxkanji )
          return( 0 ) ;
      ushortstrcpy( kanji, src_kouho );
      return( ushortstrlen( (Ushort *)src_kouho ) ) ;
    }
    return( -1 ) ;
}

int
RkwGetKanji(cxnum, kanji, maxkanji)
int cxnum;
wchar_t *kanji;
int maxkanji;
{
  int len;

    len = _RkwGetKanji(cxnum, rkc.cbuf, CBUFSIZE);
    if (len < 0) {
      return( len );
    }
    else {
      if( !kanji ) {
        return ushort2wchar(rkc.cbuf, len, rkc.wbuf, CBUFSIZE);
      }
      else if (maxkanji <= 0) {
          return( 0 );
      }
      else {
        return ushort2wchar(rkc.cbuf, len, kanji, maxkanji);
      }
    }
}

static int
_RkwGetKanjiList(cxnum, kouho, max)
int cxnum, max ;
Ushort *kouho ;
{
    RkcContext    *cx = getCC( cxnum, CHECK ) ;
    RkcBun  *bun ;
    register Ushort  *dest_kouho, *src_kouho ;
    register int i, len ;
    int total ;

    if( cx ) {
      bun = &cx->bun[ cx->curbun ];
      if( LoadKouho( cx ) < 0 )
          return( -1 ) ;
      if( !bun->kanji )
          return( 0 ) ;
      if( !kouho )
          return( bun->maxcand ? bun->maxcand : 1 ) ;
      /* 候補をコピーする */
      src_kouho = bun->kanji ;
      dest_kouho = kouho ;
      for( total = ushortstrlen( src_kouho ) + 1, i = 0;
          (i < bun->maxcand) && (total < max) ; i++, total += len ) {
          len = ushortstrcpy( dest_kouho, src_kouho ) + 1 ;
          src_kouho += len ;
          dest_kouho += len ;
      }
      *(dest_kouho++) = (Ushort)0 ;
      *(dest_kouho) = (Ushort)0 ;
      return( i ) ;
    }
    return( -1 ) ;
}

int
RkwGetKanjiList(cxnum, kanjis, maxkanjis)
int cxnum;
wchar_t *kanjis;
int maxkanjis;
{
  int nkanji, len, i, j = 0, k = 0;
  int retval;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  Ushort cbuf[CBIGBUFSIZE];
#else
  Ushort *cbuf = GlobalAlloc(GMEM_FIXED, sizeof(Ushort) * CBIGBUFSIZE);
  if (!cbuf) {
    return 0;
  }
#endif

  if( !kanjis ) {
    retval = _RkwGetKanjiList(cxnum, (Ushort *)0, 0);
  }
  else if (maxkanjis <= 0) {
    retval = 0;
  }
  else {
  nkanji = _RkwGetKanjiList(cxnum, cbuf, CBIGBUFSIZE);

  for (i = 0 ; i < nkanji ; i++) {
    len = ushortstrlen(cbuf + j);
    if (k + len > maxkanjis - 2)                      /* S005 */
      break;                                          /* S005 */
    k += ushort2wchar(cbuf + j, len, kanjis + k, maxkanjis);      /* S005 */
    kanjis[k++] = (wchar_t)0;
    j += len + 1;
  }
  kanjis[k] = (wchar_t)0;
  retval = i;
  }
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  GlobalFree((HGLOBAL)cbuf);
#endif
  return retval;
}

int
RkwGoTo(cxnum, bnum)
int cxnum, bnum ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;

    if( cx ){
      if ( 0 <= bnum && bnum < cx->maxbun )
           cx->curbun = bnum;
      return(cx->curbun);
    }
    return( 0 );
}

int
RkwLeft(cxnum)
int cxnum;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;

    if( cx ){
      if ( --cx->curbun < 0 )
           cx->curbun = cx->maxbun-1 ;
      return( cx->curbun );
    }
    return( 0 );
}

int
RkwRight(cxnum)
int cxnum;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;

    if( cx ){
      if ( ++cx->curbun > cx->maxbun-1 )
           cx->curbun = 0;
      return( cx->curbun );
    }
    return( 0 );
}

#define ENLARGE     -1
#define SHORTEN     -2
#define MIN_YOMI     1

#ifdef __STDC__
int _RkwGetYomi(RkcContext *, Ushort *, int);
#else
int _RkwGetYomi();
#endif

static int
RKReSize( cxnum, len )
int cxnum, len ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    int ret;            /* 総文節数 */

    if( cx ) {    
      /* 文節長が変更できるかどうかチェックする */
      register RkcBun *bun = &cx->bun[ cx->curbun ] ;

      /* カレント文節が候補列を既に読み込んでいる場合の処理 */
      if( bun->flags == NUMBER_KOUHO ) {
           /* 文節縮めでカレント読みの長さがMIN_YOMIの場合は何もせずに */
           /* カレント文節数を返す */
          int yomilen = ushortstrlen((Ushort *)SeekKouho( bun,
                               (bun->maxcand ? (bun->maxcand-1) : 0)));

          if( (len == SHORTEN) || (len == MIN_YOMI) ) {
            if( yomilen == MIN_YOMI )
                return( cx->maxbun ) ;
          } else {
            int curbun_save = cx->curbun ;
            int yomi_zan ;

            for( yomi_zan = 0; cx->curbun < cx->maxbun; cx->curbun++ ) {
                int ylen, retval = 0;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
                Ushort tmp_yomi[CBUFSIZE];
#else
                Ushort *tmp_yomi = GlobalAlloc(GMEM_FIXED,
                                       sizeof(Ushort) * CBUFSIZE);
                if (!tmp_yomi) {
                  return -1;
                }
#endif
                ylen = _RkwGetYomi(cx, tmp_yomi, CBUFSIZE);
                if (ylen < 0) {
                  retval = -1;
                }
                else {
                  yomi_zan += ylen ;
                }
#ifdef USE_MALLOC_FOR_BIG_ARRAY
                GlobalFree((HGLOBAL)tmp_yomi);
#endif
                if (retval < 0) {
                  return retval;
                }
            }
            cx->curbun = curbun_save ;
            yomi_zan += cx->maxyomi;
            if( ((len == ENLARGE) && (yomilen + 1 > yomi_zan))
                                          || (yomi_zan < len) )
                return( cx->maxbun ) ;
          }
      }
      /* 〇文節から最終文節まで格納される */    
      if ((ret = (*RKCP->resize)(cx, len)) <= 0) {
          return( -1 ) ;
      }
      StoreFirstKouho( cx, ret ) ;
      if( cx->lastyomi != (Ushort *)NULL ){
          if ((len = (*RKCP->get_last_yomi)(cx, cx->lastyomi, CBUFSIZE))
            < 0) return -1;
          cx->maxyomi = len;
      }
      return( ret ) ;
    }
    return( 0 ) ;
}

int
RkwResize( cxnum, len )
int cxnum, len ;
{
    if( len <= 0 ) {
      register RkcContext  *cx = getCC( cxnum, CHECK ) ;

      if( cx )
          return( cx->maxbun ) ;
      else
          return( 0 ) ;
    }

    return( RKReSize( cxnum, len ) ) ;
}

int
RkwEnlarge( cxnum )  /* 文節伸ばし */
int cxnum ;
{
    return( RKReSize( cxnum, ENLARGE  ) ) ;
}

int
RkwShorten(cxnum)    /* 文節縮め */
int cxnum ;
{
    return( RKReSize( cxnum, SHORTEN ) ) ;
}

static int
_RkwStoreYomi(cxnum, yomi, max)
int cxnum, max ;
Ushort *yomi ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    int ret, len ;

    ret = 0 ;
    if( cx ) {
      if ((ret =  (*RKCP->store_yomi)(cx, yomi, max)) < 0) {
          return( -1 ) ;
      }
      StoreFirstKouho( cx, ret ) ;
      if (!max && cx->curbun && cx->curbun == cx->maxbun)
        cx->curbun--;
      if( cx->lastyomi != (Ushort *)NULL ){
          if ((len = (*RKCP->get_last_yomi)(cx, cx->lastyomi, CBUFSIZE))
            < 0 ) return -1;
          cx->maxyomi = len;
      }
    }
    return( ret ) ;
}

int
RkwStoreYomi(cxnum, yomi, maxyomi)
int cxnum;
wchar_t *yomi;
int maxyomi;
{
  int len;

  if (yomi && maxyomi >= 0) {
    len = RKI_MIN(wcharstrlen(yomi),maxyomi); 
    len = wchar2ushort(yomi, len, rkc.cbuf, CBUFSIZE) + 1;
  } else {
    rkc.cbuf[0] = 0;
    len = 0;
  }
  return _RkwStoreYomi(cxnum, rkc.cbuf, len);
}

int                                             /* S003 */
_RkwGetYomi(cx, yomi, maxyomi)
RkcContext *cx;
int maxyomi;
Ushort      *yomi;
{
    register RkcBun     *bun ;
    Ushort  *src_yomi;
    int len, retval = -1;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
    Ushort  tmp_yomi[CBUFSIZE];
#else
    Ushort *tmp_yomi = GlobalAlloc(GMEM_FIXED, sizeof(Ushort) * CBUFSIZE);
    if (!tmp_yomi) {
      return -1;
    }
#endif

    if( cx ){
      bun = &cx->bun[ cx->curbun ] ;            
      if( !PROTOCOL && (ProtocolMinor == 0) ) {
          /* Ver 1.0 では,取りあえず候補一覧を取ってくる */
          if( LoadKouho( cx ) < 0 )
            retval = -1;
      }
      if( bun->flags == NUMBER_KOUHO ) {
          src_yomi = SeekKouho( bun, (bun->maxcand ? (bun->maxcand-1) : 0) );
      } else {
          if ((*RKCP->get_yomi)(cx, tmp_yomi) < 0)
            retval = -1;
          src_yomi = tmp_yomi;
      }

      if( (len = ushortstrlen( (Ushort *)src_yomi )) > maxyomi )
          retval = 0;

      bcopy( src_yomi, yomi, (len + 1) * sizeof( short ) );
      retval = len;
    }
#ifdef USE_MALLOC_FOR_BIG_ARRAY
    GlobalFree((HGLOBAL)tmp_yomi);
#endif
    return retval;
}

int
RkwGetYomi(cxnum, yomi, maxyomi)
int cxnum;
wchar_t *yomi;
int maxyomi;
{
  int len;

  if ((len = _RkwGetYomi(getCC( cxnum, CHECK ), rkc.cbuf, CBUFSIZE)) < 0) {
    return( len );
  }
  else {
    if( !yomi ) {
      return ushort2wchar(rkc.cbuf, len, rkc.wbuf, CBUFSIZE);
    }
    else if( maxyomi <= 0 )
      return( 0 );

    return ushort2wchar(rkc.cbuf, len, yomi, maxyomi);
  }
}

int
RkwGetLex(cxnum, lex, maxlex)
int cxnum, maxlex ;
RkLex *lex ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    int ret = -1 ;

    if( cx ){
      if (lex == (RkLex *)NULL) {
#ifndef USE_MALLOC_FOR_BIG_ARRAY
      RkLex buf[1024];
#else
      RkLex *buf = (RkLex *)GlobalAlloc(GMEM_FIXED, sizeof(RkLex) * 1024);
      if (!buf) {
        return 0;
      }
#endif
      ret = (*RKCP->get_lex)(cx, 1024, buf); 
#ifdef USE_MALLOC_FOR_BIG_ARRAY
      GlobalFree((HGLOBAL)buf);
#endif
      }
      else if( maxlex <= 0 )
      return( 0 );

      ret = (*RKCP->get_lex)(cx, maxlex, lex);
    }
    return( ret ) ;
}

int
RkwGetStat(cxnum, stat)
int cxnum ;
RkStat *stat ;
{
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;
    int ret ;

    if( cx && stat ){
      ret = (*RKCP->get_stat)(cx, stat);
      if( !PROTOCOL && (ProtocolMinor == 0) ) {
          int p[ 7 ] ;
          register int tmp1, tmp2 ;
          int i ;

          bcopy( stat, p, sizeof( RkStat ) ) ;
          tmp1 = p[ 5 ];
          tmp2 = p[ 6 ] ;
          for( i = 4; i > 1; i-- )
            p[ i + 2 ] = p[ i ] ;
          p[ 2 ] = tmp1 ;
          p[ 3 ] = tmp2 ;
          bcopy( p, stat, sizeof( RkStat ) ) ;
      }
    } else {
      ret = -1 ;
    }

    return( ret ) ;
}

char *
RkwGetServerName()
{
  if (ConnectIrohaServerName[0]) {
    return( ConnectIrohaServerName ) ;
  }
  else {
    return ServerNameSpecified;
  }
}

int
RkwGetProtocolVersion(majorp, minorp)
int *majorp, *minorp;
{
    *majorp = ProtocolMajor;
    *minorp = ProtocolMinor;
    return 0;
}

exp(int)
RkwGetServerVersion(majorp, minorp)
int *majorp, *minorp;
{
    if( !PROTOCOL )
      return( RkwGetProtocolVersion(majorp, minorp) );

    return( rkcw_get_server_info(majorp, minorp) );
}

                                          /* begin:S004 */
int
RkcGetServerFD()
{
    return( ServerFD );
}

int
G070_RkcGetServerFD()
{
    return( ServerFD );
}

int
RkcConnectIrohaServer( servername )
char* servername;
{
    /* XXX:
     * RkcDisconnectIrohaServerに相当するインターフェースが無いので、
     * これはメモリリークを引き起こす。今のところこのAPIは古いcannastatが
     * ver 1.xのサーバと通信する場合にだけ使うので、この問題は無視する
     * ことにする。
     */
    rkc_configure();
    return( rkc_Connect_Iroha_Server( servername ) );
}
                                          /* end:S004 */
int
G069_RkcConnectIrohaServer( servername )
char* servername;
{
    return RkcConnectIrohaServer(servername);
}

void
RkcListenConfigErrors( handler )
RkcConfigErrorProc handler;
{
    config_error_handler = handler;
}

#ifdef EXTENSION
static
CheckRemoteToolProtoVersion(mode)
{
  if (!PROTOCOL && ProtocolMinor < 2) /* protocol version 1.2 */
    return -1;
  else if (canna_version(ProtocolMajor, ProtocolMinor) < canna_version(3, 1) &&
         (mode & (RK_GRP_DIC | RK_SYS_DIC | RK_GRP_DIR | RK_SYS_DIR))) {
    return -1;
  }
  return 0;
}

int
RkwListDic( cxnum, dirname, dicnames_return, size )
int cxnum, size ;
char *dirname, *dicnames_return ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx) {
      return -1;
    }
    if (CheckRemoteToolProtoVersion(0)) {
      return ACCES;
    }

    if( !dirname )
      if( !(dirname = FindLogname()) )
          return( -1 ) ;

    if( !dicnames_return ) {
#ifndef USE_MALLOC_FOR_BIG_ARRAY
      char buffer[ MAXDATA ] ;

      return (*RKCP->list_dictionary)(cx, dirname, buffer, MAXDATA);
#else
      char *buffer = GlobalAlloc(GMEM_FIXED, MAXDATA);
      if (buffer) {
        int retval =
          (*RKCP->list_dictionary)(cx, dirname, buffer, MAXDATA);
        GlobalFree((HGLOBAL)buffer);
        return retval;
      }
      else {
        return 0;
      }
#endif
    }
    else if( size <= 0 )
      return( 0 ) ;

    return (*RKCP->list_dictionary)(cx, dirname, dicnames_return, size);
}

int
RkwCreateDic( cxnum, dicname, mode )
int cxnum, mode ;
char *dicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx || !dicname) {
      return -1;
    }
    if (CheckRemoteToolProtoVersion(mode)) {
      return ACCES;
    }

    return (*RKCP->create_dictionary)(cx, (char *)dicname, mode);
}

exp(int)
RkwRemoveDic( cxnum, dicname, mode )
int cxnum ;
char *dicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx || !dicname) {
      return -1;
    }
    if (CheckRemoteToolProtoVersion(mode)) {
      return ACCES;
    }

    return (*RKCP->remove_dictionary)(cx, dicname, mode);
}

exp(int)
RkwRenameDic( cxnum, dicname, newdicname, mode )
int cxnum, mode ;
char *dicname, *newdicname;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx || !dicname || !newdicname) {
      return -1;
    }
    if (CheckRemoteToolProtoVersion(mode)) {
      return ACCES;
    }

    return (*RKCP->rename_dictionary)(cx, dicname, newdicname, mode);
}

/* CopyDic を 入れる。 */

exp(int)
RkwCopyDic(cxnum, dirname, dicname, newdicname, mode )
int cxnum, mode ;
char *dirname,*dicname, *newdicname ;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx || !dirname || !dicname) {
      return -1;
    }
/*
  Protocol Version 3.2 からサポート。それ以前のサーバへは送ってはいけない。
*/

  if (canna_version(ProtocolMajor, ProtocolMinor) > canna_version(3, 1)) {
    return (*RKCP->copy_dictionary)(cx, dirname, dicname, newdicname, mode);
  }
  return -1;

/* Protocol Version 3.2 */

}

/* ここまで */

static
_RkwGetWordTextDic( cxnum, dirname, dicname, info, infolen )
int cxnum, infolen ;
unsigned char *dirname, *dicname;
Ushort *info;
{
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if (!cx || !dirname || !dicname) {
      return -1;
    }

    if (CheckRemoteToolProtoVersion(0)) {
      return ACCES;
    }

    return (*RKCP->get_text_dictionary)
      (cx, (char *)dirname, (char *)dicname, info, infolen);
}

exp(int)
RkwGetWordTextDic(cxnum, dirname, dicname, info, infolen)
int cxnum, infolen ;
unsigned char *dirname, *dicname;
wchar_t *info;
{
  int len;

  len = _RkwGetWordTextDic(cxnum, dirname, dicname, rkc.cbuf, CBUFSIZE);
  if (len < 0){
    return len;
  }
  else {
    if( !info ) {
      return ushort2wchar(rkc.cbuf, len, rkc.buffer, BUFSIZE);
    }
    else if( infolen <= 0 )
      return 0;

    return ushort2wchar(rkc.cbuf, len, info, infolen);
  }
}

#else
RkwListDic(){}
RkwCreateDic(){}
RkwRemoveDic(){}
RkwRenameDic(){}
RkwGetWordTextDic(){}
#endif /* EXTENSION */

/* 逐次自動変換機能関数                   */
/*                                  */
/* 逐次自動変換機能導入によって追加される関数   */

static int
_RkwSubstYomi( cxnum, ys, ye, yomi, nyomi )
int cxnum, ys, ye, nyomi;
Ushort      *yomi;
{
    register RkcContext *cx = getCC( cxnum, CHECK );
    int len, curbun, nbun = -1, pbun, retval = -1;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
    Ushort cbuf[CBUFSIZE];
#else
    Ushort *cbuf = GlobalAlloc(GMEM_FIXED, sizeof(Ushort) * CBUFSIZE);
    if (!cbuf) {
      return -1;
    }
#endif

    if( cx ){
      len = cx->maxyomi;
      if( ys < 0 || ye < 0 || ye < ys || len < ys || len < ye ) {
        retval = -1;
        goto done;
      }

      nyomi = RKI_MIN( ushortstrlen( yomi ), nyomi);
      curbun = cx->curbun;
      cx->curbun = 0;
      if ((nbun = (*RKCP->subst_yomi)(cx, cx->maxbun, ys, ye, yomi, nyomi))
          < 0) {
          cx->curbun = curbun;
          retval = -1;
          goto done;
      }

      pbun = cx->maxbun;
      cx->maxbun = 0; /* StoreFirstKouho であんまりものを捨てないように */
      StoreFirstKouho(cx, nbun);

      if (nbun != pbun) {
        len = (*RKCP->get_last_yomi)(cx, cx->lastyomi, CBUFSIZE);
        if (len < 0) {
          retval = -1;
          goto done;
        }
      } else {
          len = ys;
          ushortstrncpy( cbuf, &(cx->lastyomi[ye]), (cx->maxyomi - ye) );
          len += ushortstrcpy( &(cx->lastyomi[ys]), yomi );
          len += ushortstrcpy( &(cx->lastyomi[ys + nyomi]), cbuf );
      }
      cx->maxyomi = len;
    }
    retval = nbun;
  done:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
    GlobalFree((HGLOBAL)cbuf);
#endif
    return retval;
}

int
RkwSubstYomi( cxnum, ys, ye, yomi, nyomi )
int cxnum, ys, ye, nyomi;
wchar_t *yomi;
{
  RkcContext *cx = getCC( cxnum, CHECK );
  int len;

  if(cx) {
    len = wchar2ushort(yomi, nyomi, rkc.cbuf, CBUFSIZE);
    return _RkwSubstYomi(cxnum, ys, ye, rkc.cbuf, len);
  }
  return( -1 ) ;
}

int
RkwFlushYomi( cxnum )
int cxnum;
{
    RkcContext *cx = getCC( cxnum, CHECK );
    int curbun, nbun = -1;

    if( cx ){
      curbun = cx->curbun;
      cx->curbun = 0;
      if ((nbun = (*RKCP->flush_yomi)(cx)) < 0) {
          cx->curbun = curbun;
          return( -1 ) ;
      }

      if( nbun != cx->maxbun ) {
          cx->curbun = cx->maxbun;
          StoreFirstKouho( cx, nbun );
          cx->curbun = curbun;
      }

      *(cx->lastyomi) = (Ushort)0;
      cx->maxyomi = 0;
    }
    return( nbun ) ;
}

static int
_RkwGetLastYomi( cxnum, yomi, maxyomi )
int   cxnum, maxyomi;
Ushort      *yomi;
{
    register RkcContext *cx = getCC( cxnum, CHECK );
    int     len = -1;

    if( cx ){
      if( !maxyomi || cx->maxyomi > maxyomi )
          return( 0 );
      len = ushortstrncpy( yomi, cx->lastyomi, cx->maxyomi );
    }
    return( len ) ;
}

int
RkwGetLastYomi( cxnum, yomi, maxyomi )
int cxnum;
wchar_t *yomi;
int maxyomi;
{
  int len;

  len = _RkwGetLastYomi(cxnum, rkc.cbuf, CBUFSIZE);
  if (len < 0) {
    return -1;
  }
  else {
    if( !yomi ) {
      return ushort2wchar(rkc.cbuf, len, rkc.wbuf, CBUFSIZE);
    }
    else if( maxyomi <= 0 )
      return 0;

    return ushort2wchar(rkc.cbuf, len, yomi, maxyomi);
  }
}

/*
 * 先頭文節から指定された文節までの先頭候補または、候補列の領域を解放する
 */
static
void
removeBUN( cx, to )
RkcContext *cx;
register int to;
{
    register RkcBun *bun ;
    register i;

    for( i = 0; i < to; i++ ) {
      bun = &cx->bun[ i ] ;
      if( bun->flags == NUMBER_KOUHO ) {
          /* 第一候補しか入っていない文節は、実際にはmallocしたわけではなく
           * サーバから通知された各文節の第一候補列の中へのポインタを
           * 設定しているだけだからフリーしない。
           */
          RkcFree( (char *)bun->kanji ) ;
          bun->kanji = (Ushort *)NULL ;
          bun->curcand = bun->maxcand = 0 ;
          bun->flags = NOTHING_KOUHO ;
      }
    }
}

int
RkwRemoveBun( cx_num, mode )
int cx_num, mode;
{
    register RkcContext  *cx = getCC( cx_num, CHECK );
    register int cnt, i;
    int ret;

    if( cx ) {
      /*
       * rkcw_remove_bun で学習すべき候補をサーバに知らせる
       */
      if ((ret = (*RKCP->remove_bun)(cx, mode)) < 0)
          return( -1 );

      removeBUN( cx, cx->curbun + 1 );
      for( cnt = 0, i = cx->curbun + 1; i < cx->maxbun; cnt++, i++ ) {
          cx->bun[cnt].kanji = cx->bun[i].kanji;
          cx->bun[cnt].curcand = cx->bun[i].curcand;
          cx->bun[cnt].maxcand = cx->bun[i].maxcand;
          cx->bun[cnt].flags = cx->bun[i].flags;
          cx->bun[i].kanji = (Ushort *)NULL ;
          cx->bun[i].curcand = cx->bun[i].maxcand = 0 ;
          cx->bun[i].flags = NOTHING_KOUHO ;
      }
      cx->curbun = cx->maxbun = 0;
      StoreFirstKouho( cx, ret ) ;
      return( ret ) ;
    }

    return( 0 ) ;
}

static int
_RkwGetSimpleKanji(cxnum, dicname, yomi, maxyomi, kanjis, maxkanjis,
               hinshis, maxhinshis)
unsigned char *dicname;
int cxnum, maxyomi, maxkanjis, maxhinshis;
Ushort *yomi, *kanjis, *hinshis;
{
    RkcContext *cx = getCC( cxnum, CHECK ) ;

    if( cx ){
      return (*RKCP->get_simple_kanji)
        (cx, (char *)dicname, yomi, maxyomi, kanjis,
         maxkanjis, hinshis, maxhinshis);
    }
    return( -1 ) ;
}

int
RkwGetSimpleKanji( cxnum, dicname, yomi, maxyomi, kanjis, maxkanjis, hinshis, maxhinshis )
int cxnum, maxyomi, maxkanjis, maxhinshis ;
wchar_t *yomi, *kanjis, *hinshis;
char *dicname;
{
  Ushort cbuf[CBUFSIZE], cbuf2[CBIGBUFSIZE], cbuf3[CBIGBUFSIZE];
  int nkanji, len, i, j = 0, k = 0, l = 0, m = 0;

  if( !dicname || !yomi || maxyomi <= 0 )
    return( -1 );

  len = wchar2ushort(yomi, maxyomi, cbuf, CBUFSIZE);
  nkanji = _RkwGetSimpleKanji(cxnum, dicname, cbuf, len,
                    cbuf2, CBIGBUFSIZE, cbuf3, CBIGBUFSIZE );

  if( nkanji <= 0 || !kanjis || !hinshis )
    return( nkanji );
  if( maxkanjis <= 0 || maxhinshis <= 0 )
    return( 0 );

  for( i = 0 ; i < nkanji ; i++ ) {
    k += ushort2wchar(cbuf2 + j, ushortstrlen(cbuf2 + j),
               kanjis + k, maxkanjis - k) + 1;
    j += ushortstrlen(cbuf2 + j) + 1;
    l += ushort2euc(cbuf3 + m, ushortstrlen(cbuf3 + m),
               hinshis + l, maxhinshis - l) + 1;
    m += ushortstrlen(cbuf3 + m) + 1;
  }
  kanjis[k] = hinshis[l] = (wchar_t)0;
  return ( nkanji );
}

int
RkwQueryDic( cxnum, username, dicname, status )             /* S002 */
int cxnum;
char *username;                           /* S002 */
char *dicname;
struct DicInfo *status;
{
    RkcContext *cx = getCC( cxnum, NOCHECK );

    if( !cx || !dicname || ProtocolMajor < 3 )
      return( -1 ) ;

    if( !username )
      if( !(username = FindLogname()) )
          return( -1 ) ;

    if( !status ) {
      struct DicInfo buffer; /* ダミー */

      return (*RKCP->query_dic)(cx, username, dicname, &buffer);
    }
    else{
      return (*RKCP->query_dic)(cx, username, dicname, status);
    }
}

static int
_RkwGetHinshi( cxnum, dst, maxdst )
int cxnum, maxdst;
Ushort *dst;
{
    RkcContext *cx = getCC( cxnum, CHECK );

    if( cx ){
      return (*RKCP->get_hinshi)(cx, dst, maxdst);
    }
    return( -1 ) ;
}

int
RkwGetHinshi( cxnum, dst, maxdst )
int cxnum, maxdst;
wchar_t *dst;
{
  int len;

  len = _RkwGetHinshi(cxnum, rkc.cbuf, CBUFSIZE);
  if (len < 0) {
    return -1;
  }
  else {
    if( !dst ) {
      return ushort2wchar(rkc.cbuf, len, rkc.wbuf, CBUFSIZE);
    }
    else if( maxdst <= 0 )
      return 0;

    return ushort2wchar(rkc.cbuf, len, dst, maxdst);
  }
}

static int
_RkwStoreRange( cxnum, yomi, maxyomi )
int cxnum, maxyomi;
Ushort *yomi;
{
    RkcContext *cx = getCC( cxnum, CHECK );

    if( cx ){
      return (*RKCP->store_range)(cx, yomi, maxyomi);
    }
    return( -1 ) ;
}

int
RkwStoreRange( cxnum, yomi, maxyomi )
int cxnum, maxyomi;
wchar_t *yomi;
{
  int len;

  if( !yomi || maxyomi <= 0 )
    return -1;

  len = wchar2ushort(yomi, maxyomi, rkc.cbuf, CBUFSIZE);
  return _RkwStoreRange(cxnum, rkc.cbuf, len);
}

int
RkwSetLocale( cxnum, locale )
int cxnum;
unsigned char *locale;
{
    RkcContext *cx = getCC( cxnum, NOCHECK );

    if( cx ){
      return (*RKCP->set_locale)(cx, (char *)locale);
    }
    return( -1 ) ;
}

/*
 *  RkwSync ()
 *
 *  Description:
 *  -----------
 *  辞書ファイルへの同期処理
 *
 *  Input:
 *  -----
 *  dicname: 辞書名@辞書名@...@@
 *
 *  Returns:
 *  -------
 *  0 or -1
 */

int
RkwSync( cxnum, dicname )
int cxnum;
char *dicname;
{
  RkcContext *cx = getCC( cxnum, NOCHECK );

  if (cx) {
    if (canna_version(ProtocolMajor, ProtocolMinor) > canna_version(3, 1)) {
      return (*RKCP->sync)(cx, dicname ? dicname : "");
    }
  }
  return -1;
}

/*
 *  RkwSetAppName ()
 *
 *  Description:
 *  -----------
 *  アプリケーション名の登録
 *
 *  Input:
 *  -----
 *  apname: アプリケーション名
 *
 *  Returns:
 *  -------
 *  0 or -1
 */

int RkwSetAppName pro((int, char *));

int
RkwSetAppName( cxnum, apname )
int cxnum;
char *apname;
{
    RkcContext *cx = getCC( cxnum, NOCHECK );

    if( cx && (ProtocolMajor > 2) && apname){
      return (*RKCP->set_app_name)(cx, apname);
    }
    return( -1 ) ;
}

int RkSetAppName pro((int, char *));

/*
 *  RkwChmodDic ()
 *
 *  Description:
 *  -----------
 *  辞書のアクセス権の変更
 *
 *  Input:
 *  -----
 *  dicname: 辞書の名前
 *
 *  mode: モード
 *
 *  Returns:
 *  -------
 *  0 or -1
 */
exp(int)
RkwChmodDic(cxnum, dicname, mode)
int cxnum;
char *dicname;
int  mode;
{
  RkcContext *cx = getCC( cxnum, NOCHECK );

  if (cx &&
      canna_version(ProtocolMajor, ProtocolMinor) > canna_version(3, 1)) {
    return (*RKCP->chmod_dic)(cx, dicname, mode);
  }
  return -1;
}

/* EUC functions */

#ifndef OMIT_EUC_FUNCS

int
RkInitialize( hostname )
char *hostname ;
{
    return( RkwInitialize( hostname ) ) ;
}

void
RkFinalize()
{
    RkwFinalize() ;
}

RkKillServer()
{
    return RkwKillServer();
}

int
RkCloseContext( cxnum )
int cxnum ;
{
    return( RkwCloseContext( cxnum ) ) ;
}

int
RkCreateContext()
{
    return( RkwCreateContext() ) ;
}

int
RkDuplicateContext( src_cx )
int src_cx ;
{
    return( RkwDuplicateContext( src_cx ) ) ;
}

int
RkGetDicList(cxnum, dicnames, max)
int cxnum ;
char *dicnames ;
int max ;
{
    return( RkwGetDicList( cxnum, dicnames, max ) ) ;
}

int
RkDefineDic(cxnum, dicname, wordrec)
int cxnum;
char *dicname, *wordrec;
{
    if( !dicname || !wordrec )
      return( -1 ) ;

    euc2ushort(wordrec, strlen(wordrec), rkc.cbuf, CBUFSIZE);
    return _RkwDefineDic(cxnum, dicname, rkc.cbuf);
}

int
RkDeleteDic(cxnum, dicname, wordrec)
int cxnum;
char *dicname, *wordrec;
{
    Ushort cbuf[CBUFSIZE];

    if( !dicname || !wordrec )
      return( -1 ) ;

    euc2ushort(wordrec, strlen(wordrec), cbuf, CBUFSIZE);
    return( _RkwDeleteDic(cxnum, dicname, cbuf) );
}

int
RkMountDic( cxnum, dicname, mode )
int cxnum, mode;
char *dicname;
{
    return( RkwMountDic( cxnum, dicname, mode ) );
}

int
RkRemountDic( cxnum, dicname, where )
int cxnum, where;
char *dicname;
{
    return( RkwRemountDic( cxnum, dicname, where ) );
}

int
RkUnmountDic( cxnum, dicname )
int cxnum;
char *dicname;
{
    return( RkwUnmountDic( cxnum, dicname ) );
}

int
RkGetMountList( cxnum, dicnames_return, max )
int cxnum, max;
char *dicnames_return;
{
    return( RkwGetMountList( cxnum, dicnames_return, max ) );
}

int
RkSetDicPath( cxnum, path ) /* サーチパスを設定 */
int cxnum ;
char *path ;
/* ARGSUSED */
{
    /*
     * サーバが立ち上がるときに設定するのでRKCでは何もせずに返す
     */
    return( 0 ) ;
}

int
RkGetDirList( cxnum, ddname, maxddname )   /* 辞書リストを取得 */
int cxnum ;
char *ddname ;
int maxddname ;
/* ARGSUSED */
{
#ifdef USE_EUC_PROTOCOL
    register RkcContext *cx = getCC( cxnum, NOCHECK ) ;

    if( !cx || ProtocolMajor > 1 )
      return( -1 ) ;

    if( !ddname ) {
      char buffer[BUFSIZE] ;

      return (rkc_get_dir_list(cx, buffer, BUFSIZE));
    } else if( maxddname <= 0 )
      return( 0 ) ;

    return( rkc_get_dir_list( cx, ddname, maxddname ) ) ;
#else /* !USE_EUC_PROTOCOL */
    return -1;
#endif /* !USE_EUC_PROTOCOL */
}

int
RkBgnBun(cxnum, yomi, maxyomi, mode)
int cxnum;
char *yomi;
int maxyomi;
int mode;
{
    Ushort cbuf[CBIGBUFSIZE];
    int len;

    if (yomi) {
      len = euc2ushort(yomi, maxyomi, cbuf, CBIGBUFSIZE);
      return( _RkwBgnBun(cxnum, cbuf, len, mode) );
    }
    else {  /* 自動変換開始 */
      return _RkwBgnBun(cxnum, (Ushort *)NULL, maxyomi, mode);
    }
}

int
RkEndBun( cxnum, mode )
int cxnum, mode ;
{
    return( RkwEndBun( cxnum, mode ) );
}

int
RkXfer( cxnum, knum )
int cxnum, knum;
{
    return( RkwXfer( cxnum, knum ) );
}

int
RkNfer( cxnum )
int cxnum ;
{
    return( RkwNfer( cxnum ) );
}

int
RkNext( cxnum )
int cxnum ;
{
    return( RkwNext( cxnum ) );
}

int
RkPrev(cxnum)
int cxnum ;
{
    return( RkwPrev( cxnum ) );
}

int
RkGetKanji(cxnum, kanji, maxkanji)
int cxnum;
unsigned char *kanji;
int maxkanji;
{
    Ushort cbuf[CBUFSIZE];
    int len;

    if( (len = _RkwGetKanji(cxnum, cbuf, CBUFSIZE)) < 0 ){
      return( len );
    }
    else {
      if( !kanji ) {
          char buffer[CBUFSIZE];

          return( ushort2euc(cbuf, len, buffer, CBUFSIZE) );
      }
      else if( maxkanji <= 0 )
          return( 0 );

      return ushort2euc(cbuf, len, (char *)kanji, maxkanji);
    }
}

int
RkGetKanjiList(cxnum, kanjis, maxkanjis)
int cxnum;
unsigned char *kanjis;
int maxkanjis;
{
  Ushort cbuf[CBIGBUFSIZE];
  int nkanji, len, i, j = 0, k = 0;
  char eucbuf[CBUFSIZE*2];                      /* S005 */
  int euclen;                                         /* S005 */

  if( !kanjis ) {
    return( _RkwGetKanjiList(cxnum, (Ushort *)0, 0) );
  }
  else if( maxkanjis <= 0 )
    return( 0 );

  nkanji = _RkwGetKanjiList(cxnum, cbuf, CBIGBUFSIZE);

  for (i = 0 ; i < nkanji ; i++) {
    len = ushortstrlen(cbuf + j);
    euclen = ushort2euc(cbuf + j, len, eucbuf, CBUFSIZE * 2);     /* S005 */
    if (k + euclen > maxkanjis - 2)                   /* S005 */
      break;                                          /* S005 */
    strcpy((char *)kanjis + k, (char *)eucbuf);             /* S005 */
    k += euclen + 1;                                  /* S005 */
    j += len + 1;
  }
  kanjis[k] = (unsigned char)0;
  return( i );                                        /* S005 */
}

int
RkGoTo(cxnum, bnum)
int cxnum, bnum ;
{
    return( RkwGoTo( cxnum, bnum ) );
}

int
RkLeft( cxnum )
int cxnum;
{
    return( RkwLeft( cxnum ) );
}

int
RkRight( cxnum )
int cxnum;
{
    return( RkwRight( cxnum ) );
}

int
RkResize(cxnum, len)
int cxnum, len ;
{
    /* この len はバイトやけど,RkwResize には文字数を渡さなあかんのと
       ちゃうやろか? こんなん,どないやって変換したらええんやろ? */
    Ushort cbuf[CBUFSIZE];
    char tmpbuf[BUFSIZE];
    register int euclen, uslen = 0;
    int curbun, ret;
    register RkcContext  *cx = getCC( cxnum, CHECK ) ;

    if( cx ) {
      if( len <= 0 )
          return( cx->maxbun );

      /* しゃあないから,読みを取ってきて文字数を調べたろ */
      curbun = cx->curbun;
      for( ; (cx->curbun < cx->maxbun) && len; (cx->curbun)++ ) {
          /* こんなんしとったらめちゃくちゃ効率悪いがな...とほほ */
          if( (ret = _RkwGetYomi( cx, cbuf, CBUFSIZE )) < 0 ) {
            cx->curbun = curbun;
            return( -1 ) ;
          }
          if( (euclen = ushort2euc(cbuf, ret, tmpbuf, BUFSIZE)) > len ) {
            uslen += euc2ushort(tmpbuf, len, cbuf, CBUFSIZE);
            break;
          } else {
            uslen += ret;
            len -= euclen;
          }
      }
      cx->curbun = curbun;
    } else {
      if( len <= 0 )
          return( 0 );
    }
    return( RKReSize( cxnum, uslen ) );
}

int
RkEnlarge( cxnum )  /* 文節伸ばし */
int cxnum ;
{
    return( RKReSize( cxnum, ENLARGE  ) ) ;
}

int
RkShorten(cxnum)    /* 文節縮め */
int cxnum ;
{
    return( RKReSize( cxnum, SHORTEN ) ) ;
}

int
RkStoreYomi(cxnum, yomi, maxyomi)
int cxnum;
char *yomi;
int maxyomi;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if (yomi && maxyomi >= 0) {
    len = RKI_MIN((int)strlen(yomi),maxyomi); 
    len = euc2ushort(yomi, len, cbuf, CBUFSIZE) + 1;
  } else {
    cbuf[0] = 0;
    len = 0;
  }
  return( _RkwStoreYomi(cxnum, cbuf, len) );
}

int
RkGetYomi(cxnum, yomi, maxyomi)
int cxnum;
unsigned char *yomi;
int maxyomi;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if ((len = _RkwGetYomi(getCC( cxnum, CHECK ), cbuf, CBUFSIZE)) < 0) {
    return( len );
  }
  else {
    if( !yomi ) {
      char buffer[CBUFSIZE];

      return( ushort2euc(cbuf, len, buffer, CBUFSIZE) );
    }
    else if( maxyomi <= 0 )
      return( 0 );

    return ushort2euc(cbuf, len, (char *)yomi, maxyomi);
  }
}

int
RkGetLex(cxnum, lex, maxlex)
int cxnum, maxlex ;
RkLex *lex ;
{
    RkLex *tango;
    Ushort ybuf[CBUFSIZE], kbuf[CBUFSIZE];
    char cbuf[BUFSIZE];
    int i, len, ylen, klen, ret;

    if( (ret = RkwGetLex( cxnum, lex, maxlex )) <= 0 )
      return( ret );
    if (lex != (RkLex *)NULL) {
      len = _RkwGetYomi(getCC( cxnum, CHECK ), ybuf, CBUFSIZE);
      len = _RkwGetKanji(cxnum, kbuf, CBUFSIZE);
      ylen = klen = 0;
      tango = lex;
      for( i = 0; i < ret; i++ ){
      len = tango->ylen;
      tango->ylen = ushort2euc(ybuf + ylen, len, cbuf, BUFSIZE);
      ylen += len;
      len = tango->klen;
      tango->klen = ushort2euc(kbuf + klen, len, cbuf, BUFSIZE);
      klen += len;
      tango++;
      }
    }
    return( ret );
}

int
RkGetStat(cxnum, stat)
int cxnum ;
RkStat *stat ;
{
    unsigned char cbuf[BUFSIZE];
    int ret;

    if( (ret = RkwGetStat( cxnum, stat )) < 0 )
      return( ret );
    stat->ylen = RkGetYomi(cxnum, cbuf, BUFSIZE);
    stat->klen = RkGetKanji(cxnum, cbuf, BUFSIZE);
    return( ret );
}

#ifdef EXTENSION
RkListDic( cxnum, dirname, dicnames_return, size )
int cxnum, size;
unsigned char *dirname, *dicnames_return;
{
  return RkwListDic(cxnum, (char *)dirname,(char *) dicnames_return, size);
}

exp(int)
RkCreateDic( cxnum, dicname, mode )
int cxnum, mode;
unsigned char *dicname;
{
  return RkwCreateDic(cxnum, (char *)dicname, mode);
}

RkRemoveDic( cxnum, dicname, mode )
int cxnum;
unsigned char *dicname;
{
  return RkwRemoveDic(cxnum, (char *)dicname, mode);
}

RkRenameDic( cxnum, dicname, newdicname, mode )
int cxnum, mode;
unsigned char *dicname, *newdicname;
{
  return RkwRenameDic(cxnum, (char *)dicname, (char *)newdicname, mode);
}

RkCopyDic(cxnum, dirname, dicname, newdicname, mode)
int cxnum, mode;
unsigned char *dirname, *dicname, *newdicname;
{
  return RkwCopyDic(cxnum, (char *)dirname, (char *)dicname,
                (char *)newdicname, mode);
}

exp(int)
RkGetWordTextDic(cxnum, dirname, dicname, info, infolen)
int cxnum, infolen ;
unsigned char *dirname, *dicname, *info;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if ((len = _RkwGetWordTextDic(cxnum, dirname, dicname, cbuf, CBUFSIZE)) < 0){
    return len;
  }
  else {
    if( !info ) {
      char buffer[CBUFSIZE];

      return( ushort2euc(cbuf, len, buffer, CBUFSIZE) );
    }
    else if( infolen <= 0 )
      return 0;

    return ushort2euc(cbuf, len, (char *)info, infolen);
  }
}

#else
RkListDic(){}
RkCreateDic(){}
RkRemoveDic(){}
RkRenameDic(){}
RkGetWordTextDic(){}
#endif /* EXTENSION */

int
RkSubstYomi( cxnum, ys, ye, yomi, nyomi )
int cxnum, ys, ye, nyomi;
char *yomi;
{
  RkcContext *cx = getCC( cxnum, CHECK );
  char cbuf[CBUFSIZE];
  Ushort cbuf2[CBUFSIZE];
  int len;

  if (cx) {
    ushort2euc(cx->lastyomi, cx->maxyomi, cbuf, CBUFSIZE);
    ys = euc2ushort(cbuf, ys, cbuf2, CBUFSIZE);
    ye = euc2ushort(cbuf, ye, cbuf2, CBUFSIZE);
    len = euc2ushort(yomi, nyomi, cbuf2, CBUFSIZE);
    return( _RkwSubstYomi(cxnum, ys, ye, cbuf2, len) );
  }
  return( -1 ) ;
}

int
RkFlushYomi( cxnum )
int cxnum;
{
    return( RkwFlushYomi( cxnum ) );
}

int
RkGetLastYomi( cxnum, yomi, maxyomi )
int cxnum;
char *yomi;
int maxyomi;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if( (len = _RkwGetLastYomi(cxnum, cbuf, CBUFSIZE)) < 0 ){
    return -1;
  }
  else {
    if( !yomi ) {
      char buffer[CBUFSIZE];

      return( ushort2euc(cbuf, len, buffer, CBUFSIZE) );
    }
    else if( maxyomi <= 0 )
      return 0;

    return ushort2euc(cbuf, len, yomi, maxyomi);
  }
}

int
RkRemoveBun( cxnum, mode )
int cxnum, mode ;
{
    return( RkwRemoveBun( cxnum, mode ) );
}

int
RkGetSimpleKanji( cxnum, dicname, yomi, maxyomi, kanjis, maxkanjis, hinshis, maxhinshis )
int cxnum, maxyomi, maxkanjis, maxhinshis ;
unsigned char *yomi, *kanjis, *hinshis ;
{
  Ushort cbuf[CBUFSIZE], cbuf2[CBIGBUFSIZE], cbuf3[CBIGBUFSIZE];
  int nkanji, len, i, j = 0, k = 0, l = 0, m = 0;

  if( !dicname || !yomi || maxyomi <= 0 )
    return( -1 );

  len = euc2ushort((char *)yomi, maxyomi, cbuf, CBUFSIZE);
  nkanji = _RkwGetSimpleKanji(cxnum, dicname, cbuf, len,
                    cbuf2, CBIGBUFSIZE, cbuf3, CBIGBUFSIZE );

  if( nkanji <= 0 || !kanjis || !hinshis )
    return( nkanji );
  if( maxkanjis <= 0 || maxhinshis <= 0 )
    return( 0 );

  for( i = 0 ; i < nkanji ; i++ ) {
    k += ushort2euc(cbuf2 + j, ushortstrlen(cbuf2 + j),
                (char *)kanjis + k, maxkanjis - k) + 1;
    j += ushortstrlen(cbuf2 + j) + 1;
    l += ushort2euc(cbuf3 + m, ushortstrlen(cbuf3 + m),
                (char *)hinshis + l, maxhinshis - l) + 1;
    m += ushortstrlen(cbuf3 + m) + 1;
  }
  kanjis[k] = hinshis[l] = (unsigned char)0;
  return ( nkanji );
}

int
RkQueryDic( cxnum, username, dicname, status )              /* S002 */
int cxnum;
char *username;                           /* S002 */
char *dicname;
struct DicInfo *status;
{
  return RkwQueryDic(cxnum, username, dicname, status);
}

int
RkGetHinshi( cxnum, dst, maxdst )
int cxnum, maxdst;
unsigned char *dst;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if( (len = _RkwGetHinshi( cxnum, cbuf, CBUFSIZE )) < 0 ){
    return -1;
  }
  else {
    if( !dst ) {
      char buffer[CBUFSIZE];

      return( ushort2euc(cbuf, len, buffer, CBUFSIZE) );
    }
    else if( maxdst <= 0 )
      return 0;

    return ushort2euc(cbuf, len, (char *)dst, maxdst);
  }
}

int
RkStoreRange( cxnum, yomi, maxyomi )
int cxnum, maxyomi;
unsigned char *yomi;
{
  Ushort cbuf[CBUFSIZE];
  int len;

  if( !yomi || maxyomi <= 0 )
    return -1;

  len = euc2ushort((char *)yomi, maxyomi, cbuf, CBUFSIZE);
  return( _RkwStoreRange( cxnum, cbuf, len ) );
}

int
RkSetLocale( cxnum, locale )
int cxnum;
unsigned char *locale;
{
    return( RkwSetLocale( cxnum, locale ) );
}

int
RkSync( cxnum, dicname )
int cxnum;
char *dicname;
{
    return( RkwSync( cxnum, dicname ) );
}

int
RkSetAppName( cxnum, apname )
int cxnum;
char *apname;
{
    return( RkwSetAppName( cxnum, apname ) );
}

int
RkChmodDic(cxnum, dicname, mode)
int cxnum;
unsigned char *dicname;
int mode;
{
  return RkwChmodDic(cxnum, (char *)dicname, mode);
}
#endif /* OMIT_EUC_FUNCS */

#ifdef ENGINE_SWITCH
exp(struct rkfuncs) RkFuncs = {
  RkwGetProtocolVersion,
  RkwGetServerName,
  RkwGetServerVersion,
  RkwInitialize,
  RkwFinalize,
  RkwCreateContext,
  RkwDuplicateContext,
  RkwCloseContext,
  RkwSetDicPath,
  RkwCreateDic,
  RkwSync,
  RkwGetDicList,
  RkwGetMountList,
  RkwMountDic,
  RkwRemountDic,
  RkwUnmountDic,
  RkwDefineDic,
  RkwDeleteDic,
  RkwGetHinshi,
  RkwGetKanji,
  RkwGetYomi,
  RkwGetLex,
  RkwGetStat,
  RkwGetKanjiList,
  RkwFlushYomi,
  RkwGetLastYomi,
  RkwRemoveBun,
  RkwSubstYomi,
  RkwBgnBun,
  RkwEndBun,
  RkwGoTo,
  RkwLeft,
  RkwRight,
  RkwNext,
  RkwPrev,
  RkwNfer,
  RkwXfer,
  RkwResize,
  RkwEnlarge,
  RkwShorten,
  RkwStoreYomi,
  RkwSetAppName,
  RkwSetUserInfo,
  RkwQueryDic,
  RkwCopyDic,
  RkwListDic,
  RkwRemoveDic,
  RkwRenameDic,
  RkwChmodDic,
  RkwGetWordTextDic,
  RkwGetSimpleKanji,
};
#endif /* ENGINE_SWITCH */
/*
 *  RkThrough ()
 *
 *  Description:
 *  -----------
 *  commandで示される機能を実行する
 *
 *  Input:
 *  -----
 *  command: コマンド番号
 *  buf: データ/結果の先頭ポインタ
 *  content_size: データのサイズ
 *  buffer_size: 結果領域のサイズ
 *
 *  Returns:
 *  -------
 *  bufに格納された大きさ or -1
 */
int
RkThrough( cxnum, command, buf, content_size, buffer_size )
int cxnum;
int command;
unsigned char *buf;
int content_size;
int buffer_size;
{
    RkcContext *cx = getCC( cxnum, NOCHECK );

    if( cx ){
      return (*RKCP->through)
        (cx, command, (char *)buf, content_size, buffer_size);
    }
    return( -1 ) ;
}                                         /* S000:end */

#ifndef wchar_t
# error "wchar_t is already undefined"
#endif
#undef wchar_t
/*********************************************************************
 *                       wchar_t replace end                         *
 *********************************************************************/

Generated by  Doxygen 1.6.0   Back to index