Attachment #501038: Release Hunspell 1.2.13 patch for bug #620626

View | Details | Raw Unified | Return to bug 620626
Collapse All | Expand All

(-)a/extensions/spellcheck/hunspell/src/README.hunspell (-2 / +2 lines)
Line     Link Here 
 Lines 30-47    Link Here 
30
* use your version of this file under the terms of the MPL, indicate your
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
34
* the terms of any one of the MPL, the GPL or the LGPL.
35
*
35
*
36
******* END LICENSE BLOCK *******
36
******* END LICENSE BLOCK *******
37
37
38
Hunspell Version: 1.2.12
38
Hunspell Version: 1.2.13
39
Additional Patches: 583582
39
Additional Patches: 
40
40
41
Hunspell Author: László Németh
41
Hunspell Author: László Németh
42
MySpell Author: Kevin Hendricks & David Einstein
42
MySpell Author: Kevin Hendricks & David Einstein
43
43
44
Hunspell is a spell checker and morphological analyser library. Hunspell
44
Hunspell is a spell checker and morphological analyser library. Hunspell
45
is based on OpenOffice.org's Myspell. Documentation, tests, and examples
45
is based on OpenOffice.org's Myspell. Documentation, tests, and examples
46
are available at http://hunspell.sourceforge.net.
46
are available at http://hunspell.sourceforge.net.
47
47
(-)a/extensions/spellcheck/hunspell/src/affentry.cpp (-1 / +1 lines)
Line     Link Here 
 Lines 155-171   inline int PfxEntry::test_condition(cons Link Here 
155
                pos = st; break;
155
                pos = st; break;
156
            }
156
            }
157
        case '^': { p = nextchar(p); neg = true; break; }
157
        case '^': { p = nextchar(p); neg = true; break; }
158
        case ']': { 
158
        case ']': { 
159
                if ((neg && ingroup) || (!neg && !ingroup)) return 0;
159
                if ((neg && ingroup) || (!neg && !ingroup)) return 0;
160
                pos = NULL;
160
                pos = NULL;
161
                p = nextchar(p);
161
                p = nextchar(p);
162
                // skip the next character
162
                // skip the next character
163
                if (!ingroup) for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++);
163
                if (!ingroup && *st) for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++);
164
                if (*st == '\0' && p) return 0; // word <= condition
164
                if (*st == '\0' && p) return 0; // word <= condition
165
                break;
165
                break;
166
            }
166
            }
167
         case '.': if (!pos) { // dots are not metacharacters in groups: [.]
167
         case '.': if (!pos) { // dots are not metacharacters in groups: [.]
168
                p = nextchar(p);
168
                p = nextchar(p);
169
                // skip the next character
169
                // skip the next character
170
                for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++);
170
                for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++);
171
                if (*st == '\0' && p) return 0; // word <= condition
171
                if (*st == '\0' && p) return 0; // word <= condition
(-)a/extensions/spellcheck/hunspell/src/affixmgr.cpp (-40 / +100 lines)
Line     Link Here 
 Lines 78-94   AffixMgr::AffixMgr(const char * affpath, Link Here 
78
  trystring = NULL;
78
  trystring = NULL;
79
  encoding=NULL;
79
  encoding=NULL;
80
  csconv=NULL;
80
  csconv=NULL;
81
  utf8 = 0;
81
  utf8 = 0;
82
  complexprefixes = 0;
82
  complexprefixes = 0;
83
  maptable = NULL;
83
  maptable = NULL;
84
  nummap = 0;
84
  nummap = 0;
85
  breaktable = NULL;
85
  breaktable = NULL;
86
  numbreak = 0;
86
  numbreak = -1;
87
  reptable = NULL;
87
  reptable = NULL;
88
  numrep = 0;
88
  numrep = 0;
89
  iconvtable = NULL;
89
  iconvtable = NULL;
90
  oconvtable = NULL;
90
  oconvtable = NULL;
91
  checkcpdtable = NULL;
91
  checkcpdtable = NULL;
92
  // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN)
92
  // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN)
93
  simplifiedcpd = 0;
93
  simplifiedcpd = 0;
94
  numcheckcpd = 0;
94
  numcheckcpd = 0;
 Lines 758-774   int AffixMgr::parse_file(const char * a Link Here 
758
                *(expw + strlen(expw)) = (char) i;
758
                *(expw + strlen(expw)) = (char) i;
759
        }
759
        }
760
    }
760
    }
761
761
762
    wordchars = mystrdup(expw);
762
    wordchars = mystrdup(expw);
763
    }
763
    }
764
764
765
    // default BREAK definition
765
    // default BREAK definition
766
    if (!breaktable) {
766
    if (numbreak == -1) {
767
        breaktable = (char **) malloc(sizeof(char *) * 3);
767
        breaktable = (char **) malloc(sizeof(char *) * 3);
768
        if (!breaktable) return 1;
768
        if (!breaktable) return 1;
769
        breaktable[0] = mystrdup("-");
769
        breaktable[0] = mystrdup("-");
770
        breaktable[1] = mystrdup("^-");
770
        breaktable[1] = mystrdup("^-");
771
        breaktable[2] = mystrdup("-$");
771
        breaktable[2] = mystrdup("-$");
772
        if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3;
772
        if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3;
773
    }
773
    }
774
    return 0;
774
    return 0;
 Lines 1316-1342   int AffixMgr::cpdrep_check(const char * Link Here 
1316
          if (candidate_check(candidate,strlen(candidate))) return 1;
1316
          if (candidate_check(candidate,strlen(candidate))) return 1;
1317
          r++; // search for the next letter
1317
          r++; // search for the next letter
1318
      }
1318
      }
1319
   }
1319
   }
1320
   return 0;
1320
   return 0;
1321
}
1321
}
1322
1322
1323
// forbid compoundings when there are special patterns at word bound
1323
// forbid compoundings when there are special patterns at word bound
1324
int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2)
1324
int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2, const char affixed)
1325
{
1325
{
1326
  int len;
1326
  int len;
1327
  for (int i = 0; i < numcheckcpd; i++) {
1327
  for (int i = 0; i < numcheckcpd; i++) {
1328
      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
1328
      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
1329
        (!r1 || !checkcpdtable[i].cond ||
1329
        (!r1 || !checkcpdtable[i].cond ||
1330
          (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) &&
1330
          (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) &&
1331
        (!r2 || !checkcpdtable[i].cond2 ||
1331
        (!r2 || !checkcpdtable[i].cond2 ||
1332
          (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) &&
1332
          (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) &&
1333
        (len = strlen(checkcpdtable[i].pattern)) && (pos > len) &&
1333
        // zero length pattern => only TESTAFF
1334
        (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1;
1334
        // zero pattern (0/flag) => unmodified stem (zero affixes allowed)
1335
        (!*(checkcpdtable[i].pattern) || (
1336
            (*(checkcpdtable[i].pattern)=='0' && r1->blen <= pos && strncmp(word + pos - r1->blen, r1->word, r1->blen) == 0) ||
1337
            (*(checkcpdtable[i].pattern)!='0' && (len = strlen(checkcpdtable[i].pattern)) &&
1338
                strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)))) {
1339
            return 1;
1340
        }
1335
  }
1341
  }
1336
  return 0;
1342
  return 0;
1337
}
1343
}
1338
1344
1339
// forbid compounding with neighbouring upper and lower case characters at word bounds
1345
// forbid compounding with neighbouring upper and lower case characters at word bounds
1340
int AffixMgr::cpdcase_check(const char * word, int pos)
1346
int AffixMgr::cpdcase_check(const char * word, int pos)
1341
{
1347
{
1342
  if (utf8) {
1348
  if (utf8) {
 Lines 1511-1526   void AffixMgr::setcminmax(int * cmin, in Link Here 
1511
          for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--);
1517
          for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--);
1512
        }
1518
        }
1513
    } else {
1519
    } else {
1514
        *cmin = cpdmin;
1520
        *cmin = cpdmin;
1515
        *cmax = len - cpdmin + 1;
1521
        *cmax = len - cpdmin + 1;
1516
    }
1522
    }
1517
}
1523
}
1518
1524
1525
1519
// check if compound word is correctly spelled
1526
// check if compound word is correctly spelled
1520
// hu_mov_rule = spec. Hungarian rule (XXX)
1527
// hu_mov_rule = spec. Hungarian rule (XXX)
1521
struct hentry * AffixMgr::compound_check(const char * word, int len, 
1528
struct hentry * AffixMgr::compound_check(const char * word, int len, 
1522
    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
1529
    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
1523
    char hu_mov_rule = 0, char is_sug = 0)
1530
    char hu_mov_rule = 0, char is_sug = 0)
1524
{
1531
{
1525
    int i; 
1532
    int i; 
1526
    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
1533
    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
 Lines 1533-1567   struct hentry * AffixMgr::compound_check Link Here 
1533
    int cmax;
1540
    int cmax;
1534
    int striple = 0;
1541
    int striple = 0;
1535
    int scpd = 0;
1542
    int scpd = 0;
1536
    int soldi = 0;
1543
    int soldi = 0;
1537
    int oldcmin = 0;
1544
    int oldcmin = 0;
1538
    int oldcmax = 0;
1545
    int oldcmax = 0;
1539
    int oldlen = 0;
1546
    int oldlen = 0;
1540
    int checkedstriple = 0;
1547
    int checkedstriple = 0;
1548
    int onlycpdrule;
1549
    int affixed = 0;
1541
1550
1542
    int checked_prefix;
1551
    int checked_prefix;
1543
1552
1544
    setcminmax(&cmin, &cmax, word, len);
1553
    setcminmax(&cmin, &cmax, word, len);
1545
1554
1546
    strcpy(st, word);
1555
    strcpy(st, word);
1547
1556
1548
    for (i = cmin; i < cmax; i++) {
1557
    for (i = cmin; i < cmax; i++) {
1549
1550
        oldnumsyllable = numsyllable;
1551
        oldwordnum = wordnum;
1552
        checked_prefix = 0;
1553
1554
        // go to end of the UTF-8 character
1558
        // go to end of the UTF-8 character
1555
        if (utf8) {
1559
        if (utf8) {
1556
            for (; (st[i] & 0xc0) == 0x80; i++);
1560
            for (; (st[i] & 0xc0) == 0x80; i++);
1557
            if (i >= cmax) return NULL;
1561
            if (i >= cmax) return NULL;
1558
        }
1562
        }
1559
1563
1564
        onlycpdrule = 0;
1565
1566
        do { // onlycpdrule loop
1567
1568
        oldnumsyllable = numsyllable;
1569
        oldwordnum = wordnum;
1570
        checked_prefix = 0;
1571
1560
        do { // simplified checkcompoundpattern loop
1572
        do { // simplified checkcompoundpattern loop
1561
1573
1562
        if (scpd > 0) {
1574
        if (scpd > 0) {
1563
          for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 ||
1575
          for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 ||
1564
            strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++);
1576
            strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++);
1565
1577
1566
          if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop
1578
          if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop
1567
          strcpy(st + i, checkcpdtable[scpd-1].pattern);
1579
          strcpy(st + i, checkcpdtable[scpd-1].pattern);
 Lines 1574-1618   struct hentry * AffixMgr::compound_check Link Here 
1574
          len += strlen(checkcpdtable[scpd-1].pattern) + strlen(checkcpdtable[scpd-1].pattern2) - strlen(checkcpdtable[scpd-1].pattern3);
1586
          len += strlen(checkcpdtable[scpd-1].pattern) + strlen(checkcpdtable[scpd-1].pattern2) - strlen(checkcpdtable[scpd-1].pattern3);
1575
          oldcmin = cmin;
1587
          oldcmin = cmin;
1576
          oldcmax = cmax;
1588
          oldcmax = cmax;
1577
          setcminmax(&cmin, &cmax, st, len);
1589
          setcminmax(&cmin, &cmax, st, len);
1578
1590
1579
          cmax = len - cpdmin + 1;
1591
          cmax = len - cpdmin + 1;
1580
        }
1592
        }
1581
1593
1582
1583
        ch = st[i];
1594
        ch = st[i];
1584
        st[i] = '\0';
1595
        st[i] = '\0';
1585
1596
1586
        sfx = NULL;
1597
        sfx = NULL;
1587
        pfx = NULL;
1598
        pfx = NULL;
1588
1599
1589
        // FIRST WORD
1600
        // FIRST WORD
1590
1601
1602
        affixed = 1;
1591
        rv = lookup(st); // perhaps without prefix
1603
        rv = lookup(st); // perhaps without prefix
1592
1604
1593
        // search homonym with compound flag
1605
        // search homonym with compound flag
1594
        while ((rv) && !hu_mov_rule &&
1606
        while ((rv) && !hu_mov_rule &&
1595
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
1607
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
1596
                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
1608
                !((compoundflag && !words && !onlycpdrule && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
1597
                  (compoundbegin && !wordnum &&
1609
                  (compoundbegin && !wordnum && !onlycpdrule && 
1598
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
1610
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
1599
                  (compoundmiddle && wordnum && !words &&
1611
                  (compoundmiddle && wordnum && !words && !onlycpdrule &&
1600
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
1612
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
1601
                  (numdefcpd &&
1613
                  (numdefcpd &&
1602
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
1614
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
1603
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))) ||
1615
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))) && (onlycpdrule = 1))) || // switch onlycpdrule on
1604
                  (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL &&
1616
                  (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL &&
1605
                    !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen)))
1617
                    !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen)))
1606
                  ) {
1618
                  ) {
1607
            rv = rv->next_homonym;
1619
            rv = rv->next_homonym;
1608
        }
1620
        }
1609
1621
1622
        if (rv) affixed = 0;
1623
1610
        if (!rv) {
1624
        if (!rv) {
1625
            if (onlycpdrule) break;
1611
            if (compoundflag && 
1626
            if (compoundflag && 
1612
             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
1627
             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
1613
                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
1628
                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
1614
                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
1629
                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
1615
                    sfx->getCont() &&
1630
                    sfx->getCont() &&
1616
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
1631
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
1617
                            sfx->getContLen())) || (compoundend &&
1632
                            sfx->getContLen())) || (compoundend &&
1618
                        TESTAFF(sfx->getCont(), compoundend, 
1633
                        TESTAFF(sfx->getCont(), compoundend, 
 Lines 1626-1646   struct hentry * AffixMgr::compound_check Link Here 
1626
                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
1641
                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
1627
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
1642
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
1628
              ((wordnum > 0) && compoundmiddle &&
1643
              ((wordnum > 0) && compoundmiddle &&
1629
                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
1644
                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
1630
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
1645
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
1631
              ) checked_prefix = 1;
1646
              ) checked_prefix = 1;
1632
        // else check forbiddenwords and needaffix
1647
        // else check forbiddenwords and needaffix
1633
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1648
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1634
            TESTAFF(rv->astr, needaffix, rv->alen) || 
1649
            TESTAFF(rv->astr, needaffix, rv->alen) ||
1650
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1635
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
1651
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
1636
             )) {
1652
             )) {
1637
                st[i] = ch;
1653
                st[i] = ch;
1638
                continue;
1654
                //continue;
1655
                break;
1639
        }
1656
        }
1640
1657
1641
            // check non_compound flag in suffix and prefix
1658
            // check non_compound flag in suffix and prefix
1642
            if ((rv) && !hu_mov_rule &&
1659
            if ((rv) && !hu_mov_rule &&
1643
                ((pfx && pfx->getCont() &&
1660
                ((pfx && pfx->getCont() &&
1644
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1661
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1645
                        pfx->getContLen())) ||
1662
                        pfx->getContLen())) ||
1646
                (sfx && sfx->getCont() &&
1663
                (sfx && sfx->getCont() &&
 Lines 1668-1683   struct hentry * AffixMgr::compound_check Link Here 
1668
                (sfx && sfx->getCont() &&
1685
                (sfx && sfx->getCont() &&
1669
                    TESTAFF(sfx->getCont(), compoundmiddle, 
1686
                    TESTAFF(sfx->getCont(), compoundmiddle, 
1670
                        sfx->getContLen())))) {
1687
                        sfx->getContLen())))) {
1671
                    rv = NULL;
1688
                    rv = NULL;
1672
            }
1689
            }
1673
1690
1674
        // check forbiddenwords
1691
        // check forbiddenwords
1675
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1692
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1693
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1676
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
1694
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
1677
                return NULL;
1695
                return NULL;
1678
            }
1696
            }
