enchant.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Pierre-Alain Joye <paj@pearfr.org> |
  14. | Ilia Alshanetsky <ilia@prohost.org> |
  15. +----------------------------------------------------------------------+
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "php.h"
  21. #include "php_ini.h"
  22. #include "ext/standard/info.h"
  23. #include "Zend/zend_exceptions.h"
  24. #include "../spl/spl_exceptions.h"
  25. #include <enchant.h>
  26. #include "php_enchant.h"
  27. #include "enchant_arginfo.h"
  28. typedef struct _broker_struct {
  29. EnchantBroker *pbroker;
  30. int nb_dict;
  31. zend_object std;
  32. } enchant_broker;
  33. typedef struct _dict_struct {
  34. EnchantDict *pdict;
  35. zval zbroker;
  36. zend_object std;
  37. } enchant_dict;
  38. zend_class_entry *enchant_broker_ce;
  39. static zend_object_handlers enchant_broker_handlers;
  40. static inline enchant_broker *enchant_broker_from_obj(zend_object *obj) {
  41. return (enchant_broker *)((char *)(obj) - XtOffsetOf(enchant_broker, std));
  42. }
  43. #define Z_ENCHANT_BROKER_P(zv) enchant_broker_from_obj(Z_OBJ_P(zv))
  44. static zend_object *enchant_broker_create_object(zend_class_entry *class_type) {
  45. enchant_broker *intern = zend_object_alloc(sizeof(enchant_broker), class_type);
  46. zend_object_std_init(&intern->std, class_type);
  47. object_properties_init(&intern->std, class_type);
  48. intern->std.handlers = &enchant_broker_handlers;
  49. return &intern->std;
  50. }
  51. zend_class_entry *enchant_dict_ce;
  52. static zend_object_handlers enchant_dict_handlers;
  53. static inline enchant_dict *enchant_dict_from_obj(zend_object *obj) {
  54. return (enchant_dict *)((char *)(obj) - XtOffsetOf(enchant_dict, std));
  55. }
  56. #define Z_ENCHANT_DICT_P(zv) enchant_dict_from_obj(Z_OBJ_P(zv))
  57. static zend_object *enchant_dict_create_object(zend_class_entry *class_type) {
  58. enchant_dict *intern = zend_object_alloc(sizeof(enchant_dict), class_type);
  59. zend_object_std_init(&intern->std, class_type);
  60. object_properties_init(&intern->std, class_type);
  61. intern->std.handlers = &enchant_dict_handlers;
  62. return &intern->std;
  63. }
  64. #define PHP_ENCHANT_MYSPELL 1
  65. #define PHP_ENCHANT_ISPELL 2
  66. /* {{{ enchant_module_entry */
  67. zend_module_entry enchant_module_entry = {
  68. STANDARD_MODULE_HEADER,
  69. "enchant",
  70. ext_functions,
  71. PHP_MINIT(enchant),
  72. PHP_MSHUTDOWN(enchant),
  73. NULL, /* Replace with NULL if there's nothing to do at request start */
  74. NULL, /* Replace with NULL if there's nothing to do at request end */
  75. PHP_MINFO(enchant),
  76. PHP_ENCHANT_VERSION,
  77. STANDARD_MODULE_PROPERTIES
  78. };
  79. /* }}} */
  80. #ifdef COMPILE_DL_ENCHANT
  81. ZEND_GET_MODULE(enchant)
  82. #endif
  83. static void
  84. enumerate_providers_fn (const char * const name,
  85. const char * const desc,
  86. const char * const file,
  87. void * ud) /* {{{ */
  88. {
  89. zval *zdesc = (zval *) ud;
  90. zval tmp_array;
  91. array_init(&tmp_array);
  92. add_assoc_string(&tmp_array, "name", (char *)name);
  93. add_assoc_string(&tmp_array, "desc", (char *)desc);
  94. add_assoc_string(&tmp_array, "file", (char *)file);
  95. add_next_index_zval(zdesc, &tmp_array);
  96. }
  97. /* }}} */
  98. static void
  99. describe_dict_fn (const char * const lang,
  100. const char * const name,
  101. const char * const desc,
  102. const char * const file,
  103. void * ud) /* {{{ */
  104. {
  105. zval *zdesc = (zval *) ud;
  106. array_init(zdesc);
  107. add_assoc_string(zdesc, "lang", (char *)lang);
  108. add_assoc_string(zdesc, "name", (char *)name);
  109. add_assoc_string(zdesc, "desc", (char *)desc);
  110. add_assoc_string(zdesc, "file", (char *)file);
  111. }
  112. /* }}} */
  113. static void php_enchant_list_dicts_fn( const char * const lang_tag,
  114. const char * const provider_name, const char * const provider_desc,
  115. const char * const provider_file, void * ud) /* {{{ */
  116. {
  117. zval *zdesc = (zval *) ud;
  118. zval tmp_array;
  119. array_init(&tmp_array);
  120. add_assoc_string(&tmp_array, "lang_tag", (char *)lang_tag);
  121. add_assoc_string(&tmp_array, "provider_name", (char *)provider_name);
  122. add_assoc_string(&tmp_array, "provider_desc", (char *)provider_desc);
  123. add_assoc_string(&tmp_array, "provider_file", (char *)provider_file);
  124. add_next_index_zval(zdesc, &tmp_array);
  125. }
  126. /* }}} */
  127. static void php_enchant_broker_free(zend_object *object) /* {{{ */
  128. {
  129. enchant_broker *broker = enchant_broker_from_obj(object);
  130. if (broker->pbroker) { /* may have been freed by enchant_broker_free */
  131. enchant_broker_free(broker->pbroker);
  132. broker->pbroker = NULL;
  133. }
  134. zend_object_std_dtor(object);
  135. }
  136. /* }}} */
  137. static void php_enchant_dict_free(zend_object *object) /* {{{ */
  138. {
  139. enchant_dict *dict = enchant_dict_from_obj(object);
  140. if (dict->pdict) { /* may have been freed by enchant_broker_free_dict */
  141. enchant_broker *broker = Z_ENCHANT_BROKER_P(&dict->zbroker);
  142. if (broker && broker->pbroker) {
  143. enchant_broker_free_dict(broker->pbroker, dict->pdict);
  144. broker->nb_dict--;
  145. zval_ptr_dtor(&dict->zbroker);
  146. }
  147. dict->pdict = NULL;
  148. }
  149. zend_object_std_dtor(object);
  150. }
  151. /* }}} */
  152. /* {{{ PHP_MINIT_FUNCTION */
  153. PHP_MINIT_FUNCTION(enchant)
  154. {
  155. enchant_broker_ce = register_class_EnchantBroker();
  156. enchant_broker_ce->create_object = enchant_broker_create_object;
  157. memcpy(&enchant_broker_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  158. enchant_broker_handlers.offset = XtOffsetOf(enchant_broker, std);
  159. enchant_broker_handlers.free_obj = php_enchant_broker_free;
  160. enchant_broker_handlers.clone_obj = NULL;
  161. enchant_broker_handlers.compare = zend_objects_not_comparable;
  162. enchant_dict_ce = register_class_EnchantDictionary();
  163. enchant_dict_ce->create_object = enchant_dict_create_object;
  164. memcpy(&enchant_dict_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  165. enchant_dict_handlers.offset = XtOffsetOf(enchant_dict, std);
  166. enchant_dict_handlers.free_obj = php_enchant_dict_free;
  167. enchant_dict_handlers.clone_obj = NULL;
  168. enchant_dict_handlers.compare = zend_objects_not_comparable;
  169. REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
  170. REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
  171. #ifdef HAVE_ENCHANT_GET_VERSION
  172. REGISTER_STRING_CONSTANT("LIBENCHANT_VERSION", enchant_get_version(), CONST_CS | CONST_PERSISTENT);
  173. #endif
  174. return SUCCESS;
  175. }
  176. /* }}} */
  177. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  178. PHP_MSHUTDOWN_FUNCTION(enchant)
  179. {
  180. return SUCCESS;
  181. }
  182. /* }}} */
  183. static void __enumerate_providers_fn (const char * const name,
  184. const char * const desc,
  185. const char * const file,
  186. void * ud) /* {{{ */
  187. {
  188. php_info_print_table_row(3, name, desc, file);
  189. }
  190. /* }}} */
  191. /* {{{ PHP_MINFO_FUNCTION */
  192. PHP_MINFO_FUNCTION(enchant)
  193. {
  194. EnchantBroker *pbroker;
  195. pbroker = enchant_broker_init();
  196. php_info_print_table_start();
  197. php_info_print_table_row(2, "enchant support", "enabled");
  198. #ifdef HAVE_ENCHANT_GET_VERSION
  199. php_info_print_table_row(2, "Libenchant Version", enchant_get_version());
  200. #elif defined(HAVE_ENCHANT_BROKER_SET_PARAM)
  201. php_info_print_table_row(2, "Libenchant Version", "1.5.x");
  202. #endif
  203. php_info_print_table_end();
  204. php_info_print_table_start();
  205. enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
  206. php_info_print_table_end();
  207. enchant_broker_free(pbroker);
  208. }
  209. /* }}} */
  210. #define PHP_ENCHANT_GET_BROKER \
  211. pbroker = Z_ENCHANT_BROKER_P(broker); \
  212. if (!pbroker->pbroker) { \
  213. zend_value_error("Invalid or uninitialized EnchantBroker object"); \
  214. RETURN_THROWS(); \
  215. }
  216. #define PHP_ENCHANT_GET_DICT \
  217. pdict = Z_ENCHANT_DICT_P(dict); \
  218. if (!pdict->pdict) { \
  219. zend_value_error("Invalid or uninitialized EnchantDictionary object"); \
  220. RETURN_THROWS(); \
  221. }
  222. /* {{{ create a new broker object capable of requesting */
  223. PHP_FUNCTION(enchant_broker_init)
  224. {
  225. enchant_broker *broker;
  226. EnchantBroker *pbroker;
  227. if (zend_parse_parameters_none() == FAILURE) {
  228. RETURN_THROWS();
  229. }
  230. pbroker = enchant_broker_init();
  231. if (pbroker) {
  232. object_init_ex(return_value, enchant_broker_ce);
  233. broker = Z_ENCHANT_BROKER_P(return_value);
  234. broker->pbroker = pbroker;
  235. broker->nb_dict = 0;
  236. } else {
  237. RETURN_FALSE;
  238. }
  239. }
  240. /* }}} */
  241. /* {{{ Destroys the broker object and its dictionaries */
  242. PHP_FUNCTION(enchant_broker_free)
  243. {
  244. zval *broker;
  245. enchant_broker *pbroker;
  246. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
  247. RETURN_THROWS();
  248. }
  249. PHP_ENCHANT_GET_BROKER;
  250. if (pbroker->nb_dict > 0) {
  251. zend_throw_error(NULL, "Cannot free EnchantBroker object with open EnchantDictionary objects");
  252. RETURN_THROWS();
  253. }
  254. if (pbroker->pbroker) {
  255. enchant_broker_free(pbroker->pbroker);
  256. pbroker->pbroker = NULL;
  257. }
  258. RETURN_TRUE;
  259. }
  260. /* }}} */
  261. /* {{{ Returns the last error of the broker */
  262. PHP_FUNCTION(enchant_broker_get_error)
  263. {
  264. zval *broker;
  265. enchant_broker *pbroker;
  266. const char *msg;
  267. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
  268. RETURN_THROWS();
  269. }
  270. PHP_ENCHANT_GET_BROKER;
  271. msg = enchant_broker_get_error(pbroker->pbroker);
  272. if (msg) {
  273. RETURN_STRING((char *)msg);
  274. }
  275. RETURN_FALSE;
  276. }
  277. /* }}} */
  278. /* {{{ Set the directory path for a given backend, works with ispell and myspell */
  279. PHP_FUNCTION(enchant_broker_set_dict_path)
  280. {
  281. zval *broker;
  282. zend_long dict_type;
  283. char *value;
  284. size_t value_len;
  285. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ols", &broker, enchant_broker_ce, &dict_type, &value, &value_len) == FAILURE) {
  286. RETURN_THROWS();
  287. }
  288. #if HAVE_ENCHANT_BROKER_SET_PARAM
  289. enchant_broker *pbroker;
  290. if (!value_len) {
  291. RETURN_FALSE;
  292. }
  293. PHP_ENCHANT_GET_BROKER;
  294. switch (dict_type) {
  295. case PHP_ENCHANT_MYSPELL:
  296. PHP_ENCHANT_GET_BROKER;
  297. enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value);
  298. RETURN_TRUE;
  299. break;
  300. case PHP_ENCHANT_ISPELL:
  301. PHP_ENCHANT_GET_BROKER;
  302. enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value);
  303. RETURN_TRUE;
  304. break;
  305. default:
  306. RETURN_FALSE;
  307. }
  308. #endif
  309. }
  310. /* }}} */
  311. /* {{{ Get the directory path for a given backend, works with ispell and myspell */
  312. PHP_FUNCTION(enchant_broker_get_dict_path)
  313. {
  314. zval *broker;
  315. zend_long dict_type;
  316. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &broker, enchant_broker_ce, &dict_type) == FAILURE) {
  317. RETURN_THROWS();
  318. }
  319. #if HAVE_ENCHANT_BROKER_SET_PARAM
  320. enchant_broker *pbroker;
  321. char *value;
  322. PHP_ENCHANT_GET_BROKER;
  323. switch (dict_type) {
  324. case PHP_ENCHANT_MYSPELL:
  325. PHP_ENCHANT_GET_BROKER;
  326. value = enchant_broker_get_param(pbroker->pbroker, "enchant.myspell.dictionary.path");
  327. break;
  328. case PHP_ENCHANT_ISPELL:
  329. PHP_ENCHANT_GET_BROKER;
  330. value = enchant_broker_get_param(pbroker->pbroker, "enchant.ispell.dictionary.path");
  331. break;
  332. default:
  333. RETURN_FALSE;
  334. }
  335. if (value == NULL) {
  336. php_error_docref(NULL, E_WARNING, "dict_path not set");
  337. RETURN_FALSE;
  338. }
  339. RETURN_STRING(value);
  340. #endif
  341. }
  342. /* }}} */
  343. /* {{{ Lists the dictionaries available for the given broker */
  344. PHP_FUNCTION(enchant_broker_list_dicts)
  345. {
  346. zval *broker;
  347. enchant_broker *pbroker;
  348. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
  349. RETURN_THROWS();
  350. }
  351. PHP_ENCHANT_GET_BROKER;
  352. array_init(return_value);
  353. enchant_broker_list_dicts(pbroker->pbroker, php_enchant_list_dicts_fn, (void *)return_value);
  354. }
  355. /* }}} */
  356. /* {{{ create a new dictionary using tag, the non-empty language tag you wish to request
  357. a dictionary for ("en_US", "de_DE", ...) */
  358. PHP_FUNCTION(enchant_broker_request_dict)
  359. {
  360. zval *broker;
  361. enchant_broker *pbroker;
  362. enchant_dict *dict;
  363. EnchantDict *pdict;
  364. char *tag;
  365. size_t taglen;
  366. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &broker, enchant_broker_ce, &tag, &taglen) == FAILURE) {
  367. RETURN_THROWS();
  368. }
  369. PHP_ENCHANT_GET_BROKER;
  370. if (taglen == 0) {
  371. zend_argument_value_error(2, "cannot be empty");
  372. RETURN_THROWS();
  373. }
  374. pdict = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
  375. if (pdict) {
  376. pbroker->nb_dict++;
  377. object_init_ex(return_value, enchant_dict_ce);
  378. dict = Z_ENCHANT_DICT_P(return_value);
  379. dict->pdict = pdict;
  380. ZVAL_COPY(&dict->zbroker, broker);
  381. } else {
  382. RETURN_FALSE;
  383. }
  384. }
  385. /* }}} */
  386. /* {{{ creates a dictionary using a PWL file. A PWL file is personal word file one word per line. It must exist before the call.*/
  387. PHP_FUNCTION(enchant_broker_request_pwl_dict)
  388. {
  389. zval *broker;
  390. enchant_broker *pbroker;
  391. enchant_dict *dict;
  392. EnchantDict *pdict;
  393. const char *pwl;
  394. size_t pwllen;
  395. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &broker, enchant_broker_ce, &pwl, &pwllen) == FAILURE) {
  396. RETURN_THROWS();
  397. }
  398. if (php_check_open_basedir(pwl)) {
  399. RETURN_FALSE;
  400. }
  401. PHP_ENCHANT_GET_BROKER;
  402. pdict = enchant_broker_request_pwl_dict(pbroker->pbroker, pwl);
  403. if (pdict) {
  404. pbroker->nb_dict++;
  405. object_init_ex(return_value, enchant_dict_ce);
  406. dict = Z_ENCHANT_DICT_P(return_value);
  407. dict->pdict = pdict;
  408. ZVAL_COPY(&dict->zbroker, broker);
  409. } else {
  410. RETURN_FALSE;
  411. }
  412. }
  413. /* }}} */
  414. /* {{{ Free the dictionary resource */
  415. PHP_FUNCTION(enchant_broker_free_dict)
  416. {
  417. zval *dict;
  418. enchant_dict *pdict;
  419. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
  420. RETURN_THROWS();
  421. }
  422. PHP_ENCHANT_GET_DICT;
  423. if (pdict->pdict) {
  424. enchant_broker *broker = Z_ENCHANT_BROKER_P(&pdict->zbroker);
  425. if (broker && broker->pbroker) {
  426. enchant_broker_free_dict(broker->pbroker, pdict->pdict);
  427. broker->nb_dict--;
  428. zval_ptr_dtor(&pdict->zbroker);
  429. }
  430. pdict->pdict = NULL;
  431. }
  432. RETURN_TRUE;
  433. }
  434. /* }}} */
  435. /* {{{ Whether a dictionary exists or not. Using non-empty tag */
  436. PHP_FUNCTION(enchant_broker_dict_exists)
  437. {
  438. zval *broker;
  439. char *tag;
  440. size_t taglen;
  441. enchant_broker * pbroker;
  442. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &broker, enchant_broker_ce, &tag, &taglen) == FAILURE) {
  443. RETURN_THROWS();
  444. }
  445. PHP_ENCHANT_GET_BROKER;
  446. RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
  447. }
  448. /* }}} */
  449. /* {{{ Declares a preference of dictionaries to use for the language
  450. described/referred to by 'tag'. The ordering is a comma delimited
  451. list of provider names. As a special exception, the "*" tag can
  452. be used as a language tag to declare a default ordering for any
  453. language that does not explicitly declare an ordering. */
  454. PHP_FUNCTION(enchant_broker_set_ordering)
  455. {
  456. zval *broker;
  457. char *pordering;
  458. size_t porderinglen;
  459. char *ptag;
  460. size_t ptaglen;
  461. enchant_broker * pbroker;
  462. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &broker, enchant_broker_ce, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
  463. RETURN_THROWS();
  464. }
  465. PHP_ENCHANT_GET_BROKER;
  466. enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
  467. RETURN_TRUE;
  468. }
  469. /* }}} */
  470. /* {{{ Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
  471. PHP_FUNCTION(enchant_broker_describe)
  472. {
  473. EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
  474. zval *broker;
  475. enchant_broker * pbroker;
  476. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
  477. RETURN_THROWS();
  478. }
  479. PHP_ENCHANT_GET_BROKER;
  480. array_init(return_value);
  481. enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
  482. }
  483. /* }}} */
  484. /* {{{ If the word is correctly spelled return true, otherwise return false, if suggestions variable
  485. is provided, fill it with spelling alternatives. */
  486. PHP_FUNCTION(enchant_dict_quick_check)
  487. {
  488. zval *dict, *sugg = NULL;
  489. char *word;
  490. size_t wordlen;
  491. enchant_dict *pdict;
  492. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|z", &dict, enchant_dict_ce, &word, &wordlen, &sugg) == FAILURE) {
  493. RETURN_THROWS();
  494. }
  495. if (sugg) {
  496. sugg = zend_try_array_init(sugg);
  497. if (!sugg) {
  498. RETURN_THROWS();
  499. }
  500. }
  501. PHP_ENCHANT_GET_DICT;
  502. if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
  503. size_t n_sugg;
  504. char **suggs;
  505. if (!sugg && ZEND_NUM_ARGS() == 2) {
  506. RETURN_FALSE;
  507. }
  508. suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
  509. if (suggs && n_sugg) {
  510. size_t i;
  511. for (i = 0; i < n_sugg; i++) {
  512. add_next_index_string(sugg, suggs[i]);
  513. }
  514. enchant_dict_free_string_list(pdict->pdict, suggs);
  515. }
  516. RETURN_FALSE;
  517. }
  518. RETURN_TRUE;
  519. }
  520. /* }}} */
  521. /* {{{ If the word is correctly spelled return true, otherwise return false */
  522. PHP_FUNCTION(enchant_dict_check)
  523. {
  524. zval *dict;
  525. char *word;
  526. size_t wordlen;
  527. enchant_dict *pdict;
  528. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
  529. RETURN_THROWS();
  530. }
  531. PHP_ENCHANT_GET_DICT;
  532. RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
  533. }
  534. /* }}} */
  535. /* {{{ Will return a list of values if any of those pre-conditions are not met.*/
  536. PHP_FUNCTION(enchant_dict_suggest)
  537. {
  538. zval *dict;
  539. char *word;
  540. size_t wordlen;
  541. char **suggs;
  542. enchant_dict *pdict;
  543. size_t n_sugg;
  544. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
  545. RETURN_THROWS();
  546. }
  547. PHP_ENCHANT_GET_DICT;
  548. array_init(return_value);
  549. suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
  550. if (suggs && n_sugg) {
  551. size_t i;
  552. for (i = 0; i < n_sugg; i++) {
  553. add_next_index_string(return_value, suggs[i]);
  554. }
  555. enchant_dict_free_string_list(pdict->pdict, suggs);
  556. }
  557. }
  558. /* }}} */
  559. /* {{{ add 'word' to personal word list */
  560. PHP_FUNCTION(enchant_dict_add)
  561. {
  562. zval *dict;
  563. char *word;
  564. size_t wordlen;
  565. enchant_dict *pdict;
  566. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
  567. RETURN_THROWS();
  568. }
  569. PHP_ENCHANT_GET_DICT;
  570. enchant_dict_add(pdict->pdict, word, wordlen);
  571. }
  572. /* }}} */
  573. /* {{{ add 'word' to this spell-checking session */
  574. PHP_FUNCTION(enchant_dict_add_to_session)
  575. {
  576. zval *dict;
  577. char *word;
  578. size_t wordlen;
  579. enchant_dict *pdict;
  580. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
  581. RETURN_THROWS();
  582. }
  583. PHP_ENCHANT_GET_DICT;
  584. enchant_dict_add_to_session(pdict->pdict, word, wordlen);
  585. }
  586. /* }}} */
  587. /* {{{ whether or not 'word' exists in this spelling-session */
  588. PHP_FUNCTION(enchant_dict_is_added)
  589. {
  590. zval *dict;
  591. char *word;
  592. size_t wordlen;
  593. enchant_dict *pdict;
  594. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
  595. RETURN_THROWS();
  596. }
  597. PHP_ENCHANT_GET_DICT;
  598. RETURN_BOOL(enchant_dict_is_added(pdict->pdict, word, wordlen));
  599. }
  600. /* }}} */
  601. /* {{{ add a correction for 'mis' using 'cor'.
  602. Notes that you replaced @mis with @cor, so it's possibly more likely
  603. that future occurrences of @mis will be replaced with @cor. So it might
  604. bump @cor up in the suggestion list.*/
  605. PHP_FUNCTION(enchant_dict_store_replacement)
  606. {
  607. zval *dict;
  608. char *mis, *cor;
  609. size_t mislen, corlen;
  610. enchant_dict *pdict;
  611. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &dict, enchant_dict_ce, &mis, &mislen, &cor, &corlen) == FAILURE) {
  612. RETURN_THROWS();
  613. }
  614. PHP_ENCHANT_GET_DICT;
  615. enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
  616. }
  617. /* }}} */
  618. /* {{{ Returns the last error of the current spelling-session */
  619. PHP_FUNCTION(enchant_dict_get_error)
  620. {
  621. zval *dict;
  622. enchant_dict *pdict;
  623. const char *msg;
  624. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
  625. RETURN_THROWS();
  626. }
  627. PHP_ENCHANT_GET_DICT;
  628. msg = enchant_dict_get_error(pdict->pdict);
  629. if (msg) {
  630. RETURN_STRING((char *)msg);
  631. }
  632. RETURN_FALSE;
  633. }
  634. /* }}} */
  635. /* {{{ Describes an individual dictionary 'dict' */
  636. PHP_FUNCTION(enchant_dict_describe)
  637. {
  638. zval *dict;
  639. enchant_dict *pdict;
  640. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
  641. RETURN_THROWS();
  642. }
  643. PHP_ENCHANT_GET_DICT;
  644. enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
  645. }
  646. /* }}} */