updated for version 7.0051
diff --git a/src/os_unix.c b/src/os_unix.c
index d89636d..945092f 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -165,6 +165,7 @@
 #endif
 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
 
+static void catch_int_signal __ARGS((void));
 static void set_signals __ARGS((void));
 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
 #ifndef __EMX__
@@ -175,6 +176,14 @@
 #ifndef NO_EXPANDPATH
 static int	pstrcmp __ARGS((const void *, const void *));
 static int	unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags));
+# if defined(MACOS_X) && defined(FEAT_MBYTE)
+extern char_u	*mac_precompose_path __ARGS((char_u *decompPath, size_t decompLen, size_t *precompLen));
+# endif
+#endif
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+extern void	mac_conv_init __ARGS((void));
+extern void	mac_conv_cleanup __ARGS((void));
 #endif
 
 #ifndef __EMX__
@@ -1083,6 +1092,10 @@
 
     out_flush();
     set_signals();
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+    mac_conv_init();
+#endif
 }
 
     static void
@@ -1113,11 +1126,8 @@
     signal(SIGPIPE, SIG_IGN);
 #endif
 
-    /*
-     * We want to catch CTRL-C (only works while in Cooked mode).
-     */
 #ifdef SIGINT
-    signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+    catch_int_signal();
 #endif
 
     /*
@@ -1149,6 +1159,17 @@
 #endif
 }
 
+#if defined(SIGINT) || defined(PROTO)
+/*
+ * Catch CTRL-C (only works while in Cooked mode).
+ */
+    static void
+catch_int_signal()
+{
+    signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+}
+#endif
+
     void
 reset_signals()
 {
@@ -2694,6 +2715,8 @@
     static void
 exit_scroll()
 {
+    if (silent_mode)
+	return;
     if (newline_on_exit || msg_didout)
     {
 	if (msg_use_printf())
@@ -2764,6 +2787,11 @@
     if (gui.in_use)
 	gui_exit(r);
 #endif
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+    mac_conv_cleanup();
+#endif
+
 #ifdef __QNX__
     /* A core dump won't be created if the signal handler
      * doesn't return, so we can't call exit() */
@@ -3282,6 +3310,27 @@
     /* Nothing to do. */
 }
 
+#ifndef USE_SYSTEM
+static void append_ga_line __ARGS((garray_T *gap));
+
+/*
+ * Append the text in "gap" below the cursor line and clear "gap".
+ */
+    static void
+append_ga_line(gap)
+    garray_T	*gap;
+{
+    /* Remove trailing CR. */
+    if (gap->ga_len > 0
+	    && !curbuf->b_p_bin
+	    && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
+	--gap->ga_len;
+    ga_append(gap, NUL);
+    ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
+    gap->ga_len = 0;
+}
+#endif
+
     int
 mch_call_shell(cmd, options)
     char_u	*cmd;
@@ -3398,11 +3447,12 @@
 
 #else /* USE_SYSTEM */	    /* don't use system(), use fork()/exec() */
 
-#define EXEC_FAILED 122	    /* Exit code when shell didn't execute.  Don't use
-			       127, some shell use that already */
+# define EXEC_FAILED 122    /* Exit code when shell didn't execute.  Don't use
+			       127, some shells use that already */
 
     char_u	*newcmd = NULL;
     pid_t	pid;
+    pid_t	wpid = 0;
     pid_t	wait_pid = 0;
 # ifdef HAVE_UNION_WAIT
     union wait	status;
@@ -3415,19 +3465,19 @@
     int		i;
     char_u	*p;
     int		inquote;
-# ifdef FEAT_GUI
     int		pty_master_fd = -1;	    /* for pty's */
+# ifdef FEAT_GUI
     int		pty_slave_fd = -1;
     char	*tty_name;
+# endif
     int		fd_toshell[2];	    /* for pipes */
     int		fd_fromshell[2];
     int		pipe_error = FALSE;
-#  ifdef HAVE_SETENV
+# ifdef HAVE_SETENV
     char	envbuf[50];
-#  else
+# else
     static char	envbuf_Rows[20];
     static char	envbuf_Columns[20];
-#  endif
 # endif
     int		did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
 
@@ -3480,19 +3530,24 @@
     }
     argv[argc] = NULL;
 
-# ifdef FEAT_GUI
     /*
-     * For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
-     * executed command into the Vim window.  Or use a pipe.
+     * For the GUI, when writing the output into the buffer and when reading
+     * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
+     * of the executed command into the Vim window.  Or use a pipe.
      */
-    if (gui.in_use && show_shell_mess)
+    if ((options & (SHELL_READ|SHELL_WRITE))
+# ifdef FEAT_GUI
+	    || (gui.in_use && show_shell_mess)
+# endif
+		    )
     {
+# ifdef FEAT_GUI
 	/*
 	 * Try to open a master pty.
 	 * If this works, open the slave pty.
 	 * If the slave can't be opened, close the master pty.
 	 */
-	if (p_guipty)
+	if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
 	{
 	    pty_master_fd = OpenPTY(&tty_name);	    /* open pty */
 	    if (pty_master_fd >= 0 && ((pty_slave_fd =
@@ -3506,6 +3561,7 @@
 	 * If not opening a pty or it didn't work, try using pipes.
 	 */
 	if (pty_master_fd < 0)
+# endif
 	{
 	    pipe_error = (pipe(fd_toshell) < 0);
 	    if (!pipe_error)			    /* pipe create OK */
@@ -3526,8 +3582,6 @@
     }
 
     if (!pipe_error)			/* pty or pipe opened or not used */
-# endif
-
     {
 # ifdef __BEOS__
 	beos_cleanup_read_thread();
@@ -3535,15 +3589,20 @@
 	if ((pid = fork()) == -1)	/* maybe we should use vfork() */
 	{
 	    MSG_PUTS(_("\nCannot fork\n"));
+	    if ((options & (SHELL_READ|SHELL_WRITE))
 # ifdef FEAT_GUI
-	    if (gui.in_use && show_shell_mess)
+		|| (gui.in_use && show_shell_mess)
+# endif
+		    )
 	    {
+# ifdef FEAT_GUI
 		if (pty_master_fd >= 0)		/* close the pseudo tty */
 		{
 		    close(pty_master_fd);
 		    close(pty_slave_fd);
 		}
 		else				/* close the pipes */
+# endif
 		{
 		    close(fd_toshell[0]);
 		    close(fd_toshell[1]);
@@ -3551,7 +3610,6 @@
 		    close(fd_fromshell[1]);
 		}
 	    }
-# endif
 	}
 	else if (pid == 0)	/* child */
 	{
@@ -3593,13 +3651,17 @@
 		    close(fd);
 		}
 	    }
+	    else if ((options & (SHELL_READ|SHELL_WRITE))
 # ifdef FEAT_GUI
-	    else if (gui.in_use)
+		    || gui.in_use
+# endif
+		    )
 	    {
 
-#  ifdef HAVE_SETSID
+# ifdef HAVE_SETSID
 		(void)setsid();
-#  endif
+# endif
+# ifdef FEAT_GUI
 		/* push stream discipline modules */
 		if (options & SHELL_COOKED)
 		    SetupSlavePTY(pty_slave_fd);
@@ -3608,8 +3670,9 @@
 		 * unless run by root) */
 		ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
 #  endif
+# endif
 		/* Simulate to have a dumb terminal (for now) */
-#  ifdef HAVE_SETENV
+# ifdef HAVE_SETENV
 		setenv("TERM", "dumb", 1);
 		sprintf((char *)envbuf, "%ld", Rows);
 		setenv("ROWS", (char *)envbuf, 1);
@@ -3617,7 +3680,7 @@
 		setenv("LINES", (char *)envbuf, 1);
 		sprintf((char *)envbuf, "%ld", Columns);
 		setenv("COLUMNS", (char *)envbuf, 1);
-#  else
+# else
 		/*
 		 * Putenv does not copy the string, it has to remain valid.
 		 * Use a static array to avoid loosing allocated memory.
@@ -3629,8 +3692,9 @@
 		putenv(envbuf_Rows);
 		sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
 		putenv(envbuf_Columns);
-#  endif
+# endif
 
+# ifdef FEAT_GUI
 		if (pty_master_fd >= 0)
 		{
 		    close(pty_master_fd);   /* close master side of pty */
@@ -3646,6 +3710,7 @@
 		    close(pty_slave_fd);    /* has been dupped, close it now */
 		}
 		else
+# endif
 		{
 		    /* set up stdin for the child */
 		    close(fd_toshell[1]);
@@ -3664,7 +3729,7 @@
 		    dup(1);
 		}
 	    }
-# endif /* FEAT_GUI */
+
 	    /*
 	     * There is no type cast for the argv, because the type may be
 	     * different on different machines. This may cause a warning
@@ -3679,21 +3744,27 @@
 	{
 	    /*
 	     * While child is running, ignore terminating signals.
+	     * Do catch CTRL-C, so that "got_int" is set.
 	     */
 	    catch_signals(SIG_IGN, SIG_ERR);
-
-# ifdef FEAT_GUI
+	    catch_int_signal();
 
 	    /*
 	     * For the GUI we redirect stdin, stdout and stderr to our window.
+	     * This is also used to pipe stdin/stdout to/from the external
+	     * command.
 	     */
-	    if (gui.in_use && show_shell_mess)
+	    if ((options & (SHELL_READ|SHELL_WRITE))
+# ifdef FEAT_GUI
+		    || (gui.in_use && show_shell_mess)
+# endif
+	       )
 	    {
-#  define BUFLEN 100		/* length for buffer, pseudo tty limit is 128 */
+# define BUFLEN 100		/* length for buffer, pseudo tty limit is 128 */
 		char_u	    buffer[BUFLEN + 1];
-#  ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
 		int	    buffer_off = 0;	/* valid bytes in buffer[] */
-#  endif
+# endif
 		char_u	    ta_buf[BUFLEN + 1];	/* TypeAHead */
 		int	    ta_len = 0;		/* valid bytes in ta_buf[] */
 		int	    len;
@@ -3702,7 +3773,10 @@
 		int	    c;
 		int	    toshell_fd;
 		int	    fromshell_fd;
+		garray_T    ga;
+		int	    noread_cnt;
 
+# ifdef FEAT_GUI
 		if (pty_master_fd >= 0)
 		{
 		    close(pty_slave_fd);	/* close slave side of pty */
@@ -3710,6 +3784,7 @@
 		    toshell_fd = dup(pty_master_fd);
 		}
 		else
+# endif
 		{
 		    close(fd_toshell[0]);
 		    close(fd_fromshell[1]);
@@ -3738,6 +3813,76 @@
 		old_State = State;
 		State = EXTERNCMD;	/* don't redraw at window resize */
 
+		if (options & SHELL_WRITE && toshell_fd >= 0)
+		{
+		    /* Fork a process that will write the lines to the
+		     * external program. */
+		    if ((wpid = fork()) == -1)
+		    {
+			MSG_PUTS(_("\nCannot fork\n"));
+		    }
+		    else if (wpid == 0)
+		    {
+			linenr_T    lnum = curbuf->b_op_start.lnum;
+			int	    written = 0;
+			char_u	    *p = ml_get(lnum);
+			char_u	    *s;
+			size_t	    l;
+
+			/* child */
+			for (;;)
+			{
+			    l = STRLEN(p + written);
+			    if (l == 0)
+				len = 0;
+			    else if (p[written] == NL)
+				/* NL -> NUL translation */
+				len = write(toshell_fd, "", (size_t)1);
+			    else
+			    {
+				s = vim_strchr(p + written, NL);
+				len = write(toshell_fd, (char *)p + written,
+					   s == NULL ? l : s - (p + written));
+			    }
+			    if (len == l)
+			    {
+				/* Finished a line, add a NL, unless this line
+				 * should not have one. */
+				if (lnum != curbuf->b_op_end.lnum
+					|| !curbuf->b_p_bin
+					|| (lnum != write_no_eol_lnum
+					    && (lnum !=
+						    curbuf->b_ml.ml_line_count
+						    || curbuf->b_p_eol)))
+				    write(toshell_fd, "\n", (size_t)1);
+				++lnum;
+				if (lnum > curbuf->b_op_end.lnum)
+				{
+				    /* finished all the lines, close pipe */
+				    close(toshell_fd);
+				    toshell_fd = -1;
+				    break;
+				}
+				p = ml_get(lnum);
+				written = 0;
+			    }
+			    else if (len > 0)
+				written += len;
+			}
+			_exit(0);
+		    }
+		    else
+		    {
+			close(toshell_fd);
+			toshell_fd = -1;
+		    }
+		}
+
+		if (options & SHELL_READ)
+		    ga_init2(&ga, 1, BUFLEN);
+
+		noread_cnt = 0;
+
 		for (;;)
 		{
 		    /*
@@ -3745,12 +3890,15 @@
 		     * if there are any.  Don't do this if we are expanding
 		     * wild cards (would eat typeahead).  Don't get extra
 		     * characters when we already have one.
+		     * Don't read characters unless we didn't get output for a
+		     * while, avoids that ":r !ls" eats typeahead.
 		     */
 		    len = 0;
 		    if (!(options & SHELL_EXPAND)
 			    && (ta_len > 0
-				|| (len = ui_inchar(ta_buf, BUFLEN, 10L,
-								     0)) > 0))
+				|| (noread_cnt > 4
+				    && (len = ui_inchar(ta_buf,
+						       BUFLEN, 10L, 0)) > 0)))
 		    {
 			/*
 			 * For pipes:
@@ -3759,19 +3907,23 @@
 			 */
 			if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
 			{
-#  ifdef SIGINT
+# ifdef SIGINT
 			    /*
 			     * Send SIGINT to the child's group or all
 			     * processes in our group.
 			     */
 			    if (ta_buf[ta_len] == Ctrl_C
 					       || ta_buf[ta_len] == intr_char)
-#   ifdef HAVE_SETSID
+			    {
+#  ifdef HAVE_SETSID
 				kill(-pid, SIGINT);
-#   else
+#  else
 				kill(0, SIGINT);
-#   endif
 #  endif
+				if (wpid > 0)
+				    kill(wpid, SIGINT);
+			    }
+# endif
 			    if (pty_master_fd < 0 && toshell_fd >= 0
 					       && ta_buf[ta_len] == Ctrl_D)
 			    {
@@ -3799,10 +3951,10 @@
 			    }
 			    else if (ta_buf[i] == '\r')
 				ta_buf[i] = '\n';
-#  ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
 			    if (has_mbyte)
 				i += (*mb_ptr2len_check)(ta_buf + i) - 1;
-#  endif
+# endif
 			}
 
 			/*
@@ -3815,7 +3967,7 @@
 			    {
 				if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
 				    msg_putchar(ta_buf[i]);
-#  ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
 				else if (has_mbyte)
 				{
 				    int l = (*mb_ptr2len_check)(ta_buf + i);
@@ -3823,7 +3975,7 @@
 				    msg_outtrans_len(ta_buf + i, l);
 				    i += l - 1;
 				}
-#  endif
+# endif
 				else
 				    msg_outtrans_len(ta_buf + i, 1);
 			    }
@@ -3837,18 +3989,37 @@
 			 * Write the characters to the child, unless EOF has
 			 * been typed for pipes.  Write one character at a
 			 * time, to avoid loosing too much typeahead.
+			 * When writing buffer lines, drop the typed
+			 * characters (only check for CTRL-C).
 			 */
-			if (toshell_fd >= 0)
+			if (options & SHELL_WRITE)
+			    ta_len = 0;
+			else if (toshell_fd >= 0)
 			{
 			    len = write(toshell_fd, (char *)ta_buf, (size_t)1);
 			    if (len > 0)
 			    {
 				ta_len -= len;
 				mch_memmove(ta_buf, ta_buf + len, ta_len);
+				noread_cnt = 0;
 			    }
 			}
 		    }
 
+		    if (got_int)
+		    {
+			/* CTRL-C sends a signal to the child, we ignore it
+			 * ourselves */
+#  ifdef HAVE_SETSID
+			kill(-pid, SIGINT);
+#  else
+			kill(0, SIGINT);
+#  endif
+			if (wpid > 0)
+			    kill(wpid, SIGINT);
+			got_int = FALSE;
+		    }
+
 		    /*
 		     * Check if the child has any characters to be printed.
 		     * Read them and write them to our window.	Repeat this as
@@ -3858,24 +4029,42 @@
 		     * TODO: This should handle escape sequences, compatible
 		     * to some terminal (vt52?).
 		     */
+		    ++noread_cnt;
 		    while (RealWaitForChar(fromshell_fd, 10L, NULL))
 		    {
 			len = read(fromshell_fd, (char *)buffer
-#  ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
 				+ buffer_off, (size_t)(BUFLEN - buffer_off)
-#  else
+# else
 				, (size_t)BUFLEN
-#  endif
+# endif
 				);
 			if (len <= 0)		    /* end of file or error */
 			    goto finished;
-#  ifdef FEAT_MBYTE
-			len += buffer_off;
-			buffer[len] = NUL;
-			if (has_mbyte)
+
+			noread_cnt = 0;
+			if (options & SHELL_READ)
+			{
+			    /* Do NUL -> NL translation, append NL separated
+			     * lines to the current buffer. */
+			    for (i = 0; i < len; ++i)
+			    {
+				if (buffer[i] == NL)
+				    append_ga_line(&ga);
+				else if (buffer[i] == NUL)
+				    ga_append(&ga, NL);
+				else
+				    ga_append(&ga, buffer[i]);
+			    }
+			}
+# ifdef FEAT_MBYTE
+			else if (has_mbyte)
 			{
 			    int		l;
 
+			    len += buffer_off;
+			    buffer[len] = NUL;
+
 			    /* Check if the last character in buffer[] is
 			     * incomplete, keep these bytes for the next
 			     * round. */
@@ -3913,8 +4102,8 @@
 			    }
 			    buffer_off = 0;
 			}
+# endif /* FEAT_MBYTE */
 			else
-#  endif /* FEAT_MBYTE */
 			{
 			    buffer[len] = NUL;
 			    msg_puts(buffer);
@@ -3931,11 +4120,11 @@
 		     * Check if the child still exists, before checking for
 		     * typed characters (otherwise we would loose typeahead).
 		     */
-#  ifdef __NeXT__
+# ifdef __NeXT__
 		    wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
-#  else
+# else
 		    wait_pid = waitpid(pid, &status, WNOHANG);
-#  endif
+# endif
 		    if ((wait_pid == (pid_t)-1 && errno == ECHILD)
 			    || (wait_pid == pid && WIFEXITED(status)))
 		    {
@@ -3946,20 +4135,29 @@
 		}
 finished:
 		p_more = p_more_save;
+		if (options & SHELL_READ)
+		{
+		    if (ga.ga_len > 0)
+		    {
+			append_ga_line(&ga);
+			/* remember that the NL was missing */
+			write_no_eol_lnum = curwin->w_cursor.lnum;
+		    }
+		    else
+			write_no_eol_lnum = 0;
+		    ga_clear(&ga);
+		}
 
-#  ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
 		/*
 		 * Give all typeahead that wasn't used back to ui_inchar().
 		 */
 		if (ta_len)
 		    ui_inchar_undo(ta_buf, ta_len);
-#  endif
 		State = old_State;
 		if (toshell_fd >= 0)
 		    close(toshell_fd);
 		close(fromshell_fd);
 	    }
-# endif /* FEAT_GUI */
 
 	    /*
 	     * Wait until our child has exited.
@@ -3970,7 +4168,7 @@
 	     */
 	    while (wait_pid != pid)
 	    {
-#ifdef _THREAD_SAFE
+# ifdef _THREAD_SAFE
 		/* Ugly hack: when compiled with Python threads are probably
 		 * used, in which case wait() sometimes hangs for no obvious
 		 * reason.  Use waitpid() instead and loop (like the GUI). */
@@ -3985,9 +4183,9 @@
 		    mch_delay(10L, TRUE);
 		    continue;
 		}
-#else
+# else
 		wait_pid = wait(&status);
-#endif
+# endif
 		if (wait_pid <= 0
 # ifdef ECHILD
 			&& errno == ECHILD
@@ -3996,6 +4194,11 @@
 		    break;
 	    }
 
+	    /* Make sure the child that writes to the external program is
+	     * dead. */
+	    if (wpid > 0)
+		kill(wpid, SIGKILL);
+
 	    /*
 	     * Set to raw mode right now, otherwise a CTRL-C after
 	     * catch_signals() will kill Vim.
@@ -4656,7 +4859,19 @@
 		    if (*path_end != NUL)
 			backslash_halve(buf + len + 1);
 		    if (mch_getperm(buf) >= 0)	/* add existing file */
+		    {
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+			size_t precomp_len = STRLEN(buf)+1;
+			char_u *precomp_buf =
+			    mac_precompose_path(buf, precomp_len, &precomp_len);
+			if (precomp_buf)
+			{
+			    mch_memmove(buf, precomp_buf, precomp_len);
+			    vim_free(precomp_buf);
+			}
+#endif
 			addfile(gap, buf, flags);
+		    }
 		}
 	    }
 	}