updated for version 7.0075
diff --git a/src/config.mk.in b/src/config.mk.in
index d5103ec..e750202 100644
--- a/src/config.mk.in
+++ b/src/config.mk.in
@@ -93,6 +93,8 @@
 
 INSTALLVIMDIFF	= @dovimdiff@
 INSTALLGVIMDIFF	= @dogvimdiff@
+INSTALL_LANGS	= @INSTALL_LANGS@
+INSTALL_TOOL_LANGS	= @INSTALL_TOOL_LANGS@
 
 ### Line break character as octal number for "tr"
 NL		= @line_break@
diff --git a/src/eval.c b/src/eval.c
index 6b16cf9..7c9ccca 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1878,7 +1878,7 @@
 	    p = get_tv_string(tv);
 	    if (op != NULL && *op == '.')
 	    {
-		s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE);
+		s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE, FALSE);
 		if (s != NULL)
 		{
 		    p = tofree = concat_str(s, p);
@@ -4092,7 +4092,8 @@
 		if (evaluate)
 		{
 		    rettv->v_type = VAR_STRING;
-		    rettv->vval.v_string = get_reg_contents(**arg, FALSE);
+		    rettv->vval.v_string = get_reg_contents(**arg,
+								FALSE, FALSE);
 		}
 		if (**arg != NUL)
 		    ++*arg;
@@ -6158,7 +6159,7 @@
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
     {"getqflist",	0, 0, f_getqflist},
-    {"getreg",		0, 1, f_getreg},
+    {"getreg",		0, 2, f_getreg},
     {"getregtype",	0, 1, f_getregtype},
     {"getwinposx",	0, 0, f_getwinposx},
     {"getwinposy",	0, 0, f_getwinposy},
@@ -6239,7 +6240,7 @@
     {"setwinvar",	3, 3, f_setwinvar},
     {"simplify",	1, 1, f_simplify},
     {"sort",		1, 2, f_sort},
-    {"split",		1, 2, f_split},
+    {"split",		1, 3, f_split},
 #ifdef HAVE_STRFTIME
     {"strftime",	1, 2, f_strftime},
 #endif
@@ -8970,9 +8971,14 @@
 {
     char_u	*strregname;
     int		regname;
+    int		arg2 = FALSE;
 
     if (argvars[0].v_type != VAR_UNKNOWN)
+    {
 	strregname = get_tv_string(&argvars[0]);
+	if (argvars[1].v_type != VAR_UNKNOWN)
+	    arg2 = get_tv_number(&argvars[1]);
+    }
     else
 	strregname = vimvars[VV_REG].vv_str;
     regname = (strregname == NULL ? '"' : *strregname);
@@ -8980,7 +8986,7 @@
 	regname = '"';
 
     rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = get_reg_contents(regname, TRUE);
+    rettv->vval.v_string = get_reg_contents(regname, TRUE, arg2);
 }
 
 /*
@@ -12345,20 +12351,60 @@
 {
     linenr_T	lnum;
     char_u	*line;
+    list_T	*l = NULL;
+    listitem_T	*li = NULL;
+    long	added = 0;
+    linenr_T	lcount = curbuf->b_ml.ml_line_count;
 
-    lnum = get_tv_lnum(argvars);
-    line = get_tv_string(&argvars[1]);
-    rettv->vval.v_number = 1;		/* FAIL is default */
-
-    if (lnum >= 1
-	    && lnum <= curbuf->b_ml.ml_line_count
-	    && u_savesub(lnum) == OK
-	    && ml_replace(lnum, line, TRUE) == OK)
+    lnum = get_tv_lnum(&argvars[0]);
+    if (argvars[1].v_type == VAR_LIST)
     {
-	changed_bytes(lnum, 0);
-	check_cursor_col();
-	rettv->vval.v_number = 0;
+	l = argvars[1].vval.v_list;
+	li = l->lv_first;
     }
+    else
+	line = get_tv_string(&argvars[1]);
+
+    rettv->vval.v_number = 0;		/* OK */
+    for (;;)
+    {
+	if (l != NULL)
+	{
+	    /* list argument, get next string */
+	    if (li == NULL)
+		break;
+	    line = get_tv_string(&li->li_tv);
+	    li = li->li_next;
+	}
+
+	rettv->vval.v_number = 1;	/* FAIL */
+	if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
+	    break;
+	if (lnum <= curbuf->b_ml.ml_line_count)
+	{
+	    /* existing line, replace it */
+	    if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
+	    {
+		changed_bytes(lnum, 0);
+		check_cursor_col();
+		rettv->vval.v_number = 0;	/* OK */
+	    }
+	}
+	else if (added > 0 || u_save(lnum - 1, lnum) == OK)
+	{
+	    /* lnum is one past the last line, append the line */
+	    ++added;
+	    if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
+		rettv->vval.v_number = 0;	/* OK */
+	}
+
+	if (l == NULL)			/* only one string argument */
+	    break;
+	++lnum;
+    }
+
+    if (added > 0)
+	appended_lines_mark(lcount, added);
 }
 
 /*
@@ -12695,7 +12741,7 @@
 {
     char_u	*str;
     char_u	*end;
-    char_u	*pat;
+    char_u	*pat = NULL;
     regmatch_T	regmatch;
     char_u	patbuf[NUMBUFLEN];
     char_u	*save_cpo;
@@ -12703,16 +12749,21 @@
     listitem_T	*ni;
     list_T	*l;
     colnr_T	col = 0;
+    int		keepempty = FALSE;
 
     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
     save_cpo = p_cpo;
     p_cpo = (char_u *)"";
 
     str = get_tv_string(&argvars[0]);
-    if (argvars[1].v_type == VAR_UNKNOWN)
-	pat = (char_u *)"[\\x01- ]\\+";
-    else
+    if (argvars[1].v_type != VAR_UNKNOWN)
+    {
 	pat = get_tv_string_buf(&argvars[1], patbuf);
+	if (argvars[2].v_type != VAR_UNKNOWN)
+	    keepempty = get_tv_number(&argvars[2]);
+    }
+    if (pat == NULL || *pat == NUL)
+	pat = (char_u *)"[\\x01- ]\\+";
 
     l = list_alloc();
     if (l == NULL)
@@ -12725,14 +12776,17 @@
     if (regmatch.regprog != NULL)
     {
 	regmatch.rm_ic = FALSE;
-	while (*str != NUL)
+	while (*str != NUL || keepempty)
 	{
-	    match = vim_regexec_nl(&regmatch, str, col);
+	    if (*str == NUL)
+		match = FALSE;	/* empty item at the end */
+	    else
+		match = vim_regexec_nl(&regmatch, str, col);
 	    if (match)
 		end = regmatch.startp[0];
 	    else
 		end = str + STRLEN(str);
