updated for version 7.0194
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index f373806..ca94386 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -675,6 +675,8 @@
 
 conflags = /nologo /subsystem:$(SUBSYSTEM) /incremental:no
 
+PATHDEF_SRC = $(OUTDIR)\pathdef.c
+
 !IF "$(MAP)" == "yes"
 # "/map" is for debugging
 conflags = $(conflags) /map
@@ -736,7 +738,6 @@
 
 clean:
 	- if exist $(OUTDIR)/nul $(DEL_TREE) $(OUTDIR)
-	- if exist auto/pathdef.c del auto/pathdef.c
 	- if exist *.obj del *.obj
 	- if exist $(VIM).exe del $(VIM).exe
 	- if exist $(VIM).ilk del $(VIM).ilk
@@ -894,8 +895,8 @@
 
 $(OUTDIR)/os_w32exe.obj:	$(OUTDIR) os_w32exe.c  $(INCL)
 
-$(OUTDIR)/pathdef.obj:	$(OUTDIR) auto/pathdef.c  $(INCL)
-	$(CC) $(CFLAGS) auto/pathdef.c
+$(OUTDIR)/pathdef.obj:	$(OUTDIR) $(PATHDEF_SRC) $(INCL)
+	$(CC) $(CFLAGS) $(PATHDEF_SRC)
 
 $(OUTDIR)/popupmenu.obj:	$(OUTDIR) popupmenu.c  $(INCL)
 
@@ -943,16 +944,16 @@
 E0_CFLAGS = $(CFLAGS:\=\\)
 E_CFLAGS = $(E0_CFLAGS:"=\")
 
-auto/pathdef.c: auto
-	@echo creating auto/pathdef.c
-	@echo /* pathdef.c */ > auto\pathdef.c
-	@echo #include "vim.h" >> auto\pathdef.c
-	@echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC:\=\\)"; >> auto\pathdef.c
-	@echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR:\=\\)"; >> auto\pathdef.c
-	@echo char_u *all_cflags = (char_u *)"$(CC:\=\\) $(E_CFLAGS)"; >> auto\pathdef.c
-	@echo char_u *all_lflags = (char_u *)"$(link:\=\\) $(LINKARGS1:\=\\) $(LINKARGS2:\=\\)"; >> auto\pathdef.c
-	@echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> auto\pathdef.c
-	@echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> auto\pathdef.c
+$(PATHDEF_SRC): auto
+	@echo creating $(PATHDEF_SRC)
+	@echo /* pathdef.c */ > $(PATHDEF_SRC)
+	@echo #include "vim.h" >> $(PATHDEF_SRC)
+	@echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC:\=\\)"; >> $(PATHDEF_SRC)
+	@echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR:\=\\)"; >> $(PATHDEF_SRC)
+	@echo char_u *all_cflags = (char_u *)"$(CC:\=\\) $(E_CFLAGS)"; >> $(PATHDEF_SRC)
+	@echo char_u *all_lflags = (char_u *)"$(link:\=\\) $(LINKARGS1:\=\\) $(LINKARGS2:\=\\)"; >> $(PATHDEF_SRC)
+	@echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> $(PATHDEF_SRC)
+	@echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> $(PATHDEF_SRC)
 
 auto:
 	if not exist auto/nul mkdir auto
diff --git a/src/edit.c b/src/edit.c
index ee574ad..c59d08f 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -68,7 +68,11 @@
     compl_T	*cp_next;
     compl_T	*cp_prev;
     char_u	*cp_str;	/* matched text */
-    char_u	*cp_fname;	/* file containing the match */
+    char_u	*cp_extra;	/* extra menu text (allocated, can be NULL) */
+    char_u	*cp_info;	/* verbose info (can be NULL) */
+    char_u	cp_kind;	/* kind of match, single letter, or NUL */
+    char_u	*cp_fname;	/* file containing the match, allocated when
+				 * cp_flags has FREE_FNAME */
     int		cp_flags;	/* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
     int		cp_number;	/* sequence number */
 };
@@ -115,20 +119,21 @@
 
 static void ins_ctrl_x __ARGS((void));
 static int  has_compl_option __ARGS((int dict_opt));
-static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir));
+static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches));
 static int  ins_compl_make_cyclic __ARGS((void));
 static void ins_compl_upd_pum __ARGS((void));
 static void ins_compl_del_pum __ARGS((void));
 static int  pum_wanted __ARGS((void));
 static int  pum_two_or_more __ARGS((void));
-static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags, int thesaurus));
+static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int flags, int thesaurus));
 static void ins_compl_free __ARGS((void));
 static void ins_compl_clear __ARGS((void));
 static int  ins_compl_bs __ARGS((void));
 static void ins_compl_addleader __ARGS((int c));
+static void ins_compl_addfrommatch __ARGS((void));
 static int  ins_compl_prep __ARGS((int c));
 static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));
-static int  ins_compl_get_exp __ARGS((pos_T *ini, int dir));
+static int  ins_compl_get_exp __ARGS((pos_T *ini));
 static void ins_compl_delete __ARGS((void));
 static void ins_compl_insert __ARGS((void));
 static int  ins_compl_next __ARGS((int allow_get_expansion, int count));
@@ -684,19 +689,34 @@
 	if (c == K_DOWN && pum_visible())
 	    c = Ctrl_N;
 
-	/* When using BS while the popup menu is wanted and still after the
-	 * character where completion started: Change the subset of matches to
-	 * what matches "compl_leader". */
-	if (compl_started && pum_wanted() && curwin->w_cursor.col > compl_col)
+	/*
+	 * Special handling of keys while the popup menu is visible or wanted
+	 * and the cursor is still in the completed word.
+	 */
+	if (compl_started && pum_wanted() && curwin->w_cursor.col >= compl_col)
 	{
-	    if ((c == K_BS || c == Ctrl_H) && ins_compl_bs())
+	    /* BS: Delete one character from "compl_leader". */
+	    if ((c == K_BS || c == Ctrl_H)
+			&& curwin->w_cursor.col > compl_col && ins_compl_bs())
 		continue;
 
-	    /* Editing the word. */
-	    if (!compl_used_match && vim_isprintc(c))
+	    /* When no match was selected or it was edited. */
+	    if (!compl_used_match)
 	    {
-		ins_compl_addleader(c);
-		continue;
+		/* CTRL-L: Add one character from the current match to
+		 * "compl_leader". */
+		if (c == Ctrl_L)
+		{
+		    ins_compl_addfrommatch();
+		    continue;
+		}
+
+		/* A printable character: Add it to "compl_leader". */
+		if (vim_isprintc(c))
+		{
+		    ins_compl_addleader(c);
+		    continue;
+		}
 	    }
 	}
 
