Attachment #510818: Hunspell 1.3.1 patch v2 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.3.1
39
Additional Patches: 583582, 586671, 586686, 603311, 617953, 626195, 631607
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 (-65 / +252 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 104-119   AffixMgr::AffixMgr(const char * affpath, Link Here 
104
  compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
104
  compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
105
  checkcompounddup = 0; // forbid double words in compounds
105
  checkcompounddup = 0; // forbid double words in compounds
106
  checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution)
106
  checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution)
107
  checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds
107
  checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds
108
  checkcompoundtriple = 0; // forbid compounds with triple letters
108
  checkcompoundtriple = 0; // forbid compounds with triple letters
109
  simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt)
109
  simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt)
110
  forbiddenword = FORBIDDENWORD; // forbidden word signing flag
110
  forbiddenword = FORBIDDENWORD; // forbidden word signing flag
111
  nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
111
  nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
112
  nongramsuggest = FLAG_NULL;
112
  lang = NULL; // language
113
  lang = NULL; // language
113
  langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
114
  langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
114
  needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes
115
  needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes
115
  cpdwordmax = -1; // default: unlimited wordcount in compound words
116
  cpdwordmax = -1; // default: unlimited wordcount in compound words
116
  cpdmin = -1;  // undefined
117
  cpdmin = -1;  // undefined
117
  cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
118
  cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
118
  cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX)
119
  cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX)
119
  cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
120
  cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
 Lines 131-149   AffixMgr::AffixMgr(const char * affpath, Link Here 
131
  version=NULL; // affix and dictionary file version string
132
  version=NULL; // affix and dictionary file version string
132
  havecontclass=0; // flags of possible continuing classes (double affix)
133
  havecontclass=0; // flags of possible continuing classes (double affix)
133
  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
134
  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
134
  // in morhological description in dictionary file. It's often combined with PSEUDOROOT.
135
  // in morhological description in dictionary file. It's often combined with PSEUDOROOT.
135
  lemma_present = FLAG_NULL; 
136
  lemma_present = FLAG_NULL; 
136
  circumfix = FLAG_NULL; 
137
  circumfix = FLAG_NULL; 
137
  onlyincompound = FLAG_NULL; 
138
  onlyincompound = FLAG_NULL; 
138
  maxngramsugs = -1; // undefined
139
  maxngramsugs = -1; // undefined
140
  maxdiff = -1; // undefined
141
  onlymaxdiff = 0;
142
  maxcpdsugs = -1; // undefined
139
  nosplitsugs = 0;
143
  nosplitsugs = 0;
140
  sugswithdots = 0;
144
  sugswithdots = 0;
141
  keepcase = 0;
145
  keepcase = 0;
146
  forceucase = 0;
147
  warn = 0;
148
  forbidwarn = 0;
142
  checksharps = 0;
149
  checksharps = 0;
143
  substandard = FLAG_NULL;
150
  substandard = FLAG_NULL;
144
  fullstrip = 0;
151
  fullstrip = 0;
145
152
146
  sfx = NULL;
153
  sfx = NULL;
147
  pfx = NULL;
154
  pfx = NULL;
148
155
149
  for (int i=0; i < SETSIZE; i++) {
156
  for (int i=0; i < SETSIZE; i++) {
 Lines 269-284   AffixMgr::~AffixMgr() Link Here 
269
  FREE_FLAG(compoundbegin);
276
  FREE_FLAG(compoundbegin);
270
  FREE_FLAG(compoundmiddle);
277
  FREE_FLAG(compoundmiddle);
271
  FREE_FLAG(compoundend);
278
  FREE_FLAG(compoundend);
272
  FREE_FLAG(compoundpermitflag);
279
  FREE_FLAG(compoundpermitflag);
273
  FREE_FLAG(compoundforbidflag);
280
  FREE_FLAG(compoundforbidflag);
274
  FREE_FLAG(compoundroot);
281
  FREE_FLAG(compoundroot);
275
  FREE_FLAG(forbiddenword);
282
  FREE_FLAG(forbiddenword);
276
  FREE_FLAG(nosuggest);
283
  FREE_FLAG(nosuggest);
284
  FREE_FLAG(nongramsuggest);
277
  FREE_FLAG(needaffix);
285
  FREE_FLAG(needaffix);
278
  FREE_FLAG(lemma_present);
286
  FREE_FLAG(lemma_present);
279
  FREE_FLAG(circumfix);
287
  FREE_FLAG(circumfix);
280
  FREE_FLAG(onlyincompound);
288
  FREE_FLAG(onlyincompound);
281
  
289
  
282
  cpdwordmax = 0;
290
  cpdwordmax = 0;
283
  pHMgr = NULL;
291
  pHMgr = NULL;
284
  cpdmin = 0;
292
  cpdmin = 0;
 Lines 472-487   int AffixMgr::parse_file(const char * a Link Here 
472
480
473
       if (strncmp(line,"NOSUGGEST",9) == 0) {
481
       if (strncmp(line,"NOSUGGEST",9) == 0) {
474
          if (parse_flag(line, &nosuggest, afflst)) {
482
          if (parse_flag(line, &nosuggest, afflst)) {
475
             delete afflst;
483
             delete afflst;
476
             return 1;
484
             return 1;
477
          }
485
          }
478
       }
486
       }
479
487
488
       if (strncmp(line,"NONGRAMSUGGEST",14) == 0) {
489
          if (parse_flag(line, &nongramsuggest, afflst)) {
490
             delete afflst;
491
             return 1;
492
          }
493
       }
494
480
       /* parse in the flag used by forbidden words */
495
       /* parse in the flag used by forbidden words */
481
       if (strncmp(line,"FORBIDDENWORD",13) == 0) {
496
       if (strncmp(line,"FORBIDDENWORD",13) == 0) {
482
          if (parse_flag(line, &forbiddenword, afflst)) {
497
          if (parse_flag(line, &forbiddenword, afflst)) {
483
             delete afflst;
498
             delete afflst;
484
             return 1;
499
             return 1;
485
          }
500
          }
486
       }
501
       }
487
502
 Lines 651-666   int AffixMgr::parse_file(const char * a Link Here 
651
666
652
       if (strncmp(line,"MAXNGRAMSUGS",12) == 0) {
667
       if (strncmp(line,"MAXNGRAMSUGS",12) == 0) {
653
          if (parse_num(line, &maxngramsugs, afflst)) {
668
          if (parse_num(line, &maxngramsugs, afflst)) {
654
             delete afflst;
669
             delete afflst;
655
             return 1;
670
             return 1;
656
          }
671
          }
657
       }
672
       }
658
673
674
       if (strncmp(line,"ONLYMAXDIFF", 11) == 0)
675
                   onlymaxdiff = 1;
676
677
       if (strncmp(line,"MAXDIFF",7) == 0) {
678
          if (parse_num(line, &maxdiff, afflst)) {
679
             delete afflst;
680
             return 1;
681
          }
682
       }
683
684
       if (strncmp(line,"MAXCPDSUGS",10) == 0) {
685
          if (parse_num(line, &maxcpdsugs, afflst)) {
686
             delete afflst;
687
             return 1;
688
          }
689
       }
690
659
       if (strncmp(line,"NOSPLITSUGS",11) == 0) {
691
       if (strncmp(line,"NOSPLITSUGS",11) == 0) {
660
                   nosplitsugs=1;
692
                   nosplitsugs=1;
661
       }
693
       }
662
694
663
       if (strncmp(line,"FULLSTRIP",9) == 0) {
695
       if (strncmp(line,"FULLSTRIP",9) == 0) {
664
                   fullstrip=1;
696
                   fullstrip=1;
665
       }
697
       }
666
698
 Lines 671-686   int AffixMgr::parse_file(const char * a Link Here 
671
       /* parse in the flag used by forbidden words */
703
       /* parse in the flag used by forbidden words */
672
       if (strncmp(line,"KEEPCASE",8) == 0) {
704
       if (strncmp(line,"KEEPCASE",8) == 0) {
673
          if (parse_flag(line, &keepcase, afflst)) {
705
          if (parse_flag(line, &keepcase, afflst)) {
674
             delete afflst;
706
             delete afflst;
675
             return 1;
707
             return 1;
676
          }
708
          }
677
       }
709
       }
678
710
711
       /* parse in the flag used by `forceucase' */
712
       if (strncmp(line,"FORCEUCASE",10) == 0) {
713
          if (parse_flag(line, &forceucase, afflst)) {
714
             delete afflst;
715
             return 1;
716
          }
717
       }
718
719
       /* parse in the flag used by `warn' */
720
       if (strncmp(line,"WARN",4) == 0) {
721
          if (parse_flag(line, &warn, afflst)) {
722
             delete afflst;
723
             return 1;
724
          }
725
       }
726
727
       if (strncmp(line,"FORBIDWARN",10) == 0) {
728
                   forbidwarn=1;
729
       }
730
679
       /* parse in the flag used by the affix generator */
731
       /* parse in the flag used by the affix generator */
680
       if (strncmp(line,"SUBSTANDARD",11) == 0) {
732
       if (strncmp(line,"SUBSTANDARD",11) == 0) {
681
          if (parse_flag(line, &substandard, afflst)) {
733
          if (parse_flag(line, &substandard, afflst)) {
682
             delete afflst;
734
             delete afflst;
683
             return 1;
735
             return 1;
684
          }
736
          }
685
       }
737
       }
686
738
 Lines 758-774   int AffixMgr::parse_file(const char * a Link Here 
758
                *(expw + strlen(expw)) = (char) i;
810
                *(expw + strlen(expw)) = (char) i;
759
        }
811
        }
760
    }
812
    }
761
813
762
    wordchars = mystrdup(expw);
814
    wordchars = mystrdup(expw);
763
    }
815
    }
764
816
765
    // default BREAK definition
817
    // default BREAK definition
766
    if (!breaktable) {
818
    if (numbreak == -1) {
767
        breaktable = (char **) malloc(sizeof(char *) * 3);
819
        breaktable = (char **) malloc(sizeof(char *) * 3);
768
        if (!breaktable) return 1;
820
        if (!breaktable) return 1;
769
        breaktable[0] = mystrdup("-");
821
        breaktable[0] = mystrdup("-");
770
        breaktable[1] = mystrdup("^-");
822
        breaktable[1] = mystrdup("^-");
771
        breaktable[2] = mystrdup("-$");
823
        breaktable[2] = mystrdup("-$");
772
        if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3;
824
        if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3;
773
    }
825
    }
774
    return 0;
826
    return 0;
 Lines 1316-1342   int AffixMgr::cpdrep_check(const char * Link Here 
1316
          if (candidate_check(candidate,strlen(candidate))) return 1;
1368
          if (candidate_check(candidate,strlen(candidate))) return 1;
1317
          r++; // search for the next letter
1369
          r++; // search for the next letter
1318
      }
1370
      }
1319
   }
1371
   }
1320
   return 0;
1372
   return 0;
1321
}
1373
}
1322
1374
1323
// forbid compoundings when there are special patterns at word bound
1375
// forbid compoundings when there are special patterns at word bound
1324
int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2)
1376
int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2, const char affixed)
1325
{
1377
{
1326
  int len;
1378
  int len;
1327
  for (int i = 0; i < numcheckcpd; i++) {
1379
  for (int i = 0; i < numcheckcpd; i++) {
1328
      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
1380
      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
1329
        (!r1 || !checkcpdtable[i].cond ||
1381
        (!r1 || !checkcpdtable[i].cond ||
1330
          (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) &&
1382
          (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) &&
1331
        (!r2 || !checkcpdtable[i].cond2 ||
1383
        (!r2 || !checkcpdtable[i].cond2 ||
1332
          (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) &&
1384
          (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) &&
1333
        (len = strlen(checkcpdtable[i].pattern)) && (pos > len) &&
1385
        // zero length pattern => only TESTAFF
1334
        (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1;
1386
        // zero pattern (0/flag) => unmodified stem (zero affixes allowed)
1387
        (!*(checkcpdtable[i].pattern) || (
1388
            (*(checkcpdtable[i].pattern)=='0' && r1->blen <= pos && strncmp(word + pos - r1->blen, r1->word, r1->blen) == 0) ||
1389
            (*(checkcpdtable[i].pattern)!='0' && (len = strlen(checkcpdtable[i].pattern)) &&
1390
                strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)))) {
1391
            return 1;
1392
        }
1335
  }
1393
  }
1336
  return 0;
1394
  return 0;
1337
}
1395
}
1338
1396
1339
// forbid compounding with neighbouring upper and lower case characters at word bounds
1397
// forbid compounding with neighbouring upper and lower case characters at word bounds
1340
int AffixMgr::cpdcase_check(const char * word, int pos)
1398
int AffixMgr::cpdcase_check(const char * word, int pos)
1341
{
1399
{
1342
  if (utf8) {
1400
  if (utf8) {
 Lines 1511-1567   void AffixMgr::setcminmax(int * cmin, in Link Here 
1511
          for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--);
1569
          for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--);
1512
        }
1570
        }
1513
    } else {
1571
    } else {
1514
        *cmin = cpdmin;
1572
        *cmin = cpdmin;
1515
        *cmax = len - cpdmin + 1;
1573
        *cmax = len - cpdmin + 1;
1516
    }
1574
    }
1517
}
1575
}
1518
1576
1577
1519
// check if compound word is correctly spelled
1578
// check if compound word is correctly spelled
1520
// hu_mov_rule = spec. Hungarian rule (XXX)
1579
// hu_mov_rule = spec. Hungarian rule (XXX)
1521
struct hentry * AffixMgr::compound_check(const char * word, int len, 
1580
struct hentry * AffixMgr::compound_check(const char * word, int len, 
1522
    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
1581
    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
1523
    char hu_mov_rule = 0, char is_sug = 0)
1582
    char hu_mov_rule = 0, char is_sug = 0, int * info = NULL)
1524
{
1583
{
1525
    int i; 
1584
    int i; 
1526
    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
1585
    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
1527
    struct hentry * rv = NULL;
1586
    struct hentry * rv = NULL;
1528
    struct hentry * rv_first;
1587
    struct hentry * rv_first;
1529
    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
1588
    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
1530
    char st [MAXWORDUTF8LEN + 4];
1589
    char st [MAXWORDUTF8LEN + 4];
1531
    char ch;
1590
    char ch = '\0';
1532
    int cmin;
1591
    int cmin;
1533
    int cmax;
1592
    int cmax;
1534
    int striple = 0;
1593
    int striple = 0;
1535
    int scpd = 0;
1594
    int scpd = 0;
1536
    int soldi = 0;
1595
    int soldi = 0;
1537
    int oldcmin = 0;
1596
    int oldcmin = 0;
1538
    int oldcmax = 0;
1597
    int oldcmax = 0;
1539
    int oldlen = 0;
1598
    int oldlen = 0;
1540
    int checkedstriple = 0;
1599
    int checkedstriple = 0;
1600
    int onlycpdrule;
1601
    int affixed = 0;
1602
    hentry ** oldwords = words;
1541
1603
1542
    int checked_prefix;
1604
    int checked_prefix;
1543
1605
1544
    setcminmax(&cmin, &cmax, word, len);
1606
    setcminmax(&cmin, &cmax, word, len);
1545
1607
1546
    strcpy(st, word);
1608
    strcpy(st, word);
1547
1609
1548
    for (i = cmin; i < cmax; i++) {
1610
    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
1611
        // go to end of the UTF-8 character
1555
        if (utf8) {
1612
        if (utf8) {
1556
            for (; (st[i] & 0xc0) == 0x80; i++);
1613
            for (; (st[i] & 0xc0) == 0x80; i++);
1557
            if (i >= cmax) return NULL;
1614
            if (i >= cmax) return NULL;
1558
        }
1615
        }
1559
1616
1617
        words = oldwords;
1618
        onlycpdrule = (words) ? 1 : 0;
1619
1620
        do { // onlycpdrule loop
1621
1622
        oldnumsyllable = numsyllable;
1623
        oldwordnum = wordnum;
1624
        checked_prefix = 0;
1625
1626
1560
        do { // simplified checkcompoundpattern loop
1627
        do { // simplified checkcompoundpattern loop
1561
1628
1562
        if (scpd > 0) {
1629
        if (scpd > 0) {
1563
          for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 ||
1630
          for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 ||
1564
            strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++);
1631
            strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++);
1565
1632
1566
          if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop
1633
          if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop
1567
          strcpy(st + i, checkcpdtable[scpd-1].pattern);
1634
          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);
1641
          len += strlen(checkcpdtable[scpd-1].pattern) + strlen(checkcpdtable[scpd-1].pattern2) - strlen(checkcpdtable[scpd-1].pattern3);
1575
          oldcmin = cmin;
1642
          oldcmin = cmin;
1576
          oldcmax = cmax;
1643
          oldcmax = cmax;
1577
          setcminmax(&cmin, &cmax, st, len);
1644
          setcminmax(&cmin, &cmax, st, len);
1578
1645
1579
          cmax = len - cpdmin + 1;
1646
          cmax = len - cpdmin + 1;
1580
        }
1647
        }
1581
1648
1582
1583
        ch = st[i];
1649
        ch = st[i];
1584
        st[i] = '\0';
1650
        st[i] = '\0';
1585
1651
1586
        sfx = NULL;
1652
        sfx = NULL;
1587
        pfx = NULL;
1653
        pfx = NULL;
1588
1654
1589
        // FIRST WORD
1655
        // FIRST WORD
1590
1656
1657
        affixed = 1;
1591
        rv = lookup(st); // perhaps without prefix
1658
        rv = lookup(st); // perhaps without prefix
1592
1659
1593
        // search homonym with compound flag
1660
        // search homonym with compound flag
1594
        while ((rv) && !hu_mov_rule &&
1661
        while ((rv) && !hu_mov_rule &&
1595
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
1662
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
1596
                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
1663
                !((compoundflag && !words && !onlycpdrule && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
1597
                  (compoundbegin && !wordnum &&
1664
                  (compoundbegin && !wordnum && !onlycpdrule && 
1598
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
1665
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
1599
                  (compoundmiddle && wordnum && !words &&
1666
                  (compoundmiddle && wordnum && !words && !onlycpdrule &&
1600
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
1667
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
1601
                  (numdefcpd &&
1668
                  (numdefcpd && onlycpdrule &&
1602
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
1669
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
1603
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))) ||
1670
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))) ||
1604
                  (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL &&
1671
                  (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL &&
1605
                    !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen)))
1672
                    !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen)))
1606
                  ) {
1673
                  ) {
1607
            rv = rv->next_homonym;
1674
            rv = rv->next_homonym;
1608
        }
1675
        }
1609
1676
1677
        if (rv) affixed = 0;
1678
1610
        if (!rv) {
1679
        if (!rv) {
1680
            if (onlycpdrule) break;
1611
            if (compoundflag && 
1681
            if (compoundflag && 
1612
             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
1682
             !(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,
1683
                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 &&
1684
                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
1615
                    sfx->getCont() &&
1685
                    sfx->getCont() &&
1616
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
1686
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
1617
                            sfx->getContLen())) || (compoundend &&
1687
                            sfx->getContLen())) || (compoundend &&
1618
                        TESTAFF(sfx->getCont(), compoundend, 
1688
                        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)) ||
1696
                ((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)))) ||
1697
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
1628
              ((wordnum > 0) && compoundmiddle &&
1698
              ((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)) ||
1699
                ((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)))))
1700
                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
1631
              ) checked_prefix = 1;
1701
              ) checked_prefix = 1;
1632
        // else check forbiddenwords and needaffix
1702
        // else check forbiddenwords and needaffix
1633
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1703
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1634
            TESTAFF(rv->astr, needaffix, rv->alen) || 
1704
            TESTAFF(rv->astr, needaffix, rv->alen) ||
1705
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1635
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
1706
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
1636
             )) {
1707
             )) {
1637
                st[i] = ch;
1708
                st[i] = ch;
1638
                continue;
1709
                //continue;
1710
                break;
1639
        }
1711
        }
1640
1712
1641
            // check non_compound flag in suffix and prefix
1713
            // check non_compound flag in suffix and prefix
1642
            if ((rv) && !hu_mov_rule &&
1714
            if ((rv) && !hu_mov_rule &&
1643
                ((pfx && pfx->getCont() &&
1715
                ((pfx && pfx->getCont() &&
1644
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1716
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1645
                        pfx->getContLen())) ||
1717
                        pfx->getContLen())) ||
1646
                (sfx && sfx->getCont() &&
1718
                (sfx && sfx->getCont() &&
 Lines 1668-1683   struct hentry * AffixMgr::compound_check Link Here 
1668
                (sfx && sfx->getCont() &&
1740
                (sfx && sfx->getCont() &&
1669
                    TESTAFF(sfx->getCont(), compoundmiddle, 
1741
                    TESTAFF(sfx->getCont(), compoundmiddle, 
1670
                        sfx->getContLen())))) {
1742
                        sfx->getContLen())))) {
1671
                    rv = NULL;
1743
                    rv = NULL;
1672
            }
1744
            }
1673
1745
1674
        // check forbiddenwords
1746
        // check forbiddenwords
1675
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1747
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1748
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1676
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
1749
            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
1677
                return NULL;
1750
                return NULL;
1678
            }
1751
            }
1679
1752
1680
        // increment word number, if the second root has a compoundroot flag
1753
        // increment word number, if the second root has a compoundroot flag
1681
        if ((rv) && compoundroot && 
1754
        if ((rv) && compoundroot && 
1682
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1755
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1683
                wordnum++;
1756
                wordnum++;
 Lines 1724-1746   struct hentry * AffixMgr::compound_check Link Here 
1724
               )
1797
               )
1725
             )
1798
             )
