192200e
To: vim-dev@vim.org
192200e
Subject: Patch 7.2.060
192200e
Fcc: outbox
192200e
From: Bram Moolenaar <Bram@moolenaar.net>
192200e
Mime-Version: 1.0
192200e
Content-Type: text/plain; charset=ISO-8859-1
192200e
Content-Transfer-Encoding: 8bit
192200e
------------
192200e
192200e
Patch 7.2.060
192200e
Problem:    When a spell files has many compound rules it may take a very long
192200e
	    time making the list of suggestions.  Displaying also can be slow
192200e
	    when there are misspelled words.
192200e
	    Can't parse some Hunspell .aff files.
192200e
Solution:   Check if a compounding can possibly work before trying a
192200e
	    combination, if the compound rules don't contain wildcards.
192200e
	    Implement using CHECKCOMPOUNDPATTERN.
192200e
	    Ignore COMPOUNDRULES.  Ignore a comment after most items.
192200e
	    Accept ONLYINCOMPOUND as an alias for NEEDCOMPOUND.
192200e
	    Accept FORBIDDENWORD as an alias for BAD.
192200e
Files:	    runtime/doc/spell.txt, src/spell.c
192200e
192200e
192200e
*** ../vim-7.2.059/runtime/doc/spell.txt	Sat Aug  9 19:36:52 2008
192200e
--- runtime/doc/spell.txt	Sun Nov 30 16:30:02 2008
192200e
***************
192200e
*** 1,4 ****
192200e
! *spell.txt*	For Vim version 7.2.  Last change: 2008 Jun 21
192200e
  
192200e
  
192200e
  		  VIM REFERENCE MANUAL	  by Bram Moolenaar
192200e
--- 1,4 ----
192200e
! *spell.txt*	For Vim version 7.2.  Last change: 2008 Nov 30
192200e
  
192200e
  
192200e
  		  VIM REFERENCE MANUAL	  by Bram Moolenaar
192200e
***************
192200e
*** 831,838 ****
192200e
  
192200e
  	# comment line ~
192200e
  
192200e
! With some items it's also possible to put a comment after it, but this isn't
192200e
! supported in general.
192200e
  
192200e
  
192200e
  ENCODING							*spell-SET*
192200e
--- 831,841 ----
192200e
  
192200e
  	# comment line ~
192200e
  
192200e
! Items with a fixed number of arguments can be followed by a comment.  But only
192200e
! if none of the arguments can contain white space.  The comment must start with
192200e
! a "#" character.  Example:
192200e
! 
192200e
! 	KEEPCASE =  # fix case for words with this flag ~
192200e
  
192200e
  
192200e
  ENCODING							*spell-SET*
192200e
***************
192200e
*** 965,970 ****
192200e
--- 968,976 ----
192200e
  
192200e
  Note: When using utf-8 only characters up to 65000 may be used for flags.
192200e
  
192200e
+ Note: even when using "num" or "long" the number of flags available to
192200e
+ compounding and prefixes is limited to about 250.
192200e
+ 
192200e
  
192200e
  AFFIXES
192200e
  					    *spell-PFX* *spell-SFX*
192200e
***************
192200e
*** 1178,1183 ****
192200e
--- 1185,1193 ----
192200e
  The flag also applies to the word with affixes, thus this can be used to mark
192200e
  a whole bunch of related words as bad.
192200e
  
192200e
+ 							*spell-FORBIDDENWORD*
192200e
+ FORBIDDENWORD can be used just like BAD.  For compatibility with Hunspell.
192200e
+ 
192200e
  							*spell-NEEDAFFIX*
192200e
  The NEEDAFFIX flag is used to require that a word is used with an affix.  The
192200e
  word itself is not a good word (unless there is an empty affix).  Example:
192200e
***************
192200e
*** 1268,1273 ****
192200e
--- 1278,1287 ----
192200e
  
192200e
  	NEEDCOMPOUND & ~
192200e
  
192200e
+ 							*spell-ONLYINCOMPOUND*
192200e
+ The ONLYINCOMPOUND does exactly the same as NEEDCOMPOUND.  Supported for
192200e
+ compatiblity with Hunspell.
192200e
+ 
192200e
  							*spell-COMPOUNDMIN*
192200e
  The minimal character length of a word used for compounding is specified with
192200e
  COMPOUNDMIN.  Example:
192200e
***************
192200e
*** 1328,1333 ****
192200e
--- 1342,1361 ----
192200e
  rules.  Can also be used for an affix to count the affix as a compounding
192200e
  word.
192200e
  
192200e
+ 						*spell-CHECKCOMPOUNDPATTERN*
192200e
+ CHECKCOMPOUNDPATTERN is used to define patterns that, when matching at the
192200e
+ position where two words are compounded together forbids the compound.
192200e
+ For example:
192200e
+ 	CHECKCOMPOUNDPATTERN o e ~
192200e
+ 
192200e
+ This forbids compounding if the first word ends in "o" and the second word
192200e
+ starts with "e".
192200e
+ 
192200e
+ The arguments must be plain text, no patterns are actually supported, despite
192200e
+ the item name.  Case is always ignored.
192200e
+ 
192200e
+ The Hunspell feature to use three arguments and flags is not supported.
192200e
+ 
192200e
  							*spell-SYLLABLE*
