/*
 * $Id: bdic.c,v 2.43.2.1 2000/08/04 05:37:02 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:
*/

/*	Version 4.0
 */
/*
  Binary (Updatable, Stable) dictionary common routine.
*/

#if defined(JS)
#ifdef WRITE_CHECK
#define BDIC_WRITE_CHECK
#endif /* WRITE_CHECK */
#endif /* JS */

#ifdef UX386
#include <X11/Xos.h>
#else
#include <sys/types.h>
#endif
#ifndef JS
#include <sys/stat.h>
#include <stdio.h>
#include "commonhd.h"
#include "jslib.h"
#include "jh.h"
#endif
#include "jdata.h"
#include "wnn_os.h"
#include "wnn_string.h"
#include "mt_jserver.h"

#ifdef JS
#ifndef BDIC_WRITE_CHECK
#define vputc(X, pt, args) putc((X), (pt))
#endif /* !BDIC_WRITE_CHECK */
#define vgetc(pt, args) getc(pt)
#else /* JS */
#define vputc(X, pt, args) putc((X), (pt))
#define vgetc(pt, args) getc(pt)
#endif /* JS */

#ifndef min
#define min(a, b) ((a > b)? b:a)
#define max(a, b) ((a < b)? b:a)
#endif

/*:::DOC_START
 *
 *    Function Name: dic_get_compressed_filename
 *    Description  : get compressed filename
 *    Parameter    :
 *         t_file:   		(Out) compressed filename
 *         file_name:     	(In) file_name
 *             caution:	file should be compressed;
 *
 *    Return value : file pointer for fopen-ed or popen-ed dictionary file
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         24-Nov-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
void
dic_get_compressed_filename(t_file, file_name )
char *t_file;
char *file_name;
{
 FILE *fp;
char mode_str[32];
/* check environment
i-file+ext    ""      ".gz"   ".Z"            ; one of any three
magic-of-file gz      Z       -               ; one of any three
prog          gz      Z       -
 */
   char t_file_ext [3][4];
      int magic_len [3];
      char magic [3][4];
      int pair_no;
      int i;
      FILE *ifpter2;
      FILE *pfpter2;
      char buf [1024];
      int num_read;

    strcpy(mode_str, "r");
    strcpy(&t_file_ext[0][0], ".gz");
    strcpy(&t_file_ext[1][0], ".Z");
    strcpy(&t_file_ext[2][0], ".Z");
    magic_len[0] = 2;
    magic_len[1] = 2;
    magic_len[2] = 2;
    strcpy(&magic[0][0], "\037\213\010");
    strcpy(&magic[1][0], "\037\235\220");
    strcpy(&magic[2][0], "\037\235\220");
/* open dic file with input mode */
 if((fp = fopen(file_name , mode_str)) == NULL){
    /* try for zipped dict */
   /* check pair */
      for(pair_no = -1, i=0; i<3; i++) {
   /* build compressed file name */
        strcpy(t_file, file_name );
        strcat(t_file, t_file_ext[i] );
   /* try to open it */
        ifpter2 = fopen(t_file , "r");
        pfpter2 = (FILE *) -1;
        if( (ifpter2 == NULL) ||
            (pfpter2 == NULL) ){
        } else {
          if( (num_read = fread(buf, 1, magic_len[i], ifpter2) ) == magic_len[i] ) {
            if( strncmp(buf, magic[i], magic_len[i]) == 0 ) {
            if(pair_no<0) pair_no = i;
            }
          }
        }
        if( ifpter2 ) fclose(ifpter2);
      }
      if(pair_no<0) {
        strcpy(t_file, "\0" );
	return ;
      }
   /* build compressed file name */
      strcpy(t_file, file_name );
      strcat(t_file, t_file_ext[pair_no] );
    } else {
   /* check pair */
      fclose(fp);
   /* build compressed file name */
      strcpy(t_file, file_name );
    }
 return ;
} /* End of dic_get_compressed_filename */

/*:::DOC_START
 *
 *    Function Name: dic_fopen
 *    Description  : open normal or compressed dictionary
 *    Parameter    :
 *         file_name:     	(In) file_name
 *         mode_str:     	(In) open mode
 *         p_is_compressed:   	(Out) indicate if compressed or not,
 *                                  used when close, !0: compressed;
 *
 *    Return value : file pointer for fopen-ed or popen-ed dictionary file
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
FILE *
dic_fopen(file_name, mode_str, p_is_compressed)
char *file_name;
char *mode_str;
int *p_is_compressed;
{
 FILE *fp;
 *p_is_compressed = 0;
 if( strcmp( mode_str, "r" ) ) {
   return fopen(file_name , mode_str);
 }
  {
/* check environment
i-file+ext    ""      ".gz"   ".Z"            ; one of any three
magic-of-file gz      Z       -               ; one of any three
prog          gz      Z       -
 */
    /* "1024" as file_name size should be not used, use
       "/usr/include/stdio.h:450:#define FILENAME_MAX    1024 ", but ... */
   char t_file [1024], cmd [1024];
   char t_file_ext [3][4];
   char cmd_b [3][40];
      int magic_len [3];
      char magic [3][4];
      int magic_len_max = 2;
      int magic_len_min = 2;
      int pair_no;
      int i;
      FILE *ifpter2;
      FILE *pfpter2;
      char buf [1024];
      int num_read;

    strcpy(&t_file_ext[0][0], ".gz");
    strcpy(&t_file_ext[1][0], ".Z");
    strcpy(&t_file_ext[2][0], ".Z");
    strcpy(&cmd_b[0][0], "gunzip -c");
    strcpy(&cmd_b[1][0], "uncompress -c");
    strcpy(&cmd_b[2][0], "uncompress -c");
    magic_len[0] = 2;
    magic_len[1] = 2;
    magic_len[2] = 2;
    strcpy(&magic[0][0], "\037\213\010");
    strcpy(&magic[1][0], "\037\235\220");
    strcpy(&magic[2][0], "\037\235\220");

/* open dic file with input mode */
 if((fp = fopen(file_name , mode_str)) == NULL){
    /* try for zipped dict */
   /* check pair */
      for(pair_no = -1, i=0; i<3; i++) {
   /* build compressed file name */
        strcpy(t_file, file_name );
        strcat(t_file, t_file_ext[i] );
   /* try to open it */
        ifpter2 = fopen(t_file , "r");
        pfpter2 = (FILE *) -1;
        if( (ifpter2 == NULL) ||
            (pfpter2 == NULL) ){
        } else {
          if( (num_read = fread(buf, 1, magic_len[i], ifpter2) ) == magic_len[i] ) {
            if( strncmp(buf, magic[i], magic_len[i]) == 0 ) {
            if(pair_no<0) pair_no = i;
            }
          }
        }
        if( ifpter2 ) fclose(ifpter2);
      }
      if(pair_no<0) {
	return NULL;
      }
   /* build compressed file name */
      strcpy(t_file, file_name );
      strcat(t_file, t_file_ext[pair_no] );
   /* try to open it */
      if((fp = fopen(t_file , "r")) == NULL){
	return NULL;
      }
      fclose(fp);
   /* build command and open */
      strcpy(cmd, cmd_b[pair_no] );
      strcat(cmd, t_file );
      if((fp = popen(cmd, "r")) == NULL){
	return NULL;
      }
      *p_is_compressed = 1;
    } else {
   /* check pair */
      if( (num_read = fread(buf, 1, magic_len_max, fp) ) > (magic_len_min-1) ) {
        for(pair_no = -1, i=0; i<3; i++) {
            if( strncmp(buf, magic[i], magic_len[i]) == 0 ) {
              if(pair_no<0) pair_no = i;
            }
        }
        if(pair_no<0) {
        } else {
          *p_is_compressed = 1;
        }
      } else {
      }
      fclose(fp);
      if(*p_is_compressed) {
   /* build command and open */
        if(pair_no == 0) {
        strcpy(cmd, cmd_b[pair_no] );
        strcat(cmd, file_name );
        } else {
        char *cmd_23a = "cat "; char *cmd_23b = " | uncompress -c -";
        strcpy(cmd, cmd_23a );
        strcat(cmd, file_name );
        strcat(cmd, cmd_23b );
        }
        if((fp = popen(cmd, "r")) == NULL){
	  return NULL;
        }
      } else {
        if((fp = fopen(file_name , "r")) == NULL){
	  return NULL;
        }
      }
    }
  }
 return fp;
} /* End of dic_fopen */