@@ -1922,7 +1942,7 @@
 }
 
 /*
- * This is like ins_compl_add(), but if ic and inf are set, then the
+ * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
  * case of the originally typed text is used, and the case of the completed
  * text is infered, ie this tries to work out what case you probably wanted
  * the rest of the word to be in -- webb
@@ -1985,9 +2005,9 @@
 	/* Copy the original case of the part we typed */
 	STRNCPY(IObuff, compl_orig_text, compl_length);
 
-	return ins_compl_add(IObuff, len, fname, dir, flags);
+	return ins_compl_add(IObuff, len, fname, NULL, dir, flags);
     }
-    return ins_compl_add(str, len, fname, dir, flags);
+    return ins_compl_add(str, len, fname, NULL, dir, flags);
 }
 
 /*
@@ -2002,14 +2022,16 @@
  * maybe because alloc() returns NULL, then FAIL is returned -- webb.
  */
     int
-ins_compl_add(str, len, fname, dir, flags)
+ins_compl_add(str, len, fname, extra, cdir, flags)
     char_u	*str;
     int		len;
     char_u	*fname;
-    int		dir;
+    char_u	*extra;	    /* extra text for popup menu or NULL */
+    int		cdir;
     int		flags;
 {
     compl_T	*match;
+    int		dir = (cdir == 0 ? compl_direction : cdir);
 
     ui_breakcheck();
     if (got_int)
@@ -2040,7 +2062,7 @@
      * Allocate a new match structure.
      * Copy the values to the new match structure.
      */
-    match = (compl_T *)alloc((unsigned)sizeof(compl_T));
+    match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T));
     if (match == NULL)
 	return FAIL;
     match->cp_number = -1;
@@ -2054,18 +2076,26 @@
 	vim_free(match);
 	return FAIL;
     }
+
     /* match-fname is:
      * - compl_curr_match->cp_fname if it is a string equal to fname.
      * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
      * - NULL otherwise.	--Acevedo */
-    if (fname && compl_curr_match && compl_curr_match->cp_fname
-	      && STRCMP(fname, compl_curr_match->cp_fname) == 0)
+    if (fname != NULL
+	    && compl_curr_match
+	    && compl_curr_match->cp_fname != NULL
+	    && STRCMP(fname, compl_curr_match->cp_fname) == 0)
 	match->cp_fname = compl_curr_match->cp_fname;
-    else if (fname && (match->cp_fname = vim_strsave(fname)) != NULL)
+    else if (fname != NULL)
+    {
+	match->cp_fname = vim_strsave(fname);
 	flags |= FREE_FNAME;
+    }
     else
 	match->cp_fname = NULL;
     match->cp_flags = flags;
+    if (extra != NULL)
+	match->cp_extra = vim_strsave(extra);
 
     /*
      * Link the new match structure in the list of matches.
@@ -2098,19 +2128,18 @@
  * Frees matches[].
  */
     static void
-ins_compl_add_matches(num_matches, matches, dir)
+ins_compl_add_matches(num_matches, matches)
     int		num_matches;
     char_u	**matches;
-    int		dir;
 {
     int		i;
     int		add_r = OK;
-    int		ldir = dir;
+    int		dir = compl_direction;
 
     for (i = 0; i < num_matches && add_r != FAIL; i++)
-	if ((add_r = ins_compl_add(matches[i], -1, NULL, ldir, 0)) == OK)
+	if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, dir, 0)) == OK)
 	    /* if dir was BACKWARD then honor it just once */
-	    ldir = FORWARD;
+	    dir = FORWARD;
     FreeWild(num_matches, matches);
 }
 
@@ -2143,7 +2172,7 @@
 
 /* "compl_match_array" points the currently displayed list of entries in the
  * popup menu.  It is NULL when there is no popup menu. */
-static char_u **compl_match_array = NULL;
+static pumitem_T *compl_match_array = NULL;
 static int compl_match_arraysize;
 
 /*
@@ -2223,11 +2252,15 @@
 
 /*
  * Show the popup menu for the list of matches.
+ * Also adjusts "compl_shown_match" to an entry that is actually displayed.
  */
     void
 ins_compl_show_pum()
 {
     compl_T     *compl;
+    compl_T     *shown_compl = NULL;
+    int		did_find_shown_match = FALSE;
+    int		shown_match_ok = FALSE;
     int		i;
     int		cur = -1;
     colnr_T	col;
@@ -2256,7 +2289,8 @@
 	} while (compl != NULL && compl != compl_first_match);
 	if (compl_match_arraysize == 0)
 	    return;
-	compl_match_array = (char_u **)alloc((unsigned)(sizeof(char_u **)
+	compl_match_array = (pumitem_T *)alloc_clear(
+				    (unsigned)(sizeof(pumitem_T)
 						    * compl_match_arraysize));
 	if (compl_match_array != NULL)
 	{
@@ -2269,19 +2303,52 @@
 			    || STRNCMP(compl->cp_str, compl_leader,
 							      lead_len) == 0))
 		{
-		    if (compl == compl_shown_match)
+		    if (!shown_match_ok)
+		    {
+			if (compl == compl_shown_match || did_find_shown_match)
+			{
+			    /* This item is the shown match or this is the
+			     * first displayed item after the shown match. */
+			    compl_shown_match = compl;
+			    did_find_shown_match = TRUE;
+			    shown_match_ok = TRUE;
+			}
+			else
+			    /* Remember this displayed match for when the
+			     * shown match is just below it. */
+			    shown_compl = compl;
 			cur = i;
-		    compl_match_array[i++] = compl->cp_str;
+		    }
+		    compl_match_array[i].pum_text = compl->cp_str;
+		    if (compl->cp_extra != NULL)
+			compl_match_array[i++].pum_extra = compl->cp_extra;
+		    else
+			compl_match_array[i++].pum_extra = compl->cp_fname;
+		}
+
+		if (compl == compl_shown_match)
+		{
+		    did_find_shown_match = TRUE;
+		    if (!shown_match_ok && shown_compl != NULL)
+		    {
+			/* The shown match isn't displayed, set it to the
+			 * previously displayed match. */
+			compl_shown_match = shown_compl;
+			shown_match_ok = TRUE;
+		    }
 		}
 		compl = compl->cp_next;
 	    } while (compl != NULL && compl != compl_first_match);