192200e
  The SYLLABLE item defines characters or character sequences that are used to
192200e
  count the number of syllables in a word.  Example:
192200e
***************
192200e
*** 1496,1501 ****
192200e
--- 1524,1533 ----
192200e
  ACCENT		(Hunspell)				*spell-ACCENT*
192200e
  		Use MAP instead. |spell-MAP|
192200e
  
192200e
+ BREAK		(Hunspell)				*spell-BREAK*
192200e
+ 		Define break points.  Unclear how it works exactly.
192200e
+ 		Not supported.
192200e
+ 
192200e
  CHECKCOMPOUNDCASE  (Hunspell)			*spell-CHECKCOMPOUNDCASE*
192200e
  		Disallow uppercase letters at compound word boundaries.
192200e
  		Not supported.
192200e
***************
192200e
*** 1512,1520 ****
192200e
  		Forbid three identical characters when compounding.  Not
192200e
  		supported.
192200e
  
192200e
- CHECKCOMPOUNDPATTERN  (Hunspell)		*spell-CHECKCOMPOUNDPATTERN*
192200e
- 		Forbid compounding when patterns match.  Not supported.
192200e
- 
192200e
  COMPLEXPREFIXES  (Hunspell)				*spell-COMPLEXPREFIXES*
192200e
  		Enables using two prefixes.  Not supported.
192200e
  
192200e
--- 1544,1549 ----
192200e
***************
192200e
*** 1536,1548 ****
192200e
  COMPOUNDMIDDLE	(Hunspell)				*spell-COMPOUNDMIDDLE*
192200e
  		Use COMPOUNDRULE instead. |spell-COMPOUNDRULE|
192200e
  
192200e
  COMPOUNDSYLLABLE  (Hunspell)			*spell-COMPOUNDSYLLABLE*
192200e
  		Use SYLLABLE and COMPOUNDSYLMAX instead. |spell-SYLLABLE|
192200e
  		|spell-COMPOUNDSYLMAX|
192200e
  
192200e
! FORBIDDENWORD	(Hunspell)				*spell-FORBIDDENWORD*
192200e
! 		Use BAD instead. |spell-BAD|
192200e
! 
192200e
  LANG		(Hunspell)				*spell-LANG*
192200e
  		This specifies language-specific behavior.  This actually
192200e
  		moves part of the language knowledge into the program,
192200e
--- 1565,1582 ----
192200e
  COMPOUNDMIDDLE	(Hunspell)				*spell-COMPOUNDMIDDLE*
192200e
  		Use COMPOUNDRULE instead. |spell-COMPOUNDRULE|
192200e
  
192200e
+ COMPOUNDRULES	(Hunspell)				*spell-COMPOUNDRULES*
192200e
+ 		Number of COMPOUNDRULE lines following.  Ignored, but the
192200e
+ 		argument must be a number.
192200e
+ 
192200e
  COMPOUNDSYLLABLE  (Hunspell)			*spell-COMPOUNDSYLLABLE*
192200e
  		Use SYLLABLE and COMPOUNDSYLMAX instead. |spell-SYLLABLE|
192200e
  		|spell-COMPOUNDSYLMAX|
192200e
  
192200e
! KEY		(Hunspell)				*spell-KEY*
192200e
! 		Define characters that are close together on the keyboard.
192200e
! 		Used to give better suggestions.  Not supported.
192200e
! 		
192200e
  LANG		(Hunspell)				*spell-LANG*
192200e
  		This specifies language-specific behavior.  This actually
192200e
  		moves part of the language knowledge into the program,
192200e
***************
192200e
*** 1553,1562 ****
192200e
  		Only needed for morphological analysis.
192200e
  
192200e
  MAXNGRAMSUGS	(Hunspell)				*spell-MAXNGRAMSUGS*
192200e
! 		Not supported.
192200e
! 
192200e
! ONLYINCOMPOUND	(Hunspell)				*spell-ONLYINCOMPOUND*
192200e
! 		Use NEEDCOMPOUND instead. |spell-NEEDCOMPOUND|
192200e
  
192200e
  PSEUDOROOT	(Hunspell)				*spell-PSEUDOROOT*
192200e
  		Use NEEDAFFIX instead. |spell-NEEDAFFIX|
192200e
--- 1587,1593 ----
192200e
  		Only needed for morphological analysis.
192200e
  
192200e
  MAXNGRAMSUGS	(Hunspell)				*spell-MAXNGRAMSUGS*
192200e
! 		Set number of n-gram suggestions.  Not supported.
192200e
  
192200e
  PSEUDOROOT	(Hunspell)				*spell-PSEUDOROOT*
192200e
  		Use NEEDAFFIX instead. |spell-NEEDAFFIX|
192200e
*** ../vim-7.2.059/src/spell.c	Sat Nov 29 20:18:44 2008
192200e
--- src/spell.c	Sun Nov 30 20:59:13 2008
192200e
***************
192200e
*** 469,474 ****
192200e
--- 469,475 ----
192200e
      garray_T	sl_comppat;	/* CHECKCOMPOUNDPATTERN items */
192200e
      regprog_T	*sl_compprog;	/* COMPOUNDRULE turned into a regexp progrm
192200e
  				 * (NULL when no compounding) */