/*:::DOC_START
 *
 *    Function Name: dic_fclose
 *    Description  : close dictionary file
 *    Parameter    :
 *         fp:     	(In) file pointer for dictionary file
 *         is_compressed:     	(In) indicate if file is compressed or not
 *
 *    Return value : None.
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
void
dic_fclose(fp, is_compressed)
FILE *fp;
int is_compressed;
{
 if(fp==(FILE*)-1 || fp == NULL){
 } else {
   if(is_compressed) {
     pclose(fp);
   } else {
     fclose(fp);
   }
 }
} /* End of dic_fclose */

/*:::DOC_START
 *
 *    Function Name: cd_convert_yomi
 *    Description  : convert or dis-convert one w_char in yomi
 *    Parameter    :
 *         w_c:     	  (In) a w_char to be converted or dis-converted.
 *         deconvert:     (In) 0 specify convert, !0 specify dis-convert.
 *
 *    Return value : converted or dis-converted one w_char in yomi. or Null.
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
w_char
cd_convert_yomi(w_c, deconvert)
w_char w_c;
int deconvert;
{
int j;
/* data for conversion */
/* convert to ascii */
int cvt_tbl_size = 128-33-1; int cvt_tbl_offset = 33;
static w_char cvt_tbl[] = {
         0xa1aa, 0xa1af, 0xa1f4, 0xa1f0, 0xa1f3, 0xa1f5, 0xa1ad, /* 041 ! - ' */
 0xa1ca, 0xa1cb, 0xa1f6, 0xa1dc, 0xa1a4, 0xa1dd, 0xa1a5, 0xa1bf, /* 050 ( - / */
 0xa3b0, 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, /* 060 0 - 7 */
 0xa3b8, 0xa3b9, 0xa1a7, 0xa1a8, 0xa1e3, 0xa1e1, 0xa1e4, 0xa1a9, /* 070 8 - ? */
 0xa1f7, 0xa3c1, 0xa3c2, 0xa3c3, 0xa3c4, 0xa3c5, 0xa3c6, 0xa3c7, /* 100 @ - G */
 0xa3c8, 0xa3c9, 0xa3ca, 0xa3cb, 0xa3cc, 0xa3cd, 0xa3ce, 0xa3cf, /* 110 H - O */
 0xa3d0, 0xa3d1, 0xa3d2, 0xa3d3, 0xa3d4, 0xa3d5, 0xa3d6, 0xa3d7, /* 120 P - W */
 0xa3d8, 0xa3d9, 0xa3da, 0xa1ce, 0xa1ef, 0xa1cf, 0xa1b0, 0xa1b2, /* 130 X - _ */
 0xa1ae, 0xa3e1, 0xa3e2, 0xa3e3, 0xa3e4, 0xa3e5, 0xa3e6, 0xa3e7, /* 140 ` - g */
 0xa3e8, 0xa3e9, 0xa3ea, 0xa3eb, 0xa3ec, 0xa3ed, 0xa3ee, 0xa3ef, /* 150 h - o */
 0xa3f0, 0xa3f1, 0xa3f2, 0xa3f3, 0xa3f4, 0xa3f5, 0xa3f6, 0xa3f7, /* 160 p - w */
 0xa3f8, 0xa3f9, 0xa3fa, 0xa1d0, 0xa1c3, 0xa1d1, 0xa1b1,         /* 170 x - ~ */
};
int cvt_tbl2_size = 3; int cvt_tbl2_offset = 0;
static w_char cvt_tbl2[][2] = {
  { 0xa1bc, 0xf8, }, { 0xa5f4, 0xf9, }, { 0xa1ab, 0xfa, }, 
  /* 1/28 "ー" 5/84 "ヴ" unused f8, 1/x "゛" dakuten  */
};
    if( deconvert == 0 ) {
      if( w_c > 0x20 && w_c < 0x7f ) {
	/* already ascii, do nothing */
	return w_c;
      } else
	if( w_c > 0xa4a0 && w_c < 0xa4f4 ) {
	  /* "hiragana", re-move first byte */
	  return w_c&0xff;
	} else
	  if( w_c > 0xa5a0 && w_c < 0xa5f4 ) {
	    /* "katakana", print warning and re-move first byte */
	    return w_c&0xff;
	  } else {
	    for(j=0; j<cvt_tbl_size ; j++ ) {
	      if( w_c == cvt_tbl[j] ) {
		return j+cvt_tbl_offset;
	      }
	    }
	    for(j=0; j<cvt_tbl2_size ; j++ ) {
	      if( w_c == cvt_tbl2[j][0] ) {
		return cvt_tbl2[j][1]+cvt_tbl2_offset;
	      }
	    }
	    return 0;
	  }
    } else {
      if( w_c > 0x20 && w_c < 0x7f ) {
	/* convert to ascii */
	return cvt_tbl[w_c-cvt_tbl_offset];
      } else
	if( w_c > 0xa0 && w_c < 0xf4 ) {
	  /* "hiragana" or "katakana", insert first byte */
	  return w_c|0xa400;
	} else {
	  for(j=0; j<cvt_tbl2_size ; j++ ) {
	    if( (w_c-cvt_tbl2_offset) == cvt_tbl2[j][1] ) {
	      return cvt_tbl2[j][0];
	    }
	  }
	  return 0;
	}
    }
}

/*:::DOC_START
 *
 *    Function Name: dic_unlink
 *    Description  : unlink dictionary file
 *    Parameter    :
 *         file_name:     	(In) file_name
 *         is_compressed:   	(In) indicate if file is compressed or not
 *
 *    Return value : same as unlink()
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
int
dic_unlink(file_name, is_compressed)
char *file_name;
int is_compressed;
{
 if( is_compressed ) {
/* open dic file with input mode */
   /* try for zipped dict */
   char t_file [1024];
   /* build compressed file name */
      dic_get_compressed_filename(t_file, file_name );
   return unlink(t_file);
 } else {
   return unlink(file_name);
 }
} /* End of dic_unlink */

/*:::DOC_START
 *
 *    Function Name: dic_read_to_eof
 *    Description  : discard content of pipe
 *    Parameter    :
 *         fp:     	(In) file pointer for dictionary file
 *         is_compressed:     	(In) indicate if file is compressed or not
 *
 *    Return value : None.
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
void
dic_read_to_eof ( fp, is_compressed)
FILE * fp;
int is_compressed;
{
/* Implementation */
int num_read; int num_size = 512; unsigned char buf[512];
    if(is_compressed) {
      while( (num_read = fread(buf ,1,num_size,fp )) > 0 );
    }
} /* End of dic_read_to_eof */

#ifdef JS
static
#else
extern
#endif
int output_file_header(), input_file_uniq(), output_header_jt(),
#ifdef BDIC_WRITE_CHECK
  put_short(), output_file_uniq(),
