/*
  iiimqccontext.cpp
  Copyright (C) 2003 Free Standards Group

  Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions: The above copyright notice and this
  permission notice shall be included in all copies or substantial
  portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL OPENI18N WG OR FREE STANDARDS GROUP. BE LIABLE
  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
  THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
  ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.

  Except as contained in this notice, the names of OpenI18N WG and/or
  Free Standards Group shall not be used in advertising or otherwise to
  promote the sale, use or other dealings in this Software without prior
  written authorization from OpenI18N WG and/or Free Standards Group
  as applicable.

  Author: ILGYOUNG PARK <Karl.Park@Sun.COM>
	  TuBo	<Gavin.Tu@Sun.COM>

*/

#include <qwidget.h>
#include <qinputcontext.h>
#include <qapplication.h>
#include <qvaluelist.h>
#include <qtextcodec.h>
#include <iiimcf.h>

#include "iiimqccontext.h"
#include "keymapper.h"
#include "lookup.h"
#include "debug.h"


#include "imaux.h"


class IIIMInputContextPrivate
{
public:
  typedef IIIMInputContext::IIIMICLIST IIIMICLIST;
  typedef IIIMInputContext::IIIMICLISTITR IIIMICLISTITR;
  typedef IIIMInputContext::IIIMInputContextID IIIMInputContextID;
  IIIMInputContextPrivate (IIIMInputContext *iiimqc);
  bool getLookupChoiceItems (QStringList &slist,
			     int *psize,
			     int *pfirst_index,
			     int *plast_index,
			     int *pcurrent_index);
  bool getLookupTitle(QString &title);

private:
  IIIMInputContext *_iiimqc;
};

IIIMInputContextPrivate::IIIMInputContextPrivate (IIIMInputContext *iiimqc)
{
  if (iiimqc)
    _iiimqc = iiimqc;
  else
    _iiimqc = 0;
}


bool IIIMInputContextPrivate::getLookupChoiceItems (QStringList &qstrlist,
					       int *psize,
					       int *pfirst_index,
					       int *plast_index,
					       int *pcurrent_index
					       )
{
  IIIMCF_context context;
  IIIMCF_lookup_choice lookup_choice;
  IIIMF_status st;
  QString *qlabel;
  QString *qcandidate;
 
  int size = 0;
  int index_of_first_candidate = 0;
  int index_of_last_candidate = 0;
  int index_of_current_candidate = 0;

  IIIMCF_text acandidate;
  IIIMCF_text alabel;
  int flag;
  IIIMICLISTITR itr = _iiimqc->_curic;
  context = (*itr)._c;
 
  if(!context)
	return FALSE;
 
  st = iiimcf_get_lookup_choice (context, &lookup_choice);
  if(st != IIIMF_STATUS_SUCCESS)
  {
 	DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice(): error\n"));	 
	return FALSE;
  } 	
  
  if(!lookup_choice)
  {
 	DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice(): error\n"));	 
	return FALSE;
  }
     
  st = iiimcf_get_lookup_choice_size (lookup_choice,
				 &size,
				 &index_of_first_candidate,
				 &index_of_last_candidate,
				 &index_of_current_candidate);
  if( st != IIIMF_STATUS_SUCCESS)
  {
	DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice_size(): error\n"));
	return FALSE;
  }	 
  
  if (psize)
    *psize = size;
  if (pfirst_index)
    *pfirst_index = index_of_first_candidate;
  if (plast_index)
    *plast_index = index_of_last_candidate;
  if (pcurrent_index)
    *pcurrent_index = index_of_current_candidate;
  
  for (int idx = 0; idx < size; idx++){
    const IIIMP_card16 *u16text;
    const IIIMP_card16 *u16label;
    int thelength; int labellength;

    st = iiimcf_get_lookup_choice_item (lookup_choice, idx,
				   &acandidate, &alabel,
				   &flag);
    if( st != IIIMF_STATUS_SUCCESS )
    {
	DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice_item(): error, idx is %d\n", idx));
    	continue;
    }	

    st = iiimcf_get_text_utf16string (acandidate, &u16text);
    if (st != IIIMF_STATUS_SUCCESS)
      continue;
  
    st = iiimcf_get_text_length (acandidate, &thelength);
    if (st != IIIMF_STATUS_SUCCESS)
      continue;

        
    st = iiimcf_get_text_utf16string (alabel, &u16label);
    if (st != IIIMF_STATUS_SUCCESS)
      continue;
  
    st = iiimcf_get_text_length (alabel, &labellength);
    if (st != IIIMF_STATUS_SUCCESS)
      continue;
  
    qlabel = new QString((const QChar *)u16label, labellength);
    qcandidate = new QString((const QChar *)u16text, thelength);
    
    DEBUG_DO(qDebug("**IIIMQCF: label: %s.\n", (const char*)qlabel->utf8())); 
    DEBUG_DO(qDebug ("**IIIMQCF: candidate:%s.\n", (const char *)qcandidate->utf8()));
    if(qlabel->isEmpty() || *qlabel == " ")
	qstrlist.append(*qcandidate);
     else
	qstrlist.append (*qlabel + " " +  *qcandidate);
   
    delete qlabel;
    delete qcandidate;				       
  }

  return TRUE;
}

