PageRenderTime 63ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/src/scim-python-lookup-table.cpp

http://scim-python.googlecode.com/
C++ | 660 lines | 519 code | 116 blank | 25 comment | 36 complexity | a3019f1ecd41d50860f826860987503c 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-lookup-table.h"
  26. #include "scim-python-attribute.h"
  27. #if Py_UNICODE_SIZE == 2
  28. # include <glib.h>
  29. #endif
  30. struct PyLookupTableObject {
  31. PyObject_HEAD
  32. /* Type-specific fields go here. */
  33. PyLookupTable lookup_table;
  34. };
  35. PyLookupTable::PyLookupTable (PyLookupTableObject *self, unsigned int page_size)
  36. : CommonLookupTable (page_size), self (self)
  37. {
  38. Py_INCREF (self);
  39. }
  40. PyLookupTable::PyLookupTable (PyLookupTableObject *self, unsigned int page_size, const std::vector<WideString> &labels)
  41. : CommonLookupTable (page_size, labels), self (self)
  42. {
  43. Py_INCREF (self);
  44. }
  45. PyLookupTable::~PyLookupTable ()
  46. {
  47. Py_DECREF (self);
  48. }
  49. PyDoc_STRVAR(py_set_candidate_labels__doc__,
  50. "set_candidate_labels ((unicode, unicode, ...)) -> none\n"
  51. "Set the strings (it must be unicode strings) to label the candidates in on page.");
  52. PyObject *
  53. PyLookupTable::py_set_candidate_labels (PyLookupTableObject *self, PyObject *args)
  54. {
  55. PyObject *labels = NULL;
  56. PyObject **items = NULL;
  57. std::vector <WideString> _labels;
  58. int size;
  59. if (!PyArg_ParseTuple (args, "o:set_candidate_labels", &labels))
  60. return NULL;
  61. if (!PySequence_Check (labels)) {
  62. PyErr_SetString (PyExc_TypeError, "labels must be an array of unicode strings.");
  63. return NULL;
  64. }
  65. size = PySequence_Size (labels);
  66. items = PySequence_Fast_ITEMS (labels);
  67. for (int i = 0; i < size; i++ ) {
  68. if (!PyUnicode_Check (items[i])) {
  69. PyErr_SetString (PyExc_TypeError, "labels must be an array of unicode strings.");
  70. return NULL;
  71. }
  72. #if Py_UNICODE_SIZE == 4
  73. _labels.push_back (WideString ((wchar_t *)PyUnicode_AS_UNICODE (items[i])));
  74. #else
  75. int usize = PyUnicode_GET_SIZE (items[i]);
  76. gunichar *unistr = g_utf16_to_ucs4 (PyUnicode_AS_UNICODE (items[i]), usize, NULL, NULL, NULL);
  77. _labels.push_back (WideString ((wchar_t *)unistr));
  78. g_free (unistr);
  79. #endif
  80. }
  81. self->lookup_table.set_candidate_labels (_labels);
  82. Py_INCREF (Py_None);
  83. return Py_None;
  84. }
  85. PyDoc_STRVAR(py_get_candidate_label__doc__,
  86. "get_candidate_label (int) -> unicode\n"
  87. "Return the label string of a candidate in page.");
  88. PyObject *
  89. PyLookupTable::py_get_candidate_label (PyLookupTableObject *self, PyObject *args)
  90. {
  91. unsigned index = 0;
  92. if (!PyArg_ParseTuple (args, "I:get_candidate_label", &index))
  93. return NULL;
  94. WideString candidate = self->lookup_table.get_candidate_label (index);
  95. #if Py_UNICODE_SIZE == 4
  96. return PyUnicode_FromUnicode ((Py_UNICODE *)candidate.c_str (), candidate.length ());
  97. #else
  98. gunichar2 *utf16_str = g_ucs4_to_utf16 ((gunichar *)candidate.c_str (),
  99. candidate.length (), NULL, NULL, NULL);
  100. PyObject * result = PyUnicode_FromUnicode ((Py_UNICODE *)utf16_str, candidate.length ());
  101. g_free (utf16_str);
  102. return result;
  103. #endif
  104. }
  105. PyDoc_STRVAR(py_set_page_size__doc__,
  106. "set_page_size (int) -> none\n"
  107. "Set the maximum page size.");
  108. PyObject *
  109. PyLookupTable::py_set_page_size (PyLookupTableObject *self, PyObject *args)
  110. {
  111. unsigned int page_size;
  112. if (!PyArg_ParseTuple (args, "I:set_page_size", &page_size))
  113. return NULL;
  114. self->lookup_table.set_page_size (page_size);
  115. Py_INCREF (Py_None);
  116. return Py_None;
  117. }
  118. PyDoc_STRVAR(py_get_page_size__doc__,
  119. "get_page_size () -> int\n"
  120. "Return the maximum page size.");
  121. PyObject *
  122. PyLookupTable::py_get_page_size (PyLookupTableObject *self, PyObject *args)
  123. {
  124. long size = self->lookup_table.get_page_size ();
  125. return PyInt_FromLong (size);
  126. }
  127. PyDoc_STRVAR(py_get_current_page_size__doc__,
  128. "get_current_page_size () -> int\n"
  129. "Return the current page size.");
  130. PyObject *
  131. PyLookupTable::py_get_current_page_size (PyLookupTableObject *self, PyObject *args)
  132. {
  133. long size = self->lookup_table.get_current_page_size ();
  134. return PyInt_FromLong (size);
  135. }
  136. PyDoc_STRVAR(py_get_current_page_start__doc__,
  137. "get_current_page_start () -> int\n"
  138. "Return the start index of current page.");
  139. PyObject *
  140. PyLookupTable::py_get_current_page_start (PyLookupTableObject *self, PyObject *args)
  141. {
  142. long index = self->lookup_table.get_current_page_start ();
  143. return PyInt_FromLong (index);
  144. }
  145. PyDoc_STRVAR(py_is_cursor_visible__doc__,
  146. "is_cursor_visible () -> bool\n"
  147. "Return true if curosr is visible.");
  148. PyObject *
  149. PyLookupTable::py_is_cursor_visible (PyLookupTableObject *self, PyObject *args)
  150. {
  151. PyObject * result;
  152. if (self->lookup_table.is_cursor_visible ()) {
  153. result = Py_True;
  154. }
  155. else {
  156. result = Py_False;
  157. }
  158. Py_INCREF (result);
  159. return result;
  160. }
  161. PyDoc_STRVAR(py_is_page_size_fixed__doc__,
  162. "is_page_size_fixed () -> bool\n"
  163. "Return true if the page size is fixed.");
  164. PyObject *
  165. PyLookupTable::py_is_page_size_fixed (PyLookupTableObject *self, PyObject *args)
  166. {
  167. PyObject * result;
  168. if (self->lookup_table.is_page_size_fixed ()) {
  169. result = Py_True;
  170. }
  171. else {
  172. result = Py_False;
  173. }
  174. Py_INCREF (result);
  175. return result;
  176. }
  177. PyDoc_STRVAR(py_get_cursor_pos__doc__,
  178. "get_cursor_pos () -> int\n"
  179. "Return the cursor position in the table, starting from 0.");
  180. PyObject *
  181. PyLookupTable::py_get_cursor_pos (PyLookupTableObject *self, PyObject *args)
  182. {
  183. int pos;
  184. pos = self->lookup_table.get_cursor_pos ();
  185. return PyInt_FromLong (pos);
  186. }
  187. PyDoc_STRVAR(py_get_cursor_pos_in_current_page__doc__,
  188. "get_cursor_pos_in_current_page () -> int\n"
  189. "Return the cursor position in the current page, starting from 0.");
  190. PyObject *
  191. PyLookupTable::py_get_cursor_pos_in_current_page (PyLookupTableObject *self, PyObject *args)
  192. {
  193. int pos;
  194. pos = self->lookup_table.get_cursor_pos_in_current_page ();
  195. return PyInt_FromLong (pos);
  196. }
  197. PyDoc_STRVAR(py_page_up__doc__,
  198. "page_up () -> bool\n"
  199. "Flip to the previous page. Return false if it's already in the first page.");
  200. PyObject *
  201. PyLookupTable::py_page_up (PyLookupTableObject *self, PyObject *args)
  202. {
  203. PyObject *result;
  204. if (self->lookup_table.page_up ())
  205. result = Py_True;
  206. else
  207. result = Py_False;
  208. Py_INCREF (result);
  209. return result;
  210. }
  211. PyDoc_STRVAR(py_page_down__doc__,
  212. "page_down () -> bool\n"
  213. "Flip to the next page. Return false if it's already in the last page.");
  214. PyObject *
  215. PyLookupTable::py_page_down (PyLookupTableObject *self, PyObject *args)
  216. {
  217. PyObject *result;
  218. if (self->lookup_table.page_down ())
  219. result = Py_True;
  220. else
  221. result = Py_False;
  222. Py_INCREF (result);
  223. return result;
  224. }
  225. PyDoc_STRVAR(py_cursor_up__doc__,
  226. "cursor_up () -> bool\n"
  227. "Move cursor position to the previous entry. Return false if it's already in the first entry.");
  228. PyObject *
  229. PyLookupTable::py_cursor_up (PyLookupTableObject *self, PyObject *args)
  230. {
  231. PyObject * result;
  232. if (self->lookup_table.cursor_up ()) {
  233. result = Py_True;
  234. }
  235. else {
  236. result = Py_False;
  237. }
  238. Py_INCREF (result);
  239. return result;
  240. }
  241. PyDoc_STRVAR(py_cursor_down__doc__,
  242. "cursor_down () -> bool\n"
  243. "Move cursor position to the next entry. Return false if it's already in the last entry.");
  244. PyObject *
  245. PyLookupTable::py_cursor_down (PyLookupTableObject *self, PyObject *args)
  246. {
  247. PyObject * result;
  248. if (self->lookup_table.cursor_down ()) {
  249. result = Py_True;
  250. }
  251. else {
  252. result = Py_False;
  253. }
  254. Py_INCREF (result);
  255. return result;
  256. }
  257. PyDoc_STRVAR(py_show_cursor__doc__,
  258. "show_cursor (bool) -> none\n"
  259. "Set the cursor visibility.");
  260. PyObject *
  261. PyLookupTable::py_show_cursor (PyLookupTableObject *self, PyObject *args)
  262. {
  263. unsigned int show = 1;
  264. if (!PyArg_ParseTuple (args, "|I:show_cursor", &show))
  265. return NULL;
  266. self->lookup_table.show_cursor (show);
  267. Py_INCREF (Py_None);
  268. return Py_None;
  269. }
  270. PyDoc_STRVAR(py_fix_page_size__doc__,
  271. "fix_page_size (bool) -> none\n"
  272. "Set the page size to be fixed, aka. prevent from being changed by FrontEnd.");
  273. PyObject *
  274. PyLookupTable::py_fix_page_size (PyLookupTableObject *self, PyObject *args)
  275. {
  276. unsigned int fixed = 1;
  277. if (!PyArg_ParseTuple (args, "|I:fix_page_size", &fixed))
  278. return NULL;
  279. self->lookup_table.fix_page_size (fixed);
  280. Py_INCREF (Py_None);
  281. return Py_None;
  282. }
  283. PyDoc_STRVAR(py_set_cursor_pos__doc__,
  284. "set_cursor_pos (int) -> none\n"
  285. "Set the cursor position.");
  286. PyObject *
  287. PyLookupTable::py_set_cursor_pos (PyLookupTableObject *self, PyObject *args)
  288. {
  289. unsigned int pos;
  290. if (!PyArg_ParseTuple (args, "I:set_cursor_pos", &pos))
  291. return NULL;
  292. self->lookup_table.set_cursor_pos (pos);
  293. Py_INCREF (Py_None);
  294. return Py_None;
  295. }
  296. PyDoc_STRVAR(py_set_cursor_pos_in_current_page__doc__,
  297. "set_cursor_pos_in_current_page (int) -> none\n"
  298. "Set the cursor position in current page.");
  299. PyObject *
  300. PyLookupTable::py_set_cursor_pos_in_current_page (PyLookupTableObject *self, PyObject *args)
  301. {
  302. unsigned int pos;
  303. if (!PyArg_ParseTuple (args, "I:set_cursor_pos_in_current_pos", &pos))
  304. return NULL;
  305. self->lookup_table.set_cursor_pos_in_current_page (pos);
  306. Py_INCREF (Py_None);
  307. return Py_None;
  308. }
  309. PyDoc_STRVAR(py_get_candidate_in_current_page__doc__,
  310. "get_candidate_in_current_page (int) -> unicode\n"
  311. "Return the content of this candidate.");
  312. PyObject *
  313. PyLookupTable::py_get_candidate_in_current_page (PyLookupTableObject *self, PyObject *args)
  314. {
  315. unsigned index = 0;
  316. if (!PyArg_ParseTuple (args, "I:get_candidate_in_current_page", &index))
  317. return NULL;
  318. WideString candidate = self->lookup_table.get_candidate_in_current_page (index);
  319. #if Py_UNICODE_SIZE == 4
  320. return PyUnicode_FromUnicode ((Py_UNICODE *)candidate.c_str (), candidate.length ());
  321. #else
  322. gunichar2 *utf16_str = g_ucs4_to_utf16 ((gunichar *)candidate.c_str (),
  323. candidate.length (), NULL, NULL, NULL);
  324. PyObject * result = PyUnicode_FromUnicode ((Py_UNICODE *)utf16_str, candidate.length ());
  325. g_free (utf16_str);
  326. return result;
  327. #endif
  328. }
  329. PyDoc_STRVAR(py_get_candidate__doc__,
  330. "get_candidate (int) -> unicode\n"
  331. "Return the content of this candidate.");
  332. PyObject *
  333. PyLookupTable::py_get_candidate (PyLookupTableObject *self, PyObject *args)
  334. {
  335. unsigned index = 0;
  336. if (!PyArg_ParseTuple (args, "I:get_candidate", &index))
  337. return NULL;
  338. WideString candidate = self->lookup_table.get_candidate (index);
  339. #if Py_UNICODE_SIZE == 4
  340. return PyUnicode_FromUnicode ((Py_UNICODE *)candidate.c_str (), candidate.length ());
  341. #else
  342. gunichar2 *utf16_str = g_ucs4_to_utf16 ((gunichar *)candidate.c_str (),
  343. candidate.length (), NULL, NULL, NULL);
  344. PyObject * result = PyUnicode_FromUnicode ((Py_UNICODE *)utf16_str, candidate.length ());
  345. g_free (utf16_str);
  346. return result;
  347. #endif
  348. }
  349. PyDoc_STRVAR(py_get_attributes__doc__,
  350. "get_attributes (int) -> list\n"
  351. "Return a list holding the attributes of this candidates.");
  352. PyObject *
  353. PyLookupTable::py_get_attributes (PyLookupTableObject *self, PyObject *args)
  354. {
  355. #if 0
  356. PyObject *result;
  357. unsigned index = 0;
  358. if (!PyArg_ParseTuple (args, "I:get_attributes", &index))
  359. return NULL;
  360. AttributeList atts = self->lookup_table.get_attributes (index)
  361. result = PyTuple_New ();
  362. #endif
  363. Py_INCREF (Py_None);
  364. return Py_None;
  365. }
  366. PyDoc_STRVAR(py_get_attributes_in_current_page__doc__,
  367. "get_attributes_in_current_page (int) -> list\n"
  368. "Return a list holding the attributes of this candidates.");
  369. PyObject *
  370. PyLookupTable::py_get_attributes_in_current_page (PyLookupTableObject *self, PyObject *args)
  371. {
  372. #if 0
  373. PyObject *result;
  374. unsigned index = 0;
  375. if (!PyArg_ParseTuple (args, "I:get_attributes", &index))
  376. return NULL;
  377. AttributeList atts = self->lookup_table.get_attributes (index)
  378. result = PyTuple_New ();
  379. #endif
  380. Py_INCREF (Py_None);
  381. return Py_None;
  382. }
  383. PyDoc_STRVAR(py_number_of_candidates__doc__,
  384. "number_of_candidates () -> int\n"
  385. "Return the number of candidates in the table.");
  386. PyObject *
  387. PyLookupTable::py_number_of_candidates (PyLookupTableObject *self, PyObject *args)
  388. {
  389. uint32 number;
  390. number = self->lookup_table.number_of_candidates ();
  391. return PyInt_FromLong (number);
  392. }
  393. PyDoc_STRVAR(py_clear__doc__,
  394. "clear () -> none\n"
  395. "Clear the table.");
  396. PyObject *
  397. PyLookupTable::py_clear (PyLookupTableObject *self, PyObject *args)
  398. {
  399. self->lookup_table.clear ();
  400. Py_INCREF (Py_None);
  401. return Py_None;
  402. }
  403. PyDoc_STRVAR(py_append_candidate__doc__,
  404. "append_candidate (unicode, list) -> bool\n"
  405. "Append a candidate string to the table, the second is a list holding the attributes.\n"
  406. "Return true if success.");
  407. PyObject *
  408. PyLookupTable::py_append_candidate (PyLookupTableObject *self, PyObject *args)
  409. {
  410. Py_UNICODE *candidate = NULL;
  411. PyObject *pAttrs = NULL;
  412. PyObject *result = Py_False;
  413. #if Py_UNICODE_SIZE == 4
  414. if (!PyArg_ParseTuple (args, "u|O:append_candidate", &candidate, &pAttrs))
  415. return NULL;
  416. if (self->lookup_table.append_candidate (WideString ((wchar_t *)candidate),
  417. Attributes_FromTupleOrList (pAttrs)))
  418. {
  419. result = Py_True;
  420. }
  421. #else
  422. int size = 0;
  423. gunichar *unistr = NULL;
  424. if (!PyArg_ParseTuple (args, "u#|O:append_candidate", &candidate, &size, &pAttrs))
  425. return NULL;
  426. unistr = g_utf16_to_ucs4 (candidate, size, NULL, NULL, NULL);
  427. if (self->lookup_table.append_candidate (WideString ((wchar_t *)unistr),
  428. Attributes_FromTupleOrList (pAttrs)))
  429. {
  430. result = Py_True;
  431. }
  432. g_free (unistr);
  433. #endif
  434. Py_INCREF (result);
  435. return result;
  436. }
  437. PyMethodDef
  438. PyLookupTable::py_methods[] = {
  439. #define ENTRY(name, flags) {#name, (PyCFunction)PyLookupTable::py_##name, flags, py_##name##__doc__}
  440. ENTRY (set_candidate_labels, METH_VARARGS),
  441. ENTRY (get_candidate_label, METH_VARARGS),
  442. ENTRY (set_page_size, METH_VARARGS),
  443. ENTRY (get_page_size, METH_NOARGS),
  444. ENTRY (get_current_page_size, METH_NOARGS),
  445. ENTRY (get_current_page_start, METH_NOARGS),
  446. ENTRY (is_cursor_visible, METH_NOARGS),
  447. ENTRY (is_page_size_fixed, METH_NOARGS),
  448. ENTRY (get_cursor_pos, METH_NOARGS),
  449. ENTRY (get_cursor_pos_in_current_page, METH_NOARGS),
  450. ENTRY (page_up, METH_NOARGS),
  451. ENTRY (page_down, METH_NOARGS),
  452. ENTRY (cursor_up, METH_NOARGS),
  453. ENTRY (cursor_down, METH_NOARGS),
  454. ENTRY (show_cursor, METH_VARARGS),
  455. ENTRY (fix_page_size, METH_VARARGS),
  456. ENTRY (set_cursor_pos, METH_VARARGS),
  457. ENTRY (set_cursor_pos_in_current_page, METH_VARARGS),
  458. ENTRY (get_candidate_in_current_page, METH_VARARGS),
  459. ENTRY (get_attributes_in_current_page, METH_VARARGS),
  460. ENTRY (get_candidate, METH_VARARGS),
  461. ENTRY (get_attributes, METH_VARARGS),
  462. ENTRY (number_of_candidates, METH_NOARGS),
  463. ENTRY (clear, METH_NOARGS),
  464. ENTRY (append_candidate, METH_VARARGS),
  465. #undef ENTRY
  466. { NULL }
  467. };
  468. PyObject *
  469. PyLookupTable::py_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
  470. {
  471. PyLookupTable *self;
  472. self = (PyLookupTable *)type->tp_alloc (type, 0);
  473. return (PyObject *)self;
  474. }
  475. int
  476. PyLookupTable::py_init (PyLookupTableObject *self, PyObject *args, PyObject *kwds)
  477. {
  478. unsigned int page_size = 10;
  479. if (!PyArg_ParseTuple (args, "|I:__init__", &page_size))
  480. return -1;
  481. new (&self->lookup_table) PyLookupTable (self, page_size);
  482. return 0;
  483. }
  484. void
  485. PyLookupTable::py_dealloc (PyLookupTableObject *self)
  486. {
  487. self->lookup_table.~LookupTable ();
  488. ((PyObject *)self)->ob_type->tp_free (self);
  489. }
  490. const PyLookupTable &
  491. PyLookupTable::from_pyobject (PyObject *object)
  492. {
  493. return ((PyLookupTableObject *)object)->lookup_table;
  494. }
  495. PyTypeObject PyLookupTableType = {
  496. PyObject_HEAD_INIT (NULL)
  497. 0, /*ob_size*/
  498. "scim.LookupTable", /*tp_name*/
  499. sizeof (PyLookupTableObject), /*tp_basicsize*/
  500. 0, /*tp_itemsize*/
  501. (destructor)PyLookupTable::py_dealloc, /*tp_dealloc*/
  502. 0, /*tp_print*/
  503. 0, /*tp_getattr*/
  504. 0, /*tp_setattr*/
  505. 0, /*tp_compare*/
  506. 0, /*tp_repr*/
  507. 0, /*tp_as_number*/
  508. 0, /*tp_as_sequence*/
  509. 0, /*tp_as_mapping*/
  510. 0, /*tp_hash */
  511. 0, /*tp_call*/
  512. 0, /*tp_str*/
  513. 0, /*tp_getattro*/
  514. 0, /*tp_setattro*/
  515. 0, /*tp_as_buffer*/
  516. Py_TPFLAGS_DEFAULT |
  517. Py_TPFLAGS_BASETYPE, /*tp_flags*/
  518. "PyLookupTable objects", /* tp_doc */
  519. 0, /* tp_traverse */
  520. 0, /* tp_clear */
  521. 0, /* tp_richcompare */
  522. 0, /* tp_weaklistoffset */
  523. 0, /* tp_iter */
  524. 0, /* tp_iternext */
  525. PyLookupTable::py_methods, /* tp_methods */
  526. 0, /* tp_members */
  527. 0, /* tp_getset */
  528. 0, /* tp_base */
  529. 0, /* tp_dict */
  530. 0, /* tp_descr_get */
  531. 0, /* tp_descr_set */
  532. 0, /* tp_dictoffset */
  533. (initproc)PyLookupTable::py_init, /* tp_init */
  534. 0, /* tp_alloc */
  535. PyLookupTable::py_new, /* tp_new */
  536. PyObject_Del, /* tp_free */
  537. };
  538. void init_lookup_table (PyObject *module)
  539. {
  540. if (PyType_Ready (&PyLookupTableType) < 0)
  541. return;
  542. Py_INCREF (&PyLookupTableType);
  543. PyModule_AddObject (module, "LookupTable", (PyObject *)&PyLookupTableType);
  544. }