/*=============================================================================
		wtkf.c
			by Nobuyuki SHIRAKI
			Last change : Tue  5 February 2002   0:38:16
=============================================================================*/


#include	"wtkf.h"

unsigned char	*wtkf_setstring(unsigned char *);


/*-----------------------------------------------------------------------------
		KANJI code Functions
-----------------------------------------------------------------------------*/

/* Automatic detection of KANJI code */
int checkkanjicode(unsigned char *data)
{
  int			euc, jis, sjis;
  unsigned long int	i, length;

  euc = jis = sjis = 1;

  /* NULL data check */
  if ( data == NULL || *data == '\0' ) return -1;

  length = strlen(data);

  /* Check KANJI Code */
  for ( i = 0 ; i < length ; i++ ) {
    /* Check JIS Code */
    if ( *(data+i) == WT_JP_CODE_ESC &&
	 (
	  (
	   i + 2 < length &&
	   *(data+i+1) == '$' &&
	   ( *(data+i+2) == '@' || *(data+i+2) == 'B' || *(data+i+2) == 'D' ) ) ||
	  (
	   i + 3 < length &&
	   *(data+i+1) == '$' &&
	   *(data+i+2) == '(' &&
	   *(data+i+3) == 'D' ) ||
	  (
	   i + 5 < length &&
	   *(data+i+1) == '$' &&
	   *(data+i+2) == '@' &&
	   *(data+i+3) == WT_JP_CODE_ESC &&
	   *(data+i+4) == '$' &&
	   *(data+i+5) == 'B' ) ||
	  (
	   i + 2 < length &&
	   *(data+i+1) == '(' &&
	   ( *(data+i+2) == 'J' || *(data+i+2) == 'H' ||
	     *(data+i+2) == 'B' || *(data+i+2) == 'I' ) )
	  ) ) {
      jis = 1;
      euc = sjis = 0;
      break;
    }
    /* Not JIS Code */
    if ( *(data+i) >= (unsigned char)0x80 ) {
      jis = 0;
    }
    if ( *(data+i) >= (unsigned char)0x81 &&
	 *(data+i) <= (unsigned char)0x9f &&
	 *(data+i) != (unsigned char)0x8e &&
	 *(data+i) != (unsigned char)0x8f ) {
      /* SJIS Code */
      sjis = 1;
      jis = euc = 0;
      break;
    }
  }

  if ( jis + euc + sjis != 1 ) {
    euc = 1;
    sjis = jis = 0;
  }

  if ( jis ) {
    return 1;
  }
  else if ( sjis ) {
    return 2;
  }
  else {
    return 0;
  }
}


/* Change any codes to EUC code */
unsigned char *change2euc(unsigned char *data)
{
  int			code;
  unsigned char		*ret = NULL;
  unsigned long int	length;

  /* NULL data check */
  if ( data == NULL || *data == '\0' )  return NULL;

  /* Check KANJI code */
  code = checkkanjicode(data);

  /* Calculate string length */
  length = strlen(data);

  /* Change KANJI code */
  switch ( code ) {
  default:
  case 0:
    /* from EUC code (not change) */
    ret = wtkf_setstring(data);
    break;
  case 1:
    /* from JIS code  */
    ret = jis2euc(data);
    break;
  case 2:
    /* from SJIS code */
    ret = sjis2euc(data);
    break;
  }

  return ret;
}


/* Change JIS code to EUC code */
unsigned char *jis2euc(unsigned char *data)
{
  int			mode;
  unsigned long int	i, j;
  unsigned long int	length, size;
  unsigned char		*ret, *tmp;

  /* Temporary area */
  size = WT_JP_CODE_STRMAX;
  if ( ( tmp = (unsigned char *)malloc(sizeof(unsigned char)*size) ) == NULL ) {
    return NULL;
  }

  length = strlen(data);
  j = mode = 0;

  for ( i = 0 ; i < length ; i++ ) {
    if ( *(data+i) == WT_JP_CODE_ESC ) {
      if ( *(data+i+1) == '(' && *(data+i+2) == 'B' ) mode = 0;
      if ( *(data+i+1) == '(' && *(data+i+2) == 'J' ) mode = 1;
      if ( *(data+i+1) == '(' && *(data+i+2) == 'H' ) mode = 1;
      if ( *(data+i+1) == '(' && *(data+i+2) == 'I' ) mode = 2;
      if ( *(data+i+1) == '$' && *(data+i+2) == '@' ) mode = 3; /* JIS1978 */
      if ( *(data+i+1) == '$' && *(data+i+2) == 'B' ) mode = 3; /* JIS1983 */
      if ( *(data+i+1) == '$' && *(data+i+2) == 'D' ) mode = 4;
      i += 2;
      continue;
    }
    else {
      switch ( mode ) {
      case 0:
	/* ASCII */
	*(tmp+j) = *(data+i);
	j++;
	break;
      case 1:
	/* JIS Roman */
	*(tmp+j) = *(data+i);
	j++;
	break;
      case 2:
	/* Katakana */
	*(tmp+j) = (unsigned char)0x8e;
	j++;
	*(tmp+j) = *(data+i) | 128;
	j++;
	break;
      case 3:
	/* Kanji */
	*(tmp+j) = *(data+i) | 128;
	i++;
	j++;
	*(tmp+j) = *(data+i) | 128;
	j++;
	break;
      case 4:
	/* Sub Kanji */
	*(tmp+j) = (unsigned char)0x8f;
	j++;
	*(tmp+j) = *(data+i) | 128;
	i++;
	j++;
	*(tmp+j) = *(data+i) | 128;
	j++;
	break;
      }
    }
    if ( j + 3 >= size ) {
      size += WT_JP_CODE_STRMIN;
      if ( ( tmp = (unsigned char *)realloc(tmp, sizeof(unsigned char)*size) ) == NULL ) {
	return NULL;
      }
    }
  }

  *(tmp+j) = '\0';

  ret = wtkf_setstring(tmp);
  free(tmp);

  return ret;
}