bool IIIMInputContextPrivate::getLookupTitle (QString &title)
{
  IIIMF_status st;
  IIIMCF_text text;
  const IIIMP_card16 *u16text;
  int thelength;
  IIIMCF_lookup_choice lookup_choice;
  IIIMCF_context context;
  IIIMICLISTITR itr = _iiimqc->_curic;
 
  title = QString::null;

  context = (*itr)._c;
  if(!context)
	return FALSE;

  st = iiimcf_get_lookup_choice (context, &lookup_choice);
  if(st != IIIMF_STATUS_SUCCESS)
  {
        DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice(): error\n"));
        return FALSE;
  }

  if(!lookup_choice)
  {
        DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_lookup_choice(): error\n"));
        return FALSE;
  }
  

  st = iiimcf_get_lookup_choice_title (lookup_choice, &text);
  if (st != IIIMF_STATUS_SUCCESS)
  {
      DEBUG_DO(qDebug("**IIIMQCF: Failed to get lookup choice title"));
      return FALSE;
  }
  
  st = iiimcf_get_text_utf16string (text, &u16text);
  if (st != IIIMF_STATUS_SUCCESS)
     return FALSE;

  st = iiimcf_get_text_length (text, &thelength);
  if (st != IIIMF_STATUS_SUCCESS)
     return FALSE;
 
   QString *tmp = new QString((const QChar *)u16text, thelength);
   title.append(*tmp);
   delete tmp;
 
    return TRUE;
}




IIIMInputContext::IIIMInputContext ()
{
  DEBUG_DO(qDebug("**IIIMQCF: IIIMInputcontext()"));
  d = new IIIMInputContextPrivate (this);
  iiimcfIsInitialized = FALSE;
  _h = 0;
  keymapper = new KeyMapper();

  iiimlookup = new IIIMQCFLookup(0, this);
  if (!iiimqcf_init_iiim ()){
    DEBUG_DO(qDebug ("**IIIQCF: iiimcf libarary initialization failed!!!\n"));
  }
}

IIIMInputContext::~IIIMInputContext ()
{
  DEBUG_DO(qDebug("**IIIMQCF: ~IIIMInputcontext()"));
  if (iiimlookup)
    delete iiimlookup;
  if(keymapper)
    delete keymapper;
  if(d)
    delete d;
}


QString IIIMInputContext::identifierName ()
{
  return "iiimqcf";
}


QString IIIMInputContext::language ()
{
	QString locale = QTextCodec::locale();
	QString language;
	 if ( locale.startsWith( "zh" ) ) {
            // Chinese language should be formed as "zh_CN", "zh_TW", "zh_HK"
            language = locale.left( 5 );
        } else {
            // other languages should be two-letter ISO 639 language code
            language = locale.left( 2 );
        }
	return language;

}


void IIIMInputContext::reset ()
{
   QInputContext::reset();
}




/*!
  setFocus () is called
  when (input context) onwerWidget gets focus in event
 */