1726
         ) { // first word is ok condition
1799
         ) { // first word is ok condition
1727
1800
1728
// LANG_hu section: spec. Hungarian rule
1801
// LANG_hu section: spec. Hungarian rule
1729
            if (langnum == LANG_hu) {
1802
            if (langnum == LANG_hu) {
1730
                // calculate syllable number of the word
1803
                // calculate syllable number of the word
1731
                numsyllable += get_syllable(st, i);
1804
                numsyllable += get_syllable(st, i);
1732
1733
                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
1805
                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
1734
                if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++;
1806
                if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++;
1735
            }
1807
            }
1736
// END of LANG_hu section
1808
// END of LANG_hu section
1737
1809
1738
1739
            // NEXT WORD(S)
1810
            // NEXT WORD(S)
1740
            rv_first = rv;
1811
            rv_first = rv;
1741
            st[i] = ch;
1812
            st[i] = ch;
1742
1813
1743
        do { // striple loop
1814
        do { // striple loop
1744
1815
1745
            // check simplifiedtriple
1816
            // check simplifiedtriple
1746
            if (simplifiedtriple) { 
1817
            if (simplifiedtriple) { 
 Lines 1758-1792   struct hentry * AffixMgr::compound_check Link Here 
1758
                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
1829
                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
1759
                           (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))) ||
1830
                           (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))) ||
1760
                             (scpd != 0 && checkcpdtable[scpd-1].cond2 != FLAG_NULL &&
1831
                             (scpd != 0 && checkcpdtable[scpd-1].cond2 != FLAG_NULL &&
1761
                                !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1832
                                !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1762
                           )) {
1833
                           )) {
1763
            rv = rv->next_homonym;
1834
            rv = rv->next_homonym;
1764
        }
1835
        }
1765
1836
1837
            // check FORCEUCASE
1838
            if (rv && forceucase && (rv) &&
1839
                (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL;
1840
1766
            if (rv && words && words[wnum + 1]) return rv_first;
1841
            if (rv && words && words[wnum + 1]) return rv_first;
1767
1842
1768
            oldnumsyllable2 = numsyllable;
1843
            oldnumsyllable2 = numsyllable;
1769
            oldwordnum2 = wordnum;
1844
            oldwordnum2 = wordnum;
1770
1845
1846
1771
// LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code
1847
// LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code
1772
            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
1848
            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
1773
                numsyllable--;
1849
                numsyllable--;
1774
            }
1850
            }
1775
// END of LANG_hu section
1851
// END of LANG_hu section
1776
1852
1777
            // increment word number, if the second root has a compoundroot flag
1853
            // increment word number, if the second root has a compoundroot flag
1778
            if ((rv) && (compoundroot) && 
1854
            if ((rv) && (compoundroot) && 
1779
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1855
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1780
                    wordnum++;
1856
                    wordnum++;
1781
            }
1857
            }
1782
1858
1783
            // check forbiddenwords
1859
            // check forbiddenwords
1784
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1860
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1861
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1785
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1862
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1786
1863
1787
            // second word is acceptable, as a root?
1864
            // second word is acceptable, as a root?
1788
            // hungarian conventions: compounding is acceptable,
1865
            // hungarian conventions: compounding is acceptable,
1789
            // when compound forms consist of 2 words, or if more,
1866
            // when compound forms consist of 2 words, or if more,
1790
            // then the syllable number of root words must be 6, or lesser.
1867
            // then the syllable number of root words must be 6, or lesser.
1791
1868
1792
            if ((rv) && (
1869
            if ((rv) && (
 Lines 1795-1811   struct hentry * AffixMgr::compound_check Link Here 
1795
                    )
1872
                    )
1796
                && (
1873
                && (
1797
                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
1874
                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
1798
                      ((cpdmaxsyllable!=0) && 
1875
                      ((cpdmaxsyllable!=0) && 
1799
                          (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable))
1876
                          (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable))
1800
                    ) &&
1877
                    ) &&
1801
               (
1878
               (
1802
                 // test CHECKCOMPOUNDPATTERN
1879
                 // test CHECKCOMPOUNDPATTERN
1803
                 !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv)
1880
                 !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv, 0)
1804
               ) &&
1881
               ) &&
1805
                (
1882
                (
1806
                     (!checkcompounddup || (rv != rv_first))
1883
                     (!checkcompounddup || (rv != rv_first))
1807
                   )
1884
                   )
1808
            // test CHECKCOMPOUNDPATTERN conditions
1885
            // test CHECKCOMPOUNDPATTERN conditions
1809
                && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL ||
1886
                && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL ||
1810
                      TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1887
                      TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))
1811
                )
1888
                )
 Lines 1816-1864   struct hentry * AffixMgr::compound_check Link Here 
1816
            }
1893
            }
1817
1894
1818
            numsyllable = oldnumsyllable2;
1895
            numsyllable = oldnumsyllable2;
1819
            wordnum = oldwordnum2;
1896
            wordnum = oldwordnum2;
1820
1897
1821
            // perhaps second word has prefix or/and suffix
1898
            // perhaps second word has prefix or/and suffix
1822
            sfx = NULL;
1899
            sfx = NULL;
1823
            sfxflag = FLAG_NULL;
1900
            sfxflag = FLAG_NULL;
1824
            rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
1901
            rv = (compoundflag && !onlycpdrule) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
1825
            if (!rv && compoundend) {
1902
            if (!rv && compoundend && !onlycpdrule) {
1826
                sfx = NULL;
1903
                sfx = NULL;
1827
                pfx = NULL;
1904
                pfx = NULL;
1828
                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
1905
                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
1829
            }
1906
            }
1830
1907
1831
            if (!rv && numdefcpd && words) {
1908
            if (!rv && numdefcpd && words) {
1832
                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
1909
                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;
1910
                if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first;
1834
                rv = NULL;
1911
                rv = NULL;
1835
            }
1912
            }
1836
1913
1837
            // test CHECKCOMPOUNDPATTERN conditions (allowed forms)
1914
            // test CHECKCOMPOUNDPATTERN conditions (allowed forms)
1838
            if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || 
1915
            if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || 
1839
                TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL;
1916
                TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL;
1840
1917
1841
            // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
1918
            // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
1842
            if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv)) rv = NULL;
1919
            if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) rv = NULL;
1843
1920
1844
            // check non_compound flag in suffix and prefix
1921
            // check non_compound flag in suffix and prefix
1845
            if ((rv) && 
1922
            if ((rv) && 
1846
                ((pfx && pfx->getCont() &&
1923
                ((pfx && pfx->getCont() &&
1847
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1924
                    TESTAFF(pfx->getCont(), compoundforbidflag, 
1848
                        pfx->getContLen())) ||
1925
                        pfx->getContLen())) ||
1849
                (sfx && sfx->getCont() &&
1926
                (sfx && sfx->getCont() &&
1850
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
1927
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
1851
                        sfx->getContLen())))) {
1928
                        sfx->getContLen())))) {
1852
                    rv = NULL;
1929
                    rv = NULL;
1853
            }
1930
            }
1854
1931
1932
            // check FORCEUCASE
1933
            if (rv && forceucase && (rv) &&
1934
                (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL;
1935
1855
            // check forbiddenwords
1936
            // check forbiddenwords
1856
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1937
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
1938
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
1857
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1939
               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
1858
1940
1859
            // pfxappnd = prefix of word+i, or NULL
1941
            // pfxappnd = prefix of word+i, or NULL
1860
            // calculate syllable number of prefix.
1942
            // calculate syllable number of prefix.
1861
            // hungarian convention: when syllable number of prefix is more,
1943
            // hungarian convention: when syllable number of prefix is more,
1862
            // than 1, the prefix+word counts as two words.
1944
            // than 1, the prefix+word counts as two words.
1863
1945
1864
            if (langnum == LANG_hu) {
1946
            if (langnum == LANG_hu) {
 Lines 1878-1894   struct hentry * AffixMgr::compound_check Link Here 
1878
1960
1879
                // increment syllable num, if last word has a SYLLABLENUM flag
1961
                // increment syllable num, if last word has a SYLLABLENUM flag
1880
                // and the suffix is beginning `s'
1962
                // and the suffix is beginning `s'
1881
1963
1882
                if (cpdsyllablenum) {
1964
                if (cpdsyllablenum) {
1883
                    switch (sfxflag) {
1965
                    switch (sfxflag) {
1884
                        case 'c': { numsyllable+=2; break; }
1966
                        case 'c': { numsyllable+=2; break; }
1885
                        case 'J': { numsyllable += 1; break; }
1967
                        case 'J': { numsyllable += 1; break; }
1886
                        case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
1968
                        case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
1887
                    }
1969
                    }
1888
                }
1970
                }
1889
            }
1971
            }
1890
1972
1891
            // increment word number, if the second word has a compoundroot flag
1973
            // increment word number, if the second word has a compoundroot flag
1892
            if ((rv) && (compoundroot) && 
1974
            if ((rv) && (compoundroot) && 
1893
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1975
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
1894
                    wordnum++;
1976
                    wordnum++;
 Lines 1913-1937   struct hentry * AffixMgr::compound_check Link Here 
1913
            }
1995
            }
1914
1996
1915
            numsyllable = oldnumsyllable2;
1997
            numsyllable = oldnumsyllable2;
1916
            wordnum = oldwordnum2;
1998
            wordnum = oldwordnum2;
1917
1999
1918
            // perhaps second word is a compound word (recursive call)
2000
            // perhaps second word is a compound word (recursive call)
1919
            if (wordnum < maxwordnum) {
2001
            if (wordnum < maxwordnum) {
1920
                rv = compound_check((st+i),strlen(st+i), wordnum+1,
2002
                rv = compound_check((st+i),strlen(st+i), wordnum+1,
1921
                     numsyllable, maxwordnum, wnum + 1, words, 0, is_sug);
2003
                     numsyllable, maxwordnum, wnum + 1, words, 0, is_sug, info);
1922
                if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv)) ||
2004
                
1923
                   (scpd != 0 && !cpdpat_check(word, i, rv_first, rv)))) rv = NULL;
2005
                if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) ||
2006
                   (scpd != 0 && !cpdpat_check(word, i, rv_first, rv, affixed)))) rv = NULL;
1924
            } else {
2007
            } else {
1925
                rv=NULL;
2008
                rv=NULL;
1926
            }
2009
            }
1927
            if (rv) {
2010
            if (rv) {
1928
                // forbid compound word, if it is a non compound word with typical fault
2011
                // forbid compound word, if it is a non compound word with typical fault
1929
                if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
2012
                if (checkcompoundrep || forbiddenword) {
2013
                    struct hentry * rv2 = NULL;
2014
2015
                    if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
2016
                    
2017
                    // check first part
2018
                    if (strncmp(rv->word, word + i, rv->blen) == 0) {
2019
                        char r = *(st + i + rv->blen);
2020
                        *(st + i + rv->blen) = '\0';
2021
                        
2022
                        if (checkcompoundrep && cpdrep_check(st, i + rv->blen)) {
2023
                            *(st + i + rv->blen) = r;
2024
                            continue;
2025
                        }
2026
2027
                        if (forbiddenword) {
2028
                            rv2 = lookup(word);
2029
                            if (!rv2) rv2 = affix_check(word, len);
2030
                            if (rv2 && rv2->astr && TESTAFF(rv2->astr, forbiddenword, rv2->alen) && 
2031
                                (strncmp(rv2->word, st, i + rv->blen) == 0)) {
2032
                                    return NULL;
2033
                            }
2034
                        }
2035
                        *(st + i + rv->blen) = r;
2036
                    }
2037
                }
1930
                return rv_first;
2038
                return rv_first;
1931
            }
2039
            }
1932
          } while (striple && !checkedstriple); // end of striple loop
2040
          } while (striple && !checkedstriple); // end of striple loop
1933
2041
1934
          if (checkedstriple) {
2042
          if (checkedstriple) {
1935
            i++;
2043
            i++;
1936
            checkedstriple = 0;
2044
            checkedstriple = 0;
1937
            striple = 0;
2045
            striple = 0;
 Lines 1943-1969   struct hentry * AffixMgr::compound_check Link Here 
1943
          i = soldi;
2051
          i = soldi;
1944
          soldi = 0;
2052
          soldi = 0;
1945
          len = oldlen;
2053
          len = oldlen;
1946
          cmin = oldcmin;
2054
          cmin = oldcmin;
1947
          cmax = oldcmax;
2055
          cmax = oldcmax;
1948
        }
2056
        }
1949
        scpd++;
2057
        scpd++;
1950
2058
1951
        } while (simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop
2059
2060
        } while (!onlycpdrule && simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop
2061
2062
        scpd = 0;
2063
        wordnum = oldwordnum;
2064
        numsyllable = oldnumsyllable;
1952
2065
1953
        if (soldi != 0) {
2066
        if (soldi != 0) {
1954
          i = soldi;
2067
          i = soldi;
1955
          strcpy(st, word); // XXX add more optim.
2068
          strcpy(st, word); // XXX add more optim.
1956
          soldi = 0;
2069
          soldi = 0;
1957
        } else st[i] = ch;
2070
        } else st[i] = ch;
1958
2071
1959
        scpd = 0;
2072
        } while (numdefcpd && oldwordnum == 0 && !onlycpdrule && (onlycpdrule = 1)); // end of onlycpd loop
1960
        wordnum = oldwordnum;
2073
1961
        numsyllable = oldnumsyllable;
1962
    }
2074
    }
1963
2075
1964
    return NULL;
2076
    return NULL;
1965
}
2077
}
1966
2078
1967
// check if compound word is correctly spelled
2079
// check if compound word is correctly spelled
1968
// hu_mov_rule = spec. Hungarian rule (XXX)
2080
// hu_mov_rule = spec. Hungarian rule (XXX)
1969
int AffixMgr::compound_check_morph(const char * word, int len, 
2081
int AffixMgr::compound_check_morph(const char * word, int len, 
 Lines 1981-2049   int AffixMgr::compound_check_morph(const Link Here 
1981
    char ch;
2093
    char ch;
1982
2094
1983
    int checked_prefix;
2095
    int checked_prefix;
1984
    char presult[MAXLNLEN];
2096
    char presult[MAXLNLEN];
1985
2097
1986
    int cmin;
2098
    int cmin;
1987
    int cmax;
2099
    int cmax;
1988
2100
2101
    int onlycpdrule;
2102
    int affixed = 0;
2103
    hentry ** oldwords = words;
2104
1989
    setcminmax(&cmin, &cmax, word, len);
2105
    setcminmax(&cmin, &cmax, word, len);
1990
2106
1991
    strcpy(st, word);
2107
    strcpy(st, word);
1992
2108
1993
    for (i = cmin; i < cmax; i++) {
2109
    for (i = cmin; i < cmax; i++) {
1994
        oldnumsyllable = numsyllable;
2110
        oldnumsyllable = numsyllable;
1995
        oldwordnum = wordnum;
2111
        oldwordnum = wordnum;
1996
        checked_prefix = 0;
2112
        checked_prefix = 0;
1997
2113
1998
        // go to end of the UTF-8 character
2114
        // go to end of the UTF-8 character
1999
        if (utf8) {
2115
        if (utf8) {
2000
            for (; (st[i] & 0xc0) == 0x80; i++);
2116
            for (; (st[i] & 0xc0) == 0x80; i++);
2001
            if (i >= cmax) return 0;
2117
            if (i >= cmax) return 0;
2002
        }
2118
        }
2003
2119
2120
        words = oldwords;
2121
        onlycpdrule = (words) ? 1 : 0;
2122
2123
        do { // onlycpdrule loop
2124
2125
        oldnumsyllable = numsyllable;
2126
        oldwordnum = wordnum;
2127
        checked_prefix = 0;
2128
2004
        ch = st[i];
2129
        ch = st[i];
2005
        st[i] = '\0';
2130
        st[i] = '\0';
2006
        sfx = NULL;
2131
        sfx = NULL;
2007
2132
2008
        // FIRST WORD
2133
        // FIRST WORD
2134
2135
        affixed = 1;
2136
2009
        *presult = '\0';
2137
        *presult = '\0';
2010
        if (partresult) mystrcat(presult, partresult, MAXLNLEN);
2138
        if (partresult) mystrcat(presult, partresult, MAXLNLEN);
2011
2139
2012
        rv = lookup(st); // perhaps without prefix
2140
        rv = lookup(st); // perhaps without prefix
2013
2141
2014
        // search homonym with compound flag
2142
        // search homonym with compound flag
2015
        while ((rv) && !hu_mov_rule && 
2143
        while ((rv) && !hu_mov_rule && 
2016
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
2144
            ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
2017
                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
2145
                !((compoundflag && !words && !onlycpdrule && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
2018
                (compoundbegin && !wordnum &&
2146
                (compoundbegin && !wordnum && !onlycpdrule &&
2019
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
2147
                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
2020
                (compoundmiddle && wordnum && !words &&
2148
                (compoundmiddle && wordnum && !words && !onlycpdrule &&
2021
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
2149
                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
2022
                  (numdefcpd &&
2150
                  (numdefcpd && onlycpdrule &&
2023
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
2151
                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
2024
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
2152
                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
2025
                  ))) {
2153
                  ))) {
2026
            rv = rv->next_homonym;
2154
            rv = rv->next_homonym;
2027
        }
2155
        }
2028
2156
2157
        if (rv) affixed = 0;
2158
2029
        if (rv)  {
2159
        if (rv)  {
2030
            sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st);
2160
            sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st);
2031
            if (!HENTRY_FIND(rv, MORPH_STEM)) {
2161
            if (!HENTRY_FIND(rv, MORPH_STEM)) {
2032
                sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM, st);
2162
                sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM, st);
2033
            }
2163
            }
2034
            // store the pointer of the hash entry
2164
            // store the pointer of the hash entry
2035
//            sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv);
2165
//            sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv);
2036
            if (HENTRY_DATA(rv)) {
2166
            if (HENTRY_DATA(rv)) {
2037
                sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv));
2167
                sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv));
2038
            }
2168
            }
2039
        }        
2169
        }        
2170
2040
        if (!rv) {
2171
        if (!rv) {
2041
            if (compoundflag && 
2172
            if (onlycpdrule) break;
2173
            if (compoundflag &&
2042
             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
2174
             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
2043
                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
2175
                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
2044
                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
2176
                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
2045
                    sfx->getCont() &&
2177
                    sfx->getCont() &&
2046
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
2178
                        ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, 
2047
                            sfx->getContLen())) || (compoundend &&
2179
                            sfx->getContLen())) || (compoundend &&
2048
                        TESTAFF(sfx->getCont(), compoundend, 
2180
                        TESTAFF(sfx->getCont(), compoundend, 
2049
                            sfx->getContLen())))) {
2181
                            sfx->getContLen())))) {
 Lines 2075-2090   int AffixMgr::compound_check_morph(const Link Here 
2075
                    sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD,
2207
                    sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD,
2076
                        MORPH_PART, st, line_uniq_app(&p, MSEP_REC));
2208
                        MORPH_PART, st, line_uniq_app(&p, MSEP_REC));
2077
                }
2209
                }
2078
                if (p) free(p);
2210
                if (p) free(p);
2079
                checked_prefix = 1;
2211
                checked_prefix = 1;
2080
            }
2212
            }
2081
        // else check forbiddenwords
2213
        // else check forbiddenwords
2082
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2214
        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2215
            TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
2083
            TESTAFF(rv->astr, needaffix, rv->alen))) {
2216
            TESTAFF(rv->astr, needaffix, rv->alen))) {
2084
                st[i] = ch;
2217
                st[i] = ch;
2085
                continue;
2218
                continue;
2086
        }
2219
        }
2087
2220
2088
            // check non_compound flag in suffix and prefix
2221
            // check non_compound flag in suffix and prefix
2089
            if ((rv) && !hu_mov_rule &&
2222
            if ((rv) && !hu_mov_rule &&
2090
                ((pfx && pfx->getCont() &&
2223
                ((pfx && pfx->getCont() &&
 Lines 2114-2130   int AffixMgr::compound_check_morph(const Link Here 
2114
                        pfx->getContLen())) ||
2247
                        pfx->getContLen())) ||
2115
                (sfx && sfx->getCont() &&
2248
                (sfx && sfx->getCont() &&
2116
                    TESTAFF(sfx->getCont(), compoundmiddle, 
2249
                    TESTAFF(sfx->getCont(), compoundmiddle, 
2117
                        sfx->getContLen())))) {
2250
                        sfx->getContLen())))) {
2118
                    rv = NULL;
2251
                    rv = NULL;
2119
            }       
2252
            }       
2120
2253
2121
        // check forbiddenwords
2254
        // check forbiddenwords
2122
        if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue;
2255
        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen)
2256
            || TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) continue;
2123
2257
2124
        // increment word number, if the second root has a compoundroot flag
2258
        // increment word number, if the second root has a compoundroot flag
2125
        if ((rv) && (compoundroot) && 
2259
        if ((rv) && (compoundroot) && 
2126
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2260
            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2127
                wordnum++;
2261
                wordnum++;
2128
        }
2262
        }
2129
2263
2130
        // first word is acceptable in compound words?
2264
        // first word is acceptable in compound words?
 Lines 2146-2162   int AffixMgr::compound_check_morph(const Link Here 
2146
          && ! (( checkcompoundtriple && !words && // test triple letters
2280
          && ! (( checkcompoundtriple && !words && // test triple letters
2147
                   (word[i-1]==word[i]) && (
2281
                   (word[i-1]==word[i]) && (
2148
                      ((i>1) && (word[i-1]==word[i-2])) || 
2282
                      ((i>1) && (word[i-1]==word[i-2])) || 
2149
                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
2283
                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
2150
                   )
2284
                   )
2151
               ) ||
2285
               ) ||
2152
               (
2286
               (
2153
                   // test CHECKCOMPOUNDPATTERN
2287
                   // test CHECKCOMPOUNDPATTERN
2154
                   numcheckcpd && !words && cpdpat_check(word, i, rv, NULL)
2288
                   numcheckcpd && !words && cpdpat_check(word, i, rv, NULL, affixed)
2155
               ) ||
2289
               ) ||
2156
               ( 
2290
               ( 
2157
                 checkcompoundcase && !words && cpdcase_check(word, i)
2291
                 checkcompoundcase && !words && cpdcase_check(word, i)
2158
               ))
2292
               ))
2159
         )
2293
         )
2160
// LANG_hu section: spec. Hungarian rule
2294
// LANG_hu section: spec. Hungarian rule
2161
         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
2295
         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