192200e
+     char_u	*sl_comprules;	/* all COMPOUNDRULE concatenated (or NULL) */
192200e
      char_u	*sl_compstartflags; /* flags for first compound word */
192200e
      char_u	*sl_compallflags; /* all flags for compound words */
192200e
      char_u	sl_nobreak;	/* When TRUE: no spaces between words */
192200e
***************
192200e
*** 839,845 ****
192200e
--- 840,849 ----
192200e
  static void slang_clear __ARGS((slang_T *lp));
192200e
  static void slang_clear_sug __ARGS((slang_T *lp));
192200e
  static void find_word __ARGS((matchinf_T *mip, int mode));
192200e
+ static int match_checkcompoundpattern __ARGS((char_u *ptr, int wlen, garray_T *gap));
192200e
  static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags));
192200e
+ static int can_be_compound __ARGS((trystate_T *sp, slang_T *slang, char_u *compflags, int flag));
192200e
+ static int match_compoundrule __ARGS((slang_T *slang, char_u *compflags));
192200e
  static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req));
192200e
  static void find_prefix __ARGS((matchinf_T *mip, int mode));
192200e
  static int fold_more __ARGS((matchinf_T *mip));
192200e
***************
192200e
*** 1519,1524 ****
192200e
--- 1523,1533 ----
192200e
  					    ((unsigned)flags >> 24)))
192200e
  		    continue;
192200e
  
192200e
+ 		/* If there is a match with a CHECKCOMPOUNDPATTERN rule
192200e
+ 		 * discard the compound word. */
192200e
+ 		if (match_checkcompoundpattern(ptr, wlen, &slang->sl_comppat))
192200e
+ 		    continue;
192200e
+ 
192200e
  		if (mode == FIND_COMPOUND)
192200e
  		{
192200e
  		    int	    capflags;
192200e
***************
192200e
*** 1577,1582 ****
192200e
--- 1586,1596 ----
192200e
  		    if (!can_compound(slang, fword, mip->mi_compflags))
192200e
  			continue;
192200e
  		}
192200e
+ 		else if (slang->sl_comprules != NULL
192200e
+ 			     && !match_compoundrule(slang, mip->mi_compflags))
192200e
+ 		    /* The compound flags collected so far do not match any
192200e
+ 		     * COMPOUNDRULE, discard the compounded word. */
192200e
+ 		    continue;
192200e
  	    }
192200e
  
192200e
  	    /* Check NEEDCOMPOUND: can't use word without compounding. */
192200e
***************
192200e
*** 1727,1732 ****
192200e
--- 1741,1779 ----
192200e
  }
192200e
  
192200e
  /*
192200e
+  * Return TRUE if there is a match between the word ptr[wlen] and
192200e
+  * CHECKCOMPOUNDPATTERN rules, assuming that we will concatenate with another
192200e
+  * word.
192200e
+  * A match means that the first part of CHECKCOMPOUNDPATTERN matches at the
192200e
+  * end of ptr[wlen] and the second part matches after it.
192200e
+  */
192200e
+     static int
192200e
+ match_checkcompoundpattern(ptr, wlen, gap)
192200e
+     char_u	*ptr;
192200e
+     int		wlen;
192200e
+     garray_T	*gap;  /* &sl_comppat */
192200e
+ {
192200e
+     int		i;
192200e
+     char_u	*p;
192200e
+     int		len;
192200e
+ 
192200e
+     for (i = 0; i + 1 < gap->ga_len; i += 2)
192200e
+     {
192200e
+ 	p = ((char_u **)gap->ga_data)[i + 1];
192200e
+ 	if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0)
192200e
+ 	{
192200e
+ 	    /* Second part matches at start of following compound word, now
192200e
+ 	     * check if first part matches at end of previous word. */
192200e
+ 	    p = ((char_u **)gap->ga_data)[i];
192200e
+ 	    len = STRLEN(p);
192200e
+ 	    if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0)
192200e
+ 		return TRUE;
192200e
+ 	}
192200e
+     }
192200e
+     return FALSE;
192200e
+ }
192200e
+ 
192200e
+ /*
192200e
   * Return TRUE if "flags" is a valid sequence of compound flags and "word"
192200e
   * does not have too many syllables.
192200e
   */
192200e
***************
192200e
*** 1773,1778 ****
192200e
--- 1820,1917 ----
192200e
  }
192200e
  
