1 #include "license.hunspell"
\r
2 #include "license.myspell"
\r
4 #ifndef MOZILLA_CLIENT
\r
14 #include "hunspell.hxx"
\r
15 #include "hunspell.h"
\r
17 #ifndef MOZILLA_CLIENT
\r
19 using namespace std;
\r
23 Hunspell::Hunspell(const char * affpath, const char * dpath)
\r
28 complexprefixes = 0;
\r
30 /* first set up the hash manager */
\r
31 pHMgr = new HashMgr(dpath, affpath);
\r
33 /* next set up the affix manager */
\r
34 /* it needs access to the hash manager lookup methods */
\r
35 pAMgr = new AffixMgr(affpath,pHMgr);
\r
37 /* get the preferred try string and the dictionary */
\r
38 /* encoding from the Affix Manager for that dictionary */
\r
39 char * try_string = pAMgr->get_try_string();
\r
40 encoding = pAMgr->get_encoding();
\r
41 csconv = get_current_cs(encoding);
\r
42 langnum = pAMgr->get_langnum();
\r
43 utf8 = pAMgr->get_utf8();
\r
44 complexprefixes = pAMgr->get_complexprefixes();
\r
45 wordbreak = pAMgr->get_breaktable();
\r
47 /* and finally set up the suggestion manager */
\r
48 pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
\r
49 if (try_string) free(try_string);
\r
53 Hunspell::~Hunspell()
\r
55 if (pSMgr) delete pSMgr;
\r
56 if (pAMgr) delete pAMgr;
\r
57 if (pHMgr) delete pHMgr;
\r
62 if (encoding) free(encoding);
\r
67 // make a copy of src at destination while removing all leading
\r
68 // blanks and removing any trailing periods after recording
\r
69 // their presence with the abbreviation flag
\r
70 // also since already going through character by character,
\r
71 // set the capitalization type
\r
72 // return the length of the "cleaned" (and UTF-8 encoded) word
\r
74 int Hunspell::cleanword2(char * dest, const char * src,
\r
75 w_char * dest_utf, int * nc, int * pcaptype, int * pabbrev)
\r
77 unsigned char * p = (unsigned char *) dest;
\r
78 const unsigned char * q = (const unsigned char * ) src;
\r
81 // first skip over any leading blanks
\r
82 while ((*q != '\0') && (*q == ' ')) q++;
\r
84 // now strip off any trailing periods (recording their presence)
\r
86 int nl = strlen((const char *)q);
\r
87 while ((nl > 0) && (*(q+nl-1)=='.')) {
\r
92 // if no characters are left it can't be capitalized
\r
99 // now determine the capitalization type of the first nl letters
\r
107 if (csconv[(*q)].ccase) ncap++;
\r
108 if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++;
\r
112 // remember to terminate the destination string
\r
115 firstcap = csconv[(unsigned char)(*dest)].ccase;
\r
118 unsigned short idx;
\r
119 *nc = u8_u16(dest_utf, MAXWORDLEN, (const char *) q);
\r
120 // don't check too long words
\r
121 if (*nc >= MAXWORDLEN) return 0;
\r
122 if (*nc == -1) { // big Unicode character (non BMP area)
\r
124 strcpy((char *) p, (char *) q);
\r
125 return strlen(dest);
\r
128 for (int i = 0; i < *nc; i++) {
\r
129 idx = (dest_utf[i].h << 8) + dest_utf[i].l;
\r
130 if (idx != unicodetolower(idx, langnum)) ncap++;
\r
131 if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++;
\r
133 u16_u8(dest, MAXWORDUTF8LEN, dest_utf, *nc);
\r
135 idx = (dest_utf[0].h << 8) + dest_utf[0].l;
\r
136 firstcap = (idx != unicodetolower(idx, langnum));
\r
140 // now finally set the captype
\r
143 } else if ((ncap == 1) && firstcap) {
\r
144 *pcaptype = INITCAP;
\r
145 } else if ((ncap == *nc) || ((ncap + nneutral) == *nc)) {
\r
146 *pcaptype = ALLCAP;
\r
147 } else if ((ncap > 1) && firstcap) {
\r
148 *pcaptype = HUHINITCAP;
\r
150 *pcaptype = HUHCAP;
\r
152 return strlen(dest);
\r
155 int Hunspell::cleanword(char * dest, const char * src,
\r
156 int * pcaptype, int * pabbrev)
\r
158 unsigned char * p = (unsigned char *) dest;
\r
159 const unsigned char * q = (const unsigned char * ) src;
\r
162 // first skip over any leading blanks
\r
163 while ((*q != '\0') && (*q == ' ')) q++;
\r
165 // now strip off any trailing periods (recording their presence)
\r
167 int nl = strlen((const char *)q);
\r
168 while ((nl > 0) && (*(q+nl-1)=='.')) {
\r
173 // if no characters are left it can't be capitalized
\r
180 // now determine the capitalization type of the first nl letters
\r
188 if (csconv[(*q)].ccase) ncap++;
\r
189 if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++;
\r
193 // remember to terminate the destination string
\r
195 firstcap = csconv[(unsigned char)(*dest)].ccase;
\r
197 unsigned short idx;
\r
198 w_char t[MAXWORDLEN];
\r
199 nc = u8_u16(t, MAXWORDLEN, src);
\r
200 for (int i = 0; i < nc; i++) {
\r
201 idx = (t[i].h << 8) + t[i].l;
\r
202 if (idx != unicodetolower(idx, langnum)) ncap++;
\r
203 if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++;
\r
205 u16_u8(dest, MAXWORDUTF8LEN, t, nc);
\r
207 idx = (t[0].h << 8) + t[0].l;
\r
208 firstcap = (idx != unicodetolower(idx, langnum));
\r
212 // now finally set the captype
\r
215 } else if ((ncap == 1) && firstcap) {
\r
216 *pcaptype = INITCAP;
\r
217 } else if ((ncap == nc) || ((ncap + nneutral) == nc)){
\r
218 *pcaptype = ALLCAP;
\r
219 } else if ((ncap > 1) && firstcap) {
\r
220 *pcaptype = HUHINITCAP;
\r
222 *pcaptype = HUHCAP;
\r
224 return strlen(dest);
\r
228 void Hunspell::mkallcap(char * p)
\r
231 w_char u[MAXWORDLEN];
\r
232 int nc = u8_u16(u, MAXWORDLEN, p);
\r
233 unsigned short idx;
\r
234 for (int i = 0; i < nc; i++) {
\r
235 idx = (u[i].h << 8) + u[i].l;
\r
236 if (idx != unicodetoupper(idx, langnum)) {
\r
237 u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
\r
238 u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
\r
241 u16_u8(p, MAXWORDUTF8LEN, u, nc);
\r
243 while (*p != '\0') {
\r
244 *p = csconv[((unsigned char) *p)].cupper;
\r
250 int Hunspell::mkallcap2(char * p, w_char * u, int nc)
\r
253 unsigned short idx;
\r
254 for (int i = 0; i < nc; i++) {
\r
255 idx = (u[i].h << 8) + u[i].l;
\r
256 if (idx != unicodetoupper(idx, langnum)) {
\r
257 u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
\r
258 u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
\r
261 u16_u8(p, MAXWORDUTF8LEN, u, nc);
\r
264 while (*p != '\0') {
\r
265 *p = csconv[((unsigned char) *p)].cupper;
\r
273 void Hunspell::mkallsmall(char * p)
\r
275 while (*p != '\0') {
\r
276 *p = csconv[((unsigned char) *p)].clower;
\r
281 int Hunspell::mkallsmall2(char * p, w_char * u, int nc)
\r
284 unsigned short idx;
\r
285 for (int i = 0; i < nc; i++) {
\r
286 idx = (u[i].h << 8) + u[i].l;
\r
287 if (idx != unicodetolower(idx, langnum)) {
\r
288 u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8);
\r
289 u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF);
\r
292 u16_u8(p, MAXWORDUTF8LEN, u, nc);
\r
295 while (*p != '\0') {
\r
296 *p = csconv[((unsigned char) *p)].clower;
\r
303 // convert UTF-8 sharp S codes to latin 1
\r
304 char * Hunspell::sharps_u8_l1(char * dest, char * source) {
\r
307 for (p++, source++; *(source - 1); p++, source++) {
\r
309 if (*source == '?') *--p = '?';
\r
314 // recursive search for right ss-?permutations
\r
315 hentry * Hunspell::spellsharps(char * base, char * pos, int n,
\r
316 int repnum, char * tmp, int * info, char **root) {
\r
317 pos = strstr(pos, "ss");
\r
318 if (pos && (n < MAXSHARPS)) {
\r
321 hentry * h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root);
\r
325 h = spellsharps(base, pos + 2, n + 1, repnum, tmp, info, root);
\r
327 } else if (repnum > 0) {
\r
328 if (utf8) return checkword(base, info, root);
\r
329 return checkword(sharps_u8_l1(tmp, base), info, root);
\r
334 int Hunspell::is_keepcase(const hentry * rv) {
\r
335 return pAMgr && rv->astr && pAMgr->get_keepcase() &&
\r
336 TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
\r
339 /* check and insert a word to beginning of the suggestion array */
\r
340 int Hunspell::insert_sug(char ***slst, char * word, int *ns) {
\r
342 if (*ns == MAXSUGGESTION) {
\r
344 free((*slst)[*ns]);
\r
346 for (int k = *ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
\r
347 (*slst)[0] = mystrdup(word);
\r
353 int Hunspell::spell(const char * word, int * info, char ** root)
\r
355 struct hentry * rv=NULL;
\r
356 // need larger vector. For example, Turkish capital letter I converted a
\r
357 // 2-byte UTF-8 character (dotless i) by mkallsmall.
\r
358 char cw[MAXWORDUTF8LEN + 4];
\r
359 char wspace[MAXWORDUTF8LEN + 4];
\r
360 w_char unicw[MAXWORDLEN + 1];
\r
361 int nc = strlen(word);
\r
364 if (nc >= MAXWORDUTF8LEN) return 0;
\r
366 if (nc >= MAXWORDLEN) return 0;
\r
370 int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
\r
372 if (wl == 0) return 1;
\r
374 if (info) *info = 0;
\r
375 if (root) *root = NULL;
\r
377 // allow numbers with dots and commas (but forbid double separators: "..", ",," etc.)
\r
378 enum { NBEGIN, NNUM, NSEP };
\r
379 int nstate = NBEGIN;
\r
382 for (i = 0; (i < wl); i++) {
\r
383 if ((cw[i] <= '9') && (cw[i] >= '0')) {
\r
385 } else if ((cw[i] == ',') || (cw[i] == '.') || (cw[i] == '-')) {
\r
386 if ((nstate == NSEP) || (i == 0)) break;
\r
390 if ((i == wl) && (nstate == NNUM)) return 1;
\r
392 // LANG_hu section: number(s) + (percent or degree) with suffixes
\r
393 if (langnum == LANG_hu) {
\r
394 if ((nstate == NNUM) && ((cw[i] == '%') || (cw[i] == '?'))
\r
395 && checkword(cw + i, info, root)) return 1;
\r
397 // END of LANG_hu section
\r
403 rv = checkword(cw, info, root);
\r
404 if ((abbv) && !(rv)) {
\r
405 memcpy(wspace,cw,wl);
\r
406 *(wspace+wl) = '.';
\r
407 *(wspace+wl+1) = '\0';
\r
408 rv = checkword(wspace, info, root);
\r
413 rv = checkword(cw, info, root);
\r
416 memcpy(wspace,cw,wl);
\r
417 *(wspace+wl) = '.';
\r
418 *(wspace+wl+1) = '\0';
\r
419 rv = checkword(wspace, info, root);
\r
422 if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) {
\r
423 char tmpword[MAXWORDUTF8LEN];
\r
424 wl = mkallsmall2(cw, unicw, nc);
\r
425 memcpy(wspace,cw,(wl+1));
\r
426 rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
\r
428 wl2 = mkinitcap2(cw, unicw, nc);
\r
429 rv = spellsharps(cw, cw, 0, 0, tmpword, info, root);
\r
431 if ((abbv) && !(rv)) {
\r
432 *(wspace+wl) = '.';
\r
433 *(wspace+wl+1) = '\0';
\r
434 rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
\r
436 memcpy(wspace, cw, wl2);
\r
437 *(wspace+wl2) = '.';
\r
438 *(wspace+wl2+1) = '\0';
\r
439 rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
\r
446 wl = mkallsmall2(cw, unicw, nc);
\r
447 memcpy(wspace,cw,(wl+1));
\r
448 rv = checkword(wspace, info, root);
\r
449 if (!rv || (is_keepcase(rv) && !((captype == INITCAP) &&
\r
450 // if CHECKSHARPS: KEEPCASE words with ?are allowed
\r
451 // in INITCAP form, too.
\r
452 pAMgr->get_checksharps() && ((utf8 && strstr(wspace, "脽")) ||
\r
453 (!utf8 && strchr(wspace, '?')))))) {
\r
454 wl2 = mkinitcap2(cw, unicw, nc);
\r
455 rv = checkword(cw, info, root);
\r
456 if (rv && (captype == ALLCAP) && is_keepcase(rv)) rv = NULL;
\r
459 *(wspace+wl) = '.';
\r
460 *(wspace+wl+1) = '\0';
\r
461 rv = checkword(wspace, info, root);
\r
462 if (!rv || is_keepcase(rv)) {
\r
463 memcpy(wspace, cw, wl2);
\r
464 *(wspace+wl2) = '.';
\r
465 *(wspace+wl2+1) = '\0';
\r
466 rv = checkword(wspace, info, root);
\r
467 if (rv && ((captype == ALLCAP) && is_keepcase(rv))) rv = NULL;
\r
476 // recursive breaking at break points (not good for morphological analysis)
\r
480 for (int j = 0; j < pAMgr->get_numbreak(); j++) {
\r
481 s=(char *) strstr(cw, wordbreak[j]);
\r
485 // examine 2 sides of the break point
\r
486 if (spell(cw) && spell(s + strlen(wordbreak[j]))) {
\r
495 // LANG_hu: compoundings with dashes and n-dashes XXX deprecated!
\r
496 if (langnum == LANG_hu) {
\r
498 // compound word with dash (HU) I18n
\r
502 dash = (char *) strstr(cw,"-");
\r
503 if (dash && !wordbreak) {
\r
505 // examine 2 sides of the dash
\r
506 if (spell(cw) && spell(dash + 3)) {
\r
512 dash = (char *) strchr(cw,'-');
\r
515 // examine 2 sides of the dash
\r
516 if (dash[1] == '\0') { // base word ending with dash
\r
517 if (spell(cw)) return 1;
\r
519 // first word ending with dash: word-
\r
520 char r2 = *(dash + 1);
\r
523 result = spell(cw);
\r
526 if (result && spell(dash+1) && ((strlen(dash+1) > 1) || (dash[1] == 'e') ||
\r
527 ((dash[1] > '0') && (dash[1] < '9')))) return 1;
\r
529 // affixed number in correct word
\r
530 if (result && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)>='.'))) {
\r
533 if (*(dash - n) == '.') n++;
\r
534 // search first not a number character to left from dash
\r
535 while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
\r
538 if ((dash - n) < cw) n--;
\r
539 // numbers: deprecated
\r
540 for(; n >= 1; n--) {
\r
541 if ((*(dash - n) >= '0') && (*(dash - n) <= '9') &&
\r
542 checkword(dash - n, info, root)) return 1;
\r
550 //int Hunspell::spell(const char * word) {
\r
551 // return spell(word, NULL, NULL);
\r
554 struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
\r
556 struct hentry * he = NULL;
\r
558 char w2[MAXWORDUTF8LEN];
\r
561 char * ignoredchars = pAMgr->get_ignore();
\r
562 if (ignoredchars != NULL) {
\r
565 int ignoredchars_utf16_len;
\r
566 unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
\r
567 remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
\r
569 remove_ignored_chars(w2,ignoredchars);
\r
574 // word reversing wrapper for complex prefixes
\r
575 if (complexprefixes) {
\r
580 if (utf8) reverseword_utf(w2); else reverseword(w2);
\r
583 // look word in hash table
\r
584 if (pHMgr) he = pHMgr->lookup(word);
\r
586 // check forbidden and onlyincompound words
\r
587 if ((he) && (he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
\r
588 info += SPELL_FORBIDDEN;
\r
589 // LANG_hu section: set dash information for suggestions
\r
590 if (langnum == LANG_hu) {
\r
591 if (pAMgr->get_compoundflag() &&
\r
592 TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) {
\r
593 info += SPELL_COMPOUND;
\r
599 // he = next not pseudoroot and not onlyincompound homonym or NULL
\r
600 while (he && (he->astr) &&
\r
601 ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), he->alen)) ||
\r
602 (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen))
\r
603 )) he = he->next_homonym;
\r
605 // check with affixes
\r
606 if (!he && pAMgr) {
\r
607 // try stripping off affixes */
\r
608 len = strlen(word);
\r
609 he = pAMgr->affix_check(word, len, 0);
\r
611 // check compound restriction
\r
612 if (he && he->astr && pAMgr->get_onlyincompound() &&
\r
613 TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) he = NULL;
\r
616 if ((he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
\r
617 info += SPELL_FORBIDDEN;
\r
621 *root = mystrdup(he->word);
\r
622 if (complexprefixes) {
\r
623 if (utf8) reverseword_utf(*root); else reverseword(*root);
\r
626 // try check compound word
\r
627 } else if (pAMgr->get_compound()) {
\r
628 he = pAMgr->compound_check(word, len,
\r
629 0,0,100,0,NULL,0,NULL,NULL,0);
\r
630 // LANG_hu section: `moving rule' with last dash
\r
631 if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) {
\r
632 char * dup = mystrdup(word);
\r
634 he = pAMgr->compound_check(dup, len-1,
\r
635 -5,0,100,0,NULL,1,NULL,NULL,0);
\r
638 // end of LANG speficic region
\r
641 *root = mystrdup(he->word);
\r
642 if (complexprefixes) {
\r
643 if (utf8) reverseword_utf(*root); else reverseword(*root);
\r
646 if (info) *info += SPELL_COMPOUND;
\r
655 int Hunspell::suggest(char*** slst, const char * word)
\r
657 char cw[MAXWORDUTF8LEN + 4];
\r
658 char wspace[MAXWORDUTF8LEN + 4];
\r
659 if (! pSMgr) return 0;
\r
660 w_char unicw[MAXWORDLEN + 1];
\r
661 int nc = strlen(word);
\r
663 if (nc >= MAXWORDUTF8LEN) return 0;
\r
665 if (nc >= MAXWORDLEN) return 0;
\r
669 int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
\r
670 if (wl == 0) return 0;
\r
678 ns = pSMgr->suggest(slst, cw, ns);
\r
684 ns = pSMgr->suggest(slst, cw, ns);
\r
685 if (ns == -1) break;
\r
686 memcpy(wspace,cw,(wl+1));
\r
687 mkallsmall2(wspace, unicw, nc);
\r
688 ns = pSMgr->suggest(slst, wspace, ns);
\r
694 ns = pSMgr->suggest(slst, cw, ns);
\r
697 if (captype == HUHINITCAP) {
\r
698 // TheOpenOffice.org -> The OpenOffice.org
\r
699 memcpy(wspace,cw,(wl+1));
\r
700 mkinitsmall2(wspace, unicw, nc);
\r
701 ns = pSMgr->suggest(slst, wspace, ns);
\r
703 memcpy(wspace,cw,(wl+1));
\r
704 mkallsmall2(wspace, unicw, nc);
\r
705 insert_sug(slst, wspace, &ns);
\r
707 ns = pSMgr->suggest(slst, wspace, ns);
\r
708 if (captype == HUHINITCAP) {
\r
709 mkinitcap2(wspace, unicw, nc);
\r
710 insert_sug(slst, wspace, &ns);
\r
711 ns = pSMgr->suggest(slst, wspace, ns);
\r
713 // aNew -> "a New" (instead of "a new")
\r
714 for (int j = prevns; j < ns; j++) {
\r
715 char * space = strchr((*slst)[j],' ');
\r
717 int slen = strlen(space + 1);
\r
718 // different case after space (need capitalisation)
\r
719 if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) {
\r
720 w_char w[MAXWORDLEN + 1];
\r
722 char * r = (*slst)[j];
\r
723 if (utf8) wc = u8_u16(w, MAXWORDLEN, space + 1);
\r
724 mkinitcap2(space + 1, w, wc);
\r
725 // set as first suggestion
\r
726 for (int k = j; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
\r
736 memcpy(wspace, cw, (wl+1));
\r
737 mkallsmall2(wspace, unicw, nc);
\r
738 ns = pSMgr->suggest(slst, wspace, ns);
\r
739 if (ns == -1) break;
\r
740 if (pAMgr && pAMgr->get_keepcase()) insert_sug(slst, wspace, &ns);
\r
741 mkinitcap2(wspace, unicw, nc);
\r
742 ns = pSMgr->suggest(slst, wspace, ns);
\r
743 for (int j=0; j < ns; j++) {
\r
744 mkallcap((*slst)[j]);
\r
745 if (pAMgr && pAMgr->get_checksharps()) {
\r
748 pos = strstr((*slst)[j], "脽");
\r
752 pos = strstr(pos+2, "脽");
\r
755 pos = strchr((*slst)[j], '?');
\r
757 (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 2);
\r
758 mystrrep((*slst)[j], "?", "SS");
\r
759 pos = strchr((*slst)[j], '?');
\r
768 // LANG_hu section: replace '-' with ' ' in Hungarian
\r
769 if (langnum == LANG_hu) {
\r
770 for (int j=0; j < ns; j++) {
\r
771 char * pos = strchr((*slst)[j],'-');
\r
774 char w[MAXWORDUTF8LEN];
\r
776 strcpy(w, (*slst)[j]);
\r
777 strcat(w, pos + 1);
\r
778 spell(w, &info, NULL);
\r
779 if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
\r
785 // END OF LANG_hu section
\r
787 // try ngram approach since found nothing
\r
788 if ((ns == 0) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) {
\r
792 ns = pSMgr->ngsuggest(*slst, cw, pHMgr);
\r
796 memcpy(wspace,cw,(wl+1));
\r
797 mkallsmall2(wspace, unicw, nc);
\r
798 ns = pSMgr->ngsuggest(*slst, wspace, pHMgr);
\r
803 memcpy(wspace,cw,(wl+1));
\r
804 mkallsmall2(wspace, unicw, nc);
\r
805 ns = pSMgr->ngsuggest(*slst, wspace, pHMgr);
\r
809 memcpy(wspace,cw,(wl+1));
\r
810 mkallsmall2(wspace, unicw, nc);
\r
811 ns = pSMgr->ngsuggest(*slst, wspace, pHMgr);
\r
812 for (int j=0; j < ns; j++)
\r
813 mkallcap((*slst)[j]);
\r
819 // word reversing wrapper for complex prefixes
\r
820 if (complexprefixes) {
\r
821 for (int j = 0; j < ns; j++) {
\r
822 if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
\r
827 if (capwords) for (int j=0; j < ns; j++) {
\r
828 mkinitcap((*slst)[j]);
\r
831 // expand suggestions with dot(s)
\r
832 if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
\r
833 for (int j = 0; j < ns; j++) {
\r
834 (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
\r
835 strcat((*slst)[j], word + strlen(word) - abbv);
\r
839 // suggest keepcase
\r
840 if (pAMgr->get_keepcase()) {
\r
845 for (int j=0; j < ns; j++) {
\r
846 if (!spell((*slst)[j])) {
\r
847 char s[MAXSWUTF8L];
\r
851 len = u8_u16(w, MAXSWL, (*slst)[j]);
\r
853 strcpy(s, (*slst)[j]);
\r
856 mkallsmall2(s, w, len);
\r
859 (*slst)[l] = mystrdup(s);
\r
862 mkinitcap2(s, w, len);
\r
864 (*slst)[l] = mystrdup(s);
\r
869 (*slst)[l] = (*slst)[j];
\r
878 // remove duplications
\r
880 for (int j = 0; j < ns; j++) {
\r
881 (*slst)[l] = (*slst)[j];
\r
882 for (int k = 0; k < l; k++) {
\r
883 if (strcmp((*slst)[k], (*slst)[j]) == 0) {
\r
893 char * Hunspell::get_dic_encoding()
\r
898 #ifdef HUNSPELL_EXPERIMENTAL
\r
899 // XXX need UTF-8 support
\r
900 int Hunspell::suggest_auto(char*** slst, const char * word)
\r
902 char cw[MAXWORDUTF8LEN + 4];
\r
903 char wspace[MAXWORDUTF8LEN + 4];
\r
904 if (! pSMgr) return 0;
\r
905 int wl = strlen(word);
\r
907 if (wl >= MAXWORDUTF8LEN) return 0;
\r
909 if (wl >= MAXWORDLEN) return 0;
\r
913 wl = cleanword(cw, word, &captype, &abbv);
\r
914 if (wl == 0) return 0;
\r
916 *slst = NULL; // HU, nsug in pSMgr->suggest
\r
920 ns = pSMgr->suggest_auto(slst, cw, ns);
\r
926 memcpy(wspace,cw,(wl+1));
\r
927 mkallsmall(wspace);
\r
928 ns = pSMgr->suggest_auto(slst, wspace, ns);
\r
929 for (int j=0; j < ns; j++)
\r
930 mkinitcap((*slst)[j]);
\r
931 ns = pSMgr->suggest_auto(slst, cw, ns);
\r
937 ns = pSMgr->suggest_auto(slst, cw, ns);
\r
939 memcpy(wspace,cw,(wl+1));
\r
940 mkallsmall(wspace);
\r
941 ns = pSMgr->suggest_auto(slst, wspace, ns);
\r
947 memcpy(wspace,cw,(wl+1));
\r
948 mkallsmall(wspace);
\r
949 ns = pSMgr->suggest_auto(slst, wspace, ns);
\r
952 ns = pSMgr->suggest_auto(slst, wspace, ns);
\r
954 for (int j=0; j < ns; j++)
\r
955 mkallcap((*slst)[j]);
\r
960 // word reversing wrapper for complex prefixes
\r
961 if (complexprefixes) {
\r
962 for (int j = 0; j < ns; j++) {
\r
963 if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
\r
967 // expand suggestions with dot(s)
\r
968 if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
\r
969 for (int j = 0; j < ns; j++) {
\r
970 (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
\r
971 strcat((*slst)[j], word + strlen(word) - abbv);
\r
975 // LANG_hu section: replace '-' with ' ' in Hungarian
\r
976 if (langnum == LANG_hu) {
\r
977 for (int j=0; j < ns; j++) {
\r
978 char * pos = strchr((*slst)[j],'-');
\r
981 char w[MAXWORDUTF8LEN];
\r
983 strcpy(w, (*slst)[j]);
\r
984 strcat(w, pos + 1);
\r
985 spell(w, &info, NULL);
\r
986 if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
\r
992 // END OF LANG_hu section
\r
996 // XXX need UTF-8 support
\r
997 int Hunspell::stem(char*** slst, const char * word)
\r
999 char cw[MAXWORDUTF8LEN + 4];
\r
1000 char wspace[MAXWORDUTF8LEN + 4];
\r
1001 if (! pSMgr) return 0;
\r
1002 int wl = strlen(word);
\r
1004 if (wl >= MAXWORDUTF8LEN) return 0;
\r
1006 if (wl >= MAXWORDLEN) return 0;
\r
1010 wl = cleanword(cw, word, &captype, &abbv);
\r
1011 if (wl == 0) return 0;
\r
1015 *slst = NULL; // HU, nsug in pSMgr->suggest
\r
1020 ns = pSMgr->suggest_stems(slst, cw, ns);
\r
1022 if ((abbv) && (ns == 0)) {
\r
1023 memcpy(wspace,cw,wl);
\r
1024 *(wspace+wl) = '.';
\r
1025 *(wspace+wl+1) = '\0';
\r
1026 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1034 ns = pSMgr->suggest_stems(slst, cw, ns);
\r
1037 memcpy(wspace,cw,(wl+1));
\r
1038 mkallsmall(wspace);
\r
1039 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1043 if ((abbv) && (ns == 0)) {
\r
1044 memcpy(wspace,cw,wl);
\r
1045 mkallsmall(wspace);
\r
1046 *(wspace+wl) = '.';
\r
1047 *(wspace+wl+1) = '\0';
\r
1048 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1056 ns = pSMgr->suggest_stems(slst, cw, ns);
\r
1057 if (ns != 0) break;
\r
1059 memcpy(wspace,cw,(wl+1));
\r
1060 mkallsmall(wspace);
\r
1061 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1064 mkinitcap(wspace);
\r
1065 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1068 if ((abbv) && (ns == 0)) {
\r
1069 memcpy(wspace,cw,wl);
\r
1070 mkallsmall(wspace);
\r
1071 *(wspace+wl) = '.';
\r
1072 *(wspace+wl+1) = '\0';
\r
1073 ns = pSMgr->suggest_stems(slst, wspace, ns);
\r
1084 int Hunspell::suggest_pos_stems(char*** slst, const char * word)
\r
1086 char cw[MAXWORDUTF8LEN + 4];
\r
1087 char wspace[MAXWORDUTF8LEN + 4];
\r
1088 if (! pSMgr) return 0;
\r
1089 int wl = strlen(word);
\r
1091 if (wl >= MAXWORDUTF8LEN) return 0;
\r
1093 if (wl >= MAXWORDLEN) return 0;
\r
1097 wl = cleanword(cw, word, &captype, &abbv);
\r
1098 if (wl == 0) return 0;
\r
1100 int ns = 0; // ns=0 = normalized input
\r
1102 *slst = NULL; // HU, nsug in pSMgr->suggest
\r
1107 ns = pSMgr->suggest_pos_stems(slst, cw, ns);
\r
1109 if ((abbv) && (ns == 0)) {
\r
1110 memcpy(wspace,cw,wl);
\r
1111 *(wspace+wl) = '.';
\r
1112 *(wspace+wl+1) = '\0';
\r
1113 ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
\r
1121 ns = pSMgr->suggest_pos_stems(slst, cw, ns);
\r
1123 if (ns == 0 || ((*slst)[0][0] == '#')) {
\r
1124 memcpy(wspace,cw,(wl+1));
\r
1125 mkallsmall(wspace);
\r
1126 ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
\r
1134 ns = pSMgr->suggest_pos_stems(slst, cw, ns);
\r
1135 if (ns != 0) break;
\r
1137 memcpy(wspace,cw,(wl+1));
\r
1138 mkallsmall(wspace);
\r
1139 ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
\r
1142 mkinitcap(wspace);
\r
1143 ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
\r
1151 #endif // END OF HUNSPELL_EXPERIMENTAL CODE
\r
1153 const char * Hunspell::get_wordchars()
\r
1155 return pAMgr->get_wordchars();
\r
1158 unsigned short * Hunspell::get_wordchars_utf16(int * len)
\r
1160 return pAMgr->get_wordchars_utf16(len);
\r
1163 void Hunspell::mkinitcap(char * p)
\r
1166 if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
\r
1169 w_char u[MAXWORDLEN];
\r
1170 len = u8_u16(u, MAXWORDLEN, p);
\r
1171 unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
\r
1172 u[0].h = (unsigned char) (i >> 8);
\r
1173 u[0].l = (unsigned char) (i & 0x00FF);
\r
1174 u16_u8(p, MAXWORDUTF8LEN, u, len);
\r
1178 int Hunspell::mkinitcap2(char * p, w_char * u, int nc)
\r
1181 if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
\r
1182 } else if (nc > 0) {
\r
1183 unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
\r
1184 u[0].h = (unsigned char) (i >> 8);
\r
1185 u[0].l = (unsigned char) (i & 0x00FF);
\r
1186 u16_u8(p, MAXWORDUTF8LEN, u, nc);
\r
1192 int Hunspell::mkinitsmall2(char * p, w_char * u, int nc)
\r
1195 if (*p != '\0') *p = csconv[((unsigned char)*p)].clower;
\r
1196 } else if (nc > 0) {
\r
1197 unsigned short i = unicodetolower((u[0].h << 8) + u[0].l, langnum);
\r
1198 u[0].h = (unsigned char) (i >> 8);
\r
1199 u[0].l = (unsigned char) (i & 0x00FF);
\r
1200 u16_u8(p, MAXWORDUTF8LEN, u, nc);
\r
1206 int Hunspell::put_word(const char * word)
\r
1209 return pHMgr->put_word(word, strlen(word), NULL);
\r
1214 int Hunspell::put_word_pattern(const char * word, const char * pattern)
\r
1217 return pHMgr->put_word_pattern(word, strlen(word), pattern);
\r
1222 const char * Hunspell::get_version()
\r
1224 return pAMgr->get_version();
\r
1227 struct cs_info * Hunspell::get_csconv()
\r
1232 #ifdef HUNSPELL_EXPERIMENTAL
\r
1233 // XXX need UTF-8 support
\r
1234 char * Hunspell::morph(const char * word)
\r
1236 char cw[MAXWORDUTF8LEN + 4];
\r
1237 char wspace[MAXWORDUTF8LEN + 4];
\r
1238 if (! pSMgr) return 0;
\r
1239 int wl = strlen(word);
\r
1241 if (wl >= MAXWORDUTF8LEN) return 0;
\r
1243 if (wl >= MAXWORDLEN) return 0;
\r
1247 wl = cleanword(cw, word, &captype, &abbv);
\r
1250 for (wl = 0; wl < abbv; wl++) cw[wl] = '.';
\r
1256 char result[MAXLNLEN];
\r
1266 // LANG_hu section: set dash information for suggestions
\r
1267 if (langnum == LANG_hu) {
\r
1268 while ((n < wl) &&
\r
1269 (((cw[n] <= '9') && (cw[n] >= '0')) || (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) {
\r
1271 if ((cw[n] == '.') || (cw[n] == ',')) {
\r
1272 if (((n2 == 0) && (n > 3)) ||
\r
1273 ((n2 > 0) && ((cw[n-1] == '.') || (cw[n-1] == ',')))) break;
\r
1279 if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return NULL;
\r
1280 if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='?)) && checkword(cw+n, NULL, NULL))) {
\r
1281 strcat(result, cw);
\r
1282 result[n - 1] = '\0';
\r
1284 st = pSMgr->suggest_morph(cw + n - 1);
\r
1286 strcat(result, st);
\r
1290 char sign = cw[n];
\r
1292 st = pSMgr->suggest_morph(cw + n - 1);
\r
1294 strcat(result, st);
\r
1297 strcat(result, "+"); // XXX SPEC. MORPHCODE
\r
1299 st = pSMgr->suggest_morph(cw + n);
\r
1301 strcat(result, st);
\r
1305 return mystrdup(result);
\r
1308 // END OF LANG_hu section
\r
1312 st = pSMgr->suggest_morph(cw);
\r
1314 strcat(result, st);
\r
1318 memcpy(wspace,cw,wl);
\r
1319 *(wspace+wl) = '.';
\r
1320 *(wspace+wl+1) = '\0';
\r
1321 st = pSMgr->suggest_morph(wspace);
\r
1323 if (*result) strcat(result, "\n");
\r
1324 strcat(result, st);
\r
1331 memcpy(wspace,cw,(wl+1));
\r
1332 mkallsmall(wspace);
\r
1333 st = pSMgr->suggest_morph(wspace);
\r
1335 strcat(result, st);
\r
1338 st = pSMgr->suggest_morph(cw);
\r
1340 if (*result) strcat(result, "\n");
\r
1341 strcat(result, st);
\r
1345 memcpy(wspace,cw,wl);
\r
1346 *(wspace+wl) = '.';
\r
1347 *(wspace+wl+1) = '\0';
\r
1348 mkallsmall(wspace);
\r
1349 st = pSMgr->suggest_morph(wspace);
\r
1351 if (*result) strcat(result, "\n");
\r
1352 strcat(result, st);
\r
1355 mkinitcap(wspace);
\r
1356 st = pSMgr->suggest_morph(wspace);
\r
1358 if (*result) strcat(result, "\n");
\r
1359 strcat(result, st);
\r
1366 st = pSMgr->suggest_morph(cw);
\r
1368 strcat(result, st);
\r
1372 memcpy(wspace,cw,(wl+1));
\r
1373 mkallsmall(wspace);
\r
1374 st = pSMgr->suggest_morph(wspace);
\r
1376 if (*result) strcat(result, "\n");
\r
1377 strcat(result, st);
\r
1384 memcpy(wspace,cw,(wl+1));
\r
1385 st = pSMgr->suggest_morph(wspace);
\r
1387 strcat(result, st);
\r
1390 mkallsmall(wspace);
\r
1391 st = pSMgr->suggest_morph(wspace);
\r
1393 if (*result) strcat(result, "\n");
\r
1394 strcat(result, st);
\r
1397 mkinitcap(wspace);
\r
1398 st = pSMgr->suggest_morph(wspace);
\r
1400 if (*result) strcat(result, "\n");
\r
1401 strcat(result, st);
\r
1405 memcpy(wspace,cw,(wl+1));
\r
1406 *(wspace+wl) = '.';
\r
1407 *(wspace+wl+1) = '\0';
\r
1408 if (*result) strcat(result, "\n");
\r
1409 st = pSMgr->suggest_morph(wspace);
\r
1411 strcat(result, st);
\r
1414 mkallsmall(wspace);
\r
1415 st = pSMgr->suggest_morph(wspace);
\r
1417 if (*result) strcat(result, "\n");
\r
1418 strcat(result, st);
\r
1421 mkinitcap(wspace);
\r
1422 st = pSMgr->suggest_morph(wspace);
\r
1424 if (*result) strcat(result, "\n");
\r
1425 strcat(result, st);
\r
1433 if (result && (*result)) {
\r
1434 // word reversing wrapper for complex prefixes
\r
1435 if (complexprefixes) {
\r
1436 if (utf8) reverseword_utf(result); else reverseword(result);
\r
1438 return mystrdup(result);
\r
1441 // compound word with dash (HU) I18n
\r
1442 char * dash = NULL;
\r
1444 // LANG_hu section: set dash information for suggestions
\r
1445 if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
\r
1446 if ((langnum == LANG_hu) && dash) {
\r
1448 // examine 2 sides of the dash
\r
1449 if (dash[1] == '\0') { // base word ending with dash
\r
1450 if (spell(cw)) return pSMgr->suggest_morph(cw);
\r
1451 } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
\r
1452 if (spell(cw) && (spell("-e"))) {
\r
1453 st = pSMgr->suggest_morph(cw);
\r
1455 strcat(result, st);
\r
1458 strcat(result,"+"); // XXX spec. separator in MORPHCODE
\r
1459 st = pSMgr->suggest_morph("-e");
\r
1461 strcat(result, st);
\r
1464 return mystrdup(result);
\r
1467 // first word ending with dash: word- XXX ???
\r
1468 char r2 = *(dash + 1);
\r
1471 nresult = spell(cw);
\r
1474 if (nresult && spell(dash+1) && ((strlen(dash+1) > 1) ||
\r
1475 ((dash[1] > '0') && (dash[1] < '9')))) {
\r
1478 strcat(result, st);
\r
1480 strcat(result,"+"); // XXX spec. separator in MORPHCODE
\r
1482 st = morph(dash+1);
\r
1484 strcat(result, st);
\r
1487 return mystrdup(result);
\r
1490 // affixed number in correct word
\r
1491 if (nresult && (dash > cw) && (((*(dash-1)<='9') &&
\r
1492 (*(dash-1)>='0')) || (*(dash-1)=='.'))) {
\r
1495 if (*(dash - n) == '.') n++;
\r
1496 // search first not a number character to left from dash
\r
1497 while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
\r
1500 if ((dash - n) < cw) n--;
\r
1501 // numbers: valami1000000-hoz
\r
1502 // examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz,
\r
1504 for(; n >= 1; n--) {
\r
1505 if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && checkword(dash - n, NULL, NULL)) {
\r
1506 strcat(result, cw);
\r
1507 result[dash - cw - n] = '\0';
\r
1508 st = pSMgr->suggest_morph(dash - n);
\r
1510 strcat(result, st);
\r
1513 return mystrdup(result);
\r
1521 // XXX need UTF-8 support
\r
1522 char * Hunspell::morph_with_correction(const char * word)
\r
1524 char cw[MAXWORDUTF8LEN + 4];
\r
1525 char wspace[MAXWORDUTF8LEN + 4];
\r
1526 if (! pSMgr) return 0;
\r
1527 int wl = strlen(word);
\r
1529 if (wl >= MAXWORDUTF8LEN) return 0;
\r
1531 if (wl >= MAXWORDLEN) return 0;
\r
1535 wl = cleanword(cw, word, &captype, &abbv);
\r
1536 if (wl == 0) return 0;
\r
1538 char result[MAXLNLEN];
\r
1546 st = pSMgr->suggest_morph_for_spelling_error(cw);
\r
1548 strcat(result, st);
\r
1552 memcpy(wspace,cw,wl);
\r
1553 *(wspace+wl) = '.';
\r
1554 *(wspace+wl+1) = '\0';
\r
1555 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1557 if (*result) strcat(result, "\n");
\r
1558 strcat(result, st);
\r
1565 memcpy(wspace,cw,(wl+1));
\r
1566 mkallsmall(wspace);
\r
1567 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1569 strcat(result, st);
\r
1572 st = pSMgr->suggest_morph_for_spelling_error(cw);
\r
1574 if (*result) strcat(result, "\n");
\r
1575 strcat(result, st);
\r
1579 memcpy(wspace,cw,wl);
\r
1580 *(wspace+wl) = '.';
\r
1581 *(wspace+wl+1) = '\0';
\r
1582 mkallsmall(wspace);
\r
1583 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1585 if (*result) strcat(result, "\n");
\r
1586 strcat(result, st);
\r
1589 mkinitcap(wspace);
\r
1590 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1592 if (*result) strcat(result, "\n");
\r
1593 strcat(result, st);
\r
1600 st = pSMgr->suggest_morph_for_spelling_error(cw);
\r
1602 strcat(result, st);
\r
1605 memcpy(wspace,cw,(wl+1));
\r
1606 mkallsmall(wspace);
\r
1607 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1609 if (*result) strcat(result, "\n");
\r
1610 strcat(result, st);
\r
1616 memcpy(wspace,cw,(wl+1));
\r
1617 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1619 strcat(result, st);
\r
1622 mkallsmall(wspace);
\r
1623 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1625 if (*result) strcat(result, "\n");
\r
1626 strcat(result, st);
\r
1629 mkinitcap(wspace);
\r
1630 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1632 if (*result) strcat(result, "\n");
\r
1633 strcat(result, st);
\r
1637 memcpy(wspace,cw,(wl+1));
\r
1638 *(wspace+wl) = '.';
\r
1639 *(wspace+wl+1) = '\0';
\r
1640 if (*result) strcat(result, "\n");
\r
1641 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1643 strcat(result, st);
\r
1646 mkallsmall(wspace);
\r
1647 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1649 if (*result) strcat(result, "\n");
\r
1650 strcat(result, st);
\r
1653 mkinitcap(wspace);
\r
1654 st = pSMgr->suggest_morph_for_spelling_error(wspace);
\r
1656 if (*result) strcat(result, "\n");
\r
1657 strcat(result, st);
\r
1665 if (result) return mystrdup(result);
\r
1670 * return line count
\r
1671 * XXX need a better data structure for morphological analysis */
\r
1672 int Hunspell::analyze(char ***out, const char *word) {
\r
1674 if (!word) return 0;
\r
1675 char * m = morph(word);
\r
1677 if (!out) return line_tok(m, out);
\r
1679 // without memory allocation
\r
1680 /* BUG missing buffer size checking */
\r
1682 for(p = 0, i = 0; m[i]; i++) {
\r
1683 if(m[i] == '\n' || !m[i+1]) {
\r
1685 strncpy((*out)[n++], m + p, i - p + 1);
\r
1686 if (m[i] == '\n') (*out)[n++][i - p] = '\0';
\r
1687 if(!m[i+1]) break;
\r
1695 #endif // END OF HUNSPELL_EXPERIMENTAL CODE
\r
1697 Hunhandle *Hunspell_create(const char * affpath, const char * dpath)
\r
1699 return (Hunhandle*)(new Hunspell(affpath, dpath));
\r
1702 void Hunspell_destroy(Hunhandle *pHunspell)
\r
1704 delete (Hunspell*)(pHunspell);
\r
1707 int Hunspell_spell(Hunhandle *pHunspell, const char *word)
\r
1709 return ((Hunspell*)pHunspell)->spell(word);
\r
1712 char *Hunspell_get_dic_encoding(Hunhandle *pHunspell)
\r
1714 return ((Hunspell*)pHunspell)->get_dic_encoding();
\r
1717 int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word)
\r
1719 return ((Hunspell*)pHunspell)->suggest(slst, word);
\r