2162
              (sfx && sfx->getCont() && (
2296
              (sfx && sfx->getCont() && (
 Lines 2222-2238   int AffixMgr::compound_check_morph(const Link Here 
2222
// END of LANG_hu section
2356
// END of LANG_hu section
2223
            // increment word number, if the second root has a compoundroot flag
2357
            // increment word number, if the second root has a compoundroot flag
2224
            if ((rv) && (compoundroot) && 
2358
            if ((rv) && (compoundroot) && 
2225
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2359
                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
2226
                    wordnum++;
2360
                    wordnum++;
2227
            }
2361
            }
2228
2362
2229
            // check forbiddenwords
2363
            // check forbiddenwords
2230
            if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) {
2364
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
2365
                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) {
2231
                st[i] = ch;
2366
                st[i] = ch;
2232
                continue;
2367
                continue;
2233
            }
2368
            }
2234
2369
2235
            // second word is acceptable, as a root?
2370
            // second word is acceptable, as a root?
2236
            // hungarian conventions: compounding is acceptable,
2371
            // hungarian conventions: compounding is acceptable,
2237
            // when compound forms consist of 2 words, or if more,
2372
            // when compound forms consist of 2 words, or if more,
2238
            // then the syllable number of root words must be 6, or lesser.
2373
            // then the syllable number of root words must be 6, or lesser.
 Lines 2276-2294   int AffixMgr::compound_check_morph(const Link Here 
2276
2411
2277
            numsyllable = oldnumsyllable2 ;
2412
            numsyllable = oldnumsyllable2 ;
2278
            wordnum = oldwordnum2;
2413
            wordnum = oldwordnum2;
2279
2414
2280
            // perhaps second word has prefix or/and suffix
2415
            // perhaps second word has prefix or/and suffix
2281
            sfx = NULL;
2416
            sfx = NULL;
2282
            sfxflag = FLAG_NULL;
2417
            sfxflag = FLAG_NULL;
2283
2418
2284
            if (compoundflag) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL;
2419
            if (compoundflag && !onlycpdrule) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL;
2285
2420
2286
            if (!rv && compoundend) {
2421
            if (!rv && compoundend && !onlycpdrule) {
2287
                sfx = NULL;
2422
                sfx = NULL;
2288
                pfx = NULL;
2423
                pfx = NULL;
2289
                rv = affix_check((word+i),strlen(word+i), compoundend);
2424
                rv = affix_check((word+i),strlen(word+i), compoundend);
2290
            }
2425
            }
2291
2426
2292
            if (!rv && numdefcpd && words) {
2427
            if (!rv && numdefcpd && words) {
2293
                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
2428
                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
2294
                if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) {
2429
                if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) {
 Lines 2316-2332   int AffixMgr::compound_check_morph(const Link Here 
2316
                        pfx->getContLen())) ||
2451
                        pfx->getContLen())) ||
2317
                (sfx && sfx->getCont() &&
2452
                (sfx && sfx->getCont() &&
2318
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
2453
                    TESTAFF(sfx->getCont(), compoundforbidflag, 
2319
                        sfx->getContLen())))) {
2454
                        sfx->getContLen())))) {
2320
                    rv = NULL;
2455
                    rv = NULL;
2321
            }
2456
            }
2322
2457
2323
            // check forbiddenwords
2458
            // check forbiddenwords
2324
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen))
2459
            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen) ||
2460
                    TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))
2325
                    && (! TESTAFF(rv->astr, needaffix, rv->alen))) {
2461
                    && (! TESTAFF(rv->astr, needaffix, rv->alen))) {
2326
                        st[i] = ch;
2462
                        st[i] = ch;
2327
                        continue;
2463
                        continue;
2328
                    }
2464
                    }
2329
2465
2330
            if (langnum == LANG_hu) {
2466
            if (langnum == LANG_hu) {
2331
                // calculate syllable number of the word
2467
                // calculate syllable number of the word
2332
                numsyllable += get_syllable(word + i, strlen(word + i));
2468
                numsyllable += get_syllable(word + i, strlen(word + i));
 Lines 2397-2412   int AffixMgr::compound_check_morph(const Link Here 
2397
                             numsyllable, maxwordnum, wnum + 1, words, 0, result, presult);
2533
                             numsyllable, maxwordnum, wnum + 1, words, 0, result, presult);
2398
            } else {
2534
            } else {
2399
                rv=NULL;
2535
                rv=NULL;
2400
            }
2536
            }
2401
        }
2537
        }
2402
        st[i] = ch;
2538
        st[i] = ch;
2403
        wordnum = oldwordnum;
2539
        wordnum = oldwordnum;
2404
        numsyllable = oldnumsyllable;
2540
        numsyllable = oldnumsyllable;
2541
2542
        } while (numdefcpd && oldwordnum == 0 && !onlycpdrule && (onlycpdrule = 1)); // end of onlycpd loop
2543
2405
    }
2544
    }
2406
    return 0;
2545
    return 0;
2407
}    
2546
}    
2408
2547
2409
 // return 1 if s1 (reversed) is a leading subset of end of s2
2548
 // return 1 if s1 (reversed) is a leading subset of end of s2
2410
/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
2549
/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
2411
 {
2550
 {
2412
    while ((len > 0) && *s1 && (*s1 == *end_of_s2)) {
2551
    while ((len > 0) && *s1 && (*s1 == *end_of_s2)) {
 Lines 2452-2490   struct hentry * AffixMgr::suffix_check ( Link Here 
2452
                   circumfix, ep->getContLen())) &&
2591
                   circumfix, ep->getContLen())) &&
2453
               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
2592
               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
2454
              // circumfix flag in prefix AND suffix
2593
              // circumfix flag in prefix AND suffix
2455
              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
2594
              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
2456
                   circumfix, ep->getContLen())) &&
2595
                   circumfix, ep->getContLen())) &&
2457
               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
2596
               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
2458
            // fogemorpheme
2597
            // fogemorpheme
2459
              (in_compound || 
2598
              (in_compound || 
2460
                 !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
2599
                 !(se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen())))) &&
2461
            // needaffix on prefix or first suffix
2600
            // needaffix on prefix or first suffix
2462
              (cclass || 
2601
              (cclass || 
2463
                   !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) ||
2602
                   !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) ||
2464
                   (ppfx && !((ep->getCont()) &&
2603
                   (ppfx && !((ep->getCont()) &&
2465
                     TESTAFF(ep->getCont(), needaffix,
2604
                     TESTAFF(ep->getCont(), needaffix,
2466
                       ep->getContLen())))
2605
                       ep->getContLen())))
2467
              )
2606
              )) {
2468
            ) {
2469
                rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, 
2607
                rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, 
2470
                    needflag, (in_compound ? 0 : onlyincompound));
2608
                    needflag, (in_compound ? 0 : onlyincompound));
2471
                if (rv) {
2609
                if (rv) {
2472
                    sfx=se; // BUG: sfx not stateless
2610
                    sfx=se; // BUG: sfx not stateless
2473
                    return rv;
2611
                    return rv;
2474
                }
2612
                }
2475
            }
2613
            }
2476
        }
2614
        }
2477
       se = se->getNext();
2615
       se = se->getNext();
2478
    }
2616
    }
2479
2617
2480
    // now handle the general case
2618
    // now handle the general case
2481
    if (len == 0) return NULL; // FULLSTRIP
2619
    if (len == 0) return NULL; // FULLSTRIP
2482
    unsigned char sp = *((const unsigned char *)(word + len - 1));
2620
    unsigned char sp= *((const unsigned char *)(word + len - 1));
2483
    SfxEntry * sptr = sStart[sp];
2621
    SfxEntry * sptr = sStart[sp];
2484
2622
2485
    while (sptr) {
2623
    while (sptr) {
2486
        if (isRevSubset(sptr->getKey(), word + len - 1, len)
2624
        if (isRevSubset(sptr->getKey(), word + len - 1, len)
2487
        ) {
2625
        ) {
2488
            // suffixes are not allowed in beginning of compounds
2626
            // suffixes are not allowed in beginning of compounds
2489
            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
2627
            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
2490
             // except when signed with compoundpermitflag flag
2628
             // except when signed with compoundpermitflag flag
 Lines 2503-2519   struct hentry * AffixMgr::suffix_check ( Link Here 
2503
                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
2641
                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
2504
            // needaffix on prefix or first suffix
2642
            // needaffix on prefix or first suffix
2505
              (cclass || 
2643
              (cclass || 
2506
                  !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) ||
2644
                  !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) ||
2507
                  (ppfx && !((ep->getCont()) &&
2645
                  (ppfx && !((ep->getCont()) &&
2508
                     TESTAFF(ep->getCont(), needaffix,
2646
                     TESTAFF(ep->getCont(), needaffix,
2509
                       ep->getContLen())))
2647
                       ep->getContLen())))
2510
              )
2648
              )
2511
            ) {
2649
            ) if (in_compound != IN_CPD_END || ppfx || !(sptr->getCont() && TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))) {
2512
                rv = sptr->checkword(word,len, sfxopts, ppfx, wlst,
2650
                rv = sptr->checkword(word,len, sfxopts, ppfx, wlst,
2513
                    maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound));
2651
                    maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound));
2514
                if (rv) {
2652
                if (rv) {
2515
                    sfx=sptr; // BUG: sfx not stateless
2653
                    sfx=sptr; // BUG: sfx not stateless
2516
                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
2654
                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
2517
                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
2655
                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
2518
                    return rv;
2656
                    return rv;
2519
                }
2657
                }
 Lines 2791-2813   struct hentry * AffixMgr::affix_check (c Link Here 
2791
    if (rv) return rv;
2929
    if (rv) return rv;
2792
2930
2793
    // if still not found check all suffixes
2931
    // if still not found check all suffixes
2794
    rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound);
2932
    rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound);
2795
2933
2796
    if (havecontclass) {
2934
    if (havecontclass) {
2797
        sfx = NULL;
2935
        sfx = NULL;
2798
        pfx = NULL;
2936
        pfx = NULL;
2937
2799
        if (rv) return rv;
2938
        if (rv) return rv;
2800
        // if still not found check all two-level suffixes
2939
        // if still not found check all two-level suffixes
2801
        rv = suffix_check_twosfx(word, len, 0, NULL, needflag);
2940
        rv = suffix_check_twosfx(word, len, 0, NULL, needflag);
2941
2802
        if (rv) return rv;
2942
        if (rv) return rv;
2803
        // if still not found check all two-level suffixes
2943
        // if still not found check all two-level suffixes
2804
        rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag);
2944
        rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag);
2805
    }
2945
    }
2946
2806
    return rv;
2947
    return rv;
2807
}
2948
}
2808
2949
2809
// check if word with affixes is correctly spelled
2950
// check if word with affixes is correctly spelled
2810
char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound)
2951
char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound)
2811
{
2952
{
2812
    char result[MAXLNLEN];
2953
    char result[MAXLNLEN];
2813
    char * st = NULL;
2954
    char * st = NULL;
 Lines 2890-2906   char * AffixMgr::morphgen(char * ts, int Link Here 
2890
3031
2891
                int cmp = morphcmp(stemmorph, targetmorph);
3032
                int cmp = morphcmp(stemmorph, targetmorph);
2892
3033
2893
                if (cmp == 0) {
3034
                if (cmp == 0) {
2894
                    char * newword = sptr->add(ts, wl);
3035
                    char * newword = sptr->add(ts, wl);
2895
                    if (newword) {
3036
                    if (newword) {
2896
                        hentry * check = pHMgr->lookup(newword); // XXX extra dic
3037
                        hentry * check = pHMgr->lookup(newword); // XXX extra dic
2897
                        if (!check || !check->astr || 
3038
                        if (!check || !check->astr || 
2898
                            !TESTAFF(check->astr, forbiddenword, check->alen)) {
3039
                            !(TESTAFF(check->astr, forbiddenword, check->alen) || 
3040
                              TESTAFF(check->astr, ONLYUPCASEFLAG, check->alen))) {
2899
                                return newword;
3041
                                return newword;
2900
                        }
3042
                        }
2901
                        free(newword);
3043
                        free(newword);
2902
                    }
3044
                    }
2903
                }
3045
                }
2904
                
3046
                
2905
                // recursive call for secondary suffixes
3047
                // recursive call for secondary suffixes
2906
                if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) &&
3048
                if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) &&
 Lines 3144-3159   int AffixMgr::get_fullstrip() const Link Here 
3144
  return fullstrip;
3286
  return fullstrip;
3145
}
3287
}
3146
3288
3147
FLAG AffixMgr::get_keepcase() const
3289
FLAG AffixMgr::get_keepcase() const
3148
{
3290
{
3149
  return keepcase;
3291
  return keepcase;
3150
}
3292
}
3151
3293
3294
FLAG AffixMgr::get_forceucase() const
3295
{
3296
  return forceucase;
3297
}
3298
3299
FLAG AffixMgr::get_warn() const
3300
{
3301
  return warn;
3302
}
3303
3304
int AffixMgr::get_forbidwarn() const
3305
{
3306
  return forbidwarn;
3307
}
3308
3152
int AffixMgr::get_checksharps() const
3309
int AffixMgr::get_checksharps() const
3153
{
3310
{
3154
  return checksharps;
3311
  return checksharps;
3155
}
3312
}
3156
3313
3157
char * AffixMgr::encode_flag(unsigned short aflag) const
3314
char * AffixMgr::encode_flag(unsigned short aflag) const
3158
{
3315
{
3159
  return pHMgr->encode_flag(aflag);
3316
  return pHMgr->encode_flag(aflag);
 Lines 3219-3234   FLAG AffixMgr::get_forbiddenword() const Link Here 
3219
}
3376
}
3220
3377
3221
// return the forbidden words control flag
3378
// return the forbidden words control flag
3222
FLAG AffixMgr::get_nosuggest() const
3379
FLAG AffixMgr::get_nosuggest() const
3223
{
3380
{
3224
  return nosuggest;
3381
  return nosuggest;
3225
}
3382
}
3226
3383
3384
// return the forbidden words control flag
3385
FLAG AffixMgr::get_nongramsuggest() const
3386
{
3387
  return nongramsuggest;
3388
}
3389
3227
// return the forbidden words flag modify flag
3390
// return the forbidden words flag modify flag
3228
FLAG AffixMgr::get_needaffix() const
3391
FLAG AffixMgr::get_needaffix() const
3229
{
3392
{
3230
  return needaffix;
3393
  return needaffix;
3231
}
3394
}
3232
3395
3233
// return the onlyincompound flag
3396
// return the onlyincompound flag
3234
FLAG AffixMgr::get_onlyincompound() const
3397
FLAG AffixMgr::get_onlyincompound() const
 Lines 3297-3318   int AffixMgr::have_contclass() const Link Here 
3297
}
3460
}
3298
3461
3299
// return utf8
3462
// return utf8
3300
int AffixMgr::get_utf8() const
3463
int AffixMgr::get_utf8() const
3301
{
3464
{
3302
  return utf8;
3465
  return utf8;
3303
}
3466
}
3304
3467
3305
// return nosplitsugs
3306
int AffixMgr::get_maxngramsugs(void) const
3468
int AffixMgr::get_maxngramsugs(void) const
3307
{
3469
{
3308
  return maxngramsugs;
3470
  return maxngramsugs;
3309
}
3471
}
3310
3472
3473
int AffixMgr::get_maxcpdsugs(void) const
3474
{
3475
  return maxcpdsugs;
3476
}
3477
3478
int AffixMgr::get_maxdiff(void) const
3479
{
3480
  return maxdiff;
3481
}
3482
3483
int AffixMgr::get_onlymaxdiff(void) const
3484
{
3485
  return onlymaxdiff;
3486
}
3487
3311
// return nosplitsugs
3488
// return nosplitsugs
3312
int AffixMgr::get_nosplitsugs(void) const
3489
int AffixMgr::get_nosplitsugs(void) const
3313
{
3490
{
3314
  return nosplitsugs;
3491
  return nosplitsugs;
3315
}
3492
}
3316
3493
3317
// return sugswithdots
3494
// return sugswithdots
3318
int AffixMgr::get_sugswithdots(void) const
3495
int AffixMgr::get_sugswithdots(void) const
 Lines 3444-3460   int AffixMgr::parse_reptable(char * lin Link Here 
3444
                  case 0: {
3621
                  case 0: {
3445
                             if (strncmp(piece,"REP",3) != 0) {
3622
                             if (strncmp(piece,"REP",3) != 0) {
3446
                                 HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3623
                                 HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3447
                                 numrep = 0;
3624
                                 numrep = 0;
3448
                                 return 1;
3625
                                 return 1;
3449
                             }
3626
                             }
3450
                             break;
3627
                             break;
3451
                          }
3628
                          }
3452
                  case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; }
3629
                  case 1: {
3630
                            if (*piece == '^') reptable[j].start = true; else reptable[j].start = false;
3631
                            reptable[j].pattern = mystrrep(mystrdup(piece + int(reptable[j].start)),"_"," ");
3632
                            int lr = strlen(reptable[j].pattern) - 1;
3633
                            if (reptable[j].pattern[lr] == '$') {
3634
                                reptable[j].end = true;
3635
                                reptable[j].pattern[lr] = '\0';
3636
                            } else reptable[j].end = false;
3637
                            break;
3638
                          }
3453
                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
3639
                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
3454
                  default: break;
3640
                  default: break;
3455
               }
3641
               }
3456
               i++;
3642
               i++;
3457
           }
3643
           }
3458
           piece = mystrsep(&tp, 0);
3644
           piece = mystrsep(&tp, 0);
3459
        }
3645
        }
3460
        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
3646
        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
 Lines 3533-3557   int AffixMgr::parse_convtable(char * li Link Here 
3533
                    break; 
3719
                    break; 
3534
                  }
3720
                  }
3535
                  default: break;
3721
                  default: break;
3536
               }
3722
               }
3537
               i++;
3723
               i++;
3538
           }
3724
           }
3539
           piece = mystrsep(&tp, 0);
3725
           piece = mystrsep(&tp, 0);
3540
        }
3726
        }
3541
      if (!pattern || !pattern2) {
3727
        if (!pattern || !pattern2) {
3542
         if (pattern)
3728
            if (pattern)
3543
            free(pattern);
3729
                free(pattern);
3544
         if (pattern2)
3730
            if (pattern2)
3545
            free(pattern2);
3731
                free(pattern2);
3546
         HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3732
            HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
3547
         return 1;
3733
            return 1;
3548
      }
3734
        }
3549
      (*rl)->add(pattern, pattern2);
3735
        (*rl)->add(pattern, pattern2);
3550
   }
3736
   }
3551
   return 0;
3737
   return 0;
3552
}
3738
}
3553
3739
3554
3740
3555
/* parse in the typical fault correcting table */
3741
/* parse in the typical fault correcting table */
3556
int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
3742
int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
3557
{
3743
{
 Lines 3935-3969   int AffixMgr::parse_maptable(char * lin Link Here 
3935
        }
4121
        }
3936
   }
4122
   }
3937
   return 0;
4123
   return 0;
3938
}
4124
}
3939
4125
3940
/* parse in the word breakpoint table */
4126
/* parse in the word breakpoint table */
3941
int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
4127
int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
3942
{
4128
{
3943
   if (numbreak != 0) {
4129
   if (numbreak > -1) {
3944
      HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum());
4130
      HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum());
3945
      return 1;
4131
      return 1;
3946
   }
4132
   }
3947
   char * tp = line;
4133
   char * tp = line;
3948
   char * piece;
4134
   char * piece;
3949
   int i = 0;
4135
   int i = 0;
3950
   int np = 0;
4136
   int np = 0;
3951
   piece = mystrsep(&tp, 0);
4137
   piece = mystrsep(&tp, 0);
3952
   while (piece) {
4138
   while (piece) {
3953
       if (*piece != '\0') {
4139
       if (*piece != '\0') {
3954
          switch(i) {
4140
          switch(i) {
3955
             case 0: { np++; break; }
4141
             case 0: { np++; break; }
3956
             case 1: { 
4142
             case 1: { 
3957
                       numbreak = atoi(piece);
4143
                       numbreak = atoi(piece);
3958
                       if (numbreak < 1) {
4144
                       if (numbreak < 0) {
3959
                          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum());
4145
                          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum());
3960
                          return 1;
4146
                          return 1;
3961
                       }
4147
                       }
4148
                       if (numbreak == 0) return 0;
3962
                       breaktable = (char **) malloc(numbreak * sizeof(char *));
4149
                       breaktable = (char **) malloc(numbreak * sizeof(char *));
3963
                       if (!breaktable) return 1;
4150
                       if (!breaktable) return 1;
3964
                       np++;
4151
                       np++;
3965
                       break;
4152
                       break;
3966
                     }
4153
                     }
3967
             default: break;
4154
             default: break;
3968
          }
4155
          }
3969
          i++;
4156
          i++;
(-)a/extensions/spellcheck/hunspell/src/affixmgr.hxx (-2 / +17 lines)
Line     Link Here 
 Lines 100-115   class LIBHUNSPELL_DLL_EXPORTED AffixMgr Link Here 
100
  FLAG                compoundpermitflag;
100
  FLAG                compoundpermitflag;
101
  int                 checkcompounddup;
101
  int                 checkcompounddup;
102
  int                 checkcompoundrep;
102
  int                 checkcompoundrep;
103
  int                 checkcompoundcase;
103
  int                 checkcompoundcase;
104
  int                 checkcompoundtriple;
104
  int                 checkcompoundtriple;
105
  int                 simplifiedtriple;
105
  int                 simplifiedtriple;
106
  FLAG                forbiddenword;
106
  FLAG                forbiddenword;
107
  FLAG                nosuggest;
107
  FLAG                nosuggest;
108
  FLAG                nongramsuggest;
108
  FLAG                needaffix;
109
  FLAG                needaffix;
109
  int                 cpdmin;
110
  int                 cpdmin;
110
  int                 numrep;
111
  int                 numrep;
111
  replentry *         reptable;
112
  replentry *         reptable;
112
  RepList *           iconvtable;
113
  RepList *           iconvtable;
113
  RepList *           oconvtable;
114
  RepList *           oconvtable;
114
  int                 nummap;
115
  int                 nummap;
115
  mapentry *          maptable;
116
  mapentry *          maptable;
 Lines 117-132   class LIBHUNSPELL_DLL_EXPORTED AffixMgr Link Here 
117
  char **             breaktable;
118
  char **             breaktable;
118
  int                 numcheckcpd;
119
  int                 numcheckcpd;
119
  patentry *          checkcpdtable;
120
  patentry *          checkcpdtable;
120
  int                 simplifiedcpd;
121
  int                 simplifiedcpd;
121
  int                 numdefcpd;
122
  int                 numdefcpd;
122
  flagentry *         defcpdtable;
123
  flagentry *         defcpdtable;
123
  phonetable *        phone;
124
  phonetable *        phone;
124
  int                 maxngramsugs;
125
  int                 maxngramsugs;
126
  int                 maxcpdsugs;
127
  int                 maxdiff;
128
  int                 onlymaxdiff;
125
  int                 nosplitsugs;
129
  int                 nosplitsugs;
126
  int                 sugswithdots;
130
  int                 sugswithdots;
127
  int                 cpdwordmax;
131
  int                 cpdwordmax;
128
  int                 cpdmaxsyllable;
132
  int                 cpdmaxsyllable;
129
  char *              cpdvowels;
133
  char *              cpdvowels;
130
  w_char *            cpdvowels_utf16;
134
  w_char *            cpdvowels_utf16;
131
  int                 cpdvowels_utf16_len;
135
  int                 cpdvowels_utf16_len;
132
  char *              cpdsyllablenum;
136
  char *              cpdsyllablenum;
 Lines 145-160   class LIBHUNSPELL_DLL_EXPORTED AffixMgr Link Here 
145
  int                 ignorechars_utf16_len;
149
  int                 ignorechars_utf16_len;
146
  char *              version;
150
  char *              version;
147
  char *              lang;
151
  char *              lang;
148
  int                 langnum;
152
  int                 langnum;
149
  FLAG                lemma_present;
153
  FLAG                lemma_present;
150
  FLAG                circumfix;
154
  FLAG                circumfix;
151
  FLAG                onlyincompound;
155
  FLAG                onlyincompound;
152
  FLAG                keepcase;
156
  FLAG                keepcase;
157
  FLAG                forceucase;
158
  FLAG                warn;
159
  int                 forbidwarn;
153
  FLAG                substandard;
160
  FLAG                substandard;
154
  int                 checksharps;
161
  int                 checksharps;
155
  int                 fullstrip;
162
  int                 fullstrip;
156
163
157
  int                 havecontclass; // boolean variable
164
  int                 havecontclass; // boolean variable
158
  char                contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix)
165
  char                contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix)
