components/vim/vim72-patches/7.2.060
changeset 198 172fc01ce997
equal deleted inserted replaced
197:fd801ec0737c 198:172fc01ce997
       
     1 To: [email protected]
       
     2 Subject: Patch 7.2.060
       
     3 Fcc: outbox
       
     4 From: Bram Moolenaar <[email protected]>
       
     5 Mime-Version: 1.0
       
     6 Content-Type: text/plain; charset=ISO-8859-1
       
     7 Content-Transfer-Encoding: 8bit
       
     8 ------------
       
     9 
       
    10 Patch 7.2.060
       
    11 Problem:    When a spell files has many compound rules it may take a very long
       
    12 	    time making the list of suggestions.  Displaying also can be slow
       
    13 	    when there are misspelled words.
       
    14 	    Can't parse some Hunspell .aff files.
       
    15 Solution:   Check if a compounding can possibly work before trying a
       
    16 	    combination, if the compound rules don't contain wildcards.
       
    17 	    Implement using CHECKCOMPOUNDPATTERN.
       
    18 	    Ignore COMPOUNDRULES.  Ignore a comment after most items.
       
    19 	    Accept ONLYINCOMPOUND as an alias for NEEDCOMPOUND.
       
    20 	    Accept FORBIDDENWORD as an alias for BAD.
       
    21 Files:	    runtime/doc/spell.txt, src/spell.c
       
    22 
       
    23 
       
    24 *** ../vim-7.2.059/runtime/doc/spell.txt	Sat Aug  9 19:36:52 2008
       
    25 --- runtime/doc/spell.txt	Sun Nov 30 16:30:02 2008
       
    26 ***************
       
    27 *** 1,4 ****
       
    28 ! *spell.txt*	For Vim version 7.2.  Last change: 2008 Jun 21
       
    29   
       
    30   
       
    31   		  VIM REFERENCE MANUAL	  by Bram Moolenaar
       
    32 --- 1,4 ----
       
    33 ! *spell.txt*	For Vim version 7.2.  Last change: 2008 Nov 30
       
    34   
       
    35   
       
    36   		  VIM REFERENCE MANUAL	  by Bram Moolenaar
       
    37 ***************
       
    38 *** 831,838 ****
       
    39   
       
    40   	# comment line ~
       
    41   
       
    42 ! With some items it's also possible to put a comment after it, but this isn't
       
    43 ! supported in general.
       
    44   
       
    45   
       
    46   ENCODING							*spell-SET*
       
    47 --- 831,841 ----
       
    48   
       
    49   	# comment line ~
       
    50   
       
    51 ! Items with a fixed number of arguments can be followed by a comment.  But only
       
    52 ! if none of the arguments can contain white space.  The comment must start with
       
    53 ! a "#" character.  Example:
       
    54 ! 
       
    55 ! 	KEEPCASE =  # fix case for words with this flag ~
       
    56   
       
    57   
       
    58   ENCODING							*spell-SET*
       
    59 ***************
       
    60 *** 965,970 ****
       
    61 --- 968,976 ----
       
    62   
       
    63   Note: When using utf-8 only characters up to 65000 may be used for flags.
       
    64   
       
    65 + Note: even when using "num" or "long" the number of flags available to
       
    66 + compounding and prefixes is limited to about 250.
       
    67 + 
       
    68   
       
    69   AFFIXES
       
    70   					    *spell-PFX* *spell-SFX*
       
    71 ***************
       
    72 *** 1178,1183 ****
       
    73 --- 1185,1193 ----
       
    74   The flag also applies to the word with affixes, thus this can be used to mark
       
    75   a whole bunch of related words as bad.
       
    76   
       
    77 + 							*spell-FORBIDDENWORD*
       
    78 + FORBIDDENWORD can be used just like BAD.  For compatibility with Hunspell.
       
    79 + 
       
    80   							*spell-NEEDAFFIX*
       
    81   The NEEDAFFIX flag is used to require that a word is used with an affix.  The
       
    82   word itself is not a good word (unless there is an empty affix).  Example:
       
    83 ***************
       
    84 *** 1268,1273 ****
       
    85 --- 1278,1287 ----
       
    86   
       
    87   	NEEDCOMPOUND & ~
       
    88   
       
    89 + 							*spell-ONLYINCOMPOUND*
       
    90 + The ONLYINCOMPOUND does exactly the same as NEEDCOMPOUND.  Supported for
       
    91 + compatiblity with Hunspell.
       
    92 + 
       
    93   							*spell-COMPOUNDMIN*
       
    94   The minimal character length of a word used for compounding is specified with
       
    95   COMPOUNDMIN.  Example:
       
    96 ***************
       
    97 *** 1328,1333 ****
       
    98 --- 1342,1361 ----
       
    99   rules.  Can also be used for an affix to count the affix as a compounding
       
   100   word.
       
   101   
       
   102 + 						*spell-CHECKCOMPOUNDPATTERN*
       
   103 + CHECKCOMPOUNDPATTERN is used to define patterns that, when matching at the
       
   104 + position where two words are compounded together forbids the compound.
       
   105 + For example:
       
   106 + 	CHECKCOMPOUNDPATTERN o e ~
       
   107 + 
       
   108 + This forbids compounding if the first word ends in "o" and the second word
       
   109 + starts with "e".
       
   110 + 
       
   111 + The arguments must be plain text, no patterns are actually supported, despite
       
   112 + the item name.  Case is always ignored.
       
   113 + 
       
   114 + The Hunspell feature to use three arguments and flags is not supported.
       
   115 + 
       
   116   							*spell-SYLLABLE*
       
   117   The SYLLABLE item defines characters or character sequences that are used to
       
   118   count the number of syllables in a word.  Example:
       
   119 ***************
       
   120 *** 1496,1501 ****
       
   121 --- 1524,1533 ----
       
   122   ACCENT		(Hunspell)				*spell-ACCENT*
       
   123   		Use MAP instead. |spell-MAP|
       
   124   
       
   125 + BREAK		(Hunspell)				*spell-BREAK*
       
   126 + 		Define break points.  Unclear how it works exactly.
       
   127 + 		Not supported.
       
   128 + 
       
   129   CHECKCOMPOUNDCASE  (Hunspell)			*spell-CHECKCOMPOUNDCASE*
       
   130   		Disallow uppercase letters at compound word boundaries.
       
   131   		Not supported.
       
   132 ***************
       
   133 *** 1512,1520 ****
       
   134   		Forbid three identical characters when compounding.  Not
       
   135   		supported.
       
   136   
       
   137 - CHECKCOMPOUNDPATTERN  (Hunspell)		*spell-CHECKCOMPOUNDPATTERN*
       
   138 - 		Forbid compounding when patterns match.  Not supported.
       
   139 - 
       
   140   COMPLEXPREFIXES  (Hunspell)				*spell-COMPLEXPREFIXES*
       
   141   		Enables using two prefixes.  Not supported.
       
   142   
       
   143 --- 1544,1549 ----
       
   144 ***************
       
   145 *** 1536,1548 ****
       
   146   COMPOUNDMIDDLE	(Hunspell)				*spell-COMPOUNDMIDDLE*
       
   147   		Use COMPOUNDRULE instead. |spell-COMPOUNDRULE|
       
   148   
       
   149   COMPOUNDSYLLABLE  (Hunspell)			*spell-COMPOUNDSYLLABLE*
       
   150   		Use SYLLABLE and COMPOUNDSYLMAX instead. |spell-SYLLABLE|
       
   151   		|spell-COMPOUNDSYLMAX|
       
   152   
       
   153 ! FORBIDDENWORD	(Hunspell)				*spell-FORBIDDENWORD*
       
   154 ! 		Use BAD instead. |spell-BAD|
       
   155 ! 
       
   156   LANG		(Hunspell)				*spell-LANG*
       
   157   		This specifies language-specific behavior.  This actually
       
   158   		moves part of the language knowledge into the program,
       
   159 --- 1565,1582 ----
       
   160   COMPOUNDMIDDLE	(Hunspell)				*spell-COMPOUNDMIDDLE*
       
   161   		Use COMPOUNDRULE instead. |spell-COMPOUNDRULE|
       
   162   
       
   163 + COMPOUNDRULES	(Hunspell)				*spell-COMPOUNDRULES*
       
   164 + 		Number of COMPOUNDRULE lines following.  Ignored, but the
       
   165 + 		argument must be a number.
       
   166 + 
       
   167   COMPOUNDSYLLABLE  (Hunspell)			*spell-COMPOUNDSYLLABLE*
       
   168   		Use SYLLABLE and COMPOUNDSYLMAX instead. |spell-SYLLABLE|
       
   169   		|spell-COMPOUNDSYLMAX|
       
   170   
       
   171 ! KEY		(Hunspell)				*spell-KEY*
       
   172 ! 		Define characters that are close together on the keyboard.
       
   173 ! 		Used to give better suggestions.  Not supported.
       
   174 ! 		
       
   175   LANG		(Hunspell)				*spell-LANG*
       
   176   		This specifies language-specific behavior.  This actually
       
   177   		moves part of the language knowledge into the program,
       
   178 ***************
       
   179 *** 1553,1562 ****
       
   180   		Only needed for morphological analysis.
       
   181   
       
   182   MAXNGRAMSUGS	(Hunspell)				*spell-MAXNGRAMSUGS*
       
   183 ! 		Not supported.
       
   184 ! 
       
   185 ! ONLYINCOMPOUND	(Hunspell)				*spell-ONLYINCOMPOUND*
       
   186 ! 		Use NEEDCOMPOUND instead. |spell-NEEDCOMPOUND|
       
   187   
       
   188   PSEUDOROOT	(Hunspell)				*spell-PSEUDOROOT*
       
   189   		Use NEEDAFFIX instead. |spell-NEEDAFFIX|
       
   190 --- 1587,1593 ----
       
   191   		Only needed for morphological analysis.
       
   192   
       
   193   MAXNGRAMSUGS	(Hunspell)				*spell-MAXNGRAMSUGS*
       
   194 ! 		Set number of n-gram suggestions.  Not supported.
       
   195   
       
   196   PSEUDOROOT	(Hunspell)				*spell-PSEUDOROOT*
       
   197   		Use NEEDAFFIX instead. |spell-NEEDAFFIX|
       
   198 *** ../vim-7.2.059/src/spell.c	Sat Nov 29 20:18:44 2008
       
   199 --- src/spell.c	Sun Nov 30 20:59:13 2008
       
   200 ***************
       
   201 *** 469,474 ****
       
   202 --- 469,475 ----
       
   203       garray_T	sl_comppat;	/* CHECKCOMPOUNDPATTERN items */
       
   204       regprog_T	*sl_compprog;	/* COMPOUNDRULE turned into a regexp progrm
       
   205   				 * (NULL when no compounding) */
       
   206 +     char_u	*sl_comprules;	/* all COMPOUNDRULE concatenated (or NULL) */
       
   207       char_u	*sl_compstartflags; /* flags for first compound word */
       
   208       char_u	*sl_compallflags; /* all flags for compound words */
       
   209       char_u	sl_nobreak;	/* When TRUE: no spaces between words */
       
   210 ***************
       
   211 *** 839,845 ****
       
   212 --- 840,849 ----
       
   213   static void slang_clear __ARGS((slang_T *lp));
       
   214   static void slang_clear_sug __ARGS((slang_T *lp));
       
   215   static void find_word __ARGS((matchinf_T *mip, int mode));
       
   216 + static int match_checkcompoundpattern __ARGS((char_u *ptr, int wlen, garray_T *gap));
       
   217   static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags));
       
   218 + static int can_be_compound __ARGS((trystate_T *sp, slang_T *slang, char_u *compflags, int flag));
       
   219 + static int match_compoundrule __ARGS((slang_T *slang, char_u *compflags));
       
   220   static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req));
       
   221   static void find_prefix __ARGS((matchinf_T *mip, int mode));
       
   222   static int fold_more __ARGS((matchinf_T *mip));
       
   223 ***************
       
   224 *** 1519,1524 ****
       
   225 --- 1523,1533 ----
       
   226   					    ((unsigned)flags >> 24)))
       
   227   		    continue;
       
   228   
       
   229 + 		/* If there is a match with a CHECKCOMPOUNDPATTERN rule
       
   230 + 		 * discard the compound word. */
       
   231 + 		if (match_checkcompoundpattern(ptr, wlen, &slang->sl_comppat))
       
   232 + 		    continue;
       
   233 + 
       
   234   		if (mode == FIND_COMPOUND)
       
   235   		{
       
   236   		    int	    capflags;
       
   237 ***************
       
   238 *** 1577,1582 ****
       
   239 --- 1586,1596 ----
       
   240   		    if (!can_compound(slang, fword, mip->mi_compflags))
       
   241   			continue;
       
   242   		}
       
   243 + 		else if (slang->sl_comprules != NULL
       
   244 + 			     && !match_compoundrule(slang, mip->mi_compflags))
       
   245 + 		    /* The compound flags collected so far do not match any
       
   246 + 		     * COMPOUNDRULE, discard the compounded word. */
       
   247 + 		    continue;
       
   248   	    }
       
   249   
       
   250   	    /* Check NEEDCOMPOUND: can't use word without compounding. */
       
   251 ***************
       
   252 *** 1727,1732 ****
       
   253 --- 1741,1779 ----
       
   254   }
       
   255   
       
   256   /*
       
   257 +  * Return TRUE if there is a match between the word ptr[wlen] and
       
   258 +  * CHECKCOMPOUNDPATTERN rules, assuming that we will concatenate with another
       
   259 +  * word.
       
   260 +  * A match means that the first part of CHECKCOMPOUNDPATTERN matches at the
       
   261 +  * end of ptr[wlen] and the second part matches after it.
       
   262 +  */
       
   263 +     static int
       
   264 + match_checkcompoundpattern(ptr, wlen, gap)
       
   265 +     char_u	*ptr;
       
   266 +     int		wlen;
       
   267 +     garray_T	*gap;  /* &sl_comppat */
       
   268 + {
       
   269 +     int		i;
       
   270 +     char_u	*p;
       
   271 +     int		len;
       
   272 + 
       
   273 +     for (i = 0; i + 1 < gap->ga_len; i += 2)
       
   274 +     {
       
   275 + 	p = ((char_u **)gap->ga_data)[i + 1];
       
   276 + 	if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0)
       
   277 + 	{
       
   278 + 	    /* Second part matches at start of following compound word, now
       
   279 + 	     * check if first part matches at end of previous word. */
       
   280 + 	    p = ((char_u **)gap->ga_data)[i];
       
   281 + 	    len = STRLEN(p);
       
   282 + 	    if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0)
       
   283 + 		return TRUE;
       
   284 + 	}
       
   285 +     }
       
   286 +     return FALSE;
       
   287 + }
       
   288 + 
       
   289 + /*
       
   290    * Return TRUE if "flags" is a valid sequence of compound flags and "word"
       
   291    * does not have too many syllables.
       
   292    */
       
   293 ***************
       
   294 *** 1773,1778 ****
       
   295 --- 1820,1917 ----
       
   296   }
       
   297   
       
   298   /*
       
   299 +  * Return TRUE when the sequence of flags in "compflags" plus "flag" can
       
   300 +  * possibly form a valid compounded word.  This also checks the COMPOUNDRULE
       
   301 +  * lines if they don't contain wildcards.
       
   302 +  */
       
   303 +     static int
       
   304 + can_be_compound(sp, slang, compflags, flag)
       
   305 +     trystate_T	*sp;
       
   306 +     slang_T	*slang;
       
   307 +     char_u	*compflags;
       
   308 +     int		flag;
       
   309 + {
       
   310 +     /* If the flag doesn't appear in sl_compstartflags or sl_compallflags
       
   311 +      * then it can't possibly compound. */
       
   312 +     if (!byte_in_str(sp->ts_complen == sp->ts_compsplit
       
   313 + 		? slang->sl_compstartflags : slang->sl_compallflags, flag))
       
   314 + 	return FALSE;
       
   315 + 
       
   316 +     /* If there are no wildcards, we can check if the flags collected so far
       
   317 +      * possibly can form a match with COMPOUNDRULE patterns.  This only
       
   318 +      * makes sense when we have two or more words. */
       
   319 +     if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit)
       
   320 +     {
       
   321 + 	int v;
       
   322 + 
       
   323 + 	compflags[sp->ts_complen] = flag;
       
   324 + 	compflags[sp->ts_complen + 1] = NUL;
       
   325 + 	v = match_compoundrule(slang, compflags + sp->ts_compsplit);
       
   326 + 	compflags[sp->ts_complen] = NUL;
       
   327 + 	return v;
       
   328 +     }
       
   329 + 
       
   330 +     return TRUE;
       
   331 + }
       
   332 + 
       
   333 + 
       
   334 + /*
       
   335 +  * Return TRUE if the compound flags in compflags[] match the start of any
       
   336 +  * compound rule.  This is used to stop trying a compound if the flags
       
   337 +  * collected so far can't possibly match any compound rule.
       
   338 +  * Caller must check that slang->sl_comprules is not NULL.
       
   339 +  */
       
   340 +     static int
       
   341 + match_compoundrule(slang, compflags)
       
   342 +     slang_T	*slang;
       
   343 +     char_u	*compflags;
       
   344 + {
       
   345 +     char_u	*p;
       
   346 +     int		i;
       
   347 +     int		c;
       
   348 + 
       
   349 +     /* loop over all the COMPOUNDRULE entries */
       
   350 +     for (p = slang->sl_comprules; *p != NUL; ++p)
       
   351 +     {
       
   352 + 	/* loop over the flags in the compound word we have made, match
       
   353 + 	 * them against the current rule entry */
       
   354 + 	for (i = 0; ; ++i)
       
   355 + 	{
       
   356 + 	    c = compflags[i];
       
   357 + 	    if (c == NUL)
       
   358 + 		/* found a rule that matches for the flags we have so far */
       
   359 + 		return TRUE;
       
   360 + 	    if (*p == '/' || *p == NUL)
       
   361 + 		break;  /* end of rule, it's too short */
       
   362 + 	    if (*p == '[')
       
   363 + 	    {
       
   364 + 		int match = FALSE;
       
   365 + 
       
   366 + 		/* compare against all the flags in [] */
       
   367 + 		++p;
       
   368 + 		while (*p != ']' && *p != NUL)
       
   369 + 		    if (*p++ == c)
       
   370 + 			match = TRUE;
       
   371 + 		if (!match)
       
   372 + 		    break;  /* none matches */
       
   373 + 	    }
       
   374 + 	    else if (*p != c)
       
   375 + 		break;  /* flag of word doesn't match flag in pattern */
       
   376 + 	    ++p;
       
   377 + 	}
       
   378 + 
       
   379 + 	/* Skip to the next "/", where the next pattern starts. */
       
   380 + 	p = vim_strchr(p, '/');
       
   381 + 	if (p == NULL)
       
   382 + 	    break;
       
   383 +     }
       
   384 + 
       
   385 +     /* Checked all the rules and none of them match the flags, so there
       
   386 +      * can't possibly be a compound starting with these flags. */
       
   387 +     return FALSE;
       
   388 + }
       
   389 + 
       
   390 + /*
       
   391    * Return non-zero if the prefix indicated by "arridx" matches with the prefix
       
   392    * ID in "flags" for the word "word".
       
   393    * The WF_RAREPFX flag is included in the return value for a rare prefix.
       
   394 ***************
       
   395 *** 2513,2521 ****
       
   396 --- 2652,2662 ----
       
   397       lp->sl_midword = NULL;
       
   398   
       
   399       vim_free(lp->sl_compprog);
       
   400 +     vim_free(lp->sl_comprules);
       
   401       vim_free(lp->sl_compstartflags);
       
   402       vim_free(lp->sl_compallflags);
       
   403       lp->sl_compprog = NULL;
       
   404 +     lp->sl_comprules = NULL;
       
   405       lp->sl_compstartflags = NULL;
       
   406       lp->sl_compallflags = NULL;
       
   407   
       
   408 ***************
       
   409 *** 3460,3465 ****
       
   410 --- 3601,3607 ----
       
   411       char_u	*pp;
       
   412       char_u	*cp;
       
   413       char_u	*ap;
       
   414 +     char_u	*crp;
       
   415       int		cnt;
       
   416       garray_T	*gap;
       
   417   
       
   418 ***************
       
   419 *** 3545,3550 ****
       
   420 --- 3687,3698 ----
       
   421       slang->sl_compallflags = ap;
       
   422       *ap = NUL;
       
   423   
       
   424 +     /* And a list of all patterns in their original form, for checking whether
       
   425 +      * compounding may work in match_compoundrule().  This is freed when we
       
   426 +      * encounter a wildcard, the check doesn't work then. */
       
   427 +     crp = alloc(todo + 1);
       
   428 +     slang->sl_comprules = crp;
       
   429 + 
       
   430       pp = pat;
       
   431       *pp++ = '^';
       
   432       *pp++ = '\\';
       
   433 ***************
       
   434 *** 3587,3592 ****
       
   435 --- 3735,3754 ----
       
   436   		    atstart = 0;
       
   437   	    }
       
   438   	}
       
   439 + 
       
   440 + 	/* Copy flag to "sl_comprules", unless we run into a wildcard. */
       
   441 + 	if (crp != NULL)
       
   442 + 	{
       
   443 + 	    if (c == '+' || c == '*')
       
   444 + 	    {
       
   445 + 		vim_free(slang->sl_comprules);
       
   446 + 		slang->sl_comprules = NULL;
       
   447 + 		crp = NULL;
       
   448 + 	    }
       
   449 + 	    else
       
   450 + 		*crp++ = c;
       
   451 + 	}
       
   452 + 
       
   453   	if (c == '/')	    /* slash separates two items */
       
   454   	{
       
   455   	    *pp++ = '\\';
       
   456 ***************
       
   457 *** 3611,3616 ****
       
   458 --- 3773,3781 ----
       
   459       *pp++ = '$';
       
   460       *pp = NUL;
       
   461   
       
   462 +     if (crp != NULL)
       
   463 + 	*crp = NUL;
       
   464 + 
       
   465       slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
       
   466       vim_free(pat);
       
   467       if (slang->sl_compprog == NULL)
       
   468 ***************
       
   469 *** 4915,4920 ****
       
   470 --- 5080,5086 ----
       
   471   } spellinfo_T;
       
   472   
       
   473   static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
       
   474 + static int is_aff_rule __ARGS((char_u **items, int itemcnt, char *rulename, int	 mincount));
       
   475   static void aff_process_flags __ARGS((afffile_T *affile, affentry_T *entry));
       
   476   static int spell_info_item __ARGS((char_u *s));
       
   477   static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u	*fname, int lnum));
       
   478 ***************
       
   479 *** 5223,5230 ****
       
   480   	/* Handle non-empty lines. */
       
   481   	if (itemcnt > 0)
       
   482   	{
       
   483 ! 	    if (STRCMP(items[0], "SET") == 0 && itemcnt == 2
       
   484 ! 						       && aff->af_enc == NULL)
       
   485   	    {
       
   486   #ifdef FEAT_MBYTE
       
   487   		/* Setup for conversion from "ENC" to 'encoding'. */
       
   488 --- 5389,5395 ----
       
   489   	/* Handle non-empty lines. */
       
   490   	if (itemcnt > 0)
       
   491   	{
       
   492 ! 	    if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL)
       
   493   	    {
       
   494   #ifdef FEAT_MBYTE
       
   495   		/* Setup for conversion from "ENC" to 'encoding'. */
       
   496 ***************
       
   497 *** 5239,5245 ****
       
   498   		    smsg((char_u *)_("Conversion in %s not supported"), fname);
       
   499   #endif
       
   500   	    }
       
   501 ! 	    else if (STRCMP(items[0], "FLAG") == 0 && itemcnt == 2
       
   502   					      && aff->af_flagtype == AFT_CHAR)
       
   503   	    {
       
   504   		if (STRCMP(items[1], "long") == 0)
       
   505 --- 5404,5410 ----
       
   506   		    smsg((char_u *)_("Conversion in %s not supported"), fname);
       
   507   #endif
       
   508   	    }
       
   509 ! 	    else if (is_aff_rule(items, itemcnt, "FLAG", 2)
       
   510   					      && aff->af_flagtype == AFT_CHAR)
       
   511   	    {
       
   512   		if (STRCMP(items[1], "long") == 0)
       
   513 ***************
       
   514 *** 5284,5352 ****
       
   515   			spin->si_info = p;
       
   516   		    }
       
   517   	    }
       
   518 ! 	    else if (STRCMP(items[0], "MIDWORD") == 0 && itemcnt == 2
       
   519   							   && midword == NULL)
       
   520   	    {
       
   521   		midword = getroom_save(spin, items[1]);
       
   522   	    }
       
   523 ! 	    else if (STRCMP(items[0], "TRY") == 0 && itemcnt == 2)
       
   524   	    {
       
   525   		/* ignored, we look in the tree for what chars may appear */
       
   526   	    }
       
   527   	    /* TODO: remove "RAR" later */
       
   528 ! 	    else if ((STRCMP(items[0], "RAR") == 0
       
   529 ! 			|| STRCMP(items[0], "RARE") == 0) && itemcnt == 2
       
   530 ! 						       && aff->af_rare == 0)
       
   531   	    {
       
   532   		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
       
   533   								 fname, lnum);
       
   534   	    }
       
   535   	    /* TODO: remove "KEP" later */
       
   536 ! 	    else if ((STRCMP(items[0], "KEP") == 0
       
   537 ! 		    || STRCMP(items[0], "KEEPCASE") == 0) && itemcnt == 2
       
   538   						     && aff->af_keepcase == 0)
       
   539   	    {
       
   540   		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
       
   541   								 fname, lnum);
       
   542   	    }
       
   543 ! 	    else if (STRCMP(items[0], "BAD") == 0 && itemcnt == 2
       
   544 ! 						       && aff->af_bad == 0)
       
   545   	    {
       
   546   		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
       
   547   								 fname, lnum);
       
   548   	    }
       
   549 ! 	    else if (STRCMP(items[0], "NEEDAFFIX") == 0 && itemcnt == 2
       
   550   						    && aff->af_needaffix == 0)
       
   551   	    {
       
   552   		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
       
   553   								 fname, lnum);
       
   554   	    }
       
   555 ! 	    else if (STRCMP(items[0], "CIRCUMFIX") == 0 && itemcnt == 2
       
   556   						    && aff->af_circumfix == 0)
       
   557   	    {
       
   558   		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
       
   559   								 fname, lnum);
       
   560   	    }
       
   561 ! 	    else if (STRCMP(items[0], "NOSUGGEST") == 0 && itemcnt == 2
       
   562   						    && aff->af_nosuggest == 0)
       
   563   	    {
       
   564   		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
       
   565   								 fname, lnum);
       
   566   	    }
       
   567 ! 	    else if (STRCMP(items[0], "NEEDCOMPOUND") == 0 && itemcnt == 2
       
   568   						     && aff->af_needcomp == 0)
       
   569   	    {
       
   570   		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
       
   571   								 fname, lnum);
       
   572   	    }
       
   573 ! 	    else if (STRCMP(items[0], "COMPOUNDROOT") == 0 && itemcnt == 2
       
   574   						     && aff->af_comproot == 0)
       
   575   	    {
       
   576   		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
       
   577   								 fname, lnum);
       
   578   	    }
       
   579 ! 	    else if (STRCMP(items[0], "COMPOUNDFORBIDFLAG") == 0
       
   580 ! 				   && itemcnt == 2 && aff->af_compforbid == 0)
       
   581   	    {
       
   582   		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
       
   583   								 fname, lnum);
       
   584 --- 5449,5519 ----
       
   585   			spin->si_info = p;
       
   586   		    }
       
   587   	    }
       
   588 ! 	    else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
       
   589   							   && midword == NULL)
       
   590   	    {
       
   591   		midword = getroom_save(spin, items[1]);
       
   592   	    }
       
   593 ! 	    else if (is_aff_rule(items, itemcnt, "TRY", 2))
       
   594   	    {
       
   595   		/* ignored, we look in the tree for what chars may appear */
       
   596   	    }
       
   597   	    /* TODO: remove "RAR" later */
       
   598 ! 	    else if ((is_aff_rule(items, itemcnt, "RAR", 2)
       
   599 ! 			|| is_aff_rule(items, itemcnt, "RARE", 2))
       
   600 ! 							 && aff->af_rare == 0)
       
   601   	    {
       
   602   		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
       
   603   								 fname, lnum);
       
   604   	    }
       
   605   	    /* TODO: remove "KEP" later */
       
   606 ! 	    else if ((is_aff_rule(items, itemcnt, "KEP", 2)
       
   607 ! 			|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
       
   608   						     && aff->af_keepcase == 0)
       
   609   	    {
       
   610   		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
       
   611   								 fname, lnum);
       
   612   	    }
       
   613 ! 	    else if ((is_aff_rule(items, itemcnt, "BAD", 2)
       
   614 ! 			|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
       
   615 ! 							  && aff->af_bad == 0)
       
   616   	    {
       
   617   		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
       
   618   								 fname, lnum);
       
   619   	    }
       
   620 ! 	    else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
       
   621   						    && aff->af_needaffix == 0)
       
   622   	    {
       
   623   		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
       
   624   								 fname, lnum);
       
   625   	    }
       
   626 ! 	    else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
       
   627   						    && aff->af_circumfix == 0)
       
   628   	    {
       
   629   		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
       
   630   								 fname, lnum);
       
   631   	    }
       
   632 ! 	    else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
       
   633   						    && aff->af_nosuggest == 0)
       
   634   	    {
       
   635   		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
       
   636   								 fname, lnum);
       
   637   	    }
       
   638 ! 	    else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
       
   639 ! 			|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
       
   640   						     && aff->af_needcomp == 0)
       
   641   	    {
       
   642   		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
       
   643   								 fname, lnum);
       
   644   	    }
       
   645 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
       
   646   						     && aff->af_comproot == 0)
       
   647   	    {
       
   648   		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
       
   649   								 fname, lnum);
       
   650   	    }
       
   651 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
       
   652 ! 						   && aff->af_compforbid == 0)
       
   653   	    {
       
   654   		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
       
   655   								 fname, lnum);
       
   656 ***************
       
   657 *** 5354,5361 ****
       
   658   		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
       
   659   			    fname, lnum);
       
   660   	    }
       
   661 ! 	    else if (STRCMP(items[0], "COMPOUNDPERMITFLAG") == 0
       
   662 ! 				   && itemcnt == 2 && aff->af_comppermit == 0)
       
   663   	    {
       
   664   		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
       
   665   								 fname, lnum);
       
   666 --- 5521,5528 ----
       
   667   		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
       
   668   			    fname, lnum);
       
   669   	    }
       
   670 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
       
   671 ! 						   && aff->af_comppermit == 0)
       
   672   	    {
       
   673   		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
       
   674   								 fname, lnum);
       
   675 ***************
       
   676 *** 5363,5369 ****
       
   677   		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
       
   678   			    fname, lnum);
       
   679   	    }
       
   680 ! 	    else if (STRCMP(items[0], "COMPOUNDFLAG") == 0 && itemcnt == 2
       
   681   							 && compflags == NULL)
       
   682   	    {
       
   683   		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
       
   684 --- 5530,5536 ----
       
   685   		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
       
   686   			    fname, lnum);
       
   687   	    }
       
   688 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2)
       
   689   							 && compflags == NULL)
       
   690   	    {
       
   691   		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
       
   692 ***************
       
   693 *** 5376,5382 ****
       
   694   		    compflags = p;
       
   695   		}
       
   696   	    }
       
   697 ! 	    else if (STRCMP(items[0], "COMPOUNDRULE") == 0 && itemcnt == 2)
       
   698   	    {
       
   699   		/* Concatenate this string to previously defined ones, using a
       
   700   		 * slash to separate them. */
       
   701 --- 5543,5557 ----
       
   702   		    compflags = p;
       
   703   		}
       
   704   	    }
       
   705 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2))
       
   706 ! 	    {
       
   707 ! 		/* We don't use the count, but do check that it's a number and
       
   708 ! 		 * not COMPOUNDRULE mistyped. */
       
   709 ! 		if (atoi((char *)items[1]) == 0)
       
   710 ! 		    smsg((char_u *)_("Wrong COMPOUNDRULES value in %s line %d: %s"),
       
   711 ! 						       fname, lnum, items[1]);
       
   712 ! 	    }
       
   713 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2))
       
   714   	    {
       
   715   		/* Concatenate this string to previously defined ones, using a
       
   716   		 * slash to separate them. */
       
   717 ***************
       
   718 *** 5395,5401 ****
       
   719   		    compflags = p;
       
   720   		}
       
   721   	    }
       
   722 ! 	    else if (STRCMP(items[0], "COMPOUNDWORDMAX") == 0 && itemcnt == 2
       
   723   							      && compmax == 0)
       
   724   	    {
       
   725   		compmax = atoi((char *)items[1]);
       
   726 --- 5570,5576 ----
       
   727   		    compflags = p;
       
   728   		}
       
   729   	    }
       
   730 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
       
   731   							      && compmax == 0)
       
   732   	    {
       
   733   		compmax = atoi((char *)items[1]);
       
   734 ***************
       
   735 *** 5403,5409 ****
       
   736   		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
       
   737   						       fname, lnum, items[1]);
       
   738   	    }
       
   739 ! 	    else if (STRCMP(items[0], "COMPOUNDMIN") == 0 && itemcnt == 2
       
   740   							   && compminlen == 0)
       
   741   	    {
       
   742   		compminlen = atoi((char *)items[1]);
       
   743 --- 5578,5584 ----
       
   744   		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
       
   745   						       fname, lnum, items[1]);
       
   746   	    }
       
   747 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2)
       
   748   							   && compminlen == 0)
       
   749   	    {
       
   750   		compminlen = atoi((char *)items[1]);
       
   751 ***************
       
   752 *** 5411,5417 ****
       
   753   		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
       
   754   						       fname, lnum, items[1]);
       
   755   	    }
       
   756 ! 	    else if (STRCMP(items[0], "COMPOUNDSYLMAX") == 0 && itemcnt == 2
       
   757   							   && compsylmax == 0)
       
   758   	    {
       
   759   		compsylmax = atoi((char *)items[1]);
       
   760 --- 5586,5592 ----
       
   761   		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
       
   762   						       fname, lnum, items[1]);
       
   763   	    }
       
   764 ! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2)
       
   765   							   && compsylmax == 0)
       
   766   	    {
       
   767   		compsylmax = atoi((char *)items[1]);
       
   768 ***************
       
   769 *** 5419,5450 ****
       
   770   		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
       
   771   						       fname, lnum, items[1]);
       
   772   	    }
       
   773 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDDUP") == 0 && itemcnt == 1)
       
   774   	    {
       
   775   		compoptions |= COMP_CHECKDUP;
       
   776   	    }
       
   777 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDREP") == 0 && itemcnt == 1)
       
   778   	    {
       
   779   		compoptions |= COMP_CHECKREP;
       
   780   	    }
       
   781 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDCASE") == 0 && itemcnt == 1)
       
   782   	    {
       
   783   		compoptions |= COMP_CHECKCASE;
       
   784   	    }
       
   785 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDTRIPLE") == 0
       
   786 ! 							      && itemcnt == 1)
       
   787   	    {
       
   788   		compoptions |= COMP_CHECKTRIPLE;
       
   789   	    }
       
   790 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0
       
   791 ! 							      && itemcnt == 2)
       
   792   	    {
       
   793   		if (atoi((char *)items[1]) == 0)
       
   794   		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
       
   795   						       fname, lnum, items[1]);
       
   796   	    }
       
   797 ! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0
       
   798 ! 							      && itemcnt == 3)
       
   799   	    {
       
   800   		garray_T    *gap = &spin->si_comppat;
       
   801   		int	    i;
       
   802 --- 5594,5622 ----
       
   803   		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
       
   804   						       fname, lnum, items[1]);
       
   805   	    }
       
   806 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1))
       
   807   	    {
       
   808   		compoptions |= COMP_CHECKDUP;
       
   809   	    }
       
   810 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1))
       
   811   	    {
       
   812   		compoptions |= COMP_CHECKREP;
       
   813   	    }
       
   814 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1))
       
   815   	    {
       
   816   		compoptions |= COMP_CHECKCASE;
       
   817   	    }
       
   818 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1))
       
   819   	    {
       
   820   		compoptions |= COMP_CHECKTRIPLE;
       
   821   	    }
       
   822 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2))
       
   823   	    {
       
   824   		if (atoi((char *)items[1]) == 0)
       
   825   		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
       
   826   						       fname, lnum, items[1]);
       
   827   	    }
       
   828 ! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3))
       
   829   	    {
       
   830   		garray_T    *gap = &spin->si_comppat;
       
   831   		int	    i;
       
   832 ***************
       
   833 *** 5463,5486 ****
       
   834   					       = getroom_save(spin, items[2]);
       
   835   		}
       
   836   	    }
       
   837 ! 	    else if (STRCMP(items[0], "SYLLABLE") == 0 && itemcnt == 2
       
   838   							  && syllable == NULL)
       
   839   	    {
       
   840   		syllable = getroom_save(spin, items[1]);
       
   841   	    }
       
   842 ! 	    else if (STRCMP(items[0], "NOBREAK") == 0 && itemcnt == 1)
       
   843   	    {
       
   844   		spin->si_nobreak = TRUE;
       
   845   	    }
       
   846 ! 	    else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1)
       
   847   	    {
       
   848   		spin->si_nosplitsugs = TRUE;
       
   849   	    }
       
   850 ! 	    else if (STRCMP(items[0], "NOSUGFILE") == 0 && itemcnt == 1)
       
   851   	    {
       
   852   		spin->si_nosugfile = TRUE;
       
   853   	    }
       
   854 ! 	    else if (STRCMP(items[0], "PFXPOSTPONE") == 0 && itemcnt == 1)
       
   855   	    {
       
   856   		aff->af_pfxpostpone = TRUE;
       
   857   	    }
       
   858 --- 5635,5658 ----
       
   859   					       = getroom_save(spin, items[2]);
       
   860   		}
       
   861   	    }
       
   862 ! 	    else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
       
   863   							  && syllable == NULL)
       
   864   	    {
       
   865   		syllable = getroom_save(spin, items[1]);
       
   866   	    }
       
   867 ! 	    else if (is_aff_rule(items, itemcnt, "NOBREAK", 1))
       
   868   	    {
       
   869   		spin->si_nobreak = TRUE;
       
   870   	    }
       
   871 ! 	    else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1))
       
   872   	    {
       
   873   		spin->si_nosplitsugs = TRUE;
       
   874   	    }
       
   875 ! 	    else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1))
       
   876   	    {
       
   877   		spin->si_nosugfile = TRUE;
       
   878   	    }
       
   879 ! 	    else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1))
       
   880   	    {
       
   881   		aff->af_pfxpostpone = TRUE;
       
   882   	    }
       
   883 ***************
       
   884 *** 5771,5794 ****
       
   885   		    }
       
   886   		}
       
   887   	    }
       
   888 ! 	    else if (STRCMP(items[0], "FOL") == 0 && itemcnt == 2
       
   889 ! 							       && fol == NULL)
       
   890   	    {
       
   891   		fol = vim_strsave(items[1]);
       
   892   	    }
       
   893 ! 	    else if (STRCMP(items[0], "LOW") == 0 && itemcnt == 2
       
   894 ! 							       && low == NULL)
       
   895   	    {
       
   896   		low = vim_strsave(items[1]);
       
   897   	    }
       
   898 ! 	    else if (STRCMP(items[0], "UPP") == 0 && itemcnt == 2
       
   899 ! 							       && upp == NULL)
       
   900   	    {
       
   901   		upp = vim_strsave(items[1]);
       
   902   	    }
       
   903 ! 	    else if ((STRCMP(items[0], "REP") == 0
       
   904 ! 			|| STRCMP(items[0], "REPSAL") == 0)
       
   905 ! 		    && itemcnt == 2)
       
   906   	    {
       
   907   		/* Ignore REP/REPSAL count */;
       
   908   		if (!isdigit(*items[1]))
       
   909 --- 5943,5962 ----
       
   910   		    }
       
   911   		}
       
   912   	    }
       
   913 ! 	    else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL)
       
   914   	    {
       
   915   		fol = vim_strsave(items[1]);
       
   916   	    }
       
   917 ! 	    else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL)
       
   918   	    {
       
   919   		low = vim_strsave(items[1]);
       
   920   	    }
       
   921 ! 	    else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL)
       
   922   	    {
       
   923   		upp = vim_strsave(items[1]);
       
   924   	    }
       
   925 ! 	    else if (is_aff_rule(items, itemcnt, "REP", 2)
       
   926 ! 		     || is_aff_rule(items, itemcnt, "REPSAL", 2))
       
   927   	    {
       
   928   		/* Ignore REP/REPSAL count */;
       
   929   		if (!isdigit(*items[1]))
       
   930 ***************
       
   931 *** 5819,5825 ****
       
   932   					 : &spin->si_rep, items[1], items[2]);
       
   933   		}
       
   934   	    }
       
   935 ! 	    else if (STRCMP(items[0], "MAP") == 0 && itemcnt == 2)
       
   936   	    {
       
   937   		/* MAP item or count */
       
   938   		if (!found_map)
       
   939 --- 5987,5993 ----
       
   940   					 : &spin->si_rep, items[1], items[2]);
       
   941   		}
       
   942   	    }
       
   943 ! 	    else if (is_aff_rule(items, itemcnt, "MAP", 2))
       
   944   	    {
       
   945   		/* MAP item or count */
       
   946   		if (!found_map)
       
   947 ***************
       
   948 *** 5856,5864 ****
       
   949   		    ga_append(&spin->si_map, '/');
       
   950   		}
       
   951   	    }
       
   952 ! 	    /* Accept "SAL from to" and "SAL from to # comment". */
       
   953 ! 	    else if (STRCMP(items[0], "SAL") == 0
       
   954 ! 		    && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#')))
       
   955   	    {
       
   956   		if (do_sal)
       
   957   		{
       
   958 --- 6024,6031 ----
       
   959   		    ga_append(&spin->si_map, '/');
       
   960   		}
       
   961   	    }
       
   962 ! 	    /* Accept "SAL from to" and "SAL from to  #comment". */
       
   963 ! 	    else if (is_aff_rule(items, itemcnt, "SAL", 3))
       
   964   	    {
       
   965   		if (do_sal)
       
   966   		{
       
   967 ***************
       
   968 *** 5877,5888 ****
       
   969   								: items[2]);
       
   970   		}
       
   971   	    }
       
   972 ! 	    else if (STRCMP(items[0], "SOFOFROM") == 0 && itemcnt == 2
       
   973   							  && sofofrom == NULL)
       
   974   	    {
       
   975   		sofofrom = getroom_save(spin, items[1]);
       
   976   	    }
       
   977 ! 	    else if (STRCMP(items[0], "SOFOTO") == 0 && itemcnt == 2
       
   978   							    && sofoto == NULL)
       
   979   	    {
       
   980   		sofoto = getroom_save(spin, items[1]);
       
   981 --- 6044,6055 ----
       
   982   								: items[2]);
       
   983   		}
       
   984   	    }
       
   985 ! 	    else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
       
   986   							  && sofofrom == NULL)
       
   987   	    {
       
   988   		sofofrom = getroom_save(spin, items[1]);
       
   989   	    }
       
   990 ! 	    else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
       
   991   							    && sofoto == NULL)
       
   992   	    {
       
   993   		sofoto = getroom_save(spin, items[1]);
       
   994 ***************
       
   995 *** 6017,6022 ****
       
   996 --- 6184,6205 ----
       
   997   }
       
   998   
       
   999   /*
       
  1000 +  * Return TRUE when items[0] equals "rulename", there are "mincount" items or
       
  1001 +  * a comment is following after item "mincount".
       
  1002 +  */
       
  1003 +     static int
       
  1004 + is_aff_rule(items, itemcnt, rulename, mincount)
       
  1005 +     char_u	**items;
       
  1006 +     int		itemcnt;
       
  1007 +     char	*rulename;
       
  1008 +     int		mincount;
       
  1009 + {
       
  1010 +     return (STRCMP(items[0], rulename) == 0
       
  1011 + 	    && (itemcnt == mincount
       
  1012 + 		|| (itemcnt > mincount && items[mincount][0] == '#')));
       
  1013 + }
       
  1014 + 
       
  1015 + /*
       
  1016    * For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from
       
  1017    * ae_flags to ae_comppermit and ae_compforbid.
       
  1018    */
       
  1019 ***************
       
  1020 *** 11492,11506 ****
       
  1021   		    vim_strncpy(preword + sp->ts_prewordlen,
       
  1022   			    tword + sp->ts_splitoff,
       
  1023   			    sp->ts_twordlen - sp->ts_splitoff);
       
  1024 ! 		    p = preword;
       
  1025 ! 		    while (*skiptowhite(p) != NUL)
       
  1026 ! 			p = skipwhite(skiptowhite(p));
       
  1027 ! 		    if (fword_ends && !can_compound(slang, p,
       
  1028 ! 						compflags + sp->ts_compsplit))
       
  1029 ! 			/* Compound is not allowed.  But it may still be
       
  1030 ! 			 * possible if we add another (short) word. */
       
  1031   			compound_ok = FALSE;
       
  1032   
       
  1033   		    /* Get pointer to last char of previous word. */
       
  1034   		    p = preword + sp->ts_prewordlen;
       
  1035   		    mb_ptr_back(preword, p);
       
  1036 --- 11675,11698 ----
       
  1037   		    vim_strncpy(preword + sp->ts_prewordlen,
       
  1038   			    tword + sp->ts_splitoff,
       
  1039   			    sp->ts_twordlen - sp->ts_splitoff);
       
  1040 ! 
       
  1041 ! 		    /* Verify CHECKCOMPOUNDPATTERN  rules. */
       
  1042 ! 		    if (match_checkcompoundpattern(preword,  sp->ts_prewordlen,
       
  1043 ! 							  &slang->sl_comppat))
       
  1044   			compound_ok = FALSE;
       
  1045   
       
  1046 + 		    if (compound_ok)
       
  1047 + 		    {
       
  1048 + 			p = preword;
       
  1049 + 			while (*skiptowhite(p) != NUL)
       
  1050 + 			    p = skipwhite(skiptowhite(p));
       
  1051 + 			if (fword_ends && !can_compound(slang, p,
       
  1052 + 						compflags + sp->ts_compsplit))
       
  1053 + 			    /* Compound is not allowed.  But it may still be
       
  1054 + 			     * possible if we add another (short) word. */
       
  1055 + 			    compound_ok = FALSE;
       
  1056 + 		    }
       
  1057 + 
       
  1058   		    /* Get pointer to last char of previous word. */
       
  1059   		    p = preword + sp->ts_prewordlen;
       
  1060   		    mb_ptr_back(preword, p);
       
  1061 ***************
       
  1062 *** 11697,11706 ****
       
  1063   			&& (slang->sl_compsylmax < MAXWLEN
       
  1064   			    || sp->ts_complen + 1 - sp->ts_compsplit
       
  1065   							  < slang->sl_compmax)
       
  1066 ! 			&& (byte_in_str(sp->ts_complen == sp->ts_compsplit
       
  1067 ! 					    ? slang->sl_compstartflags
       
  1068 ! 					    : slang->sl_compallflags,
       
  1069 ! 						    ((unsigned)flags >> 24))))
       
  1070   		{
       
  1071   		    try_compound = TRUE;
       
  1072   		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
       
  1073 --- 11889,11897 ----
       
  1074   			&& (slang->sl_compsylmax < MAXWLEN
       
  1075   			    || sp->ts_complen + 1 - sp->ts_compsplit
       
  1076   							  < slang->sl_compmax)
       
  1077 ! 			&& (can_be_compound(sp, slang,
       
  1078 ! 					 compflags, ((unsigned)flags >> 24))))
       
  1079 ! 
       
  1080   		{
       
  1081   		    try_compound = TRUE;
       
  1082   		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
       
  1083 *** ../vim-7.2.059/src/version.c	Sun Nov 30 15:15:56 2008
       
  1084 --- src/version.c	Sun Nov 30 21:09:23 2008
       
  1085 ***************
       
  1086 *** 678,679 ****
       
  1087 --- 678,681 ----
       
  1088   {   /* Add new patch number below this line */
       
  1089 + /**/
       
  1090 +     60,
       
  1091   /**/
       
  1092 
       
  1093 -- 
       
  1094 DEAD PERSON:  I'm getting better!
       
  1095 CUSTOMER:     No, you're not -- you'll be stone dead in a moment.
       
  1096 MORTICIAN:    Oh, I can't take him like that -- it's against regulations.
       
  1097                                   The Quest for the Holy Grail (Monty Python)
       
  1098 
       
  1099  /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
       
  1100 ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
       
  1101 \\\        download, build and distribute -- http://www.A-A-P.org        ///
       
  1102  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///