void IIIMInputContext::setFocus ()
{
  /* Intentionally not calling QInputContext::focusWidget()
   in accordance with the commenet in qinputcontext.h
  */
  IIIMICLISTITR itr;
  int pos;
  QString qpreedit;
  IIIMF_status st; 
  IIIMCF_event ev;  

 
  QWidget *keywidget = qApp->focusWidget();
  
  if(!keywidget)	
	return;

  DEBUG_DO(qDebug ("**IIIMQCF: setFocus() for widget(name: %s, WId : %d)",
	  qApp->focusWidget ()->name (),
	  (int)qApp->focusWidget ()->winId ()
	  ));

  itr = get_iiimcf_session_context (keywidget);
  set_current_iiimcf_session_context (keywidget);
 
  cur_context = (*itr)._c; 
 
  st = iiimcf_create_seticfocus_event (&ev);
  if (st != IIIMF_STATUS_SUCCESS)
  { 
     DEBUG_DO(qDebug("**IIIMQCF: iiimcf_create_seticfocus_event(): error"));
     return;
   }

  if (forwardEvent (keywidget, ev, &st))
  {
    DEBUG_DO(qDebug("**IIIMQCF: forward iiim_seticfocus event, and return sucessfully"));
    iiimqcf_event_dispatch (keywidget);
   }
  
  if (get_preedit_data (keywidget, qpreedit, &pos)){
    if(!qpreedit)
	return;
    DEBUG_DO(qDebug("**IIIMQCF: setFocus() preedit string is  %s\n", qpreedit.ascii()));
    sendIMEvent (QEvent::IMCompose, qpreedit, pos, qpreedit.length());    
  }

   iiimlookup->showLookupWindow (keywidget);
   IIim_aux_set_icfocus(this);
}


/*!
  ussetFocus () is (supposed to be) called
  when (input context) onwerWidget gets focus in event.
  But for now, there doesn't seem to be actual implementation
  to call this method,from , say, QWidget class etc.
 */
void IIIMInputContext::unsetFocus ()
{
  QWidget *w = qApp->focusWidget ();
  if (w)
    DEBUG_DO(qDebug ("**IIIMQCF: unsetFocus() for widiget \"%s\"",
	    qApp->focusWidget()->name()));

  iiimlookup->hideLookupWindow ();
  IIim_aux_unset_icfocus(this);
}


void IIIMInputContext::setMicroFocus( int x, int y, int w, int h, QFont *f)
{
  if(!f)
	DEBUG_DO(qDebug("**IIIMQCF: setMicroFocus(): font is null"));
  DEBUG_DO(qDebug ("**IIIMQCF: setMicroFocus():Cursor position (%d, %d), width is %d, height is %d\n", x, y, w, h));
  
  cursor_h = h;

  QWidget *widget = qApp->focusWidget();
  if ( widget ) {
        QPoint p( x, y );
        p = widget->mapFromGlobal( p );
  	cursor_x = p.x();
	cursor_y = p.y();
  	DEBUG_DO(qDebug ("**IIIMQCF: setMicroFocus():local  Cursor position (%d, %d), \
		width is %d, height is %d\n", cursor_x, cursor_y, w, h));
  }
  else
  {
	cursor_x = 0;
        cursor_y = 0;
  }

  iiimlookup->layoutWindow(x, y, w, h);
}


void IIIMInputContext::mouseHandler( int x, QEvent::Type type,
			       Qt::ButtonState button, Qt::ButtonState state )
{
  DEBUG_DO(qDebug("**IIIMQCF: mouseHandler(): x is %d, type is %d, button state is %d,%d\n",\
				 x, type, button, state));
 /* if ( type == QEvent::MouseButtonPress ||
       type == QEvent::MouseButtonDblClick )
    reset();
*/
}


