/*
 * $Id: write.c,v 1.2 2001/06/14 18:16:18 ura Exp $
 */

/*
 * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
 * This file is part of FreeWnn.
 * 
 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
 * Copyright 1991, 1992 by Massachusetts Institute of Technology
 *
 * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp>
 *
 * 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, 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 GNU Emacs; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Commentary:
 *
 * Change log:
 *
 * Last modified date: 8,Feb.1999
 *
 * Code:
 *
 */
/*      Version 4.0
 */
#include <stdio.h>
#include "commonhd.h"
#include "sdefine.h"
#include "xim.h"
#include "sheader.h"
#include "proto.h"
#include "ext.h"

#if !defined(X11R5) && defined(BC_X11R5)
extern XIMCmblk *cur_cblk;
#define IS_XIMR5_CLIENT()       (cur_cblk->ximr5)
#endif /* !defined(X11R5) && defined(BC_X11R5) */

static int
send_returnend ()
{
  ximReturnReply reply;

  reply.type = 0;
  reply.length = 0;
  reply.keysym = 0;
  if (need_byteswap () == True)
    {
      byteswap_ReturnReply (&reply);
    }
  if (_WriteToClient (&reply, sz_ximReturnReply) == -1)
    return (-1);
  return (0);
}

static int
send_ct (ct, ct_len)
     register char *ct;
     register int ct_len;
{
  ximReturnReply reply;

  reply.type = XIM_STRING;
  reply.length = ct_len;
  reply.keysym = 0;
  if (need_byteswap () == True)
    {
      byteswap_ReturnReply (&reply);
    }
  if (_WriteToClient (&reply, sz_ximReturnReply) == -1)
    return (-1);
  if (ct_len > 0)
    {
      if (_WriteToClient (ct, ct_len) == -1)
        return (-1);
    }
  return (0);
}

static int
send_keysym (keysym, str)
     KeySym keysym;
     char str;
{
  ximReturnReply reply;
  char buf[2];
  int tmp_length;

  reply.type = XIM_KEYSYM;
  if (keysym < 0x20)
    {
      keysym |= 0xff00;
      reply.length = 0;
    }
  else
    {
      reply.length = 1;
      buf[0] = str & 0xff;
      buf[1] = '\0';
    }
  reply.keysym = keysym;
  tmp_length = reply.length;
  if (need_byteswap () == True)
    {
      byteswap_ReturnReply (&reply);
    }
  if (_WriteToClient (&reply, sz_ximReturnReply) == -1)
    return (-1);
  if (tmp_length > 0)
    {
      if (_WriteToClient (buf, tmp_length) == -1)
        return (-1);
    }
  return (0);
}

int
return_eventreply (state, mode, num)
     short state;
     short mode;
     short num;
{
  ximEventReply reply;

  reply.state = state;
  reply.detail = mode;
  reply.number = num;
  if (need_byteswap () == True)
    {
      byteswap_EventReply (&reply);
    }
  if (_WriteToClient (&reply, sz_ximEventReply) == -1)
    return (-1);
  return (0);
}

int
send_nofilter ()
{
#ifndef X11R5
#ifdef BC_X11R5
  if (IS_XIMR5_CLIENT ())
    {
      if (return_eventreply (0, XIM_NOFILTER, 0) == -1)
        return (-1);
    }
  else
#endif /* BC_X11R5 */
    return xim_send_nofilter ();
#else
  if (return_eventreply (0, XIM_NOFILTER, 0) == -1)
    return (-1);
#endif /* !X11R5 */
  return (0);
}

static int
send_ch_locale (locale)
     char *locale;
{
  return_eventreply (0, XIM_CH_LOCALE, strlen (locale));
  if (_WriteToClient (locale, strlen (locale)) == -1)
    return (-1);
  return (0);
}

int
send_end ()
{
  if (cur_p && cur_p->ch_lc_flg)
    {
      send_ch_locale (cur_p->cur_xl->cur_lc->lc_name);
      cur_p->ch_lc_flg = 0;
    }
  if (return_eventreply (0, 0, 0) == -1)
    return (-1);
  if (_Send_Flush () == -1)
    return (-1);
  return (0);
}

