xref: /vim-8.2.3635/src/spell.c (revision f4cd3e80)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * spell.c: code for spell checking
12  *
13  * The spell checking mechanism uses a tree (aka trie).  Each node in the tree
14  * has a list of bytes that can appear (siblings).  For each byte there is a
15  * pointer to the node with the byte that follows in the word (child).
16  *
17  * A NUL byte is used where the word may end.  The bytes are sorted, so that
18  * binary searching can be used and the NUL bytes are at the start.  The
19  * number of possible bytes is stored before the list of bytes.
20  *
21  * The tree uses two arrays: "byts" stores the characters, "idxs" stores
22  * either the next index or flags.  The tree starts at index 0.  For example,
23  * to lookup "vi" this sequence is followed:
24  *	i = 0
25  *	len = byts[i]
26  *	n = where "v" appears in byts[i + 1] to byts[i + len]
27  *	i = idxs[n]
28  *	len = byts[i]
29  *	n = where "i" appears in byts[i + 1] to byts[i + len]
30  *	i = idxs[n]
31  *	len = byts[i]
32  *	find that byts[i + 1] is 0, idxs[i + 1] has flags for "vi".
33  *
34  * There are two word trees: one with case-folded words and one with words in
35  * original case.  The second one is only used for keep-case words and is
36  * usually small.
37  *
38  * There is one additional tree for when not all prefixes are applied when
39  * generating the .spl file.  This tree stores all the possible prefixes, as
40  * if they were words.  At each word (prefix) end the prefix nr is stored, the
41  * following word must support this prefix nr.  And the condition nr is
42  * stored, used to lookup the condition that the word must match with.
43  *
44  * Thanks to Olaf Seibert for providing an example implementation of this tree
45  * and the compression mechanism.
46  *
47  * Matching involves checking the caps type: Onecap ALLCAP KeepCap.
48  *
49  * Why doesn't Vim use aspell/ispell/myspell/etc.?
50  * See ":help develop-spell".
51  */
52 
53 /* Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word.
54  * Only use it for small word lists! */
55 #if 0
56 # define SPELL_PRINTTREE
57 #endif
58 
59 /*
60  * Use this to adjust the score after finding suggestions, based on the
61  * suggested word sounding like the bad word.  This is much faster than doing
62  * it for every possible suggestion.
63  * Disadvantage: When "the" is typed as "hte" it sounds different and goes
64  * down in the list.
65  * Used when 'spellsuggest' is set to "best".
66  */
67 #define RESCORE(word_score, sound_score) ((3 * word_score + sound_score) / 4)
68 
69 /*
70  * Vim spell file format: <HEADER>
71  *			  <SECTIONS>
72  *			  <LWORDTREE>
73  *			  <KWORDTREE>
74  *			  <PREFIXTREE>
75  *
76  * <HEADER>: <fileID> <versionnr>
77  *
78  * <fileID>     8 bytes    "VIMspell"
79  * <versionnr>  1 byte	    VIMSPELLVERSION
80  *
81  *
82  * Sections make it possible to add information to the .spl file without
83  * making it incompatible with previous versions.  There are two kinds of
84  * sections:
85  * 1. Not essential for correct spell checking.  E.g. for making suggestions.
86  *    These are skipped when not supported.
87  * 2. Optional information, but essential for spell checking when present.
88  *    E.g. conditions for affixes.  When this section is present but not
89  *    supported an error message is given.
90  *
91  * <SECTIONS>: <section> ... <sectionend>
92  *
93  * <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
94  *
95  * <sectionID>	  1 byte    number from 0 to 254 identifying the section
96  *
97  * <sectionflags> 1 byte    SNF_REQUIRED: this section is required for correct
98  *					    spell checking
99  *
100  * <sectionlen>   4 bytes   length of section contents, MSB first
101  *
102  * <sectionend>	  1 byte    SN_END
103  *
104  *
105  * sectionID == SN_REGION: <regionname> ...
106  * <regionname>	 2 bytes    Up to 8 region names: ca, au, etc.  Lower case.
107  *			    First <regionname> is region 1.
108  *
109  * sectionID == SN_CHARFLAGS: <charflagslen> <charflags>
110  *				<folcharslen> <folchars>
111  * <charflagslen> 1 byte    Number of bytes in <charflags> (should be 128).
112  * <charflags>  N bytes     List of flags (first one is for character 128):
113  *			    0x01  word character	CF_WORD
114  *			    0x02  upper-case character	CF_UPPER
115  * <folcharslen>  2 bytes   Number of bytes in <folchars>.
116  * <folchars>     N bytes   Folded characters, first one is for character 128.
117  *
118  * sectionID == SN_MIDWORD: <midword>
119  * <midword>     N bytes    Characters that are word characters only when used
120  *			    in the middle of a word.
121  *
122  * sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ...
123  * <prefcondcnt> 2 bytes    Number of <prefcond> items following.
124  * <prefcond> : <condlen> <condstr>
125  * <condlen>	1 byte	    Length of <condstr>.
126  * <condstr>	N bytes	    Condition for the prefix.
127  *
128  * sectionID == SN_REP: <repcount> <rep> ...
129  * <repcount>	 2 bytes    number of <rep> items, MSB first.
130  * <rep> : <repfromlen> <repfrom> <reptolen> <repto>
131  * <repfromlen>	 1 byte	    length of <repfrom>
132  * <repfrom>	 N bytes    "from" part of replacement
133  * <reptolen>	 1 byte	    length of <repto>
134  * <repto>	 N bytes    "to" part of replacement
135  *
136  * sectionID == SN_SAL: <salflags> <salcount> <sal> ...
137  * <salflags>	 1 byte	    flags for soundsalike conversion:
138  *			    SAL_F0LLOWUP
139  *			    SAL_COLLAPSE
140  *			    SAL_REM_ACCENTS
141  * <salcount>    2 bytes    number of <sal> items following
142  * <sal> : <salfromlen> <salfrom> <saltolen> <salto>
143  * <salfromlen>	 1 byte	    length of <salfrom>
144  * <salfrom>	 N bytes    "from" part of soundsalike
145  * <saltolen>	 1 byte	    length of <salto>
146  * <salto>	 N bytes    "to" part of soundsalike
147  *
148  * sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
149  * <sofofromlen> 2 bytes    length of <sofofrom>
150  * <sofofrom>	 N bytes    "from" part of soundfold
151  * <sofotolen>	 2 bytes    length of <sofoto>
152  * <sofoto>	 N bytes    "to" part of soundfold
153  *
154  * sectionID == SN_MAP: <mapstr>
155  * <mapstr>	 N bytes    String with sequences of similar characters,
156  *			    separated by slashes.
157  *
158  * sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compflags>
159  * <compmax>     1 byte	    Maximum nr of words in compound word.
160  * <compminlen>  1 byte	    Minimal word length for compounding.
161  * <compsylmax>  1 byte	    Maximum nr of syllables in compound word.
162  * <compflags>   N bytes    Flags from COMPOUNDFLAGS items, separated by
163  *			    slashes.
164  *
165  * sectionID == SN_NOBREAK: (empty, its presence is enough)
166  *
167  * sectionID == SN_SYLLABLE: <syllable>
168  * <syllable>    N bytes    String from SYLLABLE item.
169  *
170  * <LWORDTREE>: <wordtree>
171  *
172  * <KWORDTREE>: <wordtree>
173  *
174  * <PREFIXTREE>: <wordtree>
175  *
176  *
177  * <wordtree>: <nodecount> <nodedata> ...
178  *
179  * <nodecount>	4 bytes	    Number of nodes following.  MSB first.
180  *
181  * <nodedata>: <siblingcount> <sibling> ...
182  *
183  * <siblingcount> 1 byte    Number of siblings in this node.  The siblings
184  *			    follow in sorted order.
185  *
186  * <sibling>: <byte> [ <nodeidx> <xbyte>
187  *		      | <flags> [<flags2>] [<region>] [<affixID>]
188  *		      | [<pflags>] <affixID> <prefcondnr> ]
189  *
190  * <byte>	1 byte	    Byte value of the sibling.  Special cases:
191  *			    BY_NOFLAGS: End of word without flags and for all
192  *					regions.
193  *					For PREFIXTREE <affixID> and
194  *					<prefcondnr> follow.
195  *			    BY_FLAGS:   End of word, <flags> follow.
196  *					For PREFIXTREE <pflags>, <affixID>
197  *					and <prefcondnr> follow.
198  *			    BY_FLAGS2:  End of word, <flags> and <flags2>
199  *					follow.  Not used in PREFIXTREE.
200  *			    BY_INDEX:   Child of sibling is shared, <nodeidx>
201  *					and <xbyte> follow.
202  *
203  * <nodeidx>	3 bytes	    Index of child for this sibling, MSB first.
204  *
205  * <xbyte>	1 byte	    byte value of the sibling.
206  *
207  * <flags>	1 byte	    bitmask of:
208  *			    WF_ALLCAP	word must have only capitals
209  *			    WF_ONECAP   first char of word must be capital
210  *			    WF_KEEPCAP	keep-case word
211  *			    WF_FIXCAP   keep-case word, all caps not allowed
212  *			    WF_RARE	rare word
213  *			    WF_BANNED	bad word
214  *			    WF_REGION	<region> follows
215  *			    WF_AFX	<affixID> follows
216  *
217  * <flags2>	1 byte	    Bitmask of:
218  *			    WF_HAS_AFF >> 8   word includes affix
219  *			    WF_NEEDCOMP >> 8  word only valid in compound
220  *
221  * <pflags>	1 byte	    bitmask of:
222  *			    WFP_RARE	rare prefix
223  *			    WFP_NC	non-combining prefix
224  *			    WFP_UP	letter after prefix made upper case
225  *
226  * <region>	1 byte	    Bitmask for regions in which word is valid.  When
227  *			    omitted it's valid in all regions.
228  *			    Lowest bit is for region 1.
229  *
230  * <affixID>	1 byte	    ID of affix that can be used with this word.  In
231  *			    PREFIXTREE used for the required prefix ID.
232  *
233  * <prefcondnr>	2 bytes	    Prefix condition number, index in <prefcond> list
234  *			    from HEADER.
235  *
236  * All text characters are in 'encoding', but stored as single bytes.
237  */
238 
239 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
240 # include <io.h>	/* for lseek(), must be before vim.h */
241 #endif
242 
243 #include "vim.h"
244 
245 #if defined(FEAT_SYN_HL) || defined(PROTO)
246 
247 #ifdef HAVE_FCNTL_H
248 # include <fcntl.h>
249 #endif
250 
251 #define MAXWLEN 250		/* Assume max. word len is this many bytes.
252 				   Some places assume a word length fits in a
253 				   byte, thus it can't be above 255. */
254 
255 /* Type used for indexes in the word tree need to be at least 4 bytes.  If int
256  * is 8 bytes we could use something smaller, but what? */
257 #if SIZEOF_INT > 3
258 typedef int idx_T;
259 #else
260 typedef long idx_T;
261 #endif
262 
263 /* Flags used for a word.  Only the lowest byte can be used, the region byte
264  * comes above it. */
265 #define WF_REGION   0x01	/* region byte follows */
266 #define WF_ONECAP   0x02	/* word with one capital (or all capitals) */
267 #define WF_ALLCAP   0x04	/* word must be all capitals */
268 #define WF_RARE	    0x08	/* rare word */
269 #define WF_BANNED   0x10	/* bad word */
270 #define WF_AFX	    0x20	/* affix ID follows */
271 #define WF_FIXCAP   0x40	/* keep-case word, allcap not allowed */
272 #define WF_KEEPCAP  0x80	/* keep-case word */
273 
274 /* for <flags2>, shifted up one byte to be used in wn_flags */
275 #define WF_HAS_AFF  0x0100	/* word includes affix */
276 #define WF_NEEDCOMP 0x0200	/* word only valid in compound */
277 
278 #define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP)
279 
280 /* flags for <pflags> */
281 #define WFP_RARE    0x01	/* rare prefix */
282 #define WFP_NC	    0x02	/* prefix is not combining */
283 #define WFP_UP	    0x04	/* to-upper prefix */
284 
285 /* Flags for postponed prefixes.  Must be above affixID (one byte)
286  * and prefcondnr (two bytes). */
287 #define WF_RAREPFX  (WFP_RARE << 24)	/* in sl_pidxs: flag for rare
288 					 * postponed prefix */
289 #define WF_PFX_NC   (WFP_NC << 24)	/* in sl_pidxs: flag for non-combining
290 					 * postponed prefix */
291 #define WF_PFX_UP   (WFP_UP << 24)	/* in sl_pidxs: flag for to-upper
292 					 * postponed prefix */
293 
294 /* Special byte values for <byte>.  Some are only used in the tree for
295  * postponed prefixes, some only in the other trees.  This is a bit messy... */
296 #define BY_NOFLAGS	0	/* end of word without flags or region; for
297 				 * postponed prefix: no <pflags> */
298 #define BY_INDEX	1	/* child is shared, index follows */
299 #define BY_FLAGS	2	/* end of word, <flags> byte follows; for
300 				 * postponed prefix: <pflags> follows */
301 #define BY_FLAGS2	3	/* end of word, <flags> and <flags2> bytes
302 				 * follow; never used in prefix tree */
303 #define BY_SPECIAL  BY_FLAGS2	/* highest special byte value */
304 
305 /* Info from "REP" and "SAL" entries in ".aff" file used in si_rep, sl_rep,
306  * and si_sal.  Not for sl_sal!
307  * One replacement: from "ft_from" to "ft_to". */
308 typedef struct fromto_S
309 {
310     char_u	*ft_from;
311     char_u	*ft_to;
312 } fromto_T;
313 
314 /* Info from "SAL" entries in ".aff" file used in sl_sal.
315  * The info is split for quick processing by spell_soundfold().
316  * Note that "sm_oneof" and "sm_rules" point into sm_lead. */
317 typedef struct salitem_S
318 {
319     char_u	*sm_lead;	/* leading letters */
320     int		sm_leadlen;	/* length of "sm_lead" */
321     char_u	*sm_oneof;	/* letters from () or NULL */
322     char_u	*sm_rules;	/* rules like ^, $, priority */
323     char_u	*sm_to;		/* replacement. */
324 #ifdef FEAT_MBYTE
325     int		*sm_lead_w;	/* wide character copy of "sm_lead" */
326     int		*sm_oneof_w;	/* wide character copy of "sm_oneof" */
327     int		*sm_to_w;	/* wide character copy of "sm_to" */
328 #endif
329 } salitem_T;
330 
331 #ifdef FEAT_MBYTE
332 typedef int salfirst_T;
333 #else
334 typedef short salfirst_T;
335 #endif
336 
337 /* Values for SP_*ERROR are negative, positive values are used by
338  * read_cnt_string(). */
339 #define	SP_TRUNCERROR	-1	/* spell file truncated error */
340 #define	SP_FORMERROR	-2	/* format error in spell file */
341 #define SP_OTHERERROR	-3	/* other error while reading spell file */
342 
343 /*
344  * Structure used to store words and other info for one language, loaded from
345  * a .spl file.
346  * The main access is through the tree in "sl_fbyts/sl_fidxs", storing the
347  * case-folded words.  "sl_kbyts/sl_kidxs" is for keep-case words.
348  *
349  * The "byts" array stores the possible bytes in each tree node, preceded by
350  * the number of possible bytes, sorted on byte value:
351  *	<len> <byte1> <byte2> ...
352  * The "idxs" array stores the index of the child node corresponding to the
353  * byte in "byts".
354  * Exception: when the byte is zero, the word may end here and "idxs" holds
355  * the flags, region mask and affixID for the word.  There may be several
356  * zeros in sequence for alternative flag/region/affixID combinations.
357  */
358 typedef struct slang_S slang_T;
359 struct slang_S
360 {
361     slang_T	*sl_next;	/* next language */
362     char_u	*sl_name;	/* language name "en", "en.rare", "nl", etc. */
363     char_u	*sl_fname;	/* name of .spl file */
364     int		sl_add;		/* TRUE if it's a .add file. */
365 
366     char_u	*sl_fbyts;	/* case-folded word bytes */
367     idx_T	*sl_fidxs;	/* case-folded word indexes */
368     char_u	*sl_kbyts;	/* keep-case word bytes */
369     idx_T	*sl_kidxs;	/* keep-case word indexes */
370     char_u	*sl_pbyts;	/* prefix tree word bytes */
371     idx_T	*sl_pidxs;	/* prefix tree word indexes */
372 
373     char_u	sl_regions[17];	/* table with up to 8 region names plus NUL */
374 
375     char_u	*sl_midword;	/* MIDWORD string or NULL */
376 
377     int		sl_compmax;	/* COMPOUNDMAX (default: MAXWLEN) */
378     int		sl_compminlen;	/* COMPOUNDMIN (default: 0) */
379     int		sl_compsylmax;	/* COMPOUNDSYLMAX (default: MAXWLEN) */
380     regprog_T	*sl_compprog;	/* COMPOUNDFLAGS turned into a regexp progrm
381 				 * (NULL when no compounding) */
382     char_u	*sl_compstartflags; /* flags for first compound word */
383     char_u	*sl_compallflags; /* all flags for compound words */
384     char_u	sl_nobreak;	/* When TRUE: no spaces between words */
385     char_u	*sl_syllable;	/* SYLLABLE repeatable chars or NULL */
386     garray_T	sl_syl_items;	/* syllable items */
387 
388     int		sl_prefixcnt;	/* number of items in "sl_prefprog" */
389     regprog_T	**sl_prefprog;	/* table with regprogs for prefixes */
390 
391     garray_T	sl_rep;		/* list of fromto_T entries from REP lines */
392     short	sl_rep_first[256];  /* indexes where byte first appears, -1 if
393 				       there is none */
394     garray_T	sl_sal;		/* list of salitem_T entries from SAL lines */
395     salfirst_T	sl_sal_first[256];  /* indexes where byte first appears, -1 if
396 				       there is none */
397     int		sl_sofo;	/* SOFOFROM and SOFOTO instead of SAL items:
398 				 * "sl_sal_first" maps chars, when has_mbyte
399 				 * "sl_sal" is a list of wide char lists. */
400     int		sl_followup;	/* SAL followup */
401     int		sl_collapse;	/* SAL collapse_result */
402     int		sl_rem_accents;	/* SAL remove_accents */
403     int		sl_has_map;	/* TRUE if there is a MAP line */
404 #ifdef FEAT_MBYTE
405     hashtab_T	sl_map_hash;	/* MAP for multi-byte chars */
406     int		sl_map_array[256]; /* MAP for first 256 chars */
407 #else
408     char_u	sl_map_array[256]; /* MAP for first 256 chars */
409 #endif
410 };
411 
412 /* First language that is loaded, start of the linked list of loaded
413  * languages. */
414 static slang_T *first_lang = NULL;
415 
416 /* Flags used in .spl file for soundsalike flags. */
417 #define SAL_F0LLOWUP		1
418 #define SAL_COLLAPSE		2
419 #define SAL_REM_ACCENTS		4
420 
421 /*
422  * Structure used in "b_langp", filled from 'spelllang'.
423  */
424 typedef struct langp_S
425 {
426     slang_T	*lp_slang;	/* info for this language */
427     slang_T	*lp_sallang;	/* language used for sound folding or NULL */
428     slang_T	*lp_replang;	/* language used for REP items or NULL */
429     int		lp_region;	/* bitmask for region or REGION_ALL */
430 } langp_T;
431 
432 #define LANGP_ENTRY(ga, i)	(((langp_T *)(ga).ga_data) + (i))
433 
434 #define REGION_ALL 0xff		/* word valid in all regions */
435 
436 #define VIMSPELLMAGIC "VIMspell"  /* string at start of Vim spell file */
437 #define VIMSPELLMAGICL 8
438 #define VIMSPELLVERSION 50
439 
440 /* Section IDs.  Only renumber them when VIMSPELLVERSION changes! */
441 #define SN_REGION	0	/* <regionname> section */
442 #define SN_CHARFLAGS	1	/* charflags section */
443 #define SN_MIDWORD	2	/* <midword> section */
444 #define SN_PREFCOND	3	/* <prefcond> section */
445 #define SN_REP		4	/* REP items section */
446 #define SN_SAL		5	/* SAL items section */
447 #define SN_SOFO		6	/* soundfolding section */
448 #define SN_MAP		7	/* MAP items section */
449 #define SN_COMPOUND	8	/* compound words section */
450 #define SN_SYLLABLE	9	/* syllable section */
451 #define SN_NOBREAK	10	/* NOBREAK section */
452 #define SN_END		255	/* end of sections */
453 
454 #define SNF_REQUIRED	1	/* <sectionflags>: required section */
455 
456 /* Result values.  Lower number is accepted over higher one. */
457 #define SP_BANNED	-1
458 #define SP_OK		0
459 #define SP_RARE		1
460 #define SP_LOCAL	2
461 #define SP_BAD		3
462 
463 /* file used for "zG" and "zW" */
464 static char_u	*int_wordlist = NULL;
465 
466 /*
467  * Information used when looking for suggestions.
468  */
469 typedef struct suginfo_S
470 {
471     garray_T	su_ga;		    /* suggestions, contains "suggest_T" */
472     int		su_maxcount;	    /* max. number of suggestions displayed */
473     int		su_maxscore;	    /* maximum score for adding to su_ga */
474     garray_T	su_sga;		    /* like su_ga, sound-folded scoring */
475     char_u	*su_badptr;	    /* start of bad word in line */
476     int		su_badlen;	    /* length of detected bad word in line */
477     int		su_badflags;	    /* caps flags for bad word */
478     char_u	su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
479     char_u	su_fbadword[MAXWLEN]; /* su_badword case-folded */
480     char_u	su_sal_badword[MAXWLEN]; /* su_badword soundfolded */
481     slang_T	*su_slang_first;    /* slang_T used for su_sal_badword */
482     hashtab_T	su_banned;	    /* table with banned words */
483     slang_T	*su_sallang;	    /* default language for sound folding */
484 } suginfo_T;
485 
486 /* One word suggestion.  Used in "si_ga". */
487 typedef struct suggest_S
488 {
489     char_u	*st_word;	/* suggested word, allocated string */
490     int		st_orglen;	/* length of replaced text */
491     int		st_score;	/* lower is better */
492     int		st_altscore;	/* used when st_score compares equal */
493     int		st_salscore;	/* st_score is for soundalike */
494     int		st_had_bonus;	/* bonus already included in score */
495     slang_T	*st_slang;	/* language used for sound folding */
496 } suggest_T;
497 
498 #define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i])
499 
500 /* Number of suggestions kept when cleaning up.  When rescore_suggestions() is
501  * called the score may change, thus we need to keep more than what is
502  * displayed. */
503 #define SUG_CLEAN_COUNT(su)    ((su)->su_maxcount < 50 ? 50 : (su)->su_maxcount)
504 
505 /* Threshold for sorting and cleaning up suggestions.  Don't want to keep lots
506  * of suggestions that are not going to be displayed. */
507 #define SUG_MAX_COUNT(su)    ((su)->su_maxcount + 50)
508 
509 /* score for various changes */
510 #define SCORE_SPLIT	149	/* split bad word */
511 #define SCORE_ICASE	52	/* slightly different case */
512 #define SCORE_REGION	200	/* word is for different region */
513 #define SCORE_RARE	180	/* rare word */
514 #define SCORE_SWAP	90	/* swap two characters */
515 #define SCORE_SWAP3	110	/* swap two characters in three */
516 #define SCORE_REP	65	/* REP replacement */
517 #define SCORE_SUBST	93	/* substitute a character */
518 #define SCORE_SIMILAR	33	/* substitute a similar character */
519 #define SCORE_SUBCOMP	33	/* substitute a composing character */
520 #define SCORE_DEL	94	/* delete a character */
521 #define SCORE_DELDUP	66	/* delete a duplicated character */
522 #define SCORE_DELCOMP	28	/* delete a composing character */
523 #define SCORE_INS	96	/* insert a character */
524 #define SCORE_INSDUP	67	/* insert a duplicate character */
525 #define SCORE_INSCOMP	30	/* insert a composing character */
526 #define SCORE_NONWORD	103	/* change non-word to word char */
527 
528 #define SCORE_FILE	30	/* suggestion from a file */
529 #define SCORE_MAXINIT	350	/* Initial maximum score: higher == slower.
530 				 * 350 allows for about three changes. */
531 
532 #define SCORE_BIG	SCORE_INS * 3	/* big difference */
533 #define SCORE_MAXMAX	999999	/* accept any score */
534 
535 /*
536  * Structure to store info for word matching.
537  */
538 typedef struct matchinf_S
539 {
540     langp_T	*mi_lp;			/* info for language and region */
541 
542     /* pointers to original text to be checked */
543     char_u	*mi_word;		/* start of word being checked */
544     char_u	*mi_end;		/* end of matching word so far */
545     char_u	*mi_fend;		/* next char to be added to mi_fword */
546     char_u	*mi_cend;		/* char after what was used for
547 					   mi_capflags */
548 
549     /* case-folded text */
550     char_u	mi_fword[MAXWLEN + 1];	/* mi_word case-folded */
551     int		mi_fwordlen;		/* nr of valid bytes in mi_fword */
552 
553     /* for when checking word after a prefix */
554     int		mi_prefarridx;		/* index in sl_pidxs with list of
555 					   affixID/condition */
556     int		mi_prefcnt;		/* number of entries at mi_prefarridx */
557     int		mi_prefixlen;		/* byte length of prefix */
558 #ifdef FEAT_MBYTE
559     int		mi_cprefixlen;		/* byte length of prefix in original
560 					   case */
561 #else
562 # define mi_cprefixlen mi_prefixlen	/* it's the same value */
563 #endif
564 
565     /* for when checking a compound word */
566     int		mi_compoff;		/* start of following word offset */
567     char_u	mi_compflags[MAXWLEN];	/* flags for compound words used */
568     int		mi_complen;		/* nr of compound words used */
569 
570     /* others */
571     int		mi_result;		/* result so far: SP_BAD, SP_OK, etc. */
572     int		mi_capflags;		/* WF_ONECAP WF_ALLCAP WF_KEEPCAP */
573     buf_T	*mi_buf;		/* buffer being checked */
574 
575     /* for NOBREAK */
576     int		mi_result2;		/* "mi_resul" without following word */
577     char_u	*mi_end2;		/* "mi_end" without following word */
578 } matchinf_T;
579 
580 /*
581  * The tables used for recognizing word characters according to spelling.
582  * These are only used for the first 256 characters of 'encoding'.
583  */
584 typedef struct spelltab_S
585 {
586     char_u  st_isw[256];	/* flags: is word char */
587     char_u  st_isu[256];	/* flags: is uppercase char */
588     char_u  st_fold[256];	/* chars: folded case */
589     char_u  st_upper[256];	/* chars: upper case */
590 } spelltab_T;
591 
592 static spelltab_T   spelltab;
593 static int	    did_set_spelltab;
594 
595 #define CF_WORD		0x01
596 #define CF_UPPER	0x02
597 
598 static void clear_spell_chartab __ARGS((spelltab_T *sp));
599 static int set_spell_finish __ARGS((spelltab_T	*new_st));
600 static int spell_iswordp __ARGS((char_u *p, buf_T *buf));
601 static int spell_iswordp_nmw __ARGS((char_u *p));
602 #ifdef FEAT_MBYTE
603 static int spell_iswordp_w __ARGS((int *p, buf_T *buf));
604 #endif
605 static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap));
606 
607 /*
608  * For finding suggestions: At each node in the tree these states are tried:
609  */
610 typedef enum
611 {
612     STATE_START = 0,	/* At start of node check for NUL bytes (goodword
613 			 * ends); if badword ends there is a match, otherwise
614 			 * try splitting word. */
615     STATE_NOPREFIX,	/* try without prefix */
616     STATE_SPLITUNDO,	/* Undo splitting. */
617     STATE_ENDNUL,	/* Past NUL bytes at start of the node. */
618     STATE_PLAIN,	/* Use each byte of the node. */
619     STATE_DEL,		/* Delete a byte from the bad word. */
620     STATE_INS,		/* Insert a byte in the bad word. */
621     STATE_SWAP,		/* Swap two bytes. */
622     STATE_UNSWAP,	/* Undo swap two characters. */
623     STATE_SWAP3,	/* Swap two characters over three. */
624     STATE_UNSWAP3,	/* Undo Swap two characters over three. */
625     STATE_UNROT3L,	/* Undo rotate three characters left */
626     STATE_UNROT3R,	/* Undo rotate three characters right */
627     STATE_REP_INI,	/* Prepare for using REP items. */
628     STATE_REP,		/* Use matching REP items from the .aff file. */
629     STATE_REP_UNDO,	/* Undo a REP item replacement. */
630     STATE_FINAL		/* End of this node. */
631 } state_T;
632 
633 /*
634  * Struct to keep the state at each level in suggest_try_change().
635  */
636 typedef struct trystate_S
637 {
638     state_T	ts_state;	/* state at this level, STATE_ */
639     int		ts_score;	/* score */
640     idx_T	ts_arridx;	/* index in tree array, start of node */
641     short	ts_curi;	/* index in list of child nodes */
642     char_u	ts_fidx;	/* index in fword[], case-folded bad word */
643     char_u	ts_fidxtry;	/* ts_fidx at which bytes may be changed */
644     char_u	ts_twordlen;	/* valid length of tword[] */
645     char_u	ts_prefixdepth;	/* stack depth for end of prefix or
646 				 * PFD_PREFIXTREE or PFD_NOPREFIX */
647     char_u	ts_flags;	/* TSF_ flags */
648 #ifdef FEAT_MBYTE
649     char_u	ts_tcharlen;	/* number of bytes in tword character */
650     char_u	ts_tcharidx;	/* current byte index in tword character */
651     char_u	ts_isdiff;	/* DIFF_ values */
652     char_u	ts_fcharstart;	/* index in fword where badword char started */
653 #endif
654     char_u	ts_prewordlen;	/* length of word in "preword[]" */
655     char_u	ts_splitoff;	/* index in "tword" after last split */
656     char_u	ts_splitfidx;	/* "ts_fidx" at word split */
657     char_u	ts_complen;	/* nr of compound words used */
658     char_u	ts_compsplit;	/* index for "compflags" where word was spit */
659     char_u	ts_save_badflags;   /* su_badflags saved here */
660 } trystate_T;
661 
662 /* values for ts_isdiff */
663 #define DIFF_NONE	0	/* no different byte (yet) */
664 #define DIFF_YES	1	/* different byte found */
665 #define DIFF_INSERT	2	/* inserting character */
666 
667 /* values for ts_flags */
668 #define TSF_PREFIXOK	1	/* already checked that prefix is OK */
669 #define TSF_DIDSPLIT	2	/* tried split at this point */
670 
671 /* special values ts_prefixdepth */
672 #define PFD_NOPREFIX	0xff	/* not using prefixes */
673 #define PFD_PREFIXTREE	0xfe	/* walking through the prefix tree */
674 #define PFD_NOTSPECIAL	0xfd	/* first value that's not special */
675 
676 /* mode values for find_word */
677 #define FIND_FOLDWORD	    0	/* find word case-folded */
678 #define FIND_KEEPWORD	    1	/* find keep-case word */
679 #define FIND_PREFIX	    2	/* find word after prefix */
680 #define FIND_COMPOUND	    3	/* find case-folded compound word */
681 #define FIND_KEEPCOMPOUND   4	/* find keep-case compound word */
682 
683 static slang_T *slang_alloc __ARGS((char_u *lang));
684 static void slang_free __ARGS((slang_T *lp));
685 static void slang_clear __ARGS((slang_T *lp));
686 static void find_word __ARGS((matchinf_T *mip, int mode));
687 static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags));
688 static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req));
689 static void find_prefix __ARGS((matchinf_T *mip, int mode));
690 static int fold_more __ARGS((matchinf_T *mip));
691 static int spell_valid_case __ARGS((int wordflags, int treeflags));
692 static int no_spell_checking __ARGS((win_T *wp));
693 static void spell_load_lang __ARGS((char_u *lang));
694 static char_u *spell_enc __ARGS((void));
695 static void int_wordlist_spl __ARGS((char_u *fname));
696 static void spell_load_cb __ARGS((char_u *fname, void *cookie));
697 static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent));
698 static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *lenp));
699 static char_u *read_string __ARGS((FILE *fd, int cnt));
700 static int read_region_section __ARGS((FILE *fd, slang_T *slang, int len));
701 static int read_charflags_section __ARGS((FILE *fd));
702 static int read_prefcond_section __ARGS((FILE *fd, slang_T *lp));
703 static int read_rep_section __ARGS((FILE *fd, slang_T *slang));
704 static int read_sal_section __ARGS((FILE *fd, slang_T *slang));
705 static int read_sofo_section __ARGS((FILE *fd, slang_T *slang));
706 static int read_compound __ARGS((FILE *fd, slang_T *slang, int len));
707 static int byte_in_str __ARGS((char_u *str, int byte));
708 static int init_syl_tab __ARGS((slang_T *slang));
709 static int count_syllables __ARGS((slang_T *slang, char_u *word));
710 static int set_sofo __ARGS((slang_T *lp, char_u *from, char_u *to));
711 static void set_sal_first __ARGS((slang_T *lp));
712 #ifdef FEAT_MBYTE
713 static int *mb_str2wide __ARGS((char_u *s));
714 #endif
715 static idx_T read_tree __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, int startidx, int prefixtree, int maxprefcondnr));
716 static void clear_midword __ARGS((buf_T *buf));
717 static void use_midword __ARGS((slang_T *lp, buf_T *buf));
718 static int find_region __ARGS((char_u *rp, char_u *region));
719 static int captype __ARGS((char_u *word, char_u *end));
720 static int badword_captype __ARGS((char_u *word, char_u *end));
721 static void spell_reload_one __ARGS((char_u *fname, int added_word));
722 static void set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp));
723 static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp));
724 static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen));
725 static int check_need_cap __ARGS((linenr_T lnum, colnr_T col));
726 static void spell_find_suggest __ARGS((char_u *badptr, suginfo_T *su, int maxcount, int banbadword, int need_cap));
727 #ifdef FEAT_EVAL
728 static void spell_suggest_expr __ARGS((suginfo_T *su, char_u *expr));
729 #endif
730 static void spell_suggest_file __ARGS((suginfo_T *su, char_u *fname));
731 static void spell_suggest_intern __ARGS((suginfo_T *su));
732 static void spell_find_cleanup __ARGS((suginfo_T *su));
733 static void onecap_copy __ARGS((char_u *word, char_u *wcopy, int upper));
734 static void allcap_copy __ARGS((char_u *word, char_u *wcopy));
735 static void suggest_try_special __ARGS((suginfo_T *su));
736 static void suggest_try_change __ARGS((suginfo_T *su));
737 static int try_deeper __ARGS((suginfo_T *su, trystate_T *stack, int depth, int score_add));
738 #ifdef FEAT_MBYTE
739 static int nofold_len __ARGS((char_u *fword, int flen, char_u *word));
740 #endif
741 static void find_keepcap_word __ARGS((slang_T *slang, char_u *fword, char_u *kword));
742 static void score_comp_sal __ARGS((suginfo_T *su));
743 static void score_combine __ARGS((suginfo_T *su));
744 static int stp_sal_score __ARGS((suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *badsound));
745 static void suggest_try_soundalike __ARGS((suginfo_T *su));
746 static void make_case_word __ARGS((char_u *fword, char_u *cword, int flags));
747 static void set_map_str __ARGS((slang_T *lp, char_u *map));
748 static int similar_chars __ARGS((slang_T *slang, int c1, int c2));
749 static void add_suggestion __ARGS((suginfo_T *su, garray_T *gap, char_u *goodword, int badlen, int score, int altscore, int had_bonus, slang_T *slang));
750 static void add_banned __ARGS((suginfo_T *su, char_u *word));
751 static int was_banned __ARGS((suginfo_T *su, char_u *word));
752 static void free_banned __ARGS((suginfo_T *su));
753 static void rescore_suggestions __ARGS((suginfo_T *su));
754 static void rescore_one __ARGS((suginfo_T *su, suggest_T *stp));
755 static int cleanup_suggestions __ARGS((garray_T *gap, int maxscore, int keep));
756 static void spell_soundfold __ARGS((slang_T *slang, char_u *inword, int folded, char_u *res));
757 static void spell_soundfold_sofo __ARGS((slang_T *slang, char_u *inword, char_u *res));
758 static void spell_soundfold_sal __ARGS((slang_T *slang, char_u *inword, char_u *res));
759 #ifdef FEAT_MBYTE
760 static void spell_soundfold_wsal __ARGS((slang_T *slang, char_u *inword, char_u *res));
761 #endif
762 static int soundalike_score __ARGS((char_u *goodsound, char_u *badsound));
763 static int spell_edit_score __ARGS((char_u *badword, char_u *goodword));
764 static void dump_word __ARGS((char_u *word, int round, int flags, linenr_T lnum));
765 static linenr_T dump_prefixes __ARGS((slang_T *slang, char_u *word, int round, int flags, linenr_T startlnum));
766 
767 /*
768  * Use our own character-case definitions, because the current locale may
769  * differ from what the .spl file uses.
770  * These must not be called with negative number!
771  */
772 #ifndef FEAT_MBYTE
773 /* Non-multi-byte implementation. */
774 # define SPELL_TOFOLD(c) ((c) < 256 ? spelltab.st_fold[c] : (c))
775 # define SPELL_TOUPPER(c) ((c) < 256 ? spelltab.st_upper[c] : (c))
776 # define SPELL_ISUPPER(c) ((c) < 256 ? spelltab.st_isu[c] : FALSE)
777 #else
778 # if defined(HAVE_WCHAR_H)
779 #  include <wchar.h>	    /* for towupper() and towlower() */
780 # endif
781 /* Multi-byte implementation.  For Unicode we can call utf_*(), but don't do
782  * that for ASCII, because we don't want to use 'casemap' here.  Otherwise use
783  * the "w" library function for characters above 255 if available. */
784 # ifdef HAVE_TOWLOWER
785 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
786 	    : (c) < 256 ? spelltab.st_fold[c] : towlower(c))
787 # else
788 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
789 	    : (c) < 256 ? spelltab.st_fold[c] : (c))
790 # endif
791 
792 # ifdef HAVE_TOWUPPER
793 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
794 	    : (c) < 256 ? spelltab.st_upper[c] : towupper(c))
795 # else
796 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
797 	    : (c) < 256 ? spelltab.st_upper[c] : (c))
798 # endif
799 
800 # ifdef HAVE_ISWUPPER
801 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
802 	    : (c) < 256 ? spelltab.st_isu[c] : iswupper(c))
803 # else
804 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
805 	    : (c) < 256 ? spelltab.st_isu[c] : (FALSE))
806 # endif
807 #endif
808 
809 
810 static char *e_format = N_("E759: Format error in spell file");
811 static char *e_spell_trunc = N_("E758: Truncated spell file");
812 static char *e_afftrailing = N_("Trailing text in %s line %d: %s");
813 static char *e_affname = N_("Affix name too long in %s line %d: %s");
814 static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP");
815 static char *e_affrange = N_("E762: Character in FOL, LOW or UPP is out of range");
816 static char *msg_compressing = N_("Compressing word tree...");
817 
818 /*
819  * Main spell-checking function.
820  * "ptr" points to a character that could be the start of a word.
821  * "*attrp" is set to the highlight index for a badly spelled word.  For a
822  * non-word or when it's OK it remains unchanged.
823  * This must only be called when 'spelllang' is not empty.
824  *
825  * "capcol" is used to check for a Capitalised word after the end of a
826  * sentence.  If it's zero then perform the check.  Return the column where to
827  * check next, or -1 when no sentence end was found.  If it's NULL then don't
828  * worry.
829  *
830  * Returns the length of the word in bytes, also when it's OK, so that the
831  * caller can skip over the word.
832  */
833     int
834 spell_check(wp, ptr, attrp, capcol)
835     win_T	*wp;		/* current window */
836     char_u	*ptr;
837     hlf_T	*attrp;
838     int		*capcol;	/* column to check for Capital */
839 {
840     matchinf_T	mi;		/* Most things are put in "mi" so that it can
841 				   be passed to functions quickly. */
842     int		nrlen = 0;	/* found a number first */
843     int		c;
844     int		wrongcaplen = 0;
845     int		lpi;
846 
847     /* A word never starts at a space or a control character.  Return quickly
848      * then, skipping over the character. */
849     if (*ptr <= ' ')
850 	return 1;
851     vim_memset(&mi, 0, sizeof(matchinf_T));
852 
853     /* A number is always OK.  Also skip hexadecimal numbers 0xFF99 and
854      * 0X99FF.  But always do check spelling to find "3GPP" and "11
855      * julifeest". */
856     if (*ptr >= '0' && *ptr <= '9')
857     {
858 	if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
859 	    mi.mi_end = skiphex(ptr + 2);
860 	else
861 	    mi.mi_end = skipdigits(ptr);
862 	nrlen = mi.mi_end - ptr;
863     }
864 
865     /* Find the normal end of the word (until the next non-word character). */
866     mi.mi_word = ptr;
867     mi.mi_fend = ptr;
868     if (spell_iswordp(mi.mi_fend, wp->w_buffer))
869     {
870 	do
871 	{
872 	    mb_ptr_adv(mi.mi_fend);
873 	} while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp->w_buffer));
874 
875 	if (capcol != NULL && *capcol == 0 && wp->w_buffer->b_cap_prog != NULL)
876 	{
877 	    /* Check word starting with capital letter. */
878 	    c = PTR2CHAR(ptr);
879 	    if (!SPELL_ISUPPER(c))
880 		wrongcaplen = (int)(mi.mi_fend - ptr);
881 	}
882     }
883     if (capcol != NULL)
884 	*capcol = -1;
885 
886     /* We always use the characters up to the next non-word character,
887      * also for bad words. */
888     mi.mi_end = mi.mi_fend;
889 
890     /* Check caps type later. */
891     mi.mi_buf = wp->w_buffer;
892 
893     /* case-fold the word with one non-word character, so that we can check
894      * for the word end. */
895     if (*mi.mi_fend != NUL)
896 	mb_ptr_adv(mi.mi_fend);
897 
898     (void)spell_casefold(ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
899 							     MAXWLEN + 1);
900     mi.mi_fwordlen = STRLEN(mi.mi_fword);
901 
902     /* The word is bad unless we recognize it. */
903     mi.mi_result = SP_BAD;
904     mi.mi_result2 = SP_BAD;
905 
906     /*
907      * Loop over the languages specified in 'spelllang'.
908      * We check them all, because a matching word may be longer than an
909      * already found matching word.
910      */
911     for (lpi = 0; lpi < wp->w_buffer->b_langp.ga_len; ++lpi)
912     {
913 	mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi);
914 
915 	/* If reloading fails the language is still in the list but everything
916 	 * has been cleared. */
917 	if (mi.mi_lp->lp_slang->sl_fidxs == NULL)
918 	    continue;
919 
920 	/* Check for a matching word in case-folded words. */
921 	find_word(&mi, FIND_FOLDWORD);
922 
923 	/* Check for a matching word in keep-case words. */
924 	find_word(&mi, FIND_KEEPWORD);
925 
926 	/* Check for matching prefixes. */
927 	find_prefix(&mi, FIND_FOLDWORD);
928 
929 	/* For a NOBREAK language, may want to use a word without a following
930 	 * word as a backup. */
931 	if (mi.mi_lp->lp_slang->sl_nobreak && mi.mi_result == SP_BAD
932 						   && mi.mi_result2 != SP_BAD)
933 	{
934 	    mi.mi_result = mi.mi_result2;
935 	    mi.mi_end = mi.mi_end2;
936 	}
937     }
938 
939     if (mi.mi_result != SP_OK)
940     {
941 	/* If we found a number skip over it.  Allows for "42nd".  Do flag
942 	 * rare and local words, e.g., "3GPP". */
943 	if (nrlen > 0)
944 	{
945 	    if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
946 		return nrlen;
947 	}
948 
949 	/* When we are at a non-word character there is no error, just
950 	 * skip over the character (try looking for a word after it). */
951 	else if (!spell_iswordp_nmw(ptr))
952 	{
953 	    if (capcol != NULL && wp->w_buffer->b_cap_prog != NULL)
954 	    {
955 		regmatch_T	regmatch;
956 
957 		/* Check for end of sentence. */
958 		regmatch.regprog = wp->w_buffer->b_cap_prog;
959 		regmatch.rm_ic = FALSE;
960 		if (vim_regexec(&regmatch, ptr, 0))
961 		    *capcol = (int)(regmatch.endp[0] - ptr);
962 	    }
963 
964 #ifdef FEAT_MBYTE
965 	    if (has_mbyte)
966 		return (*mb_ptr2len)(ptr);
967 #endif
968 	    return 1;
969 	}
970 	else if (mi.mi_end == ptr)
971 	    /* Always include at least one character.  Required for when there
972 	     * is a mixup in "midword". */
973 	    mb_ptr_adv(mi.mi_end);
974 	else if (mi.mi_result == SP_BAD
975 		&& LANGP_ENTRY(wp->w_buffer->b_langp, 0)->lp_slang->sl_nobreak)
976 	{
977 	    char_u	*p, *fp;
978 	    int		save_result = mi.mi_result;
979 
980 	    /* First language in 'spelllang' is NOBREAK.  Find first position
981 	     * at which any word would be valid. */
982 	    mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
983 	    if (mi.mi_lp->lp_slang->sl_fidxs != NULL)
984 	    {
985 		p = mi.mi_word;
986 		fp = mi.mi_fword;
987 		for (;;)
988 		{
989 		    mb_ptr_adv(p);
990 		    mb_ptr_adv(fp);
991 		    if (p >= mi.mi_end)
992 			break;
993 		    mi.mi_compoff = fp - mi.mi_fword;
994 		    find_word(&mi, FIND_COMPOUND);
995 		    if (mi.mi_result != SP_BAD)
996 		    {
997 			mi.mi_end = p;
998 			break;
999 		    }
1000 		}
1001 		mi.mi_result = save_result;
1002 	    }
1003 	}
1004 
1005 	if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
1006 	    *attrp = HLF_SPB;
1007 	else if (mi.mi_result == SP_RARE)
1008 	    *attrp = HLF_SPR;
1009 	else
1010 	    *attrp = HLF_SPL;
1011     }
1012 
1013     if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE))
1014     {
1015 	/* Report SpellCap only when the word isn't badly spelled. */
1016 	*attrp = HLF_SPC;
1017 	return wrongcaplen;
1018     }
1019 
1020     return (int)(mi.mi_end - ptr);
1021 }
1022 
1023 /*
1024  * Check if the word at "mip->mi_word" is in the tree.
1025  * When "mode" is FIND_FOLDWORD check in fold-case word tree.
1026  * When "mode" is FIND_KEEPWORD check in keep-case word tree.
1027  * When "mode" is FIND_PREFIX check for word after prefix in fold-case word
1028  * tree.
1029  *
1030  * For a match mip->mi_result is updated.
1031  */
1032     static void
1033 find_word(mip, mode)
1034     matchinf_T	*mip;
1035     int		mode;
1036 {
1037     idx_T	arridx = 0;
1038     int		endlen[MAXWLEN];    /* length at possible word endings */
1039     idx_T	endidx[MAXWLEN];    /* possible word endings */
1040     int		endidxcnt = 0;
1041     int		len;
1042     int		wlen = 0;
1043     int		flen;
1044     int		c;
1045     char_u	*ptr;
1046     idx_T	lo, hi, m;
1047 #ifdef FEAT_MBYTE
1048     char_u	*s;
1049 #endif
1050     char_u	*p;
1051     int		res = SP_BAD;
1052     slang_T	*slang = mip->mi_lp->lp_slang;
1053     unsigned	flags;
1054     char_u	*byts;
1055     idx_T	*idxs;
1056     int		word_ends;
1057     int		prefix_found;
1058     int		nobreak_result;
1059 
1060     if (mode == FIND_KEEPWORD || mode == FIND_KEEPCOMPOUND)
1061     {
1062 	/* Check for word with matching case in keep-case tree. */
1063 	ptr = mip->mi_word;
1064 	flen = 9999;		    /* no case folding, always enough bytes */
1065 	byts = slang->sl_kbyts;
1066 	idxs = slang->sl_kidxs;
1067 
1068 	if (mode == FIND_KEEPCOMPOUND)
1069 	    /* Skip over the previously found word(s). */
1070 	    wlen += mip->mi_compoff;
1071     }
1072     else
1073     {
1074 	/* Check for case-folded in case-folded tree. */
1075 	ptr = mip->mi_fword;
1076 	flen = mip->mi_fwordlen;    /* available case-folded bytes */
1077 	byts = slang->sl_fbyts;
1078 	idxs = slang->sl_fidxs;
1079 
1080 	if (mode == FIND_PREFIX)
1081 	{
1082 	    /* Skip over the prefix. */
1083 	    wlen = mip->mi_prefixlen;
1084 	    flen -= mip->mi_prefixlen;
1085 	}
1086 	else if (mode == FIND_COMPOUND)
1087 	{
1088 	    /* Skip over the previously found word(s). */
1089 	    wlen = mip->mi_compoff;
1090 	    flen -= mip->mi_compoff;
1091 	}
1092 
1093     }
1094 
1095     if (byts == NULL)
1096 	return;			/* array is empty */
1097 
1098     /*
1099      * Repeat advancing in the tree until:
1100      * - there is a byte that doesn't match,
1101      * - we reach the end of the tree,
1102      * - or we reach the end of the line.
1103      */
1104     for (;;)
1105     {
1106 	if (flen <= 0 && *mip->mi_fend != NUL)
1107 	    flen = fold_more(mip);
1108 
1109 	len = byts[arridx++];
1110 
1111 	/* If the first possible byte is a zero the word could end here.
1112 	 * Remember this index, we first check for the longest word. */
1113 	if (byts[arridx] == 0)
1114 	{
1115 	    if (endidxcnt == MAXWLEN)
1116 	    {
1117 		/* Must be a corrupted spell file. */
1118 		EMSG(_(e_format));
1119 		return;
1120 	    }
1121 	    endlen[endidxcnt] = wlen;
1122 	    endidx[endidxcnt++] = arridx++;
1123 	    --len;
1124 
1125 	    /* Skip over the zeros, there can be several flag/region
1126 	     * combinations. */
1127 	    while (len > 0 && byts[arridx] == 0)
1128 	    {
1129 		++arridx;
1130 		--len;
1131 	    }
1132 	    if (len == 0)
1133 		break;	    /* no children, word must end here */
1134 	}
1135 
1136 	/* Stop looking at end of the line. */
1137 	if (ptr[wlen] == NUL)
1138 	    break;
1139 
1140 	/* Perform a binary search in the list of accepted bytes. */
1141 	c = ptr[wlen];
1142 	if (c == TAB)	    /* <Tab> is handled like <Space> */
1143 	    c = ' ';
1144 	lo = arridx;
1145 	hi = arridx + len - 1;
1146 	while (lo < hi)
1147 	{
1148 	    m = (lo + hi) / 2;
1149 	    if (byts[m] > c)
1150 		hi = m - 1;
1151 	    else if (byts[m] < c)
1152 		lo = m + 1;
1153 	    else
1154 	    {
1155 		lo = hi = m;
1156 		break;
1157 	    }
1158 	}
1159 
1160 	/* Stop if there is no matching byte. */
1161 	if (hi < lo || byts[lo] != c)
1162 	    break;
1163 
1164 	/* Continue at the child (if there is one). */
1165 	arridx = idxs[lo];
1166 	++wlen;
1167 	--flen;
1168 
1169 	/* One space in the good word may stand for several spaces in the
1170 	 * checked word. */
1171 	if (c == ' ')
1172 	{
1173 	    for (;;)
1174 	    {
1175 		if (flen <= 0 && *mip->mi_fend != NUL)
1176 		    flen = fold_more(mip);
1177 		if (ptr[wlen] != ' ' && ptr[wlen] != TAB)
1178 		    break;
1179 		++wlen;
1180 		--flen;
1181 	    }
1182 	}
1183     }
1184 
1185     /*
1186      * Verify that one of the possible endings is valid.  Try the longest
1187      * first.
1188      */
1189     while (endidxcnt > 0)
1190     {
1191 	--endidxcnt;
1192 	arridx = endidx[endidxcnt];
1193 	wlen = endlen[endidxcnt];
1194 
1195 #ifdef FEAT_MBYTE
1196 	if ((*mb_head_off)(ptr, ptr + wlen) > 0)
1197 	    continue;	    /* not at first byte of character */
1198 #endif
1199 	if (spell_iswordp(ptr + wlen, mip->mi_buf))
1200 	{
1201 	    if (slang->sl_compprog == NULL && !slang->sl_nobreak)
1202 		continue;	    /* next char is a word character */
1203 	    word_ends = FALSE;
1204 	}
1205 	else
1206 	    word_ends = TRUE;
1207 	/* The prefix flag is before compound flags.  Once a valid prefix flag
1208 	 * has been found we try compound flags. */
1209 	prefix_found = FALSE;
1210 
1211 #ifdef FEAT_MBYTE
1212 	if (mode != FIND_KEEPWORD && has_mbyte)
1213 	{
1214 	    /* Compute byte length in original word, length may change
1215 	     * when folding case.  This can be slow, take a shortcut when the
1216 	     * case-folded word is equal to the keep-case word. */
1217 	    p = mip->mi_word;
1218 	    if (STRNCMP(ptr, p, wlen) != 0)
1219 	    {
1220 		for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1221 		    mb_ptr_adv(p);
1222 		wlen = p - mip->mi_word;
1223 	    }
1224 	}
1225 #endif
1226 
1227 	/* Check flags and region.  For FIND_PREFIX check the condition and
1228 	 * prefix ID.
1229 	 * Repeat this if there are more flags/region alternatives until there
1230 	 * is a match. */
1231 	res = SP_BAD;
1232 	for (len = byts[arridx - 1]; len > 0 && byts[arridx] == 0;
1233 							      --len, ++arridx)
1234 	{
1235 	    flags = idxs[arridx];
1236 
1237 	    /* For the fold-case tree check that the case of the checked word
1238 	     * matches with what the word in the tree requires.
1239 	     * For keep-case tree the case is always right.  For prefixes we
1240 	     * don't bother to check. */
1241 	    if (mode == FIND_FOLDWORD)
1242 	    {
1243 		if (mip->mi_cend != mip->mi_word + wlen)
1244 		{
1245 		    /* mi_capflags was set for a different word length, need
1246 		     * to do it again. */
1247 		    mip->mi_cend = mip->mi_word + wlen;
1248 		    mip->mi_capflags = captype(mip->mi_word, mip->mi_cend);
1249 		}
1250 
1251 		if (mip->mi_capflags == WF_KEEPCAP
1252 				|| !spell_valid_case(mip->mi_capflags, flags))
1253 		    continue;
1254 	    }
1255 
1256 	    /* When mode is FIND_PREFIX the word must support the prefix:
1257 	     * check the prefix ID and the condition.  Do that for the list at
1258 	     * mip->mi_prefarridx that find_prefix() filled. */
1259 	    else if (mode == FIND_PREFIX && !prefix_found)
1260 	    {
1261 		c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
1262 				    flags,
1263 				    mip->mi_word + mip->mi_cprefixlen, slang,
1264 				    FALSE);
1265 		if (c == 0)
1266 		    continue;
1267 
1268 		/* Use the WF_RARE flag for a rare prefix. */
1269 		if (c & WF_RAREPFX)
1270 		    flags |= WF_RARE;
1271 		prefix_found = TRUE;
1272 	    }
1273 
1274 	    if (slang->sl_nobreak)
1275 	    {
1276 		if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND)
1277 			&& (flags & WF_BANNED) == 0)
1278 		{
1279 		    /* NOBREAK: found a valid following word.  That's all we
1280 		     * need to know, so return. */
1281 		    mip->mi_result = SP_OK;
1282 		    break;
1283 		}
1284 	    }
1285 
1286 	    else if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND
1287 								|| !word_ends))
1288 	    {
1289 		/* If there is no  flag or the word is shorter than
1290 		 * COMPOUNDMIN reject it quickly.
1291 		 * Makes you wonder why someone puts a compound flag on a word
1292 		 * that's too short...  Myspell compatibility requires this
1293 		 * anyway. */
1294 		if (((unsigned)flags >> 24) == 0
1295 			     || wlen - mip->mi_compoff < slang->sl_compminlen)
1296 		    continue;
1297 #ifdef FEAT_MBYTE
1298 		/* For multi-byte chars check character length against
1299 		 * COMPOUNDMIN. */
1300 		if (has_mbyte
1301 			&& slang->sl_compminlen > 0
1302 			&& mb_charlen_len(mip->mi_word + mip->mi_compoff,
1303 				wlen - mip->mi_compoff) < slang->sl_compminlen)
1304 			continue;
1305 #endif
1306 
1307 		/* Limit the number of compound words to COMPOUNDMAX if no
1308 		 * maximum for syllables is specified. */
1309 		if (!word_ends && mip->mi_complen + 2 > slang->sl_compmax
1310 					   && slang->sl_compsylmax == MAXWLEN)
1311 		    continue;
1312 
1313 		/* Quickly check if compounding is possible with this flag. */
1314 		if (!byte_in_str(mip->mi_complen == 0
1315 					? slang->sl_compstartflags
1316 					: slang->sl_compallflags,
1317 					    ((unsigned)flags >> 24)))
1318 		    continue;
1319 
1320 		if (mode == FIND_COMPOUND)
1321 		{
1322 		    int	    capflags;
1323 
1324 		    /* Need to check the caps type of the appended compound
1325 		     * word. */
1326 #ifdef FEAT_MBYTE
1327 		    if (has_mbyte && STRNCMP(ptr, mip->mi_word,
1328 							mip->mi_compoff) != 0)
1329 		    {
1330 			/* case folding may have changed the length */
1331 			p = mip->mi_word;
1332 			for (s = ptr; s < ptr + mip->mi_compoff; mb_ptr_adv(s))
1333 			    mb_ptr_adv(p);
1334 		    }
1335 		    else
1336 #endif
1337 			p = mip->mi_word + mip->mi_compoff;
1338 		    capflags = captype(p, mip->mi_word + wlen);
1339 		    if (capflags == WF_KEEPCAP || (capflags == WF_ALLCAP
1340 						 && (flags & WF_FIXCAP) != 0))
1341 			continue;
1342 
1343 		    if (capflags != WF_ALLCAP)
1344 		    {
1345 			/* When the character before the word is a word
1346 			 * character we do not accept a Onecap word.  We do
1347 			 * accept a no-caps word, even when the dictionary
1348 			 * word specifies ONECAP. */
1349 			mb_ptr_back(mip->mi_word, p);
1350 			if (spell_iswordp_nmw(p)
1351 				? capflags == WF_ONECAP
1352 				: (flags & WF_ONECAP) != 0
1353 						     && capflags != WF_ONECAP)
1354 			    continue;
1355 		    }
1356 		}
1357 
1358 		/* If the word ends the sequence of compound flags of the
1359 		 * words must match with one of the COMPOUNDFLAGS items and
1360 		 * the number of syllables must not be too large. */
1361 		mip->mi_compflags[mip->mi_complen] = ((unsigned)flags >> 24);
1362 		mip->mi_compflags[mip->mi_complen + 1] = NUL;
1363 		if (word_ends)
1364 		{
1365 		    char_u	fword[MAXWLEN];
1366 
1367 		    if (slang->sl_compsylmax < MAXWLEN)
1368 		    {
1369 			/* "fword" is only needed for checking syllables. */
1370 			if (ptr == mip->mi_word)
1371 			    (void)spell_casefold(ptr, wlen, fword, MAXWLEN);
1372 			else
1373 			    vim_strncpy(fword, ptr, endlen[endidxcnt]);
1374 		    }
1375 		    if (!can_compound(slang, fword, mip->mi_compflags))
1376 			continue;
1377 		}
1378 	    }
1379 
1380 	    /* Check NEEDCOMPOUND: can't use word without compounding. */
1381 	    else if (flags & WF_NEEDCOMP)
1382 		continue;
1383 
1384 	    nobreak_result = SP_OK;
1385 
1386 	    if (!word_ends)
1387 	    {
1388 		int	save_result = mip->mi_result;
1389 		char_u	*save_end = mip->mi_end;
1390 		langp_T	*save_lp = mip->mi_lp;
1391 		int	lpi;
1392 
1393 		/* Check that a valid word follows.  If there is one and we
1394 		 * are compounding, it will set "mi_result", thus we are
1395 		 * always finished here.  For NOBREAK we only check that a
1396 		 * valid word follows.
1397 		 * Recursive! */
1398 		if (slang->sl_nobreak)
1399 		    mip->mi_result = SP_BAD;
1400 
1401 		/* Find following word in case-folded tree. */
1402 		mip->mi_compoff = endlen[endidxcnt];
1403 #ifdef FEAT_MBYTE
1404 		if (has_mbyte && mode == FIND_KEEPWORD)
1405 		{
1406 		    /* Compute byte length in case-folded word from "wlen":
1407 		     * byte length in keep-case word.  Length may change when
1408 		     * folding case.  This can be slow, take a shortcut when
1409 		     * the case-folded word is equal to the keep-case word. */
1410 		    p = mip->mi_fword;
1411 		    if (STRNCMP(ptr, p, wlen) != 0)
1412 		    {
1413 			for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1414 			    mb_ptr_adv(p);
1415 			mip->mi_compoff = p - mip->mi_fword;
1416 		    }
1417 		}
1418 #endif
1419 		c = mip->mi_compoff;
1420 		++mip->mi_complen;
1421 
1422 		/* For NOBREAK we need to try all NOBREAK languages, at least
1423 		 * to find the ".add" file(s). */
1424 		for (lpi = 0; lpi < mip->mi_buf->b_langp.ga_len; ++lpi)
1425 		{
1426 		    if (slang->sl_nobreak)
1427 		    {
1428 			mip->mi_lp = LANGP_ENTRY(mip->mi_buf->b_langp, lpi);
1429 			if (mip->mi_lp->lp_slang->sl_fidxs == NULL
1430 					 || !mip->mi_lp->lp_slang->sl_nobreak)
1431 			    continue;
1432 		    }
1433 
1434 		    find_word(mip, FIND_COMPOUND);
1435 
1436 		    /* When NOBREAK any word that matches is OK.  Otherwise we
1437 		     * need to find the longest match, thus try with keep-case
1438 		     * and prefix too. */
1439 		    if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1440 		    {
1441 			/* Find following word in keep-case tree. */
1442 			mip->mi_compoff = wlen;
1443 			find_word(mip, FIND_KEEPCOMPOUND);
1444 
1445 			if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1446 			{
1447 			    /* Check for following word with prefix. */
1448 			    mip->mi_compoff = c;
1449 			    find_prefix(mip, FIND_COMPOUND);
1450 			}
1451 		    }
1452 
1453 		    if (!slang->sl_nobreak)
1454 			break;
1455 		}
1456 		--mip->mi_complen;
1457 		mip->mi_lp = save_lp;
1458 
1459 		if (slang->sl_nobreak)
1460 		{
1461 		    nobreak_result = mip->mi_result;
1462 		    mip->mi_result = save_result;
1463 		    mip->mi_end = save_end;
1464 		}
1465 		else
1466 		{
1467 		    if (mip->mi_result == SP_OK)
1468 			break;
1469 		    continue;
1470 		}
1471 	    }
1472 
1473 	    if (flags & WF_BANNED)
1474 		res = SP_BANNED;
1475 	    else if (flags & WF_REGION)
1476 	    {
1477 		/* Check region. */
1478 		if ((mip->mi_lp->lp_region & (flags >> 16)) != 0)
1479 		    res = SP_OK;
1480 		else
1481 		    res = SP_LOCAL;
1482 	    }
1483 	    else if (flags & WF_RARE)
1484 		res = SP_RARE;
1485 	    else
1486 		res = SP_OK;
1487 
1488 	    /* Always use the longest match and the best result.  For NOBREAK
1489 	     * we separately keep the longest match without a following good
1490 	     * word as a fall-back. */
1491 	    if (nobreak_result == SP_BAD)
1492 	    {
1493 		if (mip->mi_result2 > res)
1494 		{
1495 		    mip->mi_result2 = res;
1496 		    mip->mi_end2 = mip->mi_word + wlen;
1497 		}
1498 		else if (mip->mi_result2 == res
1499 					&& mip->mi_end2 < mip->mi_word + wlen)
1500 		    mip->mi_end2 = mip->mi_word + wlen;
1501 	    }
1502 	    else if (mip->mi_result > res)
1503 	    {
1504 		mip->mi_result = res;
1505 		mip->mi_end = mip->mi_word + wlen;
1506 	    }
1507 	    else if (mip->mi_result == res && mip->mi_end < mip->mi_word + wlen)
1508 		mip->mi_end = mip->mi_word + wlen;
1509 
1510 	    if (mip->mi_result == SP_OK)
1511 		break;
1512 	}
1513 
1514 	if (mip->mi_result == SP_OK)
1515 	    break;
1516     }
1517 }
1518 
1519 /*
1520  * Return TRUE if "flags" is a valid sequence of compound flags and
1521  * "word[len]" does not have too many syllables.
1522  */
1523     static int
1524 can_compound(slang, word, flags)
1525     slang_T	*slang;
1526     char_u	*word;
1527     char_u	*flags;
1528 {
1529     regmatch_T	regmatch;
1530 #ifdef FEAT_MBYTE
1531     char_u	uflags[MAXWLEN * 2];
1532     int		i;
1533 #endif
1534     char_u	*p;
1535 
1536     if (slang->sl_compprog == NULL)
1537 	return FALSE;
1538 #ifdef FEAT_MBYTE
1539     if (enc_utf8)
1540     {
1541 	/* Need to convert the single byte flags to utf8 characters. */
1542 	p = uflags;
1543 	for (i = 0; flags[i] != NUL; ++i)
1544 	    p += mb_char2bytes(flags[i], p);
1545 	*p = NUL;
1546 	p = uflags;
1547     }
1548     else
1549 #endif
1550 	p = flags;
1551     regmatch.regprog = slang->sl_compprog;
1552     regmatch.rm_ic = FALSE;
1553     if (!vim_regexec(&regmatch, p, 0))
1554 	return FALSE;
1555 
1556     /* Count the number of syllables.  This may be slow, do it last.  If there
1557      * are too many syllables AND the number of compound words is above
1558      * COMPOUNDMAX then compounding is not allowed. */
1559     if (slang->sl_compsylmax < MAXWLEN
1560 		       && count_syllables(slang, word) > slang->sl_compsylmax)
1561 	return (int)STRLEN(flags) < slang->sl_compmax;
1562     return TRUE;
1563 }
1564 
1565 /*
1566  * Return non-zero if the prefix indicated by "arridx" matches with the prefix
1567  * ID in "flags" for the word "word".
1568  * The WF_RAREPFX flag is included in the return value for a rare prefix.
1569  */
1570     static int
1571 valid_word_prefix(totprefcnt, arridx, flags, word, slang, cond_req)
1572     int		totprefcnt;	/* nr of prefix IDs */
1573     int		arridx;		/* idx in sl_pidxs[] */
1574     int		flags;
1575     char_u	*word;
1576     slang_T	*slang;
1577     int		cond_req;	/* only use prefixes with a condition */
1578 {
1579     int		prefcnt;
1580     int		pidx;
1581     regprog_T	*rp;
1582     regmatch_T	regmatch;
1583     int		prefid;
1584 
1585     prefid = (unsigned)flags >> 24;
1586     for (prefcnt = totprefcnt - 1; prefcnt >= 0; --prefcnt)
1587     {
1588 	pidx = slang->sl_pidxs[arridx + prefcnt];
1589 
1590 	/* Check the prefix ID. */
1591 	if (prefid != (pidx & 0xff))
1592 	    continue;
1593 
1594 	/* Check if the prefix doesn't combine and the word already has a
1595 	 * suffix. */
1596 	if ((flags & WF_HAS_AFF) && (pidx & WF_PFX_NC))
1597 	    continue;
1598 
1599 	/* Check the condition, if there is one.  The condition index is
1600 	 * stored in the two bytes above the prefix ID byte.  */
1601 	rp = slang->sl_prefprog[((unsigned)pidx >> 8) & 0xffff];
1602 	if (rp != NULL)
1603 	{
1604 	    regmatch.regprog = rp;
1605 	    regmatch.rm_ic = FALSE;
1606 	    if (!vim_regexec(&regmatch, word, 0))
1607 		continue;
1608 	}
1609 	else if (cond_req)
1610 	    continue;
1611 
1612 	/* It's a match!  Return the WF_ flags. */
1613 	return pidx;
1614     }
1615     return 0;
1616 }
1617 
1618 /*
1619  * Check if the word at "mip->mi_word" has a matching prefix.
1620  * If it does, then check the following word.
1621  *
1622  * If "mode" is "FIND_COMPOUND" then do the same after another word, find a
1623  * prefix in a compound word.
1624  *
1625  * For a match mip->mi_result is updated.
1626  */
1627     static void
1628 find_prefix(mip, mode)
1629     matchinf_T	*mip;
1630     int		mode;
1631 {
1632     idx_T	arridx = 0;
1633     int		len;
1634     int		wlen = 0;
1635     int		flen;
1636     int		c;
1637     char_u	*ptr;
1638     idx_T	lo, hi, m;
1639     slang_T	*slang = mip->mi_lp->lp_slang;
1640     char_u	*byts;
1641     idx_T	*idxs;
1642 
1643     byts = slang->sl_pbyts;
1644     if (byts == NULL)
1645 	return;			/* array is empty */
1646 
1647     /* We use the case-folded word here, since prefixes are always
1648      * case-folded. */
1649     ptr = mip->mi_fword;
1650     flen = mip->mi_fwordlen;    /* available case-folded bytes */
1651     if (mode == FIND_COMPOUND)
1652     {
1653 	/* Skip over the previously found word(s). */
1654 	ptr += mip->mi_compoff;
1655 	flen -= mip->mi_compoff;
1656     }
1657     idxs = slang->sl_pidxs;
1658 
1659     /*
1660      * Repeat advancing in the tree until:
1661      * - there is a byte that doesn't match,
1662      * - we reach the end of the tree,
1663      * - or we reach the end of the line.
1664      */
1665     for (;;)
1666     {
1667 	if (flen == 0 && *mip->mi_fend != NUL)
1668 	    flen = fold_more(mip);
1669 
1670 	len = byts[arridx++];
1671 
1672 	/* If the first possible byte is a zero the prefix could end here.
1673 	 * Check if the following word matches and supports the prefix. */
1674 	if (byts[arridx] == 0)
1675 	{
1676 	    /* There can be several prefixes with different conditions.  We
1677 	     * try them all, since we don't know which one will give the
1678 	     * longest match.  The word is the same each time, pass the list
1679 	     * of possible prefixes to find_word(). */
1680 	    mip->mi_prefarridx = arridx;
1681 	    mip->mi_prefcnt = len;
1682 	    while (len > 0 && byts[arridx] == 0)
1683 	    {
1684 		++arridx;
1685 		--len;
1686 	    }
1687 	    mip->mi_prefcnt -= len;
1688 
1689 	    /* Find the word that comes after the prefix. */
1690 	    mip->mi_prefixlen = wlen;
1691 	    if (mode == FIND_COMPOUND)
1692 		/* Skip over the previously found word(s). */
1693 		mip->mi_prefixlen += mip->mi_compoff;
1694 
1695 #ifdef FEAT_MBYTE
1696 	    if (has_mbyte)
1697 	    {
1698 		/* Case-folded length may differ from original length. */
1699 		mip->mi_cprefixlen = nofold_len(mip->mi_fword,
1700 					     mip->mi_prefixlen, mip->mi_word);
1701 	    }
1702 	    else
1703 		mip->mi_cprefixlen = mip->mi_prefixlen;
1704 #endif
1705 	    find_word(mip, FIND_PREFIX);
1706 
1707 
1708 	    if (len == 0)
1709 		break;	    /* no children, word must end here */
1710 	}
1711 
1712 	/* Stop looking at end of the line. */
1713 	if (ptr[wlen] == NUL)
1714 	    break;
1715 
1716 	/* Perform a binary search in the list of accepted bytes. */
1717 	c = ptr[wlen];
1718 	lo = arridx;
1719 	hi = arridx + len - 1;
1720 	while (lo < hi)
1721 	{
1722 	    m = (lo + hi) / 2;
1723 	    if (byts[m] > c)
1724 		hi = m - 1;
1725 	    else if (byts[m] < c)
1726 		lo = m + 1;
1727 	    else
1728 	    {
1729 		lo = hi = m;
1730 		break;
1731 	    }
1732 	}
1733 
1734 	/* Stop if there is no matching byte. */
1735 	if (hi < lo || byts[lo] != c)
1736 	    break;
1737 
1738 	/* Continue at the child (if there is one). */
1739 	arridx = idxs[lo];
1740 	++wlen;
1741 	--flen;
1742     }
1743 }
1744 
1745 /*
1746  * Need to fold at least one more character.  Do until next non-word character
1747  * for efficiency.
1748  * Return the length of the folded chars in bytes.
1749  */
1750     static int
1751 fold_more(mip)
1752     matchinf_T	*mip;
1753 {
1754     int		flen;
1755     char_u	*p;
1756 
1757     p = mip->mi_fend;
1758     do
1759     {
1760 	mb_ptr_adv(mip->mi_fend);
1761     } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_buf));
1762 
1763     /* Include the non-word character so that we can check for the
1764      * word end. */
1765     if (*mip->mi_fend != NUL)
1766 	mb_ptr_adv(mip->mi_fend);
1767 
1768     (void)spell_casefold(p, (int)(mip->mi_fend - p),
1769 			     mip->mi_fword + mip->mi_fwordlen,
1770 			     MAXWLEN - mip->mi_fwordlen);
1771     flen = STRLEN(mip->mi_fword + mip->mi_fwordlen);
1772     mip->mi_fwordlen += flen;
1773     return flen;
1774 }
1775 
1776 /*
1777  * Check case flags for a word.  Return TRUE if the word has the requested
1778  * case.
1779  */
1780     static int
1781 spell_valid_case(wordflags, treeflags)
1782     int	    wordflags;	    /* flags for the checked word. */
1783     int	    treeflags;	    /* flags for the word in the spell tree */
1784 {
1785     return ((wordflags == WF_ALLCAP && (treeflags & WF_FIXCAP) == 0)
1786 	    || ((treeflags & (WF_ALLCAP | WF_KEEPCAP)) == 0
1787 		&& ((treeflags & WF_ONECAP) == 0
1788 					   || (wordflags & WF_ONECAP) != 0)));
1789 }
1790 
1791 /*
1792  * Return TRUE if spell checking is not enabled.
1793  */
1794     static int
1795 no_spell_checking(wp)
1796     win_T	*wp;
1797 {
1798     if (!wp->w_p_spell || *wp->w_buffer->b_p_spl == NUL)
1799     {
1800 	EMSG(_("E756: Spell checking is not enabled"));
1801 	return TRUE;
1802     }
1803     return FALSE;
1804 }
1805 
1806 /*
1807  * Move to next spell error.
1808  * "curline" is FALSE for "[s", "]s", "[S" and "]S".
1809  * "curline" is TRUE to find word under/after cursor in the same line.
1810  * For Insert mode completion "dir" is BACKWARD and "curline" is TRUE: move
1811  * to after badly spelled word before the cursor.
1812  * Return 0 if not found, length of the badly spelled word otherwise.
1813  */
1814     int
1815 spell_move_to(wp, dir, allwords, curline, attrp)
1816     win_T	*wp;
1817     int		dir;		/* FORWARD or BACKWARD */
1818     int		allwords;	/* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */
1819     int		curline;
1820     hlf_T	*attrp;		/* return: attributes of bad word or NULL
1821 				   (only when "dir" is FORWARD) */
1822 {
1823     linenr_T	lnum;
1824     pos_T	found_pos;
1825     int		found_len = 0;
1826     char_u	*line;
1827     char_u	*p;
1828     char_u	*endp;
1829     hlf_T	attr;
1830     int		len;
1831     int		has_syntax = syntax_present(wp->w_buffer);
1832     int		col;
1833     int		can_spell;
1834     char_u	*buf = NULL;
1835     int		buflen = 0;
1836     int		skip = 0;
1837     int		capcol = -1;
1838     int		found_one = FALSE;
1839     int		wrapped = FALSE;
1840 
1841     if (no_spell_checking(wp))
1842 	return 0;
1843 
1844     /*
1845      * Start looking for bad word at the start of the line, because we can't
1846      * start halfway a word, we don't know where the it starts or ends.
1847      *
1848      * When searching backwards, we continue in the line to find the last
1849      * bad word (in the cursor line: before the cursor).
1850      *
1851      * We concatenate the start of the next line, so that wrapped words work
1852      * (e.g. "et<line-break>cetera").  Doesn't work when searching backwards
1853      * though...
1854      */
1855     lnum = wp->w_cursor.lnum;
1856     found_pos.lnum = 0;
1857 
1858     while (!got_int)
1859     {
1860 	line = ml_get_buf(wp->w_buffer, lnum, FALSE);
1861 
1862 	len = STRLEN(line);
1863 	if (buflen < len + MAXWLEN + 2)
1864 	{
1865 	    vim_free(buf);
1866 	    buflen = len + MAXWLEN + 2;
1867 	    buf = alloc(buflen);
1868 	    if (buf == NULL)
1869 		break;
1870 	}
1871 
1872 	/* In first line check first word for Capital. */
1873 	if (lnum == 1)
1874 	    capcol = 0;
1875 
1876 	/* For checking first word with a capital skip white space. */
1877 	if (capcol == 0)
1878 	    capcol = skipwhite(line) - line;
1879 
1880 	/* Copy the line into "buf" and append the start of the next line if
1881 	 * possible. */
1882 	STRCPY(buf, line);
1883 	if (lnum < wp->w_buffer->b_ml.ml_line_count)
1884 	    spell_cat_line(buf + STRLEN(buf), ml_get(lnum + 1), MAXWLEN);
1885 
1886 	p = buf + skip;
1887 	endp = buf + len;
1888 	while (p < endp)
1889 	{
1890 	    /* When searching backward don't search after the cursor.  Unless
1891 	     * we wrapped around the end of the buffer. */
1892 	    if (dir == BACKWARD
1893 		    && lnum == wp->w_cursor.lnum
1894 		    && !wrapped
1895 		    && (colnr_T)(p - buf) >= wp->w_cursor.col)
1896 		break;
1897 
1898 	    /* start of word */
1899 	    attr = HLF_COUNT;
1900 	    len = spell_check(wp, p, &attr, &capcol);
1901 
1902 	    if (attr != HLF_COUNT)
1903 	    {
1904 		/* We found a bad word.  Check the attribute. */
1905 		if (allwords || attr == HLF_SPB)
1906 		{
1907 		    found_one = TRUE;
1908 
1909 		    /* When searching forward only accept a bad word after
1910 		     * the cursor. */
1911 		    if (dir == BACKWARD
1912 			    || lnum != wp->w_cursor.lnum
1913 			    || (lnum == wp->w_cursor.lnum
1914 				&& (wrapped
1915 				    || (colnr_T)(curline ? p - buf + len
1916 						     : p - buf)
1917 						  > wp->w_cursor.col)))
1918 		    {
1919 			if (has_syntax)
1920 			{
1921 			    col = p - buf;
1922 			    (void)syn_get_id(wp, lnum, (colnr_T)col,
1923 						       FALSE, &can_spell);
1924 			}
1925 			else
1926 			    can_spell = TRUE;
1927 
1928 			if (can_spell)
1929 			{
1930 			    found_pos.lnum = lnum;
1931 			    found_pos.col = p - buf;
1932 #ifdef FEAT_VIRTUALEDIT
1933 			    found_pos.coladd = 0;
1934 #endif
1935 			    if (dir == FORWARD)
1936 			    {
1937 				/* No need to search further. */
1938 				wp->w_cursor = found_pos;
1939 				vim_free(buf);
1940 				if (attrp != NULL)
1941 				    *attrp = attr;
1942 				return len;
1943 			    }
1944 			    else if (curline)
1945 				/* Insert mode completion: put cursor after
1946 				 * the bad word. */
1947 				found_pos.col += len;
1948 			    found_len = len;
1949 			}
1950 		    }
1951 		}
1952 	    }
1953 
1954 	    /* advance to character after the word */
1955 	    p += len;
1956 	    capcol -= len;
1957 	}
1958 
1959 	if (dir == BACKWARD && found_pos.lnum != 0)
1960 	{
1961 	    /* Use the last match in the line (before the cursor). */
1962 	    wp->w_cursor = found_pos;
1963 	    vim_free(buf);
1964 	    return found_len;
1965 	}
1966 
1967 	if (curline)
1968 	    break;	/* only check cursor line */
1969 
1970 	/* Advance to next line. */
1971 	if (dir == BACKWARD)
1972 	{
1973 	    /* If we are back at the starting line and searched it again there
1974 	     * is no match, give up. */
1975 	    if (lnum == wp->w_cursor.lnum && wrapped)
1976 		break;
1977 
1978 	    if (lnum > 1)
1979 		--lnum;
1980 	    else if (!p_ws)
1981 		break;	    /* at first line and 'nowrapscan' */
1982 	    else
1983 	    {
1984 		/* Wrap around to the end of the buffer.  May search the
1985 		 * starting line again and accept the last match. */
1986 		lnum = wp->w_buffer->b_ml.ml_line_count;
1987 		wrapped = TRUE;
1988 		if (!shortmess(SHM_SEARCH))
1989 		    give_warning((char_u *)_(top_bot_msg), TRUE);
1990 	    }
1991 	    capcol = -1;
1992 	}
1993 	else
1994 	{
1995 	    if (lnum < wp->w_buffer->b_ml.ml_line_count)
1996 		++lnum;
1997 	    else if (!p_ws)
1998 		break;	    /* at first line and 'nowrapscan' */
1999 	    else
2000 	    {
2001 		/* Wrap around to the start of the buffer.  May search the
2002 		 * starting line again and accept the first match. */
2003 		lnum = 1;
2004 		wrapped = TRUE;
2005 		if (!shortmess(SHM_SEARCH))
2006 		    give_warning((char_u *)_(bot_top_msg), TRUE);
2007 	    }
2008 
2009 	    /* If we are back at the starting line and there is no match then
2010 	     * give up. */
2011 	    if (lnum == wp->w_cursor.lnum && !found_one)
2012 		break;
2013 
2014 	    /* Skip the characters at the start of the next line that were
2015 	     * included in a match crossing line boundaries. */
2016 	    if (attr == HLF_COUNT)
2017 		skip = p - endp;
2018 	    else
2019 		skip = 0;
2020 
2021 	    /* Capscol skips over the inserted space. */
2022 	    --capcol;
2023 
2024 	    /* But after empty line check first word in next line */
2025 	    if (*skipwhite(line) == NUL)
2026 		capcol = 0;
2027 	}
2028 
2029 	line_breakcheck();
2030     }
2031 
2032     vim_free(buf);
2033     return 0;
2034 }
2035 
2036 /*
2037  * For spell checking: concatenate the start of the following line "line" into
2038  * "buf", blanking-out special characters.  Copy less then "maxlen" bytes.
2039  */
2040     void
2041 spell_cat_line(buf, line, maxlen)
2042     char_u	*buf;
2043     char_u	*line;
2044     int		maxlen;
2045 {
2046     char_u	*p;
2047     int		n;
2048 
2049     p = skipwhite(line);
2050     while (vim_strchr((char_u *)"*#/\"\t", *p) != NULL)
2051 	p = skipwhite(p + 1);
2052 
2053     if (*p != NUL)
2054     {
2055 	*buf = ' ';
2056 	vim_strncpy(buf + 1, line, maxlen - 2);
2057 	n = p - line;
2058 	if (n >= maxlen)
2059 	    n = maxlen - 1;
2060 	vim_memset(buf + 1, ' ', n);
2061     }
2062 }
2063 
2064 typedef struct spelload_S
2065 {
2066     char_u  sl_lang[MAXWLEN + 1];	/* language name */
2067     slang_T *sl_slang;			/* resulting slang_T struct */
2068     int	    sl_nobreak;			/* NOBREAK language found */
2069 } spelload_T;
2070 
2071 /*
2072  * Load word list(s) for "lang" from Vim spell file(s).
2073  * "lang" must be the language without the region: e.g., "en".
2074  */
2075     static void
2076 spell_load_lang(lang)
2077     char_u	*lang;
2078 {
2079     char_u	fname_enc[85];
2080     int		r;
2081     spelload_T	sl;
2082 
2083     /* Copy the language name to pass it to spell_load_cb() as a cookie.
2084      * It's truncated when an error is detected. */
2085     STRCPY(sl.sl_lang, lang);
2086     sl.sl_slang = NULL;
2087     sl.sl_nobreak = FALSE;
2088 
2089     /*
2090      * Find the first spell file for "lang" in 'runtimepath' and load it.
2091      */
2092     vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2093 					"spell/%s.%s.spl", lang, spell_enc());
2094     r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2095 
2096     if (r == FAIL && *sl.sl_lang != NUL)
2097     {
2098 	/* Try loading the ASCII version. */
2099 	vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2100 						  "spell/%s.ascii.spl", lang);
2101 	r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2102     }
2103 
2104     if (r == FAIL)
2105 	smsg((char_u *)_("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""),
2106 						     lang, spell_enc(), lang);
2107     else if (sl.sl_slang != NULL)
2108     {
2109 	/* At least one file was loaded, now load all the additions. */
2110 	STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
2111 	do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl);
2112     }
2113 }
2114 
2115 /*
2116  * Return the encoding used for spell checking: Use 'encoding', except that we
2117  * use "latin1" for "latin9".  And limit to 60 characters (just in case).
2118  */
2119     static char_u *
2120 spell_enc()
2121 {
2122 
2123 #ifdef FEAT_MBYTE
2124     if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0)
2125 	return p_enc;
2126 #endif
2127     return (char_u *)"latin1";
2128 }
2129 
2130 /*
2131  * Get the name of the .spl file for the internal wordlist into
2132  * "fname[MAXPATHL]".
2133  */
2134     static void
2135 int_wordlist_spl(fname)
2136     char_u	    *fname;
2137 {
2138     vim_snprintf((char *)fname, MAXPATHL, "%s.%s.spl",
2139 						  int_wordlist, spell_enc());
2140 }
2141 
2142 /*
2143  * Allocate a new slang_T.
2144  * Caller must fill "sl_next".
2145  */
2146     static slang_T *
2147 slang_alloc(lang)
2148     char_u	*lang;
2149 {
2150     slang_T *lp;
2151 
2152     lp = (slang_T *)alloc_clear(sizeof(slang_T));
2153     if (lp != NULL)
2154     {
2155 	lp->sl_name = vim_strsave(lang);
2156 	ga_init2(&lp->sl_rep, sizeof(fromto_T), 10);
2157 	lp->sl_compmax = MAXWLEN;
2158 	lp->sl_compsylmax = MAXWLEN;
2159     }
2160     return lp;
2161 }
2162 
2163 /*
2164  * Free the contents of an slang_T and the structure itself.
2165  */
2166     static void
2167 slang_free(lp)
2168     slang_T	*lp;
2169 {
2170     vim_free(lp->sl_name);
2171     vim_free(lp->sl_fname);
2172     slang_clear(lp);
2173     vim_free(lp);
2174 }
2175 
2176 /*
2177  * Clear an slang_T so that the file can be reloaded.
2178  */
2179     static void
2180 slang_clear(lp)
2181     slang_T	*lp;
2182 {
2183     garray_T	*gap;
2184     fromto_T	*ftp;
2185     salitem_T	*smp;
2186     int		i;
2187 
2188     vim_free(lp->sl_fbyts);
2189     lp->sl_fbyts = NULL;
2190     vim_free(lp->sl_kbyts);
2191     lp->sl_kbyts = NULL;
2192     vim_free(lp->sl_pbyts);
2193     lp->sl_pbyts = NULL;
2194 
2195     vim_free(lp->sl_fidxs);
2196     lp->sl_fidxs = NULL;
2197     vim_free(lp->sl_kidxs);
2198     lp->sl_kidxs = NULL;
2199     vim_free(lp->sl_pidxs);
2200     lp->sl_pidxs = NULL;
2201 
2202     gap = &lp->sl_rep;
2203     while (gap->ga_len > 0)
2204     {
2205 	ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len];
2206 	vim_free(ftp->ft_from);
2207 	vim_free(ftp->ft_to);
2208     }
2209     ga_clear(gap);
2210 
2211     gap = &lp->sl_sal;
2212     if (lp->sl_sofo)
2213     {
2214 	/* "ga_len" is set to 1 without adding an item for latin1 */
2215 	if (gap->ga_data != NULL)
2216 	    /* SOFOFROM and SOFOTO items: free lists of wide characters. */
2217 	    for (i = 0; i < gap->ga_len; ++i)
2218 		vim_free(((int **)gap->ga_data)[i]);
2219     }
2220     else
2221 	/* SAL items: free salitem_T items */
2222 	while (gap->ga_len > 0)
2223 	{
2224 	    smp = &((salitem_T *)gap->ga_data)[--gap->ga_len];
2225 	    vim_free(smp->sm_lead);
2226 	    /* Don't free sm_oneof and sm_rules, they point into sm_lead. */
2227 	    vim_free(smp->sm_to);
2228 #ifdef FEAT_MBYTE
2229 	    vim_free(smp->sm_lead_w);
2230 	    vim_free(smp->sm_oneof_w);
2231 	    vim_free(smp->sm_to_w);
2232 #endif
2233 	}
2234     ga_clear(gap);
2235 
2236     for (i = 0; i < lp->sl_prefixcnt; ++i)
2237 	vim_free(lp->sl_prefprog[i]);
2238     lp->sl_prefixcnt = 0;
2239     vim_free(lp->sl_prefprog);
2240     lp->sl_prefprog = NULL;
2241 
2242     vim_free(lp->sl_midword);
2243     lp->sl_midword = NULL;
2244 
2245     vim_free(lp->sl_compprog);
2246     vim_free(lp->sl_compstartflags);
2247     vim_free(lp->sl_compallflags);
2248     lp->sl_compprog = NULL;
2249     lp->sl_compstartflags = NULL;
2250     lp->sl_compallflags = NULL;
2251 
2252     vim_free(lp->sl_syllable);
2253     lp->sl_syllable = NULL;
2254     ga_clear(&lp->sl_syl_items);
2255 
2256 #ifdef FEAT_MBYTE
2257     {
2258 	int	    todo = lp->sl_map_hash.ht_used;
2259 	hashitem_T  *hi;
2260 
2261 	for (hi = lp->sl_map_hash.ht_array; todo > 0; ++hi)
2262 	    if (!HASHITEM_EMPTY(hi))
2263 	    {
2264 		--todo;
2265 		vim_free(hi->hi_key);
2266 	    }
2267     }
2268     hash_clear(&lp->sl_map_hash);
2269 #endif
2270 
2271     lp->sl_compmax = MAXWLEN;
2272     lp->sl_compminlen = 0;
2273     lp->sl_compsylmax = MAXWLEN;
2274     lp->sl_regions[0] = NUL;
2275 }
2276 
2277 /*
2278  * Load one spell file and store the info into a slang_T.
2279  * Invoked through do_in_runtimepath().
2280  */
2281     static void
2282 spell_load_cb(fname, cookie)
2283     char_u	*fname;
2284     void	*cookie;
2285 {
2286     spelload_T	*slp = (spelload_T *)cookie;
2287     slang_T	*slang;
2288 
2289     slang = spell_load_file(fname, slp->sl_lang, NULL, FALSE);
2290     if (slang != NULL)
2291     {
2292 	/* When a previously loaded file has NOBREAK also use it for the
2293 	 * ".add" files. */
2294 	if (slp->sl_nobreak && slang->sl_add)
2295 	    slang->sl_nobreak = TRUE;
2296 	else if (slang->sl_nobreak)
2297 	    slp->sl_nobreak = TRUE;
2298 
2299 	slp->sl_slang = slang;
2300     }
2301 }
2302 
2303 /*
2304  * Load one spell file and store the info into a slang_T.
2305  *
2306  * This is invoked in two ways:
2307  * - From spell_load_cb() to load a spell file for the first time.  "lang" is
2308  *   the language name, "old_lp" is NULL.  Will allocate an slang_T.
2309  * - To reload a spell file that was changed.  "lang" is NULL and "old_lp"
2310  *   points to the existing slang_T.
2311  * Returns the slang_T the spell file was loaded into.  NULL for error.
2312  */
2313     static slang_T *
2314 spell_load_file(fname, lang, old_lp, silent)
2315     char_u	*fname;
2316     char_u	*lang;
2317     slang_T	*old_lp;
2318     int		silent;		/* no error if file doesn't exist */
2319 {
2320     FILE	*fd;
2321     char_u	buf[VIMSPELLMAGICL];
2322     char_u	*p;
2323     char_u	*bp;
2324     idx_T	*ip;
2325     int		i;
2326     int		n;
2327     int		len;
2328     int		round;
2329     char_u	*save_sourcing_name = sourcing_name;
2330     linenr_T	save_sourcing_lnum = sourcing_lnum;
2331     slang_T	*lp = NULL;
2332     idx_T	idx;
2333     int		c = 0;
2334     int		res;
2335 
2336     fd = mch_fopen((char *)fname, "r");
2337     if (fd == NULL)
2338     {
2339 	if (!silent)
2340 	    EMSG2(_(e_notopen), fname);
2341 	else if (p_verbose > 2)
2342 	{
2343 	    verbose_enter();
2344 	    smsg((char_u *)e_notopen, fname);
2345 	    verbose_leave();
2346 	}
2347 	goto endFAIL;
2348     }
2349     if (p_verbose > 2)
2350     {
2351 	verbose_enter();
2352 	smsg((char_u *)_("Reading spell file \"%s\""), fname);
2353 	verbose_leave();
2354     }
2355 
2356     if (old_lp == NULL)
2357     {
2358 	lp = slang_alloc(lang);
2359 	if (lp == NULL)
2360 	    goto endFAIL;
2361 
2362 	/* Remember the file name, used to reload the file when it's updated. */
2363 	lp->sl_fname = vim_strsave(fname);
2364 	if (lp->sl_fname == NULL)
2365 	    goto endFAIL;
2366 
2367 	/* Check for .add.spl. */
2368 	lp->sl_add = strstr((char *)gettail(fname), ".add.") != NULL;
2369     }
2370     else
2371 	lp = old_lp;
2372 
2373     /* Set sourcing_name, so that error messages mention the file name. */
2374     sourcing_name = fname;
2375     sourcing_lnum = 0;
2376 
2377     /* <HEADER>: <fileID>
2378      */
2379     for (i = 0; i < VIMSPELLMAGICL; ++i)
2380 	buf[i] = getc(fd);				/* <fileID> */
2381     if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0)
2382     {
2383 	EMSG(_("E757: This does not look like a spell file"));
2384 	goto endFAIL;
2385     }
2386     c = getc(fd);					/* <versionnr> */
2387     if (c < VIMSPELLVERSION)
2388     {
2389 	EMSG(_("E771: Old spell file, needs to be updated"));
2390 	goto endFAIL;
2391     }
2392     else if (c > VIMSPELLVERSION)
2393     {
2394 	EMSG(_("E772: Spell file is for newer version of Vim"));
2395 	goto endFAIL;
2396     }
2397 
2398 
2399     /*
2400      * <SECTIONS>: <section> ... <sectionend>
2401      * <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
2402      */
2403     for (;;)
2404     {
2405 	n = getc(fd);			    /* <sectionID> or <sectionend> */
2406 	if (n == SN_END)
2407 	    break;
2408 	c = getc(fd);					/* <sectionflags> */
2409 	len = (getc(fd) << 24) + (getc(fd) << 16) + (getc(fd) << 8) + getc(fd);
2410 							/* <sectionlen> */
2411 	if (len < 0)
2412 	    goto truncerr;
2413 
2414 	res = 0;
2415 	switch (n)
2416 	{
2417 	    case SN_REGION:
2418 		res = read_region_section(fd, lp, len);
2419 		break;
2420 
2421 	    case SN_CHARFLAGS:
2422 		res = read_charflags_section(fd);
2423 		break;
2424 
2425 	    case SN_MIDWORD:
2426 		lp->sl_midword = read_string(fd, len);	/* <midword> */
2427 		if (lp->sl_midword == NULL)
2428 		    goto endFAIL;
2429 		break;
2430 
2431 	    case SN_PREFCOND:
2432 		res = read_prefcond_section(fd, lp);
2433 		break;
2434 
2435 	    case SN_REP:
2436 		res = read_rep_section(fd, lp);
2437 		break;
2438 
2439 	    case SN_SAL:
2440 		res = read_sal_section(fd, lp);
2441 		break;
2442 
2443 	    case SN_SOFO:
2444 		res = read_sofo_section(fd, lp);
2445 		break;
2446 
2447 	    case SN_MAP:
2448 		p = read_string(fd, len);		/* <mapstr> */
2449 		if (p == NULL)
2450 		    goto endFAIL;
2451 		set_map_str(lp, p);
2452 		vim_free(p);
2453 		break;
2454 
2455 	    case SN_COMPOUND:
2456 		res = read_compound(fd, lp, len);
2457 		break;
2458 
2459 	    case SN_NOBREAK:
2460 		lp->sl_nobreak = TRUE;
2461 		break;
2462 
2463 	    case SN_SYLLABLE:
2464 		lp->sl_syllable = read_string(fd, len);	/* <syllable> */
2465 		if (lp->sl_syllable == NULL)
2466 		    goto endFAIL;
2467 		if (init_syl_tab(lp) == FAIL)
2468 		    goto endFAIL;
2469 		break;
2470 
2471 	    default:
2472 		/* Unsupported section.  When it's required give an error
2473 		 * message.  When it's not required skip the contents. */
2474 		if (c & SNF_REQUIRED)
2475 		{
2476 		    EMSG(_("E770: Unsupported section in spell file"));
2477 		    goto endFAIL;
2478 		}
2479 		while (--len >= 0)
2480 		    if (getc(fd) < 0)
2481 			goto truncerr;
2482 		break;
2483 	}
2484 	if (res == SP_FORMERROR)
2485 	{
2486 formerr:
2487 	    EMSG(_(e_format));
2488 	    goto endFAIL;
2489 	}
2490 	if (res == SP_TRUNCERROR)
2491 	{
2492 truncerr:
2493 	    EMSG(_(e_spell_trunc));
2494 	    goto endFAIL;
2495 	}
2496 	if (res == SP_OTHERERROR)
2497 	    goto endFAIL;
2498     }
2499 
2500     /* round 1: <LWORDTREE>
2501      * round 2: <KWORDTREE>
2502      * round 3: <PREFIXTREE> */
2503     for (round = 1; round <= 3; ++round)
2504     {
2505 	/* The tree size was computed when writing the file, so that we can
2506 	 * allocate it as one long block. <nodecount> */
2507 	len = (getc(fd) << 24) + (getc(fd) << 16) + (getc(fd) << 8) + getc(fd);
2508 	if (len < 0)
2509 	    goto truncerr;
2510 	if (len > 0)
2511 	{
2512 	    /* Allocate the byte array. */
2513 	    bp = lalloc((long_u)len, TRUE);
2514 	    if (bp == NULL)
2515 		goto endFAIL;
2516 	    if (round == 1)
2517 		lp->sl_fbyts = bp;
2518 	    else if (round == 2)
2519 		lp->sl_kbyts = bp;
2520 	    else
2521 		lp->sl_pbyts = bp;
2522 
2523 	    /* Allocate the index array. */
2524 	    ip = (idx_T *)lalloc_clear((long_u)(len * sizeof(int)), TRUE);
2525 	    if (ip == NULL)
2526 		goto endFAIL;
2527 	    if (round == 1)
2528 		lp->sl_fidxs = ip;
2529 	    else if (round == 2)
2530 		lp->sl_kidxs = ip;
2531 	    else
2532 		lp->sl_pidxs = ip;
2533 
2534 	    /* Read the tree and store it in the array. */
2535 	    idx = read_tree(fd, bp, ip, len, 0, round == 3, lp->sl_prefixcnt);
2536 	    if (idx == -1)
2537 		goto truncerr;
2538 	    if (idx < 0)
2539 		goto formerr;
2540 	}
2541     }
2542 
2543     /* For a new file link it in the list of spell files. */
2544     if (old_lp == NULL)
2545     {
2546 	lp->sl_next = first_lang;
2547 	first_lang = lp;
2548     }
2549 
2550     goto endOK;
2551 
2552 endFAIL:
2553     if (lang != NULL)
2554 	/* truncating the name signals the error to spell_load_lang() */
2555 	*lang = NUL;
2556     if (lp != NULL && old_lp == NULL)
2557 	slang_free(lp);
2558     lp = NULL;
2559 
2560 endOK:
2561     if (fd != NULL)
2562 	fclose(fd);
2563     sourcing_name = save_sourcing_name;
2564     sourcing_lnum = save_sourcing_lnum;
2565 
2566     return lp;
2567 }
2568 
2569 /*
2570  * Read a length field from "fd" in "cnt_bytes" bytes.
2571  * Allocate memory, read the string into it and add a NUL at the end.
2572  * Returns NULL when the count is zero.
2573  * Sets "*cntp" to SP_*ERROR when there is an error, length of the result
2574  * otherwise.
2575  */
2576     static char_u *
2577 read_cnt_string(fd, cnt_bytes, cntp)
2578     FILE	*fd;
2579     int		cnt_bytes;
2580     int		*cntp;
2581 {
2582     int		cnt = 0;
2583     int		i;
2584     char_u	*str;
2585 
2586     /* read the length bytes, MSB first */
2587     for (i = 0; i < cnt_bytes; ++i)
2588 	cnt = (cnt << 8) + getc(fd);
2589     if (cnt < 0)
2590     {
2591 	*cntp = SP_TRUNCERROR;
2592 	return NULL;
2593     }
2594     *cntp = cnt;
2595     if (cnt == 0)
2596 	return NULL;	    /* nothing to read, return NULL */
2597 
2598     str = read_string(fd, cnt);
2599     if (str == NULL)
2600 	*cntp = SP_OTHERERROR;
2601     return str;
2602 }
2603 
2604 /*
2605  * Read a string of length "cnt" from "fd" into allocated memory.
2606  * Returns NULL when out of memory.
2607  */
2608     static char_u *
2609 read_string(fd, cnt)
2610     FILE	*fd;
2611     int		cnt;
2612 {
2613     char_u	*str;
2614     int		i;
2615 
2616     /* allocate memory */
2617     str = alloc((unsigned)cnt + 1);
2618     if (str != NULL)
2619     {
2620 	/* Read the string.  Doesn't check for truncated file. */
2621 	for (i = 0; i < cnt; ++i)
2622 	    str[i] = getc(fd);
2623 	str[i] = NUL;
2624     }
2625     return str;
2626 }
2627 
2628 /*
2629  * Read SN_REGION: <regionname> ...
2630  * Return SP_*ERROR flags.
2631  */
2632     static int
2633 read_region_section(fd, lp, len)
2634     FILE	*fd;
2635     slang_T	*lp;
2636     int		len;
2637 {
2638     int		i;
2639 
2640     if (len > 16)
2641 	return SP_FORMERROR;
2642     for (i = 0; i < len; ++i)
2643 	lp->sl_regions[i] = getc(fd);			/* <regionname> */
2644     lp->sl_regions[len] = NUL;
2645     return 0;
2646 }
2647 
2648 /*
2649  * Read SN_CHARFLAGS section: <charflagslen> <charflags>
2650  *				<folcharslen> <folchars>
2651  * Return SP_*ERROR flags.
2652  */
2653     static int
2654 read_charflags_section(fd)
2655     FILE	*fd;
2656 {
2657     char_u	*flags;
2658     char_u	*fol;
2659     int		flagslen, follen;
2660 
2661     /* <charflagslen> <charflags> */
2662     flags = read_cnt_string(fd, 1, &flagslen);
2663     if (flagslen < 0)
2664 	return flagslen;
2665 
2666     /* <folcharslen> <folchars> */
2667     fol = read_cnt_string(fd, 2, &follen);
2668     if (follen < 0)
2669     {
2670 	vim_free(flags);
2671 	return follen;
2672     }
2673 
2674     /* Set the word-char flags and fill SPELL_ISUPPER() table. */
2675     if (flags != NULL && fol != NULL)
2676 	set_spell_charflags(flags, flagslen, fol);
2677 
2678     vim_free(flags);
2679     vim_free(fol);
2680 
2681     /* When <charflagslen> is zero then <fcharlen> must also be zero. */
2682     if ((flags == NULL) != (fol == NULL))
2683 	return SP_FORMERROR;
2684     return 0;
2685 }
2686 
2687 /*
2688  * Read SN_PREFCOND section.
2689  * Return SP_*ERROR flags.
2690  */
2691     static int
2692 read_prefcond_section(fd, lp)
2693     FILE	*fd;
2694     slang_T	*lp;
2695 {
2696     int		cnt;
2697     int		i;
2698     int		n;
2699     char_u	*p;
2700     char_u	buf[MAXWLEN + 1];
2701 
2702     /* <prefcondcnt> <prefcond> ... */
2703     cnt = (getc(fd) << 8) + getc(fd);			/* <prefcondcnt> */
2704     if (cnt <= 0)
2705 	return SP_FORMERROR;
2706 
2707     lp->sl_prefprog = (regprog_T **)alloc_clear(
2708 					 (unsigned)sizeof(regprog_T *) * cnt);
2709     if (lp->sl_prefprog == NULL)
2710 	return SP_OTHERERROR;
2711     lp->sl_prefixcnt = cnt;
2712 
2713     for (i = 0; i < cnt; ++i)
2714     {
2715 	/* <prefcond> : <condlen> <condstr> */
2716 	n = getc(fd);					/* <condlen> */
2717 	if (n < 0 || n >= MAXWLEN)
2718 	    return SP_FORMERROR;
2719 
2720 	/* When <condlen> is zero we have an empty condition.  Otherwise
2721 	 * compile the regexp program used to check for the condition. */
2722 	if (n > 0)
2723 	{
2724 	    buf[0] = '^';	    /* always match at one position only */
2725 	    p = buf + 1;
2726 	    while (n-- > 0)
2727 		*p++ = getc(fd);			/* <condstr> */
2728 	    *p = NUL;
2729 	    lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING);
2730 	}
2731     }
2732     return 0;
2733 }
2734 
2735 /*
2736  * Read REP items section from "fd": <repcount> <rep> ...
2737  * Return SP_*ERROR flags.
2738  */
2739     static int
2740 read_rep_section(fd, slang)
2741     FILE	*fd;
2742     slang_T	*slang;
2743 {
2744     int		cnt;
2745     garray_T	*gap;
2746     fromto_T	*ftp;
2747     short	*first;
2748     int		i;
2749 
2750     cnt = (getc(fd) << 8) + getc(fd);			/* <repcount> */
2751     if (cnt < 0)
2752 	return SP_TRUNCERROR;
2753 
2754     gap = &slang->sl_rep;
2755     if (ga_grow(gap, cnt) == FAIL)
2756 	return SP_OTHERERROR;
2757 
2758     /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
2759     for (; gap->ga_len < cnt; ++gap->ga_len)
2760     {
2761 	ftp = &((fromto_T *)gap->ga_data)[gap->ga_len];
2762 	ftp->ft_from = read_cnt_string(fd, 1, &i);
2763 	if (i < 0)
2764 	    return i;
2765 	if (i == 0)
2766 	    return SP_FORMERROR;
2767 	ftp->ft_to = read_cnt_string(fd, 1, &i);
2768 	if (i <= 0)
2769 	{
2770 	    vim_free(ftp->ft_from);
2771 	    if (i < 0)
2772 		return i;
2773 	    return SP_FORMERROR;
2774 	}
2775     }
2776 
2777     /* Fill the first-index table. */
2778     first = slang->sl_rep_first;
2779     for (i = 0; i < 256; ++i)
2780 	first[i] = -1;
2781     for (i = 0; i < gap->ga_len; ++i)
2782     {
2783 	ftp = &((fromto_T *)gap->ga_data)[i];
2784 	if (first[*ftp->ft_from] == -1)
2785 	    first[*ftp->ft_from] = i;
2786     }
2787     return 0;
2788 }
2789 
2790 /*
2791  * Read SN_SAL section: <salflags> <salcount> <sal> ...
2792  * Return SP_*ERROR flags.
2793  */
2794     static int
2795 read_sal_section(fd, slang)
2796     FILE	*fd;
2797     slang_T	*slang;
2798 {
2799     int		i;
2800     int		cnt;
2801     garray_T	*gap;
2802     salitem_T	*smp;
2803     int		ccnt;
2804     char_u	*p;
2805     int		c = NUL;
2806 
2807     slang->sl_sofo = FALSE;
2808 
2809     i = getc(fd);				/* <salflags> */
2810     if (i & SAL_F0LLOWUP)
2811 	slang->sl_followup = TRUE;
2812     if (i & SAL_COLLAPSE)
2813 	slang->sl_collapse = TRUE;
2814     if (i & SAL_REM_ACCENTS)
2815 	slang->sl_rem_accents = TRUE;
2816 
2817     cnt = (getc(fd) << 8) + getc(fd);		/* <salcount> */
2818     if (cnt < 0)
2819 	return SP_TRUNCERROR;
2820 
2821     gap = &slang->sl_sal;
2822     ga_init2(gap, sizeof(salitem_T), 10);
2823     if (ga_grow(gap, cnt + 1) == FAIL)
2824 	return SP_OTHERERROR;
2825 
2826     /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
2827     for (; gap->ga_len < cnt; ++gap->ga_len)
2828     {
2829 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
2830 	ccnt = getc(fd);			/* <salfromlen> */
2831 	if (ccnt < 0)
2832 	    return SP_TRUNCERROR;
2833 	if ((p = alloc(ccnt + 2)) == NULL)
2834 	    return SP_OTHERERROR;
2835 	smp->sm_lead = p;
2836 
2837 	/* Read up to the first special char into sm_lead. */
2838 	for (i = 0; i < ccnt; ++i)
2839 	{
2840 	    c = getc(fd);			/* <salfrom> */
2841 	    if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL)
2842 		break;
2843 	    *p++ = c;
2844 	}
2845 	smp->sm_leadlen = p - smp->sm_lead;
2846 	*p++ = NUL;
2847 
2848 	/* Put (abc) chars in sm_oneof, if any. */
2849 	if (c == '(')
2850 	{
2851 	    smp->sm_oneof = p;
2852 	    for (++i; i < ccnt; ++i)
2853 	    {
2854 		c = getc(fd);			/* <salfrom> */
2855 		if (c == ')')
2856 		    break;
2857 		*p++ = c;
2858 	    }
2859 	    *p++ = NUL;
2860 	    if (++i < ccnt)
2861 		c = getc(fd);
2862 	}
2863 	else
2864 	    smp->sm_oneof = NULL;
2865 
2866 	/* Any following chars go in sm_rules. */
2867 	smp->sm_rules = p;
2868 	if (i < ccnt)
2869 	    /* store the char we got while checking for end of sm_lead */
2870 	    *p++ = c;
2871 	for (++i; i < ccnt; ++i)
2872 	    *p++ = getc(fd);			/* <salfrom> */
2873 	*p++ = NUL;
2874 
2875 	/* <saltolen> <salto> */
2876 	smp->sm_to = read_cnt_string(fd, 1, &ccnt);
2877 	if (ccnt < 0)
2878 	{
2879 	    vim_free(smp->sm_lead);
2880 	    return ccnt;
2881 	}
2882 
2883 #ifdef FEAT_MBYTE
2884 	if (has_mbyte)
2885 	{
2886 	    /* convert the multi-byte strings to wide char strings */
2887 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
2888 	    smp->sm_leadlen = mb_charlen(smp->sm_lead);
2889 	    if (smp->sm_oneof == NULL)
2890 		smp->sm_oneof_w = NULL;
2891 	    else
2892 		smp->sm_oneof_w = mb_str2wide(smp->sm_oneof);
2893 	    if (smp->sm_to == NULL)
2894 		smp->sm_to_w = NULL;
2895 	    else
2896 		smp->sm_to_w = mb_str2wide(smp->sm_to);
2897 	    if (smp->sm_lead_w == NULL
2898 		    || (smp->sm_oneof_w == NULL && smp->sm_oneof != NULL)
2899 		    || (smp->sm_to_w == NULL && smp->sm_to != NULL))
2900 	    {
2901 		vim_free(smp->sm_lead);
2902 		vim_free(smp->sm_to);
2903 		vim_free(smp->sm_lead_w);
2904 		vim_free(smp->sm_oneof_w);
2905 		vim_free(smp->sm_to_w);
2906 		return SP_OTHERERROR;
2907 	    }
2908 	}
2909 #endif
2910     }
2911 
2912     if (gap->ga_len > 0)
2913     {
2914 	/* Add one extra entry to mark the end with an empty sm_lead.  Avoids
2915 	 * that we need to check the index every time. */
2916 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
2917 	if ((p = alloc(1)) == NULL)
2918 	    return SP_OTHERERROR;
2919 	p[0] = NUL;
2920 	smp->sm_lead = p;
2921 	smp->sm_leadlen = 0;
2922 	smp->sm_oneof = NULL;
2923 	smp->sm_rules = p;
2924 	smp->sm_to = NULL;
2925 #ifdef FEAT_MBYTE
2926 	if (has_mbyte)
2927 	{
2928 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
2929 	    smp->sm_leadlen = 0;
2930 	    smp->sm_oneof_w = NULL;
2931 	    smp->sm_to_w = NULL;
2932 	}
2933 #endif
2934 	++gap->ga_len;
2935     }
2936 
2937     /* Fill the first-index table. */
2938     set_sal_first(slang);
2939 
2940     return 0;
2941 }
2942 
2943 /*
2944  * SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
2945  * Return SP_*ERROR flags.
2946  */
2947     static int
2948 read_sofo_section(fd, slang)
2949     FILE	*fd;
2950     slang_T	*slang;
2951 {
2952     int		cnt;
2953     char_u	*from, *to;
2954     int		res;
2955 
2956     slang->sl_sofo = TRUE;
2957 
2958     /* <sofofromlen> <sofofrom> */
2959     from = read_cnt_string(fd, 2, &cnt);
2960     if (cnt < 0)
2961 	return cnt;
2962 
2963     /* <sofotolen> <sofoto> */
2964     to = read_cnt_string(fd, 2, &cnt);
2965     if (cnt < 0)
2966     {
2967 	vim_free(from);
2968 	return cnt;
2969     }
2970 
2971     /* Store the info in slang->sl_sal and/or slang->sl_sal_first. */
2972     if (from != NULL && to != NULL)
2973 	res = set_sofo(slang, from, to);
2974     else if (from != NULL || to != NULL)
2975 	res = SP_FORMERROR;    /* only one of two strings is an error */
2976     else
2977 	res = 0;
2978 
2979     vim_free(from);
2980     vim_free(to);
2981     return res;
2982 }
2983 
2984 /*
2985  * Read the compound section from the .spl file:
2986  *	<compmax> <compminlen> <compsylmax> <compflags>
2987  * Returns SP_*ERROR flags.
2988  */
2989     static int
2990 read_compound(fd, slang, len)
2991     FILE	*fd;
2992     slang_T	*slang;
2993     int		len;
2994 {
2995     int		todo = len;
2996     int		c;
2997     int		atstart;
2998     char_u	*pat;
2999     char_u	*pp;
3000     char_u	*cp;
3001     char_u	*ap;
3002 
3003     if (todo < 2)
3004 	return SP_FORMERROR;	/* need at least two bytes */
3005 
3006     --todo;
3007     c = getc(fd);					/* <compmax> */
3008     if (c < 2)
3009 	c = MAXWLEN;
3010     slang->sl_compmax = c;
3011 
3012     --todo;
3013     c = getc(fd);					/* <compminlen> */
3014     if (c < 1)
3015 	c = 0;
3016     slang->sl_compminlen = c;
3017 
3018     --todo;
3019     c = getc(fd);					/* <compsylmax> */
3020     if (c < 1)
3021 	c = MAXWLEN;
3022     slang->sl_compsylmax = c;
3023 
3024     /* Turn the COMPOUNDFLAGS items into a regexp pattern:
3025      * "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$".
3026      * Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes.
3027      * Conversion to utf-8 may double the size. */
3028     c = todo * 2 + 7;
3029 #ifdef FEAT_MBYTE
3030     if (enc_utf8)
3031 	c += todo * 2;
3032 #endif
3033     pat = alloc((unsigned)c);
3034     if (pat == NULL)
3035 	return SP_OTHERERROR;
3036 
3037     /* We also need a list of all flags that can appear at the start and one
3038      * for all flags. */
3039     cp = alloc(todo + 1);
3040     if (cp == NULL)
3041     {
3042 	vim_free(pat);
3043 	return SP_OTHERERROR;
3044     }
3045     slang->sl_compstartflags = cp;
3046     *cp = NUL;
3047 
3048     ap = alloc(todo + 1);
3049     if (ap == NULL)
3050     {
3051 	vim_free(pat);
3052 	return SP_OTHERERROR;
3053     }
3054     slang->sl_compallflags = ap;
3055     *ap = NUL;
3056 
3057     pp = pat;
3058     *pp++ = '^';
3059     *pp++ = '\\';
3060     *pp++ = '(';
3061 
3062     atstart = 1;
3063     while (todo-- > 0)
3064     {
3065 	c = getc(fd);					/* <compflags> */
3066 
3067 	/* Add all flags to "sl_compallflags". */
3068 	if (vim_strchr((char_u *)"+*[]/", c) == NULL
3069 		&& !byte_in_str(slang->sl_compallflags, c))
3070 	{
3071 	    *ap++ = c;
3072 	    *ap = NUL;
3073 	}
3074 
3075 	if (atstart != 0)
3076 	{
3077 	    /* At start of item: copy flags to "sl_compstartflags".  For a
3078 	     * [abc] item set "atstart" to 2 and copy up to the ']'. */
3079 	    if (c == '[')
3080 		atstart = 2;
3081 	    else if (c == ']')
3082 		atstart = 0;
3083 	    else
3084 	    {
3085 		if (!byte_in_str(slang->sl_compstartflags, c))
3086 		{
3087 		    *cp++ = c;
3088 		    *cp = NUL;
3089 		}
3090 		if (atstart == 1)
3091 		    atstart = 0;
3092 	    }
3093 	}
3094 	if (c == '/')	    /* slash separates two items */
3095 	{
3096 	    *pp++ = '\\';
3097 	    *pp++ = '|';
3098 	    atstart = 1;
3099 	}
3100 	else		    /* normal char, "[abc]" and '*' are copied as-is */
3101 	{
3102 	    if (c == '+' || c == '~')
3103 		*pp++ = '\\';	    /* "a+" becomes "a\+" */
3104 #ifdef FEAT_MBYTE
3105 	    if (enc_utf8)
3106 		pp += mb_char2bytes(c, pp);
3107 	    else
3108 #endif
3109 		*pp++ = c;
3110 	}
3111     }
3112 
3113     *pp++ = '\\';
3114     *pp++ = ')';
3115     *pp++ = '$';
3116     *pp = NUL;
3117 
3118     slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
3119     vim_free(pat);
3120     if (slang->sl_compprog == NULL)
3121 	return SP_FORMERROR;
3122 
3123     return 0;
3124 }
3125 
3126 /*
3127  * Return TRUE if byte "n" appears in "str".
3128  * Like strchr() but independent of locale.
3129  */
3130     static int
3131 byte_in_str(str, n)
3132     char_u	*str;
3133     int		n;
3134 {
3135     char_u	*p;
3136 
3137     for (p = str; *p != NUL; ++p)
3138 	if (*p == n)
3139 	    return TRUE;
3140     return FALSE;
3141 }
3142 
3143 #define SY_MAXLEN   30
3144 typedef struct syl_item_S
3145 {
3146     char_u	sy_chars[SY_MAXLEN];	    /* the sequence of chars */
3147     int		sy_len;
3148 } syl_item_T;
3149 
3150 /*
3151  * Truncate "slang->sl_syllable" at the first slash and put the following items
3152  * in "slang->sl_syl_items".
3153  */
3154     static int
3155 init_syl_tab(slang)
3156     slang_T	*slang;
3157 {
3158     char_u	*p;
3159     char_u	*s;
3160     int		l;
3161     syl_item_T	*syl;
3162 
3163     ga_init2(&slang->sl_syl_items, sizeof(syl_item_T), 4);
3164     p = vim_strchr(slang->sl_syllable, '/');
3165     while (p != NULL)
3166     {
3167 	*p++ = NUL;
3168 	if (*p == NUL)	    /* trailing slash */
3169 	    break;
3170 	s = p;
3171 	p = vim_strchr(p, '/');
3172 	if (p == NULL)
3173 	    l = STRLEN(s);
3174 	else
3175 	    l = p - s;
3176 	if (l >= SY_MAXLEN)
3177 	    return SP_FORMERROR;
3178 	if (ga_grow(&slang->sl_syl_items, 1) == FAIL)
3179 	    return SP_OTHERERROR;
3180 	syl = ((syl_item_T *)slang->sl_syl_items.ga_data)
3181 					       + slang->sl_syl_items.ga_len++;
3182 	vim_strncpy(syl->sy_chars, s, l);
3183 	syl->sy_len = l;
3184     }
3185     return OK;
3186 }
3187 
3188 /*
3189  * Count the number of syllables in "word".
3190  * When "word" contains spaces the syllables after the last space are counted.
3191  * Returns zero if syllables are not defines.
3192  */
3193     static int
3194 count_syllables(slang, word)
3195     slang_T	*slang;
3196     char_u	*word;
3197 {
3198     int		cnt = 0;
3199     int		skip = FALSE;
3200     char_u	*p;
3201     int		len;
3202     int		i;
3203     syl_item_T	*syl;
3204     int		c;
3205 
3206     if (slang->sl_syllable == NULL)
3207 	return 0;
3208 
3209     for (p = word; *p != NUL; p += len)
3210     {
3211 	/* When running into a space reset counter. */
3212 	if (*p == ' ')
3213 	{
3214 	    len = 1;
3215 	    cnt = 0;
3216 	    continue;
3217 	}
3218 
3219 	/* Find longest match of syllable items. */
3220 	len = 0;
3221 	for (i = 0; i < slang->sl_syl_items.ga_len; ++i)
3222 	{
3223 	    syl = ((syl_item_T *)slang->sl_syl_items.ga_data) + i;
3224 	    if (syl->sy_len > len
3225 			       && STRNCMP(p, syl->sy_chars, syl->sy_len) == 0)
3226 		len = syl->sy_len;
3227 	}
3228 	if (len != 0)	/* found a match, count syllable  */
3229 	{
3230 	    ++cnt;
3231 	    skip = FALSE;
3232 	}
3233 	else
3234 	{
3235 	    /* No recognized syllable item, at least a syllable char then? */
3236 #ifdef FEAT_MBYTE
3237 	    c = mb_ptr2char(p);
3238 	    len = (*mb_ptr2len)(p);
3239 #else
3240 	    c = *p;
3241 	    len = 1;
3242 #endif
3243 	    if (vim_strchr(slang->sl_syllable, c) == NULL)
3244 		skip = FALSE;	    /* No, search for next syllable */
3245 	    else if (!skip)
3246 	    {
3247 		++cnt;		    /* Yes, count it */
3248 		skip = TRUE;	    /* don't count following syllable chars */
3249 	    }
3250 	}
3251     }
3252     return cnt;
3253 }
3254 
3255 /*
3256  * Set the SOFOFROM and SOFOTO items in language "lp".
3257  * Returns SP_*ERROR flags when there is something wrong.
3258  */
3259     static int
3260 set_sofo(lp, from, to)
3261     slang_T	*lp;
3262     char_u	*from;
3263     char_u	*to;
3264 {
3265     int		i;
3266 
3267 #ifdef FEAT_MBYTE
3268     garray_T	*gap;
3269     char_u	*s;
3270     char_u	*p;
3271     int		c;
3272     int		*inp;
3273 
3274     if (has_mbyte)
3275     {
3276 	/* Use "sl_sal" as an array with 256 pointers to a list of wide
3277 	 * characters.  The index is the low byte of the character.
3278 	 * The list contains from-to pairs with a terminating NUL.
3279 	 * sl_sal_first[] is used for latin1 "from" characters. */
3280 	gap = &lp->sl_sal;
3281 	ga_init2(gap, sizeof(int *), 1);
3282 	if (ga_grow(gap, 256) == FAIL)
3283 	    return SP_OTHERERROR;
3284 	vim_memset(gap->ga_data, 0, sizeof(int *) * 256);
3285 	gap->ga_len = 256;
3286 
3287 	/* First count the number of items for each list.  Temporarily use
3288 	 * sl_sal_first[] for this. */
3289 	for (p = from, s = to; *p != NUL && *s != NUL; )
3290 	{
3291 	    c = mb_cptr2char_adv(&p);
3292 	    mb_cptr_adv(s);
3293 	    if (c >= 256)
3294 		++lp->sl_sal_first[c & 0xff];
3295 	}
3296 	if (*p != NUL || *s != NUL)	    /* lengths differ */
3297 	    return SP_FORMERROR;
3298 
3299 	/* Allocate the lists. */
3300 	for (i = 0; i < 256; ++i)
3301 	    if (lp->sl_sal_first[i] > 0)
3302 	    {
3303 		p = alloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1));
3304 		if (p == NULL)
3305 		    return SP_OTHERERROR;
3306 		((int **)gap->ga_data)[i] = (int *)p;
3307 		*(int *)p = 0;
3308 	    }
3309 
3310 	/* Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal
3311 	 * list. */
3312 	vim_memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
3313 	for (p = from, s = to; *p != NUL && *s != NUL; )
3314 	{
3315 	    c = mb_cptr2char_adv(&p);
3316 	    i = mb_cptr2char_adv(&s);
3317 	    if (c >= 256)
3318 	    {
3319 		/* Append the from-to chars at the end of the list with
3320 		 * the low byte. */
3321 		inp = ((int **)gap->ga_data)[c & 0xff];
3322 		while (*inp != 0)
3323 		    ++inp;
3324 		*inp++ = c;		/* from char */
3325 		*inp++ = i;		/* to char */
3326 		*inp++ = NUL;		/* NUL at the end */
3327 	    }
3328 	    else
3329 		/* mapping byte to char is done in sl_sal_first[] */
3330 		lp->sl_sal_first[c] = i;
3331 	}
3332     }
3333     else
3334 #endif
3335     {
3336 	/* mapping bytes to bytes is done in sl_sal_first[] */
3337 	if (STRLEN(from) != STRLEN(to))
3338 	    return SP_FORMERROR;
3339 
3340 	for (i = 0; to[i] != NUL; ++i)
3341 	    lp->sl_sal_first[from[i]] = to[i];
3342 	lp->sl_sal.ga_len = 1;		/* indicates we have soundfolding */
3343     }
3344 
3345     return 0;
3346 }
3347 
3348 /*
3349  * Fill the first-index table for "lp".
3350  */
3351     static void
3352 set_sal_first(lp)
3353     slang_T	*lp;
3354 {
3355     salfirst_T	*sfirst;
3356     int		i;
3357     salitem_T	*smp;
3358     int		c;
3359     garray_T	*gap = &lp->sl_sal;
3360 
3361     sfirst = lp->sl_sal_first;
3362     for (i = 0; i < 256; ++i)
3363 	sfirst[i] = -1;
3364     smp = (salitem_T *)gap->ga_data;
3365     for (i = 0; i < gap->ga_len; ++i)
3366     {
3367 #ifdef FEAT_MBYTE
3368 	if (has_mbyte)
3369 	    /* Use the lowest byte of the first character.  For latin1 it's
3370 	     * the character, for other encodings it should differ for most
3371 	     * characters. */
3372 	    c = *smp[i].sm_lead_w & 0xff;
3373 	else
3374 #endif
3375 	    c = *smp[i].sm_lead;
3376 	if (sfirst[c] == -1)
3377 	{
3378 	    sfirst[c] = i;
3379 #ifdef FEAT_MBYTE
3380 	    if (has_mbyte)
3381 	    {
3382 		int		n;
3383 
3384 		/* Make sure all entries with this byte are following each
3385 		 * other.  Move the ones that are in the wrong position.  Do
3386 		 * keep the same ordering! */
3387 		while (i + 1 < gap->ga_len
3388 				       && (*smp[i + 1].sm_lead_w & 0xff) == c)
3389 		    /* Skip over entry with same index byte. */
3390 		    ++i;
3391 
3392 		for (n = 1; i + n < gap->ga_len; ++n)
3393 		    if ((*smp[i + n].sm_lead_w & 0xff) == c)
3394 		    {
3395 			salitem_T  tsal;
3396 
3397 			/* Move entry with same index byte after the entries
3398 			 * we already found. */
3399 			++i;
3400 			--n;
3401 			tsal = smp[i + n];
3402 			mch_memmove(smp + i + 1, smp + i,
3403 						       sizeof(salitem_T) * n);
3404 			smp[i] = tsal;
3405 		    }
3406 	    }
3407 #endif
3408 	}
3409     }
3410 }
3411 
3412 #ifdef FEAT_MBYTE
3413 /*
3414  * Turn a multi-byte string into a wide character string.
3415  * Return it in allocated memory (NULL for out-of-memory)
3416  */
3417     static int *
3418 mb_str2wide(s)
3419     char_u	*s;
3420 {
3421     int		*res;
3422     char_u	*p;
3423     int		i = 0;
3424 
3425     res = (int *)alloc(sizeof(int) * (mb_charlen(s) + 1));
3426     if (res != NULL)
3427     {
3428 	for (p = s; *p != NUL; )
3429 	    res[i++] = mb_ptr2char_adv(&p);
3430 	res[i] = NUL;
3431     }
3432     return res;
3433 }
3434 #endif
3435 
3436 /*
3437  * Read one row of siblings from the spell file and store it in the byte array
3438  * "byts" and index array "idxs".  Recursively read the children.
3439  *
3440  * NOTE: The code here must match put_node().
3441  *
3442  * Returns the index follosing the siblings.
3443  * Returns -1 if the file is shorter than expected.
3444  * Returns -2 if there is a format error.
3445  */
3446     static idx_T
3447 read_tree(fd, byts, idxs, maxidx, startidx, prefixtree, maxprefcondnr)
3448     FILE	*fd;
3449     char_u	*byts;
3450     idx_T	*idxs;
3451     int		maxidx;		    /* size of arrays */
3452     idx_T	startidx;	    /* current index in "byts" and "idxs" */
3453     int		prefixtree;	    /* TRUE for reading PREFIXTREE */
3454     int		maxprefcondnr;	    /* maximum for <prefcondnr> */
3455 {
3456     int		len;
3457     int		i;
3458     int		n;
3459     idx_T	idx = startidx;
3460     int		c;
3461     int		c2;
3462 #define SHARED_MASK	0x8000000
3463 
3464     len = getc(fd);					/* <siblingcount> */
3465     if (len <= 0)
3466 	return -1;
3467 
3468     if (startidx + len >= maxidx)
3469 	return -2;
3470     byts[idx++] = len;
3471 
3472     /* Read the byte values, flag/region bytes and shared indexes. */
3473     for (i = 1; i <= len; ++i)
3474     {
3475 	c = getc(fd);					/* <byte> */
3476 	if (c < 0)
3477 	    return -1;
3478 	if (c <= BY_SPECIAL)
3479 	{
3480 	    if (c == BY_NOFLAGS && !prefixtree)
3481 	    {
3482 		/* No flags, all regions. */
3483 		idxs[idx] = 0;
3484 		c = 0;
3485 	    }
3486 	    else if (c != BY_INDEX)
3487 	    {
3488 		if (prefixtree)
3489 		{
3490 		    /* Read the optional pflags byte, the prefix ID and the
3491 		     * condition nr.  In idxs[] store the prefix ID in the low
3492 		     * byte, the condition index shifted up 8 bits, the flags
3493 		     * shifted up 24 bits. */
3494 		    if (c == BY_FLAGS)
3495 			c = getc(fd) << 24;		/* <pflags> */
3496 		    else
3497 			c = 0;
3498 
3499 		    c |= getc(fd);			/* <affixID> */
3500 
3501 		    n = (getc(fd) << 8) + getc(fd);	/* <prefcondnr> */
3502 		    if (n >= maxprefcondnr)
3503 			return -2;
3504 		    c |= (n << 8);
3505 		}
3506 		else /* c must be BY_FLAGS or BY_FLAGS2 */
3507 		{
3508 		    /* Read flags and optional region and prefix ID.  In
3509 		     * idxs[] the flags go in the low two bytes, region above
3510 		     * that and prefix ID above the region. */
3511 		    c2 = c;
3512 		    c = getc(fd);			/* <flags> */
3513 		    if (c2 == BY_FLAGS2)
3514 			c = (getc(fd) << 8) + c;	/* <flags2> */
3515 		    if (c & WF_REGION)
3516 			c = (getc(fd) << 16) + c;	/* <region> */
3517 		    if (c & WF_AFX)
3518 			c = (getc(fd) << 24) + c;	/* <affixID> */
3519 		}
3520 
3521 		idxs[idx] = c;
3522 		c = 0;
3523 	    }
3524 	    else /* c == BY_INDEX */
3525 	    {
3526 							/* <nodeidx> */
3527 		n = (getc(fd) << 16) + (getc(fd) << 8) + getc(fd);
3528 		if (n < 0 || n >= maxidx)
3529 		    return -2;
3530 		idxs[idx] = n + SHARED_MASK;
3531 		c = getc(fd);				/* <xbyte> */
3532 	    }
3533 	}
3534 	byts[idx++] = c;
3535     }
3536 
3537     /* Recursively read the children for non-shared siblings.
3538      * Skip the end-of-word ones (zero byte value) and the shared ones (and
3539      * remove SHARED_MASK) */
3540     for (i = 1; i <= len; ++i)
3541 	if (byts[startidx + i] != 0)
3542 	{
3543 	    if (idxs[startidx + i] & SHARED_MASK)
3544 		idxs[startidx + i] &= ~SHARED_MASK;
3545 	    else
3546 	    {
3547 		idxs[startidx + i] = idx;
3548 		idx = read_tree(fd, byts, idxs, maxidx, idx,
3549 						     prefixtree, maxprefcondnr);
3550 		if (idx < 0)
3551 		    break;
3552 	    }
3553 	}
3554 
3555     return idx;
3556 }
3557 
3558 /*
3559  * Parse 'spelllang' and set buf->b_langp accordingly.
3560  * Returns NULL if it's OK, an error message otherwise.
3561  */
3562     char_u *
3563 did_set_spelllang(buf)
3564     buf_T	*buf;
3565 {
3566     garray_T	ga;
3567     char_u	*splp;
3568     char_u	*region;
3569     char_u	region_cp[3];
3570     int		filename;
3571     int		region_mask;
3572     slang_T	*slang;
3573     int		c;
3574     char_u	lang[MAXWLEN + 1];
3575     char_u	spf_name[MAXPATHL];
3576     int		len;
3577     char_u	*p;
3578     int		round;
3579     char_u	*spf;
3580     char_u	*use_region = NULL;
3581     int		dont_use_region = FALSE;
3582     int		nobreak = FALSE;
3583     int		i, j;
3584     langp_T	*lp, *lp2;
3585 
3586     ga_init2(&ga, sizeof(langp_T), 2);
3587     clear_midword(buf);
3588 
3589     /* loop over comma separated language names. */
3590     for (splp = buf->b_p_spl; *splp != NUL; )
3591     {
3592 	/* Get one language name. */
3593 	copy_option_part(&splp, lang, MAXWLEN, ",");
3594 
3595 	region = NULL;
3596 	len = STRLEN(lang);
3597 
3598 	/* If the name ends in ".spl" use it as the name of the spell file.
3599 	 * If there is a region name let "region" point to it and remove it
3600 	 * from the name. */
3601 	if (len > 4 && fnamecmp(lang + len - 4, ".spl") == 0)
3602 	{
3603 	    filename = TRUE;
3604 
3605 	    /* Locate a region and remove it from the file name. */
3606 	    p = vim_strchr(gettail(lang), '_');
3607 	    if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
3608 						      && !ASCII_ISALPHA(p[3]))
3609 	    {
3610 		vim_strncpy(region_cp, p + 1, 2);
3611 		mch_memmove(p, p + 3, len - (p - lang) - 2);
3612 		len -= 3;
3613 		region = region_cp;
3614 	    }
3615 	    else
3616 		dont_use_region = TRUE;
3617 
3618 	    /* Check if we loaded this language before. */
3619 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
3620 		if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
3621 		    break;
3622 	}
3623 	else
3624 	{
3625 	    filename = FALSE;
3626 	    if (len > 3 && lang[len - 3] == '_')
3627 	    {
3628 		region = lang + len - 2;
3629 		len -= 3;
3630 		lang[len] = NUL;
3631 	    }
3632 	    else
3633 		dont_use_region = TRUE;
3634 
3635 	    /* Check if we loaded this language before. */
3636 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
3637 		if (STRICMP(lang, slang->sl_name) == 0)
3638 		    break;
3639 	}
3640 
3641 	if (region != NULL)
3642 	{
3643 	    /* If the region differs from what was used before then don't
3644 	     * use it for 'spellfile'. */
3645 	    if (use_region != NULL && STRCMP(region, use_region) != 0)
3646 		dont_use_region = TRUE;
3647 	    use_region = region;
3648 	}
3649 
3650 	/* If not found try loading the language now. */
3651 	if (slang == NULL)
3652 	{
3653 	    if (filename)
3654 		(void)spell_load_file(lang, lang, NULL, FALSE);
3655 	    else
3656 		spell_load_lang(lang);
3657 	}
3658 
3659 	/*
3660 	 * Loop over the languages, there can be several files for "lang".
3661 	 */
3662 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
3663 	    if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
3664 			 : STRICMP(lang, slang->sl_name) == 0)
3665 	    {
3666 		region_mask = REGION_ALL;
3667 		if (!filename && region != NULL)
3668 		{
3669 		    /* find region in sl_regions */
3670 		    c = find_region(slang->sl_regions, region);
3671 		    if (c == REGION_ALL)
3672 		    {
3673 			if (slang->sl_add)
3674 			{
3675 			    if (*slang->sl_regions != NUL)
3676 				/* This addition file is for other regions. */
3677 				region_mask = 0;
3678 			}
3679 			else
3680 			    /* This is probably an error.  Give a warning and
3681 			     * accept the words anyway. */
3682 			    smsg((char_u *)
3683 				    _("Warning: region %s not supported"),
3684 								      region);
3685 		    }
3686 		    else
3687 			region_mask = 1 << c;
3688 		}
3689 
3690 		if (region_mask != 0)
3691 		{
3692 		    if (ga_grow(&ga, 1) == FAIL)
3693 		    {
3694 			ga_clear(&ga);
3695 			return e_outofmem;
3696 		    }
3697 		    LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
3698 		    LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
3699 		    ++ga.ga_len;
3700 		    use_midword(slang, buf);
3701 		    if (slang->sl_nobreak)
3702 			nobreak = TRUE;
3703 		}
3704 	    }
3705     }
3706 
3707     /* round 0: load int_wordlist, if possible.
3708      * round 1: load first name in 'spellfile'.
3709      * round 2: load second name in 'spellfile.
3710      * etc. */
3711     spf = curbuf->b_p_spf;
3712     for (round = 0; round == 0 || *spf != NUL; ++round)
3713     {
3714 	if (round == 0)
3715 	{
3716 	    /* Internal wordlist, if there is one. */
3717 	    if (int_wordlist == NULL)
3718 		continue;
3719 	    int_wordlist_spl(spf_name);
3720 	}
3721 	else
3722 	{
3723 	    /* One entry in 'spellfile'. */
3724 	    copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
3725 	    STRCAT(spf_name, ".spl");
3726 
3727 	    /* If it was already found above then skip it. */
3728 	    for (c = 0; c < ga.ga_len; ++c)
3729 	    {
3730 		p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
3731 		if (p != NULL && fullpathcmp(spf_name, p, FALSE) == FPC_SAME)
3732 		    break;
3733 	    }
3734 	    if (c < ga.ga_len)
3735 		continue;
3736 	}
3737 
3738 	/* Check if it was loaded already. */
3739 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
3740 	    if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
3741 		break;
3742 	if (slang == NULL)
3743 	{
3744 	    /* Not loaded, try loading it now.  The language name includes the
3745 	     * region name, the region is ignored otherwise.  for int_wordlist
3746 	     * use an arbitrary name. */
3747 	    if (round == 0)
3748 		STRCPY(lang, "internal wordlist");
3749 	    else
3750 	    {
3751 		vim_strncpy(lang, gettail(spf_name), MAXWLEN);
3752 		p = vim_strchr(lang, '.');
3753 		if (p != NULL)
3754 		    *p = NUL;	/* truncate at ".encoding.add" */
3755 	    }
3756 	    slang = spell_load_file(spf_name, lang, NULL, TRUE);
3757 
3758 	    /* If one of the languages has NOBREAK we assume the addition
3759 	     * files also have this. */
3760 	    if (slang != NULL && nobreak)
3761 		slang->sl_nobreak = TRUE;
3762 	}
3763 	if (slang != NULL && ga_grow(&ga, 1) == OK)
3764 	{
3765 	    region_mask = REGION_ALL;
3766 	    if (use_region != NULL && !dont_use_region)
3767 	    {
3768 		/* find region in sl_regions */
3769 		c = find_region(slang->sl_regions, use_region);
3770 		if (c != REGION_ALL)
3771 		    region_mask = 1 << c;
3772 		else if (*slang->sl_regions != NUL)
3773 		    /* This spell file is for other regions. */
3774 		    region_mask = 0;
3775 	    }
3776 
3777 	    if (region_mask != 0)
3778 	    {
3779 		LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
3780 		LANGP_ENTRY(ga, ga.ga_len)->lp_sallang = NULL;
3781 		LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL;
3782 		LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
3783 		++ga.ga_len;
3784 		use_midword(slang, buf);
3785 	    }
3786 	}
3787     }
3788 
3789     /* Everything is fine, store the new b_langp value. */
3790     ga_clear(&buf->b_langp);
3791     buf->b_langp = ga;
3792 
3793     /* For each language figure out what language to use for sound folding and
3794      * REP items.  If the language doesn't support it itself use another one
3795      * with the same name.  E.g. for "en-math" use "en". */
3796     for (i = 0; i < ga.ga_len; ++i)
3797     {
3798 	lp = LANGP_ENTRY(ga, i);
3799 
3800 	/* sound folding */
3801 	if (lp->lp_slang->sl_sal.ga_len > 0)
3802 	    /* language does sound folding itself */
3803 	    lp->lp_sallang = lp->lp_slang;
3804 	else
3805 	    /* find first similar language that does sound folding */
3806 	    for (j = 0; j < ga.ga_len; ++j)
3807 	    {
3808 		lp2 = LANGP_ENTRY(ga, j);
3809 		if (lp2->lp_slang->sl_sal.ga_len > 0
3810 			&& STRNCMP(lp->lp_slang->sl_name,
3811 					      lp2->lp_slang->sl_name, 2) == 0)
3812 		{
3813 		    lp->lp_sallang = lp2->lp_slang;
3814 		    break;
3815 		}
3816 	    }
3817 
3818 	/* REP items */
3819 	if (lp->lp_slang->sl_rep.ga_len > 0)
3820 	    /* language has REP items itself */
3821 	    lp->lp_replang = lp->lp_slang;
3822 	else
3823 	    /* find first similar language that does sound folding */
3824 	    for (j = 0; j < ga.ga_len; ++j)
3825 	    {
3826 		lp2 = LANGP_ENTRY(ga, j);
3827 		if (lp2->lp_slang->sl_rep.ga_len > 0
3828 			&& STRNCMP(lp->lp_slang->sl_name,
3829 					      lp2->lp_slang->sl_name, 2) == 0)
3830 		{
3831 		    lp->lp_replang = lp2->lp_slang;
3832 		    break;
3833 		}
3834 	    }
3835     }
3836 
3837     return NULL;
3838 }
3839 
3840 /*
3841  * Clear the midword characters for buffer "buf".
3842  */
3843     static void
3844 clear_midword(buf)
3845     buf_T	*buf;
3846 {
3847     vim_memset(buf->b_spell_ismw, 0, 256);
3848 #ifdef FEAT_MBYTE
3849     vim_free(buf->b_spell_ismw_mb);
3850     buf->b_spell_ismw_mb = NULL;
3851 #endif
3852 }
3853 
3854 /*
3855  * Use the "sl_midword" field of language "lp" for buffer "buf".
3856  * They add up to any currently used midword characters.
3857  */
3858     static void
3859 use_midword(lp, buf)
3860     slang_T	*lp;
3861     buf_T	*buf;
3862 {
3863     char_u	*p;
3864 
3865     if (lp->sl_midword == NULL)	    /* there aren't any */
3866 	return;
3867 
3868     for (p = lp->sl_midword; *p != NUL; )
3869 #ifdef FEAT_MBYTE
3870 	if (has_mbyte)
3871 	{
3872 	    int	    c, l, n;
3873 	    char_u  *bp;
3874 
3875 	    c = mb_ptr2char(p);
3876 	    l = (*mb_ptr2len)(p);
3877 	    if (c < 256 && l <= 2)
3878 		buf->b_spell_ismw[c] = TRUE;
3879 	    else if (buf->b_spell_ismw_mb == NULL)
3880 		/* First multi-byte char in "b_spell_ismw_mb". */
3881 		buf->b_spell_ismw_mb = vim_strnsave(p, l);
3882 	    else
3883 	    {
3884 		/* Append multi-byte chars to "b_spell_ismw_mb". */
3885 		n = STRLEN(buf->b_spell_ismw_mb);
3886 		bp = vim_strnsave(buf->b_spell_ismw_mb, n + l);
3887 		if (bp != NULL)
3888 		{
3889 		    vim_free(buf->b_spell_ismw_mb);
3890 		    buf->b_spell_ismw_mb = bp;
3891 		    vim_strncpy(bp + n, p, l);
3892 		}
3893 	    }
3894 	    p += l;
3895 	}
3896 	else
3897 #endif
3898 	    buf->b_spell_ismw[*p++] = TRUE;
3899 }
3900 
3901 /*
3902  * Find the region "region[2]" in "rp" (points to "sl_regions").
3903  * Each region is simply stored as the two characters of it's name.
3904  * Returns the index if found (first is 0), REGION_ALL if not found.
3905  */
3906     static int
3907 find_region(rp, region)
3908     char_u	*rp;
3909     char_u	*region;
3910 {
3911     int		i;
3912 
3913     for (i = 0; ; i += 2)
3914     {
3915 	if (rp[i] == NUL)
3916 	    return REGION_ALL;
3917 	if (rp[i] == region[0] && rp[i + 1] == region[1])
3918 	    break;
3919     }
3920     return i / 2;
3921 }
3922 
3923 /*
3924  * Return case type of word:
3925  * w word	0
3926  * Word		WF_ONECAP
3927  * W WORD	WF_ALLCAP
3928  * WoRd	wOrd	WF_KEEPCAP
3929  */
3930     static int
3931 captype(word, end)
3932     char_u	*word;
3933     char_u	*end;	    /* When NULL use up to NUL byte. */
3934 {
3935     char_u	*p;
3936     int		c;
3937     int		firstcap;
3938     int		allcap;
3939     int		past_second = FALSE;	/* past second word char */
3940 
3941     /* find first letter */
3942     for (p = word; !spell_iswordp_nmw(p); mb_ptr_adv(p))
3943 	if (end == NULL ? *p == NUL : p >= end)
3944 	    return 0;	    /* only non-word characters, illegal word */
3945 #ifdef FEAT_MBYTE
3946     if (has_mbyte)
3947 	c = mb_ptr2char_adv(&p);
3948     else
3949 #endif
3950 	c = *p++;
3951     firstcap = allcap = SPELL_ISUPPER(c);
3952 
3953     /*
3954      * Need to check all letters to find a word with mixed upper/lower.
3955      * But a word with an upper char only at start is a ONECAP.
3956      */
3957     for ( ; end == NULL ? *p != NUL : p < end; mb_ptr_adv(p))
3958 	if (spell_iswordp_nmw(p))
3959 	{
3960 	    c = PTR2CHAR(p);
3961 	    if (!SPELL_ISUPPER(c))
3962 	    {
3963 		/* UUl -> KEEPCAP */
3964 		if (past_second && allcap)
3965 		    return WF_KEEPCAP;
3966 		allcap = FALSE;
3967 	    }
3968 	    else if (!allcap)
3969 		/* UlU -> KEEPCAP */
3970 		return WF_KEEPCAP;
3971 	    past_second = TRUE;
3972 	}
3973 
3974     if (allcap)
3975 	return WF_ALLCAP;
3976     if (firstcap)
3977 	return WF_ONECAP;
3978     return 0;
3979 }
3980 
3981 /*
3982  * Like captype() but for a KEEPCAP word add ONECAP if the word starts with a
3983  * capital.  So that make_case_word() can turn WOrd into Word.
3984  * Add ALLCAP for "WOrD".
3985  */
3986     static int
3987 badword_captype(word, end)
3988     char_u	*word;
3989     char_u	*end;
3990 {
3991     int		flags = captype(word, end);
3992     int		c;
3993     int		l, u;
3994     int		first;
3995     char_u	*p;
3996 
3997     if (flags & WF_KEEPCAP)
3998     {
3999 	/* Count the number of UPPER and lower case letters. */
4000 	l = u = 0;
4001 	first = FALSE;
4002 	for (p = word; p < end; mb_ptr_adv(p))
4003 	{
4004 	    c = PTR2CHAR(p);
4005 	    if (SPELL_ISUPPER(c))
4006 	    {
4007 		++u;
4008 		if (p == word)
4009 		    first = TRUE;
4010 	    }
4011 	    else
4012 		++l;
4013 	}
4014 
4015 	/* If there are more UPPER than lower case letters suggest an
4016 	 * ALLCAP word.  Otherwise, if the first letter is UPPER then
4017 	 * suggest ONECAP.  Exception: "ALl" most likely should be "All",
4018 	 * require three upper case letters. */
4019 	if (u > l && u > 2)
4020 	    flags |= WF_ALLCAP;
4021 	else if (first)
4022 	    flags |= WF_ONECAP;
4023     }
4024     return flags;
4025 }
4026 
4027 # if defined(FEAT_MBYTE) || defined(EXITFREE) || defined(PROTO)
4028 /*
4029  * Free all languages.
4030  */
4031     void
4032 spell_free_all()
4033 {
4034     slang_T	*slang;
4035     buf_T	*buf;
4036     char_u	fname[MAXPATHL];
4037 
4038     /* Go through all buffers and handle 'spelllang'. */
4039     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4040 	ga_clear(&buf->b_langp);
4041 
4042     while (first_lang != NULL)
4043     {
4044 	slang = first_lang;
4045 	first_lang = slang->sl_next;
4046 	slang_free(slang);
4047     }
4048 
4049     if (int_wordlist != NULL)
4050     {
4051 	/* Delete the internal wordlist and its .spl file */
4052 	mch_remove(int_wordlist);
4053 	int_wordlist_spl(fname);
4054 	mch_remove(fname);
4055 	vim_free(int_wordlist);
4056 	int_wordlist = NULL;
4057     }
4058 
4059     init_spell_chartab();
4060 }
4061 # endif
4062 
4063 # if defined(FEAT_MBYTE) || defined(PROTO)
4064 /*
4065  * Clear all spelling tables and reload them.
4066  * Used after 'encoding' is set and when ":mkspell" was used.
4067  */
4068     void
4069 spell_reload()
4070 {
4071     buf_T	*buf;
4072     win_T	*wp;
4073 
4074     /* Initialize the table for spell_iswordp(). */
4075     init_spell_chartab();
4076 
4077     /* Unload all allocated memory. */
4078     spell_free_all();
4079 
4080     /* Go through all buffers and handle 'spelllang'. */
4081     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4082     {
4083 	/* Only load the wordlists when 'spelllang' is set and there is a
4084 	 * window for this buffer in which 'spell' is set. */
4085 	if (*buf->b_p_spl != NUL)
4086 	{
4087 	    FOR_ALL_WINDOWS(wp)
4088 		if (wp->w_buffer == buf && wp->w_p_spell)
4089 		{
4090 		    (void)did_set_spelllang(buf);
4091 # ifdef FEAT_WINDOWS
4092 		    break;
4093 # endif
4094 		}
4095 	}
4096     }
4097 }
4098 # endif
4099 
4100 /*
4101  * Reload the spell file "fname" if it's loaded.
4102  */
4103     static void
4104 spell_reload_one(fname, added_word)
4105     char_u	*fname;
4106     int		added_word;	/* invoked through "zg" */
4107 {
4108     slang_T	*slang;
4109     int		didit = FALSE;
4110 
4111     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4112     {
4113 	if (fullpathcmp(fname, slang->sl_fname, FALSE) == FPC_SAME)
4114 	{
4115 	    slang_clear(slang);
4116 	    if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
4117 		/* reloading failed, clear the language */
4118 		slang_clear(slang);
4119 	    redraw_all_later(NOT_VALID);
4120 	    didit = TRUE;
4121 	}
4122     }
4123 
4124     /* When "zg" was used and the file wasn't loaded yet, should redo
4125      * 'spelllang' to get it loaded. */
4126     if (added_word && !didit)
4127 	did_set_spelllang(curbuf);
4128 }
4129 
4130 
4131 /*
4132  * Functions for ":mkspell".
4133  */
4134 
4135 #define MAXLINELEN  500		/* Maximum length in bytes of a line in a .aff
4136 				   and .dic file. */
4137 /*
4138  * Main structure to store the contents of a ".aff" file.
4139  */
4140 typedef struct afffile_S
4141 {
4142     char_u	*af_enc;	/* "SET", normalized, alloc'ed string or NULL */
4143     int		af_flagtype;	/* AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG */
4144     int		af_slash;	/* character used in word for slash */
4145     unsigned	af_rar;		/* RAR ID for rare word */
4146     unsigned	af_kep;		/* KEP ID for keep-case word */
4147     unsigned	af_bad;		/* BAD ID for banned word */
4148     unsigned	af_needaffix;	/* NEEDAFFIX ID */
4149     unsigned	af_needcomp;	/* NEEDCOMPOUND ID */
4150     int		af_pfxpostpone;	/* postpone prefixes without chop string */
4151     hashtab_T	af_pref;	/* hashtable for prefixes, affheader_T */
4152     hashtab_T	af_suff;	/* hashtable for suffixes, affheader_T */
4153     hashtab_T	af_comp;	/* hashtable for compound flags, compitem_T */
4154 } afffile_T;
4155 
4156 #define AFT_CHAR	0	/* flags are one character */
4157 #define AFT_LONG	1	/* flags are two characters */
4158 #define AFT_CAPLONG	2	/* flags are one or two characters */
4159 #define AFT_NUM		3	/* flags are numbers, comma separated */
4160 
4161 typedef struct affentry_S affentry_T;
4162 /* Affix entry from ".aff" file.  Used for prefixes and suffixes. */
4163 struct affentry_S
4164 {
4165     affentry_T	*ae_next;	/* next affix with same name/number */
4166     char_u	*ae_chop;	/* text to chop off basic word (can be NULL) */
4167     char_u	*ae_add;	/* text to add to basic word (can be NULL) */
4168     char_u	*ae_cond;	/* condition (NULL for ".") */
4169     regprog_T	*ae_prog;	/* regexp program for ae_cond or NULL */
4170     char_u	ae_rare;	/* rare affix */
4171     char_u	ae_nocomp;	/* word with affix not compoundable */
4172 };
4173 
4174 #ifdef FEAT_MBYTE
4175 # define AH_KEY_LEN 17		/* 2 x 8 bytes + NUL */
4176 #else
4177 # define AH_KEY_LEN 7		/* 6 digits + NUL */
4178 #endif
4179 
4180 /* Affix header from ".aff" file.  Used for af_pref and af_suff. */
4181 typedef struct affheader_S
4182 {
4183     char_u	ah_key[AH_KEY_LEN]; /* key for hashtab == name of affix */
4184     unsigned	ah_flag;	/* affix name as number, uses "af_flagtype" */
4185     int		ah_newID;	/* prefix ID after renumbering; 0 if not used */
4186     int		ah_combine;	/* suffix may combine with prefix */
4187     int		ah_follows;	/* another affix block should be following */
4188     affentry_T	*ah_first;	/* first affix entry */
4189 } affheader_T;
4190 
4191 #define HI2AH(hi)   ((affheader_T *)(hi)->hi_key)
4192 
4193 /* Flag used in compound items. */
4194 typedef struct compitem_S
4195 {
4196     char_u	ci_key[AH_KEY_LEN]; /* key for hashtab == name of compound */
4197     unsigned	ci_flag;	/* affix name as number, uses "af_flagtype" */
4198     int		ci_newID;	/* affix ID after renumbering. */
4199 } compitem_T;
4200 
4201 #define HI2CI(hi)   ((compitem_T *)(hi)->hi_key)
4202 
4203 /*
4204  * Structure that is used to store the items in the word tree.  This avoids
4205  * the need to keep track of each allocated thing, everything is freed all at
4206  * once after ":mkspell" is done.
4207  */
4208 #define  SBLOCKSIZE 16000	/* size of sb_data */
4209 typedef struct sblock_S sblock_T;
4210 struct sblock_S
4211 {
4212     sblock_T	*sb_next;	/* next block in list */
4213     int		sb_used;	/* nr of bytes already in use */
4214     char_u	sb_data[1];	/* data, actually longer */
4215 };
4216 
4217 /*
4218  * A node in the tree.
4219  */
4220 typedef struct wordnode_S wordnode_T;
4221 struct wordnode_S
4222 {
4223     union   /* shared to save space */
4224     {
4225 	char_u	hashkey[6];	/* the hash key, only used while compressing */
4226 	int	index;		/* index in written nodes (valid after first
4227 				   round) */
4228     } wn_u1;
4229     union   /* shared to save space */
4230     {
4231 	wordnode_T *next;	/* next node with same hash key */
4232 	wordnode_T *wnode;	/* parent node that will write this node */
4233     } wn_u2;
4234     wordnode_T	*wn_child;	/* child (next byte in word) */
4235     wordnode_T  *wn_sibling;	/* next sibling (alternate byte in word,
4236 				   always sorted) */
4237     int		wn_refs;	/* Nr. of references to this node.  Only
4238 				   relevant for first node in a list of
4239 				   siblings, in following siblings it is
4240 				   always one. */
4241     char_u	wn_byte;	/* Byte for this node. NUL for word end */
4242     char_u	wn_affixID;	/* when "wn_byte" is NUL: supported/required
4243 				   prefix ID or 0 */
4244     short_u	wn_flags;	/* when "wn_byte" is NUL: WF_ flags */
4245     short	wn_region;	/* when "wn_byte" is NUL: region mask; for
4246 				   PREFIXTREE it's the prefcondnr */
4247 #ifdef SPELL_PRINTTREE
4248     int		wn_nr;		/* sequence nr for printing */
4249 #endif
4250 };
4251 
4252 #define WN_MASK	 0xffff		/* mask relevant bits of "wn_flags" */
4253 
4254 #define HI2WN(hi)    (wordnode_T *)((hi)->hi_key)
4255 
4256 /*
4257  * Info used while reading the spell files.
4258  */
4259 typedef struct spellinfo_S
4260 {
4261     wordnode_T	*si_foldroot;	/* tree with case-folded words */
4262     long	si_foldwcount;	/* nr of words in si_foldroot */
4263 
4264     wordnode_T	*si_keeproot;	/* tree with keep-case words */
4265     long	si_keepwcount;	/* nr of words in si_keeproot */
4266 
4267     wordnode_T	*si_prefroot;	/* tree with postponed prefixes */
4268 
4269     sblock_T	*si_blocks;	/* memory blocks used */
4270     long	si_blocks_cnt;	/* memory blocks allocated */
4271     long	si_compress_cnt;    /* words to add before lowering
4272 				       compression limit */
4273     wordnode_T	*si_first_free; /* List of nodes that have been freed during
4274 				   compression, linked by "wn_child" field. */
4275     long	si_free_count;	/* number of nodes in si_first_free */
4276 #ifdef SPELL_PRINTTREE
4277     int		si_wordnode_nr;	/* sequence nr for nodes */
4278 #endif
4279 
4280 
4281     int		si_ascii;	/* handling only ASCII words */
4282     int		si_add;		/* addition file */
4283     int		si_clear_chartab;   /* when TRUE clear char tables */
4284     int		si_region;	/* region mask */
4285     vimconv_T	si_conv;	/* for conversion to 'encoding' */
4286     int		si_memtot;	/* runtime memory used */
4287     int		si_verbose;	/* verbose messages */
4288     int		si_msg_count;	/* number of words added since last message */
4289     int		si_region_count; /* number of regions supported (1 when there
4290 				    are no regions) */
4291     char_u	si_region_name[16]; /* region names; used only if
4292 				     * si_region_count > 1) */
4293 
4294     garray_T	si_rep;		/* list of fromto_T entries from REP lines */
4295     garray_T	si_sal;		/* list of fromto_T entries from SAL lines */
4296     char_u	*si_sofofr;	/* SOFOFROM text */
4297     char_u	*si_sofoto;	/* SOFOTO text */
4298     int		si_followup;	/* soundsalike: ? */
4299     int		si_collapse;	/* soundsalike: ? */
4300     int		si_rem_accents;	/* soundsalike: remove accents */
4301     garray_T	si_map;		/* MAP info concatenated */
4302     char_u	*si_midword;	/* MIDWORD chars or NULL  */
4303     int		si_compmax;	/* max nr of words for compounding */
4304     int		si_compminlen;	/* minimal length for compounding */
4305     int		si_compsylmax;	/* max nr of syllables for compounding */
4306     char_u	*si_compflags;	/* flags used for compounding */
4307     char_u	si_nobreak;	/* NOBREAK */
4308     char_u	*si_syllable;	/* syllable string */
4309     garray_T	si_prefcond;	/* table with conditions for postponed
4310 				 * prefixes, each stored as a string */
4311     int		si_newprefID;	/* current value for ah_newID */
4312     int		si_newcompID;	/* current value for compound ID */
4313 } spellinfo_T;
4314 
4315 static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
4316 static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u	*fname, int lnum));
4317 static unsigned get_affitem __ARGS((int flagtype, char_u **pp));
4318 static void process_compflags __ARGS((spellinfo_T *spin, afffile_T *aff, char_u *compflags));
4319 static void check_renumber __ARGS((spellinfo_T *spin));
4320 static int flag_in_afflist __ARGS((int flagtype, char_u *afflist, unsigned flag));
4321 static void aff_check_number __ARGS((int spinval, int affval, char *name));
4322 static void aff_check_string __ARGS((char_u *spinval, char_u *affval, char *name));
4323 static int str_equal __ARGS((char_u *s1, char_u	*s2));
4324 static void add_fromto __ARGS((spellinfo_T *spin, garray_T *gap, char_u	*from, char_u *to));
4325 static int sal_to_bool __ARGS((char_u *s));
4326 static int has_non_ascii __ARGS((char_u *s));
4327 static void spell_free_aff __ARGS((afffile_T *aff));
4328 static int spell_read_dic __ARGS((spellinfo_T *spin, char_u *fname, afffile_T *affile));
4329 static int get_pfxlist __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
4330 static void get_compflags __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
4331 static int store_aff_word __ARGS((spellinfo_T *spin, char_u *word, char_u *afflist, afffile_T *affile, hashtab_T *ht, hashtab_T *xht, int comb, int flags, char_u *pfxlist, int pfxlen));
4332 static int spell_read_wordfile __ARGS((spellinfo_T *spin, char_u *fname));
4333 static void *getroom __ARGS((spellinfo_T *spin, size_t len, int align));
4334 static char_u *getroom_save __ARGS((spellinfo_T *spin, char_u *s));
4335 static void free_blocks __ARGS((sblock_T *bl));
4336 static wordnode_T *wordtree_alloc __ARGS((spellinfo_T *spin));
4337 static int store_word __ARGS((spellinfo_T *spin, char_u *word, int flags, int region, char_u *pfxlist, int need_affix));
4338 static int tree_add_word __ARGS((spellinfo_T *spin, char_u *word, wordnode_T *tree, int flags, int region, int affixID));
4339 static wordnode_T *get_wordnode __ARGS((spellinfo_T *spin));
4340 static void deref_wordnode __ARGS((spellinfo_T *spin, wordnode_T *node));
4341 static void free_wordnode __ARGS((spellinfo_T *spin, wordnode_T *n));
4342 static void wordtree_compress __ARGS((spellinfo_T *spin, wordnode_T *root));
4343 static int node_compress __ARGS((spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot));
4344 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
4345 static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
4346 static void clear_node __ARGS((wordnode_T *node));
4347 static int put_node __ARGS((FILE *fd, wordnode_T *node, int index, int regionmask, int prefixtree));
4348 static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int overwrite, int added_word));
4349 static void init_spellfile __ARGS((void));
4350 
4351 /* In the postponed prefixes tree wn_flags is used to store the WFP_ flags,
4352  * but it must be negative to indicate the prefix tree to tree_add_word().
4353  * Use a negative number with the lower 8 bits zero. */
4354 #define PFX_FLAGS	-256
4355 
4356 /*
4357  * Tunable parameters for when the tree is compressed.  See 'mkspellmem'.
4358  */
4359 static long compress_start = 30000;	/* memory / SBLOCKSIZE */
4360 static long compress_inc = 100;		/* memory / SBLOCKSIZE */
4361 static long compress_added = 500000;	/* word count */
4362 
4363 #ifdef SPELL_PRINTTREE
4364 /*
4365  * For debugging the tree code: print the current tree in a (more or less)
4366  * readable format, so that we can see what happens when adding a word and/or
4367  * compressing the tree.
4368  * Based on code from Olaf Seibert.
4369  */
4370 #define PRINTLINESIZE	1000
4371 #define PRINTWIDTH	6
4372 
4373 #define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \
4374 	    PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2)
4375 
4376 static char line1[PRINTLINESIZE];
4377 static char line2[PRINTLINESIZE];
4378 static char line3[PRINTLINESIZE];
4379 
4380     static void
4381 spell_clear_flags(wordnode_T *node)
4382 {
4383     wordnode_T	*np;
4384 
4385     for (np = node; np != NULL; np = np->wn_sibling)
4386     {
4387 	np->wn_u1.index = FALSE;
4388 	spell_clear_flags(np->wn_child);
4389     }
4390 }
4391 
4392     static void
4393 spell_print_node(wordnode_T *node, int depth)
4394 {
4395     if (node->wn_u1.index)
4396     {
4397 	/* Done this node before, print the reference. */
4398 	PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0);
4399 	PRINTSOME(line2, depth, "    ", 0, 0);
4400 	PRINTSOME(line3, depth, "    ", 0, 0);
4401 	msg(line1);
4402 	msg(line2);
4403 	msg(line3);
4404     }
4405     else
4406     {
4407 	node->wn_u1.index = TRUE;
4408 
4409 	if (node->wn_byte != NUL)
4410 	{
4411 	    if (node->wn_child != NULL)
4412 		PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0);
4413 	    else
4414 		/* Cannot happen? */
4415 		PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0);
4416 	}
4417 	else
4418 	    PRINTSOME(line1, depth, " $    ", 0, 0);
4419 
4420 	PRINTSOME(line2, depth, "%d/%d    ", node->wn_nr, node->wn_refs);
4421 
4422 	if (node->wn_sibling != NULL)
4423 	    PRINTSOME(line3, depth, " |    ", 0, 0);
4424 	else
4425 	    PRINTSOME(line3, depth, "      ", 0, 0);
4426 
4427 	if (node->wn_byte == NUL)
4428 	{
4429 	    msg(line1);
4430 	    msg(line2);
4431 	    msg(line3);
4432 	}
4433 
4434 	/* do the children */
4435 	if (node->wn_byte != NUL && node->wn_child != NULL)
4436 	    spell_print_node(node->wn_child, depth + 1);
4437 
4438 	/* do the siblings */
4439 	if (node->wn_sibling != NULL)
4440 	{
4441 	    /* get rid of all parent details except | */
4442 	    STRCPY(line1, line3);
4443 	    STRCPY(line2, line3);
4444 	    spell_print_node(node->wn_sibling, depth);
4445 	}
4446     }
4447 }
4448 
4449     static void
4450 spell_print_tree(wordnode_T *root)
4451 {
4452     if (root != NULL)
4453     {
4454 	/* Clear the "wn_u1.index" fields, used to remember what has been
4455 	 * done. */
4456 	spell_clear_flags(root);
4457 
4458 	/* Recursively print the tree. */
4459 	spell_print_node(root, 0);
4460     }
4461 }
4462 #endif /* SPELL_PRINTTREE */
4463 
4464 /*
4465  * Read the affix file "fname".
4466  * Returns an afffile_T, NULL for complete failure.
4467  */
4468     static afffile_T *
4469 spell_read_aff(spin, fname)
4470     spellinfo_T	*spin;
4471     char_u	*fname;
4472 {
4473     FILE	*fd;
4474     afffile_T	*aff;
4475     char_u	rline[MAXLINELEN];
4476     char_u	*line;
4477     char_u	*pc = NULL;
4478 #define MAXITEMCNT  7
4479     char_u	*(items[MAXITEMCNT]);
4480     int		itemcnt;
4481     char_u	*p;
4482     int		lnum = 0;
4483     affheader_T	*cur_aff = NULL;
4484     int		did_postpone_prefix = FALSE;
4485     int		aff_todo = 0;
4486     hashtab_T	*tp;
4487     char_u	*low = NULL;
4488     char_u	*fol = NULL;
4489     char_u	*upp = NULL;
4490     int		do_rep;
4491     int		do_sal;
4492     int		do_map;
4493     int		found_map = FALSE;
4494     hashitem_T	*hi;
4495     int		l;
4496     int		compminlen = 0;		/* COMPOUNDMIN value */
4497     int		compsylmax = 0;		/* COMPOUNDSYLMAX value */
4498     int		compmax = 0;		/* COMPOUNDMAX value */
4499     char_u	*compflags = NULL;	/* COMPOUNDFLAG and COMPOUNDFLAGS
4500 					   concatenated */
4501     char_u	*midword = NULL;	/* MIDWORD value */
4502     char_u	*syllable = NULL;	/* SYLLABLE value */
4503     char_u	*sofofrom = NULL;	/* SOFOFROM value */
4504     char_u	*sofoto = NULL;		/* SOFOTO value */
4505 
4506     /*
4507      * Open the file.
4508      */
4509     fd = mch_fopen((char *)fname, "r");
4510     if (fd == NULL)
4511     {
4512 	EMSG2(_(e_notopen), fname);
4513 	return NULL;
4514     }
4515 
4516     if (spin->si_verbose || p_verbose > 2)
4517     {
4518 	if (!spin->si_verbose)
4519 	    verbose_enter();
4520 	smsg((char_u *)_("Reading affix file %s ..."), fname);
4521 	out_flush();
4522 	if (!spin->si_verbose)
4523 	    verbose_leave();
4524     }
4525 
4526     /* Only do REP lines when not done in another .aff file already. */
4527     do_rep = spin->si_rep.ga_len == 0;
4528 
4529     /* Only do SAL lines when not done in another .aff file already. */
4530     do_sal = spin->si_sal.ga_len == 0;
4531 
4532     /* Only do MAP lines when not done in another .aff file already. */
4533     do_map = spin->si_map.ga_len == 0;
4534 
4535     /*
4536      * Allocate and init the afffile_T structure.
4537      */
4538     aff = (afffile_T *)getroom(spin, sizeof(afffile_T), TRUE);
4539     if (aff == NULL)
4540 	return NULL;
4541     hash_init(&aff->af_pref);
4542     hash_init(&aff->af_suff);
4543     hash_init(&aff->af_comp);
4544 
4545     /*
4546      * Read all the lines in the file one by one.
4547      */
4548     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
4549     {
4550 	line_breakcheck();
4551 	++lnum;
4552 
4553 	/* Skip comment lines. */
4554 	if (*rline == '#')
4555 	    continue;
4556 
4557 	/* Convert from "SET" to 'encoding' when needed. */
4558 	vim_free(pc);
4559 #ifdef FEAT_MBYTE
4560 	if (spin->si_conv.vc_type != CONV_NONE)
4561 	{
4562 	    pc = string_convert(&spin->si_conv, rline, NULL);
4563 	    if (pc == NULL)
4564 	    {
4565 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
4566 							   fname, lnum, rline);
4567 		continue;
4568 	    }
4569 	    line = pc;
4570 	}
4571 	else
4572 #endif
4573 	{
4574 	    pc = NULL;
4575 	    line = rline;
4576 	}
4577 
4578 	/* Split the line up in white separated items.  Put a NUL after each
4579 	 * item. */
4580 	itemcnt = 0;
4581 	for (p = line; ; )
4582 	{
4583 	    while (*p != NUL && *p <= ' ')  /* skip white space and CR/NL */
4584 		++p;
4585 	    if (*p == NUL)
4586 		break;
4587 	    if (itemcnt == MAXITEMCNT)	    /* too many items */
4588 		break;
4589 	    items[itemcnt++] = p;
4590 	    while (*p > ' ')	    /* skip until white space or CR/NL */
4591 		++p;
4592 	    if (*p == NUL)
4593 		break;
4594 	    *p++ = NUL;
4595 	}
4596 
4597 	/* Handle non-empty lines. */
4598 	if (itemcnt > 0)
4599 	{
4600 	    if (STRCMP(items[0], "SET") == 0 && itemcnt == 2
4601 						       && aff->af_enc == NULL)
4602 	    {
4603 #ifdef FEAT_MBYTE
4604 		/* Setup for conversion from "ENC" to 'encoding'. */
4605 		aff->af_enc = enc_canonize(items[1]);
4606 		if (aff->af_enc != NULL && !spin->si_ascii
4607 			&& convert_setup(&spin->si_conv, aff->af_enc,
4608 							       p_enc) == FAIL)
4609 		    smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
4610 					       fname, aff->af_enc, p_enc);
4611 		spin->si_conv.vc_fail = TRUE;
4612 #else
4613 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
4614 #endif
4615 	    }
4616 	    else if (STRCMP(items[0], "FLAG") == 0 && itemcnt == 2
4617 					      && aff->af_flagtype == AFT_CHAR)
4618 	    {
4619 		if (STRCMP(items[1], "long") == 0)
4620 		    aff->af_flagtype = AFT_LONG;
4621 		else if (STRCMP(items[1], "num") == 0)
4622 		    aff->af_flagtype = AFT_NUM;
4623 		else if (STRCMP(items[1], "caplong") == 0)
4624 		    aff->af_flagtype = AFT_CAPLONG;
4625 		else
4626 		    smsg((char_u *)_("Invalid value for FLAG in %s line %d: %s"),
4627 			    fname, lnum, items[1]);
4628 		if (aff->af_rar != 0 || aff->af_kep != 0 || aff->af_bad != 0
4629 			|| aff->af_needaffix != 0
4630 			|| aff->af_needcomp != 0
4631 			|| compflags != NULL
4632 			|| aff->af_suff.ht_used > 0
4633 			|| aff->af_pref.ht_used > 0)
4634 		    smsg((char_u *)_("FLAG after using flags in %s line %d: %s"),
4635 			    fname, lnum, items[1]);
4636 	    }
4637 	    else if (STRCMP(items[0], "MIDWORD") == 0 && itemcnt == 2
4638 							   && midword == NULL)
4639 	    {
4640 		midword = getroom_save(spin, items[1]);
4641 	    }
4642 	    else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1)
4643 	    {
4644 		/* ignored, we always split */
4645 	    }
4646 	    else if (STRCMP(items[0], "TRY") == 0 && itemcnt == 2)
4647 	    {
4648 		/* ignored, we look in the tree for what chars may appear */
4649 	    }
4650 	    else if (STRCMP(items[0], "SLASH") == 0 && itemcnt == 2
4651 							&& aff->af_slash == 0)
4652 	    {
4653 		aff->af_slash = items[1][0];
4654 		if (items[1][1] != NUL)
4655 		    smsg((char_u *)_("Character used for SLASH must be ASCII; in %s line %d: %s"),
4656 			    fname, lnum, items[1]);
4657 	    }
4658 	    else if (STRCMP(items[0], "RAR") == 0 && itemcnt == 2
4659 						       && aff->af_rar == 0)
4660 	    {
4661 		aff->af_rar = affitem2flag(aff->af_flagtype, items[1],
4662 								 fname, lnum);
4663 	    }
4664 	    else if (STRCMP(items[0], "KEP") == 0 && itemcnt == 2
4665 						       && aff->af_kep == 0)
4666 	    {
4667 		aff->af_kep = affitem2flag(aff->af_flagtype, items[1],
4668 								 fname, lnum);
4669 	    }
4670 	    else if (STRCMP(items[0], "BAD") == 0 && itemcnt == 2
4671 						       && aff->af_bad == 0)
4672 	    {
4673 		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
4674 								 fname, lnum);
4675 	    }
4676 	    else if (STRCMP(items[0], "NEEDAFFIX") == 0 && itemcnt == 2
4677 						    && aff->af_needaffix == 0)
4678 	    {
4679 		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
4680 								 fname, lnum);
4681 	    }
4682 	    else if (STRCMP(items[0], "NEEDCOMPOUND") == 0 && itemcnt == 2
4683 						     && aff->af_needcomp == 0)
4684 	    {
4685 		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
4686 								 fname, lnum);
4687 	    }
4688 	    else if (STRCMP(items[0], "COMPOUNDFLAG") == 0 && itemcnt == 2
4689 							 && compflags == NULL)
4690 	    {
4691 		/* Turn flag "c" into COMPOUNDFLAGS compatible string "c+",
4692 		 * "Na" into "Na+", "1234" into "1234+". */
4693 		p = getroom(spin, STRLEN(items[1]) + 2, FALSE);
4694 		if (p != NULL)
4695 		{
4696 		    STRCPY(p, items[1]);
4697 		    STRCAT(p, "+");
4698 		    compflags = p;
4699 		}
4700 	    }
4701 	    else if (STRCMP(items[0], "COMPOUNDFLAGS") == 0 && itemcnt == 2)
4702 	    {
4703 		/* Concatenate this string to previously defined ones, using a
4704 		 * slash to separate them. */
4705 		l = STRLEN(items[1]) + 1;
4706 		if (compflags != NULL)
4707 		    l += STRLEN(compflags) + 1;
4708 		p = getroom(spin, l, FALSE);
4709 		if (p != NULL)
4710 		{
4711 		    if (compflags != NULL)
4712 		    {
4713 			STRCPY(p, compflags);
4714 			STRCAT(p, "/");
4715 		    }
4716 		    STRCAT(p, items[1]);
4717 		    compflags = p;
4718 		}
4719 	    }
4720 	    else if (STRCMP(items[0], "COMPOUNDMAX") == 0 && itemcnt == 2
4721 							      && compmax == 0)
4722 	    {
4723 		compmax = atoi((char *)items[1]);
4724 		if (compmax == 0)
4725 		    smsg((char_u *)_("Wrong COMPOUNDMAX value in %s line %d: %s"),
4726 						       fname, lnum, items[1]);
4727 	    }
4728 	    else if (STRCMP(items[0], "COMPOUNDMIN") == 0 && itemcnt == 2
4729 							   && compminlen == 0)
4730 	    {
4731 		compminlen = atoi((char *)items[1]);
4732 		if (compminlen == 0)
4733 		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
4734 						       fname, lnum, items[1]);
4735 	    }
4736 	    else if (STRCMP(items[0], "COMPOUNDSYLMAX") == 0 && itemcnt == 2
4737 							   && compsylmax == 0)
4738 	    {
4739 		compsylmax = atoi((char *)items[1]);
4740 		if (compsylmax == 0)
4741 		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
4742 						       fname, lnum, items[1]);
4743 	    }
4744 	    else if (STRCMP(items[0], "SYLLABLE") == 0 && itemcnt == 2
4745 							  && syllable == NULL)
4746 	    {
4747 		syllable = getroom_save(spin, items[1]);
4748 	    }
4749 	    else if (STRCMP(items[0], "NOBREAK") == 0 && itemcnt == 1)
4750 	    {
4751 		spin->si_nobreak = TRUE;
4752 	    }
4753 	    else if (STRCMP(items[0], "PFXPOSTPONE") == 0 && itemcnt == 1)
4754 	    {
4755 		aff->af_pfxpostpone = TRUE;
4756 	    }
4757 	    else if ((STRCMP(items[0], "PFX") == 0
4758 					      || STRCMP(items[0], "SFX") == 0)
4759 		    && aff_todo == 0
4760 		    && itemcnt >= 4)
4761 	    {
4762 		int	lasti = 4;
4763 		char_u	key[AH_KEY_LEN];
4764 
4765 		if (*items[0] == 'P')
4766 		    tp = &aff->af_pref;
4767 		else
4768 		    tp = &aff->af_suff;
4769 
4770 		/* Myspell allows the same affix name to be used multiple
4771 		 * times.  The affix files that do this have an undocumented
4772 		 * "S" flag on all but the last block, thus we check for that
4773 		 * and store it in ah_follows. */
4774 		vim_strncpy(key, items[1], AH_KEY_LEN - 1);
4775 		hi = hash_find(tp, key);
4776 		if (!HASHITEM_EMPTY(hi))
4777 		{
4778 		    cur_aff = HI2AH(hi);
4779 		    if (cur_aff->ah_combine != (*items[2] == 'Y'))
4780 			smsg((char_u *)_("Different combining flag in continued affix block in %s line %d: %s"),
4781 						   fname, lnum, items[1]);
4782 		    if (!cur_aff->ah_follows)
4783 			smsg((char_u *)_("Duplicate affix in %s line %d: %s"),
4784 						       fname, lnum, items[1]);
4785 		}
4786 		else
4787 		{
4788 		    /* New affix letter. */
4789 		    cur_aff = (affheader_T *)getroom(spin,
4790 						   sizeof(affheader_T), TRUE);
4791 		    if (cur_aff == NULL)
4792 			break;
4793 		    cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1],
4794 								 fname, lnum);
4795 		    if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN)
4796 			break;
4797 		    if (cur_aff->ah_flag == aff->af_bad
4798 			    || cur_aff->ah_flag == aff->af_rar
4799 			    || cur_aff->ah_flag == aff->af_kep
4800 			    || cur_aff->ah_flag == aff->af_needaffix
4801 			    || cur_aff->ah_flag == aff->af_needcomp)
4802 			smsg((char_u *)_("Affix also used for BAD/RAR/KEP/NEEDAFFIX/NEEDCOMPOUND in %s line %d: %s"),
4803 						       fname, lnum, items[1]);
4804 		    STRCPY(cur_aff->ah_key, items[1]);
4805 		    hash_add(tp, cur_aff->ah_key);
4806 
4807 		    cur_aff->ah_combine = (*items[2] == 'Y');
4808 		}
4809 
4810 		/* Check for the "S" flag, which apparently means that another
4811 		 * block with the same affix name is following. */
4812 		if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0)
4813 		{
4814 		    ++lasti;
4815 		    cur_aff->ah_follows = TRUE;
4816 		}
4817 		else
4818 		    cur_aff->ah_follows = FALSE;
4819 
4820 		/* Myspell allows extra text after the item, but that might
4821 		 * mean mistakes go unnoticed.  Require a comment-starter. */
4822 		if (itemcnt > lasti && *items[lasti] != '#')
4823 		    smsg((char_u *)_("Trailing text in %s line %d: %s"),
4824 						       fname, lnum, items[4]);
4825 
4826 		if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0)
4827 		    smsg((char_u *)_("Expected Y or N in %s line %d: %s"),
4828 						       fname, lnum, items[2]);
4829 
4830 		if (*items[0] == 'P' && aff->af_pfxpostpone)
4831 		{
4832 		    if (cur_aff->ah_newID == 0)
4833 		    {
4834 			/* Use a new number in the .spl file later, to be able
4835 			 * to handle multiple .aff files. */
4836 			check_renumber(spin);
4837 			cur_aff->ah_newID = ++spin->si_newprefID;
4838 
4839 			/* We only really use ah_newID if the prefix is
4840 			 * postponed.  We know that only after handling all
4841 			 * the items. */
4842 			did_postpone_prefix = FALSE;
4843 		    }
4844 		    else
4845 			/* Did use the ID in a previous block. */
4846 			did_postpone_prefix = TRUE;
4847 		}
4848 
4849 		aff_todo = atoi((char *)items[3]);
4850 	    }
4851 	    else if ((STRCMP(items[0], "PFX") == 0
4852 					      || STRCMP(items[0], "SFX") == 0)
4853 		    && aff_todo > 0
4854 		    && STRCMP(cur_aff->ah_key, items[1]) == 0
4855 		    && itemcnt >= 5)
4856 	    {
4857 		affentry_T	*aff_entry;
4858 		int		rare = FALSE;
4859 		int		nocomp = FALSE;
4860 		int		upper = FALSE;
4861 		int		lasti = 5;
4862 
4863 		/* Check for "rare" and "nocomp" after the other info. */
4864 		while (itemcnt > lasti)
4865 		{
4866 		    if (!rare && STRICMP(items[lasti], "rare") == 0)
4867 		    {
4868 			rare = TRUE;
4869 			++lasti;
4870 		    }
4871 		    else if (!nocomp && STRICMP(items[lasti], "nocomp") == 0)
4872 		    {
4873 			nocomp = TRUE;
4874 			++lasti;
4875 		    }
4876 		    else
4877 			break;
4878 		}
4879 
4880 		/* Myspell allows extra text after the item, but that might
4881 		 * mean mistakes go unnoticed.  Require a comment-starter. */
4882 		if (itemcnt > lasti && *items[lasti] != '#')
4883 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[lasti]);
4884 
4885 		/* New item for an affix letter. */
4886 		--aff_todo;
4887 		aff_entry = (affentry_T *)getroom(spin,
4888 						    sizeof(affentry_T), TRUE);
4889 		if (aff_entry == NULL)
4890 		    break;
4891 		aff_entry->ae_rare = rare;
4892 		aff_entry->ae_nocomp = nocomp;
4893 
4894 		if (STRCMP(items[2], "0") != 0)
4895 		    aff_entry->ae_chop = getroom_save(spin, items[2]);
4896 		if (STRCMP(items[3], "0") != 0)
4897 		    aff_entry->ae_add = getroom_save(spin, items[3]);
4898 
4899 		/* Don't use an affix entry with non-ASCII characters when
4900 		 * "spin->si_ascii" is TRUE. */
4901 		if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop)
4902 					  || has_non_ascii(aff_entry->ae_add)))
4903 		{
4904 		    aff_entry->ae_next = cur_aff->ah_first;
4905 		    cur_aff->ah_first = aff_entry;
4906 
4907 		    if (STRCMP(items[4], ".") != 0)
4908 		    {
4909 			char_u	buf[MAXLINELEN];
4910 
4911 			aff_entry->ae_cond = getroom_save(spin, items[4]);
4912 			if (*items[0] == 'P')
4913 			    sprintf((char *)buf, "^%s", items[4]);
4914 			else
4915 			    sprintf((char *)buf, "%s$", items[4]);
4916 			aff_entry->ae_prog = vim_regcomp(buf,
4917 					    RE_MAGIC + RE_STRING + RE_STRICT);
4918 			if (aff_entry->ae_prog == NULL)
4919 			    smsg((char_u *)_("Broken condition in %s line %d: %s"),
4920 						       fname, lnum, items[4]);
4921 		    }
4922 
4923 		    /* For postponed prefixes we need an entry in si_prefcond
4924 		     * for the condition.  Use an existing one if possible. */
4925 		    if (*items[0] == 'P' && aff->af_pfxpostpone)
4926 		    {
4927 			/* When the chop string is one lower-case letter and
4928 			 * the add string ends in the upper-case letter we set
4929 			 * the "upper" flag, clear "ae_chop" and remove the
4930 			 * letters from "ae_add".  The condition must either
4931 			 * be empty or start with the same letter. */
4932 			if (aff_entry->ae_chop != NULL
4933 				&& aff_entry->ae_add != NULL
4934 #ifdef FEAT_MBYTE
4935 				&& aff_entry->ae_chop[(*mb_ptr2len)(
4936 						   aff_entry->ae_chop)] == NUL
4937 #else
4938 				&& aff_entry->ae_chop[1] == NUL
4939 #endif
4940 				)
4941 			{
4942 			    int		c, c_up;
4943 
4944 			    c = PTR2CHAR(aff_entry->ae_chop);
4945 			    c_up = SPELL_TOUPPER(c);
4946 			    if (c_up != c
4947 				    && (aff_entry->ae_cond == NULL
4948 					|| PTR2CHAR(aff_entry->ae_cond) == c))
4949 			    {
4950 				p = aff_entry->ae_add
4951 						  + STRLEN(aff_entry->ae_add);
4952 				mb_ptr_back(aff_entry->ae_add, p);
4953 				if (PTR2CHAR(p) == c_up)
4954 				{
4955 				    upper = TRUE;
4956 				    aff_entry->ae_chop = NULL;
4957 				    *p = NUL;
4958 
4959 				    /* The condition is matched with the
4960 				     * actual word, thus must check for the
4961 				     * upper-case letter. */
4962 				    if (aff_entry->ae_cond != NULL)
4963 				    {
4964 					char_u	buf[MAXLINELEN];
4965 #ifdef FEAT_MBYTE
4966 					if (has_mbyte)
4967 					{
4968 					    onecap_copy(items[4], buf, TRUE);
4969 					    aff_entry->ae_cond = getroom_save(
4970 								   spin, buf);
4971 					}
4972 					else
4973 #endif
4974 					    *aff_entry->ae_cond = c_up;
4975 					if (aff_entry->ae_cond != NULL)
4976 					{
4977 					    sprintf((char *)buf, "^%s",
4978 							  aff_entry->ae_cond);
4979 					    vim_free(aff_entry->ae_prog);
4980 					    aff_entry->ae_prog = vim_regcomp(
4981 						    buf, RE_MAGIC + RE_STRING);
4982 					}
4983 				    }
4984 				}
4985 			    }
4986 			}
4987 
4988 			if (aff_entry->ae_chop == NULL)
4989 			{
4990 			    int		idx;
4991 			    char_u	**pp;
4992 			    int		n;
4993 
4994 			    /* Find a previously used condition. */
4995 			    for (idx = spin->si_prefcond.ga_len - 1; idx >= 0;
4996 									--idx)
4997 			    {
4998 				p = ((char_u **)spin->si_prefcond.ga_data)[idx];
4999 				if (str_equal(p, aff_entry->ae_cond))
5000 				    break;
5001 			    }
5002 			    if (idx < 0 && ga_grow(&spin->si_prefcond, 1) == OK)
5003 			    {
5004 				/* Not found, add a new condition. */
5005 				idx = spin->si_prefcond.ga_len++;
5006 				pp = ((char_u **)spin->si_prefcond.ga_data)
5007 									+ idx;
5008 				if (aff_entry->ae_cond == NULL)
5009 				    *pp = NULL;
5010 				else
5011 				    *pp = getroom_save(spin,
5012 							  aff_entry->ae_cond);
5013 			    }
5014 
5015 			    /* Add the prefix to the prefix tree. */
5016 			    if (aff_entry->ae_add == NULL)
5017 				p = (char_u *)"";
5018 			    else
5019 				p = aff_entry->ae_add;
5020 			    /* PFX_FLAGS is a negative number, so that
5021 			     * tree_add_word() knows this is the prefix tree. */
5022 			    n = PFX_FLAGS;
5023 			    if (rare)
5024 				n |= WFP_RARE;
5025 			    if (!cur_aff->ah_combine)
5026 				n |= WFP_NC;
5027 			    if (upper)
5028 				n |= WFP_UP;
5029 			    tree_add_word(spin, p, spin->si_prefroot, n,
5030 						      idx, cur_aff->ah_newID);
5031 			    did_postpone_prefix = TRUE;
5032 			}
5033 
5034 			/* Didn't actually use ah_newID, backup si_newprefID. */
5035 			if (aff_todo == 0 && !did_postpone_prefix)
5036 			{
5037 			    --spin->si_newprefID;
5038 			    cur_aff->ah_newID = 0;
5039 			}
5040 		    }
5041 		}
5042 	    }
5043 	    else if (STRCMP(items[0], "FOL") == 0 && itemcnt == 2
5044 							       && fol == NULL)
5045 	    {
5046 		fol = vim_strsave(items[1]);
5047 	    }
5048 	    else if (STRCMP(items[0], "LOW") == 0 && itemcnt == 2
5049 							       && low == NULL)
5050 	    {
5051 		low = vim_strsave(items[1]);
5052 	    }
5053 	    else if (STRCMP(items[0], "UPP") == 0 && itemcnt == 2
5054 							       && upp == NULL)
5055 	    {
5056 		upp = vim_strsave(items[1]);
5057 	    }
5058 	    else if (STRCMP(items[0], "REP") == 0 && itemcnt == 2)
5059 	    {
5060 		/* Ignore REP count */;
5061 		if (!isdigit(*items[1]))
5062 		    smsg((char_u *)_("Expected REP count in %s line %d"),
5063 								 fname, lnum);
5064 	    }
5065 	    else if (STRCMP(items[0], "REP") == 0 && itemcnt >= 3)
5066 	    {
5067 		/* REP item */
5068 		/* Myspell ignores extra arguments, we require it starts with
5069 		 * # to detect mistakes. */
5070 		if (itemcnt > 3 && items[3][0] != '#')
5071 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[3]);
5072 		if (do_rep)
5073 		{
5074 		    /* Replace underscore with space (can't include a space
5075 		     * directly). */
5076 		    for (p = items[1]; *p != NUL; mb_ptr_adv(p))
5077 			if (*p == '_')
5078 			    *p = ' ';
5079 		    for (p = items[2]; *p != NUL; mb_ptr_adv(p))
5080 			if (*p == '_')
5081 			    *p = ' ';
5082 		    add_fromto(spin, &spin->si_rep, items[1], items[2]);
5083 		}
5084 	    }
5085 	    else if (STRCMP(items[0], "MAP") == 0 && itemcnt == 2)
5086 	    {
5087 		/* MAP item or count */
5088 		if (!found_map)
5089 		{
5090 		    /* First line contains the count. */
5091 		    found_map = TRUE;
5092 		    if (!isdigit(*items[1]))
5093 			smsg((char_u *)_("Expected MAP count in %s line %d"),
5094 								 fname, lnum);
5095 		}
5096 		else if (do_map)
5097 		{
5098 		    int		c;
5099 
5100 		    /* Check that every character appears only once. */
5101 		    for (p = items[1]; *p != NUL; )
5102 		    {
5103 #ifdef FEAT_MBYTE
5104 			c = mb_ptr2char_adv(&p);
5105 #else
5106 			c = *p++;
5107 #endif
5108 			if ((spin->si_map.ga_len > 0
5109 				    && vim_strchr(spin->si_map.ga_data, c)
5110 								      != NULL)
5111 				|| vim_strchr(p, c) != NULL)
5112 			    smsg((char_u *)_("Duplicate character in MAP in %s line %d"),
5113 								 fname, lnum);
5114 		    }
5115 
5116 		    /* We simply concatenate all the MAP strings, separated by
5117 		     * slashes. */
5118 		    ga_concat(&spin->si_map, items[1]);
5119 		    ga_append(&spin->si_map, '/');
5120 		}
5121 	    }
5122 	    /* Accept "SAL from to" and "SAL from to # comment". */
5123 	    else if (STRCMP(items[0], "SAL") == 0
5124 		    && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#')))
5125 	    {
5126 		if (do_sal)
5127 		{
5128 		    /* SAL item (sounds-a-like)
5129 		     * Either one of the known keys or a from-to pair. */
5130 		    if (STRCMP(items[1], "followup") == 0)
5131 			spin->si_followup = sal_to_bool(items[2]);
5132 		    else if (STRCMP(items[1], "collapse_result") == 0)
5133 			spin->si_collapse = sal_to_bool(items[2]);
5134 		    else if (STRCMP(items[1], "remove_accents") == 0)
5135 			spin->si_rem_accents = sal_to_bool(items[2]);
5136 		    else
5137 			/* when "to" is "_" it means empty */
5138 			add_fromto(spin, &spin->si_sal, items[1],
5139 				     STRCMP(items[2], "_") == 0 ? (char_u *)""
5140 								: items[2]);
5141 		}
5142 	    }
5143 	    else if (STRCMP(items[0], "SOFOFROM") == 0 && itemcnt == 2
5144 							  && sofofrom == NULL)
5145 	    {
5146 		sofofrom = getroom_save(spin, items[1]);
5147 	    }
5148 	    else if (STRCMP(items[0], "SOFOTO") == 0 && itemcnt == 2
5149 							    && sofoto == NULL)
5150 	    {
5151 		sofoto = getroom_save(spin, items[1]);
5152 	    }
5153 	    else
5154 		smsg((char_u *)_("Unrecognized or duplicate item in %s line %d: %s"),
5155 						       fname, lnum, items[0]);
5156 	}
5157     }
5158 
5159     if (fol != NULL || low != NULL || upp != NULL)
5160     {
5161 	if (spin->si_clear_chartab)
5162 	{
5163 	    /* Clear the char type tables, don't want to use any of the
5164 	     * currently used spell properties. */
5165 	    init_spell_chartab();
5166 	    spin->si_clear_chartab = FALSE;
5167 	}
5168 
5169 	/*
5170 	 * Don't write a word table for an ASCII file, so that we don't check
5171 	 * for conflicts with a word table that matches 'encoding'.
5172 	 * Don't write one for utf-8 either, we use utf_*() and
5173 	 * mb_get_class(), the list of chars in the file will be incomplete.
5174 	 */
5175 	if (!spin->si_ascii
5176 #ifdef FEAT_MBYTE
5177 		&& !enc_utf8
5178 #endif
5179 		)
5180 	{
5181 	    if (fol == NULL || low == NULL || upp == NULL)
5182 		smsg((char_u *)_("Missing FOL/LOW/UPP line in %s"), fname);
5183 	    else
5184 		(void)set_spell_chartab(fol, low, upp);
5185 	}
5186 
5187 	vim_free(fol);
5188 	vim_free(low);
5189 	vim_free(upp);
5190     }
5191 
5192     /* Use compound specifications of the .aff file for the spell info. */
5193     if (compmax != 0)
5194     {
5195 	aff_check_number(spin->si_compmax, compmax, "COMPOUNDMAX");
5196 	spin->si_compmax = compmax;
5197     }
5198 
5199     if (compminlen != 0)
5200     {
5201 	aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN");
5202 	spin->si_compminlen = compminlen;
5203     }
5204 
5205     if (compsylmax != 0)
5206     {
5207 	if (syllable == NULL)
5208 	    smsg((char_u *)_("COMPOUNDSYLMAX used without SYLLABLE"));
5209 	aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX");
5210 	spin->si_compsylmax = compsylmax;
5211     }
5212 
5213     if (compflags != NULL)
5214 	process_compflags(spin, aff, compflags);
5215 
5216     /* Check that we didn't use too many renumbered flags. */
5217     if (spin->si_newcompID < spin->si_newprefID)
5218     {
5219 	if (spin->si_newcompID == 127 || spin->si_newcompID == 255)
5220 	    MSG(_("Too many postponed prefixes"));
5221 	else if (spin->si_newprefID == 0 || spin->si_newprefID == 127)
5222 	    MSG(_("Too many compound flags"));
5223 	else
5224 	    MSG(_("Too many posponed prefixes and/or compound flags"));
5225     }
5226 
5227     if (syllable != NULL)
5228     {
5229 	aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
5230 	spin->si_syllable = syllable;
5231     }
5232 
5233     if (sofofrom != NULL || sofoto != NULL)
5234     {
5235 	if (sofofrom == NULL || sofoto == NULL)
5236 	    smsg((char_u *)_("Missing SOFO%s line in %s"),
5237 				     sofofrom == NULL ? "FROM" : "TO", fname);
5238 	else if (spin->si_sal.ga_len > 0)
5239 	    smsg((char_u *)_("Both SAL and SOFO lines in %s"), fname);
5240 	else
5241 	{
5242 	    aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
5243 	    aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
5244 	    spin->si_sofofr = sofofrom;
5245 	    spin->si_sofoto = sofoto;
5246 	}
5247     }
5248 
5249     if (midword != NULL)
5250     {
5251 	aff_check_string(spin->si_midword, midword, "MIDWORD");
5252 	spin->si_midword = midword;
5253     }
5254 
5255     vim_free(pc);
5256     fclose(fd);
5257     return aff;
5258 }
5259 
5260 /*
5261  * Turn an affix flag name into a number, according to the FLAG type.
5262  * returns zero for failure.
5263  */
5264     static unsigned
5265 affitem2flag(flagtype, item, fname, lnum)
5266     int		flagtype;
5267     char_u	*item;
5268     char_u	*fname;
5269     int		lnum;
5270 {
5271     unsigned	res;
5272     char_u	*p = item;
5273 
5274     res = get_affitem(flagtype, &p);
5275     if (res == 0)
5276     {
5277 	if (flagtype == AFT_NUM)
5278 	    smsg((char_u *)_("Flag is not a number in %s line %d: %s"),
5279 							   fname, lnum, item);
5280 	else
5281 	    smsg((char_u *)_("Illegal flag in %s line %d: %s"),
5282 							   fname, lnum, item);
5283     }
5284     if (*p != NUL)
5285     {
5286 	smsg((char_u *)_(e_affname), fname, lnum, item);
5287 	return 0;
5288     }
5289 
5290     return res;
5291 }
5292 
5293 /*
5294  * Get one affix name from "*pp" and advance the pointer.
5295  * Returns zero for an error, still advances the pointer then.
5296  */
5297     static unsigned
5298 get_affitem(flagtype, pp)
5299     int		flagtype;
5300     char_u	**pp;
5301 {
5302     int		res;
5303 
5304     if (flagtype == AFT_NUM)
5305     {
5306 	if (!VIM_ISDIGIT(**pp))
5307 	{
5308 	    ++*pp;	/* always advance, avoid getting stuck */
5309 	    return 0;
5310 	}
5311 	res = getdigits(pp);
5312     }
5313     else
5314     {
5315 #ifdef FEAT_MBYTE
5316 	res = mb_ptr2char_adv(pp);
5317 #else
5318 	res = *(*pp)++;
5319 #endif
5320 	if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
5321 						 && res >= 'A' && res <= 'Z'))
5322 	{
5323 	    if (**pp == NUL)
5324 		return 0;
5325 #ifdef FEAT_MBYTE
5326 	    res = mb_ptr2char_adv(pp) + (res << 16);
5327 #else
5328 	    res = *(*pp)++ + (res << 16);
5329 #endif
5330 	}
5331     }
5332     return res;
5333 }
5334 
5335 /*
5336  * Process the "compflags" string used in an affix file and append it to
5337  * spin->si_compflags.
5338  * The processing involves changing the affix names to ID numbers, so that
5339  * they fit in one byte.
5340  */
5341     static void
5342 process_compflags(spin, aff, compflags)
5343     spellinfo_T	*spin;
5344     afffile_T	*aff;
5345     char_u	*compflags;
5346 {
5347     char_u	*p;
5348     char_u	*prevp;
5349     unsigned	flag;
5350     compitem_T	*ci;
5351     int		id;
5352     int		len;
5353     char_u	*tp;
5354     char_u	key[AH_KEY_LEN];
5355     hashitem_T	*hi;
5356 
5357     /* Make room for the old and the new compflags, concatenated with a / in
5358      * between.  Processing it makes it shorter, but we don't know by how
5359      * much, thus allocate the maximum. */
5360     len = STRLEN(compflags) + 1;
5361     if (spin->si_compflags != NULL)
5362 	len += STRLEN(spin->si_compflags) + 1;
5363     p = getroom(spin, len, FALSE);
5364     if (p == NULL)
5365 	return;
5366     if (spin->si_compflags != NULL)
5367     {
5368 	STRCPY(p, spin->si_compflags);
5369 	STRCAT(p, "/");
5370     }
5371     spin->si_compflags = p;
5372     tp = p + STRLEN(p);
5373 
5374     for (p = compflags; *p != NUL; )
5375     {
5376 	if (vim_strchr((char_u *)"/*+[]", *p) != NULL)
5377 	    /* Copy non-flag characters directly. */
5378 	    *tp++ = *p++;
5379 	else
5380 	{
5381 	    /* First get the flag number, also checks validity. */
5382 	    prevp = p;
5383 	    flag = get_affitem(aff->af_flagtype, &p);
5384 	    if (flag != 0)
5385 	    {
5386 		/* Find the flag in the hashtable.  If it was used before, use
5387 		 * the existing ID.  Otherwise add a new entry. */
5388 		vim_strncpy(key, prevp, p - prevp);
5389 		hi = hash_find(&aff->af_comp, key);
5390 		if (!HASHITEM_EMPTY(hi))
5391 		    id = HI2CI(hi)->ci_newID;
5392 		else
5393 		{
5394 		    ci = (compitem_T *)getroom(spin, sizeof(compitem_T), TRUE);
5395 		    if (ci == NULL)
5396 			break;
5397 		    STRCPY(ci->ci_key, key);
5398 		    ci->ci_flag = flag;
5399 		    /* Avoid using a flag ID that has a special meaning in a
5400 		     * regexp (also inside []). */
5401 		    do
5402 		    {
5403 			check_renumber(spin);
5404 			id = spin->si_newcompID--;
5405 		    } while (vim_strchr((char_u *)"/+*[]\\-^", id) != NULL);
5406 		    ci->ci_newID = id;
5407 		    hash_add(&aff->af_comp, ci->ci_key);
5408 		}
5409 		*tp++ = id;
5410 	    }
5411 	    if (aff->af_flagtype == AFT_NUM && *p == ',')
5412 		++p;
5413 	}
5414     }
5415 
5416     *tp = NUL;
5417 }
5418 
5419 /*
5420  * Check that the new IDs for postponed affixes and compounding don't overrun
5421  * each other.  We have almost 255 available, but start at 0-127 to avoid
5422  * using two bytes for utf-8.  When the 0-127 range is used up go to 128-255.
5423  * When that is used up an error message is given.
5424  */
5425     static void
5426 check_renumber(spin)
5427     spellinfo_T	*spin;
5428 {
5429     if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128)
5430     {
5431 	spin->si_newprefID = 127;
5432 	spin->si_newcompID = 255;
5433     }
5434 }
5435 
5436 /*
5437  * Return TRUE if flag "flag" appears in affix list "afflist".
5438  */
5439     static int
5440 flag_in_afflist(flagtype, afflist, flag)
5441     int		flagtype;
5442     char_u	*afflist;
5443     unsigned	flag;
5444 {
5445     char_u	*p;
5446     unsigned	n;
5447 
5448     switch (flagtype)
5449     {
5450 	case AFT_CHAR:
5451 	    return vim_strchr(afflist, flag) != NULL;
5452 
5453 	case AFT_CAPLONG:
5454 	case AFT_LONG:
5455 	    for (p = afflist; *p != NUL; )
5456 	    {
5457 #ifdef FEAT_MBYTE
5458 		n = mb_ptr2char_adv(&p);
5459 #else
5460 		n = *p++;
5461 #endif
5462 		if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
5463 								 && *p != NUL)
5464 #ifdef FEAT_MBYTE
5465 		    n = mb_ptr2char_adv(&p) + (n << 16);
5466 #else
5467 		    n = *p++ + (n << 16);
5468 #endif
5469 		if (n == flag)
5470 		    return TRUE;
5471 	    }
5472 	    break;
5473 
5474 	case AFT_NUM:
5475 	    for (p = afflist; *p != NUL; )
5476 	    {
5477 		n = getdigits(&p);
5478 		if (n == flag)
5479 		    return TRUE;
5480 		if (*p != NUL)	/* skip over comma */
5481 		    ++p;
5482 	    }
5483 	    break;
5484     }
5485     return FALSE;
5486 }
5487 
5488 /*
5489  * Give a warning when "spinval" and "affval" numbers are set and not the same.
5490  */
5491     static void
5492 aff_check_number(spinval, affval, name)
5493     int	    spinval;
5494     int	    affval;
5495     char    *name;
5496 {
5497     if (spinval != 0 && spinval != affval)
5498 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
5499 }
5500 
5501 /*
5502  * Give a warning when "spinval" and "affval" strings are set and not the same.
5503  */
5504     static void
5505 aff_check_string(spinval, affval, name)
5506     char_u	*spinval;
5507     char_u	*affval;
5508     char	*name;
5509 {
5510     if (spinval != NULL && STRCMP(spinval, affval) != 0)
5511 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
5512 }
5513 
5514 /*
5515  * Return TRUE if strings "s1" and "s2" are equal.  Also consider both being
5516  * NULL as equal.
5517  */
5518     static int
5519 str_equal(s1, s2)
5520     char_u	*s1;
5521     char_u	*s2;
5522 {
5523     if (s1 == NULL || s2 == NULL)
5524 	return s1 == s2;
5525     return STRCMP(s1, s2) == 0;
5526 }
5527 
5528 /*
5529  * Add a from-to item to "gap".  Used for REP and SAL items.
5530  * They are stored case-folded.
5531  */
5532     static void
5533 add_fromto(spin, gap, from, to)
5534     spellinfo_T	*spin;
5535     garray_T	*gap;
5536     char_u	*from;
5537     char_u	*to;
5538 {
5539     fromto_T	*ftp;
5540     char_u	word[MAXWLEN];
5541 
5542     if (ga_grow(gap, 1) == OK)
5543     {
5544 	ftp = ((fromto_T *)gap->ga_data) + gap->ga_len;
5545 	(void)spell_casefold(from, STRLEN(from), word, MAXWLEN);
5546 	ftp->ft_from = getroom_save(spin, word);
5547 	(void)spell_casefold(to, STRLEN(to), word, MAXWLEN);
5548 	ftp->ft_to = getroom_save(spin, word);
5549 	++gap->ga_len;
5550     }
5551 }
5552 
5553 /*
5554  * Convert a boolean argument in a SAL line to TRUE or FALSE;
5555  */
5556     static int
5557 sal_to_bool(s)
5558     char_u	*s;
5559 {
5560     return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0;
5561 }
5562 
5563 /*
5564  * Return TRUE if string "s" contains a non-ASCII character (128 or higher).
5565  * When "s" is NULL FALSE is returned.
5566  */
5567     static int
5568 has_non_ascii(s)
5569     char_u	*s;
5570 {
5571     char_u	*p;
5572 
5573     if (s != NULL)
5574 	for (p = s; *p != NUL; ++p)
5575 	    if (*p >= 128)
5576 		return TRUE;
5577     return FALSE;
5578 }
5579 
5580 /*
5581  * Free the structure filled by spell_read_aff().
5582  */
5583     static void
5584 spell_free_aff(aff)
5585     afffile_T	*aff;
5586 {
5587     hashtab_T	*ht;
5588     hashitem_T	*hi;
5589     int		todo;
5590     affheader_T	*ah;
5591     affentry_T	*ae;
5592 
5593     vim_free(aff->af_enc);
5594 
5595     /* All this trouble to free the "ae_prog" items... */
5596     for (ht = &aff->af_pref; ; ht = &aff->af_suff)
5597     {
5598 	todo = ht->ht_used;
5599 	for (hi = ht->ht_array; todo > 0; ++hi)
5600 	{
5601 	    if (!HASHITEM_EMPTY(hi))
5602 	    {
5603 		--todo;
5604 		ah = HI2AH(hi);
5605 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
5606 		    vim_free(ae->ae_prog);
5607 	    }
5608 	}
5609 	if (ht == &aff->af_suff)
5610 	    break;
5611     }
5612 
5613     hash_clear(&aff->af_pref);
5614     hash_clear(&aff->af_suff);
5615     hash_clear(&aff->af_comp);
5616 }
5617 
5618 /*
5619  * Read dictionary file "fname".
5620  * Returns OK or FAIL;
5621  */
5622     static int
5623 spell_read_dic(spin, fname, affile)
5624     spellinfo_T	*spin;
5625     char_u	*fname;
5626     afffile_T	*affile;
5627 {
5628     hashtab_T	ht;
5629     char_u	line[MAXLINELEN];
5630     char_u	*p;
5631     char_u	*afflist;
5632     char_u	store_afflist[MAXWLEN];
5633     int		pfxlen;
5634     int		need_affix;
5635     char_u	*dw;
5636     char_u	*pc;
5637     char_u	*w;
5638     int		l;
5639     hash_T	hash;
5640     hashitem_T	*hi;
5641     FILE	*fd;
5642     int		lnum = 1;
5643     int		non_ascii = 0;
5644     int		retval = OK;
5645     char_u	message[MAXLINELEN + MAXWLEN];
5646     int		flags;
5647     int		duplicate = 0;
5648 
5649     /*
5650      * Open the file.
5651      */
5652     fd = mch_fopen((char *)fname, "r");
5653     if (fd == NULL)
5654     {
5655 	EMSG2(_(e_notopen), fname);
5656 	return FAIL;
5657     }
5658 
5659     /* The hashtable is only used to detect duplicated words. */
5660     hash_init(&ht);
5661 
5662     if (spin->si_verbose || p_verbose > 2)
5663     {
5664 	if (!spin->si_verbose)
5665 	    verbose_enter();
5666 	smsg((char_u *)_("Reading dictionary file %s ..."), fname);
5667 	out_flush();
5668 	if (!spin->si_verbose)
5669 	    verbose_leave();
5670     }
5671 
5672     /* start with a message for the first line */
5673     spin->si_msg_count = 999999;
5674 
5675     /* Read and ignore the first line: word count. */
5676     (void)vim_fgets(line, MAXLINELEN, fd);
5677     if (!vim_isdigit(*skipwhite(line)))
5678 	EMSG2(_("E760: No word count in %s"), fname);
5679 
5680     /*
5681      * Read all the lines in the file one by one.
5682      * The words are converted to 'encoding' here, before being added to
5683      * the hashtable.
5684      */
5685     while (!vim_fgets(line, MAXLINELEN, fd) && !got_int)
5686     {
5687 	line_breakcheck();
5688 	++lnum;
5689 	if (line[0] == '#' || line[0] == '/')
5690 	    continue;	/* comment line */
5691 
5692 	/* Remove CR, LF and white space from the end.  White space halfway
5693 	 * the word is kept to allow e.g., "et al.". */
5694 	l = STRLEN(line);
5695 	while (l > 0 && line[l - 1] <= ' ')
5696 	    --l;
5697 	if (l == 0)
5698 	    continue;	/* empty line */
5699 	line[l] = NUL;
5700 
5701 	/* Find the optional affix names.  Replace the SLASH character by a
5702 	 * slash. */
5703 	afflist = NULL;
5704 	for (p = line; *p != NUL; mb_ptr_adv(p))
5705 	{
5706 	    if (*p == affile->af_slash)
5707 		*p = '/';
5708 	    else if (*p == '/')
5709 	    {
5710 		*p = NUL;
5711 		afflist = p + 1;
5712 		break;
5713 	    }
5714 	}
5715 
5716 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
5717 	if (spin->si_ascii && has_non_ascii(line))
5718 	{
5719 	    ++non_ascii;
5720 	    continue;
5721 	}
5722 
5723 #ifdef FEAT_MBYTE
5724 	/* Convert from "SET" to 'encoding' when needed. */
5725 	if (spin->si_conv.vc_type != CONV_NONE)
5726 	{
5727 	    pc = string_convert(&spin->si_conv, line, NULL);
5728 	    if (pc == NULL)
5729 	    {
5730 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
5731 						       fname, lnum, line);
5732 		continue;
5733 	    }
5734 	    w = pc;
5735 	}
5736 	else
5737 #endif
5738 	{
5739 	    pc = NULL;
5740 	    w = line;
5741 	}
5742 
5743 	/* This takes time, print a message every 10000 words. */
5744 	if (spin->si_verbose && spin->si_msg_count > 10000)
5745 	{
5746 	    spin->si_msg_count = 0;
5747 	    vim_snprintf((char *)message, sizeof(message),
5748 		    _("line %6d, word %6d - %s"),
5749 		       lnum, spin->si_foldwcount + spin->si_keepwcount, w);
5750 	    msg_start();
5751 	    msg_puts_long_attr(message, 0);
5752 	    msg_clr_eos();
5753 	    msg_didout = FALSE;
5754 	    msg_col = 0;
5755 	    out_flush();
5756 	}
5757 
5758 	/* Store the word in the hashtable to be able to find duplicates. */
5759 	dw = (char_u *)getroom_save(spin, w);
5760 	if (dw == NULL)
5761 	    retval = FAIL;
5762 	vim_free(pc);
5763 	if (retval == FAIL)
5764 	    break;
5765 
5766 	hash = hash_hash(dw);
5767 	hi = hash_lookup(&ht, dw, hash);
5768 	if (!HASHITEM_EMPTY(hi))
5769 	{
5770 	    if (p_verbose > 0)
5771 		smsg((char_u *)_("Duplicate word in %s line %d: %s"),
5772 							     fname, lnum, dw);
5773 	    else if (duplicate == 0)
5774 		smsg((char_u *)_("First duplicate word in %s line %d: %s"),
5775 							     fname, lnum, dw);
5776 	    ++duplicate;
5777 	}
5778 	else
5779 	    hash_add_item(&ht, hi, dw, hash);
5780 
5781 	flags = 0;
5782 	store_afflist[0] = NUL;
5783 	pfxlen = 0;
5784 	need_affix = FALSE;
5785 	if (afflist != NULL)
5786 	{
5787 	    /* Check for affix name that stands for keep-case word and stands
5788 	     * for rare word (if defined). */
5789 	    if (affile->af_kep != 0 && flag_in_afflist(
5790 				affile->af_flagtype, afflist, affile->af_kep))
5791 		flags |= WF_KEEPCAP | WF_FIXCAP;
5792 	    if (affile->af_rar != 0 && flag_in_afflist(
5793 				affile->af_flagtype, afflist, affile->af_rar))
5794 		flags |= WF_RARE;
5795 	    if (affile->af_bad != 0 && flag_in_afflist(
5796 				affile->af_flagtype, afflist, affile->af_bad))
5797 		flags |= WF_BANNED;
5798 	    if (affile->af_needaffix != 0 && flag_in_afflist(
5799 			  affile->af_flagtype, afflist, affile->af_needaffix))
5800 		need_affix = TRUE;
5801 	    if (affile->af_needcomp != 0 && flag_in_afflist(
5802 			   affile->af_flagtype, afflist, affile->af_needcomp))
5803 		flags |= WF_NEEDCOMP;
5804 
5805 	    if (affile->af_pfxpostpone)
5806 		/* Need to store the list of prefix IDs with the word. */
5807 		pfxlen = get_pfxlist(affile, afflist, store_afflist);
5808 
5809 	    if (spin->si_compflags != NULL)
5810 		/* Need to store the list of compound flags with the word.
5811 		 * Concatenate them to the list of prefix IDs. */
5812 		get_compflags(affile, afflist, store_afflist + pfxlen);
5813 	}
5814 
5815 	/* Add the word to the word tree(s). */
5816 	if (store_word(spin, dw, flags, spin->si_region,
5817 					   store_afflist, need_affix) == FAIL)
5818 	    retval = FAIL;
5819 
5820 	if (afflist != NULL)
5821 	{
5822 	    /* Find all matching suffixes and add the resulting words.
5823 	     * Additionally do matching prefixes that combine. */
5824 	    if (store_aff_word(spin, dw, afflist, affile,
5825 			   &affile->af_suff, &affile->af_pref,
5826 				 FALSE, flags, store_afflist, pfxlen) == FAIL)
5827 		retval = FAIL;
5828 
5829 	    /* Find all matching prefixes and add the resulting words. */
5830 	    if (store_aff_word(spin, dw, afflist, affile,
5831 			  &affile->af_pref, NULL,
5832 				 FALSE, flags, store_afflist, pfxlen) == FAIL)
5833 		retval = FAIL;
5834 	}
5835     }
5836 
5837     if (duplicate > 0)
5838 	smsg((char_u *)_("%d duplicate word(s) in %s"), duplicate, fname);
5839     if (spin->si_ascii && non_ascii > 0)
5840 	smsg((char_u *)_("Ignored %d word(s) with non-ASCII characters in %s"),
5841 							    non_ascii, fname);
5842     hash_clear(&ht);
5843 
5844     fclose(fd);
5845     return retval;
5846 }
5847 
5848 /*
5849  * Get the list of prefix IDs from the affix list "afflist".
5850  * Used for PFXPOSTPONE.
5851  * Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
5852  * and return the number of affixes.
5853  */
5854     static int
5855 get_pfxlist(affile, afflist, store_afflist)
5856     afffile_T	*affile;
5857     char_u	*afflist;
5858     char_u	*store_afflist;
5859 {
5860     char_u	*p;
5861     char_u	*prevp;
5862     int		cnt = 0;
5863     int		id;
5864     char_u	key[AH_KEY_LEN];
5865     hashitem_T	*hi;
5866 
5867     for (p = afflist; *p != NUL; )
5868     {
5869 	prevp = p;
5870 	if (get_affitem(affile->af_flagtype, &p) != 0)
5871 	{
5872 	    /* A flag is a postponed prefix flag if it appears in "af_pref"
5873 	     * and it's ID is not zero. */
5874 	    vim_strncpy(key, prevp, p - prevp);
5875 	    hi = hash_find(&affile->af_pref, key);
5876 	    if (!HASHITEM_EMPTY(hi))
5877 	    {
5878 		id = HI2AH(hi)->ah_newID;
5879 		if (id != 0)
5880 		    store_afflist[cnt++] = id;
5881 	    }
5882 	}
5883 	if (affile->af_flagtype == AFT_NUM && *p == ',')
5884 	    ++p;
5885     }
5886 
5887     store_afflist[cnt] = NUL;
5888     return cnt;
5889 }
5890 
5891 /*
5892  * Get the list of compound IDs from the affix list "afflist" that are used
5893  * for compound words.
5894  * Puts the flags in "store_afflist[]".
5895  */
5896     static void
5897 get_compflags(affile, afflist, store_afflist)
5898     afffile_T	*affile;
5899     char_u	*afflist;
5900     char_u	*store_afflist;
5901 {
5902     char_u	*p;
5903     char_u	*prevp;
5904     int		cnt = 0;
5905     char_u	key[AH_KEY_LEN];
5906     hashitem_T	*hi;
5907 
5908     for (p = afflist; *p != NUL; )
5909     {
5910 	prevp = p;
5911 	if (get_affitem(affile->af_flagtype, &p) != 0)
5912 	{
5913 	    /* A flag is a compound flag if it appears in "af_comp". */
5914 	    vim_strncpy(key, prevp, p - prevp);
5915 	    hi = hash_find(&affile->af_comp, key);
5916 	    if (!HASHITEM_EMPTY(hi))
5917 		store_afflist[cnt++] = HI2CI(hi)->ci_newID;
5918 	}
5919 	if (affile->af_flagtype == AFT_NUM && *p == ',')
5920 	    ++p;
5921     }
5922 
5923     store_afflist[cnt] = NUL;
5924 }
5925 
5926 /*
5927  * Apply affixes to a word and store the resulting words.
5928  * "ht" is the hashtable with affentry_T that need to be applied, either
5929  * prefixes or suffixes.
5930  * "xht", when not NULL, is the prefix hashtable, to be used additionally on
5931  * the resulting words for combining affixes.
5932  *
5933  * Returns FAIL when out of memory.
5934  */
5935     static int
5936 store_aff_word(spin, word, afflist, affile, ht, xht, comb, flags,
5937 							      pfxlist, pfxlen)
5938     spellinfo_T	*spin;		/* spell info */
5939     char_u	*word;		/* basic word start */
5940     char_u	*afflist;	/* list of names of supported affixes */
5941     afffile_T	*affile;
5942     hashtab_T	*ht;
5943     hashtab_T	*xht;
5944     int		comb;		/* only use affixes that combine */
5945     int		flags;		/* flags for the word */
5946     char_u	*pfxlist;	/* list of prefix IDs */
5947     int		pfxlen;		/* nr of flags in "pfxlist" for prefixes, rest
5948 				 * is compound flags */
5949 {
5950     int		todo;
5951     hashitem_T	*hi;
5952     affheader_T	*ah;
5953     affentry_T	*ae;
5954     regmatch_T	regmatch;
5955     char_u	newword[MAXWLEN];
5956     int		retval = OK;
5957     int		i;
5958     char_u	*p;
5959     int		use_flags;
5960     char_u	*use_pfxlist;
5961     char_u	pfx_pfxlist[MAXWLEN];
5962     size_t	wordlen = STRLEN(word);
5963 
5964     todo = ht->ht_used;
5965     for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi)
5966     {
5967 	if (!HASHITEM_EMPTY(hi))
5968 	{
5969 	    --todo;
5970 	    ah = HI2AH(hi);
5971 
5972 	    /* Check that the affix combines, if required, and that the word
5973 	     * supports this affix. */
5974 	    if ((!comb || ah->ah_combine) && flag_in_afflist(
5975 				   affile->af_flagtype, afflist, ah->ah_flag))
5976 	    {
5977 		/* Loop over all affix entries with this name. */
5978 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
5979 		{
5980 		    /* Check the condition.  It's not logical to match case
5981 		     * here, but it is required for compatibility with
5982 		     * Myspell.
5983 		     * Another requirement from Myspell is that the chop
5984 		     * string is shorter than the word itself.
5985 		     * For prefixes, when "PFXPOSTPONE" was used, only do
5986 		     * prefixes with a chop string. */
5987 		    regmatch.regprog = ae->ae_prog;
5988 		    regmatch.rm_ic = FALSE;
5989 		    if ((xht != NULL || !affile->af_pfxpostpone
5990 				|| ae->ae_chop != NULL)
5991 			    && (ae->ae_chop == NULL
5992 				|| STRLEN(ae->ae_chop) < wordlen)
5993 			    && (ae->ae_prog == NULL
5994 				|| vim_regexec(&regmatch, word, (colnr_T)0)))
5995 		    {
5996 			/* Match.  Remove the chop and add the affix. */
5997 			if (xht == NULL)
5998 			{
5999 			    /* prefix: chop/add at the start of the word */
6000 			    if (ae->ae_add == NULL)
6001 				*newword = NUL;
6002 			    else
6003 				STRCPY(newword, ae->ae_add);
6004 			    p = word;
6005 			    if (ae->ae_chop != NULL)
6006 			    {
6007 				/* Skip chop string. */
6008 #ifdef FEAT_MBYTE
6009 				if (has_mbyte)
6010 				{
6011 				    i = mb_charlen(ae->ae_chop);
6012 				    for ( ; i > 0; --i)
6013 					mb_ptr_adv(p);
6014 				}
6015 				else
6016 #endif
6017 				    p += STRLEN(ae->ae_chop);
6018 			    }
6019 			    STRCAT(newword, p);
6020 			}
6021 			else
6022 			{
6023 			    /* suffix: chop/add at the end of the word */
6024 			    STRCPY(newword, word);
6025 			    if (ae->ae_chop != NULL)
6026 			    {
6027 				/* Remove chop string. */
6028 				p = newword + STRLEN(newword);
6029 				i = MB_CHARLEN(ae->ae_chop);
6030 				for ( ; i > 0; --i)
6031 				    mb_ptr_back(newword, p);
6032 				*p = NUL;
6033 			    }
6034 			    if (ae->ae_add != NULL)
6035 				STRCAT(newword, ae->ae_add);
6036 			}
6037 
6038 			/* Obey the "rare" flag of the affix. */
6039 			if (ae->ae_rare)
6040 			    use_flags = flags | WF_RARE;
6041 			else
6042 			    use_flags = flags;
6043 
6044 			/* Obey the "nocomp" flag of the affix: don't use the
6045 			 * compound flags. */
6046 			use_pfxlist = pfxlist;
6047 			if (ae->ae_nocomp && pfxlist != NULL)
6048 			{
6049 			    vim_strncpy(pfx_pfxlist, pfxlist, pfxlen);
6050 			    use_pfxlist = pfx_pfxlist;
6051 			}
6052 
6053 			/* When there are postponed prefixes... */
6054 			if (spin->si_prefroot != NULL
6055 				&& spin->si_prefroot->wn_sibling != NULL)
6056 			{
6057 			    /* ... add a flag to indicate an affix was used. */
6058 			    use_flags |= WF_HAS_AFF;
6059 
6060 			    /* ... don't use a prefix list if combining
6061 			     * affixes is not allowed.  But do use the
6062 			     * compound flags after them. */
6063 			    if ((!ah->ah_combine || comb) && pfxlist != NULL)
6064 				use_pfxlist += pfxlen;
6065 			}
6066 
6067 			/* Store the modified word. */
6068 			if (store_word(spin, newword, use_flags,
6069 				 spin->si_region, use_pfxlist, FALSE) == FAIL)
6070 			    retval = FAIL;
6071 
6072 			/* When added a suffix and combining is allowed also
6073 			 * try adding prefixes additionally. */
6074 			if (xht != NULL && ah->ah_combine)
6075 			    if (store_aff_word(spin, newword, afflist, affile,
6076 					  xht, NULL, TRUE,
6077 				      use_flags, use_pfxlist, pfxlen) == FAIL)
6078 				retval = FAIL;
6079 		    }
6080 		}
6081 	    }
6082 	}
6083     }
6084 
6085     return retval;
6086 }
6087 
6088 /*
6089  * Read a file with a list of words.
6090  */
6091     static int
6092 spell_read_wordfile(spin, fname)
6093     spellinfo_T	*spin;
6094     char_u	*fname;
6095 {
6096     FILE	*fd;
6097     long	lnum = 0;
6098     char_u	rline[MAXLINELEN];
6099     char_u	*line;
6100     char_u	*pc = NULL;
6101     char_u	*p;
6102     int		l;
6103     int		retval = OK;
6104     int		did_word = FALSE;
6105     int		non_ascii = 0;
6106     int		flags;
6107     int		regionmask;
6108 
6109     /*
6110      * Open the file.
6111      */
6112     fd = mch_fopen((char *)fname, "r");
6113     if (fd == NULL)
6114     {
6115 	EMSG2(_(e_notopen), fname);
6116 	return FAIL;
6117     }
6118 
6119     if (spin->si_verbose || p_verbose > 2)
6120     {
6121 	if (!spin->si_verbose)
6122 	    verbose_enter();
6123 	smsg((char_u *)_("Reading word file %s ..."), fname);
6124 	out_flush();
6125 	if (!spin->si_verbose)
6126 	    verbose_leave();
6127     }
6128 
6129     /*
6130      * Read all the lines in the file one by one.
6131      */
6132     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
6133     {
6134 	line_breakcheck();
6135 	++lnum;
6136 
6137 	/* Skip comment lines. */
6138 	if (*rline == '#')
6139 	    continue;
6140 
6141 	/* Remove CR, LF and white space from the end. */
6142 	l = STRLEN(rline);
6143 	while (l > 0 && rline[l - 1] <= ' ')
6144 	    --l;
6145 	if (l == 0)
6146 	    continue;	/* empty or blank line */
6147 	rline[l] = NUL;
6148 
6149 	/* Convert from "=encoding={encoding}" to 'encoding' when needed. */
6150 	vim_free(pc);
6151 #ifdef FEAT_MBYTE
6152 	if (spin->si_conv.vc_type != CONV_NONE)
6153 	{
6154 	    pc = string_convert(&spin->si_conv, rline, NULL);
6155 	    if (pc == NULL)
6156 	    {
6157 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
6158 							   fname, lnum, rline);
6159 		continue;
6160 	    }
6161 	    line = pc;
6162 	}
6163 	else
6164 #endif
6165 	{
6166 	    pc = NULL;
6167 	    line = rline;
6168 	}
6169 
6170 	if (*line == '/')
6171 	{
6172 	    ++line;
6173 	    if (STRNCMP(line, "encoding=", 9) == 0)
6174 	    {
6175 		if (spin->si_conv.vc_type != CONV_NONE)
6176 		    smsg((char_u *)_("Duplicate /encoding= line ignored in %s line %d: %s"),
6177 						       fname, lnum, line - 1);
6178 		else if (did_word)
6179 		    smsg((char_u *)_("/encoding= line after word ignored in %s line %d: %s"),
6180 						       fname, lnum, line - 1);
6181 		else
6182 		{
6183 #ifdef FEAT_MBYTE
6184 		    char_u	*enc;
6185 
6186 		    /* Setup for conversion to 'encoding'. */
6187 		    line += 10;
6188 		    enc = enc_canonize(line);
6189 		    if (enc != NULL && !spin->si_ascii
6190 			    && convert_setup(&spin->si_conv, enc,
6191 							       p_enc) == FAIL)
6192 			smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
6193 							  fname, line, p_enc);
6194 		    vim_free(enc);
6195 		    spin->si_conv.vc_fail = TRUE;
6196 #else
6197 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
6198 #endif
6199 		}
6200 		continue;
6201 	    }
6202 
6203 	    if (STRNCMP(line, "regions=", 8) == 0)
6204 	    {
6205 		if (spin->si_region_count > 1)
6206 		    smsg((char_u *)_("Duplicate /regions= line ignored in %s line %d: %s"),
6207 						       fname, lnum, line);
6208 		else
6209 		{
6210 		    line += 8;
6211 		    if (STRLEN(line) > 16)
6212 			smsg((char_u *)_("Too many regions in %s line %d: %s"),
6213 						       fname, lnum, line);
6214 		    else
6215 		    {
6216 			spin->si_region_count = STRLEN(line) / 2;
6217 			STRCPY(spin->si_region_name, line);
6218 
6219 			/* Adjust the mask for a word valid in all regions. */
6220 			spin->si_region = (1 << spin->si_region_count) - 1;
6221 		    }
6222 		}
6223 		continue;
6224 	    }
6225 
6226 	    smsg((char_u *)_("/ line ignored in %s line %d: %s"),
6227 						       fname, lnum, line - 1);
6228 	    continue;
6229 	}
6230 
6231 	flags = 0;
6232 	regionmask = spin->si_region;
6233 
6234 	/* Check for flags and region after a slash. */
6235 	p = vim_strchr(line, '/');
6236 	if (p != NULL)
6237 	{
6238 	    *p++ = NUL;
6239 	    while (*p != NUL)
6240 	    {
6241 		if (*p == '=')		/* keep-case word */
6242 		    flags |= WF_KEEPCAP | WF_FIXCAP;
6243 		else if (*p == '!')	/* Bad, bad, wicked word. */
6244 		    flags |= WF_BANNED;
6245 		else if (*p == '?')	/* Rare word. */
6246 		    flags |= WF_RARE;
6247 		else if (VIM_ISDIGIT(*p)) /* region number(s) */
6248 		{
6249 		    if ((flags & WF_REGION) == 0)   /* first one */
6250 			regionmask = 0;
6251 		    flags |= WF_REGION;
6252 
6253 		    l = *p - '0';
6254 		    if (l > spin->si_region_count)
6255 		    {
6256 			smsg((char_u *)_("Invalid region nr in %s line %d: %s"),
6257 							  fname, lnum, p);
6258 			break;
6259 		    }
6260 		    regionmask |= 1 << (l - 1);
6261 		}
6262 		else
6263 		{
6264 		    smsg((char_u *)_("Unrecognized flags in %s line %d: %s"),
6265 							      fname, lnum, p);
6266 		    break;
6267 		}
6268 		++p;
6269 	    }
6270 	}
6271 
6272 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
6273 	if (spin->si_ascii && has_non_ascii(line))
6274 	{
6275 	    ++non_ascii;
6276 	    continue;
6277 	}
6278 
6279 	/* Normal word: store it. */
6280 	if (store_word(spin, line, flags, regionmask, NULL, FALSE) == FAIL)
6281 	{
6282 	    retval = FAIL;
6283 	    break;
6284 	}
6285 	did_word = TRUE;
6286     }
6287 
6288     vim_free(pc);
6289     fclose(fd);
6290 
6291     if (spin->si_ascii && non_ascii > 0 && (spin->si_verbose || p_verbose > 2))
6292     {
6293 	if (p_verbose > 2)
6294 	    verbose_enter();
6295 	smsg((char_u *)_("Ignored %d words with non-ASCII characters"),
6296 								   non_ascii);
6297 	if (p_verbose > 2)
6298 	    verbose_leave();
6299     }
6300     return retval;
6301 }
6302 
6303 /*
6304  * Get part of an sblock_T, "len" bytes long.
6305  * This avoids calling free() for every little struct we use (and keeping
6306  * track of them).
6307  * The memory is cleared to all zeros.
6308  * Returns NULL when out of memory.
6309  */
6310     static void *
6311 getroom(spin, len, align)
6312     spellinfo_T *spin;
6313     size_t	len;		/* length needed */
6314     int		align;		/* align for pointer */
6315 {
6316     char_u	*p;
6317     sblock_T	*bl = spin->si_blocks;
6318 
6319     if (align && bl != NULL)
6320 	/* Round size up for alignment.  On some systems structures need to be
6321 	 * aligned to the size of a pointer (e.g., SPARC). */
6322 	bl->sb_used = (bl->sb_used + sizeof(char *) - 1)
6323 						      & ~(sizeof(char *) - 1);
6324 
6325     if (bl == NULL || bl->sb_used + len > SBLOCKSIZE)
6326     {
6327 	/* Allocate a block of memory. This is not freed until much later. */
6328 	bl = (sblock_T *)alloc_clear((unsigned)(sizeof(sblock_T) + SBLOCKSIZE));
6329 	if (bl == NULL)
6330 	    return NULL;
6331 	bl->sb_next = spin->si_blocks;
6332 	spin->si_blocks = bl;
6333 	bl->sb_used = 0;
6334 	++spin->si_blocks_cnt;
6335     }
6336 
6337     p = bl->sb_data + bl->sb_used;
6338     bl->sb_used += len;
6339 
6340     return p;
6341 }
6342 
6343 /*
6344  * Make a copy of a string into memory allocated with getroom().
6345  */
6346     static char_u *
6347 getroom_save(spin, s)
6348     spellinfo_T	*spin;
6349     char_u	*s;
6350 {
6351     char_u	*sc;
6352 
6353     sc = (char_u *)getroom(spin, STRLEN(s) + 1, FALSE);
6354     if (sc != NULL)
6355 	STRCPY(sc, s);
6356     return sc;
6357 }
6358 
6359 
6360 /*
6361  * Free the list of allocated sblock_T.
6362  */
6363     static void
6364 free_blocks(bl)
6365     sblock_T	*bl;
6366 {
6367     sblock_T	*next;
6368 
6369     while (bl != NULL)
6370     {
6371 	next = bl->sb_next;
6372 	vim_free(bl);
6373 	bl = next;
6374     }
6375 }
6376 
6377 /*
6378  * Allocate the root of a word tree.
6379  */
6380     static wordnode_T *
6381 wordtree_alloc(spin)
6382     spellinfo_T *spin;
6383 {
6384     return (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
6385 }
6386 
6387 /*
6388  * Store a word in the tree(s).
6389  * Always store it in the case-folded tree.  For a keep-case word this is
6390  * useful when the word can also be used with all caps (no WF_FIXCAP flag) and
6391  * used to find suggestions.
6392  * For a keep-case word also store it in the keep-case tree.
6393  * When "pfxlist" is not NULL store the word for each postponed prefix ID and
6394  * compound flag.
6395  */
6396     static int
6397 store_word(spin, word, flags, region, pfxlist, need_affix)
6398     spellinfo_T	*spin;
6399     char_u	*word;
6400     int		flags;		/* extra flags, WF_BANNED */
6401     int		region;		/* supported region(s) */
6402     char_u	*pfxlist;	/* list of prefix IDs or NULL */
6403     int		need_affix;	/* only store word with affix ID */
6404 {
6405     int		len = STRLEN(word);
6406     int		ct = captype(word, word + len);
6407     char_u	foldword[MAXWLEN];
6408     int		res = OK;
6409     char_u	*p;
6410 
6411     (void)spell_casefold(word, len, foldword, MAXWLEN);
6412     for (p = pfxlist; res == OK; ++p)
6413     {
6414 	if (!need_affix || (p != NULL && *p != NUL))
6415 	    res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
6416 						  region, p == NULL ? 0 : *p);
6417 	if (p == NULL || *p == NUL)
6418 	    break;
6419     }
6420     ++spin->si_foldwcount;
6421 
6422     if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP)))
6423     {
6424 	for (p = pfxlist; res == OK; ++p)
6425 	{
6426 	    if (!need_affix || (p != NULL && *p != NUL))
6427 		res = tree_add_word(spin, word, spin->si_keeproot, flags,
6428 						  region, p == NULL ? 0 : *p);
6429 	    if (p == NULL || *p == NUL)
6430 		break;
6431 	}
6432 	++spin->si_keepwcount;
6433     }
6434     return res;
6435 }
6436 
6437 /*
6438  * Add word "word" to a word tree at "root".
6439  * When "flags" < 0 we are adding to the prefix tree where flags is used for
6440  * "rare" and "region" is the condition nr.
6441  * Returns FAIL when out of memory.
6442  */
6443     static int
6444 tree_add_word(spin, word, root, flags, region, affixID)
6445     spellinfo_T	*spin;
6446     char_u	*word;
6447     wordnode_T	*root;
6448     int		flags;
6449     int		region;
6450     int		affixID;
6451 {
6452     wordnode_T	*node = root;
6453     wordnode_T	*np;
6454     wordnode_T	*copyp, **copyprev;
6455     wordnode_T	**prev = NULL;
6456     int		i;
6457 
6458     /* Add each byte of the word to the tree, including the NUL at the end. */
6459     for (i = 0; ; ++i)
6460     {
6461 	/* When there is more than one reference to this node we need to make
6462 	 * a copy, so that we can modify it.  Copy the whole list of siblings
6463 	 * (we don't optimize for a partly shared list of siblings). */
6464 	if (node != NULL && node->wn_refs > 1)
6465 	{
6466 	    --node->wn_refs;
6467 	    copyprev = prev;
6468 	    for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling)
6469 	    {
6470 		/* Allocate a new node and copy the info. */
6471 		np = get_wordnode(spin);
6472 		if (np == NULL)
6473 		    return FAIL;
6474 		np->wn_child = copyp->wn_child;
6475 		if (np->wn_child != NULL)
6476 		    ++np->wn_child->wn_refs;	/* child gets extra ref */
6477 		np->wn_byte = copyp->wn_byte;
6478 		if (np->wn_byte == NUL)
6479 		{
6480 		    np->wn_flags = copyp->wn_flags;
6481 		    np->wn_region = copyp->wn_region;
6482 		    np->wn_affixID = copyp->wn_affixID;
6483 		}
6484 
6485 		/* Link the new node in the list, there will be one ref. */
6486 		np->wn_refs = 1;
6487 		*copyprev = np;
6488 		copyprev = &np->wn_sibling;
6489 
6490 		/* Let "node" point to the head of the copied list. */
6491 		if (copyp == node)
6492 		    node = np;
6493 	    }
6494 	}
6495 
6496 	/* Look for the sibling that has the same character.  They are sorted
6497 	 * on byte value, thus stop searching when a sibling is found with a
6498 	 * higher byte value.  For zero bytes (end of word) the sorting is
6499 	 * done on flags and then on affixID. */
6500 	while (node != NULL
6501 		&& (node->wn_byte < word[i]
6502 		    || (node->wn_byte == NUL
6503 			&& (flags < 0
6504 			    ? node->wn_affixID < affixID
6505 			    : node->wn_flags < (flags & WN_MASK)
6506 				|| (node->wn_flags == (flags & WN_MASK)
6507 				    && node->wn_affixID < affixID)))))
6508 	{
6509 	    prev = &node->wn_sibling;
6510 	    node = *prev;
6511 	}
6512 	if (node == NULL
6513 		|| node->wn_byte != word[i]
6514 		|| (word[i] == NUL
6515 		    && (flags < 0
6516 			|| node->wn_flags != (flags & WN_MASK)
6517 			|| node->wn_affixID != affixID)))
6518 	{
6519 	    /* Allocate a new node. */
6520 	    np = get_wordnode(spin);
6521 	    if (np == NULL)
6522 		return FAIL;
6523 	    np->wn_byte = word[i];
6524 
6525 	    /* If "node" is NULL this is a new child or the end of the sibling
6526 	     * list: ref count is one.  Otherwise use ref count of sibling and
6527 	     * make ref count of sibling one (matters when inserting in front
6528 	     * of the list of siblings). */
6529 	    if (node == NULL)
6530 		np->wn_refs = 1;
6531 	    else
6532 	    {
6533 		np->wn_refs = node->wn_refs;
6534 		node->wn_refs = 1;
6535 	    }
6536 	    *prev = np;
6537 	    np->wn_sibling = node;
6538 	    node = np;
6539 	}
6540 
6541 	if (word[i] == NUL)
6542 	{
6543 	    node->wn_flags = flags;
6544 	    node->wn_region |= region;
6545 	    node->wn_affixID = affixID;
6546 	    break;
6547 	}
6548 	prev = &node->wn_child;
6549 	node = *prev;
6550     }
6551 #ifdef SPELL_PRINTTREE
6552     smsg("Added \"%s\"", word);
6553     spell_print_tree(root->wn_sibling);
6554 #endif
6555 
6556     /* count nr of words added since last message */
6557     ++spin->si_msg_count;
6558 
6559     if (spin->si_compress_cnt > 1)
6560     {
6561 	if (--spin->si_compress_cnt == 1)
6562 	    /* Did enough words to lower the block count limit. */
6563 	    spin->si_blocks_cnt += compress_inc;
6564     }
6565 
6566     /*
6567      * When we have allocated lots of memory we need to compress the word tree
6568      * to free up some room.  But compression is slow, and we might actually
6569      * need that room, thus only compress in the following situations:
6570      * 1. When not compressed before (si_compress_cnt == 0): when using
6571      *    "compress_start" blocks.
6572      * 2. When compressed before and used "compress_inc" blocks before
6573      *    adding "compress_added" words (si_compress_cnt > 1).
6574      * 3. When compressed before, added "compress_added" words
6575      *    (si_compress_cnt == 1) and the number of free nodes drops below the
6576      *    maximum word length.
6577      */
6578 #ifndef SPELL_PRINTTREE
6579     if (spin->si_compress_cnt == 1
6580 	    ? spin->si_free_count < MAXWLEN
6581 	    : spin->si_blocks_cnt >= compress_start)
6582 #endif
6583     {
6584 	/* Decrement the block counter.  The effect is that we compress again
6585 	 * when the freed up room has been used and another "compress_inc"
6586 	 * blocks have been allocated.  Unless "compress_added" words have
6587 	 * been added, then the limit is put back again. */
6588 	spin->si_blocks_cnt -= compress_inc;
6589 	spin->si_compress_cnt = compress_added;
6590 
6591 	if (spin->si_verbose)
6592 	{
6593 	    msg_start();
6594 	    msg_puts((char_u *)_(msg_compressing));
6595 	    msg_clr_eos();
6596 	    msg_didout = FALSE;
6597 	    msg_col = 0;
6598 	    out_flush();
6599 	}
6600 
6601 	/* Compress both trees.  Either they both have many nodes, which makes
6602 	 * compression useful, or one of them is small, which means
6603 	 * compression goes fast. */
6604 	wordtree_compress(spin, spin->si_foldroot);
6605 	wordtree_compress(spin, spin->si_keeproot);
6606     }
6607 
6608     return OK;
6609 }
6610 
6611 /*
6612  * Check the 'mkspellmem' option.  Return FAIL if it's wrong.
6613  * Sets "sps_flags".
6614  */
6615     int
6616 spell_check_msm()
6617 {
6618     char_u	*p = p_msm;
6619     long	start = 0;
6620     long	inc = 0;
6621     long	added = 0;
6622 
6623     if (!VIM_ISDIGIT(*p))
6624 	return FAIL;
6625     /* block count = (value * 1024) / SBLOCKSIZE (but avoid overflow)*/
6626     start = (getdigits(&p) * 10) / (SBLOCKSIZE / 102);
6627     if (*p != ',')
6628 	return FAIL;
6629     ++p;
6630     if (!VIM_ISDIGIT(*p))
6631 	return FAIL;
6632     inc = (getdigits(&p) * 102) / (SBLOCKSIZE / 10);
6633     if (*p != ',')
6634 	return FAIL;
6635     ++p;
6636     if (!VIM_ISDIGIT(*p))
6637 	return FAIL;
6638     added = getdigits(&p) * 1024;
6639     if (*p != NUL)
6640 	return FAIL;
6641 
6642     if (start == 0 || inc == 0 || added == 0 || inc > start)
6643 	return FAIL;
6644 
6645     compress_start = start;
6646     compress_inc = inc;
6647     compress_added = added;
6648     return OK;
6649 }
6650 
6651 
6652 /*
6653  * Get a wordnode_T, either from the list of previously freed nodes or
6654  * allocate a new one.
6655  */
6656     static wordnode_T *
6657 get_wordnode(spin)
6658     spellinfo_T	    *spin;
6659 {
6660     wordnode_T *n;
6661 
6662     if (spin->si_first_free == NULL)
6663 	n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
6664     else
6665     {
6666 	n = spin->si_first_free;
6667 	spin->si_first_free = n->wn_child;
6668 	vim_memset(n, 0, sizeof(wordnode_T));
6669 	--spin->si_free_count;
6670     }
6671 #ifdef SPELL_PRINTTREE
6672     n->wn_nr = ++spin->si_wordnode_nr;
6673 #endif
6674     return n;
6675 }
6676 
6677 /*
6678  * Decrement the reference count on a node (which is the head of a list of
6679  * siblings).  If the reference count becomes zero free the node and its
6680  * siblings.
6681  */
6682     static void
6683 deref_wordnode(spin, node)
6684     spellinfo_T *spin;
6685     wordnode_T  *node;
6686 {
6687     wordnode_T *np;
6688 
6689     if (--node->wn_refs == 0)
6690 	for (np = node; np != NULL; np = np->wn_sibling)
6691 	{
6692 	    if (np->wn_child != NULL)
6693 		deref_wordnode(spin, np->wn_child);
6694 	    free_wordnode(spin, np);
6695 	}
6696 }
6697 
6698 /*
6699  * Free a wordnode_T for re-use later.
6700  * Only the "wn_child" field becomes invalid.
6701  */
6702     static void
6703 free_wordnode(spin, n)
6704     spellinfo_T	*spin;
6705     wordnode_T  *n;
6706 {
6707     n->wn_child = spin->si_first_free;
6708     spin->si_first_free = n;
6709     ++spin->si_free_count;
6710 }
6711 
6712 /*
6713  * Compress a tree: find tails that are identical and can be shared.
6714  */
6715     static void
6716 wordtree_compress(spin, root)
6717     spellinfo_T	    *spin;
6718     wordnode_T	    *root;
6719 {
6720     hashtab_T	    ht;
6721     int		    n;
6722     int		    tot = 0;
6723     int		    perc;
6724 
6725     /* Skip the root itself, it's not actually used.  The first sibling is the
6726      * start of the tree. */
6727     if (root->wn_sibling != NULL)
6728     {
6729 	hash_init(&ht);
6730 	n = node_compress(spin, root->wn_sibling, &ht, &tot);
6731 
6732 #ifndef SPELL_PRINTTREE
6733 	if (spin->si_verbose || p_verbose > 2)
6734 #endif
6735 	{
6736 	    if (!spin->si_verbose)
6737 		verbose_enter();
6738 	    if (tot > 1000000)
6739 		perc = (tot - n) / (tot / 100);
6740 	    else if (tot == 0)
6741 		perc = 0;
6742 	    else
6743 		perc = (tot - n) * 100 / tot;
6744 	    smsg((char_u *)_("Compressed %d of %d nodes; %d%% remaining"),
6745 								n, tot, perc);
6746 	    if (p_verbose > 2)
6747 		verbose_leave();
6748 	}
6749 #ifdef SPELL_PRINTTREE
6750 	spell_print_tree(root->wn_sibling);
6751 #endif
6752 	hash_clear(&ht);
6753     }
6754 }
6755 
6756 /*
6757  * Compress a node, its siblings and its children, depth first.
6758  * Returns the number of compressed nodes.
6759  */
6760     static int
6761 node_compress(spin, node, ht, tot)
6762     spellinfo_T	*spin;
6763     wordnode_T	*node;
6764     hashtab_T	*ht;
6765     int		*tot;	    /* total count of nodes before compressing,
6766 			       incremented while going through the tree */
6767 {
6768     wordnode_T	*np;
6769     wordnode_T	*tp;
6770     wordnode_T	*child;
6771     hash_T	hash;
6772     hashitem_T	*hi;
6773     int		len = 0;
6774     unsigned	nr, n;
6775     int		compressed = 0;
6776 
6777     /*
6778      * Go through the list of siblings.  Compress each child and then try
6779      * finding an identical child to replace it.
6780      * Note that with "child" we mean not just the node that is pointed to,
6781      * but the whole list of siblings, of which the node is the first.
6782      */
6783     for (np = node; np != NULL && !got_int; np = np->wn_sibling)
6784     {
6785 	++len;
6786 	if ((child = np->wn_child) != NULL)
6787 	{
6788 	    /* Compress the child.  This fills hashkey. */
6789 	    compressed += node_compress(spin, child, ht, tot);
6790 
6791 	    /* Try to find an identical child. */
6792 	    hash = hash_hash(child->wn_u1.hashkey);
6793 	    hi = hash_lookup(ht, child->wn_u1.hashkey, hash);
6794 	    tp = NULL;
6795 	    if (!HASHITEM_EMPTY(hi))
6796 	    {
6797 		/* There are children with an identical hash value.  Now check
6798 		 * if there is one that is really identical. */
6799 		for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next)
6800 		    if (node_equal(child, tp))
6801 		    {
6802 			/* Found one!  Now use that child in place of the
6803 			 * current one.  This means the current child and all
6804 			 * its siblings is unlinked from the tree. */
6805 			++tp->wn_refs;
6806 			deref_wordnode(spin, child);
6807 			np->wn_child = tp;
6808 			++compressed;
6809 			break;
6810 		    }
6811 		if (tp == NULL)
6812 		{
6813 		    /* No other child with this hash value equals the child of
6814 		     * the node, add it to the linked list after the first
6815 		     * item. */
6816 		    tp = HI2WN(hi);
6817 		    child->wn_u2.next = tp->wn_u2.next;
6818 		    tp->wn_u2.next = child;
6819 		}
6820 	    }
6821 	    else
6822 		/* No other child has this hash value, add it to the
6823 		 * hashtable. */
6824 		hash_add_item(ht, hi, child->wn_u1.hashkey, hash);
6825 	}
6826     }
6827     *tot += len;
6828 
6829     /*
6830      * Make a hash key for the node and its siblings, so that we can quickly
6831      * find a lookalike node.  This must be done after compressing the sibling
6832      * list, otherwise the hash key would become invalid by the compression.
6833      */
6834     node->wn_u1.hashkey[0] = len;
6835     nr = 0;
6836     for (np = node; np != NULL; np = np->wn_sibling)
6837     {
6838 	if (np->wn_byte == NUL)
6839 	    /* end node: use wn_flags, wn_region and wn_affixID */
6840 	    n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16);
6841 	else
6842 	    /* byte node: use the byte value and the child pointer */
6843 	    n = np->wn_byte + ((long_u)np->wn_child << 8);
6844 	nr = nr * 101 + n;
6845     }
6846 
6847     /* Avoid NUL bytes, it terminates the hash key. */
6848     n = nr & 0xff;
6849     node->wn_u1.hashkey[1] = n == 0 ? 1 : n;
6850     n = (nr >> 8) & 0xff;
6851     node->wn_u1.hashkey[2] = n == 0 ? 1 : n;
6852     n = (nr >> 16) & 0xff;
6853     node->wn_u1.hashkey[3] = n == 0 ? 1 : n;
6854     n = (nr >> 24) & 0xff;
6855     node->wn_u1.hashkey[4] = n == 0 ? 1 : n;
6856     node->wn_u1.hashkey[5] = NUL;
6857 
6858     /* Check for CTRL-C pressed now and then. */
6859     fast_breakcheck();
6860 
6861     return compressed;
6862 }
6863 
6864 /*
6865  * Return TRUE when two nodes have identical siblings and children.
6866  */
6867     static int
6868 node_equal(n1, n2)
6869     wordnode_T	*n1;
6870     wordnode_T	*n2;
6871 {
6872     wordnode_T	*p1;
6873     wordnode_T	*p2;
6874 
6875     for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL;
6876 				     p1 = p1->wn_sibling, p2 = p2->wn_sibling)
6877 	if (p1->wn_byte != p2->wn_byte
6878 		|| (p1->wn_byte == NUL
6879 		    ? (p1->wn_flags != p2->wn_flags
6880 			|| p1->wn_region != p2->wn_region
6881 			|| p1->wn_affixID != p2->wn_affixID)
6882 		    : (p1->wn_child != p2->wn_child)))
6883 	    break;
6884 
6885     return p1 == NULL && p2 == NULL;
6886 }
6887 
6888 /*
6889  * Write a number to file "fd", MSB first, in "len" bytes.
6890  */
6891     void
6892 put_bytes(fd, nr, len)
6893     FILE    *fd;
6894     long_u  nr;
6895     int	    len;
6896 {
6897     int	    i;
6898 
6899     for (i = len - 1; i >= 0; --i)
6900 	putc((int)(nr >> (i * 8)), fd);
6901 }
6902 
6903 static int
6904 #ifdef __BORLANDC__
6905 _RTLENTRYF
6906 #endif
6907 rep_compare __ARGS((const void *s1, const void *s2));
6908 
6909 /*
6910  * Function given to qsort() to sort the REP items on "from" string.
6911  */
6912     static int
6913 #ifdef __BORLANDC__
6914 _RTLENTRYF
6915 #endif
6916 rep_compare(s1, s2)
6917     const void	*s1;
6918     const void	*s2;
6919 {
6920     fromto_T	*p1 = (fromto_T *)s1;
6921     fromto_T	*p2 = (fromto_T *)s2;
6922 
6923     return STRCMP(p1->ft_from, p2->ft_from);
6924 }
6925 
6926 /*
6927  * Write the Vim .spl file "fname".
6928  * Return FAIL or OK;
6929  */
6930     static int
6931 write_vim_spell(spin, fname)
6932     spellinfo_T	*spin;
6933     char_u	*fname;
6934 {
6935     FILE	*fd;
6936     int		regionmask;
6937     int		round;
6938     wordnode_T	*tree;
6939     int		nodecount;
6940     int		i;
6941     int		l;
6942     garray_T	*gap;
6943     fromto_T	*ftp;
6944     char_u	*p;
6945     int		rr;
6946     int		retval = OK;
6947 
6948     fd = mch_fopen((char *)fname, "w");
6949     if (fd == NULL)
6950     {
6951 	EMSG2(_(e_notopen), fname);
6952 	return FAIL;
6953     }
6954 
6955     /* <HEADER>: <fileID> <versionnr> */
6956 							    /* <fileID> */
6957     if (fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd) != 1)
6958     {
6959 	EMSG(_(e_write));
6960 	retval = FAIL;
6961     }
6962     putc(VIMSPELLVERSION, fd);				    /* <versionnr> */
6963 
6964     /*
6965      * <SECTIONS>: <section> ... <sectionend>
6966      */
6967 
6968     /* SN_REGION: <regionname> ...
6969      * Write the region names only if there is more than one. */
6970     if (spin->si_region_count > 1)
6971     {
6972 	putc(SN_REGION, fd);				/* <sectionID> */
6973 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
6974 	l = spin->si_region_count * 2;
6975 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
6976 	fwrite(spin->si_region_name, (size_t)l, (size_t)1, fd);
6977 							/* <regionname> ... */
6978 	regionmask = (1 << spin->si_region_count) - 1;
6979     }
6980     else
6981 	regionmask = 0;
6982 
6983     /* SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars>
6984      *
6985      * The table with character flags and the table for case folding.
6986      * This makes sure the same characters are recognized as word characters
6987      * when generating an when using a spell file.
6988      * Skip this for ASCII, the table may conflict with the one used for
6989      * 'encoding'.
6990      * Also skip this for an .add.spl file, the main spell file must contain
6991      * the table (avoids that it conflicts).  File is shorter too.
6992      */
6993     if (!spin->si_ascii && !spin->si_add)
6994     {
6995 	char_u	folchars[128 * 8];
6996 	int	flags;
6997 
6998 	putc(SN_CHARFLAGS, fd);				/* <sectionID> */
6999 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
7000 
7001 	/* Form the <folchars> string first, we need to know its length. */
7002 	l = 0;
7003 	for (i = 128; i < 256; ++i)
7004 	{
7005 #ifdef FEAT_MBYTE
7006 	    if (has_mbyte)
7007 		l += mb_char2bytes(spelltab.st_fold[i], folchars + l);
7008 	    else
7009 #endif
7010 		folchars[l++] = spelltab.st_fold[i];
7011 	}
7012 	put_bytes(fd, (long_u)(1 + 128 + 2 + l), 4);	/* <sectionlen> */
7013 
7014 	fputc(128, fd);					/* <charflagslen> */
7015 	for (i = 128; i < 256; ++i)
7016 	{
7017 	    flags = 0;
7018 	    if (spelltab.st_isw[i])
7019 		flags |= CF_WORD;
7020 	    if (spelltab.st_isu[i])
7021 		flags |= CF_UPPER;
7022 	    fputc(flags, fd);				/* <charflags> */
7023 	}
7024 
7025 	put_bytes(fd, (long_u)l, 2);			/* <folcharslen> */
7026 	fwrite(folchars, (size_t)l, (size_t)1, fd);	/* <folchars> */
7027     }
7028 
7029     /* SN_MIDWORD: <midword> */
7030     if (spin->si_midword != NULL)
7031     {
7032 	putc(SN_MIDWORD, fd);				/* <sectionID> */
7033 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
7034 
7035 	i = STRLEN(spin->si_midword);
7036 	put_bytes(fd, (long_u)i, 4);			/* <sectionlen> */
7037 	fwrite(spin->si_midword, (size_t)i, (size_t)1, fd); /* <midword> */
7038     }
7039 
7040     /* SN_PREFCOND: <prefcondcnt> <prefcond> ... */
7041     if (spin->si_prefcond.ga_len > 0)
7042     {
7043 	putc(SN_PREFCOND, fd);				/* <sectionID> */
7044 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
7045 
7046 	l = write_spell_prefcond(NULL, &spin->si_prefcond);
7047 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
7048 
7049 	write_spell_prefcond(fd, &spin->si_prefcond);
7050     }
7051 
7052     /* SN_REP: <repcount> <rep> ...
7053      * SN_SAL: <salflags> <salcount> <sal> ... */
7054 
7055     /* Sort the REP items. */
7056     qsort(spin->si_rep.ga_data, (size_t)spin->si_rep.ga_len,
7057 					       sizeof(fromto_T), rep_compare);
7058 
7059     /* round 1: SN_REP section
7060      * round 2: SN_SAL section (unless SN_SOFO is used) */
7061     for (round = 1; round <= 2; ++round)
7062     {
7063 	if (round == 1)
7064 	{
7065 	    gap = &spin->si_rep;
7066 	    putc(SN_REP, fd);				/* <sectionID> */
7067 	}
7068 	else
7069 	{
7070 	    if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
7071 		/* using SN_SOFO section instead of SN_SAL */
7072 		break;
7073 	    gap = &spin->si_sal;
7074 	    putc(SN_SAL, fd);				/* <sectionID> */
7075 	}
7076 
7077 	/* This is for making suggestions, section is not required. */
7078 	putc(0, fd);					/* <sectionflags> */
7079 
7080 	/* Compute the length of what follows. */
7081 	l = 2;	    /* count <repcount> or <salcount> */
7082 	for (i = 0; i < gap->ga_len; ++i)
7083 	{
7084 	    ftp = &((fromto_T *)gap->ga_data)[i];
7085 	    l += 1 + STRLEN(ftp->ft_from);  /* count <*fromlen> and <*from> */
7086 	    l += 1 + STRLEN(ftp->ft_to);    /* count <*tolen> and <*to> */
7087 	}
7088 	if (round == 2)
7089 	    ++l;	/* count <salflags> */
7090 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
7091 
7092 	if (round == 2)
7093 	{
7094 	    i = 0;
7095 	    if (spin->si_followup)
7096 		i |= SAL_F0LLOWUP;
7097 	    if (spin->si_collapse)
7098 		i |= SAL_COLLAPSE;
7099 	    if (spin->si_rem_accents)
7100 		i |= SAL_REM_ACCENTS;
7101 	    putc(i, fd);			/* <salflags> */
7102 	}
7103 
7104 	put_bytes(fd, (long_u)gap->ga_len, 2);	/* <repcount> or <salcount> */
7105 	for (i = 0; i < gap->ga_len; ++i)
7106 	{
7107 	    /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
7108 	    /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
7109 	    ftp = &((fromto_T *)gap->ga_data)[i];
7110 	    for (rr = 1; rr <= 2; ++rr)
7111 	    {
7112 		p = rr == 1 ? ftp->ft_from : ftp->ft_to;
7113 		l = STRLEN(p);
7114 		putc(l, fd);
7115 		fwrite(p, l, (size_t)1, fd);
7116 	    }
7117 	}
7118 
7119     }
7120 
7121     /* SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
7122      * This is for making suggestions, section is not required. */
7123     if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
7124     {
7125 	putc(SN_SOFO, fd);				/* <sectionID> */
7126 	putc(0, fd);					/* <sectionflags> */
7127 
7128 	l = STRLEN(spin->si_sofofr);
7129 	put_bytes(fd, (long_u)(l + STRLEN(spin->si_sofoto) + 4), 4);
7130 							/* <sectionlen> */
7131 
7132 	put_bytes(fd, (long_u)l, 2);			/* <sofofromlen> */
7133 	fwrite(spin->si_sofofr, l, (size_t)1, fd);	/* <sofofrom> */
7134 
7135 	l = STRLEN(spin->si_sofoto);
7136 	put_bytes(fd, (long_u)l, 2);			/* <sofotolen> */
7137 	fwrite(spin->si_sofoto, l, (size_t)1, fd);	/* <sofoto> */
7138     }
7139 
7140     /* SN_MAP: <mapstr>
7141      * This is for making suggestions, section is not required. */
7142     if (spin->si_map.ga_len > 0)
7143     {
7144 	putc(SN_MAP, fd);				/* <sectionID> */
7145 	putc(0, fd);					/* <sectionflags> */
7146 	l = spin->si_map.ga_len;
7147 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
7148 	fwrite(spin->si_map.ga_data, (size_t)l, (size_t)1, fd);
7149 							/* <mapstr> */
7150     }
7151 
7152     /* SN_COMPOUND: compound info.
7153      * We don't mark it required, when not supported all compound words will
7154      * be bad words. */
7155     if (spin->si_compflags != NULL)
7156     {
7157 	putc(SN_COMPOUND, fd);				/* <sectionID> */
7158 	putc(0, fd);					/* <sectionflags> */
7159 
7160 	l = STRLEN(spin->si_compflags);
7161 	put_bytes(fd, (long_u)(l + 3), 4);		/* <sectionlen> */
7162 	putc(spin->si_compmax, fd);			/* <compmax> */
7163 	putc(spin->si_compminlen, fd);			/* <compminlen> */
7164 	putc(spin->si_compsylmax, fd);			/* <compsylmax> */
7165 							/* <compflags> */
7166 	fwrite(spin->si_compflags, (size_t)l, (size_t)1, fd);
7167     }
7168 
7169     /* SN_NOBREAK: NOBREAK flag */
7170     if (spin->si_nobreak)
7171     {
7172 	putc(SN_NOBREAK, fd);				/* <sectionID> */
7173 	putc(0, fd);					/* <sectionflags> */
7174 
7175 	/* It's empty, the precense of the section flags the feature. */
7176 	put_bytes(fd, (long_u)0, 4);			/* <sectionlen> */
7177     }
7178 
7179     /* SN_SYLLABLE: syllable info.
7180      * We don't mark it required, when not supported syllables will not be
7181      * counted. */
7182     if (spin->si_syllable != NULL)
7183     {
7184 	putc(SN_SYLLABLE, fd);				/* <sectionID> */
7185 	putc(0, fd);					/* <sectionflags> */
7186 
7187 	l = STRLEN(spin->si_syllable);
7188 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
7189 	fwrite(spin->si_syllable, (size_t)l, (size_t)1, fd); /* <syllable> */
7190     }
7191 
7192     /* end of <SECTIONS> */
7193     putc(SN_END, fd);					/* <sectionend> */
7194 
7195 
7196     /*
7197      * <LWORDTREE>  <KWORDTREE>  <PREFIXTREE>
7198      */
7199     spin->si_memtot = 0;
7200     for (round = 1; round <= 3; ++round)
7201     {
7202 	if (round == 1)
7203 	    tree = spin->si_foldroot->wn_sibling;
7204 	else if (round == 2)
7205 	    tree = spin->si_keeproot->wn_sibling;
7206 	else
7207 	    tree = spin->si_prefroot->wn_sibling;
7208 
7209 	/* Clear the index and wnode fields in the tree. */
7210 	clear_node(tree);
7211 
7212 	/* Count the number of nodes.  Needed to be able to allocate the
7213 	 * memory when reading the nodes.  Also fills in index for shared
7214 	 * nodes. */
7215 	nodecount = put_node(NULL, tree, 0, regionmask, round == 3);
7216 
7217 	/* number of nodes in 4 bytes */
7218 	put_bytes(fd, (long_u)nodecount, 4);	/* <nodecount> */
7219 	spin->si_memtot += nodecount + nodecount * sizeof(int);
7220 
7221 	/* Write the nodes. */
7222 	(void)put_node(fd, tree, 0, regionmask, round == 3);
7223     }
7224 
7225     /* Write another byte to check for errors. */
7226     if (putc(0, fd) == EOF)
7227 	retval = FAIL;
7228 
7229     if (fclose(fd) == EOF)
7230 	retval = FAIL;
7231 
7232     return retval;
7233 }
7234 
7235 /*
7236  * Clear the index and wnode fields of "node", it siblings and its
7237  * children.  This is needed because they are a union with other items to save
7238  * space.
7239  */
7240     static void
7241 clear_node(node)
7242     wordnode_T	*node;
7243 {
7244     wordnode_T	*np;
7245 
7246     if (node != NULL)
7247 	for (np = node; np != NULL; np = np->wn_sibling)
7248 	{
7249 	    np->wn_u1.index = 0;
7250 	    np->wn_u2.wnode = NULL;
7251 
7252 	    if (np->wn_byte != NUL)
7253 		clear_node(np->wn_child);
7254 	}
7255 }
7256 
7257 
7258 /*
7259  * Dump a word tree at node "node".
7260  *
7261  * This first writes the list of possible bytes (siblings).  Then for each
7262  * byte recursively write the children.
7263  *
7264  * NOTE: The code here must match the code in read_tree(), since assumptions
7265  * are made about the indexes (so that we don't have to write them in the
7266  * file).
7267  *
7268  * Returns the number of nodes used.
7269  */
7270     static int
7271 put_node(fd, node, index, regionmask, prefixtree)
7272     FILE	*fd;		/* NULL when only counting */
7273     wordnode_T	*node;
7274     int		index;
7275     int		regionmask;
7276     int		prefixtree;	/* TRUE for PREFIXTREE */
7277 {
7278     int		newindex = index;
7279     int		siblingcount = 0;
7280     wordnode_T	*np;
7281     int		flags;
7282 
7283     /* If "node" is zero the tree is empty. */
7284     if (node == NULL)
7285 	return 0;
7286 
7287     /* Store the index where this node is written. */
7288     node->wn_u1.index = index;
7289 
7290     /* Count the number of siblings. */
7291     for (np = node; np != NULL; np = np->wn_sibling)
7292 	++siblingcount;
7293 
7294     /* Write the sibling count. */
7295     if (fd != NULL)
7296 	putc(siblingcount, fd);				/* <siblingcount> */
7297 
7298     /* Write each sibling byte and optionally extra info. */
7299     for (np = node; np != NULL; np = np->wn_sibling)
7300     {
7301 	if (np->wn_byte == 0)
7302 	{
7303 	    if (fd != NULL)
7304 	    {
7305 		/* For a NUL byte (end of word) write the flags etc. */
7306 		if (prefixtree)
7307 		{
7308 		    /* In PREFIXTREE write the required affixID and the
7309 		     * associated condition nr (stored in wn_region).  The
7310 		     * byte value is misused to store the "rare" and "not
7311 		     * combining" flags */
7312 		    if (np->wn_flags == (short_u)PFX_FLAGS)
7313 			putc(BY_NOFLAGS, fd);		/* <byte> */
7314 		    else
7315 		    {
7316 			putc(BY_FLAGS, fd);		/* <byte> */
7317 			putc(np->wn_flags, fd);		/* <pflags> */
7318 		    }
7319 		    putc(np->wn_affixID, fd);		/* <affixID> */
7320 		    put_bytes(fd, (long_u)np->wn_region, 2); /* <prefcondnr> */
7321 		}
7322 		else
7323 		{
7324 		    /* For word trees we write the flag/region items. */
7325 		    flags = np->wn_flags;
7326 		    if (regionmask != 0 && np->wn_region != regionmask)
7327 			flags |= WF_REGION;
7328 		    if (np->wn_affixID != 0)
7329 			flags |= WF_AFX;
7330 		    if (flags == 0)
7331 		    {
7332 			/* word without flags or region */
7333 			putc(BY_NOFLAGS, fd);			/* <byte> */
7334 		    }
7335 		    else
7336 		    {
7337 			if (np->wn_flags >= 0x100)
7338 			{
7339 			    putc(BY_FLAGS2, fd);		/* <byte> */
7340 			    putc(flags, fd);			/* <flags> */
7341 			    putc((unsigned)flags >> 8, fd);	/* <flags2> */
7342 			}
7343 			else
7344 			{
7345 			    putc(BY_FLAGS, fd);			/* <byte> */
7346 			    putc(flags, fd);			/* <flags> */
7347 			}
7348 			if (flags & WF_REGION)
7349 			    putc(np->wn_region, fd);		/* <region> */
7350 			if (flags & WF_AFX)
7351 			    putc(np->wn_affixID, fd);		/* <affixID> */
7352 		    }
7353 		}
7354 	    }
7355 	}
7356 	else
7357 	{
7358 	    if (np->wn_child->wn_u1.index != 0
7359 					 && np->wn_child->wn_u2.wnode != node)
7360 	    {
7361 		/* The child is written elsewhere, write the reference. */
7362 		if (fd != NULL)
7363 		{
7364 		    putc(BY_INDEX, fd);			/* <byte> */
7365 							/* <nodeidx> */
7366 		    put_bytes(fd, (long_u)np->wn_child->wn_u1.index, 3);
7367 		}
7368 	    }
7369 	    else if (np->wn_child->wn_u2.wnode == NULL)
7370 		/* We will write the child below and give it an index. */
7371 		np->wn_child->wn_u2.wnode = node;
7372 
7373 	    if (fd != NULL)
7374 		if (putc(np->wn_byte, fd) == EOF) /* <byte> or <xbyte> */
7375 		{
7376 		    EMSG(_(e_write));
7377 		    return 0;
7378 		}
7379 	}
7380     }
7381 
7382     /* Space used in the array when reading: one for each sibling and one for
7383      * the count. */
7384     newindex += siblingcount + 1;
7385 
7386     /* Recursively dump the children of each sibling. */
7387     for (np = node; np != NULL; np = np->wn_sibling)
7388 	if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node)
7389 	    newindex = put_node(fd, np->wn_child, newindex, regionmask,
7390 								  prefixtree);
7391 
7392     return newindex;
7393 }
7394 
7395 
7396 /*
7397  * ":mkspell [-ascii] outfile  infile ..."
7398  * ":mkspell [-ascii] addfile"
7399  */
7400     void
7401 ex_mkspell(eap)
7402     exarg_T *eap;
7403 {
7404     int		fcount;
7405     char_u	**fnames;
7406     char_u	*arg = eap->arg;
7407     int		ascii = FALSE;
7408 
7409     if (STRNCMP(arg, "-ascii", 6) == 0)
7410     {
7411 	ascii = TRUE;
7412 	arg = skipwhite(arg + 6);
7413     }
7414 
7415     /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */
7416     if (get_arglist_exp(arg, &fcount, &fnames) == OK)
7417     {
7418 	mkspell(fcount, fnames, ascii, eap->forceit, FALSE);
7419 	FreeWild(fcount, fnames);
7420     }
7421 }
7422 
7423 /*
7424  * Create a Vim spell file from one or more word lists.
7425  * "fnames[0]" is the output file name.
7426  * "fnames[fcount - 1]" is the last input file name.
7427  * Exception: when "fnames[0]" ends in ".add" it's used as the input file name
7428  * and ".spl" is appended to make the output file name.
7429  */
7430     static void
7431 mkspell(fcount, fnames, ascii, overwrite, added_word)
7432     int		fcount;
7433     char_u	**fnames;
7434     int		ascii;		    /* -ascii argument given */
7435     int		overwrite;	    /* overwrite existing output file */
7436     int		added_word;	    /* invoked through "zg" */
7437 {
7438     char_u	fname[MAXPATHL];
7439     char_u	wfname[MAXPATHL];
7440     char_u	**innames;
7441     int		incount;
7442     afffile_T	*(afile[8]);
7443     int		i;
7444     int		len;
7445     struct stat	st;
7446     int		error = FALSE;
7447     spellinfo_T spin;
7448 
7449     vim_memset(&spin, 0, sizeof(spin));
7450     spin.si_verbose = !added_word;
7451     spin.si_ascii = ascii;
7452     spin.si_followup = TRUE;
7453     spin.si_rem_accents = TRUE;
7454     ga_init2(&spin.si_rep, (int)sizeof(fromto_T), 20);
7455     ga_init2(&spin.si_sal, (int)sizeof(fromto_T), 20);
7456     ga_init2(&spin.si_map, (int)sizeof(char_u), 100);
7457     ga_init2(&spin.si_prefcond, (int)sizeof(char_u *), 50);
7458     spin.si_newcompID = 127;	/* start compound ID at first maximum */
7459 
7460     /* default: fnames[0] is output file, following are input files */
7461     innames = &fnames[1];
7462     incount = fcount - 1;
7463 
7464     if (fcount >= 1)
7465     {
7466 	len = STRLEN(fnames[0]);
7467 	if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0)
7468 	{
7469 	    /* For ":mkspell path/en.latin1.add" output file is
7470 	     * "path/en.latin1.add.spl". */
7471 	    innames = &fnames[0];
7472 	    incount = 1;
7473 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.spl", fnames[0]);
7474 	}
7475 	else if (fcount == 1)
7476 	{
7477 	    /* For ":mkspell path/vim" output file is "path/vim.latin1.spl". */
7478 	    innames = &fnames[0];
7479 	    incount = 1;
7480 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0],
7481 			     spin.si_ascii ? (char_u *)"ascii" : spell_enc());
7482 	}
7483 	else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0)
7484 	{
7485 	    /* Name ends in ".spl", use as the file name. */
7486 	    vim_strncpy(wfname, fnames[0], sizeof(wfname) - 1);
7487 	}
7488 	else
7489 	    /* Name should be language, make the file name from it. */
7490 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0],
7491 			     spin.si_ascii ? (char_u *)"ascii" : spell_enc());
7492 
7493 	/* Check for .ascii.spl. */
7494 	if (strstr((char *)gettail(wfname), ".ascii.") != NULL)
7495 	    spin.si_ascii = TRUE;
7496 
7497 	/* Check for .add.spl. */
7498 	if (strstr((char *)gettail(wfname), ".add.") != NULL)
7499 	    spin.si_add = TRUE;
7500     }
7501 
7502     if (incount <= 0)
7503 	EMSG(_(e_invarg));	/* need at least output and input names */
7504     else if (vim_strchr(gettail(wfname), '_') != NULL)
7505 	EMSG(_("E751: Output file name must not have region name"));
7506     else if (incount > 8)
7507 	EMSG(_("E754: Only up to 8 regions supported"));
7508     else
7509     {
7510 	/* Check for overwriting before doing things that may take a lot of
7511 	 * time. */
7512 	if (!overwrite && mch_stat((char *)wfname, &st) >= 0)
7513 	{
7514 	    EMSG(_(e_exists));
7515 	    return;
7516 	}
7517 	if (mch_isdir(wfname))
7518 	{
7519 	    EMSG2(_(e_isadir2), wfname);
7520 	    return;
7521 	}
7522 
7523 	/*
7524 	 * Init the aff and dic pointers.
7525 	 * Get the region names if there are more than 2 arguments.
7526 	 */
7527 	for (i = 0; i < incount; ++i)
7528 	{
7529 	    afile[i] = NULL;
7530 
7531 	    if (incount > 1)
7532 	    {
7533 		len = STRLEN(innames[i]);
7534 		if (STRLEN(gettail(innames[i])) < 5
7535 						|| innames[i][len - 3] != '_')
7536 		{
7537 		    EMSG2(_("E755: Invalid region in %s"), innames[i]);
7538 		    return;
7539 		}
7540 		spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]);
7541 		spin.si_region_name[i * 2 + 1] =
7542 					     TOLOWER_ASC(innames[i][len - 1]);
7543 	    }
7544 	}
7545 	spin.si_region_count = incount;
7546 
7547 	spin.si_foldroot = wordtree_alloc(&spin);
7548 	spin.si_keeproot = wordtree_alloc(&spin);
7549 	spin.si_prefroot = wordtree_alloc(&spin);
7550 	if (spin.si_foldroot == NULL
7551 		|| spin.si_keeproot == NULL
7552 		|| spin.si_prefroot == NULL)
7553 	{
7554 	    free_blocks(spin.si_blocks);
7555 	    return;
7556 	}
7557 
7558 	/* When not producing a .add.spl file clear the character table when
7559 	 * we encounter one in the .aff file.  This means we dump the current
7560 	 * one in the .spl file if the .aff file doesn't define one.  That's
7561 	 * better than guessing the contents, the table will match a
7562 	 * previously loaded spell file. */
7563 	if (!spin.si_add)
7564 	    spin.si_clear_chartab = TRUE;
7565 
7566 	/*
7567 	 * Read all the .aff and .dic files.
7568 	 * Text is converted to 'encoding'.
7569 	 * Words are stored in the case-folded and keep-case trees.
7570 	 */
7571 	for (i = 0; i < incount && !error; ++i)
7572 	{
7573 	    spin.si_conv.vc_type = CONV_NONE;
7574 	    spin.si_region = 1 << i;
7575 
7576 	    vim_snprintf((char *)fname, sizeof(fname), "%s.aff", innames[i]);
7577 	    if (mch_stat((char *)fname, &st) >= 0)
7578 	    {
7579 		/* Read the .aff file.  Will init "spin->si_conv" based on the
7580 		 * "SET" line. */
7581 		afile[i] = spell_read_aff(&spin, fname);
7582 		if (afile[i] == NULL)
7583 		    error = TRUE;
7584 		else
7585 		{
7586 		    /* Read the .dic file and store the words in the trees. */
7587 		    vim_snprintf((char *)fname, sizeof(fname), "%s.dic",
7588 								  innames[i]);
7589 		    if (spell_read_dic(&spin, fname, afile[i]) == FAIL)
7590 			error = TRUE;
7591 		}
7592 	    }
7593 	    else
7594 	    {
7595 		/* No .aff file, try reading the file as a word list.  Store
7596 		 * the words in the trees. */
7597 		if (spell_read_wordfile(&spin, innames[i]) == FAIL)
7598 		    error = TRUE;
7599 	    }
7600 
7601 #ifdef FEAT_MBYTE
7602 	    /* Free any conversion stuff. */
7603 	    convert_setup(&spin.si_conv, NULL, NULL);
7604 #endif
7605 	}
7606 
7607 	if (spin.si_compflags != NULL && spin.si_nobreak)
7608 	    MSG(_("Warning: both compounding and NOBREAK specified"));
7609 
7610 	if (!error)
7611 	{
7612 	    /*
7613 	     * Combine tails in the tree.
7614 	     */
7615 	    if (spin.si_verbose || p_verbose > 2)
7616 	    {
7617 		if (!spin.si_verbose)
7618 		    verbose_enter();
7619 		MSG(_(msg_compressing));
7620 		out_flush();
7621 		if (!spin.si_verbose)
7622 		    verbose_leave();
7623 	    }
7624 	    wordtree_compress(&spin, spin.si_foldroot);
7625 	    wordtree_compress(&spin, spin.si_keeproot);
7626 	    wordtree_compress(&spin, spin.si_prefroot);
7627 	}
7628 
7629 	if (!error)
7630 	{
7631 	    /*
7632 	     * Write the info in the spell file.
7633 	     */
7634 	    if (spin.si_verbose || p_verbose > 2)
7635 	    {
7636 		if (!spin.si_verbose)
7637 		    verbose_enter();
7638 		smsg((char_u *)_("Writing spell file %s ..."), wfname);
7639 		out_flush();
7640 		if (!spin.si_verbose)
7641 		    verbose_leave();
7642 	    }
7643 
7644 	    error = write_vim_spell(&spin, wfname) == FAIL;
7645 
7646 	    if (spin.si_verbose || p_verbose > 2)
7647 	    {
7648 		if (!spin.si_verbose)
7649 		    verbose_enter();
7650 		MSG(_("Done!"));
7651 		smsg((char_u *)_("Estimated runtime memory use: %d bytes"),
7652 							      spin.si_memtot);
7653 		out_flush();
7654 		if (!spin.si_verbose)
7655 		    verbose_leave();
7656 	    }
7657 
7658 	    /* If the file is loaded need to reload it. */
7659 	    if (!error)
7660 		spell_reload_one(wfname, added_word);
7661 	}
7662 
7663 	/* Free the allocated memory. */
7664 	ga_clear(&spin.si_rep);
7665 	ga_clear(&spin.si_sal);
7666 	ga_clear(&spin.si_map);
7667 	ga_clear(&spin.si_prefcond);
7668 
7669 	/* Free the .aff file structures. */
7670 	for (i = 0; i < incount; ++i)
7671 	    if (afile[i] != NULL)
7672 		spell_free_aff(afile[i]);
7673 
7674 	/* Free all the bits and pieces at once. */
7675 	free_blocks(spin.si_blocks);
7676     }
7677 }
7678 
7679 
7680 /*
7681  * ":[count]spellgood  {word}"
7682  * ":[count]spellwrong  {word}"
7683  */
7684     void
7685 ex_spell(eap)
7686     exarg_T *eap;
7687 {
7688     spell_add_word(eap->arg, STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
7689 				    eap->forceit ? 0 : (int)eap->line2);
7690 }
7691 
7692 /*
7693  * Add "word[len]" to 'spellfile' as a good or bad word.
7694  */
7695     void
7696 spell_add_word(word, len, bad, index)
7697     char_u	*word;
7698     int		len;
7699     int		bad;
7700     int		index;	    /* "zG" and "zW": zero, otherwise index in
7701 			       'spellfile' */
7702 {
7703     FILE	*fd;
7704     buf_T	*buf = NULL;
7705     int		new_spf = FALSE;
7706     char_u	*fname;
7707     char_u	fnamebuf[MAXPATHL];
7708     char_u	line[MAXWLEN * 2];
7709     long	fpos, fpos_next = 0;
7710     int		i;
7711     char_u	*spf;
7712 
7713     if (index == 0)	    /* use internal wordlist */
7714     {
7715 	if (int_wordlist == NULL)
7716 	{
7717 	    int_wordlist = vim_tempname('s');
7718 	    if (int_wordlist == NULL)
7719 		return;
7720 	}
7721 	fname = int_wordlist;
7722     }
7723     else
7724     {
7725 	/* If 'spellfile' isn't set figure out a good default value. */
7726 	if (*curbuf->b_p_spf == NUL)
7727 	{
7728 	    init_spellfile();
7729 	    new_spf = TRUE;
7730 	}
7731 
7732 	if (*curbuf->b_p_spf == NUL)
7733 	{
7734 	    EMSG2(_(e_notset), "spellfile");
7735 	    return;
7736 	}
7737 
7738 	for (spf = curbuf->b_p_spf, i = 1; *spf != NUL; ++i)
7739 	{
7740 	    copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
7741 	    if (i == index)
7742 		break;
7743 	    if (*spf == NUL)
7744 	    {
7745 		EMSGN(_("E765: 'spellfile' does not have %ld entries"), index);
7746 		return;
7747 	    }
7748 	}
7749 
7750 	/* Check that the user isn't editing the .add file somewhere. */
7751 	buf = buflist_findname_exp(fnamebuf);
7752 	if (buf != NULL && buf->b_ml.ml_mfp == NULL)
7753 	    buf = NULL;
7754 	if (buf != NULL && bufIsChanged(buf))
7755 	{
7756 	    EMSG(_(e_bufloaded));
7757 	    return;
7758 	}
7759 
7760 	fname = fnamebuf;
7761     }
7762 
7763     if (bad)
7764     {
7765 	/* When the word also appears as good word we need to remove that one,
7766 	 * since its flags sort before the one with WF_BANNED. */
7767 	fd = mch_fopen((char *)fname, "r");
7768 	if (fd != NULL)
7769 	{
7770 	    while (!vim_fgets(line, MAXWLEN * 2, fd))
7771 	    {
7772 		fpos = fpos_next;
7773 		fpos_next = ftell(fd);
7774 		if (STRNCMP(word, line, len) == 0
7775 			&& (line[len] == '/' || line[len] < ' '))
7776 		{
7777 		    /* Found duplicate word.  Remove it by writing a '#' at
7778 		     * the start of the line.  Mixing reading and writing
7779 		     * doesn't work for all systems, close the file first. */
7780 		    fclose(fd);
7781 		    fd = mch_fopen((char *)fname, "r+");
7782 		    if (fd == NULL)
7783 			break;
7784 		    if (fseek(fd, fpos, SEEK_SET) == 0)
7785 			fputc('#', fd);
7786 		    fseek(fd, fpos_next, SEEK_SET);
7787 		}
7788 	    }
7789 	    fclose(fd);
7790 	}
7791     }
7792 
7793     fd = mch_fopen((char *)fname, "a");
7794     if (fd == NULL && new_spf)
7795     {
7796 	/* We just initialized the 'spellfile' option and can't open the file.
7797 	 * We may need to create the "spell" directory first.  We already
7798 	 * checked the runtime directory is writable in init_spellfile(). */
7799 	if (!dir_of_file_exists(fname))
7800 	{
7801 	    /* The directory doesn't exist.  Try creating it and opening the
7802 	     * file again. */
7803 	    vim_mkdir(NameBuff, 0755);
7804 	    fd = mch_fopen((char *)fname, "a");
7805 	}
7806     }
7807 
7808     if (fd == NULL)
7809 	EMSG2(_(e_notopen), fname);
7810     else
7811     {
7812 	if (bad)
7813 	    fprintf(fd, "%.*s/!\n", len, word);
7814 	else
7815 	    fprintf(fd, "%.*s\n", len, word);
7816 	fclose(fd);
7817 
7818 	/* Update the .add.spl file. */
7819 	mkspell(1, &fname, FALSE, TRUE, TRUE);
7820 
7821 	/* If the .add file is edited somewhere, reload it. */
7822 	if (buf != NULL)
7823 	    buf_reload(buf);
7824 
7825 	redraw_all_later(NOT_VALID);
7826     }
7827 }
7828 
7829 /*
7830  * Initialize 'spellfile' for the current buffer.
7831  */
7832     static void
7833 init_spellfile()
7834 {
7835     char_u	buf[MAXPATHL];
7836     int		l;
7837     char_u	*fname;
7838     char_u	*rtp;
7839     char_u	*lend;
7840     int		aspath = FALSE;
7841     char_u	*lstart = curbuf->b_p_spl;
7842 
7843     if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0)
7844     {
7845 	/* Find the end of the language name.  Exclude the region.  If there
7846 	 * is a path separator remember the start of the tail. */
7847 	for (lend = curbuf->b_p_spl; *lend != NUL
7848 			&& vim_strchr((char_u *)",._", *lend) == NULL; ++lend)
7849 	    if (vim_ispathsep(*lend))
7850 	    {
7851 		aspath = TRUE;
7852 		lstart = lend + 1;
7853 	    }
7854 
7855 	/* Loop over all entries in 'runtimepath'.  Use the first one where we
7856 	 * are allowed to write. */
7857 	rtp = p_rtp;
7858 	while (*rtp != NUL)
7859 	{
7860 	    if (aspath)
7861 		/* Use directory of an entry with path, e.g., for
7862 		 * "/dir/lg.utf-8.spl" use "/dir". */
7863 		vim_strncpy(buf, curbuf->b_p_spl, lstart - curbuf->b_p_spl - 1);
7864 	    else
7865 		/* Copy the path from 'runtimepath' to buf[]. */
7866 		copy_option_part(&rtp, buf, MAXPATHL, ",");
7867 	    if (filewritable(buf) == 2)
7868 	    {
7869 		/* Use the first language name from 'spelllang' and the
7870 		 * encoding used in the first loaded .spl file. */
7871 		if (aspath)
7872 		    vim_strncpy(buf, curbuf->b_p_spl, lend - curbuf->b_p_spl);
7873 		else
7874 		{
7875 		    l = STRLEN(buf);
7876 		    vim_snprintf((char *)buf + l, MAXPATHL - l,
7877 				 "/spell/%.*s", (int)(lend - lstart), lstart);
7878 		}
7879 		l = STRLEN(buf);
7880 		fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname;
7881 		vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
7882 			fname != NULL
7883 			  && strstr((char *)gettail(fname), ".ascii.") != NULL
7884 				       ? (char_u *)"ascii" : spell_enc());
7885 		set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
7886 		break;
7887 	    }
7888 	    aspath = FALSE;
7889 	}
7890     }
7891 }
7892 
7893 
7894 /*
7895  * Init the chartab used for spelling for ASCII.
7896  * EBCDIC is not supported!
7897  */
7898     static void
7899 clear_spell_chartab(sp)
7900     spelltab_T	*sp;
7901 {
7902     int		i;
7903 
7904     /* Init everything to FALSE. */
7905     vim_memset(sp->st_isw, FALSE, sizeof(sp->st_isw));
7906     vim_memset(sp->st_isu, FALSE, sizeof(sp->st_isu));
7907     for (i = 0; i < 256; ++i)
7908     {
7909 	sp->st_fold[i] = i;
7910 	sp->st_upper[i] = i;
7911     }
7912 
7913     /* We include digits.  A word shouldn't start with a digit, but handling
7914      * that is done separately. */
7915     for (i = '0'; i <= '9'; ++i)
7916 	sp->st_isw[i] = TRUE;
7917     for (i = 'A'; i <= 'Z'; ++i)
7918     {
7919 	sp->st_isw[i] = TRUE;
7920 	sp->st_isu[i] = TRUE;
7921 	sp->st_fold[i] = i + 0x20;
7922     }
7923     for (i = 'a'; i <= 'z'; ++i)
7924     {
7925 	sp->st_isw[i] = TRUE;
7926 	sp->st_upper[i] = i - 0x20;
7927     }
7928 }
7929 
7930 /*
7931  * Init the chartab used for spelling.  Only depends on 'encoding'.
7932  * Called once while starting up and when 'encoding' changes.
7933  * The default is to use isalpha(), but the spell file should define the word
7934  * characters to make it possible that 'encoding' differs from the current
7935  * locale.  For utf-8 we don't use isalpha() but our own functions.
7936  */
7937     void
7938 init_spell_chartab()
7939 {
7940     int	    i;
7941 
7942     did_set_spelltab = FALSE;
7943     clear_spell_chartab(&spelltab);
7944 #ifdef FEAT_MBYTE
7945     if (enc_dbcs)
7946     {
7947 	/* DBCS: assume double-wide characters are word characters. */
7948 	for (i = 128; i <= 255; ++i)
7949 	    if (MB_BYTE2LEN(i) == 2)
7950 		spelltab.st_isw[i] = TRUE;
7951     }
7952     else if (enc_utf8)
7953     {
7954 	for (i = 128; i < 256; ++i)
7955 	{
7956 	    spelltab.st_isu[i] = utf_isupper(i);
7957 	    spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i);
7958 	    spelltab.st_fold[i] = utf_fold(i);
7959 	    spelltab.st_upper[i] = utf_toupper(i);
7960 	}
7961     }
7962     else
7963 #endif
7964     {
7965 	/* Rough guess: use locale-dependent library functions. */
7966 	for (i = 128; i < 256; ++i)
7967 	{
7968 	    if (MB_ISUPPER(i))
7969 	    {
7970 		spelltab.st_isw[i] = TRUE;
7971 		spelltab.st_isu[i] = TRUE;
7972 		spelltab.st_fold[i] = MB_TOLOWER(i);
7973 	    }
7974 	    else if (MB_ISLOWER(i))
7975 	    {
7976 		spelltab.st_isw[i] = TRUE;
7977 		spelltab.st_upper[i] = MB_TOUPPER(i);
7978 	    }
7979 	}
7980     }
7981 }
7982 
7983 /*
7984  * Set the spell character tables from strings in the affix file.
7985  */
7986     static int
7987 set_spell_chartab(fol, low, upp)
7988     char_u	*fol;
7989     char_u	*low;
7990     char_u	*upp;
7991 {
7992     /* We build the new tables here first, so that we can compare with the
7993      * previous one. */
7994     spelltab_T	new_st;
7995     char_u	*pf = fol, *pl = low, *pu = upp;
7996     int		f, l, u;
7997 
7998     clear_spell_chartab(&new_st);
7999 
8000     while (*pf != NUL)
8001     {
8002 	if (*pl == NUL || *pu == NUL)
8003 	{
8004 	    EMSG(_(e_affform));
8005 	    return FAIL;
8006 	}
8007 #ifdef FEAT_MBYTE
8008 	f = mb_ptr2char_adv(&pf);
8009 	l = mb_ptr2char_adv(&pl);
8010 	u = mb_ptr2char_adv(&pu);
8011 #else
8012 	f = *pf++;
8013 	l = *pl++;
8014 	u = *pu++;
8015 #endif
8016 	/* Every character that appears is a word character. */
8017 	if (f < 256)
8018 	    new_st.st_isw[f] = TRUE;
8019 	if (l < 256)
8020 	    new_st.st_isw[l] = TRUE;
8021 	if (u < 256)
8022 	    new_st.st_isw[u] = TRUE;
8023 
8024 	/* if "LOW" and "FOL" are not the same the "LOW" char needs
8025 	 * case-folding */
8026 	if (l < 256 && l != f)
8027 	{
8028 	    if (f >= 256)
8029 	    {
8030 		EMSG(_(e_affrange));
8031 		return FAIL;
8032 	    }
8033 	    new_st.st_fold[l] = f;
8034 	}
8035 
8036 	/* if "UPP" and "FOL" are not the same the "UPP" char needs
8037 	 * case-folding, it's upper case and the "UPP" is the upper case of
8038 	 * "FOL" . */
8039 	if (u < 256 && u != f)
8040 	{
8041 	    if (f >= 256)
8042 	    {
8043 		EMSG(_(e_affrange));
8044 		return FAIL;
8045 	    }
8046 	    new_st.st_fold[u] = f;
8047 	    new_st.st_isu[u] = TRUE;
8048 	    new_st.st_upper[f] = u;
8049 	}
8050     }
8051 
8052     if (*pl != NUL || *pu != NUL)
8053     {
8054 	EMSG(_(e_affform));
8055 	return FAIL;
8056     }
8057 
8058     return set_spell_finish(&new_st);
8059 }
8060 
8061 /*
8062  * Set the spell character tables from strings in the .spl file.
8063  */
8064     static void
8065 set_spell_charflags(flags, cnt, fol)
8066     char_u	*flags;
8067     int		cnt;	    /* length of "flags" */
8068     char_u	*fol;
8069 {
8070     /* We build the new tables here first, so that we can compare with the
8071      * previous one. */
8072     spelltab_T	new_st;
8073     int		i;
8074     char_u	*p = fol;
8075     int		c;
8076 
8077     clear_spell_chartab(&new_st);
8078 
8079     for (i = 0; i < 128; ++i)
8080     {
8081 	if (i < cnt)
8082 	{
8083 	    new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0;
8084 	    new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0;
8085 	}
8086 
8087 	if (*p != NUL)
8088 	{
8089 #ifdef FEAT_MBYTE
8090 	    c = mb_ptr2char_adv(&p);
8091 #else
8092 	    c = *p++;
8093 #endif
8094 	    new_st.st_fold[i + 128] = c;
8095 	    if (i + 128 != c && new_st.st_isu[i + 128] && c < 256)
8096 		new_st.st_upper[c] = i + 128;
8097 	}
8098     }
8099 
8100     (void)set_spell_finish(&new_st);
8101 }
8102 
8103     static int
8104 set_spell_finish(new_st)
8105     spelltab_T	*new_st;
8106 {
8107     int		i;
8108 
8109     if (did_set_spelltab)
8110     {
8111 	/* check that it's the same table */
8112 	for (i = 0; i < 256; ++i)
8113 	{
8114 	    if (spelltab.st_isw[i] != new_st->st_isw[i]
8115 		    || spelltab.st_isu[i] != new_st->st_isu[i]
8116 		    || spelltab.st_fold[i] != new_st->st_fold[i]
8117 		    || spelltab.st_upper[i] != new_st->st_upper[i])
8118 	    {
8119 		EMSG(_("E763: Word characters differ between spell files"));
8120 		return FAIL;
8121 	    }
8122 	}
8123     }
8124     else
8125     {
8126 	/* copy the new spelltab into the one being used */
8127 	spelltab = *new_st;
8128 	did_set_spelltab = TRUE;
8129     }
8130 
8131     return OK;
8132 }
8133 
8134 /*
8135  * Return TRUE if "p" points to a word character.
8136  * As a special case we see "midword" characters as word character when it is
8137  * followed by a word character.  This finds they'there but not 'they there'.
8138  * Thus this only works properly when past the first character of the word.
8139  */
8140     static int
8141 spell_iswordp(p, buf)
8142     char_u	*p;
8143     buf_T	*buf;	    /* buffer used */
8144 {
8145 #ifdef FEAT_MBYTE
8146     char_u	*s;
8147     int		l;
8148     int		c;
8149 
8150     if (has_mbyte)
8151     {
8152 	l = MB_BYTE2LEN(*p);
8153 	s = p;
8154 	if (l == 1)
8155 	{
8156 	    /* be quick for ASCII */
8157 	    if (buf->b_spell_ismw[*p])
8158 	    {
8159 		s = p + 1;		/* skip a mid-word character */
8160 		l = MB_BYTE2LEN(*s);
8161 	    }
8162 	}
8163 	else
8164 	{
8165 	    c = mb_ptr2char(p);
8166 	    if (c < 256 ? buf->b_spell_ismw[c]
8167 		    : (buf->b_spell_ismw_mb != NULL
8168 			   && vim_strchr(buf->b_spell_ismw_mb, c) != NULL))
8169 	    {
8170 		s = p + l;
8171 		l = MB_BYTE2LEN(*s);
8172 	    }
8173 	}
8174 
8175 	c = mb_ptr2char(s);
8176 	if (c > 255)
8177 	    return mb_get_class(s) >= 2;
8178 	return spelltab.st_isw[c];
8179     }
8180 #endif
8181 
8182     return spelltab.st_isw[buf->b_spell_ismw[*p] ? p[1] : p[0]];
8183 }
8184 
8185 /*
8186  * Return TRUE if "p" points to a word character.
8187  * Unlike spell_iswordp() this doesn't check for "midword" characters.
8188  */
8189     static int
8190 spell_iswordp_nmw(p)
8191     char_u	*p;
8192 {
8193 #ifdef FEAT_MBYTE
8194     int		c;
8195 
8196     if (has_mbyte)
8197     {
8198 	c = mb_ptr2char(p);
8199 	if (c > 255)
8200 	    return mb_get_class(p) >= 2;
8201 	return spelltab.st_isw[c];
8202     }
8203 #endif
8204     return spelltab.st_isw[*p];
8205 }
8206 
8207 #ifdef FEAT_MBYTE
8208 /*
8209  * Return TRUE if "p" points to a word character.
8210  * Wide version of spell_iswordp().
8211  */
8212     static int
8213 spell_iswordp_w(p, buf)
8214     int		*p;
8215     buf_T	*buf;
8216 {
8217     int		*s;
8218 
8219     if (*p < 256 ? buf->b_spell_ismw[*p]
8220 		 : (buf->b_spell_ismw_mb != NULL
8221 			     && vim_strchr(buf->b_spell_ismw_mb, *p) != NULL))
8222 	s = p + 1;
8223     else
8224 	s = p;
8225 
8226     if (*s > 255)
8227     {
8228 	if (enc_utf8)
8229 	    return utf_class(*s) >= 2;
8230 	if (enc_dbcs)
8231 	    return dbcs_class((unsigned)*s >> 8, *s & 0xff) >= 2;
8232 	return 0;
8233     }
8234     return spelltab.st_isw[*s];
8235 }
8236 #endif
8237 
8238 /*
8239  * Write the table with prefix conditions to the .spl file.
8240  * When "fd" is NULL only count the length of what is written.
8241  */
8242     static int
8243 write_spell_prefcond(fd, gap)
8244     FILE	*fd;
8245     garray_T	*gap;
8246 {
8247     int		i;
8248     char_u	*p;
8249     int		len;
8250     int		totlen;
8251 
8252     if (fd != NULL)
8253 	put_bytes(fd, (long_u)gap->ga_len, 2);	    /* <prefcondcnt> */
8254 
8255     totlen = 2 + gap->ga_len; /* length of <prefcondcnt> and <condlen> bytes */
8256 
8257     for (i = 0; i < gap->ga_len; ++i)
8258     {
8259 	/* <prefcond> : <condlen> <condstr> */
8260 	p = ((char_u **)gap->ga_data)[i];
8261 	if (p != NULL)
8262 	{
8263 	    len = STRLEN(p);
8264 	    if (fd != NULL)
8265 	    {
8266 		fputc(len, fd);
8267 		fwrite(p, (size_t)len, (size_t)1, fd);
8268 	    }
8269 	    totlen += len;
8270 	}
8271 	else if (fd != NULL)
8272 	    fputc(0, fd);
8273     }
8274 
8275     return totlen;
8276 }
8277 
8278 /*
8279  * Case-fold "str[len]" into "buf[buflen]".  The result is NUL terminated.
8280  * Uses the character definitions from the .spl file.
8281  * When using a multi-byte 'encoding' the length may change!
8282  * Returns FAIL when something wrong.
8283  */
8284     static int
8285 spell_casefold(str, len, buf, buflen)
8286     char_u	*str;
8287     int		len;
8288     char_u	*buf;
8289     int		buflen;
8290 {
8291     int		i;
8292 
8293     if (len >= buflen)
8294     {
8295 	buf[0] = NUL;
8296 	return FAIL;		/* result will not fit */
8297     }
8298 
8299 #ifdef FEAT_MBYTE
8300     if (has_mbyte)
8301     {
8302 	int	outi = 0;
8303 	char_u	*p;
8304 	int	c;
8305 
8306 	/* Fold one character at a time. */
8307 	for (p = str; p < str + len; )
8308 	{
8309 	    if (outi + MB_MAXBYTES > buflen)
8310 	    {
8311 		buf[outi] = NUL;
8312 		return FAIL;
8313 	    }
8314 	    c = mb_cptr2char_adv(&p);
8315 	    outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
8316 	}
8317 	buf[outi] = NUL;
8318     }
8319     else
8320 #endif
8321     {
8322 	/* Be quick for non-multibyte encodings. */
8323 	for (i = 0; i < len; ++i)
8324 	    buf[i] = spelltab.st_fold[str[i]];
8325 	buf[i] = NUL;
8326     }
8327 
8328     return OK;
8329 }
8330 
8331 #define SPS_BEST    1
8332 #define SPS_FAST    2
8333 #define SPS_DOUBLE  4
8334 
8335 static int sps_flags = SPS_BEST;
8336 static int sps_limit = 9999;
8337 
8338 /*
8339  * Check the 'spellsuggest' option.  Return FAIL if it's wrong.
8340  * Sets "sps_flags" and "sps_limit".
8341  */
8342     int
8343 spell_check_sps()
8344 {
8345     char_u	*p;
8346     char_u	*s;
8347     char_u	buf[MAXPATHL];
8348     int		f;
8349 
8350     sps_flags = 0;
8351     sps_limit = 9999;
8352 
8353     for (p = p_sps; *p != NUL; )
8354     {
8355 	copy_option_part(&p, buf, MAXPATHL, ",");
8356 
8357 	f = 0;
8358 	if (VIM_ISDIGIT(*buf))
8359 	{
8360 	    s = buf;
8361 	    sps_limit = getdigits(&s);
8362 	    if (*s != NUL && !VIM_ISDIGIT(*s))
8363 		f = -1;
8364 	}
8365 	else if (STRCMP(buf, "best") == 0)
8366 	    f = SPS_BEST;
8367 	else if (STRCMP(buf, "fast") == 0)
8368 	    f = SPS_FAST;
8369 	else if (STRCMP(buf, "double") == 0)
8370 	    f = SPS_DOUBLE;
8371 	else if (STRNCMP(buf, "expr:", 5) != 0
8372 		&& STRNCMP(buf, "file:", 5) != 0)
8373 	    f = -1;
8374 
8375 	if (f == -1 || (sps_flags != 0 && f != 0))
8376 	{
8377 	    sps_flags = SPS_BEST;
8378 	    sps_limit = 9999;
8379 	    return FAIL;
8380 	}
8381 	if (f != 0)
8382 	    sps_flags = f;
8383     }
8384 
8385     if (sps_flags == 0)
8386 	sps_flags = SPS_BEST;
8387 
8388     return OK;
8389 }
8390 
8391 /* Remember what "z?" replaced. */
8392 static char_u	*repl_from = NULL;
8393 static char_u	*repl_to = NULL;
8394 
8395 /*
8396  * "z?": Find badly spelled word under or after the cursor.
8397  * Give suggestions for the properly spelled word.
8398  * When "count" is non-zero use that suggestion.
8399  */
8400     void
8401 spell_suggest(count)
8402     int		count;
8403 {
8404     char_u	*line;
8405     pos_T	prev_cursor = curwin->w_cursor;
8406     char_u	wcopy[MAXWLEN + 2];
8407     char_u	*p;
8408     int		i;
8409     int		c;
8410     suginfo_T	sug;
8411     suggest_T	*stp;
8412     int		mouse_used;
8413     int		need_cap;
8414     int		limit;
8415     int		selected = count;
8416 
8417     /* Find the start of the badly spelled word. */
8418     if (spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL) == 0
8419 	    || curwin->w_cursor.col > prev_cursor.col)
8420     {
8421 	if (!curwin->w_p_spell || *curbuf->b_p_spl == NUL)
8422 	    return;
8423 
8424 	/* No bad word or it starts after the cursor: use the word under the
8425 	 * cursor. */
8426 	curwin->w_cursor = prev_cursor;
8427 	line = ml_get_curline();
8428 	p = line + curwin->w_cursor.col;
8429 	/* Backup to before start of word. */
8430 	while (p > line && spell_iswordp_nmw(p))
8431 	    mb_ptr_back(line, p);
8432 	/* Forward to start of word. */
8433 	while (*p != NUL && !spell_iswordp_nmw(p))
8434 	    mb_ptr_adv(p);
8435 
8436 	if (!spell_iswordp_nmw(p))		/* No word found. */
8437 	{
8438 	    beep_flush();
8439 	    return;
8440 	}
8441 	curwin->w_cursor.col = p - line;
8442     }
8443 
8444     /* Get the word and its length. */
8445 
8446     /* Figure out if the word should be capitalised. */
8447     need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
8448 
8449     line = ml_get_curline();
8450 
8451     /* Get the list of suggestions.  Limit to 'lines' - 2 or the number in
8452      * 'spellsuggest', whatever is smaller. */
8453     if (sps_limit > (int)Rows - 2)
8454 	limit = (int)Rows - 2;
8455     else
8456 	limit = sps_limit;
8457     spell_find_suggest(line + curwin->w_cursor.col, &sug, limit,
8458 							      TRUE, need_cap);
8459 
8460     if (sug.su_ga.ga_len == 0)
8461 	MSG(_("Sorry, no suggestions"));
8462     else if (count > 0)
8463     {
8464 	if (count > sug.su_ga.ga_len)
8465 	    smsg((char_u *)_("Sorry, only %ld suggestions"),
8466 						      (long)sug.su_ga.ga_len);
8467     }
8468     else
8469     {
8470 	vim_free(repl_from);
8471 	repl_from = NULL;
8472 	vim_free(repl_to);
8473 	repl_to = NULL;
8474 
8475 #ifdef FEAT_RIGHTLEFT
8476 	/* When 'rightleft' is set the list is drawn right-left. */
8477 	cmdmsg_rl = curwin->w_p_rl;
8478 	if (cmdmsg_rl)
8479 	    msg_col = Columns - 1;
8480 #endif
8481 
8482 	/* List the suggestions. */
8483 	msg_start();
8484 	lines_left = Rows;	/* avoid more prompt */
8485 	vim_snprintf((char *)IObuff, IOSIZE, _("Change \"%.*s\" to:"),
8486 						sug.su_badlen, sug.su_badptr);
8487 #ifdef FEAT_RIGHTLEFT
8488 	if (cmdmsg_rl && STRNCMP(IObuff, "Change", 6) == 0)
8489 	{
8490 	    /* And now the rabbit from the high hat: Avoid showing the
8491 	     * untranslated message rightleft. */
8492 	    vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC",
8493 						sug.su_badlen, sug.su_badptr);
8494 	}
8495 #endif
8496 	msg_puts(IObuff);
8497 	msg_clr_eos();
8498 	msg_putchar('\n');
8499 
8500 	msg_scroll = TRUE;
8501 	for (i = 0; i < sug.su_ga.ga_len; ++i)
8502 	{
8503 	    stp = &SUG(sug.su_ga, i);
8504 
8505 	    /* The suggested word may replace only part of the bad word, add
8506 	     * the not replaced part. */
8507 	    STRCPY(wcopy, stp->st_word);
8508 	    if (sug.su_badlen > stp->st_orglen)
8509 		vim_strncpy(wcopy + STRLEN(wcopy),
8510 					       sug.su_badptr + stp->st_orglen,
8511 					      sug.su_badlen - stp->st_orglen);
8512 	    vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
8513 #ifdef FEAT_RIGHTLEFT
8514 	    if (cmdmsg_rl)
8515 		rl_mirror(IObuff);
8516 #endif
8517 	    msg_puts(IObuff);
8518 
8519 	    vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy);
8520 	    msg_puts(IObuff);
8521 
8522 	    /* The word may replace more than "su_badlen". */
8523 	    if (sug.su_badlen < stp->st_orglen)
8524 	    {
8525 		vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""),
8526 					       stp->st_orglen, sug.su_badptr);
8527 		msg_puts(IObuff);
8528 	    }
8529 
8530 	    if (p_verbose > 0)
8531 	    {
8532 		/* Add the score. */
8533 		if (sps_flags & (SPS_DOUBLE | SPS_BEST))
8534 		    vim_snprintf((char *)IObuff, IOSIZE, " (%s%d - %d)",
8535 			stp->st_salscore ? "s " : "",
8536 			stp->st_score, stp->st_altscore);
8537 		else
8538 		    vim_snprintf((char *)IObuff, IOSIZE, " (%d)",
8539 			    stp->st_score);
8540 #ifdef FEAT_RIGHTLEFT
8541 		if (cmdmsg_rl)
8542 		    /* Mirror the numbers, but keep the leading space. */
8543 		    rl_mirror(IObuff + 1);
8544 #endif
8545 		msg_advance(30);
8546 		msg_puts(IObuff);
8547 	    }
8548 	    msg_putchar('\n');
8549 	}
8550 
8551 #ifdef FEAT_RIGHTLEFT
8552 	cmdmsg_rl = FALSE;
8553 	msg_col = 0;
8554 #endif
8555 	/* Ask for choice. */
8556 	selected = prompt_for_number(&mouse_used);
8557 	if (mouse_used)
8558 	    selected -= lines_left;
8559     }
8560 
8561     if (selected > 0 && selected <= sug.su_ga.ga_len && u_save_cursor() == OK)
8562     {
8563 	/* Save the from and to text for :spellrepall. */
8564 	stp = &SUG(sug.su_ga, selected - 1);
8565 	if (sug.su_badlen > stp->st_orglen)
8566 	{
8567 	    /* Replacing less than "su_badlen", append the remainder to
8568 	     * repl_to. */
8569 	    repl_from = vim_strnsave(sug.su_badptr, sug.su_badlen);
8570 	    vim_snprintf((char *)IObuff, IOSIZE, "%s%.*s", stp->st_word,
8571 		    sug.su_badlen - stp->st_orglen,
8572 					      sug.su_badptr + stp->st_orglen);
8573 	    repl_to = vim_strsave(IObuff);
8574 	}
8575 	else
8576 	{
8577 	    /* Replacing su_badlen or more, use the whole word. */
8578 	    repl_from = vim_strnsave(sug.su_badptr, stp->st_orglen);
8579 	    repl_to = vim_strsave(stp->st_word);
8580 	}
8581 
8582 	/* Replace the word. */
8583 	p = alloc(STRLEN(line) - stp->st_orglen + STRLEN(stp->st_word) + 1);
8584 	if (p != NULL)
8585 	{
8586 	    c = sug.su_badptr - line;
8587 	    mch_memmove(p, line, c);
8588 	    STRCPY(p + c, stp->st_word);
8589 	    STRCAT(p, sug.su_badptr + stp->st_orglen);
8590 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
8591 	    curwin->w_cursor.col = c;
8592 	    changed_bytes(curwin->w_cursor.lnum, c);
8593 
8594 	    /* For redo we use a change-word command. */
8595 	    ResetRedobuff();
8596 	    AppendToRedobuff((char_u *)"ciw");
8597 	    AppendToRedobuff(stp->st_word);
8598 	    AppendCharToRedobuff(ESC);
8599 	}
8600     }
8601     else
8602 	curwin->w_cursor = prev_cursor;
8603 
8604     spell_find_cleanup(&sug);
8605 }
8606 
8607 /*
8608  * Check if the word at line "lnum" column "col" is required to start with a
8609  * capital.  This uses 'spellcapcheck' of the current buffer.
8610  */
8611     static int
8612 check_need_cap(lnum, col)
8613     linenr_T	lnum;
8614     colnr_T	col;
8615 {
8616     int		need_cap = FALSE;
8617     char_u	*line;
8618     char_u	*line_copy = NULL;
8619     char_u	*p;
8620     colnr_T	endcol;
8621     regmatch_T	regmatch;
8622 
8623     if (curbuf->b_cap_prog == NULL)
8624 	return FALSE;
8625 
8626     line = ml_get_curline();
8627     endcol = 0;
8628     if ((int)(skipwhite(line) - line) >= (int)col)
8629     {
8630 	/* At start of line, check if previous line is empty or sentence
8631 	 * ends there. */
8632 	if (lnum == 1)
8633 	    need_cap = TRUE;
8634 	else
8635 	{
8636 	    line = ml_get(lnum - 1);
8637 	    if (*skipwhite(line) == NUL)
8638 		need_cap = TRUE;
8639 	    else
8640 	    {
8641 		/* Append a space in place of the line break. */
8642 		line_copy = concat_str(line, (char_u *)" ");
8643 		line = line_copy;
8644 		endcol = STRLEN(line);
8645 	    }
8646 	}
8647     }
8648     else
8649 	endcol = col;
8650 
8651     if (endcol > 0)
8652     {
8653 	/* Check if sentence ends before the bad word. */
8654 	regmatch.regprog = curbuf->b_cap_prog;
8655 	regmatch.rm_ic = FALSE;
8656 	p = line + endcol;
8657 	for (;;)
8658 	{
8659 	    mb_ptr_back(line, p);
8660 	    if (p == line || spell_iswordp_nmw(p))
8661 		break;
8662 	    if (vim_regexec(&regmatch, p, 0)
8663 					 && regmatch.endp[0] == line + endcol)
8664 	    {
8665 		need_cap = TRUE;
8666 		break;
8667 	    }
8668 	}
8669     }
8670 
8671     vim_free(line_copy);
8672 
8673     return need_cap;
8674 }
8675 
8676 
8677 /*
8678  * ":spellrepall"
8679  */
8680 /*ARGSUSED*/
8681     void
8682 ex_spellrepall(eap)
8683     exarg_T *eap;
8684 {
8685     pos_T	pos = curwin->w_cursor;
8686     char_u	*frompat;
8687     int		addlen;
8688     char_u	*line;
8689     char_u	*p;
8690     int		save_ws = p_ws;
8691     linenr_T	prev_lnum = 0;
8692 
8693     if (repl_from == NULL || repl_to == NULL)
8694     {
8695 	EMSG(_("E752: No previous spell replacement"));
8696 	return;
8697     }
8698     addlen = STRLEN(repl_to) - STRLEN(repl_from);
8699 
8700     frompat = alloc(STRLEN(repl_from) + 7);
8701     if (frompat == NULL)
8702 	return;
8703     sprintf((char *)frompat, "\\V\\<%s\\>", repl_from);
8704     p_ws = FALSE;
8705 
8706     sub_nsubs = 0;
8707     sub_nlines = 0;
8708     curwin->w_cursor.lnum = 0;
8709     while (!got_int)
8710     {
8711 	if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP) == 0
8712 						   || u_save_cursor() == FAIL)
8713 	    break;
8714 
8715 	/* Only replace when the right word isn't there yet.  This happens
8716 	 * when changing "etc" to "etc.". */
8717 	line = ml_get_curline();
8718 	if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col,
8719 					       repl_to, STRLEN(repl_to)) != 0)
8720 	{
8721 	    p = alloc(STRLEN(line) + addlen + 1);
8722 	    if (p == NULL)
8723 		break;
8724 	    mch_memmove(p, line, curwin->w_cursor.col);
8725 	    STRCPY(p + curwin->w_cursor.col, repl_to);
8726 	    STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from));
8727 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
8728 	    changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
8729 
8730 	    if (curwin->w_cursor.lnum != prev_lnum)
8731 	    {
8732 		++sub_nlines;
8733 		prev_lnum = curwin->w_cursor.lnum;
8734 	    }
8735 	    ++sub_nsubs;
8736 	}
8737 	curwin->w_cursor.col += STRLEN(repl_to);
8738     }
8739 
8740     p_ws = save_ws;
8741     curwin->w_cursor = pos;
8742     vim_free(frompat);
8743 
8744     if (sub_nsubs == 0)
8745 	EMSG2(_("E753: Not found: %s"), repl_from);
8746     else
8747 	do_sub_msg(FALSE);
8748 }
8749 
8750 /*
8751  * Find spell suggestions for "word".  Return them in the growarray "*gap" as
8752  * a list of allocated strings.
8753  */
8754     void
8755 spell_suggest_list(gap, word, maxcount, need_cap)
8756     garray_T	*gap;
8757     char_u	*word;
8758     int		maxcount;	/* maximum nr of suggestions */
8759     int		need_cap;	/* 'spellcapcheck' matched */
8760 {
8761     suginfo_T	sug;
8762     int		i;
8763     suggest_T	*stp;
8764     char_u	*wcopy;
8765 
8766     spell_find_suggest(word, &sug, maxcount, FALSE, need_cap);
8767 
8768     /* Make room in "gap". */
8769     ga_init2(gap, sizeof(char_u *), sug.su_ga.ga_len + 1);
8770     if (ga_grow(gap, sug.su_ga.ga_len) == FAIL)
8771 	return;
8772 
8773     for (i = 0; i < sug.su_ga.ga_len; ++i)
8774     {
8775 	stp = &SUG(sug.su_ga, i);
8776 
8777 	/* The suggested word may replace only part of "word", add the not
8778 	 * replaced part. */
8779 	wcopy = alloc(STRLEN(stp->st_word)
8780 				+ STRLEN(sug.su_badptr + stp->st_orglen) + 1);
8781 	if (wcopy == NULL)
8782 	    break;
8783 	STRCPY(wcopy, stp->st_word);
8784 	STRCAT(wcopy, sug.su_badptr + stp->st_orglen);
8785 	((char_u **)gap->ga_data)[gap->ga_len++] = wcopy;
8786     }
8787 
8788     spell_find_cleanup(&sug);
8789 }
8790 
8791 /*
8792  * Find spell suggestions for the word at the start of "badptr".
8793  * Return the suggestions in "su->su_ga".
8794  * The maximum number of suggestions is "maxcount".
8795  * Note: does use info for the current window.
8796  * This is based on the mechanisms of Aspell, but completely reimplemented.
8797  */
8798     static void
8799 spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
8800     char_u	*badptr;
8801     suginfo_T	*su;
8802     int		maxcount;
8803     int		banbadword;	/* don't include badword in suggestions */
8804     int		need_cap;	/* word should start with capital */
8805 {
8806     hlf_T	attr = HLF_COUNT;
8807     char_u	buf[MAXPATHL];
8808     char_u	*p;
8809     int		do_combine = FALSE;
8810     char_u	*sps_copy;
8811 #ifdef FEAT_EVAL
8812     static int	expr_busy = FALSE;
8813 #endif
8814     int		c;
8815     int		i;
8816     langp_T	*lp;
8817 
8818     /*
8819      * Set the info in "*su".
8820      */
8821     vim_memset(su, 0, sizeof(suginfo_T));
8822     ga_init2(&su->su_ga, (int)sizeof(suggest_T), 10);
8823     ga_init2(&su->su_sga, (int)sizeof(suggest_T), 10);
8824     if (*badptr == NUL)
8825 	return;
8826     hash_init(&su->su_banned);
8827 
8828     su->su_badptr = badptr;
8829     su->su_badlen = spell_check(curwin, su->su_badptr, &attr, NULL);
8830     su->su_maxcount = maxcount;
8831     su->su_maxscore = SCORE_MAXINIT;
8832 
8833     if (su->su_badlen >= MAXWLEN)
8834 	su->su_badlen = MAXWLEN - 1;	/* just in case */
8835     vim_strncpy(su->su_badword, su->su_badptr, su->su_badlen);
8836     (void)spell_casefold(su->su_badptr, su->su_badlen,
8837 						    su->su_fbadword, MAXWLEN);
8838     /* get caps flags for bad word */
8839     su->su_badflags = badword_captype(su->su_badptr,
8840 					       su->su_badptr + su->su_badlen);
8841     if (need_cap)
8842 	su->su_badflags |= WF_ONECAP;
8843 
8844     /* Find the default language for sound folding.  We simply use the first
8845      * one in 'spelllang' that supports sound folding.  That's good for when
8846      * using multiple files for one language, it's not that bad when mixing
8847      * languages (e.g., "pl,en"). */
8848     for (i = 0; i < curbuf->b_langp.ga_len; ++i)
8849     {
8850 	lp = LANGP_ENTRY(curbuf->b_langp, i);
8851 	if (lp->lp_sallang != NULL)
8852 	{
8853 	    su->su_sallang = lp->lp_sallang;
8854 	    break;
8855 	}
8856     }
8857 
8858     /* Soundfold the bad word with the default sound folding, so that we don't
8859      * have to do this many times. */
8860     if (su->su_sallang != NULL)
8861 	spell_soundfold(su->su_sallang, su->su_fbadword, TRUE,
8862 							  su->su_sal_badword);
8863 
8864     /* If the word is not capitalised and spell_check() doesn't consider the
8865      * word to be bad then it might need to be capitalised.  Add a suggestion
8866      * for that. */
8867     c = PTR2CHAR(su->su_badptr);
8868     if (!SPELL_ISUPPER(c) && attr == HLF_COUNT)
8869     {
8870 	make_case_word(su->su_badword, buf, WF_ONECAP);
8871 	add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
8872 						     0, TRUE, su->su_sallang);
8873     }
8874 
8875     /* Ban the bad word itself.  It may appear in another region. */
8876     if (banbadword)
8877 	add_banned(su, su->su_badword);
8878 
8879     /* Make a copy of 'spellsuggest', because the expression may change it. */
8880     sps_copy = vim_strsave(p_sps);
8881     if (sps_copy == NULL)
8882 	return;
8883 
8884     /* Loop over the items in 'spellsuggest'. */
8885     for (p = sps_copy; *p != NUL; )
8886     {
8887 	copy_option_part(&p, buf, MAXPATHL, ",");
8888 
8889 	if (STRNCMP(buf, "expr:", 5) == 0)
8890 	{
8891 #ifdef FEAT_EVAL
8892 	    /* Evaluate an expression.  Skip this when called recursively,
8893 	     * when using spellsuggest() in the expression. */
8894 	    if (!expr_busy)
8895 	    {
8896 		expr_busy = TRUE;
8897 		spell_suggest_expr(su, buf + 5);
8898 		expr_busy = FALSE;
8899 	    }
8900 #endif
8901 	}
8902 	else if (STRNCMP(buf, "file:", 5) == 0)
8903 	    /* Use list of suggestions in a file. */
8904 	    spell_suggest_file(su, buf + 5);
8905 	else
8906 	{
8907 	    /* Use internal method. */
8908 	    spell_suggest_intern(su);
8909 	    if (sps_flags & SPS_DOUBLE)
8910 		do_combine = TRUE;
8911 	}
8912     }
8913 
8914     vim_free(sps_copy);
8915 
8916     if (do_combine)
8917 	/* Combine the two list of suggestions.  This must be done last,
8918 	 * because sorting changes the order again. */
8919 	score_combine(su);
8920 }
8921 
8922 #ifdef FEAT_EVAL
8923 /*
8924  * Find suggestions by evaluating expression "expr".
8925  */
8926     static void
8927 spell_suggest_expr(su, expr)
8928     suginfo_T	*su;
8929     char_u	*expr;
8930 {
8931     list_T	*list;
8932     listitem_T	*li;
8933     int		score;
8934     char_u	*p;
8935 
8936     /* The work is split up in a few parts to avoid having to export
8937      * suginfo_T.
8938      * First evaluate the expression and get the resulting list. */
8939     list = eval_spell_expr(su->su_badword, expr);
8940     if (list != NULL)
8941     {
8942 	/* Loop over the items in the list. */
8943 	for (li = list->lv_first; li != NULL; li = li->li_next)
8944 	    if (li->li_tv.v_type == VAR_LIST)
8945 	    {
8946 		/* Get the word and the score from the items. */
8947 		score = get_spellword(li->li_tv.vval.v_list, &p);
8948 		if (score >= 0)
8949 		    add_suggestion(su, &su->su_ga, p,
8950 			       su->su_badlen, score, 0, TRUE, su->su_sallang);
8951 	    }
8952 	list_unref(list);
8953     }
8954 
8955     /* Sort the suggestions and truncate at "maxcount". */
8956     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
8957 }
8958 #endif
8959 
8960 /*
8961  * Find suggestions in file "fname".  Used for "file:" in 'spellsuggest'.
8962  */
8963     static void
8964 spell_suggest_file(su, fname)
8965     suginfo_T	*su;
8966     char_u	*fname;
8967 {
8968     FILE	*fd;
8969     char_u	line[MAXWLEN * 2];
8970     char_u	*p;
8971     int		len;
8972     char_u	cword[MAXWLEN];
8973 
8974     /* Open the file. */
8975     fd = mch_fopen((char *)fname, "r");
8976     if (fd == NULL)
8977     {
8978 	EMSG2(_(e_notopen), fname);
8979 	return;
8980     }
8981 
8982     /* Read it line by line. */
8983     while (!vim_fgets(line, MAXWLEN * 2, fd) && !got_int)
8984     {
8985 	line_breakcheck();
8986 
8987 	p = vim_strchr(line, '/');
8988 	if (p == NULL)
8989 	    continue;	    /* No Tab found, just skip the line. */
8990 	*p++ = NUL;
8991 	if (STRICMP(su->su_badword, line) == 0)
8992 	{
8993 	    /* Match!  Isolate the good word, until CR or NL. */
8994 	    for (len = 0; p[len] >= ' '; ++len)
8995 		;
8996 	    p[len] = NUL;
8997 
8998 	    /* If the suggestion doesn't have specific case duplicate the case
8999 	     * of the bad word. */
9000 	    if (captype(p, NULL) == 0)
9001 	    {
9002 		make_case_word(p, cword, su->su_badflags);
9003 		p = cword;
9004 	    }
9005 
9006 	    add_suggestion(su, &su->su_ga, p, su->su_badlen,
9007 					 SCORE_FILE, 0, TRUE, su->su_sallang);
9008 	}
9009     }
9010 
9011     fclose(fd);
9012 
9013     /* Sort the suggestions and truncate at "maxcount". */
9014     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
9015 }
9016 
9017 /*
9018  * Find suggestions for the internal method indicated by "sps_flags".
9019  */
9020     static void
9021 spell_suggest_intern(su)
9022     suginfo_T	*su;
9023 {
9024     /*
9025      * 1. Try special cases, such as repeating a word: "the the" -> "the".
9026      *
9027      * Set a maximum score to limit the combination of operations that is
9028      * tried.
9029      */
9030     suggest_try_special(su);
9031 
9032     /*
9033      * 2. Try inserting/deleting/swapping/changing a letter, use REP entries
9034      *    from the .aff file and inserting a space (split the word).
9035      */
9036     suggest_try_change(su);
9037 
9038     /* For the resulting top-scorers compute the sound-a-like score. */
9039     if (sps_flags & SPS_DOUBLE)
9040 	score_comp_sal(su);
9041 
9042     /*
9043      * 3. Try finding sound-a-like words.
9044      *
9045      * Only do this when we don't have a lot of suggestions yet, because it's
9046      * very slow and often doesn't find new suggestions.
9047      */
9048     if ((sps_flags & SPS_DOUBLE)
9049 	    || (!(sps_flags & SPS_FAST)
9050 				    && su->su_ga.ga_len < SUG_CLEAN_COUNT(su)))
9051     {
9052 	/* Allow a higher score now. */
9053 	su->su_maxscore = SCORE_MAXMAX;
9054 	suggest_try_soundalike(su);
9055     }
9056 
9057     /* When CTRL-C was hit while searching do show the results. */
9058     ui_breakcheck();
9059     if (got_int)
9060     {
9061 	(void)vgetc();
9062 	got_int = FALSE;
9063     }
9064 
9065     if ((sps_flags & SPS_DOUBLE) == 0 && su->su_ga.ga_len != 0)
9066     {
9067 	if (sps_flags & SPS_BEST)
9068 	    /* Adjust the word score for how it sounds like. */
9069 	    rescore_suggestions(su);
9070 
9071 	/* Sort the suggestions and truncate at "maxcount". */
9072 	(void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
9073     }
9074 }
9075 
9076 /*
9077  * Free the info put in "*su" by spell_find_suggest().
9078  */
9079     static void
9080 spell_find_cleanup(su)
9081     suginfo_T	*su;
9082 {
9083     int		i;
9084 
9085     /* Free the suggestions. */
9086     for (i = 0; i < su->su_ga.ga_len; ++i)
9087 	vim_free(SUG(su->su_ga, i).st_word);
9088     ga_clear(&su->su_ga);
9089     for (i = 0; i < su->su_sga.ga_len; ++i)
9090 	vim_free(SUG(su->su_sga, i).st_word);
9091     ga_clear(&su->su_sga);
9092 
9093     /* Free the banned words. */
9094     free_banned(su);
9095 }
9096 
9097 /*
9098  * Make a copy of "word", with the first letter upper or lower cased, to
9099  * "wcopy[MAXWLEN]".  "word" must not be empty.
9100  * The result is NUL terminated.
9101  */
9102     static void
9103 onecap_copy(word, wcopy, upper)
9104     char_u	*word;
9105     char_u	*wcopy;
9106     int		upper;	    /* TRUE: first letter made upper case */
9107 {
9108     char_u	*p;
9109     int		c;
9110     int		l;
9111 
9112     p = word;
9113 #ifdef FEAT_MBYTE
9114     if (has_mbyte)
9115 	c = mb_cptr2char_adv(&p);
9116     else
9117 #endif
9118 	c = *p++;
9119     if (upper)
9120 	c = SPELL_TOUPPER(c);
9121     else
9122 	c = SPELL_TOFOLD(c);
9123 #ifdef FEAT_MBYTE
9124     if (has_mbyte)
9125 	l = mb_char2bytes(c, wcopy);
9126     else
9127 #endif
9128     {
9129 	l = 1;
9130 	wcopy[0] = c;
9131     }
9132     vim_strncpy(wcopy + l, p, MAXWLEN - l - 1);
9133 }
9134 
9135 /*
9136  * Make a copy of "word" with all the letters upper cased into
9137  * "wcopy[MAXWLEN]".  The result is NUL terminated.
9138  */
9139     static void
9140 allcap_copy(word, wcopy)
9141     char_u	*word;
9142     char_u	*wcopy;
9143 {
9144     char_u	*s;
9145     char_u	*d;
9146     int		c;
9147 
9148     d = wcopy;
9149     for (s = word; *s != NUL; )
9150     {
9151 #ifdef FEAT_MBYTE
9152 	if (has_mbyte)
9153 	    c = mb_cptr2char_adv(&s);
9154 	else
9155 #endif
9156 	    c = *s++;
9157 
9158 #ifdef FEAT_MBYTE
9159 	/* We only change � to SS when we are certain latin1 is used.  It
9160 	 * would cause weird errors in other 8-bit encodings. */
9161 	if (enc_latin1like && c == 0xdf)
9162 	{
9163 	    c = 'S';
9164 	    if (d - wcopy >= MAXWLEN - 1)
9165 		break;
9166 	    *d++ = c;
9167 	}
9168 	else
9169 #endif
9170 	    c = SPELL_TOUPPER(c);
9171 
9172 #ifdef FEAT_MBYTE
9173 	if (has_mbyte)
9174 	{
9175 	    if (d - wcopy >= MAXWLEN - MB_MAXBYTES)
9176 		break;
9177 	    d += mb_char2bytes(c, d);
9178 	}
9179 	else
9180 #endif
9181 	{
9182 	    if (d - wcopy >= MAXWLEN - 1)
9183 		break;
9184 	    *d++ = c;
9185 	}
9186     }
9187     *d = NUL;
9188 }
9189 
9190 /*
9191  * Try finding suggestions by recognizing specific situations.
9192  */
9193     static void
9194 suggest_try_special(su)
9195     suginfo_T	*su;
9196 {
9197     char_u	*p;
9198     size_t	len;
9199     int		c;
9200     char_u	word[MAXWLEN];
9201 
9202     /*
9203      * Recognize a word that is repeated: "the the".
9204      */
9205     p = skiptowhite(su->su_fbadword);
9206     len = p - su->su_fbadword;
9207     p = skipwhite(p);
9208     if (STRLEN(p) == len && STRNCMP(su->su_fbadword, p, len) == 0)
9209     {
9210 	/* Include badflags: if the badword is onecap or allcap
9211 	 * use that for the goodword too: "The the" -> "The". */
9212 	c = su->su_fbadword[len];
9213 	su->su_fbadword[len] = NUL;
9214 	make_case_word(su->su_fbadword, word, su->su_badflags);
9215 	su->su_fbadword[len] = c;
9216 
9217 	/* Give a soundalike score of 0, compute the score as if deleting one
9218 	 * character. */
9219 	add_suggestion(su, &su->su_ga, word, su->su_badlen,
9220 			      RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang);
9221     }
9222 }
9223 
9224 /*
9225  * Try finding suggestions by adding/removing/swapping letters.
9226  *
9227  * This uses a state machine.  At each node in the tree we try various
9228  * operations.  When trying if an operation work "depth" is increased and the
9229  * stack[] is used to store info.  This allows combinations, thus insert one
9230  * character, replace one and delete another.  The number of changes is
9231  * limited by su->su_maxscore, checked in try_deeper().
9232  *
9233  * After implementing this I noticed an article by Kemal Oflazer that
9234  * describes something similar: "Error-tolerant Finite State Recognition with
9235  * Applications to Morphological Analysis and Spelling Correction" (1996).
9236  * The implementation in the article is simplified and requires a stack of
9237  * unknown depth.  The implementation here only needs a stack depth of the
9238  * length of the word.
9239  */
9240     static void
9241 suggest_try_change(su)
9242     suginfo_T	*su;
9243 {
9244     char_u	fword[MAXWLEN];	    /* copy of the bad word, case-folded */
9245     char_u	tword[MAXWLEN];	    /* good word collected so far */
9246     trystate_T	stack[MAXWLEN];
9247     char_u	preword[MAXWLEN * 3]; /* word found with proper case;
9248 				       * concatanation of prefix compound
9249 				       * words and split word.  NUL terminated
9250 				       * when going deeper but not when coming
9251 				       * back. */
9252     char_u	compflags[MAXWLEN];	/* compound flags, one for each word */
9253     trystate_T	*sp;
9254     int		newscore;
9255     langp_T	*lp;
9256     char_u	*byts, *fbyts, *pbyts;
9257     idx_T	*idxs, *fidxs, *pidxs;
9258     int		depth;
9259     int		c, c2, c3;
9260     int		n;
9261     int		flags;
9262     garray_T	*gap;
9263     idx_T	arridx;
9264     int		len;
9265     char_u	*p;
9266     fromto_T	*ftp;
9267     int		fl = 0, tl;
9268     int		repextra = 0;	    /* extra bytes in fword[] from REP item */
9269     slang_T	*slang;
9270     int		fword_ends;
9271     int		lpi;
9272     int		maysplit;
9273     int		goodword_ends;
9274 
9275     /* We make a copy of the case-folded bad word, so that we can modify it
9276      * to find matches (esp. REP items).  Append some more text, changing
9277      * chars after the bad word may help. */
9278     STRCPY(fword, su->su_fbadword);
9279     n = STRLEN(fword);
9280     p = su->su_badptr + su->su_badlen;
9281     (void)spell_casefold(p, STRLEN(p), fword + n, MAXWLEN - n);
9282 
9283     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
9284     {
9285 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
9286 	slang = lp->lp_slang;
9287 
9288 	/* If reloading a spell file fails it's still in the list but
9289 	 * everything has been cleared. */
9290 	if (slang->sl_fbyts == NULL)
9291 	    continue;
9292 
9293 	/*
9294 	 * Go through the whole case-fold tree, try changes at each node.
9295 	 * "tword[]" contains the word collected from nodes in the tree.
9296 	 * "fword[]" the word we are trying to match with (initially the bad
9297 	 * word).
9298 	 */
9299 	depth = 0;
9300 	sp = &stack[0];
9301 	vim_memset(sp, 0, sizeof(trystate_T));
9302 	sp->ts_curi = 1;
9303 
9304 	/*
9305 	 * When there are postponed prefixes we need to use these first.  At
9306 	 * the end of the prefix we continue in the case-fold tree.
9307 	 */
9308 	fbyts = slang->sl_fbyts;
9309 	fidxs = slang->sl_fidxs;
9310 	pbyts = slang->sl_pbyts;
9311 	pidxs = slang->sl_pidxs;
9312 	if (pbyts != NULL)
9313 	{
9314 	    byts = pbyts;
9315 	    idxs = pidxs;
9316 	    sp->ts_prefixdepth = PFD_PREFIXTREE;
9317 	    sp->ts_state = STATE_NOPREFIX;	/* try without prefix first */
9318 	}
9319 	else
9320 	{
9321 	    byts = fbyts;
9322 	    idxs = fidxs;
9323 	    sp->ts_prefixdepth = PFD_NOPREFIX;
9324 	    sp->ts_state = STATE_START;
9325 	}
9326 
9327 	/*
9328 	 * Loop to find all suggestions.  At each round we either:
9329 	 * - For the current state try one operation, advance "ts_curi",
9330 	 *   increase "depth".
9331 	 * - When a state is done go to the next, set "ts_state".
9332 	 * - When all states are tried decrease "depth".
9333 	 */
9334 	while (depth >= 0 && !got_int)
9335 	{
9336 	    sp = &stack[depth];
9337 	    switch (sp->ts_state)
9338 	    {
9339 	    case STATE_START:
9340 	    case STATE_NOPREFIX:
9341 		/*
9342 		 * Start of node: Deal with NUL bytes, which means
9343 		 * tword[] may end here.
9344 		 */
9345 		arridx = sp->ts_arridx;	    /* current node in the tree */
9346 		len = byts[arridx];	    /* bytes in this node */
9347 		arridx += sp->ts_curi;	    /* index of current byte */
9348 
9349 		if (sp->ts_prefixdepth == PFD_PREFIXTREE)
9350 		{
9351 		    /* Skip over the NUL bytes, we use them later. */
9352 		    for (n = 0; n < len && byts[arridx + n] == 0; ++n)
9353 			;
9354 		    sp->ts_curi += n;
9355 
9356 		    /* Always past NUL bytes now. */
9357 		    n = (int)sp->ts_state;
9358 		    sp->ts_state = STATE_ENDNUL;
9359 		    sp->ts_save_badflags = su->su_badflags;
9360 
9361 		    /* At end of a prefix or at start of prefixtree: check for
9362 		     * following word. */
9363 		    if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)
9364 		    {
9365 			/* Set su->su_badflags to the caps type at this
9366 			 * position.  Use the caps type until here for the
9367 			 * prefix itself. */
9368 #ifdef FEAT_MBYTE
9369 			if (has_mbyte)
9370 			    n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
9371 			else
9372 #endif
9373 			    n = sp->ts_fidx;
9374 			flags = badword_captype(su->su_badptr,
9375 							   su->su_badptr + n);
9376 			su->su_badflags = badword_captype(su->su_badptr + n,
9377 					       su->su_badptr + su->su_badlen);
9378 			++depth;
9379 			stack[depth] = stack[depth - 1];
9380 			sp = &stack[depth];
9381 			sp->ts_prefixdepth = depth - 1;
9382 			byts = fbyts;
9383 			idxs = fidxs;
9384 			sp->ts_state = STATE_START;
9385 			sp->ts_curi = 1;   /* start just after length byte */
9386 			sp->ts_arridx = 0;
9387 
9388 			/* Move the prefix to preword[] with the right case
9389 			 * and make find_keepcap_word() works. */
9390 			tword[sp->ts_twordlen] = NUL;
9391 			make_case_word(tword + sp->ts_splitoff,
9392 						  preword + sp->ts_prewordlen,
9393 								       flags);
9394 			sp->ts_prewordlen = STRLEN(preword);
9395 			sp->ts_splitoff = sp->ts_twordlen;
9396 		    }
9397 		    break;
9398 		}
9399 
9400 		if (sp->ts_curi > len || byts[arridx] != 0)
9401 		{
9402 		    /* Past bytes in node and/or past NUL bytes. */
9403 		    sp->ts_state = STATE_ENDNUL;
9404 		    sp->ts_save_badflags = su->su_badflags;
9405 		    break;
9406 		}
9407 
9408 		/*
9409 		 * End of word in tree.
9410 		 */
9411 		++sp->ts_curi;		/* eat one NUL byte */
9412 
9413 		flags = (int)idxs[arridx];
9414 		fword_ends = (fword[sp->ts_fidx] == NUL
9415 			       || !spell_iswordp(fword + sp->ts_fidx, curbuf));
9416 		tword[sp->ts_twordlen] = NUL;
9417 
9418 		if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
9419 					&& (sp->ts_flags & TSF_PREFIXOK) == 0)
9420 		{
9421 		    /* There was a prefix before the word.  Check that the
9422 		     * prefix can be used with this word. */
9423 		    /* Count the length of the NULs in the prefix.  If there
9424 		     * are none this must be the first try without a prefix.
9425 		     */
9426 		    n = stack[sp->ts_prefixdepth].ts_arridx;
9427 		    len = pbyts[n++];
9428 		    for (c = 0; c < len && pbyts[n + c] == 0; ++c)
9429 			;
9430 		    if (c > 0)
9431 		    {
9432 			c = valid_word_prefix(c, n, flags,
9433 				       tword + sp->ts_splitoff, slang, FALSE);
9434 			if (c == 0)
9435 			    break;
9436 
9437 			/* Use the WF_RARE flag for a rare prefix. */
9438 			if (c & WF_RAREPFX)
9439 			    flags |= WF_RARE;
9440 
9441 			/* Tricky: when checking for both prefix and
9442 			 * compounding we run into the prefix flag first.
9443 			 * Remember that it's OK, so that we accept the prefix
9444 			 * when arriving at a compound flag. */
9445 			sp->ts_flags |= TSF_PREFIXOK;
9446 		    }
9447 		}
9448 
9449 		/* Check NEEDCOMPOUND: can't use word without compounding.  Do
9450 		 * try appending another compound word below. */
9451 		if (sp->ts_complen == sp->ts_compsplit && fword_ends
9452 						     && (flags & WF_NEEDCOMP))
9453 		    goodword_ends = FALSE;
9454 		else
9455 		    goodword_ends = TRUE;
9456 
9457 		if (sp->ts_complen > sp->ts_compsplit)
9458 		{
9459 		    if (slang->sl_nobreak)
9460 		    {
9461 			/* There was a word before this word.  When there was
9462 			 * no change in this word (it was correct) add the
9463 			 * first word as a suggestion.  If this word was
9464 			 * corrected too, we need to check if a correct word
9465 			 * follows. */
9466 			if (sp->ts_fidx - sp->ts_splitfidx
9467 					  == sp->ts_twordlen - sp->ts_splitoff
9468 				&& STRNCMP(fword + sp->ts_splitfidx,
9469 					    tword + sp->ts_splitoff,
9470 					 sp->ts_fidx - sp->ts_splitfidx) == 0)
9471 			{
9472 			    preword[sp->ts_prewordlen] = NUL;
9473 			    add_suggestion(su, &su->su_ga, preword,
9474 				    sp->ts_splitfidx - repextra,
9475 				    sp->ts_score, 0, FALSE,
9476 				    lp->lp_sallang);
9477 			    break;
9478 			}
9479 		    }
9480 		    else
9481 		    {
9482 			/* There was a compound word before this word.  If
9483 			 * this word does not support compounding then give up
9484 			 * (splitting is tried for the word without compound
9485 			 * flag). */
9486 			if (((unsigned)flags >> 24) == 0
9487 				|| sp->ts_twordlen - sp->ts_splitoff
9488 						       < slang->sl_compminlen)
9489 			    break;
9490 #ifdef FEAT_MBYTE
9491 			/* For multi-byte chars check character length against
9492 			 * COMPOUNDMIN. */
9493 			if (has_mbyte
9494 				&& slang->sl_compminlen > 0
9495 				&& mb_charlen(tword + sp->ts_splitoff)
9496 						       < slang->sl_compminlen)
9497 			    break;
9498 #endif
9499 
9500 			compflags[sp->ts_complen] = ((unsigned)flags >> 24);
9501 			compflags[sp->ts_complen + 1] = NUL;
9502 			vim_strncpy(preword + sp->ts_prewordlen,
9503 				tword + sp->ts_splitoff,
9504 				sp->ts_twordlen - sp->ts_splitoff);
9505 			p = preword;
9506 			while (*skiptowhite(p) != NUL)
9507 			    p = skipwhite(skiptowhite(p));
9508 			if (fword_ends && !can_compound(slang, p,
9509 						compflags + sp->ts_compsplit))
9510 			    break;
9511 
9512 			/* Get pointer to last char of previous word. */
9513 			p = preword + sp->ts_prewordlen;
9514 			mb_ptr_back(preword, p);
9515 		    }
9516 		}
9517 		else
9518 		    p = NULL;
9519 
9520 		/*
9521 		 * Form the word with proper case in preword.
9522 		 * If there is a word from a previous split, append.
9523 		 */
9524 		if (flags & WF_KEEPCAP)
9525 		    /* Must find the word in the keep-case tree. */
9526 		    find_keepcap_word(slang, tword + sp->ts_splitoff,
9527 						 preword + sp->ts_prewordlen);
9528 		else
9529 		{
9530 		    /* Include badflags: if the badword is onecap or allcap
9531 		     * use that for the goodword too.  But if the badword is
9532 		     * allcap and it's only one char long use onecap. */
9533 		    c = su->su_badflags;
9534 		    if ((c & WF_ALLCAP)
9535 #ifdef FEAT_MBYTE
9536 			    && su->su_badlen == (*mb_ptr2len)(su->su_badptr)
9537 #else
9538 			    && su->su_badlen == 1
9539 #endif
9540 			    )
9541 			c = WF_ONECAP;
9542 		    c |= flags;
9543 
9544 		    /* When appending a compound word after a word character
9545 		     * don't use Onecap. */
9546 		    if (p != NULL && spell_iswordp_nmw(p))
9547 			c &= ~WF_ONECAP;
9548 		    make_case_word(tword + sp->ts_splitoff,
9549 					      preword + sp->ts_prewordlen, c);
9550 		}
9551 
9552 		/* Don't use a banned word.  It may appear again as a good
9553 		 * word, thus remember it. */
9554 		if (flags & WF_BANNED)
9555 		{
9556 		    add_banned(su, preword + sp->ts_prewordlen);
9557 		    break;
9558 		}
9559 		if ((sp->ts_complen == sp->ts_compsplit
9560 			    && was_banned(su, preword + sp->ts_prewordlen))
9561 						   || was_banned(su, preword))
9562 		{
9563 		    if (slang->sl_compprog == NULL)
9564 			break;
9565 		    /* the word so far was banned but we may try compounding */
9566 		    goodword_ends = FALSE;
9567 		}
9568 
9569 		newscore = 0;
9570 		if ((flags & WF_REGION)
9571 			    && (((unsigned)flags >> 16) & lp->lp_region) == 0)
9572 		    newscore += SCORE_REGION;
9573 		if (flags & WF_RARE)
9574 		    newscore += SCORE_RARE;
9575 
9576 		if (!spell_valid_case(su->su_badflags,
9577 				  captype(preword + sp->ts_prewordlen, NULL)))
9578 		    newscore += SCORE_ICASE;
9579 
9580 		maysplit = TRUE;
9581 		if (fword_ends && goodword_ends
9582 					     && sp->ts_fidx >= sp->ts_fidxtry)
9583 		{
9584 		    /* The badword also ends: add suggestions.  Give a penalty
9585 		     * when changing non-word char to word char, e.g., "thes,"
9586 		     * -> "these". */
9587 		    p = fword + sp->ts_fidx;
9588 #ifdef FEAT_MBYTE
9589 		    if (has_mbyte)
9590 			mb_ptr_back(fword, p);
9591 		    else
9592 #endif
9593 			--p;
9594 		    if (!spell_iswordp(p, curbuf))
9595 		    {
9596 			p = preword + STRLEN(preword);
9597 #ifdef FEAT_MBYTE
9598 			if (has_mbyte)
9599 			    mb_ptr_back(preword, p);
9600 			else
9601 #endif
9602 			    --p;
9603 			if (spell_iswordp(p, curbuf))
9604 			    newscore += SCORE_NONWORD;
9605 		    }
9606 
9607 		    add_suggestion(su, &su->su_ga, preword,
9608 					sp->ts_fidx - repextra,
9609 					sp->ts_score + newscore, 0, FALSE,
9610 					lp->lp_sallang);
9611 
9612 		    /* When the bad word doesn't end yet, try changing the
9613 		     * next word.  E.g., find suggestions for "the the" where
9614 		     * the second "the" is different.  It's done like a split.
9615 		     */
9616 		    if (sp->ts_fidx - repextra >= su->su_badlen)
9617 			maysplit = FALSE;
9618 		}
9619 
9620 		if (maysplit
9621 			&& (sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
9622 #ifdef FEAT_MBYTE
9623 			/* Don't split halfway a character. */
9624 			&& (!has_mbyte || sp->ts_tcharlen == 0)
9625 #endif
9626 			)
9627 		{
9628 		    int	    try_compound;
9629 
9630 		    /* Get here in two situations:
9631 		     * 1. The word in the tree ends but the badword continues:
9632 		     *    If the word allows compounding try that.  Otherwise
9633 		     *    try a split by inserting a space.  For both check
9634 		     *    that a valid words starts at fword[sp->ts_fidx].
9635 		     *    For NOBREAK do like compounding to be able to check
9636 		     *    if the next word is valid.
9637 		     * 2. The badword does end, but it was due to a change
9638 		     *    (e.g., a swap).  No need to split, but do check that
9639 		     *    the following word is valid.
9640 		     */
9641 		    try_compound = FALSE;
9642 		    if ((!fword_ends || !goodword_ends)
9643 			    && slang->sl_compprog != NULL
9644 			    && ((unsigned)flags >> 24) != 0
9645 			    && sp->ts_twordlen - sp->ts_splitoff
9646 						      >= slang->sl_compminlen
9647 #ifdef FEAT_MBYTE
9648 			    && (!has_mbyte
9649 				|| slang->sl_compminlen == 0
9650 				|| mb_charlen(tword + sp->ts_splitoff)
9651 						      >= slang->sl_compminlen)
9652 #endif
9653 			    && (slang->sl_compsylmax < MAXWLEN
9654 				|| sp->ts_complen + 1 - sp->ts_compsplit
9655 							   < slang->sl_compmax)
9656 			    && (byte_in_str(sp->ts_complen == sp->ts_compsplit
9657 						? slang->sl_compstartflags
9658 						: slang->sl_compallflags,
9659 						    ((unsigned)flags >> 24))))
9660 		    {
9661 			try_compound = TRUE;
9662 			compflags[sp->ts_complen] = ((unsigned)flags >> 24);
9663 			compflags[sp->ts_complen + 1] = NUL;
9664 		    }
9665 
9666 		    /* For NOBREAK we never try splitting, it won't make any
9667 		     * word valid. */
9668 		    if (slang->sl_nobreak)
9669 			try_compound = TRUE;
9670 
9671 		    /* If we could add a compound word, and it's also possible
9672 		     * to split at this point, do the split first and set
9673 		     * TSF_DIDSPLIT to avoid doing it again. */
9674 		    else if (!fword_ends
9675 			    && try_compound
9676 			    && (sp->ts_flags & TSF_DIDSPLIT) == 0)
9677 		    {
9678 			try_compound = FALSE;
9679 			sp->ts_flags |= TSF_DIDSPLIT;
9680 			--sp->ts_curi;	    /* do the same NUL again */
9681 			compflags[sp->ts_complen] = NUL;
9682 		    }
9683 		    else
9684 			sp->ts_flags &= ~TSF_DIDSPLIT;
9685 
9686 		    if (!try_compound && (!fword_ends || !goodword_ends))
9687 		    {
9688 			/* If we're going to split need to check that the
9689 			 * words so far are valid for compounding.  If there
9690 			 * is only one word it must not have the NEEDCOMPOUND
9691 			 * flag. */
9692 			if (sp->ts_complen == sp->ts_compsplit
9693 						     && (flags & WF_NEEDCOMP))
9694 			    break;
9695 			p = preword;
9696 			while (*skiptowhite(p) != NUL)
9697 			    p = skipwhite(skiptowhite(p));
9698 			if (sp->ts_complen > sp->ts_compsplit
9699 				&& !can_compound(slang, p,
9700 						compflags + sp->ts_compsplit))
9701 			    break;
9702 			newscore += SCORE_SPLIT;
9703 		    }
9704 
9705 		    if (try_deeper(su, stack, depth, newscore))
9706 		    {
9707 			/* Save things to be restored at STATE_SPLITUNDO. */
9708 			sp->ts_save_badflags = su->su_badflags;
9709 			sp->ts_state = STATE_SPLITUNDO;
9710 
9711 			++depth;
9712 			sp = &stack[depth];
9713 
9714 			/* Append a space to preword when splitting. */
9715 			if (!try_compound && !fword_ends)
9716 			    STRCAT(preword, " ");
9717 			sp->ts_prewordlen = STRLEN(preword);
9718 			sp->ts_splitoff = sp->ts_twordlen;
9719 			sp->ts_splitfidx = sp->ts_fidx;
9720 
9721 			/* If the badword has a non-word character at this
9722 			 * position skip it.  That means replacing the
9723 			 * non-word character with a space.  Always skip a
9724 			 * character when the word ends.  But only when the
9725 			 * good word can end. */
9726 			if (((!try_compound
9727 				    && !spell_iswordp_nmw(fword + sp->ts_fidx))
9728 				|| fword_ends)
9729 			    && goodword_ends)
9730 			{
9731 			    int	    l;
9732 
9733 #ifdef FEAT_MBYTE
9734 			    if (has_mbyte)
9735 				l = MB_BYTE2LEN(fword[sp->ts_fidx]);
9736 			    else
9737 #endif
9738 				l = 1;
9739 			    if (fword_ends)
9740 			    {
9741 				/* Copy the skipped character to preword. */
9742 				mch_memmove(preword + sp->ts_prewordlen,
9743 						      fword + sp->ts_fidx, l);
9744 				sp->ts_prewordlen += l;
9745 				preword[sp->ts_prewordlen] = NUL;
9746 			    }
9747 			    else
9748 				sp->ts_score -= SCORE_SPLIT - SCORE_SUBST;
9749 			    sp->ts_fidx += l;
9750 			}
9751 
9752 			/* When compounding include compound flag in
9753 			 * compflags[] (already set above).  When splitting we
9754 			 * may start compounding over again.  */
9755 			if (try_compound)
9756 			    ++sp->ts_complen;
9757 			else
9758 			    sp->ts_compsplit = sp->ts_complen;
9759 			sp->ts_prefixdepth = PFD_NOPREFIX;
9760 
9761 			/* set su->su_badflags to the caps type at this
9762 			 * position */
9763 #ifdef FEAT_MBYTE
9764 			if (has_mbyte)
9765 			    n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
9766 			else
9767 #endif
9768 			    n = sp->ts_fidx;
9769 			su->su_badflags = badword_captype(su->su_badptr + n,
9770 					       su->su_badptr + su->su_badlen);
9771 
9772 			/* Restart at top of the tree. */
9773 			sp->ts_arridx = 0;
9774 
9775 			/* If there are postponed prefixes, try these too. */
9776 			if (pbyts != NULL)
9777 			{
9778 			    byts = pbyts;
9779 			    idxs = pidxs;
9780 			    sp->ts_prefixdepth = PFD_PREFIXTREE;
9781 			    sp->ts_state = STATE_NOPREFIX;
9782 			}
9783 		    }
9784 		}
9785 		break;
9786 
9787 	    case STATE_SPLITUNDO:
9788 		/* Undo the changes done for word split or compound word. */
9789 		su->su_badflags = sp->ts_save_badflags;
9790 
9791 		/* Continue looking for NUL bytes. */
9792 		sp->ts_state = STATE_START;
9793 
9794 		/* In case we went into the prefix tree. */
9795 		byts = fbyts;
9796 		idxs = fidxs;
9797 		break;
9798 
9799 	    case STATE_ENDNUL:
9800 		/* Past the NUL bytes in the node. */
9801 		su->su_badflags = sp->ts_save_badflags;
9802 		if (fword[sp->ts_fidx] == NUL
9803 #ifdef FEAT_MBYTE
9804 			&& sp->ts_tcharlen == 0
9805 #endif
9806 		   )
9807 		{
9808 		    /* The badword ends, can't use the bytes in this node. */
9809 		    sp->ts_state = STATE_DEL;
9810 		    break;
9811 		}
9812 		sp->ts_state = STATE_PLAIN;
9813 		/*FALLTHROUGH*/
9814 
9815 	    case STATE_PLAIN:
9816 		/*
9817 		 * Go over all possible bytes at this node, add each to
9818 		 * tword[] and use child node.  "ts_curi" is the index.
9819 		 */
9820 		arridx = sp->ts_arridx;
9821 		if (sp->ts_curi > byts[arridx])
9822 		{
9823 		    /* Done all bytes at this node, do next state.  When still
9824 		     * at already changed bytes skip the other tricks. */
9825 		    if (sp->ts_fidx >= sp->ts_fidxtry)
9826 			sp->ts_state = STATE_DEL;
9827 		    else
9828 			sp->ts_state = STATE_FINAL;
9829 		}
9830 		else
9831 		{
9832 		    arridx += sp->ts_curi++;
9833 		    c = byts[arridx];
9834 
9835 		    /* Normal byte, go one level deeper.  If it's not equal to
9836 		     * the byte in the bad word adjust the score.  But don't
9837 		     * even try when the byte was already changed. */
9838 		    if (c == fword[sp->ts_fidx]
9839 #ifdef FEAT_MBYTE
9840 			    || (sp->ts_tcharlen > 0
9841 						&& sp->ts_isdiff != DIFF_NONE)
9842 #endif
9843 			    )
9844 			newscore = 0;
9845 		    else
9846 			newscore = SCORE_SUBST;
9847 		    if ((newscore == 0 || sp->ts_fidx >= sp->ts_fidxtry)
9848 				    && try_deeper(su, stack, depth, newscore))
9849 		    {
9850 			++depth;
9851 			sp = &stack[depth];
9852 			++sp->ts_fidx;
9853 			tword[sp->ts_twordlen++] = c;
9854 			sp->ts_arridx = idxs[arridx];
9855 #ifdef FEAT_MBYTE
9856 			if (newscore == SCORE_SUBST)
9857 			    sp->ts_isdiff = DIFF_YES;
9858 			if (has_mbyte)
9859 			{
9860 			    /* Multi-byte characters are a bit complicated to
9861 			     * handle: They differ when any of the bytes
9862 			     * differ and then their length may also differ. */
9863 			    if (sp->ts_tcharlen == 0)
9864 			    {
9865 				/* First byte. */
9866 				sp->ts_tcharidx = 0;
9867 				sp->ts_tcharlen = MB_BYTE2LEN(c);
9868 				sp->ts_fcharstart = sp->ts_fidx - 1;
9869 				sp->ts_isdiff = (newscore != 0)
9870 						       ? DIFF_YES : DIFF_NONE;
9871 			    }
9872 			    else if (sp->ts_isdiff == DIFF_INSERT)
9873 				/* When inserting trail bytes don't advance in
9874 				 * the bad word. */
9875 				--sp->ts_fidx;
9876 			    if (++sp->ts_tcharidx == sp->ts_tcharlen)
9877 			    {
9878 				/* Last byte of character. */
9879 				if (sp->ts_isdiff == DIFF_YES)
9880 				{
9881 				    /* Correct ts_fidx for the byte length of
9882 				     * the character (we didn't check that
9883 				     * before). */
9884 				    sp->ts_fidx = sp->ts_fcharstart
9885 						+ MB_BYTE2LEN(
9886 						    fword[sp->ts_fcharstart]);
9887 
9888 				    /* For changing a composing character
9889 				     * adjust the score from SCORE_SUBST to
9890 				     * SCORE_SUBCOMP. */
9891 				    if (enc_utf8
9892 					    && utf_iscomposing(
9893 						mb_ptr2char(tword
9894 						    + sp->ts_twordlen
9895 							   - sp->ts_tcharlen))
9896 					    && utf_iscomposing(
9897 						mb_ptr2char(fword
9898 							+ sp->ts_fcharstart)))
9899 					sp->ts_score -=
9900 						  SCORE_SUBST - SCORE_SUBCOMP;
9901 
9902 				    /* For a similar character adjust score
9903 				     * from SCORE_SUBST to SCORE_SIMILAR. */
9904 				    else if (slang->sl_has_map
9905 					    && similar_chars(slang,
9906 						mb_ptr2char(tword
9907 						    + sp->ts_twordlen
9908 							   - sp->ts_tcharlen),
9909 						mb_ptr2char(fword
9910 							+ sp->ts_fcharstart)))
9911 					sp->ts_score -=
9912 						  SCORE_SUBST - SCORE_SIMILAR;
9913 				}
9914 				else if (sp->ts_isdiff == DIFF_INSERT
9915 					&& sp->ts_twordlen > sp->ts_tcharlen)
9916 				{
9917 				    p = tword + sp->ts_twordlen
9918 							    - sp->ts_tcharlen;
9919 				    c = mb_ptr2char(p);
9920 				    if (enc_utf8 && utf_iscomposing(c))
9921 				    {
9922 					/* Inserting a composing char doesn't
9923 					 * count that much. */
9924 					sp->ts_score -= SCORE_INS
9925 							      - SCORE_INSCOMP;
9926 				    }
9927 				    else
9928 				    {
9929 					/* If the previous character was the
9930 					 * same, thus doubling a character,
9931 					 * give a bonus to the score. */
9932 					mb_ptr_back(tword, p);
9933 					if (c == mb_ptr2char(p))
9934 					    sp->ts_score -= SCORE_INS
9935 							       - SCORE_INSDUP;
9936 				    }
9937 				}
9938 
9939 				/* Starting a new char, reset the length. */
9940 				sp->ts_tcharlen = 0;
9941 			    }
9942 			}
9943 			else
9944 #endif
9945 			{
9946 			    /* If we found a similar char adjust the score.
9947 			     * We do this after calling try_deeper() because
9948 			     * it's slow. */
9949 			    if (newscore != 0
9950 				    && slang->sl_has_map
9951 				    && similar_chars(slang,
9952 						   c, fword[sp->ts_fidx - 1]))
9953 				sp->ts_score -= SCORE_SUBST - SCORE_SIMILAR;
9954 			}
9955 		    }
9956 		}
9957 		break;
9958 
9959 	    case STATE_DEL:
9960 #ifdef FEAT_MBYTE
9961 		/* When past the first byte of a multi-byte char don't try
9962 		 * delete/insert/swap a character. */
9963 		if (has_mbyte && sp->ts_tcharlen > 0)
9964 		{
9965 		    sp->ts_state = STATE_FINAL;
9966 		    break;
9967 		}
9968 #endif
9969 		/*
9970 		 * Try skipping one character in the bad word (delete it).
9971 		 */
9972 		sp->ts_state = STATE_INS;
9973 		sp->ts_curi = 1;
9974 		if (fword[sp->ts_fidx] != NUL
9975 			&& try_deeper(su, stack, depth, SCORE_DEL))
9976 		{
9977 		    ++depth;
9978 
9979 		    /* Advance over the character in fword[]. Give a bonus to
9980 		     * the score if the same character is following "nn" ->
9981 		     * "n". */
9982 #ifdef FEAT_MBYTE
9983 		    if (has_mbyte)
9984 		    {
9985 			c = mb_ptr2char(fword + sp->ts_fidx);
9986 			stack[depth].ts_fidx += MB_BYTE2LEN(fword[sp->ts_fidx]);
9987 			if (enc_utf8 && utf_iscomposing(c))
9988 			    stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
9989 			else if (c == mb_ptr2char(fword + stack[depth].ts_fidx))
9990 			    stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
9991 		    }
9992 		    else
9993 #endif
9994 		    {
9995 			++stack[depth].ts_fidx;
9996 			if (fword[sp->ts_fidx] == fword[sp->ts_fidx + 1])
9997 			    stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
9998 		    }
9999 		    break;
10000 		}
10001 		/*FALLTHROUGH*/
10002 
10003 	    case STATE_INS:
10004 		/* Insert one byte.  Do this for each possible byte at this
10005 		 * node. */
10006 		n = sp->ts_arridx;
10007 		if (sp->ts_curi > byts[n])
10008 		{
10009 		    /* Done all bytes at this node, do next state. */
10010 		    sp->ts_state = STATE_SWAP;
10011 		}
10012 		else
10013 		{
10014 		    /* Do one more byte at this node.  Skip NUL bytes. */
10015 		    n += sp->ts_curi++;
10016 		    c = byts[n];
10017 		    if (c != 0 && try_deeper(su, stack, depth, SCORE_INS))
10018 		    {
10019 			++depth;
10020 			sp = &stack[depth];
10021 			tword[sp->ts_twordlen++] = c;
10022 			sp->ts_arridx = idxs[n];
10023 #ifdef FEAT_MBYTE
10024 			if (has_mbyte)
10025 			{
10026 			    fl = MB_BYTE2LEN(c);
10027 			    if (fl > 1)
10028 			    {
10029 				/* There are following bytes for the same
10030 				 * character.  We must find all bytes before
10031 				 * trying delete/insert/swap/etc. */
10032 				sp->ts_tcharlen = fl;
10033 				sp->ts_tcharidx = 1;
10034 				sp->ts_isdiff = DIFF_INSERT;
10035 			    }
10036 			}
10037 			else
10038 			    fl = 1;
10039 			if (fl == 1)
10040 #endif
10041 			{
10042 			    /* If the previous character was the same, thus
10043 			     * doubling a character, give a bonus to the
10044 			     * score. */
10045 			    if (sp->ts_twordlen >= 2
10046 					   && tword[sp->ts_twordlen - 2] == c)
10047 				sp->ts_score -= SCORE_INS - SCORE_INSDUP;
10048 			}
10049 		    }
10050 		}
10051 		break;
10052 
10053 	    case STATE_SWAP:
10054 		/*
10055 		 * Swap two bytes in the bad word: "12" -> "21".
10056 		 * We change "fword" here, it's changed back afterwards.
10057 		 */
10058 		p = fword + sp->ts_fidx;
10059 		c = *p;
10060 		if (c == NUL)
10061 		{
10062 		    /* End of word, can't swap or replace. */
10063 		    sp->ts_state = STATE_FINAL;
10064 		    break;
10065 		}
10066 
10067 		/* Don't swap if the first character is not a word character.
10068 		 * SWAP3 etc. also don't make sense then. */
10069 		if (!spell_iswordp(p, curbuf))
10070 		{
10071 		    sp->ts_state = STATE_REP_INI;
10072 		    break;
10073 		}
10074 
10075 #ifdef FEAT_MBYTE
10076 		if (has_mbyte)
10077 		{
10078 		    n = mb_cptr2len(p);
10079 		    c = mb_ptr2char(p);
10080 		    if (!spell_iswordp(p + n, curbuf))
10081 			c2 = c; /* don't swap non-word char */
10082 		    else
10083 			c2 = mb_ptr2char(p + n);
10084 		}
10085 		else
10086 #endif
10087 		{
10088 		    if (!spell_iswordp(p + 1, curbuf))
10089 			c2 = c; /* don't swap non-word char */
10090 		    else
10091 			c2 = p[1];
10092 		}
10093 
10094 		/* When characters are identical, swap won't do anything.
10095 		 * Also get here if the second char is not a word character. */
10096 		if (c == c2)
10097 		{
10098 		    sp->ts_state = STATE_SWAP3;
10099 		    break;
10100 		}
10101 		if (c2 != NUL && try_deeper(su, stack, depth, SCORE_SWAP))
10102 		{
10103 		    sp->ts_state = STATE_UNSWAP;
10104 		    ++depth;
10105 #ifdef FEAT_MBYTE
10106 		    if (has_mbyte)
10107 		    {
10108 			fl = mb_char2len(c2);
10109 			mch_memmove(p, p + n, fl);
10110 			mb_char2bytes(c, p + fl);
10111 			stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
10112 		    }
10113 		    else
10114 #endif
10115 		    {
10116 			p[0] = c2;
10117 			p[1] = c;
10118 			stack[depth].ts_fidxtry = sp->ts_fidx + 2;
10119 		    }
10120 		}
10121 		else
10122 		    /* If this swap doesn't work then SWAP3 won't either. */
10123 		    sp->ts_state = STATE_REP_INI;
10124 		break;
10125 
10126 	    case STATE_UNSWAP:
10127 		/* Undo the STATE_SWAP swap: "21" -> "12". */
10128 		p = fword + sp->ts_fidx;
10129 #ifdef FEAT_MBYTE
10130 		if (has_mbyte)
10131 		{
10132 		    n = MB_BYTE2LEN(*p);
10133 		    c = mb_ptr2char(p + n);
10134 		    mch_memmove(p + MB_BYTE2LEN(p[n]), p, n);
10135 		    mb_char2bytes(c, p);
10136 		}
10137 		else
10138 #endif
10139 		{
10140 		    c = *p;
10141 		    *p = p[1];
10142 		    p[1] = c;
10143 		}
10144 		/*FALLTHROUGH*/
10145 
10146 	    case STATE_SWAP3:
10147 		/* Swap two bytes, skipping one: "123" -> "321".  We change
10148 		 * "fword" here, it's changed back afterwards. */
10149 		p = fword + sp->ts_fidx;
10150 #ifdef FEAT_MBYTE
10151 		if (has_mbyte)
10152 		{
10153 		    n = mb_cptr2len(p);
10154 		    c = mb_ptr2char(p);
10155 		    fl = mb_cptr2len(p + n);
10156 		    c2 = mb_ptr2char(p + n);
10157 		    if (!spell_iswordp(p + n + fl, curbuf))
10158 			c3 = c;	/* don't swap non-word char */
10159 		    else
10160 			c3 = mb_ptr2char(p + n + fl);
10161 		}
10162 		else
10163 #endif
10164 		{
10165 		    c = *p;
10166 		    c2 = p[1];
10167 		    if (!spell_iswordp(p + 2, curbuf))
10168 			c3 = c;	/* don't swap non-word char */
10169 		    else
10170 			c3 = p[2];
10171 		}
10172 
10173 		/* When characters are identical: "121" then SWAP3 result is
10174 		 * identical, ROT3L result is same as SWAP: "211", ROT3L
10175 		 * result is same as SWAP on next char: "112".  Thus skip all
10176 		 * swapping.  Also skip when c3 is NUL.
10177 		 * Also get here when the third character is not a word
10178 		 * character.  Second character may any char: "a.b" -> "b.a" */
10179 		if (c == c3 || c3 == NUL)
10180 		{
10181 		    sp->ts_state = STATE_REP_INI;
10182 		    break;
10183 		}
10184 		if (try_deeper(su, stack, depth, SCORE_SWAP3))
10185 		{
10186 		    sp->ts_state = STATE_UNSWAP3;
10187 		    ++depth;
10188 #ifdef FEAT_MBYTE
10189 		    if (has_mbyte)
10190 		    {
10191 			tl = mb_char2len(c3);
10192 			mch_memmove(p, p + n + fl, tl);
10193 			mb_char2bytes(c2, p + tl);
10194 			mb_char2bytes(c, p + fl + tl);
10195 			stack[depth].ts_fidxtry = sp->ts_fidx + n + fl + tl;
10196 		    }
10197 		    else
10198 #endif
10199 		    {
10200 			p[0] = p[2];
10201 			p[2] = c;
10202 			stack[depth].ts_fidxtry = sp->ts_fidx + 3;
10203 		    }
10204 		}
10205 		else
10206 		    sp->ts_state = STATE_REP_INI;
10207 		break;
10208 
10209 	    case STATE_UNSWAP3:
10210 		/* Undo STATE_SWAP3: "321" -> "123" */
10211 		p = fword + sp->ts_fidx;
10212 #ifdef FEAT_MBYTE
10213 		if (has_mbyte)
10214 		{
10215 		    n = MB_BYTE2LEN(*p);
10216 		    c2 = mb_ptr2char(p + n);
10217 		    fl = MB_BYTE2LEN(p[n]);
10218 		    c = mb_ptr2char(p + n + fl);
10219 		    tl = MB_BYTE2LEN(p[n + fl]);
10220 		    mch_memmove(p + fl + tl, p, n);
10221 		    mb_char2bytes(c, p);
10222 		    mb_char2bytes(c2, p + tl);
10223 		    p = p + tl;
10224 		}
10225 		else
10226 #endif
10227 		{
10228 		    c = *p;
10229 		    *p = p[2];
10230 		    p[2] = c;
10231 		    ++p;
10232 		}
10233 
10234 		if (!spell_iswordp(p, curbuf))
10235 		{
10236 		    /* Middle char is not a word char, skip the rotate.
10237 		     * First and third char were already checked at swap
10238 		     * and swap3. */
10239 		    sp->ts_state = STATE_REP_INI;
10240 		    break;
10241 		}
10242 
10243 		/* Rotate three characters left: "123" -> "231".  We change
10244 		 * "fword" here, it's changed back afterwards. */
10245 		if (try_deeper(su, stack, depth, SCORE_SWAP3))
10246 		{
10247 		    sp->ts_state = STATE_UNROT3L;
10248 		    ++depth;
10249 		    p = fword + sp->ts_fidx;
10250 #ifdef FEAT_MBYTE
10251 		    if (has_mbyte)
10252 		    {
10253 			n = mb_cptr2len(p);
10254 			c = mb_ptr2char(p);
10255 			fl = mb_cptr2len(p + n);
10256 			fl += mb_cptr2len(p + n + fl);
10257 			mch_memmove(p, p + n, fl);
10258 			mb_char2bytes(c, p + fl);
10259 			stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
10260 		    }
10261 		    else
10262 #endif
10263 		    {
10264 			c = *p;
10265 			*p = p[1];
10266 			p[1] = p[2];
10267 			p[2] = c;
10268 			stack[depth].ts_fidxtry = sp->ts_fidx + 3;
10269 		    }
10270 		}
10271 		else
10272 		    sp->ts_state = STATE_REP_INI;
10273 		break;
10274 
10275 	    case STATE_UNROT3L:
10276 		/* Undo ROT3L: "231" -> "123" */
10277 		p = fword + sp->ts_fidx;
10278 #ifdef FEAT_MBYTE
10279 		if (has_mbyte)
10280 		{
10281 		    n = MB_BYTE2LEN(*p);
10282 		    n += MB_BYTE2LEN(p[n]);
10283 		    c = mb_ptr2char(p + n);
10284 		    tl = MB_BYTE2LEN(p[n]);
10285 		    mch_memmove(p + tl, p, n);
10286 		    mb_char2bytes(c, p);
10287 		}
10288 		else
10289 #endif
10290 		{
10291 		    c = p[2];
10292 		    p[2] = p[1];
10293 		    p[1] = *p;
10294 		    *p = c;
10295 		}
10296 
10297 		/* Rotate three bytes right: "123" -> "312".  We change
10298 		 * "fword" here, it's changed back afterwards. */
10299 		if (try_deeper(su, stack, depth, SCORE_SWAP3))
10300 		{
10301 		    sp->ts_state = STATE_UNROT3R;
10302 		    ++depth;
10303 		    p = fword + sp->ts_fidx;
10304 #ifdef FEAT_MBYTE
10305 		    if (has_mbyte)
10306 		    {
10307 			n = mb_cptr2len(p);
10308 			n += mb_cptr2len(p + n);
10309 			c = mb_ptr2char(p + n);
10310 			tl = mb_cptr2len(p + n);
10311 			mch_memmove(p + tl, p, n);
10312 			mb_char2bytes(c, p);
10313 			stack[depth].ts_fidxtry = sp->ts_fidx + n + tl;
10314 		    }
10315 		    else
10316 #endif
10317 		    {
10318 			c = p[2];
10319 			p[2] = p[1];
10320 			p[1] = *p;
10321 			*p = c;
10322 			stack[depth].ts_fidxtry = sp->ts_fidx + 3;
10323 		    }
10324 		}
10325 		else
10326 		    sp->ts_state = STATE_REP_INI;
10327 		break;
10328 
10329 	    case STATE_UNROT3R:
10330 		/* Undo ROT3R: "312" -> "123" */
10331 		p = fword + sp->ts_fidx;
10332 #ifdef FEAT_MBYTE
10333 		if (has_mbyte)
10334 		{
10335 		    c = mb_ptr2char(p);
10336 		    tl = MB_BYTE2LEN(*p);
10337 		    n = MB_BYTE2LEN(p[tl]);
10338 		    n += MB_BYTE2LEN(p[tl + n]);
10339 		    mch_memmove(p, p + tl, n);
10340 		    mb_char2bytes(c, p + n);
10341 		}
10342 		else
10343 #endif
10344 		{
10345 		    c = *p;
10346 		    *p = p[1];
10347 		    p[1] = p[2];
10348 		    p[2] = c;
10349 		}
10350 		/*FALLTHROUGH*/
10351 
10352 	    case STATE_REP_INI:
10353 		/* Check if matching with REP items from the .aff file would
10354 		 * work.  Quickly skip if:
10355 		 * - there are no REP items
10356 		 * - the score is going to be too high anyway
10357 		 * - already applied a REP item or swapped here  */
10358 		if (lp->lp_replang == NULL
10359 			|| sp->ts_score + SCORE_REP >= su->su_maxscore
10360 			|| sp->ts_fidx < sp->ts_fidxtry)
10361 		{
10362 		    sp->ts_state = STATE_FINAL;
10363 		    break;
10364 		}
10365 		gap = &lp->lp_replang->sl_rep;
10366 
10367 		/* Use the first byte to quickly find the first entry that
10368 		 * may match.  If the index is -1 there is none. */
10369 		sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]];
10370 		if (sp->ts_curi < 0)
10371 		{
10372 		    sp->ts_state = STATE_FINAL;
10373 		    break;
10374 		}
10375 
10376 		sp->ts_state = STATE_REP;
10377 		/*FALLTHROUGH*/
10378 
10379 	    case STATE_REP:
10380 		/* Try matching with REP items from the .aff file.  For each
10381 		 * match replace the characters and check if the resulting
10382 		 * word is valid. */
10383 		p = fword + sp->ts_fidx;
10384 
10385 		gap = &lp->lp_replang->sl_rep;
10386 		while (sp->ts_curi < gap->ga_len)
10387 		{
10388 		    ftp = (fromto_T *)gap->ga_data + sp->ts_curi++;
10389 		    if (*ftp->ft_from != *p)
10390 		    {
10391 			/* past possible matching entries */
10392 			sp->ts_curi = gap->ga_len;
10393 			break;
10394 		    }
10395 		    if (STRNCMP(ftp->ft_from, p, STRLEN(ftp->ft_from)) == 0
10396 			    && try_deeper(su, stack, depth, SCORE_REP))
10397 		    {
10398 			/* Need to undo this afterwards. */
10399 			sp->ts_state = STATE_REP_UNDO;
10400 
10401 			/* Change the "from" to the "to" string. */
10402 			++depth;
10403 			fl = STRLEN(ftp->ft_from);
10404 			tl = STRLEN(ftp->ft_to);
10405 			if (fl != tl)
10406 			{
10407 			    mch_memmove(p + tl, p + fl, STRLEN(p + fl) + 1);
10408 			    repextra += tl - fl;
10409 			}
10410 			mch_memmove(p, ftp->ft_to, tl);
10411 			stack[depth].ts_fidxtry = sp->ts_fidx + tl;
10412 #ifdef FEAT_MBYTE
10413 			stack[depth].ts_tcharlen = 0;
10414 #endif
10415 			break;
10416 		    }
10417 		}
10418 
10419 		if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP)
10420 		    /* No (more) matches. */
10421 		    sp->ts_state = STATE_FINAL;
10422 
10423 		break;
10424 
10425 	    case STATE_REP_UNDO:
10426 		/* Undo a REP replacement and continue with the next one. */
10427 		ftp = (fromto_T *)lp->lp_replang->sl_rep.ga_data
10428 							    + sp->ts_curi - 1;
10429 		fl = STRLEN(ftp->ft_from);
10430 		tl = STRLEN(ftp->ft_to);
10431 		p = fword + sp->ts_fidx;
10432 		if (fl != tl)
10433 		{
10434 		    mch_memmove(p + fl, p + tl, STRLEN(p + tl) + 1);
10435 		    repextra -= tl - fl;
10436 		}
10437 		mch_memmove(p, ftp->ft_from, fl);
10438 		sp->ts_state = STATE_REP;
10439 		break;
10440 
10441 	    default:
10442 		/* Did all possible states at this level, go up one level. */
10443 		--depth;
10444 
10445 		if (depth >= 0 && stack[depth].ts_prefixdepth == PFD_PREFIXTREE)
10446 		{
10447 		    /* Continue in or go back to the prefix tree. */
10448 		    byts = pbyts;
10449 		    idxs = pidxs;
10450 		}
10451 
10452 		/* Don't check for CTRL-C too often, it takes time. */
10453 		line_breakcheck();
10454 	    }
10455 	}
10456     }
10457 }
10458 
10459 /*
10460  * Try going one level deeper in the tree.
10461  */
10462     static int
10463 try_deeper(su, stack, depth, score_add)
10464     suginfo_T	*su;
10465     trystate_T	*stack;
10466     int		depth;
10467     int		score_add;
10468 {
10469     int		newscore;
10470 
10471     /* Refuse to go deeper if the scrore is getting too big. */
10472     newscore = stack[depth].ts_score + score_add;
10473     if (newscore >= su->su_maxscore)
10474 	return FALSE;
10475 
10476     stack[depth + 1] = stack[depth];
10477     stack[depth + 1].ts_state = STATE_START;
10478     stack[depth + 1].ts_score = newscore;
10479     stack[depth + 1].ts_curi = 1;	/* start just after length byte */
10480     stack[depth + 1].ts_flags = 0;
10481     return TRUE;
10482 }
10483 
10484 #ifdef FEAT_MBYTE
10485 /*
10486  * Case-folding may change the number of bytes: Count nr of chars in
10487  * fword[flen] and return the byte length of that many chars in "word".
10488  */
10489     static int
10490 nofold_len(fword, flen, word)
10491     char_u	*fword;
10492     int		flen;
10493     char_u	*word;
10494 {
10495     char_u	*p;
10496     int		i = 0;
10497 
10498     for (p = fword; p < fword + flen; mb_ptr_adv(p))
10499 	++i;
10500     for (p = word; i > 0; mb_ptr_adv(p))
10501 	--i;
10502     return (int)(p - word);
10503 }
10504 #endif
10505 
10506 /*
10507  * "fword" is a good word with case folded.  Find the matching keep-case
10508  * words and put it in "kword".
10509  * Theoretically there could be several keep-case words that result in the
10510  * same case-folded word, but we only find one...
10511  */
10512     static void
10513 find_keepcap_word(slang, fword, kword)
10514     slang_T	*slang;
10515     char_u	*fword;
10516     char_u	*kword;
10517 {
10518     char_u	uword[MAXWLEN];		/* "fword" in upper-case */
10519     int		depth;
10520     idx_T	tryidx;
10521 
10522     /* The following arrays are used at each depth in the tree. */
10523     idx_T	arridx[MAXWLEN];
10524     int		round[MAXWLEN];
10525     int		fwordidx[MAXWLEN];
10526     int		uwordidx[MAXWLEN];
10527     int		kwordlen[MAXWLEN];
10528 
10529     int		flen, ulen;
10530     int		l;
10531     int		len;
10532     int		c;
10533     idx_T	lo, hi, m;
10534     char_u	*p;
10535     char_u	*byts = slang->sl_kbyts;    /* array with bytes of the words */
10536     idx_T	*idxs = slang->sl_kidxs;    /* array with indexes */
10537 
10538     if (byts == NULL)
10539     {
10540 	/* array is empty: "cannot happen" */
10541 	*kword = NUL;
10542 	return;
10543     }
10544 
10545     /* Make an all-cap version of "fword". */
10546     allcap_copy(fword, uword);
10547 
10548     /*
10549      * Each character needs to be tried both case-folded and upper-case.
10550      * All this gets very complicated if we keep in mind that changing case
10551      * may change the byte length of a multi-byte character...
10552      */
10553     depth = 0;
10554     arridx[0] = 0;
10555     round[0] = 0;
10556     fwordidx[0] = 0;
10557     uwordidx[0] = 0;
10558     kwordlen[0] = 0;
10559     while (depth >= 0)
10560     {
10561 	if (fword[fwordidx[depth]] == NUL)
10562 	{
10563 	    /* We are at the end of "fword".  If the tree allows a word to end
10564 	     * here we have found a match. */
10565 	    if (byts[arridx[depth] + 1] == 0)
10566 	    {
10567 		kword[kwordlen[depth]] = NUL;
10568 		return;
10569 	    }
10570 
10571 	    /* kword is getting too long, continue one level up */
10572 	    --depth;
10573 	}
10574 	else if (++round[depth] > 2)
10575 	{
10576 	    /* tried both fold-case and upper-case character, continue one
10577 	     * level up */
10578 	    --depth;
10579 	}
10580 	else
10581 	{
10582 	    /*
10583 	     * round[depth] == 1: Try using the folded-case character.
10584 	     * round[depth] == 2: Try using the upper-case character.
10585 	     */
10586 #ifdef FEAT_MBYTE
10587 	    if (has_mbyte)
10588 	    {
10589 		flen = mb_cptr2len(fword + fwordidx[depth]);
10590 		ulen = mb_cptr2len(uword + uwordidx[depth]);
10591 	    }
10592 	    else
10593 #endif
10594 		ulen = flen = 1;
10595 	    if (round[depth] == 1)
10596 	    {
10597 		p = fword + fwordidx[depth];
10598 		l = flen;
10599 	    }
10600 	    else
10601 	    {
10602 		p = uword + uwordidx[depth];
10603 		l = ulen;
10604 	    }
10605 
10606 	    for (tryidx = arridx[depth]; l > 0; --l)
10607 	    {
10608 		/* Perform a binary search in the list of accepted bytes. */
10609 		len = byts[tryidx++];
10610 		c = *p++;
10611 		lo = tryidx;
10612 		hi = tryidx + len - 1;
10613 		while (lo < hi)
10614 		{
10615 		    m = (lo + hi) / 2;
10616 		    if (byts[m] > c)
10617 			hi = m - 1;
10618 		    else if (byts[m] < c)
10619 			lo = m + 1;
10620 		    else
10621 		    {
10622 			lo = hi = m;
10623 			break;
10624 		    }
10625 		}
10626 
10627 		/* Stop if there is no matching byte. */
10628 		if (hi < lo || byts[lo] != c)
10629 		    break;
10630 
10631 		/* Continue at the child (if there is one). */
10632 		tryidx = idxs[lo];
10633 	    }
10634 
10635 	    if (l == 0)
10636 	    {
10637 		/*
10638 		 * Found the matching char.  Copy it to "kword" and go a
10639 		 * level deeper.
10640 		 */
10641 		if (round[depth] == 1)
10642 		{
10643 		    STRNCPY(kword + kwordlen[depth], fword + fwordidx[depth],
10644 									flen);
10645 		    kwordlen[depth + 1] = kwordlen[depth] + flen;
10646 		}
10647 		else
10648 		{
10649 		    STRNCPY(kword + kwordlen[depth], uword + uwordidx[depth],
10650 									ulen);
10651 		    kwordlen[depth + 1] = kwordlen[depth] + ulen;
10652 		}
10653 		fwordidx[depth + 1] = fwordidx[depth] + flen;
10654 		uwordidx[depth + 1] = uwordidx[depth] + ulen;
10655 
10656 		++depth;
10657 		arridx[depth] = tryidx;
10658 		round[depth] = 0;
10659 	    }
10660 	}
10661     }
10662 
10663     /* Didn't find it: "cannot happen". */
10664     *kword = NUL;
10665 }
10666 
10667 /*
10668  * Compute the sound-a-like score for suggestions in su->su_ga and add them to
10669  * su->su_sga.
10670  */
10671     static void
10672 score_comp_sal(su)
10673     suginfo_T	*su;
10674 {
10675     langp_T	*lp;
10676     char_u	badsound[MAXWLEN];
10677     int		i;
10678     suggest_T   *stp;
10679     suggest_T   *sstp;
10680     int		score;
10681     int		lpi;
10682 
10683     if (ga_grow(&su->su_sga, su->su_ga.ga_len) == FAIL)
10684 	return;
10685 
10686     /*	Use the sound-folding of the first language that supports it. */
10687     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
10688     {
10689 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
10690 	if (lp->lp_slang->sl_sal.ga_len > 0)
10691 	{
10692 	    /* soundfold the bad word */
10693 	    spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, badsound);
10694 
10695 	    for (i = 0; i < su->su_ga.ga_len; ++i)
10696 	    {
10697 		stp = &SUG(su->su_ga, i);
10698 
10699 		/* Case-fold the suggested word, sound-fold it and compute the
10700 		 * sound-a-like score. */
10701 		score = stp_sal_score(stp, su, lp->lp_slang, badsound);
10702 		if (score < SCORE_MAXMAX)
10703 		{
10704 		    /* Add the suggestion. */
10705 		    sstp = &SUG(su->su_sga, su->su_sga.ga_len);
10706 		    sstp->st_word = vim_strsave(stp->st_word);
10707 		    if (sstp->st_word != NULL)
10708 		    {
10709 			sstp->st_score = score;
10710 			sstp->st_altscore = 0;
10711 			sstp->st_orglen = stp->st_orglen;
10712 			++su->su_sga.ga_len;
10713 		    }
10714 		}
10715 	    }
10716 	    break;
10717 	}
10718     }
10719 }
10720 
10721 /*
10722  * Combine the list of suggestions in su->su_ga and su->su_sga.
10723  * They are intwined.
10724  */
10725     static void
10726 score_combine(su)
10727     suginfo_T	*su;
10728 {
10729     int		i;
10730     int		j;
10731     garray_T	ga;
10732     garray_T	*gap;
10733     langp_T	*lp;
10734     suggest_T	*stp;
10735     char_u	*p;
10736     char_u	badsound[MAXWLEN];
10737     int		round;
10738     int		lpi;
10739 
10740     /* Add the alternate score to su_ga. */
10741     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
10742     {
10743 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
10744 	if (lp->lp_slang->sl_sal.ga_len > 0)
10745 	{
10746 	    /* soundfold the bad word */
10747 	    spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, badsound);
10748 
10749 	    for (i = 0; i < su->su_ga.ga_len; ++i)
10750 	    {
10751 		stp = &SUG(su->su_ga, i);
10752 		stp->st_altscore = stp_sal_score(stp, su, lp->lp_slang,
10753 								    badsound);
10754 		if (stp->st_altscore == SCORE_MAXMAX)
10755 		    stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4;
10756 		else
10757 		    stp->st_score = (stp->st_score * 3
10758 						  + stp->st_altscore) / 4;
10759 		stp->st_salscore = FALSE;
10760 	    }
10761 	    break;
10762 	}
10763     }
10764 
10765     /* Add the alternate score to su_sga. */
10766     for (i = 0; i < su->su_sga.ga_len; ++i)
10767     {
10768 	stp = &SUG(su->su_sga, i);
10769 	stp->st_altscore = spell_edit_score(su->su_badword, stp->st_word);
10770 	if (stp->st_score == SCORE_MAXMAX)
10771 	    stp->st_score = (SCORE_BIG * 7 + stp->st_altscore) / 8;
10772 	else
10773 	    stp->st_score = (stp->st_score * 7 + stp->st_altscore) / 8;
10774 	stp->st_salscore = TRUE;
10775     }
10776 
10777     /* Sort the suggestions and truncate at "maxcount" for both lists. */
10778     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10779     (void)cleanup_suggestions(&su->su_sga, su->su_maxscore, su->su_maxcount);
10780 
10781     ga_init2(&ga, (int)sizeof(suginfo_T), 1);
10782     if (ga_grow(&ga, su->su_ga.ga_len + su->su_sga.ga_len) == FAIL)
10783 	return;
10784 
10785     stp = &SUG(ga, 0);
10786     for (i = 0; i < su->su_ga.ga_len || i < su->su_sga.ga_len; ++i)
10787     {
10788 	/* round 1: get a suggestion from su_ga
10789 	 * round 2: get a suggestion from su_sga */
10790 	for (round = 1; round <= 2; ++round)
10791 	{
10792 	    gap = round == 1 ? &su->su_ga : &su->su_sga;
10793 	    if (i < gap->ga_len)
10794 	    {
10795 		/* Don't add a word if it's already there. */
10796 		p = SUG(*gap, i).st_word;
10797 		for (j = 0; j < ga.ga_len; ++j)
10798 		    if (STRCMP(stp[j].st_word, p) == 0)
10799 			break;
10800 		if (j == ga.ga_len)
10801 		    stp[ga.ga_len++] = SUG(*gap, i);
10802 		else
10803 		    vim_free(p);
10804 	    }
10805 	}
10806     }
10807 
10808     ga_clear(&su->su_ga);
10809     ga_clear(&su->su_sga);
10810 
10811     /* Truncate the list to the number of suggestions that will be displayed. */
10812     if (ga.ga_len > su->su_maxcount)
10813     {
10814 	for (i = su->su_maxcount; i < ga.ga_len; ++i)
10815 	    vim_free(stp[i].st_word);
10816 	ga.ga_len = su->su_maxcount;
10817     }
10818 
10819     su->su_ga = ga;
10820 }
10821 
10822 /*
10823  * For the goodword in "stp" compute the soundalike score compared to the
10824  * badword.
10825  */
10826     static int
10827 stp_sal_score(stp, su, slang, badsound)
10828     suggest_T	*stp;
10829     suginfo_T	*su;
10830     slang_T	*slang;
10831     char_u	*badsound;	/* sound-folded badword */
10832 {
10833     char_u	*p;
10834     char_u	*pbad;
10835     char_u	*pgood;
10836     char_u	badsound2[MAXWLEN];
10837     char_u	fword[MAXWLEN];
10838     char_u	goodsound[MAXWLEN];
10839     char_u	goodword[MAXWLEN];
10840     int		lendiff;
10841 
10842     lendiff = (int)(su->su_badlen - stp->st_orglen);
10843     if (lendiff >= 0)
10844 	pbad = badsound;
10845     else
10846     {
10847 	/* soundfold the bad word with more characters following */
10848 	(void)spell_casefold(su->su_badptr, stp->st_orglen, fword, MAXWLEN);
10849 
10850 	/* When joining two words the sound often changes a lot.  E.g., "t he"
10851 	 * sounds like "t h" while "the" sounds like "@".  Avoid that by
10852 	 * removing the space.  Don't do it when the good word also contains a
10853 	 * space. */
10854 	if (vim_iswhite(su->su_badptr[su->su_badlen])
10855 					 && *skiptowhite(stp->st_word) == NUL)
10856 	    for (p = fword; *(p = skiptowhite(p)) != NUL; )
10857 		mch_memmove(p, p + 1, STRLEN(p));
10858 
10859 	spell_soundfold(slang, fword, TRUE, badsound2);
10860 	pbad = badsound2;
10861     }
10862 
10863     if (lendiff > 0)
10864     {
10865 	/* Add part of the bad word to the good word, so that we soundfold
10866 	 * what replaces the bad word. */
10867 	STRCPY(goodword, stp->st_word);
10868 	STRNCAT(goodword, su->su_badptr + su->su_badlen - lendiff, lendiff);
10869 	pgood = goodword;
10870     }
10871     else
10872 	pgood = stp->st_word;
10873 
10874     /* Sound-fold the word and compute the score for the difference. */
10875     spell_soundfold(slang, pgood, FALSE, goodsound);
10876 
10877     return soundalike_score(goodsound, pbad);
10878 }
10879 
10880 /*
10881  * Find suggestions by comparing the word in a sound-a-like form.
10882  * Note: This doesn't support postponed prefixes.
10883  */
10884     static void
10885 suggest_try_soundalike(su)
10886     suginfo_T	*su;
10887 {
10888     char_u	salword[MAXWLEN];
10889     char_u	tword[MAXWLEN];
10890     char_u	tsalword[MAXWLEN];
10891     idx_T	arridx[MAXWLEN];
10892     int		curi[MAXWLEN];
10893     langp_T	*lp;
10894     char_u	*byts;
10895     idx_T	*idxs;
10896     int		depth;
10897     int		c;
10898     idx_T	n;
10899     int		round;
10900     int		flags;
10901     int		sound_score;
10902     int		local_score;
10903     int		lpi;
10904     slang_T	*slang;
10905 
10906     /* Do this for all languages that support sound folding. */
10907     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
10908     {
10909 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
10910 	slang = lp->lp_slang;
10911 	if (slang->sl_sal.ga_len > 0)
10912 	{
10913 	    /* soundfold the bad word */
10914 	    spell_soundfold(slang, su->su_fbadword, TRUE, salword);
10915 
10916 	    /*
10917 	     * Go through the whole tree, soundfold each word and compare.
10918 	     * round 1: use the case-folded tree.
10919 	     * round 2: use the keep-case tree.
10920 	     */
10921 	    for (round = 1; round <= 2; ++round)
10922 	    {
10923 		if (round == 1)
10924 		{
10925 		    byts = slang->sl_fbyts;
10926 		    idxs = slang->sl_fidxs;
10927 		}
10928 		else
10929 		{
10930 		    byts = slang->sl_kbyts;
10931 		    idxs = slang->sl_kidxs;
10932 		    if (byts == NULL)	    /* no keep-case words */
10933 			continue;
10934 		}
10935 
10936 		depth = 0;
10937 		arridx[0] = 0;
10938 		curi[0] = 1;
10939 		while (depth >= 0 && !got_int)
10940 		{
10941 		    if (curi[depth] > byts[arridx[depth]])
10942 		    {
10943 			/* Done all bytes at this node, go up one level. */
10944 			--depth;
10945 			line_breakcheck();
10946 		    }
10947 		    else
10948 		    {
10949 			/* Do one more byte at this node. */
10950 			n = arridx[depth] + curi[depth];
10951 			++curi[depth];
10952 			c = byts[n];
10953 			if (c == 0)
10954 			{
10955 			    /* End of word, deal with the word. */
10956 			    flags = (int)idxs[n];
10957 			    if (round == 2 || (flags & WF_KEEPCAP) == 0)
10958 			    {
10959 				tword[depth] = NUL;
10960 				/* Sound-fold.  Only in keep-case tree need to
10961 				 * case-fold the word. */
10962 				spell_soundfold(slang, tword,
10963 							round == 1, tsalword);
10964 
10965 				/* Compute the edit distance between the
10966 				 * sound-a-like words. */
10967 				sound_score = soundalike_score(salword,
10968 								    tsalword);
10969 
10970 				/* Add a penalty for words in another region. */
10971 				if ((flags & WF_REGION) && (((unsigned)flags
10972 						 >> 16) & lp->lp_region) == 0)
10973 				    local_score = SCORE_REGION;
10974 				else
10975 				    local_score = 0;
10976 				sound_score += local_score;
10977 
10978 				if (sound_score < SCORE_MAXMAX)
10979 				{
10980 				    char_u	cword[MAXWLEN];
10981 				    char_u	*p;
10982 				    int		score;
10983 
10984 				    flags |= su->su_badflags;
10985 				    if (round == 1 && (flags & WF_CAPMASK) != 0)
10986 				    {
10987 					/* Need to fix case according to
10988 					 * "flags". */
10989 					make_case_word(tword, cword, flags);
10990 					p = cword;
10991 				    }
10992 				    else
10993 					p = tword;
10994 
10995 				    if (sps_flags & SPS_DOUBLE)
10996 					add_suggestion(su, &su->su_sga, p,
10997 						su->su_badlen,
10998 						sound_score, 0, FALSE,
10999 						lp->lp_sallang);
11000 				    else
11001 				    {
11002 					/* Compute the score. */
11003 					score = spell_edit_score(
11004 							   su->su_badword, p)
11005 						    + local_score;
11006 					if (sps_flags & SPS_BEST)
11007 					    /* give a bonus for the good word
11008 					     * sounding the same as the bad
11009 					     * word */
11010 					    add_suggestion(su, &su->su_ga, p,
11011 						    su->su_badlen,
11012 						  RESCORE(score, sound_score),
11013 						    sound_score, TRUE,
11014 						    lp->lp_sallang);
11015 					else
11016 					    add_suggestion(su, &su->su_ga, p,
11017 						    su->su_badlen,
11018 						    score + sound_score,
11019 						    0, FALSE,
11020 						    lp->lp_sallang);
11021 				    }
11022 				}
11023 			    }
11024 
11025 			    /* Skip over other NUL bytes. */
11026 			    while (byts[n + 1] == 0)
11027 			    {
11028 				++n;
11029 				++curi[depth];
11030 			    }
11031 			}
11032 			else
11033 			{
11034 			    /* Normal char, go one level deeper. */
11035 			    tword[depth++] = c;
11036 			    arridx[depth] = idxs[n];
11037 			    curi[depth] = 1;
11038 			}
11039 		    }
11040 		}
11041 	    }
11042 	}
11043     }
11044 }
11045 
11046 /*
11047  * Copy "fword" to "cword", fixing case according to "flags".
11048  */
11049     static void
11050 make_case_word(fword, cword, flags)
11051     char_u	*fword;
11052     char_u	*cword;
11053     int		flags;
11054 {
11055     if (flags & WF_ALLCAP)
11056 	/* Make it all upper-case */
11057 	allcap_copy(fword, cword);
11058     else if (flags & WF_ONECAP)
11059 	/* Make the first letter upper-case */
11060 	onecap_copy(fword, cword, TRUE);
11061     else
11062 	/* Use goodword as-is. */
11063 	STRCPY(cword, fword);
11064 }
11065 
11066 /*
11067  * Use map string "map" for languages "lp".
11068  */
11069     static void
11070 set_map_str(lp, map)
11071     slang_T	*lp;
11072     char_u	*map;
11073 {
11074     char_u	*p;
11075     int		headc = 0;
11076     int		c;
11077     int		i;
11078 
11079     if (*map == NUL)
11080     {
11081 	lp->sl_has_map = FALSE;
11082 	return;
11083     }
11084     lp->sl_has_map = TRUE;
11085 
11086     /* Init the array and hash table empty. */
11087     for (i = 0; i < 256; ++i)
11088 	lp->sl_map_array[i] = 0;
11089 #ifdef FEAT_MBYTE
11090     hash_init(&lp->sl_map_hash);
11091 #endif
11092 
11093     /*
11094      * The similar characters are stored separated with slashes:
11095      * "aaa/bbb/ccc/".  Fill sl_map_array[c] with the character before c and
11096      * before the same slash.  For characters above 255 sl_map_hash is used.
11097      */
11098     for (p = map; *p != NUL; )
11099     {
11100 #ifdef FEAT_MBYTE
11101 	c = mb_cptr2char_adv(&p);
11102 #else
11103 	c = *p++;
11104 #endif
11105 	if (c == '/')
11106 	    headc = 0;
11107 	else
11108 	{
11109 	    if (headc == 0)
11110 		 headc = c;
11111 
11112 #ifdef FEAT_MBYTE
11113 	    /* Characters above 255 don't fit in sl_map_array[], put them in
11114 	     * the hash table.  Each entry is the char, a NUL the headchar and
11115 	     * a NUL. */
11116 	    if (c >= 256)
11117 	    {
11118 		int	    cl = mb_char2len(c);
11119 		int	    headcl = mb_char2len(headc);
11120 		char_u	    *b;
11121 		hash_T	    hash;
11122 		hashitem_T  *hi;
11123 
11124 		b = alloc((unsigned)(cl + headcl + 2));
11125 		if (b == NULL)
11126 		    return;
11127 		mb_char2bytes(c, b);
11128 		b[cl] = NUL;
11129 		mb_char2bytes(headc, b + cl + 1);
11130 		b[cl + 1 + headcl] = NUL;
11131 		hash = hash_hash(b);
11132 		hi = hash_lookup(&lp->sl_map_hash, b, hash);
11133 		if (HASHITEM_EMPTY(hi))
11134 		    hash_add_item(&lp->sl_map_hash, hi, b, hash);
11135 		else
11136 		{
11137 		    /* This should have been checked when generating the .spl
11138 		     * file. */
11139 		    EMSG(_("E999: duplicate char in MAP entry"));
11140 		    vim_free(b);
11141 		}
11142 	    }
11143 	    else
11144 #endif
11145 		lp->sl_map_array[c] = headc;
11146 	}
11147     }
11148 }
11149 
11150 /*
11151  * Return TRUE if "c1" and "c2" are similar characters according to the MAP
11152  * lines in the .aff file.
11153  */
11154     static int
11155 similar_chars(slang, c1, c2)
11156     slang_T	*slang;
11157     int		c1;
11158     int		c2;
11159 {
11160     int		m1, m2;
11161 #ifdef FEAT_MBYTE
11162     char_u	buf[MB_MAXBYTES];
11163     hashitem_T  *hi;
11164 
11165     if (c1 >= 256)
11166     {
11167 	buf[mb_char2bytes(c1, buf)] = 0;
11168 	hi = hash_find(&slang->sl_map_hash, buf);
11169 	if (HASHITEM_EMPTY(hi))
11170 	    m1 = 0;
11171 	else
11172 	    m1 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
11173     }
11174     else
11175 #endif
11176 	m1 = slang->sl_map_array[c1];
11177     if (m1 == 0)
11178 	return FALSE;
11179 
11180 
11181 #ifdef FEAT_MBYTE
11182     if (c2 >= 256)
11183     {
11184 	buf[mb_char2bytes(c2, buf)] = 0;
11185 	hi = hash_find(&slang->sl_map_hash, buf);
11186 	if (HASHITEM_EMPTY(hi))
11187 	    m2 = 0;
11188 	else
11189 	    m2 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
11190     }
11191     else
11192 #endif
11193 	m2 = slang->sl_map_array[c2];
11194 
11195     return m1 == m2;
11196 }
11197 
11198 /*
11199  * Add a suggestion to the list of suggestions.
11200  * Do not add a duplicate suggestion or suggestions with a bad score.
11201  * When "use_score" is not zero it's used, otherwise the score is computed
11202  * with spell_edit_score().
11203  */
11204     static void
11205 add_suggestion(su, gap, goodword, badlenarg, score, altscore, had_bonus, slang)
11206     suginfo_T	*su;
11207     garray_T	*gap;
11208     char_u	*goodword;
11209     int		badlenarg;	/* len of bad word replaced with "goodword" */
11210     int		score;
11211     int		altscore;
11212     int		had_bonus;	/* value for st_had_bonus */
11213     slang_T	*slang;		/* language for sound folding */
11214 {
11215     int		goodlen = STRLEN(goodword); /* len of goodword changed */
11216     int		badlen = badlenarg;	    /* len of bad word changed */
11217     suggest_T   *stp;
11218     suggest_T   new_sug;
11219     int		i;
11220     hlf_T	attr = HLF_COUNT;
11221     char_u	longword[MAXWLEN + 1];
11222     char_u	*pgood, *pbad;
11223 
11224     /* Check that the word really is valid.  Esp. for banned words and for
11225      * split words, such as "the the".  Need to append what follows to check
11226      * for that. */
11227     STRCPY(longword, goodword);
11228     vim_strncpy(longword + goodlen, su->su_badptr + badlen, MAXWLEN - goodlen);
11229     (void)spell_check(curwin, longword, &attr, NULL);
11230     if (attr != HLF_COUNT)
11231 	return;
11232 
11233     /* Minimize "badlen" for consistency.  Avoids that changing "the the" to
11234      * "thee the" is added next to changing the first "the" the "thee".  */
11235     pgood = goodword + STRLEN(goodword);
11236     pbad = su->su_badptr + badlen;
11237     while (pgood > goodword && pbad > su->su_badptr)
11238     {
11239 	mb_ptr_back(goodword, pgood);
11240 	mb_ptr_back(su->su_badptr, pbad);
11241 #ifdef FEAT_MBYTE
11242 	if (has_mbyte)
11243 	{
11244 	    if (mb_ptr2char(pgood) != mb_ptr2char(pbad))
11245 		break;
11246 	}
11247 	else
11248 #endif
11249 	    if (*pgood != *pbad)
11250 		break;
11251 	badlen = pbad - su->su_badptr;
11252 	goodlen = pgood - goodword;
11253     }
11254     if (badlen == 0 && goodlen == 0)
11255 	/* goodword doesn't change anything; may happen for "the the" changing
11256 	 * the first "the" to itself. */
11257 	return;
11258 
11259     if (score <= su->su_maxscore)
11260     {
11261 	/* Check if the word is already there.  Also check the length that is
11262 	 * being replaced "thes," -> "these" is a different suggestion from
11263 	 * "thes" -> "these". */
11264 	stp = &SUG(*gap, 0);
11265 	for (i = gap->ga_len - 1; i >= 0; --i)
11266 	    if ((int)STRLEN(stp[i].st_word) == goodlen
11267 			&& STRNCMP(stp[i].st_word, goodword, goodlen) == 0
11268 						&& stp[i].st_orglen == badlen)
11269 	    {
11270 		/*
11271 		 * Found it.  Remember the word with the lowest score.
11272 		 */
11273 		if (stp[i].st_slang == NULL)
11274 		    stp[i].st_slang = slang;
11275 
11276 		new_sug.st_score = score;
11277 		new_sug.st_altscore = altscore;
11278 		new_sug.st_had_bonus = had_bonus;
11279 
11280 		if (stp[i].st_had_bonus != had_bonus)
11281 		{
11282 		    /* Only one of the two had the soundalike score computed.
11283 		     * Need to do that for the other one now, otherwise the
11284 		     * scores can't be compared.  This happens because
11285 		     * suggest_try_change() doesn't compute the soundalike
11286 		     * word to keep it fast, while some special methods set
11287 		     * the soundalike score to zero. */
11288 		    if (had_bonus)
11289 			rescore_one(su, &stp[i]);
11290 		    else
11291 		    {
11292 			new_sug.st_word = goodword;
11293 			new_sug.st_slang = stp[i].st_slang;
11294 			new_sug.st_orglen = badlen;
11295 			rescore_one(su, &new_sug);
11296 		    }
11297 		}
11298 
11299 		if (stp[i].st_score > new_sug.st_score)
11300 		{
11301 		    stp[i].st_score = new_sug.st_score;
11302 		    stp[i].st_altscore = new_sug.st_altscore;
11303 		    stp[i].st_had_bonus = new_sug.st_had_bonus;
11304 		}
11305 		break;
11306 	    }
11307 
11308 	if (i < 0 && ga_grow(gap, 1) == OK)
11309 	{
11310 	    /* Add a suggestion. */
11311 	    stp = &SUG(*gap, gap->ga_len);
11312 	    stp->st_word = vim_strnsave(goodword, goodlen);
11313 	    if (stp->st_word != NULL)
11314 	    {
11315 		stp->st_score = score;
11316 		stp->st_altscore = altscore;
11317 		stp->st_had_bonus = had_bonus;
11318 		stp->st_orglen = badlen;
11319 		stp->st_slang = slang;
11320 		++gap->ga_len;
11321 
11322 		/* If we have too many suggestions now, sort the list and keep
11323 		 * the best suggestions. */
11324 		if (gap->ga_len > SUG_MAX_COUNT(su))
11325 		    su->su_maxscore = cleanup_suggestions(gap, su->su_maxscore,
11326 							 SUG_CLEAN_COUNT(su));
11327 	    }
11328 	}
11329     }
11330 }
11331 
11332 /*
11333  * Add a word to be banned.
11334  */
11335     static void
11336 add_banned(su, word)
11337     suginfo_T	*su;
11338     char_u	*word;
11339 {
11340     char_u	*s = vim_strsave(word);
11341     hash_T	hash;
11342     hashitem_T	*hi;
11343 
11344     if (s != NULL)
11345     {
11346 	hash = hash_hash(s);
11347 	hi = hash_lookup(&su->su_banned, s, hash);
11348 	if (HASHITEM_EMPTY(hi))
11349 	    hash_add_item(&su->su_banned, hi, s, hash);
11350 	else
11351 	    vim_free(s);
11352     }
11353 }
11354 
11355 /*
11356  * Return TRUE if a word appears in the list of banned words.
11357  */
11358     static int
11359 was_banned(su, word)
11360     suginfo_T	*su;
11361     char_u	*word;
11362 {
11363     hashitem_T	*hi = hash_find(&su->su_banned, word);
11364 
11365     return !HASHITEM_EMPTY(hi);
11366 }
11367 
11368 /*
11369  * Free the banned words in "su".
11370  */
11371     static void
11372 free_banned(su)
11373     suginfo_T	*su;
11374 {
11375     int		todo;
11376     hashitem_T	*hi;
11377 
11378     todo = su->su_banned.ht_used;
11379     for (hi = su->su_banned.ht_array; todo > 0; ++hi)
11380     {
11381 	if (!HASHITEM_EMPTY(hi))
11382 	{
11383 	    vim_free(hi->hi_key);
11384 	    --todo;
11385 	}
11386     }
11387     hash_clear(&su->su_banned);
11388 }
11389 
11390 /*
11391  * Recompute the score for all suggestions if sound-folding is possible.  This
11392  * is slow, thus only done for the final results.
11393  */
11394     static void
11395 rescore_suggestions(su)
11396     suginfo_T	*su;
11397 {
11398     int		i;
11399 
11400     if (su->su_sallang != NULL)
11401 	for (i = 0; i < su->su_ga.ga_len; ++i)
11402 	    rescore_one(su, &SUG(su->su_ga, i));
11403 }
11404 
11405 /*
11406  * Recompute the score for one suggestion if sound-folding is possible.
11407  */
11408     static void
11409 rescore_one(su, stp)
11410     suginfo_T	*su;
11411     suggest_T	*stp;
11412 {
11413     slang_T	*slang = stp->st_slang;
11414     char_u	sal_badword[MAXWLEN];
11415     char_u	*p;
11416 
11417     /* Only rescore suggestions that have no sal score yet and do have a
11418      * language. */
11419     if (slang != NULL && slang->sl_sal.ga_len > 0 && !stp->st_had_bonus)
11420     {
11421 	if (slang == su->su_sallang)
11422 	    p = su->su_sal_badword;
11423 	else
11424 	{
11425 	    spell_soundfold(slang, su->su_fbadword, TRUE, sal_badword);
11426 	    p = sal_badword;
11427 	}
11428 
11429 	stp->st_altscore = stp_sal_score(stp, su, slang, p);
11430 	if (stp->st_altscore == SCORE_MAXMAX)
11431 	    stp->st_altscore = SCORE_BIG;
11432 	stp->st_score = RESCORE(stp->st_score, stp->st_altscore);
11433 	stp->st_had_bonus = TRUE;
11434     }
11435 }
11436 
11437 static int
11438 #ifdef __BORLANDC__
11439 _RTLENTRYF
11440 #endif
11441 sug_compare __ARGS((const void *s1, const void *s2));
11442 
11443 /*
11444  * Function given to qsort() to sort the suggestions on st_score.
11445  * First on "st_score", then "st_altscore" then alphabetically.
11446  */
11447     static int
11448 #ifdef __BORLANDC__
11449 _RTLENTRYF
11450 #endif
11451 sug_compare(s1, s2)
11452     const void	*s1;
11453     const void	*s2;
11454 {
11455     suggest_T	*p1 = (suggest_T *)s1;
11456     suggest_T	*p2 = (suggest_T *)s2;
11457     int		n = p1->st_score - p2->st_score;
11458 
11459     if (n == 0)
11460     {
11461 	n = p1->st_altscore - p2->st_altscore;
11462 	if (n == 0)
11463 	    n = STRICMP(p1->st_word, p2->st_word);
11464     }
11465     return n;
11466 }
11467 
11468 /*
11469  * Cleanup the suggestions:
11470  * - Sort on score.
11471  * - Remove words that won't be displayed.
11472  * Returns the maximum score in the list or "maxscore" unmodified.
11473  */
11474     static int
11475 cleanup_suggestions(gap, maxscore, keep)
11476     garray_T	*gap;
11477     int		maxscore;
11478     int		keep;		/* nr of suggestions to keep */
11479 {
11480     suggest_T   *stp = &SUG(*gap, 0);
11481     int		i;
11482 
11483     /* Sort the list. */
11484     qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
11485 
11486     /* Truncate the list to the number of suggestions that will be displayed. */
11487     if (gap->ga_len > keep)
11488     {
11489 	for (i = keep; i < gap->ga_len; ++i)
11490 	    vim_free(stp[i].st_word);
11491 	gap->ga_len = keep;
11492 	return stp[keep - 1].st_score;
11493     }
11494     return maxscore;
11495 }
11496 
11497 #if defined(FEAT_EVAL) || defined(PROTO)
11498 /*
11499  * Soundfold a string, for soundfold().
11500  * Result is in allocated memory, NULL for an error.
11501  */
11502     char_u *
11503 eval_soundfold(word)
11504     char_u	*word;
11505 {
11506     langp_T	*lp;
11507     char_u	sound[MAXWLEN];
11508     int		lpi;
11509 
11510     if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
11511 	/* Use the sound-folding of the first language that supports it. */
11512 	for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
11513 	{
11514 	    lp = LANGP_ENTRY(curbuf->b_langp, lpi);
11515 	    if (lp->lp_slang->sl_sal.ga_len > 0)
11516 	    {
11517 		/* soundfold the word */
11518 		spell_soundfold(lp->lp_slang, word, FALSE, sound);
11519 		return vim_strsave(sound);
11520 	    }
11521 	}
11522 
11523     /* No language with sound folding, return word as-is. */
11524     return vim_strsave(word);
11525 }
11526 #endif
11527 
11528 /*
11529  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
11530  *
11531  * There are many ways to turn a word into a sound-a-like representation.  The
11532  * oldest is Soundex (1918!).   A nice overview can be found in "Approximate
11533  * swedish name matching - survey and test of different algorithms" by Klas
11534  * Erikson.
11535  *
11536  * We support two methods:
11537  * 1. SOFOFROM/SOFOTO do a simple character mapping.
11538  * 2. SAL items define a more advanced sound-folding (and much slower).
11539  */
11540     static void
11541 spell_soundfold(slang, inword, folded, res)
11542     slang_T	*slang;
11543     char_u	*inword;
11544     int		folded;	    /* "inword" is already case-folded */
11545     char_u	*res;
11546 {
11547     char_u	fword[MAXWLEN];
11548     char_u	*word;
11549 
11550     if (slang->sl_sofo)
11551 	/* SOFOFROM and SOFOTO used */
11552 	spell_soundfold_sofo(slang, inword, res);
11553     else
11554     {
11555 	/* SAL items used.  Requires the word to be case-folded. */
11556 	if (folded)
11557 	    word = inword;
11558 	else
11559 	{
11560 	    (void)spell_casefold(inword, STRLEN(inword), fword, MAXWLEN);
11561 	    word = fword;
11562 	}
11563 
11564 #ifdef FEAT_MBYTE
11565 	if (has_mbyte)
11566 	    spell_soundfold_wsal(slang, word, res);
11567 	else
11568 #endif
11569 	    spell_soundfold_sal(slang, word, res);
11570     }
11571 }
11572 
11573 /*
11574  * Perform sound folding of "inword" into "res" according to SOFOFROM and
11575  * SOFOTO lines.
11576  */
11577     static void
11578 spell_soundfold_sofo(slang, inword, res)
11579     slang_T	*slang;
11580     char_u	*inword;
11581     char_u	*res;
11582 {
11583     char_u	*s;
11584     int		ri = 0;
11585     int		c;
11586 
11587 #ifdef FEAT_MBYTE
11588     if (has_mbyte)
11589     {
11590 	int	prevc = 0;
11591 	int	*ip;
11592 
11593 	/* The sl_sal_first[] table contains the translation for chars up to
11594 	 * 255, sl_sal the rest. */
11595 	for (s = inword; *s != NUL; )
11596 	{
11597 	    c = mb_cptr2char_adv(&s);
11598 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
11599 		c = ' ';
11600 	    else if (c < 256)
11601 		c = slang->sl_sal_first[c];
11602 	    else
11603 	    {
11604 		ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
11605 		if (ip == NULL)		/* empty list, can't match */
11606 		    c = NUL;
11607 		else
11608 		    for (;;)		/* find "c" in the list */
11609 		    {
11610 			if (*ip == 0)	/* not found */
11611 			{
11612 			    c = NUL;
11613 			    break;
11614 			}
11615 			if (*ip == c)	/* match! */
11616 			{
11617 			    c = ip[1];
11618 			    break;
11619 			}
11620 			ip += 2;
11621 		    }
11622 	    }
11623 
11624 	    if (c != NUL && c != prevc)
11625 	    {
11626 		ri += mb_char2bytes(c, res + ri);
11627 		if (ri + MB_MAXBYTES > MAXWLEN)
11628 		    break;
11629 		prevc = c;
11630 	    }
11631 	}
11632     }
11633     else
11634 #endif
11635     {
11636 	/* The sl_sal_first[] table contains the translation. */
11637 	for (s = inword; (c = *s) != NUL; ++s)
11638 	{
11639 	    if (vim_iswhite(c))
11640 		c = ' ';
11641 	    else
11642 		c = slang->sl_sal_first[c];
11643 	    if (c != NUL && (ri == 0 || res[ri - 1] != c))
11644 		res[ri++] = c;
11645 	}
11646     }
11647 
11648     res[ri] = NUL;
11649 }
11650 
11651     static void
11652 spell_soundfold_sal(slang, inword, res)
11653     slang_T	*slang;
11654     char_u	*inword;
11655     char_u	*res;
11656 {
11657     salitem_T	*smp;
11658     char_u	word[MAXWLEN];
11659     char_u	*s = inword;
11660     char_u	*t;
11661     char_u	*pf;
11662     int		i, j, z;
11663     int		reslen;
11664     int		n, k = 0;
11665     int		z0;
11666     int		k0;
11667     int		n0;
11668     int		c;
11669     int		pri;
11670     int		p0 = -333;
11671     int		c0;
11672 
11673     /* Remove accents, if wanted.  We actually remove all non-word characters.
11674      * But keep white space.  We need a copy, the word may be changed here. */
11675     if (slang->sl_rem_accents)
11676     {
11677 	t = word;
11678 	while (*s != NUL)
11679 	{
11680 	    if (vim_iswhite(*s))
11681 	    {
11682 		*t++ = ' ';
11683 		s = skipwhite(s);
11684 	    }
11685 	    else
11686 	    {
11687 		if (spell_iswordp_nmw(s))
11688 		    *t++ = *s;
11689 		++s;
11690 	    }
11691 	}
11692 	*t = NUL;
11693     }
11694     else
11695 	STRCPY(word, s);
11696 
11697     smp = (salitem_T *)slang->sl_sal.ga_data;
11698 
11699     /*
11700      * This comes from Aspell phonet.cpp.  Converted from C++ to C.
11701      * Changed to keep spaces.
11702      */
11703     i = reslen = z = 0;
11704     while ((c = word[i]) != NUL)
11705     {
11706 	/* Start with the first rule that has the character in the word. */
11707 	n = slang->sl_sal_first[c];
11708 	z0 = 0;
11709 
11710 	if (n >= 0)
11711 	{
11712 	    /* check all rules for the same letter */
11713 	    for (; (s = smp[n].sm_lead)[0] == c; ++n)
11714 	    {
11715 		/* Quickly skip entries that don't match the word.  Most
11716 		 * entries are less then three chars, optimize for that. */
11717 		k = smp[n].sm_leadlen;
11718 		if (k > 1)
11719 		{
11720 		    if (word[i + 1] != s[1])
11721 			continue;
11722 		    if (k > 2)
11723 		    {
11724 			for (j = 2; j < k; ++j)
11725 			    if (word[i + j] != s[j])
11726 				break;
11727 			if (j < k)
11728 			    continue;
11729 		    }
11730 		}
11731 
11732 		if ((pf = smp[n].sm_oneof) != NULL)
11733 		{
11734 		    /* Check for match with one of the chars in "sm_oneof". */
11735 		    while (*pf != NUL && *pf != word[i + k])
11736 			++pf;
11737 		    if (*pf == NUL)
11738 			continue;
11739 		    ++k;
11740 		}
11741 		s = smp[n].sm_rules;
11742 		pri = 5;    /* default priority */
11743 
11744 		p0 = *s;
11745 		k0 = k;
11746 		while (*s == '-' && k > 1)
11747 		{
11748 		    k--;
11749 		    s++;
11750 		}
11751 		if (*s == '<')
11752 		    s++;
11753 		if (VIM_ISDIGIT(*s))
11754 		{
11755 		    /* determine priority */
11756 		    pri = *s - '0';
11757 		    s++;
11758 		}
11759 		if (*s == '^' && *(s + 1) == '^')
11760 		    s++;
11761 
11762 		if (*s == NUL
11763 			|| (*s == '^'
11764 			    && (i == 0 || !(word[i - 1] == ' '
11765 				      || spell_iswordp(word + i - 1, curbuf)))
11766 			    && (*(s + 1) != '$'
11767 				|| (!spell_iswordp(word + i + k0, curbuf))))
11768 			|| (*s == '$' && i > 0
11769 			    && spell_iswordp(word + i - 1, curbuf)
11770 			    && (!spell_iswordp(word + i + k0, curbuf))))
11771 		{
11772 		    /* search for followup rules, if:    */
11773 		    /* followup and k > 1  and  NO '-' in searchstring */
11774 		    c0 = word[i + k - 1];
11775 		    n0 = slang->sl_sal_first[c0];
11776 
11777 		    if (slang->sl_followup && k > 1 && n0 >= 0
11778 					   && p0 != '-' && word[i + k] != NUL)
11779 		    {
11780 			/* test follow-up rule for "word[i + k]" */
11781 			for ( ; (s = smp[n0].sm_lead)[0] == c0; ++n0)
11782 			{
11783 			    /* Quickly skip entries that don't match the word.
11784 			     * */
11785 			    k0 = smp[n0].sm_leadlen;
11786 			    if (k0 > 1)
11787 			    {
11788 				if (word[i + k] != s[1])
11789 				    continue;
11790 				if (k0 > 2)
11791 				{
11792 				    pf = word + i + k + 1;
11793 				    for (j = 2; j < k0; ++j)
11794 					if (*pf++ != s[j])
11795 					    break;
11796 				    if (j < k0)
11797 					continue;
11798 				}
11799 			    }
11800 			    k0 += k - 1;
11801 
11802 			    if ((pf = smp[n0].sm_oneof) != NULL)
11803 			    {
11804 				/* Check for match with one of the chars in
11805 				 * "sm_oneof". */
11806 				while (*pf != NUL && *pf != word[i + k0])
11807 				    ++pf;
11808 				if (*pf == NUL)
11809 				    continue;
11810 				++k0;
11811 			    }
11812 
11813 			    p0 = 5;
11814 			    s = smp[n0].sm_rules;
11815 			    while (*s == '-')
11816 			    {
11817 				/* "k0" gets NOT reduced because
11818 				 * "if (k0 == k)" */
11819 				s++;
11820 			    }
11821 			    if (*s == '<')
11822 				s++;
11823 			    if (VIM_ISDIGIT(*s))
11824 			    {
11825 				p0 = *s - '0';
11826 				s++;
11827 			    }
11828 
11829 			    if (*s == NUL
11830 				    /* *s == '^' cuts */
11831 				    || (*s == '$'
11832 					    && !spell_iswordp(word + i + k0,
11833 								     curbuf)))
11834 			    {
11835 				if (k0 == k)
11836 				    /* this is just a piece of the string */
11837 				    continue;
11838 
11839 				if (p0 < pri)
11840 				    /* priority too low */
11841 				    continue;
11842 				/* rule fits; stop search */
11843 				break;
11844 			    }
11845 			}
11846 
11847 			if (p0 >= pri && smp[n0].sm_lead[0] == c0)
11848 			    continue;
11849 		    }
11850 
11851 		    /* replace string */
11852 		    s = smp[n].sm_to;
11853 		    if (s == NULL)
11854 			s = (char_u *)"";
11855 		    pf = smp[n].sm_rules;
11856 		    p0 = (vim_strchr(pf, '<') != NULL) ? 1 : 0;
11857 		    if (p0 == 1 && z == 0)
11858 		    {
11859 			/* rule with '<' is used */
11860 			if (reslen > 0 && *s != NUL && (res[reslen - 1] == c
11861 						    || res[reslen - 1] == *s))
11862 			    reslen--;
11863 			z0 = 1;
11864 			z = 1;
11865 			k0 = 0;
11866 			while (*s != NUL && word[i + k0] != NUL)
11867 			{
11868 			    word[i + k0] = *s;
11869 			    k0++;
11870 			    s++;
11871 			}
11872 			if (k > k0)
11873 			    mch_memmove(word + i + k0, word + i + k,
11874 						    STRLEN(word + i + k) + 1);
11875 
11876 			/* new "actual letter" */
11877 			c = word[i];
11878 		    }
11879 		    else
11880 		    {
11881 			/* no '<' rule used */
11882 			i += k - 1;
11883 			z = 0;
11884 			while (*s != NUL && s[1] != NUL && reslen < MAXWLEN)
11885 			{
11886 			    if (reslen == 0 || res[reslen - 1] != *s)
11887 				res[reslen++] = *s;
11888 			    s++;
11889 			}
11890 			/* new "actual letter" */
11891 			c = *s;
11892 			if (strstr((char *)pf, "^^") != NULL)
11893 			{
11894 			    if (c != NUL)
11895 				res[reslen++] = c;
11896 			    mch_memmove(word, word + i + 1,
11897 						    STRLEN(word + i + 1) + 1);
11898 			    i = 0;
11899 			    z0 = 1;
11900 			}
11901 		    }
11902 		    break;
11903 		}
11904 	    }
11905 	}
11906 	else if (vim_iswhite(c))
11907 	{
11908 	    c = ' ';
11909 	    k = 1;
11910 	}
11911 
11912 	if (z0 == 0)
11913 	{
11914 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
11915 		    && (!slang->sl_collapse || reslen == 0
11916 						     || res[reslen - 1] != c))
11917 		/* condense only double letters */
11918 		res[reslen++] = c;
11919 
11920 	    i++;
11921 	    z = 0;
11922 	    k = 0;
11923 	}
11924     }
11925 
11926     res[reslen] = NUL;
11927 }
11928 
11929 #ifdef FEAT_MBYTE
11930 /*
11931  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
11932  * Multi-byte version of spell_soundfold().
11933  */
11934     static void
11935 spell_soundfold_wsal(slang, inword, res)
11936     slang_T	*slang;
11937     char_u	*inword;
11938     char_u	*res;
11939 {
11940     salitem_T	*smp = (salitem_T *)slang->sl_sal.ga_data;
11941     int		word[MAXWLEN];
11942     int		wres[MAXWLEN];
11943     int		l;
11944     char_u	*s;
11945     int		*ws;
11946     char_u	*t;
11947     int		*pf;
11948     int		i, j, z;
11949     int		reslen;
11950     int		n, k = 0;
11951     int		z0;
11952     int		k0;
11953     int		n0;
11954     int		c;
11955     int		pri;
11956     int		p0 = -333;
11957     int		c0;
11958     int		did_white = FALSE;
11959 
11960     /*
11961      * Convert the multi-byte string to a wide-character string.
11962      * Remove accents, if wanted.  We actually remove all non-word characters.
11963      * But keep white space.
11964      */
11965     n = 0;
11966     for (s = inword; *s != NUL; )
11967     {
11968 	t = s;
11969 	c = mb_cptr2char_adv(&s);
11970 	if (slang->sl_rem_accents)
11971 	{
11972 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
11973 	    {
11974 		if (did_white)
11975 		    continue;
11976 		c = ' ';
11977 		did_white = TRUE;
11978 	    }
11979 	    else
11980 	    {
11981 		did_white = FALSE;
11982 		if (!spell_iswordp_nmw(t))
11983 		    continue;
11984 	    }
11985 	}
11986 	word[n++] = c;
11987     }
11988     word[n] = NUL;
11989 
11990     /*
11991      * This comes from Aspell phonet.cpp.
11992      * Converted from C++ to C.  Added support for multi-byte chars.
11993      * Changed to keep spaces.
11994      */
11995     i = reslen = z = 0;
11996     while ((c = word[i]) != NUL)
11997     {
11998 	/* Start with the first rule that has the character in the word. */
11999 	n = slang->sl_sal_first[c & 0xff];
12000 	z0 = 0;
12001 
12002 	if (n >= 0)
12003 	{
12004 	    /* check all rules for the same index byte */
12005 	    for (; ((ws = smp[n].sm_lead_w)[0] & 0xff) == (c & 0xff); ++n)
12006 	    {
12007 		/* Quickly skip entries that don't match the word.  Most
12008 		 * entries are less then three chars, optimize for that. */
12009 		if (c != ws[0])
12010 		    continue;
12011 		k = smp[n].sm_leadlen;
12012 		if (k > 1)
12013 		{
12014 		    if (word[i + 1] != ws[1])
12015 			continue;
12016 		    if (k > 2)
12017 		    {
12018 			for (j = 2; j < k; ++j)
12019 			    if (word[i + j] != ws[j])
12020 				break;
12021 			if (j < k)
12022 			    continue;
12023 		    }
12024 		}
12025 
12026 		if ((pf = smp[n].sm_oneof_w) != NULL)
12027 		{
12028 		    /* Check for match with one of the chars in "sm_oneof". */
12029 		    while (*pf != NUL && *pf != word[i + k])
12030 			++pf;
12031 		    if (*pf == NUL)
12032 			continue;
12033 		    ++k;
12034 		}
12035 		s = smp[n].sm_rules;
12036 		pri = 5;    /* default priority */
12037 
12038 		p0 = *s;
12039 		k0 = k;
12040 		while (*s == '-' && k > 1)
12041 		{
12042 		    k--;
12043 		    s++;
12044 		}
12045 		if (*s == '<')
12046 		    s++;
12047 		if (VIM_ISDIGIT(*s))
12048 		{
12049 		    /* determine priority */
12050 		    pri = *s - '0';
12051 		    s++;
12052 		}
12053 		if (*s == '^' && *(s + 1) == '^')
12054 		    s++;
12055 
12056 		if (*s == NUL
12057 			|| (*s == '^'
12058 			    && (i == 0 || !(word[i - 1] == ' '
12059 				    || spell_iswordp_w(word + i - 1, curbuf)))
12060 			    && (*(s + 1) != '$'
12061 				|| (!spell_iswordp_w(word + i + k0, curbuf))))
12062 			|| (*s == '$' && i > 0
12063 			    && spell_iswordp_w(word + i - 1, curbuf)
12064 			    && (!spell_iswordp_w(word + i + k0, curbuf))))
12065 		{
12066 		    /* search for followup rules, if:    */
12067 		    /* followup and k > 1  and  NO '-' in searchstring */
12068 		    c0 = word[i + k - 1];
12069 		    n0 = slang->sl_sal_first[c0 & 0xff];
12070 
12071 		    if (slang->sl_followup && k > 1 && n0 >= 0
12072 					   && p0 != '-' && word[i + k] != NUL)
12073 		    {
12074 			/* Test follow-up rule for "word[i + k]"; loop over
12075 			 * all entries with the same index byte. */
12076 			for ( ; ((ws = smp[n0].sm_lead_w)[0] & 0xff)
12077 							 == (c0 & 0xff); ++n0)
12078 			{
12079 			    /* Quickly skip entries that don't match the word.
12080 			     */
12081 			    if (c0 != ws[0])
12082 				continue;
12083 			    k0 = smp[n0].sm_leadlen;
12084 			    if (k0 > 1)
12085 			    {
12086 				if (word[i + k] != ws[1])
12087 				    continue;
12088 				if (k0 > 2)
12089 				{
12090 				    pf = word + i + k + 1;
12091 				    for (j = 2; j < k0; ++j)
12092 					if (*pf++ != ws[j])
12093 					    break;
12094 				    if (j < k0)
12095 					continue;
12096 				}
12097 			    }
12098 			    k0 += k - 1;
12099 
12100 			    if ((pf = smp[n0].sm_oneof_w) != NULL)
12101 			    {
12102 				/* Check for match with one of the chars in
12103 				 * "sm_oneof". */
12104 				while (*pf != NUL && *pf != word[i + k0])
12105 				    ++pf;
12106 				if (*pf == NUL)
12107 				    continue;
12108 				++k0;
12109 			    }
12110 
12111 			    p0 = 5;
12112 			    s = smp[n0].sm_rules;
12113 			    while (*s == '-')
12114 			    {
12115 				/* "k0" gets NOT reduced because
12116 				 * "if (k0 == k)" */
12117 				s++;
12118 			    }
12119 			    if (*s == '<')
12120 				s++;
12121 			    if (VIM_ISDIGIT(*s))
12122 			    {
12123 				p0 = *s - '0';
12124 				s++;
12125 			    }
12126 
12127 			    if (*s == NUL
12128 				    /* *s == '^' cuts */
12129 				    || (*s == '$'
12130 					 && !spell_iswordp_w(word + i + k0,
12131 								     curbuf)))
12132 			    {
12133 				if (k0 == k)
12134 				    /* this is just a piece of the string */
12135 				    continue;
12136 
12137 				if (p0 < pri)
12138 				    /* priority too low */
12139 				    continue;
12140 				/* rule fits; stop search */
12141 				break;
12142 			    }
12143 			}
12144 
12145 			if (p0 >= pri && (smp[n0].sm_lead_w[0] & 0xff)
12146 							       == (c0 & 0xff))
12147 			    continue;
12148 		    }
12149 
12150 		    /* replace string */
12151 		    ws = smp[n].sm_to_w;
12152 		    s = smp[n].sm_rules;
12153 		    p0 = (vim_strchr(s, '<') != NULL) ? 1 : 0;
12154 		    if (p0 == 1 && z == 0)
12155 		    {
12156 			/* rule with '<' is used */
12157 			if (reslen > 0 && ws != NULL && *ws != NUL
12158 				&& (wres[reslen - 1] == c
12159 						    || wres[reslen - 1] == *ws))
12160 			    reslen--;
12161 			z0 = 1;
12162 			z = 1;
12163 			k0 = 0;
12164 			if (ws != NULL)
12165 			    while (*ws != NUL && word[i + k0] != NUL)
12166 			    {
12167 				word[i + k0] = *ws;
12168 				k0++;
12169 				ws++;
12170 			    }
12171 			if (k > k0)
12172 			    mch_memmove(word + i + k0, word + i + k,
12173 				    sizeof(int) * (STRLEN(word + i + k) + 1));
12174 
12175 			/* new "actual letter" */
12176 			c = word[i];
12177 		    }
12178 		    else
12179 		    {
12180 			/* no '<' rule used */
12181 			i += k - 1;
12182 			z = 0;
12183 			if (ws != NULL)
12184 			    while (*ws != NUL && ws[1] != NUL
12185 							  && reslen < MAXWLEN)
12186 			    {
12187 				if (reslen == 0 || wres[reslen - 1] != *ws)
12188 				    wres[reslen++] = *ws;
12189 				ws++;
12190 			    }
12191 			/* new "actual letter" */
12192 			if (ws == NULL)
12193 			    c = NUL;
12194 			else
12195 			    c = *ws;
12196 			if (strstr((char *)s, "^^") != NULL)
12197 			{
12198 			    if (c != NUL)
12199 				wres[reslen++] = c;
12200 			    mch_memmove(word, word + i + 1,
12201 				    sizeof(int) * (STRLEN(word + i + 1) + 1));
12202 			    i = 0;
12203 			    z0 = 1;
12204 			}
12205 		    }
12206 		    break;
12207 		}
12208 	    }
12209 	}
12210 	else if (vim_iswhite(c))
12211 	{
12212 	    c = ' ';
12213 	    k = 1;
12214 	}
12215 
12216 	if (z0 == 0)
12217 	{
12218 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
12219 		    && (!slang->sl_collapse || reslen == 0
12220 						     || wres[reslen - 1] != c))
12221 		/* condense only double letters */
12222 		wres[reslen++] = c;
12223 
12224 	    i++;
12225 	    z = 0;
12226 	    k = 0;
12227 	}
12228     }
12229 
12230     /* Convert wide characters in "wres" to a multi-byte string in "res". */
12231     l = 0;
12232     for (n = 0; n < reslen; ++n)
12233     {
12234 	l += mb_char2bytes(wres[n], res + l);
12235 	if (l + MB_MAXBYTES > MAXWLEN)
12236 	    break;
12237     }
12238     res[l] = NUL;
12239 }
12240 #endif
12241 
12242 /*
12243  * Compute a score for two sound-a-like words.
12244  * This permits up to two inserts/deletes/swaps/etc. to keep things fast.
12245  * Instead of a generic loop we write out the code.  That keeps it fast by
12246  * avoiding checks that will not be possible.
12247  */
12248     static int
12249 soundalike_score(goodstart, badstart)
12250     char_u	*goodstart;	/* sound-folded good word */
12251     char_u	*badstart;	/* sound-folded bad word */
12252 {
12253     char_u	*goodsound = goodstart;
12254     char_u	*badsound = badstart;
12255     int		goodlen;
12256     int		badlen;
12257     int		n;
12258     char_u	*pl, *ps;
12259     char_u	*pl2, *ps2;
12260     int		score = 0;
12261 
12262     /* adding/inserting "*" at the start (word starts with vowel) shouldn't be
12263      * counted so much, vowels halfway the word aren't counted at all. */
12264     if ((*badsound == '*' || *goodsound == '*') && *badsound != *goodsound)
12265     {
12266 	score = SCORE_DEL / 2;
12267 	if (*badsound == '*')
12268 	    ++badsound;
12269 	else
12270 	    ++goodsound;
12271     }
12272 
12273     goodlen = STRLEN(goodsound);
12274     badlen = STRLEN(badsound);
12275 
12276     /* Return quickly if the lenghts are too different to be fixed by two
12277      * changes. */
12278     n = goodlen - badlen;
12279     if (n < -2 || n > 2)
12280 	return SCORE_MAXMAX;
12281 
12282     if (n > 0)
12283     {
12284 	pl = goodsound;	    /* goodsound is longest */
12285 	ps = badsound;
12286     }
12287     else
12288     {
12289 	pl = badsound;	    /* badsound is longest */
12290 	ps = goodsound;
12291     }
12292 
12293     /* Skip over the identical part. */
12294     while (*pl == *ps && *pl != NUL)
12295     {
12296 	++pl;
12297 	++ps;
12298     }
12299 
12300     switch (n)
12301     {
12302 	case -2:
12303 	case 2:
12304 	    /*
12305 	     * Must delete two characters from "pl".
12306 	     */
12307 	    ++pl;	/* first delete */
12308 	    while (*pl == *ps)
12309 	    {
12310 		++pl;
12311 		++ps;
12312 	    }
12313 	    /* strings must be equal after second delete */
12314 	    if (STRCMP(pl + 1, ps) == 0)
12315 		return score + SCORE_DEL * 2;
12316 
12317 	    /* Failed to compare. */
12318 	    break;
12319 
12320 	case -1:
12321 	case 1:
12322 	    /*
12323 	     * Minimal one delete from "pl" required.
12324 	     */
12325 
12326 	    /* 1: delete */
12327 	    pl2 = pl + 1;
12328 	    ps2 = ps;
12329 	    while (*pl2 == *ps2)
12330 	    {
12331 		if (*pl2 == NUL)	/* reached the end */
12332 		    return score + SCORE_DEL;
12333 		++pl2;
12334 		++ps2;
12335 	    }
12336 
12337 	    /* 2: delete then swap, then rest must be equal */
12338 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
12339 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
12340 		return score + SCORE_DEL + SCORE_SWAP;
12341 
12342 	    /* 3: delete then substitute, then the rest must be equal */
12343 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
12344 		return score + SCORE_DEL + SCORE_SUBST;
12345 
12346 	    /* 4: first swap then delete */
12347 	    if (pl[0] == ps[1] && pl[1] == ps[0])
12348 	    {
12349 		pl2 = pl + 2;	    /* swap, skip two chars */
12350 		ps2 = ps + 2;
12351 		while (*pl2 == *ps2)
12352 		{
12353 		    ++pl2;
12354 		    ++ps2;
12355 		}
12356 		/* delete a char and then strings must be equal */
12357 		if (STRCMP(pl2 + 1, ps2) == 0)
12358 		    return score + SCORE_SWAP + SCORE_DEL;
12359 	    }
12360 
12361 	    /* 5: first substitute then delete */
12362 	    pl2 = pl + 1;	    /* substitute, skip one char */
12363 	    ps2 = ps + 1;
12364 	    while (*pl2 == *ps2)
12365 	    {
12366 		++pl2;
12367 		++ps2;
12368 	    }
12369 	    /* delete a char and then strings must be equal */
12370 	    if (STRCMP(pl2 + 1, ps2) == 0)
12371 		return score + SCORE_SUBST + SCORE_DEL;
12372 
12373 	    /* Failed to compare. */
12374 	    break;
12375 
12376 	case 0:
12377 	    /*
12378 	     * Lenghts are equal, thus changes must result in same length: An
12379 	     * insert is only possible in combination with a delete.
12380 	     * 1: check if for identical strings
12381 	     */
12382 	    if (*pl == NUL)
12383 		return score;
12384 
12385 	    /* 2: swap */
12386 	    if (pl[0] == ps[1] && pl[1] == ps[0])
12387 	    {
12388 		pl2 = pl + 2;	    /* swap, skip two chars */
12389 		ps2 = ps + 2;
12390 		while (*pl2 == *ps2)
12391 		{
12392 		    if (*pl2 == NUL)	/* reached the end */
12393 			return score + SCORE_SWAP;
12394 		    ++pl2;
12395 		    ++ps2;
12396 		}
12397 		/* 3: swap and swap again */
12398 		if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
12399 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
12400 		    return score + SCORE_SWAP + SCORE_SWAP;
12401 
12402 		/* 4: swap and substitute */
12403 		if (STRCMP(pl2 + 1, ps2 + 1) == 0)
12404 		    return score + SCORE_SWAP + SCORE_SUBST;
12405 	    }
12406 
12407 	    /* 5: substitute */
12408 	    pl2 = pl + 1;
12409 	    ps2 = ps + 1;
12410 	    while (*pl2 == *ps2)
12411 	    {
12412 		if (*pl2 == NUL)	/* reached the end */
12413 		    return score + SCORE_SUBST;
12414 		++pl2;
12415 		++ps2;
12416 	    }
12417 
12418 	    /* 6: substitute and swap */
12419 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
12420 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
12421 		return score + SCORE_SUBST + SCORE_SWAP;
12422 
12423 	    /* 7: substitute and substitute */
12424 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
12425 		return score + SCORE_SUBST + SCORE_SUBST;
12426 
12427 	    /* 8: insert then delete */
12428 	    pl2 = pl;
12429 	    ps2 = ps + 1;
12430 	    while (*pl2 == *ps2)
12431 	    {
12432 		++pl2;
12433 		++ps2;
12434 	    }
12435 	    if (STRCMP(pl2 + 1, ps2) == 0)
12436 		return score + SCORE_INS + SCORE_DEL;
12437 
12438 	    /* 9: delete then insert */
12439 	    pl2 = pl + 1;
12440 	    ps2 = ps;
12441 	    while (*pl2 == *ps2)
12442 	    {
12443 		++pl2;
12444 		++ps2;
12445 	    }
12446 	    if (STRCMP(pl2, ps2 + 1) == 0)
12447 		return score + SCORE_INS + SCORE_DEL;
12448 
12449 	    /* Failed to compare. */
12450 	    break;
12451     }
12452 
12453     return SCORE_MAXMAX;
12454 }
12455 
12456 /*
12457  * Compute the "edit distance" to turn "badword" into "goodword".  The less
12458  * deletes/inserts/substitutes/swaps are required the lower the score.
12459  *
12460  * The algorithm is described by Du and Chang, 1992.
12461  * The implementation of the algorithm comes from Aspell editdist.cpp,
12462  * edit_distance().  It has been converted from C++ to C and modified to
12463  * support multi-byte characters.
12464  */
12465     static int
12466 spell_edit_score(badword, goodword)
12467     char_u	*badword;
12468     char_u	*goodword;
12469 {
12470     int		*cnt;
12471     int		badlen, goodlen;	/* lenghts including NUL */
12472     int		j, i;
12473     int		t;
12474     int		bc, gc;
12475     int		pbc, pgc;
12476 #ifdef FEAT_MBYTE
12477     char_u	*p;
12478     int		wbadword[MAXWLEN];
12479     int		wgoodword[MAXWLEN];
12480 
12481     if (has_mbyte)
12482     {
12483 	/* Get the characters from the multi-byte strings and put them in an
12484 	 * int array for easy access. */
12485 	for (p = badword, badlen = 0; *p != NUL; )
12486 	    wbadword[badlen++] = mb_cptr2char_adv(&p);
12487 	wbadword[badlen++] = 0;
12488 	for (p = goodword, goodlen = 0; *p != NUL; )
12489 	    wgoodword[goodlen++] = mb_cptr2char_adv(&p);
12490 	wgoodword[goodlen++] = 0;
12491     }
12492     else
12493 #endif
12494     {
12495 	badlen = STRLEN(badword) + 1;
12496 	goodlen = STRLEN(goodword) + 1;
12497     }
12498 
12499     /* We use "cnt" as an array: CNT(badword_idx, goodword_idx). */
12500 #define CNT(a, b)   cnt[(a) + (b) * (badlen + 1)]
12501     cnt = (int *)lalloc((long_u)(sizeof(int) * (badlen + 1) * (goodlen + 1)),
12502 									TRUE);
12503     if (cnt == NULL)
12504 	return 0;	/* out of memory */
12505 
12506     CNT(0, 0) = 0;
12507     for (j = 1; j <= goodlen; ++j)
12508 	CNT(0, j) = CNT(0, j - 1) + SCORE_DEL;
12509 
12510     for (i = 1; i <= badlen; ++i)
12511     {
12512 	CNT(i, 0) = CNT(i - 1, 0) + SCORE_INS;
12513 	for (j = 1; j <= goodlen; ++j)
12514 	{
12515 #ifdef FEAT_MBYTE
12516 	    if (has_mbyte)
12517 	    {
12518 		bc = wbadword[i - 1];
12519 		gc = wgoodword[j - 1];
12520 	    }
12521 	    else
12522 #endif
12523 	    {
12524 		bc = badword[i - 1];
12525 		gc = goodword[j - 1];
12526 	    }
12527 	    if (bc == gc)
12528 		CNT(i, j) = CNT(i - 1, j - 1);
12529 	    else
12530 	    {
12531 		/* Use a better score when there is only a case difference. */
12532 		if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
12533 		    CNT(i, j) = SCORE_ICASE + CNT(i - 1, j - 1);
12534 		else
12535 		    CNT(i, j) = SCORE_SUBST + CNT(i - 1, j - 1);
12536 
12537 		if (i > 1 && j > 1)
12538 		{
12539 #ifdef FEAT_MBYTE
12540 		    if (has_mbyte)
12541 		    {
12542 			pbc = wbadword[i - 2];
12543 			pgc = wgoodword[j - 2];
12544 		    }
12545 		    else
12546 #endif
12547 		    {
12548 			pbc = badword[i - 2];
12549 			pgc = goodword[j - 2];
12550 		    }
12551 		    if (bc == pgc && pbc == gc)
12552 		    {
12553 			t = SCORE_SWAP + CNT(i - 2, j - 2);
12554 			if (t < CNT(i, j))
12555 			    CNT(i, j) = t;
12556 		    }
12557 		}
12558 		t = SCORE_DEL + CNT(i - 1, j);
12559 		if (t < CNT(i, j))
12560 		    CNT(i, j) = t;
12561 		t = SCORE_INS + CNT(i, j - 1);
12562 		if (t < CNT(i, j))
12563 		    CNT(i, j) = t;
12564 	    }
12565 	}
12566     }
12567 
12568     i = CNT(badlen - 1, goodlen - 1);
12569     vim_free(cnt);
12570     return i;
12571 }
12572 
12573 /*
12574  * ":spelldump"
12575  */
12576 /*ARGSUSED*/
12577     void
12578 ex_spelldump(eap)
12579     exarg_T *eap;
12580 {
12581     buf_T	*buf = curbuf;
12582     langp_T	*lp;
12583     slang_T	*slang;
12584     idx_T	arridx[MAXWLEN];
12585     int		curi[MAXWLEN];
12586     char_u	word[MAXWLEN];
12587     int		c;
12588     char_u	*byts;
12589     idx_T	*idxs;
12590     linenr_T	lnum = 0;
12591     int		round;
12592     int		depth;
12593     int		n;
12594     int		flags;
12595     char_u	*region_names = NULL;	    /* region names being used */
12596     int		do_region = TRUE;	    /* dump region names and numbers */
12597     char_u	*p;
12598     int		lpi;
12599 
12600     if (no_spell_checking(curwin))
12601 	return;
12602 
12603     /* Create a new empty buffer by splitting the window. */
12604     do_cmdline_cmd((char_u *)"new");
12605     if (!bufempty() || !buf_valid(buf))
12606 	return;
12607 
12608     /* Find out if we can support regions: All languages must support the same
12609      * regions or none at all. */
12610     for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
12611     {
12612 	lp = LANGP_ENTRY(buf->b_langp, lpi);
12613 	p = lp->lp_slang->sl_regions;
12614 	if (p[0] != 0)
12615 	{
12616 	    if (region_names == NULL)	    /* first language with regions */
12617 		region_names = p;
12618 	    else if (STRCMP(region_names, p) != 0)
12619 	    {
12620 		do_region = FALSE;	    /* region names are different */
12621 		break;
12622 	    }
12623 	}
12624     }
12625 
12626     if (do_region && region_names != NULL)
12627     {
12628 	vim_snprintf((char *)IObuff, IOSIZE, "/regions=%s", region_names);
12629 	ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
12630     }
12631     else
12632 	do_region = FALSE;
12633 
12634     /*
12635      * Loop over all files loaded for the entries in 'spelllang'.
12636      */
12637     for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
12638     {
12639 	lp = LANGP_ENTRY(buf->b_langp, lpi);
12640 	slang = lp->lp_slang;
12641 	if (slang->sl_fbyts == NULL)	    /* reloading failed */
12642 	    continue;
12643 
12644 	vim_snprintf((char *)IObuff, IOSIZE, "# file: %s", slang->sl_fname);
12645 	ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
12646 
12647 	/* round 1: case-folded tree
12648 	 * round 2: keep-case tree */
12649 	for (round = 1; round <= 2; ++round)
12650 	{
12651 	    if (round == 1)
12652 	    {
12653 		byts = slang->sl_fbyts;
12654 		idxs = slang->sl_fidxs;
12655 	    }
12656 	    else
12657 	    {
12658 		byts = slang->sl_kbyts;
12659 		idxs = slang->sl_kidxs;
12660 	    }
12661 	    if (byts == NULL)
12662 		continue;		/* array is empty */
12663 
12664 	    depth = 0;
12665 	    arridx[0] = 0;
12666 	    curi[0] = 1;
12667 	    while (depth >= 0 && !got_int)
12668 	    {
12669 		if (curi[depth] > byts[arridx[depth]])
12670 		{
12671 		    /* Done all bytes at this node, go up one level. */
12672 		    --depth;
12673 		    line_breakcheck();
12674 		}
12675 		else
12676 		{
12677 		    /* Do one more byte at this node. */
12678 		    n = arridx[depth] + curi[depth];
12679 		    ++curi[depth];
12680 		    c = byts[n];
12681 		    if (c == 0)
12682 		    {
12683 			/* End of word, deal with the word.
12684 			 * Don't use keep-case words in the fold-case tree,
12685 			 * they will appear in the keep-case tree.
12686 			 * Only use the word when the region matches. */
12687 			flags = (int)idxs[n];
12688 			if ((round == 2 || (flags & WF_KEEPCAP) == 0)
12689 				&& (flags & WF_NEEDCOMP) == 0
12690 				&& (do_region
12691 				    || (flags & WF_REGION) == 0
12692 				    || (((unsigned)flags >> 16)
12693 						       & lp->lp_region) != 0))
12694 			{
12695 			    word[depth] = NUL;
12696 			    if (!do_region)
12697 				flags &= ~WF_REGION;
12698 
12699 			    /* Dump the basic word if there is no prefix or
12700 			     * when it's the first one. */
12701 			    c = (unsigned)flags >> 24;
12702 			    if (c == 0 || curi[depth] == 2)
12703 				dump_word(word, round, flags, lnum++);
12704 
12705 			    /* Apply the prefix, if there is one. */
12706 			    if (c != 0)
12707 				lnum = dump_prefixes(slang, word, round,
12708 								 flags, lnum);
12709 			}
12710 		    }
12711 		    else
12712 		    {
12713 			/* Normal char, go one level deeper. */
12714 			word[depth++] = c;
12715 			arridx[depth] = idxs[n];
12716 			curi[depth] = 1;
12717 		    }
12718 		}
12719 	    }
12720 	}
12721     }
12722 
12723     /* Delete the empty line that we started with. */
12724     if (curbuf->b_ml.ml_line_count > 1)
12725 	ml_delete(curbuf->b_ml.ml_line_count, FALSE);
12726 
12727     redraw_later(NOT_VALID);
12728 }
12729 
12730 /*
12731  * Dump one word: apply case modifications and append a line to the buffer.
12732  */
12733     static void
12734 dump_word(word, round, flags, lnum)
12735     char_u	*word;
12736     int		round;
12737     int		flags;
12738     linenr_T	lnum;
12739 {
12740     int		keepcap = FALSE;
12741     char_u	*p;
12742     char_u	cword[MAXWLEN];
12743     char_u	badword[MAXWLEN + 10];
12744     int		i;
12745 
12746     if (round == 1 && (flags & WF_CAPMASK) != 0)
12747     {
12748 	/* Need to fix case according to "flags". */
12749 	make_case_word(word, cword, flags);
12750 	p = cword;
12751     }
12752     else
12753     {
12754 	p = word;
12755 	if (round == 2 && ((captype(word, NULL) & WF_KEEPCAP) == 0
12756 						 || (flags & WF_FIXCAP) != 0))
12757 	    keepcap = TRUE;
12758     }
12759 
12760     /* Add flags and regions after a slash. */
12761     if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap)
12762     {
12763 	STRCPY(badword, p);
12764 	STRCAT(badword, "/");
12765 	if (keepcap)
12766 	    STRCAT(badword, "=");
12767 	if (flags & WF_BANNED)
12768 	    STRCAT(badword, "!");
12769 	else if (flags & WF_RARE)
12770 	    STRCAT(badword, "?");
12771 	if (flags & WF_REGION)
12772 	    for (i = 0; i < 7; ++i)
12773 		if (flags & (0x10000 << i))
12774 		    sprintf((char *)badword + STRLEN(badword), "%d", i + 1);
12775 	p = badword;
12776     }
12777 
12778     ml_append(lnum, p, (colnr_T)0, FALSE);
12779 }
12780 
12781 /*
12782  * For ":spelldump": Find matching prefixes for "word".  Prepend each to
12783  * "word" and append a line to the buffer.
12784  * Return the updated line number.
12785  */
12786     static linenr_T
12787 dump_prefixes(slang, word, round, flags, startlnum)
12788     slang_T	*slang;
12789     char_u	*word;	    /* case-folded word */
12790     int		round;
12791     int		flags;	    /* flags with prefix ID */
12792     linenr_T	startlnum;
12793 {
12794     idx_T	arridx[MAXWLEN];
12795     int		curi[MAXWLEN];
12796     char_u	prefix[MAXWLEN];
12797     char_u	word_up[MAXWLEN];
12798     int		has_word_up = FALSE;
12799     int		c;
12800     char_u	*byts;
12801     idx_T	*idxs;
12802     linenr_T	lnum = startlnum;
12803     int		depth;
12804     int		n;
12805     int		len;
12806     int		i;
12807 
12808     /* if the word starts with a lower-case letter make the word with an
12809      * upper-case letter in word_up[]. */
12810     c = PTR2CHAR(word);
12811     if (SPELL_TOUPPER(c) != c)
12812     {
12813 	onecap_copy(word, word_up, TRUE);
12814 	has_word_up = TRUE;
12815     }
12816 
12817     byts = slang->sl_pbyts;
12818     idxs = slang->sl_pidxs;
12819     if (byts != NULL)		/* array not is empty */
12820     {
12821 	/*
12822 	 * Loop over all prefixes, building them byte-by-byte in prefix[].
12823 	 * When at the end of a prefix check that it supports "flags".
12824 	 */
12825 	depth = 0;
12826 	arridx[0] = 0;
12827 	curi[0] = 1;
12828 	while (depth >= 0 && !got_int)
12829 	{
12830 	    n = arridx[depth];
12831 	    len = byts[n];
12832 	    if (curi[depth] > len)
12833 	    {
12834 		/* Done all bytes at this node, go up one level. */
12835 		--depth;
12836 		line_breakcheck();
12837 	    }
12838 	    else
12839 	    {
12840 		/* Do one more byte at this node. */
12841 		n += curi[depth];
12842 		++curi[depth];
12843 		c = byts[n];
12844 		if (c == 0)
12845 		{
12846 		    /* End of prefix, find out how many IDs there are. */
12847 		    for (i = 1; i < len; ++i)
12848 			if (byts[n + i] != 0)
12849 			    break;
12850 		    curi[depth] += i - 1;
12851 
12852 		    c = valid_word_prefix(i, n, flags, word, slang, FALSE);
12853 		    if (c != 0)
12854 		    {
12855 			vim_strncpy(prefix + depth, word, MAXWLEN - depth - 1);
12856 			dump_word(prefix, round,
12857 				(c & WF_RAREPFX) ? (flags | WF_RARE)
12858 							     : flags, lnum++);
12859 		    }
12860 
12861 		    /* Check for prefix that matches the word when the
12862 		     * first letter is upper-case, but only if the prefix has
12863 		     * a condition. */
12864 		    if (has_word_up)
12865 		    {
12866 			c = valid_word_prefix(i, n, flags, word_up, slang,
12867 									TRUE);
12868 			if (c != 0)
12869 			{
12870 			    vim_strncpy(prefix + depth, word_up,
12871 							 MAXWLEN - depth - 1);
12872 			    dump_word(prefix, round,
12873 				    (c & WF_RAREPFX) ? (flags | WF_RARE)
12874 							     : flags, lnum++);
12875 			}
12876 		    }
12877 		}
12878 		else
12879 		{
12880 		    /* Normal char, go one level deeper. */
12881 		    prefix[depth++] = c;
12882 		    arridx[depth] = idxs[n];
12883 		    curi[depth] = 1;
12884 		}
12885 	    }
12886 	}
12887     }
12888 
12889     return lnum;
12890 }
12891 
12892 /*
12893  * Move "p" to end of word.
12894  */
12895     char_u *
12896 spell_to_word_end(start, buf)
12897     char_u  *start;
12898     buf_T   *buf;
12899 {
12900     char_u  *p = start;
12901 
12902     while (*p != NUL && spell_iswordp(p, buf))
12903 	mb_ptr_adv(p);
12904     return p;
12905 }
12906 
12907 #if defined(FEAT_INS_EXPAND) || defined(PROTO)
12908 /*
12909  * Find start of the word in front of the cursor.  We don't check if it is
12910  * badly spelled, with completion we can only change the word in front of the
12911  * cursor.
12912  * Used for Insert mode completion CTRL-X ?.
12913  * Returns the column number of the word.
12914  */
12915     int
12916 spell_word_start(startcol)
12917     int		startcol;
12918 {
12919     char_u	*line;
12920     char_u	*p;
12921     int		col = 0;
12922 
12923     if (no_spell_checking(curwin))
12924 	return startcol;
12925 
12926     /* Find a word character before "startcol". */
12927     line = ml_get_curline();
12928     for (p = line + startcol; p > line; )
12929     {
12930 	mb_ptr_back(line, p);
12931 	if (spell_iswordp_nmw(p))
12932 	    break;
12933     }
12934 
12935     /* Go back to start of the word. */
12936     while (p > line)
12937     {
12938 	col = p - line;
12939 	mb_ptr_back(line, p);
12940 	if (!spell_iswordp(p, curbuf))
12941 	    break;
12942 	col = 0;
12943     }
12944 
12945     return col;
12946 }
12947 
12948 /*
12949  * Need to check for 'spellcapcheck' now, the word is removed before
12950  * expand_spelling() is called.  Therefore the ugly global variable.
12951  */
12952 static int spell_expand_need_cap;
12953 
12954     void
12955 spell_expand_check_cap(col)
12956     colnr_T col;
12957 {
12958     spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col);
12959 }
12960 
12961 /*
12962  * Get list of spelling suggestions.
12963  * Used for Insert mode completion CTRL-X ?.
12964  * Returns the number of matches.  The matches are in "matchp[]", array of
12965  * allocated strings.
12966  */
12967 /*ARGSUSED*/
12968     int
12969 expand_spelling(lnum, col, pat, matchp)
12970     linenr_T	lnum;
12971     int		col;
12972     char_u	*pat;
12973     char_u	***matchp;
12974 {
12975     garray_T	ga;
12976 
12977     spell_suggest_list(&ga, pat, 100, spell_expand_need_cap);
12978     *matchp = ga.ga_data;
12979     return ga.ga_len;
12980 }
12981 #endif
12982 
12983 #endif  /* FEAT_SYN_HL */
12984