bool IIIMInputContext::iiimqcf_event_dispatch (QWidget *w)
{
  IIIMCF_context c;
  IIIMF_status st;
  IIIMCF_event ev;
  IIIMCF_event_type et;
  int conversion_mode = FALSE;
  
  QString lookup_title;
  QKeyEvent *pqkey;
  QString qpreedit;
  QString qcommitted;
  QStringList candidates;
  int size, first_index, last_index, current_index;
 
  if (_curic == 0)
    return FALSE;
  

  c = (*_curic)._c; 

  if(!c) 
  {
     DEBUG_DO(qDebug("**IIIMQCF: iiimqcf_event_dispatch: get current IC error\n"));	
     return FALSE ;
  }
 
  while ( (st = iiimcf_get_next_event (c, &ev)) == IIIMF_STATUS_SUCCESS){
    st = iiimcf_get_event_type (ev, &et);
    if (st != IIIMF_STATUS_SUCCESS)
      continue;

    switch (et){
    case IIIMCF_EVENT_TYPE_KEYEVENT:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_KEYEVENT "));
      return FALSE;
      /*break;*/
      
    case IIIMCF_EVENT_TYPE_TRIGGER_NOTIFY:
      st = iiimcf_get_current_conversion_mode (c, &conversion_mode);

      if (conversion_mode){
	DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch() : trigger on"));
	sendIMEvent (QEvent::IMStart); 
      } else {
	DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch() : trigger off"));
	iiimlookup->clearLookupChoices ();
	iiimlookup->hideLookupWindow ();
	
	sendIMEvent (QEvent::IMEnd);
      }

      break;
      
    case IIIMCF_EVENT_TYPE_UI_PREEDIT_START:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch() : preedit start"));
      sendIMEvent (QEvent::IMStart); 
      break;
      
    case IIIMCF_EVENT_TYPE_UI_PREEDIT_CHANGE:
      int pos;

      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_PREEDIT_CHANGE"));
      
      if (!get_preedit_data (w, qpreedit, &pos))
      {
        sendIMEvent(QEvent::IMEnd);
	break;
      }
      if(!qpreedit)
	 break;

      if( !this->isComposing()  )
         sendIMEvent (QEvent::IMStart); 
      sendIMEvent (QEvent::IMCompose, qpreedit, pos, qpreedit.length());
      qpreedit = QString::null;
      break;

    case IIIMCF_EVENT_TYPE_UI_PREEDIT_DONE:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_PREEDIT_DONE"));
      get_committed_text (w, qcommitted);
      sendIMEvent(QEvent::IMEnd);
      break;
      
    case IIIMCF_EVENT_TYPE_UI_COMMIT:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_COMMIT"));
      if (!get_committed_text (w, qcommitted))
	break;
     
      if( !this->isComposing()  )
         sendIMEvent (QEvent::IMStart); /*for user-defined preedit/lookup */ 
      sendIMEvent (QEvent::IMEnd, qcommitted,qcommitted.length ());

      break;

      
    case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_START:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_START"));
      d->getLookupChoiceItems (candidates,
			       &size, &first_index,
			       &last_index, &current_index);
     
      if(d->getLookupTitle(lookup_title))
          DEBUG_DO(qDebug("**IIIMQCF: lookup_title is %s\n", lookup_title.ascii())); 
      else
      {	
          DEBUG_DO(qDebug("**IIIMQCF: can not get lookup_title\n"));
          lookup_title.append("Input method");
      }
      iiimlookup->setLookupTitle(lookup_title);
      iiimlookup->setLookupChoices (candidates,
				    size, first_index,
				    last_index, current_index);
      DEBUG_DO(qDebug ("**IIIMQCF: To OPEN LOOKUP WINDOW FROM %s", (*_curic)._w->name()));
      
      size = 0;
      first_index = 0;
      last_index = 0;
      current_index = 0;
      candidates.clear();
 
      iiimlookup->showLookupWindow ((*_curic)._w);
      
      break;
      
    case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE"));

      d->getLookupChoiceItems (candidates,
			       &size, &first_index,
			       &last_index, &current_index);
      
      iiimlookup->setLookupChoices (candidates,
				    size, first_index,
				    last_index, current_index);
      iiimlookup->showLookupWindow ((*_curic)._w);
      DEBUG_DO(qDebug("**IIIQCF: IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE: end\n "));
      break;
      
    case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_DONE:
      DEBUG_DO(qDebug ("IIIMQCF: iiimqcf_event_dispatch():IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_DONE"));
      iiimlookup->clearLookupChoices ();
      iiimlookup->hideLookupWindow ();
      /*sendIMEvent(QEvent::IMEnd);*/
      break;
      
    case IIIMCF_EVENT_TYPE_AUX_START:
	  DEBUG_DO (qDebug ("aux_start"));
	  iiim_aux_start (this, ev);
	  break;
	case IIIMCF_EVENT_TYPE_AUX_DRAW:
	  DEBUG_DO (qDebug ("aux_draw"));
	  iiim_aux_draw (this, ev);
	  break;
	case IIIMCF_EVENT_TYPE_AUX_DONE:
	  DEBUG_DO (qDebug ("aux_done"));
	  iiim_aux_done (this, ev);
	  break;
	case IIIMCF_EVENT_TYPE_AUX_GETVALUES:
	  DEBUG_DO (qDebug ("aux_getvalues_reply"));
	  iiim_aux_getvalues_reply (this, ev);
	  break;
    default:
      DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_event_dispatch():event type 0x%x", et));
      break;
    }
    iiimcf_dispatch_event (c, ev);
    iiimcf_ignore_event (ev);    
  }
  return TRUE;
}