+
+	    if (!shown_match_ok)    /* no displayed match at all */
+		cur = -1;
 	}
     }
     else
     {
 	/* popup menu already exists, only need to find the current item.*/
 	for (i = 0; i < compl_match_arraysize; ++i)
-	    if (compl_match_array[i] == compl_shown_match->cp_str)
+	    if (compl_match_array[i].pum_text == compl_shown_match->cp_str)
 		break;
 	cur = i;
     }
@@ -2309,10 +2376,9 @@
  * completions.
  */
     static void
-ins_compl_dictionaries(dict, pat, dir, flags, thesaurus)
+ins_compl_dictionaries(dict, pat, flags, thesaurus)
     char_u	*dict;
     char_u	*pat;
-    int		dir;
     int		flags;
     int		thesaurus;
 {
@@ -2325,6 +2391,7 @@
     int		count;
     int		i;
     int		save_p_scs;
+    int		dir = compl_direction;
 
     buf = alloc(LSIZE);
     /* If 'infercase' is set, don't use 'smartcase' here */
@@ -2521,6 +2588,7 @@
 	/* several entries may use the same fname, free it just once. */
 	if (match->cp_flags & FREE_FNAME)
 	    vim_free(match->cp_fname);
+	vim_free(match->cp_extra);
 	vim_free(match);
     } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
     compl_first_match = compl_curr_match = NULL;
@@ -2541,8 +2609,8 @@
 }
 
 /*
- * Delete one character before the cursor and make a subset of the matches
- * that match now.
+ * Delete one character before the cursor and show the subset of the matches
+ * that match the word that is now before the cursor.
  * Returns TRUE if the work is done and another char to be got from the user.
  */
     static int
@@ -2630,6 +2698,29 @@
 }
 
 /*
+ * Append one character to the match leader.  May reduce the number of
+ * matches.
+ */
+    static void
+ins_compl_addfrommatch()
+{
+    char_u	*p;
+    int		len = curwin->w_cursor.col - compl_col;
+    int		c;
+
+    p = compl_shown_match->cp_str;
+    if (STRLEN(p) <= len)   /* the match is too short */
+	return;
+    p += len;
+#ifdef FEAT_MBYTE
+    c = mb_ptr2char(p);
+#else
+    c = *p;
+#endif
+    ins_compl_addleader(c);
+}
+
+/*
  * Prepare for Insert mode completion, or stop it.
  * Called just after typing a character in Insert mode.
  * Returns TRUE when the character is not to be inserted;
@@ -2919,30 +3010,30 @@
 }
 
 #ifdef FEAT_COMPL_FUNC
-static int expand_by_function __ARGS((int type, char_u *base, char_u ***matches));
+static void expand_by_function __ARGS((int type, char_u *base));
 
 /*
  * Execute user defined complete function 'completefunc' or 'omnifunc', and
  * get matches in "matches".
  * Return value is number of matches.
  */
-    static int
-expand_by_function(type, base, matches)
+    static void
+expand_by_function(type, base)
     int		type;	    /* CTRL_X_OMNI or CTRL_X_FUNCTION */
     char_u	*base;
-    char_u	***matches;
 {
     list_T      *matchlist;
     char_u	*args[2];
     listitem_T	*li;
-    garray_T    ga;
     char_u	*p;
     char_u	*funcname;
     pos_T	pos;
+    int		dir = compl_direction;
+    char_u	*x;
 
     funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
     if (*funcname == NUL)
-	return 0;
+	return;
 
     /* Call 'completefunc' to obtain the list of matches. */
     args[0] = (char_u *)"0";
@@ -2952,42 +3043,47 @@
     matchlist = call_func_retlist(funcname, 2, args, FALSE);
     curwin->w_cursor = pos;	/* restore the cursor position */
     if (matchlist == NULL)
-	return 0;
+	return;
 
-    /* Go through the List with matches and put them in an array. */
-    ga_init2(&ga, (int)sizeof(char_u *), 8);
+    /* Go through the List with matches and add each of them. */
     for (li = matchlist->lv_first; li != NULL; li = li->li_next)
     {
-	p = get_tv_string_chk(&li->li_tv);
+	if (li->li_tv.v_type == VAR_DICT && li->li_tv.vval.v_dict != NULL)
+	{
+	    p = get_dict_string(li->li_tv.vval.v_dict, (char_u *)"word", FALSE);
+	    x = get_dict_string(li->li_tv.vval.v_dict, (char_u *)"menu", FALSE);
+	}
+	else
+	{
+	    p = get_tv_string_chk(&li->li_tv);
+	    x = NULL;
+	}
 	if (p != NULL && *p != NUL)
 	{
-	    if (ga_grow(&ga, 1) == FAIL)
-		break;
-	    ((char_u **)ga.ga_data)[ga.ga_len] = vim_strsave(p);
-	    ++ga.ga_len;
+	    if (ins_compl_add(p, -1, NULL, x, dir, 0) == OK)
+		/* if dir was BACKWARD then honor it just once */
+		dir = FORWARD;
 	}
 	else if (did_emsg)
 	    break;
     }
 
     list_unref(matchlist);
-    *matches = (char_u **)ga.ga_data;
-    return ga.ga_len;
 }
 #endif /* FEAT_COMPL_FUNC */
 
 /*
  * Get the next expansion(s), using "compl_pattern".
- * The search starts at position "ini" in curbuf and in the direction dir.
+ * The search starts at position "ini" in curbuf and in the direction
+ * compl_direction.
  * When "compl_started" is FALSE start at that position, otherwise
  * continue where we stopped searching before.
  * This may return before finding all the matches.
  * Return the total number of matches or -1 if still unknown -- Acevedo
  */
     static int
-ins_compl_get_exp(ini, dir)
+ins_compl_get_exp(ini)
     pos_T	*ini;
-    int		dir;
 {
     static pos_T	first_match_pos;
     static pos_T	last_match_pos;
@@ -3023,7 +3119,7 @@
     }
 
     old_match = compl_curr_match;	/* remember the last current match */