192200e
  /*
192200e
+  * Return TRUE when the sequence of flags in "compflags" plus "flag" can
192200e
+  * possibly form a valid compounded word.  This also checks the COMPOUNDRULE
192200e
+  * lines if they don't contain wildcards.
192200e
+  */
192200e
+     static int
192200e
+ can_be_compound(sp, slang, compflags, flag)
192200e
+     trystate_T	*sp;
192200e
+     slang_T	*slang;
192200e
+     char_u	*compflags;
192200e
+     int		flag;
192200e
+ {
192200e
+     /* If the flag doesn't appear in sl_compstartflags or sl_compallflags
192200e
+      * then it can't possibly compound. */
192200e
+     if (!byte_in_str(sp->ts_complen == sp->ts_compsplit
192200e
+ 		? slang->sl_compstartflags : slang->sl_compallflags, flag))
192200e
+ 	return FALSE;
192200e
+ 
192200e
+     /* If there are no wildcards, we can check if the flags collected so far
192200e
+      * possibly can form a match with COMPOUNDRULE patterns.  This only
192200e
+      * makes sense when we have two or more words. */
192200e
+     if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit)
192200e
+     {
192200e
+ 	int v;
192200e
+ 
192200e
+ 	compflags[sp->ts_complen] = flag;
192200e
+ 	compflags[sp->ts_complen + 1] = NUL;
192200e
+ 	v = match_compoundrule(slang, compflags + sp->ts_compsplit);
192200e
+ 	compflags[sp->ts_complen] = NUL;
192200e
+ 	return v;
192200e
+     }
192200e
+ 
192200e
+     return TRUE;
192200e
+ }
192200e
+ 
192200e
+ 
192200e
+ /*
192200e
+  * Return TRUE if the compound flags in compflags[] match the start of any
192200e
+  * compound rule.  This is used to stop trying a compound if the flags
192200e
+  * collected so far can't possibly match any compound rule.
192200e
+  * Caller must check that slang->sl_comprules is not NULL.
192200e
+  */
192200e
+     static int
192200e
+ match_compoundrule(slang, compflags)
192200e
+     slang_T	*slang;
192200e
+     char_u	*compflags;
192200e
+ {
192200e
+     char_u	*p;
192200e
+     int		i;
192200e
+     int		c;
192200e
+ 
192200e
+     /* loop over all the COMPOUNDRULE entries */
192200e
+     for (p = slang->sl_comprules; *p != NUL; ++p)
192200e
+     {
192200e
+ 	/* loop over the flags in the compound word we have made, match
192200e
+ 	 * them against the current rule entry */
192200e
+ 	for (i = 0; ; ++i)
192200e
+ 	{
192200e
+ 	    c = compflags[i];
192200e
+ 	    if (c == NUL)
192200e
+ 		/* found a rule that matches for the flags we have so far */
192200e
+ 		return TRUE;
192200e
+ 	    if (*p == '/' || *p == NUL)
192200e
+ 		break;  /* end of rule, it's too short */
192200e
+ 	    if (*p == '[')
192200e
+ 	    {
192200e
+ 		int match = FALSE;
192200e
+ 
192200e
+ 		/* compare against all the flags in [] */
192200e
+ 		++p;
192200e
+ 		while (*p != ']' && *p != NUL)
192200e
+ 		    if (*p++ == c)
192200e
+ 			match = TRUE;
192200e
+ 		if (!match)
192200e
+ 		    break;  /* none matches */
192200e
+ 	    }
192200e
+ 	    else if (*p != c)
192200e
+ 		break;  /* flag of word doesn't match flag in pattern */
192200e
+ 	    ++p;
192200e
+ 	}
192200e
+ 
192200e
+ 	/* Skip to the next "/", where the next pattern starts. */
192200e
+ 	p = vim_strchr(p, '/');
192200e
+ 	if (p == NULL)
192200e
+ 	    break;
192200e
+     }
192200e
+ 
192200e
+     /* Checked all the rules and none of them match the flags, so there
192200e
+      * can't possibly be a compound starting with these flags. */
192200e
+     return FALSE;
192200e
+ }
192200e
+ 
192200e
+ /*
192200e
   * Return non-zero if the prefix indicated by "arridx" matches with the prefix
192200e
   * ID in "flags" for the word "word".
192200e
   * The WF_RAREPFX flag is included in the return value for a rare prefix.
192200e
***************
192200e
*** 2513,2521 ****
192200e
--- 2652,2662 ----
192200e
      lp->sl_midword = NULL;
192200e
  
192200e
      vim_free(lp->sl_compprog);
192200e
+     vim_free(lp->sl_comprules);
192200e
      vim_free(lp->sl_compstartflags);
192200e
      vim_free(lp->sl_compallflags);
192200e
      lp->sl_compprog = NULL;
192200e
+     lp->sl_comprules = NULL;
192200e
      lp->sl_compstartflags = NULL;
192200e
      lp->sl_compallflags = NULL;
192200e
  
192200e
***************
192200e
*** 3460,3465 ****
192200e
--- 3601,3607 ----
192200e
      char_u	*pp;
192200e
      char_u	*cp;
192200e
      char_u	*ap;
192200e
+     char_u	*crp;
192200e
      int		cnt;
192200e
      garray_T	*gap;
192200e
  
192200e
***************
192200e
*** 3545,3550 ****
192200e
--- 3687,3698 ----
192200e
      slang->sl_compallflags = ap;
192200e
      *ap = NUL;
192200e
  
192200e
+     /* And a list of all patterns in their original form, for checking whether
192200e
+      * compounding may work in match_compoundrule().  This is freed when we
192200e
+      * encounter a wildcard, the check doesn't work then. */
192200e
+     crp = alloc(todo + 1);
192200e
+     slang->sl_comprules = crp;
192200e
+ 
192200e
      pp = pat;
192200e
      *pp++ = '^';
192200e
      *pp++ = '\\';
192200e
***************
192200e
*** 3587,3592 ****
192200e
--- 3735,3754 ----
192200e
  		    atstart = 0;
192200e
  	    }
192200e
  	}