159
166
160
public:
167
public:
 Lines 195-219   public: Link Here 
195
            unsigned short al, char * morph, char * targetmorph, int level);
202
            unsigned short al, char * morph, char * targetmorph, int level);
196
203
197
  int    expand_rootword(struct guessword * wlst, int maxn, const char * ts,
204
  int    expand_rootword(struct guessword * wlst, int maxn, const char * ts,
198
            int wl, const unsigned short * ap, unsigned short al, char * bad,
205
            int wl, const unsigned short * ap, unsigned short al, char * bad,
199
            int, char *);
206
            int, char *);
200
207
201
  short       get_syllable (const char * word, int wlen);
208
  short       get_syllable (const char * word, int wlen);
202
  int         cpdrep_check(const char * word, int len);
209
  int         cpdrep_check(const char * word, int len);
203
  int         cpdpat_check(const char * word, int len, hentry * r1, hentry * r2);
210
  int         cpdpat_check(const char * word, int len, hentry * r1, hentry * r2,
211
                    const char affixed);
204
  int         defcpd_check(hentry *** words, short wnum, hentry * rv,
212
  int         defcpd_check(hentry *** words, short wnum, hentry * rv,
205
                    hentry ** rwords, char all);
213
                    hentry ** rwords, char all);
206
  int         cpdcase_check(const char * word, int len);
214
  int         cpdcase_check(const char * word, int len);
207
  inline int  candidate_check(const char * word, int len);
215
  inline int  candidate_check(const char * word, int len);
208
  void        setcminmax(int * cmin, int * cmax, const char * word, int len);
216
  void        setcminmax(int * cmin, int * cmax, const char * word, int len);
209
  struct hentry * compound_check(const char * word, int len, short wordnum,
217
  struct hentry * compound_check(const char * word, int len, short wordnum,
210
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
218
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
211
            char hu_mov_rule, char is_sug);
219
            char hu_mov_rule, char is_sug, int * info);
212
220
213
  int compound_check_morph(const char * word, int len, short wordnum,
221
  int compound_check_morph(const char * word, int len, short wordnum,
214
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
222
            short numsyllable, short maxwordnum, short wnum, hentry ** words,
215
            char hu_mov_rule, char ** result, char * partresult);
223
            char hu_mov_rule, char ** result, char * partresult);
216
224
217
  struct hentry * lookup(const char * word);
225
  struct hentry * lookup(const char * word);
218
  int                 get_numrep() const;
226
  int                 get_numrep() const;
219
  struct replentry *  get_reptable() const;
227
  struct replentry *  get_reptable() const;
 Lines 232-264   public: Link Here 
232
  unsigned short *    get_wordchars_utf16(int * len) const;
240
  unsigned short *    get_wordchars_utf16(int * len) const;
233
  char *              get_ignore() const;
241
  char *              get_ignore() const;
234
  unsigned short *    get_ignore_utf16(int * len) const;
242
  unsigned short *    get_ignore_utf16(int * len) const;
235
  int                 get_compound() const;
243
  int                 get_compound() const;
236
  FLAG                get_compoundflag() const;
244
  FLAG                get_compoundflag() const;
237
  FLAG                get_compoundbegin() const;
245
  FLAG                get_compoundbegin() const;
238
  FLAG                get_forbiddenword() const;
246
  FLAG                get_forbiddenword() const;
239
  FLAG                get_nosuggest() const;
247
  FLAG                get_nosuggest() const;
248
  FLAG                get_nongramsuggest() const;
240
  FLAG                get_needaffix() const;
249
  FLAG                get_needaffix() const;
241
  FLAG                get_onlyincompound() const;
250
  FLAG                get_onlyincompound() const;
242
  FLAG                get_compoundroot() const;
251
  FLAG                get_compoundroot() const;
243
  FLAG                get_lemma_present() const;
252
  FLAG                get_lemma_present() const;
244
  int                 get_checknum() const;
253
  int                 get_checknum() const;
245
  const char *        get_prefix() const;
254
  const char *        get_prefix() const;
246
  const char *        get_suffix() const;
255
  const char *        get_suffix() const;
247
  const char *        get_derived() const;
256
  const char *        get_derived() const;
248
  const char *        get_version() const;
257
  const char *        get_version() const;
249
  int                 have_contclass() const;
258
  int                 have_contclass() const;
250
  int                 get_utf8() const;
259
  int                 get_utf8() const;
251
  int                 get_complexprefixes() const;
260
  int                 get_complexprefixes() const;
252
  char *              get_suffixed(char ) const;
261
  char *              get_suffixed(char ) const;
253
  int                 get_maxngramsugs() const;
262
  int                 get_maxngramsugs() const;
263
  int                 get_maxcpdsugs() const;
264
  int                 get_maxdiff() const;
265
  int                 get_onlymaxdiff() const;
254
  int                 get_nosplitsugs() const;
266
  int                 get_nosplitsugs() const;
255
  int                 get_sugswithdots(void) const;
267
  int                 get_sugswithdots(void) const;
256
  FLAG                get_keepcase(void) const;
268
  FLAG                get_keepcase(void) const;
269
  FLAG                get_forceucase(void) const;
270
  FLAG                get_warn(void) const;
271
  int                 get_forbidwarn(void) const;
257
  int                 get_checksharps(void) const;
272
  int                 get_checksharps(void) const;
258
  char *              encode_flag(unsigned short aflag) const;
273
  char *              encode_flag(unsigned short aflag) const;
259
  int                 get_fullstrip() const;
274
  int                 get_fullstrip() const;
260
275
261
private:
276
private:
262
  int  parse_file(const char * affpath, const char * key);
277
  int  parse_file(const char * affpath, const char * key);
263
  int  parse_flag(char * line, unsigned short * out, FileMgr * af);
278
  int  parse_flag(char * line, unsigned short * out, FileMgr * af);
264
  int  parse_num(char * line, int * out, FileMgr * af);
279
  int  parse_num(char * line, int * out, FileMgr * af);
