PageRenderTime 838ms CodeModel.GetById 120ms app.highlight 354ms RepoModel.GetById 142ms app.codeStats 1ms

/src/scim-python-engine.cpp

http://scim-python.googlecode.com/
C++ | 1043 lines | 770 code | 201 blank | 72 comment | 50 complexity | 2763000dc776399f2aa316b4f1c03642 MD5 | raw file
   1/* vim:set noet ts=4: */
   2/** 
   3 * scim-python
   4 * 
   5 * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
   6 *
   7 *
   8 * This library is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU Lesser General Public
  10 * License as published by the Free Software Foundation; either
  11 * version 2 of the License, or (at your option) any later version.
  12 *
  13 * This library is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU Lesser General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU Lesser General Public
  19 * License along with this program; if not, write to the
  20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  21 * Boston, MA  02111-1307  USA
  22 *
  23 * $Id: $
  24 */
  25#include "scim-python.h"
  26#if Py_UNICODE_SIZE == 2
  27#  include <glib.h>
  28#endif
  29
  30extern PyTypeObject PyIMEngineType;
  31
  32struct PyIMEngineObject {
  33	PyListObject list;
  34	/* Type-specific fields go here. */
  35	PyIMEngine engine;
  36};
  37
  38
  39PyIMEngine::PyIMEngine (
  40		PyObject			*self,
  41		PyObject 			*factory,
  42		PyObject			*config,
  43		const String		&encoding,
  44		int				  	id)
  45  : IMEngineInstanceBase (PyIMEngineFactory::from_pyobject (factory), 
  46	encoding, id), 
  47	self (self), 
  48	factory (factory),
  49	config (config)
  50{
  51	Py_INCREF (self);
  52	Py_INCREF (factory);
  53	Py_INCREF (config);
  54
  55	reload_signal_connection = 
  56		PyConfig_from_pyobject (config)->signal_connect_reload (slot (this, &PyIMEngine::reload_config));
  57}
  58
  59PyIMEngine::~PyIMEngine ()
  60{
  61	reload_signal_connection.disconnect ();
  62
  63	Py_XDECREF (config);
  64	Py_XDECREF (factory);
  65	Py_XDECREF (self);
  66}
  67
  68void
  69PyIMEngine::operator delete (void *p)
  70{
  71}
  72
  73#define PY_CALL(fun) ({								\
  74	PyObject *pValue = NULL;						\
  75	PyObject *pFunc = NULL;							\
  76	pFunc = PyObject_GetAttrString (this->self, fun);\
  77	if (pFunc != NULL) {							\
  78		pValue = PyObject_CallObject (pFunc, NULL);	\
  79		Py_DECREF (pFunc);							\
  80	}												\
  81	pValue;})
  82
  83#define PY_CALL_1(fun, arg1) ({						\
  84	PyObject *pValue = NULL;						\
  85	PyObject *pFunc = NULL;							\
  86	PyObject *pArgs = NULL;							\
  87	pFunc = PyObject_GetAttrString (this->self, fun);\
  88	if (pFunc != NULL) {							\
  89		pArgs = Py_BuildValue ("(O)", arg1);		\
  90		pValue = PyObject_CallObject (pFunc, pArgs);\
  91		Py_DECREF (pFunc);							\
  92		Py_DECREF (pArgs);							\
  93	}												\
  94	pValue;})
  95
  96#define PY_CHECK_RET(v)							\
  97	if (v == NULL) {							\
  98		PyErr_Print ();							\
  99		return;									\
 100	}
 101
 102#define PY_CHECK_RET_VAL(v, val)				\
 103	if (v == NULL) {							\
 104		PyErr_Print ();							\
 105		return val;								\
 106	}
 107
 108bool 
 109PyIMEngine::process_key_event (const KeyEvent &key)
 110{
 111	PyObject *pValue;
 112
 113	bool result = false;
 114
 115	pValue = PY_CALL_1("process_key_event", PyKeyEvent_New (key));
 116
 117	PY_CHECK_RET_VAL (pValue, false);
 118
 119	result = (pValue == Py_True); 
 120	Py_XDECREF (pValue);
 121
 122	return result;
 123}
 124
 125PyDoc_STRVAR (IMEngine_process_key_event__doc__,
 126"process_key_event (key_event)\n\n"
 127"This function will be called, when user press keyboard in client application.\n"
 128"IM developer must implement it in sub class.\n");
 129PyObject *
 130PyIMEngine::py_process_key_event (PyIMEngineObject *self, PyObject *args)
 131{
 132	PyErr_SetString (PyExc_NotImplementedError, "process_key_event is not implemented!");
 133	return NULL;
 134}
 135
 136
 137void
 138PyIMEngine::move_preedit_caret (unsigned int pos)
 139{
 140	PyObject *pValue = NULL;
 141
 142	pValue = PY_CALL_1 ("move_preedit_caret", PyInt_FromLong ((unsigned long)pos));
 143
 144	PY_CHECK_RET (pValue);
 145	Py_XDECREF (pValue);
 146}
 147
 148PyDoc_STRVAR (IMEngine_move_preedit_caret__doc__,
 149"move_preedit_caret (pos)\n\n"
 150"This function will be called, when client move preedit caret.\n"
 151"IM developer may override it in sub class.\n");
 152PyObject *
 153PyIMEngine::py_move_preedit_caret (PyIMEngineObject *self, PyObject *args)
 154{
 155	unsigned int pos;
 156
 157	if (!PyArg_ParseTuple (args, "I:move_preedit_caret", &pos))
 158		return NULL;
 159
 160	self->engine.IMEngineInstanceBase::move_preedit_caret (pos);
 161
 162	Py_INCREF (Py_None);
 163	return Py_None;
 164
 165}
 166
 167void
 168PyIMEngine::select_candidate (unsigned int index)
 169{
 170	PyObject *pValue = NULL;
 171
 172	pValue = PY_CALL_1 ("select_candidate", PyInt_FromLong ((unsigned long)index));
 173	PY_CHECK_RET (pValue);
 174
 175	Py_XDECREF (pValue);
 176}
 177
 178
 179PyDoc_STRVAR (IMEngine_select_candidate__doc__,
 180"select_candidate (index)\n\n"
 181"IM developer may override it in sub class.\n");
 182PyObject *
 183PyIMEngine::py_select_candidate (PyIMEngineObject *self, PyObject *args)
 184{
 185	unsigned int index;
 186
 187	if (!PyArg_ParseTuple (args, "I:select_candidate", &index))
 188		return NULL;
 189
 190	self->engine.IMEngineInstanceBase::select_candidate (index);
 191
 192	Py_INCREF (Py_None);
 193	return Py_None;
 194
 195}
 196
 197void
 198PyIMEngine::update_lookup_table_page_size (unsigned int page_size)
 199{
 200	PyObject *pValue = NULL;
 201
 202	pValue = PY_CALL_1 ("update_lookup_table_page_size", PyInt_FromLong ((unsigned long)page_size));
 203	PY_CHECK_RET (pValue);
 204
 205	Py_XDECREF (pValue);
 206}
 207
 208
 209PyDoc_STRVAR (IMEngine_update_lookup_table_page_size__doc__,
 210"update_lookup_table_page_size (page_size)\n\n"
 211"This function will be called, when page size of lookup table is changed.\n"
 212"IM developer may override it in sub class.\n");
 213PyObject *
 214PyIMEngine::py_update_lookup_table_page_size (PyIMEngineObject *self, PyObject *args)
 215{
 216	unsigned int page_size;
 217
 218	if (!PyArg_ParseTuple (args, "I:update_lookup_table_page_size", &page_size))
 219		return NULL;
 220
 221	self->engine.IMEngineInstanceBase::move_preedit_caret (page_size);
 222
 223	Py_INCREF (Py_None);
 224	return Py_None;
 225
 226}
 227
 228void
 229PyIMEngine::lookup_table_page_up ()
 230{
 231	PyObject *pValue = NULL;
 232	pValue = PY_CALL ("lookup_table_page_up");
 233	PY_CHECK_RET (pValue);
 234	Py_XDECREF (pValue);
 235}
 236
 237PyDoc_STRVAR (IMEngine_lookup_table_page_up__doc__,
 238"lookup_table_page_up ()\n\n"
 239"This function will be called, when user press page up button in candidate window.\n"
 240"IM developer may override it in sub class.\n");
 241PyObject *
 242PyIMEngine::py_lookup_table_page_up (PyIMEngineObject *self)
 243{
 244	self->engine.IMEngineInstanceBase::lookup_table_page_up ();
 245
 246	Py_INCREF (Py_None);
 247	return Py_None;
 248}
 249
 250void
 251PyIMEngine::lookup_table_page_down ()
 252{
 253	PyObject *pValue = NULL;
 254
 255	pValue = PY_CALL ("lookup_table_page_down");
 256	PY_CHECK_RET (pValue);
 257
 258	Py_XDECREF (pValue);
 259}
 260
 261PyDoc_STRVAR (IMEngine_lookup_table_page_down__doc__,
 262"lookup_table_page_down ()\n\n"
 263"This function will be called, when user press page down button in candidate window.\n"
 264"IM developer may override it in sub class.\n");
 265PyObject *
 266PyIMEngine::py_lookup_table_page_down (PyIMEngineObject *self)
 267{
 268	self->engine.IMEngineInstanceBase::lookup_table_page_down ();
 269
 270	Py_INCREF (Py_None);
 271	return Py_None;
 272}
 273
 274void
 275PyIMEngine::reset ()
 276{
 277	PyObject *pValue = NULL;
 278
 279	pValue = PY_CALL ("reset");
 280	PY_CHECK_RET (pValue);
 281
 282	Py_XDECREF (pValue);
 283}
 284
 285PyDoc_STRVAR (IMEngine_reset__doc__,
 286"reset ()\n\n"
 287"This function will be called, when im client request reseting engine.\n"
 288"IM developer may override it in sub class.\n");
 289PyObject *
 290PyIMEngine::py_reset (PyIMEngineObject *self)
 291{
 292	self->engine.IMEngineInstanceBase::reset ();
 293
 294	Py_INCREF (Py_None);
 295	return Py_None;
 296}
 297
 298void
 299PyIMEngine::focus_in ()
 300{
 301	PyObject *pValue = NULL;
 302
 303	pValue = PY_CALL ("focus_in");
 304	PY_CHECK_RET (pValue);
 305
 306	Py_XDECREF (pValue);
 307}
 308
 309PyDoc_STRVAR (IMEngine_focus_in__doc__,
 310"focus_in ()\n\n"
 311"This function will be called, when engine is focused in.\n"
 312"IM developer may override it in sub class.\n");
 313PyObject *
 314PyIMEngine::py_focus_in (PyIMEngineObject *self)
 315{
 316	self->engine.IMEngineInstanceBase::focus_in ();
 317
 318	Py_INCREF (Py_None);
 319	return Py_None;
 320}
 321
 322void
 323PyIMEngine::focus_out ()
 324{
 325	PyObject *pValue = NULL;
 326
 327	pValue = PY_CALL ("focus_out");
 328	PY_CHECK_RET (pValue);
 329
 330	Py_XDECREF (pValue);
 331}
 332
 333PyDoc_STRVAR (IMEngine_focus_out__doc__,
 334"focus_out ()\n\n"
 335"This function will be called, when engine is focused out.\n"
 336"IM developer may override it in sub class.\n");
 337PyObject *
 338PyIMEngine::py_focus_out (PyIMEngineObject *self)
 339{
 340	self->engine.IMEngineInstanceBase::focus_out ();
 341
 342	Py_INCREF (Py_None);
 343	return Py_None;
 344}
 345
 346void
 347PyIMEngine::trigger_property (const String &property)
 348{
 349	PyObject *pValue = NULL;
 350
 351	pValue = PY_CALL_1 ("trigger_property", PyString_FromString (property.c_str ()));
 352	PY_CHECK_RET (pValue);
 353
 354	Py_XDECREF (pValue);
 355}
 356
 357
 358PyDoc_STRVAR (IMEngine_trigger_property__doc__,
 359"trigger_property (prop_name)\n\n"
 360"This function will be called, when user presses property button on panel.\n"
 361"IM developer may override it in sub class.\n");
 362PyObject *
 363PyIMEngine::py_trigger_property (PyIMEngineObject *self, PyObject *args)
 364{
 365	char *property;
 366
 367	if (!PyArg_ParseTuple (args, "s:trigger_property", &property))
 368		return NULL;
 369
 370	self->engine.IMEngineInstanceBase::trigger_property (String (property));
 371
 372	Py_INCREF (Py_None);
 373	return Py_None;
 374
 375}
 376
 377void
 378PyIMEngine::process_helper_event (const String &helper_uuid, const Transaction &trans)
 379{
 380	//IMEngineInstanceBase::process_helper_event (helper_uuid, trans);
 381}
 382
 383PyDoc_STRVAR (IMEngine_process_helper_event__doc__,
 384"process_helper (uuid, trans)\n\n"
 385"This function will be called, when user ....\n"
 386"IM developer may override it in sub class.\n");
 387PyObject *
 388PyIMEngine::py_process_helper_event (PyIMEngineObject *self, PyObject *args)
 389{
 390	// TODO: 
 391	char *helper_uuid;
 392	PyObject *trans;
 393
 394	if (!PyArg_ParseTuple (args, "sO:process_helper_event", &helper_uuid, &trans))
 395		return NULL;
 396
 397	//self->engine.IMEngineInstanceBase::update_client_capabilities (cap);
 398
 399	Py_INCREF (Py_None);
 400	return Py_None;
 401
 402}
 403
 404void
 405PyIMEngine::update_client_capabilities (unsigned int cap)
 406{
 407	PyObject *pValue = NULL;
 408
 409	pValue = PY_CALL_1 ("update_client_capabilities", PyInt_FromLong ((unsigned long)cap));
 410	PY_CHECK_RET (pValue);
 411
 412	Py_XDECREF (pValue);
 413}
 414
 415PyDoc_STRVAR (IMEngine_update_client_capabilities__doc__,
 416"update_client_capabilities (cap)\n\n"
 417"This function will be called, when im client request update client capabilities.\n"
 418"IM developer may override it in sub class.\n");
 419PyObject *
 420PyIMEngine::py_update_client_capabilities (PyIMEngineObject *self, PyObject *args)
 421{
 422	unsigned int cap;
 423
 424	if (!PyArg_ParseTuple (args, "I:update_client_capabilities", &cap))
 425		return NULL;
 426	self->engine.IMEngineInstanceBase::update_client_capabilities (cap);
 427
 428	Py_INCREF (Py_None);
 429	return Py_None;
 430
 431}
 432
 433
 434void 
 435PyIMEngine::reload_config (const ConfigPointer &config)
 436{
 437	PyObject *pFunc = NULL;
 438	PyObject *pValue = NULL;
 439	PyObject *pArgs = NULL;
 440
 441	pFunc = PyObject_GetAttrString (this->self, "reload_config");
 442	if (pFunc == NULL)
 443		goto _failed_out;
 444
 445	pArgs = Py_BuildValue ("(O)", this->config);
 446	if (pArgs == NULL)
 447		goto _failed_out;
 448
 449	pValue = PyObject_CallObject (pFunc, pArgs);
 450	if (pValue == NULL)
 451		goto _failed_out;
 452
 453	goto _success_out;
 454
 455_failed_out:
 456	PyErr_Print ();
 457_success_out:
 458	Py_XDECREF (pArgs);
 459	Py_XDECREF (pFunc);
 460	Py_XDECREF (pValue);
 461}
 462
 463IMEngineInstanceBase *
 464PyIMEngine::from_pyobject (PyObject *object)
 465{
 466	PyIMEngineObject *self = (PyIMEngineObject *)object;
 467	return (IMEngineInstanceBase *) &self->engine;
 468}
 469
 470PyObject *
 471PyIMEngine::py_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
 472{
 473	PyIMEngine *self;
 474	self = (PyIMEngine *)type->tp_alloc (type, 0);
 475	return (PyObject *)self;
 476}
 477
 478
 479int
 480PyIMEngine::py_init (PyIMEngineObject *self, PyObject *args, PyObject *kwds)
 481{
 482	PyObject *factory;
 483	PyObject *config;
 484	char *encoding;
 485	int id;
 486
 487	if (!PyArg_ParseTuple (args, "OOsi:__init__", &factory, &config, &encoding, &id)) {
 488		PyErr_Print ();
 489		return -1;
 490	}
 491
 492	new (&self->engine) PyIMEngine ((PyObject *)self, 
 493								factory,
 494								config,
 495								String (encoding), id);
 496	return 0;
 497}
 498
 499void
 500PyIMEngine::py_dealloc (PyIMEngineObject *self)
 501{
 502	((PyObject *)self)->ob_type->tp_free (self);
 503}
 504
 505PyDoc_STRVAR (IMEngine_show_preedit_string__doc__,
 506"show_preedit_string ()\n\n"
 507"Hide the preedit string.\n");
 508PyObject *
 509PyIMEngine::py_show_preedit_string (PyIMEngineObject *self)
 510{
 511	self->engine.show_preedit_string ();
 512
 513	Py_INCREF (Py_None);
 514	return Py_None;
 515}
 516
 517
 518PyDoc_STRVAR (IMEngine_show_aux_string__doc__,
 519"show_aux_string ()\n\n"
 520"Hide the aux string.\n");
 521PyObject *
 522PyIMEngine::py_show_aux_string (PyIMEngineObject *self)
 523{
 524	self->engine.show_aux_string ();
 525
 526	Py_INCREF (Py_None);
 527	return Py_None;
 528}
 529
 530PyDoc_STRVAR (IMEngine_show_lookup_table__doc__,
 531"show_lookup_table ()\n\n"
 532"Hide the lookup table.\n");
 533PyObject *
 534PyIMEngine::py_show_lookup_table (PyIMEngineObject *self)
 535{
 536	self->engine.show_lookup_table ();
 537
 538	Py_INCREF (Py_None);
 539	return Py_None;
 540}
 541
 542PyDoc_STRVAR (IMEngine_hide_preedit_string__doc__,
 543"hide_preedit_string ()\n\n"
 544"Hide the preedit string.\n");
 545PyObject *
 546PyIMEngine::py_hide_preedit_string (PyIMEngineObject *self)
 547{
 548	self->engine.hide_preedit_string ();
 549
 550	Py_INCREF (Py_None);
 551	return Py_None;
 552}
 553
 554PyDoc_STRVAR (IMEngine_hide_aux_string__doc__,
 555"hide_aux_string ()\n\n"
 556"Hide the aux string.\n");
 557PyObject *
 558PyIMEngine::py_hide_aux_string (PyIMEngineObject *self)
 559{
 560	self->engine.hide_aux_string ();
 561
 562	Py_INCREF (Py_None);
 563	return Py_None;
 564}
 565
 566PyDoc_STRVAR (IMEngine_hide_lookup_table__doc__,
 567"hide_lookup_table ()\n\n"
 568"Hide the lookup table.\n");
 569PyObject *
 570PyIMEngine::py_hide_lookup_table (PyIMEngineObject *self)
 571{
 572	self->engine.hide_lookup_table ();
 573
 574	Py_INCREF (Py_None);
 575	return Py_None;
 576}
 577
 578PyDoc_STRVAR (IMEngine_update_preedit_caret__doc__,
 579"update_preedit_caret (pos)\n\n"
 580"Update the caret position of preedit string.\n");
 581PyObject *
 582PyIMEngine::py_update_preedit_caret (PyIMEngineObject *self, PyObject *args)
 583{
 584	int caret;
 585	if (!PyArg_ParseTuple (args, "i:update_preedit_caret", &caret))
 586			return NULL;
 587	self->engine.update_preedit_caret (caret);
 588
 589	Py_INCREF (Py_None);
 590	return Py_None;
 591}
 592
 593/*
 594void update_preedit_string (const WideString	&str,
 595							const AttributeList &attrs = AttributeList ());
 596*/
 597PyDoc_STRVAR (IMEngine_update_preedit_string__doc__,
 598"update_preedit_string (text, attrs = None)\n\n"
 599"Update preedit string with attrs.\n");
 600PyObject *
 601PyIMEngine::py_update_preedit_string (PyIMEngineObject *self, PyObject *args)
 602{
 603	Py_UNICODE *str = NULL;
 604	PyObject *pAttrs = NULL;
 605	AttributeList attrs;
 606
 607#if Py_UNICODE_SIZE == 4
 608
 609
 610	if (!PyArg_ParseTuple (args, "u|O:update_preedit_string", &str, &pAttrs))
 611		return NULL;
 612
 613	self->engine.update_preedit_string (WideString ((wchar_t *)str), 
 614								Attributes_FromTupleOrList (pAttrs));
 615#else
 616	gunichar *unistr = NULL;
 617	int size = 0;
 618
 619	if (!PyArg_ParseTuple (args, "u#|O:update_preedit_string", &str, &size, &pAttrs))
 620		return NULL;
 621
 622	unistr = g_utf16_to_ucs4 (str, size, NULL, NULL, NULL);
 623
 624	self->engine.update_preedit_string (WideString ((wchar_t *)unistr), 
 625								Attributes_FromTupleOrList (pAttrs));
 626	g_free (unistr);
 627
 628#endif
 629
 630	Py_INCREF (Py_None);
 631	return Py_None;
 632
 633}
 634
 635/*
 636 * void update_aux_string (const WideString	&str,
 637 * 						   const AttributeList &attrs = AttributeList ());
 638 */
 639PyDoc_STRVAR (IMEngine_update_aux_string__doc__,
 640"update_aux_string (text, attrs = None)\n\n"
 641"Update aux string with attrs.\n");
 642PyObject *
 643PyIMEngine::py_update_aux_string (PyIMEngineObject *self, PyObject *args)
 644{
 645	Py_UNICODE *str = NULL;
 646	PyObject *pAttrs = NULL;
 647	AttributeList attrs;
 648
 649#if Py_UNICODE_SIZE == 4
 650	if (!PyArg_ParseTuple (args, "u|O:update_aux_string", &str, &pAttrs))
 651		return NULL;
 652
 653	self->engine.update_aux_string (WideString ((wchar_t *)str),
 654								Attributes_FromTupleOrList (pAttrs));
 655#else
 656	int size = 0;
 657	gunichar *unistr = NULL;
 658	if (!PyArg_ParseTuple (args, "u#|O:update_aux_string", &str, &size, &pAttrs))
 659		return NULL;
 660
 661	unistr = g_utf16_to_ucs4 (str, size, NULL, NULL, NULL);
 662	self->engine.update_aux_string (WideString ((wchar_t *)unistr),
 663								Attributes_FromTupleOrList (pAttrs));
 664	g_free (unistr);
 665#endif
 666
 667	Py_INCREF (Py_None);
 668	return Py_None;
 669}
 670
 671/*
 672 * void update_lookup_table (const LookupTable &table);
 673 */
 674PyDoc_STRVAR (IMEngine_update_lookup_table__doc__,
 675"update_lookup_table (lookup_table)\n\n"
 676"Update the lookup table that contains candidates.\n");
 677PyObject *
 678PyIMEngine::py_update_lookup_table (PyIMEngineObject *self, PyObject *args)
 679{
 680
 681	PyObject *lookup_table = NULL;
 682
 683	if (!PyArg_ParseTuple (args, "O:update_lookup_table", &lookup_table))
 684		return NULL;
 685
 686	self->engine.update_lookup_table (PyLookupTable::from_pyobject (lookup_table));
 687
 688	Py_INCREF (Py_None);
 689	return Py_None;
 690}
 691
 692/*
 693 * void commit_string (const WideString &str);
 694 */
 695PyDoc_STRVAR (IMEngine_commit_string__doc__,
 696"commit_string (text)\n\n"
 697"Commit text to im client.\n");
 698PyObject *
 699PyIMEngine::py_commit_string (PyIMEngineObject *self, PyObject *args)
 700{
 701	Py_UNICODE *str = NULL;
 702
 703#if Py_UNICODE_SIZE == 4
 704	if (!PyArg_ParseTuple (args, "u:commit_string", &str))
 705		return NULL;
 706
 707	self->engine.commit_string (WideString ((wchar_t *)str));
 708#else
 709	int size = 0;
 710	gunichar *unistr = NULL;
 711
 712	if (!PyArg_ParseTuple (args, "u#:commit_string", &str, &size))
 713		return NULL;
 714
 715	unistr = g_utf16_to_ucs4 (str, size, NULL, NULL, NULL);
 716	self->engine.commit_string (WideString ((wchar_t *)unistr));
 717	g_free (unistr);
 718#endif
 719
 720	Py_INCREF (Py_None);
 721	return Py_None;
 722}
 723
 724/*
 725 * void forward_key_event (const KeyEvent &key);
 726 */
 727PyDoc_STRVAR (IMEngine_forward_key_event__doc__,
 728"forward_key_event (key_event)\n\n"
 729"Forward a key_event (scim.KeyEvent) to im client.\n");
 730PyObject *
 731PyIMEngine::py_forward_key_event (PyIMEngineObject *self, PyObject *args)
 732{
 733	Py_INCREF (Py_None);
 734	return Py_None;
 735}
 736
 737/*
 738 * void register_properties (const PropertyList &properties);
 739 */
 740PyDoc_STRVAR (IMEngine_register_properties__doc__,
 741"register_properties (props)\n\n"
 742"Regitser props (a list of scim.Property) with IMEngine.\n");
 743PyObject *
 744PyIMEngine::py_register_properties (PyIMEngineObject *self, PyObject *args)
 745{
 746	PyObject *props = NULL;
 747	PropertyList proplist;
 748	int i;
 749
 750	if (!PyArg_ParseTuple (args, "O:register_properties", &props))
 751		return NULL;
 752
 753	if (PyList_Check (props)) {
 754		for (i = 0; i < PyList_Size (props); i++) {
 755			PyObject *prop = PyList_GetItem (props, i);
 756			proplist.push_back (PyProperty_AsProperty (prop));
 757		}
 758	}
 759	else if (PyTuple_Check (props)) {
 760		for (i = 0; i < PyTuple_Size (props); i++) {
 761			PyObject *prop = PyTuple_GetItem (props, i);
 762			proplist.push_back (PyProperty_AsProperty (prop));
 763		}
 764
 765	}
 766	else {
 767		PyErr_SetString (PyExc_TypeError, "the argument must be a list or a tuple that contains propertys");
 768		return NULL;
 769	}
 770
 771	self->engine.register_properties (proplist);
 772
 773	Py_INCREF (Py_None);
 774	return Py_None;
 775}
 776
 777/*
 778 * void update_property (const Property &property);
 779 */
 780PyDoc_STRVAR (IMEngine_update_property__doc__,
 781"update_property (property)\n\n"
 782"Update property (scim.Property) with IMEngine.\n");
 783PyObject *
 784PyIMEngine::py_update_property (PyIMEngineObject *self, PyObject *args)
 785{
 786	PyObject *prop = NULL;
 787
 788	if (!PyArg_ParseTuple (args, "O:update_property", &prop))
 789		return NULL;
 790
 791
 792	self->engine.update_property (PyProperty_AsProperty (prop));
 793
 794	Py_INCREF (Py_None);
 795	return Py_None;
 796}
 797
 798/*
 799 * void beep ();
 800 */
 801PyDoc_STRVAR (IMEngine_beep__doc__,
 802"beep ()\n\n"
 803"Beep.\n");
 804PyObject *
 805PyIMEngine::py_beep (PyIMEngineObject *self)
 806{
 807	self->engine.beep ();
 808
 809	Py_INCREF (Py_None);
 810	return Py_None;
 811}
 812
 813/*
 814 * void start_helper (const String &helper_uuid);
 815 */
 816PyDoc_STRVAR (IMEngine_start_helper__doc__,
 817"start_helper (helper_uuid)\n\n"
 818"Start a helper specified with the uuid.\n");
 819PyObject *
 820PyIMEngine::py_start_helper (PyIMEngineObject *self, PyObject *args)
 821{
 822	char *str = NULL;
 823
 824	if (!PyArg_ParseTuple (args, "s:start_helper", &str))
 825		return NULL;
 826
 827	self->engine.start_helper (String (str));
 828
 829	Py_INCREF (Py_None);
 830	return Py_None;
 831}
 832
 833/*
 834 * void stop_helper (const String &helper_uuid);
 835 */
 836PyDoc_STRVAR (IMEngine_stop_helper__doc__,
 837"stop_helper (helper_uuid)\n\n"
 838"Stop a helper specified with the uuid.\n");
 839PyObject *
 840PyIMEngine::py_stop_helper (PyIMEngineObject *self, PyObject *args)
 841{
 842	char *str = NULL;
 843
 844	if (!PyArg_ParseTuple (args, "s:stop_helper", &str))
 845		return NULL;
 846
 847	self->engine.stop_helper (String (str));
 848
 849	Py_INCREF (Py_None);
 850	return Py_None;
 851}
 852
 853/*
 854 * void send_helper_event (const String &helper_uuid, const Transaction &trans);
 855 */
 856PyDoc_STRVAR (IMEngine_send_helper_event__doc__,
 857"send_helper_event ()\n\n"
 858"Do nothing.\n");
 859PyObject *
 860PyIMEngine::py_send_helper_event (PyIMEngineObject *self, PyObject *args)
 861{
 862	char *str = NULL;
 863
 864	if (!PyArg_ParseTuple (args, "s:send_helper_event", &str))
 865		return NULL;
 866
 867	Py_INCREF (Py_None);
 868	return Py_None;
 869}
 870
 871/*
 872 * bool get_surrounding_text (WideString &text, 
 873 * 							  int &cursor,
 874 * 							  int maxlen_before = -1, 
 875 * 							  int maxlen_after = -1);
 876 */
 877PyDoc_STRVAR (IMEngine_get_surrounding_text__doc__,
 878"get_surrounding_text (maxlen_before = -1, maxlen_after = -1)\n\n"
 879"Retrieves a tuple contains a text and cursor within the text.\n");
 880PyObject *
 881PyIMEngine::py_get_surrounding_text (PyIMEngineObject *self, PyObject *args)
 882{
 883	PyObject *tuple;
 884
 885	int maxlen_before = -1;
 886	int maxlen_after = -1;
 887
 888	if (!PyArg_ParseTuple (args, "|ii:get_surrounding_text", &maxlen_before, &maxlen_after))
 889		return NULL;
 890
 891	WideString text;
 892	int cursor;
 893	int provided = self->engine.get_surrounding_text(text, cursor, maxlen_before, maxlen_after);
 894	
 895	tuple = PyTuple_New (2);
 896
 897	if (!provided) {
 898		text = L"";
 899		cursor = 0;
 900	}
 901
 902#if Py_UNICODE_SIZE == 4
 903	PyTuple_SET_ITEM (tuple, 0, PyUnicode_FromUnicode ((Py_UNICODE *)text.c_str(), text.length()));
 904#else
 905	gunichar2 *utf16_str = g_ucs4_to_utf16 (text.c_str(), -1, NULL, NULL, NULL);
 906	PyTuple_SET_ITEM (tuple, 0, PyUnicode_FromUnicode ((Py_UNICODE *)utf16_str, text.length()));
 907#endif
 908	PyTuple_SET_ITEM (tuple, 1, PyInt_FromLong ((long) cursor));
 909	
 910	return tuple;
 911}
 912
 913/*
 914 * bool delete_surrounding_text (int offset, int len);
 915 */
 916PyDoc_STRVAR (IMEngine_delete_surrounding_text__doc__,
 917"delete_surrounding_text (offset, len)\n\n"
 918"Do nothing.\n");
 919PyObject *
 920PyIMEngine::py_delete_surrounding_text (PyIMEngineObject *self, PyObject *args)
 921{
 922	int offset;
 923	int len;
 924
 925	if (!PyArg_ParseTuple (args, "ii:delete_surrounding_text", &offset, &len))
 926		return NULL;
 927
 928	self->engine.delete_surrounding_text (offset, len);
 929
 930	Py_INCREF (Py_None);
 931	return Py_None;
 932}
 933
 934PyMethodDef
 935PyIMEngine::py_methods[] = {
 936
 937#define ENTRY(name, type) \
 938	{ \
 939		#name, \
 940		(PyCFunction)PyIMEngine::py_##name, \
 941		type, \
 942		IMEngine_##name##__doc__ \
 943	}
 944
 945	ENTRY (show_preedit_string, METH_NOARGS),
 946	ENTRY (show_aux_string, METH_NOARGS),
 947	ENTRY (show_lookup_table, METH_NOARGS),
 948	ENTRY (hide_preedit_string, METH_NOARGS),
 949	ENTRY (hide_aux_string, METH_NOARGS),
 950	ENTRY (hide_lookup_table, METH_NOARGS),
 951
 952	ENTRY (update_preedit_caret, METH_VARARGS),
 953	ENTRY (update_preedit_string, METH_VARARGS),
 954	ENTRY (update_aux_string, METH_VARARGS),
 955	ENTRY (update_lookup_table, METH_VARARGS),
 956
 957	ENTRY (commit_string, METH_VARARGS),
 958	ENTRY (forward_key_event, METH_VARARGS),
 959
 960	ENTRY (register_properties, METH_VARARGS),
 961	ENTRY (update_property, METH_VARARGS),
 962
 963	ENTRY (beep, METH_NOARGS),
 964
 965	ENTRY (start_helper, METH_VARARGS),
 966	ENTRY (stop_helper, METH_VARARGS),
 967	ENTRY (send_helper_event, METH_VARARGS),
 968
 969	ENTRY (get_surrounding_text, METH_VARARGS),
 970	ENTRY (delete_surrounding_text, METH_VARARGS),
 971
 972	ENTRY (process_key_event, METH_VARARGS),
 973	ENTRY (move_preedit_caret, METH_VARARGS),
 974	ENTRY (select_candidate, METH_VARARGS),
 975	ENTRY (update_lookup_table_page_size, METH_VARARGS),
 976
 977	ENTRY (lookup_table_page_up, METH_NOARGS),
 978	ENTRY (lookup_table_page_down, METH_NOARGS),
 979	ENTRY (reset, METH_NOARGS),
 980	ENTRY (focus_in, METH_NOARGS),
 981	ENTRY (focus_out, METH_NOARGS),
 982
 983	ENTRY (trigger_property, METH_VARARGS),
 984	ENTRY (process_helper_event, METH_VARARGS),
 985	ENTRY (update_client_capabilities, METH_VARARGS),
 986#undef ENTRY
 987		{ NULL }
 988};
 989
 990PyTypeObject PyIMEngineType = {
 991	PyObject_HEAD_INIT (NULL)
 992	0,						 		/*ob_size*/
 993	"scim.IMEngine", 				/*tp_name*/
 994	sizeof (PyIMEngineObject), 		/*tp_basicsize*/
 995	0,						 		/*tp_itemsize*/
 996	(destructor)PyIMEngine::py_dealloc,	/*tp_dealloc*/
 997	0,			  					/*tp_print*/
 998	0,						 		/*tp_getattr*/
 999	0,								/*tp_setattr*/
1000	0,								/*tp_compare*/
1001	0,			  					/*tp_repr*/
1002	0,								/*tp_as_number*/
1003	0,			  					/*tp_as_sequence*/
1004	0,								/*tp_as_mapping*/
1005	0,			  					/*tp_hash */
1006	0,								/*tp_call*/
1007	0,		  						/*tp_str*/
1008	0,					   			/*tp_getattro*/
1009	0,								/*tp_setattro*/
1010	0,					 			/*tp_as_buffer*/
1011	Py_TPFLAGS_DEFAULT | 
1012	Py_TPFLAGS_BASETYPE,			/*tp_flags*/
1013	"IMEngineInstanceBase objects",	/* tp_doc */
1014	0,					  	/* tp_traverse */
1015	0,					  	/* tp_clear */
1016	0,					  	/* tp_richcompare */
1017	0,					  	/* tp_weaklistoffset */
1018	0,					  	/* tp_iter */
1019	0,					  	/* tp_iternext */
1020	PyIMEngine::py_methods,	/* tp_methods */
1021	0,			 			/* tp_members */
1022	0,						/* tp_getset */
1023	0,						/* tp_base */
1024	0,						/* tp_dict */
1025	0,						/* tp_descr_get */
1026	0,						/* tp_descr_set */
1027	0,						/* tp_dictoffset */
1028	(initproc)PyIMEngine::py_init,	/* tp_init */
1029	0,						 		/* tp_alloc */
1030	PyIMEngine::py_new,				/* tp_new */
1031	PyObject_Del,					/* tp_free */
1032};
1033
1034
1035void init_engine (PyObject *module)
1036{
1037	if (PyType_Ready (&PyIMEngineType) < 0)
1038		return;
1039
1040	Py_INCREF (&PyIMEngineType);
1041	PyModule_AddObject (module, "IMEngine", (PyObject *)&PyIMEngineType);
1042}
1043