/*
 *
 * UNICON - The Console Chinese & I18N
 * Copyright (c) 1999-2000
 *
 * This file is part of UNICON, a console Chinese & I18N
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * See the file COPYING directory of this archive
 * Author: see CREDITS
 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <ImmDefs.h>
#include <TLS_DoubleByteConvertor.hpp>

TLS_CDoubleByteConvertor::TLS_CDoubleByteConvertor ()
{
}

TLS_CDoubleByteConvertor::~TLS_CDoubleByteConvertor ()
{
}

int TLS_CDoubleByteConvertor::String (char *szStr, long SourceType, long TargetType)
{
    char *p;

    p = (char *) malloc (strlen (szStr) + 1);
    if (p == NULL)
        return 0;

    if (String2 (szStr, SourceType, p, TargetType) == 1)
        strcpy (szStr, p);
    free (p);

    return 1;
}

int TLS_CDoubleByteConvertor::String2 (char *szStr1, long SourceType,
                                   char *szStr2, long TargetType)
{
    if (SourceType == IMM_LC_GB2312 && TargetType == IMM_LC_BIG5)
        GbStringToBig5String (szStr1, szStr2, strlen (szStr1));
    else if (SourceType == IMM_LC_BIG5 && TargetType == IMM_LC_GB2312)
        Big5StringToGbString (szStr1, szStr2, strlen (szStr1));
    else
        return 0;
    return 1;
}

/* GB2312 and Big5 Support */
#include <string.h>
#include <TLS_HzConvertTable.h>

/**************************************************************************
 *              Coding Processing Routines and Structures                 *
 **************************************************************************/

/* These are char internal codes to address(offset) conversion routines
   Chinese, Japanese,Korean coding */

int TLS_CDoubleByteConvertor::IsGB2312(u_char ch1, u_char ch2)
{
    static u_char min1 = 0xa1, 
                  max1 = 0xfe;
    return (ch1 >= min1 && ch1 <= max1 && ch2 >= min1 && ch2 <= max1);
}

int TLS_CDoubleByteConvertor::IsBIG5 (u_char ch1, u_char ch2)
{
    static u_char min1 = 0xa1,
                  min2 = 0x40,
                  max1 = 0xf9,
                  max2 = 0x7e,
                  max3 = 0xfe;
    return (ch1 >= min1 && ch1 <= max1) &&
            ((ch2 >= min2 && ch2 <= max2) || (ch2 >= min1 && ch2 <= max3));
}

void TLS_CDoubleByteConvertor::GbCharToBig5(char *gb, char *big5)
{
    u_int i;

    for(i=0; i < TABLENUM; i++)
    {
        if(gb[0] == g2b[i].gb[0] &&
           gb[1] == g2b[i].gb[1]) 
        {
            big5[0] = g2b[i].big5[0];
            big5[1] = g2b[i].big5[1];
            return;
        }
    }
    strcpy(big5, "¡¼");    //0xA1BC
}

void TLS_CDoubleByteConvertor::Big5CharToGb (char *big5, char *gb)
{
    u_int i;

    for (i = 0; i < TABLENUM; i++)
    {
        if(big5[0] == g2b[i].big5[0] &&
           big5[1] == g2b[i].big5[1]) 
        {
            gb[0] = g2b[i].gb[0];
            gb[1] = g2b[i].gb[1];
            return;
        }
    }
    strcpy(gb, "¡õ");
}

void TLS_CDoubleByteConvertor::GbStringToBig5String 
                         (char *gbstr, char *big5str, int big5len)
{
    int i, gblen = strlen (gbstr);
    char b5[3];

    strcpy(big5str, "");

    if(!gbstr) 
        return;

    for (i = 0; i < big5len && i < gblen;)
    {
        if (i + 1 == gblen || IsGB2312 (gbstr[i], gbstr[i+1]) == 0)
        {
            strncat (big5str, &gbstr[i], 1);
            i++;
            continue;
        }
        GbCharToBig5(gbstr+i, b5);
        strncat(big5str, b5, 2);
        i += 2;
    }
}

void TLS_CDoubleByteConvertor::Big5StringToGbString 
                (char *big5str, char *gbstr, int gblen)
{
    int i, big5len = strlen (big5str);
    char gb[3];

    strcpy(gbstr, "");

    if(!big5str) 
        return;

    for (i = 0; i < gblen && i < big5len;)
    {
        if (i + 1 == big5len || IsBIG5 (big5str[i], big5str[i+1]) == 0)
        {
            strncat(gbstr, &big5str[i], 1);
            i++;
            continue;
        }
        Big5CharToGb (big5str+i, gb);
        strncat(gbstr, gb, 2);
        i += 2;
    }
}
#ifdef __DBC_DEBUG__
int main (int argc, char **argv)
{
    if (argc < 4)
    {
        printf ("%s --gbtobig5 <source file> <target file> \n", argv[0]);
        printf ("%s --big5togb <source file> <target file> \n", argv[0]);
        exit (0);
    }
    if (! (strcmp (argv[1], "--gbtobig5") == 0 ||
          strcmp (argv[1], "--big5togb") == 0))
    {
        printf ("wrong parameter ....");
        exit (0);
    }
    FILE *fpIn, *fpOut;
    if ((fpIn = fopen (argv[2], "rt")) == NULL)
    {
         printf ("can't open %s \n", argv[1]);
         exit (0);
    }
    fpOut = fopen (argv[3], "wt");
    
    TLS_CDoubleByteConvertor a;
    char buf1[256], buf2[256];
    while (fgets (buf1, sizeof (buf1), fpIn) != NULL)
    {
        if ( !strcmp (argv[1], "--gbtobig5"))
            a.GbStringToBig5String (buf1, buf2, sizeof (buf2));
        else
            a.Big5StringToGbString (buf1, buf2, sizeof (buf2));
        fprintf (fpOut, "%s", buf2);
    }
    fclose (fpIn);
    fclose (fpOut);
    return 0;
}
#endif
 