(-)a/extensions/spellcheck/hunspell/src/atypes.hxx (+9 lines)
Line     Link Here 
 Lines 87-102   static inline void HUNSPELL_WARNING(FILE Link Here 
87
#define aeLONGCOND      (1 << 4)
87
#define aeLONGCOND      (1 << 4)
88
88
89
// compound options
89
// compound options
90
#define IN_CPD_NOT   0
90
#define IN_CPD_NOT   0
91
#define IN_CPD_BEGIN 1
91
#define IN_CPD_BEGIN 1
92
#define IN_CPD_END   2
92
#define IN_CPD_END   2
93
#define IN_CPD_OTHER 3
93
#define IN_CPD_OTHER 3
94
94
95
// info options
96
#define  SPELL_COMPOUND  (1 << 0)
97
#define  SPELL_FORBIDDEN (1 << 1)
98
#define  SPELL_ALLCAP    (1 << 2)
99
#define  SPELL_NOCAP     (1 << 3)
100
#define  SPELL_INITCAP   (1 << 4)
101
#define  SPELL_ORIGCAP   (1 << 5)
102
#define  SPELL_WARN      (1 << 6)
103
95
#define MAXLNLEN        8192
104
#define MAXLNLEN        8192
96
105
97
#define MINCPDLEN       3
106
#define MINCPDLEN       3
98
#define MAXCOMPOUND     10
107
#define MAXCOMPOUND     10
99
#define MAXCONDLEN      20
108
#define MAXCONDLEN      20
100
#define MAXCONDLEN_1    (MAXCONDLEN - sizeof(char *))
109
#define MAXCONDLEN_1    (MAXCONDLEN - sizeof(char *))
101
110
102
#define MAXACC          1000
111
#define MAXACC          1000
(-)a/extensions/spellcheck/hunspell/src/csutil.cpp (-63 / +381 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 "nsUnicharUtils.h"
82
#include "nsICharsetConverterManager.h"
90
#include "nsICharsetConverterManager.h"
83
#include "nsUnicharUtilCIID.h"
84
#include "nsUnicharUtils.h"
85
91
86
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
92
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
87
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
88
#endif
93
#endif
89
94
95
struct unicode_info2 {
96
  char cletter;
97
  unsigned short cupper;
98
  unsigned short clower;
99
};
100
90
static struct unicode_info2 * utf_tbl = NULL;
101
static struct unicode_info2 * utf_tbl = NULL;
91
static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
102
static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
92
103
93
/* only UTF-16 (BMP) implementation */
104
/* only UTF-16 (BMP) implementation */
94
char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
105
char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
95
    signed char * u8 = (signed char *)dest;
106
    signed char * u8 = (signed char *)dest;
96
    signed char * u8_max = (signed char *)(u8 + size);
107
    signed char * u8_max = (signed char *)(u8 + size);
97
    const w_char * u2 = src;
108
    const w_char * u2 = src;
 Lines 347-365   int line_tok(const char * text, char *** Link Here 
347
    char * p = strchr(dup, breakchar);
358
    char * p = strchr(dup, breakchar);
348
    while (p) {
359
    while (p) {
349
        linenum++;
360
        linenum++;
350
        *p = '\0';
361
        *p = '\0';
351
        p++;
362
        p++;
352
        p = strchr(p, breakchar);
363
        p = strchr(p, breakchar);
353
    }
364
    }
354
    linenum++;
365
    linenum++;
355
//    fprintf(stderr, "LINEN:%d %p %p\n", linenum, lines, *lines);
356
    *lines = (char **) malloc(linenum * sizeof(char *));
366
    *lines = (char **) malloc(linenum * sizeof(char *));
357
//    fprintf(stderr, "hello\n");
358
    if (!(*lines)) {
367
    if (!(*lines)) {
359
        free(dup);
368
        free(dup);
360
        return 0;
369
        return 0;
361
    }
370
    }
362
371
363
    p = dup;
372
    p = dup;
364
    int l = 0;
373
    int l = 0;
365
    for (int i = 0; i < linenum; i++) {
374
    for (int i = 0; i < linenum; i++) {
 Lines 590-620   char * copy_field(char * dest, const cha Link Here 
590
       return dest;
599
       return dest;
591
  }
600
  }
592
  return NULL;
601
  return NULL;
593
}
602
}
594
603
595
char * mystrrep(char * word, const char * pat, const char * rep) {
604
char * mystrrep(char * word, const char * pat, const char * rep) {
596
    char * pos = strstr(word, pat);
605
    char * pos = strstr(word, pat);
597
    if (pos) {
606
    if (pos) {
598
        int replen = strlen(rep);
607
      int replen = strlen(rep);
599
        int patlen = strlen(pat);
608
      int patlen = strlen(pat);
609
      while (pos) {
600
        if (replen < patlen) {
610
        if (replen < patlen) {
601
            char * end = word + strlen(word);
611
            char * end = word + strlen(word);
602
            char * next = pos + replen;
612
            char * next = pos + replen;
603
            char * prev = pos + strlen(pat);
613
            char * prev = pos + strlen(pat);
604
            for (; prev < end; *next = *prev, prev++, next++);
614
            for (; prev < end; *next = *prev, prev++, next++);
605
            *next = '\0';
615
            *next = '\0';
606
        } else if (replen > patlen) {
616
        } else if (replen > patlen) {
607
            char * end = pos + patlen;
617
            char * end = pos + patlen;
608
            char * next = word + strlen(word) + replen - patlen;
618
            char * next = word + strlen(word) + replen - patlen;
609
            char * prev = next - replen + patlen;
619
            char * prev = next - replen + patlen;
610
            for (; prev >= end; *next = *prev, prev--, next--);
620
            for (; prev >= end; *next = *prev, prev--, next--);
611
        }
621
        }
612
        strncpy(pos, rep, replen);
622
        strncpy(pos, rep, replen);
623
        pos = strstr(word, pat);
624
      }
613
    }
625
    }
614
    return word;
626
    return word;
615
}
627
}
616
628
617
 // reverse word 
629
 // reverse word 
618
 int reverseword(char * word) {
630
 int reverseword(char * word) {
619
   char r;
631
   char r;
620
   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
632
   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
 Lines 5165-5209   static struct cs_info iscii_devanagari_t Link Here 
5165
{ 0x00, 0xfa, 0xfa },
5177
{ 0x00, 0xfa, 0xfa },
5166
{ 0x00, 0xfb, 0xfb },
5178
{ 0x00, 0xfb, 0xfb },
5167
{ 0x00, 0xfc, 0xfc },
5179
{ 0x00, 0xfc, 0xfc },
5168
{ 0x00, 0xfd, 0xfd },
5180
{ 0x00, 0xfd, 0xfd },
5169
{ 0x00, 0xfe, 0xfe },
5181
{ 0x00, 0xfe, 0xfe },
5170
{ 0x00, 0xff, 0xff }
5182
{ 0x00, 0xff, 0xff }
5171
};
5183
};
5172
5184
5173
static struct enc_entry encds[] = {
5185
static struct cs_info tis620_tbl[] = {
5174
{"ISO8859-1",iso1_tbl},
5186
{ 0x00, 0x00, 0x00 },
5175
{"ISO8859-2",iso2_tbl},
5187
{ 0x00, 0x01, 0x01 },
5176
{"ISO8859-3",iso3_tbl},
5188
{ 0x00, 0x02, 0x02 },
5177
{"ISO8859-4",iso4_tbl},
5189
{ 0x00, 0x03, 0x03 },
5178
{"ISO8859-5",iso5_tbl},
5190
{ 0x00, 0x04, 0x04 },
5179
{"ISO8859-6",iso6_tbl},
5191
{ 0x00, 0x05, 0x05 },
5180
{"ISO8859-7",iso7_tbl},
5192
{ 0x00, 0x06, 0x06 },
5181
{"ISO8859-8",iso8_tbl},
5193
{ 0x00, 0x07, 0x07 },
5182
{"ISO8859-9",iso9_tbl},
5194
{ 0x00, 0x08, 0x08 },
5183
{"ISO8859-10",iso10_tbl},
5195
{ 0x00, 0x09, 0x09 },
5184
{"KOI8-R",koi8r_tbl},
5196
{ 0x00, 0x0a, 0x0a },
5185
{"KOI8-U",koi8u_tbl},
5197
{ 0x00, 0x0b, 0x0b },
5186
{"microsoft-cp1251",cp1251_tbl},
5198
{ 0x00, 0x0c, 0x0c },
5187
{"ISO8859-13", iso13_tbl},
5199
{ 0x00, 0x0d, 0x0d },
5188
{"ISO8859-14", iso14_tbl},
5200
{ 0x00, 0x0e, 0x0e },
5189
{"ISO8859-15", iso15_tbl},
5201
{ 0x00, 0x0f, 0x0f },
5190
{"ISCII-DEVANAGARI", iscii_devanagari_tbl}
5202
{ 0x00, 0x10, 0x10 },
5203
{ 0x00, 0x11, 0x11 },
5204
{ 0x00, 0x12, 0x12 },
5205
{ 0x00, 0x13, 0x13 },
5206
{ 0x00, 0x14, 0x14 },
5207
{ 0x00, 0x15, 0x15 },
5208
{ 0x00, 0x16, 0x16 },
5209
{ 0x00, 0x17, 0x17 },
5210
{ 0x00, 0x18, 0x18 },
5211
{ 0x00, 0x19, 0x19 },
5212
{ 0x00, 0x1a, 0x1a },
5213
{ 0x00, 0x1b, 0x1b },
5214
{ 0x00, 0x1c, 0x1c },
5215
{ 0x00, 0x1d, 0x1d },
5216
{ 0x00, 0x1e, 0x1e },
5217
{ 0x00, 0x1f, 0x1f },
5218
{ 0x00, 0x20, 0x20 },
5219
{ 0x00, 0x21, 0x21 },
5220
{ 0x00, 0x22, 0x22 },
5221
{ 0x00, 0x23, 0x23 },
5222
{ 0x00, 0x24, 0x24 },
5223
{ 0x00, 0x25, 0x25 },
5224
{ 0x00, 0x26, 0x26 },
5225
{ 0x00, 0x27, 0x27 },
5226
{ 0x00, 0x28, 0x28 },
5227
{ 0x00, 0x29, 0x29 },
5228
{ 0x00, 0x2a, 0x2a },
5229
{ 0x00, 0x2b, 0x2b },
5230
{ 0x00, 0x2c, 0x2c },
5231
{ 0x00, 0x2d, 0x2d },
5232
{ 0x00, 0x2e, 0x2e },
5233
{ 0x00, 0x2f, 0x2f },
5234
{ 0x00, 0x30, 0x30 },
5235
{ 0x00, 0x31, 0x31 },
5236
{ 0x00, 0x32, 0x32 },
5237
{ 0x00, 0x33, 0x33 },
5238
{ 0x00, 0x34, 0x34 },
5239
{ 0x00, 0x35, 0x35 },
5240
{ 0x00, 0x36, 0x36 },
5241
{ 0x00, 0x37, 0x37 },
5242
{ 0x00, 0x38, 0x38 },
5243
{ 0x00, 0x39, 0x39 },
5244
{ 0x00, 0x3a, 0x3a },
5245
{ 0x00, 0x3b, 0x3b },
5246
{ 0x00, 0x3c, 0x3c },
5247
{ 0x00, 0x3d, 0x3d },
5248
{ 0x00, 0x3e, 0x3e },
5249
{ 0x00, 0x3f, 0x3f },
5250
{ 0x00, 0x40, 0x40 },
5251
{ 0x01, 0x61, 0x41 },
5252
{ 0x01, 0x62, 0x42 },
5253
{ 0x01, 0x63, 0x43 },
5254
{ 0x01, 0x64, 0x44 },
5255
{ 0x01, 0x65, 0x45 },
5256
{ 0x01, 0x66, 0x46 },
5257
{ 0x01, 0x67, 0x47 },
5258
{ 0x01, 0x68, 0x48 },
5259
{ 0x01, 0x69, 0x49 },
5260
{ 0x01, 0x6a, 0x4a },
5261
{ 0x01, 0x6b, 0x4b },
5262
{ 0x01, 0x6c, 0x4c },
5263
{ 0x01, 0x6d, 0x4d },
5264
{ 0x01, 0x6e, 0x4e },
5265
{ 0x01, 0x6f, 0x4f },
5266
{ 0x01, 0x70, 0x50 },
5267
{ 0x01, 0x71, 0x51 },
5268
{ 0x01, 0x72, 0x52 },
5269
{ 0x01, 0x73, 0x53 },
5270
{ 0x01, 0x74, 0x54 },
5271
{ 0x01, 0x75, 0x55 },
5272
{ 0x01, 0x76, 0x56 },
5273
{ 0x01, 0x77, 0x57 },
5274
{ 0x01, 0x78, 0x58 },
5275
{ 0x01, 0x79, 0x59 },
5276
{ 0x01, 0x7a, 0x5a },
5277
{ 0x00, 0x5b, 0x5b },
5278
{ 0x00, 0x5c, 0x5c },
5279
{ 0x00, 0x5d, 0x5d },
5280
{ 0x00, 0x5e, 0x5e },
5281
{ 0x00, 0x5f, 0x5f },
5282
{ 0x00, 0x60, 0x60 },
5283
{ 0x00, 0x61, 0x41 },
5284
{ 0x00, 0x62, 0x42 },
5285
{ 0x00, 0x63, 0x43 },
5286
{ 0x00, 0x64, 0x44 },
5287
{ 0x00, 0x65, 0x45 },
5288
{ 0x00, 0x66, 0x46 },
5289
{ 0x00, 0x67, 0x47 },
5290
{ 0x00, 0x68, 0x48 },
5291
{ 0x00, 0x69, 0x49 },
5292
{ 0x00, 0x6a, 0x4a },
5293
{ 0x00, 0x6b, 0x4b },
5294
{ 0x00, 0x6c, 0x4c },
5295
{ 0x00, 0x6d, 0x4d },
5296
{ 0x00, 0x6e, 0x4e },
5297
{ 0x00, 0x6f, 0x4f },
5298
{ 0x00, 0x70, 0x50 },
5299
{ 0x00, 0x71, 0x51 },
5300
{ 0x00, 0x72, 0x52 },
5301
{ 0x00, 0x73, 0x53 },
5302
{ 0x00, 0x74, 0x54 },
5303
{ 0x00, 0x75, 0x55 },
5304
{ 0x00, 0x76, 0x56 },
5305
{ 0x00, 0x77, 0x57 },
5306
{ 0x00, 0x78, 0x58 },
5307
{ 0x00, 0x79, 0x59 },
5308
{ 0x00, 0x7a, 0x5a },
5309
{ 0x00, 0x7b, 0x7b },
5310
{ 0x00, 0x7c, 0x7c },
5311
{ 0x00, 0x7d, 0x7d },
5312
{ 0x00, 0x7e, 0x7e },
5313
{ 0x00, 0x7f, 0x7f },
5314
{ 0x00, 0x80, 0x80 },
5315
{ 0x00, 0x81, 0x81 },
5316
{ 0x00, 0x82, 0x82 },
5317
{ 0x00, 0x83, 0x83 },
5318
{ 0x00, 0x84, 0x84 },
5319
{ 0x00, 0x85, 0x85 },
5320
{ 0x00, 0x86, 0x86 },
5321
{ 0x00, 0x87, 0x87 },
5322
{ 0x00, 0x88, 0x88 },
5323
{ 0x00, 0x89, 0x89 },
5324
{ 0x00, 0x8a, 0x8a },
5325
{ 0x00, 0x8b, 0x8b },
5326
{ 0x00, 0x8c, 0x8c },
5327
{ 0x00, 0x8d, 0x8d },
5328
{ 0x00, 0x8e, 0x8e },
5329
{ 0x00, 0x8f, 0x8f },
5330
{ 0x00, 0x90, 0x90 },
5331
{ 0x00, 0x91, 0x91 },
5332
{ 0x00, 0x92, 0x92 },
5333
{ 0x00, 0x93, 0x93 },
5334
{ 0x00, 0x94, 0x94 },
5335
{ 0x00, 0x95, 0x95 },
5336
{ 0x00, 0x96, 0x96 },
5337
{ 0x00, 0x97, 0x97 },
5338
{ 0x00, 0x98, 0x98 },
5339
{ 0x00, 0x99, 0x99 },
5340
{ 0x00, 0x9a, 0x9a },
5341
{ 0x00, 0x9b, 0x9b },
5342
{ 0x00, 0x9c, 0x9c },
5343
{ 0x00, 0x9d, 0x9d },
5344
{ 0x00, 0x9e, 0x9e },
5345
{ 0x00, 0x9f, 0x9f },
5346
{ 0x00, 0xa0, 0xa0 },
5347
{ 0x00, 0xa1, 0xa1 },
5348
{ 0x00, 0xa2, 0xa2 },
5349
{ 0x00, 0xa3, 0xa3 },
5350
{ 0x00, 0xa4, 0xa4 },
5351
{ 0x00, 0xa5, 0xa5 },
5352
{ 0x00, 0xa6, 0xa6 },
5353
{ 0x00, 0xa7, 0xa7 },
5354
{ 0x00, 0xa8, 0xa8 },
5355
{ 0x00, 0xa9, 0xa9 },
5356
{ 0x00, 0xaa, 0xaa },
5357
{ 0x00, 0xab, 0xab },
5358
{ 0x00, 0xac, 0xac },
5359
{ 0x00, 0xad, 0xad },
5360
{ 0x00, 0xae, 0xae },
5361
{ 0x00, 0xaf, 0xaf },
5362
{ 0x00, 0xb0, 0xb0 },
5363
{ 0x00, 0xb1, 0xb1 },
5364
{ 0x00, 0xb2, 0xb2 },
5365
{ 0x00, 0xb3, 0xb3 },
5366
{ 0x00, 0xb4, 0xb4 },
5367
{ 0x00, 0xb5, 0xb5 },
5368
{ 0x00, 0xb6, 0xb6 },
5369
{ 0x00, 0xb7, 0xb7 },
5370
{ 0x00, 0xb8, 0xb8 },
5371
{ 0x00, 0xb9, 0xb9 },
5372
{ 0x00, 0xba, 0xba },
5373
{ 0x00, 0xbb, 0xbb },
5374
{ 0x00, 0xbc, 0xbc },
5375
{ 0x00, 0xbd, 0xbd },
5376
{ 0x00, 0xbe, 0xbe },
5377
{ 0x00, 0xbf, 0xbf },
5378
{ 0x00, 0xc0, 0xc0 },
5379
{ 0x00, 0xc1, 0xc1 },
5380
{ 0x00, 0xc2, 0xc2 },
5381
{ 0x00, 0xc3, 0xc3 },
5382
{ 0x00, 0xc4, 0xc4 },
5383
{ 0x00, 0xc5, 0xc5 },
5384
{ 0x00, 0xc6, 0xc6 },
5385
{ 0x00, 0xc7, 0xc7 },
5386
{ 0x00, 0xc8, 0xc8 },
5387
{ 0x00, 0xc9, 0xc9 },
5388
{ 0x00, 0xca, 0xca },
5389
{ 0x00, 0xcb, 0xcb },
5390
{ 0x00, 0xcc, 0xcc },
5391
{ 0x00, 0xcd, 0xcd },
5392
{ 0x00, 0xce, 0xce },
5393
{ 0x00, 0xcf, 0xcf },
5394
{ 0x00, 0xd0, 0xd0 },
5395
{ 0x00, 0xd1, 0xd1 },
5396
{ 0x00, 0xd2, 0xd2 },
5397
{ 0x00, 0xd3, 0xd3 },
5398
{ 0x00, 0xd4, 0xd4 },
5399
{ 0x00, 0xd5, 0xd5 },
5400
{ 0x00, 0xd6, 0xd6 },
5401
{ 0x00, 0xd7, 0xd7 },
5402
{ 0x00, 0xd8, 0xd8 },
5403
{ 0x00, 0xd9, 0xd9 },
5404
{ 0x00, 0xda, 0xda },
5405
{ 0x00, 0xdb, 0xdb },
5406
{ 0x00, 0xdc, 0xdc },
5407
{ 0x00, 0xdd, 0xdd },
5408
{ 0x00, 0xde, 0xde },
5409
{ 0x00, 0xdf, 0xdf },
5410
{ 0x00, 0xe0, 0xe0 },
5411
{ 0x00, 0xe1, 0xe1 },
5412
{ 0x00, 0xe2, 0xe2 },
5413
{ 0x00, 0xe3, 0xe3 },
5414
{ 0x00, 0xe4, 0xe4 },
5415
{ 0x00, 0xe5, 0xe5 },
5416
{ 0x00, 0xe6, 0xe6 },
5417
{ 0x00, 0xe7, 0xe7 },
5418
{ 0x00, 0xe8, 0xe8 },
5419
{ 0x00, 0xe9, 0xe9 },
5420
{ 0x00, 0xea, 0xea },
5421
{ 0x00, 0xeb, 0xeb },
5422
{ 0x00, 0xec, 0xec },
5423
{ 0x00, 0xed, 0xed },
5424
{ 0x00, 0xee, 0xee },
5425
{ 0x00, 0xef, 0xef },
5426
{ 0x00, 0xf0, 0xf0 },
5427
{ 0x00, 0xf1, 0xf1 },
5428
{ 0x00, 0xf2, 0xf2 },
5429
{ 0x00, 0xf3, 0xf3 },
5430
{ 0x00, 0xf4, 0xf4 },
5431
{ 0x00, 0xf5, 0xf5 },
5432
{ 0x00, 0xf6, 0xf6 },
5433
{ 0x00, 0xf7, 0xf7 },
5434
{ 0x00, 0xf8, 0xf8 },
5435
{ 0x00, 0xf9, 0xf9 },
5436
{ 0x00, 0xfa, 0xfa },
5437
{ 0x00, 0xfb, 0xfb },
5438
{ 0x00, 0xfc, 0xfc },
5439
{ 0x00, 0xfd, 0xfd },
5440
{ 0x00, 0xfe, 0xfe },
5441
{ 0x00, 0xff, 0xff }
5191
};
5442
};
5192
5443
5444
struct enc_entry {
5445
  const char * enc_name;
5446
  struct cs_info * cs_table;
5447
};
5448
5449
static struct enc_entry encds[] = {
5450
  {"iso88591",iso1_tbl},                     //ISO-8859-1
5451
  {"iso88592",iso2_tbl},                     //ISO-8859-2
5452
  {"iso88593",iso3_tbl},                     //ISO-8859-3
5453
  {"iso88594",iso4_tbl},                     //ISO-8859-4
5454
  {"iso88595",iso5_tbl},                     //ISO-8859-5
5455
  {"iso88596",iso6_tbl},                     //ISO-8859-6
5456
  {"iso88597",iso7_tbl},                     //ISO-8859-7
5457
  {"iso88598",iso8_tbl},                     //ISO-8859-8
5458
  {"iso88599",iso9_tbl},                     //ISO-8859-9
5459
  {"iso885910",iso10_tbl},                   //ISO-8859-10
5460
  {"tis620",tis620_tbl},                     //TIS-620/ISO-8859-11
5461
  {"tis6202533",tis620_tbl},                 //TIS-620/ISO-8859-11
5462
  {"iso885911",tis620_tbl},                  //TIS-620/ISO-8859-11
5463
  {"iso885913", iso13_tbl},                  //ISO-8859-13
5464
  {"iso885914", iso14_tbl},                  //ISO-8859-14
5465
  {"iso885915", iso15_tbl},                  //ISO-8859-15
5466
  {"koi8r",koi8r_tbl},                       //KOI8-R
5467
  {"koi8u",koi8u_tbl},                       //KOI8-U
5468
  {"cp1251",cp1251_tbl},                     //CP-1251
5469
  {"microsoftcp1251",cp1251_tbl},            //microsoft-cp1251
5470
  {"xisciias", iscii_devanagari_tbl},        //x-iscii-as
5471
  {"isciidevanagari", iscii_devanagari_tbl}  //ISCII-DEVANAGARI
5472
};
5473
5474
/* map to lower case and remove non alphanumeric chars */
5475
static void toAsciiLowerAndRemoveNonAlphanumeric( const char* pName, char* pBuf )
5476
{
5477
    while ( *pName )
5478
    {
5479
        /* A-Z */
5480
        if ( (*pName >= 0x41) && (*pName <= 0x5A) )
5481
        {
5482
            *pBuf = (*pName)+0x20;  /* toAsciiLower */
5483
            pBuf++;
5484
        }
5485
        /* a-z, 0-9 */
5486
        else if ( ((*pName >= 0x61) && (*pName <= 0x7A)) ||
5487
                  ((*pName >= 0x30) && (*pName <= 0x39)) )
5488
        {
5489
            *pBuf = *pName;
5490
            pBuf++;
5491
        }
5492
5493
        pName++;
5494
    }
5495
5496
    *pBuf = '\0';
5497
}
5498
5193
struct cs_info * get_current_cs(const char * es) {
5499
struct cs_info * get_current_cs(const char * es) {
5194
  struct cs_info * ccs = encds[0].cs_table;
5500
  char *normalized_encoding = new char[strlen(es)+1];
5501
  toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding);
5502
5503
  struct cs_info * ccs = NULL;
5195
  int n = sizeof(encds) / sizeof(encds[0]);
5504
  int n = sizeof(encds) / sizeof(encds[0]);
5196
  for (int i = 0; i < n; i++) {
5505
  for (int i = 0; i < n; i++) {
5197
    if (strcmp(es,encds[i].enc_name) == 0) {
5506
    if (strcmp(normalized_encoding,encds[i].enc_name) == 0) {
5198
      ccs = encds[i].cs_table;
5507
      ccs = encds[i].cs_table;
5199
      break;
5508
      break;
5200
    }
5509
    }
5201
  }
5510
  }
5511
5512
  delete[] normalized_encoding;
5513
5514
  if (!ccs) {
5515
    HUNSPELL_WARNING(stderr, "error: unknown encoding %s: using %s as fallback\n", es, encds[0].enc_name);
5516
    ccs = encds[0].cs_table;
5517
  }
5518
5202
  return ccs;
5519
  return ccs;
5203
}
5520
}
5204
#else
5521
#else
5205
// XXX This function was rewritten for mozilla. Instead of storing the
5522
// XXX This function was rewritten for mozilla. Instead of storing the
5206
// conversion tables static in this file, create them when needed
5523
// conversion tables static in this file, create them when needed
5207
// with help the mozilla backend.
5524
// with help the mozilla backend.
5208
struct cs_info * get_current_cs(const char * es) {
5525
struct cs_info * get_current_cs(const char * es) {
5209
  struct cs_info *ccs;
5526
  struct cs_info *ccs;
 Lines 5220-5235   struct cs_info * get_current_cs(const ch Link Here 
5220
  if (NS_FAILED(rv))
5537
  if (NS_FAILED(rv))
5221
    return nsnull;
5538
    return nsnull;
5222
  encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?');
5539
  encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?');
5223
  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
5540
  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
5224
  if (NS_FAILED(rv))
5541
  if (NS_FAILED(rv))
5225
    return nsnull;
5542
    return nsnull;
5226
  decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
5543
  decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
5227
5544
5545
  if (NS_FAILED(rv))
5546
    return nsnull;
5547
5228
  ccs = new cs_info[256];
5548
  ccs = new cs_info[256];
5229
5549
5230
  for (unsigned int i = 0; i <= 0xff; ++i) {
5550
  for (unsigned int i = 0; i <= 0xff; ++i) {
5231
    PRBool success = PR_FALSE;
5551
    PRBool success = PR_FALSE;
5232
    // We want to find the upper/lowercase equivalents of each byte
5552
    // We want to find the upper/lowercase equivalents of each byte
5233
    // in this 1-byte character encoding.  Call our encoding/decoding
5553
    // in this 1-byte character encoding.  Call our encoding/decoding
5234
    // APIs separately for each byte since they may reject some of the
5554
    // APIs separately for each byte since they may reject some of the
5235
    // bytes, and we want to handle errors separately for each byte.
5555
    // bytes, and we want to handle errors separately for each byte.
 Lines 5294-5354   char * get_casechars(const char * enc) { Link Here 
5294
    }
5614
    }
5295
    *p = '\0';
5615
    *p = '\0';
5296
#ifdef MOZILLA_CLIENT
5616
#ifdef MOZILLA_CLIENT
5297
    delete [] csconv;
5617
    delete [] csconv;
5298
#endif
5618
#endif
5299
    return mystrdup(expw);
5619
    return mystrdup(expw);
5300
}
5620
}
5301
5621
5622
// language to encoding default map
5302
5623
5624
struct lang_map {
5625
  const char * lang;
5626
  int num;
5627
};
5303
5628
5304
static struct lang_map lang2enc[] = {
5629
static struct lang_map lang2enc[] = {
5305
{"ar", "UTF-8", LANG_ar},
5630
{"ar", LANG_ar},
5306
{"az", "UTF-8", LANG_az},
5631
{"az", LANG_az},
5307
{"bg", "microsoft-cp1251", LANG_bg},
5632
{"az_AZ", LANG_az}, // for back-compatibility
5308
{"ca", "ISO8859-1", LANG_ca},
5633
{"bg", LANG_bg},
5309
{"cs", "ISO8859-2", LANG_cs},
5634
{"ca", LANG_ca},
5310
{"da", "ISO8859-1", LANG_da},
5635
{"cs", LANG_cs},
5311
{"de", "ISO8859-1", LANG_de},
5636
{"da", LANG_da},
5312
{"el", "ISO8859-7", LANG_el},
5637
{"de", LANG_de},
5313
{"en", "ISO8859-1", LANG_en},
5638
{"el", LANG_el},
5314
{"es", "ISO8859-1", LANG_es},
5639
{"en", LANG_en},
5315
{"eu", "ISO8859-1", LANG_eu},
5640
{"es", LANG_es},
5316
{"gl", "ISO8859-1", LANG_gl},
5641
{"eu", LANG_eu},
5317
{"fr", "ISO8859-15", LANG_fr},
5642
{"gl", LANG_gl},
5318
{"hr", "ISO8859-2", LANG_hr},
5643
{"fr", LANG_fr},
5319
{"hu", "ISO8859-2", LANG_hu},
5644
{"hr", LANG_hr},
5320
{"it", "ISO8859-1", LANG_it},
5645
{"hu", LANG_hu},
5321
{"la", "ISO8859-1", LANG_la},
5646
{"hu_HU", LANG_hu}, // for back-compatibility
5322
{"lv", "ISO8859-13", LANG_lv},
5647
{"it", LANG_it},
5323
{"nl", "ISO8859-1", LANG_nl},
5648
{"la", LANG_la},
5324
{"pl", "ISO8859-2", LANG_pl},
5649
{"lv", LANG_lv},
5325
{"pt", "ISO8859-1", LANG_pt},
5650
{"nl", LANG_nl},
5326
{"sv", "ISO8859-1", LANG_sv},
5651
{"pl", LANG_pl},
5327
{"tr", "UTF-8", LANG_tr},
5652
{"pt", LANG_pt},
5328
{"ru", "KOI8-R", LANG_ru},
5653
{"sv", LANG_sv},
5329
{"uk", "KOI8-U", LANG_uk}
5654
{"tr", LANG_tr},
5655
{"tr_TR", LANG_tr}, // for back-compatibility
5656
{"ru", LANG_ru},
5657
{"uk", LANG_uk}
5330
};
5658
};
5331
5659
5332
5660
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) {
5661
int get_lang_num(const char * lang) {
5344
  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
5662
  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
5345
  for (int i = 0; i < n; i++) {
5663
  for (int i = 0; i < n; i++) {
5346
    if (strncmp(lang,lang2enc[i].lang,2) == 0) {
5664
    if (strcmp(lang, lang2enc[i].lang) == 0) {
5347
      return lang2enc[i].num;
5665
      return lang2enc[i].num;
5348
    }
5666
    }
5349
  }
5667
  }
5350
  return LANG_xx;
5668
  return LANG_xx;
5351
}
5669
}
5352
5670
5353
#ifndef OPENOFFICEORG
5671
#ifndef OPENOFFICEORG
5354
#ifndef MOZILLA_CLIENT
5672
#ifndef MOZILLA_CLIENT
(-)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 lines)
Line     Link Here 
 Lines 541-557   int HashMgr::hash(const char * word) con Link Here 
541
      hv ^= (*word++);
541
      hv ^= (*word++);
542
    }
542
    }
543
    return (unsigned long) hv % tablesize;
543
    return (unsigned long) hv % tablesize;
544
}
544
}
545
545
546
int HashMgr::decode_flags(unsigned short ** result, char * flags, FileMgr * af) {
546
int HashMgr::decode_flags(unsigned short ** result, char * flags, FileMgr * af) {
547
    int len;
547
    int len;
548
    if (*flags == '\0') {
548
    if (*flags == '\0') {
549
        HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n", af->getlinenum());
550
        *result = NULL;
549
        *result = NULL;
551
        return 0;
550
        return 0;
552
    }
551
    }
553
    switch (flag_mode) {
552
    switch (flag_mode) {
554
      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
553
      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
555
        len = strlen(flags);
554
        len = strlen(flags);
556
        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());
557
        len /= 2;
556
        len /= 2;
(-)a/extensions/spellcheck/hunspell/src/hunspell.cpp (-11 / +47 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 417-443   int Hunspell::spell(const char * word, i Link Here 
417
    } else break;
418
    } else break;
418
  }
419
  }
419
  if ((i == wl) && (nstate == NNUM)) return 1;
420
  if ((i == wl) && (nstate == NNUM)) return 1;
420
  if (!info) info = &info2; else *info = 0;
421
  if (!info) info = &info2; else *info = 0;
421
422
422
  switch(captype) {
423
  switch(captype) {
423
     case HUHCAP:
424
     case HUHCAP:
424
     case HUHINITCAP:
425
     case HUHINITCAP:
426
            *info += SPELL_ORIGCAP;
425
     case NOCAP: {
427
     case NOCAP: {
426
            rv = checkword(cw, info, root);
428
            rv = checkword(cw, info, root);
427
            if ((abbv) && !(rv)) {
429
            if ((abbv) && !(rv)) {
428
                memcpy(wspace,cw,wl);
430
                memcpy(wspace,cw,wl);
429
                *(wspace+wl) = '.';
431
                *(wspace+wl) = '.';
430
                *(wspace+wl+1) = '\0';
432
                *(wspace+wl+1) = '\0';
431
                rv = checkword(wspace, info, root);
433
                rv = checkword(wspace, info, root);
432
            }
434
            }
433
            break;
435
            break;
434
         }
436
         }
435
     case ALLCAP: {
437
     case ALLCAP: {
438
            *info += SPELL_ORIGCAP;
436
            rv = checkword(cw, info, root);
439
            rv = checkword(cw, info, root);
437
            if (rv) break;
440
            if (rv) break;
438
            if (abbv) {
441
            if (abbv) {
439
                memcpy(wspace,cw,wl);
442
                memcpy(wspace,cw,wl);
440
                *(wspace+wl) = '.';
443
                *(wspace+wl) = '.';
441
                *(wspace+wl+1) = '\0';
444
                *(wspace+wl+1) = '\0';
442
                rv = checkword(wspace, info, root);
445
                rv = checkword(wspace, info, root);
443
                if (rv) break;
446
                if (rv) break;
 Lines 488-509   int Hunspell::spell(const char * word, i Link Here 
488
                        *(wspace+wl2+1) = '\0';
491
                        *(wspace+wl2+1) = '\0';
489
                        rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
492
                        rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
490
                    }
493
                    }
491
                }
494
                }
492
                if (rv) break;
495
                if (rv) break;
493
            }
496
            }
494
        }
497
        }