192200e
+ 
192200e
+ 	/* Copy flag to "sl_comprules", unless we run into a wildcard. */
192200e
+ 	if (crp != NULL)
192200e
+ 	{
192200e
+ 	    if (c == '+' || c == '*')
192200e
+ 	    {
192200e
+ 		vim_free(slang->sl_comprules);
192200e
+ 		slang->sl_comprules = NULL;
192200e
+ 		crp = NULL;
192200e
+ 	    }
192200e
+ 	    else
192200e
+ 		*crp++ = c;
192200e
+ 	}
192200e
+ 
192200e
  	if (c == '/')	    /* slash separates two items */
192200e
  	{
192200e
  	    *pp++ = '\\';
192200e
***************
192200e
*** 3611,3616 ****
192200e
--- 3773,3781 ----
192200e
      *pp++ = '$';
192200e
      *pp = NUL;
192200e
  
192200e
+     if (crp != NULL)
192200e
+ 	*crp = NUL;
192200e
+ 
192200e
      slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
192200e
      vim_free(pat);
192200e
      if (slang->sl_compprog == NULL)
192200e
***************
192200e
*** 4915,4920 ****
192200e
--- 5080,5086 ----
192200e
  } spellinfo_T;
192200e
  
192200e
  static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
192200e
+ static int is_aff_rule __ARGS((char_u **items, int itemcnt, char *rulename, int	 mincount));
192200e
  static void aff_process_flags __ARGS((afffile_T *affile, affentry_T *entry));
192200e
  static int spell_info_item __ARGS((char_u *s));
192200e
  static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u	*fname, int lnum));
192200e
***************
192200e
*** 5223,5230 ****
192200e
  	/* Handle non-empty lines. */
192200e
  	if (itemcnt > 0)
192200e
  	{
192200e
! 	    if (STRCMP(items[0], "SET") == 0 && itemcnt == 2
192200e
! 						       && aff->af_enc == NULL)
192200e
  	    {
192200e
  #ifdef FEAT_MBYTE
192200e
  		/* Setup for conversion from "ENC" to 'encoding'. */
192200e
--- 5389,5395 ----
192200e
  	/* Handle non-empty lines. */
192200e
  	if (itemcnt > 0)
192200e
  	{
192200e
! 	    if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL)
192200e
  	    {
192200e
  #ifdef FEAT_MBYTE
192200e
  		/* Setup for conversion from "ENC" to 'encoding'. */
192200e
***************
192200e
*** 5239,5245 ****
192200e
  		    smsg((char_u *)_("Conversion in %s not supported"), fname);
192200e
  #endif
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "FLAG") == 0 && itemcnt == 2
192200e
  					      && aff->af_flagtype == AFT_CHAR)
192200e
  	    {
192200e
  		if (STRCMP(items[1], "long") == 0)
192200e
--- 5404,5410 ----
192200e
  		    smsg((char_u *)_("Conversion in %s not supported"), fname);
192200e
  #endif
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "FLAG", 2)
192200e
  					      && aff->af_flagtype == AFT_CHAR)
192200e
  	    {
192200e
  		if (STRCMP(items[1], "long") == 0)
192200e
***************
192200e
*** 5284,5352 ****
192200e
  			spin->si_info = p;
192200e
  		    }
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "MIDWORD") == 0 && itemcnt == 2
192200e
  							   && midword == NULL)
192200e
  	    {
192200e
  		midword = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "TRY") == 0 && itemcnt == 2)
192200e
  	    {
192200e
  		/* ignored, we look in the tree for what chars may appear */
192200e
  	    }
192200e
  	    /* TODO: remove "RAR" later */
192200e
! 	    else if ((STRCMP(items[0], "RAR") == 0
192200e
! 			|| STRCMP(items[0], "RARE") == 0) && itemcnt == 2
192200e
! 						       && aff->af_rare == 0)
192200e
  	    {
192200e
  		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
  	    /* TODO: remove "KEP" later */
192200e
! 	    else if ((STRCMP(items[0], "KEP") == 0
192200e
! 		    || STRCMP(items[0], "KEEPCASE") == 0) && itemcnt == 2
192200e
  						     && aff->af_keepcase == 0)
192200e
  	    {
192200e
  		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "BAD") == 0 && itemcnt == 2
192200e
! 						       && aff->af_bad == 0)
192200e
  	    {
192200e
  		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NEEDAFFIX") == 0 && itemcnt == 2
192200e
  						    && aff->af_needaffix == 0)
192200e
  	    {
192200e
  		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CIRCUMFIX") == 0 && itemcnt == 2
192200e
  						    && aff->af_circumfix == 0)
192200e
  	    {
192200e
  		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NOSUGGEST") == 0 && itemcnt == 2
192200e
  						    && aff->af_nosuggest == 0)
192200e
  	    {
192200e
  		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NEEDCOMPOUND") == 0 && itemcnt == 2
192200e
  						     && aff->af_needcomp == 0)
192200e
  	    {
192200e
  		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDROOT") == 0 && itemcnt == 2
192200e
  						     && aff->af_comproot == 0)
192200e
  	    {
192200e
  		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDFORBIDFLAG") == 0
192200e
! 				   && itemcnt == 2 && aff->af_compforbid == 0)
192200e
  	    {
192200e
  		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
--- 5449,5519 ----
192200e
  			spin->si_info = p;
192200e
  		    }
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
192200e
  							   && midword == NULL)
