diff -r c015eedb9b4a -r 16a6bada509b runtime/doc/eval.txt
--- a/runtime/doc/eval.txt	Sun Jul 14 15:06:50 2013 +0200
+++ b/runtime/doc/eval.txt	Sun Jul 14 19:55:58 2013 -0400
@@ -3513,7 +3513,7 @@
 		See |expand()| for expanding special Vim variables.  See
 		|system()| for getting the raw output of an external command.
 
-globpath({path}, {expr} [, {flag}])			*globpath()*
+globpath({path}, {expr} [, {nosuf} [, {list}]])			*globpath()*
 		Perform glob() on all directories in {path} and concatenate
 		the results.  Example: >
 			:echo globpath(&rtp, "syntax/c.vim")
@@ -3525,11 +3525,18 @@
 		trailing backslash, remove it if you put a comma after it.
 		If the expansion fails for one of the directories, there is no
 		error message.
-		Unless the optional {flag} argument is given and is non-zero,
+
+		Unless the optional {nosuf} argument is given and is non-zero,
 		the 'suffixes' and 'wildignore' options apply: Names matching
 		one of the patterns in 'wildignore' will be skipped and
 		'suffixes' affect the ordering of matches.
 
+		When {list} is present and it is non-zero the result is a List
+		with all matching files. The advantage of using a List is, you
+		also get filenames containing newlines correctly. Otherwise
+		the result is a String and when there are several matches,
+		they are separated by <NL> characters.
+
 		The "**" item can be used to search in a directory tree.
 		For example, to find all "README.txt" files in the directories
 		in 'runtimepath' and below: >
diff -r c015eedb9b4a -r 16a6bada509b src/eval.c
--- a/src/eval.c	Sun Jul 14 15:06:50 2013 +0200
+++ b/src/eval.c	Sun Jul 14 19:55:58 2013 -0400
@@ -7949,7 +7949,7 @@
     {"getwinposy",	0, 0, f_getwinposy},
     {"getwinvar",	2, 3, f_getwinvar},
     {"glob",		1, 3, f_glob},
-    {"globpath",	2, 3, f_globpath},
+    {"globpath",	2, 4, f_globpath},
     {"has",		1, 1, f_has},
     {"has_key",		2, 2, f_has_key},
     {"haslocaldir",	0, 0, f_haslocaldir},
@@ -12056,18 +12056,49 @@
     char_u	buf1[NUMBUFLEN];
     char_u	*file = get_tv_string_buf_chk(&argvars[1], buf1);
     int		error = FALSE;
+    garray_T	ga;
+    int		i;
+    char_u	*s;
+
+    ga_init2(&ga, (int)sizeof(char_u **), 10);
 
     /* When the optional second argument is non-zero, don't remove matches
     * for 'wildignore' and don't put matches for 'suffixes' at the end. */
-    if (argvars[2].v_type != VAR_UNKNOWN
-				&& get_tv_number_chk(&argvars[2], &error))
-	flags |= WILD_KEEP_ALL;
-    rettv->v_type = VAR_STRING;
-    if (file == NULL || error)
+    rettv->v_type = VAR_STRING;
+    if (argvars[2].v_type != VAR_UNKNOWN)
+    {
+	if (get_tv_number_chk(&argvars[2], &error))
+	    flags |= WILD_KEEP_ALL;
+	if (argvars[3].v_type != VAR_UNKNOWN
+				    && get_tv_number_chk(&argvars[3], &error))
+	{
+	    rettv->v_type = VAR_LIST;
+	    rettv->vval.v_list = NULL;
+	}
+    }
+    if (file != NULL && !error)
+    {
+	globpath(get_tv_string(&argvars[0]), file, &ga, flags);
+	if (rettv->v_type == VAR_STRING)
+	{
+	    rettv->vval.v_string = ga_concat_strings(&ga);
+	    s = rettv->vval.v_string;
+	    for (i = 0, s = rettv->vval.v_string; i < ga.ga_len - 1; i++)
+	    {
+		s += (int)STRLEN(((char_u **)(ga.ga_data))[i]);
+		*s++ = '\n';
+	    }
+	}
+	else if (rettv_list_alloc(rettv) != FAIL)
+	{
+	    for (i = 0; i < ga.ga_len; ++i)
+		list_append_string(rettv->vval.v_list,
+					    ((char_u **)(ga.ga_data))[i], -1);
+            ga_clear_strings(&ga);
+	}
+    }
+    else
 	rettv->vval.v_string = NULL;
