diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index 7013e6d7072457f862b6fc2c60c87261fca66ad9..9a72f3b0d0f7edfbbf3f4eaeca64c46625959a16 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -1,4 +1,4 @@
-*spell.txt*	For Vim version 7.0aa.  Last change: 2005 Jun 21
+*spell.txt*	For Vim version 7.0aa.  Last change: 2005 Jun 22
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -41,7 +41,9 @@ To search for the next misspelled word:
 
 							*[s*
 [s			Like "]s" but search backwards, find the misspelled
-			word before the cursor.
+			word before the cursor.  Doesn't recognize words
+			split over two lines, thus may stop at words that are
+			not highlighted as bad.
 
 							*]S*
 ]S			Like "]s" but only stop at bad words, not at rare
@@ -77,12 +79,11 @@ automatically be updated.  More details about the 'spellfile' format below
 Finding suggestions for bad words:
 
 							*z?*
-z?			For the badly spelled word under the cursor suggest
-			the correctly spelled word.
-			When there is no badly spelled word under the cursor
-			use the one after the cursor, in the same line.
-			The results are sorted on similarity to the badly
-			spelled word.
+z?			For the word under/after the cursor suggest correctly
+			spelled words.  This also works to find alternative
+			for words that are not highlighted as bad words.
+			The results are sorted on similarity to the word
+			under/after the cursor.
 			This may take a long time.  Hit CTRL-C when you are
 			bored.
 			You can enter the number of your choice or press
@@ -90,8 +91,6 @@ z?			For the badly spelled word under the cursor suggest
 			If 'verbose' is non-zero a score will be displayed to
 			indicate the likeliness to the badly spelled word (the
 			higher the score the more different).
-			The score may be slightly wrong for words with
-			multi-byte characters.
 			When a word was replaced the redo command "." will
 			repeat the word replacement.  This works like "ciw",
 			the good word and <Esc>.
@@ -205,6 +204,25 @@ A word that starts with a digit is always ignored.  That includes hex numbers
 in the form 0xff and 0XFF.
 
 
+WORD COMBINATIONS
+
+It is possible to spell-check words that include a space.  This is used to
+recognize words that are invalid when used by themselves, e.g. for "et al.".
+It can also be used to recognize "the the" and highlight it.
+
+The number of spaces is irrelevant.  In most cases a line break may also
+appear.  However, this makes it difficult to find out where to start checking
+for spelling mistakes.  When you make a change to one line and only that line
+is redrawn Vim won't look in the previous line, thus when "et" is at the end
+of the previous line "al." will be flagged as an error.  And when you type
+"the<CR>the" the highlighting doesn't appear until the first line is redrawn.
+Use |CTRL-L| to redraw right away.  "[s" will also stop at a word combination
+with a line break.
+
+When encountering a line break Vim skips characters such as '*', '>' and '"',
+so that comments in C, shell and Vim code can be spell checked.
+
+
 SYNTAX HIGHLIGHTING					*spell-syntax*
 
 Files that use syntax highlighting can specify where spell checking should be
@@ -218,6 +236,15 @@ For the second method adding the @NoSpell cluster will disable spell checking
 again.  This can be used, for example, to add @Spell to the comments of a
 program, and add @NoSpell for items that shouldn't be checked.
 
+
+VIM SCRIPTS
+
+If you want to write a Vim script that does something with spelling, you may
+find these functions useful:
+
+    spellbadword()	find badly spelled word at the cursor
+    spellsuggest()	get list of spelling suggestions
+
 ==============================================================================
 2. Generating a spell file				*spell-mkspell*
 
@@ -228,7 +255,8 @@ You can create a Vim spell file from the .aff and .dic files that Myspell
 uses.  Myspell is used by OpenOffice.org and Mozilla.  You should be able to
 find them here:
 	http://lingucomponent.openoffice.org/spell_dic.html
-You can also use a plain word list.
+You can also use a plain word list.  The results are the same, the choice
+depends on what you find.
 
 Make sure your current locale is set properly, otherwise Vim doesn't know what
 characters are upper/lower case letters.  If the locale isn't available (e.g.,
@@ -267,6 +295,10 @@ when using an MS-Windows codepage on Unix) add tables to the .aff file
 			they appear are used. |spell-affix-REP|
 			|spell-affix-SAL|
 
+			This command uses a lot of memory, required to find
+			the optimal word tree (Polish requires a few hundred
+			Mbyte).  The final result will be much smaller.
+
 			When the spell file was written all currently used
 			spell files will be reloaded.
 
@@ -520,7 +552,20 @@ rare words.  Example:
 
 Rare words are highlighted differently from bad words.  This is to be used for
 words that are correct for the language, but are hardly ever used and could be