-    pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos;
+    pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
     /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
     for (;;)
     {
@@ -3126,7 +3222,7 @@
 #ifdef FEAT_FIND_ID
 	case CTRL_X_PATH_PATTERNS:
 	case CTRL_X_PATH_DEFINES:
-	    find_pattern_in_path(compl_pattern, dir,
+	    find_pattern_in_path(compl_pattern, compl_direction,
 				 (int)STRLEN(compl_pattern), FALSE, FALSE,
 				 (type == CTRL_X_PATH_DEFINES
 				  && !(compl_cont_status & CONT_SOL))
@@ -3146,7 +3242,7 @@
 			     : (*curbuf->b_p_dict == NUL
 				 ? p_dict
 				 : curbuf->b_p_dict)),
-			    compl_pattern, dir,
+			    compl_pattern,
 				 dict ? dict_f : 0, type == CTRL_X_THESAURUS);
 	    dict = NULL;
 	    break;
@@ -3163,7 +3259,7 @@
 		    TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
 		    TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
 	    {
-		ins_compl_add_matches(num_matches, matches, dir);
+		ins_compl_add_matches(num_matches, matches);
 	    }
 	    p_ic = save_p_ic;
 	    break;
@@ -3175,7 +3271,7 @@
 
 		/* May change home directory back to "~". */
 		tilde_replace(compl_pattern, num_matches, matches);
-		ins_compl_add_matches(num_matches, matches, dir);
+		ins_compl_add_matches(num_matches, matches);
 	    }
 	    break;
 
@@ -3183,15 +3279,13 @@
 	    if (expand_cmdline(&compl_xp, compl_pattern,
 			(int)STRLEN(compl_pattern),
 					 &num_matches, &matches) == EXPAND_OK)
-		ins_compl_add_matches(num_matches, matches, dir);
+		ins_compl_add_matches(num_matches, matches);
 	    break;
 
 #ifdef FEAT_COMPL_FUNC
 	case CTRL_X_FUNCTION:
 	case CTRL_X_OMNI:
-	    num_matches = expand_by_function(type, compl_pattern, &matches);
-	    if (num_matches > 0)
-		ins_compl_add_matches(num_matches, matches, dir);
+	    expand_by_function(type, compl_pattern);
 	    break;
 #endif
 
@@ -3200,7 +3294,7 @@
 	    num_matches = expand_spelling(first_match_pos.lnum,
 				 first_match_pos.col, compl_pattern, &matches);
 	    if (num_matches > 0)
-		ins_compl_add_matches(num_matches, matches, dir);
+		ins_compl_add_matches(num_matches, matches);
 #endif
 	    break;
 
@@ -3230,9 +3324,10 @@
 		if (	ctrl_x_mode == CTRL_X_WHOLE_LINE
 			|| (compl_cont_status & CONT_SOL))
 		    found_new_match = search_for_exact_line(ins_buf, pos,
-							    dir, compl_pattern);
+					      compl_direction, compl_pattern);
 		else
-		    found_new_match = searchit(NULL, ins_buf, pos, dir,
+		    found_new_match = searchit(NULL, ins_buf, pos,
+							      compl_direction,
 				 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
 								     RE_LAST);
 		if (!compl_started)
@@ -3335,7 +3430,7 @@
 		}
 		if (ins_compl_add_infercase(ptr, len,
 				 ins_buf == curbuf ? NULL : ins_buf->b_sfname,
-						       dir, flags) != NOTDONE)
+					   0, flags) != NOTDONE)
 		{
 		    found_new_match = OK;
 		    break;
@@ -3388,7 +3483,7 @@
     /* If several matches were added (FORWARD) or the search failed and has
      * just been made cyclic then we have to move compl_curr_match to the next
      * or previous entry (if any) -- Acevedo */
-    compl_curr_match = dir == FORWARD ? old_match->cp_next : old_match->cp_prev;
+    compl_curr_match = compl_direction == FORWARD ? old_match->cp_next : old_match->cp_prev;
     if (compl_curr_match == NULL)
 	compl_curr_match = old_match;
     return i;
@@ -3476,7 +3571,7 @@
 	    if (!allow_get_expansion)
 		return -1;
 
-	    num_matches = ins_compl_get_exp(&compl_startpos, compl_direction);
+	    num_matches = ins_compl_get_exp(&compl_startpos);
 	    if (compl_pending && compl_direction == compl_shows_dir)
 		compl_shown_match = compl_curr_match;
 	    found_end = FALSE;
@@ -3992,7 +4087,7 @@
 	 * when the list of matches is freed. */
 	compl_orig_text = vim_strnsave(line + compl_col, compl_length);
 	if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
-					    -1, NULL, 0, ORIGINAL_TEXT) != OK)
+				      -1, NULL, NULL, 0, ORIGINAL_TEXT) != OK)
 	{
 	    vim_free(compl_pattern);
 	    compl_pattern = NULL;
diff --git a/src/eval.c b/src/eval.c
index c44aae0..3044ef8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6342,20 +6342,26 @@
 }
 
 /*
- * Get a string item from a dictionary in allocated memory.
+ * Get a string item from a dictionary.
+ * When "save" is TRUE allocate memory for it.
  * Returns NULL if the entry doesn't exist or out of memory.
  */
     char_u *
-get_dict_string(d, key)
+get_dict_string(d, key, save)
     dict_T	*d;
     char_u	*key;