1679
1697
1680
        // increment word number, if the second root has a compoundroot flag
1698
        // increment word number, if the second root has a compoundroot flag
1681
        if ((rv) && compoundroot && 
1699
        if ((rv) && compoundroot && 
1682
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1700
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1683
                wordnum++;
1701
                wordnum++;
 Lines 1730-1746   struct hentry * AffixMgr::compound_check Link Here 
1730
                // calculate syllable number of the word
1748
                // calculate syllable number of the word
1731
                numsyllable += get_syllable(st, i);
1749
                numsyllable += get_syllable(st, i);
1732
1750
1733
                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
1751
                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
1734
                if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++;
1752
                if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++;
1735
            }
1753
            }
1736
// END of LANG_hu section
1754
// END of LANG_hu section
1737
1755
1738
1739
            // NEXT WORD(S)
1756
            // NEXT WORD(S)
1740
            rv_first = rv;
1757
            rv_first = rv;
1741
            st[i] = ch;
1758
            st[i] = ch;
1742
1759
1743
        do { // striple loop
1760
        do { // striple loop
1744
1761
1745
            // check simplifiedtriple
1762
            // check simplifiedtriple
1746
            if (simplifiedtriple) { 
1763
            if (simplifiedtriple) { 
 Lines 1777-1792   struct hentry * AffixMgr::compound_check Link Here 
1777
            // increment word number, if the second root has a compoundroot flag
1794
            // increment word number, if the second root has a compoundroot flag
1778
            if ((rv) && (compoundroot) && 
1795
            if ((rv) && (compoundroot) && 
1779
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1796
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1780
                    wordnum++;
1797
                    wordnum++;
1781
            }
1798
            }
1782
1799
1783
            // check forbiddenwords
1800
            // check forbiddenwords
1784
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1801
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1802
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1785
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1803
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1786
1804
1787
            // second word is acceptable, as a root?
1805
            // second word is acceptable, as a root?
1788
            // hungarian conventions: compounding is acceptable,
1806
            // hungarian conventions: compounding is acceptable,
1789
            // when compound forms consist of 2 words, or if more,
1807
            // when compound forms consist of 2 words, or if more,
1790
            // then the syllable number of root words must be 6, or lesser.
1808
            // then the syllable number of root words must be 6, or lesser.
1791
1809
1792
            if ((rv) && (
1810
            if ((rv) && (
 Lines 1795-1811   struct hentry * AffixMgr::compound_check Link Here 
1795
                    )
1813
                    )
1796
                && (
1814
                && (
1797
                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
1815
                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
1798
                      ((cpdmaxsyllable!=0) && 
1816
                      ((cpdmaxsyllable!=0) && 
1799
                          (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable))
1817
                          (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable))
1800
                    ) &&
1818
                    ) &&
1801
               (
1819
               (
1802
                 // test CHECKCOMPOUNDPATTERN
1820
                 // test CHECKCOMPOUNDPATTERN
1803
                 !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv)
1821
                 !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv, 0)
1804
               ) &&
1822
               ) &&
1805
                (
1823
                (
1806
                     (!checkcompounddup || (rv != rv_first))
1824
                     (!checkcompounddup || (rv != rv_first))
1807
                   )
1825
                   )
1808
            // test CHECKCOMPOUNDPATTERN conditions
1826
            // test CHECKCOMPOUNDPATTERN conditions
1809
                && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL ||
1827
                && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL ||
1810
                      TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1828
                      TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1811
                )
1829
                )
 Lines 1816-1864   struct hentry * AffixMgr::compound_check Link Here 
1816
            }
1834
            }
1817
1835
1818
            numsyllable = oldnumsyllable2;
1836
            numsyllable = oldnumsyllable2;
1819
            wordnum = oldwordnum2;
1837
            wordnum = oldwordnum2;
1820
1838
1821
            // perhaps second word has prefix or/and suffix
1839
            // perhaps second word has prefix or/and suffix
1822
            sfx = NULL;
1840
            sfx = NULL;
1823
            sfxflag = FLAG_NULL;
1841
            sfxflag = FLAG_NULL;
1824
            rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
1842
            rv = (compoundflag && !onlycpdrule) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
1825
            if (!rv && compoundend) {
1843
            if (!rv && compoundend && !onlycpdrule) {
1826
                sfx = NULL;
1844
                sfx = NULL;
1827
                pfx = NULL;
1845
                pfx = NULL;
1828
                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
1846
                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
1829
            }
1847
            }
1830
1848
1831
            if (!rv && numdefcpd && words) {
1849
            if (!rv && numdefcpd && words) {
1832
                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
1850
                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
1833
                if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first;
1851
                if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first;
1834
                rv = NULL;
1852
                rv = NULL;
1835
            }
1853
            }
1836
1854
1837
            // test CHECKCOMPOUNDPATTERN conditions (allowed forms)
1855
            // test CHECKCOMPOUNDPATTERN conditions (allowed forms)
1838
            if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || 
1856
            if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || 
1839
                TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL;
1857
                TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL;
1840
1858
1841
            // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
1859
            // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
1842
            if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv)) rv = NULL;
1860
            if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) rv = NULL;
1843
1861
1844
            // check non_compound flag in suffix and prefix
1862
            // check non_compound flag in suffix and prefix
1845
            if ((rv) && 
1863
            if ((rv) && 
1846
                ((pfx && pfx->getCont() &&
1864
                ((pfx && pfx->getCont() &&
1847
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1865
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1848
                        pfx->getContLen())) ||
1866
                        pfx->getContLen())) ||
1849
                (sfx && sfx->getCont() &&
1867
                (sfx && sfx->getCont() &&
1850
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
1868
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
1851
                        sfx->getContLen())))) {
1869
                        sfx->getContLen())))) {
1852
                    rv = NULL;
1870
                    rv = NULL;
1853
            }
1871
            }
1854
1872
1855
            // check forbiddenwords
1873
            // check forbiddenwords
1856
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1874
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1875
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1857
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1876
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1858
1877
1859
            // pfxappnd = prefix of word+i, or NULL
1878
            // pfxappnd = prefix of word+i, or NULL
1860
            // calculate syllable number of prefix.
1879
            // calculate syllable number of prefix.
1861
            // hungarian convention: when syllable number of prefix is more,
1880
            // hungarian convention: when syllable number of prefix is more,
1862
            // than 1, the prefix+word counts as two words.
1881
            // than 1, the prefix+word counts as two words.
1863
1882
1864
            if (langnum == LANG_hu) {
1883
            if (langnum == LANG_hu) {
 Lines 1878-1894   struct hentry * AffixMgr::compound_check Link Here 
1878
1897
1879
                // increment syllable num, if last word has a SYLLABLENUM flag
1898
                // increment syllable num, if last word has a SYLLABLENUM flag
1880
                // and the suffix is beginning `s'
1899
                // and the suffix is beginning `s'
1881
1900
1882
                if (cpdsyllablenum) {
1901
                if (cpdsyllablenum) {
1883
                    switch (sfxflag) {
1902
                    switch (sfxflag) {
1884
                        case 'c': { numsyllable+=2; break; }
1903
                        case 'c': { numsyllable+=2; break; }
1885
                        case 'J': { numsyllable += 1; break; }
1904
                        case 'J': { numsyllable += 1; break; }
1886
                        case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
1905
                        case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
1887
                    }
1906
                    }
1888
                }
1907
                }
1889
            }
1908
            }