-a typing mistake anyway.
+a typing mistake anyway.  When the same word is found as good it won't be
+highlighted as rare.
+
+
+BAD WORDS
+							*spell-affix-BAD*
+In the affix file a BAD line can be used to define the affix name used for
+bad words.  Example:
+
+	BAD ! ~
+
+This can be used to exclude words that would otherwise be good.  For example
+"the the".  Once a word has been marked as bad it won't be undone by
+encountering the same word as good.
 
 
 REPLACEMENTS						*spell-affix-REP*
diff --git a/runtime/doc/tags b/runtime/doc/tags
index ce4807a8e2ebba9cc2b4b086bfb97d39270497ac..fe6340eb1d764d4f2d43dc06754e3df2dee6c012 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -731,11 +731,13 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
 'spell'	options.txt	/*'spell'*
 'spellfile'	options.txt	/*'spellfile'*
 'spelllang'	options.txt	/*'spelllang'*
+'spellsuggest'	options.txt	/*'spellsuggest'*
 'spf'	options.txt	/*'spf'*
 'spl'	options.txt	/*'spl'*
 'splitbelow'	options.txt	/*'splitbelow'*
 'splitright'	options.txt	/*'splitright'*
 'spr'	options.txt	/*'spr'*
+'sps'	options.txt	/*'sps'*
 'sr'	options.txt	/*'sr'*
 'srr'	options.txt	/*'srr'*
 'ss'	options.txt	/*'ss'*
@@ -5130,7 +5132,6 @@ hebrew	hebrew.txt	/*hebrew*
 hebrew.txt	hebrew.txt	/*hebrew.txt*
 help	various.txt	/*help*
 help-context	help.txt	/*help-context*
-help-tags	tags	1
 help-translated	various.txt	/*help-translated*
 help-xterm-window	various.txt	/*help-xterm-window*
 help.txt	help.txt	/*help.txt*
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 6cc15e9225a48030501d4cf76e9fe347c4b720e6..bcb88eb9ff05762a7909bcdc293cf9987ac7afc7 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -1,4 +1,4 @@
-*various.txt*   For Vim version 7.0aa.  Last change: 2005 May 31
+*various.txt*   For Vim version 7.0aa.  Last change: 2005 Jun 22
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -14,7 +14,8 @@ Various commands					*various*
 1. Various commands					*various-cmds*
 
 							*CTRL-L*
-CTRL-L			Clear and redraw the screen (later).
+CTRL-L			Clear and redraw the screen.  The redraw may happen
+			later, after processing typeahead.
 
 							*:redr* *:redraw*
 :redr[aw][!]		Redraw the screen right now.  When ! is included it is
diff --git a/runtime/ftplugin/c.vim b/runtime/ftplugin/c.vim
index 39ba8232ef1d92963e8adffed08ab836a6e28607..47b2ec6d2a078cce1e2a62affe60adf7163b89cf 100644
--- a/runtime/ftplugin/c.vim
+++ b/runtime/ftplugin/c.vim
@@ -1,7 +1,7 @@
 " Vim filetype plugin file
 " Language:	C
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2005 Mar 27
+" Last Change:	2005 Jun 22
 
 " Only do this when not done yet for this buffer
 if exists("b:did_ftplugin")
@@ -12,6 +12,7 @@ endif
 let b:did_ftplugin = 1
 
 " Using line continuation here.
+let s:cpo_save = &cpo
 set cpo-=C
 
 let b:undo_ftplugin = "setl fo< com< | if has('vms') | setl isk< | endif"
@@ -48,3 +49,6 @@ if has("gui_win32") && !exists("b:browsefilter")
 	  \ "All Files (*.*)\t*.*\n"
   endif
 endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/spell/en.latin1.spl b/runtime/spell/en.latin1.spl
index ba4990c55e58f1b7ee7d8f175a7f7b35f5f2b680..38c4c9cd127da8e636610aa1d4c4bec75d8c8209 100644
Binary files a/runtime/spell/en.latin1.spl and b/runtime/spell/en.latin1.spl differ
diff --git a/src/proto/spell.pro b/src/proto/spell.pro
index 15a68a686322b4ca5b6d48f57d8bff4d25f9743b..2771a902c0ab9396ae4a15b33bdcaf65276c68fb 100644
--- a/src/proto/spell.pro
+++ b/src/proto/spell.pro
@@ -1,6 +1,7 @@
 /* spell.c */
 int spell_check __ARGS((win_T *wp, char_u *ptr, int *attrp));
 int spell_move_to __ARGS((int dir, int allwords, int curline));
+void spell_cat_line __ARGS((char_u *buf, char_u *line, int maxlen));
 char_u *did_set_spelllang __ARGS((buf_T *buf));
 void spell_reload __ARGS((void));
 void put_bytes __ARGS((FILE *fd, long_u nr, int len));
