summaryrefslogtreecommitdiff
path: root/libs/hunspell/src/hunspell.c++
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hunspell/src/hunspell.c++')
-rw-r--r--libs/hunspell/src/hunspell.c++1554
1 files changed, 541 insertions, 1013 deletions
diff --git a/libs/hunspell/src/hunspell.c++ b/libs/hunspell/src/hunspell.c++
index 726c72931a..f7c1581087 100644
--- a/libs/hunspell/src/hunspell.c++
+++ b/libs/hunspell/src/hunspell.c++
@@ -85,6 +85,9 @@
#include <limits>
#include <string>
+#define MAXWORDLEN 176
+#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
+
Hunspell::Hunspell(const char* affpath, const char* dpath, const char* key) {
encoding = NULL;
csconv = NULL;
@@ -158,14 +161,16 @@ int Hunspell::add_dic(const char* dpath, const char* key) {
// set the capitalization type
// return the length of the "cleaned" (and UTF-8 encoded) word
-int Hunspell::cleanword2(char* dest,
+size_t Hunspell::cleanword2(std::string& dest,
+ std::vector<w_char>& dest_utf,
const char* src,
- w_char* dest_utf,
int* nc,
int* pcaptype,
- int* pabbrev) {
- unsigned char* p = (unsigned char*)dest;
- const unsigned char* q = (const unsigned char*)src;
+ size_t* pabbrev) {
+ dest.clear();
+ dest_utf.clear();
+
+ const char* q = src;
// first skip over any leading blanks
while ((*q != '\0') && (*q == ' '))
@@ -173,7 +178,7 @@ int Hunspell::cleanword2(char* dest,
// now strip off any trailing periods (recording their presence)
*pabbrev = 0;
- int nl = strlen((const char*)q);
+ int nl = strlen(q);
while ((nl > 0) && (*(q + nl - 1) == '.')) {
nl--;
(*pabbrev)++;
@@ -182,35 +187,26 @@ int Hunspell::cleanword2(char* dest,
// if no characters are left it can't be capitalized
if (nl <= 0) {
*pcaptype = NOCAP;
- *p = '\0';
return 0;
}
- strncpy(dest, (char*)q, nl);
- *(dest + nl) = '\0';
- nl = strlen(dest);
+ dest.append(q, nl);
+ nl = dest.size();
if (utf8) {
- *nc = u8_u16(dest_utf, MAXWORDLEN, dest);
- // don't check too long words
- if (*nc >= MAXWORDLEN)
- return 0;
- if (*nc == -1) { // big Unicode character (non BMP area)
- *pcaptype = NOCAP;
- return nl;
- }
- *pcaptype = get_captype_utf8(dest_utf, *nc, langnum);
+ *nc = u8_u16(dest_utf, dest);
+ *pcaptype = get_captype_utf8(dest_utf, langnum);
} else {
- *pcaptype = get_captype(dest, nl, csconv);
+ *pcaptype = get_captype(dest, csconv);
*nc = nl;
}
return nl;
}
-int Hunspell::cleanword(char* dest,
+void Hunspell::cleanword(std::string& dest,
const char* src,
int* pcaptype,
int* pabbrev) {
- unsigned char* p = (unsigned char*)dest;
+ dest.clear();
const unsigned char* q = (const unsigned char*)src;
int firstcap = 0;
@@ -229,8 +225,7 @@ int Hunspell::cleanword(char* dest,
// if no characters are left it can't be capitalized
if (nl <= 0) {
*pcaptype = NOCAP;
- *p = '\0';
- return 0;
+ return;
}
// now determine the capitalization type of the first nl letters
@@ -245,27 +240,25 @@ int Hunspell::cleanword(char* dest,
ncap++;
if (csconv[(*q)].cupper == csconv[(*q)].clower)
nneutral++;
- *p++ = *q++;
+ dest.push_back(*q++);
nl--;
}
// remember to terminate the destination string
- *p = '\0';
- firstcap = csconv[(unsigned char)(*dest)].ccase;
+ firstcap = csconv[static_cast<unsigned char>(dest[0])].ccase;
} else {
- unsigned short idx;
- w_char t[MAXWORDLEN];
- nc = u8_u16(t, MAXWORDLEN, src);
- for (int i = 0; i < nc; i++) {
- idx = (t[i].h << 8) + t[i].l;
+ std::vector<w_char> t;
+ u8_u16(t, src);
+ for (size_t i = 0; i < t.size(); ++i) {
+ unsigned short idx = (t[i].h << 8) + t[i].l;
unsigned short low = unicodetolower(idx, langnum);
if (idx != low)
ncap++;
if (unicodetoupper(idx, langnum) == low)
nneutral++;
}
- u16_u8(dest, MAXWORDUTF8LEN, t, nc);
+ u16_u8(dest, t);
if (ncap) {
- idx = (t[0].h << 8) + t[0].l;
+ unsigned short idx = (t[0].h << 8) + t[0].l;
firstcap = (idx != unicodetolower(idx, langnum));
}
}
@@ -282,117 +275,60 @@ int Hunspell::cleanword(char* dest,
} else {
*pcaptype = HUHCAP;
}
- return strlen(dest);
}
-void Hunspell::mkallcap(char* p) {
+void Hunspell::mkallcap(std::string& u8) {
if (utf8) {
- w_char u[MAXWORDLEN];
- int nc = u8_u16(u, MAXWORDLEN, p);
- unsigned short idx;
- for (int i = 0; i < nc; i++) {
- idx = (u[i].h << 8) + u[i].l;
- if (idx != unicodetoupper(idx, langnum)) {
- u[i].h = (unsigned char)(unicodetoupper(idx, langnum) >> 8);
- u[i].l = (unsigned char)(unicodetoupper(idx, langnum) & 0x00FF);
- }
- }
- u16_u8(p, MAXWORDUTF8LEN, u, nc);
+ std::vector<w_char> u16;
+ u8_u16(u16, u8);
+ ::mkallcap_utf(u16, langnum);
+ u16_u8(u8, u16);
} else {
- while (*p != '\0') {
- *p = csconv[((unsigned char)*p)].cupper;
- p++;
- }
- }
-}
-
-int Hunspell::mkallcap2(char* p, w_char* u, int nc) {
- if (utf8) {
- unsigned short idx;
- for (int i = 0; i < nc; i++) {
- idx = (u[i].h << 8) + u[i].l;
- unsigned short up = unicodetoupper(idx, langnum);
- if (idx != up) {
- u[i].h = (unsigned char)(up >> 8);
- u[i].l = (unsigned char)(up & 0x00FF);
- }
- }
- u16_u8(p, MAXWORDUTF8LEN, u, nc);
- return strlen(p);
- } else {
- while (*p != '\0') {
- *p = csconv[((unsigned char)*p)].cupper;
- p++;
- }
- }
- return nc;
-}
-
-void Hunspell::mkallsmall(char* p) {
- while (*p != '\0') {
- *p = csconv[((unsigned char)*p)].clower;
- p++;
+ ::mkallcap(u8, csconv);
}
}
-int Hunspell::mkallsmall2(char* p, w_char* u, int nc) {
+int Hunspell::mkallsmall2(std::string& u8, std::vector<w_char>& u16) {
if (utf8) {
- unsigned short idx;
- for (int i = 0; i < nc; i++) {
- idx = (u[i].h << 8) + u[i].l;
- unsigned short low = unicodetolower(idx, langnum);
- if (idx != low) {
- u[i].h = (unsigned char)(low >> 8);
- u[i].l = (unsigned char)(low & 0x00FF);
- }
- }
- u16_u8(p, MAXWORDUTF8LEN, u, nc);
- return strlen(p);
+ ::mkallsmall_utf(u16, langnum);
+ u16_u8(u8, u16);
} else {
- while (*p != '\0') {
- *p = csconv[((unsigned char)*p)].clower;
- p++;
- }
+ ::mkallsmall(u8, csconv);
}
- return nc;
+ return u8.size();
}
// convert UTF-8 sharp S codes to latin 1
-char* Hunspell::sharps_u8_l1(char* dest, char* source) {
- char* p = dest;
- *p = *source;
- for (p++, source++; *(source - 1); p++, source++) {
- *p = *source;
- if (*source == '\x9F')
- *--p = '\xDF';
- }
+std::string Hunspell::sharps_u8_l1(const std::string& source) {
+ std::string dest(source);
+ mystrrep(dest, "\xC3\x9F", "\xDF");
return dest;
}
// recursive search for right ss - sharp s permutations
-hentry* Hunspell::spellsharps(char* base,
- char* pos,
+hentry* Hunspell::spellsharps(std::string& base,
+ size_t n_pos,
int n,
int repnum,
- char* tmp,
int* info,
char** root) {
- pos = strstr(pos, "ss");
- if (pos && (n < MAXSHARPS)) {
- *pos = '\xC3';
- *(pos + 1) = '\x9F';
- hentry* h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root);
+ size_t pos = base.find("ss", n_pos);
+ if (pos != std::string::npos && (n < MAXSHARPS)) {
+ base[pos] = '\xC3';
+ base[pos + 1] = '\x9F';
+ hentry* h = spellsharps(base, pos + 2, n + 1, repnum + 1, info, root);
if (h)
return h;
- *pos = 's';
- *(pos + 1) = 's';
- h = spellsharps(base, pos + 2, n + 1, repnum, tmp, info, root);
+ base[pos] = 's';
+ base[pos + 1] = 's';
+ h = spellsharps(base, pos + 2, n + 1, repnum, info, root);
if (h)
return h;
} else if (repnum > 0) {
if (utf8)
- return checkword(base, info, root);
- return checkword(sharps_u8_l1(tmp, base), info, root);
+ return checkword(base.c_str(), info, root);
+ std::string tmp(sharps_u8_l1(base));
+ return checkword(tmp.c_str(), info, root);
}
return NULL;
}
@@ -403,7 +339,7 @@ int Hunspell::is_keepcase(const hentry* rv) {
}
/* insert a word to the beginning of the suggestion array and return ns */
-int Hunspell::insert_sug(char*** slst, char* word, int ns) {
+int Hunspell::insert_sug(char*** slst, const char* word, int ns) {
if (!*slst)
return ns;
char* dup = mystrdup(word);
@@ -421,11 +357,6 @@ int Hunspell::insert_sug(char*** slst, char* word, int ns) {
int Hunspell::spell(const char* word, int* info, char** root) {
struct hentry* rv = NULL;
- // need larger vector. For example, Turkish capital letter I converted a
- // 2-byte UTF-8 character (dotless i) by mkallsmall.
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
- w_char unicw[MAXWORDLEN];
int info2 = 0;
if (!info)
@@ -437,7 +368,6 @@ int Hunspell::spell(const char* word, int* info, char** root) {
if (strcmp(word, SPELL_XML) == 0)
return 1;
int nc = strlen(word);
- int wl2 = 0;
if (utf8) {
if (nc >= MAXWORDUTF8LEN)
return 0;
@@ -445,19 +375,26 @@ int Hunspell::spell(const char* word, int* info, char** root) {
if (nc >= MAXWORDLEN)
return 0;
}
- int captype = 0;
- int abbv = 0;
- int wl = 0;
+ int captype = NOCAP;
+ size_t abbv = 0;
+ size_t wl = 0;
+
+ std::string scw;
+ std::vector<w_char> sunicw;
// input conversion
RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace, MAXWORDUTF8LEN) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
- else
- wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+ {
+ std::string wspace;
+
+ int convstatus = rl ? rl->conv(word, wspace) : 0;
+ if (convstatus < 0)
+ return 0;
+ else if (convstatus > 0)
+ wl = cleanword2(scw, sunicw, wspace.c_str(), &nc, &captype, &abbv);
+ else
+ wl = cleanword2(scw, sunicw, word, &nc, &captype, &abbv);
+ }
#ifdef MOZILLA_CLIENT
// accept the abbreviated words without dots
@@ -474,12 +411,12 @@ int Hunspell::spell(const char* word, int* info, char** root) {
// "..", "--" etc.)
enum { NBEGIN, NNUM, NSEP };
int nstate = NBEGIN;
- int i;
+ size_t i;
for (i = 0; (i < wl); i++) {
- if ((cw[i] <= '9') && (cw[i] >= '0')) {
+ if ((scw[i] <= '9') && (scw[i] >= '0')) {
nstate = NNUM;
- } else if ((cw[i] == ',') || (cw[i] == '.') || (cw[i] == '-')) {
+ } else if ((scw[i] == ',') || (scw[i] == '.') || (scw[i] == '-')) {
if ((nstate == NSEP) || (i == 0))
break;
nstate = NSEP;
@@ -496,75 +433,75 @@ int Hunspell::spell(const char* word, int* info, char** root) {
*info += SPELL_ORIGCAP;
/* FALLTHROUGH */
case NOCAP:
- rv = checkword(cw, info, root);
+ rv = checkword(scw.c_str(), info, root);
if ((abbv) && !(rv)) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- rv = checkword(wspace, info, root);
+ std::string u8buffer(scw);
+ u8buffer.push_back('.');
+ rv = checkword(u8buffer.c_str(), info, root);
}
break;
case ALLCAP: {
*info += SPELL_ORIGCAP;
- rv = checkword(cw, info, root);
+ rv = checkword(scw.c_str(), info, root);
if (rv)
break;
if (abbv) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- rv = checkword(wspace, info, root);
+ std::string u8buffer(scw);
+ u8buffer.push_back('.');
+ rv = checkword(u8buffer.c_str(), info, root);
if (rv)
break;
}
// Spec. prefix handling for Catalan, French, Italian:
// prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
- if (pAMgr && strchr(cw, '\'')) {
- mkallsmall2(cw, unicw, nc);
- // There are no really sane circumstances where this could fail,
- // but anyway...
- if (char* apostrophe = strchr(cw, '\'')) {
+ size_t apos = pAMgr ? scw.find('\'') : std::string::npos;
+ if (apos != std::string::npos) {
+ mkallsmall2(scw, sunicw);
+ //conversion may result in string with different len to pre-mkallsmall2
+ //so re-scan
+ if (apos != std::string::npos && apos < scw.size() - 1) {
+ std::string part1 = scw.substr(0, apos+1);
+ std::string part2 = scw.substr(apos+1);
if (utf8) {
- w_char tmpword[MAXWORDLEN];
- *apostrophe = '\0';
- wl2 = u8_u16(tmpword, MAXWORDLEN, cw);
- *apostrophe = '\'';
- if (wl2 >= 0 && wl2 < nc) {
- mkinitcap2(apostrophe + 1, unicw + wl2 + 1, nc - wl2 - 1);
- rv = checkword(cw, info, root);
- if (rv)
- break;
- }
+ std::vector<w_char> part1u, part2u;
+ u8_u16(part1u, part1);
+ u8_u16(part2u, part2);
+ mkinitcap2(part2, part2u);
+ scw = part1 + part2;
+ sunicw = part1u;
+ sunicw.insert(sunicw.end(), part2u.begin(), part2u.end());
+ rv = checkword(scw.c_str(), info, root);
+ if (rv)
+ break;
} else {
- mkinitcap2(apostrophe + 1, unicw, nc);
- rv = checkword(cw, info, root);
+ mkinitcap2(part2, sunicw);
+ scw = part1 + part2;
+ rv = checkword(scw.c_str(), info, root);
if (rv)
break;
}
+ mkinitcap2(scw, sunicw);
+ rv = checkword(scw.c_str(), info, root);
+ if (rv)
+ break;
}
- mkinitcap2(cw, unicw, nc);
- rv = checkword(cw, info, root);
- if (rv)
- break;
}
- if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) {
- char tmpword[MAXWORDUTF8LEN];
- wl = mkallsmall2(cw, unicw, nc);
- memcpy(wspace, cw, (wl + 1));
- rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+ if (pAMgr && pAMgr->get_checksharps() && scw.find("SS") != std::string::npos) {
+
+ mkallsmall2(scw, sunicw);
+ std::string u8buffer(scw);
+ rv = spellsharps(u8buffer, 0, 0, 0, info, root);
if (!rv) {
- wl2 = mkinitcap2(cw, unicw, nc);
- rv = spellsharps(cw, cw, 0, 0, tmpword, info, root);
+ mkinitcap2(scw, sunicw);
+ rv = spellsharps(scw, 0, 0, 0, info, root);
}
if ((abbv) && !(rv)) {
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+ u8buffer.push_back('.');
+ rv = spellsharps(u8buffer, 0, 0, 0, info, root);
if (!rv) {
- memcpy(wspace, cw, wl2);
- *(wspace + wl2) = '.';
- *(wspace + wl2 + 1) = '\0';
- rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+ u8buffer = std::string(scw);
+ u8buffer.push_back('.');
+ rv = spellsharps(u8buffer, 0, 0, 0, info, root);
}
}
if (rv)
@@ -572,13 +509,14 @@ int Hunspell::spell(const char* word, int* info, char** root) {
}
}
case INITCAP: {
+
*info += SPELL_ORIGCAP;
- wl = mkallsmall2(cw, unicw, nc);
- memcpy(wspace, cw, (wl + 1));
- wl2 = mkinitcap2(cw, unicw, nc);
+ mkallsmall2(scw, sunicw);
+ std::string u8buffer(scw);
+ mkinitcap2(scw, sunicw);
if (captype == INITCAP)
*info += SPELL_INITCAP;
- rv = checkword(cw, info, root);
+ rv = checkword(scw.c_str(), info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
// forbid bad capitalization
@@ -593,18 +531,16 @@ int Hunspell::spell(const char* word, int* info, char** root) {
if (rv)
break;
- rv = checkword(wspace, info, root);
+ rv = checkword(u8buffer.c_str(), info, root);
if (abbv && !rv) {
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- rv = checkword(wspace, info, root);
+ u8buffer.push_back('.');
+ rv = checkword(u8buffer.c_str(), info, root);
if (!rv) {
- memcpy(wspace, cw, wl2);
- *(wspace + wl2) = '.';
- *(wspace + wl2 + 1) = '\0';
+ u8buffer = scw;
+ u8buffer.push_back('.');
if (captype == INITCAP)
*info += SPELL_INITCAP;
- rv = checkword(wspace, info, root);
+ rv = checkword(u8buffer.c_str(), info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
if (rv && is_keepcase(rv) && (captype == ALLCAP))
@@ -617,8 +553,8 @@ int Hunspell::spell(const char* word, int* info, char** root) {
// if CHECKSHARPS: KEEPCASE words with \xDF are allowed
// in INITCAP form, too.
!(pAMgr->get_checksharps() &&
- ((utf8 && strstr(wspace, "\xC3\x9F")) ||
- (!utf8 && strchr(wspace, '\xDF'))))))
+ ((utf8 && u8buffer.find("\xC3\x9F") != std::string::npos) ||
+ (!utf8 && u8buffer.find('\xDF') != std::string::npos)))))
rv = NULL;
break;
}
@@ -637,67 +573,66 @@ int Hunspell::spell(const char* word, int* info, char** root) {
// recursive breaking at break points
if (wordbreak) {
- char* s;
- char r;
+
int nbr = 0;
- wl = strlen(cw);
+ wl = scw.size();
int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
// calculate break points for recursion limit
for (int j = 0; j < numbreak; j++) {
- s = cw;
- do {
- s = (char*)strstr(s, wordbreak[j]);
- if (s) {
- nbr++;
- s++;
- }
- } while (s);
+ size_t len = strlen(wordbreak[j]);
+ size_t pos = 0;
+ while ((pos = scw.find(wordbreak[j], pos, len)) != std::string::npos) {
+ ++nbr;
+ pos += len;
+ }
}
if (nbr >= 10)
return 0;
// check boundary patterns (^begin and end$)
for (int j = 0; j < numbreak; j++) {
- int plen = strlen(wordbreak[j]);
+ size_t plen = strlen(wordbreak[j]);
if (plen == 1 || plen > wl)
continue;
+
if (wordbreak[j][0] == '^' &&
- strncmp(cw, wordbreak[j] + 1, plen - 1) == 0 && spell(cw + plen - 1))
+ scw.compare(0, plen - 1, wordbreak[j] + 1, plen -1) == 0 && spell(scw.c_str() + plen - 1))
return 1;
+
if (wordbreak[j][plen - 1] == '$' &&
- strncmp(cw + wl - plen + 1, wordbreak[j], plen - 1) == 0) {
- r = cw[wl - plen + 1];
- cw[wl - plen + 1] = '\0';
- if (spell(cw))
+ scw.compare(wl - plen + 1, plen - 1, wordbreak[j], plen - 1) == 0) {
+ char r = scw[wl - plen + 1];
+ scw[wl - plen + 1] = '\0';
+ if (spell(scw.c_str()))
return 1;
- cw[wl - plen + 1] = r;
+ scw[wl - plen + 1] = r;
}
}
// other patterns
for (int j = 0; j < numbreak; j++) {
- int plen = strlen(wordbreak[j]);
- s = (char*)strstr(cw, wordbreak[j]);
- if (s && (s > cw) && (s < cw + wl - plen)) {
- if (!spell(s + plen))
+ size_t plen = strlen(wordbreak[j]);
+ size_t found = scw.find(wordbreak[j]);
+ if ((found > 0) && (found < wl - plen)) {
+ if (!spell(scw.c_str() + found + plen))
continue;
- r = *s;
- *s = '\0';
+ char r = scw[found];
+ scw[found] = '\0';
// examine 2 sides of the break point
- if (spell(cw))
+ if (spell(scw.c_str()))
return 1;
- *s = r;
+ scw[found] = r;
// LANG_hu: spec. dash rule
if (langnum == LANG_hu && strcmp(wordbreak[j], "-") == 0) {
- r = s[1];
- s[1] = '\0';
- if (spell(cw))
+ r = scw[found + 1];
+ scw[found + 1] = '\0';
+ if (spell(scw.c_str()))
return 1; // check the first part with dash
- s[1] = r;
+ scw[found + 1] = r;
}
- // end of LANG speficic region
+ // end of LANG specific region
}
}
}
@@ -716,10 +651,9 @@ struct hentry* Hunspell::checkword(const char* w, int* info, char** root) {
if (ignoredchars != NULL) {
w2.assign(w);
if (utf8) {
- int ignoredchars_utf16_len;
- unsigned short* ignoredchars_utf16 =
- pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
- remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
+ const std::vector<w_char>& ignoredchars_utf16 =
+ pAMgr->get_ignore_utf16();
+ remove_ignored_chars_utf(w2, ignoredchars_utf16);
} else {
remove_ignored_chars(w2, ignoredchars);
}
@@ -802,37 +736,40 @@ struct hentry* Hunspell::checkword(const char* w, int* info, char** root) {
return NULL;
}
if (root) {
- *root = mystrdup(he->word);
- if (*root && complexprefixes) {
+ std::string word_root(he->word);
+ if (complexprefixes) {
if (utf8)
- reverseword_utf(*root);
+ reverseword_utf(word_root);
else
- reverseword(*root);
+ reverseword(word_root);
}
+ *root = mystrdup(word_root.c_str());
}
// try check compound word
} else if (pAMgr->get_compound()) {
- he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0, info);
+ struct hentry* rwords[100]; // buffer for COMPOUND pattern checking
+ he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, (hentry**)&rwords, 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, (hentry**)&rwords, 1, 0,
info);
free(dup);
}
- // end of LANG speficic region
+ // end of LANG specific region
if (he) {
if (root) {
- *root = mystrdup(he->word);
- if (*root && complexprefixes) {
+ std::string word_root(he->word);
+ if (complexprefixes) {
if (utf8)
- reverseword_utf(*root);
+ reverseword_utf(word_root);
else
- reverseword(*root);
+ reverseword(word_root);
}
+ *root = mystrdup(word_root.c_str());
}
if (info)
*info += SPELL_COMPOUND;
@@ -845,11 +782,8 @@ struct hentry* Hunspell::checkword(const char* w, int* info, char** root) {
int Hunspell::suggest(char*** slst, const char* word) {
int onlycmpdsug = 0;
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
if (!pSMgr || maxdic == 0)
return 0;
- w_char unicw[MAXWORDLEN];
*slst = NULL;
// process XML input of the simplified API (see manual)
if (strncmp(word, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
@@ -863,130 +797,132 @@ int Hunspell::suggest(char*** slst, const char* word) {
if (nc >= MAXWORDLEN)
return 0;
}
- int captype = 0;
- int abbv = 0;
- int wl = 0;
+ int captype = NOCAP;
+ size_t abbv = 0;
+ size_t wl = 0;
+
+ std::string scw;
+ std::vector<w_char> sunicw;
// input conversion
RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace, MAXWORDUTF8LEN) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
- else
- wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+ {
+ std::string wspace;
+
+ int convstatus = rl ? rl->conv(word, wspace) : 0;
+ if (convstatus < 0)
+ return 0;
+ else if (convstatus > 0)
+ wl = cleanword2(scw, sunicw, wspace.c_str(), &nc, &captype, &abbv);
+ else
+ wl = cleanword2(scw, sunicw, word, &nc, &captype, &abbv);
+
+ if (wl == 0)
+ return 0;
+ }
- 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;
- }
+ if (checkword(scw.c_str(), &info, NULL)) {
+ std::string form(scw);
+ mkinitcap(form);
+
+ char** wlst = (char**)malloc(MAXSUGGESTION * sizeof(char*));
+ if (wlst == NULL)
+ return -1;
+ *slst = wlst;
+ wlst[0] = mystrdup(form.c_str());
+ for (int i = 1; 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);
+ ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
break;
}
case INITCAP: {
capwords = 1;
- ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
+ ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
if (ns == -1)
break;
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ std::string wspace(scw);
+ mkallsmall2(wspace, sunicw);
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
break;
}
case HUHINITCAP:
capwords = 1;
case HUHCAP: {
- ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
+ ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
if (ns != -1) {
- int prevns;
// something.The -> something. The
- char* dot = strchr(cw, '.');
- if (dot && (dot > cw)) {
+ size_t dot_pos = scw.find('.');
+ if (dot_pos != std::string::npos) {
+ std::string postdot = scw.substr(dot_pos + 1);
int captype_;
if (utf8) {
- w_char w_[MAXWORDLEN];
- int wl_ = u8_u16(w_, MAXWORDLEN, dot + 1);
- captype_ = get_captype_utf8(w_, wl_, langnum);
- } else
- captype_ = get_captype(dot + 1, strlen(dot + 1), csconv);
+ std::vector<w_char> postdotu;
+ u8_u16(postdotu, postdot);
+ captype_ = get_captype_utf8(postdotu, langnum);
+ } else {
+ captype_ = get_captype(postdot, csconv);
+ }
if (captype_ == INITCAP) {
- char* st = mystrdup(cw);
- if (st) {
- char* newst = (char*)realloc(st, wl + 2);
- if (newst == NULL)
- free(st);
- st = newst;
- }
- if (st) {
- st[(dot - cw) + 1] = ' ';
- strcpy(st + (dot - cw) + 2, dot + 1);
- ns = insert_sug(slst, st, ns);
- free(st);
- }
+ std::string str(scw);
+ str.insert(dot_pos + 1, 1, ' ');
+ ns = insert_sug(slst, str.c_str(), ns);
}
}
+
+ std::string wspace;
+
if (captype == HUHINITCAP) {
// TheOpenOffice.org -> The OpenOffice.org
- memcpy(wspace, cw, (wl + 1));
- mkinitsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ wspace = scw;
+ mkinitsmall2(wspace, sunicw);
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
}
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- if (spell(wspace))
- ns = insert_sug(slst, wspace, ns);
- prevns = ns;
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ wspace = scw;
+ mkallsmall2(wspace, sunicw);
+ if (spell(wspace.c_str()))
+ ns = insert_sug(slst, wspace.c_str(), ns);
+ int prevns = ns;
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
if (captype == HUHINITCAP) {
- mkinitcap2(wspace, unicw, nc);
- if (spell(wspace))
- ns = insert_sug(slst, wspace, ns);
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ mkinitcap2(wspace, sunicw);
+ if (spell(wspace.c_str()))
+ ns = insert_sug(slst, wspace.c_str(), ns);
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
}
// aNew -> "a New" (instead of "a new")
for (int j = prevns; j < ns; j++) {
char* space = strchr((*slst)[j], ' ');
if (space) {
- int slen = strlen(space + 1);
+ size_t slen = strlen(space + 1);
// different case after space (need capitalisation)
- if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) {
- w_char w[MAXWORDLEN];
- int wc = 0;
- char* r = (*slst)[j];
+ if ((slen < wl) && strcmp(scw.c_str() + wl - slen, space + 1)) {
+ std::string first((*slst)[j], space + 1);
+ std::string second(space + 1);
+ std::vector<w_char> w;
if (utf8)
- wc = u8_u16(w, MAXWORDLEN, space + 1);
- mkinitcap2(space + 1, w, wc);
+ u8_u16(w, second);
+ mkinitcap2(second, w);
// set as first suggestion
+ char* r = (*slst)[j];
for (int k = j; k > 0; k--)
(*slst)[k] = (*slst)[k - 1];
- (*slst)[0] = r;
+ free(r);
+ (*slst)[0] = mystrdup((first + second).c_str());
}
}
}
@@ -995,35 +931,30 @@ int Hunspell::suggest(char*** slst, const char* word) {
}
case ALLCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ std::string wspace(scw);
+ mkallsmall2(wspace, sunicw);
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
if (ns == -1)
break;
- if (pAMgr && pAMgr->get_keepcase() && spell(wspace))
- ns = insert_sug(slst, wspace, ns);
- mkinitcap2(wspace, unicw, nc);
- ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+ if (pAMgr && pAMgr->get_keepcase() && spell(wspace.c_str()))
+ ns = insert_sug(slst, wspace.c_str(), ns);
+ mkinitcap2(wspace, sunicw);
+ ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
for (int j = 0; j < ns; j++) {
- mkallcap((*slst)[j]);
+ std::string form((*slst)[j]);
+ mkallcap(form);
+
if (pAMgr && pAMgr->get_checksharps()) {
- char* pos;
if (utf8) {
- pos = strstr((*slst)[j], "\xC3\x9F");
- while (pos) {
- *pos = 'S';
- *(pos + 1) = 'S';
- pos = strstr(pos + 2, "\xC3\x9F");
- }
+ mystrrep(form, "\xC3\x9F", "SS");
} else {
- pos = strchr((*slst)[j], '\xDF');
- while (pos) {
- (*slst)[j] = (char*)realloc((*slst)[j], strlen((*slst)[j]) + 2);
- mystrrep((*slst)[j], "\xDF", "SS");
- pos = strchr((*slst)[j], '\xDF');
- }
+ mystrrep(form, "\xDF", "SS");
}
}
+
+ free((*slst)[j]);
+ (*slst)[j] = mystrdup(form.c_str());
+
}
break;
}
@@ -1035,11 +966,10 @@ int Hunspell::suggest(char*** slst, const char* word) {
char* pos = strchr((*slst)[j], '-');
if (pos) {
int info;
- char w[MAXWORDUTF8LEN];
*pos = '\0';
- strcpy(w, (*slst)[j]);
- strcat(w, pos + 1);
- (void)spell(w, &info, NULL);
+ std::string w((*slst)[j]);
+ w.append(pos + 1);
+ (void)spell(w.c_str(), &info, NULL);
if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
*pos = ' ';
} else
@@ -1054,64 +984,67 @@ int Hunspell::suggest(char*** slst, const char* word) {
(*slst)) {
switch (captype) {
case NOCAP: {
- ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr, maxdic);
+ ns = pSMgr->ngsuggest(*slst, scw.c_str(), ns, pHMgr, maxdic);
break;
}
case HUHINITCAP:
capwords = 1;
case HUHCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic);
+ std::string wspace(scw);
+ mkallsmall2(wspace, sunicw);
+ ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
break;
}
case INITCAP: {
capwords = 1;
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic);
+ std::string wspace(scw);
+ mkallsmall2(wspace, sunicw);
+ ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
break;
}
case ALLCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
+ std::string wspace(scw);
+ mkallsmall2(wspace, sunicw);
int oldns = ns;
- ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic);
- for (int j = oldns; j < ns; j++)
- mkallcap((*slst)[j]);
+ ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
+ for (int j = oldns; j < ns; j++) {
+ std::string form((*slst)[j]);
+ mkallcap(form);
+ free((*slst)[j]);
+ (*slst)[j] = mystrdup(form.c_str());
+ }
break;
}
}
}
// try dash suggestion (Afo-American -> Afro-American)
- if (char* pos = strchr(cw, '-')) {
- char* ppos = cw;
+ size_t dash_pos = scw.find('-');
+ if (dash_pos != std::string::npos) {
int nodashsug = 1;
- char** nlst = NULL;
- int nn = 0;
- int last = 0;
- if (*slst) {
- for (int j = 0; j < ns && nodashsug == 1; j++) {
- if (strchr((*slst)[j], '-'))
- nodashsug = 0;
- }
+ for (int j = 0; j < ns && nodashsug == 1; j++) {
+ if (strchr((*slst)[j], '-'))
+ nodashsug = 0;
}
+
+ size_t prev_pos = 0;
+ bool last = false;
+
while (nodashsug && !last) {
- if (*pos == '\0')
+ if (dash_pos == scw.size())
last = 1;
- else
- *pos = '\0';
- if (!spell(ppos)) {
- nn = suggest(&nlst, ppos);
+ std::string chunk = scw.substr(prev_pos, dash_pos - prev_pos);
+ if (!spell(chunk.c_str())) {
+ char** nlst = NULL;
+ int nn = suggest(&nlst, chunk.c_str());
for (int j = nn - 1; j >= 0; j--) {
- strncpy(wspace, cw, ppos - cw);
- strcpy(wspace + (ppos - cw), nlst[j]);
+ std::string wspace = scw.substr(0, prev_pos);
+ wspace.append(nlst[j]);
if (!last) {
- strcat(wspace, "-");
- strcat(wspace, pos + 1);
+ wspace.append("-");
+ wspace.append(scw.substr(dash_pos + 1));
}
- ns = insert_sug(slst, wspace, ns);
+ ns = insert_sug(slst, wspace.c_str(), ns);
free(nlst[j]);
}
if (nlst != NULL)
@@ -1119,29 +1052,34 @@ int Hunspell::suggest(char*** slst, const char* word) {
nodashsug = 0;
}
if (!last) {
- *pos = '-';
- ppos = pos + 1;
- pos = strchr(ppos, '-');
+ prev_pos = dash_pos + 1;
+ dash_pos = scw.find('-', prev_pos);
}
- if (!pos)
- pos = cw + strlen(cw);
+ if (dash_pos == std::string::npos)
+ dash_pos = scw.size();
}
}
// word reversing wrapper for complex prefixes
if (complexprefixes) {
for (int j = 0; j < ns; j++) {
+ std::string root((*slst)[j]);
+ free((*slst)[j]);
if (utf8)
- reverseword_utf((*slst)[j]);
+ reverseword_utf(root);
else
- reverseword((*slst)[j]);
+ reverseword(root);
+ (*slst)[j] = mystrdup(root.c_str());
}
}
// capitalize
if (capwords)
for (int j = 0; j < ns; j++) {
- mkinitcap((*slst)[j]);
+ std::string form((*slst)[j]);
+ free((*slst)[j]);
+ mkinitcap(form);
+ (*slst)[j] = mystrdup(form.c_str());
}
// expand suggestions with dot(s)
@@ -1160,25 +1098,23 @@ int Hunspell::suggest(char*** slst, const char* word) {
int l = 0;
for (int j = 0; j < ns; j++) {
if (!strchr((*slst)[j], ' ') && !spell((*slst)[j])) {
- char s[MAXSWUTF8L];
- w_char w[MAXSWL];
- int len;
+ std::string s;
+ std::vector<w_char> w;
if (utf8) {
- len = u8_u16(w, MAXSWL, (*slst)[j]);
+ u8_u16(w, (*slst)[j]);
} else {
- strcpy(s, (*slst)[j]);
- len = strlen(s);
+ s = (*slst)[j];
}
- mkallsmall2(s, w, len);
+ mkallsmall2(s, w);
free((*slst)[j]);
- if (spell(s)) {
- (*slst)[l] = mystrdup(s);
+ if (spell(s.c_str())) {
+ (*slst)[l] = mystrdup(s.c_str());
if ((*slst)[l])
l++;
} else {
- mkinitcap2(s, w, len);
- if (spell(s)) {
- (*slst)[l] = mystrdup(s);
+ mkinitcap2(s, w);
+ if (spell(s.c_str())) {
+ (*slst)[l] = mystrdup(s.c_str());
if ((*slst)[l])
l++;
}
@@ -1211,9 +1147,10 @@ int Hunspell::suggest(char*** slst, const char* word) {
// output conversion
rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
for (int j = 0; rl && j < ns; j++) {
- if (rl->conv((*slst)[j], wspace, MAXWORDUTF8LEN) > 0) {
+ std::string wspace;
+ if (rl->conv((*slst)[j], wspace) > 0) {
free((*slst)[j]);
- (*slst)[j] = mystrdup(wspace);
+ (*slst)[j] = mystrdup(wspace.c_str());
}
}
@@ -1233,151 +1170,25 @@ char* Hunspell::get_dic_encoding() {
return encoding;
}
-#ifdef HUNSPELL_EXPERIMENTAL
-// XXX UTF-8 support is OK?
-int Hunspell::suggest_auto(char*** slst, const char* word) {
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
- if (!pSMgr || maxdic == 0)
- return 0;
- w_char unicw[MAXWORDLEN];
- int nc = strlen(word);
- if (utf8) {
- if (nc >= MAXWORDUTF8LEN)
- return 0;
- } else {
- if (nc >= MAXWORDLEN)
- return 0;
- }
- int captype = 0;
- int abbv = 0;
- int wl = 0;
-
- // input conversion
- RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- 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;
- *slst = NULL; // HU, nsug in pSMgr->suggest
-
- switch (captype) {
- case NOCAP: {
- ns = pSMgr->suggest_auto(slst, cw, ns);
- if (ns > 0)
- break;
- break;
- }
-
- case INITCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest_auto(slst, wspace, ns);
- for (int j = 0; j < ns; j++)
- mkinitcap((*slst)[j]);
- ns = pSMgr->suggest_auto(slst, cw, ns);
- break;
- }
-
- case HUHINITCAP:
- case HUHCAP: {
- ns = pSMgr->suggest_auto(slst, cw, ns);
- if (ns == 0) {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest_auto(slst, wspace, ns);
- }
- break;
- }
-
- case ALLCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest_auto(slst, wspace, ns);
-
- mkinitcap(wspace);
- ns = pSMgr->suggest_auto(slst, wspace, ns);
-
- for (int j = 0; j < ns; j++)
- mkallcap((*slst)[j]);
- break;
- }
- }
-
- // word reversing wrapper for complex prefixes
- if (complexprefixes) {
- for (int j = 0; j < ns; j++) {
- if (utf8)
- reverseword_utf((*slst)[j]);
- else
- reverseword((*slst)[j]);
- }
- }
-
- // expand suggestions with dot(s)
- if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
- for (int j = 0; j < ns; j++) {
- (*slst)[j] = (char*)realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
- strcat((*slst)[j], word + strlen(word) - abbv);
- }
- }
-
- // 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]);
- strcat(w, pos + 1);
- spell(w, &info, NULL);
- if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
- *pos = ' ';
- } else
- *pos = '-';
- }
- }
- }
-
- // output conversion
- rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
- for (int j = 0; rl && j < ns; j++) {
- if (rl->conv((*slst)[j], wspace) > 0) {
- free((*slst)[j]);
- (*slst)[j] = mystrdup(wspace);
- }
- }
-
- // END OF LANG_hu section
- return ns;
-}
-#endif
-
int Hunspell::stem(char*** slst, char** desc, int n) {
- char result[MAXLNLEN];
- char result2[MAXLNLEN];
+
+ std::string result2;
*slst = NULL;
if (n == 0)
return 0;
- *result2 = '\0';
for (int i = 0; i < n; i++) {
- *result = '\0';
+
+ std::string result;
+
// add compound word parts (except the last one)
char* s = (char*)desc[i];
char* part = strstr(s, MORPH_PART);
if (part) {
char* nextpart = strstr(part + 1, MORPH_PART);
while (nextpart) {
- copy_field(result + strlen(result), part, MORPH_PART);
+ std::string field;
+ copy_field(field, part, MORPH_PART);
+ result.append(field);
part = nextpart;
nextpart = strstr(part + 1, MORPH_PART);
}
@@ -1404,22 +1215,28 @@ int Hunspell::stem(char*** slst, char** desc, int n) {
int genl = line_tok(sg, &gen, MSEP_REC);
free(sg);
for (int j = 0; j < genl; j++) {
- sprintf(result2 + strlen(result2), "%c%s%s", MSEP_REC, result,
- gen[j]);
+ result2.push_back(MSEP_REC);
+ result2.append(result);
+ result2.append(gen[j]);
}
freelist(&gen, genl);
}
} else {
- sprintf(result2 + strlen(result2), "%c%s", MSEP_REC, result);
+ result2.push_back(MSEP_REC);
+ result2.append(result);
if (strstr(pl[k], MORPH_SURF_PFX)) {
- copy_field(result2 + strlen(result2), pl[k], MORPH_SURF_PFX);
+ std::string field;
+ copy_field(field, pl[k], MORPH_SURF_PFX);
+ result2.append(field);
}
- copy_field(result2 + strlen(result2), pl[k], MORPH_STEM);
+ std::string field;
+ copy_field(field, pl[k], MORPH_STEM);
+ result2.append(field);
}
}
freelist(&pl, pln);
}
- int sln = line_tok(result2, slst, MSEP_REC);
+ int sln = line_tok(result2.c_str(), slst, MSEP_REC);
return uniqlist(*slst, sln);
}
@@ -1431,148 +1248,43 @@ int Hunspell::stem(char*** slst, const char* word) {
return pln2;
}
-#ifdef HUNSPELL_EXPERIMENTAL
-int Hunspell::suggest_pos_stems(char*** slst, const char* word) {
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
- if (!pSMgr || maxdic == 0)
- return 0;
- w_char unicw[MAXWORDLEN];
- int nc = strlen(word);
- if (utf8) {
- if (nc >= MAXWORDUTF8LEN)
- return 0;
- } else {
- if (nc >= MAXWORDLEN)
- return 0;
- }
- int captype = 0;
- int abbv = 0;
- int wl = 0;
-
- // input conversion
- RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- 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; // ns=0 = normalized input
-
- *slst = NULL; // HU, nsug in pSMgr->suggest
-
- switch (captype) {
- case HUHCAP:
- case NOCAP: {
- ns = pSMgr->suggest_pos_stems(slst, cw, ns);
-
- if ((abbv) && (ns == 0)) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
- }
-
- break;
- }
-
- case INITCAP: {
- ns = pSMgr->suggest_pos_stems(slst, cw, ns);
-
- if (ns == 0 || ((*slst)[0][0] == '#')) {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
- }
-
- break;
- }
-
- case ALLCAP: {
- ns = pSMgr->suggest_pos_stems(slst, cw, ns);
- if (ns != 0)
- break;
-
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
-
- if (ns == 0) {
- mkinitcap(wspace);
- ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
- }
- break;
- }
- }
-
- // output conversion
- rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
- for (int j = 0; rl && j < ns; j++) {
- if (rl->conv((*slst)[j], wspace) > 0) {
- free((*slst)[j]);
- (*slst)[j] = mystrdup(wspace);
- }
- }
-
- return ns;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
const char* Hunspell::get_wordchars() {
return pAMgr->get_wordchars();
}
-unsigned short* Hunspell::get_wordchars_utf16(int* len) {
- return pAMgr->get_wordchars_utf16(len);
+const std::vector<w_char>& Hunspell::get_wordchars_utf16() {
+ return pAMgr->get_wordchars_utf16();
}
-void Hunspell::mkinitcap(char* p) {
- if (!utf8) {
- if (*p != '\0')
- *p = csconv[((unsigned char)*p)].cupper;
+void Hunspell::mkinitcap(std::string& u8) {
+ if (utf8) {
+ std::vector<w_char> u16;
+ u8_u16(u16, u8);
+ ::mkinitcap_utf(u16, langnum);
+ u16_u8(u8, u16);
} else {
- int len;
- w_char u[MAXWORDLEN];
- len = u8_u16(u, MAXWORDLEN, p);
- unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
- u[0].h = (unsigned char)(i >> 8);
- u[0].l = (unsigned char)(i & 0x00FF);
- u16_u8(p, MAXWORDUTF8LEN, u, len);
+ ::mkinitcap(u8, csconv);
}
}
-int Hunspell::mkinitcap2(char* p, w_char* u, int nc) {
- if (!utf8) {
- if (*p != '\0')
- *p = csconv[((unsigned char)*p)].cupper;
- } else if (nc > 0) {
- unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
- u[0].h = (unsigned char)(i >> 8);
- u[0].l = (unsigned char)(i & 0x00FF);
- u16_u8(p, MAXWORDUTF8LEN, u, nc);
- return strlen(p);
+int Hunspell::mkinitcap2(std::string& u8, std::vector<w_char>& u16) {
+ if (utf8) {
+ ::mkinitcap_utf(u16, langnum);
+ u16_u8(u8, u16);
+ } else {
+ ::mkinitcap(u8, csconv);
}
- return nc;
+ return u8.size();
}
-int Hunspell::mkinitsmall2(char* p, w_char* u, int nc) {
- if (!utf8) {
- if (*p != '\0')
- *p = csconv[((unsigned char)*p)].clower;
- } else if (nc > 0) {
- unsigned short i = unicodetolower((u[0].h << 8) + u[0].l, langnum);
- u[0].h = (unsigned char)(i >> 8);
- u[0].l = (unsigned char)(i & 0x00FF);
- u16_u8(p, MAXWORDUTF8LEN, u, nc);
- return strlen(p);
+int Hunspell::mkinitsmall2(std::string& u8, std::vector<w_char>& u16) {
+ if (utf8) {
+ ::mkinitsmall_utf(u16, langnum);
+ u16_u8(u8, u16);
+ } else {
+ ::mkinitsmall(u8, csconv);
}
- return nc;
+ return u8.size();
}
int Hunspell::add(const char* word) {
@@ -1601,20 +1313,16 @@ struct cs_info* Hunspell::get_csconv() {
return csconv;
}
-void Hunspell::cat_result(char* result, char* st) {
+void Hunspell::cat_result(std::string& result, char* st) {
if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
+ if (!result.empty())
+ result.append("\n");
+ result.append(st);
free(st);
}
}
int Hunspell::analyze(char*** slst, const char* word) {
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
- w_char unicw[MAXWORDLEN];
- int wl2 = 0;
*slst = NULL;
if (!pSMgr || maxdic == 0)
return 0;
@@ -1626,48 +1334,52 @@ int Hunspell::analyze(char*** slst, const char* word) {
if (nc >= MAXWORDLEN)
return 0;
}
- int captype = 0;
- int abbv = 0;
- int wl = 0;
+ int captype = NOCAP;
+ size_t abbv = 0;
+ size_t wl = 0;
+
+ std::string scw;
+ std::vector<w_char> sunicw;
// input conversion
RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace, MAXWORDUTF8LEN) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
- else
- wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+ {
+ std::string wspace;
+
+ int convstatus = rl ? rl->conv(word, wspace) : 0;
+ if (convstatus < 0)
+ return 0;
+ else if (convstatus > 0)
+ wl = cleanword2(scw, sunicw, wspace.c_str(), &nc, &captype, &abbv);
+ else
+ wl = cleanword2(scw, sunicw, word, &nc, &captype, &abbv);
+ }
if (wl == 0) {
if (abbv) {
+ scw.clear();
for (wl = 0; wl < abbv; wl++)
- cw[wl] = '.';
- cw[wl] = '\0';
+ scw.push_back('.');
abbv = 0;
} else
return 0;
}
- char result[MAXLNLEN];
- char* st = NULL;
-
- *result = '\0';
+ std::string result;
- int n = 0;
- int n2 = 0;
- int n3 = 0;
+ size_t n = 0;
+ size_t n2 = 0;
+ size_t n3 = 0;
// test numbers
// LANG_hu section: set dash information for suggestions
if (langnum == LANG_hu) {
- while ((n < wl) && (((cw[n] <= '9') && (cw[n] >= '0')) ||
- (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) {
+ while ((n < wl) && (((scw[n] <= '9') && (scw[n] >= '0')) ||
+ (((scw[n] == '.') || (scw[n] == ',')) && (n > 0)))) {
n++;
- if ((cw[n] == '.') || (cw[n] == ',')) {
+ if ((scw[n] == '.') || (scw[n] == ',')) {
if (((n2 == 0) && (n > 3)) ||
- ((n2 > 0) && ((cw[n - 1] == '.') || (cw[n - 1] == ','))))
+ ((n2 > 0) && ((scw[n - 1] == '.') || (scw[n - 1] == ','))))
break;
n2++;
n3 = n;
@@ -1676,21 +1388,21 @@ int Hunspell::analyze(char*** slst, const char* word) {
if ((n == wl) && (n3 > 0) && (n - n3 > 3))
return 0;
- if ((n == wl) || ((n > 0) && ((cw[n] == '%') || (cw[n] == '\xB0')) &&
- checkword(cw + n, NULL, NULL))) {
- mystrcat(result, cw, MAXLNLEN);
- result[n - 1] = '\0';
+ if ((n == wl) || ((n > 0) && ((scw[n] == '%') || (scw[n] == '\xB0')) &&
+ checkword(scw.c_str() + n, NULL, NULL))) {
+ result.append(scw);
+ result.resize(n - 1);
if (n == wl)
- cat_result(result, pSMgr->suggest_morph(cw + n - 1));
+ cat_result(result, pSMgr->suggest_morph(scw.c_str() + n - 1));
else {
- char sign = cw[n];
- cw[n] = '\0';
- cat_result(result, pSMgr->suggest_morph(cw + n - 1));
- mystrcat(result, "+", MAXLNLEN); // XXX SPEC. MORPHCODE
- cw[n] = sign;
- cat_result(result, pSMgr->suggest_morph(cw + n));
+ char sign = scw[n];
+ scw[n] = '\0';
+ cat_result(result, pSMgr->suggest_morph(scw.c_str() + n - 1));
+ result.push_back('+'); // XXX SPEC. MORPHCODE
+ scw[n] = sign;
+ cat_result(result, pSMgr->suggest_morph(scw.c_str() + n));
}
- return line_tok(result, slst, MSEP_REC);
+ return line_tok(result.c_str(), slst, MSEP_REC);
}
}
// END OF LANG_hu section
@@ -1699,64 +1411,58 @@ int Hunspell::analyze(char*** slst, const char* word) {
case HUHCAP:
case HUHINITCAP:
case NOCAP: {
- cat_result(result, pSMgr->suggest_morph(cw));
+ cat_result(result, pSMgr->suggest_morph(scw.c_str()));
if (abbv) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- cat_result(result, pSMgr->suggest_morph(wspace));
+ std::string u8buffer(scw);
+ u8buffer.push_back('.');
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
}
break;
}
case INITCAP: {
- wl = mkallsmall2(cw, unicw, nc);
- memcpy(wspace, cw, (wl + 1));
- wl2 = mkinitcap2(cw, unicw, nc);
- cat_result(result, pSMgr->suggest_morph(wspace));
- cat_result(result, pSMgr->suggest_morph(cw));
+ wl = mkallsmall2(scw, sunicw);
+ std::string u8buffer(scw);
+ mkinitcap2(scw, sunicw);
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
+ cat_result(result, pSMgr->suggest_morph(scw.c_str()));
if (abbv) {
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- cat_result(result, pSMgr->suggest_morph(wspace));
+ u8buffer.push_back('.');
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
- memcpy(wspace, cw, wl2);
- *(wspace + wl2) = '.';
- *(wspace + wl2 + 1) = '\0';
+ u8buffer = scw;
+ u8buffer.push_back('.');
- cat_result(result, pSMgr->suggest_morph(wspace));
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
}
break;
}
case ALLCAP: {
- cat_result(result, pSMgr->suggest_morph(cw));
+ cat_result(result, pSMgr->suggest_morph(scw.c_str()));
if (abbv) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- cat_result(result, pSMgr->suggest_morph(cw));
+ std::string u8buffer(scw);
+ u8buffer.push_back('.');
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
}
- wl = mkallsmall2(cw, unicw, nc);
- memcpy(wspace, cw, (wl + 1));
- wl2 = mkinitcap2(cw, unicw, nc);
+ mkallsmall2(scw, sunicw);
+ std::string u8buffer(scw);
+ mkinitcap2(scw, sunicw);
- cat_result(result, pSMgr->suggest_morph(wspace));
- cat_result(result, pSMgr->suggest_morph(cw));
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
+ cat_result(result, pSMgr->suggest_morph(scw.c_str()));
if (abbv) {
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- cat_result(result, pSMgr->suggest_morph(wspace));
+ u8buffer.push_back('.');
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
- memcpy(wspace, cw, wl2);
- *(wspace + wl2) = '.';
- *(wspace + wl2 + 1) = '\0';
+ u8buffer = scw;
+ u8buffer.push_back('.');
- cat_result(result, pSMgr->suggest_morph(wspace));
+ cat_result(result, pSMgr->suggest_morph(u8buffer.c_str()));
}
break;
}
}
- if (*result) {
+ if (!result.empty()) {
// word reversing wrapper for complex prefixes
if (complexprefixes) {
if (utf8)
@@ -1764,95 +1470,94 @@ int Hunspell::analyze(char*** slst, const char* word) {
else
reverseword(result);
}
- return line_tok(result, slst, MSEP_REC);
+ return line_tok(result.c_str(), 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) {
- *dash = '\0';
+
+ size_t dash_pos = langnum == LANG_hu ? scw.find('-') : std::string::npos;
+ int nresult = 0;
+ if (dash_pos != std::string::npos) {
+ std::string part1 = scw.substr(0, dash_pos);
+ std::string part2 = scw.substr(dash_pos+1);
+
// examine 2 sides of the dash
- if (dash[1] == '\0') { // base word ending with dash
- if (spell(cw)) {
- char* p = pSMgr->suggest_morph(cw);
+ if (part2.empty()) { // base word ending with dash
+ if (spell(part1.c_str())) {
+ char* p = pSMgr->suggest_morph(part1.c_str());
if (p) {
int ret = line_tok(p, slst, MSEP_REC);
free(p);
return ret;
}
}
- } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
- if (spell(cw) && (spell("-e"))) {
- st = pSMgr->suggest_morph(cw);
+ } else if (part2.size() == 1 && part2[0] == 'e') { // XXX (HU) -e hat.
+ if (spell(part1.c_str()) && (spell("-e"))) {
+ char* st = pSMgr->suggest_morph(part1.c_str());
if (st) {
- mystrcat(result, st, MAXLNLEN);
+ result.append(st);
free(st);
}
- mystrcat(result, "+", MAXLNLEN); // XXX spec. separator in MORPHCODE
+ result.push_back('+'); // XXX spec. separator in MORPHCODE
st = pSMgr->suggest_morph("-e");
if (st) {
- mystrcat(result, st, MAXLNLEN);
+ result.append(st);
free(st);
}
- return line_tok(result, slst, MSEP_REC);
+ return line_tok(result.c_str(), slst, MSEP_REC);
}
} else {
// first word ending with dash: word- XXX ???
- char r2 = *(dash + 1);
- dash[0] = '-';
- dash[1] = '\0';
- nresult = spell(cw);
- dash[1] = r2;
- dash[0] = '\0';
- if (nresult && spell(dash + 1) &&
- ((strlen(dash + 1) > 1) || ((dash[1] > '0') && (dash[1] < '9')))) {
- st = pSMgr->suggest_morph(cw);
+ part1.push_back(' ');
+ nresult = spell(part1.c_str());
+ part1.erase(part1.size() - 1);
+ if (nresult && spell(part2.c_str()) &&
+ ((part2.size() > 1) || ((part2[0] > '0') && (part2[0] < '9')))) {
+ char* st = pSMgr->suggest_morph(part1.c_str());
if (st) {
- mystrcat(result, st, MAXLNLEN);
+ result.append(st);
free(st);
- mystrcat(result, "+", MAXLNLEN); // XXX spec. separator in MORPHCODE
+ result.push_back('+'); // XXX spec. separator in MORPHCODE
}
- st = pSMgr->suggest_morph(dash + 1);
+ st = pSMgr->suggest_morph(part2.c_str());
if (st) {
- mystrcat(result, st, MAXLNLEN);
+ result.append(st);
free(st);
}
- return line_tok(result, slst, MSEP_REC);
+ return line_tok(result.c_str(), slst, MSEP_REC);
}
}
// affixed number in correct word
- if (nresult && (dash > cw) &&
- (((*(dash - 1) <= '9') && (*(dash - 1) >= '0')) ||
- (*(dash - 1) == '.'))) {
- *dash = '-';
+ if (nresult && (dash_pos > 0) &&
+ (((scw[dash_pos - 1] <= '9') && (scw[dash_pos - 1] >= '0')) ||
+ (scw[dash_pos - 1] == '.'))) {
n = 1;
- if (*(dash - n) == '.')
+ if (scw[dash_pos - n] == '.')
n++;
// search first not a number character to left from dash
- while (((dash - n) >= cw) && ((*(dash - n) == '0') || (n < 3)) &&
+ while ((dash_pos >= n) && ((scw[dash_pos - n] == '0') || (n < 3)) &&
(n < 6)) {
n++;
}
- if ((dash - n) < cw)
+ if (dash_pos < n)
n--;
// numbers: valami1000000-hoz
// examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz,
// 56-hoz, 6-hoz
for (; n >= 1; n--) {
- if ((*(dash - n) >= '0') && (*(dash - n) <= '9') &&
- checkword(dash - n, NULL, NULL)) {
- mystrcat(result, cw, MAXLNLEN);
- result[dash - cw - n] = '\0';
- st = pSMgr->suggest_morph(dash - n);
+ if (scw[dash_pos - n] < '0' || scw[dash_pos - n] > '9') {
+ continue;
+ }
+ std::string chunk = scw.substr(dash_pos - n);
+ if (checkword(chunk.c_str(), NULL, NULL)) {
+ result.append(chunk);
+ char* st = pSMgr->suggest_morph(chunk.c_str());
if (st) {
- mystrcat(result, st, MAXLNLEN);
+ result.append(st);
free(st);
}
- return line_tok(result, slst, MSEP_REC);
+ return line_tok(result.c_str(), slst, MSEP_REC);
}
}
}
@@ -1866,30 +1571,33 @@ int Hunspell::generate(char*** slst, const char* word, char** pl, int pln) {
return 0;
char** pl2;
int pl2n = analyze(&pl2, word);
- int captype = 0;
+ int captype = NOCAP;
int abbv = 0;
- char cw[MAXWORDUTF8LEN];
+ std::string cw;
cleanword(cw, word, &captype, &abbv);
- char result[MAXLNLEN];
- *result = '\0';
+ std::string result;
for (int i = 0; i < pln; i++) {
cat_result(result, pSMgr->suggest_gen(pl2, pl2n, pl[i]));
}
freelist(&pl2, pl2n);
- if (*result) {
+ if (!result.empty()) {
// allcap
if (captype == ALLCAP)
mkallcap(result);
// line split
- int linenum = line_tok(result, slst, MSEP_REC);
+ int linenum = line_tok(result.c_str(), slst, MSEP_REC);
// capitalize
if (captype == INITCAP || captype == HUHINITCAP) {
- for (int j = 0; j < linenum; j++)
- mkinitcap((*slst)[j]);
+ for (int j = 0; j < linenum; j++) {
+ std::string form((*slst)[j]);
+ free((*slst)[j]);
+ mkinitcap(form);
+ (*slst)[j] = mystrdup(form.c_str());
+ }
}
// temporary filtering of prefix related errors (eg.
@@ -1923,22 +1631,21 @@ int Hunspell::generate(char*** slst, const char* word, const char* pattern) {
}
// minimal XML parser functions
-int Hunspell::get_xml_par(char* dest, const char* par, int max) {
- char* d = dest;
+std::string Hunspell::get_xml_par(const char* par) {
+ std::string dest;
if (!par)
- return 0;
+ return dest;
char end = *par;
- char* dmax = dest + max;
if (end == '>')
end = '<';
else if (end != '\'' && end != '"')
return 0; // bad XML
- for (par++; d < dmax && *par != '\0' && *par != end; par++, d++)
- *d = *par;
- *d = '\0';
+ for (par++; *par != '\0' && *par != end; ++par) {
+ dest.push_back(*par);
+ }
mystrrep(dest, "&lt;", "<");
mystrrep(dest, "&amp;", "&");
- return (int)(d - dest);
+ return dest;
}
int Hunspell::get_langnum() const {
@@ -1967,18 +1674,17 @@ const char* Hunspell::get_xml_pos(const char* s, const char* attr) {
int Hunspell::check_xml_par(const char* q,
const char* attr,
const char* value) {
- char cw[MAXWORDUTF8LEN];
- if (get_xml_par(cw, get_xml_pos(q, attr), MAXWORDUTF8LEN - 1) &&
- strcmp(cw, value) == 0)
+ std::string cw = get_xml_par(get_xml_pos(q, attr));
+ if (cw == value)
return 1;
return 0;
}
-int Hunspell::get_xml_list(char*** slst, char* list, const char* tag) {
- int n = 0;
- char* p;
+int Hunspell::get_xml_list(char*** slst, const char* list, const char* tag) {
if (!list)
return 0;
+ int n = 0;
+ const char* p;
for (p = list; ((p = strstr(p, tag)) != NULL); p++)
n++;
if (n == 0)
@@ -1987,25 +1693,20 @@ int Hunspell::get_xml_list(char*** slst, char* list, const char* tag) {
if (!*slst)
return 0;
for (p = list, n = 0; ((p = strstr(p, tag)) != NULL); p++, n++) {
- int l = strlen(p);
- (*slst)[n] = (char*)malloc(l + 1);
- if (!(*slst)[n])
- return n;
- if (!get_xml_par((*slst)[n], p + strlen(tag) - 1, l)) {
- free((*slst)[n]);
+ std::string cw = get_xml_par(p + strlen(tag) - 1);
+ if (cw.empty()) {
break;
}
+ (*slst)[n] = mystrdup(cw.c_str());
}
return n;
}
int Hunspell::spellml(char*** slst, const char* word) {
- char *q, *q2;
- char cw[MAXWORDUTF8LEN], cw2[MAXWORDUTF8LEN];
- q = (char*)strstr(word, "<query");
+ const char* q = strstr(word, "<query");
if (!q)
return 0; // bad XML input
- q2 = strchr(q, '>');
+ const char* q2 = strchr(q, '>');
if (!q2)
return 0; // bad XML input
q2 = strstr(q2, "<word");
@@ -2013,8 +1714,9 @@ int Hunspell::spellml(char*** slst, const char* word) {
return 0; // bad XML input
if (check_xml_par(q, "type=", "analyze")) {
int n = 0;
- if (get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 10))
- n = analyze(slst, cw);
+ std::string cw = get_xml_par(strchr(q2, '>'));
+ if (!cw.empty())
+ n = analyze(slst, cw.c_str());
if (n == 0)
return 0;
// convert the result to <code><a>ana1</a><a>ana2</a></code> format
@@ -2036,22 +1738,25 @@ int Hunspell::spellml(char*** slst, const char* word) {
(*slst)[0] = mystrdup(r.c_str());
return 1;
} else if (check_xml_par(q, "type=", "stem")) {
- if (get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1))
- return stem(slst, cw);
+ std::string cw = get_xml_par(strchr(q2, '>'));
+ if (!cw.empty())
+ return stem(slst, cw.c_str());
} else if (check_xml_par(q, "type=", "generate")) {
- int n = get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1);
- if (n == 0)
+ std::string cw = get_xml_par(strchr(q2, '>'));
+ if (cw.empty())
return 0;
- char* q3 = strstr(q2 + 1, "<word");
+ const char* q3 = strstr(q2 + 1, "<word");
if (q3) {
- if (get_xml_par(cw2, strchr(q3, '>'), MAXWORDUTF8LEN - 1)) {
- return generate(slst, cw, cw2);
+ std::string cw2 = get_xml_par(strchr(q3, '>'));
+ if (!cw2.empty()) {
+ return generate(slst, cw.c_str(), cw2.c_str());
}
} else {
if ((q2 = strstr(q2 + 1, "<code")) != NULL) {
char** slst2;
- if ((n = get_xml_list(&slst2, strchr(q2, '>'), "<a>")) != 0) {
- int n2 = generate(slst, cw, slst2, n);
+ int n = get_xml_list(&slst2, strchr(q2, '>'), "<a>");
+ if (n != 0) {
+ int n2 = generate(slst, cw.c_str(), slst2, n);
freelist(&slst2, n);
return uniqlist(*slst, n2);
}
@@ -2062,182 +1767,6 @@ int Hunspell::spellml(char*** slst, const char* word) {
return 0;
}
-#ifdef HUNSPELL_EXPERIMENTAL
-// XXX is UTF-8 support OK?
-char* Hunspell::morph_with_correction(const char* word) {
- char cw[MAXWORDUTF8LEN];
- char wspace[MAXWORDUTF8LEN];
- if (!pSMgr || maxdic == 0)
- return NULL;
- w_char unicw[MAXWORDLEN];
- int nc = strlen(word);
- if (utf8) {
- if (nc >= MAXWORDUTF8LEN)
- return NULL;
- } else {
- if (nc >= MAXWORDLEN)
- return NULL;
- }
- int captype = 0;
- int abbv = 0;
- int wl = 0;
-
- // input conversion
- RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
- int convstatus = rl ? rl->conv(word, wspace) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
- else
- wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
-
- if (wl == 0)
- return NULL;
-
- char result[MAXLNLEN];
- char* st = NULL;
-
- *result = '\0';
-
- switch (captype) {
- case NOCAP: {
- st = pSMgr->suggest_morph_for_spelling_error(cw);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- if (abbv) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- }
- break;
- }
- case INITCAP: {
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- st = pSMgr->suggest_morph_for_spelling_error(cw);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- if (abbv) {
- memcpy(wspace, cw, wl);
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- mkallsmall2(wspace, unicw, nc);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- mkinitcap(wspace);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- }
- break;
- }
- case HUHCAP: {
- st = pSMgr->suggest_morph_for_spelling_error(cw);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- memcpy(wspace, cw, (wl + 1));
- mkallsmall2(wspace, unicw, nc);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- break;
- }
- case ALLCAP: {
- memcpy(wspace, cw, (wl + 1));
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- mkallsmall2(wspace, unicw, nc);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- mkinitcap(wspace);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- if (abbv) {
- memcpy(wspace, cw, (wl + 1));
- *(wspace + wl) = '.';
- *(wspace + wl + 1) = '\0';
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- mkallsmall2(wspace, unicw, nc);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- mkinitcap(wspace);
- st = pSMgr->suggest_morph_for_spelling_error(wspace);
- if (st) {
- if (*result)
- mystrcat(result, "\n", MAXLNLEN);
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- }
- break;
- }
- }
-
- if (*result)
- return mystrdup(result);
- return NULL;
-}
-
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
Hunhandle* Hunspell_create(const char* affpath, const char* dpath) {
return (Hunhandle*)(new Hunspell(affpath, dpath));
}
@@ -2333,10 +1862,9 @@ int Hunspell::suffix_suggest(char*** slst, const char* root_word) {
if (ignoredchars != NULL) {
w2.assign(root_word);
if (utf8) {
- int ignoredchars_utf16_len;
- unsigned short* ignoredchars_utf16 =
- pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
- remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
+ const std::vector<w_char>& ignoredchars_utf16 =
+ pAMgr->get_ignore_utf16();
+ remove_ignored_chars_utf(w2, ignoredchars_utf16);
} else {
remove_ignored_chars(w2, ignoredchars);
}