192200e
  	    {
192200e
  		midword = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "TRY", 2))
192200e
  	    {
192200e
  		/* ignored, we look in the tree for what chars may appear */
192200e
  	    }
192200e
  	    /* TODO: remove "RAR" later */
192200e
! 	    else if ((is_aff_rule(items, itemcnt, "RAR", 2)
192200e
! 			|| is_aff_rule(items, itemcnt, "RARE", 2))
192200e
! 							 && aff->af_rare == 0)
192200e
  	    {
192200e
  		aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
  	    /* TODO: remove "KEP" later */
192200e
! 	    else if ((is_aff_rule(items, itemcnt, "KEP", 2)
192200e
! 			|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
192200e
  						     && aff->af_keepcase == 0)
192200e
  	    {
192200e
  		aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if ((is_aff_rule(items, itemcnt, "BAD", 2)
192200e
! 			|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
192200e
! 							  && aff->af_bad == 0)
192200e
  	    {
192200e
  		aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
192200e
  						    && aff->af_needaffix == 0)
192200e
  	    {
192200e
  		aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
192200e
  						    && aff->af_circumfix == 0)
192200e
  	    {
192200e
  		aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
192200e
  						    && aff->af_nosuggest == 0)
192200e
  	    {
192200e
  		aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
192200e
! 			|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
192200e
  						     && aff->af_needcomp == 0)
192200e
  	    {
192200e
  		aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
192200e
  						     && aff->af_comproot == 0)
192200e
  	    {
192200e
  		aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
192200e
! 						   && aff->af_compforbid == 0)
192200e
  	    {
192200e
  		aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
***************
192200e
*** 5354,5361 ****
192200e
  		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
192200e
  			    fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDPERMITFLAG") == 0
192200e
! 				   && itemcnt == 2 && aff->af_comppermit == 0)
192200e
  	    {
192200e
  		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
--- 5521,5528 ----
192200e
  		    smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
192200e
  			    fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
192200e
! 						   && aff->af_comppermit == 0)
192200e
  	    {
192200e
  		aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
192200e
  								 fname, lnum);
192200e
***************
192200e
*** 5363,5369 ****
192200e
  		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
192200e
  			    fname, lnum);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDFLAG") == 0 && itemcnt == 2
192200e
  							 && compflags == NULL)
192200e
  	    {
192200e
  		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
192200e
--- 5530,5536 ----
192200e
  		    smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
192200e
  			    fname, lnum);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2)
192200e
  							 && compflags == NULL)
192200e
  	    {
192200e
  		/* Turn flag "c" into COMPOUNDRULE compatible string "c+",
192200e
***************
192200e
*** 5376,5382 ****
192200e
  		    compflags = p;
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDRULE") == 0 && itemcnt == 2)
192200e
  	    {
192200e
  		/* Concatenate this string to previously defined ones, using a
192200e
  		 * slash to separate them. */
192200e
--- 5543,5557 ----
192200e
  		    compflags = p;
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2))
192200e
! 	    {
192200e
! 		/* We don't use the count, but do check that it's a number and
192200e
! 		 * not COMPOUNDRULE mistyped. */
192200e
! 		if (atoi((char *)items[1]) == 0)
192200e
! 		    smsg((char_u *)_("Wrong COMPOUNDRULES value in %s line %d: %s"),
192200e
! 						       fname, lnum, items[1]);
192200e
! 	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2))
192200e
  	    {
192200e
  		/* Concatenate this string to previously defined ones, using a
192200e
  		 * slash to separate them. */
192200e
***************
192200e
*** 5395,5401 ****
192200e
  		    compflags = p;
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDWORDMAX") == 0 && itemcnt == 2
192200e
  							      && compmax == 0)
192200e
  	    {
192200e
  		compmax = atoi((char *)items[1]);
192200e
--- 5570,5576 ----
192200e
  		    compflags = p;
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
192200e
  							      && compmax == 0)
192200e
  	    {
192200e
  		compmax = atoi((char *)items[1]);
192200e
***************
192200e
*** 5403,5409 ****
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDMIN") == 0 && itemcnt == 2
192200e
  							   && compminlen == 0)
192200e
  	    {
192200e
  		compminlen = atoi((char *)items[1]);
192200e
--- 5578,5584 ----
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2)
192200e
  							   && compminlen == 0)
192200e
  	    {
192200e
  		compminlen = atoi((char *)items[1]);
192200e
***************
192200e
*** 5411,5417 ****
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "COMPOUNDSYLMAX") == 0 && itemcnt == 2
192200e
  							   && compsylmax == 0)
192200e
  	    {
192200e
  		compsylmax = atoi((char *)items[1]);
192200e
--- 5586,5592 ----
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2)
192200e
  							   && compsylmax == 0)
192200e
  	    {
192200e
  		compsylmax = atoi((char *)items[1]);
192200e
***************
192200e
*** 5419,5450 ****
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDDUP") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKDUP;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDREP") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKREP;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDCASE") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKCASE;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDTRIPLE") == 0
192200e
! 							      && itemcnt == 1)
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKTRIPLE;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0
192200e
! 							      && itemcnt == 2)
192200e
  	    {
192200e
  		if (atoi((char *)items[1]) == 0)
192200e
  		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0
192200e
! 							      && itemcnt == 3)
192200e
  	    {
192200e
  		garray_T    *gap = &spin->si_comppat;
192200e
  		int	    i;
192200e
--- 5594,5622 ----
192200e
  		    smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1))
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKDUP;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1))
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKREP;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1))
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKCASE;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1))
192200e
  	    {
192200e
  		compoptions |= COMP_CHECKTRIPLE;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2))
