/*
 *  $Id: yincoding.c,v 1.7 2005/04/10 15:26:37 aonoto Exp $
 */

/*
 * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
 * This file is part of FreeWnn.
 * 
 * Copyright Kyoto University Research Institute for Mathematical Sciences
 *                 1987, 1988, 1989, 1990, 1991, 1992
 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
 * Copyright FreeWnn Project 1999, 2000, 2002
 *
 * Maintainer:  FreeWnn Project   <freewnn@tomo.gr.jp>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/**  cWnn  Version 1.1   **/
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include  <stdio.h>
#include  <ctype.h>
#include  "commonhd.h"
#ifdef CHINESE
#if STDC_HEADERS
#  include  <string.h>
#elif HAVE_STRINGS_H
#  include  <strings.h>
#endif /* STDC_HEADERS */

#include  "cplib.h"
#include  "rk_spclval.h"
#include  "jh.h"
#include  "wnn_string.h"

extern char *py_table[];
extern char *zy_table[];
unsigned char last_mark;        /* Using to reme previous auto_state() */

/* copied from old sstrings.c */
static int
cwnn_sStrcpy (c, w)
     register char *c;
     register w_char *w;
{
  char *c0 = c;
  for (; *w != 0; w++)
    {
      if ((*w & 0x8080) == 0x8000)
        {
          *c++ = 0x8f;
          *c++ = (char) ((*w & 0xff00) >> 8);
          *c++ = (char) ((*w & 0x007f) | 0x0080);
        }
      else
        {
          if (*w & 0xff00)
            *c++ = (char) ((*w & 0xff00) >> 8);
          else if (*w & 0x80)
            *c++ = 0x8e;
          *c++ = (char) (*w & 0x00ff);
        }
    }
  *c = '\0';
  return (c - c0);
}


static int
cwnn_Sstrcpy (w, c)
     w_char *w;
     unsigned char *c;
{
  w_char *w0 = w;

  for (; *c;)
    {
      if (*c & 0x80)
        {
          if (*c == 0x8e)
            {
              c++;
              *w++ = (unsigned short) *c++;
            }
          else if (*c == 0x8f)
            {
              c++;
              *w = (unsigned short) (*c++ << 8);
              *w++ |= (unsigned short) (*c++ & 0x7f);
            }
          else
            {
              *w = (unsigned short) (*c++ << 8);
              *w++ |= (unsigned short) *c++;
            }
        }
      else
        {
          *w++ = (unsigned short) *c++;
        }
    }
  *w = 0;
  return (w - w0);
}

static int
cwnn_Sstrcat (w, c)
     w_char *w;
     unsigned char *c;
{
  w_char *w0 = w;

  for (; *w; w++);

  for (; *c;)
    {
      if (*c & 0x80)
        {
          if (*c == 0x8e)
            {
              c++;
              *w++ = (unsigned short) *c++;
            }
          else if (*c == 0x8f)
            {
              c++;
              *w = (unsigned short) (*c++ << 8);
              *w++ |= (unsigned short) (*c++ & 0x7f);
            }
          else
            {
              *w = (unsigned short) (*c++ << 8);
              *w++ |= (unsigned short) *c++;
            }
        }
      else
        {
          *w++ = (unsigned short) *c++;
        }
    }
  *w = 0;
  return (w - w0);
}

/********** py_yunmu(), zy_yunmu(): if yuyin with YunMu, return YunMu's 
        position in YunMu table. after that, you must calculate its 
        real yun_raw static        if without YunMu, return -1  
***********/
static int
py_yunmu (yuyin)
     register char *yuyin;
{
  register int i;
  for (i = (PY_NUM_YUNMU * 5) - 1; i >= 0; i--)
    {
      if (strncmp (yuyin, py_yunmu_tbl[i], strlen (py_yunmu_tbl[i])) == 0)
        return (i);
    }
  return (-1);
}

static int
zy_yunmu (yuyin)
     register char *yuyin;
{
  register int i;
  for (i = (ZY_NUM_YUNMU * 5) - 1; i >= 0; i--)
    {
      if (strncmp (yuyin, zy_yunmu_tbl[i], strlen (zy_yunmu_tbl[i])) == 0)
        return (i);
    }
  return (-1);
}