bool IIIMInputContext::get_preedit_data (QWidget *w, QString &text, int *cursor)
{
  IIIMCF_context c;
  IIIMCF_text preedit_text;
  IIIMF_status st;
  QString *qtext;
  
  const IIIMP_card16 *u16text;
  int length;

  if(!w || !cursor)
	return FALSE;

  c = (*_curic)._c;
  st = iiimcf_get_preedit_text (c, &preedit_text, cursor);
  
  if (st != IIIMF_STATUS_SUCCESS)
  {
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_preedit_text(): error\n"));
    return FALSE;
  }
 

  st = iiimcf_get_text_utf16string (preedit_text, &u16text);
  if (st != IIIMF_STATUS_SUCCESS)
  {
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_text_utf16string(): error\n"));
    return FALSE;
  }
  
  iiimcf_get_text_length (preedit_text, &length);
  if (st != IIIMF_STATUS_SUCCESS)
  {
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_text_length(): error\n"));
    return FALSE;
   }

  if(length == 0)
  {
	DEBUG_DO(qDebug("**IIIMQCF: get_preedit_data(): length is zero\n "));
        return FALSE;
  }
  qtext = new QString ((const QChar *)u16text, length);
  text = *qtext;
 
  delete qtext;
 
  DEBUG_DO(qDebug("**IIIMQCF: iiimcf_get_preedit_text(): preedit_text is  %s\n", text.ascii()));  
  return TRUE;
}

bool IIIMInputContext::get_committed_text (QWidget *w, QString &text)
{
  IIIMCF_context c;
  IIIMCF_text committed_text;
  IIIMF_status st;
  QString *qtext;
  
  const IIIMP_card16 *u16text;
  int length;

  if(!w)
	return FALSE;
  
  c = (*_curic)._c;
  st = iiimcf_get_committed_text (c, &committed_text);
  
  if (st != IIIMF_STATUS_SUCCESS)
    return FALSE;

  st = iiimcf_get_text_utf16string (committed_text, &u16text);
  if (st != IIIMF_STATUS_SUCCESS)
    return FALSE;
  
  iiimcf_get_text_length (committed_text, &length);
  if (st != IIIMF_STATUS_SUCCESS)
    return FALSE;
  qtext = new QString ((const QChar *)u16text, length);
  text = *qtext;
  
  return TRUE;
}


