patch 7.4.2200
Problem:    Cannot get all information about a quickfix list.
Solution:   Add an optional argument to get/set loc/qf list(). (Yegappan
            Lakshmanan)
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 8b5ad22..8bb002a 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -171,6 +171,7 @@
 static void f_getftime(typval_T *argvars, typval_T *rettv);
 static void f_getftype(typval_T *argvars, typval_T *rettv);
 static void f_getline(typval_T *argvars, typval_T *rettv);
+static void f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED);
 static void f_getmatches(typval_T *argvars, typval_T *rettv);
 static void f_getpid(typval_T *argvars, typval_T *rettv);
 static void f_getcurpos(typval_T *argvars, typval_T *rettv);
@@ -591,11 +592,11 @@
     {"getftime",	1, 1, f_getftime},
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
-    {"getloclist",	1, 1, f_getqflist},
+    {"getloclist",	1, 2, f_getloclist},
     {"getmatches",	0, 0, f_getmatches},
     {"getpid",		0, 0, f_getpid},
     {"getpos",		1, 1, f_getpos},
-    {"getqflist",	0, 0, f_getqflist},
+    {"getqflist",	0, 1, f_getqflist},
     {"getreg",		0, 3, f_getreg},
     {"getregtype",	0, 1, f_getregtype},
     {"gettabvar",	2, 3, f_gettabvar},
@@ -741,10 +742,10 @@
     {"setcmdpos",	1, 1, f_setcmdpos},
     {"setfperm",	2, 2, f_setfperm},
     {"setline",		2, 2, f_setline},
-    {"setloclist",	2, 3, f_setloclist},
+    {"setloclist",	2, 4, f_setloclist},
     {"setmatches",	1, 1, f_setmatches},
     {"setpos",		2, 2, f_setpos},
-    {"setqflist",	1, 2, f_setqflist},
+    {"setqflist",	1, 3, f_setqflist},
     {"setreg",		2, 3, f_setreg},
     {"settabvar",	3, 3, f_settabvar},
     {"settabwinvar",	4, 4, f_settabwinvar},
@@ -4529,6 +4530,51 @@
     get_buffer_lines(curbuf, lnum, end, retlist, rettv);
 }
 
+static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv);
+
+    static void
+get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
+{
+#ifdef FEAT_QUICKFIX
+    if (what_arg->v_type == VAR_UNKNOWN)
+    {
+	if (rettv_list_alloc(rettv) == OK)
+	    if (is_qf || wp != NULL)
+		(void)get_errorlist(wp, -1, rettv->vval.v_list);
+    }
+    else
+    {
+	if (rettv_dict_alloc(rettv) == OK)
+	    if (is_qf || (wp != NULL))
+	    {
+		if (what_arg->v_type == VAR_DICT)
+		{
+		    dict_T	*d = what_arg->vval.v_dict;
+
+		    if (d != NULL)
+			get_errorlist_properties(wp, d, rettv->vval.v_dict);
+		}
+		else
+		    EMSG(_(e_dictreq));
+	    }
+    }
+#endif
+}
+
+/*
+ * "getloclist()" function
+ */
+    static void
+f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+#ifdef FEAT_QUICKFIX
+    win_T	*wp;
+
+    wp = find_win_by_nr(&argvars[0], NULL);
+    get_qf_loc_list(FALSE, wp, &argvars[1], rettv);
+#endif
+}
+
 /*
  * "getmatches()" function
  */
@@ -4666,28 +4712,13 @@
 }
 
 /*
- * "getqflist()" and "getloclist()" functions
+ * "getqflist()" function
  */
     static void
 f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
 {
 #ifdef FEAT_QUICKFIX
-    win_T	*wp;
-#endif
-
-#ifdef FEAT_QUICKFIX
-    if (rettv_list_alloc(rettv) == OK)
-    {
-	wp = NULL;
-	if (argvars[0].v_type != VAR_UNKNOWN)	/* getloclist() */
-	{
-	    wp = find_win_by_nr(&argvars[0], NULL);
-	    if (wp == NULL)
-		return;
-	}
-
-	(void)get_errorlist(wp, rettv->vval.v_list);
-    }
+    get_qf_loc_list(TRUE, NULL, &argvars[0], rettv);
 #endif
 }
 