/* is_pinyin():  if is PinYin with Shengmu,     return 1   */
/*              if is PinYin without Shengmu ,   return 0   */
/*              else                            return -1  */

static int
is_pinyin (sheng_raw, yun_raw)
     register int sheng_raw;
     register int yun_raw;
{

  if ((sheng_raw >= 0) && (sheng_raw < PY_NUM_SHENGMU) && (yun_raw >= 0) && (yun_raw < PY_NUM_YUNMU) && (pinyin_tbl[sheng_raw * PY_NUM_YUNMU + yun_raw] == 1))
    {
      if (sheng_raw == EMPTY_SHENG_RAW)
        return (0);
      else
        return (1);
    }
  else
    return (-1);

}

/* is_zhuyin():  if is ZhuYin with Shengmu:     return 1   */
/*               if is ZhuYin without Shengmu:  return 0   */
/*                                       else:  return -1  */

static int
is_zhuyin (sheng_raw, yun_raw)
     register int sheng_raw;
     register int yun_raw;
{

  if ((sheng_raw >= 0)
       && (sheng_raw < ZY_NUM_SHENGMU)
       && (yun_raw >= 0)
       && (yun_raw < ZY_NUM_YUNMU)
       && ((zhuyin_tbl[sheng_raw * ZY_NUM_YUNMU + yun_raw] & 0x8000) == 0x8000))
    {
      if (sheng_raw == EMPTY_SHENG_RAW)
        return (0);
      else
        return (1);
    }
  return (-1);
}

/* py_shengmu(), zy_shengmu(): 
        if yuyin with ShengMu, return Shengmu's position
        in ShengMu table.  if without ShengMu, return -1  
*/
static int
py_shengmu (yuyin)
     register char *yuyin;
{
  register int i;
  for (i = PY_NUM_SHENGMU - 1; i > 0; i--)
    {
      if (strncmp (yuyin, py_shengmu_tbl[i], strlen (py_shengmu_tbl[i])) == 0)
        return (i);
    }
  return (-1);
}

static int
zy_shengmu (yuyin)
     register char *yuyin;
{
  register int i;
  for (i = ZY_NUM_SHENGMU - 1; i > 0; i--)
    {
      if (strncmp (yuyin, zy_shengmu_tbl[i], strlen (zy_shengmu_tbl[i])) == 0)
        return (i);
    }
  return (-1);
}

#ifdef nodef
static void
getstr_pzy (lstr, yincod, which)
     register letter *lstr;
     register w_char yincod;
     int which;
{
  register letter *ltmp;

  ltmp = lstr;
  for (; *lstr; lstr++)

    if ((which == CWNN_PINYIN) && ((*lstr & 0x0000ffff) == PY_EOF))
      break;
    else if ((which == CWNN_ZHUYIN) && (isZY_EOF (*lstr & 0x0000ffff)))
      break;
  lstr++;
  *ltmp++ = yincod;
  for (; *lstr; lstr++)
    *ltmp++ = *lstr;
  *ltmp = 0;
}
#endif

/* create_yincod(): input:  
        raw in ShengMu table of PinYin, raw in YunMu table of PinYin,
        sisheng  output: yincod: if is PinYin, otherwise:0. 
*/

static w_char
create_yincod (sheng_raw, yun_raw, ss)
     register int sheng_raw;
     register int yun_raw;
     register int ss;
{
  int ret = 0;
  if (is_pinyin (sheng_raw, yun_raw) == 1)      /*Has Shengmu */
    ret = 0x0080 + (((yun_raw << 1) + 0x20) << 8) + ((sheng_raw - 1) << 2) + 0x20;
  else if (is_pinyin (sheng_raw, yun_raw) == 0) /*Not Shengmu */
    ret = 0x0080 + (((yun_raw << 1) + 0x20) << 8) + ((X_SHENG_RAW - 1) << 2) + 0x20;    /*Rent this */
  else
    return (ret);
  if ((ss > 0) && (ss <= 4))
    ret += 0x0100 + ss - 1;
  return (ret);
}

