/*
 *
 * 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <TLS_HzInput.hpp>
#include <TLS_DoubleByteConvertor.hpp>
#include <TLS_AsciiConvertor.hpp>
#include <TLS_const.h>

extern TLS_CDoubleByteConvertor *pCDoubleByteConvertor;
extern TLS_CAsciiConvertor *pCAsciiConvertor [N_ASCII_CONVERTOR];

TLS_CHzInput::TLS_CHzInput (ImmOp_T *pImmSlib0, char *szImmTable, u_long type)
{
    error = 0;
    pImmSlib = pImmSlib0;
    pClient = pImmSlib->pImmOp->open (szImmTable, type);
    ClientType = type;
    IsHanziInput = IsFullChar = IsFullComma = 0;
    if (pClient == NULL)
        error = 1;
}

TLS_CHzInput::~TLS_CHzInput ()
{
    if (pClient != NULL)
       pImmSlib->pImmOp->close (pClient);
}

PhraseItem *TLS_CHzInput::DupBufPhrase 
            (PhraseItem *pOld, PhraseItem *pNew,
             char *buf, int buflen, char **pNextPos) 
{
    char *p1 = buf;
    if (pOld == NULL)
        return NULL;
    int len = strlen (pOld->szKeys) + 1 +
          sizeof (*pOld->KeyLen) +
          strlen (pOld->szPhrase) + 1 +
          sizeof (*pOld->frequency);
    if (len > buflen)
        return NULL;

    PhraseItem *p = pNew, *q = pOld;

    p->szKeys = p1;
    strcpy (p->szKeys, q->szKeys);
    p1 += strlen (p->szKeys) + 1;

    p->KeyLen = (u_char *) p1;
    *p->KeyLen = *q->KeyLen;
    p1 += sizeof (u_char);

    p->szPhrase = p1;
    strcpy (p->szPhrase, q->szPhrase);
    p1 += strlen (p->szPhrase) + 1;

    p->frequency = (freq_t *) p1;
    *p->frequency = *q->frequency;
    p1 += sizeof (freq_t);
    if ((char **) NULL != pNextPos)
        *pNextPos = p1;
    return pNew;
}


/* Input Method Operation */
int TLS_CHzInput::KeyFilter (u_char key, char *buf, int *len)
{
    int n = 0;
    if (IsFullChar == 1)
    {
        n = FullCharFilter (key, buf, len);
        if (n == 0 && IsFullComma == 1)
            n = FullSymbolFilter (key, buf, len);
    }
    else if (IsHanziInput == 1)
    {
        n = pImmSlib->pImmOp->KeyFilter (pClient, key, buf, len);
        if (n == 2 && 
            (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL &&
            ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff))
            pCDoubleByteConvertor->String (buf,
                          pImmSlib->pImmOp->type >> 24 & 0xff, ClientType);
        if (n == 0 && IsFullComma == 1)
            n = FullSymbolFilter (key, buf, len);
    }
    else 
    {
        if (IsFullComma == 1)
            n = FullSymbolFilter (key, buf, len);
    }
    return n;
}

int TLS_CHzInput::FullSymbolFilter (u_char key, char *buf, int *len)
{
    int n;
    switch (ClientType)
    {
        case IMM_LC_GB2312:
        case IMM_LC_GB18030:
        case IMM_LC_GBK:
            n = ASCII_CONVERTOR_GB;
            break;
        case IMM_LC_BIG5:
        case IMM_LC_BIG5HKSCS:
            n = ASCII_CONVERTOR_BIG5;
            break;
        default:
            return 0;
    }
    char *s = pCAsciiConvertor[n]->szFullSymbolKeyStroke (key);
    if (s == NULL)
        return 0;
    strcpy (buf, s);
    *len = strlen (buf);
    return 2;
}

int TLS_CHzInput::FullCharFilter (u_char key, char *buf, int *len)
{
    int n;
    switch (ClientType)
    {
        case IMM_LC_GB2312:
        case IMM_LC_GB18030:
        case IMM_LC_GBK:
            n = ASCII_CONVERTOR_GB;
            break;
        case IMM_LC_BIG5HKSCS:
        case IMM_LC_BIG5:
            n = ASCII_CONVERTOR_BIG5;
            break;
        default:
            return 0;
    }
    char *s = pCAsciiConvertor[n]->szFullCharKeyStroke (key);
    if (s == NULL)
        return 0;
    strcpy (buf, s);
    *len = strlen (buf);
    return 2;
}