495
     case INITCAP: {
498
     case INITCAP: {
499
             *info += SPELL_ORIGCAP;
496
             wl = mkallsmall2(cw, unicw, nc);
500
             wl = mkallsmall2(cw, unicw, nc);
497
             memcpy(wspace,cw,(wl+1));
501
             memcpy(wspace,cw,(wl+1));
498
             wl2 = mkinitcap2(cw, unicw, nc);
502
             wl2 = mkinitcap2(cw, unicw, nc);
499
    	     if (captype == INITCAP) *info += SPELL_INITCAP;
503
             if (captype == INITCAP) *info += SPELL_INITCAP;
500
             rv = checkword(cw, info, root);
504
             rv = checkword(cw, info, root);
501
    	     if (captype == INITCAP) *info -= SPELL_INITCAP;
505
             if (captype == INITCAP) *info -= SPELL_INITCAP;
502
             // forbid bad capitalization
506
             // forbid bad capitalization
503
             // (for example, ijs -> Ijs instead of IJs in Dutch)
507
             // (for example, ijs -> Ijs instead of IJs in Dutch)
504
             // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
508
             // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
505
             if (*info & SPELL_FORBIDDEN) {
509
             if (*info & SPELL_FORBIDDEN) {
506
                rv = NULL;
510
                rv = NULL;
507
                break;
511
                break;
508
             }
512
             }
509
             if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
513
             if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
 Lines 532-548   int Hunspell::spell(const char * word, i Link Here 
532
                   // in INITCAP form, too.
536
                   // in INITCAP form, too.
533
                   !(pAMgr->get_checksharps() &&
537
                   !(pAMgr->get_checksharps() &&
534
                      ((utf8 && strstr(wspace, "\xC3\x9F")) ||
538
                      ((utf8 && strstr(wspace, "\xC3\x9F")) ||
535
                      (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL;
539
                      (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL;
536
             break;
540
             break;
537
           }
541
           }
538
  }
542
  }
539
543
540
  if (rv) return 1;
544
  if (rv) {
545
      if (pAMgr && pAMgr->get_warn() && rv->astr &&
546
          TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) {
547
              *info += SPELL_WARN;
548
	      if (pAMgr->get_forbidwarn()) return 0;
549
              return HUNSPELL_OK_WARN;
550
      }
551
      return HUNSPELL_OK;
552
  }
541
553
542
  // recursive breaking at break points
554
  // recursive breaking at break points
543
  if (wordbreak) {
555
  if (wordbreak) {
544
    char * s;
556
    char * s;
545
    char r;
557
    char r;
546
    int nbr = 0;
558
    int nbr = 0;
547
    wl = strlen(cw);
559
    wl = strlen(cw);
548
    int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
560
    int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
 Lines 618-633   struct hentry * Hunspell::checkword(cons Link Here 
618
        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
630
        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
619
        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
631
        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
620
     } else {
632
     } else {
621
        remove_ignored_chars(w2,ignoredchars);
633
        remove_ignored_chars(w2,ignoredchars);
622
     }
634
     }
623
     word = w2;
635
     word = w2;
624
  } else word = w;
636
  } else word = w;
625
637
638
  len = strlen(word);
639
640
  if (!len)
641
      return NULL;
642
626
  // word reversing wrapper for complex prefixes
643
  // word reversing wrapper for complex prefixes
627
  if (complexprefixes) {
644
  if (complexprefixes) {
628
    if (word != w2) {
645
    if (word != w2) {
629
      strcpy(w2, word);
646
      strcpy(w2, word);
630
      word = w2;
647
      word = w2;
631
    }
648
    }
632
    if (utf8) reverseword_utf(w2); else reverseword(w2);
649
    if (utf8) reverseword_utf(w2); else reverseword(w2);
633
  }
650
  }
 Lines 655-671   struct hentry * Hunspell::checkword(cons Link Here 
655
       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
672
       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
656
       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
673
       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
657
    )) he = he->next_homonym;
674
    )) he = he->next_homonym;
658
  }
675
  }
659
676
660
  // check with affixes
677
  // check with affixes
661
  if (!he && pAMgr) {
678
  if (!he && pAMgr) {
662
     // try stripping off affixes */
679
     // try stripping off affixes */
663
     len = strlen(word);
664
     he = pAMgr->affix_check(word, len, 0);
680
     he = pAMgr->affix_check(word, len, 0);
665
681
666
     // check compound restriction and onlyupcase
682
     // check compound restriction and onlyupcase
667
     if (he && he->astr && (
683
     if (he && he->astr && (
668
        (pAMgr->get_onlyincompound() &&
684
        (pAMgr->get_onlyincompound() &&
669
    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
685
    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
670
        (info && (*info & SPELL_INITCAP) &&
686
        (info && (*info & SPELL_INITCAP) &&
671
    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
687
    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
 Lines 680-702   struct hentry * Hunspell::checkword(cons Link Here 
680
        if (root) {
696
        if (root) {
681
            *root = mystrdup(he->word);
697
            *root = mystrdup(he->word);
682
            if (*root && complexprefixes) {
698
            if (*root && complexprefixes) {
683
                if (utf8) reverseword_utf(*root); else reverseword(*root);
699
                if (utf8) reverseword_utf(*root); else reverseword(*root);
684
            }
700
            }
685
        }
701
        }
686
     // try check compound word
702
     // try check compound word
687
     } else if (pAMgr->get_compound()) {
703
     } else if (pAMgr->get_compound()) {
688
          he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0);
704
          he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0, info);
689
          // LANG_hu section: `moving rule' with last dash
705
          // LANG_hu section: `moving rule' with last dash
690
          if ((!he) && (langnum == LANG_hu) && (word[len-1] == '-')) {
706
          if ((!he) && (langnum == LANG_hu) && (word[len-1] == '-')) {
691
             char * dup = mystrdup(word);
707
             char * dup = mystrdup(word);
692
             if (!dup) return NULL;
708
             if (!dup) return NULL;
693
             dup[len-1] = '\0';
709
             dup[len-1] = '\0';
694
             he = pAMgr->compound_check(dup, len-1, -5, 0, 100, 0, NULL, 1, 0);
710
             he = pAMgr->compound_check(dup, len-1, -5, 0, 100, 0, NULL, 1, 0, info);
695
             free(dup);
711
             free(dup);
696
          }
712
          }
697
          // end of LANG speficic region
713
          // end of LANG speficic region
698
          if (he) {
714
          if (he) {
699
                if (root) {
715
                if (root) {
700
                    *root = mystrdup(he->word);
716
                    *root = mystrdup(he->word);
701
                    if (*root && complexprefixes) {
717
                    if (*root && complexprefixes) {
702
                        if (utf8) reverseword_utf(*root); else reverseword(*root);
718
                        if (utf8) reverseword_utf(*root); else reverseword(*root);
 Lines 737-752   int Hunspell::suggest(char*** slst, cons Link Here 
737
  RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
753
  RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
738
  if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
754
  if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv);
739
  else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
755
  else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
740
756
741
  if (wl == 0) return 0;
757
  if (wl == 0) return 0;
742
  int ns = 0;
758
  int ns = 0;
743
  int capwords = 0;
759
  int capwords = 0;
744
760
761
  // check capitalized form for FORCEUCASE
762
  if (pAMgr && captype == NOCAP && pAMgr->get_forceucase()) {
763
    int info = SPELL_ORIGCAP;
764
    char ** wlst;
765
    if (checkword(cw, &info, NULL)) {
766
        if (*slst) {
767
            wlst = *slst;
768
        } else {
769
            wlst = (char **) malloc(MAXSUGGESTION * sizeof(char *));
770
            if (wlst == NULL) return -1;
771
            *slst = wlst;
772
            for (int i = 0; i < MAXSUGGESTION; i++) {
773
                wlst[i] = NULL;
774
            }
775
        }
776
        wlst[0] = mystrdup(cw);
777
        mkinitcap(wlst[0]);
778
        return 1;
779
    }
780
  }
781
 
745
  switch(captype) {
782
  switch(captype) {
746
     case NOCAP:   {
783
     case NOCAP:   {
747
                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
784
                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
748
                     break;
785
                     break;
749
                   }
786
                   }
750
787
751
     case INITCAP: {
788
     case INITCAP: {
752
                     capwords = 1;
789
                     capwords = 1;
 Lines 850-866   int Hunspell::suggest(char*** slst, cons Link Here 
850
                                }
887
                                }
851
                            }
888
                            }
852
                        }
889
                        }
853
                     }
890
                     }
854
                     break;
891
                     break;
855
                   }
892
                   }
856
  }
893
  }
857
894
858
  // LANG_hu section: replace '-' with ' ' in Hungarian
895
 // LANG_hu section: replace '-' with ' ' in Hungarian
859
  if (langnum == LANG_hu) {
896
  if (langnum == LANG_hu) {
860
      for (int j=0; j < ns; j++) {
897
      for (int j=0; j < ns; j++) {
861
          char * pos = strchr((*slst)[j],'-');
898
          char * pos = strchr((*slst)[j],'-');
862
          if (pos) {
899
          if (pos) {
863
              int info;
900
              int info;
864
              char w[MAXWORDUTF8LEN];
901
              char w[MAXWORDUTF8LEN];
865
              *pos = '\0';
902
              *pos = '\0';
866
              strcpy(w, (*slst)[j]);
903
              strcpy(w, (*slst)[j]);
 Lines 869-886   int Hunspell::suggest(char*** slst, cons Link Here 
869
              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
906
              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
870
                  *pos = ' ';
907
                  *pos = ' ';
871
              } else *pos = '-';
908
              } else *pos = '-';
872
          }
909
          }
873
      }
910
      }
874
  }
911
  }
875
  // END OF LANG_hu section
912
  // END OF LANG_hu section
876
913
877
  // try ngram approach since found nothing
914
  // try ngram approach since found nothing or only compound words
878
  if ((ns == 0 || onlycmpdsug) && pAMgr && (pAMgr->get_maxngramsugs() != 0) && (*slst)) {
915
  if (pAMgr && (ns == 0 || onlycmpdsug) && (pAMgr->get_maxngramsugs() != 0) && (*slst)) {
879
      switch(captype) {
916
      switch(captype) {
880
          case NOCAP: {
917
          case NOCAP: {
881
              ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr, maxdic);
918
              ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr, maxdic);
882
              break;
919
              break;
883
          }
920
          }
884
	  case HUHINITCAP:
921
	  case HUHINITCAP:
885
              capwords = 1;
922
              capwords = 1;
886
          case HUHCAP: {
923
          case HUHCAP: {
 Lines 1512-1528   int Hunspell::analyze(char*** slst, cons Link Here 
1512
  }
1549
  }
1513
1550
1514
  if (*result) {
1551
  if (*result) {
1515
    // word reversing wrapper for complex prefixes
1552
    // word reversing wrapper for complex prefixes
1516
    if (complexprefixes) {
1553
    if (complexprefixes) {
1517
      if (utf8) reverseword_utf(result); else reverseword(result);
1554
      if (utf8) reverseword_utf(result); else reverseword(result);
1518
    }
1555
    }
1519
    return line_tok(result, slst, MSEP_REC);
1556
    return line_tok(result, slst, MSEP_REC);
1520
1521
  }
1557
  }
1522
1558
1523
  // compound word with dash (HU) I18n
1559
  // compound word with dash (HU) I18n
1524
  char * dash = NULL;
1560
  char * dash = NULL;
1525
  int nresult = 0;
1561
  int nresult = 0;
1526
  // LANG_hu section: set dash information for suggestions
1562
  // LANG_hu section: set dash information for suggestions
1527
  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
1563
  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
1528
  if ((langnum == LANG_hu) && dash) {
1564
  if ((langnum == LANG_hu) && dash) {
(-)a/extensions/spellcheck/hunspell/src/hunspell.hxx (-6 / +3 lines)
Line     Link Here 
 Lines 57-84    Link Here 
57
57
58
#include "hunvisapi.h"
58
#include "hunvisapi.h"
59
59
60
#include "hashmgr.hxx"
60
#include "hashmgr.hxx"
61
#include "affixmgr.hxx"
61
#include "affixmgr.hxx"
62
#include "suggestmgr.hxx"
62
#include "suggestmgr.hxx"
63
#include "langnum.hxx"
63
#include "langnum.hxx"
64
64
65
#define  SPELL_COMPOUND  (1 << 0)
66
#define  SPELL_FORBIDDEN (1 << 1)
67
#define  SPELL_ALLCAP    (1 << 2)
68
#define  SPELL_NOCAP     (1 << 3)
69
#define  SPELL_INITCAP   (1 << 4)
70
71
#define  SPELL_XML "<?xml?>"
65
#define  SPELL_XML "<?xml?>"
72
66
73
#define MAXDIC 20
67
#define MAXDIC 20
74
#define MAXSUGGESTION 15
68
#define MAXSUGGESTION 15
75
#define MAXSHARPS 5
69
#define MAXSHARPS 5
76
70
71
#define HUNSPELL_OK       (1 << 0)
72
#define HUNSPELL_OK_WARN  (1 << 1)
73
77
#ifndef _MYSPELLMGR_HXX_
74
#ifndef _MYSPELLMGR_HXX_
78
#define _MYSPELLMGR_HXX_
75
#define _MYSPELLMGR_HXX_
79
76
80
class LIBHUNSPELL_DLL_EXPORTED Hunspell
77
class LIBHUNSPELL_DLL_EXPORTED Hunspell
81
{
78
{
82
  AffixMgr*       pAMgr;
79
  AffixMgr*       pAMgr;
83
  HashMgr*        pHMgr[MAXDIC];
80
  HashMgr*        pHMgr[MAXDIC];
84
  int             maxdic;
81
  int             maxdic;
(-)a/extensions/spellcheck/hunspell/src/replist.cpp (-4 / +2 lines)
Line     Link Here 
 Lines 63-120   replentry * RepList::item(int n) { Link Here 
63
    return dat[n];
63
    return dat[n];
64
}
64
}
65
65
66
int RepList::near(const char * word) {
66
int RepList::near(const char * word) {
67
    int p1 = 0;
67
    int p1 = 0;
68
    int p2 = pos;
68
    int p2 = pos;
69
    while ((p2 - p1) > 1) {
69
    while ((p2 - p1) > 1) {
70
      int m = (p1 + p2) / 2;
70
      int m = (p1 + p2) / 2;
71
//      fprintf(stderr, "m: %d p1: %d p2: %d dat: %s\n", m, p1, p2, dat[m]->pattern);
72
      int c = strcmp(word, dat[m]->pattern);
71
      int c = strcmp(word, dat[m]->pattern);
73
      if (c <= 0) {
72
      if (c <= 0) {
74
        if (c < 0) p2 = m; else p1 = p2 = m;
73
        if (c < 0) p2 = m; else p1 = p2 = m;
75
      } else p1 = m;
74
      } else p1 = m;
76
    }
75
    }
77
//    fprintf(stderr, "NEAR: %s (word: %s)\n", dat[p1]->pattern, word);
78
    return p1;
76
    return p1;
79
}
77
}
80
78
81
int RepList::match(const char * word, int n) {
79
int RepList::match(const char * word, int n) {
82
    if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0) return strlen(dat[n]->pattern);
80
    if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0) return strlen(dat[n]->pattern);
83
    return 0;
81
    return 0;
84
}
82
}
85
83
86
int RepList::add(char * pat1, char * pat2) {
84
int RepList::add(char * pat1, char * pat2) {
87
    if (pos >= size || pat1 == NULL || pat2 == NULL) return 1;
85
    if (pos >= size || pat1 == NULL || pat2 == NULL) return 1;
88
    replentry * r = (replentry *) malloc(sizeof(replentry));
86
    replentry * r = (replentry *) malloc(sizeof(replentry));
89
    if (r == NULL) return 1;
87
    if (r == NULL) return 1;
90
    r->pattern = mystrrep(pat1, "_", " ");
88
    r->pattern = mystrrep(pat1, "_", " ");
91
    r->pattern2 = mystrrep(pat2, "_", " ");
89
    r->pattern2 = mystrrep(pat2, "_", " ");
90
    r->start = false;
91
    r->end = false;
92
    dat[pos++] = r;
92
    dat[pos++] = r;
93
    for (int i = pos - 1; i > 0; i--) {
93
    for (int i = pos - 1; i > 0; i--) {
94
      r = dat[i];
94
      r = dat[i];
95
      if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
95
      if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
96
          dat[i] = dat[i - 1];
96
          dat[i] = dat[i - 1];
97
          dat[i - 1] = r;
97
          dat[i - 1] = r;
98
      } else break;
98
      } else break;
99
    }
99
    }
100
    return 0;
100
    return 0;
101
}
101
}
102
102
103
int RepList::conv(const char * word, char * dest) {
103
int RepList::conv(const char * word, char * dest) {
104
    int stl = 0;
104
    int stl = 0;
105
    int change = 0;
105
    int change = 0;
106
//    for (int i = 0; i < pos; i++) fprintf(stderr, "%d. %s\n", i, dat[i]->pattern);
107
    for (size_t i = 0; i < strlen(word); i++) {
106
    for (size_t i = 0; i < strlen(word); i++) {
108
        int n = near(word + i);
107
        int n = near(word + i);
109
        int l = match(word + i, n);
108
        int l = match(word + i, n);
110
        if (l) {
109
        if (l) {
111
          strcpy(dest + stl, dat[n]->pattern2);
110
          strcpy(dest + stl, dat[n]->pattern2);
112
          stl += strlen(dat[n]->pattern2);
111
          stl += strlen(dat[n]->pattern2);
113
          i += l - 1;
112
          i += l - 1;
114
          change = 1;
113
          change = 1;
115
        } else dest[stl++] = word[i];
114
        } else dest[stl++] = word[i];
116
    }
115
    }
117
    dest[stl] = '\0';
116
    dest[stl] = '\0';
118
//    fprintf(stderr, "i: %s o: %s change: %d\n", word, dest, change);
119
    return change;
117
    return change;
120
}
118
}
(-)a/extensions/spellcheck/hunspell/src/suggestmgr.cpp (-78 / +165 lines)
Line     Link Here 
 Lines 86-111   SuggestMgr::SuggestMgr(const char * trym Link Here 
86
86
87
  utf8 = 0;
87
  utf8 = 0;
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
  maxcpdsugs = MAXCOMPOUNDSUGS;
94
95
95
  if (pAMgr) {
96
  if (pAMgr) {
96
        char * enc = pAMgr->get_encoding();
97
        csconv = get_current_cs(enc);
98
        free(enc);
99
        langnum = pAMgr->get_langnum();
97
        langnum = pAMgr->get_langnum();
100
        ckey = pAMgr->get_key_string();
98
        ckey = pAMgr->get_key_string();
101
        nosplitsugs = pAMgr->get_nosplitsugs();
99
        nosplitsugs = pAMgr->get_nosplitsugs();
102
        if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs();
100
        if (pAMgr->get_maxngramsugs() >= 0)
101
            maxngramsugs = pAMgr->get_maxngramsugs();
103
        utf8 = pAMgr->get_utf8();
102
        utf8 = pAMgr->get_utf8();
103
	if (pAMgr->get_maxcpdsugs() >= 0)
104
	    maxcpdsugs = pAMgr->get_maxcpdsugs();
105
        if (!utf8)
106
        {
107
            char * enc = pAMgr->get_encoding();
108
            csconv = get_current_cs(enc);
109
            free(enc);
110
        }
104
        complexprefixes = pAMgr->get_complexprefixes();
111
        complexprefixes = pAMgr->get_complexprefixes();
105
  }
112
  }
106
113
107
  if (ckey) {  
114
  if (ckey) {  
108
    if (utf8) {
115
    if (utf8) {
109
        w_char t[MAXSWL];    
116
        w_char t[MAXSWL];    
110
        ckeyl = u8_u16(t, MAXSWL, ckey);
117
        ckeyl = u8_u16(t, MAXSWL, ckey);
111
        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
118
        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
 Lines 173-191   int SuggestMgr::testsug(char** wlst, con Link Here 
173
180
174
int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
181
int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
175
    int * onlycompoundsug)
182
    int * onlycompoundsug)
176
{
183
{
177
  int nocompoundtwowords = 0;
184
  int nocompoundtwowords = 0;
178
  char ** wlst;    
185
  char ** wlst;    
179
  w_char word_utf[MAXSWL];
186
  w_char word_utf[MAXSWL];
180
  int wl = 0;
187
  int wl = 0;
181
188
  int nsugorig = nsug;
182
  char w2[MAXWORDUTF8LEN];
189
  char w2[MAXWORDUTF8LEN];
183
  const char * word = w;
190
  const char * word = w;
191
  int oldSug = 0;
184
192
185
  // word reversing wrapper for complex prefixes
193
  // word reversing wrapper for complex prefixes
186
  if (complexprefixes) {
194
  if (complexprefixes) {
187
    strcpy(w2, w);
195
    strcpy(w2, w);
188
    if (utf8) reverseword_utf(w2); else reverseword(w2);
196
    if (utf8) reverseword_utf(w2); else reverseword(w2);
189
    word = w2;
197
    word = w2;
190
  }
198
  }
191
    
199
    
 Lines 196-310   int SuggestMgr::suggest(char*** slst, co Link Here 
196
        if (wlst == NULL) return -1;
204
        if (wlst == NULL) return -1;
197
        for (int i = 0; i < maxSug; i++) {
205
        for (int i = 0; i < maxSug; i++) {
198
            wlst[i] = NULL;
206
            wlst[i] = NULL;
199
        }
207
        }
200
    }
208
    }
201
    
209
    
202
    if (utf8) {
210
    if (utf8) {
203
        wl = u8_u16(word_utf, MAXSWL, word);
211
        wl = u8_u16(word_utf, MAXSWL, word);
212
	if (wl == -1) {
213
    		*slst = wlst;
214
		 return nsug;
215
	}
204
    }
216
    }
205
217
206
    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
218
    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
207
219
220
    // limit compound suggestion
221
    if (cpdsuggest > 0) oldSug = nsug;
222
208
    // suggestions for an uppercase word (html -> HTML)
223
    // suggestions for an uppercase word (html -> HTML)
209
    if ((nsug < maxSug) && (nsug > -1)) {
224
    if ((nsug < maxSug) && (nsug > -1)) {
210
        nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
225
        nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
211
                    capchars(wlst, word, nsug, cpdsuggest);
226
                    capchars(wlst, word, nsug, cpdsuggest);
212
    }
227
    }
213
228
214
    // perhaps we made a typical fault of spelling
229
    // perhaps we made a typical fault of spelling
215
    if ((nsug < maxSug) && (nsug > -1))
230
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
216
    nsug = replchars(wlst, word, nsug, cpdsuggest);
231
      nsug = replchars(wlst, word, nsug, cpdsuggest);
232
    }
217
233
218
    // perhaps we made chose the wrong char from a related set
234
    // perhaps we made chose the wrong char from a related set
219
    if ((nsug < maxSug) && (nsug > -1)) {
235
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
220
      nsug = mapchars(wlst, word, nsug, cpdsuggest);
236
      nsug = mapchars(wlst, word, nsug, cpdsuggest);
221
    }
237
    }
222
238
239
    // only suggest compound words when no other suggestion
240
    if ((cpdsuggest == 0) && (nsug > nsugorig)) nocompoundtwowords=1;
241
223
    // did we swap the order of chars by mistake
242
    // did we swap the order of chars by mistake
224
    if ((nsug < maxSug) && (nsug > -1)) {
243
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
225
        nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
244
        nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
226
                    swapchar(wlst, word, nsug, cpdsuggest);
245
                    swapchar(wlst, word, nsug, cpdsuggest);
227
    }
246
    }
228
247
229
    // did we swap the order of non adjacent chars by mistake
248
    // did we swap the order of non adjacent chars by mistake
230
    if ((nsug < maxSug) && (nsug > -1)) {
249
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
231
        nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
250
        nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
232
                    longswapchar(wlst, word, nsug, cpdsuggest);
251
                    longswapchar(wlst, word, nsug, cpdsuggest);
233
    }
252
    }
234
253
235
    // did we just hit the wrong key in place of a good char (case and keyboard)
254
    // did we just hit the wrong key in place of a good char (case and keyboard)
236
    if ((nsug < maxSug) && (nsug > -1)) {
255
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
237
        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
256
        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
238
                    badcharkey(wlst, word, nsug, cpdsuggest);
257
                    badcharkey(wlst, word, nsug, cpdsuggest);
239
    }
258
    }
240
259
241
    // only suggest compound words when no other suggestion
242
    if ((cpdsuggest == 0) && (nsug > 0)) nocompoundtwowords=1;
243
244
    // did we add a char that should not be there
260
    // did we add a char that should not be there
245
    if ((nsug < maxSug) && (nsug > -1)) {
261
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
246
        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
262
        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
247
                    extrachar(wlst, word, nsug, cpdsuggest);
263
                    extrachar(wlst, word, nsug, cpdsuggest);
248
    }
264
    }
249
265
250
266
251
    // did we forgot a char
267
    // did we forgot a char
252
    if ((nsug < maxSug) && (nsug > -1)) {
268
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
253
        nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
269
        nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
254
                    forgotchar(wlst, word, nsug, cpdsuggest);
270
                    forgotchar(wlst, word, nsug, cpdsuggest);
255
    }
271
    }
256
272
257
    // did we move a char
273
    // did we move a char
258
    if ((nsug < maxSug) && (nsug > -1)) {
274
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
259
        nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
275
        nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
260
                    movechar(wlst, word, nsug, cpdsuggest);
276
                    movechar(wlst, word, nsug, cpdsuggest);
261
    }
277
    }
262
278
263
    // did we just hit the wrong key in place of a good char
279
    // did we just hit the wrong key in place of a good char
264
    if ((nsug < maxSug) && (nsug > -1)) {
280
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
265
        nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
281
        nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
266
                    badchar(wlst, word, nsug, cpdsuggest);
282
                    badchar(wlst, word, nsug, cpdsuggest);
267
    }
283
    }
268
284
269
    // did we double two characters
285
    // did we double two characters
270
    if ((nsug < maxSug) && (nsug > -1)) {
286
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
271
        nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
287
        nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
272
                    doubletwochars(wlst, word, nsug, cpdsuggest);
288
                    doubletwochars(wlst, word, nsug, cpdsuggest);
273
    }
289
    }
274
290
275
    // perhaps we forgot to hit space and two words ran together
291
    // perhaps we forgot to hit space and two words ran together
276
    if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) {
292
    if (!nosplitsugs && (nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) {
277
                nsug = twowords(wlst, word, nsug, cpdsuggest);
293
        nsug = twowords(wlst, word, nsug, cpdsuggest);
278
        }
294
    }
279
295
280
    } // repeating ``for'' statement compounding support
296
    } // repeating ``for'' statement compounding support
281
297
282
    if (nsug < 0) {
298
    if (nsug < 0) {
283
     // we ran out of memory - we should free up as much as possible
299
     // we ran out of memory - we should free up as much as possible
284
       for (int i = 0; i < maxSug; i++)
300
       for (int i = 0; i < maxSug; i++)
285
         if (wlst[i] != NULL) free(wlst[i]);
301
         if (wlst[i] != NULL) free(wlst[i]);
286
       free(wlst);
302
       free(wlst);
287
       wlst = NULL;
303
       wlst = NULL;
288
    }
304
    }
289
    
305
290
    if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1;
306
    if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1;
291
307
292
    *slst = wlst;
308
    *slst = wlst;
293
    return nsug;
309
    return nsug;
294
}
310
}
295
311
296
// generate suggestions for a word with typical mistake
312
// generate suggestions for a word with typical mistake
297
//    pass in address of array of char * pointers
313
//    pass in address of array of char * pointers
298
#ifdef HUNSPELL_EXPERIMENTAL
314
#ifdef HUNSPELL_EXPERIMENTAL
299
int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug)
315
int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug)
300
{
316
{
301
    int nocompoundtwowords = 0;
317
    int nocompoundtwowords = 0;
302
    char ** wlst;
318
    char ** wlst;
319
    int oldSug;
303
320
304
  char w2[MAXWORDUTF8LEN];
321
  char w2[MAXWORDUTF8LEN];
305
  const char * word = w;
322
  const char * word = w;
306
323
307
  // word reversing wrapper for complex prefixes
324
  // word reversing wrapper for complex prefixes
308
  if (complexprefixes) {
325
  if (complexprefixes) {
309
    strcpy(w2, w);
326
    strcpy(w2, w);
310
    if (utf8) reverseword_utf(w2); else reverseword(w2);
327
    if (utf8) reverseword_utf(w2); else reverseword(w2);
 Lines 315-343   int SuggestMgr::suggest_auto(char*** sls Link Here 
315
        wlst = *slst;
332
        wlst = *slst;
316
    } else {
333
    } else {
317
        wlst = (char **) malloc(maxSug * sizeof(char *));
334
        wlst = (char **) malloc(maxSug * sizeof(char *));
318
        if (wlst == NULL) return -1;
335
        if (wlst == NULL) return -1;
319
    }
336
    }
320
337
321
    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
338
    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
322
339
340
    // limit compound suggestion
341
    if (cpdsuggest > 0) oldSug = nsug;
342
323
    // perhaps we made a typical fault of spelling
343
    // perhaps we made a typical fault of spelling
324
    if ((nsug < maxSug) && (nsug > -1))
344
    if ((nsug < maxSug) && (nsug > -1))
325
    nsug = replchars(wlst, word, nsug, cpdsuggest);
345
    nsug = replchars(wlst, word, nsug, cpdsuggest);
326
346
327
    // perhaps we made chose the wrong char from a related set
347
    // perhaps we made chose the wrong char from a related set
328
    if ((nsug < maxSug) && (nsug > -1))
348
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs)))
329
      nsug = mapchars(wlst, word, nsug, cpdsuggest);