#endif /* BDIC_WRITE_CHECK */
  create_file_header(), input_file_header(), change_file_uniq1(),
  output_header_hjt();

#ifdef JS
static
#else
extern
#endif
#ifdef BDIC_WRITE_CHECK
void new_pwd();
#else /* BDIC_WRITE_CHECK */
void put_short(), output_file_uniq(), new_pwd();
#endif /* BDIC_WRITE_CHECK */

#ifdef BDIC_WRITE_CHECK
static int
vputc(c, fp, args)
char c;
FILE *fp;
ARGS *args;
{
    if (fwrite(&c, sizeof(char), 1, fp) <= 0) return(-1);
    return(0);
}
#endif /* BDIC_WRITE_CHECK */

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
putnull(ofpter, n, args)
register FILE *ofpter;
register int n;
ARGS *args;
{
    for(;n;n--){
#ifdef BDIC_WRITE_CHECK
	if (vputc('\0', ofpter, args) == -1) return(-1);
#else /* BDIC_WRITE_CHECK */
	vputc('\0', ofpter, args);
#endif /* BDIC_WRITE_CHECK */
    }
#ifdef BDIC_WRITE_CHECK
    return(0);
#endif /* BDIC_WRITE_CHECK */
}

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
put_n_str(ofpter, c, n, args)
register FILE *ofpter;
register int n;
register char *c;
ARGS *args;
{
    for(;n;n--){
#ifdef BDIC_WRITE_CHECK
	if (vputc(*c++, ofpter, args) == -1) return(-1);
#else /* BDIC_WRITE_CHECK */
	vputc(*c++, ofpter, args);
#endif /* BDIC_WRITE_CHECK */
    }
#ifdef BDIC_WRITE_CHECK
    return(0);
#endif /* BDIC_WRITE_CHECK */
}  

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
put_n_EU_str(ofpter, c, n, args)
register FILE *ofpter;
register w_char *c;
register int n;
ARGS *args;
{
    for(;n;n--){
#ifdef BDIC_WRITE_CHECK
	if (put_short(ofpter, (int)(*c++), args) == -1) return(-1);
#else /* BDIC_WRITE_CHECK */
	put_short(ofpter, (int)(*c++), args);
#endif /* BDIC_WRITE_CHECK */
    }
#ifdef BDIC_WRITE_CHECK
    return(0);
#endif /* BDIC_WRITE_CHECK */
}

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
put_short(ofpter, i, args)
register FILE *ofpter;
register int i;
ARGS *args;
{
#ifdef BDIC_WRITE_CHECK
    if ((vputc(i >> 8, ofpter, args) == -1) ||
	(vputc(i     , ofpter, args) == -1)) return(-1);
    return(0);
#else /* BDIC_WRITE_CHECK */
    vputc(i >> 8, ofpter, args);
    vputc(i     , ofpter, args);
#endif /* BDIC_WRITE_CHECK */
}

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
putint(ofpter, i, args)
register FILE *ofpter;
register int i;
ARGS *args;
{
#ifdef BDIC_WRITE_CHECK
    if ((vputc(i >> 24, ofpter, args) == -1) ||
	(vputc(i >> 16, ofpter, args) == -1) ||
	(vputc(i >> 8 , ofpter, args) == -1) ||
	(vputc(i      , ofpter, args) == -1)) return(-1);
    return(0);
#else /* BDIC_WRITE_CHECK */
    vputc(i >> 24, ofpter, args);
    vputc(i >> 16, ofpter, args);
    vputc(i >> 8 , ofpter, args);
    vputc(i      , ofpter, args);
#endif /* BDIC_WRITE_CHECK */
}

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
put_n_int(ofpter, i, n, args)
register FILE *ofpter;
register int *i;
register int n;
ARGS *args;
{
#ifdef COPY_HINDO_IN

    for(;n;n--){
#ifdef BDIC_WRITE_CHECK
        if(putint(ofpter, (int)(*i++), args) == -1) return(-1);
#else /* BDIC_WRITE_CHECK */
        putint(ofpter, (int)(*i++), args);
#endif /* BDIC_WRITE_CHECK */
    }
#ifdef BDIC_WRITE_CHECK
    return(0);
#endif /* BDIC_WRITE_CHECK */

#else /* COPY_HINDO_IN */

#ifdef BDIC_WRITE_CHECK
    return(putnull(ofpter, n, args));
#else /* BDIC_WRITE_CHECK */
    putnull(ofpter, n, args);
#endif /* BDIC_WRITE_CHECK */

#endif /* COPY_HINDO_IN */
}

#ifdef JS
static
#endif
int
getnull(ifpter, n, args)
register FILE *ifpter;
register int n;
ARGS *args;
{
    register int k;
    
    for(;n;n--){
	k = vgetc(ifpter, args);
	if(k == -1)return(-1);
    }
    return(0);
}

#ifdef JS
static
#endif
int
getnstr(ifpter, n, st, args)
register FILE *ifpter;
register int n;
register char *st;
ARGS *args;
{
    int k;
    
    for(;n;n--){
	k = vgetc(ifpter, args);
	*st++ = k;
	if(k == -1)return(-1);
    }
    return(0);
}

#if	!defined(JS) && !defined(JSERVER)
int
get_n_EU_str(ifpter, n, st, args)
register FILE *ifpter;
register int n;
register w_char *st;
ARGS *args;
{
    register    int k;
    extern int get_short();
    
    for(;n;n--){
	k = get_short((short *)st++, ifpter, args);
	if(k == -1)return(-1);
    }
    return(0);
}

int
get_short(sp,ifpter, args)
register short *sp;
FILE *ifpter;
ARGS *args;
{
    register int i = 0;
    register int k;
    
    i |= (k = vgetc(ifpter, args)) << 8;
    if(k == -1)return(-1);
    i |= (k = vgetc(ifpter, args));
    if(k == -1)return(-1);
    *sp = i;
    return(0);
}
#endif

#ifdef JS
static
#endif
int
getint(ip,ifpter, args)
register FILE *ifpter;
int *ip;
ARGS *args;
{
    register int i = 0;
    register int k;
    
    i |= (k = vgetc(ifpter, args)) << 24;
    if(k == -1)return(-1);
    i |= (k = vgetc(ifpter, args)) << 16;
    if(k == -1)return(-1);
    i |= (k = vgetc(ifpter, args)) << 8;
    if(k == -1)return(-1);
    i |= (k = vgetc(ifpter, args));
    if(k == -1)return(-1);
    *ip = i;
    return(0);
}

#ifndef JS
void
udytoS(yomi,tnum,hostart,tary)
register w_char *yomi;
register int tnum;
char *hostart;
register struct uind1 *tary;
{
    struct uind2 *hop;
    int len;
    
    hop = (struct uind2 *)((char *)hostart + tary[tnum].pter);
    yomi[0] = tary[tnum].yomi1 >> 16;
    yomi[1] = tary[tnum].yomi1 & 0xffff;
    if(yomi[1]){
	yomi[2] = tary[tnum].yomi2 >> 16;
	if(yomi[2]){
	    yomi[3] = tary[tnum].yomi2 & 0xffff;
	}
    }
    len = hop->yomi[0];
    /*Strncpy(yomi + 4, (hop->yomi) + 1, len - 4);
      In order not to use ../etc/strings.c*/
    bcopy((char *)((hop->yomi) + 1), (char *)(yomi + 4),  max(0, ((len - 4)) * 2));
    yomi[len] = 0;
}
#endif

