]> granicus.if.org Git - php/commitdiff
- Initial commit
authorPierre Joye <pajoye@php.net>
Mon, 8 Mar 2004 20:12:13 +0000 (20:12 +0000)
committerPierre Joye <pajoye@php.net>
Mon, 8 Mar 2004 20:12:13 +0000 (20:12 +0000)
ext/enchant/config.m4 [new file with mode: 0755]
ext/enchant/config.w32 [new file with mode: 0644]
ext/enchant/docs/examples/example1.php [new file with mode: 0644]
ext/enchant/enchant.c [new file with mode: 0755]
ext/enchant/package.xml [new file with mode: 0755]
ext/enchant/php_enchant.h [new file with mode: 0644]

diff --git a/ext/enchant/config.m4 b/ext/enchant/config.m4
new file mode 100755 (executable)
index 0000000..b59cd8f
--- /dev/null
@@ -0,0 +1,36 @@
+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)
+fi
diff --git a/ext/enchant/config.w32 b/ext/enchant/config.w32
new file mode 100644 (file)
index 0000000..5be9572
--- /dev/null
@@ -0,0 +1,9 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_ENABLE("enchant", "Enchant Support", "no");
+
+if (PHP_ENCHANT == "yes") {
+       EXTENSION("enchant", "enchant.c");
+       AC_DEFINE('HAVE_ENCHANT', 1, 'Have Enchant support', false);
+}
diff --git a/ext/enchant/docs/examples/example1.php b/ext/enchant/docs/examples/example1.php
new file mode 100644 (file)
index 0000000..9d503f7
--- /dev/null
@@ -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 100755 (executable)
index 0000000..648e7cb
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 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$
+*/
+
+#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;
+       zval                    *rsrc_id;
+} _enchant_broker;
+
+typedef struct _dict_struct {
+       unsigned int    id;
+       EnchantDict             *pdict;
+       enchant_broker  *pbroker;
+       zval                    *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)*/
+
+/* {{{ enchant_functions[]
+ *
+ * Every user visible function must have an entry in enchant_functions[].
+ */
+function_entry enchant_functions[] = {
+       PHP_FE(enchant_broker_init, NULL)
+       PHP_FE(enchant_broker_free, NULL)
+       PHP_FE(enchant_broker_get_error, NULL)
+       PHP_FE(enchant_broker_request_dict,     NULL)
+       PHP_FE(enchant_broker_request_pwl_dict, NULL)
+       PHP_FE(enchant_broker_free_dict, NULL)
+       PHP_FE(enchant_broker_dict_exists, NULL)
+       PHP_FE(enchant_broker_set_ordering, NULL)
+       PHP_FE(enchant_broker_describe, NULL)
+       PHP_FE(enchant_dict_check, NULL)
+       PHP_FE(enchant_dict_suggest, NULL)
+       PHP_FE(enchant_dict_add_to_personal, NULL)
+       PHP_FE(enchant_dict_add_to_session, NULL)
+       PHP_FE(enchant_dict_is_in_session, NULL)
+       PHP_FE(enchant_dict_store_replacement, NULL)
+       PHP_FE(enchant_dict_get_error, NULL)
+       PHP_FE(enchant_dict_describe, NULL)
+
+       {NULL, NULL, NULL}      /* Must be the last line in enchant_functions[] */
+};
+/* }}} */
+
+/* {{{ 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
+       "0.1", /* Replace with version number for your extension */
+#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;
+       zval *tmp_array;
+
+       MAKE_STD_ZVAL(tmp_array);
+       array_init(tmp_array);
+
+       add_assoc_string(tmp_array, "lang", (char *)lang, 1);
+       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 php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+       int total, tofree;
+       if (rsrc->ptr) {
+               enchant_broker *broker = (enchant_broker *)rsrc->ptr;
+               if (broker) {
+                       if (broker->pbroker) {
+                               if (broker->dictcnt && broker->dict) {
+                                       if (broker->dict) {
+                                               tofree = total = broker->dictcnt-1;
+                                               do {
+                                                       printf("broker free, dict id: %i\n", broker->dict[total]->id);
+                                                       zend_list_delete(Z_RESVAL_P(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)
+{
+       int prev;
+
+       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);
+                       }
+                       prev = -pdict->pbroker->dictcnt;
+                       printf("id:%i\n",pdict->id);
+                       if (pdict->id) {
+                               pdict->pbroker->dict[pdict->id-1]->next = NULL;
+                       }
+                       //efree(pdict);
+               }
+       }
+}
+
+/* {{{ 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);
+
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(enchant)
+{
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+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", "@version@");
+       php_info_print_table_row(2, "Revision", "$Revision$");
+       php_info_print_table_row(1, "Provides");
+       enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
+       php_info_print_table_end();
+}
+/* }}} */
+
+/* {{{ proto resource enchant_new([int weekstart])
+   create a new broker object capable of requesting */
+PHP_FUNCTION(enchant_broker_init)
+{
+       enchant_broker *broker;
+       EnchantBroker *pbroker;
+
+       if ( ZEND_NUM_ARGS() ) {
+               ZEND_WRONG_PARAM_COUNT();
+
+       }
+
+       pbroker = enchant_broker_init();
+
+       if (pbroker) {
+               broker = (enchant_broker *) safe_emalloc(sizeof(enchant_broker), 1, 0);
+               broker->pbroker = pbroker;
+               broker->dict = NULL;
+               broker->dictcnt = 0;
+               ZEND_REGISTER_RESOURCE(return_value, broker, le_enchant_broker);
+               broker->rsrc_id = return_value;
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto boolean enchant_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;
+       }
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant_broker", le_enchant_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;
+       char *msg=NULL;
+       enchant_broker *pbroker;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant broker", le_enchant_broker);
+
+       if (pbroker) {
+               if (pbroker->pbroker) {
+                       msg = enchant_broker_get_error(pbroker->pbroker);
+               }
+       }
+       if (msg) {
+               RETURN_STRING((char *)msg, 1);
+       }
+}
+/* }}} */
+
+/* {{{ proto resource enchant_broker_request_dict(resource broker, string tag)
+       create a new dict 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;
+       }
+
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant broker", le_enchant_broker);
+       if (pbroker) {
+               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 **)safe_emalloc(sizeof(enchant_dict *), 1, 0);
+                               pos = 0;
+                               pbroker->dictcnt++;
+                       }
+                       printf("new id: %i\n", pos);
+                       dict = pbroker->dict[pos] = (enchant_dict *)safe_emalloc(sizeof(enchant_dict), 1, 0);
+                       dict->id = pos;
+                       dict->pbroker = pbroker;
+                       dict->pdict = d;
+                       dict->rsrc_id = return_value;
+                       dict->prev = pos?pbroker->dict[pos-1]:NULL;
+                       dict->next = NULL;
+                       pbroker->dict[pos] = dict;
+                       if (pos) {
+                               pbroker->dict[pos-1]->next = dict;
+                       }
+                       ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict);
+               } else {
+                       RETURN_FALSE;
+               }
+       }
+}
+/* }}} */
+
+/* {{{ proto resource enchant_broker_request_pwl_dict(resource dict, string tag)
+   creates a dictionnary using a PWL file. A PWL file is personal word file one word per line.
+   It must exists before the call.*/
+PHP_FUNCTION(enchant_broker_request_pwl_dict)
+{
+       zval *broker;
+       enchant_broker *pbroker;
+       enchant_dict *dict;
+       EnchantDict *d;
+       char *pwl;
+       long pwllen;
+       int pos;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &pwl, &pwllen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant broker", le_enchant_broker);
+       if (pbroker) {
+               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 **)safe_emalloc(sizeof(enchant_dict *), 1, 0);
+                               pos = 0;
+                               pbroker->dictcnt++;
+                       }
+                       dict = pbroker->dict[pos] = (enchant_dict *)safe_emalloc(sizeof(enchant_dict), 1, 0);
+                       dict->id = pos;
+                       dict->pbroker = pbroker;
+                       dict->pdict = d;
+                       dict->rsrc_id = return_value;
+                       dict->prev = pos?pbroker->dict[pos-1]:NULL;
+                       dict->next = NULL;
+                       pbroker->dict[pos] = dict;
+                       if (pos) {
+                               pbroker->dict[pos-1]->next = dict;
+                       }
+                       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;
+       }
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+       zend_list_delete(Z_RESVAL_P(dict));
+}
+/* }}} */
+
+/* {{{ proto bool enchant_new_dmy(resource broker, string tag)
+   Wether a dictionary exists or not. Using non-empty tag */
+PHP_FUNCTION(enchant_broker_dict_exists)
+{
+       zval *broker;
+       char *tag;
+       long taglen = 0;
+       enchant_broker * pbroker;
+       int exists = 0;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant_broker", le_enchant_broker);
+       if (pbroker && taglen) {
+               if (pbroker->pbroker) {
+                       exists = enchant_broker_dict_exists(pbroker->pbroker, tag);
+                       RETURN_TRUE;
+               } else {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ressource broker invalid");
+                       RETURN_FALSE;
+               }
+       }
+       RETURN_FALSE;
+}
+/* }}} */
+
+
+/* {{{ proto resource 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;
+       }
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant broker", le_enchant_broker);
+       if (pbroker->pbroker) {
+               enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
+       } else {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ressource broker invalid");
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ 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;
+       }
+       ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant broker", le_enchant_broker);
+       if (pbroker->pbroker) {
+               enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
+       } else {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ressource broker invalid");
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto long enchant_dict_check(resource broker)
+    0 if the word is correctly spelled, positive if not, negative if error */
+PHP_FUNCTION(enchant_dict_check)
+{
+       zval *dict;
+       char *word;
+       enchant_dict *pdict;
+       int results;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &results) == FAILURE) {
+               RETURN_FALSE;
+       }
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+       results = enchant_dict_check( pdict->pdict, word, strlen(word));
+       RETURN_LONG((long)results);
+}
+/* }}} */
+
+/* {{{ proto array enchant_dict_suggest(resource broker, string word)
+    Will return an list of values if any of those pre-conditions are not met.*/
+PHP_FUNCTION(enchant_dict_suggest)
+{
+       zval *dict;
+       char *word;
+       long wordlen;
+       char **suggs;
+       enchant_dict *pdict;
+       int i;
+       int n_sugg;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+               RETURN_FALSE;
+       }
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+       if (pdict) {
+               if (pdict->pdict) {
+                       suggs = enchant_dict_suggest(pdict->pdict, word, strlen(word), &n_sugg);
+                       if (suggs && n_sugg) {
+                               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 resource enchant_dict_add_to_personal(resource broker)
+    A list of UTF-8 encoded suggestions, or false */
+PHP_FUNCTION(enchant_dict_add_to_personal)
+{
+       zval *dict;
+       char *word;
+       long wordlen;
+       enchant_dict *pdict;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+
+       if (pdict) {
+               if (pdict->pdict) {
+                       enchant_dict_add_to_personal(pdict->pdict, word, wordlen);
+               }
+       }
+}
+/* }}} */
+
+/* {{{ proto bool enchant_dict_add_to_session(resource broker, string word)
+   add 'word' to this spell-checking session */
+PHP_FUNCTION(enchant_dict_add_to_session)
+{
+       zval *dict;
+       char *word;
+       long wordlen;
+       enchant_dict *pdict;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+
+       if (pdict) {
+               if (pdict->pdict) {
+                       enchant_dict_add_to_session(pdict->pdict, word, wordlen);
+               }
+       }
+}
+/* }}} */
+
+/* {{{ proto bool enchant_dict_is_in_session(resource broker)
+   whether or not 'word' exists in this spelling-session */
+PHP_FUNCTION(enchant_dict_is_in_session)
+{
+       zval *dict;
+       char *word;
+       long wordlen;
+       long result=0;
+       enchant_dict *pdict;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+
+       if (pdict) {
+               if (pdict->pdict) {
+                       result = (long)enchant_dict_is_in_session(pdict->pdict, word, wordlen);
+               }
+       }
+       RETURN_BOOL(result);
+}
+/* }}} */
+
+/* {{{ proto resource enchant_dict_store_replacement(resource broker, 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;
+       long mislen;
+       char *cor;
+       long corlen;
+
+       enchant_dict *pdict;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+
+       if (pdict) {
+               if (pdict->pdict) {
+                       enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
+               }
+       }
+}
+/* }}} */
+
+/* {{{ proto resource enchant_dict_get_error(resource dict)
+   Returns the last error of the current spelling-session */
+PHP_FUNCTION(enchant_dict_get_error)
+{
+       zval *dict;
+       char *msg=NULL;
+       enchant_dict *pdict;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       ZEND_FETCH_RESOURCE(pdict, enchant_broker *, &dict, -1, "enchant broker", le_enchant_broker);
+
+       if (pdict) {
+               if (pdict->pdict) {
+                       msg = enchant_dict_get_error(pdict->pdict);
+               }
+       }
+       if (msg) {
+               RETURN_STRING((char *)msg, 1);
+       }
+}
+/* }}} */
+
+/* {{{ proto resource 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;
+       }
+       ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict);
+       if (pdict) {
+               if (pdict->pdict) {
+                       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 (executable)
index 0000000..f075f3f
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE package SYSTEM "../pear/package.dtd">
+<package>
+ <name>enchant</name>
+ <summary>Date and Time Library</summary>
+ <maintainers>
+  <maintainer>
+   <user>pajoye</user>
+   <name>Pierre-Alain Joye</name>
+   <email>paj@pearfr.org</email>
+   <role>lead</role>
+  </maintainer>
+ </maintainers>
+ <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 (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>
+ <license>PHP</license>
+ <release>
+  <state>alpha</state>
+  <version>0.1</version>
+  <date>2004-03-08</date>
+  <notes>Initial release</notes>
+  <filelist>
+   <file role="src" name="config.m4"/>
+   <file role="src" name="config.w32"/>
+   <file role="src" name="enchant.c"/>
+   <file role="src" name="php_enchant.h"/>
+   <dir name="docs" role="doc">
+     <dir name="examples">
+       <file name="example1.php"/>
+     </dir>
+   </dir>
+  </filelist>
+  <configureoptions>
+   <configureoption name="with-enchant" default="shared" prompt="libenchant prefix?"/>
+  </configureoptions>
+  <deps>
+   <dep type="php" rel="ge" version="5" />
+  </deps>
+ </release>
+</package>
+<!--
+vim:et:ts=1:sw=1
+-->
diff --git a/ext/enchant/php_enchant.h b/ext/enchant/php_enchant.h
new file mode 100644 (file)
index 0000000..54ae791
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 4                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2003 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
+
+#ifdef PHP_WIN32
+#define PHP_ENCHANT_API __declspec(dllexport)
+#else
+#define PHP_ENCHANT_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static void php_enchant_dict_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+
+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_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);
+
+#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:
+ */
+