@@ -9525,7 +9556,7 @@
 	appended_lines_mark(lcount, added);
 }
 
-static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv);
+static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv);
 
 /*
  * Used by "setqflist()" and "setloclist()" functions
@@ -9535,6 +9566,7 @@
     win_T	*wp UNUSED,
     typval_T	*list_arg UNUSED,
     typval_T	*action_arg UNUSED,
+    typval_T	*what_arg UNUSED,
     typval_T	*rettv)
 {
 #ifdef FEAT_QUICKFIX
@@ -9551,6 +9583,8 @@
     else
     {
 	list_T  *l = list_arg->vval.v_list;
+	dict_T	*d = NULL;
+	int	valid_dict = TRUE;
 
 	if (action_arg->v_type == VAR_STRING)
 	{
@@ -9567,8 +9601,20 @@
 	else
 	    EMSG(_(e_stringreq));
 
-	if (l != NULL && action && set_errorlist(wp, l, action,
-	       (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK)
+	if (action_arg->v_type != VAR_UNKNOWN
+		&& what_arg->v_type != VAR_UNKNOWN)
+	{
+	    if (what_arg->v_type == VAR_DICT)
+		d = what_arg->vval.v_dict;
+	    else
+	    {
+		EMSG(_(e_dictreq));
+		valid_dict = FALSE;
+	    }
+	}
+
+	if (l != NULL && action && valid_dict && set_errorlist(wp, l, action,
+	    (char_u *)(wp == NULL ? "setqflist()" : "setloclist()"), d) == OK)
 	    rettv->vval.v_number = 0;
     }
 #endif
@@ -9586,7 +9632,7 @@
 
     win = find_win_by_nr(&argvars[0], NULL);
     if (win != NULL)
-	set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
+	set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv);
 }
 
 /*
@@ -9754,7 +9800,7 @@
     static void
 f_setqflist(typval_T *argvars, typval_T *rettv)
 {
-    set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv);
+    set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv);
 }
 
 /*
diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro
index 02c2d98..99f5ede 100644
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -27,8 +27,9 @@
 void ex_cfile(exarg_T *eap);
 void ex_vimgrep(exarg_T *eap);
 char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags);
-int get_errorlist(win_T *wp, list_T *list);
-int set_errorlist(win_T *wp, list_T *list, int action, char_u *title);
+int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict);
+int get_errorlist(win_T *wp, int qf_idx, list_T *list);
+int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what);
 void ex_cbuffer(exarg_T *eap);
 void ex_cexpr(exarg_T *eap);
 void ex_helpgrep(exarg_T *eap);
diff --git a/src/quickfix.c b/src/quickfix.c
index aa94ae6..2fa6ed9 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -3141,6 +3141,24 @@
 }
 
 /*
+ * Update the w:quickfix_title variable in the quickfix/location list window
+ */
+    static void
+qf_update_win_titlevar(qf_info_T *qi)
+{
+    win_T	*win;
+    win_T	*curwin_save;
+
+    if ((win = qf_find_win(qi)) != NULL)
+    {
+	curwin_save = curwin;
+	curwin = win;
+	qf_set_title_var(qi);
+	curwin = curwin_save;
+    }
+}
+
+/*
  * Find the quickfix buffer.  If it exists, update the contents.
  */
     static void