1890
1909
1891
            // increment word number, if the second word has a compoundroot flag
1910
            // increment word number, if the second word has a compoundroot flag
1892
            if ((rv) && (compoundroot) && 
1911
            if ((rv) && (compoundroot) && 
1893
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1912
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1894
                    wordnum++;
1913
                    wordnum++;
 Lines 1914-1937   struct hentry * AffixMgr::compound_check Link Here 
1914
1933
1915
            numsyllable = oldnumsyllable2;
1934
            numsyllable = oldnumsyllable2;
1916
            wordnum = oldwordnum2;
1935
            wordnum = oldwordnum2;
1917
1936
1918
            // perhaps second word is a compound word (recursive call)
1937
            // perhaps second word is a compound word (recursive call)
1919
            if (wordnum < maxwordnum) {
1938
            if (wordnum < maxwordnum) {
1920
                rv = compound_check((st+i),strlen(st+i), wordnum+1,
1939
                rv = compound_check((st+i),strlen(st+i), wordnum+1,
1921
                     numsyllable, maxwordnum, wnum + 1, words, 0, is_sug);
1940
                     numsyllable, maxwordnum, wnum + 1, words, 0, is_sug);
1922
                if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv)) ||
1941
                if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) ||
1923
                   (scpd != 0 && !cpdpat_check(word, i, rv_first, rv)))) rv = NULL;
1942
                   (scpd != 0 && !cpdpat_check(word, i, rv_first, rv, affixed)))) rv = NULL;
1924
            } else {
1943
            } else {
1925
                rv=NULL;
1944
                rv=NULL;
1926
            }
1945
            }
1927
            if (rv) {
1946
            if (rv) {
1928
                // forbid compound word, if it is a non compound word with typical fault
1947
                // forbid compound word, if it is a non compound word with typical fault
1929
                if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
1948
                if (checkcompoundrep || forbiddenword) {
1949
                    struct hentry * rv2 = NULL;
1950
                    if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
1951
                    // check first part
1952
                    if (strncmp(rv->word, word + i, rv->blen) == 0) {
1953
                        char r = *(st + i + rv->blen);
1954
                        *(st + i + rv->blen) = '\0';
1955
                        if (checkcompoundrep && cpdrep_check(st, i + rv->blen)) return NULL;
1956
                        if (forbiddenword) {
1957
                    	    rv2 = lookup(word);
1958
                    	    if (!rv2) rv2 = affix_check(word, len);
1959
                    	    if (rv2 && rv2->astr && TESTAFF(rv2->astr, forbiddenword, rv2->alen) && 
1960
                    		(strncmp(rv2->word, st, i + rv->blen) == 0)) {
1961
                		    return NULL;
1962
                	    }
1963
                	}
1964
                	*(st + i + rv->blen) = r;
1965
                    }
1966
                }
1967
1930
                return rv_first;
1968
                return rv_first;
1931
            }
1969
            }
1932
          } while (striple && !checkedstriple); // end of striple loop
1970
          } while (striple && !checkedstriple); // end of striple loop
1933
1971
1934
          if (checkedstriple) {
1972
          if (checkedstriple) {
1935
            i++;
1973
            i++;
1936
            checkedstriple = 0;
1974
            checkedstriple = 0;
1937
            striple = 0;
1975
            striple = 0;
 Lines 1943-1969   struct hentry * AffixMgr::compound_check Link Here 
1943
          i = soldi;
1981
          i = soldi;
1944
          soldi = 0;
1982
          soldi = 0;
1945
          len = oldlen;
1983
          len = oldlen;
1946
          cmin = oldcmin;
1984
          cmin = oldcmin;
1947
          cmax = oldcmax;
1985
          cmax = oldcmax;
1948
        }
1986
        }
1949
        scpd++;
1987
        scpd++;
1950
1988
1951
        } while (simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop
1989
        } while (!onlycpdrule && simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop
1990
1991
        scpd = 0;
1992
        wordnum = oldwordnum;
1993
        numsyllable = oldnumsyllable;
1952
1994
1953
        if (soldi != 0) {
1995
        if (soldi != 0) {
1954
          i = soldi;
1996
          i = soldi;
1955
          strcpy(st, word); // XXX add more optim.
1997
          strcpy(st, word); // XXX add more optim.
1956
          soldi = 0;
1998
          soldi = 0;
1957
        } else st[i] = ch;
1999
        } else st[i] = ch;
1958
2000
1959
        scpd = 0;
2001
        } while (numdefcpd && oldwordnum == 0 && !onlycpdrule && (onlycpdrule = 1)); // end of onlycpd loop
1960
        wordnum = oldwordnum;
2002
1961
        numsyllable = oldnumsyllable;
1962
    }
2003
    }
1963
2004
1964
    return NULL;
2005
    return NULL;
1965
}
2006
}
1966
2007
1967
// check if compound word is correctly spelled
2008
// check if compound word is correctly spelled
1968
// hu_mov_rule = spec. Hungarian rule (XXX)
2009
// hu_mov_rule = spec. Hungarian rule (XXX)
1969
int AffixMgr::compound_check_morph(const char * word, int len, 
2010
int AffixMgr::compound_check_morph(const char * word, int len, 
 Lines 2075-2090   int AffixMgr::compound_check_morph(const Link Here 
2075
                    sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD,
2116
                    sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD,
2076
                        MORPH_PART, st, line_uniq_app(&p, MSEP_REC));
2117
                        MORPH_PART, st, line_uniq_app(&p, MSEP_REC));
2077
                }
2118
                }
2078
                if (p) free(p);
2119
                if (p) free(p);
2079
                checked_prefix = 1;
2120
                checked_prefix = 1;
2080
            }
2121
            }
2081
        // else check forbiddenwords
2122
        // else check forbiddenwords
2082
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2123
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2124
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
2083
            TESTAFF(rv->astr, needaffix, rv->alen))) {
2125
            TESTAFF(rv->astr, needaffix, rv->alen))) {
2084
                st[i] = ch;
2126
                st[i] = ch;
2085
                continue;
2127
                continue;
2086
        }
2128
        }
2087
2129
2088
            // check non_compound flag in suffix and prefix
2130
            // check non_compound flag in suffix and prefix
2089
            if ((rv) && !hu_mov_rule &&
2131
            if ((rv) && !hu_mov_rule &&
2090
                ((pfx && pfx->getCont() &&
2132
                ((pfx && pfx->getCont() &&
 Lines 2114-2130   int AffixMgr::compound_check_morph(const Link Here 
2114
                        pfx->getContLen())) ||
2156
                        pfx->getContLen())) ||
2115
                (sfx && sfx->getCont() &&
2157
                (sfx && sfx->getCont() &&
2116
                    TESTAFF(sfx->getCont(), compoundmiddle, 
2158
                    TESTAFF(sfx->getCont(), compoundmiddle, 
2117
                        sfx->getContLen())))) {
2159
                        sfx->getContLen())))) {
2118
                    rv = NULL;
2160
                    rv = NULL;
2119
            }       
2161
            }       
2120
2162
2121
        // check forbiddenwords
2163
        // check forbiddenwords
2122
        if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue;
2164
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen)
2165
            || TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) continue;
2123
2166
2124
        // increment word number, if the second root has a compoundroot flag
2167
        // increment word number, if the second root has a compoundroot flag
2125
        if ((rv) && (compoundroot) && 
2168
        if ((rv) && (compoundroot) && 
2126
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2169
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2127
                wordnum++;
2170
                wordnum++;
2128
        }
2171
        }
2129
2172
2130
        // first word is acceptable in compound words?
2173
        // first word is acceptable in compound words?
 Lines 2146-2162   int AffixMgr::compound_check_morph(const Link Here 
2146
          && ! (( checkcompoundtriple && !words && // test triple letters
2189
          && ! (( checkcompoundtriple && !words && // test triple letters
2147
                   (word[i-1]==word[i]) && (
2190
                   (word[i-1]==word[i]) && (
2148
                      ((i>1) && (word[i-1]==word[i-2])) || 
2191
                      ((i>1) && (word[i-1]==word[i-2])) || 
2149
                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
2192
                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
2150
                   )
2193
                   )
2151
               ) ||
2194
               ) ||
2152
               (
2195
               (
2153
                   // test CHECKCOMPOUNDPATTERN
2196
                   // test CHECKCOMPOUNDPATTERN
2154
                   numcheckcpd && !words && cpdpat_check(word, i, rv, NULL)
2197
                   numcheckcpd && !words && cpdpat_check(word, i, rv, NULL, 0)
2155
               ) ||
2198
               ) ||
2156
               ( 
2199
               ( 
2157
                 checkcompoundcase && !words && cpdcase_check(word, i)
2200
                 checkcompoundcase && !words && cpdcase_check(word, i)
2158
               ))
2201
               ))
2159
         )
2202
         )
2160
// LANG_hu section: spec. Hungarian rule
2203
// LANG_hu section: spec. Hungarian rule
2161
         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
2204
         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
2162
              (sfx && sfx->getCont() && (
2205
              (sfx && sfx->getCont() && (
 Lines 2222-2238   int AffixMgr::compound_check_morph(const Link Here 
2222
// END of LANG_hu section
2265
// END of LANG_hu section
2223
            // increment word number, if the second root has a compoundroot flag
2266
            // increment word number, if the second root has a compoundroot flag
2224
            if ((rv) && (compoundroot) && 
2267
            if ((rv) && (compoundroot) && 
2225
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2268
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2226
                    wordnum++;
2269
                    wordnum++;
2227
            }
2270
            }
2228
2271
2229
            // check forbiddenwords
2272
            // check forbiddenwords
2230
            if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) {
2273
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2274
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) {
2231
                st[i] = ch;
2275
                st[i] = ch;
2232
                continue;
2276
                continue;
2233
            }
2277
            }
2234
2278
2235
            // second word is acceptable, as a root?
2279
            // second word is acceptable, as a root?
2236
            // hungarian conventions: compounding is acceptable,
2280
            // hungarian conventions: compounding is acceptable,
2237
            // when compound forms consist of 2 words, or if more,
2281
            // when compound forms consist of 2 words, or if more,
2238
            // then the syllable number of root words must be 6, or lesser.
2282
            // then the syllable number of root words must be 6, or lesser.
 Lines 2316-2332   int AffixMgr::compound_check_morph(const Link Here 
2316
                        pfx->getContLen())) ||
2360
                        pfx->getContLen())) ||
2317
                (sfx && sfx->getCont() &&
2361
                (sfx && sfx->getCont() &&
2318
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
2362
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
2319
                        sfx->getContLen())))) {
2363
                        sfx->getContLen())))) {
2320
                    rv = NULL;
2364
                    rv = NULL;
2321
            }
2365
            }
2322
2366
2323
            // check forbiddenwords
2367
            // check forbiddenwords
2324
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen))
2368
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen) ||
2369
                    TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))
2325
                    && (! TESTAFF(rv->astr, needaffix, rv->alen))) {
2370
                    && (! TESTAFF(rv->astr, needaffix, rv->alen))) {
2326
                        st[i] = ch;
2371
                        st[i] = ch;
2327
                        continue;
2372
                        continue;
2328
                    }
2373
                    }
