[59931] trunk/dports/editors

raimue at macports.org raimue at macports.org
Tue Oct 27 09:38:18 PDT 2009


Revision: 59931
          http://trac.macports.org/changeset/59931
Author:   raimue at macports.org
Date:     2009-10-27 09:38:15 -0700 (Tue, 27 Oct 2009)
Log Message:
-----------
editors/vim, editors/vim-app:
Add +shell variant, #21770

Modified Paths:
--------------
    trunk/dports/editors/vim/Portfile
    trunk/dports/editors/vim-app/Portfile

Added Paths:
-----------
    trunk/dports/editors/vim/files/patch-vimshell.diff
    trunk/dports/editors/vim-app/files/patch-vimshell.diff

Modified: trunk/dports/editors/vim/Portfile
===================================================================
--- trunk/dports/editors/vim/Portfile	2009-10-27 14:53:46 UTC (rev 59930)
+++ trunk/dports/editors/vim/Portfile	2009-10-27 16:38:15 UTC (rev 59931)
@@ -112,6 +112,11 @@
     configure.args-append --with-xim
 }
 
+variant shell description {Enables shell windows} {
+    # Patch taken from http://www.wana.at/vimshell/
+    patchfiles-append       patch-vimshell.diff
+}
+
 variant perl description {Enable Perl scripting} {
     configure.args-append   --enable-perlinterp
     depends_lib-append      path:bin/perl:perl5

Added: trunk/dports/editors/vim/files/patch-vimshell.diff
===================================================================
--- trunk/dports/editors/vim/files/patch-vimshell.diff	                        (rev 0)
+++ trunk/dports/editors/vim/files/patch-vimshell.diff	2009-10-27 16:38:15 UTC (rev 59931)
@@ -0,0 +1,4565 @@
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/README_vimshell.txt ./README_vimshell.txt
+--- ../vim72.orig/README_vimshell.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./README_vimshell.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,12 @@
++TESTING
++=======
++
++shell-read with poll(2)
++shell-read with select(2) - works
++compiling VIM without builtin terminals - only termcap or terminfo - works
++GUI-VIM ohne builtin_terms ?
++
++DOCUMENTATION
++=============
++
++See :help vimshell for documentation.
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/runtime/doc/vimshell.txt ./runtime/doc/vimshell.txt
+--- ../vim72.orig/runtime/doc/vimshell.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./runtime/doc/vimshell.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,93 @@
++*vimshell.txt*   For Vim version 7.0.  Last change: 2006 Sep 2
++
++
++		  VIM REFERENCE MANUAL    by Bram Moolenaar
++
++
++The VIM-Shell                                            *vimshell*
++
++1. What is VIM-Shell?
++
++The VIM-shell is a extension for VIM, a very popular programmer's editor for
++many platforms, written by Bram Moolenaar et al. VIM features split windows,
++and this patch makes it possible to start shells in those windows. It is only
++available for POSIX systems like Linux, FreeBSD, OpenBSD, NetBSD and MacOS X.
++I don't think the Windows-VIM needs such a patch, because I think the command
++line there isn't really popular.
++
++==============================================================================
++2. How to use the VIM-Shell
++
++2.1 General concept: ":vimshell"
++
++The whole VIM-Shell functionality is hidden behind one single command:
++:vimshell.
++
++:vimshell[!] [params] tries to close your active buffer and creates a new one.
++This behaves exactly the same as the :enew command (see :help enew im VIM for
++details). If you have local modifications to your buffer, the command will be
++aborted (but you can override this by adding a ! at the end, in this case the
++active buffer will be dismissed in any case). The window containing this empty
++buffer is then converted to a VIM-Shell.
++
++:vimshell
++
++starts a VIM-Shell in your current window. I strongly suggest you open a new
++window before doing that. By default, without any parameters, /bin/sh will be
++spawned.
++
++:vimshell bash
++
++When called with parameters, VIM-Shell passes these parameters verbatim to
++execvp when starting a shell. Your current $PATH will be searched for the
++command.
++
++:vimshell irssi -n anonymous -c vienna.irc.at
++
++starts the textmode IRC client "irssi" with the abovementioned parameters.
++
++:vimshell mutt
++
++Never lose track of your e-mails while working in VIM!
++
++When you exit such a shell, or the program running in it terminates, the
++buffer will be converted back to a normal, empty VIM-buffer. The window will
++not be closed.
++
++2.2 Navigation
++
++When the currently active window is a VIM-Shell, every character entered gets
++routed to the shell, and no mapping expansion takes place. VIM doesn't get any
++notice of the characters that you type in a VIM-Shell.
++
++The big exception is Ctrl_W, which is passed through to VIM, so you can close
++the VIM-shell (Ctrl_W + c), change to another window, resize the window, etc.
++Key mappings
++
++Because I feel that opening up a window and then typing :vimshell is a bit
++cumbersome, I suggest you use the following key mappings in your .vimrc:
++
++	" VIM-Shell
++	" Ctrl_W e opens up a vimshell in a horizontally split window
++	" Ctrl_W E opens up a vimshell in a vertically split window
++	" The shell window will be auto closed after termination
++	nmap <C-W>e :new \| vimshell bash<CR>
++	nmap <C-W>E :vnew \| vimshell bash<CR>
++
++Just hitting Ctrl_W and e to drop a shell window in your VIM session is
++really, really comfortable :-)
++
++This is a small introduction on how to use the new features in your
++VIM-Shell-enabled VIM.
++
++==============================================================================
++3. Authorship
++
++The VIM-Shell was written in 2004, 2005, 2006 by Thomas Wana <thomas at wana.at>.
++Homepage: http://www.wana.at/vimshell/
++
++The VIM-Shell is published under the GNU GPL license (which is compatible with
++the VIM license). The copyright remains by the author.
++
++==============================================================================
++ vim:tw=78:ts=8:ft=help:norl:
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/Makefile ./src/Makefile
+--- ../vim72.orig/src/Makefile	2009-10-02 13:39:24.000000000 +0100
++++ ./src/Makefile	2009-10-02 13:39:57.000000000 +0100
+@@ -841,7 +841,6 @@
+ ###	 For LynxOS 3.1.0, tested on PC
+ #EXTRA_LIBS= -lXext -lSM -lICE -lnetinet -lXmu
+ 
+-
+ ### (V)  For CX/UX 6.2	(on Harris/Concurrent NightHawk 4800, 5800). Remove
+ ###	 -Qtarget if only in a 5800 environment.  (Kipp E. Howard)
+ #CFLAGS = -O -Qtarget=m88110compat
+@@ -1291,7 +1290,6 @@
+ # Use this for cproto 3 patchlevel 7 or above (use "cproto -V" to check):
+ PROTO_FLAGS = -m -M__ARGS -d -E"$(CPP)" $(NO_ATTR)
+ 
+-
+ ################################################
+ ##   no changes required below this line      ##
+ ################################################
+@@ -1410,6 +1408,8 @@
+ 	auto/pathdef.c \
+ 	popupmnu.c \
+ 	quickfix.c \
++	vim_shell.c \
++	terminal.c \
+ 	regexp.c \
+ 	screen.c \
+ 	search.c \
+@@ -1482,6 +1482,8 @@
+ 	objects/pathdef.o \
+ 	objects/popupmnu.o \
+ 	objects/quickfix.o \
++	objects/vim_shell.o \
++	objects/terminal.o \
+ 	objects/regexp.o \
+ 	objects/screen.o \
+ 	objects/search.o \
+@@ -2536,6 +2538,12 @@
+ objects/quickfix.o: quickfix.c
+ 	$(CCC) -o $@ quickfix.c
+ 
++objects/vim_shell.o: vim_shell.c
++	$(CCC) -o $@ vim_shell.c
++
++objects/terminal.o: terminal.c
++	$(CCC) -o $@ terminal.c
++
+ objects/regexp.o: regexp.c
+ 	$(CCC) -o $@ regexp.c
+ 
+@@ -2803,6 +2811,8 @@
+   auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
+   regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
+   globals.h farsi.h arabic.h
++objects/terminal.o: terminal.c vim_shell.h
++objects/vim_shell.o: vim_shell.c vim_shell.h
+ objects/regexp.o: regexp.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+   ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+   gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/auto/configure ./src/auto/configure
+--- ../vim72.orig/src/auto/configure	2009-10-02 13:39:25.000000000 +0100
++++ ./src/auto/configure	2009-10-02 13:39:57.000000000 +0100
+@@ -17145,6 +17145,269 @@
+ fi
+ 
+ 
++if test "$(uname)" = "Darwin"; then
++      LIBS="$LIBS"
++else
++      LIBS="$LIBS -lutil"
++fi
++
++
++
++for ac_header in pty.h libutil.h stdint.h
++do
++as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++else
++  # Is the header compilable?
++echo "$as_me:$LINENO: checking $ac_header usability" >&5
++echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++$ac_includes_default
++#include <$ac_header>
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++  (eval $ac_compile) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; } &&
++	 { ac_try='test -s conftest.$ac_objext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  ac_header_compiler=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_header_compiler=no
++fi
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6
++
++# Is the header present?
++echo "$as_me:$LINENO: checking $ac_header presence" >&5
++echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#include <$ac_header>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } >/dev/null; then
++  if test -s conftest.err; then
++    ac_cpp_err=$ac_c_preproc_warn_flag
++    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
++  else
++    ac_cpp_err=
++  fi
++else
++  ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++  ac_header_preproc=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++  ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6
++
++# So?  What about this header?
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++  yes:no: )
++    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
++    ac_header_preproc=yes
++    ;;
++  no:yes:* )
++    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
++echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------------ ##
++## Report this to the AC_PACKAGE_NAME lists.  ##
++## ------------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
++esac
++echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  eval "$as_ac_Header=\$ac_header_preproc"
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++
++fi
++if test `eval echo '${'$as_ac_Header'}'` = yes; then
++  cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
++
++for ac_func in forkpty
++do
++as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
++echo "$as_me:$LINENO: checking for $ac_func" >&5
++echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
++if eval "test \"\${$as_ac_var+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
++   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
++#define $ac_func innocuous_$ac_func
++
++/* System header to define __stub macros and hopefully few prototypes,
++    which can conflict with char $ac_func (); below.
++    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++    <limits.h> exists even on freestanding compilers.  */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
++
++#undef $ac_func
++
++/* Override any gcc2 internal prototype to avoid an error.  */
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++/* We use char because int might match the return type of a gcc2
++   builtin and then its argument prototype would still apply.  */
++char $ac_func ();
++/* The GNU C library defines this for functions which it implements
++    to always fail with ENOSYS.  Some functions are actually named
++    something starting with __ and the normal name is an alias.  */
++#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
++choke me
++#else
++char (*f) () = $ac_func;
++#endif
++#ifdef __cplusplus
++}
++#endif
++
++int
++main ()
++{
++return f != $ac_func;
++  ;
++  return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++  (eval $ac_link) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; } &&
++	 { ac_try='test -s conftest$ac_exeext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  eval "$as_ac_var=yes"
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++eval "$as_ac_var=no"
++fi
++rm -f conftest.err conftest.$ac_objext \
++      conftest$ac_exeext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
++if test `eval echo '${'$as_ac_var'}'` = yes; then
++  cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++done
++
++if test $ac_cv_func_forkpty = no; then
++    { { echo "$as_me:$LINENO: error: vimshell needs forkpty - sorry." >&5
++echo "$as_me: error: vimshell needs forkpty - sorry." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++
+ ac_config_files="$ac_config_files auto/config.mk:config.mk.in"
+ 
+ cat >confcache <<\_ACEOF
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/buffer.c ./src/buffer.c
+--- ../vim72.orig/src/buffer.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/buffer.c	2009-10-02 13:39:57.000000000 +0100
+@@ -575,6 +575,17 @@
+ #ifdef FEAT_TCL
+     tcl_buffer_free(buf);
+ #endif
++#ifdef FEAT_VIMSHELL
++    if(buf->is_shell!=0)
++    {
++	/*
++	 * It is guaranteed that this buffer isn't connected to a
++	 * window anymore, or else we'd not come up here. So we can
++	 * savely scrap the shell here.
++	 */
++	vim_shell_delete(buf);
++    }
++#endif
+     u_blockfree(buf);		    /* free the memory allocated for undo */
+     ml_close(buf, TRUE);	    /* close and delete the memline/memfile */
+     buf->b_ml.ml_line_count = 0;    /* no lines in buffer */
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/colines.c ./src/colines.c
+--- ../vim72.orig/src/colines.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/colines.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,39 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <signal.h>
++#include <termios.h>
++#include <sys/types.h>
++#include <pty.h>
++
++void sigwinch(int arg)
++{
++	struct winsize ws;
++	printf("window size is now: ");
++
++	if(ioctl(0, TIOCGWINSZ, &ws)<0)
++	{
++		perror("ioctl");
++		return;
++	}
++	printf("rows = %d, cols = %d\n", ws.ws_row, ws.ws_col);
++}
++
++int main()
++{
++	struct sigaction sa;
++	sa.sa_handler=sigwinch;
++	sigemptyset(&sa.sa_mask);
++	sa.sa_flags=0;
++	if(sigaction(SIGWINCH, &sa, NULL)<0)
++	{
++		perror("sigaction");
++		return -1;
++	}
++	sigwinch(0);
++	while(1)
++	{
++		sleep(10);
++	}
++	return 0;
++}
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/config.h.in ./src/config.h.in
+--- ../vim72.orig/src/config.h.in	2009-10-02 13:39:24.000000000 +0100
++++ ./src/config.h.in	2009-10-02 13:39:57.000000000 +0100
+@@ -387,3 +387,8 @@
+ 
+ /* Define if you want XSMP interaction as well as vanilla swapfile safety */
+ #undef USE_XSMP_INTERACT
++
++/* VIMSHELL stuff */
++#undef HAVE_PTY_H
++#undef HAVE_LIBUTIL_H
++#undef HAVE_STDINT_H
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/configure.in ./src/configure.in
+--- ../vim72.orig/src/configure.in	2009-10-02 13:39:25.000000000 +0100
++++ ./src/configure.in	2009-10-02 13:39:57.000000000 +0100
+@@ -3241,6 +3241,23 @@
+ fi
+ AC_SUBST(DEPEND_CFLAGS_FILTER)
+ 
++dnl ------------------------------------------------------------------
++dnl VIMSHELL configure thingies
++dnl needs -lutil, but not on MacOS X
++dnl The $MACOSX variable isn't set on the Mac I can use for testing, so we
++dnl have to use other means to find out if this is a Mac. uname for example.
++if test "$(uname)" = "Darwin"; then
++      LIBS="$LIBS"
++else
++      LIBS="$LIBS -lutil"
++fi
++AC_CHECK_HEADERS(pty.h libutil.h stdint.h)
++AC_CHECK_FUNCS(forkpty)
++if test $ac_cv_func_forkpty = no; then
++    AC_MSG_ERROR(vimshell needs forkpty - sorry.)
++fi
++dnl ------------------------------------------------------------------
++
+ dnl write output files
+ AC_OUTPUT(auto/config.mk:config.mk.in)
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/eval.c ./src/eval.c
+--- ../vim72.orig/src/eval.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/eval.c	2009-10-02 13:39:57.000000000 +0100
+@@ -11836,6 +11836,9 @@
+ #if defined(UNIX) && defined(FEAT_X11)
+ 	"X11",
+ #endif
++#ifdef FEAT_VIMSHELL
++	"vimshell",
++#endif
+ 	NULL
+     };
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_cmds.h ./src/ex_cmds.h
+--- ../vim72.orig/src/ex_cmds.h	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ex_cmds.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1007,6 +1007,10 @@
+ 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+ EX(CMD_view,		"view",		ex_edit,
+ 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
++#ifdef FEAT_VIMSHELL
++EX(CMD_vimshell,	"vimshell",	ex_vimshell,
++			EXTRA|BANG|TRLBAR|CMDWIN),
++#endif
+ EX(CMD_vimgrep,		"vimgrep",	ex_vimgrep,
+ 			RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+ EX(CMD_vimgrepadd,	"vimgrepadd",	ex_vimgrep,
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_docmd.c ./src/ex_docmd.c
+--- ../vim72.orig/src/ex_docmd.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ex_docmd.c	2009-10-02 13:39:57.000000000 +0100
+@@ -143,6 +143,7 @@
+ static void	ex_quit __ARGS((exarg_T *eap));
+ static void	ex_cquit __ARGS((exarg_T *eap));
+ static void	ex_quit_all __ARGS((exarg_T *eap));
++static void	ex_vimshell __ARGS((exarg_T *eap));
+ #ifdef FEAT_WINDOWS
+ static void	ex_close __ARGS((exarg_T *eap));
+ static void	ex_win_close __ARGS((int forceit, win_T *win, tabpage_T *tp));
+@@ -11109,3 +11110,115 @@
+     ml_clearmarked();	   /* clear rest of the marks */
+ }
+ #endif
++
++#ifdef FEAT_VIMSHELL
++/*
++ * ":vimshell": creates an empty buffer in the current window and starts a
++ * VIM-Shell inside.
++ * ":vimshellac": same as "vimshell" but closes the window after the shell
++ * terminated (ac = "auto-close"). This is useful for redefinitions of 'Man'
++ * etc.
++ */
++    static void
++ex_vimshell(eap)
++    exarg_T	*eap;
++{
++    unsigned char *argv[50], argidx, *p;
++    unsigned char cmdline[500];
++    char cmdbuf[50];
++
++    if(curbuf->is_shell!=0)
++    {
++	emsg("VIMSHELL: current buffer is already a shell!");
++	return;
++    }
++
++    snprintf(cmdbuf, sizeof(cmdbuf), ":enew%s", eap->forceit==TRUE ? "!" : "");
++
++    /*
++     * Do a ":enew" command to get a new buffer in the current window.
++     * Also assures that we don't throw away any unsaved changes the user
++     * made to the previous buffer.
++     */
++    did_emsg=FALSE;
++    if(do_cmdline_cmd(cmdbuf)==FAIL || did_emsg==TRUE)
++    {
++	return;
++    }
++
++    /*
++     * Set buffer read only (the user can't write into it anyway, but just
++     * to make sure. We want to be able to close the buffer without any
++     * problems any time).
++     */
++    curbuf->b_p_ro=TRUE;
++
++    /*
++     * Parse command line arguments. If none given, default to '/bin/sh'
++     */
++    snprintf(cmdline, sizeof(cmdline), "%s", eap->arg);
++    p=cmdline;
++    argidx=0;
++    if(!strcmp(p, ""))
++    {
++	argv[0]="/bin/sh";
++    }
++    else
++    {
++	argv[argidx]=p;
++	do
++	{
++	    if(*p==' ')
++	    {
++		argidx++;
++		if(argidx+1 >= sizeof(argv)/sizeof(argv[0]))
++		{
++		    /*
++		     * Too many command line arguments, drop out
++		     */
++		    emsg("VIMSHELL: too many command line arguments");
++		    return;
++		}
++
++		/*
++		 * Convert all ' ' to \0
++		 */
++		for(;*p==' ';p++)
++		    *p=0;
++		if(*p!=0)
++		{
++		    argv[argidx]=p;
++		}
++	    }
++	} while(*p++);
++    }
++    argv[++argidx]=NULL;
++
++    /*
++     * Convert the current buffer into a shell window.
++     */
++    curbuf->shell=(struct vim_shell_window *)vim_shell_new(W_WIDTH(curwin), curwin->w_height);
++    if(curbuf->shell==NULL)
++    {
++	EMSG2("VIMSHELL: error creating a new shell: %s", vim_shell_strerror());
++	return;
++    }
++    curbuf->is_shell=1;
++    curbuf->gtk_input_id=0;
++
++    /*
++     * start the shell
++     */
++    if(vim_shell_start(curbuf->shell, (char **)argv)<0)
++    {
++	EMSG2("VIMSHELL: error starting the shell: %s", vim_shell_strerror());
++
++	vim_shell_delete(curbuf);
++	return;
++    }
++
++    /*
++     * we're up and running.
++     */
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/feature.h ./src/feature.h
+--- ../vim72.orig/src/feature.h	2009-10-02 13:39:26.000000000 +0100
++++ ./src/feature.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1267,6 +1267,15 @@
+ #endif
+ 
+ /*
++ * The VIM-Shell. Only works on UNIX for now (more specifically,
++ * only Linux, *BSD and MacOS X, others not tested. Generally, if
++ * a system has a forkpty call, it should be working.)
++ */
++#if defined(FEAT_NORMAL) && (defined(UNIX) || defined(MACOS_X))
++#define FEAT_VIMSHELL
++#endif
++
++/*
+  * +autochdir		'autochdir' option.
+  */
+ #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/gui_gtk_x11.c ./src/gui_gtk_x11.c
+--- ../vim72.orig/src/gui_gtk_x11.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/gui_gtk_x11.c	2009-10-02 13:39:57.000000000 +0100
+@@ -6470,6 +6470,65 @@
+ }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++/*
++ * VIM-Shell callback, called when a shell file descriptor has data
++ * available.
++ */
++    static void
++vimshell_request_cb(
++    gpointer	data,
++    gint	source_fd,
++    GdkInputCondition condition)
++{
++    buf_T *buf;
++    int did_redraw=0;
++
++    /*
++     * Search the right buffer.
++     */
++    for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++    {
++	if(buf->is_shell!=0 && buf->shell && buf->shell->fd_master==source_fd)
++	{
++	    int r;
++
++	    r=vim_shell_do_read_lowlevel(buf);
++	    if(r>did_redraw)
++		did_redraw=r;
++
++	    if(r==1 && updating_screen==FALSE)
++		redraw_buf_later(buf, VALID);
++	    else if(r==2)
++	    {
++		/*
++		 * Shell died, so remove the GTK-input
++		 * VIMSHELL TODO: this should really be happening inside vim_shell_delete
++		 */
++		gdk_input_remove(buf->gtk_input_id);
++		buf->gtk_input_id=0;
++		if(updating_screen==FALSE)
++		    redraw_buf_later(buf, CLEAR);
++	    }
++	}
++    }
++
++    if(updating_screen==FALSE)
++    {
++	if(did_redraw==1)
++	    update_screen(VALID);
++	else if(did_redraw==2)
++	{
++	    update_screen(CLEAR);
++	    out_flush();
++	}
++    }
++
++    if (gtk_main_level() > 0)
++	gtk_main_quit();
++}
++#endif
++
+ /*
+  * GUI input routine called by gui_wait_for_chars().  Waits for a character
+  * from the keyboard.
+@@ -6506,6 +6565,23 @@
+     }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    /*
++     * Go through all buffers, see if we have to add not yet added inputs
++     */
++    {
++	buf_T *buf;
++	for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++	{
++	    if(buf->is_shell!=0 && buf->shell && buf->gtk_input_id==0)
++	    {
++		buf->gtk_input_id=gdk_input_add(buf->shell->fd_master,
++			GDK_INPUT_READ, vimshell_request_cb, NULL);
++	    }
++	}
++    }
++#endif
++
+     timed_out = FALSE;
+ 
+     /* this timeout makes sure that we will return if no characters arrived in
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/main.c ./src/main.c
+--- ../vim72.orig/src/main.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/main.c	2009-10-02 13:39:57.000000000 +0100
+@@ -180,6 +180,10 @@
+      */
+     mch_early_init();
+ 
++#ifdef FEAT_VIMSHELL
++    vim_shell_init();
++#endif
++
+     /* Many variables are in "params" so that we can pass them to invoked
+      * functions without a lot of arguments.  "argc" and "argv" are also
+      * copied, so that they can be changed. */
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/move.c ./src/move.c
+--- ../vim72.orig/src/move.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/move.c	2009-10-02 13:39:57.000000000 +0100
+@@ -675,6 +675,14 @@
+     void
+ validate_cursor()
+ {
++#ifdef FEAT_VIMSHELL
++    /*
++     * The vimshell repositions its artificial cursor in vim_shell_redraw. Don't do the
++     * checks below.
++     */
++    if(curwin->w_buffer && curwin->w_buffer->is_shell!=0)
++	return;
++#endif
+     check_cursor_moved(curwin);
+     if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
+ 	curs_columns(TRUE);
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/normal.c ./src/normal.c
+--- ../vim72.orig/src/normal.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/normal.c	2009-10-02 13:41:52.000000000 +0100
+@@ -646,11 +646,50 @@
+     dont_scroll = FALSE;	/* allow scrolling here */
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    /*
++     * We reroute ALL characters to the shell, EXCEPT Ctrl_W, so all
++     * Window-Commands should still be working (not unimportant, think of
++     * leaving the window ...)
++     * VIMSHELL TODO: what about mouse commands, GUI commands, etc
++     */
++    if(curbuf->is_shell)
++    {
++      no_mapping++;
++      allow_keys++;
++      c = safe_vgetc();
++      no_mapping--;
++      allow_keys--;
++
++      if(curbuf->is_shell && c!=Ctrl_W)
++      {
++          if(vim_shell_write(curbuf->shell, c)<0)
++          {
++                  /*
++                   * The shell died, clean up
++                   */
++                  vim_shell_delete(curbuf);
++                  curbuf->is_shell=0;
++                  curbuf->b_p_ro=FALSE;
++
++                  redraw_later(CLEAR);
++                  update_screen(CLEAR);
++          }
++          return;
++      }
++    }
++    else
++    {
++      c = safe_vgetc();
++      LANGMAP_ADJUST(c, TRUE);
++    }
++#else
+     /*
+      * Get the command character from the user.
+      */
+     c = safe_vgetc();
+     LANGMAP_ADJUST(c, TRUE);
++#endif
+ 
+ #ifdef FEAT_VISUAL
+     /*
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/os_unix.c ./src/os_unix.c
+--- ../vim72.orig/src/os_unix.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/os_unix.c	2009-10-02 13:39:57.000000000 +0100
+@@ -4809,7 +4809,7 @@
+ # endif
+ #endif
+ #ifndef HAVE_SELECT
+-	struct pollfd   fds[5];
++	struct pollfd   fds[50];
+ 	int		nfd;
+ # ifdef FEAT_XCLIPBOARD
+ 	int		xterm_idx = -1;
+@@ -4820,6 +4820,15 @@
+ # ifdef USE_XSMP
+ 	int		xsmp_idx = -1;
+ # endif
++# ifdef FEAT_VIMSHELL
++	struct
++	{
++	    int idx;
++	    struct vim_shell_window *shell;
++	    buf_T *buffer;
++	}		vimshell_idxs[50];
++	int		vimshell_idx_cnt;
++# endif
+ 	int		towait = (int)msec;
+ 
+ # ifdef FEAT_MZSCHEME
+@@ -4870,6 +4879,49 @@
+ 	    nfd++;
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * Loop through all windows and see if they contain vimshells.
++	     * If yes, add the master-fd to the list of polled fds.
++	     */
++	    memset(vimshell_idxs, 0, sizeof(vimshell_idxs));
++	    vimshell_idx_cnt=0;
++	    for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
++	    {
++		buf_T *buf;
++		if(buf->is_shell!=0)
++		{
++		    vimshell_idxs[vimshell_idx_count].idx=nfd;
++		    vimshell_idxs[vimshell_idx_count].buffer=buf;
++		    vimshell_idxs[vimshell_idx_count].shell=buf->shell;
++
++		    /*
++		     * We will first run out of fds before we run out of
++		     * vimshell_idxs-slots, so no check here.
++		     */
++		    vimshell_idx_count++;
++
++		    if(buf->shell==NULL)
++		    {
++			// VIMSHELL TODO: error message here
++			continue;
++		    }
++		    fds[nfd].fd = buf->shell->fd_master;
++		    fds[nfd].events = POLLIN;
++		    nfd++;
++		    if(nfd>=sizeof(fds)/sizeof(fds[0]))
++		    {
++			/*
++			 * no more fds-slots left! aieeee
++			 */
++			// VIMSHELL TODO: issue a warning here or something
++			break;
++		    }
++		}
++	    }
++	}
++# endif
+ 
+ 	ret = poll(fds, nfd, towait);
+ # ifdef FEAT_MZSCHEME
+@@ -4923,6 +4975,38 @@
+ 		finished = FALSE;	/* Try again */
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++#error "VIMSHELL: probably doesn't work with poll(), never tested, sorry (use select)"
++	{
++	    /*
++	     * See if any of the shell's fds have a read request ready
++	     * If yes, call the shell's read handler.
++	     */
++	    int i;
++	    int did_redraw=0;
++	    for(i=0;i<vimshell_idx_cnt;i++)
++	    {
++		if(fds[vimshell_idxs[i].idx].revents & POLLIN)
++		{
++		    if(vim_shell_read(vimshell_idxs[i].shell)<0)
++		    {
++			// VIMSHELL TODO: handle error here
++			continue;
++		    }
++
++		    redraw_buf_later(vimshell_idxs[i].buffer, NOT_VALID);
++
++		    did_redraw=1;
++		}
++		// VIMSHELL TODO: handle POLLHUP here too (shell terminated)
++	    }
++	    if(did_redraw==1)
++	    {
++		update_screen(NOT_VALID);
++		out_flush();
++	    }
++	}
++# endif
+ 
+ 
+ #else /* HAVE_SELECT */
+@@ -5004,6 +5088,25 @@
+ 		maxfd = xsmp_icefd;
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * Loop through all windows and see if they contain vimshells.
++	     * If yes, add the master-fd to the list of fds
++	     */
++	    win_T *win;
++	    FOR_ALL_WINDOWS(win)
++	    {
++		buf_T *buf=win->w_buffer;
++		if(buf->is_shell!=0)
++		{
++		    FD_SET(buf->shell->fd_master, &rfds);
++		    if (maxfd < buf->shell->fd_master)
++			maxfd = buf->shell->fd_master;
++		}
++	    }
++	}
++# endif
+ 
+ # ifdef OLD_VMS
+ 	/* Old VMS as v6.2 and older have broken select(). It waits more than
+@@ -5081,6 +5184,16 @@
+ 	    }
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	if((maxfd=vim_shell_do_read_select(rfds))!=0)
++	{
++	    ret-=maxfd;
++#  ifdef MAY_LOOP
++	    if (ret == 0)
++		finished = FALSE;   /* keep going if event was only one */
++#  endif
++	}
++# endif
+ 
+ #endif /* HAVE_SELECT */
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/screen.c ./src/screen.c
+--- ../vim72.orig/src/screen.c	2009-10-02 13:39:26.000000000 +0100
++++ ./src/screen.c	2009-10-02 13:39:57.000000000 +0100
+@@ -91,13 +91,21 @@
+ /*
+  * The attributes that are actually active for writing to the screen.
+  */
++#ifdef FEAT_VIMSHELL
++int		screen_attr = 0;
++#else
+ static int	screen_attr = 0;
++#endif
+ 
+ /*
+  * Positioning the cursor is reduced by remembering the last position.
+  * Mostly used by windgoto() and screen_char().
+  */
++#ifdef FEAT_VIMSHELL
++int		screen_cur_row, screen_cur_col;	/* last known cursor position */
++#else
+ static int	screen_cur_row, screen_cur_col;	/* last known cursor position */
++#endif
+ 
+ #ifdef FEAT_SEARCH_EXTRA
+ static match_T search_hl;	/* used for 'hlsearch' highlight matching */
+@@ -141,7 +149,11 @@
+ static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
+ static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
+ #endif
++#ifdef FEAT_VIMSHELL
++void screen_start_highlight __ARGS((int attr));
++#else
+ static void screen_start_highlight __ARGS((int attr));
++#endif
+ static void screen_char __ARGS((unsigned off, int row, int col));
+ #ifdef FEAT_MBYTE
+ static void screen_char_2 __ARGS((unsigned off, int row, int col));
+@@ -833,6 +845,7 @@
+     }
+ #endif
+ 
++
+ #ifdef FEAT_SEARCH_EXTRA
+     /* Setup for match and 'hlsearch' highlighting.  Disable any previous
+      * match */
+@@ -1477,6 +1490,7 @@
+     win_foldinfo.fi_level = 0;
+ #endif
+ 
++
+     /*
+      * Update all the window rows.
+      */
+@@ -1903,9 +1917,19 @@
+ 	else if (dollar_vcol == 0)
+ 	    wp->w_botline = lnum;
+ 
++#ifdef FEAT_VIMSHELL
++	/*
++	 * We don't want '~' to appear right in the middle of our shells ...
++	 */
++	if(wp->w_buffer->is_shell==0)
++	{
++#endif
+ 	/* make sure the rest of the screen is blank */
+ 	/* put '~'s on rows that aren't part of the file. */
+ 	win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_AT);
++#ifdef FEAT_VIMSHELL
++	}
++#endif
+     }
+ 
+     /* Reset the type of redrawing required, the window has been updated. */
+@@ -1953,6 +1977,18 @@
+     if (!got_int)
+ 	got_int = save_got_int;
+ #endif
++
++#ifdef FEAT_VIMSHELL
++    /*
++     * If this window contains a shell, redraw the shell.
++     */
++    if(wp->w_buffer->is_shell != 0)
++    {
++	wp->w_buffer->shell->force_redraw=(type>=NOT_VALID ? 1 : 0);
++	vim_shell_redraw(wp->w_buffer->shell, wp);
++	return;
++    }
++#endif
+ }
+ 
+ #ifdef FEAT_SIGNS
+@@ -6756,7 +6792,11 @@
+ }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++      void
++#else
+       static void
++#endif
+ screen_start_highlight(attr)
+       int	attr;
+ {
+@@ -6956,7 +6996,11 @@
+  * Put character ScreenLines["off"] on the screen at position "row" and "col",
+  * using the attributes from ScreenAttrs["off"].
+  */
++#ifdef FEAT_VIMSHELL
++    void
++#else
+     static void
++#endif
+ screen_char(off, row, col)
+     unsigned	off;
+     int		row;
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/structs.h ./src/structs.h
+--- ../vim72.orig/src/structs.h	2009-10-02 13:39:26.000000000 +0100
++++ ./src/structs.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1145,6 +1145,10 @@
+ 
+ typedef struct file_buffer buf_T;
+ 
++#ifdef FEAT_VIMSHELL
++struct vim_shell_window;
++#endif
++
+ struct file_buffer
+ {
+     memline_T	b_ml;		/* associated memline (also contains line
+@@ -1591,6 +1595,11 @@
+     int		b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    char	is_shell;                /* (flag) Is this buffer a shell? (0 = false) */
++    struct	vim_shell_window *shell; /* Pointer to the shell struct, or NULL */
++    int		gtk_input_id;            /* GTK-input id returned by gdk_input_add, only for GUI */
++#endif
+ };
+ 
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/syntax.c ./src/syntax.c
+--- ../vim72.orig/src/syntax.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/syntax.c	2009-10-02 13:39:57.000000000 +0100
+@@ -6005,6 +6005,10 @@
+ syntax_present(buf)
+     buf_T	*buf;
+ {
++#ifdef FEAT_VIMSHELL
++    if(buf->is_shell!=0)
++	return 0;
++#endif
+     return (buf->b_syn_patterns.ga_len != 0
+ 	    || buf->b_syn_clusters.ga_len != 0
+ 	    || buf->b_keywtab.ht_used > 0
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/terminal.c ./src/terminal.c
+--- ../vim72.orig/src/terminal.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/terminal.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,1933 @@
++/*
++ * terminal.c
++ *
++ * This is the screen-like terminal emulator; it is a better vt100 and supports the
++ * same commands that screen does (including color etc).
++ *
++ * The interface is vim_shell_terminal_input and vim_shell_terminal_output. These
++ * functions get characters from the shell (or from the user) and process them
++ * accordingly to the terminal rules (ESC sequences etc). They then work directly
++ * on the vim_shell-window-buffer, updating its contents.
++ *
++ * VIMSHELL TODO: *) don't scroll scroll region if cursor is outside
++ *                *) change the buffer name according to the window title
++ *                *) CSI (0x9B)
++ *                *) Get the ESC codes for switching charsets from terminfo/termcap
++ *                *) Origin mode
++ *                *) "erase with background color"
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ */
++
++static char *RCSID="$Id$";
++
++#include <string.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <errno.h>
++
++#include "vim.h"
++
++#ifdef FEAT_VIMSHELL
++#ifdef VIMSHELL_DEBUG
++#  define ESCDEBUG
++/*
++ * Really extreme logging
++ * Log *every* character we write to the shell
++ */
++//#  define VERBOSE
++#endif
++
++#ifdef ESCDEBUG
++#  define ESCDEBUGPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
++#else
++#  define ESCDEBUGPRINTF(a...)
++#endif
++
++#ifdef VERBOSE
++#  define VERBOSEPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
++#else
++#  define VERBOSEPRINTF(a...)
++#endif
++
++/*
++ * These are the VIM keynames.
++ */
++#define VIMSHELL_KEY_DOWN	K_DOWN
++#define VIMSHELL_KEY_UP		K_UP
++#define VIMSHELL_KEY_LEFT	K_LEFT
++#define VIMSHELL_KEY_RIGHT	K_RIGHT
++#define VIMSHELL_KEY_HOME	K_HOME
++#define VIMSHELL_KEY_BACKSPACE	K_BS
++#define VIMSHELL_KEY_F1		K_F1
++#define VIMSHELL_KEY_F2		K_F2
++#define VIMSHELL_KEY_F3		K_F3
++#define VIMSHELL_KEY_F4		K_F4
++#define VIMSHELL_KEY_F5		K_F5
++#define VIMSHELL_KEY_F6		K_F6
++#define VIMSHELL_KEY_F7		K_F7
++#define VIMSHELL_KEY_F8		K_F8
++#define VIMSHELL_KEY_F9		K_F9
++#define VIMSHELL_KEY_F10	K_F10
++#define VIMSHELL_KEY_F11	K_F11
++#define VIMSHELL_KEY_F12	K_F12
++#define VIMSHELL_KEY_DC		K_DEL
++#define VIMSHELL_KEY_END	K_END
++#define VIMSHELL_KEY_IC		K_INS
++#define VIMSHELL_KEY_NPAGE	K_PAGEDOWN
++#define VIMSHELL_KEY_PPAGE	K_PAGEUP
++#define VIMSHELL_KEY_K0		K_K0
++#define VIMSHELL_KEY_K1		K_K1
++#define VIMSHELL_KEY_K2		K_K2
++#define VIMSHELL_KEY_K3		K_K3
++#define VIMSHELL_KEY_K4		K_K4
++#define VIMSHELL_KEY_K5		K_K5
++#define VIMSHELL_KEY_K6		K_K6
++#define VIMSHELL_KEY_K7		K_K7
++#define VIMSHELL_KEY_K8		K_K8
++#define VIMSHELL_KEY_K9		K_K9
++#define VIMSHELL_KEY_KPLUS	K_KPLUS
++#define VIMSHELL_KEY_KMINUS	K_KMINUS
++#define VIMSHELL_KEY_KDIVIDE	K_KDIVIDE
++#define VIMSHELL_KEY_KMULTIPLY	K_KMULTIPLY
++#define VIMSHELL_KEY_KENTER	K_KENTER
++#define VIMSHELL_KEY_KPOINT	K_KPOINT
++
++static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20]);
++static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20]);
++static int terminal_flush_output(struct vim_shell_window *shell);
++
++/*
++ * A routine that prints a buffer in 'hexdump -C'-style via printf
++ */
++static void hexdump(FILE *fp, unsigned char *buffer, long len)
++{
++	unsigned long pos=0;
++
++	while(len>0)
++	{
++		int i;
++		fprintf(fp,"%08x  ",(unsigned int)pos);
++		for(i=0;i<16 && i<len;i++)
++		{
++			fprintf(fp,"%02x ",buffer[pos+i]);
++			if(i==7 || i==15)
++				fprintf(fp," ");
++		}
++		fprintf(fp,"|");
++		for(i=0;i<16 && i<len;i++)
++		{
++			unsigned char c=buffer[pos+i];
++			if(isprint(c))
++			{
++				fprintf(fp,"%c",c);
++			}
++			else
++			{
++				fprintf(fp,".");
++			}
++		}
++		fprintf(fp,"|\n");
++		len-=16;
++		pos+=16;
++	}
++}
++
++/*
++ * Tabulation Clear (TBC)
++ *
++ * 9/11 6/7
++ * CSI   g
++ *
++ * 	Clears a horizontal tab stop at cursor position.
++ *
++ * 	9/11 3/0 6/7
++ * 	CSI   0   g
++ *
++ * 		Clears a horizontal tab stop at cursor position.
++ *
++ * 		9/11 3/3 6/7
++ * 		CSI   3   g
++ *
++ * 			Clears all horizontal tab stops.
++ */
++static void terminal_TBC(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int param;
++
++	if(argc==0)
++	{
++		param=0;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF("%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	// VIMSHELL TODO: DRINGEND! wenn argc==0 dann ist argv[0] NULL und wir crashen
++	// hier ... passiert in einigen Funktionen, dank copy+paste! Super gmocht Tom!
++	param=strtol(argv[0], NULL, 10);
++	switch(param)
++	{
++		case 0:
++			shell->tabline[shell->cursor_x]=0;
++			break;
++		case 3:
++			memset(shell->tabline, 0, shell->size_x);
++			break;
++		default:
++			ESCDEBUGPRINTF( "%s: sequence error (2)\n", __FUNCTION__);
++	}
++}
++
++/*
++ * CUB . Cursor Backward . Host to VT100 and VT100 to Host
++ * ESC [ Pn D 	default value: 1
++ *
++ * The CUB sequence moves the active position to the left. The distance moved is
++ * determined by the parameter. If the parameter value is zero or one, the active
++ * position is moved one position to the left. If the parameter value is n, the active
++ * position is moved n positions to the left. If an attempt is made to move the cursor
++ * to the left of the left margin, the cursor stops at the left margin. Editor Function
++ */
++static void terminal_CUB(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	if(shell->cursor_x<distance)
++		shell->cursor_x=0;
++	else
++		shell->cursor_x-=distance;
++}
++
++/*
++ * CUU . Cursor Up . Host to VT100 and VT100 to Host
++ * ESC [ Pn A 	default value: 1
++ *
++ * Moves the active position upward without altering the column position. The
++ * number of lines moved is determined by the parameter. A parameter value of zero
++ * or one moves the active position one line upward. A parameter value of n moves the
++ * active position n lines upward. If an attempt is made to move the cursor above the
++ * top margin, the cursor stops at the top margin. Editor Function
++ */
++static void terminal_CUU(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	if((int)shell->cursor_y-distance<shell->scroll_top_margin)
++		shell->cursor_y=shell->scroll_top_margin;
++	else
++		shell->cursor_y-=distance;
++}
++
++
++/*
++ * CUD . Cursor Down . Host to VT100 and VT100 to Host
++ * ESC [ Pn B 	default value: 1
++ *
++ * The CUD sequence moves the active position downward without altering the column
++ * position. The number of lines moved is determined by the parameter. If the parameter
++ * value is zero or one, the active position is moved one line downward. If the parameter
++ * value is n, the active position is moved n lines downward. In an attempt is made to
++ * move the cursor below the bottom margin, the cursor stops at the bottom margin. Editor Function
++ */
++static void terminal_CUD(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	shell->cursor_y+=distance;
++	if(shell->cursor_y+1>=shell->scroll_bottom_margin)
++		shell->cursor_y=shell->scroll_bottom_margin;
++}
++
++/*
++ * CUF . Cursor Forward . Host to VT100 and VT100 to Host
++ * ESC [ Pn C 	default value: 1
++ *
++ * The CUF sequence moves the active position to the right. The distance moved is
++ * determined by the parameter. A parameter value of zero or one moves the active
++ * position one position to the right. A parameter value of n moves the active position n
++ * positions to the right. If an attempt is made to move the cursor to the right
++ * of the right margin, the cursor stops at the right margin. Editor Function
++ */
++static void terminal_CUF(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	shell->cursor_x+=distance;
++	if(shell->cursor_x+1>=shell->size_x)
++		shell->cursor_x=shell->size_x+1;
++}
++
++/*
++ * SGR . Select Graphic Rendition
++ * ESC [ Ps ; . . . ; Ps m 	default value: 0
++ *
++ * Invoke the graphic rendition specified by the parameter(s). All following characters
++ * transmitted to the VT100 are rendered according to the parameter(s) until the next
++ * occurrence of SGR. Format Effector
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Attributes off
++ * 1 	Bold or increased intensity
++ * 4 	Underscore
++ * 5 	Blink
++ * 7 	Negative (reverse) image
++ *
++ * All other parameter values are ignored.
++ *
++ * With the Advanced Video Option, only one type of character attribute is possible as
++ * determined by the cursor selection; in that case specifying either the underscore or
++ * the reverse attribute will activate the currently selected attribute. (See cursor
++ * selection in Chapter 1).
++ */
++static void terminal_SGR(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc==0)
++	{
++		shell->rendition=0;
++		shell->fgcolor=VIMSHELL_COLOR_DEFAULT;  // default fgcolor
++		shell->bgcolor=VIMSHELL_COLOR_DEFAULT;  // default bgcolor
++	}
++	else
++	{
++		int i;
++		for(i=0;i<argc;i++)
++		{
++			int val;
++			switch((val=strtol(argv[i], NULL, 10)))
++			{
++				case 0:
++					shell->rendition=0;
++					shell->fgcolor=VIMSHELL_COLOR_DEFAULT;
++					shell->bgcolor=VIMSHELL_COLOR_DEFAULT;
++					break;
++				case 1:
++					shell->rendition|=RENDITION_BOLD;
++					break;
++				case 2:
++					shell->rendition|=RENDITION_DIM;
++					break;
++				case 4:
++					shell->rendition|=RENDITION_UNDERSCORE;
++					break;
++				case 5:
++					shell->rendition|=RENDITION_BLINK;
++					break;
++				case 7:
++					shell->rendition|=RENDITION_NEGATIVE;
++					break;
++				case 8:
++					shell->rendition|=RENDITION_HIDDEN;
++					break;
++				case 22:
++					shell->rendition&=~RENDITION_BOLD;
++					break;
++				case 24:
++					shell->rendition&=~RENDITION_UNDERSCORE;
++					break;
++				case 25:
++					shell->rendition&=~RENDITION_BLINK;
++					break;
++				case 27:
++					shell->rendition&=~RENDITION_NEGATIVE;
++					break;
++				default:
++					if(val>=30 && val<=37)
++						shell->fgcolor=val-30;
++					else if(val>=40 && val<=47)
++						shell->bgcolor=val-40;
++					else if(val==39)
++						shell->fgcolor=VIMSHELL_COLOR_DEFAULT; // default fgcolor
++					else if(val==49)
++						shell->bgcolor=VIMSHELL_COLOR_DEFAULT; // default bgcolor
++					else
++						ESCDEBUGPRINTF( "%s: unknown rendition %s\n",
++								__FUNCTION__, argv[i]);
++			}
++		}
++	}
++	ESCDEBUGPRINTF("%s: rendition is now: %04x\n", __FUNCTION__, shell->rendition);
++	ESCDEBUGPRINTF("%s: foreground color: %d, background color: %d\n", __FUNCTION__,
++			shell->fgcolor, shell->bgcolor);
++}
++
++/*
++ * Copy the screen contents to the alternate screen.
++ */
++static void terminal_backup_screen(struct vim_shell_window *shell)
++{
++	size_t len;
++	if(shell->alt!=NULL)
++	{
++		ESCDEBUGPRINTF( "%s: WARNING: alternate screen taken\n", __FUNCTION__);
++		vim_shell_free(shell->alt->winbuf);
++		vim_shell_free(shell->alt->bgbuf);
++		vim_shell_free(shell->alt->fgbuf);
++		vim_shell_free(shell->alt->rendbuf);
++		vim_shell_free(shell->alt->tabline);
++		vim_shell_free(shell->alt->charset);
++		vim_shell_free(shell->alt);
++		shell->alt=NULL;
++	}
++
++	shell->alt=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
++	if(shell->alt==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: ERROR: unable to allocate a new screen\n", __FUNCTION__);
++		return;
++	}
++
++	*(shell->alt)=*shell;
++
++	len=shell->size_x*shell->size_y;
++	shell->alt->winbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->fgbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->bgbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->rendbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->tabline=(uint8_t *)vim_shell_malloc(shell->size_x);
++	shell->alt->charset=(uint8_t *)vim_shell_malloc(len);
++	if(shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL ||
++			shell->alt->charset==NULL || shell->alt->tabline==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: ERROR: unable to allocate buffers\n", __FUNCTION__);
++		if(shell->alt->winbuf) vim_shell_free(shell->alt->winbuf);
++		if(shell->alt->fgbuf) vim_shell_free(shell->alt->fgbuf);
++		if(shell->alt->bgbuf) vim_shell_free(shell->alt->bgbuf);
++		if(shell->alt->rendbuf) vim_shell_free(shell->alt->rendbuf);
++		if(shell->alt->tabline) vim_shell_free(shell->alt->tabline);
++		if(shell->alt->charset) vim_shell_free(shell->alt->charset);
++		vim_shell_free(shell->alt);
++		shell->alt=NULL;
++		return;
++	}
++
++	memcpy(shell->alt->winbuf, shell->winbuf, len);
++	memcpy(shell->alt->fgbuf, shell->fgbuf, len);
++	memcpy(shell->alt->bgbuf, shell->bgbuf, len);
++	memcpy(shell->alt->rendbuf, shell->rendbuf, len);
++	memcpy(shell->alt->charset, shell->charset, len);
++	memcpy(shell->alt->tabline, shell->tabline, shell->size_x);
++}
++
++/*
++ * Restore the alternate screen
++ */
++static void terminal_restore_screen(struct vim_shell_window *shell)
++{
++	struct vim_shell_window *alt;
++	if(shell->alt==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: WARNING: nothing to restore\n", __FUNCTION__);
++		return;
++	}
++
++	vim_shell_free(shell->winbuf);
++	vim_shell_free(shell->rendbuf);
++	vim_shell_free(shell->tabline);
++	vim_shell_free(shell->fgbuf);
++	vim_shell_free(shell->bgbuf);
++	vim_shell_free(shell->charset);
++
++	alt=shell->alt;
++	*shell=*(shell->alt);
++	shell->alt=NULL;
++
++	vim_shell_free(alt);
++
++	/*
++	 * Invalidate the shell so it will be fully redrawn
++	 */
++	shell->force_redraw=1;
++}
++
++/*
++ * Erases the whole screen and homes the cursor.
++ */
++static void terminal_init_screen(struct vim_shell_window *shell)
++{
++	char ed_argv[20][20];
++
++	strcpy(ed_argv[0], "2");
++
++	/*
++	 * Erase all of the display.
++	 */
++	terminal_ED(shell, 1, ed_argv);
++
++	/*
++	 * Cursor to HOME position.
++	 */
++	terminal_CUP(shell, 0, NULL);
++}
++
++static void terminal_mode(struct vim_shell_window *shell, int set, int argc, char argv[20][20])
++{
++	int i;
++
++	for(i=0;i<argc;i++)
++	{
++		if(!strcmp(argv[i], "4"))
++		{
++			shell->insert_mode=set;
++			ESCDEBUGPRINTF( "%s: insert mode: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?1"))
++		{
++			shell->application_cursor_mode=set;
++			ESCDEBUGPRINTF( "%s: application cursor mode: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?5"))
++		{
++			ESCDEBUGPRINTF("%s: background dark/light mode ignored\n", __FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?6"))
++		{
++			ESCDEBUGPRINTF("%s: set terminal width ignored\n", __FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?7"))
++		{
++			shell->wraparound=set;
++			ESCDEBUGPRINTF( "%s: wraparound: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "34") || !strcmp(argv[i], "?25"))
++		{
++			shell->cursor_visible=set;
++			ESCDEBUGPRINTF( "%s: cursor visible: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?4"))
++		{
++			ESCDEBUGPRINTF("%s: selection between smooth and jump scrolling ignored\n",__FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?1049") || !strcmp(argv[i], "?1047"))
++		{
++			if(set==1)
++			{
++				terminal_backup_screen(shell);
++				terminal_init_screen(shell);
++				ESCDEBUGPRINTF( "%s: terminal screen backed up.\n", __FUNCTION__);
++			}
++			else
++			{
++				terminal_restore_screen(shell);
++				ESCDEBUGPRINTF( "%s: terminal screen restored from backup.\n", __FUNCTION__);
++			}
++		}
++		else
++		{
++			ESCDEBUGPRINTF( "%s: unimplemented terminal mode: %s\n", __FUNCTION__, argv[i]);
++		}
++	}
++}
++
++/*
++ * EL . Erase In Line
++ * ESC [ Ps K 	default value: 0
++ *
++ * Erases some or all characters in the active line according to the parameter. Editor Function
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Erase from the active position to the end of the line, inclusive (default)
++ * 1 	Erase from the start of the line to the active position, inclusive
++ * 2 	Erase all of the line, inclusive
++ */
++static void terminal_EL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int i, size, pos;
++
++	if(argc==0)
++		i=0;
++	else if(argc==1)
++		i=strtol(argv[0], NULL, 10);
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++
++	size=shell->size_x*shell->size_y;
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	if(i==0)
++	{
++		/*
++		 * erase from the active position to the end of line
++		 */
++
++		memset(shell->winbuf+pos, ' ', shell->size_x-shell->cursor_x);
++		memset(shell->fgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
++		memset(shell->bgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
++		memset(shell->rendbuf+pos, 0, shell->size_x-shell->cursor_x);
++		memset(shell->charset+pos, 0, shell->size_x-shell->cursor_x);
++		ESCDEBUGPRINTF( "%s: erase from active position to end of line\n", __FUNCTION__);
++
++	}
++	else if(i==1)
++	{
++		/*
++		 * erase from start of the line to the active position, inclusive
++		 */
++
++		memset(shell->winbuf+shell->cursor_y*shell->size_x, ' ', shell->cursor_x);
++		memset(shell->fgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
++		memset(shell->bgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
++		memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
++		memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
++		ESCDEBUGPRINTF( "%s: erase from start of line to active position\n", __FUNCTION__);
++	}
++	else if(i==2)
++	{
++		/*
++		 * Erase all of the line
++		 */
++
++		memset(shell->winbuf +shell->cursor_y*shell->size_x, ' ', shell->size_x);
++		memset(shell->fgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++		memset(shell->bgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++		memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->size_x);
++		memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->size_x);
++		ESCDEBUGPRINTF( "%s: erase all of the line\n", __FUNCTION__);
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
++		return;
++	}
++}
++
++/*
++ * ED . Erase In Display
++ * ESC [ Ps J 	default value: 0
++ *
++ * This sequence erases some or all of the characters in the display according
++ * to the parameter. Any complete line erased by this sequence will return that
++ * line to single width mode. Editor Function
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Erase from the active position to the end of the screen, inclusive (default)
++ * 1 	Erase from start of the screen to the active position, inclusive
++ * 2 	Erase all of the display . all lines are erased, changed to single-width, and the cursor does not move.
++ */
++static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int i, size, pos;
++
++	if(argc==0)
++		i=0;
++	else if(argc==1)
++		i=strtol(argv[0], NULL, 10);
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++
++	size=shell->size_x*shell->size_y;
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	if(i==0)
++	{
++		/*
++		 * erase from the active position to the end of screen
++		 */
++
++		memset(shell->winbuf+pos, ' ', size-pos);
++		memset(shell->fgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
++		memset(shell->bgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
++		memset(shell->rendbuf+pos, 0, size-pos);
++		memset(shell->charset+pos, 0, size-pos);
++		ESCDEBUGPRINTF( "%s: erase from active position to end of screen\n", __FUNCTION__);
++
++	}
++	else if(i==1)
++	{
++		/*
++		 * erase from start of the screen to the active position, inclusive
++		 */
++
++		memset(shell->winbuf, ' ', pos);
++		memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, pos);
++		memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, pos);
++		memset(shell->rendbuf, 0, pos);
++		memset(shell->charset, 0, pos);
++		ESCDEBUGPRINTF( "%s: erase from start of screen to active position\n", __FUNCTION__);
++	}
++	else if(i==2)
++	{
++		/*
++		 * Erase all of the display
++		 */
++
++		memset(shell->winbuf, ' ', size);
++		memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, size);
++		memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, size);
++		memset(shell->rendbuf, 0, size);
++		memset(shell->charset, 0, size);
++		ESCDEBUGPRINTF( "%s: erase all of the display\n", __FUNCTION__);
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
++		return;
++	}
++}
++
++/*
++ * CUP . Cursor Position
++ * ESC [ Pn ; Pn H 	default value: 1
++ *
++ * The CUP sequence moves the active position to the position specified by
++ * the parameters. This sequence has two parameter values, the first specifying
++ * the line position and the second specifying the column position. A parameter
++ * value of zero or one for the first or second parameter moves the active
++ * position to the first line or column in the display, respectively. The default
++ * condition with no parameters present is equivalent to a cursor to home action.
++ * In the VT100, this control behaves identically with its format effector
++ * counterpart, HVP. Editor Function
++ *
++ * The numbering of lines depends on the state of the Origin Mode (DECOM).
++ */
++static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc==0)
++	{
++		/*
++		 * goto home position
++		 */
++		shell->cursor_x=0;
++		shell->cursor_y=0;
++	}
++	else if(argc==2)
++	{
++		int x, y;
++
++		y=strtol(argv[0], NULL, 10);
++		x=strtol(argv[1], NULL, 10);
++		if(x==0)
++			x++;
++		if(y==0)
++			y++;
++
++		shell->cursor_y=y-1;
++		shell->cursor_x=x-1;
++
++		// VIMSHELL TODO: if origin mode enabled, position at the
++		//                top margin or so :)
++
++		if(shell->cursor_x>=shell->size_x)
++			shell->cursor_x=shell->size_x-1;
++		if(shell->cursor_y>=shell->size_y)
++			shell->cursor_y=shell->size_y-1;
++	}
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++	ESCDEBUGPRINTF( "%s: moved to X = %d, Y = %d\n", __FUNCTION__, shell->cursor_x, shell->cursor_y);
++}
++
++/*
++ * DECSTBM . Set Top and Bottom Margins (DEC Private)
++ * ESC [ Pn; Pn r 	default values: see below
++ *
++ * This sequence sets the top and bottom margins to define the scrolling region.
++ * The first parameter is the line number of the first line in the scrolling region; the
++ * second parameter is the line number of the bottom line in the scrolling region. Default
++ * is the entire screen (no margins). The minimum size of the scrolling region allowed is
++ * two lines, i.e., the top margin must be less than the bottom margin. The cursor is placed
++ * in the home position (see Origin Mode DECOM).
++ */
++static void terminal_DECSTBM(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc!=2)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	shell->scroll_top_margin=strtol(argv[0], NULL, 10)-1;
++	shell->scroll_bottom_margin=strtol(argv[1], NULL, 10)-1;
++
++	ESCDEBUGPRINTF( "%s: top margin = %d, bottom margin = %d\n", __FUNCTION__,
++			shell->scroll_top_margin, shell->scroll_bottom_margin);
++
++	if(shell->scroll_top_margin>=shell->scroll_bottom_margin)
++	{
++		ESCDEBUGPRINTF( "%s: scroll margin error %d >= %d\n", __FUNCTION__,
++				shell->scroll_top_margin, shell->scroll_bottom_margin);
++
++		shell->scroll_top_margin=0;
++		shell->scroll_bottom_margin=shell->size_y-1;
++
++		return;
++	}
++
++	// Move cursor into home position
++	terminal_CUP(shell, 0, NULL);
++}
++
++
++// Status: 100%
++static void terminal_scroll_up(struct vim_shell_window *shell)
++{
++	// VIMSHELL TODO: maintain a scrollback buffer? copy the first line into
++	// a scrollback buffer.
++
++	/*
++	 * scroll up by moving up the screen buffer a whole line. blank out
++	 * the last line.
++	 */
++	int len, from, to;
++
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++
++	len=shell->scroll_bottom_margin-shell->scroll_top_margin;
++	len*=shell->size_x;
++
++	to=shell->scroll_top_margin*shell->size_x;
++	from=shell->size_x+shell->scroll_top_margin*shell->size_x;
++
++	memmove(shell->winbuf+to, shell->winbuf+from, len);
++	memmove(shell->fgbuf+to, shell->fgbuf+from, len);
++	memmove(shell->bgbuf+to, shell->bgbuf+from, len);
++	memmove(shell->rendbuf+to, shell->rendbuf+from, len);
++	memmove(shell->charset+to, shell->charset+from, len);
++
++	memset(shell->winbuf+shell->scroll_bottom_margin*shell->size_x, ' ', shell->size_x);
++	memset(shell->fgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->bgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->rendbuf+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
++	memset(shell->charset+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
++}
++
++// Status: unknown
++static void terminal_scroll_down(struct vim_shell_window *shell)
++{
++	/*
++	 * scroll down by moving the screen buffer down a whole line, overwriting
++	 * the last line. Then, blank out the first line.
++	 */
++	size_t len;
++	int from, to;
++
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++
++	len=shell->scroll_bottom_margin-shell->scroll_top_margin;
++	len*=shell->size_x;
++
++	to=shell->scroll_top_margin*shell->size_x+shell->size_x;
++	from=shell->scroll_top_margin*shell->size_x;
++
++	memmove(shell->winbuf+to, shell->winbuf+from, len);
++	memmove(shell->fgbuf+to, shell->fgbuf+from, len);
++	memmove(shell->bgbuf+to, shell->bgbuf+from, len);
++	memmove(shell->rendbuf+to, shell->rendbuf+from, len);
++	memmove(shell->charset+to, shell->charset+from, len);
++
++	memset(shell->winbuf+from, ' ', shell->size_x);
++	memset(shell->fgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->bgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->rendbuf+from, 0, shell->size_x);
++	memset(shell->charset+from, 0, shell->size_x);
++}
++
++/*
++ * Insert Line(s) (ANSI).
++ * ESC [ Pn L
++ * Inserts Pn lines at the cursor. If fewer than Pn lines remain from the current line to the
++ * end of the scrolling region, the number of lines inserted is the lesser number. Lines within
++ * the scrolling region at and below the cursor move down. Lines moved past the bottom margin
++ * are lost. The cursor is reset to the first column. This sequence is ignored when the
++ * cursor is outside the scrolling region.
++ */
++// Status: unknown
++static void terminal_IL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int lines, bak_top;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		lines=1;
++	else
++	{
++		lines=strtol(argv[0], NULL, 10);
++		if(lines==0)
++			lines=1;
++	}
++
++	if(shell->scroll_bottom_margin-shell->cursor_y < lines)
++		lines=shell->scroll_bottom_margin-shell->cursor_y;
++
++	bak_top=shell->scroll_top_margin;
++
++	ESCDEBUGPRINTF( "%s: inserted %d lines\n", __FUNCTION__, lines);
++
++	/*
++	 * Set a scrolling region around the part we want to move and scroll down 'lines' times.
++	 */
++	shell->scroll_top_margin=shell->cursor_y;
++	while(lines--)
++		terminal_scroll_down(shell);
++
++	shell->scroll_top_margin=bak_top;
++
++	shell->cursor_x=0;
++}
++
++/*
++ * Delete Line(s) (ANSI).
++ * ESC [ Pn M
++ * Deletes Pn lines starting at the line with the cursor. If fewer than Pn lines remain from
++ * the current line to the end of the scrolling region, the number of lines deleted is the
++ * lesser number. As lines are deleted, lines within the scrolling region and below the cursor move
++ * up, and blank lines are added at the bottom of the scrolling region. The cursor is reset to the
++ * first column. This sequence is ignored when the cursor is outside the scrolling region.
++ * VIMSHELL TODO last sentence
++ */
++// Status: unknown
++static void terminal_DL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int lines, bak_top;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		lines=1;
++	else
++	{
++		lines=strtol(argv[0], NULL, 10);
++		if(lines==0)
++			lines=1;
++	}
++
++	if(shell->scroll_bottom_margin-shell->cursor_y < lines)
++		lines=shell->scroll_bottom_margin-shell->cursor_y;
++
++	bak_top=shell->scroll_top_margin;
++
++	ESCDEBUGPRINTF( "%s: deleted %d lines\n", __FUNCTION__, lines);
++
++	/*
++	 * Set a scrolling region around the part we want to move and scroll up 'lines' times.
++	 */
++	shell->scroll_top_margin=shell->cursor_y;
++	while(lines--)
++		terminal_scroll_up(shell);
++
++	shell->scroll_top_margin=bak_top;
++
++	shell->cursor_x=0;
++}
++
++/*
++ * Insert Characters (ANSI)
++ * ESC [ Pn @
++ * Insert Pn blank characters at the cursor position, with the character attributes set to
++ * normal. The cursor does not move and remains at the beginning of the inserted blank characters.
++ * A parameter of 0 or 1 inserts one blank character. Data on the line is shifted forward as
++ * in character insertion.
++ */
++static void terminal_ICH(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int chars;
++	int curpos;
++	size_t len;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		chars=1;
++	else
++	{
++		chars=strtol(argv[0], NULL, 10);
++		if(chars==0)
++			chars=1;
++	}
++
++	curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	len=shell->size_x-shell->cursor_x-1;
++
++	ESCDEBUGPRINTF( "%s: inserted %d characters\n", __FUNCTION__, chars);
++
++	while(chars--)
++	{
++		memmove(shell->winbuf+curpos+1, shell->winbuf+curpos, len);
++		memmove(shell->fgbuf+curpos+1, shell->fgbuf+curpos, len);
++		memmove(shell->bgbuf+curpos+1, shell->bgbuf+curpos, len);
++		memmove(shell->rendbuf+curpos+1, shell->rendbuf+curpos, len);
++		memmove(shell->charset+curpos+1, shell->charset+curpos, len);
++
++		memset(shell->winbuf+curpos, ' ', 1);
++		memset(shell->fgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->bgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->rendbuf+curpos, 0, 1);
++		memset(shell->charset+curpos, 0, 1);
++	}
++}
++
++/*
++ * Delete Characters (ANSI)
++ * ESC [ Pn P
++ * Deletes Pn characters starting with the character at the cursor position. When a character
++ * is deleted, all characters to the right of the cursor move to the left. This creates a space
++ * character at the right margin for each character deleted. Character attributes move with the
++ * characters. The spaces created at the end of the line have all their character attributes off.
++ */
++static void terminal_DCH(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int chars;
++	int curpos;
++	size_t len;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		chars=1;
++	else
++	{
++		chars=strtol(argv[0], NULL, 10);
++		if(chars==0)
++			chars=1;
++	}
++
++	curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	len=shell->size_x-shell->cursor_x-1;
++
++	ESCDEBUGPRINTF( "%s: deleted %d characters\n", __FUNCTION__, chars);
++
++	while(chars--)
++	{
++		memmove(shell->winbuf+curpos, shell->winbuf+curpos+1, len);
++		memmove(shell->fgbuf+curpos, shell->fgbuf+curpos+1, len);
++		memmove(shell->bgbuf+curpos, shell->bgbuf+curpos+1, len);
++		memmove(shell->rendbuf+curpos, shell->rendbuf+curpos+1, len);
++		memmove(shell->charset+curpos, shell->charset+curpos+1, len);
++
++		memset(shell->winbuf+curpos+len, ' ', 1);
++		memset(shell->fgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->bgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->rendbuf+curpos+len, 0, 1);
++		memset(shell->charset+curpos+len, 0, 1);
++	}
++}
++
++static void terminal_BEL(struct vim_shell_window *shell)
++{
++	/*
++	 * "Sound bell tone from keyboard."
++	 * Sure.
++	 */
++}
++
++static void terminal_BS(struct vim_shell_window *shell)
++{
++	/*
++	 * "Move the cursor to the left one character position,
++	 * unless it is at the left margin, in which case no action occurs."
++	 */
++	if(shell->cursor_x>0)
++		shell->cursor_x--;
++}
++
++static void terminal_LF(struct vim_shell_window *shell)
++{
++	/*
++	 * "This code causes a line feed or a new line operation."
++	 */
++
++	if(shell->just_wrapped_around==1)
++	{
++		/*
++		 * Terminals which have the xenl capability ignore a linefeed after
++		 * an auto margin wrap.
++		 */
++		VERBOSEPRINTF( "%s: ignored LF because of earlier wrap around\n",
++				__FUNCTION__);
++		return;
++	}
++
++	shell->cursor_y++;
++	if(shell->cursor_y-1==shell->scroll_bottom_margin)
++	{
++		shell->cursor_y--;
++		terminal_scroll_up(shell);
++	}
++
++	VERBOSEPRINTF( "%s: did LF, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
++			shell->cursor_x, shell->cursor_y);
++}
++
++static void terminal_CR(struct vim_shell_window *shell)
++{
++	/*
++	 * "Move cursor to the left margin on the current line."
++	 */
++	if(shell->just_wrapped_around==1)
++	{
++		/*
++		 * Terminals which have the xenl capability ignore a linefeed after
++		 * an auto margin wrap.
++		 */
++		VERBOSEPRINTF( "%s: ignored CR because of earlier wrap around\n",
++				__FUNCTION__);
++		return;
++	}
++	shell->cursor_x=0;
++	VERBOSEPRINTF( "%s: did CR, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
++			shell->cursor_x, shell->cursor_y);
++}
++
++/*
++ * RI . Reverse Index
++ * ESC M
++ *
++ * Move the active position to the same horizontal position on the preceding line. If the
++ * active position is at the top margin, a scroll down is performed. Format Effector
++ */
++static void terminal_RI(struct vim_shell_window *shell)
++{
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++	if(shell->cursor_y==shell->scroll_top_margin)
++		terminal_scroll_down(shell);
++	else
++		shell->cursor_y--;
++}
++
++/*
++ * IND . Index
++ * ESC D
++ *
++ * This sequence causes the active position to move downward one line without changing the
++ * column position. If the active position is at the bottom margin, a scroll up is performed.
++ * Format Effector
++ */
++static void terminal_IND(struct vim_shell_window *shell)
++{
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++	if(shell->cursor_y==shell->scroll_bottom_margin)
++		terminal_scroll_up(shell);
++	else
++		shell->cursor_y++;
++}
++
++/*
++ * ESC 7
++ * ESC [s (ANSI)
++ * Saves the current terminal rendering settings
++ */
++static void terminal_save_attributes(struct vim_shell_window *shell)
++{
++	shell->saved_cursor_x=shell->cursor_x;
++	shell->saved_cursor_y=shell->cursor_y;
++	shell->saved_rendition=shell->rendition;
++	shell->saved_fgcolor=shell->fgcolor;
++	shell->saved_bgcolor=shell->bgcolor;
++	shell->saved_G0_charset=shell->G0_charset;
++	shell->saved_G1_charset=shell->G1_charset;
++	shell->saved_application_keypad_mode=shell->application_keypad_mode;
++	shell->saved_application_cursor_mode=shell->application_cursor_mode;
++	shell->saved_insert_mode=shell->insert_mode;
++}
++
++/*
++ * ESC 8
++ * ESC [u (ANSI)
++ * Restores the current terminal rendering settings
++ */
++static void terminal_restore_attributes(struct vim_shell_window *shell)
++{
++	shell->cursor_x=shell->saved_cursor_x;
++	shell->cursor_y=shell->saved_cursor_y;
++	shell->rendition=shell->saved_rendition;
++	shell->fgcolor=shell->saved_fgcolor;
++	shell->bgcolor=shell->saved_bgcolor;
++	shell->G0_charset=shell->saved_G0_charset;
++	shell->G1_charset=shell->saved_G1_charset;
++	shell->application_keypad_mode=shell->saved_application_keypad_mode;
++	shell->application_cursor_mode=shell->saved_application_cursor_mode;
++	shell->insert_mode=shell->saved_insert_mode;
++}
++
++#define ADVANCE_PSEQ { pseq++; if(*pseq==0) return; }
++
++/*
++ * Attempts to parse the escape sequence stored in shell->esc_sequence.
++ * When it succeeds, it removes that escape sequence from the buffer and
++ * possibly clears shell->in_esc_sequence when there are no characters left,
++ * leaving ESC mode.
++ */
++static void terminal_parse_esc_sequence(struct vim_shell_window *shell)
++{
++	char *pseq;
++
++	if(shell->in_esc_sequence==0 || shell->esc_sequence[0]!=033)
++	{
++		ESCDEBUGPRINTF( "%s: invalid esc sequence in esc buffer\n",
++				__FUNCTION__);
++		/*
++		 * We would stick here forever, so flush the buffer
++		 */
++		shell->in_esc_sequence=0;
++		terminal_flush_output(shell);
++
++		return;
++	}
++
++	if(shell->in_esc_sequence==1)
++	{
++		ESCDEBUGPRINTF( "%s: not much in the buffer ...\n", __FUNCTION__);
++		return;
++	}
++
++	shell->esc_sequence[shell->in_esc_sequence]=0;
++	pseq=shell->esc_sequence+1;
++
++	if(*pseq=='[')
++	{
++		/*
++		 * Got a Control Sequence Introducer (CSI) = ESC [
++		 * Parse Parameters.
++		 */
++
++		int argc=0;
++		char argv[20][20];
++
++		ADVANCE_PSEQ;
++
++		memset(argv, 0, sizeof(argv));
++
++		if((*pseq>='0' && *pseq<='9') || *pseq=='?' || *pseq==';')
++		{
++			int cont;
++			do
++			{
++				cont=0;
++				while((*pseq>='0' && *pseq<='9') || *pseq=='?')
++				{
++					char dummy[2];
++					dummy[0]=*pseq;
++					dummy[1]=0;
++					strcat(argv[argc], dummy);
++					ADVANCE_PSEQ;
++				}
++				if(argv[argc][0]==0)
++				{
++					strcpy(argv[argc], "0");
++				}
++
++				argc++;
++				if(*pseq==';')
++				{
++					cont=1;
++					ADVANCE_PSEQ;
++				}
++			} while(cont==1);
++		}
++
++#ifdef ESCDEBUG
++		ESCDEBUGPRINTF("%s: sequence = '%s', argc = %d, ", __FUNCTION__, shell->esc_sequence, argc);
++		{
++			int i;
++			for(i=0;i<argc;i++)
++			{
++				ESCDEBUGPRINTF("argv[%d] = '%s', ",i, argv[i]);
++			}
++		}
++		ESCDEBUGPRINTF("\n");
++#endif
++
++		switch(*pseq)
++		{
++			case 'f':
++			case 'H':
++				terminal_CUP(shell, argc, argv);
++				break;
++			case 'J':
++				terminal_ED(shell, argc, argv);
++				break;
++			case 'K':
++				terminal_EL(shell, argc, argv);
++				break;
++			case 'C':
++				terminal_CUF(shell, argc, argv);
++				break;
++			case 'l':
++				terminal_mode(shell, 0, argc, argv);
++				break;
++			case 'h':
++				terminal_mode(shell, 1, argc, argv);
++				break;
++			case 'm':
++				terminal_SGR(shell, argc, argv);
++				break;
++			case 'r': // set scroll margins
++				terminal_DECSTBM(shell, argc, argv);
++				break;
++			case 'B': // cursor down
++				terminal_CUD(shell, argc, argv);
++				break;
++			case 'D': // cursor backward
++				terminal_CUB(shell, argc, argv);
++				break;
++			case 'A': // cursor up
++				terminal_CUU(shell, argc, argv);
++				break;
++			case 'M': // delete line
++				terminal_DL(shell, argc, argv);
++				break;
++			case 'L': // insert line
++				terminal_IL(shell, argc, argv);
++				break;
++			case '@': // insert characters
++				terminal_ICH(shell, argc, argv);
++				break;
++			case 'P': // delete characters
++				terminal_DCH(shell, argc, argv);
++				break;
++			case 'E': // new line
++				terminal_CR(shell);
++				terminal_LF(shell);
++				break;
++			case 's': // Save Cursor and attributes
++				terminal_save_attributes(shell);
++				break;
++			case 'u': // Restore Cursor and attributes
++				terminal_restore_attributes(shell);
++				break;
++			case 'g': // Tabulator clear
++				terminal_TBC(shell, argc, argv);
++				break;
++			default:
++				ESCDEBUGPRINTF( "%s: unimplemented CSI code: %c\n",
++						__FUNCTION__, *pseq);
++		}
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: sequence is (probably not yet complete) '%s'\n",
++				__FUNCTION__, shell->esc_sequence);
++		switch(*pseq)
++		{
++			case '#':
++				ADVANCE_PSEQ;
++				if(*pseq=='8') // fill screen with E's
++				{
++					memset(shell->winbuf, 'E', shell->size_x*shell->size_y);
++				}
++				break;
++			case '(': // switch G0 charset
++				ADVANCE_PSEQ;
++				shell->G0_charset=*pseq;
++				ESCDEBUGPRINTF( "%s: G0 character set is now: %c\n", __FUNCTION__, *pseq);
++				break;
++			case ')': // switch G1 charset
++				ADVANCE_PSEQ;
++				shell->G1_charset=*pseq;
++				ESCDEBUGPRINTF( "%s: G1 character set is now: %c\n", __FUNCTION__, *pseq);
++				break;
++			case 'D': // index
++				terminal_IND(shell);
++				break;
++			case 'M': // reverse index
++				terminal_RI(shell);
++				break;
++			case '7': // Save Cursor
++				terminal_save_attributes(shell);
++				break;
++			case '8': // Restore Cursor
++				terminal_restore_attributes(shell);
++				break;
++			case '=': // Application Keypad Mode
++				shell->application_keypad_mode=1;
++				ESCDEBUGPRINTF( "%s: keypad switched to application mode\n", __FUNCTION__);
++				break;
++			case '>': // Numeric Keypad Mode
++				shell->application_keypad_mode=0;
++				ESCDEBUGPRINTF( "%s: keypad switched to numeric mode\n", __FUNCTION__);
++				break;
++			case 'H': // Set Horizontal Tab
++				shell->tabline[shell->cursor_x]=1;
++				break;
++			case 'E': // NEL - Moves cursor to first position on next line. If cursor is
++				  // at bottom margin, screen performs a scroll-up.
++				terminal_IND(shell);
++				shell->cursor_x=0;
++				break;
++			case ']': // This could be the beginning of the xterm title hack
++				ADVANCE_PSEQ;
++				if(*pseq=='1' || *pseq=='2' || *pseq=='0')
++				{
++					char title[50];
++					ADVANCE_PSEQ;
++					if(*pseq==';')
++					{
++						int end;
++						title[0]=0;
++						/*
++						 * I know this loop is ugly but ADVANCE_PSEQ
++						 * is a macro, sorry
++						 */
++						for(end=0;!end;)
++						{
++							ADVANCE_PSEQ;
++							if(strlen(title)>sizeof(title)-2)
++								end=1;
++							if(*pseq==7)
++								end=1;
++							else
++							{
++								char dummy[2];
++								dummy[0]=*pseq;
++								dummy[1]=0;
++								strcat(title, dummy);
++							}
++						}
++
++						snprintf(shell->windowtitle, sizeof(shell->windowtitle),
++								"%s", title);
++
++						ESCDEBUGPRINTF( "%s: changing title to '%s'\n",
++								__FUNCTION__, shell->windowtitle);
++					}
++					else
++					{
++						ESCDEBUGPRINTF( "%s: error in xterm title hack "
++								"sequence: %c\n", __FUNCTION__, *pseq);
++					}
++				}
++				else
++				{
++					ESCDEBUGPRINTF( "%s: unimplemented xterm title hack "
++							"code: %d\n", __FUNCTION__, *pseq);
++				}
++				break;
++			default:
++				ESCDEBUGPRINTF( "%s: unimplemented esc code: %c\n",
++						__FUNCTION__, *pseq);
++		}
++	}
++
++	/*
++	 * when we end up here, we successfully completed the sequence.
++	 */
++	shell->in_esc_sequence=0;
++	terminal_flush_output(shell);
++
++#ifdef ESCDEBUG
++	pseq++;
++	if(*pseq!=0)
++	{
++		ESCDEBUGPRINTF( "WARNING: %s: sequence is not over! left in buffer: '%s'\n",
++				__FUNCTION__, pseq);
++	}
++#endif
++}
++
++
++/*
++ * Main character write part.
++ * This here runs most of the time, just writing the character to the
++ * right cursor position.
++ */
++static void terminal_normal_char(struct vim_shell_window *shell, char input)
++{
++	int pos;
++	uint8_t charset;
++
++	shell->just_wrapped_around=0;
++	/*
++	 * If the cursor is currently in the 'virtual' column (that is the column
++	 * after the physical line end), we wrap around now.
++	 */
++	if(shell->cursor_x==shell->size_x)
++	{
++		if(shell->wraparound==1)
++		{
++			terminal_CR(shell);
++			terminal_LF(shell);
++			shell->just_wrapped_around=1;
++			VERBOSEPRINTF( "%s: auto margin - wrapped around!\n",__FUNCTION__);
++		}
++		else
++		{
++			shell->cursor_x--;
++		}
++	}
++
++	/*
++	 * write the character at its right position.
++	 */
++	if(shell->insert_mode!=0)
++	{
++		/*
++		 * If insert mode is on, move all characters from the current position+1 to
++		 * the end of the row. The last character on the row falls out.
++		 * Fortunately, we already implemented this kind of operation :)
++		 */
++                terminal_ICH(shell, 0, NULL);
++	}
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++
++	/*
++	 * Select which character to display.
++	 */
++	if(shell->active_charset==1)
++		charset=shell->G1_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
++	else
++		charset=shell->G0_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
++
++	shell->winbuf[pos]=input;
++	shell->fgbuf[pos]=shell->fgcolor;
++	shell->bgbuf[pos]=shell->bgcolor;
++	shell->rendbuf[pos]=shell->rendition;
++	shell->charset[pos]=charset;
++	VERBOSEPRINTF( "%s: writing char '%c' to position X = %u, Y = %u (col: 0x%02x,0x%02x)\n", __FUNCTION__,
++			input, shell->cursor_x, shell->cursor_y, current_fg, current_bg);
++	shell->cursor_x++;
++}
++
++/*
++ * Here, all characters between 000 and 037 are processed. This is in a
++ * separate function because control characters can be in the normal
++ * flow of characters or in the middle of escape sequences.
++ */
++static void terminal_process_control_char(struct vim_shell_window *shell, char input)
++{
++	switch(input)
++	{
++		case 007: // BEL, Bell, 0x07
++			terminal_BEL(shell);
++			break;
++		case 010: // BS, Backspace, 0x08
++			terminal_BS(shell);
++			break;
++		case 011: // TAB
++			{
++				/*
++				 * Move to the next tabstop or stop at the right margin if no
++				 * tabstop found.
++				 */
++				int i, found;
++				for(found=0, i=shell->cursor_x+1;i<shell->size_x && !found;i++)
++				{
++					if(shell->tabline[i]==1)
++					{
++						shell->cursor_x=i;
++						found=1;
++					}
++				}
++				if(found==0)
++				{
++					shell->cursor_x=shell->size_x-1;
++				}
++			}
++			break;
++		case 013:
++		case 014:
++		case 012: // LF, Line Feed, 0x0a, \n
++			terminal_LF(shell);
++			break;
++		case 015: // CR, Carriage Return, 0x0d, \r
++			terminal_CR(shell);
++			break;
++		case 016: // SO, Invoke G1 character set, as designated by SCS control sequence.
++			shell->active_charset=1;
++			break;
++		case 017: // SI, Select G0 character set, as selected by ESC ( sequence.
++			shell->active_charset=0;
++			break;
++		case 030:
++		case 032: // CAN or SUB - cancel escape sequence
++			shell->in_esc_sequence=0;
++			// VIMSHELL TODO: display substitution character?
++			ESCDEBUGPRINTF("%s: WARNING: possible source of rendering faults: "
++					"substitution characters after CAN or SUB?\n", __FUNCTION__);
++			break;
++		case 033: // ESC, Escape
++			/*
++			 * Note: This also fulfills the requirement that a ESC occuring while processing
++			 *       an escape sequence should restart the sequence.
++			 */
++			shell->in_esc_sequence=1;
++			shell->esc_sequence[0]=033;
++			break;
++		default:
++			ESCDEBUGPRINTF("%s: unimplemented control character: %u\n", __FUNCTION__, input);
++			break;
++	}
++}
++
++static void terminal_input_char(struct vim_shell_window *shell, char input)
++{
++	if(shell->in_esc_sequence==0)
++	{
++		if(input>=0 && input<=037)
++		{
++			/*
++			 * A control character, process it
++			 */
++			terminal_process_control_char(shell, input);
++		}
++		else
++		{
++			// all normal characters are processed here
++			terminal_normal_char(shell, input);
++		}
++	}
++	else
++	{
++		if(input>=0 && input<=037)
++		{
++			/*
++			 * That's right, control characters can appear even in
++			 * the middle of escape sequences.
++			 */
++			terminal_process_control_char(shell, input);
++			return;
++		}
++
++		/*
++		 * Aha, we are right in the middle of an escape sequence.
++		 * Add this character and attempt to parse the sequence.
++		 */
++		shell->esc_sequence[shell->in_esc_sequence]=input;
++		shell->in_esc_sequence++;
++
++		if(shell->in_esc_sequence>=sizeof(shell->esc_sequence))
++		{
++			/*
++			 * about to overrun esc sequence buffer ...
++			 * Should never happen, but still: kill the sequence, or we'd loop
++			 * forever.
++			 */
++
++			shell->in_esc_sequence=0;
++			terminal_flush_output(shell);
++			return;
++		}
++
++		terminal_parse_esc_sequence(shell);
++	}
++}
++
++/*
++ * If we are ready, flush the outbuf into the shell.
++ * CHECK: should always be called when shell->in_esc_sequence goes back to zero,
++ *        so characters that are waiting for a sequence to become complete can be
++ *        flushed out.
++ */
++static int terminal_flush_output(struct vim_shell_window *shell)
++{
++	if(/*shell->in_esc_sequence==0 && */ shell->outbuf_pos>0)
++	{
++		int len;
++#ifdef ESCDEBUG
++		ESCDEBUGPRINTF( "%s: sending:\n",__FUNCTION__);
++		hexdump(vimshell_debug_fp, shell->outbuf, shell->outbuf_pos);
++#endif
++		len=write(shell->fd_master, shell->outbuf, shell->outbuf_pos);
++		if(len<0)
++		{
++			ESCDEBUGPRINTF( "%s: ERROR: write failed: %s\n",
++					__FUNCTION__,strerror(errno));
++			shell->outbuf_pos=0;
++			return -1;
++		}
++
++		if(shell->outbuf_pos!=len)
++			memmove(shell->outbuf, shell->outbuf+len, len);
++		shell->outbuf_pos-=len;
++
++		return len;
++	}
++	return 0;
++}
++
++/*
++ * Main Terminal processing method (VIM <- Shell).
++ * Gets a buffer with input data from the shell, interprets it and updates
++ * the shell window's windowbuffer accordingly.
++ */
++void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len)
++{
++	int i;
++	for(i=0;i<len;i++)
++	{
++		terminal_input_char(shell, input[i]);
++	}
++}
++
++/*
++ * Main Terminal output method (VIM -> Shell).
++ * Translates the character 'c' into an appropriate escape sequence (if necessary)
++ * and puts it into the out buffer.
++ */
++int vim_shell_terminal_output(struct vim_shell_window *shell, int c)
++{
++	char outbuf[50];
++	size_t written;
++
++	outbuf[1]=0;
++
++	switch(c)
++	{
++		case VIMSHELL_KEY_BACKSPACE:
++			sprintf(outbuf, "\177");
++			ESCDEBUGPRINTF( "%s: key is backspace\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_UP:
++			sprintf(outbuf, "\033%cA", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor up\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_DOWN:
++			sprintf(outbuf, "\033%cB", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor down\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_LEFT:
++			sprintf(outbuf, "\033%cD", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor left\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_RIGHT:
++			sprintf(outbuf, "\033%cC", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor right\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_HOME:
++			sprintf(outbuf, "\033[1~");
++			ESCDEBUGPRINTF( "%s: key is home\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F1:
++			sprintf(outbuf, "\033OP");
++			ESCDEBUGPRINTF( "%s: key is F1\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F2:
++			sprintf(outbuf, "\033OQ");
++			ESCDEBUGPRINTF( "%s: key is F2\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F3:
++			sprintf(outbuf, "\033OR");
++			ESCDEBUGPRINTF( "%s: key is F3\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F4:
++			sprintf(outbuf, "\033OS");
++			ESCDEBUGPRINTF( "%s: key is F4\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F5:
++			sprintf(outbuf, "\033[15~");
++			ESCDEBUGPRINTF( "%s: key is F5\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F6:
++			sprintf(outbuf, "\033[17~");
++			ESCDEBUGPRINTF( "%s: key is F6\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F7:
++			sprintf(outbuf, "\033[18~");
++			ESCDEBUGPRINTF( "%s: key is F7\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F8:
++			sprintf(outbuf, "\033[19~");
++			ESCDEBUGPRINTF( "%s: key is F8\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F9:
++			sprintf(outbuf, "\033[20~");
++			ESCDEBUGPRINTF( "%s: key is F9\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F10:
++			sprintf(outbuf, "\033[21~");
++			ESCDEBUGPRINTF( "%s: key is F10\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F11:
++			sprintf(outbuf, "\033[23~");
++			ESCDEBUGPRINTF( "%s: key is F11\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F12:
++			sprintf(outbuf, "\033[24~");
++			ESCDEBUGPRINTF( "%s: key is F12\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_DC:
++			sprintf(outbuf, "\033[3~");
++			ESCDEBUGPRINTF( "%s: key is delete character\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_END:
++			sprintf(outbuf, "\033[4~");
++			ESCDEBUGPRINTF( "%s: key is end\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_IC:
++			sprintf(outbuf, "\033[2~");
++			ESCDEBUGPRINTF( "%s: key is insert character\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_NPAGE:
++			sprintf(outbuf, "\033[6~");
++			ESCDEBUGPRINTF( "%s: key is page down\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_PPAGE:
++			sprintf(outbuf, "\033[5~");
++			ESCDEBUGPRINTF( "%s: key is page up\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K0:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Op" : "0");
++			ESCDEBUGPRINTF( "%s: key is keypad 0\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K1:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oq" : "1");
++			ESCDEBUGPRINTF( "%s: key is keypad 1\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K2:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Or" : "2");
++			ESCDEBUGPRINTF( "%s: key is keypad 2\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K3:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Os" : "3");
++			ESCDEBUGPRINTF( "%s: key is keypad 3\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K4:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ot" : "4");
++			ESCDEBUGPRINTF( "%s: key is keypad 4\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K5:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ou" : "5");
++			ESCDEBUGPRINTF( "%s: key is keypad 5\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K6:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ov" : "6");
++			ESCDEBUGPRINTF( "%s: key is keypad 6\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K7:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ow" : "7");
++			ESCDEBUGPRINTF( "%s: key is keypad 7\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K8:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ox" : "8");
++			ESCDEBUGPRINTF( "%s: key is keypad 8\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K9:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oy" : "9");
++			ESCDEBUGPRINTF( "%s: key is keypad 9\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KPLUS:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ok" : "+");
++			ESCDEBUGPRINTF( "%s: key is keypad plus\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KMINUS:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Om" : "-");
++			ESCDEBUGPRINTF( "%s: key is keypad minus\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KDIVIDE:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oo" : "/");
++			ESCDEBUGPRINTF( "%s: key is keypad divide\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KMULTIPLY:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oj" : "*");
++			ESCDEBUGPRINTF( "%s: key is keypad multiply\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KENTER:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033OM" : "\015");
++			ESCDEBUGPRINTF( "%s: key is keypad enter\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KPOINT:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033On" : ".");
++			ESCDEBUGPRINTF( "%s: key is keypad point\n", __FUNCTION__);
++			break;
++		default:
++			outbuf[0]=(char)c;
++	}
++
++	if(shell->outbuf_pos+strlen(outbuf)>=sizeof(shell->outbuf))
++	{
++		written=sizeof(shell->outbuf)-shell->outbuf_pos;
++		ESCDEBUGPRINTF( "%s: WARNING: prevented from overflowing the outbuf, help!\n",
++				__FUNCTION__);
++	}
++	else
++		written=strlen(outbuf);
++
++	memcpy(shell->outbuf+shell->outbuf_pos, outbuf, written);
++	shell->outbuf_pos+=written;
++
++	if(terminal_flush_output(shell)<0)
++		return -1;
++
++	return written;
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ui.c ./src/ui.c
+--- ../vim72.orig/src/ui.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ui.c	2009-10-02 13:39:57.000000000 +0100
+@@ -1786,6 +1786,64 @@
+     len = 0;	/* to avoid gcc warning */
+     for (try = 0; try < 100; ++try)
+     {
++#  ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * When we use the VIM shell, we use select to look if there was
++	     * some activity on the shells. This is because the read below after
++	     * this block blocks, and this sucks.
++	     *
++	     * This loop is basically here so the shells can send updates while
++	     * we are waiting for the read(2) on the read_cmd_fd to become available.
++	     */
++#  ifndef HAVE_SELECT
++#error sorry - vimshell needs select. programmer is too lazy to write this with poll (at this time)
++#  endif
++	    fd_set rdfd;
++	    buf_T *buf;
++	    int maxfd, ret, done;
++
++	    done=0;
++	    while(!done)
++	    {
++		FD_ZERO(&rdfd);
++		FD_SET(read_cmd_fd, &rdfd);
++		maxfd=read_cmd_fd;
++
++		for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
++		{
++		    if(buf->is_shell!=0)
++		    {
++			FD_SET(buf->shell->fd_master, &rdfd);
++			if( maxfd < buf->shell->fd_master)
++			    maxfd = buf->shell->fd_master;
++		    }
++		}
++
++		ret=select(maxfd+1, &rdfd, NULL, NULL, NULL);
++		if(ret<0)
++		{
++		    /*
++		     * we fsck'd something up ... let's just get out of here
++		     */
++		    done=1;
++		}
++		else if(ret>0)
++		{
++		    if(FD_ISSET(read_cmd_fd, &rdfd))
++		    {
++			/*
++			 * we have what we came here for. exit this loop
++			 * (but only after processing available shell reads)
++			 */
++			done=1;
++		    }
++
++		    vim_shell_do_read_select(rdfd);
++		}
++	    } // while(!done)
++	}
++#  endif
+ #  ifdef VMS
+ 	len = vms_read(
+ #  else
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/version.c ./src/version.c
+--- ../vim72.orig/src/version.c	2009-10-02 13:39:26.000000000 +0100
++++ ./src/version.c	2009-10-02 13:39:57.000000000 +0100
+@@ -581,6 +581,11 @@
+ #else
+ 	"-vertsplit",
+ #endif
++#ifdef FEAT_VIMSHELL
++	"+vimshell",
++#else
++	"-vimshell",
++#endif
+ #ifdef FEAT_VIRTUALEDIT
+ 	"+virtualedit",
+ #else
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim.h ./src/vim.h
+--- ../vim72.orig/src/vim.h	2009-10-02 13:39:24.000000000 +0100
++++ ./src/vim.h	2009-10-02 13:39:57.000000000 +0100
+@@ -396,6 +396,14 @@
+ 
+ /*
+  * The characters and attributes cached for the screen.
++ * VIM-Shell: the VIM-shell really needs more than one byte for the attributes.
++ *            Despite of a single warning during compilation, it seems to work
++ *            fine to simply change the type here.
++ *            We use the sattr_T as follows:
++ *            The lowest byte is handled the same as before, for rendering attributes.
++ *            The remaining byte is split, the uppermost 4 bits for the active foreground
++ *            color, and the lowermost 4 bits for the active background color (at this
++ *            screen position).
+  */
+ typedef char_u schar_T;
+ #ifdef FEAT_SYN_HL
+@@ -2054,6 +2062,10 @@
+ # include <XSUB.h>
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++#include "vim_shell.h"
++#endif
++
+ /* values for vim_handle_signal() that are not a signal */
+ #define SIGNAL_BLOCK	-1
+ #define SIGNAL_UNBLOCK  -2
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.c ./src/vim_shell.c
+--- ../vim72.orig/src/vim_shell.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/vim_shell.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,926 @@
++/*
++ * vim_shell.c
++ *
++ * This is the interface layer of the VIM-Shell. VIM only calls functions from this module,
++ * e.g. create a new VIM-Shell, read characters from the shell or write characters to the
++ * shell. The respective functions pass these things down to the terminal layer, implemented
++ * in terminal.c.
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ */
++
++
++static char *RCSID="$Id$";
++
++#include "vim.h"
++
++#ifdef FEAT_VIMSHELL
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <signal.h>
++#ifdef HAVE_PTY_H
++#include <pty.h>
++#endif
++#ifdef HAVE_TERMIOS_H
++#include <termios.h>
++#endif
++#ifdef HAVE_LIBUTIL_H
++#include <libutil.h>
++#endif
++#include <fcntl.h>
++
++#if !defined(TIOCSWINSZ)
++#  error "VIMSHELL: needs TIOCSWINSZ at the moment, not available on your system, sorry."
++#endif
++
++#ifdef VIMSHELL_DEBUG
++#  define CHILDDEBUG
++#  define SIGDEBUG
++#endif
++
++#ifdef CHILDDEBUG
++#  define CHILDDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
++#else
++#  define CHILDDEBUGPRINTF(a...)
++#endif
++
++#ifdef SIGDEBUG
++#  define SIGDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
++#else
++#  define SIGDEBUGPRINTF(a...)
++#endif
++
++
++int vimshell_errno;
++
++FILE *vimshell_debug_fp=NULL;
++
++/*
++ * Main initialization function. Sets up global things always needed for the VIM shell.
++ */
++int vim_shell_init()
++{
++#ifdef VIMSHELL_DEBUG
++	vimshell_debug_fp=fopen("vimshell.debug", "w");
++#endif
++
++	/*
++	 * Everything went OK
++	 */
++	return 0;
++}
++
++/*
++ * A routine that prints a buffer in 'hexdump -C'-style via printf
++ */
++static void hexdump(FILE *fp, unsigned char *buffer, long len)
++{
++	unsigned long pos=0;
++
++	while(len>0)
++	{
++		int i;
++		fprintf(fp,"%08x  ",(unsigned int)pos);
++		for(i=0;i<16 && i<len;i++)
++		{
++			fprintf(fp,"%02x ",buffer[pos+i]);
++			if(i==7 || i==15)
++				fprintf(fp," ");
++		}
++		fprintf(fp,"|");
++		for(i=0;i<16 && i<len;i++)
++		{
++			unsigned char c=buffer[pos+i];
++			if(isprint(c))
++			{
++				fprintf(fp,"%c",c);
++			}
++			else
++			{
++				fprintf(fp,".");
++			}
++		}
++		fprintf(fp,"|\n");
++		len-=16;
++		pos+=16;
++	}
++}
++
++/*
++ * Create a new window.
++ * @return: pointer to a new struct vim_shell_window on success
++ *          NULL on failure
++ */
++struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height)
++{
++	struct vim_shell_window *rval;
++	int i;
++
++	rval=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
++	if(rval==NULL)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		return NULL;
++	}
++
++	memset(rval, 0, sizeof(struct vim_shell_window));
++
++	rval->size_x=width;
++	rval->size_y=height;
++
++	rval->fgcolor=VIMSHELL_COLOR_DEFAULT;
++	rval->bgcolor=VIMSHELL_COLOR_DEFAULT;
++
++	rval->G0_charset='B';  // United States (USASCII)
++	rval->G1_charset='0';  // Special graphics characters and line drawing set
++	rval->active_charset=0;
++
++	rval->winbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->charset=(uint8_t *)vim_shell_malloc(width*height);
++	rval->tabline=(uint8_t *)vim_shell_malloc(width);
++	//rval->phys_screen=(uint32_t *)vim_shell_malloc(width*height*4);
++	if(rval->winbuf==NULL || rval->fgbuf==NULL || rval->bgbuf==NULL || rval->rendbuf==NULL || rval->charset==NULL ||
++			rval->tabline==NULL /* || rval->phys_screen==NULL */)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		// VIMSHELL TODO: cleanup, free the buffers that were successfully allocated
++		vim_shell_free(rval);
++		return NULL;
++	}
++	memset(rval->winbuf, ' ', width*height);
++	memset(rval->fgbuf, rval->fgcolor, width*height);
++	memset(rval->bgbuf, rval->bgcolor, width*height);
++	memset(rval->rendbuf, 0, width*height);
++	memset(rval->charset, 0, width*height);
++	memset(rval->tabline, 0, width);
++
++#if 0
++	for(i=0;i<width*height;i++)
++	{
++		/*
++		 * This is: default foreground, default background, no rendering attributes, ' ' as character
++		 */
++		rval->phys_screen[i]=0x09090020;
++	}
++#endif
++
++	/*
++	 * Set a tab every 8 columns (default)
++	 */
++	for(i=1;i<width;i++)
++	{
++		if((i+1)%8==0 && i+1<width)
++			rval->tabline[i]=1;
++	}
++
++	rval->wraparound=1;
++
++	rval->cursor_x=0;
++	rval->cursor_y=0;
++	rval->cursor_visible=1;
++
++	rval->scroll_top_margin=0;
++	rval->scroll_bottom_margin=height-1;
++
++	CHILDDEBUGPRINTF("%s: vimshell created, width = %d, height = %d\n",
++			__FUNCTION__, width, height);
++
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return rval;
++}
++
++/*
++ * start the program in argv in the shell window.
++ */
++int vim_shell_start(struct vim_shell_window *shell, char *argv[])
++{
++	struct winsize winsize;
++	struct termios termios;
++
++	memset(&termios, 0, sizeof(struct termios));
++
++	/*
++	 * Set terminal parameters.
++	 */
++	termios.c_iflag=ICRNL;
++	termios.c_oflag=ONLCR | OPOST;
++	termios.c_cflag=CS8 | CREAD | HUPCL;
++	termios.c_lflag=ECHO | ECHOE | ECHOK | ECHOKE | ISIG | ECHOCTL | ICANON;
++	termios.c_cc[VMIN]=1;
++	termios.c_cc[VTIME]=0;
++	termios.c_cc[VINTR]=003;
++	termios.c_cc[VQUIT]=034;
++	termios.c_cc[VERASE]=0177;
++	termios.c_cc[VKILL]=025;
++	termios.c_cc[VEOF]=004;
++	termios.c_cc[VSTART]=021;
++	termios.c_cc[VSTOP]=023;
++	termios.c_cc[VSUSP]=032;
++
++	winsize.ws_row=shell->size_y;
++	winsize.ws_col=shell->size_x;
++	winsize.ws_xpixel=0;
++	winsize.ws_ypixel=0;
++
++	/*
++	 * allocate a pty, fork and exec the command
++	 */
++	shell->pid=forkpty(&shell->fd_master, NULL, &termios, &winsize);
++	if(shell->pid==0)
++	{
++		/*
++		 * child code
++		 */
++		setenv("TERM", "screen", 1);
++		if(execvp(*argv, argv)<0)
++		{
++			vimshell_errno=VIMSHELL_EXECV_ERROR;
++			// VIMSHELL TODO close fds??
++			return -1;
++		}
++	}
++	else if(shell->pid<0)
++	{
++		vimshell_errno=VIMSHELL_FORKPTY_ERROR;
++		return -1;
++	}
++
++	/*
++	 * Set the file descriptor to non-blocking
++	 */
++	if(fcntl(shell->fd_master, F_SETFL, fcntl(shell->fd_master, F_GETFL) | O_NONBLOCK)<0)
++	{
++		vimshell_errno=VIMSHELL_FCNTL_ERROR;
++		return -1;
++	}
++
++	/*
++	 * parent code
++	 */
++	if(ioctl(shell->fd_master, TIOCSWINSZ, &winsize)<0)
++	{
++		CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
++				__FUNCTION__,strerror(errno));
++	}
++
++	return 0;
++}
++
++/*
++ * this is much like strerror, only with vimshell_errno. Additionally, if errno is not
++ * null, the formatted error message (strerror) will be appended to the output.
++ */
++char *vim_shell_strerror()
++{
++	static char errbuf[200];
++	static char *errmsg[]={"Success",
++		"Out of memory",
++		"forkpty error",
++		"read error",
++		"write error",
++		"execv error",
++		"sigaction error",
++	        "read (EOF)",
++	        "fcntl error"};
++
++	if(errno==0)
++		return errmsg[vimshell_errno];
++
++	snprintf(errbuf, sizeof(errbuf), "%s: %s", errmsg[vimshell_errno], strerror(errno));
++	return errbuf;
++}
++
++/*
++ * Read what is available from the master pty and tear it through the
++ * terminal emulation. This will fill the window buffer.
++ */
++int vim_shell_read(struct vim_shell_window *shell)
++{
++	// for now, copy what we have into the window buffer.
++	char input[2000];
++	int rval;
++
++retry:
++	if((rval=read(shell->fd_master, input, sizeof(input)))<0)
++	{
++		if(errno==EINTR)
++			goto retry;
++		if(errno==EAGAIN)
++		{
++			/*
++			 * This function should only be called when there really
++			 * are bytes available to read from the fd_master. This
++			 * is ensured by calling select() before this function.
++			 * But it seems that there is a race with a SIGWINSZ right
++			 * in the middle of a select() (reporting there are characters
++			 * available) and the following read() that will block forever.
++			 * It seems that SIGWINSZ flushes the processes input queue, at
++			 * least on Linux.
++			 *
++			 * So if we get here although there is nothing to read, don't
++			 * report an error, just return successfully.
++			 */
++			goto success;
++		}
++
++		vimshell_errno=VIMSHELL_READ_ERROR;
++		return -1;
++	}
++
++	if(rval==0)
++	{
++		/*
++		 * This means end-of-file, the subprocess exited.
++		 */
++		vimshell_errno=VIMSHELL_READ_EOF;
++		return -1;
++	}
++
++#ifdef RAWDEBUG
++	fprintf(vimshell_debug_fp, "\nincoming bytes:\n");
++	hexdump(vimshell_debug_fp, input, rval);
++#endif
++
++	/*
++	 * Interface to the terminal layer: give the input buffer to the
++	 * terminal emulator for processing.
++	 */
++	vim_shell_terminal_input(shell, input, rval);
++
++success:
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return 0;
++}
++
++/*
++ * Write a character to the VIM-Shell.
++ * Blow it through terminal_output so it gets translated correctly etc...
++ */
++int vim_shell_write(struct vim_shell_window *shell, int c)
++{
++	if(vim_shell_terminal_output(shell, c)<0)
++	{
++		vimshell_errno=VIMSHELL_WRITE_ERROR;
++		return -1;
++	}
++
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return 0;
++}
++
++/*
++ * Free everything that is associated with this shell window.
++ * Also terminates the process. The shell pointer will be set to NULL.
++ * The buffer will be restored to a usable, empty buffer.
++ */
++void vim_shell_delete(buf_T *buf)
++{
++	struct vim_shell_window *sh=buf->shell;
++	int status;
++	pid_t pid;
++
++	/*
++	 * First, kill the child and wait for it.
++	 * VIMSHELL TODO: this can be extended a lot. e.g. using a SIGCHLD handler
++	 * or an SIGALRM handler and kill(SIGKILL) the process when the alarm fires
++	 * etc. But for now (and most of all cases) this should be OK.
++	 */
++	pid=sh->pid;
++	if(pid>0)
++	{
++		kill(pid, SIGTERM);
++		kill(pid, SIGHUP);
++		while(waitpid(pid, &status, 0)<0 && errno==EINTR);
++		CHILDDEBUGPRINTF( "%s: PID %u terminated, exit status = %d\n", __FUNCTION__, pid,
++			WEXITSTATUS(status));
++	}
++
++	/*
++	 * The child is dead. Clean up
++	 */
++	close(sh->fd_master);
++	if(sh->alt)
++	{
++		vim_shell_free(sh->alt->winbuf);
++		vim_shell_free(sh->alt->fgbuf);
++		vim_shell_free(sh->alt->bgbuf);
++		vim_shell_free(sh->alt->rendbuf);
++		vim_shell_free(sh->alt->tabline);
++		vim_shell_free(sh->alt->charset);
++		vim_shell_free(sh->alt);
++		sh->alt=NULL;
++	}
++	vim_shell_free(sh->winbuf);
++	vim_shell_free(sh->fgbuf);
++	vim_shell_free(sh->bgbuf);
++	vim_shell_free(sh->rendbuf);
++	vim_shell_free(sh->tabline);
++	vim_shell_free(sh->charset);
++	vim_shell_free(sh);
++
++	CHILDDEBUGPRINTF( "%s: vimshell %p freed.\n", __FUNCTION__, sh);
++
++	buf->is_shell=0;
++	buf->shell=NULL;
++	buf->b_p_ro=FALSE;
++}
++
++/*
++ * Does the work of actually resizing the shell's buffers. Deallocating them,
++ * reallocating them, copying over the old contents to the right places, etc...
++ * rval: 0 = success, <0 = error
++ */
++static int internal_screenbuf_resize(struct vim_shell_window *shell, int width, int height)
++{
++	uint8_t *owinbuf, *ofgbuf, *obgbuf, *orendbuf, *otabline, *ocharset;
++	int x, y, len, vlen;
++	uint16_t oldwidth, oldheight;
++
++	oldwidth=shell->size_x;
++	oldheight=shell->size_y;
++	shell->size_x=(uint16_t)width;
++	shell->size_y=(uint16_t)height;
++
++	owinbuf=shell->winbuf;
++	ofgbuf=shell->fgbuf;
++	obgbuf=shell->bgbuf;
++	orendbuf=shell->rendbuf;
++	ocharset=shell->charset;
++	otabline=shell->tabline;
++
++	shell->winbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->charset=(uint8_t *)vim_shell_malloc(width*height);
++	shell->tabline=(uint8_t *)vim_shell_malloc(width);
++	if(shell->winbuf==NULL || shell->fgbuf==NULL || shell->bgbuf==NULL || shell->rendbuf==NULL || shell->charset==NULL ||
++			shell->tabline==NULL)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		if(shell->winbuf) vim_shell_free(shell->winbuf);
++		if(shell->fgbuf) vim_shell_free(shell->fgbuf);
++		if(shell->bgbuf) vim_shell_free(shell->bgbuf);
++		if(shell->rendbuf) vim_shell_free(shell->rendbuf);
++		if(shell->charset) vim_shell_free(shell->charset);
++		if(shell->tabline) vim_shell_free(shell->tabline);
++
++		/*
++		 * Reassign the old buffers, they are still valid. And bring the shell
++		 * back to a sane state.
++		 */
++		shell->winbuf=owinbuf;
++		shell->fgbuf=ofgbuf;
++		shell->bgbuf=obgbuf;
++		shell->rendbuf=orendbuf;
++		shell->charset=ocharset;
++		shell->tabline=otabline;
++
++		shell->size_x=oldwidth;
++		shell->size_y=oldheight;
++
++		return -1;
++	}
++	memset(shell->winbuf, ' ', width*height);
++	memset(shell->fgbuf, shell->fgcolor, width*height);
++	memset(shell->bgbuf, shell->bgcolor, width*height);
++	memset(shell->rendbuf, 0, width*height);
++	memset(shell->charset, 0, width*height);
++	memset(shell->tabline, 0, width);
++
++	CHILDDEBUGPRINTF( "%s: width = %d, height = %d, oldwidth = %d, oldheight = %d\n",__FUNCTION__,width,height,
++			oldwidth,oldheight);
++
++	/*
++	 * copy over the old contents of the screen, line by line (!)
++	 */
++	len=(oldwidth<width ? oldwidth : width);
++	vlen=(oldheight<height ? oldheight : height);
++	for(y=0;y<vlen;y++)
++	{
++		int y_off;
++		y_off=oldheight-vlen;
++		memcpy(shell->winbuf+y*width, owinbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->fgbuf+y*width, ofgbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->bgbuf+y*width, obgbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->rendbuf+y*width, orendbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->charset+y*width, ocharset+(y+y_off)*oldwidth, len);
++	}
++	memcpy(shell->tabline, otabline, len);
++
++	/*
++	 * free the old contents
++	 */
++	vim_shell_free(owinbuf);
++	vim_shell_free(ofgbuf);
++	vim_shell_free(obgbuf);
++	vim_shell_free(orendbuf);
++	vim_shell_free(otabline);
++	vim_shell_free(ocharset);
++
++	/*
++	 * Correct tabs
++	 */
++	if(oldwidth<width)
++	{
++		for(x=oldwidth;x<width;x++)
++		{
++			if((x+1)%8==0 && x+1<width)
++				shell->tabline[x]=1;
++		}
++	}
++
++	/*
++	 * Correct cursor
++	 */
++	if(shell->cursor_x>=shell->size_x)
++		shell->cursor_x=shell->size_x-1;
++	if(shell->cursor_y>=shell->size_y)
++		shell->cursor_y=shell->size_y-1;
++
++	/*
++	 * Update scroll region
++	 */
++	shell->scroll_top_margin=0;
++	shell->scroll_bottom_margin=shell->size_y-1;
++
++	/*
++	 * Invalidate the vimshell screen buffer, so vim_shell_redraw redraws the whole
++	 * screen.
++	 */
++	shell->force_redraw=1;
++
++	return 0;
++}
++
++/*
++ * Resizes the shell.
++ * It reallocates all the size dependant buffers and instructs the shell to change
++ * its size.
++ * The width and height parameters are the *desired* width and height. The actual
++ * width and height is dependant on wether all windows that currently render this shell
++ * are able to display this width and height.
++ */
++void vim_shell_resize(struct vim_shell_window *shell, int want_width, int want_height)
++{
++	int width, height;
++	struct winsize ws;
++	win_T *win;
++
++	width=want_width;
++	height=want_height;
++	FOR_ALL_WINDOWS(win)
++	{
++		if(win->w_buffer && win->w_buffer->is_shell && win->w_buffer->shell==shell)
++		{
++			if(win->w_width<width)
++				width=win->w_width;
++			if(win->w_height<height)
++				height=win->w_height;
++		}
++	}
++
++	CHILDDEBUGPRINTF( "%s: resizing to %d, %d\n",__FUNCTION__,width,height);
++
++	if(internal_screenbuf_resize(shell, width, height)<0)
++	{
++		CHILDDEBUGPRINTF("%s: error while resizing.\n", __FUNCTION__);
++		return;
++	}
++	if(shell->alt!=NULL)
++	{
++		if(internal_screenbuf_resize(shell->alt, width, height)<0)
++		{
++			CHILDDEBUGPRINTF("%s: error while resizing the backup screen. Recovering...\n", __FUNCTION__);
++
++			/*
++			 * We now really have a problem. The main shell window is already
++			 * resized and this one didn't work. What should we do? Just destroy the screen
++			 * backup so it never gets restored. internal_screenbuf_resize already did
++			 * the job to of freeing the SINGle buffers, we just have to free the remaining struct.
++			 */
++			vim_shell_free(shell->alt);
++			shell->alt=NULL;
++		}
++	}
++
++	/*
++	 * Tell the shell that the size has changed.
++	 */
++	ws.ws_row=height;
++	ws.ws_col=width;
++	ws.ws_xpixel=0;
++	ws.ws_ypixel=0;
++	if(ioctl(shell->fd_master, TIOCSWINSZ, &ws)<0)
++	{
++		CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
++				__FUNCTION__,strerror(errno));
++	}
++}
++
++/*
++ * Draws the Shell-Buffer into the VIM-Window.
++ */
++void vim_shell_redraw(struct vim_shell_window *shell, win_T *win)
++{
++	int x, y;
++	int win_row, win_col;
++	int off;
++	int last_set_fg, last_set_bg;
++	int cs_state;
++	int term_is_bold, term_is_underline, term_is_negative;
++	int saved_screen_cur_row, saved_screen_cur_col;
++	int force_redraw;
++	int using_gui=0;
++	int t_colors_original=t_colors;
++
++	if(t_colors>15)
++	{
++		t_colors = 15;
++	}
++
++#ifdef FEAT_GUI
++	if(gui.in_use)
++	{
++		using_gui=1;
++	}
++#endif
++
++	win_row=W_WINROW(win);
++	win_col=W_WINCOL(win);
++
++	force_redraw=shell->force_redraw;
++
++	// invalidate the color cache
++	last_set_fg=last_set_bg=-1;
++	cs_state=VIMSHELL_CHARSET_USASCII;
++
++	saved_screen_cur_row=screen_cur_row;
++	saved_screen_cur_col=screen_cur_col;
++
++	// go to normal mode
++	term_is_bold=term_is_underline=term_is_negative=0;
++	screen_stop_highlight();
++
++	for(y=0;y<shell->size_y;y++)
++	{
++		size_t index=y*shell->size_x;
++		int skipped, y_reposition_necessary;
++
++		off=LineOffset[win_row+y]+win_col;
++		skipped=0;
++		y_reposition_necessary=1;
++		for(x=0;x<shell->size_x;x++)
++		{
++			uint8_t c=shell->winbuf[index];
++			sattr_T r=(sattr_T)shell->rendbuf[index];
++			uint8_t fg=shell->fgbuf[index];
++			uint8_t bg=shell->bgbuf[index];
++			uint8_t cs=shell->charset[index];
++			uint8_t fg_color=fg&0xF;
++			uint8_t bg_color=bg&0xF;
++			if(t_colors > 15)
++			{
++				bg_color=0x00;
++				fg_color=0x03;
++			}
++
++			/*
++			 * Switch terminal charset if necessary
++			 */
++			if(cs_state!=cs)
++			{
++				cs_state=cs;
++				if(cs==VIMSHELL_CHARSET_USASCII)
++				{
++					// VIMSHELL TODO: make a term code out of this hack
++					out_str_nf("\033(B");
++					CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
++				}
++				else if(cs==VIMSHELL_CHARSET_DRAWING)
++				{
++					// VIMSHELL TODO: make a term code out of this hack
++					out_str_nf("\033(0");
++					CHILDDEBUGPRINTF( "%s: switched terminal to alternate charset\n",__FUNCTION__);
++				}
++			}
++
++			/*
++			 * Store the foreground and background color along with the rendering attributes.
++			 */
++			r |= (fg&0x0F)<<12 | (bg&0x0F)<<8;
++
++			/*
++			 * Only do an update if render attributes or the character
++			 * has changed at this position.
++			 */
++			if(ScreenLines[off]!=c || ScreenAttrs[off]!=r || force_redraw)
++			{
++				// render attributes
++				if( ((r & RENDITION_BOLD)==0) == (term_is_bold==0) &&
++						((r & RENDITION_UNDERSCORE)==0) == (term_is_underline==0) &&
++						((r & RENDITION_NEGATIVE)==0) == (term_is_negative==0))
++				{
++					/*
++					 * already in the right rendition mode ...
++					 */
++				}
++				else if(using_gui==0)
++				{
++					out_str_nf(T_ME);
++					term_is_bold=term_is_underline=term_is_negative=0;
++					last_set_fg=last_set_bg=-1;
++					if ((r & RENDITION_BOLD) && !term_is_bold)
++					{
++						if(T_MD!=NULL)
++							out_str_nf(T_MD);
++						term_is_bold=1;
++					}
++					if ((r & RENDITION_UNDERSCORE) && !term_is_underline)
++					{
++						if(T_US != NULL)
++							out_str_nf(T_US);
++						term_is_underline=1;
++					}
++					if ((r & RENDITION_NEGATIVE) && !term_is_negative)
++					{
++						if(T_MR!=NULL)
++							out_str_nf(T_MR);
++						term_is_negative=1;
++					}
++				}
++
++				// colors
++				if(t_colors > 1 && using_gui==0)
++				{
++					// VIMSHELL TODO: not every terminal will understand these colors ...
++					// look at tag:cterm_normal_fg_color
++					if(last_set_fg!=fg_color)
++					{
++						term_fg_color(fg_color);
++						last_set_fg=fg_color;
++					}
++					if(last_set_bg!=bg_color)
++					{
++						term_bg_color(bg_color);
++						last_set_bg=bg_color;
++					}
++				}
++
++				ScreenLines[off]=c;
++				ScreenAttrs[off]=r;
++
++				if(y_reposition_necessary || skipped>0)
++				{
++					/*
++					 * Bring the cursor to where we need it.
++					 */
++					term_windgoto(win_row+y, win_col+x);
++					skipped=0;
++					y_reposition_necessary=0;
++				}
++
++				// print it
++				out_char(c);
++			}
++			else
++			{
++				skipped++;
++			}
++
++			off++;
++			index++;
++		}
++	}
++	/*
++	 * Always leave this function with the normal ASCII charset enabled and
++	 * with sane rendering attributes (normal mode).
++	 */
++	if(cs_state!=VIMSHELL_CHARSET_USASCII)
++	{
++		// VIMSHELL TODO: make a term code out of this hack
++		out_str_nf("\033(B");
++		CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
++	}
++
++	/*
++	 * Move the cursor to where VIM thinks it is :)
++	 */
++	term_windgoto(saved_screen_cur_row, saved_screen_cur_col);
++
++	/*
++	 * Position the cursor.
++	 * VIMSHELL TODO: we could cache that, e.g. when the cursor didn't move don't turn
++	 * it on again etc.
++	 */
++	win->w_wrow=shell->cursor_y;
++	win->w_wcol=shell->cursor_x;
++	setcursor();
++	cursor_on();
++
++	/*
++	 * Restore the rendering attributes
++	 */
++	out_str_nf(T_ME);
++	screen_start_highlight(screen_attr);
++	out_flush();
++
++	if(shell->force_redraw)
++		shell->force_redraw=0;
++
++	t_colors = t_colors_original;
++}
++
++/*
++ * Really do the read, finally :)
++ * Returns 1 if the contents of the window are VALID (in VIM speak)
++ * Returns 2 if the contents have to be CLEARed (after the shell has died)
++ */
++int vim_shell_do_read_lowlevel(buf_T *buf)
++{
++	int rval=1;
++	if(vim_shell_read(buf->shell)<0)
++	{
++		/*
++		 * Shell died? Cleanup. Also remove the RO attribute from the
++		 * buffer.
++		 */
++		vim_shell_delete(buf);
++		rval=2;
++	}
++
++	return rval;
++}
++
++/*
++ * This function is called from two places: os_unix.c and ui.c, and handles
++ * shell reads that are necessary because a select() became ready. This function
++ * is here to avoid identical code in both places.
++ * It returns the number of shell-reads.
++ * If there was no activity in any of the shells, it returns 0.
++ */
++int vim_shell_do_read_select(fd_set rfds)
++{
++	/*
++	 * Loop through all buffers and see if they are vimshells.
++	 * If yes, check if there are read events ready for the appropriate
++	 * fds. If so, call the shell's read handler.
++	 */
++	buf_T *buf;
++	int did_redraw=0;
++	int rval=0;
++
++	for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++	{
++		if(buf->is_shell != 0)
++		{
++			if(FD_ISSET(buf->shell->fd_master, &rfds))
++			{
++				int r;
++
++				r=vim_shell_do_read_lowlevel(buf);
++				if(r>did_redraw)
++					did_redraw=r;
++
++				rval++;
++
++				if(r==1 && updating_screen==FALSE)
++					redraw_buf_later(buf, VALID);
++				else if(r==2 && updating_screen==FALSE)
++					redraw_buf_later(buf, CLEAR);
++			}
++		}
++	}
++
++	/*
++	 * Only redraw if we aren't currently redrawing, to avoid endless recursions.
++	 * update_screen calls win_update, which calls win_line, which calls breakcheck,
++	 * which again calls RealWaitForChar which calls this function ...
++	 */
++	if(updating_screen==FALSE)
++	{
++		if(did_redraw==1)
++		{
++			update_screen(VALID);
++		}
++		else if(did_redraw==2 || did_redraw==3)
++		{
++			update_screen(CLEAR);
++			out_flush();
++		}
++	}
++
++	return rval;
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.h ./src/vim_shell.h
+--- ../vim72.orig/src/vim_shell.h	1970-01-01 01:00:00.000000000 +0100
++++ ./src/vim_shell.h	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,273 @@
++/*
++ * vim_shell.h
++ *
++ * Global include file for VIM-Shell. Defines structures and interfaces.
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ * $Id$
++ */
++
++#ifndef __VIMSHELL_H
++
++#define __VIMSHELL_H
++
++#include "vim.h"
++
++#include <stdio.h>
++#ifdef HAVE_STDINT_H
++#include <stdint.h>
++#endif
++#include <sys/types.h>
++#include <sys/select.h>
++
++/*
++ * Master debug flag. Disable this and no debug messages at all will
++ * be written anywhere.
++ */
++//#define VIMSHELL_DEBUG
++
++/*
++ * Rendition constants
++ */
++#define RENDITION_BOLD 1
++#define RENDITION_UNDERSCORE 2
++#define RENDITION_BLINK 4
++#define RENDITION_NEGATIVE 8
++#define RENDITION_DIM 16
++#define RENDITION_HIDDEN 32
++
++/*
++ * charset constants
++ */
++#define VIMSHELL_CHARSET_USASCII 0
++#define VIMSHELL_CHARSET_DRAWING 1
++
++/*
++ * Color constants
++ */
++#define VIMSHELL_COLOR_BLACK 0
++#define VIMSHELL_COLOR_RED 1
++#define VIMSHELL_COLOR_GREEN 2
++#define VIMSHELL_COLOR_YELLOW 3
++#define VIMSHELL_COLOR_BLUE 4
++#define VIMSHELL_COLOR_MAGENTA 5
++#define VIMSHELL_COLOR_CYAN 6
++#define VIMSHELL_COLOR_WHITE 7
++#define VIMSHELL_COLOR_DEFAULT 9
++
++#define vim_shell_malloc alloc
++#define vim_shell_free vim_free
++
++/*
++ * The main vim_shell_window struct.
++ * Holds everything that is needed to know about a single
++ * vim shell. (like file descriptors, window buffers, window
++ * positions, etc)
++ */
++struct vim_shell_window
++{
++	/*
++	 * current dimensions of the window
++	 */
++	uint16_t size_x;
++	uint16_t size_y;
++
++	/*
++	 * cursor position and visible flag
++	 */
++	uint16_t cursor_x;
++	uint16_t cursor_y;
++	uint16_t cursor_visible;
++
++	/*
++	 * Saved cursor positions (ESC 7, ESC 8)
++	 */
++	uint16_t saved_cursor_x;
++	uint16_t saved_cursor_y;
++
++	/*
++	 * We support the xterm title hack and store the title in this buffer.
++	 */
++	char windowtitle[50];
++
++	/*
++	 * The output buffer. This is necessary because writes to the shell can be delayed,
++	 * e.g. if we are waiting for an incoming ESC sequence to complete.
++	 */
++	uint8_t outbuf[100];
++	uint8_t outbuf_pos;
++
++	/*
++	 * Pointer to the window buffer.
++	 * The window buffer is the internal representation of the
++	 * window's content. The vim shell receives characters from
++	 * the terminal, which the terminal emulation translates into
++	 * e.g. cursor positions or actual characters. These are placed
++	 * here at the right screen position. Its size is size_y*size_x.
++	 */
++	uint8_t *winbuf;
++	uint8_t *fgbuf;
++	uint8_t *bgbuf;
++	uint8_t *rendbuf;
++	uint8_t *charset;
++
++	/*
++	 * The tabulator line. It represents a single row. Zero means no
++	 * tab at this position, 1 means there is a tab.
++	 */
++	uint8_t *tabline;
++
++	/*
++	 * These buffers hold what's currently physical on the screen.
++	 * Note, not on the "virtual" screen, that is the image of the shell,
++	 * but the real screen that is printed out in vim_shell_redraw.
++	 * This is mainly to implement caching features...
++	 * We hold here:
++	 * 1 byte foreground-color
++	 * 1 byte background-color
++	 * 1 byte rendering attributes
++	 * 1 byte the actual character
++	 */
++	uint32_t *phys_screen;
++
++	/*
++	 * Flag that determines if we are right in the middle of an
++	 * escape sequence coming in.
++	 */
++	uint8_t in_esc_sequence;
++
++	/*
++	 * Buffer for a escape sequence in progress (see in_esc_sequence).
++	 */
++	uint8_t esc_sequence[50];
++
++	/*
++	 * Auto-Margin enabled?
++	 */
++	uint8_t wraparound;
++
++	/*
++	 * Caused the last character a warp around?
++	 */
++	uint8_t just_wrapped_around;
++
++	/*
++	 * The currently used rendition of the shell.
++	 */
++	uint8_t rendition;
++	uint8_t saved_rendition;
++
++	/*
++	 * The currently active colors.
++	 */
++	uint8_t fgcolor;
++	uint8_t bgcolor;
++	uint8_t saved_fgcolor;
++	uint8_t saved_bgcolor;
++
++	/*
++	 * Scroll region.
++	 */
++	uint8_t scroll_top_margin;
++	uint8_t scroll_bottom_margin;
++
++	/*
++	 * Charset configuration.
++	 */
++	uint8_t G0_charset;
++	uint8_t G1_charset;
++	uint8_t active_charset;
++	uint8_t saved_G0_charset;
++	uint8_t saved_G1_charset;
++	uint8_t saved_active_charset;
++
++	/*
++	 * Mode switches.
++	 */
++	uint8_t application_keypad_mode;
++	uint8_t application_cursor_mode;
++	uint8_t saved_application_keypad_mode;
++	uint8_t saved_application_cursor_mode;
++
++	uint8_t insert_mode;
++	uint8_t saved_insert_mode;
++
++	/*
++	 * This flag determines if the shell should be completely redrawn in the next
++	 * vim_shell_redraw, regardless of what we think to know about the screen.
++	 */
++	uint8_t force_redraw;
++
++	/*
++	 * Pointer to the alternate screen. If NULL, there is no alternate screen.
++	 * If not NULL, this holds a backup of the screen contents and properties
++	 * before the screen switch. Switching back means to copy back the contents
++	 * of the alternate screen to the main screen and freeing the alternate screen.
++	 */
++	struct vim_shell_window *alt;
++
++	/*
++	 * file descriptor of the master side of the pty
++	 */
++	int fd_master;
++
++	/*
++	 * pid of the subshell
++	 */
++	pid_t pid;
++
++};
++
++/*
++ * This is set when something goes wrong in one of the
++ * vim_shell functions.
++ */
++extern int vimshell_errno;
++
++/*
++ * The debug handle where debug-messages will be written
++ */
++extern FILE *vimshell_debug_fp;
++
++#define VIMSHELL_SUCCESS 0
++#define VIMSHELL_OUT_OF_MEMORY 1
++#define VIMSHELL_FORKPTY_ERROR 2
++#define VIMSHELL_READ_ERROR 3
++#define VIMSHELL_WRITE_ERROR 4
++#define VIMSHELL_EXECV_ERROR 5
++#define VIMSHELL_SIGACTION_ERROR 6
++#define VIMSHELL_READ_EOF 7
++#define VIMSHELL_FCNTL_ERROR 8
++
++/*
++ * vim_shell.c
++ */
++extern int vim_shell_init();
++extern struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height);
++extern int vim_shell_start(struct vim_shell_window *shell, char *argv[]);
++extern char *vim_shell_strerror();
++extern int vim_shell_read(struct vim_shell_window *shell);
++extern int vim_shell_write(struct vim_shell_window *shell, int c);
++extern void vim_shell_redraw(struct vim_shell_window *shell, win_T *win);
++extern int vim_shell_do_read_select(fd_set rfds);
++extern int vim_shell_do_read_lowlevel(buf_T *buf);
++extern void vim_shell_delete(buf_T *buf);
++extern void vim_shell_resize(struct vim_shell_window *shell, int width, int height);
++
++/*
++ * terminal.c
++ */
++extern void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len);
++extern int vim_shell_terminal_output(struct vim_shell_window *shell, int c);
++
++/*
++ * screen.c
++ */
++extern int screen_cur_row, screen_cur_col;	/* last known cursor position */
++extern void screen_start_highlight __ARGS((int attr));
++extern int screen_attr;
++
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/window.c ./src/window.c
+--- ../vim72.orig/src/window.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/window.c	2009-10-02 13:39:57.000000000 +0100
+@@ -119,6 +119,12 @@
+ # define CHECK_CMDWIN
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++# define CHECK_VIMSHELL if (curwin->w_buffer->is_shell != 0) { EMSG("VIMSHELL: command not available for shell windows"); break; }
++#else
++# define CHECK_VIMSHELL
++#endif
++
+     switch (nchar)
+     {
+ /* split current window in two parts, horizontally */
+@@ -486,6 +492,7 @@
+ #if defined(FEAT_QUICKFIX)
+     case '}':
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 		if (Prenum)
+ 		    g_do_tagpreview = Prenum;
+ 		else
+@@ -495,6 +502,7 @@
+     case ']':
+     case Ctrl_RSB:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ #ifdef FEAT_VISUAL
+ 		reset_VIsual_and_resel();	/* stop Visual mode */
+ #endif
+@@ -515,6 +523,7 @@
+     case Ctrl_F:
+ wingotofile:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 
+ 		ptr = grab_file_name(Prenum1, &lnum);
+ 		if (ptr != NULL)
+@@ -553,6 +562,7 @@
+     case 'd':			    /* Go to definition, using 'define' */
+     case Ctrl_D:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 		if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
+ 		    break;
+ 		find_pattern_in_path(ptr, 0, len, TRUE,
+@@ -584,6 +594,7 @@
+     case 'g':
+     case Ctrl_G:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ #ifdef USE_ON_FLY_SCROLL
+ 		dont_scroll = TRUE;		/* disallow scrolling here */
+ #endif
+@@ -5555,6 +5566,15 @@
+     wp->w_redr_status = TRUE;
+ #endif
+     invalidate_botline_win(wp);
++
++#ifdef FEAT_VIMSHELL
++    if(wp->w_buffer->is_shell!=0)
++    {
++	struct vim_shell_window *shell=wp->w_buffer->shell;
++	vim_shell_resize(shell, shell->size_x, height);
++	redraw_win_later(wp, CLEAR);
++    }
++#endif
+ }
+ 
+ #ifdef FEAT_VERTSPLIT
+@@ -5577,6 +5597,14 @@
+     }
+     redraw_win_later(wp, NOT_VALID);
+     wp->w_redr_status = TRUE;
++#ifdef FEAT_VIMSHELL
++    if(wp->w_buffer->is_shell!=0)
++    {
++	struct vim_shell_window *shell=wp->w_buffer->shell;
++	vim_shell_resize(shell, width, shell->size_y);
++	redraw_win_later(wp, CLEAR);
++    }
++#endif
+ }
+ #endif
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/test.txt ./test.txt
+--- ../vim72.orig/test.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./test.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,2 @@
++asdfasdfA
++:q

Modified: trunk/dports/editors/vim-app/Portfile
===================================================================
--- trunk/dports/editors/vim-app/Portfile	2009-10-27 14:53:46 UTC (rev 59930)
+++ trunk/dports/editors/vim-app/Portfile	2009-10-27 16:38:15 UTC (rev 59931)
@@ -125,6 +125,11 @@
     configure.args-append --with-xim
 }
 
+variant shell description {Enables shell windows} {
+    # Patch taken from http://www.wana.at/vimshell/
+    patchfiles-append       patch-vimshell.diff
+}
+
 variant perl description {Enable Perl scripting} {
     configure.args-append   --enable-perlinterp
     depends_lib-append      path:bin/perl:perl5

Added: trunk/dports/editors/vim-app/files/patch-vimshell.diff
===================================================================
--- trunk/dports/editors/vim-app/files/patch-vimshell.diff	                        (rev 0)
+++ trunk/dports/editors/vim-app/files/patch-vimshell.diff	2009-10-27 16:38:15 UTC (rev 59931)
@@ -0,0 +1,4565 @@
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/README_vimshell.txt ./README_vimshell.txt
+--- ../vim72.orig/README_vimshell.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./README_vimshell.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,12 @@
++TESTING
++=======
++
++shell-read with poll(2)
++shell-read with select(2) - works
++compiling VIM without builtin terminals - only termcap or terminfo - works
++GUI-VIM ohne builtin_terms ?
++
++DOCUMENTATION
++=============
++
++See :help vimshell for documentation.
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/runtime/doc/vimshell.txt ./runtime/doc/vimshell.txt
+--- ../vim72.orig/runtime/doc/vimshell.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./runtime/doc/vimshell.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,93 @@
++*vimshell.txt*   For Vim version 7.0.  Last change: 2006 Sep 2
++
++
++		  VIM REFERENCE MANUAL    by Bram Moolenaar
++
++
++The VIM-Shell                                            *vimshell*
++
++1. What is VIM-Shell?
++
++The VIM-shell is a extension for VIM, a very popular programmer's editor for
++many platforms, written by Bram Moolenaar et al. VIM features split windows,
++and this patch makes it possible to start shells in those windows. It is only
++available for POSIX systems like Linux, FreeBSD, OpenBSD, NetBSD and MacOS X.
++I don't think the Windows-VIM needs such a patch, because I think the command
++line there isn't really popular.
++
++==============================================================================
++2. How to use the VIM-Shell
++
++2.1 General concept: ":vimshell"
++
++The whole VIM-Shell functionality is hidden behind one single command:
++:vimshell.
++
++:vimshell[!] [params] tries to close your active buffer and creates a new one.
++This behaves exactly the same as the :enew command (see :help enew im VIM for
++details). If you have local modifications to your buffer, the command will be
++aborted (but you can override this by adding a ! at the end, in this case the
++active buffer will be dismissed in any case). The window containing this empty
++buffer is then converted to a VIM-Shell.
++
++:vimshell
++
++starts a VIM-Shell in your current window. I strongly suggest you open a new
++window before doing that. By default, without any parameters, /bin/sh will be
++spawned.
++
++:vimshell bash
++
++When called with parameters, VIM-Shell passes these parameters verbatim to
++execvp when starting a shell. Your current $PATH will be searched for the
++command.
++
++:vimshell irssi -n anonymous -c vienna.irc.at
++
++starts the textmode IRC client "irssi" with the abovementioned parameters.
++
++:vimshell mutt
++
++Never lose track of your e-mails while working in VIM!
++
++When you exit such a shell, or the program running in it terminates, the
++buffer will be converted back to a normal, empty VIM-buffer. The window will
++not be closed.
++
++2.2 Navigation
++
++When the currently active window is a VIM-Shell, every character entered gets
++routed to the shell, and no mapping expansion takes place. VIM doesn't get any
++notice of the characters that you type in a VIM-Shell.
++
++The big exception is Ctrl_W, which is passed through to VIM, so you can close
++the VIM-shell (Ctrl_W + c), change to another window, resize the window, etc.
++Key mappings
++
++Because I feel that opening up a window and then typing :vimshell is a bit
++cumbersome, I suggest you use the following key mappings in your .vimrc:
++
++	" VIM-Shell
++	" Ctrl_W e opens up a vimshell in a horizontally split window
++	" Ctrl_W E opens up a vimshell in a vertically split window
++	" The shell window will be auto closed after termination
++	nmap <C-W>e :new \| vimshell bash<CR>
++	nmap <C-W>E :vnew \| vimshell bash<CR>
++
++Just hitting Ctrl_W and e to drop a shell window in your VIM session is
++really, really comfortable :-)
++
++This is a small introduction on how to use the new features in your
++VIM-Shell-enabled VIM.
++
++==============================================================================
++3. Authorship
++
++The VIM-Shell was written in 2004, 2005, 2006 by Thomas Wana <thomas at wana.at>.
++Homepage: http://www.wana.at/vimshell/
++
++The VIM-Shell is published under the GNU GPL license (which is compatible with
++the VIM license). The copyright remains by the author.
++
++==============================================================================
++ vim:tw=78:ts=8:ft=help:norl:
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/Makefile ./src/Makefile
+--- ../vim72.orig/src/Makefile	2009-10-02 13:39:24.000000000 +0100
++++ ./src/Makefile	2009-10-02 13:39:57.000000000 +0100
+@@ -841,7 +841,6 @@
+ ###	 For LynxOS 3.1.0, tested on PC
+ #EXTRA_LIBS= -lXext -lSM -lICE -lnetinet -lXmu
+ 
+-
+ ### (V)  For CX/UX 6.2	(on Harris/Concurrent NightHawk 4800, 5800). Remove
+ ###	 -Qtarget if only in a 5800 environment.  (Kipp E. Howard)
+ #CFLAGS = -O -Qtarget=m88110compat
+@@ -1291,7 +1290,6 @@
+ # Use this for cproto 3 patchlevel 7 or above (use "cproto -V" to check):
+ PROTO_FLAGS = -m -M__ARGS -d -E"$(CPP)" $(NO_ATTR)
+ 
+-
+ ################################################
+ ##   no changes required below this line      ##
+ ################################################
+@@ -1410,6 +1408,8 @@
+ 	auto/pathdef.c \
+ 	popupmnu.c \
+ 	quickfix.c \
++	vim_shell.c \
++	terminal.c \
+ 	regexp.c \
+ 	screen.c \
+ 	search.c \
+@@ -1482,6 +1482,8 @@
+ 	objects/pathdef.o \
+ 	objects/popupmnu.o \
+ 	objects/quickfix.o \
++	objects/vim_shell.o \
++	objects/terminal.o \
+ 	objects/regexp.o \
+ 	objects/screen.o \
+ 	objects/search.o \
+@@ -2536,6 +2538,12 @@
+ objects/quickfix.o: quickfix.c
+ 	$(CCC) -o $@ quickfix.c
+ 
++objects/vim_shell.o: vim_shell.c
++	$(CCC) -o $@ vim_shell.c
++
++objects/terminal.o: terminal.c
++	$(CCC) -o $@ terminal.c
++
+ objects/regexp.o: regexp.c
+ 	$(CCC) -o $@ regexp.c
+ 
+@@ -2803,6 +2811,8 @@
+   auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
+   regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
+   globals.h farsi.h arabic.h
++objects/terminal.o: terminal.c vim_shell.h
++objects/vim_shell.o: vim_shell.c vim_shell.h
+ objects/regexp.o: regexp.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+   ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+   gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/auto/configure ./src/auto/configure
+--- ../vim72.orig/src/auto/configure	2009-10-02 13:39:25.000000000 +0100
++++ ./src/auto/configure	2009-10-02 13:39:57.000000000 +0100
+@@ -17145,6 +17145,269 @@
+ fi
+ 
+ 
++if test "$(uname)" = "Darwin"; then
++      LIBS="$LIBS"
++else
++      LIBS="$LIBS -lutil"
++fi
++
++
++
++for ac_header in pty.h libutil.h stdint.h
++do
++as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++else
++  # Is the header compilable?
++echo "$as_me:$LINENO: checking $ac_header usability" >&5
++echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++$ac_includes_default
++#include <$ac_header>
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++  (eval $ac_compile) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; } &&
++	 { ac_try='test -s conftest.$ac_objext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  ac_header_compiler=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_header_compiler=no
++fi
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6
++
++# Is the header present?
++echo "$as_me:$LINENO: checking $ac_header presence" >&5
++echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#include <$ac_header>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } >/dev/null; then
++  if test -s conftest.err; then
++    ac_cpp_err=$ac_c_preproc_warn_flag
++    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
++  else
++    ac_cpp_err=
++  fi
++else
++  ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++  ac_header_preproc=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++  ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6
++
++# So?  What about this header?
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++  yes:no: )
++    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
++    ac_header_preproc=yes
++    ;;
++  no:yes:* )
++    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
++echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------------ ##
++## Report this to the AC_PACKAGE_NAME lists.  ##
++## ------------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
++esac
++echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  eval "$as_ac_Header=\$ac_header_preproc"
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++
++fi
++if test `eval echo '${'$as_ac_Header'}'` = yes; then
++  cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
++
++for ac_func in forkpty
++do
++as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
++echo "$as_me:$LINENO: checking for $ac_func" >&5
++echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
++if eval "test \"\${$as_ac_var+set}\" = set"; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
++   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
++#define $ac_func innocuous_$ac_func
++
++/* System header to define __stub macros and hopefully few prototypes,
++    which can conflict with char $ac_func (); below.
++    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++    <limits.h> exists even on freestanding compilers.  */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
++
++#undef $ac_func
++
++/* Override any gcc2 internal prototype to avoid an error.  */
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++/* We use char because int might match the return type of a gcc2
++   builtin and then its argument prototype would still apply.  */
++char $ac_func ();
++/* The GNU C library defines this for functions which it implements
++    to always fail with ENOSYS.  Some functions are actually named
++    something starting with __ and the normal name is an alias.  */
++#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
++choke me
++#else
++char (*f) () = $ac_func;
++#endif
++#ifdef __cplusplus
++}
++#endif
++
++int
++main ()
++{
++return f != $ac_func;
++  ;
++  return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++  (eval $ac_link) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; } &&
++	 { ac_try='test -s conftest$ac_exeext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  eval "$as_ac_var=yes"
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++eval "$as_ac_var=no"
++fi
++rm -f conftest.err conftest.$ac_objext \
++      conftest$ac_exeext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
++if test `eval echo '${'$as_ac_var'}'` = yes; then
++  cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++done
++
++if test $ac_cv_func_forkpty = no; then
++    { { echo "$as_me:$LINENO: error: vimshell needs forkpty - sorry." >&5
++echo "$as_me: error: vimshell needs forkpty - sorry." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++
+ ac_config_files="$ac_config_files auto/config.mk:config.mk.in"
+ 
+ cat >confcache <<\_ACEOF
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/buffer.c ./src/buffer.c
+--- ../vim72.orig/src/buffer.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/buffer.c	2009-10-02 13:39:57.000000000 +0100
+@@ -575,6 +575,17 @@
+ #ifdef FEAT_TCL
+     tcl_buffer_free(buf);
+ #endif
++#ifdef FEAT_VIMSHELL
++    if(buf->is_shell!=0)
++    {
++	/*
++	 * It is guaranteed that this buffer isn't connected to a
++	 * window anymore, or else we'd not come up here. So we can
++	 * savely scrap the shell here.
++	 */
++	vim_shell_delete(buf);
++    }
++#endif
+     u_blockfree(buf);		    /* free the memory allocated for undo */
+     ml_close(buf, TRUE);	    /* close and delete the memline/memfile */
+     buf->b_ml.ml_line_count = 0;    /* no lines in buffer */
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/colines.c ./src/colines.c
+--- ../vim72.orig/src/colines.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/colines.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,39 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <signal.h>
++#include <termios.h>
++#include <sys/types.h>
++#include <pty.h>
++
++void sigwinch(int arg)
++{
++	struct winsize ws;
++	printf("window size is now: ");
++
++	if(ioctl(0, TIOCGWINSZ, &ws)<0)
++	{
++		perror("ioctl");
++		return;
++	}
++	printf("rows = %d, cols = %d\n", ws.ws_row, ws.ws_col);
++}
++
++int main()
++{
++	struct sigaction sa;
++	sa.sa_handler=sigwinch;
++	sigemptyset(&sa.sa_mask);
++	sa.sa_flags=0;
++	if(sigaction(SIGWINCH, &sa, NULL)<0)
++	{
++		perror("sigaction");
++		return -1;
++	}
++	sigwinch(0);
++	while(1)
++	{
++		sleep(10);
++	}
++	return 0;
++}
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/config.h.in ./src/config.h.in
+--- ../vim72.orig/src/config.h.in	2009-10-02 13:39:24.000000000 +0100
++++ ./src/config.h.in	2009-10-02 13:39:57.000000000 +0100
+@@ -387,3 +387,8 @@
+ 
+ /* Define if you want XSMP interaction as well as vanilla swapfile safety */
+ #undef USE_XSMP_INTERACT
++
++/* VIMSHELL stuff */
++#undef HAVE_PTY_H
++#undef HAVE_LIBUTIL_H
++#undef HAVE_STDINT_H
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/configure.in ./src/configure.in
+--- ../vim72.orig/src/configure.in	2009-10-02 13:39:25.000000000 +0100
++++ ./src/configure.in	2009-10-02 13:39:57.000000000 +0100
+@@ -3241,6 +3241,23 @@
+ fi
+ AC_SUBST(DEPEND_CFLAGS_FILTER)
+ 
++dnl ------------------------------------------------------------------
++dnl VIMSHELL configure thingies
++dnl needs -lutil, but not on MacOS X
++dnl The $MACOSX variable isn't set on the Mac I can use for testing, so we
++dnl have to use other means to find out if this is a Mac. uname for example.
++if test "$(uname)" = "Darwin"; then
++      LIBS="$LIBS"
++else
++      LIBS="$LIBS -lutil"
++fi
++AC_CHECK_HEADERS(pty.h libutil.h stdint.h)
++AC_CHECK_FUNCS(forkpty)
++if test $ac_cv_func_forkpty = no; then
++    AC_MSG_ERROR(vimshell needs forkpty - sorry.)
++fi
++dnl ------------------------------------------------------------------
++
+ dnl write output files
+ AC_OUTPUT(auto/config.mk:config.mk.in)
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/eval.c ./src/eval.c
+--- ../vim72.orig/src/eval.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/eval.c	2009-10-02 13:39:57.000000000 +0100
+@@ -11836,6 +11836,9 @@
+ #if defined(UNIX) && defined(FEAT_X11)
+ 	"X11",
+ #endif
++#ifdef FEAT_VIMSHELL
++	"vimshell",
++#endif
+ 	NULL
+     };
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_cmds.h ./src/ex_cmds.h
+--- ../vim72.orig/src/ex_cmds.h	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ex_cmds.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1007,6 +1007,10 @@
+ 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+ EX(CMD_view,		"view",		ex_edit,
+ 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
++#ifdef FEAT_VIMSHELL
++EX(CMD_vimshell,	"vimshell",	ex_vimshell,
++			EXTRA|BANG|TRLBAR|CMDWIN),
++#endif
+ EX(CMD_vimgrep,		"vimgrep",	ex_vimgrep,
+ 			RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+ EX(CMD_vimgrepadd,	"vimgrepadd",	ex_vimgrep,
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_docmd.c ./src/ex_docmd.c
+--- ../vim72.orig/src/ex_docmd.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ex_docmd.c	2009-10-02 13:39:57.000000000 +0100
+@@ -143,6 +143,7 @@
+ static void	ex_quit __ARGS((exarg_T *eap));
+ static void	ex_cquit __ARGS((exarg_T *eap));
+ static void	ex_quit_all __ARGS((exarg_T *eap));
++static void	ex_vimshell __ARGS((exarg_T *eap));
+ #ifdef FEAT_WINDOWS
+ static void	ex_close __ARGS((exarg_T *eap));
+ static void	ex_win_close __ARGS((int forceit, win_T *win, tabpage_T *tp));
+@@ -11109,3 +11110,115 @@
+     ml_clearmarked();	   /* clear rest of the marks */
+ }
+ #endif
++
++#ifdef FEAT_VIMSHELL
++/*
++ * ":vimshell": creates an empty buffer in the current window and starts a
++ * VIM-Shell inside.
++ * ":vimshellac": same as "vimshell" but closes the window after the shell
++ * terminated (ac = "auto-close"). This is useful for redefinitions of 'Man'
++ * etc.
++ */
++    static void
++ex_vimshell(eap)
++    exarg_T	*eap;
++{
++    unsigned char *argv[50], argidx, *p;
++    unsigned char cmdline[500];
++    char cmdbuf[50];
++
++    if(curbuf->is_shell!=0)
++    {
++	emsg("VIMSHELL: current buffer is already a shell!");
++	return;
++    }
++
++    snprintf(cmdbuf, sizeof(cmdbuf), ":enew%s", eap->forceit==TRUE ? "!" : "");
++
++    /*
++     * Do a ":enew" command to get a new buffer in the current window.
++     * Also assures that we don't throw away any unsaved changes the user
++     * made to the previous buffer.
++     */
++    did_emsg=FALSE;
++    if(do_cmdline_cmd(cmdbuf)==FAIL || did_emsg==TRUE)
++    {
++	return;
++    }
++
++    /*
++     * Set buffer read only (the user can't write into it anyway, but just
++     * to make sure. We want to be able to close the buffer without any
++     * problems any time).
++     */
++    curbuf->b_p_ro=TRUE;
++
++    /*
++     * Parse command line arguments. If none given, default to '/bin/sh'
++     */
++    snprintf(cmdline, sizeof(cmdline), "%s", eap->arg);
++    p=cmdline;
++    argidx=0;
++    if(!strcmp(p, ""))
++    {
++	argv[0]="/bin/sh";
++    }
++    else
++    {
++	argv[argidx]=p;
++	do
++	{
++	    if(*p==' ')
++	    {
++		argidx++;
++		if(argidx+1 >= sizeof(argv)/sizeof(argv[0]))
++		{
++		    /*
++		     * Too many command line arguments, drop out
++		     */
++		    emsg("VIMSHELL: too many command line arguments");
++		    return;
++		}
++
++		/*
++		 * Convert all ' ' to \0
++		 */
++		for(;*p==' ';p++)
++		    *p=0;
++		if(*p!=0)
++		{
++		    argv[argidx]=p;
++		}
++	    }
++	} while(*p++);
++    }
++    argv[++argidx]=NULL;
++
++    /*
++     * Convert the current buffer into a shell window.
++     */
++    curbuf->shell=(struct vim_shell_window *)vim_shell_new(W_WIDTH(curwin), curwin->w_height);
++    if(curbuf->shell==NULL)
++    {
++	EMSG2("VIMSHELL: error creating a new shell: %s", vim_shell_strerror());
++	return;
++    }
++    curbuf->is_shell=1;
++    curbuf->gtk_input_id=0;
++
++    /*
++     * start the shell
++     */
++    if(vim_shell_start(curbuf->shell, (char **)argv)<0)
++    {
++	EMSG2("VIMSHELL: error starting the shell: %s", vim_shell_strerror());
++
++	vim_shell_delete(curbuf);
++	return;
++    }
++
++    /*
++     * we're up and running.
++     */
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/feature.h ./src/feature.h
+--- ../vim72.orig/src/feature.h	2009-10-02 13:39:26.000000000 +0100
++++ ./src/feature.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1267,6 +1267,15 @@
+ #endif
+ 
+ /*
++ * The VIM-Shell. Only works on UNIX for now (more specifically,
++ * only Linux, *BSD and MacOS X, others not tested. Generally, if
++ * a system has a forkpty call, it should be working.)
++ */
++#if defined(FEAT_NORMAL) && (defined(UNIX) || defined(MACOS_X))
++#define FEAT_VIMSHELL
++#endif
++
++/*
+  * +autochdir		'autochdir' option.
+  */
+ #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/gui_gtk_x11.c ./src/gui_gtk_x11.c
+--- ../vim72.orig/src/gui_gtk_x11.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/gui_gtk_x11.c	2009-10-02 13:39:57.000000000 +0100
+@@ -6470,6 +6470,65 @@
+ }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++/*
++ * VIM-Shell callback, called when a shell file descriptor has data
++ * available.
++ */
++    static void
++vimshell_request_cb(
++    gpointer	data,
++    gint	source_fd,
++    GdkInputCondition condition)
++{
++    buf_T *buf;
++    int did_redraw=0;
++
++    /*
++     * Search the right buffer.
++     */
++    for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++    {
++	if(buf->is_shell!=0 && buf->shell && buf->shell->fd_master==source_fd)
++	{
++	    int r;
++
++	    r=vim_shell_do_read_lowlevel(buf);
++	    if(r>did_redraw)
++		did_redraw=r;
++
++	    if(r==1 && updating_screen==FALSE)
++		redraw_buf_later(buf, VALID);
++	    else if(r==2)
++	    {
++		/*
++		 * Shell died, so remove the GTK-input
++		 * VIMSHELL TODO: this should really be happening inside vim_shell_delete
++		 */
++		gdk_input_remove(buf->gtk_input_id);
++		buf->gtk_input_id=0;
++		if(updating_screen==FALSE)
++		    redraw_buf_later(buf, CLEAR);
++	    }
++	}
++    }
++
++    if(updating_screen==FALSE)
++    {
++	if(did_redraw==1)
++	    update_screen(VALID);
++	else if(did_redraw==2)
++	{
++	    update_screen(CLEAR);
++	    out_flush();
++	}
++    }
++
++    if (gtk_main_level() > 0)
++	gtk_main_quit();
++}
++#endif
++
+ /*
+  * GUI input routine called by gui_wait_for_chars().  Waits for a character
+  * from the keyboard.
+@@ -6506,6 +6565,23 @@
+     }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    /*
++     * Go through all buffers, see if we have to add not yet added inputs
++     */
++    {
++	buf_T *buf;
++	for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++	{
++	    if(buf->is_shell!=0 && buf->shell && buf->gtk_input_id==0)
++	    {
++		buf->gtk_input_id=gdk_input_add(buf->shell->fd_master,
++			GDK_INPUT_READ, vimshell_request_cb, NULL);
++	    }
++	}
++    }
++#endif
++
+     timed_out = FALSE;
+ 
+     /* this timeout makes sure that we will return if no characters arrived in
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/main.c ./src/main.c
+--- ../vim72.orig/src/main.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/main.c	2009-10-02 13:39:57.000000000 +0100
+@@ -180,6 +180,10 @@
+      */
+     mch_early_init();
+ 
++#ifdef FEAT_VIMSHELL
++    vim_shell_init();
++#endif
++
+     /* Many variables are in "params" so that we can pass them to invoked
+      * functions without a lot of arguments.  "argc" and "argv" are also
+      * copied, so that they can be changed. */
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/move.c ./src/move.c
+--- ../vim72.orig/src/move.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/move.c	2009-10-02 13:39:57.000000000 +0100
+@@ -675,6 +675,14 @@
+     void
+ validate_cursor()
+ {
++#ifdef FEAT_VIMSHELL
++    /*
++     * The vimshell repositions its artificial cursor in vim_shell_redraw. Don't do the
++     * checks below.
++     */
++    if(curwin->w_buffer && curwin->w_buffer->is_shell!=0)
++	return;
++#endif
+     check_cursor_moved(curwin);
+     if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
+ 	curs_columns(TRUE);
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/normal.c ./src/normal.c
+--- ../vim72.orig/src/normal.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/normal.c	2009-10-02 13:41:52.000000000 +0100
+@@ -646,11 +646,50 @@
+     dont_scroll = FALSE;	/* allow scrolling here */
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    /*
++     * We reroute ALL characters to the shell, EXCEPT Ctrl_W, so all
++     * Window-Commands should still be working (not unimportant, think of
++     * leaving the window ...)
++     * VIMSHELL TODO: what about mouse commands, GUI commands, etc
++     */
++    if(curbuf->is_shell)
++    {
++      no_mapping++;
++      allow_keys++;
++      c = safe_vgetc();
++      no_mapping--;
++      allow_keys--;
++
++      if(curbuf->is_shell && c!=Ctrl_W)
++      {
++          if(vim_shell_write(curbuf->shell, c)<0)
++          {
++                  /*
++                   * The shell died, clean up
++                   */
++                  vim_shell_delete(curbuf);
++                  curbuf->is_shell=0;
++                  curbuf->b_p_ro=FALSE;
++
++                  redraw_later(CLEAR);
++                  update_screen(CLEAR);
++          }
++          return;
++      }
++    }
++    else
++    {
++      c = safe_vgetc();
++      LANGMAP_ADJUST(c, TRUE);
++    }
++#else
+     /*
+      * Get the command character from the user.
+      */
+     c = safe_vgetc();
+     LANGMAP_ADJUST(c, TRUE);
++#endif
+ 
+ #ifdef FEAT_VISUAL
+     /*
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/os_unix.c ./src/os_unix.c
+--- ../vim72.orig/src/os_unix.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/os_unix.c	2009-10-02 13:39:57.000000000 +0100
+@@ -4809,7 +4809,7 @@
+ # endif
+ #endif
+ #ifndef HAVE_SELECT
+-	struct pollfd   fds[5];
++	struct pollfd   fds[50];
+ 	int		nfd;
+ # ifdef FEAT_XCLIPBOARD
+ 	int		xterm_idx = -1;
+@@ -4820,6 +4820,15 @@
+ # ifdef USE_XSMP
+ 	int		xsmp_idx = -1;
+ # endif
++# ifdef FEAT_VIMSHELL
++	struct
++	{
++	    int idx;
++	    struct vim_shell_window *shell;
++	    buf_T *buffer;
++	}		vimshell_idxs[50];
++	int		vimshell_idx_cnt;
++# endif
+ 	int		towait = (int)msec;
+ 
+ # ifdef FEAT_MZSCHEME
+@@ -4870,6 +4879,49 @@
+ 	    nfd++;
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * Loop through all windows and see if they contain vimshells.
++	     * If yes, add the master-fd to the list of polled fds.
++	     */
++	    memset(vimshell_idxs, 0, sizeof(vimshell_idxs));
++	    vimshell_idx_cnt=0;
++	    for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
++	    {
++		buf_T *buf;
++		if(buf->is_shell!=0)
++		{
++		    vimshell_idxs[vimshell_idx_count].idx=nfd;
++		    vimshell_idxs[vimshell_idx_count].buffer=buf;
++		    vimshell_idxs[vimshell_idx_count].shell=buf->shell;
++
++		    /*
++		     * We will first run out of fds before we run out of
++		     * vimshell_idxs-slots, so no check here.
++		     */
++		    vimshell_idx_count++;
++
++		    if(buf->shell==NULL)
++		    {
++			// VIMSHELL TODO: error message here
++			continue;
++		    }
++		    fds[nfd].fd = buf->shell->fd_master;
++		    fds[nfd].events = POLLIN;
++		    nfd++;
++		    if(nfd>=sizeof(fds)/sizeof(fds[0]))
++		    {
++			/*
++			 * no more fds-slots left! aieeee
++			 */
++			// VIMSHELL TODO: issue a warning here or something
++			break;
++		    }
++		}
++	    }
++	}
++# endif
+ 
+ 	ret = poll(fds, nfd, towait);
+ # ifdef FEAT_MZSCHEME
+@@ -4923,6 +4975,38 @@
+ 		finished = FALSE;	/* Try again */
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++#error "VIMSHELL: probably doesn't work with poll(), never tested, sorry (use select)"
++	{
++	    /*
++	     * See if any of the shell's fds have a read request ready
++	     * If yes, call the shell's read handler.
++	     */
++	    int i;
++	    int did_redraw=0;
++	    for(i=0;i<vimshell_idx_cnt;i++)
++	    {
++		if(fds[vimshell_idxs[i].idx].revents & POLLIN)
++		{
++		    if(vim_shell_read(vimshell_idxs[i].shell)<0)
++		    {
++			// VIMSHELL TODO: handle error here
++			continue;
++		    }
++
++		    redraw_buf_later(vimshell_idxs[i].buffer, NOT_VALID);
++
++		    did_redraw=1;
++		}
++		// VIMSHELL TODO: handle POLLHUP here too (shell terminated)
++	    }
++	    if(did_redraw==1)
++	    {
++		update_screen(NOT_VALID);
++		out_flush();
++	    }
++	}
++# endif
+ 
+ 
+ #else /* HAVE_SELECT */
+@@ -5004,6 +5088,25 @@
+ 		maxfd = xsmp_icefd;
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * Loop through all windows and see if they contain vimshells.
++	     * If yes, add the master-fd to the list of fds
++	     */
++	    win_T *win;
++	    FOR_ALL_WINDOWS(win)
++	    {
++		buf_T *buf=win->w_buffer;
++		if(buf->is_shell!=0)
++		{
++		    FD_SET(buf->shell->fd_master, &rfds);
++		    if (maxfd < buf->shell->fd_master)
++			maxfd = buf->shell->fd_master;
++		}
++	    }
++	}
++# endif
+ 
+ # ifdef OLD_VMS
+ 	/* Old VMS as v6.2 and older have broken select(). It waits more than
+@@ -5081,6 +5184,16 @@
+ 	    }
+ 	}
+ # endif
++# ifdef FEAT_VIMSHELL
++	if((maxfd=vim_shell_do_read_select(rfds))!=0)
++	{
++	    ret-=maxfd;
++#  ifdef MAY_LOOP
++	    if (ret == 0)
++		finished = FALSE;   /* keep going if event was only one */
++#  endif
++	}
++# endif
+ 
+ #endif /* HAVE_SELECT */
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/screen.c ./src/screen.c
+--- ../vim72.orig/src/screen.c	2009-10-02 13:39:26.000000000 +0100
++++ ./src/screen.c	2009-10-02 13:39:57.000000000 +0100
+@@ -91,13 +91,21 @@
+ /*
+  * The attributes that are actually active for writing to the screen.
+  */
++#ifdef FEAT_VIMSHELL
++int		screen_attr = 0;
++#else
+ static int	screen_attr = 0;
++#endif
+ 
+ /*
+  * Positioning the cursor is reduced by remembering the last position.
+  * Mostly used by windgoto() and screen_char().
+  */
++#ifdef FEAT_VIMSHELL
++int		screen_cur_row, screen_cur_col;	/* last known cursor position */
++#else
+ static int	screen_cur_row, screen_cur_col;	/* last known cursor position */
++#endif
+ 
+ #ifdef FEAT_SEARCH_EXTRA
+ static match_T search_hl;	/* used for 'hlsearch' highlight matching */
+@@ -141,7 +149,11 @@
+ static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
+ static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
+ #endif
++#ifdef FEAT_VIMSHELL
++void screen_start_highlight __ARGS((int attr));
++#else
+ static void screen_start_highlight __ARGS((int attr));
++#endif
+ static void screen_char __ARGS((unsigned off, int row, int col));
+ #ifdef FEAT_MBYTE
+ static void screen_char_2 __ARGS((unsigned off, int row, int col));
+@@ -833,6 +845,7 @@
+     }
+ #endif
+ 
++
+ #ifdef FEAT_SEARCH_EXTRA
+     /* Setup for match and 'hlsearch' highlighting.  Disable any previous
+      * match */
+@@ -1477,6 +1490,7 @@
+     win_foldinfo.fi_level = 0;
+ #endif
+ 
++
+     /*
+      * Update all the window rows.
+      */
+@@ -1903,9 +1917,19 @@
+ 	else if (dollar_vcol == 0)
+ 	    wp->w_botline = lnum;
+ 
++#ifdef FEAT_VIMSHELL
++	/*
++	 * We don't want '~' to appear right in the middle of our shells ...
++	 */
++	if(wp->w_buffer->is_shell==0)
++	{
++#endif
+ 	/* make sure the rest of the screen is blank */
+ 	/* put '~'s on rows that aren't part of the file. */
+ 	win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_AT);
++#ifdef FEAT_VIMSHELL
++	}
++#endif
+     }
+ 
+     /* Reset the type of redrawing required, the window has been updated. */
+@@ -1953,6 +1977,18 @@
+     if (!got_int)
+ 	got_int = save_got_int;
+ #endif
++
++#ifdef FEAT_VIMSHELL
++    /*
++     * If this window contains a shell, redraw the shell.
++     */
++    if(wp->w_buffer->is_shell != 0)
++    {
++	wp->w_buffer->shell->force_redraw=(type>=NOT_VALID ? 1 : 0);
++	vim_shell_redraw(wp->w_buffer->shell, wp);
++	return;
++    }
++#endif
+ }
+ 
+ #ifdef FEAT_SIGNS
+@@ -6756,7 +6792,11 @@
+ }
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++      void
++#else
+       static void
++#endif
+ screen_start_highlight(attr)
+       int	attr;
+ {
+@@ -6956,7 +6996,11 @@
+  * Put character ScreenLines["off"] on the screen at position "row" and "col",
+  * using the attributes from ScreenAttrs["off"].
+  */
++#ifdef FEAT_VIMSHELL
++    void
++#else
+     static void
++#endif
+ screen_char(off, row, col)
+     unsigned	off;
+     int		row;
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/structs.h ./src/structs.h
+--- ../vim72.orig/src/structs.h	2009-10-02 13:39:26.000000000 +0100
++++ ./src/structs.h	2009-10-02 13:39:57.000000000 +0100
+@@ -1145,6 +1145,10 @@
+ 
+ typedef struct file_buffer buf_T;
+ 
++#ifdef FEAT_VIMSHELL
++struct vim_shell_window;
++#endif
++
+ struct file_buffer
+ {
+     memline_T	b_ml;		/* associated memline (also contains line
+@@ -1591,6 +1595,11 @@
+     int		b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++    char	is_shell;                /* (flag) Is this buffer a shell? (0 = false) */
++    struct	vim_shell_window *shell; /* Pointer to the shell struct, or NULL */
++    int		gtk_input_id;            /* GTK-input id returned by gdk_input_add, only for GUI */
++#endif
+ };
+ 
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/syntax.c ./src/syntax.c
+--- ../vim72.orig/src/syntax.c	2009-10-02 13:39:24.000000000 +0100
++++ ./src/syntax.c	2009-10-02 13:39:57.000000000 +0100
+@@ -6005,6 +6005,10 @@
+ syntax_present(buf)
+     buf_T	*buf;
+ {
++#ifdef FEAT_VIMSHELL
++    if(buf->is_shell!=0)
++	return 0;
++#endif
+     return (buf->b_syn_patterns.ga_len != 0
+ 	    || buf->b_syn_clusters.ga_len != 0
+ 	    || buf->b_keywtab.ht_used > 0
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/terminal.c ./src/terminal.c
+--- ../vim72.orig/src/terminal.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/terminal.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,1933 @@
++/*
++ * terminal.c
++ *
++ * This is the screen-like terminal emulator; it is a better vt100 and supports the
++ * same commands that screen does (including color etc).
++ *
++ * The interface is vim_shell_terminal_input and vim_shell_terminal_output. These
++ * functions get characters from the shell (or from the user) and process them
++ * accordingly to the terminal rules (ESC sequences etc). They then work directly
++ * on the vim_shell-window-buffer, updating its contents.
++ *
++ * VIMSHELL TODO: *) don't scroll scroll region if cursor is outside
++ *                *) change the buffer name according to the window title
++ *                *) CSI (0x9B)
++ *                *) Get the ESC codes for switching charsets from terminfo/termcap
++ *                *) Origin mode
++ *                *) "erase with background color"
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ */
++
++static char *RCSID="$Id$";
++
++#include <string.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <errno.h>
++
++#include "vim.h"
++
++#ifdef FEAT_VIMSHELL
++#ifdef VIMSHELL_DEBUG
++#  define ESCDEBUG
++/*
++ * Really extreme logging
++ * Log *every* character we write to the shell
++ */
++//#  define VERBOSE
++#endif
++
++#ifdef ESCDEBUG
++#  define ESCDEBUGPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
++#else
++#  define ESCDEBUGPRINTF(a...)
++#endif
++
++#ifdef VERBOSE
++#  define VERBOSEPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
++#else
++#  define VERBOSEPRINTF(a...)
++#endif
++
++/*
++ * These are the VIM keynames.
++ */
++#define VIMSHELL_KEY_DOWN	K_DOWN
++#define VIMSHELL_KEY_UP		K_UP
++#define VIMSHELL_KEY_LEFT	K_LEFT
++#define VIMSHELL_KEY_RIGHT	K_RIGHT
++#define VIMSHELL_KEY_HOME	K_HOME
++#define VIMSHELL_KEY_BACKSPACE	K_BS
++#define VIMSHELL_KEY_F1		K_F1
++#define VIMSHELL_KEY_F2		K_F2
++#define VIMSHELL_KEY_F3		K_F3
++#define VIMSHELL_KEY_F4		K_F4
++#define VIMSHELL_KEY_F5		K_F5
++#define VIMSHELL_KEY_F6		K_F6
++#define VIMSHELL_KEY_F7		K_F7
++#define VIMSHELL_KEY_F8		K_F8
++#define VIMSHELL_KEY_F9		K_F9
++#define VIMSHELL_KEY_F10	K_F10
++#define VIMSHELL_KEY_F11	K_F11
++#define VIMSHELL_KEY_F12	K_F12
++#define VIMSHELL_KEY_DC		K_DEL
++#define VIMSHELL_KEY_END	K_END
++#define VIMSHELL_KEY_IC		K_INS
++#define VIMSHELL_KEY_NPAGE	K_PAGEDOWN
++#define VIMSHELL_KEY_PPAGE	K_PAGEUP
++#define VIMSHELL_KEY_K0		K_K0
++#define VIMSHELL_KEY_K1		K_K1
++#define VIMSHELL_KEY_K2		K_K2
++#define VIMSHELL_KEY_K3		K_K3
++#define VIMSHELL_KEY_K4		K_K4
++#define VIMSHELL_KEY_K5		K_K5
++#define VIMSHELL_KEY_K6		K_K6
++#define VIMSHELL_KEY_K7		K_K7
++#define VIMSHELL_KEY_K8		K_K8
++#define VIMSHELL_KEY_K9		K_K9
++#define VIMSHELL_KEY_KPLUS	K_KPLUS
++#define VIMSHELL_KEY_KMINUS	K_KMINUS
++#define VIMSHELL_KEY_KDIVIDE	K_KDIVIDE
++#define VIMSHELL_KEY_KMULTIPLY	K_KMULTIPLY
++#define VIMSHELL_KEY_KENTER	K_KENTER
++#define VIMSHELL_KEY_KPOINT	K_KPOINT
++
++static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20]);
++static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20]);
++static int terminal_flush_output(struct vim_shell_window *shell);
++
++/*
++ * A routine that prints a buffer in 'hexdump -C'-style via printf
++ */
++static void hexdump(FILE *fp, unsigned char *buffer, long len)
++{
++	unsigned long pos=0;
++
++	while(len>0)
++	{
++		int i;
++		fprintf(fp,"%08x  ",(unsigned int)pos);
++		for(i=0;i<16 && i<len;i++)
++		{
++			fprintf(fp,"%02x ",buffer[pos+i]);
++			if(i==7 || i==15)
++				fprintf(fp," ");
++		}
++		fprintf(fp,"|");
++		for(i=0;i<16 && i<len;i++)
++		{
++			unsigned char c=buffer[pos+i];
++			if(isprint(c))
++			{
++				fprintf(fp,"%c",c);
++			}
++			else
++			{
++				fprintf(fp,".");
++			}
++		}
++		fprintf(fp,"|\n");
++		len-=16;
++		pos+=16;
++	}
++}
++
++/*
++ * Tabulation Clear (TBC)
++ *
++ * 9/11 6/7
++ * CSI   g
++ *
++ * 	Clears a horizontal tab stop at cursor position.
++ *
++ * 	9/11 3/0 6/7
++ * 	CSI   0   g
++ *
++ * 		Clears a horizontal tab stop at cursor position.
++ *
++ * 		9/11 3/3 6/7
++ * 		CSI   3   g
++ *
++ * 			Clears all horizontal tab stops.
++ */
++static void terminal_TBC(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int param;
++
++	if(argc==0)
++	{
++		param=0;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF("%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	// VIMSHELL TODO: DRINGEND! wenn argc==0 dann ist argv[0] NULL und wir crashen
++	// hier ... passiert in einigen Funktionen, dank copy+paste! Super gmocht Tom!
++	param=strtol(argv[0], NULL, 10);
++	switch(param)
++	{
++		case 0:
++			shell->tabline[shell->cursor_x]=0;
++			break;
++		case 3:
++			memset(shell->tabline, 0, shell->size_x);
++			break;
++		default:
++			ESCDEBUGPRINTF( "%s: sequence error (2)\n", __FUNCTION__);
++	}
++}
++
++/*
++ * CUB . Cursor Backward . Host to VT100 and VT100 to Host
++ * ESC [ Pn D 	default value: 1
++ *
++ * The CUB sequence moves the active position to the left. The distance moved is
++ * determined by the parameter. If the parameter value is zero or one, the active
++ * position is moved one position to the left. If the parameter value is n, the active
++ * position is moved n positions to the left. If an attempt is made to move the cursor
++ * to the left of the left margin, the cursor stops at the left margin. Editor Function
++ */
++static void terminal_CUB(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	if(shell->cursor_x<distance)
++		shell->cursor_x=0;
++	else
++		shell->cursor_x-=distance;
++}
++
++/*
++ * CUU . Cursor Up . Host to VT100 and VT100 to Host
++ * ESC [ Pn A 	default value: 1
++ *
++ * Moves the active position upward without altering the column position. The
++ * number of lines moved is determined by the parameter. A parameter value of zero
++ * or one moves the active position one line upward. A parameter value of n moves the
++ * active position n lines upward. If an attempt is made to move the cursor above the
++ * top margin, the cursor stops at the top margin. Editor Function
++ */
++static void terminal_CUU(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	if((int)shell->cursor_y-distance<shell->scroll_top_margin)
++		shell->cursor_y=shell->scroll_top_margin;
++	else
++		shell->cursor_y-=distance;
++}
++
++
++/*
++ * CUD . Cursor Down . Host to VT100 and VT100 to Host
++ * ESC [ Pn B 	default value: 1
++ *
++ * The CUD sequence moves the active position downward without altering the column
++ * position. The number of lines moved is determined by the parameter. If the parameter
++ * value is zero or one, the active position is moved one line downward. If the parameter
++ * value is n, the active position is moved n lines downward. In an attempt is made to
++ * move the cursor below the bottom margin, the cursor stops at the bottom margin. Editor Function
++ */
++static void terminal_CUD(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	shell->cursor_y+=distance;
++	if(shell->cursor_y+1>=shell->scroll_bottom_margin)
++		shell->cursor_y=shell->scroll_bottom_margin;
++}
++
++/*
++ * CUF . Cursor Forward . Host to VT100 and VT100 to Host
++ * ESC [ Pn C 	default value: 1
++ *
++ * The CUF sequence moves the active position to the right. The distance moved is
++ * determined by the parameter. A parameter value of zero or one moves the active
++ * position one position to the right. A parameter value of n moves the active position n
++ * positions to the right. If an attempt is made to move the cursor to the right
++ * of the right margin, the cursor stops at the right margin. Editor Function
++ */
++static void terminal_CUF(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int distance;
++
++	if(argc==0)
++	{
++		distance=1;
++	}
++	else if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	distance=strtol(argv[0], NULL, 10);
++	if(distance==0)
++		distance=1;
++
++	shell->cursor_x+=distance;
++	if(shell->cursor_x+1>=shell->size_x)
++		shell->cursor_x=shell->size_x+1;
++}
++
++/*
++ * SGR . Select Graphic Rendition
++ * ESC [ Ps ; . . . ; Ps m 	default value: 0
++ *
++ * Invoke the graphic rendition specified by the parameter(s). All following characters
++ * transmitted to the VT100 are rendered according to the parameter(s) until the next
++ * occurrence of SGR. Format Effector
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Attributes off
++ * 1 	Bold or increased intensity
++ * 4 	Underscore
++ * 5 	Blink
++ * 7 	Negative (reverse) image
++ *
++ * All other parameter values are ignored.
++ *
++ * With the Advanced Video Option, only one type of character attribute is possible as
++ * determined by the cursor selection; in that case specifying either the underscore or
++ * the reverse attribute will activate the currently selected attribute. (See cursor
++ * selection in Chapter 1).
++ */
++static void terminal_SGR(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc==0)
++	{
++		shell->rendition=0;
++		shell->fgcolor=VIMSHELL_COLOR_DEFAULT;  // default fgcolor
++		shell->bgcolor=VIMSHELL_COLOR_DEFAULT;  // default bgcolor
++	}
++	else
++	{
++		int i;
++		for(i=0;i<argc;i++)
++		{
++			int val;
++			switch((val=strtol(argv[i], NULL, 10)))
++			{
++				case 0:
++					shell->rendition=0;
++					shell->fgcolor=VIMSHELL_COLOR_DEFAULT;
++					shell->bgcolor=VIMSHELL_COLOR_DEFAULT;
++					break;
++				case 1:
++					shell->rendition|=RENDITION_BOLD;
++					break;
++				case 2:
++					shell->rendition|=RENDITION_DIM;
++					break;
++				case 4:
++					shell->rendition|=RENDITION_UNDERSCORE;
++					break;
++				case 5:
++					shell->rendition|=RENDITION_BLINK;
++					break;
++				case 7:
++					shell->rendition|=RENDITION_NEGATIVE;
++					break;
++				case 8:
++					shell->rendition|=RENDITION_HIDDEN;
++					break;
++				case 22:
++					shell->rendition&=~RENDITION_BOLD;
++					break;
++				case 24:
++					shell->rendition&=~RENDITION_UNDERSCORE;
++					break;
++				case 25:
++					shell->rendition&=~RENDITION_BLINK;
++					break;
++				case 27:
++					shell->rendition&=~RENDITION_NEGATIVE;
++					break;
++				default:
++					if(val>=30 && val<=37)
++						shell->fgcolor=val-30;
++					else if(val>=40 && val<=47)
++						shell->bgcolor=val-40;
++					else if(val==39)
++						shell->fgcolor=VIMSHELL_COLOR_DEFAULT; // default fgcolor
++					else if(val==49)
++						shell->bgcolor=VIMSHELL_COLOR_DEFAULT; // default bgcolor
++					else
++						ESCDEBUGPRINTF( "%s: unknown rendition %s\n",
++								__FUNCTION__, argv[i]);
++			}
++		}
++	}
++	ESCDEBUGPRINTF("%s: rendition is now: %04x\n", __FUNCTION__, shell->rendition);
++	ESCDEBUGPRINTF("%s: foreground color: %d, background color: %d\n", __FUNCTION__,
++			shell->fgcolor, shell->bgcolor);
++}
++
++/*
++ * Copy the screen contents to the alternate screen.
++ */
++static void terminal_backup_screen(struct vim_shell_window *shell)
++{
++	size_t len;
++	if(shell->alt!=NULL)
++	{
++		ESCDEBUGPRINTF( "%s: WARNING: alternate screen taken\n", __FUNCTION__);
++		vim_shell_free(shell->alt->winbuf);
++		vim_shell_free(shell->alt->bgbuf);
++		vim_shell_free(shell->alt->fgbuf);
++		vim_shell_free(shell->alt->rendbuf);
++		vim_shell_free(shell->alt->tabline);
++		vim_shell_free(shell->alt->charset);
++		vim_shell_free(shell->alt);
++		shell->alt=NULL;
++	}
++
++	shell->alt=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
++	if(shell->alt==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: ERROR: unable to allocate a new screen\n", __FUNCTION__);
++		return;
++	}
++
++	*(shell->alt)=*shell;
++
++	len=shell->size_x*shell->size_y;
++	shell->alt->winbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->fgbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->bgbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->rendbuf=(uint8_t *)vim_shell_malloc(len);
++	shell->alt->tabline=(uint8_t *)vim_shell_malloc(shell->size_x);
++	shell->alt->charset=(uint8_t *)vim_shell_malloc(len);
++	if(shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL ||
++			shell->alt->charset==NULL || shell->alt->tabline==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: ERROR: unable to allocate buffers\n", __FUNCTION__);
++		if(shell->alt->winbuf) vim_shell_free(shell->alt->winbuf);
++		if(shell->alt->fgbuf) vim_shell_free(shell->alt->fgbuf);
++		if(shell->alt->bgbuf) vim_shell_free(shell->alt->bgbuf);
++		if(shell->alt->rendbuf) vim_shell_free(shell->alt->rendbuf);
++		if(shell->alt->tabline) vim_shell_free(shell->alt->tabline);
++		if(shell->alt->charset) vim_shell_free(shell->alt->charset);
++		vim_shell_free(shell->alt);
++		shell->alt=NULL;
++		return;
++	}
++
++	memcpy(shell->alt->winbuf, shell->winbuf, len);
++	memcpy(shell->alt->fgbuf, shell->fgbuf, len);
++	memcpy(shell->alt->bgbuf, shell->bgbuf, len);
++	memcpy(shell->alt->rendbuf, shell->rendbuf, len);
++	memcpy(shell->alt->charset, shell->charset, len);
++	memcpy(shell->alt->tabline, shell->tabline, shell->size_x);
++}
++
++/*
++ * Restore the alternate screen
++ */
++static void terminal_restore_screen(struct vim_shell_window *shell)
++{
++	struct vim_shell_window *alt;
++	if(shell->alt==NULL)
++	{
++		ESCDEBUGPRINTF( "%s: WARNING: nothing to restore\n", __FUNCTION__);
++		return;
++	}
++
++	vim_shell_free(shell->winbuf);
++	vim_shell_free(shell->rendbuf);
++	vim_shell_free(shell->tabline);
++	vim_shell_free(shell->fgbuf);
++	vim_shell_free(shell->bgbuf);
++	vim_shell_free(shell->charset);
++
++	alt=shell->alt;
++	*shell=*(shell->alt);
++	shell->alt=NULL;
++
++	vim_shell_free(alt);
++
++	/*
++	 * Invalidate the shell so it will be fully redrawn
++	 */
++	shell->force_redraw=1;
++}
++
++/*
++ * Erases the whole screen and homes the cursor.
++ */
++static void terminal_init_screen(struct vim_shell_window *shell)
++{
++	char ed_argv[20][20];
++
++	strcpy(ed_argv[0], "2");
++
++	/*
++	 * Erase all of the display.
++	 */
++	terminal_ED(shell, 1, ed_argv);
++
++	/*
++	 * Cursor to HOME position.
++	 */
++	terminal_CUP(shell, 0, NULL);
++}
++
++static void terminal_mode(struct vim_shell_window *shell, int set, int argc, char argv[20][20])
++{
++	int i;
++
++	for(i=0;i<argc;i++)
++	{
++		if(!strcmp(argv[i], "4"))
++		{
++			shell->insert_mode=set;
++			ESCDEBUGPRINTF( "%s: insert mode: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?1"))
++		{
++			shell->application_cursor_mode=set;
++			ESCDEBUGPRINTF( "%s: application cursor mode: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?5"))
++		{
++			ESCDEBUGPRINTF("%s: background dark/light mode ignored\n", __FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?6"))
++		{
++			ESCDEBUGPRINTF("%s: set terminal width ignored\n", __FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?7"))
++		{
++			shell->wraparound=set;
++			ESCDEBUGPRINTF( "%s: wraparound: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "34") || !strcmp(argv[i], "?25"))
++		{
++			shell->cursor_visible=set;
++			ESCDEBUGPRINTF( "%s: cursor visible: %d\n", __FUNCTION__, set);
++		}
++		else if(!strcmp(argv[i], "?4"))
++		{
++			ESCDEBUGPRINTF("%s: selection between smooth and jump scrolling ignored\n",__FUNCTION__);
++		}
++		else if(!strcmp(argv[i], "?1049") || !strcmp(argv[i], "?1047"))
++		{
++			if(set==1)
++			{
++				terminal_backup_screen(shell);
++				terminal_init_screen(shell);
++				ESCDEBUGPRINTF( "%s: terminal screen backed up.\n", __FUNCTION__);
++			}
++			else
++			{
++				terminal_restore_screen(shell);
++				ESCDEBUGPRINTF( "%s: terminal screen restored from backup.\n", __FUNCTION__);
++			}
++		}
++		else
++		{
++			ESCDEBUGPRINTF( "%s: unimplemented terminal mode: %s\n", __FUNCTION__, argv[i]);
++		}
++	}
++}
++
++/*
++ * EL . Erase In Line
++ * ESC [ Ps K 	default value: 0
++ *
++ * Erases some or all characters in the active line according to the parameter. Editor Function
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Erase from the active position to the end of the line, inclusive (default)
++ * 1 	Erase from the start of the line to the active position, inclusive
++ * 2 	Erase all of the line, inclusive
++ */
++static void terminal_EL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int i, size, pos;
++
++	if(argc==0)
++		i=0;
++	else if(argc==1)
++		i=strtol(argv[0], NULL, 10);
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++
++	size=shell->size_x*shell->size_y;
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	if(i==0)
++	{
++		/*
++		 * erase from the active position to the end of line
++		 */
++
++		memset(shell->winbuf+pos, ' ', shell->size_x-shell->cursor_x);
++		memset(shell->fgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
++		memset(shell->bgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
++		memset(shell->rendbuf+pos, 0, shell->size_x-shell->cursor_x);
++		memset(shell->charset+pos, 0, shell->size_x-shell->cursor_x);
++		ESCDEBUGPRINTF( "%s: erase from active position to end of line\n", __FUNCTION__);
++
++	}
++	else if(i==1)
++	{
++		/*
++		 * erase from start of the line to the active position, inclusive
++		 */
++
++		memset(shell->winbuf+shell->cursor_y*shell->size_x, ' ', shell->cursor_x);
++		memset(shell->fgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
++		memset(shell->bgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
++		memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
++		memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
++		ESCDEBUGPRINTF( "%s: erase from start of line to active position\n", __FUNCTION__);
++	}
++	else if(i==2)
++	{
++		/*
++		 * Erase all of the line
++		 */
++
++		memset(shell->winbuf +shell->cursor_y*shell->size_x, ' ', shell->size_x);
++		memset(shell->fgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++		memset(shell->bgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++		memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->size_x);
++		memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->size_x);
++		ESCDEBUGPRINTF( "%s: erase all of the line\n", __FUNCTION__);
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
++		return;
++	}
++}
++
++/*
++ * ED . Erase In Display
++ * ESC [ Ps J 	default value: 0
++ *
++ * This sequence erases some or all of the characters in the display according
++ * to the parameter. Any complete line erased by this sequence will return that
++ * line to single width mode. Editor Function
++ *
++ * Parameter 	Parameter Meaning
++ * 0 	Erase from the active position to the end of the screen, inclusive (default)
++ * 1 	Erase from start of the screen to the active position, inclusive
++ * 2 	Erase all of the display . all lines are erased, changed to single-width, and the cursor does not move.
++ */
++static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int i, size, pos;
++
++	if(argc==0)
++		i=0;
++	else if(argc==1)
++		i=strtol(argv[0], NULL, 10);
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++
++	size=shell->size_x*shell->size_y;
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	if(i==0)
++	{
++		/*
++		 * erase from the active position to the end of screen
++		 */
++
++		memset(shell->winbuf+pos, ' ', size-pos);
++		memset(shell->fgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
++		memset(shell->bgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
++		memset(shell->rendbuf+pos, 0, size-pos);
++		memset(shell->charset+pos, 0, size-pos);
++		ESCDEBUGPRINTF( "%s: erase from active position to end of screen\n", __FUNCTION__);
++
++	}
++	else if(i==1)
++	{
++		/*
++		 * erase from start of the screen to the active position, inclusive
++		 */
++
++		memset(shell->winbuf, ' ', pos);
++		memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, pos);
++		memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, pos);
++		memset(shell->rendbuf, 0, pos);
++		memset(shell->charset, 0, pos);
++		ESCDEBUGPRINTF( "%s: erase from start of screen to active position\n", __FUNCTION__);
++	}
++	else if(i==2)
++	{
++		/*
++		 * Erase all of the display
++		 */
++
++		memset(shell->winbuf, ' ', size);
++		memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, size);
++		memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, size);
++		memset(shell->rendbuf, 0, size);
++		memset(shell->charset, 0, size);
++		ESCDEBUGPRINTF( "%s: erase all of the display\n", __FUNCTION__);
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
++		return;
++	}
++}
++
++/*
++ * CUP . Cursor Position
++ * ESC [ Pn ; Pn H 	default value: 1
++ *
++ * The CUP sequence moves the active position to the position specified by
++ * the parameters. This sequence has two parameter values, the first specifying
++ * the line position and the second specifying the column position. A parameter
++ * value of zero or one for the first or second parameter moves the active
++ * position to the first line or column in the display, respectively. The default
++ * condition with no parameters present is equivalent to a cursor to home action.
++ * In the VT100, this control behaves identically with its format effector
++ * counterpart, HVP. Editor Function
++ *
++ * The numbering of lines depends on the state of the Origin Mode (DECOM).
++ */
++static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc==0)
++	{
++		/*
++		 * goto home position
++		 */
++		shell->cursor_x=0;
++		shell->cursor_y=0;
++	}
++	else if(argc==2)
++	{
++		int x, y;
++
++		y=strtol(argv[0], NULL, 10);
++		x=strtol(argv[1], NULL, 10);
++		if(x==0)
++			x++;
++		if(y==0)
++			y++;
++
++		shell->cursor_y=y-1;
++		shell->cursor_x=x-1;
++
++		// VIMSHELL TODO: if origin mode enabled, position at the
++		//                top margin or so :)
++
++		if(shell->cursor_x>=shell->size_x)
++			shell->cursor_x=shell->size_x-1;
++		if(shell->cursor_y>=shell->size_y)
++			shell->cursor_y=shell->size_y-1;
++	}
++	else
++	{
++		/*
++		 * Error in sequence
++		 */
++		ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
++		return;
++	}
++	ESCDEBUGPRINTF( "%s: moved to X = %d, Y = %d\n", __FUNCTION__, shell->cursor_x, shell->cursor_y);
++}
++
++/*
++ * DECSTBM . Set Top and Bottom Margins (DEC Private)
++ * ESC [ Pn; Pn r 	default values: see below
++ *
++ * This sequence sets the top and bottom margins to define the scrolling region.
++ * The first parameter is the line number of the first line in the scrolling region; the
++ * second parameter is the line number of the bottom line in the scrolling region. Default
++ * is the entire screen (no margins). The minimum size of the scrolling region allowed is
++ * two lines, i.e., the top margin must be less than the bottom margin. The cursor is placed
++ * in the home position (see Origin Mode DECOM).
++ */
++static void terminal_DECSTBM(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	if(argc!=2)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	shell->scroll_top_margin=strtol(argv[0], NULL, 10)-1;
++	shell->scroll_bottom_margin=strtol(argv[1], NULL, 10)-1;
++
++	ESCDEBUGPRINTF( "%s: top margin = %d, bottom margin = %d\n", __FUNCTION__,
++			shell->scroll_top_margin, shell->scroll_bottom_margin);
++
++	if(shell->scroll_top_margin>=shell->scroll_bottom_margin)
++	{
++		ESCDEBUGPRINTF( "%s: scroll margin error %d >= %d\n", __FUNCTION__,
++				shell->scroll_top_margin, shell->scroll_bottom_margin);
++
++		shell->scroll_top_margin=0;
++		shell->scroll_bottom_margin=shell->size_y-1;
++
++		return;
++	}
++
++	// Move cursor into home position
++	terminal_CUP(shell, 0, NULL);
++}
++
++
++// Status: 100%
++static void terminal_scroll_up(struct vim_shell_window *shell)
++{
++	// VIMSHELL TODO: maintain a scrollback buffer? copy the first line into
++	// a scrollback buffer.
++
++	/*
++	 * scroll up by moving up the screen buffer a whole line. blank out
++	 * the last line.
++	 */
++	int len, from, to;
++
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++
++	len=shell->scroll_bottom_margin-shell->scroll_top_margin;
++	len*=shell->size_x;
++
++	to=shell->scroll_top_margin*shell->size_x;
++	from=shell->size_x+shell->scroll_top_margin*shell->size_x;
++
++	memmove(shell->winbuf+to, shell->winbuf+from, len);
++	memmove(shell->fgbuf+to, shell->fgbuf+from, len);
++	memmove(shell->bgbuf+to, shell->bgbuf+from, len);
++	memmove(shell->rendbuf+to, shell->rendbuf+from, len);
++	memmove(shell->charset+to, shell->charset+from, len);
++
++	memset(shell->winbuf+shell->scroll_bottom_margin*shell->size_x, ' ', shell->size_x);
++	memset(shell->fgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->bgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->rendbuf+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
++	memset(shell->charset+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
++}
++
++// Status: unknown
++static void terminal_scroll_down(struct vim_shell_window *shell)
++{
++	/*
++	 * scroll down by moving the screen buffer down a whole line, overwriting
++	 * the last line. Then, blank out the first line.
++	 */
++	size_t len;
++	int from, to;
++
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++
++	len=shell->scroll_bottom_margin-shell->scroll_top_margin;
++	len*=shell->size_x;
++
++	to=shell->scroll_top_margin*shell->size_x+shell->size_x;
++	from=shell->scroll_top_margin*shell->size_x;
++
++	memmove(shell->winbuf+to, shell->winbuf+from, len);
++	memmove(shell->fgbuf+to, shell->fgbuf+from, len);
++	memmove(shell->bgbuf+to, shell->bgbuf+from, len);
++	memmove(shell->rendbuf+to, shell->rendbuf+from, len);
++	memmove(shell->charset+to, shell->charset+from, len);
++
++	memset(shell->winbuf+from, ' ', shell->size_x);
++	memset(shell->fgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->bgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
++	memset(shell->rendbuf+from, 0, shell->size_x);
++	memset(shell->charset+from, 0, shell->size_x);
++}
++
++/*
++ * Insert Line(s) (ANSI).
++ * ESC [ Pn L
++ * Inserts Pn lines at the cursor. If fewer than Pn lines remain from the current line to the
++ * end of the scrolling region, the number of lines inserted is the lesser number. Lines within
++ * the scrolling region at and below the cursor move down. Lines moved past the bottom margin
++ * are lost. The cursor is reset to the first column. This sequence is ignored when the
++ * cursor is outside the scrolling region.
++ */
++// Status: unknown
++static void terminal_IL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int lines, bak_top;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		lines=1;
++	else
++	{
++		lines=strtol(argv[0], NULL, 10);
++		if(lines==0)
++			lines=1;
++	}
++
++	if(shell->scroll_bottom_margin-shell->cursor_y < lines)
++		lines=shell->scroll_bottom_margin-shell->cursor_y;
++
++	bak_top=shell->scroll_top_margin;
++
++	ESCDEBUGPRINTF( "%s: inserted %d lines\n", __FUNCTION__, lines);
++
++	/*
++	 * Set a scrolling region around the part we want to move and scroll down 'lines' times.
++	 */
++	shell->scroll_top_margin=shell->cursor_y;
++	while(lines--)
++		terminal_scroll_down(shell);
++
++	shell->scroll_top_margin=bak_top;
++
++	shell->cursor_x=0;
++}
++
++/*
++ * Delete Line(s) (ANSI).
++ * ESC [ Pn M
++ * Deletes Pn lines starting at the line with the cursor. If fewer than Pn lines remain from
++ * the current line to the end of the scrolling region, the number of lines deleted is the
++ * lesser number. As lines are deleted, lines within the scrolling region and below the cursor move
++ * up, and blank lines are added at the bottom of the scrolling region. The cursor is reset to the
++ * first column. This sequence is ignored when the cursor is outside the scrolling region.
++ * VIMSHELL TODO last sentence
++ */
++// Status: unknown
++static void terminal_DL(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int lines, bak_top;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		lines=1;
++	else
++	{
++		lines=strtol(argv[0], NULL, 10);
++		if(lines==0)
++			lines=1;
++	}
++
++	if(shell->scroll_bottom_margin-shell->cursor_y < lines)
++		lines=shell->scroll_bottom_margin-shell->cursor_y;
++
++	bak_top=shell->scroll_top_margin;
++
++	ESCDEBUGPRINTF( "%s: deleted %d lines\n", __FUNCTION__, lines);
++
++	/*
++	 * Set a scrolling region around the part we want to move and scroll up 'lines' times.
++	 */
++	shell->scroll_top_margin=shell->cursor_y;
++	while(lines--)
++		terminal_scroll_up(shell);
++
++	shell->scroll_top_margin=bak_top;
++
++	shell->cursor_x=0;
++}
++
++/*
++ * Insert Characters (ANSI)
++ * ESC [ Pn @
++ * Insert Pn blank characters at the cursor position, with the character attributes set to
++ * normal. The cursor does not move and remains at the beginning of the inserted blank characters.
++ * A parameter of 0 or 1 inserts one blank character. Data on the line is shifted forward as
++ * in character insertion.
++ */
++static void terminal_ICH(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int chars;
++	int curpos;
++	size_t len;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		chars=1;
++	else
++	{
++		chars=strtol(argv[0], NULL, 10);
++		if(chars==0)
++			chars=1;
++	}
++
++	curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	len=shell->size_x-shell->cursor_x-1;
++
++	ESCDEBUGPRINTF( "%s: inserted %d characters\n", __FUNCTION__, chars);
++
++	while(chars--)
++	{
++		memmove(shell->winbuf+curpos+1, shell->winbuf+curpos, len);
++		memmove(shell->fgbuf+curpos+1, shell->fgbuf+curpos, len);
++		memmove(shell->bgbuf+curpos+1, shell->bgbuf+curpos, len);
++		memmove(shell->rendbuf+curpos+1, shell->rendbuf+curpos, len);
++		memmove(shell->charset+curpos+1, shell->charset+curpos, len);
++
++		memset(shell->winbuf+curpos, ' ', 1);
++		memset(shell->fgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->bgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->rendbuf+curpos, 0, 1);
++		memset(shell->charset+curpos, 0, 1);
++	}
++}
++
++/*
++ * Delete Characters (ANSI)
++ * ESC [ Pn P
++ * Deletes Pn characters starting with the character at the cursor position. When a character
++ * is deleted, all characters to the right of the cursor move to the left. This creates a space
++ * character at the right margin for each character deleted. Character attributes move with the
++ * characters. The spaces created at the end of the line have all their character attributes off.
++ */
++static void terminal_DCH(struct vim_shell_window *shell, int argc, char argv[20][20])
++{
++	int chars;
++	int curpos;
++	size_t len;
++	if(argc>1)
++	{
++		ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
++		return;
++	}
++
++	if(argc==0)
++		chars=1;
++	else
++	{
++		chars=strtol(argv[0], NULL, 10);
++		if(chars==0)
++			chars=1;
++	}
++
++	curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
++	len=shell->size_x-shell->cursor_x-1;
++
++	ESCDEBUGPRINTF( "%s: deleted %d characters\n", __FUNCTION__, chars);
++
++	while(chars--)
++	{
++		memmove(shell->winbuf+curpos, shell->winbuf+curpos+1, len);
++		memmove(shell->fgbuf+curpos, shell->fgbuf+curpos+1, len);
++		memmove(shell->bgbuf+curpos, shell->bgbuf+curpos+1, len);
++		memmove(shell->rendbuf+curpos, shell->rendbuf+curpos+1, len);
++		memmove(shell->charset+curpos, shell->charset+curpos+1, len);
++
++		memset(shell->winbuf+curpos+len, ' ', 1);
++		memset(shell->fgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->bgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
++		memset(shell->rendbuf+curpos+len, 0, 1);
++		memset(shell->charset+curpos+len, 0, 1);
++	}
++}
++
++static void terminal_BEL(struct vim_shell_window *shell)
++{
++	/*
++	 * "Sound bell tone from keyboard."
++	 * Sure.
++	 */
++}
++
++static void terminal_BS(struct vim_shell_window *shell)
++{
++	/*
++	 * "Move the cursor to the left one character position,
++	 * unless it is at the left margin, in which case no action occurs."
++	 */
++	if(shell->cursor_x>0)
++		shell->cursor_x--;
++}
++
++static void terminal_LF(struct vim_shell_window *shell)
++{
++	/*
++	 * "This code causes a line feed or a new line operation."
++	 */
++
++	if(shell->just_wrapped_around==1)
++	{
++		/*
++		 * Terminals which have the xenl capability ignore a linefeed after
++		 * an auto margin wrap.
++		 */
++		VERBOSEPRINTF( "%s: ignored LF because of earlier wrap around\n",
++				__FUNCTION__);
++		return;
++	}
++
++	shell->cursor_y++;
++	if(shell->cursor_y-1==shell->scroll_bottom_margin)
++	{
++		shell->cursor_y--;
++		terminal_scroll_up(shell);
++	}
++
++	VERBOSEPRINTF( "%s: did LF, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
++			shell->cursor_x, shell->cursor_y);
++}
++
++static void terminal_CR(struct vim_shell_window *shell)
++{
++	/*
++	 * "Move cursor to the left margin on the current line."
++	 */
++	if(shell->just_wrapped_around==1)
++	{
++		/*
++		 * Terminals which have the xenl capability ignore a linefeed after
++		 * an auto margin wrap.
++		 */
++		VERBOSEPRINTF( "%s: ignored CR because of earlier wrap around\n",
++				__FUNCTION__);
++		return;
++	}
++	shell->cursor_x=0;
++	VERBOSEPRINTF( "%s: did CR, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
++			shell->cursor_x, shell->cursor_y);
++}
++
++/*
++ * RI . Reverse Index
++ * ESC M
++ *
++ * Move the active position to the same horizontal position on the preceding line. If the
++ * active position is at the top margin, a scroll down is performed. Format Effector
++ */
++static void terminal_RI(struct vim_shell_window *shell)
++{
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++	if(shell->cursor_y==shell->scroll_top_margin)
++		terminal_scroll_down(shell);
++	else
++		shell->cursor_y--;
++}
++
++/*
++ * IND . Index
++ * ESC D
++ *
++ * This sequence causes the active position to move downward one line without changing the
++ * column position. If the active position is at the bottom margin, a scroll up is performed.
++ * Format Effector
++ */
++static void terminal_IND(struct vim_shell_window *shell)
++{
++	ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
++	if(shell->cursor_y==shell->scroll_bottom_margin)
++		terminal_scroll_up(shell);
++	else
++		shell->cursor_y++;
++}
++
++/*
++ * ESC 7
++ * ESC [s (ANSI)
++ * Saves the current terminal rendering settings
++ */
++static void terminal_save_attributes(struct vim_shell_window *shell)
++{
++	shell->saved_cursor_x=shell->cursor_x;
++	shell->saved_cursor_y=shell->cursor_y;
++	shell->saved_rendition=shell->rendition;
++	shell->saved_fgcolor=shell->fgcolor;
++	shell->saved_bgcolor=shell->bgcolor;
++	shell->saved_G0_charset=shell->G0_charset;
++	shell->saved_G1_charset=shell->G1_charset;
++	shell->saved_application_keypad_mode=shell->application_keypad_mode;
++	shell->saved_application_cursor_mode=shell->application_cursor_mode;
++	shell->saved_insert_mode=shell->insert_mode;
++}
++
++/*
++ * ESC 8
++ * ESC [u (ANSI)
++ * Restores the current terminal rendering settings
++ */
++static void terminal_restore_attributes(struct vim_shell_window *shell)
++{
++	shell->cursor_x=shell->saved_cursor_x;
++	shell->cursor_y=shell->saved_cursor_y;
++	shell->rendition=shell->saved_rendition;
++	shell->fgcolor=shell->saved_fgcolor;
++	shell->bgcolor=shell->saved_bgcolor;
++	shell->G0_charset=shell->saved_G0_charset;
++	shell->G1_charset=shell->saved_G1_charset;
++	shell->application_keypad_mode=shell->saved_application_keypad_mode;
++	shell->application_cursor_mode=shell->saved_application_cursor_mode;
++	shell->insert_mode=shell->saved_insert_mode;
++}
++
++#define ADVANCE_PSEQ { pseq++; if(*pseq==0) return; }
++
++/*
++ * Attempts to parse the escape sequence stored in shell->esc_sequence.
++ * When it succeeds, it removes that escape sequence from the buffer and
++ * possibly clears shell->in_esc_sequence when there are no characters left,
++ * leaving ESC mode.
++ */
++static void terminal_parse_esc_sequence(struct vim_shell_window *shell)
++{
++	char *pseq;
++
++	if(shell->in_esc_sequence==0 || shell->esc_sequence[0]!=033)
++	{
++		ESCDEBUGPRINTF( "%s: invalid esc sequence in esc buffer\n",
++				__FUNCTION__);
++		/*
++		 * We would stick here forever, so flush the buffer
++		 */
++		shell->in_esc_sequence=0;
++		terminal_flush_output(shell);
++
++		return;
++	}
++
++	if(shell->in_esc_sequence==1)
++	{
++		ESCDEBUGPRINTF( "%s: not much in the buffer ...\n", __FUNCTION__);
++		return;
++	}
++
++	shell->esc_sequence[shell->in_esc_sequence]=0;
++	pseq=shell->esc_sequence+1;
++
++	if(*pseq=='[')
++	{
++		/*
++		 * Got a Control Sequence Introducer (CSI) = ESC [
++		 * Parse Parameters.
++		 */
++
++		int argc=0;
++		char argv[20][20];
++
++		ADVANCE_PSEQ;
++
++		memset(argv, 0, sizeof(argv));
++
++		if((*pseq>='0' && *pseq<='9') || *pseq=='?' || *pseq==';')
++		{
++			int cont;
++			do
++			{
++				cont=0;
++				while((*pseq>='0' && *pseq<='9') || *pseq=='?')
++				{
++					char dummy[2];
++					dummy[0]=*pseq;
++					dummy[1]=0;
++					strcat(argv[argc], dummy);
++					ADVANCE_PSEQ;
++				}
++				if(argv[argc][0]==0)
++				{
++					strcpy(argv[argc], "0");
++				}
++
++				argc++;
++				if(*pseq==';')
++				{
++					cont=1;
++					ADVANCE_PSEQ;
++				}
++			} while(cont==1);
++		}
++
++#ifdef ESCDEBUG
++		ESCDEBUGPRINTF("%s: sequence = '%s', argc = %d, ", __FUNCTION__, shell->esc_sequence, argc);
++		{
++			int i;
++			for(i=0;i<argc;i++)
++			{
++				ESCDEBUGPRINTF("argv[%d] = '%s', ",i, argv[i]);
++			}
++		}
++		ESCDEBUGPRINTF("\n");
++#endif
++
++		switch(*pseq)
++		{
++			case 'f':
++			case 'H':
++				terminal_CUP(shell, argc, argv);
++				break;
++			case 'J':
++				terminal_ED(shell, argc, argv);
++				break;
++			case 'K':
++				terminal_EL(shell, argc, argv);
++				break;
++			case 'C':
++				terminal_CUF(shell, argc, argv);
++				break;
++			case 'l':
++				terminal_mode(shell, 0, argc, argv);
++				break;
++			case 'h':
++				terminal_mode(shell, 1, argc, argv);
++				break;
++			case 'm':
++				terminal_SGR(shell, argc, argv);
++				break;
++			case 'r': // set scroll margins
++				terminal_DECSTBM(shell, argc, argv);
++				break;
++			case 'B': // cursor down
++				terminal_CUD(shell, argc, argv);
++				break;
++			case 'D': // cursor backward
++				terminal_CUB(shell, argc, argv);
++				break;
++			case 'A': // cursor up
++				terminal_CUU(shell, argc, argv);
++				break;
++			case 'M': // delete line
++				terminal_DL(shell, argc, argv);
++				break;
++			case 'L': // insert line
++				terminal_IL(shell, argc, argv);
++				break;
++			case '@': // insert characters
++				terminal_ICH(shell, argc, argv);
++				break;
++			case 'P': // delete characters
++				terminal_DCH(shell, argc, argv);
++				break;
++			case 'E': // new line
++				terminal_CR(shell);
++				terminal_LF(shell);
++				break;
++			case 's': // Save Cursor and attributes
++				terminal_save_attributes(shell);
++				break;
++			case 'u': // Restore Cursor and attributes
++				terminal_restore_attributes(shell);
++				break;
++			case 'g': // Tabulator clear
++				terminal_TBC(shell, argc, argv);
++				break;
++			default:
++				ESCDEBUGPRINTF( "%s: unimplemented CSI code: %c\n",
++						__FUNCTION__, *pseq);
++		}
++	}
++	else
++	{
++		ESCDEBUGPRINTF( "%s: sequence is (probably not yet complete) '%s'\n",
++				__FUNCTION__, shell->esc_sequence);
++		switch(*pseq)
++		{
++			case '#':
++				ADVANCE_PSEQ;
++				if(*pseq=='8') // fill screen with E's
++				{
++					memset(shell->winbuf, 'E', shell->size_x*shell->size_y);
++				}
++				break;
++			case '(': // switch G0 charset
++				ADVANCE_PSEQ;
++				shell->G0_charset=*pseq;
++				ESCDEBUGPRINTF( "%s: G0 character set is now: %c\n", __FUNCTION__, *pseq);
++				break;
++			case ')': // switch G1 charset
++				ADVANCE_PSEQ;
++				shell->G1_charset=*pseq;
++				ESCDEBUGPRINTF( "%s: G1 character set is now: %c\n", __FUNCTION__, *pseq);
++				break;
++			case 'D': // index
++				terminal_IND(shell);
++				break;
++			case 'M': // reverse index
++				terminal_RI(shell);
++				break;
++			case '7': // Save Cursor
++				terminal_save_attributes(shell);
++				break;
++			case '8': // Restore Cursor
++				terminal_restore_attributes(shell);
++				break;
++			case '=': // Application Keypad Mode
++				shell->application_keypad_mode=1;
++				ESCDEBUGPRINTF( "%s: keypad switched to application mode\n", __FUNCTION__);
++				break;
++			case '>': // Numeric Keypad Mode
++				shell->application_keypad_mode=0;
++				ESCDEBUGPRINTF( "%s: keypad switched to numeric mode\n", __FUNCTION__);
++				break;
++			case 'H': // Set Horizontal Tab
++				shell->tabline[shell->cursor_x]=1;
++				break;
++			case 'E': // NEL - Moves cursor to first position on next line. If cursor is
++				  // at bottom margin, screen performs a scroll-up.
++				terminal_IND(shell);
++				shell->cursor_x=0;
++				break;
++			case ']': // This could be the beginning of the xterm title hack
++				ADVANCE_PSEQ;
++				if(*pseq=='1' || *pseq=='2' || *pseq=='0')
++				{
++					char title[50];
++					ADVANCE_PSEQ;
++					if(*pseq==';')
++					{
++						int end;
++						title[0]=0;
++						/*
++						 * I know this loop is ugly but ADVANCE_PSEQ
++						 * is a macro, sorry
++						 */
++						for(end=0;!end;)
++						{
++							ADVANCE_PSEQ;
++							if(strlen(title)>sizeof(title)-2)
++								end=1;
++							if(*pseq==7)
++								end=1;
++							else
++							{
++								char dummy[2];
++								dummy[0]=*pseq;
++								dummy[1]=0;
++								strcat(title, dummy);
++							}
++						}
++
++						snprintf(shell->windowtitle, sizeof(shell->windowtitle),
++								"%s", title);
++
++						ESCDEBUGPRINTF( "%s: changing title to '%s'\n",
++								__FUNCTION__, shell->windowtitle);
++					}
++					else
++					{
++						ESCDEBUGPRINTF( "%s: error in xterm title hack "
++								"sequence: %c\n", __FUNCTION__, *pseq);
++					}
++				}
++				else
++				{
++					ESCDEBUGPRINTF( "%s: unimplemented xterm title hack "
++							"code: %d\n", __FUNCTION__, *pseq);
++				}
++				break;
++			default:
++				ESCDEBUGPRINTF( "%s: unimplemented esc code: %c\n",
++						__FUNCTION__, *pseq);
++		}
++	}
++
++	/*
++	 * when we end up here, we successfully completed the sequence.
++	 */
++	shell->in_esc_sequence=0;
++	terminal_flush_output(shell);
++
++#ifdef ESCDEBUG
++	pseq++;
++	if(*pseq!=0)
++	{
++		ESCDEBUGPRINTF( "WARNING: %s: sequence is not over! left in buffer: '%s'\n",
++				__FUNCTION__, pseq);
++	}
++#endif
++}
++
++
++/*
++ * Main character write part.
++ * This here runs most of the time, just writing the character to the
++ * right cursor position.
++ */
++static void terminal_normal_char(struct vim_shell_window *shell, char input)
++{
++	int pos;
++	uint8_t charset;
++
++	shell->just_wrapped_around=0;
++	/*
++	 * If the cursor is currently in the 'virtual' column (that is the column
++	 * after the physical line end), we wrap around now.
++	 */
++	if(shell->cursor_x==shell->size_x)
++	{
++		if(shell->wraparound==1)
++		{
++			terminal_CR(shell);
++			terminal_LF(shell);
++			shell->just_wrapped_around=1;
++			VERBOSEPRINTF( "%s: auto margin - wrapped around!\n",__FUNCTION__);
++		}
++		else
++		{
++			shell->cursor_x--;
++		}
++	}
++
++	/*
++	 * write the character at its right position.
++	 */
++	if(shell->insert_mode!=0)
++	{
++		/*
++		 * If insert mode is on, move all characters from the current position+1 to
++		 * the end of the row. The last character on the row falls out.
++		 * Fortunately, we already implemented this kind of operation :)
++		 */
++                terminal_ICH(shell, 0, NULL);
++	}
++	pos=shell->cursor_y*shell->size_x+shell->cursor_x;
++
++	/*
++	 * Select which character to display.
++	 */
++	if(shell->active_charset==1)
++		charset=shell->G1_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
++	else
++		charset=shell->G0_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
++
++	shell->winbuf[pos]=input;
++	shell->fgbuf[pos]=shell->fgcolor;
++	shell->bgbuf[pos]=shell->bgcolor;
++	shell->rendbuf[pos]=shell->rendition;
++	shell->charset[pos]=charset;
++	VERBOSEPRINTF( "%s: writing char '%c' to position X = %u, Y = %u (col: 0x%02x,0x%02x)\n", __FUNCTION__,
++			input, shell->cursor_x, shell->cursor_y, current_fg, current_bg);
++	shell->cursor_x++;
++}
++
++/*
++ * Here, all characters between 000 and 037 are processed. This is in a
++ * separate function because control characters can be in the normal
++ * flow of characters or in the middle of escape sequences.
++ */
++static void terminal_process_control_char(struct vim_shell_window *shell, char input)
++{
++	switch(input)
++	{
++		case 007: // BEL, Bell, 0x07
++			terminal_BEL(shell);
++			break;
++		case 010: // BS, Backspace, 0x08
++			terminal_BS(shell);
++			break;
++		case 011: // TAB
++			{
++				/*
++				 * Move to the next tabstop or stop at the right margin if no
++				 * tabstop found.
++				 */
++				int i, found;
++				for(found=0, i=shell->cursor_x+1;i<shell->size_x && !found;i++)
++				{
++					if(shell->tabline[i]==1)
++					{
++						shell->cursor_x=i;
++						found=1;
++					}
++				}
++				if(found==0)
++				{
++					shell->cursor_x=shell->size_x-1;
++				}
++			}
++			break;
++		case 013:
++		case 014:
++		case 012: // LF, Line Feed, 0x0a, \n
++			terminal_LF(shell);
++			break;
++		case 015: // CR, Carriage Return, 0x0d, \r
++			terminal_CR(shell);
++			break;
++		case 016: // SO, Invoke G1 character set, as designated by SCS control sequence.
++			shell->active_charset=1;
++			break;
++		case 017: // SI, Select G0 character set, as selected by ESC ( sequence.
++			shell->active_charset=0;
++			break;
++		case 030:
++		case 032: // CAN or SUB - cancel escape sequence
++			shell->in_esc_sequence=0;
++			// VIMSHELL TODO: display substitution character?
++			ESCDEBUGPRINTF("%s: WARNING: possible source of rendering faults: "
++					"substitution characters after CAN or SUB?\n", __FUNCTION__);
++			break;
++		case 033: // ESC, Escape
++			/*
++			 * Note: This also fulfills the requirement that a ESC occuring while processing
++			 *       an escape sequence should restart the sequence.
++			 */
++			shell->in_esc_sequence=1;
++			shell->esc_sequence[0]=033;
++			break;
++		default:
++			ESCDEBUGPRINTF("%s: unimplemented control character: %u\n", __FUNCTION__, input);
++			break;
++	}
++}
++
++static void terminal_input_char(struct vim_shell_window *shell, char input)
++{
++	if(shell->in_esc_sequence==0)
++	{
++		if(input>=0 && input<=037)
++		{
++			/*
++			 * A control character, process it
++			 */
++			terminal_process_control_char(shell, input);
++		}
++		else
++		{
++			// all normal characters are processed here
++			terminal_normal_char(shell, input);
++		}
++	}
++	else
++	{
++		if(input>=0 && input<=037)
++		{
++			/*
++			 * That's right, control characters can appear even in
++			 * the middle of escape sequences.
++			 */
++			terminal_process_control_char(shell, input);
++			return;
++		}
++
++		/*
++		 * Aha, we are right in the middle of an escape sequence.
++		 * Add this character and attempt to parse the sequence.
++		 */
++		shell->esc_sequence[shell->in_esc_sequence]=input;
++		shell->in_esc_sequence++;
++
++		if(shell->in_esc_sequence>=sizeof(shell->esc_sequence))
++		{
++			/*
++			 * about to overrun esc sequence buffer ...
++			 * Should never happen, but still: kill the sequence, or we'd loop
++			 * forever.
++			 */
++
++			shell->in_esc_sequence=0;
++			terminal_flush_output(shell);
++			return;
++		}
++
++		terminal_parse_esc_sequence(shell);
++	}
++}
++
++/*
++ * If we are ready, flush the outbuf into the shell.
++ * CHECK: should always be called when shell->in_esc_sequence goes back to zero,
++ *        so characters that are waiting for a sequence to become complete can be
++ *        flushed out.
++ */
++static int terminal_flush_output(struct vim_shell_window *shell)
++{
++	if(/*shell->in_esc_sequence==0 && */ shell->outbuf_pos>0)
++	{
++		int len;
++#ifdef ESCDEBUG
++		ESCDEBUGPRINTF( "%s: sending:\n",__FUNCTION__);
++		hexdump(vimshell_debug_fp, shell->outbuf, shell->outbuf_pos);
++#endif
++		len=write(shell->fd_master, shell->outbuf, shell->outbuf_pos);
++		if(len<0)
++		{
++			ESCDEBUGPRINTF( "%s: ERROR: write failed: %s\n",
++					__FUNCTION__,strerror(errno));
++			shell->outbuf_pos=0;
++			return -1;
++		}
++
++		if(shell->outbuf_pos!=len)
++			memmove(shell->outbuf, shell->outbuf+len, len);
++		shell->outbuf_pos-=len;
++
++		return len;
++	}
++	return 0;
++}
++
++/*
++ * Main Terminal processing method (VIM <- Shell).
++ * Gets a buffer with input data from the shell, interprets it and updates
++ * the shell window's windowbuffer accordingly.
++ */
++void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len)
++{
++	int i;
++	for(i=0;i<len;i++)
++	{
++		terminal_input_char(shell, input[i]);
++	}
++}
++
++/*
++ * Main Terminal output method (VIM -> Shell).
++ * Translates the character 'c' into an appropriate escape sequence (if necessary)
++ * and puts it into the out buffer.
++ */
++int vim_shell_terminal_output(struct vim_shell_window *shell, int c)
++{
++	char outbuf[50];
++	size_t written;
++
++	outbuf[1]=0;
++
++	switch(c)
++	{
++		case VIMSHELL_KEY_BACKSPACE:
++			sprintf(outbuf, "\177");
++			ESCDEBUGPRINTF( "%s: key is backspace\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_UP:
++			sprintf(outbuf, "\033%cA", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor up\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_DOWN:
++			sprintf(outbuf, "\033%cB", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor down\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_LEFT:
++			sprintf(outbuf, "\033%cD", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor left\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_RIGHT:
++			sprintf(outbuf, "\033%cC", shell->application_cursor_mode ? 'O' : '[');
++			ESCDEBUGPRINTF( "%s: key is cursor right\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_HOME:
++			sprintf(outbuf, "\033[1~");
++			ESCDEBUGPRINTF( "%s: key is home\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F1:
++			sprintf(outbuf, "\033OP");
++			ESCDEBUGPRINTF( "%s: key is F1\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F2:
++			sprintf(outbuf, "\033OQ");
++			ESCDEBUGPRINTF( "%s: key is F2\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F3:
++			sprintf(outbuf, "\033OR");
++			ESCDEBUGPRINTF( "%s: key is F3\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F4:
++			sprintf(outbuf, "\033OS");
++			ESCDEBUGPRINTF( "%s: key is F4\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F5:
++			sprintf(outbuf, "\033[15~");
++			ESCDEBUGPRINTF( "%s: key is F5\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F6:
++			sprintf(outbuf, "\033[17~");
++			ESCDEBUGPRINTF( "%s: key is F6\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F7:
++			sprintf(outbuf, "\033[18~");
++			ESCDEBUGPRINTF( "%s: key is F7\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F8:
++			sprintf(outbuf, "\033[19~");
++			ESCDEBUGPRINTF( "%s: key is F8\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F9:
++			sprintf(outbuf, "\033[20~");
++			ESCDEBUGPRINTF( "%s: key is F9\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F10:
++			sprintf(outbuf, "\033[21~");
++			ESCDEBUGPRINTF( "%s: key is F10\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F11:
++			sprintf(outbuf, "\033[23~");
++			ESCDEBUGPRINTF( "%s: key is F11\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_F12:
++			sprintf(outbuf, "\033[24~");
++			ESCDEBUGPRINTF( "%s: key is F12\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_DC:
++			sprintf(outbuf, "\033[3~");
++			ESCDEBUGPRINTF( "%s: key is delete character\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_END:
++			sprintf(outbuf, "\033[4~");
++			ESCDEBUGPRINTF( "%s: key is end\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_IC:
++			sprintf(outbuf, "\033[2~");
++			ESCDEBUGPRINTF( "%s: key is insert character\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_NPAGE:
++			sprintf(outbuf, "\033[6~");
++			ESCDEBUGPRINTF( "%s: key is page down\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_PPAGE:
++			sprintf(outbuf, "\033[5~");
++			ESCDEBUGPRINTF( "%s: key is page up\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K0:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Op" : "0");
++			ESCDEBUGPRINTF( "%s: key is keypad 0\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K1:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oq" : "1");
++			ESCDEBUGPRINTF( "%s: key is keypad 1\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K2:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Or" : "2");
++			ESCDEBUGPRINTF( "%s: key is keypad 2\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K3:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Os" : "3");
++			ESCDEBUGPRINTF( "%s: key is keypad 3\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K4:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ot" : "4");
++			ESCDEBUGPRINTF( "%s: key is keypad 4\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K5:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ou" : "5");
++			ESCDEBUGPRINTF( "%s: key is keypad 5\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K6:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ov" : "6");
++			ESCDEBUGPRINTF( "%s: key is keypad 6\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K7:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ow" : "7");
++			ESCDEBUGPRINTF( "%s: key is keypad 7\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K8:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ox" : "8");
++			ESCDEBUGPRINTF( "%s: key is keypad 8\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_K9:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oy" : "9");
++			ESCDEBUGPRINTF( "%s: key is keypad 9\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KPLUS:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ok" : "+");
++			ESCDEBUGPRINTF( "%s: key is keypad plus\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KMINUS:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Om" : "-");
++			ESCDEBUGPRINTF( "%s: key is keypad minus\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KDIVIDE:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oo" : "/");
++			ESCDEBUGPRINTF( "%s: key is keypad divide\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KMULTIPLY:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oj" : "*");
++			ESCDEBUGPRINTF( "%s: key is keypad multiply\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KENTER:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033OM" : "\015");
++			ESCDEBUGPRINTF( "%s: key is keypad enter\n", __FUNCTION__);
++			break;
++		case VIMSHELL_KEY_KPOINT:
++			sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033On" : ".");
++			ESCDEBUGPRINTF( "%s: key is keypad point\n", __FUNCTION__);
++			break;
++		default:
++			outbuf[0]=(char)c;
++	}
++
++	if(shell->outbuf_pos+strlen(outbuf)>=sizeof(shell->outbuf))
++	{
++		written=sizeof(shell->outbuf)-shell->outbuf_pos;
++		ESCDEBUGPRINTF( "%s: WARNING: prevented from overflowing the outbuf, help!\n",
++				__FUNCTION__);
++	}
++	else
++		written=strlen(outbuf);
++
++	memcpy(shell->outbuf+shell->outbuf_pos, outbuf, written);
++	shell->outbuf_pos+=written;
++
++	if(terminal_flush_output(shell)<0)
++		return -1;
++
++	return written;
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ui.c ./src/ui.c
+--- ../vim72.orig/src/ui.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/ui.c	2009-10-02 13:39:57.000000000 +0100
+@@ -1786,6 +1786,64 @@
+     len = 0;	/* to avoid gcc warning */
+     for (try = 0; try < 100; ++try)
+     {
++#  ifdef FEAT_VIMSHELL
++	{
++	    /*
++	     * When we use the VIM shell, we use select to look if there was
++	     * some activity on the shells. This is because the read below after
++	     * this block blocks, and this sucks.
++	     *
++	     * This loop is basically here so the shells can send updates while
++	     * we are waiting for the read(2) on the read_cmd_fd to become available.
++	     */
++#  ifndef HAVE_SELECT
++#error sorry - vimshell needs select. programmer is too lazy to write this with poll (at this time)
++#  endif
++	    fd_set rdfd;
++	    buf_T *buf;
++	    int maxfd, ret, done;
++
++	    done=0;
++	    while(!done)
++	    {
++		FD_ZERO(&rdfd);
++		FD_SET(read_cmd_fd, &rdfd);
++		maxfd=read_cmd_fd;
++
++		for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
++		{
++		    if(buf->is_shell!=0)
++		    {
++			FD_SET(buf->shell->fd_master, &rdfd);
++			if( maxfd < buf->shell->fd_master)
++			    maxfd = buf->shell->fd_master;
++		    }
++		}
++
++		ret=select(maxfd+1, &rdfd, NULL, NULL, NULL);
++		if(ret<0)
++		{
++		    /*
++		     * we fsck'd something up ... let's just get out of here
++		     */
++		    done=1;
++		}
++		else if(ret>0)
++		{
++		    if(FD_ISSET(read_cmd_fd, &rdfd))
++		    {
++			/*
++			 * we have what we came here for. exit this loop
++			 * (but only after processing available shell reads)
++			 */
++			done=1;
++		    }
++
++		    vim_shell_do_read_select(rdfd);
++		}
++	    } // while(!done)
++	}
++#  endif
+ #  ifdef VMS
+ 	len = vms_read(
+ #  else
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/version.c ./src/version.c
+--- ../vim72.orig/src/version.c	2009-10-02 13:39:26.000000000 +0100
++++ ./src/version.c	2009-10-02 13:39:57.000000000 +0100
+@@ -581,6 +581,11 @@
+ #else
+ 	"-vertsplit",
+ #endif
++#ifdef FEAT_VIMSHELL
++	"+vimshell",
++#else
++	"-vimshell",
++#endif
+ #ifdef FEAT_VIRTUALEDIT
+ 	"+virtualedit",
+ #else
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim.h ./src/vim.h
+--- ../vim72.orig/src/vim.h	2009-10-02 13:39:24.000000000 +0100
++++ ./src/vim.h	2009-10-02 13:39:57.000000000 +0100
+@@ -396,6 +396,14 @@
+ 
+ /*
+  * The characters and attributes cached for the screen.
++ * VIM-Shell: the VIM-shell really needs more than one byte for the attributes.
++ *            Despite of a single warning during compilation, it seems to work
++ *            fine to simply change the type here.
++ *            We use the sattr_T as follows:
++ *            The lowest byte is handled the same as before, for rendering attributes.
++ *            The remaining byte is split, the uppermost 4 bits for the active foreground
++ *            color, and the lowermost 4 bits for the active background color (at this
++ *            screen position).
+  */
+ typedef char_u schar_T;
+ #ifdef FEAT_SYN_HL
+@@ -2054,6 +2062,10 @@
+ # include <XSUB.h>
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++#include "vim_shell.h"
++#endif
++
+ /* values for vim_handle_signal() that are not a signal */
+ #define SIGNAL_BLOCK	-1
+ #define SIGNAL_UNBLOCK  -2
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.c ./src/vim_shell.c
+--- ../vim72.orig/src/vim_shell.c	1970-01-01 01:00:00.000000000 +0100
++++ ./src/vim_shell.c	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,926 @@
++/*
++ * vim_shell.c
++ *
++ * This is the interface layer of the VIM-Shell. VIM only calls functions from this module,
++ * e.g. create a new VIM-Shell, read characters from the shell or write characters to the
++ * shell. The respective functions pass these things down to the terminal layer, implemented
++ * in terminal.c.
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ */
++
++
++static char *RCSID="$Id$";
++
++#include "vim.h"
++
++#ifdef FEAT_VIMSHELL
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <signal.h>
++#ifdef HAVE_PTY_H
++#include <pty.h>
++#endif
++#ifdef HAVE_TERMIOS_H
++#include <termios.h>
++#endif
++#ifdef HAVE_LIBUTIL_H
++#include <libutil.h>
++#endif
++#include <fcntl.h>
++
++#if !defined(TIOCSWINSZ)
++#  error "VIMSHELL: needs TIOCSWINSZ at the moment, not available on your system, sorry."
++#endif
++
++#ifdef VIMSHELL_DEBUG
++#  define CHILDDEBUG
++#  define SIGDEBUG
++#endif
++
++#ifdef CHILDDEBUG
++#  define CHILDDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
++#else
++#  define CHILDDEBUGPRINTF(a...)
++#endif
++
++#ifdef SIGDEBUG
++#  define SIGDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
++#else
++#  define SIGDEBUGPRINTF(a...)
++#endif
++
++
++int vimshell_errno;
++
++FILE *vimshell_debug_fp=NULL;
++
++/*
++ * Main initialization function. Sets up global things always needed for the VIM shell.
++ */
++int vim_shell_init()
++{
++#ifdef VIMSHELL_DEBUG
++	vimshell_debug_fp=fopen("vimshell.debug", "w");
++#endif
++
++	/*
++	 * Everything went OK
++	 */
++	return 0;
++}
++
++/*
++ * A routine that prints a buffer in 'hexdump -C'-style via printf
++ */
++static void hexdump(FILE *fp, unsigned char *buffer, long len)
++{
++	unsigned long pos=0;
++
++	while(len>0)
++	{
++		int i;
++		fprintf(fp,"%08x  ",(unsigned int)pos);
++		for(i=0;i<16 && i<len;i++)
++		{
++			fprintf(fp,"%02x ",buffer[pos+i]);
++			if(i==7 || i==15)
++				fprintf(fp," ");
++		}
++		fprintf(fp,"|");
++		for(i=0;i<16 && i<len;i++)
++		{
++			unsigned char c=buffer[pos+i];
++			if(isprint(c))
++			{
++				fprintf(fp,"%c",c);
++			}
++			else
++			{
++				fprintf(fp,".");
++			}
++		}
++		fprintf(fp,"|\n");
++		len-=16;
++		pos+=16;
++	}
++}
++
++/*
++ * Create a new window.
++ * @return: pointer to a new struct vim_shell_window on success
++ *          NULL on failure
++ */
++struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height)
++{
++	struct vim_shell_window *rval;
++	int i;
++
++	rval=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
++	if(rval==NULL)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		return NULL;
++	}
++
++	memset(rval, 0, sizeof(struct vim_shell_window));
++
++	rval->size_x=width;
++	rval->size_y=height;
++
++	rval->fgcolor=VIMSHELL_COLOR_DEFAULT;
++	rval->bgcolor=VIMSHELL_COLOR_DEFAULT;
++
++	rval->G0_charset='B';  // United States (USASCII)
++	rval->G1_charset='0';  // Special graphics characters and line drawing set
++	rval->active_charset=0;
++
++	rval->winbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
++	rval->charset=(uint8_t *)vim_shell_malloc(width*height);
++	rval->tabline=(uint8_t *)vim_shell_malloc(width);
++	//rval->phys_screen=(uint32_t *)vim_shell_malloc(width*height*4);
++	if(rval->winbuf==NULL || rval->fgbuf==NULL || rval->bgbuf==NULL || rval->rendbuf==NULL || rval->charset==NULL ||
++			rval->tabline==NULL /* || rval->phys_screen==NULL */)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		// VIMSHELL TODO: cleanup, free the buffers that were successfully allocated
++		vim_shell_free(rval);
++		return NULL;
++	}
++	memset(rval->winbuf, ' ', width*height);
++	memset(rval->fgbuf, rval->fgcolor, width*height);
++	memset(rval->bgbuf, rval->bgcolor, width*height);
++	memset(rval->rendbuf, 0, width*height);
++	memset(rval->charset, 0, width*height);
++	memset(rval->tabline, 0, width);
++
++#if 0
++	for(i=0;i<width*height;i++)
++	{
++		/*
++		 * This is: default foreground, default background, no rendering attributes, ' ' as character
++		 */
++		rval->phys_screen[i]=0x09090020;
++	}
++#endif
++
++	/*
++	 * Set a tab every 8 columns (default)
++	 */
++	for(i=1;i<width;i++)
++	{
++		if((i+1)%8==0 && i+1<width)
++			rval->tabline[i]=1;
++	}
++
++	rval->wraparound=1;
++
++	rval->cursor_x=0;
++	rval->cursor_y=0;
++	rval->cursor_visible=1;
++
++	rval->scroll_top_margin=0;
++	rval->scroll_bottom_margin=height-1;
++
++	CHILDDEBUGPRINTF("%s: vimshell created, width = %d, height = %d\n",
++			__FUNCTION__, width, height);
++
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return rval;
++}
++
++/*
++ * start the program in argv in the shell window.
++ */
++int vim_shell_start(struct vim_shell_window *shell, char *argv[])
++{
++	struct winsize winsize;
++	struct termios termios;
++
++	memset(&termios, 0, sizeof(struct termios));
++
++	/*
++	 * Set terminal parameters.
++	 */
++	termios.c_iflag=ICRNL;
++	termios.c_oflag=ONLCR | OPOST;
++	termios.c_cflag=CS8 | CREAD | HUPCL;
++	termios.c_lflag=ECHO | ECHOE | ECHOK | ECHOKE | ISIG | ECHOCTL | ICANON;
++	termios.c_cc[VMIN]=1;
++	termios.c_cc[VTIME]=0;
++	termios.c_cc[VINTR]=003;
++	termios.c_cc[VQUIT]=034;
++	termios.c_cc[VERASE]=0177;
++	termios.c_cc[VKILL]=025;
++	termios.c_cc[VEOF]=004;
++	termios.c_cc[VSTART]=021;
++	termios.c_cc[VSTOP]=023;
++	termios.c_cc[VSUSP]=032;
++
++	winsize.ws_row=shell->size_y;
++	winsize.ws_col=shell->size_x;
++	winsize.ws_xpixel=0;
++	winsize.ws_ypixel=0;
++
++	/*
++	 * allocate a pty, fork and exec the command
++	 */
++	shell->pid=forkpty(&shell->fd_master, NULL, &termios, &winsize);
++	if(shell->pid==0)
++	{
++		/*
++		 * child code
++		 */
++		setenv("TERM", "screen", 1);
++		if(execvp(*argv, argv)<0)
++		{
++			vimshell_errno=VIMSHELL_EXECV_ERROR;
++			// VIMSHELL TODO close fds??
++			return -1;
++		}
++	}
++	else if(shell->pid<0)
++	{
++		vimshell_errno=VIMSHELL_FORKPTY_ERROR;
++		return -1;
++	}
++
++	/*
++	 * Set the file descriptor to non-blocking
++	 */
++	if(fcntl(shell->fd_master, F_SETFL, fcntl(shell->fd_master, F_GETFL) | O_NONBLOCK)<0)
++	{
++		vimshell_errno=VIMSHELL_FCNTL_ERROR;
++		return -1;
++	}
++
++	/*
++	 * parent code
++	 */
++	if(ioctl(shell->fd_master, TIOCSWINSZ, &winsize)<0)
++	{
++		CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
++				__FUNCTION__,strerror(errno));
++	}
++
++	return 0;
++}
++
++/*
++ * this is much like strerror, only with vimshell_errno. Additionally, if errno is not
++ * null, the formatted error message (strerror) will be appended to the output.
++ */
++char *vim_shell_strerror()
++{
++	static char errbuf[200];
++	static char *errmsg[]={"Success",
++		"Out of memory",
++		"forkpty error",
++		"read error",
++		"write error",
++		"execv error",
++		"sigaction error",
++	        "read (EOF)",
++	        "fcntl error"};
++
++	if(errno==0)
++		return errmsg[vimshell_errno];
++
++	snprintf(errbuf, sizeof(errbuf), "%s: %s", errmsg[vimshell_errno], strerror(errno));
++	return errbuf;
++}
++
++/*
++ * Read what is available from the master pty and tear it through the
++ * terminal emulation. This will fill the window buffer.
++ */
++int vim_shell_read(struct vim_shell_window *shell)
++{
++	// for now, copy what we have into the window buffer.
++	char input[2000];
++	int rval;
++
++retry:
++	if((rval=read(shell->fd_master, input, sizeof(input)))<0)
++	{
++		if(errno==EINTR)
++			goto retry;
++		if(errno==EAGAIN)
++		{
++			/*
++			 * This function should only be called when there really
++			 * are bytes available to read from the fd_master. This
++			 * is ensured by calling select() before this function.
++			 * But it seems that there is a race with a SIGWINSZ right
++			 * in the middle of a select() (reporting there are characters
++			 * available) and the following read() that will block forever.
++			 * It seems that SIGWINSZ flushes the processes input queue, at
++			 * least on Linux.
++			 *
++			 * So if we get here although there is nothing to read, don't
++			 * report an error, just return successfully.
++			 */
++			goto success;
++		}
++
++		vimshell_errno=VIMSHELL_READ_ERROR;
++		return -1;
++	}
++
++	if(rval==0)
++	{
++		/*
++		 * This means end-of-file, the subprocess exited.
++		 */
++		vimshell_errno=VIMSHELL_READ_EOF;
++		return -1;
++	}
++
++#ifdef RAWDEBUG
++	fprintf(vimshell_debug_fp, "\nincoming bytes:\n");
++	hexdump(vimshell_debug_fp, input, rval);
++#endif
++
++	/*
++	 * Interface to the terminal layer: give the input buffer to the
++	 * terminal emulator for processing.
++	 */
++	vim_shell_terminal_input(shell, input, rval);
++
++success:
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return 0;
++}
++
++/*
++ * Write a character to the VIM-Shell.
++ * Blow it through terminal_output so it gets translated correctly etc...
++ */
++int vim_shell_write(struct vim_shell_window *shell, int c)
++{
++	if(vim_shell_terminal_output(shell, c)<0)
++	{
++		vimshell_errno=VIMSHELL_WRITE_ERROR;
++		return -1;
++	}
++
++	vimshell_errno=VIMSHELL_SUCCESS;
++	return 0;
++}
++
++/*
++ * Free everything that is associated with this shell window.
++ * Also terminates the process. The shell pointer will be set to NULL.
++ * The buffer will be restored to a usable, empty buffer.
++ */
++void vim_shell_delete(buf_T *buf)
++{
++	struct vim_shell_window *sh=buf->shell;
++	int status;
++	pid_t pid;
++
++	/*
++	 * First, kill the child and wait for it.
++	 * VIMSHELL TODO: this can be extended a lot. e.g. using a SIGCHLD handler
++	 * or an SIGALRM handler and kill(SIGKILL) the process when the alarm fires
++	 * etc. But for now (and most of all cases) this should be OK.
++	 */
++	pid=sh->pid;
++	if(pid>0)
++	{
++		kill(pid, SIGTERM);
++		kill(pid, SIGHUP);
++		while(waitpid(pid, &status, 0)<0 && errno==EINTR);
++		CHILDDEBUGPRINTF( "%s: PID %u terminated, exit status = %d\n", __FUNCTION__, pid,
++			WEXITSTATUS(status));
++	}
++
++	/*
++	 * The child is dead. Clean up
++	 */
++	close(sh->fd_master);
++	if(sh->alt)
++	{
++		vim_shell_free(sh->alt->winbuf);
++		vim_shell_free(sh->alt->fgbuf);
++		vim_shell_free(sh->alt->bgbuf);
++		vim_shell_free(sh->alt->rendbuf);
++		vim_shell_free(sh->alt->tabline);
++		vim_shell_free(sh->alt->charset);
++		vim_shell_free(sh->alt);
++		sh->alt=NULL;
++	}
++	vim_shell_free(sh->winbuf);
++	vim_shell_free(sh->fgbuf);
++	vim_shell_free(sh->bgbuf);
++	vim_shell_free(sh->rendbuf);
++	vim_shell_free(sh->tabline);
++	vim_shell_free(sh->charset);
++	vim_shell_free(sh);
++
++	CHILDDEBUGPRINTF( "%s: vimshell %p freed.\n", __FUNCTION__, sh);
++
++	buf->is_shell=0;
++	buf->shell=NULL;
++	buf->b_p_ro=FALSE;
++}
++
++/*
++ * Does the work of actually resizing the shell's buffers. Deallocating them,
++ * reallocating them, copying over the old contents to the right places, etc...
++ * rval: 0 = success, <0 = error
++ */
++static int internal_screenbuf_resize(struct vim_shell_window *shell, int width, int height)
++{
++	uint8_t *owinbuf, *ofgbuf, *obgbuf, *orendbuf, *otabline, *ocharset;
++	int x, y, len, vlen;
++	uint16_t oldwidth, oldheight;
++
++	oldwidth=shell->size_x;
++	oldheight=shell->size_y;
++	shell->size_x=(uint16_t)width;
++	shell->size_y=(uint16_t)height;
++
++	owinbuf=shell->winbuf;
++	ofgbuf=shell->fgbuf;
++	obgbuf=shell->bgbuf;
++	orendbuf=shell->rendbuf;
++	ocharset=shell->charset;
++	otabline=shell->tabline;
++
++	shell->winbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
++	shell->charset=(uint8_t *)vim_shell_malloc(width*height);
++	shell->tabline=(uint8_t *)vim_shell_malloc(width);
++	if(shell->winbuf==NULL || shell->fgbuf==NULL || shell->bgbuf==NULL || shell->rendbuf==NULL || shell->charset==NULL ||
++			shell->tabline==NULL)
++	{
++		vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
++		if(shell->winbuf) vim_shell_free(shell->winbuf);
++		if(shell->fgbuf) vim_shell_free(shell->fgbuf);
++		if(shell->bgbuf) vim_shell_free(shell->bgbuf);
++		if(shell->rendbuf) vim_shell_free(shell->rendbuf);
++		if(shell->charset) vim_shell_free(shell->charset);
++		if(shell->tabline) vim_shell_free(shell->tabline);
++
++		/*
++		 * Reassign the old buffers, they are still valid. And bring the shell
++		 * back to a sane state.
++		 */
++		shell->winbuf=owinbuf;
++		shell->fgbuf=ofgbuf;
++		shell->bgbuf=obgbuf;
++		shell->rendbuf=orendbuf;
++		shell->charset=ocharset;
++		shell->tabline=otabline;
++
++		shell->size_x=oldwidth;
++		shell->size_y=oldheight;
++
++		return -1;
++	}
++	memset(shell->winbuf, ' ', width*height);
++	memset(shell->fgbuf, shell->fgcolor, width*height);
++	memset(shell->bgbuf, shell->bgcolor, width*height);
++	memset(shell->rendbuf, 0, width*height);
++	memset(shell->charset, 0, width*height);
++	memset(shell->tabline, 0, width);
++
++	CHILDDEBUGPRINTF( "%s: width = %d, height = %d, oldwidth = %d, oldheight = %d\n",__FUNCTION__,width,height,
++			oldwidth,oldheight);
++
++	/*
++	 * copy over the old contents of the screen, line by line (!)
++	 */
++	len=(oldwidth<width ? oldwidth : width);
++	vlen=(oldheight<height ? oldheight : height);
++	for(y=0;y<vlen;y++)
++	{
++		int y_off;
++		y_off=oldheight-vlen;
++		memcpy(shell->winbuf+y*width, owinbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->fgbuf+y*width, ofgbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->bgbuf+y*width, obgbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->rendbuf+y*width, orendbuf+(y+y_off)*oldwidth, len);
++		memcpy(shell->charset+y*width, ocharset+(y+y_off)*oldwidth, len);
++	}
++	memcpy(shell->tabline, otabline, len);
++
++	/*
++	 * free the old contents
++	 */
++	vim_shell_free(owinbuf);
++	vim_shell_free(ofgbuf);
++	vim_shell_free(obgbuf);
++	vim_shell_free(orendbuf);
++	vim_shell_free(otabline);
++	vim_shell_free(ocharset);
++
++	/*
++	 * Correct tabs
++	 */
++	if(oldwidth<width)
++	{
++		for(x=oldwidth;x<width;x++)
++		{
++			if((x+1)%8==0 && x+1<width)
++				shell->tabline[x]=1;
++		}
++	}
++
++	/*
++	 * Correct cursor
++	 */
++	if(shell->cursor_x>=shell->size_x)
++		shell->cursor_x=shell->size_x-1;
++	if(shell->cursor_y>=shell->size_y)
++		shell->cursor_y=shell->size_y-1;
++
++	/*
++	 * Update scroll region
++	 */
++	shell->scroll_top_margin=0;
++	shell->scroll_bottom_margin=shell->size_y-1;
++
++	/*
++	 * Invalidate the vimshell screen buffer, so vim_shell_redraw redraws the whole
++	 * screen.
++	 */
++	shell->force_redraw=1;
++
++	return 0;
++}
++
++/*
++ * Resizes the shell.
++ * It reallocates all the size dependant buffers and instructs the shell to change
++ * its size.
++ * The width and height parameters are the *desired* width and height. The actual
++ * width and height is dependant on wether all windows that currently render this shell
++ * are able to display this width and height.
++ */
++void vim_shell_resize(struct vim_shell_window *shell, int want_width, int want_height)
++{
++	int width, height;
++	struct winsize ws;
++	win_T *win;
++
++	width=want_width;
++	height=want_height;
++	FOR_ALL_WINDOWS(win)
++	{
++		if(win->w_buffer && win->w_buffer->is_shell && win->w_buffer->shell==shell)
++		{
++			if(win->w_width<width)
++				width=win->w_width;
++			if(win->w_height<height)
++				height=win->w_height;
++		}
++	}
++
++	CHILDDEBUGPRINTF( "%s: resizing to %d, %d\n",__FUNCTION__,width,height);
++
++	if(internal_screenbuf_resize(shell, width, height)<0)
++	{
++		CHILDDEBUGPRINTF("%s: error while resizing.\n", __FUNCTION__);
++		return;
++	}
++	if(shell->alt!=NULL)
++	{
++		if(internal_screenbuf_resize(shell->alt, width, height)<0)
++		{
++			CHILDDEBUGPRINTF("%s: error while resizing the backup screen. Recovering...\n", __FUNCTION__);
++
++			/*
++			 * We now really have a problem. The main shell window is already
++			 * resized and this one didn't work. What should we do? Just destroy the screen
++			 * backup so it never gets restored. internal_screenbuf_resize already did
++			 * the job to of freeing the SINGle buffers, we just have to free the remaining struct.
++			 */
++			vim_shell_free(shell->alt);
++			shell->alt=NULL;
++		}
++	}
++
++	/*
++	 * Tell the shell that the size has changed.
++	 */
++	ws.ws_row=height;
++	ws.ws_col=width;
++	ws.ws_xpixel=0;
++	ws.ws_ypixel=0;
++	if(ioctl(shell->fd_master, TIOCSWINSZ, &ws)<0)
++	{
++		CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
++				__FUNCTION__,strerror(errno));
++	}
++}
++
++/*
++ * Draws the Shell-Buffer into the VIM-Window.
++ */
++void vim_shell_redraw(struct vim_shell_window *shell, win_T *win)
++{
++	int x, y;
++	int win_row, win_col;
++	int off;
++	int last_set_fg, last_set_bg;
++	int cs_state;
++	int term_is_bold, term_is_underline, term_is_negative;
++	int saved_screen_cur_row, saved_screen_cur_col;
++	int force_redraw;
++	int using_gui=0;
++	int t_colors_original=t_colors;
++
++	if(t_colors>15)
++	{
++		t_colors = 15;
++	}
++
++#ifdef FEAT_GUI
++	if(gui.in_use)
++	{
++		using_gui=1;
++	}
++#endif
++
++	win_row=W_WINROW(win);
++	win_col=W_WINCOL(win);
++
++	force_redraw=shell->force_redraw;
++
++	// invalidate the color cache
++	last_set_fg=last_set_bg=-1;
++	cs_state=VIMSHELL_CHARSET_USASCII;
++
++	saved_screen_cur_row=screen_cur_row;
++	saved_screen_cur_col=screen_cur_col;
++
++	// go to normal mode
++	term_is_bold=term_is_underline=term_is_negative=0;
++	screen_stop_highlight();
++
++	for(y=0;y<shell->size_y;y++)
++	{
++		size_t index=y*shell->size_x;
++		int skipped, y_reposition_necessary;
++
++		off=LineOffset[win_row+y]+win_col;
++		skipped=0;
++		y_reposition_necessary=1;
++		for(x=0;x<shell->size_x;x++)
++		{
++			uint8_t c=shell->winbuf[index];
++			sattr_T r=(sattr_T)shell->rendbuf[index];
++			uint8_t fg=shell->fgbuf[index];
++			uint8_t bg=shell->bgbuf[index];
++			uint8_t cs=shell->charset[index];
++			uint8_t fg_color=fg&0xF;
++			uint8_t bg_color=bg&0xF;
++			if(t_colors > 15)
++			{
++				bg_color=0x00;
++				fg_color=0x03;
++			}
++
++			/*
++			 * Switch terminal charset if necessary
++			 */
++			if(cs_state!=cs)
++			{
++				cs_state=cs;
++				if(cs==VIMSHELL_CHARSET_USASCII)
++				{
++					// VIMSHELL TODO: make a term code out of this hack
++					out_str_nf("\033(B");
++					CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
++				}
++				else if(cs==VIMSHELL_CHARSET_DRAWING)
++				{
++					// VIMSHELL TODO: make a term code out of this hack
++					out_str_nf("\033(0");
++					CHILDDEBUGPRINTF( "%s: switched terminal to alternate charset\n",__FUNCTION__);
++				}
++			}
++
++			/*
++			 * Store the foreground and background color along with the rendering attributes.
++			 */
++			r |= (fg&0x0F)<<12 | (bg&0x0F)<<8;
++
++			/*
++			 * Only do an update if render attributes or the character
++			 * has changed at this position.
++			 */
++			if(ScreenLines[off]!=c || ScreenAttrs[off]!=r || force_redraw)
++			{
++				// render attributes
++				if( ((r & RENDITION_BOLD)==0) == (term_is_bold==0) &&
++						((r & RENDITION_UNDERSCORE)==0) == (term_is_underline==0) &&
++						((r & RENDITION_NEGATIVE)==0) == (term_is_negative==0))
++				{
++					/*
++					 * already in the right rendition mode ...
++					 */
++				}
++				else if(using_gui==0)
++				{
++					out_str_nf(T_ME);
++					term_is_bold=term_is_underline=term_is_negative=0;
++					last_set_fg=last_set_bg=-1;
++					if ((r & RENDITION_BOLD) && !term_is_bold)
++					{
++						if(T_MD!=NULL)
++							out_str_nf(T_MD);
++						term_is_bold=1;
++					}
++					if ((r & RENDITION_UNDERSCORE) && !term_is_underline)
++					{
++						if(T_US != NULL)
++							out_str_nf(T_US);
++						term_is_underline=1;
++					}
++					if ((r & RENDITION_NEGATIVE) && !term_is_negative)
++					{
++						if(T_MR!=NULL)
++							out_str_nf(T_MR);
++						term_is_negative=1;
++					}
++				}
++
++				// colors
++				if(t_colors > 1 && using_gui==0)
++				{
++					// VIMSHELL TODO: not every terminal will understand these colors ...
++					// look at tag:cterm_normal_fg_color
++					if(last_set_fg!=fg_color)
++					{
++						term_fg_color(fg_color);
++						last_set_fg=fg_color;
++					}
++					if(last_set_bg!=bg_color)
++					{
++						term_bg_color(bg_color);
++						last_set_bg=bg_color;
++					}
++				}
++
++				ScreenLines[off]=c;
++				ScreenAttrs[off]=r;
++
++				if(y_reposition_necessary || skipped>0)
++				{
++					/*
++					 * Bring the cursor to where we need it.
++					 */
++					term_windgoto(win_row+y, win_col+x);
++					skipped=0;
++					y_reposition_necessary=0;
++				}
++
++				// print it
++				out_char(c);
++			}
++			else
++			{
++				skipped++;
++			}
++
++			off++;
++			index++;
++		}
++	}
++	/*
++	 * Always leave this function with the normal ASCII charset enabled and
++	 * with sane rendering attributes (normal mode).
++	 */
++	if(cs_state!=VIMSHELL_CHARSET_USASCII)
++	{
++		// VIMSHELL TODO: make a term code out of this hack
++		out_str_nf("\033(B");
++		CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
++	}
++
++	/*
++	 * Move the cursor to where VIM thinks it is :)
++	 */
++	term_windgoto(saved_screen_cur_row, saved_screen_cur_col);
++
++	/*
++	 * Position the cursor.
++	 * VIMSHELL TODO: we could cache that, e.g. when the cursor didn't move don't turn
++	 * it on again etc.
++	 */
++	win->w_wrow=shell->cursor_y;
++	win->w_wcol=shell->cursor_x;
++	setcursor();
++	cursor_on();
++
++	/*
++	 * Restore the rendering attributes
++	 */
++	out_str_nf(T_ME);
++	screen_start_highlight(screen_attr);
++	out_flush();
++
++	if(shell->force_redraw)
++		shell->force_redraw=0;
++
++	t_colors = t_colors_original;
++}
++
++/*
++ * Really do the read, finally :)
++ * Returns 1 if the contents of the window are VALID (in VIM speak)
++ * Returns 2 if the contents have to be CLEARed (after the shell has died)
++ */
++int vim_shell_do_read_lowlevel(buf_T *buf)
++{
++	int rval=1;
++	if(vim_shell_read(buf->shell)<0)
++	{
++		/*
++		 * Shell died? Cleanup. Also remove the RO attribute from the
++		 * buffer.
++		 */
++		vim_shell_delete(buf);
++		rval=2;
++	}
++
++	return rval;
++}
++
++/*
++ * This function is called from two places: os_unix.c and ui.c, and handles
++ * shell reads that are necessary because a select() became ready. This function
++ * is here to avoid identical code in both places.
++ * It returns the number of shell-reads.
++ * If there was no activity in any of the shells, it returns 0.
++ */
++int vim_shell_do_read_select(fd_set rfds)
++{
++	/*
++	 * Loop through all buffers and see if they are vimshells.
++	 * If yes, check if there are read events ready for the appropriate
++	 * fds. If so, call the shell's read handler.
++	 */
++	buf_T *buf;
++	int did_redraw=0;
++	int rval=0;
++
++	for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
++	{
++		if(buf->is_shell != 0)
++		{
++			if(FD_ISSET(buf->shell->fd_master, &rfds))
++			{
++				int r;
++
++				r=vim_shell_do_read_lowlevel(buf);
++				if(r>did_redraw)
++					did_redraw=r;
++
++				rval++;
++
++				if(r==1 && updating_screen==FALSE)
++					redraw_buf_later(buf, VALID);
++				else if(r==2 && updating_screen==FALSE)
++					redraw_buf_later(buf, CLEAR);
++			}
++		}
++	}
++
++	/*
++	 * Only redraw if we aren't currently redrawing, to avoid endless recursions.
++	 * update_screen calls win_update, which calls win_line, which calls breakcheck,
++	 * which again calls RealWaitForChar which calls this function ...
++	 */
++	if(updating_screen==FALSE)
++	{
++		if(did_redraw==1)
++		{
++			update_screen(VALID);
++		}
++		else if(did_redraw==2 || did_redraw==3)
++		{
++			update_screen(CLEAR);
++			out_flush();
++		}
++	}
++
++	return rval;
++}
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.h ./src/vim_shell.h
+--- ../vim72.orig/src/vim_shell.h	1970-01-01 01:00:00.000000000 +0100
++++ ./src/vim_shell.h	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,273 @@
++/*
++ * vim_shell.h
++ *
++ * Global include file for VIM-Shell. Defines structures and interfaces.
++ *
++ * This file is part of the VIM-Shell project. http://vimshell.wana.at
++ *
++ * Author: Thomas Wana <thomas at wana.at>
++ *
++ * $Id$
++ */
++
++#ifndef __VIMSHELL_H
++
++#define __VIMSHELL_H
++
++#include "vim.h"
++
++#include <stdio.h>
++#ifdef HAVE_STDINT_H
++#include <stdint.h>
++#endif
++#include <sys/types.h>
++#include <sys/select.h>
++
++/*
++ * Master debug flag. Disable this and no debug messages at all will
++ * be written anywhere.
++ */
++//#define VIMSHELL_DEBUG
++
++/*
++ * Rendition constants
++ */
++#define RENDITION_BOLD 1
++#define RENDITION_UNDERSCORE 2
++#define RENDITION_BLINK 4
++#define RENDITION_NEGATIVE 8
++#define RENDITION_DIM 16
++#define RENDITION_HIDDEN 32
++
++/*
++ * charset constants
++ */
++#define VIMSHELL_CHARSET_USASCII 0
++#define VIMSHELL_CHARSET_DRAWING 1
++
++/*
++ * Color constants
++ */
++#define VIMSHELL_COLOR_BLACK 0
++#define VIMSHELL_COLOR_RED 1
++#define VIMSHELL_COLOR_GREEN 2
++#define VIMSHELL_COLOR_YELLOW 3
++#define VIMSHELL_COLOR_BLUE 4
++#define VIMSHELL_COLOR_MAGENTA 5
++#define VIMSHELL_COLOR_CYAN 6
++#define VIMSHELL_COLOR_WHITE 7
++#define VIMSHELL_COLOR_DEFAULT 9
++
++#define vim_shell_malloc alloc
++#define vim_shell_free vim_free
++
++/*
++ * The main vim_shell_window struct.
++ * Holds everything that is needed to know about a single
++ * vim shell. (like file descriptors, window buffers, window
++ * positions, etc)
++ */
++struct vim_shell_window
++{
++	/*
++	 * current dimensions of the window
++	 */
++	uint16_t size_x;
++	uint16_t size_y;
++
++	/*
++	 * cursor position and visible flag
++	 */
++	uint16_t cursor_x;
++	uint16_t cursor_y;
++	uint16_t cursor_visible;
++
++	/*
++	 * Saved cursor positions (ESC 7, ESC 8)
++	 */
++	uint16_t saved_cursor_x;
++	uint16_t saved_cursor_y;
++
++	/*
++	 * We support the xterm title hack and store the title in this buffer.
++	 */
++	char windowtitle[50];
++
++	/*
++	 * The output buffer. This is necessary because writes to the shell can be delayed,
++	 * e.g. if we are waiting for an incoming ESC sequence to complete.
++	 */
++	uint8_t outbuf[100];
++	uint8_t outbuf_pos;
++
++	/*
++	 * Pointer to the window buffer.
++	 * The window buffer is the internal representation of the
++	 * window's content. The vim shell receives characters from
++	 * the terminal, which the terminal emulation translates into
++	 * e.g. cursor positions or actual characters. These are placed
++	 * here at the right screen position. Its size is size_y*size_x.
++	 */
++	uint8_t *winbuf;
++	uint8_t *fgbuf;
++	uint8_t *bgbuf;
++	uint8_t *rendbuf;
++	uint8_t *charset;
++
++	/*
++	 * The tabulator line. It represents a single row. Zero means no
++	 * tab at this position, 1 means there is a tab.
++	 */
++	uint8_t *tabline;
++
++	/*
++	 * These buffers hold what's currently physical on the screen.
++	 * Note, not on the "virtual" screen, that is the image of the shell,
++	 * but the real screen that is printed out in vim_shell_redraw.
++	 * This is mainly to implement caching features...
++	 * We hold here:
++	 * 1 byte foreground-color
++	 * 1 byte background-color
++	 * 1 byte rendering attributes
++	 * 1 byte the actual character
++	 */
++	uint32_t *phys_screen;
++
++	/*
++	 * Flag that determines if we are right in the middle of an
++	 * escape sequence coming in.
++	 */
++	uint8_t in_esc_sequence;
++
++	/*
++	 * Buffer for a escape sequence in progress (see in_esc_sequence).
++	 */
++	uint8_t esc_sequence[50];
++
++	/*
++	 * Auto-Margin enabled?
++	 */
++	uint8_t wraparound;
++
++	/*
++	 * Caused the last character a warp around?
++	 */
++	uint8_t just_wrapped_around;
++
++	/*
++	 * The currently used rendition of the shell.
++	 */
++	uint8_t rendition;
++	uint8_t saved_rendition;
++
++	/*
++	 * The currently active colors.
++	 */
++	uint8_t fgcolor;
++	uint8_t bgcolor;
++	uint8_t saved_fgcolor;
++	uint8_t saved_bgcolor;
++
++	/*
++	 * Scroll region.
++	 */
++	uint8_t scroll_top_margin;
++	uint8_t scroll_bottom_margin;
++
++	/*
++	 * Charset configuration.
++	 */
++	uint8_t G0_charset;
++	uint8_t G1_charset;
++	uint8_t active_charset;
++	uint8_t saved_G0_charset;
++	uint8_t saved_G1_charset;
++	uint8_t saved_active_charset;
++
++	/*
++	 * Mode switches.
++	 */
++	uint8_t application_keypad_mode;
++	uint8_t application_cursor_mode;
++	uint8_t saved_application_keypad_mode;
++	uint8_t saved_application_cursor_mode;
++
++	uint8_t insert_mode;
++	uint8_t saved_insert_mode;
++
++	/*
++	 * This flag determines if the shell should be completely redrawn in the next
++	 * vim_shell_redraw, regardless of what we think to know about the screen.
++	 */
++	uint8_t force_redraw;
++
++	/*
++	 * Pointer to the alternate screen. If NULL, there is no alternate screen.
++	 * If not NULL, this holds a backup of the screen contents and properties
++	 * before the screen switch. Switching back means to copy back the contents
++	 * of the alternate screen to the main screen and freeing the alternate screen.
++	 */
++	struct vim_shell_window *alt;
++
++	/*
++	 * file descriptor of the master side of the pty
++	 */
++	int fd_master;
++
++	/*
++	 * pid of the subshell
++	 */
++	pid_t pid;
++
++};
++
++/*
++ * This is set when something goes wrong in one of the
++ * vim_shell functions.
++ */
++extern int vimshell_errno;
++
++/*
++ * The debug handle where debug-messages will be written
++ */
++extern FILE *vimshell_debug_fp;
++
++#define VIMSHELL_SUCCESS 0
++#define VIMSHELL_OUT_OF_MEMORY 1
++#define VIMSHELL_FORKPTY_ERROR 2
++#define VIMSHELL_READ_ERROR 3
++#define VIMSHELL_WRITE_ERROR 4
++#define VIMSHELL_EXECV_ERROR 5
++#define VIMSHELL_SIGACTION_ERROR 6
++#define VIMSHELL_READ_EOF 7
++#define VIMSHELL_FCNTL_ERROR 8
++
++/*
++ * vim_shell.c
++ */
++extern int vim_shell_init();
++extern struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height);
++extern int vim_shell_start(struct vim_shell_window *shell, char *argv[]);
++extern char *vim_shell_strerror();
++extern int vim_shell_read(struct vim_shell_window *shell);
++extern int vim_shell_write(struct vim_shell_window *shell, int c);
++extern void vim_shell_redraw(struct vim_shell_window *shell, win_T *win);
++extern int vim_shell_do_read_select(fd_set rfds);
++extern int vim_shell_do_read_lowlevel(buf_T *buf);
++extern void vim_shell_delete(buf_T *buf);
++extern void vim_shell_resize(struct vim_shell_window *shell, int width, int height);
++
++/*
++ * terminal.c
++ */
++extern void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len);
++extern int vim_shell_terminal_output(struct vim_shell_window *shell, int c);
++
++/*
++ * screen.c
++ */
++extern int screen_cur_row, screen_cur_col;	/* last known cursor position */
++extern void screen_start_highlight __ARGS((int attr));
++extern int screen_attr;
++
++#endif
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/window.c ./src/window.c
+--- ../vim72.orig/src/window.c	2009-10-02 13:39:25.000000000 +0100
++++ ./src/window.c	2009-10-02 13:39:57.000000000 +0100
+@@ -119,6 +119,12 @@
+ # define CHECK_CMDWIN
+ #endif
+ 
++#ifdef FEAT_VIMSHELL
++# define CHECK_VIMSHELL if (curwin->w_buffer->is_shell != 0) { EMSG("VIMSHELL: command not available for shell windows"); break; }
++#else
++# define CHECK_VIMSHELL
++#endif
++
+     switch (nchar)
+     {
+ /* split current window in two parts, horizontally */
+@@ -486,6 +492,7 @@
+ #if defined(FEAT_QUICKFIX)
+     case '}':
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 		if (Prenum)
+ 		    g_do_tagpreview = Prenum;
+ 		else
+@@ -495,6 +502,7 @@
+     case ']':
+     case Ctrl_RSB:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ #ifdef FEAT_VISUAL
+ 		reset_VIsual_and_resel();	/* stop Visual mode */
+ #endif
+@@ -515,6 +523,7 @@
+     case Ctrl_F:
+ wingotofile:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 
+ 		ptr = grab_file_name(Prenum1, &lnum);
+ 		if (ptr != NULL)
+@@ -553,6 +562,7 @@
+     case 'd':			    /* Go to definition, using 'define' */
+     case Ctrl_D:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ 		if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
+ 		    break;
+ 		find_pattern_in_path(ptr, 0, len, TRUE,
+@@ -584,6 +594,7 @@
+     case 'g':
+     case Ctrl_G:
+ 		CHECK_CMDWIN
++		CHECK_VIMSHELL
+ #ifdef USE_ON_FLY_SCROLL
+ 		dont_scroll = TRUE;		/* disallow scrolling here */
+ #endif
+@@ -5555,6 +5566,15 @@
+     wp->w_redr_status = TRUE;
+ #endif
+     invalidate_botline_win(wp);
++
++#ifdef FEAT_VIMSHELL
++    if(wp->w_buffer->is_shell!=0)
++    {
++	struct vim_shell_window *shell=wp->w_buffer->shell;
++	vim_shell_resize(shell, shell->size_x, height);
++	redraw_win_later(wp, CLEAR);
++    }
++#endif
+ }
+ 
+ #ifdef FEAT_VERTSPLIT
+@@ -5577,6 +5597,14 @@
+     }
+     redraw_win_later(wp, NOT_VALID);
+     wp->w_redr_status = TRUE;
++#ifdef FEAT_VIMSHELL
++    if(wp->w_buffer->is_shell!=0)
++    {
++	struct vim_shell_window *shell=wp->w_buffer->shell;
++	vim_shell_resize(shell, width, shell->size_y);
++	redraw_win_later(wp, CLEAR);
++    }
++#endif
+ }
+ #endif
+ 
+diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/test.txt ./test.txt
+--- ../vim72.orig/test.txt	1970-01-01 01:00:00.000000000 +0100
++++ ./test.txt	2009-10-02 13:39:57.000000000 +0100
+@@ -0,0 +1,2 @@
++asdfasdfA
++:q
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20091027/0a3c239a/attachment-0001.html>


More information about the macports-changes mailing list