+    int		save;
 {
     dictitem_T	*di;
+    char_u	*s;
 
     di = dict_find(d, key, -1);
     if (di == NULL)
 	return NULL;
-    return vim_strsave(get_tv_string(&di->di_tv));
+    s = get_tv_string(&di->di_tv);
+    if (save && s != NULL)
+	s = vim_strsave(s);
+    return s;
 }
 
 /*
@@ -8014,11 +8020,20 @@
     typval_T	*argvars;
     typval_T	*rettv;
 {
-    char_u	*s;
+    char_u	*word;
+    char_u	*extra = NULL;
 
-    s = get_tv_string_chk(&argvars[0]);
-    if (s != NULL)
-	rettv->vval.v_number = ins_compl_add(s, -1, NULL, FORWARD, 0);
+    if (argvars[0].v_type == VAR_DICT && argvars[0].vval.v_dict != NULL)
+    {
+	word = get_dict_string(argvars[0].vval.v_dict,
+						     (char_u *)"word", FALSE);
+	extra = get_dict_string(argvars[0].vval.v_dict,
+						     (char_u *)"menu", FALSE);
+    }
+    else
+	word = get_tv_string_chk(&argvars[0]);
+    if (word != NULL)
+	rettv->vval.v_number = ins_compl_add(word, -1, NULL, extra, 0, 0);
 }
 
 /*
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 488c6de..a5b0552 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -515,6 +515,8 @@
 			BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
 EX(CMD_lgrepadd,	"lgrepadd",	ex_make,
 			BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+EX(CMD_lhelpgrep,	"lhelpgrep",	ex_helpgrep,
+			EXTRA|NOTRLCOM|NEEDARG),
 EX(CMD_ll,		"ll",		ex_cc,
 			RANGE|NOTADR|COUNT|TRLBAR|BANG),
 EX(CMD_llast,		"llast",	ex_cc,
diff --git a/src/netbeans.c b/src/netbeans.c
index 78107bf..a2c57fc 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -75,6 +75,7 @@
 
 static void nb_init_graphics __ARGS((void));
 static void coloncmd __ARGS((char *cmd, ...));
+static void nb_set_curbuf __ARGS((buf_T *buf));
 #ifdef FEAT_GUI_MOTIF
 static void messageFromNetbeans __ARGS((XtPointer, int *, XtInputId *));
 #endif
@@ -1365,8 +1366,7 @@
 		netbeansFireChanges = FALSE;
 		netbeansSuppressNoLines = TRUE;
 
-		if (curbuf != buf->bufp)
-		    set_curbuf(buf->bufp, DOBUF_GOTO);
+		nb_set_curbuf(buf->bufp);
 		wasChanged = buf->bufp->b_changed;
 		cp = (char *)args;
 		off = strtol(cp, &cp, 10);
@@ -1488,8 +1488,7 @@
 		netbeansFireChanges = 0;
 		lbuf[0] = '\0';
 
-		if (curbuf != buf->bufp)
-		    set_curbuf(buf->bufp, DOBUF_GOTO);
+		nb_set_curbuf(buf->bufp);
 		old_b_changed = buf->bufp->b_changed;
 
 		pos = off2pos(buf->bufp, off);
@@ -1694,8 +1693,7 @@
 	    }
 	    doupdate = 1;
 	    buf->initDone = TRUE;
-	    if (curbuf != buf->bufp)
-		set_curbuf(buf->bufp, DOBUF_GOTO);
+	    nb_set_curbuf(buf->bufp);
 #if defined(FEAT_AUTOCMD)
 	    apply_autocmds(EVENT_BUFREADPOST, 0, 0, FALSE, buf->bufp);
 #endif
@@ -1891,8 +1889,8 @@
 		return FAIL;
 	    }
 
-	    if (curbuf != buf->bufp)
-		set_curbuf(buf->bufp, DOBUF_GOTO);
+	    nb_set_curbuf(buf->bufp);
+
 #ifdef FEAT_VISUAL
 	    /* Don't want Visual mode now. */
 	    if (VIsual_active)
@@ -2140,8 +2138,7 @@
 		nbdebug(("    null bufp in %s command", cmd));
 		return FAIL;
 	    }
-	    if (curbuf != buf->bufp)
-		set_curbuf(buf->bufp, DOBUF_GOTO);
+	    nb_set_curbuf(buf->bufp);
 	    cp = (char *)args;
 	    off = strtol(cp, &cp, 10);
 	    len = strtol(cp, NULL, 10);
@@ -2315,6 +2312,19 @@
 
 
 /*
+ * If "buf" is not the current buffer try changing to a window that edits this
+ * buffer.  If there is no such window then close the current buffer and set
+ * the current buffer as "buf".
+ */
+    static void
+nb_set_curbuf(buf)
+    buf_T *buf;
+{
+    if (curbuf != buf && buf_jump_open_win(buf) == NULL)
+	set_curbuf(buf, DOBUF_GOTO);
+}
+
+/*
  * Process a vim colon command.
  */
     static void
diff --git a/src/popupmenu.c b/src/popupmenu.c
index 7024e55..9d11a45 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -14,13 +14,14 @@
 
 #if defined(FEAT_INS_EXPAND) || defined(PROTO)
 
-static char_u **pum_array = NULL;	/* items of displayed pum */
+static pumitem_T *pum_array = NULL;	/* items of displayed pum */
 static int pum_size;			/* nr of items in "pum_array" */
 static int pum_selected;		/* index of selected item or -1 */
 static int pum_first = 0;		/* index of top item */
 
 static int pum_height;			/* nr of displayed pum items */
 static int pum_width;			/* width of displayed pum items */
+static int pum_base_width;		/* width of pum items base */
 static int pum_scrollbar;		/* TRUE when scrollbar present */
 
 static int pum_row;			/* top row of pum */
@@ -37,7 +38,7 @@
  */
     void
 pum_display(array, size, selected, row, height, col)
-    char_u	**array;
+    pumitem_T	*array;
     int		size;
     int		selected;	/* index of initially selected item */
     int		row;
@@ -47,6 +48,7 @@
     int		w;
     int		def_width = PUM_DEF_WIDTH;
     int		max_width = 0;
+    int		extra_width = 0;
     int		i;
 
     /*
@@ -87,13 +89,20 @@
     if (pum_height < 1 || (pum_height == 1 && size > 1))
 	return;
 
-    /* Compute the width of the widest match. */
+    /* Compute the width of the widest match and the widest extra. */
     for (i = 0; i < size; ++i)
     {
-	w = vim_strsize(array[i]);
+	w = vim_strsize(array[i].pum_text);
 	if (max_width < w)
 	    max_width = w;
+	if (array[i].pum_extra != NULL)
+	{
+	    w = vim_strsize(array[i].pum_extra);
+	    if (extra_width < w)
+		extra_width = w;
+	}
     }
+    pum_base_width = max_width;
 
     /* if there are more items than room we need a scrollbar */
     if (pum_height < size)
@@ -112,8 +121,13 @@
 	/* align pum column with "col" */
 	pum_col = col;
 	pum_width = Columns - pum_col - pum_scrollbar;