@@ -3148,7 +3166,6 @@
 {
     buf_T	*buf;
     win_T	*win;
-    win_T	*curwin_save;
     aco_save_T	aco;
 
     /* Check if a buffer for the quickfix list exists.  Update it. */
@@ -3161,13 +3178,7 @@
 	    /* set curwin/curbuf to buf and save a few things */
 	    aucmd_prepbuf(&aco, buf);
 
-	if ((win = qf_find_win(qi)) != NULL)
-	{
-	    curwin_save = curwin;
-	    curwin = win;
-	    qf_set_title_var(qi);
-	    curwin = curwin_save;
-	}
+	qf_update_win_titlevar(qi);
 
 	qf_fill_buffer(qi, buf, old_last);
 
@@ -4532,9 +4543,10 @@
 #if defined(FEAT_EVAL) || defined(PROTO)
 /*
  * Add each quickfix error to list "list" as a dictionary.
+ * If qf_idx is -1, use the current list. Otherwise, use the specified list.
  */
     int
-get_errorlist(win_T *wp, list_T *list)
+get_errorlist(win_T *wp, int qf_idx, list_T *list)
 {
     qf_info_T	*qi = &ql_info;
     dict_T	*dict;
@@ -4550,12 +4562,15 @@
 	    return FAIL;
     }
 
-    if (qi->qf_curlist >= qi->qf_listcount
-	    || qi->qf_lists[qi->qf_curlist].qf_count == 0)
+    if (qf_idx == -1)
+	qf_idx = qi->qf_curlist;
+
+    if (qf_idx >= qi->qf_listcount
+	    || qi->qf_lists[qf_idx].qf_count == 0)
 	return FAIL;
 
-    qfp = qi->qf_lists[qi->qf_curlist].qf_start;
-    for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i)
+    qfp = qi->qf_lists[qf_idx].qf_start;
+    for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; ++i)
     {
 	/* Handle entries with a non-existing buffer number. */
 	bufnum = qfp->qf_fnum;
@@ -4590,16 +4605,93 @@
 }
 
 /*
- * Populate the quickfix list with the items supplied in the list
- * of dictionaries. "title" will be copied to w:quickfix_title.
- * "action" is 'a' for add, 'r' for replace.  Otherwise create a new list.
+ * Flags used by getqflist()/getloclist() to determine which fields to return.
+ */
+enum {
+    QF_GETLIST_NONE	= 0x0,
+    QF_GETLIST_TITLE	= 0x1,
+    QF_GETLIST_ITEMS	= 0x2,
+    QF_GETLIST_NR	= 0x4,
+    QF_GETLIST_WINID	= 0x8,
+    QF_GETLIST_ALL	= 0xFF
+};
+
+/*
+ * Return quickfix/location list details (title) as a
+ * dictionary. 'what' contains the details to return. If 'list_idx' is -1,
+ * then current list is used. Otherwise the specified list is used.
  */
     int
-set_errorlist(
-    win_T	*wp,
-    list_T	*list,
-    int		action,
-    char_u	*title)
+get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
+{
+    qf_info_T	*qi = &ql_info;
+    int		status = OK;
+    int		qf_idx;
+    dictitem_T	*di;
+    int		flags = QF_GETLIST_NONE;
+
+    if (wp != NULL)
+    {
+	qi = GET_LOC_LIST(wp);
+	if (qi == NULL)
+	    return FAIL;
+    }
+
+    qf_idx = qi->qf_curlist;		/* default is the current list */
+    if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
+    {
+	/* Use the specified quickfix/location list */
+	if (di->di_tv.v_type == VAR_NUMBER)
+	{
+	    qf_idx = di->di_tv.vval.v_number - 1;
+	    if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
+		return FAIL;
+	    flags |= QF_GETLIST_NR;
+	}
+	else
+	    return FAIL;
+    }
+
+    if (dict_find(what, (char_u *)"all", -1) != NULL)
+	flags |= QF_GETLIST_ALL;
+
+    if (dict_find(what, (char_u *)"title", -1) != NULL)
+	flags |= QF_GETLIST_TITLE;
+
+    if (dict_find(what, (char_u *)"winid", -1) != NULL)
+	flags |= QF_GETLIST_WINID;
+
+    if (flags & QF_GETLIST_TITLE)
+    {
+	char_u	*t;
+	t = qi->qf_lists[qf_idx].qf_title;
+	if (t == NULL)
+	    t = (char_u *)"";
+	status = dict_add_nr_str(retdict, "title", 0L, t);
+    }
+    if ((status == OK) && (flags & QF_GETLIST_NR))
+	status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
+    if ((status == OK) && (flags & QF_GETLIST_WINID))
+    {
+	win_T	*win;
+	win = qf_find_win(qi);
+	if (win != NULL)
+	    status = dict_add_nr_str(retdict, "winid", win->w_id, NULL);
+    }
+
+    return status;
+}
+
+/*
+ * Add list of entries to quickfix/location list. Each list entry is
+ * a dictionary with item information.
+ */
+    static int
+qf_add_entries(
+	qf_info_T	*qi,
+	list_T		*list,
+	char_u		*title,
+	int		action)
 {
     listitem_T	*li;
     dict_T	*d;
@@ -4613,16 +4705,8 @@
 #endif
     int		valid, status;
     int		retval = OK;
-    qf_info_T	*qi = &ql_info;
     int		did_bufnr_emsg = FALSE;
 
-    if (wp != NULL)
-    {
-	qi = ll_get_or_alloc_list(wp);
-	if (qi == NULL)
-	    return FAIL;
-    }
-
     if (action == ' ' || qi->qf_curlist == qi->qf_listcount)
 	/* make place for a new list */
 	qf_new_list(qi, title);
@@ -4719,6 +4803,74 @@
 
     return retval;
 }