bool IIIMInputContext::filterEvent (const QEvent *event)
{
  IIIMCF_keyevent *pkev;
  IIIMCF_event ev;
  IIIMF_status st;
  QKeyEvent *qkev;
  QWidget *keywidget;

  int code;
  char ascii;
  Qt::ButtonState state;
  
  /* We are only interested in key event..*/
    if ((event->type() != QEvent::KeyRelease) &&
      (event->type() != QEvent::KeyPress))
    return FALSE;
  
  /* But for now, let's not care about key release event */
  if (event->type() == QEvent::KeyRelease){
    /* qDebug ("filterEvent=KeyRelease Event ignoring"); */
    return FALSE;
  }

#if 0
  /*
    It is not likely this code will evaluate to true, becuase
    this checking is already done within qapplication_x11.cpp.
    see QApplication::x11ProcessEvent( XEvent* event )
  */
  if (!keywidget->isEnabled () || !keywidget->isInputMethodEnabled ()){
    qDebug ("IIIMInputContext(%d) : not yet composing, thus ignoring",
	      id);
    return FALSE;
  }
#endif
  
  qkev = (QKeyEvent *)event;
  code = qkev->key();
  ascii = qkev->ascii();
  state = qkev->state();
  
  /*  if current status is not Composing, then return FALSE
  if (isNotComposing ())
  return FALSE;

   ugly test code
   see the qnamespace.h in qt library.
   I need a mapping table from QT's value to IIIM
  */

  if (state == Qt::ControlButton){
    if (code == ' ')
      DEBUG_DO(qDebug ("**IIIMQCF: control space pressed"));
  }
  
  pkev = get_iiimcf_keyevent_from (qkev);
  if (!pkev){
    DEBUG_DO(qDebug ("**IIIMQCF: Error creating IIIMCF_keyevent object"));
    goto commit_this_event; 
  }
  
  st = iiimcf_create_keyevent (pkev, &ev);
  if (st != IIIMF_STATUS_SUCCESS){
    DEBUG_DO(qDebug ("**IIIMQCF: Error creating IIIMCF_keyevent object"));
    goto commit_this_event;
  }
  /* delete pkev */
  delete pkev;
  
  /* FIX ME */
  keywidget = qApp->focusWidget();
  
  if(!keywidget)
	return FALSE;
  DEBUG_DO(qDebug("**IIIMQCF: filterEvent(), get focusWidget's name is %s, id is %d",\
		 keywidget->name(), (int)keywidget->winId()));  

  if (forwardEvent (keywidget, ev, &st)){/*send messages to IIIMSF */
    if(iiimqcf_event_dispatch (keywidget))
	return TRUE;
    else
   	 return FALSE; 
  }
  if(st != IIIMF_STATUS_EVENT_NOT_FORWARDED && st != IIIMF_STATUS_IC_INVALID)
  {
        
        DEBUG_DO(qDebug("**IIIMQCF: status is not IIIMF_STATUS_EVENT_NOT_FORWARDED"));
	return FALSE;
   }
  
  
  DEBUG_DO(qDebug("**IIIMQCF: status is  IIIMF_STATUS_EVENT_NOT_FORWARDED"));
  commit_this_event:
	/* TODO */
  	return FALSE;

}


IIIMCF_handle IIIMInputContext::iiimqcf_init_iiim (void)
{
  IIIMF_status st;
  IIIMCF_attr attr;

  if (iiimcfIsInitialized){
    DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_init_iiim : Handle alread exists, returning"));
    return _h;
  }
  
  st = iiimcf_initialize (IIIMCF_ATTR_NULL);
  if (st != IIIMF_STATUS_SUCCESS){
    return 0;
  }

  st = iiimcf_create_attr (&attr);
  if (st != IIIMF_STATUS_SUCCESS){
    return 0;
  }
  st = iiimcf_attr_put_string_value (attr,
				     IIIMCF_ATTR_CLIENT_TYPE,
				     "QT IIIMCF Module");
  if (st != IIIMF_STATUS_SUCCESS){
    return 0;
  }
  
  DEBUG_DO(qDebug ("**IIIMQCF: iiimqcf_init_iiim : Creating IIIMCF handle"));
#if 0
  int i = 1;
  while (i);
#endif
  st = iiimcf_create_handle (attr, &_h);
  
  if (st != IIIMF_STATUS_SUCCESS){
    return 0;
  }
  
  iiim_setup_aux_object(_h);
  aux = NULL;
 
  st = iiimcf_destroy_attr (attr);
  iiimcfIsInitialized = TRUE;
  return _h;
}