/* pzy_yincod() 
        in:     The param is expected to be a PinYin or a ZhuYin.
        return:  a Yin_code is returned, if it is a PinYin or a ZhuYin.
        otherwise, 0 is returned, 
*/
static int
pzy_get_sheng_yun (yuyin, ss, sheng_raw, yun_raw, which)
     register char *yuyin;      /* one PinYin or ZhuYin with end of character */
     register int *ss;          /* get SiSheng from PinYin or ZhuYin */
     register int *sheng_raw;   /* position in ShengMu table */
     int *yun_raw;              /* position in YunMu table */
     int which;
{
/*
  register int     j;
*/
  register char *pzytmp;

  *ss = -1;
  *sheng_raw = -1;
  *yun_raw = -1;

  pzytmp = yuyin;

  if (which == CWNN_PINYIN)
    {                           /* for Pinyin case */

      if ((*sheng_raw = py_shengmu (pzytmp)) == -1)
        {                       /* no ShengMu  */
          if ((*yun_raw = py_yunmu (pzytmp)) == -1)
            return (0);
          else
            {
              pzytmp += strlen (py_yunmu_tbl[*yun_raw]);
              *sheng_raw = 0;
              *ss = *yun_raw % 5;
              *yun_raw = *yun_raw / 5;
              return (pzytmp - yuyin);
            }
        }
      else
        {                       /* has ShengMu */
/*
            for ( j = 0; (int)j < (int)strlen(py_shengmu_tbl[*sheng_raw]); j++) 
                pzytmp++;
*/
          pzytmp += strlen (py_shengmu_tbl[*sheng_raw]);
          if (strlen (pzytmp) == 0)
            return (0);
          if ((*yun_raw = py_yunmu (pzytmp)) != -1)
            {
              pzytmp += strlen (py_yunmu_tbl[*yun_raw]);
              *ss = *yun_raw % 5;
              *yun_raw = *yun_raw / 5;
              return (pzytmp - yuyin);
            }
          else
            {
              pzytmp = yuyin;
              if ((*yun_raw = py_yunmu (pzytmp)) == -1)
                return (0);
              else
                {
                  pzytmp += strlen (py_yunmu_tbl[*yun_raw]);
                  *sheng_raw = 0;
                  *ss = *yun_raw % 5;
                  *yun_raw = *yun_raw / 5;
                  return (pzytmp - yuyin);
                }
            }
        }                       /* has ShengMu when Pinyin */
    }
  else
    {                           /* for Zhuyin case */

      if ((*sheng_raw = zy_shengmu (pzytmp)) == -1)
        {                       /* no ShengMu  */
          if ((*yun_raw = zy_yunmu (pzytmp)) == -1)
            return (0);
          else
            {
              pzytmp += strlen (zy_yunmu_tbl[*yun_raw]);
              *sheng_raw = 0;
              *ss = *yun_raw % 5;
              *yun_raw = *yun_raw / 5;
              return (pzytmp - yuyin);
            }
        }
      else
        {                       /* has ShengMu */
/*
            for ( j = 0; (int)j < (int)strlen(zy_shengmu_tbl[*sheng_raw]); j++) 
                pzytmp++;
*/
          pzytmp += strlen (zy_shengmu_tbl[*sheng_raw]);
          if (strlen (pzytmp) == 0)
            return (0);
          if ((*yun_raw = zy_yunmu (pzytmp)) != -1)
            {
              pzytmp += strlen (zy_yunmu_tbl[*yun_raw]);
              *ss = *yun_raw % 5;
              *yun_raw = *yun_raw / 5;
              return (pzytmp - yuyin);
            }
          else
            {
              pzytmp = yuyin;
              if ((*yun_raw = zy_yunmu (pzytmp)) == -1)
                return (0);
              else
                {
                  pzytmp += strlen (zy_yunmu_tbl[*yun_raw]);
                  *sheng_raw = 0;
                  *ss = *yun_raw % 5;
                  *yun_raw = *yun_raw / 5;
                  return (pzytmp - yuyin);
                }
            }
        }                       /* has ShengMu when Zhuyin */
    }                           /* which */
}