-	if (pum_width > def_width)
-	    pum_width = def_width;
+	if (pum_width > max_width + extra_width + 1
+						 && pum_width > PUM_DEF_WIDTH)
+	{
+	    pum_width = max_width + extra_width + 1;
+	    if (pum_width < PUM_DEF_WIDTH)
+		pum_width = PUM_DEF_WIDTH;
+	}
     }
     else if (Columns < def_width)
     {
@@ -153,9 +167,10 @@
     int		idx;
     char_u	*s;
     char_u	*p;
-    int		width, w;
+    int		totwidth, width, w;
     int		thumb_pos = 0;
     int		thumb_heigth = 1;
+    int		round;
 
     if (pum_scrollbar)
     {
@@ -176,32 +191,46 @@
 	if (pum_col > 0)
 	    screen_putchar(' ', row, pum_col - 1, attr);
 
-	/* Display each entry, use two spaces for a Tab. */
+	/* Display each entry, use two spaces for a Tab.
+	 * Do this twice: For the main text and for the extra info */
 	col = pum_col;
-	width = 0;
-	s = NULL;
-	for (p = pum_array[idx]; ; mb_ptr_adv(p))
+	totwidth = 0;
+	for (round = 1; round <= 2; ++round)
 	{
-	    if (s == NULL)
-		s = p;
-	    w = ptr2cells(p);
-	    if (*p == NUL || *p == TAB || width + w > pum_width)
+	    width = 0;
+	    s = NULL;
+	    for (p = round == 1 ? pum_array[idx].pum_text
+				: pum_array[idx].pum_extra; ; mb_ptr_adv(p))
 	    {
-		/* Display the text that fits or comes before a Tab. */
-		screen_puts_len(s, p - s, row, col, attr);
-		col += width;
+		if (s == NULL)
+		    s = p;
+		w = ptr2cells(p);
+		if (*p == NUL || *p == TAB || totwidth + w > pum_width)
+		{
+		    /* Display the text that fits or comes before a Tab. */
+		    screen_puts_len(s, p - s, row, col, attr);
+		    col += width;
 
-		if (*p != TAB)
-		    break;
+		    if (*p != TAB)
+			break;
 
-		/* Display two spaces for a Tab. */
-		screen_puts_len((char_u *)"  ", 2, row, col, attr);
-		col += 2;
-		s = NULL;
-		width = 0;
+		    /* Display two spaces for a Tab. */
+		    screen_puts_len((char_u *)"  ", 2, row, col, attr);
+		    col += 2;
+		    totwidth += 2;
+		    s = NULL;	    /* start text at next char */
+		    width = 0;
+		}
+		else
+		    width += w;
 	    }
-	    else
-		width += w;
+	    if (round == 2 || pum_array[idx].pum_extra == NULL
+					   || pum_base_width + 1 >= pum_width)
+		break;
+	    screen_fill(row, row + 1, col, pum_col + pum_base_width + 1,
+							      ' ', ' ', attr);
+	    col = pum_col + pum_base_width + 1;
+	    totwidth = pum_base_width + 1;
 	}
 
 	screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
index 27594f0..3939efc 100644
--- a/src/proto/edit.pro
+++ b/src/proto/edit.pro
@@ -8,7 +8,7 @@
 void backspace_until_column __ARGS((int col));
 int vim_is_ctrl_x_key __ARGS((int c));
 int ins_compl_add_infercase __ARGS((char_u *str, int len, char_u *fname, int dir, int flags));
-int ins_compl_add __ARGS((char_u *str, int len, char_u *fname, int dir, int flags));
+int ins_compl_add __ARGS((char_u *str, int len, char_u *fname, char_u *extra, int cdir, int flags));
 void ins_compl_show_pum __ARGS((void));
 char_u *find_word_start __ARGS((char_u *ptr));
 char_u *find_word_end __ARGS((char_u *ptr));
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index a6490ca..b8ba215 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -42,15 +42,15 @@
 int do_unlet __ARGS((char_u *name, int forceit));
 void del_menutrans_vars __ARGS((void));
 char_u *get_user_var_name __ARGS((expand_T *xp, int idx));
+list_T *list_alloc __ARGS((void));
 void list_unref __ARGS((list_T *l));
+void list_free __ARGS((list_T *l));
 dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
 int list_append_dict __ARGS((list_T *list, dict_T *dict));
 int garbage_collect __ARGS((void));
-list_T *list_alloc __ARGS((void));
-void list_free __ARGS((list_T *l));
 dict_T *dict_alloc __ARGS((void));
 int dict_add_nr_str __ARGS((dict_T *d, char *key, long nr, char_u *str));
-char_u *get_dict_string __ARGS((dict_T *d, char_u *key));
+char_u *get_dict_string __ARGS((dict_T *d, char_u *key, int save));
 long get_dict_number __ARGS((dict_T *d, char_u *key));
 char_u *get_function_name __ARGS((expand_T *xp, int idx));
 char_u *get_expr_name __ARGS((expand_T *xp, int idx));
diff --git a/src/proto/popupmenu.pro b/src/proto/popupmenu.pro
index 119d039..05f9eab 100644
--- a/src/proto/popupmenu.pro
+++ b/src/proto/popupmenu.pro
@@ -1,5 +1,5 @@
 /* popupmenu.c */
-void pum_display __ARGS((char_u **array, int size, int selected, int row, int height, int col));
+void pum_display __ARGS((pumitem_T *array, int size, int selected, int row, int height, int col));
 void pum_redraw __ARGS((void));
 void pum_set_selected __ARGS((int n));
 void pum_undisplay __ARGS((void));
diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro
index 152f906..408bf6d 100644
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -1,7 +1,8 @@
 /* quickfix.c */
 int qf_init __ARGS((win_T *wp, char_u *efile, char_u *errorformat, int newlist));
 void qf_free_all __ARGS((win_T *wp));
-void qf_jump __ARGS((win_T *wp, int dir, int errornr, int forceit));
+void copy_loclist __ARGS((win_T *from, win_T *to));
+void qf_jump __ARGS((qf_info_T *qi, int dir, int errornr, int forceit));
 void qf_list __ARGS((exarg_T *eap));
 void qf_age __ARGS((exarg_T *eap));
 void qf_mark_adjust __ARGS((win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after));
@@ -26,5 +27,4 @@
 void ex_cbuffer __ARGS((exarg_T *eap));
 void ex_cexpr __ARGS((exarg_T *eap));
 void ex_helpgrep __ARGS((exarg_T *eap));
-void copy_loclist __ARGS((win_T *from, win_T *to));
 /* vim: set ft=c : */
diff --git a/src/quickfix.c b/src/quickfix.c
index 7136b7e..f9278a2 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -954,19 +954,21 @@
 }
 
 /*
- * Allocate a new location list for window 'wp'
+ * Allocate a new location list
  */
-    static int
-ll_new_list(wp)
-    win_T   *wp;
+    static qf_info_T *
+ll_new_list()
 {
-    if ((wp->w_llist = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T))) == NULL)
-	return FAIL;
+    qf_info_T *qi;
 