diff --git a/src/screen.c b/src/screen.c
index b1fbedfa251bfe441a35e549ed35d01f08720499..6fb5931dbc077c7b4bf1913e599e87cc193458e8 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -2502,8 +2502,17 @@ win_line(wp, lnum, startrow, endrow)
     int		has_syntax = FALSE;	/* this buffer has syntax highl. */
     int		save_did_emsg;
     int		has_spell = FALSE;	/* this buffer has spell checking */
+# define SPWORDLEN 150
+    char_u	nextline[SPWORDLEN * 2];/* text with start of the next line */
+    int		nextlinecol;		/* column where nextline[] starts */
+    int		nextline_idx;		/* index in nextline[] where next line
+					   starts */
     int		spell_attr = 0;		/* attributes desired by spelling */
     int		word_end = 0;		/* last byte with same spell_attr */
+    static linenr_T  checked_lnum = 0;	/* line number for checked_col */
+    static int	checked_col = 0;	/* column in checked_lnum up to which
+					 * there are no spell errors */
+    int		cur_checked_col = 0;	/* checked column for current line */
 #endif
     int		extra_check;		/* has syntax or linebreak */
 #ifdef FEAT_MBYTE
@@ -2609,6 +2618,22 @@ win_line(wp, lnum, startrow, endrow)
 	/* Prepare for spell checking. */
 	has_spell = TRUE;
 	extra_check = TRUE;
+
+	/* Get the start of the next line, so that words that wrap to the next
+	 * line are found too: "et<line-break>al.".
+	 * Trick: skip a few chars for C/shell/Vim comments */
+	nextline[SPWORDLEN] = NUL;
+	if (lnum < wp->w_buffer->b_ml.ml_line_count)
+	{
+	    line = ml_get_buf(wp->w_buffer, lnum + 1, FALSE);
+	    spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
+	}
+
+	/* When a word wrapped from the previous line the start of the current
+	 * line is valid. */
+	if (lnum == checked_lnum)
+	    cur_checked_col = checked_col;
+	checked_lnum = 0;
     }
 #endif
 
@@ -2774,6 +2799,42 @@ win_line(wp, lnum, startrow, endrow)
     line = ml_get_buf(wp->w_buffer, lnum, FALSE);
     ptr = line;
 