/* Change SJIS code to EUC code */
unsigned char *sjis2euc(unsigned char *data)
{
  int			mode;
  unsigned long int	i, j;
  unsigned long int	length, size;
  unsigned char		*ret, *tmp;

  /* Temporary area */
  size = WT_JP_CODE_STRMAX;
  if ( ( tmp = (unsigned char *)malloc(sizeof(unsigned char)*size) ) == NULL ) {
    return NULL;
  }

  length = strlen(data);
  j = mode = 0;

  for ( i = 0 ; i < length ; i++ ) {
    if ( ( *(data+i) & 0x80 ) == 0x00 )		mode = 0;
    if ( *(data+i) >= (unsigned char)0xa1 &&
	 *(data+i) <= (unsigned char)0xdf )		mode = 1;
    if ( *(data+i) >= (unsigned char)0x81 &&
	 *(data+i) <= (unsigned char)0x9f )		mode = 2;
    if ( *(data+i) >= (unsigned char)0xe0 &&
	 *(data+i) <= (unsigned char)0xef )		mode = 3;

    switch ( mode ) {
    case 0:
      /* ASCII */
      *(tmp+j) = *(data+i);
      j++;
      break;
    case 1:
      /* Katakana */
      *(tmp+j) = (unsigned char)0x8e;
      j++;
      *(tmp+j) = *(data+i);
      j++;
      break;
    case 2:
      /* Kanji 1 */
      if ( *(data+i+1) <= (unsigned char)0x9e ) {
	*(tmp+j) = 0x80 |
	  ((( *(data+i) - (unsigned char)0x81 ) * 2 )
	   + (unsigned char)0x21 );
	i++;
	j++;
	if ( *(data+i) <= (unsigned char)0x7e ) {
	  *(tmp+j) = *(data+i) + 0x61;
	  j++;
	}
	else {
	  *(tmp+j) = *(data+i) + 0x60;
	  j++;
	}
      }
      else {
	*(tmp+j) = 0x80 |
	  ((( *(data+i) - (unsigned char)0x81 ) * 2 )
	   + (unsigned char)0x22 );
	i++;
	j++;
	*(tmp+j) = *(data+i) + 0x02;
	j++;
      }
      break;
    case 3:
      /* Kanji 2 */
      if ( *(data+i+1) <= (unsigned char)0x9e ) {
	*(tmp+j) = 0x80 |
	  ((( *(data+i) - (unsigned char)0xe0 ) * 2 )
	   + (unsigned char)0xdf );
	i++;
	j++;
	if ( *(data+i) <= (unsigned char)0x7e ) {
	  *(tmp+j) = *(data+i) + 0x61;
	  j++;
	}
	else {
	  *(tmp+j) = *(data+i) + 0x60;
	  j++;
	}
      }
      else {
	*(tmp+j) = 0x80 |
	  ((( *(data+i) - (unsigned char)0xe0 ) * 2 )
	   + (unsigned char)0xe0 );
	i++;
	j++;
	*(tmp+j) = *(data+i) + 0x02;
	j++;
      }
      break;
    }
    if ( j + 2 >= size ) {
      size += WT_JP_CODE_STRMIN;
      if ( ( tmp = (unsigned char *)realloc(tmp, sizeof(unsigned char)*size) ) == NULL ) {
	return NULL;
      }
    }
  }

  *(tmp+j) = '\0';

  ret = wtkf_setstring(tmp);
  free(tmp);

  return ret;
}


/* Keep string area */
unsigned char *wtkf_setstring(unsigned char *string)
{
  unsigned char		*ret;
  unsigned long int	length;

  if ( string == NULL || *string == '\0' ) return NULL;

  length = strlen(string) + 1;

  if ( ( ret = (unsigned char *)malloc(sizeof(unsigned char)*length) ) == NULL ) {
    return NULL;
  }

  strcpy(ret, string);

  return ret;
}


/*=============================================================================
			end
=============================================================================*/