int TLS_CHzInput::ResetInput ()
{
   return pImmSlib->pImmOp->ResetInput (pClient);
}

int TLS_CHzInput::SetInputMode (long mode)
{
    IsHanziInput = IsFullChar = IsFullComma = 0;
    if (mode & IMM_DOUBLE_BYTE_MODE)
        IsHanziInput = 1;
    if (mode & IMM_FULL_SYMBOL_MODE)
        IsFullComma = 1;
    if (mode & IMM_FULL_CHAR_MODE)
        IsFullChar = 1;
    if (mode & IMM_FULL_ASCII_MODE)
    {
            IsFullChar = 1;
            IsFullComma = 1;
    }
    return 1;
}

/* Input Area Configuration & Operation */
int TLS_CHzInput::ConfigInputArea (int SelectionLen)
{
   return pImmSlib->pImmOp->ConfigInputArea (pClient, SelectionLen);
}

int TLS_CHzInput::GetInputDisplay (char *buf, long buflen)
{
   int n = pImmSlib->pImmOp->GetInputDisplay (pClient, buf, buflen);
   if (ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff) &&
       (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL)
       pCDoubleByteConvertor->String (buf,
           pImmSlib->pImmOp->type >> 24 & 0xff, ClientType);
    return n;
}

int TLS_CHzInput::GetSelectDisplay (char *buf, long buflen)
{
   int n = pImmSlib->pImmOp->GetSelectDisplay (pClient, buf, buflen);
   if (ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff) &&
       (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL)
       pCDoubleByteConvertor->String (buf, 
           pImmSlib->pImmOp->type >> 24 & 0xff, ClientType);
   return n;
}

/* Phrase Item Operations */
int TLS_CHzInput::ModifyPhrase (long n, PhraseItem *p)
{
   if (pImmSlib->pImmOp->ModifyPhraseItem == NULL)
       return 1;
   PhraseItem *pTarget, m;
   pTarget = DupBufPhrase (p, &m, 
             tmpbuf, sizeof (tmpbuf), (char **) NULL);
   if (pTarget == NULL)
       return 0;
   if (ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff) &&
       (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL)
       pCDoubleByteConvertor->String (pTarget->szPhrase,
           ClientType, pImmSlib->pImmOp->type >> 24 & 0xff);
   return pImmSlib->pImmOp->ModifyPhraseItem (pClient, n, pTarget);
}

int TLS_CHzInput::AppendPhrase (PhraseItem *p)
{
   if (pImmSlib->pImmOp->AddPhrase == NULL)
       return 1;
   PhraseItem *pTarget, m;
   pTarget = DupBufPhrase (p, &m,
             tmpbuf, sizeof (tmpbuf), (char **) NULL);
   if (pTarget == NULL)
        return 0;
   if (ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff) &&
       (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL)
       pCDoubleByteConvertor->String (pTarget->szPhrase,
           ClientType, pImmSlib->pImmOp->type >> 24 & 0xff);
   return pImmSlib->pImmOp->AddPhrase (pClient, pTarget);
}

int TLS_CHzInput::FlushUserPhrase ()
{
   return pImmSlib->pImmOp->Flush (pClient);
}

PhraseItem *TLS_CHzInput::pGetSelectionItem (long n, PhraseItem *pTarget,
                      char *buf, int buflen)
{
   PhraseItem *p = pImmSlib->pImmOp->pGetItem (pClient, n);
   if (p == NULL)
       return NULL;
   pTarget = DupBufPhrase (p, pTarget, buf, buflen, (char **) NULL);
   if (pTarget == NULL)
        return 0;
   if (ClientType != (pImmSlib->pImmOp->type >> 24 & 0xff) &&
      (pImmSlib->pImmOp->type >> 24 & 0xff) != IMM_LC_ALL)
       pCDoubleByteConvertor->String (pTarget->szPhrase,
            pImmSlib->pImmOp->type >> 24 & 0xff, ClientType);
   return pTarget;
}