2329
2374
2330
            if (langnum == LANG_hu) {
2375
            if (langnum == LANG_hu) {
2331
                // calculate syllable number of the word
2376
                // calculate syllable number of the word
2332
                numsyllable += get_syllable(word + i, strlen(word + i));
2377
                numsyllable += get_syllable(word + i, strlen(word + i));
 Lines 2886-2902   char * AffixMgr::morphgen(char * ts, int Link Here 
2886
2931
2887
                int cmp = morphcmp(stemmorph, targetmorph);
2932
                int cmp = morphcmp(stemmorph, targetmorph);
2888
2933
2889
                if (cmp == 0) {
2934
                if (cmp == 0) {
2890
                    char * newword = sptr->add(ts, wl);
2935
                    char * newword = sptr->add(ts, wl);
2891
                    if (newword) {
2936
                    if (newword) {
2892
                        hentry * check = pHMgr->lookup(newword); // XXX extra dic
2937
                        hentry * check = pHMgr->lookup(newword); // XXX extra dic
2893
                        if (!check || !check->astr || 
2938
                        if (!check || !check->astr || 
2894
                            !TESTAFF(check->astr, forbiddenword, check->alen)) {
2939
                            !(TESTAFF(check->astr, forbiddenword, check->alen) || 
2940
                              TESTAFF(check->astr, ONLYUPCASEFLAG, check->alen))) {
2895
                                return newword;
2941
                                return newword;
2896
                        }
2942
                        }
2897
                        free(newword);
2943
                        free(newword);
2898
                    }
2944
                    }
2899
                }
2945
                }
2900
                
2946
                
2901
                // recursive call for secondary suffixes
2947
                // recursive call for secondary suffixes
2902
                if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) &&
2948
                if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) &&
 Lines 3440-3456   int AffixMgr::parse_reptable(char * lin Link Here 
3440
                  case 0: {
3486
                  case 0: {
3441
                             if (strncmp(piece,"REP",3) != 0) {
3487
                             if (strncmp(piece,"REP",3) != 0) {
3442
                                 HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3488
                                 HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3443
                                 numrep = 0;
3489
                                 numrep = 0;
3444
                                 return 1;
3490
                                 return 1;
3445
                             }
3491
                             }
3446
                             break;
3492
                             break;
3447
                          }
3493
                          }
3448
                  case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; }
3494
                  case 1: {
3495
                            if (*piece == '^') reptable[j].start = true; else reptable[j].start = false;
3496
                            reptable[j].pattern = mystrrep(mystrdup(piece + int(reptable[j].start)),"_"," ");
3497
                            int lr = strlen(reptable[j].pattern) - 1;
3498
                            if (reptable[j].pattern[lr] == '$') {
3499
                                reptable[j].end = true;
3500
                                reptable[j].pattern[lr] = '\0';
3501
                            } else reptable[j].end = false;
3502
                            break;
3503
                          }
3449
                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
3504
                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
3450
                  default: break;
3505
                  default: break;
3451
               }
3506
               }
3452
               i++;
3507
               i++;
3453
           }
3508
           }
3454
           piece = mystrsep(&tp, 0);
3509
           piece = mystrsep(&tp, 0);
3455
        }
3510
        }
3456
        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
3511
        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
 Lines 3530-3547   int AffixMgr::parse_convtable(char * li Link Here 
3530
                  }
3585
                  }
3531
                  default: break;
3586
                  default: break;
3532
               }
3587
               }
3533
               i++;
3588
               i++;
3534
           }
3589
           }
3535
           piece = mystrsep(&tp, 0);
3590
           piece = mystrsep(&tp, 0);
3536
        }
3591
        }
3537
        if (!pattern || !pattern2) {
3592
        if (!pattern || !pattern2) {
3538
             HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3593
            if (pattern)
3539
             return 1;
3594
                free(pattern);
3595
            if (pattern2)
3596
                free(pattern2);
3597
            HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3598
            return 1;
3540
        }
3599
        }
3541
        (*rl)->add(pattern, pattern2);
3600
        (*rl)->add(pattern, pattern2);
3542
   }
3601
   }
3543
   return 0;
3602
   return 0;
3544
}
3603
}
3545
3604
3546
3605
3547
/* parse in the typical fault correcting table */
3606
/* parse in the typical fault correcting table */
 Lines 3927-3961   int AffixMgr::parse_maptable(char * lin Link Here 
3927
        }
3986
        }
3928
   }
3987
   }
3929
   return 0;
3988
   return 0;
3930
}
3989
}
3931
3990
3932
/* parse in the word breakpoint table */
3991
/* parse in the word breakpoint table */
3933
int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
3992
int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
3934
{
3993
{
3935
   if (numbreak != 0) {
3994
   if (numbreak > -1) {
3936
      HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum());
3995
      HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum());
3937
      return 1;
3996
      return 1;
3938
   }
3997
   }
3939
   char * tp = line;
3998
   char * tp = line;
3940
   char * piece;
3999
   char * piece;
3941
   int i = 0;
4000
   int i = 0;
3942
   int np = 0;
4001
   int np = 0;
3943
   piece = mystrsep(&tp, 0);
4002
   piece = mystrsep(&tp, 0);
3944
   while (piece) {
4003
   while (piece) {
3945
       if (*piece != '\0') {
4004
       if (*piece != '\0') {
3946
          switch(i) {
4005
          switch(i) {
3947
             case 0: { np++; break; }
4006
             case 0: { np++; break; }
3948
             case 1: { 
4007
             case 1: { 
3949
                       numbreak = atoi(piece);
4008
                       numbreak = atoi(piece);
3950
                       if (numbreak < 1) {
4009
                       if (numbreak < 0) {
3951
                          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum());
4010
                          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum());
3952
                          return 1;
4011
                          return 1;
3953
                       }
4012
                       }
4013
                       if (numbreak == 0) return 0;
3954
                       breaktable = (char **) malloc(numbreak * sizeof(char *));
4014
                       breaktable = (char **) malloc(numbreak * sizeof(char *));
3955
                       if (!breaktable) return 1;
4015
                       if (!breaktable) return 1;
3956
                       np++;
4016
                       np++;
3957
                       break;
4017
                       break;
3958
                     }
4018
                     }
3959
             default: break;
4019
             default: break;
3960
          }
4020
          }
3961
          i++;
4021
          i++;
(-)a/extensions/spellcheck/hunspell/src/affixmgr.hxx (-1 / +2 lines)
Line     Link Here 
 Lines 195-211   public: Link Here 
195
            unsigned short al, char * morph, char * targetmorph, int level);
195
            unsigned short al, char * morph, char * targetmorph, int level);
196
196
197
  int    expand_rootword(struct guessword * wlst, int maxn, const char * ts,
197
  int    expand_rootword(struct guessword * wlst, int maxn, const char * ts,
198
            int wl, const unsigned short * ap, unsigned short al, char * bad,
198
            int wl, const unsigned short * ap, unsigned short al, char * bad,
199
            int, char *);
199
            int, char *);
200
200
201
  short       get_syllable (const char * word, int wlen);
201
  short       get_syllable (const char * word, int wlen);
202
  int         cpdrep_check(const char * word, int len);
202
  int         cpdrep_check(const char * word, int len);
203
  int         cpdpat_check(const char * word, int len, hentry * r1, hentry * r2);
203
  int         cpdpat_check(const char * word, int len, hentry * r1, hentry * r2,
204
                    const char affixed);
204
  int         defcpd_check(hentry *** words, short wnum, hentry * rv,
205
  int         defcpd_check(hentry *** words, short wnum, hentry * rv,
205
                    hentry ** rwords, char all);
206
                    hentry ** rwords, char all);
206
  int         cpdcase_check(const char * word, int len);
207
  int         cpdcase_check(const char * word, int len);
207
  inline int  candidate_check(const char * word, int len);
208
  inline int  candidate_check(const char * word, int len);
208
  void        setcminmax(int * cmin, int * cmax, const char * word, int len);
209
  void        setcminmax(int * cmin, int * cmax, const char * word, int len);
209
  struct hentry * compound_check(const char * word, int len, short wordnum,
210
  struct hentry * compound_check(const char * word, int len, short wordnum,
210
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
211
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
211
            char hu_mov_rule, char is_sug);
212
            char hu_mov_rule, char is_sug);
(-)a/extensions/spellcheck/hunspell/src/csutil.cpp (-62 / +139 lines)
Line     Link Here 
 Lines 60-97    Link Here 
60
#include <string.h>
60
#include <string.h>
61
#include <stdio.h> 
61
#include <stdio.h> 
62
#include <ctype.h>
62
#include <ctype.h>
63
63
64
#include "csutil.hxx"
64
#include "csutil.hxx"
65
#include "atypes.hxx"
65
#include "atypes.hxx"
66
#include "langnum.hxx"
66
#include "langnum.hxx"
67
67
68
// Unicode character encoding information
69
struct unicode_info {
70
  unsigned short c;
71
  unsigned short cupper;
72
  unsigned short clower;
73
};
74
68
#ifdef OPENOFFICEORG
75
#ifdef OPENOFFICEORG
69
#  include <unicode/uchar.h>
76
#  include <unicode/uchar.h>
70
#else
77
#else
71
#  ifndef MOZILLA_CLIENT
78
#  ifndef MOZILLA_CLIENT
72
#    include "utf_info.cxx"
79
#    include "utf_info.cxx"
73
#    define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info)))
80
#    define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info)))
74
#  endif
81
#  endif
75
#endif
82
#endif
76
83
77
#ifdef MOZILLA_CLIENT
84
#ifdef MOZILLA_CLIENT
78
#include "nsCOMPtr.h"
85
#include "nsCOMPtr.h"
79
#include "nsServiceManagerUtils.h"
86
#include "nsServiceManagerUtils.h"
80
#include "nsIUnicodeEncoder.h"
87
#include "nsIUnicodeEncoder.h"
81
#include "nsIUnicodeDecoder.h"
88
#include "nsIUnicodeDecoder.h"
89
#include "nsICaseConversion.h"
82
#include "nsICharsetConverterManager.h"
90
#include "nsICharsetConverterManager.h"
83
#include "nsUnicharUtilCIID.h"
91
#include "nsUnicharUtilCIID.h"
84
#include "nsUnicharUtils.h"
92
#include "nsUnicharUtils.h"
85
93
86
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
94
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
87
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
95
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
88
#endif
96
#endif
89
97
98
struct unicode_info2 {
99
  char cletter;
100
  unsigned short cupper;
101
  unsigned short clower;
102
};
103
90
static struct unicode_info2 * utf_tbl = NULL;
104
static struct unicode_info2 * utf_tbl = NULL;
91
static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
105
static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
92
106
93
/* only UTF-16 (BMP) implementation */
107
/* only UTF-16 (BMP) implementation */
94
char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
108
char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
95
    signed char * u8 = (signed char *)dest;
109
    signed char * u8 = (signed char *)dest;
96
    signed char * u8_max = (signed char *)(u8 + size);
110
    signed char * u8_max = (signed char *)(u8 + size);
97
    const w_char * u2 = src;
111
    const w_char * u2 = src;
 Lines 590-620   char * copy_field(char * dest, const cha Link Here 
590
       return dest;
604
       return dest;
591
  }
605
  }
592
  return NULL;
606
  return NULL;
