Mozilla Home
Privacy
Cookies
Legal
Bugzilla
Browse
Advanced Search
New Bug
Reports
Documentation
Log In
Log In with GitHub
or
Remember me
Browse
Advanced Search
New Bug
Reports
Documentation
Attachment 507295 Details for
Bug 620626
[patch]
1.2.14 to 1.3.0 interdiff
hun1214-130.diff (text/plain), 54.39 KB, created by
Ryan VanderMeulen [:RyanVM]
(
hide
)
Description:
1.2.14 to 1.3.0 interdiff
Filename:
MIME Type:
Creator:
Ryan VanderMeulen [:RyanVM]
Size:
54.39 KB
patch
obsolete
>diff -up8 affixmgr.cpp affixmgr.cpp >--- affixmgr.cpp 2011-01-06 06:48:34 -0500 >+++ affixmgr.cpp 2011-01-26 04:18:20 -0500 >@@ -50,16 +50,17 @@ AffixMgr::AffixMgr(const char * affpath, > compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word > checkcompounddup = 0; // forbid double words in compounds > checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution) > checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds > checkcompoundtriple = 0; // forbid compounds with triple letters > simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt) > forbiddenword = FORBIDDENWORD; // forbidden word signing flag > nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag >+ nongramsuggest = FLAG_NULL; > lang = NULL; // language > langnum = 0; // language code (see http://l10n.openoffice.org/languages.html) > needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes > cpdwordmax = -1; // default: unlimited wordcount in compound words > cpdmin = -1; // undefined > cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words > cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX) > cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search) >@@ -77,19 +78,25 @@ AffixMgr::AffixMgr(const char * affpath, > version=NULL; // affix and dictionary file version string > havecontclass=0; // flags of possible continuing classes (double affix) > // LEMMA_PRESENT: not put root into the morphological output. Lemma presents > // in morhological description in dictionary file. It's often combined with PSEUDOROOT. > lemma_present = FLAG_NULL; > circumfix = FLAG_NULL; > onlyincompound = FLAG_NULL; > maxngramsugs = -1; // undefined >+ maxdiff = -1; // undefined >+ onlymaxdiff = 0; >+ maxcpdsugs = -1; // undefined > nosplitsugs = 0; > sugswithdots = 0; > keepcase = 0; >+ forceucase = 0; >+ warn = 0; >+ forbidwarn = 0; > checksharps = 0; > substandard = FLAG_NULL; > fullstrip = 0; > > sfx = NULL; > pfx = NULL; > > for (int i=0; i < SETSIZE; i++) { >@@ -215,16 +222,17 @@ AffixMgr::~AffixMgr() > FREE_FLAG(compoundbegin); > FREE_FLAG(compoundmiddle); > FREE_FLAG(compoundend); > FREE_FLAG(compoundpermitflag); > FREE_FLAG(compoundforbidflag); > FREE_FLAG(compoundroot); > FREE_FLAG(forbiddenword); > FREE_FLAG(nosuggest); >+ FREE_FLAG(nongramsuggest); > FREE_FLAG(needaffix); > FREE_FLAG(lemma_present); > FREE_FLAG(circumfix); > FREE_FLAG(onlyincompound); > > cpdwordmax = 0; > pHMgr = NULL; > cpdmin = 0; >@@ -418,16 +426,23 @@ int AffixMgr::parse_file(const char * a > > if (strncmp(line,"NOSUGGEST",9) == 0) { > if (parse_flag(line, &nosuggest, afflst)) { > delete afflst; > return 1; > } > } > >+ if (strncmp(line,"NONGRAMSUGGEST",14) == 0) { >+ if (parse_flag(line, &nongramsuggest, afflst)) { >+ delete afflst; >+ return 1; >+ } >+ } >+ > /* parse in the flag used by forbidden words */ > if (strncmp(line,"FORBIDDENWORD",13) == 0) { > if (parse_flag(line, &forbiddenword, afflst)) { > delete afflst; > return 1; > } > } > >@@ -597,16 +612,33 @@ int AffixMgr::parse_file(const char * a > > if (strncmp(line,"MAXNGRAMSUGS",12) == 0) { > if (parse_num(line, &maxngramsugs, afflst)) { > delete afflst; > return 1; > } > } > >+ if (strncmp(line,"ONLYMAXDIFF", 11) == 0) >+ onlymaxdiff = 1; >+ >+ if (strncmp(line,"MAXDIFF",7) == 0) { >+ if (parse_num(line, &maxdiff, afflst)) { >+ delete afflst; >+ return 1; >+ } >+ } >+ >+ if (strncmp(line,"MAXCPDSUGS",10) == 0) { >+ if (parse_num(line, &maxcpdsugs, afflst)) { >+ delete afflst; >+ return 1; >+ } >+ } >+ > if (strncmp(line,"NOSPLITSUGS",11) == 0) { > nosplitsugs=1; > } > > if (strncmp(line,"FULLSTRIP",9) == 0) { > fullstrip=1; > } > >@@ -617,16 +649,36 @@ int AffixMgr::parse_file(const char * a > /* parse in the flag used by forbidden words */ > if (strncmp(line,"KEEPCASE",8) == 0) { > if (parse_flag(line, &keepcase, afflst)) { > delete afflst; > return 1; > } > } > >+ /* parse in the flag used by `forceucase' */ >+ if (strncmp(line,"FORCEUCASE",10) == 0) { >+ if (parse_flag(line, &forceucase, afflst)) { >+ delete afflst; >+ return 1; >+ } >+ } >+ >+ /* parse in the flag used by `warn' */ >+ if (strncmp(line,"WARN",4) == 0) { >+ if (parse_flag(line, &warn, afflst)) { >+ delete afflst; >+ return 1; >+ } >+ } >+ >+ if (strncmp(line,"FORBIDWARN",10) == 0) { >+ forbidwarn=1; >+ } >+ > /* parse in the flag used by the affix generator */ > if (strncmp(line,"SUBSTANDARD",11) == 0) { > if (parse_flag(line, &substandard, afflst)) { > delete afflst; > return 1; > } > } > >@@ -1468,25 +1520,25 @@ void AffixMgr::setcminmax(int * cmin, in > } > } > > > // check if compound word is correctly spelled > // hu_mov_rule = spec. Hungarian rule (XXX) > struct hentry * AffixMgr::compound_check(const char * word, int len, > short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL, >- char hu_mov_rule = 0, char is_sug = 0) >+ char hu_mov_rule = 0, char is_sug = 0, int info = 0) > { > int i; > short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; > struct hentry * rv = NULL; > struct hentry * rv_first; > struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking > char st [MAXWORDUTF8LEN + 4]; >- char ch; >+ char ch = '\0'; > int cmin; > int cmax; > int striple = 0; > int scpd = 0; > int soldi = 0; > int oldcmin = 0; > int oldcmax = 0; > int oldlen = 0; >@@ -1721,21 +1773,26 @@ struct hentry * AffixMgr::compound_check > (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || > (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))) || > (scpd != 0 && checkcpdtable[scpd-1].cond2 != FLAG_NULL && > !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen)) > )) { > rv = rv->next_homonym; > } > >+ // check FORCEUCASE >+ if (rv && forceucase && (rv) && >+ (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info & SPELL_ORIGCAP)) rv = NULL; >+ > if (rv && words && words[wnum + 1]) return rv_first; > > oldnumsyllable2 = numsyllable; > oldwordnum2 = wordnum; > >+ > // LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code > if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) { > numsyllable--; > } > // END of LANG_hu section > > // increment word number, if the second root has a compoundroot flag > if ((rv) && (compoundroot) && >@@ -1811,16 +1868,20 @@ struct hentry * AffixMgr::compound_check > TESTAFF(pfx->getCont(), compoundforbidflag, > pfx->getContLen())) || > (sfx && sfx->getCont() && > TESTAFF(sfx->getCont(), compoundforbidflag, > sfx->getContLen())))) { > rv = NULL; > } > >+ // check FORCEUCASE >+ if (rv && forceucase && (rv) && >+ (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info & SPELL_ORIGCAP)) rv = NULL; >+ > // check forbiddenwords > if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || > TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || > (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL; > > // pfxappnd = prefix of word+i, or NULL > // calculate syllable number of prefix. > // hungarian convention: when syllable number of prefix is more, >@@ -1878,17 +1939,17 @@ struct hentry * AffixMgr::compound_check > } > > numsyllable = oldnumsyllable2; > wordnum = oldwordnum2; > > // perhaps second word is a compound word (recursive call) > if (wordnum < maxwordnum) { > rv = compound_check((st+i),strlen(st+i), wordnum+1, >- numsyllable, maxwordnum, wnum + 1, words, 0, is_sug); >+ numsyllable, maxwordnum, wnum + 1, words, 0, is_sug, info); > if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) || > (scpd != 0 && !cpdpat_check(word, i, rv_first, rv, affixed)))) rv = NULL; > } else { > rv=NULL; > } > if (rv) { > // forbid compound word, if it is a non compound word with typical fault > if (checkcompoundrep || forbiddenword) { >@@ -2020,17 +2081,17 @@ int AffixMgr::compound_check_morph(const > } > // store the pointer of the hash entry > // sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv); > if (HENTRY_DATA(rv)) { > sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv)); > } > } > if (!rv) { >- if (compoundflag && >+ if (compoundflag && !words && > !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { > if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, > FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule && > sfx->getCont() && > ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, > sfx->getContLen())) || (compoundend && > TESTAFF(sfx->getCont(), compoundend, > sfx->getContLen())))) { >@@ -2443,38 +2504,38 @@ struct hentry * AffixMgr::suffix_check ( > circumfix, ep->getContLen())) && > (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) || > // circumfix flag in prefix AND suffix > ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(), > circumfix, ep->getContLen())) && > (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen()))))) && > // fogemorpheme > (in_compound || >- !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && >+ !(se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen())))) && > // needaffix on prefix or first suffix > (cclass || > !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || > (ppfx && !((ep->getCont()) && > TESTAFF(ep->getCont(), needaffix, > ep->getContLen()))) >- ) >- ) { >+ )) { > rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, > needflag, (in_compound ? 0 : onlyincompound)); > if (rv) { > sfx=se; // BUG: sfx not stateless > return rv; > } > } > } > se = se->getNext(); > } >- >+ > // now handle the general case >- unsigned char sp = *((const unsigned char *)(word + len - 1)); >+ if (len == 0) return NULL; // FULLSTRIP >+ unsigned char sp= *((const unsigned char *)(word + len - 1)); > SfxEntry * sptr = sStart[sp]; > > while (sptr) { > if (isRevSubset(sptr->getKey(), word + len - 1, len) > ) { > // suffixes are not allowed in beginning of compounds > if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass > // except when signed with compoundpermitflag flag >@@ -2493,17 +2554,17 @@ struct hentry * AffixMgr::suffix_check ( > !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && > // needaffix on prefix or first suffix > (cclass || > !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || > (ppfx && !((ep->getCont()) && > TESTAFF(ep->getCont(), needaffix, > ep->getContLen()))) > ) >- ) { >+ ) if (in_compound != IN_CPD_END || ppfx || !(sptr->getCont() && TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))) { > rv = sptr->checkword(word,len, sfxopts, ppfx, wlst, > maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound)); > if (rv) { > sfx=sptr; // BUG: sfx not stateless > sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless > if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless > return rv; > } >@@ -2529,18 +2590,19 @@ struct hentry * AffixMgr::suffix_check_t > while (se) { > if (contclasses[se->getFlag()]) > { > rv = se->check_twosfx(word,len, sfxopts, ppfx, needflag); > if (rv) return rv; > } > se = se->getNext(); > } >- >+ > // now handle the general case >+ if (len == 0) return NULL; // FULLSTRIP > unsigned char sp = *((const unsigned char *)(word + len - 1)); > SfxEntry * sptr = sStart[sp]; > > while (sptr) { > if (isRevSubset(sptr->getKey(), word + len - 1, len)) { > if (contclasses[sptr->getFlag()]) > { > rv = sptr->check_twosfx(word,len, sfxopts, ppfx, needflag); >@@ -2591,18 +2653,19 @@ char * AffixMgr::suffix_check_twosfx_mor > mystrcat(result, " ", MAXLNLEN); > mystrcat(result, se->getMorph(), MAXLNLEN); > } else debugflag(result, se->getFlag()); > mystrcat(result, "\n", MAXLNLEN); > } > } > se = se->getNext(); > } >- >+ > // now handle the general case >+ if (len == 0) return NULL; // FULLSTRIP > unsigned char sp = *((const unsigned char *)(word + len - 1)); > SfxEntry * sptr = sStart[sp]; > > while (sptr) { > if (isRevSubset(sptr->getKey(), word + len - 1, len)) { > if (contclasses[sptr->getFlag()]) > { > st = sptr->check_twosfx_morph(word,len, sfxopts, ppfx, needflag); >@@ -2697,18 +2760,19 @@ char * AffixMgr::suffix_check_morph(cons > mystrcat(result, se->getMorph(), MAXLNLEN); > } else debugflag(result, se->getFlag()); > mystrcat(result, "\n", MAXLNLEN); > rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); > } > } > se = se->getNext(); > } >- >+ > // now handle the general case >+ if (len == 0) return NULL; // FULLSTRIP > unsigned char sp = *((const unsigned char *)(word + len - 1)); > SfxEntry * sptr = sStart[sp]; > > while (sptr) { > if (isRevSubset(sptr->getKey(), word + len - 1, len) > ) { > // suffixes are not allowed in beginning of compounds > if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass >@@ -2778,23 +2842,26 @@ struct hentry * AffixMgr::affix_check (c > if (rv) return rv; > > // if still not found check all suffixes > rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound); > > if (havecontclass) { > sfx = NULL; > pfx = NULL; >+ > if (rv) return rv; > // if still not found check all two-level suffixes > rv = suffix_check_twosfx(word, len, 0, NULL, needflag); >+ > if (rv) return rv; > // if still not found check all two-level suffixes > rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag); > } >+ > return rv; > } > > // check if word with affixes is correctly spelled > char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound) > { > char result[MAXLNLEN]; > char * st = NULL; >@@ -3132,16 +3199,31 @@ int AffixMgr::get_fullstrip() const > return fullstrip; > } > > FLAG AffixMgr::get_keepcase() const > { > return keepcase; > } > >+FLAG AffixMgr::get_forceucase() const >+{ >+ return forceucase; >+} >+ >+FLAG AffixMgr::get_warn() const >+{ >+ return warn; >+} >+ >+int AffixMgr::get_forbidwarn() const >+{ >+ return forbidwarn; >+} >+ > int AffixMgr::get_checksharps() const > { > return checksharps; > } > > char * AffixMgr::encode_flag(unsigned short aflag) const > { > return pHMgr->encode_flag(aflag); >@@ -3207,16 +3289,22 @@ FLAG AffixMgr::get_forbiddenword() const > } > > // return the forbidden words control flag > FLAG AffixMgr::get_nosuggest() const > { > return nosuggest; > } > >+// return the forbidden words control flag >+FLAG AffixMgr::get_nongramsuggest() const >+{ >+ return nongramsuggest; >+} >+ > // return the forbidden words flag modify flag > FLAG AffixMgr::get_needaffix() const > { > return needaffix; > } > > // return the onlyincompound flag > FLAG AffixMgr::get_onlyincompound() const >@@ -3285,22 +3373,36 @@ int AffixMgr::have_contclass() const > } > > // return utf8 > int AffixMgr::get_utf8() const > { > return utf8; > } > >-// return nosplitsugs > int AffixMgr::get_maxngramsugs(void) const > { > return maxngramsugs; > } > >+int AffixMgr::get_maxcpdsugs(void) const >+{ >+ return maxcpdsugs; >+} >+ >+int AffixMgr::get_maxdiff(void) const >+{ >+ return maxdiff; >+} >+ >+int AffixMgr::get_onlymaxdiff(void) const >+{ >+ return onlymaxdiff; >+} >+ > // return nosplitsugs > int AffixMgr::get_nosplitsugs(void) const > { > return nosplitsugs; > } > > // return sugswithdots > int AffixMgr::get_sugswithdots(void) const >diff -up8 affixmgr.hxx affixmgr.hxx >--- affixmgr.hxx 2010-12-16 17:20:52 -0500 >+++ affixmgr.hxx 2011-01-26 04:18:52 -0500 >@@ -43,16 +43,17 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr > FLAG compoundpermitflag; > int checkcompounddup; > int checkcompoundrep; > int checkcompoundcase; > int checkcompoundtriple; > int simplifiedtriple; > FLAG forbiddenword; > FLAG nosuggest; >+ FLAG nongramsuggest; > FLAG needaffix; > int cpdmin; > int numrep; > replentry * reptable; > RepList * iconvtable; > RepList * oconvtable; > int nummap; > mapentry * maptable; >@@ -60,16 +61,19 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr > char ** breaktable; > int numcheckcpd; > patentry * checkcpdtable; > int simplifiedcpd; > int numdefcpd; > flagentry * defcpdtable; > phonetable * phone; > int maxngramsugs; >+ int maxcpdsugs; >+ int maxdiff; >+ int onlymaxdiff; > int nosplitsugs; > int sugswithdots; > int cpdwordmax; > int cpdmaxsyllable; > char * cpdvowels; > w_char * cpdvowels_utf16; > int cpdvowels_utf16_len; > char * cpdsyllablenum; >@@ -88,16 +92,19 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr > int ignorechars_utf16_len; > char * version; > char * lang; > int langnum; > FLAG lemma_present; > FLAG circumfix; > FLAG onlyincompound; > FLAG keepcase; >+ FLAG forceucase; >+ FLAG warn; >+ int forbidwarn; > FLAG substandard; > int checksharps; > int fullstrip; > > int havecontclass; // boolean variable > char contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix) > > public: >@@ -147,17 +154,17 @@ public: > const char affixed); > int defcpd_check(hentry *** words, short wnum, hentry * rv, > hentry ** rwords, char all); > int cpdcase_check(const char * word, int len); > inline int candidate_check(const char * word, int len); > void setcminmax(int * cmin, int * cmax, const char * word, int len); > struct hentry * compound_check(const char * word, int len, short wordnum, > short numsyllable, short maxwordnum, short wnum, hentry ** words, >- char hu_mov_rule, char is_sug); >+ char hu_mov_rule, char is_sug, int info); > > int compound_check_morph(const char * word, int len, short wordnum, > short numsyllable, short maxwordnum, short wnum, hentry ** words, > char hu_mov_rule, char ** result, char * partresult); > > struct hentry * lookup(const char * word); > int get_numrep() const; > struct replentry * get_reptable() const; >@@ -176,33 +183,40 @@ public: > unsigned short * get_wordchars_utf16(int * len) const; > char * get_ignore() const; > unsigned short * get_ignore_utf16(int * len) const; > int get_compound() const; > FLAG get_compoundflag() const; > FLAG get_compoundbegin() const; > FLAG get_forbiddenword() const; > FLAG get_nosuggest() const; >+ FLAG get_nongramsuggest() const; > FLAG get_needaffix() const; > FLAG get_onlyincompound() const; > FLAG get_compoundroot() const; > FLAG get_lemma_present() const; > int get_checknum() const; > const char * get_prefix() const; > const char * get_suffix() const; > const char * get_derived() const; > const char * get_version() const; > int have_contclass() const; > int get_utf8() const; > int get_complexprefixes() const; > char * get_suffixed(char ) const; > int get_maxngramsugs() const; >+ int get_maxcpdsugs() const; >+ int get_maxdiff() const; >+ int get_onlymaxdiff() const; > int get_nosplitsugs() const; > int get_sugswithdots(void) const; > FLAG get_keepcase(void) const; >+ FLAG get_forceucase(void) const; >+ FLAG get_warn(void) const; >+ int get_forbidwarn(void) const; > int get_checksharps(void) const; > char * encode_flag(unsigned short aflag) const; > int get_fullstrip() const; > > private: > int parse_file(const char * affpath, const char * key); > int parse_flag(char * line, unsigned short * out, FileMgr * af); > int parse_num(char * line, int * out, FileMgr * af); >diff -up8 atypes.hxx atypes.hxx >--- atypes.hxx 2010-03-03 09:18:44 -0500 >+++ atypes.hxx 2011-01-21 09:58:24 -0500 >@@ -30,16 +30,25 @@ static inline void HUNSPELL_WARNING(FILE > #define aeLONGCOND (1 << 4) > > // compound options > #define IN_CPD_NOT 0 > #define IN_CPD_BEGIN 1 > #define IN_CPD_END 2 > #define IN_CPD_OTHER 3 > >+// info options >+#define SPELL_COMPOUND (1 << 0) >+#define SPELL_FORBIDDEN (1 << 1) >+#define SPELL_ALLCAP (1 << 2) >+#define SPELL_NOCAP (1 << 3) >+#define SPELL_INITCAP (1 << 4) >+#define SPELL_ORIGCAP (1 << 5) >+#define SPELL_WARN (1 << 6) >+ > #define MAXLNLEN 8192 > > #define MINCPDLEN 3 > #define MAXCOMPOUND 10 > #define MAXCONDLEN 20 > #define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char *)) > > #define MAXACC 1000 >diff -up8 csutil.cpp csutil.cpp >--- csutil.cpp 2011-01-06 05:56:18 -0500 >+++ csutil.cpp 2011-01-26 07:31:14 -0500 >@@ -303,19 +303,17 @@ int line_tok(const char * text, char *** > char * p = strchr(dup, breakchar); > while (p) { > linenum++; > *p = '\0'; > p++; > p = strchr(p, breakchar); > } > linenum++; >-// fprintf(stderr, "LINEN:%d %p %p\n", linenum, lines, *lines); > *lines = (char **) malloc(linenum * sizeof(char *)); >-// fprintf(stderr, "hello\n"); > if (!(*lines)) { > free(dup); > return 0; > } > > p = dup; > int l = 0; > for (int i = 0; i < linenum; i++) { >diff -up8 hunspell.cpp hunspell.cpp >--- hunspell.cpp 2010-12-09 15:05:12 -0500 >+++ hunspell.cpp 2011-01-26 04:20:06 -0500 >@@ -364,27 +364,29 @@ int Hunspell::spell(const char * word, i > } else break; > } > if ((i == wl) && (nstate == NNUM)) return 1; > if (!info) info = &info2; else *info = 0; > > switch(captype) { > case HUHCAP: > case HUHINITCAP: >+ *info += SPELL_ORIGCAP; > case NOCAP: { > rv = checkword(cw, info, root); > if ((abbv) && !(rv)) { > memcpy(wspace,cw,wl); > *(wspace+wl) = '.'; > *(wspace+wl+1) = '\0'; > rv = checkword(wspace, info, root); > } > break; > } > case ALLCAP: { >+ *info += SPELL_ORIGCAP; > rv = checkword(cw, info, root); > if (rv) break; > if (abbv) { > memcpy(wspace,cw,wl); > *(wspace+wl) = '.'; > *(wspace+wl+1) = '\0'; > rv = checkword(wspace, info, root); > if (rv) break; >@@ -435,22 +437,23 @@ int Hunspell::spell(const char * word, i > *(wspace+wl2+1) = '\0'; > rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); > } > } > if (rv) break; > } > } > case INITCAP: { >+ *info += SPELL_ORIGCAP; > wl = mkallsmall2(cw, unicw, nc); > memcpy(wspace,cw,(wl+1)); > wl2 = mkinitcap2(cw, unicw, nc); >- if (captype == INITCAP) *info += SPELL_INITCAP; >+ if (captype == INITCAP) *info += SPELL_INITCAP; > rv = checkword(cw, info, root); >- if (captype == INITCAP) *info -= SPELL_INITCAP; >+ if (captype == INITCAP) *info -= SPELL_INITCAP; > // forbid bad capitalization > // (for example, ijs -> Ijs instead of IJs in Dutch) > // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag) > if (*info & SPELL_FORBIDDEN) { > rv = NULL; > break; > } > if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL; >@@ -479,17 +482,25 @@ int Hunspell::spell(const char * word, i > // in INITCAP form, too. > !(pAMgr->get_checksharps() && > ((utf8 && strstr(wspace, "\xC3\x9F")) || > (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL; > break; > } > } > >- if (rv) return 1; >+ if (rv) { >+ if (pAMgr && pAMgr->get_warn() && rv->astr && >+ TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) { >+ *info += SPELL_WARN; >+ if (pAMgr->get_forbidwarn()) return 0; >+ return HUNSPELL_OK_WARN; >+ } >+ return HUNSPELL_OK; >+ } > > // recursive breaking at break points > if (wordbreak) { > char * s; > char r; > int nbr = 0; > wl = strlen(cw); > int numbreak = pAMgr ? pAMgr->get_numbreak() : 0; >@@ -631,23 +642,23 @@ struct hentry * Hunspell::checkword(cons > if (root) { > *root = mystrdup(he->word); > if (*root && complexprefixes) { > if (utf8) reverseword_utf(*root); else reverseword(*root); > } > } > // try check compound word > } else if (pAMgr->get_compound()) { >- he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0); >+ he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0, *info); > // LANG_hu section: `moving rule' with last dash > if ((!he) && (langnum == LANG_hu) && (word[len-1] == '-')) { > char * dup = mystrdup(word); > if (!dup) return NULL; > dup[len-1] = '\0'; >- he = pAMgr->compound_check(dup, len-1, -5, 0, 100, 0, NULL, 1, 0); >+ he = pAMgr->compound_check(dup, len-1, -5, 0, 100, 0, NULL, 1, 0, *info); > free(dup); > } > // end of LANG speficic region > if (he) { > if (root) { > *root = mystrdup(he->word); > if (*root && complexprefixes) { > if (utf8) reverseword_utf(*root); else reverseword(*root); >@@ -688,16 +699,37 @@ int Hunspell::suggest(char*** slst, cons > RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL; > if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv); > else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); > > if (wl == 0) return 0; > int ns = 0; > int capwords = 0; > >+ // check capitalized form for FORCEUCASE >+ if (pAMgr && captype == NOCAP && pAMgr->get_forceucase()) { >+ int info = SPELL_ORIGCAP; >+ char ** wlst; >+ if (checkword(cw, &info, NULL)) { >+ if (*slst) { >+ wlst = *slst; >+ } else { >+ wlst = (char **) malloc(MAXSUGGESTION * sizeof(char *)); >+ if (wlst == NULL) return -1; >+ *slst = wlst; >+ for (int i = 0; i < MAXSUGGESTION; i++) { >+ wlst[i] = NULL; >+ } >+ } >+ wlst[0] = mystrdup(cw); >+ mkinitcap(wlst[0]); >+ return 1; >+ } >+ } >+ > switch(captype) { > case NOCAP: { > ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); > break; > } > > case INITCAP: { > capwords = 1; >@@ -801,17 +833,17 @@ int Hunspell::suggest(char*** slst, cons > } > } > } > } > break; > } > } > >- // LANG_hu section: replace '-' with ' ' in Hungarian >+ // LANG_hu section: replace '-' with ' ' in Hungarian > if (langnum == LANG_hu) { > for (int j=0; j < ns; j++) { > char * pos = strchr((*slst)[j],'-'); > if (pos) { > int info; > char w[MAXWORDUTF8LEN]; > *pos = '\0'; > strcpy(w, (*slst)[j]); >@@ -1463,17 +1495,16 @@ int Hunspell::analyze(char*** slst, cons > } > > if (*result) { > // word reversing wrapper for complex prefixes > if (complexprefixes) { > if (utf8) reverseword_utf(result); else reverseword(result); > } > return line_tok(result, slst, MSEP_REC); >- > } > > // compound word with dash (HU) I18n > char * dash = NULL; > int nresult = 0; > // LANG_hu section: set dash information for suggestions > if (langnum == LANG_hu) dash = (char *) strchr(cw,'-'); > if ((langnum == LANG_hu) && dash) { >diff -up8 hunspell.hxx hunspell.hxx >--- hunspell.hxx 2010-04-16 04:03:36 -0400 >+++ hunspell.hxx 2011-01-21 09:44:00 -0500 >@@ -1,27 +1,24 @@ > #include "hunvisapi.h" > > #include "hashmgr.hxx" > #include "affixmgr.hxx" > #include "suggestmgr.hxx" > #include "langnum.hxx" > >-#define SPELL_COMPOUND (1 << 0) >-#define SPELL_FORBIDDEN (1 << 1) >-#define SPELL_ALLCAP (1 << 2) >-#define SPELL_NOCAP (1 << 3) >-#define SPELL_INITCAP (1 << 4) >- > #define SPELL_XML "<?xml?>" > > #define MAXDIC 20 > #define MAXSUGGESTION 15 > #define MAXSHARPS 5 > >+#define HUNSPELL_OK (1 << 0) >+#define HUNSPELL_OK_WARN (1 << 1) >+ > #ifndef _MYSPELLMGR_HXX_ > #define _MYSPELLMGR_HXX_ > > class LIBHUNSPELL_DLL_EXPORTED Hunspell > { > AffixMgr* pAMgr; > HashMgr* pHMgr[MAXDIC]; > int maxdic; >diff -up8 replist.cpp replist.cpp >--- replist.cpp 2010-10-26 18:17:04 -0400 >+++ replist.cpp 2011-01-26 07:32:14 -0500 >@@ -32,23 +32,21 @@ replentry * RepList::item(int n) { > return dat[n]; > } > > int RepList::near(const char * word) { > int p1 = 0; > int p2 = pos; > while ((p2 - p1) > 1) { > int m = (p1 + p2) / 2; >-// fprintf(stderr, "m: %d p1: %d p2: %d dat: %s\n", m, p1, p2, dat[m]->pattern); > int c = strcmp(word, dat[m]->pattern); > if (c <= 0) { > if (c < 0) p2 = m; else p1 = p2 = m; > } else p1 = m; > } >-// fprintf(stderr, "NEAR: %s (word: %s)\n", dat[p1]->pattern, word); > return p1; > } > > int RepList::match(const char * word, int n) { > if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0) return strlen(dat[n]->pattern); > return 0; > } > >@@ -69,23 +67,21 @@ int RepList::add(char * pat1, char * pat > } else break; > } > return 0; > } > > int RepList::conv(const char * word, char * dest) { > int stl = 0; > int change = 0; >-// for (int i = 0; i < pos; i++) fprintf(stderr, "%d. %s\n", i, dat[i]->pattern); > for (size_t i = 0; i < strlen(word); i++) { > int n = near(word + i); > int l = match(word + i, n); > if (l) { > strcpy(dest + stl, dat[n]->pattern2); > stl += strlen(dat[n]->pattern2); > i += l - 1; > change = 1; > } else dest[stl++] = word[i]; > } > dest[stl] = '\0'; >-// fprintf(stderr, "i: %s o: %s change: %d\n", word, dest, change); > return change; > } >diff -up8 suggestmgr.cpp suggestmgr.cpp >--- suggestmgr.cpp 2011-01-06 05:56:18 -0500 >+++ suggestmgr.cpp 2011-01-26 07:15:08 -0500 >@@ -32,24 +32,27 @@ SuggestMgr::SuggestMgr(const char * trym > > utf8 = 0; > langnum = 0; > complexprefixes = 0; > > maxSug = maxn; > nosplitsugs = 0; > maxngramsugs = MAXNGRAMSUGS; >+ maxcpdsugs = MAXCOMPOUNDSUGS; > > if (pAMgr) { > langnum = pAMgr->get_langnum(); > ckey = pAMgr->get_key_string(); > nosplitsugs = pAMgr->get_nosplitsugs(); > if (pAMgr->get_maxngramsugs() >= 0) > maxngramsugs = pAMgr->get_maxngramsugs(); > utf8 = pAMgr->get_utf8(); >+ if (pAMgr->get_maxcpdsugs() >= 0) >+ maxcpdsugs = pAMgr->get_maxcpdsugs(); > if (!utf8) > { > char * enc = pAMgr->get_encoding(); > csconv = get_current_cs(enc); > free(enc); > } > complexprefixes = pAMgr->get_complexprefixes(); > } >@@ -126,16 +129,17 @@ int SuggestMgr::suggest(char*** slst, co > { > int nocompoundtwowords = 0; > char ** wlst; > w_char word_utf[MAXSWL]; > int wl = 0; > int nsugorig = nsug; > char w2[MAXWORDUTF8LEN]; > const char * word = w; >+ int oldSug = 0; > > // word reversing wrapper for complex prefixes > if (complexprefixes) { > strcpy(w2, w); > if (utf8) reverseword_utf(w2); else reverseword(w2); > word = w2; > } > >@@ -150,111 +154,116 @@ int SuggestMgr::suggest(char*** slst, co > } > > if (utf8) { > wl = u8_u16(word_utf, MAXSWL, word); > } > > for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) { > >+ // limit compound suggestion >+ if (cpdsuggest > 0) oldSug = nsug; >+ > // suggestions for an uppercase word (html -> HTML) > if ((nsug < maxSug) && (nsug > -1)) { > nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > capchars(wlst, word, nsug, cpdsuggest); > } > > // perhaps we made a typical fault of spelling >- if ((nsug < maxSug) && (nsug > -1)) >- nsug = replchars(wlst, word, nsug, cpdsuggest); >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { >+ nsug = replchars(wlst, word, nsug, cpdsuggest); >+ } > > // perhaps we made chose the wrong char from a related set >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = mapchars(wlst, word, nsug, cpdsuggest); > } > > // did we swap the order of chars by mistake >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > swapchar(wlst, word, nsug, cpdsuggest); > } > > // did we swap the order of non adjacent chars by mistake >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > longswapchar(wlst, word, nsug, cpdsuggest); > } > > // did we just hit the wrong key in place of a good char (case and keyboard) >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > badcharkey(wlst, word, nsug, cpdsuggest); > } > > // only suggest compound words when no other suggestion > if ((cpdsuggest == 0) && (nsug > nsugorig)) nocompoundtwowords=1; > > // did we add a char that should not be there >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > extrachar(wlst, word, nsug, cpdsuggest); > } > > > // did we forgot a char >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > forgotchar(wlst, word, nsug, cpdsuggest); > } > > // did we move a char >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > movechar(wlst, word, nsug, cpdsuggest); > } > > // did we just hit the wrong key in place of a good char >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > badchar(wlst, word, nsug, cpdsuggest); > } > > // did we double two characters >- if ((nsug < maxSug) && (nsug > -1)) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { > nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : > doubletwochars(wlst, word, nsug, cpdsuggest); > } > > // perhaps we forgot to hit space and two words ran together >- if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) { >- nsug = twowords(wlst, word, nsug, cpdsuggest); >- } >+ if (!nosplitsugs && (nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { >+ nsug = twowords(wlst, word, nsug, cpdsuggest); >+ } > > } // repeating ``for'' statement compounding support > > if (nsug < 0) { > // we ran out of memory - we should free up as much as possible > for (int i = 0; i < maxSug; i++) > if (wlst[i] != NULL) free(wlst[i]); > free(wlst); > wlst = NULL; > } >- >+ > if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1; > > *slst = wlst; > return nsug; > } > > // generate suggestions for a word with typical mistake > // pass in address of array of char * pointers > #ifdef HUNSPELL_EXPERIMENTAL > int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug) > { > int nocompoundtwowords = 0; > char ** wlst; >+ int oldSug; > > char w2[MAXWORDUTF8LEN]; > const char * word = w; > > // word reversing wrapper for complex prefixes > if (complexprefixes) { > strcpy(w2, w); > if (utf8) reverseword_utf(w2); else reverseword(w2); >@@ -265,29 +274,32 @@ int SuggestMgr::suggest_auto(char*** sls > wlst = *slst; > } else { > wlst = (char **) malloc(maxSug * sizeof(char *)); > if (wlst == NULL) return -1; > } > > for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) { > >+ // limit compound suggestion >+ if (cpdsuggest > 0) oldSug = nsug; >+ > // perhaps we made a typical fault of spelling > if ((nsug < maxSug) && (nsug > -1)) > nsug = replchars(wlst, word, nsug, cpdsuggest); > > // perhaps we made chose the wrong char from a related set >- if ((nsug < maxSug) && (nsug > -1)) >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) > nsug = mapchars(wlst, word, nsug, cpdsuggest); > > if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; > > // perhaps we forgot to hit space and two words ran together > >- if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) { >+ if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs)) && check_forbidden(word, strlen(word))) { > nsug = twowords(wlst, word, nsug, cpdsuggest); > } > > } // repeating ``for'' statement compounding support > > if (nsug < 0) { > for (int i=0;i<maxSug; i++) > if (wlst[i] != NULL) free(wlst[i]); >@@ -1007,17 +1019,17 @@ int SuggestMgr::ngsuggest(char** wlst, c > for (i = 0; i < MAX_ROOTS; i++) { > roots[i] = NULL; > scores[i] = -100 * i; > rootsphon[i] = NULL; > scoresphon[i] = -100 * i; > } > lp = MAX_ROOTS - 1; > lpphon = MAX_ROOTS - 1; >- scphon = scoresphon[MAX_ROOTS-1]; >+ scphon = -20000; > > char w2[MAXWORDUTF8LEN]; > char f[MAXSWUTF8L]; > char * word = w; > > // word reversing wrapper for complex prefixes > if (complexprefixes) { > strcpy(w2, w); >@@ -1038,58 +1050,80 @@ int SuggestMgr::ngsuggest(char** wlst, c > } > > struct hentry* hp = NULL; > int col = -1; > phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL; > char target[MAXSWUTF8L]; > char candidate[MAXSWUTF8L]; > if (ph) { >- strcpy(candidate, word); >- mkallcap(candidate, csconv); >+ if (utf8) { >+ w_char _w[MAXSWL]; >+ int _wl = u8_u16(_w, MAXSWL, word); >+ mkallcap_utf(_w, _wl, langnum); >+ u16_u8(candidate, MAXSWUTF8L, _w, _wl); >+ } else { >+ strcpy(candidate, word); >+ mkallcap(candidate, csconv); >+ } > phonet(candidate, target, n, *ph); > } > >+ FLAG forbiddenword = pAMgr ? pAMgr->get_forbiddenword() : FLAG_NULL; >+ FLAG nosuggest = pAMgr ? pAMgr->get_nosuggest() : FLAG_NULL; >+ FLAG nongramsuggest = pAMgr ? pAMgr->get_nongramsuggest() : FLAG_NULL; >+ FLAG onlyincompound = pAMgr ? pAMgr->get_onlyincompound() : FLAG_NULL; >+ > for (i = 0; i < md; i++) { > while (0 != (hp = (pHMgr[i])->walk_hashtable(col, hp))) { > if ((hp->astr) && (pAMgr) && >- (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) || >+ (TESTAFF(hp->astr, forbiddenword, hp->alen) || > TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) || >- TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) || >- TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue; >+ TESTAFF(hp->astr, nosuggest, hp->alen) || >+ TESTAFF(hp->astr, nongramsuggest, hp->alen) || >+ TESTAFF(hp->astr, onlyincompound, hp->alen))) continue; > > sc = ngram(3, word, HENTRY_WORD(hp), NGRAM_LONGER_WORSE + NGRAM_LOWERING) + > leftcommonsubstring(word, HENTRY_WORD(hp)); > > // check special pronounciation > if ((hp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) { > int sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE + NGRAM_LOWERING) + >- leftcommonsubstring(word, f); >+ + leftcommonsubstring(word, f); > if (sc2 > sc) sc = sc2; > } > >+ scphon = -20000; > if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) { >- char target2[MAXSWUTF8L]; >+ char target2[MAXSWUTF8L]; >+ if (utf8) { >+ w_char _w[MAXSWL]; >+ int _wl = u8_u16(_w, MAXSWL, HENTRY_WORD(hp)); >+ mkallcap_utf(_w, _wl, langnum); >+ u16_u8(candidate, MAXSWUTF8L, _w, _wl); >+ } else { > strcpy(candidate, HENTRY_WORD(hp)); > mkallcap(candidate, csconv); >- phonet(candidate, target2, -1, *ph); >- scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE); >+ } >+ phonet(candidate, target2, -1, *ph); >+ scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE); > } > > if (sc > scores[lp]) { > scores[lp] = sc; > roots[lp] = hp; > lval = sc; > for (j=0; j < MAX_ROOTS; j++) > if (scores[j] < lval) { > lp = j; > lval = scores[j]; > } > } > >+ > if (scphon > scoresphon[lpphon]) { > scoresphon[lpphon] = scphon; > rootsphon[lpphon] = HENTRY_WORD(hp); > lval = scphon; > for (j=0; j < MAX_ROOTS; j++) > if (scoresphon[j] < lval) { > lpphon = j; > lval = scoresphon[j]; >@@ -1142,17 +1176,17 @@ int SuggestMgr::ngsuggest(char** wlst, c > int nw = pAMgr->expand_rootword(glst, MAX_WORDS, HENTRY_WORD(rp), rp->blen, > rp->astr, rp->alen, word, nc, > ((rp->var & H_OPT_PHON) ? copy_field(f, HENTRY_DATA(rp), MORPH_PHON) : NULL)); > > for (int k = 0; k < nw ; k++) { > sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) + > leftcommonsubstring(word, glst[k].word); > >- if ((sc > thresh)) { >+ if (sc > thresh) { > if (sc > gscore[lp]) { > if (guess[lp]) { > free (guess[lp]); > if (guessorig[lp]) { > free(guessorig[lp]); > guessorig[lp] = NULL; > } > } >@@ -1165,17 +1199,17 @@ int SuggestMgr::ngsuggest(char** wlst, c > lp = j; > lval = gscore[j]; > } > } else { > free(glst[k].word); > if (glst[k].orig) free(glst[k].orig); > } > } else { >- free(glst[k].word); >+ free(glst[k].word); > if (glst[k].orig) free(glst[k].orig); > } > } > } > } > free(glst); > > // now we are done generating guesses >@@ -1184,16 +1218,23 @@ int SuggestMgr::ngsuggest(char** wlst, c > > bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); > if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS); > > // weight suggestions with a similarity index, based on > // the longest common subsequent algorithm and resort > > int is_swap; >+ int re; >+ float fact = 1.0; >+ if (pAMgr) { >+ int maxd = pAMgr->get_maxdiff(); >+ if (maxd >= 0) fact = (10.0 - maxd)/5.0; >+ } >+ > for (i=0; i < MAX_GUESS; i++) { > if (guess[i]) { > // lowering guess[i] > char gl[MAXSWUTF8L]; > int len; > if (utf8) { > w_char _w[MAXSWL]; > len = u8_u16(_w, MAXSWL, guess[i]); >@@ -1207,27 +1248,33 @@ int SuggestMgr::ngsuggest(char** wlst, c > > int _lcs = lcslen(word, gl); > > // same characters with different casing > if ((n == len) && (n == _lcs)) { > gscore[i] += 2000; > break; > } >- >- // heuristic weigthing of ngram scores >- gscore[i] += >+ // using 2-gram instead of 3, and other weightening >+ gscore[i] = > // length of longest common subsequent minus length difference > 2 * _lcs - abs((int) (n - len)) + > // weight length of the left common substring > leftcommonsubstring(word, gl) + > // weight equal character positions >- ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) + >+ (commoncharacterpositions(word, gl, &is_swap) ? 1: 0) + > // swap character (not neighboring) >- ((is_swap) ? 1000 : 0); >+ ((is_swap) ? 10 : 0) + >+ // ngram >+ ngram(4, word, gl, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) + >+ // weighted ngrams >+ (re = ngram(2, word, gl, NGRAM_ANY_MISMATCH + NGRAM_LOWERING + NGRAM_WEIGHTED)) + >+ (re += ngram(2, gl, word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING + NGRAM_WEIGHTED)) + >+ // different limit for dictionaries with PHONE rules >+ (ph ? (re < len * fact ? -1000 : 0) : (re < (n + len)*fact? -1000 : 0)); > } > } > > bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); > > // phonetic version > if (ph) for (i=0; i < MAX_ROOTS; i++) { > if (rootsphon[i]) { >@@ -1258,17 +1305,25 @@ int SuggestMgr::ngsuggest(char** wlst, c > int oldns = ns; > > int same = 0; > for (i=0; i < MAX_GUESS; i++) { > if (guess[i]) { > if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) { > int unique = 1; > // leave only excellent suggestions, if exists >- if (gscore[i] > 1000) same = 1; >+ if (gscore[i] > 1000) same = 1; else if (gscore[i] < -100) { >+ same = 1; >+ // keep the best ngram suggestions, unless in ONLYMAXDIFF mode >+ if (ns > oldns || (pAMgr && pAMgr->get_onlymaxdiff())) { >+ free(guess[i]); >+ if (guessorig[i]) free(guessorig[i]); >+ continue; >+ } >+ } > for (j = 0; j < ns; j++) { > // don't suggest previous suggestions or a previous suggestion with prefixes or affixes > if ((!guessorig[i] && strstr(guess[i], wlst[j])) || > (guessorig[i] && strstr(guessorig[i], wlst[j])) || > // check forbidden words > !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0; > } > if (unique) { >@@ -1303,45 +1358,49 @@ int SuggestMgr::ngsuggest(char** wlst, c > wlst[ns++] = mystrdup(rootsphon[i]); > if (!wlst[ns - 1]) return ns - 1; > } > } > } > } > > if (nonbmp) utf8 = 1; >+// if (specpron) free(specpron); > return ns; > } > > > // see if a candidate suggestion is spelled correctly > // needs to check both root words and words with affixes > > // obsolote MySpell-HU modifications: > // return value 2 and 3 marks compounding with hyphen (-) > // `3' marks roots without suffix > int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit) > { > struct hentry * rv=NULL; >+ struct hentry * rv2=NULL; > int nosuffix = 0; > > // check time limit > if (timer) { > (*timer)--; > if (!(*timer) && timelimit) { > if ((clock() - *timelimit) > TIMELIMIT) return 0; > *timer = MAXPLUSTIMER; > } > } > > if (pAMgr) { > if (cpdsuggest==1) { > if (pAMgr->get_compound()) { >- rv = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 1); //EXT >- if (rv) return 3; // XXX obsolote categorisation >+ rv = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 1, 0); //EXT >+ if (rv && (!(rv2 = pAMgr->lookup(word)) || !rv2->astr || >+ !(TESTAFF(rv2->astr,pAMgr->get_forbiddenword(),rv2->alen) || >+ TESTAFF(rv2->astr,pAMgr->get_nosuggest(),rv2->alen)))) return 3; // XXX obsolote categorisation + only ICONV needs affix flag check? > } > return 0; > } > > rv = pAMgr->lookup(word); > > if (rv) { > if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) >@@ -1663,60 +1722,72 @@ char * SuggestMgr::suggest_gen(char ** d > > // generate an n-gram score comparing s1 and s2 > int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt) > { > int nscore = 0; > int ns; > int l1; > int l2; >+ int test = 0; > > if (utf8) { > w_char su1[MAXSWL]; > w_char su2[MAXSWL]; > l1 = u8_u16(su1, MAXSWL, s1); > l2 = u8_u16(su2, MAXSWL, s2); > if ((l2 <= 0) || (l1 == -1)) return 0; > // lowering dictionary word > if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum); > for (int j = 1; j <= n; j++) { > ns = 0; > for (int i = 0; i <= (l1-j); i++) { >+ int k = 0; > for (int l = 0; l <= (l2-j); l++) { >- int k; >- for (k = 0; (k < j); k++) { >+ for (k = 0; k < j; k++) { > w_char * c1 = su1 + i + k; > w_char * c2 = su2 + l + k; > if ((c1->l != c2->l) || (c1->h != c2->h)) break; > } > if (k == j) { >- ns++; >+ ns++; > break; >- } >- } >+ } >+ } >+ if (k != j && opt & NGRAM_WEIGHTED) { >+ ns--; >+ test++; >+ if (i == 0 || i == l1-j) ns--; // side weight >+ } > } > nscore = nscore + ns; >- if (ns < 2) break; >+ if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break; > } > } else { > l2 = strlen(s2); > if (l2 == 0) return 0; > l1 = strlen(s1); > char *t = mystrdup(s2); > if (opt & NGRAM_LOWERING) mkallsmall(t, csconv); > for (int j = 1; j <= n; j++) { > ns = 0; > for (int i = 0; i <= (l1-j); i++) { > char c = *(s1 + i + j); > *(s1 + i + j) = '\0'; >- if (strstr(t,(s1+i))) ns++; >+ if (strstr(t,(s1+i))) { >+ ns++; >+ } else if (opt & NGRAM_WEIGHTED) { >+ ns--; >+test++; >+ if (i == 0 || i == l1-j) ns--; // side weight >+ } > *(s1 + i + j ) = c; > } > nscore = nscore + ns; >- if (ns < 2) break; >+ if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break; > } > free(t); > } > > ns = 0; > if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2; > if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2; > ns = (nscore - ((ns > 0) ? ns : 0)); >diff -up8 suggestmgr.hxx suggestmgr.hxx >--- suggestmgr.hxx 2010-04-15 07:22:10 -0400 >+++ suggestmgr.hxx 2011-01-21 16:00:00 -0500 >@@ -3,25 +3,27 @@ > > #define MAXSWL 100 > #define MAXSWUTF8L (MAXSWL * 4) > #define MAX_ROOTS 100 > #define MAX_WORDS 100 > #define MAX_GUESS 200 > #define MAXNGRAMSUGS 4 > #define MAXPHONSUGS 2 >+#define MAXCOMPOUNDSUGS 3 > > // timelimit: max ~1/4 sec (process time on Linux) for a time consuming function > #define TIMELIMIT (CLOCKS_PER_SEC >> 2) > #define MINTIMER 100 > #define MAXPLUSTIMER 100 > > #define NGRAM_LONGER_WORSE (1 << 0) > #define NGRAM_ANY_MISMATCH (1 << 1) > #define NGRAM_LOWERING (1 << 2) >+#define NGRAM_WEIGHTED (1 << 3) > > #include "hunvisapi.h" > > #include "atypes.hxx" > #include "affixmgr.hxx" > #include "hashmgr.hxx" > #include "langnum.hxx" > #include <time.h> >@@ -40,16 +42,17 @@ class LIBHUNSPELL_DLL_EXPORTED SuggestMg > > AffixMgr* pAMgr; > int maxSug; > struct cs_info * csconv; > int utf8; > int langnum; > int nosplitsugs; > int maxngramsugs; >+ int maxcpdsugs; > int complexprefixes; > > > public: > SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr); > ~SuggestMgr(); > > int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
|
Review
Attachments on
bug 620626
:
499654
|
501038
|
501297
|
501846
|
507294
|
507295
|
509332
|
510818