349
      nsug = mapchars(wlst, word, nsug, cpdsuggest);
330
350
331
    if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1;
351
    if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1;
332
352
333
    // perhaps we forgot to hit space and two words ran together
353
    // perhaps we forgot to hit space and two words ran together
334
354
335
    if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) {
355
    if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs)) && check_forbidden(word, strlen(word))) {
336
                nsug = twowords(wlst, word, nsug, cpdsuggest);
356
                nsug = twowords(wlst, word, nsug, cpdsuggest);
337
        }
357
        }
338
    
358
    
339
    } // repeating ``for'' statement compounding support
359
    } // repeating ``for'' statement compounding support
340
360
341
    if (nsug < 0) {
361
    if (nsug < 0) {
342
       for (int i=0;i<maxSug; i++)
362
       for (int i=0;i<maxSug; i++)
343
         if (wlst[i] != NULL) free(wlst[i]);
363
         if (wlst[i] != NULL) free(wlst[i]);
 Lines 444-482   int SuggestMgr::replchars(char** wlst, c Link Here 
444
  int numrep = pAMgr->get_numrep();
464
  int numrep = pAMgr->get_numrep();
445
  struct replentry* reptable = pAMgr->get_reptable();
465
  struct replentry* reptable = pAMgr->get_reptable();
446
  if (reptable==NULL) return ns;
466
  if (reptable==NULL) return ns;
447
  for (int i=0; i < numrep; i++ ) {
467
  for (int i=0; i < numrep; i++ ) {
448
      r = word;
468
      r = word;
449
      lenr = strlen(reptable[i].pattern2);
469
      lenr = strlen(reptable[i].pattern2);
450
      lenp = strlen(reptable[i].pattern);
470
      lenp = strlen(reptable[i].pattern);
451
      // search every occurence of the pattern in the word
471
      // search every occurence of the pattern in the word
452
      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
472
      while ((r=strstr(r, reptable[i].pattern)) != NULL && (!reptable[i].end || strlen(r) == strlen(reptable[i].pattern)) &&
473
        (!reptable[i].start || r == word)) {
453
          strcpy(candidate, word);
474
          strcpy(candidate, word);
454
          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
475
          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
455
          strcpy(candidate+(r-word),reptable[i].pattern2);
476
          strcpy(candidate+(r-word),reptable[i].pattern2);
456
          strcpy(candidate+(r-word)+lenr, r+lenp);
477
          strcpy(candidate+(r-word)+lenr, r+lenp);
457
          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
478
          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
458
          if (ns == -1) return -1;
479
          if (ns == -1) return -1;
459
          // check REP suggestions with space
480
          // check REP suggestions with space
460
          char * sp = strchr(candidate, ' ');
481
          char * sp = strchr(candidate, ' ');
461
          if (sp) {
482
          if (sp) {
462
            *sp = '\0';
483
            char * prev = candidate;
463
            if (checkword(candidate, strlen(candidate), 0, NULL, NULL)) {
484
            while (sp) {
464
              int oldns = ns;
485
              *sp = '\0';
486
              if (checkword(prev, strlen(prev), 0, NULL, NULL)) {
487
                int oldns = ns;
488
                *sp = ' ';
489
                ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
490
                if (ns == -1) return -1;
491
                if (oldns < ns) {
492
                  free(wlst[ns - 1]);
493
                  wlst[ns - 1] = mystrdup(candidate);
494
                  if (!wlst[ns - 1]) return -1;
495
                }
496
              }
465
              *sp = ' ';
497
              *sp = ' ';
466
              ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
498
              prev = sp + 1;
467
              if (ns == -1) return -1;
499
              sp = strchr(prev, ' ');
468
              if (oldns < ns) {
500
            }
469
                free(wlst[ns - 1]);
470
                wlst[ns - 1] = mystrdup(candidate);
471
                if (!wlst[ns - 1]) return -1;
472
              }
473
            }            
474
            *sp = ' ';
475
          }
501
          }
476
          r++; // search for the next letter
502
          r++; // search for the next letter
477
      }
503
      }
478
   }
504
   }
479
   return ns;
505
   return ns;
480
}
506
}
481
507
482
// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
508
// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
 Lines 1051-1067   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1051
  for (i = 0; i < MAX_ROOTS; i++) {
1077
  for (i = 0; i < MAX_ROOTS; i++) {
1052
    roots[i] = NULL;
1078
    roots[i] = NULL;
1053
    scores[i] = -100 * i;
1079
    scores[i] = -100 * i;
1054
    rootsphon[i] = NULL;
1080
    rootsphon[i] = NULL;
1055
    scoresphon[i] = -100 * i;
1081
    scoresphon[i] = -100 * i;
1056
  }
1082
  }
1057
  lp = MAX_ROOTS - 1;
1083
  lp = MAX_ROOTS - 1;
1058
  lpphon = MAX_ROOTS - 1;
1084
  lpphon = MAX_ROOTS - 1;
1059
  scphon = scoresphon[MAX_ROOTS-1];
1085
  scphon = -20000;
1086
  int low = NGRAM_LOWERING;
1060
  
1087
  
1061
  char w2[MAXWORDUTF8LEN];
1088
  char w2[MAXWORDUTF8LEN];
1062
  char f[MAXSWUTF8L];
1089
  char f[MAXSWUTF8L];
1063
  char * word = w;
1090
  char * word = w;
1064
1091
1065
  // word reversing wrapper for complex prefixes
1092
  // word reversing wrapper for complex prefixes