+#ifdef FEAT_SYN_HL
+    if (has_spell)
+    {
+	/* To be able to spell-check over line boundaries copy the end of the
+	 * current line into nextline[].  Above the start of the next line was
+	 * copied to nextline[SPWORDLEN]. */
+	if (nextline[SPWORDLEN] == NUL)
+	{
+	    /* No next line or it is empty. */
+	    nextlinecol = MAXCOL;
+	    nextline_idx = 0;
+	}
+	else
+	{
+	    v = STRLEN(line);
+	    if (v < SPWORDLEN)
+	    {
+		/* Short line, use it completely and append the start of the
+		 * next line. */
+		nextlinecol = 0;
+		mch_memmove(nextline, line, (size_t)v);
+		mch_memmove(nextline + v, nextline + SPWORDLEN,
+					    STRLEN(nextline + SPWORDLEN) + 1);
+		nextline_idx = v + 1;
+	    }
+	    else
+	    {
+		/* Long line, use only the last SPWORDLEN bytes. */
+		nextlinecol = v - SPWORDLEN;
+		mch_memmove(nextline, line + nextlinecol, SPWORDLEN);
+		nextline_idx = SPWORDLEN + 1;
+	    }
+	}
+    }
+#endif
+
     /* find start of trailing whitespace */
     if (wp->w_p_list && lcs_trail)
     {
@@ -3587,14 +3648,15 @@ win_line(wp, lnum, startrow, endrow)
 		 * Only do this when there is no syntax highlighting, the
 		 * @Spell cluster is not used or the current syntax item
 		 * contains the @Spell cluster. */
-		if (has_spell && v >= word_end)
+		if (has_spell && v >= word_end && v > cur_checked_col)
 		{
 		    spell_attr = 0;
 		    if (area_attr == 0 && search_attr == 0)
 			char_attr = syntax_attr;
 		    if (c != 0 && (!has_syntax || can_spell))
 		    {
-			char_u	*prev_ptr;
+			char_u	*prev_ptr, *p;
+			int	len;
 # ifdef FEAT_MBYTE
 			if (has_mbyte)
 			{
@@ -3604,7 +3666,15 @@ win_line(wp, lnum, startrow, endrow)
 			else
 # endif
 			    prev_ptr = ptr - 1;
-			word_end = v + spell_check(wp, prev_ptr, &spell_attr);
+
+			/* Use nextline[] if possible, it has the start of the
+			 * next line concatenated. */
+			if ((prev_ptr - line) - nextlinecol >= 0)
+			    p = nextline + (prev_ptr - line) - nextlinecol;
+			else
+			    p = prev_ptr;
+			len = spell_check(wp, p, &spell_attr);
+			word_end = v + len;
 
 			/* In Insert mode only highlight a word that
 			 * doesn't touch the cursor. */
@@ -3618,10 +3688,24 @@ win_line(wp, lnum, startrow, endrow)
 			    spell_attr = 0;
 			    spell_redraw_lnum = lnum;
 			}
+
+			if (spell_attr == 0 && p != prev_ptr
+				       && (p - nextline) + len > nextline_idx)
+			{
+			    /* Remember that the good word continues at the
+			     * start of the next line. */
+			    checked_lnum = lnum + 1;
+			    checked_col = (p - nextline) + len - nextline_idx;
+			}
 		    }
 		}
 		if (spell_attr != 0)
-		    char_attr = hl_combine_attr(char_attr, spell_attr);
+		{
+		    if (area_attr == 0 && search_attr == 0)
+			char_attr = hl_combine_attr(char_attr, spell_attr);
+		    else
+			char_attr = hl_combine_attr(spell_attr, char_attr);
+		}
 #endif
 #ifdef FEAT_LINEBREAK
 		/*
diff --git a/src/syntax.c b/src/syntax.c
index 1d8f41bf3b1fafb53ead17a8769cafdfcfca5397..4fdbbbf6fbd6a71c53316b6f8a89aed13ab7f9cc 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -7591,26 +7591,27 @@ get_attr_entry(table, aep)
 
 #if defined(FEAT_SYN_HL) || defined(PROTO)
 /*
- * Combine the spelling attributes with other attributes.  "spell_attr"
- * overrules "char_attr".
+ * Combine special attributes (e.g., for spelling) with other attributes
+ * (e.g., for syntax highlighting).
+ * "prim_attr" overrules "char_attr".
  * This creates a new group when required.
  * Since we expect there to be few spelling mistakes we don't cache the
  * result.
  * Return the resulting attributes.
  */
     int
-hl_combine_attr(char_attr, spell_attr)
+hl_combine_attr(char_attr, prim_attr)
     int	    char_attr;
-    int	    spell_attr;
+    int	    prim_attr;
 {
     attrentry_T *char_aep = NULL;
     attrentry_T *spell_aep;
     attrentry_T new_en;
 
     if (char_attr == 0)
-	return spell_attr;
-    if (char_attr <= HL_ALL && spell_attr <= HL_ALL)
-	return char_attr | spell_attr;
+	return prim_attr;
+    if (char_attr <= HL_ALL && prim_attr <= HL_ALL)
+	return char_attr | prim_attr;
 #ifdef FEAT_GUI
     if (gui.in_use)
     {
@@ -7625,11 +7626,11 @@ hl_combine_attr(char_attr, spell_attr)
 		new_en.ae_attr = char_attr;
 	}
 
-	if (spell_attr <= HL_ALL)
-	    new_en.ae_attr |= spell_attr;
+	if (prim_attr <= HL_ALL)
+	    new_en.ae_attr |= prim_attr;
 	else
 	{
-	    spell_aep = syn_gui_attr2entry(spell_attr);
+	    spell_aep = syn_gui_attr2entry(prim_attr);
 	    if (spell_aep != NULL)
 	    {
 		new_en.ae_attr |= spell_aep->ae_attr;
@@ -7664,11 +7665,11 @@ hl_combine_attr(char_attr, spell_attr)
 		new_en.ae_attr = char_attr;
 	}
 
-	if (spell_attr <= HL_ALL)
-	    new_en.ae_attr |= spell_attr;
+	if (prim_attr <= HL_ALL)
+	    new_en.ae_attr |= prim_attr;
 	else
 	{
-	    spell_aep = syn_cterm_attr2entry(spell_attr);
+	    spell_aep = syn_cterm_attr2entry(prim_attr);
 	    if (spell_aep != NULL)
 	    {
 		new_en.ae_attr |= spell_aep->ae_attr;
@@ -7692,11 +7693,11 @@ hl_combine_attr(char_attr, spell_attr)
 	    new_en.ae_attr = char_attr;
     }
 
-    if (spell_attr <= HL_ALL)
-	new_en.ae_attr |= spell_attr;
+    if (prim_attr <= HL_ALL)
+	new_en.ae_attr |= prim_attr;
     else
     {
-	spell_aep = syn_cterm_attr2entry(spell_attr);
+	spell_aep = syn_cterm_attr2entry(prim_attr);
 	if (spell_aep != NULL)
 	{
 	    new_en.ae_attr |= spell_aep->ae_attr;