#ifdef BDIC_WRITE_CHECK
static char *
make_tmp_name(n, args)
char *n;
ARGS *args;
{
    static char buf[256];

    if (n == NULL || *n == '\0') return NULL;
    sprintf(buf, "%s~", n);
    return(buf);
}

static char *
make_backup_name(n, args)
char *n;
ARGS *args;
{
    static char buf[256];

    if (n == NULL || *n == '\0') return NULL;
    sprintf(buf, "%s#", n);
    return(buf);
}


#ifdef JS
static
#endif
void
check_backup(n, args)
char *n;
ARGS *args;
{
    char *p;

    if ((p = make_tmp_name(n, args)) && (access(p, F_OK) != -1)) unlink(p);
    if ((p = make_backup_name(n, args)) && (access(p, F_OK) != -1)) {
	unlink(n);
	link(p, n);
	unlink(p);
    }
}

static int
copy_file_to_file(from, to)
FILE *from, *to;
{
    char buf[1024];
    int r_len, w_len, i;

    for (;;) {
	r_len = fread(buf, 1, 1024, from);
	if (r_len <= 0) break;
	for ( i = 0; i < r_len; i += w_len) {
	    w_len = fwrite(&buf[i], 1, r_len - i, to);
	    if (w_len <= 0) {
		fseek(from, 0, 0);
		fseek(to, 0, 0);
		return(-1);
	    }
	    if (w_len >= r_len) break;
	}
    }
    fseek(from, 0, 0);
    fseek(to, 0, 0);
    return(0);
}

#ifdef JS
static
#endif
void
delete_tmp_file(n)
char *n;
{
    if (n && *n) unlink(n);
}

#ifdef JS
static
#endif
char *
make_backup_file(n, args)
char *n;
ARGS *args;
{
    FILE *fp, *fp2;
    char *p, *p2;

    if ((p = make_backup_name(n, args)) == NULL) return(NULL);
    if ((p2 = make_tmp_name(n, args)) == NULL) return(NULL);

    fp = fp2 = NULL;
    if (((fp = fopen(p2, "w+")) == NULL) || ((fp2 = fopen(n, "r")) == NULL)) {
	if(fp) fclose(fp);
	if(fp2) fclose(fp2);
	return NULL;
    }
    if (copy_file_to_file(fp2, fp) == -1) {
	fclose(fp);
	fclose(fp2);
	return(NULL);
    }
    fclose(fp);
    fclose(fp2);
    if (access(p, F_OK) != -1) unlink(p);
    link(p2, p);
    unlink(p2);
    return(p);
}

#ifdef JS
static
#endif
char *
make_tmp_file(n, copy, ret_fp, args)
char *n;
int copy;
FILE **ret_fp;
ARGS *args;
{
    FILE *fp, *fp2;
    struct wnn_file_head fh;
    char *p;

    p = make_tmp_name(n, args);
    if ((fp = fopen(p, "w+")) == NULL) {
	*ret_fp = NULL;
	return NULL;
    }
    if (copy && (fp2 = fopen(n, "r")) != NULL) {
	input_file_header(fp2, &fh, args);
	fseek(fp2, 0, 0);
	if ((copy_file_to_file(fp2, fp) == -1) ||
	    (create_file_header(fp, fh.file_type, fh.file_passwd, args) == -1)) {
	    fclose(fp);
	    fclose(fp2);
	    *ret_fp = NULL;
	    return NULL;
	}
	fseek(fp, 0, 0);
	fclose(fp2);
    }
    *ret_fp = fp;
    return p;
}

#ifdef JS
static
#endif
void
move_tmp_to_org(tmp_name, org_name, copy)
char *tmp_name, *org_name;
int copy;
{
    FILE *org, *tmp;

    org = tmp = NULL;

    if (copy) {
	if (((tmp = fopen(tmp_name, "r")) == NULL) ||
	    ((org = fopen(org_name, "w+")) == NULL)) {
	    if(tmp) fclose(tmp);
	    if(org) fclose(org);
	    return;
	}
	copy_file_to_file(tmp, org);
	fclose(tmp);
	fclose(org);
    } else {
	unlink(org_name);
	link(tmp_name, org_name);
    }
    unlink(tmp_name);
}
#endif /* BDIC_WRITE_CHECK */

#ifdef JS
static
#endif
int
set_file_header(fh, ofpter, file_type, file_passwd, args)
FILE *ofpter;
int file_type;
char *file_passwd;
ARGS *args;
    struct wnn_file_head *fh;
{
    struct stat buf;
    char hostname[WNN_HOSTLEN];

    if(fstat(fileno(ofpter), &buf) == -1){
        return(-1);
    }
    gethostname(hostname, WNN_HOSTLEN);
    hostname[WNN_HOSTLEN - 1] = '\0';

    fh->file_uniq.time = (int)buf.st_ctime;
    fh->file_uniq.dev = (int)buf.st_dev;
    fh->file_uniq.inode = (int)buf.st_ino;
    bzero(fh->file_uniq.createhost, WNN_HOSTLEN);
    strcpy(fh->file_uniq.createhost, hostname);
    
    /* file_uniq_org */
    fh->file_uniq_org.time = (int)buf.st_ctime;
    fh->file_uniq_org.dev = (int)buf.st_dev;
    fh->file_uniq_org.inode = (int)buf.st_ino;
    bzero(fh->file_uniq_org.createhost, WNN_HOSTLEN);
    strcpy(fh->file_uniq_org.createhost, hostname);

    fh->file_type = file_type;
    if(file_passwd){
        strncpy(fh->file_passwd, file_passwd, WNN_PASSWD_LEN);
    }else{
        bzero(fh->file_passwd, WNN_PASSWD_LEN);
    }
    return(0);
}

#ifdef JS
static
#endif
int
create_file_header(ofpter, file_type, file_passwd, args)
FILE *ofpter;
int file_type;
char *file_passwd;
ARGS *args;
{
    struct wnn_file_head fh;
    if(set_file_header(&fh, ofpter, file_type, file_passwd, args) == -1) return(-1);
    if(output_file_header(ofpter, &fh, args) == -1) return(-1);
    return(0);
}

/* 128 Bytes File Header */

#ifdef JS
static
#endif
int
output_file_header(ofpter, hp, args)
FILE *ofpter;
struct wnn_file_head *hp;
ARGS *args;
{
#ifdef BDIC_WRITE_CHECK
    if ((put_n_str(ofpter, WNN_FILE_STRING, WNN_FILE_STRING_LEN, args) == -1) ||
	(putint(ofpter, hp->file_type, args) == -1) ||
	(output_file_uniq(&hp->file_uniq, ofpter, args) == -1) ||
	(output_file_uniq(&hp->file_uniq_org, ofpter, args) == -1) ||
	(put_n_str(ofpter, hp->file_passwd, WNN_PASSWD_LEN, args) == -1) ||
	(putnull(ofpter, 36, args) == -1)) return(-1);		/* Future Use */
#else /* BDIC_WRITE_CHECK */
    put_n_str(ofpter, WNN_FILE_STRING, WNN_FILE_STRING_LEN, args);
    putint(ofpter, hp->file_type, args);
    output_file_uniq(&hp->file_uniq, ofpter, args);
    output_file_uniq(&hp->file_uniq_org, ofpter, args);
    put_n_str(ofpter, hp->file_passwd, WNN_PASSWD_LEN, args);
    putnull(ofpter, 36, args);		/* Future Use */
#endif /* BDIC_WRITE_CHECK */
    return(0);
}