int
return_cl_it ()
{
#ifdef  XJPLIB
  if (cur_x && cur_x->xjp)
    {
      XJp_return_cl_it ();
      return (0);
    }
#endif /* XJPLIB */
  if (cur_input != 0)
    {
      if (send_nofilter () == -1)
        return (-1);
    }
  return (0);
}

void
xw_write (w_buf, size)
     register w_char *w_buf;
     register int size;
{
  register XIMLangRec *xl;
  w_char w_c;
  w_char *start;
  register int cnt;
  int conv_len, send_len;
  KeySym keysym;

  if (!size)
    {
      return;
    }
#ifdef  XJPLIB
  if (cur_x && cur_x->xjp)
    {
      XJp_xw_write (w_buf, size);
      return;
    }
#endif /* XJPLIB */

  if (henkan_off_flag)
    {
      return_cl_it ();
      return;
    }
#ifdef BC_X11R5
  if (IS_XIMR5_CLIENT ())
#endif /* BC_X11R5 */
#if defined(X11R5) || defined(BC_X11R5)
    return_eventreply (0, XIM_RETURN, 0);
#endif /* defined(X11R5) || defined(BC_X11R5) */

  xl = cur_p->cur_xl;

  if (IsPreeditPosition (cur_x) && cur_p->cur_xl->del_x >= cur_p->cur_xl->max_pos)
    {
      JWMline_clear1 ();
    }

  conv_len = 0;
  start = w_buf;
  for (cnt = 0; cnt < size; cnt++, w_buf++)
    {
      if (!((w_c = *w_buf) & 0xff80))
        {
          if (conv_len)
            {
              while (1)
                {
                  send_len = w_char_to_ct (xl->xlc, start, ct_buf, conv_len, ct_buf_max);
                  if (send_len < -1)
                    {
                      break;
                    }
                  else if (send_len == -1)
                    {
                      if (realloc_ct_buf () < 0)
                        break;
                    }
                  else if (send_len > 0)
                    {
#ifndef X11R5
#ifdef BC_X11R5
                      if (IS_XIMR5_CLIENT ())
                        send_ct (ct_buf, send_len);
                      else
#endif /* BC_X11R5 */
                        xim_send_ct (ct_buf, send_len);
#else
                      send_ct (ct_buf, send_len);
#endif /* !X11R5 */
                      break;
                    }
                }
              conv_len = 0;
            }
          keysym = (int) w_c;
#ifndef X11R5
#ifdef BC_X11R5
          if (IS_XIMR5_CLIENT ())
            send_keysym (keysym, w_c);
          else
#endif /* BC_X11R5 */
            xim_send_keysym (keysym, w_c);
#else
          send_keysym (keysym, w_c);
#endif /* !X11R5 */
        }
      else
        {
          if (conv_len == 0)
            {
              start = w_buf;
            }
          conv_len++;
        }
    }
  if (conv_len)
    {
      while (1)
        {
          send_len = w_char_to_ct (xl->xlc, start, ct_buf, conv_len, ct_buf_max);
          if (send_len < -1)
            {
              break;
            }
          else if (send_len == -1)
            {
              if (realloc_ct_buf () < 0)
                break;
            }
          else if (send_len > 0)
            {
#ifndef X11R5
#ifdef BC_X11R5
              if (IS_XIMR5_CLIENT ())
                send_ct (ct_buf, send_len);
              else
#endif /* BC_X11R5 */
                xim_send_ct (ct_buf, send_len);
#else
              send_ct (ct_buf, send_len);
#endif /* !X11R5 */
              break;
            }
        }
      conv_len = 0;
    }
#ifdef BC_X11R5
  if (IS_XIMR5_CLIENT ())
#endif /* BC_X11R5 */
#if defined(X11R5) || defined(BC_X11R5)
    send_returnend ();
#endif /* defined(X11R5) || defined(BC_X11R5) */
  return;
}