-	    if (end > str)
+	    if (keepempty || end > str || (l->lv_len > 0 && *str != NUL))
 	    {
 		ni = listitem_alloc();
 		if (ni == NULL)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 46a30c1..20bba1c 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -261,6 +261,156 @@
     return len;
 }
 
+/* Buffer for one line used during sorting.  It's allocated to contain the
+ * longest line being sorted. */
+static char_u	*sortbuf;
+
+static int	sort_ic;		/* ignore case */
+
+static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare __ARGS((const void *s1, const void *s2));
+
+    static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare(s1, s2)
+    const void	*s1;
+    const void	*s2;
+{
+    lpos_T	l1 = *(lpos_T *)s1;
+    lpos_T	l2 = *(lpos_T *)s2;
+    char_u	*s;
+
+    /* We need to copy one line into "sortbuf", because there is no guarantee
+     * that the first pointer becomes invalid when obtaining the second one. */
+    STRCPY(sortbuf, ml_get(l1.lnum) + l1.col);
+    s = ml_get(l2.lnum) + l2.col;
+    return sort_ic ? STRICMP(sortbuf, s) : STRCMP(sortbuf, s);
+}
+
+/*
+ * ":sort".
+ */
+    void
+ex_sort(eap)
+    exarg_T	*eap;
+{
+    regmatch_T	regmatch;
+    int		len;
+    linenr_T	lnum;
+    long	maxlen = 0;
+    lpos_T	*nrs;
+    size_t	count = eap->line2 - eap->line1 + 1;
+    int		i;
+    char_u	*p;
+    char_u	*s;
+    int		unique = FALSE;
+    long	deleted;
+
+    if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
+	return;
+    sortbuf = NULL;
+    regmatch.regprog = NULL;
+    nrs = (lpos_T *)lalloc((long_u)(count * sizeof(lpos_T)), TRUE);
+    if (nrs == NULL)
+	goto theend;
+
+    for (p = eap->arg; *p != NUL; ++p)
+    {
+	if (vim_iswhite(*p))
+	    ;
+	else if (*p == 'i')
+	    sort_ic = TRUE;
+	else if (*p == 'u')
+	    unique = TRUE;
+	else if (!ASCII_ISALPHA(*p))
+	{
+	    s = skip_regexp(p + 1, *p, TRUE, NULL);
+	    if (*s != *p)
+	    {
+		EMSG(_(e_invalpat));
+		goto theend;
+	    }
+	    *s = NUL;
+	    regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
+	    if (regmatch.regprog == NULL)
+		goto theend;
+	    p = s + 1;
+	    regmatch.rm_ic = p_ic;
+	}
+	else
+	{
+	    EMSG2(_(e_invarg2), p);
+	    goto theend;
+	}
+    }
+
+    /*
+     * Make an array with all line numbers, so that we don't have to copy all
+     * the lines into allocated memory.
+     * Also get the longest line length.
+     */
+    for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
+    {
+	nrs[lnum - eap->line1].lnum = lnum;
+	nrs[lnum - eap->line1].col = 0;
+
+	s = ml_get(lnum);
+	if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0))
+	    nrs[lnum - eap->line1].col = regmatch.endp[0] - s;
+
+	len = STRLEN(s);
+	if (maxlen < len)
+	    maxlen = len;
+    }
+
+    sortbuf = alloc((unsigned)maxlen + 1);
+    if (sortbuf == NULL)
+	goto theend;
+
+    /* sort the array of line numbers */
+    qsort((void *)nrs, count, sizeof(lpos_T), sort_compare);
+
+    /* Insert the lines in the sorted order below the last one. */
+    lnum = eap->line2;
+    for (i = 0; i < count; ++i)
+    {
+	s = ml_get(nrs[eap->forceit ? count - i - 1 : i].lnum);
+	if (!unique || i == 0
+		|| (sort_ic ? STRICMP(s, sortbuf) : STRCMP(s, sortbuf)) != 0)
+	{
+	    if (ml_append(lnum++, s, (colnr_T)0, FALSE) == FAIL)
+		break;
+	    STRCPY(sortbuf, s);
+	}
+    }
+
+    /* delete the original lines if appending worked */
+    if (i == count)
+	for (i = 0; i < count; ++i)
+	    ml_delete(eap->line1, FALSE);
+    else
+	count = 0;
+
+    deleted = count - (lnum - eap->line2);
+    if (deleted > 0)
+	mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted);
+    else if (deleted < 0)
+	mark_adjust(eap->line2, MAXLNUM, -deleted, 0L);
+    changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
+    curwin->w_cursor.lnum = eap->line1;
+    beginline(BL_WHITE | BL_FIX);
+
+theend:
+    vim_free(nrs);
+    vim_free(sortbuf);
+    vim_free(regmatch.regprog);
+}
+
 /*
  * ":retab".
  */
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 8eada96..eb11fb9 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -753,6 +753,8 @@
 			RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
 EX(CMD_source,		"source",	ex_source,
 			BANG|FILE1|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_sort,		"sort",		ex_sort,
+			RANGE|DFLALL|WHOLEFOLD|BANG|EXTRA|NOTRLCOM|MODIFY),
 EX(CMD_split,		"split",	ex_splitview,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_sprevious,	"sprevious",	ex_previous,
diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro
index 50238bb..baa1233 100644
--- a/src/proto/ex_cmds.pro
+++ b/src/proto/ex_cmds.pro
@@ -1,6 +1,7 @@
 /* ex_cmds.c */
 void do_ascii __ARGS((exarg_T *eap));
 void ex_align __ARGS((exarg_T *eap));
+void ex_sort __ARGS((exarg_T *eap));
 void ex_retab __ARGS((exarg_T *eap));
 int do_move __ARGS((linenr_T line1, linenr_T line2, linenr_T dest));
 void ex_copy __ARGS((linenr_T line1, linenr_T line2, linenr_T n));