#ifdef JS
static
#endif
int
input_file_header(ifpter, hp, args)
FILE *ifpter;
struct wnn_file_head *hp;
ARGS *args;
{

    char wnn_file_string[WNN_FILE_STRING_LEN + 1];
    int err = 0;
    
    getnstr(ifpter, WNN_FILE_STRING_LEN, wnn_file_string, args);
    if(strncmp(wnn_file_string, WNN_FILE_STRING, WNN_FILE_STRING_LEN))
	err = -1;
    if(getint((&hp->file_type), ifpter, args) == -1) err = -1;
    if(input_file_uniq(&(hp->file_uniq), ifpter, args) == -1) err = -1;
    if(input_file_uniq(&(hp->file_uniq_org), ifpter, args) == -1) err = -1;
    getnstr(ifpter, WNN_PASSWD_LEN, hp->file_passwd, args);
    getnull(ifpter, 36, args);
    return(err);
}

#ifdef JS
static
#endif
#ifdef BDIC_WRITE_CHECK
int
#else /* BDIC_WRITE_CHECK */
void
#endif /* BDIC_WRITE_CHECK */
output_file_uniq(funiq, ofpter, args)
struct wnn_file_uniq *funiq;
FILE *ofpter;
ARGS *args;
{
#ifdef BDIC_WRITE_CHECK
    if ((putint(ofpter, funiq->time, args) == -1) ||
	(putint(ofpter, funiq->dev, args) == -1) ||
	(putint(ofpter, funiq->inode, args) == -1) ||
	(put_n_str(ofpter, funiq->createhost,
		   strlen(funiq->createhost), args) == -1) ||
	(putnull(ofpter, WNN_HOSTLEN - strlen(funiq->createhost), args) == -1))
	return(-1);
    return(0);
#else /* BDIC_WRITE_CHECK */
    putint(ofpter, funiq->time, args);
    putint(ofpter, funiq->dev, args);
    putint(ofpter, funiq->inode, args);
    put_n_str(ofpter, funiq->createhost, strlen(funiq->createhost), args);
    putnull(ofpter, WNN_HOSTLEN - strlen(funiq->createhost), args);
#endif /* BDIC_WRITE_CHECK */
}

#ifdef JS
static
#endif
int
input_file_uniq(funiq, ifpter, args)
struct wnn_file_uniq *funiq;
FILE *ifpter;
ARGS *args;
{
    if(
       getint(&(funiq->time), ifpter, args) == -1 ||
       getint(&(funiq->dev), ifpter, args) == -1 ||
       getint(&(funiq->inode), ifpter, args) == -1 ||
       getnstr(ifpter, WNN_HOSTLEN, funiq->createhost, args) == -1)
	return(-1);
    return(0);
}

#ifdef JS
static
#endif
int
check_inode(f, fh)
FILE *f;
struct wnn_file_head *fh;
{
    struct stat buf;
    if(fstat(fileno(f), &buf) == -1){
	return(-1);
    }
    if((int)buf.st_ino != fh->file_uniq.inode){
	return(-1);
    }
    return(0);
}
/*:::DOC_START
 *
 *    Function Name: dic_check_inode
 *    Description  : check i-node of file
 *    Parameter    :
 *         f:           (In) file pointer for dictionary file
 *         fh:          (In) file header
 *         file_name:   (In) file_name
 *         is_compressed:       (In) indicate if file is compressed or not
 *
 *    Return value : check result, 0: same, -1: different
 *                   (same as check_inode()), always same if file is compressed
 *
 *    Author      :  fujimori
 *
 *    Revision history:
 *         22-Sep-94: fujimori: initial
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
int
dic_check_inode(f, fh, file_name, is_compressed)
FILE *f;
struct wnn_file_head *fh;
char *file_name;
int is_compressed;
{
/* Implementation */
  FILE *fp;
  if(is_compressed == 0){
    return(check_inode(f, fh));
  } else {
    struct stat buf;
/* open dic file with input mode */
    /* try for zipped dict */
    /* "1024" as file_name size should be not used, use
       "/usr/include/stdio.h:450:#define FILENAME_MAX    1024 ", but ... */
    char t_file [1024];
   /* build compressed file name */
    dic_get_compressed_filename(t_file, file_name );
   /* try to open it */
    if((fp = fopen(t_file , "r")) == NULL){
	return (-1);
    }
    if(fstat(fileno(fp), &buf) == -1){
	fclose(fp);
	return(-1);
    }
    if((int)buf.st_ino != fh->file_uniq.inode){
    }
    fclose(fp);
    return(0);
  }
} /* End of dic_check_inode */

