xref: /vim-8.2.3635/src/spell.c (revision 00a927d6)
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  * LZ trie ideas:
47  *	http://www.irb.hr/hr/home/ristov/papers/RistovLZtrieRevision1.pdf
48  * More papers: http://www-igm.univ-mlv.fr/~laporte/publi_en.html
49  *
50  * Matching involves checking the caps type: Onecap ALLCAP KeepCap.
51  *
52  * Why doesn't Vim use aspell/ispell/myspell/etc.?
53  * See ":help develop-spell".
54  */
55 
56 /* Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word.
57  * Only use it for small word lists! */
58 #if 0
59 # define SPELL_PRINTTREE
60 #endif
61 
62 /* Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a
63  * specific word. */
64 #if 0
65 # define DEBUG_TRIEWALK
66 #endif
67 
68 /*
69  * Use this to adjust the score after finding suggestions, based on the
70  * suggested word sounding like the bad word.  This is much faster than doing
71  * it for every possible suggestion.
72  * Disadvantage: When "the" is typed as "hte" it sounds quite different ("@"
73  * vs "ht") and goes down in the list.
74  * Used when 'spellsuggest' is set to "best".
75  */
76 #define RESCORE(word_score, sound_score) ((3 * word_score + sound_score) / 4)
77 
78 /*
79  * Do the opposite: based on a maximum end score and a known sound score,
80  * compute the maximum word score that can be used.
81  */
82 #define MAXSCORE(word_score, sound_score) ((4 * word_score - sound_score) / 3)
83 
84 /*
85  * Vim spell file format: <HEADER>
86  *			  <SECTIONS>
87  *			  <LWORDTREE>
88  *			  <KWORDTREE>
89  *			  <PREFIXTREE>
90  *
91  * <HEADER>: <fileID> <versionnr>
92  *
93  * <fileID>     8 bytes    "VIMspell"
94  * <versionnr>  1 byte	    VIMSPELLVERSION
95  *
96  *
97  * Sections make it possible to add information to the .spl file without
98  * making it incompatible with previous versions.  There are two kinds of
99  * sections:
100  * 1. Not essential for correct spell checking.  E.g. for making suggestions.
101  *    These are skipped when not supported.
102  * 2. Optional information, but essential for spell checking when present.
103  *    E.g. conditions for affixes.  When this section is present but not
104  *    supported an error message is given.
105  *
106  * <SECTIONS>: <section> ... <sectionend>
107  *
108  * <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
109  *
110  * <sectionID>	  1 byte    number from 0 to 254 identifying the section
111  *
112  * <sectionflags> 1 byte    SNF_REQUIRED: this section is required for correct
113  *					    spell checking
114  *
115  * <sectionlen>   4 bytes   length of section contents, MSB first
116  *
117  * <sectionend>	  1 byte    SN_END
118  *
119  *
120  * sectionID == SN_INFO: <infotext>
121  * <infotext>	 N bytes    free format text with spell file info (version,
122  *			    website, etc)
123  *
124  * sectionID == SN_REGION: <regionname> ...
125  * <regionname>	 2 bytes    Up to 8 region names: ca, au, etc.  Lower case.
126  *			    First <regionname> is region 1.
127  *
128  * sectionID == SN_CHARFLAGS: <charflagslen> <charflags>
129  *				<folcharslen> <folchars>
130  * <charflagslen> 1 byte    Number of bytes in <charflags> (should be 128).
131  * <charflags>  N bytes     List of flags (first one is for character 128):
132  *			    0x01  word character	CF_WORD
133  *			    0x02  upper-case character	CF_UPPER
134  * <folcharslen>  2 bytes   Number of bytes in <folchars>.
135  * <folchars>     N bytes   Folded characters, first one is for character 128.
136  *
137  * sectionID == SN_MIDWORD: <midword>
138  * <midword>     N bytes    Characters that are word characters only when used
139  *			    in the middle of a word.
140  *
141  * sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ...
142  * <prefcondcnt> 2 bytes    Number of <prefcond> items following.
143  * <prefcond> : <condlen> <condstr>
144  * <condlen>	1 byte	    Length of <condstr>.
145  * <condstr>	N bytes	    Condition for the prefix.
146  *
147  * sectionID == SN_REP: <repcount> <rep> ...
148  * <repcount>	 2 bytes    number of <rep> items, MSB first.
149  * <rep> : <repfromlen> <repfrom> <reptolen> <repto>
150  * <repfromlen>	 1 byte	    length of <repfrom>
151  * <repfrom>	 N bytes    "from" part of replacement
152  * <reptolen>	 1 byte	    length of <repto>
153  * <repto>	 N bytes    "to" part of replacement
154  *
155  * sectionID == SN_REPSAL: <repcount> <rep> ...
156  *   just like SN_REP but for soundfolded words
157  *
158  * sectionID == SN_SAL: <salflags> <salcount> <sal> ...
159  * <salflags>	 1 byte	    flags for soundsalike conversion:
160  *			    SAL_F0LLOWUP
161  *			    SAL_COLLAPSE
162  *			    SAL_REM_ACCENTS
163  * <salcount>    2 bytes    number of <sal> items following
164  * <sal> : <salfromlen> <salfrom> <saltolen> <salto>
165  * <salfromlen>	 1 byte	    length of <salfrom>
166  * <salfrom>	 N bytes    "from" part of soundsalike
167  * <saltolen>	 1 byte	    length of <salto>
168  * <salto>	 N bytes    "to" part of soundsalike
169  *
170  * sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
171  * <sofofromlen> 2 bytes    length of <sofofrom>
172  * <sofofrom>	 N bytes    "from" part of soundfold
173  * <sofotolen>	 2 bytes    length of <sofoto>
174  * <sofoto>	 N bytes    "to" part of soundfold
175  *
176  * sectionID == SN_SUGFILE: <timestamp>
177  * <timestamp>   8 bytes    time in seconds that must match with .sug file
178  *
179  * sectionID == SN_NOSPLITSUGS: nothing
180  *
181  * sectionID == SN_WORDS: <word> ...
182  * <word>	 N bytes    NUL terminated common word
183  *
184  * sectionID == SN_MAP: <mapstr>
185  * <mapstr>	 N bytes    String with sequences of similar characters,
186  *			    separated by slashes.
187  *
188  * sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions>
189  *				<comppatcount> <comppattern> ... <compflags>
190  * <compmax>     1 byte	    Maximum nr of words in compound word.
191  * <compminlen>  1 byte	    Minimal word length for compounding.
192  * <compsylmax>  1 byte	    Maximum nr of syllables in compound word.
193  * <compoptions> 2 bytes    COMP_ flags.
194  * <comppatcount> 2 bytes   number of <comppattern> following
195  * <compflags>   N bytes    Flags from COMPOUNDRULE items, separated by
196  *			    slashes.
197  *
198  * <comppattern>: <comppatlen> <comppattext>
199  * <comppatlen>	 1 byte	    length of <comppattext>
200  * <comppattext> N bytes    end or begin chars from CHECKCOMPOUNDPATTERN
201  *
202  * sectionID == SN_NOBREAK: (empty, its presence is what matters)
203  *
204  * sectionID == SN_SYLLABLE: <syllable>
205  * <syllable>    N bytes    String from SYLLABLE item.
206  *
207  * <LWORDTREE>: <wordtree>
208  *
209  * <KWORDTREE>: <wordtree>
210  *
211  * <PREFIXTREE>: <wordtree>
212  *
213  *
214  * <wordtree>: <nodecount> <nodedata> ...
215  *
216  * <nodecount>	4 bytes	    Number of nodes following.  MSB first.
217  *
218  * <nodedata>: <siblingcount> <sibling> ...
219  *
220  * <siblingcount> 1 byte    Number of siblings in this node.  The siblings
221  *			    follow in sorted order.
222  *
223  * <sibling>: <byte> [ <nodeidx> <xbyte>
224  *		      | <flags> [<flags2>] [<region>] [<affixID>]
225  *		      | [<pflags>] <affixID> <prefcondnr> ]
226  *
227  * <byte>	1 byte	    Byte value of the sibling.  Special cases:
228  *			    BY_NOFLAGS: End of word without flags and for all
229  *					regions.
230  *					For PREFIXTREE <affixID> and
231  *					<prefcondnr> follow.
232  *			    BY_FLAGS:   End of word, <flags> follow.
233  *					For PREFIXTREE <pflags>, <affixID>
234  *					and <prefcondnr> follow.
235  *			    BY_FLAGS2:  End of word, <flags> and <flags2>
236  *					follow.  Not used in PREFIXTREE.
237  *			    BY_INDEX:   Child of sibling is shared, <nodeidx>
238  *					and <xbyte> follow.
239  *
240  * <nodeidx>	3 bytes	    Index of child for this sibling, MSB first.
241  *
242  * <xbyte>	1 byte	    byte value of the sibling.
243  *
244  * <flags>	1 byte	    bitmask of:
245  *			    WF_ALLCAP	word must have only capitals
246  *			    WF_ONECAP   first char of word must be capital
247  *			    WF_KEEPCAP	keep-case word
248  *			    WF_FIXCAP   keep-case word, all caps not allowed
249  *			    WF_RARE	rare word
250  *			    WF_BANNED	bad word
251  *			    WF_REGION	<region> follows
252  *			    WF_AFX	<affixID> follows
253  *
254  * <flags2>	1 byte	    Bitmask of:
255  *			    WF_HAS_AFF >> 8   word includes affix
256  *			    WF_NEEDCOMP >> 8  word only valid in compound
257  *			    WF_NOSUGGEST >> 8  word not used for suggestions
258  *			    WF_COMPROOT >> 8  word already a compound
259  *			    WF_NOCOMPBEF >> 8 no compounding before this word
260  *			    WF_NOCOMPAFT >> 8 no compounding after this word
261  *
262  * <pflags>	1 byte	    bitmask of:
263  *			    WFP_RARE	rare prefix
264  *			    WFP_NC	non-combining prefix
265  *			    WFP_UP	letter after prefix made upper case
266  *
267  * <region>	1 byte	    Bitmask for regions in which word is valid.  When
268  *			    omitted it's valid in all regions.
269  *			    Lowest bit is for region 1.
270  *
271  * <affixID>	1 byte	    ID of affix that can be used with this word.  In
272  *			    PREFIXTREE used for the required prefix ID.
273  *
274  * <prefcondnr>	2 bytes	    Prefix condition number, index in <prefcond> list
275  *			    from HEADER.
276  *
277  * All text characters are in 'encoding', but stored as single bytes.
278  */
279 
280 /*
281  * Vim .sug file format:  <SUGHEADER>
282  *			  <SUGWORDTREE>
283  *			  <SUGTABLE>
284  *
285  * <SUGHEADER>: <fileID> <versionnr> <timestamp>
286  *
287  * <fileID>     6 bytes     "VIMsug"
288  * <versionnr>  1 byte      VIMSUGVERSION
289  * <timestamp>  8 bytes     timestamp that must match with .spl file
290  *
291  *
292  * <SUGWORDTREE>: <wordtree>  (see above, no flags or region used)
293  *
294  *
295  * <SUGTABLE>: <sugwcount> <sugline> ...
296  *
297  * <sugwcount>	4 bytes	    number of <sugline> following
298  *
299  * <sugline>: <sugnr> ... NUL
300  *
301  * <sugnr>:     X bytes     word number that results in this soundfolded word,
302  *			    stored as an offset to the previous number in as
303  *			    few bytes as possible, see offset2bytes())
304  */
305 
306 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
307 # include "vimio.h"	/* for lseek(), must be before vim.h */
308 #endif
309 
310 #include "vim.h"
311 
312 #if defined(FEAT_SPELL) || defined(PROTO)
313 
314 #ifndef UNIX		/* it's in os_unix.h for Unix */
315 # include <time.h>	/* for time_t */
316 #endif
317 
318 #define MAXWLEN 250		/* Assume max. word len is this many bytes.
319 				   Some places assume a word length fits in a
320 				   byte, thus it can't be above 255. */
321 
322 /* Type used for indexes in the word tree need to be at least 4 bytes.  If int
323  * is 8 bytes we could use something smaller, but what? */
324 #if SIZEOF_INT > 3
325 typedef int idx_T;
326 #else
327 typedef long idx_T;
328 #endif
329 
330 /* Flags used for a word.  Only the lowest byte can be used, the region byte
331  * comes above it. */
332 #define WF_REGION   0x01	/* region byte follows */
333 #define WF_ONECAP   0x02	/* word with one capital (or all capitals) */
334 #define WF_ALLCAP   0x04	/* word must be all capitals */
335 #define WF_RARE	    0x08	/* rare word */
336 #define WF_BANNED   0x10	/* bad word */
337 #define WF_AFX	    0x20	/* affix ID follows */
338 #define WF_FIXCAP   0x40	/* keep-case word, allcap not allowed */
339 #define WF_KEEPCAP  0x80	/* keep-case word */
340 
341 /* for <flags2>, shifted up one byte to be used in wn_flags */
342 #define WF_HAS_AFF  0x0100	/* word includes affix */
343 #define WF_NEEDCOMP 0x0200	/* word only valid in compound */
344 #define WF_NOSUGGEST 0x0400	/* word not to be suggested */
345 #define WF_COMPROOT 0x0800	/* already compounded word, COMPOUNDROOT */
346 #define WF_NOCOMPBEF 0x1000	/* no compounding before this word */
347 #define WF_NOCOMPAFT 0x2000	/* no compounding after this word */
348 
349 /* only used for su_badflags */
350 #define WF_MIXCAP   0x20	/* mix of upper and lower case: macaRONI */
351 
352 #define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP)
353 
354 /* flags for <pflags> */
355 #define WFP_RARE	    0x01	/* rare prefix */
356 #define WFP_NC		    0x02	/* prefix is not combining */
357 #define WFP_UP		    0x04	/* to-upper prefix */
358 #define WFP_COMPPERMIT	    0x08	/* prefix with COMPOUNDPERMITFLAG */
359 #define WFP_COMPFORBID	    0x10	/* prefix with COMPOUNDFORBIDFLAG */
360 
361 /* Flags for postponed prefixes in "sl_pidxs".  Must be above affixID (one
362  * byte) and prefcondnr (two bytes). */
363 #define WF_RAREPFX  (WFP_RARE << 24)	/* rare postponed prefix */
364 #define WF_PFX_NC   (WFP_NC << 24)	/* non-combining postponed prefix */
365 #define WF_PFX_UP   (WFP_UP << 24)	/* to-upper postponed prefix */
366 #define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) /* postponed prefix with
367 						  * COMPOUNDPERMITFLAG */
368 #define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) /* postponed prefix with
369 						  * COMPOUNDFORBIDFLAG */
370 
371 
372 /* flags for <compoptions> */
373 #define COMP_CHECKDUP		1	/* CHECKCOMPOUNDDUP */
374 #define COMP_CHECKREP		2	/* CHECKCOMPOUNDREP */
375 #define COMP_CHECKCASE		4	/* CHECKCOMPOUNDCASE */
376 #define COMP_CHECKTRIPLE	8	/* CHECKCOMPOUNDTRIPLE */
377 
378 /* Special byte values for <byte>.  Some are only used in the tree for
379  * postponed prefixes, some only in the other trees.  This is a bit messy... */
380 #define BY_NOFLAGS	0	/* end of word without flags or region; for
381 				 * postponed prefix: no <pflags> */
382 #define BY_INDEX	1	/* child is shared, index follows */
383 #define BY_FLAGS	2	/* end of word, <flags> byte follows; for
384 				 * postponed prefix: <pflags> follows */
385 #define BY_FLAGS2	3	/* end of word, <flags> and <flags2> bytes
386 				 * follow; never used in prefix tree */
387 #define BY_SPECIAL  BY_FLAGS2	/* highest special byte value */
388 
389 /* Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep,
390  * si_repsal, sl_rep, and si_sal.  Not for sl_sal!
391  * One replacement: from "ft_from" to "ft_to". */
392 typedef struct fromto_S
393 {
394     char_u	*ft_from;
395     char_u	*ft_to;
396 } fromto_T;
397 
398 /* Info from "SAL" entries in ".aff" file used in sl_sal.
399  * The info is split for quick processing by spell_soundfold().
400  * Note that "sm_oneof" and "sm_rules" point into sm_lead. */
401 typedef struct salitem_S
402 {
403     char_u	*sm_lead;	/* leading letters */
404     int		sm_leadlen;	/* length of "sm_lead" */
405     char_u	*sm_oneof;	/* letters from () or NULL */
406     char_u	*sm_rules;	/* rules like ^, $, priority */
407     char_u	*sm_to;		/* replacement. */
408 #ifdef FEAT_MBYTE
409     int		*sm_lead_w;	/* wide character copy of "sm_lead" */
410     int		*sm_oneof_w;	/* wide character copy of "sm_oneof" */
411     int		*sm_to_w;	/* wide character copy of "sm_to" */
412 #endif
413 } salitem_T;
414 
415 #ifdef FEAT_MBYTE
416 typedef int salfirst_T;
417 #else
418 typedef short salfirst_T;
419 #endif
420 
421 /* Values for SP_*ERROR are negative, positive values are used by
422  * read_cnt_string(). */
423 #define	SP_TRUNCERROR	-1	/* spell file truncated error */
424 #define	SP_FORMERROR	-2	/* format error in spell file */
425 #define SP_OTHERERROR	-3	/* other error while reading spell file */
426 
427 /*
428  * Structure used to store words and other info for one language, loaded from
429  * a .spl file.
430  * The main access is through the tree in "sl_fbyts/sl_fidxs", storing the
431  * case-folded words.  "sl_kbyts/sl_kidxs" is for keep-case words.
432  *
433  * The "byts" array stores the possible bytes in each tree node, preceded by
434  * the number of possible bytes, sorted on byte value:
435  *	<len> <byte1> <byte2> ...
436  * The "idxs" array stores the index of the child node corresponding to the
437  * byte in "byts".
438  * Exception: when the byte is zero, the word may end here and "idxs" holds
439  * the flags, region mask and affixID for the word.  There may be several
440  * zeros in sequence for alternative flag/region/affixID combinations.
441  */
442 typedef struct slang_S slang_T;
443 struct slang_S
444 {
445     slang_T	*sl_next;	/* next language */
446     char_u	*sl_name;	/* language name "en", "en.rare", "nl", etc. */
447     char_u	*sl_fname;	/* name of .spl file */
448     int		sl_add;		/* TRUE if it's a .add file. */
449 
450     char_u	*sl_fbyts;	/* case-folded word bytes */
451     idx_T	*sl_fidxs;	/* case-folded word indexes */
452     char_u	*sl_kbyts;	/* keep-case word bytes */
453     idx_T	*sl_kidxs;	/* keep-case word indexes */
454     char_u	*sl_pbyts;	/* prefix tree word bytes */
455     idx_T	*sl_pidxs;	/* prefix tree word indexes */
456 
457     char_u	*sl_info;	/* infotext string or NULL */
458 
459     char_u	sl_regions[17];	/* table with up to 8 region names plus NUL */
460 
461     char_u	*sl_midword;	/* MIDWORD string or NULL */
462 
463     hashtab_T	sl_wordcount;	/* hashtable with word count, wordcount_T */
464 
465     int		sl_compmax;	/* COMPOUNDWORDMAX (default: MAXWLEN) */
466     int		sl_compminlen;	/* COMPOUNDMIN (default: 0) */
467     int		sl_compsylmax;	/* COMPOUNDSYLMAX (default: MAXWLEN) */
468     int		sl_compoptions;	/* COMP_* flags */
469     garray_T	sl_comppat;	/* CHECKCOMPOUNDPATTERN items */
470     regprog_T	*sl_compprog;	/* COMPOUNDRULE turned into a regexp progrm
471 				 * (NULL when no compounding) */
472     char_u	*sl_comprules;	/* all COMPOUNDRULE concatenated (or NULL) */
473     char_u	*sl_compstartflags; /* flags for first compound word */
474     char_u	*sl_compallflags; /* all flags for compound words */
475     char_u	sl_nobreak;	/* When TRUE: no spaces between words */
476     char_u	*sl_syllable;	/* SYLLABLE repeatable chars or NULL */
477     garray_T	sl_syl_items;	/* syllable items */
478 
479     int		sl_prefixcnt;	/* number of items in "sl_prefprog" */
480     regprog_T	**sl_prefprog;	/* table with regprogs for prefixes */
481 
482     garray_T	sl_rep;		/* list of fromto_T entries from REP lines */
483     short	sl_rep_first[256];  /* indexes where byte first appears, -1 if
484 				       there is none */
485     garray_T	sl_sal;		/* list of salitem_T entries from SAL lines */
486     salfirst_T	sl_sal_first[256];  /* indexes where byte first appears, -1 if
487 				       there is none */
488     int		sl_followup;	/* SAL followup */
489     int		sl_collapse;	/* SAL collapse_result */
490     int		sl_rem_accents;	/* SAL remove_accents */
491     int		sl_sofo;	/* SOFOFROM and SOFOTO instead of SAL items:
492 				 * "sl_sal_first" maps chars, when has_mbyte
493 				 * "sl_sal" is a list of wide char lists. */
494     garray_T	sl_repsal;	/* list of fromto_T entries from REPSAL lines */
495     short	sl_repsal_first[256];  /* sl_rep_first for REPSAL lines */
496     int		sl_nosplitsugs;	/* don't suggest splitting a word */
497 
498     /* Info from the .sug file.  Loaded on demand. */
499     time_t	sl_sugtime;	/* timestamp for .sug file */
500     char_u	*sl_sbyts;	/* soundfolded word bytes */
501     idx_T	*sl_sidxs;	/* soundfolded word indexes */
502     buf_T	*sl_sugbuf;	/* buffer with word number table */
503     int		sl_sugloaded;	/* TRUE when .sug file was loaded or failed to
504 				   load */
505 
506     int		sl_has_map;	/* TRUE if there is a MAP line */
507 #ifdef FEAT_MBYTE
508     hashtab_T	sl_map_hash;	/* MAP for multi-byte chars */
509     int		sl_map_array[256]; /* MAP for first 256 chars */
510 #else
511     char_u	sl_map_array[256]; /* MAP for first 256 chars */
512 #endif
513     hashtab_T	sl_sounddone;	/* table with soundfolded words that have
514 				   handled, see add_sound_suggest() */
515 };
516 
517 /* First language that is loaded, start of the linked list of loaded
518  * languages. */
519 static slang_T *first_lang = NULL;
520 
521 /* Flags used in .spl file for soundsalike flags. */
522 #define SAL_F0LLOWUP		1
523 #define SAL_COLLAPSE		2
524 #define SAL_REM_ACCENTS		4
525 
526 /*
527  * Structure used in "b_langp", filled from 'spelllang'.
528  */
529 typedef struct langp_S
530 {
531     slang_T	*lp_slang;	/* info for this language */
532     slang_T	*lp_sallang;	/* language used for sound folding or NULL */
533     slang_T	*lp_replang;	/* language used for REP items or NULL */
534     int		lp_region;	/* bitmask for region or REGION_ALL */
535 } langp_T;
536 
537 #define LANGP_ENTRY(ga, i)	(((langp_T *)(ga).ga_data) + (i))
538 
539 #define REGION_ALL 0xff		/* word valid in all regions */
540 
541 #define VIMSPELLMAGIC "VIMspell"  /* string at start of Vim spell file */
542 #define VIMSPELLMAGICL 8
543 #define VIMSPELLVERSION 50
544 
545 #define VIMSUGMAGIC "VIMsug"	/* string at start of Vim .sug file */
546 #define VIMSUGMAGICL 6
547 #define VIMSUGVERSION 1
548 
549 /* Section IDs.  Only renumber them when VIMSPELLVERSION changes! */
550 #define SN_REGION	0	/* <regionname> section */
551 #define SN_CHARFLAGS	1	/* charflags section */
552 #define SN_MIDWORD	2	/* <midword> section */
553 #define SN_PREFCOND	3	/* <prefcond> section */
554 #define SN_REP		4	/* REP items section */
555 #define SN_SAL		5	/* SAL items section */
556 #define SN_SOFO		6	/* soundfolding section */
557 #define SN_MAP		7	/* MAP items section */
558 #define SN_COMPOUND	8	/* compound words section */
559 #define SN_SYLLABLE	9	/* syllable section */
560 #define SN_NOBREAK	10	/* NOBREAK section */
561 #define SN_SUGFILE	11	/* timestamp for .sug file */
562 #define SN_REPSAL	12	/* REPSAL items section */
563 #define SN_WORDS	13	/* common words */
564 #define SN_NOSPLITSUGS	14	/* don't split word for suggestions */
565 #define SN_INFO		15	/* info section */
566 #define SN_END		255	/* end of sections */
567 
568 #define SNF_REQUIRED	1	/* <sectionflags>: required section */
569 
570 /* Result values.  Lower number is accepted over higher one. */
571 #define SP_BANNED	-1
572 #define SP_OK		0
573 #define SP_RARE		1
574 #define SP_LOCAL	2
575 #define SP_BAD		3
576 
577 /* file used for "zG" and "zW" */
578 static char_u	*int_wordlist = NULL;
579 
580 typedef struct wordcount_S
581 {
582     short_u	wc_count;	    /* nr of times word was seen */
583     char_u	wc_word[1];	    /* word, actually longer */
584 } wordcount_T;
585 
586 static wordcount_T dumwc;
587 #define WC_KEY_OFF  (unsigned)(dumwc.wc_word - (char_u *)&dumwc)
588 #define HI2WC(hi)     ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF))
589 #define MAXWORDCOUNT 0xffff
590 
591 /*
592  * Information used when looking for suggestions.
593  */
594 typedef struct suginfo_S
595 {
596     garray_T	su_ga;		    /* suggestions, contains "suggest_T" */
597     int		su_maxcount;	    /* max. number of suggestions displayed */
598     int		su_maxscore;	    /* maximum score for adding to su_ga */
599     int		su_sfmaxscore;	    /* idem, for when doing soundfold words */
600     garray_T	su_sga;		    /* like su_ga, sound-folded scoring */
601     char_u	*su_badptr;	    /* start of bad word in line */
602     int		su_badlen;	    /* length of detected bad word in line */
603     int		su_badflags;	    /* caps flags for bad word */
604     char_u	su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
605     char_u	su_fbadword[MAXWLEN]; /* su_badword case-folded */
606     char_u	su_sal_badword[MAXWLEN]; /* su_badword soundfolded */
607     hashtab_T	su_banned;	    /* table with banned words */
608     slang_T	*su_sallang;	    /* default language for sound folding */
609 } suginfo_T;
610 
611 /* One word suggestion.  Used in "si_ga". */
612 typedef struct suggest_S
613 {
614     char_u	*st_word;	/* suggested word, allocated string */
615     int		st_wordlen;	/* STRLEN(st_word) */
616     int		st_orglen;	/* length of replaced text */
617     int		st_score;	/* lower is better */
618     int		st_altscore;	/* used when st_score compares equal */
619     int		st_salscore;	/* st_score is for soundalike */
620     int		st_had_bonus;	/* bonus already included in score */
621     slang_T	*st_slang;	/* language used for sound folding */
622 } suggest_T;
623 
624 #define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i])
625 
626 /* TRUE if a word appears in the list of banned words.  */
627 #define WAS_BANNED(su, word) (!HASHITEM_EMPTY(hash_find(&su->su_banned, word)))
628 
629 /* Number of suggestions kept when cleaning up.  We need to keep more than
630  * what is displayed, because when rescore_suggestions() is called the score
631  * may change and wrong suggestions may be removed later. */
632 #define SUG_CLEAN_COUNT(su)    ((su)->su_maxcount < 130 ? 150 : (su)->su_maxcount + 20)
633 
634 /* Threshold for sorting and cleaning up suggestions.  Don't want to keep lots
635  * of suggestions that are not going to be displayed. */
636 #define SUG_MAX_COUNT(su)	(SUG_CLEAN_COUNT(su) + 50)
637 
638 /* score for various changes */
639 #define SCORE_SPLIT	149	/* split bad word */
640 #define SCORE_SPLIT_NO	249	/* split bad word with NOSPLITSUGS */
641 #define SCORE_ICASE	52	/* slightly different case */
642 #define SCORE_REGION	200	/* word is for different region */
643 #define SCORE_RARE	180	/* rare word */
644 #define SCORE_SWAP	75	/* swap two characters */
645 #define SCORE_SWAP3	110	/* swap two characters in three */
646 #define SCORE_REP	65	/* REP replacement */
647 #define SCORE_SUBST	93	/* substitute a character */
648 #define SCORE_SIMILAR	33	/* substitute a similar character */
649 #define SCORE_SUBCOMP	33	/* substitute a composing character */
650 #define SCORE_DEL	94	/* delete a character */
651 #define SCORE_DELDUP	66	/* delete a duplicated character */
652 #define SCORE_DELCOMP	28	/* delete a composing character */
653 #define SCORE_INS	96	/* insert a character */
654 #define SCORE_INSDUP	67	/* insert a duplicate character */
655 #define SCORE_INSCOMP	30	/* insert a composing character */
656 #define SCORE_NONWORD	103	/* change non-word to word char */
657 
658 #define SCORE_FILE	30	/* suggestion from a file */
659 #define SCORE_MAXINIT	350	/* Initial maximum score: higher == slower.
660 				 * 350 allows for about three changes. */
661 
662 #define SCORE_COMMON1	30	/* subtracted for words seen before */
663 #define SCORE_COMMON2	40	/* subtracted for words often seen */
664 #define SCORE_COMMON3	50	/* subtracted for words very often seen */
665 #define SCORE_THRES2	10	/* word count threshold for COMMON2 */
666 #define SCORE_THRES3	100	/* word count threshold for COMMON3 */
667 
668 /* When trying changed soundfold words it becomes slow when trying more than
669  * two changes.  With less then two changes it's slightly faster but we miss a
670  * few good suggestions.  In rare cases we need to try three of four changes.
671  */
672 #define SCORE_SFMAX1	200	/* maximum score for first try */
673 #define SCORE_SFMAX2	300	/* maximum score for second try */
674 #define SCORE_SFMAX3	400	/* maximum score for third try */
675 
676 #define SCORE_BIG	SCORE_INS * 3	/* big difference */
677 #define SCORE_MAXMAX	999999		/* accept any score */
678 #define SCORE_LIMITMAX	350		/* for spell_edit_score_limit() */
679 
680 /* for spell_edit_score_limit() we need to know the minimum value of
681  * SCORE_ICASE, SCORE_SWAP, SCORE_DEL, SCORE_SIMILAR and SCORE_INS */
682 #define SCORE_EDIT_MIN	SCORE_SIMILAR
683 
684 /*
685  * Structure to store info for word matching.
686  */
687 typedef struct matchinf_S
688 {
689     langp_T	*mi_lp;			/* info for language and region */
690 
691     /* pointers to original text to be checked */
692     char_u	*mi_word;		/* start of word being checked */
693     char_u	*mi_end;		/* end of matching word so far */
694     char_u	*mi_fend;		/* next char to be added to mi_fword */
695     char_u	*mi_cend;		/* char after what was used for
696 					   mi_capflags */
697 
698     /* case-folded text */
699     char_u	mi_fword[MAXWLEN + 1];	/* mi_word case-folded */
700     int		mi_fwordlen;		/* nr of valid bytes in mi_fword */
701 
702     /* for when checking word after a prefix */
703     int		mi_prefarridx;		/* index in sl_pidxs with list of
704 					   affixID/condition */
705     int		mi_prefcnt;		/* number of entries at mi_prefarridx */
706     int		mi_prefixlen;		/* byte length of prefix */
707 #ifdef FEAT_MBYTE
708     int		mi_cprefixlen;		/* byte length of prefix in original
709 					   case */
710 #else
711 # define mi_cprefixlen mi_prefixlen	/* it's the same value */
712 #endif
713 
714     /* for when checking a compound word */
715     int		mi_compoff;		/* start of following word offset */
716     char_u	mi_compflags[MAXWLEN];	/* flags for compound words used */
717     int		mi_complen;		/* nr of compound words used */
718     int		mi_compextra;		/* nr of COMPOUNDROOT words */
719 
720     /* others */
721     int		mi_result;		/* result so far: SP_BAD, SP_OK, etc. */
722     int		mi_capflags;		/* WF_ONECAP WF_ALLCAP WF_KEEPCAP */
723     buf_T	*mi_buf;		/* buffer being checked */
724 
725     /* for NOBREAK */
726     int		mi_result2;		/* "mi_resul" without following word */
727     char_u	*mi_end2;		/* "mi_end" without following word */
728 } matchinf_T;
729 
730 /*
731  * The tables used for recognizing word characters according to spelling.
732  * These are only used for the first 256 characters of 'encoding'.
733  */
734 typedef struct spelltab_S
735 {
736     char_u  st_isw[256];	/* flags: is word char */
737     char_u  st_isu[256];	/* flags: is uppercase char */
738     char_u  st_fold[256];	/* chars: folded case */
739     char_u  st_upper[256];	/* chars: upper case */
740 } spelltab_T;
741 
742 static spelltab_T   spelltab;
743 static int	    did_set_spelltab;
744 
745 #define CF_WORD		0x01
746 #define CF_UPPER	0x02
747 
748 static void clear_spell_chartab __ARGS((spelltab_T *sp));
749 static int set_spell_finish __ARGS((spelltab_T	*new_st));
750 static int spell_iswordp __ARGS((char_u *p, buf_T *buf));
751 static int spell_iswordp_nmw __ARGS((char_u *p));
752 #ifdef FEAT_MBYTE
753 static int spell_mb_isword_class __ARGS((int cl));
754 static int spell_iswordp_w __ARGS((int *p, buf_T *buf));
755 #endif
756 static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap));
757 
758 /*
759  * For finding suggestions: At each node in the tree these states are tried:
760  */
761 typedef enum
762 {
763     STATE_START = 0,	/* At start of node check for NUL bytes (goodword
764 			 * ends); if badword ends there is a match, otherwise
765 			 * try splitting word. */
766     STATE_NOPREFIX,	/* try without prefix */
767     STATE_SPLITUNDO,	/* Undo splitting. */
768     STATE_ENDNUL,	/* Past NUL bytes at start of the node. */
769     STATE_PLAIN,	/* Use each byte of the node. */
770     STATE_DEL,		/* Delete a byte from the bad word. */
771     STATE_INS_PREP,	/* Prepare for inserting bytes. */
772     STATE_INS,		/* Insert a byte in the bad word. */
773     STATE_SWAP,		/* Swap two bytes. */
774     STATE_UNSWAP,	/* Undo swap two characters. */
775     STATE_SWAP3,	/* Swap two characters over three. */
776     STATE_UNSWAP3,	/* Undo Swap two characters over three. */
777     STATE_UNROT3L,	/* Undo rotate three characters left */
778     STATE_UNROT3R,	/* Undo rotate three characters right */
779     STATE_REP_INI,	/* Prepare for using REP items. */
780     STATE_REP,		/* Use matching REP items from the .aff file. */
781     STATE_REP_UNDO,	/* Undo a REP item replacement. */
782     STATE_FINAL		/* End of this node. */
783 } state_T;
784 
785 /*
786  * Struct to keep the state at each level in suggest_try_change().
787  */
788 typedef struct trystate_S
789 {
790     state_T	ts_state;	/* state at this level, STATE_ */
791     int		ts_score;	/* score */
792     idx_T	ts_arridx;	/* index in tree array, start of node */
793     short	ts_curi;	/* index in list of child nodes */
794     char_u	ts_fidx;	/* index in fword[], case-folded bad word */
795     char_u	ts_fidxtry;	/* ts_fidx at which bytes may be changed */
796     char_u	ts_twordlen;	/* valid length of tword[] */
797     char_u	ts_prefixdepth;	/* stack depth for end of prefix or
798 				 * PFD_PREFIXTREE or PFD_NOPREFIX */
799     char_u	ts_flags;	/* TSF_ flags */
800 #ifdef FEAT_MBYTE
801     char_u	ts_tcharlen;	/* number of bytes in tword character */
802     char_u	ts_tcharidx;	/* current byte index in tword character */
803     char_u	ts_isdiff;	/* DIFF_ values */
804     char_u	ts_fcharstart;	/* index in fword where badword char started */
805 #endif
806     char_u	ts_prewordlen;	/* length of word in "preword[]" */
807     char_u	ts_splitoff;	/* index in "tword" after last split */
808     char_u	ts_splitfidx;	/* "ts_fidx" at word split */
809     char_u	ts_complen;	/* nr of compound words used */
810     char_u	ts_compsplit;	/* index for "compflags" where word was spit */
811     char_u	ts_save_badflags;   /* su_badflags saved here */
812     char_u	ts_delidx;	/* index in fword for char that was deleted,
813 				   valid when "ts_flags" has TSF_DIDDEL */
814 } trystate_T;
815 
816 /* values for ts_isdiff */
817 #define DIFF_NONE	0	/* no different byte (yet) */
818 #define DIFF_YES	1	/* different byte found */
819 #define DIFF_INSERT	2	/* inserting character */
820 
821 /* values for ts_flags */
822 #define TSF_PREFIXOK	1	/* already checked that prefix is OK */
823 #define TSF_DIDSPLIT	2	/* tried split at this point */
824 #define TSF_DIDDEL	4	/* did a delete, "ts_delidx" has index */
825 
826 /* special values ts_prefixdepth */
827 #define PFD_NOPREFIX	0xff	/* not using prefixes */
828 #define PFD_PREFIXTREE	0xfe	/* walking through the prefix tree */
829 #define PFD_NOTSPECIAL	0xfd	/* highest value that's not special */
830 
831 /* mode values for find_word */
832 #define FIND_FOLDWORD	    0	/* find word case-folded */
833 #define FIND_KEEPWORD	    1	/* find keep-case word */
834 #define FIND_PREFIX	    2	/* find word after prefix */
835 #define FIND_COMPOUND	    3	/* find case-folded compound word */
836 #define FIND_KEEPCOMPOUND   4	/* find keep-case compound word */
837 
838 static slang_T *slang_alloc __ARGS((char_u *lang));
839 static void slang_free __ARGS((slang_T *lp));
840 static void slang_clear __ARGS((slang_T *lp));
841 static void slang_clear_sug __ARGS((slang_T *lp));
842 static void find_word __ARGS((matchinf_T *mip, int mode));
843 static int match_checkcompoundpattern __ARGS((char_u *ptr, int wlen, garray_T *gap));
844 static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags));
845 static int can_be_compound __ARGS((trystate_T *sp, slang_T *slang, char_u *compflags, int flag));
846 static int match_compoundrule __ARGS((slang_T *slang, char_u *compflags));
847 static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req));
848 static void find_prefix __ARGS((matchinf_T *mip, int mode));
849 static int fold_more __ARGS((matchinf_T *mip));
850 static int spell_valid_case __ARGS((int wordflags, int treeflags));
851 static int no_spell_checking __ARGS((win_T *wp));
852 static void spell_load_lang __ARGS((char_u *lang));
853 static char_u *spell_enc __ARGS((void));
854 static void int_wordlist_spl __ARGS((char_u *fname));
855 static void spell_load_cb __ARGS((char_u *fname, void *cookie));
856 static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent));
857 static int get2c __ARGS((FILE *fd));
858 static int get3c __ARGS((FILE *fd));
859 static int get4c __ARGS((FILE *fd));
860 static time_t get8c __ARGS((FILE *fd));
861 static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *lenp));
862 static char_u *read_string __ARGS((FILE *fd, int cnt));
863 static int read_region_section __ARGS((FILE *fd, slang_T *slang, int len));
864 static int read_charflags_section __ARGS((FILE *fd));
865 static int read_prefcond_section __ARGS((FILE *fd, slang_T *lp));
866 static int read_rep_section __ARGS((FILE *fd, garray_T *gap, short *first));
867 static int read_sal_section __ARGS((FILE *fd, slang_T *slang));
868 static int read_words_section __ARGS((FILE *fd, slang_T *lp, int len));
869 static void count_common_word __ARGS((slang_T *lp, char_u *word, int len, int count));
870 static int score_wordcount_adj __ARGS((slang_T *slang, int score, char_u *word, int split));
871 static int read_sofo_section __ARGS((FILE *fd, slang_T *slang));
872 static int read_compound __ARGS((FILE *fd, slang_T *slang, int len));
873 static int byte_in_str __ARGS((char_u *str, int byte));
874 static int init_syl_tab __ARGS((slang_T *slang));
875 static int count_syllables __ARGS((slang_T *slang, char_u *word));
876 static int set_sofo __ARGS((slang_T *lp, char_u *from, char_u *to));
877 static void set_sal_first __ARGS((slang_T *lp));
878 #ifdef FEAT_MBYTE
879 static int *mb_str2wide __ARGS((char_u *s));
880 #endif
881 static int spell_read_tree __ARGS((FILE *fd, char_u **bytsp, idx_T **idxsp, int prefixtree, int prefixcnt));
882 static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, int startidx, int prefixtree, int maxprefcondnr));
883 static void clear_midword __ARGS((buf_T *buf));
884 static void use_midword __ARGS((slang_T *lp, buf_T *buf));
885 static int find_region __ARGS((char_u *rp, char_u *region));
886 static int captype __ARGS((char_u *word, char_u *end));
887 static int badword_captype __ARGS((char_u *word, char_u *end));
888 static void spell_reload_one __ARGS((char_u *fname, int added_word));
889 static void set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp));
890 static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp));
891 static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen));
892 static int check_need_cap __ARGS((linenr_T lnum, colnr_T col));
893 static void spell_find_suggest __ARGS((char_u *badptr, int badlen, suginfo_T *su, int maxcount, int banbadword, int need_cap, int interactive));
894 #ifdef FEAT_EVAL
895 static void spell_suggest_expr __ARGS((suginfo_T *su, char_u *expr));
896 #endif
897 static void spell_suggest_file __ARGS((suginfo_T *su, char_u *fname));
898 static void spell_suggest_intern __ARGS((suginfo_T *su, int interactive));
899 static void suggest_load_files __ARGS((void));
900 static void tree_count_words __ARGS((char_u *byts, idx_T *idxs));
901 static void spell_find_cleanup __ARGS((suginfo_T *su));
902 static void onecap_copy __ARGS((char_u *word, char_u *wcopy, int upper));
903 static void allcap_copy __ARGS((char_u *word, char_u *wcopy));
904 static void suggest_try_special __ARGS((suginfo_T *su));
905 static void suggest_try_change __ARGS((suginfo_T *su));
906 static void suggest_trie_walk __ARGS((suginfo_T *su, langp_T *lp, char_u *fword, int soundfold));
907 static void go_deeper __ARGS((trystate_T *stack, int depth, int score_add));
908 #ifdef FEAT_MBYTE
909 static int nofold_len __ARGS((char_u *fword, int flen, char_u *word));
910 #endif
911 static void find_keepcap_word __ARGS((slang_T *slang, char_u *fword, char_u *kword));
912 static void score_comp_sal __ARGS((suginfo_T *su));
913 static void score_combine __ARGS((suginfo_T *su));
914 static int stp_sal_score __ARGS((suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *badsound));
915 static void suggest_try_soundalike_prep __ARGS((void));
916 static void suggest_try_soundalike __ARGS((suginfo_T *su));
917 static void suggest_try_soundalike_finish __ARGS((void));
918 static void add_sound_suggest __ARGS((suginfo_T *su, char_u *goodword, int score, langp_T *lp));
919 static int soundfold_find __ARGS((slang_T *slang, char_u *word));
920 static void make_case_word __ARGS((char_u *fword, char_u *cword, int flags));
921 static void set_map_str __ARGS((slang_T *lp, char_u *map));
922 static int similar_chars __ARGS((slang_T *slang, int c1, int c2));
923 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, int maxsf));
924 static void check_suggestions __ARGS((suginfo_T *su, garray_T *gap));
925 static void add_banned __ARGS((suginfo_T *su, char_u *word));
926 static void rescore_suggestions __ARGS((suginfo_T *su));
927 static void rescore_one __ARGS((suginfo_T *su, suggest_T *stp));
928 static int cleanup_suggestions __ARGS((garray_T *gap, int maxscore, int keep));
929 static void spell_soundfold __ARGS((slang_T *slang, char_u *inword, int folded, char_u *res));
930 static void spell_soundfold_sofo __ARGS((slang_T *slang, char_u *inword, char_u *res));
931 static void spell_soundfold_sal __ARGS((slang_T *slang, char_u *inword, char_u *res));
932 #ifdef FEAT_MBYTE
933 static void spell_soundfold_wsal __ARGS((slang_T *slang, char_u *inword, char_u *res));
934 #endif
935 static int soundalike_score __ARGS((char_u *goodsound, char_u *badsound));
936 static int spell_edit_score __ARGS((slang_T *slang, char_u *badword, char_u *goodword));
937 static int spell_edit_score_limit __ARGS((slang_T *slang, char_u *badword, char_u *goodword, int limit));
938 #ifdef FEAT_MBYTE
939 static int spell_edit_score_limit_w __ARGS((slang_T *slang, char_u *badword, char_u *goodword, int limit));
940 #endif
941 static void dump_word __ARGS((slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T lnum));
942 static linenr_T dump_prefixes __ARGS((slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T startlnum));
943 static buf_T *open_spellbuf __ARGS((void));
944 static void close_spellbuf __ARGS((buf_T *buf));
945 
946 /*
947  * Use our own character-case definitions, because the current locale may
948  * differ from what the .spl file uses.
949  * These must not be called with negative number!
950  */
951 #ifndef FEAT_MBYTE
952 /* Non-multi-byte implementation. */
953 # define SPELL_TOFOLD(c) ((c) < 256 ? (int)spelltab.st_fold[c] : (c))
954 # define SPELL_TOUPPER(c) ((c) < 256 ? (int)spelltab.st_upper[c] : (c))
955 # define SPELL_ISUPPER(c) ((c) < 256 ? spelltab.st_isu[c] : FALSE)
956 #else
957 # if defined(HAVE_WCHAR_H)
958 #  include <wchar.h>	    /* for towupper() and towlower() */
959 # endif
960 /* Multi-byte implementation.  For Unicode we can call utf_*(), but don't do
961  * that for ASCII, because we don't want to use 'casemap' here.  Otherwise use
962  * the "w" library function for characters above 255 if available. */
963 # ifdef HAVE_TOWLOWER
964 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
965 	    : (c) < 256 ? (int)spelltab.st_fold[c] : (int)towlower(c))
966 # else
967 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
968 	    : (c) < 256 ? (int)spelltab.st_fold[c] : (c))
969 # endif
970 
971 # ifdef HAVE_TOWUPPER
972 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
973 	    : (c) < 256 ? (int)spelltab.st_upper[c] : (int)towupper(c))
974 # else
975 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
976 	    : (c) < 256 ? (int)spelltab.st_upper[c] : (c))
977 # endif
978 
979 # ifdef HAVE_ISWUPPER
980 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
981 	    : (c) < 256 ? spelltab.st_isu[c] : iswupper(c))
982 # else
983 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
984 	    : (c) < 256 ? spelltab.st_isu[c] : (FALSE))
985 # endif
986 #endif
987 
988 
989 static char *e_format = N_("E759: Format error in spell file");
990 static char *e_spell_trunc = N_("E758: Truncated spell file");
991 static char *e_afftrailing = N_("Trailing text in %s line %d: %s");
992 static char *e_affname = N_("Affix name too long in %s line %d: %s");
993 static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP");
994 static char *e_affrange = N_("E762: Character in FOL, LOW or UPP is out of range");
995 static char *msg_compressing = N_("Compressing word tree...");
996 
997 /* Remember what "z?" replaced. */
998 static char_u	*repl_from = NULL;
999 static char_u	*repl_to = NULL;
1000 
1001 /*
1002  * Main spell-checking function.
1003  * "ptr" points to a character that could be the start of a word.
1004  * "*attrp" is set to the highlight index for a badly spelled word.  For a
1005  * non-word or when it's OK it remains unchanged.
1006  * This must only be called when 'spelllang' is not empty.
1007  *
1008  * "capcol" is used to check for a Capitalised word after the end of a
1009  * sentence.  If it's zero then perform the check.  Return the column where to
1010  * check next, or -1 when no sentence end was found.  If it's NULL then don't
1011  * worry.
1012  *
1013  * Returns the length of the word in bytes, also when it's OK, so that the
1014  * caller can skip over the word.
1015  */
1016     int
1017 spell_check(wp, ptr, attrp, capcol, docount)
1018     win_T	*wp;		/* current window */
1019     char_u	*ptr;
1020     hlf_T	*attrp;
1021     int		*capcol;	/* column to check for Capital */
1022     int		docount;	/* count good words */
1023 {
1024     matchinf_T	mi;		/* Most things are put in "mi" so that it can
1025 				   be passed to functions quickly. */
1026     int		nrlen = 0;	/* found a number first */
1027     int		c;
1028     int		wrongcaplen = 0;
1029     int		lpi;
1030     int		count_word = docount;
1031 
1032     /* A word never starts at a space or a control character.  Return quickly
1033      * then, skipping over the character. */
1034     if (*ptr <= ' ')
1035 	return 1;
1036 
1037     /* Return here when loading language files failed. */
1038     if (wp->w_buffer->b_langp.ga_len == 0)
1039 	return 1;
1040 
1041     vim_memset(&mi, 0, sizeof(matchinf_T));
1042 
1043     /* A number is always OK.  Also skip hexadecimal numbers 0xFF99 and
1044      * 0X99FF.  But always do check spelling to find "3GPP" and "11
1045      * julifeest". */
1046     if (*ptr >= '0' && *ptr <= '9')
1047     {
1048 	if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
1049 	    mi.mi_end = skiphex(ptr + 2);
1050 	else
1051 	    mi.mi_end = skipdigits(ptr);
1052 	nrlen = (int)(mi.mi_end - ptr);
1053     }
1054 
1055     /* Find the normal end of the word (until the next non-word character). */
1056     mi.mi_word = ptr;
1057     mi.mi_fend = ptr;
1058     if (spell_iswordp(mi.mi_fend, wp->w_buffer))
1059     {
1060 	do
1061 	{
1062 	    mb_ptr_adv(mi.mi_fend);
1063 	} while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp->w_buffer));
1064 
1065 	if (capcol != NULL && *capcol == 0 && wp->w_buffer->b_cap_prog != NULL)
1066 	{
1067 	    /* Check word starting with capital letter. */
1068 	    c = PTR2CHAR(ptr);
1069 	    if (!SPELL_ISUPPER(c))
1070 		wrongcaplen = (int)(mi.mi_fend - ptr);
1071 	}
1072     }
1073     if (capcol != NULL)
1074 	*capcol = -1;
1075 
1076     /* We always use the characters up to the next non-word character,
1077      * also for bad words. */
1078     mi.mi_end = mi.mi_fend;
1079 
1080     /* Check caps type later. */
1081     mi.mi_buf = wp->w_buffer;
1082 
1083     /* case-fold the word with one non-word character, so that we can check
1084      * for the word end. */
1085     if (*mi.mi_fend != NUL)
1086 	mb_ptr_adv(mi.mi_fend);
1087 
1088     (void)spell_casefold(ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
1089 							     MAXWLEN + 1);
1090     mi.mi_fwordlen = (int)STRLEN(mi.mi_fword);
1091 
1092     /* The word is bad unless we recognize it. */
1093     mi.mi_result = SP_BAD;
1094     mi.mi_result2 = SP_BAD;
1095 
1096     /*
1097      * Loop over the languages specified in 'spelllang'.
1098      * We check them all, because a word may be matched longer in another
1099      * language.
1100      */
1101     for (lpi = 0; lpi < wp->w_buffer->b_langp.ga_len; ++lpi)
1102     {
1103 	mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi);
1104 
1105 	/* If reloading fails the language is still in the list but everything
1106 	 * has been cleared. */
1107 	if (mi.mi_lp->lp_slang->sl_fidxs == NULL)
1108 	    continue;
1109 
1110 	/* Check for a matching word in case-folded words. */
1111 	find_word(&mi, FIND_FOLDWORD);
1112 
1113 	/* Check for a matching word in keep-case words. */
1114 	find_word(&mi, FIND_KEEPWORD);
1115 
1116 	/* Check for matching prefixes. */
1117 	find_prefix(&mi, FIND_FOLDWORD);
1118 
1119 	/* For a NOBREAK language, may want to use a word without a following
1120 	 * word as a backup. */
1121 	if (mi.mi_lp->lp_slang->sl_nobreak && mi.mi_result == SP_BAD
1122 						   && mi.mi_result2 != SP_BAD)
1123 	{
1124 	    mi.mi_result = mi.mi_result2;
1125 	    mi.mi_end = mi.mi_end2;
1126 	}
1127 
1128 	/* Count the word in the first language where it's found to be OK. */
1129 	if (count_word && mi.mi_result == SP_OK)
1130 	{
1131 	    count_common_word(mi.mi_lp->lp_slang, ptr,
1132 						   (int)(mi.mi_end - ptr), 1);
1133 	    count_word = FALSE;
1134 	}
1135     }
1136 
1137     if (mi.mi_result != SP_OK)
1138     {
1139 	/* If we found a number skip over it.  Allows for "42nd".  Do flag
1140 	 * rare and local words, e.g., "3GPP". */
1141 	if (nrlen > 0)
1142 	{
1143 	    if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
1144 		return nrlen;
1145 	}
1146 
1147 	/* When we are at a non-word character there is no error, just
1148 	 * skip over the character (try looking for a word after it). */
1149 	else if (!spell_iswordp_nmw(ptr))
1150 	{
1151 	    if (capcol != NULL && wp->w_buffer->b_cap_prog != NULL)
1152 	    {
1153 		regmatch_T	regmatch;
1154 
1155 		/* Check for end of sentence. */
1156 		regmatch.regprog = wp->w_buffer->b_cap_prog;
1157 		regmatch.rm_ic = FALSE;
1158 		if (vim_regexec(&regmatch, ptr, 0))
1159 		    *capcol = (int)(regmatch.endp[0] - ptr);
1160 	    }
1161 
1162 #ifdef FEAT_MBYTE
1163 	    if (has_mbyte)
1164 		return (*mb_ptr2len)(ptr);
1165 #endif
1166 	    return 1;
1167 	}
1168 	else if (mi.mi_end == ptr)
1169 	    /* Always include at least one character.  Required for when there
1170 	     * is a mixup in "midword". */
1171 	    mb_ptr_adv(mi.mi_end);
1172 	else if (mi.mi_result == SP_BAD
1173 		&& LANGP_ENTRY(wp->w_buffer->b_langp, 0)->lp_slang->sl_nobreak)
1174 	{
1175 	    char_u	*p, *fp;
1176 	    int		save_result = mi.mi_result;
1177 
1178 	    /* First language in 'spelllang' is NOBREAK.  Find first position
1179 	     * at which any word would be valid. */
1180 	    mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
1181 	    if (mi.mi_lp->lp_slang->sl_fidxs != NULL)
1182 	    {
1183 		p = mi.mi_word;
1184 		fp = mi.mi_fword;
1185 		for (;;)
1186 		{
1187 		    mb_ptr_adv(p);
1188 		    mb_ptr_adv(fp);
1189 		    if (p >= mi.mi_end)
1190 			break;
1191 		    mi.mi_compoff = (int)(fp - mi.mi_fword);
1192 		    find_word(&mi, FIND_COMPOUND);
1193 		    if (mi.mi_result != SP_BAD)
1194 		    {
1195 			mi.mi_end = p;
1196 			break;
1197 		    }
1198 		}
1199 		mi.mi_result = save_result;
1200 	    }
1201 	}
1202 
1203 	if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
1204 	    *attrp = HLF_SPB;
1205 	else if (mi.mi_result == SP_RARE)
1206 	    *attrp = HLF_SPR;
1207 	else
1208 	    *attrp = HLF_SPL;
1209     }
1210 
1211     if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE))
1212     {
1213 	/* Report SpellCap only when the word isn't badly spelled. */
1214 	*attrp = HLF_SPC;
1215 	return wrongcaplen;
1216     }
1217 
1218     return (int)(mi.mi_end - ptr);
1219 }
1220 
1221 /*
1222  * Check if the word at "mip->mi_word" is in the tree.
1223  * When "mode" is FIND_FOLDWORD check in fold-case word tree.
1224  * When "mode" is FIND_KEEPWORD check in keep-case word tree.
1225  * When "mode" is FIND_PREFIX check for word after prefix in fold-case word
1226  * tree.
1227  *
1228  * For a match mip->mi_result is updated.
1229  */
1230     static void
1231 find_word(mip, mode)
1232     matchinf_T	*mip;
1233     int		mode;
1234 {
1235     idx_T	arridx = 0;
1236     int		endlen[MAXWLEN];    /* length at possible word endings */
1237     idx_T	endidx[MAXWLEN];    /* possible word endings */
1238     int		endidxcnt = 0;
1239     int		len;
1240     int		wlen = 0;
1241     int		flen;
1242     int		c;
1243     char_u	*ptr;
1244     idx_T	lo, hi, m;
1245 #ifdef FEAT_MBYTE
1246     char_u	*s;
1247 #endif
1248     char_u	*p;
1249     int		res = SP_BAD;
1250     slang_T	*slang = mip->mi_lp->lp_slang;
1251     unsigned	flags;
1252     char_u	*byts;
1253     idx_T	*idxs;
1254     int		word_ends;
1255     int		prefix_found;
1256     int		nobreak_result;
1257 
1258     if (mode == FIND_KEEPWORD || mode == FIND_KEEPCOMPOUND)
1259     {
1260 	/* Check for word with matching case in keep-case tree. */
1261 	ptr = mip->mi_word;
1262 	flen = 9999;		    /* no case folding, always enough bytes */
1263 	byts = slang->sl_kbyts;
1264 	idxs = slang->sl_kidxs;
1265 
1266 	if (mode == FIND_KEEPCOMPOUND)
1267 	    /* Skip over the previously found word(s). */
1268 	    wlen += mip->mi_compoff;
1269     }
1270     else
1271     {
1272 	/* Check for case-folded in case-folded tree. */
1273 	ptr = mip->mi_fword;
1274 	flen = mip->mi_fwordlen;    /* available case-folded bytes */
1275 	byts = slang->sl_fbyts;
1276 	idxs = slang->sl_fidxs;
1277 
1278 	if (mode == FIND_PREFIX)
1279 	{
1280 	    /* Skip over the prefix. */
1281 	    wlen = mip->mi_prefixlen;
1282 	    flen -= mip->mi_prefixlen;
1283 	}
1284 	else if (mode == FIND_COMPOUND)
1285 	{
1286 	    /* Skip over the previously found word(s). */
1287 	    wlen = mip->mi_compoff;
1288 	    flen -= mip->mi_compoff;
1289 	}
1290 
1291     }
1292 
1293     if (byts == NULL)
1294 	return;			/* array is empty */
1295 
1296     /*
1297      * Repeat advancing in the tree until:
1298      * - there is a byte that doesn't match,
1299      * - we reach the end of the tree,
1300      * - or we reach the end of the line.
1301      */
1302     for (;;)
1303     {
1304 	if (flen <= 0 && *mip->mi_fend != NUL)
1305 	    flen = fold_more(mip);
1306 
1307 	len = byts[arridx++];
1308 
1309 	/* If the first possible byte is a zero the word could end here.
1310 	 * Remember this index, we first check for the longest word. */
1311 	if (byts[arridx] == 0)
1312 	{
1313 	    if (endidxcnt == MAXWLEN)
1314 	    {
1315 		/* Must be a corrupted spell file. */
1316 		EMSG(_(e_format));
1317 		return;
1318 	    }
1319 	    endlen[endidxcnt] = wlen;
1320 	    endidx[endidxcnt++] = arridx++;
1321 	    --len;
1322 
1323 	    /* Skip over the zeros, there can be several flag/region
1324 	     * combinations. */
1325 	    while (len > 0 && byts[arridx] == 0)
1326 	    {
1327 		++arridx;
1328 		--len;
1329 	    }
1330 	    if (len == 0)
1331 		break;	    /* no children, word must end here */
1332 	}
1333 
1334 	/* Stop looking at end of the line. */
1335 	if (ptr[wlen] == NUL)
1336 	    break;
1337 
1338 	/* Perform a binary search in the list of accepted bytes. */
1339 	c = ptr[wlen];
1340 	if (c == TAB)	    /* <Tab> is handled like <Space> */
1341 	    c = ' ';
1342 	lo = arridx;
1343 	hi = arridx + len - 1;
1344 	while (lo < hi)
1345 	{
1346 	    m = (lo + hi) / 2;
1347 	    if (byts[m] > c)
1348 		hi = m - 1;
1349 	    else if (byts[m] < c)
1350 		lo = m + 1;
1351 	    else
1352 	    {
1353 		lo = hi = m;
1354 		break;
1355 	    }
1356 	}
1357 
1358 	/* Stop if there is no matching byte. */
1359 	if (hi < lo || byts[lo] != c)
1360 	    break;
1361 
1362 	/* Continue at the child (if there is one). */
1363 	arridx = idxs[lo];
1364 	++wlen;
1365 	--flen;
1366 
1367 	/* One space in the good word may stand for several spaces in the
1368 	 * checked word. */
1369 	if (c == ' ')
1370 	{
1371 	    for (;;)
1372 	    {
1373 		if (flen <= 0 && *mip->mi_fend != NUL)
1374 		    flen = fold_more(mip);
1375 		if (ptr[wlen] != ' ' && ptr[wlen] != TAB)
1376 		    break;
1377 		++wlen;
1378 		--flen;
1379 	    }
1380 	}
1381     }
1382 
1383     /*
1384      * Verify that one of the possible endings is valid.  Try the longest
1385      * first.
1386      */
1387     while (endidxcnt > 0)
1388     {
1389 	--endidxcnt;
1390 	arridx = endidx[endidxcnt];
1391 	wlen = endlen[endidxcnt];
1392 
1393 #ifdef FEAT_MBYTE
1394 	if ((*mb_head_off)(ptr, ptr + wlen) > 0)
1395 	    continue;	    /* not at first byte of character */
1396 #endif
1397 	if (spell_iswordp(ptr + wlen, mip->mi_buf))
1398 	{
1399 	    if (slang->sl_compprog == NULL && !slang->sl_nobreak)
1400 		continue;	    /* next char is a word character */
1401 	    word_ends = FALSE;
1402 	}
1403 	else
1404 	    word_ends = TRUE;
1405 	/* The prefix flag is before compound flags.  Once a valid prefix flag
1406 	 * has been found we try compound flags. */
1407 	prefix_found = FALSE;
1408 
1409 #ifdef FEAT_MBYTE
1410 	if (mode != FIND_KEEPWORD && has_mbyte)
1411 	{
1412 	    /* Compute byte length in original word, length may change
1413 	     * when folding case.  This can be slow, take a shortcut when the
1414 	     * case-folded word is equal to the keep-case word. */
1415 	    p = mip->mi_word;
1416 	    if (STRNCMP(ptr, p, wlen) != 0)
1417 	    {
1418 		for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1419 		    mb_ptr_adv(p);
1420 		wlen = (int)(p - mip->mi_word);
1421 	    }
1422 	}
1423 #endif
1424 
1425 	/* Check flags and region.  For FIND_PREFIX check the condition and
1426 	 * prefix ID.
1427 	 * Repeat this if there are more flags/region alternatives until there
1428 	 * is a match. */
1429 	res = SP_BAD;
1430 	for (len = byts[arridx - 1]; len > 0 && byts[arridx] == 0;
1431 							      --len, ++arridx)
1432 	{
1433 	    flags = idxs[arridx];
1434 
1435 	    /* For the fold-case tree check that the case of the checked word
1436 	     * matches with what the word in the tree requires.
1437 	     * For keep-case tree the case is always right.  For prefixes we
1438 	     * don't bother to check. */
1439 	    if (mode == FIND_FOLDWORD)
1440 	    {
1441 		if (mip->mi_cend != mip->mi_word + wlen)
1442 		{
1443 		    /* mi_capflags was set for a different word length, need
1444 		     * to do it again. */
1445 		    mip->mi_cend = mip->mi_word + wlen;
1446 		    mip->mi_capflags = captype(mip->mi_word, mip->mi_cend);
1447 		}
1448 
1449 		if (mip->mi_capflags == WF_KEEPCAP
1450 				|| !spell_valid_case(mip->mi_capflags, flags))
1451 		    continue;
1452 	    }
1453 
1454 	    /* When mode is FIND_PREFIX the word must support the prefix:
1455 	     * check the prefix ID and the condition.  Do that for the list at
1456 	     * mip->mi_prefarridx that find_prefix() filled. */
1457 	    else if (mode == FIND_PREFIX && !prefix_found)
1458 	    {
1459 		c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
1460 				    flags,
1461 				    mip->mi_word + mip->mi_cprefixlen, slang,
1462 				    FALSE);
1463 		if (c == 0)
1464 		    continue;
1465 
1466 		/* Use the WF_RARE flag for a rare prefix. */
1467 		if (c & WF_RAREPFX)
1468 		    flags |= WF_RARE;
1469 		prefix_found = TRUE;
1470 	    }
1471 
1472 	    if (slang->sl_nobreak)
1473 	    {
1474 		if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND)
1475 			&& (flags & WF_BANNED) == 0)
1476 		{
1477 		    /* NOBREAK: found a valid following word.  That's all we
1478 		     * need to know, so return. */
1479 		    mip->mi_result = SP_OK;
1480 		    break;
1481 		}
1482 	    }
1483 
1484 	    else if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND
1485 								|| !word_ends))
1486 	    {
1487 		/* If there is no compound flag or the word is shorter than
1488 		 * COMPOUNDMIN reject it quickly.
1489 		 * Makes you wonder why someone puts a compound flag on a word
1490 		 * that's too short...  Myspell compatibility requires this
1491 		 * anyway. */
1492 		if (((unsigned)flags >> 24) == 0
1493 			     || wlen - mip->mi_compoff < slang->sl_compminlen)
1494 		    continue;
1495 #ifdef FEAT_MBYTE
1496 		/* For multi-byte chars check character length against
1497 		 * COMPOUNDMIN. */
1498 		if (has_mbyte
1499 			&& slang->sl_compminlen > 0
1500 			&& mb_charlen_len(mip->mi_word + mip->mi_compoff,
1501 				wlen - mip->mi_compoff) < slang->sl_compminlen)
1502 			continue;
1503 #endif
1504 
1505 		/* Limit the number of compound words to COMPOUNDWORDMAX if no
1506 		 * maximum for syllables is specified. */
1507 		if (!word_ends && mip->mi_complen + mip->mi_compextra + 2
1508 							   > slang->sl_compmax
1509 					   && slang->sl_compsylmax == MAXWLEN)
1510 		    continue;
1511 
1512 		/* Don't allow compounding on a side where an affix was added,
1513 		 * unless COMPOUNDPERMITFLAG was used. */
1514 		if (mip->mi_complen > 0 && (flags & WF_NOCOMPBEF))
1515 		    continue;
1516 		if (!word_ends && (flags & WF_NOCOMPAFT))
1517 		    continue;
1518 
1519 		/* Quickly check if compounding is possible with this flag. */
1520 		if (!byte_in_str(mip->mi_complen == 0
1521 					? slang->sl_compstartflags
1522 					: slang->sl_compallflags,
1523 					    ((unsigned)flags >> 24)))
1524 		    continue;
1525 
1526 		/* If there is a match with a CHECKCOMPOUNDPATTERN rule
1527 		 * discard the compound word. */
1528 		if (match_checkcompoundpattern(ptr, wlen, &slang->sl_comppat))
1529 		    continue;
1530 
1531 		if (mode == FIND_COMPOUND)
1532 		{
1533 		    int	    capflags;
1534 
1535 		    /* Need to check the caps type of the appended compound
1536 		     * word. */
1537 #ifdef FEAT_MBYTE
1538 		    if (has_mbyte && STRNCMP(ptr, mip->mi_word,
1539 							mip->mi_compoff) != 0)
1540 		    {
1541 			/* case folding may have changed the length */
1542 			p = mip->mi_word;
1543 			for (s = ptr; s < ptr + mip->mi_compoff; mb_ptr_adv(s))
1544 			    mb_ptr_adv(p);
1545 		    }
1546 		    else
1547 #endif
1548 			p = mip->mi_word + mip->mi_compoff;
1549 		    capflags = captype(p, mip->mi_word + wlen);
1550 		    if (capflags == WF_KEEPCAP || (capflags == WF_ALLCAP
1551 						 && (flags & WF_FIXCAP) != 0))
1552 			continue;
1553 
1554 		    if (capflags != WF_ALLCAP)
1555 		    {
1556 			/* When the character before the word is a word
1557 			 * character we do not accept a Onecap word.  We do
1558 			 * accept a no-caps word, even when the dictionary
1559 			 * word specifies ONECAP. */
1560 			mb_ptr_back(mip->mi_word, p);
1561 			if (spell_iswordp_nmw(p)
1562 				? capflags == WF_ONECAP
1563 				: (flags & WF_ONECAP) != 0
1564 						     && capflags != WF_ONECAP)
1565 			    continue;
1566 		    }
1567 		}
1568 
1569 		/* If the word ends the sequence of compound flags of the
1570 		 * words must match with one of the COMPOUNDRULE items and
1571 		 * the number of syllables must not be too large. */
1572 		mip->mi_compflags[mip->mi_complen] = ((unsigned)flags >> 24);
1573 		mip->mi_compflags[mip->mi_complen + 1] = NUL;
1574 		if (word_ends)
1575 		{
1576 		    char_u	fword[MAXWLEN];
1577 
1578 		    if (slang->sl_compsylmax < MAXWLEN)
1579 		    {
1580 			/* "fword" is only needed for checking syllables. */
1581 			if (ptr == mip->mi_word)
1582 			    (void)spell_casefold(ptr, wlen, fword, MAXWLEN);
1583 			else
1584 			    vim_strncpy(fword, ptr, endlen[endidxcnt]);
1585 		    }
1586 		    if (!can_compound(slang, fword, mip->mi_compflags))
1587 			continue;
1588 		}
1589 		else if (slang->sl_comprules != NULL
1590 			     && !match_compoundrule(slang, mip->mi_compflags))
1591 		    /* The compound flags collected so far do not match any
1592 		     * COMPOUNDRULE, discard the compounded word. */
1593 		    continue;
1594 	    }
1595 
1596 	    /* Check NEEDCOMPOUND: can't use word without compounding. */
1597 	    else if (flags & WF_NEEDCOMP)
1598 		continue;
1599 
1600 	    nobreak_result = SP_OK;
1601 
1602 	    if (!word_ends)
1603 	    {
1604 		int	save_result = mip->mi_result;
1605 		char_u	*save_end = mip->mi_end;
1606 		langp_T	*save_lp = mip->mi_lp;
1607 		int	lpi;
1608 
1609 		/* Check that a valid word follows.  If there is one and we
1610 		 * are compounding, it will set "mi_result", thus we are
1611 		 * always finished here.  For NOBREAK we only check that a
1612 		 * valid word follows.
1613 		 * Recursive! */
1614 		if (slang->sl_nobreak)
1615 		    mip->mi_result = SP_BAD;
1616 
1617 		/* Find following word in case-folded tree. */
1618 		mip->mi_compoff = endlen[endidxcnt];
1619 #ifdef FEAT_MBYTE
1620 		if (has_mbyte && mode == FIND_KEEPWORD)
1621 		{
1622 		    /* Compute byte length in case-folded word from "wlen":
1623 		     * byte length in keep-case word.  Length may change when
1624 		     * folding case.  This can be slow, take a shortcut when
1625 		     * the case-folded word is equal to the keep-case word. */
1626 		    p = mip->mi_fword;
1627 		    if (STRNCMP(ptr, p, wlen) != 0)
1628 		    {
1629 			for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1630 			    mb_ptr_adv(p);
1631 			mip->mi_compoff = (int)(p - mip->mi_fword);
1632 		    }
1633 		}
1634 #endif
1635 		c = mip->mi_compoff;
1636 		++mip->mi_complen;
1637 		if (flags & WF_COMPROOT)
1638 		    ++mip->mi_compextra;
1639 
1640 		/* For NOBREAK we need to try all NOBREAK languages, at least
1641 		 * to find the ".add" file(s). */
1642 		for (lpi = 0; lpi < mip->mi_buf->b_langp.ga_len; ++lpi)
1643 		{
1644 		    if (slang->sl_nobreak)
1645 		    {
1646 			mip->mi_lp = LANGP_ENTRY(mip->mi_buf->b_langp, lpi);
1647 			if (mip->mi_lp->lp_slang->sl_fidxs == NULL
1648 					 || !mip->mi_lp->lp_slang->sl_nobreak)
1649 			    continue;
1650 		    }
1651 
1652 		    find_word(mip, FIND_COMPOUND);
1653 
1654 		    /* When NOBREAK any word that matches is OK.  Otherwise we
1655 		     * need to find the longest match, thus try with keep-case
1656 		     * and prefix too. */
1657 		    if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1658 		    {
1659 			/* Find following word in keep-case tree. */
1660 			mip->mi_compoff = wlen;
1661 			find_word(mip, FIND_KEEPCOMPOUND);
1662 
1663 #if 0	    /* Disabled, a prefix must not appear halfway a compound word,
1664 	       unless the COMPOUNDPERMITFLAG is used and then it can't be a
1665 	       postponed prefix. */
1666 			if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1667 			{
1668 			    /* Check for following word with prefix. */
1669 			    mip->mi_compoff = c;
1670 			    find_prefix(mip, FIND_COMPOUND);
1671 			}
1672 #endif
1673 		    }
1674 
1675 		    if (!slang->sl_nobreak)
1676 			break;
1677 		}
1678 		--mip->mi_complen;
1679 		if (flags & WF_COMPROOT)
1680 		    --mip->mi_compextra;
1681 		mip->mi_lp = save_lp;
1682 
1683 		if (slang->sl_nobreak)
1684 		{
1685 		    nobreak_result = mip->mi_result;
1686 		    mip->mi_result = save_result;
1687 		    mip->mi_end = save_end;
1688 		}
1689 		else
1690 		{
1691 		    if (mip->mi_result == SP_OK)
1692 			break;
1693 		    continue;
1694 		}
1695 	    }
1696 
1697 	    if (flags & WF_BANNED)
1698 		res = SP_BANNED;
1699 	    else if (flags & WF_REGION)
1700 	    {
1701 		/* Check region. */
1702 		if ((mip->mi_lp->lp_region & (flags >> 16)) != 0)
1703 		    res = SP_OK;
1704 		else
1705 		    res = SP_LOCAL;
1706 	    }
1707 	    else if (flags & WF_RARE)
1708 		res = SP_RARE;
1709 	    else
1710 		res = SP_OK;
1711 
1712 	    /* Always use the longest match and the best result.  For NOBREAK
1713 	     * we separately keep the longest match without a following good
1714 	     * word as a fall-back. */
1715 	    if (nobreak_result == SP_BAD)
1716 	    {
1717 		if (mip->mi_result2 > res)
1718 		{
1719 		    mip->mi_result2 = res;
1720 		    mip->mi_end2 = mip->mi_word + wlen;
1721 		}
1722 		else if (mip->mi_result2 == res
1723 					&& mip->mi_end2 < mip->mi_word + wlen)
1724 		    mip->mi_end2 = mip->mi_word + wlen;
1725 	    }
1726 	    else if (mip->mi_result > res)
1727 	    {
1728 		mip->mi_result = res;
1729 		mip->mi_end = mip->mi_word + wlen;
1730 	    }
1731 	    else if (mip->mi_result == res && mip->mi_end < mip->mi_word + wlen)
1732 		mip->mi_end = mip->mi_word + wlen;
1733 
1734 	    if (mip->mi_result == SP_OK)
1735 		break;
1736 	}
1737 
1738 	if (mip->mi_result == SP_OK)
1739 	    break;
1740     }
1741 }
1742 
1743 /*
1744  * Return TRUE if there is a match between the word ptr[wlen] and
1745  * CHECKCOMPOUNDPATTERN rules, assuming that we will concatenate with another
1746  * word.
1747  * A match means that the first part of CHECKCOMPOUNDPATTERN matches at the
1748  * end of ptr[wlen] and the second part matches after it.
1749  */
1750     static int
1751 match_checkcompoundpattern(ptr, wlen, gap)
1752     char_u	*ptr;
1753     int		wlen;
1754     garray_T	*gap;  /* &sl_comppat */
1755 {
1756     int		i;
1757     char_u	*p;
1758     int		len;
1759 
1760     for (i = 0; i + 1 < gap->ga_len; i += 2)
1761     {
1762 	p = ((char_u **)gap->ga_data)[i + 1];
1763 	if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0)
1764 	{
1765 	    /* Second part matches at start of following compound word, now
1766 	     * check if first part matches at end of previous word. */
1767 	    p = ((char_u **)gap->ga_data)[i];
1768 	    len = (int)STRLEN(p);
1769 	    if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0)
1770 		return TRUE;
1771 	}
1772     }
1773     return FALSE;
1774 }
1775 
1776 /*
1777  * Return TRUE if "flags" is a valid sequence of compound flags and "word"
1778  * does not have too many syllables.
1779  */
1780     static int
1781 can_compound(slang, word, flags)
1782     slang_T	*slang;
1783     char_u	*word;
1784     char_u	*flags;
1785 {
1786     regmatch_T	regmatch;
1787 #ifdef FEAT_MBYTE
1788     char_u	uflags[MAXWLEN * 2];
1789     int		i;
1790 #endif
1791     char_u	*p;
1792 
1793     if (slang->sl_compprog == NULL)
1794 	return FALSE;
1795 #ifdef FEAT_MBYTE
1796     if (enc_utf8)
1797     {
1798 	/* Need to convert the single byte flags to utf8 characters. */
1799 	p = uflags;
1800 	for (i = 0; flags[i] != NUL; ++i)
1801 	    p += mb_char2bytes(flags[i], p);
1802 	*p = NUL;
1803 	p = uflags;
1804     }
1805     else
1806 #endif
1807 	p = flags;
1808     regmatch.regprog = slang->sl_compprog;
1809     regmatch.rm_ic = FALSE;
1810     if (!vim_regexec(&regmatch, p, 0))
1811 	return FALSE;
1812 
1813     /* Count the number of syllables.  This may be slow, do it last.  If there
1814      * are too many syllables AND the number of compound words is above
1815      * COMPOUNDWORDMAX then compounding is not allowed. */
1816     if (slang->sl_compsylmax < MAXWLEN
1817 		       && count_syllables(slang, word) > slang->sl_compsylmax)
1818 	return (int)STRLEN(flags) < slang->sl_compmax;
1819     return TRUE;
1820 }
1821 
1822 /*
1823  * Return TRUE when the sequence of flags in "compflags" plus "flag" can
1824  * possibly form a valid compounded word.  This also checks the COMPOUNDRULE
1825  * lines if they don't contain wildcards.
1826  */
1827     static int
1828 can_be_compound(sp, slang, compflags, flag)
1829     trystate_T	*sp;
1830     slang_T	*slang;
1831     char_u	*compflags;
1832     int		flag;
1833 {
1834     /* If the flag doesn't appear in sl_compstartflags or sl_compallflags
1835      * then it can't possibly compound. */
1836     if (!byte_in_str(sp->ts_complen == sp->ts_compsplit
1837 		? slang->sl_compstartflags : slang->sl_compallflags, flag))
1838 	return FALSE;
1839 
1840     /* If there are no wildcards, we can check if the flags collected so far
1841      * possibly can form a match with COMPOUNDRULE patterns.  This only
1842      * makes sense when we have two or more words. */
1843     if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit)
1844     {
1845 	int v;
1846 
1847 	compflags[sp->ts_complen] = flag;
1848 	compflags[sp->ts_complen + 1] = NUL;
1849 	v = match_compoundrule(slang, compflags + sp->ts_compsplit);
1850 	compflags[sp->ts_complen] = NUL;
1851 	return v;
1852     }
1853 
1854     return TRUE;
1855 }
1856 
1857 
1858 /*
1859  * Return TRUE if the compound flags in compflags[] match the start of any
1860  * compound rule.  This is used to stop trying a compound if the flags
1861  * collected so far can't possibly match any compound rule.
1862  * Caller must check that slang->sl_comprules is not NULL.
1863  */
1864     static int
1865 match_compoundrule(slang, compflags)
1866     slang_T	*slang;
1867     char_u	*compflags;
1868 {
1869     char_u	*p;
1870     int		i;
1871     int		c;
1872 
1873     /* loop over all the COMPOUNDRULE entries */
1874     for (p = slang->sl_comprules; *p != NUL; ++p)
1875     {
1876 	/* loop over the flags in the compound word we have made, match
1877 	 * them against the current rule entry */
1878 	for (i = 0; ; ++i)
1879 	{
1880 	    c = compflags[i];
1881 	    if (c == NUL)
1882 		/* found a rule that matches for the flags we have so far */
1883 		return TRUE;
1884 	    if (*p == '/' || *p == NUL)
1885 		break;  /* end of rule, it's too short */
1886 	    if (*p == '[')
1887 	    {
1888 		int match = FALSE;
1889 
1890 		/* compare against all the flags in [] */
1891 		++p;
1892 		while (*p != ']' && *p != NUL)
1893 		    if (*p++ == c)
1894 			match = TRUE;
1895 		if (!match)
1896 		    break;  /* none matches */
1897 	    }
1898 	    else if (*p != c)
1899 		break;  /* flag of word doesn't match flag in pattern */
1900 	    ++p;
1901 	}
1902 
1903 	/* Skip to the next "/", where the next pattern starts. */
1904 	p = vim_strchr(p, '/');
1905 	if (p == NULL)
1906 	    break;
1907     }
1908 
1909     /* Checked all the rules and none of them match the flags, so there
1910      * can't possibly be a compound starting with these flags. */
1911     return FALSE;
1912 }
1913 
1914 /*
1915  * Return non-zero if the prefix indicated by "arridx" matches with the prefix
1916  * ID in "flags" for the word "word".
1917  * The WF_RAREPFX flag is included in the return value for a rare prefix.
1918  */
1919     static int
1920 valid_word_prefix(totprefcnt, arridx, flags, word, slang, cond_req)
1921     int		totprefcnt;	/* nr of prefix IDs */
1922     int		arridx;		/* idx in sl_pidxs[] */
1923     int		flags;
1924     char_u	*word;
1925     slang_T	*slang;
1926     int		cond_req;	/* only use prefixes with a condition */
1927 {
1928     int		prefcnt;
1929     int		pidx;
1930     regprog_T	*rp;
1931     regmatch_T	regmatch;
1932     int		prefid;
1933 
1934     prefid = (unsigned)flags >> 24;
1935     for (prefcnt = totprefcnt - 1; prefcnt >= 0; --prefcnt)
1936     {
1937 	pidx = slang->sl_pidxs[arridx + prefcnt];
1938 
1939 	/* Check the prefix ID. */
1940 	if (prefid != (pidx & 0xff))
1941 	    continue;
1942 
1943 	/* Check if the prefix doesn't combine and the word already has a
1944 	 * suffix. */
1945 	if ((flags & WF_HAS_AFF) && (pidx & WF_PFX_NC))
1946 	    continue;
1947 
1948 	/* Check the condition, if there is one.  The condition index is
1949 	 * stored in the two bytes above the prefix ID byte.  */
1950 	rp = slang->sl_prefprog[((unsigned)pidx >> 8) & 0xffff];
1951 	if (rp != NULL)
1952 	{
1953 	    regmatch.regprog = rp;
1954 	    regmatch.rm_ic = FALSE;
1955 	    if (!vim_regexec(&regmatch, word, 0))
1956 		continue;
1957 	}
1958 	else if (cond_req)
1959 	    continue;
1960 
1961 	/* It's a match!  Return the WF_ flags. */
1962 	return pidx;
1963     }
1964     return 0;
1965 }
1966 
1967 /*
1968  * Check if the word at "mip->mi_word" has a matching prefix.
1969  * If it does, then check the following word.
1970  *
1971  * If "mode" is "FIND_COMPOUND" then do the same after another word, find a
1972  * prefix in a compound word.
1973  *
1974  * For a match mip->mi_result is updated.
1975  */
1976     static void
1977 find_prefix(mip, mode)
1978     matchinf_T	*mip;
1979     int		mode;
1980 {
1981     idx_T	arridx = 0;
1982     int		len;
1983     int		wlen = 0;
1984     int		flen;
1985     int		c;
1986     char_u	*ptr;
1987     idx_T	lo, hi, m;
1988     slang_T	*slang = mip->mi_lp->lp_slang;
1989     char_u	*byts;
1990     idx_T	*idxs;
1991 
1992     byts = slang->sl_pbyts;
1993     if (byts == NULL)
1994 	return;			/* array is empty */
1995 
1996     /* We use the case-folded word here, since prefixes are always
1997      * case-folded. */
1998     ptr = mip->mi_fword;
1999     flen = mip->mi_fwordlen;    /* available case-folded bytes */
2000     if (mode == FIND_COMPOUND)
2001     {
2002 	/* Skip over the previously found word(s). */
2003 	ptr += mip->mi_compoff;
2004 	flen -= mip->mi_compoff;
2005     }
2006     idxs = slang->sl_pidxs;
2007 
2008     /*
2009      * Repeat advancing in the tree until:
2010      * - there is a byte that doesn't match,
2011      * - we reach the end of the tree,
2012      * - or we reach the end of the line.
2013      */
2014     for (;;)
2015     {
2016 	if (flen == 0 && *mip->mi_fend != NUL)
2017 	    flen = fold_more(mip);
2018 
2019 	len = byts[arridx++];
2020 
2021 	/* If the first possible byte is a zero the prefix could end here.
2022 	 * Check if the following word matches and supports the prefix. */
2023 	if (byts[arridx] == 0)
2024 	{
2025 	    /* There can be several prefixes with different conditions.  We
2026 	     * try them all, since we don't know which one will give the
2027 	     * longest match.  The word is the same each time, pass the list
2028 	     * of possible prefixes to find_word(). */
2029 	    mip->mi_prefarridx = arridx;
2030 	    mip->mi_prefcnt = len;
2031 	    while (len > 0 && byts[arridx] == 0)
2032 	    {
2033 		++arridx;
2034 		--len;
2035 	    }
2036 	    mip->mi_prefcnt -= len;
2037 
2038 	    /* Find the word that comes after the prefix. */
2039 	    mip->mi_prefixlen = wlen;
2040 	    if (mode == FIND_COMPOUND)
2041 		/* Skip over the previously found word(s). */
2042 		mip->mi_prefixlen += mip->mi_compoff;
2043 
2044 #ifdef FEAT_MBYTE
2045 	    if (has_mbyte)
2046 	    {
2047 		/* Case-folded length may differ from original length. */
2048 		mip->mi_cprefixlen = nofold_len(mip->mi_fword,
2049 					     mip->mi_prefixlen, mip->mi_word);
2050 	    }
2051 	    else
2052 		mip->mi_cprefixlen = mip->mi_prefixlen;
2053 #endif
2054 	    find_word(mip, FIND_PREFIX);
2055 
2056 
2057 	    if (len == 0)
2058 		break;	    /* no children, word must end here */
2059 	}
2060 
2061 	/* Stop looking at end of the line. */
2062 	if (ptr[wlen] == NUL)
2063 	    break;
2064 
2065 	/* Perform a binary search in the list of accepted bytes. */
2066 	c = ptr[wlen];
2067 	lo = arridx;
2068 	hi = arridx + len - 1;
2069 	while (lo < hi)
2070 	{
2071 	    m = (lo + hi) / 2;
2072 	    if (byts[m] > c)
2073 		hi = m - 1;
2074 	    else if (byts[m] < c)
2075 		lo = m + 1;
2076 	    else
2077 	    {
2078 		lo = hi = m;
2079 		break;
2080 	    }
2081 	}
2082 
2083 	/* Stop if there is no matching byte. */
2084 	if (hi < lo || byts[lo] != c)
2085 	    break;
2086 
2087 	/* Continue at the child (if there is one). */
2088 	arridx = idxs[lo];
2089 	++wlen;
2090 	--flen;
2091     }
2092 }
2093 
2094 /*
2095  * Need to fold at least one more character.  Do until next non-word character
2096  * for efficiency.  Include the non-word character too.
2097  * Return the length of the folded chars in bytes.
2098  */
2099     static int
2100 fold_more(mip)
2101     matchinf_T	*mip;
2102 {
2103     int		flen;
2104     char_u	*p;
2105 
2106     p = mip->mi_fend;
2107     do
2108     {
2109 	mb_ptr_adv(mip->mi_fend);
2110     } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_buf));
2111 
2112     /* Include the non-word character so that we can check for the word end. */
2113     if (*mip->mi_fend != NUL)
2114 	mb_ptr_adv(mip->mi_fend);
2115 
2116     (void)spell_casefold(p, (int)(mip->mi_fend - p),
2117 			     mip->mi_fword + mip->mi_fwordlen,
2118 			     MAXWLEN - mip->mi_fwordlen);
2119     flen = (int)STRLEN(mip->mi_fword + mip->mi_fwordlen);
2120     mip->mi_fwordlen += flen;
2121     return flen;
2122 }
2123 
2124 /*
2125  * Check case flags for a word.  Return TRUE if the word has the requested
2126  * case.
2127  */
2128     static int
2129 spell_valid_case(wordflags, treeflags)
2130     int	    wordflags;	    /* flags for the checked word. */
2131     int	    treeflags;	    /* flags for the word in the spell tree */
2132 {
2133     return ((wordflags == WF_ALLCAP && (treeflags & WF_FIXCAP) == 0)
2134 	    || ((treeflags & (WF_ALLCAP | WF_KEEPCAP)) == 0
2135 		&& ((treeflags & WF_ONECAP) == 0
2136 					   || (wordflags & WF_ONECAP) != 0)));
2137 }
2138 
2139 /*
2140  * Return TRUE if spell checking is not enabled.
2141  */
2142     static int
2143 no_spell_checking(wp)
2144     win_T	*wp;
2145 {
2146     if (!wp->w_p_spell || *wp->w_buffer->b_p_spl == NUL
2147 					 || wp->w_buffer->b_langp.ga_len == 0)
2148     {
2149 	EMSG(_("E756: Spell checking is not enabled"));
2150 	return TRUE;
2151     }
2152     return FALSE;
2153 }
2154 
2155 /*
2156  * Move to next spell error.
2157  * "curline" is FALSE for "[s", "]s", "[S" and "]S".
2158  * "curline" is TRUE to find word under/after cursor in the same line.
2159  * For Insert mode completion "dir" is BACKWARD and "curline" is TRUE: move
2160  * to after badly spelled word before the cursor.
2161  * Return 0 if not found, length of the badly spelled word otherwise.
2162  */
2163     int
2164 spell_move_to(wp, dir, allwords, curline, attrp)
2165     win_T	*wp;
2166     int		dir;		/* FORWARD or BACKWARD */
2167     int		allwords;	/* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */
2168     int		curline;
2169     hlf_T	*attrp;		/* return: attributes of bad word or NULL
2170 				   (only when "dir" is FORWARD) */
2171 {
2172     linenr_T	lnum;
2173     pos_T	found_pos;
2174     int		found_len = 0;
2175     char_u	*line;
2176     char_u	*p;
2177     char_u	*endp;
2178     hlf_T	attr;
2179     int		len;
2180 # ifdef FEAT_SYN_HL
2181     int		has_syntax = syntax_present(wp->w_buffer);
2182 # endif
2183     int		col;
2184     int		can_spell;
2185     char_u	*buf = NULL;
2186     int		buflen = 0;
2187     int		skip = 0;
2188     int		capcol = -1;
2189     int		found_one = FALSE;
2190     int		wrapped = FALSE;
2191 
2192     if (no_spell_checking(wp))
2193 	return 0;
2194 
2195     /*
2196      * Start looking for bad word at the start of the line, because we can't
2197      * start halfway a word, we don't know where it starts or ends.
2198      *
2199      * When searching backwards, we continue in the line to find the last
2200      * bad word (in the cursor line: before the cursor).
2201      *
2202      * We concatenate the start of the next line, so that wrapped words work
2203      * (e.g. "et<line-break>cetera").  Doesn't work when searching backwards
2204      * though...
2205      */
2206     lnum = wp->w_cursor.lnum;
2207     clearpos(&found_pos);
2208 
2209     while (!got_int)
2210     {
2211 	line = ml_get_buf(wp->w_buffer, lnum, FALSE);
2212 
2213 	len = (int)STRLEN(line);
2214 	if (buflen < len + MAXWLEN + 2)
2215 	{
2216 	    vim_free(buf);
2217 	    buflen = len + MAXWLEN + 2;
2218 	    buf = alloc(buflen);
2219 	    if (buf == NULL)
2220 		break;
2221 	}
2222 
2223 	/* In first line check first word for Capital. */
2224 	if (lnum == 1)
2225 	    capcol = 0;
2226 
2227 	/* For checking first word with a capital skip white space. */
2228 	if (capcol == 0)
2229 	    capcol = (int)(skipwhite(line) - line);
2230 	else if (curline && wp == curwin)
2231 	{
2232 	    /* For spellbadword(): check if first word needs a capital. */
2233 	    col = (int)(skipwhite(line) - line);
2234 	    if (check_need_cap(lnum, col))
2235 		capcol = col;
2236 
2237 	    /* Need to get the line again, may have looked at the previous
2238 	     * one. */
2239 	    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
2240 	}
2241 
2242 	/* Copy the line into "buf" and append the start of the next line if
2243 	 * possible. */
2244 	STRCPY(buf, line);
2245 	if (lnum < wp->w_buffer->b_ml.ml_line_count)
2246 	    spell_cat_line(buf + STRLEN(buf),
2247 			  ml_get_buf(wp->w_buffer, lnum + 1, FALSE), MAXWLEN);
2248 
2249 	p = buf + skip;
2250 	endp = buf + len;
2251 	while (p < endp)
2252 	{
2253 	    /* When searching backward don't search after the cursor.  Unless
2254 	     * we wrapped around the end of the buffer. */
2255 	    if (dir == BACKWARD
2256 		    && lnum == wp->w_cursor.lnum
2257 		    && !wrapped
2258 		    && (colnr_T)(p - buf) >= wp->w_cursor.col)
2259 		break;
2260 
2261 	    /* start of word */
2262 	    attr = HLF_COUNT;
2263 	    len = spell_check(wp, p, &attr, &capcol, FALSE);
2264 
2265 	    if (attr != HLF_COUNT)
2266 	    {
2267 		/* We found a bad word.  Check the attribute. */
2268 		if (allwords || attr == HLF_SPB)
2269 		{
2270 		    /* When searching forward only accept a bad word after
2271 		     * the cursor. */
2272 		    if (dir == BACKWARD
2273 			    || lnum != wp->w_cursor.lnum
2274 			    || (lnum == wp->w_cursor.lnum
2275 				&& (wrapped
2276 				    || (colnr_T)(curline ? p - buf + len
2277 						     : p - buf)
2278 						  > wp->w_cursor.col)))
2279 		    {
2280 # ifdef FEAT_SYN_HL
2281 			if (has_syntax)
2282 			{
2283 			    col = (int)(p - buf);
2284 			    (void)syn_get_id(wp, lnum, (colnr_T)col,
2285 						    FALSE, &can_spell, FALSE);
2286 			    if (!can_spell)
2287 				attr = HLF_COUNT;
2288 			}
2289 			else
2290 #endif
2291 			    can_spell = TRUE;
2292 
2293 			if (can_spell)
2294 			{
2295 			    found_one = TRUE;
2296 			    found_pos.lnum = lnum;
2297 			    found_pos.col = (int)(p - buf);
2298 #ifdef FEAT_VIRTUALEDIT
2299 			    found_pos.coladd = 0;
2300 #endif
2301 			    if (dir == FORWARD)
2302 			    {
2303 				/* No need to search further. */
2304 				wp->w_cursor = found_pos;
2305 				vim_free(buf);
2306 				if (attrp != NULL)
2307 				    *attrp = attr;
2308 				return len;
2309 			    }
2310 			    else if (curline)
2311 				/* Insert mode completion: put cursor after
2312 				 * the bad word. */
2313 				found_pos.col += len;
2314 			    found_len = len;
2315 			}
2316 		    }
2317 		    else
2318 			found_one = TRUE;
2319 		}
2320 	    }
2321 
2322 	    /* advance to character after the word */
2323 	    p += len;
2324 	    capcol -= len;
2325 	}
2326 
2327 	if (dir == BACKWARD && found_pos.lnum != 0)
2328 	{
2329 	    /* Use the last match in the line (before the cursor). */
2330 	    wp->w_cursor = found_pos;
2331 	    vim_free(buf);
2332 	    return found_len;
2333 	}
2334 
2335 	if (curline)
2336 	    break;	/* only check cursor line */
2337 
2338 	/* Advance to next line. */
2339 	if (dir == BACKWARD)
2340 	{
2341 	    /* If we are back at the starting line and searched it again there
2342 	     * is no match, give up. */
2343 	    if (lnum == wp->w_cursor.lnum && wrapped)
2344 		break;
2345 
2346 	    if (lnum > 1)
2347 		--lnum;
2348 	    else if (!p_ws)
2349 		break;	    /* at first line and 'nowrapscan' */
2350 	    else
2351 	    {
2352 		/* Wrap around to the end of the buffer.  May search the
2353 		 * starting line again and accept the last match. */
2354 		lnum = wp->w_buffer->b_ml.ml_line_count;
2355 		wrapped = TRUE;
2356 		if (!shortmess(SHM_SEARCH))
2357 		    give_warning((char_u *)_(top_bot_msg), TRUE);
2358 	    }
2359 	    capcol = -1;
2360 	}
2361 	else
2362 	{
2363 	    if (lnum < wp->w_buffer->b_ml.ml_line_count)
2364 		++lnum;
2365 	    else if (!p_ws)
2366 		break;	    /* at first line and 'nowrapscan' */
2367 	    else
2368 	    {
2369 		/* Wrap around to the start of the buffer.  May search the
2370 		 * starting line again and accept the first match. */
2371 		lnum = 1;
2372 		wrapped = TRUE;
2373 		if (!shortmess(SHM_SEARCH))
2374 		    give_warning((char_u *)_(bot_top_msg), TRUE);
2375 	    }
2376 
2377 	    /* If we are back at the starting line and there is no match then
2378 	     * give up. */
2379 	    if (lnum == wp->w_cursor.lnum && (!found_one || wrapped))
2380 		break;
2381 
2382 	    /* Skip the characters at the start of the next line that were
2383 	     * included in a match crossing line boundaries. */
2384 	    if (attr == HLF_COUNT)
2385 		skip = (int)(p - endp);
2386 	    else
2387 		skip = 0;
2388 
2389 	    /* Capcol skips over the inserted space. */
2390 	    --capcol;
2391 
2392 	    /* But after empty line check first word in next line */
2393 	    if (*skipwhite(line) == NUL)
2394 		capcol = 0;
2395 	}
2396 
2397 	line_breakcheck();
2398     }
2399 
2400     vim_free(buf);
2401     return 0;
2402 }
2403 
2404 /*
2405  * For spell checking: concatenate the start of the following line "line" into
2406  * "buf", blanking-out special characters.  Copy less then "maxlen" bytes.
2407  * Keep the blanks at the start of the next line, this is used in win_line()
2408  * to skip those bytes if the word was OK.
2409  */
2410     void
2411 spell_cat_line(buf, line, maxlen)
2412     char_u	*buf;
2413     char_u	*line;
2414     int		maxlen;
2415 {
2416     char_u	*p;
2417     int		n;
2418 
2419     p = skipwhite(line);
2420     while (vim_strchr((char_u *)"*#/\"\t", *p) != NULL)
2421 	p = skipwhite(p + 1);
2422 
2423     if (*p != NUL)
2424     {
2425 	/* Only worth concatenating if there is something else than spaces to
2426 	 * concatenate. */
2427 	n = (int)(p - line) + 1;
2428 	if (n < maxlen - 1)
2429 	{
2430 	    vim_memset(buf, ' ', n);
2431 	    vim_strncpy(buf +  n, p, maxlen - 1 - n);
2432 	}
2433     }
2434 }
2435 
2436 /*
2437  * Structure used for the cookie argument of do_in_runtimepath().
2438  */
2439 typedef struct spelload_S
2440 {
2441     char_u  sl_lang[MAXWLEN + 1];	/* language name */
2442     slang_T *sl_slang;			/* resulting slang_T struct */
2443     int	    sl_nobreak;			/* NOBREAK language found */
2444 } spelload_T;
2445 
2446 /*
2447  * Load word list(s) for "lang" from Vim spell file(s).
2448  * "lang" must be the language without the region: e.g., "en".
2449  */
2450     static void
2451 spell_load_lang(lang)
2452     char_u	*lang;
2453 {
2454     char_u	fname_enc[85];
2455     int		r;
2456     spelload_T	sl;
2457 #ifdef FEAT_AUTOCMD
2458     int		round;
2459 #endif
2460 
2461     /* Copy the language name to pass it to spell_load_cb() as a cookie.
2462      * It's truncated when an error is detected. */
2463     STRCPY(sl.sl_lang, lang);
2464     sl.sl_slang = NULL;
2465     sl.sl_nobreak = FALSE;
2466 
2467 #ifdef FEAT_AUTOCMD
2468     /* We may retry when no spell file is found for the language, an
2469      * autocommand may load it then. */
2470     for (round = 1; round <= 2; ++round)
2471 #endif
2472     {
2473 	/*
2474 	 * Find the first spell file for "lang" in 'runtimepath' and load it.
2475 	 */
2476 	vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2477 					"spell/%s.%s.spl", lang, spell_enc());
2478 	r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2479 
2480 	if (r == FAIL && *sl.sl_lang != NUL)
2481 	{
2482 	    /* Try loading the ASCII version. */
2483 	    vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2484 						  "spell/%s.ascii.spl", lang);
2485 	    r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2486 
2487 #ifdef FEAT_AUTOCMD
2488 	    if (r == FAIL && *sl.sl_lang != NUL && round == 1
2489 		    && apply_autocmds(EVENT_SPELLFILEMISSING, lang,
2490 					      curbuf->b_fname, FALSE, curbuf))
2491 		continue;
2492 	    break;
2493 #endif
2494 	}
2495 #ifdef FEAT_AUTOCMD
2496 	break;
2497 #endif
2498     }
2499 
2500     if (r == FAIL)
2501     {
2502 	smsg((char_u *)_("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""),
2503 						     lang, spell_enc(), lang);
2504     }
2505     else if (sl.sl_slang != NULL)
2506     {
2507 	/* At least one file was loaded, now load ALL the additions. */
2508 	STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
2509 	do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl);
2510     }
2511 }
2512 
2513 /*
2514  * Return the encoding used for spell checking: Use 'encoding', except that we
2515  * use "latin1" for "latin9".  And limit to 60 characters (just in case).
2516  */
2517     static char_u *
2518 spell_enc()
2519 {
2520 
2521 #ifdef FEAT_MBYTE
2522     if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0)
2523 	return p_enc;
2524 #endif
2525     return (char_u *)"latin1";
2526 }
2527 
2528 /*
2529  * Get the name of the .spl file for the internal wordlist into
2530  * "fname[MAXPATHL]".
2531  */
2532     static void
2533 int_wordlist_spl(fname)
2534     char_u	    *fname;
2535 {
2536     vim_snprintf((char *)fname, MAXPATHL, "%s.%s.spl",
2537 						  int_wordlist, spell_enc());
2538 }
2539 
2540 /*
2541  * Allocate a new slang_T for language "lang".  "lang" can be NULL.
2542  * Caller must fill "sl_next".
2543  */
2544     static slang_T *
2545 slang_alloc(lang)
2546     char_u	*lang;
2547 {
2548     slang_T *lp;
2549 
2550     lp = (slang_T *)alloc_clear(sizeof(slang_T));
2551     if (lp != NULL)
2552     {
2553 	if (lang != NULL)
2554 	    lp->sl_name = vim_strsave(lang);
2555 	ga_init2(&lp->sl_rep, sizeof(fromto_T), 10);
2556 	ga_init2(&lp->sl_repsal, sizeof(fromto_T), 10);
2557 	lp->sl_compmax = MAXWLEN;
2558 	lp->sl_compsylmax = MAXWLEN;
2559 	hash_init(&lp->sl_wordcount);
2560     }
2561 
2562     return lp;
2563 }
2564 
2565 /*
2566  * Free the contents of an slang_T and the structure itself.
2567  */
2568     static void
2569 slang_free(lp)
2570     slang_T	*lp;
2571 {
2572     vim_free(lp->sl_name);
2573     vim_free(lp->sl_fname);
2574     slang_clear(lp);
2575     vim_free(lp);
2576 }
2577 
2578 /*
2579  * Clear an slang_T so that the file can be reloaded.
2580  */
2581     static void
2582 slang_clear(lp)
2583     slang_T	*lp;
2584 {
2585     garray_T	*gap;
2586     fromto_T	*ftp;
2587     salitem_T	*smp;
2588     int		i;
2589     int		round;
2590 
2591     vim_free(lp->sl_fbyts);
2592     lp->sl_fbyts = NULL;
2593     vim_free(lp->sl_kbyts);
2594     lp->sl_kbyts = NULL;
2595     vim_free(lp->sl_pbyts);
2596     lp->sl_pbyts = NULL;
2597 
2598     vim_free(lp->sl_fidxs);
2599     lp->sl_fidxs = NULL;
2600     vim_free(lp->sl_kidxs);
2601     lp->sl_kidxs = NULL;
2602     vim_free(lp->sl_pidxs);
2603     lp->sl_pidxs = NULL;
2604 
2605     for (round = 1; round <= 2; ++round)
2606     {
2607 	gap = round == 1 ? &lp->sl_rep : &lp->sl_repsal;
2608 	while (gap->ga_len > 0)
2609 	{
2610 	    ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len];
2611 	    vim_free(ftp->ft_from);
2612 	    vim_free(ftp->ft_to);
2613 	}
2614 	ga_clear(gap);
2615     }
2616 
2617     gap = &lp->sl_sal;
2618     if (lp->sl_sofo)
2619     {
2620 	/* "ga_len" is set to 1 without adding an item for latin1 */
2621 	if (gap->ga_data != NULL)
2622 	    /* SOFOFROM and SOFOTO items: free lists of wide characters. */
2623 	    for (i = 0; i < gap->ga_len; ++i)
2624 		vim_free(((int **)gap->ga_data)[i]);
2625     }
2626     else
2627 	/* SAL items: free salitem_T items */
2628 	while (gap->ga_len > 0)
2629 	{
2630 	    smp = &((salitem_T *)gap->ga_data)[--gap->ga_len];
2631 	    vim_free(smp->sm_lead);
2632 	    /* Don't free sm_oneof and sm_rules, they point into sm_lead. */
2633 	    vim_free(smp->sm_to);
2634 #ifdef FEAT_MBYTE
2635 	    vim_free(smp->sm_lead_w);
2636 	    vim_free(smp->sm_oneof_w);
2637 	    vim_free(smp->sm_to_w);
2638 #endif
2639 	}
2640     ga_clear(gap);
2641 
2642     for (i = 0; i < lp->sl_prefixcnt; ++i)
2643 	vim_free(lp->sl_prefprog[i]);
2644     lp->sl_prefixcnt = 0;
2645     vim_free(lp->sl_prefprog);
2646     lp->sl_prefprog = NULL;
2647 
2648     vim_free(lp->sl_info);
2649     lp->sl_info = NULL;
2650 
2651     vim_free(lp->sl_midword);
2652     lp->sl_midword = NULL;
2653 
2654     vim_free(lp->sl_compprog);
2655     vim_free(lp->sl_comprules);
2656     vim_free(lp->sl_compstartflags);
2657     vim_free(lp->sl_compallflags);
2658     lp->sl_compprog = NULL;
2659     lp->sl_comprules = NULL;
2660     lp->sl_compstartflags = NULL;
2661     lp->sl_compallflags = NULL;
2662 
2663     vim_free(lp->sl_syllable);
2664     lp->sl_syllable = NULL;
2665     ga_clear(&lp->sl_syl_items);
2666 
2667     ga_clear_strings(&lp->sl_comppat);
2668 
2669     hash_clear_all(&lp->sl_wordcount, WC_KEY_OFF);
2670     hash_init(&lp->sl_wordcount);
2671 
2672 #ifdef FEAT_MBYTE
2673     hash_clear_all(&lp->sl_map_hash, 0);
2674 #endif
2675 
2676     /* Clear info from .sug file. */
2677     slang_clear_sug(lp);
2678 
2679     lp->sl_compmax = MAXWLEN;
2680     lp->sl_compminlen = 0;
2681     lp->sl_compsylmax = MAXWLEN;
2682     lp->sl_regions[0] = NUL;
2683 }
2684 
2685 /*
2686  * Clear the info from the .sug file in "lp".
2687  */
2688     static void
2689 slang_clear_sug(lp)
2690     slang_T	*lp;
2691 {
2692     vim_free(lp->sl_sbyts);
2693     lp->sl_sbyts = NULL;
2694     vim_free(lp->sl_sidxs);
2695     lp->sl_sidxs = NULL;
2696     close_spellbuf(lp->sl_sugbuf);
2697     lp->sl_sugbuf = NULL;
2698     lp->sl_sugloaded = FALSE;
2699     lp->sl_sugtime = 0;
2700 }
2701 
2702 /*
2703  * Load one spell file and store the info into a slang_T.
2704  * Invoked through do_in_runtimepath().
2705  */
2706     static void
2707 spell_load_cb(fname, cookie)
2708     char_u	*fname;
2709     void	*cookie;
2710 {
2711     spelload_T	*slp = (spelload_T *)cookie;
2712     slang_T	*slang;
2713 
2714     slang = spell_load_file(fname, slp->sl_lang, NULL, FALSE);
2715     if (slang != NULL)
2716     {
2717 	/* When a previously loaded file has NOBREAK also use it for the
2718 	 * ".add" files. */
2719 	if (slp->sl_nobreak && slang->sl_add)
2720 	    slang->sl_nobreak = TRUE;
2721 	else if (slang->sl_nobreak)
2722 	    slp->sl_nobreak = TRUE;
2723 
2724 	slp->sl_slang = slang;
2725     }
2726 }
2727 
2728 /*
2729  * Load one spell file and store the info into a slang_T.
2730  *
2731  * This is invoked in three ways:
2732  * - From spell_load_cb() to load a spell file for the first time.  "lang" is
2733  *   the language name, "old_lp" is NULL.  Will allocate an slang_T.
2734  * - To reload a spell file that was changed.  "lang" is NULL and "old_lp"
2735  *   points to the existing slang_T.
2736  * - Just after writing a .spl file; it's read back to produce the .sug file.
2737  *   "old_lp" is NULL and "lang" is NULL.  Will allocate an slang_T.
2738  *
2739  * Returns the slang_T the spell file was loaded into.  NULL for error.
2740  */
2741     static slang_T *
2742 spell_load_file(fname, lang, old_lp, silent)
2743     char_u	*fname;
2744     char_u	*lang;
2745     slang_T	*old_lp;
2746     int		silent;		/* no error if file doesn't exist */
2747 {
2748     FILE	*fd;
2749     char_u	buf[VIMSPELLMAGICL];
2750     char_u	*p;
2751     int		i;
2752     int		n;
2753     int		len;
2754     char_u	*save_sourcing_name = sourcing_name;
2755     linenr_T	save_sourcing_lnum = sourcing_lnum;
2756     slang_T	*lp = NULL;
2757     int		c = 0;
2758     int		res;
2759 
2760     fd = mch_fopen((char *)fname, "r");
2761     if (fd == NULL)
2762     {
2763 	if (!silent)
2764 	    EMSG2(_(e_notopen), fname);
2765 	else if (p_verbose > 2)
2766 	{
2767 	    verbose_enter();
2768 	    smsg((char_u *)e_notopen, fname);
2769 	    verbose_leave();
2770 	}
2771 	goto endFAIL;
2772     }
2773     if (p_verbose > 2)
2774     {
2775 	verbose_enter();
2776 	smsg((char_u *)_("Reading spell file \"%s\""), fname);
2777 	verbose_leave();
2778     }
2779 
2780     if (old_lp == NULL)
2781     {
2782 	lp = slang_alloc(lang);
2783 	if (lp == NULL)
2784 	    goto endFAIL;
2785 
2786 	/* Remember the file name, used to reload the file when it's updated. */
2787 	lp->sl_fname = vim_strsave(fname);
2788 	if (lp->sl_fname == NULL)
2789 	    goto endFAIL;
2790 
2791 	/* Check for .add.spl. */
2792 	lp->sl_add = strstr((char *)gettail(fname), ".add.") != NULL;
2793     }
2794     else
2795 	lp = old_lp;
2796 
2797     /* Set sourcing_name, so that error messages mention the file name. */
2798     sourcing_name = fname;
2799     sourcing_lnum = 0;
2800 
2801     /*
2802      * <HEADER>: <fileID>
2803      */
2804     for (i = 0; i < VIMSPELLMAGICL; ++i)
2805 	buf[i] = getc(fd);				/* <fileID> */
2806     if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0)
2807     {
2808 	EMSG(_("E757: This does not look like a spell file"));
2809 	goto endFAIL;
2810     }
2811     c = getc(fd);					/* <versionnr> */
2812     if (c < VIMSPELLVERSION)
2813     {
2814 	EMSG(_("E771: Old spell file, needs to be updated"));
2815 	goto endFAIL;
2816     }
2817     else if (c > VIMSPELLVERSION)
2818     {
2819 	EMSG(_("E772: Spell file is for newer version of Vim"));
2820 	goto endFAIL;
2821     }
2822 
2823 
2824     /*
2825      * <SECTIONS>: <section> ... <sectionend>
2826      * <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
2827      */
2828     for (;;)
2829     {
2830 	n = getc(fd);			    /* <sectionID> or <sectionend> */
2831 	if (n == SN_END)
2832 	    break;
2833 	c = getc(fd);					/* <sectionflags> */
2834 	len = get4c(fd);				/* <sectionlen> */
2835 	if (len < 0)
2836 	    goto truncerr;
2837 
2838 	res = 0;
2839 	switch (n)
2840 	{
2841 	    case SN_INFO:
2842 		lp->sl_info = read_string(fd, len);	/* <infotext> */
2843 		if (lp->sl_info == NULL)
2844 		    goto endFAIL;
2845 		break;
2846 
2847 	    case SN_REGION:
2848 		res = read_region_section(fd, lp, len);
2849 		break;
2850 
2851 	    case SN_CHARFLAGS:
2852 		res = read_charflags_section(fd);
2853 		break;
2854 
2855 	    case SN_MIDWORD:
2856 		lp->sl_midword = read_string(fd, len);	/* <midword> */
2857 		if (lp->sl_midword == NULL)
2858 		    goto endFAIL;
2859 		break;
2860 
2861 	    case SN_PREFCOND:
2862 		res = read_prefcond_section(fd, lp);
2863 		break;
2864 
2865 	    case SN_REP:
2866 		res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first);
2867 		break;
2868 
2869 	    case SN_REPSAL:
2870 		res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first);
2871 		break;
2872 
2873 	    case SN_SAL:
2874 		res = read_sal_section(fd, lp);
2875 		break;
2876 
2877 	    case SN_SOFO:
2878 		res = read_sofo_section(fd, lp);
2879 		break;
2880 
2881 	    case SN_MAP:
2882 		p = read_string(fd, len);		/* <mapstr> */
2883 		if (p == NULL)
2884 		    goto endFAIL;
2885 		set_map_str(lp, p);
2886 		vim_free(p);
2887 		break;
2888 
2889 	    case SN_WORDS:
2890 		res = read_words_section(fd, lp, len);
2891 		break;
2892 
2893 	    case SN_SUGFILE:
2894 		lp->sl_sugtime = get8c(fd);		/* <timestamp> */
2895 		break;
2896 
2897 	    case SN_NOSPLITSUGS:
2898 		lp->sl_nosplitsugs = TRUE;		/* <timestamp> */
2899 		break;
2900 
2901 	    case SN_COMPOUND:
2902 		res = read_compound(fd, lp, len);
2903 		break;
2904 
2905 	    case SN_NOBREAK:
2906 		lp->sl_nobreak = TRUE;
2907 		break;
2908 
2909 	    case SN_SYLLABLE:
2910 		lp->sl_syllable = read_string(fd, len);	/* <syllable> */
2911 		if (lp->sl_syllable == NULL)
2912 		    goto endFAIL;
2913 		if (init_syl_tab(lp) == FAIL)
2914 		    goto endFAIL;
2915 		break;
2916 
2917 	    default:
2918 		/* Unsupported section.  When it's required give an error
2919 		 * message.  When it's not required skip the contents. */
2920 		if (c & SNF_REQUIRED)
2921 		{
2922 		    EMSG(_("E770: Unsupported section in spell file"));
2923 		    goto endFAIL;
2924 		}
2925 		while (--len >= 0)
2926 		    if (getc(fd) < 0)
2927 			goto truncerr;
2928 		break;
2929 	}
2930 someerror:
2931 	if (res == SP_FORMERROR)
2932 	{
2933 	    EMSG(_(e_format));
2934 	    goto endFAIL;
2935 	}
2936 	if (res == SP_TRUNCERROR)
2937 	{
2938 truncerr:
2939 	    EMSG(_(e_spell_trunc));
2940 	    goto endFAIL;
2941 	}
2942 	if (res == SP_OTHERERROR)
2943 	    goto endFAIL;
2944     }
2945 
2946     /* <LWORDTREE> */
2947     res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, FALSE, 0);
2948     if (res != 0)
2949 	goto someerror;
2950 
2951     /* <KWORDTREE> */
2952     res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, FALSE, 0);
2953     if (res != 0)
2954 	goto someerror;
2955 
2956     /* <PREFIXTREE> */
2957     res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, TRUE,
2958 							    lp->sl_prefixcnt);
2959     if (res != 0)
2960 	goto someerror;
2961 
2962     /* For a new file link it in the list of spell files. */
2963     if (old_lp == NULL && lang != NULL)
2964     {
2965 	lp->sl_next = first_lang;
2966 	first_lang = lp;
2967     }
2968 
2969     goto endOK;
2970 
2971 endFAIL:
2972     if (lang != NULL)
2973 	/* truncating the name signals the error to spell_load_lang() */
2974 	*lang = NUL;
2975     if (lp != NULL && old_lp == NULL)
2976 	slang_free(lp);
2977     lp = NULL;
2978 
2979 endOK:
2980     if (fd != NULL)
2981 	fclose(fd);
2982     sourcing_name = save_sourcing_name;
2983     sourcing_lnum = save_sourcing_lnum;
2984 
2985     return lp;
2986 }
2987 
2988 /*
2989  * Read 2 bytes from "fd" and turn them into an int, MSB first.
2990  */
2991     static int
2992 get2c(fd)
2993     FILE	*fd;
2994 {
2995     long	n;
2996 
2997     n = getc(fd);
2998     n = (n << 8) + getc(fd);
2999     return n;
3000 }
3001 
3002 /*
3003  * Read 3 bytes from "fd" and turn them into an int, MSB first.
3004  */
3005     static int
3006 get3c(fd)
3007     FILE	*fd;
3008 {
3009     long	n;
3010 
3011     n = getc(fd);
3012     n = (n << 8) + getc(fd);
3013     n = (n << 8) + getc(fd);
3014     return n;
3015 }
3016 
3017 /*
3018  * Read 4 bytes from "fd" and turn them into an int, MSB first.
3019  */
3020     static int
3021 get4c(fd)
3022     FILE	*fd;
3023 {
3024     long	n;
3025 
3026     n = getc(fd);
3027     n = (n << 8) + getc(fd);
3028     n = (n << 8) + getc(fd);
3029     n = (n << 8) + getc(fd);
3030     return n;
3031 }
3032 
3033 /*
3034  * Read 8 bytes from "fd" and turn them into a time_t, MSB first.
3035  */
3036     static time_t
3037 get8c(fd)
3038     FILE	*fd;
3039 {
3040     time_t	n = 0;
3041     int		i;
3042 
3043     for (i = 0; i < 8; ++i)
3044 	n = (n << 8) + getc(fd);
3045     return n;
3046 }
3047 
3048 /*
3049  * Read a length field from "fd" in "cnt_bytes" bytes.
3050  * Allocate memory, read the string into it and add a NUL at the end.
3051  * Returns NULL when the count is zero.
3052  * Sets "*cntp" to SP_*ERROR when there is an error, length of the result
3053  * otherwise.
3054  */
3055     static char_u *
3056 read_cnt_string(fd, cnt_bytes, cntp)
3057     FILE	*fd;
3058     int		cnt_bytes;
3059     int		*cntp;
3060 {
3061     int		cnt = 0;
3062     int		i;
3063     char_u	*str;
3064 
3065     /* read the length bytes, MSB first */
3066     for (i = 0; i < cnt_bytes; ++i)
3067 	cnt = (cnt << 8) + getc(fd);
3068     if (cnt < 0)
3069     {
3070 	*cntp = SP_TRUNCERROR;
3071 	return NULL;
3072     }
3073     *cntp = cnt;
3074     if (cnt == 0)
3075 	return NULL;	    /* nothing to read, return NULL */
3076 
3077     str = read_string(fd, cnt);
3078     if (str == NULL)
3079 	*cntp = SP_OTHERERROR;
3080     return str;
3081 }
3082 
3083 /*
3084  * Read a string of length "cnt" from "fd" into allocated memory.
3085  * Returns NULL when out of memory or unable to read that many bytes.
3086  */
3087     static char_u *
3088 read_string(fd, cnt)
3089     FILE	*fd;
3090     int		cnt;
3091 {
3092     char_u	*str;
3093     int		i;
3094     int		c;
3095 
3096     /* allocate memory */
3097     str = alloc((unsigned)cnt + 1);
3098     if (str != NULL)
3099     {
3100 	/* Read the string.  Quit when running into the EOF. */
3101 	for (i = 0; i < cnt; ++i)
3102 	{
3103 	    c = getc(fd);
3104 	    if (c == EOF)
3105 	    {
3106 		vim_free(str);
3107 		return NULL;
3108 	    }
3109 	    str[i] = c;
3110 	}
3111 	str[i] = NUL;
3112     }
3113     return str;
3114 }
3115 
3116 /*
3117  * Read SN_REGION: <regionname> ...
3118  * Return SP_*ERROR flags.
3119  */
3120     static int
3121 read_region_section(fd, lp, len)
3122     FILE	*fd;
3123     slang_T	*lp;
3124     int		len;
3125 {
3126     int		i;
3127 
3128     if (len > 16)
3129 	return SP_FORMERROR;
3130     for (i = 0; i < len; ++i)
3131 	lp->sl_regions[i] = getc(fd);			/* <regionname> */
3132     lp->sl_regions[len] = NUL;
3133     return 0;
3134 }
3135 
3136 /*
3137  * Read SN_CHARFLAGS section: <charflagslen> <charflags>
3138  *				<folcharslen> <folchars>
3139  * Return SP_*ERROR flags.
3140  */
3141     static int
3142 read_charflags_section(fd)
3143     FILE	*fd;
3144 {
3145     char_u	*flags;
3146     char_u	*fol;
3147     int		flagslen, follen;
3148 
3149     /* <charflagslen> <charflags> */
3150     flags = read_cnt_string(fd, 1, &flagslen);
3151     if (flagslen < 0)
3152 	return flagslen;
3153 
3154     /* <folcharslen> <folchars> */
3155     fol = read_cnt_string(fd, 2, &follen);
3156     if (follen < 0)
3157     {
3158 	vim_free(flags);
3159 	return follen;
3160     }
3161 
3162     /* Set the word-char flags and fill SPELL_ISUPPER() table. */
3163     if (flags != NULL && fol != NULL)
3164 	set_spell_charflags(flags, flagslen, fol);
3165 
3166     vim_free(flags);
3167     vim_free(fol);
3168 
3169     /* When <charflagslen> is zero then <fcharlen> must also be zero. */
3170     if ((flags == NULL) != (fol == NULL))
3171 	return SP_FORMERROR;
3172     return 0;
3173 }
3174 
3175 /*
3176  * Read SN_PREFCOND section.
3177  * Return SP_*ERROR flags.
3178  */
3179     static int
3180 read_prefcond_section(fd, lp)
3181     FILE	*fd;
3182     slang_T	*lp;
3183 {
3184     int		cnt;
3185     int		i;
3186     int		n;
3187     char_u	*p;
3188     char_u	buf[MAXWLEN + 1];
3189 
3190     /* <prefcondcnt> <prefcond> ... */
3191     cnt = get2c(fd);					/* <prefcondcnt> */
3192     if (cnt <= 0)
3193 	return SP_FORMERROR;
3194 
3195     lp->sl_prefprog = (regprog_T **)alloc_clear(
3196 					 (unsigned)sizeof(regprog_T *) * cnt);
3197     if (lp->sl_prefprog == NULL)
3198 	return SP_OTHERERROR;
3199     lp->sl_prefixcnt = cnt;
3200 
3201     for (i = 0; i < cnt; ++i)
3202     {
3203 	/* <prefcond> : <condlen> <condstr> */
3204 	n = getc(fd);					/* <condlen> */
3205 	if (n < 0 || n >= MAXWLEN)
3206 	    return SP_FORMERROR;
3207 
3208 	/* When <condlen> is zero we have an empty condition.  Otherwise
3209 	 * compile the regexp program used to check for the condition. */
3210 	if (n > 0)
3211 	{
3212 	    buf[0] = '^';	    /* always match at one position only */
3213 	    p = buf + 1;
3214 	    while (n-- > 0)
3215 		*p++ = getc(fd);			/* <condstr> */
3216 	    *p = NUL;
3217 	    lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING);
3218 	}
3219     }
3220     return 0;
3221 }
3222 
3223 /*
3224  * Read REP or REPSAL items section from "fd": <repcount> <rep> ...
3225  * Return SP_*ERROR flags.
3226  */
3227     static int
3228 read_rep_section(fd, gap, first)
3229     FILE	*fd;
3230     garray_T	*gap;
3231     short	*first;
3232 {
3233     int		cnt;
3234     fromto_T	*ftp;
3235     int		i;
3236 
3237     cnt = get2c(fd);					/* <repcount> */
3238     if (cnt < 0)
3239 	return SP_TRUNCERROR;
3240 
3241     if (ga_grow(gap, cnt) == FAIL)
3242 	return SP_OTHERERROR;
3243 
3244     /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
3245     for (; gap->ga_len < cnt; ++gap->ga_len)
3246     {
3247 	ftp = &((fromto_T *)gap->ga_data)[gap->ga_len];
3248 	ftp->ft_from = read_cnt_string(fd, 1, &i);
3249 	if (i < 0)
3250 	    return i;
3251 	if (i == 0)
3252 	    return SP_FORMERROR;
3253 	ftp->ft_to = read_cnt_string(fd, 1, &i);
3254 	if (i <= 0)
3255 	{
3256 	    vim_free(ftp->ft_from);
3257 	    if (i < 0)
3258 		return i;
3259 	    return SP_FORMERROR;
3260 	}
3261     }
3262 
3263     /* Fill the first-index table. */
3264     for (i = 0; i < 256; ++i)
3265 	first[i] = -1;
3266     for (i = 0; i < gap->ga_len; ++i)
3267     {
3268 	ftp = &((fromto_T *)gap->ga_data)[i];
3269 	if (first[*ftp->ft_from] == -1)
3270 	    first[*ftp->ft_from] = i;
3271     }
3272     return 0;
3273 }
3274 
3275 /*
3276  * Read SN_SAL section: <salflags> <salcount> <sal> ...
3277  * Return SP_*ERROR flags.
3278  */
3279     static int
3280 read_sal_section(fd, slang)
3281     FILE	*fd;
3282     slang_T	*slang;
3283 {
3284     int		i;
3285     int		cnt;
3286     garray_T	*gap;
3287     salitem_T	*smp;
3288     int		ccnt;
3289     char_u	*p;
3290     int		c = NUL;
3291 
3292     slang->sl_sofo = FALSE;
3293 
3294     i = getc(fd);				/* <salflags> */
3295     if (i & SAL_F0LLOWUP)
3296 	slang->sl_followup = TRUE;
3297     if (i & SAL_COLLAPSE)
3298 	slang->sl_collapse = TRUE;
3299     if (i & SAL_REM_ACCENTS)
3300 	slang->sl_rem_accents = TRUE;
3301 
3302     cnt = get2c(fd);				/* <salcount> */
3303     if (cnt < 0)
3304 	return SP_TRUNCERROR;
3305 
3306     gap = &slang->sl_sal;
3307     ga_init2(gap, sizeof(salitem_T), 10);
3308     if (ga_grow(gap, cnt + 1) == FAIL)
3309 	return SP_OTHERERROR;
3310 
3311     /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
3312     for (; gap->ga_len < cnt; ++gap->ga_len)
3313     {
3314 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
3315 	ccnt = getc(fd);			/* <salfromlen> */
3316 	if (ccnt < 0)
3317 	    return SP_TRUNCERROR;
3318 	if ((p = alloc(ccnt + 2)) == NULL)
3319 	    return SP_OTHERERROR;
3320 	smp->sm_lead = p;
3321 
3322 	/* Read up to the first special char into sm_lead. */
3323 	for (i = 0; i < ccnt; ++i)
3324 	{
3325 	    c = getc(fd);			/* <salfrom> */
3326 	    if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL)
3327 		break;
3328 	    *p++ = c;
3329 	}
3330 	smp->sm_leadlen = (int)(p - smp->sm_lead);
3331 	*p++ = NUL;
3332 
3333 	/* Put (abc) chars in sm_oneof, if any. */
3334 	if (c == '(')
3335 	{
3336 	    smp->sm_oneof = p;
3337 	    for (++i; i < ccnt; ++i)
3338 	    {
3339 		c = getc(fd);			/* <salfrom> */
3340 		if (c == ')')
3341 		    break;
3342 		*p++ = c;
3343 	    }
3344 	    *p++ = NUL;
3345 	    if (++i < ccnt)
3346 		c = getc(fd);
3347 	}
3348 	else
3349 	    smp->sm_oneof = NULL;
3350 
3351 	/* Any following chars go in sm_rules. */
3352 	smp->sm_rules = p;
3353 	if (i < ccnt)
3354 	    /* store the char we got while checking for end of sm_lead */
3355 	    *p++ = c;
3356 	for (++i; i < ccnt; ++i)
3357 	    *p++ = getc(fd);			/* <salfrom> */
3358 	*p++ = NUL;
3359 
3360 	/* <saltolen> <salto> */
3361 	smp->sm_to = read_cnt_string(fd, 1, &ccnt);
3362 	if (ccnt < 0)
3363 	{
3364 	    vim_free(smp->sm_lead);
3365 	    return ccnt;
3366 	}
3367 
3368 #ifdef FEAT_MBYTE
3369 	if (has_mbyte)
3370 	{
3371 	    /* convert the multi-byte strings to wide char strings */
3372 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
3373 	    smp->sm_leadlen = mb_charlen(smp->sm_lead);
3374 	    if (smp->sm_oneof == NULL)
3375 		smp->sm_oneof_w = NULL;
3376 	    else
3377 		smp->sm_oneof_w = mb_str2wide(smp->sm_oneof);
3378 	    if (smp->sm_to == NULL)
3379 		smp->sm_to_w = NULL;
3380 	    else
3381 		smp->sm_to_w = mb_str2wide(smp->sm_to);
3382 	    if (smp->sm_lead_w == NULL
3383 		    || (smp->sm_oneof_w == NULL && smp->sm_oneof != NULL)
3384 		    || (smp->sm_to_w == NULL && smp->sm_to != NULL))
3385 	    {
3386 		vim_free(smp->sm_lead);
3387 		vim_free(smp->sm_to);
3388 		vim_free(smp->sm_lead_w);
3389 		vim_free(smp->sm_oneof_w);
3390 		vim_free(smp->sm_to_w);
3391 		return SP_OTHERERROR;
3392 	    }
3393 	}
3394 #endif
3395     }
3396 
3397     if (gap->ga_len > 0)
3398     {
3399 	/* Add one extra entry to mark the end with an empty sm_lead.  Avoids
3400 	 * that we need to check the index every time. */
3401 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
3402 	if ((p = alloc(1)) == NULL)
3403 	    return SP_OTHERERROR;
3404 	p[0] = NUL;
3405 	smp->sm_lead = p;
3406 	smp->sm_leadlen = 0;
3407 	smp->sm_oneof = NULL;
3408 	smp->sm_rules = p;
3409 	smp->sm_to = NULL;
3410 #ifdef FEAT_MBYTE
3411 	if (has_mbyte)
3412 	{
3413 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
3414 	    smp->sm_leadlen = 0;
3415 	    smp->sm_oneof_w = NULL;
3416 	    smp->sm_to_w = NULL;
3417 	}
3418 #endif
3419 	++gap->ga_len;
3420     }
3421 
3422     /* Fill the first-index table. */
3423     set_sal_first(slang);
3424 
3425     return 0;
3426 }
3427 
3428 /*
3429  * Read SN_WORDS: <word> ...
3430  * Return SP_*ERROR flags.
3431  */
3432     static int
3433 read_words_section(fd, lp, len)
3434     FILE	*fd;
3435     slang_T	*lp;
3436     int		len;
3437 {
3438     int		done = 0;
3439     int		i;
3440     int		c;
3441     char_u	word[MAXWLEN];
3442 
3443     while (done < len)
3444     {
3445 	/* Read one word at a time. */
3446 	for (i = 0; ; ++i)
3447 	{
3448 	    c = getc(fd);
3449 	    if (c == EOF)
3450 		return SP_TRUNCERROR;
3451 	    word[i] = c;
3452 	    if (word[i] == NUL)
3453 		break;
3454 	    if (i == MAXWLEN - 1)
3455 		return SP_FORMERROR;
3456 	}
3457 
3458 	/* Init the count to 10. */
3459 	count_common_word(lp, word, -1, 10);
3460 	done += i + 1;
3461     }
3462     return 0;
3463 }
3464 
3465 /*
3466  * Add a word to the hashtable of common words.
3467  * If it's already there then the counter is increased.
3468  */
3469     static void
3470 count_common_word(lp, word, len, count)
3471     slang_T	*lp;
3472     char_u	*word;
3473     int		len;	    /* word length, -1 for upto NUL */
3474     int		count;	    /* 1 to count once, 10 to init */
3475 {
3476     hash_T	hash;
3477     hashitem_T	*hi;
3478     wordcount_T	*wc;
3479     char_u	buf[MAXWLEN];
3480     char_u	*p;
3481 
3482     if (len == -1)
3483 	p = word;
3484     else
3485     {
3486 	vim_strncpy(buf, word, len);
3487 	p = buf;
3488     }
3489 
3490     hash = hash_hash(p);
3491     hi = hash_lookup(&lp->sl_wordcount, p, hash);
3492     if (HASHITEM_EMPTY(hi))
3493     {
3494 	wc = (wordcount_T *)alloc((unsigned)(sizeof(wordcount_T) + STRLEN(p)));
3495 	if (wc == NULL)
3496 	    return;
3497 	STRCPY(wc->wc_word, p);
3498 	wc->wc_count = count;
3499 	hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
3500     }
3501     else
3502     {
3503 	wc = HI2WC(hi);
3504 	if ((wc->wc_count += count) < (unsigned)count)	/* check for overflow */
3505 	    wc->wc_count = MAXWORDCOUNT;
3506     }
3507 }
3508 
3509 /*
3510  * Adjust the score of common words.
3511  */
3512     static int
3513 score_wordcount_adj(slang, score, word, split)
3514     slang_T	*slang;
3515     int		score;
3516     char_u	*word;
3517     int		split;	    /* word was split, less bonus */
3518 {
3519     hashitem_T	*hi;
3520     wordcount_T	*wc;
3521     int		bonus;
3522     int		newscore;
3523 
3524     hi = hash_find(&slang->sl_wordcount, word);
3525     if (!HASHITEM_EMPTY(hi))
3526     {
3527 	wc = HI2WC(hi);
3528 	if (wc->wc_count < SCORE_THRES2)
3529 	    bonus = SCORE_COMMON1;
3530 	else if (wc->wc_count < SCORE_THRES3)
3531 	    bonus = SCORE_COMMON2;
3532 	else
3533 	    bonus = SCORE_COMMON3;
3534 	if (split)
3535 	    newscore = score - bonus / 2;
3536 	else
3537 	    newscore = score - bonus;
3538 	if (newscore < 0)
3539 	    return 0;
3540 	return newscore;
3541     }
3542     return score;
3543 }
3544 
3545 /*
3546  * SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
3547  * Return SP_*ERROR flags.
3548  */
3549     static int
3550 read_sofo_section(fd, slang)
3551     FILE	*fd;
3552     slang_T	*slang;
3553 {
3554     int		cnt;
3555     char_u	*from, *to;
3556     int		res;
3557 
3558     slang->sl_sofo = TRUE;
3559 
3560     /* <sofofromlen> <sofofrom> */
3561     from = read_cnt_string(fd, 2, &cnt);
3562     if (cnt < 0)
3563 	return cnt;
3564 
3565     /* <sofotolen> <sofoto> */
3566     to = read_cnt_string(fd, 2, &cnt);
3567     if (cnt < 0)
3568     {
3569 	vim_free(from);
3570 	return cnt;
3571     }
3572 
3573     /* Store the info in slang->sl_sal and/or slang->sl_sal_first. */
3574     if (from != NULL && to != NULL)
3575 	res = set_sofo(slang, from, to);
3576     else if (from != NULL || to != NULL)
3577 	res = SP_FORMERROR;    /* only one of two strings is an error */
3578     else
3579 	res = 0;
3580 
3581     vim_free(from);
3582     vim_free(to);
3583     return res;
3584 }
3585 
3586 /*
3587  * Read the compound section from the .spl file:
3588  *	<compmax> <compminlen> <compsylmax> <compoptions> <compflags>
3589  * Returns SP_*ERROR flags.
3590  */
3591     static int
3592 read_compound(fd, slang, len)
3593     FILE	*fd;
3594     slang_T	*slang;
3595     int		len;
3596 {
3597     int		todo = len;
3598     int		c;
3599     int		atstart;
3600     char_u	*pat;
3601     char_u	*pp;
3602     char_u	*cp;
3603     char_u	*ap;
3604     char_u	*crp;
3605     int		cnt;
3606     garray_T	*gap;
3607 
3608     if (todo < 2)
3609 	return SP_FORMERROR;	/* need at least two bytes */
3610 
3611     --todo;
3612     c = getc(fd);					/* <compmax> */
3613     if (c < 2)
3614 	c = MAXWLEN;
3615     slang->sl_compmax = c;
3616 
3617     --todo;
3618     c = getc(fd);					/* <compminlen> */
3619     if (c < 1)
3620 	c = 0;
3621     slang->sl_compminlen = c;
3622 
3623     --todo;
3624     c = getc(fd);					/* <compsylmax> */
3625     if (c < 1)
3626 	c = MAXWLEN;
3627     slang->sl_compsylmax = c;
3628 
3629     c = getc(fd);					/* <compoptions> */
3630     if (c != 0)
3631 	ungetc(c, fd);	    /* be backwards compatible with Vim 7.0b */
3632     else
3633     {
3634 	--todo;
3635 	c = getc(fd);	    /* only use the lower byte for now */
3636 	--todo;
3637 	slang->sl_compoptions = c;
3638 
3639 	gap = &slang->sl_comppat;
3640 	c = get2c(fd);					/* <comppatcount> */
3641 	todo -= 2;
3642 	ga_init2(gap, sizeof(char_u *), c);
3643 	if (ga_grow(gap, c) == OK)
3644 	    while (--c >= 0)
3645 	    {
3646 		((char_u **)(gap->ga_data))[gap->ga_len++] =
3647 						 read_cnt_string(fd, 1, &cnt);
3648 					    /* <comppatlen> <comppattext> */
3649 		if (cnt < 0)
3650 		    return cnt;
3651 		todo -= cnt + 1;
3652 	    }
3653     }
3654     if (todo < 0)
3655 	return SP_FORMERROR;
3656 
3657     /* Turn the COMPOUNDRULE items into a regexp pattern:
3658      * "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$".
3659      * Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes.
3660      * Conversion to utf-8 may double the size. */
3661     c = todo * 2 + 7;
3662 #ifdef FEAT_MBYTE
3663     if (enc_utf8)
3664 	c += todo * 2;
3665 #endif
3666     pat = alloc((unsigned)c);
3667     if (pat == NULL)
3668 	return SP_OTHERERROR;
3669 
3670     /* We also need a list of all flags that can appear at the start and one
3671      * for all flags. */
3672     cp = alloc(todo + 1);
3673     if (cp == NULL)
3674     {
3675 	vim_free(pat);
3676 	return SP_OTHERERROR;
3677     }
3678     slang->sl_compstartflags = cp;
3679     *cp = NUL;
3680 
3681     ap = alloc(todo + 1);
3682     if (ap == NULL)
3683     {
3684 	vim_free(pat);
3685 	return SP_OTHERERROR;
3686     }
3687     slang->sl_compallflags = ap;
3688     *ap = NUL;
3689 
3690     /* And a list of all patterns in their original form, for checking whether
3691      * compounding may work in match_compoundrule().  This is freed when we
3692      * encounter a wildcard, the check doesn't work then. */
3693     crp = alloc(todo + 1);
3694     slang->sl_comprules = crp;
3695 
3696     pp = pat;
3697     *pp++ = '^';
3698     *pp++ = '\\';
3699     *pp++ = '(';
3700 
3701     atstart = 1;
3702     while (todo-- > 0)
3703     {
3704 	c = getc(fd);					/* <compflags> */
3705 	if (c == EOF)
3706 	{
3707 	    vim_free(pat);
3708 	    return SP_TRUNCERROR;
3709 	}
3710 
3711 	/* Add all flags to "sl_compallflags". */
3712 	if (vim_strchr((char_u *)"+*[]/", c) == NULL
3713 		&& !byte_in_str(slang->sl_compallflags, c))
3714 	{
3715 	    *ap++ = c;
3716 	    *ap = NUL;
3717 	}
3718 
3719 	if (atstart != 0)
3720 	{
3721 	    /* At start of item: copy flags to "sl_compstartflags".  For a
3722 	     * [abc] item set "atstart" to 2 and copy up to the ']'. */
3723 	    if (c == '[')
3724 		atstart = 2;
3725 	    else if (c == ']')
3726 		atstart = 0;
3727 	    else
3728 	    {
3729 		if (!byte_in_str(slang->sl_compstartflags, c))
3730 		{
3731 		    *cp++ = c;
3732 		    *cp = NUL;
3733 		}
3734 		if (atstart == 1)
3735 		    atstart = 0;
3736 	    }
3737 	}
3738 
3739 	/* Copy flag to "sl_comprules", unless we run into a wildcard. */
3740 	if (crp != NULL)
3741 	{
3742 	    if (c == '+' || c == '*')
3743 	    {
3744 		vim_free(slang->sl_comprules);
3745 		slang->sl_comprules = NULL;
3746 		crp = NULL;
3747 	    }
3748 	    else
3749 		*crp++ = c;
3750 	}
3751 
3752 	if (c == '/')	    /* slash separates two items */
3753 	{
3754 	    *pp++ = '\\';
3755 	    *pp++ = '|';
3756 	    atstart = 1;
3757 	}
3758 	else		    /* normal char, "[abc]" and '*' are copied as-is */
3759 	{
3760 	    if (c == '+' || c == '~')
3761 		*pp++ = '\\';	    /* "a+" becomes "a\+" */
3762 #ifdef FEAT_MBYTE
3763 	    if (enc_utf8)
3764 		pp += mb_char2bytes(c, pp);
3765 	    else
3766 #endif
3767 		*pp++ = c;
3768 	}
3769     }
3770 
3771     *pp++ = '\\';
3772     *pp++ = ')';
3773     *pp++ = '$';
3774     *pp = NUL;
3775 
3776     if (crp != NULL)
3777 	*crp = NUL;
3778 
3779     slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
3780     vim_free(pat);
3781     if (slang->sl_compprog == NULL)
3782 	return SP_FORMERROR;
3783 
3784     return 0;
3785 }
3786 
3787 /*
3788  * Return TRUE if byte "n" appears in "str".
3789  * Like strchr() but independent of locale.
3790  */
3791     static int
3792 byte_in_str(str, n)
3793     char_u	*str;
3794     int		n;
3795 {
3796     char_u	*p;
3797 
3798     for (p = str; *p != NUL; ++p)
3799 	if (*p == n)
3800 	    return TRUE;
3801     return FALSE;
3802 }
3803 
3804 #define SY_MAXLEN   30
3805 typedef struct syl_item_S
3806 {
3807     char_u	sy_chars[SY_MAXLEN];	    /* the sequence of chars */
3808     int		sy_len;
3809 } syl_item_T;
3810 
3811 /*
3812  * Truncate "slang->sl_syllable" at the first slash and put the following items
3813  * in "slang->sl_syl_items".
3814  */
3815     static int
3816 init_syl_tab(slang)
3817     slang_T	*slang;
3818 {
3819     char_u	*p;
3820     char_u	*s;
3821     int		l;
3822     syl_item_T	*syl;
3823 
3824     ga_init2(&slang->sl_syl_items, sizeof(syl_item_T), 4);
3825     p = vim_strchr(slang->sl_syllable, '/');
3826     while (p != NULL)
3827     {
3828 	*p++ = NUL;
3829 	if (*p == NUL)	    /* trailing slash */
3830 	    break;
3831 	s = p;
3832 	p = vim_strchr(p, '/');
3833 	if (p == NULL)
3834 	    l = (int)STRLEN(s);
3835 	else
3836 	    l = (int)(p - s);
3837 	if (l >= SY_MAXLEN)
3838 	    return SP_FORMERROR;
3839 	if (ga_grow(&slang->sl_syl_items, 1) == FAIL)
3840 	    return SP_OTHERERROR;
3841 	syl = ((syl_item_T *)slang->sl_syl_items.ga_data)
3842 					       + slang->sl_syl_items.ga_len++;
3843 	vim_strncpy(syl->sy_chars, s, l);
3844 	syl->sy_len = l;
3845     }
3846     return OK;
3847 }
3848 
3849 /*
3850  * Count the number of syllables in "word".
3851  * When "word" contains spaces the syllables after the last space are counted.
3852  * Returns zero if syllables are not defines.
3853  */
3854     static int
3855 count_syllables(slang, word)
3856     slang_T	*slang;
3857     char_u	*word;
3858 {
3859     int		cnt = 0;
3860     int		skip = FALSE;
3861     char_u	*p;
3862     int		len;
3863     int		i;
3864     syl_item_T	*syl;
3865     int		c;
3866 
3867     if (slang->sl_syllable == NULL)
3868 	return 0;
3869 
3870     for (p = word; *p != NUL; p += len)
3871     {
3872 	/* When running into a space reset counter. */
3873 	if (*p == ' ')
3874 	{
3875 	    len = 1;
3876 	    cnt = 0;
3877 	    continue;
3878 	}
3879 
3880 	/* Find longest match of syllable items. */
3881 	len = 0;
3882 	for (i = 0; i < slang->sl_syl_items.ga_len; ++i)
3883 	{
3884 	    syl = ((syl_item_T *)slang->sl_syl_items.ga_data) + i;
3885 	    if (syl->sy_len > len
3886 			       && STRNCMP(p, syl->sy_chars, syl->sy_len) == 0)
3887 		len = syl->sy_len;
3888 	}
3889 	if (len != 0)	/* found a match, count syllable  */
3890 	{
3891 	    ++cnt;
3892 	    skip = FALSE;
3893 	}
3894 	else
3895 	{
3896 	    /* No recognized syllable item, at least a syllable char then? */
3897 #ifdef FEAT_MBYTE
3898 	    c = mb_ptr2char(p);
3899 	    len = (*mb_ptr2len)(p);
3900 #else
3901 	    c = *p;
3902 	    len = 1;
3903 #endif
3904 	    if (vim_strchr(slang->sl_syllable, c) == NULL)
3905 		skip = FALSE;	    /* No, search for next syllable */
3906 	    else if (!skip)
3907 	    {
3908 		++cnt;		    /* Yes, count it */
3909 		skip = TRUE;	    /* don't count following syllable chars */
3910 	    }
3911 	}
3912     }
3913     return cnt;
3914 }
3915 
3916 /*
3917  * Set the SOFOFROM and SOFOTO items in language "lp".
3918  * Returns SP_*ERROR flags when there is something wrong.
3919  */
3920     static int
3921 set_sofo(lp, from, to)
3922     slang_T	*lp;
3923     char_u	*from;
3924     char_u	*to;
3925 {
3926     int		i;
3927 
3928 #ifdef FEAT_MBYTE
3929     garray_T	*gap;
3930     char_u	*s;
3931     char_u	*p;
3932     int		c;
3933     int		*inp;
3934 
3935     if (has_mbyte)
3936     {
3937 	/* Use "sl_sal" as an array with 256 pointers to a list of wide
3938 	 * characters.  The index is the low byte of the character.
3939 	 * The list contains from-to pairs with a terminating NUL.
3940 	 * sl_sal_first[] is used for latin1 "from" characters. */
3941 	gap = &lp->sl_sal;
3942 	ga_init2(gap, sizeof(int *), 1);
3943 	if (ga_grow(gap, 256) == FAIL)
3944 	    return SP_OTHERERROR;
3945 	vim_memset(gap->ga_data, 0, sizeof(int *) * 256);
3946 	gap->ga_len = 256;
3947 
3948 	/* First count the number of items for each list.  Temporarily use
3949 	 * sl_sal_first[] for this. */
3950 	for (p = from, s = to; *p != NUL && *s != NUL; )
3951 	{
3952 	    c = mb_cptr2char_adv(&p);
3953 	    mb_cptr_adv(s);
3954 	    if (c >= 256)
3955 		++lp->sl_sal_first[c & 0xff];
3956 	}
3957 	if (*p != NUL || *s != NUL)	    /* lengths differ */
3958 	    return SP_FORMERROR;
3959 
3960 	/* Allocate the lists. */
3961 	for (i = 0; i < 256; ++i)
3962 	    if (lp->sl_sal_first[i] > 0)
3963 	    {
3964 		p = alloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1));
3965 		if (p == NULL)
3966 		    return SP_OTHERERROR;
3967 		((int **)gap->ga_data)[i] = (int *)p;
3968 		*(int *)p = 0;
3969 	    }
3970 
3971 	/* Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal
3972 	 * list. */
3973 	vim_memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
3974 	for (p = from, s = to; *p != NUL && *s != NUL; )
3975 	{
3976 	    c = mb_cptr2char_adv(&p);
3977 	    i = mb_cptr2char_adv(&s);
3978 	    if (c >= 256)
3979 	    {
3980 		/* Append the from-to chars at the end of the list with
3981 		 * the low byte. */
3982 		inp = ((int **)gap->ga_data)[c & 0xff];
3983 		while (*inp != 0)
3984 		    ++inp;
3985 		*inp++ = c;		/* from char */
3986 		*inp++ = i;		/* to char */
3987 		*inp++ = NUL;		/* NUL at the end */
3988 	    }
3989 	    else
3990 		/* mapping byte to char is done in sl_sal_first[] */
3991 		lp->sl_sal_first[c] = i;
3992 	}
3993     }
3994     else
3995 #endif
3996     {
3997 	/* mapping bytes to bytes is done in sl_sal_first[] */
3998 	if (STRLEN(from) != STRLEN(to))
3999 	    return SP_FORMERROR;
4000 
4001 	for (i = 0; to[i] != NUL; ++i)
4002 	    lp->sl_sal_first[from[i]] = to[i];
4003 	lp->sl_sal.ga_len = 1;		/* indicates we have soundfolding */
4004     }
4005 
4006     return 0;
4007 }
4008 
4009 /*
4010  * Fill the first-index table for "lp".
4011  */
4012     static void
4013 set_sal_first(lp)
4014     slang_T	*lp;
4015 {
4016     salfirst_T	*sfirst;
4017     int		i;
4018     salitem_T	*smp;
4019     int		c;
4020     garray_T	*gap = &lp->sl_sal;
4021 
4022     sfirst = lp->sl_sal_first;
4023     for (i = 0; i < 256; ++i)
4024 	sfirst[i] = -1;
4025     smp = (salitem_T *)gap->ga_data;
4026     for (i = 0; i < gap->ga_len; ++i)
4027     {
4028 #ifdef FEAT_MBYTE
4029 	if (has_mbyte)
4030 	    /* Use the lowest byte of the first character.  For latin1 it's
4031 	     * the character, for other encodings it should differ for most
4032 	     * characters. */
4033 	    c = *smp[i].sm_lead_w & 0xff;
4034 	else
4035 #endif
4036 	    c = *smp[i].sm_lead;
4037 	if (sfirst[c] == -1)
4038 	{
4039 	    sfirst[c] = i;
4040 #ifdef FEAT_MBYTE
4041 	    if (has_mbyte)
4042 	    {
4043 		int		n;
4044 
4045 		/* Make sure all entries with this byte are following each
4046 		 * other.  Move the ones that are in the wrong position.  Do
4047 		 * keep the same ordering! */
4048 		while (i + 1 < gap->ga_len
4049 				       && (*smp[i + 1].sm_lead_w & 0xff) == c)
4050 		    /* Skip over entry with same index byte. */
4051 		    ++i;
4052 
4053 		for (n = 1; i + n < gap->ga_len; ++n)
4054 		    if ((*smp[i + n].sm_lead_w & 0xff) == c)
4055 		    {
4056 			salitem_T  tsal;
4057 
4058 			/* Move entry with same index byte after the entries
4059 			 * we already found. */
4060 			++i;
4061 			--n;
4062 			tsal = smp[i + n];
4063 			mch_memmove(smp + i + 1, smp + i,
4064 						       sizeof(salitem_T) * n);
4065 			smp[i] = tsal;
4066 		    }
4067 	    }
4068 #endif
4069 	}
4070     }
4071 }
4072 
4073 #ifdef FEAT_MBYTE
4074 /*
4075  * Turn a multi-byte string into a wide character string.
4076  * Return it in allocated memory (NULL for out-of-memory)
4077  */
4078     static int *
4079 mb_str2wide(s)
4080     char_u	*s;
4081 {
4082     int		*res;
4083     char_u	*p;
4084     int		i = 0;
4085 
4086     res = (int *)alloc(sizeof(int) * (mb_charlen(s) + 1));
4087     if (res != NULL)
4088     {
4089 	for (p = s; *p != NUL; )
4090 	    res[i++] = mb_ptr2char_adv(&p);
4091 	res[i] = NUL;
4092     }
4093     return res;
4094 }
4095 #endif
4096 
4097 /*
4098  * Read a tree from the .spl or .sug file.
4099  * Allocates the memory and stores pointers in "bytsp" and "idxsp".
4100  * This is skipped when the tree has zero length.
4101  * Returns zero when OK, SP_ value for an error.
4102  */
4103     static int
4104 spell_read_tree(fd, bytsp, idxsp, prefixtree, prefixcnt)
4105     FILE	*fd;
4106     char_u	**bytsp;
4107     idx_T	**idxsp;
4108     int		prefixtree;	/* TRUE for the prefix tree */
4109     int		prefixcnt;	/* when "prefixtree" is TRUE: prefix count */
4110 {
4111     int		len;
4112     int		idx;
4113     char_u	*bp;
4114     idx_T	*ip;
4115 
4116     /* The tree size was computed when writing the file, so that we can
4117      * allocate it as one long block. <nodecount> */
4118     len = get4c(fd);
4119     if (len < 0)
4120 	return SP_TRUNCERROR;
4121     if (len > 0)
4122     {
4123 	/* Allocate the byte array. */
4124 	bp = lalloc((long_u)len, TRUE);
4125 	if (bp == NULL)
4126 	    return SP_OTHERERROR;
4127 	*bytsp = bp;
4128 
4129 	/* Allocate the index array. */
4130 	ip = (idx_T *)lalloc_clear((long_u)(len * sizeof(int)), TRUE);
4131 	if (ip == NULL)
4132 	    return SP_OTHERERROR;
4133 	*idxsp = ip;
4134 
4135 	/* Recursively read the tree and store it in the array. */
4136 	idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt);
4137 	if (idx < 0)
4138 	    return idx;
4139     }
4140     return 0;
4141 }
4142 
4143 /*
4144  * Read one row of siblings from the spell file and store it in the byte array
4145  * "byts" and index array "idxs".  Recursively read the children.
4146  *
4147  * NOTE: The code here must match put_node()!
4148  *
4149  * Returns the index (>= 0) following the siblings.
4150  * Returns SP_TRUNCERROR if the file is shorter than expected.
4151  * Returns SP_FORMERROR if there is a format error.
4152  */
4153     static idx_T
4154 read_tree_node(fd, byts, idxs, maxidx, startidx, prefixtree, maxprefcondnr)
4155     FILE	*fd;
4156     char_u	*byts;
4157     idx_T	*idxs;
4158     int		maxidx;		    /* size of arrays */
4159     idx_T	startidx;	    /* current index in "byts" and "idxs" */
4160     int		prefixtree;	    /* TRUE for reading PREFIXTREE */
4161     int		maxprefcondnr;	    /* maximum for <prefcondnr> */
4162 {
4163     int		len;
4164     int		i;
4165     int		n;
4166     idx_T	idx = startidx;
4167     int		c;
4168     int		c2;
4169 #define SHARED_MASK	0x8000000
4170 
4171     len = getc(fd);					/* <siblingcount> */
4172     if (len <= 0)
4173 	return SP_TRUNCERROR;
4174 
4175     if (startidx + len >= maxidx)
4176 	return SP_FORMERROR;
4177     byts[idx++] = len;
4178 
4179     /* Read the byte values, flag/region bytes and shared indexes. */
4180     for (i = 1; i <= len; ++i)
4181     {
4182 	c = getc(fd);					/* <byte> */
4183 	if (c < 0)
4184 	    return SP_TRUNCERROR;
4185 	if (c <= BY_SPECIAL)
4186 	{
4187 	    if (c == BY_NOFLAGS && !prefixtree)
4188 	    {
4189 		/* No flags, all regions. */
4190 		idxs[idx] = 0;
4191 		c = 0;
4192 	    }
4193 	    else if (c != BY_INDEX)
4194 	    {
4195 		if (prefixtree)
4196 		{
4197 		    /* Read the optional pflags byte, the prefix ID and the
4198 		     * condition nr.  In idxs[] store the prefix ID in the low
4199 		     * byte, the condition index shifted up 8 bits, the flags
4200 		     * shifted up 24 bits. */
4201 		    if (c == BY_FLAGS)
4202 			c = getc(fd) << 24;		/* <pflags> */
4203 		    else
4204 			c = 0;
4205 
4206 		    c |= getc(fd);			/* <affixID> */
4207 
4208 		    n = get2c(fd);			/* <prefcondnr> */
4209 		    if (n >= maxprefcondnr)
4210 			return SP_FORMERROR;
4211 		    c |= (n << 8);
4212 		}
4213 		else /* c must be BY_FLAGS or BY_FLAGS2 */
4214 		{
4215 		    /* Read flags and optional region and prefix ID.  In
4216 		     * idxs[] the flags go in the low two bytes, region above
4217 		     * that and prefix ID above the region. */
4218 		    c2 = c;
4219 		    c = getc(fd);			/* <flags> */
4220 		    if (c2 == BY_FLAGS2)
4221 			c = (getc(fd) << 8) + c;	/* <flags2> */
4222 		    if (c & WF_REGION)
4223 			c = (getc(fd) << 16) + c;	/* <region> */
4224 		    if (c & WF_AFX)
4225 			c = (getc(fd) << 24) + c;	/* <affixID> */
4226 		}
4227 
4228 		idxs[idx] = c;
4229 		c = 0;
4230 	    }
4231 	    else /* c == BY_INDEX */
4232 	    {
4233 							/* <nodeidx> */
4234 		n = get3c(fd);
4235 		if (n < 0 || n >= maxidx)
4236 		    return SP_FORMERROR;
4237 		idxs[idx] = n + SHARED_MASK;
4238 		c = getc(fd);				/* <xbyte> */
4239 	    }
4240 	}
4241 	byts[idx++] = c;
4242     }
4243 
4244     /* Recursively read the children for non-shared siblings.
4245      * Skip the end-of-word ones (zero byte value) and the shared ones (and
4246      * remove SHARED_MASK) */
4247     for (i = 1; i <= len; ++i)
4248 	if (byts[startidx + i] != 0)
4249 	{
4250 	    if (idxs[startidx + i] & SHARED_MASK)
4251 		idxs[startidx + i] &= ~SHARED_MASK;
4252 	    else
4253 	    {
4254 		idxs[startidx + i] = idx;
4255 		idx = read_tree_node(fd, byts, idxs, maxidx, idx,
4256 						     prefixtree, maxprefcondnr);
4257 		if (idx < 0)
4258 		    break;
4259 	    }
4260 	}
4261 
4262     return idx;
4263 }
4264 
4265 /*
4266  * Parse 'spelllang' and set buf->b_langp accordingly.
4267  * Returns NULL if it's OK, an error message otherwise.
4268  */
4269     char_u *
4270 did_set_spelllang(buf)
4271     buf_T	*buf;
4272 {
4273     garray_T	ga;
4274     char_u	*splp;
4275     char_u	*region;
4276     char_u	region_cp[3];
4277     int		filename;
4278     int		region_mask;
4279     slang_T	*slang;
4280     int		c;
4281     char_u	lang[MAXWLEN + 1];
4282     char_u	spf_name[MAXPATHL];
4283     int		len;
4284     char_u	*p;
4285     int		round;
4286     char_u	*spf;
4287     char_u	*use_region = NULL;
4288     int		dont_use_region = FALSE;
4289     int		nobreak = FALSE;
4290     int		i, j;
4291     langp_T	*lp, *lp2;
4292     static int	recursive = FALSE;
4293     char_u	*ret_msg = NULL;
4294     char_u	*spl_copy;
4295 
4296     /* We don't want to do this recursively.  May happen when a language is
4297      * not available and the SpellFileMissing autocommand opens a new buffer
4298      * in which 'spell' is set. */
4299     if (recursive)
4300 	return NULL;
4301     recursive = TRUE;
4302 
4303     ga_init2(&ga, sizeof(langp_T), 2);
4304     clear_midword(buf);
4305 
4306     /* Make a copy of 'spellang', the SpellFileMissing autocommands may change
4307      * it under our fingers. */
4308     spl_copy = vim_strsave(buf->b_p_spl);
4309     if (spl_copy == NULL)
4310 	goto theend;
4311 
4312     /* loop over comma separated language names. */
4313     for (splp = spl_copy; *splp != NUL; )
4314     {
4315 	/* Get one language name. */
4316 	copy_option_part(&splp, lang, MAXWLEN, ",");
4317 
4318 	region = NULL;
4319 	len = (int)STRLEN(lang);
4320 
4321 	/* If the name ends in ".spl" use it as the name of the spell file.
4322 	 * If there is a region name let "region" point to it and remove it
4323 	 * from the name. */
4324 	if (len > 4 && fnamecmp(lang + len - 4, ".spl") == 0)
4325 	{
4326 	    filename = TRUE;
4327 
4328 	    /* Locate a region and remove it from the file name. */
4329 	    p = vim_strchr(gettail(lang), '_');
4330 	    if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
4331 						      && !ASCII_ISALPHA(p[3]))
4332 	    {
4333 		vim_strncpy(region_cp, p + 1, 2);
4334 		mch_memmove(p, p + 3, len - (p - lang) - 2);
4335 		len -= 3;
4336 		region = region_cp;
4337 	    }
4338 	    else
4339 		dont_use_region = TRUE;
4340 
4341 	    /* Check if we loaded this language before. */
4342 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4343 		if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
4344 		    break;
4345 	}
4346 	else
4347 	{
4348 	    filename = FALSE;
4349 	    if (len > 3 && lang[len - 3] == '_')
4350 	    {
4351 		region = lang + len - 2;
4352 		len -= 3;
4353 		lang[len] = NUL;
4354 	    }
4355 	    else
4356 		dont_use_region = TRUE;
4357 
4358 	    /* Check if we loaded this language before. */
4359 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4360 		if (STRICMP(lang, slang->sl_name) == 0)
4361 		    break;
4362 	}
4363 
4364 	if (region != NULL)
4365 	{
4366 	    /* If the region differs from what was used before then don't
4367 	     * use it for 'spellfile'. */
4368 	    if (use_region != NULL && STRCMP(region, use_region) != 0)
4369 		dont_use_region = TRUE;
4370 	    use_region = region;
4371 	}
4372 
4373 	/* If not found try loading the language now. */
4374 	if (slang == NULL)
4375 	{
4376 	    if (filename)
4377 		(void)spell_load_file(lang, lang, NULL, FALSE);
4378 	    else
4379 	    {
4380 		spell_load_lang(lang);
4381 #ifdef FEAT_AUTOCMD
4382 		/* SpellFileMissing autocommands may do anything, including
4383 		 * destroying the buffer we are using... */
4384 		if (!buf_valid(buf))
4385 		{
4386 		    ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer";
4387 		    goto theend;
4388 		}
4389 #endif
4390 	    }
4391 	}
4392 
4393 	/*
4394 	 * Loop over the languages, there can be several files for "lang".
4395 	 */
4396 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4397 	    if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
4398 			 : STRICMP(lang, slang->sl_name) == 0)
4399 	    {
4400 		region_mask = REGION_ALL;
4401 		if (!filename && region != NULL)
4402 		{
4403 		    /* find region in sl_regions */
4404 		    c = find_region(slang->sl_regions, region);
4405 		    if (c == REGION_ALL)
4406 		    {
4407 			if (slang->sl_add)
4408 			{
4409 			    if (*slang->sl_regions != NUL)
4410 				/* This addition file is for other regions. */
4411 				region_mask = 0;
4412 			}
4413 			else
4414 			    /* This is probably an error.  Give a warning and
4415 			     * accept the words anyway. */
4416 			    smsg((char_u *)
4417 				    _("Warning: region %s not supported"),
4418 								      region);
4419 		    }
4420 		    else
4421 			region_mask = 1 << c;
4422 		}
4423 
4424 		if (region_mask != 0)
4425 		{
4426 		    if (ga_grow(&ga, 1) == FAIL)
4427 		    {
4428 			ga_clear(&ga);
4429 			ret_msg = e_outofmem;
4430 			goto theend;
4431 		    }
4432 		    LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
4433 		    LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
4434 		    ++ga.ga_len;
4435 		    use_midword(slang, buf);
4436 		    if (slang->sl_nobreak)
4437 			nobreak = TRUE;
4438 		}
4439 	    }
4440     }
4441 
4442     /* round 0: load int_wordlist, if possible.
4443      * round 1: load first name in 'spellfile'.
4444      * round 2: load second name in 'spellfile.
4445      * etc. */
4446     spf = buf->b_p_spf;
4447     for (round = 0; round == 0 || *spf != NUL; ++round)
4448     {
4449 	if (round == 0)
4450 	{
4451 	    /* Internal wordlist, if there is one. */
4452 	    if (int_wordlist == NULL)
4453 		continue;
4454 	    int_wordlist_spl(spf_name);
4455 	}
4456 	else
4457 	{
4458 	    /* One entry in 'spellfile'. */
4459 	    copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
4460 	    STRCAT(spf_name, ".spl");
4461 
4462 	    /* If it was already found above then skip it. */
4463 	    for (c = 0; c < ga.ga_len; ++c)
4464 	    {
4465 		p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
4466 		if (p != NULL && fullpathcmp(spf_name, p, FALSE) == FPC_SAME)
4467 		    break;
4468 	    }
4469 	    if (c < ga.ga_len)
4470 		continue;
4471 	}
4472 
4473 	/* Check if it was loaded already. */
4474 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4475 	    if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
4476 		break;
4477 	if (slang == NULL)
4478 	{
4479 	    /* Not loaded, try loading it now.  The language name includes the
4480 	     * region name, the region is ignored otherwise.  for int_wordlist
4481 	     * use an arbitrary name. */
4482 	    if (round == 0)
4483 		STRCPY(lang, "internal wordlist");
4484 	    else
4485 	    {
4486 		vim_strncpy(lang, gettail(spf_name), MAXWLEN);
4487 		p = vim_strchr(lang, '.');
4488 		if (p != NULL)
4489 		    *p = NUL;	/* truncate at ".encoding.add" */
4490 	    }
4491 	    slang = spell_load_file(spf_name, lang, NULL, TRUE);
4492 
4493 	    /* If one of the languages has NOBREAK we assume the addition
4494 	     * files also have this. */
4495 	    if (slang != NULL && nobreak)
4496 		slang->sl_nobreak = TRUE;
4497 	}
4498 	if (slang != NULL && ga_grow(&ga, 1) == OK)
4499 	{
4500 	    region_mask = REGION_ALL;
4501 	    if (use_region != NULL && !dont_use_region)
4502 	    {
4503 		/* find region in sl_regions */
4504 		c = find_region(slang->sl_regions, use_region);
4505 		if (c != REGION_ALL)
4506 		    region_mask = 1 << c;
4507 		else if (*slang->sl_regions != NUL)
4508 		    /* This spell file is for other regions. */
4509 		    region_mask = 0;
4510 	    }
4511 
4512 	    if (region_mask != 0)
4513 	    {
4514 		LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
4515 		LANGP_ENTRY(ga, ga.ga_len)->lp_sallang = NULL;
4516 		LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL;
4517 		LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
4518 		++ga.ga_len;
4519 		use_midword(slang, buf);
4520 	    }
4521 	}
4522     }
4523 
4524     /* Everything is fine, store the new b_langp value. */
4525     ga_clear(&buf->b_langp);
4526     buf->b_langp = ga;
4527 
4528     /* For each language figure out what language to use for sound folding and
4529      * REP items.  If the language doesn't support it itself use another one
4530      * with the same name.  E.g. for "en-math" use "en". */
4531     for (i = 0; i < ga.ga_len; ++i)
4532     {
4533 	lp = LANGP_ENTRY(ga, i);
4534 
4535 	/* sound folding */
4536 	if (lp->lp_slang->sl_sal.ga_len > 0)
4537 	    /* language does sound folding itself */
4538 	    lp->lp_sallang = lp->lp_slang;
4539 	else
4540 	    /* find first similar language that does sound folding */
4541 	    for (j = 0; j < ga.ga_len; ++j)
4542 	    {
4543 		lp2 = LANGP_ENTRY(ga, j);
4544 		if (lp2->lp_slang->sl_sal.ga_len > 0
4545 			&& STRNCMP(lp->lp_slang->sl_name,
4546 					      lp2->lp_slang->sl_name, 2) == 0)
4547 		{
4548 		    lp->lp_sallang = lp2->lp_slang;
4549 		    break;
4550 		}
4551 	    }
4552 
4553 	/* REP items */
4554 	if (lp->lp_slang->sl_rep.ga_len > 0)
4555 	    /* language has REP items itself */
4556 	    lp->lp_replang = lp->lp_slang;
4557 	else
4558 	    /* find first similar language that has REP items */
4559 	    for (j = 0; j < ga.ga_len; ++j)
4560 	    {
4561 		lp2 = LANGP_ENTRY(ga, j);
4562 		if (lp2->lp_slang->sl_rep.ga_len > 0
4563 			&& STRNCMP(lp->lp_slang->sl_name,
4564 					      lp2->lp_slang->sl_name, 2) == 0)
4565 		{
4566 		    lp->lp_replang = lp2->lp_slang;
4567 		    break;
4568 		}
4569 	    }
4570     }
4571 
4572 theend:
4573     vim_free(spl_copy);
4574     recursive = FALSE;
4575     return ret_msg;
4576 }
4577 
4578 /*
4579  * Clear the midword characters for buffer "buf".
4580  */
4581     static void
4582 clear_midword(buf)
4583     buf_T	*buf;
4584 {
4585     vim_memset(buf->b_spell_ismw, 0, 256);
4586 #ifdef FEAT_MBYTE
4587     vim_free(buf->b_spell_ismw_mb);
4588     buf->b_spell_ismw_mb = NULL;
4589 #endif
4590 }
4591 
4592 /*
4593  * Use the "sl_midword" field of language "lp" for buffer "buf".
4594  * They add up to any currently used midword characters.
4595  */
4596     static void
4597 use_midword(lp, buf)
4598     slang_T	*lp;
4599     buf_T	*buf;
4600 {
4601     char_u	*p;
4602 
4603     if (lp->sl_midword == NULL)	    /* there aren't any */
4604 	return;
4605 
4606     for (p = lp->sl_midword; *p != NUL; )
4607 #ifdef FEAT_MBYTE
4608 	if (has_mbyte)
4609 	{
4610 	    int	    c, l, n;
4611 	    char_u  *bp;
4612 
4613 	    c = mb_ptr2char(p);
4614 	    l = (*mb_ptr2len)(p);
4615 	    if (c < 256 && l <= 2)
4616 		buf->b_spell_ismw[c] = TRUE;
4617 	    else if (buf->b_spell_ismw_mb == NULL)
4618 		/* First multi-byte char in "b_spell_ismw_mb". */
4619 		buf->b_spell_ismw_mb = vim_strnsave(p, l);
4620 	    else
4621 	    {
4622 		/* Append multi-byte chars to "b_spell_ismw_mb". */
4623 		n = (int)STRLEN(buf->b_spell_ismw_mb);
4624 		bp = vim_strnsave(buf->b_spell_ismw_mb, n + l);
4625 		if (bp != NULL)
4626 		{
4627 		    vim_free(buf->b_spell_ismw_mb);
4628 		    buf->b_spell_ismw_mb = bp;
4629 		    vim_strncpy(bp + n, p, l);
4630 		}
4631 	    }
4632 	    p += l;
4633 	}
4634 	else
4635 #endif
4636 	    buf->b_spell_ismw[*p++] = TRUE;
4637 }
4638 
4639 /*
4640  * Find the region "region[2]" in "rp" (points to "sl_regions").
4641  * Each region is simply stored as the two characters of it's name.
4642  * Returns the index if found (first is 0), REGION_ALL if not found.
4643  */
4644     static int
4645 find_region(rp, region)
4646     char_u	*rp;
4647     char_u	*region;
4648 {
4649     int		i;
4650 
4651     for (i = 0; ; i += 2)
4652     {
4653 	if (rp[i] == NUL)
4654 	    return REGION_ALL;
4655 	if (rp[i] == region[0] && rp[i + 1] == region[1])
4656 	    break;
4657     }
4658     return i / 2;
4659 }
4660 
4661 /*
4662  * Return case type of word:
4663  * w word	0
4664  * Word		WF_ONECAP
4665  * W WORD	WF_ALLCAP
4666  * WoRd	wOrd	WF_KEEPCAP
4667  */
4668     static int
4669 captype(word, end)
4670     char_u	*word;
4671     char_u	*end;	    /* When NULL use up to NUL byte. */
4672 {
4673     char_u	*p;
4674     int		c;
4675     int		firstcap;
4676     int		allcap;
4677     int		past_second = FALSE;	/* past second word char */
4678 
4679     /* find first letter */
4680     for (p = word; !spell_iswordp_nmw(p); mb_ptr_adv(p))
4681 	if (end == NULL ? *p == NUL : p >= end)
4682 	    return 0;	    /* only non-word characters, illegal word */
4683 #ifdef FEAT_MBYTE
4684     if (has_mbyte)
4685 	c = mb_ptr2char_adv(&p);
4686     else
4687 #endif
4688 	c = *p++;
4689     firstcap = allcap = SPELL_ISUPPER(c);
4690 
4691     /*
4692      * Need to check all letters to find a word with mixed upper/lower.
4693      * But a word with an upper char only at start is a ONECAP.
4694      */
4695     for ( ; end == NULL ? *p != NUL : p < end; mb_ptr_adv(p))
4696 	if (spell_iswordp_nmw(p))
4697 	{
4698 	    c = PTR2CHAR(p);
4699 	    if (!SPELL_ISUPPER(c))
4700 	    {
4701 		/* UUl -> KEEPCAP */
4702 		if (past_second && allcap)
4703 		    return WF_KEEPCAP;
4704 		allcap = FALSE;
4705 	    }
4706 	    else if (!allcap)
4707 		/* UlU -> KEEPCAP */
4708 		return WF_KEEPCAP;
4709 	    past_second = TRUE;
4710 	}
4711 
4712     if (allcap)
4713 	return WF_ALLCAP;
4714     if (firstcap)
4715 	return WF_ONECAP;
4716     return 0;
4717 }
4718 
4719 /*
4720  * Like captype() but for a KEEPCAP word add ONECAP if the word starts with a
4721  * capital.  So that make_case_word() can turn WOrd into Word.
4722  * Add ALLCAP for "WOrD".
4723  */
4724     static int
4725 badword_captype(word, end)
4726     char_u	*word;
4727     char_u	*end;
4728 {
4729     int		flags = captype(word, end);
4730     int		c;
4731     int		l, u;
4732     int		first;
4733     char_u	*p;
4734 
4735     if (flags & WF_KEEPCAP)
4736     {
4737 	/* Count the number of UPPER and lower case letters. */
4738 	l = u = 0;
4739 	first = FALSE;
4740 	for (p = word; p < end; mb_ptr_adv(p))
4741 	{
4742 	    c = PTR2CHAR(p);
4743 	    if (SPELL_ISUPPER(c))
4744 	    {
4745 		++u;
4746 		if (p == word)
4747 		    first = TRUE;
4748 	    }
4749 	    else
4750 		++l;
4751 	}
4752 
4753 	/* If there are more UPPER than lower case letters suggest an
4754 	 * ALLCAP word.  Otherwise, if the first letter is UPPER then
4755 	 * suggest ONECAP.  Exception: "ALl" most likely should be "All",
4756 	 * require three upper case letters. */
4757 	if (u > l && u > 2)
4758 	    flags |= WF_ALLCAP;
4759 	else if (first)
4760 	    flags |= WF_ONECAP;
4761 
4762 	if (u >= 2 && l >= 2)	/* maCARONI maCAroni */
4763 	    flags |= WF_MIXCAP;
4764     }
4765     return flags;
4766 }
4767 
4768 # if defined(FEAT_MBYTE) || defined(EXITFREE) || defined(PROTO)
4769 /*
4770  * Free all languages.
4771  */
4772     void
4773 spell_free_all()
4774 {
4775     slang_T	*slang;
4776     buf_T	*buf;
4777     char_u	fname[MAXPATHL];
4778 
4779     /* Go through all buffers and handle 'spelllang'. */
4780     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4781 	ga_clear(&buf->b_langp);
4782 
4783     while (first_lang != NULL)
4784     {
4785 	slang = first_lang;
4786 	first_lang = slang->sl_next;
4787 	slang_free(slang);
4788     }
4789 
4790     if (int_wordlist != NULL)
4791     {
4792 	/* Delete the internal wordlist and its .spl file */
4793 	mch_remove(int_wordlist);
4794 	int_wordlist_spl(fname);
4795 	mch_remove(fname);
4796 	vim_free(int_wordlist);
4797 	int_wordlist = NULL;
4798     }
4799 
4800     init_spell_chartab();
4801 
4802     vim_free(repl_to);
4803     repl_to = NULL;
4804     vim_free(repl_from);
4805     repl_from = NULL;
4806 }
4807 # endif
4808 
4809 # if defined(FEAT_MBYTE) || defined(PROTO)
4810 /*
4811  * Clear all spelling tables and reload them.
4812  * Used after 'encoding' is set and when ":mkspell" was used.
4813  */
4814     void
4815 spell_reload()
4816 {
4817     buf_T	*buf;
4818     win_T	*wp;
4819 
4820     /* Initialize the table for spell_iswordp(). */
4821     init_spell_chartab();
4822 
4823     /* Unload all allocated memory. */
4824     spell_free_all();
4825 
4826     /* Go through all buffers and handle 'spelllang'. */
4827     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4828     {
4829 	/* Only load the wordlists when 'spelllang' is set and there is a
4830 	 * window for this buffer in which 'spell' is set. */
4831 	if (*buf->b_p_spl != NUL)
4832 	{
4833 	    FOR_ALL_WINDOWS(wp)
4834 		if (wp->w_buffer == buf && wp->w_p_spell)
4835 		{
4836 		    (void)did_set_spelllang(buf);
4837 # ifdef FEAT_WINDOWS
4838 		    break;
4839 # endif
4840 		}
4841 	}
4842     }
4843 }
4844 # endif
4845 
4846 /*
4847  * Reload the spell file "fname" if it's loaded.
4848  */
4849     static void
4850 spell_reload_one(fname, added_word)
4851     char_u	*fname;
4852     int		added_word;	/* invoked through "zg" */
4853 {
4854     slang_T	*slang;
4855     int		didit = FALSE;
4856 
4857     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4858     {
4859 	if (fullpathcmp(fname, slang->sl_fname, FALSE) == FPC_SAME)
4860 	{
4861 	    slang_clear(slang);
4862 	    if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
4863 		/* reloading failed, clear the language */
4864 		slang_clear(slang);
4865 	    redraw_all_later(SOME_VALID);
4866 	    didit = TRUE;
4867 	}
4868     }
4869 
4870     /* When "zg" was used and the file wasn't loaded yet, should redo
4871      * 'spelllang' to load it now. */
4872     if (added_word && !didit)
4873 	did_set_spelllang(curbuf);
4874 }
4875 
4876 
4877 /*
4878  * Functions for ":mkspell".
4879  */
4880 
4881 #define MAXLINELEN  500		/* Maximum length in bytes of a line in a .aff
4882 				   and .dic file. */
4883 /*
4884  * Main structure to store the contents of a ".aff" file.
4885  */
4886 typedef struct afffile_S
4887 {
4888     char_u	*af_enc;	/* "SET", normalized, alloc'ed string or NULL */
4889     int		af_flagtype;	/* AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG */
4890     unsigned	af_rare;	/* RARE ID for rare word */
4891     unsigned	af_keepcase;	/* KEEPCASE ID for keep-case word */
4892     unsigned	af_bad;		/* BAD ID for banned word */
4893     unsigned	af_needaffix;	/* NEEDAFFIX ID */
4894     unsigned	af_circumfix;	/* CIRCUMFIX ID */
4895     unsigned	af_needcomp;	/* NEEDCOMPOUND ID */
4896     unsigned	af_comproot;	/* COMPOUNDROOT ID */
4897     unsigned	af_compforbid;	/* COMPOUNDFORBIDFLAG ID */
4898     unsigned	af_comppermit;	/* COMPOUNDPERMITFLAG ID */
4899     unsigned	af_nosuggest;	/* NOSUGGEST ID */
4900     int		af_pfxpostpone;	/* postpone prefixes without chop string and
4901 				   without flags */
4902     hashtab_T	af_pref;	/* hashtable for prefixes, affheader_T */
4903     hashtab_T	af_suff;	/* hashtable for suffixes, affheader_T */
4904     hashtab_T	af_comp;	/* hashtable for compound flags, compitem_T */
4905 } afffile_T;
4906 
4907 #define AFT_CHAR	0	/* flags are one character */
4908 #define AFT_LONG	1	/* flags are two characters */
4909 #define AFT_CAPLONG	2	/* flags are one or two characters */
4910 #define AFT_NUM		3	/* flags are numbers, comma separated */
4911 
4912 typedef struct affentry_S affentry_T;
4913 /* Affix entry from ".aff" file.  Used for prefixes and suffixes. */
4914 struct affentry_S
4915 {
4916     affentry_T	*ae_next;	/* next affix with same name/number */
4917     char_u	*ae_chop;	/* text to chop off basic word (can be NULL) */
4918     char_u	*ae_add;	/* text to add to basic word (can be NULL) */
4919     char_u	*ae_flags;	/* flags on the affix (can be NULL) */
4920     char_u	*ae_cond;	/* condition (NULL for ".") */
4921     regprog_T	*ae_prog;	/* regexp program for ae_cond or NULL */
4922     char	ae_compforbid;	/* COMPOUNDFORBIDFLAG found */
4923     char	ae_comppermit;	/* COMPOUNDPERMITFLAG found */
4924 };
4925 
4926 #ifdef FEAT_MBYTE
4927 # define AH_KEY_LEN 17		/* 2 x 8 bytes + NUL */
4928 #else
4929 # define AH_KEY_LEN 7		/* 6 digits + NUL */
4930 #endif
4931 
4932 /* Affix header from ".aff" file.  Used for af_pref and af_suff. */
4933 typedef struct affheader_S
4934 {
4935     char_u	ah_key[AH_KEY_LEN]; /* key for hashtab == name of affix */
4936     unsigned	ah_flag;	/* affix name as number, uses "af_flagtype" */
4937     int		ah_newID;	/* prefix ID after renumbering; 0 if not used */
4938     int		ah_combine;	/* suffix may combine with prefix */
4939     int		ah_follows;	/* another affix block should be following */
4940     affentry_T	*ah_first;	/* first affix entry */
4941 } affheader_T;
4942 
4943 #define HI2AH(hi)   ((affheader_T *)(hi)->hi_key)
4944 
4945 /* Flag used in compound items. */
4946 typedef struct compitem_S
4947 {
4948     char_u	ci_key[AH_KEY_LEN]; /* key for hashtab == name of compound */
4949     unsigned	ci_flag;	/* affix name as number, uses "af_flagtype" */
4950     int		ci_newID;	/* affix ID after renumbering. */
4951 } compitem_T;
4952 
4953 #define HI2CI(hi)   ((compitem_T *)(hi)->hi_key)
4954 
4955 /*
4956  * Structure that is used to store the items in the word tree.  This avoids
4957  * the need to keep track of each allocated thing, everything is freed all at
4958  * once after ":mkspell" is done.
4959  * Note: "sb_next" must be just before "sb_data" to make sure the alignment of
4960  * "sb_data" is correct for systems where pointers must be aligned on
4961  * pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc).
4962  */
4963 #define  SBLOCKSIZE 16000	/* size of sb_data */
4964 typedef struct sblock_S sblock_T;
4965 struct sblock_S
4966 {
4967     int		sb_used;	/* nr of bytes already in use */
4968     sblock_T	*sb_next;	/* next block in list */
4969     char_u	sb_data[1];	/* data, actually longer */
4970 };
4971 
4972 /*
4973  * A node in the tree.
4974  */
4975 typedef struct wordnode_S wordnode_T;
4976 struct wordnode_S
4977 {
4978     union   /* shared to save space */
4979     {
4980 	char_u	hashkey[6];	/* the hash key, only used while compressing */
4981 	int	index;		/* index in written nodes (valid after first
4982 				   round) */
4983     } wn_u1;
4984     union   /* shared to save space */
4985     {
4986 	wordnode_T *next;	/* next node with same hash key */
4987 	wordnode_T *wnode;	/* parent node that will write this node */
4988     } wn_u2;
4989     wordnode_T	*wn_child;	/* child (next byte in word) */
4990     wordnode_T  *wn_sibling;	/* next sibling (alternate byte in word,
4991 				   always sorted) */
4992     int		wn_refs;	/* Nr. of references to this node.  Only
4993 				   relevant for first node in a list of
4994 				   siblings, in following siblings it is
4995 				   always one. */
4996     char_u	wn_byte;	/* Byte for this node. NUL for word end */
4997 
4998     /* Info for when "wn_byte" is NUL.
4999      * In PREFIXTREE "wn_region" is used for the prefcondnr.
5000      * In the soundfolded word tree "wn_flags" has the MSW of the wordnr and
5001      * "wn_region" the LSW of the wordnr. */
5002     char_u	wn_affixID;	/* supported/required prefix ID or 0 */
5003     short_u	wn_flags;	/* WF_ flags */
5004     short	wn_region;	/* region mask */
5005 
5006 #ifdef SPELL_PRINTTREE
5007     int		wn_nr;		/* sequence nr for printing */
5008 #endif
5009 };
5010 
5011 #define WN_MASK	 0xffff		/* mask relevant bits of "wn_flags" */
5012 
5013 #define HI2WN(hi)    (wordnode_T *)((hi)->hi_key)
5014 
5015 /*
5016  * Info used while reading the spell files.
5017  */
5018 typedef struct spellinfo_S
5019 {
5020     wordnode_T	*si_foldroot;	/* tree with case-folded words */
5021     long	si_foldwcount;	/* nr of words in si_foldroot */
5022 
5023     wordnode_T	*si_keeproot;	/* tree with keep-case words */
5024     long	si_keepwcount;	/* nr of words in si_keeproot */
5025 
5026     wordnode_T	*si_prefroot;	/* tree with postponed prefixes */
5027 
5028     long	si_sugtree;	/* creating the soundfolding trie */
5029 
5030     sblock_T	*si_blocks;	/* memory blocks used */
5031     long	si_blocks_cnt;	/* memory blocks allocated */
5032     long	si_compress_cnt;    /* words to add before lowering
5033 				       compression limit */
5034     wordnode_T	*si_first_free; /* List of nodes that have been freed during
5035 				   compression, linked by "wn_child" field. */
5036     long	si_free_count;	/* number of nodes in si_first_free */
5037 #ifdef SPELL_PRINTTREE
5038     int		si_wordnode_nr;	/* sequence nr for nodes */
5039 #endif
5040     buf_T	*si_spellbuf;	/* buffer used to store soundfold word table */
5041 
5042     int		si_ascii;	/* handling only ASCII words */
5043     int		si_add;		/* addition file */
5044     int		si_clear_chartab;   /* when TRUE clear char tables */
5045     int		si_region;	/* region mask */
5046     vimconv_T	si_conv;	/* for conversion to 'encoding' */
5047     int		si_memtot;	/* runtime memory used */
5048     int		si_verbose;	/* verbose messages */
5049     int		si_msg_count;	/* number of words added since last message */
5050     char_u	*si_info;	/* info text chars or NULL  */
5051     int		si_region_count; /* number of regions supported (1 when there
5052 				    are no regions) */
5053     char_u	si_region_name[16]; /* region names; used only if
5054 				     * si_region_count > 1) */
5055 
5056     garray_T	si_rep;		/* list of fromto_T entries from REP lines */
5057     garray_T	si_repsal;	/* list of fromto_T entries from REPSAL lines */
5058     garray_T	si_sal;		/* list of fromto_T entries from SAL lines */
5059     char_u	*si_sofofr;	/* SOFOFROM text */
5060     char_u	*si_sofoto;	/* SOFOTO text */
5061     int		si_nosugfile;	/* NOSUGFILE item found */
5062     int		si_nosplitsugs;	/* NOSPLITSUGS item found */
5063     int		si_followup;	/* soundsalike: ? */
5064     int		si_collapse;	/* soundsalike: ? */
5065     hashtab_T	si_commonwords;	/* hashtable for common words */
5066     time_t	si_sugtime;	/* timestamp for .sug file */
5067     int		si_rem_accents;	/* soundsalike: remove accents */
5068     garray_T	si_map;		/* MAP info concatenated */
5069     char_u	*si_midword;	/* MIDWORD chars or NULL  */
5070     int		si_compmax;	/* max nr of words for compounding */
5071     int		si_compminlen;	/* minimal length for compounding */
5072     int		si_compsylmax;	/* max nr of syllables for compounding */
5073     int		si_compoptions;	/* COMP_ flags */
5074     garray_T	si_comppat;	/* CHECKCOMPOUNDPATTERN items, each stored as
5075 				   a string */
5076     char_u	*si_compflags;	/* flags used for compounding */
5077     char_u	si_nobreak;	/* NOBREAK */
5078     char_u	*si_syllable;	/* syllable string */
5079     garray_T	si_prefcond;	/* table with conditions for postponed
5080 				 * prefixes, each stored as a string */
5081     int		si_newprefID;	/* current value for ah_newID */
5082     int		si_newcompID;	/* current value for compound ID */
5083 } spellinfo_T;
5084 
5085 static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
5086 static int is_aff_rule __ARGS((char_u **items, int itemcnt, char *rulename, int	 mincount));
5087 static void aff_process_flags __ARGS((afffile_T *affile, affentry_T *entry));
5088 static int spell_info_item __ARGS((char_u *s));
5089 static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u	*fname, int lnum));
5090 static unsigned get_affitem __ARGS((int flagtype, char_u **pp));
5091 static void process_compflags __ARGS((spellinfo_T *spin, afffile_T *aff, char_u *compflags));
5092 static void check_renumber __ARGS((spellinfo_T *spin));
5093 static int flag_in_afflist __ARGS((int flagtype, char_u *afflist, unsigned flag));
5094 static void aff_check_number __ARGS((int spinval, int affval, char *name));
5095 static void aff_check_string __ARGS((char_u *spinval, char_u *affval, char *name));
5096 static int str_equal __ARGS((char_u *s1, char_u	*s2));
5097 static void add_fromto __ARGS((spellinfo_T *spin, garray_T *gap, char_u	*from, char_u *to));
5098 static int sal_to_bool __ARGS((char_u *s));
5099 static int has_non_ascii __ARGS((char_u *s));
5100 static void spell_free_aff __ARGS((afffile_T *aff));
5101 static int spell_read_dic __ARGS((spellinfo_T *spin, char_u *fname, afffile_T *affile));
5102 static int get_affix_flags __ARGS((afffile_T *affile, char_u *afflist));
5103 static int get_pfxlist __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
5104 static void get_compflags __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
5105 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 condit, int flags, char_u *pfxlist, int pfxlen));
5106 static int spell_read_wordfile __ARGS((spellinfo_T *spin, char_u *fname));
5107 static void *getroom __ARGS((spellinfo_T *spin, size_t len, int align));
5108 static char_u *getroom_save __ARGS((spellinfo_T *spin, char_u *s));
5109 static void free_blocks __ARGS((sblock_T *bl));
5110 static wordnode_T *wordtree_alloc __ARGS((spellinfo_T *spin));
5111 static int store_word __ARGS((spellinfo_T *spin, char_u *word, int flags, int region, char_u *pfxlist, int need_affix));
5112 static int tree_add_word __ARGS((spellinfo_T *spin, char_u *word, wordnode_T *tree, int flags, int region, int affixID));
5113 static wordnode_T *get_wordnode __ARGS((spellinfo_T *spin));
5114 static int deref_wordnode __ARGS((spellinfo_T *spin, wordnode_T *node));
5115 static void free_wordnode __ARGS((spellinfo_T *spin, wordnode_T *n));
5116 static void wordtree_compress __ARGS((spellinfo_T *spin, wordnode_T *root));
5117 static int node_compress __ARGS((spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot));
5118 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
5119 static void put_sugtime __ARGS((spellinfo_T *spin, FILE *fd));
5120 static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
5121 static void clear_node __ARGS((wordnode_T *node));
5122 static int put_node __ARGS((FILE *fd, wordnode_T *node, int idx, int regionmask, int prefixtree));
5123 static void spell_make_sugfile __ARGS((spellinfo_T *spin, char_u *wfname));
5124 static int sug_filltree __ARGS((spellinfo_T *spin, slang_T *slang));
5125 static int sug_maketable __ARGS((spellinfo_T *spin));
5126 static int sug_filltable __ARGS((spellinfo_T *spin, wordnode_T *node, int startwordnr, garray_T *gap));
5127 static int offset2bytes __ARGS((int nr, char_u *buf));
5128 static int bytes2offset __ARGS((char_u **pp));
5129 static void sug_write __ARGS((spellinfo_T *spin, char_u *fname));
5130 static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int overwrite, int added_word));
5131 static void spell_message __ARGS((spellinfo_T *spin, char_u *str));
5132 static void init_spellfile __ARGS((void));
5133 
5134 /* In the postponed prefixes tree wn_flags is used to store the WFP_ flags,
5135  * but it must be negative to indicate the prefix tree to tree_add_word().
5136  * Use a negative number with the lower 8 bits zero. */
5137 #define PFX_FLAGS	-256
5138 
5139 /* flags for "condit" argument of store_aff_word() */
5140 #define CONDIT_COMB	1	/* affix must combine */
5141 #define CONDIT_CFIX	2	/* affix must have CIRCUMFIX flag */
5142 #define CONDIT_SUF	4	/* add a suffix for matching flags */
5143 #define CONDIT_AFF	8	/* word already has an affix */
5144 
5145 /*
5146  * Tunable parameters for when the tree is compressed.  See 'mkspellmem'.
5147  */
5148 static long compress_start = 30000;	/* memory / SBLOCKSIZE */
5149 static long compress_inc = 100;		/* memory / SBLOCKSIZE */
5150 static long compress_added = 500000;	/* word count */
5151 
5152 #ifdef SPELL_PRINTTREE
5153 /*
5154  * For debugging the tree code: print the current tree in a (more or less)
5155  * readable format, so that we can see what happens when adding a word and/or
5156  * compressing the tree.
5157  * Based on code from Olaf Seibert.
5158  */
5159 #define PRINTLINESIZE	1000
5160 #define PRINTWIDTH	6
5161 
5162 #define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \
5163 	    PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2)
5164 
5165 static char line1[PRINTLINESIZE];
5166 static char line2[PRINTLINESIZE];
5167 static char line3[PRINTLINESIZE];
5168 
5169     static void
5170 spell_clear_flags(wordnode_T *node)
5171 {
5172     wordnode_T	*np;
5173 
5174     for (np = node; np != NULL; np = np->wn_sibling)
5175     {
5176 	np->wn_u1.index = FALSE;
5177 	spell_clear_flags(np->wn_child);
5178     }
5179 }
5180 
5181     static void
5182 spell_print_node(wordnode_T *node, int depth)
5183 {
5184     if (node->wn_u1.index)
5185     {
5186 	/* Done this node before, print the reference. */
5187 	PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0);
5188 	PRINTSOME(line2, depth, "    ", 0, 0);
5189 	PRINTSOME(line3, depth, "    ", 0, 0);
5190 	msg(line1);
5191 	msg(line2);
5192 	msg(line3);
5193     }
5194     else
5195     {
5196 	node->wn_u1.index = TRUE;
5197 
5198 	if (node->wn_byte != NUL)
5199 	{
5200 	    if (node->wn_child != NULL)
5201 		PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0);
5202 	    else
5203 		/* Cannot happen? */
5204 		PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0);
5205 	}
5206 	else
5207 	    PRINTSOME(line1, depth, " $    ", 0, 0);
5208 
5209 	PRINTSOME(line2, depth, "%d/%d    ", node->wn_nr, node->wn_refs);
5210 
5211 	if (node->wn_sibling != NULL)
5212 	    PRINTSOME(line3, depth, " |    ", 0, 0);
5213 	else
5214 	    PRINTSOME(line3, depth, "      ", 0, 0);
5215 
5216 	if (node->wn_byte == NUL)
5217 	{
5218 	    msg(line1);
5219 	    msg(line2);
5220 	    msg(line3);
5221 	}
5222 
5223 	/* do the children */
5224 	if (node->wn_byte != NUL && node->wn_child != NULL)
5225 	    spell_print_node(node->wn_child, depth + 1);
5226 
5227 	/* do the siblings */
5228 	if (node->wn_sibling != NULL)
5229 	{
5230 	    /* get rid of all parent details except | */
5231 	    STRCPY(line1, line3);
5232 	    STRCPY(line2, line3);
5233 	    spell_print_node(node->wn_sibling, depth);
5234 	}
5235     }
5236 }
5237 
5238     static void
5239 spell_print_tree(wordnode_T *root)
5240 {
5241     if (root != NULL)
5242     {
5243 	/* Clear the "wn_u1.index" fields, used to remember what has been
5244 	 * done. */
5245 	spell_clear_flags(root);
5246 
5247 	/* Recursively print the tree. */
5248 	spell_print_node(root, 0);
5249     }
5250 }
5251 #endif /* SPELL_PRINTTREE */
5252 
5253 /*
5254  * Read the affix file "fname".
5255  * Returns an afffile_T, NULL for complete failure.
5256  */
5257     static afffile_T *
5258 spell_read_aff(spin, fname)
5259     spellinfo_T	*spin;
5260     char_u	*fname;
5261 {
5262     FILE	*fd;
5263     afffile_T	*aff;
5264     char_u	rline[MAXLINELEN];
5265     char_u	*line;
5266     char_u	*pc = NULL;
5267 #define MAXITEMCNT  30
5268     char_u	*(items[MAXITEMCNT]);
5269     int		itemcnt;
5270     char_u	*p;
5271     int		lnum = 0;
5272     affheader_T	*cur_aff = NULL;
5273     int		did_postpone_prefix = FALSE;
5274     int		aff_todo = 0;
5275     hashtab_T	*tp;
5276     char_u	*low = NULL;
5277     char_u	*fol = NULL;
5278     char_u	*upp = NULL;
5279     int		do_rep;
5280     int		do_repsal;
5281     int		do_sal;
5282     int		do_mapline;
5283     int		found_map = FALSE;
5284     hashitem_T	*hi;
5285     int		l;
5286     int		compminlen = 0;		/* COMPOUNDMIN value */
5287     int		compsylmax = 0;		/* COMPOUNDSYLMAX value */
5288     int		compoptions = 0;	/* COMP_ flags */
5289     int		compmax = 0;		/* COMPOUNDWORDMAX value */
5290     char_u	*compflags = NULL;	/* COMPOUNDFLAG and COMPOUNDRULE
5291 					   concatenated */
5292     char_u	*midword = NULL;	/* MIDWORD value */
5293     char_u	*syllable = NULL;	/* SYLLABLE value */
5294     char_u	*sofofrom = NULL;	/* SOFOFROM value */
5295     char_u	*sofoto = NULL;		/* SOFOTO value */
5296 
5297     /*
5298      * Open the file.
5299      */
5300     fd = mch_fopen((char *)fname, "r");
5301     if (fd == NULL)
5302     {
5303 	EMSG2(_(e_notopen), fname);
5304 	return NULL;
5305     }
5306 
5307     vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname);
5308     spell_message(spin, IObuff);
5309 
5310     /* Only do REP lines when not done in another .aff file already. */
5311     do_rep = spin->si_rep.ga_len == 0;
5312 
5313     /* Only do REPSAL lines when not done in another .aff file already. */
5314     do_repsal = spin->si_repsal.ga_len == 0;
5315 
5316     /* Only do SAL lines when not done in another .aff file already. */
5317     do_sal = spin->si_sal.ga_len == 0;
5318 
5319     /* Only do MAP lines when not done in another .aff file already. */
5320     do_mapline = spin->si_map.ga_len == 0;
5321 
5322     /*
5323      * Allocate and init the afffile_T structure.
5324      */
5325     aff = (afffile_T *)getroom(spin, sizeof(afffile_T), TRUE);
5326     if (aff == NULL)
5327     {
5328 	fclose(fd);
5329 	return NULL;
5330     }
5331     hash_init(&aff->af_pref);
5332     hash_init(&aff->af_suff);
5333     hash_init(&aff->af_comp);
5334 
5335     /*
5336      * Read all the lines in the file one by one.
5337      */
5338     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
5339     {
5340 	line_breakcheck();
5341 	++lnum;
5342 
5343 	/* Skip comment lines. */
5344 	if (*rline == '#')
5345 	    continue;
5346 
5347 	/* Convert from "SET" to 'encoding' when needed. */
5348 	vim_free(pc);
5349 #ifdef FEAT_MBYTE
5350 	if (spin->si_conv.vc_type != CONV_NONE)
5351 	{
5352 	    pc = string_convert(&spin->si_conv, rline, NULL);
5353 	    if (pc == NULL)
5354 	    {
5355 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
5356 							   fname, lnum, rline);
5357 		continue;
5358 	    }
5359 	    line = pc;
5360 	}
5361 	else
5362 #endif
5363 	{
5364 	    pc = NULL;
5365 	    line = rline;
5366 	}
5367 
5368 	/* Split the line up in white separated items.  Put a NUL after each
5369 	 * item. */
5370 	itemcnt = 0;
5371 	for (p = line; ; )
5372 	{
5373 	    while (*p != NUL && *p <= ' ')  /* skip white space and CR/NL */
5374 		++p;
5375 	    if (*p == NUL)
5376 		break;
5377 	    if (itemcnt == MAXITEMCNT)	    /* too many items */
5378 		break;
5379 	    items[itemcnt++] = p;
5380 	    /* A few items have arbitrary text argument, don't split them. */
5381 	    if (itemcnt == 2 && spell_info_item(items[0]))
5382 		while (*p >= ' ' || *p == TAB)    /* skip until CR/NL */
5383 		    ++p;
5384 	    else
5385 		while (*p > ' ')    /* skip until white space or CR/NL */
5386 		    ++p;
5387 	    if (*p == NUL)
5388 		break;
5389 	    *p++ = NUL;
5390 	}
5391 
5392 	/* Handle non-empty lines. */
5393 	if (itemcnt > 0)
5394 	{
5395 	    if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL)
5396 	    {
5397 #ifdef FEAT_MBYTE
5398 		/* Setup for conversion from "ENC" to 'encoding'. */
5399 		aff->af_enc = enc_canonize(items[1]);
5400 		if (aff->af_enc != NULL && !spin->si_ascii
5401 			&& convert_setup(&spin->si_conv, aff->af_enc,
5402 							       p_enc) == FAIL)
5403 		    smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
5404 					       fname, aff->af_enc, p_enc);
5405 		spin->si_conv.vc_fail = TRUE;
5406 #else
5407 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
5408 #endif
5409 	    }
5410 	    else if (is_aff_rule(items, itemcnt, "FLAG", 2)
5411 					      && aff->af_flagtype == AFT_CHAR)
5412 	    {
5413 		if (STRCMP(items[1], "long") == 0)
5414 		    aff->af_flagtype = AFT_LONG;
5415 		else if (STRCMP(items[1], "num") == 0)
5416 		    aff->af_flagtype = AFT_NUM;
5417 		else if (STRCMP(items[1], "caplong") == 0)
5418 		    aff->af_flagtype = AFT_CAPLONG;
5419 		else
5420 		    smsg((char_u *)_("Invalid value for FLAG in %s line %d: %s"),
5421 			    fname, lnum, items[1]);
5422 		if (aff->af_rare != 0
5423 			|| aff->af_keepcase != 0
5424 			|| aff->af_bad != 0
5425 			|| aff->af_needaffix != 0
5426 			|| aff->af_circumfix != 0
5427 			|| aff->af_needcomp != 0
5428 			|| aff->af_comproot != 0
5429 			|| aff->af_nosuggest != 0
5430 			|| compflags != NULL
5431 			|| aff->af_suff.ht_used > 0
5432 			|| aff->af_pref.ht_used > 0)
5433 		    smsg((char_u *)_("FLAG after using flags in %s line %d: %s"),
5434 			    fname, lnum, items[1]);
5435 	    }
5436 	    else if (spell_info_item(items[0]))
5437 	    {
5438 		    p = (char_u *)getroom(spin,
5439 			    (spin->si_info == NULL ? 0 : STRLEN(spin->si_info))
5440 			    + STRLEN(items[0])
5441 			    + STRLEN(items[1]) + 3, FALSE);
5442 		    if (p != NULL)
5443 		    {
5444 			if (spin->si_info != NULL)
5445 			{
5446 			    STRCPY(p, spin->si_info);
5447 			    STRCAT(p, "\n");
5448 			}
5449 			STRCAT(p, items[0]);
5450 			STRCAT(p, " ");
5451 			STRCAT(p, items[1]);
5452 			spin->si_info = p;
5453 		    }
5454 	    }
5455 	    else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
5456 							   && midword == NULL)
5457 	    {
5458 		midword = getroom_save(spin, items[1]);
5459 	    }
5460 	    else if (is_aff_rule(items, itemcnt, "TRY", 2))
5461 	    {
5462 		/* ignored, we look in the tree for what chars may appear */
5463 	    }
5464 	    /* TODO: remove "RAR" later */
5465 	    else if ((is_aff_rule(items, itemcnt, "RAR", 2)
5466 			|| is_aff_rule(items, itemcnt, "RARE", 2))
5467 							 && aff->af_rare == 0)
5468 	    {
5469 		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
5470 								 fname, lnum);
5471 	    }
5472 	    /* TODO: remove "KEP" later */
5473 	    else if ((is_aff_rule(items, itemcnt, "KEP", 2)
5474 			|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
5475 						     && aff->af_keepcase == 0)
5476 	    {
5477 		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
5478 								 fname, lnum);
5479 	    }
5480 	    else if ((is_aff_rule(items, itemcnt, "BAD", 2)
5481 			|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
5482 							  && aff->af_bad == 0)
5483 	    {
5484 		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
5485 								 fname, lnum);
5486 	    }
5487 	    else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
5488 						    && aff->af_needaffix == 0)
5489 	    {
5490 		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
5491 								 fname, lnum);
5492 	    }
5493 	    else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
5494 						    && aff->af_circumfix == 0)
5495 	    {
5496 		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
5497 								 fname, lnum);
5498 	    }
5499 	    else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
5500 						    && aff->af_nosuggest == 0)
5501 	    {
5502 		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
5503 								 fname, lnum);
5504 	    }
5505 	    else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
5506 			|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
5507 						     && aff->af_needcomp == 0)
5508 	    {
5509 		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
5510 								 fname, lnum);
5511 	    }
5512 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
5513 						     && aff->af_comproot == 0)
5514 	    {
5515 		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
5516 								 fname, lnum);
5517 	    }
5518 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
5519 						   && aff->af_compforbid == 0)
5520 	    {
5521 		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
5522 								 fname, lnum);
5523 		if (aff->af_pref.ht_used > 0)
5524 		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
5525 			    fname, lnum);
5526 	    }
5527 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
5528 						   && aff->af_comppermit == 0)
5529 	    {
5530 		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
5531 								 fname, lnum);
5532 		if (aff->af_pref.ht_used > 0)
5533 		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
5534 			    fname, lnum);
5535 	    }
5536 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2)
5537 							 && compflags == NULL)
5538 	    {
5539 		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
5540 		 * "Na" into "Na+", "1234" into "1234+". */
5541 		p = getroom(spin, STRLEN(items[1]) + 2, FALSE);
5542 		if (p != NULL)
5543 		{
5544 		    STRCPY(p, items[1]);
5545 		    STRCAT(p, "+");
5546 		    compflags = p;
5547 		}
5548 	    }
5549 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2))
5550 	    {
5551 		/* We don't use the count, but do check that it's a number and
5552 		 * not COMPOUNDRULE mistyped. */
5553 		if (atoi((char *)items[1]) == 0)
5554 		    smsg((char_u *)_("Wrong COMPOUNDRULES value in %s line %d: %s"),
5555 						       fname, lnum, items[1]);
5556 	    }
5557 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2))
5558 	    {
5559 		/* Concatenate this string to previously defined ones, using a
5560 		 * slash to separate them. */
5561 		l = (int)STRLEN(items[1]) + 1;
5562 		if (compflags != NULL)
5563 		    l += (int)STRLEN(compflags) + 1;
5564 		p = getroom(spin, l, FALSE);
5565 		if (p != NULL)
5566 		{
5567 		    if (compflags != NULL)
5568 		    {
5569 			STRCPY(p, compflags);
5570 			STRCAT(p, "/");
5571 		    }
5572 		    STRCAT(p, items[1]);
5573 		    compflags = p;
5574 		}
5575 	    }
5576 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
5577 							      && compmax == 0)
5578 	    {
5579 		compmax = atoi((char *)items[1]);
5580 		if (compmax == 0)
5581 		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
5582 						       fname, lnum, items[1]);
5583 	    }
5584 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2)
5585 							   && compminlen == 0)
5586 	    {
5587 		compminlen = atoi((char *)items[1]);
5588 		if (compminlen == 0)
5589 		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
5590 						       fname, lnum, items[1]);
5591 	    }
5592 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2)
5593 							   && compsylmax == 0)
5594 	    {
5595 		compsylmax = atoi((char *)items[1]);
5596 		if (compsylmax == 0)
5597 		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
5598 						       fname, lnum, items[1]);
5599 	    }
5600 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1))
5601 	    {
5602 		compoptions |= COMP_CHECKDUP;
5603 	    }
5604 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1))
5605 	    {
5606 		compoptions |= COMP_CHECKREP;
5607 	    }
5608 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1))
5609 	    {
5610 		compoptions |= COMP_CHECKCASE;
5611 	    }
5612 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1))
5613 	    {
5614 		compoptions |= COMP_CHECKTRIPLE;
5615 	    }
5616 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2))
5617 	    {
5618 		if (atoi((char *)items[1]) == 0)
5619 		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
5620 						       fname, lnum, items[1]);
5621 	    }
5622 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3))
5623 	    {
5624 		garray_T    *gap = &spin->si_comppat;
5625 		int	    i;
5626 
5627 		/* Only add the couple if it isn't already there. */
5628 		for (i = 0; i < gap->ga_len - 1; i += 2)
5629 		    if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0
5630 			    && STRCMP(((char_u **)(gap->ga_data))[i + 1],
5631 							       items[2]) == 0)
5632 			break;
5633 		if (i >= gap->ga_len && ga_grow(gap, 2) == OK)
5634 		{
5635 		    ((char_u **)(gap->ga_data))[gap->ga_len++]
5636 					       = getroom_save(spin, items[1]);
5637 		    ((char_u **)(gap->ga_data))[gap->ga_len++]
5638 					       = getroom_save(spin, items[2]);
5639 		}
5640 	    }
5641 	    else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
5642 							  && syllable == NULL)
5643 	    {
5644 		syllable = getroom_save(spin, items[1]);
5645 	    }
5646 	    else if (is_aff_rule(items, itemcnt, "NOBREAK", 1))
5647 	    {
5648 		spin->si_nobreak = TRUE;
5649 	    }
5650 	    else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1))
5651 	    {
5652 		spin->si_nosplitsugs = TRUE;
5653 	    }
5654 	    else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1))
5655 	    {
5656 		spin->si_nosugfile = TRUE;
5657 	    }
5658 	    else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1))
5659 	    {
5660 		aff->af_pfxpostpone = TRUE;
5661 	    }
5662 	    else if ((STRCMP(items[0], "PFX") == 0
5663 					      || STRCMP(items[0], "SFX") == 0)
5664 		    && aff_todo == 0
5665 		    && itemcnt >= 4)
5666 	    {
5667 		int	lasti = 4;
5668 		char_u	key[AH_KEY_LEN];
5669 
5670 		if (*items[0] == 'P')
5671 		    tp = &aff->af_pref;
5672 		else
5673 		    tp = &aff->af_suff;
5674 
5675 		/* Myspell allows the same affix name to be used multiple
5676 		 * times.  The affix files that do this have an undocumented
5677 		 * "S" flag on all but the last block, thus we check for that
5678 		 * and store it in ah_follows. */
5679 		vim_strncpy(key, items[1], AH_KEY_LEN - 1);
5680 		hi = hash_find(tp, key);
5681 		if (!HASHITEM_EMPTY(hi))
5682 		{
5683 		    cur_aff = HI2AH(hi);
5684 		    if (cur_aff->ah_combine != (*items[2] == 'Y'))
5685 			smsg((char_u *)_("Different combining flag in continued affix block in %s line %d: %s"),
5686 						   fname, lnum, items[1]);
5687 		    if (!cur_aff->ah_follows)
5688 			smsg((char_u *)_("Duplicate affix in %s line %d: %s"),
5689 						       fname, lnum, items[1]);
5690 		}
5691 		else
5692 		{
5693 		    /* New affix letter. */
5694 		    cur_aff = (affheader_T *)getroom(spin,
5695 						   sizeof(affheader_T), TRUE);
5696 		    if (cur_aff == NULL)
5697 			break;
5698 		    cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1],
5699 								 fname, lnum);
5700 		    if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN)
5701 			break;
5702 		    if (cur_aff->ah_flag == aff->af_bad
5703 			    || cur_aff->ah_flag == aff->af_rare
5704 			    || cur_aff->ah_flag == aff->af_keepcase
5705 			    || cur_aff->ah_flag == aff->af_needaffix
5706 			    || cur_aff->ah_flag == aff->af_circumfix
5707 			    || cur_aff->ah_flag == aff->af_nosuggest
5708 			    || cur_aff->ah_flag == aff->af_needcomp
5709 			    || cur_aff->ah_flag == aff->af_comproot)
5710 			smsg((char_u *)_("Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s line %d: %s"),
5711 						       fname, lnum, items[1]);
5712 		    STRCPY(cur_aff->ah_key, items[1]);
5713 		    hash_add(tp, cur_aff->ah_key);
5714 
5715 		    cur_aff->ah_combine = (*items[2] == 'Y');
5716 		}
5717 
5718 		/* Check for the "S" flag, which apparently means that another
5719 		 * block with the same affix name is following. */
5720 		if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0)
5721 		{
5722 		    ++lasti;
5723 		    cur_aff->ah_follows = TRUE;
5724 		}
5725 		else
5726 		    cur_aff->ah_follows = FALSE;
5727 
5728 		/* Myspell allows extra text after the item, but that might
5729 		 * mean mistakes go unnoticed.  Require a comment-starter. */
5730 		if (itemcnt > lasti && *items[lasti] != '#')
5731 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[lasti]);
5732 
5733 		if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0)
5734 		    smsg((char_u *)_("Expected Y or N in %s line %d: %s"),
5735 						       fname, lnum, items[2]);
5736 
5737 		if (*items[0] == 'P' && aff->af_pfxpostpone)
5738 		{
5739 		    if (cur_aff->ah_newID == 0)
5740 		    {
5741 			/* Use a new number in the .spl file later, to be able
5742 			 * to handle multiple .aff files. */
5743 			check_renumber(spin);
5744 			cur_aff->ah_newID = ++spin->si_newprefID;
5745 
5746 			/* We only really use ah_newID if the prefix is
5747 			 * postponed.  We know that only after handling all
5748 			 * the items. */
5749 			did_postpone_prefix = FALSE;
5750 		    }
5751 		    else
5752 			/* Did use the ID in a previous block. */
5753 			did_postpone_prefix = TRUE;
5754 		}
5755 
5756 		aff_todo = atoi((char *)items[3]);
5757 	    }
5758 	    else if ((STRCMP(items[0], "PFX") == 0
5759 					      || STRCMP(items[0], "SFX") == 0)
5760 		    && aff_todo > 0
5761 		    && STRCMP(cur_aff->ah_key, items[1]) == 0
5762 		    && itemcnt >= 5)
5763 	    {
5764 		affentry_T	*aff_entry;
5765 		int		upper = FALSE;
5766 		int		lasti = 5;
5767 
5768 		/* Myspell allows extra text after the item, but that might
5769 		 * mean mistakes go unnoticed.  Require a comment-starter.
5770 		 * Hunspell uses a "-" item. */
5771 		if (itemcnt > lasti && *items[lasti] != '#'
5772 			&& (STRCMP(items[lasti], "-") != 0
5773 						     || itemcnt != lasti + 1))
5774 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[lasti]);
5775 
5776 		/* New item for an affix letter. */
5777 		--aff_todo;
5778 		aff_entry = (affentry_T *)getroom(spin,
5779 						    sizeof(affentry_T), TRUE);
5780 		if (aff_entry == NULL)
5781 		    break;
5782 
5783 		if (STRCMP(items[2], "0") != 0)
5784 		    aff_entry->ae_chop = getroom_save(spin, items[2]);
5785 		if (STRCMP(items[3], "0") != 0)
5786 		{
5787 		    aff_entry->ae_add = getroom_save(spin, items[3]);
5788 
5789 		    /* Recognize flags on the affix: abcd/XYZ */
5790 		    aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/');
5791 		    if (aff_entry->ae_flags != NULL)
5792 		    {
5793 			*aff_entry->ae_flags++ = NUL;
5794 			aff_process_flags(aff, aff_entry);
5795 		    }
5796 		}
5797 
5798 		/* Don't use an affix entry with non-ASCII characters when
5799 		 * "spin->si_ascii" is TRUE. */
5800 		if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop)
5801 					  || has_non_ascii(aff_entry->ae_add)))
5802 		{
5803 		    aff_entry->ae_next = cur_aff->ah_first;
5804 		    cur_aff->ah_first = aff_entry;
5805 
5806 		    if (STRCMP(items[4], ".") != 0)
5807 		    {
5808 			char_u	buf[MAXLINELEN];
5809 
5810 			aff_entry->ae_cond = getroom_save(spin, items[4]);
5811 			if (*items[0] == 'P')
5812 			    sprintf((char *)buf, "^%s", items[4]);
5813 			else
5814 			    sprintf((char *)buf, "%s$", items[4]);
5815 			aff_entry->ae_prog = vim_regcomp(buf,
5816 					    RE_MAGIC + RE_STRING + RE_STRICT);
5817 			if (aff_entry->ae_prog == NULL)
5818 			    smsg((char_u *)_("Broken condition in %s line %d: %s"),
5819 						       fname, lnum, items[4]);
5820 		    }
5821 
5822 		    /* For postponed prefixes we need an entry in si_prefcond
5823 		     * for the condition.  Use an existing one if possible.
5824 		     * Can't be done for an affix with flags, ignoring
5825 		     * COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. */
5826 		    if (*items[0] == 'P' && aff->af_pfxpostpone
5827 					       && aff_entry->ae_flags == NULL)
5828 		    {
5829 			/* When the chop string is one lower-case letter and
5830 			 * the add string ends in the upper-case letter we set
5831 			 * the "upper" flag, clear "ae_chop" and remove the
5832 			 * letters from "ae_add".  The condition must either
5833 			 * be empty or start with the same letter. */
5834 			if (aff_entry->ae_chop != NULL
5835 				&& aff_entry->ae_add != NULL
5836 #ifdef FEAT_MBYTE
5837 				&& aff_entry->ae_chop[(*mb_ptr2len)(
5838 						   aff_entry->ae_chop)] == NUL
5839 #else
5840 				&& aff_entry->ae_chop[1] == NUL
5841 #endif
5842 				)
5843 			{
5844 			    int		c, c_up;
5845 
5846 			    c = PTR2CHAR(aff_entry->ae_chop);
5847 			    c_up = SPELL_TOUPPER(c);
5848 			    if (c_up != c
5849 				    && (aff_entry->ae_cond == NULL
5850 					|| PTR2CHAR(aff_entry->ae_cond) == c))
5851 			    {
5852 				p = aff_entry->ae_add
5853 						  + STRLEN(aff_entry->ae_add);
5854 				mb_ptr_back(aff_entry->ae_add, p);
5855 				if (PTR2CHAR(p) == c_up)
5856 				{
5857 				    upper = TRUE;
5858 				    aff_entry->ae_chop = NULL;
5859 				    *p = NUL;
5860 
5861 				    /* The condition is matched with the
5862 				     * actual word, thus must check for the
5863 				     * upper-case letter. */
5864 				    if (aff_entry->ae_cond != NULL)
5865 				    {
5866 					char_u	buf[MAXLINELEN];
5867 #ifdef FEAT_MBYTE
5868 					if (has_mbyte)
5869 					{
5870 					    onecap_copy(items[4], buf, TRUE);
5871 					    aff_entry->ae_cond = getroom_save(
5872 								   spin, buf);
5873 					}
5874 					else
5875 #endif
5876 					    *aff_entry->ae_cond = c_up;
5877 					if (aff_entry->ae_cond != NULL)
5878 					{
5879 					    sprintf((char *)buf, "^%s",
5880 							  aff_entry->ae_cond);
5881 					    vim_free(aff_entry->ae_prog);
5882 					    aff_entry->ae_prog = vim_regcomp(
5883 						    buf, RE_MAGIC + RE_STRING);
5884 					}
5885 				    }
5886 				}
5887 			    }
5888 			}
5889 
5890 			if (aff_entry->ae_chop == NULL
5891 					       && aff_entry->ae_flags == NULL)
5892 			{
5893 			    int		idx;
5894 			    char_u	**pp;
5895 			    int		n;
5896 
5897 			    /* Find a previously used condition. */
5898 			    for (idx = spin->si_prefcond.ga_len - 1; idx >= 0;
5899 									--idx)
5900 			    {
5901 				p = ((char_u **)spin->si_prefcond.ga_data)[idx];
5902 				if (str_equal(p, aff_entry->ae_cond))
5903 				    break;
5904 			    }
5905 			    if (idx < 0 && ga_grow(&spin->si_prefcond, 1) == OK)
5906 			    {
5907 				/* Not found, add a new condition. */
5908 				idx = spin->si_prefcond.ga_len++;
5909 				pp = ((char_u **)spin->si_prefcond.ga_data)
5910 									+ idx;
5911 				if (aff_entry->ae_cond == NULL)
5912 				    *pp = NULL;
5913 				else
5914 				    *pp = getroom_save(spin,
5915 							  aff_entry->ae_cond);
5916 			    }
5917 
5918 			    /* Add the prefix to the prefix tree. */
5919 			    if (aff_entry->ae_add == NULL)
5920 				p = (char_u *)"";
5921 			    else
5922 				p = aff_entry->ae_add;
5923 
5924 			    /* PFX_FLAGS is a negative number, so that
5925 			     * tree_add_word() knows this is the prefix tree. */
5926 			    n = PFX_FLAGS;
5927 			    if (!cur_aff->ah_combine)
5928 				n |= WFP_NC;
5929 			    if (upper)
5930 				n |= WFP_UP;
5931 			    if (aff_entry->ae_comppermit)
5932 				n |= WFP_COMPPERMIT;
5933 			    if (aff_entry->ae_compforbid)
5934 				n |= WFP_COMPFORBID;
5935 			    tree_add_word(spin, p, spin->si_prefroot, n,
5936 						      idx, cur_aff->ah_newID);
5937 			    did_postpone_prefix = TRUE;
5938 			}
5939 
5940 			/* Didn't actually use ah_newID, backup si_newprefID. */
5941 			if (aff_todo == 0 && !did_postpone_prefix)
5942 			{
5943 			    --spin->si_newprefID;
5944 			    cur_aff->ah_newID = 0;
5945 			}
5946 		    }
5947 		}
5948 	    }
5949 	    else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL)
5950 	    {
5951 		fol = vim_strsave(items[1]);
5952 	    }
5953 	    else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL)
5954 	    {
5955 		low = vim_strsave(items[1]);
5956 	    }
5957 	    else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL)
5958 	    {
5959 		upp = vim_strsave(items[1]);
5960 	    }
5961 	    else if (is_aff_rule(items, itemcnt, "REP", 2)
5962 		     || is_aff_rule(items, itemcnt, "REPSAL", 2))
5963 	    {
5964 		/* Ignore REP/REPSAL count */;
5965 		if (!isdigit(*items[1]))
5966 		    smsg((char_u *)_("Expected REP(SAL) count in %s line %d"),
5967 								 fname, lnum);
5968 	    }
5969 	    else if ((STRCMP(items[0], "REP") == 0
5970 			|| STRCMP(items[0], "REPSAL") == 0)
5971 		    && itemcnt >= 3)
5972 	    {
5973 		/* REP/REPSAL item */
5974 		/* Myspell ignores extra arguments, we require it starts with
5975 		 * # to detect mistakes. */
5976 		if (itemcnt > 3 && items[3][0] != '#')
5977 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[3]);
5978 		if (items[0][3] == 'S' ? do_repsal : do_rep)
5979 		{
5980 		    /* Replace underscore with space (can't include a space
5981 		     * directly). */
5982 		    for (p = items[1]; *p != NUL; mb_ptr_adv(p))
5983 			if (*p == '_')
5984 			    *p = ' ';
5985 		    for (p = items[2]; *p != NUL; mb_ptr_adv(p))
5986 			if (*p == '_')
5987 			    *p = ' ';
5988 		    add_fromto(spin, items[0][3] == 'S'
5989 					 ? &spin->si_repsal
5990 					 : &spin->si_rep, items[1], items[2]);
5991 		}
5992 	    }
5993 	    else if (is_aff_rule(items, itemcnt, "MAP", 2))
5994 	    {
5995 		/* MAP item or count */
5996 		if (!found_map)
5997 		{
5998 		    /* First line contains the count. */
5999 		    found_map = TRUE;
6000 		    if (!isdigit(*items[1]))
6001 			smsg((char_u *)_("Expected MAP count in %s line %d"),
6002 								 fname, lnum);
6003 		}
6004 		else if (do_mapline)
6005 		{
6006 		    int		c;
6007 
6008 		    /* Check that every character appears only once. */
6009 		    for (p = items[1]; *p != NUL; )
6010 		    {
6011 #ifdef FEAT_MBYTE
6012 			c = mb_ptr2char_adv(&p);
6013 #else
6014 			c = *p++;
6015 #endif
6016 			if ((spin->si_map.ga_len > 0
6017 				    && vim_strchr(spin->si_map.ga_data, c)
6018 								      != NULL)
6019 				|| vim_strchr(p, c) != NULL)
6020 			    smsg((char_u *)_("Duplicate character in MAP in %s line %d"),
6021 								 fname, lnum);
6022 		    }
6023 
6024 		    /* We simply concatenate all the MAP strings, separated by
6025 		     * slashes. */
6026 		    ga_concat(&spin->si_map, items[1]);
6027 		    ga_append(&spin->si_map, '/');
6028 		}
6029 	    }
6030 	    /* Accept "SAL from to" and "SAL from to  #comment". */
6031 	    else if (is_aff_rule(items, itemcnt, "SAL", 3))
6032 	    {
6033 		if (do_sal)
6034 		{
6035 		    /* SAL item (sounds-a-like)
6036 		     * Either one of the known keys or a from-to pair. */
6037 		    if (STRCMP(items[1], "followup") == 0)
6038 			spin->si_followup = sal_to_bool(items[2]);
6039 		    else if (STRCMP(items[1], "collapse_result") == 0)
6040 			spin->si_collapse = sal_to_bool(items[2]);
6041 		    else if (STRCMP(items[1], "remove_accents") == 0)
6042 			spin->si_rem_accents = sal_to_bool(items[2]);
6043 		    else
6044 			/* when "to" is "_" it means empty */
6045 			add_fromto(spin, &spin->si_sal, items[1],
6046 				     STRCMP(items[2], "_") == 0 ? (char_u *)""
6047 								: items[2]);
6048 		}
6049 	    }
6050 	    else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
6051 							  && sofofrom == NULL)
6052 	    {
6053 		sofofrom = getroom_save(spin, items[1]);
6054 	    }
6055 	    else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
6056 							    && sofoto == NULL)
6057 	    {
6058 		sofoto = getroom_save(spin, items[1]);
6059 	    }
6060 	    else if (STRCMP(items[0], "COMMON") == 0)
6061 	    {
6062 		int	i;
6063 
6064 		for (i = 1; i < itemcnt; ++i)
6065 		{
6066 		    if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords,
6067 								   items[i])))
6068 		    {
6069 			p = vim_strsave(items[i]);
6070 			if (p == NULL)
6071 			    break;
6072 			hash_add(&spin->si_commonwords, p);
6073 		    }
6074 		}
6075 	    }
6076 	    else
6077 		smsg((char_u *)_("Unrecognized or duplicate item in %s line %d: %s"),
6078 						       fname, lnum, items[0]);
6079 	}
6080     }
6081 
6082     if (fol != NULL || low != NULL || upp != NULL)
6083     {
6084 	if (spin->si_clear_chartab)
6085 	{
6086 	    /* Clear the char type tables, don't want to use any of the
6087 	     * currently used spell properties. */
6088 	    init_spell_chartab();
6089 	    spin->si_clear_chartab = FALSE;
6090 	}
6091 
6092 	/*
6093 	 * Don't write a word table for an ASCII file, so that we don't check
6094 	 * for conflicts with a word table that matches 'encoding'.
6095 	 * Don't write one for utf-8 either, we use utf_*() and
6096 	 * mb_get_class(), the list of chars in the file will be incomplete.
6097 	 */
6098 	if (!spin->si_ascii
6099 #ifdef FEAT_MBYTE
6100 		&& !enc_utf8
6101 #endif
6102 		)
6103 	{
6104 	    if (fol == NULL || low == NULL || upp == NULL)
6105 		smsg((char_u *)_("Missing FOL/LOW/UPP line in %s"), fname);
6106 	    else
6107 		(void)set_spell_chartab(fol, low, upp);
6108 	}
6109 
6110 	vim_free(fol);
6111 	vim_free(low);
6112 	vim_free(upp);
6113     }
6114 
6115     /* Use compound specifications of the .aff file for the spell info. */
6116     if (compmax != 0)
6117     {
6118 	aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX");
6119 	spin->si_compmax = compmax;
6120     }
6121 
6122     if (compminlen != 0)
6123     {
6124 	aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN");
6125 	spin->si_compminlen = compminlen;
6126     }
6127 
6128     if (compsylmax != 0)
6129     {
6130 	if (syllable == NULL)
6131 	    smsg((char_u *)_("COMPOUNDSYLMAX used without SYLLABLE"));
6132 	aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX");
6133 	spin->si_compsylmax = compsylmax;
6134     }
6135 
6136     if (compoptions != 0)
6137     {
6138 	aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options");
6139 	spin->si_compoptions |= compoptions;
6140     }
6141 
6142     if (compflags != NULL)
6143 	process_compflags(spin, aff, compflags);
6144 
6145     /* Check that we didn't use too many renumbered flags. */
6146     if (spin->si_newcompID < spin->si_newprefID)
6147     {
6148 	if (spin->si_newcompID == 127 || spin->si_newcompID == 255)
6149 	    MSG(_("Too many postponed prefixes"));
6150 	else if (spin->si_newprefID == 0 || spin->si_newprefID == 127)
6151 	    MSG(_("Too many compound flags"));
6152 	else
6153 	    MSG(_("Too many postponed prefixes and/or compound flags"));
6154     }
6155 
6156     if (syllable != NULL)
6157     {
6158 	aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
6159 	spin->si_syllable = syllable;
6160     }
6161 
6162     if (sofofrom != NULL || sofoto != NULL)
6163     {
6164 	if (sofofrom == NULL || sofoto == NULL)
6165 	    smsg((char_u *)_("Missing SOFO%s line in %s"),
6166 				     sofofrom == NULL ? "FROM" : "TO", fname);
6167 	else if (spin->si_sal.ga_len > 0)
6168 	    smsg((char_u *)_("Both SAL and SOFO lines in %s"), fname);
6169 	else
6170 	{
6171 	    aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
6172 	    aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
6173 	    spin->si_sofofr = sofofrom;
6174 	    spin->si_sofoto = sofoto;
6175 	}
6176     }
6177 
6178     if (midword != NULL)
6179     {
6180 	aff_check_string(spin->si_midword, midword, "MIDWORD");
6181 	spin->si_midword = midword;
6182     }
6183 
6184     vim_free(pc);
6185     fclose(fd);
6186     return aff;
6187 }
6188 
6189 /*
6190  * Return TRUE when items[0] equals "rulename", there are "mincount" items or
6191  * a comment is following after item "mincount".
6192  */
6193     static int
6194 is_aff_rule(items, itemcnt, rulename, mincount)
6195     char_u	**items;
6196     int		itemcnt;
6197     char	*rulename;
6198     int		mincount;
6199 {
6200     return (STRCMP(items[0], rulename) == 0
6201 	    && (itemcnt == mincount
6202 		|| (itemcnt > mincount && items[mincount][0] == '#')));
6203 }
6204 
6205 /*
6206  * For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from
6207  * ae_flags to ae_comppermit and ae_compforbid.
6208  */
6209     static void
6210 aff_process_flags(affile, entry)
6211     afffile_T	*affile;
6212     affentry_T	*entry;
6213 {
6214     char_u	*p;
6215     char_u	*prevp;
6216     unsigned	flag;
6217 
6218     if (entry->ae_flags != NULL
6219 		&& (affile->af_compforbid != 0 || affile->af_comppermit != 0))
6220     {
6221 	for (p = entry->ae_flags; *p != NUL; )
6222 	{
6223 	    prevp = p;
6224 	    flag = get_affitem(affile->af_flagtype, &p);
6225 	    if (flag == affile->af_comppermit || flag == affile->af_compforbid)
6226 	    {
6227 		STRMOVE(prevp, p);
6228 		p = prevp;
6229 		if (flag == affile->af_comppermit)
6230 		    entry->ae_comppermit = TRUE;
6231 		else
6232 		    entry->ae_compforbid = TRUE;
6233 	    }
6234 	    if (affile->af_flagtype == AFT_NUM && *p == ',')
6235 		++p;
6236 	}
6237 	if (*entry->ae_flags == NUL)
6238 	    entry->ae_flags = NULL;	/* nothing left */
6239     }
6240 }
6241 
6242 /*
6243  * Return TRUE if "s" is the name of an info item in the affix file.
6244  */
6245     static int
6246 spell_info_item(s)
6247     char_u	*s;
6248 {
6249     return STRCMP(s, "NAME") == 0
6250 	|| STRCMP(s, "HOME") == 0
6251 	|| STRCMP(s, "VERSION") == 0
6252 	|| STRCMP(s, "AUTHOR") == 0
6253 	|| STRCMP(s, "EMAIL") == 0
6254 	|| STRCMP(s, "COPYRIGHT") == 0;
6255 }
6256 
6257 /*
6258  * Turn an affix flag name into a number, according to the FLAG type.
6259  * returns zero for failure.
6260  */
6261     static unsigned
6262 affitem2flag(flagtype, item, fname, lnum)
6263     int		flagtype;
6264     char_u	*item;
6265     char_u	*fname;
6266     int		lnum;
6267 {
6268     unsigned	res;
6269     char_u	*p = item;
6270 
6271     res = get_affitem(flagtype, &p);
6272     if (res == 0)
6273     {
6274 	if (flagtype == AFT_NUM)
6275 	    smsg((char_u *)_("Flag is not a number in %s line %d: %s"),
6276 							   fname, lnum, item);
6277 	else
6278 	    smsg((char_u *)_("Illegal flag in %s line %d: %s"),
6279 							   fname, lnum, item);
6280     }
6281     if (*p != NUL)
6282     {
6283 	smsg((char_u *)_(e_affname), fname, lnum, item);
6284 	return 0;
6285     }
6286 
6287     return res;
6288 }
6289 
6290 /*
6291  * Get one affix name from "*pp" and advance the pointer.
6292  * Returns zero for an error, still advances the pointer then.
6293  */
6294     static unsigned
6295 get_affitem(flagtype, pp)
6296     int		flagtype;
6297     char_u	**pp;
6298 {
6299     int		res;
6300 
6301     if (flagtype == AFT_NUM)
6302     {
6303 	if (!VIM_ISDIGIT(**pp))
6304 	{
6305 	    ++*pp;	/* always advance, avoid getting stuck */
6306 	    return 0;
6307 	}
6308 	res = getdigits(pp);
6309     }
6310     else
6311     {
6312 #ifdef FEAT_MBYTE
6313 	res = mb_ptr2char_adv(pp);
6314 #else
6315 	res = *(*pp)++;
6316 #endif
6317 	if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
6318 						 && res >= 'A' && res <= 'Z'))
6319 	{
6320 	    if (**pp == NUL)
6321 		return 0;
6322 #ifdef FEAT_MBYTE
6323 	    res = mb_ptr2char_adv(pp) + (res << 16);
6324 #else
6325 	    res = *(*pp)++ + (res << 16);
6326 #endif
6327 	}
6328     }
6329     return res;
6330 }
6331 
6332 /*
6333  * Process the "compflags" string used in an affix file and append it to
6334  * spin->si_compflags.
6335  * The processing involves changing the affix names to ID numbers, so that
6336  * they fit in one byte.
6337  */
6338     static void
6339 process_compflags(spin, aff, compflags)
6340     spellinfo_T	*spin;
6341     afffile_T	*aff;
6342     char_u	*compflags;
6343 {
6344     char_u	*p;
6345     char_u	*prevp;
6346     unsigned	flag;
6347     compitem_T	*ci;
6348     int		id;
6349     int		len;
6350     char_u	*tp;
6351     char_u	key[AH_KEY_LEN];
6352     hashitem_T	*hi;
6353 
6354     /* Make room for the old and the new compflags, concatenated with a / in
6355      * between.  Processing it makes it shorter, but we don't know by how
6356      * much, thus allocate the maximum. */
6357     len = (int)STRLEN(compflags) + 1;
6358     if (spin->si_compflags != NULL)
6359 	len += (int)STRLEN(spin->si_compflags) + 1;
6360     p = getroom(spin, len, FALSE);
6361     if (p == NULL)
6362 	return;
6363     if (spin->si_compflags != NULL)
6364     {
6365 	STRCPY(p, spin->si_compflags);
6366 	STRCAT(p, "/");
6367     }
6368     spin->si_compflags = p;
6369     tp = p + STRLEN(p);
6370 
6371     for (p = compflags; *p != NUL; )
6372     {
6373 	if (vim_strchr((char_u *)"/*+[]", *p) != NULL)
6374 	    /* Copy non-flag characters directly. */
6375 	    *tp++ = *p++;
6376 	else
6377 	{
6378 	    /* First get the flag number, also checks validity. */
6379 	    prevp = p;
6380 	    flag = get_affitem(aff->af_flagtype, &p);
6381 	    if (flag != 0)
6382 	    {
6383 		/* Find the flag in the hashtable.  If it was used before, use
6384 		 * the existing ID.  Otherwise add a new entry. */
6385 		vim_strncpy(key, prevp, p - prevp);
6386 		hi = hash_find(&aff->af_comp, key);
6387 		if (!HASHITEM_EMPTY(hi))
6388 		    id = HI2CI(hi)->ci_newID;
6389 		else
6390 		{
6391 		    ci = (compitem_T *)getroom(spin, sizeof(compitem_T), TRUE);
6392 		    if (ci == NULL)
6393 			break;
6394 		    STRCPY(ci->ci_key, key);
6395 		    ci->ci_flag = flag;
6396 		    /* Avoid using a flag ID that has a special meaning in a
6397 		     * regexp (also inside []). */
6398 		    do
6399 		    {
6400 			check_renumber(spin);
6401 			id = spin->si_newcompID--;
6402 		    } while (vim_strchr((char_u *)"/+*[]\\-^", id) != NULL);
6403 		    ci->ci_newID = id;
6404 		    hash_add(&aff->af_comp, ci->ci_key);
6405 		}
6406 		*tp++ = id;
6407 	    }
6408 	    if (aff->af_flagtype == AFT_NUM && *p == ',')
6409 		++p;
6410 	}
6411     }
6412 
6413     *tp = NUL;
6414 }
6415 
6416 /*
6417  * Check that the new IDs for postponed affixes and compounding don't overrun
6418  * each other.  We have almost 255 available, but start at 0-127 to avoid
6419  * using two bytes for utf-8.  When the 0-127 range is used up go to 128-255.
6420  * When that is used up an error message is given.
6421  */
6422     static void
6423 check_renumber(spin)
6424     spellinfo_T	*spin;
6425 {
6426     if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128)
6427     {
6428 	spin->si_newprefID = 127;
6429 	spin->si_newcompID = 255;
6430     }
6431 }
6432 
6433 /*
6434  * Return TRUE if flag "flag" appears in affix list "afflist".
6435  */
6436     static int
6437 flag_in_afflist(flagtype, afflist, flag)
6438     int		flagtype;
6439     char_u	*afflist;
6440     unsigned	flag;
6441 {
6442     char_u	*p;
6443     unsigned	n;
6444 
6445     switch (flagtype)
6446     {
6447 	case AFT_CHAR:
6448 	    return vim_strchr(afflist, flag) != NULL;
6449 
6450 	case AFT_CAPLONG:
6451 	case AFT_LONG:
6452 	    for (p = afflist; *p != NUL; )
6453 	    {
6454 #ifdef FEAT_MBYTE
6455 		n = mb_ptr2char_adv(&p);
6456 #else
6457 		n = *p++;
6458 #endif
6459 		if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
6460 								 && *p != NUL)
6461 #ifdef FEAT_MBYTE
6462 		    n = mb_ptr2char_adv(&p) + (n << 16);
6463 #else
6464 		    n = *p++ + (n << 16);
6465 #endif
6466 		if (n == flag)
6467 		    return TRUE;
6468 	    }
6469 	    break;
6470 
6471 	case AFT_NUM:
6472 	    for (p = afflist; *p != NUL; )
6473 	    {
6474 		n = getdigits(&p);
6475 		if (n == flag)
6476 		    return TRUE;
6477 		if (*p != NUL)	/* skip over comma */
6478 		    ++p;
6479 	    }
6480 	    break;
6481     }
6482     return FALSE;
6483 }
6484 
6485 /*
6486  * Give a warning when "spinval" and "affval" numbers are set and not the same.
6487  */
6488     static void
6489 aff_check_number(spinval, affval, name)
6490     int	    spinval;
6491     int	    affval;
6492     char    *name;
6493 {
6494     if (spinval != 0 && spinval != affval)
6495 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
6496 }
6497 
6498 /*
6499  * Give a warning when "spinval" and "affval" strings are set and not the same.
6500  */
6501     static void
6502 aff_check_string(spinval, affval, name)
6503     char_u	*spinval;
6504     char_u	*affval;
6505     char	*name;
6506 {
6507     if (spinval != NULL && STRCMP(spinval, affval) != 0)
6508 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
6509 }
6510 
6511 /*
6512  * Return TRUE if strings "s1" and "s2" are equal.  Also consider both being
6513  * NULL as equal.
6514  */
6515     static int
6516 str_equal(s1, s2)
6517     char_u	*s1;
6518     char_u	*s2;
6519 {
6520     if (s1 == NULL || s2 == NULL)
6521 	return s1 == s2;
6522     return STRCMP(s1, s2) == 0;
6523 }
6524 
6525 /*
6526  * Add a from-to item to "gap".  Used for REP and SAL items.
6527  * They are stored case-folded.
6528  */
6529     static void
6530 add_fromto(spin, gap, from, to)
6531     spellinfo_T	*spin;
6532     garray_T	*gap;
6533     char_u	*from;
6534     char_u	*to;
6535 {
6536     fromto_T	*ftp;
6537     char_u	word[MAXWLEN];
6538 
6539     if (ga_grow(gap, 1) == OK)
6540     {
6541 	ftp = ((fromto_T *)gap->ga_data) + gap->ga_len;
6542 	(void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN);
6543 	ftp->ft_from = getroom_save(spin, word);
6544 	(void)spell_casefold(to, (int)STRLEN(to), word, MAXWLEN);
6545 	ftp->ft_to = getroom_save(spin, word);
6546 	++gap->ga_len;
6547     }
6548 }
6549 
6550 /*
6551  * Convert a boolean argument in a SAL line to TRUE or FALSE;
6552  */
6553     static int
6554 sal_to_bool(s)
6555     char_u	*s;
6556 {
6557     return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0;
6558 }
6559 
6560 /*
6561  * Return TRUE if string "s" contains a non-ASCII character (128 or higher).
6562  * When "s" is NULL FALSE is returned.
6563  */
6564     static int
6565 has_non_ascii(s)
6566     char_u	*s;
6567 {
6568     char_u	*p;
6569 
6570     if (s != NULL)
6571 	for (p = s; *p != NUL; ++p)
6572 	    if (*p >= 128)
6573 		return TRUE;
6574     return FALSE;
6575 }
6576 
6577 /*
6578  * Free the structure filled by spell_read_aff().
6579  */
6580     static void
6581 spell_free_aff(aff)
6582     afffile_T	*aff;
6583 {
6584     hashtab_T	*ht;
6585     hashitem_T	*hi;
6586     int		todo;
6587     affheader_T	*ah;
6588     affentry_T	*ae;
6589 
6590     vim_free(aff->af_enc);
6591 
6592     /* All this trouble to free the "ae_prog" items... */
6593     for (ht = &aff->af_pref; ; ht = &aff->af_suff)
6594     {
6595 	todo = (int)ht->ht_used;
6596 	for (hi = ht->ht_array; todo > 0; ++hi)
6597 	{
6598 	    if (!HASHITEM_EMPTY(hi))
6599 	    {
6600 		--todo;
6601 		ah = HI2AH(hi);
6602 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
6603 		    vim_free(ae->ae_prog);
6604 	    }
6605 	}
6606 	if (ht == &aff->af_suff)
6607 	    break;
6608     }
6609 
6610     hash_clear(&aff->af_pref);
6611     hash_clear(&aff->af_suff);
6612     hash_clear(&aff->af_comp);
6613 }
6614 
6615 /*
6616  * Read dictionary file "fname".
6617  * Returns OK or FAIL;
6618  */
6619     static int
6620 spell_read_dic(spin, fname, affile)
6621     spellinfo_T	*spin;
6622     char_u	*fname;
6623     afffile_T	*affile;
6624 {
6625     hashtab_T	ht;
6626     char_u	line[MAXLINELEN];
6627     char_u	*p;
6628     char_u	*afflist;
6629     char_u	store_afflist[MAXWLEN];
6630     int		pfxlen;
6631     int		need_affix;
6632     char_u	*dw;
6633     char_u	*pc;
6634     char_u	*w;
6635     int		l;
6636     hash_T	hash;
6637     hashitem_T	*hi;
6638     FILE	*fd;
6639     int		lnum = 1;
6640     int		non_ascii = 0;
6641     int		retval = OK;
6642     char_u	message[MAXLINELEN + MAXWLEN];
6643     int		flags;
6644     int		duplicate = 0;
6645 
6646     /*
6647      * Open the file.
6648      */
6649     fd = mch_fopen((char *)fname, "r");
6650     if (fd == NULL)
6651     {
6652 	EMSG2(_(e_notopen), fname);
6653 	return FAIL;
6654     }
6655 
6656     /* The hashtable is only used to detect duplicated words. */
6657     hash_init(&ht);
6658 
6659     vim_snprintf((char *)IObuff, IOSIZE,
6660 				  _("Reading dictionary file %s ..."), fname);
6661     spell_message(spin, IObuff);
6662 
6663     /* start with a message for the first line */
6664     spin->si_msg_count = 999999;
6665 
6666     /* Read and ignore the first line: word count. */
6667     (void)vim_fgets(line, MAXLINELEN, fd);
6668     if (!vim_isdigit(*skipwhite(line)))
6669 	EMSG2(_("E760: No word count in %s"), fname);
6670 
6671     /*
6672      * Read all the lines in the file one by one.
6673      * The words are converted to 'encoding' here, before being added to
6674      * the hashtable.
6675      */
6676     while (!vim_fgets(line, MAXLINELEN, fd) && !got_int)
6677     {
6678 	line_breakcheck();
6679 	++lnum;
6680 	if (line[0] == '#' || line[0] == '/')
6681 	    continue;	/* comment line */
6682 
6683 	/* Remove CR, LF and white space from the end.  White space halfway
6684 	 * the word is kept to allow e.g., "et al.". */
6685 	l = (int)STRLEN(line);
6686 	while (l > 0 && line[l - 1] <= ' ')
6687 	    --l;
6688 	if (l == 0)
6689 	    continue;	/* empty line */
6690 	line[l] = NUL;
6691 
6692 #ifdef FEAT_MBYTE
6693 	/* Convert from "SET" to 'encoding' when needed. */
6694 	if (spin->si_conv.vc_type != CONV_NONE)
6695 	{
6696 	    pc = string_convert(&spin->si_conv, line, NULL);
6697 	    if (pc == NULL)
6698 	    {
6699 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
6700 						       fname, lnum, line);
6701 		continue;
6702 	    }
6703 	    w = pc;
6704 	}
6705 	else
6706 #endif
6707 	{
6708 	    pc = NULL;
6709 	    w = line;
6710 	}
6711 
6712 	/* Truncate the word at the "/", set "afflist" to what follows.
6713 	 * Replace "\/" by "/" and "\\" by "\". */
6714 	afflist = NULL;
6715 	for (p = w; *p != NUL; mb_ptr_adv(p))
6716 	{
6717 	    if (*p == '\\' && (p[1] == '\\' || p[1] == '/'))
6718 		STRMOVE(p, p + 1);
6719 	    else if (*p == '/')
6720 	    {
6721 		*p = NUL;
6722 		afflist = p + 1;
6723 		break;
6724 	    }
6725 	}
6726 
6727 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
6728 	if (spin->si_ascii && has_non_ascii(w))
6729 	{
6730 	    ++non_ascii;
6731 	    vim_free(pc);
6732 	    continue;
6733 	}
6734 
6735 	/* This takes time, print a message every 10000 words. */
6736 	if (spin->si_verbose && spin->si_msg_count > 10000)
6737 	{
6738 	    spin->si_msg_count = 0;
6739 	    vim_snprintf((char *)message, sizeof(message),
6740 		    _("line %6d, word %6d - %s"),
6741 		       lnum, spin->si_foldwcount + spin->si_keepwcount, w);
6742 	    msg_start();
6743 	    msg_puts_long_attr(message, 0);
6744 	    msg_clr_eos();
6745 	    msg_didout = FALSE;
6746 	    msg_col = 0;
6747 	    out_flush();
6748 	}
6749 
6750 	/* Store the word in the hashtable to be able to find duplicates. */
6751 	dw = (char_u *)getroom_save(spin, w);
6752 	if (dw == NULL)
6753 	{
6754 	    retval = FAIL;
6755 	    vim_free(pc);
6756 	    break;
6757 	}
6758 
6759 	hash = hash_hash(dw);
6760 	hi = hash_lookup(&ht, dw, hash);
6761 	if (!HASHITEM_EMPTY(hi))
6762 	{
6763 	    if (p_verbose > 0)
6764 		smsg((char_u *)_("Duplicate word in %s line %d: %s"),
6765 							     fname, lnum, dw);
6766 	    else if (duplicate == 0)
6767 		smsg((char_u *)_("First duplicate word in %s line %d: %s"),
6768 							     fname, lnum, dw);
6769 	    ++duplicate;
6770 	}
6771 	else
6772 	    hash_add_item(&ht, hi, dw, hash);
6773 
6774 	flags = 0;
6775 	store_afflist[0] = NUL;
6776 	pfxlen = 0;
6777 	need_affix = FALSE;
6778 	if (afflist != NULL)
6779 	{
6780 	    /* Extract flags from the affix list. */
6781 	    flags |= get_affix_flags(affile, afflist);
6782 
6783 	    if (affile->af_needaffix != 0 && flag_in_afflist(
6784 			  affile->af_flagtype, afflist, affile->af_needaffix))
6785 		need_affix = TRUE;
6786 
6787 	    if (affile->af_pfxpostpone)
6788 		/* Need to store the list of prefix IDs with the word. */
6789 		pfxlen = get_pfxlist(affile, afflist, store_afflist);
6790 
6791 	    if (spin->si_compflags != NULL)
6792 		/* Need to store the list of compound flags with the word.
6793 		 * Concatenate them to the list of prefix IDs. */
6794 		get_compflags(affile, afflist, store_afflist + pfxlen);
6795 	}
6796 
6797 	/* Add the word to the word tree(s). */
6798 	if (store_word(spin, dw, flags, spin->si_region,
6799 					   store_afflist, need_affix) == FAIL)
6800 	    retval = FAIL;
6801 
6802 	if (afflist != NULL)
6803 	{
6804 	    /* Find all matching suffixes and add the resulting words.
6805 	     * Additionally do matching prefixes that combine. */
6806 	    if (store_aff_word(spin, dw, afflist, affile,
6807 			   &affile->af_suff, &affile->af_pref,
6808 			    CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL)
6809 		retval = FAIL;
6810 
6811 	    /* Find all matching prefixes and add the resulting words. */
6812 	    if (store_aff_word(spin, dw, afflist, affile,
6813 			  &affile->af_pref, NULL,
6814 			    CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL)
6815 		retval = FAIL;
6816 	}
6817 
6818 	vim_free(pc);
6819     }
6820 
6821     if (duplicate > 0)
6822 	smsg((char_u *)_("%d duplicate word(s) in %s"), duplicate, fname);
6823     if (spin->si_ascii && non_ascii > 0)
6824 	smsg((char_u *)_("Ignored %d word(s) with non-ASCII characters in %s"),
6825 							    non_ascii, fname);
6826     hash_clear(&ht);
6827 
6828     fclose(fd);
6829     return retval;
6830 }
6831 
6832 /*
6833  * Check for affix flags in "afflist" that are turned into word flags.
6834  * Return WF_ flags.
6835  */
6836     static int
6837 get_affix_flags(affile, afflist)
6838     afffile_T	*affile;
6839     char_u	*afflist;
6840 {
6841     int		flags = 0;
6842 
6843     if (affile->af_keepcase != 0 && flag_in_afflist(
6844 			   affile->af_flagtype, afflist, affile->af_keepcase))
6845 	flags |= WF_KEEPCAP | WF_FIXCAP;
6846     if (affile->af_rare != 0 && flag_in_afflist(
6847 			       affile->af_flagtype, afflist, affile->af_rare))
6848 	flags |= WF_RARE;
6849     if (affile->af_bad != 0 && flag_in_afflist(
6850 				affile->af_flagtype, afflist, affile->af_bad))
6851 	flags |= WF_BANNED;
6852     if (affile->af_needcomp != 0 && flag_in_afflist(
6853 			   affile->af_flagtype, afflist, affile->af_needcomp))
6854 	flags |= WF_NEEDCOMP;
6855     if (affile->af_comproot != 0 && flag_in_afflist(
6856 			   affile->af_flagtype, afflist, affile->af_comproot))
6857 	flags |= WF_COMPROOT;
6858     if (affile->af_nosuggest != 0 && flag_in_afflist(
6859 			  affile->af_flagtype, afflist, affile->af_nosuggest))
6860 	flags |= WF_NOSUGGEST;
6861     return flags;
6862 }
6863 
6864 /*
6865  * Get the list of prefix IDs from the affix list "afflist".
6866  * Used for PFXPOSTPONE.
6867  * Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
6868  * and return the number of affixes.
6869  */
6870     static int
6871 get_pfxlist(affile, afflist, store_afflist)
6872     afffile_T	*affile;
6873     char_u	*afflist;
6874     char_u	*store_afflist;
6875 {
6876     char_u	*p;
6877     char_u	*prevp;
6878     int		cnt = 0;
6879     int		id;
6880     char_u	key[AH_KEY_LEN];
6881     hashitem_T	*hi;
6882 
6883     for (p = afflist; *p != NUL; )
6884     {
6885 	prevp = p;
6886 	if (get_affitem(affile->af_flagtype, &p) != 0)
6887 	{
6888 	    /* A flag is a postponed prefix flag if it appears in "af_pref"
6889 	     * and it's ID is not zero. */
6890 	    vim_strncpy(key, prevp, p - prevp);
6891 	    hi = hash_find(&affile->af_pref, key);
6892 	    if (!HASHITEM_EMPTY(hi))
6893 	    {
6894 		id = HI2AH(hi)->ah_newID;
6895 		if (id != 0)
6896 		    store_afflist[cnt++] = id;
6897 	    }
6898 	}
6899 	if (affile->af_flagtype == AFT_NUM && *p == ',')
6900 	    ++p;
6901     }
6902 
6903     store_afflist[cnt] = NUL;
6904     return cnt;
6905 }
6906 
6907 /*
6908  * Get the list of compound IDs from the affix list "afflist" that are used
6909  * for compound words.
6910  * Puts the flags in "store_afflist[]".
6911  */
6912     static void
6913 get_compflags(affile, afflist, store_afflist)
6914     afffile_T	*affile;
6915     char_u	*afflist;
6916     char_u	*store_afflist;
6917 {
6918     char_u	*p;
6919     char_u	*prevp;
6920     int		cnt = 0;
6921     char_u	key[AH_KEY_LEN];
6922     hashitem_T	*hi;
6923 
6924     for (p = afflist; *p != NUL; )
6925     {
6926 	prevp = p;
6927 	if (get_affitem(affile->af_flagtype, &p) != 0)
6928 	{
6929 	    /* A flag is a compound flag if it appears in "af_comp". */
6930 	    vim_strncpy(key, prevp, p - prevp);
6931 	    hi = hash_find(&affile->af_comp, key);
6932 	    if (!HASHITEM_EMPTY(hi))
6933 		store_afflist[cnt++] = HI2CI(hi)->ci_newID;
6934 	}
6935 	if (affile->af_flagtype == AFT_NUM && *p == ',')
6936 	    ++p;
6937     }
6938 
6939     store_afflist[cnt] = NUL;
6940 }
6941 
6942 /*
6943  * Apply affixes to a word and store the resulting words.
6944  * "ht" is the hashtable with affentry_T that need to be applied, either
6945  * prefixes or suffixes.
6946  * "xht", when not NULL, is the prefix hashtable, to be used additionally on
6947  * the resulting words for combining affixes.
6948  *
6949  * Returns FAIL when out of memory.
6950  */
6951     static int
6952 store_aff_word(spin, word, afflist, affile, ht, xht, condit, flags,
6953 							      pfxlist, pfxlen)
6954     spellinfo_T	*spin;		/* spell info */
6955     char_u	*word;		/* basic word start */
6956     char_u	*afflist;	/* list of names of supported affixes */
6957     afffile_T	*affile;
6958     hashtab_T	*ht;
6959     hashtab_T	*xht;
6960     int		condit;		/* CONDIT_SUF et al. */
6961     int		flags;		/* flags for the word */
6962     char_u	*pfxlist;	/* list of prefix IDs */
6963     int		pfxlen;		/* nr of flags in "pfxlist" for prefixes, rest
6964 				 * is compound flags */
6965 {
6966     int		todo;
6967     hashitem_T	*hi;
6968     affheader_T	*ah;
6969     affentry_T	*ae;
6970     regmatch_T	regmatch;
6971     char_u	newword[MAXWLEN];
6972     int		retval = OK;
6973     int		i, j;
6974     char_u	*p;
6975     int		use_flags;
6976     char_u	*use_pfxlist;
6977     int		use_pfxlen;
6978     int		need_affix;
6979     char_u	store_afflist[MAXWLEN];
6980     char_u	pfx_pfxlist[MAXWLEN];
6981     size_t	wordlen = STRLEN(word);
6982     int		use_condit;
6983 
6984     todo = (int)ht->ht_used;
6985     for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi)
6986     {
6987 	if (!HASHITEM_EMPTY(hi))
6988 	{
6989 	    --todo;
6990 	    ah = HI2AH(hi);
6991 
6992 	    /* Check that the affix combines, if required, and that the word
6993 	     * supports this affix. */
6994 	    if (((condit & CONDIT_COMB) == 0 || ah->ah_combine)
6995 		    && flag_in_afflist(affile->af_flagtype, afflist,
6996 								 ah->ah_flag))
6997 	    {
6998 		/* Loop over all affix entries with this name. */
6999 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
7000 		{
7001 		    /* Check the condition.  It's not logical to match case
7002 		     * here, but it is required for compatibility with
7003 		     * Myspell.
7004 		     * Another requirement from Myspell is that the chop
7005 		     * string is shorter than the word itself.
7006 		     * For prefixes, when "PFXPOSTPONE" was used, only do
7007 		     * prefixes with a chop string and/or flags.
7008 		     * When a previously added affix had CIRCUMFIX this one
7009 		     * must have it too, if it had not then this one must not
7010 		     * have one either. */
7011 		    regmatch.regprog = ae->ae_prog;
7012 		    regmatch.rm_ic = FALSE;
7013 		    if ((xht != NULL || !affile->af_pfxpostpone
7014 				|| ae->ae_chop != NULL
7015 				|| ae->ae_flags != NULL)
7016 			    && (ae->ae_chop == NULL
7017 				|| STRLEN(ae->ae_chop) < wordlen)
7018 			    && (ae->ae_prog == NULL
7019 				|| vim_regexec(&regmatch, word, (colnr_T)0))
7020 			    && (((condit & CONDIT_CFIX) == 0)
7021 				== ((condit & CONDIT_AFF) == 0
7022 				    || ae->ae_flags == NULL
7023 				    || !flag_in_afflist(affile->af_flagtype,
7024 					ae->ae_flags, affile->af_circumfix))))
7025 		    {
7026 			/* Match.  Remove the chop and add the affix. */
7027 			if (xht == NULL)
7028 			{
7029 			    /* prefix: chop/add at the start of the word */
7030 			    if (ae->ae_add == NULL)
7031 				*newword = NUL;
7032 			    else
7033 				STRCPY(newword, ae->ae_add);
7034 			    p = word;
7035 			    if (ae->ae_chop != NULL)
7036 			    {
7037 				/* Skip chop string. */
7038 #ifdef FEAT_MBYTE
7039 				if (has_mbyte)
7040 				{
7041 				    i = mb_charlen(ae->ae_chop);
7042 				    for ( ; i > 0; --i)
7043 					mb_ptr_adv(p);
7044 				}
7045 				else
7046 #endif
7047 				    p += STRLEN(ae->ae_chop);
7048 			    }
7049 			    STRCAT(newword, p);
7050 			}
7051 			else
7052 			{
7053 			    /* suffix: chop/add at the end of the word */
7054 			    STRCPY(newword, word);
7055 			    if (ae->ae_chop != NULL)
7056 			    {
7057 				/* Remove chop string. */
7058 				p = newword + STRLEN(newword);
7059 				i = (int)MB_CHARLEN(ae->ae_chop);
7060 				for ( ; i > 0; --i)
7061 				    mb_ptr_back(newword, p);
7062 				*p = NUL;
7063 			    }
7064 			    if (ae->ae_add != NULL)
7065 				STRCAT(newword, ae->ae_add);
7066 			}
7067 
7068 			use_flags = flags;
7069 			use_pfxlist = pfxlist;
7070 			use_pfxlen = pfxlen;
7071 			need_affix = FALSE;
7072 			use_condit = condit | CONDIT_COMB | CONDIT_AFF;
7073 			if (ae->ae_flags != NULL)
7074 			{
7075 			    /* Extract flags from the affix list. */
7076 			    use_flags |= get_affix_flags(affile, ae->ae_flags);
7077 
7078 			    if (affile->af_needaffix != 0 && flag_in_afflist(
7079 					affile->af_flagtype, ae->ae_flags,
7080 							affile->af_needaffix))
7081 				need_affix = TRUE;
7082 
7083 			    /* When there is a CIRCUMFIX flag the other affix
7084 			     * must also have it and we don't add the word
7085 			     * with one affix. */
7086 			    if (affile->af_circumfix != 0 && flag_in_afflist(
7087 					affile->af_flagtype, ae->ae_flags,
7088 							affile->af_circumfix))
7089 			    {
7090 				use_condit |= CONDIT_CFIX;
7091 				if ((condit & CONDIT_CFIX) == 0)
7092 				    need_affix = TRUE;
7093 			    }
7094 
7095 			    if (affile->af_pfxpostpone
7096 						|| spin->si_compflags != NULL)
7097 			    {
7098 				if (affile->af_pfxpostpone)
7099 				    /* Get prefix IDS from the affix list. */
7100 				    use_pfxlen = get_pfxlist(affile,
7101 						 ae->ae_flags, store_afflist);
7102 				else
7103 				    use_pfxlen = 0;
7104 				use_pfxlist = store_afflist;
7105 
7106 				/* Combine the prefix IDs. Avoid adding the
7107 				 * same ID twice. */
7108 				for (i = 0; i < pfxlen; ++i)
7109 				{
7110 				    for (j = 0; j < use_pfxlen; ++j)
7111 					if (pfxlist[i] == use_pfxlist[j])
7112 					    break;
7113 				    if (j == use_pfxlen)
7114 					use_pfxlist[use_pfxlen++] = pfxlist[i];
7115 				}
7116 
7117 				if (spin->si_compflags != NULL)
7118 				    /* Get compound IDS from the affix list. */
7119 				    get_compflags(affile, ae->ae_flags,
7120 						  use_pfxlist + use_pfxlen);
7121 
7122 				/* Combine the list of compound flags.
7123 				 * Concatenate them to the prefix IDs list.
7124 				 * Avoid adding the same ID twice. */
7125 				for (i = pfxlen; pfxlist[i] != NUL; ++i)
7126 				{
7127 				    for (j = use_pfxlen;
7128 						   use_pfxlist[j] != NUL; ++j)
7129 					if (pfxlist[i] == use_pfxlist[j])
7130 					    break;
7131 				    if (use_pfxlist[j] == NUL)
7132 				    {
7133 					use_pfxlist[j++] = pfxlist[i];
7134 					use_pfxlist[j] = NUL;
7135 				    }
7136 				}
7137 			    }
7138 			}
7139 
7140 			/* Obey a "COMPOUNDFORBIDFLAG" of the affix: don't
7141 			 * use the compound flags. */
7142 			if (use_pfxlist != NULL && ae->ae_compforbid)
7143 			{
7144 			    vim_strncpy(pfx_pfxlist, use_pfxlist, use_pfxlen);
7145 			    use_pfxlist = pfx_pfxlist;
7146 			}
7147 
7148 			/* When there are postponed prefixes... */
7149 			if (spin->si_prefroot != NULL
7150 				&& spin->si_prefroot->wn_sibling != NULL)
7151 			{
7152 			    /* ... add a flag to indicate an affix was used. */
7153 			    use_flags |= WF_HAS_AFF;
7154 
7155 			    /* ... don't use a prefix list if combining
7156 			     * affixes is not allowed.  But do use the
7157 			     * compound flags after them. */
7158 			    if (!ah->ah_combine && use_pfxlist != NULL)
7159 				use_pfxlist += use_pfxlen;
7160 			}
7161 
7162 			/* When compounding is supported and there is no
7163 			 * "COMPOUNDPERMITFLAG" then forbid compounding on the
7164 			 * side where the affix is applied. */
7165 			if (spin->si_compflags != NULL && !ae->ae_comppermit)
7166 			{
7167 			    if (xht != NULL)
7168 				use_flags |= WF_NOCOMPAFT;
7169 			    else
7170 				use_flags |= WF_NOCOMPBEF;
7171 			}
7172 
7173 			/* Store the modified word. */
7174 			if (store_word(spin, newword, use_flags,
7175 						 spin->si_region, use_pfxlist,
7176 							  need_affix) == FAIL)
7177 			    retval = FAIL;
7178 
7179 			/* When added a prefix or a first suffix and the affix
7180 			 * has flags may add a(nother) suffix.  RECURSIVE! */
7181 			if ((condit & CONDIT_SUF) && ae->ae_flags != NULL)
7182 			    if (store_aff_word(spin, newword, ae->ae_flags,
7183 					affile, &affile->af_suff, xht,
7184 					   use_condit & (xht == NULL
7185 							? ~0 :  ~CONDIT_SUF),
7186 				      use_flags, use_pfxlist, pfxlen) == FAIL)
7187 				retval = FAIL;
7188 
7189 			/* When added a suffix and combining is allowed also
7190 			 * try adding a prefix additionally.  Both for the
7191 			 * word flags and for the affix flags.  RECURSIVE! */
7192 			if (xht != NULL && ah->ah_combine)
7193 			{
7194 			    if (store_aff_word(spin, newword,
7195 					afflist, affile,
7196 					xht, NULL, use_condit,
7197 					use_flags, use_pfxlist,
7198 					pfxlen) == FAIL
7199 				    || (ae->ae_flags != NULL
7200 					&& store_aff_word(spin, newword,
7201 					    ae->ae_flags, affile,
7202 					    xht, NULL, use_condit,
7203 					    use_flags, use_pfxlist,
7204 					    pfxlen) == FAIL))
7205 				retval = FAIL;
7206 			}
7207 		    }
7208 		}
7209 	    }
7210 	}
7211     }
7212 
7213     return retval;
7214 }
7215 
7216 /*
7217  * Read a file with a list of words.
7218  */
7219     static int
7220 spell_read_wordfile(spin, fname)
7221     spellinfo_T	*spin;
7222     char_u	*fname;
7223 {
7224     FILE	*fd;
7225     long	lnum = 0;
7226     char_u	rline[MAXLINELEN];
7227     char_u	*line;
7228     char_u	*pc = NULL;
7229     char_u	*p;
7230     int		l;
7231     int		retval = OK;
7232     int		did_word = FALSE;
7233     int		non_ascii = 0;
7234     int		flags;
7235     int		regionmask;
7236 
7237     /*
7238      * Open the file.
7239      */
7240     fd = mch_fopen((char *)fname, "r");
7241     if (fd == NULL)
7242     {
7243 	EMSG2(_(e_notopen), fname);
7244 	return FAIL;
7245     }
7246 
7247     vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname);
7248     spell_message(spin, IObuff);
7249 
7250     /*
7251      * Read all the lines in the file one by one.
7252      */
7253     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
7254     {
7255 	line_breakcheck();
7256 	++lnum;
7257 
7258 	/* Skip comment lines. */
7259 	if (*rline == '#')
7260 	    continue;
7261 
7262 	/* Remove CR, LF and white space from the end. */
7263 	l = (int)STRLEN(rline);
7264 	while (l > 0 && rline[l - 1] <= ' ')
7265 	    --l;
7266 	if (l == 0)
7267 	    continue;	/* empty or blank line */
7268 	rline[l] = NUL;
7269 
7270 	/* Convert from "/encoding={encoding}" to 'encoding' when needed. */
7271 	vim_free(pc);
7272 #ifdef FEAT_MBYTE
7273 	if (spin->si_conv.vc_type != CONV_NONE)
7274 	{
7275 	    pc = string_convert(&spin->si_conv, rline, NULL);
7276 	    if (pc == NULL)
7277 	    {
7278 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
7279 							   fname, lnum, rline);
7280 		continue;
7281 	    }
7282 	    line = pc;
7283 	}
7284 	else
7285 #endif
7286 	{
7287 	    pc = NULL;
7288 	    line = rline;
7289 	}
7290 
7291 	if (*line == '/')
7292 	{
7293 	    ++line;
7294 	    if (STRNCMP(line, "encoding=", 9) == 0)
7295 	    {
7296 		if (spin->si_conv.vc_type != CONV_NONE)
7297 		    smsg((char_u *)_("Duplicate /encoding= line ignored in %s line %d: %s"),
7298 						       fname, lnum, line - 1);
7299 		else if (did_word)
7300 		    smsg((char_u *)_("/encoding= line after word ignored in %s line %d: %s"),
7301 						       fname, lnum, line - 1);
7302 		else
7303 		{
7304 #ifdef FEAT_MBYTE
7305 		    char_u	*enc;
7306 
7307 		    /* Setup for conversion to 'encoding'. */
7308 		    line += 9;
7309 		    enc = enc_canonize(line);
7310 		    if (enc != NULL && !spin->si_ascii
7311 			    && convert_setup(&spin->si_conv, enc,
7312 							       p_enc) == FAIL)
7313 			smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
7314 							  fname, line, p_enc);
7315 		    vim_free(enc);
7316 		    spin->si_conv.vc_fail = TRUE;
7317 #else
7318 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
7319 #endif
7320 		}
7321 		continue;
7322 	    }
7323 
7324 	    if (STRNCMP(line, "regions=", 8) == 0)
7325 	    {
7326 		if (spin->si_region_count > 1)
7327 		    smsg((char_u *)_("Duplicate /regions= line ignored in %s line %d: %s"),
7328 						       fname, lnum, line);
7329 		else
7330 		{
7331 		    line += 8;
7332 		    if (STRLEN(line) > 16)
7333 			smsg((char_u *)_("Too many regions in %s line %d: %s"),
7334 						       fname, lnum, line);
7335 		    else
7336 		    {
7337 			spin->si_region_count = (int)STRLEN(line) / 2;
7338 			STRCPY(spin->si_region_name, line);
7339 
7340 			/* Adjust the mask for a word valid in all regions. */
7341 			spin->si_region = (1 << spin->si_region_count) - 1;
7342 		    }
7343 		}
7344 		continue;
7345 	    }
7346 
7347 	    smsg((char_u *)_("/ line ignored in %s line %d: %s"),
7348 						       fname, lnum, line - 1);
7349 	    continue;
7350 	}
7351 
7352 	flags = 0;
7353 	regionmask = spin->si_region;
7354 
7355 	/* Check for flags and region after a slash. */
7356 	p = vim_strchr(line, '/');
7357 	if (p != NULL)
7358 	{
7359 	    *p++ = NUL;
7360 	    while (*p != NUL)
7361 	    {
7362 		if (*p == '=')		/* keep-case word */
7363 		    flags |= WF_KEEPCAP | WF_FIXCAP;
7364 		else if (*p == '!')	/* Bad, bad, wicked word. */
7365 		    flags |= WF_BANNED;
7366 		else if (*p == '?')	/* Rare word. */
7367 		    flags |= WF_RARE;
7368 		else if (VIM_ISDIGIT(*p)) /* region number(s) */
7369 		{
7370 		    if ((flags & WF_REGION) == 0)   /* first one */
7371 			regionmask = 0;
7372 		    flags |= WF_REGION;
7373 
7374 		    l = *p - '0';
7375 		    if (l > spin->si_region_count)
7376 		    {
7377 			smsg((char_u *)_("Invalid region nr in %s line %d: %s"),
7378 							  fname, lnum, p);
7379 			break;
7380 		    }
7381 		    regionmask |= 1 << (l - 1);
7382 		}
7383 		else
7384 		{
7385 		    smsg((char_u *)_("Unrecognized flags in %s line %d: %s"),
7386 							      fname, lnum, p);
7387 		    break;
7388 		}
7389 		++p;
7390 	    }
7391 	}
7392 
7393 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
7394 	if (spin->si_ascii && has_non_ascii(line))
7395 	{
7396 	    ++non_ascii;
7397 	    continue;
7398 	}
7399 
7400 	/* Normal word: store it. */
7401 	if (store_word(spin, line, flags, regionmask, NULL, FALSE) == FAIL)
7402 	{
7403 	    retval = FAIL;
7404 	    break;
7405 	}
7406 	did_word = TRUE;
7407     }
7408 
7409     vim_free(pc);
7410     fclose(fd);
7411 
7412     if (spin->si_ascii && non_ascii > 0)
7413     {
7414 	vim_snprintf((char *)IObuff, IOSIZE,
7415 		  _("Ignored %d words with non-ASCII characters"), non_ascii);
7416 	spell_message(spin, IObuff);
7417     }
7418 
7419     return retval;
7420 }
7421 
7422 /*
7423  * Get part of an sblock_T, "len" bytes long.
7424  * This avoids calling free() for every little struct we use (and keeping
7425  * track of them).
7426  * The memory is cleared to all zeros.
7427  * Returns NULL when out of memory.
7428  */
7429     static void *
7430 getroom(spin, len, align)
7431     spellinfo_T *spin;
7432     size_t	len;		/* length needed */
7433     int		align;		/* align for pointer */
7434 {
7435     char_u	*p;
7436     sblock_T	*bl = spin->si_blocks;
7437 
7438     if (align && bl != NULL)
7439 	/* Round size up for alignment.  On some systems structures need to be
7440 	 * aligned to the size of a pointer (e.g., SPARC). */
7441 	bl->sb_used = (bl->sb_used + sizeof(char *) - 1)
7442 						      & ~(sizeof(char *) - 1);
7443 
7444     if (bl == NULL || bl->sb_used + len > SBLOCKSIZE)
7445     {
7446 	/* Allocate a block of memory. This is not freed until much later. */
7447 	bl = (sblock_T *)alloc_clear((unsigned)(sizeof(sblock_T) + SBLOCKSIZE));
7448 	if (bl == NULL)
7449 	    return NULL;
7450 	bl->sb_next = spin->si_blocks;
7451 	spin->si_blocks = bl;
7452 	bl->sb_used = 0;
7453 	++spin->si_blocks_cnt;
7454     }
7455 
7456     p = bl->sb_data + bl->sb_used;
7457     bl->sb_used += (int)len;
7458 
7459     return p;
7460 }
7461 
7462 /*
7463  * Make a copy of a string into memory allocated with getroom().
7464  */
7465     static char_u *
7466 getroom_save(spin, s)
7467     spellinfo_T	*spin;
7468     char_u	*s;
7469 {
7470     char_u	*sc;
7471 
7472     sc = (char_u *)getroom(spin, STRLEN(s) + 1, FALSE);
7473     if (sc != NULL)
7474 	STRCPY(sc, s);
7475     return sc;
7476 }
7477 
7478 
7479 /*
7480  * Free the list of allocated sblock_T.
7481  */
7482     static void
7483 free_blocks(bl)
7484     sblock_T	*bl;
7485 {
7486     sblock_T	*next;
7487 
7488     while (bl != NULL)
7489     {
7490 	next = bl->sb_next;
7491 	vim_free(bl);
7492 	bl = next;
7493     }
7494 }
7495 
7496 /*
7497  * Allocate the root of a word tree.
7498  */
7499     static wordnode_T *
7500 wordtree_alloc(spin)
7501     spellinfo_T *spin;
7502 {
7503     return (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
7504 }
7505 
7506 /*
7507  * Store a word in the tree(s).
7508  * Always store it in the case-folded tree.  For a keep-case word this is
7509  * useful when the word can also be used with all caps (no WF_FIXCAP flag) and
7510  * used to find suggestions.
7511  * For a keep-case word also store it in the keep-case tree.
7512  * When "pfxlist" is not NULL store the word for each postponed prefix ID and
7513  * compound flag.
7514  */
7515     static int
7516 store_word(spin, word, flags, region, pfxlist, need_affix)
7517     spellinfo_T	*spin;
7518     char_u	*word;
7519     int		flags;		/* extra flags, WF_BANNED */
7520     int		region;		/* supported region(s) */
7521     char_u	*pfxlist;	/* list of prefix IDs or NULL */
7522     int		need_affix;	/* only store word with affix ID */
7523 {
7524     int		len = (int)STRLEN(word);
7525     int		ct = captype(word, word + len);
7526     char_u	foldword[MAXWLEN];
7527     int		res = OK;
7528     char_u	*p;
7529 
7530     (void)spell_casefold(word, len, foldword, MAXWLEN);
7531     for (p = pfxlist; res == OK; ++p)
7532     {
7533 	if (!need_affix || (p != NULL && *p != NUL))
7534 	    res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
7535 						  region, p == NULL ? 0 : *p);
7536 	if (p == NULL || *p == NUL)
7537 	    break;
7538     }
7539     ++spin->si_foldwcount;
7540 
7541     if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP)))
7542     {
7543 	for (p = pfxlist; res == OK; ++p)
7544 	{
7545 	    if (!need_affix || (p != NULL && *p != NUL))
7546 		res = tree_add_word(spin, word, spin->si_keeproot, flags,
7547 						  region, p == NULL ? 0 : *p);
7548 	    if (p == NULL || *p == NUL)
7549 		break;
7550 	}
7551 	++spin->si_keepwcount;
7552     }
7553     return res;
7554 }
7555 
7556 /*
7557  * Add word "word" to a word tree at "root".
7558  * When "flags" < 0 we are adding to the prefix tree where "flags" is used for
7559  * "rare" and "region" is the condition nr.
7560  * Returns FAIL when out of memory.
7561  */
7562     static int
7563 tree_add_word(spin, word, root, flags, region, affixID)
7564     spellinfo_T	*spin;
7565     char_u	*word;
7566     wordnode_T	*root;
7567     int		flags;
7568     int		region;
7569     int		affixID;
7570 {
7571     wordnode_T	*node = root;
7572     wordnode_T	*np;
7573     wordnode_T	*copyp, **copyprev;
7574     wordnode_T	**prev = NULL;
7575     int		i;
7576 
7577     /* Add each byte of the word to the tree, including the NUL at the end. */
7578     for (i = 0; ; ++i)
7579     {
7580 	/* When there is more than one reference to this node we need to make
7581 	 * a copy, so that we can modify it.  Copy the whole list of siblings
7582 	 * (we don't optimize for a partly shared list of siblings). */
7583 	if (node != NULL && node->wn_refs > 1)
7584 	{
7585 	    --node->wn_refs;
7586 	    copyprev = prev;
7587 	    for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling)
7588 	    {
7589 		/* Allocate a new node and copy the info. */
7590 		np = get_wordnode(spin);
7591 		if (np == NULL)
7592 		    return FAIL;
7593 		np->wn_child = copyp->wn_child;
7594 		if (np->wn_child != NULL)
7595 		    ++np->wn_child->wn_refs;	/* child gets extra ref */
7596 		np->wn_byte = copyp->wn_byte;
7597 		if (np->wn_byte == NUL)
7598 		{
7599 		    np->wn_flags = copyp->wn_flags;
7600 		    np->wn_region = copyp->wn_region;
7601 		    np->wn_affixID = copyp->wn_affixID;
7602 		}
7603 
7604 		/* Link the new node in the list, there will be one ref. */
7605 		np->wn_refs = 1;
7606 		if (copyprev != NULL)
7607 		    *copyprev = np;
7608 		copyprev = &np->wn_sibling;
7609 
7610 		/* Let "node" point to the head of the copied list. */
7611 		if (copyp == node)
7612 		    node = np;
7613 	    }
7614 	}
7615 
7616 	/* Look for the sibling that has the same character.  They are sorted
7617 	 * on byte value, thus stop searching when a sibling is found with a
7618 	 * higher byte value.  For zero bytes (end of word) the sorting is
7619 	 * done on flags and then on affixID. */
7620 	while (node != NULL
7621 		&& (node->wn_byte < word[i]
7622 		    || (node->wn_byte == NUL
7623 			&& (flags < 0
7624 			    ? node->wn_affixID < (unsigned)affixID
7625 			    : (node->wn_flags < (unsigned)(flags & WN_MASK)
7626 				|| (node->wn_flags == (flags & WN_MASK)
7627 				    && (spin->si_sugtree
7628 					? (node->wn_region & 0xffff) < region
7629 					: node->wn_affixID
7630 						    < (unsigned)affixID)))))))
7631 	{
7632 	    prev = &node->wn_sibling;
7633 	    node = *prev;
7634 	}
7635 	if (node == NULL
7636 		|| node->wn_byte != word[i]
7637 		|| (word[i] == NUL
7638 		    && (flags < 0
7639 			|| spin->si_sugtree
7640 			|| node->wn_flags != (flags & WN_MASK)
7641 			|| node->wn_affixID != affixID)))
7642 	{
7643 	    /* Allocate a new node. */
7644 	    np = get_wordnode(spin);
7645 	    if (np == NULL)
7646 		return FAIL;
7647 	    np->wn_byte = word[i];
7648 
7649 	    /* If "node" is NULL this is a new child or the end of the sibling
7650 	     * list: ref count is one.  Otherwise use ref count of sibling and
7651 	     * make ref count of sibling one (matters when inserting in front
7652 	     * of the list of siblings). */
7653 	    if (node == NULL)
7654 		np->wn_refs = 1;
7655 	    else
7656 	    {
7657 		np->wn_refs = node->wn_refs;
7658 		node->wn_refs = 1;
7659 	    }
7660 	    *prev = np;
7661 	    np->wn_sibling = node;
7662 	    node = np;
7663 	}
7664 
7665 	if (word[i] == NUL)
7666 	{
7667 	    node->wn_flags = flags;
7668 	    node->wn_region |= region;
7669 	    node->wn_affixID = affixID;
7670 	    break;
7671 	}
7672 	prev = &node->wn_child;
7673 	node = *prev;
7674     }
7675 #ifdef SPELL_PRINTTREE
7676     smsg("Added \"%s\"", word);
7677     spell_print_tree(root->wn_sibling);
7678 #endif
7679 
7680     /* count nr of words added since last message */
7681     ++spin->si_msg_count;
7682 
7683     if (spin->si_compress_cnt > 1)
7684     {
7685 	if (--spin->si_compress_cnt == 1)
7686 	    /* Did enough words to lower the block count limit. */
7687 	    spin->si_blocks_cnt += compress_inc;
7688     }
7689 
7690     /*
7691      * When we have allocated lots of memory we need to compress the word tree
7692      * to free up some room.  But compression is slow, and we might actually
7693      * need that room, thus only compress in the following situations:
7694      * 1. When not compressed before (si_compress_cnt == 0): when using
7695      *    "compress_start" blocks.
7696      * 2. When compressed before and used "compress_inc" blocks before
7697      *    adding "compress_added" words (si_compress_cnt > 1).
7698      * 3. When compressed before, added "compress_added" words
7699      *    (si_compress_cnt == 1) and the number of free nodes drops below the
7700      *    maximum word length.
7701      */
7702 #ifndef SPELL_PRINTTREE
7703     if (spin->si_compress_cnt == 1
7704 	    ? spin->si_free_count < MAXWLEN
7705 	    : spin->si_blocks_cnt >= compress_start)
7706 #endif
7707     {
7708 	/* Decrement the block counter.  The effect is that we compress again
7709 	 * when the freed up room has been used and another "compress_inc"
7710 	 * blocks have been allocated.  Unless "compress_added" words have
7711 	 * been added, then the limit is put back again. */
7712 	spin->si_blocks_cnt -= compress_inc;
7713 	spin->si_compress_cnt = compress_added;
7714 
7715 	if (spin->si_verbose)
7716 	{
7717 	    msg_start();
7718 	    msg_puts((char_u *)_(msg_compressing));
7719 	    msg_clr_eos();
7720 	    msg_didout = FALSE;
7721 	    msg_col = 0;
7722 	    out_flush();
7723 	}
7724 
7725 	/* Compress both trees.  Either they both have many nodes, which makes
7726 	 * compression useful, or one of them is small, which means
7727 	 * compression goes fast.  But when filling the souldfold word tree
7728 	 * there is no keep-case tree. */
7729 	wordtree_compress(spin, spin->si_foldroot);
7730 	if (affixID >= 0)
7731 	    wordtree_compress(spin, spin->si_keeproot);
7732     }
7733 
7734     return OK;
7735 }
7736 
7737 /*
7738  * Check the 'mkspellmem' option.  Return FAIL if it's wrong.
7739  * Sets "sps_flags".
7740  */
7741     int
7742 spell_check_msm()
7743 {
7744     char_u	*p = p_msm;
7745     long	start = 0;
7746     long	incr = 0;
7747     long	added = 0;
7748 
7749     if (!VIM_ISDIGIT(*p))
7750 	return FAIL;
7751     /* block count = (value * 1024) / SBLOCKSIZE (but avoid overflow)*/
7752     start = (getdigits(&p) * 10) / (SBLOCKSIZE / 102);
7753     if (*p != ',')
7754 	return FAIL;
7755     ++p;
7756     if (!VIM_ISDIGIT(*p))
7757 	return FAIL;
7758     incr = (getdigits(&p) * 102) / (SBLOCKSIZE / 10);
7759     if (*p != ',')
7760 	return FAIL;
7761     ++p;
7762     if (!VIM_ISDIGIT(*p))
7763 	return FAIL;
7764     added = getdigits(&p) * 1024;
7765     if (*p != NUL)
7766 	return FAIL;
7767 
7768     if (start == 0 || incr == 0 || added == 0 || incr > start)
7769 	return FAIL;
7770 
7771     compress_start = start;
7772     compress_inc = incr;
7773     compress_added = added;
7774     return OK;
7775 }
7776 
7777 
7778 /*
7779  * Get a wordnode_T, either from the list of previously freed nodes or
7780  * allocate a new one.
7781  */
7782     static wordnode_T *
7783 get_wordnode(spin)
7784     spellinfo_T	    *spin;
7785 {
7786     wordnode_T *n;
7787 
7788     if (spin->si_first_free == NULL)
7789 	n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
7790     else
7791     {
7792 	n = spin->si_first_free;
7793 	spin->si_first_free = n->wn_child;
7794 	vim_memset(n, 0, sizeof(wordnode_T));
7795 	--spin->si_free_count;
7796     }
7797 #ifdef SPELL_PRINTTREE
7798     n->wn_nr = ++spin->si_wordnode_nr;
7799 #endif
7800     return n;
7801 }
7802 
7803 /*
7804  * Decrement the reference count on a node (which is the head of a list of
7805  * siblings).  If the reference count becomes zero free the node and its
7806  * siblings.
7807  * Returns the number of nodes actually freed.
7808  */
7809     static int
7810 deref_wordnode(spin, node)
7811     spellinfo_T *spin;
7812     wordnode_T  *node;
7813 {
7814     wordnode_T	*np;
7815     int		cnt = 0;
7816 
7817     if (--node->wn_refs == 0)
7818     {
7819 	for (np = node; np != NULL; np = np->wn_sibling)
7820 	{
7821 	    if (np->wn_child != NULL)
7822 		cnt += deref_wordnode(spin, np->wn_child);
7823 	    free_wordnode(spin, np);
7824 	    ++cnt;
7825 	}
7826 	++cnt;	    /* length field */
7827     }
7828     return cnt;
7829 }
7830 
7831 /*
7832  * Free a wordnode_T for re-use later.
7833  * Only the "wn_child" field becomes invalid.
7834  */
7835     static void
7836 free_wordnode(spin, n)
7837     spellinfo_T	*spin;
7838     wordnode_T  *n;
7839 {
7840     n->wn_child = spin->si_first_free;
7841     spin->si_first_free = n;
7842     ++spin->si_free_count;
7843 }
7844 
7845 /*
7846  * Compress a tree: find tails that are identical and can be shared.
7847  */
7848     static void
7849 wordtree_compress(spin, root)
7850     spellinfo_T	    *spin;
7851     wordnode_T	    *root;
7852 {
7853     hashtab_T	    ht;
7854     int		    n;
7855     int		    tot = 0;
7856     int		    perc;
7857 
7858     /* Skip the root itself, it's not actually used.  The first sibling is the
7859      * start of the tree. */
7860     if (root->wn_sibling != NULL)
7861     {
7862 	hash_init(&ht);
7863 	n = node_compress(spin, root->wn_sibling, &ht, &tot);
7864 
7865 #ifndef SPELL_PRINTTREE
7866 	if (spin->si_verbose || p_verbose > 2)
7867 #endif
7868 	{
7869 	    if (tot > 1000000)
7870 		perc = (tot - n) / (tot / 100);
7871 	    else if (tot == 0)
7872 		perc = 0;
7873 	    else
7874 		perc = (tot - n) * 100 / tot;
7875 	    vim_snprintf((char *)IObuff, IOSIZE,
7876 			  _("Compressed %d of %d nodes; %d (%d%%) remaining"),
7877 						       n, tot, tot - n, perc);
7878 	    spell_message(spin, IObuff);
7879 	}
7880 #ifdef SPELL_PRINTTREE
7881 	spell_print_tree(root->wn_sibling);
7882 #endif
7883 	hash_clear(&ht);
7884     }
7885 }
7886 
7887 /*
7888  * Compress a node, its siblings and its children, depth first.
7889  * Returns the number of compressed nodes.
7890  */
7891     static int
7892 node_compress(spin, node, ht, tot)
7893     spellinfo_T	*spin;
7894     wordnode_T	*node;
7895     hashtab_T	*ht;
7896     int		*tot;	    /* total count of nodes before compressing,
7897 			       incremented while going through the tree */
7898 {
7899     wordnode_T	*np;
7900     wordnode_T	*tp;
7901     wordnode_T	*child;
7902     hash_T	hash;
7903     hashitem_T	*hi;
7904     int		len = 0;
7905     unsigned	nr, n;
7906     int		compressed = 0;
7907 
7908     /*
7909      * Go through the list of siblings.  Compress each child and then try
7910      * finding an identical child to replace it.
7911      * Note that with "child" we mean not just the node that is pointed to,
7912      * but the whole list of siblings of which the child node is the first.
7913      */
7914     for (np = node; np != NULL && !got_int; np = np->wn_sibling)
7915     {
7916 	++len;
7917 	if ((child = np->wn_child) != NULL)
7918 	{
7919 	    /* Compress the child first.  This fills hashkey. */
7920 	    compressed += node_compress(spin, child, ht, tot);
7921 
7922 	    /* Try to find an identical child. */
7923 	    hash = hash_hash(child->wn_u1.hashkey);
7924 	    hi = hash_lookup(ht, child->wn_u1.hashkey, hash);
7925 	    if (!HASHITEM_EMPTY(hi))
7926 	    {
7927 		/* There are children we encountered before with a hash value
7928 		 * identical to the current child.  Now check if there is one
7929 		 * that is really identical. */
7930 		for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next)
7931 		    if (node_equal(child, tp))
7932 		    {
7933 			/* Found one!  Now use that child in place of the
7934 			 * current one.  This means the current child and all
7935 			 * its siblings is unlinked from the tree. */
7936 			++tp->wn_refs;
7937 			compressed += deref_wordnode(spin, child);
7938 			np->wn_child = tp;
7939 			break;
7940 		    }
7941 		if (tp == NULL)
7942 		{
7943 		    /* No other child with this hash value equals the child of
7944 		     * the node, add it to the linked list after the first
7945 		     * item. */
7946 		    tp = HI2WN(hi);
7947 		    child->wn_u2.next = tp->wn_u2.next;
7948 		    tp->wn_u2.next = child;
7949 		}
7950 	    }
7951 	    else
7952 		/* No other child has this hash value, add it to the
7953 		 * hashtable. */
7954 		hash_add_item(ht, hi, child->wn_u1.hashkey, hash);
7955 	}
7956     }
7957     *tot += len + 1;	/* add one for the node that stores the length */
7958 
7959     /*
7960      * Make a hash key for the node and its siblings, so that we can quickly
7961      * find a lookalike node.  This must be done after compressing the sibling
7962      * list, otherwise the hash key would become invalid by the compression.
7963      */
7964     node->wn_u1.hashkey[0] = len;
7965     nr = 0;
7966     for (np = node; np != NULL; np = np->wn_sibling)
7967     {
7968 	if (np->wn_byte == NUL)
7969 	    /* end node: use wn_flags, wn_region and wn_affixID */
7970 	    n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16);
7971 	else
7972 	    /* byte node: use the byte value and the child pointer */
7973 	    n = (unsigned)(np->wn_byte + ((long_u)np->wn_child << 8));
7974 	nr = nr * 101 + n;
7975     }
7976 
7977     /* Avoid NUL bytes, it terminates the hash key. */
7978     n = nr & 0xff;
7979     node->wn_u1.hashkey[1] = n == 0 ? 1 : n;
7980     n = (nr >> 8) & 0xff;
7981     node->wn_u1.hashkey[2] = n == 0 ? 1 : n;
7982     n = (nr >> 16) & 0xff;
7983     node->wn_u1.hashkey[3] = n == 0 ? 1 : n;
7984     n = (nr >> 24) & 0xff;
7985     node->wn_u1.hashkey[4] = n == 0 ? 1 : n;
7986     node->wn_u1.hashkey[5] = NUL;
7987 
7988     /* Check for CTRL-C pressed now and then. */
7989     fast_breakcheck();
7990 
7991     return compressed;
7992 }
7993 
7994 /*
7995  * Return TRUE when two nodes have identical siblings and children.
7996  */
7997     static int
7998 node_equal(n1, n2)
7999     wordnode_T	*n1;
8000     wordnode_T	*n2;
8001 {
8002     wordnode_T	*p1;
8003     wordnode_T	*p2;
8004 
8005     for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL;
8006 				     p1 = p1->wn_sibling, p2 = p2->wn_sibling)
8007 	if (p1->wn_byte != p2->wn_byte
8008 		|| (p1->wn_byte == NUL
8009 		    ? (p1->wn_flags != p2->wn_flags
8010 			|| p1->wn_region != p2->wn_region
8011 			|| p1->wn_affixID != p2->wn_affixID)
8012 		    : (p1->wn_child != p2->wn_child)))
8013 	    break;
8014 
8015     return p1 == NULL && p2 == NULL;
8016 }
8017 
8018 /*
8019  * Write a number to file "fd", MSB first, in "len" bytes.
8020  */
8021     void
8022 put_bytes(fd, nr, len)
8023     FILE    *fd;
8024     long_u  nr;
8025     int	    len;
8026 {
8027     int	    i;
8028 
8029     for (i = len - 1; i >= 0; --i)
8030 	putc((int)(nr >> (i * 8)), fd);
8031 }
8032 
8033 #ifdef _MSC_VER
8034 # if (_MSC_VER <= 1200)
8035 /* This line is required for VC6 without the service pack.  Also see the
8036  * matching #pragma below. */
8037  #  pragma optimize("", off)
8038 # endif
8039 #endif
8040 
8041 /*
8042  * Write spin->si_sugtime to file "fd".
8043  */
8044     static void
8045 put_sugtime(spin, fd)
8046     spellinfo_T *spin;
8047     FILE	*fd;
8048 {
8049     int		c;
8050     int		i;
8051 
8052     /* time_t can be up to 8 bytes in size, more than long_u, thus we
8053      * can't use put_bytes() here. */
8054     for (i = 7; i >= 0; --i)
8055 	if (i + 1 > (int)sizeof(time_t))
8056 	    /* ">>" doesn't work well when shifting more bits than avail */
8057 	    putc(0, fd);
8058 	else
8059 	{
8060 	    c = (unsigned)spin->si_sugtime >> (i * 8);
8061 	    putc(c, fd);
8062 	}
8063 }
8064 
8065 #ifdef _MSC_VER
8066 # if (_MSC_VER <= 1200)
8067  #  pragma optimize("", on)
8068 # endif
8069 #endif
8070 
8071 static int
8072 #ifdef __BORLANDC__
8073 _RTLENTRYF
8074 #endif
8075 rep_compare __ARGS((const void *s1, const void *s2));
8076 
8077 /*
8078  * Function given to qsort() to sort the REP items on "from" string.
8079  */
8080     static int
8081 #ifdef __BORLANDC__
8082 _RTLENTRYF
8083 #endif
8084 rep_compare(s1, s2)
8085     const void	*s1;
8086     const void	*s2;
8087 {
8088     fromto_T	*p1 = (fromto_T *)s1;
8089     fromto_T	*p2 = (fromto_T *)s2;
8090 
8091     return STRCMP(p1->ft_from, p2->ft_from);
8092 }
8093 
8094 /*
8095  * Write the Vim .spl file "fname".
8096  * Return FAIL or OK;
8097  */
8098     static int
8099 write_vim_spell(spin, fname)
8100     spellinfo_T	*spin;
8101     char_u	*fname;
8102 {
8103     FILE	*fd;
8104     int		regionmask;
8105     int		round;
8106     wordnode_T	*tree;
8107     int		nodecount;
8108     int		i;
8109     int		l;
8110     garray_T	*gap;
8111     fromto_T	*ftp;
8112     char_u	*p;
8113     int		rr;
8114     int		retval = OK;
8115     size_t	fwv = 1;  /* collect return value of fwrite() to avoid
8116 			     warnings from picky compiler */
8117 
8118     fd = mch_fopen((char *)fname, "w");
8119     if (fd == NULL)
8120     {
8121 	EMSG2(_(e_notopen), fname);
8122 	return FAIL;
8123     }
8124 
8125     /* <HEADER>: <fileID> <versionnr> */
8126 							    /* <fileID> */
8127     fwv &= fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd);
8128     if (fwv != (size_t)1)
8129 	/* Catch first write error, don't try writing more. */
8130 	goto theend;
8131 
8132     putc(VIMSPELLVERSION, fd);				    /* <versionnr> */
8133 
8134     /*
8135      * <SECTIONS>: <section> ... <sectionend>
8136      */
8137 
8138     /* SN_INFO: <infotext> */
8139     if (spin->si_info != NULL)
8140     {
8141 	putc(SN_INFO, fd);				/* <sectionID> */
8142 	putc(0, fd);					/* <sectionflags> */
8143 
8144 	i = (int)STRLEN(spin->si_info);
8145 	put_bytes(fd, (long_u)i, 4);			/* <sectionlen> */
8146 	fwv &= fwrite(spin->si_info, (size_t)i, (size_t)1, fd); /* <infotext> */
8147     }
8148 
8149     /* SN_REGION: <regionname> ...
8150      * Write the region names only if there is more than one. */
8151     if (spin->si_region_count > 1)
8152     {
8153 	putc(SN_REGION, fd);				/* <sectionID> */
8154 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8155 	l = spin->si_region_count * 2;
8156 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8157 	fwv &= fwrite(spin->si_region_name, (size_t)l, (size_t)1, fd);
8158 							/* <regionname> ... */
8159 	regionmask = (1 << spin->si_region_count) - 1;
8160     }
8161     else
8162 	regionmask = 0;
8163 
8164     /* SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars>
8165      *
8166      * The table with character flags and the table for case folding.
8167      * This makes sure the same characters are recognized as word characters
8168      * when generating an when using a spell file.
8169      * Skip this for ASCII, the table may conflict with the one used for
8170      * 'encoding'.
8171      * Also skip this for an .add.spl file, the main spell file must contain
8172      * the table (avoids that it conflicts).  File is shorter too.
8173      */
8174     if (!spin->si_ascii && !spin->si_add)
8175     {
8176 	char_u	folchars[128 * 8];
8177 	int	flags;
8178 
8179 	putc(SN_CHARFLAGS, fd);				/* <sectionID> */
8180 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8181 
8182 	/* Form the <folchars> string first, we need to know its length. */
8183 	l = 0;
8184 	for (i = 128; i < 256; ++i)
8185 	{
8186 #ifdef FEAT_MBYTE
8187 	    if (has_mbyte)
8188 		l += mb_char2bytes(spelltab.st_fold[i], folchars + l);
8189 	    else
8190 #endif
8191 		folchars[l++] = spelltab.st_fold[i];
8192 	}
8193 	put_bytes(fd, (long_u)(1 + 128 + 2 + l), 4);	/* <sectionlen> */
8194 
8195 	fputc(128, fd);					/* <charflagslen> */
8196 	for (i = 128; i < 256; ++i)
8197 	{
8198 	    flags = 0;
8199 	    if (spelltab.st_isw[i])
8200 		flags |= CF_WORD;
8201 	    if (spelltab.st_isu[i])
8202 		flags |= CF_UPPER;
8203 	    fputc(flags, fd);				/* <charflags> */
8204 	}
8205 
8206 	put_bytes(fd, (long_u)l, 2);			/* <folcharslen> */
8207 	fwv &= fwrite(folchars, (size_t)l, (size_t)1, fd); /* <folchars> */
8208     }
8209 
8210     /* SN_MIDWORD: <midword> */
8211     if (spin->si_midword != NULL)
8212     {
8213 	putc(SN_MIDWORD, fd);				/* <sectionID> */
8214 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8215 
8216 	i = (int)STRLEN(spin->si_midword);
8217 	put_bytes(fd, (long_u)i, 4);			/* <sectionlen> */
8218 	fwv &= fwrite(spin->si_midword, (size_t)i, (size_t)1, fd);
8219 							/* <midword> */
8220     }
8221 
8222     /* SN_PREFCOND: <prefcondcnt> <prefcond> ... */
8223     if (spin->si_prefcond.ga_len > 0)
8224     {
8225 	putc(SN_PREFCOND, fd);				/* <sectionID> */
8226 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8227 
8228 	l = write_spell_prefcond(NULL, &spin->si_prefcond);
8229 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8230 
8231 	write_spell_prefcond(fd, &spin->si_prefcond);
8232     }
8233 
8234     /* SN_REP: <repcount> <rep> ...
8235      * SN_SAL: <salflags> <salcount> <sal> ...
8236      * SN_REPSAL: <repcount> <rep> ... */
8237 
8238     /* round 1: SN_REP section
8239      * round 2: SN_SAL section (unless SN_SOFO is used)
8240      * round 3: SN_REPSAL section */
8241     for (round = 1; round <= 3; ++round)
8242     {
8243 	if (round == 1)
8244 	    gap = &spin->si_rep;
8245 	else if (round == 2)
8246 	{
8247 	    /* Don't write SN_SAL when using a SN_SOFO section */
8248 	    if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
8249 		continue;
8250 	    gap = &spin->si_sal;
8251 	}
8252 	else
8253 	    gap = &spin->si_repsal;
8254 
8255 	/* Don't write the section if there are no items. */
8256 	if (gap->ga_len == 0)
8257 	    continue;
8258 
8259 	/* Sort the REP/REPSAL items. */
8260 	if (round != 2)
8261 	    qsort(gap->ga_data, (size_t)gap->ga_len,
8262 					       sizeof(fromto_T), rep_compare);
8263 
8264 	i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL);
8265 	putc(i, fd);					/* <sectionID> */
8266 
8267 	/* This is for making suggestions, section is not required. */
8268 	putc(0, fd);					/* <sectionflags> */
8269 
8270 	/* Compute the length of what follows. */
8271 	l = 2;	    /* count <repcount> or <salcount> */
8272 	for (i = 0; i < gap->ga_len; ++i)
8273 	{
8274 	    ftp = &((fromto_T *)gap->ga_data)[i];
8275 	    l += 1 + (int)STRLEN(ftp->ft_from);  /* count <*fromlen> and <*from> */
8276 	    l += 1 + (int)STRLEN(ftp->ft_to);    /* count <*tolen> and <*to> */
8277 	}
8278 	if (round == 2)
8279 	    ++l;	/* count <salflags> */
8280 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8281 
8282 	if (round == 2)
8283 	{
8284 	    i = 0;
8285 	    if (spin->si_followup)
8286 		i |= SAL_F0LLOWUP;
8287 	    if (spin->si_collapse)
8288 		i |= SAL_COLLAPSE;
8289 	    if (spin->si_rem_accents)
8290 		i |= SAL_REM_ACCENTS;
8291 	    putc(i, fd);			/* <salflags> */
8292 	}
8293 
8294 	put_bytes(fd, (long_u)gap->ga_len, 2);	/* <repcount> or <salcount> */
8295 	for (i = 0; i < gap->ga_len; ++i)
8296 	{
8297 	    /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
8298 	    /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
8299 	    ftp = &((fromto_T *)gap->ga_data)[i];
8300 	    for (rr = 1; rr <= 2; ++rr)
8301 	    {
8302 		p = rr == 1 ? ftp->ft_from : ftp->ft_to;
8303 		l = (int)STRLEN(p);
8304 		putc(l, fd);
8305 		if (l > 0)
8306 		    fwv &= fwrite(p, l, (size_t)1, fd);
8307 	    }
8308 	}
8309 
8310     }
8311 
8312     /* SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
8313      * This is for making suggestions, section is not required. */
8314     if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
8315     {
8316 	putc(SN_SOFO, fd);				/* <sectionID> */
8317 	putc(0, fd);					/* <sectionflags> */
8318 
8319 	l = (int)STRLEN(spin->si_sofofr);
8320 	put_bytes(fd, (long_u)(l + STRLEN(spin->si_sofoto) + 4), 4);
8321 							/* <sectionlen> */
8322 
8323 	put_bytes(fd, (long_u)l, 2);			/* <sofofromlen> */
8324 	fwv &= fwrite(spin->si_sofofr, l, (size_t)1, fd); /* <sofofrom> */
8325 
8326 	l = (int)STRLEN(spin->si_sofoto);
8327 	put_bytes(fd, (long_u)l, 2);			/* <sofotolen> */
8328 	fwv &= fwrite(spin->si_sofoto, l, (size_t)1, fd); /* <sofoto> */
8329     }
8330 
8331     /* SN_WORDS: <word> ...
8332      * This is for making suggestions, section is not required. */
8333     if (spin->si_commonwords.ht_used > 0)
8334     {
8335 	putc(SN_WORDS, fd);				/* <sectionID> */
8336 	putc(0, fd);					/* <sectionflags> */
8337 
8338 	/* round 1: count the bytes
8339 	 * round 2: write the bytes */
8340 	for (round = 1; round <= 2; ++round)
8341 	{
8342 	    int		todo;
8343 	    int		len = 0;
8344 	    hashitem_T	*hi;
8345 
8346 	    todo = (int)spin->si_commonwords.ht_used;
8347 	    for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi)
8348 		if (!HASHITEM_EMPTY(hi))
8349 		{
8350 		    l = (int)STRLEN(hi->hi_key) + 1;
8351 		    len += l;
8352 		    if (round == 2)			/* <word> */
8353 			fwv &= fwrite(hi->hi_key, (size_t)l, (size_t)1, fd);
8354 		    --todo;
8355 		}
8356 	    if (round == 1)
8357 		put_bytes(fd, (long_u)len, 4);		/* <sectionlen> */
8358 	}
8359     }
8360 
8361     /* SN_MAP: <mapstr>
8362      * This is for making suggestions, section is not required. */
8363     if (spin->si_map.ga_len > 0)
8364     {
8365 	putc(SN_MAP, fd);				/* <sectionID> */
8366 	putc(0, fd);					/* <sectionflags> */
8367 	l = spin->si_map.ga_len;
8368 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8369 	fwv &= fwrite(spin->si_map.ga_data, (size_t)l, (size_t)1, fd);
8370 							/* <mapstr> */
8371     }
8372 
8373     /* SN_SUGFILE: <timestamp>
8374      * This is used to notify that a .sug file may be available and at the
8375      * same time allows for checking that a .sug file that is found matches
8376      * with this .spl file.  That's because the word numbers must be exactly
8377      * right. */
8378     if (!spin->si_nosugfile
8379 	    && (spin->si_sal.ga_len > 0
8380 		     || (spin->si_sofofr != NULL && spin->si_sofoto != NULL)))
8381     {
8382 	putc(SN_SUGFILE, fd);				/* <sectionID> */
8383 	putc(0, fd);					/* <sectionflags> */
8384 	put_bytes(fd, (long_u)8, 4);			/* <sectionlen> */
8385 
8386 	/* Set si_sugtime and write it to the file. */
8387 	spin->si_sugtime = time(NULL);
8388 	put_sugtime(spin, fd);				/* <timestamp> */
8389     }
8390 
8391     /* SN_NOSPLITSUGS: nothing
8392      * This is used to notify that no suggestions with word splits are to be
8393      * made. */
8394     if (spin->si_nosplitsugs)
8395     {
8396 	putc(SN_NOSPLITSUGS, fd);			/* <sectionID> */
8397 	putc(0, fd);					/* <sectionflags> */
8398 	put_bytes(fd, (long_u)0, 4);			/* <sectionlen> */
8399     }
8400 
8401     /* SN_COMPOUND: compound info.
8402      * We don't mark it required, when not supported all compound words will
8403      * be bad words. */
8404     if (spin->si_compflags != NULL)
8405     {
8406 	putc(SN_COMPOUND, fd);				/* <sectionID> */
8407 	putc(0, fd);					/* <sectionflags> */
8408 
8409 	l = (int)STRLEN(spin->si_compflags);
8410 	for (i = 0; i < spin->si_comppat.ga_len; ++i)
8411 	    l += (int)STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1;
8412 	put_bytes(fd, (long_u)(l + 7), 4);		/* <sectionlen> */
8413 
8414 	putc(spin->si_compmax, fd);			/* <compmax> */
8415 	putc(spin->si_compminlen, fd);			/* <compminlen> */
8416 	putc(spin->si_compsylmax, fd);			/* <compsylmax> */
8417 	putc(0, fd);		/* for Vim 7.0b compatibility */
8418 	putc(spin->si_compoptions, fd);			/* <compoptions> */
8419 	put_bytes(fd, (long_u)spin->si_comppat.ga_len, 2);
8420 							/* <comppatcount> */
8421 	for (i = 0; i < spin->si_comppat.ga_len; ++i)
8422 	{
8423 	    p = ((char_u **)(spin->si_comppat.ga_data))[i];
8424 	    putc((int)STRLEN(p), fd);			/* <comppatlen> */
8425 	    fwv &= fwrite(p, (size_t)STRLEN(p), (size_t)1, fd);
8426 							/* <comppattext> */
8427 	}
8428 							/* <compflags> */
8429 	fwv &= fwrite(spin->si_compflags, (size_t)STRLEN(spin->si_compflags),
8430 							       (size_t)1, fd);
8431     }
8432 
8433     /* SN_NOBREAK: NOBREAK flag */
8434     if (spin->si_nobreak)
8435     {
8436 	putc(SN_NOBREAK, fd);				/* <sectionID> */
8437 	putc(0, fd);					/* <sectionflags> */
8438 
8439 	/* It's empty, the presence of the section flags the feature. */
8440 	put_bytes(fd, (long_u)0, 4);			/* <sectionlen> */
8441     }
8442 
8443     /* SN_SYLLABLE: syllable info.
8444      * We don't mark it required, when not supported syllables will not be
8445      * counted. */
8446     if (spin->si_syllable != NULL)
8447     {
8448 	putc(SN_SYLLABLE, fd);				/* <sectionID> */
8449 	putc(0, fd);					/* <sectionflags> */
8450 
8451 	l = (int)STRLEN(spin->si_syllable);
8452 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8453 	fwv &= fwrite(spin->si_syllable, (size_t)l, (size_t)1, fd);
8454 							/* <syllable> */
8455     }
8456 
8457     /* end of <SECTIONS> */
8458     putc(SN_END, fd);					/* <sectionend> */
8459 
8460 
8461     /*
8462      * <LWORDTREE>  <KWORDTREE>  <PREFIXTREE>
8463      */
8464     spin->si_memtot = 0;
8465     for (round = 1; round <= 3; ++round)
8466     {
8467 	if (round == 1)
8468 	    tree = spin->si_foldroot->wn_sibling;
8469 	else if (round == 2)
8470 	    tree = spin->si_keeproot->wn_sibling;
8471 	else
8472 	    tree = spin->si_prefroot->wn_sibling;
8473 
8474 	/* Clear the index and wnode fields in the tree. */
8475 	clear_node(tree);
8476 
8477 	/* Count the number of nodes.  Needed to be able to allocate the
8478 	 * memory when reading the nodes.  Also fills in index for shared
8479 	 * nodes. */
8480 	nodecount = put_node(NULL, tree, 0, regionmask, round == 3);
8481 
8482 	/* number of nodes in 4 bytes */
8483 	put_bytes(fd, (long_u)nodecount, 4);	/* <nodecount> */
8484 	spin->si_memtot += nodecount + nodecount * sizeof(int);
8485 
8486 	/* Write the nodes. */
8487 	(void)put_node(fd, tree, 0, regionmask, round == 3);
8488     }
8489 
8490     /* Write another byte to check for errors (file system full). */
8491     if (putc(0, fd) == EOF)
8492 	retval = FAIL;
8493 theend:
8494     if (fclose(fd) == EOF)
8495 	retval = FAIL;
8496 
8497     if (fwv != (size_t)1)
8498 	retval = FAIL;
8499     if (retval == FAIL)
8500 	EMSG(_(e_write));
8501 
8502     return retval;
8503 }
8504 
8505 /*
8506  * Clear the index and wnode fields of "node", it siblings and its
8507  * children.  This is needed because they are a union with other items to save
8508  * space.
8509  */
8510     static void
8511 clear_node(node)
8512     wordnode_T	*node;
8513 {
8514     wordnode_T	*np;
8515 
8516     if (node != NULL)
8517 	for (np = node; np != NULL; np = np->wn_sibling)
8518 	{
8519 	    np->wn_u1.index = 0;
8520 	    np->wn_u2.wnode = NULL;
8521 
8522 	    if (np->wn_byte != NUL)
8523 		clear_node(np->wn_child);
8524 	}
8525 }
8526 
8527 
8528 /*
8529  * Dump a word tree at node "node".
8530  *
8531  * This first writes the list of possible bytes (siblings).  Then for each
8532  * byte recursively write the children.
8533  *
8534  * NOTE: The code here must match the code in read_tree_node(), since
8535  * assumptions are made about the indexes (so that we don't have to write them
8536  * in the file).
8537  *
8538  * Returns the number of nodes used.
8539  */
8540     static int
8541 put_node(fd, node, idx, regionmask, prefixtree)
8542     FILE	*fd;		/* NULL when only counting */
8543     wordnode_T	*node;
8544     int		idx;
8545     int		regionmask;
8546     int		prefixtree;	/* TRUE for PREFIXTREE */
8547 {
8548     int		newindex = idx;
8549     int		siblingcount = 0;
8550     wordnode_T	*np;
8551     int		flags;
8552 
8553     /* If "node" is zero the tree is empty. */
8554     if (node == NULL)
8555 	return 0;
8556 
8557     /* Store the index where this node is written. */
8558     node->wn_u1.index = idx;
8559 
8560     /* Count the number of siblings. */
8561     for (np = node; np != NULL; np = np->wn_sibling)
8562 	++siblingcount;
8563 
8564     /* Write the sibling count. */
8565     if (fd != NULL)
8566 	putc(siblingcount, fd);				/* <siblingcount> */
8567 
8568     /* Write each sibling byte and optionally extra info. */
8569     for (np = node; np != NULL; np = np->wn_sibling)
8570     {
8571 	if (np->wn_byte == 0)
8572 	{
8573 	    if (fd != NULL)
8574 	    {
8575 		/* For a NUL byte (end of word) write the flags etc. */
8576 		if (prefixtree)
8577 		{
8578 		    /* In PREFIXTREE write the required affixID and the
8579 		     * associated condition nr (stored in wn_region).  The
8580 		     * byte value is misused to store the "rare" and "not
8581 		     * combining" flags */
8582 		    if (np->wn_flags == (short_u)PFX_FLAGS)
8583 			putc(BY_NOFLAGS, fd);		/* <byte> */
8584 		    else
8585 		    {
8586 			putc(BY_FLAGS, fd);		/* <byte> */
8587 			putc(np->wn_flags, fd);		/* <pflags> */
8588 		    }
8589 		    putc(np->wn_affixID, fd);		/* <affixID> */
8590 		    put_bytes(fd, (long_u)np->wn_region, 2); /* <prefcondnr> */
8591 		}
8592 		else
8593 		{
8594 		    /* For word trees we write the flag/region items. */
8595 		    flags = np->wn_flags;
8596 		    if (regionmask != 0 && np->wn_region != regionmask)
8597 			flags |= WF_REGION;
8598 		    if (np->wn_affixID != 0)
8599 			flags |= WF_AFX;
8600 		    if (flags == 0)
8601 		    {
8602 			/* word without flags or region */
8603 			putc(BY_NOFLAGS, fd);			/* <byte> */
8604 		    }
8605 		    else
8606 		    {
8607 			if (np->wn_flags >= 0x100)
8608 			{
8609 			    putc(BY_FLAGS2, fd);		/* <byte> */
8610 			    putc(flags, fd);			/* <flags> */
8611 			    putc((unsigned)flags >> 8, fd);	/* <flags2> */
8612 			}
8613 			else
8614 			{
8615 			    putc(BY_FLAGS, fd);			/* <byte> */
8616 			    putc(flags, fd);			/* <flags> */
8617 			}
8618 			if (flags & WF_REGION)
8619 			    putc(np->wn_region, fd);		/* <region> */
8620 			if (flags & WF_AFX)
8621 			    putc(np->wn_affixID, fd);		/* <affixID> */
8622 		    }
8623 		}
8624 	    }
8625 	}
8626 	else
8627 	{
8628 	    if (np->wn_child->wn_u1.index != 0
8629 					 && np->wn_child->wn_u2.wnode != node)
8630 	    {
8631 		/* The child is written elsewhere, write the reference. */
8632 		if (fd != NULL)
8633 		{
8634 		    putc(BY_INDEX, fd);			/* <byte> */
8635 							/* <nodeidx> */
8636 		    put_bytes(fd, (long_u)np->wn_child->wn_u1.index, 3);
8637 		}
8638 	    }
8639 	    else if (np->wn_child->wn_u2.wnode == NULL)
8640 		/* We will write the child below and give it an index. */
8641 		np->wn_child->wn_u2.wnode = node;
8642 
8643 	    if (fd != NULL)
8644 		if (putc(np->wn_byte, fd) == EOF) /* <byte> or <xbyte> */
8645 		{
8646 		    EMSG(_(e_write));
8647 		    return 0;
8648 		}
8649 	}
8650     }
8651 
8652     /* Space used in the array when reading: one for each sibling and one for
8653      * the count. */
8654     newindex += siblingcount + 1;
8655 
8656     /* Recursively dump the children of each sibling. */
8657     for (np = node; np != NULL; np = np->wn_sibling)
8658 	if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node)
8659 	    newindex = put_node(fd, np->wn_child, newindex, regionmask,
8660 								  prefixtree);
8661 
8662     return newindex;
8663 }
8664 
8665 
8666 /*
8667  * ":mkspell [-ascii] outfile  infile ..."
8668  * ":mkspell [-ascii] addfile"
8669  */
8670     void
8671 ex_mkspell(eap)
8672     exarg_T *eap;
8673 {
8674     int		fcount;
8675     char_u	**fnames;
8676     char_u	*arg = eap->arg;
8677     int		ascii = FALSE;
8678 
8679     if (STRNCMP(arg, "-ascii", 6) == 0)
8680     {
8681 	ascii = TRUE;
8682 	arg = skipwhite(arg + 6);
8683     }
8684 
8685     /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */
8686     if (get_arglist_exp(arg, &fcount, &fnames) == OK)
8687     {
8688 	mkspell(fcount, fnames, ascii, eap->forceit, FALSE);
8689 	FreeWild(fcount, fnames);
8690     }
8691 }
8692 
8693 /*
8694  * Create the .sug file.
8695  * Uses the soundfold info in "spin".
8696  * Writes the file with the name "wfname", with ".spl" changed to ".sug".
8697  */
8698     static void
8699 spell_make_sugfile(spin, wfname)
8700     spellinfo_T	*spin;
8701     char_u	*wfname;
8702 {
8703     char_u	fname[MAXPATHL];
8704     int		len;
8705     slang_T	*slang;
8706     int		free_slang = FALSE;
8707 
8708     /*
8709      * Read back the .spl file that was written.  This fills the required
8710      * info for soundfolding.  This also uses less memory than the
8711      * pointer-linked version of the trie.  And it avoids having two versions
8712      * of the code for the soundfolding stuff.
8713      * It might have been done already by spell_reload_one().
8714      */
8715     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
8716 	if (fullpathcmp(wfname, slang->sl_fname, FALSE) == FPC_SAME)
8717 	    break;
8718     if (slang == NULL)
8719     {
8720 	spell_message(spin, (char_u *)_("Reading back spell file..."));
8721 	slang = spell_load_file(wfname, NULL, NULL, FALSE);
8722 	if (slang == NULL)
8723 	    return;
8724 	free_slang = TRUE;
8725     }
8726 
8727     /*
8728      * Clear the info in "spin" that is used.
8729      */
8730     spin->si_blocks = NULL;
8731     spin->si_blocks_cnt = 0;
8732     spin->si_compress_cnt = 0;	    /* will stay at 0 all the time*/
8733     spin->si_free_count = 0;
8734     spin->si_first_free = NULL;
8735     spin->si_foldwcount = 0;
8736 
8737     /*
8738      * Go through the trie of good words, soundfold each word and add it to
8739      * the soundfold trie.
8740      */
8741     spell_message(spin, (char_u *)_("Performing soundfolding..."));
8742     if (sug_filltree(spin, slang) == FAIL)
8743 	goto theend;
8744 
8745     /*
8746      * Create the table which links each soundfold word with a list of the
8747      * good words it may come from.  Creates buffer "spin->si_spellbuf".
8748      * This also removes the wordnr from the NUL byte entries to make
8749      * compression possible.
8750      */
8751     if (sug_maketable(spin) == FAIL)
8752 	goto theend;
8753 
8754     smsg((char_u *)_("Number of words after soundfolding: %ld"),
8755 				 (long)spin->si_spellbuf->b_ml.ml_line_count);
8756 
8757     /*
8758      * Compress the soundfold trie.
8759      */
8760     spell_message(spin, (char_u *)_(msg_compressing));
8761     wordtree_compress(spin, spin->si_foldroot);
8762 
8763     /*
8764      * Write the .sug file.
8765      * Make the file name by changing ".spl" to ".sug".
8766      */
8767     STRCPY(fname, wfname);
8768     len = (int)STRLEN(fname);
8769     fname[len - 2] = 'u';
8770     fname[len - 1] = 'g';
8771     sug_write(spin, fname);
8772 
8773 theend:
8774     if (free_slang)
8775 	slang_free(slang);
8776     free_blocks(spin->si_blocks);
8777     close_spellbuf(spin->si_spellbuf);
8778 }
8779 
8780 /*
8781  * Build the soundfold trie for language "slang".
8782  */
8783     static int
8784 sug_filltree(spin, slang)
8785     spellinfo_T	*spin;
8786     slang_T	*slang;
8787 {
8788     char_u	*byts;
8789     idx_T	*idxs;
8790     int		depth;
8791     idx_T	arridx[MAXWLEN];
8792     int		curi[MAXWLEN];
8793     char_u	tword[MAXWLEN];
8794     char_u	tsalword[MAXWLEN];
8795     int		c;
8796     idx_T	n;
8797     unsigned	words_done = 0;
8798     int		wordcount[MAXWLEN];
8799 
8800     /* We use si_foldroot for the souldfolded trie. */
8801     spin->si_foldroot = wordtree_alloc(spin);
8802     if (spin->si_foldroot == NULL)
8803 	return FAIL;
8804 
8805     /* let tree_add_word() know we're adding to the soundfolded tree */
8806     spin->si_sugtree = TRUE;
8807 
8808     /*
8809      * Go through the whole case-folded tree, soundfold each word and put it
8810      * in the trie.
8811      */
8812     byts = slang->sl_fbyts;
8813     idxs = slang->sl_fidxs;
8814 
8815     arridx[0] = 0;
8816     curi[0] = 1;
8817     wordcount[0] = 0;
8818 
8819     depth = 0;
8820     while (depth >= 0 && !got_int)
8821     {
8822 	if (curi[depth] > byts[arridx[depth]])
8823 	{
8824 	    /* Done all bytes at this node, go up one level. */
8825 	    idxs[arridx[depth]] = wordcount[depth];
8826 	    if (depth > 0)
8827 		wordcount[depth - 1] += wordcount[depth];
8828 
8829 	    --depth;
8830 	    line_breakcheck();
8831 	}
8832 	else
8833 	{
8834 
8835 	    /* Do one more byte at this node. */
8836 	    n = arridx[depth] + curi[depth];
8837 	    ++curi[depth];
8838 
8839 	    c = byts[n];
8840 	    if (c == 0)
8841 	    {
8842 		/* Sound-fold the word. */
8843 		tword[depth] = NUL;
8844 		spell_soundfold(slang, tword, TRUE, tsalword);
8845 
8846 		/* We use the "flags" field for the MSB of the wordnr,
8847 		 * "region" for the LSB of the wordnr.  */
8848 		if (tree_add_word(spin, tsalword, spin->si_foldroot,
8849 				words_done >> 16, words_done & 0xffff,
8850 							   0) == FAIL)
8851 		    return FAIL;
8852 
8853 		++words_done;
8854 		++wordcount[depth];
8855 
8856 		/* Reset the block count each time to avoid compression
8857 		 * kicking in. */
8858 		spin->si_blocks_cnt = 0;
8859 
8860 		/* Skip over any other NUL bytes (same word with different
8861 		 * flags). */
8862 		while (byts[n + 1] == 0)
8863 		{
8864 		    ++n;
8865 		    ++curi[depth];
8866 		}
8867 	    }
8868 	    else
8869 	    {
8870 		/* Normal char, go one level deeper. */
8871 		tword[depth++] = c;
8872 		arridx[depth] = idxs[n];
8873 		curi[depth] = 1;
8874 		wordcount[depth] = 0;
8875 	    }
8876 	}
8877     }
8878 
8879     smsg((char_u *)_("Total number of words: %d"), words_done);
8880 
8881     return OK;
8882 }
8883 
8884 /*
8885  * Make the table that links each word in the soundfold trie to the words it
8886  * can be produced from.
8887  * This is not unlike lines in a file, thus use a memfile to be able to access
8888  * the table efficiently.
8889  * Returns FAIL when out of memory.
8890  */
8891     static int
8892 sug_maketable(spin)
8893     spellinfo_T	*spin;
8894 {
8895     garray_T	ga;
8896     int		res = OK;
8897 
8898     /* Allocate a buffer, open a memline for it and create the swap file
8899      * (uses a temp file, not a .swp file). */
8900     spin->si_spellbuf = open_spellbuf();
8901     if (spin->si_spellbuf == NULL)
8902 	return FAIL;
8903 
8904     /* Use a buffer to store the line info, avoids allocating many small
8905      * pieces of memory. */
8906     ga_init2(&ga, 1, 100);
8907 
8908     /* recursively go through the tree */
8909     if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1)
8910 	res = FAIL;
8911 
8912     ga_clear(&ga);
8913     return res;
8914 }
8915 
8916 /*
8917  * Fill the table for one node and its children.
8918  * Returns the wordnr at the start of the node.
8919  * Returns -1 when out of memory.
8920  */
8921     static int
8922 sug_filltable(spin, node, startwordnr, gap)
8923     spellinfo_T	*spin;
8924     wordnode_T	*node;
8925     int		startwordnr;
8926     garray_T	*gap;	    /* place to store line of numbers */
8927 {
8928     wordnode_T	*p, *np;
8929     int		wordnr = startwordnr;
8930     int		nr;
8931     int		prev_nr;
8932 
8933     for (p = node; p != NULL; p = p->wn_sibling)
8934     {
8935 	if (p->wn_byte == NUL)
8936 	{
8937 	    gap->ga_len = 0;
8938 	    prev_nr = 0;
8939 	    for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling)
8940 	    {
8941 		if (ga_grow(gap, 10) == FAIL)
8942 		    return -1;
8943 
8944 		nr = (np->wn_flags << 16) + (np->wn_region & 0xffff);
8945 		/* Compute the offset from the previous nr and store the
8946 		 * offset in a way that it takes a minimum number of bytes.
8947 		 * It's a bit like utf-8, but without the need to mark
8948 		 * following bytes. */
8949 		nr -= prev_nr;
8950 		prev_nr += nr;
8951 		gap->ga_len += offset2bytes(nr,
8952 					 (char_u *)gap->ga_data + gap->ga_len);
8953 	    }
8954 
8955 	    /* add the NUL byte */
8956 	    ((char_u *)gap->ga_data)[gap->ga_len++] = NUL;
8957 
8958 	    if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr,
8959 				     gap->ga_data, gap->ga_len, TRUE) == FAIL)
8960 		return -1;
8961 	    ++wordnr;
8962 
8963 	    /* Remove extra NUL entries, we no longer need them. We don't
8964 	     * bother freeing the nodes, the won't be reused anyway. */
8965 	    while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL)
8966 		p->wn_sibling = p->wn_sibling->wn_sibling;
8967 
8968 	    /* Clear the flags on the remaining NUL node, so that compression
8969 	     * works a lot better. */
8970 	    p->wn_flags = 0;
8971 	    p->wn_region = 0;
8972 	}
8973 	else
8974 	{
8975 	    wordnr = sug_filltable(spin, p->wn_child, wordnr, gap);
8976 	    if (wordnr == -1)
8977 		return -1;
8978 	}
8979     }
8980     return wordnr;
8981 }
8982 
8983 /*
8984  * Convert an offset into a minimal number of bytes.
8985  * Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL
8986  * bytes.
8987  */
8988     static int
8989 offset2bytes(nr, buf)
8990     int	    nr;
8991     char_u  *buf;
8992 {
8993     int	    rem;
8994     int	    b1, b2, b3, b4;
8995 
8996     /* Split the number in parts of base 255.  We need to avoid NUL bytes. */
8997     b1 = nr % 255 + 1;
8998     rem = nr / 255;
8999     b2 = rem % 255 + 1;
9000     rem = rem / 255;
9001     b3 = rem % 255 + 1;
9002     b4 = rem / 255 + 1;
9003 
9004     if (b4 > 1 || b3 > 0x1f)	/* 4 bytes */
9005     {
9006 	buf[0] = 0xe0 + b4;
9007 	buf[1] = b3;
9008 	buf[2] = b2;
9009 	buf[3] = b1;
9010 	return 4;
9011     }
9012     if (b3 > 1 || b2 > 0x3f )	/* 3 bytes */
9013     {
9014 	buf[0] = 0xc0 + b3;
9015 	buf[1] = b2;
9016 	buf[2] = b1;
9017 	return 3;
9018     }
9019     if (b2 > 1 || b1 > 0x7f )	/* 2 bytes */
9020     {
9021 	buf[0] = 0x80 + b2;
9022 	buf[1] = b1;
9023 	return 2;
9024     }
9025 				/* 1 byte */
9026     buf[0] = b1;
9027     return 1;
9028 }
9029 
9030 /*
9031  * Opposite of offset2bytes().
9032  * "pp" points to the bytes and is advanced over it.
9033  * Returns the offset.
9034  */
9035     static int
9036 bytes2offset(pp)
9037     char_u	**pp;
9038 {
9039     char_u	*p = *pp;
9040     int		nr;
9041     int		c;
9042 
9043     c = *p++;
9044     if ((c & 0x80) == 0x00)		/* 1 byte */
9045     {
9046 	nr = c - 1;
9047     }
9048     else if ((c & 0xc0) == 0x80)	/* 2 bytes */
9049     {
9050 	nr = (c & 0x3f) - 1;
9051 	nr = nr * 255 + (*p++ - 1);
9052     }
9053     else if ((c & 0xe0) == 0xc0)	/* 3 bytes */
9054     {
9055 	nr = (c & 0x1f) - 1;
9056 	nr = nr * 255 + (*p++ - 1);
9057 	nr = nr * 255 + (*p++ - 1);
9058     }
9059     else				/* 4 bytes */
9060     {
9061 	nr = (c & 0x0f) - 1;
9062 	nr = nr * 255 + (*p++ - 1);
9063 	nr = nr * 255 + (*p++ - 1);
9064 	nr = nr * 255 + (*p++ - 1);
9065     }
9066 
9067     *pp = p;
9068     return nr;
9069 }
9070 
9071 /*
9072  * Write the .sug file in "fname".
9073  */
9074     static void
9075 sug_write(spin, fname)
9076     spellinfo_T	*spin;
9077     char_u	*fname;
9078 {
9079     FILE	*fd;
9080     wordnode_T	*tree;
9081     int		nodecount;
9082     int		wcount;
9083     char_u	*line;
9084     linenr_T	lnum;
9085     int		len;
9086 
9087     /* Create the file.  Note that an existing file is silently overwritten! */
9088     fd = mch_fopen((char *)fname, "w");
9089     if (fd == NULL)
9090     {
9091 	EMSG2(_(e_notopen), fname);
9092 	return;
9093     }
9094 
9095     vim_snprintf((char *)IObuff, IOSIZE,
9096 				  _("Writing suggestion file %s ..."), fname);
9097     spell_message(spin, IObuff);
9098 
9099     /*
9100      * <SUGHEADER>: <fileID> <versionnr> <timestamp>
9101      */
9102     if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) /* <fileID> */
9103     {
9104 	EMSG(_(e_write));
9105 	goto theend;
9106     }
9107     putc(VIMSUGVERSION, fd);				/* <versionnr> */
9108 
9109     /* Write si_sugtime to the file. */
9110     put_sugtime(spin, fd);				/* <timestamp> */
9111 
9112     /*
9113      * <SUGWORDTREE>
9114      */
9115     spin->si_memtot = 0;
9116     tree = spin->si_foldroot->wn_sibling;
9117 
9118     /* Clear the index and wnode fields in the tree. */
9119     clear_node(tree);
9120 
9121     /* Count the number of nodes.  Needed to be able to allocate the
9122      * memory when reading the nodes.  Also fills in index for shared
9123      * nodes. */
9124     nodecount = put_node(NULL, tree, 0, 0, FALSE);
9125 
9126     /* number of nodes in 4 bytes */
9127     put_bytes(fd, (long_u)nodecount, 4);	/* <nodecount> */
9128     spin->si_memtot += nodecount + nodecount * sizeof(int);
9129 
9130     /* Write the nodes. */
9131     (void)put_node(fd, tree, 0, 0, FALSE);
9132 
9133     /*
9134      * <SUGTABLE>: <sugwcount> <sugline> ...
9135      */
9136     wcount = spin->si_spellbuf->b_ml.ml_line_count;
9137     put_bytes(fd, (long_u)wcount, 4);	/* <sugwcount> */
9138 
9139     for (lnum = 1; lnum <= (linenr_T)wcount; ++lnum)
9140     {
9141 	/* <sugline>: <sugnr> ... NUL */
9142 	line = ml_get_buf(spin->si_spellbuf, lnum, FALSE);
9143 	len = (int)STRLEN(line) + 1;
9144 	if (fwrite(line, (size_t)len, (size_t)1, fd) == 0)
9145 	{
9146 	    EMSG(_(e_write));
9147 	    goto theend;
9148 	}
9149 	spin->si_memtot += len;
9150     }
9151 
9152     /* Write another byte to check for errors. */
9153     if (putc(0, fd) == EOF)
9154 	EMSG(_(e_write));
9155 
9156     vim_snprintf((char *)IObuff, IOSIZE,
9157 		 _("Estimated runtime memory use: %d bytes"), spin->si_memtot);
9158     spell_message(spin, IObuff);
9159 
9160 theend:
9161     /* close the file */
9162     fclose(fd);
9163 }
9164 
9165 /*
9166  * Open a spell buffer.  This is a nameless buffer that is not in the buffer
9167  * list and only contains text lines.  Can use a swapfile to reduce memory
9168  * use.
9169  * Most other fields are invalid!  Esp. watch out for string options being
9170  * NULL and there is no undo info.
9171  * Returns NULL when out of memory.
9172  */
9173     static buf_T *
9174 open_spellbuf()
9175 {
9176     buf_T	*buf;
9177 
9178     buf = (buf_T *)alloc_clear(sizeof(buf_T));
9179     if (buf != NULL)
9180     {
9181 	buf->b_spell = TRUE;
9182 	buf->b_p_swf = TRUE;	/* may create a swap file */
9183 	ml_open(buf);
9184 	ml_open_file(buf);	/* create swap file now */
9185     }
9186     return buf;
9187 }
9188 
9189 /*
9190  * Close the buffer used for spell info.
9191  */
9192     static void
9193 close_spellbuf(buf)
9194     buf_T	*buf;
9195 {
9196     if (buf != NULL)
9197     {
9198 	ml_close(buf, TRUE);
9199 	vim_free(buf);
9200     }
9201 }
9202 
9203 
9204 /*
9205  * Create a Vim spell file from one or more word lists.
9206  * "fnames[0]" is the output file name.
9207  * "fnames[fcount - 1]" is the last input file name.
9208  * Exception: when "fnames[0]" ends in ".add" it's used as the input file name
9209  * and ".spl" is appended to make the output file name.
9210  */
9211     static void
9212 mkspell(fcount, fnames, ascii, overwrite, added_word)
9213     int		fcount;
9214     char_u	**fnames;
9215     int		ascii;		    /* -ascii argument given */
9216     int		overwrite;	    /* overwrite existing output file */
9217     int		added_word;	    /* invoked through "zg" */
9218 {
9219     char_u	fname[MAXPATHL];
9220     char_u	wfname[MAXPATHL];
9221     char_u	**innames;
9222     int		incount;
9223     afffile_T	*(afile[8]);
9224     int		i;
9225     int		len;
9226     struct stat	st;
9227     int		error = FALSE;
9228     spellinfo_T spin;
9229 
9230     vim_memset(&spin, 0, sizeof(spin));
9231     spin.si_verbose = !added_word;
9232     spin.si_ascii = ascii;
9233     spin.si_followup = TRUE;
9234     spin.si_rem_accents = TRUE;
9235     ga_init2(&spin.si_rep, (int)sizeof(fromto_T), 20);
9236     ga_init2(&spin.si_repsal, (int)sizeof(fromto_T), 20);
9237     ga_init2(&spin.si_sal, (int)sizeof(fromto_T), 20);
9238     ga_init2(&spin.si_map, (int)sizeof(char_u), 100);
9239     ga_init2(&spin.si_comppat, (int)sizeof(char_u *), 20);
9240     ga_init2(&spin.si_prefcond, (int)sizeof(char_u *), 50);
9241     hash_init(&spin.si_commonwords);
9242     spin.si_newcompID = 127;	/* start compound ID at first maximum */
9243 
9244     /* default: fnames[0] is output file, following are input files */
9245     innames = &fnames[1];
9246     incount = fcount - 1;
9247 
9248     if (fcount >= 1)
9249     {
9250 	len = (int)STRLEN(fnames[0]);
9251 	if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0)
9252 	{
9253 	    /* For ":mkspell path/en.latin1.add" output file is
9254 	     * "path/en.latin1.add.spl". */
9255 	    innames = &fnames[0];
9256 	    incount = 1;
9257 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.spl", fnames[0]);
9258 	}
9259 	else if (fcount == 1)
9260 	{
9261 	    /* For ":mkspell path/vim" output file is "path/vim.latin1.spl". */
9262 	    innames = &fnames[0];
9263 	    incount = 1;
9264 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0],
9265 			     spin.si_ascii ? (char_u *)"ascii" : spell_enc());
9266 	}
9267 	else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0)
9268 	{
9269 	    /* Name ends in ".spl", use as the file name. */
9270 	    vim_strncpy(wfname, fnames[0], sizeof(wfname) - 1);
9271 	}
9272 	else
9273 	    /* Name should be language, make the file name from it. */
9274 	    vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0],
9275 			     spin.si_ascii ? (char_u *)"ascii" : spell_enc());
9276 
9277 	/* Check for .ascii.spl. */
9278 	if (strstr((char *)gettail(wfname), ".ascii.") != NULL)
9279 	    spin.si_ascii = TRUE;
9280 
9281 	/* Check for .add.spl. */
9282 	if (strstr((char *)gettail(wfname), ".add.") != NULL)
9283 	    spin.si_add = TRUE;
9284     }
9285 
9286     if (incount <= 0)
9287 	EMSG(_(e_invarg));	/* need at least output and input names */
9288     else if (vim_strchr(gettail(wfname), '_') != NULL)
9289 	EMSG(_("E751: Output file name must not have region name"));
9290     else if (incount > 8)
9291 	EMSG(_("E754: Only up to 8 regions supported"));
9292     else
9293     {
9294 	/* Check for overwriting before doing things that may take a lot of
9295 	 * time. */
9296 	if (!overwrite && mch_stat((char *)wfname, &st) >= 0)
9297 	{
9298 	    EMSG(_(e_exists));
9299 	    return;
9300 	}
9301 	if (mch_isdir(wfname))
9302 	{
9303 	    EMSG2(_(e_isadir2), wfname);
9304 	    return;
9305 	}
9306 
9307 	/*
9308 	 * Init the aff and dic pointers.
9309 	 * Get the region names if there are more than 2 arguments.
9310 	 */
9311 	for (i = 0; i < incount; ++i)
9312 	{
9313 	    afile[i] = NULL;
9314 
9315 	    if (incount > 1)
9316 	    {
9317 		len = (int)STRLEN(innames[i]);
9318 		if (STRLEN(gettail(innames[i])) < 5
9319 						|| innames[i][len - 3] != '_')
9320 		{
9321 		    EMSG2(_("E755: Invalid region in %s"), innames[i]);
9322 		    return;
9323 		}
9324 		spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]);
9325 		spin.si_region_name[i * 2 + 1] =
9326 					     TOLOWER_ASC(innames[i][len - 1]);
9327 	    }
9328 	}
9329 	spin.si_region_count = incount;
9330 
9331 	spin.si_foldroot = wordtree_alloc(&spin);
9332 	spin.si_keeproot = wordtree_alloc(&spin);
9333 	spin.si_prefroot = wordtree_alloc(&spin);
9334 	if (spin.si_foldroot == NULL
9335 		|| spin.si_keeproot == NULL
9336 		|| spin.si_prefroot == NULL)
9337 	{
9338 	    free_blocks(spin.si_blocks);
9339 	    return;
9340 	}
9341 
9342 	/* When not producing a .add.spl file clear the character table when
9343 	 * we encounter one in the .aff file.  This means we dump the current
9344 	 * one in the .spl file if the .aff file doesn't define one.  That's
9345 	 * better than guessing the contents, the table will match a
9346 	 * previously loaded spell file. */
9347 	if (!spin.si_add)
9348 	    spin.si_clear_chartab = TRUE;
9349 
9350 	/*
9351 	 * Read all the .aff and .dic files.
9352 	 * Text is converted to 'encoding'.
9353 	 * Words are stored in the case-folded and keep-case trees.
9354 	 */
9355 	for (i = 0; i < incount && !error; ++i)
9356 	{
9357 	    spin.si_conv.vc_type = CONV_NONE;
9358 	    spin.si_region = 1 << i;
9359 
9360 	    vim_snprintf((char *)fname, sizeof(fname), "%s.aff", innames[i]);
9361 	    if (mch_stat((char *)fname, &st) >= 0)
9362 	    {
9363 		/* Read the .aff file.  Will init "spin->si_conv" based on the
9364 		 * "SET" line. */
9365 		afile[i] = spell_read_aff(&spin, fname);
9366 		if (afile[i] == NULL)
9367 		    error = TRUE;
9368 		else
9369 		{
9370 		    /* Read the .dic file and store the words in the trees. */
9371 		    vim_snprintf((char *)fname, sizeof(fname), "%s.dic",
9372 								  innames[i]);
9373 		    if (spell_read_dic(&spin, fname, afile[i]) == FAIL)
9374 			error = TRUE;
9375 		}
9376 	    }
9377 	    else
9378 	    {
9379 		/* No .aff file, try reading the file as a word list.  Store
9380 		 * the words in the trees. */
9381 		if (spell_read_wordfile(&spin, innames[i]) == FAIL)
9382 		    error = TRUE;
9383 	    }
9384 
9385 #ifdef FEAT_MBYTE
9386 	    /* Free any conversion stuff. */
9387 	    convert_setup(&spin.si_conv, NULL, NULL);
9388 #endif
9389 	}
9390 
9391 	if (spin.si_compflags != NULL && spin.si_nobreak)
9392 	    MSG(_("Warning: both compounding and NOBREAK specified"));
9393 
9394 	if (!error && !got_int)
9395 	{
9396 	    /*
9397 	     * Combine tails in the tree.
9398 	     */
9399 	    spell_message(&spin, (char_u *)_(msg_compressing));
9400 	    wordtree_compress(&spin, spin.si_foldroot);
9401 	    wordtree_compress(&spin, spin.si_keeproot);
9402 	    wordtree_compress(&spin, spin.si_prefroot);
9403 	}
9404 
9405 	if (!error && !got_int)
9406 	{
9407 	    /*
9408 	     * Write the info in the spell file.
9409 	     */
9410 	    vim_snprintf((char *)IObuff, IOSIZE,
9411 				      _("Writing spell file %s ..."), wfname);
9412 	    spell_message(&spin, IObuff);
9413 
9414 	    error = write_vim_spell(&spin, wfname) == FAIL;
9415 
9416 	    spell_message(&spin, (char_u *)_("Done!"));
9417 	    vim_snprintf((char *)IObuff, IOSIZE,
9418 		 _("Estimated runtime memory use: %d bytes"), spin.si_memtot);
9419 	    spell_message(&spin, IObuff);
9420 
9421 	    /*
9422 	     * If the file is loaded need to reload it.
9423 	     */
9424 	    if (!error)
9425 		spell_reload_one(wfname, added_word);
9426 	}
9427 
9428 	/* Free the allocated memory. */
9429 	ga_clear(&spin.si_rep);
9430 	ga_clear(&spin.si_repsal);
9431 	ga_clear(&spin.si_sal);
9432 	ga_clear(&spin.si_map);
9433 	ga_clear(&spin.si_comppat);
9434 	ga_clear(&spin.si_prefcond);
9435 	hash_clear_all(&spin.si_commonwords, 0);
9436 
9437 	/* Free the .aff file structures. */
9438 	for (i = 0; i < incount; ++i)
9439 	    if (afile[i] != NULL)
9440 		spell_free_aff(afile[i]);
9441 
9442 	/* Free all the bits and pieces at once. */
9443 	free_blocks(spin.si_blocks);
9444 
9445 	/*
9446 	 * If there is soundfolding info and no NOSUGFILE item create the
9447 	 * .sug file with the soundfolded word trie.
9448 	 */
9449 	if (spin.si_sugtime != 0 && !error && !got_int)
9450 	    spell_make_sugfile(&spin, wfname);
9451 
9452     }
9453 }
9454 
9455 /*
9456  * Display a message for spell file processing when 'verbose' is set or using
9457  * ":mkspell".  "str" can be IObuff.
9458  */
9459     static void
9460 spell_message(spin, str)
9461     spellinfo_T *spin;
9462     char_u	*str;
9463 {
9464     if (spin->si_verbose || p_verbose > 2)
9465     {
9466 	if (!spin->si_verbose)
9467 	    verbose_enter();
9468 	MSG(str);
9469 	out_flush();
9470 	if (!spin->si_verbose)
9471 	    verbose_leave();
9472     }
9473 }
9474 
9475 /*
9476  * ":[count]spellgood  {word}"
9477  * ":[count]spellwrong  {word}"
9478  * ":[count]spellundo  {word}"
9479  */
9480     void
9481 ex_spell(eap)
9482     exarg_T *eap;
9483 {
9484     spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
9485 				   eap->forceit ? 0 : (int)eap->line2,
9486 				   eap->cmdidx == CMD_spellundo);
9487 }
9488 
9489 /*
9490  * Add "word[len]" to 'spellfile' as a good or bad word.
9491  */
9492     void
9493 spell_add_word(word, len, bad, idx, undo)
9494     char_u	*word;
9495     int		len;
9496     int		bad;
9497     int		idx;	    /* "zG" and "zW": zero, otherwise index in
9498 			       'spellfile' */
9499     int		undo;	    /* TRUE for "zug", "zuG", "zuw" and "zuW" */
9500 {
9501     FILE	*fd = NULL;
9502     buf_T	*buf = NULL;
9503     int		new_spf = FALSE;
9504     char_u	*fname;
9505     char_u	fnamebuf[MAXPATHL];
9506     char_u	line[MAXWLEN * 2];
9507     long	fpos, fpos_next = 0;
9508     int		i;
9509     char_u	*spf;
9510 
9511     if (idx == 0)	    /* use internal wordlist */
9512     {
9513 	if (int_wordlist == NULL)
9514 	{
9515 	    int_wordlist = vim_tempname('s');
9516 	    if (int_wordlist == NULL)
9517 		return;
9518 	}
9519 	fname = int_wordlist;
9520     }
9521     else
9522     {
9523 	/* If 'spellfile' isn't set figure out a good default value. */
9524 	if (*curbuf->b_p_spf == NUL)
9525 	{
9526 	    init_spellfile();
9527 	    new_spf = TRUE;
9528 	}
9529 
9530 	if (*curbuf->b_p_spf == NUL)
9531 	{
9532 	    EMSG2(_(e_notset), "spellfile");
9533 	    return;
9534 	}
9535 
9536 	for (spf = curbuf->b_p_spf, i = 1; *spf != NUL; ++i)
9537 	{
9538 	    copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
9539 	    if (i == idx)
9540 		break;
9541 	    if (*spf == NUL)
9542 	    {
9543 		EMSGN(_("E765: 'spellfile' does not have %ld entries"), idx);
9544 		return;
9545 	    }
9546 	}
9547 
9548 	/* Check that the user isn't editing the .add file somewhere. */
9549 	buf = buflist_findname_exp(fnamebuf);
9550 	if (buf != NULL && buf->b_ml.ml_mfp == NULL)
9551 	    buf = NULL;
9552 	if (buf != NULL && bufIsChanged(buf))
9553 	{
9554 	    EMSG(_(e_bufloaded));
9555 	    return;
9556 	}
9557 
9558 	fname = fnamebuf;
9559     }
9560 
9561     if (bad || undo)
9562     {
9563 	/* When the word appears as good word we need to remove that one,
9564 	 * since its flags sort before the one with WF_BANNED. */
9565 	fd = mch_fopen((char *)fname, "r");
9566 	if (fd != NULL)
9567 	{
9568 	    while (!vim_fgets(line, MAXWLEN * 2, fd))
9569 	    {
9570 		fpos = fpos_next;
9571 		fpos_next = ftell(fd);
9572 		if (STRNCMP(word, line, len) == 0
9573 			&& (line[len] == '/' || line[len] < ' '))
9574 		{
9575 		    /* Found duplicate word.  Remove it by writing a '#' at
9576 		     * the start of the line.  Mixing reading and writing
9577 		     * doesn't work for all systems, close the file first. */
9578 		    fclose(fd);
9579 		    fd = mch_fopen((char *)fname, "r+");
9580 		    if (fd == NULL)
9581 			break;
9582 		    if (fseek(fd, fpos, SEEK_SET) == 0)
9583 		    {
9584 			fputc('#', fd);
9585 			if (undo)
9586 			{
9587 			    home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE);
9588 			    smsg((char_u *)_("Word removed from %s"), NameBuff);
9589 			}
9590 		    }
9591 		    fseek(fd, fpos_next, SEEK_SET);
9592 		}
9593 	    }
9594 	    fclose(fd);
9595 	}
9596     }
9597 
9598     if (!undo)
9599     {
9600 	fd = mch_fopen((char *)fname, "a");
9601 	if (fd == NULL && new_spf)
9602 	{
9603 	    char_u *p;
9604 
9605 	    /* We just initialized the 'spellfile' option and can't open the
9606 	     * file.  We may need to create the "spell" directory first.  We
9607 	     * already checked the runtime directory is writable in
9608 	     * init_spellfile(). */
9609 	    if (!dir_of_file_exists(fname) && (p = gettail_sep(fname)) != fname)
9610 	    {
9611 		int c = *p;
9612 
9613 		/* The directory doesn't exist.  Try creating it and opening
9614 		 * the file again. */
9615 		*p = NUL;
9616 		vim_mkdir(fname, 0755);
9617 		*p = c;
9618 		fd = mch_fopen((char *)fname, "a");
9619 	    }
9620 	}
9621 
9622 	if (fd == NULL)
9623 	    EMSG2(_(e_notopen), fname);
9624 	else
9625 	{
9626 	    if (bad)
9627 		fprintf(fd, "%.*s/!\n", len, word);
9628 	    else
9629 		fprintf(fd, "%.*s\n", len, word);
9630 	    fclose(fd);
9631 
9632 	    home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE);
9633 	    smsg((char_u *)_("Word added to %s"), NameBuff);
9634 	}
9635     }
9636 
9637     if (fd != NULL)
9638     {
9639 	/* Update the .add.spl file. */
9640 	mkspell(1, &fname, FALSE, TRUE, TRUE);
9641 
9642 	/* If the .add file is edited somewhere, reload it. */
9643 	if (buf != NULL)
9644 	    buf_reload(buf, buf->b_orig_mode);
9645 
9646 	redraw_all_later(SOME_VALID);
9647     }
9648 }
9649 
9650 /*
9651  * Initialize 'spellfile' for the current buffer.
9652  */
9653     static void
9654 init_spellfile()
9655 {
9656     char_u	buf[MAXPATHL];
9657     int		l;
9658     char_u	*fname;
9659     char_u	*rtp;
9660     char_u	*lend;
9661     int		aspath = FALSE;
9662     char_u	*lstart = curbuf->b_p_spl;
9663 
9664     if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0)
9665     {
9666 	/* Find the end of the language name.  Exclude the region.  If there
9667 	 * is a path separator remember the start of the tail. */
9668 	for (lend = curbuf->b_p_spl; *lend != NUL
9669 			&& vim_strchr((char_u *)",._", *lend) == NULL; ++lend)
9670 	    if (vim_ispathsep(*lend))
9671 	    {
9672 		aspath = TRUE;
9673 		lstart = lend + 1;
9674 	    }
9675 
9676 	/* Loop over all entries in 'runtimepath'.  Use the first one where we
9677 	 * are allowed to write. */
9678 	rtp = p_rtp;
9679 	while (*rtp != NUL)
9680 	{
9681 	    if (aspath)
9682 		/* Use directory of an entry with path, e.g., for
9683 		 * "/dir/lg.utf-8.spl" use "/dir". */
9684 		vim_strncpy(buf, curbuf->b_p_spl, lstart - curbuf->b_p_spl - 1);
9685 	    else
9686 		/* Copy the path from 'runtimepath' to buf[]. */
9687 		copy_option_part(&rtp, buf, MAXPATHL, ",");
9688 	    if (filewritable(buf) == 2)
9689 	    {
9690 		/* Use the first language name from 'spelllang' and the
9691 		 * encoding used in the first loaded .spl file. */
9692 		if (aspath)
9693 		    vim_strncpy(buf, curbuf->b_p_spl, lend - curbuf->b_p_spl);
9694 		else
9695 		{
9696 		    /* Create the "spell" directory if it doesn't exist yet. */
9697 		    l = (int)STRLEN(buf);
9698 		    vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell");
9699 		    if (!filewritable(buf) != 2)
9700 			vim_mkdir(buf, 0755);
9701 
9702 		    l = (int)STRLEN(buf);
9703 		    vim_snprintf((char *)buf + l, MAXPATHL - l,
9704 				 "/%.*s", (int)(lend - lstart), lstart);
9705 		}
9706 		l = (int)STRLEN(buf);
9707 		fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname;
9708 		vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
9709 			fname != NULL
9710 			  && strstr((char *)gettail(fname), ".ascii.") != NULL
9711 				       ? (char_u *)"ascii" : spell_enc());
9712 		set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
9713 		break;
9714 	    }
9715 	    aspath = FALSE;
9716 	}
9717     }
9718 }
9719 
9720 
9721 /*
9722  * Init the chartab used for spelling for ASCII.
9723  * EBCDIC is not supported!
9724  */
9725     static void
9726 clear_spell_chartab(sp)
9727     spelltab_T	*sp;
9728 {
9729     int		i;
9730 
9731     /* Init everything to FALSE. */
9732     vim_memset(sp->st_isw, FALSE, sizeof(sp->st_isw));
9733     vim_memset(sp->st_isu, FALSE, sizeof(sp->st_isu));
9734     for (i = 0; i < 256; ++i)
9735     {
9736 	sp->st_fold[i] = i;
9737 	sp->st_upper[i] = i;
9738     }
9739 
9740     /* We include digits.  A word shouldn't start with a digit, but handling
9741      * that is done separately. */
9742     for (i = '0'; i <= '9'; ++i)
9743 	sp->st_isw[i] = TRUE;
9744     for (i = 'A'; i <= 'Z'; ++i)
9745     {
9746 	sp->st_isw[i] = TRUE;
9747 	sp->st_isu[i] = TRUE;
9748 	sp->st_fold[i] = i + 0x20;
9749     }
9750     for (i = 'a'; i <= 'z'; ++i)
9751     {
9752 	sp->st_isw[i] = TRUE;
9753 	sp->st_upper[i] = i - 0x20;
9754     }
9755 }
9756 
9757 /*
9758  * Init the chartab used for spelling.  Only depends on 'encoding'.
9759  * Called once while starting up and when 'encoding' changes.
9760  * The default is to use isalpha(), but the spell file should define the word
9761  * characters to make it possible that 'encoding' differs from the current
9762  * locale.  For utf-8 we don't use isalpha() but our own functions.
9763  */
9764     void
9765 init_spell_chartab()
9766 {
9767     int	    i;
9768 
9769     did_set_spelltab = FALSE;
9770     clear_spell_chartab(&spelltab);
9771 #ifdef FEAT_MBYTE
9772     if (enc_dbcs)
9773     {
9774 	/* DBCS: assume double-wide characters are word characters. */
9775 	for (i = 128; i <= 255; ++i)
9776 	    if (MB_BYTE2LEN(i) == 2)
9777 		spelltab.st_isw[i] = TRUE;
9778     }
9779     else if (enc_utf8)
9780     {
9781 	for (i = 128; i < 256; ++i)
9782 	{
9783 	    int f = utf_fold(i);
9784 	    int u = utf_toupper(i);
9785 
9786 	    spelltab.st_isu[i] = utf_isupper(i);
9787 	    spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i);
9788 	    /* The folded/upper-cased value is different between latin1 and
9789 	     * utf8 for 0xb5, causing E763 for no good reason.  Use the latin1
9790 	     * value for utf-8 to avoid this. */
9791 	    spelltab.st_fold[i] = (f < 256) ? f : i;
9792 	    spelltab.st_upper[i] = (u < 256) ? u : i;
9793 	}
9794     }
9795     else
9796 #endif
9797     {
9798 	/* Rough guess: use locale-dependent library functions. */
9799 	for (i = 128; i < 256; ++i)
9800 	{
9801 	    if (MB_ISUPPER(i))
9802 	    {
9803 		spelltab.st_isw[i] = TRUE;
9804 		spelltab.st_isu[i] = TRUE;
9805 		spelltab.st_fold[i] = MB_TOLOWER(i);
9806 	    }
9807 	    else if (MB_ISLOWER(i))
9808 	    {
9809 		spelltab.st_isw[i] = TRUE;
9810 		spelltab.st_upper[i] = MB_TOUPPER(i);
9811 	    }
9812 	}
9813     }
9814 }
9815 
9816 /*
9817  * Set the spell character tables from strings in the affix file.
9818  */
9819     static int
9820 set_spell_chartab(fol, low, upp)
9821     char_u	*fol;
9822     char_u	*low;
9823     char_u	*upp;
9824 {
9825     /* We build the new tables here first, so that we can compare with the
9826      * previous one. */
9827     spelltab_T	new_st;
9828     char_u	*pf = fol, *pl = low, *pu = upp;
9829     int		f, l, u;
9830 
9831     clear_spell_chartab(&new_st);
9832 
9833     while (*pf != NUL)
9834     {
9835 	if (*pl == NUL || *pu == NUL)
9836 	{
9837 	    EMSG(_(e_affform));
9838 	    return FAIL;
9839 	}
9840 #ifdef FEAT_MBYTE
9841 	f = mb_ptr2char_adv(&pf);
9842 	l = mb_ptr2char_adv(&pl);
9843 	u = mb_ptr2char_adv(&pu);
9844 #else
9845 	f = *pf++;
9846 	l = *pl++;
9847 	u = *pu++;
9848 #endif
9849 	/* Every character that appears is a word character. */
9850 	if (f < 256)
9851 	    new_st.st_isw[f] = TRUE;
9852 	if (l < 256)
9853 	    new_st.st_isw[l] = TRUE;
9854 	if (u < 256)
9855 	    new_st.st_isw[u] = TRUE;
9856 
9857 	/* if "LOW" and "FOL" are not the same the "LOW" char needs
9858 	 * case-folding */
9859 	if (l < 256 && l != f)
9860 	{
9861 	    if (f >= 256)
9862 	    {
9863 		EMSG(_(e_affrange));
9864 		return FAIL;
9865 	    }
9866 	    new_st.st_fold[l] = f;
9867 	}
9868 
9869 	/* if "UPP" and "FOL" are not the same the "UPP" char needs
9870 	 * case-folding, it's upper case and the "UPP" is the upper case of
9871 	 * "FOL" . */
9872 	if (u < 256 && u != f)
9873 	{
9874 	    if (f >= 256)
9875 	    {
9876 		EMSG(_(e_affrange));
9877 		return FAIL;
9878 	    }
9879 	    new_st.st_fold[u] = f;
9880 	    new_st.st_isu[u] = TRUE;
9881 	    new_st.st_upper[f] = u;
9882 	}
9883     }
9884 
9885     if (*pl != NUL || *pu != NUL)
9886     {
9887 	EMSG(_(e_affform));
9888 	return FAIL;
9889     }
9890 
9891     return set_spell_finish(&new_st);
9892 }
9893 
9894 /*
9895  * Set the spell character tables from strings in the .spl file.
9896  */
9897     static void
9898 set_spell_charflags(flags, cnt, fol)
9899     char_u	*flags;
9900     int		cnt;	    /* length of "flags" */
9901     char_u	*fol;
9902 {
9903     /* We build the new tables here first, so that we can compare with the
9904      * previous one. */
9905     spelltab_T	new_st;
9906     int		i;
9907     char_u	*p = fol;
9908     int		c;
9909 
9910     clear_spell_chartab(&new_st);
9911 
9912     for (i = 0; i < 128; ++i)
9913     {
9914 	if (i < cnt)
9915 	{
9916 	    new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0;
9917 	    new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0;
9918 	}
9919 
9920 	if (*p != NUL)
9921 	{
9922 #ifdef FEAT_MBYTE
9923 	    c = mb_ptr2char_adv(&p);
9924 #else
9925 	    c = *p++;
9926 #endif
9927 	    new_st.st_fold[i + 128] = c;
9928 	    if (i + 128 != c && new_st.st_isu[i + 128] && c < 256)
9929 		new_st.st_upper[c] = i + 128;
9930 	}
9931     }
9932 
9933     (void)set_spell_finish(&new_st);
9934 }
9935 
9936     static int
9937 set_spell_finish(new_st)
9938     spelltab_T	*new_st;
9939 {
9940     int		i;
9941 
9942     if (did_set_spelltab)
9943     {
9944 	/* check that it's the same table */
9945 	for (i = 0; i < 256; ++i)
9946 	{
9947 	    if (spelltab.st_isw[i] != new_st->st_isw[i]
9948 		    || spelltab.st_isu[i] != new_st->st_isu[i]
9949 		    || spelltab.st_fold[i] != new_st->st_fold[i]
9950 		    || spelltab.st_upper[i] != new_st->st_upper[i])
9951 	    {
9952 		EMSG(_("E763: Word characters differ between spell files"));
9953 		return FAIL;
9954 	    }
9955 	}
9956     }
9957     else
9958     {
9959 	/* copy the new spelltab into the one being used */
9960 	spelltab = *new_st;
9961 	did_set_spelltab = TRUE;
9962     }
9963 
9964     return OK;
9965 }
9966 
9967 /*
9968  * Return TRUE if "p" points to a word character.
9969  * As a special case we see "midword" characters as word character when it is
9970  * followed by a word character.  This finds they'there but not 'they there'.
9971  * Thus this only works properly when past the first character of the word.
9972  */
9973     static int
9974 spell_iswordp(p, buf)
9975     char_u	*p;
9976     buf_T	*buf;	    /* buffer used */
9977 {
9978 #ifdef FEAT_MBYTE
9979     char_u	*s;
9980     int		l;
9981     int		c;
9982 
9983     if (has_mbyte)
9984     {
9985 	l = MB_BYTE2LEN(*p);
9986 	s = p;
9987 	if (l == 1)
9988 	{
9989 	    /* be quick for ASCII */
9990 	    if (buf->b_spell_ismw[*p])
9991 	    {
9992 		s = p + 1;		/* skip a mid-word character */
9993 		l = MB_BYTE2LEN(*s);
9994 	    }
9995 	}
9996 	else
9997 	{
9998 	    c = mb_ptr2char(p);
9999 	    if (c < 256 ? buf->b_spell_ismw[c]
10000 		    : (buf->b_spell_ismw_mb != NULL
10001 			   && vim_strchr(buf->b_spell_ismw_mb, c) != NULL))
10002 	    {
10003 		s = p + l;
10004 		l = MB_BYTE2LEN(*s);
10005 	    }
10006 	}
10007 
10008 	c = mb_ptr2char(s);
10009 	if (c > 255)
10010 	    return spell_mb_isword_class(mb_get_class(s));
10011 	return spelltab.st_isw[c];
10012     }
10013 #endif
10014 
10015     return spelltab.st_isw[buf->b_spell_ismw[*p] ? p[1] : p[0]];
10016 }
10017 
10018 /*
10019  * Return TRUE if "p" points to a word character.
10020  * Unlike spell_iswordp() this doesn't check for "midword" characters.
10021  */
10022     static int
10023 spell_iswordp_nmw(p)
10024     char_u	*p;
10025 {
10026 #ifdef FEAT_MBYTE
10027     int		c;
10028 
10029     if (has_mbyte)
10030     {
10031 	c = mb_ptr2char(p);
10032 	if (c > 255)
10033 	    return spell_mb_isword_class(mb_get_class(p));
10034 	return spelltab.st_isw[c];
10035     }
10036 #endif
10037     return spelltab.st_isw[*p];
10038 }
10039 
10040 #ifdef FEAT_MBYTE
10041 /*
10042  * Return TRUE if word class indicates a word character.
10043  * Only for characters above 255.
10044  * Unicode subscript and superscript are not considered word characters.
10045  */
10046     static int
10047 spell_mb_isword_class(cl)
10048     int cl;
10049 {
10050     return cl >= 2 && cl != 0x2070 && cl != 0x2080;
10051 }
10052 
10053 /*
10054  * Return TRUE if "p" points to a word character.
10055  * Wide version of spell_iswordp().
10056  */
10057     static int
10058 spell_iswordp_w(p, buf)
10059     int		*p;
10060     buf_T	*buf;
10061 {
10062     int		*s;
10063 
10064     if (*p < 256 ? buf->b_spell_ismw[*p]
10065 		 : (buf->b_spell_ismw_mb != NULL
10066 			     && vim_strchr(buf->b_spell_ismw_mb, *p) != NULL))
10067 	s = p + 1;
10068     else
10069 	s = p;
10070 
10071     if (*s > 255)
10072     {
10073 	if (enc_utf8)
10074 	    return spell_mb_isword_class(utf_class(*s));
10075 	if (enc_dbcs)
10076 	    return dbcs_class((unsigned)*s >> 8, *s & 0xff) >= 2;
10077 	return 0;
10078     }
10079     return spelltab.st_isw[*s];
10080 }
10081 #endif
10082 
10083 /*
10084  * Write the table with prefix conditions to the .spl file.
10085  * When "fd" is NULL only count the length of what is written.
10086  */
10087     static int
10088 write_spell_prefcond(fd, gap)
10089     FILE	*fd;
10090     garray_T	*gap;
10091 {
10092     int		i;
10093     char_u	*p;
10094     int		len;
10095     int		totlen;
10096     size_t	x = 1;  /* collect return value of fwrite() */
10097 
10098     if (fd != NULL)
10099 	put_bytes(fd, (long_u)gap->ga_len, 2);	    /* <prefcondcnt> */
10100 
10101     totlen = 2 + gap->ga_len; /* length of <prefcondcnt> and <condlen> bytes */
10102 
10103     for (i = 0; i < gap->ga_len; ++i)
10104     {
10105 	/* <prefcond> : <condlen> <condstr> */
10106 	p = ((char_u **)gap->ga_data)[i];
10107 	if (p != NULL)
10108 	{
10109 	    len = (int)STRLEN(p);
10110 	    if (fd != NULL)
10111 	    {
10112 		fputc(len, fd);
10113 		x &= fwrite(p, (size_t)len, (size_t)1, fd);
10114 	    }
10115 	    totlen += len;
10116 	}
10117 	else if (fd != NULL)
10118 	    fputc(0, fd);
10119     }
10120 
10121     return totlen;
10122 }
10123 
10124 /*
10125  * Case-fold "str[len]" into "buf[buflen]".  The result is NUL terminated.
10126  * Uses the character definitions from the .spl file.
10127  * When using a multi-byte 'encoding' the length may change!
10128  * Returns FAIL when something wrong.
10129  */
10130     static int
10131 spell_casefold(str, len, buf, buflen)
10132     char_u	*str;
10133     int		len;
10134     char_u	*buf;
10135     int		buflen;
10136 {
10137     int		i;
10138 
10139     if (len >= buflen)
10140     {
10141 	buf[0] = NUL;
10142 	return FAIL;		/* result will not fit */
10143     }
10144 
10145 #ifdef FEAT_MBYTE
10146     if (has_mbyte)
10147     {
10148 	int	outi = 0;
10149 	char_u	*p;
10150 	int	c;
10151 
10152 	/* Fold one character at a time. */
10153 	for (p = str; p < str + len; )
10154 	{
10155 	    if (outi + MB_MAXBYTES > buflen)
10156 	    {
10157 		buf[outi] = NUL;
10158 		return FAIL;
10159 	    }
10160 	    c = mb_cptr2char_adv(&p);
10161 	    outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
10162 	}
10163 	buf[outi] = NUL;
10164     }
10165     else
10166 #endif
10167     {
10168 	/* Be quick for non-multibyte encodings. */
10169 	for (i = 0; i < len; ++i)
10170 	    buf[i] = spelltab.st_fold[str[i]];
10171 	buf[i] = NUL;
10172     }
10173 
10174     return OK;
10175 }
10176 
10177 /* values for sps_flags */
10178 #define SPS_BEST    1
10179 #define SPS_FAST    2
10180 #define SPS_DOUBLE  4
10181 
10182 static int sps_flags = SPS_BEST;	/* flags from 'spellsuggest' */
10183 static int sps_limit = 9999;		/* max nr of suggestions given */
10184 
10185 /*
10186  * Check the 'spellsuggest' option.  Return FAIL if it's wrong.
10187  * Sets "sps_flags" and "sps_limit".
10188  */
10189     int
10190 spell_check_sps()
10191 {
10192     char_u	*p;
10193     char_u	*s;
10194     char_u	buf[MAXPATHL];
10195     int		f;
10196 
10197     sps_flags = 0;
10198     sps_limit = 9999;
10199 
10200     for (p = p_sps; *p != NUL; )
10201     {
10202 	copy_option_part(&p, buf, MAXPATHL, ",");
10203 
10204 	f = 0;
10205 	if (VIM_ISDIGIT(*buf))
10206 	{
10207 	    s = buf;
10208 	    sps_limit = getdigits(&s);
10209 	    if (*s != NUL && !VIM_ISDIGIT(*s))
10210 		f = -1;
10211 	}
10212 	else if (STRCMP(buf, "best") == 0)
10213 	    f = SPS_BEST;
10214 	else if (STRCMP(buf, "fast") == 0)
10215 	    f = SPS_FAST;
10216 	else if (STRCMP(buf, "double") == 0)
10217 	    f = SPS_DOUBLE;
10218 	else if (STRNCMP(buf, "expr:", 5) != 0
10219 		&& STRNCMP(buf, "file:", 5) != 0)
10220 	    f = -1;
10221 
10222 	if (f == -1 || (sps_flags != 0 && f != 0))
10223 	{
10224 	    sps_flags = SPS_BEST;
10225 	    sps_limit = 9999;
10226 	    return FAIL;
10227 	}
10228 	if (f != 0)
10229 	    sps_flags = f;
10230     }
10231 
10232     if (sps_flags == 0)
10233 	sps_flags = SPS_BEST;
10234 
10235     return OK;
10236 }
10237 
10238 /*
10239  * "z?": Find badly spelled word under or after the cursor.
10240  * Give suggestions for the properly spelled word.
10241  * In Visual mode use the highlighted word as the bad word.
10242  * When "count" is non-zero use that suggestion.
10243  */
10244     void
10245 spell_suggest(count)
10246     int		count;
10247 {
10248     char_u	*line;
10249     pos_T	prev_cursor = curwin->w_cursor;
10250     char_u	wcopy[MAXWLEN + 2];
10251     char_u	*p;
10252     int		i;
10253     int		c;
10254     suginfo_T	sug;
10255     suggest_T	*stp;
10256     int		mouse_used;
10257     int		need_cap;
10258     int		limit;
10259     int		selected = count;
10260     int		badlen = 0;
10261     int		msg_scroll_save = msg_scroll;
10262 
10263     if (no_spell_checking(curwin))
10264 	return;
10265 
10266 #ifdef FEAT_VISUAL
10267     if (VIsual_active)
10268     {
10269 	/* Use the Visually selected text as the bad word.  But reject
10270 	 * a multi-line selection. */
10271 	if (curwin->w_cursor.lnum != VIsual.lnum)
10272 	{
10273 	    vim_beep();
10274 	    return;
10275 	}
10276 	badlen = (int)curwin->w_cursor.col - (int)VIsual.col;
10277 	if (badlen < 0)
10278 	    badlen = -badlen;
10279 	else
10280 	    curwin->w_cursor.col = VIsual.col;
10281 	++badlen;
10282 	end_visual_mode();
10283     }
10284     else
10285 #endif
10286 	/* Find the start of the badly spelled word. */
10287 	if (spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL) == 0
10288 	    || curwin->w_cursor.col > prev_cursor.col)
10289     {
10290 	/* No bad word or it starts after the cursor: use the word under the
10291 	 * cursor. */
10292 	curwin->w_cursor = prev_cursor;
10293 	line = ml_get_curline();
10294 	p = line + curwin->w_cursor.col;
10295 	/* Backup to before start of word. */
10296 	while (p > line && spell_iswordp_nmw(p))
10297 	    mb_ptr_back(line, p);
10298 	/* Forward to start of word. */
10299 	while (*p != NUL && !spell_iswordp_nmw(p))
10300 	    mb_ptr_adv(p);
10301 
10302 	if (!spell_iswordp_nmw(p))		/* No word found. */
10303 	{
10304 	    beep_flush();
10305 	    return;
10306 	}
10307 	curwin->w_cursor.col = (colnr_T)(p - line);
10308     }
10309 
10310     /* Get the word and its length. */
10311 
10312     /* Figure out if the word should be capitalised. */
10313     need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
10314 
10315     /* Make a copy of current line since autocommands may free the line. */
10316     line = vim_strsave(ml_get_curline());
10317     if (line == NULL)
10318 	goto skip;
10319 
10320     /* Get the list of suggestions.  Limit to 'lines' - 2 or the number in
10321      * 'spellsuggest', whatever is smaller. */
10322     if (sps_limit > (int)Rows - 2)
10323 	limit = (int)Rows - 2;
10324     else
10325 	limit = sps_limit;
10326     spell_find_suggest(line + curwin->w_cursor.col, badlen, &sug, limit,
10327 							TRUE, need_cap, TRUE);
10328 
10329     if (sug.su_ga.ga_len == 0)
10330 	MSG(_("Sorry, no suggestions"));
10331     else if (count > 0)
10332     {
10333 	if (count > sug.su_ga.ga_len)
10334 	    smsg((char_u *)_("Sorry, only %ld suggestions"),
10335 						      (long)sug.su_ga.ga_len);
10336     }
10337     else
10338     {
10339 	vim_free(repl_from);
10340 	repl_from = NULL;
10341 	vim_free(repl_to);
10342 	repl_to = NULL;
10343 
10344 #ifdef FEAT_RIGHTLEFT
10345 	/* When 'rightleft' is set the list is drawn right-left. */
10346 	cmdmsg_rl = curwin->w_p_rl;
10347 	if (cmdmsg_rl)
10348 	    msg_col = Columns - 1;
10349 #endif
10350 
10351 	/* List the suggestions. */
10352 	msg_start();
10353 	msg_row = Rows - 1;	/* for when 'cmdheight' > 1 */
10354 	lines_left = Rows;	/* avoid more prompt */
10355 	vim_snprintf((char *)IObuff, IOSIZE, _("Change \"%.*s\" to:"),
10356 						sug.su_badlen, sug.su_badptr);
10357 #ifdef FEAT_RIGHTLEFT
10358 	if (cmdmsg_rl && STRNCMP(IObuff, "Change", 6) == 0)
10359 	{
10360 	    /* And now the rabbit from the high hat: Avoid showing the
10361 	     * untranslated message rightleft. */
10362 	    vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC",
10363 						sug.su_badlen, sug.su_badptr);
10364 	}
10365 #endif
10366 	msg_puts(IObuff);
10367 	msg_clr_eos();
10368 	msg_putchar('\n');
10369 
10370 	msg_scroll = TRUE;
10371 	for (i = 0; i < sug.su_ga.ga_len; ++i)
10372 	{
10373 	    stp = &SUG(sug.su_ga, i);
10374 
10375 	    /* The suggested word may replace only part of the bad word, add
10376 	     * the not replaced part. */
10377 	    STRCPY(wcopy, stp->st_word);
10378 	    if (sug.su_badlen > stp->st_orglen)
10379 		vim_strncpy(wcopy + stp->st_wordlen,
10380 					       sug.su_badptr + stp->st_orglen,
10381 					      sug.su_badlen - stp->st_orglen);
10382 	    vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
10383 #ifdef FEAT_RIGHTLEFT
10384 	    if (cmdmsg_rl)
10385 		rl_mirror(IObuff);
10386 #endif
10387 	    msg_puts(IObuff);
10388 
10389 	    vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy);
10390 	    msg_puts(IObuff);
10391 
10392 	    /* The word may replace more than "su_badlen". */
10393 	    if (sug.su_badlen < stp->st_orglen)
10394 	    {
10395 		vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""),
10396 					       stp->st_orglen, sug.su_badptr);
10397 		msg_puts(IObuff);
10398 	    }
10399 
10400 	    if (p_verbose > 0)
10401 	    {
10402 		/* Add the score. */
10403 		if (sps_flags & (SPS_DOUBLE | SPS_BEST))
10404 		    vim_snprintf((char *)IObuff, IOSIZE, " (%s%d - %d)",
10405 			stp->st_salscore ? "s " : "",
10406 			stp->st_score, stp->st_altscore);
10407 		else
10408 		    vim_snprintf((char *)IObuff, IOSIZE, " (%d)",
10409 			    stp->st_score);
10410 #ifdef FEAT_RIGHTLEFT
10411 		if (cmdmsg_rl)
10412 		    /* Mirror the numbers, but keep the leading space. */
10413 		    rl_mirror(IObuff + 1);
10414 #endif
10415 		msg_advance(30);
10416 		msg_puts(IObuff);
10417 	    }
10418 	    msg_putchar('\n');
10419 	}
10420 
10421 #ifdef FEAT_RIGHTLEFT
10422 	cmdmsg_rl = FALSE;
10423 	msg_col = 0;
10424 #endif
10425 	/* Ask for choice. */
10426 	selected = prompt_for_number(&mouse_used);
10427 	if (mouse_used)
10428 	    selected -= lines_left;
10429 	lines_left = Rows;		/* avoid more prompt */
10430 	/* don't delay for 'smd' in normal_cmd() */
10431 	msg_scroll = msg_scroll_save;
10432     }
10433 
10434     if (selected > 0 && selected <= sug.su_ga.ga_len && u_save_cursor() == OK)
10435     {
10436 	/* Save the from and to text for :spellrepall. */
10437 	stp = &SUG(sug.su_ga, selected - 1);
10438 	if (sug.su_badlen > stp->st_orglen)
10439 	{
10440 	    /* Replacing less than "su_badlen", append the remainder to
10441 	     * repl_to. */
10442 	    repl_from = vim_strnsave(sug.su_badptr, sug.su_badlen);
10443 	    vim_snprintf((char *)IObuff, IOSIZE, "%s%.*s", stp->st_word,
10444 		    sug.su_badlen - stp->st_orglen,
10445 					      sug.su_badptr + stp->st_orglen);
10446 	    repl_to = vim_strsave(IObuff);
10447 	}
10448 	else
10449 	{
10450 	    /* Replacing su_badlen or more, use the whole word. */
10451 	    repl_from = vim_strnsave(sug.su_badptr, stp->st_orglen);
10452 	    repl_to = vim_strsave(stp->st_word);
10453 	}
10454 
10455 	/* Replace the word. */
10456 	p = alloc((unsigned)STRLEN(line) - stp->st_orglen
10457 						       + stp->st_wordlen + 1);
10458 	if (p != NULL)
10459 	{
10460 	    c = (int)(sug.su_badptr - line);
10461 	    mch_memmove(p, line, c);
10462 	    STRCPY(p + c, stp->st_word);
10463 	    STRCAT(p, sug.su_badptr + stp->st_orglen);
10464 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
10465 	    curwin->w_cursor.col = c;
10466 
10467 	    /* For redo we use a change-word command. */
10468 	    ResetRedobuff();
10469 	    AppendToRedobuff((char_u *)"ciw");
10470 	    AppendToRedobuffLit(p + c,
10471 			    stp->st_wordlen + sug.su_badlen - stp->st_orglen);
10472 	    AppendCharToRedobuff(ESC);
10473 
10474 	    /* After this "p" may be invalid. */
10475 	    changed_bytes(curwin->w_cursor.lnum, c);
10476 	}
10477     }
10478     else
10479 	curwin->w_cursor = prev_cursor;
10480 
10481     spell_find_cleanup(&sug);
10482 skip:
10483     vim_free(line);
10484 }
10485 
10486 /*
10487  * Check if the word at line "lnum" column "col" is required to start with a
10488  * capital.  This uses 'spellcapcheck' of the current buffer.
10489  */
10490     static int
10491 check_need_cap(lnum, col)
10492     linenr_T	lnum;
10493     colnr_T	col;
10494 {
10495     int		need_cap = FALSE;
10496     char_u	*line;
10497     char_u	*line_copy = NULL;
10498     char_u	*p;
10499     colnr_T	endcol;
10500     regmatch_T	regmatch;
10501 
10502     if (curbuf->b_cap_prog == NULL)
10503 	return FALSE;
10504 
10505     line = ml_get_curline();
10506     endcol = 0;
10507     if ((int)(skipwhite(line) - line) >= (int)col)
10508     {
10509 	/* At start of line, check if previous line is empty or sentence
10510 	 * ends there. */
10511 	if (lnum == 1)
10512 	    need_cap = TRUE;
10513 	else
10514 	{
10515 	    line = ml_get(lnum - 1);
10516 	    if (*skipwhite(line) == NUL)
10517 		need_cap = TRUE;
10518 	    else
10519 	    {
10520 		/* Append a space in place of the line break. */
10521 		line_copy = concat_str(line, (char_u *)" ");
10522 		line = line_copy;
10523 		endcol = (colnr_T)STRLEN(line);
10524 	    }
10525 	}
10526     }
10527     else
10528 	endcol = col;
10529 
10530     if (endcol > 0)
10531     {
10532 	/* Check if sentence ends before the bad word. */
10533 	regmatch.regprog = curbuf->b_cap_prog;
10534 	regmatch.rm_ic = FALSE;
10535 	p = line + endcol;
10536 	for (;;)
10537 	{
10538 	    mb_ptr_back(line, p);
10539 	    if (p == line || spell_iswordp_nmw(p))
10540 		break;
10541 	    if (vim_regexec(&regmatch, p, 0)
10542 					 && regmatch.endp[0] == line + endcol)
10543 	    {
10544 		need_cap = TRUE;
10545 		break;
10546 	    }
10547 	}
10548     }
10549 
10550     vim_free(line_copy);
10551 
10552     return need_cap;
10553 }
10554 
10555 
10556 /*
10557  * ":spellrepall"
10558  */
10559     void
10560 ex_spellrepall(eap)
10561     exarg_T *eap UNUSED;
10562 {
10563     pos_T	pos = curwin->w_cursor;
10564     char_u	*frompat;
10565     int		addlen;
10566     char_u	*line;
10567     char_u	*p;
10568     int		save_ws = p_ws;
10569     linenr_T	prev_lnum = 0;
10570 
10571     if (repl_from == NULL || repl_to == NULL)
10572     {
10573 	EMSG(_("E752: No previous spell replacement"));
10574 	return;
10575     }
10576     addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from));
10577 
10578     frompat = alloc((unsigned)STRLEN(repl_from) + 7);
10579     if (frompat == NULL)
10580 	return;
10581     sprintf((char *)frompat, "\\V\\<%s\\>", repl_from);
10582     p_ws = FALSE;
10583 
10584     sub_nsubs = 0;
10585     sub_nlines = 0;
10586     curwin->w_cursor.lnum = 0;
10587     while (!got_int)
10588     {
10589 	if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
10590 						   || u_save_cursor() == FAIL)
10591 	    break;
10592 
10593 	/* Only replace when the right word isn't there yet.  This happens
10594 	 * when changing "etc" to "etc.". */
10595 	line = ml_get_curline();
10596 	if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col,
10597 					       repl_to, STRLEN(repl_to)) != 0)
10598 	{
10599 	    p = alloc((unsigned)STRLEN(line) + addlen + 1);
10600 	    if (p == NULL)
10601 		break;
10602 	    mch_memmove(p, line, curwin->w_cursor.col);
10603 	    STRCPY(p + curwin->w_cursor.col, repl_to);
10604 	    STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from));
10605 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
10606 	    changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
10607 
10608 	    if (curwin->w_cursor.lnum != prev_lnum)
10609 	    {
10610 		++sub_nlines;
10611 		prev_lnum = curwin->w_cursor.lnum;
10612 	    }
10613 	    ++sub_nsubs;
10614 	}
10615 	curwin->w_cursor.col += (colnr_T)STRLEN(repl_to);
10616     }
10617 
10618     p_ws = save_ws;
10619     curwin->w_cursor = pos;
10620     vim_free(frompat);
10621 
10622     if (sub_nsubs == 0)
10623 	EMSG2(_("E753: Not found: %s"), repl_from);
10624     else
10625 	do_sub_msg(FALSE);
10626 }
10627 
10628 /*
10629  * Find spell suggestions for "word".  Return them in the growarray "*gap" as
10630  * a list of allocated strings.
10631  */
10632     void
10633 spell_suggest_list(gap, word, maxcount, need_cap, interactive)
10634     garray_T	*gap;
10635     char_u	*word;
10636     int		maxcount;	/* maximum nr of suggestions */
10637     int		need_cap;	/* 'spellcapcheck' matched */
10638     int		interactive;
10639 {
10640     suginfo_T	sug;
10641     int		i;
10642     suggest_T	*stp;
10643     char_u	*wcopy;
10644 
10645     spell_find_suggest(word, 0, &sug, maxcount, FALSE, need_cap, interactive);
10646 
10647     /* Make room in "gap". */
10648     ga_init2(gap, sizeof(char_u *), sug.su_ga.ga_len + 1);
10649     if (ga_grow(gap, sug.su_ga.ga_len) == OK)
10650     {
10651 	for (i = 0; i < sug.su_ga.ga_len; ++i)
10652 	{
10653 	    stp = &SUG(sug.su_ga, i);
10654 
10655 	    /* The suggested word may replace only part of "word", add the not
10656 	     * replaced part. */
10657 	    wcopy = alloc(stp->st_wordlen
10658 		      + (unsigned)STRLEN(sug.su_badptr + stp->st_orglen) + 1);
10659 	    if (wcopy == NULL)
10660 		break;
10661 	    STRCPY(wcopy, stp->st_word);
10662 	    STRCPY(wcopy + stp->st_wordlen, sug.su_badptr + stp->st_orglen);
10663 	    ((char_u **)gap->ga_data)[gap->ga_len++] = wcopy;
10664 	}
10665     }
10666 
10667     spell_find_cleanup(&sug);
10668 }
10669 
10670 /*
10671  * Find spell suggestions for the word at the start of "badptr".
10672  * Return the suggestions in "su->su_ga".
10673  * The maximum number of suggestions is "maxcount".
10674  * Note: does use info for the current window.
10675  * This is based on the mechanisms of Aspell, but completely reimplemented.
10676  */
10677     static void
10678 spell_find_suggest(badptr, badlen, su, maxcount, banbadword, need_cap, interactive)
10679     char_u	*badptr;
10680     int		badlen;		/* length of bad word or 0 if unknown */
10681     suginfo_T	*su;
10682     int		maxcount;
10683     int		banbadword;	/* don't include badword in suggestions */
10684     int		need_cap;	/* word should start with capital */
10685     int		interactive;
10686 {
10687     hlf_T	attr = HLF_COUNT;
10688     char_u	buf[MAXPATHL];
10689     char_u	*p;
10690     int		do_combine = FALSE;
10691     char_u	*sps_copy;
10692 #ifdef FEAT_EVAL
10693     static int	expr_busy = FALSE;
10694 #endif
10695     int		c;
10696     int		i;
10697     langp_T	*lp;
10698 
10699     /*
10700      * Set the info in "*su".
10701      */
10702     vim_memset(su, 0, sizeof(suginfo_T));
10703     ga_init2(&su->su_ga, (int)sizeof(suggest_T), 10);
10704     ga_init2(&su->su_sga, (int)sizeof(suggest_T), 10);
10705     if (*badptr == NUL)
10706 	return;
10707     hash_init(&su->su_banned);
10708 
10709     su->su_badptr = badptr;
10710     if (badlen != 0)
10711 	su->su_badlen = badlen;
10712     else
10713 	su->su_badlen = spell_check(curwin, su->su_badptr, &attr, NULL, FALSE);
10714     su->su_maxcount = maxcount;
10715     su->su_maxscore = SCORE_MAXINIT;
10716 
10717     if (su->su_badlen >= MAXWLEN)
10718 	su->su_badlen = MAXWLEN - 1;	/* just in case */
10719     vim_strncpy(su->su_badword, su->su_badptr, su->su_badlen);
10720     (void)spell_casefold(su->su_badptr, su->su_badlen,
10721 						    su->su_fbadword, MAXWLEN);
10722     /* get caps flags for bad word */
10723     su->su_badflags = badword_captype(su->su_badptr,
10724 					       su->su_badptr + su->su_badlen);
10725     if (need_cap)
10726 	su->su_badflags |= WF_ONECAP;
10727 
10728     /* Find the default language for sound folding.  We simply use the first
10729      * one in 'spelllang' that supports sound folding.  That's good for when
10730      * using multiple files for one language, it's not that bad when mixing
10731      * languages (e.g., "pl,en"). */
10732     for (i = 0; i < curbuf->b_langp.ga_len; ++i)
10733     {
10734 	lp = LANGP_ENTRY(curbuf->b_langp, i);
10735 	if (lp->lp_sallang != NULL)
10736 	{
10737 	    su->su_sallang = lp->lp_sallang;
10738 	    break;
10739 	}
10740     }
10741 
10742     /* Soundfold the bad word with the default sound folding, so that we don't
10743      * have to do this many times. */
10744     if (su->su_sallang != NULL)
10745 	spell_soundfold(su->su_sallang, su->su_fbadword, TRUE,
10746 							  su->su_sal_badword);
10747 
10748     /* If the word is not capitalised and spell_check() doesn't consider the
10749      * word to be bad then it might need to be capitalised.  Add a suggestion
10750      * for that. */
10751     c = PTR2CHAR(su->su_badptr);
10752     if (!SPELL_ISUPPER(c) && attr == HLF_COUNT)
10753     {
10754 	make_case_word(su->su_badword, buf, WF_ONECAP);
10755 	add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
10756 					      0, TRUE, su->su_sallang, FALSE);
10757     }
10758 
10759     /* Ban the bad word itself.  It may appear in another region. */
10760     if (banbadword)
10761 	add_banned(su, su->su_badword);
10762 
10763     /* Make a copy of 'spellsuggest', because the expression may change it. */
10764     sps_copy = vim_strsave(p_sps);
10765     if (sps_copy == NULL)
10766 	return;
10767 
10768     /* Loop over the items in 'spellsuggest'. */
10769     for (p = sps_copy; *p != NUL; )
10770     {
10771 	copy_option_part(&p, buf, MAXPATHL, ",");
10772 
10773 	if (STRNCMP(buf, "expr:", 5) == 0)
10774 	{
10775 #ifdef FEAT_EVAL
10776 	    /* Evaluate an expression.  Skip this when called recursively,
10777 	     * when using spellsuggest() in the expression. */
10778 	    if (!expr_busy)
10779 	    {
10780 		expr_busy = TRUE;
10781 		spell_suggest_expr(su, buf + 5);
10782 		expr_busy = FALSE;
10783 	    }
10784 #endif
10785 	}
10786 	else if (STRNCMP(buf, "file:", 5) == 0)
10787 	    /* Use list of suggestions in a file. */
10788 	    spell_suggest_file(su, buf + 5);
10789 	else
10790 	{
10791 	    /* Use internal method. */
10792 	    spell_suggest_intern(su, interactive);
10793 	    if (sps_flags & SPS_DOUBLE)
10794 		do_combine = TRUE;
10795 	}
10796     }
10797 
10798     vim_free(sps_copy);
10799 
10800     if (do_combine)
10801 	/* Combine the two list of suggestions.  This must be done last,
10802 	 * because sorting changes the order again. */
10803 	score_combine(su);
10804 }
10805 
10806 #ifdef FEAT_EVAL
10807 /*
10808  * Find suggestions by evaluating expression "expr".
10809  */
10810     static void
10811 spell_suggest_expr(su, expr)
10812     suginfo_T	*su;
10813     char_u	*expr;
10814 {
10815     list_T	*list;
10816     listitem_T	*li;
10817     int		score;
10818     char_u	*p;
10819 
10820     /* The work is split up in a few parts to avoid having to export
10821      * suginfo_T.
10822      * First evaluate the expression and get the resulting list. */
10823     list = eval_spell_expr(su->su_badword, expr);
10824     if (list != NULL)
10825     {
10826 	/* Loop over the items in the list. */
10827 	for (li = list->lv_first; li != NULL; li = li->li_next)
10828 	    if (li->li_tv.v_type == VAR_LIST)
10829 	    {
10830 		/* Get the word and the score from the items. */
10831 		score = get_spellword(li->li_tv.vval.v_list, &p);
10832 		if (score >= 0 && score <= su->su_maxscore)
10833 		    add_suggestion(su, &su->su_ga, p, su->su_badlen,
10834 				       score, 0, TRUE, su->su_sallang, FALSE);
10835 	    }
10836 	list_unref(list);
10837     }
10838 
10839     /* Remove bogus suggestions, sort and truncate at "maxcount". */
10840     check_suggestions(su, &su->su_ga);
10841     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10842 }
10843 #endif
10844 
10845 /*
10846  * Find suggestions in file "fname".  Used for "file:" in 'spellsuggest'.
10847  */
10848     static void
10849 spell_suggest_file(su, fname)
10850     suginfo_T	*su;
10851     char_u	*fname;
10852 {
10853     FILE	*fd;
10854     char_u	line[MAXWLEN * 2];
10855     char_u	*p;
10856     int		len;
10857     char_u	cword[MAXWLEN];
10858 
10859     /* Open the file. */
10860     fd = mch_fopen((char *)fname, "r");
10861     if (fd == NULL)
10862     {
10863 	EMSG2(_(e_notopen), fname);
10864 	return;
10865     }
10866 
10867     /* Read it line by line. */
10868     while (!vim_fgets(line, MAXWLEN * 2, fd) && !got_int)
10869     {
10870 	line_breakcheck();
10871 
10872 	p = vim_strchr(line, '/');
10873 	if (p == NULL)
10874 	    continue;	    /* No Tab found, just skip the line. */
10875 	*p++ = NUL;
10876 	if (STRICMP(su->su_badword, line) == 0)
10877 	{
10878 	    /* Match!  Isolate the good word, until CR or NL. */
10879 	    for (len = 0; p[len] >= ' '; ++len)
10880 		;
10881 	    p[len] = NUL;
10882 
10883 	    /* If the suggestion doesn't have specific case duplicate the case
10884 	     * of the bad word. */
10885 	    if (captype(p, NULL) == 0)
10886 	    {
10887 		make_case_word(p, cword, su->su_badflags);
10888 		p = cword;
10889 	    }
10890 
10891 	    add_suggestion(su, &su->su_ga, p, su->su_badlen,
10892 				  SCORE_FILE, 0, TRUE, su->su_sallang, FALSE);
10893 	}
10894     }
10895 
10896     fclose(fd);
10897 
10898     /* Remove bogus suggestions, sort and truncate at "maxcount". */
10899     check_suggestions(su, &su->su_ga);
10900     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10901 }
10902 
10903 /*
10904  * Find suggestions for the internal method indicated by "sps_flags".
10905  */
10906     static void
10907 spell_suggest_intern(su, interactive)
10908     suginfo_T	*su;
10909     int		interactive;
10910 {
10911     /*
10912      * Load the .sug file(s) that are available and not done yet.
10913      */
10914     suggest_load_files();
10915 
10916     /*
10917      * 1. Try special cases, such as repeating a word: "the the" -> "the".
10918      *
10919      * Set a maximum score to limit the combination of operations that is
10920      * tried.
10921      */
10922     suggest_try_special(su);
10923 
10924     /*
10925      * 2. Try inserting/deleting/swapping/changing a letter, use REP entries
10926      *    from the .aff file and inserting a space (split the word).
10927      */
10928     suggest_try_change(su);
10929 
10930     /* For the resulting top-scorers compute the sound-a-like score. */
10931     if (sps_flags & SPS_DOUBLE)
10932 	score_comp_sal(su);
10933 
10934     /*
10935      * 3. Try finding sound-a-like words.
10936      */
10937     if ((sps_flags & SPS_FAST) == 0)
10938     {
10939 	if (sps_flags & SPS_BEST)
10940 	    /* Adjust the word score for the suggestions found so far for how
10941 	     * they sounds like. */
10942 	    rescore_suggestions(su);
10943 
10944 	/*
10945 	 * While going through the soundfold tree "su_maxscore" is the score
10946 	 * for the soundfold word, limits the changes that are being tried,
10947 	 * and "su_sfmaxscore" the rescored score, which is set by
10948 	 * cleanup_suggestions().
10949 	 * First find words with a small edit distance, because this is much
10950 	 * faster and often already finds the top-N suggestions.  If we didn't
10951 	 * find many suggestions try again with a higher edit distance.
10952 	 * "sl_sounddone" is used to avoid doing the same word twice.
10953 	 */
10954 	suggest_try_soundalike_prep();
10955 	su->su_maxscore = SCORE_SFMAX1;
10956 	su->su_sfmaxscore = SCORE_MAXINIT * 3;
10957 	suggest_try_soundalike(su);
10958 	if (su->su_ga.ga_len < SUG_CLEAN_COUNT(su))
10959 	{
10960 	    /* We didn't find enough matches, try again, allowing more
10961 	     * changes to the soundfold word. */
10962 	    su->su_maxscore = SCORE_SFMAX2;
10963 	    suggest_try_soundalike(su);
10964 	    if (su->su_ga.ga_len < SUG_CLEAN_COUNT(su))
10965 	    {
10966 		/* Still didn't find enough matches, try again, allowing even
10967 		 * more changes to the soundfold word. */
10968 		su->su_maxscore = SCORE_SFMAX3;
10969 		suggest_try_soundalike(su);
10970 	    }
10971 	}
10972 	su->su_maxscore = su->su_sfmaxscore;
10973 	suggest_try_soundalike_finish();
10974     }
10975 
10976     /* When CTRL-C was hit while searching do show the results.  Only clear
10977      * got_int when using a command, not for spellsuggest(). */
10978     ui_breakcheck();
10979     if (interactive && got_int)
10980     {
10981 	(void)vgetc();
10982 	got_int = FALSE;
10983     }
10984 
10985     if ((sps_flags & SPS_DOUBLE) == 0 && su->su_ga.ga_len != 0)
10986     {
10987 	if (sps_flags & SPS_BEST)
10988 	    /* Adjust the word score for how it sounds like. */
10989 	    rescore_suggestions(su);
10990 
10991 	/* Remove bogus suggestions, sort and truncate at "maxcount". */
10992 	check_suggestions(su, &su->su_ga);
10993 	(void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10994     }
10995 }
10996 
10997 /*
10998  * Load the .sug files for languages that have one and weren't loaded yet.
10999  */
11000     static void
11001 suggest_load_files()
11002 {
11003     langp_T	*lp;
11004     int		lpi;
11005     slang_T	*slang;
11006     char_u	*dotp;
11007     FILE	*fd;
11008     char_u	buf[MAXWLEN];
11009     int		i;
11010     time_t	timestamp;
11011     int		wcount;
11012     int		wordnr;
11013     garray_T	ga;
11014     int		c;
11015 
11016     /* Do this for all languages that support sound folding. */
11017     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
11018     {
11019 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
11020 	slang = lp->lp_slang;
11021 	if (slang->sl_sugtime != 0 && !slang->sl_sugloaded)
11022 	{
11023 	    /* Change ".spl" to ".sug" and open the file.  When the file isn't
11024 	     * found silently skip it.  Do set "sl_sugloaded" so that we
11025 	     * don't try again and again. */
11026 	    slang->sl_sugloaded = TRUE;
11027 
11028 	    dotp = vim_strrchr(slang->sl_fname, '.');
11029 	    if (dotp == NULL || fnamecmp(dotp, ".spl") != 0)
11030 		continue;
11031 	    STRCPY(dotp, ".sug");
11032 	    fd = mch_fopen((char *)slang->sl_fname, "r");
11033 	    if (fd == NULL)
11034 		goto nextone;
11035 
11036 	    /*
11037 	     * <SUGHEADER>: <fileID> <versionnr> <timestamp>
11038 	     */
11039 	    for (i = 0; i < VIMSUGMAGICL; ++i)
11040 		buf[i] = getc(fd);			/* <fileID> */
11041 	    if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0)
11042 	    {
11043 		EMSG2(_("E778: This does not look like a .sug file: %s"),
11044 							     slang->sl_fname);
11045 		goto nextone;
11046 	    }
11047 	    c = getc(fd);				/* <versionnr> */
11048 	    if (c < VIMSUGVERSION)
11049 	    {
11050 		EMSG2(_("E779: Old .sug file, needs to be updated: %s"),
11051 							     slang->sl_fname);
11052 		goto nextone;
11053 	    }
11054 	    else if (c > VIMSUGVERSION)
11055 	    {
11056 		EMSG2(_("E780: .sug file is for newer version of Vim: %s"),
11057 							     slang->sl_fname);
11058 		goto nextone;
11059 	    }
11060 
11061 	    /* Check the timestamp, it must be exactly the same as the one in
11062 	     * the .spl file.  Otherwise the word numbers won't match. */
11063 	    timestamp = get8c(fd);			/* <timestamp> */
11064 	    if (timestamp != slang->sl_sugtime)
11065 	    {
11066 		EMSG2(_("E781: .sug file doesn't match .spl file: %s"),
11067 							     slang->sl_fname);
11068 		goto nextone;
11069 	    }
11070 
11071 	    /*
11072 	     * <SUGWORDTREE>: <wordtree>
11073 	     * Read the trie with the soundfolded words.
11074 	     */
11075 	    if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs,
11076 							       FALSE, 0) != 0)
11077 	    {
11078 someerror:
11079 		EMSG2(_("E782: error while reading .sug file: %s"),
11080 							     slang->sl_fname);
11081 		slang_clear_sug(slang);
11082 		goto nextone;
11083 	    }
11084 
11085 	    /*
11086 	     * <SUGTABLE>: <sugwcount> <sugline> ...
11087 	     *
11088 	     * Read the table with word numbers.  We use a file buffer for
11089 	     * this, because it's so much like a file with lines.  Makes it
11090 	     * possible to swap the info and save on memory use.
11091 	     */
11092 	    slang->sl_sugbuf = open_spellbuf();
11093 	    if (slang->sl_sugbuf == NULL)
11094 		goto someerror;
11095 							    /* <sugwcount> */
11096 	    wcount = get4c(fd);
11097 	    if (wcount < 0)
11098 		goto someerror;
11099 
11100 	    /* Read all the wordnr lists into the buffer, one NUL terminated
11101 	     * list per line. */
11102 	    ga_init2(&ga, 1, 100);
11103 	    for (wordnr = 0; wordnr < wcount; ++wordnr)
11104 	    {
11105 		ga.ga_len = 0;
11106 		for (;;)
11107 		{
11108 		    c = getc(fd);			    /* <sugline> */
11109 		    if (c < 0 || ga_grow(&ga, 1) == FAIL)
11110 			goto someerror;
11111 		    ((char_u *)ga.ga_data)[ga.ga_len++] = c;
11112 		    if (c == NUL)
11113 			break;
11114 		}
11115 		if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr,
11116 					 ga.ga_data, ga.ga_len, TRUE) == FAIL)
11117 		    goto someerror;
11118 	    }
11119 	    ga_clear(&ga);
11120 
11121 	    /*
11122 	     * Need to put word counts in the word tries, so that we can find
11123 	     * a word by its number.
11124 	     */
11125 	    tree_count_words(slang->sl_fbyts, slang->sl_fidxs);
11126 	    tree_count_words(slang->sl_sbyts, slang->sl_sidxs);
11127 
11128 nextone:
11129 	    if (fd != NULL)
11130 		fclose(fd);
11131 	    STRCPY(dotp, ".spl");
11132 	}
11133     }
11134 }
11135 
11136 
11137 /*
11138  * Fill in the wordcount fields for a trie.
11139  * Returns the total number of words.
11140  */
11141     static void
11142 tree_count_words(byts, idxs)
11143     char_u	*byts;
11144     idx_T	*idxs;
11145 {
11146     int		depth;
11147     idx_T	arridx[MAXWLEN];
11148     int		curi[MAXWLEN];
11149     int		c;
11150     idx_T	n;
11151     int		wordcount[MAXWLEN];
11152 
11153     arridx[0] = 0;
11154     curi[0] = 1;
11155     wordcount[0] = 0;
11156     depth = 0;
11157     while (depth >= 0 && !got_int)
11158     {
11159 	if (curi[depth] > byts[arridx[depth]])
11160 	{
11161 	    /* Done all bytes at this node, go up one level. */
11162 	    idxs[arridx[depth]] = wordcount[depth];
11163 	    if (depth > 0)
11164 		wordcount[depth - 1] += wordcount[depth];
11165 
11166 	    --depth;
11167 	    fast_breakcheck();
11168 	}
11169 	else
11170 	{
11171 	    /* Do one more byte at this node. */
11172 	    n = arridx[depth] + curi[depth];
11173 	    ++curi[depth];
11174 
11175 	    c = byts[n];
11176 	    if (c == 0)
11177 	    {
11178 		/* End of word, count it. */
11179 		++wordcount[depth];
11180 
11181 		/* Skip over any other NUL bytes (same word with different
11182 		 * flags). */
11183 		while (byts[n + 1] == 0)
11184 		{
11185 		    ++n;
11186 		    ++curi[depth];
11187 		}
11188 	    }
11189 	    else
11190 	    {
11191 		/* Normal char, go one level deeper to count the words. */
11192 		++depth;
11193 		arridx[depth] = idxs[n];
11194 		curi[depth] = 1;
11195 		wordcount[depth] = 0;
11196 	    }
11197 	}
11198     }
11199 }
11200 
11201 /*
11202  * Free the info put in "*su" by spell_find_suggest().
11203  */
11204     static void
11205 spell_find_cleanup(su)
11206     suginfo_T	*su;
11207 {
11208     int		i;
11209 
11210     /* Free the suggestions. */
11211     for (i = 0; i < su->su_ga.ga_len; ++i)
11212 	vim_free(SUG(su->su_ga, i).st_word);
11213     ga_clear(&su->su_ga);
11214     for (i = 0; i < su->su_sga.ga_len; ++i)
11215 	vim_free(SUG(su->su_sga, i).st_word);
11216     ga_clear(&su->su_sga);
11217 
11218     /* Free the banned words. */
11219     hash_clear_all(&su->su_banned, 0);
11220 }
11221 
11222 /*
11223  * Make a copy of "word", with the first letter upper or lower cased, to
11224  * "wcopy[MAXWLEN]".  "word" must not be empty.
11225  * The result is NUL terminated.
11226  */
11227     static void
11228 onecap_copy(word, wcopy, upper)
11229     char_u	*word;
11230     char_u	*wcopy;
11231     int		upper;	    /* TRUE: first letter made upper case */
11232 {
11233     char_u	*p;
11234     int		c;
11235     int		l;
11236 
11237     p = word;
11238 #ifdef FEAT_MBYTE
11239     if (has_mbyte)
11240 	c = mb_cptr2char_adv(&p);
11241     else
11242 #endif
11243 	c = *p++;
11244     if (upper)
11245 	c = SPELL_TOUPPER(c);
11246     else
11247 	c = SPELL_TOFOLD(c);
11248 #ifdef FEAT_MBYTE
11249     if (has_mbyte)
11250 	l = mb_char2bytes(c, wcopy);
11251     else
11252 #endif
11253     {
11254 	l = 1;
11255 	wcopy[0] = c;
11256     }
11257     vim_strncpy(wcopy + l, p, MAXWLEN - l - 1);
11258 }
11259 
11260 /*
11261  * Make a copy of "word" with all the letters upper cased into
11262  * "wcopy[MAXWLEN]".  The result is NUL terminated.
11263  */
11264     static void
11265 allcap_copy(word, wcopy)
11266     char_u	*word;
11267     char_u	*wcopy;
11268 {
11269     char_u	*s;
11270     char_u	*d;
11271     int		c;
11272 
11273     d = wcopy;
11274     for (s = word; *s != NUL; )
11275     {
11276 #ifdef FEAT_MBYTE
11277 	if (has_mbyte)
11278 	    c = mb_cptr2char_adv(&s);
11279 	else
11280 #endif
11281 	    c = *s++;
11282 
11283 #ifdef FEAT_MBYTE
11284 	/* We only change � to SS when we are certain latin1 is used.  It
11285 	 * would cause weird errors in other 8-bit encodings. */
11286 	if (enc_latin1like && c == 0xdf)
11287 	{
11288 	    c = 'S';
11289 	    if (d - wcopy >= MAXWLEN - 1)
11290 		break;
11291 	    *d++ = c;
11292 	}
11293 	else
11294 #endif
11295 	    c = SPELL_TOUPPER(c);
11296 
11297 #ifdef FEAT_MBYTE
11298 	if (has_mbyte)
11299 	{
11300 	    if (d - wcopy >= MAXWLEN - MB_MAXBYTES)
11301 		break;
11302 	    d += mb_char2bytes(c, d);
11303 	}
11304 	else
11305 #endif
11306 	{
11307 	    if (d - wcopy >= MAXWLEN - 1)
11308 		break;
11309 	    *d++ = c;
11310 	}
11311     }
11312     *d = NUL;
11313 }
11314 
11315 /*
11316  * Try finding suggestions by recognizing specific situations.
11317  */
11318     static void
11319 suggest_try_special(su)
11320     suginfo_T	*su;
11321 {
11322     char_u	*p;
11323     size_t	len;
11324     int		c;
11325     char_u	word[MAXWLEN];
11326 
11327     /*
11328      * Recognize a word that is repeated: "the the".
11329      */
11330     p = skiptowhite(su->su_fbadword);
11331     len = p - su->su_fbadword;
11332     p = skipwhite(p);
11333     if (STRLEN(p) == len && STRNCMP(su->su_fbadword, p, len) == 0)
11334     {
11335 	/* Include badflags: if the badword is onecap or allcap
11336 	 * use that for the goodword too: "The the" -> "The". */
11337 	c = su->su_fbadword[len];
11338 	su->su_fbadword[len] = NUL;
11339 	make_case_word(su->su_fbadword, word, su->su_badflags);
11340 	su->su_fbadword[len] = c;
11341 
11342 	/* Give a soundalike score of 0, compute the score as if deleting one
11343 	 * character. */
11344 	add_suggestion(su, &su->su_ga, word, su->su_badlen,
11345 		       RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang, FALSE);
11346     }
11347 }
11348 
11349 /*
11350  * Try finding suggestions by adding/removing/swapping letters.
11351  */
11352     static void
11353 suggest_try_change(su)
11354     suginfo_T	*su;
11355 {
11356     char_u	fword[MAXWLEN];	    /* copy of the bad word, case-folded */
11357     int		n;
11358     char_u	*p;
11359     int		lpi;
11360     langp_T	*lp;
11361 
11362     /* We make a copy of the case-folded bad word, so that we can modify it
11363      * to find matches (esp. REP items).  Append some more text, changing
11364      * chars after the bad word may help. */
11365     STRCPY(fword, su->su_fbadword);
11366     n = (int)STRLEN(fword);
11367     p = su->su_badptr + su->su_badlen;
11368     (void)spell_casefold(p, (int)STRLEN(p), fword + n, MAXWLEN - n);
11369 
11370     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
11371     {
11372 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
11373 
11374 	/* If reloading a spell file fails it's still in the list but
11375 	 * everything has been cleared. */
11376 	if (lp->lp_slang->sl_fbyts == NULL)
11377 	    continue;
11378 
11379 	/* Try it for this language.  Will add possible suggestions. */
11380 	suggest_trie_walk(su, lp, fword, FALSE);
11381     }
11382 }
11383 
11384 /* Check the maximum score, if we go over it we won't try this change. */
11385 #define TRY_DEEPER(su, stack, depth, add) \
11386 		(stack[depth].ts_score + (add) < su->su_maxscore)
11387 
11388 /*
11389  * Try finding suggestions by adding/removing/swapping letters.
11390  *
11391  * This uses a state machine.  At each node in the tree we try various
11392  * operations.  When trying if an operation works "depth" is increased and the
11393  * stack[] is used to store info.  This allows combinations, thus insert one
11394  * character, replace one and delete another.  The number of changes is
11395  * limited by su->su_maxscore.
11396  *
11397  * After implementing this I noticed an article by Kemal Oflazer that
11398  * describes something similar: "Error-tolerant Finite State Recognition with
11399  * Applications to Morphological Analysis and Spelling Correction" (1996).
11400  * The implementation in the article is simplified and requires a stack of
11401  * unknown depth.  The implementation here only needs a stack depth equal to
11402  * the length of the word.
11403  *
11404  * This is also used for the sound-folded word, "soundfold" is TRUE then.
11405  * The mechanism is the same, but we find a match with a sound-folded word
11406  * that comes from one or more original words.  Each of these words may be
11407  * added, this is done by add_sound_suggest().
11408  * Don't use:
11409  *	the prefix tree or the keep-case tree
11410  *	"su->su_badlen"
11411  *	anything to do with upper and lower case
11412  *	anything to do with word or non-word characters ("spell_iswordp()")
11413  *	banned words
11414  *	word flags (rare, region, compounding)
11415  *	word splitting for now
11416  *	"similar_chars()"
11417  *	use "slang->sl_repsal" instead of "lp->lp_replang->sl_rep"
11418  */
11419     static void
11420 suggest_trie_walk(su, lp, fword, soundfold)
11421     suginfo_T	*su;
11422     langp_T	*lp;
11423     char_u	*fword;
11424     int		soundfold;
11425 {
11426     char_u	tword[MAXWLEN];	    /* good word collected so far */
11427     trystate_T	stack[MAXWLEN];
11428     char_u	preword[MAXWLEN * 3]; /* word found with proper case;
11429 				       * concatenation of prefix compound
11430 				       * words and split word.  NUL terminated
11431 				       * when going deeper but not when coming
11432 				       * back. */
11433     char_u	compflags[MAXWLEN];	/* compound flags, one for each word */
11434     trystate_T	*sp;
11435     int		newscore;
11436     int		score;
11437     char_u	*byts, *fbyts, *pbyts;
11438     idx_T	*idxs, *fidxs, *pidxs;
11439     int		depth;
11440     int		c, c2, c3;
11441     int		n = 0;
11442     int		flags;
11443     garray_T	*gap;
11444     idx_T	arridx;
11445     int		len;
11446     char_u	*p;
11447     fromto_T	*ftp;
11448     int		fl = 0, tl;
11449     int		repextra = 0;	    /* extra bytes in fword[] from REP item */
11450     slang_T	*slang = lp->lp_slang;
11451     int		fword_ends;
11452     int		goodword_ends;
11453 #ifdef DEBUG_TRIEWALK
11454     /* Stores the name of the change made at each level. */
11455     char_u	changename[MAXWLEN][80];
11456 #endif
11457     int		breakcheckcount = 1000;
11458     int		compound_ok;
11459 
11460     /*
11461      * Go through the whole case-fold tree, try changes at each node.
11462      * "tword[]" contains the word collected from nodes in the tree.
11463      * "fword[]" the word we are trying to match with (initially the bad
11464      * word).
11465      */
11466     depth = 0;
11467     sp = &stack[0];
11468     vim_memset(sp, 0, sizeof(trystate_T));
11469     sp->ts_curi = 1;
11470 
11471     if (soundfold)
11472     {
11473 	/* Going through the soundfold tree. */
11474 	byts = fbyts = slang->sl_sbyts;
11475 	idxs = fidxs = slang->sl_sidxs;
11476 	pbyts = NULL;
11477 	pidxs = NULL;
11478 	sp->ts_prefixdepth = PFD_NOPREFIX;
11479 	sp->ts_state = STATE_START;
11480     }
11481     else
11482     {
11483 	/*
11484 	 * When there are postponed prefixes we need to use these first.  At
11485 	 * the end of the prefix we continue in the case-fold tree.
11486 	 */
11487 	fbyts = slang->sl_fbyts;
11488 	fidxs = slang->sl_fidxs;
11489 	pbyts = slang->sl_pbyts;
11490 	pidxs = slang->sl_pidxs;
11491 	if (pbyts != NULL)
11492 	{
11493 	    byts = pbyts;
11494 	    idxs = pidxs;
11495 	    sp->ts_prefixdepth = PFD_PREFIXTREE;
11496 	    sp->ts_state = STATE_NOPREFIX;	/* try without prefix first */
11497 	}
11498 	else
11499 	{
11500 	    byts = fbyts;
11501 	    idxs = fidxs;
11502 	    sp->ts_prefixdepth = PFD_NOPREFIX;
11503 	    sp->ts_state = STATE_START;
11504 	}
11505     }
11506 
11507     /*
11508      * Loop to find all suggestions.  At each round we either:
11509      * - For the current state try one operation, advance "ts_curi",
11510      *   increase "depth".
11511      * - When a state is done go to the next, set "ts_state".
11512      * - When all states are tried decrease "depth".
11513      */
11514     while (depth >= 0 && !got_int)
11515     {
11516 	sp = &stack[depth];
11517 	switch (sp->ts_state)
11518 	{
11519 	case STATE_START:
11520 	case STATE_NOPREFIX:
11521 	    /*
11522 	     * Start of node: Deal with NUL bytes, which means
11523 	     * tword[] may end here.
11524 	     */
11525 	    arridx = sp->ts_arridx;	    /* current node in the tree */
11526 	    len = byts[arridx];		    /* bytes in this node */
11527 	    arridx += sp->ts_curi;	    /* index of current byte */
11528 
11529 	    if (sp->ts_prefixdepth == PFD_PREFIXTREE)
11530 	    {
11531 		/* Skip over the NUL bytes, we use them later. */
11532 		for (n = 0; n < len && byts[arridx + n] == 0; ++n)
11533 		    ;
11534 		sp->ts_curi += n;
11535 
11536 		/* Always past NUL bytes now. */
11537 		n = (int)sp->ts_state;
11538 		sp->ts_state = STATE_ENDNUL;
11539 		sp->ts_save_badflags = su->su_badflags;
11540 
11541 		/* At end of a prefix or at start of prefixtree: check for
11542 		 * following word. */
11543 		if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)
11544 		{
11545 		    /* Set su->su_badflags to the caps type at this position.
11546 		     * Use the caps type until here for the prefix itself. */
11547 #ifdef FEAT_MBYTE
11548 		    if (has_mbyte)
11549 			n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
11550 		    else
11551 #endif
11552 			n = sp->ts_fidx;
11553 		    flags = badword_captype(su->su_badptr, su->su_badptr + n);
11554 		    su->su_badflags = badword_captype(su->su_badptr + n,
11555 					       su->su_badptr + su->su_badlen);
11556 #ifdef DEBUG_TRIEWALK
11557 		    sprintf(changename[depth], "prefix");
11558 #endif
11559 		    go_deeper(stack, depth, 0);
11560 		    ++depth;
11561 		    sp = &stack[depth];
11562 		    sp->ts_prefixdepth = depth - 1;
11563 		    byts = fbyts;
11564 		    idxs = fidxs;
11565 		    sp->ts_arridx = 0;
11566 
11567 		    /* Move the prefix to preword[] with the right case
11568 		     * and make find_keepcap_word() works. */
11569 		    tword[sp->ts_twordlen] = NUL;
11570 		    make_case_word(tword + sp->ts_splitoff,
11571 					  preword + sp->ts_prewordlen, flags);
11572 		    sp->ts_prewordlen = (char_u)STRLEN(preword);
11573 		    sp->ts_splitoff = sp->ts_twordlen;
11574 		}
11575 		break;
11576 	    }
11577 
11578 	    if (sp->ts_curi > len || byts[arridx] != 0)
11579 	    {
11580 		/* Past bytes in node and/or past NUL bytes. */
11581 		sp->ts_state = STATE_ENDNUL;
11582 		sp->ts_save_badflags = su->su_badflags;
11583 		break;
11584 	    }
11585 
11586 	    /*
11587 	     * End of word in tree.
11588 	     */
11589 	    ++sp->ts_curi;		/* eat one NUL byte */
11590 
11591 	    flags = (int)idxs[arridx];
11592 
11593 	    /* Skip words with the NOSUGGEST flag. */
11594 	    if (flags & WF_NOSUGGEST)
11595 		break;
11596 
11597 	    fword_ends = (fword[sp->ts_fidx] == NUL
11598 			   || (soundfold
11599 			       ? vim_iswhite(fword[sp->ts_fidx])
11600 			       : !spell_iswordp(fword + sp->ts_fidx, curbuf)));
11601 	    tword[sp->ts_twordlen] = NUL;
11602 
11603 	    if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
11604 					&& (sp->ts_flags & TSF_PREFIXOK) == 0)
11605 	    {
11606 		/* There was a prefix before the word.  Check that the prefix
11607 		 * can be used with this word. */
11608 		/* Count the length of the NULs in the prefix.  If there are
11609 		 * none this must be the first try without a prefix.  */
11610 		n = stack[sp->ts_prefixdepth].ts_arridx;
11611 		len = pbyts[n++];
11612 		for (c = 0; c < len && pbyts[n + c] == 0; ++c)
11613 		    ;
11614 		if (c > 0)
11615 		{
11616 		    c = valid_word_prefix(c, n, flags,
11617 				       tword + sp->ts_splitoff, slang, FALSE);
11618 		    if (c == 0)
11619 			break;
11620 
11621 		    /* Use the WF_RARE flag for a rare prefix. */
11622 		    if (c & WF_RAREPFX)
11623 			flags |= WF_RARE;
11624 
11625 		    /* Tricky: when checking for both prefix and compounding
11626 		     * we run into the prefix flag first.
11627 		     * Remember that it's OK, so that we accept the prefix
11628 		     * when arriving at a compound flag. */
11629 		    sp->ts_flags |= TSF_PREFIXOK;
11630 		}
11631 	    }
11632 
11633 	    /* Check NEEDCOMPOUND: can't use word without compounding.  Do try
11634 	     * appending another compound word below. */
11635 	    if (sp->ts_complen == sp->ts_compsplit && fword_ends
11636 						     && (flags & WF_NEEDCOMP))
11637 		goodword_ends = FALSE;
11638 	    else
11639 		goodword_ends = TRUE;
11640 
11641 	    p = NULL;
11642 	    compound_ok = TRUE;
11643 	    if (sp->ts_complen > sp->ts_compsplit)
11644 	    {
11645 		if (slang->sl_nobreak)
11646 		{
11647 		    /* There was a word before this word.  When there was no
11648 		     * change in this word (it was correct) add the first word
11649 		     * as a suggestion.  If this word was corrected too, we
11650 		     * need to check if a correct word follows. */
11651 		    if (sp->ts_fidx - sp->ts_splitfidx
11652 					  == sp->ts_twordlen - sp->ts_splitoff
11653 			    && STRNCMP(fword + sp->ts_splitfidx,
11654 					tword + sp->ts_splitoff,
11655 					 sp->ts_fidx - sp->ts_splitfidx) == 0)
11656 		    {
11657 			preword[sp->ts_prewordlen] = NUL;
11658 			newscore = score_wordcount_adj(slang, sp->ts_score,
11659 						 preword + sp->ts_prewordlen,
11660 						 sp->ts_prewordlen > 0);
11661 			/* Add the suggestion if the score isn't too bad. */
11662 			if (newscore <= su->su_maxscore)
11663 			    add_suggestion(su, &su->su_ga, preword,
11664 				    sp->ts_splitfidx - repextra,
11665 				    newscore, 0, FALSE,
11666 				    lp->lp_sallang, FALSE);
11667 			break;
11668 		    }
11669 		}
11670 		else
11671 		{
11672 		    /* There was a compound word before this word.  If this
11673 		     * word does not support compounding then give up
11674 		     * (splitting is tried for the word without compound
11675 		     * flag). */
11676 		    if (((unsigned)flags >> 24) == 0
11677 			    || sp->ts_twordlen - sp->ts_splitoff
11678 						       < slang->sl_compminlen)
11679 			break;
11680 #ifdef FEAT_MBYTE
11681 		    /* For multi-byte chars check character length against
11682 		     * COMPOUNDMIN. */
11683 		    if (has_mbyte
11684 			    && slang->sl_compminlen > 0
11685 			    && mb_charlen(tword + sp->ts_splitoff)
11686 						       < slang->sl_compminlen)
11687 			break;
11688 #endif
11689 
11690 		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
11691 		    compflags[sp->ts_complen + 1] = NUL;
11692 		    vim_strncpy(preword + sp->ts_prewordlen,
11693 			    tword + sp->ts_splitoff,
11694 			    sp->ts_twordlen - sp->ts_splitoff);
11695 
11696 		    /* Verify CHECKCOMPOUNDPATTERN  rules. */
11697 		    if (match_checkcompoundpattern(preword,  sp->ts_prewordlen,
11698 							  &slang->sl_comppat))
11699 			compound_ok = FALSE;
11700 
11701 		    if (compound_ok)
11702 		    {
11703 			p = preword;
11704 			while (*skiptowhite(p) != NUL)
11705 			    p = skipwhite(skiptowhite(p));
11706 			if (fword_ends && !can_compound(slang, p,
11707 						compflags + sp->ts_compsplit))
11708 			    /* Compound is not allowed.  But it may still be
11709 			     * possible if we add another (short) word. */
11710 			    compound_ok = FALSE;
11711 		    }
11712 
11713 		    /* Get pointer to last char of previous word. */
11714 		    p = preword + sp->ts_prewordlen;
11715 		    mb_ptr_back(preword, p);
11716 		}
11717 	    }
11718 
11719 	    /*
11720 	     * Form the word with proper case in preword.
11721 	     * If there is a word from a previous split, append.
11722 	     * For the soundfold tree don't change the case, simply append.
11723 	     */
11724 	    if (soundfold)
11725 		STRCPY(preword + sp->ts_prewordlen, tword + sp->ts_splitoff);
11726 	    else if (flags & WF_KEEPCAP)
11727 		/* Must find the word in the keep-case tree. */
11728 		find_keepcap_word(slang, tword + sp->ts_splitoff,
11729 						 preword + sp->ts_prewordlen);
11730 	    else
11731 	    {
11732 		/* Include badflags: If the badword is onecap or allcap
11733 		 * use that for the goodword too.  But if the badword is
11734 		 * allcap and it's only one char long use onecap. */
11735 		c = su->su_badflags;
11736 		if ((c & WF_ALLCAP)
11737 #ifdef FEAT_MBYTE
11738 			&& su->su_badlen == (*mb_ptr2len)(su->su_badptr)
11739 #else
11740 			&& su->su_badlen == 1
11741 #endif
11742 			)
11743 		    c = WF_ONECAP;
11744 		c |= flags;
11745 
11746 		/* When appending a compound word after a word character don't
11747 		 * use Onecap. */
11748 		if (p != NULL && spell_iswordp_nmw(p))
11749 		    c &= ~WF_ONECAP;
11750 		make_case_word(tword + sp->ts_splitoff,
11751 					      preword + sp->ts_prewordlen, c);
11752 	    }
11753 
11754 	    if (!soundfold)
11755 	    {
11756 		/* Don't use a banned word.  It may appear again as a good
11757 		 * word, thus remember it. */
11758 		if (flags & WF_BANNED)
11759 		{
11760 		    add_banned(su, preword + sp->ts_prewordlen);
11761 		    break;
11762 		}
11763 		if ((sp->ts_complen == sp->ts_compsplit
11764 			    && WAS_BANNED(su, preword + sp->ts_prewordlen))
11765 						   || WAS_BANNED(su, preword))
11766 		{
11767 		    if (slang->sl_compprog == NULL)
11768 			break;
11769 		    /* the word so far was banned but we may try compounding */
11770 		    goodword_ends = FALSE;
11771 		}
11772 	    }
11773 
11774 	    newscore = 0;
11775 	    if (!soundfold)	/* soundfold words don't have flags */
11776 	    {
11777 		if ((flags & WF_REGION)
11778 			    && (((unsigned)flags >> 16) & lp->lp_region) == 0)
11779 		    newscore += SCORE_REGION;
11780 		if (flags & WF_RARE)
11781 		    newscore += SCORE_RARE;
11782 
11783 		if (!spell_valid_case(su->su_badflags,
11784 				  captype(preword + sp->ts_prewordlen, NULL)))
11785 		    newscore += SCORE_ICASE;
11786 	    }
11787 
11788 	    /* TODO: how about splitting in the soundfold tree? */
11789 	    if (fword_ends
11790 		    && goodword_ends
11791 		    && sp->ts_fidx >= sp->ts_fidxtry
11792 		    && compound_ok)
11793 	    {
11794 		/* The badword also ends: add suggestions. */
11795 #ifdef DEBUG_TRIEWALK
11796 		if (soundfold && STRCMP(preword, "smwrd") == 0)
11797 		{
11798 		    int	    j;
11799 
11800 		    /* print the stack of changes that brought us here */
11801 		    smsg("------ %s -------", fword);
11802 		    for (j = 0; j < depth; ++j)
11803 			smsg("%s", changename[j]);
11804 		}
11805 #endif
11806 		if (soundfold)
11807 		{
11808 		    /* For soundfolded words we need to find the original
11809 		     * words, the edit distance and then add them. */
11810 		    add_sound_suggest(su, preword, sp->ts_score, lp);
11811 		}
11812 		else
11813 		{
11814 		    /* Give a penalty when changing non-word char to word
11815 		     * char, e.g., "thes," -> "these". */
11816 		    p = fword + sp->ts_fidx;
11817 		    mb_ptr_back(fword, p);
11818 		    if (!spell_iswordp(p, curbuf))
11819 		    {
11820 			p = preword + STRLEN(preword);
11821 			mb_ptr_back(preword, p);
11822 			if (spell_iswordp(p, curbuf))
11823 			    newscore += SCORE_NONWORD;
11824 		    }
11825 
11826 		    /* Give a bonus to words seen before. */
11827 		    score = score_wordcount_adj(slang,
11828 						sp->ts_score + newscore,
11829 						preword + sp->ts_prewordlen,
11830 						sp->ts_prewordlen > 0);
11831 
11832 		    /* Add the suggestion if the score isn't too bad. */
11833 		    if (score <= su->su_maxscore)
11834 		    {
11835 			add_suggestion(su, &su->su_ga, preword,
11836 				    sp->ts_fidx - repextra,
11837 				    score, 0, FALSE, lp->lp_sallang, FALSE);
11838 
11839 			if (su->su_badflags & WF_MIXCAP)
11840 			{
11841 			    /* We really don't know if the word should be
11842 			     * upper or lower case, add both. */
11843 			    c = captype(preword, NULL);
11844 			    if (c == 0 || c == WF_ALLCAP)
11845 			    {
11846 				make_case_word(tword + sp->ts_splitoff,
11847 					      preword + sp->ts_prewordlen,
11848 						      c == 0 ? WF_ALLCAP : 0);
11849 
11850 				add_suggestion(su, &su->su_ga, preword,
11851 					sp->ts_fidx - repextra,
11852 					score + SCORE_ICASE, 0, FALSE,
11853 					lp->lp_sallang, FALSE);
11854 			    }
11855 			}
11856 		    }
11857 		}
11858 	    }
11859 
11860 	    /*
11861 	     * Try word split and/or compounding.
11862 	     */
11863 	    if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
11864 #ifdef FEAT_MBYTE
11865 		    /* Don't split halfway a character. */
11866 		    && (!has_mbyte || sp->ts_tcharlen == 0)
11867 #endif
11868 		    )
11869 	    {
11870 		int	try_compound;
11871 		int	try_split;
11872 
11873 		/* If past the end of the bad word don't try a split.
11874 		 * Otherwise try changing the next word.  E.g., find
11875 		 * suggestions for "the the" where the second "the" is
11876 		 * different.  It's done like a split.
11877 		 * TODO: word split for soundfold words */
11878 		try_split = (sp->ts_fidx - repextra < su->su_badlen)
11879 								&& !soundfold;
11880 
11881 		/* Get here in several situations:
11882 		 * 1. The word in the tree ends:
11883 		 *    If the word allows compounding try that.  Otherwise try
11884 		 *    a split by inserting a space.  For both check that a
11885 		 *    valid words starts at fword[sp->ts_fidx].
11886 		 *    For NOBREAK do like compounding to be able to check if
11887 		 *    the next word is valid.
11888 		 * 2. The badword does end, but it was due to a change (e.g.,
11889 		 *    a swap).  No need to split, but do check that the
11890 		 *    following word is valid.
11891 		 * 3. The badword and the word in the tree end.  It may still
11892 		 *    be possible to compound another (short) word.
11893 		 */
11894 		try_compound = FALSE;
11895 		if (!soundfold
11896 			&& slang->sl_compprog != NULL
11897 			&& ((unsigned)flags >> 24) != 0
11898 			&& sp->ts_twordlen - sp->ts_splitoff
11899 						       >= slang->sl_compminlen
11900 #ifdef FEAT_MBYTE
11901 			&& (!has_mbyte
11902 			    || slang->sl_compminlen == 0
11903 			    || mb_charlen(tword + sp->ts_splitoff)
11904 						      >= slang->sl_compminlen)
11905 #endif
11906 			&& (slang->sl_compsylmax < MAXWLEN
11907 			    || sp->ts_complen + 1 - sp->ts_compsplit
11908 							  < slang->sl_compmax)
11909 			&& (can_be_compound(sp, slang,
11910 					 compflags, ((unsigned)flags >> 24))))
11911 
11912 		{
11913 		    try_compound = TRUE;
11914 		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
11915 		    compflags[sp->ts_complen + 1] = NUL;
11916 		}
11917 
11918 		/* For NOBREAK we never try splitting, it won't make any word
11919 		 * valid. */
11920 		if (slang->sl_nobreak)
11921 		    try_compound = TRUE;
11922 
11923 		/* If we could add a compound word, and it's also possible to
11924 		 * split at this point, do the split first and set
11925 		 * TSF_DIDSPLIT to avoid doing it again. */
11926 		else if (!fword_ends
11927 			&& try_compound
11928 			&& (sp->ts_flags & TSF_DIDSPLIT) == 0)
11929 		{
11930 		    try_compound = FALSE;
11931 		    sp->ts_flags |= TSF_DIDSPLIT;
11932 		    --sp->ts_curi;	    /* do the same NUL again */
11933 		    compflags[sp->ts_complen] = NUL;
11934 		}
11935 		else
11936 		    sp->ts_flags &= ~TSF_DIDSPLIT;
11937 
11938 		if (try_split || try_compound)
11939 		{
11940 		    if (!try_compound && (!fword_ends || !goodword_ends))
11941 		    {
11942 			/* If we're going to split need to check that the
11943 			 * words so far are valid for compounding.  If there
11944 			 * is only one word it must not have the NEEDCOMPOUND
11945 			 * flag. */
11946 			if (sp->ts_complen == sp->ts_compsplit
11947 						     && (flags & WF_NEEDCOMP))
11948 			    break;
11949 			p = preword;
11950 			while (*skiptowhite(p) != NUL)
11951 			    p = skipwhite(skiptowhite(p));
11952 			if (sp->ts_complen > sp->ts_compsplit
11953 				&& !can_compound(slang, p,
11954 						compflags + sp->ts_compsplit))
11955 			    break;
11956 
11957 			if (slang->sl_nosplitsugs)
11958 			    newscore += SCORE_SPLIT_NO;
11959 			else
11960 			    newscore += SCORE_SPLIT;
11961 
11962 			/* Give a bonus to words seen before. */
11963 			newscore = score_wordcount_adj(slang, newscore,
11964 					   preword + sp->ts_prewordlen, TRUE);
11965 		    }
11966 
11967 		    if (TRY_DEEPER(su, stack, depth, newscore))
11968 		    {
11969 			go_deeper(stack, depth, newscore);
11970 #ifdef DEBUG_TRIEWALK
11971 			if (!try_compound && !fword_ends)
11972 			    sprintf(changename[depth], "%.*s-%s: split",
11973 				 sp->ts_twordlen, tword, fword + sp->ts_fidx);
11974 			else
11975 			    sprintf(changename[depth], "%.*s-%s: compound",
11976 				 sp->ts_twordlen, tword, fword + sp->ts_fidx);
11977 #endif
11978 			/* Save things to be restored at STATE_SPLITUNDO. */
11979 			sp->ts_save_badflags = su->su_badflags;
11980 			sp->ts_state = STATE_SPLITUNDO;
11981 
11982 			++depth;
11983 			sp = &stack[depth];
11984 
11985 			/* Append a space to preword when splitting. */
11986 			if (!try_compound && !fword_ends)
11987 			    STRCAT(preword, " ");
11988 			sp->ts_prewordlen = (char_u)STRLEN(preword);
11989 			sp->ts_splitoff = sp->ts_twordlen;
11990 			sp->ts_splitfidx = sp->ts_fidx;
11991 
11992 			/* If the badword has a non-word character at this
11993 			 * position skip it.  That means replacing the
11994 			 * non-word character with a space.  Always skip a
11995 			 * character when the word ends.  But only when the
11996 			 * good word can end. */
11997 			if (((!try_compound && !spell_iswordp_nmw(fword
11998 							       + sp->ts_fidx))
11999 				    || fword_ends)
12000 				&& fword[sp->ts_fidx] != NUL
12001 				&& goodword_ends)
12002 			{
12003 			    int	    l;
12004 
12005 #ifdef FEAT_MBYTE
12006 			    if (has_mbyte)
12007 				l = MB_BYTE2LEN(fword[sp->ts_fidx]);
12008 			    else
12009 #endif
12010 				l = 1;
12011 			    if (fword_ends)
12012 			    {
12013 				/* Copy the skipped character to preword. */
12014 				mch_memmove(preword + sp->ts_prewordlen,
12015 						      fword + sp->ts_fidx, l);
12016 				sp->ts_prewordlen += l;
12017 				preword[sp->ts_prewordlen] = NUL;
12018 			    }
12019 			    else
12020 				sp->ts_score -= SCORE_SPLIT - SCORE_SUBST;
12021 			    sp->ts_fidx += l;
12022 			}
12023 
12024 			/* When compounding include compound flag in
12025 			 * compflags[] (already set above).  When splitting we
12026 			 * may start compounding over again.  */
12027 			if (try_compound)
12028 			    ++sp->ts_complen;
12029 			else
12030 			    sp->ts_compsplit = sp->ts_complen;
12031 			sp->ts_prefixdepth = PFD_NOPREFIX;
12032 
12033 			/* set su->su_badflags to the caps type at this
12034 			 * position */
12035 #ifdef FEAT_MBYTE
12036 			if (has_mbyte)
12037 			    n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
12038 			else
12039 #endif
12040 			    n = sp->ts_fidx;
12041 			su->su_badflags = badword_captype(su->su_badptr + n,
12042 					       su->su_badptr + su->su_badlen);
12043 
12044 			/* Restart at top of the tree. */
12045 			sp->ts_arridx = 0;
12046 
12047 			/* If there are postponed prefixes, try these too. */
12048 			if (pbyts != NULL)
12049 			{
12050 			    byts = pbyts;
12051 			    idxs = pidxs;
12052 			    sp->ts_prefixdepth = PFD_PREFIXTREE;
12053 			    sp->ts_state = STATE_NOPREFIX;
12054 			}
12055 		    }
12056 		}
12057 	    }
12058 	    break;
12059 
12060 	case STATE_SPLITUNDO:
12061 	    /* Undo the changes done for word split or compound word. */
12062 	    su->su_badflags = sp->ts_save_badflags;
12063 
12064 	    /* Continue looking for NUL bytes. */
12065 	    sp->ts_state = STATE_START;
12066 
12067 	    /* In case we went into the prefix tree. */
12068 	    byts = fbyts;
12069 	    idxs = fidxs;
12070 	    break;
12071 
12072 	case STATE_ENDNUL:
12073 	    /* Past the NUL bytes in the node. */
12074 	    su->su_badflags = sp->ts_save_badflags;
12075 	    if (fword[sp->ts_fidx] == NUL
12076 #ifdef FEAT_MBYTE
12077 		    && sp->ts_tcharlen == 0
12078 #endif
12079 	       )
12080 	    {
12081 		/* The badword ends, can't use STATE_PLAIN. */
12082 		sp->ts_state = STATE_DEL;
12083 		break;
12084 	    }
12085 	    sp->ts_state = STATE_PLAIN;
12086 	    /*FALLTHROUGH*/
12087 
12088 	case STATE_PLAIN:
12089 	    /*
12090 	     * Go over all possible bytes at this node, add each to tword[]
12091 	     * and use child node.  "ts_curi" is the index.
12092 	     */
12093 	    arridx = sp->ts_arridx;
12094 	    if (sp->ts_curi > byts[arridx])
12095 	    {
12096 		/* Done all bytes at this node, do next state.  When still at
12097 		 * already changed bytes skip the other tricks. */
12098 		if (sp->ts_fidx >= sp->ts_fidxtry)
12099 		    sp->ts_state = STATE_DEL;
12100 		else
12101 		    sp->ts_state = STATE_FINAL;
12102 	    }
12103 	    else
12104 	    {
12105 		arridx += sp->ts_curi++;
12106 		c = byts[arridx];
12107 
12108 		/* Normal byte, go one level deeper.  If it's not equal to the
12109 		 * byte in the bad word adjust the score.  But don't even try
12110 		 * when the byte was already changed.  And don't try when we
12111 		 * just deleted this byte, accepting it is always cheaper then
12112 		 * delete + substitute. */
12113 		if (c == fword[sp->ts_fidx]
12114 #ifdef FEAT_MBYTE
12115 			|| (sp->ts_tcharlen > 0 && sp->ts_isdiff != DIFF_NONE)
12116 #endif
12117 			)
12118 		    newscore = 0;
12119 		else
12120 		    newscore = SCORE_SUBST;
12121 		if ((newscore == 0
12122 			    || (sp->ts_fidx >= sp->ts_fidxtry
12123 				&& ((sp->ts_flags & TSF_DIDDEL) == 0
12124 				    || c != fword[sp->ts_delidx])))
12125 			&& TRY_DEEPER(su, stack, depth, newscore))
12126 		{
12127 		    go_deeper(stack, depth, newscore);
12128 #ifdef DEBUG_TRIEWALK
12129 		    if (newscore > 0)
12130 			sprintf(changename[depth], "%.*s-%s: subst %c to %c",
12131 				sp->ts_twordlen, tword, fword + sp->ts_fidx,
12132 				fword[sp->ts_fidx], c);
12133 		    else
12134 			sprintf(changename[depth], "%.*s-%s: accept %c",
12135 				sp->ts_twordlen, tword, fword + sp->ts_fidx,
12136 				fword[sp->ts_fidx]);
12137 #endif
12138 		    ++depth;
12139 		    sp = &stack[depth];
12140 		    ++sp->ts_fidx;
12141 		    tword[sp->ts_twordlen++] = c;
12142 		    sp->ts_arridx = idxs[arridx];
12143 #ifdef FEAT_MBYTE
12144 		    if (newscore == SCORE_SUBST)
12145 			sp->ts_isdiff = DIFF_YES;
12146 		    if (has_mbyte)
12147 		    {
12148 			/* Multi-byte characters are a bit complicated to
12149 			 * handle: They differ when any of the bytes differ
12150 			 * and then their length may also differ. */
12151 			if (sp->ts_tcharlen == 0)
12152 			{
12153 			    /* First byte. */
12154 			    sp->ts_tcharidx = 0;
12155 			    sp->ts_tcharlen = MB_BYTE2LEN(c);
12156 			    sp->ts_fcharstart = sp->ts_fidx - 1;
12157 			    sp->ts_isdiff = (newscore != 0)
12158 						       ? DIFF_YES : DIFF_NONE;
12159 			}
12160 			else if (sp->ts_isdiff == DIFF_INSERT)
12161 			    /* When inserting trail bytes don't advance in the
12162 			     * bad word. */
12163 			    --sp->ts_fidx;
12164 			if (++sp->ts_tcharidx == sp->ts_tcharlen)
12165 			{
12166 			    /* Last byte of character. */
12167 			    if (sp->ts_isdiff == DIFF_YES)
12168 			    {
12169 				/* Correct ts_fidx for the byte length of the
12170 				 * character (we didn't check that before). */
12171 				sp->ts_fidx = sp->ts_fcharstart
12172 					    + MB_BYTE2LEN(
12173 						    fword[sp->ts_fcharstart]);
12174 
12175 				/* For changing a composing character adjust
12176 				 * the score from SCORE_SUBST to
12177 				 * SCORE_SUBCOMP. */
12178 				if (enc_utf8
12179 					&& utf_iscomposing(
12180 					    mb_ptr2char(tword
12181 						+ sp->ts_twordlen
12182 							   - sp->ts_tcharlen))
12183 					&& utf_iscomposing(
12184 					    mb_ptr2char(fword
12185 							+ sp->ts_fcharstart)))
12186 				    sp->ts_score -=
12187 						  SCORE_SUBST - SCORE_SUBCOMP;
12188 
12189 				/* For a similar character adjust score from
12190 				 * SCORE_SUBST to SCORE_SIMILAR. */
12191 				else if (!soundfold
12192 					&& slang->sl_has_map
12193 					&& similar_chars(slang,
12194 					    mb_ptr2char(tword
12195 						+ sp->ts_twordlen
12196 							   - sp->ts_tcharlen),
12197 					    mb_ptr2char(fword
12198 							+ sp->ts_fcharstart)))
12199 				    sp->ts_score -=
12200 						  SCORE_SUBST - SCORE_SIMILAR;
12201 			    }
12202 			    else if (sp->ts_isdiff == DIFF_INSERT
12203 					 && sp->ts_twordlen > sp->ts_tcharlen)
12204 			    {
12205 				p = tword + sp->ts_twordlen - sp->ts_tcharlen;
12206 				c = mb_ptr2char(p);
12207 				if (enc_utf8 && utf_iscomposing(c))
12208 				{
12209 				    /* Inserting a composing char doesn't
12210 				     * count that much. */
12211 				    sp->ts_score -= SCORE_INS - SCORE_INSCOMP;
12212 				}
12213 				else
12214 				{
12215 				    /* If the previous character was the same,
12216 				     * thus doubling a character, give a bonus
12217 				     * to the score.  Also for the soundfold
12218 				     * tree (might seem illogical but does
12219 				     * give better scores). */
12220 				    mb_ptr_back(tword, p);
12221 				    if (c == mb_ptr2char(p))
12222 					sp->ts_score -= SCORE_INS
12223 							       - SCORE_INSDUP;
12224 				}
12225 			    }
12226 
12227 			    /* Starting a new char, reset the length. */
12228 			    sp->ts_tcharlen = 0;
12229 			}
12230 		    }
12231 		    else
12232 #endif
12233 		    {
12234 			/* If we found a similar char adjust the score.
12235 			 * We do this after calling go_deeper() because
12236 			 * it's slow. */
12237 			if (newscore != 0
12238 				&& !soundfold
12239 				&& slang->sl_has_map
12240 				&& similar_chars(slang,
12241 						   c, fword[sp->ts_fidx - 1]))
12242 			    sp->ts_score -= SCORE_SUBST - SCORE_SIMILAR;
12243 		    }
12244 		}
12245 	    }
12246 	    break;
12247 
12248 	case STATE_DEL:
12249 #ifdef FEAT_MBYTE
12250 	    /* When past the first byte of a multi-byte char don't try
12251 	     * delete/insert/swap a character. */
12252 	    if (has_mbyte && sp->ts_tcharlen > 0)
12253 	    {
12254 		sp->ts_state = STATE_FINAL;
12255 		break;
12256 	    }
12257 #endif
12258 	    /*
12259 	     * Try skipping one character in the bad word (delete it).
12260 	     */
12261 	    sp->ts_state = STATE_INS_PREP;
12262 	    sp->ts_curi = 1;
12263 	    if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*')
12264 		/* Deleting a vowel at the start of a word counts less, see
12265 		 * soundalike_score(). */
12266 		newscore = 2 * SCORE_DEL / 3;
12267 	    else
12268 		newscore = SCORE_DEL;
12269 	    if (fword[sp->ts_fidx] != NUL
12270 				    && TRY_DEEPER(su, stack, depth, newscore))
12271 	    {
12272 		go_deeper(stack, depth, newscore);
12273 #ifdef DEBUG_TRIEWALK
12274 		sprintf(changename[depth], "%.*s-%s: delete %c",
12275 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12276 			fword[sp->ts_fidx]);
12277 #endif
12278 		++depth;
12279 
12280 		/* Remember what character we deleted, so that we can avoid
12281 		 * inserting it again. */
12282 		stack[depth].ts_flags |= TSF_DIDDEL;
12283 		stack[depth].ts_delidx = sp->ts_fidx;
12284 
12285 		/* Advance over the character in fword[].  Give a bonus to the
12286 		 * score if the same character is following "nn" -> "n".  It's
12287 		 * a bit illogical for soundfold tree but it does give better
12288 		 * results. */
12289 #ifdef FEAT_MBYTE
12290 		if (has_mbyte)
12291 		{
12292 		    c = mb_ptr2char(fword + sp->ts_fidx);
12293 		    stack[depth].ts_fidx += MB_BYTE2LEN(fword[sp->ts_fidx]);
12294 		    if (enc_utf8 && utf_iscomposing(c))
12295 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
12296 		    else if (c == mb_ptr2char(fword + stack[depth].ts_fidx))
12297 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
12298 		}
12299 		else
12300 #endif
12301 		{
12302 		    ++stack[depth].ts_fidx;
12303 		    if (fword[sp->ts_fidx] == fword[sp->ts_fidx + 1])
12304 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
12305 		}
12306 		break;
12307 	    }
12308 	    /*FALLTHROUGH*/
12309 
12310 	case STATE_INS_PREP:
12311 	    if (sp->ts_flags & TSF_DIDDEL)
12312 	    {
12313 		/* If we just deleted a byte then inserting won't make sense,
12314 		 * a substitute is always cheaper. */
12315 		sp->ts_state = STATE_SWAP;
12316 		break;
12317 	    }
12318 
12319 	    /* skip over NUL bytes */
12320 	    n = sp->ts_arridx;
12321 	    for (;;)
12322 	    {
12323 		if (sp->ts_curi > byts[n])
12324 		{
12325 		    /* Only NUL bytes at this node, go to next state. */
12326 		    sp->ts_state = STATE_SWAP;
12327 		    break;
12328 		}
12329 		if (byts[n + sp->ts_curi] != NUL)
12330 		{
12331 		    /* Found a byte to insert. */
12332 		    sp->ts_state = STATE_INS;
12333 		    break;
12334 		}
12335 		++sp->ts_curi;
12336 	    }
12337 	    break;
12338 
12339 	    /*FALLTHROUGH*/
12340 
12341 	case STATE_INS:
12342 	    /* Insert one byte.  Repeat this for each possible byte at this
12343 	     * node. */
12344 	    n = sp->ts_arridx;
12345 	    if (sp->ts_curi > byts[n])
12346 	    {
12347 		/* Done all bytes at this node, go to next state. */
12348 		sp->ts_state = STATE_SWAP;
12349 		break;
12350 	    }
12351 
12352 	    /* Do one more byte at this node, but:
12353 	     * - Skip NUL bytes.
12354 	     * - Skip the byte if it's equal to the byte in the word,
12355 	     *   accepting that byte is always better.
12356 	     */
12357 	    n += sp->ts_curi++;
12358 	    c = byts[n];
12359 	    if (soundfold && sp->ts_twordlen == 0 && c == '*')
12360 		/* Inserting a vowel at the start of a word counts less,
12361 		 * see soundalike_score(). */
12362 		newscore = 2 * SCORE_INS / 3;
12363 	    else
12364 		newscore = SCORE_INS;
12365 	    if (c != fword[sp->ts_fidx]
12366 				    && TRY_DEEPER(su, stack, depth, newscore))
12367 	    {
12368 		go_deeper(stack, depth, newscore);
12369 #ifdef DEBUG_TRIEWALK
12370 		sprintf(changename[depth], "%.*s-%s: insert %c",
12371 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12372 			c);
12373 #endif
12374 		++depth;
12375 		sp = &stack[depth];
12376 		tword[sp->ts_twordlen++] = c;
12377 		sp->ts_arridx = idxs[n];
12378 #ifdef FEAT_MBYTE
12379 		if (has_mbyte)
12380 		{
12381 		    fl = MB_BYTE2LEN(c);
12382 		    if (fl > 1)
12383 		    {
12384 			/* There are following bytes for the same character.
12385 			 * We must find all bytes before trying
12386 			 * delete/insert/swap/etc. */
12387 			sp->ts_tcharlen = fl;
12388 			sp->ts_tcharidx = 1;
12389 			sp->ts_isdiff = DIFF_INSERT;
12390 		    }
12391 		}
12392 		else
12393 		    fl = 1;
12394 		if (fl == 1)
12395 #endif
12396 		{
12397 		    /* If the previous character was the same, thus doubling a
12398 		     * character, give a bonus to the score.  Also for
12399 		     * soundfold words (illogical but does give a better
12400 		     * score). */
12401 		    if (sp->ts_twordlen >= 2
12402 					   && tword[sp->ts_twordlen - 2] == c)
12403 			sp->ts_score -= SCORE_INS - SCORE_INSDUP;
12404 		}
12405 	    }
12406 	    break;
12407 
12408 	case STATE_SWAP:
12409 	    /*
12410 	     * Swap two bytes in the bad word: "12" -> "21".
12411 	     * We change "fword" here, it's changed back afterwards at
12412 	     * STATE_UNSWAP.
12413 	     */
12414 	    p = fword + sp->ts_fidx;
12415 	    c = *p;
12416 	    if (c == NUL)
12417 	    {
12418 		/* End of word, can't swap or replace. */
12419 		sp->ts_state = STATE_FINAL;
12420 		break;
12421 	    }
12422 
12423 	    /* Don't swap if the first character is not a word character.
12424 	     * SWAP3 etc. also don't make sense then. */
12425 	    if (!soundfold && !spell_iswordp(p, curbuf))
12426 	    {
12427 		sp->ts_state = STATE_REP_INI;
12428 		break;
12429 	    }
12430 
12431 #ifdef FEAT_MBYTE
12432 	    if (has_mbyte)
12433 	    {
12434 		n = mb_cptr2len(p);
12435 		c = mb_ptr2char(p);
12436 		if (p[n] == NUL)
12437 		    c2 = NUL;
12438 		else if (!soundfold && !spell_iswordp(p + n, curbuf))
12439 		    c2 = c; /* don't swap non-word char */
12440 		else
12441 		    c2 = mb_ptr2char(p + n);
12442 	    }
12443 	    else
12444 #endif
12445 	    {
12446 		if (p[1] == NUL)
12447 		    c2 = NUL;
12448 		else if (!soundfold && !spell_iswordp(p + 1, curbuf))
12449 		    c2 = c; /* don't swap non-word char */
12450 		else
12451 		    c2 = p[1];
12452 	    }
12453 
12454 	    /* When the second character is NUL we can't swap. */
12455 	    if (c2 == NUL)
12456 	    {
12457 		sp->ts_state = STATE_REP_INI;
12458 		break;
12459 	    }
12460 
12461 	    /* When characters are identical, swap won't do anything.
12462 	     * Also get here if the second char is not a word character. */
12463 	    if (c == c2)
12464 	    {
12465 		sp->ts_state = STATE_SWAP3;
12466 		break;
12467 	    }
12468 	    if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP))
12469 	    {
12470 		go_deeper(stack, depth, SCORE_SWAP);
12471 #ifdef DEBUG_TRIEWALK
12472 		sprintf(changename[depth], "%.*s-%s: swap %c and %c",
12473 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12474 			c, c2);
12475 #endif
12476 		sp->ts_state = STATE_UNSWAP;
12477 		++depth;
12478 #ifdef FEAT_MBYTE
12479 		if (has_mbyte)
12480 		{
12481 		    fl = mb_char2len(c2);
12482 		    mch_memmove(p, p + n, fl);
12483 		    mb_char2bytes(c, p + fl);
12484 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
12485 		}
12486 		else
12487 #endif
12488 		{
12489 		    p[0] = c2;
12490 		    p[1] = c;
12491 		    stack[depth].ts_fidxtry = sp->ts_fidx + 2;
12492 		}
12493 	    }
12494 	    else
12495 		/* If this swap doesn't work then SWAP3 won't either. */
12496 		sp->ts_state = STATE_REP_INI;
12497 	    break;
12498 
12499 	case STATE_UNSWAP:
12500 	    /* Undo the STATE_SWAP swap: "21" -> "12". */
12501 	    p = fword + sp->ts_fidx;
12502 #ifdef FEAT_MBYTE
12503 	    if (has_mbyte)
12504 	    {
12505 		n = MB_BYTE2LEN(*p);
12506 		c = mb_ptr2char(p + n);
12507 		mch_memmove(p + MB_BYTE2LEN(p[n]), p, n);
12508 		mb_char2bytes(c, p);
12509 	    }
12510 	    else
12511 #endif
12512 	    {
12513 		c = *p;
12514 		*p = p[1];
12515 		p[1] = c;
12516 	    }
12517 	    /*FALLTHROUGH*/
12518 
12519 	case STATE_SWAP3:
12520 	    /* Swap two bytes, skipping one: "123" -> "321".  We change
12521 	     * "fword" here, it's changed back afterwards at STATE_UNSWAP3. */
12522 	    p = fword + sp->ts_fidx;
12523 #ifdef FEAT_MBYTE
12524 	    if (has_mbyte)
12525 	    {
12526 		n = mb_cptr2len(p);
12527 		c = mb_ptr2char(p);
12528 		fl = mb_cptr2len(p + n);
12529 		c2 = mb_ptr2char(p + n);
12530 		if (!soundfold && !spell_iswordp(p + n + fl, curbuf))
12531 		    c3 = c;	/* don't swap non-word char */
12532 		else
12533 		    c3 = mb_ptr2char(p + n + fl);
12534 	    }
12535 	    else
12536 #endif
12537 	    {
12538 		c = *p;
12539 		c2 = p[1];
12540 		if (!soundfold && !spell_iswordp(p + 2, curbuf))
12541 		    c3 = c;	/* don't swap non-word char */
12542 		else
12543 		    c3 = p[2];
12544 	    }
12545 
12546 	    /* When characters are identical: "121" then SWAP3 result is
12547 	     * identical, ROT3L result is same as SWAP: "211", ROT3L result is
12548 	     * same as SWAP on next char: "112".  Thus skip all swapping.
12549 	     * Also skip when c3 is NUL.
12550 	     * Also get here when the third character is not a word character.
12551 	     * Second character may any char: "a.b" -> "b.a" */
12552 	    if (c == c3 || c3 == NUL)
12553 	    {
12554 		sp->ts_state = STATE_REP_INI;
12555 		break;
12556 	    }
12557 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12558 	    {
12559 		go_deeper(stack, depth, SCORE_SWAP3);
12560 #ifdef DEBUG_TRIEWALK
12561 		sprintf(changename[depth], "%.*s-%s: swap3 %c and %c",
12562 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12563 			c, c3);
12564 #endif
12565 		sp->ts_state = STATE_UNSWAP3;
12566 		++depth;
12567 #ifdef FEAT_MBYTE
12568 		if (has_mbyte)
12569 		{
12570 		    tl = mb_char2len(c3);
12571 		    mch_memmove(p, p + n + fl, tl);
12572 		    mb_char2bytes(c2, p + tl);
12573 		    mb_char2bytes(c, p + fl + tl);
12574 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl + tl;
12575 		}
12576 		else
12577 #endif
12578 		{
12579 		    p[0] = p[2];
12580 		    p[2] = c;
12581 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12582 		}
12583 	    }
12584 	    else
12585 		sp->ts_state = STATE_REP_INI;
12586 	    break;
12587 
12588 	case STATE_UNSWAP3:
12589 	    /* Undo STATE_SWAP3: "321" -> "123" */
12590 	    p = fword + sp->ts_fidx;
12591 #ifdef FEAT_MBYTE
12592 	    if (has_mbyte)
12593 	    {
12594 		n = MB_BYTE2LEN(*p);
12595 		c2 = mb_ptr2char(p + n);
12596 		fl = MB_BYTE2LEN(p[n]);
12597 		c = mb_ptr2char(p + n + fl);
12598 		tl = MB_BYTE2LEN(p[n + fl]);
12599 		mch_memmove(p + fl + tl, p, n);
12600 		mb_char2bytes(c, p);
12601 		mb_char2bytes(c2, p + tl);
12602 		p = p + tl;
12603 	    }
12604 	    else
12605 #endif
12606 	    {
12607 		c = *p;
12608 		*p = p[2];
12609 		p[2] = c;
12610 		++p;
12611 	    }
12612 
12613 	    if (!soundfold && !spell_iswordp(p, curbuf))
12614 	    {
12615 		/* Middle char is not a word char, skip the rotate.  First and
12616 		 * third char were already checked at swap and swap3. */
12617 		sp->ts_state = STATE_REP_INI;
12618 		break;
12619 	    }
12620 
12621 	    /* Rotate three characters left: "123" -> "231".  We change
12622 	     * "fword" here, it's changed back afterwards at STATE_UNROT3L. */
12623 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12624 	    {
12625 		go_deeper(stack, depth, SCORE_SWAP3);
12626 #ifdef DEBUG_TRIEWALK
12627 		p = fword + sp->ts_fidx;
12628 		sprintf(changename[depth], "%.*s-%s: rotate left %c%c%c",
12629 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12630 			p[0], p[1], p[2]);
12631 #endif
12632 		sp->ts_state = STATE_UNROT3L;
12633 		++depth;
12634 		p = fword + sp->ts_fidx;
12635 #ifdef FEAT_MBYTE
12636 		if (has_mbyte)
12637 		{
12638 		    n = mb_cptr2len(p);
12639 		    c = mb_ptr2char(p);
12640 		    fl = mb_cptr2len(p + n);
12641 		    fl += mb_cptr2len(p + n + fl);
12642 		    mch_memmove(p, p + n, fl);
12643 		    mb_char2bytes(c, p + fl);
12644 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
12645 		}
12646 		else
12647 #endif
12648 		{
12649 		    c = *p;
12650 		    *p = p[1];
12651 		    p[1] = p[2];
12652 		    p[2] = c;
12653 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12654 		}
12655 	    }
12656 	    else
12657 		sp->ts_state = STATE_REP_INI;
12658 	    break;
12659 
12660 	case STATE_UNROT3L:
12661 	    /* Undo ROT3L: "231" -> "123" */
12662 	    p = fword + sp->ts_fidx;
12663 #ifdef FEAT_MBYTE
12664 	    if (has_mbyte)
12665 	    {
12666 		n = MB_BYTE2LEN(*p);
12667 		n += MB_BYTE2LEN(p[n]);
12668 		c = mb_ptr2char(p + n);
12669 		tl = MB_BYTE2LEN(p[n]);
12670 		mch_memmove(p + tl, p, n);
12671 		mb_char2bytes(c, p);
12672 	    }
12673 	    else
12674 #endif
12675 	    {
12676 		c = p[2];
12677 		p[2] = p[1];
12678 		p[1] = *p;
12679 		*p = c;
12680 	    }
12681 
12682 	    /* Rotate three bytes right: "123" -> "312".  We change "fword"
12683 	     * here, it's changed back afterwards at STATE_UNROT3R. */
12684 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12685 	    {
12686 		go_deeper(stack, depth, SCORE_SWAP3);
12687 #ifdef DEBUG_TRIEWALK
12688 		p = fword + sp->ts_fidx;
12689 		sprintf(changename[depth], "%.*s-%s: rotate right %c%c%c",
12690 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12691 			p[0], p[1], p[2]);
12692 #endif
12693 		sp->ts_state = STATE_UNROT3R;
12694 		++depth;
12695 		p = fword + sp->ts_fidx;
12696 #ifdef FEAT_MBYTE
12697 		if (has_mbyte)
12698 		{
12699 		    n = mb_cptr2len(p);
12700 		    n += mb_cptr2len(p + n);
12701 		    c = mb_ptr2char(p + n);
12702 		    tl = mb_cptr2len(p + n);
12703 		    mch_memmove(p + tl, p, n);
12704 		    mb_char2bytes(c, p);
12705 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + tl;
12706 		}
12707 		else
12708 #endif
12709 		{
12710 		    c = p[2];
12711 		    p[2] = p[1];
12712 		    p[1] = *p;
12713 		    *p = c;
12714 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12715 		}
12716 	    }
12717 	    else
12718 		sp->ts_state = STATE_REP_INI;
12719 	    break;
12720 
12721 	case STATE_UNROT3R:
12722 	    /* Undo ROT3R: "312" -> "123" */
12723 	    p = fword + sp->ts_fidx;
12724 #ifdef FEAT_MBYTE
12725 	    if (has_mbyte)
12726 	    {
12727 		c = mb_ptr2char(p);
12728 		tl = MB_BYTE2LEN(*p);
12729 		n = MB_BYTE2LEN(p[tl]);
12730 		n += MB_BYTE2LEN(p[tl + n]);
12731 		mch_memmove(p, p + tl, n);
12732 		mb_char2bytes(c, p + n);
12733 	    }
12734 	    else
12735 #endif
12736 	    {
12737 		c = *p;
12738 		*p = p[1];
12739 		p[1] = p[2];
12740 		p[2] = c;
12741 	    }
12742 	    /*FALLTHROUGH*/
12743 
12744 	case STATE_REP_INI:
12745 	    /* Check if matching with REP items from the .aff file would work.
12746 	     * Quickly skip if:
12747 	     * - there are no REP items and we are not in the soundfold trie
12748 	     * - the score is going to be too high anyway
12749 	     * - already applied a REP item or swapped here  */
12750 	    if ((lp->lp_replang == NULL && !soundfold)
12751 		    || sp->ts_score + SCORE_REP >= su->su_maxscore
12752 		    || sp->ts_fidx < sp->ts_fidxtry)
12753 	    {
12754 		sp->ts_state = STATE_FINAL;
12755 		break;
12756 	    }
12757 
12758 	    /* Use the first byte to quickly find the first entry that may
12759 	     * match.  If the index is -1 there is none. */
12760 	    if (soundfold)
12761 		sp->ts_curi = slang->sl_repsal_first[fword[sp->ts_fidx]];
12762 	    else
12763 		sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]];
12764 
12765 	    if (sp->ts_curi < 0)
12766 	    {
12767 		sp->ts_state = STATE_FINAL;
12768 		break;
12769 	    }
12770 
12771 	    sp->ts_state = STATE_REP;
12772 	    /*FALLTHROUGH*/
12773 
12774 	case STATE_REP:
12775 	    /* Try matching with REP items from the .aff file.  For each match
12776 	     * replace the characters and check if the resulting word is
12777 	     * valid. */
12778 	    p = fword + sp->ts_fidx;
12779 
12780 	    if (soundfold)
12781 		gap = &slang->sl_repsal;
12782 	    else
12783 		gap = &lp->lp_replang->sl_rep;
12784 	    while (sp->ts_curi < gap->ga_len)
12785 	    {
12786 		ftp = (fromto_T *)gap->ga_data + sp->ts_curi++;
12787 		if (*ftp->ft_from != *p)
12788 		{
12789 		    /* past possible matching entries */
12790 		    sp->ts_curi = gap->ga_len;
12791 		    break;
12792 		}
12793 		if (STRNCMP(ftp->ft_from, p, STRLEN(ftp->ft_from)) == 0
12794 			&& TRY_DEEPER(su, stack, depth, SCORE_REP))
12795 		{
12796 		    go_deeper(stack, depth, SCORE_REP);
12797 #ifdef DEBUG_TRIEWALK
12798 		    sprintf(changename[depth], "%.*s-%s: replace %s with %s",
12799 			    sp->ts_twordlen, tword, fword + sp->ts_fidx,
12800 			    ftp->ft_from, ftp->ft_to);
12801 #endif
12802 		    /* Need to undo this afterwards. */
12803 		    sp->ts_state = STATE_REP_UNDO;
12804 
12805 		    /* Change the "from" to the "to" string. */
12806 		    ++depth;
12807 		    fl = (int)STRLEN(ftp->ft_from);
12808 		    tl = (int)STRLEN(ftp->ft_to);
12809 		    if (fl != tl)
12810 		    {
12811 			STRMOVE(p + tl, p + fl);
12812 			repextra += tl - fl;
12813 		    }
12814 		    mch_memmove(p, ftp->ft_to, tl);
12815 		    stack[depth].ts_fidxtry = sp->ts_fidx + tl;
12816 #ifdef FEAT_MBYTE
12817 		    stack[depth].ts_tcharlen = 0;
12818 #endif
12819 		    break;
12820 		}
12821 	    }
12822 
12823 	    if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP)
12824 		/* No (more) matches. */
12825 		sp->ts_state = STATE_FINAL;
12826 
12827 	    break;
12828 
12829 	case STATE_REP_UNDO:
12830 	    /* Undo a REP replacement and continue with the next one. */
12831 	    if (soundfold)
12832 		gap = &slang->sl_repsal;
12833 	    else
12834 		gap = &lp->lp_replang->sl_rep;
12835 	    ftp = (fromto_T *)gap->ga_data + sp->ts_curi - 1;
12836 	    fl = (int)STRLEN(ftp->ft_from);
12837 	    tl = (int)STRLEN(ftp->ft_to);
12838 	    p = fword + sp->ts_fidx;
12839 	    if (fl != tl)
12840 	    {
12841 		STRMOVE(p + fl, p + tl);
12842 		repextra -= tl - fl;
12843 	    }
12844 	    mch_memmove(p, ftp->ft_from, fl);
12845 	    sp->ts_state = STATE_REP;
12846 	    break;
12847 
12848 	default:
12849 	    /* Did all possible states at this level, go up one level. */
12850 	    --depth;
12851 
12852 	    if (depth >= 0 && stack[depth].ts_prefixdepth == PFD_PREFIXTREE)
12853 	    {
12854 		/* Continue in or go back to the prefix tree. */
12855 		byts = pbyts;
12856 		idxs = pidxs;
12857 	    }
12858 
12859 	    /* Don't check for CTRL-C too often, it takes time. */
12860 	    if (--breakcheckcount == 0)
12861 	    {
12862 		ui_breakcheck();
12863 		breakcheckcount = 1000;
12864 	    }
12865 	}
12866     }
12867 }
12868 
12869 
12870 /*
12871  * Go one level deeper in the tree.
12872  */
12873     static void
12874 go_deeper(stack, depth, score_add)
12875     trystate_T	*stack;
12876     int		depth;
12877     int		score_add;
12878 {
12879     stack[depth + 1] = stack[depth];
12880     stack[depth + 1].ts_state = STATE_START;
12881     stack[depth + 1].ts_score = stack[depth].ts_score + score_add;
12882     stack[depth + 1].ts_curi = 1;	/* start just after length byte */
12883     stack[depth + 1].ts_flags = 0;
12884 }
12885 
12886 #ifdef FEAT_MBYTE
12887 /*
12888  * Case-folding may change the number of bytes: Count nr of chars in
12889  * fword[flen] and return the byte length of that many chars in "word".
12890  */
12891     static int
12892 nofold_len(fword, flen, word)
12893     char_u	*fword;
12894     int		flen;
12895     char_u	*word;
12896 {
12897     char_u	*p;
12898     int		i = 0;
12899 
12900     for (p = fword; p < fword + flen; mb_ptr_adv(p))
12901 	++i;
12902     for (p = word; i > 0; mb_ptr_adv(p))
12903 	--i;
12904     return (int)(p - word);
12905 }
12906 #endif
12907 
12908 /*
12909  * "fword" is a good word with case folded.  Find the matching keep-case
12910  * words and put it in "kword".
12911  * Theoretically there could be several keep-case words that result in the
12912  * same case-folded word, but we only find one...
12913  */
12914     static void
12915 find_keepcap_word(slang, fword, kword)
12916     slang_T	*slang;
12917     char_u	*fword;
12918     char_u	*kword;
12919 {
12920     char_u	uword[MAXWLEN];		/* "fword" in upper-case */
12921     int		depth;
12922     idx_T	tryidx;
12923 
12924     /* The following arrays are used at each depth in the tree. */
12925     idx_T	arridx[MAXWLEN];
12926     int		round[MAXWLEN];
12927     int		fwordidx[MAXWLEN];
12928     int		uwordidx[MAXWLEN];
12929     int		kwordlen[MAXWLEN];
12930 
12931     int		flen, ulen;
12932     int		l;
12933     int		len;
12934     int		c;
12935     idx_T	lo, hi, m;
12936     char_u	*p;
12937     char_u	*byts = slang->sl_kbyts;    /* array with bytes of the words */
12938     idx_T	*idxs = slang->sl_kidxs;    /* array with indexes */
12939 
12940     if (byts == NULL)
12941     {
12942 	/* array is empty: "cannot happen" */
12943 	*kword = NUL;
12944 	return;
12945     }
12946 
12947     /* Make an all-cap version of "fword". */
12948     allcap_copy(fword, uword);
12949 
12950     /*
12951      * Each character needs to be tried both case-folded and upper-case.
12952      * All this gets very complicated if we keep in mind that changing case
12953      * may change the byte length of a multi-byte character...
12954      */
12955     depth = 0;
12956     arridx[0] = 0;
12957     round[0] = 0;
12958     fwordidx[0] = 0;
12959     uwordidx[0] = 0;
12960     kwordlen[0] = 0;
12961     while (depth >= 0)
12962     {
12963 	if (fword[fwordidx[depth]] == NUL)
12964 	{
12965 	    /* We are at the end of "fword".  If the tree allows a word to end
12966 	     * here we have found a match. */
12967 	    if (byts[arridx[depth] + 1] == 0)
12968 	    {
12969 		kword[kwordlen[depth]] = NUL;
12970 		return;
12971 	    }
12972 
12973 	    /* kword is getting too long, continue one level up */
12974 	    --depth;
12975 	}
12976 	else if (++round[depth] > 2)
12977 	{
12978 	    /* tried both fold-case and upper-case character, continue one
12979 	     * level up */
12980 	    --depth;
12981 	}
12982 	else
12983 	{
12984 	    /*
12985 	     * round[depth] == 1: Try using the folded-case character.
12986 	     * round[depth] == 2: Try using the upper-case character.
12987 	     */
12988 #ifdef FEAT_MBYTE
12989 	    if (has_mbyte)
12990 	    {
12991 		flen = mb_cptr2len(fword + fwordidx[depth]);
12992 		ulen = mb_cptr2len(uword + uwordidx[depth]);
12993 	    }
12994 	    else
12995 #endif
12996 		ulen = flen = 1;
12997 	    if (round[depth] == 1)
12998 	    {
12999 		p = fword + fwordidx[depth];
13000 		l = flen;
13001 	    }
13002 	    else
13003 	    {
13004 		p = uword + uwordidx[depth];
13005 		l = ulen;
13006 	    }
13007 
13008 	    for (tryidx = arridx[depth]; l > 0; --l)
13009 	    {
13010 		/* Perform a binary search in the list of accepted bytes. */
13011 		len = byts[tryidx++];
13012 		c = *p++;
13013 		lo = tryidx;
13014 		hi = tryidx + len - 1;
13015 		while (lo < hi)
13016 		{
13017 		    m = (lo + hi) / 2;
13018 		    if (byts[m] > c)
13019 			hi = m - 1;
13020 		    else if (byts[m] < c)
13021 			lo = m + 1;
13022 		    else
13023 		    {
13024 			lo = hi = m;
13025 			break;
13026 		    }
13027 		}
13028 
13029 		/* Stop if there is no matching byte. */
13030 		if (hi < lo || byts[lo] != c)
13031 		    break;
13032 
13033 		/* Continue at the child (if there is one). */
13034 		tryidx = idxs[lo];
13035 	    }
13036 
13037 	    if (l == 0)
13038 	    {
13039 		/*
13040 		 * Found the matching char.  Copy it to "kword" and go a
13041 		 * level deeper.
13042 		 */
13043 		if (round[depth] == 1)
13044 		{
13045 		    STRNCPY(kword + kwordlen[depth], fword + fwordidx[depth],
13046 									flen);
13047 		    kwordlen[depth + 1] = kwordlen[depth] + flen;
13048 		}
13049 		else
13050 		{
13051 		    STRNCPY(kword + kwordlen[depth], uword + uwordidx[depth],
13052 									ulen);
13053 		    kwordlen[depth + 1] = kwordlen[depth] + ulen;
13054 		}
13055 		fwordidx[depth + 1] = fwordidx[depth] + flen;
13056 		uwordidx[depth + 1] = uwordidx[depth] + ulen;
13057 
13058 		++depth;
13059 		arridx[depth] = tryidx;
13060 		round[depth] = 0;
13061 	    }
13062 	}
13063     }
13064 
13065     /* Didn't find it: "cannot happen". */
13066     *kword = NUL;
13067 }
13068 
13069 /*
13070  * Compute the sound-a-like score for suggestions in su->su_ga and add them to
13071  * su->su_sga.
13072  */
13073     static void
13074 score_comp_sal(su)
13075     suginfo_T	*su;
13076 {
13077     langp_T	*lp;
13078     char_u	badsound[MAXWLEN];
13079     int		i;
13080     suggest_T   *stp;
13081     suggest_T   *sstp;
13082     int		score;
13083     int		lpi;
13084 
13085     if (ga_grow(&su->su_sga, su->su_ga.ga_len) == FAIL)
13086 	return;
13087 
13088     /*	Use the sound-folding of the first language that supports it. */
13089     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
13090     {
13091 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
13092 	if (lp->lp_slang->sl_sal.ga_len > 0)
13093 	{
13094 	    /* soundfold the bad word */
13095 	    spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, badsound);
13096 
13097 	    for (i = 0; i < su->su_ga.ga_len; ++i)
13098 	    {
13099 		stp = &SUG(su->su_ga, i);
13100 
13101 		/* Case-fold the suggested word, sound-fold it and compute the
13102 		 * sound-a-like score. */
13103 		score = stp_sal_score(stp, su, lp->lp_slang, badsound);
13104 		if (score < SCORE_MAXMAX)
13105 		{
13106 		    /* Add the suggestion. */
13107 		    sstp = &SUG(su->su_sga, su->su_sga.ga_len);
13108 		    sstp->st_word = vim_strsave(stp->st_word);
13109 		    if (sstp->st_word != NULL)
13110 		    {
13111 			sstp->st_wordlen = stp->st_wordlen;
13112 			sstp->st_score = score;
13113 			sstp->st_altscore = 0;
13114 			sstp->st_orglen = stp->st_orglen;
13115 			++su->su_sga.ga_len;
13116 		    }
13117 		}
13118 	    }
13119 	    break;
13120 	}
13121     }
13122 }
13123 
13124 /*
13125  * Combine the list of suggestions in su->su_ga and su->su_sga.
13126  * They are intwined.
13127  */
13128     static void
13129 score_combine(su)
13130     suginfo_T	*su;
13131 {
13132     int		i;
13133     int		j;
13134     garray_T	ga;
13135     garray_T	*gap;
13136     langp_T	*lp;
13137     suggest_T	*stp;
13138     char_u	*p;
13139     char_u	badsound[MAXWLEN];
13140     int		round;
13141     int		lpi;
13142     slang_T	*slang = NULL;
13143 
13144     /* Add the alternate score to su_ga. */
13145     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
13146     {
13147 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
13148 	if (lp->lp_slang->sl_sal.ga_len > 0)
13149 	{
13150 	    /* soundfold the bad word */
13151 	    slang = lp->lp_slang;
13152 	    spell_soundfold(slang, su->su_fbadword, TRUE, badsound);
13153 
13154 	    for (i = 0; i < su->su_ga.ga_len; ++i)
13155 	    {
13156 		stp = &SUG(su->su_ga, i);
13157 		stp->st_altscore = stp_sal_score(stp, su, slang, badsound);
13158 		if (stp->st_altscore == SCORE_MAXMAX)
13159 		    stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4;
13160 		else
13161 		    stp->st_score = (stp->st_score * 3
13162 						  + stp->st_altscore) / 4;
13163 		stp->st_salscore = FALSE;
13164 	    }
13165 	    break;
13166 	}
13167     }
13168 
13169     if (slang == NULL)	/* Using "double" without sound folding. */
13170     {
13171 	(void)cleanup_suggestions(&su->su_ga, su->su_maxscore,
13172 							     su->su_maxcount);
13173 	return;
13174     }
13175 
13176     /* Add the alternate score to su_sga. */
13177     for (i = 0; i < su->su_sga.ga_len; ++i)
13178     {
13179 	stp = &SUG(su->su_sga, i);
13180 	stp->st_altscore = spell_edit_score(slang,
13181 						su->su_badword, stp->st_word);
13182 	if (stp->st_score == SCORE_MAXMAX)
13183 	    stp->st_score = (SCORE_BIG * 7 + stp->st_altscore) / 8;
13184 	else
13185 	    stp->st_score = (stp->st_score * 7 + stp->st_altscore) / 8;
13186 	stp->st_salscore = TRUE;
13187     }
13188 
13189     /* Remove bad suggestions, sort the suggestions and truncate at "maxcount"
13190      * for both lists. */
13191     check_suggestions(su, &su->su_ga);
13192     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
13193     check_suggestions(su, &su->su_sga);
13194     (void)cleanup_suggestions(&su->su_sga, su->su_maxscore, su->su_maxcount);
13195 
13196     ga_init2(&ga, (int)sizeof(suginfo_T), 1);
13197     if (ga_grow(&ga, su->su_ga.ga_len + su->su_sga.ga_len) == FAIL)
13198 	return;
13199 
13200     stp = &SUG(ga, 0);
13201     for (i = 0; i < su->su_ga.ga_len || i < su->su_sga.ga_len; ++i)
13202     {
13203 	/* round 1: get a suggestion from su_ga
13204 	 * round 2: get a suggestion from su_sga */
13205 	for (round = 1; round <= 2; ++round)
13206 	{
13207 	    gap = round == 1 ? &su->su_ga : &su->su_sga;
13208 	    if (i < gap->ga_len)
13209 	    {
13210 		/* Don't add a word if it's already there. */
13211 		p = SUG(*gap, i).st_word;
13212 		for (j = 0; j < ga.ga_len; ++j)
13213 		    if (STRCMP(stp[j].st_word, p) == 0)
13214 			break;
13215 		if (j == ga.ga_len)
13216 		    stp[ga.ga_len++] = SUG(*gap, i);
13217 		else
13218 		    vim_free(p);
13219 	    }
13220 	}
13221     }
13222 
13223     ga_clear(&su->su_ga);
13224     ga_clear(&su->su_sga);
13225 
13226     /* Truncate the list to the number of suggestions that will be displayed. */
13227     if (ga.ga_len > su->su_maxcount)
13228     {
13229 	for (i = su->su_maxcount; i < ga.ga_len; ++i)
13230 	    vim_free(stp[i].st_word);
13231 	ga.ga_len = su->su_maxcount;
13232     }
13233 
13234     su->su_ga = ga;
13235 }
13236 
13237 /*
13238  * For the goodword in "stp" compute the soundalike score compared to the
13239  * badword.
13240  */
13241     static int
13242 stp_sal_score(stp, su, slang, badsound)
13243     suggest_T	*stp;
13244     suginfo_T	*su;
13245     slang_T	*slang;
13246     char_u	*badsound;	/* sound-folded badword */
13247 {
13248     char_u	*p;
13249     char_u	*pbad;
13250     char_u	*pgood;
13251     char_u	badsound2[MAXWLEN];
13252     char_u	fword[MAXWLEN];
13253     char_u	goodsound[MAXWLEN];
13254     char_u	goodword[MAXWLEN];
13255     int		lendiff;
13256 
13257     lendiff = (int)(su->su_badlen - stp->st_orglen);
13258     if (lendiff >= 0)
13259 	pbad = badsound;
13260     else
13261     {
13262 	/* soundfold the bad word with more characters following */
13263 	(void)spell_casefold(su->su_badptr, stp->st_orglen, fword, MAXWLEN);
13264 
13265 	/* When joining two words the sound often changes a lot.  E.g., "t he"
13266 	 * sounds like "t h" while "the" sounds like "@".  Avoid that by
13267 	 * removing the space.  Don't do it when the good word also contains a
13268 	 * space. */
13269 	if (vim_iswhite(su->su_badptr[su->su_badlen])
13270 					 && *skiptowhite(stp->st_word) == NUL)
13271 	    for (p = fword; *(p = skiptowhite(p)) != NUL; )
13272 		STRMOVE(p, p + 1);
13273 
13274 	spell_soundfold(slang, fword, TRUE, badsound2);
13275 	pbad = badsound2;
13276     }
13277 
13278     if (lendiff > 0)
13279     {
13280 	/* Add part of the bad word to the good word, so that we soundfold
13281 	 * what replaces the bad word. */
13282 	STRCPY(goodword, stp->st_word);
13283 	vim_strncpy(goodword + stp->st_wordlen,
13284 			    su->su_badptr + su->su_badlen - lendiff, lendiff);
13285 	pgood = goodword;
13286     }
13287     else
13288 	pgood = stp->st_word;
13289 
13290     /* Sound-fold the word and compute the score for the difference. */
13291     spell_soundfold(slang, pgood, FALSE, goodsound);
13292 
13293     return soundalike_score(goodsound, pbad);
13294 }
13295 
13296 /* structure used to store soundfolded words that add_sound_suggest() has
13297  * handled already. */
13298 typedef struct
13299 {
13300     short	sft_score;	/* lowest score used */
13301     char_u	sft_word[1];    /* soundfolded word, actually longer */
13302 } sftword_T;
13303 
13304 static sftword_T dumsft;
13305 #define HIKEY2SFT(p)  ((sftword_T *)(p - (dumsft.sft_word - (char_u *)&dumsft)))
13306 #define HI2SFT(hi)     HIKEY2SFT((hi)->hi_key)
13307 
13308 /*
13309  * Prepare for calling suggest_try_soundalike().
13310  */
13311     static void
13312 suggest_try_soundalike_prep()
13313 {
13314     langp_T	*lp;
13315     int		lpi;
13316     slang_T	*slang;
13317 
13318     /* Do this for all languages that support sound folding and for which a
13319      * .sug file has been loaded. */
13320     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
13321     {
13322 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
13323 	slang = lp->lp_slang;
13324 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13325 	    /* prepare the hashtable used by add_sound_suggest() */
13326 	    hash_init(&slang->sl_sounddone);
13327     }
13328 }
13329 
13330 /*
13331  * Find suggestions by comparing the word in a sound-a-like form.
13332  * Note: This doesn't support postponed prefixes.
13333  */
13334     static void
13335 suggest_try_soundalike(su)
13336     suginfo_T	*su;
13337 {
13338     char_u	salword[MAXWLEN];
13339     langp_T	*lp;
13340     int		lpi;
13341     slang_T	*slang;
13342 
13343     /* Do this for all languages that support sound folding and for which a
13344      * .sug file has been loaded. */
13345     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
13346     {
13347 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
13348 	slang = lp->lp_slang;
13349 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13350 	{
13351 	    /* soundfold the bad word */
13352 	    spell_soundfold(slang, su->su_fbadword, TRUE, salword);
13353 
13354 	    /* try all kinds of inserts/deletes/swaps/etc. */
13355 	    /* TODO: also soundfold the next words, so that we can try joining
13356 	     * and splitting */
13357 	    suggest_trie_walk(su, lp, salword, TRUE);
13358 	}
13359     }
13360 }
13361 
13362 /*
13363  * Finish up after calling suggest_try_soundalike().
13364  */
13365     static void
13366 suggest_try_soundalike_finish()
13367 {
13368     langp_T	*lp;
13369     int		lpi;
13370     slang_T	*slang;
13371     int		todo;
13372     hashitem_T	*hi;
13373 
13374     /* Do this for all languages that support sound folding and for which a
13375      * .sug file has been loaded. */
13376     for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
13377     {
13378 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
13379 	slang = lp->lp_slang;
13380 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13381 	{
13382 	    /* Free the info about handled words. */
13383 	    todo = (int)slang->sl_sounddone.ht_used;
13384 	    for (hi = slang->sl_sounddone.ht_array; todo > 0; ++hi)
13385 		if (!HASHITEM_EMPTY(hi))
13386 		{
13387 		    vim_free(HI2SFT(hi));
13388 		    --todo;
13389 		}
13390 
13391 	    /* Clear the hashtable, it may also be used by another region. */
13392 	    hash_clear(&slang->sl_sounddone);
13393 	    hash_init(&slang->sl_sounddone);
13394 	}
13395     }
13396 }
13397 
13398 /*
13399  * A match with a soundfolded word is found.  Add the good word(s) that
13400  * produce this soundfolded word.
13401  */
13402     static void
13403 add_sound_suggest(su, goodword, score, lp)
13404     suginfo_T	*su;
13405     char_u	*goodword;
13406     int		score;		/* soundfold score  */
13407     langp_T	*lp;
13408 {
13409     slang_T	*slang = lp->lp_slang;	/* language for sound folding */
13410     int		sfwordnr;
13411     char_u	*nrline;
13412     int		orgnr;
13413     char_u	theword[MAXWLEN];
13414     int		i;
13415     int		wlen;
13416     char_u	*byts;
13417     idx_T	*idxs;
13418     int		n;
13419     int		wordcount;
13420     int		wc;
13421     int		goodscore;
13422     hash_T	hash;
13423     hashitem_T  *hi;
13424     sftword_T	*sft;
13425     int		bc, gc;
13426     int		limit;
13427 
13428     /*
13429      * It's very well possible that the same soundfold word is found several
13430      * times with different scores.  Since the following is quite slow only do
13431      * the words that have a better score than before.  Use a hashtable to
13432      * remember the words that have been done.
13433      */
13434     hash = hash_hash(goodword);
13435     hi = hash_lookup(&slang->sl_sounddone, goodword, hash);
13436     if (HASHITEM_EMPTY(hi))
13437     {
13438 	sft = (sftword_T *)alloc((unsigned)(sizeof(sftword_T)
13439 							 + STRLEN(goodword)));
13440 	if (sft != NULL)
13441 	{
13442 	    sft->sft_score = score;
13443 	    STRCPY(sft->sft_word, goodword);
13444 	    hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
13445 	}
13446     }
13447     else
13448     {
13449 	sft = HI2SFT(hi);
13450 	if (score >= sft->sft_score)
13451 	    return;
13452 	sft->sft_score = score;
13453     }
13454 
13455     /*
13456      * Find the word nr in the soundfold tree.
13457      */
13458     sfwordnr = soundfold_find(slang, goodword);
13459     if (sfwordnr < 0)
13460     {
13461 	EMSG2(_(e_intern2), "add_sound_suggest()");
13462 	return;
13463     }
13464 
13465     /*
13466      * go over the list of good words that produce this soundfold word
13467      */
13468     nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)(sfwordnr + 1), FALSE);
13469     orgnr = 0;
13470     while (*nrline != NUL)
13471     {
13472 	/* The wordnr was stored in a minimal nr of bytes as an offset to the
13473 	 * previous wordnr. */
13474 	orgnr += bytes2offset(&nrline);
13475 
13476 	byts = slang->sl_fbyts;
13477 	idxs = slang->sl_fidxs;
13478 
13479 	/* Lookup the word "orgnr" one of the two tries. */
13480 	n = 0;
13481 	wlen = 0;
13482 	wordcount = 0;
13483 	for (;;)
13484 	{
13485 	    i = 1;
13486 	    if (wordcount == orgnr && byts[n + 1] == NUL)
13487 		break;	/* found end of word */
13488 
13489 	    if (byts[n + 1] == NUL)
13490 		++wordcount;
13491 
13492 	    /* skip over the NUL bytes */
13493 	    for ( ; byts[n + i] == NUL; ++i)
13494 		if (i > byts[n])	/* safety check */
13495 		{
13496 		    STRCPY(theword + wlen, "BAD");
13497 		    goto badword;
13498 		}
13499 
13500 	    /* One of the siblings must have the word. */
13501 	    for ( ; i < byts[n]; ++i)
13502 	    {
13503 		wc = idxs[idxs[n + i]];	/* nr of words under this byte */
13504 		if (wordcount + wc > orgnr)
13505 		    break;
13506 		wordcount += wc;
13507 	    }
13508 
13509 	    theword[wlen++] = byts[n + i];
13510 	    n = idxs[n + i];
13511 	}
13512 badword:
13513 	theword[wlen] = NUL;
13514 
13515 	/* Go over the possible flags and regions. */
13516 	for (; i <= byts[n] && byts[n + i] == NUL; ++i)
13517 	{
13518 	    char_u	cword[MAXWLEN];
13519 	    char_u	*p;
13520 	    int		flags = (int)idxs[n + i];
13521 
13522 	    /* Skip words with the NOSUGGEST flag */
13523 	    if (flags & WF_NOSUGGEST)
13524 		continue;
13525 
13526 	    if (flags & WF_KEEPCAP)
13527 	    {
13528 		/* Must find the word in the keep-case tree. */
13529 		find_keepcap_word(slang, theword, cword);
13530 		p = cword;
13531 	    }
13532 	    else
13533 	    {
13534 		flags |= su->su_badflags;
13535 		if ((flags & WF_CAPMASK) != 0)
13536 		{
13537 		    /* Need to fix case according to "flags". */
13538 		    make_case_word(theword, cword, flags);
13539 		    p = cword;
13540 		}
13541 		else
13542 		    p = theword;
13543 	    }
13544 
13545 	    /* Add the suggestion. */
13546 	    if (sps_flags & SPS_DOUBLE)
13547 	    {
13548 		/* Add the suggestion if the score isn't too bad. */
13549 		if (score <= su->su_maxscore)
13550 		    add_suggestion(su, &su->su_sga, p, su->su_badlen,
13551 					       score, 0, FALSE, slang, FALSE);
13552 	    }
13553 	    else
13554 	    {
13555 		/* Add a penalty for words in another region. */
13556 		if ((flags & WF_REGION)
13557 			    && (((unsigned)flags >> 16) & lp->lp_region) == 0)
13558 		    goodscore = SCORE_REGION;
13559 		else
13560 		    goodscore = 0;
13561 
13562 		/* Add a small penalty for changing the first letter from
13563 		 * lower to upper case.  Helps for "tath" -> "Kath", which is
13564 		 * less common thatn "tath" -> "path".  Don't do it when the
13565 		 * letter is the same, that has already been counted. */
13566 		gc = PTR2CHAR(p);
13567 		if (SPELL_ISUPPER(gc))
13568 		{
13569 		    bc = PTR2CHAR(su->su_badword);
13570 		    if (!SPELL_ISUPPER(bc)
13571 				      && SPELL_TOFOLD(bc) != SPELL_TOFOLD(gc))
13572 			goodscore += SCORE_ICASE / 2;
13573 		}
13574 
13575 		/* Compute the score for the good word.  This only does letter
13576 		 * insert/delete/swap/replace.  REP items are not considered,
13577 		 * which may make the score a bit higher.
13578 		 * Use a limit for the score to make it work faster.  Use
13579 		 * MAXSCORE(), because RESCORE() will change the score.
13580 		 * If the limit is very high then the iterative method is
13581 		 * inefficient, using an array is quicker. */
13582 		limit = MAXSCORE(su->su_sfmaxscore - goodscore, score);
13583 		if (limit > SCORE_LIMITMAX)
13584 		    goodscore += spell_edit_score(slang, su->su_badword, p);
13585 		else
13586 		    goodscore += spell_edit_score_limit(slang, su->su_badword,
13587 								    p, limit);
13588 
13589 		/* When going over the limit don't bother to do the rest. */
13590 		if (goodscore < SCORE_MAXMAX)
13591 		{
13592 		    /* Give a bonus to words seen before. */
13593 		    goodscore = score_wordcount_adj(slang, goodscore, p, FALSE);
13594 
13595 		    /* Add the suggestion if the score isn't too bad. */
13596 		    goodscore = RESCORE(goodscore, score);
13597 		    if (goodscore <= su->su_sfmaxscore)
13598 			add_suggestion(su, &su->su_ga, p, su->su_badlen,
13599 					 goodscore, score, TRUE, slang, TRUE);
13600 		}
13601 	    }
13602 	}
13603 	/* smsg("word %s (%d): %s (%d)", sftword, sftnr, theword, orgnr); */
13604     }
13605 }
13606 
13607 /*
13608  * Find word "word" in fold-case tree for "slang" and return the word number.
13609  */
13610     static int
13611 soundfold_find(slang, word)
13612     slang_T	*slang;
13613     char_u	*word;
13614 {
13615     idx_T	arridx = 0;
13616     int		len;
13617     int		wlen = 0;
13618     int		c;
13619     char_u	*ptr = word;
13620     char_u	*byts;
13621     idx_T	*idxs;
13622     int		wordnr = 0;
13623 
13624     byts = slang->sl_sbyts;
13625     idxs = slang->sl_sidxs;
13626 
13627     for (;;)
13628     {
13629 	/* First byte is the number of possible bytes. */
13630 	len = byts[arridx++];
13631 
13632 	/* If the first possible byte is a zero the word could end here.
13633 	 * If the word ends we found the word.  If not skip the NUL bytes. */
13634 	c = ptr[wlen];
13635 	if (byts[arridx] == NUL)
13636 	{
13637 	    if (c == NUL)
13638 		break;
13639 
13640 	    /* Skip over the zeros, there can be several. */
13641 	    while (len > 0 && byts[arridx] == NUL)
13642 	    {
13643 		++arridx;
13644 		--len;
13645 	    }
13646 	    if (len == 0)
13647 		return -1;    /* no children, word should have ended here */
13648 	    ++wordnr;
13649 	}
13650 
13651 	/* If the word ends we didn't find it. */
13652 	if (c == NUL)
13653 	    return -1;
13654 
13655 	/* Perform a binary search in the list of accepted bytes. */
13656 	if (c == TAB)	    /* <Tab> is handled like <Space> */
13657 	    c = ' ';
13658 	while (byts[arridx] < c)
13659 	{
13660 	    /* The word count is in the first idxs[] entry of the child. */
13661 	    wordnr += idxs[idxs[arridx]];
13662 	    ++arridx;
13663 	    if (--len == 0)	/* end of the bytes, didn't find it */
13664 		return -1;
13665 	}
13666 	if (byts[arridx] != c)	/* didn't find the byte */
13667 	    return -1;
13668 
13669 	/* Continue at the child (if there is one). */
13670 	arridx = idxs[arridx];
13671 	++wlen;
13672 
13673 	/* One space in the good word may stand for several spaces in the
13674 	 * checked word. */
13675 	if (c == ' ')
13676 	    while (ptr[wlen] == ' ' || ptr[wlen] == TAB)
13677 		++wlen;
13678     }
13679 
13680     return wordnr;
13681 }
13682 
13683 /*
13684  * Copy "fword" to "cword", fixing case according to "flags".
13685  */
13686     static void
13687 make_case_word(fword, cword, flags)
13688     char_u	*fword;
13689     char_u	*cword;
13690     int		flags;
13691 {
13692     if (flags & WF_ALLCAP)
13693 	/* Make it all upper-case */
13694 	allcap_copy(fword, cword);
13695     else if (flags & WF_ONECAP)
13696 	/* Make the first letter upper-case */
13697 	onecap_copy(fword, cword, TRUE);
13698     else
13699 	/* Use goodword as-is. */
13700 	STRCPY(cword, fword);
13701 }
13702 
13703 /*
13704  * Use map string "map" for languages "lp".
13705  */
13706     static void
13707 set_map_str(lp, map)
13708     slang_T	*lp;
13709     char_u	*map;
13710 {
13711     char_u	*p;
13712     int		headc = 0;
13713     int		c;
13714     int		i;
13715 
13716     if (*map == NUL)
13717     {
13718 	lp->sl_has_map = FALSE;
13719 	return;
13720     }
13721     lp->sl_has_map = TRUE;
13722 
13723     /* Init the array and hash tables empty. */
13724     for (i = 0; i < 256; ++i)
13725 	lp->sl_map_array[i] = 0;
13726 #ifdef FEAT_MBYTE
13727     hash_init(&lp->sl_map_hash);
13728 #endif
13729 
13730     /*
13731      * The similar characters are stored separated with slashes:
13732      * "aaa/bbb/ccc/".  Fill sl_map_array[c] with the character before c and
13733      * before the same slash.  For characters above 255 sl_map_hash is used.
13734      */
13735     for (p = map; *p != NUL; )
13736     {
13737 #ifdef FEAT_MBYTE
13738 	c = mb_cptr2char_adv(&p);
13739 #else
13740 	c = *p++;
13741 #endif
13742 	if (c == '/')
13743 	    headc = 0;
13744 	else
13745 	{
13746 	    if (headc == 0)
13747 		 headc = c;
13748 
13749 #ifdef FEAT_MBYTE
13750 	    /* Characters above 255 don't fit in sl_map_array[], put them in
13751 	     * the hash table.  Each entry is the char, a NUL the headchar and
13752 	     * a NUL. */
13753 	    if (c >= 256)
13754 	    {
13755 		int	    cl = mb_char2len(c);
13756 		int	    headcl = mb_char2len(headc);
13757 		char_u	    *b;
13758 		hash_T	    hash;
13759 		hashitem_T  *hi;
13760 
13761 		b = alloc((unsigned)(cl + headcl + 2));
13762 		if (b == NULL)
13763 		    return;
13764 		mb_char2bytes(c, b);
13765 		b[cl] = NUL;
13766 		mb_char2bytes(headc, b + cl + 1);
13767 		b[cl + 1 + headcl] = NUL;
13768 		hash = hash_hash(b);
13769 		hi = hash_lookup(&lp->sl_map_hash, b, hash);
13770 		if (HASHITEM_EMPTY(hi))
13771 		    hash_add_item(&lp->sl_map_hash, hi, b, hash);
13772 		else
13773 		{
13774 		    /* This should have been checked when generating the .spl
13775 		     * file. */
13776 		    EMSG(_("E783: duplicate char in MAP entry"));
13777 		    vim_free(b);
13778 		}
13779 	    }
13780 	    else
13781 #endif
13782 		lp->sl_map_array[c] = headc;
13783 	}
13784     }
13785 }
13786 
13787 /*
13788  * Return TRUE if "c1" and "c2" are similar characters according to the MAP
13789  * lines in the .aff file.
13790  */
13791     static int
13792 similar_chars(slang, c1, c2)
13793     slang_T	*slang;
13794     int		c1;
13795     int		c2;
13796 {
13797     int		m1, m2;
13798 #ifdef FEAT_MBYTE
13799     char_u	buf[MB_MAXBYTES];
13800     hashitem_T  *hi;
13801 
13802     if (c1 >= 256)
13803     {
13804 	buf[mb_char2bytes(c1, buf)] = 0;
13805 	hi = hash_find(&slang->sl_map_hash, buf);
13806 	if (HASHITEM_EMPTY(hi))
13807 	    m1 = 0;
13808 	else
13809 	    m1 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
13810     }
13811     else
13812 #endif
13813 	m1 = slang->sl_map_array[c1];
13814     if (m1 == 0)
13815 	return FALSE;
13816 
13817 
13818 #ifdef FEAT_MBYTE
13819     if (c2 >= 256)
13820     {
13821 	buf[mb_char2bytes(c2, buf)] = 0;
13822 	hi = hash_find(&slang->sl_map_hash, buf);
13823 	if (HASHITEM_EMPTY(hi))
13824 	    m2 = 0;
13825 	else
13826 	    m2 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
13827     }
13828     else
13829 #endif
13830 	m2 = slang->sl_map_array[c2];
13831 
13832     return m1 == m2;
13833 }
13834 
13835 /*
13836  * Add a suggestion to the list of suggestions.
13837  * For a suggestion that is already in the list the lowest score is remembered.
13838  */
13839     static void
13840 add_suggestion(su, gap, goodword, badlenarg, score, altscore, had_bonus,
13841 								 slang, maxsf)
13842     suginfo_T	*su;
13843     garray_T	*gap;		/* either su_ga or su_sga */
13844     char_u	*goodword;
13845     int		badlenarg;	/* len of bad word replaced with "goodword" */
13846     int		score;
13847     int		altscore;
13848     int		had_bonus;	/* value for st_had_bonus */
13849     slang_T	*slang;		/* language for sound folding */
13850     int		maxsf;		/* su_maxscore applies to soundfold score,
13851 				   su_sfmaxscore to the total score. */
13852 {
13853     int		goodlen;	/* len of goodword changed */
13854     int		badlen;		/* len of bad word changed */
13855     suggest_T   *stp;
13856     suggest_T   new_sug;
13857     int		i;
13858     char_u	*pgood, *pbad;
13859 
13860     /* Minimize "badlen" for consistency.  Avoids that changing "the the" to
13861      * "thee the" is added next to changing the first "the" the "thee".  */
13862     pgood = goodword + STRLEN(goodword);
13863     pbad = su->su_badptr + badlenarg;
13864     for (;;)
13865     {
13866 	goodlen = (int)(pgood - goodword);
13867 	badlen = (int)(pbad - su->su_badptr);
13868 	if (goodlen <= 0 || badlen <= 0)
13869 	    break;
13870 	mb_ptr_back(goodword, pgood);
13871 	mb_ptr_back(su->su_badptr, pbad);
13872 #ifdef FEAT_MBYTE
13873 	if (has_mbyte)
13874 	{
13875 	    if (mb_ptr2char(pgood) != mb_ptr2char(pbad))
13876 		break;
13877 	}
13878 	else
13879 #endif
13880 	    if (*pgood != *pbad)
13881 		break;
13882     }
13883 
13884     if (badlen == 0 && goodlen == 0)
13885 	/* goodword doesn't change anything; may happen for "the the" changing
13886 	 * the first "the" to itself. */
13887 	return;
13888 
13889     if (gap->ga_len == 0)
13890 	i = -1;
13891     else
13892     {
13893 	/* Check if the word is already there.  Also check the length that is
13894 	 * being replaced "thes," -> "these" is a different suggestion from
13895 	 * "thes" -> "these". */
13896 	stp = &SUG(*gap, 0);
13897 	for (i = gap->ga_len; --i >= 0; ++stp)
13898 	    if (stp->st_wordlen == goodlen
13899 		    && stp->st_orglen == badlen
13900 		    && STRNCMP(stp->st_word, goodword, goodlen) == 0)
13901 	    {
13902 		/*
13903 		 * Found it.  Remember the word with the lowest score.
13904 		 */
13905 		if (stp->st_slang == NULL)
13906 		    stp->st_slang = slang;
13907 
13908 		new_sug.st_score = score;
13909 		new_sug.st_altscore = altscore;
13910 		new_sug.st_had_bonus = had_bonus;
13911 
13912 		if (stp->st_had_bonus != had_bonus)
13913 		{
13914 		    /* Only one of the two had the soundalike score computed.
13915 		     * Need to do that for the other one now, otherwise the
13916 		     * scores can't be compared.  This happens because
13917 		     * suggest_try_change() doesn't compute the soundalike
13918 		     * word to keep it fast, while some special methods set
13919 		     * the soundalike score to zero. */
13920 		    if (had_bonus)
13921 			rescore_one(su, stp);
13922 		    else
13923 		    {
13924 			new_sug.st_word = stp->st_word;
13925 			new_sug.st_wordlen = stp->st_wordlen;
13926 			new_sug.st_slang = stp->st_slang;
13927 			new_sug.st_orglen = badlen;
13928 			rescore_one(su, &new_sug);
13929 		    }
13930 		}
13931 
13932 		if (stp->st_score > new_sug.st_score)
13933 		{
13934 		    stp->st_score = new_sug.st_score;
13935 		    stp->st_altscore = new_sug.st_altscore;
13936 		    stp->st_had_bonus = new_sug.st_had_bonus;
13937 		}
13938 		break;
13939 	    }
13940     }
13941 
13942     if (i < 0 && ga_grow(gap, 1) == OK)
13943     {
13944 	/* Add a suggestion. */
13945 	stp = &SUG(*gap, gap->ga_len);
13946 	stp->st_word = vim_strnsave(goodword, goodlen);
13947 	if (stp->st_word != NULL)
13948 	{
13949 	    stp->st_wordlen = goodlen;
13950 	    stp->st_score = score;
13951 	    stp->st_altscore = altscore;
13952 	    stp->st_had_bonus = had_bonus;
13953 	    stp->st_orglen = badlen;
13954 	    stp->st_slang = slang;
13955 	    ++gap->ga_len;
13956 
13957 	    /* If we have too many suggestions now, sort the list and keep
13958 	     * the best suggestions. */
13959 	    if (gap->ga_len > SUG_MAX_COUNT(su))
13960 	    {
13961 		if (maxsf)
13962 		    su->su_sfmaxscore = cleanup_suggestions(gap,
13963 				      su->su_sfmaxscore, SUG_CLEAN_COUNT(su));
13964 		else
13965 		{
13966 		    i = su->su_maxscore;
13967 		    su->su_maxscore = cleanup_suggestions(gap,
13968 					su->su_maxscore, SUG_CLEAN_COUNT(su));
13969 		}
13970 	    }
13971 	}
13972     }
13973 }
13974 
13975 /*
13976  * Suggestions may in fact be flagged as errors.  Esp. for banned words and
13977  * for split words, such as "the the".  Remove these from the list here.
13978  */
13979     static void
13980 check_suggestions(su, gap)
13981     suginfo_T	*su;
13982     garray_T	*gap;		    /* either su_ga or su_sga */
13983 {
13984     suggest_T   *stp;
13985     int		i;
13986     char_u	longword[MAXWLEN + 1];
13987     int		len;
13988     hlf_T	attr;
13989 
13990     stp = &SUG(*gap, 0);
13991     for (i = gap->ga_len - 1; i >= 0; --i)
13992     {
13993 	/* Need to append what follows to check for "the the". */
13994 	STRCPY(longword, stp[i].st_word);
13995 	len = stp[i].st_wordlen;
13996 	vim_strncpy(longword + len, su->su_badptr + stp[i].st_orglen,
13997 							       MAXWLEN - len);
13998 	attr = HLF_COUNT;
13999 	(void)spell_check(curwin, longword, &attr, NULL, FALSE);
14000 	if (attr != HLF_COUNT)
14001 	{
14002 	    /* Remove this entry. */
14003 	    vim_free(stp[i].st_word);
14004 	    --gap->ga_len;
14005 	    if (i < gap->ga_len)
14006 		mch_memmove(stp + i, stp + i + 1,
14007 				       sizeof(suggest_T) * (gap->ga_len - i));
14008 	}
14009     }
14010 }
14011 
14012 
14013 /*
14014  * Add a word to be banned.
14015  */
14016     static void
14017 add_banned(su, word)
14018     suginfo_T	*su;
14019     char_u	*word;
14020 {
14021     char_u	*s;
14022     hash_T	hash;
14023     hashitem_T	*hi;
14024 
14025     hash = hash_hash(word);
14026     hi = hash_lookup(&su->su_banned, word, hash);
14027     if (HASHITEM_EMPTY(hi))
14028     {
14029 	s = vim_strsave(word);
14030 	if (s != NULL)
14031 	    hash_add_item(&su->su_banned, hi, s, hash);
14032     }
14033 }
14034 
14035 /*
14036  * Recompute the score for all suggestions if sound-folding is possible.  This
14037  * is slow, thus only done for the final results.
14038  */
14039     static void
14040 rescore_suggestions(su)
14041     suginfo_T	*su;
14042 {
14043     int		i;
14044 
14045     if (su->su_sallang != NULL)
14046 	for (i = 0; i < su->su_ga.ga_len; ++i)
14047 	    rescore_one(su, &SUG(su->su_ga, i));
14048 }
14049 
14050 /*
14051  * Recompute the score for one suggestion if sound-folding is possible.
14052  */
14053     static void
14054 rescore_one(su, stp)
14055     suginfo_T	*su;
14056     suggest_T	*stp;
14057 {
14058     slang_T	*slang = stp->st_slang;
14059     char_u	sal_badword[MAXWLEN];
14060     char_u	*p;
14061 
14062     /* Only rescore suggestions that have no sal score yet and do have a
14063      * language. */
14064     if (slang != NULL && slang->sl_sal.ga_len > 0 && !stp->st_had_bonus)
14065     {
14066 	if (slang == su->su_sallang)
14067 	    p = su->su_sal_badword;
14068 	else
14069 	{
14070 	    spell_soundfold(slang, su->su_fbadword, TRUE, sal_badword);
14071 	    p = sal_badword;
14072 	}
14073 
14074 	stp->st_altscore = stp_sal_score(stp, su, slang, p);
14075 	if (stp->st_altscore == SCORE_MAXMAX)
14076 	    stp->st_altscore = SCORE_BIG;
14077 	stp->st_score = RESCORE(stp->st_score, stp->st_altscore);
14078 	stp->st_had_bonus = TRUE;
14079     }
14080 }
14081 
14082 static int
14083 #ifdef __BORLANDC__
14084 _RTLENTRYF
14085 #endif
14086 sug_compare __ARGS((const void *s1, const void *s2));
14087 
14088 /*
14089  * Function given to qsort() to sort the suggestions on st_score.
14090  * First on "st_score", then "st_altscore" then alphabetically.
14091  */
14092     static int
14093 #ifdef __BORLANDC__
14094 _RTLENTRYF
14095 #endif
14096 sug_compare(s1, s2)
14097     const void	*s1;
14098     const void	*s2;
14099 {
14100     suggest_T	*p1 = (suggest_T *)s1;
14101     suggest_T	*p2 = (suggest_T *)s2;
14102     int		n = p1->st_score - p2->st_score;
14103 
14104     if (n == 0)
14105     {
14106 	n = p1->st_altscore - p2->st_altscore;
14107 	if (n == 0)
14108 	    n = STRICMP(p1->st_word, p2->st_word);
14109     }
14110     return n;
14111 }
14112 
14113 /*
14114  * Cleanup the suggestions:
14115  * - Sort on score.
14116  * - Remove words that won't be displayed.
14117  * Returns the maximum score in the list or "maxscore" unmodified.
14118  */
14119     static int
14120 cleanup_suggestions(gap, maxscore, keep)
14121     garray_T	*gap;
14122     int		maxscore;
14123     int		keep;		/* nr of suggestions to keep */
14124 {
14125     suggest_T   *stp = &SUG(*gap, 0);
14126     int		i;
14127 
14128     /* Sort the list. */
14129     qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
14130 
14131     /* Truncate the list to the number of suggestions that will be displayed. */
14132     if (gap->ga_len > keep)
14133     {
14134 	for (i = keep; i < gap->ga_len; ++i)
14135 	    vim_free(stp[i].st_word);
14136 	gap->ga_len = keep;
14137 	return stp[keep - 1].st_score;
14138     }
14139     return maxscore;
14140 }
14141 
14142 #if defined(FEAT_EVAL) || defined(PROTO)
14143 /*
14144  * Soundfold a string, for soundfold().
14145  * Result is in allocated memory, NULL for an error.
14146  */
14147     char_u *
14148 eval_soundfold(word)
14149     char_u	*word;
14150 {
14151     langp_T	*lp;
14152     char_u	sound[MAXWLEN];
14153     int		lpi;
14154 
14155     if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
14156 	/* Use the sound-folding of the first language that supports it. */
14157 	for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
14158 	{
14159 	    lp = LANGP_ENTRY(curbuf->b_langp, lpi);
14160 	    if (lp->lp_slang->sl_sal.ga_len > 0)
14161 	    {
14162 		/* soundfold the word */
14163 		spell_soundfold(lp->lp_slang, word, FALSE, sound);
14164 		return vim_strsave(sound);
14165 	    }
14166 	}
14167 
14168     /* No language with sound folding, return word as-is. */
14169     return vim_strsave(word);
14170 }
14171 #endif
14172 
14173 /*
14174  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
14175  *
14176  * There are many ways to turn a word into a sound-a-like representation.  The
14177  * oldest is Soundex (1918!).   A nice overview can be found in "Approximate
14178  * swedish name matching - survey and test of different algorithms" by Klas
14179  * Erikson.
14180  *
14181  * We support two methods:
14182  * 1. SOFOFROM/SOFOTO do a simple character mapping.
14183  * 2. SAL items define a more advanced sound-folding (and much slower).
14184  */
14185     static void
14186 spell_soundfold(slang, inword, folded, res)
14187     slang_T	*slang;
14188     char_u	*inword;
14189     int		folded;	    /* "inword" is already case-folded */
14190     char_u	*res;
14191 {
14192     char_u	fword[MAXWLEN];
14193     char_u	*word;
14194 
14195     if (slang->sl_sofo)
14196 	/* SOFOFROM and SOFOTO used */
14197 	spell_soundfold_sofo(slang, inword, res);
14198     else
14199     {
14200 	/* SAL items used.  Requires the word to be case-folded. */
14201 	if (folded)
14202 	    word = inword;
14203 	else
14204 	{
14205 	    (void)spell_casefold(inword, (int)STRLEN(inword), fword, MAXWLEN);
14206 	    word = fword;
14207 	}
14208 
14209 #ifdef FEAT_MBYTE
14210 	if (has_mbyte)
14211 	    spell_soundfold_wsal(slang, word, res);
14212 	else
14213 #endif
14214 	    spell_soundfold_sal(slang, word, res);
14215     }
14216 }
14217 
14218 /*
14219  * Perform sound folding of "inword" into "res" according to SOFOFROM and
14220  * SOFOTO lines.
14221  */
14222     static void
14223 spell_soundfold_sofo(slang, inword, res)
14224     slang_T	*slang;
14225     char_u	*inword;
14226     char_u	*res;
14227 {
14228     char_u	*s;
14229     int		ri = 0;
14230     int		c;
14231 
14232 #ifdef FEAT_MBYTE
14233     if (has_mbyte)
14234     {
14235 	int	prevc = 0;
14236 	int	*ip;
14237 
14238 	/* The sl_sal_first[] table contains the translation for chars up to
14239 	 * 255, sl_sal the rest. */
14240 	for (s = inword; *s != NUL; )
14241 	{
14242 	    c = mb_cptr2char_adv(&s);
14243 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
14244 		c = ' ';
14245 	    else if (c < 256)
14246 		c = slang->sl_sal_first[c];
14247 	    else
14248 	    {
14249 		ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
14250 		if (ip == NULL)		/* empty list, can't match */
14251 		    c = NUL;
14252 		else
14253 		    for (;;)		/* find "c" in the list */
14254 		    {
14255 			if (*ip == 0)	/* not found */
14256 			{
14257 			    c = NUL;
14258 			    break;
14259 			}
14260 			if (*ip == c)	/* match! */
14261 			{
14262 			    c = ip[1];
14263 			    break;
14264 			}
14265 			ip += 2;
14266 		    }
14267 	    }
14268 
14269 	    if (c != NUL && c != prevc)
14270 	    {
14271 		ri += mb_char2bytes(c, res + ri);
14272 		if (ri + MB_MAXBYTES > MAXWLEN)
14273 		    break;
14274 		prevc = c;
14275 	    }
14276 	}
14277     }
14278     else
14279 #endif
14280     {
14281 	/* The sl_sal_first[] table contains the translation. */
14282 	for (s = inword; (c = *s) != NUL; ++s)
14283 	{
14284 	    if (vim_iswhite(c))
14285 		c = ' ';
14286 	    else
14287 		c = slang->sl_sal_first[c];
14288 	    if (c != NUL && (ri == 0 || res[ri - 1] != c))
14289 		res[ri++] = c;
14290 	}
14291     }
14292 
14293     res[ri] = NUL;
14294 }
14295 
14296     static void
14297 spell_soundfold_sal(slang, inword, res)
14298     slang_T	*slang;
14299     char_u	*inword;
14300     char_u	*res;
14301 {
14302     salitem_T	*smp;
14303     char_u	word[MAXWLEN];
14304     char_u	*s = inword;
14305     char_u	*t;
14306     char_u	*pf;
14307     int		i, j, z;
14308     int		reslen;
14309     int		n, k = 0;
14310     int		z0;
14311     int		k0;
14312     int		n0;
14313     int		c;
14314     int		pri;
14315     int		p0 = -333;
14316     int		c0;
14317 
14318     /* Remove accents, if wanted.  We actually remove all non-word characters.
14319      * But keep white space.  We need a copy, the word may be changed here. */
14320     if (slang->sl_rem_accents)
14321     {
14322 	t = word;
14323 	while (*s != NUL)
14324 	{
14325 	    if (vim_iswhite(*s))
14326 	    {
14327 		*t++ = ' ';
14328 		s = skipwhite(s);
14329 	    }
14330 	    else
14331 	    {
14332 		if (spell_iswordp_nmw(s))
14333 		    *t++ = *s;
14334 		++s;
14335 	    }
14336 	}
14337 	*t = NUL;
14338     }
14339     else
14340 	STRCPY(word, s);
14341 
14342     smp = (salitem_T *)slang->sl_sal.ga_data;
14343 
14344     /*
14345      * This comes from Aspell phonet.cpp.  Converted from C++ to C.
14346      * Changed to keep spaces.
14347      */
14348     i = reslen = z = 0;
14349     while ((c = word[i]) != NUL)
14350     {
14351 	/* Start with the first rule that has the character in the word. */
14352 	n = slang->sl_sal_first[c];
14353 	z0 = 0;
14354 
14355 	if (n >= 0)
14356 	{
14357 	    /* check all rules for the same letter */
14358 	    for (; (s = smp[n].sm_lead)[0] == c; ++n)
14359 	    {
14360 		/* Quickly skip entries that don't match the word.  Most
14361 		 * entries are less then three chars, optimize for that. */
14362 		k = smp[n].sm_leadlen;
14363 		if (k > 1)
14364 		{
14365 		    if (word[i + 1] != s[1])
14366 			continue;
14367 		    if (k > 2)
14368 		    {
14369 			for (j = 2; j < k; ++j)
14370 			    if (word[i + j] != s[j])
14371 				break;
14372 			if (j < k)
14373 			    continue;
14374 		    }
14375 		}
14376 
14377 		if ((pf = smp[n].sm_oneof) != NULL)
14378 		{
14379 		    /* Check for match with one of the chars in "sm_oneof". */
14380 		    while (*pf != NUL && *pf != word[i + k])
14381 			++pf;
14382 		    if (*pf == NUL)
14383 			continue;
14384 		    ++k;
14385 		}
14386 		s = smp[n].sm_rules;
14387 		pri = 5;    /* default priority */
14388 
14389 		p0 = *s;
14390 		k0 = k;
14391 		while (*s == '-' && k > 1)
14392 		{
14393 		    k--;
14394 		    s++;
14395 		}
14396 		if (*s == '<')
14397 		    s++;
14398 		if (VIM_ISDIGIT(*s))
14399 		{
14400 		    /* determine priority */
14401 		    pri = *s - '0';
14402 		    s++;
14403 		}
14404 		if (*s == '^' && *(s + 1) == '^')
14405 		    s++;
14406 
14407 		if (*s == NUL
14408 			|| (*s == '^'
14409 			    && (i == 0 || !(word[i - 1] == ' '
14410 				      || spell_iswordp(word + i - 1, curbuf)))
14411 			    && (*(s + 1) != '$'
14412 				|| (!spell_iswordp(word + i + k0, curbuf))))
14413 			|| (*s == '$' && i > 0
14414 			    && spell_iswordp(word + i - 1, curbuf)
14415 			    && (!spell_iswordp(word + i + k0, curbuf))))
14416 		{
14417 		    /* search for followup rules, if:    */
14418 		    /* followup and k > 1  and  NO '-' in searchstring */
14419 		    c0 = word[i + k - 1];
14420 		    n0 = slang->sl_sal_first[c0];
14421 
14422 		    if (slang->sl_followup && k > 1 && n0 >= 0
14423 					   && p0 != '-' && word[i + k] != NUL)
14424 		    {
14425 			/* test follow-up rule for "word[i + k]" */
14426 			for ( ; (s = smp[n0].sm_lead)[0] == c0; ++n0)
14427 			{
14428 			    /* Quickly skip entries that don't match the word.
14429 			     * */
14430 			    k0 = smp[n0].sm_leadlen;
14431 			    if (k0 > 1)
14432 			    {
14433 				if (word[i + k] != s[1])
14434 				    continue;
14435 				if (k0 > 2)
14436 				{
14437 				    pf = word + i + k + 1;
14438 				    for (j = 2; j < k0; ++j)
14439 					if (*pf++ != s[j])
14440 					    break;
14441 				    if (j < k0)
14442 					continue;
14443 				}
14444 			    }
14445 			    k0 += k - 1;
14446 
14447 			    if ((pf = smp[n0].sm_oneof) != NULL)
14448 			    {
14449 				/* Check for match with one of the chars in
14450 				 * "sm_oneof". */
14451 				while (*pf != NUL && *pf != word[i + k0])
14452 				    ++pf;
14453 				if (*pf == NUL)
14454 				    continue;
14455 				++k0;
14456 			    }
14457 
14458 			    p0 = 5;
14459 			    s = smp[n0].sm_rules;
14460 			    while (*s == '-')
14461 			    {
14462 				/* "k0" gets NOT reduced because
14463 				 * "if (k0 == k)" */
14464 				s++;
14465 			    }
14466 			    if (*s == '<')
14467 				s++;
14468 			    if (VIM_ISDIGIT(*s))
14469 			    {
14470 				p0 = *s - '0';
14471 				s++;
14472 			    }
14473 
14474 			    if (*s == NUL
14475 				    /* *s == '^' cuts */
14476 				    || (*s == '$'
14477 					    && !spell_iswordp(word + i + k0,
14478 								     curbuf)))
14479 			    {
14480 				if (k0 == k)
14481 				    /* this is just a piece of the string */
14482 				    continue;
14483 
14484 				if (p0 < pri)
14485 				    /* priority too low */
14486 				    continue;
14487 				/* rule fits; stop search */
14488 				break;
14489 			    }
14490 			}
14491 
14492 			if (p0 >= pri && smp[n0].sm_lead[0] == c0)
14493 			    continue;
14494 		    }
14495 
14496 		    /* replace string */
14497 		    s = smp[n].sm_to;
14498 		    if (s == NULL)
14499 			s = (char_u *)"";
14500 		    pf = smp[n].sm_rules;
14501 		    p0 = (vim_strchr(pf, '<') != NULL) ? 1 : 0;
14502 		    if (p0 == 1 && z == 0)
14503 		    {
14504 			/* rule with '<' is used */
14505 			if (reslen > 0 && *s != NUL && (res[reslen - 1] == c
14506 						    || res[reslen - 1] == *s))
14507 			    reslen--;
14508 			z0 = 1;
14509 			z = 1;
14510 			k0 = 0;
14511 			while (*s != NUL && word[i + k0] != NUL)
14512 			{
14513 			    word[i + k0] = *s;
14514 			    k0++;
14515 			    s++;
14516 			}
14517 			if (k > k0)
14518 			    STRMOVE(word + i + k0, word + i + k);
14519 
14520 			/* new "actual letter" */
14521 			c = word[i];
14522 		    }
14523 		    else
14524 		    {
14525 			/* no '<' rule used */
14526 			i += k - 1;
14527 			z = 0;
14528 			while (*s != NUL && s[1] != NUL && reslen < MAXWLEN)
14529 			{
14530 			    if (reslen == 0 || res[reslen - 1] != *s)
14531 				res[reslen++] = *s;
14532 			    s++;
14533 			}
14534 			/* new "actual letter" */
14535 			c = *s;
14536 			if (strstr((char *)pf, "^^") != NULL)
14537 			{
14538 			    if (c != NUL)
14539 				res[reslen++] = c;
14540 			    STRMOVE(word, word + i + 1);
14541 			    i = 0;
14542 			    z0 = 1;
14543 			}
14544 		    }
14545 		    break;
14546 		}
14547 	    }
14548 	}
14549 	else if (vim_iswhite(c))
14550 	{
14551 	    c = ' ';
14552 	    k = 1;
14553 	}
14554 
14555 	if (z0 == 0)
14556 	{
14557 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
14558 		    && (!slang->sl_collapse || reslen == 0
14559 						     || res[reslen - 1] != c))
14560 		/* condense only double letters */
14561 		res[reslen++] = c;
14562 
14563 	    i++;
14564 	    z = 0;
14565 	    k = 0;
14566 	}
14567     }
14568 
14569     res[reslen] = NUL;
14570 }
14571 
14572 #ifdef FEAT_MBYTE
14573 /*
14574  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
14575  * Multi-byte version of spell_soundfold().
14576  */
14577     static void
14578 spell_soundfold_wsal(slang, inword, res)
14579     slang_T	*slang;
14580     char_u	*inword;
14581     char_u	*res;
14582 {
14583     salitem_T	*smp = (salitem_T *)slang->sl_sal.ga_data;
14584     int		word[MAXWLEN];
14585     int		wres[MAXWLEN];
14586     int		l;
14587     char_u	*s;
14588     int		*ws;
14589     char_u	*t;
14590     int		*pf;
14591     int		i, j, z;
14592     int		reslen;
14593     int		n, k = 0;
14594     int		z0;
14595     int		k0;
14596     int		n0;
14597     int		c;
14598     int		pri;
14599     int		p0 = -333;
14600     int		c0;
14601     int		did_white = FALSE;
14602 
14603     /*
14604      * Convert the multi-byte string to a wide-character string.
14605      * Remove accents, if wanted.  We actually remove all non-word characters.
14606      * But keep white space.
14607      */
14608     n = 0;
14609     for (s = inword; *s != NUL; )
14610     {
14611 	t = s;
14612 	c = mb_cptr2char_adv(&s);
14613 	if (slang->sl_rem_accents)
14614 	{
14615 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
14616 	    {
14617 		if (did_white)
14618 		    continue;
14619 		c = ' ';
14620 		did_white = TRUE;
14621 	    }
14622 	    else
14623 	    {
14624 		did_white = FALSE;
14625 		if (!spell_iswordp_nmw(t))
14626 		    continue;
14627 	    }
14628 	}
14629 	word[n++] = c;
14630     }
14631     word[n] = NUL;
14632 
14633     /*
14634      * This comes from Aspell phonet.cpp.
14635      * Converted from C++ to C.  Added support for multi-byte chars.
14636      * Changed to keep spaces.
14637      */
14638     i = reslen = z = 0;
14639     while ((c = word[i]) != NUL)
14640     {
14641 	/* Start with the first rule that has the character in the word. */
14642 	n = slang->sl_sal_first[c & 0xff];
14643 	z0 = 0;
14644 
14645 	if (n >= 0)
14646 	{
14647 	    /* check all rules for the same index byte */
14648 	    for (; ((ws = smp[n].sm_lead_w)[0] & 0xff) == (c & 0xff); ++n)
14649 	    {
14650 		/* Quickly skip entries that don't match the word.  Most
14651 		 * entries are less then three chars, optimize for that. */
14652 		if (c != ws[0])
14653 		    continue;
14654 		k = smp[n].sm_leadlen;
14655 		if (k > 1)
14656 		{
14657 		    if (word[i + 1] != ws[1])
14658 			continue;
14659 		    if (k > 2)
14660 		    {
14661 			for (j = 2; j < k; ++j)
14662 			    if (word[i + j] != ws[j])
14663 				break;
14664 			if (j < k)
14665 			    continue;
14666 		    }
14667 		}
14668 
14669 		if ((pf = smp[n].sm_oneof_w) != NULL)
14670 		{
14671 		    /* Check for match with one of the chars in "sm_oneof". */
14672 		    while (*pf != NUL && *pf != word[i + k])
14673 			++pf;
14674 		    if (*pf == NUL)
14675 			continue;
14676 		    ++k;
14677 		}
14678 		s = smp[n].sm_rules;
14679 		pri = 5;    /* default priority */
14680 
14681 		p0 = *s;
14682 		k0 = k;
14683 		while (*s == '-' && k > 1)
14684 		{
14685 		    k--;
14686 		    s++;
14687 		}
14688 		if (*s == '<')
14689 		    s++;
14690 		if (VIM_ISDIGIT(*s))
14691 		{
14692 		    /* determine priority */
14693 		    pri = *s - '0';
14694 		    s++;
14695 		}
14696 		if (*s == '^' && *(s + 1) == '^')
14697 		    s++;
14698 
14699 		if (*s == NUL
14700 			|| (*s == '^'
14701 			    && (i == 0 || !(word[i - 1] == ' '
14702 				    || spell_iswordp_w(word + i - 1, curbuf)))
14703 			    && (*(s + 1) != '$'
14704 				|| (!spell_iswordp_w(word + i + k0, curbuf))))
14705 			|| (*s == '$' && i > 0
14706 			    && spell_iswordp_w(word + i - 1, curbuf)
14707 			    && (!spell_iswordp_w(word + i + k0, curbuf))))
14708 		{
14709 		    /* search for followup rules, if:    */
14710 		    /* followup and k > 1  and  NO '-' in searchstring */
14711 		    c0 = word[i + k - 1];
14712 		    n0 = slang->sl_sal_first[c0 & 0xff];
14713 
14714 		    if (slang->sl_followup && k > 1 && n0 >= 0
14715 					   && p0 != '-' && word[i + k] != NUL)
14716 		    {
14717 			/* Test follow-up rule for "word[i + k]"; loop over
14718 			 * all entries with the same index byte. */
14719 			for ( ; ((ws = smp[n0].sm_lead_w)[0] & 0xff)
14720 							 == (c0 & 0xff); ++n0)
14721 			{
14722 			    /* Quickly skip entries that don't match the word.
14723 			     */
14724 			    if (c0 != ws[0])
14725 				continue;
14726 			    k0 = smp[n0].sm_leadlen;
14727 			    if (k0 > 1)
14728 			    {
14729 				if (word[i + k] != ws[1])
14730 				    continue;
14731 				if (k0 > 2)
14732 				{
14733 				    pf = word + i + k + 1;
14734 				    for (j = 2; j < k0; ++j)
14735 					if (*pf++ != ws[j])
14736 					    break;
14737 				    if (j < k0)
14738 					continue;
14739 				}
14740 			    }
14741 			    k0 += k - 1;
14742 
14743 			    if ((pf = smp[n0].sm_oneof_w) != NULL)
14744 			    {
14745 				/* Check for match with one of the chars in
14746 				 * "sm_oneof". */
14747 				while (*pf != NUL && *pf != word[i + k0])
14748 				    ++pf;
14749 				if (*pf == NUL)
14750 				    continue;
14751 				++k0;
14752 			    }
14753 
14754 			    p0 = 5;
14755 			    s = smp[n0].sm_rules;
14756 			    while (*s == '-')
14757 			    {
14758 				/* "k0" gets NOT reduced because
14759 				 * "if (k0 == k)" */
14760 				s++;
14761 			    }
14762 			    if (*s == '<')
14763 				s++;
14764 			    if (VIM_ISDIGIT(*s))
14765 			    {
14766 				p0 = *s - '0';
14767 				s++;
14768 			    }
14769 
14770 			    if (*s == NUL
14771 				    /* *s == '^' cuts */
14772 				    || (*s == '$'
14773 					 && !spell_iswordp_w(word + i + k0,
14774 								     curbuf)))
14775 			    {
14776 				if (k0 == k)
14777 				    /* this is just a piece of the string */
14778 				    continue;
14779 
14780 				if (p0 < pri)
14781 				    /* priority too low */
14782 				    continue;
14783 				/* rule fits; stop search */
14784 				break;
14785 			    }
14786 			}
14787 
14788 			if (p0 >= pri && (smp[n0].sm_lead_w[0] & 0xff)
14789 							       == (c0 & 0xff))
14790 			    continue;
14791 		    }
14792 
14793 		    /* replace string */
14794 		    ws = smp[n].sm_to_w;
14795 		    s = smp[n].sm_rules;
14796 		    p0 = (vim_strchr(s, '<') != NULL) ? 1 : 0;
14797 		    if (p0 == 1 && z == 0)
14798 		    {
14799 			/* rule with '<' is used */
14800 			if (reslen > 0 && ws != NULL && *ws != NUL
14801 				&& (wres[reslen - 1] == c
14802 						    || wres[reslen - 1] == *ws))
14803 			    reslen--;
14804 			z0 = 1;
14805 			z = 1;
14806 			k0 = 0;
14807 			if (ws != NULL)
14808 			    while (*ws != NUL && word[i + k0] != NUL)
14809 			    {
14810 				word[i + k0] = *ws;
14811 				k0++;
14812 				ws++;
14813 			    }
14814 			if (k > k0)
14815 			    mch_memmove(word + i + k0, word + i + k,
14816 				    sizeof(int) * (STRLEN(word + i + k) + 1));
14817 
14818 			/* new "actual letter" */
14819 			c = word[i];
14820 		    }
14821 		    else
14822 		    {
14823 			/* no '<' rule used */
14824 			i += k - 1;
14825 			z = 0;
14826 			if (ws != NULL)
14827 			    while (*ws != NUL && ws[1] != NUL
14828 							  && reslen < MAXWLEN)
14829 			    {
14830 				if (reslen == 0 || wres[reslen - 1] != *ws)
14831 				    wres[reslen++] = *ws;
14832 				ws++;
14833 			    }
14834 			/* new "actual letter" */
14835 			if (ws == NULL)
14836 			    c = NUL;
14837 			else
14838 			    c = *ws;
14839 			if (strstr((char *)s, "^^") != NULL)
14840 			{
14841 			    if (c != NUL)
14842 				wres[reslen++] = c;
14843 			    mch_memmove(word, word + i + 1,
14844 				    sizeof(int) * (STRLEN(word + i + 1) + 1));
14845 			    i = 0;
14846 			    z0 = 1;
14847 			}
14848 		    }
14849 		    break;
14850 		}
14851 	    }
14852 	}
14853 	else if (vim_iswhite(c))
14854 	{
14855 	    c = ' ';
14856 	    k = 1;
14857 	}
14858 
14859 	if (z0 == 0)
14860 	{
14861 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
14862 		    && (!slang->sl_collapse || reslen == 0
14863 						     || wres[reslen - 1] != c))
14864 		/* condense only double letters */
14865 		wres[reslen++] = c;
14866 
14867 	    i++;
14868 	    z = 0;
14869 	    k = 0;
14870 	}
14871     }
14872 
14873     /* Convert wide characters in "wres" to a multi-byte string in "res". */
14874     l = 0;
14875     for (n = 0; n < reslen; ++n)
14876     {
14877 	l += mb_char2bytes(wres[n], res + l);
14878 	if (l + MB_MAXBYTES > MAXWLEN)
14879 	    break;
14880     }
14881     res[l] = NUL;
14882 }
14883 #endif
14884 
14885 /*
14886  * Compute a score for two sound-a-like words.
14887  * This permits up to two inserts/deletes/swaps/etc. to keep things fast.
14888  * Instead of a generic loop we write out the code.  That keeps it fast by
14889  * avoiding checks that will not be possible.
14890  */
14891     static int
14892 soundalike_score(goodstart, badstart)
14893     char_u	*goodstart;	/* sound-folded good word */
14894     char_u	*badstart;	/* sound-folded bad word */
14895 {
14896     char_u	*goodsound = goodstart;
14897     char_u	*badsound = badstart;
14898     int		goodlen;
14899     int		badlen;
14900     int		n;
14901     char_u	*pl, *ps;
14902     char_u	*pl2, *ps2;
14903     int		score = 0;
14904 
14905     /* adding/inserting "*" at the start (word starts with vowel) shouldn't be
14906      * counted so much, vowels halfway the word aren't counted at all. */
14907     if ((*badsound == '*' || *goodsound == '*') && *badsound != *goodsound)
14908     {
14909 	if (badsound[1] == goodsound[1]
14910 		|| (badsound[1] != NUL
14911 		    && goodsound[1] != NUL
14912 		    && badsound[2] == goodsound[2]))
14913 	{
14914 	    /* handle like a substitute */
14915 	}
14916 	else
14917 	{
14918 	    score = 2 * SCORE_DEL / 3;
14919 	    if (*badsound == '*')
14920 		++badsound;
14921 	    else
14922 		++goodsound;
14923 	}
14924     }
14925 
14926     goodlen = (int)STRLEN(goodsound);
14927     badlen = (int)STRLEN(badsound);
14928 
14929     /* Return quickly if the lengths are too different to be fixed by two
14930      * changes. */
14931     n = goodlen - badlen;
14932     if (n < -2 || n > 2)
14933 	return SCORE_MAXMAX;
14934 
14935     if (n > 0)
14936     {
14937 	pl = goodsound;	    /* goodsound is longest */
14938 	ps = badsound;
14939     }
14940     else
14941     {
14942 	pl = badsound;	    /* badsound is longest */
14943 	ps = goodsound;
14944     }
14945 
14946     /* Skip over the identical part. */
14947     while (*pl == *ps && *pl != NUL)
14948     {
14949 	++pl;
14950 	++ps;
14951     }
14952 
14953     switch (n)
14954     {
14955 	case -2:
14956 	case 2:
14957 	    /*
14958 	     * Must delete two characters from "pl".
14959 	     */
14960 	    ++pl;	/* first delete */
14961 	    while (*pl == *ps)
14962 	    {
14963 		++pl;
14964 		++ps;
14965 	    }
14966 	    /* strings must be equal after second delete */
14967 	    if (STRCMP(pl + 1, ps) == 0)
14968 		return score + SCORE_DEL * 2;
14969 
14970 	    /* Failed to compare. */
14971 	    break;
14972 
14973 	case -1:
14974 	case 1:
14975 	    /*
14976 	     * Minimal one delete from "pl" required.
14977 	     */
14978 
14979 	    /* 1: delete */
14980 	    pl2 = pl + 1;
14981 	    ps2 = ps;
14982 	    while (*pl2 == *ps2)
14983 	    {
14984 		if (*pl2 == NUL)	/* reached the end */
14985 		    return score + SCORE_DEL;
14986 		++pl2;
14987 		++ps2;
14988 	    }
14989 
14990 	    /* 2: delete then swap, then rest must be equal */
14991 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
14992 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
14993 		return score + SCORE_DEL + SCORE_SWAP;
14994 
14995 	    /* 3: delete then substitute, then the rest must be equal */
14996 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
14997 		return score + SCORE_DEL + SCORE_SUBST;
14998 
14999 	    /* 4: first swap then delete */
15000 	    if (pl[0] == ps[1] && pl[1] == ps[0])
15001 	    {
15002 		pl2 = pl + 2;	    /* swap, skip two chars */
15003 		ps2 = ps + 2;
15004 		while (*pl2 == *ps2)
15005 		{
15006 		    ++pl2;
15007 		    ++ps2;
15008 		}
15009 		/* delete a char and then strings must be equal */
15010 		if (STRCMP(pl2 + 1, ps2) == 0)
15011 		    return score + SCORE_SWAP + SCORE_DEL;
15012 	    }
15013 
15014 	    /* 5: first substitute then delete */
15015 	    pl2 = pl + 1;	    /* substitute, skip one char */
15016 	    ps2 = ps + 1;
15017 	    while (*pl2 == *ps2)
15018 	    {
15019 		++pl2;
15020 		++ps2;
15021 	    }
15022 	    /* delete a char and then strings must be equal */
15023 	    if (STRCMP(pl2 + 1, ps2) == 0)
15024 		return score + SCORE_SUBST + SCORE_DEL;
15025 
15026 	    /* Failed to compare. */
15027 	    break;
15028 
15029 	case 0:
15030 	    /*
15031 	     * Lengths are equal, thus changes must result in same length: An
15032 	     * insert is only possible in combination with a delete.
15033 	     * 1: check if for identical strings
15034 	     */
15035 	    if (*pl == NUL)
15036 		return score;
15037 
15038 	    /* 2: swap */
15039 	    if (pl[0] == ps[1] && pl[1] == ps[0])
15040 	    {
15041 		pl2 = pl + 2;	    /* swap, skip two chars */
15042 		ps2 = ps + 2;
15043 		while (*pl2 == *ps2)
15044 		{
15045 		    if (*pl2 == NUL)	/* reached the end */
15046 			return score + SCORE_SWAP;
15047 		    ++pl2;
15048 		    ++ps2;
15049 		}
15050 		/* 3: swap and swap again */
15051 		if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
15052 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
15053 		    return score + SCORE_SWAP + SCORE_SWAP;
15054 
15055 		/* 4: swap and substitute */
15056 		if (STRCMP(pl2 + 1, ps2 + 1) == 0)
15057 		    return score + SCORE_SWAP + SCORE_SUBST;
15058 	    }
15059 
15060 	    /* 5: substitute */
15061 	    pl2 = pl + 1;
15062 	    ps2 = ps + 1;
15063 	    while (*pl2 == *ps2)
15064 	    {
15065 		if (*pl2 == NUL)	/* reached the end */
15066 		    return score + SCORE_SUBST;
15067 		++pl2;
15068 		++ps2;
15069 	    }
15070 
15071 	    /* 6: substitute and swap */
15072 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
15073 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
15074 		return score + SCORE_SUBST + SCORE_SWAP;
15075 
15076 	    /* 7: substitute and substitute */
15077 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
15078 		return score + SCORE_SUBST + SCORE_SUBST;
15079 
15080 	    /* 8: insert then delete */
15081 	    pl2 = pl;
15082 	    ps2 = ps + 1;
15083 	    while (*pl2 == *ps2)
15084 	    {
15085 		++pl2;
15086 		++ps2;
15087 	    }
15088 	    if (STRCMP(pl2 + 1, ps2) == 0)
15089 		return score + SCORE_INS + SCORE_DEL;
15090 
15091 	    /* 9: delete then insert */
15092 	    pl2 = pl + 1;
15093 	    ps2 = ps;
15094 	    while (*pl2 == *ps2)
15095 	    {
15096 		++pl2;
15097 		++ps2;
15098 	    }
15099 	    if (STRCMP(pl2, ps2 + 1) == 0)
15100 		return score + SCORE_INS + SCORE_DEL;
15101 
15102 	    /* Failed to compare. */
15103 	    break;
15104     }
15105 
15106     return SCORE_MAXMAX;
15107 }
15108 
15109 /*
15110  * Compute the "edit distance" to turn "badword" into "goodword".  The less
15111  * deletes/inserts/substitutes/swaps are required the lower the score.
15112  *
15113  * The algorithm is described by Du and Chang, 1992.
15114  * The implementation of the algorithm comes from Aspell editdist.cpp,
15115  * edit_distance().  It has been converted from C++ to C and modified to
15116  * support multi-byte characters.
15117  */
15118     static int
15119 spell_edit_score(slang, badword, goodword)
15120     slang_T	*slang;
15121     char_u	*badword;
15122     char_u	*goodword;
15123 {
15124     int		*cnt;
15125     int		badlen, goodlen;	/* lengths including NUL */
15126     int		j, i;
15127     int		t;
15128     int		bc, gc;
15129     int		pbc, pgc;
15130 #ifdef FEAT_MBYTE
15131     char_u	*p;
15132     int		wbadword[MAXWLEN];
15133     int		wgoodword[MAXWLEN];
15134 
15135     if (has_mbyte)
15136     {
15137 	/* Get the characters from the multi-byte strings and put them in an
15138 	 * int array for easy access. */
15139 	for (p = badword, badlen = 0; *p != NUL; )
15140 	    wbadword[badlen++] = mb_cptr2char_adv(&p);
15141 	wbadword[badlen++] = 0;
15142 	for (p = goodword, goodlen = 0; *p != NUL; )
15143 	    wgoodword[goodlen++] = mb_cptr2char_adv(&p);
15144 	wgoodword[goodlen++] = 0;
15145     }
15146     else
15147 #endif
15148     {
15149 	badlen = (int)STRLEN(badword) + 1;
15150 	goodlen = (int)STRLEN(goodword) + 1;
15151     }
15152 
15153     /* We use "cnt" as an array: CNT(badword_idx, goodword_idx). */
15154 #define CNT(a, b)   cnt[(a) + (b) * (badlen + 1)]
15155     cnt = (int *)lalloc((long_u)(sizeof(int) * (badlen + 1) * (goodlen + 1)),
15156 									TRUE);
15157     if (cnt == NULL)
15158 	return 0;	/* out of memory */
15159 
15160     CNT(0, 0) = 0;
15161     for (j = 1; j <= goodlen; ++j)
15162 	CNT(0, j) = CNT(0, j - 1) + SCORE_INS;
15163 
15164     for (i = 1; i <= badlen; ++i)
15165     {
15166 	CNT(i, 0) = CNT(i - 1, 0) + SCORE_DEL;
15167 	for (j = 1; j <= goodlen; ++j)
15168 	{
15169 #ifdef FEAT_MBYTE
15170 	    if (has_mbyte)
15171 	    {
15172 		bc = wbadword[i - 1];
15173 		gc = wgoodword[j - 1];
15174 	    }
15175 	    else
15176 #endif
15177 	    {
15178 		bc = badword[i - 1];
15179 		gc = goodword[j - 1];
15180 	    }
15181 	    if (bc == gc)
15182 		CNT(i, j) = CNT(i - 1, j - 1);
15183 	    else
15184 	    {
15185 		/* Use a better score when there is only a case difference. */
15186 		if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15187 		    CNT(i, j) = SCORE_ICASE + CNT(i - 1, j - 1);
15188 		else
15189 		{
15190 		    /* For a similar character use SCORE_SIMILAR. */
15191 		    if (slang != NULL
15192 			    && slang->sl_has_map
15193 			    && similar_chars(slang, gc, bc))
15194 			CNT(i, j) = SCORE_SIMILAR + CNT(i - 1, j - 1);
15195 		    else
15196 			CNT(i, j) = SCORE_SUBST + CNT(i - 1, j - 1);
15197 		}
15198 
15199 		if (i > 1 && j > 1)
15200 		{
15201 #ifdef FEAT_MBYTE
15202 		    if (has_mbyte)
15203 		    {
15204 			pbc = wbadword[i - 2];
15205 			pgc = wgoodword[j - 2];
15206 		    }
15207 		    else
15208 #endif
15209 		    {
15210 			pbc = badword[i - 2];
15211 			pgc = goodword[j - 2];
15212 		    }
15213 		    if (bc == pgc && pbc == gc)
15214 		    {
15215 			t = SCORE_SWAP + CNT(i - 2, j - 2);
15216 			if (t < CNT(i, j))
15217 			    CNT(i, j) = t;
15218 		    }
15219 		}
15220 		t = SCORE_DEL + CNT(i - 1, j);
15221 		if (t < CNT(i, j))
15222 		    CNT(i, j) = t;
15223 		t = SCORE_INS + CNT(i, j - 1);
15224 		if (t < CNT(i, j))
15225 		    CNT(i, j) = t;
15226 	    }
15227 	}
15228     }
15229 
15230     i = CNT(badlen - 1, goodlen - 1);
15231     vim_free(cnt);
15232     return i;
15233 }
15234 
15235 typedef struct
15236 {
15237     int		badi;
15238     int		goodi;
15239     int		score;
15240 } limitscore_T;
15241 
15242 /*
15243  * Like spell_edit_score(), but with a limit on the score to make it faster.
15244  * May return SCORE_MAXMAX when the score is higher than "limit".
15245  *
15246  * This uses a stack for the edits still to be tried.
15247  * The idea comes from Aspell leditdist.cpp.  Rewritten in C and added support
15248  * for multi-byte characters.
15249  */
15250     static int
15251 spell_edit_score_limit(slang, badword, goodword, limit)
15252     slang_T	*slang;
15253     char_u	*badword;
15254     char_u	*goodword;
15255     int		limit;
15256 {
15257     limitscore_T    stack[10];		/* allow for over 3 * 2 edits */
15258     int		    stackidx;
15259     int		    bi, gi;
15260     int		    bi2, gi2;
15261     int		    bc, gc;
15262     int		    score;
15263     int		    score_off;
15264     int		    minscore;
15265     int		    round;
15266 
15267 #ifdef FEAT_MBYTE
15268     /* Multi-byte characters require a bit more work, use a different function
15269      * to avoid testing "has_mbyte" quite often. */
15270     if (has_mbyte)
15271 	return spell_edit_score_limit_w(slang, badword, goodword, limit);
15272 #endif
15273 
15274     /*
15275      * The idea is to go from start to end over the words.  So long as
15276      * characters are equal just continue, this always gives the lowest score.
15277      * When there is a difference try several alternatives.  Each alternative
15278      * increases "score" for the edit distance.  Some of the alternatives are
15279      * pushed unto a stack and tried later, some are tried right away.  At the
15280      * end of the word the score for one alternative is known.  The lowest
15281      * possible score is stored in "minscore".
15282      */
15283     stackidx = 0;
15284     bi = 0;
15285     gi = 0;
15286     score = 0;
15287     minscore = limit + 1;
15288 
15289     for (;;)
15290     {
15291 	/* Skip over an equal part, score remains the same. */
15292 	for (;;)
15293 	{
15294 	    bc = badword[bi];
15295 	    gc = goodword[gi];
15296 	    if (bc != gc)	/* stop at a char that's different */
15297 		break;
15298 	    if (bc == NUL)	/* both words end */
15299 	    {
15300 		if (score < minscore)
15301 		    minscore = score;
15302 		goto pop;	/* do next alternative */
15303 	    }
15304 	    ++bi;
15305 	    ++gi;
15306 	}
15307 
15308 	if (gc == NUL)    /* goodword ends, delete badword chars */
15309 	{
15310 	    do
15311 	    {
15312 		if ((score += SCORE_DEL) >= minscore)
15313 		    goto pop;	    /* do next alternative */
15314 	    } while (badword[++bi] != NUL);
15315 	    minscore = score;
15316 	}
15317 	else if (bc == NUL) /* badword ends, insert badword chars */
15318 	{
15319 	    do
15320 	    {
15321 		if ((score += SCORE_INS) >= minscore)
15322 		    goto pop;	    /* do next alternative */
15323 	    } while (goodword[++gi] != NUL);
15324 	    minscore = score;
15325 	}
15326 	else			/* both words continue */
15327 	{
15328 	    /* If not close to the limit, perform a change.  Only try changes
15329 	     * that may lead to a lower score than "minscore".
15330 	     * round 0: try deleting a char from badword
15331 	     * round 1: try inserting a char in badword */
15332 	    for (round = 0; round <= 1; ++round)
15333 	    {
15334 		score_off = score + (round == 0 ? SCORE_DEL : SCORE_INS);
15335 		if (score_off < minscore)
15336 		{
15337 		    if (score_off + SCORE_EDIT_MIN >= minscore)
15338 		    {
15339 			/* Near the limit, rest of the words must match.  We
15340 			 * can check that right now, no need to push an item
15341 			 * onto the stack. */
15342 			bi2 = bi + 1 - round;
15343 			gi2 = gi + round;
15344 			while (goodword[gi2] == badword[bi2])
15345 			{
15346 			    if (goodword[gi2] == NUL)
15347 			    {
15348 				minscore = score_off;
15349 				break;
15350 			    }
15351 			    ++bi2;
15352 			    ++gi2;
15353 			}
15354 		    }
15355 		    else
15356 		    {
15357 			/* try deleting/inserting a character later */
15358 			stack[stackidx].badi = bi + 1 - round;
15359 			stack[stackidx].goodi = gi + round;
15360 			stack[stackidx].score = score_off;
15361 			++stackidx;
15362 		    }
15363 		}
15364 	    }
15365 
15366 	    if (score + SCORE_SWAP < minscore)
15367 	    {
15368 		/* If swapping two characters makes a match then the
15369 		 * substitution is more expensive, thus there is no need to
15370 		 * try both. */
15371 		if (gc == badword[bi + 1] && bc == goodword[gi + 1])
15372 		{
15373 		    /* Swap two characters, that is: skip them. */
15374 		    gi += 2;
15375 		    bi += 2;
15376 		    score += SCORE_SWAP;
15377 		    continue;
15378 		}
15379 	    }
15380 
15381 	    /* Substitute one character for another which is the same
15382 	     * thing as deleting a character from both goodword and badword.
15383 	     * Use a better score when there is only a case difference. */
15384 	    if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15385 		score += SCORE_ICASE;
15386 	    else
15387 	    {
15388 		/* For a similar character use SCORE_SIMILAR. */
15389 		if (slang != NULL
15390 			&& slang->sl_has_map
15391 			&& similar_chars(slang, gc, bc))
15392 		    score += SCORE_SIMILAR;
15393 		else
15394 		    score += SCORE_SUBST;
15395 	    }
15396 
15397 	    if (score < minscore)
15398 	    {
15399 		/* Do the substitution. */
15400 		++gi;
15401 		++bi;
15402 		continue;
15403 	    }
15404 	}
15405 pop:
15406 	/*
15407 	 * Get here to try the next alternative, pop it from the stack.
15408 	 */
15409 	if (stackidx == 0)		/* stack is empty, finished */
15410 	    break;
15411 
15412 	/* pop an item from the stack */
15413 	--stackidx;
15414 	gi = stack[stackidx].goodi;
15415 	bi = stack[stackidx].badi;
15416 	score = stack[stackidx].score;
15417     }
15418 
15419     /* When the score goes over "limit" it may actually be much higher.
15420      * Return a very large number to avoid going below the limit when giving a
15421      * bonus. */
15422     if (minscore > limit)
15423 	return SCORE_MAXMAX;
15424     return minscore;
15425 }
15426 
15427 #ifdef FEAT_MBYTE
15428 /*
15429  * Multi-byte version of spell_edit_score_limit().
15430  * Keep it in sync with the above!
15431  */
15432     static int
15433 spell_edit_score_limit_w(slang, badword, goodword, limit)
15434     slang_T	*slang;
15435     char_u	*badword;
15436     char_u	*goodword;
15437     int		limit;
15438 {
15439     limitscore_T    stack[10];		/* allow for over 3 * 2 edits */
15440     int		    stackidx;
15441     int		    bi, gi;
15442     int		    bi2, gi2;
15443     int		    bc, gc;
15444     int		    score;
15445     int		    score_off;
15446     int		    minscore;
15447     int		    round;
15448     char_u	    *p;
15449     int		    wbadword[MAXWLEN];
15450     int		    wgoodword[MAXWLEN];
15451 
15452     /* Get the characters from the multi-byte strings and put them in an
15453      * int array for easy access. */
15454     bi = 0;
15455     for (p = badword; *p != NUL; )
15456 	wbadword[bi++] = mb_cptr2char_adv(&p);
15457     wbadword[bi++] = 0;
15458     gi = 0;
15459     for (p = goodword; *p != NUL; )
15460 	wgoodword[gi++] = mb_cptr2char_adv(&p);
15461     wgoodword[gi++] = 0;
15462 
15463     /*
15464      * The idea is to go from start to end over the words.  So long as
15465      * characters are equal just continue, this always gives the lowest score.
15466      * When there is a difference try several alternatives.  Each alternative
15467      * increases "score" for the edit distance.  Some of the alternatives are
15468      * pushed unto a stack and tried later, some are tried right away.  At the
15469      * end of the word the score for one alternative is known.  The lowest
15470      * possible score is stored in "minscore".
15471      */
15472     stackidx = 0;
15473     bi = 0;
15474     gi = 0;
15475     score = 0;
15476     minscore = limit + 1;
15477 
15478     for (;;)
15479     {
15480 	/* Skip over an equal part, score remains the same. */
15481 	for (;;)
15482 	{
15483 	    bc = wbadword[bi];
15484 	    gc = wgoodword[gi];
15485 
15486 	    if (bc != gc)	/* stop at a char that's different */
15487 		break;
15488 	    if (bc == NUL)	/* both words end */
15489 	    {
15490 		if (score < minscore)
15491 		    minscore = score;
15492 		goto pop;	/* do next alternative */
15493 	    }
15494 	    ++bi;
15495 	    ++gi;
15496 	}
15497 
15498 	if (gc == NUL)    /* goodword ends, delete badword chars */
15499 	{
15500 	    do
15501 	    {
15502 		if ((score += SCORE_DEL) >= minscore)
15503 		    goto pop;	    /* do next alternative */
15504 	    } while (wbadword[++bi] != NUL);
15505 	    minscore = score;
15506 	}
15507 	else if (bc == NUL) /* badword ends, insert badword chars */
15508 	{
15509 	    do
15510 	    {
15511 		if ((score += SCORE_INS) >= minscore)
15512 		    goto pop;	    /* do next alternative */
15513 	    } while (wgoodword[++gi] != NUL);
15514 	    minscore = score;
15515 	}
15516 	else			/* both words continue */
15517 	{
15518 	    /* If not close to the limit, perform a change.  Only try changes
15519 	     * that may lead to a lower score than "minscore".
15520 	     * round 0: try deleting a char from badword
15521 	     * round 1: try inserting a char in badword */
15522 	    for (round = 0; round <= 1; ++round)
15523 	    {
15524 		score_off = score + (round == 0 ? SCORE_DEL : SCORE_INS);
15525 		if (score_off < minscore)
15526 		{
15527 		    if (score_off + SCORE_EDIT_MIN >= minscore)
15528 		    {
15529 			/* Near the limit, rest of the words must match.  We
15530 			 * can check that right now, no need to push an item
15531 			 * onto the stack. */
15532 			bi2 = bi + 1 - round;
15533 			gi2 = gi + round;
15534 			while (wgoodword[gi2] == wbadword[bi2])
15535 			{
15536 			    if (wgoodword[gi2] == NUL)
15537 			    {
15538 				minscore = score_off;
15539 				break;
15540 			    }
15541 			    ++bi2;
15542 			    ++gi2;
15543 			}
15544 		    }
15545 		    else
15546 		    {
15547 			/* try deleting a character from badword later */
15548 			stack[stackidx].badi = bi + 1 - round;
15549 			stack[stackidx].goodi = gi + round;
15550 			stack[stackidx].score = score_off;
15551 			++stackidx;
15552 		    }
15553 		}
15554 	    }
15555 
15556 	    if (score + SCORE_SWAP < minscore)
15557 	    {
15558 		/* If swapping two characters makes a match then the
15559 		 * substitution is more expensive, thus there is no need to
15560 		 * try both. */
15561 		if (gc == wbadword[bi + 1] && bc == wgoodword[gi + 1])
15562 		{
15563 		    /* Swap two characters, that is: skip them. */
15564 		    gi += 2;
15565 		    bi += 2;
15566 		    score += SCORE_SWAP;
15567 		    continue;
15568 		}
15569 	    }
15570 
15571 	    /* Substitute one character for another which is the same
15572 	     * thing as deleting a character from both goodword and badword.
15573 	     * Use a better score when there is only a case difference. */
15574 	    if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15575 		score += SCORE_ICASE;
15576 	    else
15577 	    {
15578 		/* For a similar character use SCORE_SIMILAR. */
15579 		if (slang != NULL
15580 			&& slang->sl_has_map
15581 			&& similar_chars(slang, gc, bc))
15582 		    score += SCORE_SIMILAR;
15583 		else
15584 		    score += SCORE_SUBST;
15585 	    }
15586 
15587 	    if (score < minscore)
15588 	    {
15589 		/* Do the substitution. */
15590 		++gi;
15591 		++bi;
15592 		continue;
15593 	    }
15594 	}
15595 pop:
15596 	/*
15597 	 * Get here to try the next alternative, pop it from the stack.
15598 	 */
15599 	if (stackidx == 0)		/* stack is empty, finished */
15600 	    break;
15601 
15602 	/* pop an item from the stack */
15603 	--stackidx;
15604 	gi = stack[stackidx].goodi;
15605 	bi = stack[stackidx].badi;
15606 	score = stack[stackidx].score;
15607     }
15608 
15609     /* When the score goes over "limit" it may actually be much higher.
15610      * Return a very large number to avoid going below the limit when giving a
15611      * bonus. */
15612     if (minscore > limit)
15613 	return SCORE_MAXMAX;
15614     return minscore;
15615 }
15616 #endif
15617 
15618 /*
15619  * ":spellinfo"
15620  */
15621     void
15622 ex_spellinfo(eap)
15623     exarg_T *eap UNUSED;
15624 {
15625     int		lpi;
15626     langp_T	*lp;
15627     char_u	*p;
15628 
15629     if (no_spell_checking(curwin))
15630 	return;
15631 
15632     msg_start();
15633     for (lpi = 0; lpi < curbuf->b_langp.ga_len && !got_int; ++lpi)
15634     {
15635 	lp = LANGP_ENTRY(curbuf->b_langp, lpi);
15636 	msg_puts((char_u *)"file: ");
15637 	msg_puts(lp->lp_slang->sl_fname);
15638 	msg_putchar('\n');
15639 	p = lp->lp_slang->sl_info;
15640 	if (p != NULL)
15641 	{
15642 	    msg_puts(p);
15643 	    msg_putchar('\n');
15644 	}
15645     }
15646     msg_end();
15647 }
15648 
15649 #define DUMPFLAG_KEEPCASE   1	/* round 2: keep-case tree */
15650 #define DUMPFLAG_COUNT	    2	/* include word count */
15651 #define DUMPFLAG_ICASE	    4	/* ignore case when finding matches */
15652 #define DUMPFLAG_ONECAP	    8	/* pattern starts with capital */
15653 #define DUMPFLAG_ALLCAP	    16	/* pattern is all capitals */
15654 
15655 /*
15656  * ":spelldump"
15657  */
15658     void
15659 ex_spelldump(eap)
15660     exarg_T *eap;
15661 {
15662     buf_T	*buf = curbuf;
15663 
15664     if (no_spell_checking(curwin))
15665 	return;
15666 
15667     /* Create a new empty buffer by splitting the window. */
15668     do_cmdline_cmd((char_u *)"new");
15669     if (!bufempty() || !buf_valid(buf))
15670 	return;
15671 
15672     spell_dump_compl(buf, NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0);
15673 
15674     /* Delete the empty line that we started with. */
15675     if (curbuf->b_ml.ml_line_count > 1)
15676 	ml_delete(curbuf->b_ml.ml_line_count, FALSE);
15677 
15678     redraw_later(NOT_VALID);
15679 }
15680 
15681 /*
15682  * Go through all possible words and:
15683  * 1. When "pat" is NULL: dump a list of all words in the current buffer.
15684  *	"ic" and "dir" are not used.
15685  * 2. When "pat" is not NULL: add matching words to insert mode completion.
15686  */
15687     void
15688 spell_dump_compl(buf, pat, ic, dir, dumpflags_arg)
15689     buf_T	*buf;	    /* buffer with spell checking */
15690     char_u	*pat;	    /* leading part of the word */
15691     int		ic;	    /* ignore case */
15692     int		*dir;	    /* direction for adding matches */
15693     int		dumpflags_arg;	/* DUMPFLAG_* */
15694 {
15695     langp_T	*lp;
15696     slang_T	*slang;
15697     idx_T	arridx[MAXWLEN];
15698     int		curi[MAXWLEN];
15699     char_u	word[MAXWLEN];
15700     int		c;
15701     char_u	*byts;
15702     idx_T	*idxs;
15703     linenr_T	lnum = 0;
15704     int		round;
15705     int		depth;
15706     int		n;
15707     int		flags;
15708     char_u	*region_names = NULL;	    /* region names being used */
15709     int		do_region = TRUE;	    /* dump region names and numbers */
15710     char_u	*p;
15711     int		lpi;
15712     int		dumpflags = dumpflags_arg;
15713     int		patlen;
15714 
15715     /* When ignoring case or when the pattern starts with capital pass this on
15716      * to dump_word(). */
15717     if (pat != NULL)
15718     {
15719 	if (ic)
15720 	    dumpflags |= DUMPFLAG_ICASE;
15721 	else
15722 	{
15723 	    n = captype(pat, NULL);
15724 	    if (n == WF_ONECAP)
15725 		dumpflags |= DUMPFLAG_ONECAP;
15726 	    else if (n == WF_ALLCAP
15727 #ifdef FEAT_MBYTE
15728 		    && (int)STRLEN(pat) > mb_ptr2len(pat)
15729 #else
15730 		    && (int)STRLEN(pat) > 1
15731 #endif
15732 		    )
15733 		dumpflags |= DUMPFLAG_ALLCAP;
15734 	}
15735     }
15736 
15737     /* Find out if we can support regions: All languages must support the same
15738      * regions or none at all. */
15739     for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
15740     {
15741 	lp = LANGP_ENTRY(buf->b_langp, lpi);
15742 	p = lp->lp_slang->sl_regions;
15743 	if (p[0] != 0)
15744 	{
15745 	    if (region_names == NULL)	    /* first language with regions */
15746 		region_names = p;
15747 	    else if (STRCMP(region_names, p) != 0)
15748 	    {
15749 		do_region = FALSE;	    /* region names are different */
15750 		break;
15751 	    }
15752 	}
15753     }
15754 
15755     if (do_region && region_names != NULL)
15756     {
15757 	if (pat == NULL)
15758 	{
15759 	    vim_snprintf((char *)IObuff, IOSIZE, "/regions=%s", region_names);
15760 	    ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
15761 	}
15762     }
15763     else
15764 	do_region = FALSE;
15765 
15766     /*
15767      * Loop over all files loaded for the entries in 'spelllang'.
15768      */
15769     for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
15770     {
15771 	lp = LANGP_ENTRY(buf->b_langp, lpi);
15772 	slang = lp->lp_slang;
15773 	if (slang->sl_fbyts == NULL)	    /* reloading failed */
15774 	    continue;
15775 
15776 	if (pat == NULL)
15777 	{
15778 	    vim_snprintf((char *)IObuff, IOSIZE, "# file: %s", slang->sl_fname);
15779 	    ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
15780 	}
15781 
15782 	/* When matching with a pattern and there are no prefixes only use
15783 	 * parts of the tree that match "pat". */
15784 	if (pat != NULL && slang->sl_pbyts == NULL)
15785 	    patlen = (int)STRLEN(pat);
15786 	else
15787 	    patlen = -1;
15788 
15789 	/* round 1: case-folded tree
15790 	 * round 2: keep-case tree */
15791 	for (round = 1; round <= 2; ++round)
15792 	{
15793 	    if (round == 1)
15794 	    {
15795 		dumpflags &= ~DUMPFLAG_KEEPCASE;
15796 		byts = slang->sl_fbyts;
15797 		idxs = slang->sl_fidxs;
15798 	    }
15799 	    else
15800 	    {
15801 		dumpflags |= DUMPFLAG_KEEPCASE;
15802 		byts = slang->sl_kbyts;
15803 		idxs = slang->sl_kidxs;
15804 	    }
15805 	    if (byts == NULL)
15806 		continue;		/* array is empty */
15807 
15808 	    depth = 0;
15809 	    arridx[0] = 0;
15810 	    curi[0] = 1;
15811 	    while (depth >= 0 && !got_int
15812 				       && (pat == NULL || !compl_interrupted))
15813 	    {
15814 		if (curi[depth] > byts[arridx[depth]])
15815 		{
15816 		    /* Done all bytes at this node, go up one level. */
15817 		    --depth;
15818 		    line_breakcheck();
15819 		    ins_compl_check_keys(50);
15820 		}
15821 		else
15822 		{
15823 		    /* Do one more byte at this node. */
15824 		    n = arridx[depth] + curi[depth];
15825 		    ++curi[depth];
15826 		    c = byts[n];
15827 		    if (c == 0)
15828 		    {
15829 			/* End of word, deal with the word.
15830 			 * Don't use keep-case words in the fold-case tree,
15831 			 * they will appear in the keep-case tree.
15832 			 * Only use the word when the region matches. */
15833 			flags = (int)idxs[n];
15834 			if ((round == 2 || (flags & WF_KEEPCAP) == 0)
15835 				&& (flags & WF_NEEDCOMP) == 0
15836 				&& (do_region
15837 				    || (flags & WF_REGION) == 0
15838 				    || (((unsigned)flags >> 16)
15839 						       & lp->lp_region) != 0))
15840 			{
15841 			    word[depth] = NUL;
15842 			    if (!do_region)
15843 				flags &= ~WF_REGION;
15844 
15845 			    /* Dump the basic word if there is no prefix or
15846 			     * when it's the first one. */
15847 			    c = (unsigned)flags >> 24;
15848 			    if (c == 0 || curi[depth] == 2)
15849 			    {
15850 				dump_word(slang, word, pat, dir,
15851 						      dumpflags, flags, lnum);
15852 				if (pat == NULL)
15853 				    ++lnum;
15854 			    }
15855 
15856 			    /* Apply the prefix, if there is one. */
15857 			    if (c != 0)
15858 				lnum = dump_prefixes(slang, word, pat, dir,
15859 						      dumpflags, flags, lnum);
15860 			}
15861 		    }
15862 		    else
15863 		    {
15864 			/* Normal char, go one level deeper. */
15865 			word[depth++] = c;
15866 			arridx[depth] = idxs[n];
15867 			curi[depth] = 1;
15868 
15869 			/* Check if this characters matches with the pattern.
15870 			 * If not skip the whole tree below it.
15871 			 * Always ignore case here, dump_word() will check
15872 			 * proper case later.  This isn't exactly right when
15873 			 * length changes for multi-byte characters with
15874 			 * ignore case... */
15875 			if (depth <= patlen
15876 					&& MB_STRNICMP(word, pat, depth) != 0)
15877 			    --depth;
15878 		    }
15879 		}
15880 	    }
15881 	}
15882     }
15883 }
15884 
15885 /*
15886  * Dump one word: apply case modifications and append a line to the buffer.
15887  * When "lnum" is zero add insert mode completion.
15888  */
15889     static void
15890 dump_word(slang, word, pat, dir, dumpflags, wordflags, lnum)
15891     slang_T	*slang;
15892     char_u	*word;
15893     char_u	*pat;
15894     int		*dir;
15895     int		dumpflags;
15896     int		wordflags;
15897     linenr_T	lnum;
15898 {
15899     int		keepcap = FALSE;
15900     char_u	*p;
15901     char_u	*tw;
15902     char_u	cword[MAXWLEN];
15903     char_u	badword[MAXWLEN + 10];
15904     int		i;
15905     int		flags = wordflags;
15906 
15907     if (dumpflags & DUMPFLAG_ONECAP)
15908 	flags |= WF_ONECAP;
15909     if (dumpflags & DUMPFLAG_ALLCAP)
15910 	flags |= WF_ALLCAP;
15911 
15912     if ((dumpflags & DUMPFLAG_KEEPCASE) == 0 && (flags & WF_CAPMASK) != 0)
15913     {
15914 	/* Need to fix case according to "flags". */
15915 	make_case_word(word, cword, flags);
15916 	p = cword;
15917     }
15918     else
15919     {
15920 	p = word;
15921 	if ((dumpflags & DUMPFLAG_KEEPCASE)
15922 		&& ((captype(word, NULL) & WF_KEEPCAP) == 0
15923 						 || (flags & WF_FIXCAP) != 0))
15924 	    keepcap = TRUE;
15925     }
15926     tw = p;
15927 
15928     if (pat == NULL)
15929     {
15930 	/* Add flags and regions after a slash. */
15931 	if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap)
15932 	{
15933 	    STRCPY(badword, p);
15934 	    STRCAT(badword, "/");
15935 	    if (keepcap)
15936 		STRCAT(badword, "=");
15937 	    if (flags & WF_BANNED)
15938 		STRCAT(badword, "!");
15939 	    else if (flags & WF_RARE)
15940 		STRCAT(badword, "?");
15941 	    if (flags & WF_REGION)
15942 		for (i = 0; i < 7; ++i)
15943 		    if (flags & (0x10000 << i))
15944 			sprintf((char *)badword + STRLEN(badword), "%d", i + 1);
15945 	    p = badword;
15946 	}
15947 
15948 	if (dumpflags & DUMPFLAG_COUNT)
15949 	{
15950 	    hashitem_T  *hi;
15951 
15952 	    /* Include the word count for ":spelldump!". */
15953 	    hi = hash_find(&slang->sl_wordcount, tw);
15954 	    if (!HASHITEM_EMPTY(hi))
15955 	    {
15956 		vim_snprintf((char *)IObuff, IOSIZE, "%s\t%d",
15957 						     tw, HI2WC(hi)->wc_count);
15958 		p = IObuff;
15959 	    }
15960 	}
15961 
15962 	ml_append(lnum, p, (colnr_T)0, FALSE);
15963     }
15964     else if (((dumpflags & DUMPFLAG_ICASE)
15965 		    ? MB_STRNICMP(p, pat, STRLEN(pat)) == 0
15966 		    : STRNCMP(p, pat, STRLEN(pat)) == 0)
15967 		&& ins_compl_add_infercase(p, (int)STRLEN(p),
15968 					  p_ic, NULL, *dir, 0) == OK)
15969 	/* if dir was BACKWARD then honor it just once */
15970 	*dir = FORWARD;
15971 }
15972 
15973 /*
15974  * For ":spelldump": Find matching prefixes for "word".  Prepend each to
15975  * "word" and append a line to the buffer.
15976  * When "lnum" is zero add insert mode completion.
15977  * Return the updated line number.
15978  */
15979     static linenr_T
15980 dump_prefixes(slang, word, pat, dir, dumpflags, flags, startlnum)
15981     slang_T	*slang;
15982     char_u	*word;	    /* case-folded word */
15983     char_u	*pat;
15984     int		*dir;
15985     int		dumpflags;
15986     int		flags;	    /* flags with prefix ID */
15987     linenr_T	startlnum;
15988 {
15989     idx_T	arridx[MAXWLEN];
15990     int		curi[MAXWLEN];
15991     char_u	prefix[MAXWLEN];
15992     char_u	word_up[MAXWLEN];
15993     int		has_word_up = FALSE;
15994     int		c;
15995     char_u	*byts;
15996     idx_T	*idxs;
15997     linenr_T	lnum = startlnum;
15998     int		depth;
15999     int		n;
16000     int		len;
16001     int		i;
16002 
16003     /* If the word starts with a lower-case letter make the word with an
16004      * upper-case letter in word_up[]. */
16005     c = PTR2CHAR(word);
16006     if (SPELL_TOUPPER(c) != c)
16007     {
16008 	onecap_copy(word, word_up, TRUE);
16009 	has_word_up = TRUE;
16010     }
16011 
16012     byts = slang->sl_pbyts;
16013     idxs = slang->sl_pidxs;
16014     if (byts != NULL)		/* array not is empty */
16015     {
16016 	/*
16017 	 * Loop over all prefixes, building them byte-by-byte in prefix[].
16018 	 * When at the end of a prefix check that it supports "flags".
16019 	 */
16020 	depth = 0;
16021 	arridx[0] = 0;
16022 	curi[0] = 1;
16023 	while (depth >= 0 && !got_int)
16024 	{
16025 	    n = arridx[depth];
16026 	    len = byts[n];
16027 	    if (curi[depth] > len)
16028 	    {
16029 		/* Done all bytes at this node, go up one level. */
16030 		--depth;
16031 		line_breakcheck();
16032 	    }
16033 	    else
16034 	    {
16035 		/* Do one more byte at this node. */
16036 		n += curi[depth];
16037 		++curi[depth];
16038 		c = byts[n];
16039 		if (c == 0)
16040 		{
16041 		    /* End of prefix, find out how many IDs there are. */
16042 		    for (i = 1; i < len; ++i)
16043 			if (byts[n + i] != 0)
16044 			    break;
16045 		    curi[depth] += i - 1;
16046 
16047 		    c = valid_word_prefix(i, n, flags, word, slang, FALSE);
16048 		    if (c != 0)
16049 		    {
16050 			vim_strncpy(prefix + depth, word, MAXWLEN - depth - 1);
16051 			dump_word(slang, prefix, pat, dir, dumpflags,
16052 				(c & WF_RAREPFX) ? (flags | WF_RARE)
16053 							       : flags, lnum);
16054 			if (lnum != 0)
16055 			    ++lnum;
16056 		    }
16057 
16058 		    /* Check for prefix that matches the word when the
16059 		     * first letter is upper-case, but only if the prefix has
16060 		     * a condition. */
16061 		    if (has_word_up)
16062 		    {
16063 			c = valid_word_prefix(i, n, flags, word_up, slang,
16064 									TRUE);
16065 			if (c != 0)
16066 			{
16067 			    vim_strncpy(prefix + depth, word_up,
16068 							 MAXWLEN - depth - 1);
16069 			    dump_word(slang, prefix, pat, dir, dumpflags,
16070 				    (c & WF_RAREPFX) ? (flags | WF_RARE)
16071 							       : flags, lnum);
16072 			    if (lnum != 0)
16073 				++lnum;
16074 			}
16075 		    }
16076 		}
16077 		else
16078 		{
16079 		    /* Normal char, go one level deeper. */
16080 		    prefix[depth++] = c;
16081 		    arridx[depth] = idxs[n];
16082 		    curi[depth] = 1;
16083 		}
16084 	    }
16085 	}
16086     }
16087 
16088     return lnum;
16089 }
16090 
16091 /*
16092  * Move "p" to the end of word "start".
16093  * Uses the spell-checking word characters.
16094  */
16095     char_u *
16096 spell_to_word_end(start, buf)
16097     char_u  *start;
16098     buf_T   *buf;
16099 {
16100     char_u  *p = start;
16101 
16102     while (*p != NUL && spell_iswordp(p, buf))
16103 	mb_ptr_adv(p);
16104     return p;
16105 }
16106 
16107 #if defined(FEAT_INS_EXPAND) || defined(PROTO)
16108 /*
16109  * For Insert mode completion CTRL-X s:
16110  * Find start of the word in front of column "startcol".
16111  * We don't check if it is badly spelled, with completion we can only change
16112  * the word in front of the cursor.
16113  * Returns the column number of the word.
16114  */
16115     int
16116 spell_word_start(startcol)
16117     int		startcol;
16118 {
16119     char_u	*line;
16120     char_u	*p;
16121     int		col = 0;
16122 
16123     if (no_spell_checking(curwin))
16124 	return startcol;
16125 
16126     /* Find a word character before "startcol". */
16127     line = ml_get_curline();
16128     for (p = line + startcol; p > line; )
16129     {
16130 	mb_ptr_back(line, p);
16131 	if (spell_iswordp_nmw(p))
16132 	    break;
16133     }
16134 
16135     /* Go back to start of the word. */
16136     while (p > line)
16137     {
16138 	col = (int)(p - line);
16139 	mb_ptr_back(line, p);
16140 	if (!spell_iswordp(p, curbuf))
16141 	    break;
16142 	col = 0;
16143     }
16144 
16145     return col;
16146 }
16147 
16148 /*
16149  * Need to check for 'spellcapcheck' now, the word is removed before
16150  * expand_spelling() is called.  Therefore the ugly global variable.
16151  */
16152 static int spell_expand_need_cap;
16153 
16154     void
16155 spell_expand_check_cap(col)
16156     colnr_T col;
16157 {
16158     spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col);
16159 }
16160 
16161 /*
16162  * Get list of spelling suggestions.
16163  * Used for Insert mode completion CTRL-X ?.
16164  * Returns the number of matches.  The matches are in "matchp[]", array of
16165  * allocated strings.
16166  */
16167     int
16168 expand_spelling(lnum, pat, matchp)
16169     linenr_T	lnum UNUSED;
16170     char_u	*pat;
16171     char_u	***matchp;
16172 {
16173     garray_T	ga;
16174 
16175     spell_suggest_list(&ga, pat, 100, spell_expand_need_cap, TRUE);
16176     *matchp = ga.ga_data;
16177     return ga.ga_len;
16178 }
16179 #endif
16180 
16181 #endif  /* FEAT_SPELL */
16182