-    else
-	rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file,
-								       flags);
 }
 
 /*
diff -r c015eedb9b4a -r 16a6bada509b src/ex_getln.c
--- a/src/ex_getln.c	Sun Jul 14 15:06:50 2013 +0200
+++ b/src/ex_getln.c	Sun Jul 14 19:55:58 2013 -0400
@@ -5095,9 +5095,9 @@
     char_u	***file;
     char	*dirnames[];
 {
-    char_u	*matches;
     char_u	*s;
     char_u	*e;
+    char_u	*match;
     garray_T	ga;
     int		i;
     int		pat_len;
@@ -5116,33 +5116,27 @@
 	    return FAIL;
 	}
 	sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat);
-	matches = globpath(p_rtp, s, 0);
+	globpath(p_rtp, s, &ga, 0);
 	vim_free(s);
-	if (matches == NULL)
-	    continue;
-
-	for (s = matches; *s != NUL; s = e)
+    }
+
+    for (i = 0; i < ga.ga_len; ++i)
+    {
+	match = ((char_u **)ga.ga_data)[i];
+	s = match;
+	e = s + STRLEN(s);
+	if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0)
 	{
-	    e = vim_strchr(s, '\n');
-	    if (e == NULL)
-		e = s + STRLEN(s);
-	    if (ga_grow(&ga, 1) == FAIL)
-		break;
-	    if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0)
-	    {
-		for (s = e - 4; s > matches; mb_ptr_back(matches, s))
-		    if (*s == '\n' || vim_ispathsep(*s))
-			break;
-		++s;
-		((char_u **)ga.ga_data)[ga.ga_len] =
-					    vim_strnsave(s, (int)(e - s - 4));
-		++ga.ga_len;
-	    }
-	    if (*e != NUL)
-		++e;
+	    e -= 4;
+	    for (s = e; s > match; mb_ptr_back(match, s))
+		if (*s == NUL || vim_ispathsep(*s))
+		    break;
+	    ++s;
+	    *e = NUL;
+	    mch_memmove(match, s, e - s + 1);
 	}
-	vim_free(matches);
     }
+
     if (ga.ga_len == 0)
 	return FAIL;
 
@@ -5163,30 +5157,26 @@
  * Returns an allocated string with all matches concatenated, separated by
  * newlines.  Returns NULL for an error or no matches.
  */
-    char_u *
-globpath(path, file, expand_options)
+    int
+globpath(path, file, ga, expand_options)
     char_u	*path;
     char_u	*file;
+    garray_T	*ga;
     int		expand_options;
 {
     expand_T	xpc;
     char_u	*buf;
-    garray_T	ga;
     int		i;
-    int		len;
     int		num_p;
     char_u	**p;
-    char_u	*cur = NULL;
 
     buf = alloc(MAXPATHL);
     if (buf == NULL)
-	return NULL;
+	return 0;
 
     ExpandInit(&xpc);
     xpc.xp_context = EXPAND_FILES;
 
-    ga_init2(&ga, 1, 100);
-
     /* Loop over all entries in {path}. */
     while (*path != NUL)
     {
@@ -5207,30 +5197,24 @@
 			     WILD_SILENT|expand_options) != FAIL && num_p > 0)
 	    {
 		ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options);
-		for (len = 0, i = 0; i < num_p; ++i)
-		    len += (int)STRLEN(p[i]) + 1;
-
-		/* Concatenate new results to previous ones. */
-		if (ga_grow(&ga, len) == OK)
+
+		if (ga_grow(ga, num_p) == OK)
 		{
-		    cur = (char_u *)ga.ga_data + ga.ga_len;
 		    for (i = 0; i < num_p; ++i)
 		    {
-			STRCPY(cur, p[i]);
-			cur += STRLEN(p[i]);
-			*cur++ = '\n';
+			((char_u **)ga->ga_data)[ga->ga_len] =
+					    vim_strnsave(p[i], STRLEN(p[i]));
+			++ga->ga_len;
 		    }
-		    ga.ga_len += len;
 		}
+
 		FreeWild(num_p, p);
 	    }
 	}
     }
-    if (cur != NULL)
-	*--cur = 0; /* Replace trailing newline with NUL */
 
     vim_free(buf);
-    return (char_u *)ga.ga_data;
+    return ga->ga_len;
 }
 
 #endif
diff -r c015eedb9b4a -r 16a6bada509b src/misc1.c
--- a/src/misc1.c	Sun Jul 14 15:06:50 2013 +0200
+++ b/src/misc1.c	Sun Jul 14 19:55:58 2013 -0400
@@ -10381,9 +10381,6 @@
 {
     char_u	*curdir;
     garray_T	path_ga;
-    char_u	*files = NULL;
-    char_u	*s;	/* start */
-    char_u	*e;	/* end */
     char_u	*paths = NULL;
 
     if ((curdir = alloc((unsigned)MAXPATHL)) == NULL)
@@ -10401,32 +10398,8 @@
     if (paths == NULL)
 	return 0;
 
-    files = globpath(paths, pattern, (flags & EW_ICASE) ? WILD_ICASE : 0);
+    globpath(paths, pattern, gap, (flags & EW_ICASE) ? WILD_ICASE : 0);
     vim_free(paths);
-    if (files == NULL)
-	return 0;
-
-    /* Copy each path in files into gap */
-    s = e = files;
-    while (*s != NUL)
-    {
-	while (*e != '\n' && *e != NUL)
-	    e++;
-	if (*e == NUL)
-	{
-	    addfile(gap, s, flags);
-	    break;
-	}
-	else
-	{
-	    /* *e is '\n' */
-	    *e = NUL;
-	    addfile(gap, s, flags);
-	    e++;
-	    s = e;
-	}
-    }
-    vim_free(files);
 
     return gap->ga_len;
 }
diff -r c015eedb9b4a -r 16a6bada509b src/proto/ex_getln.pro
--- a/src/proto/ex_getln.pro	Sun Jul 14 15:06:50 2013 +0200
+++ b/src/proto/ex_getln.pro	Sun Jul 14 19:55:58 2013 -0400
@@ -32,7 +32,7 @@
 void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col));
 int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches));
 int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped));
-char_u *globpath __ARGS((char_u *path, char_u *file, int expand_options));
+int globpath __ARGS((char_u *path, char_u *file, garray_T *ga, int expand_options));
 void init_history __ARGS((void));
 int get_histtype __ARGS((char_u *name));
 void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep));
