xref: /vim-8.2.3635/src/spell.c (revision cc7ff3fc)
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 #include "vim.h"
307 
308 #if defined(FEAT_SPELL) || defined(PROTO)
309 
310 #ifndef UNIX		/* it's in os_unix.h for Unix */
311 # include <time.h>	/* for time_t */
312 #endif
313 
314 #define MAXWLEN 254		/* Assume max. word len is this many bytes.
315 				   Some places assume a word length fits in a
316 				   byte, thus it can't be above 255.
317 				   Must be >= PFD_NOTSPECIAL. */
318 
319 /* Type used for indexes in the word tree need to be at least 4 bytes.  If int
320  * is 8 bytes we could use something smaller, but what? */
321 #if VIM_SIZEOF_INT > 3
322 typedef int idx_T;
323 #else
324 typedef long idx_T;
325 #endif
326 
327 #ifdef VMS
328 # define SPL_FNAME_TMPL  "%s_%s.spl"
329 # define SPL_FNAME_ADD   "_add."
330 # define SPL_FNAME_ASCII "_ascii."
331 #else
332 # define SPL_FNAME_TMPL  "%s.%s.spl"
333 # define SPL_FNAME_ADD   ".add."
334 # define SPL_FNAME_ASCII ".ascii."
335 #endif
336 
337 /* Flags used for a word.  Only the lowest byte can be used, the region byte
338  * comes above it. */
339 #define WF_REGION   0x01	/* region byte follows */
340 #define WF_ONECAP   0x02	/* word with one capital (or all capitals) */
341 #define WF_ALLCAP   0x04	/* word must be all capitals */
342 #define WF_RARE	    0x08	/* rare word */
343 #define WF_BANNED   0x10	/* bad word */
344 #define WF_AFX	    0x20	/* affix ID follows */
345 #define WF_FIXCAP   0x40	/* keep-case word, allcap not allowed */
346 #define WF_KEEPCAP  0x80	/* keep-case word */
347 
348 /* for <flags2>, shifted up one byte to be used in wn_flags */
349 #define WF_HAS_AFF  0x0100	/* word includes affix */
350 #define WF_NEEDCOMP 0x0200	/* word only valid in compound */
351 #define WF_NOSUGGEST 0x0400	/* word not to be suggested */
352 #define WF_COMPROOT 0x0800	/* already compounded word, COMPOUNDROOT */
353 #define WF_NOCOMPBEF 0x1000	/* no compounding before this word */
354 #define WF_NOCOMPAFT 0x2000	/* no compounding after this word */
355 
356 /* only used for su_badflags */
357 #define WF_MIXCAP   0x20	/* mix of upper and lower case: macaRONI */
358 
359 #define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP)
360 
361 /* flags for <pflags> */
362 #define WFP_RARE	    0x01	/* rare prefix */
363 #define WFP_NC		    0x02	/* prefix is not combining */
364 #define WFP_UP		    0x04	/* to-upper prefix */
365 #define WFP_COMPPERMIT	    0x08	/* prefix with COMPOUNDPERMITFLAG */
366 #define WFP_COMPFORBID	    0x10	/* prefix with COMPOUNDFORBIDFLAG */
367 
368 /* Flags for postponed prefixes in "sl_pidxs".  Must be above affixID (one
369  * byte) and prefcondnr (two bytes). */
370 #define WF_RAREPFX  (WFP_RARE << 24)	/* rare postponed prefix */
371 #define WF_PFX_NC   (WFP_NC << 24)	/* non-combining postponed prefix */
372 #define WF_PFX_UP   (WFP_UP << 24)	/* to-upper postponed prefix */
373 #define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) /* postponed prefix with
374 						  * COMPOUNDPERMITFLAG */
375 #define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) /* postponed prefix with
376 						  * COMPOUNDFORBIDFLAG */
377 
378 
379 /* flags for <compoptions> */
380 #define COMP_CHECKDUP		1	/* CHECKCOMPOUNDDUP */
381 #define COMP_CHECKREP		2	/* CHECKCOMPOUNDREP */
382 #define COMP_CHECKCASE		4	/* CHECKCOMPOUNDCASE */
383 #define COMP_CHECKTRIPLE	8	/* CHECKCOMPOUNDTRIPLE */
384 
385 /* Special byte values for <byte>.  Some are only used in the tree for
386  * postponed prefixes, some only in the other trees.  This is a bit messy... */
387 #define BY_NOFLAGS	0	/* end of word without flags or region; for
388 				 * postponed prefix: no <pflags> */
389 #define BY_INDEX	1	/* child is shared, index follows */
390 #define BY_FLAGS	2	/* end of word, <flags> byte follows; for
391 				 * postponed prefix: <pflags> follows */
392 #define BY_FLAGS2	3	/* end of word, <flags> and <flags2> bytes
393 				 * follow; never used in prefix tree */
394 #define BY_SPECIAL  BY_FLAGS2	/* highest special byte value */
395 
396 /* Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep,
397  * si_repsal, sl_rep, and si_sal.  Not for sl_sal!
398  * One replacement: from "ft_from" to "ft_to". */
399 typedef struct fromto_S
400 {
401     char_u	*ft_from;
402     char_u	*ft_to;
403 } fromto_T;
404 
405 /* Info from "SAL" entries in ".aff" file used in sl_sal.
406  * The info is split for quick processing by spell_soundfold().
407  * Note that "sm_oneof" and "sm_rules" point into sm_lead. */
408 typedef struct salitem_S
409 {
410     char_u	*sm_lead;	/* leading letters */
411     int		sm_leadlen;	/* length of "sm_lead" */
412     char_u	*sm_oneof;	/* letters from () or NULL */
413     char_u	*sm_rules;	/* rules like ^, $, priority */
414     char_u	*sm_to;		/* replacement. */
415 #ifdef FEAT_MBYTE
416     int		*sm_lead_w;	/* wide character copy of "sm_lead" */
417     int		*sm_oneof_w;	/* wide character copy of "sm_oneof" */
418     int		*sm_to_w;	/* wide character copy of "sm_to" */
419 #endif
420 } salitem_T;
421 
422 #ifdef FEAT_MBYTE
423 typedef int salfirst_T;
424 #else
425 typedef short salfirst_T;
426 #endif
427 
428 /* Values for SP_*ERROR are negative, positive values are used by
429  * read_cnt_string(). */
430 #define	SP_TRUNCERROR	-1	/* spell file truncated error */
431 #define	SP_FORMERROR	-2	/* format error in spell file */
432 #define SP_OTHERERROR	-3	/* other error while reading spell file */
433 
434 /*
435  * Structure used to store words and other info for one language, loaded from
436  * a .spl file.
437  * The main access is through the tree in "sl_fbyts/sl_fidxs", storing the
438  * case-folded words.  "sl_kbyts/sl_kidxs" is for keep-case words.
439  *
440  * The "byts" array stores the possible bytes in each tree node, preceded by
441  * the number of possible bytes, sorted on byte value:
442  *	<len> <byte1> <byte2> ...
443  * The "idxs" array stores the index of the child node corresponding to the
444  * byte in "byts".
445  * Exception: when the byte is zero, the word may end here and "idxs" holds
446  * the flags, region mask and affixID for the word.  There may be several
447  * zeros in sequence for alternative flag/region/affixID combinations.
448  */
449 typedef struct slang_S slang_T;
450 struct slang_S
451 {
452     slang_T	*sl_next;	/* next language */
453     char_u	*sl_name;	/* language name "en", "en.rare", "nl", etc. */
454     char_u	*sl_fname;	/* name of .spl file */
455     int		sl_add;		/* TRUE if it's a .add file. */
456 
457     char_u	*sl_fbyts;	/* case-folded word bytes */
458     idx_T	*sl_fidxs;	/* case-folded word indexes */
459     char_u	*sl_kbyts;	/* keep-case word bytes */
460     idx_T	*sl_kidxs;	/* keep-case word indexes */
461     char_u	*sl_pbyts;	/* prefix tree word bytes */
462     idx_T	*sl_pidxs;	/* prefix tree word indexes */
463 
464     char_u	*sl_info;	/* infotext string or NULL */
465 
466     char_u	sl_regions[17];	/* table with up to 8 region names plus NUL */
467 
468     char_u	*sl_midword;	/* MIDWORD string or NULL */
469 
470     hashtab_T	sl_wordcount;	/* hashtable with word count, wordcount_T */
471 
472     int		sl_compmax;	/* COMPOUNDWORDMAX (default: MAXWLEN) */
473     int		sl_compminlen;	/* COMPOUNDMIN (default: 0) */
474     int		sl_compsylmax;	/* COMPOUNDSYLMAX (default: MAXWLEN) */
475     int		sl_compoptions;	/* COMP_* flags */
476     garray_T	sl_comppat;	/* CHECKCOMPOUNDPATTERN items */
477     regprog_T	*sl_compprog;	/* COMPOUNDRULE turned into a regexp progrm
478 				 * (NULL when no compounding) */
479     char_u	*sl_comprules;	/* all COMPOUNDRULE concatenated (or NULL) */
480     char_u	*sl_compstartflags; /* flags for first compound word */
481     char_u	*sl_compallflags; /* all flags for compound words */
482     char_u	sl_nobreak;	/* When TRUE: no spaces between words */
483     char_u	*sl_syllable;	/* SYLLABLE repeatable chars or NULL */
484     garray_T	sl_syl_items;	/* syllable items */
485 
486     int		sl_prefixcnt;	/* number of items in "sl_prefprog" */
487     regprog_T	**sl_prefprog;	/* table with regprogs for prefixes */
488 
489     garray_T	sl_rep;		/* list of fromto_T entries from REP lines */
490     short	sl_rep_first[256];  /* indexes where byte first appears, -1 if
491 				       there is none */
492     garray_T	sl_sal;		/* list of salitem_T entries from SAL lines */
493     salfirst_T	sl_sal_first[256];  /* indexes where byte first appears, -1 if
494 				       there is none */
495     int		sl_followup;	/* SAL followup */
496     int		sl_collapse;	/* SAL collapse_result */
497     int		sl_rem_accents;	/* SAL remove_accents */
498     int		sl_sofo;	/* SOFOFROM and SOFOTO instead of SAL items:
499 				 * "sl_sal_first" maps chars, when has_mbyte
500 				 * "sl_sal" is a list of wide char lists. */
501     garray_T	sl_repsal;	/* list of fromto_T entries from REPSAL lines */
502     short	sl_repsal_first[256];  /* sl_rep_first for REPSAL lines */
503     int		sl_nosplitsugs;	/* don't suggest splitting a word */
504 
505     /* Info from the .sug file.  Loaded on demand. */
506     time_t	sl_sugtime;	/* timestamp for .sug file */
507     char_u	*sl_sbyts;	/* soundfolded word bytes */
508     idx_T	*sl_sidxs;	/* soundfolded word indexes */
509     buf_T	*sl_sugbuf;	/* buffer with word number table */
510     int		sl_sugloaded;	/* TRUE when .sug file was loaded or failed to
511 				   load */
512 
513     int		sl_has_map;	/* TRUE if there is a MAP line */
514 #ifdef FEAT_MBYTE
515     hashtab_T	sl_map_hash;	/* MAP for multi-byte chars */
516     int		sl_map_array[256]; /* MAP for first 256 chars */
517 #else
518     char_u	sl_map_array[256]; /* MAP for first 256 chars */
519 #endif
520     hashtab_T	sl_sounddone;	/* table with soundfolded words that have
521 				   handled, see add_sound_suggest() */
522 };
523 
524 /* First language that is loaded, start of the linked list of loaded
525  * languages. */
526 static slang_T *first_lang = NULL;
527 
528 /* Flags used in .spl file for soundsalike flags. */
529 #define SAL_F0LLOWUP		1
530 #define SAL_COLLAPSE		2
531 #define SAL_REM_ACCENTS		4
532 
533 /*
534  * Structure used in "b_langp", filled from 'spelllang'.
535  */
536 typedef struct langp_S
537 {
538     slang_T	*lp_slang;	/* info for this language */
539     slang_T	*lp_sallang;	/* language used for sound folding or NULL */
540     slang_T	*lp_replang;	/* language used for REP items or NULL */
541     int		lp_region;	/* bitmask for region or REGION_ALL */
542 } langp_T;
543 
544 #define LANGP_ENTRY(ga, i)	(((langp_T *)(ga).ga_data) + (i))
545 
546 #define REGION_ALL 0xff		/* word valid in all regions */
547 
548 #define VIMSPELLMAGIC "VIMspell"  /* string at start of Vim spell file */
549 #define VIMSPELLMAGICL 8
550 #define VIMSPELLVERSION 50
551 
552 #define VIMSUGMAGIC "VIMsug"	/* string at start of Vim .sug file */
553 #define VIMSUGMAGICL 6
554 #define VIMSUGVERSION 1
555 
556 /* Section IDs.  Only renumber them when VIMSPELLVERSION changes! */
557 #define SN_REGION	0	/* <regionname> section */
558 #define SN_CHARFLAGS	1	/* charflags section */
559 #define SN_MIDWORD	2	/* <midword> section */
560 #define SN_PREFCOND	3	/* <prefcond> section */
561 #define SN_REP		4	/* REP items section */
562 #define SN_SAL		5	/* SAL items section */
563 #define SN_SOFO		6	/* soundfolding section */
564 #define SN_MAP		7	/* MAP items section */
565 #define SN_COMPOUND	8	/* compound words section */
566 #define SN_SYLLABLE	9	/* syllable section */
567 #define SN_NOBREAK	10	/* NOBREAK section */
568 #define SN_SUGFILE	11	/* timestamp for .sug file */
569 #define SN_REPSAL	12	/* REPSAL items section */
570 #define SN_WORDS	13	/* common words */
571 #define SN_NOSPLITSUGS	14	/* don't split word for suggestions */
572 #define SN_INFO		15	/* info section */
573 #define SN_END		255	/* end of sections */
574 
575 #define SNF_REQUIRED	1	/* <sectionflags>: required section */
576 
577 /* Result values.  Lower number is accepted over higher one. */
578 #define SP_BANNED	-1
579 #define SP_OK		0
580 #define SP_RARE		1
581 #define SP_LOCAL	2
582 #define SP_BAD		3
583 
584 /* file used for "zG" and "zW" */
585 static char_u	*int_wordlist = NULL;
586 
587 typedef struct wordcount_S
588 {
589     short_u	wc_count;	    /* nr of times word was seen */
590     char_u	wc_word[1];	    /* word, actually longer */
591 } wordcount_T;
592 
593 static wordcount_T dumwc;
594 #define WC_KEY_OFF  (unsigned)(dumwc.wc_word - (char_u *)&dumwc)
595 #define HI2WC(hi)     ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF))
596 #define MAXWORDCOUNT 0xffff
597 
598 /*
599  * Information used when looking for suggestions.
600  */
601 typedef struct suginfo_S
602 {
603     garray_T	su_ga;		    /* suggestions, contains "suggest_T" */
604     int		su_maxcount;	    /* max. number of suggestions displayed */
605     int		su_maxscore;	    /* maximum score for adding to su_ga */
606     int		su_sfmaxscore;	    /* idem, for when doing soundfold words */
607     garray_T	su_sga;		    /* like su_ga, sound-folded scoring */
608     char_u	*su_badptr;	    /* start of bad word in line */
609     int		su_badlen;	    /* length of detected bad word in line */
610     int		su_badflags;	    /* caps flags for bad word */
611     char_u	su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
612     char_u	su_fbadword[MAXWLEN]; /* su_badword case-folded */
613     char_u	su_sal_badword[MAXWLEN]; /* su_badword soundfolded */
614     hashtab_T	su_banned;	    /* table with banned words */
615     slang_T	*su_sallang;	    /* default language for sound folding */
616 } suginfo_T;
617 
618 /* One word suggestion.  Used in "si_ga". */
619 typedef struct suggest_S
620 {
621     char_u	*st_word;	/* suggested word, allocated string */
622     int		st_wordlen;	/* STRLEN(st_word) */
623     int		st_orglen;	/* length of replaced text */
624     int		st_score;	/* lower is better */
625     int		st_altscore;	/* used when st_score compares equal */
626     int		st_salscore;	/* st_score is for soundalike */
627     int		st_had_bonus;	/* bonus already included in score */
628     slang_T	*st_slang;	/* language used for sound folding */
629 } suggest_T;
630 
631 #define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i])
632 
633 /* TRUE if a word appears in the list of banned words.  */
634 #define WAS_BANNED(su, word) (!HASHITEM_EMPTY(hash_find(&su->su_banned, word)))
635 
636 /* Number of suggestions kept when cleaning up.  We need to keep more than
637  * what is displayed, because when rescore_suggestions() is called the score
638  * may change and wrong suggestions may be removed later. */
639 #define SUG_CLEAN_COUNT(su)    ((su)->su_maxcount < 130 ? 150 : (su)->su_maxcount + 20)
640 
641 /* Threshold for sorting and cleaning up suggestions.  Don't want to keep lots
642  * of suggestions that are not going to be displayed. */
643 #define SUG_MAX_COUNT(su)	(SUG_CLEAN_COUNT(su) + 50)
644 
645 /* score for various changes */
646 #define SCORE_SPLIT	149	/* split bad word */
647 #define SCORE_SPLIT_NO	249	/* split bad word with NOSPLITSUGS */
648 #define SCORE_ICASE	52	/* slightly different case */
649 #define SCORE_REGION	200	/* word is for different region */
650 #define SCORE_RARE	180	/* rare word */
651 #define SCORE_SWAP	75	/* swap two characters */
652 #define SCORE_SWAP3	110	/* swap two characters in three */
653 #define SCORE_REP	65	/* REP replacement */
654 #define SCORE_SUBST	93	/* substitute a character */
655 #define SCORE_SIMILAR	33	/* substitute a similar character */
656 #define SCORE_SUBCOMP	33	/* substitute a composing character */
657 #define SCORE_DEL	94	/* delete a character */
658 #define SCORE_DELDUP	66	/* delete a duplicated character */
659 #define SCORE_DELCOMP	28	/* delete a composing character */
660 #define SCORE_INS	96	/* insert a character */
661 #define SCORE_INSDUP	67	/* insert a duplicate character */
662 #define SCORE_INSCOMP	30	/* insert a composing character */
663 #define SCORE_NONWORD	103	/* change non-word to word char */
664 
665 #define SCORE_FILE	30	/* suggestion from a file */
666 #define SCORE_MAXINIT	350	/* Initial maximum score: higher == slower.
667 				 * 350 allows for about three changes. */
668 
669 #define SCORE_COMMON1	30	/* subtracted for words seen before */
670 #define SCORE_COMMON2	40	/* subtracted for words often seen */
671 #define SCORE_COMMON3	50	/* subtracted for words very often seen */
672 #define SCORE_THRES2	10	/* word count threshold for COMMON2 */
673 #define SCORE_THRES3	100	/* word count threshold for COMMON3 */
674 
675 /* When trying changed soundfold words it becomes slow when trying more than
676  * two changes.  With less then two changes it's slightly faster but we miss a
677  * few good suggestions.  In rare cases we need to try three of four changes.
678  */
679 #define SCORE_SFMAX1	200	/* maximum score for first try */
680 #define SCORE_SFMAX2	300	/* maximum score for second try */
681 #define SCORE_SFMAX3	400	/* maximum score for third try */
682 
683 #define SCORE_BIG	SCORE_INS * 3	/* big difference */
684 #define SCORE_MAXMAX	999999		/* accept any score */
685 #define SCORE_LIMITMAX	350		/* for spell_edit_score_limit() */
686 
687 /* for spell_edit_score_limit() we need to know the minimum value of
688  * SCORE_ICASE, SCORE_SWAP, SCORE_DEL, SCORE_SIMILAR and SCORE_INS */
689 #define SCORE_EDIT_MIN	SCORE_SIMILAR
690 
691 /*
692  * Structure to store info for word matching.
693  */
694 typedef struct matchinf_S
695 {
696     langp_T	*mi_lp;			/* info for language and region */
697 
698     /* pointers to original text to be checked */
699     char_u	*mi_word;		/* start of word being checked */
700     char_u	*mi_end;		/* end of matching word so far */
701     char_u	*mi_fend;		/* next char to be added to mi_fword */
702     char_u	*mi_cend;		/* char after what was used for
703 					   mi_capflags */
704 
705     /* case-folded text */
706     char_u	mi_fword[MAXWLEN + 1];	/* mi_word case-folded */
707     int		mi_fwordlen;		/* nr of valid bytes in mi_fword */
708 
709     /* for when checking word after a prefix */
710     int		mi_prefarridx;		/* index in sl_pidxs with list of
711 					   affixID/condition */
712     int		mi_prefcnt;		/* number of entries at mi_prefarridx */
713     int		mi_prefixlen;		/* byte length of prefix */
714 #ifdef FEAT_MBYTE
715     int		mi_cprefixlen;		/* byte length of prefix in original
716 					   case */
717 #else
718 # define mi_cprefixlen mi_prefixlen	/* it's the same value */
719 #endif
720 
721     /* for when checking a compound word */
722     int		mi_compoff;		/* start of following word offset */
723     char_u	mi_compflags[MAXWLEN];	/* flags for compound words used */
724     int		mi_complen;		/* nr of compound words used */
725     int		mi_compextra;		/* nr of COMPOUNDROOT words */
726 
727     /* others */
728     int		mi_result;		/* result so far: SP_BAD, SP_OK, etc. */
729     int		mi_capflags;		/* WF_ONECAP WF_ALLCAP WF_KEEPCAP */
730     win_T	*mi_win;		/* buffer being checked */
731 
732     /* for NOBREAK */
733     int		mi_result2;		/* "mi_resul" without following word */
734     char_u	*mi_end2;		/* "mi_end" without following word */
735 } matchinf_T;
736 
737 /*
738  * The tables used for recognizing word characters according to spelling.
739  * These are only used for the first 256 characters of 'encoding'.
740  */
741 typedef struct spelltab_S
742 {
743     char_u  st_isw[256];	/* flags: is word char */
744     char_u  st_isu[256];	/* flags: is uppercase char */
745     char_u  st_fold[256];	/* chars: folded case */
746     char_u  st_upper[256];	/* chars: upper case */
747 } spelltab_T;
748 
749 static spelltab_T   spelltab;
750 static int	    did_set_spelltab;
751 
752 #define CF_WORD		0x01
753 #define CF_UPPER	0x02
754 
755 static void clear_spell_chartab __ARGS((spelltab_T *sp));
756 static int set_spell_finish __ARGS((spelltab_T	*new_st));
757 static int spell_iswordp __ARGS((char_u *p, win_T *wp));
758 static int spell_iswordp_nmw __ARGS((char_u *p, win_T *wp));
759 #ifdef FEAT_MBYTE
760 static int spell_mb_isword_class __ARGS((int cl, win_T *wp));
761 static int spell_iswordp_w __ARGS((int *p, win_T *wp));
762 #endif
763 static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap));
764 
765 /*
766  * For finding suggestions: At each node in the tree these states are tried:
767  */
768 typedef enum
769 {
770     STATE_START = 0,	/* At start of node check for NUL bytes (goodword
771 			 * ends); if badword ends there is a match, otherwise
772 			 * try splitting word. */
773     STATE_NOPREFIX,	/* try without prefix */
774     STATE_SPLITUNDO,	/* Undo splitting. */
775     STATE_ENDNUL,	/* Past NUL bytes at start of the node. */
776     STATE_PLAIN,	/* Use each byte of the node. */
777     STATE_DEL,		/* Delete a byte from the bad word. */
778     STATE_INS_PREP,	/* Prepare for inserting bytes. */
779     STATE_INS,		/* Insert a byte in the bad word. */
780     STATE_SWAP,		/* Swap two bytes. */
781     STATE_UNSWAP,	/* Undo swap two characters. */
782     STATE_SWAP3,	/* Swap two characters over three. */
783     STATE_UNSWAP3,	/* Undo Swap two characters over three. */
784     STATE_UNROT3L,	/* Undo rotate three characters left */
785     STATE_UNROT3R,	/* Undo rotate three characters right */
786     STATE_REP_INI,	/* Prepare for using REP items. */
787     STATE_REP,		/* Use matching REP items from the .aff file. */
788     STATE_REP_UNDO,	/* Undo a REP item replacement. */
789     STATE_FINAL		/* End of this node. */
790 } state_T;
791 
792 /*
793  * Struct to keep the state at each level in suggest_try_change().
794  */
795 typedef struct trystate_S
796 {
797     state_T	ts_state;	/* state at this level, STATE_ */
798     int		ts_score;	/* score */
799     idx_T	ts_arridx;	/* index in tree array, start of node */
800     short	ts_curi;	/* index in list of child nodes */
801     char_u	ts_fidx;	/* index in fword[], case-folded bad word */
802     char_u	ts_fidxtry;	/* ts_fidx at which bytes may be changed */
803     char_u	ts_twordlen;	/* valid length of tword[] */
804     char_u	ts_prefixdepth;	/* stack depth for end of prefix or
805 				 * PFD_PREFIXTREE or PFD_NOPREFIX */
806     char_u	ts_flags;	/* TSF_ flags */
807 #ifdef FEAT_MBYTE
808     char_u	ts_tcharlen;	/* number of bytes in tword character */
809     char_u	ts_tcharidx;	/* current byte index in tword character */
810     char_u	ts_isdiff;	/* DIFF_ values */
811     char_u	ts_fcharstart;	/* index in fword where badword char started */
812 #endif
813     char_u	ts_prewordlen;	/* length of word in "preword[]" */
814     char_u	ts_splitoff;	/* index in "tword" after last split */
815     char_u	ts_splitfidx;	/* "ts_fidx" at word split */
816     char_u	ts_complen;	/* nr of compound words used */
817     char_u	ts_compsplit;	/* index for "compflags" where word was spit */
818     char_u	ts_save_badflags;   /* su_badflags saved here */
819     char_u	ts_delidx;	/* index in fword for char that was deleted,
820 				   valid when "ts_flags" has TSF_DIDDEL */
821 } trystate_T;
822 
823 /* values for ts_isdiff */
824 #define DIFF_NONE	0	/* no different byte (yet) */
825 #define DIFF_YES	1	/* different byte found */
826 #define DIFF_INSERT	2	/* inserting character */
827 
828 /* values for ts_flags */
829 #define TSF_PREFIXOK	1	/* already checked that prefix is OK */
830 #define TSF_DIDSPLIT	2	/* tried split at this point */
831 #define TSF_DIDDEL	4	/* did a delete, "ts_delidx" has index */
832 
833 /* special values ts_prefixdepth */
834 #define PFD_NOPREFIX	0xff	/* not using prefixes */
835 #define PFD_PREFIXTREE	0xfe	/* walking through the prefix tree */
836 #define PFD_NOTSPECIAL	0xfd	/* highest value that's not special */
837 
838 /* mode values for find_word */
839 #define FIND_FOLDWORD	    0	/* find word case-folded */
840 #define FIND_KEEPWORD	    1	/* find keep-case word */
841 #define FIND_PREFIX	    2	/* find word after prefix */
842 #define FIND_COMPOUND	    3	/* find case-folded compound word */
843 #define FIND_KEEPCOMPOUND   4	/* find keep-case compound word */
844 
845 static slang_T *slang_alloc __ARGS((char_u *lang));
846 static void slang_free __ARGS((slang_T *lp));
847 static void slang_clear __ARGS((slang_T *lp));
848 static void slang_clear_sug __ARGS((slang_T *lp));
849 static void find_word __ARGS((matchinf_T *mip, int mode));
850 static int match_checkcompoundpattern __ARGS((char_u *ptr, int wlen, garray_T *gap));
851 static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags));
852 static int can_be_compound __ARGS((trystate_T *sp, slang_T *slang, char_u *compflags, int flag));
853 static int match_compoundrule __ARGS((slang_T *slang, char_u *compflags));
854 static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req));
855 static void find_prefix __ARGS((matchinf_T *mip, int mode));
856 static int fold_more __ARGS((matchinf_T *mip));
857 static int spell_valid_case __ARGS((int wordflags, int treeflags));
858 static int no_spell_checking __ARGS((win_T *wp));
859 static void spell_load_lang __ARGS((char_u *lang));
860 static char_u *spell_enc __ARGS((void));
861 static void int_wordlist_spl __ARGS((char_u *fname));
862 static void spell_load_cb __ARGS((char_u *fname, void *cookie));
863 static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent));
864 static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *lenp));
865 static int read_region_section __ARGS((FILE *fd, slang_T *slang, int len));
866 static int read_charflags_section __ARGS((FILE *fd));
867 static int read_prefcond_section __ARGS((FILE *fd, slang_T *lp));
868 static int read_rep_section __ARGS((FILE *fd, garray_T *gap, short *first));
869 static int read_sal_section __ARGS((FILE *fd, slang_T *slang));
870 static int read_words_section __ARGS((FILE *fd, slang_T *lp, int len));
871 static void count_common_word __ARGS((slang_T *lp, char_u *word, int len, int count));
872 static int score_wordcount_adj __ARGS((slang_T *slang, int score, char_u *word, int split));
873 static int read_sofo_section __ARGS((FILE *fd, slang_T *slang));
874 static int read_compound __ARGS((FILE *fd, slang_T *slang, int len));
875 static int byte_in_str __ARGS((char_u *str, int byte));
876 static int init_syl_tab __ARGS((slang_T *slang));
877 static int count_syllables __ARGS((slang_T *slang, char_u *word));
878 static int set_sofo __ARGS((slang_T *lp, char_u *from, char_u *to));
879 static void set_sal_first __ARGS((slang_T *lp));
880 #ifdef FEAT_MBYTE
881 static int *mb_str2wide __ARGS((char_u *s));
882 #endif
883 static int spell_read_tree __ARGS((FILE *fd, char_u **bytsp, idx_T **idxsp, int prefixtree, int prefixcnt));
884 static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx_T startidx, int prefixtree, int maxprefcondnr));
885 static void clear_midword __ARGS((win_T *buf));
886 static void use_midword __ARGS((slang_T *lp, win_T *buf));
887 static int find_region __ARGS((char_u *rp, char_u *region));
888 static int captype __ARGS((char_u *word, char_u *end));
889 static int badword_captype __ARGS((char_u *word, char_u *end));
890 static void spell_reload_one __ARGS((char_u *fname, int added_word));
891 static void set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp));
892 static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp));
893 static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen));
894 static int check_need_cap __ARGS((linenr_T lnum, colnr_T col));
895 static void spell_find_suggest __ARGS((char_u *badptr, int badlen, suginfo_T *su, int maxcount, int banbadword, int need_cap, int interactive));
896 #ifdef FEAT_EVAL
897 static void spell_suggest_expr __ARGS((suginfo_T *su, char_u *expr));
898 #endif
899 static void spell_suggest_file __ARGS((suginfo_T *su, char_u *fname));
900 static void spell_suggest_intern __ARGS((suginfo_T *su, int interactive));
901 static void suggest_load_files __ARGS((void));
902 static void tree_count_words __ARGS((char_u *byts, idx_T *idxs));
903 static void spell_find_cleanup __ARGS((suginfo_T *su));
904 static void onecap_copy __ARGS((char_u *word, char_u *wcopy, int upper));
905 static void allcap_copy __ARGS((char_u *word, char_u *wcopy));
906 static void suggest_try_special __ARGS((suginfo_T *su));
907 static void suggest_try_change __ARGS((suginfo_T *su));
908 static void suggest_trie_walk __ARGS((suginfo_T *su, langp_T *lp, char_u *fword, int soundfold));
909 static void go_deeper __ARGS((trystate_T *stack, int depth, int score_add));
910 #ifdef FEAT_MBYTE
911 static int nofold_len __ARGS((char_u *fword, int flen, char_u *word));
912 #endif
913 static void find_keepcap_word __ARGS((slang_T *slang, char_u *fword, char_u *kword));
914 static void score_comp_sal __ARGS((suginfo_T *su));
915 static void score_combine __ARGS((suginfo_T *su));
916 static int stp_sal_score __ARGS((suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *badsound));
917 static void suggest_try_soundalike_prep __ARGS((void));
918 static void suggest_try_soundalike __ARGS((suginfo_T *su));
919 static void suggest_try_soundalike_finish __ARGS((void));
920 static void add_sound_suggest __ARGS((suginfo_T *su, char_u *goodword, int score, langp_T *lp));
921 static int soundfold_find __ARGS((slang_T *slang, char_u *word));
922 static void make_case_word __ARGS((char_u *fword, char_u *cword, int flags));
923 static void set_map_str __ARGS((slang_T *lp, char_u *map));
924 static int similar_chars __ARGS((slang_T *slang, int c1, int c2));
925 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));
926 static void check_suggestions __ARGS((suginfo_T *su, garray_T *gap));
927 static void add_banned __ARGS((suginfo_T *su, char_u *word));
928 static void rescore_suggestions __ARGS((suginfo_T *su));
929 static void rescore_one __ARGS((suginfo_T *su, suggest_T *stp));
930 static int cleanup_suggestions __ARGS((garray_T *gap, int maxscore, int keep));
931 static void spell_soundfold __ARGS((slang_T *slang, char_u *inword, int folded, char_u *res));
932 static void spell_soundfold_sofo __ARGS((slang_T *slang, char_u *inword, char_u *res));
933 static void spell_soundfold_sal __ARGS((slang_T *slang, char_u *inword, char_u *res));
934 #ifdef FEAT_MBYTE
935 static void spell_soundfold_wsal __ARGS((slang_T *slang, char_u *inword, char_u *res));
936 #endif
937 static int soundalike_score __ARGS((char_u *goodsound, char_u *badsound));
938 static int spell_edit_score __ARGS((slang_T *slang, char_u *badword, char_u *goodword));
939 static int spell_edit_score_limit __ARGS((slang_T *slang, char_u *badword, char_u *goodword, int limit));
940 #ifdef FEAT_MBYTE
941 static int spell_edit_score_limit_w __ARGS((slang_T *slang, char_u *badword, char_u *goodword, int limit));
942 #endif
943 static void dump_word __ARGS((slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T lnum));
944 static linenr_T dump_prefixes __ARGS((slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T startlnum));
945 static buf_T *open_spellbuf __ARGS((void));
946 static void close_spellbuf __ARGS((buf_T *buf));
947 
948 /*
949  * Use our own character-case definitions, because the current locale may
950  * differ from what the .spl file uses.
951  * These must not be called with negative number!
952  */
953 #ifndef FEAT_MBYTE
954 /* Non-multi-byte implementation. */
955 # define SPELL_TOFOLD(c) ((c) < 256 ? (int)spelltab.st_fold[c] : (c))
956 # define SPELL_TOUPPER(c) ((c) < 256 ? (int)spelltab.st_upper[c] : (c))
957 # define SPELL_ISUPPER(c) ((c) < 256 ? spelltab.st_isu[c] : FALSE)
958 #else
959 # if defined(HAVE_WCHAR_H)
960 #  include <wchar.h>	    /* for towupper() and towlower() */
961 # endif
962 /* Multi-byte implementation.  For Unicode we can call utf_*(), but don't do
963  * that for ASCII, because we don't want to use 'casemap' here.  Otherwise use
964  * the "w" library function for characters above 255 if available. */
965 # ifdef HAVE_TOWLOWER
966 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
967 	    : (c) < 256 ? (int)spelltab.st_fold[c] : (int)towlower(c))
968 # else
969 #  define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \
970 	    : (c) < 256 ? (int)spelltab.st_fold[c] : (c))
971 # endif
972 
973 # ifdef HAVE_TOWUPPER
974 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
975 	    : (c) < 256 ? (int)spelltab.st_upper[c] : (int)towupper(c))
976 # else
977 #  define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \
978 	    : (c) < 256 ? (int)spelltab.st_upper[c] : (c))
979 # endif
980 
981 # ifdef HAVE_ISWUPPER
982 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
983 	    : (c) < 256 ? spelltab.st_isu[c] : iswupper(c))
984 # else
985 #  define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \
986 	    : (c) < 256 ? spelltab.st_isu[c] : (FALSE))
987 # endif
988 #endif
989 
990 
991 static char *e_format = N_("E759: Format error in spell file");
992 static char *e_spell_trunc = N_("E758: Truncated spell file");
993 static char *e_afftrailing = N_("Trailing text in %s line %d: %s");
994 static char *e_affname = N_("Affix name too long in %s line %d: %s");
995 static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP");
996 static char *e_affrange = N_("E762: Character in FOL, LOW or UPP is out of range");
997 static char *msg_compressing = N_("Compressing word tree...");
998 
999 /* Remember what "z?" replaced. */
1000 static char_u	*repl_from = NULL;
1001 static char_u	*repl_to = NULL;
1002 
1003 /*
1004  * Main spell-checking function.
1005  * "ptr" points to a character that could be the start of a word.
1006  * "*attrp" is set to the highlight index for a badly spelled word.  For a
1007  * non-word or when it's OK it remains unchanged.
1008  * This must only be called when 'spelllang' is not empty.
1009  *
1010  * "capcol" is used to check for a Capitalised word after the end of a
1011  * sentence.  If it's zero then perform the check.  Return the column where to
1012  * check next, or -1 when no sentence end was found.  If it's NULL then don't
1013  * worry.
1014  *
1015  * Returns the length of the word in bytes, also when it's OK, so that the
1016  * caller can skip over the word.
1017  */
1018     int
1019 spell_check(wp, ptr, attrp, capcol, docount)
1020     win_T	*wp;		/* current window */
1021     char_u	*ptr;
1022     hlf_T	*attrp;
1023     int		*capcol;	/* column to check for Capital */
1024     int		docount;	/* count good words */
1025 {
1026     matchinf_T	mi;		/* Most things are put in "mi" so that it can
1027 				   be passed to functions quickly. */
1028     int		nrlen = 0;	/* found a number first */
1029     int		c;
1030     int		wrongcaplen = 0;
1031     int		lpi;
1032     int		count_word = docount;
1033 
1034     /* A word never starts at a space or a control character.  Return quickly
1035      * then, skipping over the character. */
1036     if (*ptr <= ' ')
1037 	return 1;
1038 
1039     /* Return here when loading language files failed. */
1040     if (wp->w_s->b_langp.ga_len == 0)
1041 	return 1;
1042 
1043     vim_memset(&mi, 0, sizeof(matchinf_T));
1044 
1045     /* A number is always OK.  Also skip hexadecimal numbers 0xFF99 and
1046      * 0X99FF.  But always do check spelling to find "3GPP" and "11
1047      * julifeest". */
1048     if (*ptr >= '0' && *ptr <= '9')
1049     {
1050 	if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
1051 	    mi.mi_end = skiphex(ptr + 2);
1052 	else
1053 	    mi.mi_end = skipdigits(ptr);
1054 	nrlen = (int)(mi.mi_end - ptr);
1055     }
1056 
1057     /* Find the normal end of the word (until the next non-word character). */
1058     mi.mi_word = ptr;
1059     mi.mi_fend = ptr;
1060     if (spell_iswordp(mi.mi_fend, wp))
1061     {
1062 	do
1063 	{
1064 	    mb_ptr_adv(mi.mi_fend);
1065 	} while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp));
1066 
1067 	if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL)
1068 	{
1069 	    /* Check word starting with capital letter. */
1070 	    c = PTR2CHAR(ptr);
1071 	    if (!SPELL_ISUPPER(c))
1072 		wrongcaplen = (int)(mi.mi_fend - ptr);
1073 	}
1074     }
1075     if (capcol != NULL)
1076 	*capcol = -1;
1077 
1078     /* We always use the characters up to the next non-word character,
1079      * also for bad words. */
1080     mi.mi_end = mi.mi_fend;
1081 
1082     /* Check caps type later. */
1083     mi.mi_capflags = 0;
1084     mi.mi_cend = NULL;
1085     mi.mi_win = wp;
1086 
1087     /* case-fold the word with one non-word character, so that we can check
1088      * for the word end. */
1089     if (*mi.mi_fend != NUL)
1090 	mb_ptr_adv(mi.mi_fend);
1091 
1092     (void)spell_casefold(ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
1093 							     MAXWLEN + 1);
1094     mi.mi_fwordlen = (int)STRLEN(mi.mi_fword);
1095 
1096     /* The word is bad unless we recognize it. */
1097     mi.mi_result = SP_BAD;
1098     mi.mi_result2 = SP_BAD;
1099 
1100     /*
1101      * Loop over the languages specified in 'spelllang'.
1102      * We check them all, because a word may be matched longer in another
1103      * language.
1104      */
1105     for (lpi = 0; lpi < wp->w_s->b_langp.ga_len; ++lpi)
1106     {
1107 	mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, lpi);
1108 
1109 	/* If reloading fails the language is still in the list but everything
1110 	 * has been cleared. */
1111 	if (mi.mi_lp->lp_slang->sl_fidxs == NULL)
1112 	    continue;
1113 
1114 	/* Check for a matching word in case-folded words. */
1115 	find_word(&mi, FIND_FOLDWORD);
1116 
1117 	/* Check for a matching word in keep-case words. */
1118 	find_word(&mi, FIND_KEEPWORD);
1119 
1120 	/* Check for matching prefixes. */
1121 	find_prefix(&mi, FIND_FOLDWORD);
1122 
1123 	/* For a NOBREAK language, may want to use a word without a following
1124 	 * word as a backup. */
1125 	if (mi.mi_lp->lp_slang->sl_nobreak && mi.mi_result == SP_BAD
1126 						   && mi.mi_result2 != SP_BAD)
1127 	{
1128 	    mi.mi_result = mi.mi_result2;
1129 	    mi.mi_end = mi.mi_end2;
1130 	}
1131 
1132 	/* Count the word in the first language where it's found to be OK. */
1133 	if (count_word && mi.mi_result == SP_OK)
1134 	{
1135 	    count_common_word(mi.mi_lp->lp_slang, ptr,
1136 						   (int)(mi.mi_end - ptr), 1);
1137 	    count_word = FALSE;
1138 	}
1139     }
1140 
1141     if (mi.mi_result != SP_OK)
1142     {
1143 	/* If we found a number skip over it.  Allows for "42nd".  Do flag
1144 	 * rare and local words, e.g., "3GPP". */
1145 	if (nrlen > 0)
1146 	{
1147 	    if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
1148 		return nrlen;
1149 	}
1150 
1151 	/* When we are at a non-word character there is no error, just
1152 	 * skip over the character (try looking for a word after it). */
1153 	else if (!spell_iswordp_nmw(ptr, wp))
1154 	{
1155 	    if (capcol != NULL && wp->w_s->b_cap_prog != NULL)
1156 	    {
1157 		regmatch_T	regmatch;
1158 		int		r;
1159 
1160 		/* Check for end of sentence. */
1161 		regmatch.regprog = wp->w_s->b_cap_prog;
1162 		regmatch.rm_ic = FALSE;
1163 		r = vim_regexec(&regmatch, ptr, 0);
1164 		wp->w_s->b_cap_prog = regmatch.regprog;
1165 		if (r)
1166 		    *capcol = (int)(regmatch.endp[0] - ptr);
1167 	    }
1168 
1169 #ifdef FEAT_MBYTE
1170 	    if (has_mbyte)
1171 		return (*mb_ptr2len)(ptr);
1172 #endif
1173 	    return 1;
1174 	}
1175 	else if (mi.mi_end == ptr)
1176 	    /* Always include at least one character.  Required for when there
1177 	     * is a mixup in "midword". */
1178 	    mb_ptr_adv(mi.mi_end);
1179 	else if (mi.mi_result == SP_BAD
1180 		&& LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak)
1181 	{
1182 	    char_u	*p, *fp;
1183 	    int		save_result = mi.mi_result;
1184 
1185 	    /* First language in 'spelllang' is NOBREAK.  Find first position
1186 	     * at which any word would be valid. */
1187 	    mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0);
1188 	    if (mi.mi_lp->lp_slang->sl_fidxs != NULL)
1189 	    {
1190 		p = mi.mi_word;
1191 		fp = mi.mi_fword;
1192 		for (;;)
1193 		{
1194 		    mb_ptr_adv(p);
1195 		    mb_ptr_adv(fp);
1196 		    if (p >= mi.mi_end)
1197 			break;
1198 		    mi.mi_compoff = (int)(fp - mi.mi_fword);
1199 		    find_word(&mi, FIND_COMPOUND);
1200 		    if (mi.mi_result != SP_BAD)
1201 		    {
1202 			mi.mi_end = p;
1203 			break;
1204 		    }
1205 		}
1206 		mi.mi_result = save_result;
1207 	    }
1208 	}
1209 
1210 	if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
1211 	    *attrp = HLF_SPB;
1212 	else if (mi.mi_result == SP_RARE)
1213 	    *attrp = HLF_SPR;
1214 	else
1215 	    *attrp = HLF_SPL;
1216     }
1217 
1218     if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE))
1219     {
1220 	/* Report SpellCap only when the word isn't badly spelled. */
1221 	*attrp = HLF_SPC;
1222 	return wrongcaplen;
1223     }
1224 
1225     return (int)(mi.mi_end - ptr);
1226 }
1227 
1228 /*
1229  * Check if the word at "mip->mi_word" is in the tree.
1230  * When "mode" is FIND_FOLDWORD check in fold-case word tree.
1231  * When "mode" is FIND_KEEPWORD check in keep-case word tree.
1232  * When "mode" is FIND_PREFIX check for word after prefix in fold-case word
1233  * tree.
1234  *
1235  * For a match mip->mi_result is updated.
1236  */
1237     static void
1238 find_word(mip, mode)
1239     matchinf_T	*mip;
1240     int		mode;
1241 {
1242     idx_T	arridx = 0;
1243     int		endlen[MAXWLEN];    /* length at possible word endings */
1244     idx_T	endidx[MAXWLEN];    /* possible word endings */
1245     int		endidxcnt = 0;
1246     int		len;
1247     int		wlen = 0;
1248     int		flen;
1249     int		c;
1250     char_u	*ptr;
1251     idx_T	lo, hi, m;
1252 #ifdef FEAT_MBYTE
1253     char_u	*s;
1254 #endif
1255     char_u	*p;
1256     int		res = SP_BAD;
1257     slang_T	*slang = mip->mi_lp->lp_slang;
1258     unsigned	flags;
1259     char_u	*byts;
1260     idx_T	*idxs;
1261     int		word_ends;
1262     int		prefix_found;
1263     int		nobreak_result;
1264 
1265     if (mode == FIND_KEEPWORD || mode == FIND_KEEPCOMPOUND)
1266     {
1267 	/* Check for word with matching case in keep-case tree. */
1268 	ptr = mip->mi_word;
1269 	flen = 9999;		    /* no case folding, always enough bytes */
1270 	byts = slang->sl_kbyts;
1271 	idxs = slang->sl_kidxs;
1272 
1273 	if (mode == FIND_KEEPCOMPOUND)
1274 	    /* Skip over the previously found word(s). */
1275 	    wlen += mip->mi_compoff;
1276     }
1277     else
1278     {
1279 	/* Check for case-folded in case-folded tree. */
1280 	ptr = mip->mi_fword;
1281 	flen = mip->mi_fwordlen;    /* available case-folded bytes */
1282 	byts = slang->sl_fbyts;
1283 	idxs = slang->sl_fidxs;
1284 
1285 	if (mode == FIND_PREFIX)
1286 	{
1287 	    /* Skip over the prefix. */
1288 	    wlen = mip->mi_prefixlen;
1289 	    flen -= mip->mi_prefixlen;
1290 	}
1291 	else if (mode == FIND_COMPOUND)
1292 	{
1293 	    /* Skip over the previously found word(s). */
1294 	    wlen = mip->mi_compoff;
1295 	    flen -= mip->mi_compoff;
1296 	}
1297 
1298     }
1299 
1300     if (byts == NULL)
1301 	return;			/* array is empty */
1302 
1303     /*
1304      * Repeat advancing in the tree until:
1305      * - there is a byte that doesn't match,
1306      * - we reach the end of the tree,
1307      * - or we reach the end of the line.
1308      */
1309     for (;;)
1310     {
1311 	if (flen <= 0 && *mip->mi_fend != NUL)
1312 	    flen = fold_more(mip);
1313 
1314 	len = byts[arridx++];
1315 
1316 	/* If the first possible byte is a zero the word could end here.
1317 	 * Remember this index, we first check for the longest word. */
1318 	if (byts[arridx] == 0)
1319 	{
1320 	    if (endidxcnt == MAXWLEN)
1321 	    {
1322 		/* Must be a corrupted spell file. */
1323 		EMSG(_(e_format));
1324 		return;
1325 	    }
1326 	    endlen[endidxcnt] = wlen;
1327 	    endidx[endidxcnt++] = arridx++;
1328 	    --len;
1329 
1330 	    /* Skip over the zeros, there can be several flag/region
1331 	     * combinations. */
1332 	    while (len > 0 && byts[arridx] == 0)
1333 	    {
1334 		++arridx;
1335 		--len;
1336 	    }
1337 	    if (len == 0)
1338 		break;	    /* no children, word must end here */
1339 	}
1340 
1341 	/* Stop looking at end of the line. */
1342 	if (ptr[wlen] == NUL)
1343 	    break;
1344 
1345 	/* Perform a binary search in the list of accepted bytes. */
1346 	c = ptr[wlen];
1347 	if (c == TAB)	    /* <Tab> is handled like <Space> */
1348 	    c = ' ';
1349 	lo = arridx;
1350 	hi = arridx + len - 1;
1351 	while (lo < hi)
1352 	{
1353 	    m = (lo + hi) / 2;
1354 	    if (byts[m] > c)
1355 		hi = m - 1;
1356 	    else if (byts[m] < c)
1357 		lo = m + 1;
1358 	    else
1359 	    {
1360 		lo = hi = m;
1361 		break;
1362 	    }
1363 	}
1364 
1365 	/* Stop if there is no matching byte. */
1366 	if (hi < lo || byts[lo] != c)
1367 	    break;
1368 
1369 	/* Continue at the child (if there is one). */
1370 	arridx = idxs[lo];
1371 	++wlen;
1372 	--flen;
1373 
1374 	/* One space in the good word may stand for several spaces in the
1375 	 * checked word. */
1376 	if (c == ' ')
1377 	{
1378 	    for (;;)
1379 	    {
1380 		if (flen <= 0 && *mip->mi_fend != NUL)
1381 		    flen = fold_more(mip);
1382 		if (ptr[wlen] != ' ' && ptr[wlen] != TAB)
1383 		    break;
1384 		++wlen;
1385 		--flen;
1386 	    }
1387 	}
1388     }
1389 
1390     /*
1391      * Verify that one of the possible endings is valid.  Try the longest
1392      * first.
1393      */
1394     while (endidxcnt > 0)
1395     {
1396 	--endidxcnt;
1397 	arridx = endidx[endidxcnt];
1398 	wlen = endlen[endidxcnt];
1399 
1400 #ifdef FEAT_MBYTE
1401 	if ((*mb_head_off)(ptr, ptr + wlen) > 0)
1402 	    continue;	    /* not at first byte of character */
1403 #endif
1404 	if (spell_iswordp(ptr + wlen, mip->mi_win))
1405 	{
1406 	    if (slang->sl_compprog == NULL && !slang->sl_nobreak)
1407 		continue;	    /* next char is a word character */
1408 	    word_ends = FALSE;
1409 	}
1410 	else
1411 	    word_ends = TRUE;
1412 	/* The prefix flag is before compound flags.  Once a valid prefix flag
1413 	 * has been found we try compound flags. */
1414 	prefix_found = FALSE;
1415 
1416 #ifdef FEAT_MBYTE
1417 	if (mode != FIND_KEEPWORD && has_mbyte)
1418 	{
1419 	    /* Compute byte length in original word, length may change
1420 	     * when folding case.  This can be slow, take a shortcut when the
1421 	     * case-folded word is equal to the keep-case word. */
1422 	    p = mip->mi_word;
1423 	    if (STRNCMP(ptr, p, wlen) != 0)
1424 	    {
1425 		for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1426 		    mb_ptr_adv(p);
1427 		wlen = (int)(p - mip->mi_word);
1428 	    }
1429 	}
1430 #endif
1431 
1432 	/* Check flags and region.  For FIND_PREFIX check the condition and
1433 	 * prefix ID.
1434 	 * Repeat this if there are more flags/region alternatives until there
1435 	 * is a match. */
1436 	res = SP_BAD;
1437 	for (len = byts[arridx - 1]; len > 0 && byts[arridx] == 0;
1438 							      --len, ++arridx)
1439 	{
1440 	    flags = idxs[arridx];
1441 
1442 	    /* For the fold-case tree check that the case of the checked word
1443 	     * matches with what the word in the tree requires.
1444 	     * For keep-case tree the case is always right.  For prefixes we
1445 	     * don't bother to check. */
1446 	    if (mode == FIND_FOLDWORD)
1447 	    {
1448 		if (mip->mi_cend != mip->mi_word + wlen)
1449 		{
1450 		    /* mi_capflags was set for a different word length, need
1451 		     * to do it again. */
1452 		    mip->mi_cend = mip->mi_word + wlen;
1453 		    mip->mi_capflags = captype(mip->mi_word, mip->mi_cend);
1454 		}
1455 
1456 		if (mip->mi_capflags == WF_KEEPCAP
1457 				|| !spell_valid_case(mip->mi_capflags, flags))
1458 		    continue;
1459 	    }
1460 
1461 	    /* When mode is FIND_PREFIX the word must support the prefix:
1462 	     * check the prefix ID and the condition.  Do that for the list at
1463 	     * mip->mi_prefarridx that find_prefix() filled. */
1464 	    else if (mode == FIND_PREFIX && !prefix_found)
1465 	    {
1466 		c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
1467 				    flags,
1468 				    mip->mi_word + mip->mi_cprefixlen, slang,
1469 				    FALSE);
1470 		if (c == 0)
1471 		    continue;
1472 
1473 		/* Use the WF_RARE flag for a rare prefix. */
1474 		if (c & WF_RAREPFX)
1475 		    flags |= WF_RARE;
1476 		prefix_found = TRUE;
1477 	    }
1478 
1479 	    if (slang->sl_nobreak)
1480 	    {
1481 		if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND)
1482 			&& (flags & WF_BANNED) == 0)
1483 		{
1484 		    /* NOBREAK: found a valid following word.  That's all we
1485 		     * need to know, so return. */
1486 		    mip->mi_result = SP_OK;
1487 		    break;
1488 		}
1489 	    }
1490 
1491 	    else if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND
1492 								|| !word_ends))
1493 	    {
1494 		/* If there is no compound flag or the word is shorter than
1495 		 * COMPOUNDMIN reject it quickly.
1496 		 * Makes you wonder why someone puts a compound flag on a word
1497 		 * that's too short...  Myspell compatibility requires this
1498 		 * anyway. */
1499 		if (((unsigned)flags >> 24) == 0
1500 			     || wlen - mip->mi_compoff < slang->sl_compminlen)
1501 		    continue;
1502 #ifdef FEAT_MBYTE
1503 		/* For multi-byte chars check character length against
1504 		 * COMPOUNDMIN. */
1505 		if (has_mbyte
1506 			&& slang->sl_compminlen > 0
1507 			&& mb_charlen_len(mip->mi_word + mip->mi_compoff,
1508 				wlen - mip->mi_compoff) < slang->sl_compminlen)
1509 			continue;
1510 #endif
1511 
1512 		/* Limit the number of compound words to COMPOUNDWORDMAX if no
1513 		 * maximum for syllables is specified. */
1514 		if (!word_ends && mip->mi_complen + mip->mi_compextra + 2
1515 							   > slang->sl_compmax
1516 					   && slang->sl_compsylmax == MAXWLEN)
1517 		    continue;
1518 
1519 		/* Don't allow compounding on a side where an affix was added,
1520 		 * unless COMPOUNDPERMITFLAG was used. */
1521 		if (mip->mi_complen > 0 && (flags & WF_NOCOMPBEF))
1522 		    continue;
1523 		if (!word_ends && (flags & WF_NOCOMPAFT))
1524 		    continue;
1525 
1526 		/* Quickly check if compounding is possible with this flag. */
1527 		if (!byte_in_str(mip->mi_complen == 0
1528 					? slang->sl_compstartflags
1529 					: slang->sl_compallflags,
1530 					    ((unsigned)flags >> 24)))
1531 		    continue;
1532 
1533 		/* If there is a match with a CHECKCOMPOUNDPATTERN rule
1534 		 * discard the compound word. */
1535 		if (match_checkcompoundpattern(ptr, wlen, &slang->sl_comppat))
1536 		    continue;
1537 
1538 		if (mode == FIND_COMPOUND)
1539 		{
1540 		    int	    capflags;
1541 
1542 		    /* Need to check the caps type of the appended compound
1543 		     * word. */
1544 #ifdef FEAT_MBYTE
1545 		    if (has_mbyte && STRNCMP(ptr, mip->mi_word,
1546 							mip->mi_compoff) != 0)
1547 		    {
1548 			/* case folding may have changed the length */
1549 			p = mip->mi_word;
1550 			for (s = ptr; s < ptr + mip->mi_compoff; mb_ptr_adv(s))
1551 			    mb_ptr_adv(p);
1552 		    }
1553 		    else
1554 #endif
1555 			p = mip->mi_word + mip->mi_compoff;
1556 		    capflags = captype(p, mip->mi_word + wlen);
1557 		    if (capflags == WF_KEEPCAP || (capflags == WF_ALLCAP
1558 						 && (flags & WF_FIXCAP) != 0))
1559 			continue;
1560 
1561 		    if (capflags != WF_ALLCAP)
1562 		    {
1563 			/* When the character before the word is a word
1564 			 * character we do not accept a Onecap word.  We do
1565 			 * accept a no-caps word, even when the dictionary
1566 			 * word specifies ONECAP. */
1567 			mb_ptr_back(mip->mi_word, p);
1568 			if (spell_iswordp_nmw(p, mip->mi_win)
1569 				? capflags == WF_ONECAP
1570 				: (flags & WF_ONECAP) != 0
1571 						     && capflags != WF_ONECAP)
1572 			    continue;
1573 		    }
1574 		}
1575 
1576 		/* If the word ends the sequence of compound flags of the
1577 		 * words must match with one of the COMPOUNDRULE items and
1578 		 * the number of syllables must not be too large. */
1579 		mip->mi_compflags[mip->mi_complen] = ((unsigned)flags >> 24);
1580 		mip->mi_compflags[mip->mi_complen + 1] = NUL;
1581 		if (word_ends)
1582 		{
1583 		    char_u	fword[MAXWLEN];
1584 
1585 		    if (slang->sl_compsylmax < MAXWLEN)
1586 		    {
1587 			/* "fword" is only needed for checking syllables. */
1588 			if (ptr == mip->mi_word)
1589 			    (void)spell_casefold(ptr, wlen, fword, MAXWLEN);
1590 			else
1591 			    vim_strncpy(fword, ptr, endlen[endidxcnt]);
1592 		    }
1593 		    if (!can_compound(slang, fword, mip->mi_compflags))
1594 			continue;
1595 		}
1596 		else if (slang->sl_comprules != NULL
1597 			     && !match_compoundrule(slang, mip->mi_compflags))
1598 		    /* The compound flags collected so far do not match any
1599 		     * COMPOUNDRULE, discard the compounded word. */
1600 		    continue;
1601 	    }
1602 
1603 	    /* Check NEEDCOMPOUND: can't use word without compounding. */
1604 	    else if (flags & WF_NEEDCOMP)
1605 		continue;
1606 
1607 	    nobreak_result = SP_OK;
1608 
1609 	    if (!word_ends)
1610 	    {
1611 		int	save_result = mip->mi_result;
1612 		char_u	*save_end = mip->mi_end;
1613 		langp_T	*save_lp = mip->mi_lp;
1614 		int	lpi;
1615 
1616 		/* Check that a valid word follows.  If there is one and we
1617 		 * are compounding, it will set "mi_result", thus we are
1618 		 * always finished here.  For NOBREAK we only check that a
1619 		 * valid word follows.
1620 		 * Recursive! */
1621 		if (slang->sl_nobreak)
1622 		    mip->mi_result = SP_BAD;
1623 
1624 		/* Find following word in case-folded tree. */
1625 		mip->mi_compoff = endlen[endidxcnt];
1626 #ifdef FEAT_MBYTE
1627 		if (has_mbyte && mode == FIND_KEEPWORD)
1628 		{
1629 		    /* Compute byte length in case-folded word from "wlen":
1630 		     * byte length in keep-case word.  Length may change when
1631 		     * folding case.  This can be slow, take a shortcut when
1632 		     * the case-folded word is equal to the keep-case word. */
1633 		    p = mip->mi_fword;
1634 		    if (STRNCMP(ptr, p, wlen) != 0)
1635 		    {
1636 			for (s = ptr; s < ptr + wlen; mb_ptr_adv(s))
1637 			    mb_ptr_adv(p);
1638 			mip->mi_compoff = (int)(p - mip->mi_fword);
1639 		    }
1640 		}
1641 #endif
1642 		c = mip->mi_compoff;
1643 		++mip->mi_complen;
1644 		if (flags & WF_COMPROOT)
1645 		    ++mip->mi_compextra;
1646 
1647 		/* For NOBREAK we need to try all NOBREAK languages, at least
1648 		 * to find the ".add" file(s). */
1649 		for (lpi = 0; lpi < mip->mi_win->w_s->b_langp.ga_len; ++lpi)
1650 		{
1651 		    if (slang->sl_nobreak)
1652 		    {
1653 			mip->mi_lp = LANGP_ENTRY(mip->mi_win->w_s->b_langp, lpi);
1654 			if (mip->mi_lp->lp_slang->sl_fidxs == NULL
1655 					 || !mip->mi_lp->lp_slang->sl_nobreak)
1656 			    continue;
1657 		    }
1658 
1659 		    find_word(mip, FIND_COMPOUND);
1660 
1661 		    /* When NOBREAK any word that matches is OK.  Otherwise we
1662 		     * need to find the longest match, thus try with keep-case
1663 		     * and prefix too. */
1664 		    if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1665 		    {
1666 			/* Find following word in keep-case tree. */
1667 			mip->mi_compoff = wlen;
1668 			find_word(mip, FIND_KEEPCOMPOUND);
1669 
1670 #if 0	    /* Disabled, a prefix must not appear halfway a compound word,
1671 	       unless the COMPOUNDPERMITFLAG is used and then it can't be a
1672 	       postponed prefix. */
1673 			if (!slang->sl_nobreak || mip->mi_result == SP_BAD)
1674 			{
1675 			    /* Check for following word with prefix. */
1676 			    mip->mi_compoff = c;
1677 			    find_prefix(mip, FIND_COMPOUND);
1678 			}
1679 #endif
1680 		    }
1681 
1682 		    if (!slang->sl_nobreak)
1683 			break;
1684 		}
1685 		--mip->mi_complen;
1686 		if (flags & WF_COMPROOT)
1687 		    --mip->mi_compextra;
1688 		mip->mi_lp = save_lp;
1689 
1690 		if (slang->sl_nobreak)
1691 		{
1692 		    nobreak_result = mip->mi_result;
1693 		    mip->mi_result = save_result;
1694 		    mip->mi_end = save_end;
1695 		}
1696 		else
1697 		{
1698 		    if (mip->mi_result == SP_OK)
1699 			break;
1700 		    continue;
1701 		}
1702 	    }
1703 
1704 	    if (flags & WF_BANNED)
1705 		res = SP_BANNED;
1706 	    else if (flags & WF_REGION)
1707 	    {
1708 		/* Check region. */
1709 		if ((mip->mi_lp->lp_region & (flags >> 16)) != 0)
1710 		    res = SP_OK;
1711 		else
1712 		    res = SP_LOCAL;
1713 	    }
1714 	    else if (flags & WF_RARE)
1715 		res = SP_RARE;
1716 	    else
1717 		res = SP_OK;
1718 
1719 	    /* Always use the longest match and the best result.  For NOBREAK
1720 	     * we separately keep the longest match without a following good
1721 	     * word as a fall-back. */
1722 	    if (nobreak_result == SP_BAD)
1723 	    {
1724 		if (mip->mi_result2 > res)
1725 		{
1726 		    mip->mi_result2 = res;
1727 		    mip->mi_end2 = mip->mi_word + wlen;
1728 		}
1729 		else if (mip->mi_result2 == res
1730 					&& mip->mi_end2 < mip->mi_word + wlen)
1731 		    mip->mi_end2 = mip->mi_word + wlen;
1732 	    }
1733 	    else if (mip->mi_result > res)
1734 	    {
1735 		mip->mi_result = res;
1736 		mip->mi_end = mip->mi_word + wlen;
1737 	    }
1738 	    else if (mip->mi_result == res && mip->mi_end < mip->mi_word + wlen)
1739 		mip->mi_end = mip->mi_word + wlen;
1740 
1741 	    if (mip->mi_result == SP_OK)
1742 		break;
1743 	}
1744 
1745 	if (mip->mi_result == SP_OK)
1746 	    break;
1747     }
1748 }
1749 
1750 /*
1751  * Return TRUE if there is a match between the word ptr[wlen] and
1752  * CHECKCOMPOUNDPATTERN rules, assuming that we will concatenate with another
1753  * word.
1754  * A match means that the first part of CHECKCOMPOUNDPATTERN matches at the
1755  * end of ptr[wlen] and the second part matches after it.
1756  */
1757     static int
1758 match_checkcompoundpattern(ptr, wlen, gap)
1759     char_u	*ptr;
1760     int		wlen;
1761     garray_T	*gap;  /* &sl_comppat */
1762 {
1763     int		i;
1764     char_u	*p;
1765     int		len;
1766 
1767     for (i = 0; i + 1 < gap->ga_len; i += 2)
1768     {
1769 	p = ((char_u **)gap->ga_data)[i + 1];
1770 	if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0)
1771 	{
1772 	    /* Second part matches at start of following compound word, now
1773 	     * check if first part matches at end of previous word. */
1774 	    p = ((char_u **)gap->ga_data)[i];
1775 	    len = (int)STRLEN(p);
1776 	    if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0)
1777 		return TRUE;
1778 	}
1779     }
1780     return FALSE;
1781 }
1782 
1783 /*
1784  * Return TRUE if "flags" is a valid sequence of compound flags and "word"
1785  * does not have too many syllables.
1786  */
1787     static int
1788 can_compound(slang, word, flags)
1789     slang_T	*slang;
1790     char_u	*word;
1791     char_u	*flags;
1792 {
1793 #ifdef FEAT_MBYTE
1794     char_u	uflags[MAXWLEN * 2];
1795     int		i;
1796 #endif
1797     char_u	*p;
1798 
1799     if (slang->sl_compprog == NULL)
1800 	return FALSE;
1801 #ifdef FEAT_MBYTE
1802     if (enc_utf8)
1803     {
1804 	/* Need to convert the single byte flags to utf8 characters. */
1805 	p = uflags;
1806 	for (i = 0; flags[i] != NUL; ++i)
1807 	    p += mb_char2bytes(flags[i], p);
1808 	*p = NUL;
1809 	p = uflags;
1810     }
1811     else
1812 #endif
1813 	p = flags;
1814     if (!vim_regexec_prog(&slang->sl_compprog, FALSE, p, 0))
1815 	return FALSE;
1816 
1817     /* Count the number of syllables.  This may be slow, do it last.  If there
1818      * are too many syllables AND the number of compound words is above
1819      * COMPOUNDWORDMAX then compounding is not allowed. */
1820     if (slang->sl_compsylmax < MAXWLEN
1821 		       && count_syllables(slang, word) > slang->sl_compsylmax)
1822 	return (int)STRLEN(flags) < slang->sl_compmax;
1823     return TRUE;
1824 }
1825 
1826 /*
1827  * Return TRUE when the sequence of flags in "compflags" plus "flag" can
1828  * possibly form a valid compounded word.  This also checks the COMPOUNDRULE
1829  * lines if they don't contain wildcards.
1830  */
1831     static int
1832 can_be_compound(sp, slang, compflags, flag)
1833     trystate_T	*sp;
1834     slang_T	*slang;
1835     char_u	*compflags;
1836     int		flag;
1837 {
1838     /* If the flag doesn't appear in sl_compstartflags or sl_compallflags
1839      * then it can't possibly compound. */
1840     if (!byte_in_str(sp->ts_complen == sp->ts_compsplit
1841 		? slang->sl_compstartflags : slang->sl_compallflags, flag))
1842 	return FALSE;
1843 
1844     /* If there are no wildcards, we can check if the flags collected so far
1845      * possibly can form a match with COMPOUNDRULE patterns.  This only
1846      * makes sense when we have two or more words. */
1847     if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit)
1848     {
1849 	int v;
1850 
1851 	compflags[sp->ts_complen] = flag;
1852 	compflags[sp->ts_complen + 1] = NUL;
1853 	v = match_compoundrule(slang, compflags + sp->ts_compsplit);
1854 	compflags[sp->ts_complen] = NUL;
1855 	return v;
1856     }
1857 
1858     return TRUE;
1859 }
1860 
1861 
1862 /*
1863  * Return TRUE if the compound flags in compflags[] match the start of any
1864  * compound rule.  This is used to stop trying a compound if the flags
1865  * collected so far can't possibly match any compound rule.
1866  * Caller must check that slang->sl_comprules is not NULL.
1867  */
1868     static int
1869 match_compoundrule(slang, compflags)
1870     slang_T	*slang;
1871     char_u	*compflags;
1872 {
1873     char_u	*p;
1874     int		i;
1875     int		c;
1876 
1877     /* loop over all the COMPOUNDRULE entries */
1878     for (p = slang->sl_comprules; *p != NUL; ++p)
1879     {
1880 	/* loop over the flags in the compound word we have made, match
1881 	 * them against the current rule entry */
1882 	for (i = 0; ; ++i)
1883 	{
1884 	    c = compflags[i];
1885 	    if (c == NUL)
1886 		/* found a rule that matches for the flags we have so far */
1887 		return TRUE;
1888 	    if (*p == '/' || *p == NUL)
1889 		break;  /* end of rule, it's too short */
1890 	    if (*p == '[')
1891 	    {
1892 		int match = FALSE;
1893 
1894 		/* compare against all the flags in [] */
1895 		++p;
1896 		while (*p != ']' && *p != NUL)
1897 		    if (*p++ == c)
1898 			match = TRUE;
1899 		if (!match)
1900 		    break;  /* none matches */
1901 	    }
1902 	    else if (*p != c)
1903 		break;  /* flag of word doesn't match flag in pattern */
1904 	    ++p;
1905 	}
1906 
1907 	/* Skip to the next "/", where the next pattern starts. */
1908 	p = vim_strchr(p, '/');
1909 	if (p == NULL)
1910 	    break;
1911     }
1912 
1913     /* Checked all the rules and none of them match the flags, so there
1914      * can't possibly be a compound starting with these flags. */
1915     return FALSE;
1916 }
1917 
1918 /*
1919  * Return non-zero if the prefix indicated by "arridx" matches with the prefix
1920  * ID in "flags" for the word "word".
1921  * The WF_RAREPFX flag is included in the return value for a rare prefix.
1922  */
1923     static int
1924 valid_word_prefix(totprefcnt, arridx, flags, word, slang, cond_req)
1925     int		totprefcnt;	/* nr of prefix IDs */
1926     int		arridx;		/* idx in sl_pidxs[] */
1927     int		flags;
1928     char_u	*word;
1929     slang_T	*slang;
1930     int		cond_req;	/* only use prefixes with a condition */
1931 {
1932     int		prefcnt;
1933     int		pidx;
1934     regprog_T	**rp;
1935     int		prefid;
1936 
1937     prefid = (unsigned)flags >> 24;
1938     for (prefcnt = totprefcnt - 1; prefcnt >= 0; --prefcnt)
1939     {
1940 	pidx = slang->sl_pidxs[arridx + prefcnt];
1941 
1942 	/* Check the prefix ID. */
1943 	if (prefid != (pidx & 0xff))
1944 	    continue;
1945 
1946 	/* Check if the prefix doesn't combine and the word already has a
1947 	 * suffix. */
1948 	if ((flags & WF_HAS_AFF) && (pidx & WF_PFX_NC))
1949 	    continue;
1950 
1951 	/* Check the condition, if there is one.  The condition index is
1952 	 * stored in the two bytes above the prefix ID byte.  */
1953 	rp = &slang->sl_prefprog[((unsigned)pidx >> 8) & 0xffff];
1954 	if (*rp != NULL)
1955 	{
1956 	    if (!vim_regexec_prog(rp, FALSE, word, 0))
1957 		continue;
1958 	}
1959 	else if (cond_req)
1960 	    continue;
1961 
1962 	/* It's a match!  Return the WF_ flags. */
1963 	return pidx;
1964     }
1965     return 0;
1966 }
1967 
1968 /*
1969  * Check if the word at "mip->mi_word" has a matching prefix.
1970  * If it does, then check the following word.
1971  *
1972  * If "mode" is "FIND_COMPOUND" then do the same after another word, find a
1973  * prefix in a compound word.
1974  *
1975  * For a match mip->mi_result is updated.
1976  */
1977     static void
1978 find_prefix(mip, mode)
1979     matchinf_T	*mip;
1980     int		mode;
1981 {
1982     idx_T	arridx = 0;
1983     int		len;
1984     int		wlen = 0;
1985     int		flen;
1986     int		c;
1987     char_u	*ptr;
1988     idx_T	lo, hi, m;
1989     slang_T	*slang = mip->mi_lp->lp_slang;
1990     char_u	*byts;
1991     idx_T	*idxs;
1992 
1993     byts = slang->sl_pbyts;
1994     if (byts == NULL)
1995 	return;			/* array is empty */
1996 
1997     /* We use the case-folded word here, since prefixes are always
1998      * case-folded. */
1999     ptr = mip->mi_fword;
2000     flen = mip->mi_fwordlen;    /* available case-folded bytes */
2001     if (mode == FIND_COMPOUND)
2002     {
2003 	/* Skip over the previously found word(s). */
2004 	ptr += mip->mi_compoff;
2005 	flen -= mip->mi_compoff;
2006     }
2007     idxs = slang->sl_pidxs;
2008 
2009     /*
2010      * Repeat advancing in the tree until:
2011      * - there is a byte that doesn't match,
2012      * - we reach the end of the tree,
2013      * - or we reach the end of the line.
2014      */
2015     for (;;)
2016     {
2017 	if (flen == 0 && *mip->mi_fend != NUL)
2018 	    flen = fold_more(mip);
2019 
2020 	len = byts[arridx++];
2021 
2022 	/* If the first possible byte is a zero the prefix could end here.
2023 	 * Check if the following word matches and supports the prefix. */
2024 	if (byts[arridx] == 0)
2025 	{
2026 	    /* There can be several prefixes with different conditions.  We
2027 	     * try them all, since we don't know which one will give the
2028 	     * longest match.  The word is the same each time, pass the list
2029 	     * of possible prefixes to find_word(). */
2030 	    mip->mi_prefarridx = arridx;
2031 	    mip->mi_prefcnt = len;
2032 	    while (len > 0 && byts[arridx] == 0)
2033 	    {
2034 		++arridx;
2035 		--len;
2036 	    }
2037 	    mip->mi_prefcnt -= len;
2038 
2039 	    /* Find the word that comes after the prefix. */
2040 	    mip->mi_prefixlen = wlen;
2041 	    if (mode == FIND_COMPOUND)
2042 		/* Skip over the previously found word(s). */
2043 		mip->mi_prefixlen += mip->mi_compoff;
2044 
2045 #ifdef FEAT_MBYTE
2046 	    if (has_mbyte)
2047 	    {
2048 		/* Case-folded length may differ from original length. */
2049 		mip->mi_cprefixlen = nofold_len(mip->mi_fword,
2050 					     mip->mi_prefixlen, mip->mi_word);
2051 	    }
2052 	    else
2053 		mip->mi_cprefixlen = mip->mi_prefixlen;
2054 #endif
2055 	    find_word(mip, FIND_PREFIX);
2056 
2057 
2058 	    if (len == 0)
2059 		break;	    /* no children, word must end here */
2060 	}
2061 
2062 	/* Stop looking at end of the line. */
2063 	if (ptr[wlen] == NUL)
2064 	    break;
2065 
2066 	/* Perform a binary search in the list of accepted bytes. */
2067 	c = ptr[wlen];
2068 	lo = arridx;
2069 	hi = arridx + len - 1;
2070 	while (lo < hi)
2071 	{
2072 	    m = (lo + hi) / 2;
2073 	    if (byts[m] > c)
2074 		hi = m - 1;
2075 	    else if (byts[m] < c)
2076 		lo = m + 1;
2077 	    else
2078 	    {
2079 		lo = hi = m;
2080 		break;
2081 	    }
2082 	}
2083 
2084 	/* Stop if there is no matching byte. */
2085 	if (hi < lo || byts[lo] != c)
2086 	    break;
2087 
2088 	/* Continue at the child (if there is one). */
2089 	arridx = idxs[lo];
2090 	++wlen;
2091 	--flen;
2092     }
2093 }
2094 
2095 /*
2096  * Need to fold at least one more character.  Do until next non-word character
2097  * for efficiency.  Include the non-word character too.
2098  * Return the length of the folded chars in bytes.
2099  */
2100     static int
2101 fold_more(mip)
2102     matchinf_T	*mip;
2103 {
2104     int		flen;
2105     char_u	*p;
2106 
2107     p = mip->mi_fend;
2108     do
2109     {
2110 	mb_ptr_adv(mip->mi_fend);
2111     } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win));
2112 
2113     /* Include the non-word character so that we can check for the word end. */
2114     if (*mip->mi_fend != NUL)
2115 	mb_ptr_adv(mip->mi_fend);
2116 
2117     (void)spell_casefold(p, (int)(mip->mi_fend - p),
2118 			     mip->mi_fword + mip->mi_fwordlen,
2119 			     MAXWLEN - mip->mi_fwordlen);
2120     flen = (int)STRLEN(mip->mi_fword + mip->mi_fwordlen);
2121     mip->mi_fwordlen += flen;
2122     return flen;
2123 }
2124 
2125 /*
2126  * Check case flags for a word.  Return TRUE if the word has the requested
2127  * case.
2128  */
2129     static int
2130 spell_valid_case(wordflags, treeflags)
2131     int	    wordflags;	    /* flags for the checked word. */
2132     int	    treeflags;	    /* flags for the word in the spell tree */
2133 {
2134     return ((wordflags == WF_ALLCAP && (treeflags & WF_FIXCAP) == 0)
2135 	    || ((treeflags & (WF_ALLCAP | WF_KEEPCAP)) == 0
2136 		&& ((treeflags & WF_ONECAP) == 0
2137 					   || (wordflags & WF_ONECAP) != 0)));
2138 }
2139 
2140 /*
2141  * Return TRUE if spell checking is not enabled.
2142  */
2143     static int
2144 no_spell_checking(wp)
2145     win_T	*wp;
2146 {
2147     if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL
2148 					 || wp->w_s->b_langp.ga_len == 0)
2149     {
2150 	EMSG(_("E756: Spell checking is not enabled"));
2151 	return TRUE;
2152     }
2153     return FALSE;
2154 }
2155 
2156 /*
2157  * Move to next spell error.
2158  * "curline" is FALSE for "[s", "]s", "[S" and "]S".
2159  * "curline" is TRUE to find word under/after cursor in the same line.
2160  * For Insert mode completion "dir" is BACKWARD and "curline" is TRUE: move
2161  * to after badly spelled word before the cursor.
2162  * Return 0 if not found, length of the badly spelled word otherwise.
2163  */
2164     int
2165 spell_move_to(wp, dir, allwords, curline, attrp)
2166     win_T	*wp;
2167     int		dir;		/* FORWARD or BACKWARD */
2168     int		allwords;	/* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */
2169     int		curline;
2170     hlf_T	*attrp;		/* return: attributes of bad word or NULL
2171 				   (only when "dir" is FORWARD) */
2172 {
2173     linenr_T	lnum;
2174     pos_T	found_pos;
2175     int		found_len = 0;
2176     char_u	*line;
2177     char_u	*p;
2178     char_u	*endp;
2179     hlf_T	attr;
2180     int		len;
2181 #ifdef FEAT_SYN_HL
2182     int		has_syntax = syntax_present(wp);
2183 #endif
2184     int		col;
2185     int		can_spell;
2186     char_u	*buf = NULL;
2187     int		buflen = 0;
2188     int		skip = 0;
2189     int		capcol = -1;
2190     int		found_one = FALSE;
2191     int		wrapped = FALSE;
2192 
2193     if (no_spell_checking(wp))
2194 	return 0;
2195 
2196     /*
2197      * Start looking for bad word at the start of the line, because we can't
2198      * start halfway a word, we don't know where it starts or ends.
2199      *
2200      * When searching backwards, we continue in the line to find the last
2201      * bad word (in the cursor line: before the cursor).
2202      *
2203      * We concatenate the start of the next line, so that wrapped words work
2204      * (e.g. "et<line-break>cetera").  Doesn't work when searching backwards
2205      * though...
2206      */
2207     lnum = wp->w_cursor.lnum;
2208     clearpos(&found_pos);
2209 
2210     while (!got_int)
2211     {
2212 	line = ml_get_buf(wp->w_buffer, lnum, FALSE);
2213 
2214 	len = (int)STRLEN(line);
2215 	if (buflen < len + MAXWLEN + 2)
2216 	{
2217 	    vim_free(buf);
2218 	    buflen = len + MAXWLEN + 2;
2219 	    buf = alloc(buflen);
2220 	    if (buf == NULL)
2221 		break;
2222 	}
2223 
2224 	/* In first line check first word for Capital. */
2225 	if (lnum == 1)
2226 	    capcol = 0;
2227 
2228 	/* For checking first word with a capital skip white space. */
2229 	if (capcol == 0)
2230 	    capcol = (int)(skipwhite(line) - line);
2231 	else if (curline && wp == curwin)
2232 	{
2233 	    /* For spellbadword(): check if first word needs a capital. */
2234 	    col = (int)(skipwhite(line) - line);
2235 	    if (check_need_cap(lnum, col))
2236 		capcol = col;
2237 
2238 	    /* Need to get the line again, may have looked at the previous
2239 	     * one. */
2240 	    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
2241 	}
2242 
2243 	/* Copy the line into "buf" and append the start of the next line if
2244 	 * possible. */
2245 	STRCPY(buf, line);
2246 	if (lnum < wp->w_buffer->b_ml.ml_line_count)
2247 	    spell_cat_line(buf + STRLEN(buf),
2248 			  ml_get_buf(wp->w_buffer, lnum + 1, FALSE), MAXWLEN);
2249 
2250 	p = buf + skip;
2251 	endp = buf + len;
2252 	while (p < endp)
2253 	{
2254 	    /* When searching backward don't search after the cursor.  Unless
2255 	     * we wrapped around the end of the buffer. */
2256 	    if (dir == BACKWARD
2257 		    && lnum == wp->w_cursor.lnum
2258 		    && !wrapped
2259 		    && (colnr_T)(p - buf) >= wp->w_cursor.col)
2260 		break;
2261 
2262 	    /* start of word */
2263 	    attr = HLF_COUNT;
2264 	    len = spell_check(wp, p, &attr, &capcol, FALSE);
2265 
2266 	    if (attr != HLF_COUNT)
2267 	    {
2268 		/* We found a bad word.  Check the attribute. */
2269 		if (allwords || attr == HLF_SPB)
2270 		{
2271 		    /* When searching forward only accept a bad word after
2272 		     * the cursor. */
2273 		    if (dir == BACKWARD
2274 			    || lnum != wp->w_cursor.lnum
2275 			    || (lnum == wp->w_cursor.lnum
2276 				&& (wrapped
2277 				    || (colnr_T)(curline ? p - buf + len
2278 						     : p - buf)
2279 						  > wp->w_cursor.col)))
2280 		    {
2281 #ifdef FEAT_SYN_HL
2282 			if (has_syntax)
2283 			{
2284 			    col = (int)(p - buf);
2285 			    (void)syn_get_id(wp, lnum, (colnr_T)col,
2286 						    FALSE, &can_spell, FALSE);
2287 			    if (!can_spell)
2288 				attr = HLF_COUNT;
2289 			}
2290 			else
2291 #endif
2292 			    can_spell = TRUE;
2293 
2294 			if (can_spell)
2295 			{
2296 			    found_one = TRUE;
2297 			    found_pos.lnum = lnum;
2298 			    found_pos.col = (int)(p - buf);
2299 #ifdef FEAT_VIRTUALEDIT
2300 			    found_pos.coladd = 0;
2301 #endif
2302 			    if (dir == FORWARD)
2303 			    {
2304 				/* No need to search further. */
2305 				wp->w_cursor = found_pos;
2306 				vim_free(buf);
2307 				if (attrp != NULL)
2308 				    *attrp = attr;
2309 				return len;
2310 			    }
2311 			    else if (curline)
2312 				/* Insert mode completion: put cursor after
2313 				 * the bad word. */
2314 				found_pos.col += len;
2315 			    found_len = len;
2316 			}
2317 		    }
2318 		    else
2319 			found_one = TRUE;
2320 		}
2321 	    }
2322 
2323 	    /* advance to character after the word */
2324 	    p += len;
2325 	    capcol -= len;
2326 	}
2327 
2328 	if (dir == BACKWARD && found_pos.lnum != 0)
2329 	{
2330 	    /* Use the last match in the line (before the cursor). */
2331 	    wp->w_cursor = found_pos;
2332 	    vim_free(buf);
2333 	    return found_len;
2334 	}
2335 
2336 	if (curline)
2337 	    break;	/* only check cursor line */
2338 
2339 	/* Advance to next line. */
2340 	if (dir == BACKWARD)
2341 	{
2342 	    /* If we are back at the starting line and searched it again there
2343 	     * is no match, give up. */
2344 	    if (lnum == wp->w_cursor.lnum && wrapped)
2345 		break;
2346 
2347 	    if (lnum > 1)
2348 		--lnum;
2349 	    else if (!p_ws)
2350 		break;	    /* at first line and 'nowrapscan' */
2351 	    else
2352 	    {
2353 		/* Wrap around to the end of the buffer.  May search the
2354 		 * starting line again and accept the last match. */
2355 		lnum = wp->w_buffer->b_ml.ml_line_count;
2356 		wrapped = TRUE;
2357 		if (!shortmess(SHM_SEARCH))
2358 		    give_warning((char_u *)_(top_bot_msg), TRUE);
2359 	    }
2360 	    capcol = -1;
2361 	}
2362 	else
2363 	{
2364 	    if (lnum < wp->w_buffer->b_ml.ml_line_count)
2365 		++lnum;
2366 	    else if (!p_ws)
2367 		break;	    /* at first line and 'nowrapscan' */
2368 	    else
2369 	    {
2370 		/* Wrap around to the start of the buffer.  May search the
2371 		 * starting line again and accept the first match. */
2372 		lnum = 1;
2373 		wrapped = TRUE;
2374 		if (!shortmess(SHM_SEARCH))
2375 		    give_warning((char_u *)_(bot_top_msg), TRUE);
2376 	    }
2377 
2378 	    /* If we are back at the starting line and there is no match then
2379 	     * give up. */
2380 	    if (lnum == wp->w_cursor.lnum && (!found_one || wrapped))
2381 		break;
2382 
2383 	    /* Skip the characters at the start of the next line that were
2384 	     * included in a match crossing line boundaries. */
2385 	    if (attr == HLF_COUNT)
2386 		skip = (int)(p - endp);
2387 	    else
2388 		skip = 0;
2389 
2390 	    /* Capcol skips over the inserted space. */
2391 	    --capcol;
2392 
2393 	    /* But after empty line check first word in next line */
2394 	    if (*skipwhite(line) == NUL)
2395 		capcol = 0;
2396 	}
2397 
2398 	line_breakcheck();
2399     }
2400 
2401     vim_free(buf);
2402     return 0;
2403 }
2404 
2405 /*
2406  * For spell checking: concatenate the start of the following line "line" into
2407  * "buf", blanking-out special characters.  Copy less then "maxlen" bytes.
2408  * Keep the blanks at the start of the next line, this is used in win_line()
2409  * to skip those bytes if the word was OK.
2410  */
2411     void
2412 spell_cat_line(buf, line, maxlen)
2413     char_u	*buf;
2414     char_u	*line;
2415     int		maxlen;
2416 {
2417     char_u	*p;
2418     int		n;
2419 
2420     p = skipwhite(line);
2421     while (vim_strchr((char_u *)"*#/\"\t", *p) != NULL)
2422 	p = skipwhite(p + 1);
2423 
2424     if (*p != NUL)
2425     {
2426 	/* Only worth concatenating if there is something else than spaces to
2427 	 * concatenate. */
2428 	n = (int)(p - line) + 1;
2429 	if (n < maxlen - 1)
2430 	{
2431 	    vim_memset(buf, ' ', n);
2432 	    vim_strncpy(buf +  n, p, maxlen - 1 - n);
2433 	}
2434     }
2435 }
2436 
2437 /*
2438  * Structure used for the cookie argument of do_in_runtimepath().
2439  */
2440 typedef struct spelload_S
2441 {
2442     char_u  sl_lang[MAXWLEN + 1];	/* language name */
2443     slang_T *sl_slang;			/* resulting slang_T struct */
2444     int	    sl_nobreak;			/* NOBREAK language found */
2445 } spelload_T;
2446 
2447 /*
2448  * Load word list(s) for "lang" from Vim spell file(s).
2449  * "lang" must be the language without the region: e.g., "en".
2450  */
2451     static void
2452 spell_load_lang(lang)
2453     char_u	*lang;
2454 {
2455     char_u	fname_enc[85];
2456     int		r;
2457     spelload_T	sl;
2458 #ifdef FEAT_AUTOCMD
2459     int		round;
2460 #endif
2461 
2462     /* Copy the language name to pass it to spell_load_cb() as a cookie.
2463      * It's truncated when an error is detected. */
2464     STRCPY(sl.sl_lang, lang);
2465     sl.sl_slang = NULL;
2466     sl.sl_nobreak = FALSE;
2467 
2468 #ifdef FEAT_AUTOCMD
2469     /* We may retry when no spell file is found for the language, an
2470      * autocommand may load it then. */
2471     for (round = 1; round <= 2; ++round)
2472 #endif
2473     {
2474 	/*
2475 	 * Find the first spell file for "lang" in 'runtimepath' and load it.
2476 	 */
2477 	vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2478 #ifdef VMS
2479 					"spell/%s_%s.spl",
2480 #else
2481 					"spell/%s.%s.spl",
2482 #endif
2483 							   lang, spell_enc());
2484 	r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2485 
2486 	if (r == FAIL && *sl.sl_lang != NUL)
2487 	{
2488 	    /* Try loading the ASCII version. */
2489 	    vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
2490 #ifdef VMS
2491 						  "spell/%s_ascii.spl",
2492 #else
2493 						  "spell/%s.ascii.spl",
2494 #endif
2495 									lang);
2496 	    r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
2497 
2498 #ifdef FEAT_AUTOCMD
2499 	    if (r == FAIL && *sl.sl_lang != NUL && round == 1
2500 		    && apply_autocmds(EVENT_SPELLFILEMISSING, lang,
2501 					      curbuf->b_fname, FALSE, curbuf))
2502 		continue;
2503 	    break;
2504 #endif
2505 	}
2506 #ifdef FEAT_AUTOCMD
2507 	break;
2508 #endif
2509     }
2510 
2511     if (r == FAIL)
2512     {
2513 	smsg((char_u *)
2514 #ifdef VMS
2515 	_("Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\""),
2516 #else
2517 	_("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""),
2518 #endif
2519 						     lang, spell_enc(), lang);
2520     }
2521     else if (sl.sl_slang != NULL)
2522     {
2523 	/* At least one file was loaded, now load ALL the additions. */
2524 	STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
2525 	do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl);
2526     }
2527 }
2528 
2529 /*
2530  * Return the encoding used for spell checking: Use 'encoding', except that we
2531  * use "latin1" for "latin9".  And limit to 60 characters (just in case).
2532  */
2533     static char_u *
2534 spell_enc()
2535 {
2536 
2537 #ifdef FEAT_MBYTE
2538     if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0)
2539 	return p_enc;
2540 #endif
2541     return (char_u *)"latin1";
2542 }
2543 
2544 /*
2545  * Get the name of the .spl file for the internal wordlist into
2546  * "fname[MAXPATHL]".
2547  */
2548     static void
2549 int_wordlist_spl(fname)
2550     char_u	    *fname;
2551 {
2552     vim_snprintf((char *)fname, MAXPATHL, SPL_FNAME_TMPL,
2553 						  int_wordlist, spell_enc());
2554 }
2555 
2556 /*
2557  * Allocate a new slang_T for language "lang".  "lang" can be NULL.
2558  * Caller must fill "sl_next".
2559  */
2560     static slang_T *
2561 slang_alloc(lang)
2562     char_u	*lang;
2563 {
2564     slang_T *lp;
2565 
2566     lp = (slang_T *)alloc_clear(sizeof(slang_T));
2567     if (lp != NULL)
2568     {
2569 	if (lang != NULL)
2570 	    lp->sl_name = vim_strsave(lang);
2571 	ga_init2(&lp->sl_rep, sizeof(fromto_T), 10);
2572 	ga_init2(&lp->sl_repsal, sizeof(fromto_T), 10);
2573 	lp->sl_compmax = MAXWLEN;
2574 	lp->sl_compsylmax = MAXWLEN;
2575 	hash_init(&lp->sl_wordcount);
2576     }
2577 
2578     return lp;
2579 }
2580 
2581 /*
2582  * Free the contents of an slang_T and the structure itself.
2583  */
2584     static void
2585 slang_free(lp)
2586     slang_T	*lp;
2587 {
2588     vim_free(lp->sl_name);
2589     vim_free(lp->sl_fname);
2590     slang_clear(lp);
2591     vim_free(lp);
2592 }
2593 
2594 /*
2595  * Clear an slang_T so that the file can be reloaded.
2596  */
2597     static void
2598 slang_clear(lp)
2599     slang_T	*lp;
2600 {
2601     garray_T	*gap;
2602     fromto_T	*ftp;
2603     salitem_T	*smp;
2604     int		i;
2605     int		round;
2606 
2607     vim_free(lp->sl_fbyts);
2608     lp->sl_fbyts = NULL;
2609     vim_free(lp->sl_kbyts);
2610     lp->sl_kbyts = NULL;
2611     vim_free(lp->sl_pbyts);
2612     lp->sl_pbyts = NULL;
2613 
2614     vim_free(lp->sl_fidxs);
2615     lp->sl_fidxs = NULL;
2616     vim_free(lp->sl_kidxs);
2617     lp->sl_kidxs = NULL;
2618     vim_free(lp->sl_pidxs);
2619     lp->sl_pidxs = NULL;
2620 
2621     for (round = 1; round <= 2; ++round)
2622     {
2623 	gap = round == 1 ? &lp->sl_rep : &lp->sl_repsal;
2624 	while (gap->ga_len > 0)
2625 	{
2626 	    ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len];
2627 	    vim_free(ftp->ft_from);
2628 	    vim_free(ftp->ft_to);
2629 	}
2630 	ga_clear(gap);
2631     }
2632 
2633     gap = &lp->sl_sal;
2634     if (lp->sl_sofo)
2635     {
2636 	/* "ga_len" is set to 1 without adding an item for latin1 */
2637 	if (gap->ga_data != NULL)
2638 	    /* SOFOFROM and SOFOTO items: free lists of wide characters. */
2639 	    for (i = 0; i < gap->ga_len; ++i)
2640 		vim_free(((int **)gap->ga_data)[i]);
2641     }
2642     else
2643 	/* SAL items: free salitem_T items */
2644 	while (gap->ga_len > 0)
2645 	{
2646 	    smp = &((salitem_T *)gap->ga_data)[--gap->ga_len];
2647 	    vim_free(smp->sm_lead);
2648 	    /* Don't free sm_oneof and sm_rules, they point into sm_lead. */
2649 	    vim_free(smp->sm_to);
2650 #ifdef FEAT_MBYTE
2651 	    vim_free(smp->sm_lead_w);
2652 	    vim_free(smp->sm_oneof_w);
2653 	    vim_free(smp->sm_to_w);
2654 #endif
2655 	}
2656     ga_clear(gap);
2657 
2658     for (i = 0; i < lp->sl_prefixcnt; ++i)
2659 	vim_regfree(lp->sl_prefprog[i]);
2660     lp->sl_prefixcnt = 0;
2661     vim_free(lp->sl_prefprog);
2662     lp->sl_prefprog = NULL;
2663 
2664     vim_free(lp->sl_info);
2665     lp->sl_info = NULL;
2666 
2667     vim_free(lp->sl_midword);
2668     lp->sl_midword = NULL;
2669 
2670     vim_regfree(lp->sl_compprog);
2671     vim_free(lp->sl_comprules);
2672     vim_free(lp->sl_compstartflags);
2673     vim_free(lp->sl_compallflags);
2674     lp->sl_compprog = NULL;
2675     lp->sl_comprules = NULL;
2676     lp->sl_compstartflags = NULL;
2677     lp->sl_compallflags = NULL;
2678 
2679     vim_free(lp->sl_syllable);
2680     lp->sl_syllable = NULL;
2681     ga_clear(&lp->sl_syl_items);
2682 
2683     ga_clear_strings(&lp->sl_comppat);
2684 
2685     hash_clear_all(&lp->sl_wordcount, WC_KEY_OFF);
2686     hash_init(&lp->sl_wordcount);
2687 
2688 #ifdef FEAT_MBYTE
2689     hash_clear_all(&lp->sl_map_hash, 0);
2690 #endif
2691 
2692     /* Clear info from .sug file. */
2693     slang_clear_sug(lp);
2694 
2695     lp->sl_compmax = MAXWLEN;
2696     lp->sl_compminlen = 0;
2697     lp->sl_compsylmax = MAXWLEN;
2698     lp->sl_regions[0] = NUL;
2699 }
2700 
2701 /*
2702  * Clear the info from the .sug file in "lp".
2703  */
2704     static void
2705 slang_clear_sug(lp)
2706     slang_T	*lp;
2707 {
2708     vim_free(lp->sl_sbyts);
2709     lp->sl_sbyts = NULL;
2710     vim_free(lp->sl_sidxs);
2711     lp->sl_sidxs = NULL;
2712     close_spellbuf(lp->sl_sugbuf);
2713     lp->sl_sugbuf = NULL;
2714     lp->sl_sugloaded = FALSE;
2715     lp->sl_sugtime = 0;
2716 }
2717 
2718 /*
2719  * Load one spell file and store the info into a slang_T.
2720  * Invoked through do_in_runtimepath().
2721  */
2722     static void
2723 spell_load_cb(fname, cookie)
2724     char_u	*fname;
2725     void	*cookie;
2726 {
2727     spelload_T	*slp = (spelload_T *)cookie;
2728     slang_T	*slang;
2729 
2730     slang = spell_load_file(fname, slp->sl_lang, NULL, FALSE);
2731     if (slang != NULL)
2732     {
2733 	/* When a previously loaded file has NOBREAK also use it for the
2734 	 * ".add" files. */
2735 	if (slp->sl_nobreak && slang->sl_add)
2736 	    slang->sl_nobreak = TRUE;
2737 	else if (slang->sl_nobreak)
2738 	    slp->sl_nobreak = TRUE;
2739 
2740 	slp->sl_slang = slang;
2741     }
2742 }
2743 
2744 /*
2745  * Load one spell file and store the info into a slang_T.
2746  *
2747  * This is invoked in three ways:
2748  * - From spell_load_cb() to load a spell file for the first time.  "lang" is
2749  *   the language name, "old_lp" is NULL.  Will allocate an slang_T.
2750  * - To reload a spell file that was changed.  "lang" is NULL and "old_lp"
2751  *   points to the existing slang_T.
2752  * - Just after writing a .spl file; it's read back to produce the .sug file.
2753  *   "old_lp" is NULL and "lang" is NULL.  Will allocate an slang_T.
2754  *
2755  * Returns the slang_T the spell file was loaded into.  NULL for error.
2756  */
2757     static slang_T *
2758 spell_load_file(fname, lang, old_lp, silent)
2759     char_u	*fname;
2760     char_u	*lang;
2761     slang_T	*old_lp;
2762     int		silent;		/* no error if file doesn't exist */
2763 {
2764     FILE	*fd;
2765     char_u	buf[VIMSPELLMAGICL];
2766     char_u	*p;
2767     int		i;
2768     int		n;
2769     int		len;
2770     char_u	*save_sourcing_name = sourcing_name;
2771     linenr_T	save_sourcing_lnum = sourcing_lnum;
2772     slang_T	*lp = NULL;
2773     int		c = 0;
2774     int		res;
2775 
2776     fd = mch_fopen((char *)fname, "r");
2777     if (fd == NULL)
2778     {
2779 	if (!silent)
2780 	    EMSG2(_(e_notopen), fname);
2781 	else if (p_verbose > 2)
2782 	{
2783 	    verbose_enter();
2784 	    smsg((char_u *)e_notopen, fname);
2785 	    verbose_leave();
2786 	}
2787 	goto endFAIL;
2788     }
2789     if (p_verbose > 2)
2790     {
2791 	verbose_enter();
2792 	smsg((char_u *)_("Reading spell file \"%s\""), fname);
2793 	verbose_leave();
2794     }
2795 
2796     if (old_lp == NULL)
2797     {
2798 	lp = slang_alloc(lang);
2799 	if (lp == NULL)
2800 	    goto endFAIL;
2801 
2802 	/* Remember the file name, used to reload the file when it's updated. */
2803 	lp->sl_fname = vim_strsave(fname);
2804 	if (lp->sl_fname == NULL)
2805 	    goto endFAIL;
2806 
2807 	/* Check for .add.spl (_add.spl for VMS). */
2808 	lp->sl_add = strstr((char *)gettail(fname), SPL_FNAME_ADD) != NULL;
2809     }
2810     else
2811 	lp = old_lp;
2812 
2813     /* Set sourcing_name, so that error messages mention the file name. */
2814     sourcing_name = fname;
2815     sourcing_lnum = 0;
2816 
2817     /*
2818      * <HEADER>: <fileID>
2819      */
2820     for (i = 0; i < VIMSPELLMAGICL; ++i)
2821 	buf[i] = getc(fd);				/* <fileID> */
2822     if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0)
2823     {
2824 	EMSG(_("E757: This does not look like a spell file"));
2825 	goto endFAIL;
2826     }
2827     c = getc(fd);					/* <versionnr> */
2828     if (c < VIMSPELLVERSION)
2829     {
2830 	EMSG(_("E771: Old spell file, needs to be updated"));
2831 	goto endFAIL;
2832     }
2833     else if (c > VIMSPELLVERSION)
2834     {
2835 	EMSG(_("E772: Spell file is for newer version of Vim"));
2836 	goto endFAIL;
2837     }
2838 
2839 
2840     /*
2841      * <SECTIONS>: <section> ... <sectionend>
2842      * <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
2843      */
2844     for (;;)
2845     {
2846 	n = getc(fd);			    /* <sectionID> or <sectionend> */
2847 	if (n == SN_END)
2848 	    break;
2849 	c = getc(fd);					/* <sectionflags> */
2850 	len = get4c(fd);				/* <sectionlen> */
2851 	if (len < 0)
2852 	    goto truncerr;
2853 
2854 	res = 0;
2855 	switch (n)
2856 	{
2857 	    case SN_INFO:
2858 		lp->sl_info = read_string(fd, len);	/* <infotext> */
2859 		if (lp->sl_info == NULL)
2860 		    goto endFAIL;
2861 		break;
2862 
2863 	    case SN_REGION:
2864 		res = read_region_section(fd, lp, len);
2865 		break;
2866 
2867 	    case SN_CHARFLAGS:
2868 		res = read_charflags_section(fd);
2869 		break;
2870 
2871 	    case SN_MIDWORD:
2872 		lp->sl_midword = read_string(fd, len);	/* <midword> */
2873 		if (lp->sl_midword == NULL)
2874 		    goto endFAIL;
2875 		break;
2876 
2877 	    case SN_PREFCOND:
2878 		res = read_prefcond_section(fd, lp);
2879 		break;
2880 
2881 	    case SN_REP:
2882 		res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first);
2883 		break;
2884 
2885 	    case SN_REPSAL:
2886 		res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first);
2887 		break;
2888 
2889 	    case SN_SAL:
2890 		res = read_sal_section(fd, lp);
2891 		break;
2892 
2893 	    case SN_SOFO:
2894 		res = read_sofo_section(fd, lp);
2895 		break;
2896 
2897 	    case SN_MAP:
2898 		p = read_string(fd, len);		/* <mapstr> */
2899 		if (p == NULL)
2900 		    goto endFAIL;
2901 		set_map_str(lp, p);
2902 		vim_free(p);
2903 		break;
2904 
2905 	    case SN_WORDS:
2906 		res = read_words_section(fd, lp, len);
2907 		break;
2908 
2909 	    case SN_SUGFILE:
2910 		lp->sl_sugtime = get8ctime(fd);		/* <timestamp> */
2911 		break;
2912 
2913 	    case SN_NOSPLITSUGS:
2914 		lp->sl_nosplitsugs = TRUE;		/* <timestamp> */
2915 		break;
2916 
2917 	    case SN_COMPOUND:
2918 		res = read_compound(fd, lp, len);
2919 		break;
2920 
2921 	    case SN_NOBREAK:
2922 		lp->sl_nobreak = TRUE;
2923 		break;
2924 
2925 	    case SN_SYLLABLE:
2926 		lp->sl_syllable = read_string(fd, len);	/* <syllable> */
2927 		if (lp->sl_syllable == NULL)
2928 		    goto endFAIL;
2929 		if (init_syl_tab(lp) == FAIL)
2930 		    goto endFAIL;
2931 		break;
2932 
2933 	    default:
2934 		/* Unsupported section.  When it's required give an error
2935 		 * message.  When it's not required skip the contents. */
2936 		if (c & SNF_REQUIRED)
2937 		{
2938 		    EMSG(_("E770: Unsupported section in spell file"));
2939 		    goto endFAIL;
2940 		}
2941 		while (--len >= 0)
2942 		    if (getc(fd) < 0)
2943 			goto truncerr;
2944 		break;
2945 	}
2946 someerror:
2947 	if (res == SP_FORMERROR)
2948 	{
2949 	    EMSG(_(e_format));
2950 	    goto endFAIL;
2951 	}
2952 	if (res == SP_TRUNCERROR)
2953 	{
2954 truncerr:
2955 	    EMSG(_(e_spell_trunc));
2956 	    goto endFAIL;
2957 	}
2958 	if (res == SP_OTHERERROR)
2959 	    goto endFAIL;
2960     }
2961 
2962     /* <LWORDTREE> */
2963     res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, FALSE, 0);
2964     if (res != 0)
2965 	goto someerror;
2966 
2967     /* <KWORDTREE> */
2968     res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, FALSE, 0);
2969     if (res != 0)
2970 	goto someerror;
2971 
2972     /* <PREFIXTREE> */
2973     res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, TRUE,
2974 							    lp->sl_prefixcnt);
2975     if (res != 0)
2976 	goto someerror;
2977 
2978     /* For a new file link it in the list of spell files. */
2979     if (old_lp == NULL && lang != NULL)
2980     {
2981 	lp->sl_next = first_lang;
2982 	first_lang = lp;
2983     }
2984 
2985     goto endOK;
2986 
2987 endFAIL:
2988     if (lang != NULL)
2989 	/* truncating the name signals the error to spell_load_lang() */
2990 	*lang = NUL;
2991     if (lp != NULL && old_lp == NULL)
2992 	slang_free(lp);
2993     lp = NULL;
2994 
2995 endOK:
2996     if (fd != NULL)
2997 	fclose(fd);
2998     sourcing_name = save_sourcing_name;
2999     sourcing_lnum = save_sourcing_lnum;
3000 
3001     return lp;
3002 }
3003 
3004 /*
3005  * Read a length field from "fd" in "cnt_bytes" bytes.
3006  * Allocate memory, read the string into it and add a NUL at the end.
3007  * Returns NULL when the count is zero.
3008  * Sets "*cntp" to SP_*ERROR when there is an error, length of the result
3009  * otherwise.
3010  */
3011     static char_u *
3012 read_cnt_string(fd, cnt_bytes, cntp)
3013     FILE	*fd;
3014     int		cnt_bytes;
3015     int		*cntp;
3016 {
3017     int		cnt = 0;
3018     int		i;
3019     char_u	*str;
3020 
3021     /* read the length bytes, MSB first */
3022     for (i = 0; i < cnt_bytes; ++i)
3023 	cnt = (cnt << 8) + getc(fd);
3024     if (cnt < 0)
3025     {
3026 	*cntp = SP_TRUNCERROR;
3027 	return NULL;
3028     }
3029     *cntp = cnt;
3030     if (cnt == 0)
3031 	return NULL;	    /* nothing to read, return NULL */
3032 
3033     str = read_string(fd, cnt);
3034     if (str == NULL)
3035 	*cntp = SP_OTHERERROR;
3036     return str;
3037 }
3038 
3039 /*
3040  * Read SN_REGION: <regionname> ...
3041  * Return SP_*ERROR flags.
3042  */
3043     static int
3044 read_region_section(fd, lp, len)
3045     FILE	*fd;
3046     slang_T	*lp;
3047     int		len;
3048 {
3049     int		i;
3050 
3051     if (len > 16)
3052 	return SP_FORMERROR;
3053     for (i = 0; i < len; ++i)
3054 	lp->sl_regions[i] = getc(fd);			/* <regionname> */
3055     lp->sl_regions[len] = NUL;
3056     return 0;
3057 }
3058 
3059 /*
3060  * Read SN_CHARFLAGS section: <charflagslen> <charflags>
3061  *				<folcharslen> <folchars>
3062  * Return SP_*ERROR flags.
3063  */
3064     static int
3065 read_charflags_section(fd)
3066     FILE	*fd;
3067 {
3068     char_u	*flags;
3069     char_u	*fol;
3070     int		flagslen, follen;
3071 
3072     /* <charflagslen> <charflags> */
3073     flags = read_cnt_string(fd, 1, &flagslen);
3074     if (flagslen < 0)
3075 	return flagslen;
3076 
3077     /* <folcharslen> <folchars> */
3078     fol = read_cnt_string(fd, 2, &follen);
3079     if (follen < 0)
3080     {
3081 	vim_free(flags);
3082 	return follen;
3083     }
3084 
3085     /* Set the word-char flags and fill SPELL_ISUPPER() table. */
3086     if (flags != NULL && fol != NULL)
3087 	set_spell_charflags(flags, flagslen, fol);
3088 
3089     vim_free(flags);
3090     vim_free(fol);
3091 
3092     /* When <charflagslen> is zero then <fcharlen> must also be zero. */
3093     if ((flags == NULL) != (fol == NULL))
3094 	return SP_FORMERROR;
3095     return 0;
3096 }
3097 
3098 /*
3099  * Read SN_PREFCOND section.
3100  * Return SP_*ERROR flags.
3101  */
3102     static int
3103 read_prefcond_section(fd, lp)
3104     FILE	*fd;
3105     slang_T	*lp;
3106 {
3107     int		cnt;
3108     int		i;
3109     int		n;
3110     char_u	*p;
3111     char_u	buf[MAXWLEN + 1];
3112 
3113     /* <prefcondcnt> <prefcond> ... */
3114     cnt = get2c(fd);					/* <prefcondcnt> */
3115     if (cnt <= 0)
3116 	return SP_FORMERROR;
3117 
3118     lp->sl_prefprog = (regprog_T **)alloc_clear(
3119 					 (unsigned)sizeof(regprog_T *) * cnt);
3120     if (lp->sl_prefprog == NULL)
3121 	return SP_OTHERERROR;
3122     lp->sl_prefixcnt = cnt;
3123 
3124     for (i = 0; i < cnt; ++i)
3125     {
3126 	/* <prefcond> : <condlen> <condstr> */
3127 	n = getc(fd);					/* <condlen> */
3128 	if (n < 0 || n >= MAXWLEN)
3129 	    return SP_FORMERROR;
3130 
3131 	/* When <condlen> is zero we have an empty condition.  Otherwise
3132 	 * compile the regexp program used to check for the condition. */
3133 	if (n > 0)
3134 	{
3135 	    buf[0] = '^';	    /* always match at one position only */
3136 	    p = buf + 1;
3137 	    while (n-- > 0)
3138 		*p++ = getc(fd);			/* <condstr> */
3139 	    *p = NUL;
3140 	    lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING);
3141 	}
3142     }
3143     return 0;
3144 }
3145 
3146 /*
3147  * Read REP or REPSAL items section from "fd": <repcount> <rep> ...
3148  * Return SP_*ERROR flags.
3149  */
3150     static int
3151 read_rep_section(fd, gap, first)
3152     FILE	*fd;
3153     garray_T	*gap;
3154     short	*first;
3155 {
3156     int		cnt;
3157     fromto_T	*ftp;
3158     int		i;
3159 
3160     cnt = get2c(fd);					/* <repcount> */
3161     if (cnt < 0)
3162 	return SP_TRUNCERROR;
3163 
3164     if (ga_grow(gap, cnt) == FAIL)
3165 	return SP_OTHERERROR;
3166 
3167     /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
3168     for (; gap->ga_len < cnt; ++gap->ga_len)
3169     {
3170 	ftp = &((fromto_T *)gap->ga_data)[gap->ga_len];
3171 	ftp->ft_from = read_cnt_string(fd, 1, &i);
3172 	if (i < 0)
3173 	    return i;
3174 	if (i == 0)
3175 	    return SP_FORMERROR;
3176 	ftp->ft_to = read_cnt_string(fd, 1, &i);
3177 	if (i <= 0)
3178 	{
3179 	    vim_free(ftp->ft_from);
3180 	    if (i < 0)
3181 		return i;
3182 	    return SP_FORMERROR;
3183 	}
3184     }
3185 
3186     /* Fill the first-index table. */
3187     for (i = 0; i < 256; ++i)
3188 	first[i] = -1;
3189     for (i = 0; i < gap->ga_len; ++i)
3190     {
3191 	ftp = &((fromto_T *)gap->ga_data)[i];
3192 	if (first[*ftp->ft_from] == -1)
3193 	    first[*ftp->ft_from] = i;
3194     }
3195     return 0;
3196 }
3197 
3198 /*
3199  * Read SN_SAL section: <salflags> <salcount> <sal> ...
3200  * Return SP_*ERROR flags.
3201  */
3202     static int
3203 read_sal_section(fd, slang)
3204     FILE	*fd;
3205     slang_T	*slang;
3206 {
3207     int		i;
3208     int		cnt;
3209     garray_T	*gap;
3210     salitem_T	*smp;
3211     int		ccnt;
3212     char_u	*p;
3213     int		c = NUL;
3214 
3215     slang->sl_sofo = FALSE;
3216 
3217     i = getc(fd);				/* <salflags> */
3218     if (i & SAL_F0LLOWUP)
3219 	slang->sl_followup = TRUE;
3220     if (i & SAL_COLLAPSE)
3221 	slang->sl_collapse = TRUE;
3222     if (i & SAL_REM_ACCENTS)
3223 	slang->sl_rem_accents = TRUE;
3224 
3225     cnt = get2c(fd);				/* <salcount> */
3226     if (cnt < 0)
3227 	return SP_TRUNCERROR;
3228 
3229     gap = &slang->sl_sal;
3230     ga_init2(gap, sizeof(salitem_T), 10);
3231     if (ga_grow(gap, cnt + 1) == FAIL)
3232 	return SP_OTHERERROR;
3233 
3234     /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
3235     for (; gap->ga_len < cnt; ++gap->ga_len)
3236     {
3237 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
3238 	ccnt = getc(fd);			/* <salfromlen> */
3239 	if (ccnt < 0)
3240 	    return SP_TRUNCERROR;
3241 	if ((p = alloc(ccnt + 2)) == NULL)
3242 	    return SP_OTHERERROR;
3243 	smp->sm_lead = p;
3244 
3245 	/* Read up to the first special char into sm_lead. */
3246 	for (i = 0; i < ccnt; ++i)
3247 	{
3248 	    c = getc(fd);			/* <salfrom> */
3249 	    if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL)
3250 		break;
3251 	    *p++ = c;
3252 	}
3253 	smp->sm_leadlen = (int)(p - smp->sm_lead);
3254 	*p++ = NUL;
3255 
3256 	/* Put (abc) chars in sm_oneof, if any. */
3257 	if (c == '(')
3258 	{
3259 	    smp->sm_oneof = p;
3260 	    for (++i; i < ccnt; ++i)
3261 	    {
3262 		c = getc(fd);			/* <salfrom> */
3263 		if (c == ')')
3264 		    break;
3265 		*p++ = c;
3266 	    }
3267 	    *p++ = NUL;
3268 	    if (++i < ccnt)
3269 		c = getc(fd);
3270 	}
3271 	else
3272 	    smp->sm_oneof = NULL;
3273 
3274 	/* Any following chars go in sm_rules. */
3275 	smp->sm_rules = p;
3276 	if (i < ccnt)
3277 	    /* store the char we got while checking for end of sm_lead */
3278 	    *p++ = c;
3279 	for (++i; i < ccnt; ++i)
3280 	    *p++ = getc(fd);			/* <salfrom> */
3281 	*p++ = NUL;
3282 
3283 	/* <saltolen> <salto> */
3284 	smp->sm_to = read_cnt_string(fd, 1, &ccnt);
3285 	if (ccnt < 0)
3286 	{
3287 	    vim_free(smp->sm_lead);
3288 	    return ccnt;
3289 	}
3290 
3291 #ifdef FEAT_MBYTE
3292 	if (has_mbyte)
3293 	{
3294 	    /* convert the multi-byte strings to wide char strings */
3295 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
3296 	    smp->sm_leadlen = mb_charlen(smp->sm_lead);
3297 	    if (smp->sm_oneof == NULL)
3298 		smp->sm_oneof_w = NULL;
3299 	    else
3300 		smp->sm_oneof_w = mb_str2wide(smp->sm_oneof);
3301 	    if (smp->sm_to == NULL)
3302 		smp->sm_to_w = NULL;
3303 	    else
3304 		smp->sm_to_w = mb_str2wide(smp->sm_to);
3305 	    if (smp->sm_lead_w == NULL
3306 		    || (smp->sm_oneof_w == NULL && smp->sm_oneof != NULL)
3307 		    || (smp->sm_to_w == NULL && smp->sm_to != NULL))
3308 	    {
3309 		vim_free(smp->sm_lead);
3310 		vim_free(smp->sm_to);
3311 		vim_free(smp->sm_lead_w);
3312 		vim_free(smp->sm_oneof_w);
3313 		vim_free(smp->sm_to_w);
3314 		return SP_OTHERERROR;
3315 	    }
3316 	}
3317 #endif
3318     }
3319 
3320     if (gap->ga_len > 0)
3321     {
3322 	/* Add one extra entry to mark the end with an empty sm_lead.  Avoids
3323 	 * that we need to check the index every time. */
3324 	smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
3325 	if ((p = alloc(1)) == NULL)
3326 	    return SP_OTHERERROR;
3327 	p[0] = NUL;
3328 	smp->sm_lead = p;
3329 	smp->sm_leadlen = 0;
3330 	smp->sm_oneof = NULL;
3331 	smp->sm_rules = p;
3332 	smp->sm_to = NULL;
3333 #ifdef FEAT_MBYTE
3334 	if (has_mbyte)
3335 	{
3336 	    smp->sm_lead_w = mb_str2wide(smp->sm_lead);
3337 	    smp->sm_leadlen = 0;
3338 	    smp->sm_oneof_w = NULL;
3339 	    smp->sm_to_w = NULL;
3340 	}
3341 #endif
3342 	++gap->ga_len;
3343     }
3344 
3345     /* Fill the first-index table. */
3346     set_sal_first(slang);
3347 
3348     return 0;
3349 }
3350 
3351 /*
3352  * Read SN_WORDS: <word> ...
3353  * Return SP_*ERROR flags.
3354  */
3355     static int
3356 read_words_section(fd, lp, len)
3357     FILE	*fd;
3358     slang_T	*lp;
3359     int		len;
3360 {
3361     int		done = 0;
3362     int		i;
3363     int		c;
3364     char_u	word[MAXWLEN];
3365 
3366     while (done < len)
3367     {
3368 	/* Read one word at a time. */
3369 	for (i = 0; ; ++i)
3370 	{
3371 	    c = getc(fd);
3372 	    if (c == EOF)
3373 		return SP_TRUNCERROR;
3374 	    word[i] = c;
3375 	    if (word[i] == NUL)
3376 		break;
3377 	    if (i == MAXWLEN - 1)
3378 		return SP_FORMERROR;
3379 	}
3380 
3381 	/* Init the count to 10. */
3382 	count_common_word(lp, word, -1, 10);
3383 	done += i + 1;
3384     }
3385     return 0;
3386 }
3387 
3388 /*
3389  * Add a word to the hashtable of common words.
3390  * If it's already there then the counter is increased.
3391  */
3392     static void
3393 count_common_word(lp, word, len, count)
3394     slang_T	*lp;
3395     char_u	*word;
3396     int		len;	    /* word length, -1 for upto NUL */
3397     int		count;	    /* 1 to count once, 10 to init */
3398 {
3399     hash_T	hash;
3400     hashitem_T	*hi;
3401     wordcount_T	*wc;
3402     char_u	buf[MAXWLEN];
3403     char_u	*p;
3404 
3405     if (len == -1)
3406 	p = word;
3407     else
3408     {
3409 	vim_strncpy(buf, word, len);
3410 	p = buf;
3411     }
3412 
3413     hash = hash_hash(p);
3414     hi = hash_lookup(&lp->sl_wordcount, p, hash);
3415     if (HASHITEM_EMPTY(hi))
3416     {
3417 	wc = (wordcount_T *)alloc((unsigned)(sizeof(wordcount_T) + STRLEN(p)));
3418 	if (wc == NULL)
3419 	    return;
3420 	STRCPY(wc->wc_word, p);
3421 	wc->wc_count = count;
3422 	hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
3423     }
3424     else
3425     {
3426 	wc = HI2WC(hi);
3427 	if ((wc->wc_count += count) < (unsigned)count)	/* check for overflow */
3428 	    wc->wc_count = MAXWORDCOUNT;
3429     }
3430 }
3431 
3432 /*
3433  * Adjust the score of common words.
3434  */
3435     static int
3436 score_wordcount_adj(slang, score, word, split)
3437     slang_T	*slang;
3438     int		score;
3439     char_u	*word;
3440     int		split;	    /* word was split, less bonus */
3441 {
3442     hashitem_T	*hi;
3443     wordcount_T	*wc;
3444     int		bonus;
3445     int		newscore;
3446 
3447     hi = hash_find(&slang->sl_wordcount, word);
3448     if (!HASHITEM_EMPTY(hi))
3449     {
3450 	wc = HI2WC(hi);
3451 	if (wc->wc_count < SCORE_THRES2)
3452 	    bonus = SCORE_COMMON1;
3453 	else if (wc->wc_count < SCORE_THRES3)
3454 	    bonus = SCORE_COMMON2;
3455 	else
3456 	    bonus = SCORE_COMMON3;
3457 	if (split)
3458 	    newscore = score - bonus / 2;
3459 	else
3460 	    newscore = score - bonus;
3461 	if (newscore < 0)
3462 	    return 0;
3463 	return newscore;
3464     }
3465     return score;
3466 }
3467 
3468 /*
3469  * SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
3470  * Return SP_*ERROR flags.
3471  */
3472     static int
3473 read_sofo_section(fd, slang)
3474     FILE	*fd;
3475     slang_T	*slang;
3476 {
3477     int		cnt;
3478     char_u	*from, *to;
3479     int		res;
3480 
3481     slang->sl_sofo = TRUE;
3482 
3483     /* <sofofromlen> <sofofrom> */
3484     from = read_cnt_string(fd, 2, &cnt);
3485     if (cnt < 0)
3486 	return cnt;
3487 
3488     /* <sofotolen> <sofoto> */
3489     to = read_cnt_string(fd, 2, &cnt);
3490     if (cnt < 0)
3491     {
3492 	vim_free(from);
3493 	return cnt;
3494     }
3495 
3496     /* Store the info in slang->sl_sal and/or slang->sl_sal_first. */
3497     if (from != NULL && to != NULL)
3498 	res = set_sofo(slang, from, to);
3499     else if (from != NULL || to != NULL)
3500 	res = SP_FORMERROR;    /* only one of two strings is an error */
3501     else
3502 	res = 0;
3503 
3504     vim_free(from);
3505     vim_free(to);
3506     return res;
3507 }
3508 
3509 /*
3510  * Read the compound section from the .spl file:
3511  *	<compmax> <compminlen> <compsylmax> <compoptions> <compflags>
3512  * Returns SP_*ERROR flags.
3513  */
3514     static int
3515 read_compound(fd, slang, len)
3516     FILE	*fd;
3517     slang_T	*slang;
3518     int		len;
3519 {
3520     int		todo = len;
3521     int		c;
3522     int		atstart;
3523     char_u	*pat;
3524     char_u	*pp;
3525     char_u	*cp;
3526     char_u	*ap;
3527     char_u	*crp;
3528     int		cnt;
3529     garray_T	*gap;
3530 
3531     if (todo < 2)
3532 	return SP_FORMERROR;	/* need at least two bytes */
3533 
3534     --todo;
3535     c = getc(fd);					/* <compmax> */
3536     if (c < 2)
3537 	c = MAXWLEN;
3538     slang->sl_compmax = c;
3539 
3540     --todo;
3541     c = getc(fd);					/* <compminlen> */
3542     if (c < 1)
3543 	c = 0;
3544     slang->sl_compminlen = c;
3545 
3546     --todo;
3547     c = getc(fd);					/* <compsylmax> */
3548     if (c < 1)
3549 	c = MAXWLEN;
3550     slang->sl_compsylmax = c;
3551 
3552     c = getc(fd);					/* <compoptions> */
3553     if (c != 0)
3554 	ungetc(c, fd);	    /* be backwards compatible with Vim 7.0b */
3555     else
3556     {
3557 	--todo;
3558 	c = getc(fd);	    /* only use the lower byte for now */
3559 	--todo;
3560 	slang->sl_compoptions = c;
3561 
3562 	gap = &slang->sl_comppat;
3563 	c = get2c(fd);					/* <comppatcount> */
3564 	todo -= 2;
3565 	ga_init2(gap, sizeof(char_u *), c);
3566 	if (ga_grow(gap, c) == OK)
3567 	    while (--c >= 0)
3568 	    {
3569 		((char_u **)(gap->ga_data))[gap->ga_len++] =
3570 						 read_cnt_string(fd, 1, &cnt);
3571 					    /* <comppatlen> <comppattext> */
3572 		if (cnt < 0)
3573 		    return cnt;
3574 		todo -= cnt + 1;
3575 	    }
3576     }
3577     if (todo < 0)
3578 	return SP_FORMERROR;
3579 
3580     /* Turn the COMPOUNDRULE items into a regexp pattern:
3581      * "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$".
3582      * Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes.
3583      * Conversion to utf-8 may double the size. */
3584     c = todo * 2 + 7;
3585 #ifdef FEAT_MBYTE
3586     if (enc_utf8)
3587 	c += todo * 2;
3588 #endif
3589     pat = alloc((unsigned)c);
3590     if (pat == NULL)
3591 	return SP_OTHERERROR;
3592 
3593     /* We also need a list of all flags that can appear at the start and one
3594      * for all flags. */
3595     cp = alloc(todo + 1);
3596     if (cp == NULL)
3597     {
3598 	vim_free(pat);
3599 	return SP_OTHERERROR;
3600     }
3601     slang->sl_compstartflags = cp;
3602     *cp = NUL;
3603 
3604     ap = alloc(todo + 1);
3605     if (ap == NULL)
3606     {
3607 	vim_free(pat);
3608 	return SP_OTHERERROR;
3609     }
3610     slang->sl_compallflags = ap;
3611     *ap = NUL;
3612 
3613     /* And a list of all patterns in their original form, for checking whether
3614      * compounding may work in match_compoundrule().  This is freed when we
3615      * encounter a wildcard, the check doesn't work then. */
3616     crp = alloc(todo + 1);
3617     slang->sl_comprules = crp;
3618 
3619     pp = pat;
3620     *pp++ = '^';
3621     *pp++ = '\\';
3622     *pp++ = '(';
3623 
3624     atstart = 1;
3625     while (todo-- > 0)
3626     {
3627 	c = getc(fd);					/* <compflags> */
3628 	if (c == EOF)
3629 	{
3630 	    vim_free(pat);
3631 	    return SP_TRUNCERROR;
3632 	}
3633 
3634 	/* Add all flags to "sl_compallflags". */
3635 	if (vim_strchr((char_u *)"?*+[]/", c) == NULL
3636 		&& !byte_in_str(slang->sl_compallflags, c))
3637 	{
3638 	    *ap++ = c;
3639 	    *ap = NUL;
3640 	}
3641 
3642 	if (atstart != 0)
3643 	{
3644 	    /* At start of item: copy flags to "sl_compstartflags".  For a
3645 	     * [abc] item set "atstart" to 2 and copy up to the ']'. */
3646 	    if (c == '[')
3647 		atstart = 2;
3648 	    else if (c == ']')
3649 		atstart = 0;
3650 	    else
3651 	    {
3652 		if (!byte_in_str(slang->sl_compstartflags, c))
3653 		{
3654 		    *cp++ = c;
3655 		    *cp = NUL;
3656 		}
3657 		if (atstart == 1)
3658 		    atstart = 0;
3659 	    }
3660 	}
3661 
3662 	/* Copy flag to "sl_comprules", unless we run into a wildcard. */
3663 	if (crp != NULL)
3664 	{
3665 	    if (c == '?' || c == '+' || c == '*')
3666 	    {
3667 		vim_free(slang->sl_comprules);
3668 		slang->sl_comprules = NULL;
3669 		crp = NULL;
3670 	    }
3671 	    else
3672 		*crp++ = c;
3673 	}
3674 
3675 	if (c == '/')	    /* slash separates two items */
3676 	{
3677 	    *pp++ = '\\';
3678 	    *pp++ = '|';
3679 	    atstart = 1;
3680 	}
3681 	else		    /* normal char, "[abc]" and '*' are copied as-is */
3682 	{
3683 	    if (c == '?' || c == '+' || c == '~')
3684 		*pp++ = '\\';	    /* "a?" becomes "a\?", "a+" becomes "a\+" */
3685 #ifdef FEAT_MBYTE
3686 	    if (enc_utf8)
3687 		pp += mb_char2bytes(c, pp);
3688 	    else
3689 #endif
3690 		*pp++ = c;
3691 	}
3692     }
3693 
3694     *pp++ = '\\';
3695     *pp++ = ')';
3696     *pp++ = '$';
3697     *pp = NUL;
3698 
3699     if (crp != NULL)
3700 	*crp = NUL;
3701 
3702     slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
3703     vim_free(pat);
3704     if (slang->sl_compprog == NULL)
3705 	return SP_FORMERROR;
3706 
3707     return 0;
3708 }
3709 
3710 /*
3711  * Return TRUE if byte "n" appears in "str".
3712  * Like strchr() but independent of locale.
3713  */
3714     static int
3715 byte_in_str(str, n)
3716     char_u	*str;
3717     int		n;
3718 {
3719     char_u	*p;
3720 
3721     for (p = str; *p != NUL; ++p)
3722 	if (*p == n)
3723 	    return TRUE;
3724     return FALSE;
3725 }
3726 
3727 #define SY_MAXLEN   30
3728 typedef struct syl_item_S
3729 {
3730     char_u	sy_chars[SY_MAXLEN];	    /* the sequence of chars */
3731     int		sy_len;
3732 } syl_item_T;
3733 
3734 /*
3735  * Truncate "slang->sl_syllable" at the first slash and put the following items
3736  * in "slang->sl_syl_items".
3737  */
3738     static int
3739 init_syl_tab(slang)
3740     slang_T	*slang;
3741 {
3742     char_u	*p;
3743     char_u	*s;
3744     int		l;
3745     syl_item_T	*syl;
3746 
3747     ga_init2(&slang->sl_syl_items, sizeof(syl_item_T), 4);
3748     p = vim_strchr(slang->sl_syllable, '/');
3749     while (p != NULL)
3750     {
3751 	*p++ = NUL;
3752 	if (*p == NUL)	    /* trailing slash */
3753 	    break;
3754 	s = p;
3755 	p = vim_strchr(p, '/');
3756 	if (p == NULL)
3757 	    l = (int)STRLEN(s);
3758 	else
3759 	    l = (int)(p - s);
3760 	if (l >= SY_MAXLEN)
3761 	    return SP_FORMERROR;
3762 	if (ga_grow(&slang->sl_syl_items, 1) == FAIL)
3763 	    return SP_OTHERERROR;
3764 	syl = ((syl_item_T *)slang->sl_syl_items.ga_data)
3765 					       + slang->sl_syl_items.ga_len++;
3766 	vim_strncpy(syl->sy_chars, s, l);
3767 	syl->sy_len = l;
3768     }
3769     return OK;
3770 }
3771 
3772 /*
3773  * Count the number of syllables in "word".
3774  * When "word" contains spaces the syllables after the last space are counted.
3775  * Returns zero if syllables are not defines.
3776  */
3777     static int
3778 count_syllables(slang, word)
3779     slang_T	*slang;
3780     char_u	*word;
3781 {
3782     int		cnt = 0;
3783     int		skip = FALSE;
3784     char_u	*p;
3785     int		len;
3786     int		i;
3787     syl_item_T	*syl;
3788     int		c;
3789 
3790     if (slang->sl_syllable == NULL)
3791 	return 0;
3792 
3793     for (p = word; *p != NUL; p += len)
3794     {
3795 	/* When running into a space reset counter. */
3796 	if (*p == ' ')
3797 	{
3798 	    len = 1;
3799 	    cnt = 0;
3800 	    continue;
3801 	}
3802 
3803 	/* Find longest match of syllable items. */
3804 	len = 0;
3805 	for (i = 0; i < slang->sl_syl_items.ga_len; ++i)
3806 	{
3807 	    syl = ((syl_item_T *)slang->sl_syl_items.ga_data) + i;
3808 	    if (syl->sy_len > len
3809 			       && STRNCMP(p, syl->sy_chars, syl->sy_len) == 0)
3810 		len = syl->sy_len;
3811 	}
3812 	if (len != 0)	/* found a match, count syllable  */
3813 	{
3814 	    ++cnt;
3815 	    skip = FALSE;
3816 	}
3817 	else
3818 	{
3819 	    /* No recognized syllable item, at least a syllable char then? */
3820 #ifdef FEAT_MBYTE
3821 	    c = mb_ptr2char(p);
3822 	    len = (*mb_ptr2len)(p);
3823 #else
3824 	    c = *p;
3825 	    len = 1;
3826 #endif
3827 	    if (vim_strchr(slang->sl_syllable, c) == NULL)
3828 		skip = FALSE;	    /* No, search for next syllable */
3829 	    else if (!skip)
3830 	    {
3831 		++cnt;		    /* Yes, count it */
3832 		skip = TRUE;	    /* don't count following syllable chars */
3833 	    }
3834 	}
3835     }
3836     return cnt;
3837 }
3838 
3839 /*
3840  * Set the SOFOFROM and SOFOTO items in language "lp".
3841  * Returns SP_*ERROR flags when there is something wrong.
3842  */
3843     static int
3844 set_sofo(lp, from, to)
3845     slang_T	*lp;
3846     char_u	*from;
3847     char_u	*to;
3848 {
3849     int		i;
3850 
3851 #ifdef FEAT_MBYTE
3852     garray_T	*gap;
3853     char_u	*s;
3854     char_u	*p;
3855     int		c;
3856     int		*inp;
3857 
3858     if (has_mbyte)
3859     {
3860 	/* Use "sl_sal" as an array with 256 pointers to a list of wide
3861 	 * characters.  The index is the low byte of the character.
3862 	 * The list contains from-to pairs with a terminating NUL.
3863 	 * sl_sal_first[] is used for latin1 "from" characters. */
3864 	gap = &lp->sl_sal;
3865 	ga_init2(gap, sizeof(int *), 1);
3866 	if (ga_grow(gap, 256) == FAIL)
3867 	    return SP_OTHERERROR;
3868 	vim_memset(gap->ga_data, 0, sizeof(int *) * 256);
3869 	gap->ga_len = 256;
3870 
3871 	/* First count the number of items for each list.  Temporarily use
3872 	 * sl_sal_first[] for this. */
3873 	for (p = from, s = to; *p != NUL && *s != NUL; )
3874 	{
3875 	    c = mb_cptr2char_adv(&p);
3876 	    mb_cptr_adv(s);
3877 	    if (c >= 256)
3878 		++lp->sl_sal_first[c & 0xff];
3879 	}
3880 	if (*p != NUL || *s != NUL)	    /* lengths differ */
3881 	    return SP_FORMERROR;
3882 
3883 	/* Allocate the lists. */
3884 	for (i = 0; i < 256; ++i)
3885 	    if (lp->sl_sal_first[i] > 0)
3886 	    {
3887 		p = alloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1));
3888 		if (p == NULL)
3889 		    return SP_OTHERERROR;
3890 		((int **)gap->ga_data)[i] = (int *)p;
3891 		*(int *)p = 0;
3892 	    }
3893 
3894 	/* Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal
3895 	 * list. */
3896 	vim_memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
3897 	for (p = from, s = to; *p != NUL && *s != NUL; )
3898 	{
3899 	    c = mb_cptr2char_adv(&p);
3900 	    i = mb_cptr2char_adv(&s);
3901 	    if (c >= 256)
3902 	    {
3903 		/* Append the from-to chars at the end of the list with
3904 		 * the low byte. */
3905 		inp = ((int **)gap->ga_data)[c & 0xff];
3906 		while (*inp != 0)
3907 		    ++inp;
3908 		*inp++ = c;		/* from char */
3909 		*inp++ = i;		/* to char */
3910 		*inp++ = NUL;		/* NUL at the end */
3911 	    }
3912 	    else
3913 		/* mapping byte to char is done in sl_sal_first[] */
3914 		lp->sl_sal_first[c] = i;
3915 	}
3916     }
3917     else
3918 #endif
3919     {
3920 	/* mapping bytes to bytes is done in sl_sal_first[] */
3921 	if (STRLEN(from) != STRLEN(to))
3922 	    return SP_FORMERROR;
3923 
3924 	for (i = 0; to[i] != NUL; ++i)
3925 	    lp->sl_sal_first[from[i]] = to[i];
3926 	lp->sl_sal.ga_len = 1;		/* indicates we have soundfolding */
3927     }
3928 
3929     return 0;
3930 }
3931 
3932 /*
3933  * Fill the first-index table for "lp".
3934  */
3935     static void
3936 set_sal_first(lp)
3937     slang_T	*lp;
3938 {
3939     salfirst_T	*sfirst;
3940     int		i;
3941     salitem_T	*smp;
3942     int		c;
3943     garray_T	*gap = &lp->sl_sal;
3944 
3945     sfirst = lp->sl_sal_first;
3946     for (i = 0; i < 256; ++i)
3947 	sfirst[i] = -1;
3948     smp = (salitem_T *)gap->ga_data;
3949     for (i = 0; i < gap->ga_len; ++i)
3950     {
3951 #ifdef FEAT_MBYTE
3952 	if (has_mbyte)
3953 	    /* Use the lowest byte of the first character.  For latin1 it's
3954 	     * the character, for other encodings it should differ for most
3955 	     * characters. */
3956 	    c = *smp[i].sm_lead_w & 0xff;
3957 	else
3958 #endif
3959 	    c = *smp[i].sm_lead;
3960 	if (sfirst[c] == -1)
3961 	{
3962 	    sfirst[c] = i;
3963 #ifdef FEAT_MBYTE
3964 	    if (has_mbyte)
3965 	    {
3966 		int		n;
3967 
3968 		/* Make sure all entries with this byte are following each
3969 		 * other.  Move the ones that are in the wrong position.  Do
3970 		 * keep the same ordering! */
3971 		while (i + 1 < gap->ga_len
3972 				       && (*smp[i + 1].sm_lead_w & 0xff) == c)
3973 		    /* Skip over entry with same index byte. */
3974 		    ++i;
3975 
3976 		for (n = 1; i + n < gap->ga_len; ++n)
3977 		    if ((*smp[i + n].sm_lead_w & 0xff) == c)
3978 		    {
3979 			salitem_T  tsal;
3980 
3981 			/* Move entry with same index byte after the entries
3982 			 * we already found. */
3983 			++i;
3984 			--n;
3985 			tsal = smp[i + n];
3986 			mch_memmove(smp + i + 1, smp + i,
3987 						       sizeof(salitem_T) * n);
3988 			smp[i] = tsal;
3989 		    }
3990 	    }
3991 #endif
3992 	}
3993     }
3994 }
3995 
3996 #ifdef FEAT_MBYTE
3997 /*
3998  * Turn a multi-byte string into a wide character string.
3999  * Return it in allocated memory (NULL for out-of-memory)
4000  */
4001     static int *
4002 mb_str2wide(s)
4003     char_u	*s;
4004 {
4005     int		*res;
4006     char_u	*p;
4007     int		i = 0;
4008 
4009     res = (int *)alloc(sizeof(int) * (mb_charlen(s) + 1));
4010     if (res != NULL)
4011     {
4012 	for (p = s; *p != NUL; )
4013 	    res[i++] = mb_ptr2char_adv(&p);
4014 	res[i] = NUL;
4015     }
4016     return res;
4017 }
4018 #endif
4019 
4020 /*
4021  * Read a tree from the .spl or .sug file.
4022  * Allocates the memory and stores pointers in "bytsp" and "idxsp".
4023  * This is skipped when the tree has zero length.
4024  * Returns zero when OK, SP_ value for an error.
4025  */
4026     static int
4027 spell_read_tree(fd, bytsp, idxsp, prefixtree, prefixcnt)
4028     FILE	*fd;
4029     char_u	**bytsp;
4030     idx_T	**idxsp;
4031     int		prefixtree;	/* TRUE for the prefix tree */
4032     int		prefixcnt;	/* when "prefixtree" is TRUE: prefix count */
4033 {
4034     int		len;
4035     int		idx;
4036     char_u	*bp;
4037     idx_T	*ip;
4038 
4039     /* The tree size was computed when writing the file, so that we can
4040      * allocate it as one long block. <nodecount> */
4041     len = get4c(fd);
4042     if (len < 0)
4043 	return SP_TRUNCERROR;
4044     if (len > 0)
4045     {
4046 	/* Allocate the byte array. */
4047 	bp = lalloc((long_u)len, TRUE);
4048 	if (bp == NULL)
4049 	    return SP_OTHERERROR;
4050 	*bytsp = bp;
4051 
4052 	/* Allocate the index array. */
4053 	ip = (idx_T *)lalloc_clear((long_u)(len * sizeof(int)), TRUE);
4054 	if (ip == NULL)
4055 	    return SP_OTHERERROR;
4056 	*idxsp = ip;
4057 
4058 	/* Recursively read the tree and store it in the array. */
4059 	idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt);
4060 	if (idx < 0)
4061 	    return idx;
4062     }
4063     return 0;
4064 }
4065 
4066 /*
4067  * Read one row of siblings from the spell file and store it in the byte array
4068  * "byts" and index array "idxs".  Recursively read the children.
4069  *
4070  * NOTE: The code here must match put_node()!
4071  *
4072  * Returns the index (>= 0) following the siblings.
4073  * Returns SP_TRUNCERROR if the file is shorter than expected.
4074  * Returns SP_FORMERROR if there is a format error.
4075  */
4076     static idx_T
4077 read_tree_node(fd, byts, idxs, maxidx, startidx, prefixtree, maxprefcondnr)
4078     FILE	*fd;
4079     char_u	*byts;
4080     idx_T	*idxs;
4081     int		maxidx;		    /* size of arrays */
4082     idx_T	startidx;	    /* current index in "byts" and "idxs" */
4083     int		prefixtree;	    /* TRUE for reading PREFIXTREE */
4084     int		maxprefcondnr;	    /* maximum for <prefcondnr> */
4085 {
4086     int		len;
4087     int		i;
4088     int		n;
4089     idx_T	idx = startidx;
4090     int		c;
4091     int		c2;
4092 #define SHARED_MASK	0x8000000
4093 
4094     len = getc(fd);					/* <siblingcount> */
4095     if (len <= 0)
4096 	return SP_TRUNCERROR;
4097 
4098     if (startidx + len >= maxidx)
4099 	return SP_FORMERROR;
4100     byts[idx++] = len;
4101 
4102     /* Read the byte values, flag/region bytes and shared indexes. */
4103     for (i = 1; i <= len; ++i)
4104     {
4105 	c = getc(fd);					/* <byte> */
4106 	if (c < 0)
4107 	    return SP_TRUNCERROR;
4108 	if (c <= BY_SPECIAL)
4109 	{
4110 	    if (c == BY_NOFLAGS && !prefixtree)
4111 	    {
4112 		/* No flags, all regions. */
4113 		idxs[idx] = 0;
4114 		c = 0;
4115 	    }
4116 	    else if (c != BY_INDEX)
4117 	    {
4118 		if (prefixtree)
4119 		{
4120 		    /* Read the optional pflags byte, the prefix ID and the
4121 		     * condition nr.  In idxs[] store the prefix ID in the low
4122 		     * byte, the condition index shifted up 8 bits, the flags
4123 		     * shifted up 24 bits. */
4124 		    if (c == BY_FLAGS)
4125 			c = getc(fd) << 24;		/* <pflags> */
4126 		    else
4127 			c = 0;
4128 
4129 		    c |= getc(fd);			/* <affixID> */
4130 
4131 		    n = get2c(fd);			/* <prefcondnr> */
4132 		    if (n >= maxprefcondnr)
4133 			return SP_FORMERROR;
4134 		    c |= (n << 8);
4135 		}
4136 		else /* c must be BY_FLAGS or BY_FLAGS2 */
4137 		{
4138 		    /* Read flags and optional region and prefix ID.  In
4139 		     * idxs[] the flags go in the low two bytes, region above
4140 		     * that and prefix ID above the region. */
4141 		    c2 = c;
4142 		    c = getc(fd);			/* <flags> */
4143 		    if (c2 == BY_FLAGS2)
4144 			c = (getc(fd) << 8) + c;	/* <flags2> */
4145 		    if (c & WF_REGION)
4146 			c = (getc(fd) << 16) + c;	/* <region> */
4147 		    if (c & WF_AFX)
4148 			c = (getc(fd) << 24) + c;	/* <affixID> */
4149 		}
4150 
4151 		idxs[idx] = c;
4152 		c = 0;
4153 	    }
4154 	    else /* c == BY_INDEX */
4155 	    {
4156 							/* <nodeidx> */
4157 		n = get3c(fd);
4158 		if (n < 0 || n >= maxidx)
4159 		    return SP_FORMERROR;
4160 		idxs[idx] = n + SHARED_MASK;
4161 		c = getc(fd);				/* <xbyte> */
4162 	    }
4163 	}
4164 	byts[idx++] = c;
4165     }
4166 
4167     /* Recursively read the children for non-shared siblings.
4168      * Skip the end-of-word ones (zero byte value) and the shared ones (and
4169      * remove SHARED_MASK) */
4170     for (i = 1; i <= len; ++i)
4171 	if (byts[startidx + i] != 0)
4172 	{
4173 	    if (idxs[startidx + i] & SHARED_MASK)
4174 		idxs[startidx + i] &= ~SHARED_MASK;
4175 	    else
4176 	    {
4177 		idxs[startidx + i] = idx;
4178 		idx = read_tree_node(fd, byts, idxs, maxidx, idx,
4179 						     prefixtree, maxprefcondnr);
4180 		if (idx < 0)
4181 		    break;
4182 	    }
4183 	}
4184 
4185     return idx;
4186 }
4187 
4188 /*
4189  * Parse 'spelllang' and set w_s->b_langp accordingly.
4190  * Returns NULL if it's OK, an error message otherwise.
4191  */
4192     char_u *
4193 did_set_spelllang(wp)
4194     win_T	*wp;
4195 {
4196     garray_T	ga;
4197     char_u	*splp;
4198     char_u	*region;
4199     char_u	region_cp[3];
4200     int		filename;
4201     int		region_mask;
4202     slang_T	*slang;
4203     int		c;
4204     char_u	lang[MAXWLEN + 1];
4205     char_u	spf_name[MAXPATHL];
4206     int		len;
4207     char_u	*p;
4208     int		round;
4209     char_u	*spf;
4210     char_u	*use_region = NULL;
4211     int		dont_use_region = FALSE;
4212     int		nobreak = FALSE;
4213     int		i, j;
4214     langp_T	*lp, *lp2;
4215     static int	recursive = FALSE;
4216     char_u	*ret_msg = NULL;
4217     char_u	*spl_copy;
4218 
4219     /* We don't want to do this recursively.  May happen when a language is
4220      * not available and the SpellFileMissing autocommand opens a new buffer
4221      * in which 'spell' is set. */
4222     if (recursive)
4223 	return NULL;
4224     recursive = TRUE;
4225 
4226     ga_init2(&ga, sizeof(langp_T), 2);
4227     clear_midword(wp);
4228 
4229     /* Make a copy of 'spelllang', the SpellFileMissing autocommands may change
4230      * it under our fingers. */
4231     spl_copy = vim_strsave(wp->w_s->b_p_spl);
4232     if (spl_copy == NULL)
4233 	goto theend;
4234 
4235 #ifdef FEAT_MBYTE
4236     wp->w_s->b_cjk = 0;
4237 #endif
4238 
4239     /* Loop over comma separated language names. */
4240     for (splp = spl_copy; *splp != NUL; )
4241     {
4242 	/* Get one language name. */
4243 	copy_option_part(&splp, lang, MAXWLEN, ",");
4244 	region = NULL;
4245 	len = (int)STRLEN(lang);
4246 
4247 	if (STRCMP(lang, "cjk") == 0)
4248 	{
4249 #ifdef FEAT_MBYTE
4250 	    wp->w_s->b_cjk = 1;
4251 #endif
4252 	    continue;
4253 	}
4254 
4255 	/* If the name ends in ".spl" use it as the name of the spell file.
4256 	 * If there is a region name let "region" point to it and remove it
4257 	 * from the name. */
4258 	if (len > 4 && fnamecmp(lang + len - 4, ".spl") == 0)
4259 	{
4260 	    filename = TRUE;
4261 
4262 	    /* Locate a region and remove it from the file name. */
4263 	    p = vim_strchr(gettail(lang), '_');
4264 	    if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
4265 						      && !ASCII_ISALPHA(p[3]))
4266 	    {
4267 		vim_strncpy(region_cp, p + 1, 2);
4268 		mch_memmove(p, p + 3, len - (p - lang) - 2);
4269 		len -= 3;
4270 		region = region_cp;
4271 	    }
4272 	    else
4273 		dont_use_region = TRUE;
4274 
4275 	    /* Check if we loaded this language before. */
4276 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4277 		if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
4278 		    break;
4279 	}
4280 	else
4281 	{
4282 	    filename = FALSE;
4283 	    if (len > 3 && lang[len - 3] == '_')
4284 	    {
4285 		region = lang + len - 2;
4286 		len -= 3;
4287 		lang[len] = NUL;
4288 	    }
4289 	    else
4290 		dont_use_region = TRUE;
4291 
4292 	    /* Check if we loaded this language before. */
4293 	    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4294 		if (STRICMP(lang, slang->sl_name) == 0)
4295 		    break;
4296 	}
4297 
4298 	if (region != NULL)
4299 	{
4300 	    /* If the region differs from what was used before then don't
4301 	     * use it for 'spellfile'. */
4302 	    if (use_region != NULL && STRCMP(region, use_region) != 0)
4303 		dont_use_region = TRUE;
4304 	    use_region = region;
4305 	}
4306 
4307 	/* If not found try loading the language now. */
4308 	if (slang == NULL)
4309 	{
4310 	    if (filename)
4311 		(void)spell_load_file(lang, lang, NULL, FALSE);
4312 	    else
4313 	    {
4314 		spell_load_lang(lang);
4315 #ifdef FEAT_AUTOCMD
4316 		/* SpellFileMissing autocommands may do anything, including
4317 		 * destroying the buffer we are using... */
4318 		if (!buf_valid(wp->w_buffer))
4319 		{
4320 		    ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer";
4321 		    goto theend;
4322 		}
4323 #endif
4324 	    }
4325 	}
4326 
4327 	/*
4328 	 * Loop over the languages, there can be several files for "lang".
4329 	 */
4330 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4331 	    if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
4332 			 : STRICMP(lang, slang->sl_name) == 0)
4333 	    {
4334 		region_mask = REGION_ALL;
4335 		if (!filename && region != NULL)
4336 		{
4337 		    /* find region in sl_regions */
4338 		    c = find_region(slang->sl_regions, region);
4339 		    if (c == REGION_ALL)
4340 		    {
4341 			if (slang->sl_add)
4342 			{
4343 			    if (*slang->sl_regions != NUL)
4344 				/* This addition file is for other regions. */
4345 				region_mask = 0;
4346 			}
4347 			else
4348 			    /* This is probably an error.  Give a warning and
4349 			     * accept the words anyway. */
4350 			    smsg((char_u *)
4351 				    _("Warning: region %s not supported"),
4352 								      region);
4353 		    }
4354 		    else
4355 			region_mask = 1 << c;
4356 		}
4357 
4358 		if (region_mask != 0)
4359 		{
4360 		    if (ga_grow(&ga, 1) == FAIL)
4361 		    {
4362 			ga_clear(&ga);
4363 			ret_msg = e_outofmem;
4364 			goto theend;
4365 		    }
4366 		    LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
4367 		    LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
4368 		    ++ga.ga_len;
4369 		    use_midword(slang, wp);
4370 		    if (slang->sl_nobreak)
4371 			nobreak = TRUE;
4372 		}
4373 	    }
4374     }
4375 
4376     /* round 0: load int_wordlist, if possible.
4377      * round 1: load first name in 'spellfile'.
4378      * round 2: load second name in 'spellfile.
4379      * etc. */
4380     spf = curwin->w_s->b_p_spf;
4381     for (round = 0; round == 0 || *spf != NUL; ++round)
4382     {
4383 	if (round == 0)
4384 	{
4385 	    /* Internal wordlist, if there is one. */
4386 	    if (int_wordlist == NULL)
4387 		continue;
4388 	    int_wordlist_spl(spf_name);
4389 	}
4390 	else
4391 	{
4392 	    /* One entry in 'spellfile'. */
4393 	    copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
4394 	    STRCAT(spf_name, ".spl");
4395 
4396 	    /* If it was already found above then skip it. */
4397 	    for (c = 0; c < ga.ga_len; ++c)
4398 	    {
4399 		p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
4400 		if (p != NULL && fullpathcmp(spf_name, p, FALSE) == FPC_SAME)
4401 		    break;
4402 	    }
4403 	    if (c < ga.ga_len)
4404 		continue;
4405 	}
4406 
4407 	/* Check if it was loaded already. */
4408 	for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4409 	    if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
4410 		break;
4411 	if (slang == NULL)
4412 	{
4413 	    /* Not loaded, try loading it now.  The language name includes the
4414 	     * region name, the region is ignored otherwise.  for int_wordlist
4415 	     * use an arbitrary name. */
4416 	    if (round == 0)
4417 		STRCPY(lang, "internal wordlist");
4418 	    else
4419 	    {
4420 		vim_strncpy(lang, gettail(spf_name), MAXWLEN);
4421 		p = vim_strchr(lang, '.');
4422 		if (p != NULL)
4423 		    *p = NUL;	/* truncate at ".encoding.add" */
4424 	    }
4425 	    slang = spell_load_file(spf_name, lang, NULL, TRUE);
4426 
4427 	    /* If one of the languages has NOBREAK we assume the addition
4428 	     * files also have this. */
4429 	    if (slang != NULL && nobreak)
4430 		slang->sl_nobreak = TRUE;
4431 	}
4432 	if (slang != NULL && ga_grow(&ga, 1) == OK)
4433 	{
4434 	    region_mask = REGION_ALL;
4435 	    if (use_region != NULL && !dont_use_region)
4436 	    {
4437 		/* find region in sl_regions */
4438 		c = find_region(slang->sl_regions, use_region);
4439 		if (c != REGION_ALL)
4440 		    region_mask = 1 << c;
4441 		else if (*slang->sl_regions != NUL)
4442 		    /* This spell file is for other regions. */
4443 		    region_mask = 0;
4444 	    }
4445 
4446 	    if (region_mask != 0)
4447 	    {
4448 		LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
4449 		LANGP_ENTRY(ga, ga.ga_len)->lp_sallang = NULL;
4450 		LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL;
4451 		LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
4452 		++ga.ga_len;
4453 		use_midword(slang, wp);
4454 	    }
4455 	}
4456     }
4457 
4458     /* Everything is fine, store the new b_langp value. */
4459     ga_clear(&wp->w_s->b_langp);
4460     wp->w_s->b_langp = ga;
4461 
4462     /* For each language figure out what language to use for sound folding and
4463      * REP items.  If the language doesn't support it itself use another one
4464      * with the same name.  E.g. for "en-math" use "en". */
4465     for (i = 0; i < ga.ga_len; ++i)
4466     {
4467 	lp = LANGP_ENTRY(ga, i);
4468 
4469 	/* sound folding */
4470 	if (lp->lp_slang->sl_sal.ga_len > 0)
4471 	    /* language does sound folding itself */
4472 	    lp->lp_sallang = lp->lp_slang;
4473 	else
4474 	    /* find first similar language that does sound folding */
4475 	    for (j = 0; j < ga.ga_len; ++j)
4476 	    {
4477 		lp2 = LANGP_ENTRY(ga, j);
4478 		if (lp2->lp_slang->sl_sal.ga_len > 0
4479 			&& STRNCMP(lp->lp_slang->sl_name,
4480 					      lp2->lp_slang->sl_name, 2) == 0)
4481 		{
4482 		    lp->lp_sallang = lp2->lp_slang;
4483 		    break;
4484 		}
4485 	    }
4486 
4487 	/* REP items */
4488 	if (lp->lp_slang->sl_rep.ga_len > 0)
4489 	    /* language has REP items itself */
4490 	    lp->lp_replang = lp->lp_slang;
4491 	else
4492 	    /* find first similar language that has REP items */
4493 	    for (j = 0; j < ga.ga_len; ++j)
4494 	    {
4495 		lp2 = LANGP_ENTRY(ga, j);
4496 		if (lp2->lp_slang->sl_rep.ga_len > 0
4497 			&& STRNCMP(lp->lp_slang->sl_name,
4498 					      lp2->lp_slang->sl_name, 2) == 0)
4499 		{
4500 		    lp->lp_replang = lp2->lp_slang;
4501 		    break;
4502 		}
4503 	    }
4504     }
4505 
4506 theend:
4507     vim_free(spl_copy);
4508     recursive = FALSE;
4509     redraw_win_later(wp, NOT_VALID);
4510     return ret_msg;
4511 }
4512 
4513 /*
4514  * Clear the midword characters for buffer "buf".
4515  */
4516     static void
4517 clear_midword(wp)
4518     win_T	*wp;
4519 {
4520     vim_memset(wp->w_s->b_spell_ismw, 0, 256);
4521 #ifdef FEAT_MBYTE
4522     vim_free(wp->w_s->b_spell_ismw_mb);
4523     wp->w_s->b_spell_ismw_mb = NULL;
4524 #endif
4525 }
4526 
4527 /*
4528  * Use the "sl_midword" field of language "lp" for buffer "buf".
4529  * They add up to any currently used midword characters.
4530  */
4531     static void
4532 use_midword(lp, wp)
4533     slang_T	*lp;
4534     win_T	*wp;
4535 {
4536     char_u	*p;
4537 
4538     if (lp->sl_midword == NULL)	    /* there aren't any */
4539 	return;
4540 
4541     for (p = lp->sl_midword; *p != NUL; )
4542 #ifdef FEAT_MBYTE
4543 	if (has_mbyte)
4544 	{
4545 	    int	    c, l, n;
4546 	    char_u  *bp;
4547 
4548 	    c = mb_ptr2char(p);
4549 	    l = (*mb_ptr2len)(p);
4550 	    if (c < 256 && l <= 2)
4551 		wp->w_s->b_spell_ismw[c] = TRUE;
4552 	    else if (wp->w_s->b_spell_ismw_mb == NULL)
4553 		/* First multi-byte char in "b_spell_ismw_mb". */
4554 		wp->w_s->b_spell_ismw_mb = vim_strnsave(p, l);
4555 	    else
4556 	    {
4557 		/* Append multi-byte chars to "b_spell_ismw_mb". */
4558 		n = (int)STRLEN(wp->w_s->b_spell_ismw_mb);
4559 		bp = vim_strnsave(wp->w_s->b_spell_ismw_mb, n + l);
4560 		if (bp != NULL)
4561 		{
4562 		    vim_free(wp->w_s->b_spell_ismw_mb);
4563 		    wp->w_s->b_spell_ismw_mb = bp;
4564 		    vim_strncpy(bp + n, p, l);
4565 		}
4566 	    }
4567 	    p += l;
4568 	}
4569 	else
4570 #endif
4571 	    wp->w_s->b_spell_ismw[*p++] = TRUE;
4572 }
4573 
4574 /*
4575  * Find the region "region[2]" in "rp" (points to "sl_regions").
4576  * Each region is simply stored as the two characters of it's name.
4577  * Returns the index if found (first is 0), REGION_ALL if not found.
4578  */
4579     static int
4580 find_region(rp, region)
4581     char_u	*rp;
4582     char_u	*region;
4583 {
4584     int		i;
4585 
4586     for (i = 0; ; i += 2)
4587     {
4588 	if (rp[i] == NUL)
4589 	    return REGION_ALL;
4590 	if (rp[i] == region[0] && rp[i + 1] == region[1])
4591 	    break;
4592     }
4593     return i / 2;
4594 }
4595 
4596 /*
4597  * Return case type of word:
4598  * w word	0
4599  * Word		WF_ONECAP
4600  * W WORD	WF_ALLCAP
4601  * WoRd	wOrd	WF_KEEPCAP
4602  */
4603     static int
4604 captype(word, end)
4605     char_u	*word;
4606     char_u	*end;	    /* When NULL use up to NUL byte. */
4607 {
4608     char_u	*p;
4609     int		c;
4610     int		firstcap;
4611     int		allcap;
4612     int		past_second = FALSE;	/* past second word char */
4613 
4614     /* find first letter */
4615     for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p))
4616 	if (end == NULL ? *p == NUL : p >= end)
4617 	    return 0;	    /* only non-word characters, illegal word */
4618 #ifdef FEAT_MBYTE
4619     if (has_mbyte)
4620 	c = mb_ptr2char_adv(&p);
4621     else
4622 #endif
4623 	c = *p++;
4624     firstcap = allcap = SPELL_ISUPPER(c);
4625 
4626     /*
4627      * Need to check all letters to find a word with mixed upper/lower.
4628      * But a word with an upper char only at start is a ONECAP.
4629      */
4630     for ( ; end == NULL ? *p != NUL : p < end; mb_ptr_adv(p))
4631 	if (spell_iswordp_nmw(p, curwin))
4632 	{
4633 	    c = PTR2CHAR(p);
4634 	    if (!SPELL_ISUPPER(c))
4635 	    {
4636 		/* UUl -> KEEPCAP */
4637 		if (past_second && allcap)
4638 		    return WF_KEEPCAP;
4639 		allcap = FALSE;
4640 	    }
4641 	    else if (!allcap)
4642 		/* UlU -> KEEPCAP */
4643 		return WF_KEEPCAP;
4644 	    past_second = TRUE;
4645 	}
4646 
4647     if (allcap)
4648 	return WF_ALLCAP;
4649     if (firstcap)
4650 	return WF_ONECAP;
4651     return 0;
4652 }
4653 
4654 /*
4655  * Like captype() but for a KEEPCAP word add ONECAP if the word starts with a
4656  * capital.  So that make_case_word() can turn WOrd into Word.
4657  * Add ALLCAP for "WOrD".
4658  */
4659     static int
4660 badword_captype(word, end)
4661     char_u	*word;
4662     char_u	*end;
4663 {
4664     int		flags = captype(word, end);
4665     int		c;
4666     int		l, u;
4667     int		first;
4668     char_u	*p;
4669 
4670     if (flags & WF_KEEPCAP)
4671     {
4672 	/* Count the number of UPPER and lower case letters. */
4673 	l = u = 0;
4674 	first = FALSE;
4675 	for (p = word; p < end; mb_ptr_adv(p))
4676 	{
4677 	    c = PTR2CHAR(p);
4678 	    if (SPELL_ISUPPER(c))
4679 	    {
4680 		++u;
4681 		if (p == word)
4682 		    first = TRUE;
4683 	    }
4684 	    else
4685 		++l;
4686 	}
4687 
4688 	/* If there are more UPPER than lower case letters suggest an
4689 	 * ALLCAP word.  Otherwise, if the first letter is UPPER then
4690 	 * suggest ONECAP.  Exception: "ALl" most likely should be "All",
4691 	 * require three upper case letters. */
4692 	if (u > l && u > 2)
4693 	    flags |= WF_ALLCAP;
4694 	else if (first)
4695 	    flags |= WF_ONECAP;
4696 
4697 	if (u >= 2 && l >= 2)	/* maCARONI maCAroni */
4698 	    flags |= WF_MIXCAP;
4699     }
4700     return flags;
4701 }
4702 
4703 /*
4704  * Delete the internal wordlist and its .spl file.
4705  */
4706     void
4707 spell_delete_wordlist()
4708 {
4709     char_u	fname[MAXPATHL];
4710 
4711     if (int_wordlist != NULL)
4712     {
4713 	mch_remove(int_wordlist);
4714 	int_wordlist_spl(fname);
4715 	mch_remove(fname);
4716 	vim_free(int_wordlist);
4717 	int_wordlist = NULL;
4718     }
4719 }
4720 
4721 #if defined(FEAT_MBYTE) || defined(EXITFREE) || defined(PROTO)
4722 /*
4723  * Free all languages.
4724  */
4725     void
4726 spell_free_all()
4727 {
4728     slang_T	*slang;
4729     buf_T	*buf;
4730 
4731     /* Go through all buffers and handle 'spelllang'. <VN> */
4732     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4733 	ga_clear(&buf->b_s.b_langp);
4734 
4735     while (first_lang != NULL)
4736     {
4737 	slang = first_lang;
4738 	first_lang = slang->sl_next;
4739 	slang_free(slang);
4740     }
4741 
4742     spell_delete_wordlist();
4743 
4744     vim_free(repl_to);
4745     repl_to = NULL;
4746     vim_free(repl_from);
4747     repl_from = NULL;
4748 }
4749 #endif
4750 
4751 #if defined(FEAT_MBYTE) || defined(PROTO)
4752 /*
4753  * Clear all spelling tables and reload them.
4754  * Used after 'encoding' is set and when ":mkspell" was used.
4755  */
4756     void
4757 spell_reload()
4758 {
4759     win_T	*wp;
4760 
4761     /* Initialize the table for spell_iswordp(). */
4762     init_spell_chartab();
4763 
4764     /* Unload all allocated memory. */
4765     spell_free_all();
4766 
4767     /* Go through all buffers and handle 'spelllang'. */
4768     for (wp = firstwin; wp != NULL; wp = wp->w_next)
4769     {
4770 	/* Only load the wordlists when 'spelllang' is set and there is a
4771 	 * window for this buffer in which 'spell' is set. */
4772 	if (*wp->w_s->b_p_spl != NUL)
4773 	{
4774 		if (wp->w_p_spell)
4775 		{
4776 		    (void)did_set_spelllang(wp);
4777 # ifdef FEAT_WINDOWS
4778 		    break;
4779 # endif
4780 		}
4781 	}
4782     }
4783 }
4784 #endif
4785 
4786 /*
4787  * Reload the spell file "fname" if it's loaded.
4788  */
4789     static void
4790 spell_reload_one(fname, added_word)
4791     char_u	*fname;
4792     int		added_word;	/* invoked through "zg" */
4793 {
4794     slang_T	*slang;
4795     int		didit = FALSE;
4796 
4797     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
4798     {
4799 	if (fullpathcmp(fname, slang->sl_fname, FALSE) == FPC_SAME)
4800 	{
4801 	    slang_clear(slang);
4802 	    if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
4803 		/* reloading failed, clear the language */
4804 		slang_clear(slang);
4805 	    redraw_all_later(SOME_VALID);
4806 	    didit = TRUE;
4807 	}
4808     }
4809 
4810     /* When "zg" was used and the file wasn't loaded yet, should redo
4811      * 'spelllang' to load it now. */
4812     if (added_word && !didit)
4813 	did_set_spelllang(curwin);
4814 }
4815 
4816 
4817 /*
4818  * Functions for ":mkspell".
4819  */
4820 
4821 #define MAXLINELEN  500		/* Maximum length in bytes of a line in a .aff
4822 				   and .dic file. */
4823 /*
4824  * Main structure to store the contents of a ".aff" file.
4825  */
4826 typedef struct afffile_S
4827 {
4828     char_u	*af_enc;	/* "SET", normalized, alloc'ed string or NULL */
4829     int		af_flagtype;	/* AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG */
4830     unsigned	af_rare;	/* RARE ID for rare word */
4831     unsigned	af_keepcase;	/* KEEPCASE ID for keep-case word */
4832     unsigned	af_bad;		/* BAD ID for banned word */
4833     unsigned	af_needaffix;	/* NEEDAFFIX ID */
4834     unsigned	af_circumfix;	/* CIRCUMFIX ID */
4835     unsigned	af_needcomp;	/* NEEDCOMPOUND ID */
4836     unsigned	af_comproot;	/* COMPOUNDROOT ID */
4837     unsigned	af_compforbid;	/* COMPOUNDFORBIDFLAG ID */
4838     unsigned	af_comppermit;	/* COMPOUNDPERMITFLAG ID */
4839     unsigned	af_nosuggest;	/* NOSUGGEST ID */
4840     int		af_pfxpostpone;	/* postpone prefixes without chop string and
4841 				   without flags */
4842     int		af_ignoreextra;	/* IGNOREEXTRA present */
4843     hashtab_T	af_pref;	/* hashtable for prefixes, affheader_T */
4844     hashtab_T	af_suff;	/* hashtable for suffixes, affheader_T */
4845     hashtab_T	af_comp;	/* hashtable for compound flags, compitem_T */
4846 } afffile_T;
4847 
4848 #define AFT_CHAR	0	/* flags are one character */
4849 #define AFT_LONG	1	/* flags are two characters */
4850 #define AFT_CAPLONG	2	/* flags are one or two characters */
4851 #define AFT_NUM		3	/* flags are numbers, comma separated */
4852 
4853 typedef struct affentry_S affentry_T;
4854 /* Affix entry from ".aff" file.  Used for prefixes and suffixes. */
4855 struct affentry_S
4856 {
4857     affentry_T	*ae_next;	/* next affix with same name/number */
4858     char_u	*ae_chop;	/* text to chop off basic word (can be NULL) */
4859     char_u	*ae_add;	/* text to add to basic word (can be NULL) */
4860     char_u	*ae_flags;	/* flags on the affix (can be NULL) */
4861     char_u	*ae_cond;	/* condition (NULL for ".") */
4862     regprog_T	*ae_prog;	/* regexp program for ae_cond or NULL */
4863     char	ae_compforbid;	/* COMPOUNDFORBIDFLAG found */
4864     char	ae_comppermit;	/* COMPOUNDPERMITFLAG found */
4865 };
4866 
4867 #ifdef FEAT_MBYTE
4868 # define AH_KEY_LEN 17		/* 2 x 8 bytes + NUL */
4869 #else
4870 # define AH_KEY_LEN 7		/* 6 digits + NUL */
4871 #endif
4872 
4873 /* Affix header from ".aff" file.  Used for af_pref and af_suff. */
4874 typedef struct affheader_S
4875 {
4876     char_u	ah_key[AH_KEY_LEN]; /* key for hashtab == name of affix */
4877     unsigned	ah_flag;	/* affix name as number, uses "af_flagtype" */
4878     int		ah_newID;	/* prefix ID after renumbering; 0 if not used */
4879     int		ah_combine;	/* suffix may combine with prefix */
4880     int		ah_follows;	/* another affix block should be following */
4881     affentry_T	*ah_first;	/* first affix entry */
4882 } affheader_T;
4883 
4884 #define HI2AH(hi)   ((affheader_T *)(hi)->hi_key)
4885 
4886 /* Flag used in compound items. */
4887 typedef struct compitem_S
4888 {
4889     char_u	ci_key[AH_KEY_LEN]; /* key for hashtab == name of compound */
4890     unsigned	ci_flag;	/* affix name as number, uses "af_flagtype" */
4891     int		ci_newID;	/* affix ID after renumbering. */
4892 } compitem_T;
4893 
4894 #define HI2CI(hi)   ((compitem_T *)(hi)->hi_key)
4895 
4896 /*
4897  * Structure that is used to store the items in the word tree.  This avoids
4898  * the need to keep track of each allocated thing, everything is freed all at
4899  * once after ":mkspell" is done.
4900  * Note: "sb_next" must be just before "sb_data" to make sure the alignment of
4901  * "sb_data" is correct for systems where pointers must be aligned on
4902  * pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc).
4903  */
4904 #define  SBLOCKSIZE 16000	/* size of sb_data */
4905 typedef struct sblock_S sblock_T;
4906 struct sblock_S
4907 {
4908     int		sb_used;	/* nr of bytes already in use */
4909     sblock_T	*sb_next;	/* next block in list */
4910     char_u	sb_data[1];	/* data, actually longer */
4911 };
4912 
4913 /*
4914  * A node in the tree.
4915  */
4916 typedef struct wordnode_S wordnode_T;
4917 struct wordnode_S
4918 {
4919     union   /* shared to save space */
4920     {
4921 	char_u	hashkey[6];	/* the hash key, only used while compressing */
4922 	int	index;		/* index in written nodes (valid after first
4923 				   round) */
4924     } wn_u1;
4925     union   /* shared to save space */
4926     {
4927 	wordnode_T *next;	/* next node with same hash key */
4928 	wordnode_T *wnode;	/* parent node that will write this node */
4929     } wn_u2;
4930     wordnode_T	*wn_child;	/* child (next byte in word) */
4931     wordnode_T  *wn_sibling;	/* next sibling (alternate byte in word,
4932 				   always sorted) */
4933     int		wn_refs;	/* Nr. of references to this node.  Only
4934 				   relevant for first node in a list of
4935 				   siblings, in following siblings it is
4936 				   always one. */
4937     char_u	wn_byte;	/* Byte for this node. NUL for word end */
4938 
4939     /* Info for when "wn_byte" is NUL.
4940      * In PREFIXTREE "wn_region" is used for the prefcondnr.
4941      * In the soundfolded word tree "wn_flags" has the MSW of the wordnr and
4942      * "wn_region" the LSW of the wordnr. */
4943     char_u	wn_affixID;	/* supported/required prefix ID or 0 */
4944     short_u	wn_flags;	/* WF_ flags */
4945     short	wn_region;	/* region mask */
4946 
4947 #ifdef SPELL_PRINTTREE
4948     int		wn_nr;		/* sequence nr for printing */
4949 #endif
4950 };
4951 
4952 #define WN_MASK	 0xffff		/* mask relevant bits of "wn_flags" */
4953 
4954 #define HI2WN(hi)    (wordnode_T *)((hi)->hi_key)
4955 
4956 /*
4957  * Info used while reading the spell files.
4958  */
4959 typedef struct spellinfo_S
4960 {
4961     wordnode_T	*si_foldroot;	/* tree with case-folded words */
4962     long	si_foldwcount;	/* nr of words in si_foldroot */
4963 
4964     wordnode_T	*si_keeproot;	/* tree with keep-case words */
4965     long	si_keepwcount;	/* nr of words in si_keeproot */
4966 
4967     wordnode_T	*si_prefroot;	/* tree with postponed prefixes */
4968 
4969     long	si_sugtree;	/* creating the soundfolding trie */
4970 
4971     sblock_T	*si_blocks;	/* memory blocks used */
4972     long	si_blocks_cnt;	/* memory blocks allocated */
4973     int		si_did_emsg;	/* TRUE when ran out of memory */
4974 
4975     long	si_compress_cnt;    /* words to add before lowering
4976 				       compression limit */
4977     wordnode_T	*si_first_free; /* List of nodes that have been freed during
4978 				   compression, linked by "wn_child" field. */
4979     long	si_free_count;	/* number of nodes in si_first_free */
4980 #ifdef SPELL_PRINTTREE
4981     int		si_wordnode_nr;	/* sequence nr for nodes */
4982 #endif
4983     buf_T	*si_spellbuf;	/* buffer used to store soundfold word table */
4984 
4985     int		si_ascii;	/* handling only ASCII words */
4986     int		si_add;		/* addition file */
4987     int		si_clear_chartab;   /* when TRUE clear char tables */
4988     int		si_region;	/* region mask */
4989     vimconv_T	si_conv;	/* for conversion to 'encoding' */
4990     int		si_memtot;	/* runtime memory used */
4991     int		si_verbose;	/* verbose messages */
4992     int		si_msg_count;	/* number of words added since last message */
4993     char_u	*si_info;	/* info text chars or NULL  */
4994     int		si_region_count; /* number of regions supported (1 when there
4995 				    are no regions) */
4996     char_u	si_region_name[17]; /* region names; used only if
4997 				     * si_region_count > 1) */
4998 
4999     garray_T	si_rep;		/* list of fromto_T entries from REP lines */
5000     garray_T	si_repsal;	/* list of fromto_T entries from REPSAL lines */
5001     garray_T	si_sal;		/* list of fromto_T entries from SAL lines */
5002     char_u	*si_sofofr;	/* SOFOFROM text */
5003     char_u	*si_sofoto;	/* SOFOTO text */
5004     int		si_nosugfile;	/* NOSUGFILE item found */
5005     int		si_nosplitsugs;	/* NOSPLITSUGS item found */
5006     int		si_followup;	/* soundsalike: ? */
5007     int		si_collapse;	/* soundsalike: ? */
5008     hashtab_T	si_commonwords;	/* hashtable for common words */
5009     time_t	si_sugtime;	/* timestamp for .sug file */
5010     int		si_rem_accents;	/* soundsalike: remove accents */
5011     garray_T	si_map;		/* MAP info concatenated */
5012     char_u	*si_midword;	/* MIDWORD chars or NULL  */
5013     int		si_compmax;	/* max nr of words for compounding */
5014     int		si_compminlen;	/* minimal length for compounding */
5015     int		si_compsylmax;	/* max nr of syllables for compounding */
5016     int		si_compoptions;	/* COMP_ flags */
5017     garray_T	si_comppat;	/* CHECKCOMPOUNDPATTERN items, each stored as
5018 				   a string */
5019     char_u	*si_compflags;	/* flags used for compounding */
5020     char_u	si_nobreak;	/* NOBREAK */
5021     char_u	*si_syllable;	/* syllable string */
5022     garray_T	si_prefcond;	/* table with conditions for postponed
5023 				 * prefixes, each stored as a string */
5024     int		si_newprefID;	/* current value for ah_newID */
5025     int		si_newcompID;	/* current value for compound ID */
5026 } spellinfo_T;
5027 
5028 static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
5029 static int is_aff_rule __ARGS((char_u **items, int itemcnt, char *rulename, int	 mincount));
5030 static void aff_process_flags __ARGS((afffile_T *affile, affentry_T *entry));
5031 static int spell_info_item __ARGS((char_u *s));
5032 static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u	*fname, int lnum));
5033 static unsigned get_affitem __ARGS((int flagtype, char_u **pp));
5034 static void process_compflags __ARGS((spellinfo_T *spin, afffile_T *aff, char_u *compflags));
5035 static void check_renumber __ARGS((spellinfo_T *spin));
5036 static int flag_in_afflist __ARGS((int flagtype, char_u *afflist, unsigned flag));
5037 static void aff_check_number __ARGS((int spinval, int affval, char *name));
5038 static void aff_check_string __ARGS((char_u *spinval, char_u *affval, char *name));
5039 static int str_equal __ARGS((char_u *s1, char_u	*s2));
5040 static void add_fromto __ARGS((spellinfo_T *spin, garray_T *gap, char_u	*from, char_u *to));
5041 static int sal_to_bool __ARGS((char_u *s));
5042 static void spell_free_aff __ARGS((afffile_T *aff));
5043 static int spell_read_dic __ARGS((spellinfo_T *spin, char_u *fname, afffile_T *affile));
5044 static int get_affix_flags __ARGS((afffile_T *affile, char_u *afflist));
5045 static int get_pfxlist __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
5046 static void get_compflags __ARGS((afffile_T *affile, char_u *afflist, char_u *store_afflist));
5047 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));
5048 static int spell_read_wordfile __ARGS((spellinfo_T *spin, char_u *fname));
5049 static void *getroom __ARGS((spellinfo_T *spin, size_t len, int align));
5050 static char_u *getroom_save __ARGS((spellinfo_T *spin, char_u *s));
5051 static void free_blocks __ARGS((sblock_T *bl));
5052 static wordnode_T *wordtree_alloc __ARGS((spellinfo_T *spin));
5053 static int store_word __ARGS((spellinfo_T *spin, char_u *word, int flags, int region, char_u *pfxlist, int need_affix));
5054 static int tree_add_word __ARGS((spellinfo_T *spin, char_u *word, wordnode_T *tree, int flags, int region, int affixID));
5055 static wordnode_T *get_wordnode __ARGS((spellinfo_T *spin));
5056 static int deref_wordnode __ARGS((spellinfo_T *spin, wordnode_T *node));
5057 static void free_wordnode __ARGS((spellinfo_T *spin, wordnode_T *n));
5058 static void wordtree_compress __ARGS((spellinfo_T *spin, wordnode_T *root));
5059 static int node_compress __ARGS((spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot));
5060 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
5061 static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
5062 static void clear_node __ARGS((wordnode_T *node));
5063 static int put_node __ARGS((FILE *fd, wordnode_T *node, int idx, int regionmask, int prefixtree));
5064 static void spell_make_sugfile __ARGS((spellinfo_T *spin, char_u *wfname));
5065 static int sug_filltree __ARGS((spellinfo_T *spin, slang_T *slang));
5066 static int sug_maketable __ARGS((spellinfo_T *spin));
5067 static int sug_filltable __ARGS((spellinfo_T *spin, wordnode_T *node, int startwordnr, garray_T *gap));
5068 static int offset2bytes __ARGS((int nr, char_u *buf));
5069 static int bytes2offset __ARGS((char_u **pp));
5070 static void sug_write __ARGS((spellinfo_T *spin, char_u *fname));
5071 static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int over_write, int added_word));
5072 static void spell_message __ARGS((spellinfo_T *spin, char_u *str));
5073 static void init_spellfile __ARGS((void));
5074 
5075 /* In the postponed prefixes tree wn_flags is used to store the WFP_ flags,
5076  * but it must be negative to indicate the prefix tree to tree_add_word().
5077  * Use a negative number with the lower 8 bits zero. */
5078 #define PFX_FLAGS	-256
5079 
5080 /* flags for "condit" argument of store_aff_word() */
5081 #define CONDIT_COMB	1	/* affix must combine */
5082 #define CONDIT_CFIX	2	/* affix must have CIRCUMFIX flag */
5083 #define CONDIT_SUF	4	/* add a suffix for matching flags */
5084 #define CONDIT_AFF	8	/* word already has an affix */
5085 
5086 /*
5087  * Tunable parameters for when the tree is compressed.  See 'mkspellmem'.
5088  */
5089 static long compress_start = 30000;	/* memory / SBLOCKSIZE */
5090 static long compress_inc = 100;		/* memory / SBLOCKSIZE */
5091 static long compress_added = 500000;	/* word count */
5092 
5093 #ifdef SPELL_PRINTTREE
5094 /*
5095  * For debugging the tree code: print the current tree in a (more or less)
5096  * readable format, so that we can see what happens when adding a word and/or
5097  * compressing the tree.
5098  * Based on code from Olaf Seibert.
5099  */
5100 #define PRINTLINESIZE	1000
5101 #define PRINTWIDTH	6
5102 
5103 #define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \
5104 	    PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2)
5105 
5106 static char line1[PRINTLINESIZE];
5107 static char line2[PRINTLINESIZE];
5108 static char line3[PRINTLINESIZE];
5109 
5110     static void
5111 spell_clear_flags(wordnode_T *node)
5112 {
5113     wordnode_T	*np;
5114 
5115     for (np = node; np != NULL; np = np->wn_sibling)
5116     {
5117 	np->wn_u1.index = FALSE;
5118 	spell_clear_flags(np->wn_child);
5119     }
5120 }
5121 
5122     static void
5123 spell_print_node(wordnode_T *node, int depth)
5124 {
5125     if (node->wn_u1.index)
5126     {
5127 	/* Done this node before, print the reference. */
5128 	PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0);
5129 	PRINTSOME(line2, depth, "    ", 0, 0);
5130 	PRINTSOME(line3, depth, "    ", 0, 0);
5131 	msg(line1);
5132 	msg(line2);
5133 	msg(line3);
5134     }
5135     else
5136     {
5137 	node->wn_u1.index = TRUE;
5138 
5139 	if (node->wn_byte != NUL)
5140 	{
5141 	    if (node->wn_child != NULL)
5142 		PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0);
5143 	    else
5144 		/* Cannot happen? */
5145 		PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0);
5146 	}
5147 	else
5148 	    PRINTSOME(line1, depth, " $    ", 0, 0);
5149 
5150 	PRINTSOME(line2, depth, "%d/%d    ", node->wn_nr, node->wn_refs);
5151 
5152 	if (node->wn_sibling != NULL)
5153 	    PRINTSOME(line3, depth, " |    ", 0, 0);
5154 	else
5155 	    PRINTSOME(line3, depth, "      ", 0, 0);
5156 
5157 	if (node->wn_byte == NUL)
5158 	{
5159 	    msg(line1);
5160 	    msg(line2);
5161 	    msg(line3);
5162 	}
5163 
5164 	/* do the children */
5165 	if (node->wn_byte != NUL && node->wn_child != NULL)
5166 	    spell_print_node(node->wn_child, depth + 1);
5167 
5168 	/* do the siblings */
5169 	if (node->wn_sibling != NULL)
5170 	{
5171 	    /* get rid of all parent details except | */
5172 	    STRCPY(line1, line3);
5173 	    STRCPY(line2, line3);
5174 	    spell_print_node(node->wn_sibling, depth);
5175 	}
5176     }
5177 }
5178 
5179     static void
5180 spell_print_tree(wordnode_T *root)
5181 {
5182     if (root != NULL)
5183     {
5184 	/* Clear the "wn_u1.index" fields, used to remember what has been
5185 	 * done. */
5186 	spell_clear_flags(root);
5187 
5188 	/* Recursively print the tree. */
5189 	spell_print_node(root, 0);
5190     }
5191 }
5192 #endif /* SPELL_PRINTTREE */
5193 
5194 /*
5195  * Read the affix file "fname".
5196  * Returns an afffile_T, NULL for complete failure.
5197  */
5198     static afffile_T *
5199 spell_read_aff(spin, fname)
5200     spellinfo_T	*spin;
5201     char_u	*fname;
5202 {
5203     FILE	*fd;
5204     afffile_T	*aff;
5205     char_u	rline[MAXLINELEN];
5206     char_u	*line;
5207     char_u	*pc = NULL;
5208 #define MAXITEMCNT  30
5209     char_u	*(items[MAXITEMCNT]);
5210     int		itemcnt;
5211     char_u	*p;
5212     int		lnum = 0;
5213     affheader_T	*cur_aff = NULL;
5214     int		did_postpone_prefix = FALSE;
5215     int		aff_todo = 0;
5216     hashtab_T	*tp;
5217     char_u	*low = NULL;
5218     char_u	*fol = NULL;
5219     char_u	*upp = NULL;
5220     int		do_rep;
5221     int		do_repsal;
5222     int		do_sal;
5223     int		do_mapline;
5224     int		found_map = FALSE;
5225     hashitem_T	*hi;
5226     int		l;
5227     int		compminlen = 0;		/* COMPOUNDMIN value */
5228     int		compsylmax = 0;		/* COMPOUNDSYLMAX value */
5229     int		compoptions = 0;	/* COMP_ flags */
5230     int		compmax = 0;		/* COMPOUNDWORDMAX value */
5231     char_u	*compflags = NULL;	/* COMPOUNDFLAG and COMPOUNDRULE
5232 					   concatenated */
5233     char_u	*midword = NULL;	/* MIDWORD value */
5234     char_u	*syllable = NULL;	/* SYLLABLE value */
5235     char_u	*sofofrom = NULL;	/* SOFOFROM value */
5236     char_u	*sofoto = NULL;		/* SOFOTO value */
5237 
5238     /*
5239      * Open the file.
5240      */
5241     fd = mch_fopen((char *)fname, "r");
5242     if (fd == NULL)
5243     {
5244 	EMSG2(_(e_notopen), fname);
5245 	return NULL;
5246     }
5247 
5248     vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname);
5249     spell_message(spin, IObuff);
5250 
5251     /* Only do REP lines when not done in another .aff file already. */
5252     do_rep = spin->si_rep.ga_len == 0;
5253 
5254     /* Only do REPSAL lines when not done in another .aff file already. */
5255     do_repsal = spin->si_repsal.ga_len == 0;
5256 
5257     /* Only do SAL lines when not done in another .aff file already. */
5258     do_sal = spin->si_sal.ga_len == 0;
5259 
5260     /* Only do MAP lines when not done in another .aff file already. */
5261     do_mapline = spin->si_map.ga_len == 0;
5262 
5263     /*
5264      * Allocate and init the afffile_T structure.
5265      */
5266     aff = (afffile_T *)getroom(spin, sizeof(afffile_T), TRUE);
5267     if (aff == NULL)
5268     {
5269 	fclose(fd);
5270 	return NULL;
5271     }
5272     hash_init(&aff->af_pref);
5273     hash_init(&aff->af_suff);
5274     hash_init(&aff->af_comp);
5275 
5276     /*
5277      * Read all the lines in the file one by one.
5278      */
5279     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
5280     {
5281 	line_breakcheck();
5282 	++lnum;
5283 
5284 	/* Skip comment lines. */
5285 	if (*rline == '#')
5286 	    continue;
5287 
5288 	/* Convert from "SET" to 'encoding' when needed. */
5289 	vim_free(pc);
5290 #ifdef FEAT_MBYTE
5291 	if (spin->si_conv.vc_type != CONV_NONE)
5292 	{
5293 	    pc = string_convert(&spin->si_conv, rline, NULL);
5294 	    if (pc == NULL)
5295 	    {
5296 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
5297 							   fname, lnum, rline);
5298 		continue;
5299 	    }
5300 	    line = pc;
5301 	}
5302 	else
5303 #endif
5304 	{
5305 	    pc = NULL;
5306 	    line = rline;
5307 	}
5308 
5309 	/* Split the line up in white separated items.  Put a NUL after each
5310 	 * item. */
5311 	itemcnt = 0;
5312 	for (p = line; ; )
5313 	{
5314 	    while (*p != NUL && *p <= ' ')  /* skip white space and CR/NL */
5315 		++p;
5316 	    if (*p == NUL)
5317 		break;
5318 	    if (itemcnt == MAXITEMCNT)	    /* too many items */
5319 		break;
5320 	    items[itemcnt++] = p;
5321 	    /* A few items have arbitrary text argument, don't split them. */
5322 	    if (itemcnt == 2 && spell_info_item(items[0]))
5323 		while (*p >= ' ' || *p == TAB)    /* skip until CR/NL */
5324 		    ++p;
5325 	    else
5326 		while (*p > ' ')    /* skip until white space or CR/NL */
5327 		    ++p;
5328 	    if (*p == NUL)
5329 		break;
5330 	    *p++ = NUL;
5331 	}
5332 
5333 	/* Handle non-empty lines. */
5334 	if (itemcnt > 0)
5335 	{
5336 	    if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL)
5337 	    {
5338 #ifdef FEAT_MBYTE
5339 		/* Setup for conversion from "ENC" to 'encoding'. */
5340 		aff->af_enc = enc_canonize(items[1]);
5341 		if (aff->af_enc != NULL && !spin->si_ascii
5342 			&& convert_setup(&spin->si_conv, aff->af_enc,
5343 							       p_enc) == FAIL)
5344 		    smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
5345 					       fname, aff->af_enc, p_enc);
5346 		spin->si_conv.vc_fail = TRUE;
5347 #else
5348 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
5349 #endif
5350 	    }
5351 	    else if (is_aff_rule(items, itemcnt, "FLAG", 2)
5352 					      && aff->af_flagtype == AFT_CHAR)
5353 	    {
5354 		if (STRCMP(items[1], "long") == 0)
5355 		    aff->af_flagtype = AFT_LONG;
5356 		else if (STRCMP(items[1], "num") == 0)
5357 		    aff->af_flagtype = AFT_NUM;
5358 		else if (STRCMP(items[1], "caplong") == 0)
5359 		    aff->af_flagtype = AFT_CAPLONG;
5360 		else
5361 		    smsg((char_u *)_("Invalid value for FLAG in %s line %d: %s"),
5362 			    fname, lnum, items[1]);
5363 		if (aff->af_rare != 0
5364 			|| aff->af_keepcase != 0
5365 			|| aff->af_bad != 0
5366 			|| aff->af_needaffix != 0
5367 			|| aff->af_circumfix != 0
5368 			|| aff->af_needcomp != 0
5369 			|| aff->af_comproot != 0
5370 			|| aff->af_nosuggest != 0
5371 			|| compflags != NULL
5372 			|| aff->af_suff.ht_used > 0
5373 			|| aff->af_pref.ht_used > 0)
5374 		    smsg((char_u *)_("FLAG after using flags in %s line %d: %s"),
5375 			    fname, lnum, items[1]);
5376 	    }
5377 	    else if (spell_info_item(items[0]))
5378 	    {
5379 		    p = (char_u *)getroom(spin,
5380 			    (spin->si_info == NULL ? 0 : STRLEN(spin->si_info))
5381 			    + STRLEN(items[0])
5382 			    + STRLEN(items[1]) + 3, FALSE);
5383 		    if (p != NULL)
5384 		    {
5385 			if (spin->si_info != NULL)
5386 			{
5387 			    STRCPY(p, spin->si_info);
5388 			    STRCAT(p, "\n");
5389 			}
5390 			STRCAT(p, items[0]);
5391 			STRCAT(p, " ");
5392 			STRCAT(p, items[1]);
5393 			spin->si_info = p;
5394 		    }
5395 	    }
5396 	    else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
5397 							   && midword == NULL)
5398 	    {
5399 		midword = getroom_save(spin, items[1]);
5400 	    }
5401 	    else if (is_aff_rule(items, itemcnt, "TRY", 2))
5402 	    {
5403 		/* ignored, we look in the tree for what chars may appear */
5404 	    }
5405 	    /* TODO: remove "RAR" later */
5406 	    else if ((is_aff_rule(items, itemcnt, "RAR", 2)
5407 			|| is_aff_rule(items, itemcnt, "RARE", 2))
5408 							 && aff->af_rare == 0)
5409 	    {
5410 		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
5411 								 fname, lnum);
5412 	    }
5413 	    /* TODO: remove "KEP" later */
5414 	    else if ((is_aff_rule(items, itemcnt, "KEP", 2)
5415 			|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
5416 						     && aff->af_keepcase == 0)
5417 	    {
5418 		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
5419 								 fname, lnum);
5420 	    }
5421 	    else if ((is_aff_rule(items, itemcnt, "BAD", 2)
5422 			|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
5423 							  && aff->af_bad == 0)
5424 	    {
5425 		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
5426 								 fname, lnum);
5427 	    }
5428 	    else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
5429 						    && aff->af_needaffix == 0)
5430 	    {
5431 		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
5432 								 fname, lnum);
5433 	    }
5434 	    else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
5435 						    && aff->af_circumfix == 0)
5436 	    {
5437 		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
5438 								 fname, lnum);
5439 	    }
5440 	    else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
5441 						    && aff->af_nosuggest == 0)
5442 	    {
5443 		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
5444 								 fname, lnum);
5445 	    }
5446 	    else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
5447 			|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
5448 						     && aff->af_needcomp == 0)
5449 	    {
5450 		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
5451 								 fname, lnum);
5452 	    }
5453 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
5454 						     && aff->af_comproot == 0)
5455 	    {
5456 		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
5457 								 fname, lnum);
5458 	    }
5459 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
5460 						   && aff->af_compforbid == 0)
5461 	    {
5462 		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
5463 								 fname, lnum);
5464 		if (aff->af_pref.ht_used > 0)
5465 		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
5466 			    fname, lnum);
5467 	    }
5468 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
5469 						   && aff->af_comppermit == 0)
5470 	    {
5471 		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
5472 								 fname, lnum);
5473 		if (aff->af_pref.ht_used > 0)
5474 		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
5475 			    fname, lnum);
5476 	    }
5477 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2)
5478 							 && compflags == NULL)
5479 	    {
5480 		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
5481 		 * "Na" into "Na+", "1234" into "1234+". */
5482 		p = getroom(spin, STRLEN(items[1]) + 2, FALSE);
5483 		if (p != NULL)
5484 		{
5485 		    STRCPY(p, items[1]);
5486 		    STRCAT(p, "+");
5487 		    compflags = p;
5488 		}
5489 	    }
5490 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2))
5491 	    {
5492 		/* We don't use the count, but do check that it's a number and
5493 		 * not COMPOUNDRULE mistyped. */
5494 		if (atoi((char *)items[1]) == 0)
5495 		    smsg((char_u *)_("Wrong COMPOUNDRULES value in %s line %d: %s"),
5496 						       fname, lnum, items[1]);
5497 	    }
5498 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2))
5499 	    {
5500 		/* Don't use the first rule if it is a number. */
5501 		if (compflags != NULL || *skipdigits(items[1]) != NUL)
5502 		{
5503 		    /* Concatenate this string to previously defined ones,
5504 		     * using a slash to separate them. */
5505 		    l = (int)STRLEN(items[1]) + 1;
5506 		    if (compflags != NULL)
5507 			l += (int)STRLEN(compflags) + 1;
5508 		    p = getroom(spin, l, FALSE);
5509 		    if (p != NULL)
5510 		    {
5511 			if (compflags != NULL)
5512 			{
5513 			    STRCPY(p, compflags);
5514 			    STRCAT(p, "/");
5515 			}
5516 			STRCAT(p, items[1]);
5517 			compflags = p;
5518 		    }
5519 		}
5520 	    }
5521 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
5522 							      && compmax == 0)
5523 	    {
5524 		compmax = atoi((char *)items[1]);
5525 		if (compmax == 0)
5526 		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
5527 						       fname, lnum, items[1]);
5528 	    }
5529 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2)
5530 							   && compminlen == 0)
5531 	    {
5532 		compminlen = atoi((char *)items[1]);
5533 		if (compminlen == 0)
5534 		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
5535 						       fname, lnum, items[1]);
5536 	    }
5537 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2)
5538 							   && compsylmax == 0)
5539 	    {
5540 		compsylmax = atoi((char *)items[1]);
5541 		if (compsylmax == 0)
5542 		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
5543 						       fname, lnum, items[1]);
5544 	    }
5545 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1))
5546 	    {
5547 		compoptions |= COMP_CHECKDUP;
5548 	    }
5549 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1))
5550 	    {
5551 		compoptions |= COMP_CHECKREP;
5552 	    }
5553 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1))
5554 	    {
5555 		compoptions |= COMP_CHECKCASE;
5556 	    }
5557 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1))
5558 	    {
5559 		compoptions |= COMP_CHECKTRIPLE;
5560 	    }
5561 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2))
5562 	    {
5563 		if (atoi((char *)items[1]) == 0)
5564 		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
5565 						       fname, lnum, items[1]);
5566 	    }
5567 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3))
5568 	    {
5569 		garray_T    *gap = &spin->si_comppat;
5570 		int	    i;
5571 
5572 		/* Only add the couple if it isn't already there. */
5573 		for (i = 0; i < gap->ga_len - 1; i += 2)
5574 		    if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0
5575 			    && STRCMP(((char_u **)(gap->ga_data))[i + 1],
5576 							       items[2]) == 0)
5577 			break;
5578 		if (i >= gap->ga_len && ga_grow(gap, 2) == OK)
5579 		{
5580 		    ((char_u **)(gap->ga_data))[gap->ga_len++]
5581 					       = getroom_save(spin, items[1]);
5582 		    ((char_u **)(gap->ga_data))[gap->ga_len++]
5583 					       = getroom_save(spin, items[2]);
5584 		}
5585 	    }
5586 	    else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
5587 							  && syllable == NULL)
5588 	    {
5589 		syllable = getroom_save(spin, items[1]);
5590 	    }
5591 	    else if (is_aff_rule(items, itemcnt, "NOBREAK", 1))
5592 	    {
5593 		spin->si_nobreak = TRUE;
5594 	    }
5595 	    else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1))
5596 	    {
5597 		spin->si_nosplitsugs = TRUE;
5598 	    }
5599 	    else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1))
5600 	    {
5601 		spin->si_nosugfile = TRUE;
5602 	    }
5603 	    else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1))
5604 	    {
5605 		aff->af_pfxpostpone = TRUE;
5606 	    }
5607 	    else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1))
5608 	    {
5609 		aff->af_ignoreextra = TRUE;
5610 	    }
5611 	    else if ((STRCMP(items[0], "PFX") == 0
5612 					      || STRCMP(items[0], "SFX") == 0)
5613 		    && aff_todo == 0
5614 		    && itemcnt >= 4)
5615 	    {
5616 		int	lasti = 4;
5617 		char_u	key[AH_KEY_LEN];
5618 
5619 		if (*items[0] == 'P')
5620 		    tp = &aff->af_pref;
5621 		else
5622 		    tp = &aff->af_suff;
5623 
5624 		/* Myspell allows the same affix name to be used multiple
5625 		 * times.  The affix files that do this have an undocumented
5626 		 * "S" flag on all but the last block, thus we check for that
5627 		 * and store it in ah_follows. */
5628 		vim_strncpy(key, items[1], AH_KEY_LEN - 1);
5629 		hi = hash_find(tp, key);
5630 		if (!HASHITEM_EMPTY(hi))
5631 		{
5632 		    cur_aff = HI2AH(hi);
5633 		    if (cur_aff->ah_combine != (*items[2] == 'Y'))
5634 			smsg((char_u *)_("Different combining flag in continued affix block in %s line %d: %s"),
5635 						   fname, lnum, items[1]);
5636 		    if (!cur_aff->ah_follows)
5637 			smsg((char_u *)_("Duplicate affix in %s line %d: %s"),
5638 						       fname, lnum, items[1]);
5639 		}
5640 		else
5641 		{
5642 		    /* New affix letter. */
5643 		    cur_aff = (affheader_T *)getroom(spin,
5644 						   sizeof(affheader_T), TRUE);
5645 		    if (cur_aff == NULL)
5646 			break;
5647 		    cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1],
5648 								 fname, lnum);
5649 		    if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN)
5650 			break;
5651 		    if (cur_aff->ah_flag == aff->af_bad
5652 			    || cur_aff->ah_flag == aff->af_rare
5653 			    || cur_aff->ah_flag == aff->af_keepcase
5654 			    || cur_aff->ah_flag == aff->af_needaffix
5655 			    || cur_aff->ah_flag == aff->af_circumfix
5656 			    || cur_aff->ah_flag == aff->af_nosuggest
5657 			    || cur_aff->ah_flag == aff->af_needcomp
5658 			    || cur_aff->ah_flag == aff->af_comproot)
5659 			smsg((char_u *)_("Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s line %d: %s"),
5660 						       fname, lnum, items[1]);
5661 		    STRCPY(cur_aff->ah_key, items[1]);
5662 		    hash_add(tp, cur_aff->ah_key);
5663 
5664 		    cur_aff->ah_combine = (*items[2] == 'Y');
5665 		}
5666 
5667 		/* Check for the "S" flag, which apparently means that another
5668 		 * block with the same affix name is following. */
5669 		if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0)
5670 		{
5671 		    ++lasti;
5672 		    cur_aff->ah_follows = TRUE;
5673 		}
5674 		else
5675 		    cur_aff->ah_follows = FALSE;
5676 
5677 		/* Myspell allows extra text after the item, but that might
5678 		 * mean mistakes go unnoticed.  Require a comment-starter. */
5679 		if (itemcnt > lasti && *items[lasti] != '#')
5680 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[lasti]);
5681 
5682 		if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0)
5683 		    smsg((char_u *)_("Expected Y or N in %s line %d: %s"),
5684 						       fname, lnum, items[2]);
5685 
5686 		if (*items[0] == 'P' && aff->af_pfxpostpone)
5687 		{
5688 		    if (cur_aff->ah_newID == 0)
5689 		    {
5690 			/* Use a new number in the .spl file later, to be able
5691 			 * to handle multiple .aff files. */
5692 			check_renumber(spin);
5693 			cur_aff->ah_newID = ++spin->si_newprefID;
5694 
5695 			/* We only really use ah_newID if the prefix is
5696 			 * postponed.  We know that only after handling all
5697 			 * the items. */
5698 			did_postpone_prefix = FALSE;
5699 		    }
5700 		    else
5701 			/* Did use the ID in a previous block. */
5702 			did_postpone_prefix = TRUE;
5703 		}
5704 
5705 		aff_todo = atoi((char *)items[3]);
5706 	    }
5707 	    else if ((STRCMP(items[0], "PFX") == 0
5708 					      || STRCMP(items[0], "SFX") == 0)
5709 		    && aff_todo > 0
5710 		    && STRCMP(cur_aff->ah_key, items[1]) == 0
5711 		    && itemcnt >= 5)
5712 	    {
5713 		affentry_T	*aff_entry;
5714 		int		upper = FALSE;
5715 		int		lasti = 5;
5716 
5717 		/* Myspell allows extra text after the item, but that might
5718 		 * mean mistakes go unnoticed.  Require a comment-starter,
5719 		 * unless IGNOREEXTRA is used.  Hunspell uses a "-" item. */
5720 		if (itemcnt > lasti
5721 			&& !aff->af_ignoreextra
5722 			&& *items[lasti] != '#'
5723 			&& (STRCMP(items[lasti], "-") != 0
5724 						     || itemcnt != lasti + 1))
5725 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[lasti]);
5726 
5727 		/* New item for an affix letter. */
5728 		--aff_todo;
5729 		aff_entry = (affentry_T *)getroom(spin,
5730 						    sizeof(affentry_T), TRUE);
5731 		if (aff_entry == NULL)
5732 		    break;
5733 
5734 		if (STRCMP(items[2], "0") != 0)
5735 		    aff_entry->ae_chop = getroom_save(spin, items[2]);
5736 		if (STRCMP(items[3], "0") != 0)
5737 		{
5738 		    aff_entry->ae_add = getroom_save(spin, items[3]);
5739 
5740 		    /* Recognize flags on the affix: abcd/XYZ */
5741 		    aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/');
5742 		    if (aff_entry->ae_flags != NULL)
5743 		    {
5744 			*aff_entry->ae_flags++ = NUL;
5745 			aff_process_flags(aff, aff_entry);
5746 		    }
5747 		}
5748 
5749 		/* Don't use an affix entry with non-ASCII characters when
5750 		 * "spin->si_ascii" is TRUE. */
5751 		if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop)
5752 					  || has_non_ascii(aff_entry->ae_add)))
5753 		{
5754 		    aff_entry->ae_next = cur_aff->ah_first;
5755 		    cur_aff->ah_first = aff_entry;
5756 
5757 		    if (STRCMP(items[4], ".") != 0)
5758 		    {
5759 			char_u	buf[MAXLINELEN];
5760 
5761 			aff_entry->ae_cond = getroom_save(spin, items[4]);
5762 			if (*items[0] == 'P')
5763 			    sprintf((char *)buf, "^%s", items[4]);
5764 			else
5765 			    sprintf((char *)buf, "%s$", items[4]);
5766 			aff_entry->ae_prog = vim_regcomp(buf,
5767 					    RE_MAGIC + RE_STRING + RE_STRICT);
5768 			if (aff_entry->ae_prog == NULL)
5769 			    smsg((char_u *)_("Broken condition in %s line %d: %s"),
5770 						       fname, lnum, items[4]);
5771 		    }
5772 
5773 		    /* For postponed prefixes we need an entry in si_prefcond
5774 		     * for the condition.  Use an existing one if possible.
5775 		     * Can't be done for an affix with flags, ignoring
5776 		     * COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. */
5777 		    if (*items[0] == 'P' && aff->af_pfxpostpone
5778 					       && aff_entry->ae_flags == NULL)
5779 		    {
5780 			/* When the chop string is one lower-case letter and
5781 			 * the add string ends in the upper-case letter we set
5782 			 * the "upper" flag, clear "ae_chop" and remove the
5783 			 * letters from "ae_add".  The condition must either
5784 			 * be empty or start with the same letter. */
5785 			if (aff_entry->ae_chop != NULL
5786 				&& aff_entry->ae_add != NULL
5787 #ifdef FEAT_MBYTE
5788 				&& aff_entry->ae_chop[(*mb_ptr2len)(
5789 						   aff_entry->ae_chop)] == NUL
5790 #else
5791 				&& aff_entry->ae_chop[1] == NUL
5792 #endif
5793 				)
5794 			{
5795 			    int		c, c_up;
5796 
5797 			    c = PTR2CHAR(aff_entry->ae_chop);
5798 			    c_up = SPELL_TOUPPER(c);
5799 			    if (c_up != c
5800 				    && (aff_entry->ae_cond == NULL
5801 					|| PTR2CHAR(aff_entry->ae_cond) == c))
5802 			    {
5803 				p = aff_entry->ae_add
5804 						  + STRLEN(aff_entry->ae_add);
5805 				mb_ptr_back(aff_entry->ae_add, p);
5806 				if (PTR2CHAR(p) == c_up)
5807 				{
5808 				    upper = TRUE;
5809 				    aff_entry->ae_chop = NULL;
5810 				    *p = NUL;
5811 
5812 				    /* The condition is matched with the
5813 				     * actual word, thus must check for the
5814 				     * upper-case letter. */
5815 				    if (aff_entry->ae_cond != NULL)
5816 				    {
5817 					char_u	buf[MAXLINELEN];
5818 #ifdef FEAT_MBYTE
5819 					if (has_mbyte)
5820 					{
5821 					    onecap_copy(items[4], buf, TRUE);
5822 					    aff_entry->ae_cond = getroom_save(
5823 								   spin, buf);
5824 					}
5825 					else
5826 #endif
5827 					    *aff_entry->ae_cond = c_up;
5828 					if (aff_entry->ae_cond != NULL)
5829 					{
5830 					    sprintf((char *)buf, "^%s",
5831 							  aff_entry->ae_cond);
5832 					    vim_regfree(aff_entry->ae_prog);
5833 					    aff_entry->ae_prog = vim_regcomp(
5834 						    buf, RE_MAGIC + RE_STRING);
5835 					}
5836 				    }
5837 				}
5838 			    }
5839 			}
5840 
5841 			if (aff_entry->ae_chop == NULL
5842 					       && aff_entry->ae_flags == NULL)
5843 			{
5844 			    int		idx;
5845 			    char_u	**pp;
5846 			    int		n;
5847 
5848 			    /* Find a previously used condition. */
5849 			    for (idx = spin->si_prefcond.ga_len - 1; idx >= 0;
5850 									--idx)
5851 			    {
5852 				p = ((char_u **)spin->si_prefcond.ga_data)[idx];
5853 				if (str_equal(p, aff_entry->ae_cond))
5854 				    break;
5855 			    }
5856 			    if (idx < 0 && ga_grow(&spin->si_prefcond, 1) == OK)
5857 			    {
5858 				/* Not found, add a new condition. */
5859 				idx = spin->si_prefcond.ga_len++;
5860 				pp = ((char_u **)spin->si_prefcond.ga_data)
5861 									+ idx;
5862 				if (aff_entry->ae_cond == NULL)
5863 				    *pp = NULL;
5864 				else
5865 				    *pp = getroom_save(spin,
5866 							  aff_entry->ae_cond);
5867 			    }
5868 
5869 			    /* Add the prefix to the prefix tree. */
5870 			    if (aff_entry->ae_add == NULL)
5871 				p = (char_u *)"";
5872 			    else
5873 				p = aff_entry->ae_add;
5874 
5875 			    /* PFX_FLAGS is a negative number, so that
5876 			     * tree_add_word() knows this is the prefix tree. */
5877 			    n = PFX_FLAGS;
5878 			    if (!cur_aff->ah_combine)
5879 				n |= WFP_NC;
5880 			    if (upper)
5881 				n |= WFP_UP;
5882 			    if (aff_entry->ae_comppermit)
5883 				n |= WFP_COMPPERMIT;
5884 			    if (aff_entry->ae_compforbid)
5885 				n |= WFP_COMPFORBID;
5886 			    tree_add_word(spin, p, spin->si_prefroot, n,
5887 						      idx, cur_aff->ah_newID);
5888 			    did_postpone_prefix = TRUE;
5889 			}
5890 
5891 			/* Didn't actually use ah_newID, backup si_newprefID. */
5892 			if (aff_todo == 0 && !did_postpone_prefix)
5893 			{
5894 			    --spin->si_newprefID;
5895 			    cur_aff->ah_newID = 0;
5896 			}
5897 		    }
5898 		}
5899 	    }
5900 	    else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL)
5901 	    {
5902 		fol = vim_strsave(items[1]);
5903 	    }
5904 	    else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL)
5905 	    {
5906 		low = vim_strsave(items[1]);
5907 	    }
5908 	    else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL)
5909 	    {
5910 		upp = vim_strsave(items[1]);
5911 	    }
5912 	    else if (is_aff_rule(items, itemcnt, "REP", 2)
5913 		     || is_aff_rule(items, itemcnt, "REPSAL", 2))
5914 	    {
5915 		/* Ignore REP/REPSAL count */;
5916 		if (!isdigit(*items[1]))
5917 		    smsg((char_u *)_("Expected REP(SAL) count in %s line %d"),
5918 								 fname, lnum);
5919 	    }
5920 	    else if ((STRCMP(items[0], "REP") == 0
5921 			|| STRCMP(items[0], "REPSAL") == 0)
5922 		    && itemcnt >= 3)
5923 	    {
5924 		/* REP/REPSAL item */
5925 		/* Myspell ignores extra arguments, we require it starts with
5926 		 * # to detect mistakes. */
5927 		if (itemcnt > 3 && items[3][0] != '#')
5928 		    smsg((char_u *)_(e_afftrailing), fname, lnum, items[3]);
5929 		if (items[0][3] == 'S' ? do_repsal : do_rep)
5930 		{
5931 		    /* Replace underscore with space (can't include a space
5932 		     * directly). */
5933 		    for (p = items[1]; *p != NUL; mb_ptr_adv(p))
5934 			if (*p == '_')
5935 			    *p = ' ';
5936 		    for (p = items[2]; *p != NUL; mb_ptr_adv(p))
5937 			if (*p == '_')
5938 			    *p = ' ';
5939 		    add_fromto(spin, items[0][3] == 'S'
5940 					 ? &spin->si_repsal
5941 					 : &spin->si_rep, items[1], items[2]);
5942 		}
5943 	    }
5944 	    else if (is_aff_rule(items, itemcnt, "MAP", 2))
5945 	    {
5946 		/* MAP item or count */
5947 		if (!found_map)
5948 		{
5949 		    /* First line contains the count. */
5950 		    found_map = TRUE;
5951 		    if (!isdigit(*items[1]))
5952 			smsg((char_u *)_("Expected MAP count in %s line %d"),
5953 								 fname, lnum);
5954 		}
5955 		else if (do_mapline)
5956 		{
5957 		    int		c;
5958 
5959 		    /* Check that every character appears only once. */
5960 		    for (p = items[1]; *p != NUL; )
5961 		    {
5962 #ifdef FEAT_MBYTE
5963 			c = mb_ptr2char_adv(&p);
5964 #else
5965 			c = *p++;
5966 #endif
5967 			if ((spin->si_map.ga_len > 0
5968 				    && vim_strchr(spin->si_map.ga_data, c)
5969 								      != NULL)
5970 				|| vim_strchr(p, c) != NULL)
5971 			    smsg((char_u *)_("Duplicate character in MAP in %s line %d"),
5972 								 fname, lnum);
5973 		    }
5974 
5975 		    /* We simply concatenate all the MAP strings, separated by
5976 		     * slashes. */
5977 		    ga_concat(&spin->si_map, items[1]);
5978 		    ga_append(&spin->si_map, '/');
5979 		}
5980 	    }
5981 	    /* Accept "SAL from to" and "SAL from to  #comment". */
5982 	    else if (is_aff_rule(items, itemcnt, "SAL", 3))
5983 	    {
5984 		if (do_sal)
5985 		{
5986 		    /* SAL item (sounds-a-like)
5987 		     * Either one of the known keys or a from-to pair. */
5988 		    if (STRCMP(items[1], "followup") == 0)
5989 			spin->si_followup = sal_to_bool(items[2]);
5990 		    else if (STRCMP(items[1], "collapse_result") == 0)
5991 			spin->si_collapse = sal_to_bool(items[2]);
5992 		    else if (STRCMP(items[1], "remove_accents") == 0)
5993 			spin->si_rem_accents = sal_to_bool(items[2]);
5994 		    else
5995 			/* when "to" is "_" it means empty */
5996 			add_fromto(spin, &spin->si_sal, items[1],
5997 				     STRCMP(items[2], "_") == 0 ? (char_u *)""
5998 								: items[2]);
5999 		}
6000 	    }
6001 	    else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
6002 							  && sofofrom == NULL)
6003 	    {
6004 		sofofrom = getroom_save(spin, items[1]);
6005 	    }
6006 	    else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
6007 							    && sofoto == NULL)
6008 	    {
6009 		sofoto = getroom_save(spin, items[1]);
6010 	    }
6011 	    else if (STRCMP(items[0], "COMMON") == 0)
6012 	    {
6013 		int	i;
6014 
6015 		for (i = 1; i < itemcnt; ++i)
6016 		{
6017 		    if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords,
6018 								   items[i])))
6019 		    {
6020 			p = vim_strsave(items[i]);
6021 			if (p == NULL)
6022 			    break;
6023 			hash_add(&spin->si_commonwords, p);
6024 		    }
6025 		}
6026 	    }
6027 	    else
6028 		smsg((char_u *)_("Unrecognized or duplicate item in %s line %d: %s"),
6029 						       fname, lnum, items[0]);
6030 	}
6031     }
6032 
6033     if (fol != NULL || low != NULL || upp != NULL)
6034     {
6035 	if (spin->si_clear_chartab)
6036 	{
6037 	    /* Clear the char type tables, don't want to use any of the
6038 	     * currently used spell properties. */
6039 	    init_spell_chartab();
6040 	    spin->si_clear_chartab = FALSE;
6041 	}
6042 
6043 	/*
6044 	 * Don't write a word table for an ASCII file, so that we don't check
6045 	 * for conflicts with a word table that matches 'encoding'.
6046 	 * Don't write one for utf-8 either, we use utf_*() and
6047 	 * mb_get_class(), the list of chars in the file will be incomplete.
6048 	 */
6049 	if (!spin->si_ascii
6050 #ifdef FEAT_MBYTE
6051 		&& !enc_utf8
6052 #endif
6053 		)
6054 	{
6055 	    if (fol == NULL || low == NULL || upp == NULL)
6056 		smsg((char_u *)_("Missing FOL/LOW/UPP line in %s"), fname);
6057 	    else
6058 		(void)set_spell_chartab(fol, low, upp);
6059 	}
6060 
6061 	vim_free(fol);
6062 	vim_free(low);
6063 	vim_free(upp);
6064     }
6065 
6066     /* Use compound specifications of the .aff file for the spell info. */
6067     if (compmax != 0)
6068     {
6069 	aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX");
6070 	spin->si_compmax = compmax;
6071     }
6072 
6073     if (compminlen != 0)
6074     {
6075 	aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN");
6076 	spin->si_compminlen = compminlen;
6077     }
6078 
6079     if (compsylmax != 0)
6080     {
6081 	if (syllable == NULL)
6082 	    smsg((char_u *)_("COMPOUNDSYLMAX used without SYLLABLE"));
6083 	aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX");
6084 	spin->si_compsylmax = compsylmax;
6085     }
6086 
6087     if (compoptions != 0)
6088     {
6089 	aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options");
6090 	spin->si_compoptions |= compoptions;
6091     }
6092 
6093     if (compflags != NULL)
6094 	process_compflags(spin, aff, compflags);
6095 
6096     /* Check that we didn't use too many renumbered flags. */
6097     if (spin->si_newcompID < spin->si_newprefID)
6098     {
6099 	if (spin->si_newcompID == 127 || spin->si_newcompID == 255)
6100 	    MSG(_("Too many postponed prefixes"));
6101 	else if (spin->si_newprefID == 0 || spin->si_newprefID == 127)
6102 	    MSG(_("Too many compound flags"));
6103 	else
6104 	    MSG(_("Too many postponed prefixes and/or compound flags"));
6105     }
6106 
6107     if (syllable != NULL)
6108     {
6109 	aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
6110 	spin->si_syllable = syllable;
6111     }
6112 
6113     if (sofofrom != NULL || sofoto != NULL)
6114     {
6115 	if (sofofrom == NULL || sofoto == NULL)
6116 	    smsg((char_u *)_("Missing SOFO%s line in %s"),
6117 				     sofofrom == NULL ? "FROM" : "TO", fname);
6118 	else if (spin->si_sal.ga_len > 0)
6119 	    smsg((char_u *)_("Both SAL and SOFO lines in %s"), fname);
6120 	else
6121 	{
6122 	    aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
6123 	    aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
6124 	    spin->si_sofofr = sofofrom;
6125 	    spin->si_sofoto = sofoto;
6126 	}
6127     }
6128 
6129     if (midword != NULL)
6130     {
6131 	aff_check_string(spin->si_midword, midword, "MIDWORD");
6132 	spin->si_midword = midword;
6133     }
6134 
6135     vim_free(pc);
6136     fclose(fd);
6137     return aff;
6138 }
6139 
6140 /*
6141  * Return TRUE when items[0] equals "rulename", there are "mincount" items or
6142  * a comment is following after item "mincount".
6143  */
6144     static int
6145 is_aff_rule(items, itemcnt, rulename, mincount)
6146     char_u	**items;
6147     int		itemcnt;
6148     char	*rulename;
6149     int		mincount;
6150 {
6151     return (STRCMP(items[0], rulename) == 0
6152 	    && (itemcnt == mincount
6153 		|| (itemcnt > mincount && items[mincount][0] == '#')));
6154 }
6155 
6156 /*
6157  * For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from
6158  * ae_flags to ae_comppermit and ae_compforbid.
6159  */
6160     static void
6161 aff_process_flags(affile, entry)
6162     afffile_T	*affile;
6163     affentry_T	*entry;
6164 {
6165     char_u	*p;
6166     char_u	*prevp;
6167     unsigned	flag;
6168 
6169     if (entry->ae_flags != NULL
6170 		&& (affile->af_compforbid != 0 || affile->af_comppermit != 0))
6171     {
6172 	for (p = entry->ae_flags; *p != NUL; )
6173 	{
6174 	    prevp = p;
6175 	    flag = get_affitem(affile->af_flagtype, &p);
6176 	    if (flag == affile->af_comppermit || flag == affile->af_compforbid)
6177 	    {
6178 		STRMOVE(prevp, p);
6179 		p = prevp;
6180 		if (flag == affile->af_comppermit)
6181 		    entry->ae_comppermit = TRUE;
6182 		else
6183 		    entry->ae_compforbid = TRUE;
6184 	    }
6185 	    if (affile->af_flagtype == AFT_NUM && *p == ',')
6186 		++p;
6187 	}
6188 	if (*entry->ae_flags == NUL)
6189 	    entry->ae_flags = NULL;	/* nothing left */
6190     }
6191 }
6192 
6193 /*
6194  * Return TRUE if "s" is the name of an info item in the affix file.
6195  */
6196     static int
6197 spell_info_item(s)
6198     char_u	*s;
6199 {
6200     return STRCMP(s, "NAME") == 0
6201 	|| STRCMP(s, "HOME") == 0
6202 	|| STRCMP(s, "VERSION") == 0
6203 	|| STRCMP(s, "AUTHOR") == 0
6204 	|| STRCMP(s, "EMAIL") == 0
6205 	|| STRCMP(s, "COPYRIGHT") == 0;
6206 }
6207 
6208 /*
6209  * Turn an affix flag name into a number, according to the FLAG type.
6210  * returns zero for failure.
6211  */
6212     static unsigned
6213 affitem2flag(flagtype, item, fname, lnum)
6214     int		flagtype;
6215     char_u	*item;
6216     char_u	*fname;
6217     int		lnum;
6218 {
6219     unsigned	res;
6220     char_u	*p = item;
6221 
6222     res = get_affitem(flagtype, &p);
6223     if (res == 0)
6224     {
6225 	if (flagtype == AFT_NUM)
6226 	    smsg((char_u *)_("Flag is not a number in %s line %d: %s"),
6227 							   fname, lnum, item);
6228 	else
6229 	    smsg((char_u *)_("Illegal flag in %s line %d: %s"),
6230 							   fname, lnum, item);
6231     }
6232     if (*p != NUL)
6233     {
6234 	smsg((char_u *)_(e_affname), fname, lnum, item);
6235 	return 0;
6236     }
6237 
6238     return res;
6239 }
6240 
6241 /*
6242  * Get one affix name from "*pp" and advance the pointer.
6243  * Returns zero for an error, still advances the pointer then.
6244  */
6245     static unsigned
6246 get_affitem(flagtype, pp)
6247     int		flagtype;
6248     char_u	**pp;
6249 {
6250     int		res;
6251 
6252     if (flagtype == AFT_NUM)
6253     {
6254 	if (!VIM_ISDIGIT(**pp))
6255 	{
6256 	    ++*pp;	/* always advance, avoid getting stuck */
6257 	    return 0;
6258 	}
6259 	res = getdigits(pp);
6260     }
6261     else
6262     {
6263 #ifdef FEAT_MBYTE
6264 	res = mb_ptr2char_adv(pp);
6265 #else
6266 	res = *(*pp)++;
6267 #endif
6268 	if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
6269 						 && res >= 'A' && res <= 'Z'))
6270 	{
6271 	    if (**pp == NUL)
6272 		return 0;
6273 #ifdef FEAT_MBYTE
6274 	    res = mb_ptr2char_adv(pp) + (res << 16);
6275 #else
6276 	    res = *(*pp)++ + (res << 16);
6277 #endif
6278 	}
6279     }
6280     return res;
6281 }
6282 
6283 /*
6284  * Process the "compflags" string used in an affix file and append it to
6285  * spin->si_compflags.
6286  * The processing involves changing the affix names to ID numbers, so that
6287  * they fit in one byte.
6288  */
6289     static void
6290 process_compflags(spin, aff, compflags)
6291     spellinfo_T	*spin;
6292     afffile_T	*aff;
6293     char_u	*compflags;
6294 {
6295     char_u	*p;
6296     char_u	*prevp;
6297     unsigned	flag;
6298     compitem_T	*ci;
6299     int		id;
6300     int		len;
6301     char_u	*tp;
6302     char_u	key[AH_KEY_LEN];
6303     hashitem_T	*hi;
6304 
6305     /* Make room for the old and the new compflags, concatenated with a / in
6306      * between.  Processing it makes it shorter, but we don't know by how
6307      * much, thus allocate the maximum. */
6308     len = (int)STRLEN(compflags) + 1;
6309     if (spin->si_compflags != NULL)
6310 	len += (int)STRLEN(spin->si_compflags) + 1;
6311     p = getroom(spin, len, FALSE);
6312     if (p == NULL)
6313 	return;
6314     if (spin->si_compflags != NULL)
6315     {
6316 	STRCPY(p, spin->si_compflags);
6317 	STRCAT(p, "/");
6318     }
6319     spin->si_compflags = p;
6320     tp = p + STRLEN(p);
6321 
6322     for (p = compflags; *p != NUL; )
6323     {
6324 	if (vim_strchr((char_u *)"/?*+[]", *p) != NULL)
6325 	    /* Copy non-flag characters directly. */
6326 	    *tp++ = *p++;
6327 	else
6328 	{
6329 	    /* First get the flag number, also checks validity. */
6330 	    prevp = p;
6331 	    flag = get_affitem(aff->af_flagtype, &p);
6332 	    if (flag != 0)
6333 	    {
6334 		/* Find the flag in the hashtable.  If it was used before, use
6335 		 * the existing ID.  Otherwise add a new entry. */
6336 		vim_strncpy(key, prevp, p - prevp);
6337 		hi = hash_find(&aff->af_comp, key);
6338 		if (!HASHITEM_EMPTY(hi))
6339 		    id = HI2CI(hi)->ci_newID;
6340 		else
6341 		{
6342 		    ci = (compitem_T *)getroom(spin, sizeof(compitem_T), TRUE);
6343 		    if (ci == NULL)
6344 			break;
6345 		    STRCPY(ci->ci_key, key);
6346 		    ci->ci_flag = flag;
6347 		    /* Avoid using a flag ID that has a special meaning in a
6348 		     * regexp (also inside []). */
6349 		    do
6350 		    {
6351 			check_renumber(spin);
6352 			id = spin->si_newcompID--;
6353 		    } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL);
6354 		    ci->ci_newID = id;
6355 		    hash_add(&aff->af_comp, ci->ci_key);
6356 		}
6357 		*tp++ = id;
6358 	    }
6359 	    if (aff->af_flagtype == AFT_NUM && *p == ',')
6360 		++p;
6361 	}
6362     }
6363 
6364     *tp = NUL;
6365 }
6366 
6367 /*
6368  * Check that the new IDs for postponed affixes and compounding don't overrun
6369  * each other.  We have almost 255 available, but start at 0-127 to avoid
6370  * using two bytes for utf-8.  When the 0-127 range is used up go to 128-255.
6371  * When that is used up an error message is given.
6372  */
6373     static void
6374 check_renumber(spin)
6375     spellinfo_T	*spin;
6376 {
6377     if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128)
6378     {
6379 	spin->si_newprefID = 127;
6380 	spin->si_newcompID = 255;
6381     }
6382 }
6383 
6384 /*
6385  * Return TRUE if flag "flag" appears in affix list "afflist".
6386  */
6387     static int
6388 flag_in_afflist(flagtype, afflist, flag)
6389     int		flagtype;
6390     char_u	*afflist;
6391     unsigned	flag;
6392 {
6393     char_u	*p;
6394     unsigned	n;
6395 
6396     switch (flagtype)
6397     {
6398 	case AFT_CHAR:
6399 	    return vim_strchr(afflist, flag) != NULL;
6400 
6401 	case AFT_CAPLONG:
6402 	case AFT_LONG:
6403 	    for (p = afflist; *p != NUL; )
6404 	    {
6405 #ifdef FEAT_MBYTE
6406 		n = mb_ptr2char_adv(&p);
6407 #else
6408 		n = *p++;
6409 #endif
6410 		if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
6411 								 && *p != NUL)
6412 #ifdef FEAT_MBYTE
6413 		    n = mb_ptr2char_adv(&p) + (n << 16);
6414 #else
6415 		    n = *p++ + (n << 16);
6416 #endif
6417 		if (n == flag)
6418 		    return TRUE;
6419 	    }
6420 	    break;
6421 
6422 	case AFT_NUM:
6423 	    for (p = afflist; *p != NUL; )
6424 	    {
6425 		n = getdigits(&p);
6426 		if (n == flag)
6427 		    return TRUE;
6428 		if (*p != NUL)	/* skip over comma */
6429 		    ++p;
6430 	    }
6431 	    break;
6432     }
6433     return FALSE;
6434 }
6435 
6436 /*
6437  * Give a warning when "spinval" and "affval" numbers are set and not the same.
6438  */
6439     static void
6440 aff_check_number(spinval, affval, name)
6441     int	    spinval;
6442     int	    affval;
6443     char    *name;
6444 {
6445     if (spinval != 0 && spinval != affval)
6446 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
6447 }
6448 
6449 /*
6450  * Give a warning when "spinval" and "affval" strings are set and not the same.
6451  */
6452     static void
6453 aff_check_string(spinval, affval, name)
6454     char_u	*spinval;
6455     char_u	*affval;
6456     char	*name;
6457 {
6458     if (spinval != NULL && STRCMP(spinval, affval) != 0)
6459 	smsg((char_u *)_("%s value differs from what is used in another .aff file"), name);
6460 }
6461 
6462 /*
6463  * Return TRUE if strings "s1" and "s2" are equal.  Also consider both being
6464  * NULL as equal.
6465  */
6466     static int
6467 str_equal(s1, s2)
6468     char_u	*s1;
6469     char_u	*s2;
6470 {
6471     if (s1 == NULL || s2 == NULL)
6472 	return s1 == s2;
6473     return STRCMP(s1, s2) == 0;
6474 }
6475 
6476 /*
6477  * Add a from-to item to "gap".  Used for REP and SAL items.
6478  * They are stored case-folded.
6479  */
6480     static void
6481 add_fromto(spin, gap, from, to)
6482     spellinfo_T	*spin;
6483     garray_T	*gap;
6484     char_u	*from;
6485     char_u	*to;
6486 {
6487     fromto_T	*ftp;
6488     char_u	word[MAXWLEN];
6489 
6490     if (ga_grow(gap, 1) == OK)
6491     {
6492 	ftp = ((fromto_T *)gap->ga_data) + gap->ga_len;
6493 	(void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN);
6494 	ftp->ft_from = getroom_save(spin, word);
6495 	(void)spell_casefold(to, (int)STRLEN(to), word, MAXWLEN);
6496 	ftp->ft_to = getroom_save(spin, word);
6497 	++gap->ga_len;
6498     }
6499 }
6500 
6501 /*
6502  * Convert a boolean argument in a SAL line to TRUE or FALSE;
6503  */
6504     static int
6505 sal_to_bool(s)
6506     char_u	*s;
6507 {
6508     return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0;
6509 }
6510 
6511 /*
6512  * Free the structure filled by spell_read_aff().
6513  */
6514     static void
6515 spell_free_aff(aff)
6516     afffile_T	*aff;
6517 {
6518     hashtab_T	*ht;
6519     hashitem_T	*hi;
6520     int		todo;
6521     affheader_T	*ah;
6522     affentry_T	*ae;
6523 
6524     vim_free(aff->af_enc);
6525 
6526     /* All this trouble to free the "ae_prog" items... */
6527     for (ht = &aff->af_pref; ; ht = &aff->af_suff)
6528     {
6529 	todo = (int)ht->ht_used;
6530 	for (hi = ht->ht_array; todo > 0; ++hi)
6531 	{
6532 	    if (!HASHITEM_EMPTY(hi))
6533 	    {
6534 		--todo;
6535 		ah = HI2AH(hi);
6536 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
6537 		    vim_regfree(ae->ae_prog);
6538 	    }
6539 	}
6540 	if (ht == &aff->af_suff)
6541 	    break;
6542     }
6543 
6544     hash_clear(&aff->af_pref);
6545     hash_clear(&aff->af_suff);
6546     hash_clear(&aff->af_comp);
6547 }
6548 
6549 /*
6550  * Read dictionary file "fname".
6551  * Returns OK or FAIL;
6552  */
6553     static int
6554 spell_read_dic(spin, fname, affile)
6555     spellinfo_T	*spin;
6556     char_u	*fname;
6557     afffile_T	*affile;
6558 {
6559     hashtab_T	ht;
6560     char_u	line[MAXLINELEN];
6561     char_u	*p;
6562     char_u	*afflist;
6563     char_u	store_afflist[MAXWLEN];
6564     int		pfxlen;
6565     int		need_affix;
6566     char_u	*dw;
6567     char_u	*pc;
6568     char_u	*w;
6569     int		l;
6570     hash_T	hash;
6571     hashitem_T	*hi;
6572     FILE	*fd;
6573     int		lnum = 1;
6574     int		non_ascii = 0;
6575     int		retval = OK;
6576     char_u	message[MAXLINELEN + MAXWLEN];
6577     int		flags;
6578     int		duplicate = 0;
6579 
6580     /*
6581      * Open the file.
6582      */
6583     fd = mch_fopen((char *)fname, "r");
6584     if (fd == NULL)
6585     {
6586 	EMSG2(_(e_notopen), fname);
6587 	return FAIL;
6588     }
6589 
6590     /* The hashtable is only used to detect duplicated words. */
6591     hash_init(&ht);
6592 
6593     vim_snprintf((char *)IObuff, IOSIZE,
6594 				  _("Reading dictionary file %s ..."), fname);
6595     spell_message(spin, IObuff);
6596 
6597     /* start with a message for the first line */
6598     spin->si_msg_count = 999999;
6599 
6600     /* Read and ignore the first line: word count. */
6601     (void)vim_fgets(line, MAXLINELEN, fd);
6602     if (!vim_isdigit(*skipwhite(line)))
6603 	EMSG2(_("E760: No word count in %s"), fname);
6604 
6605     /*
6606      * Read all the lines in the file one by one.
6607      * The words are converted to 'encoding' here, before being added to
6608      * the hashtable.
6609      */
6610     while (!vim_fgets(line, MAXLINELEN, fd) && !got_int)
6611     {
6612 	line_breakcheck();
6613 	++lnum;
6614 	if (line[0] == '#' || line[0] == '/')
6615 	    continue;	/* comment line */
6616 
6617 	/* Remove CR, LF and white space from the end.  White space halfway
6618 	 * the word is kept to allow e.g., "et al.". */
6619 	l = (int)STRLEN(line);
6620 	while (l > 0 && line[l - 1] <= ' ')
6621 	    --l;
6622 	if (l == 0)
6623 	    continue;	/* empty line */
6624 	line[l] = NUL;
6625 
6626 #ifdef FEAT_MBYTE
6627 	/* Convert from "SET" to 'encoding' when needed. */
6628 	if (spin->si_conv.vc_type != CONV_NONE)
6629 	{
6630 	    pc = string_convert(&spin->si_conv, line, NULL);
6631 	    if (pc == NULL)
6632 	    {
6633 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
6634 						       fname, lnum, line);
6635 		continue;
6636 	    }
6637 	    w = pc;
6638 	}
6639 	else
6640 #endif
6641 	{
6642 	    pc = NULL;
6643 	    w = line;
6644 	}
6645 
6646 	/* Truncate the word at the "/", set "afflist" to what follows.
6647 	 * Replace "\/" by "/" and "\\" by "\". */
6648 	afflist = NULL;
6649 	for (p = w; *p != NUL; mb_ptr_adv(p))
6650 	{
6651 	    if (*p == '\\' && (p[1] == '\\' || p[1] == '/'))
6652 		STRMOVE(p, p + 1);
6653 	    else if (*p == '/')
6654 	    {
6655 		*p = NUL;
6656 		afflist = p + 1;
6657 		break;
6658 	    }
6659 	}
6660 
6661 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
6662 	if (spin->si_ascii && has_non_ascii(w))
6663 	{
6664 	    ++non_ascii;
6665 	    vim_free(pc);
6666 	    continue;
6667 	}
6668 
6669 	/* This takes time, print a message every 10000 words. */
6670 	if (spin->si_verbose && spin->si_msg_count > 10000)
6671 	{
6672 	    spin->si_msg_count = 0;
6673 	    vim_snprintf((char *)message, sizeof(message),
6674 		    _("line %6d, word %6d - %s"),
6675 		       lnum, spin->si_foldwcount + spin->si_keepwcount, w);
6676 	    msg_start();
6677 	    msg_puts_long_attr(message, 0);
6678 	    msg_clr_eos();
6679 	    msg_didout = FALSE;
6680 	    msg_col = 0;
6681 	    out_flush();
6682 	}
6683 
6684 	/* Store the word in the hashtable to be able to find duplicates. */
6685 	dw = (char_u *)getroom_save(spin, w);
6686 	if (dw == NULL)
6687 	{
6688 	    retval = FAIL;
6689 	    vim_free(pc);
6690 	    break;
6691 	}
6692 
6693 	hash = hash_hash(dw);
6694 	hi = hash_lookup(&ht, dw, hash);
6695 	if (!HASHITEM_EMPTY(hi))
6696 	{
6697 	    if (p_verbose > 0)
6698 		smsg((char_u *)_("Duplicate word in %s line %d: %s"),
6699 							     fname, lnum, dw);
6700 	    else if (duplicate == 0)
6701 		smsg((char_u *)_("First duplicate word in %s line %d: %s"),
6702 							     fname, lnum, dw);
6703 	    ++duplicate;
6704 	}
6705 	else
6706 	    hash_add_item(&ht, hi, dw, hash);
6707 
6708 	flags = 0;
6709 	store_afflist[0] = NUL;
6710 	pfxlen = 0;
6711 	need_affix = FALSE;
6712 	if (afflist != NULL)
6713 	{
6714 	    /* Extract flags from the affix list. */
6715 	    flags |= get_affix_flags(affile, afflist);
6716 
6717 	    if (affile->af_needaffix != 0 && flag_in_afflist(
6718 			  affile->af_flagtype, afflist, affile->af_needaffix))
6719 		need_affix = TRUE;
6720 
6721 	    if (affile->af_pfxpostpone)
6722 		/* Need to store the list of prefix IDs with the word. */
6723 		pfxlen = get_pfxlist(affile, afflist, store_afflist);
6724 
6725 	    if (spin->si_compflags != NULL)
6726 		/* Need to store the list of compound flags with the word.
6727 		 * Concatenate them to the list of prefix IDs. */
6728 		get_compflags(affile, afflist, store_afflist + pfxlen);
6729 	}
6730 
6731 	/* Add the word to the word tree(s). */
6732 	if (store_word(spin, dw, flags, spin->si_region,
6733 					   store_afflist, need_affix) == FAIL)
6734 	    retval = FAIL;
6735 
6736 	if (afflist != NULL)
6737 	{
6738 	    /* Find all matching suffixes and add the resulting words.
6739 	     * Additionally do matching prefixes that combine. */
6740 	    if (store_aff_word(spin, dw, afflist, affile,
6741 			   &affile->af_suff, &affile->af_pref,
6742 			    CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL)
6743 		retval = FAIL;
6744 
6745 	    /* Find all matching prefixes and add the resulting words. */
6746 	    if (store_aff_word(spin, dw, afflist, affile,
6747 			  &affile->af_pref, NULL,
6748 			    CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL)
6749 		retval = FAIL;
6750 	}
6751 
6752 	vim_free(pc);
6753     }
6754 
6755     if (duplicate > 0)
6756 	smsg((char_u *)_("%d duplicate word(s) in %s"), duplicate, fname);
6757     if (spin->si_ascii && non_ascii > 0)
6758 	smsg((char_u *)_("Ignored %d word(s) with non-ASCII characters in %s"),
6759 							    non_ascii, fname);
6760     hash_clear(&ht);
6761 
6762     fclose(fd);
6763     return retval;
6764 }
6765 
6766 /*
6767  * Check for affix flags in "afflist" that are turned into word flags.
6768  * Return WF_ flags.
6769  */
6770     static int
6771 get_affix_flags(affile, afflist)
6772     afffile_T	*affile;
6773     char_u	*afflist;
6774 {
6775     int		flags = 0;
6776 
6777     if (affile->af_keepcase != 0 && flag_in_afflist(
6778 			   affile->af_flagtype, afflist, affile->af_keepcase))
6779 	flags |= WF_KEEPCAP | WF_FIXCAP;
6780     if (affile->af_rare != 0 && flag_in_afflist(
6781 			       affile->af_flagtype, afflist, affile->af_rare))
6782 	flags |= WF_RARE;
6783     if (affile->af_bad != 0 && flag_in_afflist(
6784 				affile->af_flagtype, afflist, affile->af_bad))
6785 	flags |= WF_BANNED;
6786     if (affile->af_needcomp != 0 && flag_in_afflist(
6787 			   affile->af_flagtype, afflist, affile->af_needcomp))
6788 	flags |= WF_NEEDCOMP;
6789     if (affile->af_comproot != 0 && flag_in_afflist(
6790 			   affile->af_flagtype, afflist, affile->af_comproot))
6791 	flags |= WF_COMPROOT;
6792     if (affile->af_nosuggest != 0 && flag_in_afflist(
6793 			  affile->af_flagtype, afflist, affile->af_nosuggest))
6794 	flags |= WF_NOSUGGEST;
6795     return flags;
6796 }
6797 
6798 /*
6799  * Get the list of prefix IDs from the affix list "afflist".
6800  * Used for PFXPOSTPONE.
6801  * Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
6802  * and return the number of affixes.
6803  */
6804     static int
6805 get_pfxlist(affile, afflist, store_afflist)
6806     afffile_T	*affile;
6807     char_u	*afflist;
6808     char_u	*store_afflist;
6809 {
6810     char_u	*p;
6811     char_u	*prevp;
6812     int		cnt = 0;
6813     int		id;
6814     char_u	key[AH_KEY_LEN];
6815     hashitem_T	*hi;
6816 
6817     for (p = afflist; *p != NUL; )
6818     {
6819 	prevp = p;
6820 	if (get_affitem(affile->af_flagtype, &p) != 0)
6821 	{
6822 	    /* A flag is a postponed prefix flag if it appears in "af_pref"
6823 	     * and it's ID is not zero. */
6824 	    vim_strncpy(key, prevp, p - prevp);
6825 	    hi = hash_find(&affile->af_pref, key);
6826 	    if (!HASHITEM_EMPTY(hi))
6827 	    {
6828 		id = HI2AH(hi)->ah_newID;
6829 		if (id != 0)
6830 		    store_afflist[cnt++] = id;
6831 	    }
6832 	}
6833 	if (affile->af_flagtype == AFT_NUM && *p == ',')
6834 	    ++p;
6835     }
6836 
6837     store_afflist[cnt] = NUL;
6838     return cnt;
6839 }
6840 
6841 /*
6842  * Get the list of compound IDs from the affix list "afflist" that are used
6843  * for compound words.
6844  * Puts the flags in "store_afflist[]".
6845  */
6846     static void
6847 get_compflags(affile, afflist, store_afflist)
6848     afffile_T	*affile;
6849     char_u	*afflist;
6850     char_u	*store_afflist;
6851 {
6852     char_u	*p;
6853     char_u	*prevp;
6854     int		cnt = 0;
6855     char_u	key[AH_KEY_LEN];
6856     hashitem_T	*hi;
6857 
6858     for (p = afflist; *p != NUL; )
6859     {
6860 	prevp = p;
6861 	if (get_affitem(affile->af_flagtype, &p) != 0)
6862 	{
6863 	    /* A flag is a compound flag if it appears in "af_comp". */
6864 	    vim_strncpy(key, prevp, p - prevp);
6865 	    hi = hash_find(&affile->af_comp, key);
6866 	    if (!HASHITEM_EMPTY(hi))
6867 		store_afflist[cnt++] = HI2CI(hi)->ci_newID;
6868 	}
6869 	if (affile->af_flagtype == AFT_NUM && *p == ',')
6870 	    ++p;
6871     }
6872 
6873     store_afflist[cnt] = NUL;
6874 }
6875 
6876 /*
6877  * Apply affixes to a word and store the resulting words.
6878  * "ht" is the hashtable with affentry_T that need to be applied, either
6879  * prefixes or suffixes.
6880  * "xht", when not NULL, is the prefix hashtable, to be used additionally on
6881  * the resulting words for combining affixes.
6882  *
6883  * Returns FAIL when out of memory.
6884  */
6885     static int
6886 store_aff_word(spin, word, afflist, affile, ht, xht, condit, flags,
6887 							      pfxlist, pfxlen)
6888     spellinfo_T	*spin;		/* spell info */
6889     char_u	*word;		/* basic word start */
6890     char_u	*afflist;	/* list of names of supported affixes */
6891     afffile_T	*affile;
6892     hashtab_T	*ht;
6893     hashtab_T	*xht;
6894     int		condit;		/* CONDIT_SUF et al. */
6895     int		flags;		/* flags for the word */
6896     char_u	*pfxlist;	/* list of prefix IDs */
6897     int		pfxlen;		/* nr of flags in "pfxlist" for prefixes, rest
6898 				 * is compound flags */
6899 {
6900     int		todo;
6901     hashitem_T	*hi;
6902     affheader_T	*ah;
6903     affentry_T	*ae;
6904     char_u	newword[MAXWLEN];
6905     int		retval = OK;
6906     int		i, j;
6907     char_u	*p;
6908     int		use_flags;
6909     char_u	*use_pfxlist;
6910     int		use_pfxlen;
6911     int		need_affix;
6912     char_u	store_afflist[MAXWLEN];
6913     char_u	pfx_pfxlist[MAXWLEN];
6914     size_t	wordlen = STRLEN(word);
6915     int		use_condit;
6916 
6917     todo = (int)ht->ht_used;
6918     for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi)
6919     {
6920 	if (!HASHITEM_EMPTY(hi))
6921 	{
6922 	    --todo;
6923 	    ah = HI2AH(hi);
6924 
6925 	    /* Check that the affix combines, if required, and that the word
6926 	     * supports this affix. */
6927 	    if (((condit & CONDIT_COMB) == 0 || ah->ah_combine)
6928 		    && flag_in_afflist(affile->af_flagtype, afflist,
6929 								 ah->ah_flag))
6930 	    {
6931 		/* Loop over all affix entries with this name. */
6932 		for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next)
6933 		{
6934 		    /* Check the condition.  It's not logical to match case
6935 		     * here, but it is required for compatibility with
6936 		     * Myspell.
6937 		     * Another requirement from Myspell is that the chop
6938 		     * string is shorter than the word itself.
6939 		     * For prefixes, when "PFXPOSTPONE" was used, only do
6940 		     * prefixes with a chop string and/or flags.
6941 		     * When a previously added affix had CIRCUMFIX this one
6942 		     * must have it too, if it had not then this one must not
6943 		     * have one either. */
6944 		    if ((xht != NULL || !affile->af_pfxpostpone
6945 				|| ae->ae_chop != NULL
6946 				|| ae->ae_flags != NULL)
6947 			    && (ae->ae_chop == NULL
6948 				|| STRLEN(ae->ae_chop) < wordlen)
6949 			    && (ae->ae_prog == NULL
6950 				|| vim_regexec_prog(&ae->ae_prog, FALSE,
6951 							    word, (colnr_T)0))
6952 			    && (((condit & CONDIT_CFIX) == 0)
6953 				== ((condit & CONDIT_AFF) == 0
6954 				    || ae->ae_flags == NULL
6955 				    || !flag_in_afflist(affile->af_flagtype,
6956 					ae->ae_flags, affile->af_circumfix))))
6957 		    {
6958 			/* Match.  Remove the chop and add the affix. */
6959 			if (xht == NULL)
6960 			{
6961 			    /* prefix: chop/add at the start of the word */
6962 			    if (ae->ae_add == NULL)
6963 				*newword = NUL;
6964 			    else
6965 				vim_strncpy(newword, ae->ae_add, MAXWLEN - 1);
6966 			    p = word;
6967 			    if (ae->ae_chop != NULL)
6968 			    {
6969 				/* Skip chop string. */
6970 #ifdef FEAT_MBYTE
6971 				if (has_mbyte)
6972 				{
6973 				    i = mb_charlen(ae->ae_chop);
6974 				    for ( ; i > 0; --i)
6975 					mb_ptr_adv(p);
6976 				}
6977 				else
6978 #endif
6979 				    p += STRLEN(ae->ae_chop);
6980 			    }
6981 			    STRCAT(newword, p);
6982 			}
6983 			else
6984 			{
6985 			    /* suffix: chop/add at the end of the word */
6986 			    vim_strncpy(newword, word, MAXWLEN - 1);
6987 			    if (ae->ae_chop != NULL)
6988 			    {
6989 				/* Remove chop string. */
6990 				p = newword + STRLEN(newword);
6991 				i = (int)MB_CHARLEN(ae->ae_chop);
6992 				for ( ; i > 0; --i)
6993 				    mb_ptr_back(newword, p);
6994 				*p = NUL;
6995 			    }
6996 			    if (ae->ae_add != NULL)
6997 				STRCAT(newword, ae->ae_add);
6998 			}
6999 
7000 			use_flags = flags;
7001 			use_pfxlist = pfxlist;
7002 			use_pfxlen = pfxlen;
7003 			need_affix = FALSE;
7004 			use_condit = condit | CONDIT_COMB | CONDIT_AFF;
7005 			if (ae->ae_flags != NULL)
7006 			{
7007 			    /* Extract flags from the affix list. */
7008 			    use_flags |= get_affix_flags(affile, ae->ae_flags);
7009 
7010 			    if (affile->af_needaffix != 0 && flag_in_afflist(
7011 					affile->af_flagtype, ae->ae_flags,
7012 							affile->af_needaffix))
7013 				need_affix = TRUE;
7014 
7015 			    /* When there is a CIRCUMFIX flag the other affix
7016 			     * must also have it and we don't add the word
7017 			     * with one affix. */
7018 			    if (affile->af_circumfix != 0 && flag_in_afflist(
7019 					affile->af_flagtype, ae->ae_flags,
7020 							affile->af_circumfix))
7021 			    {
7022 				use_condit |= CONDIT_CFIX;
7023 				if ((condit & CONDIT_CFIX) == 0)
7024 				    need_affix = TRUE;
7025 			    }
7026 
7027 			    if (affile->af_pfxpostpone
7028 						|| spin->si_compflags != NULL)
7029 			    {
7030 				if (affile->af_pfxpostpone)
7031 				    /* Get prefix IDS from the affix list. */
7032 				    use_pfxlen = get_pfxlist(affile,
7033 						 ae->ae_flags, store_afflist);
7034 				else
7035 				    use_pfxlen = 0;
7036 				use_pfxlist = store_afflist;
7037 
7038 				/* Combine the prefix IDs. Avoid adding the
7039 				 * same ID twice. */
7040 				for (i = 0; i < pfxlen; ++i)
7041 				{
7042 				    for (j = 0; j < use_pfxlen; ++j)
7043 					if (pfxlist[i] == use_pfxlist[j])
7044 					    break;
7045 				    if (j == use_pfxlen)
7046 					use_pfxlist[use_pfxlen++] = pfxlist[i];
7047 				}
7048 
7049 				if (spin->si_compflags != NULL)
7050 				    /* Get compound IDS from the affix list. */
7051 				    get_compflags(affile, ae->ae_flags,
7052 						  use_pfxlist + use_pfxlen);
7053 
7054 				/* Combine the list of compound flags.
7055 				 * Concatenate them to the prefix IDs list.
7056 				 * Avoid adding the same ID twice. */
7057 				for (i = pfxlen; pfxlist[i] != NUL; ++i)
7058 				{
7059 				    for (j = use_pfxlen;
7060 						   use_pfxlist[j] != NUL; ++j)
7061 					if (pfxlist[i] == use_pfxlist[j])
7062 					    break;
7063 				    if (use_pfxlist[j] == NUL)
7064 				    {
7065 					use_pfxlist[j++] = pfxlist[i];
7066 					use_pfxlist[j] = NUL;
7067 				    }
7068 				}
7069 			    }
7070 			}
7071 
7072 			/* Obey a "COMPOUNDFORBIDFLAG" of the affix: don't
7073 			 * use the compound flags. */
7074 			if (use_pfxlist != NULL && ae->ae_compforbid)
7075 			{
7076 			    vim_strncpy(pfx_pfxlist, use_pfxlist, use_pfxlen);
7077 			    use_pfxlist = pfx_pfxlist;
7078 			}
7079 
7080 			/* When there are postponed prefixes... */
7081 			if (spin->si_prefroot != NULL
7082 				&& spin->si_prefroot->wn_sibling != NULL)
7083 			{
7084 			    /* ... add a flag to indicate an affix was used. */
7085 			    use_flags |= WF_HAS_AFF;
7086 
7087 			    /* ... don't use a prefix list if combining
7088 			     * affixes is not allowed.  But do use the
7089 			     * compound flags after them. */
7090 			    if (!ah->ah_combine && use_pfxlist != NULL)
7091 				use_pfxlist += use_pfxlen;
7092 			}
7093 
7094 			/* When compounding is supported and there is no
7095 			 * "COMPOUNDPERMITFLAG" then forbid compounding on the
7096 			 * side where the affix is applied. */
7097 			if (spin->si_compflags != NULL && !ae->ae_comppermit)
7098 			{
7099 			    if (xht != NULL)
7100 				use_flags |= WF_NOCOMPAFT;
7101 			    else
7102 				use_flags |= WF_NOCOMPBEF;
7103 			}
7104 
7105 			/* Store the modified word. */
7106 			if (store_word(spin, newword, use_flags,
7107 						 spin->si_region, use_pfxlist,
7108 							  need_affix) == FAIL)
7109 			    retval = FAIL;
7110 
7111 			/* When added a prefix or a first suffix and the affix
7112 			 * has flags may add a(nother) suffix.  RECURSIVE! */
7113 			if ((condit & CONDIT_SUF) && ae->ae_flags != NULL)
7114 			    if (store_aff_word(spin, newword, ae->ae_flags,
7115 					affile, &affile->af_suff, xht,
7116 					   use_condit & (xht == NULL
7117 							? ~0 :  ~CONDIT_SUF),
7118 				      use_flags, use_pfxlist, pfxlen) == FAIL)
7119 				retval = FAIL;
7120 
7121 			/* When added a suffix and combining is allowed also
7122 			 * try adding a prefix additionally.  Both for the
7123 			 * word flags and for the affix flags.  RECURSIVE! */
7124 			if (xht != NULL && ah->ah_combine)
7125 			{
7126 			    if (store_aff_word(spin, newword,
7127 					afflist, affile,
7128 					xht, NULL, use_condit,
7129 					use_flags, use_pfxlist,
7130 					pfxlen) == FAIL
7131 				    || (ae->ae_flags != NULL
7132 					&& store_aff_word(spin, newword,
7133 					    ae->ae_flags, affile,
7134 					    xht, NULL, use_condit,
7135 					    use_flags, use_pfxlist,
7136 					    pfxlen) == FAIL))
7137 				retval = FAIL;
7138 			}
7139 		    }
7140 		}
7141 	    }
7142 	}
7143     }
7144 
7145     return retval;
7146 }
7147 
7148 /*
7149  * Read a file with a list of words.
7150  */
7151     static int
7152 spell_read_wordfile(spin, fname)
7153     spellinfo_T	*spin;
7154     char_u	*fname;
7155 {
7156     FILE	*fd;
7157     long	lnum = 0;
7158     char_u	rline[MAXLINELEN];
7159     char_u	*line;
7160     char_u	*pc = NULL;
7161     char_u	*p;
7162     int		l;
7163     int		retval = OK;
7164     int		did_word = FALSE;
7165     int		non_ascii = 0;
7166     int		flags;
7167     int		regionmask;
7168 
7169     /*
7170      * Open the file.
7171      */
7172     fd = mch_fopen((char *)fname, "r");
7173     if (fd == NULL)
7174     {
7175 	EMSG2(_(e_notopen), fname);
7176 	return FAIL;
7177     }
7178 
7179     vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname);
7180     spell_message(spin, IObuff);
7181 
7182     /*
7183      * Read all the lines in the file one by one.
7184      */
7185     while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
7186     {
7187 	line_breakcheck();
7188 	++lnum;
7189 
7190 	/* Skip comment lines. */
7191 	if (*rline == '#')
7192 	    continue;
7193 
7194 	/* Remove CR, LF and white space from the end. */
7195 	l = (int)STRLEN(rline);
7196 	while (l > 0 && rline[l - 1] <= ' ')
7197 	    --l;
7198 	if (l == 0)
7199 	    continue;	/* empty or blank line */
7200 	rline[l] = NUL;
7201 
7202 	/* Convert from "/encoding={encoding}" to 'encoding' when needed. */
7203 	vim_free(pc);
7204 #ifdef FEAT_MBYTE
7205 	if (spin->si_conv.vc_type != CONV_NONE)
7206 	{
7207 	    pc = string_convert(&spin->si_conv, rline, NULL);
7208 	    if (pc == NULL)
7209 	    {
7210 		smsg((char_u *)_("Conversion failure for word in %s line %d: %s"),
7211 							   fname, lnum, rline);
7212 		continue;
7213 	    }
7214 	    line = pc;
7215 	}
7216 	else
7217 #endif
7218 	{
7219 	    pc = NULL;
7220 	    line = rline;
7221 	}
7222 
7223 	if (*line == '/')
7224 	{
7225 	    ++line;
7226 	    if (STRNCMP(line, "encoding=", 9) == 0)
7227 	    {
7228 		if (spin->si_conv.vc_type != CONV_NONE)
7229 		    smsg((char_u *)_("Duplicate /encoding= line ignored in %s line %d: %s"),
7230 						       fname, lnum, line - 1);
7231 		else if (did_word)
7232 		    smsg((char_u *)_("/encoding= line after word ignored in %s line %d: %s"),
7233 						       fname, lnum, line - 1);
7234 		else
7235 		{
7236 #ifdef FEAT_MBYTE
7237 		    char_u	*enc;
7238 
7239 		    /* Setup for conversion to 'encoding'. */
7240 		    line += 9;
7241 		    enc = enc_canonize(line);
7242 		    if (enc != NULL && !spin->si_ascii
7243 			    && convert_setup(&spin->si_conv, enc,
7244 							       p_enc) == FAIL)
7245 			smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
7246 							  fname, line, p_enc);
7247 		    vim_free(enc);
7248 		    spin->si_conv.vc_fail = TRUE;
7249 #else
7250 		    smsg((char_u *)_("Conversion in %s not supported"), fname);
7251 #endif
7252 		}
7253 		continue;
7254 	    }
7255 
7256 	    if (STRNCMP(line, "regions=", 8) == 0)
7257 	    {
7258 		if (spin->si_region_count > 1)
7259 		    smsg((char_u *)_("Duplicate /regions= line ignored in %s line %d: %s"),
7260 						       fname, lnum, line);
7261 		else
7262 		{
7263 		    line += 8;
7264 		    if (STRLEN(line) > 16)
7265 			smsg((char_u *)_("Too many regions in %s line %d: %s"),
7266 						       fname, lnum, line);
7267 		    else
7268 		    {
7269 			spin->si_region_count = (int)STRLEN(line) / 2;
7270 			STRCPY(spin->si_region_name, line);
7271 
7272 			/* Adjust the mask for a word valid in all regions. */
7273 			spin->si_region = (1 << spin->si_region_count) - 1;
7274 		    }
7275 		}
7276 		continue;
7277 	    }
7278 
7279 	    smsg((char_u *)_("/ line ignored in %s line %d: %s"),
7280 						       fname, lnum, line - 1);
7281 	    continue;
7282 	}
7283 
7284 	flags = 0;
7285 	regionmask = spin->si_region;
7286 
7287 	/* Check for flags and region after a slash. */
7288 	p = vim_strchr(line, '/');
7289 	if (p != NULL)
7290 	{
7291 	    *p++ = NUL;
7292 	    while (*p != NUL)
7293 	    {
7294 		if (*p == '=')		/* keep-case word */
7295 		    flags |= WF_KEEPCAP | WF_FIXCAP;
7296 		else if (*p == '!')	/* Bad, bad, wicked word. */
7297 		    flags |= WF_BANNED;
7298 		else if (*p == '?')	/* Rare word. */
7299 		    flags |= WF_RARE;
7300 		else if (VIM_ISDIGIT(*p)) /* region number(s) */
7301 		{
7302 		    if ((flags & WF_REGION) == 0)   /* first one */
7303 			regionmask = 0;
7304 		    flags |= WF_REGION;
7305 
7306 		    l = *p - '0';
7307 		    if (l > spin->si_region_count)
7308 		    {
7309 			smsg((char_u *)_("Invalid region nr in %s line %d: %s"),
7310 							  fname, lnum, p);
7311 			break;
7312 		    }
7313 		    regionmask |= 1 << (l - 1);
7314 		}
7315 		else
7316 		{
7317 		    smsg((char_u *)_("Unrecognized flags in %s line %d: %s"),
7318 							      fname, lnum, p);
7319 		    break;
7320 		}
7321 		++p;
7322 	    }
7323 	}
7324 
7325 	/* Skip non-ASCII words when "spin->si_ascii" is TRUE. */
7326 	if (spin->si_ascii && has_non_ascii(line))
7327 	{
7328 	    ++non_ascii;
7329 	    continue;
7330 	}
7331 
7332 	/* Normal word: store it. */
7333 	if (store_word(spin, line, flags, regionmask, NULL, FALSE) == FAIL)
7334 	{
7335 	    retval = FAIL;
7336 	    break;
7337 	}
7338 	did_word = TRUE;
7339     }
7340 
7341     vim_free(pc);
7342     fclose(fd);
7343 
7344     if (spin->si_ascii && non_ascii > 0)
7345     {
7346 	vim_snprintf((char *)IObuff, IOSIZE,
7347 		  _("Ignored %d words with non-ASCII characters"), non_ascii);
7348 	spell_message(spin, IObuff);
7349     }
7350 
7351     return retval;
7352 }
7353 
7354 /*
7355  * Get part of an sblock_T, "len" bytes long.
7356  * This avoids calling free() for every little struct we use (and keeping
7357  * track of them).
7358  * The memory is cleared to all zeros.
7359  * Returns NULL when out of memory.
7360  */
7361     static void *
7362 getroom(spin, len, align)
7363     spellinfo_T *spin;
7364     size_t	len;		/* length needed */
7365     int		align;		/* align for pointer */
7366 {
7367     char_u	*p;
7368     sblock_T	*bl = spin->si_blocks;
7369 
7370     if (align && bl != NULL)
7371 	/* Round size up for alignment.  On some systems structures need to be
7372 	 * aligned to the size of a pointer (e.g., SPARC). */
7373 	bl->sb_used = (bl->sb_used + sizeof(char *) - 1)
7374 						      & ~(sizeof(char *) - 1);
7375 
7376     if (bl == NULL || bl->sb_used + len > SBLOCKSIZE)
7377     {
7378 	if (len >= SBLOCKSIZE)
7379 	    bl = NULL;
7380 	else
7381 	    /* Allocate a block of memory. It is not freed until much later. */
7382 	    bl = (sblock_T *)alloc_clear(
7383 				   (unsigned)(sizeof(sblock_T) + SBLOCKSIZE));
7384 	if (bl == NULL)
7385 	{
7386 	    if (!spin->si_did_emsg)
7387 	    {
7388 		EMSG(_("E845: Insufficient memory, word list will be incomplete"));
7389 		spin->si_did_emsg = TRUE;
7390 	    }
7391 	    return NULL;
7392 	}
7393 	bl->sb_next = spin->si_blocks;
7394 	spin->si_blocks = bl;
7395 	bl->sb_used = 0;
7396 	++spin->si_blocks_cnt;
7397     }
7398 
7399     p = bl->sb_data + bl->sb_used;
7400     bl->sb_used += (int)len;
7401 
7402     return p;
7403 }
7404 
7405 /*
7406  * Make a copy of a string into memory allocated with getroom().
7407  * Returns NULL when out of memory.
7408  */
7409     static char_u *
7410 getroom_save(spin, s)
7411     spellinfo_T	*spin;
7412     char_u	*s;
7413 {
7414     char_u	*sc;
7415 
7416     sc = (char_u *)getroom(spin, STRLEN(s) + 1, FALSE);
7417     if (sc != NULL)
7418 	STRCPY(sc, s);
7419     return sc;
7420 }
7421 
7422 
7423 /*
7424  * Free the list of allocated sblock_T.
7425  */
7426     static void
7427 free_blocks(bl)
7428     sblock_T	*bl;
7429 {
7430     sblock_T	*next;
7431 
7432     while (bl != NULL)
7433     {
7434 	next = bl->sb_next;
7435 	vim_free(bl);
7436 	bl = next;
7437     }
7438 }
7439 
7440 /*
7441  * Allocate the root of a word tree.
7442  * Returns NULL when out of memory.
7443  */
7444     static wordnode_T *
7445 wordtree_alloc(spin)
7446     spellinfo_T *spin;
7447 {
7448     return (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
7449 }
7450 
7451 /*
7452  * Store a word in the tree(s).
7453  * Always store it in the case-folded tree.  For a keep-case word this is
7454  * useful when the word can also be used with all caps (no WF_FIXCAP flag) and
7455  * used to find suggestions.
7456  * For a keep-case word also store it in the keep-case tree.
7457  * When "pfxlist" is not NULL store the word for each postponed prefix ID and
7458  * compound flag.
7459  */
7460     static int
7461 store_word(spin, word, flags, region, pfxlist, need_affix)
7462     spellinfo_T	*spin;
7463     char_u	*word;
7464     int		flags;		/* extra flags, WF_BANNED */
7465     int		region;		/* supported region(s) */
7466     char_u	*pfxlist;	/* list of prefix IDs or NULL */
7467     int		need_affix;	/* only store word with affix ID */
7468 {
7469     int		len = (int)STRLEN(word);
7470     int		ct = captype(word, word + len);
7471     char_u	foldword[MAXWLEN];
7472     int		res = OK;
7473     char_u	*p;
7474 
7475     (void)spell_casefold(word, len, foldword, MAXWLEN);
7476     for (p = pfxlist; res == OK; ++p)
7477     {
7478 	if (!need_affix || (p != NULL && *p != NUL))
7479 	    res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
7480 						  region, p == NULL ? 0 : *p);
7481 	if (p == NULL || *p == NUL)
7482 	    break;
7483     }
7484     ++spin->si_foldwcount;
7485 
7486     if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP)))
7487     {
7488 	for (p = pfxlist; res == OK; ++p)
7489 	{
7490 	    if (!need_affix || (p != NULL && *p != NUL))
7491 		res = tree_add_word(spin, word, spin->si_keeproot, flags,
7492 						  region, p == NULL ? 0 : *p);
7493 	    if (p == NULL || *p == NUL)
7494 		break;
7495 	}
7496 	++spin->si_keepwcount;
7497     }
7498     return res;
7499 }
7500 
7501 /*
7502  * Add word "word" to a word tree at "root".
7503  * When "flags" < 0 we are adding to the prefix tree where "flags" is used for
7504  * "rare" and "region" is the condition nr.
7505  * Returns FAIL when out of memory.
7506  */
7507     static int
7508 tree_add_word(spin, word, root, flags, region, affixID)
7509     spellinfo_T	*spin;
7510     char_u	*word;
7511     wordnode_T	*root;
7512     int		flags;
7513     int		region;
7514     int		affixID;
7515 {
7516     wordnode_T	*node = root;
7517     wordnode_T	*np;
7518     wordnode_T	*copyp, **copyprev;
7519     wordnode_T	**prev = NULL;
7520     int		i;
7521 
7522     /* Add each byte of the word to the tree, including the NUL at the end. */
7523     for (i = 0; ; ++i)
7524     {
7525 	/* When there is more than one reference to this node we need to make
7526 	 * a copy, so that we can modify it.  Copy the whole list of siblings
7527 	 * (we don't optimize for a partly shared list of siblings). */
7528 	if (node != NULL && node->wn_refs > 1)
7529 	{
7530 	    --node->wn_refs;
7531 	    copyprev = prev;
7532 	    for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling)
7533 	    {
7534 		/* Allocate a new node and copy the info. */
7535 		np = get_wordnode(spin);
7536 		if (np == NULL)
7537 		    return FAIL;
7538 		np->wn_child = copyp->wn_child;
7539 		if (np->wn_child != NULL)
7540 		    ++np->wn_child->wn_refs;	/* child gets extra ref */
7541 		np->wn_byte = copyp->wn_byte;
7542 		if (np->wn_byte == NUL)
7543 		{
7544 		    np->wn_flags = copyp->wn_flags;
7545 		    np->wn_region = copyp->wn_region;
7546 		    np->wn_affixID = copyp->wn_affixID;
7547 		}
7548 
7549 		/* Link the new node in the list, there will be one ref. */
7550 		np->wn_refs = 1;
7551 		if (copyprev != NULL)
7552 		    *copyprev = np;
7553 		copyprev = &np->wn_sibling;
7554 
7555 		/* Let "node" point to the head of the copied list. */
7556 		if (copyp == node)
7557 		    node = np;
7558 	    }
7559 	}
7560 
7561 	/* Look for the sibling that has the same character.  They are sorted
7562 	 * on byte value, thus stop searching when a sibling is found with a
7563 	 * higher byte value.  For zero bytes (end of word) the sorting is
7564 	 * done on flags and then on affixID. */
7565 	while (node != NULL
7566 		&& (node->wn_byte < word[i]
7567 		    || (node->wn_byte == NUL
7568 			&& (flags < 0
7569 			    ? node->wn_affixID < (unsigned)affixID
7570 			    : (node->wn_flags < (unsigned)(flags & WN_MASK)
7571 				|| (node->wn_flags == (flags & WN_MASK)
7572 				    && (spin->si_sugtree
7573 					? (node->wn_region & 0xffff) < region
7574 					: node->wn_affixID
7575 						    < (unsigned)affixID)))))))
7576 	{
7577 	    prev = &node->wn_sibling;
7578 	    node = *prev;
7579 	}
7580 	if (node == NULL
7581 		|| node->wn_byte != word[i]
7582 		|| (word[i] == NUL
7583 		    && (flags < 0
7584 			|| spin->si_sugtree
7585 			|| node->wn_flags != (flags & WN_MASK)
7586 			|| node->wn_affixID != affixID)))
7587 	{
7588 	    /* Allocate a new node. */
7589 	    np = get_wordnode(spin);
7590 	    if (np == NULL)
7591 		return FAIL;
7592 	    np->wn_byte = word[i];
7593 
7594 	    /* If "node" is NULL this is a new child or the end of the sibling
7595 	     * list: ref count is one.  Otherwise use ref count of sibling and
7596 	     * make ref count of sibling one (matters when inserting in front
7597 	     * of the list of siblings). */
7598 	    if (node == NULL)
7599 		np->wn_refs = 1;
7600 	    else
7601 	    {
7602 		np->wn_refs = node->wn_refs;
7603 		node->wn_refs = 1;
7604 	    }
7605 	    if (prev != NULL)
7606 		*prev = np;
7607 	    np->wn_sibling = node;
7608 	    node = np;
7609 	}
7610 
7611 	if (word[i] == NUL)
7612 	{
7613 	    node->wn_flags = flags;
7614 	    node->wn_region |= region;
7615 	    node->wn_affixID = affixID;
7616 	    break;
7617 	}
7618 	prev = &node->wn_child;
7619 	node = *prev;
7620     }
7621 #ifdef SPELL_PRINTTREE
7622     smsg("Added \"%s\"", word);
7623     spell_print_tree(root->wn_sibling);
7624 #endif
7625 
7626     /* count nr of words added since last message */
7627     ++spin->si_msg_count;
7628 
7629     if (spin->si_compress_cnt > 1)
7630     {
7631 	if (--spin->si_compress_cnt == 1)
7632 	    /* Did enough words to lower the block count limit. */
7633 	    spin->si_blocks_cnt += compress_inc;
7634     }
7635 
7636     /*
7637      * When we have allocated lots of memory we need to compress the word tree
7638      * to free up some room.  But compression is slow, and we might actually
7639      * need that room, thus only compress in the following situations:
7640      * 1. When not compressed before (si_compress_cnt == 0): when using
7641      *    "compress_start" blocks.
7642      * 2. When compressed before and used "compress_inc" blocks before
7643      *    adding "compress_added" words (si_compress_cnt > 1).
7644      * 3. When compressed before, added "compress_added" words
7645      *    (si_compress_cnt == 1) and the number of free nodes drops below the
7646      *    maximum word length.
7647      */
7648 #ifndef SPELL_PRINTTREE
7649     if (spin->si_compress_cnt == 1
7650 	    ? spin->si_free_count < MAXWLEN
7651 	    : spin->si_blocks_cnt >= compress_start)
7652 #endif
7653     {
7654 	/* Decrement the block counter.  The effect is that we compress again
7655 	 * when the freed up room has been used and another "compress_inc"
7656 	 * blocks have been allocated.  Unless "compress_added" words have
7657 	 * been added, then the limit is put back again. */
7658 	spin->si_blocks_cnt -= compress_inc;
7659 	spin->si_compress_cnt = compress_added;
7660 
7661 	if (spin->si_verbose)
7662 	{
7663 	    msg_start();
7664 	    msg_puts((char_u *)_(msg_compressing));
7665 	    msg_clr_eos();
7666 	    msg_didout = FALSE;
7667 	    msg_col = 0;
7668 	    out_flush();
7669 	}
7670 
7671 	/* Compress both trees.  Either they both have many nodes, which makes
7672 	 * compression useful, or one of them is small, which means
7673 	 * compression goes fast.  But when filling the soundfold word tree
7674 	 * there is no keep-case tree. */
7675 	wordtree_compress(spin, spin->si_foldroot);
7676 	if (affixID >= 0)
7677 	    wordtree_compress(spin, spin->si_keeproot);
7678     }
7679 
7680     return OK;
7681 }
7682 
7683 /*
7684  * Check the 'mkspellmem' option.  Return FAIL if it's wrong.
7685  * Sets "sps_flags".
7686  */
7687     int
7688 spell_check_msm()
7689 {
7690     char_u	*p = p_msm;
7691     long	start = 0;
7692     long	incr = 0;
7693     long	added = 0;
7694 
7695     if (!VIM_ISDIGIT(*p))
7696 	return FAIL;
7697     /* block count = (value * 1024) / SBLOCKSIZE (but avoid overflow)*/
7698     start = (getdigits(&p) * 10) / (SBLOCKSIZE / 102);
7699     if (*p != ',')
7700 	return FAIL;
7701     ++p;
7702     if (!VIM_ISDIGIT(*p))
7703 	return FAIL;
7704     incr = (getdigits(&p) * 102) / (SBLOCKSIZE / 10);
7705     if (*p != ',')
7706 	return FAIL;
7707     ++p;
7708     if (!VIM_ISDIGIT(*p))
7709 	return FAIL;
7710     added = getdigits(&p) * 1024;
7711     if (*p != NUL)
7712 	return FAIL;
7713 
7714     if (start == 0 || incr == 0 || added == 0 || incr > start)
7715 	return FAIL;
7716 
7717     compress_start = start;
7718     compress_inc = incr;
7719     compress_added = added;
7720     return OK;
7721 }
7722 
7723 
7724 /*
7725  * Get a wordnode_T, either from the list of previously freed nodes or
7726  * allocate a new one.
7727  * Returns NULL when out of memory.
7728  */
7729     static wordnode_T *
7730 get_wordnode(spin)
7731     spellinfo_T	    *spin;
7732 {
7733     wordnode_T *n;
7734 
7735     if (spin->si_first_free == NULL)
7736 	n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), TRUE);
7737     else
7738     {
7739 	n = spin->si_first_free;
7740 	spin->si_first_free = n->wn_child;
7741 	vim_memset(n, 0, sizeof(wordnode_T));
7742 	--spin->si_free_count;
7743     }
7744 #ifdef SPELL_PRINTTREE
7745     if (n != NULL)
7746 	n->wn_nr = ++spin->si_wordnode_nr;
7747 #endif
7748     return n;
7749 }
7750 
7751 /*
7752  * Decrement the reference count on a node (which is the head of a list of
7753  * siblings).  If the reference count becomes zero free the node and its
7754  * siblings.
7755  * Returns the number of nodes actually freed.
7756  */
7757     static int
7758 deref_wordnode(spin, node)
7759     spellinfo_T *spin;
7760     wordnode_T  *node;
7761 {
7762     wordnode_T	*np;
7763     int		cnt = 0;
7764 
7765     if (--node->wn_refs == 0)
7766     {
7767 	for (np = node; np != NULL; np = np->wn_sibling)
7768 	{
7769 	    if (np->wn_child != NULL)
7770 		cnt += deref_wordnode(spin, np->wn_child);
7771 	    free_wordnode(spin, np);
7772 	    ++cnt;
7773 	}
7774 	++cnt;	    /* length field */
7775     }
7776     return cnt;
7777 }
7778 
7779 /*
7780  * Free a wordnode_T for re-use later.
7781  * Only the "wn_child" field becomes invalid.
7782  */
7783     static void
7784 free_wordnode(spin, n)
7785     spellinfo_T	*spin;
7786     wordnode_T  *n;
7787 {
7788     n->wn_child = spin->si_first_free;
7789     spin->si_first_free = n;
7790     ++spin->si_free_count;
7791 }
7792 
7793 /*
7794  * Compress a tree: find tails that are identical and can be shared.
7795  */
7796     static void
7797 wordtree_compress(spin, root)
7798     spellinfo_T	    *spin;
7799     wordnode_T	    *root;
7800 {
7801     hashtab_T	    ht;
7802     int		    n;
7803     int		    tot = 0;
7804     int		    perc;
7805 
7806     /* Skip the root itself, it's not actually used.  The first sibling is the
7807      * start of the tree. */
7808     if (root->wn_sibling != NULL)
7809     {
7810 	hash_init(&ht);
7811 	n = node_compress(spin, root->wn_sibling, &ht, &tot);
7812 
7813 #ifndef SPELL_PRINTTREE
7814 	if (spin->si_verbose || p_verbose > 2)
7815 #endif
7816 	{
7817 	    if (tot > 1000000)
7818 		perc = (tot - n) / (tot / 100);
7819 	    else if (tot == 0)
7820 		perc = 0;
7821 	    else
7822 		perc = (tot - n) * 100 / tot;
7823 	    vim_snprintf((char *)IObuff, IOSIZE,
7824 			  _("Compressed %d of %d nodes; %d (%d%%) remaining"),
7825 						       n, tot, tot - n, perc);
7826 	    spell_message(spin, IObuff);
7827 	}
7828 #ifdef SPELL_PRINTTREE
7829 	spell_print_tree(root->wn_sibling);
7830 #endif
7831 	hash_clear(&ht);
7832     }
7833 }
7834 
7835 /*
7836  * Compress a node, its siblings and its children, depth first.
7837  * Returns the number of compressed nodes.
7838  */
7839     static int
7840 node_compress(spin, node, ht, tot)
7841     spellinfo_T	*spin;
7842     wordnode_T	*node;
7843     hashtab_T	*ht;
7844     int		*tot;	    /* total count of nodes before compressing,
7845 			       incremented while going through the tree */
7846 {
7847     wordnode_T	*np;
7848     wordnode_T	*tp;
7849     wordnode_T	*child;
7850     hash_T	hash;
7851     hashitem_T	*hi;
7852     int		len = 0;
7853     unsigned	nr, n;
7854     int		compressed = 0;
7855 
7856     /*
7857      * Go through the list of siblings.  Compress each child and then try
7858      * finding an identical child to replace it.
7859      * Note that with "child" we mean not just the node that is pointed to,
7860      * but the whole list of siblings of which the child node is the first.
7861      */
7862     for (np = node; np != NULL && !got_int; np = np->wn_sibling)
7863     {
7864 	++len;
7865 	if ((child = np->wn_child) != NULL)
7866 	{
7867 	    /* Compress the child first.  This fills hashkey. */
7868 	    compressed += node_compress(spin, child, ht, tot);
7869 
7870 	    /* Try to find an identical child. */
7871 	    hash = hash_hash(child->wn_u1.hashkey);
7872 	    hi = hash_lookup(ht, child->wn_u1.hashkey, hash);
7873 	    if (!HASHITEM_EMPTY(hi))
7874 	    {
7875 		/* There are children we encountered before with a hash value
7876 		 * identical to the current child.  Now check if there is one
7877 		 * that is really identical. */
7878 		for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next)
7879 		    if (node_equal(child, tp))
7880 		    {
7881 			/* Found one!  Now use that child in place of the
7882 			 * current one.  This means the current child and all
7883 			 * its siblings is unlinked from the tree. */
7884 			++tp->wn_refs;
7885 			compressed += deref_wordnode(spin, child);
7886 			np->wn_child = tp;
7887 			break;
7888 		    }
7889 		if (tp == NULL)
7890 		{
7891 		    /* No other child with this hash value equals the child of
7892 		     * the node, add it to the linked list after the first
7893 		     * item. */
7894 		    tp = HI2WN(hi);
7895 		    child->wn_u2.next = tp->wn_u2.next;
7896 		    tp->wn_u2.next = child;
7897 		}
7898 	    }
7899 	    else
7900 		/* No other child has this hash value, add it to the
7901 		 * hashtable. */
7902 		hash_add_item(ht, hi, child->wn_u1.hashkey, hash);
7903 	}
7904     }
7905     *tot += len + 1;	/* add one for the node that stores the length */
7906 
7907     /*
7908      * Make a hash key for the node and its siblings, so that we can quickly
7909      * find a lookalike node.  This must be done after compressing the sibling
7910      * list, otherwise the hash key would become invalid by the compression.
7911      */
7912     node->wn_u1.hashkey[0] = len;
7913     nr = 0;
7914     for (np = node; np != NULL; np = np->wn_sibling)
7915     {
7916 	if (np->wn_byte == NUL)
7917 	    /* end node: use wn_flags, wn_region and wn_affixID */
7918 	    n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16);
7919 	else
7920 	    /* byte node: use the byte value and the child pointer */
7921 	    n = (unsigned)(np->wn_byte + ((long_u)np->wn_child << 8));
7922 	nr = nr * 101 + n;
7923     }
7924 
7925     /* Avoid NUL bytes, it terminates the hash key. */
7926     n = nr & 0xff;
7927     node->wn_u1.hashkey[1] = n == 0 ? 1 : n;
7928     n = (nr >> 8) & 0xff;
7929     node->wn_u1.hashkey[2] = n == 0 ? 1 : n;
7930     n = (nr >> 16) & 0xff;
7931     node->wn_u1.hashkey[3] = n == 0 ? 1 : n;
7932     n = (nr >> 24) & 0xff;
7933     node->wn_u1.hashkey[4] = n == 0 ? 1 : n;
7934     node->wn_u1.hashkey[5] = NUL;
7935 
7936     /* Check for CTRL-C pressed now and then. */
7937     fast_breakcheck();
7938 
7939     return compressed;
7940 }
7941 
7942 /*
7943  * Return TRUE when two nodes have identical siblings and children.
7944  */
7945     static int
7946 node_equal(n1, n2)
7947     wordnode_T	*n1;
7948     wordnode_T	*n2;
7949 {
7950     wordnode_T	*p1;
7951     wordnode_T	*p2;
7952 
7953     for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL;
7954 				     p1 = p1->wn_sibling, p2 = p2->wn_sibling)
7955 	if (p1->wn_byte != p2->wn_byte
7956 		|| (p1->wn_byte == NUL
7957 		    ? (p1->wn_flags != p2->wn_flags
7958 			|| p1->wn_region != p2->wn_region
7959 			|| p1->wn_affixID != p2->wn_affixID)
7960 		    : (p1->wn_child != p2->wn_child)))
7961 	    break;
7962 
7963     return p1 == NULL && p2 == NULL;
7964 }
7965 
7966 static int
7967 #ifdef __BORLANDC__
7968 _RTLENTRYF
7969 #endif
7970 rep_compare __ARGS((const void *s1, const void *s2));
7971 
7972 /*
7973  * Function given to qsort() to sort the REP items on "from" string.
7974  */
7975     static int
7976 #ifdef __BORLANDC__
7977 _RTLENTRYF
7978 #endif
7979 rep_compare(s1, s2)
7980     const void	*s1;
7981     const void	*s2;
7982 {
7983     fromto_T	*p1 = (fromto_T *)s1;
7984     fromto_T	*p2 = (fromto_T *)s2;
7985 
7986     return STRCMP(p1->ft_from, p2->ft_from);
7987 }
7988 
7989 /*
7990  * Write the Vim .spl file "fname".
7991  * Return FAIL or OK;
7992  */
7993     static int
7994 write_vim_spell(spin, fname)
7995     spellinfo_T	*spin;
7996     char_u	*fname;
7997 {
7998     FILE	*fd;
7999     int		regionmask;
8000     int		round;
8001     wordnode_T	*tree;
8002     int		nodecount;
8003     int		i;
8004     int		l;
8005     garray_T	*gap;
8006     fromto_T	*ftp;
8007     char_u	*p;
8008     int		rr;
8009     int		retval = OK;
8010     size_t	fwv = 1;  /* collect return value of fwrite() to avoid
8011 			     warnings from picky compiler */
8012 
8013     fd = mch_fopen((char *)fname, "w");
8014     if (fd == NULL)
8015     {
8016 	EMSG2(_(e_notopen), fname);
8017 	return FAIL;
8018     }
8019 
8020     /* <HEADER>: <fileID> <versionnr> */
8021 							    /* <fileID> */
8022     fwv &= fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd);
8023     if (fwv != (size_t)1)
8024 	/* Catch first write error, don't try writing more. */
8025 	goto theend;
8026 
8027     putc(VIMSPELLVERSION, fd);				    /* <versionnr> */
8028 
8029     /*
8030      * <SECTIONS>: <section> ... <sectionend>
8031      */
8032 
8033     /* SN_INFO: <infotext> */
8034     if (spin->si_info != NULL)
8035     {
8036 	putc(SN_INFO, fd);				/* <sectionID> */
8037 	putc(0, fd);					/* <sectionflags> */
8038 
8039 	i = (int)STRLEN(spin->si_info);
8040 	put_bytes(fd, (long_u)i, 4);			/* <sectionlen> */
8041 	fwv &= fwrite(spin->si_info, (size_t)i, (size_t)1, fd); /* <infotext> */
8042     }
8043 
8044     /* SN_REGION: <regionname> ...
8045      * Write the region names only if there is more than one. */
8046     if (spin->si_region_count > 1)
8047     {
8048 	putc(SN_REGION, fd);				/* <sectionID> */
8049 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8050 	l = spin->si_region_count * 2;
8051 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8052 	fwv &= fwrite(spin->si_region_name, (size_t)l, (size_t)1, fd);
8053 							/* <regionname> ... */
8054 	regionmask = (1 << spin->si_region_count) - 1;
8055     }
8056     else
8057 	regionmask = 0;
8058 
8059     /* SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars>
8060      *
8061      * The table with character flags and the table for case folding.
8062      * This makes sure the same characters are recognized as word characters
8063      * when generating an when using a spell file.
8064      * Skip this for ASCII, the table may conflict with the one used for
8065      * 'encoding'.
8066      * Also skip this for an .add.spl file, the main spell file must contain
8067      * the table (avoids that it conflicts).  File is shorter too.
8068      */
8069     if (!spin->si_ascii && !spin->si_add)
8070     {
8071 	char_u	folchars[128 * 8];
8072 	int	flags;
8073 
8074 	putc(SN_CHARFLAGS, fd);				/* <sectionID> */
8075 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8076 
8077 	/* Form the <folchars> string first, we need to know its length. */
8078 	l = 0;
8079 	for (i = 128; i < 256; ++i)
8080 	{
8081 #ifdef FEAT_MBYTE
8082 	    if (has_mbyte)
8083 		l += mb_char2bytes(spelltab.st_fold[i], folchars + l);
8084 	    else
8085 #endif
8086 		folchars[l++] = spelltab.st_fold[i];
8087 	}
8088 	put_bytes(fd, (long_u)(1 + 128 + 2 + l), 4);	/* <sectionlen> */
8089 
8090 	fputc(128, fd);					/* <charflagslen> */
8091 	for (i = 128; i < 256; ++i)
8092 	{
8093 	    flags = 0;
8094 	    if (spelltab.st_isw[i])
8095 		flags |= CF_WORD;
8096 	    if (spelltab.st_isu[i])
8097 		flags |= CF_UPPER;
8098 	    fputc(flags, fd);				/* <charflags> */
8099 	}
8100 
8101 	put_bytes(fd, (long_u)l, 2);			/* <folcharslen> */
8102 	fwv &= fwrite(folchars, (size_t)l, (size_t)1, fd); /* <folchars> */
8103     }
8104 
8105     /* SN_MIDWORD: <midword> */
8106     if (spin->si_midword != NULL)
8107     {
8108 	putc(SN_MIDWORD, fd);				/* <sectionID> */
8109 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8110 
8111 	i = (int)STRLEN(spin->si_midword);
8112 	put_bytes(fd, (long_u)i, 4);			/* <sectionlen> */
8113 	fwv &= fwrite(spin->si_midword, (size_t)i, (size_t)1, fd);
8114 							/* <midword> */
8115     }
8116 
8117     /* SN_PREFCOND: <prefcondcnt> <prefcond> ... */
8118     if (spin->si_prefcond.ga_len > 0)
8119     {
8120 	putc(SN_PREFCOND, fd);				/* <sectionID> */
8121 	putc(SNF_REQUIRED, fd);				/* <sectionflags> */
8122 
8123 	l = write_spell_prefcond(NULL, &spin->si_prefcond);
8124 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8125 
8126 	write_spell_prefcond(fd, &spin->si_prefcond);
8127     }
8128 
8129     /* SN_REP: <repcount> <rep> ...
8130      * SN_SAL: <salflags> <salcount> <sal> ...
8131      * SN_REPSAL: <repcount> <rep> ... */
8132 
8133     /* round 1: SN_REP section
8134      * round 2: SN_SAL section (unless SN_SOFO is used)
8135      * round 3: SN_REPSAL section */
8136     for (round = 1; round <= 3; ++round)
8137     {
8138 	if (round == 1)
8139 	    gap = &spin->si_rep;
8140 	else if (round == 2)
8141 	{
8142 	    /* Don't write SN_SAL when using a SN_SOFO section */
8143 	    if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
8144 		continue;
8145 	    gap = &spin->si_sal;
8146 	}
8147 	else
8148 	    gap = &spin->si_repsal;
8149 
8150 	/* Don't write the section if there are no items. */
8151 	if (gap->ga_len == 0)
8152 	    continue;
8153 
8154 	/* Sort the REP/REPSAL items. */
8155 	if (round != 2)
8156 	    qsort(gap->ga_data, (size_t)gap->ga_len,
8157 					       sizeof(fromto_T), rep_compare);
8158 
8159 	i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL);
8160 	putc(i, fd);					/* <sectionID> */
8161 
8162 	/* This is for making suggestions, section is not required. */
8163 	putc(0, fd);					/* <sectionflags> */
8164 
8165 	/* Compute the length of what follows. */
8166 	l = 2;	    /* count <repcount> or <salcount> */
8167 	for (i = 0; i < gap->ga_len; ++i)
8168 	{
8169 	    ftp = &((fromto_T *)gap->ga_data)[i];
8170 	    l += 1 + (int)STRLEN(ftp->ft_from);  /* count <*fromlen> and <*from> */
8171 	    l += 1 + (int)STRLEN(ftp->ft_to);    /* count <*tolen> and <*to> */
8172 	}
8173 	if (round == 2)
8174 	    ++l;	/* count <salflags> */
8175 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8176 
8177 	if (round == 2)
8178 	{
8179 	    i = 0;
8180 	    if (spin->si_followup)
8181 		i |= SAL_F0LLOWUP;
8182 	    if (spin->si_collapse)
8183 		i |= SAL_COLLAPSE;
8184 	    if (spin->si_rem_accents)
8185 		i |= SAL_REM_ACCENTS;
8186 	    putc(i, fd);			/* <salflags> */
8187 	}
8188 
8189 	put_bytes(fd, (long_u)gap->ga_len, 2);	/* <repcount> or <salcount> */
8190 	for (i = 0; i < gap->ga_len; ++i)
8191 	{
8192 	    /* <rep> : <repfromlen> <repfrom> <reptolen> <repto> */
8193 	    /* <sal> : <salfromlen> <salfrom> <saltolen> <salto> */
8194 	    ftp = &((fromto_T *)gap->ga_data)[i];
8195 	    for (rr = 1; rr <= 2; ++rr)
8196 	    {
8197 		p = rr == 1 ? ftp->ft_from : ftp->ft_to;
8198 		l = (int)STRLEN(p);
8199 		putc(l, fd);
8200 		if (l > 0)
8201 		    fwv &= fwrite(p, l, (size_t)1, fd);
8202 	    }
8203 	}
8204 
8205     }
8206 
8207     /* SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto>
8208      * This is for making suggestions, section is not required. */
8209     if (spin->si_sofofr != NULL && spin->si_sofoto != NULL)
8210     {
8211 	putc(SN_SOFO, fd);				/* <sectionID> */
8212 	putc(0, fd);					/* <sectionflags> */
8213 
8214 	l = (int)STRLEN(spin->si_sofofr);
8215 	put_bytes(fd, (long_u)(l + STRLEN(spin->si_sofoto) + 4), 4);
8216 							/* <sectionlen> */
8217 
8218 	put_bytes(fd, (long_u)l, 2);			/* <sofofromlen> */
8219 	fwv &= fwrite(spin->si_sofofr, l, (size_t)1, fd); /* <sofofrom> */
8220 
8221 	l = (int)STRLEN(spin->si_sofoto);
8222 	put_bytes(fd, (long_u)l, 2);			/* <sofotolen> */
8223 	fwv &= fwrite(spin->si_sofoto, l, (size_t)1, fd); /* <sofoto> */
8224     }
8225 
8226     /* SN_WORDS: <word> ...
8227      * This is for making suggestions, section is not required. */
8228     if (spin->si_commonwords.ht_used > 0)
8229     {
8230 	putc(SN_WORDS, fd);				/* <sectionID> */
8231 	putc(0, fd);					/* <sectionflags> */
8232 
8233 	/* round 1: count the bytes
8234 	 * round 2: write the bytes */
8235 	for (round = 1; round <= 2; ++round)
8236 	{
8237 	    int		todo;
8238 	    int		len = 0;
8239 	    hashitem_T	*hi;
8240 
8241 	    todo = (int)spin->si_commonwords.ht_used;
8242 	    for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi)
8243 		if (!HASHITEM_EMPTY(hi))
8244 		{
8245 		    l = (int)STRLEN(hi->hi_key) + 1;
8246 		    len += l;
8247 		    if (round == 2)			/* <word> */
8248 			fwv &= fwrite(hi->hi_key, (size_t)l, (size_t)1, fd);
8249 		    --todo;
8250 		}
8251 	    if (round == 1)
8252 		put_bytes(fd, (long_u)len, 4);		/* <sectionlen> */
8253 	}
8254     }
8255 
8256     /* SN_MAP: <mapstr>
8257      * This is for making suggestions, section is not required. */
8258     if (spin->si_map.ga_len > 0)
8259     {
8260 	putc(SN_MAP, fd);				/* <sectionID> */
8261 	putc(0, fd);					/* <sectionflags> */
8262 	l = spin->si_map.ga_len;
8263 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8264 	fwv &= fwrite(spin->si_map.ga_data, (size_t)l, (size_t)1, fd);
8265 							/* <mapstr> */
8266     }
8267 
8268     /* SN_SUGFILE: <timestamp>
8269      * This is used to notify that a .sug file may be available and at the
8270      * same time allows for checking that a .sug file that is found matches
8271      * with this .spl file.  That's because the word numbers must be exactly
8272      * right. */
8273     if (!spin->si_nosugfile
8274 	    && (spin->si_sal.ga_len > 0
8275 		     || (spin->si_sofofr != NULL && spin->si_sofoto != NULL)))
8276     {
8277 	putc(SN_SUGFILE, fd);				/* <sectionID> */
8278 	putc(0, fd);					/* <sectionflags> */
8279 	put_bytes(fd, (long_u)8, 4);			/* <sectionlen> */
8280 
8281 	/* Set si_sugtime and write it to the file. */
8282 	spin->si_sugtime = time(NULL);
8283 	put_time(fd, spin->si_sugtime);			/* <timestamp> */
8284     }
8285 
8286     /* SN_NOSPLITSUGS: nothing
8287      * This is used to notify that no suggestions with word splits are to be
8288      * made. */
8289     if (spin->si_nosplitsugs)
8290     {
8291 	putc(SN_NOSPLITSUGS, fd);			/* <sectionID> */
8292 	putc(0, fd);					/* <sectionflags> */
8293 	put_bytes(fd, (long_u)0, 4);			/* <sectionlen> */
8294     }
8295 
8296     /* SN_COMPOUND: compound info.
8297      * We don't mark it required, when not supported all compound words will
8298      * be bad words. */
8299     if (spin->si_compflags != NULL)
8300     {
8301 	putc(SN_COMPOUND, fd);				/* <sectionID> */
8302 	putc(0, fd);					/* <sectionflags> */
8303 
8304 	l = (int)STRLEN(spin->si_compflags);
8305 	for (i = 0; i < spin->si_comppat.ga_len; ++i)
8306 	    l += (int)STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1;
8307 	put_bytes(fd, (long_u)(l + 7), 4);		/* <sectionlen> */
8308 
8309 	putc(spin->si_compmax, fd);			/* <compmax> */
8310 	putc(spin->si_compminlen, fd);			/* <compminlen> */
8311 	putc(spin->si_compsylmax, fd);			/* <compsylmax> */
8312 	putc(0, fd);		/* for Vim 7.0b compatibility */
8313 	putc(spin->si_compoptions, fd);			/* <compoptions> */
8314 	put_bytes(fd, (long_u)spin->si_comppat.ga_len, 2);
8315 							/* <comppatcount> */
8316 	for (i = 0; i < spin->si_comppat.ga_len; ++i)
8317 	{
8318 	    p = ((char_u **)(spin->si_comppat.ga_data))[i];
8319 	    putc((int)STRLEN(p), fd);			/* <comppatlen> */
8320 	    fwv &= fwrite(p, (size_t)STRLEN(p), (size_t)1, fd);
8321 							/* <comppattext> */
8322 	}
8323 							/* <compflags> */
8324 	fwv &= fwrite(spin->si_compflags, (size_t)STRLEN(spin->si_compflags),
8325 							       (size_t)1, fd);
8326     }
8327 
8328     /* SN_NOBREAK: NOBREAK flag */
8329     if (spin->si_nobreak)
8330     {
8331 	putc(SN_NOBREAK, fd);				/* <sectionID> */
8332 	putc(0, fd);					/* <sectionflags> */
8333 
8334 	/* It's empty, the presence of the section flags the feature. */
8335 	put_bytes(fd, (long_u)0, 4);			/* <sectionlen> */
8336     }
8337 
8338     /* SN_SYLLABLE: syllable info.
8339      * We don't mark it required, when not supported syllables will not be
8340      * counted. */
8341     if (spin->si_syllable != NULL)
8342     {
8343 	putc(SN_SYLLABLE, fd);				/* <sectionID> */
8344 	putc(0, fd);					/* <sectionflags> */
8345 
8346 	l = (int)STRLEN(spin->si_syllable);
8347 	put_bytes(fd, (long_u)l, 4);			/* <sectionlen> */
8348 	fwv &= fwrite(spin->si_syllable, (size_t)l, (size_t)1, fd);
8349 							/* <syllable> */
8350     }
8351 
8352     /* end of <SECTIONS> */
8353     putc(SN_END, fd);					/* <sectionend> */
8354 
8355 
8356     /*
8357      * <LWORDTREE>  <KWORDTREE>  <PREFIXTREE>
8358      */
8359     spin->si_memtot = 0;
8360     for (round = 1; round <= 3; ++round)
8361     {
8362 	if (round == 1)
8363 	    tree = spin->si_foldroot->wn_sibling;
8364 	else if (round == 2)
8365 	    tree = spin->si_keeproot->wn_sibling;
8366 	else
8367 	    tree = spin->si_prefroot->wn_sibling;
8368 
8369 	/* Clear the index and wnode fields in the tree. */
8370 	clear_node(tree);
8371 
8372 	/* Count the number of nodes.  Needed to be able to allocate the
8373 	 * memory when reading the nodes.  Also fills in index for shared
8374 	 * nodes. */
8375 	nodecount = put_node(NULL, tree, 0, regionmask, round == 3);
8376 
8377 	/* number of nodes in 4 bytes */
8378 	put_bytes(fd, (long_u)nodecount, 4);	/* <nodecount> */
8379 	spin->si_memtot += nodecount + nodecount * sizeof(int);
8380 
8381 	/* Write the nodes. */
8382 	(void)put_node(fd, tree, 0, regionmask, round == 3);
8383     }
8384 
8385     /* Write another byte to check for errors (file system full). */
8386     if (putc(0, fd) == EOF)
8387 	retval = FAIL;
8388 theend:
8389     if (fclose(fd) == EOF)
8390 	retval = FAIL;
8391 
8392     if (fwv != (size_t)1)
8393 	retval = FAIL;
8394     if (retval == FAIL)
8395 	EMSG(_(e_write));
8396 
8397     return retval;
8398 }
8399 
8400 /*
8401  * Clear the index and wnode fields of "node", it siblings and its
8402  * children.  This is needed because they are a union with other items to save
8403  * space.
8404  */
8405     static void
8406 clear_node(node)
8407     wordnode_T	*node;
8408 {
8409     wordnode_T	*np;
8410 
8411     if (node != NULL)
8412 	for (np = node; np != NULL; np = np->wn_sibling)
8413 	{
8414 	    np->wn_u1.index = 0;
8415 	    np->wn_u2.wnode = NULL;
8416 
8417 	    if (np->wn_byte != NUL)
8418 		clear_node(np->wn_child);
8419 	}
8420 }
8421 
8422 
8423 /*
8424  * Dump a word tree at node "node".
8425  *
8426  * This first writes the list of possible bytes (siblings).  Then for each
8427  * byte recursively write the children.
8428  *
8429  * NOTE: The code here must match the code in read_tree_node(), since
8430  * assumptions are made about the indexes (so that we don't have to write them
8431  * in the file).
8432  *
8433  * Returns the number of nodes used.
8434  */
8435     static int
8436 put_node(fd, node, idx, regionmask, prefixtree)
8437     FILE	*fd;		/* NULL when only counting */
8438     wordnode_T	*node;
8439     int		idx;
8440     int		regionmask;
8441     int		prefixtree;	/* TRUE for PREFIXTREE */
8442 {
8443     int		newindex = idx;
8444     int		siblingcount = 0;
8445     wordnode_T	*np;
8446     int		flags;
8447 
8448     /* If "node" is zero the tree is empty. */
8449     if (node == NULL)
8450 	return 0;
8451 
8452     /* Store the index where this node is written. */
8453     node->wn_u1.index = idx;
8454 
8455     /* Count the number of siblings. */
8456     for (np = node; np != NULL; np = np->wn_sibling)
8457 	++siblingcount;
8458 
8459     /* Write the sibling count. */
8460     if (fd != NULL)
8461 	putc(siblingcount, fd);				/* <siblingcount> */
8462 
8463     /* Write each sibling byte and optionally extra info. */
8464     for (np = node; np != NULL; np = np->wn_sibling)
8465     {
8466 	if (np->wn_byte == 0)
8467 	{
8468 	    if (fd != NULL)
8469 	    {
8470 		/* For a NUL byte (end of word) write the flags etc. */
8471 		if (prefixtree)
8472 		{
8473 		    /* In PREFIXTREE write the required affixID and the
8474 		     * associated condition nr (stored in wn_region).  The
8475 		     * byte value is misused to store the "rare" and "not
8476 		     * combining" flags */
8477 		    if (np->wn_flags == (short_u)PFX_FLAGS)
8478 			putc(BY_NOFLAGS, fd);		/* <byte> */
8479 		    else
8480 		    {
8481 			putc(BY_FLAGS, fd);		/* <byte> */
8482 			putc(np->wn_flags, fd);		/* <pflags> */
8483 		    }
8484 		    putc(np->wn_affixID, fd);		/* <affixID> */
8485 		    put_bytes(fd, (long_u)np->wn_region, 2); /* <prefcondnr> */
8486 		}
8487 		else
8488 		{
8489 		    /* For word trees we write the flag/region items. */
8490 		    flags = np->wn_flags;
8491 		    if (regionmask != 0 && np->wn_region != regionmask)
8492 			flags |= WF_REGION;
8493 		    if (np->wn_affixID != 0)
8494 			flags |= WF_AFX;
8495 		    if (flags == 0)
8496 		    {
8497 			/* word without flags or region */
8498 			putc(BY_NOFLAGS, fd);			/* <byte> */
8499 		    }
8500 		    else
8501 		    {
8502 			if (np->wn_flags >= 0x100)
8503 			{
8504 			    putc(BY_FLAGS2, fd);		/* <byte> */
8505 			    putc(flags, fd);			/* <flags> */
8506 			    putc((unsigned)flags >> 8, fd);	/* <flags2> */
8507 			}
8508 			else
8509 			{
8510 			    putc(BY_FLAGS, fd);			/* <byte> */
8511 			    putc(flags, fd);			/* <flags> */
8512 			}
8513 			if (flags & WF_REGION)
8514 			    putc(np->wn_region, fd);		/* <region> */
8515 			if (flags & WF_AFX)
8516 			    putc(np->wn_affixID, fd);		/* <affixID> */
8517 		    }
8518 		}
8519 	    }
8520 	}
8521 	else
8522 	{
8523 	    if (np->wn_child->wn_u1.index != 0
8524 					 && np->wn_child->wn_u2.wnode != node)
8525 	    {
8526 		/* The child is written elsewhere, write the reference. */
8527 		if (fd != NULL)
8528 		{
8529 		    putc(BY_INDEX, fd);			/* <byte> */
8530 							/* <nodeidx> */
8531 		    put_bytes(fd, (long_u)np->wn_child->wn_u1.index, 3);
8532 		}
8533 	    }
8534 	    else if (np->wn_child->wn_u2.wnode == NULL)
8535 		/* We will write the child below and give it an index. */
8536 		np->wn_child->wn_u2.wnode = node;
8537 
8538 	    if (fd != NULL)
8539 		if (putc(np->wn_byte, fd) == EOF) /* <byte> or <xbyte> */
8540 		{
8541 		    EMSG(_(e_write));
8542 		    return 0;
8543 		}
8544 	}
8545     }
8546 
8547     /* Space used in the array when reading: one for each sibling and one for
8548      * the count. */
8549     newindex += siblingcount + 1;
8550 
8551     /* Recursively dump the children of each sibling. */
8552     for (np = node; np != NULL; np = np->wn_sibling)
8553 	if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node)
8554 	    newindex = put_node(fd, np->wn_child, newindex, regionmask,
8555 								  prefixtree);
8556 
8557     return newindex;
8558 }
8559 
8560 
8561 /*
8562  * ":mkspell [-ascii] outfile  infile ..."
8563  * ":mkspell [-ascii] addfile"
8564  */
8565     void
8566 ex_mkspell(eap)
8567     exarg_T *eap;
8568 {
8569     int		fcount;
8570     char_u	**fnames;
8571     char_u	*arg = eap->arg;
8572     int		ascii = FALSE;
8573 
8574     if (STRNCMP(arg, "-ascii", 6) == 0)
8575     {
8576 	ascii = TRUE;
8577 	arg = skipwhite(arg + 6);
8578     }
8579 
8580     /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */
8581     if (get_arglist_exp(arg, &fcount, &fnames, FALSE) == OK)
8582     {
8583 	mkspell(fcount, fnames, ascii, eap->forceit, FALSE);
8584 	FreeWild(fcount, fnames);
8585     }
8586 }
8587 
8588 /*
8589  * Create the .sug file.
8590  * Uses the soundfold info in "spin".
8591  * Writes the file with the name "wfname", with ".spl" changed to ".sug".
8592  */
8593     static void
8594 spell_make_sugfile(spin, wfname)
8595     spellinfo_T	*spin;
8596     char_u	*wfname;
8597 {
8598     char_u	*fname = NULL;
8599     int		len;
8600     slang_T	*slang;
8601     int		free_slang = FALSE;
8602 
8603     /*
8604      * Read back the .spl file that was written.  This fills the required
8605      * info for soundfolding.  This also uses less memory than the
8606      * pointer-linked version of the trie.  And it avoids having two versions
8607      * of the code for the soundfolding stuff.
8608      * It might have been done already by spell_reload_one().
8609      */
8610     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
8611 	if (fullpathcmp(wfname, slang->sl_fname, FALSE) == FPC_SAME)
8612 	    break;
8613     if (slang == NULL)
8614     {
8615 	spell_message(spin, (char_u *)_("Reading back spell file..."));
8616 	slang = spell_load_file(wfname, NULL, NULL, FALSE);
8617 	if (slang == NULL)
8618 	    return;
8619 	free_slang = TRUE;
8620     }
8621 
8622     /*
8623      * Clear the info in "spin" that is used.
8624      */
8625     spin->si_blocks = NULL;
8626     spin->si_blocks_cnt = 0;
8627     spin->si_compress_cnt = 0;	    /* will stay at 0 all the time*/
8628     spin->si_free_count = 0;
8629     spin->si_first_free = NULL;
8630     spin->si_foldwcount = 0;
8631 
8632     /*
8633      * Go through the trie of good words, soundfold each word and add it to
8634      * the soundfold trie.
8635      */
8636     spell_message(spin, (char_u *)_("Performing soundfolding..."));
8637     if (sug_filltree(spin, slang) == FAIL)
8638 	goto theend;
8639 
8640     /*
8641      * Create the table which links each soundfold word with a list of the
8642      * good words it may come from.  Creates buffer "spin->si_spellbuf".
8643      * This also removes the wordnr from the NUL byte entries to make
8644      * compression possible.
8645      */
8646     if (sug_maketable(spin) == FAIL)
8647 	goto theend;
8648 
8649     smsg((char_u *)_("Number of words after soundfolding: %ld"),
8650 				 (long)spin->si_spellbuf->b_ml.ml_line_count);
8651 
8652     /*
8653      * Compress the soundfold trie.
8654      */
8655     spell_message(spin, (char_u *)_(msg_compressing));
8656     wordtree_compress(spin, spin->si_foldroot);
8657 
8658     /*
8659      * Write the .sug file.
8660      * Make the file name by changing ".spl" to ".sug".
8661      */
8662     fname = alloc(MAXPATHL);
8663     if (fname == NULL)
8664 	goto theend;
8665     vim_strncpy(fname, wfname, MAXPATHL - 1);
8666     len = (int)STRLEN(fname);
8667     fname[len - 2] = 'u';
8668     fname[len - 1] = 'g';
8669     sug_write(spin, fname);
8670 
8671 theend:
8672     vim_free(fname);
8673     if (free_slang)
8674 	slang_free(slang);
8675     free_blocks(spin->si_blocks);
8676     close_spellbuf(spin->si_spellbuf);
8677 }
8678 
8679 /*
8680  * Build the soundfold trie for language "slang".
8681  */
8682     static int
8683 sug_filltree(spin, slang)
8684     spellinfo_T	*spin;
8685     slang_T	*slang;
8686 {
8687     char_u	*byts;
8688     idx_T	*idxs;
8689     int		depth;
8690     idx_T	arridx[MAXWLEN];
8691     int		curi[MAXWLEN];
8692     char_u	tword[MAXWLEN];
8693     char_u	tsalword[MAXWLEN];
8694     int		c;
8695     idx_T	n;
8696     unsigned	words_done = 0;
8697     int		wordcount[MAXWLEN];
8698 
8699     /* We use si_foldroot for the soundfolded trie. */
8700     spin->si_foldroot = wordtree_alloc(spin);
8701     if (spin->si_foldroot == NULL)
8702 	return FAIL;
8703 
8704     /* let tree_add_word() know we're adding to the soundfolded tree */
8705     spin->si_sugtree = TRUE;
8706 
8707     /*
8708      * Go through the whole case-folded tree, soundfold each word and put it
8709      * in the trie.
8710      */
8711     byts = slang->sl_fbyts;
8712     idxs = slang->sl_fidxs;
8713 
8714     arridx[0] = 0;
8715     curi[0] = 1;
8716     wordcount[0] = 0;
8717 
8718     depth = 0;
8719     while (depth >= 0 && !got_int)
8720     {
8721 	if (curi[depth] > byts[arridx[depth]])
8722 	{
8723 	    /* Done all bytes at this node, go up one level. */
8724 	    idxs[arridx[depth]] = wordcount[depth];
8725 	    if (depth > 0)
8726 		wordcount[depth - 1] += wordcount[depth];
8727 
8728 	    --depth;
8729 	    line_breakcheck();
8730 	}
8731 	else
8732 	{
8733 
8734 	    /* Do one more byte at this node. */
8735 	    n = arridx[depth] + curi[depth];
8736 	    ++curi[depth];
8737 
8738 	    c = byts[n];
8739 	    if (c == 0)
8740 	    {
8741 		/* Sound-fold the word. */
8742 		tword[depth] = NUL;
8743 		spell_soundfold(slang, tword, TRUE, tsalword);
8744 
8745 		/* We use the "flags" field for the MSB of the wordnr,
8746 		 * "region" for the LSB of the wordnr.  */
8747 		if (tree_add_word(spin, tsalword, spin->si_foldroot,
8748 				words_done >> 16, words_done & 0xffff,
8749 							   0) == FAIL)
8750 		    return FAIL;
8751 
8752 		++words_done;
8753 		++wordcount[depth];
8754 
8755 		/* Reset the block count each time to avoid compression
8756 		 * kicking in. */
8757 		spin->si_blocks_cnt = 0;
8758 
8759 		/* Skip over any other NUL bytes (same word with different
8760 		 * flags). */
8761 		while (byts[n + 1] == 0)
8762 		{
8763 		    ++n;
8764 		    ++curi[depth];
8765 		}
8766 	    }
8767 	    else
8768 	    {
8769 		/* Normal char, go one level deeper. */
8770 		tword[depth++] = c;
8771 		arridx[depth] = idxs[n];
8772 		curi[depth] = 1;
8773 		wordcount[depth] = 0;
8774 	    }
8775 	}
8776     }
8777 
8778     smsg((char_u *)_("Total number of words: %d"), words_done);
8779 
8780     return OK;
8781 }
8782 
8783 /*
8784  * Make the table that links each word in the soundfold trie to the words it
8785  * can be produced from.
8786  * This is not unlike lines in a file, thus use a memfile to be able to access
8787  * the table efficiently.
8788  * Returns FAIL when out of memory.
8789  */
8790     static int
8791 sug_maketable(spin)
8792     spellinfo_T	*spin;
8793 {
8794     garray_T	ga;
8795     int		res = OK;
8796 
8797     /* Allocate a buffer, open a memline for it and create the swap file
8798      * (uses a temp file, not a .swp file). */
8799     spin->si_spellbuf = open_spellbuf();
8800     if (spin->si_spellbuf == NULL)
8801 	return FAIL;
8802 
8803     /* Use a buffer to store the line info, avoids allocating many small
8804      * pieces of memory. */
8805     ga_init2(&ga, 1, 100);
8806 
8807     /* recursively go through the tree */
8808     if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1)
8809 	res = FAIL;
8810 
8811     ga_clear(&ga);
8812     return res;
8813 }
8814 
8815 /*
8816  * Fill the table for one node and its children.
8817  * Returns the wordnr at the start of the node.
8818  * Returns -1 when out of memory.
8819  */
8820     static int
8821 sug_filltable(spin, node, startwordnr, gap)
8822     spellinfo_T	*spin;
8823     wordnode_T	*node;
8824     int		startwordnr;
8825     garray_T	*gap;	    /* place to store line of numbers */
8826 {
8827     wordnode_T	*p, *np;
8828     int		wordnr = startwordnr;
8829     int		nr;
8830     int		prev_nr;
8831 
8832     for (p = node; p != NULL; p = p->wn_sibling)
8833     {
8834 	if (p->wn_byte == NUL)
8835 	{
8836 	    gap->ga_len = 0;
8837 	    prev_nr = 0;
8838 	    for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling)
8839 	    {
8840 		if (ga_grow(gap, 10) == FAIL)
8841 		    return -1;
8842 
8843 		nr = (np->wn_flags << 16) + (np->wn_region & 0xffff);
8844 		/* Compute the offset from the previous nr and store the
8845 		 * offset in a way that it takes a minimum number of bytes.
8846 		 * It's a bit like utf-8, but without the need to mark
8847 		 * following bytes. */
8848 		nr -= prev_nr;
8849 		prev_nr += nr;
8850 		gap->ga_len += offset2bytes(nr,
8851 					 (char_u *)gap->ga_data + gap->ga_len);
8852 	    }
8853 
8854 	    /* add the NUL byte */
8855 	    ((char_u *)gap->ga_data)[gap->ga_len++] = NUL;
8856 
8857 	    if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr,
8858 				     gap->ga_data, gap->ga_len, TRUE) == FAIL)
8859 		return -1;
8860 	    ++wordnr;
8861 
8862 	    /* Remove extra NUL entries, we no longer need them. We don't
8863 	     * bother freeing the nodes, the won't be reused anyway. */
8864 	    while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL)
8865 		p->wn_sibling = p->wn_sibling->wn_sibling;
8866 
8867 	    /* Clear the flags on the remaining NUL node, so that compression
8868 	     * works a lot better. */
8869 	    p->wn_flags = 0;
8870 	    p->wn_region = 0;
8871 	}
8872 	else
8873 	{
8874 	    wordnr = sug_filltable(spin, p->wn_child, wordnr, gap);
8875 	    if (wordnr == -1)
8876 		return -1;
8877 	}
8878     }
8879     return wordnr;
8880 }
8881 
8882 /*
8883  * Convert an offset into a minimal number of bytes.
8884  * Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL
8885  * bytes.
8886  */
8887     static int
8888 offset2bytes(nr, buf)
8889     int	    nr;
8890     char_u  *buf;
8891 {
8892     int	    rem;
8893     int	    b1, b2, b3, b4;
8894 
8895     /* Split the number in parts of base 255.  We need to avoid NUL bytes. */
8896     b1 = nr % 255 + 1;
8897     rem = nr / 255;
8898     b2 = rem % 255 + 1;
8899     rem = rem / 255;
8900     b3 = rem % 255 + 1;
8901     b4 = rem / 255 + 1;
8902 
8903     if (b4 > 1 || b3 > 0x1f)	/* 4 bytes */
8904     {
8905 	buf[0] = 0xe0 + b4;
8906 	buf[1] = b3;
8907 	buf[2] = b2;
8908 	buf[3] = b1;
8909 	return 4;
8910     }
8911     if (b3 > 1 || b2 > 0x3f )	/* 3 bytes */
8912     {
8913 	buf[0] = 0xc0 + b3;
8914 	buf[1] = b2;
8915 	buf[2] = b1;
8916 	return 3;
8917     }
8918     if (b2 > 1 || b1 > 0x7f )	/* 2 bytes */
8919     {
8920 	buf[0] = 0x80 + b2;
8921 	buf[1] = b1;
8922 	return 2;
8923     }
8924 				/* 1 byte */
8925     buf[0] = b1;
8926     return 1;
8927 }
8928 
8929 /*
8930  * Opposite of offset2bytes().
8931  * "pp" points to the bytes and is advanced over it.
8932  * Returns the offset.
8933  */
8934     static int
8935 bytes2offset(pp)
8936     char_u	**pp;
8937 {
8938     char_u	*p = *pp;
8939     int		nr;
8940     int		c;
8941 
8942     c = *p++;
8943     if ((c & 0x80) == 0x00)		/* 1 byte */
8944     {
8945 	nr = c - 1;
8946     }
8947     else if ((c & 0xc0) == 0x80)	/* 2 bytes */
8948     {
8949 	nr = (c & 0x3f) - 1;
8950 	nr = nr * 255 + (*p++ - 1);
8951     }
8952     else if ((c & 0xe0) == 0xc0)	/* 3 bytes */
8953     {
8954 	nr = (c & 0x1f) - 1;
8955 	nr = nr * 255 + (*p++ - 1);
8956 	nr = nr * 255 + (*p++ - 1);
8957     }
8958     else				/* 4 bytes */
8959     {
8960 	nr = (c & 0x0f) - 1;
8961 	nr = nr * 255 + (*p++ - 1);
8962 	nr = nr * 255 + (*p++ - 1);
8963 	nr = nr * 255 + (*p++ - 1);
8964     }
8965 
8966     *pp = p;
8967     return nr;
8968 }
8969 
8970 /*
8971  * Write the .sug file in "fname".
8972  */
8973     static void
8974 sug_write(spin, fname)
8975     spellinfo_T	*spin;
8976     char_u	*fname;
8977 {
8978     FILE	*fd;
8979     wordnode_T	*tree;
8980     int		nodecount;
8981     int		wcount;
8982     char_u	*line;
8983     linenr_T	lnum;
8984     int		len;
8985 
8986     /* Create the file.  Note that an existing file is silently overwritten! */
8987     fd = mch_fopen((char *)fname, "w");
8988     if (fd == NULL)
8989     {
8990 	EMSG2(_(e_notopen), fname);
8991 	return;
8992     }
8993 
8994     vim_snprintf((char *)IObuff, IOSIZE,
8995 				  _("Writing suggestion file %s ..."), fname);
8996     spell_message(spin, IObuff);
8997 
8998     /*
8999      * <SUGHEADER>: <fileID> <versionnr> <timestamp>
9000      */
9001     if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) /* <fileID> */
9002     {
9003 	EMSG(_(e_write));
9004 	goto theend;
9005     }
9006     putc(VIMSUGVERSION, fd);				/* <versionnr> */
9007 
9008     /* Write si_sugtime to the file. */
9009     put_time(fd, spin->si_sugtime);			/* <timestamp> */
9010 
9011     /*
9012      * <SUGWORDTREE>
9013      */
9014     spin->si_memtot = 0;
9015     tree = spin->si_foldroot->wn_sibling;
9016 
9017     /* Clear the index and wnode fields in the tree. */
9018     clear_node(tree);
9019 
9020     /* Count the number of nodes.  Needed to be able to allocate the
9021      * memory when reading the nodes.  Also fills in index for shared
9022      * nodes. */
9023     nodecount = put_node(NULL, tree, 0, 0, FALSE);
9024 
9025     /* number of nodes in 4 bytes */
9026     put_bytes(fd, (long_u)nodecount, 4);	/* <nodecount> */
9027     spin->si_memtot += nodecount + nodecount * sizeof(int);
9028 
9029     /* Write the nodes. */
9030     (void)put_node(fd, tree, 0, 0, FALSE);
9031 
9032     /*
9033      * <SUGTABLE>: <sugwcount> <sugline> ...
9034      */
9035     wcount = spin->si_spellbuf->b_ml.ml_line_count;
9036     put_bytes(fd, (long_u)wcount, 4);	/* <sugwcount> */
9037 
9038     for (lnum = 1; lnum <= (linenr_T)wcount; ++lnum)
9039     {
9040 	/* <sugline>: <sugnr> ... NUL */
9041 	line = ml_get_buf(spin->si_spellbuf, lnum, FALSE);
9042 	len = (int)STRLEN(line) + 1;
9043 	if (fwrite(line, (size_t)len, (size_t)1, fd) == 0)
9044 	{
9045 	    EMSG(_(e_write));
9046 	    goto theend;
9047 	}
9048 	spin->si_memtot += len;
9049     }
9050 
9051     /* Write another byte to check for errors. */
9052     if (putc(0, fd) == EOF)
9053 	EMSG(_(e_write));
9054 
9055     vim_snprintf((char *)IObuff, IOSIZE,
9056 		 _("Estimated runtime memory use: %d bytes"), spin->si_memtot);
9057     spell_message(spin, IObuff);
9058 
9059 theend:
9060     /* close the file */
9061     fclose(fd);
9062 }
9063 
9064 /*
9065  * Open a spell buffer.  This is a nameless buffer that is not in the buffer
9066  * list and only contains text lines.  Can use a swapfile to reduce memory
9067  * use.
9068  * Most other fields are invalid!  Esp. watch out for string options being
9069  * NULL and there is no undo info.
9070  * Returns NULL when out of memory.
9071  */
9072     static buf_T *
9073 open_spellbuf()
9074 {
9075     buf_T	*buf;
9076 
9077     buf = (buf_T *)alloc_clear(sizeof(buf_T));
9078     if (buf != NULL)
9079     {
9080 	buf->b_spell = TRUE;
9081 	buf->b_p_swf = TRUE;	/* may create a swap file */
9082 #ifdef FEAT_CRYPT
9083 	buf->b_p_key = empty_option;
9084 #endif
9085 	ml_open(buf);
9086 	ml_open_file(buf);	/* create swap file now */
9087     }
9088     return buf;
9089 }
9090 
9091 /*
9092  * Close the buffer used for spell info.
9093  */
9094     static void
9095 close_spellbuf(buf)
9096     buf_T	*buf;
9097 {
9098     if (buf != NULL)
9099     {
9100 	ml_close(buf, TRUE);
9101 	vim_free(buf);
9102     }
9103 }
9104 
9105 
9106 /*
9107  * Create a Vim spell file from one or more word lists.
9108  * "fnames[0]" is the output file name.
9109  * "fnames[fcount - 1]" is the last input file name.
9110  * Exception: when "fnames[0]" ends in ".add" it's used as the input file name
9111  * and ".spl" is appended to make the output file name.
9112  */
9113     static void
9114 mkspell(fcount, fnames, ascii, over_write, added_word)
9115     int		fcount;
9116     char_u	**fnames;
9117     int		ascii;		    /* -ascii argument given */
9118     int		over_write;	    /* overwrite existing output file */
9119     int		added_word;	    /* invoked through "zg" */
9120 {
9121     char_u	*fname = NULL;
9122     char_u	*wfname;
9123     char_u	**innames;
9124     int		incount;
9125     afffile_T	*(afile[8]);
9126     int		i;
9127     int		len;
9128     struct stat	st;
9129     int		error = FALSE;
9130     spellinfo_T spin;
9131 
9132     vim_memset(&spin, 0, sizeof(spin));
9133     spin.si_verbose = !added_word;
9134     spin.si_ascii = ascii;
9135     spin.si_followup = TRUE;
9136     spin.si_rem_accents = TRUE;
9137     ga_init2(&spin.si_rep, (int)sizeof(fromto_T), 20);
9138     ga_init2(&spin.si_repsal, (int)sizeof(fromto_T), 20);
9139     ga_init2(&spin.si_sal, (int)sizeof(fromto_T), 20);
9140     ga_init2(&spin.si_map, (int)sizeof(char_u), 100);
9141     ga_init2(&spin.si_comppat, (int)sizeof(char_u *), 20);
9142     ga_init2(&spin.si_prefcond, (int)sizeof(char_u *), 50);
9143     hash_init(&spin.si_commonwords);
9144     spin.si_newcompID = 127;	/* start compound ID at first maximum */
9145 
9146     /* default: fnames[0] is output file, following are input files */
9147     innames = &fnames[1];
9148     incount = fcount - 1;
9149 
9150     wfname = alloc(MAXPATHL);
9151     if (wfname == NULL)
9152 	return;
9153 
9154     if (fcount >= 1)
9155     {
9156 	len = (int)STRLEN(fnames[0]);
9157 	if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0)
9158 	{
9159 	    /* For ":mkspell path/en.latin1.add" output file is
9160 	     * "path/en.latin1.add.spl". */
9161 	    innames = &fnames[0];
9162 	    incount = 1;
9163 	    vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]);
9164 	}
9165 	else if (fcount == 1)
9166 	{
9167 	    /* For ":mkspell path/vim" output file is "path/vim.latin1.spl". */
9168 	    innames = &fnames[0];
9169 	    incount = 1;
9170 	    vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL,
9171 		  fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
9172 	}
9173 	else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0)
9174 	{
9175 	    /* Name ends in ".spl", use as the file name. */
9176 	    vim_strncpy(wfname, fnames[0], MAXPATHL - 1);
9177 	}
9178 	else
9179 	    /* Name should be language, make the file name from it. */
9180 	    vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL,
9181 		  fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
9182 
9183 	/* Check for .ascii.spl. */
9184 	if (strstr((char *)gettail(wfname), SPL_FNAME_ASCII) != NULL)
9185 	    spin.si_ascii = TRUE;
9186 
9187 	/* Check for .add.spl. */
9188 	if (strstr((char *)gettail(wfname), SPL_FNAME_ADD) != NULL)
9189 	    spin.si_add = TRUE;
9190     }
9191 
9192     if (incount <= 0)
9193 	EMSG(_(e_invarg));	/* need at least output and input names */
9194     else if (vim_strchr(gettail(wfname), '_') != NULL)
9195 	EMSG(_("E751: Output file name must not have region name"));
9196     else if (incount > 8)
9197 	EMSG(_("E754: Only up to 8 regions supported"));
9198     else
9199     {
9200 	/* Check for overwriting before doing things that may take a lot of
9201 	 * time. */
9202 	if (!over_write && mch_stat((char *)wfname, &st) >= 0)
9203 	{
9204 	    EMSG(_(e_exists));
9205 	    goto theend;
9206 	}
9207 	if (mch_isdir(wfname))
9208 	{
9209 	    EMSG2(_(e_isadir2), wfname);
9210 	    goto theend;
9211 	}
9212 
9213 	fname = alloc(MAXPATHL);
9214 	if (fname == NULL)
9215 	    goto theend;
9216 
9217 	/*
9218 	 * Init the aff and dic pointers.
9219 	 * Get the region names if there are more than 2 arguments.
9220 	 */
9221 	for (i = 0; i < incount; ++i)
9222 	{
9223 	    afile[i] = NULL;
9224 
9225 	    if (incount > 1)
9226 	    {
9227 		len = (int)STRLEN(innames[i]);
9228 		if (STRLEN(gettail(innames[i])) < 5
9229 						|| innames[i][len - 3] != '_')
9230 		{
9231 		    EMSG2(_("E755: Invalid region in %s"), innames[i]);
9232 		    goto theend;
9233 		}
9234 		spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]);
9235 		spin.si_region_name[i * 2 + 1] =
9236 					     TOLOWER_ASC(innames[i][len - 1]);
9237 	    }
9238 	}
9239 	spin.si_region_count = incount;
9240 
9241 	spin.si_foldroot = wordtree_alloc(&spin);
9242 	spin.si_keeproot = wordtree_alloc(&spin);
9243 	spin.si_prefroot = wordtree_alloc(&spin);
9244 	if (spin.si_foldroot == NULL
9245 		|| spin.si_keeproot == NULL
9246 		|| spin.si_prefroot == NULL)
9247 	{
9248 	    free_blocks(spin.si_blocks);
9249 	    goto theend;
9250 	}
9251 
9252 	/* When not producing a .add.spl file clear the character table when
9253 	 * we encounter one in the .aff file.  This means we dump the current
9254 	 * one in the .spl file if the .aff file doesn't define one.  That's
9255 	 * better than guessing the contents, the table will match a
9256 	 * previously loaded spell file. */
9257 	if (!spin.si_add)
9258 	    spin.si_clear_chartab = TRUE;
9259 
9260 	/*
9261 	 * Read all the .aff and .dic files.
9262 	 * Text is converted to 'encoding'.
9263 	 * Words are stored in the case-folded and keep-case trees.
9264 	 */
9265 	for (i = 0; i < incount && !error; ++i)
9266 	{
9267 	    spin.si_conv.vc_type = CONV_NONE;
9268 	    spin.si_region = 1 << i;
9269 
9270 	    vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]);
9271 	    if (mch_stat((char *)fname, &st) >= 0)
9272 	    {
9273 		/* Read the .aff file.  Will init "spin->si_conv" based on the
9274 		 * "SET" line. */
9275 		afile[i] = spell_read_aff(&spin, fname);
9276 		if (afile[i] == NULL)
9277 		    error = TRUE;
9278 		else
9279 		{
9280 		    /* Read the .dic file and store the words in the trees. */
9281 		    vim_snprintf((char *)fname, MAXPATHL, "%s.dic",
9282 								  innames[i]);
9283 		    if (spell_read_dic(&spin, fname, afile[i]) == FAIL)
9284 			error = TRUE;
9285 		}
9286 	    }
9287 	    else
9288 	    {
9289 		/* No .aff file, try reading the file as a word list.  Store
9290 		 * the words in the trees. */
9291 		if (spell_read_wordfile(&spin, innames[i]) == FAIL)
9292 		    error = TRUE;
9293 	    }
9294 
9295 #ifdef FEAT_MBYTE
9296 	    /* Free any conversion stuff. */
9297 	    convert_setup(&spin.si_conv, NULL, NULL);
9298 #endif
9299 	}
9300 
9301 	if (spin.si_compflags != NULL && spin.si_nobreak)
9302 	    MSG(_("Warning: both compounding and NOBREAK specified"));
9303 
9304 	if (!error && !got_int)
9305 	{
9306 	    /*
9307 	     * Combine tails in the tree.
9308 	     */
9309 	    spell_message(&spin, (char_u *)_(msg_compressing));
9310 	    wordtree_compress(&spin, spin.si_foldroot);
9311 	    wordtree_compress(&spin, spin.si_keeproot);
9312 	    wordtree_compress(&spin, spin.si_prefroot);
9313 	}
9314 
9315 	if (!error && !got_int)
9316 	{
9317 	    /*
9318 	     * Write the info in the spell file.
9319 	     */
9320 	    vim_snprintf((char *)IObuff, IOSIZE,
9321 				      _("Writing spell file %s ..."), wfname);
9322 	    spell_message(&spin, IObuff);
9323 
9324 	    error = write_vim_spell(&spin, wfname) == FAIL;
9325 
9326 	    spell_message(&spin, (char_u *)_("Done!"));
9327 	    vim_snprintf((char *)IObuff, IOSIZE,
9328 		 _("Estimated runtime memory use: %d bytes"), spin.si_memtot);
9329 	    spell_message(&spin, IObuff);
9330 
9331 	    /*
9332 	     * If the file is loaded need to reload it.
9333 	     */
9334 	    if (!error)
9335 		spell_reload_one(wfname, added_word);
9336 	}
9337 
9338 	/* Free the allocated memory. */
9339 	ga_clear(&spin.si_rep);
9340 	ga_clear(&spin.si_repsal);
9341 	ga_clear(&spin.si_sal);
9342 	ga_clear(&spin.si_map);
9343 	ga_clear(&spin.si_comppat);
9344 	ga_clear(&spin.si_prefcond);
9345 	hash_clear_all(&spin.si_commonwords, 0);
9346 
9347 	/* Free the .aff file structures. */
9348 	for (i = 0; i < incount; ++i)
9349 	    if (afile[i] != NULL)
9350 		spell_free_aff(afile[i]);
9351 
9352 	/* Free all the bits and pieces at once. */
9353 	free_blocks(spin.si_blocks);
9354 
9355 	/*
9356 	 * If there is soundfolding info and no NOSUGFILE item create the
9357 	 * .sug file with the soundfolded word trie.
9358 	 */
9359 	if (spin.si_sugtime != 0 && !error && !got_int)
9360 	    spell_make_sugfile(&spin, wfname);
9361 
9362     }
9363 
9364 theend:
9365     vim_free(fname);
9366     vim_free(wfname);
9367 }
9368 
9369 /*
9370  * Display a message for spell file processing when 'verbose' is set or using
9371  * ":mkspell".  "str" can be IObuff.
9372  */
9373     static void
9374 spell_message(spin, str)
9375     spellinfo_T *spin;
9376     char_u	*str;
9377 {
9378     if (spin->si_verbose || p_verbose > 2)
9379     {
9380 	if (!spin->si_verbose)
9381 	    verbose_enter();
9382 	MSG(str);
9383 	out_flush();
9384 	if (!spin->si_verbose)
9385 	    verbose_leave();
9386     }
9387 }
9388 
9389 /*
9390  * ":[count]spellgood  {word}"
9391  * ":[count]spellwrong  {word}"
9392  * ":[count]spellundo  {word}"
9393  */
9394     void
9395 ex_spell(eap)
9396     exarg_T *eap;
9397 {
9398     spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
9399 				   eap->forceit ? 0 : (int)eap->line2,
9400 				   eap->cmdidx == CMD_spellundo);
9401 }
9402 
9403 /*
9404  * Add "word[len]" to 'spellfile' as a good or bad word.
9405  */
9406     void
9407 spell_add_word(word, len, bad, idx, undo)
9408     char_u	*word;
9409     int		len;
9410     int		bad;
9411     int		idx;	    /* "zG" and "zW": zero, otherwise index in
9412 			       'spellfile' */
9413     int		undo;	    /* TRUE for "zug", "zuG", "zuw" and "zuW" */
9414 {
9415     FILE	*fd = NULL;
9416     buf_T	*buf = NULL;
9417     int		new_spf = FALSE;
9418     char_u	*fname;
9419     char_u	*fnamebuf = NULL;
9420     char_u	line[MAXWLEN * 2];
9421     long	fpos, fpos_next = 0;
9422     int		i;
9423     char_u	*spf;
9424 
9425     if (idx == 0)	    /* use internal wordlist */
9426     {
9427 	if (int_wordlist == NULL)
9428 	{
9429 	    int_wordlist = vim_tempname('s', FALSE);
9430 	    if (int_wordlist == NULL)
9431 		return;
9432 	}
9433 	fname = int_wordlist;
9434     }
9435     else
9436     {
9437 	/* If 'spellfile' isn't set figure out a good default value. */
9438 	if (*curwin->w_s->b_p_spf == NUL)
9439 	{
9440 	    init_spellfile();
9441 	    new_spf = TRUE;
9442 	}
9443 
9444 	if (*curwin->w_s->b_p_spf == NUL)
9445 	{
9446 	    EMSG2(_(e_notset), "spellfile");
9447 	    return;
9448 	}
9449 	fnamebuf = alloc(MAXPATHL);
9450 	if (fnamebuf == NULL)
9451 	    return;
9452 
9453 	for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i)
9454 	{
9455 	    copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
9456 	    if (i == idx)
9457 		break;
9458 	    if (*spf == NUL)
9459 	    {
9460 		EMSGN(_("E765: 'spellfile' does not have %ld entries"), idx);
9461 		vim_free(fnamebuf);
9462 		return;
9463 	    }
9464 	}
9465 
9466 	/* Check that the user isn't editing the .add file somewhere. */
9467 	buf = buflist_findname_exp(fnamebuf);
9468 	if (buf != NULL && buf->b_ml.ml_mfp == NULL)
9469 	    buf = NULL;
9470 	if (buf != NULL && bufIsChanged(buf))
9471 	{
9472 	    EMSG(_(e_bufloaded));
9473 	    vim_free(fnamebuf);
9474 	    return;
9475 	}
9476 
9477 	fname = fnamebuf;
9478     }
9479 
9480     if (bad || undo)
9481     {
9482 	/* When the word appears as good word we need to remove that one,
9483 	 * since its flags sort before the one with WF_BANNED. */
9484 	fd = mch_fopen((char *)fname, "r");
9485 	if (fd != NULL)
9486 	{
9487 	    while (!vim_fgets(line, MAXWLEN * 2, fd))
9488 	    {
9489 		fpos = fpos_next;
9490 		fpos_next = ftell(fd);
9491 		if (STRNCMP(word, line, len) == 0
9492 			&& (line[len] == '/' || line[len] < ' '))
9493 		{
9494 		    /* Found duplicate word.  Remove it by writing a '#' at
9495 		     * the start of the line.  Mixing reading and writing
9496 		     * doesn't work for all systems, close the file first. */
9497 		    fclose(fd);
9498 		    fd = mch_fopen((char *)fname, "r+");
9499 		    if (fd == NULL)
9500 			break;
9501 		    if (fseek(fd, fpos, SEEK_SET) == 0)
9502 		    {
9503 			fputc('#', fd);
9504 			if (undo)
9505 			{
9506 			    home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE);
9507 			    smsg((char_u *)_("Word '%.*s' removed from %s"),
9508 							 len, word, NameBuff);
9509 			}
9510 		    }
9511 		    fseek(fd, fpos_next, SEEK_SET);
9512 		}
9513 	    }
9514 	    if (fd != NULL)
9515 		fclose(fd);
9516 	}
9517     }
9518 
9519     if (!undo)
9520     {
9521 	fd = mch_fopen((char *)fname, "a");
9522 	if (fd == NULL && new_spf)
9523 	{
9524 	    char_u *p;
9525 
9526 	    /* We just initialized the 'spellfile' option and can't open the
9527 	     * file.  We may need to create the "spell" directory first.  We
9528 	     * already checked the runtime directory is writable in
9529 	     * init_spellfile(). */
9530 	    if (!dir_of_file_exists(fname) && (p = gettail_sep(fname)) != fname)
9531 	    {
9532 		int c = *p;
9533 
9534 		/* The directory doesn't exist.  Try creating it and opening
9535 		 * the file again. */
9536 		*p = NUL;
9537 		vim_mkdir(fname, 0755);
9538 		*p = c;
9539 		fd = mch_fopen((char *)fname, "a");
9540 	    }
9541 	}
9542 
9543 	if (fd == NULL)
9544 	    EMSG2(_(e_notopen), fname);
9545 	else
9546 	{
9547 	    if (bad)
9548 		fprintf(fd, "%.*s/!\n", len, word);
9549 	    else
9550 		fprintf(fd, "%.*s\n", len, word);
9551 	    fclose(fd);
9552 
9553 	    home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE);
9554 	    smsg((char_u *)_("Word '%.*s' added to %s"), len, word, NameBuff);
9555 	}
9556     }
9557 
9558     if (fd != NULL)
9559     {
9560 	/* Update the .add.spl file. */
9561 	mkspell(1, &fname, FALSE, TRUE, TRUE);
9562 
9563 	/* If the .add file is edited somewhere, reload it. */
9564 	if (buf != NULL)
9565 	    buf_reload(buf, buf->b_orig_mode);
9566 
9567 	redraw_all_later(SOME_VALID);
9568     }
9569     vim_free(fnamebuf);
9570 }
9571 
9572 /*
9573  * Initialize 'spellfile' for the current buffer.
9574  */
9575     static void
9576 init_spellfile()
9577 {
9578     char_u	*buf;
9579     int		l;
9580     char_u	*fname;
9581     char_u	*rtp;
9582     char_u	*lend;
9583     int		aspath = FALSE;
9584     char_u	*lstart = curbuf->b_s.b_p_spl;
9585 
9586     if (*curwin->w_s->b_p_spl != NUL && curwin->w_s->b_langp.ga_len > 0)
9587     {
9588 	buf = alloc(MAXPATHL);
9589 	if (buf == NULL)
9590 	    return;
9591 
9592 	/* Find the end of the language name.  Exclude the region.  If there
9593 	 * is a path separator remember the start of the tail. */
9594 	for (lend = curwin->w_s->b_p_spl; *lend != NUL
9595 			&& vim_strchr((char_u *)",._", *lend) == NULL; ++lend)
9596 	    if (vim_ispathsep(*lend))
9597 	    {
9598 		aspath = TRUE;
9599 		lstart = lend + 1;
9600 	    }
9601 
9602 	/* Loop over all entries in 'runtimepath'.  Use the first one where we
9603 	 * are allowed to write. */
9604 	rtp = p_rtp;
9605 	while (*rtp != NUL)
9606 	{
9607 	    if (aspath)
9608 		/* Use directory of an entry with path, e.g., for
9609 		 * "/dir/lg.utf-8.spl" use "/dir". */
9610 		vim_strncpy(buf, curbuf->b_s.b_p_spl,
9611 					    lstart - curbuf->b_s.b_p_spl - 1);
9612 	    else
9613 		/* Copy the path from 'runtimepath' to buf[]. */
9614 		copy_option_part(&rtp, buf, MAXPATHL, ",");
9615 	    if (filewritable(buf) == 2)
9616 	    {
9617 		/* Use the first language name from 'spelllang' and the
9618 		 * encoding used in the first loaded .spl file. */
9619 		if (aspath)
9620 		    vim_strncpy(buf, curbuf->b_s.b_p_spl,
9621 						  lend - curbuf->b_s.b_p_spl);
9622 		else
9623 		{
9624 		    /* Create the "spell" directory if it doesn't exist yet. */
9625 		    l = (int)STRLEN(buf);
9626 		    vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell");
9627 		    if (filewritable(buf) != 2)
9628 			vim_mkdir(buf, 0755);
9629 
9630 		    l = (int)STRLEN(buf);
9631 		    vim_snprintf((char *)buf + l, MAXPATHL - l,
9632 				 "/%.*s", (int)(lend - lstart), lstart);
9633 		}
9634 		l = (int)STRLEN(buf);
9635 		fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
9636 							 ->lp_slang->sl_fname;
9637 		vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
9638 			fname != NULL
9639 			  && strstr((char *)gettail(fname), ".ascii.") != NULL
9640 				       ? (char_u *)"ascii" : spell_enc());
9641 		set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
9642 		break;
9643 	    }
9644 	    aspath = FALSE;
9645 	}
9646 
9647 	vim_free(buf);
9648     }
9649 }
9650 
9651 
9652 /*
9653  * Init the chartab used for spelling for ASCII.
9654  * EBCDIC is not supported!
9655  */
9656     static void
9657 clear_spell_chartab(sp)
9658     spelltab_T	*sp;
9659 {
9660     int		i;
9661 
9662     /* Init everything to FALSE. */
9663     vim_memset(sp->st_isw, FALSE, sizeof(sp->st_isw));
9664     vim_memset(sp->st_isu, FALSE, sizeof(sp->st_isu));
9665     for (i = 0; i < 256; ++i)
9666     {
9667 	sp->st_fold[i] = i;
9668 	sp->st_upper[i] = i;
9669     }
9670 
9671     /* We include digits.  A word shouldn't start with a digit, but handling
9672      * that is done separately. */
9673     for (i = '0'; i <= '9'; ++i)
9674 	sp->st_isw[i] = TRUE;
9675     for (i = 'A'; i <= 'Z'; ++i)
9676     {
9677 	sp->st_isw[i] = TRUE;
9678 	sp->st_isu[i] = TRUE;
9679 	sp->st_fold[i] = i + 0x20;
9680     }
9681     for (i = 'a'; i <= 'z'; ++i)
9682     {
9683 	sp->st_isw[i] = TRUE;
9684 	sp->st_upper[i] = i - 0x20;
9685     }
9686 }
9687 
9688 /*
9689  * Init the chartab used for spelling.  Only depends on 'encoding'.
9690  * Called once while starting up and when 'encoding' changes.
9691  * The default is to use isalpha(), but the spell file should define the word
9692  * characters to make it possible that 'encoding' differs from the current
9693  * locale.  For utf-8 we don't use isalpha() but our own functions.
9694  */
9695     void
9696 init_spell_chartab()
9697 {
9698     int	    i;
9699 
9700     did_set_spelltab = FALSE;
9701     clear_spell_chartab(&spelltab);
9702 #ifdef FEAT_MBYTE
9703     if (enc_dbcs)
9704     {
9705 	/* DBCS: assume double-wide characters are word characters. */
9706 	for (i = 128; i <= 255; ++i)
9707 	    if (MB_BYTE2LEN(i) == 2)
9708 		spelltab.st_isw[i] = TRUE;
9709     }
9710     else if (enc_utf8)
9711     {
9712 	for (i = 128; i < 256; ++i)
9713 	{
9714 	    int f = utf_fold(i);
9715 	    int u = utf_toupper(i);
9716 
9717 	    spelltab.st_isu[i] = utf_isupper(i);
9718 	    spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i);
9719 	    /* The folded/upper-cased value is different between latin1 and
9720 	     * utf8 for 0xb5, causing E763 for no good reason.  Use the latin1
9721 	     * value for utf-8 to avoid this. */
9722 	    spelltab.st_fold[i] = (f < 256) ? f : i;
9723 	    spelltab.st_upper[i] = (u < 256) ? u : i;
9724 	}
9725     }
9726     else
9727 #endif
9728     {
9729 	/* Rough guess: use locale-dependent library functions. */
9730 	for (i = 128; i < 256; ++i)
9731 	{
9732 	    if (MB_ISUPPER(i))
9733 	    {
9734 		spelltab.st_isw[i] = TRUE;
9735 		spelltab.st_isu[i] = TRUE;
9736 		spelltab.st_fold[i] = MB_TOLOWER(i);
9737 	    }
9738 	    else if (MB_ISLOWER(i))
9739 	    {
9740 		spelltab.st_isw[i] = TRUE;
9741 		spelltab.st_upper[i] = MB_TOUPPER(i);
9742 	    }
9743 	}
9744     }
9745 }
9746 
9747 /*
9748  * Set the spell character tables from strings in the affix file.
9749  */
9750     static int
9751 set_spell_chartab(fol, low, upp)
9752     char_u	*fol;
9753     char_u	*low;
9754     char_u	*upp;
9755 {
9756     /* We build the new tables here first, so that we can compare with the
9757      * previous one. */
9758     spelltab_T	new_st;
9759     char_u	*pf = fol, *pl = low, *pu = upp;
9760     int		f, l, u;
9761 
9762     clear_spell_chartab(&new_st);
9763 
9764     while (*pf != NUL)
9765     {
9766 	if (*pl == NUL || *pu == NUL)
9767 	{
9768 	    EMSG(_(e_affform));
9769 	    return FAIL;
9770 	}
9771 #ifdef FEAT_MBYTE
9772 	f = mb_ptr2char_adv(&pf);
9773 	l = mb_ptr2char_adv(&pl);
9774 	u = mb_ptr2char_adv(&pu);
9775 #else
9776 	f = *pf++;
9777 	l = *pl++;
9778 	u = *pu++;
9779 #endif
9780 	/* Every character that appears is a word character. */
9781 	if (f < 256)
9782 	    new_st.st_isw[f] = TRUE;
9783 	if (l < 256)
9784 	    new_st.st_isw[l] = TRUE;
9785 	if (u < 256)
9786 	    new_st.st_isw[u] = TRUE;
9787 
9788 	/* if "LOW" and "FOL" are not the same the "LOW" char needs
9789 	 * case-folding */
9790 	if (l < 256 && l != f)
9791 	{
9792 	    if (f >= 256)
9793 	    {
9794 		EMSG(_(e_affrange));
9795 		return FAIL;
9796 	    }
9797 	    new_st.st_fold[l] = f;
9798 	}
9799 
9800 	/* if "UPP" and "FOL" are not the same the "UPP" char needs
9801 	 * case-folding, it's upper case and the "UPP" is the upper case of
9802 	 * "FOL" . */
9803 	if (u < 256 && u != f)
9804 	{
9805 	    if (f >= 256)
9806 	    {
9807 		EMSG(_(e_affrange));
9808 		return FAIL;
9809 	    }
9810 	    new_st.st_fold[u] = f;
9811 	    new_st.st_isu[u] = TRUE;
9812 	    new_st.st_upper[f] = u;
9813 	}
9814     }
9815 
9816     if (*pl != NUL || *pu != NUL)
9817     {
9818 	EMSG(_(e_affform));
9819 	return FAIL;
9820     }
9821 
9822     return set_spell_finish(&new_st);
9823 }
9824 
9825 /*
9826  * Set the spell character tables from strings in the .spl file.
9827  */
9828     static void
9829 set_spell_charflags(flags, cnt, fol)
9830     char_u	*flags;
9831     int		cnt;	    /* length of "flags" */
9832     char_u	*fol;
9833 {
9834     /* We build the new tables here first, so that we can compare with the
9835      * previous one. */
9836     spelltab_T	new_st;
9837     int		i;
9838     char_u	*p = fol;
9839     int		c;
9840 
9841     clear_spell_chartab(&new_st);
9842 
9843     for (i = 0; i < 128; ++i)
9844     {
9845 	if (i < cnt)
9846 	{
9847 	    new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0;
9848 	    new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0;
9849 	}
9850 
9851 	if (*p != NUL)
9852 	{
9853 #ifdef FEAT_MBYTE
9854 	    c = mb_ptr2char_adv(&p);
9855 #else
9856 	    c = *p++;
9857 #endif
9858 	    new_st.st_fold[i + 128] = c;
9859 	    if (i + 128 != c && new_st.st_isu[i + 128] && c < 256)
9860 		new_st.st_upper[c] = i + 128;
9861 	}
9862     }
9863 
9864     (void)set_spell_finish(&new_st);
9865 }
9866 
9867     static int
9868 set_spell_finish(new_st)
9869     spelltab_T	*new_st;
9870 {
9871     int		i;
9872 
9873     if (did_set_spelltab)
9874     {
9875 	/* check that it's the same table */
9876 	for (i = 0; i < 256; ++i)
9877 	{
9878 	    if (spelltab.st_isw[i] != new_st->st_isw[i]
9879 		    || spelltab.st_isu[i] != new_st->st_isu[i]
9880 		    || spelltab.st_fold[i] != new_st->st_fold[i]
9881 		    || spelltab.st_upper[i] != new_st->st_upper[i])
9882 	    {
9883 		EMSG(_("E763: Word characters differ between spell files"));
9884 		return FAIL;
9885 	    }
9886 	}
9887     }
9888     else
9889     {
9890 	/* copy the new spelltab into the one being used */
9891 	spelltab = *new_st;
9892 	did_set_spelltab = TRUE;
9893     }
9894 
9895     return OK;
9896 }
9897 
9898 /*
9899  * Return TRUE if "p" points to a word character.
9900  * As a special case we see "midword" characters as word character when it is
9901  * followed by a word character.  This finds they'there but not 'they there'.
9902  * Thus this only works properly when past the first character of the word.
9903  */
9904     static int
9905 spell_iswordp(p, wp)
9906     char_u	*p;
9907     win_T	*wp;	    /* buffer used */
9908 {
9909 #ifdef FEAT_MBYTE
9910     char_u	*s;
9911     int		l;
9912     int		c;
9913 
9914     if (has_mbyte)
9915     {
9916 	l = MB_BYTE2LEN(*p);
9917 	s = p;
9918 	if (l == 1)
9919 	{
9920 	    /* be quick for ASCII */
9921 	    if (wp->w_s->b_spell_ismw[*p])
9922 		s = p + 1;		/* skip a mid-word character */
9923 	}
9924 	else
9925 	{
9926 	    c = mb_ptr2char(p);
9927 	    if (c < 256 ? wp->w_s->b_spell_ismw[c]
9928 		    : (wp->w_s->b_spell_ismw_mb != NULL
9929 			   && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL))
9930 		s = p + l;
9931 	}
9932 
9933 	c = mb_ptr2char(s);
9934 	if (c > 255)
9935 	    return spell_mb_isword_class(mb_get_class(s), wp);
9936 	return spelltab.st_isw[c];
9937     }
9938 #endif
9939 
9940     return spelltab.st_isw[wp->w_s->b_spell_ismw[*p] ? p[1] : p[0]];
9941 }
9942 
9943 /*
9944  * Return TRUE if "p" points to a word character.
9945  * Unlike spell_iswordp() this doesn't check for "midword" characters.
9946  */
9947     static int
9948 spell_iswordp_nmw(p, wp)
9949     char_u	*p;
9950     win_T	*wp;
9951 {
9952 #ifdef FEAT_MBYTE
9953     int		c;
9954 
9955     if (has_mbyte)
9956     {
9957 	c = mb_ptr2char(p);
9958 	if (c > 255)
9959 	    return spell_mb_isword_class(mb_get_class(p), wp);
9960 	return spelltab.st_isw[c];
9961     }
9962 #endif
9963     return spelltab.st_isw[*p];
9964 }
9965 
9966 #ifdef FEAT_MBYTE
9967 /*
9968  * Return TRUE if word class indicates a word character.
9969  * Only for characters above 255.
9970  * Unicode subscript and superscript are not considered word characters.
9971  * See also dbcs_class() and utf_class() in mbyte.c.
9972  */
9973     static int
9974 spell_mb_isword_class(cl, wp)
9975     int		cl;
9976     win_T	*wp;
9977 {
9978     if (wp->w_s->b_cjk)
9979 	/* East Asian characters are not considered word characters. */
9980 	return cl == 2 || cl == 0x2800;
9981     return cl >= 2 && cl != 0x2070 && cl != 0x2080;
9982 }
9983 
9984 /*
9985  * Return TRUE if "p" points to a word character.
9986  * Wide version of spell_iswordp().
9987  */
9988     static int
9989 spell_iswordp_w(p, wp)
9990     int		*p;
9991     win_T	*wp;
9992 {
9993     int		*s;
9994 
9995     if (*p < 256 ? wp->w_s->b_spell_ismw[*p]
9996 		 : (wp->w_s->b_spell_ismw_mb != NULL
9997 			     && vim_strchr(wp->w_s->b_spell_ismw_mb, *p) != NULL))
9998 	s = p + 1;
9999     else
10000 	s = p;
10001 
10002     if (*s > 255)
10003     {
10004 	if (enc_utf8)
10005 	    return spell_mb_isword_class(utf_class(*s), wp);
10006 	if (enc_dbcs)
10007 	    return spell_mb_isword_class(
10008 				dbcs_class((unsigned)*s >> 8, *s & 0xff), wp);
10009 	return 0;
10010     }
10011     return spelltab.st_isw[*s];
10012 }
10013 #endif
10014 
10015 /*
10016  * Write the table with prefix conditions to the .spl file.
10017  * When "fd" is NULL only count the length of what is written.
10018  */
10019     static int
10020 write_spell_prefcond(fd, gap)
10021     FILE	*fd;
10022     garray_T	*gap;
10023 {
10024     int		i;
10025     char_u	*p;
10026     int		len;
10027     int		totlen;
10028     size_t	x = 1;  /* collect return value of fwrite() */
10029 
10030     if (fd != NULL)
10031 	put_bytes(fd, (long_u)gap->ga_len, 2);	    /* <prefcondcnt> */
10032 
10033     totlen = 2 + gap->ga_len; /* length of <prefcondcnt> and <condlen> bytes */
10034 
10035     for (i = 0; i < gap->ga_len; ++i)
10036     {
10037 	/* <prefcond> : <condlen> <condstr> */
10038 	p = ((char_u **)gap->ga_data)[i];
10039 	if (p != NULL)
10040 	{
10041 	    len = (int)STRLEN(p);
10042 	    if (fd != NULL)
10043 	    {
10044 		fputc(len, fd);
10045 		x &= fwrite(p, (size_t)len, (size_t)1, fd);
10046 	    }
10047 	    totlen += len;
10048 	}
10049 	else if (fd != NULL)
10050 	    fputc(0, fd);
10051     }
10052 
10053     return totlen;
10054 }
10055 
10056 /*
10057  * Case-fold "str[len]" into "buf[buflen]".  The result is NUL terminated.
10058  * Uses the character definitions from the .spl file.
10059  * When using a multi-byte 'encoding' the length may change!
10060  * Returns FAIL when something wrong.
10061  */
10062     static int
10063 spell_casefold(str, len, buf, buflen)
10064     char_u	*str;
10065     int		len;
10066     char_u	*buf;
10067     int		buflen;
10068 {
10069     int		i;
10070 
10071     if (len >= buflen)
10072     {
10073 	buf[0] = NUL;
10074 	return FAIL;		/* result will not fit */
10075     }
10076 
10077 #ifdef FEAT_MBYTE
10078     if (has_mbyte)
10079     {
10080 	int	outi = 0;
10081 	char_u	*p;
10082 	int	c;
10083 
10084 	/* Fold one character at a time. */
10085 	for (p = str; p < str + len; )
10086 	{
10087 	    if (outi + MB_MAXBYTES > buflen)
10088 	    {
10089 		buf[outi] = NUL;
10090 		return FAIL;
10091 	    }
10092 	    c = mb_cptr2char_adv(&p);
10093 	    outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
10094 	}
10095 	buf[outi] = NUL;
10096     }
10097     else
10098 #endif
10099     {
10100 	/* Be quick for non-multibyte encodings. */
10101 	for (i = 0; i < len; ++i)
10102 	    buf[i] = spelltab.st_fold[str[i]];
10103 	buf[i] = NUL;
10104     }
10105 
10106     return OK;
10107 }
10108 
10109 /* values for sps_flags */
10110 #define SPS_BEST    1
10111 #define SPS_FAST    2
10112 #define SPS_DOUBLE  4
10113 
10114 static int sps_flags = SPS_BEST;	/* flags from 'spellsuggest' */
10115 static int sps_limit = 9999;		/* max nr of suggestions given */
10116 
10117 /*
10118  * Check the 'spellsuggest' option.  Return FAIL if it's wrong.
10119  * Sets "sps_flags" and "sps_limit".
10120  */
10121     int
10122 spell_check_sps()
10123 {
10124     char_u	*p;
10125     char_u	*s;
10126     char_u	buf[MAXPATHL];
10127     int		f;
10128 
10129     sps_flags = 0;
10130     sps_limit = 9999;
10131 
10132     for (p = p_sps; *p != NUL; )
10133     {
10134 	copy_option_part(&p, buf, MAXPATHL, ",");
10135 
10136 	f = 0;
10137 	if (VIM_ISDIGIT(*buf))
10138 	{
10139 	    s = buf;
10140 	    sps_limit = getdigits(&s);
10141 	    if (*s != NUL && !VIM_ISDIGIT(*s))
10142 		f = -1;
10143 	}
10144 	else if (STRCMP(buf, "best") == 0)
10145 	    f = SPS_BEST;
10146 	else if (STRCMP(buf, "fast") == 0)
10147 	    f = SPS_FAST;
10148 	else if (STRCMP(buf, "double") == 0)
10149 	    f = SPS_DOUBLE;
10150 	else if (STRNCMP(buf, "expr:", 5) != 0
10151 		&& STRNCMP(buf, "file:", 5) != 0)
10152 	    f = -1;
10153 
10154 	if (f == -1 || (sps_flags != 0 && f != 0))
10155 	{
10156 	    sps_flags = SPS_BEST;
10157 	    sps_limit = 9999;
10158 	    return FAIL;
10159 	}
10160 	if (f != 0)
10161 	    sps_flags = f;
10162     }
10163 
10164     if (sps_flags == 0)
10165 	sps_flags = SPS_BEST;
10166 
10167     return OK;
10168 }
10169 
10170 /*
10171  * "z=": Find badly spelled word under or after the cursor.
10172  * Give suggestions for the properly spelled word.
10173  * In Visual mode use the highlighted word as the bad word.
10174  * When "count" is non-zero use that suggestion.
10175  */
10176     void
10177 spell_suggest(count)
10178     int		count;
10179 {
10180     char_u	*line;
10181     pos_T	prev_cursor = curwin->w_cursor;
10182     char_u	wcopy[MAXWLEN + 2];
10183     char_u	*p;
10184     int		i;
10185     int		c;
10186     suginfo_T	sug;
10187     suggest_T	*stp;
10188     int		mouse_used;
10189     int		need_cap;
10190     int		limit;
10191     int		selected = count;
10192     int		badlen = 0;
10193     int		msg_scroll_save = msg_scroll;
10194 
10195     if (no_spell_checking(curwin))
10196 	return;
10197 
10198     if (VIsual_active)
10199     {
10200 	/* Use the Visually selected text as the bad word.  But reject
10201 	 * a multi-line selection. */
10202 	if (curwin->w_cursor.lnum != VIsual.lnum)
10203 	{
10204 	    vim_beep(BO_SPELL);
10205 	    return;
10206 	}
10207 	badlen = (int)curwin->w_cursor.col - (int)VIsual.col;
10208 	if (badlen < 0)
10209 	    badlen = -badlen;
10210 	else
10211 	    curwin->w_cursor.col = VIsual.col;
10212 	++badlen;
10213 	end_visual_mode();
10214     }
10215     /* Find the start of the badly spelled word. */
10216     else if (spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL) == 0
10217 	    || curwin->w_cursor.col > prev_cursor.col)
10218     {
10219 	/* No bad word or it starts after the cursor: use the word under the
10220 	 * cursor. */
10221 	curwin->w_cursor = prev_cursor;
10222 	line = ml_get_curline();
10223 	p = line + curwin->w_cursor.col;
10224 	/* Backup to before start of word. */
10225 	while (p > line && spell_iswordp_nmw(p, curwin))
10226 	    mb_ptr_back(line, p);
10227 	/* Forward to start of word. */
10228 	while (*p != NUL && !spell_iswordp_nmw(p, curwin))
10229 	    mb_ptr_adv(p);
10230 
10231 	if (!spell_iswordp_nmw(p, curwin))		/* No word found. */
10232 	{
10233 	    beep_flush();
10234 	    return;
10235 	}
10236 	curwin->w_cursor.col = (colnr_T)(p - line);
10237     }
10238 
10239     /* Get the word and its length. */
10240 
10241     /* Figure out if the word should be capitalised. */
10242     need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
10243 
10244     /* Make a copy of current line since autocommands may free the line. */
10245     line = vim_strsave(ml_get_curline());
10246     if (line == NULL)
10247 	goto skip;
10248 
10249     /* Get the list of suggestions.  Limit to 'lines' - 2 or the number in
10250      * 'spellsuggest', whatever is smaller. */
10251     if (sps_limit > (int)Rows - 2)
10252 	limit = (int)Rows - 2;
10253     else
10254 	limit = sps_limit;
10255     spell_find_suggest(line + curwin->w_cursor.col, badlen, &sug, limit,
10256 							TRUE, need_cap, TRUE);
10257 
10258     if (sug.su_ga.ga_len == 0)
10259 	MSG(_("Sorry, no suggestions"));
10260     else if (count > 0)
10261     {
10262 	if (count > sug.su_ga.ga_len)
10263 	    smsg((char_u *)_("Sorry, only %ld suggestions"),
10264 						      (long)sug.su_ga.ga_len);
10265     }
10266     else
10267     {
10268 	vim_free(repl_from);
10269 	repl_from = NULL;
10270 	vim_free(repl_to);
10271 	repl_to = NULL;
10272 
10273 #ifdef FEAT_RIGHTLEFT
10274 	/* When 'rightleft' is set the list is drawn right-left. */
10275 	cmdmsg_rl = curwin->w_p_rl;
10276 	if (cmdmsg_rl)
10277 	    msg_col = Columns - 1;
10278 #endif
10279 
10280 	/* List the suggestions. */
10281 	msg_start();
10282 	msg_row = Rows - 1;	/* for when 'cmdheight' > 1 */
10283 	lines_left = Rows;	/* avoid more prompt */
10284 	vim_snprintf((char *)IObuff, IOSIZE, _("Change \"%.*s\" to:"),
10285 						sug.su_badlen, sug.su_badptr);
10286 #ifdef FEAT_RIGHTLEFT
10287 	if (cmdmsg_rl && STRNCMP(IObuff, "Change", 6) == 0)
10288 	{
10289 	    /* And now the rabbit from the high hat: Avoid showing the
10290 	     * untranslated message rightleft. */
10291 	    vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC",
10292 						sug.su_badlen, sug.su_badptr);
10293 	}
10294 #endif
10295 	msg_puts(IObuff);
10296 	msg_clr_eos();
10297 	msg_putchar('\n');
10298 
10299 	msg_scroll = TRUE;
10300 	for (i = 0; i < sug.su_ga.ga_len; ++i)
10301 	{
10302 	    stp = &SUG(sug.su_ga, i);
10303 
10304 	    /* The suggested word may replace only part of the bad word, add
10305 	     * the not replaced part. */
10306 	    vim_strncpy(wcopy, stp->st_word, MAXWLEN);
10307 	    if (sug.su_badlen > stp->st_orglen)
10308 		vim_strncpy(wcopy + stp->st_wordlen,
10309 					       sug.su_badptr + stp->st_orglen,
10310 					      sug.su_badlen - stp->st_orglen);
10311 	    vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
10312 #ifdef FEAT_RIGHTLEFT
10313 	    if (cmdmsg_rl)
10314 		rl_mirror(IObuff);
10315 #endif
10316 	    msg_puts(IObuff);
10317 
10318 	    vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy);
10319 	    msg_puts(IObuff);
10320 
10321 	    /* The word may replace more than "su_badlen". */
10322 	    if (sug.su_badlen < stp->st_orglen)
10323 	    {
10324 		vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""),
10325 					       stp->st_orglen, sug.su_badptr);
10326 		msg_puts(IObuff);
10327 	    }
10328 
10329 	    if (p_verbose > 0)
10330 	    {
10331 		/* Add the score. */
10332 		if (sps_flags & (SPS_DOUBLE | SPS_BEST))
10333 		    vim_snprintf((char *)IObuff, IOSIZE, " (%s%d - %d)",
10334 			stp->st_salscore ? "s " : "",
10335 			stp->st_score, stp->st_altscore);
10336 		else
10337 		    vim_snprintf((char *)IObuff, IOSIZE, " (%d)",
10338 			    stp->st_score);
10339 #ifdef FEAT_RIGHTLEFT
10340 		if (cmdmsg_rl)
10341 		    /* Mirror the numbers, but keep the leading space. */
10342 		    rl_mirror(IObuff + 1);
10343 #endif
10344 		msg_advance(30);
10345 		msg_puts(IObuff);
10346 	    }
10347 	    msg_putchar('\n');
10348 	}
10349 
10350 #ifdef FEAT_RIGHTLEFT
10351 	cmdmsg_rl = FALSE;
10352 	msg_col = 0;
10353 #endif
10354 	/* Ask for choice. */
10355 	selected = prompt_for_number(&mouse_used);
10356 	if (mouse_used)
10357 	    selected -= lines_left;
10358 	lines_left = Rows;		/* avoid more prompt */
10359 	/* don't delay for 'smd' in normal_cmd() */
10360 	msg_scroll = msg_scroll_save;
10361     }
10362 
10363     if (selected > 0 && selected <= sug.su_ga.ga_len && u_save_cursor() == OK)
10364     {
10365 	/* Save the from and to text for :spellrepall. */
10366 	stp = &SUG(sug.su_ga, selected - 1);
10367 	if (sug.su_badlen > stp->st_orglen)
10368 	{
10369 	    /* Replacing less than "su_badlen", append the remainder to
10370 	     * repl_to. */
10371 	    repl_from = vim_strnsave(sug.su_badptr, sug.su_badlen);
10372 	    vim_snprintf((char *)IObuff, IOSIZE, "%s%.*s", stp->st_word,
10373 		    sug.su_badlen - stp->st_orglen,
10374 					      sug.su_badptr + stp->st_orglen);
10375 	    repl_to = vim_strsave(IObuff);
10376 	}
10377 	else
10378 	{
10379 	    /* Replacing su_badlen or more, use the whole word. */
10380 	    repl_from = vim_strnsave(sug.su_badptr, stp->st_orglen);
10381 	    repl_to = vim_strsave(stp->st_word);
10382 	}
10383 
10384 	/* Replace the word. */
10385 	p = alloc((unsigned)STRLEN(line) - stp->st_orglen
10386 						       + stp->st_wordlen + 1);
10387 	if (p != NULL)
10388 	{
10389 	    c = (int)(sug.su_badptr - line);
10390 	    mch_memmove(p, line, c);
10391 	    STRCPY(p + c, stp->st_word);
10392 	    STRCAT(p, sug.su_badptr + stp->st_orglen);
10393 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
10394 	    curwin->w_cursor.col = c;
10395 
10396 	    /* For redo we use a change-word command. */
10397 	    ResetRedobuff();
10398 	    AppendToRedobuff((char_u *)"ciw");
10399 	    AppendToRedobuffLit(p + c,
10400 			    stp->st_wordlen + sug.su_badlen - stp->st_orglen);
10401 	    AppendCharToRedobuff(ESC);
10402 
10403 	    /* After this "p" may be invalid. */
10404 	    changed_bytes(curwin->w_cursor.lnum, c);
10405 	}
10406     }
10407     else
10408 	curwin->w_cursor = prev_cursor;
10409 
10410     spell_find_cleanup(&sug);
10411 skip:
10412     vim_free(line);
10413 }
10414 
10415 /*
10416  * Check if the word at line "lnum" column "col" is required to start with a
10417  * capital.  This uses 'spellcapcheck' of the current buffer.
10418  */
10419     static int
10420 check_need_cap(lnum, col)
10421     linenr_T	lnum;
10422     colnr_T	col;
10423 {
10424     int		need_cap = FALSE;
10425     char_u	*line;
10426     char_u	*line_copy = NULL;
10427     char_u	*p;
10428     colnr_T	endcol;
10429     regmatch_T	regmatch;
10430 
10431     if (curwin->w_s->b_cap_prog == NULL)
10432 	return FALSE;
10433 
10434     line = ml_get_curline();
10435     endcol = 0;
10436     if ((int)(skipwhite(line) - line) >= (int)col)
10437     {
10438 	/* At start of line, check if previous line is empty or sentence
10439 	 * ends there. */
10440 	if (lnum == 1)
10441 	    need_cap = TRUE;
10442 	else
10443 	{
10444 	    line = ml_get(lnum - 1);
10445 	    if (*skipwhite(line) == NUL)
10446 		need_cap = TRUE;
10447 	    else
10448 	    {
10449 		/* Append a space in place of the line break. */
10450 		line_copy = concat_str(line, (char_u *)" ");
10451 		line = line_copy;
10452 		endcol = (colnr_T)STRLEN(line);
10453 	    }
10454 	}
10455     }
10456     else
10457 	endcol = col;
10458 
10459     if (endcol > 0)
10460     {
10461 	/* Check if sentence ends before the bad word. */
10462 	regmatch.regprog = curwin->w_s->b_cap_prog;
10463 	regmatch.rm_ic = FALSE;
10464 	p = line + endcol;
10465 	for (;;)
10466 	{
10467 	    mb_ptr_back(line, p);
10468 	    if (p == line || spell_iswordp_nmw(p, curwin))
10469 		break;
10470 	    if (vim_regexec(&regmatch, p, 0)
10471 					 && regmatch.endp[0] == line + endcol)
10472 	    {
10473 		need_cap = TRUE;
10474 		break;
10475 	    }
10476 	}
10477 	curwin->w_s->b_cap_prog = regmatch.regprog;
10478     }
10479 
10480     vim_free(line_copy);
10481 
10482     return need_cap;
10483 }
10484 
10485 
10486 /*
10487  * ":spellrepall"
10488  */
10489     void
10490 ex_spellrepall(eap)
10491     exarg_T *eap UNUSED;
10492 {
10493     pos_T	pos = curwin->w_cursor;
10494     char_u	*frompat;
10495     int		addlen;
10496     char_u	*line;
10497     char_u	*p;
10498     int		save_ws = p_ws;
10499     linenr_T	prev_lnum = 0;
10500 
10501     if (repl_from == NULL || repl_to == NULL)
10502     {
10503 	EMSG(_("E752: No previous spell replacement"));
10504 	return;
10505     }
10506     addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from));
10507 
10508     frompat = alloc((unsigned)STRLEN(repl_from) + 7);
10509     if (frompat == NULL)
10510 	return;
10511     sprintf((char *)frompat, "\\V\\<%s\\>", repl_from);
10512     p_ws = FALSE;
10513 
10514     sub_nsubs = 0;
10515     sub_nlines = 0;
10516     curwin->w_cursor.lnum = 0;
10517     while (!got_int)
10518     {
10519 	if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
10520 						   || u_save_cursor() == FAIL)
10521 	    break;
10522 
10523 	/* Only replace when the right word isn't there yet.  This happens
10524 	 * when changing "etc" to "etc.". */
10525 	line = ml_get_curline();
10526 	if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col,
10527 					       repl_to, STRLEN(repl_to)) != 0)
10528 	{
10529 	    p = alloc((unsigned)STRLEN(line) + addlen + 1);
10530 	    if (p == NULL)
10531 		break;
10532 	    mch_memmove(p, line, curwin->w_cursor.col);
10533 	    STRCPY(p + curwin->w_cursor.col, repl_to);
10534 	    STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from));
10535 	    ml_replace(curwin->w_cursor.lnum, p, FALSE);
10536 	    changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
10537 
10538 	    if (curwin->w_cursor.lnum != prev_lnum)
10539 	    {
10540 		++sub_nlines;
10541 		prev_lnum = curwin->w_cursor.lnum;
10542 	    }
10543 	    ++sub_nsubs;
10544 	}
10545 	curwin->w_cursor.col += (colnr_T)STRLEN(repl_to);
10546     }
10547 
10548     p_ws = save_ws;
10549     curwin->w_cursor = pos;
10550     vim_free(frompat);
10551 
10552     if (sub_nsubs == 0)
10553 	EMSG2(_("E753: Not found: %s"), repl_from);
10554     else
10555 	do_sub_msg(FALSE);
10556 }
10557 
10558 /*
10559  * Find spell suggestions for "word".  Return them in the growarray "*gap" as
10560  * a list of allocated strings.
10561  */
10562     void
10563 spell_suggest_list(gap, word, maxcount, need_cap, interactive)
10564     garray_T	*gap;
10565     char_u	*word;
10566     int		maxcount;	/* maximum nr of suggestions */
10567     int		need_cap;	/* 'spellcapcheck' matched */
10568     int		interactive;
10569 {
10570     suginfo_T	sug;
10571     int		i;
10572     suggest_T	*stp;
10573     char_u	*wcopy;
10574 
10575     spell_find_suggest(word, 0, &sug, maxcount, FALSE, need_cap, interactive);
10576 
10577     /* Make room in "gap". */
10578     ga_init2(gap, sizeof(char_u *), sug.su_ga.ga_len + 1);
10579     if (ga_grow(gap, sug.su_ga.ga_len) == OK)
10580     {
10581 	for (i = 0; i < sug.su_ga.ga_len; ++i)
10582 	{
10583 	    stp = &SUG(sug.su_ga, i);
10584 
10585 	    /* The suggested word may replace only part of "word", add the not
10586 	     * replaced part. */
10587 	    wcopy = alloc(stp->st_wordlen
10588 		      + (unsigned)STRLEN(sug.su_badptr + stp->st_orglen) + 1);
10589 	    if (wcopy == NULL)
10590 		break;
10591 	    STRCPY(wcopy, stp->st_word);
10592 	    STRCPY(wcopy + stp->st_wordlen, sug.su_badptr + stp->st_orglen);
10593 	    ((char_u **)gap->ga_data)[gap->ga_len++] = wcopy;
10594 	}
10595     }
10596 
10597     spell_find_cleanup(&sug);
10598 }
10599 
10600 /*
10601  * Find spell suggestions for the word at the start of "badptr".
10602  * Return the suggestions in "su->su_ga".
10603  * The maximum number of suggestions is "maxcount".
10604  * Note: does use info for the current window.
10605  * This is based on the mechanisms of Aspell, but completely reimplemented.
10606  */
10607     static void
10608 spell_find_suggest(badptr, badlen, su, maxcount, banbadword, need_cap, interactive)
10609     char_u	*badptr;
10610     int		badlen;		/* length of bad word or 0 if unknown */
10611     suginfo_T	*su;
10612     int		maxcount;
10613     int		banbadword;	/* don't include badword in suggestions */
10614     int		need_cap;	/* word should start with capital */
10615     int		interactive;
10616 {
10617     hlf_T	attr = HLF_COUNT;
10618     char_u	buf[MAXPATHL];
10619     char_u	*p;
10620     int		do_combine = FALSE;
10621     char_u	*sps_copy;
10622 #ifdef FEAT_EVAL
10623     static int	expr_busy = FALSE;
10624 #endif
10625     int		c;
10626     int		i;
10627     langp_T	*lp;
10628 
10629     /*
10630      * Set the info in "*su".
10631      */
10632     vim_memset(su, 0, sizeof(suginfo_T));
10633     ga_init2(&su->su_ga, (int)sizeof(suggest_T), 10);
10634     ga_init2(&su->su_sga, (int)sizeof(suggest_T), 10);
10635     if (*badptr == NUL)
10636 	return;
10637     hash_init(&su->su_banned);
10638 
10639     su->su_badptr = badptr;
10640     if (badlen != 0)
10641 	su->su_badlen = badlen;
10642     else
10643 	su->su_badlen = spell_check(curwin, su->su_badptr, &attr, NULL, FALSE);
10644     su->su_maxcount = maxcount;
10645     su->su_maxscore = SCORE_MAXINIT;
10646 
10647     if (su->su_badlen >= MAXWLEN)
10648 	su->su_badlen = MAXWLEN - 1;	/* just in case */
10649     vim_strncpy(su->su_badword, su->su_badptr, su->su_badlen);
10650     (void)spell_casefold(su->su_badptr, su->su_badlen,
10651 						    su->su_fbadword, MAXWLEN);
10652     /* get caps flags for bad word */
10653     su->su_badflags = badword_captype(su->su_badptr,
10654 					       su->su_badptr + su->su_badlen);
10655     if (need_cap)
10656 	su->su_badflags |= WF_ONECAP;
10657 
10658     /* Find the default language for sound folding.  We simply use the first
10659      * one in 'spelllang' that supports sound folding.  That's good for when
10660      * using multiple files for one language, it's not that bad when mixing
10661      * languages (e.g., "pl,en"). */
10662     for (i = 0; i < curbuf->b_s.b_langp.ga_len; ++i)
10663     {
10664 	lp = LANGP_ENTRY(curbuf->b_s.b_langp, i);
10665 	if (lp->lp_sallang != NULL)
10666 	{
10667 	    su->su_sallang = lp->lp_sallang;
10668 	    break;
10669 	}
10670     }
10671 
10672     /* Soundfold the bad word with the default sound folding, so that we don't
10673      * have to do this many times. */
10674     if (su->su_sallang != NULL)
10675 	spell_soundfold(su->su_sallang, su->su_fbadword, TRUE,
10676 							  su->su_sal_badword);
10677 
10678     /* If the word is not capitalised and spell_check() doesn't consider the
10679      * word to be bad then it might need to be capitalised.  Add a suggestion
10680      * for that. */
10681     c = PTR2CHAR(su->su_badptr);
10682     if (!SPELL_ISUPPER(c) && attr == HLF_COUNT)
10683     {
10684 	make_case_word(su->su_badword, buf, WF_ONECAP);
10685 	add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
10686 					      0, TRUE, su->su_sallang, FALSE);
10687     }
10688 
10689     /* Ban the bad word itself.  It may appear in another region. */
10690     if (banbadword)
10691 	add_banned(su, su->su_badword);
10692 
10693     /* Make a copy of 'spellsuggest', because the expression may change it. */
10694     sps_copy = vim_strsave(p_sps);
10695     if (sps_copy == NULL)
10696 	return;
10697 
10698     /* Loop over the items in 'spellsuggest'. */
10699     for (p = sps_copy; *p != NUL; )
10700     {
10701 	copy_option_part(&p, buf, MAXPATHL, ",");
10702 
10703 	if (STRNCMP(buf, "expr:", 5) == 0)
10704 	{
10705 #ifdef FEAT_EVAL
10706 	    /* Evaluate an expression.  Skip this when called recursively,
10707 	     * when using spellsuggest() in the expression. */
10708 	    if (!expr_busy)
10709 	    {
10710 		expr_busy = TRUE;
10711 		spell_suggest_expr(su, buf + 5);
10712 		expr_busy = FALSE;
10713 	    }
10714 #endif
10715 	}
10716 	else if (STRNCMP(buf, "file:", 5) == 0)
10717 	    /* Use list of suggestions in a file. */
10718 	    spell_suggest_file(su, buf + 5);
10719 	else
10720 	{
10721 	    /* Use internal method. */
10722 	    spell_suggest_intern(su, interactive);
10723 	    if (sps_flags & SPS_DOUBLE)
10724 		do_combine = TRUE;
10725 	}
10726     }
10727 
10728     vim_free(sps_copy);
10729 
10730     if (do_combine)
10731 	/* Combine the two list of suggestions.  This must be done last,
10732 	 * because sorting changes the order again. */
10733 	score_combine(su);
10734 }
10735 
10736 #ifdef FEAT_EVAL
10737 /*
10738  * Find suggestions by evaluating expression "expr".
10739  */
10740     static void
10741 spell_suggest_expr(su, expr)
10742     suginfo_T	*su;
10743     char_u	*expr;
10744 {
10745     list_T	*list;
10746     listitem_T	*li;
10747     int		score;
10748     char_u	*p;
10749 
10750     /* The work is split up in a few parts to avoid having to export
10751      * suginfo_T.
10752      * First evaluate the expression and get the resulting list. */
10753     list = eval_spell_expr(su->su_badword, expr);
10754     if (list != NULL)
10755     {
10756 	/* Loop over the items in the list. */
10757 	for (li = list->lv_first; li != NULL; li = li->li_next)
10758 	    if (li->li_tv.v_type == VAR_LIST)
10759 	    {
10760 		/* Get the word and the score from the items. */
10761 		score = get_spellword(li->li_tv.vval.v_list, &p);
10762 		if (score >= 0 && score <= su->su_maxscore)
10763 		    add_suggestion(su, &su->su_ga, p, su->su_badlen,
10764 				       score, 0, TRUE, su->su_sallang, FALSE);
10765 	    }
10766 	list_unref(list);
10767     }
10768 
10769     /* Remove bogus suggestions, sort and truncate at "maxcount". */
10770     check_suggestions(su, &su->su_ga);
10771     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10772 }
10773 #endif
10774 
10775 /*
10776  * Find suggestions in file "fname".  Used for "file:" in 'spellsuggest'.
10777  */
10778     static void
10779 spell_suggest_file(su, fname)
10780     suginfo_T	*su;
10781     char_u	*fname;
10782 {
10783     FILE	*fd;
10784     char_u	line[MAXWLEN * 2];
10785     char_u	*p;
10786     int		len;
10787     char_u	cword[MAXWLEN];
10788 
10789     /* Open the file. */
10790     fd = mch_fopen((char *)fname, "r");
10791     if (fd == NULL)
10792     {
10793 	EMSG2(_(e_notopen), fname);
10794 	return;
10795     }
10796 
10797     /* Read it line by line. */
10798     while (!vim_fgets(line, MAXWLEN * 2, fd) && !got_int)
10799     {
10800 	line_breakcheck();
10801 
10802 	p = vim_strchr(line, '/');
10803 	if (p == NULL)
10804 	    continue;	    /* No Tab found, just skip the line. */
10805 	*p++ = NUL;
10806 	if (STRICMP(su->su_badword, line) == 0)
10807 	{
10808 	    /* Match!  Isolate the good word, until CR or NL. */
10809 	    for (len = 0; p[len] >= ' '; ++len)
10810 		;
10811 	    p[len] = NUL;
10812 
10813 	    /* If the suggestion doesn't have specific case duplicate the case
10814 	     * of the bad word. */
10815 	    if (captype(p, NULL) == 0)
10816 	    {
10817 		make_case_word(p, cword, su->su_badflags);
10818 		p = cword;
10819 	    }
10820 
10821 	    add_suggestion(su, &su->su_ga, p, su->su_badlen,
10822 				  SCORE_FILE, 0, TRUE, su->su_sallang, FALSE);
10823 	}
10824     }
10825 
10826     fclose(fd);
10827 
10828     /* Remove bogus suggestions, sort and truncate at "maxcount". */
10829     check_suggestions(su, &su->su_ga);
10830     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10831 }
10832 
10833 /*
10834  * Find suggestions for the internal method indicated by "sps_flags".
10835  */
10836     static void
10837 spell_suggest_intern(su, interactive)
10838     suginfo_T	*su;
10839     int		interactive;
10840 {
10841     /*
10842      * Load the .sug file(s) that are available and not done yet.
10843      */
10844     suggest_load_files();
10845 
10846     /*
10847      * 1. Try special cases, such as repeating a word: "the the" -> "the".
10848      *
10849      * Set a maximum score to limit the combination of operations that is
10850      * tried.
10851      */
10852     suggest_try_special(su);
10853 
10854     /*
10855      * 2. Try inserting/deleting/swapping/changing a letter, use REP entries
10856      *    from the .aff file and inserting a space (split the word).
10857      */
10858     suggest_try_change(su);
10859 
10860     /* For the resulting top-scorers compute the sound-a-like score. */
10861     if (sps_flags & SPS_DOUBLE)
10862 	score_comp_sal(su);
10863 
10864     /*
10865      * 3. Try finding sound-a-like words.
10866      */
10867     if ((sps_flags & SPS_FAST) == 0)
10868     {
10869 	if (sps_flags & SPS_BEST)
10870 	    /* Adjust the word score for the suggestions found so far for how
10871 	     * they sounds like. */
10872 	    rescore_suggestions(su);
10873 
10874 	/*
10875 	 * While going through the soundfold tree "su_maxscore" is the score
10876 	 * for the soundfold word, limits the changes that are being tried,
10877 	 * and "su_sfmaxscore" the rescored score, which is set by
10878 	 * cleanup_suggestions().
10879 	 * First find words with a small edit distance, because this is much
10880 	 * faster and often already finds the top-N suggestions.  If we didn't
10881 	 * find many suggestions try again with a higher edit distance.
10882 	 * "sl_sounddone" is used to avoid doing the same word twice.
10883 	 */
10884 	suggest_try_soundalike_prep();
10885 	su->su_maxscore = SCORE_SFMAX1;
10886 	su->su_sfmaxscore = SCORE_MAXINIT * 3;
10887 	suggest_try_soundalike(su);
10888 	if (su->su_ga.ga_len < SUG_CLEAN_COUNT(su))
10889 	{
10890 	    /* We didn't find enough matches, try again, allowing more
10891 	     * changes to the soundfold word. */
10892 	    su->su_maxscore = SCORE_SFMAX2;
10893 	    suggest_try_soundalike(su);
10894 	    if (su->su_ga.ga_len < SUG_CLEAN_COUNT(su))
10895 	    {
10896 		/* Still didn't find enough matches, try again, allowing even
10897 		 * more changes to the soundfold word. */
10898 		su->su_maxscore = SCORE_SFMAX3;
10899 		suggest_try_soundalike(su);
10900 	    }
10901 	}
10902 	su->su_maxscore = su->su_sfmaxscore;
10903 	suggest_try_soundalike_finish();
10904     }
10905 
10906     /* When CTRL-C was hit while searching do show the results.  Only clear
10907      * got_int when using a command, not for spellsuggest(). */
10908     ui_breakcheck();
10909     if (interactive && got_int)
10910     {
10911 	(void)vgetc();
10912 	got_int = FALSE;
10913     }
10914 
10915     if ((sps_flags & SPS_DOUBLE) == 0 && su->su_ga.ga_len != 0)
10916     {
10917 	if (sps_flags & SPS_BEST)
10918 	    /* Adjust the word score for how it sounds like. */
10919 	    rescore_suggestions(su);
10920 
10921 	/* Remove bogus suggestions, sort and truncate at "maxcount". */
10922 	check_suggestions(su, &su->su_ga);
10923 	(void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
10924     }
10925 }
10926 
10927 /*
10928  * Load the .sug files for languages that have one and weren't loaded yet.
10929  */
10930     static void
10931 suggest_load_files()
10932 {
10933     langp_T	*lp;
10934     int		lpi;
10935     slang_T	*slang;
10936     char_u	*dotp;
10937     FILE	*fd;
10938     char_u	buf[MAXWLEN];
10939     int		i;
10940     time_t	timestamp;
10941     int		wcount;
10942     int		wordnr;
10943     garray_T	ga;
10944     int		c;
10945 
10946     /* Do this for all languages that support sound folding. */
10947     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
10948     {
10949 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
10950 	slang = lp->lp_slang;
10951 	if (slang->sl_sugtime != 0 && !slang->sl_sugloaded)
10952 	{
10953 	    /* Change ".spl" to ".sug" and open the file.  When the file isn't
10954 	     * found silently skip it.  Do set "sl_sugloaded" so that we
10955 	     * don't try again and again. */
10956 	    slang->sl_sugloaded = TRUE;
10957 
10958 	    dotp = vim_strrchr(slang->sl_fname, '.');
10959 	    if (dotp == NULL || fnamecmp(dotp, ".spl") != 0)
10960 		continue;
10961 	    STRCPY(dotp, ".sug");
10962 	    fd = mch_fopen((char *)slang->sl_fname, "r");
10963 	    if (fd == NULL)
10964 		goto nextone;
10965 
10966 	    /*
10967 	     * <SUGHEADER>: <fileID> <versionnr> <timestamp>
10968 	     */
10969 	    for (i = 0; i < VIMSUGMAGICL; ++i)
10970 		buf[i] = getc(fd);			/* <fileID> */
10971 	    if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0)
10972 	    {
10973 		EMSG2(_("E778: This does not look like a .sug file: %s"),
10974 							     slang->sl_fname);
10975 		goto nextone;
10976 	    }
10977 	    c = getc(fd);				/* <versionnr> */
10978 	    if (c < VIMSUGVERSION)
10979 	    {
10980 		EMSG2(_("E779: Old .sug file, needs to be updated: %s"),
10981 							     slang->sl_fname);
10982 		goto nextone;
10983 	    }
10984 	    else if (c > VIMSUGVERSION)
10985 	    {
10986 		EMSG2(_("E780: .sug file is for newer version of Vim: %s"),
10987 							     slang->sl_fname);
10988 		goto nextone;
10989 	    }
10990 
10991 	    /* Check the timestamp, it must be exactly the same as the one in
10992 	     * the .spl file.  Otherwise the word numbers won't match. */
10993 	    timestamp = get8ctime(fd);			/* <timestamp> */
10994 	    if (timestamp != slang->sl_sugtime)
10995 	    {
10996 		EMSG2(_("E781: .sug file doesn't match .spl file: %s"),
10997 							     slang->sl_fname);
10998 		goto nextone;
10999 	    }
11000 
11001 	    /*
11002 	     * <SUGWORDTREE>: <wordtree>
11003 	     * Read the trie with the soundfolded words.
11004 	     */
11005 	    if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs,
11006 							       FALSE, 0) != 0)
11007 	    {
11008 someerror:
11009 		EMSG2(_("E782: error while reading .sug file: %s"),
11010 							     slang->sl_fname);
11011 		slang_clear_sug(slang);
11012 		goto nextone;
11013 	    }
11014 
11015 	    /*
11016 	     * <SUGTABLE>: <sugwcount> <sugline> ...
11017 	     *
11018 	     * Read the table with word numbers.  We use a file buffer for
11019 	     * this, because it's so much like a file with lines.  Makes it
11020 	     * possible to swap the info and save on memory use.
11021 	     */
11022 	    slang->sl_sugbuf = open_spellbuf();
11023 	    if (slang->sl_sugbuf == NULL)
11024 		goto someerror;
11025 							    /* <sugwcount> */
11026 	    wcount = get4c(fd);
11027 	    if (wcount < 0)
11028 		goto someerror;
11029 
11030 	    /* Read all the wordnr lists into the buffer, one NUL terminated
11031 	     * list per line. */
11032 	    ga_init2(&ga, 1, 100);
11033 	    for (wordnr = 0; wordnr < wcount; ++wordnr)
11034 	    {
11035 		ga.ga_len = 0;
11036 		for (;;)
11037 		{
11038 		    c = getc(fd);			    /* <sugline> */
11039 		    if (c < 0 || ga_grow(&ga, 1) == FAIL)
11040 			goto someerror;
11041 		    ((char_u *)ga.ga_data)[ga.ga_len++] = c;
11042 		    if (c == NUL)
11043 			break;
11044 		}
11045 		if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr,
11046 					 ga.ga_data, ga.ga_len, TRUE) == FAIL)
11047 		    goto someerror;
11048 	    }
11049 	    ga_clear(&ga);
11050 
11051 	    /*
11052 	     * Need to put word counts in the word tries, so that we can find
11053 	     * a word by its number.
11054 	     */
11055 	    tree_count_words(slang->sl_fbyts, slang->sl_fidxs);
11056 	    tree_count_words(slang->sl_sbyts, slang->sl_sidxs);
11057 
11058 nextone:
11059 	    if (fd != NULL)
11060 		fclose(fd);
11061 	    STRCPY(dotp, ".spl");
11062 	}
11063     }
11064 }
11065 
11066 
11067 /*
11068  * Fill in the wordcount fields for a trie.
11069  * Returns the total number of words.
11070  */
11071     static void
11072 tree_count_words(byts, idxs)
11073     char_u	*byts;
11074     idx_T	*idxs;
11075 {
11076     int		depth;
11077     idx_T	arridx[MAXWLEN];
11078     int		curi[MAXWLEN];
11079     int		c;
11080     idx_T	n;
11081     int		wordcount[MAXWLEN];
11082 
11083     arridx[0] = 0;
11084     curi[0] = 1;
11085     wordcount[0] = 0;
11086     depth = 0;
11087     while (depth >= 0 && !got_int)
11088     {
11089 	if (curi[depth] > byts[arridx[depth]])
11090 	{
11091 	    /* Done all bytes at this node, go up one level. */
11092 	    idxs[arridx[depth]] = wordcount[depth];
11093 	    if (depth > 0)
11094 		wordcount[depth - 1] += wordcount[depth];
11095 
11096 	    --depth;
11097 	    fast_breakcheck();
11098 	}
11099 	else
11100 	{
11101 	    /* Do one more byte at this node. */
11102 	    n = arridx[depth] + curi[depth];
11103 	    ++curi[depth];
11104 
11105 	    c = byts[n];
11106 	    if (c == 0)
11107 	    {
11108 		/* End of word, count it. */
11109 		++wordcount[depth];
11110 
11111 		/* Skip over any other NUL bytes (same word with different
11112 		 * flags). */
11113 		while (byts[n + 1] == 0)
11114 		{
11115 		    ++n;
11116 		    ++curi[depth];
11117 		}
11118 	    }
11119 	    else
11120 	    {
11121 		/* Normal char, go one level deeper to count the words. */
11122 		++depth;
11123 		arridx[depth] = idxs[n];
11124 		curi[depth] = 1;
11125 		wordcount[depth] = 0;
11126 	    }
11127 	}
11128     }
11129 }
11130 
11131 /*
11132  * Free the info put in "*su" by spell_find_suggest().
11133  */
11134     static void
11135 spell_find_cleanup(su)
11136     suginfo_T	*su;
11137 {
11138     int		i;
11139 
11140     /* Free the suggestions. */
11141     for (i = 0; i < su->su_ga.ga_len; ++i)
11142 	vim_free(SUG(su->su_ga, i).st_word);
11143     ga_clear(&su->su_ga);
11144     for (i = 0; i < su->su_sga.ga_len; ++i)
11145 	vim_free(SUG(su->su_sga, i).st_word);
11146     ga_clear(&su->su_sga);
11147 
11148     /* Free the banned words. */
11149     hash_clear_all(&su->su_banned, 0);
11150 }
11151 
11152 /*
11153  * Make a copy of "word", with the first letter upper or lower cased, to
11154  * "wcopy[MAXWLEN]".  "word" must not be empty.
11155  * The result is NUL terminated.
11156  */
11157     static void
11158 onecap_copy(word, wcopy, upper)
11159     char_u	*word;
11160     char_u	*wcopy;
11161     int		upper;	    /* TRUE: first letter made upper case */
11162 {
11163     char_u	*p;
11164     int		c;
11165     int		l;
11166 
11167     p = word;
11168 #ifdef FEAT_MBYTE
11169     if (has_mbyte)
11170 	c = mb_cptr2char_adv(&p);
11171     else
11172 #endif
11173 	c = *p++;
11174     if (upper)
11175 	c = SPELL_TOUPPER(c);
11176     else
11177 	c = SPELL_TOFOLD(c);
11178 #ifdef FEAT_MBYTE
11179     if (has_mbyte)
11180 	l = mb_char2bytes(c, wcopy);
11181     else
11182 #endif
11183     {
11184 	l = 1;
11185 	wcopy[0] = c;
11186     }
11187     vim_strncpy(wcopy + l, p, MAXWLEN - l - 1);
11188 }
11189 
11190 /*
11191  * Make a copy of "word" with all the letters upper cased into
11192  * "wcopy[MAXWLEN]".  The result is NUL terminated.
11193  */
11194     static void
11195 allcap_copy(word, wcopy)
11196     char_u	*word;
11197     char_u	*wcopy;
11198 {
11199     char_u	*s;
11200     char_u	*d;
11201     int		c;
11202 
11203     d = wcopy;
11204     for (s = word; *s != NUL; )
11205     {
11206 #ifdef FEAT_MBYTE
11207 	if (has_mbyte)
11208 	    c = mb_cptr2char_adv(&s);
11209 	else
11210 #endif
11211 	    c = *s++;
11212 
11213 #ifdef FEAT_MBYTE
11214 	/* We only change 0xdf to SS when we are certain latin1 is used.  It
11215 	 * would cause weird errors in other 8-bit encodings. */
11216 	if (enc_latin1like && c == 0xdf)
11217 	{
11218 	    c = 'S';
11219 	    if (d - wcopy >= MAXWLEN - 1)
11220 		break;
11221 	    *d++ = c;
11222 	}
11223 	else
11224 #endif
11225 	    c = SPELL_TOUPPER(c);
11226 
11227 #ifdef FEAT_MBYTE
11228 	if (has_mbyte)
11229 	{
11230 	    if (d - wcopy >= MAXWLEN - MB_MAXBYTES)
11231 		break;
11232 	    d += mb_char2bytes(c, d);
11233 	}
11234 	else
11235 #endif
11236 	{
11237 	    if (d - wcopy >= MAXWLEN - 1)
11238 		break;
11239 	    *d++ = c;
11240 	}
11241     }
11242     *d = NUL;
11243 }
11244 
11245 /*
11246  * Try finding suggestions by recognizing specific situations.
11247  */
11248     static void
11249 suggest_try_special(su)
11250     suginfo_T	*su;
11251 {
11252     char_u	*p;
11253     size_t	len;
11254     int		c;
11255     char_u	word[MAXWLEN];
11256 
11257     /*
11258      * Recognize a word that is repeated: "the the".
11259      */
11260     p = skiptowhite(su->su_fbadword);
11261     len = p - su->su_fbadword;
11262     p = skipwhite(p);
11263     if (STRLEN(p) == len && STRNCMP(su->su_fbadword, p, len) == 0)
11264     {
11265 	/* Include badflags: if the badword is onecap or allcap
11266 	 * use that for the goodword too: "The the" -> "The". */
11267 	c = su->su_fbadword[len];
11268 	su->su_fbadword[len] = NUL;
11269 	make_case_word(su->su_fbadword, word, su->su_badflags);
11270 	su->su_fbadword[len] = c;
11271 
11272 	/* Give a soundalike score of 0, compute the score as if deleting one
11273 	 * character. */
11274 	add_suggestion(su, &su->su_ga, word, su->su_badlen,
11275 		       RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang, FALSE);
11276     }
11277 }
11278 
11279 /*
11280  * Try finding suggestions by adding/removing/swapping letters.
11281  */
11282     static void
11283 suggest_try_change(su)
11284     suginfo_T	*su;
11285 {
11286     char_u	fword[MAXWLEN];	    /* copy of the bad word, case-folded */
11287     int		n;
11288     char_u	*p;
11289     int		lpi;
11290     langp_T	*lp;
11291 
11292     /* We make a copy of the case-folded bad word, so that we can modify it
11293      * to find matches (esp. REP items).  Append some more text, changing
11294      * chars after the bad word may help. */
11295     STRCPY(fword, su->su_fbadword);
11296     n = (int)STRLEN(fword);
11297     p = su->su_badptr + su->su_badlen;
11298     (void)spell_casefold(p, (int)STRLEN(p), fword + n, MAXWLEN - n);
11299 
11300     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
11301     {
11302 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
11303 
11304 	/* If reloading a spell file fails it's still in the list but
11305 	 * everything has been cleared. */
11306 	if (lp->lp_slang->sl_fbyts == NULL)
11307 	    continue;
11308 
11309 	/* Try it for this language.  Will add possible suggestions. */
11310 	suggest_trie_walk(su, lp, fword, FALSE);
11311     }
11312 }
11313 
11314 /* Check the maximum score, if we go over it we won't try this change. */
11315 #define TRY_DEEPER(su, stack, depth, add) \
11316 		(stack[depth].ts_score + (add) < su->su_maxscore)
11317 
11318 /*
11319  * Try finding suggestions by adding/removing/swapping letters.
11320  *
11321  * This uses a state machine.  At each node in the tree we try various
11322  * operations.  When trying if an operation works "depth" is increased and the
11323  * stack[] is used to store info.  This allows combinations, thus insert one
11324  * character, replace one and delete another.  The number of changes is
11325  * limited by su->su_maxscore.
11326  *
11327  * After implementing this I noticed an article by Kemal Oflazer that
11328  * describes something similar: "Error-tolerant Finite State Recognition with
11329  * Applications to Morphological Analysis and Spelling Correction" (1996).
11330  * The implementation in the article is simplified and requires a stack of
11331  * unknown depth.  The implementation here only needs a stack depth equal to
11332  * the length of the word.
11333  *
11334  * This is also used for the sound-folded word, "soundfold" is TRUE then.
11335  * The mechanism is the same, but we find a match with a sound-folded word
11336  * that comes from one or more original words.  Each of these words may be
11337  * added, this is done by add_sound_suggest().
11338  * Don't use:
11339  *	the prefix tree or the keep-case tree
11340  *	"su->su_badlen"
11341  *	anything to do with upper and lower case
11342  *	anything to do with word or non-word characters ("spell_iswordp()")
11343  *	banned words
11344  *	word flags (rare, region, compounding)
11345  *	word splitting for now
11346  *	"similar_chars()"
11347  *	use "slang->sl_repsal" instead of "lp->lp_replang->sl_rep"
11348  */
11349     static void
11350 suggest_trie_walk(su, lp, fword, soundfold)
11351     suginfo_T	*su;
11352     langp_T	*lp;
11353     char_u	*fword;
11354     int		soundfold;
11355 {
11356     char_u	tword[MAXWLEN];	    /* good word collected so far */
11357     trystate_T	stack[MAXWLEN];
11358     char_u	preword[MAXWLEN * 3]; /* word found with proper case;
11359 				       * concatenation of prefix compound
11360 				       * words and split word.  NUL terminated
11361 				       * when going deeper but not when coming
11362 				       * back. */
11363     char_u	compflags[MAXWLEN];	/* compound flags, one for each word */
11364     trystate_T	*sp;
11365     int		newscore;
11366     int		score;
11367     char_u	*byts, *fbyts, *pbyts;
11368     idx_T	*idxs, *fidxs, *pidxs;
11369     int		depth;
11370     int		c, c2, c3;
11371     int		n = 0;
11372     int		flags;
11373     garray_T	*gap;
11374     idx_T	arridx;
11375     int		len;
11376     char_u	*p;
11377     fromto_T	*ftp;
11378     int		fl = 0, tl;
11379     int		repextra = 0;	    /* extra bytes in fword[] from REP item */
11380     slang_T	*slang = lp->lp_slang;
11381     int		fword_ends;
11382     int		goodword_ends;
11383 #ifdef DEBUG_TRIEWALK
11384     /* Stores the name of the change made at each level. */
11385     char_u	changename[MAXWLEN][80];
11386 #endif
11387     int		breakcheckcount = 1000;
11388     int		compound_ok;
11389 
11390     /*
11391      * Go through the whole case-fold tree, try changes at each node.
11392      * "tword[]" contains the word collected from nodes in the tree.
11393      * "fword[]" the word we are trying to match with (initially the bad
11394      * word).
11395      */
11396     depth = 0;
11397     sp = &stack[0];
11398     vim_memset(sp, 0, sizeof(trystate_T));
11399     sp->ts_curi = 1;
11400 
11401     if (soundfold)
11402     {
11403 	/* Going through the soundfold tree. */
11404 	byts = fbyts = slang->sl_sbyts;
11405 	idxs = fidxs = slang->sl_sidxs;
11406 	pbyts = NULL;
11407 	pidxs = NULL;
11408 	sp->ts_prefixdepth = PFD_NOPREFIX;
11409 	sp->ts_state = STATE_START;
11410     }
11411     else
11412     {
11413 	/*
11414 	 * When there are postponed prefixes we need to use these first.  At
11415 	 * the end of the prefix we continue in the case-fold tree.
11416 	 */
11417 	fbyts = slang->sl_fbyts;
11418 	fidxs = slang->sl_fidxs;
11419 	pbyts = slang->sl_pbyts;
11420 	pidxs = slang->sl_pidxs;
11421 	if (pbyts != NULL)
11422 	{
11423 	    byts = pbyts;
11424 	    idxs = pidxs;
11425 	    sp->ts_prefixdepth = PFD_PREFIXTREE;
11426 	    sp->ts_state = STATE_NOPREFIX;	/* try without prefix first */
11427 	}
11428 	else
11429 	{
11430 	    byts = fbyts;
11431 	    idxs = fidxs;
11432 	    sp->ts_prefixdepth = PFD_NOPREFIX;
11433 	    sp->ts_state = STATE_START;
11434 	}
11435     }
11436 
11437     /*
11438      * Loop to find all suggestions.  At each round we either:
11439      * - For the current state try one operation, advance "ts_curi",
11440      *   increase "depth".
11441      * - When a state is done go to the next, set "ts_state".
11442      * - When all states are tried decrease "depth".
11443      */
11444     while (depth >= 0 && !got_int)
11445     {
11446 	sp = &stack[depth];
11447 	switch (sp->ts_state)
11448 	{
11449 	case STATE_START:
11450 	case STATE_NOPREFIX:
11451 	    /*
11452 	     * Start of node: Deal with NUL bytes, which means
11453 	     * tword[] may end here.
11454 	     */
11455 	    arridx = sp->ts_arridx;	    /* current node in the tree */
11456 	    len = byts[arridx];		    /* bytes in this node */
11457 	    arridx += sp->ts_curi;	    /* index of current byte */
11458 
11459 	    if (sp->ts_prefixdepth == PFD_PREFIXTREE)
11460 	    {
11461 		/* Skip over the NUL bytes, we use them later. */
11462 		for (n = 0; n < len && byts[arridx + n] == 0; ++n)
11463 		    ;
11464 		sp->ts_curi += n;
11465 
11466 		/* Always past NUL bytes now. */
11467 		n = (int)sp->ts_state;
11468 		sp->ts_state = STATE_ENDNUL;
11469 		sp->ts_save_badflags = su->su_badflags;
11470 
11471 		/* At end of a prefix or at start of prefixtree: check for
11472 		 * following word. */
11473 		if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)
11474 		{
11475 		    /* Set su->su_badflags to the caps type at this position.
11476 		     * Use the caps type until here for the prefix itself. */
11477 #ifdef FEAT_MBYTE
11478 		    if (has_mbyte)
11479 			n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
11480 		    else
11481 #endif
11482 			n = sp->ts_fidx;
11483 		    flags = badword_captype(su->su_badptr, su->su_badptr + n);
11484 		    su->su_badflags = badword_captype(su->su_badptr + n,
11485 					       su->su_badptr + su->su_badlen);
11486 #ifdef DEBUG_TRIEWALK
11487 		    sprintf(changename[depth], "prefix");
11488 #endif
11489 		    go_deeper(stack, depth, 0);
11490 		    ++depth;
11491 		    sp = &stack[depth];
11492 		    sp->ts_prefixdepth = depth - 1;
11493 		    byts = fbyts;
11494 		    idxs = fidxs;
11495 		    sp->ts_arridx = 0;
11496 
11497 		    /* Move the prefix to preword[] with the right case
11498 		     * and make find_keepcap_word() works. */
11499 		    tword[sp->ts_twordlen] = NUL;
11500 		    make_case_word(tword + sp->ts_splitoff,
11501 					  preword + sp->ts_prewordlen, flags);
11502 		    sp->ts_prewordlen = (char_u)STRLEN(preword);
11503 		    sp->ts_splitoff = sp->ts_twordlen;
11504 		}
11505 		break;
11506 	    }
11507 
11508 	    if (sp->ts_curi > len || byts[arridx] != 0)
11509 	    {
11510 		/* Past bytes in node and/or past NUL bytes. */
11511 		sp->ts_state = STATE_ENDNUL;
11512 		sp->ts_save_badflags = su->su_badflags;
11513 		break;
11514 	    }
11515 
11516 	    /*
11517 	     * End of word in tree.
11518 	     */
11519 	    ++sp->ts_curi;		/* eat one NUL byte */
11520 
11521 	    flags = (int)idxs[arridx];
11522 
11523 	    /* Skip words with the NOSUGGEST flag. */
11524 	    if (flags & WF_NOSUGGEST)
11525 		break;
11526 
11527 	    fword_ends = (fword[sp->ts_fidx] == NUL
11528 			   || (soundfold
11529 			       ? vim_iswhite(fword[sp->ts_fidx])
11530 			       : !spell_iswordp(fword + sp->ts_fidx, curwin)));
11531 	    tword[sp->ts_twordlen] = NUL;
11532 
11533 	    if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
11534 					&& (sp->ts_flags & TSF_PREFIXOK) == 0)
11535 	    {
11536 		/* There was a prefix before the word.  Check that the prefix
11537 		 * can be used with this word. */
11538 		/* Count the length of the NULs in the prefix.  If there are
11539 		 * none this must be the first try without a prefix.  */
11540 		n = stack[sp->ts_prefixdepth].ts_arridx;
11541 		len = pbyts[n++];
11542 		for (c = 0; c < len && pbyts[n + c] == 0; ++c)
11543 		    ;
11544 		if (c > 0)
11545 		{
11546 		    c = valid_word_prefix(c, n, flags,
11547 				       tword + sp->ts_splitoff, slang, FALSE);
11548 		    if (c == 0)
11549 			break;
11550 
11551 		    /* Use the WF_RARE flag for a rare prefix. */
11552 		    if (c & WF_RAREPFX)
11553 			flags |= WF_RARE;
11554 
11555 		    /* Tricky: when checking for both prefix and compounding
11556 		     * we run into the prefix flag first.
11557 		     * Remember that it's OK, so that we accept the prefix
11558 		     * when arriving at a compound flag. */
11559 		    sp->ts_flags |= TSF_PREFIXOK;
11560 		}
11561 	    }
11562 
11563 	    /* Check NEEDCOMPOUND: can't use word without compounding.  Do try
11564 	     * appending another compound word below. */
11565 	    if (sp->ts_complen == sp->ts_compsplit && fword_ends
11566 						     && (flags & WF_NEEDCOMP))
11567 		goodword_ends = FALSE;
11568 	    else
11569 		goodword_ends = TRUE;
11570 
11571 	    p = NULL;
11572 	    compound_ok = TRUE;
11573 	    if (sp->ts_complen > sp->ts_compsplit)
11574 	    {
11575 		if (slang->sl_nobreak)
11576 		{
11577 		    /* There was a word before this word.  When there was no
11578 		     * change in this word (it was correct) add the first word
11579 		     * as a suggestion.  If this word was corrected too, we
11580 		     * need to check if a correct word follows. */
11581 		    if (sp->ts_fidx - sp->ts_splitfidx
11582 					  == sp->ts_twordlen - sp->ts_splitoff
11583 			    && STRNCMP(fword + sp->ts_splitfidx,
11584 					tword + sp->ts_splitoff,
11585 					 sp->ts_fidx - sp->ts_splitfidx) == 0)
11586 		    {
11587 			preword[sp->ts_prewordlen] = NUL;
11588 			newscore = score_wordcount_adj(slang, sp->ts_score,
11589 						 preword + sp->ts_prewordlen,
11590 						 sp->ts_prewordlen > 0);
11591 			/* Add the suggestion if the score isn't too bad. */
11592 			if (newscore <= su->su_maxscore)
11593 			    add_suggestion(su, &su->su_ga, preword,
11594 				    sp->ts_splitfidx - repextra,
11595 				    newscore, 0, FALSE,
11596 				    lp->lp_sallang, FALSE);
11597 			break;
11598 		    }
11599 		}
11600 		else
11601 		{
11602 		    /* There was a compound word before this word.  If this
11603 		     * word does not support compounding then give up
11604 		     * (splitting is tried for the word without compound
11605 		     * flag). */
11606 		    if (((unsigned)flags >> 24) == 0
11607 			    || sp->ts_twordlen - sp->ts_splitoff
11608 						       < slang->sl_compminlen)
11609 			break;
11610 #ifdef FEAT_MBYTE
11611 		    /* For multi-byte chars check character length against
11612 		     * COMPOUNDMIN. */
11613 		    if (has_mbyte
11614 			    && slang->sl_compminlen > 0
11615 			    && mb_charlen(tword + sp->ts_splitoff)
11616 						       < slang->sl_compminlen)
11617 			break;
11618 #endif
11619 
11620 		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
11621 		    compflags[sp->ts_complen + 1] = NUL;
11622 		    vim_strncpy(preword + sp->ts_prewordlen,
11623 			    tword + sp->ts_splitoff,
11624 			    sp->ts_twordlen - sp->ts_splitoff);
11625 
11626 		    /* Verify CHECKCOMPOUNDPATTERN  rules. */
11627 		    if (match_checkcompoundpattern(preword,  sp->ts_prewordlen,
11628 							  &slang->sl_comppat))
11629 			compound_ok = FALSE;
11630 
11631 		    if (compound_ok)
11632 		    {
11633 			p = preword;
11634 			while (*skiptowhite(p) != NUL)
11635 			    p = skipwhite(skiptowhite(p));
11636 			if (fword_ends && !can_compound(slang, p,
11637 						compflags + sp->ts_compsplit))
11638 			    /* Compound is not allowed.  But it may still be
11639 			     * possible if we add another (short) word. */
11640 			    compound_ok = FALSE;
11641 		    }
11642 
11643 		    /* Get pointer to last char of previous word. */
11644 		    p = preword + sp->ts_prewordlen;
11645 		    mb_ptr_back(preword, p);
11646 		}
11647 	    }
11648 
11649 	    /*
11650 	     * Form the word with proper case in preword.
11651 	     * If there is a word from a previous split, append.
11652 	     * For the soundfold tree don't change the case, simply append.
11653 	     */
11654 	    if (soundfold)
11655 		STRCPY(preword + sp->ts_prewordlen, tword + sp->ts_splitoff);
11656 	    else if (flags & WF_KEEPCAP)
11657 		/* Must find the word in the keep-case tree. */
11658 		find_keepcap_word(slang, tword + sp->ts_splitoff,
11659 						 preword + sp->ts_prewordlen);
11660 	    else
11661 	    {
11662 		/* Include badflags: If the badword is onecap or allcap
11663 		 * use that for the goodword too.  But if the badword is
11664 		 * allcap and it's only one char long use onecap. */
11665 		c = su->su_badflags;
11666 		if ((c & WF_ALLCAP)
11667 #ifdef FEAT_MBYTE
11668 			&& su->su_badlen == (*mb_ptr2len)(su->su_badptr)
11669 #else
11670 			&& su->su_badlen == 1
11671 #endif
11672 			)
11673 		    c = WF_ONECAP;
11674 		c |= flags;
11675 
11676 		/* When appending a compound word after a word character don't
11677 		 * use Onecap. */
11678 		if (p != NULL && spell_iswordp_nmw(p, curwin))
11679 		    c &= ~WF_ONECAP;
11680 		make_case_word(tword + sp->ts_splitoff,
11681 					      preword + sp->ts_prewordlen, c);
11682 	    }
11683 
11684 	    if (!soundfold)
11685 	    {
11686 		/* Don't use a banned word.  It may appear again as a good
11687 		 * word, thus remember it. */
11688 		if (flags & WF_BANNED)
11689 		{
11690 		    add_banned(su, preword + sp->ts_prewordlen);
11691 		    break;
11692 		}
11693 		if ((sp->ts_complen == sp->ts_compsplit
11694 			    && WAS_BANNED(su, preword + sp->ts_prewordlen))
11695 						   || WAS_BANNED(su, preword))
11696 		{
11697 		    if (slang->sl_compprog == NULL)
11698 			break;
11699 		    /* the word so far was banned but we may try compounding */
11700 		    goodword_ends = FALSE;
11701 		}
11702 	    }
11703 
11704 	    newscore = 0;
11705 	    if (!soundfold)	/* soundfold words don't have flags */
11706 	    {
11707 		if ((flags & WF_REGION)
11708 			    && (((unsigned)flags >> 16) & lp->lp_region) == 0)
11709 		    newscore += SCORE_REGION;
11710 		if (flags & WF_RARE)
11711 		    newscore += SCORE_RARE;
11712 
11713 		if (!spell_valid_case(su->su_badflags,
11714 				  captype(preword + sp->ts_prewordlen, NULL)))
11715 		    newscore += SCORE_ICASE;
11716 	    }
11717 
11718 	    /* TODO: how about splitting in the soundfold tree? */
11719 	    if (fword_ends
11720 		    && goodword_ends
11721 		    && sp->ts_fidx >= sp->ts_fidxtry
11722 		    && compound_ok)
11723 	    {
11724 		/* The badword also ends: add suggestions. */
11725 #ifdef DEBUG_TRIEWALK
11726 		if (soundfold && STRCMP(preword, "smwrd") == 0)
11727 		{
11728 		    int	    j;
11729 
11730 		    /* print the stack of changes that brought us here */
11731 		    smsg("------ %s -------", fword);
11732 		    for (j = 0; j < depth; ++j)
11733 			smsg("%s", changename[j]);
11734 		}
11735 #endif
11736 		if (soundfold)
11737 		{
11738 		    /* For soundfolded words we need to find the original
11739 		     * words, the edit distance and then add them. */
11740 		    add_sound_suggest(su, preword, sp->ts_score, lp);
11741 		}
11742 		else if (sp->ts_fidx > 0)
11743 		{
11744 		    /* Give a penalty when changing non-word char to word
11745 		     * char, e.g., "thes," -> "these". */
11746 		    p = fword + sp->ts_fidx;
11747 		    mb_ptr_back(fword, p);
11748 		    if (!spell_iswordp(p, curwin))
11749 		    {
11750 			p = preword + STRLEN(preword);
11751 			mb_ptr_back(preword, p);
11752 			if (spell_iswordp(p, curwin))
11753 			    newscore += SCORE_NONWORD;
11754 		    }
11755 
11756 		    /* Give a bonus to words seen before. */
11757 		    score = score_wordcount_adj(slang,
11758 						sp->ts_score + newscore,
11759 						preword + sp->ts_prewordlen,
11760 						sp->ts_prewordlen > 0);
11761 
11762 		    /* Add the suggestion if the score isn't too bad. */
11763 		    if (score <= su->su_maxscore)
11764 		    {
11765 			add_suggestion(su, &su->su_ga, preword,
11766 				    sp->ts_fidx - repextra,
11767 				    score, 0, FALSE, lp->lp_sallang, FALSE);
11768 
11769 			if (su->su_badflags & WF_MIXCAP)
11770 			{
11771 			    /* We really don't know if the word should be
11772 			     * upper or lower case, add both. */
11773 			    c = captype(preword, NULL);
11774 			    if (c == 0 || c == WF_ALLCAP)
11775 			    {
11776 				make_case_word(tword + sp->ts_splitoff,
11777 					      preword + sp->ts_prewordlen,
11778 						      c == 0 ? WF_ALLCAP : 0);
11779 
11780 				add_suggestion(su, &su->su_ga, preword,
11781 					sp->ts_fidx - repextra,
11782 					score + SCORE_ICASE, 0, FALSE,
11783 					lp->lp_sallang, FALSE);
11784 			    }
11785 			}
11786 		    }
11787 		}
11788 	    }
11789 
11790 	    /*
11791 	     * Try word split and/or compounding.
11792 	     */
11793 	    if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
11794 #ifdef FEAT_MBYTE
11795 		    /* Don't split halfway a character. */
11796 		    && (!has_mbyte || sp->ts_tcharlen == 0)
11797 #endif
11798 		    )
11799 	    {
11800 		int	try_compound;
11801 		int	try_split;
11802 
11803 		/* If past the end of the bad word don't try a split.
11804 		 * Otherwise try changing the next word.  E.g., find
11805 		 * suggestions for "the the" where the second "the" is
11806 		 * different.  It's done like a split.
11807 		 * TODO: word split for soundfold words */
11808 		try_split = (sp->ts_fidx - repextra < su->su_badlen)
11809 								&& !soundfold;
11810 
11811 		/* Get here in several situations:
11812 		 * 1. The word in the tree ends:
11813 		 *    If the word allows compounding try that.  Otherwise try
11814 		 *    a split by inserting a space.  For both check that a
11815 		 *    valid words starts at fword[sp->ts_fidx].
11816 		 *    For NOBREAK do like compounding to be able to check if
11817 		 *    the next word is valid.
11818 		 * 2. The badword does end, but it was due to a change (e.g.,
11819 		 *    a swap).  No need to split, but do check that the
11820 		 *    following word is valid.
11821 		 * 3. The badword and the word in the tree end.  It may still
11822 		 *    be possible to compound another (short) word.
11823 		 */
11824 		try_compound = FALSE;
11825 		if (!soundfold
11826 			&& slang->sl_compprog != NULL
11827 			&& ((unsigned)flags >> 24) != 0
11828 			&& sp->ts_twordlen - sp->ts_splitoff
11829 						       >= slang->sl_compminlen
11830 #ifdef FEAT_MBYTE
11831 			&& (!has_mbyte
11832 			    || slang->sl_compminlen == 0
11833 			    || mb_charlen(tword + sp->ts_splitoff)
11834 						      >= slang->sl_compminlen)
11835 #endif
11836 			&& (slang->sl_compsylmax < MAXWLEN
11837 			    || sp->ts_complen + 1 - sp->ts_compsplit
11838 							  < slang->sl_compmax)
11839 			&& (can_be_compound(sp, slang,
11840 					 compflags, ((unsigned)flags >> 24))))
11841 
11842 		{
11843 		    try_compound = TRUE;
11844 		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
11845 		    compflags[sp->ts_complen + 1] = NUL;
11846 		}
11847 
11848 		/* For NOBREAK we never try splitting, it won't make any word
11849 		 * valid. */
11850 		if (slang->sl_nobreak)
11851 		    try_compound = TRUE;
11852 
11853 		/* If we could add a compound word, and it's also possible to
11854 		 * split at this point, do the split first and set
11855 		 * TSF_DIDSPLIT to avoid doing it again. */
11856 		else if (!fword_ends
11857 			&& try_compound
11858 			&& (sp->ts_flags & TSF_DIDSPLIT) == 0)
11859 		{
11860 		    try_compound = FALSE;
11861 		    sp->ts_flags |= TSF_DIDSPLIT;
11862 		    --sp->ts_curi;	    /* do the same NUL again */
11863 		    compflags[sp->ts_complen] = NUL;
11864 		}
11865 		else
11866 		    sp->ts_flags &= ~TSF_DIDSPLIT;
11867 
11868 		if (try_split || try_compound)
11869 		{
11870 		    if (!try_compound && (!fword_ends || !goodword_ends))
11871 		    {
11872 			/* If we're going to split need to check that the
11873 			 * words so far are valid for compounding.  If there
11874 			 * is only one word it must not have the NEEDCOMPOUND
11875 			 * flag. */
11876 			if (sp->ts_complen == sp->ts_compsplit
11877 						     && (flags & WF_NEEDCOMP))
11878 			    break;
11879 			p = preword;
11880 			while (*skiptowhite(p) != NUL)
11881 			    p = skipwhite(skiptowhite(p));
11882 			if (sp->ts_complen > sp->ts_compsplit
11883 				&& !can_compound(slang, p,
11884 						compflags + sp->ts_compsplit))
11885 			    break;
11886 
11887 			if (slang->sl_nosplitsugs)
11888 			    newscore += SCORE_SPLIT_NO;
11889 			else
11890 			    newscore += SCORE_SPLIT;
11891 
11892 			/* Give a bonus to words seen before. */
11893 			newscore = score_wordcount_adj(slang, newscore,
11894 					   preword + sp->ts_prewordlen, TRUE);
11895 		    }
11896 
11897 		    if (TRY_DEEPER(su, stack, depth, newscore))
11898 		    {
11899 			go_deeper(stack, depth, newscore);
11900 #ifdef DEBUG_TRIEWALK
11901 			if (!try_compound && !fword_ends)
11902 			    sprintf(changename[depth], "%.*s-%s: split",
11903 				 sp->ts_twordlen, tword, fword + sp->ts_fidx);
11904 			else
11905 			    sprintf(changename[depth], "%.*s-%s: compound",
11906 				 sp->ts_twordlen, tword, fword + sp->ts_fidx);
11907 #endif
11908 			/* Save things to be restored at STATE_SPLITUNDO. */
11909 			sp->ts_save_badflags = su->su_badflags;
11910 			sp->ts_state = STATE_SPLITUNDO;
11911 
11912 			++depth;
11913 			sp = &stack[depth];
11914 
11915 			/* Append a space to preword when splitting. */
11916 			if (!try_compound && !fword_ends)
11917 			    STRCAT(preword, " ");
11918 			sp->ts_prewordlen = (char_u)STRLEN(preword);
11919 			sp->ts_splitoff = sp->ts_twordlen;
11920 			sp->ts_splitfidx = sp->ts_fidx;
11921 
11922 			/* If the badword has a non-word character at this
11923 			 * position skip it.  That means replacing the
11924 			 * non-word character with a space.  Always skip a
11925 			 * character when the word ends.  But only when the
11926 			 * good word can end. */
11927 			if (((!try_compound && !spell_iswordp_nmw(fword
11928 							       + sp->ts_fidx,
11929 							       curwin))
11930 				    || fword_ends)
11931 				&& fword[sp->ts_fidx] != NUL
11932 				&& goodword_ends)
11933 			{
11934 			    int	    l;
11935 
11936 #ifdef FEAT_MBYTE
11937 			    if (has_mbyte)
11938 				l = MB_BYTE2LEN(fword[sp->ts_fidx]);
11939 			    else
11940 #endif
11941 				l = 1;
11942 			    if (fword_ends)
11943 			    {
11944 				/* Copy the skipped character to preword. */
11945 				mch_memmove(preword + sp->ts_prewordlen,
11946 						      fword + sp->ts_fidx, l);
11947 				sp->ts_prewordlen += l;
11948 				preword[sp->ts_prewordlen] = NUL;
11949 			    }
11950 			    else
11951 				sp->ts_score -= SCORE_SPLIT - SCORE_SUBST;
11952 			    sp->ts_fidx += l;
11953 			}
11954 
11955 			/* When compounding include compound flag in
11956 			 * compflags[] (already set above).  When splitting we
11957 			 * may start compounding over again.  */
11958 			if (try_compound)
11959 			    ++sp->ts_complen;
11960 			else
11961 			    sp->ts_compsplit = sp->ts_complen;
11962 			sp->ts_prefixdepth = PFD_NOPREFIX;
11963 
11964 			/* set su->su_badflags to the caps type at this
11965 			 * position */
11966 #ifdef FEAT_MBYTE
11967 			if (has_mbyte)
11968 			    n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
11969 			else
11970 #endif
11971 			    n = sp->ts_fidx;
11972 			su->su_badflags = badword_captype(su->su_badptr + n,
11973 					       su->su_badptr + su->su_badlen);
11974 
11975 			/* Restart at top of the tree. */
11976 			sp->ts_arridx = 0;
11977 
11978 			/* If there are postponed prefixes, try these too. */
11979 			if (pbyts != NULL)
11980 			{
11981 			    byts = pbyts;
11982 			    idxs = pidxs;
11983 			    sp->ts_prefixdepth = PFD_PREFIXTREE;
11984 			    sp->ts_state = STATE_NOPREFIX;
11985 			}
11986 		    }
11987 		}
11988 	    }
11989 	    break;
11990 
11991 	case STATE_SPLITUNDO:
11992 	    /* Undo the changes done for word split or compound word. */
11993 	    su->su_badflags = sp->ts_save_badflags;
11994 
11995 	    /* Continue looking for NUL bytes. */
11996 	    sp->ts_state = STATE_START;
11997 
11998 	    /* In case we went into the prefix tree. */
11999 	    byts = fbyts;
12000 	    idxs = fidxs;
12001 	    break;
12002 
12003 	case STATE_ENDNUL:
12004 	    /* Past the NUL bytes in the node. */
12005 	    su->su_badflags = sp->ts_save_badflags;
12006 	    if (fword[sp->ts_fidx] == NUL
12007 #ifdef FEAT_MBYTE
12008 		    && sp->ts_tcharlen == 0
12009 #endif
12010 	       )
12011 	    {
12012 		/* The badword ends, can't use STATE_PLAIN. */
12013 		sp->ts_state = STATE_DEL;
12014 		break;
12015 	    }
12016 	    sp->ts_state = STATE_PLAIN;
12017 	    /*FALLTHROUGH*/
12018 
12019 	case STATE_PLAIN:
12020 	    /*
12021 	     * Go over all possible bytes at this node, add each to tword[]
12022 	     * and use child node.  "ts_curi" is the index.
12023 	     */
12024 	    arridx = sp->ts_arridx;
12025 	    if (sp->ts_curi > byts[arridx])
12026 	    {
12027 		/* Done all bytes at this node, do next state.  When still at
12028 		 * already changed bytes skip the other tricks. */
12029 		if (sp->ts_fidx >= sp->ts_fidxtry)
12030 		    sp->ts_state = STATE_DEL;
12031 		else
12032 		    sp->ts_state = STATE_FINAL;
12033 	    }
12034 	    else
12035 	    {
12036 		arridx += sp->ts_curi++;
12037 		c = byts[arridx];
12038 
12039 		/* Normal byte, go one level deeper.  If it's not equal to the
12040 		 * byte in the bad word adjust the score.  But don't even try
12041 		 * when the byte was already changed.  And don't try when we
12042 		 * just deleted this byte, accepting it is always cheaper than
12043 		 * delete + substitute. */
12044 		if (c == fword[sp->ts_fidx]
12045 #ifdef FEAT_MBYTE
12046 			|| (sp->ts_tcharlen > 0 && sp->ts_isdiff != DIFF_NONE)
12047 #endif
12048 			)
12049 		    newscore = 0;
12050 		else
12051 		    newscore = SCORE_SUBST;
12052 		if ((newscore == 0
12053 			    || (sp->ts_fidx >= sp->ts_fidxtry
12054 				&& ((sp->ts_flags & TSF_DIDDEL) == 0
12055 				    || c != fword[sp->ts_delidx])))
12056 			&& TRY_DEEPER(su, stack, depth, newscore))
12057 		{
12058 		    go_deeper(stack, depth, newscore);
12059 #ifdef DEBUG_TRIEWALK
12060 		    if (newscore > 0)
12061 			sprintf(changename[depth], "%.*s-%s: subst %c to %c",
12062 				sp->ts_twordlen, tword, fword + sp->ts_fidx,
12063 				fword[sp->ts_fidx], c);
12064 		    else
12065 			sprintf(changename[depth], "%.*s-%s: accept %c",
12066 				sp->ts_twordlen, tword, fword + sp->ts_fidx,
12067 				fword[sp->ts_fidx]);
12068 #endif
12069 		    ++depth;
12070 		    sp = &stack[depth];
12071 		    ++sp->ts_fidx;
12072 		    tword[sp->ts_twordlen++] = c;
12073 		    sp->ts_arridx = idxs[arridx];
12074 #ifdef FEAT_MBYTE
12075 		    if (newscore == SCORE_SUBST)
12076 			sp->ts_isdiff = DIFF_YES;
12077 		    if (has_mbyte)
12078 		    {
12079 			/* Multi-byte characters are a bit complicated to
12080 			 * handle: They differ when any of the bytes differ
12081 			 * and then their length may also differ. */
12082 			if (sp->ts_tcharlen == 0)
12083 			{
12084 			    /* First byte. */
12085 			    sp->ts_tcharidx = 0;
12086 			    sp->ts_tcharlen = MB_BYTE2LEN(c);
12087 			    sp->ts_fcharstart = sp->ts_fidx - 1;
12088 			    sp->ts_isdiff = (newscore != 0)
12089 						       ? DIFF_YES : DIFF_NONE;
12090 			}
12091 			else if (sp->ts_isdiff == DIFF_INSERT)
12092 			    /* When inserting trail bytes don't advance in the
12093 			     * bad word. */
12094 			    --sp->ts_fidx;
12095 			if (++sp->ts_tcharidx == sp->ts_tcharlen)
12096 			{
12097 			    /* Last byte of character. */
12098 			    if (sp->ts_isdiff == DIFF_YES)
12099 			    {
12100 				/* Correct ts_fidx for the byte length of the
12101 				 * character (we didn't check that before). */
12102 				sp->ts_fidx = sp->ts_fcharstart
12103 					    + MB_BYTE2LEN(
12104 						    fword[sp->ts_fcharstart]);
12105 
12106 				/* For changing a composing character adjust
12107 				 * the score from SCORE_SUBST to
12108 				 * SCORE_SUBCOMP. */
12109 				if (enc_utf8
12110 					&& utf_iscomposing(
12111 					    mb_ptr2char(tword
12112 						+ sp->ts_twordlen
12113 							   - sp->ts_tcharlen))
12114 					&& utf_iscomposing(
12115 					    mb_ptr2char(fword
12116 							+ sp->ts_fcharstart)))
12117 				    sp->ts_score -=
12118 						  SCORE_SUBST - SCORE_SUBCOMP;
12119 
12120 				/* For a similar character adjust score from
12121 				 * SCORE_SUBST to SCORE_SIMILAR. */
12122 				else if (!soundfold
12123 					&& slang->sl_has_map
12124 					&& similar_chars(slang,
12125 					    mb_ptr2char(tword
12126 						+ sp->ts_twordlen
12127 							   - sp->ts_tcharlen),
12128 					    mb_ptr2char(fword
12129 							+ sp->ts_fcharstart)))
12130 				    sp->ts_score -=
12131 						  SCORE_SUBST - SCORE_SIMILAR;
12132 			    }
12133 			    else if (sp->ts_isdiff == DIFF_INSERT
12134 					 && sp->ts_twordlen > sp->ts_tcharlen)
12135 			    {
12136 				p = tword + sp->ts_twordlen - sp->ts_tcharlen;
12137 				c = mb_ptr2char(p);
12138 				if (enc_utf8 && utf_iscomposing(c))
12139 				{
12140 				    /* Inserting a composing char doesn't
12141 				     * count that much. */
12142 				    sp->ts_score -= SCORE_INS - SCORE_INSCOMP;
12143 				}
12144 				else
12145 				{
12146 				    /* If the previous character was the same,
12147 				     * thus doubling a character, give a bonus
12148 				     * to the score.  Also for the soundfold
12149 				     * tree (might seem illogical but does
12150 				     * give better scores). */
12151 				    mb_ptr_back(tword, p);
12152 				    if (c == mb_ptr2char(p))
12153 					sp->ts_score -= SCORE_INS
12154 							       - SCORE_INSDUP;
12155 				}
12156 			    }
12157 
12158 			    /* Starting a new char, reset the length. */
12159 			    sp->ts_tcharlen = 0;
12160 			}
12161 		    }
12162 		    else
12163 #endif
12164 		    {
12165 			/* If we found a similar char adjust the score.
12166 			 * We do this after calling go_deeper() because
12167 			 * it's slow. */
12168 			if (newscore != 0
12169 				&& !soundfold
12170 				&& slang->sl_has_map
12171 				&& similar_chars(slang,
12172 						   c, fword[sp->ts_fidx - 1]))
12173 			    sp->ts_score -= SCORE_SUBST - SCORE_SIMILAR;
12174 		    }
12175 		}
12176 	    }
12177 	    break;
12178 
12179 	case STATE_DEL:
12180 #ifdef FEAT_MBYTE
12181 	    /* When past the first byte of a multi-byte char don't try
12182 	     * delete/insert/swap a character. */
12183 	    if (has_mbyte && sp->ts_tcharlen > 0)
12184 	    {
12185 		sp->ts_state = STATE_FINAL;
12186 		break;
12187 	    }
12188 #endif
12189 	    /*
12190 	     * Try skipping one character in the bad word (delete it).
12191 	     */
12192 	    sp->ts_state = STATE_INS_PREP;
12193 	    sp->ts_curi = 1;
12194 	    if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*')
12195 		/* Deleting a vowel at the start of a word counts less, see
12196 		 * soundalike_score(). */
12197 		newscore = 2 * SCORE_DEL / 3;
12198 	    else
12199 		newscore = SCORE_DEL;
12200 	    if (fword[sp->ts_fidx] != NUL
12201 				    && TRY_DEEPER(su, stack, depth, newscore))
12202 	    {
12203 		go_deeper(stack, depth, newscore);
12204 #ifdef DEBUG_TRIEWALK
12205 		sprintf(changename[depth], "%.*s-%s: delete %c",
12206 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12207 			fword[sp->ts_fidx]);
12208 #endif
12209 		++depth;
12210 
12211 		/* Remember what character we deleted, so that we can avoid
12212 		 * inserting it again. */
12213 		stack[depth].ts_flags |= TSF_DIDDEL;
12214 		stack[depth].ts_delidx = sp->ts_fidx;
12215 
12216 		/* Advance over the character in fword[].  Give a bonus to the
12217 		 * score if the same character is following "nn" -> "n".  It's
12218 		 * a bit illogical for soundfold tree but it does give better
12219 		 * results. */
12220 #ifdef FEAT_MBYTE
12221 		if (has_mbyte)
12222 		{
12223 		    c = mb_ptr2char(fword + sp->ts_fidx);
12224 		    stack[depth].ts_fidx += MB_BYTE2LEN(fword[sp->ts_fidx]);
12225 		    if (enc_utf8 && utf_iscomposing(c))
12226 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
12227 		    else if (c == mb_ptr2char(fword + stack[depth].ts_fidx))
12228 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
12229 		}
12230 		else
12231 #endif
12232 		{
12233 		    ++stack[depth].ts_fidx;
12234 		    if (fword[sp->ts_fidx] == fword[sp->ts_fidx + 1])
12235 			stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
12236 		}
12237 		break;
12238 	    }
12239 	    /*FALLTHROUGH*/
12240 
12241 	case STATE_INS_PREP:
12242 	    if (sp->ts_flags & TSF_DIDDEL)
12243 	    {
12244 		/* If we just deleted a byte then inserting won't make sense,
12245 		 * a substitute is always cheaper. */
12246 		sp->ts_state = STATE_SWAP;
12247 		break;
12248 	    }
12249 
12250 	    /* skip over NUL bytes */
12251 	    n = sp->ts_arridx;
12252 	    for (;;)
12253 	    {
12254 		if (sp->ts_curi > byts[n])
12255 		{
12256 		    /* Only NUL bytes at this node, go to next state. */
12257 		    sp->ts_state = STATE_SWAP;
12258 		    break;
12259 		}
12260 		if (byts[n + sp->ts_curi] != NUL)
12261 		{
12262 		    /* Found a byte to insert. */
12263 		    sp->ts_state = STATE_INS;
12264 		    break;
12265 		}
12266 		++sp->ts_curi;
12267 	    }
12268 	    break;
12269 
12270 	    /*FALLTHROUGH*/
12271 
12272 	case STATE_INS:
12273 	    /* Insert one byte.  Repeat this for each possible byte at this
12274 	     * node. */
12275 	    n = sp->ts_arridx;
12276 	    if (sp->ts_curi > byts[n])
12277 	    {
12278 		/* Done all bytes at this node, go to next state. */
12279 		sp->ts_state = STATE_SWAP;
12280 		break;
12281 	    }
12282 
12283 	    /* Do one more byte at this node, but:
12284 	     * - Skip NUL bytes.
12285 	     * - Skip the byte if it's equal to the byte in the word,
12286 	     *   accepting that byte is always better.
12287 	     */
12288 	    n += sp->ts_curi++;
12289 	    c = byts[n];
12290 	    if (soundfold && sp->ts_twordlen == 0 && c == '*')
12291 		/* Inserting a vowel at the start of a word counts less,
12292 		 * see soundalike_score(). */
12293 		newscore = 2 * SCORE_INS / 3;
12294 	    else
12295 		newscore = SCORE_INS;
12296 	    if (c != fword[sp->ts_fidx]
12297 				    && TRY_DEEPER(su, stack, depth, newscore))
12298 	    {
12299 		go_deeper(stack, depth, newscore);
12300 #ifdef DEBUG_TRIEWALK
12301 		sprintf(changename[depth], "%.*s-%s: insert %c",
12302 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12303 			c);
12304 #endif
12305 		++depth;
12306 		sp = &stack[depth];
12307 		tword[sp->ts_twordlen++] = c;
12308 		sp->ts_arridx = idxs[n];
12309 #ifdef FEAT_MBYTE
12310 		if (has_mbyte)
12311 		{
12312 		    fl = MB_BYTE2LEN(c);
12313 		    if (fl > 1)
12314 		    {
12315 			/* There are following bytes for the same character.
12316 			 * We must find all bytes before trying
12317 			 * delete/insert/swap/etc. */
12318 			sp->ts_tcharlen = fl;
12319 			sp->ts_tcharidx = 1;
12320 			sp->ts_isdiff = DIFF_INSERT;
12321 		    }
12322 		}
12323 		else
12324 		    fl = 1;
12325 		if (fl == 1)
12326 #endif
12327 		{
12328 		    /* If the previous character was the same, thus doubling a
12329 		     * character, give a bonus to the score.  Also for
12330 		     * soundfold words (illogical but does give a better
12331 		     * score). */
12332 		    if (sp->ts_twordlen >= 2
12333 					   && tword[sp->ts_twordlen - 2] == c)
12334 			sp->ts_score -= SCORE_INS - SCORE_INSDUP;
12335 		}
12336 	    }
12337 	    break;
12338 
12339 	case STATE_SWAP:
12340 	    /*
12341 	     * Swap two bytes in the bad word: "12" -> "21".
12342 	     * We change "fword" here, it's changed back afterwards at
12343 	     * STATE_UNSWAP.
12344 	     */
12345 	    p = fword + sp->ts_fidx;
12346 	    c = *p;
12347 	    if (c == NUL)
12348 	    {
12349 		/* End of word, can't swap or replace. */
12350 		sp->ts_state = STATE_FINAL;
12351 		break;
12352 	    }
12353 
12354 	    /* Don't swap if the first character is not a word character.
12355 	     * SWAP3 etc. also don't make sense then. */
12356 	    if (!soundfold && !spell_iswordp(p, curwin))
12357 	    {
12358 		sp->ts_state = STATE_REP_INI;
12359 		break;
12360 	    }
12361 
12362 #ifdef FEAT_MBYTE
12363 	    if (has_mbyte)
12364 	    {
12365 		n = mb_cptr2len(p);
12366 		c = mb_ptr2char(p);
12367 		if (p[n] == NUL)
12368 		    c2 = NUL;
12369 		else if (!soundfold && !spell_iswordp(p + n, curwin))
12370 		    c2 = c; /* don't swap non-word char */
12371 		else
12372 		    c2 = mb_ptr2char(p + n);
12373 	    }
12374 	    else
12375 #endif
12376 	    {
12377 		if (p[1] == NUL)
12378 		    c2 = NUL;
12379 		else if (!soundfold && !spell_iswordp(p + 1, curwin))
12380 		    c2 = c; /* don't swap non-word char */
12381 		else
12382 		    c2 = p[1];
12383 	    }
12384 
12385 	    /* When the second character is NUL we can't swap. */
12386 	    if (c2 == NUL)
12387 	    {
12388 		sp->ts_state = STATE_REP_INI;
12389 		break;
12390 	    }
12391 
12392 	    /* When characters are identical, swap won't do anything.
12393 	     * Also get here if the second char is not a word character. */
12394 	    if (c == c2)
12395 	    {
12396 		sp->ts_state = STATE_SWAP3;
12397 		break;
12398 	    }
12399 	    if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP))
12400 	    {
12401 		go_deeper(stack, depth, SCORE_SWAP);
12402 #ifdef DEBUG_TRIEWALK
12403 		sprintf(changename[depth], "%.*s-%s: swap %c and %c",
12404 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12405 			c, c2);
12406 #endif
12407 		sp->ts_state = STATE_UNSWAP;
12408 		++depth;
12409 #ifdef FEAT_MBYTE
12410 		if (has_mbyte)
12411 		{
12412 		    fl = mb_char2len(c2);
12413 		    mch_memmove(p, p + n, fl);
12414 		    mb_char2bytes(c, p + fl);
12415 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
12416 		}
12417 		else
12418 #endif
12419 		{
12420 		    p[0] = c2;
12421 		    p[1] = c;
12422 		    stack[depth].ts_fidxtry = sp->ts_fidx + 2;
12423 		}
12424 	    }
12425 	    else
12426 		/* If this swap doesn't work then SWAP3 won't either. */
12427 		sp->ts_state = STATE_REP_INI;
12428 	    break;
12429 
12430 	case STATE_UNSWAP:
12431 	    /* Undo the STATE_SWAP swap: "21" -> "12". */
12432 	    p = fword + sp->ts_fidx;
12433 #ifdef FEAT_MBYTE
12434 	    if (has_mbyte)
12435 	    {
12436 		n = MB_BYTE2LEN(*p);
12437 		c = mb_ptr2char(p + n);
12438 		mch_memmove(p + MB_BYTE2LEN(p[n]), p, n);
12439 		mb_char2bytes(c, p);
12440 	    }
12441 	    else
12442 #endif
12443 	    {
12444 		c = *p;
12445 		*p = p[1];
12446 		p[1] = c;
12447 	    }
12448 	    /*FALLTHROUGH*/
12449 
12450 	case STATE_SWAP3:
12451 	    /* Swap two bytes, skipping one: "123" -> "321".  We change
12452 	     * "fword" here, it's changed back afterwards at STATE_UNSWAP3. */
12453 	    p = fword + sp->ts_fidx;
12454 #ifdef FEAT_MBYTE
12455 	    if (has_mbyte)
12456 	    {
12457 		n = mb_cptr2len(p);
12458 		c = mb_ptr2char(p);
12459 		fl = mb_cptr2len(p + n);
12460 		c2 = mb_ptr2char(p + n);
12461 		if (!soundfold && !spell_iswordp(p + n + fl, curwin))
12462 		    c3 = c;	/* don't swap non-word char */
12463 		else
12464 		    c3 = mb_ptr2char(p + n + fl);
12465 	    }
12466 	    else
12467 #endif
12468 	    {
12469 		c = *p;
12470 		c2 = p[1];
12471 		if (!soundfold && !spell_iswordp(p + 2, curwin))
12472 		    c3 = c;	/* don't swap non-word char */
12473 		else
12474 		    c3 = p[2];
12475 	    }
12476 
12477 	    /* When characters are identical: "121" then SWAP3 result is
12478 	     * identical, ROT3L result is same as SWAP: "211", ROT3L result is
12479 	     * same as SWAP on next char: "112".  Thus skip all swapping.
12480 	     * Also skip when c3 is NUL.
12481 	     * Also get here when the third character is not a word character.
12482 	     * Second character may any char: "a.b" -> "b.a" */
12483 	    if (c == c3 || c3 == NUL)
12484 	    {
12485 		sp->ts_state = STATE_REP_INI;
12486 		break;
12487 	    }
12488 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12489 	    {
12490 		go_deeper(stack, depth, SCORE_SWAP3);
12491 #ifdef DEBUG_TRIEWALK
12492 		sprintf(changename[depth], "%.*s-%s: swap3 %c and %c",
12493 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12494 			c, c3);
12495 #endif
12496 		sp->ts_state = STATE_UNSWAP3;
12497 		++depth;
12498 #ifdef FEAT_MBYTE
12499 		if (has_mbyte)
12500 		{
12501 		    tl = mb_char2len(c3);
12502 		    mch_memmove(p, p + n + fl, tl);
12503 		    mb_char2bytes(c2, p + tl);
12504 		    mb_char2bytes(c, p + fl + tl);
12505 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl + tl;
12506 		}
12507 		else
12508 #endif
12509 		{
12510 		    p[0] = p[2];
12511 		    p[2] = c;
12512 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12513 		}
12514 	    }
12515 	    else
12516 		sp->ts_state = STATE_REP_INI;
12517 	    break;
12518 
12519 	case STATE_UNSWAP3:
12520 	    /* Undo STATE_SWAP3: "321" -> "123" */
12521 	    p = fword + sp->ts_fidx;
12522 #ifdef FEAT_MBYTE
12523 	    if (has_mbyte)
12524 	    {
12525 		n = MB_BYTE2LEN(*p);
12526 		c2 = mb_ptr2char(p + n);
12527 		fl = MB_BYTE2LEN(p[n]);
12528 		c = mb_ptr2char(p + n + fl);
12529 		tl = MB_BYTE2LEN(p[n + fl]);
12530 		mch_memmove(p + fl + tl, p, n);
12531 		mb_char2bytes(c, p);
12532 		mb_char2bytes(c2, p + tl);
12533 		p = p + tl;
12534 	    }
12535 	    else
12536 #endif
12537 	    {
12538 		c = *p;
12539 		*p = p[2];
12540 		p[2] = c;
12541 		++p;
12542 	    }
12543 
12544 	    if (!soundfold && !spell_iswordp(p, curwin))
12545 	    {
12546 		/* Middle char is not a word char, skip the rotate.  First and
12547 		 * third char were already checked at swap and swap3. */
12548 		sp->ts_state = STATE_REP_INI;
12549 		break;
12550 	    }
12551 
12552 	    /* Rotate three characters left: "123" -> "231".  We change
12553 	     * "fword" here, it's changed back afterwards at STATE_UNROT3L. */
12554 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12555 	    {
12556 		go_deeper(stack, depth, SCORE_SWAP3);
12557 #ifdef DEBUG_TRIEWALK
12558 		p = fword + sp->ts_fidx;
12559 		sprintf(changename[depth], "%.*s-%s: rotate left %c%c%c",
12560 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12561 			p[0], p[1], p[2]);
12562 #endif
12563 		sp->ts_state = STATE_UNROT3L;
12564 		++depth;
12565 		p = fword + sp->ts_fidx;
12566 #ifdef FEAT_MBYTE
12567 		if (has_mbyte)
12568 		{
12569 		    n = mb_cptr2len(p);
12570 		    c = mb_ptr2char(p);
12571 		    fl = mb_cptr2len(p + n);
12572 		    fl += mb_cptr2len(p + n + fl);
12573 		    mch_memmove(p, p + n, fl);
12574 		    mb_char2bytes(c, p + fl);
12575 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
12576 		}
12577 		else
12578 #endif
12579 		{
12580 		    c = *p;
12581 		    *p = p[1];
12582 		    p[1] = p[2];
12583 		    p[2] = c;
12584 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12585 		}
12586 	    }
12587 	    else
12588 		sp->ts_state = STATE_REP_INI;
12589 	    break;
12590 
12591 	case STATE_UNROT3L:
12592 	    /* Undo ROT3L: "231" -> "123" */
12593 	    p = fword + sp->ts_fidx;
12594 #ifdef FEAT_MBYTE
12595 	    if (has_mbyte)
12596 	    {
12597 		n = MB_BYTE2LEN(*p);
12598 		n += MB_BYTE2LEN(p[n]);
12599 		c = mb_ptr2char(p + n);
12600 		tl = MB_BYTE2LEN(p[n]);
12601 		mch_memmove(p + tl, p, n);
12602 		mb_char2bytes(c, p);
12603 	    }
12604 	    else
12605 #endif
12606 	    {
12607 		c = p[2];
12608 		p[2] = p[1];
12609 		p[1] = *p;
12610 		*p = c;
12611 	    }
12612 
12613 	    /* Rotate three bytes right: "123" -> "312".  We change "fword"
12614 	     * here, it's changed back afterwards at STATE_UNROT3R. */
12615 	    if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3))
12616 	    {
12617 		go_deeper(stack, depth, SCORE_SWAP3);
12618 #ifdef DEBUG_TRIEWALK
12619 		p = fword + sp->ts_fidx;
12620 		sprintf(changename[depth], "%.*s-%s: rotate right %c%c%c",
12621 			sp->ts_twordlen, tword, fword + sp->ts_fidx,
12622 			p[0], p[1], p[2]);
12623 #endif
12624 		sp->ts_state = STATE_UNROT3R;
12625 		++depth;
12626 		p = fword + sp->ts_fidx;
12627 #ifdef FEAT_MBYTE
12628 		if (has_mbyte)
12629 		{
12630 		    n = mb_cptr2len(p);
12631 		    n += mb_cptr2len(p + n);
12632 		    c = mb_ptr2char(p + n);
12633 		    tl = mb_cptr2len(p + n);
12634 		    mch_memmove(p + tl, p, n);
12635 		    mb_char2bytes(c, p);
12636 		    stack[depth].ts_fidxtry = sp->ts_fidx + n + tl;
12637 		}
12638 		else
12639 #endif
12640 		{
12641 		    c = p[2];
12642 		    p[2] = p[1];
12643 		    p[1] = *p;
12644 		    *p = c;
12645 		    stack[depth].ts_fidxtry = sp->ts_fidx + 3;
12646 		}
12647 	    }
12648 	    else
12649 		sp->ts_state = STATE_REP_INI;
12650 	    break;
12651 
12652 	case STATE_UNROT3R:
12653 	    /* Undo ROT3R: "312" -> "123" */
12654 	    p = fword + sp->ts_fidx;
12655 #ifdef FEAT_MBYTE
12656 	    if (has_mbyte)
12657 	    {
12658 		c = mb_ptr2char(p);
12659 		tl = MB_BYTE2LEN(*p);
12660 		n = MB_BYTE2LEN(p[tl]);
12661 		n += MB_BYTE2LEN(p[tl + n]);
12662 		mch_memmove(p, p + tl, n);
12663 		mb_char2bytes(c, p + n);
12664 	    }
12665 	    else
12666 #endif
12667 	    {
12668 		c = *p;
12669 		*p = p[1];
12670 		p[1] = p[2];
12671 		p[2] = c;
12672 	    }
12673 	    /*FALLTHROUGH*/
12674 
12675 	case STATE_REP_INI:
12676 	    /* Check if matching with REP items from the .aff file would work.
12677 	     * Quickly skip if:
12678 	     * - there are no REP items and we are not in the soundfold trie
12679 	     * - the score is going to be too high anyway
12680 	     * - already applied a REP item or swapped here  */
12681 	    if ((lp->lp_replang == NULL && !soundfold)
12682 		    || sp->ts_score + SCORE_REP >= su->su_maxscore
12683 		    || sp->ts_fidx < sp->ts_fidxtry)
12684 	    {
12685 		sp->ts_state = STATE_FINAL;
12686 		break;
12687 	    }
12688 
12689 	    /* Use the first byte to quickly find the first entry that may
12690 	     * match.  If the index is -1 there is none. */
12691 	    if (soundfold)
12692 		sp->ts_curi = slang->sl_repsal_first[fword[sp->ts_fidx]];
12693 	    else
12694 		sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]];
12695 
12696 	    if (sp->ts_curi < 0)
12697 	    {
12698 		sp->ts_state = STATE_FINAL;
12699 		break;
12700 	    }
12701 
12702 	    sp->ts_state = STATE_REP;
12703 	    /*FALLTHROUGH*/
12704 
12705 	case STATE_REP:
12706 	    /* Try matching with REP items from the .aff file.  For each match
12707 	     * replace the characters and check if the resulting word is
12708 	     * valid. */
12709 	    p = fword + sp->ts_fidx;
12710 
12711 	    if (soundfold)
12712 		gap = &slang->sl_repsal;
12713 	    else
12714 		gap = &lp->lp_replang->sl_rep;
12715 	    while (sp->ts_curi < gap->ga_len)
12716 	    {
12717 		ftp = (fromto_T *)gap->ga_data + sp->ts_curi++;
12718 		if (*ftp->ft_from != *p)
12719 		{
12720 		    /* past possible matching entries */
12721 		    sp->ts_curi = gap->ga_len;
12722 		    break;
12723 		}
12724 		if (STRNCMP(ftp->ft_from, p, STRLEN(ftp->ft_from)) == 0
12725 			&& TRY_DEEPER(su, stack, depth, SCORE_REP))
12726 		{
12727 		    go_deeper(stack, depth, SCORE_REP);
12728 #ifdef DEBUG_TRIEWALK
12729 		    sprintf(changename[depth], "%.*s-%s: replace %s with %s",
12730 			    sp->ts_twordlen, tword, fword + sp->ts_fidx,
12731 			    ftp->ft_from, ftp->ft_to);
12732 #endif
12733 		    /* Need to undo this afterwards. */
12734 		    sp->ts_state = STATE_REP_UNDO;
12735 
12736 		    /* Change the "from" to the "to" string. */
12737 		    ++depth;
12738 		    fl = (int)STRLEN(ftp->ft_from);
12739 		    tl = (int)STRLEN(ftp->ft_to);
12740 		    if (fl != tl)
12741 		    {
12742 			STRMOVE(p + tl, p + fl);
12743 			repextra += tl - fl;
12744 		    }
12745 		    mch_memmove(p, ftp->ft_to, tl);
12746 		    stack[depth].ts_fidxtry = sp->ts_fidx + tl;
12747 #ifdef FEAT_MBYTE
12748 		    stack[depth].ts_tcharlen = 0;
12749 #endif
12750 		    break;
12751 		}
12752 	    }
12753 
12754 	    if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP)
12755 		/* No (more) matches. */
12756 		sp->ts_state = STATE_FINAL;
12757 
12758 	    break;
12759 
12760 	case STATE_REP_UNDO:
12761 	    /* Undo a REP replacement and continue with the next one. */
12762 	    if (soundfold)
12763 		gap = &slang->sl_repsal;
12764 	    else
12765 		gap = &lp->lp_replang->sl_rep;
12766 	    ftp = (fromto_T *)gap->ga_data + sp->ts_curi - 1;
12767 	    fl = (int)STRLEN(ftp->ft_from);
12768 	    tl = (int)STRLEN(ftp->ft_to);
12769 	    p = fword + sp->ts_fidx;
12770 	    if (fl != tl)
12771 	    {
12772 		STRMOVE(p + fl, p + tl);
12773 		repextra -= tl - fl;
12774 	    }
12775 	    mch_memmove(p, ftp->ft_from, fl);
12776 	    sp->ts_state = STATE_REP;
12777 	    break;
12778 
12779 	default:
12780 	    /* Did all possible states at this level, go up one level. */
12781 	    --depth;
12782 
12783 	    if (depth >= 0 && stack[depth].ts_prefixdepth == PFD_PREFIXTREE)
12784 	    {
12785 		/* Continue in or go back to the prefix tree. */
12786 		byts = pbyts;
12787 		idxs = pidxs;
12788 	    }
12789 
12790 	    /* Don't check for CTRL-C too often, it takes time. */
12791 	    if (--breakcheckcount == 0)
12792 	    {
12793 		ui_breakcheck();
12794 		breakcheckcount = 1000;
12795 	    }
12796 	}
12797     }
12798 }
12799 
12800 
12801 /*
12802  * Go one level deeper in the tree.
12803  */
12804     static void
12805 go_deeper(stack, depth, score_add)
12806     trystate_T	*stack;
12807     int		depth;
12808     int		score_add;
12809 {
12810     stack[depth + 1] = stack[depth];
12811     stack[depth + 1].ts_state = STATE_START;
12812     stack[depth + 1].ts_score = stack[depth].ts_score + score_add;
12813     stack[depth + 1].ts_curi = 1;	/* start just after length byte */
12814     stack[depth + 1].ts_flags = 0;
12815 }
12816 
12817 #ifdef FEAT_MBYTE
12818 /*
12819  * Case-folding may change the number of bytes: Count nr of chars in
12820  * fword[flen] and return the byte length of that many chars in "word".
12821  */
12822     static int
12823 nofold_len(fword, flen, word)
12824     char_u	*fword;
12825     int		flen;
12826     char_u	*word;
12827 {
12828     char_u	*p;
12829     int		i = 0;
12830 
12831     for (p = fword; p < fword + flen; mb_ptr_adv(p))
12832 	++i;
12833     for (p = word; i > 0; mb_ptr_adv(p))
12834 	--i;
12835     return (int)(p - word);
12836 }
12837 #endif
12838 
12839 /*
12840  * "fword" is a good word with case folded.  Find the matching keep-case
12841  * words and put it in "kword".
12842  * Theoretically there could be several keep-case words that result in the
12843  * same case-folded word, but we only find one...
12844  */
12845     static void
12846 find_keepcap_word(slang, fword, kword)
12847     slang_T	*slang;
12848     char_u	*fword;
12849     char_u	*kword;
12850 {
12851     char_u	uword[MAXWLEN];		/* "fword" in upper-case */
12852     int		depth;
12853     idx_T	tryidx;
12854 
12855     /* The following arrays are used at each depth in the tree. */
12856     idx_T	arridx[MAXWLEN];
12857     int		round[MAXWLEN];
12858     int		fwordidx[MAXWLEN];
12859     int		uwordidx[MAXWLEN];
12860     int		kwordlen[MAXWLEN];
12861 
12862     int		flen, ulen;
12863     int		l;
12864     int		len;
12865     int		c;
12866     idx_T	lo, hi, m;
12867     char_u	*p;
12868     char_u	*byts = slang->sl_kbyts;    /* array with bytes of the words */
12869     idx_T	*idxs = slang->sl_kidxs;    /* array with indexes */
12870 
12871     if (byts == NULL)
12872     {
12873 	/* array is empty: "cannot happen" */
12874 	*kword = NUL;
12875 	return;
12876     }
12877 
12878     /* Make an all-cap version of "fword". */
12879     allcap_copy(fword, uword);
12880 
12881     /*
12882      * Each character needs to be tried both case-folded and upper-case.
12883      * All this gets very complicated if we keep in mind that changing case
12884      * may change the byte length of a multi-byte character...
12885      */
12886     depth = 0;
12887     arridx[0] = 0;
12888     round[0] = 0;
12889     fwordidx[0] = 0;
12890     uwordidx[0] = 0;
12891     kwordlen[0] = 0;
12892     while (depth >= 0)
12893     {
12894 	if (fword[fwordidx[depth]] == NUL)
12895 	{
12896 	    /* We are at the end of "fword".  If the tree allows a word to end
12897 	     * here we have found a match. */
12898 	    if (byts[arridx[depth] + 1] == 0)
12899 	    {
12900 		kword[kwordlen[depth]] = NUL;
12901 		return;
12902 	    }
12903 
12904 	    /* kword is getting too long, continue one level up */
12905 	    --depth;
12906 	}
12907 	else if (++round[depth] > 2)
12908 	{
12909 	    /* tried both fold-case and upper-case character, continue one
12910 	     * level up */
12911 	    --depth;
12912 	}
12913 	else
12914 	{
12915 	    /*
12916 	     * round[depth] == 1: Try using the folded-case character.
12917 	     * round[depth] == 2: Try using the upper-case character.
12918 	     */
12919 #ifdef FEAT_MBYTE
12920 	    if (has_mbyte)
12921 	    {
12922 		flen = mb_cptr2len(fword + fwordidx[depth]);
12923 		ulen = mb_cptr2len(uword + uwordidx[depth]);
12924 	    }
12925 	    else
12926 #endif
12927 		ulen = flen = 1;
12928 	    if (round[depth] == 1)
12929 	    {
12930 		p = fword + fwordidx[depth];
12931 		l = flen;
12932 	    }
12933 	    else
12934 	    {
12935 		p = uword + uwordidx[depth];
12936 		l = ulen;
12937 	    }
12938 
12939 	    for (tryidx = arridx[depth]; l > 0; --l)
12940 	    {
12941 		/* Perform a binary search in the list of accepted bytes. */
12942 		len = byts[tryidx++];
12943 		c = *p++;
12944 		lo = tryidx;
12945 		hi = tryidx + len - 1;
12946 		while (lo < hi)
12947 		{
12948 		    m = (lo + hi) / 2;
12949 		    if (byts[m] > c)
12950 			hi = m - 1;
12951 		    else if (byts[m] < c)
12952 			lo = m + 1;
12953 		    else
12954 		    {
12955 			lo = hi = m;
12956 			break;
12957 		    }
12958 		}
12959 
12960 		/* Stop if there is no matching byte. */
12961 		if (hi < lo || byts[lo] != c)
12962 		    break;
12963 
12964 		/* Continue at the child (if there is one). */
12965 		tryidx = idxs[lo];
12966 	    }
12967 
12968 	    if (l == 0)
12969 	    {
12970 		/*
12971 		 * Found the matching char.  Copy it to "kword" and go a
12972 		 * level deeper.
12973 		 */
12974 		if (round[depth] == 1)
12975 		{
12976 		    STRNCPY(kword + kwordlen[depth], fword + fwordidx[depth],
12977 									flen);
12978 		    kwordlen[depth + 1] = kwordlen[depth] + flen;
12979 		}
12980 		else
12981 		{
12982 		    STRNCPY(kword + kwordlen[depth], uword + uwordidx[depth],
12983 									ulen);
12984 		    kwordlen[depth + 1] = kwordlen[depth] + ulen;
12985 		}
12986 		fwordidx[depth + 1] = fwordidx[depth] + flen;
12987 		uwordidx[depth + 1] = uwordidx[depth] + ulen;
12988 
12989 		++depth;
12990 		arridx[depth] = tryidx;
12991 		round[depth] = 0;
12992 	    }
12993 	}
12994     }
12995 
12996     /* Didn't find it: "cannot happen". */
12997     *kword = NUL;
12998 }
12999 
13000 /*
13001  * Compute the sound-a-like score for suggestions in su->su_ga and add them to
13002  * su->su_sga.
13003  */
13004     static void
13005 score_comp_sal(su)
13006     suginfo_T	*su;
13007 {
13008     langp_T	*lp;
13009     char_u	badsound[MAXWLEN];
13010     int		i;
13011     suggest_T   *stp;
13012     suggest_T   *sstp;
13013     int		score;
13014     int		lpi;
13015 
13016     if (ga_grow(&su->su_sga, su->su_ga.ga_len) == FAIL)
13017 	return;
13018 
13019     /*	Use the sound-folding of the first language that supports it. */
13020     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
13021     {
13022 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
13023 	if (lp->lp_slang->sl_sal.ga_len > 0)
13024 	{
13025 	    /* soundfold the bad word */
13026 	    spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, badsound);
13027 
13028 	    for (i = 0; i < su->su_ga.ga_len; ++i)
13029 	    {
13030 		stp = &SUG(su->su_ga, i);
13031 
13032 		/* Case-fold the suggested word, sound-fold it and compute the
13033 		 * sound-a-like score. */
13034 		score = stp_sal_score(stp, su, lp->lp_slang, badsound);
13035 		if (score < SCORE_MAXMAX)
13036 		{
13037 		    /* Add the suggestion. */
13038 		    sstp = &SUG(su->su_sga, su->su_sga.ga_len);
13039 		    sstp->st_word = vim_strsave(stp->st_word);
13040 		    if (sstp->st_word != NULL)
13041 		    {
13042 			sstp->st_wordlen = stp->st_wordlen;
13043 			sstp->st_score = score;
13044 			sstp->st_altscore = 0;
13045 			sstp->st_orglen = stp->st_orglen;
13046 			++su->su_sga.ga_len;
13047 		    }
13048 		}
13049 	    }
13050 	    break;
13051 	}
13052     }
13053 }
13054 
13055 /*
13056  * Combine the list of suggestions in su->su_ga and su->su_sga.
13057  * They are entwined.
13058  */
13059     static void
13060 score_combine(su)
13061     suginfo_T	*su;
13062 {
13063     int		i;
13064     int		j;
13065     garray_T	ga;
13066     garray_T	*gap;
13067     langp_T	*lp;
13068     suggest_T	*stp;
13069     char_u	*p;
13070     char_u	badsound[MAXWLEN];
13071     int		round;
13072     int		lpi;
13073     slang_T	*slang = NULL;
13074 
13075     /* Add the alternate score to su_ga. */
13076     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
13077     {
13078 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
13079 	if (lp->lp_slang->sl_sal.ga_len > 0)
13080 	{
13081 	    /* soundfold the bad word */
13082 	    slang = lp->lp_slang;
13083 	    spell_soundfold(slang, su->su_fbadword, TRUE, badsound);
13084 
13085 	    for (i = 0; i < su->su_ga.ga_len; ++i)
13086 	    {
13087 		stp = &SUG(su->su_ga, i);
13088 		stp->st_altscore = stp_sal_score(stp, su, slang, badsound);
13089 		if (stp->st_altscore == SCORE_MAXMAX)
13090 		    stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4;
13091 		else
13092 		    stp->st_score = (stp->st_score * 3
13093 						  + stp->st_altscore) / 4;
13094 		stp->st_salscore = FALSE;
13095 	    }
13096 	    break;
13097 	}
13098     }
13099 
13100     if (slang == NULL)	/* Using "double" without sound folding. */
13101     {
13102 	(void)cleanup_suggestions(&su->su_ga, su->su_maxscore,
13103 							     su->su_maxcount);
13104 	return;
13105     }
13106 
13107     /* Add the alternate score to su_sga. */
13108     for (i = 0; i < su->su_sga.ga_len; ++i)
13109     {
13110 	stp = &SUG(su->su_sga, i);
13111 	stp->st_altscore = spell_edit_score(slang,
13112 						su->su_badword, stp->st_word);
13113 	if (stp->st_score == SCORE_MAXMAX)
13114 	    stp->st_score = (SCORE_BIG * 7 + stp->st_altscore) / 8;
13115 	else
13116 	    stp->st_score = (stp->st_score * 7 + stp->st_altscore) / 8;
13117 	stp->st_salscore = TRUE;
13118     }
13119 
13120     /* Remove bad suggestions, sort the suggestions and truncate at "maxcount"
13121      * for both lists. */
13122     check_suggestions(su, &su->su_ga);
13123     (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
13124     check_suggestions(su, &su->su_sga);
13125     (void)cleanup_suggestions(&su->su_sga, su->su_maxscore, su->su_maxcount);
13126 
13127     ga_init2(&ga, (int)sizeof(suginfo_T), 1);
13128     if (ga_grow(&ga, su->su_ga.ga_len + su->su_sga.ga_len) == FAIL)
13129 	return;
13130 
13131     stp = &SUG(ga, 0);
13132     for (i = 0; i < su->su_ga.ga_len || i < su->su_sga.ga_len; ++i)
13133     {
13134 	/* round 1: get a suggestion from su_ga
13135 	 * round 2: get a suggestion from su_sga */
13136 	for (round = 1; round <= 2; ++round)
13137 	{
13138 	    gap = round == 1 ? &su->su_ga : &su->su_sga;
13139 	    if (i < gap->ga_len)
13140 	    {
13141 		/* Don't add a word if it's already there. */
13142 		p = SUG(*gap, i).st_word;
13143 		for (j = 0; j < ga.ga_len; ++j)
13144 		    if (STRCMP(stp[j].st_word, p) == 0)
13145 			break;
13146 		if (j == ga.ga_len)
13147 		    stp[ga.ga_len++] = SUG(*gap, i);
13148 		else
13149 		    vim_free(p);
13150 	    }
13151 	}
13152     }
13153 
13154     ga_clear(&su->su_ga);
13155     ga_clear(&su->su_sga);
13156 
13157     /* Truncate the list to the number of suggestions that will be displayed. */
13158     if (ga.ga_len > su->su_maxcount)
13159     {
13160 	for (i = su->su_maxcount; i < ga.ga_len; ++i)
13161 	    vim_free(stp[i].st_word);
13162 	ga.ga_len = su->su_maxcount;
13163     }
13164 
13165     su->su_ga = ga;
13166 }
13167 
13168 /*
13169  * For the goodword in "stp" compute the soundalike score compared to the
13170  * badword.
13171  */
13172     static int
13173 stp_sal_score(stp, su, slang, badsound)
13174     suggest_T	*stp;
13175     suginfo_T	*su;
13176     slang_T	*slang;
13177     char_u	*badsound;	/* sound-folded badword */
13178 {
13179     char_u	*p;
13180     char_u	*pbad;
13181     char_u	*pgood;
13182     char_u	badsound2[MAXWLEN];
13183     char_u	fword[MAXWLEN];
13184     char_u	goodsound[MAXWLEN];
13185     char_u	goodword[MAXWLEN];
13186     int		lendiff;
13187 
13188     lendiff = (int)(su->su_badlen - stp->st_orglen);
13189     if (lendiff >= 0)
13190 	pbad = badsound;
13191     else
13192     {
13193 	/* soundfold the bad word with more characters following */
13194 	(void)spell_casefold(su->su_badptr, stp->st_orglen, fword, MAXWLEN);
13195 
13196 	/* When joining two words the sound often changes a lot.  E.g., "t he"
13197 	 * sounds like "t h" while "the" sounds like "@".  Avoid that by
13198 	 * removing the space.  Don't do it when the good word also contains a
13199 	 * space. */
13200 	if (vim_iswhite(su->su_badptr[su->su_badlen])
13201 					 && *skiptowhite(stp->st_word) == NUL)
13202 	    for (p = fword; *(p = skiptowhite(p)) != NUL; )
13203 		STRMOVE(p, p + 1);
13204 
13205 	spell_soundfold(slang, fword, TRUE, badsound2);
13206 	pbad = badsound2;
13207     }
13208 
13209     if (lendiff > 0 && stp->st_wordlen + lendiff < MAXWLEN)
13210     {
13211 	/* Add part of the bad word to the good word, so that we soundfold
13212 	 * what replaces the bad word. */
13213 	STRCPY(goodword, stp->st_word);
13214 	vim_strncpy(goodword + stp->st_wordlen,
13215 			    su->su_badptr + su->su_badlen - lendiff, lendiff);
13216 	pgood = goodword;
13217     }
13218     else
13219 	pgood = stp->st_word;
13220 
13221     /* Sound-fold the word and compute the score for the difference. */
13222     spell_soundfold(slang, pgood, FALSE, goodsound);
13223 
13224     return soundalike_score(goodsound, pbad);
13225 }
13226 
13227 /* structure used to store soundfolded words that add_sound_suggest() has
13228  * handled already. */
13229 typedef struct
13230 {
13231     short	sft_score;	/* lowest score used */
13232     char_u	sft_word[1];    /* soundfolded word, actually longer */
13233 } sftword_T;
13234 
13235 static sftword_T dumsft;
13236 #define HIKEY2SFT(p)  ((sftword_T *)(p - (dumsft.sft_word - (char_u *)&dumsft)))
13237 #define HI2SFT(hi)     HIKEY2SFT((hi)->hi_key)
13238 
13239 /*
13240  * Prepare for calling suggest_try_soundalike().
13241  */
13242     static void
13243 suggest_try_soundalike_prep()
13244 {
13245     langp_T	*lp;
13246     int		lpi;
13247     slang_T	*slang;
13248 
13249     /* Do this for all languages that support sound folding and for which a
13250      * .sug file has been loaded. */
13251     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
13252     {
13253 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
13254 	slang = lp->lp_slang;
13255 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13256 	    /* prepare the hashtable used by add_sound_suggest() */
13257 	    hash_init(&slang->sl_sounddone);
13258     }
13259 }
13260 
13261 /*
13262  * Find suggestions by comparing the word in a sound-a-like form.
13263  * Note: This doesn't support postponed prefixes.
13264  */
13265     static void
13266 suggest_try_soundalike(su)
13267     suginfo_T	*su;
13268 {
13269     char_u	salword[MAXWLEN];
13270     langp_T	*lp;
13271     int		lpi;
13272     slang_T	*slang;
13273 
13274     /* Do this for all languages that support sound folding and for which a
13275      * .sug file has been loaded. */
13276     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
13277     {
13278 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
13279 	slang = lp->lp_slang;
13280 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13281 	{
13282 	    /* soundfold the bad word */
13283 	    spell_soundfold(slang, su->su_fbadword, TRUE, salword);
13284 
13285 	    /* try all kinds of inserts/deletes/swaps/etc. */
13286 	    /* TODO: also soundfold the next words, so that we can try joining
13287 	     * and splitting */
13288 	    suggest_trie_walk(su, lp, salword, TRUE);
13289 	}
13290     }
13291 }
13292 
13293 /*
13294  * Finish up after calling suggest_try_soundalike().
13295  */
13296     static void
13297 suggest_try_soundalike_finish()
13298 {
13299     langp_T	*lp;
13300     int		lpi;
13301     slang_T	*slang;
13302     int		todo;
13303     hashitem_T	*hi;
13304 
13305     /* Do this for all languages that support sound folding and for which a
13306      * .sug file has been loaded. */
13307     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
13308     {
13309 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
13310 	slang = lp->lp_slang;
13311 	if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
13312 	{
13313 	    /* Free the info about handled words. */
13314 	    todo = (int)slang->sl_sounddone.ht_used;
13315 	    for (hi = slang->sl_sounddone.ht_array; todo > 0; ++hi)
13316 		if (!HASHITEM_EMPTY(hi))
13317 		{
13318 		    vim_free(HI2SFT(hi));
13319 		    --todo;
13320 		}
13321 
13322 	    /* Clear the hashtable, it may also be used by another region. */
13323 	    hash_clear(&slang->sl_sounddone);
13324 	    hash_init(&slang->sl_sounddone);
13325 	}
13326     }
13327 }
13328 
13329 /*
13330  * A match with a soundfolded word is found.  Add the good word(s) that
13331  * produce this soundfolded word.
13332  */
13333     static void
13334 add_sound_suggest(su, goodword, score, lp)
13335     suginfo_T	*su;
13336     char_u	*goodword;
13337     int		score;		/* soundfold score  */
13338     langp_T	*lp;
13339 {
13340     slang_T	*slang = lp->lp_slang;	/* language for sound folding */
13341     int		sfwordnr;
13342     char_u	*nrline;
13343     int		orgnr;
13344     char_u	theword[MAXWLEN];
13345     int		i;
13346     int		wlen;
13347     char_u	*byts;
13348     idx_T	*idxs;
13349     int		n;
13350     int		wordcount;
13351     int		wc;
13352     int		goodscore;
13353     hash_T	hash;
13354     hashitem_T  *hi;
13355     sftword_T	*sft;
13356     int		bc, gc;
13357     int		limit;
13358 
13359     /*
13360      * It's very well possible that the same soundfold word is found several
13361      * times with different scores.  Since the following is quite slow only do
13362      * the words that have a better score than before.  Use a hashtable to
13363      * remember the words that have been done.
13364      */
13365     hash = hash_hash(goodword);
13366     hi = hash_lookup(&slang->sl_sounddone, goodword, hash);
13367     if (HASHITEM_EMPTY(hi))
13368     {
13369 	sft = (sftword_T *)alloc((unsigned)(sizeof(sftword_T)
13370 							 + STRLEN(goodword)));
13371 	if (sft != NULL)
13372 	{
13373 	    sft->sft_score = score;
13374 	    STRCPY(sft->sft_word, goodword);
13375 	    hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
13376 	}
13377     }
13378     else
13379     {
13380 	sft = HI2SFT(hi);
13381 	if (score >= sft->sft_score)
13382 	    return;
13383 	sft->sft_score = score;
13384     }
13385 
13386     /*
13387      * Find the word nr in the soundfold tree.
13388      */
13389     sfwordnr = soundfold_find(slang, goodword);
13390     if (sfwordnr < 0)
13391     {
13392 	EMSG2(_(e_intern2), "add_sound_suggest()");
13393 	return;
13394     }
13395 
13396     /*
13397      * go over the list of good words that produce this soundfold word
13398      */
13399     nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)(sfwordnr + 1), FALSE);
13400     orgnr = 0;
13401     while (*nrline != NUL)
13402     {
13403 	/* The wordnr was stored in a minimal nr of bytes as an offset to the
13404 	 * previous wordnr. */
13405 	orgnr += bytes2offset(&nrline);
13406 
13407 	byts = slang->sl_fbyts;
13408 	idxs = slang->sl_fidxs;
13409 
13410 	/* Lookup the word "orgnr" one of the two tries. */
13411 	n = 0;
13412 	wordcount = 0;
13413 	for (wlen = 0; wlen < MAXWLEN - 3; ++wlen)
13414 	{
13415 	    i = 1;
13416 	    if (wordcount == orgnr && byts[n + 1] == NUL)
13417 		break;	/* found end of word */
13418 
13419 	    if (byts[n + 1] == NUL)
13420 		++wordcount;
13421 
13422 	    /* skip over the NUL bytes */
13423 	    for ( ; byts[n + i] == NUL; ++i)
13424 		if (i > byts[n])	/* safety check */
13425 		{
13426 		    STRCPY(theword + wlen, "BAD");
13427 		    wlen += 3;
13428 		    goto badword;
13429 		}
13430 
13431 	    /* One of the siblings must have the word. */
13432 	    for ( ; i < byts[n]; ++i)
13433 	    {
13434 		wc = idxs[idxs[n + i]];	/* nr of words under this byte */
13435 		if (wordcount + wc > orgnr)
13436 		    break;
13437 		wordcount += wc;
13438 	    }
13439 
13440 	    theword[wlen] = byts[n + i];
13441 	    n = idxs[n + i];
13442 	}
13443 badword:
13444 	theword[wlen] = NUL;
13445 
13446 	/* Go over the possible flags and regions. */
13447 	for (; i <= byts[n] && byts[n + i] == NUL; ++i)
13448 	{
13449 	    char_u	cword[MAXWLEN];
13450 	    char_u	*p;
13451 	    int		flags = (int)idxs[n + i];
13452 
13453 	    /* Skip words with the NOSUGGEST flag */
13454 	    if (flags & WF_NOSUGGEST)
13455 		continue;
13456 
13457 	    if (flags & WF_KEEPCAP)
13458 	    {
13459 		/* Must find the word in the keep-case tree. */
13460 		find_keepcap_word(slang, theword, cword);
13461 		p = cword;
13462 	    }
13463 	    else
13464 	    {
13465 		flags |= su->su_badflags;
13466 		if ((flags & WF_CAPMASK) != 0)
13467 		{
13468 		    /* Need to fix case according to "flags". */
13469 		    make_case_word(theword, cword, flags);
13470 		    p = cword;
13471 		}
13472 		else
13473 		    p = theword;
13474 	    }
13475 
13476 	    /* Add the suggestion. */
13477 	    if (sps_flags & SPS_DOUBLE)
13478 	    {
13479 		/* Add the suggestion if the score isn't too bad. */
13480 		if (score <= su->su_maxscore)
13481 		    add_suggestion(su, &su->su_sga, p, su->su_badlen,
13482 					       score, 0, FALSE, slang, FALSE);
13483 	    }
13484 	    else
13485 	    {
13486 		/* Add a penalty for words in another region. */
13487 		if ((flags & WF_REGION)
13488 			    && (((unsigned)flags >> 16) & lp->lp_region) == 0)
13489 		    goodscore = SCORE_REGION;
13490 		else
13491 		    goodscore = 0;
13492 
13493 		/* Add a small penalty for changing the first letter from
13494 		 * lower to upper case.  Helps for "tath" -> "Kath", which is
13495 		 * less common than "tath" -> "path".  Don't do it when the
13496 		 * letter is the same, that has already been counted. */
13497 		gc = PTR2CHAR(p);
13498 		if (SPELL_ISUPPER(gc))
13499 		{
13500 		    bc = PTR2CHAR(su->su_badword);
13501 		    if (!SPELL_ISUPPER(bc)
13502 				      && SPELL_TOFOLD(bc) != SPELL_TOFOLD(gc))
13503 			goodscore += SCORE_ICASE / 2;
13504 		}
13505 
13506 		/* Compute the score for the good word.  This only does letter
13507 		 * insert/delete/swap/replace.  REP items are not considered,
13508 		 * which may make the score a bit higher.
13509 		 * Use a limit for the score to make it work faster.  Use
13510 		 * MAXSCORE(), because RESCORE() will change the score.
13511 		 * If the limit is very high then the iterative method is
13512 		 * inefficient, using an array is quicker. */
13513 		limit = MAXSCORE(su->su_sfmaxscore - goodscore, score);
13514 		if (limit > SCORE_LIMITMAX)
13515 		    goodscore += spell_edit_score(slang, su->su_badword, p);
13516 		else
13517 		    goodscore += spell_edit_score_limit(slang, su->su_badword,
13518 								    p, limit);
13519 
13520 		/* When going over the limit don't bother to do the rest. */
13521 		if (goodscore < SCORE_MAXMAX)
13522 		{
13523 		    /* Give a bonus to words seen before. */
13524 		    goodscore = score_wordcount_adj(slang, goodscore, p, FALSE);
13525 
13526 		    /* Add the suggestion if the score isn't too bad. */
13527 		    goodscore = RESCORE(goodscore, score);
13528 		    if (goodscore <= su->su_sfmaxscore)
13529 			add_suggestion(su, &su->su_ga, p, su->su_badlen,
13530 					 goodscore, score, TRUE, slang, TRUE);
13531 		}
13532 	    }
13533 	}
13534 	/* smsg("word %s (%d): %s (%d)", sftword, sftnr, theword, orgnr); */
13535     }
13536 }
13537 
13538 /*
13539  * Find word "word" in fold-case tree for "slang" and return the word number.
13540  */
13541     static int
13542 soundfold_find(slang, word)
13543     slang_T	*slang;
13544     char_u	*word;
13545 {
13546     idx_T	arridx = 0;
13547     int		len;
13548     int		wlen = 0;
13549     int		c;
13550     char_u	*ptr = word;
13551     char_u	*byts;
13552     idx_T	*idxs;
13553     int		wordnr = 0;
13554 
13555     byts = slang->sl_sbyts;
13556     idxs = slang->sl_sidxs;
13557 
13558     for (;;)
13559     {
13560 	/* First byte is the number of possible bytes. */
13561 	len = byts[arridx++];
13562 
13563 	/* If the first possible byte is a zero the word could end here.
13564 	 * If the word ends we found the word.  If not skip the NUL bytes. */
13565 	c = ptr[wlen];
13566 	if (byts[arridx] == NUL)
13567 	{
13568 	    if (c == NUL)
13569 		break;
13570 
13571 	    /* Skip over the zeros, there can be several. */
13572 	    while (len > 0 && byts[arridx] == NUL)
13573 	    {
13574 		++arridx;
13575 		--len;
13576 	    }
13577 	    if (len == 0)
13578 		return -1;    /* no children, word should have ended here */
13579 	    ++wordnr;
13580 	}
13581 
13582 	/* If the word ends we didn't find it. */
13583 	if (c == NUL)
13584 	    return -1;
13585 
13586 	/* Perform a binary search in the list of accepted bytes. */
13587 	if (c == TAB)	    /* <Tab> is handled like <Space> */
13588 	    c = ' ';
13589 	while (byts[arridx] < c)
13590 	{
13591 	    /* The word count is in the first idxs[] entry of the child. */
13592 	    wordnr += idxs[idxs[arridx]];
13593 	    ++arridx;
13594 	    if (--len == 0)	/* end of the bytes, didn't find it */
13595 		return -1;
13596 	}
13597 	if (byts[arridx] != c)	/* didn't find the byte */
13598 	    return -1;
13599 
13600 	/* Continue at the child (if there is one). */
13601 	arridx = idxs[arridx];
13602 	++wlen;
13603 
13604 	/* One space in the good word may stand for several spaces in the
13605 	 * checked word. */
13606 	if (c == ' ')
13607 	    while (ptr[wlen] == ' ' || ptr[wlen] == TAB)
13608 		++wlen;
13609     }
13610 
13611     return wordnr;
13612 }
13613 
13614 /*
13615  * Copy "fword" to "cword", fixing case according to "flags".
13616  */
13617     static void
13618 make_case_word(fword, cword, flags)
13619     char_u	*fword;
13620     char_u	*cword;
13621     int		flags;
13622 {
13623     if (flags & WF_ALLCAP)
13624 	/* Make it all upper-case */
13625 	allcap_copy(fword, cword);
13626     else if (flags & WF_ONECAP)
13627 	/* Make the first letter upper-case */
13628 	onecap_copy(fword, cword, TRUE);
13629     else
13630 	/* Use goodword as-is. */
13631 	STRCPY(cword, fword);
13632 }
13633 
13634 /*
13635  * Use map string "map" for languages "lp".
13636  */
13637     static void
13638 set_map_str(lp, map)
13639     slang_T	*lp;
13640     char_u	*map;
13641 {
13642     char_u	*p;
13643     int		headc = 0;
13644     int		c;
13645     int		i;
13646 
13647     if (*map == NUL)
13648     {
13649 	lp->sl_has_map = FALSE;
13650 	return;
13651     }
13652     lp->sl_has_map = TRUE;
13653 
13654     /* Init the array and hash tables empty. */
13655     for (i = 0; i < 256; ++i)
13656 	lp->sl_map_array[i] = 0;
13657 #ifdef FEAT_MBYTE
13658     hash_init(&lp->sl_map_hash);
13659 #endif
13660 
13661     /*
13662      * The similar characters are stored separated with slashes:
13663      * "aaa/bbb/ccc/".  Fill sl_map_array[c] with the character before c and
13664      * before the same slash.  For characters above 255 sl_map_hash is used.
13665      */
13666     for (p = map; *p != NUL; )
13667     {
13668 #ifdef FEAT_MBYTE
13669 	c = mb_cptr2char_adv(&p);
13670 #else
13671 	c = *p++;
13672 #endif
13673 	if (c == '/')
13674 	    headc = 0;
13675 	else
13676 	{
13677 	    if (headc == 0)
13678 		 headc = c;
13679 
13680 #ifdef FEAT_MBYTE
13681 	    /* Characters above 255 don't fit in sl_map_array[], put them in
13682 	     * the hash table.  Each entry is the char, a NUL the headchar and
13683 	     * a NUL. */
13684 	    if (c >= 256)
13685 	    {
13686 		int	    cl = mb_char2len(c);
13687 		int	    headcl = mb_char2len(headc);
13688 		char_u	    *b;
13689 		hash_T	    hash;
13690 		hashitem_T  *hi;
13691 
13692 		b = alloc((unsigned)(cl + headcl + 2));
13693 		if (b == NULL)
13694 		    return;
13695 		mb_char2bytes(c, b);
13696 		b[cl] = NUL;
13697 		mb_char2bytes(headc, b + cl + 1);
13698 		b[cl + 1 + headcl] = NUL;
13699 		hash = hash_hash(b);
13700 		hi = hash_lookup(&lp->sl_map_hash, b, hash);
13701 		if (HASHITEM_EMPTY(hi))
13702 		    hash_add_item(&lp->sl_map_hash, hi, b, hash);
13703 		else
13704 		{
13705 		    /* This should have been checked when generating the .spl
13706 		     * file. */
13707 		    EMSG(_("E783: duplicate char in MAP entry"));
13708 		    vim_free(b);
13709 		}
13710 	    }
13711 	    else
13712 #endif
13713 		lp->sl_map_array[c] = headc;
13714 	}
13715     }
13716 }
13717 
13718 /*
13719  * Return TRUE if "c1" and "c2" are similar characters according to the MAP
13720  * lines in the .aff file.
13721  */
13722     static int
13723 similar_chars(slang, c1, c2)
13724     slang_T	*slang;
13725     int		c1;
13726     int		c2;
13727 {
13728     int		m1, m2;
13729 #ifdef FEAT_MBYTE
13730     char_u	buf[MB_MAXBYTES + 1];
13731     hashitem_T  *hi;
13732 
13733     if (c1 >= 256)
13734     {
13735 	buf[mb_char2bytes(c1, buf)] = 0;
13736 	hi = hash_find(&slang->sl_map_hash, buf);
13737 	if (HASHITEM_EMPTY(hi))
13738 	    m1 = 0;
13739 	else
13740 	    m1 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
13741     }
13742     else
13743 #endif
13744 	m1 = slang->sl_map_array[c1];
13745     if (m1 == 0)
13746 	return FALSE;
13747 
13748 
13749 #ifdef FEAT_MBYTE
13750     if (c2 >= 256)
13751     {
13752 	buf[mb_char2bytes(c2, buf)] = 0;
13753 	hi = hash_find(&slang->sl_map_hash, buf);
13754 	if (HASHITEM_EMPTY(hi))
13755 	    m2 = 0;
13756 	else
13757 	    m2 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
13758     }
13759     else
13760 #endif
13761 	m2 = slang->sl_map_array[c2];
13762 
13763     return m1 == m2;
13764 }
13765 
13766 /*
13767  * Add a suggestion to the list of suggestions.
13768  * For a suggestion that is already in the list the lowest score is remembered.
13769  */
13770     static void
13771 add_suggestion(su, gap, goodword, badlenarg, score, altscore, had_bonus,
13772 								 slang, maxsf)
13773     suginfo_T	*su;
13774     garray_T	*gap;		/* either su_ga or su_sga */
13775     char_u	*goodword;
13776     int		badlenarg;	/* len of bad word replaced with "goodword" */
13777     int		score;
13778     int		altscore;
13779     int		had_bonus;	/* value for st_had_bonus */
13780     slang_T	*slang;		/* language for sound folding */
13781     int		maxsf;		/* su_maxscore applies to soundfold score,
13782 				   su_sfmaxscore to the total score. */
13783 {
13784     int		goodlen;	/* len of goodword changed */
13785     int		badlen;		/* len of bad word changed */
13786     suggest_T   *stp;
13787     suggest_T   new_sug;
13788     int		i;
13789     char_u	*pgood, *pbad;
13790 
13791     /* Minimize "badlen" for consistency.  Avoids that changing "the the" to
13792      * "thee the" is added next to changing the first "the" the "thee".  */
13793     pgood = goodword + STRLEN(goodword);
13794     pbad = su->su_badptr + badlenarg;
13795     for (;;)
13796     {
13797 	goodlen = (int)(pgood - goodword);
13798 	badlen = (int)(pbad - su->su_badptr);
13799 	if (goodlen <= 0 || badlen <= 0)
13800 	    break;
13801 	mb_ptr_back(goodword, pgood);
13802 	mb_ptr_back(su->su_badptr, pbad);
13803 #ifdef FEAT_MBYTE
13804 	if (has_mbyte)
13805 	{
13806 	    if (mb_ptr2char(pgood) != mb_ptr2char(pbad))
13807 		break;
13808 	}
13809 	else
13810 #endif
13811 	    if (*pgood != *pbad)
13812 		break;
13813     }
13814 
13815     if (badlen == 0 && goodlen == 0)
13816 	/* goodword doesn't change anything; may happen for "the the" changing
13817 	 * the first "the" to itself. */
13818 	return;
13819 
13820     if (gap->ga_len == 0)
13821 	i = -1;
13822     else
13823     {
13824 	/* Check if the word is already there.  Also check the length that is
13825 	 * being replaced "thes," -> "these" is a different suggestion from
13826 	 * "thes" -> "these". */
13827 	stp = &SUG(*gap, 0);
13828 	for (i = gap->ga_len; --i >= 0; ++stp)
13829 	    if (stp->st_wordlen == goodlen
13830 		    && stp->st_orglen == badlen
13831 		    && STRNCMP(stp->st_word, goodword, goodlen) == 0)
13832 	    {
13833 		/*
13834 		 * Found it.  Remember the word with the lowest score.
13835 		 */
13836 		if (stp->st_slang == NULL)
13837 		    stp->st_slang = slang;
13838 
13839 		new_sug.st_score = score;
13840 		new_sug.st_altscore = altscore;
13841 		new_sug.st_had_bonus = had_bonus;
13842 
13843 		if (stp->st_had_bonus != had_bonus)
13844 		{
13845 		    /* Only one of the two had the soundalike score computed.
13846 		     * Need to do that for the other one now, otherwise the
13847 		     * scores can't be compared.  This happens because
13848 		     * suggest_try_change() doesn't compute the soundalike
13849 		     * word to keep it fast, while some special methods set
13850 		     * the soundalike score to zero. */
13851 		    if (had_bonus)
13852 			rescore_one(su, stp);
13853 		    else
13854 		    {
13855 			new_sug.st_word = stp->st_word;
13856 			new_sug.st_wordlen = stp->st_wordlen;
13857 			new_sug.st_slang = stp->st_slang;
13858 			new_sug.st_orglen = badlen;
13859 			rescore_one(su, &new_sug);
13860 		    }
13861 		}
13862 
13863 		if (stp->st_score > new_sug.st_score)
13864 		{
13865 		    stp->st_score = new_sug.st_score;
13866 		    stp->st_altscore = new_sug.st_altscore;
13867 		    stp->st_had_bonus = new_sug.st_had_bonus;
13868 		}
13869 		break;
13870 	    }
13871     }
13872 
13873     if (i < 0 && ga_grow(gap, 1) == OK)
13874     {
13875 	/* Add a suggestion. */
13876 	stp = &SUG(*gap, gap->ga_len);
13877 	stp->st_word = vim_strnsave(goodword, goodlen);
13878 	if (stp->st_word != NULL)
13879 	{
13880 	    stp->st_wordlen = goodlen;
13881 	    stp->st_score = score;
13882 	    stp->st_altscore = altscore;
13883 	    stp->st_had_bonus = had_bonus;
13884 	    stp->st_orglen = badlen;
13885 	    stp->st_slang = slang;
13886 	    ++gap->ga_len;
13887 
13888 	    /* If we have too many suggestions now, sort the list and keep
13889 	     * the best suggestions. */
13890 	    if (gap->ga_len > SUG_MAX_COUNT(su))
13891 	    {
13892 		if (maxsf)
13893 		    su->su_sfmaxscore = cleanup_suggestions(gap,
13894 				      su->su_sfmaxscore, SUG_CLEAN_COUNT(su));
13895 		else
13896 		    su->su_maxscore = cleanup_suggestions(gap,
13897 					su->su_maxscore, SUG_CLEAN_COUNT(su));
13898 	    }
13899 	}
13900     }
13901 }
13902 
13903 /*
13904  * Suggestions may in fact be flagged as errors.  Esp. for banned words and
13905  * for split words, such as "the the".  Remove these from the list here.
13906  */
13907     static void
13908 check_suggestions(su, gap)
13909     suginfo_T	*su;
13910     garray_T	*gap;		    /* either su_ga or su_sga */
13911 {
13912     suggest_T   *stp;
13913     int		i;
13914     char_u	longword[MAXWLEN + 1];
13915     int		len;
13916     hlf_T	attr;
13917 
13918     stp = &SUG(*gap, 0);
13919     for (i = gap->ga_len - 1; i >= 0; --i)
13920     {
13921 	/* Need to append what follows to check for "the the". */
13922 	vim_strncpy(longword, stp[i].st_word, MAXWLEN);
13923 	len = stp[i].st_wordlen;
13924 	vim_strncpy(longword + len, su->su_badptr + stp[i].st_orglen,
13925 							       MAXWLEN - len);
13926 	attr = HLF_COUNT;
13927 	(void)spell_check(curwin, longword, &attr, NULL, FALSE);
13928 	if (attr != HLF_COUNT)
13929 	{
13930 	    /* Remove this entry. */
13931 	    vim_free(stp[i].st_word);
13932 	    --gap->ga_len;
13933 	    if (i < gap->ga_len)
13934 		mch_memmove(stp + i, stp + i + 1,
13935 				       sizeof(suggest_T) * (gap->ga_len - i));
13936 	}
13937     }
13938 }
13939 
13940 
13941 /*
13942  * Add a word to be banned.
13943  */
13944     static void
13945 add_banned(su, word)
13946     suginfo_T	*su;
13947     char_u	*word;
13948 {
13949     char_u	*s;
13950     hash_T	hash;
13951     hashitem_T	*hi;
13952 
13953     hash = hash_hash(word);
13954     hi = hash_lookup(&su->su_banned, word, hash);
13955     if (HASHITEM_EMPTY(hi))
13956     {
13957 	s = vim_strsave(word);
13958 	if (s != NULL)
13959 	    hash_add_item(&su->su_banned, hi, s, hash);
13960     }
13961 }
13962 
13963 /*
13964  * Recompute the score for all suggestions if sound-folding is possible.  This
13965  * is slow, thus only done for the final results.
13966  */
13967     static void
13968 rescore_suggestions(su)
13969     suginfo_T	*su;
13970 {
13971     int		i;
13972 
13973     if (su->su_sallang != NULL)
13974 	for (i = 0; i < su->su_ga.ga_len; ++i)
13975 	    rescore_one(su, &SUG(su->su_ga, i));
13976 }
13977 
13978 /*
13979  * Recompute the score for one suggestion if sound-folding is possible.
13980  */
13981     static void
13982 rescore_one(su, stp)
13983     suginfo_T	*su;
13984     suggest_T	*stp;
13985 {
13986     slang_T	*slang = stp->st_slang;
13987     char_u	sal_badword[MAXWLEN];
13988     char_u	*p;
13989 
13990     /* Only rescore suggestions that have no sal score yet and do have a
13991      * language. */
13992     if (slang != NULL && slang->sl_sal.ga_len > 0 && !stp->st_had_bonus)
13993     {
13994 	if (slang == su->su_sallang)
13995 	    p = su->su_sal_badword;
13996 	else
13997 	{
13998 	    spell_soundfold(slang, su->su_fbadword, TRUE, sal_badword);
13999 	    p = sal_badword;
14000 	}
14001 
14002 	stp->st_altscore = stp_sal_score(stp, su, slang, p);
14003 	if (stp->st_altscore == SCORE_MAXMAX)
14004 	    stp->st_altscore = SCORE_BIG;
14005 	stp->st_score = RESCORE(stp->st_score, stp->st_altscore);
14006 	stp->st_had_bonus = TRUE;
14007     }
14008 }
14009 
14010 static int
14011 #ifdef __BORLANDC__
14012 _RTLENTRYF
14013 #endif
14014 sug_compare __ARGS((const void *s1, const void *s2));
14015 
14016 /*
14017  * Function given to qsort() to sort the suggestions on st_score.
14018  * First on "st_score", then "st_altscore" then alphabetically.
14019  */
14020     static int
14021 #ifdef __BORLANDC__
14022 _RTLENTRYF
14023 #endif
14024 sug_compare(s1, s2)
14025     const void	*s1;
14026     const void	*s2;
14027 {
14028     suggest_T	*p1 = (suggest_T *)s1;
14029     suggest_T	*p2 = (suggest_T *)s2;
14030     int		n = p1->st_score - p2->st_score;
14031 
14032     if (n == 0)
14033     {
14034 	n = p1->st_altscore - p2->st_altscore;
14035 	if (n == 0)
14036 	    n = STRICMP(p1->st_word, p2->st_word);
14037     }
14038     return n;
14039 }
14040 
14041 /*
14042  * Cleanup the suggestions:
14043  * - Sort on score.
14044  * - Remove words that won't be displayed.
14045  * Returns the maximum score in the list or "maxscore" unmodified.
14046  */
14047     static int
14048 cleanup_suggestions(gap, maxscore, keep)
14049     garray_T	*gap;
14050     int		maxscore;
14051     int		keep;		/* nr of suggestions to keep */
14052 {
14053     suggest_T   *stp = &SUG(*gap, 0);
14054     int		i;
14055 
14056     /* Sort the list. */
14057     qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
14058 
14059     /* Truncate the list to the number of suggestions that will be displayed. */
14060     if (gap->ga_len > keep)
14061     {
14062 	for (i = keep; i < gap->ga_len; ++i)
14063 	    vim_free(stp[i].st_word);
14064 	gap->ga_len = keep;
14065 	return stp[keep - 1].st_score;
14066     }
14067     return maxscore;
14068 }
14069 
14070 #if defined(FEAT_EVAL) || defined(PROTO)
14071 /*
14072  * Soundfold a string, for soundfold().
14073  * Result is in allocated memory, NULL for an error.
14074  */
14075     char_u *
14076 eval_soundfold(word)
14077     char_u	*word;
14078 {
14079     langp_T	*lp;
14080     char_u	sound[MAXWLEN];
14081     int		lpi;
14082 
14083     if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
14084 	/* Use the sound-folding of the first language that supports it. */
14085 	for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
14086 	{
14087 	    lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
14088 	    if (lp->lp_slang->sl_sal.ga_len > 0)
14089 	    {
14090 		/* soundfold the word */
14091 		spell_soundfold(lp->lp_slang, word, FALSE, sound);
14092 		return vim_strsave(sound);
14093 	    }
14094 	}
14095 
14096     /* No language with sound folding, return word as-is. */
14097     return vim_strsave(word);
14098 }
14099 #endif
14100 
14101 /*
14102  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
14103  *
14104  * There are many ways to turn a word into a sound-a-like representation.  The
14105  * oldest is Soundex (1918!).   A nice overview can be found in "Approximate
14106  * swedish name matching - survey and test of different algorithms" by Klas
14107  * Erikson.
14108  *
14109  * We support two methods:
14110  * 1. SOFOFROM/SOFOTO do a simple character mapping.
14111  * 2. SAL items define a more advanced sound-folding (and much slower).
14112  */
14113     static void
14114 spell_soundfold(slang, inword, folded, res)
14115     slang_T	*slang;
14116     char_u	*inword;
14117     int		folded;	    /* "inword" is already case-folded */
14118     char_u	*res;
14119 {
14120     char_u	fword[MAXWLEN];
14121     char_u	*word;
14122 
14123     if (slang->sl_sofo)
14124 	/* SOFOFROM and SOFOTO used */
14125 	spell_soundfold_sofo(slang, inword, res);
14126     else
14127     {
14128 	/* SAL items used.  Requires the word to be case-folded. */
14129 	if (folded)
14130 	    word = inword;
14131 	else
14132 	{
14133 	    (void)spell_casefold(inword, (int)STRLEN(inword), fword, MAXWLEN);
14134 	    word = fword;
14135 	}
14136 
14137 #ifdef FEAT_MBYTE
14138 	if (has_mbyte)
14139 	    spell_soundfold_wsal(slang, word, res);
14140 	else
14141 #endif
14142 	    spell_soundfold_sal(slang, word, res);
14143     }
14144 }
14145 
14146 /*
14147  * Perform sound folding of "inword" into "res" according to SOFOFROM and
14148  * SOFOTO lines.
14149  */
14150     static void
14151 spell_soundfold_sofo(slang, inword, res)
14152     slang_T	*slang;
14153     char_u	*inword;
14154     char_u	*res;
14155 {
14156     char_u	*s;
14157     int		ri = 0;
14158     int		c;
14159 
14160 #ifdef FEAT_MBYTE
14161     if (has_mbyte)
14162     {
14163 	int	prevc = 0;
14164 	int	*ip;
14165 
14166 	/* The sl_sal_first[] table contains the translation for chars up to
14167 	 * 255, sl_sal the rest. */
14168 	for (s = inword; *s != NUL; )
14169 	{
14170 	    c = mb_cptr2char_adv(&s);
14171 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
14172 		c = ' ';
14173 	    else if (c < 256)
14174 		c = slang->sl_sal_first[c];
14175 	    else
14176 	    {
14177 		ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
14178 		if (ip == NULL)		/* empty list, can't match */
14179 		    c = NUL;
14180 		else
14181 		    for (;;)		/* find "c" in the list */
14182 		    {
14183 			if (*ip == 0)	/* not found */
14184 			{
14185 			    c = NUL;
14186 			    break;
14187 			}
14188 			if (*ip == c)	/* match! */
14189 			{
14190 			    c = ip[1];
14191 			    break;
14192 			}
14193 			ip += 2;
14194 		    }
14195 	    }
14196 
14197 	    if (c != NUL && c != prevc)
14198 	    {
14199 		ri += mb_char2bytes(c, res + ri);
14200 		if (ri + MB_MAXBYTES > MAXWLEN)
14201 		    break;
14202 		prevc = c;
14203 	    }
14204 	}
14205     }
14206     else
14207 #endif
14208     {
14209 	/* The sl_sal_first[] table contains the translation. */
14210 	for (s = inword; (c = *s) != NUL; ++s)
14211 	{
14212 	    if (vim_iswhite(c))
14213 		c = ' ';
14214 	    else
14215 		c = slang->sl_sal_first[c];
14216 	    if (c != NUL && (ri == 0 || res[ri - 1] != c))
14217 		res[ri++] = c;
14218 	}
14219     }
14220 
14221     res[ri] = NUL;
14222 }
14223 
14224     static void
14225 spell_soundfold_sal(slang, inword, res)
14226     slang_T	*slang;
14227     char_u	*inword;
14228     char_u	*res;
14229 {
14230     salitem_T	*smp;
14231     char_u	word[MAXWLEN];
14232     char_u	*s = inword;
14233     char_u	*t;
14234     char_u	*pf;
14235     int		i, j, z;
14236     int		reslen;
14237     int		n, k = 0;
14238     int		z0;
14239     int		k0;
14240     int		n0;
14241     int		c;
14242     int		pri;
14243     int		p0 = -333;
14244     int		c0;
14245 
14246     /* Remove accents, if wanted.  We actually remove all non-word characters.
14247      * But keep white space.  We need a copy, the word may be changed here. */
14248     if (slang->sl_rem_accents)
14249     {
14250 	t = word;
14251 	while (*s != NUL)
14252 	{
14253 	    if (vim_iswhite(*s))
14254 	    {
14255 		*t++ = ' ';
14256 		s = skipwhite(s);
14257 	    }
14258 	    else
14259 	    {
14260 		if (spell_iswordp_nmw(s, curwin))
14261 		    *t++ = *s;
14262 		++s;
14263 	    }
14264 	}
14265 	*t = NUL;
14266     }
14267     else
14268 	vim_strncpy(word, s, MAXWLEN - 1);
14269 
14270     smp = (salitem_T *)slang->sl_sal.ga_data;
14271 
14272     /*
14273      * This comes from Aspell phonet.cpp.  Converted from C++ to C.
14274      * Changed to keep spaces.
14275      */
14276     i = reslen = z = 0;
14277     while ((c = word[i]) != NUL)
14278     {
14279 	/* Start with the first rule that has the character in the word. */
14280 	n = slang->sl_sal_first[c];
14281 	z0 = 0;
14282 
14283 	if (n >= 0)
14284 	{
14285 	    /* check all rules for the same letter */
14286 	    for (; (s = smp[n].sm_lead)[0] == c; ++n)
14287 	    {
14288 		/* Quickly skip entries that don't match the word.  Most
14289 		 * entries are less then three chars, optimize for that. */
14290 		k = smp[n].sm_leadlen;
14291 		if (k > 1)
14292 		{
14293 		    if (word[i + 1] != s[1])
14294 			continue;
14295 		    if (k > 2)
14296 		    {
14297 			for (j = 2; j < k; ++j)
14298 			    if (word[i + j] != s[j])
14299 				break;
14300 			if (j < k)
14301 			    continue;
14302 		    }
14303 		}
14304 
14305 		if ((pf = smp[n].sm_oneof) != NULL)
14306 		{
14307 		    /* Check for match with one of the chars in "sm_oneof". */
14308 		    while (*pf != NUL && *pf != word[i + k])
14309 			++pf;
14310 		    if (*pf == NUL)
14311 			continue;
14312 		    ++k;
14313 		}
14314 		s = smp[n].sm_rules;
14315 		pri = 5;    /* default priority */
14316 
14317 		p0 = *s;
14318 		k0 = k;
14319 		while (*s == '-' && k > 1)
14320 		{
14321 		    k--;
14322 		    s++;
14323 		}
14324 		if (*s == '<')
14325 		    s++;
14326 		if (VIM_ISDIGIT(*s))
14327 		{
14328 		    /* determine priority */
14329 		    pri = *s - '0';
14330 		    s++;
14331 		}
14332 		if (*s == '^' && *(s + 1) == '^')
14333 		    s++;
14334 
14335 		if (*s == NUL
14336 			|| (*s == '^'
14337 			    && (i == 0 || !(word[i - 1] == ' '
14338 				      || spell_iswordp(word + i - 1, curwin)))
14339 			    && (*(s + 1) != '$'
14340 				|| (!spell_iswordp(word + i + k0, curwin))))
14341 			|| (*s == '$' && i > 0
14342 			    && spell_iswordp(word + i - 1, curwin)
14343 			    && (!spell_iswordp(word + i + k0, curwin))))
14344 		{
14345 		    /* search for followup rules, if:    */
14346 		    /* followup and k > 1  and  NO '-' in searchstring */
14347 		    c0 = word[i + k - 1];
14348 		    n0 = slang->sl_sal_first[c0];
14349 
14350 		    if (slang->sl_followup && k > 1 && n0 >= 0
14351 					   && p0 != '-' && word[i + k] != NUL)
14352 		    {
14353 			/* test follow-up rule for "word[i + k]" */
14354 			for ( ; (s = smp[n0].sm_lead)[0] == c0; ++n0)
14355 			{
14356 			    /* Quickly skip entries that don't match the word.
14357 			     * */
14358 			    k0 = smp[n0].sm_leadlen;
14359 			    if (k0 > 1)
14360 			    {
14361 				if (word[i + k] != s[1])
14362 				    continue;
14363 				if (k0 > 2)
14364 				{
14365 				    pf = word + i + k + 1;
14366 				    for (j = 2; j < k0; ++j)
14367 					if (*pf++ != s[j])
14368 					    break;
14369 				    if (j < k0)
14370 					continue;
14371 				}
14372 			    }
14373 			    k0 += k - 1;
14374 
14375 			    if ((pf = smp[n0].sm_oneof) != NULL)
14376 			    {
14377 				/* Check for match with one of the chars in
14378 				 * "sm_oneof". */
14379 				while (*pf != NUL && *pf != word[i + k0])
14380 				    ++pf;
14381 				if (*pf == NUL)
14382 				    continue;
14383 				++k0;
14384 			    }
14385 
14386 			    p0 = 5;
14387 			    s = smp[n0].sm_rules;
14388 			    while (*s == '-')
14389 			    {
14390 				/* "k0" gets NOT reduced because
14391 				 * "if (k0 == k)" */
14392 				s++;
14393 			    }
14394 			    if (*s == '<')
14395 				s++;
14396 			    if (VIM_ISDIGIT(*s))
14397 			    {
14398 				p0 = *s - '0';
14399 				s++;
14400 			    }
14401 
14402 			    if (*s == NUL
14403 				    /* *s == '^' cuts */
14404 				    || (*s == '$'
14405 					    && !spell_iswordp(word + i + k0,
14406 								     curwin)))
14407 			    {
14408 				if (k0 == k)
14409 				    /* this is just a piece of the string */
14410 				    continue;
14411 
14412 				if (p0 < pri)
14413 				    /* priority too low */
14414 				    continue;
14415 				/* rule fits; stop search */
14416 				break;
14417 			    }
14418 			}
14419 
14420 			if (p0 >= pri && smp[n0].sm_lead[0] == c0)
14421 			    continue;
14422 		    }
14423 
14424 		    /* replace string */
14425 		    s = smp[n].sm_to;
14426 		    if (s == NULL)
14427 			s = (char_u *)"";
14428 		    pf = smp[n].sm_rules;
14429 		    p0 = (vim_strchr(pf, '<') != NULL) ? 1 : 0;
14430 		    if (p0 == 1 && z == 0)
14431 		    {
14432 			/* rule with '<' is used */
14433 			if (reslen > 0 && *s != NUL && (res[reslen - 1] == c
14434 						    || res[reslen - 1] == *s))
14435 			    reslen--;
14436 			z0 = 1;
14437 			z = 1;
14438 			k0 = 0;
14439 			while (*s != NUL && word[i + k0] != NUL)
14440 			{
14441 			    word[i + k0] = *s;
14442 			    k0++;
14443 			    s++;
14444 			}
14445 			if (k > k0)
14446 			    STRMOVE(word + i + k0, word + i + k);
14447 
14448 			/* new "actual letter" */
14449 			c = word[i];
14450 		    }
14451 		    else
14452 		    {
14453 			/* no '<' rule used */
14454 			i += k - 1;
14455 			z = 0;
14456 			while (*s != NUL && s[1] != NUL && reslen < MAXWLEN)
14457 			{
14458 			    if (reslen == 0 || res[reslen - 1] != *s)
14459 				res[reslen++] = *s;
14460 			    s++;
14461 			}
14462 			/* new "actual letter" */
14463 			c = *s;
14464 			if (strstr((char *)pf, "^^") != NULL)
14465 			{
14466 			    if (c != NUL)
14467 				res[reslen++] = c;
14468 			    STRMOVE(word, word + i + 1);
14469 			    i = 0;
14470 			    z0 = 1;
14471 			}
14472 		    }
14473 		    break;
14474 		}
14475 	    }
14476 	}
14477 	else if (vim_iswhite(c))
14478 	{
14479 	    c = ' ';
14480 	    k = 1;
14481 	}
14482 
14483 	if (z0 == 0)
14484 	{
14485 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
14486 		    && (!slang->sl_collapse || reslen == 0
14487 						     || res[reslen - 1] != c))
14488 		/* condense only double letters */
14489 		res[reslen++] = c;
14490 
14491 	    i++;
14492 	    z = 0;
14493 	    k = 0;
14494 	}
14495     }
14496 
14497     res[reslen] = NUL;
14498 }
14499 
14500 #ifdef FEAT_MBYTE
14501 /*
14502  * Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
14503  * Multi-byte version of spell_soundfold().
14504  */
14505     static void
14506 spell_soundfold_wsal(slang, inword, res)
14507     slang_T	*slang;
14508     char_u	*inword;
14509     char_u	*res;
14510 {
14511     salitem_T	*smp = (salitem_T *)slang->sl_sal.ga_data;
14512     int		word[MAXWLEN];
14513     int		wres[MAXWLEN];
14514     int		l;
14515     char_u	*s;
14516     int		*ws;
14517     char_u	*t;
14518     int		*pf;
14519     int		i, j, z;
14520     int		reslen;
14521     int		n, k = 0;
14522     int		z0;
14523     int		k0;
14524     int		n0;
14525     int		c;
14526     int		pri;
14527     int		p0 = -333;
14528     int		c0;
14529     int		did_white = FALSE;
14530     int		wordlen;
14531 
14532 
14533     /*
14534      * Convert the multi-byte string to a wide-character string.
14535      * Remove accents, if wanted.  We actually remove all non-word characters.
14536      * But keep white space.
14537      */
14538     wordlen = 0;
14539     for (s = inword; *s != NUL; )
14540     {
14541 	t = s;
14542 	c = mb_cptr2char_adv(&s);
14543 	if (slang->sl_rem_accents)
14544 	{
14545 	    if (enc_utf8 ? utf_class(c) == 0 : vim_iswhite(c))
14546 	    {
14547 		if (did_white)
14548 		    continue;
14549 		c = ' ';
14550 		did_white = TRUE;
14551 	    }
14552 	    else
14553 	    {
14554 		did_white = FALSE;
14555 		if (!spell_iswordp_nmw(t, curwin))
14556 		    continue;
14557 	    }
14558 	}
14559 	word[wordlen++] = c;
14560     }
14561     word[wordlen] = NUL;
14562 
14563     /*
14564      * This algorithm comes from Aspell phonet.cpp.
14565      * Converted from C++ to C.  Added support for multi-byte chars.
14566      * Changed to keep spaces.
14567      */
14568     i = reslen = z = 0;
14569     while ((c = word[i]) != NUL)
14570     {
14571 	/* Start with the first rule that has the character in the word. */
14572 	n = slang->sl_sal_first[c & 0xff];
14573 	z0 = 0;
14574 
14575 	if (n >= 0)
14576 	{
14577 	    /* Check all rules for the same index byte.
14578 	     * If c is 0x300 need extra check for the end of the array, as
14579 	     * (c & 0xff) is NUL. */
14580 	    for (; ((ws = smp[n].sm_lead_w)[0] & 0xff) == (c & 0xff)
14581 							 && ws[0] != NUL; ++n)
14582 	    {
14583 		/* Quickly skip entries that don't match the word.  Most
14584 		 * entries are less then three chars, optimize for that. */
14585 		if (c != ws[0])
14586 		    continue;
14587 		k = smp[n].sm_leadlen;
14588 		if (k > 1)
14589 		{
14590 		    if (word[i + 1] != ws[1])
14591 			continue;
14592 		    if (k > 2)
14593 		    {
14594 			for (j = 2; j < k; ++j)
14595 			    if (word[i + j] != ws[j])
14596 				break;
14597 			if (j < k)
14598 			    continue;
14599 		    }
14600 		}
14601 
14602 		if ((pf = smp[n].sm_oneof_w) != NULL)
14603 		{
14604 		    /* Check for match with one of the chars in "sm_oneof". */
14605 		    while (*pf != NUL && *pf != word[i + k])
14606 			++pf;
14607 		    if (*pf == NUL)
14608 			continue;
14609 		    ++k;
14610 		}
14611 		s = smp[n].sm_rules;
14612 		pri = 5;    /* default priority */
14613 
14614 		p0 = *s;
14615 		k0 = k;
14616 		while (*s == '-' && k > 1)
14617 		{
14618 		    k--;
14619 		    s++;
14620 		}
14621 		if (*s == '<')
14622 		    s++;
14623 		if (VIM_ISDIGIT(*s))
14624 		{
14625 		    /* determine priority */
14626 		    pri = *s - '0';
14627 		    s++;
14628 		}
14629 		if (*s == '^' && *(s + 1) == '^')
14630 		    s++;
14631 
14632 		if (*s == NUL
14633 			|| (*s == '^'
14634 			    && (i == 0 || !(word[i - 1] == ' '
14635 				    || spell_iswordp_w(word + i - 1, curwin)))
14636 			    && (*(s + 1) != '$'
14637 				|| (!spell_iswordp_w(word + i + k0, curwin))))
14638 			|| (*s == '$' && i > 0
14639 			    && spell_iswordp_w(word + i - 1, curwin)
14640 			    && (!spell_iswordp_w(word + i + k0, curwin))))
14641 		{
14642 		    /* search for followup rules, if:    */
14643 		    /* followup and k > 1  and  NO '-' in searchstring */
14644 		    c0 = word[i + k - 1];
14645 		    n0 = slang->sl_sal_first[c0 & 0xff];
14646 
14647 		    if (slang->sl_followup && k > 1 && n0 >= 0
14648 					   && p0 != '-' && word[i + k] != NUL)
14649 		    {
14650 			/* Test follow-up rule for "word[i + k]"; loop over
14651 			 * all entries with the same index byte. */
14652 			for ( ; ((ws = smp[n0].sm_lead_w)[0] & 0xff)
14653 							 == (c0 & 0xff); ++n0)
14654 			{
14655 			    /* Quickly skip entries that don't match the word.
14656 			     */
14657 			    if (c0 != ws[0])
14658 				continue;
14659 			    k0 = smp[n0].sm_leadlen;
14660 			    if (k0 > 1)
14661 			    {
14662 				if (word[i + k] != ws[1])
14663 				    continue;
14664 				if (k0 > 2)
14665 				{
14666 				    pf = word + i + k + 1;
14667 				    for (j = 2; j < k0; ++j)
14668 					if (*pf++ != ws[j])
14669 					    break;
14670 				    if (j < k0)
14671 					continue;
14672 				}
14673 			    }
14674 			    k0 += k - 1;
14675 
14676 			    if ((pf = smp[n0].sm_oneof_w) != NULL)
14677 			    {
14678 				/* Check for match with one of the chars in
14679 				 * "sm_oneof". */
14680 				while (*pf != NUL && *pf != word[i + k0])
14681 				    ++pf;
14682 				if (*pf == NUL)
14683 				    continue;
14684 				++k0;
14685 			    }
14686 
14687 			    p0 = 5;
14688 			    s = smp[n0].sm_rules;
14689 			    while (*s == '-')
14690 			    {
14691 				/* "k0" gets NOT reduced because
14692 				 * "if (k0 == k)" */
14693 				s++;
14694 			    }
14695 			    if (*s == '<')
14696 				s++;
14697 			    if (VIM_ISDIGIT(*s))
14698 			    {
14699 				p0 = *s - '0';
14700 				s++;
14701 			    }
14702 
14703 			    if (*s == NUL
14704 				    /* *s == '^' cuts */
14705 				    || (*s == '$'
14706 					 && !spell_iswordp_w(word + i + k0,
14707 								     curwin)))
14708 			    {
14709 				if (k0 == k)
14710 				    /* this is just a piece of the string */
14711 				    continue;
14712 
14713 				if (p0 < pri)
14714 				    /* priority too low */
14715 				    continue;
14716 				/* rule fits; stop search */
14717 				break;
14718 			    }
14719 			}
14720 
14721 			if (p0 >= pri && (smp[n0].sm_lead_w[0] & 0xff)
14722 							       == (c0 & 0xff))
14723 			    continue;
14724 		    }
14725 
14726 		    /* replace string */
14727 		    ws = smp[n].sm_to_w;
14728 		    s = smp[n].sm_rules;
14729 		    p0 = (vim_strchr(s, '<') != NULL) ? 1 : 0;
14730 		    if (p0 == 1 && z == 0)
14731 		    {
14732 			/* rule with '<' is used */
14733 			if (reslen > 0 && ws != NULL && *ws != NUL
14734 				&& (wres[reslen - 1] == c
14735 						    || wres[reslen - 1] == *ws))
14736 			    reslen--;
14737 			z0 = 1;
14738 			z = 1;
14739 			k0 = 0;
14740 			if (ws != NULL)
14741 			    while (*ws != NUL && word[i + k0] != NUL)
14742 			    {
14743 				word[i + k0] = *ws;
14744 				k0++;
14745 				ws++;
14746 			    }
14747 			if (k > k0)
14748 			    mch_memmove(word + i + k0, word + i + k,
14749 				    sizeof(int) * (wordlen - (i + k) + 1));
14750 
14751 			/* new "actual letter" */
14752 			c = word[i];
14753 		    }
14754 		    else
14755 		    {
14756 			/* no '<' rule used */
14757 			i += k - 1;
14758 			z = 0;
14759 			if (ws != NULL)
14760 			    while (*ws != NUL && ws[1] != NUL
14761 							  && reslen < MAXWLEN)
14762 			    {
14763 				if (reslen == 0 || wres[reslen - 1] != *ws)
14764 				    wres[reslen++] = *ws;
14765 				ws++;
14766 			    }
14767 			/* new "actual letter" */
14768 			if (ws == NULL)
14769 			    c = NUL;
14770 			else
14771 			    c = *ws;
14772 			if (strstr((char *)s, "^^") != NULL)
14773 			{
14774 			    if (c != NUL)
14775 				wres[reslen++] = c;
14776 			    mch_memmove(word, word + i + 1,
14777 				       sizeof(int) * (wordlen - (i + 1) + 1));
14778 			    i = 0;
14779 			    z0 = 1;
14780 			}
14781 		    }
14782 		    break;
14783 		}
14784 	    }
14785 	}
14786 	else if (vim_iswhite(c))
14787 	{
14788 	    c = ' ';
14789 	    k = 1;
14790 	}
14791 
14792 	if (z0 == 0)
14793 	{
14794 	    if (k && !p0 && reslen < MAXWLEN && c != NUL
14795 		    && (!slang->sl_collapse || reslen == 0
14796 						     || wres[reslen - 1] != c))
14797 		/* condense only double letters */
14798 		wres[reslen++] = c;
14799 
14800 	    i++;
14801 	    z = 0;
14802 	    k = 0;
14803 	}
14804     }
14805 
14806     /* Convert wide characters in "wres" to a multi-byte string in "res". */
14807     l = 0;
14808     for (n = 0; n < reslen; ++n)
14809     {
14810 	l += mb_char2bytes(wres[n], res + l);
14811 	if (l + MB_MAXBYTES > MAXWLEN)
14812 	    break;
14813     }
14814     res[l] = NUL;
14815 }
14816 #endif
14817 
14818 /*
14819  * Compute a score for two sound-a-like words.
14820  * This permits up to two inserts/deletes/swaps/etc. to keep things fast.
14821  * Instead of a generic loop we write out the code.  That keeps it fast by
14822  * avoiding checks that will not be possible.
14823  */
14824     static int
14825 soundalike_score(goodstart, badstart)
14826     char_u	*goodstart;	/* sound-folded good word */
14827     char_u	*badstart;	/* sound-folded bad word */
14828 {
14829     char_u	*goodsound = goodstart;
14830     char_u	*badsound = badstart;
14831     int		goodlen;
14832     int		badlen;
14833     int		n;
14834     char_u	*pl, *ps;
14835     char_u	*pl2, *ps2;
14836     int		score = 0;
14837 
14838     /* Adding/inserting "*" at the start (word starts with vowel) shouldn't be
14839      * counted so much, vowels halfway the word aren't counted at all. */
14840     if ((*badsound == '*' || *goodsound == '*') && *badsound != *goodsound)
14841     {
14842 	if ((badsound[0] == NUL && goodsound[1] == NUL)
14843 	    || (goodsound[0] == NUL && badsound[1] == NUL))
14844 	    /* changing word with vowel to word without a sound */
14845 	    return SCORE_DEL;
14846 	if (badsound[0] == NUL || goodsound[0] == NUL)
14847 	    /* more than two changes */
14848 	    return SCORE_MAXMAX;
14849 
14850 	if (badsound[1] == goodsound[1]
14851 		|| (badsound[1] != NUL
14852 		    && goodsound[1] != NUL
14853 		    && badsound[2] == goodsound[2]))
14854 	{
14855 	    /* handle like a substitute */
14856 	}
14857 	else
14858 	{
14859 	    score = 2 * SCORE_DEL / 3;
14860 	    if (*badsound == '*')
14861 		++badsound;
14862 	    else
14863 		++goodsound;
14864 	}
14865     }
14866 
14867     goodlen = (int)STRLEN(goodsound);
14868     badlen = (int)STRLEN(badsound);
14869 
14870     /* Return quickly if the lengths are too different to be fixed by two
14871      * changes. */
14872     n = goodlen - badlen;
14873     if (n < -2 || n > 2)
14874 	return SCORE_MAXMAX;
14875 
14876     if (n > 0)
14877     {
14878 	pl = goodsound;	    /* goodsound is longest */
14879 	ps = badsound;
14880     }
14881     else
14882     {
14883 	pl = badsound;	    /* badsound is longest */
14884 	ps = goodsound;
14885     }
14886 
14887     /* Skip over the identical part. */
14888     while (*pl == *ps && *pl != NUL)
14889     {
14890 	++pl;
14891 	++ps;
14892     }
14893 
14894     switch (n)
14895     {
14896 	case -2:
14897 	case 2:
14898 	    /*
14899 	     * Must delete two characters from "pl".
14900 	     */
14901 	    ++pl;	/* first delete */
14902 	    while (*pl == *ps)
14903 	    {
14904 		++pl;
14905 		++ps;
14906 	    }
14907 	    /* strings must be equal after second delete */
14908 	    if (STRCMP(pl + 1, ps) == 0)
14909 		return score + SCORE_DEL * 2;
14910 
14911 	    /* Failed to compare. */
14912 	    break;
14913 
14914 	case -1:
14915 	case 1:
14916 	    /*
14917 	     * Minimal one delete from "pl" required.
14918 	     */
14919 
14920 	    /* 1: delete */
14921 	    pl2 = pl + 1;
14922 	    ps2 = ps;
14923 	    while (*pl2 == *ps2)
14924 	    {
14925 		if (*pl2 == NUL)	/* reached the end */
14926 		    return score + SCORE_DEL;
14927 		++pl2;
14928 		++ps2;
14929 	    }
14930 
14931 	    /* 2: delete then swap, then rest must be equal */
14932 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
14933 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
14934 		return score + SCORE_DEL + SCORE_SWAP;
14935 
14936 	    /* 3: delete then substitute, then the rest must be equal */
14937 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
14938 		return score + SCORE_DEL + SCORE_SUBST;
14939 
14940 	    /* 4: first swap then delete */
14941 	    if (pl[0] == ps[1] && pl[1] == ps[0])
14942 	    {
14943 		pl2 = pl + 2;	    /* swap, skip two chars */
14944 		ps2 = ps + 2;
14945 		while (*pl2 == *ps2)
14946 		{
14947 		    ++pl2;
14948 		    ++ps2;
14949 		}
14950 		/* delete a char and then strings must be equal */
14951 		if (STRCMP(pl2 + 1, ps2) == 0)
14952 		    return score + SCORE_SWAP + SCORE_DEL;
14953 	    }
14954 
14955 	    /* 5: first substitute then delete */
14956 	    pl2 = pl + 1;	    /* substitute, skip one char */
14957 	    ps2 = ps + 1;
14958 	    while (*pl2 == *ps2)
14959 	    {
14960 		++pl2;
14961 		++ps2;
14962 	    }
14963 	    /* delete a char and then strings must be equal */
14964 	    if (STRCMP(pl2 + 1, ps2) == 0)
14965 		return score + SCORE_SUBST + SCORE_DEL;
14966 
14967 	    /* Failed to compare. */
14968 	    break;
14969 
14970 	case 0:
14971 	    /*
14972 	     * Lengths are equal, thus changes must result in same length: An
14973 	     * insert is only possible in combination with a delete.
14974 	     * 1: check if for identical strings
14975 	     */
14976 	    if (*pl == NUL)
14977 		return score;
14978 
14979 	    /* 2: swap */
14980 	    if (pl[0] == ps[1] && pl[1] == ps[0])
14981 	    {
14982 		pl2 = pl + 2;	    /* swap, skip two chars */
14983 		ps2 = ps + 2;
14984 		while (*pl2 == *ps2)
14985 		{
14986 		    if (*pl2 == NUL)	/* reached the end */
14987 			return score + SCORE_SWAP;
14988 		    ++pl2;
14989 		    ++ps2;
14990 		}
14991 		/* 3: swap and swap again */
14992 		if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
14993 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
14994 		    return score + SCORE_SWAP + SCORE_SWAP;
14995 
14996 		/* 4: swap and substitute */
14997 		if (STRCMP(pl2 + 1, ps2 + 1) == 0)
14998 		    return score + SCORE_SWAP + SCORE_SUBST;
14999 	    }
15000 
15001 	    /* 5: substitute */
15002 	    pl2 = pl + 1;
15003 	    ps2 = ps + 1;
15004 	    while (*pl2 == *ps2)
15005 	    {
15006 		if (*pl2 == NUL)	/* reached the end */
15007 		    return score + SCORE_SUBST;
15008 		++pl2;
15009 		++ps2;
15010 	    }
15011 
15012 	    /* 6: substitute and swap */
15013 	    if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
15014 					     && STRCMP(pl2 + 2, ps2 + 2) == 0)
15015 		return score + SCORE_SUBST + SCORE_SWAP;
15016 
15017 	    /* 7: substitute and substitute */
15018 	    if (STRCMP(pl2 + 1, ps2 + 1) == 0)
15019 		return score + SCORE_SUBST + SCORE_SUBST;
15020 
15021 	    /* 8: insert then delete */
15022 	    pl2 = pl;
15023 	    ps2 = ps + 1;
15024 	    while (*pl2 == *ps2)
15025 	    {
15026 		++pl2;
15027 		++ps2;
15028 	    }
15029 	    if (STRCMP(pl2 + 1, ps2) == 0)
15030 		return score + SCORE_INS + SCORE_DEL;
15031 
15032 	    /* 9: delete then insert */
15033 	    pl2 = pl + 1;
15034 	    ps2 = ps;
15035 	    while (*pl2 == *ps2)
15036 	    {
15037 		++pl2;
15038 		++ps2;
15039 	    }
15040 	    if (STRCMP(pl2, ps2 + 1) == 0)
15041 		return score + SCORE_INS + SCORE_DEL;
15042 
15043 	    /* Failed to compare. */
15044 	    break;
15045     }
15046 
15047     return SCORE_MAXMAX;
15048 }
15049 
15050 /*
15051  * Compute the "edit distance" to turn "badword" into "goodword".  The less
15052  * deletes/inserts/substitutes/swaps are required the lower the score.
15053  *
15054  * The algorithm is described by Du and Chang, 1992.
15055  * The implementation of the algorithm comes from Aspell editdist.cpp,
15056  * edit_distance().  It has been converted from C++ to C and modified to
15057  * support multi-byte characters.
15058  */
15059     static int
15060 spell_edit_score(slang, badword, goodword)
15061     slang_T	*slang;
15062     char_u	*badword;
15063     char_u	*goodword;
15064 {
15065     int		*cnt;
15066     int		badlen, goodlen;	/* lengths including NUL */
15067     int		j, i;
15068     int		t;
15069     int		bc, gc;
15070     int		pbc, pgc;
15071 #ifdef FEAT_MBYTE
15072     char_u	*p;
15073     int		wbadword[MAXWLEN];
15074     int		wgoodword[MAXWLEN];
15075 
15076     if (has_mbyte)
15077     {
15078 	/* Get the characters from the multi-byte strings and put them in an
15079 	 * int array for easy access. */
15080 	for (p = badword, badlen = 0; *p != NUL; )
15081 	    wbadword[badlen++] = mb_cptr2char_adv(&p);
15082 	wbadword[badlen++] = 0;
15083 	for (p = goodword, goodlen = 0; *p != NUL; )
15084 	    wgoodword[goodlen++] = mb_cptr2char_adv(&p);
15085 	wgoodword[goodlen++] = 0;
15086     }
15087     else
15088 #endif
15089     {
15090 	badlen = (int)STRLEN(badword) + 1;
15091 	goodlen = (int)STRLEN(goodword) + 1;
15092     }
15093 
15094     /* We use "cnt" as an array: CNT(badword_idx, goodword_idx). */
15095 #define CNT(a, b)   cnt[(a) + (b) * (badlen + 1)]
15096     cnt = (int *)lalloc((long_u)(sizeof(int) * (badlen + 1) * (goodlen + 1)),
15097 									TRUE);
15098     if (cnt == NULL)
15099 	return 0;	/* out of memory */
15100 
15101     CNT(0, 0) = 0;
15102     for (j = 1; j <= goodlen; ++j)
15103 	CNT(0, j) = CNT(0, j - 1) + SCORE_INS;
15104 
15105     for (i = 1; i <= badlen; ++i)
15106     {
15107 	CNT(i, 0) = CNT(i - 1, 0) + SCORE_DEL;
15108 	for (j = 1; j <= goodlen; ++j)
15109 	{
15110 #ifdef FEAT_MBYTE
15111 	    if (has_mbyte)
15112 	    {
15113 		bc = wbadword[i - 1];
15114 		gc = wgoodword[j - 1];
15115 	    }
15116 	    else
15117 #endif
15118 	    {
15119 		bc = badword[i - 1];
15120 		gc = goodword[j - 1];
15121 	    }
15122 	    if (bc == gc)
15123 		CNT(i, j) = CNT(i - 1, j - 1);
15124 	    else
15125 	    {
15126 		/* Use a better score when there is only a case difference. */
15127 		if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15128 		    CNT(i, j) = SCORE_ICASE + CNT(i - 1, j - 1);
15129 		else
15130 		{
15131 		    /* For a similar character use SCORE_SIMILAR. */
15132 		    if (slang != NULL
15133 			    && slang->sl_has_map
15134 			    && similar_chars(slang, gc, bc))
15135 			CNT(i, j) = SCORE_SIMILAR + CNT(i - 1, j - 1);
15136 		    else
15137 			CNT(i, j) = SCORE_SUBST + CNT(i - 1, j - 1);
15138 		}
15139 
15140 		if (i > 1 && j > 1)
15141 		{
15142 #ifdef FEAT_MBYTE
15143 		    if (has_mbyte)
15144 		    {
15145 			pbc = wbadword[i - 2];
15146 			pgc = wgoodword[j - 2];
15147 		    }
15148 		    else
15149 #endif
15150 		    {
15151 			pbc = badword[i - 2];
15152 			pgc = goodword[j - 2];
15153 		    }
15154 		    if (bc == pgc && pbc == gc)
15155 		    {
15156 			t = SCORE_SWAP + CNT(i - 2, j - 2);
15157 			if (t < CNT(i, j))
15158 			    CNT(i, j) = t;
15159 		    }
15160 		}
15161 		t = SCORE_DEL + CNT(i - 1, j);
15162 		if (t < CNT(i, j))
15163 		    CNT(i, j) = t;
15164 		t = SCORE_INS + CNT(i, j - 1);
15165 		if (t < CNT(i, j))
15166 		    CNT(i, j) = t;
15167 	    }
15168 	}
15169     }
15170 
15171     i = CNT(badlen - 1, goodlen - 1);
15172     vim_free(cnt);
15173     return i;
15174 }
15175 
15176 typedef struct
15177 {
15178     int		badi;
15179     int		goodi;
15180     int		score;
15181 } limitscore_T;
15182 
15183 /*
15184  * Like spell_edit_score(), but with a limit on the score to make it faster.
15185  * May return SCORE_MAXMAX when the score is higher than "limit".
15186  *
15187  * This uses a stack for the edits still to be tried.
15188  * The idea comes from Aspell leditdist.cpp.  Rewritten in C and added support
15189  * for multi-byte characters.
15190  */
15191     static int
15192 spell_edit_score_limit(slang, badword, goodword, limit)
15193     slang_T	*slang;
15194     char_u	*badword;
15195     char_u	*goodword;
15196     int		limit;
15197 {
15198     limitscore_T    stack[10];		/* allow for over 3 * 2 edits */
15199     int		    stackidx;
15200     int		    bi, gi;
15201     int		    bi2, gi2;
15202     int		    bc, gc;
15203     int		    score;
15204     int		    score_off;
15205     int		    minscore;
15206     int		    round;
15207 
15208 #ifdef FEAT_MBYTE
15209     /* Multi-byte characters require a bit more work, use a different function
15210      * to avoid testing "has_mbyte" quite often. */
15211     if (has_mbyte)
15212 	return spell_edit_score_limit_w(slang, badword, goodword, limit);
15213 #endif
15214 
15215     /*
15216      * The idea is to go from start to end over the words.  So long as
15217      * characters are equal just continue, this always gives the lowest score.
15218      * When there is a difference try several alternatives.  Each alternative
15219      * increases "score" for the edit distance.  Some of the alternatives are
15220      * pushed unto a stack and tried later, some are tried right away.  At the
15221      * end of the word the score for one alternative is known.  The lowest
15222      * possible score is stored in "minscore".
15223      */
15224     stackidx = 0;
15225     bi = 0;
15226     gi = 0;
15227     score = 0;
15228     minscore = limit + 1;
15229 
15230     for (;;)
15231     {
15232 	/* Skip over an equal part, score remains the same. */
15233 	for (;;)
15234 	{
15235 	    bc = badword[bi];
15236 	    gc = goodword[gi];
15237 	    if (bc != gc)	/* stop at a char that's different */
15238 		break;
15239 	    if (bc == NUL)	/* both words end */
15240 	    {
15241 		if (score < minscore)
15242 		    minscore = score;
15243 		goto pop;	/* do next alternative */
15244 	    }
15245 	    ++bi;
15246 	    ++gi;
15247 	}
15248 
15249 	if (gc == NUL)    /* goodword ends, delete badword chars */
15250 	{
15251 	    do
15252 	    {
15253 		if ((score += SCORE_DEL) >= minscore)
15254 		    goto pop;	    /* do next alternative */
15255 	    } while (badword[++bi] != NUL);
15256 	    minscore = score;
15257 	}
15258 	else if (bc == NUL) /* badword ends, insert badword chars */
15259 	{
15260 	    do
15261 	    {
15262 		if ((score += SCORE_INS) >= minscore)
15263 		    goto pop;	    /* do next alternative */
15264 	    } while (goodword[++gi] != NUL);
15265 	    minscore = score;
15266 	}
15267 	else			/* both words continue */
15268 	{
15269 	    /* If not close to the limit, perform a change.  Only try changes
15270 	     * that may lead to a lower score than "minscore".
15271 	     * round 0: try deleting a char from badword
15272 	     * round 1: try inserting a char in badword */
15273 	    for (round = 0; round <= 1; ++round)
15274 	    {
15275 		score_off = score + (round == 0 ? SCORE_DEL : SCORE_INS);
15276 		if (score_off < minscore)
15277 		{
15278 		    if (score_off + SCORE_EDIT_MIN >= minscore)
15279 		    {
15280 			/* Near the limit, rest of the words must match.  We
15281 			 * can check that right now, no need to push an item
15282 			 * onto the stack. */
15283 			bi2 = bi + 1 - round;
15284 			gi2 = gi + round;
15285 			while (goodword[gi2] == badword[bi2])
15286 			{
15287 			    if (goodword[gi2] == NUL)
15288 			    {
15289 				minscore = score_off;
15290 				break;
15291 			    }
15292 			    ++bi2;
15293 			    ++gi2;
15294 			}
15295 		    }
15296 		    else
15297 		    {
15298 			/* try deleting/inserting a character later */
15299 			stack[stackidx].badi = bi + 1 - round;
15300 			stack[stackidx].goodi = gi + round;
15301 			stack[stackidx].score = score_off;
15302 			++stackidx;
15303 		    }
15304 		}
15305 	    }
15306 
15307 	    if (score + SCORE_SWAP < minscore)
15308 	    {
15309 		/* If swapping two characters makes a match then the
15310 		 * substitution is more expensive, thus there is no need to
15311 		 * try both. */
15312 		if (gc == badword[bi + 1] && bc == goodword[gi + 1])
15313 		{
15314 		    /* Swap two characters, that is: skip them. */
15315 		    gi += 2;
15316 		    bi += 2;
15317 		    score += SCORE_SWAP;
15318 		    continue;
15319 		}
15320 	    }
15321 
15322 	    /* Substitute one character for another which is the same
15323 	     * thing as deleting a character from both goodword and badword.
15324 	     * Use a better score when there is only a case difference. */
15325 	    if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15326 		score += SCORE_ICASE;
15327 	    else
15328 	    {
15329 		/* For a similar character use SCORE_SIMILAR. */
15330 		if (slang != NULL
15331 			&& slang->sl_has_map
15332 			&& similar_chars(slang, gc, bc))
15333 		    score += SCORE_SIMILAR;
15334 		else
15335 		    score += SCORE_SUBST;
15336 	    }
15337 
15338 	    if (score < minscore)
15339 	    {
15340 		/* Do the substitution. */
15341 		++gi;
15342 		++bi;
15343 		continue;
15344 	    }
15345 	}
15346 pop:
15347 	/*
15348 	 * Get here to try the next alternative, pop it from the stack.
15349 	 */
15350 	if (stackidx == 0)		/* stack is empty, finished */
15351 	    break;
15352 
15353 	/* pop an item from the stack */
15354 	--stackidx;
15355 	gi = stack[stackidx].goodi;
15356 	bi = stack[stackidx].badi;
15357 	score = stack[stackidx].score;
15358     }
15359 
15360     /* When the score goes over "limit" it may actually be much higher.
15361      * Return a very large number to avoid going below the limit when giving a
15362      * bonus. */
15363     if (minscore > limit)
15364 	return SCORE_MAXMAX;
15365     return minscore;
15366 }
15367 
15368 #ifdef FEAT_MBYTE
15369 /*
15370  * Multi-byte version of spell_edit_score_limit().
15371  * Keep it in sync with the above!
15372  */
15373     static int
15374 spell_edit_score_limit_w(slang, badword, goodword, limit)
15375     slang_T	*slang;
15376     char_u	*badword;
15377     char_u	*goodword;
15378     int		limit;
15379 {
15380     limitscore_T    stack[10];		/* allow for over 3 * 2 edits */
15381     int		    stackidx;
15382     int		    bi, gi;
15383     int		    bi2, gi2;
15384     int		    bc, gc;
15385     int		    score;
15386     int		    score_off;
15387     int		    minscore;
15388     int		    round;
15389     char_u	    *p;
15390     int		    wbadword[MAXWLEN];
15391     int		    wgoodword[MAXWLEN];
15392 
15393     /* Get the characters from the multi-byte strings and put them in an
15394      * int array for easy access. */
15395     bi = 0;
15396     for (p = badword; *p != NUL; )
15397 	wbadword[bi++] = mb_cptr2char_adv(&p);
15398     wbadword[bi++] = 0;
15399     gi = 0;
15400     for (p = goodword; *p != NUL; )
15401 	wgoodword[gi++] = mb_cptr2char_adv(&p);
15402     wgoodword[gi++] = 0;
15403 
15404     /*
15405      * The idea is to go from start to end over the words.  So long as
15406      * characters are equal just continue, this always gives the lowest score.
15407      * When there is a difference try several alternatives.  Each alternative
15408      * increases "score" for the edit distance.  Some of the alternatives are
15409      * pushed unto a stack and tried later, some are tried right away.  At the
15410      * end of the word the score for one alternative is known.  The lowest
15411      * possible score is stored in "minscore".
15412      */
15413     stackidx = 0;
15414     bi = 0;
15415     gi = 0;
15416     score = 0;
15417     minscore = limit + 1;
15418 
15419     for (;;)
15420     {
15421 	/* Skip over an equal part, score remains the same. */
15422 	for (;;)
15423 	{
15424 	    bc = wbadword[bi];
15425 	    gc = wgoodword[gi];
15426 
15427 	    if (bc != gc)	/* stop at a char that's different */
15428 		break;
15429 	    if (bc == NUL)	/* both words end */
15430 	    {
15431 		if (score < minscore)
15432 		    minscore = score;
15433 		goto pop;	/* do next alternative */
15434 	    }
15435 	    ++bi;
15436 	    ++gi;
15437 	}
15438 
15439 	if (gc == NUL)    /* goodword ends, delete badword chars */
15440 	{
15441 	    do
15442 	    {
15443 		if ((score += SCORE_DEL) >= minscore)
15444 		    goto pop;	    /* do next alternative */
15445 	    } while (wbadword[++bi] != NUL);
15446 	    minscore = score;
15447 	}
15448 	else if (bc == NUL) /* badword ends, insert badword chars */
15449 	{
15450 	    do
15451 	    {
15452 		if ((score += SCORE_INS) >= minscore)
15453 		    goto pop;	    /* do next alternative */
15454 	    } while (wgoodword[++gi] != NUL);
15455 	    minscore = score;
15456 	}
15457 	else			/* both words continue */
15458 	{
15459 	    /* If not close to the limit, perform a change.  Only try changes
15460 	     * that may lead to a lower score than "minscore".
15461 	     * round 0: try deleting a char from badword
15462 	     * round 1: try inserting a char in badword */
15463 	    for (round = 0; round <= 1; ++round)
15464 	    {
15465 		score_off = score + (round == 0 ? SCORE_DEL : SCORE_INS);
15466 		if (score_off < minscore)
15467 		{
15468 		    if (score_off + SCORE_EDIT_MIN >= minscore)
15469 		    {
15470 			/* Near the limit, rest of the words must match.  We
15471 			 * can check that right now, no need to push an item
15472 			 * onto the stack. */
15473 			bi2 = bi + 1 - round;
15474 			gi2 = gi + round;
15475 			while (wgoodword[gi2] == wbadword[bi2])
15476 			{
15477 			    if (wgoodword[gi2] == NUL)
15478 			    {
15479 				minscore = score_off;
15480 				break;
15481 			    }
15482 			    ++bi2;
15483 			    ++gi2;
15484 			}
15485 		    }
15486 		    else
15487 		    {
15488 			/* try deleting a character from badword later */
15489 			stack[stackidx].badi = bi + 1 - round;
15490 			stack[stackidx].goodi = gi + round;
15491 			stack[stackidx].score = score_off;
15492 			++stackidx;
15493 		    }
15494 		}
15495 	    }
15496 
15497 	    if (score + SCORE_SWAP < minscore)
15498 	    {
15499 		/* If swapping two characters makes a match then the
15500 		 * substitution is more expensive, thus there is no need to
15501 		 * try both. */
15502 		if (gc == wbadword[bi + 1] && bc == wgoodword[gi + 1])
15503 		{
15504 		    /* Swap two characters, that is: skip them. */
15505 		    gi += 2;
15506 		    bi += 2;
15507 		    score += SCORE_SWAP;
15508 		    continue;
15509 		}
15510 	    }
15511 
15512 	    /* Substitute one character for another which is the same
15513 	     * thing as deleting a character from both goodword and badword.
15514 	     * Use a better score when there is only a case difference. */
15515 	    if (SPELL_TOFOLD(bc) == SPELL_TOFOLD(gc))
15516 		score += SCORE_ICASE;
15517 	    else
15518 	    {
15519 		/* For a similar character use SCORE_SIMILAR. */
15520 		if (slang != NULL
15521 			&& slang->sl_has_map
15522 			&& similar_chars(slang, gc, bc))
15523 		    score += SCORE_SIMILAR;
15524 		else
15525 		    score += SCORE_SUBST;
15526 	    }
15527 
15528 	    if (score < minscore)
15529 	    {
15530 		/* Do the substitution. */
15531 		++gi;
15532 		++bi;
15533 		continue;
15534 	    }
15535 	}
15536 pop:
15537 	/*
15538 	 * Get here to try the next alternative, pop it from the stack.
15539 	 */
15540 	if (stackidx == 0)		/* stack is empty, finished */
15541 	    break;
15542 
15543 	/* pop an item from the stack */
15544 	--stackidx;
15545 	gi = stack[stackidx].goodi;
15546 	bi = stack[stackidx].badi;
15547 	score = stack[stackidx].score;
15548     }
15549 
15550     /* When the score goes over "limit" it may actually be much higher.
15551      * Return a very large number to avoid going below the limit when giving a
15552      * bonus. */
15553     if (minscore > limit)
15554 	return SCORE_MAXMAX;
15555     return minscore;
15556 }
15557 #endif
15558 
15559 /*
15560  * ":spellinfo"
15561  */
15562     void
15563 ex_spellinfo(eap)
15564     exarg_T *eap UNUSED;
15565 {
15566     int		lpi;
15567     langp_T	*lp;
15568     char_u	*p;
15569 
15570     if (no_spell_checking(curwin))
15571 	return;
15572 
15573     msg_start();
15574     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi)
15575     {
15576 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
15577 	msg_puts((char_u *)"file: ");
15578 	msg_puts(lp->lp_slang->sl_fname);
15579 	msg_putchar('\n');
15580 	p = lp->lp_slang->sl_info;
15581 	if (p != NULL)
15582 	{
15583 	    msg_puts(p);
15584 	    msg_putchar('\n');
15585 	}
15586     }
15587     msg_end();
15588 }
15589 
15590 #define DUMPFLAG_KEEPCASE   1	/* round 2: keep-case tree */
15591 #define DUMPFLAG_COUNT	    2	/* include word count */
15592 #define DUMPFLAG_ICASE	    4	/* ignore case when finding matches */
15593 #define DUMPFLAG_ONECAP	    8	/* pattern starts with capital */
15594 #define DUMPFLAG_ALLCAP	    16	/* pattern is all capitals */
15595 
15596 /*
15597  * ":spelldump"
15598  */
15599     void
15600 ex_spelldump(eap)
15601     exarg_T *eap;
15602 {
15603     char_u  *spl;
15604     long    dummy;
15605 
15606     if (no_spell_checking(curwin))
15607 	return;
15608     get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
15609 
15610     /* Create a new empty buffer in a new window. */
15611     do_cmdline_cmd((char_u *)"new");
15612 
15613     /* enable spelling locally in the new window */
15614     set_option_value((char_u*)"spell", TRUE, (char_u*)"", OPT_LOCAL);
15615     set_option_value((char_u*)"spl",  dummy,         spl, OPT_LOCAL);
15616     vim_free(spl);
15617 
15618     if (!bufempty() || !buf_valid(curbuf))
15619 	return;
15620 
15621     spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0);
15622 
15623     /* Delete the empty line that we started with. */
15624     if (curbuf->b_ml.ml_line_count > 1)
15625 	ml_delete(curbuf->b_ml.ml_line_count, FALSE);
15626 
15627     redraw_later(NOT_VALID);
15628 }
15629 
15630 /*
15631  * Go through all possible words and:
15632  * 1. When "pat" is NULL: dump a list of all words in the current buffer.
15633  *	"ic" and "dir" are not used.
15634  * 2. When "pat" is not NULL: add matching words to insert mode completion.
15635  */
15636     void
15637 spell_dump_compl(pat, ic, dir, dumpflags_arg)
15638     char_u	*pat;	    /* leading part of the word */
15639     int		ic;	    /* ignore case */
15640     int		*dir;	    /* direction for adding matches */
15641     int		dumpflags_arg;	/* DUMPFLAG_* */
15642 {
15643     langp_T	*lp;
15644     slang_T	*slang;
15645     idx_T	arridx[MAXWLEN];
15646     int		curi[MAXWLEN];
15647     char_u	word[MAXWLEN];
15648     int		c;
15649     char_u	*byts;
15650     idx_T	*idxs;
15651     linenr_T	lnum = 0;
15652     int		round;
15653     int		depth;
15654     int		n;
15655     int		flags;
15656     char_u	*region_names = NULL;	    /* region names being used */
15657     int		do_region = TRUE;	    /* dump region names and numbers */
15658     char_u	*p;
15659     int		lpi;
15660     int		dumpflags = dumpflags_arg;
15661     int		patlen;
15662 
15663     /* When ignoring case or when the pattern starts with capital pass this on
15664      * to dump_word(). */
15665     if (pat != NULL)
15666     {
15667 	if (ic)
15668 	    dumpflags |= DUMPFLAG_ICASE;
15669 	else
15670 	{
15671 	    n = captype(pat, NULL);
15672 	    if (n == WF_ONECAP)
15673 		dumpflags |= DUMPFLAG_ONECAP;
15674 	    else if (n == WF_ALLCAP
15675 #ifdef FEAT_MBYTE
15676 		    && (int)STRLEN(pat) > mb_ptr2len(pat)
15677 #else
15678 		    && (int)STRLEN(pat) > 1
15679 #endif
15680 		    )
15681 		dumpflags |= DUMPFLAG_ALLCAP;
15682 	}
15683     }
15684 
15685     /* Find out if we can support regions: All languages must support the same
15686      * regions or none at all. */
15687     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
15688     {
15689 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
15690 	p = lp->lp_slang->sl_regions;
15691 	if (p[0] != 0)
15692 	{
15693 	    if (region_names == NULL)	    /* first language with regions */
15694 		region_names = p;
15695 	    else if (STRCMP(region_names, p) != 0)
15696 	    {
15697 		do_region = FALSE;	    /* region names are different */
15698 		break;
15699 	    }
15700 	}
15701     }
15702 
15703     if (do_region && region_names != NULL)
15704     {
15705 	if (pat == NULL)
15706 	{
15707 	    vim_snprintf((char *)IObuff, IOSIZE, "/regions=%s", region_names);
15708 	    ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
15709 	}
15710     }
15711     else
15712 	do_region = FALSE;
15713 
15714     /*
15715      * Loop over all files loaded for the entries in 'spelllang'.
15716      */
15717     for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
15718     {
15719 	lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
15720 	slang = lp->lp_slang;
15721 	if (slang->sl_fbyts == NULL)	    /* reloading failed */
15722 	    continue;
15723 
15724 	if (pat == NULL)
15725 	{
15726 	    vim_snprintf((char *)IObuff, IOSIZE, "# file: %s", slang->sl_fname);
15727 	    ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
15728 	}
15729 
15730 	/* When matching with a pattern and there are no prefixes only use
15731 	 * parts of the tree that match "pat". */
15732 	if (pat != NULL && slang->sl_pbyts == NULL)
15733 	    patlen = (int)STRLEN(pat);
15734 	else
15735 	    patlen = -1;
15736 
15737 	/* round 1: case-folded tree
15738 	 * round 2: keep-case tree */
15739 	for (round = 1; round <= 2; ++round)
15740 	{
15741 	    if (round == 1)
15742 	    {
15743 		dumpflags &= ~DUMPFLAG_KEEPCASE;
15744 		byts = slang->sl_fbyts;
15745 		idxs = slang->sl_fidxs;
15746 	    }
15747 	    else
15748 	    {
15749 		dumpflags |= DUMPFLAG_KEEPCASE;
15750 		byts = slang->sl_kbyts;
15751 		idxs = slang->sl_kidxs;
15752 	    }
15753 	    if (byts == NULL)
15754 		continue;		/* array is empty */
15755 
15756 	    depth = 0;
15757 	    arridx[0] = 0;
15758 	    curi[0] = 1;
15759 	    while (depth >= 0 && !got_int
15760 				       && (pat == NULL || !compl_interrupted))
15761 	    {
15762 		if (curi[depth] > byts[arridx[depth]])
15763 		{
15764 		    /* Done all bytes at this node, go up one level. */
15765 		    --depth;
15766 		    line_breakcheck();
15767 		    ins_compl_check_keys(50);
15768 		}
15769 		else
15770 		{
15771 		    /* Do one more byte at this node. */
15772 		    n = arridx[depth] + curi[depth];
15773 		    ++curi[depth];
15774 		    c = byts[n];
15775 		    if (c == 0)
15776 		    {
15777 			/* End of word, deal with the word.
15778 			 * Don't use keep-case words in the fold-case tree,
15779 			 * they will appear in the keep-case tree.
15780 			 * Only use the word when the region matches. */
15781 			flags = (int)idxs[n];
15782 			if ((round == 2 || (flags & WF_KEEPCAP) == 0)
15783 				&& (flags & WF_NEEDCOMP) == 0
15784 				&& (do_region
15785 				    || (flags & WF_REGION) == 0
15786 				    || (((unsigned)flags >> 16)
15787 						       & lp->lp_region) != 0))
15788 			{
15789 			    word[depth] = NUL;
15790 			    if (!do_region)
15791 				flags &= ~WF_REGION;
15792 
15793 			    /* Dump the basic word if there is no prefix or
15794 			     * when it's the first one. */
15795 			    c = (unsigned)flags >> 24;
15796 			    if (c == 0 || curi[depth] == 2)
15797 			    {
15798 				dump_word(slang, word, pat, dir,
15799 						      dumpflags, flags, lnum);
15800 				if (pat == NULL)
15801 				    ++lnum;
15802 			    }
15803 
15804 			    /* Apply the prefix, if there is one. */
15805 			    if (c != 0)
15806 				lnum = dump_prefixes(slang, word, pat, dir,
15807 						      dumpflags, flags, lnum);
15808 			}
15809 		    }
15810 		    else
15811 		    {
15812 			/* Normal char, go one level deeper. */
15813 			word[depth++] = c;
15814 			arridx[depth] = idxs[n];
15815 			curi[depth] = 1;
15816 
15817 			/* Check if this characters matches with the pattern.
15818 			 * If not skip the whole tree below it.
15819 			 * Always ignore case here, dump_word() will check
15820 			 * proper case later.  This isn't exactly right when
15821 			 * length changes for multi-byte characters with
15822 			 * ignore case... */
15823 			if (depth <= patlen
15824 					&& MB_STRNICMP(word, pat, depth) != 0)
15825 			    --depth;
15826 		    }
15827 		}
15828 	    }
15829 	}
15830     }
15831 }
15832 
15833 /*
15834  * Dump one word: apply case modifications and append a line to the buffer.
15835  * When "lnum" is zero add insert mode completion.
15836  */
15837     static void
15838 dump_word(slang, word, pat, dir, dumpflags, wordflags, lnum)
15839     slang_T	*slang;
15840     char_u	*word;
15841     char_u	*pat;
15842     int		*dir;
15843     int		dumpflags;
15844     int		wordflags;
15845     linenr_T	lnum;
15846 {
15847     int		keepcap = FALSE;
15848     char_u	*p;
15849     char_u	*tw;
15850     char_u	cword[MAXWLEN];
15851     char_u	badword[MAXWLEN + 10];
15852     int		i;
15853     int		flags = wordflags;
15854 
15855     if (dumpflags & DUMPFLAG_ONECAP)
15856 	flags |= WF_ONECAP;
15857     if (dumpflags & DUMPFLAG_ALLCAP)
15858 	flags |= WF_ALLCAP;
15859 
15860     if ((dumpflags & DUMPFLAG_KEEPCASE) == 0 && (flags & WF_CAPMASK) != 0)
15861     {
15862 	/* Need to fix case according to "flags". */
15863 	make_case_word(word, cword, flags);
15864 	p = cword;
15865     }
15866     else
15867     {
15868 	p = word;
15869 	if ((dumpflags & DUMPFLAG_KEEPCASE)
15870 		&& ((captype(word, NULL) & WF_KEEPCAP) == 0
15871 						 || (flags & WF_FIXCAP) != 0))
15872 	    keepcap = TRUE;
15873     }
15874     tw = p;
15875 
15876     if (pat == NULL)
15877     {
15878 	/* Add flags and regions after a slash. */
15879 	if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap)
15880 	{
15881 	    STRCPY(badword, p);
15882 	    STRCAT(badword, "/");
15883 	    if (keepcap)
15884 		STRCAT(badword, "=");
15885 	    if (flags & WF_BANNED)
15886 		STRCAT(badword, "!");
15887 	    else if (flags & WF_RARE)
15888 		STRCAT(badword, "?");
15889 	    if (flags & WF_REGION)
15890 		for (i = 0; i < 7; ++i)
15891 		    if (flags & (0x10000 << i))
15892 			sprintf((char *)badword + STRLEN(badword), "%d", i + 1);
15893 	    p = badword;
15894 	}
15895 
15896 	if (dumpflags & DUMPFLAG_COUNT)
15897 	{
15898 	    hashitem_T  *hi;
15899 
15900 	    /* Include the word count for ":spelldump!". */
15901 	    hi = hash_find(&slang->sl_wordcount, tw);
15902 	    if (!HASHITEM_EMPTY(hi))
15903 	    {
15904 		vim_snprintf((char *)IObuff, IOSIZE, "%s\t%d",
15905 						     tw, HI2WC(hi)->wc_count);
15906 		p = IObuff;
15907 	    }
15908 	}
15909 
15910 	ml_append(lnum, p, (colnr_T)0, FALSE);
15911     }
15912     else if (((dumpflags & DUMPFLAG_ICASE)
15913 		    ? MB_STRNICMP(p, pat, STRLEN(pat)) == 0
15914 		    : STRNCMP(p, pat, STRLEN(pat)) == 0)
15915 		&& ins_compl_add_infercase(p, (int)STRLEN(p),
15916 					  p_ic, NULL, *dir, 0) == OK)
15917 	/* if dir was BACKWARD then honor it just once */
15918 	*dir = FORWARD;
15919 }
15920 
15921 /*
15922  * For ":spelldump": Find matching prefixes for "word".  Prepend each to
15923  * "word" and append a line to the buffer.
15924  * When "lnum" is zero add insert mode completion.
15925  * Return the updated line number.
15926  */
15927     static linenr_T
15928 dump_prefixes(slang, word, pat, dir, dumpflags, flags, startlnum)
15929     slang_T	*slang;
15930     char_u	*word;	    /* case-folded word */
15931     char_u	*pat;
15932     int		*dir;
15933     int		dumpflags;
15934     int		flags;	    /* flags with prefix ID */
15935     linenr_T	startlnum;
15936 {
15937     idx_T	arridx[MAXWLEN];
15938     int		curi[MAXWLEN];
15939     char_u	prefix[MAXWLEN];
15940     char_u	word_up[MAXWLEN];
15941     int		has_word_up = FALSE;
15942     int		c;
15943     char_u	*byts;
15944     idx_T	*idxs;
15945     linenr_T	lnum = startlnum;
15946     int		depth;
15947     int		n;
15948     int		len;
15949     int		i;
15950 
15951     /* If the word starts with a lower-case letter make the word with an
15952      * upper-case letter in word_up[]. */
15953     c = PTR2CHAR(word);
15954     if (SPELL_TOUPPER(c) != c)
15955     {
15956 	onecap_copy(word, word_up, TRUE);
15957 	has_word_up = TRUE;
15958     }
15959 
15960     byts = slang->sl_pbyts;
15961     idxs = slang->sl_pidxs;
15962     if (byts != NULL)		/* array not is empty */
15963     {
15964 	/*
15965 	 * Loop over all prefixes, building them byte-by-byte in prefix[].
15966 	 * When at the end of a prefix check that it supports "flags".
15967 	 */
15968 	depth = 0;
15969 	arridx[0] = 0;
15970 	curi[0] = 1;
15971 	while (depth >= 0 && !got_int)
15972 	{
15973 	    n = arridx[depth];
15974 	    len = byts[n];
15975 	    if (curi[depth] > len)
15976 	    {
15977 		/* Done all bytes at this node, go up one level. */
15978 		--depth;
15979 		line_breakcheck();
15980 	    }
15981 	    else
15982 	    {
15983 		/* Do one more byte at this node. */
15984 		n += curi[depth];
15985 		++curi[depth];
15986 		c = byts[n];
15987 		if (c == 0)
15988 		{
15989 		    /* End of prefix, find out how many IDs there are. */
15990 		    for (i = 1; i < len; ++i)
15991 			if (byts[n + i] != 0)
15992 			    break;
15993 		    curi[depth] += i - 1;
15994 
15995 		    c = valid_word_prefix(i, n, flags, word, slang, FALSE);
15996 		    if (c != 0)
15997 		    {
15998 			vim_strncpy(prefix + depth, word, MAXWLEN - depth - 1);
15999 			dump_word(slang, prefix, pat, dir, dumpflags,
16000 				(c & WF_RAREPFX) ? (flags | WF_RARE)
16001 							       : flags, lnum);
16002 			if (lnum != 0)
16003 			    ++lnum;
16004 		    }
16005 
16006 		    /* Check for prefix that matches the word when the
16007 		     * first letter is upper-case, but only if the prefix has
16008 		     * a condition. */
16009 		    if (has_word_up)
16010 		    {
16011 			c = valid_word_prefix(i, n, flags, word_up, slang,
16012 									TRUE);
16013 			if (c != 0)
16014 			{
16015 			    vim_strncpy(prefix + depth, word_up,
16016 							 MAXWLEN - depth - 1);
16017 			    dump_word(slang, prefix, pat, dir, dumpflags,
16018 				    (c & WF_RAREPFX) ? (flags | WF_RARE)
16019 							       : flags, lnum);
16020 			    if (lnum != 0)
16021 				++lnum;
16022 			}
16023 		    }
16024 		}
16025 		else
16026 		{
16027 		    /* Normal char, go one level deeper. */
16028 		    prefix[depth++] = c;
16029 		    arridx[depth] = idxs[n];
16030 		    curi[depth] = 1;
16031 		}
16032 	    }
16033 	}
16034     }
16035 
16036     return lnum;
16037 }
16038 
16039 /*
16040  * Move "p" to the end of word "start".
16041  * Uses the spell-checking word characters.
16042  */
16043     char_u *
16044 spell_to_word_end(start, win)
16045     char_u  *start;
16046     win_T   *win;
16047 {
16048     char_u  *p = start;
16049 
16050     while (*p != NUL && spell_iswordp(p, win))
16051 	mb_ptr_adv(p);
16052     return p;
16053 }
16054 
16055 #if defined(FEAT_INS_EXPAND) || defined(PROTO)
16056 /*
16057  * For Insert mode completion CTRL-X s:
16058  * Find start of the word in front of column "startcol".
16059  * We don't check if it is badly spelled, with completion we can only change
16060  * the word in front of the cursor.
16061  * Returns the column number of the word.
16062  */
16063     int
16064 spell_word_start(startcol)
16065     int		startcol;
16066 {
16067     char_u	*line;
16068     char_u	*p;
16069     int		col = 0;
16070 
16071     if (no_spell_checking(curwin))
16072 	return startcol;
16073 
16074     /* Find a word character before "startcol". */
16075     line = ml_get_curline();
16076     for (p = line + startcol; p > line; )
16077     {
16078 	mb_ptr_back(line, p);
16079 	if (spell_iswordp_nmw(p, curwin))
16080 	    break;
16081     }
16082 
16083     /* Go back to start of the word. */
16084     while (p > line)
16085     {
16086 	col = (int)(p - line);
16087 	mb_ptr_back(line, p);
16088 	if (!spell_iswordp(p, curwin))
16089 	    break;
16090 	col = 0;
16091     }
16092 
16093     return col;
16094 }
16095 
16096 /*
16097  * Need to check for 'spellcapcheck' now, the word is removed before
16098  * expand_spelling() is called.  Therefore the ugly global variable.
16099  */
16100 static int spell_expand_need_cap;
16101 
16102     void
16103 spell_expand_check_cap(col)
16104     colnr_T col;
16105 {
16106     spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col);
16107 }
16108 
16109 /*
16110  * Get list of spelling suggestions.
16111  * Used for Insert mode completion CTRL-X ?.
16112  * Returns the number of matches.  The matches are in "matchp[]", array of
16113  * allocated strings.
16114  */
16115     int
16116 expand_spelling(lnum, pat, matchp)
16117     linenr_T	lnum UNUSED;
16118     char_u	*pat;
16119     char_u	***matchp;
16120 {
16121     garray_T	ga;
16122 
16123     spell_suggest_list(&ga, pat, 100, spell_expand_need_cap, TRUE);
16124     *matchp = ga.ga_data;
16125     return ga.ga_len;
16126 }
16127 #endif
16128 
16129 #endif  /* FEAT_SPELL */
16130