static w_char
pzy_yincod (one_yuyin, len)
     register char *one_yuyin;
     register int *len;
{
  int ss[1];
  int sheng_raw[1];
  int yun_raw[1];
  register int zytmp;
  register int ret;

  *len = 0;
  /* for Pinyin */
  if (ret = pzy_get_sheng_yun (one_yuyin, ss, sheng_raw, yun_raw, CWNN_PINYIN))
    if (is_pinyin (sheng_raw[0], yun_raw[0]) != -1)
      {
        *len = ret;
        return (create_yincod (sheng_raw[0], yun_raw[0], ss[0]));
      }
  /* for Zhuyin */
  if (ret = pzy_get_sheng_yun (one_yuyin, ss, sheng_raw, yun_raw, CWNN_ZHUYIN))
    {
      zytmp = zhuyin_tbl[sheng_raw[0] * ZY_NUM_YUNMU + yun_raw[0]];
      if (is_zhuyin (sheng_raw[0], yun_raw[0]) != -1)
        {
          if ((zytmp & 0x0080) == 0x0080)
            {
              sheng_raw[0] = (zytmp >> 8) & 0x7f;
              yun_raw[0] = zytmp & 0x7f;
            }
          *len = ret;
          return (create_yincod (sheng_raw[0], yun_raw[0], ss[0]));
        }
    }
  return (0);                   /* Otherwise, Not a Pinyin nor Zhuyin  */
}

/* ltoScpy():  copy strings from letter type to w_char type */

static int
ltoScpy (w, l)
     register w_char *w;
     register letter *l;
{
  register w_char *w0 = w;

  for (; *l; l++)
    {
      if (                      /* ((*l & 0x0000ffff) == PY_EOF) || isZY_EOF(*l & 0x0000ffff)
                                   || */ (*l == EOLTTR))
        /* add by Kuwari */
        break;
      *w++ = (*l & 0x0000ffff);
    }
  *w = (w_char) 0;
  return (w - w0);
}

/* find_pinyin():       find a YuYin in a string.  if there is a YuYin.
         it must be at the tail of string.  return point of start YuYin
         else return -1 eg. ;abcdHuang. 'Huang.' is a PinYin & return 5
         012345
*/
static int
find_pinyin (str)
     register char *str;
{
  register char *py_zy_tmp;
  register int i;
  register int pnt;
  int len;
  pnt = -1;
  if ((((*(str + strlen (str) - 2) << 8) & 0xff00) | (*(str + strlen (str) - 1) & 0x00ff)) != PY_EOF)
    return (-1);
  for (i = strlen (str) - 1; i >= 0; i--)
    {
      if ((int) (strlen (str) - i) > PY_LEN)
        return (pnt);
      py_zy_tmp = str + i;
      if (pzy_yincod (py_zy_tmp, &len) != 0)
        pnt = i;
    }
  return (pnt);
}

static int
find_zhuyin (str)
     register char *str;
{
  register char *py_zy_tmp;
  register int i;
  register int pnt;
  int len;
  pnt = -1;
  if (!isZY_EOF (((*(str + strlen (str) - 2) << 8) & 0xff00) | (*(str + strlen (str) - 1) & 0x00ff)))
    return (-1);
  for (i = strlen (str) - 1; i >= 0; i--)
    {
      if ((int) (strlen (str) - i) > PY_LEN)
        return (pnt);
      py_zy_tmp = str + i;
      if (pzy_yincod (py_zy_tmp, &len) != 0)
        pnt = i;
    }
  return (pnt);
}

/* get_one_zhuyin(): get one ZhuYin from ZhuYin strings */
/* get_one_pinyin(): get one PinYin from PinYin strings */
static int
get_one_pinyin (pinzhuyin_str, one_pinzhuyin)
     register unsigned char *pinzhuyin_str;
     register char *one_pinzhuyin;
{
  register w_char chrtmp;
  for (; (chrtmp = (((*pinzhuyin_str << 8) & 0xff00) | (*(pinzhuyin_str + 1) & 0x00ff))) != PY_EOF && *pinzhuyin_str != 0; pinzhuyin_str++)
    *one_pinzhuyin++ = *pinzhuyin_str;
  if (chrtmp == PY_EOF)
    {
      *one_pinzhuyin++ = *pinzhuyin_str;
      pinzhuyin_str++;
      *one_pinzhuyin++ = *pinzhuyin_str;
      *one_pinzhuyin = 0;
      return (1);
    }
  else
    {
      *one_pinzhuyin = 0;
      return (0);
    }
}