1066
  if (complexprefixes) {
1093
  if (complexprefixes) {
1067
    strcpy(w2, w);
1094
    strcpy(w2, w);
 Lines 1071-1139   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1071
1098
1072
  char mw[MAXSWUTF8L];
1099
  char mw[MAXSWUTF8L];
1073
  w_char u8[MAXSWL];
1100
  w_char u8[MAXSWL];
1074
  int nc = strlen(word);
1101
  int nc = strlen(word);
1075
  int n = (utf8) ? u8_u16(u8, MAXSWL, word) : nc;
1102
  int n = (utf8) ? u8_u16(u8, MAXSWL, word) : nc;
1076
  
1103
  
1077
  // set character based ngram suggestion for words with non-BMP Unicode characters
1104
  // set character based ngram suggestion for words with non-BMP Unicode characters
1078
  if (n == -1) {
1105
  if (n == -1) {
1079
    utf8 = 0;
1106
    utf8 = 0; // XXX not state-free
1080
    n = nc;
1107
    n = nc;
1081
    nonbmp = 1;
1108
    nonbmp = 1;
1109
    low = 0;
1082
  }
1110
  }
1083
1111
1084
  struct hentry* hp = NULL;
1112
  struct hentry* hp = NULL;
1085
  int col = -1;
1113
  int col = -1;
1086
  phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL;
1114
  phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL;
1087
  char target[MAXSWUTF8L];
1115
  char target[MAXSWUTF8L];
1088
  char candidate[MAXSWUTF8L];
1116
  char candidate[MAXSWUTF8L];
1089
  if (ph) {
1117
  if (ph) {
1090
    strcpy(candidate, word);
1118
    if (utf8) {
1091
    mkallcap(candidate, csconv);
1119
      w_char _w[MAXSWL];
1092
    phonet(candidate, target, n, *ph);
1120
      int _wl = u8_u16(_w, MAXSWL, word);
1121
      mkallcap_utf(_w, _wl, langnum);
1122
      u16_u8(candidate, MAXSWUTF8L, _w, _wl);
1123
    } else {
1124
      strcpy(candidate, word);
1125
      if (!nonbmp) mkallcap(candidate, csconv);
1126
    }
1127
    phonet(candidate, target, nc, *ph); // XXX phonet() is 8-bit (nc, not n)
1093
  }
1128
  }
1094
1129
1130
  FLAG forbiddenword = pAMgr ? pAMgr->get_forbiddenword() : FLAG_NULL;
1131
  FLAG nosuggest = pAMgr ? pAMgr->get_nosuggest() : FLAG_NULL;
1132
  FLAG nongramsuggest = pAMgr ? pAMgr->get_nongramsuggest() : FLAG_NULL;
1133
  FLAG onlyincompound = pAMgr ? pAMgr->get_onlyincompound() : FLAG_NULL;
1134
1095
  for (i = 0; i < md; i++) {  
1135
  for (i = 0; i < md; i++) {  
1096
  while (0 != (hp = (pHMgr[i])->walk_hashtable(col, hp))) {
1136
  while (0 != (hp = (pHMgr[i])->walk_hashtable(col, hp))) {
1097
    if ((hp->astr) && (pAMgr) && 
1137
    if ((hp->astr) && (pAMgr) && 
1098
       (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) ||
1138
       (TESTAFF(hp->astr, forbiddenword, hp->alen) ||
1099
          TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
1139
          TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
1100
          TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) ||
1140
          TESTAFF(hp->astr, nosuggest, hp->alen) ||
1101
          TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue;
1141
          TESTAFF(hp->astr, nongramsuggest, hp->alen) ||
1142
          TESTAFF(hp->astr, onlyincompound, hp->alen))) continue;
1102
1143
1103
    sc = ngram(3, word, HENTRY_WORD(hp), NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
1144
    sc = ngram(3, word, HENTRY_WORD(hp), NGRAM_LONGER_WORSE + low) +
1104
	leftcommonsubstring(word, HENTRY_WORD(hp));
1145
	leftcommonsubstring(word, HENTRY_WORD(hp));
1105
1146
1106
    // check special pronounciation
1147
    // check special pronounciation
1107
    if ((hp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) {
1148
    if ((hp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) {
1108
	int sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
1149
	int sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE + low) +
1109
	leftcommonsubstring(word, f);
1150
		+ leftcommonsubstring(word, f);
1110
	if (sc2 > sc) sc = sc2;
1151
	if (sc2 > sc) sc = sc2;
1111
    }
1152
    }
1112
    
1153
    
1154
    scphon = -20000;
1113
    if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
1155
    if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
1114
	char target2[MAXSWUTF8L];
1156
      char target2[MAXSWUTF8L];
1157
      if (utf8) {
1158
        w_char _w[MAXSWL];
1159
        int _wl = u8_u16(_w, MAXSWL, HENTRY_WORD(hp));
1160
        mkallcap_utf(_w, _wl, langnum);
1161
        u16_u8(candidate, MAXSWUTF8L, _w, _wl);
1162
      } else {
1115
        strcpy(candidate, HENTRY_WORD(hp));
1163
        strcpy(candidate, HENTRY_WORD(hp));
1116
        mkallcap(candidate, csconv);
1164
        mkallcap(candidate, csconv);
1117
        phonet(candidate, target2, -1, *ph);
1165
      }
1118
        scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE);
1166
      phonet(candidate, target2, -1, *ph);
1167
      scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE);
1119
    }
1168
    }
1120
1169
1121
    if (sc > scores[lp]) {
1170
    if (sc > scores[lp]) {
1122
      scores[lp] = sc;  
1171
      scores[lp] = sc;  
1123
      roots[lp] = hp;
1172
      roots[lp] = hp;
1124
      lval = sc;
1173
      lval = sc;
1125
      for (j=0; j < MAX_ROOTS; j++)
1174
      for (j=0; j < MAX_ROOTS; j++)
1126
        if (scores[j] < lval) {
1175
        if (scores[j] < lval) {
1127
          lp = j;
1176
          lp = j;
1128
          lval = scores[j];
1177
          lval = scores[j];
1129
        }
1178
        }
1130
    }
1179
    }
1131
1180
1181
1132
    if (scphon > scoresphon[lpphon]) {
1182
    if (scphon > scoresphon[lpphon]) {
1133
      scoresphon[lpphon] = scphon;
1183
      scoresphon[lpphon] = scphon;
1134
      rootsphon[lpphon] = HENTRY_WORD(hp);
1184
      rootsphon[lpphon] = HENTRY_WORD(hp);
1135
      lval = scphon;
1185
      lval = scphon;
1136
      for (j=0; j < MAX_ROOTS; j++)
1186
      for (j=0; j < MAX_ROOTS; j++)
1137
        if (scoresphon[j] < lval) {
1187
        if (scoresphon[j] < lval) {
1138
          lpphon = j;
1188
          lpphon = j;
1139
          lval = scoresphon[j];
1189
          lval = scoresphon[j];
 Lines 1144-1170   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1144
  // find minimum threshold for a passable suggestion
1194
  // find minimum threshold for a passable suggestion
1145
  // mangle original word three differnt ways
1195
  // mangle original word three differnt ways
1146
  // and score them to generate a minimum acceptable score
1196
  // and score them to generate a minimum acceptable score
1147
  int thresh = 0;
1197
  int thresh = 0;
1148
  for (int sp = 1; sp < 4; sp++) {
1198
  for (int sp = 1; sp < 4; sp++) {
1149
     if (utf8) {
1199
     if (utf8) {
1150
       for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*';
1200
       for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*';
1151
       u16_u8(mw, MAXSWUTF8L, u8, n);
1201
       u16_u8(mw, MAXSWUTF8L, u8, n);
1152
       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
1202
       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + low);
1153
     } else {
1203
     } else {
1154
       strcpy(mw, word);
1204
       strcpy(mw, word);
1155
       for (int k=sp; k < n; k+=4) *(mw + k) = '*';
1205
       for (int k=sp; k < n; k+=4) *(mw + k) = '*';
1156
       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
1206
       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + low);
1157
     }
1207
     }
1158
  }
1208
  }
1159
  thresh = thresh / 3;
1209
  thresh = thresh / 3;
1160
  thresh--;
1210
  thresh--;
1161
1211
1162
  // now expand affixes on each of these root words and
1212
 // now expand affixes on each of these root words and
1163
  // and use length adjusted ngram scores to select
1213
  // and use length adjusted ngram scores to select
1164
  // possible suggestions
1214
  // possible suggestions
1165
  char * guess[MAX_GUESS];
1215
  char * guess[MAX_GUESS];
1166
  char * guessorig[MAX_GUESS];
1216
  char * guessorig[MAX_GUESS];
1167
  int gscore[MAX_GUESS];
1217
  int gscore[MAX_GUESS];
1168
  for(i=0;i<MAX_GUESS;i++) {
1218
  for(i=0;i<MAX_GUESS;i++) {
1169
     guess[i] = NULL;
1219
     guess[i] = NULL;
1170
     guessorig[i] = NULL;
1220
     guessorig[i] = NULL;
 Lines 1183-1202   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1183
  for (i = 0; i < MAX_ROOTS; i++) {
1233
  for (i = 0; i < MAX_ROOTS; i++) {
1184
      if (roots[i]) {
1234
      if (roots[i]) {
1185
        struct hentry * rp = roots[i];
1235
        struct hentry * rp = roots[i];
1186
        int nw = pAMgr->expand_rootword(glst, MAX_WORDS, HENTRY_WORD(rp), rp->blen,
1236
        int nw = pAMgr->expand_rootword(glst, MAX_WORDS, HENTRY_WORD(rp), rp->blen,
1187
            	    rp->astr, rp->alen, word, nc, 
1237
            	    rp->astr, rp->alen, word, nc, 
1188
                    ((rp->var & H_OPT_PHON) ? copy_field(f, HENTRY_DATA(rp), MORPH_PHON) : NULL));
1238
                    ((rp->var & H_OPT_PHON) ? copy_field(f, HENTRY_DATA(rp), MORPH_PHON) : NULL));
1189
1239
1190
        for (int k = 0; k < nw ; k++) {
1240
        for (int k = 0; k < nw ; k++) {
1191
           sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) +
1241
           sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + low) +
1192
               leftcommonsubstring(word, glst[k].word);
1242
               leftcommonsubstring(word, glst[k].word);
1193
1243
1194
           if ((sc > thresh)) {
1244
           if (sc > thresh) {
1195
              if (sc > gscore[lp]) {
1245
              if (sc > gscore[lp]) {
1196
                 if (guess[lp]) {
1246
                 if (guess[lp]) {
1197
                    free (guess[lp]);
1247
                    free (guess[lp]);
1198
                    if (guessorig[lp]) {
1248
                    if (guessorig[lp]) {
1199
                	free(guessorig[lp]);
1249
                	free(guessorig[lp]);
1200
                	guessorig[lp] = NULL;
1250
                	guessorig[lp] = NULL;
1201
            	    }
1251
            	    }
1202
                 }
1252
                 }
 Lines 1209-1225   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1209
                       lp = j;
1259
                       lp = j;
1210
                       lval = gscore[j];
1260
                       lval = gscore[j];
1211
                    }
1261
                    }
1212
              } else { 
1262
              } else { 
1213
                free(glst[k].word);
1263
                free(glst[k].word);
1214
                if (glst[k].orig) free(glst[k].orig);
1264
                if (glst[k].orig) free(glst[k].orig);
1215
              }
1265
              }
1216
           } else {
1266
           } else {
1217
        	free(glst[k].word);
1267
                free(glst[k].word);
1218
                if (glst[k].orig) free(glst[k].orig);
1268
                if (glst[k].orig) free(glst[k].orig);
1219
           }
1269
           }
1220
        }
1270
        }
1221
      }
1271
      }
1222
  }
1272
  }
1223
  free(glst);
1273
  free(glst);
1224
1274
1225
  // now we are done generating guesses
1275
  // now we are done generating guesses
 Lines 1227-1277   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1227
  
1277
  
1228
  
1278
  
1229
  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
1279
  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
1230
  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
1280
  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
1231
1281
1232
  // weight suggestions with a similarity index, based on
1282
  // weight suggestions with a similarity index, based on
1233
  // the longest common subsequent algorithm and resort
1283
  // the longest common subsequent algorithm and resort
1234
1284
1235
  int is_swap;
1285
  int is_swap = 0;
1286
  int re = 0;
1287
  double fact = 1.0;
1288
  if (pAMgr) {
1289
	int maxd = pAMgr->get_maxdiff();
1290
	if (maxd >= 0) fact = (10.0 - maxd)/5.0;
1291
  }
1292
1236
  for (i=0; i < MAX_GUESS; i++) {
1293
  for (i=0; i < MAX_GUESS; i++) {
1237
      if (guess[i]) {
1294
      if (guess[i]) {
1238
        // lowering guess[i]
1295
        // lowering guess[i]
1239
        char gl[MAXSWUTF8L];
1296
        char gl[MAXSWUTF8L];
1240
        int len;
1297
        int len;
1241
        if (utf8) {
1298
        if (utf8) {
1242
          w_char _w[MAXSWL];
1299
          w_char _w[MAXSWL];
1243
          len = u8_u16(_w, MAXSWL, guess[i]);
1300
          len = u8_u16(_w, MAXSWL, guess[i]);
1244
          mkallsmall_utf(_w, len, langnum);
1301
          mkallsmall_utf(_w, len, langnum);
1245
          u16_u8(gl, MAXSWUTF8L, _w, len);
1302
          u16_u8(gl, MAXSWUTF8L, _w, len);
1246
        } else {
1303
        } else {
1247
          strcpy(gl, guess[i]);
1304
          strcpy(gl, guess[i]);
1248
          mkallsmall(gl, csconv);
1305
          if (!nonbmp) mkallsmall(gl, csconv);
1249
          len = strlen(guess[i]);
1306
          len = strlen(guess[i]);
1250
        }
1307
        }
1251
1308
1252
        int _lcs = lcslen(word, gl);
1309
        int _lcs = lcslen(word, gl);
1253
1310
1254
        // same characters with different casing
1311
        // same characters with different casing
1255
        if ((n == len) && (n == _lcs)) {
1312
        if ((n == len) && (n == _lcs)) {
1256
            gscore[i] += 2000;
1313
            gscore[i] += 2000;
1257
            break;
1314
            break;
1258
        }
1315
        }
1259
        
1316
        // using 2-gram instead of 3, and other weightening
1260
        // heuristic weigthing of ngram scores
1317
        gscore[i] =
1261
        gscore[i] +=
1262
          // length of longest common subsequent minus length difference
1318
          // length of longest common subsequent minus length difference
1263
          2 * _lcs - abs((int) (n - len)) +
1319
          2 * _lcs - abs((int) (n - len)) +
1264
          // weight length of the left common substring
1320
          // weight length of the left common substring
1265
          leftcommonsubstring(word, gl) +
1321
          leftcommonsubstring(word, gl) +
1266
          // weight equal character positions
1322
          // weight equal character positions
1267
          ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) +
1323
          (!nonbmp && commoncharacterpositions(word, gl, &is_swap) ? 1: 0) +
1268
          // swap character (not neighboring)
1324
          // swap character (not neighboring)
1269
          ((is_swap) ? 1000 : 0);
1325
          ((is_swap) ? 10 : 0) +
1326
          // ngram
1327
          ngram(4, word, gl, NGRAM_ANY_MISMATCH + low) +
1328
          // weighted ngrams
1329
          (re = ngram(2, word, gl, NGRAM_ANY_MISMATCH + low + NGRAM_WEIGHTED)) +
1330
          (re += ngram(2, gl, word, NGRAM_ANY_MISMATCH + low + NGRAM_WEIGHTED)) +
1331
          // different limit for dictionaries with PHONE rules
1332
          (ph ? (re < len * fact ? -1000 : 0) : (re < (n + len)*fact? -1000 : 0));
1270
      }
1333
      }
1271
  }
1334
  }
1272
1335
1273
  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
1336
  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
1274
1337
1275
// phonetic version
1338
// phonetic version
1276
  if (ph) for (i=0; i < MAX_ROOTS; i++) {
1339
  if (ph) for (i=0; i < MAX_ROOTS; i++) {
1277
      if (rootsphon[i]) {
1340
      if (rootsphon[i]) {
 Lines 1280-1296   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1280
        int len;
1343
        int len;
1281
        if (utf8) {
1344
        if (utf8) {
1282
          w_char _w[MAXSWL];
1345
          w_char _w[MAXSWL];
1283
          len = u8_u16(_w, MAXSWL, rootsphon[i]);
1346
          len = u8_u16(_w, MAXSWL, rootsphon[i]);
1284
          mkallsmall_utf(_w, len, langnum);
1347
          mkallsmall_utf(_w, len, langnum);
1285
          u16_u8(gl, MAXSWUTF8L, _w, len);
1348
          u16_u8(gl, MAXSWUTF8L, _w, len);
1286
        } else {
1349
        } else {
1287
          strcpy(gl, rootsphon[i]);
1350
          strcpy(gl, rootsphon[i]);
1288
          mkallsmall(gl, csconv);
1351
          if (!nonbmp) mkallsmall(gl, csconv);
1289
          len = strlen(rootsphon[i]);
1352
          len = strlen(rootsphon[i]);
1290
        }
1353
        }
1291
1354
1292
        // heuristic weigthing of ngram scores
1355
        // heuristic weigthing of ngram scores
1293
        scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) +
1356
        scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) +
1294
          // weight length of the left common substring
1357
          // weight length of the left common substring
1295
          leftcommonsubstring(word, gl);
1358
          leftcommonsubstring(word, gl);
1296
      }
1359
      }
 Lines 1302-1318   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1302
  int oldns = ns;
1365
  int oldns = ns;
1303
1366
1304
  int same = 0;
1367
  int same = 0;
1305
  for (i=0; i < MAX_GUESS; i++) {
1368
  for (i=0; i < MAX_GUESS; i++) {
1306
    if (guess[i]) {
1369
    if (guess[i]) {
1307
      if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) {
1370
      if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) {
1308
        int unique = 1;
1371
        int unique = 1;
1309
        // leave only excellent suggestions, if exists
1372
        // leave only excellent suggestions, if exists
1310
        if (gscore[i] > 1000) same = 1;
1373
        if (gscore[i] > 1000) same = 1; else if (gscore[i] < -100) {
1374
            same = 1;
1375
	    // keep the best ngram suggestions, unless in ONLYMAXDIFF mode
1376
            if (ns > oldns || (pAMgr && pAMgr->get_onlymaxdiff())) {
1377
    	        free(guess[i]);
1378
    	        if (guessorig[i]) free(guessorig[i]);
1379
                continue;
1380
            }
1381
        }
1311
        for (j = 0; j < ns; j++) {
1382
        for (j = 0; j < ns; j++) {
1312
          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
1383
          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
1313
          if ((!guessorig[i] && strstr(guess[i], wlst[j])) ||
1384
          if ((!guessorig[i] && strstr(guess[i], wlst[j])) ||
1314
	     (guessorig[i] && strstr(guessorig[i], wlst[j])) ||
1385
	     (guessorig[i] && strstr(guessorig[i], wlst[j])) ||
1315
            // check forbidden words
1386
            // check forbidden words
1316
            !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0;
1387
            !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0;
1317
        }
1388
        }
1318
        if (unique) {
1389
        if (unique) {
 Lines 1331-1347   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1331
      }
1402
      }
1332
    }
1403
    }
1333
  }
1404
  }
1334
1405
1335
  oldns = ns;
1406
  oldns = ns;
1336
  if (ph) for (i=0; i < MAX_ROOTS; i++) {
1407
  if (ph) for (i=0; i < MAX_ROOTS; i++) {
1337
    if (rootsphon[i]) {
1408
    if (rootsphon[i]) {
1338
      if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) {
1409
      if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) {
1339
        int unique = 1;
1410
	int unique = 1;
1340
        for (j = 0; j < ns; j++) {
1411
        for (j = 0; j < ns; j++) {
1341
          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
1412
          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
1342
          if (strstr(rootsphon[i], wlst[j]) || 
1413
          if (strstr(rootsphon[i], wlst[j]) || 
1343
            // check forbidden words
1414
            // check forbidden words
1344
            !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0;
1415
            !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0;
1345
        }
1416
        }
1346
        if (unique) {
1417
        if (unique) {
1347
            wlst[ns++] = mystrdup(rootsphon[i]);
1418
            wlst[ns++] = mystrdup(rootsphon[i]);
 Lines 1360-1391   int SuggestMgr::ngsuggest(char** wlst, c Link Here 
1360
// needs to check both root words and words with affixes
1431
// needs to check both root words and words with affixes
1361
1432
1362
// obsolote MySpell-HU modifications:
1433
// obsolote MySpell-HU modifications:
1363
// return value 2 and 3 marks compounding with hyphen (-)
1434
// return value 2 and 3 marks compounding with hyphen (-)
1364
// `3' marks roots without suffix
1435
// `3' marks roots without suffix
1365
int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit)
1436
int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit)
1366
{
1437
{
1367
  struct hentry * rv=NULL;
1438
  struct hentry * rv=NULL;
1439
  struct hentry * rv2=NULL;
1368
  int nosuffix = 0;
1440
  int nosuffix = 0;
1369
1441
1370
  // check time limit
1442
  // check time limit
1371
  if (timer) {
1443
  if (timer) {
1372
    (*timer)--;
1444
    (*timer)--;
1373
    if (!(*timer) && timelimit) {
1445
    if (!(*timer) && timelimit) {
1374
      if ((clock() - *timelimit) > TIMELIMIT) return 0;
1446
      if ((clock() - *timelimit) > TIMELIMIT) return 0;
1375
      *timer = MAXPLUSTIMER;
1447
      *timer = MAXPLUSTIMER;
1376
    }
1448
    }
1377
  }
1449
  }
1378
  
1450
  
1379
  if (pAMgr) { 
1451
  if (pAMgr) { 
1380
    if (cpdsuggest==1) {
1452
    if (cpdsuggest==1) {
1381
      if (pAMgr->get_compound()) {
1453
      if (pAMgr->get_compound()) {
1382
        rv = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 1); //EXT
1454
        rv = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 1, 0); //EXT
1383
        if (rv) return 3; // XXX obsolote categorisation
1455
        if (rv && (!(rv2 = pAMgr->lookup(word)) || !rv2->astr || 
1456
            !(TESTAFF(rv2->astr,pAMgr->get_forbiddenword(),rv2->alen) ||
1457
            TESTAFF(rv2->astr,pAMgr->get_nosuggest(),rv2->alen)))) return 3; // XXX obsolote categorisation + only ICONV needs affix flag check?
1384
        }
1458
        }
1385
        return 0;
1459
        return 0;
1386
    }
1460
    }
1387
1461
1388
    rv = pAMgr->lookup(word);
1462
    rv = pAMgr->lookup(word);
1389
1463
1390
    if (rv) {
1464
    if (rv) {
1391
        if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
1465
        if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
 Lines 1707-1782   char * SuggestMgr::suggest_gen(char ** d Link Here 
1707
1781
1708
// generate an n-gram score comparing s1 and s2
1782
// generate an n-gram score comparing s1 and s2
1709
int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt)
1783
int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt)
1710
{
1784
{
1711
  int nscore = 0;
1785
  int nscore = 0;
1712
  int ns;
1786
  int ns;
1713
  int l1;
1787
  int l1;
1714
  int l2;
1788
  int l2;
1789
  int test = 0;
1715
1790
1716
  if (utf8) {
1791
  if (utf8) {
1717
    w_char su1[MAXSWL];
1792
    w_char su1[MAXSWL];
1718
    w_char su2[MAXSWL];
1793
    w_char su2[MAXSWL];
1719
    l1 = u8_u16(su1, MAXSWL, s1);
1794
    l1 = u8_u16(su1, MAXSWL, s1);
1720
    l2 = u8_u16(su2, MAXSWL, s2);
1795
    l2 = u8_u16(su2, MAXSWL, s2);
1721
    if ((l2 <= 0) || (l1 == -1)) return 0;
1796
    if ((l2 <= 0) || (l1 == -1)) return 0;
1722
    // lowering dictionary word
1797
    // lowering dictionary word
1723
    if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum);
1798
    if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum);
1724
    for (int j = 1; j <= n; j++) {
1799
    for (int j = 1; j <= n; j++) {
1725
      ns = 0;
1800
      ns = 0;
1726
      for (int i = 0; i <= (l1-j); i++) {
1801
      for (int i = 0; i <= (l1-j); i++) {
1802
	int k = 0;
1727
        for (int l = 0; l <= (l2-j); l++) {
1803
        for (int l = 0; l <= (l2-j); l++) {
1728
            int k;
1804
            for (k = 0; k < j; k++) {
1729
            for (k = 0; (k < j); k++) {
1730
              w_char * c1 = su1 + i + k;
1805
              w_char * c1 = su1 + i + k;
1731
              w_char * c2 = su2 + l + k;
1806
              w_char * c2 = su2 + l + k;
1732
              if ((c1->l != c2->l) || (c1->h != c2->h)) break;
1807
              if ((c1->l != c2->l) || (c1->h != c2->h)) break;
1733
            }
1808
            }
1734
            if (k == j) {
1809
            if (k == j) {
1735
                ns++;
1810
		ns++;
1736
                break;
1811
                break;
1737
            }
1812
            } 
1738
        }
1813
	}
1814
	if (k != j && opt & NGRAM_WEIGHTED) {
1815
	  ns--;
1816
	  test++;
1817
	  if (i == 0 || i == l1-j) ns--; // side weight
1818
	}
1739
      }
1819
      }
1740
      nscore = nscore + ns;
1820
      nscore = nscore + ns;
1741
      if (ns < 2) break;
1821
      if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break;
1742
    }
1822
    }
1743
  } else {  
1823
  } else {  
1744
    l2 = strlen(s2);
1824
    l2 = strlen(s2);
1745
    if (l2 == 0) return 0;
1825
    if (l2 == 0) return 0;
1746
    l1 = strlen(s1);
1826
    l1 = strlen(s1);
1747
    char *t = mystrdup(s2);
1827
    char *t = mystrdup(s2);
1748
    if (opt & NGRAM_LOWERING) mkallsmall(t, csconv);
1828
    if (opt & NGRAM_LOWERING) mkallsmall(t, csconv);
1749
    for (int j = 1; j <= n; j++) {
1829
    for (int j = 1; j <= n; j++) {
1750
      ns = 0;
1830
      ns = 0;
1751
      for (int i = 0; i <= (l1-j); i++) {
1831
      for (int i = 0; i <= (l1-j); i++) {
1752
        char c = *(s1 + i + j);
1832
        char c = *(s1 + i + j);
1753
        *(s1 + i + j) = '\0';
1833
        *(s1 + i + j) = '\0';
1754
        if (strstr(t,(s1+i))) ns++;
1834
        if (strstr(t,(s1+i))) {
1835
	  ns++;
1836
	} else if (opt & NGRAM_WEIGHTED) {
1837
	  ns--;
1838
test++;
1839
	  if (i == 0 || i == l1-j) ns--; // side weight
1840
	}
1755
        *(s1 + i + j ) = c;
1841
        *(s1 + i + j ) = c;
1756
      }
1842
      }
1757
      nscore = nscore + ns;
1843
      nscore = nscore + ns;
1758
      if (ns < 2) break;
1844
      if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break;
1759
    }
1845
    }
1760
    free(t);
1846
    free(t);
1761
  }
1847
  }
1762
  
1848
  
1763
  ns = 0;
1849
  ns = 0;
1764
  if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
1850
  if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
1765
  if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2;
1851
  if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2;
1766
  ns = (nscore - ((ns > 0) ? ns : 0));
1852
  ns = (nscore - ((ns > 0) ? ns : 0));
1767
  return ns;
1853
  return ns;
1768
}
1854
}
1769
1855
1770
// length of the left common substring of s1 and (decapitalised) s2
1856
// length of the left common substring of s1 and (decapitalised) s2
1771
int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) {
1857
int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) {
1772
  if (utf8) {
1858
  if (utf8) {
1773
    w_char su1[MAXSWL];
1859
    w_char su1[MAXSWL];
1774
    w_char su2[MAXSWL];
1860
    w_char su2[MAXSWL];
1861
    su1[0].l = su2[0].l = su1[0].h = su2[0].h = 0;
1775
    // decapitalize dictionary word
1862
    // decapitalize dictionary word
1776
    if (complexprefixes) {
1863
    if (complexprefixes) {
1777
      int l1 = u8_u16(su1, MAXSWL, s1);
1864
      int l1 = u8_u16(su1, MAXSWL, s1);
1778
      int l2 = u8_u16(su2, MAXSWL, s2);
1865
      int l2 = u8_u16(su2, MAXSWL, s2);
1779
      if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1;
1866
      if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1;
1780
    } else {
1867
    } else {
1781
      int i;
1868
      int i;
1782
      u8_u16(su1, 1, s1);
1869
      u8_u16(su1, 1, s1);
(-)a/extensions/spellcheck/hunspell/src/suggestmgr.hxx (+3 lines)
Line     Link Here 
 Lines 60-84    Link Here 
60
60
61
#define MAXSWL 100
61
#define MAXSWL 100
62
#define MAXSWUTF8L (MAXSWL * 4)
62
#define MAXSWUTF8L (MAXSWL * 4)
63
#define MAX_ROOTS 100
63
#define MAX_ROOTS 100
64
#define MAX_WORDS 100
64
#define MAX_WORDS 100
65
#define MAX_GUESS 200
65
#define MAX_GUESS 200
66
#define MAXNGRAMSUGS 4
66
#define MAXNGRAMSUGS 4
67
#define MAXPHONSUGS 2
67
#define MAXPHONSUGS 2
68
#define MAXCOMPOUNDSUGS 3
68
69
69
// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function
70
// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function
70
#define TIMELIMIT (CLOCKS_PER_SEC >> 2)
71
#define TIMELIMIT (CLOCKS_PER_SEC >> 2)
71
#define MINTIMER 100
72
#define MINTIMER 100
72
#define MAXPLUSTIMER 100
73
#define MAXPLUSTIMER 100
73
74
74
#define NGRAM_LONGER_WORSE  (1 << 0)
75
#define NGRAM_LONGER_WORSE  (1 << 0)
75
#define NGRAM_ANY_MISMATCH  (1 << 1)
76
#define NGRAM_ANY_MISMATCH  (1 << 1)
76
#define NGRAM_LOWERING      (1 << 2)
77
#define NGRAM_LOWERING      (1 << 2)
78
#define NGRAM_WEIGHTED      (1 << 3)
77
79
78
#include "hunvisapi.h"
80
#include "hunvisapi.h"
79
81
80
#include "atypes.hxx"
82
#include "atypes.hxx"
81
#include "affixmgr.hxx"
83
#include "affixmgr.hxx"
82
#include "hashmgr.hxx"
84
#include "hashmgr.hxx"
83
#include "langnum.hxx"
85
#include "langnum.hxx"
84
#include <time.h>
86
#include <time.h>
 Lines 97-112   class LIBHUNSPELL_DLL_EXPORTED SuggestMg Link Here 
97
99
98
  AffixMgr*       pAMgr;
100
  AffixMgr*       pAMgr;
99
  int             maxSug;
101
  int             maxSug;
100
  struct cs_info * csconv;
102
  struct cs_info * csconv;
101
  int             utf8;
103
  int             utf8;
102
  int             langnum;
104
  int             langnum;
103
  int             nosplitsugs;
105
  int             nosplitsugs;
104
  int             maxngramsugs;
106
  int             maxngramsugs;
107
  int             maxcpdsugs;
105
  int             complexprefixes;
108
  int             complexprefixes;
106
109
107
110
108
public:
111
public:
109
  SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr);
112
  SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr);
110
  ~SuggestMgr();
113
  ~SuggestMgr();
111
114
112
  int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug);
115
  int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug);
(-)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