593
}
607
}
594
608
595
char * mystrrep(char * word, const char * pat, const char * rep) {
609
char * mystrrep(char * word, const char * pat, const char * rep) {
596
    char * pos = strstr(word, pat);
610
    char * pos = strstr(word, pat);
597
    if (pos) {
611
    if (pos) {
598
        int replen = strlen(rep);
612
      int replen = strlen(rep);
599
        int patlen = strlen(pat);
613
      int patlen = strlen(pat);
614
      while (pos) {
600
        if (replen < patlen) {
615
        if (replen < patlen) {
601
            char * end = word + strlen(word);
616
            char * end = word + strlen(word);
602
            char * next = pos + replen;
617
            char * next = pos + replen;
603
            char * prev = pos + strlen(pat);
618
            char * prev = pos + strlen(pat);
604
            for (; prev < end; *next = *prev, prev++, next++);
619
            for (; prev < end; *next = *prev, prev++, next++);
605
            *next = '\0';
620
            *next = '\0';
606
        } else if (replen > patlen) {
621
        } else if (replen > patlen) {
607
            char * end = pos + patlen;
622
            char * end = pos + patlen;
608
            char * next = word + strlen(word) + replen - patlen;
623
            char * next = word + strlen(word) + replen - patlen;
609
            char * prev = next - replen + patlen;
624
            char * prev = next - replen + patlen;
610
            for (; prev >= end; *next = *prev, prev--, next--);
625
            for (; prev >= end; *next = *prev, prev--, next--);
611
        }
626
        }
612
        strncpy(pos, rep, replen);
627
        strncpy(pos, rep, replen);
628
        pos = strstr(word, pat);
629
      }
613
    }
630
    }
614
    return word;
631
    return word;
615
}
632
}
616
633
617
 // reverse word 
634
 // reverse word 
618
 int reverseword(char * word) {
635
 int reverseword(char * word) {
619
   char r;
636
   char r;
620
   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
637
   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
 Lines 5165-5235   static struct cs_info iscii_devanagari_t Link Here 
5165
{ 0x00, 0xfa, 0xfa },
5182
{ 0x00, 0xfa, 0xfa },
5166
{ 0x00, 0xfb, 0xfb },
5183
{ 0x00, 0xfb, 0xfb },
5167
{ 0x00, 0xfc, 0xfc },
5184
{ 0x00, 0xfc, 0xfc },
5168
{ 0x00, 0xfd, 0xfd },
5185
{ 0x00, 0xfd, 0xfd },
5169
{ 0x00, 0xfe, 0xfe },
5186
{ 0x00, 0xfe, 0xfe },
5170
{ 0x00, 0xff, 0xff }
5187
{ 0x00, 0xff, 0xff }
5171
};
5188
};
5172
5189
5173
static struct enc_entry encds[] = {
5190
struct enc_entry {
5174
{"ISO8859-1",iso1_tbl},
5191
  const char * enc_name;
5175
{"ISO8859-2",iso2_tbl},
5192
  struct cs_info * cs_table;
5176
{"ISO8859-3",iso3_tbl},
5177
{"ISO8859-4",iso4_tbl},
5178
{"ISO8859-5",iso5_tbl},
5179
{"ISO8859-6",iso6_tbl},
5180
{"ISO8859-7",iso7_tbl},
5181
{"ISO8859-8",iso8_tbl},
5182
{"ISO8859-9",iso9_tbl},
5183
{"ISO8859-10",iso10_tbl},
5184
{"KOI8-R",koi8r_tbl},
5185
{"KOI8-U",koi8u_tbl},
5186
{"microsoft-cp1251",cp1251_tbl},
5187
{"ISO8859-13", iso13_tbl},
5188
{"ISO8859-14", iso14_tbl},
5189
{"ISO8859-15", iso15_tbl},
5190
{"ISCII-DEVANAGARI", iscii_devanagari_tbl}
5191
};
5193
};
5192
5194
5195
static struct enc_entry encds[] = {
5196
  {"iso88591",iso1_tbl},                     //ISO-8859-1
5197
  {"iso88592",iso2_tbl},                     //ISO-8859-2
5198
  {"iso88593",iso3_tbl},                     //ISO-8859-3
5199
  {"iso88594",iso4_tbl},                     //ISO-8859-4
5200
  {"iso88595",iso5_tbl},                     //ISO-8859-5
5201
  {"iso88596",iso6_tbl},                     //ISO-8859-6
5202
  {"iso88597",iso7_tbl},                     //ISO-8859-7
5203
  {"iso88598",iso8_tbl},                     //ISO-8859-8
5204
  {"iso88599",iso9_tbl},                     //ISO-8859-9
5205
  {"iso885910",iso10_tbl},                   //ISO-8859-10
5206
  {"iso885913", iso13_tbl},                  //ISO-8859-13
5207
  {"iso885914", iso14_tbl},                  //ISO-8859-14
5208
  {"iso885915", iso15_tbl},                  //ISO-8859-15
5209
  {"koi8r",koi8r_tbl},                       //KOI8-R
5210
  {"koi8u",koi8u_tbl},                       //KOI8-U
5211
  {"cp1251",cp1251_tbl},                     //CP-1251
5212
  {"microsoftcp1251",cp1251_tbl},            //microsoft-cp1251
5213
  {"xisciias", iscii_devanagari_tbl},        //x-iscii-as
5214
  {"isciidevanagari", iscii_devanagari_tbl}  //ISCII-DEVANAGARI
5215
};
5216
5217
/* map to lower case and remove non alphanumeric chars */
5218
static void toAsciiLowerAndRemoveNonAlphanumeric( const char* pName, char* pBuf )
5219
{
5220
    while ( *pName )
5221
    {
5222
        /* A-Z */
5223
        if ( (*pName >= 0x41) && (*pName <= 0x5A) )
5224
        {
5225
            *pBuf = (*pName)+0x20;  /* toAsciiLower */
5226
            pBuf++;
5227
        }
5228
        /* a-z, 0-9 */
5229
        else if ( ((*pName >= 0x61) && (*pName <= 0x7A)) ||
5230
                  ((*pName >= 0x30) && (*pName <= 0x39)) )
5231
        {
5232
            *pBuf = *pName;
5233
            pBuf++;
5234
        }
5235
5236
        pName++;
5237
    }
5238
5239
    *pBuf = '\0';
5240
}
5241
5193
struct cs_info * get_current_cs(const char * es) {
5242
struct cs_info * get_current_cs(const char * es) {
5194
  struct cs_info * ccs = encds[0].cs_table;
5243
  char *normalized_encoding = new char[strlen(es)+1];
5244
  toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding);
5245
5246
  struct cs_info * ccs = NULL;
5195
  int n = sizeof(encds) / sizeof(encds[0]);
5247
  int n = sizeof(encds) / sizeof(encds[0]);
5196
  for (int i = 0; i < n; i++) {
5248
  for (int i = 0; i < n; i++) {
5197
    if (strcmp(es,encds[i].enc_name) == 0) {
5249
    if (strcmp(normalized_encoding,encds[i].enc_name) == 0) {
5198
      ccs = encds[i].cs_table;
5250
      ccs = encds[i].cs_table;
5199
      break;
5251
      break;
5200
    }
5252
    }
5201
  }
5253
  }
5254
5255
  delete[] normalized_encoding;
5256
5257
  if (!ccs) {
5258
    HUNSPELL_WARNING(stderr, "error: unknown encoding %s: using %s as fallback\n", es, encds[0].enc_name);
5259
    ccs = encds[0].cs_table;
5260
  }
5261
5202
  return ccs;
5262
  return ccs;
5203
}
5263
}
5204
#else
5264
#else
5205
// XXX This function was rewritten for mozilla. Instead of storing the
5265
// XXX This function was rewritten for mozilla. Instead of storing the
5206
// conversion tables static in this file, create them when needed
5266
// conversion tables static in this file, create them when needed
5207
// with help the mozilla backend.
5267
// with help the mozilla backend.
5208
struct cs_info * get_current_cs(const char * es) {
5268
struct cs_info * get_current_cs(const char * es) {
5209
  struct cs_info *ccs;
5269
  struct cs_info *ccs;
5210
5270
5211
  nsCOMPtr<nsIUnicodeEncoder> encoder; 
5271
  nsCOMPtr<nsIUnicodeEncoder> encoder; 
5212
  nsCOMPtr<nsIUnicodeDecoder> decoder; 
5272
  nsCOMPtr<nsIUnicodeDecoder> decoder; 
5273
  nsCOMPtr<nsICaseConversion> caseConv;
5213
5274
5214
  nsresult rv;
5275
  nsresult rv;
5215
  nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv);
5276
  nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv);
5216
  if (NS_FAILED(rv))
5277
  if (NS_FAILED(rv))
5217
    return nsnull;
5278
    return nsnull;
5218
5279
5219
  rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder));
5280
  rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder));
5220
  if (NS_FAILED(rv))
5281
  if (NS_FAILED(rv))
5221
    return nsnull;
5282
    return nsnull;
5222
  encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?');
5283
  encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?');
5223
  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
5284
  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
5224
  if (NS_FAILED(rv))
5285
  if (NS_FAILED(rv))
5225
    return nsnull;
5286
    return nsnull;
5226
  decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
5287
  decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
5227
5288
5289
  caseConv = do_GetService(kUnicharUtilCID, &rv);
5290
  if (NS_FAILED(rv))
5291
    return nsnull;
5292
5228
  ccs = new cs_info[256];
5293
  ccs = new cs_info[256];
5229
5294
5230
  for (unsigned int i = 0; i <= 0xff; ++i) {
5295
  for (unsigned int i = 0; i <= 0xff; ++i) {
5231
    PRBool success = PR_FALSE;
5296
    PRBool success = PR_FALSE;
5232
    // We want to find the upper/lowercase equivalents of each byte
5297
    // We want to find the upper/lowercase equivalents of each byte
5233
    // in this 1-byte character encoding.  Call our encoding/decoding
5298
    // in this 1-byte character encoding.  Call our encoding/decoding
5234
    // APIs separately for each byte since they may reject some of the
5299
    // APIs separately for each byte since they may reject some of the
5235
    // bytes, and we want to handle errors separately for each byte.
5300
    // bytes, and we want to handle errors separately for each byte.
 Lines 5241-5264   struct cs_info * get_current_cs(const ch Link Here 
5241
      PRUnichar uni, uniCased;
5306
      PRUnichar uni, uniCased;
5242
      PRInt32 charLength = 1, uniLength = 1;
5307
      PRInt32 charLength = 1, uniLength = 1;
5243
5308
5244
      rv = decoder->Convert(&source, &charLength, &uni, &uniLength);
5309
      rv = decoder->Convert(&source, &charLength, &uni, &uniLength);
5245
      // Explicitly check NS_OK because we don't want to allow
5310
      // Explicitly check NS_OK because we don't want to allow
5246
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5311
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5247
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5312
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5248
        break;
5313
        break;
5249
      uniCased = ToLowerCase(uni);
5314
      rv = caseConv->ToLower(uni, &uniCased);
5315
      if (NS_FAILED(rv))
5316
        break;
5250
      rv = encoder->Convert(&uniCased, &uniLength, &lower, &charLength);
5317
      rv = encoder->Convert(&uniCased, &uniLength, &lower, &charLength);
5251
      // Explicitly check NS_OK because we don't want to allow
5318
      // Explicitly check NS_OK because we don't want to allow
5252
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5319
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5253
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5320
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5254
        break;
5321
        break;
5255
5322
5256
      uniCased = ToUpperCase(uni);
5323
      rv = caseConv->ToUpper(uni, &uniCased);
5324
      if (NS_FAILED(rv))
5325
        break;
5257
      rv = encoder->Convert(&uniCased, &uniLength, &upper, &charLength);
5326
      rv = encoder->Convert(&uniCased, &uniLength, &upper, &charLength);
5258
      // Explicitly check NS_OK because we don't want to allow
5327
      // Explicitly check NS_OK because we don't want to allow
5259
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5328
      // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT.
5260
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5329
      if (rv != NS_OK || charLength != 1 || uniLength != 1)
5261
        break;
5330
        break;
5262
5331
5263
      success = PR_TRUE;
5332
      success = PR_TRUE;
5264
    } while (0);
5333
    } while (0);
 Lines 5294-5354   char * get_casechars(const char * enc) { Link Here 
5294
    }
5363
    }
5295
    *p = '\0';
5364
    *p = '\0';
5296
#ifdef MOZILLA_CLIENT
5365
#ifdef MOZILLA_CLIENT
5297
    delete [] csconv;
5366
    delete [] csconv;
5298
#endif
5367
#endif
5299
    return mystrdup(expw);
5368
    return mystrdup(expw);
5300
}
5369
}
5301
5370
5371
// language to encoding default map
5302
5372
5373
struct lang_map {
5374
  const char * lang;
5375
  int num;
5376
};
5303
5377
5304
static struct lang_map lang2enc[] = {
5378
static struct lang_map lang2enc[] = {
5305
{"ar", "UTF-8", LANG_ar},
5379
{"ar", LANG_ar},
5306
{"az", "UTF-8", LANG_az},
5380
{"az", LANG_az},
5307
{"bg", "microsoft-cp1251", LANG_bg},
5381
{"bg", LANG_bg},
5308
{"ca", "ISO8859-1", LANG_ca},
5382
{"ca", LANG_ca},
5309
{"cs", "ISO8859-2", LANG_cs},
5383
{"cs", LANG_cs},
5310
{"da", "ISO8859-1", LANG_da},
5384
{"da", LANG_da},
5311
{"de", "ISO8859-1", LANG_de},
5385
{"de", LANG_de},
5312
{"el", "ISO8859-7", LANG_el},
5386
{"el", LANG_el},
5313
{"en", "ISO8859-1", LANG_en},
5387
{"en", LANG_en},
5314
{"es", "ISO8859-1", LANG_es},
5388
{"es", LANG_es},
5315
{"eu", "ISO8859-1", LANG_eu},
5389
{"eu", LANG_eu},
5316
{"gl", "ISO8859-1", LANG_gl},
5390
{"gl", LANG_gl},
5317
{"fr", "ISO8859-15", LANG_fr},
5391
{"fr", LANG_fr},
5318
{"hr", "ISO8859-2", LANG_hr},
5392
{"hr", LANG_hr},
5319
{"hu", "ISO8859-2", LANG_hu},
5393
{"hu", LANG_hu},
5320
{"it", "ISO8859-1", LANG_it},
5394
{"it", LANG_it},
5321
{"la", "ISO8859-1", LANG_la},
5395
{"la", LANG_la},
5322
{"lv", "ISO8859-13", LANG_lv},
5396
{"lv", LANG_lv},
5323
{"nl", "ISO8859-1", LANG_nl},
5397
{"nl", LANG_nl},
5324
{"pl", "ISO8859-2", LANG_pl},
5398
{"pl", LANG_pl},
5325
{"pt", "ISO8859-1", LANG_pt},
5399
{"pt", LANG_pt},
5326
{"sv", "ISO8859-1", LANG_sv},
5400
{"sv", LANG_sv},
5327
{"tr", "UTF-8", LANG_tr},
5401
{"tr", LANG_tr},
5328
{"ru", "KOI8-R", LANG_ru},
5402
{"ru", LANG_ru},
5329
{"uk", "KOI8-U", LANG_uk}
5403
{"uk", LANG_uk}
5330
};
5404
};
5331
5405
5332
5406
5333
const char * get_default_enc(const char * lang) {
5334
  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
5335
  for (int i = 0; i < n; i++) {
5336
    if (strcmp(lang,lang2enc[i].lang) == 0) {
5337
      return lang2enc[i].def_enc;
5338
    }
5339
  }
5340
  return NULL;
5341
}
5342
5343
int get_lang_num(const char * lang) {
5407
int get_lang_num(const char * lang) {
5344
  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
5408
  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
5345
  for (int i = 0; i < n; i++) {
5409
  for (int i = 0; i < n; i++) {
5346
    if (strncmp(lang,lang2enc[i].lang,2) == 0) {
5410
    if (strcmp(lang, lang2enc[i].lang) == 0) {
5347
      return lang2enc[i].num;
5411
      return lang2enc[i].num;
5348
    }
5412
    }
5349
  }
5413
  }
5350
  return LANG_xx;
5414
  return LANG_xx;
5351
}
5415
}
5352
5416
5353
#ifndef OPENOFFICEORG
5417
#ifndef OPENOFFICEORG
5354
#ifndef MOZILLA_CLIENT
5418
#ifndef MOZILLA_CLIENT
 Lines 5377-5404   int initialize_utf_tbl() { Link Here 
5377
void free_utf_tbl() {
5441
void free_utf_tbl() {
5378
  if (utf_tbl_count > 0) utf_tbl_count--;
5442
  if (utf_tbl_count > 0) utf_tbl_count--;
5379
  if (utf_tbl && (utf_tbl_count == 0)) {
5443
  if (utf_tbl && (utf_tbl_count == 0)) {
5380
    free(utf_tbl);
5444
    free(utf_tbl);
5381
    utf_tbl = NULL;
5445
    utf_tbl = NULL;
5382
  }
5446
  }
5383
}
5447
}
5384
5448
5449
#ifdef MOZILLA_CLIENT
5450
static nsCOMPtr<nsICaseConversion>& getcaseConv()
5451
{
5452
  nsresult rv;
5453
  static nsCOMPtr<nsICaseConversion> caseConv = do_GetService(kUnicharUtilCID, &rv);
5454
  return caseConv;
5455
}
5456
#endif
5457
5385
unsigned short unicodetoupper(unsigned short c, int langnum)
5458
unsigned short unicodetoupper(unsigned short c, int langnum)
5386
{
5459
{
5387
  // In Azeri and Turkish, I and i dictinct letters:
5460
  // In Azeri and Turkish, I and i dictinct letters:
5388
  // There are a dotless lower case i pair of upper `I',
5461
  // There are a dotless lower case i pair of upper `I',
5389
  // and an upper I with dot pair of lower `i'. 
5462
  // and an upper I with dot pair of lower `i'. 
5390
  if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr)))
5463
  if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr)))
5391
    return 0x0130;
5464
    return 0x0130;
5392
#ifdef OPENOFFICEORG
5465
#ifdef OPENOFFICEORG
5393
  return u_toupper(c);
5466
  return u_toupper(c);
5394
#else
5467
#else
5395
#ifdef MOZILLA_CLIENT
5468
#ifdef MOZILLA_CLIENT
5396
  return ToUpperCase((PRUnichar) c);
5469
  PRUnichar ch2;
5470
  getcaseConv()->ToUpper((PRUnichar) c, &ch2);
5471
  return ch2;
5397
#else
5472
#else
5398
  return (utf_tbl) ? utf_tbl[c].cupper : c;
5473
  return (utf_tbl) ? utf_tbl[c].cupper : c;
5399
#endif
5474
#endif
5400
#endif
5475
#endif
5401
}
5476
}
5402
5477
5403
unsigned short unicodetolower(unsigned short c, int langnum)
5478
unsigned short unicodetolower(unsigned short c, int langnum)
5404
{
5479
{
 Lines 5406-5422   unsigned short unicodetolower(unsigned s Link Here 
5406
  // There are a dotless lower case i pair of upper `I',
5481
  // There are a dotless lower case i pair of upper `I',
5407
  // and an upper I with dot pair of lower `i'. 
5482
  // and an upper I with dot pair of lower `i'. 
5408
  if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr)))
5483
  if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr)))
5409
    return 0x0131;
5484
    return 0x0131;
5410
#ifdef OPENOFFICEORG
5485
#ifdef OPENOFFICEORG
5411
  return u_tolower(c);
5486
  return u_tolower(c);
5412
#else
5487
#else
5413
#ifdef MOZILLA_CLIENT
5488
#ifdef MOZILLA_CLIENT
5414
  return ToLowerCase((PRUnichar) c);
5489
  PRUnichar ch2;
5490
  getcaseConv()->ToLower((PRUnichar) c, &ch2);
5491
  return ch2;
5415
#else
5492
#else
5416
  return (utf_tbl) ? utf_tbl[c].clower : c;
5493
  return (utf_tbl) ? utf_tbl[c].clower : c;
5417
#endif
5494
#endif
5418
#endif
5495
#endif
5419
}
5496
}
5420
5497
5421
int unicodeisalpha(unsigned short c)
5498
int unicodeisalpha(unsigned short c)
5422
{
5499
{
(-)a/extensions/spellcheck/hunspell/src/csutil.hxx (-32 / +4 lines)
Line     Link Here 
 Lines 168-219   LIBHUNSPELL_DLL_EXPORTED void freelist(c Link Here 
168
168
169
// character encoding information
169
// character encoding information
170
struct cs_info {
170
struct cs_info {
171
  unsigned char ccase;
171
  unsigned char ccase;
172
  unsigned char clower;
172
  unsigned char clower;
173
  unsigned char cupper;
173
  unsigned char cupper;
174
};
174
};
175
175
176
// Unicode character encoding information
177
struct unicode_info {
178
  unsigned short c;
179
  unsigned short cupper;
180
  unsigned short clower;
181
};
182
183
struct unicode_info2 {
184
  char cletter;
185
  unsigned short cupper;
186
  unsigned short clower;
187
};
188
189
LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl();
176
LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl();
190
LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl();
177
LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl();
191
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c, int langnum);
178
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c, int langnum);
192
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c, int langnum);
179
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c, int langnum);
193
LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c);
180
LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c);
194
181
195
struct enc_entry {
196
  const char * enc_name;
197
  struct cs_info * cs_table;
198
};
199
200
// language to encoding default map
201
202
struct lang_map {
203
  const char * lang;
204
  const char * def_enc;
205
  int num;
206
};
207
208
LIBHUNSPELL_DLL_EXPORTED struct cs_info * get_current_cs(const char * es);
182
LIBHUNSPELL_DLL_EXPORTED struct cs_info * get_current_cs(const char * es);
209
183
210
LIBHUNSPELL_DLL_EXPORTED const char * get_default_enc(const char * lang);
211
212
// get language identifiers of language codes
184
// get language identifiers of language codes
213
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char * lang);
185
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char * lang);
214
186
215
// get characters of the given 8bit encoding with lower- and uppercase forms
187
// get characters of the given 8bit encoding with lower- and uppercase forms
216
LIBHUNSPELL_DLL_EXPORTED char * get_casechars(const char * enc);
188
LIBHUNSPELL_DLL_EXPORTED char * get_casechars(const char * enc);
217
189
218
// convert null terminated string to all caps using encoding
190
// convert null terminated string to all caps using encoding
219
LIBHUNSPELL_DLL_EXPORTED void enmkallcap(char * d, const char * p, const char * encoding);
191
LIBHUNSPELL_DLL_EXPORTED void enmkallcap(char * d, const char * p, const char * encoding);
 Lines 271-302   LIBHUNSPELL_DLL_EXPORTED char * get_stor Link Here 
