/*
 *
 * 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
 */

/*****************************************************************************
 *
 * ImmServer.c  ===  Communicaton between Server and Client 
 *
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <TLC_ImmServer.hpp>
#include <ImmComm.h>

TLC_CImmServer::TLC_CImmServer (char *szIpAddr, u_short port)
{
    pCSocketClient = new TLC_CSocketClient (szIpAddr, port);
    MemIn = new TLC_CMemFile (512), 
    MemOut = new TLC_CMemFile (512);
}

TLC_CImmServer::~TLC_CImmServer ()
{
    delete pCSocketClient;
    delete MemIn;
    delete MemOut;
}

IMM_HANDLE  TLC_CImmServer::OpenImm (char *szImmModule, 
                                 char *szImmTable, u_long type, IMM *p)
{
    /* format the frame that will send */
    MemOut->rewind ();
    *MemOut << (long) IMM_OPEN_SERVER;
    *MemOut << (PSTR) szImmModule;
    *MemOut << (PSTR) szImmTable;
    *MemOut << (long) type;

    /* send to server */
    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    IMM_HANDLE h;
    long state;
    *MemIn >> state;
    *MemIn >> h;
    PSTR szMethod = (PSTR) p->szMethod;
    *MemIn >> szMethod;
    if (state == IMM_NORMAL)
        return h;
    else
        return -1;
}

int TLC_CImmServer::CloseImm (IMM_HANDLE  handle)
{
    /* write the frame */
    MemOut->rewind ();
    *MemOut << (long) IMM_CLOSE_SERVER;
    *MemOut << (long) handle;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;
    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

int TLC_CImmServer::ResetInput (IMM_HANDLE  handle)
{
    MemOut->rewind (); 
    *MemOut << (long) IMM_RESET_INPUT;
    *MemOut << (long) handle;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;

    if (state == IMM_NORMAL)
        return 1;
    return 0;

}

int TLC_CImmServer::KeyFilter (IMM_HANDLE handle, u_char key, char *buf, int *len)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_KEY_FILTER;
    *MemOut << (long) handle;
    *MemOut << (char) key;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    long rt, a;

    *MemIn >> state;
    *MemIn >> rt;
    
    if (rt == 2)
    {
        *MemIn >> a;
        *MemIn >> (PSTR) buf;
        *len = (int) a;
    }
    if (state == IMM_NORMAL)
        return (int) rt;
    return 0;
}

int TLC_CImmServer::SetInputMode (IMM_HANDLE handle, long mode)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_SET_INPUTMODE;
    *MemOut << (long) handle;
    *MemOut << (long) mode;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;
    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

/* Input Area Configuration & Operation */
int TLC_CImmServer::ConfigInputArea (IMM_HANDLE handle, int SelectionLen)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_CONFIG_INPUT_AREA;
    *MemOut << (long) handle;
    *MemOut << (long) SelectionLen;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;

    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

int TLC_CImmServer::GetInputDisplay (IMM_HANDLE handle, char *buf, long buflen)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_GET_INPUT_DISPLAY;
    *MemOut << (long) handle;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;
    *MemIn >> (PSTR) buf;

    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

int TLC_CImmServer::GetSelectDisplay (IMM_HANDLE handle, char *buf, long buflen)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_GET_SELECT_DISPLAY;
    *MemOut << (long) handle;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    long total;
    *MemIn >> state;
    *MemIn >> total;
    *MemIn >> (PSTR) buf;

    if (state == IMM_NORMAL)
        return (int) total;
    return 0;
}

int TLC_CImmServer::SetPhraseItem (IMM_HANDLE handle, u_long n, 
                        char *szCode, char *szPhrase, u_long freq)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_SET_PHRASE_ITEM << (long) handle << (long) n;
    *MemOut << (PSTR) szCode << (char) strlen (szCode);
    *MemOut << (PSTR) szPhrase << (long) freq;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int len = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (len);

    /* get the frame */
    long state;
    *MemIn >> state;

    if (state == IMM_NORMAL)
        return 1;
    return 0;
    
}

int TLC_CImmServer::AddUserPhrase (IMM_HANDLE handle, 
                        char *szCode,
                        char *szPhrase,
                        u_long freq)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_ADD_USER_PHRASE << (long) handle;
    *MemOut << (PSTR) szCode << (char) strlen (szCode);
    *MemOut << (PSTR) szPhrase << (long) freq;

    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;

    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

int TLC_CImmServer::FlushUserPhrase (IMM_HANDLE handle)
{
    MemOut->rewind ();
    *MemOut << (long) IMM_FLUSH_USER_PHRASE << (long) handle;
    pCSocketClient->Write (MemOut->pGetBuf(), MemOut->GetBufLen ());

    /* receive the reply */
    int n = pCSocketClient->Read (MemIn->pGetBuf(), MemOut->GetMax ());
    MemIn->rewind ();
    MemIn->SetBufLen (n);

    /* get the frame */
    long state;
    *MemIn >> state;

    if (state == IMM_NORMAL)
        return 1;
    return 0;
}

