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

tdespell2

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

tdespell2

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

tdespell2

Skip menu "tdespell2"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdespell2 by doxygen 1.9.4
This website is maintained by Timothy Pearson.