271
243
272
// hash entry macros
244
// hash entry macros
273
LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_DATA(struct hentry *h)
245
LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_DATA(struct hentry *h)
274
{
246
{
275
    char *ret;
247
    char *ret;
276
    if (!h->var)
248
    if (!h->var)
277
        ret = NULL;
249
        ret = NULL;
278
    else if (h->var & H_OPT_ALIASM)
250
    else if (h->var & H_OPT_ALIASM)
279
        ret = get_stored_pointer(&(h->word[0]) + h->blen + 1);
251
        ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1);
280
    else 
252
    else 
281
        ret = &(h->word[0]) + h->blen + 1;
253
        ret = HENTRY_WORD(h) + h->blen + 1;
282
    return ret;
254
    return ret;
283
}
255
}
284
256
285
// NULL-free version for warning-free OOo build
257
// NULL-free version for warning-free OOo build
286
LIBHUNSPELL_DLL_EXPORTED inline const char* HENTRY_DATA2(const struct hentry *h)
258
LIBHUNSPELL_DLL_EXPORTED inline const char* HENTRY_DATA2(const struct hentry *h)
287
{
259
{
288
    const char *ret;
260
    const char *ret;
289
    if (!h->var)
261
    if (!h->var)
290
        ret = "";
262
        ret = "";
291
    else if (h->var & H_OPT_ALIASM)
263
    else if (h->var & H_OPT_ALIASM)
292
        ret = get_stored_pointer(&(h->word[0]) + h->blen + 1);
264
        ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1);
293
    else
265
    else
294
        ret = &(h->word[0]) + h->blen + 1;
266
        ret = HENTRY_WORD(h) + h->blen + 1;
295
    return ret;
267
    return ret;
296
}
268
}
297
269
298
LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_FIND(struct hentry *h, const char *p)
270
LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_FIND(struct hentry *h, const char *p)
299
{
271
{
300
    return (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL);
272
    return (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL);
301
}
273
}
302
274
(-)a/extensions/spellcheck/hunspell/src/hashmgr.cpp (-1 / +1 lines)
Line     Link Here 
 Lines 497-512   int HashMgr::load_tables(const char * tp Link Here 
497
        if (!al) {
497
        if (!al) {
498
            HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n", dict->getlinenum());
498
            HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n", dict->getlinenum());
499
            *ap = '\0';
499
            *ap = '\0';
500
        }
500
        }
501
      } else {
501
      } else {
502
        al = decode_flags(&flags, ap + 1, dict);
502
        al = decode_flags(&flags, ap + 1, dict);
503
        if (al == -1) {
503
        if (al == -1) {
504
            HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
504
            HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
505
            delete dict;
505
            return 6;
506
            return 6;
506
        }
507
        }
507
        flag_qsort(flags, 0, al);
508
        flag_qsort(flags, 0, al);
508
      }
509
      }
509
    } else {
510
    } else {
510
      al = 0;
511
      al = 0;
511
      ap = NULL;
512
      ap = NULL;
512
      flags = NULL;
513
      flags = NULL;
 Lines 540-556   int HashMgr::hash(const char * word) con Link Here 
540
      hv ^= (*word++);
541
      hv ^= (*word++);
541
    }
542
    }
542
    return (unsigned long) hv % tablesize;
543
    return (unsigned long) hv % tablesize;
543
}
544
}
544
545
545
int HashMgr::decode_flags(unsigned short ** result, char * flags, FileMgr * af) {
546
int HashMgr::decode_flags(unsigned short ** result, char * flags, FileMgr * af) {
546
    int len;
547
    int len;
547
    if (*flags == '\0') {
548
    if (*flags == '\0') {
548
        HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n", af->getlinenum());
549
        *result = NULL;
549
        *result = NULL;
550
        return 0;
550
        return 0;
551
    }
551
    }
552
    switch (flag_mode) {
552
    switch (flag_mode) {
553
      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
553
      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
554
        len = strlen(flags);
554
        len = strlen(flags);
555
        if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n", af->getlinenum());
555
        if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n", af->getlinenum());
556
        len /= 2;
556
        len /= 2;
(-)a/extensions/spellcheck/hunspell/src/hunspell.cpp (-10 / +24 lines)
Line     Link Here 
 Lines 82-100   Hunspell::Hunspell(const char * affpath, Link Here 
82
    /* next set up the affix manager */
82
    /* next set up the affix manager */
83
    /* it needs access to the hash manager lookup methods */
83
    /* it needs access to the hash manager lookup methods */
84
    pAMgr = new AffixMgr(affpath, pHMgr, &maxdic, key);
84
    pAMgr = new AffixMgr(affpath, pHMgr, &maxdic, key);
85
85
86
    /* get the preferred try string and the dictionary */
86
    /* get the preferred try string and the dictionary */
87
    /* encoding from the Affix Manager for that dictionary */
87
    /* encoding from the Affix Manager for that dictionary */
88
    char * try_string = pAMgr->get_try_string();
88
    char * try_string = pAMgr->get_try_string();
89
    encoding = pAMgr->get_encoding();
89
    encoding = pAMgr->get_encoding();
90
    csconv = get_current_cs(encoding);
91
    langnum = pAMgr->get_langnum();
90
    langnum = pAMgr->get_langnum();
92
    utf8 = pAMgr->get_utf8();
91
    utf8 = pAMgr->get_utf8();
92
    if (!utf8)
93
        csconv = get_current_cs(encoding);
93
    complexprefixes = pAMgr->get_complexprefixes();
94
    complexprefixes = pAMgr->get_complexprefixes();
94
    wordbreak = pAMgr->get_breaktable();
95
    wordbreak = pAMgr->get_breaktable();
95
96
96
    /* and finally set up the suggestion manager */
97
    /* and finally set up the suggestion manager */
97
    pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
98
    pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
98
    if (try_string) free(try_string);
99
    if (try_string) free(try_string);
99
}
100
}
100
101
 Lines 618-633   struct hentry * Hunspell::checkword(cons Link Here 
618
        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
619
        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
619
        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
620
        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
620
     } else {
621
     } else {
621
        remove_ignored_chars(w2,ignoredchars);
622
        remove_ignored_chars(w2,ignoredchars);
622
     }
623
     }
623
     word = w2;
624
     word = w2;
624
  } else word = w;
625
  } else word = w;
625
626
627
  len = strlen(word);
628
629
  if (!len)
630
      return NULL;
631
626
  // word reversing wrapper for complex prefixes
632
  // word reversing wrapper for complex prefixes
627
  if (complexprefixes) {
633
  if (complexprefixes) {
628
    if (word != w2) {
634
    if (word != w2) {
629
      strcpy(w2, word);
635
      strcpy(w2, word);
630
      word = w2;
636
      word = w2;
631
    }
637
    }
632
    if (utf8) reverseword_utf(w2); else reverseword(w2);
638
    if (utf8) reverseword_utf(w2); else reverseword(w2);
633
  }
639
  }
 Lines 655-671   struct hentry * Hunspell::checkword(cons Link Here 
655
       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
661
       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
656
       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
662
       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
657
    )) he = he->next_homonym;
663
    )) he = he->next_homonym;
658
  }
664
  }
659
665
660
  // check with affixes
666
  // check with affixes