IIIMCF_keyevent * IIIMInputContext::get_iiimcf_keyevent_from (QKeyEvent *kev)
{
  IIIMCF_keyevent *pkev = new IIIMCF_keyevent;
  
  if (pkev == 0){
    DEBUG_DO(qDebug ("**IIIMQCF: get_iiimcf_keyevent_from() failed"));
    return 0;
  }
  
  pkev->keycode = keymapper->q2i(kev->key());
  pkev->keychar = kev->ascii();
  pkev->modifier = keymapper->modifier (kev->state());
  
  DEBUG_DO(qDebug("**IIIMQCF: get_iiimcf_keyevent_from(): keychar is %c, keycode is %d, modifier is %d\n", \
		  pkev->keychar, pkev->keycode, pkev->modifier)); 
  return pkev;
}

void IIIMInputContext::im_context_aux_set_values (IIIMCF_context context, IIIMCF_event ev)
{
  IIIMF_status st;  

  QWidget *keywidget = qApp->focusWidget();
  if(!keywidget)
	return;

  DEBUG_DO(qDebug ("**IIIMQCF: setFocus() for widget(name: %s, WId : %d)",
	  qApp->focusWidget ()->name (),
	  (int)qApp->focusWidget ()->winId ()
	  ));
 
  if (forwardEvent (keywidget, ev, &st))
  {
    DEBUG_DO(qDebug("**IIIMQCF: forward im_context_aux_set_values, and return sucessfully"));
    iiimqcf_event_dispatch (keywidget);
   }
  
}

void IIIMInputContext::im_context_change_conversion_mode(IIIMCF_context context, char *conv_mode)
{
  QWidget *keywidget = qApp->focusWidget();
  IIIMF_status st;

  if(!keywidget)
	return;
  DEBUG_DO(qDebug ("**IIIMQCF: setFocus() for widget(name: %s, WId : %d)",
	  qApp->focusWidget ()->name (),
	  (int)qApp->focusWidget ()->winId ()
	  ));

  IIIMCF_event event;
  if (conv_mode && !strcmp (conv_mode, "on"))
    {
      st = iiimcf_create_trigger_notify_event (TRUE, &event);
      if (st != IIIMF_STATUS_SUCCESS)
	return;
    }
  else if (conv_mode && !strcmp (conv_mode, "off"))
    {
      IIIMF_status st;
      st = iiimcf_create_trigger_notify_event (FALSE, &event);
      if (st != IIIMF_STATUS_SUCCESS)
	return;
    }
  if (forwardEvent (keywidget, event, &st))
  {
    DEBUG_DO(qDebug("**IIIMQCF: forward , im_context_change_conversion_mode() and return sucessfully"));
    iiimqcf_event_dispatch (keywidget);
   }
}


QWidget* IIIMInputContext::get_focus_widget()
{
  return (qApp->focusWidget());
}


bool IIIMInputContext::forwardEvent (QWidget *keywidget, IIIMCF_event ev, IIIMF_status *st_ret)
{
  IIIMCF_context c;
  IIIMICLISTITR itr;
  IIIMF_status st;

  if(!keywidget)
	return FALSE;
    
  DEBUG_DO(qDebug ("**IIIMQCF: forwardEvent() on widget %s", keywidget->name ()));

  itr = get_iiimcf_session_context (keywidget);

  c = (*itr)._c;
  
  if(!c)
  {
    DEBUG_DO(qDebug("**IIIMQCF: forwardEvent(): get ic error\n"));
    if(st_ret)
       *st_ret = IIIMF_STATUS_EVENT_NOT_FORWARDED;
    return FALSE;
  }

  /* Send messages to IIIMSF */
  st = iiimcf_forward_event (c, ev);
  if(st_ret)
     *st_ret = st;

  switch (st){
   
  case IIIMF_STATUS_SUCCESS:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event:IIIMF_STATUS_SUCCESS\n "));
    break;
  case IIIMF_STATUS_IC_INVALID:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event:IIIMF_STATUS_IC_INVALID\n"));
  case IIIMF_STATUS_EVENT_NOT_FORWARDED:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event: IIIMF_STATUS_EVENT_NOT_FORWARDED\n"));
    break;
  case IIIMF_STATUS_STREAM_SEND:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event:IIIMF_STATUS_STREAM_SEND\n"));
  case IIIMF_STATUS_STREAM_RECEIVE:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event:IIIMF_STATUS_STREAM_RECEIVE\n"));
  case IIIMF_STATUS_CONNECTION_CLOSED:
    DEBUG_DO(qDebug("**IIIMQCF: iiimcf_forward_event:IIIMF_STATUS_CONNECTION_CLOSED\n"));
    /*et_error_message (context_iiim);*/
    iiimcf_ignore_event (ev);
    break;
  default:
    iiimcf_ignore_event (ev);
    /*status_window_set_text (context_iiim->status_window, "");*/
    break;
  }

  return (st == IIIMF_STATUS_SUCCESS);
}