static int
get_one_zhuyin (pinzhuyin_str, one_pinzhuyin)
     register unsigned char *pinzhuyin_str;
     register char *one_pinzhuyin;
{
  register w_char chrtmp;
  for (; !isZY_EOF (chrtmp = (((*pinzhuyin_str << 8) & 0xff00) | (*(pinzhuyin_str + 1) & 0x00ff))) && *pinzhuyin_str != 0; pinzhuyin_str++)
    *one_pinzhuyin++ = *pinzhuyin_str;
  if (isZY_EOF (chrtmp))
    {
      *one_pinzhuyin++ = *pinzhuyin_str;
      pinzhuyin_str++;
      *one_pinzhuyin++ = *pinzhuyin_str;
      *one_pinzhuyin = 0;
      return (1);
    }
  else
    {
      *one_pinzhuyin = 0;
      return (0);
    }
}

/* cwnn_is_yincod(c)    To check is "c"is a yincod. 
        if so, return(1) otherwise return 0*/
int
cwnn_is_yincod (c)
     register w_char c;
{
  register int sheng_raw;
  register int yun_raw;

  if (!_cwnn_isyincod_d (c))
    return (0);

  sheng_raw = Shengraw (c);
  yun_raw = Yunraw (c);
  if (is_pinyin (sheng_raw, yun_raw))
    return (1);
  if (sheng_raw == X_SHENG_RAW && is_pinyin (EMPTY_SHENG_RAW, yun_raw) == 0)
    return (1);
  else
    return (0);
}

/* For a given 'yincod', creat the corresponding Pinyin or Zhuyin
   to pzy_buf as a w_char string. If the given 'yincod' is not a yincod,
   'yincod', followed by a NULL is created to pzy_fub.
   Return: the lenth of pzy_buf is returned.
   Lenth means the lenth in console but not num of character.
*/
int
cwnn_yincod_pzy (register w_char *pzy_buf, register w_char c, int which)
//     register w_char *pzy_buf;  /* out:    a Pinyin or Zhuyin */
//     register w_char c;         /* input:  a yincod     */
//     int which;                 /* option Pinyin or Zhuyin */
{
  register int sheng_raw;
  register int yun_raw;
  register int ss;              /* for Sisheng  */
  register int zytmp;

  if (!cwnn_is_yincod (c))
    {
      *pzy_buf = c;
      *(pzy_buf + 1) = 0;
      return (1);

/*      if ( ((c&0x00ff)>0xa0) && ((c&0x00ff)< 0xff) &&
             ((c>>8) > 0xa0) && ((c>>8) < 0xff) )
                return(2);      
        else    return(1);
*/
    }

  sheng_raw = Shengraw (c);
  yun_raw = Yunraw (c);
  ss = _cwnn_sisheng (c);

  if (which == CWNN_PINYIN)
    {                           /* For Pinyin case */
      if (sheng_raw == X_SHENG_RAW && is_pinyin (sheng_raw, yun_raw) == -1)
        if (is_pinyin (EMPTY_SHENG_RAW, yun_raw) == 0)
          sheng_raw = EMPTY_SHENG_RAW;
      cwnn_Sstrcpy (pzy_buf, py_shengmu_tbl[sheng_raw]);
      if (_cwnn_has_sisheng (c))
        cwnn_Sstrcat (pzy_buf, py_yunmu_tbl[yun_raw * 5 + ss]);
      else
        cwnn_Sstrcat (pzy_buf, py_yunmu_tbl[yun_raw * 5]);
    }
  else
    {                           /* For Zhuyin case */

      zytmp = zhuyin_tbl[sheng_raw * ZY_NUM_YUNMU + yun_raw];
      if (is_zhuyin (sheng_raw, yun_raw) == -1)
        {
          if ((zytmp & 0x0080) == 0x0080)
            {
              sheng_raw = (zytmp >> 8) & 0x7f;
              yun_raw = zytmp & 0x7f;
            }
          else
            {
              if ((sheng_raw == X_SHENG_RAW) && (is_zhuyin (EMPTY_SHENG_RAW, yun_raw) == 0))
                sheng_raw = EMPTY_SHENG_RAW;
            }
        }
      cwnn_Sstrcpy (pzy_buf, zy_shengmu_tbl[sheng_raw]);
      if (yun_raw == EMPTY_YUN_RAW)
        {
          w_char tmp_w;
          if (_cwnn_has_sisheng (c))
            {
              switch (ss)
                {
                case 1:
                  tmp_w = ZY_EOF_1;
                  break;
                case 2:
                  tmp_w = ZY_EOF_2;
                  break;
                case 3:
                  tmp_w = ZY_EOF_3;
                  break;
                case 4:
                  tmp_w = ZY_EOF_4;
                  break;
                }
            }
          else
            {
              tmp_w = ZY_EOF_0;
            }
          wnn_Strncat (pzy_buf, &tmp_w, 1);
        }
      else
        {
          if (_cwnn_has_sisheng (c))
            cwnn_Sstrcat (pzy_buf, zy_yunmu_tbl[yun_raw * 5 + ss]);
          else
            cwnn_Sstrcat (pzy_buf, zy_yunmu_tbl[yun_raw * 5]);
        }
    }
  return (wnn_Strlen (pzy_buf));
}

