/*
 * $Id: yincoding.c,v 2.4.2.1 2000/08/04 05:37:07 kaneda Exp $
 */
/*
WNN6 CLIENT LIBRARY--SOFTWARE LICENSE TERMS AND CONDITIONS


Wnn6 Client Library :
(C) Copyright OMRON Corporation.       1995,1998,2000 all rights reserved.
(C) Copyright OMRON Software Co., Ltd. 1995,1998,2000 all rights reserved.

Wnn Software :
(C) Copyright Kyoto University Research Institute for Mathematical Sciences
     1987, 1988, 1989, 1990, 1991, 1992, 1993
(C) Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1993
(C) Copyright ASCTEC, Inc.  1987, 1988, 1989, 1990, 1991, 1992, 1993

Preamble

These Wnn6 Client Library--Software License Terms and Conditions
 (the "License Agreement") shall state the conditions under which you are
 permitted to copy, distribute or modify the software which can be used
 to create Wnn6 Client Library (the "Wnn6 Client Library").  The License
 Agreement can be freely copied and distributed verbatim, however, you
 shall NOT add, delete or change anything on the License Agreement.

OMRON Corporation and OMRON Software Co., Ltd. (collectively referred to
 as "OMRON") jointly developed the Wnn6 Software (development code name
 is FI-Wnn), based on the Wnn Software.  Starting from November, 1st, 1998,
 OMRON publishes the source code of the Wnn6 Client Library, and OMRON
 permits anyone to copy, distribute or change the Wnn6 Client Library under
 the License Agreement.

Wnn6 Client Library is based on the original version of Wnn developed by
 Kyoto University Research Institute for Mathematical Sciences (KURIMS),
 OMRON Corporation and ASTEC Inc.

Article 1.  Definition.

"Source Code" means the embodiment of the computer code, readable and
 understandable by a programmer of ordinary skills.  It includes related
 source code level system documentation, comments and procedural code.

"Object File" means a file, in substantially binary form, which is directly
 executable by a computer after linking applicable files.

"Library" means a file, composed of several Object Files, which is directly
 executable by a computer after linking applicable files.

"Software" means a set of Source Code including information on its use.

"Wnn6 Client Library" the computer program, originally supplied by OMRON,
 which can be used to create Wnn6 Client Library.

"Executable Module" means a file, created after linking Object Files or
 Library, which is directly executable by a computer.

"User" means anyone who uses the Wnn6 Client Library under the License
 Agreement.

Article 2.  Copyright

2.1  OMRON Corporation and OMRON Software Co., Ltd. jointly own the Wnn6
 Client Library, including, without limitation, its copyright.

2.2  Following words followed by the above copyright notices appear
 in all supporting documentation of software based on Wnn6 Client Library:

  This software is based on the original version of Wnn6 Client Library
  developed by OMRON Corporation and OMRON Software Co., Ltd. and also based on
  the original version of Wnn developed by Kyoto University Research Institute
  for Mathematical Sciences (KURIMS), OMRON Corporation and ASTEC Inc.

Article 3.  Grant

3.1  A User is permitted to make and distribute verbatim copies of
 the Wnn6 Client Library, including verbatim of copies of the License
 Agreement, under the License Agreement.

3.2  A User is permitted to modify the Wnn6 Client Library to create
 Software ("Modified Software") under the License Agreement.  A User
 is also permitted to make or distribute copies of Modified Software,
 including verbatim copies of the License Agreement with the following
 information.  Upon modifying the Wnn6 Client Library, a User MUST insert
 comments--stating the name of the User, the reason for the modifications,
 the date of the modifications, additional terms and conditions on the
 part of the modifications if there is any, and potential risks of using
 the Modified Software if they are known--right after the end of the
 License Agreement (or the last comment, if comments are inserted already).

3.3  A User is permitted to create Library or Executable Modules by
 modifying the Wnn6 Client Library in whole or in part under the License
 Agreement.  A User is also permitted to make or distribute copies of
 Library or Executable Modules with verbatim copies of the License
 Agreement under the License Agreement.  Upon modifying the Wnn6 Client
 Library for creating Library or Executable Modules, except for porting
 a computer, a User MUST add a text file to a package of the Wnn6 Client
 Library, providing information on the name of the User, the reason for
 the modifications, the date of the modifications, additional terms and
 conditions on the part of the modifications if there is any, and potential
 risks associated with using the modified Wnn6 Client Library, Library or
 Executable Modules if they are known.

3.4  A User is permitted to incorporate the Wnn6 Client Library in whole
 or in part into another Software, although its license terms and
 conditions may be different from the License Agreement, if such
 incorporation or use associated with the incorporation does NOT violate
 the License Agreement.

Article 4. Warranty

THE WNN6 CLIENT LIBRARY IS PROVIDED BY OMRON ON AN "AS IS" BAISIS.
  OMRON EXPRESSLY DISLCIAMS ANY AND ALL WRRANTIES, EXPRESS OR IMPLIED,
 INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE, IN CONNECTION WITH THE WNN6 CLIENT LIBRARY
 OR THE USE OR OTHER DEALING IN THE WNN6 CLIENT LIBRARY.  IN NO EVENT
 SHALL OMRON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, PUNITIVE
 OR CONSEQUENTIAL DAMAGES OF ANY KIND WHATSOEVER IN CONNECTION WITH THE
 WNN6 CLIENT LIBRARY OR THE USE OR OTHER DEALING IN THE WNN6 CLIENT
LIBRARY.

***************************************************************************
Wnn6 Client Library :
(C) Copyright OMRON Corporation.       1995,1998,2000 all rights reserved.
(C) Copyright OMRON Software Co., Ltd. 1995,1998,2000 all rights reserved.

Wnn Software :
(C) Copyright Kyoto University Research Institute for Mathematical Sciences
     1987, 1988, 1989, 1990, 1991, 1992, 1993
(C) Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1993
(C) Copyright ASCTEC, Inc.  1987, 1988, 1989, 1990, 1991, 1992, 1993
***************************************************************************

Comments on Modifications:
*/

/**  cWnn  Version 1.1	 **/

#include  <stdio.h>
#include  <ctype.h>
#include  "commonhd.h"
#ifdef CHINESE
#ifdef SYSVR2
#include  <string.h>
#endif
#ifdef BSD42
#include  <strings.h>
#endif
#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 unsigned char *c;
register w_char *w;
{
    unsigned 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);
}

  	
/* 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(pzy_buf, c, 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 */