192200e
  	    {
192200e
  		if (atoi((char *)items[1]) == 0)
192200e
  		    smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"),
192200e
  						       fname, lnum, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3))
192200e
  	    {
192200e
  		garray_T    *gap = &spin->si_comppat;
192200e
  		int	    i;
192200e
***************
192200e
*** 5463,5486 ****
192200e
  					       = getroom_save(spin, items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "SYLLABLE") == 0 && itemcnt == 2
192200e
  							  && syllable == NULL)
192200e
  	    {
192200e
  		syllable = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NOBREAK") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		spin->si_nobreak = TRUE;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		spin->si_nosplitsugs = TRUE;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "NOSUGFILE") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		spin->si_nosugfile = TRUE;
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "PFXPOSTPONE") == 0 && itemcnt == 1)
192200e
  	    {
192200e
  		aff->af_pfxpostpone = TRUE;
192200e
  	    }
192200e
--- 5635,5658 ----
192200e
  					       = getroom_save(spin, items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
192200e
  							  && syllable == NULL)
192200e
  	    {
192200e
  		syllable = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "NOBREAK", 1))
192200e
  	    {
192200e
  		spin->si_nobreak = TRUE;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1))
192200e
  	    {
192200e
  		spin->si_nosplitsugs = TRUE;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1))
192200e
  	    {
192200e
  		spin->si_nosugfile = TRUE;
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1))
192200e
  	    {
192200e
  		aff->af_pfxpostpone = TRUE;
192200e
  	    }
192200e
***************
192200e
*** 5771,5794 ****
192200e
  		    }
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "FOL") == 0 && itemcnt == 2
192200e
! 							       && fol == NULL)
192200e
  	    {
192200e
  		fol = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "LOW") == 0 && itemcnt == 2
192200e
! 							       && low == NULL)
192200e
  	    {
192200e
  		low = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "UPP") == 0 && itemcnt == 2
192200e
! 							       && upp == NULL)
192200e
  	    {
192200e
  		upp = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if ((STRCMP(items[0], "REP") == 0
192200e
! 			|| STRCMP(items[0], "REPSAL") == 0)
192200e
! 		    && itemcnt == 2)
192200e
  	    {
192200e
  		/* Ignore REP/REPSAL count */;
192200e
  		if (!isdigit(*items[1]))
192200e
--- 5943,5962 ----
192200e
  		    }
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL)
192200e
  	    {
192200e
  		fol = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL)
192200e
  	    {
192200e
  		low = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL)
192200e
  	    {
192200e
  		upp = vim_strsave(items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "REP", 2)
192200e
! 		     || is_aff_rule(items, itemcnt, "REPSAL", 2))
192200e
  	    {
192200e
  		/* Ignore REP/REPSAL count */;
192200e
  		if (!isdigit(*items[1]))
192200e
***************
192200e
*** 5819,5825 ****
192200e
  					 : &spin->si_rep, items[1], items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "MAP") == 0 && itemcnt == 2)
192200e
  	    {
192200e
  		/* MAP item or count */
192200e
  		if (!found_map)
192200e
--- 5987,5993 ----
192200e
  					 : &spin->si_rep, items[1], items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "MAP", 2))
192200e
  	    {
192200e
  		/* MAP item or count */
192200e
  		if (!found_map)
192200e
***************
192200e
*** 5856,5864 ****
192200e
  		    ga_append(&spin->si_map, '/');
192200e
  		}
192200e
  	    }
192200e
! 	    /* Accept "SAL from to" and "SAL from to # comment". */
192200e
! 	    else if (STRCMP(items[0], "SAL") == 0
192200e
! 		    && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#')))
192200e
  	    {
192200e
  		if (do_sal)
192200e
  		{
192200e
--- 6024,6031 ----
192200e
  		    ga_append(&spin->si_map, '/');
192200e
  		}
192200e
  	    }
192200e
! 	    /* Accept "SAL from to" and "SAL from to  #comment". */
192200e
! 	    else if (is_aff_rule(items, itemcnt, "SAL", 3))
192200e
  	    {
192200e
  		if (do_sal)
192200e
  		{
192200e
***************
192200e
*** 5877,5888 ****
192200e
  								: items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "SOFOFROM") == 0 && itemcnt == 2
192200e
  							  && sofofrom == NULL)
192200e
  	    {
192200e
  		sofofrom = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (STRCMP(items[0], "SOFOTO") == 0 && itemcnt == 2
192200e
  							    && sofoto == NULL)
192200e
  	    {
192200e
  		sofoto = getroom_save(spin, items[1]);
192200e
--- 6044,6055 ----
192200e
  								: items[2]);
192200e
  		}
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
192200e
  							  && sofofrom == NULL)
192200e
  	    {
192200e
  		sofofrom = getroom_save(spin, items[1]);
192200e
  	    }
192200e
! 	    else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
192200e
  							    && sofoto == NULL)