/* Copy s2 which having yincod to s1 in which yincod are replaced by
the corresponding Pinyin or Zhuyin. Lenth of s2 is returned
*/
int
cwnn_yincod_pzy_str (s1, s2, n, which)
     register w_char *s1;       /* result string having Pinyin or Zhuyin */
     register w_char *s2;       /* input string having Yincod */
     int n;
     int which;
{
  w_char s2tmp[LINE_SIZE];
  register int i, j;
  w_char pzy_buf[10];
  int len, sum_len;

  len = 0;
  sum_len = 0;
  for (i = 0; i < n; i++)
    s2tmp[i] = s2[i];
  for (i = 0; i < n; i++)
    {

/*      len = cwnn_yincod_pzy(pzy_buf, s2tmp[i], which);
        for (j = 0; j < len; j++) 
                *s1++ = pzy_buf[j];
        sum_len += len;
*/
/* Strlen(pzy_buf) is the num of w_char , but "len" means the width */

      len = cwnn_yincod_pzy (pzy_buf, s2tmp[i], which);
      for (j = 0; j < wnn_Strlen (pzy_buf); j++)
        *s1++ = pzy_buf[j];
      sum_len += wnn_Strlen (pzy_buf);
    }
  *s1 = 0;
  return (sum_len);
}

/* cwnn_pzy_yincod(s1, s2, which): 
After the matching in automaton, the string may be a Pinyin or a Zhuyin
If so, it will be replace by the coreesponding Yincod */

int
cwnn_pzy_yincod (s1, s2, which)
     letter *s1, *s2;
     int which;
{
  /*
     register w_char codetmp2[PY_LEN];
     register char *codetmp1 = {"          "};
   */
  w_char codetmp2_buf[PY_LEN * 10 + 1];
  char codetmp1_buf[PY_LEN * 20 + 2];
  register w_char *codetmp2 = codetmp2_buf;
  register char *codetmp1 = codetmp1_buf;
  register letter *lettertmp = s2, *s1tmp = s1;
  register w_char yincod;
  int len;
  int conv = 0;
  w_char save_w[2];
  char save, tmp[6];

  save_w[0] = save_w[1] = 0;
  ltoScpy (codetmp2, lettertmp);
  if (cwnn_sStrcpy (codetmp1, codetmp2) <= 0)
    return (0);

/*      if ((yincod = pzy_yincod(codetmp1)) != 0) 
                getstr_pzy(s1, yincod, which);

Jun 13 Zhong */
  for (; *lettertmp && *lettertmp != EOLTTR;)
    {
      if ((yincod = pzy_yincod (codetmp1, &len)) != 0)
        {
          conv++;
          *s1tmp++ = (letter) yincod;
          save = codetmp1[len];
          codetmp1[len] = '\0';
          lettertmp += cwnn_Sstrcpy (codetmp2, codetmp1);
          codetmp1[len] = save;
          codetmp1 += len;
        }
      else
        {
          save_w[0] = (w_char) (*lettertmp & 0xffff);
          *s1tmp++ = *lettertmp++;
          codetmp1 += cwnn_sStrcpy (tmp, save_w);
        }
    }
  if (*lettertmp == EOLTTR)
    *s1tmp++ = *lettertmp++;
  if (conv)
    {
      return (s1tmp - s1);
    }
  else
    {
      return (0);
    }
}

