summaryrefslogtreecommitdiff
path: root/ext/enchant
diff options
context:
space:
mode:
Diffstat (limited to 'ext/enchant')
-rw-r--r--ext/enchant/CREDITS2
-rwxr-xr-xext/enchant/config.m442
-rw-r--r--ext/enchant/config.w3217
-rw-r--r--ext/enchant/docs/examples/example1.php25
-rw-r--r--ext/enchant/enchant.c943
-rwxr-xr-xext/enchant/package.xml162
-rw-r--r--ext/enchant/php_enchant.h82
-rw-r--r--ext/enchant/tests/broker_describe.phpt28
-rw-r--r--ext/enchant/tests/broker_free.phpt21
-rw-r--r--ext/enchant/tests/broker_init.phpt15
-rw-r--r--ext/enchant/tests/broker_request_dict.phpt31
-rw-r--r--ext/enchant/tests/bug13181.phpt43
-rw-r--r--ext/enchant/tests/dict_quick_check.phpt26
-rw-r--r--ext/enchant/tests/hindi_correct.txt1
-rw-r--r--ext/enchant/tests/hindi_incorrect.txt1
15 files changed, 1439 insertions, 0 deletions
diff --git a/ext/enchant/CREDITS b/ext/enchant/CREDITS
new file mode 100644
index 0000000..481febb
--- /dev/null
+++ b/ext/enchant/CREDITS
@@ -0,0 +1,2 @@
+enchant
+Pierre-Alain Joye, Ilia Alshanetsky
diff --git a/ext/enchant/config.m4 b/ext/enchant/config.m4
new file mode 100755
index 0000000..cc40d0b
--- /dev/null
+++ b/ext/enchant/config.m4
@@ -0,0 +1,42 @@
+dnl
+dnl $Id$
+dnl
+
+PHP_ARG_WITH(enchant,for ENCHANT support,
+[ --with-enchant[=DIR] Include enchant support.
+ GNU Aspell version 1.1.3 or higher required.])
+
+if test "$PHP_ENCHANT" != "no"; then
+ PHP_NEW_EXTENSION(enchant, enchant.c, $ext_shared)
+ if test "$PHP_ENCHANT" != "yes"; then
+ ENCHANT_SEARCH_DIRS=$PHP_ENCHANT
+ else
+ ENCHANT_SEARCH_DIRS="/usr/local /usr"
+ fi
+ for i in $ENCHANT_SEARCH_DIRS; do
+ if test -f $i/include/enchant/enchant.h; then
+ ENCHANT_DIR=$i
+ ENCHANT_INCDIR=$i/include/enchant
+ elif test -f $i/include/enchant.h; then
+ ENCHANT_DIR=$i
+ ENCHANT_INCDIR=$i/include
+ fi
+ done
+
+ if test -z "$ENCHANT_DIR"; then
+ AC_MSG_ERROR(Cannot find enchant)
+ fi
+
+ ENCHANT_LIBDIR=$ENCHANT_DIR/lib
+
+ AC_DEFINE(HAVE_ENCHANT,1,[ ])
+ PHP_SUBST(ENCHANT_SHARED_LIBADD)
+ PHP_ADD_LIBRARY_WITH_PATH(enchant, $ENCHANT_LIBDIR, ENCHANT_SHARED_LIBADD)
+ PHP_ADD_INCLUDE($ENCHANT_INCDIR)
+ PHP_CHECK_LIBRARY(enchant, enchant_broker_set_param,
+ [
+ AC_DEFINE(HAVE_ENCHANT_BROKER_SET_PARAM, 1, [ ])
+ AC_DEFINE(ENCHANT_VERSION_STRING, "1.5.x", [ ])
+ ], [], [ -L$ENCHANT_LIB $ENCHANT_SHARED_LIBADD])
+
+fi
diff --git a/ext/enchant/config.w32 b/ext/enchant/config.w32
new file mode 100644
index 0000000..3e4c357
--- /dev/null
+++ b/ext/enchant/config.w32
@@ -0,0 +1,17 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("enchant", "Enchant Support", "no");
+
+if (PHP_ENCHANT == "yes") {
+ if (CHECK_HEADER_ADD_INCLUDE("enchant.h", "CFLAGS_ENCHANT", PHP_ENCHANT+ ";" + PHP_PHP_BUILD + "\\include\\enchant") &&
+ CHECK_HEADER_ADD_INCLUDE("glib.h", "CFLAGS_ENCHANT", PHP_ENCHANT+ ";" + PHP_PHP_BUILD + "\\include\\glib-2.0") &&
+ CHECK_LIB("libenchant.lib", "enchant", PHP_ENCHANT) ) {
+ EXTENSION("enchant", "enchant.c");
+ AC_DEFINE('HAVE_ENCHANT', 1, 'Have Enchant support', false);
+ AC_DEFINE('HAVE_ENCHANT_BROKER_SET_PARAM', 1);
+ ADD_FLAG("CFLAG_ENCHANT", "/D _WIN32");
+ } else {
+ WARNING('Could not find enchant.h; skipping');
+ }
+}
diff --git a/ext/enchant/docs/examples/example1.php b/ext/enchant/docs/examples/example1.php
new file mode 100644
index 0000000..048cc83
--- /dev/null
+++ b/ext/enchant/docs/examples/example1.php
@@ -0,0 +1,25 @@
+<?php
+$tag = 'en_US';
+$r = enchant_broker_init();
+$bprovides = enchant_broker_describe($r);
+echo "Current broker provides the following backend(s):\n";
+print_r($bprovides);
+
+
+if (enchant_broker_dict_exists($r,$tag)) {
+ $d = enchant_broker_request_dict($r, $tag);
+ $dprovides = enchant_dict_describe($d);
+ echo "dictionary $tag provides:\n";
+ $spellerrors = enchant_dict_check($d, "soong");
+ print_r($dprovides);
+ echo "found $spellerrors spell errors\n";
+ if (spellerrors) {
+ $suggs = enchant_dict_suggest($d, "soong");
+ echo "Suggestions for 'soong':";
+ print_r($suggs);
+ }
+ enchant_broker_free_dict($d);
+} else {
+}
+enchant_broker_free($r);
+?>
diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c
new file mode 100644
index 0000000..be6d9f6
--- /dev/null
+++ b/ext/enchant/enchant.c
@@ -0,0 +1,943 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Pierre-Alain Joye <paj@pearfr.org> |
+ | Ilia Alshanetsky <ilia@prohost.org> |
+ +----------------------------------------------------------------------+
+
+ $Id: 3d50cb80a6388ef6552aa4e71d33a136792f4fc2 $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <enchant.h>
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_enchant.h"
+
+typedef EnchantBroker * EnchantBrokerPtr;
+typedef struct _broker_struct enchant_broker;
+typedef struct _dict_struct enchant_dict;
+
+typedef enchant_broker * enchant_brokerPtr;
+typedef enchant_dict * enchant_dictPtr;
+
+typedef struct _broker_struct {
+ EnchantBroker *pbroker;
+ enchant_dict **dict;
+ unsigned int dictcnt;
+ long rsrc_id;
+} _enchant_broker;
+
+typedef struct _dict_struct {
+ unsigned int id;
+ EnchantDict *pdict;
+ enchant_broker *pbroker;
+ long rsrc_id;
+ enchant_dict *next;
+ enchant_dict *prev;
+} _enchant_dict;
+
+
+/* True global resources - no need for thread safety here */
+static int le_enchant_broker;
+static int le_enchant_dict;
+
+/* If you declare any globals in php_enchant.h uncomment this:*/
+/*ZEND_DECLARE_MODULE_GLOBALS(enchant)*/
+
+#define PHP_ENCHANT_MYSPELL 1
+#define PHP_ENCHANT_ISPELL 2
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO(arginfo_enchant_broker_init, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free, 0, 0, 1)
+ ZEND_ARG_INFO(0, broker)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_dict_path, 0, 0, 3)
+ ZEND_ARG_INFO(0, broker)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_get_dict_path, 0, 0, 2)
+ ZEND_ARG_INFO(0, broker)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_dict, 0, 0, 2)
+ ZEND_ARG_INFO(0, broker)
+ ZEND_ARG_INFO(0, tag)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_pwl_dict, 0, 0, 2)
+ ZEND_ARG_INFO(0, broker)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free_dict, 0, 0, 1)
+ ZEND_ARG_INFO(0, dict)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_ordering, 0, 0, 3)
+ ZEND_ARG_INFO(0, broker)
+ ZEND_ARG_INFO(0, tag)
+ ZEND_ARG_INFO(0, ordering)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_quick_check, 0, 0, 2)
+ ZEND_ARG_INFO(0, dict)
+ ZEND_ARG_INFO(0, word)
+ ZEND_ARG_INFO(1, suggestions)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_check, 0, 0, 2)
+ ZEND_ARG_INFO(0, dict)
+ ZEND_ARG_INFO(0, word)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_store_replacement, 0, 0, 3)
+ ZEND_ARG_INFO(0, dict)
+ ZEND_ARG_INFO(0, mis)
+ ZEND_ARG_INFO(0, cor)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ enchant_functions[]
+ *
+ * Every user visible function must have an entry in enchant_functions[].
+ */
+zend_function_entry enchant_functions[] = {
+ PHP_FE(enchant_broker_init, arginfo_enchant_broker_init)
+ PHP_FE(enchant_broker_free, arginfo_enchant_broker_free)
+ PHP_FE(enchant_broker_get_error, arginfo_enchant_broker_free)
+ PHP_FE(enchant_broker_set_dict_path, arginfo_enchant_broker_set_dict_path)
+ PHP_FE(enchant_broker_get_dict_path, arginfo_enchant_broker_get_dict_path)
+ PHP_FE(enchant_broker_list_dicts, arginfo_enchant_broker_free)
+ PHP_FE(enchant_broker_request_dict, arginfo_enchant_broker_request_dict)
+ PHP_FE(enchant_broker_request_pwl_dict, arginfo_enchant_broker_request_pwl_dict)
+ PHP_FE(enchant_broker_free_dict, arginfo_enchant_broker_free_dict)
+ PHP_FE(enchant_broker_dict_exists, arginfo_enchant_broker_request_dict)
+ PHP_FE(enchant_broker_set_ordering, arginfo_enchant_broker_set_ordering)
+ PHP_FE(enchant_broker_describe, arginfo_enchant_broker_free)
+ PHP_FE(enchant_dict_check, arginfo_enchant_dict_check)
+ PHP_FE(enchant_dict_suggest, arginfo_enchant_dict_check)
+ PHP_FE(enchant_dict_add_to_personal, arginfo_enchant_dict_check)
+ PHP_FE(enchant_dict_add_to_session, arginfo_enchant_dict_check)
+ PHP_FE(enchant_dict_is_in_session, arginfo_enchant_dict_check)
+ PHP_FE(enchant_dict_store_replacement, arginfo_enchant_dict_store_replacement)
+ PHP_FE(enchant_dict_get_error, arginfo_enchant_broker_free_dict)
+ PHP_FE(enchant_dict_describe, arginfo_enchant_broker_free_dict)
+ PHP_FE(enchant_dict_quick_check, arginfo_enchant_dict_quick_check)
+ PHP_FE_END
+};
+/* }}} */
+
+/* {{{ enchant_module_entry
+ */
+zend_module_entry enchant_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "enchant",
+ enchant_functions,
+ PHP_MINIT(enchant),
+ PHP_MSHUTDOWN(enchant),
+ NULL, /* Replace with NULL if there's nothing to do at request start */
+ NULL, /* Replace with NULL if there's nothing to do at request end */
+ PHP_MINFO(enchant),
+#if ZEND_MODULE_API_NO >= 20010901
+ PHP_ENCHANT_VERSION,
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_ENCHANT
+ZEND_GET_MODULE(enchant)
+#endif
+
+static void
+enumerate_providers_fn (const char * const name,
+ const char * const desc,
+ const char * const file,
+ void * ud) /* {{{ */
+{
+ zval *zdesc = (zval *) ud;
+ zval *tmp_array;
+
+ MAKE_STD_ZVAL(tmp_array);
+ array_init(tmp_array);
+
+ add_assoc_string(tmp_array, "name", (char *)name, 1);
+ add_assoc_string(tmp_array, "desc", (char *)desc, 1);
+ add_assoc_string(tmp_array, "file", (char *)file, 1);
+
+ if (Z_TYPE_P(zdesc)!=IS_ARRAY) {
+ array_init(zdesc);
+ }
+
+ add_next_index_zval(zdesc, tmp_array);
+}
+/* }}} */
+
+static void
+describe_dict_fn (const char * const lang,
+ const char * const name,
+ const char * const desc,
+ const char * const file,
+ void * ud) /* {{{ */
+{
+ zval *zdesc = (zval *) ud;
+ array_init(zdesc);
+ add_assoc_string(zdesc, "lang", (char *)lang, 1);
+ add_assoc_string(zdesc, "name", (char *)name, 1);
+ add_assoc_string(zdesc, "desc", (char *)desc, 1);
+ add_assoc_string(zdesc, "file", (char *)file, 1);
+}
+/* }}} */
+
+static void php_enchant_list_dicts_fn( const char * const lang_tag,
+ const char * const provider_name, const char * const provider_desc,
+ const char * const provider_file, void * ud) /* {{{ */
+{
+ zval *zdesc = (zval *) ud;
+ zval *tmp_array;
+
+ MAKE_STD_ZVAL(tmp_array);
+ array_init(tmp_array);
+ add_assoc_string(tmp_array, "lang_tag", (char *)lang_tag, 1);
+ add_assoc_string(tmp_array, "provider_name", (char *)provider_name, 1);
+ add_assoc_string(tmp_array, "provider_desc", (char *)provider_desc, 1);
+ add_assoc_string(tmp_array, "provider_file", (char *)provider_file, 1);
+
+ if (Z_TYPE_P(zdesc) != IS_ARRAY) {
+ array_init(zdesc);
+ }
+ add_next_index_zval(zdesc, tmp_array);
+
+}
+/* }}} */
+
+static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+{
+ if (rsrc->ptr) {
+ enchant_broker *broker = (enchant_broker *)rsrc->ptr;
+ if (broker) {
+ if (broker->pbroker) {
+ if (broker->dictcnt && broker->dict) {
+ if (broker->dict) {
+ int total;
+ total = broker->dictcnt-1;
+ do {
+ zend_list_delete(broker->dict[total]->rsrc_id);
+ efree(broker->dict[total]);
+ total--;
+ } while (total>=0);
+ }
+ efree(broker->dict);
+ broker->dict = NULL;
+ }
+ enchant_broker_free(broker->pbroker);
+ }
+ efree(broker);
+ }
+ }
+}
+/* }}} */
+
+static void php_enchant_dict_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+
+{
+ if (rsrc->ptr) {
+ enchant_dict *pdict = (enchant_dict *)rsrc->ptr;
+ if (pdict) {
+ if (pdict->pdict && pdict->pbroker) {
+ enchant_broker_free_dict(pdict->pbroker->pbroker, pdict->pdict);
+ if (pdict->id) {
+ pdict->pbroker->dict[pdict->id-1]->next = NULL;
+ }
+ zend_list_delete(pdict->pbroker->rsrc_id);
+ }
+
+ }
+ }
+}
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(enchant)
+{
+ le_enchant_broker = zend_register_list_destructors_ex(php_enchant_broker_free, NULL, "enchant_broker", module_number);
+ le_enchant_dict = zend_register_list_destructors_ex(php_enchant_dict_free, NULL, "enchant_dict", module_number);
+ REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_CS | CONST_PERSISTENT);
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(enchant)
+{
+ return SUCCESS;
+}
+/* }}} */
+
+static void __enumerate_providers_fn (const char * const name,
+ const char * const desc,
+ const char * const file,
+ void * ud) /* {{{ */
+{
+ php_info_print_table_row(3, name, desc, file);
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(enchant)
+{
+ EnchantBroker *pbroker;
+
+ pbroker = enchant_broker_init();
+ php_info_print_table_start();
+ php_info_print_table_header(2, "enchant support", "enabled");
+ php_info_print_table_row(2, "Version", PHP_ENCHANT_VERSION);
+#ifdef ENCHANT_VERSION_STRING
+ php_info_print_table_row(2, "Libenchant Version", ENCHANT_VERSION_STRING);
+#elif defined(HAVE_ENCHANT_BROKER_SET_PARAM)
+ php_info_print_table_row(2, "Libenchant Version", "1.5.0 or later");
+#endif
+ php_info_print_table_row(2, "Revision", "$Id: 3d50cb80a6388ef6552aa4e71d33a136792f4fc2 $");
+ php_info_print_table_end();
+
+ php_info_print_table_start();
+ enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
+ php_info_print_table_end();
+ enchant_broker_free(pbroker);
+}
+/* }}} */
+
+#define PHP_ENCHANT_GET_BROKER \
+ ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant_broker", le_enchant_broker); \
+ if (!pbroker || !pbroker->pbroker) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Resource broker invalid"); \
+ RETURN_FALSE; \
+ }
+
+#define PHP_ENCHANT_GET_DICT \
+ ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant_dict", le_enchant_dict); \
+ if (!pdict || !pdict->pdict) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Invalid dictionary resource."); \
+ RETURN_FALSE; \
+ }
+
+/* {{{ proto resource enchant_broker_init()
+ create a new broker object capable of requesting */
+PHP_FUNCTION(enchant_broker_init)
+{
+ enchant_broker *broker;
+ EnchantBroker *pbroker;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ pbroker = enchant_broker_init();
+
+ if (pbroker) {
+ broker = (enchant_broker *) emalloc(sizeof(enchant_broker));
+ broker->pbroker = pbroker;
+ broker->dict = NULL;
+ broker->dictcnt = 0;
+ broker->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, broker, le_enchant_broker);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto boolean enchant_broker_free(resource broker)
+ Destroys the broker object and its dictionnaries */
+PHP_FUNCTION(enchant_broker_free)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
+ RETURN_FALSE;
+ }
+ PHP_ENCHANT_GET_BROKER;
+
+ zend_list_delete(Z_RESVAL_P(broker));
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string enchant_broker_get_error(resource broker)
+ Returns the last error of the broker */
+PHP_FUNCTION(enchant_broker_get_error)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+ char *msg;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ msg = enchant_broker_get_error(pbroker->pbroker);
+ if (msg) {
+ RETURN_STRING((char *)msg, 1);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+#if HAVE_ENCHANT_BROKER_SET_PARAM
+/* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
+ Set the directory path for a given backend, works with ispell and myspell */
+PHP_FUNCTION(enchant_broker_set_dict_path)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+ long dict_type;
+ char *value;
+ int value_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &broker, &dict_type, &value, &value_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!value_len) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ switch (dict_type) {
+ case PHP_ENCHANT_MYSPELL:
+ PHP_ENCHANT_GET_BROKER;
+ enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value);
+ RETURN_TRUE;
+ break;
+
+ case PHP_ENCHANT_ISPELL:
+ PHP_ENCHANT_GET_BROKER;
+ enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value);
+ RETURN_TRUE;
+ break;
+
+ default:
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+
+/* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
+ Get the directory path for a given backend, works with ispell and myspell */
+PHP_FUNCTION(enchant_broker_get_dict_path)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+ long dict_type;
+ char *value;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &broker, &dict_type) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ switch (dict_type) {
+ case PHP_ENCHANT_MYSPELL:
+ PHP_ENCHANT_GET_BROKER;
+ value = enchant_broker_get_param(pbroker->pbroker, "enchant.myspell.dictionary.path");
+ break;
+
+ case PHP_ENCHANT_ISPELL:
+ PHP_ENCHANT_GET_BROKER;
+ value = enchant_broker_get_param(pbroker->pbroker, "enchant.ispell.dictionary.path");
+ break;
+
+ default:
+ RETURN_FALSE;
+ }
+
+ RETURN_STRING(value, 1);
+}
+/* }}} */
+#else
+/* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
+ Set the directory path for a given backend, works with ispell and myspell */
+PHP_FUNCTION(enchant_broker_set_dict_path)
+{
+ RETURN_FALSE;
+}
+/* }}} */
+
+
+/* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
+ Get the directory path for a given backend, works with ispell and myspell */
+PHP_FUNCTION(enchant_broker_get_dict_path)
+{
+ RETURN_FALSE;
+}
+/* }}} */
+#endif
+
+/* {{{ proto string enchant_broker_list_dicts(resource broker)
+ Lists the dictionaries available for the given broker */
+PHP_FUNCTION(enchant_broker_list_dicts)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ enchant_broker_list_dicts(pbroker->pbroker, php_enchant_list_dicts_fn, (void *)return_value);
+}
+/* }}} */
+
+/* {{{ proto resource enchant_broker_request_dict(resource broker, string tag)
+ create a new dictionary using tag, the non-empty language tag you wish to request
+ a dictionary for ("en_US", "de_DE", ...) */
+PHP_FUNCTION(enchant_broker_request_dict)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+ enchant_dict *dict;
+ EnchantDict *d;
+ char *tag;
+ int taglen;
+ int pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ if (taglen == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tag cannot be empty");
+ RETURN_FALSE;
+ }
+
+ d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
+ if (d) {
+ if (pbroker->dictcnt) {
+ pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
+ pos = pbroker->dictcnt++;
+ } else {
+ pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
+ pos = 0;
+ pbroker->dictcnt++;
+ }
+
+ dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
+ dict->id = pos;
+ dict->pbroker = pbroker;
+ dict->pdict = d;
+ dict->prev = pos ? pbroker->dict[pos-1] : NULL;
+ dict->next = NULL;
+ pbroker->dict[pos] = dict;
+
+ if (pos) {
+ pbroker->dict[pos-1]->next = dict;
+ }
+
+ dict->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict);
+ zend_list_addref(pbroker->rsrc_id);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto resource enchant_broker_request_pwl_dict(resource broker, string filename)
+ creates a dictionary using a PWL file. A PWL file is personal word file one word per line. It must exist before the call.*/
+PHP_FUNCTION(enchant_broker_request_pwl_dict)
+{
+ zval *broker;
+ enchant_broker *pbroker;
+ enchant_dict *dict;
+ EnchantDict *d;
+ char *pwl;
+ int pwllen;
+ int pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &broker, &pwl, &pwllen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+#if PHP_API_VERSION < 20100412
+ if ((PG(safe_mode) && (!php_checkuid(pwl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pwl TSRMLS_CC)) {
+#else
+ if (php_check_open_basedir(pwl TSRMLS_CC)) {
+#endif
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl);
+ if (d) {
+ if (pbroker->dictcnt) {
+ pos = pbroker->dictcnt++;
+ pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
+ } else {
+ pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
+ pos = 0;
+ pbroker->dictcnt++;
+ }
+ dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
+ dict->id = pos;
+ dict->pbroker = pbroker;
+ dict->pdict = d;
+ dict->prev = pos?pbroker->dict[pos-1]:NULL;
+ dict->next = NULL;
+ pbroker->dict[pos] = dict;
+ if (pos) {
+ pbroker->dict[pos-1]->next = dict;
+ }
+ dict->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto resource enchant_broker_free_dict(resource dict)
+ Free the dictionary resource */
+PHP_FUNCTION(enchant_broker_free_dict)
+{
+ zval *dict;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ zend_list_delete(Z_RESVAL_P(dict));
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool enchant_broker_dict_exists(resource broker, string tag)
+ Wether a dictionary exists or not. Using non-empty tag */
+PHP_FUNCTION(enchant_broker_dict_exists)
+{
+ zval *broker;
+ char *tag;
+ int taglen;
+ enchant_broker * pbroker;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
+}
+/* }}} */
+
+/* {{{ proto bool enchant_broker_set_ordering(resource broker, string tag, string ordering)
+ Declares a preference of dictionaries to use for the language
+ described/referred to by 'tag'. The ordering is a comma delimited
+ list of provider names. As a special exception, the "*" tag can
+ be used as a language tag to declare a default ordering for any
+ language that does not explictly declare an ordering. */
+
+PHP_FUNCTION(enchant_broker_set_ordering)
+{
+ zval *broker;
+ char *pordering;
+ int porderinglen;
+ char *ptag;
+ int ptaglen;
+ enchant_broker * pbroker;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &broker, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array enchant_broker_describe(resource broker)
+ Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
+PHP_FUNCTION(enchant_broker_describe)
+{
+ EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
+ zval *broker;
+ enchant_broker * pbroker;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_BROKER;
+
+ enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
+}
+/* }}} */
+
+/* {{{ proto bool enchant_dict_quick_check(resource dict, string word [, array &suggestions])
+ If the word is correctly spelled return true, otherwise return false, if suggestions variable
+ is provided, fill it with spelling alternatives. */
+PHP_FUNCTION(enchant_dict_quick_check)
+{
+ zval *dict, *sugg = NULL;
+ char *word;
+ int wordlen;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (sugg) {
+ zval_dtor(sugg);
+ array_init(sugg);
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
+ int n_sugg;
+ size_t n_sugg_st;
+ char **suggs;
+
+ if (!sugg && ZEND_NUM_ARGS() == 2) {
+ RETURN_FALSE;
+ }
+
+ suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
+ memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
+ if (suggs && n_sugg) {
+ int i;
+ for (i = 0; i < n_sugg; i++) {
+ add_next_index_string(sugg, suggs[i], 1);
+ }
+ enchant_dict_free_suggestions(pdict->pdict, suggs);
+ }
+
+
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool enchant_dict_check(resource dict, string word)
+ If the word is correctly spelled return true, otherwise return false */
+PHP_FUNCTION(enchant_dict_check)
+{
+ zval *dict;
+ char *word;
+ int wordlen;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
+}
+/* }}} */
+
+/* {{{ proto array enchant_dict_suggest(resource dict, string word)
+ Will return a list of values if any of those pre-conditions are not met.*/
+PHP_FUNCTION(enchant_dict_suggest)
+{
+ zval *dict;
+ char *word;
+ int wordlen;
+ char **suggs;
+ enchant_dict *pdict;
+ int n_sugg;
+ size_t n_sugg_st;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
+ memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
+ if (suggs && n_sugg) {
+ int i;
+
+ array_init(return_value);
+ for (i = 0; i < n_sugg; i++) {
+ add_next_index_string(return_value, suggs[i], 1);
+ }
+
+ enchant_dict_free_suggestions(pdict->pdict, suggs);
+ }
+}
+/* }}} */
+
+/* {{{ proto void enchant_dict_add_to_personal(resource dict, string word)
+ add 'word' to personal word list */
+PHP_FUNCTION(enchant_dict_add_to_personal)
+{
+ zval *dict;
+ char *word;
+ int wordlen;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ enchant_dict_add_to_personal(pdict->pdict, word, wordlen);
+}
+/* }}} */
+
+/* {{{ proto void enchant_dict_add_to_session(resource dict, string word)
+ add 'word' to this spell-checking session */
+PHP_FUNCTION(enchant_dict_add_to_session)
+{
+ zval *dict;
+ char *word;
+ int wordlen;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ enchant_dict_add_to_session(pdict->pdict, word, wordlen);
+}
+/* }}} */
+
+/* {{{ proto bool enchant_dict_is_in_session(resource dict, string word)
+ whether or not 'word' exists in this spelling-session */
+PHP_FUNCTION(enchant_dict_is_in_session)
+{
+ zval *dict;
+ char *word;
+ int wordlen;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen));
+}
+/* }}} */
+
+/* {{{ proto void enchant_dict_store_replacement(resource dict, string mis, string cor)
+ add a correction for 'mis' using 'cor'.
+ Notes that you replaced @mis with @cor, so it's possibly more likely
+ that future occurrences of @mis will be replaced with @cor. So it might
+ bump @cor up in the suggestion list.*/
+PHP_FUNCTION(enchant_dict_store_replacement)
+{
+ zval *dict;
+ char *mis, *cor;
+ int mislen, corlen;
+
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
+}
+/* }}} */
+
+/* {{{ proto string enchant_dict_get_error(resource dict)
+ Returns the last error of the current spelling-session */
+PHP_FUNCTION(enchant_dict_get_error)
+{
+ zval *dict;
+ enchant_dict *pdict;
+ char *msg;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ msg = enchant_dict_get_error(pdict->pdict);
+ if (msg) {
+ RETURN_STRING((char *)msg, 1);
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto array enchant_dict_describe(resource dict)
+ Describes an individual dictionary 'dict' */
+PHP_FUNCTION(enchant_dict_describe)
+{
+ zval *dict;
+ enchant_dict *pdict;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ PHP_ENCHANT_GET_DICT;
+
+ enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/enchant/package.xml b/ext/enchant/package.xml
new file mode 100755
index 0000000..1012839
--- /dev/null
+++ b/ext/enchant/package.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.4.8" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+ <name>enchant</name>
+ <channel>pecl.php.net</channel>
+ <summary>libenchant binder, support near all spelling tools</summary>
+ <description>Enchant is a binder for libenchant. Libenchant provides a common
+API for many spell libraries:
+- aspell/pspell (intended to replace ispell)
+- hspell (hebrew)
+- ispell
+- myspell/hunspell (OpenOffice project, mozilla)
+- uspell (primarily Yiddish, Hebrew, and Eastern European languages)
+A plugin system allows to add custom spell support.
+see www.abisource.com/enchant/
+ </description>
+ <lead>
+ <name>Pierre-Alain Joye</name>
+ <user>pajoye</user>
+ <email>paj@pearfr.org</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Ilia Alshanetsky</name>
+ <user>iliaa</user>
+ <email>ilia@php.net</email>
+ <active>yes</active>
+ </lead>
+ <date>2008-04-16</date>
+ <version>
+ <release>1.0.2</release>
+ <api>1.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- #13181, Leaving a context frees the dictionnary resources
+- Fix protos descriptions in the sources
+</notes>
+ <contents>
+ <dir name="/">
+ <dir name="docs">
+ <dir name="examples">
+ <file name="example1.php" role="doc"/>
+ </dir>
+ <!-- //docs/examples -->
+ </dir>
+ <!-- //docs -->
+ <file name="config.m4" role="src"/>
+ <file name="config.w32" role="src"/>
+ <file name="CREDITS" role="doc"/>
+ <file name="enchant.c" role="src"/>
+ <file name="php_enchant.h" role="src"/>
+ <dir name="tests">
+ <file name="broker_describe.phpt" role="test"/>
+ <file name="broker_free.phpt" role="test"/>
+ <file name="broker_init.phpt" role="test"/>
+ <file name="broker_request_dict.phpt" role="test"/>
+ <file name="hindi_correct.txt" role="test"/>
+ <file name="hindi_incorrect.txt" role="test"/>
+ <file name="bug13181.phpt" role="test"/>
+ </dir>
+ </dir>
+ <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0b1</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <providesextension>enchant</providesextension>
+ <extsrcrelease>
+ <configureoption default="shared" name="with-enchant" prompt="libenchant prefix?"/>
+ </extsrcrelease>
+ <changelog>
+ <release>
+ <date>2006-03-21</date>
+ <version>
+ <release>1.0.1</release>
+ <api>1.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- add enchant_broker_list_dicts to get a list of available dictionaries
+- fix compilation warnings
+- add examples
+- add tests</notes>
+ </release>
+ <release>
+ <date>2004-08-11</date>
+ <version>
+ <release>1.0</release>
+ <api>1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- Fixed leak inside MINFO function.
+- Fixed crash inside enchant_dict_suggest() when there are no suggestions.
+- Added missing safe_mode/open_basedir check inside enchant_broker_request_pwl_dict().
+- Fixed various function prototypes.
+- Fixed possible leak in suggestions result.
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.2.1</release>
+ <api>0.2.1</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2004-03-11</date>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- Fix possible leak in suggestions result
+- Move to beta status
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.2.0</release>
+ <api>0.2.0</api>
+ </version>
+ <stability>
+ <release>alpha</release>
+ <api>alpha</api>
+ </stability>
+ <date>2006-03-21</date>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- Add Ilia Alshanetsky as maintainer
+- Cleanup sources codes (ilia)
+- Add enchant_dict_quick_check (ilia)
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.1</release>
+ <api>0.1</api>
+ </version>
+ <stability>
+ <release>alpha</release>
+ <api>alpha</api>
+ </stability>
+ <date>2003-03-08</date>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>Initial release
+ </notes>
+ </release>
+ </changelog>
+</package>
diff --git a/ext/enchant/php_enchant.h b/ext/enchant/php_enchant.h
new file mode 100644
index 0000000..604c479
--- /dev/null
+++ b/ext/enchant/php_enchant.h
@@ -0,0 +1,82 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Pierre-Alain Joye <paj@pearfr.org> |
+ +----------------------------------------------------------------------+
+
+ $Id$
+*/
+
+#ifndef PHP_ENCHANT_H
+#define PHP_ENCHANT_H
+
+extern zend_module_entry enchant_module_entry;
+#define phpext_enchant_ptr &enchant_module_entry
+
+#define PHP_ENCHANT_VERSION "1.1.0"
+
+#ifdef PHP_WIN32
+#define PHP_ENCHANT_API __declspec(dllexport)
+#else
+#define PHP_ENCHANT_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(enchant);
+PHP_MSHUTDOWN_FUNCTION(enchant);
+PHP_MINFO_FUNCTION(enchant);
+
+PHP_FUNCTION(enchant_broker_init);
+PHP_FUNCTION(enchant_broker_free);
+PHP_FUNCTION(enchant_broker_get_error);
+PHP_FUNCTION(enchant_broker_set_dict_path);
+PHP_FUNCTION(enchant_broker_get_dict_path);
+PHP_FUNCTION(enchant_broker_list_dicts);
+PHP_FUNCTION(enchant_broker_request_dict);
+PHP_FUNCTION(enchant_broker_request_pwl_dict);
+PHP_FUNCTION(enchant_broker_free_dict);
+PHP_FUNCTION(enchant_broker_dict_exists);
+PHP_FUNCTION(enchant_broker_set_ordering);
+PHP_FUNCTION(enchant_broker_describe);
+
+PHP_FUNCTION(enchant_dict_check);
+PHP_FUNCTION(enchant_dict_suggest);
+PHP_FUNCTION(enchant_dict_add_to_personal);
+PHP_FUNCTION(enchant_dict_add_to_session);
+PHP_FUNCTION(enchant_dict_is_in_session);
+PHP_FUNCTION(enchant_dict_store_replacement);
+PHP_FUNCTION(enchant_dict_get_error);
+PHP_FUNCTION(enchant_dict_describe);
+PHP_FUNCTION(enchant_dict_quick_check);
+
+#ifdef ZTS
+#define ENCHANT_G(v) TSRMG(enchant_globals_id, zend_enchant_globals *, v)
+#else
+#define ENCHANT_G(v) (enchant_globals.v)
+#endif
+
+#endif /* PHP_ENCHANT_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
+
diff --git a/ext/enchant/tests/broker_describe.phpt b/ext/enchant/tests/broker_describe.phpt
new file mode 100644
index 0000000..4c03f6f
--- /dev/null
+++ b/ext/enchant/tests/broker_describe.phpt
@@ -0,0 +1,28 @@
+--TEST--
+enchant_broker_describe() function
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+
+ ?>
+--FILE--
+<?php
+$broker = enchant_broker_init();
+
+if(!$broker) exit("failed, broker_init failure\n");
+
+$provides = enchant_broker_describe($broker);
+
+if (is_array($provides)) {
+ foreach ($provides as $backend) {
+ if (!(isset($backend['name']) && isset($backend['desc']) && isset($backend['file']))) {
+ exit("failed\n");
+ }
+ }
+ exit("OK\n");
+} else {
+ echo "failed";
+}
+?>
+--EXPECTF--
+OK
diff --git a/ext/enchant/tests/broker_free.phpt b/ext/enchant/tests/broker_free.phpt
new file mode 100644
index 0000000..d00c22a
--- /dev/null
+++ b/ext/enchant/tests/broker_free.phpt
@@ -0,0 +1,21 @@
+--TEST--
+enchant_broker_free() function
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+
+ ?>
+--FILE--
+<?php
+$broker = enchant_broker_init();
+if (is_resource($broker)) {
+ echo "OK\n";
+ enchant_broker_free($broker);
+} else {
+ exit("init failed\n");
+}
+echo "OK\n";
+?>
+--EXPECT--
+OK
+OK
diff --git a/ext/enchant/tests/broker_init.phpt b/ext/enchant/tests/broker_init.phpt
new file mode 100644
index 0000000..359a653
--- /dev/null
+++ b/ext/enchant/tests/broker_init.phpt
@@ -0,0 +1,15 @@
+--TEST--
+enchant_broker_init() function
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+
+ ?>
+--FILE--
+<?php
+$broker = enchant_broker_init();
+echo is_resource($broker) ? "OK" : "Failure";
+echo "\n";
+?>
+--EXPECT--
+OK
diff --git a/ext/enchant/tests/broker_request_dict.phpt b/ext/enchant/tests/broker_request_dict.phpt
new file mode 100644
index 0000000..5744da6
--- /dev/null
+++ b/ext/enchant/tests/broker_request_dict.phpt
@@ -0,0 +1,31 @@
+--TEST--
+enchant_broker_request_dict() function
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+?>
+--FILE--
+<?php
+$broker = enchant_broker_init();
+if (!is_resource($broker)) {
+ exit("init failed\n");
+}
+
+$dicts = enchant_broker_list_dicts($broker);
+if (is_array($dicts)) {
+ if (count($dicts)) {
+ $dict = enchant_broker_request_dict($broker, $dicts[0]['lang_tag']);
+ if (is_resource($dict)) {
+ echo "OK\n";
+ } else {
+ echo "fail to request " . $dicts[0]['lang_tag'];
+ }
+ }
+} else {
+ exit("list dicts failed\n");
+}
+echo "OK\n";
+?>
+--EXPECT--
+OK
+OK
diff --git a/ext/enchant/tests/bug13181.phpt b/ext/enchant/tests/bug13181.phpt
new file mode 100644
index 0000000..38aec63
--- /dev/null
+++ b/ext/enchant/tests/bug13181.phpt
@@ -0,0 +1,43 @@
+--TEST--
+bug #13181, leaving a context frees the broker resources
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+
+ ?>
+--FILE--
+<?php
+function get_dictionnary() {
+ $rBroker = enchant_broker_init();
+ $t = enchant_broker_request_dict($rBroker, 'en');
+ var_dump($t);
+ return $t;
+}
+$rDict = get_dictionnary();
+var_dump($rDict);
+enchant_dict_suggest($rDict, "soong");
+
+function get_broker() {
+ $t = enchant_broker_init();
+ var_dump($t);
+ return $t;
+}
+
+$rbroker = get_broker();
+var_dump($rbroker);
+
+function get_dict($broker) {
+ $t = enchant_broker_request_dict($broker, 'en');
+ var_dump($t);
+ return $t;
+}
+$rDict = get_dict($rbroker);
+var_dump($rDict);
+?>
+--EXPECTF--
+resource(%d) of type (enchant_dict)
+resource(%d) of type (enchant_dict)
+resource(%d) of type (enchant_broker)
+resource(%d) of type (enchant_broker)
+resource(%d) of type (enchant_dict)
+resource(%d) of type (enchant_dict)
diff --git a/ext/enchant/tests/dict_quick_check.phpt b/ext/enchant/tests/dict_quick_check.phpt
new file mode 100644
index 0000000..3412de1
--- /dev/null
+++ b/ext/enchant/tests/dict_quick_check.phpt
@@ -0,0 +1,26 @@
+--TEST--
+enchant_dict_quick_check() basic test
+--SKIPIF--
+<?php
+if(!extension_loaded('enchant')) die('skip, enchant not loader');
+
+$tag = 'en_US';
+$r = enchant_broker_init();
+if (!enchant_broker_dict_exists($r, $tag))
+ die('skip, no dictionary for ' . $tag . ' tag');
+?>
+--FILE--
+<?php
+
+$tag = 'en_US';
+$r = enchant_broker_init();
+
+$d = enchant_broker_request_dict($r, $tag);
+enchant_dict_quick_check($d, 'soong', $suggs);
+
+echo "Elements: " . count($suggs) . "\n";
+echo "Done\n";
+?>
+--EXPECTF--
+Elements: %d
+Done
diff --git a/ext/enchant/tests/hindi_correct.txt b/ext/enchant/tests/hindi_correct.txt
new file mode 100644
index 0000000..cced6b8
--- /dev/null
+++ b/ext/enchant/tests/hindi_correct.txt
@@ -0,0 +1 @@
+इस पृष्ठ में एक लिंक बनाने के लिये इस प्रतीक को खीचें व छोड़ें
diff --git a/ext/enchant/tests/hindi_incorrect.txt b/ext/enchant/tests/hindi_incorrect.txt
new file mode 100644
index 0000000..1f7353c
--- /dev/null
+++ b/ext/enchant/tests/hindi_incorrect.txt
@@ -0,0 +1 @@
+इस पृष्ठ में एक लिंक बनाने के लिये इस प्रतीक को खच व छड