#ifdef JS
static
#endif
int
change_file_uniq(fh, n, args)
struct wnn_file_head *fh;
char *n;
ARGS *args;
{
    int x;
    FILE *fp;
#ifdef BDIC_WRITE_CHECK
    char *tmp, *backup = NULL;
    backup = make_backup_file(n, args);
    if ((tmp = make_tmp_file(n, 1, &fp, args)) == NULL) {
	delete_tmp_file(backup);
#else /* BDIC_WRITE_CHECK */
    if((fp = fopen(n,"r+")) == NULL){
#endif /* BDIC_WRITE_CHECK */
	return(-1);
    }
    /* file_uniq_org は変更しない */	
#ifdef BDIC_WRITE_CHECK
    if (change_file_uniq1(fp, fh->file_type, fh->file_passwd, &(fh->file_uniq_org), args) == -1) {
	fclose(fp);
	delete_tmp_file(tmp);
	delete_tmp_file(backup);
	return(-1);
    }
#else /* BDIC_WRITE_CHECK */
    change_file_uniq1(fp, fh->file_type, fh->file_passwd, &(fh->file_uniq_org), args);
#endif /* BDIC_WRITE_CHECK */
    fseek(fp, 0, 0);
    x = input_file_header(fp, fh, args);/* It must not occur. */
    fclose(fp);
#ifdef BDIC_WRITE_CHECK
    if(x == -1) {
	delete_tmp_file(tmp);
	delete_tmp_file(backup);
	return(-1); 
    }
    move_tmp_to_org(tmp, n, 0);
    delete_tmp_file(backup);
#else /* BDIC_WRITE_CHECK */
    if(x == -1) return(-1);
#endif /* BDIC_WRITE_CHECK */
    return(0);
}    

#ifdef JS
static
#endif
int
change_file_uniq1(ofpter, file_type, file_passwd, file_uniq, args)
FILE *ofpter;
int file_type;
char *file_passwd;
struct wnn_file_uniq *file_uniq;
ARGS *args;
{
    struct stat buf;
    char hostname[WNN_HOSTLEN];
    struct wnn_file_head fh;

    if(fstat(fileno(ofpter), &buf) == -1){
	return(-1);
    }
    gethostname(hostname, WNN_HOSTLEN);
    hostname[WNN_HOSTLEN - 1] = '\0';

    fh.file_uniq.time = (int)buf.st_ctime;
    fh.file_uniq.dev = (int)buf.st_dev;
    fh.file_uniq.inode = (int)buf.st_ino;
    bzero(fh.file_uniq.createhost, WNN_HOSTLEN);
    strcpy(fh.file_uniq.createhost, hostname);
    
    /* file_uniq_org */
    fh.file_uniq_org.time = file_uniq->time;
    fh.file_uniq_org.dev = file_uniq->dev;
    fh.file_uniq_org.inode = file_uniq->inode;
    bzero(fh.file_uniq_org.createhost, WNN_HOSTLEN);
    strcpy(fh.file_uniq_org.createhost, file_uniq->createhost);

    fh.file_type = file_type;
    if(file_passwd){
	strncpy(fh.file_passwd, file_passwd, WNN_PASSWD_LEN);
    }else{
	bzero(fh.file_passwd, WNN_PASSWD_LEN);
    }
    if(output_file_header(ofpter, &fh, args) == -1) return(-1);
    return(0);
}




#if	!defined(JS) && !defined(JSERVER)
void
vputs(c, fp, args)
register char *c;
register FILE *fp;
ARGS *args;
{
    while(*c){
	vputc(*c++, fp, args);
    }
}

int
vputws(w, fp, args)
register w_char *w;
register FILE *fp;
ARGS *args;
{
    register int n;
    UCHAR tmp[LENGTHYOMI*3];
    
    n = wnn_sStrcpy(tmp, w);
    vputs(tmp, fp, args);
    return(n);
}
#endif


extern char *wnn_get_hinsi_name();

#if	!defined(JS) && !defined(JSERVER)
int
put_yomi_str(yomi, ofpter, args)
w_char *yomi;
FILE *ofpter;
ARGS *args;
{
    register int c;
    register int i = 0;
    UCHAR tmp[LENGTHYOMI*3], *p;

    wnn_sStrcpy(tmp, yomi);
    for(p = tmp;*p;p++){
	c = (int)*p;
	if(c == '\\'){
	    vputc('\\', ofpter, args);
	    vputc('\\', ofpter, args);
	    i += 2;
	}else if(c > 0x20){
	    vputc(c, ofpter, args);
	    i += 1;
	}else{
	    char tmp[8];
	    sprintf(tmp , "\\0%o" , c);
	    vputs(tmp, ofpter, args);
	    i += strlen(tmp);
	}
    }
    return(i);
}
#endif

#ifndef JS
/*:::DOC_START
 *
 *    Function Name: Get_knj2
 *    Description  : get KOUHO string , YOMI string and comment string from 
 *                   "kptr" with "kanji2" offset
 *    Parameter    :
 *         kptr:     (In) wchar pointer of those strings
 *         kanji2:   (In) offset of terget entry. 上記、ポインターの
 *                        何番め先の候補・読み・コメントのストリングを得たいかを指定する。
 *                         0: jentptrそのもの。
 *                         1: 次
 *                         .
 *                         n: n番目
 *         kouho:    (Out) return of the HOUHO(候補) string
 *         yomi:     (Out) return of the YOMI(読み) string
 *         com:      (Out) return of the comment string
 *
 *    Return value :  None.
 *
 *    Author      :  Masaki Harima
 *
 *    Revision history:
 *         31-AUG-94: harima:  just wrote this comment. no changes souces
 *
 *:::DOC_END
 */
void
Get_knj2(kptr,kanji2, kouho, yomi, comment)
UCHAR *kptr;
int kanji2;
w_char *kouho, *comment, *yomi;
{
	extern void get_kanji_str();

	int tcnt;
	for (tcnt = 0; tcnt < kanji2; tcnt++){
		kptr += *kptr;
	}
	get_kanji_str(kptr, kouho, yomi, comment);
	return;
}

static void
copy_kanji_str_from_cd(kptr, kanji)
UCHAR *kptr;
w_char *kanji;
{
    int n , k;
    n = *kptr++ - 1;
    for(k = 0 ; k < n ;) {
	    if(kanji) *kanji++ = ((int) *kptr << 8 | *(kptr + 1));
	    kptr += 2;
	    k+= 2;
    }
    if(kanji)*kanji = 0;
}

void
get_kanji_str(kptr, kanji, yomi, comment)
UCHAR *kptr;
w_char *kanji, *comment, *yomi;
{
    w_char *tmpy;
    w_char *tmpk;
    w_char *tmpc;
    extern void Get_kanji_str_r();

    /* 漢字・読み・コメント情報を初期化 */
    if(kanji) kanji[0] = (w_char)0;
    if(yomi) yomi[0] = (w_char)0;
    if(comment) comment[0] = (w_char)0;

/* CAUTION: jisho syurui is not checked, but ... */
/* not compact dictionary case */
  if( (((int) (*kptr)) % 2 ) == 0){
    Get_kanji_str_r(kptr, &tmpk, &tmpy, &tmpc);

#ifdef CONVERT_from_TOP /* Don't warry. Only use in server and jutil */
    if(kanji && tmpk)wnn_Strcpy(kanji, tmpk);
    if(yomi && tmpy)wnn_Strcpy(yomi, tmpy);
#else	/* conver from bottom */
    if(kanji && tmpk)wnn_Sreverse(kanji, tmpk);
    if(yomi && tmpy)wnn_Sreverse(yomi, tmpy);
#endif	/* CONVERT_from_TOP */
    if(comment && tmpc)wnn_Strcpy(comment, tmpc);
  }else{
    w_char *c;
    w_char tmpk_dt[LENGTHKANJI];
    c = tmpk = &tmpk_dt[0];
    copy_kanji_str_from_cd(kptr, c);
#ifdef CONVERT_from_TOP /* Don't warry. Only use in server and jutil */
    if(kanji && tmpk)wnn_Strcpy(kanji, tmpk);
#else	/* conver from bottom */
    if(kanji && tmpk)wnn_Sreverse(kanji, tmpk);
#endif	/* CONVERT_from_TOP */
  }
}

/* ?? need doc. CAUTION: *tmpk is IO */
void
Get_kanji_str_r_cd (kptr, tmpk, tmpy, tmpc)
UCHAR *kptr;
w_char **tmpk, **tmpy, **tmpc;
{
/* CAUTION: jisho syurui is not checked, but ... */
/* not compact dictionary case */
  if( (((int) (*kptr)) % 2 ) == 0){
        printf("Get_kanji_str_r_cd: do not call me for non-compact dictionary.\n" );
  }else{
/* compact dictionary case */
  }
    copy_kanji_str_from_cd(kptr, *tmpk);
}

void
Get_kanji_str_r(kptr, tmpk, tmpy, tmpc)
UCHAR *kptr;
w_char **tmpk, **tmpy, **tmpc;
{
    int state = *(kptr + 1);
    static w_char dmy = 0; /* Must not be allocated on Stack!! */
    int adres;

/* CAUTION: jisho syurui is not checked, but ... */
/* not compact dictionary case */
  if( (((int) (*kptr)) % 2 ) == 0){
  }else{
/* compact dictionary case */
        printf("Get_kanji_str_r: do not call me for compact dictionary.\n" );
  }
    if(state & FORWARDED){
	/* Forward occures when comment-set is used */
	adres = (*(w_char *)(kptr + 2)) << 16 | (*(w_char *)(kptr + 4));
	Get_kanji_str_r(kptr + adres, tmpk, tmpy, tmpc);
	return;
    }
/*    get_kanji_str_r(kptr, tmpk, tmpy, comment); */
    if(state & HAS_YOMI){
	*tmpy = ((w_char *)(kptr + 2));
	*tmpk = *tmpy + wnn_Strlen(*tmpy) + 1;
    }else{
	*tmpy = &dmy;
	*tmpk = ((w_char *)(kptr + 2));
    }
    if(state & HAS_COMMENT){
	*tmpc = *tmpk + wnn_Strlen(*tmpk) + 1;
    }else{
	*tmpc = &dmy;
    }
}


UCHAR
kanjiaddr(d0, kanji, yomi, comment)
UCHAR *d0;
w_char *kanji, *yomi, *comment;
{
    w_char *dest = (w_char *)(d0 + 2);
    int state = 0;
    w_char *pt;

    if(yomi && *yomi){
#ifdef CONVERT_from_TOP /* Don't warry. Only use in server and jutil */
        pt = yomi;
        for(;*pt;){
            *dest++ = *pt++;
        } 
#else	/* conver from bottom */
	pt = yomi + wnn_Strlen(yomi) - 1;
	for(;pt >= yomi;){
	    *dest++ = *pt--;
	}
#endif /* CONVERT_from_TOP */
	state |= HAS_YOMI;
	*dest++ = 0;
    }

#ifdef CONVERT_from_TOP /* Don't warry. Only use in server and jutil */
    pt = kanji;
    for(;*pt;){
            *dest++ = *pt++;
        } 
#else	/* conver from bottom */
    pt = kanji + wnn_Strlen(kanji) - 1;
    for(;pt >= kanji;){
	*dest++ = *pt--;
    }
#endif /* CONVERT_from_TOP */
    *dest++ = 0;

    if(comment && *comment){
	pt = comment;
	for(;*pt;){
	    *dest++ = *pt++;
	}
	state |= HAS_COMMENT;
	*dest++ = 0;
    }
    *d0 = (UCHAR)((UCHAR *)dest - d0);
    *(d0 + 1) = state;
    return(*d0);
}	

#endif


/*:::DOC_START
 *
 *    Function Name: create_null_dic
 *    Description  : 辞書ファイルを作成する
 *    Parameter    :
 *         fn :      (In) 作成辞書ファイル名
 *         comm :    (In) 作成辞書ファイルコメント
 *         passwd    (In) 作成辞書ファイルパスワード
 *         hpasswd : (In) 作成辞書内頻度パスワード
 *         which :   (In) 作成辞書ファイルタイプ
 *	   args :    (InOut) スレッド管理用構造体へのポインタ
 *
 *    Return value : 0==SUCCESS, -1==ERROR
 *
 *    Author      :  Hideyuki Kishiba
 *
 *    Revision history:
 *
 *:::DOC_END
 */
#ifdef JS
static
#endif
int
create_null_dic(fn, comm, passwd, hpasswd, which, args)
char  *fn;
w_char *comm;
char *passwd, *hpasswd;  /* not encoded passwd */
int which;
ARGS *args;
{
    FILE *fp;
    struct JT jt;
    char epasswd[WNN_PASSWD_LEN];
    extern void new_pwd();

    /* マージ辞書にはシステム辞書マスクを立てる */
    if(which == WNN_MERGE_DICT) which |= WNN_SYSTEM_DICT;

    jt.total = 0;
    jt.gosuu = 0;
    if(hpasswd){
	new_pwd(hpasswd, jt.hpasswd);
    }else{
	bzero(jt.hpasswd, WNN_PASSWD_LEN);
    }
    jt.syurui = which;
    jt.maxserial = 0;
    jt.maxtable = 0;
    jt.maxhontai = (which == WNN_UD_DICT)? 4: 0;
    jt.maxkanji = 0;
    if(comm){
	jt.maxcomment = wnn_Strlen(comm);
    }else{
	jt.maxcomment = 0;
    }
    jt.maxhinsi_list = 0;
    jt.maxri1[D_YOMI] = 0;
    jt.maxri1[D_KANJI] = 0;
    jt.maxri2 = 0;

    if((fp = fopen(fn, "w+")) == NULL){
	/*	error1( "Jserver:create_null_ud:No file %s.\n", fn); */
	return(-1);
    }
    if(passwd){
	new_pwd(passwd, epasswd);
    }else{
	bzero(epasswd, WNN_PASSWD_LEN);
    }
    if(create_file_header(fp, WNN_FT_DICT_FILE,epasswd, args) == -1 ||
       output_header_jt(fp, &jt, args) == -1){
	fclose(fp);return(-1);
    }
#ifdef BDIC_WRITE_CHECK
    if (put_n_EU_str(fp, comm, jt.maxcomment, args) == -1) {
	fclose(fp);
	return(-1);
    }
#else /* BDIC_WRITE_CHECK */
    put_n_EU_str(fp, comm, jt.maxcomment, args);
#endif /* BDIC_WRITE_CHECK */
    if(which == WNN_UD_DICT){
#ifdef BDIC_WRITE_CHECK
	if (putint(fp, 0, args) == -1) {	/* hontai[0] */
	    fclose(fp);
	    return(-1);
	}
#else /* BDIC_WRITE_CHECK */
	putint(fp, 0, args);			/* hontai[0] */
#endif /* BDIC_WRITE_CHECK */
    }

#ifdef	BSD42
    fchmod(fileno(fp), 0664);
    fclose(fp);
#else	/* SYSV */
    fclose(fp);
    chmod(fn, 0664);
#endif	/* BSD42 */
    return(0);
} /* End of create_null_dic */


#ifdef JS
static
#endif
int
create_hindo_file(funiq, fn, comm, passwd, serial, hindo_in, args)
struct wnn_file_uniq *funiq;
char *fn;
w_char *comm;
char *passwd;			/* Not encoded */
int serial;
int *hindo_in;
ARGS *args;
{
    FILE *fp;
    struct HJT hjt;
    char epasswd[WNN_PASSWD_LEN];
    w_char tmp[1];
    int i;

    tmp[0] = 0;
    if(comm == NULL) comm = tmp;
    bcopy(funiq, &(hjt.dic_file_uniq), WNN_F_UNIQ_LEN);
    hjt.maxcomment = wnn_Strlen(comm);
    
    hjt.maxserial = serial;
    hjt.hindo_area = (int)((serial + MAX_HINDO_DATA_AREA - 1) / MAX_HINDO_DATA_AREA);
    if(hjt.hindo_area != 0) {
	if((hjt.curserial = (unsigned char *)
	        malloc(hjt.hindo_area * sizeof(unsigned char))) == NULL)
            return(-1);
	for(i = 0; i < hjt.hindo_area; i++) (hjt.curserial)[i] = 0;
    } else
        hjt.curserial = NULL;

    if((fp = fopen(fn, "w+")) == NULL){
	return(-1);
    }
    if(passwd){
	new_pwd(passwd, epasswd);
    }else{
	bzero(epasswd, WNN_PASSWD_LEN);
    }
    if(create_file_header(fp, WNN_FT_HINDO_FILE, epasswd, args) == -1){fclose(fp);return(-1);}
#ifdef BDIC_WRITE_CHECK
    if ((output_header_hjt(fp, &hjt, args) == -1) ||
	(put_n_EU_str(fp, comm, hjt.maxcomment, args) == -1) ||
	(put_n_int(fp, hindo_in, 0, args) == -1)) {
	fclose(fp);
	return(-1);
    }
#else /* BDIC_WRITE_CHECK */
    output_header_hjt(fp, &hjt, args);
    put_n_EU_str(fp, comm, hjt.maxcomment, args);
    put_n_int(fp, hindo_in, 0, args);
#endif /* BDIC_WRITE_CHECK */

#ifdef	BSD42
    fchmod(fileno(fp), 0664);
    fclose(fp);
#else	/* SYSV */
    fclose(fp);
    chmod(fn, 0664);
#endif	/* BSD42 */
    return(0);
}

/* Header Total 128 Bytes */

#ifndef	JS
int
input_header_jt(ifpter, jt1, args)
FILE *ifpter;
struct JT *jt1;
ARGS *args;
{
    if(
       getint(&jt1->syurui , ifpter, args) == -1 ||
       getint(&jt1->maxcomment, ifpter, args) == -1 ||
       getint(&jt1->maxhinsi_list, ifpter, args) == -1 ||
       getint(&jt1->maxserial , ifpter, args) == -1 ||
       getint(&jt1->maxkanji , ifpter, args) == -1 ||
       getint(&jt1->maxtable , ifpter, args) == -1 ||
       getint(&jt1->maxhontai , ifpter, args) == -1 ||
       getint(&jt1->gosuu , ifpter, args) == -1 ||
       getnstr(ifpter, WNN_PASSWD_LEN, jt1->hpasswd, args) == -1 ||
       getint(&jt1->total , ifpter, args) == -1 ||
       getint(&jt1->maxri1[D_YOMI] , ifpter, args) == -1 ||
       getint(&jt1->maxri1[D_KANJI] , ifpter, args) == -1 ||
       getint(&jt1->maxri2, ifpter, args) == -1 ||
       getnull(ifpter, 56, args) == -1)
	return(-1);
    return(0);
}
#endif

#ifdef JS
static
#endif
int
output_header_jt(ofpter, jt1, args)
FILE *ofpter;
struct JT *jt1;
ARGS *args;
{
#ifdef BDIC_WRITE_CHECK
    if ((putint(ofpter, jt1->syurui, args) == -1) ||
	(putint(ofpter, jt1->maxcomment, args) == -1) ||
	(putint(ofpter,  jt1->maxhinsi_list, args) == -1) ||
	(putint(ofpter, jt1->maxserial, args) == -1) ||
	(putint(ofpter, jt1->maxkanji, args) == -1) ||
	(putint(ofpter, jt1->maxtable, args) == -1) ||
	(putint(ofpter, jt1->maxhontai, args) == -1) ||
	(putint(ofpter, jt1->gosuu, args) == -1) ||
	(put_n_str(ofpter, jt1->hpasswd, WNN_PASSWD_LEN, args) == -1) ||
	(putint(ofpter, jt1->total, args) == -1) ||
	(putint(ofpter, jt1->maxri1[D_YOMI], args) == -1) ||
	(putint(ofpter, jt1->maxri1[D_KANJI], args) == -1) ||
	(putint(ofpter, jt1->maxri2, args) == -1) ||
	(putnull(ofpter, 56, args) == -1)) return(-1);
#else /* BDIC_WRITE_CHECK */
    putint(ofpter, jt1->syurui, args);
    putint(ofpter, jt1->maxcomment, args);
    putint(ofpter,  jt1->maxhinsi_list, args);
    putint(ofpter, jt1->maxserial, args);
    putint(ofpter, jt1->maxkanji, args);
    putint(ofpter, jt1->maxtable, args);
    putint(ofpter, jt1->maxhontai, args);
    putint(ofpter, jt1->gosuu, args);
    put_n_str(ofpter, jt1->hpasswd, WNN_PASSWD_LEN, args);
    putint(ofpter, jt1->total, args);
    putint(ofpter, jt1->maxri1[D_YOMI], args);
    putint(ofpter, jt1->maxri1[D_KANJI], args);
    putint(ofpter, jt1->maxri2, args);
    putnull(ofpter, 56, args);
#endif /* BDIC_WRITE_CHECK */
    return(0);
}

/* Header 64 Byte */
#ifndef	JS
int
input_header_hjt(ifpter, hjt1, args)
FILE *ifpter;
struct HJT *hjt1;
ARGS *args;
{
    int i;
    if(
       input_file_uniq(&hjt1->dic_file_uniq, ifpter, args) == -1 ||  /* 7 * 4 */
       getint(&hjt1->maxcomment, ifpter, args) == -1 ||
       getint(&hjt1->maxserial, ifpter, args) == -1) return(-1);

    if(getint(&hjt1->hindo_area, ifpter, args) == -1)
        return(-1);
    if(hjt1->hindo_area != 0) {
	if((hjt1->curserial = (unsigned char *)
	        malloc(hjt1->hindo_area * sizeof(unsigned char))) == NULL)
            return(-1);
	for(i = 0; i < hjt1->hindo_area; i++)
	    (hjt1->curserial)[i] = vgetc(ifpter, args);
    } else
        hjt1->curserial = NULL;

    return(0);
}
#endif

#ifdef JS
static
#endif
int
output_header_hjt(ofpter, hjt1, args)
FILE *ofpter;
struct HJT *hjt1;
ARGS *args;
{
    int i;
#ifdef BDIC_WRITE_CHECK
    if ((output_file_uniq(&hjt1->dic_file_uniq, ofpter, args) == -1) ||
	(putint(ofpter, hjt1->maxcomment, args) == -1) ||
	(putint(ofpter, hjt1->maxserial, args) == -1) ||
	(putint(ofpter, hjt1->hindo_area, args) == -1)) return(-1);
    for(i = 0; i < hjt1->hindo_area; i++) {
	if(vputc((hjt1->curserial)[i], ofpter, args) == -1) return(-1);
    }
#else /* BDIC_WRITE_CHECK */
    output_file_uniq(&hjt1->dic_file_uniq, ofpter, args);
    putint(ofpter, hjt1->maxcomment, args);
    putint(ofpter, hjt1->maxserial, args);
    putint(ofpter, hjt1->hindo_area, args);
    for(i = 0; i < hjt1->hindo_area; i++)
        vputc((hjt1->curserial)[i], ofpter, args);
#endif /* BDIC_WRITE_CHECK */
    return(0);
}


#if	!defined(JS) && !defined(JSERVER)
/* Only use JUTIL */
void
Print_entry(yomi, kstr, cstr, hindo, ima, hinsi, serial, ofpter, esc_exp, args)
w_char *yomi, *kstr,*cstr;
int serial, hindo, ima, hinsi;
FILE *ofpter;
int esc_exp;
ARGS *args;
{
    register int len;
    char *k;
    char buf[32];
    static w_char revy[LENGTHKANJI];
    extern void kanji_esc_str();
    
    if ((yomi == 0) || (kstr == 0))
	return;

    if(serial != -1){
	sprintf(buf, "%d\t", serial);
	vputs(buf, ofpter, args);
    }

    len = put_yomi_str(yomi, ofpter, args);
    if(len < 8)vputc('\t' , ofpter, args);
    if(len < 16)vputc('\t' , ofpter, args);
    vputc('\t' , ofpter, args);
    
    if(esc_exp){
#ifdef CONVERT_from_TOP /* Don't warry. Only use in jutil */
	wnn_Strcpy(revy, yomi);
#else	/* conver from bottom */
	wnn_Sreverse(revy, yomi);
#endif /* CONVERT_from_TOP */
        kanji_esc_str(kstr, revy, wnn_Strlen(yomi), args);
        len = put_yomi_str(kstr, ofpter, args);
    }else{
        len = vputws(kstr, ofpter, args); 
    }
    if(len < 8)vputc('\t' , ofpter, args);
    if(len < 16)vputc('\t' , ofpter, args);
    vputc('\t' , ofpter, args);
    
    k = wnn_get_hinsi_name(hinsi, args);
    if(k){
        vputs(k, ofpter, args);
        if((int)strlen(k) < 8)vputc('\t' , ofpter, args);
        vputc('\t' , ofpter, args);
    }else{
        sprintf(buf, "%d\t\t", hinsi);
        vputs(buf, ofpter, args);
    }

    if(ima) vputc('*', ofpter, args);
    if(hindo == -1){    /*  Real hindo == -1 means Not to use it */
        vputs("-", ofpter, args);
    }else{
        sprintf(buf, "%d", hindo);
        vputs(buf, ofpter, args);
    }
    if(cstr && cstr[0]){
        vputc('\t', ofpter, args);
        len = vputws(cstr, ofpter, args); 
    }
    vputc('\n', ofpter, args);
}
#endif

    
#ifdef BDIC_WRITE_CHECK
#undef BDIC_WRITE_CHECK
#endif