/* cwnn_py_yincod_str(), cwnn_zy_yincod_str():HUANG: for atod
        we get yomi as PinYin or ZhuYin strings from ascii-dictionary and
        translate it to YINcode
*/
void
cwnn_py_yincod_str (yuyin_str, css, un_sisheng_yincod_str, yincod_str)
     register char *yuyin_str;  /* yomi: PinYin or ZhuYin strings */
     register char *css;        /* get sisheng strings from PinYin strings */
     register w_char *un_sisheng_yincod_str;    /* no-sisheng Yincod strings */
     register w_char *yincod_str;       /* Yincod strings with sisheng */
{
/*
  register  char    one_yuyin[LINE_SIZE];
  register  w_char not_yuyin[LINE_SIZE];
*/
  char one_yuyin_buf[LINE_SIZE];
  w_char not_yuyin_buf[LINE_SIZE];
  register char *one_yuyin = one_yuyin_buf;
  register w_char *not_yuyin = not_yuyin_buf;
  register int yin_eof;
  register w_char yincod;
  register int i, pst;
  int len;

  for (; *yuyin_str;)
    {
      yin_eof = get_one_pinyin (yuyin_str, one_yuyin);
      yuyin_str += strlen (one_yuyin);
      cwnn_Sstrcpy (not_yuyin, one_yuyin);
      pst = find_pinyin (one_yuyin);
      if (yin_eof == 1 && pst != -1)
        {
          for (i = 0; i < pst; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
          yincod = pzy_yincod (one_yuyin, &len);
          *yincod_str++ = yincod;
          *un_sisheng_yincod_str++ = _cwnn_yincod_0 (yincod);
          *css++ = (char) (_cwnn_sisheng (yincod) + 0x30);
        }
      else
        {
          for (i = 0; not_yuyin[i]; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
        }
    }
  *yincod_str = 0;
  *un_sisheng_yincod_str = 0;
  *css = 0;
}

void
cwnn_zy_yincod_str (yuyin_str, css, un_sisheng_yincod_str, yincod_str)
     register char *yuyin_str;  /* yomi: PinYin or ZhuYin strings */
     register char *css;        /* get sisheng strings from PinYin strings */
     register w_char *un_sisheng_yincod_str;    /* no-sisheng Yincod strings */
     register w_char *yincod_str;       /* Yincod strings with sisheng */
{
/*
  register  char    one_yuyin[LINE_SIZE];
  register  w_char not_yuyin[LINE_SIZE];
*/
  char one_yuyin_buf[LINE_SIZE];
  w_char not_yuyin_buf[LINE_SIZE];
  register char *one_yuyin = one_yuyin_buf;
  register w_char *not_yuyin = not_yuyin_buf;
  register int yin_eof;
  register w_char yincod;
  register int i, pst;
  int len;

  for (; *yuyin_str;)
    {
      yin_eof = get_one_zhuyin (yuyin_str, one_yuyin);
      yuyin_str += strlen (one_yuyin);
      cwnn_Sstrcpy (not_yuyin, one_yuyin);
      pst = find_zhuyin (one_yuyin);
      if (yin_eof == 1 && pst != -1)
        {
          for (i = 0; i < pst; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
          yincod = pzy_yincod (one_yuyin, &len);
          *yincod_str++ = yincod;
          *un_sisheng_yincod_str++ = _cwnn_yincod_0 (yincod);
          *css++ = (char) (_cwnn_sisheng (yincod) + 0x30);
        }
      else
        {
          for (i = 0; not_yuyin[i]; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
        }
    }
  *yincod_str = 0;
  *un_sisheng_yincod_str = 0;
  *css = 0;
}

/* cwnn_py_str_analysis(), cp_zy_str_analysis():   HUANG: for atod
        we get yomi as PinYin or ZhuYin strings from ascii-dictionary 
        and translate it to YINcode
*/
void
cwnn_py_str_analysis (yuyin_str, css, un_sisheng_yincod_str, yincod_str)
     register char *yuyin_str;  /* yomi: PinYin or ZhuYin strings */
     register char *css;        /* get sisheng strings from PinYin strings */
     register w_char *un_sisheng_yincod_str;    /* no-sisheng Yincod strings */
     register w_char *yincod_str;       /* Yincod strings with sisheng */
{
/*
  register  char    one_yuyin[LINE_SIZE];
  register  w_char not_yuyin[LINE_SIZE];
*/
  char one_yuyin_buf[LINE_SIZE];
  w_char not_yuyin_buf[LINE_SIZE];
  register char *one_yuyin = one_yuyin_buf;
  register w_char *not_yuyin = not_yuyin_buf;
  register int yin_eof;
  register w_char yincod;
  register int i, pst;
  int len;
  for (; *yuyin_str;)
    {
      yin_eof = get_one_pinyin (yuyin_str, one_yuyin);
      yuyin_str += strlen (one_yuyin);
      cwnn_Sstrcpy (not_yuyin, one_yuyin);
      pst = find_pinyin (one_yuyin);
      if (yin_eof == 1 && pst != -1)
        {
          for (i = 0; i < pst; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
          yincod = pzy_yincod (one_yuyin, &len);
          *yincod_str++ = yincod;
          *un_sisheng_yincod_str++ = _cwnn_yincod_0 (yincod);
          *css++ = (char) (_cwnn_sisheng (yincod) + 0x30);
        }
      else
        {
          for (i = 0; not_yuyin[i]; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
        }
    }
  *yincod_str = 0;
  *un_sisheng_yincod_str = 0;
  *css = 0;
}

void
cwnn_zy_str_analysis (yuyin_str, css, un_sisheng_yincod_str, yincod_str)
     register char *yuyin_str;  /* yomi: PinYin or ZhuYin strings */
     register char *css;        /* get sisheng strings from PinYin strings */
     register w_char *un_sisheng_yincod_str;    /* no-sisheng Yincod strings */
     register w_char *yincod_str;       /* Yincod strings with sisheng */
{
/*
  register  char    one_yuyin[LINE_SIZE];
  register  w_char not_yuyin[LINE_SIZE];
*/
  char one_yuyin_buf[LINE_SIZE];
  w_char not_yuyin_buf[LINE_SIZE];
  register char *one_yuyin = one_yuyin_buf;
  register w_char *not_yuyin = not_yuyin_buf;
  register int yin_eof;
  register w_char yincod;
  register int i, pst;
  int len;
  for (; *yuyin_str;)
    {
      yin_eof = get_one_zhuyin (yuyin_str, one_yuyin);
      yuyin_str += strlen (one_yuyin);
      cwnn_Sstrcpy (not_yuyin, one_yuyin);
      pst = find_zhuyin (one_yuyin);
      if (yin_eof == 1 && pst != -1)
        {
          for (i = 0; i < pst; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
          yincod = pzy_yincod (one_yuyin, &len);
          *yincod_str++ = yincod;
          *un_sisheng_yincod_str++ = _cwnn_yincod_0 (yincod);
          *css++ = (char) (_cwnn_sisheng (yincod) + 0x30);
        }
      else
        {
          for (i = 0; not_yuyin[i]; i++)
            {
              *yincod_str++ = not_yuyin[i];
              *un_sisheng_yincod_str++ = not_yuyin[i];
              *css++ = '5';
            }
        }
    }
  *yincod_str = 0;
  *un_sisheng_yincod_str = 0;
  *css = 0;
}
#endif /* CHINESE */