661
  if (!he && pAMgr) {
667
  if (!he && pAMgr) {
662
     // try stripping off affixes */
668
     // try stripping off affixes */
663
     len = strlen(word);
664
     he = pAMgr->affix_check(word, len, 0);
669
     he = pAMgr->affix_check(word, len, 0);
665
670
666
     // check compound restriction and onlyupcase
671
     // check compound restriction and onlyupcase
667
     if (he && he->astr && (
672
     if (he && he->astr && (
668
        (pAMgr->get_onlyincompound() &&
673
        (pAMgr->get_onlyincompound() &&
669
    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
674
    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
670
        (info && (*info & SPELL_INITCAP) &&
675
        (info && (*info & SPELL_INITCAP) &&
671
    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
676
    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
 Lines 1008-1027   int Hunspell::suggest(char*** slst, cons Link Here 
1008
  // remove duplications
1013
  // remove duplications
1009
  int l = 0;
1014
  int l = 0;
1010
  for (int j = 0; j < ns; j++) {
1015
  for (int j = 0; j < ns; j++) {
1011
    (*slst)[l] = (*slst)[j];
1016
    (*slst)[l] = (*slst)[j];
1012
    for (int k = 0; k < l; k++) {
1017
    for (int k = 0; k < l; k++) {
1013
      if (strcmp((*slst)[k], (*slst)[j]) == 0) {
1018
      if (strcmp((*slst)[k], (*slst)[j]) == 0) {
1014
        free((*slst)[j]);
1019
        free((*slst)[j]);
1015
        l--;
1020
        l--;
1021
        break;
1016
      }
1022
      }
1017
    }
1023
    }
1018
    l++;
1024
    l++;
1019
  }
1025
  }
1026
  ns = l;
1020
1027
1021
  // output conversion
1028
  // output conversion
1022
  rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
1029
  rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
1023
  for (int j = 0; rl && j < ns; j++) {
1030
  for (int j = 0; rl && j < ns; j++) {
1024
    if (rl->conv((*slst)[j], wspace)) {
1031
    if (rl->conv((*slst)[j], wspace)) {
1025
      free((*slst)[j]);
1032
      free((*slst)[j]);
1026
      (*slst)[j] = mystrdup(wspace);
1033
      (*slst)[j] = mystrdup(wspace);
1027
    }
1034
    }
 Lines 1524-1540   int Hunspell::analyze(char*** slst, cons Link Here 
1524
  // LANG_hu section: set dash information for suggestions
1531
  // LANG_hu section: set dash information for suggestions
1525
  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
1532
  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
1526
  if ((langnum == LANG_hu) && dash) {
1533
  if ((langnum == LANG_hu) && dash) {
1527
      *dash='\0';
1534
      *dash='\0';
1528
      // examine 2 sides of the dash
1535
      // examine 2 sides of the dash
1529
      if (dash[1] == '\0') { // base word ending with dash
1536
      if (dash[1] == '\0') { // base word ending with dash
1530
        if (spell(cw)) {
1537
        if (spell(cw)) {
1531
		char * p = pSMgr->suggest_morph(cw);
1538
		char * p = pSMgr->suggest_morph(cw);
1532
		if (p) return line_tok(pSMgr->suggest_morph(cw), slst, MSEP_REC);
1539
		if (p) {
1540
		    int ret = line_tok(p, slst, MSEP_REC);
1541
		    free(p);
1542
		    return ret;
1543
		}
1544
		
1533
	}
1545
	}
1534
      } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
1546
      } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
1535
        if (spell(cw) && (spell("-e"))) {
1547
        if (spell(cw) && (spell("-e"))) {
1536
                        st = pSMgr->suggest_morph(cw);
1548
                        st = pSMgr->suggest_morph(cw);
1537
                        if (st) {
1549
                        if (st) {
1538
                                mystrcat(result, st, MAXLNLEN);
1550
                                mystrcat(result, st, MAXLNLEN);
1539
                                free(st);
1551
                                free(st);
1540
                        }
1552
                        }
 Lines 1707-1723   int Hunspell::get_xml_list(char ***slst, Link Here 
1707
    if (!list) return 0;
1719
    if (!list) return 0;
1708
    for (p = list; (p = strstr(p, tag)); p++) n++;
1720
    for (p = list; (p = strstr(p, tag)); p++) n++;
1709
    if (n == 0) return 0;
1721
    if (n == 0) return 0;
1710
    *slst = (char **) malloc(sizeof(char *) * n);
1722
    *slst = (char **) malloc(sizeof(char *) * n);
1711
    if (!*slst) return 0;
1723
    if (!*slst) return 0;
1712
    for (p = list, n = 0; (p = strstr(p, tag)); p++, n++) {
1724
    for (p = list, n = 0; (p = strstr(p, tag)); p++, n++) {
1713
        int l = strlen(p);
1725
        int l = strlen(p);
1714
        (*slst)[n] = (char *) malloc(l + 1);
1726
        (*slst)[n] = (char *) malloc(l + 1);
1715
        if (!(*slst)[n]) return (n > 0 ? n - 1 : 0);
1727
        if (!(*slst)[n]) return n;
1716
        if (!get_xml_par((*slst)[n], p + strlen(tag) - 1, l)) {
1728
        if (!get_xml_par((*slst)[n], p + strlen(tag) - 1, l)) {
1717
            free((*slst)[n]);
1729
            free((*slst)[n]);
1718
            break;
1730
            break;
1719
        }
1731
        }
1720
    }
1732
    }
1721
    return n;
1733
    return n;
1722
}
1734
}
1723
1735
 Lines 1759-1780   int Hunspell::spellml(char*** slst, cons Link Here 
1759
      int n = get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1);
1771
      int n = get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1);
1760
      if (n == 0) return 0;
1772
      if (n == 0) return 0;
1761
      char * q3 = strstr(q2 + 1, "<word");
1773
      char * q3 = strstr(q2 + 1, "<word");
1762
      if (q3) {
1774
      if (q3) {
1763
        if (get_xml_par(cw2, strchr(q3, '>'), MAXWORDUTF8LEN - 1)) {
1775
        if (get_xml_par(cw2, strchr(q3, '>'), MAXWORDUTF8LEN - 1)) {
1764
            return generate(slst, cw, cw2);
1776
            return generate(slst, cw, cw2);
1765
        }
1777
        }
1766
      } else {
1778
      } else {
1767
        char ** slst2;
1779
        if ((q2 = strstr(q2 + 1, "<code"))) {
1768
        if ((q2 = strstr(q2 + 1, "<code")) &&
1780
          char ** slst2;
1769
          (n = get_xml_list(&slst2, strchr(q2, '>'), "<a>"))) {
1781
          if ((n = get_xml_list(&slst2, strchr(q2, '>'), "<a>"))) {
1770
             int n2 = generate(slst, cw, slst2, n);
1782
            int n2 = generate(slst, cw, slst2, n);
1771
             freelist(&slst2, n);
1783
            freelist(&slst2, n);
1772
             return uniqlist(*slst, n2);
1784
            return uniqlist(*slst, n2);
1785
          }
1786
          freelist(&slst2, n);
1773
        }
1787
        }
1774
      }
1788
      }
1775
  }
1789
  }
1776
  return 0;
1790
  return 0;
1777
}
1791
}
1778
1792
1779
1793
1780
#ifdef HUNSPELL_EXPERIMENTAL
1794
#ifdef HUNSPELL_EXPERIMENTAL
(-)a/extensions/spellcheck/hunspell/src/replist.cpp (+2 lines)
Line     Link Here 
 Lines 84-99   int RepList::match(const char * word, in Link Here 
84
}
84
}
85
85
86
int RepList::add(char * pat1, char * pat2) {
86
int RepList::add(char * pat1, char * pat2) {
87
    if (pos >= size || pat1 == NULL || pat2 == NULL) return 1;
87
    if (pos >= size || pat1 == NULL || pat2 == NULL) return 1;
88
    replentry * r = (replentry *) malloc(sizeof(replentry));
88
    replentry * r = (replentry *) malloc(sizeof(replentry));
89
    if (r == NULL) return 1;
89
    if (r == NULL) return 1;
90
    r->pattern = mystrrep(pat1, "_", " ");
90
    r->pattern = mystrrep(pat1, "_", " ");
91
    r->pattern2 = mystrrep(pat2, "_", " ");
91
    r->pattern2 = mystrrep(pat2, "_", " ");
92
    r->start = false;
93
    r->end = false;
92
    dat[pos++] = r;
94
    dat[pos++] = r;
93
    for (int i = pos - 1; i > 0; i--) {
95
    for (int i = pos - 1; i > 0; i--) {
94
      r = dat[i];
96
      r = dat[i];
95
      if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
97
      if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
96
          dat[i] = dat[i - 1];
98
          dat[i] = dat[i - 1];
97
          dat[i - 1] = r;
99
          dat[i - 1] = r;
98
      } else break;
100
      } else break;
99
    }
101
    }
(-)a/extensions/spellcheck/hunspell/src/suggestmgr.cpp (-19 / +29 lines)
Line     Link Here 
 Lines 88-111   SuggestMgr::SuggestMgr(const char * trym Link Here 
88
  langnum = 0;
88
  langnum = 0;
89
  complexprefixes = 0;  
89
  complexprefixes = 0;  
90
  
90
  
91
  maxSug = maxn;
91
  maxSug = maxn;
92
  nosplitsugs = 0;
92
  nosplitsugs = 0;
93
  maxngramsugs = MAXNGRAMSUGS;
93
  maxngramsugs = MAXNGRAMSUGS;
94
94
95
  if (pAMgr) {
95
  if (pAMgr) {
96
        char * enc = pAMgr->get_encoding();
97
        csconv = get_current_cs(enc);
98
        free(enc);
99
        langnum = pAMgr->get_langnum();
96
        langnum = pAMgr->get_langnum();
100
        ckey = pAMgr->get_key_string();
97
        ckey = pAMgr->get_key_string();
101
        nosplitsugs = pAMgr->get_nosplitsugs();
98
        nosplitsugs = pAMgr->get_nosplitsugs();
102
        if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs();
99
        if (pAMgr->get_maxngramsugs() >= 0)
100
            maxngramsugs = pAMgr->get_maxngramsugs();
103
        utf8 = pAMgr->get_utf8();
101
        utf8 = pAMgr->get_utf8();
102
        if (!utf8)
103
        {
104
            char * enc = pAMgr->get_encoding();
105
            csconv = get_current_cs(enc);
106
            free(enc);
107
        }
104
        complexprefixes = pAMgr->get_complexprefixes();
108
        complexprefixes = pAMgr->get_complexprefixes();
105
  }
109
  }
106
110
107
  if (ckey) {  
111
  if (ckey) {  
108
    if (utf8) {
112
    if (utf8) {
109
        w_char t[MAXSWL];    
113
        w_char t[MAXSWL];    
110
        ckeyl = u8_u16(t, MAXSWL, ckey);
114
        ckeyl = u8_u16(t, MAXSWL, ckey);
111
        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
115
        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
 Lines 173-189   int SuggestMgr::testsug(char** wlst, con Link Here 
173
177
174
int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
178
int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
175
    int * onlycompoundsug)
179
    int * onlycompoundsug)
176
{
180
{
177
  int nocompoundtwowords = 0;
181
  int nocompoundtwowords = 0;
178
  char ** wlst;    
182
  char ** wlst;    
179
  w_char word_utf[MAXSWL];
183
  w_char word_utf[MAXSWL];
180
  int wl = 0;
184
  int wl = 0;
181
185
  int nsugorig = nsug;
182
  char w2[MAXWORDUTF8LEN];
186
  char w2[MAXWORDUTF8LEN];
183
  const char * word = w;
187
  const char * word = w;
184
188
185
  // word reversing wrapper for complex prefixes
189
  // word reversing wrapper for complex prefixes
186
  if (complexprefixes) {
190
  if (complexprefixes) {
187
    strcpy(w2, w);
191
    strcpy(w2, w);
188
    if (utf8) reverseword_utf(w2); else reverseword(w2);
192
    if (utf8) reverseword_utf(w2); else reverseword(w2);
189
    word = w2;
193
    word = w2;
 Lines 234-250   int SuggestMgr::suggest(char*** slst, co Link Here 
234
238
235
    // did we just hit the wrong key in place of a good char (case and keyboard)
239
    // did we just hit the wrong key in place of a good char (case and keyboard)
236
    if ((nsug < maxSug) && (nsug > -1)) {
240
    if ((nsug < maxSug) && (nsug > -1)) {
237
        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
241
        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
238
                    badcharkey(wlst, word, nsug, cpdsuggest);
242
                    badcharkey(wlst, word, nsug, cpdsuggest);
239
    }
243
    }
240
244
241
    // only suggest compound words when no other suggestion
245
    // only suggest compound words when no other suggestion
242
    if ((cpdsuggest == 0) && (nsug > 0)) nocompoundtwowords=1;
246
    if ((cpdsuggest == 0) && (nsug > nsugorig)) nocompoundtwowords=1;
243
247
244
    // did we add a char that should not be there
248
    // did we add a char that should not be there
245
    if ((nsug < maxSug) && (nsug > -1)) {
249
    if ((nsug < maxSug) && (nsug > -1)) {
246
        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
250
        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
247
                    extrachar(wlst, word, nsug, cpdsuggest);
251
                    extrachar(wlst, word, nsug, cpdsuggest);
248
    }
252
    }
249
253
250
254
 Lines 444-482   int SuggestMgr::replchars(char** wlst, c Link Here 
444
  int numrep = pAMgr->get_numrep();
448
  int numrep = pAMgr->get_numrep();
445
  struct replentry* reptable = pAMgr->get_reptable();
449
  struct replentry* reptable = pAMgr->get_reptable();
446
  if (reptable==NULL) return ns;
450
  if (reptable==NULL) return ns;
447
  for (int i=0; i < numrep; i++ ) {
451
  for (int i=0; i < numrep; i++ ) {
448
      r = word;
452
      r = word;
449
      lenr = strlen(reptable[i].pattern2);
453
      lenr = strlen(reptable[i].pattern2);
450
      lenp = strlen(reptable[i].pattern);
454
      lenp = strlen(reptable[i].pattern);
451
      // search every occurence of the pattern in the word
455
      // search every occurence of the pattern in the word
452
      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
456
      while ((r=strstr(r, reptable[i].pattern)) != NULL && (!reptable[i].end || strlen(r) == strlen(reptable[i].pattern)) &&
457
        (!reptable[i].start || r == word)) {
453
          strcpy(candidate, word);
458
          strcpy(candidate, word);
454
          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
459
          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
455
          strcpy(candidate+(r-word),reptable[i].pattern2);
460
          strcpy(candidate+(r-word),reptable[i].pattern2);
456
          strcpy(candidate+(r-word)+lenr, r+lenp);
461
          strcpy(candidate+(r-word)+lenr, r+lenp);
457
          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
462
          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
458
          if (ns == -1) return -1;
463
          if (ns == -1) return -1;
459
          // check REP suggestions with space
464
          // check REP suggestions with space
460
          char * sp = strchr(candidate, ' ');
465
          char * sp = strchr(candidate, ' ');
461
          if (sp) {
466
          if (sp) {
462
            *sp = '\0';
467
            char * prev = candidate;
463
            if (checkword(candidate, strlen(candidate), 0, NULL, NULL)) {
468
            while (sp) {
464
              int oldns = ns;
469
              *sp = '\0';
470
              if (checkword(prev, strlen(prev), 0, NULL, NULL)) {
471
                int oldns = ns;
472
                *sp = ' ';
473
                ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
474
                if (ns == -1) return -1;
475
                if (oldns < ns) {
476
                  free(wlst[ns - 1]);
477
                  wlst[ns - 1] = mystrdup(candidate);
478
                  if (!wlst[ns - 1]) return -1;
479
                }
480
              }
465
              *sp = ' ';
481
              *sp = ' ';
466
              ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
482
              prev = sp + 1;
467
              if (ns == -1) return -1;
483
              sp = strchr(prev, ' ');
468
              if (oldns < ns) {
484
            }
469
                free(wlst[ns - 1]);
470
                wlst[ns - 1] = mystrdup(candidate);
471
                if (!wlst[ns - 1]) return -1;
472
              }
473
            }            
474
            *sp = ' ';
475
          }
485
          }
476
          r++; // search for the next letter
486
          r++; // search for the next letter
477
      }
487
      }
478
   }
488
   }
479
   return ns;
489
   return ns;
480
}
490
}
481
491
482
// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
492
// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
(-)a/extensions/spellcheck/hunspell/src/w_char.hxx (+2 lines)
Line     Link Here 
 Lines 42-52   typedef struct __attribute__ ((packed)) Link Here 
42
    unsigned char l;
42
    unsigned char l;
43
    unsigned char h;
43
    unsigned char h;
44
} w_char;
44
} w_char;
45
45
46
// two character arrays
46
// two character arrays
47
struct replentry {
47
struct replentry {
48
  char * pattern;
48
  char * pattern;
49
  char * pattern2;
49
  char * pattern2;
50
  bool start;
51
  bool end;
50
};
52
};
51
53
52
#endif
54
#endif

Return to bug 620626