bool IIIMInputContext::set_current_iiimcf_session_context (QWidget *widget)
{
  if(!widget)
	return FALSE;
  IIIMICLISTITR it = get_iiimcf_session_context (widget);
  _curic = it;
  if (it != _iclist.end ()){
    _curic = it;
    return TRUE;
  } else
    return FALSE;
}


IIIMCF_handle IIIMInputContext::get_iiimcf_handle()
{
	if(_h)
		return _h;
	else
		return NULL;

}


IIIMInputContext::IIIMICLISTITR
IIIMInputContext::search_iiimiclist_for (QWidget *widget)
{
  if(!widget)
	return NULL;

  IIIMICLISTITR it = _iclist.begin ();

  DEBUG_DO(qDebug ("**IIIMQCF: Searcing widget %s", widget->name()));
  DEBUG_DO(qDebug("**IIIMQCF: length of iclist is %d", _iclist.count()));

  /* Currently, onley keep one IC for one standalone QT application, will support multiple IC within on QT application in
     latter. So mark code below currently. 
  */
  /*while (it != _iclist.end ()){
    DEBUG_DO(qDebug ("**IIIMQCF: search_iiimiclist_for ():%s\n", (*it)._w->name()));
    if ((*it)._w == widget)
      break;
    else
      it++;
  }
  if (it == _iclist.end ())
    DEBUG_DO(qDebug ("**IIIMQCF: Search Failed"));
  else
    DEBUG_DO(qDebug ("**IIIMQCF: Search Success"));
  */

  return it; // it == _iclist.end ();
}


IIIMInputContext::IIIMICLISTITR
IIIMInputContext::create_iiimcf_session_context (QWidget *widget)
{
  if(!widget)
	return NULL;

  IIIMICLISTITR it = search_iiimiclist_for (widget);
  IIIMInputContextID iiimic;
  
  if ( (it == _iclist.end ()) ||
       !(*it)._c ){
    IIIMCF_attr attr;
    IIIMF_status st;
    st = iiimcf_create_attr (&attr);
    st = iiimcf_create_context (_h, NULL, &iiimic._c);

    DEBUG_DO(qDebug ("**IIIMQCF: create_iiimcf_session_context():creating IIIMCF_context"));

    iiimic._w = widget;
    it = _iclist.prepend (iiimic);
    iiimcf_destroy_attr (attr);
    
  }
  return it;
}

IIIMInputContext::IIIMICLISTITR
IIIMInputContext::get_iiimcf_session_context (QWidget *widget, bool doCreate)
{
  if(!widget)
	return NULL;

  IIIMICLISTITR it = search_iiimiclist_for (widget);
  
  if ( (it == _iclist.end () || !(*it)._c) &&  doCreate){
    DEBUG_DO(qDebug ("**IIIMQCF: get_iiimcf_session_context() : need to create new IIIMCF_context on %s", widget->name()));
    return create_iiimcf_session_context (widget);
  }
  return it;
}



bool IIIMInputContext::isPreeditRelocationEnabled()
{
    return ( language() == "ja" ); 
}


bool IIIMInputContext::isPreeditPreservationEnabled()
{
     return ( language() == "ja" );
}