-    vim_memset(wp->w_llist, 0, (size_t)(sizeof(qf_info_T)));
-    wp->w_llist->qf_refcount++;
+    qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T));
+    if (qi != NULL)
+    {
+	vim_memset(qi, 0, (size_t)(sizeof(qf_info_T)));
+	qi->qf_refcount++;
+    }
 
-    return OK;
+    return qi;
 }
 
 /*
@@ -988,8 +990,7 @@
     ll_free_all(&wp->w_llist_ref);
 
     if (wp->w_llist == NULL)
-	if (ll_new_list(wp) == FAIL)	/* new location list */
-	    return NULL;
+	wp->w_llist = ll_new_list();	    /* new location list */
     return wp->w_llist;
 }
 
@@ -1018,7 +1019,8 @@
     if (qi == NULL)		    /* no location list to copy */
 	return;
 
-    if (ll_new_list(to) == FAIL)    /* allocate a new location list */
+    /* allocate a new location list */
+    if ((to->w_llist = ll_new_list()) == NULL)
 	return;
 
     to->w_llist->qf_listcount = qi->qf_listcount;
@@ -1331,13 +1333,12 @@
  * else go to entry "errornr"
  */
     void
-qf_jump(winptr, dir, errornr, forceit)
-    win_T	*winptr;
+qf_jump(qi, dir, errornr, forceit)
+    qf_info_T	*qi;
     int		dir;
     int		errornr;
     int		forceit;
 {
-    qf_info_T		*qi = &ql_info;
     qf_info_T		*ll_ref;
     qfline_T		*qf_ptr;
     qfline_T		*old_qf_ptr;
@@ -1367,8 +1368,8 @@
     int			ok = OK;
     int			usable_win;
 
-    if (winptr != NULL)
-	qi = GET_LOC_LIST(winptr);
+    if (qi == NULL)
+	qi = &ql_info;
 
     if (qi->qf_curlist >= qi->qf_listcount
 	|| qi->qf_lists[qi->qf_curlist].qf_count == 0)
@@ -1494,6 +1495,14 @@
 
 	    if (curwin->w_height < p_hh)
 		win_setheight((int)p_hh);
+
+	    if (qi != &ql_info)	    /* not a quickfix list */
+	    {
+		/* The new window should use the supplied location list */
+		qf_free_all(curwin);
+		curwin->w_llist = qi;
+		qi->qf_refcount++;
+	    }
 	}
 
 	if (!p_im)
@@ -2583,7 +2592,7 @@
     char_u	*cmd;
     unsigned	len;
     win_T	*wp = NULL;
-    qf_info_T	*qi;
+    qf_info_T	*qi = &ql_info;
 #ifdef FEAT_AUTOCMD
     char_u	*au_name = NULL;
 
@@ -2667,7 +2676,7 @@
 					   (eap->cmdidx != CMD_grepadd
 					    && eap->cmdidx != CMD_lgrepadd)) > 0
 	    && !eap->forceit)
-	qf_jump(wp, 0, 0, FALSE);		/* display first error */
+	qf_jump(qi, 0, 0, FALSE);		/* display first error */
 
     mch_remove(fname);
     vim_free(fname);
@@ -2745,11 +2754,12 @@
 ex_cc(eap)
     exarg_T	*eap;
 {
-    win_T	*wp = NULL;
-    qf_info_T	*qi;
+    qf_info_T	*qi = &ql_info;
 
-    if (eap->cmdidx == CMD_ll || eap->cmdidx == CMD_lrewind
-	|| eap->cmdidx == CMD_lfirst || eap->cmdidx == CMD_llast)
+    if (eap->cmdidx == CMD_ll
+	    || eap->cmdidx == CMD_lrewind
+	    || eap->cmdidx == CMD_lfirst
+	    || eap->cmdidx == CMD_llast)
     {
 	qi = GET_LOC_LIST(curwin);
 	if (qi == NULL)
@@ -2757,10 +2767,9 @@
 	    EMSG(_(e_loclist));
 	    return;
 	}
-	wp = curwin;
     }
 
-    qf_jump(wp, 0,
+    qf_jump(qi, 0,
 	    eap->addr_count > 0
 	    ? (int)eap->line2
 	    : (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll)
@@ -2780,12 +2789,14 @@
 ex_cnext(eap)
     exarg_T	*eap;
 {
-    win_T	*wp = NULL;
-    qf_info_T	*qi;
+    qf_info_T	*qi = &ql_info;
 
-    if (eap->cmdidx == CMD_lnext || eap->cmdidx == CMD_lNext
-	|| eap->cmdidx == CMD_lprevious || eap->cmdidx == CMD_lnfile
-	|| eap->cmdidx == CMD_lNfile || eap->cmdidx == CMD_lpfile)
+    if (eap->cmdidx == CMD_lnext
+	    || eap->cmdidx == CMD_lNext
+	    || eap->cmdidx == CMD_lprevious
+	    || eap->cmdidx == CMD_lnfile
+	    || eap->cmdidx == CMD_lNfile
+	    || eap->cmdidx == CMD_lpfile)
     {
 	qi = GET_LOC_LIST(curwin);
 	if (qi == NULL)
@@ -2793,10 +2804,9 @@
 	    EMSG(_(e_loclist));
 	    return;
 	}
-	wp = curwin;
     }
 
-    qf_jump(wp, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext)
+    qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext)
 	    ? FORWARD
 	    : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile)
 		? FORWARD_FILE
