• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kspell2
 

kspell2

  • kspell2
  • plugins
  • ispell
tgood.cpp
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* enchant
3  * Copyright (C) 2003 Dom Lachowicz
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, Dom Lachowicz
21  * gives permission to link the code of this program with
22  * non-LGPL Spelling Provider libraries (eg: a MSFT Office
23  * spell checker backend) and distribute linked combinations including
24  * the two. You must obey the GNU Lesser General Public License in all
25  * respects for all of the code used other than said providers. If you modify
26  * this file, you may extend this exception to your version of the
27  * file, but you are not obligated to do so. If you do not wish to
28  * do so, delete this exception statement from your version.
29  */
30 
31 /*
32  * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  *
39  * 1. Redistributions of source code must retain the above copyright
40  * notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  * notice, this list of conditions and the following disclaimer in the
43  * documentation and/or other materials provided with the distribution.
44  * 3. All modifications to the source code must be clearly marked as
45  * such. Binary redistributions based on modified source code
46  * must be clearly marked as modified versions in the documentation
47  * and/or other materials provided with the distribution.
48  * 4. All advertising materials mentioning features or use of this software
49  * must display the following acknowledgment:
50  * This product includes software developed by Geoff Kuenning and
51  * other unpaid contributors.
52  * 5. The name of Geoff Kuenning may not be used to endorse or promote
53  * products derived from this software without specific prior
54  * written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59  * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66  * SUCH DAMAGE.
67  */
68 
69 /*
70  * Table-driven version of good.c.
71  *
72  * Geoff Kuenning, July 1987
73  */
74 
75 /*
76  * $Log$
77  * Revision 1.1 2004/01/31 16:44:12 zrusin
78  * ISpell plugin.
79  *
80  * Revision 1.4 2003/08/14 17:51:29 dom
81  * update license - exception clause should be Lesser GPL
82  *
83  * Revision 1.3 2003/07/28 20:40:28 dom
84  * fix up the license clause, further win32-registry proof some directory getting functions
85  *
86  * Revision 1.2 2003/07/16 22:52:56 dom
87  * LGPL + exception license
88  *
89  * Revision 1.1 2003/07/15 01:15:09 dom
90  * ispell enchant backend
91  *
92  * Revision 1.2 2003/01/29 05:50:12 hippietrail
93  *
94  * Fixed my mess in EncodingManager.
95  * Changed many C casts to C++ casts.
96  *
97  * Revision 1.1 2003/01/24 05:52:36 hippietrail
98  *
99  * Refactored ispell code. Old ispell global variables had been put into
100  * an allocated structure, a pointer to which was passed to many functions.
101  * I have now made all such functions and variables private members of the
102  * ISpellChecker class. It was C OO, now it's C++ OO.
103  *
104  * I've fixed the makefiles and tested compilation but am unable to test
105  * operation. Please back out my changes if they cause problems which
106  * are not obvious or easy to fix.
107  *
108  * Revision 1.6 2003/01/06 18:48:42 dom
109  * ispell cleanup, start of using new 'add' save features
110  *
111  * Revision 1.5 2002/09/19 05:31:20 hippietrail
112  *
113  * More Ispell cleanup. Conditional globals and DEREF macros are removed.
114  * K&R function declarations removed, converted to Doxygen style comments
115  * where possible. No code has been changed (I hope). Compiles for me but
116  * unable to test.
117  *
118  * Revision 1.4 2002/09/17 03:03:31 hippietrail
119  *
120  * After seeking permission on the developer list I've reformatted all the
121  * spelling source which seemed to have parts which used 2, 3, 4, and 8
122  * spaces for tabs. It should all look good with our standard 4-space
123  * tabs now.
124  * I've concentrated just on indentation in the actual code. More prettying
125  * could be done.
126  * * NO code changes were made *
127  *
128  * Revision 1.3 2002/09/13 17:20:14 mpritchett
129  * Fix more warnings for Linux build
130  *
131  * Revision 1.2 2001/05/12 16:05:42 thomasf
132  * Big pseudo changes to ispell to make it pass around a structure rather
133  * than rely on all sorts of gloabals willy nilly here and there. Also
134  * fixed our spelling class to work with accepting suggestions once more.
135  * This code is dirty, gross and ugly (not to mention still not supporting
136  * multiple hash sized just yet) but it works on my machine and will no
137  * doubt break other machines.
138  *
139  * Revision 1.1 2001/04/15 16:01:24 tomas_f
140  * moving to spell/xp
141  *
142  * Revision 1.7 1999/10/20 06:03:56 sterwill
143  * Changed C++-style comments to C-style comments in C code.
144  *
145  * Revision 1.6 1999/10/20 03:19:35 paul
146  * Hacked ispell code to ignore any characters that don't fit in the lookup tables loaded from the dictionary. It ain't pretty, but at least we don't crash there any more.
147  *
148  * Revision 1.5 1999/04/13 17:12:51 jeff
149  * Applied "Darren O. Benham" <gecko@benham.net> spell check changes.
150  * Fixed crash on Win32 with the new code.
151  *
152  * Revision 1.4 1998/12/29 14:55:33 eric
153  *
154  * I've doctored the ispell code pretty extensively here. It is now
155  * warning-free on Win32. It also *works* on Win32 now, since I
156  * replaced all the I/O calls with ANSI standard ones.
157  *
158  * Revision 1.4 1998/12/29 14:55:33 eric
159  *
160  * I've doctored the ispell code pretty extensively here. It is now
161  * warning-free on Win32. It also *works* on Win32 now, since I
162  * replaced all the I/O calls with ANSI standard ones.
163  *
164  * Revision 1.3 1998/12/28 23:11:30 eric
165  *
166  * modified spell code and integration to build on Windows.
167  * This is still a hack.
168  *
169  * Actually, it doesn't yet WORK on Windows. It just builds.
170  * SpellCheckInit is failing for some reason.
171  *
172  * Revision 1.2 1998/12/28 22:16:22 eric
173  *
174  * These changes begin to incorporate the spell checker into AbiWord. Most
175  * of this is a hack.
176  *
177  * 1. added other/spell to the -I list in config/abi_defs
178  * 2. replaced other/spell/Makefile with one which is more like
179  * our build system.
180  * 3. added other/spell to other/Makefile so that the build will now
181  * dive down and build the spell check library.
182  * 4. added the AbiSpell library to the Makefiles in wp/main
183  * 5. added a call to SpellCheckInit in wp/main/unix/UnixMain.cpp.
184  * This call is a HACK and should be replaced with something
185  * proper later.
186  * 6. added code to fv_View.cpp as follows:
187  * whenever you double-click on a word, the spell checker
188  * verifies that word and prints its status to stdout.
189  *
190  * Caveats:
191  * 1. This will break the Windows build. I'm going to work on fixing it
192  * now.
193  * 2. This only works if your dictionary is in /usr/lib/ispell/american.hash.
194  * The dictionary location is currently hard-coded. This will be
195  * fixed as well.
196  *
197  * Anyway, such as it is, it works.
198  *
199  * Revision 1.1 1998/12/28 18:04:43 davet
200  * Spell checker code stripped from ispell. At this point, there are
201  * two external routines... the Init routine, and a check-a-word routine
202  * which returns a boolean value, and takes a 16 bit char string.
203  * The code resembles the ispell code as much as possible still.
204  *
205  * Revision 1.32 1994/11/02 06:56:16 geoff
206  * Remove the anyword feature, which I've decided is a bad idea.
207  *
208  * Revision 1.31 1994/10/25 05:46:25 geoff
209  * Add support for the FF_ANYWORD (affix applies to all words, even if
210  * flag bit isn't set) flag option.
211  *
212  * Revision 1.30 1994/05/24 06:23:08 geoff
213  * Don't create a hit if "allhits" is clear and capitalization
214  * mismatches. This cures a bug where a word could be in the dictionary
215  * and yet not found.
216  *
217  * Revision 1.29 1994/05/17 06:44:21 geoff
218  * Add support for controlled compound formation and the COMPOUNDONLY
219  * option to affix flags.
220  *
221  * Revision 1.28 1994/01/25 07:12:13 geoff
222  * Get rid of all old RCS log lines in preparation for the 3.1 release.
223  *
224  */
225 
226 #include <ctype.h>
227 #include <stdlib.h>
228 #include <string.h>
229 
230 #include "ispell_checker.h"
231 
243 void ISpellChecker::chk_aff (ichar_t *word, ichar_t *ucword,
244  int len, int ignoreflagbits, int allhits, int pfxopts, int sfxopts)
245 {
246  ichar_t * cp; /* Pointer to char to index on */
247  struct flagptr * ind; /* Flag index table to test */
248 
249  pfx_list_chk (word, ucword, len, pfxopts, sfxopts, &m_pflagindex[0],
250  ignoreflagbits, allhits);
251  cp = ucword;
252  /* HACK: bail on unrecognized chars */
253  if (*cp >= (SET_SIZE + MAXSTRINGCHARS))
254  return;
255  ind = &m_pflagindex[*cp++];
256  while (ind->numents == 0 && ind->pu.fp != NULL)
257  {
258  if (*cp == 0)
259  return;
260  if (ind->pu.fp[0].numents)
261  {
262  pfx_list_chk (word, ucword, len, pfxopts, sfxopts, &ind->pu.fp[0],
263  ignoreflagbits, allhits);
264  if (m_numhits && !allhits && /* !cflag && */ !ignoreflagbits)
265  return;
266  }
267  /* HACK: bail on unrecognized chars */
268  if (*cp >= (SET_SIZE + MAXSTRINGCHARS))
269  return;
270  ind = &ind->pu.fp[*cp++];
271  }
272  pfx_list_chk (word, ucword, len, pfxopts, sfxopts, ind, ignoreflagbits,
273  allhits);
274  if (m_numhits && !allhits && /* !cflag &&*/ !ignoreflagbits)
275  return;
276  chk_suf (word, ucword, len, sfxopts, static_cast<struct flagent *>(NULL),
277  ignoreflagbits, allhits);
278 }
279 
292 void ISpellChecker::pfx_list_chk (ichar_t *word, ichar_t *ucword, int len, int optflags,
293  int sfxopts, struct flagptr * ind, int ignoreflagbits, int allhits)
294 {
295  int cond; /* Condition number */
296  ichar_t * cp; /* Pointer into end of ucword */
297  struct dent * dent; /* Dictionary entry we found */
298  int entcount; /* Number of entries to process */
299  struct flagent *
300  flent; /* Current table entry */
301  int preadd; /* Length added to tword2 as prefix */
302  int tlen; /* Length of tword */
303  ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */
304  ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */
305 
306  for (flent = ind->pu.ent, entcount = ind->numents;
307  entcount > 0;
308  flent++, entcount--)
309  {
310  /*
311  * If this is a compound-only affix, ignore it unless we're
312  * looking for that specific thing.
313  */
314  if ((flent->flagflags & FF_COMPOUNDONLY) != 0
315  && (optflags & FF_COMPOUNDONLY) == 0)
316  continue;
317 
318  /*
319  * See if the prefix matches.
320  */
321  tlen = len - flent->affl;
322  if (tlen > 0
323  && (flent->affl == 0
324  || icharncmp (flent->affix, ucword, flent->affl) == 0)
325  && tlen + flent->stripl >= flent->numconds)
326  {
327  /*
328  * The prefix matches. Remove it, replace it by the "strip"
329  * string (if any), and check the original conditions.
330  */
331  if (flent->stripl)
332  icharcpy (tword, flent->strip);
333  icharcpy (tword + flent->stripl, ucword + flent->affl);
334  cp = tword;
335  for (cond = 0; cond < flent->numconds; cond++)
336  {
337  if ((flent->conds[*cp++] & (1 << cond)) == 0)
338  break;
339  }
340  if (cond >= flent->numconds)
341  {
342  /*
343  * The conditions match. See if the word is in the
344  * dictionary.
345  */
346  tlen += flent->stripl;
347 
348  if (ignoreflagbits)
349  {
350  if ((dent = ispell_lookup (tword, 1)) != NULL)
351  {
352  cp = tword2;
353  if (flent->affl)
354  {
355  icharcpy (cp, flent->affix);
356  cp += flent->affl;
357  *cp++ = '+';
358  }
359  preadd = cp - tword2;
360  icharcpy (cp, tword);
361  cp += tlen;
362  if (flent->stripl)
363  {
364  *cp++ = '-';
365  icharcpy (cp, flent->strip);
366  }
367  }
368  }
369  else if ((dent = ispell_lookup (tword, 1)) != NULL
370  && TSTMASKBIT (dent->mask, flent->flagbit))
371  {
372  if (m_numhits < MAX_HITS)
373  {
374  m_hits[m_numhits].dictent = dent;
375  m_hits[m_numhits].prefix = flent;
376  m_hits[m_numhits].suffix = NULL;
377  m_numhits++;
378  }
379  if (!allhits)
380  {
381 #ifndef NO_CAPITALIZATION_SUPPORT
382  if (cap_ok (word, &m_hits[0], len))
383  return;
384  m_numhits = 0;
385 #else /* NO_CAPITALIZATION_SUPPORT */
386  return;
387 #endif /* NO_CAPITALIZATION_SUPPORT */
388  }
389  }
390  /*
391  * Handle cross-products.
392  */
393  if (flent->flagflags & FF_CROSSPRODUCT)
394  chk_suf (word, tword, tlen, sfxopts | FF_CROSSPRODUCT,
395  flent, ignoreflagbits, allhits);
396  }
397  }
398  }
399 }
400 
412 void
413 ISpellChecker::chk_suf (ichar_t *word, ichar_t *ucword,
414  int len, int optflags, struct flagent *pfxent,
415  int ignoreflagbits, int allhits)
416 {
417  ichar_t * cp; /* Pointer to char to index on */
418  struct flagptr * ind; /* Flag index table to test */
419 
420  suf_list_chk (word, ucword, len, &m_sflagindex[0], optflags, pfxent,
421  ignoreflagbits, allhits);
422  cp = ucword + len - 1;
423  /* HACK: bail on unrecognized chars */
424  if (*cp >= (SET_SIZE + MAXSTRINGCHARS))
425  return;
426  ind = &m_sflagindex[*cp];
427  while (ind->numents == 0 && ind->pu.fp != NULL)
428  {
429  if (cp == ucword)
430  return;
431  if (ind->pu.fp[0].numents)
432  {
433  suf_list_chk (word, ucword, len, &ind->pu.fp[0],
434  optflags, pfxent, ignoreflagbits, allhits);
435  if (m_numhits != 0 && !allhits && /* !cflag && */ !ignoreflagbits)
436  return;
437  }
438  /* HACK: bail on unrecognized chars */
439  if (*(cp-1) >= (SET_SIZE + MAXSTRINGCHARS))
440  return;
441  ind = &ind->pu.fp[*--cp];
442  }
443  suf_list_chk (word, ucword, len, ind, optflags, pfxent,
444  ignoreflagbits, allhits);
445 }
446 
457 void ISpellChecker::suf_list_chk (ichar_t *word, ichar_t *ucword,
458  int len, struct flagptr *ind, int optflags,
459  struct flagent *pfxent, int ignoreflagbits, int allhits)
460 {
461  ichar_t * cp; /* Pointer into end of ucword */
462  int cond; /* Condition number */
463  struct dent * dent; /* Dictionary entry we found */
464  int entcount; /* Number of entries to process */
465  struct flagent *
466  flent; /* Current table entry */
467  int preadd; /* Length added to tword2 as prefix */
468  int tlen; /* Length of tword */
469  ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */
470  ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */
471 
472  icharcpy (tword, ucword);
473  for (flent = ind->pu.ent, entcount = ind->numents;
474  entcount > 0;
475  flent++, entcount--)
476  {
477  if ((optflags & FF_CROSSPRODUCT) != 0
478  && (flent->flagflags & FF_CROSSPRODUCT) == 0)
479  continue;
480  /*
481  * If this is a compound-only affix, ignore it unless we're
482  * looking for that specific thing.
483  */
484  if ((flent->flagflags & FF_COMPOUNDONLY) != 0
485  && (optflags & FF_COMPOUNDONLY) == 0)
486  continue;
487 
488  /*
489  * See if the suffix matches.
490  */
491  tlen = len - flent->affl;
492  if (tlen > 0
493  && (flent->affl == 0
494  || icharcmp (flent->affix, ucword + tlen) == 0)
495  && tlen + flent->stripl >= flent->numconds)
496  {
497  /*
498  * The suffix matches. Remove it, replace it by the "strip"
499  * string (if any), and check the original conditions.
500  */
501  icharcpy (tword, ucword);
502  cp = tword + tlen;
503  if (flent->stripl)
504  {
505  icharcpy (cp, flent->strip);
506  tlen += flent->stripl;
507  cp = tword + tlen;
508  }
509  else
510  *cp = '\0';
511  for (cond = flent->numconds; --cond >= 0; )
512  {
513  if ((flent->conds[*--cp] & (1 << cond)) == 0)
514  break;
515  }
516  if (cond < 0)
517  {
518  /*
519  * The conditions match. See if the word is in the
520  * dictionary.
521  */
522  if (ignoreflagbits)
523  {
524  if ((dent = ispell_lookup (tword, 1)) != NULL)
525  {
526  cp = tword2;
527  if ((optflags & FF_CROSSPRODUCT)
528  && pfxent->affl != 0)
529  {
530  icharcpy (cp, pfxent->affix);
531  cp += pfxent->affl;
532  *cp++ = '+';
533  }
534  preadd = cp - tword2;
535  icharcpy (cp, tword);
536  cp += tlen;
537  if ((optflags & FF_CROSSPRODUCT)
538  && pfxent->stripl != 0)
539  {
540  *cp++ = '-';
541  icharcpy (cp, pfxent->strip);
542  cp += pfxent->stripl;
543  }
544  if (flent->stripl)
545  {
546  *cp++ = '-';
547  icharcpy (cp, flent->strip);
548  cp += flent->stripl;
549  }
550  if (flent->affl)
551  {
552  *cp++ = '+';
553  icharcpy (cp, flent->affix);
554  cp += flent->affl;
555  }
556  }
557  }
558  else if ((dent = ispell_lookup (tword, 1)) != NULL
559  && TSTMASKBIT (dent->mask, flent->flagbit)
560  && ((optflags & FF_CROSSPRODUCT) == 0
561  || TSTMASKBIT (dent->mask, pfxent->flagbit)))
562  {
563  if (m_numhits < MAX_HITS)
564  {
565  m_hits[m_numhits].dictent = dent;
566  m_hits[m_numhits].prefix = pfxent;
567  m_hits[m_numhits].suffix = flent;
568  m_numhits++;
569  }
570  if (!allhits)
571  {
572 #ifndef NO_CAPITALIZATION_SUPPORT
573  if (cap_ok (word, &m_hits[0], len))
574  return;
575  m_numhits = 0;
576 #else /* NO_CAPITALIZATION_SUPPORT */
577  return;
578 #endif /* NO_CAPITALIZATION_SUPPORT */
579  }
580  }
581  }
582  }
583  }
584 }
585 
597 int ISpellChecker::expand_pre (char *croot, ichar_t *rootword, MASKTYPE mask[],
598  int option, char *extra)
599 {
600  int entcount; /* No. of entries to process */
601  int explength; /* Length of expansions */
602  struct flagent *
603  flent; /* Current table entry */
604 
605  for (flent = m_pflaglist, entcount = m_numpflags, explength = 0;
606  entcount > 0;
607  flent++, entcount--)
608  {
609  if (TSTMASKBIT (mask, flent->flagbit))
610  explength +=
611  pr_pre_expansion (croot, rootword, flent, mask, option, extra);
612  }
613  return explength;
614 }
615 
628 int ISpellChecker::pr_pre_expansion ( char *croot, ichar_t *rootword,
629  struct flagent *flent, MASKTYPE mask[], int option,
630  char *extra)
631 {
632  int cond; /* Current condition number */
633  ichar_t * nextc; /* Next case choice */
634  int tlen; /* Length of tword */
635  ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Temp */
636 
637  tlen = icharlen (rootword);
638  if (flent->numconds > tlen)
639  return 0;
640  tlen -= flent->stripl;
641  if (tlen <= 0)
642  return 0;
643  tlen += flent->affl;
644  for (cond = 0, nextc = rootword; cond < flent->numconds; cond++)
645  {
646  if ((flent->conds[mytoupper (*nextc++)] & (1 << cond)) == 0)
647  return 0;
648  }
649  /*
650  * The conditions are satisfied. Copy the word, add the prefix,
651  * and make it the proper case. This code is carefully written
652  * to match that ins_cap and cap_ok. Note that the affix, as
653  * inserted, is uppercase.
654  *
655  * There is a tricky bit here: if the root is capitalized, we
656  * want a capitalized result. If the root is followcase, however,
657  * we want to duplicate the case of the first remaining letter
658  * of the root. In other words, "Loved/U" should generate "Unloved",
659  * but "LOved/U" should generate "UNLOved" and "lOved/U" should
660  * produce "unlOved".
661  */
662  if (flent->affl)
663  {
664  icharcpy (tword, flent->affix);
665  nextc = tword + flent->affl;
666  }
667  icharcpy (nextc, rootword + flent->stripl);
668  if (myupper (rootword[0]))
669  {
670  /* We must distinguish followcase from capitalized and all-upper */
671  for (nextc = rootword + 1; *nextc; nextc++)
672  {
673  if (!myupper (*nextc))
674  break;
675  }
676  if (*nextc)
677  {
678  /* It's a followcase or capitalized word. Figure out which. */
679  for ( ; *nextc; nextc++)
680  {
681  if (myupper (*nextc))
682  break;
683  }
684  if (*nextc)
685  {
686  /* It's followcase. */
687  if (!myupper (tword[flent->affl]))
688  forcelc (tword, flent->affl);
689  }
690  else
691  {
692  /* It's capitalized */
693  forcelc (tword + 1, tlen - 1);
694  }
695  }
696  }
697  else
698  {
699  /* Followcase or all-lower, we don't care which */
700  if (!myupper (*nextc))
701  forcelc (tword, flent->affl);
702  }
703  if (option == 3)
704  printf ("\n%s", croot);
705  if (option != 4)
706  printf (" %s%s", ichartosstr (tword, 1), extra);
707  if (flent->flagflags & FF_CROSSPRODUCT)
708  return tlen
709  + expand_suf (croot, tword, mask, FF_CROSSPRODUCT, option, extra);
710  else
711  return tlen;
712 }
713 
726 int ISpellChecker::expand_suf (char *croot, ichar_t *rootword, MASKTYPE mask[],
727  int optflags, int option, char *extra)
728 {
729  int entcount; /* No. of entries to process */
730  int explength; /* Length of expansions */
731  struct flagent *
732  flent; /* Current table entry */
733 
734  for (flent = m_sflaglist, entcount = m_numsflags, explength = 0;
735  entcount > 0;
736  flent++, entcount--)
737  {
738  if (TSTMASKBIT (mask, flent->flagbit))
739  {
740  if ((optflags & FF_CROSSPRODUCT) == 0
741  || (flent->flagflags & FF_CROSSPRODUCT))
742  explength +=
743  pr_suf_expansion (croot, rootword, flent, option, extra);
744  }
745  }
746  return explength;
747 }
748 
760 int ISpellChecker::pr_suf_expansion (char *croot, ichar_t *rootword,
761  struct flagent *flent, int option, char *extra)
762 {
763  int cond; /* Current condition number */
764  ichar_t * nextc; /* Next case choice */
765  int tlen; /* Length of tword */
766  ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Temp */
767 
768  tlen = icharlen (rootword);
769  cond = flent->numconds;
770  if (cond > tlen)
771  return 0;
772  if (tlen - flent->stripl <= 0)
773  return 0;
774  for (nextc = rootword + tlen; --cond >= 0; )
775  {
776  if ((flent->conds[mytoupper (*--nextc)] & (1 << cond)) == 0)
777  return 0;
778  }
779  /*
780  * The conditions are satisfied. Copy the word, add the suffix,
781  * and make it match the case of the last remaining character of the
782  * root. Again, this code carefully matches ins_cap and cap_ok.
783  */
784  icharcpy (tword, rootword);
785  nextc = tword + tlen - flent->stripl;
786  if (flent->affl)
787  {
788  icharcpy (nextc, flent->affix);
789  if (!myupper (nextc[-1]))
790  forcelc (nextc, flent->affl);
791  }
792  else
793  *nextc = 0;
794  if (option == 3)
795  printf ("\n%s", croot);
796  if (option != 4)
797  printf (" %s%s", ichartosstr (tword, 1), extra);
798  return tlen + flent->affl - flent->stripl;
799 }
800 
805 void ISpellChecker::forcelc (ichar_t *dst, int len) /* Force to lowercase */
806 {
807 
808  for ( ; --len >= 0; dst++)
809  *dst = mytolower (*dst);
810 }

kspell2

Skip menu "kspell2"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kspell2

Skip menu "kspell2"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kspell2 by doxygen 1.8.8
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |