enchant.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.0 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/3_0.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Pierre-Alain Joye <paj@pearfr.org> |
  16. | Ilia Alshanetsky <ilia@prohost.org> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/info.h"
  25. #include <enchant.h>
  26. #include "php_enchant.h"
  27. typedef EnchantBroker * EnchantBrokerPtr;
  28. typedef struct _broker_struct enchant_broker;
  29. typedef struct _dict_struct enchant_dict;
  30. typedef enchant_broker * enchant_brokerPtr;
  31. typedef enchant_dict * enchant_dictPtr;
  32. typedef struct _broker_struct {
  33. EnchantBroker *pbroker;
  34. enchant_dict **dict;
  35. unsigned int dictcnt;
  36. zend_resource *rsrc;
  37. } _enchant_broker;
  38. typedef struct _dict_struct {
  39. unsigned int id;
  40. EnchantDict *pdict;
  41. enchant_broker *pbroker;
  42. zend_resource *rsrc;
  43. } _enchant_dict;
  44. /* True global resources - no need for thread safety here */
  45. static int le_enchant_broker;
  46. static int le_enchant_dict;
  47. /* If you declare any globals in php_enchant.h uncomment this:*/
  48. /*ZEND_DECLARE_MODULE_GLOBALS(enchant)*/
  49. #define PHP_ENCHANT_MYSPELL 1
  50. #define PHP_ENCHANT_ISPELL 2
  51. /* {{{ arginfo */
  52. ZEND_BEGIN_ARG_INFO(arginfo_enchant_broker_init, 0)
  53. ZEND_END_ARG_INFO()
  54. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free, 0, 0, 1)
  55. ZEND_ARG_INFO(0, broker)
  56. ZEND_END_ARG_INFO()
  57. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_dict_path, 0, 0, 3)
  58. ZEND_ARG_INFO(0, broker)
  59. ZEND_ARG_INFO(0, name)
  60. ZEND_ARG_INFO(0, value)
  61. ZEND_END_ARG_INFO()
  62. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_get_dict_path, 0, 0, 2)
  63. ZEND_ARG_INFO(0, broker)
  64. ZEND_ARG_INFO(0, name)
  65. ZEND_END_ARG_INFO()
  66. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_dict, 0, 0, 2)
  67. ZEND_ARG_INFO(0, broker)
  68. ZEND_ARG_INFO(0, tag)
  69. ZEND_END_ARG_INFO()
  70. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_pwl_dict, 0, 0, 2)
  71. ZEND_ARG_INFO(0, broker)
  72. ZEND_ARG_INFO(0, filename)
  73. ZEND_END_ARG_INFO()
  74. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free_dict, 0, 0, 1)
  75. ZEND_ARG_INFO(0, dict)
  76. ZEND_END_ARG_INFO()
  77. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_ordering, 0, 0, 3)
  78. ZEND_ARG_INFO(0, broker)
  79. ZEND_ARG_INFO(0, tag)
  80. ZEND_ARG_INFO(0, ordering)
  81. ZEND_END_ARG_INFO()
  82. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_quick_check, 0, 0, 2)
  83. ZEND_ARG_INFO(0, dict)
  84. ZEND_ARG_INFO(0, word)
  85. ZEND_ARG_INFO(1, suggestions)
  86. ZEND_END_ARG_INFO()
  87. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_check, 0, 0, 2)
  88. ZEND_ARG_INFO(0, dict)
  89. ZEND_ARG_INFO(0, word)
  90. ZEND_END_ARG_INFO()
  91. ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_store_replacement, 0, 0, 3)
  92. ZEND_ARG_INFO(0, dict)
  93. ZEND_ARG_INFO(0, mis)
  94. ZEND_ARG_INFO(0, cor)
  95. ZEND_END_ARG_INFO()
  96. /* }}} */
  97. /* {{{ enchant_functions[]
  98. *
  99. * Every user visible function must have an entry in enchant_functions[].
  100. */
  101. static const zend_function_entry enchant_functions[] = {
  102. PHP_FE(enchant_broker_init, arginfo_enchant_broker_init)
  103. PHP_FE(enchant_broker_free, arginfo_enchant_broker_free)
  104. PHP_FE(enchant_broker_get_error, arginfo_enchant_broker_free)
  105. PHP_FE(enchant_broker_set_dict_path, arginfo_enchant_broker_set_dict_path)
  106. PHP_FE(enchant_broker_get_dict_path, arginfo_enchant_broker_get_dict_path)
  107. PHP_FE(enchant_broker_list_dicts, arginfo_enchant_broker_free)
  108. PHP_FE(enchant_broker_request_dict, arginfo_enchant_broker_request_dict)
  109. PHP_FE(enchant_broker_request_pwl_dict, arginfo_enchant_broker_request_pwl_dict)
  110. PHP_FE(enchant_broker_free_dict, arginfo_enchant_broker_free_dict)
  111. PHP_FE(enchant_broker_dict_exists, arginfo_enchant_broker_request_dict)
  112. PHP_FE(enchant_broker_set_ordering, arginfo_enchant_broker_set_ordering)
  113. PHP_FE(enchant_broker_describe, arginfo_enchant_broker_free)
  114. PHP_FE(enchant_dict_check, arginfo_enchant_dict_check)
  115. PHP_FE(enchant_dict_suggest, arginfo_enchant_dict_check)
  116. PHP_FE(enchant_dict_add_to_personal, arginfo_enchant_dict_check)
  117. PHP_FE(enchant_dict_add_to_session, arginfo_enchant_dict_check)
  118. PHP_FE(enchant_dict_is_in_session, arginfo_enchant_dict_check)
  119. PHP_FE(enchant_dict_store_replacement, arginfo_enchant_dict_store_replacement)
  120. PHP_FE(enchant_dict_get_error, arginfo_enchant_broker_free_dict)
  121. PHP_FE(enchant_dict_describe, arginfo_enchant_broker_free_dict)
  122. PHP_FE(enchant_dict_quick_check, arginfo_enchant_dict_quick_check)
  123. PHP_FE_END
  124. };
  125. /* }}} */
  126. /* {{{ enchant_module_entry
  127. */
  128. zend_module_entry enchant_module_entry = {
  129. STANDARD_MODULE_HEADER,
  130. "enchant",
  131. enchant_functions,
  132. PHP_MINIT(enchant),
  133. PHP_MSHUTDOWN(enchant),
  134. NULL, /* Replace with NULL if there's nothing to do at request start */
  135. NULL, /* Replace with NULL if there's nothing to do at request end */
  136. PHP_MINFO(enchant),
  137. PHP_ENCHANT_VERSION,
  138. STANDARD_MODULE_PROPERTIES
  139. };
  140. /* }}} */
  141. #ifdef COMPILE_DL_ENCHANT
  142. ZEND_GET_MODULE(enchant)
  143. #endif
  144. static void
  145. enumerate_providers_fn (const char * const name,
  146. const char * const desc,
  147. const char * const file,
  148. void * ud) /* {{{ */
  149. {
  150. zval *zdesc = (zval *) ud;
  151. zval tmp_array;
  152. array_init(&tmp_array);
  153. add_assoc_string(&tmp_array, "name", (char *)name);
  154. add_assoc_string(&tmp_array, "desc", (char *)desc);
  155. add_assoc_string(&tmp_array, "file", (char *)file);
  156. if (Z_TYPE_P(zdesc)!=IS_ARRAY) {
  157. array_init(zdesc);
  158. }
  159. add_next_index_zval(zdesc, &tmp_array);
  160. }
  161. /* }}} */
  162. static void
  163. describe_dict_fn (const char * const lang,
  164. const char * const name,
  165. const char * const desc,
  166. const char * const file,
  167. void * ud) /* {{{ */
  168. {
  169. zval *zdesc = (zval *) ud;
  170. array_init(zdesc);
  171. add_assoc_string(zdesc, "lang", (char *)lang);
  172. add_assoc_string(zdesc, "name", (char *)name);
  173. add_assoc_string(zdesc, "desc", (char *)desc);
  174. add_assoc_string(zdesc, "file", (char *)file);
  175. }
  176. /* }}} */
  177. static void php_enchant_list_dicts_fn( const char * const lang_tag,
  178. const char * const provider_name, const char * const provider_desc,
  179. const char * const provider_file, void * ud) /* {{{ */
  180. {
  181. zval *zdesc = (zval *) ud;
  182. zval tmp_array;
  183. array_init(&tmp_array);
  184. add_assoc_string(&tmp_array, "lang_tag", (char *)lang_tag);
  185. add_assoc_string(&tmp_array, "provider_name", (char *)provider_name);
  186. add_assoc_string(&tmp_array, "provider_desc", (char *)provider_desc);
  187. add_assoc_string(&tmp_array, "provider_file", (char *)provider_file);
  188. if (Z_TYPE_P(zdesc) != IS_ARRAY) {
  189. array_init(zdesc);
  190. }
  191. add_next_index_zval(zdesc, &tmp_array);
  192. }
  193. /* }}} */
  194. static void php_enchant_broker_free(zend_resource *rsrc) /* {{{ */
  195. {
  196. if (rsrc->ptr) {
  197. enchant_broker *broker = (enchant_broker *)rsrc->ptr;
  198. if (broker) {
  199. if (broker->pbroker) {
  200. if (broker->dictcnt && broker->dict) {
  201. if (broker->dict) {
  202. int total;
  203. total = broker->dictcnt-1;
  204. do {
  205. if (broker->dict[total]) {
  206. enchant_dict *pdict = broker->dict[total];
  207. broker->dict[total] = NULL;
  208. zend_list_free(pdict->rsrc);
  209. efree(pdict);
  210. }
  211. total--;
  212. } while (total>=0);
  213. }
  214. efree(broker->dict);
  215. broker->dict = NULL;
  216. }
  217. enchant_broker_free(broker->pbroker);
  218. }
  219. efree(broker);
  220. }
  221. }
  222. }
  223. /* }}} */
  224. static void php_enchant_dict_free(zend_resource *rsrc) /* {{{ */
  225. {
  226. if (rsrc->ptr) {
  227. enchant_dict *pdict = (enchant_dict *)rsrc->ptr;
  228. if (pdict) {
  229. enchant_broker *pbroker = pdict->pbroker;
  230. if (pdict->pdict && pbroker) {
  231. enchant_broker_free_dict(pbroker->pbroker, pdict->pdict);
  232. }
  233. pbroker->dict[pdict->id] = NULL;
  234. efree(pdict);
  235. zend_list_delete(pbroker->rsrc);
  236. }
  237. }
  238. }
  239. /* }}} */
  240. /* {{{ PHP_MINIT_FUNCTION
  241. */
  242. PHP_MINIT_FUNCTION(enchant)
  243. {
  244. le_enchant_broker = zend_register_list_destructors_ex(php_enchant_broker_free, NULL, "enchant_broker", module_number);
  245. le_enchant_dict = zend_register_list_destructors_ex(php_enchant_dict_free, NULL, "enchant_dict", module_number);
  246. REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_CS | CONST_PERSISTENT);
  247. REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_CS | CONST_PERSISTENT);
  248. return SUCCESS;
  249. }
  250. /* }}} */
  251. /* {{{ PHP_MSHUTDOWN_FUNCTION
  252. */
  253. PHP_MSHUTDOWN_FUNCTION(enchant)
  254. {
  255. return SUCCESS;
  256. }
  257. /* }}} */
  258. static void __enumerate_providers_fn (const char * const name,
  259. const char * const desc,
  260. const char * const file,
  261. void * ud) /* {{{ */
  262. {
  263. php_info_print_table_row(3, name, desc, file);
  264. }
  265. /* }}} */
  266. /* {{{ PHP_MINFO_FUNCTION
  267. */
  268. PHP_MINFO_FUNCTION(enchant)
  269. {
  270. EnchantBroker *pbroker;
  271. pbroker = enchant_broker_init();
  272. php_info_print_table_start();
  273. php_info_print_table_row(2, "enchant support", "enabled");
  274. #ifdef ENCHANT_VERSION_STRING
  275. php_info_print_table_row(2, "Libenchant Version", ENCHANT_VERSION_STRING);
  276. #elif defined(HAVE_ENCHANT_BROKER_SET_PARAM)
  277. php_info_print_table_row(2, "Libenchant Version", "1.5.0 or later");
  278. #endif
  279. php_info_print_table_end();
  280. php_info_print_table_start();
  281. enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
  282. php_info_print_table_end();
  283. enchant_broker_free(pbroker);
  284. }
  285. /* }}} */
  286. #define PHP_ENCHANT_GET_BROKER \
  287. pbroker = (enchant_broker *)zend_fetch_resource(Z_RES_P(broker), "enchant_broker", le_enchant_broker); \
  288. if (!pbroker || !pbroker->pbroker) { \
  289. php_error_docref(NULL, E_WARNING, "%s", "Resource broker invalid"); \
  290. RETURN_FALSE; \
  291. }
  292. #define PHP_ENCHANT_GET_DICT \
  293. pdict = (enchant_dict *)zend_fetch_resource(Z_RES_P(dict), "enchant_dict", le_enchant_dict); \
  294. if (!pdict || !pdict->pdict) { \
  295. php_error_docref(NULL, E_WARNING, "%s", "Invalid dictionary resource."); \
  296. RETURN_FALSE; \
  297. }
  298. /* {{{ proto resource enchant_broker_init()
  299. create a new broker object capable of requesting */
  300. PHP_FUNCTION(enchant_broker_init)
  301. {
  302. enchant_broker *broker;
  303. EnchantBroker *pbroker;
  304. if (zend_parse_parameters_none() == FAILURE) {
  305. return;
  306. }
  307. pbroker = enchant_broker_init();
  308. if (pbroker) {
  309. broker = (enchant_broker *) emalloc(sizeof(enchant_broker));
  310. broker->pbroker = pbroker;
  311. broker->dict = NULL;
  312. broker->dictcnt = 0;
  313. broker->rsrc = zend_register_resource(broker, le_enchant_broker);
  314. RETURN_RES(broker->rsrc);
  315. } else {
  316. RETURN_FALSE;
  317. }
  318. }
  319. /* }}} */
  320. /* {{{ proto bool enchant_broker_free(resource broker)
  321. Destroys the broker object and its dictionnaries */
  322. PHP_FUNCTION(enchant_broker_free)
  323. {
  324. zval *broker;
  325. enchant_broker *pbroker;
  326. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &broker) == FAILURE) {
  327. RETURN_FALSE;
  328. }
  329. PHP_ENCHANT_GET_BROKER;
  330. zend_list_close(Z_RES_P(broker));
  331. RETURN_TRUE;
  332. }
  333. /* }}} */
  334. /* {{{ proto string enchant_broker_get_error(resource broker)
  335. Returns the last error of the broker */
  336. PHP_FUNCTION(enchant_broker_get_error)
  337. {
  338. zval *broker;
  339. enchant_broker *pbroker;
  340. char *msg;
  341. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &broker) == FAILURE) {
  342. RETURN_FALSE;
  343. }
  344. PHP_ENCHANT_GET_BROKER;
  345. msg = enchant_broker_get_error(pbroker->pbroker);
  346. if (msg) {
  347. RETURN_STRING((char *)msg);
  348. }
  349. RETURN_FALSE;
  350. }
  351. /* }}} */
  352. #if HAVE_ENCHANT_BROKER_SET_PARAM
  353. /* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
  354. Set the directory path for a given backend, works with ispell and myspell */
  355. PHP_FUNCTION(enchant_broker_set_dict_path)
  356. {
  357. zval *broker;
  358. enchant_broker *pbroker;
  359. zend_long dict_type;
  360. char *value;
  361. size_t value_len;
  362. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rls", &broker, &dict_type, &value, &value_len) == FAILURE) {
  363. RETURN_FALSE;
  364. }
  365. if (!value_len) {
  366. RETURN_FALSE;
  367. }
  368. PHP_ENCHANT_GET_BROKER;
  369. switch (dict_type) {
  370. case PHP_ENCHANT_MYSPELL:
  371. PHP_ENCHANT_GET_BROKER;
  372. enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value);
  373. RETURN_TRUE;
  374. break;
  375. case PHP_ENCHANT_ISPELL:
  376. PHP_ENCHANT_GET_BROKER;
  377. enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value);
  378. RETURN_TRUE;
  379. break;
  380. default:
  381. RETURN_FALSE;
  382. }
  383. }
  384. /* }}} */
  385. /* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
  386. Get the directory path for a given backend, works with ispell and myspell */
  387. PHP_FUNCTION(enchant_broker_get_dict_path)
  388. {
  389. zval *broker;
  390. enchant_broker *pbroker;
  391. zend_long dict_type;
  392. char *value;
  393. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &broker, &dict_type) == FAILURE) {
  394. RETURN_FALSE;
  395. }
  396. PHP_ENCHANT_GET_BROKER;
  397. switch (dict_type) {
  398. case PHP_ENCHANT_MYSPELL:
  399. PHP_ENCHANT_GET_BROKER;
  400. value = enchant_broker_get_param(pbroker->pbroker, "enchant.myspell.dictionary.path");
  401. break;
  402. case PHP_ENCHANT_ISPELL:
  403. PHP_ENCHANT_GET_BROKER;
  404. value = enchant_broker_get_param(pbroker->pbroker, "enchant.ispell.dictionary.path");
  405. break;
  406. default:
  407. RETURN_FALSE;
  408. }
  409. if (value == NULL) {
  410. php_error_docref(NULL, E_WARNING, "dict_path not set");
  411. RETURN_FALSE;
  412. }
  413. RETURN_STRING(value);
  414. }
  415. /* }}} */
  416. #else
  417. /* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
  418. Set the directory path for a given backend, works with ispell and myspell */
  419. PHP_FUNCTION(enchant_broker_set_dict_path)
  420. {
  421. RETURN_FALSE;
  422. }
  423. /* }}} */
  424. /* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
  425. Get the directory path for a given backend, works with ispell and myspell */
  426. PHP_FUNCTION(enchant_broker_get_dict_path)
  427. {
  428. RETURN_FALSE;
  429. }
  430. /* }}} */
  431. #endif
  432. /* {{{ proto string enchant_broker_list_dicts(resource broker)
  433. Lists the dictionaries available for the given broker */
  434. PHP_FUNCTION(enchant_broker_list_dicts)
  435. {
  436. zval *broker;
  437. enchant_broker *pbroker;
  438. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &broker) == FAILURE) {
  439. RETURN_FALSE;
  440. }
  441. PHP_ENCHANT_GET_BROKER;
  442. enchant_broker_list_dicts(pbroker->pbroker, php_enchant_list_dicts_fn, (void *)return_value);
  443. }
  444. /* }}} */
  445. /* {{{ proto resource enchant_broker_request_dict(resource broker, string tag)
  446. create a new dictionary using tag, the non-empty language tag you wish to request
  447. a dictionary for ("en_US", "de_DE", ...) */
  448. PHP_FUNCTION(enchant_broker_request_dict)
  449. {
  450. zval *broker;
  451. enchant_broker *pbroker;
  452. enchant_dict *dict;
  453. EnchantDict *d;
  454. char *tag;
  455. size_t taglen;
  456. int pos;
  457. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &broker, &tag, &taglen) == FAILURE) {
  458. RETURN_FALSE;
  459. }
  460. PHP_ENCHANT_GET_BROKER;
  461. if (taglen == 0) {
  462. php_error_docref(NULL, E_WARNING, "Tag cannot be empty");
  463. RETURN_FALSE;
  464. }
  465. d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
  466. if (d) {
  467. pos = pbroker->dictcnt++;
  468. if (pbroker->dictcnt) {
  469. pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
  470. } else {
  471. pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
  472. pos = 0;
  473. }
  474. dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
  475. dict->id = pos;
  476. dict->pbroker = pbroker;
  477. dict->pdict = d;
  478. pbroker->dict[pos] = dict;
  479. dict->rsrc = zend_register_resource(dict, le_enchant_dict);
  480. GC_ADDREF(pbroker->rsrc);
  481. RETURN_RES(dict->rsrc);
  482. } else {
  483. RETURN_FALSE;
  484. }
  485. }
  486. /* }}} */
  487. /* {{{ proto resource enchant_broker_request_pwl_dict(resource broker, string filename)
  488. creates a dictionary using a PWL file. A PWL file is personal word file one word per line. It must exist before the call.*/
  489. PHP_FUNCTION(enchant_broker_request_pwl_dict)
  490. {
  491. zval *broker;
  492. enchant_broker *pbroker;
  493. enchant_dict *dict;
  494. EnchantDict *d;
  495. char *pwl;
  496. size_t pwllen;
  497. int pos;
  498. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &broker, &pwl, &pwllen) == FAILURE) {
  499. RETURN_FALSE;
  500. }
  501. if (php_check_open_basedir(pwl)) {
  502. RETURN_FALSE;
  503. }
  504. PHP_ENCHANT_GET_BROKER;
  505. d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl);
  506. if (d) {
  507. pos = pbroker->dictcnt++;
  508. if (pbroker->dictcnt) {
  509. pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
  510. } else {
  511. pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
  512. pos = 0;
  513. }
  514. dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
  515. dict->id = pos;
  516. dict->pbroker = pbroker;
  517. dict->pdict = d;
  518. pbroker->dict[pos] = dict;
  519. dict->rsrc = zend_register_resource(dict, le_enchant_dict);
  520. GC_ADDREF(pbroker->rsrc);
  521. RETURN_RES(dict->rsrc);
  522. } else {
  523. RETURN_FALSE;
  524. }
  525. }
  526. /* }}} */
  527. /* {{{ proto resource enchant_broker_free_dict(resource dict)
  528. Free the dictionary resource */
  529. PHP_FUNCTION(enchant_broker_free_dict)
  530. {
  531. zval *dict;
  532. enchant_dict *pdict;
  533. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
  534. RETURN_FALSE;
  535. }
  536. PHP_ENCHANT_GET_DICT;
  537. zend_list_close(Z_RES_P(dict));
  538. RETURN_TRUE;
  539. }
  540. /* }}} */
  541. /* {{{ proto bool enchant_broker_dict_exists(resource broker, string tag)
  542. Whether a dictionary exists or not. Using non-empty tag */
  543. PHP_FUNCTION(enchant_broker_dict_exists)
  544. {
  545. zval *broker;
  546. char *tag;
  547. size_t taglen;
  548. enchant_broker * pbroker;
  549. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &broker, &tag, &taglen) == FAILURE) {
  550. RETURN_FALSE;
  551. }
  552. PHP_ENCHANT_GET_BROKER;
  553. RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
  554. }
  555. /* }}} */
  556. /* {{{ proto bool enchant_broker_set_ordering(resource broker, string tag, string ordering)
  557. Declares a preference of dictionaries to use for the language
  558. described/referred to by 'tag'. The ordering is a comma delimited
  559. list of provider names. As a special exception, the "*" tag can
  560. be used as a language tag to declare a default ordering for any
  561. language that does not explicitly declare an ordering. */
  562. PHP_FUNCTION(enchant_broker_set_ordering)
  563. {
  564. zval *broker;
  565. char *pordering;
  566. size_t porderinglen;
  567. char *ptag;
  568. size_t ptaglen;
  569. enchant_broker * pbroker;
  570. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &broker, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
  571. RETURN_FALSE;
  572. }
  573. PHP_ENCHANT_GET_BROKER;
  574. enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
  575. RETURN_TRUE;
  576. }
  577. /* }}} */
  578. /* {{{ proto array enchant_broker_describe(resource broker)
  579. Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
  580. PHP_FUNCTION(enchant_broker_describe)
  581. {
  582. EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
  583. zval *broker;
  584. enchant_broker * pbroker;
  585. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &broker) == FAILURE) {
  586. RETURN_FALSE;
  587. }
  588. PHP_ENCHANT_GET_BROKER;
  589. enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
  590. }
  591. /* }}} */
  592. /* {{{ proto bool enchant_dict_quick_check(resource dict, string word [, array &suggestions])
  593. If the word is correctly spelled return true, otherwise return false, if suggestions variable
  594. is provided, fill it with spelling alternatives. */
  595. PHP_FUNCTION(enchant_dict_quick_check)
  596. {
  597. zval *dict, *sugg = NULL;
  598. char *word;
  599. size_t wordlen;
  600. enchant_dict *pdict;
  601. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) {
  602. RETURN_FALSE;
  603. }
  604. if (sugg) {
  605. zval_ptr_dtor(sugg);
  606. array_init(sugg);
  607. }
  608. PHP_ENCHANT_GET_DICT;
  609. if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
  610. size_t n_sugg;
  611. char **suggs;
  612. if (!sugg && ZEND_NUM_ARGS() == 2) {
  613. RETURN_FALSE;
  614. }
  615. suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
  616. if (suggs && n_sugg) {
  617. size_t i;
  618. for (i = 0; i < n_sugg; i++) {
  619. add_next_index_string(sugg, suggs[i]);
  620. }
  621. enchant_dict_free_suggestions(pdict->pdict, suggs);
  622. }
  623. RETURN_FALSE;
  624. }
  625. RETURN_TRUE;
  626. }
  627. /* }}} */
  628. /* {{{ proto bool enchant_dict_check(resource dict, string word)
  629. If the word is correctly spelled return true, otherwise return false */
  630. PHP_FUNCTION(enchant_dict_check)
  631. {
  632. zval *dict;
  633. char *word;
  634. size_t wordlen;
  635. enchant_dict *pdict;
  636. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
  637. RETURN_FALSE;
  638. }
  639. PHP_ENCHANT_GET_DICT;
  640. RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
  641. }
  642. /* }}} */
  643. /* {{{ proto array enchant_dict_suggest(resource dict, string word)
  644. Will return a list of values if any of those pre-conditions are not met.*/
  645. PHP_FUNCTION(enchant_dict_suggest)
  646. {
  647. zval *dict;
  648. char *word;
  649. size_t wordlen;
  650. char **suggs;
  651. enchant_dict *pdict;
  652. size_t n_sugg;
  653. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
  654. RETURN_FALSE;
  655. }
  656. PHP_ENCHANT_GET_DICT;
  657. suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
  658. if (suggs && n_sugg) {
  659. size_t i;
  660. array_init(return_value);
  661. for (i = 0; i < n_sugg; i++) {
  662. add_next_index_string(return_value, suggs[i]);
  663. }
  664. enchant_dict_free_suggestions(pdict->pdict, suggs);
  665. }
  666. }
  667. /* }}} */
  668. /* {{{ proto void enchant_dict_add_to_personal(resource dict, string word)
  669. add 'word' to personal word list */
  670. PHP_FUNCTION(enchant_dict_add_to_personal)
  671. {
  672. zval *dict;
  673. char *word;
  674. size_t wordlen;
  675. enchant_dict *pdict;
  676. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
  677. RETURN_FALSE;
  678. }
  679. PHP_ENCHANT_GET_DICT;
  680. enchant_dict_add_to_personal(pdict->pdict, word, wordlen);
  681. }
  682. /* }}} */
  683. /* {{{ proto void enchant_dict_add_to_session(resource dict, string word)
  684. add 'word' to this spell-checking session */
  685. PHP_FUNCTION(enchant_dict_add_to_session)
  686. {
  687. zval *dict;
  688. char *word;
  689. size_t wordlen;
  690. enchant_dict *pdict;
  691. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
  692. RETURN_FALSE;
  693. }
  694. PHP_ENCHANT_GET_DICT;
  695. enchant_dict_add_to_session(pdict->pdict, word, wordlen);
  696. }
  697. /* }}} */
  698. /* {{{ proto bool enchant_dict_is_in_session(resource dict, string word)
  699. whether or not 'word' exists in this spelling-session */
  700. PHP_FUNCTION(enchant_dict_is_in_session)
  701. {
  702. zval *dict;
  703. char *word;
  704. size_t wordlen;
  705. enchant_dict *pdict;
  706. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
  707. RETURN_FALSE;
  708. }
  709. PHP_ENCHANT_GET_DICT;
  710. RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen));
  711. }
  712. /* }}} */
  713. /* {{{ proto void enchant_dict_store_replacement(resource dict, string mis, string cor)
  714. add a correction for 'mis' using 'cor'.
  715. Notes that you replaced @mis with @cor, so it's possibly more likely
  716. that future occurrences of @mis will be replaced with @cor. So it might
  717. bump @cor up in the suggestion list.*/
  718. PHP_FUNCTION(enchant_dict_store_replacement)
  719. {
  720. zval *dict;
  721. char *mis, *cor;
  722. size_t mislen, corlen;
  723. enchant_dict *pdict;
  724. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) {
  725. RETURN_FALSE;
  726. }
  727. PHP_ENCHANT_GET_DICT;
  728. enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
  729. }
  730. /* }}} */
  731. /* {{{ proto string enchant_dict_get_error(resource dict)
  732. Returns the last error of the current spelling-session */
  733. PHP_FUNCTION(enchant_dict_get_error)
  734. {
  735. zval *dict;
  736. enchant_dict *pdict;
  737. char *msg;
  738. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
  739. RETURN_FALSE;
  740. }
  741. PHP_ENCHANT_GET_DICT;
  742. msg = enchant_dict_get_error(pdict->pdict);
  743. if (msg) {
  744. RETURN_STRING((char *)msg);
  745. }
  746. RETURN_FALSE;
  747. }
  748. /* }}} */
  749. /* {{{ proto array enchant_dict_describe(resource dict)
  750. Describes an individual dictionary 'dict' */
  751. PHP_FUNCTION(enchant_dict_describe)
  752. {
  753. zval *dict;
  754. enchant_dict *pdict;
  755. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
  756. RETURN_FALSE;
  757. }
  758. PHP_ENCHANT_GET_DICT;
  759. enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
  760. }
  761. /* }}} */
  762. /*
  763. * Local variables:
  764. * tab-width: 4
  765. * c-basic-offset: 4
  766. * End:
  767. * vim600: noet sw=4 ts=4 fdm=marker
  768. * vim<600: noet sw=4 ts=4
  769. */