@@ -2816,7 +2826,7 @@
     exarg_T	*eap;
 {
     win_T	*wp = NULL;
-    qf_info_T	*qi;
+    qf_info_T	*qi = &ql_info;
 
     if (eap->cmdidx == CMD_lfile || eap->cmdidx == CMD_lgetfile
 	|| eap->cmdidx == CMD_laddfile)
@@ -2844,7 +2854,7 @@
 				  && eap->cmdidx != CMD_laddfile)) > 0
 				  && (eap->cmdidx == CMD_cfile
 					     || eap->cmdidx == CMD_lfile))
-	qf_jump(wp, 0, 0, eap->forceit);	/* display first error */
+	qf_jump(qi, 0, 0, eap->forceit);	/* display first error */
 }
 
 /*
@@ -2865,7 +2875,6 @@
     int		fi;
     qf_info_T	*qi = &ql_info;
     qfline_T	*prevp = NULL;
-    win_T	*wp = NULL;
     long	lnum;
     buf_T	*buf;
     int		duplicate_name = FALSE;
@@ -2899,13 +2908,14 @@
     }
 #endif
 
-    if (eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lvimgrep
-	|| eap->cmdidx == CMD_lgrepadd || eap->cmdidx == CMD_lvimgrepadd)
+    if (eap->cmdidx == CMD_grep
+	    || eap->cmdidx == CMD_lvimgrep
+	    || eap->cmdidx == CMD_lgrepadd
+	    || eap->cmdidx == CMD_lvimgrepadd)
     {
 	qi = ll_get_or_alloc_list(curwin);
 	if (qi == NULL)
 	    return;
-	wp = curwin;
     }
 
     /* Get the search pattern: either white-separated or enclosed in // */
@@ -3105,7 +3115,7 @@
     if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
     {
 	if ((flags & VGR_NOJUMP) == 0)
-	    qf_jump(wp, 0, 0, eap->forceit);
+	    qf_jump(qi, 0, 0, eap->forceit);
     }
     else
 	EMSG2(_(e_nomatch2), s);
@@ -3376,14 +3386,14 @@
 	if (d == NULL)
 	    continue;
 
-	filename = get_dict_string(d, (char_u *)"filename");
+	filename = get_dict_string(d, (char_u *)"filename", TRUE);
 	lnum = get_dict_number(d, (char_u *)"lnum");
 	col = get_dict_number(d, (char_u *)"col");
 	vcol = get_dict_number(d, (char_u *)"vcol");
 	nr = get_dict_number(d, (char_u *)"nr");
-	type = get_dict_string(d, (char_u *)"type");
-	pattern = get_dict_string(d, (char_u *)"pattern");
-	text = get_dict_string(d, (char_u *)"text");
+	type = get_dict_string(d, (char_u *)"type", TRUE);
+	pattern = get_dict_string(d, (char_u *)"pattern", TRUE);
+	text = get_dict_string(d, (char_u *)"text", TRUE);
 	if (text == NULL)
 	    text = vim_strsave((char_u *)"");
 
@@ -3484,14 +3494,12 @@
 {
     typval_T	*tv;
     qf_info_T	*qi = &ql_info;
-    win_T	*wp = NULL;
 
     if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_laddexpr)
     {
 	qi = ll_get_or_alloc_list(curwin);
 	if (qi == NULL)
 	    return;
-	wp = curwin;
     }
 
     /* Evaluate the expression.  When the result is a string or a list we can
@@ -3507,7 +3515,7 @@
 			     || eap->cmdidx == CMD_lexpr),
 						 (linenr_T)0, (linenr_T)0) > 0
 		    && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr))
-		qf_jump(wp, 0, 0, eap->forceit);  /* display first error */
+		qf_jump(qi, 0, 0, eap->forceit);  /* display first error */
 	}
 	else
 	    EMSG(_("E777: String or List expected"));
@@ -3536,6 +3544,8 @@
     char_u	*lang;
 #endif
     qf_info_T	*qi = &ql_info;
+    int		new_qi = FALSE;
+    win_T	*wp;
 
     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
     save_cpo = p_cpo;
@@ -3546,6 +3556,27 @@
     lang = check_help_lang(eap->arg);
 #endif
 
+    if (eap->cmdidx == CMD_lhelpgrep)
+    {
+	/* Find an existing help window */
+	FOR_ALL_WINDOWS(wp)
+	    if (wp->w_buffer != NULL && wp->w_buffer->b_help)
+		break;
+
+	if (wp == NULL)	    /* Help window not found */
+	    qi = NULL;
+	else
+	    qi = wp->w_llist;
+
+	if (qi == NULL)
+	{
+	    /* Allocate a new location list for help text matches */
+	    if ((qi = ll_new_list()) == NULL)
+		return;
+	    new_qi = TRUE;
+	}
+    }
+
     regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
     regmatch.rm_ic = FALSE;
     if (regmatch.regprog != NULL)
@@ -3635,9 +3666,23 @@
 
     /* Jump to first match. */
     if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
-	qf_jump(NULL, 0, 0, FALSE);
+	qf_jump(qi, 0, 0, FALSE);
     else
 	EMSG2(_(e_nomatch2), eap->arg);
+
+    if (eap->cmdidx == CMD_lhelpgrep)
+    {
+	/* If the help window is not opened or if it already points to the
+	 * correct location list, then free the new location list
+	 */ 
+	if (!curwin->w_buffer->b_help || curwin->w_llist == qi)
+	{
+	    if (new_qi)
+		ll_free_all(&qi);
+	}
+	else if (curwin->w_llist == NULL)
+	    curwin->w_llist = qi;
+    }
 }
 
 #endif /* FEAT_QUICKFIX */
diff --git a/src/structs.h b/src/structs.h
index e8d5b72..462ee52 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1085,9 +1085,7 @@
 # define B_SPELL(buf)  (0)
 #endif
 
-#ifdef FEAT_QUICKFIX
 typedef struct qf_info_S qf_info_T;
-#endif
 
 /*
  * buffer: structure that holds information about one file
@@ -2148,3 +2146,13 @@
 } prt_settings_T;
 
 #define PRINT_NUMBER_WIDTH 8
+
+/*
+ * Used for popup menu items.
+ */
+typedef struct
+{
+    char_u	*pum_text;	/* main menu text */
+    char_u	*pum_extra;	/* extra menu text (may be truncated) */
+    char_u	*pum_info;	/* extra info */
+} pumitem_T;
diff --git a/src/version.h b/src/version.h
index 5d6c7f9..14b374d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 4)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 4, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 7)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 7, compiled "