+
+    static int
+qf_set_properties(qf_info_T *qi, dict_T *what)
+{
+    dictitem_T	*di;
+    int		retval = FAIL;
+    int		qf_idx;
+
+    qf_idx = qi->qf_curlist;		/* default is the current list */
+    if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
+    {
+	/* Use the specified quickfix/location list */
+	if (di->di_tv.v_type == VAR_NUMBER)
+	{
+	    qf_idx = di->di_tv.vval.v_number - 1;
+	    if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
+		return FAIL;
+	}
+	else
+	    return FAIL;
+    }
+
+    if ((di = dict_find(what, (char_u *)"title", -1)) != NULL)
+    {
+	if (di->di_tv.v_type == VAR_STRING)
+	{
+	    vim_free(qi->qf_lists[qf_idx].qf_title);
+	    qi->qf_lists[qf_idx].qf_title =
+		get_dict_string(what, (char_u *)"title", TRUE);
+	    if (qf_idx == qi->qf_curlist)
+		qf_update_win_titlevar(qi);
+	    retval = OK;
+	}
+    }
+
+    return retval;
+}
+
+/*
+ * Populate the quickfix list with the items supplied in the list
+ * of dictionaries. "title" will be copied to w:quickfix_title.
+ * "action" is 'a' for add, 'r' for replace.  Otherwise create a new list.
+ */
+    int
+set_errorlist(
+	win_T	*wp,
+	list_T	*list,
+	int	action,
+	char_u	*title,
+	dict_T	*what)
+{
+    qf_info_T	*qi = &ql_info;
+    int		retval = OK;
+
+    if (wp != NULL)
+    {
+	qi = ll_get_or_alloc_list(wp);
+	if (qi == NULL)
+	    return FAIL;
+    }
+
+    if (what != NULL)
+	retval = qf_set_properties(qi, what);
+    else
+	retval = qf_add_entries(qi, list, title, action);
+
+    return retval;
+}
 #endif
 
 /*
diff --git a/src/tag.c b/src/tag.c
index cfc2b51..e388a43 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -916,7 +916,7 @@
 		}
 
 		vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
-		set_errorlist(curwin, list, ' ', IObuff);
+		set_errorlist(curwin, list, ' ', IObuff, NULL);
 
 		list_free(list);
 		vim_free(fname);
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 9f0b510..b7d985d 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -1505,3 +1505,42 @@
 
   call delete('Xgrepthis')
 endfunc
+
+" Quickfix/Location list set/get properties tests
+function Xproperty_tests(cchar)
+    call s:setup_commands(a:cchar)
+
+    " Error cases
+    call assert_fails('call g:Xgetlist(99)', 'E715:')
+    call assert_fails('call g:Xsetlist(99)', 'E714:')
+    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
+
+    " Set and get the title
+    Xopen
+    wincmd p
+    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
+    call g:Xsetlist([], 'a', {'title' : 'Sample'})
+    let d = g:Xgetlist({"title":1})
+    call assert_equal('Sample', d.title)
+
+    Xopen
+    call assert_equal('Sample', w:quickfix_title)
+    Xclose
+
+    " Invalid arguments
+    call assert_fails('call g:Xgetlist([])', 'E715')
+    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
+    let s = g:Xsetlist([], 'a', {'abc':1})
+    call assert_equal(-1, s)
+
+    call assert_equal({}, g:Xgetlist({'abc':1}))
+
+    if a:cchar == 'l'
+	call assert_equal({}, getloclist(99, ['title']))
+    endif
+endfunction
+
+function Test_qf_property()
+    call Xproperty_tests('c')
+    call Xproperty_tests('l')
+endfunction
diff --git a/src/version.c b/src/version.c
index b324c12..66648d2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2200,
+/**/
     2199,
 /**/
     2198,