192200e
  	    {
192200e
  		sofoto = getroom_save(spin, items[1]);
192200e
***************
192200e
*** 6017,6022 ****
192200e
--- 6184,6205 ----
192200e
  }
192200e
  
192200e
  /*
192200e
+  * Return TRUE when items[0] equals "rulename", there are "mincount" items or
192200e
+  * a comment is following after item "mincount".
192200e
+  */
192200e
+     static int
192200e
+ is_aff_rule(items, itemcnt, rulename, mincount)
192200e
+     char_u	**items;
192200e
+     int		itemcnt;
192200e
+     char	*rulename;
192200e
+     int		mincount;
192200e
+ {
192200e
+     return (STRCMP(items[0], rulename) == 0
192200e
+ 	    && (itemcnt == mincount
192200e
+ 		|| (itemcnt > mincount && items[mincount][0] == '#')));
192200e
+ }
192200e
+ 
192200e
+ /*
192200e
   * For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from
192200e
   * ae_flags to ae_comppermit and ae_compforbid.
192200e
   */
192200e
***************
192200e
*** 11492,11506 ****
192200e
  		    vim_strncpy(preword + sp->ts_prewordlen,
192200e
  			    tword + sp->ts_splitoff,
192200e
  			    sp->ts_twordlen - sp->ts_splitoff);
192200e
! 		    p = preword;
192200e
! 		    while (*skiptowhite(p) != NUL)
192200e
! 			p = skipwhite(skiptowhite(p));
192200e
! 		    if (fword_ends && !can_compound(slang, p,
192200e
! 						compflags + sp->ts_compsplit))
192200e
! 			/* Compound is not allowed.  But it may still be
192200e
! 			 * possible if we add another (short) word. */
192200e
  			compound_ok = FALSE;
192200e
  
192200e
  		    /* Get pointer to last char of previous word. */
192200e
  		    p = preword + sp->ts_prewordlen;
192200e
  		    mb_ptr_back(preword, p);
192200e
--- 11675,11698 ----
192200e
  		    vim_strncpy(preword + sp->ts_prewordlen,
192200e
  			    tword + sp->ts_splitoff,
192200e
  			    sp->ts_twordlen - sp->ts_splitoff);
192200e
! 
192200e
! 		    /* Verify CHECKCOMPOUNDPATTERN  rules. */
192200e
! 		    if (match_checkcompoundpattern(preword,  sp->ts_prewordlen,
192200e
! 							  &slang->sl_comppat))
192200e
  			compound_ok = FALSE;
192200e
  
192200e
+ 		    if (compound_ok)
192200e
+ 		    {
192200e
+ 			p = preword;
192200e
+ 			while (*skiptowhite(p) != NUL)
192200e
+ 			    p = skipwhite(skiptowhite(p));
192200e
+ 			if (fword_ends && !can_compound(slang, p,
192200e
+ 						compflags + sp->ts_compsplit))
192200e
+ 			    /* Compound is not allowed.  But it may still be
192200e
+ 			     * possible if we add another (short) word. */
192200e
+ 			    compound_ok = FALSE;
192200e
+ 		    }
192200e
+ 
192200e
  		    /* Get pointer to last char of previous word. */
192200e
  		    p = preword + sp->ts_prewordlen;
192200e
  		    mb_ptr_back(preword, p);
192200e
***************
192200e
*** 11697,11706 ****
192200e
  			&& (slang->sl_compsylmax < MAXWLEN
192200e
  			    || sp->ts_complen + 1 - sp->ts_compsplit
192200e
  							  < slang->sl_compmax)
192200e
! 			&& (byte_in_str(sp->ts_complen == sp->ts_compsplit
192200e
! 					    ? slang->sl_compstartflags
192200e
! 					    : slang->sl_compallflags,
192200e
! 						    ((unsigned)flags >> 24))))
192200e
  		{
192200e
  		    try_compound = TRUE;
192200e
  		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
192200e
--- 11889,11897 ----
192200e
  			&& (slang->sl_compsylmax < MAXWLEN
192200e
  			    || sp->ts_complen + 1 - sp->ts_compsplit
192200e
  							  < slang->sl_compmax)
192200e
! 			&& (can_be_compound(sp, slang,
192200e
! 					 compflags, ((unsigned)flags >> 24))))
192200e
! 
192200e
  		{
192200e
  		    try_compound = TRUE;
192200e
  		    compflags[sp->ts_complen] = ((unsigned)flags >> 24);
192200e
*** ../vim-7.2.059/src/version.c	Sun Nov 30 15:15:56 2008
192200e
--- src/version.c	Sun Nov 30 21:09:23 2008
192200e
***************
192200e
*** 678,679 ****
192200e
--- 678,681 ----
192200e
  {   /* Add new patch number below this line */
192200e
+ /**/
192200e
+     60,
192200e
  /**/
192200e
192200e
-- 
192200e
DEAD PERSON:  I'm getting better!
192200e
CUSTOMER:     No, you're not -- you'll be stone dead in a moment.
192200e
MORTICIAN:    Oh, I can't take him like that -- it's against regulations.
192200e
                                  The Quest for the Holy Grail (Monty Python)
192200e
192200e
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
192200e
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
192200e
\\\        download, build and distribute -- http://www.A-A-P.org        ///
192200e
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///