/* # skkinput (Simple Kana-Kanji Input)
 * HistMgr.c
 * This file is part of skkinput.
 * Copyright (C) 1997
 * Takashi SAKAMOTO (sakamoto@yajima.kuis.kyoto-u.ac.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 skkinput; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/IntrinsicP.h>

#include "commondef.h"
#include "HistMgr.h"
#include "resrcs.h"

/*
 * ヒストリに残される情報( eggnl 及び chatadapter )の初期値。
 */
extern int skk_egg_like_newline ;
extern int skkinput_chatadaptermode ;
extern int skkinput_rjj_like_input ;

/*
 * ヒストリを記録しているリスト。
 */
static HistoryListNode *unmanagedHistoryListTop = NULL ;

/*
 * このソースの中だけのプライベートな関数達。
 */
static HistoryListNode *create_newHistoryNode( Window client )
{
  HistoryListNode *node ;
  /* malloc を用いてメモリを確保する。*/
  if( ( node = malloc( sizeof( HistoryListNode ) ) ) == NULL ){
    /* もはやメモリを確保できなかった場合。*/
    fprintf( stderr, "Memory fault...\n" ) ;
    exit( 1 ) ;
  }
  /* 念のためにあらかじめ初期化しておく。初期化しなくても必要な時に勝 */
  /* 手に初期化するつもりではあるのだが…。*/
  node->mask            = 0 ;
  node->next            = NULL ;
  node->client          = client ;
  node->history_start   = node->history_end = 0 ;
  MYCHAR_SET_END_OF_STRING( node->history[ 0 ] ) ;
  MYCHAR_SET_END_OF_STRING( node->histcurbak[ 0 ] ) ;
  node->egg_nl          = skk_egg_like_newline ;
  node->chat_adapter    = skkinput_chatadaptermode ;
  node->j_mode          = True ;
  node->j_zenkaku       = False ;
  node->j_katakana_mode = False ;
  /* RJJ 風の設定がしれあれば、初期化段階で必ず True にする。*/
  node->overthespot_like_input = ( skkinput_rjj_like_input )? True : (-1) ;
  return node ;
}

/*
 * このソースの外から参照されるパブリックな関数達。
 */

/*
 * ヒストリの初期化、サービスの開始を行う関数。
 */
HistoryListNode *history_setup( Widget gw, Window client_window )
{
  HistoryListNode *node, *pNode ;

  pNode = node = unmanagedHistoryListTop ;
  while( node != NULL ){
    if( node->client == client_window )
      break ;
    pNode = node ;
    node  = node->next ;
  }
  if( node == NULL ){
    node = create_newHistoryNode( client_window ) ;
    node->mask = HISTORY_BUFFER_MASK ;
  } else {
    if( pNode == node ){
      unmanagedHistoryListTop = node->next ;
    } else {
      pNode->next = node->next ;
    }
  }
  return node ;
}

/*
 * ヒストリをヒストリリストへと戻す関数。
 *---
 * 破棄されるわけではなく、リストへと戻されるだけである。
 */
void history_close( Display *disp, caddr_t caller )
{
  HistoryListNode *node = ( HistoryListNode *)caller ;
  /* ヒストリのリストにつなぎ直す。*/
  node->next = unmanagedHistoryListTop ;
  unmanagedHistoryListTop = node ;
  return ;
}

/*
 * 指定された変換クライアントに対するヒストリを破棄する関数。
 *----
 * この処理が終わるまで、一度作られた変換クライアントに対する 
 * SelectInput は取り消すことができない。この後、client_window には 
 * NoEventMask をかけることになる。
 */
void history_destroy( Window client_window )
{
  HistoryListNode *node = unmanagedHistoryListTop, *pNode ;
  pNode = node ;
  while( node != NULL ){
    /* クライアントウィンドウが存在するかどうかを調べる。*/
    if( node->client == client_window ){
      /* 既に存在しなくなっているのなら、ヒストリを抹消する。*/
      if( node == pNode ){
	unmanagedHistoryListTop = node->next ;
	free( node ) ;
	pNode = node = unmanagedHistoryListTop ;
      } else {
	pNode->next = node->next ;
	free( node ) ;
	node = pNode->next ;
      }
    } else {
      pNode = node ;
      node = node->next ;
    }
  }
  return ;
}
