Ticket #21770: vimshell.patch

File vimshell.patch, 128.6 KB (added by avsm@…, 15 years ago)
  • files/patch-vimshell.diff

     
     1diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/README_vimshell.txt ./README_vimshell.txt
     2--- ../vim72.orig/README_vimshell.txt   1970-01-01 01:00:00.000000000 +0100
     3+++ ./README_vimshell.txt       2009-10-02 13:39:57.000000000 +0100
     4@@ -0,0 +1,12 @@
     5+TESTING
     6+=======
     7+
     8+shell-read with poll(2)
     9+shell-read with select(2) - works
     10+compiling VIM without builtin terminals - only termcap or terminfo - works
     11+GUI-VIM ohne builtin_terms ?
     12+
     13+DOCUMENTATION
     14+=============
     15+
     16+See :help vimshell for documentation.
     17diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/runtime/doc/vimshell.txt ./runtime/doc/vimshell.txt
     18--- ../vim72.orig/runtime/doc/vimshell.txt      1970-01-01 01:00:00.000000000 +0100
     19+++ ./runtime/doc/vimshell.txt  2009-10-02 13:39:57.000000000 +0100
     20@@ -0,0 +1,93 @@
     21+*vimshell.txt*   For Vim version 7.0.  Last change: 2006 Sep 2
     22+
     23+
     24+                 VIM REFERENCE MANUAL    by Bram Moolenaar
     25+
     26+
     27+The VIM-Shell                                            *vimshell*
     28+
     29+1. What is VIM-Shell?
     30+
     31+The VIM-shell is a extension for VIM, a very popular programmer's editor for
     32+many platforms, written by Bram Moolenaar et al. VIM features split windows,
     33+and this patch makes it possible to start shells in those windows. It is only
     34+available for POSIX systems like Linux, FreeBSD, OpenBSD, NetBSD and MacOS X.
     35+I don't think the Windows-VIM needs such a patch, because I think the command
     36+line there isn't really popular.
     37+
     38+==============================================================================
     39+2. How to use the VIM-Shell
     40+
     41+2.1 General concept: ":vimshell"
     42+
     43+The whole VIM-Shell functionality is hidden behind one single command:
     44+:vimshell.
     45+
     46+:vimshell[!] [params] tries to close your active buffer and creates a new one.
     47+This behaves exactly the same as the :enew command (see :help enew im VIM for
     48+details). If you have local modifications to your buffer, the command will be
     49+aborted (but you can override this by adding a ! at the end, in this case the
     50+active buffer will be dismissed in any case). The window containing this empty
     51+buffer is then converted to a VIM-Shell.
     52+
     53+:vimshell
     54+
     55+starts a VIM-Shell in your current window. I strongly suggest you open a new
     56+window before doing that. By default, without any parameters, /bin/sh will be
     57+spawned.
     58+
     59+:vimshell bash
     60+
     61+When called with parameters, VIM-Shell passes these parameters verbatim to
     62+execvp when starting a shell. Your current $PATH will be searched for the
     63+command.
     64+
     65+:vimshell irssi -n anonymous -c vienna.irc.at
     66+
     67+starts the textmode IRC client "irssi" with the abovementioned parameters.
     68+
     69+:vimshell mutt
     70+
     71+Never lose track of your e-mails while working in VIM!
     72+
     73+When you exit such a shell, or the program running in it terminates, the
     74+buffer will be converted back to a normal, empty VIM-buffer. The window will
     75+not be closed.
     76+
     77+2.2 Navigation
     78+
     79+When the currently active window is a VIM-Shell, every character entered gets
     80+routed to the shell, and no mapping expansion takes place. VIM doesn't get any
     81+notice of the characters that you type in a VIM-Shell.
     82+
     83+The big exception is Ctrl_W, which is passed through to VIM, so you can close
     84+the VIM-shell (Ctrl_W + c), change to another window, resize the window, etc.
     85+Key mappings
     86+
     87+Because I feel that opening up a window and then typing :vimshell is a bit
     88+cumbersome, I suggest you use the following key mappings in your .vimrc:
     89+
     90+       " VIM-Shell
     91+       " Ctrl_W e opens up a vimshell in a horizontally split window
     92+       " Ctrl_W E opens up a vimshell in a vertically split window
     93+       " The shell window will be auto closed after termination
     94+       nmap <C-W>e :new \| vimshell bash<CR>
     95+       nmap <C-W>E :vnew \| vimshell bash<CR>
     96+
     97+Just hitting Ctrl_W and e to drop a shell window in your VIM session is
     98+really, really comfortable :-)
     99+
     100+This is a small introduction on how to use the new features in your
     101+VIM-Shell-enabled VIM.
     102+
     103+==============================================================================
     104+3. Authorship
     105+
     106+The VIM-Shell was written in 2004, 2005, 2006 by Thomas Wana <thomas@wana.at>.
     107+Homepage: http://www.wana.at/vimshell/
     108+
     109+The VIM-Shell is published under the GNU GPL license (which is compatible with
     110+the VIM license). The copyright remains by the author.
     111+
     112+==============================================================================
     113+ vim:tw=78:ts=8:ft=help:norl:
     114diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/Makefile ./src/Makefile
     115--- ../vim72.orig/src/Makefile  2009-10-02 13:39:24.000000000 +0100
     116+++ ./src/Makefile      2009-10-02 13:39:57.000000000 +0100
     117@@ -841,7 +841,6 @@
     118 ###     For LynxOS 3.1.0, tested on PC
     119 #EXTRA_LIBS= -lXext -lSM -lICE -lnetinet -lXmu
     120 
     121-
     122 ### (V)  For CX/UX 6.2 (on Harris/Concurrent NightHawk 4800, 5800). Remove
     123 ###     -Qtarget if only in a 5800 environment.  (Kipp E. Howard)
     124 #CFLAGS = -O -Qtarget=m88110compat
     125@@ -1291,7 +1290,6 @@
     126 # Use this for cproto 3 patchlevel 7 or above (use "cproto -V" to check):
     127 PROTO_FLAGS = -m -M__ARGS -d -E"$(CPP)" $(NO_ATTR)
     128 
     129-
     130 ################################################
     131 ##   no changes required below this line      ##
     132 ################################################
     133@@ -1410,6 +1408,8 @@
     134        auto/pathdef.c \
     135        popupmnu.c \
     136        quickfix.c \
     137+       vim_shell.c \
     138+       terminal.c \
     139        regexp.c \
     140        screen.c \
     141        search.c \
     142@@ -1482,6 +1482,8 @@
     143        objects/pathdef.o \
     144        objects/popupmnu.o \
     145        objects/quickfix.o \
     146+       objects/vim_shell.o \
     147+       objects/terminal.o \
     148        objects/regexp.o \
     149        objects/screen.o \
     150        objects/search.o \
     151@@ -2536,6 +2538,12 @@
     152 objects/quickfix.o: quickfix.c
     153        $(CCC) -o $@ quickfix.c
     154 
     155+objects/vim_shell.o: vim_shell.c
     156+       $(CCC) -o $@ vim_shell.c
     157+
     158+objects/terminal.o: terminal.c
     159+       $(CCC) -o $@ terminal.c
     160+
     161 objects/regexp.o: regexp.c
     162        $(CCC) -o $@ regexp.c
     163 
     164@@ -2803,6 +2811,8 @@
     165   auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
     166   regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
     167   globals.h farsi.h arabic.h
     168+objects/terminal.o: terminal.c vim_shell.h
     169+objects/vim_shell.o: vim_shell.c vim_shell.h
     170 objects/regexp.o: regexp.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
     171   ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
     172   gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
     173diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/auto/configure ./src/auto/configure
     174--- ../vim72.orig/src/auto/configure    2009-10-02 13:39:25.000000000 +0100
     175+++ ./src/auto/configure        2009-10-02 13:39:57.000000000 +0100
     176@@ -17145,6 +17145,269 @@
     177 fi
     178 
     179 
     180+if test "$(uname)" = "Darwin"; then
     181+      LIBS="$LIBS"
     182+else
     183+      LIBS="$LIBS -lutil"
     184+fi
     185+
     186+
     187+
     188+for ac_header in pty.h libutil.h stdint.h
     189+do
     190+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
     191+if eval "test \"\${$as_ac_Header+set}\" = set"; then
     192+  echo "$as_me:$LINENO: checking for $ac_header" >&5
     193+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
     194+if eval "test \"\${$as_ac_Header+set}\" = set"; then
     195+  echo $ECHO_N "(cached) $ECHO_C" >&6
     196+fi
     197+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
     198+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
     199+else
     200+  # Is the header compilable?
     201+echo "$as_me:$LINENO: checking $ac_header usability" >&5
     202+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
     203+cat >conftest.$ac_ext <<_ACEOF
     204+/* confdefs.h.  */
     205+_ACEOF
     206+cat confdefs.h >>conftest.$ac_ext
     207+cat >>conftest.$ac_ext <<_ACEOF
     208+/* end confdefs.h.  */
     209+$ac_includes_default
     210+#include <$ac_header>
     211+_ACEOF
     212+rm -f conftest.$ac_objext
     213+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
     214+  (eval $ac_compile) 2>conftest.er1
     215+  ac_status=$?
     216+  grep -v '^ *+' conftest.er1 >conftest.err
     217+  rm -f conftest.er1
     218+  cat conftest.err >&5
     219+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     220+  (exit $ac_status); } &&
     221+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
     222+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
     223+  (eval $ac_try) 2>&5
     224+  ac_status=$?
     225+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     226+  (exit $ac_status); }; } &&
     227+        { ac_try='test -s conftest.$ac_objext'
     228+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
     229+  (eval $ac_try) 2>&5
     230+  ac_status=$?
     231+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     232+  (exit $ac_status); }; }; then
     233+  ac_header_compiler=yes
     234+else
     235+  echo "$as_me: failed program was:" >&5
     236+sed 's/^/| /' conftest.$ac_ext >&5
     237+
     238+ac_header_compiler=no
     239+fi
     240+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     241+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
     242+echo "${ECHO_T}$ac_header_compiler" >&6
     243+
     244+# Is the header present?
     245+echo "$as_me:$LINENO: checking $ac_header presence" >&5
     246+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
     247+cat >conftest.$ac_ext <<_ACEOF
     248+/* confdefs.h.  */
     249+_ACEOF
     250+cat confdefs.h >>conftest.$ac_ext
     251+cat >>conftest.$ac_ext <<_ACEOF
     252+/* end confdefs.h.  */
     253+#include <$ac_header>
     254+_ACEOF
     255+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
     256+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
     257+  ac_status=$?
     258+  grep -v '^ *+' conftest.er1 >conftest.err
     259+  rm -f conftest.er1
     260+  cat conftest.err >&5
     261+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     262+  (exit $ac_status); } >/dev/null; then
     263+  if test -s conftest.err; then
     264+    ac_cpp_err=$ac_c_preproc_warn_flag
     265+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
     266+  else
     267+    ac_cpp_err=
     268+  fi
     269+else
     270+  ac_cpp_err=yes
     271+fi
     272+if test -z "$ac_cpp_err"; then
     273+  ac_header_preproc=yes
     274+else
     275+  echo "$as_me: failed program was:" >&5
     276+sed 's/^/| /' conftest.$ac_ext >&5
     277+
     278+  ac_header_preproc=no
     279+fi
     280+rm -f conftest.err conftest.$ac_ext
     281+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
     282+echo "${ECHO_T}$ac_header_preproc" >&6
     283+
     284+# So?  What about this header?
     285+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
     286+  yes:no: )
     287+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
     288+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
     289+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
     290+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
     291+    ac_header_preproc=yes
     292+    ;;
     293+  no:yes:* )
     294+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
     295+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
     296+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
     297+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
     298+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
     299+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
     300+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
     301+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
     302+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
     303+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
     304+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
     305+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
     306+    (
     307+      cat <<\_ASBOX
     308+## ------------------------------------------ ##
     309+## Report this to the AC_PACKAGE_NAME lists.  ##
     310+## ------------------------------------------ ##
     311+_ASBOX
     312+    ) |
     313+      sed "s/^/$as_me: WARNING:     /" >&2
     314+    ;;
     315+esac
     316+echo "$as_me:$LINENO: checking for $ac_header" >&5
     317+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
     318+if eval "test \"\${$as_ac_Header+set}\" = set"; then
     319+  echo $ECHO_N "(cached) $ECHO_C" >&6
     320+else
     321+  eval "$as_ac_Header=\$ac_header_preproc"
     322+fi
     323+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
     324+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
     325+
     326+fi
     327+if test `eval echo '${'$as_ac_Header'}'` = yes; then
     328+  cat >>confdefs.h <<_ACEOF
     329+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
     330+_ACEOF
     331+
     332+fi
     333+
     334+done
     335+
     336+
     337+for ac_func in forkpty
     338+do
     339+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
     340+echo "$as_me:$LINENO: checking for $ac_func" >&5
     341+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
     342+if eval "test \"\${$as_ac_var+set}\" = set"; then
     343+  echo $ECHO_N "(cached) $ECHO_C" >&6
     344+else
     345+  cat >conftest.$ac_ext <<_ACEOF
     346+/* confdefs.h.  */
     347+_ACEOF
     348+cat confdefs.h >>conftest.$ac_ext
     349+cat >>conftest.$ac_ext <<_ACEOF
     350+/* end confdefs.h.  */
     351+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
     352+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
     353+#define $ac_func innocuous_$ac_func
     354+
     355+/* System header to define __stub macros and hopefully few prototypes,
     356+    which can conflict with char $ac_func (); below.
     357+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
     358+    <limits.h> exists even on freestanding compilers.  */
     359+
     360+#ifdef __STDC__
     361+# include <limits.h>
     362+#else
     363+# include <assert.h>
     364+#endif
     365+
     366+#undef $ac_func
     367+
     368+/* Override any gcc2 internal prototype to avoid an error.  */
     369+#ifdef __cplusplus
     370+extern "C"
     371+{
     372+#endif
     373+/* We use char because int might match the return type of a gcc2
     374+   builtin and then its argument prototype would still apply.  */
     375+char $ac_func ();
     376+/* The GNU C library defines this for functions which it implements
     377+    to always fail with ENOSYS.  Some functions are actually named
     378+    something starting with __ and the normal name is an alias.  */
     379+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
     380+choke me
     381+#else
     382+char (*f) () = $ac_func;
     383+#endif
     384+#ifdef __cplusplus
     385+}
     386+#endif
     387+
     388+int
     389+main ()
     390+{
     391+return f != $ac_func;
     392+  ;
     393+  return 0;
     394+}
     395+_ACEOF
     396+rm -f conftest.$ac_objext conftest$ac_exeext
     397+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
     398+  (eval $ac_link) 2>conftest.er1
     399+  ac_status=$?
     400+  grep -v '^ *+' conftest.er1 >conftest.err
     401+  rm -f conftest.er1
     402+  cat conftest.err >&5
     403+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     404+  (exit $ac_status); } &&
     405+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
     406+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
     407+  (eval $ac_try) 2>&5
     408+  ac_status=$?
     409+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     410+  (exit $ac_status); }; } &&
     411+        { ac_try='test -s conftest$ac_exeext'
     412+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
     413+  (eval $ac_try) 2>&5
     414+  ac_status=$?
     415+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
     416+  (exit $ac_status); }; }; then
     417+  eval "$as_ac_var=yes"
     418+else
     419+  echo "$as_me: failed program was:" >&5
     420+sed 's/^/| /' conftest.$ac_ext >&5
     421+
     422+eval "$as_ac_var=no"
     423+fi
     424+rm -f conftest.err conftest.$ac_objext \
     425+      conftest$ac_exeext conftest.$ac_ext
     426+fi
     427+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
     428+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
     429+if test `eval echo '${'$as_ac_var'}'` = yes; then
     430+  cat >>confdefs.h <<_ACEOF
     431+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
     432+_ACEOF
     433+
     434+fi
     435+done
     436+
     437+if test $ac_cv_func_forkpty = no; then
     438+    { { echo "$as_me:$LINENO: error: vimshell needs forkpty - sorry." >&5
     439+echo "$as_me: error: vimshell needs forkpty - sorry." >&2;}
     440+   { (exit 1); exit 1; }; }
     441+fi
     442+
     443 ac_config_files="$ac_config_files auto/config.mk:config.mk.in"
     444 
     445 cat >confcache <<\_ACEOF
     446diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/buffer.c ./src/buffer.c
     447--- ../vim72.orig/src/buffer.c  2009-10-02 13:39:24.000000000 +0100
     448+++ ./src/buffer.c      2009-10-02 13:39:57.000000000 +0100
     449@@ -575,6 +575,17 @@
     450 #ifdef FEAT_TCL
     451     tcl_buffer_free(buf);
     452 #endif
     453+#ifdef FEAT_VIMSHELL
     454+    if(buf->is_shell!=0)
     455+    {
     456+       /*
     457+        * It is guaranteed that this buffer isn't connected to a
     458+        * window anymore, or else we'd not come up here. So we can
     459+        * savely scrap the shell here.
     460+        */
     461+       vim_shell_delete(buf);
     462+    }
     463+#endif
     464     u_blockfree(buf);              /* free the memory allocated for undo */
     465     ml_close(buf, TRUE);           /* close and delete the memline/memfile */
     466     buf->b_ml.ml_line_count = 0;    /* no lines in buffer */
     467diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/colines.c ./src/colines.c
     468--- ../vim72.orig/src/colines.c 1970-01-01 01:00:00.000000000 +0100
     469+++ ./src/colines.c     2009-10-02 13:39:57.000000000 +0100
     470@@ -0,0 +1,39 @@
     471+#include <stdio.h>
     472+#include <unistd.h>
     473+#include <stdlib.h>
     474+#include <signal.h>
     475+#include <termios.h>
     476+#include <sys/types.h>
     477+#include <pty.h>
     478+
     479+void sigwinch(int arg)
     480+{
     481+       struct winsize ws;
     482+       printf("window size is now: ");
     483+
     484+       if(ioctl(0, TIOCGWINSZ, &ws)<0)
     485+       {
     486+               perror("ioctl");
     487+               return;
     488+       }
     489+       printf("rows = %d, cols = %d\n", ws.ws_row, ws.ws_col);
     490+}
     491+
     492+int main()
     493+{
     494+       struct sigaction sa;
     495+       sa.sa_handler=sigwinch;
     496+       sigemptyset(&sa.sa_mask);
     497+       sa.sa_flags=0;
     498+       if(sigaction(SIGWINCH, &sa, NULL)<0)
     499+       {
     500+               perror("sigaction");
     501+               return -1;
     502+       }
     503+       sigwinch(0);
     504+       while(1)
     505+       {
     506+               sleep(10);
     507+       }
     508+       return 0;
     509+}
     510diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/config.h.in ./src/config.h.in
     511--- ../vim72.orig/src/config.h.in       2009-10-02 13:39:24.000000000 +0100
     512+++ ./src/config.h.in   2009-10-02 13:39:57.000000000 +0100
     513@@ -387,3 +387,8 @@
     514 
     515 /* Define if you want XSMP interaction as well as vanilla swapfile safety */
     516 #undef USE_XSMP_INTERACT
     517+
     518+/* VIMSHELL stuff */
     519+#undef HAVE_PTY_H
     520+#undef HAVE_LIBUTIL_H
     521+#undef HAVE_STDINT_H
     522diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/configure.in ./src/configure.in
     523--- ../vim72.orig/src/configure.in      2009-10-02 13:39:25.000000000 +0100
     524+++ ./src/configure.in  2009-10-02 13:39:57.000000000 +0100
     525@@ -3241,6 +3241,23 @@
     526 fi
     527 AC_SUBST(DEPEND_CFLAGS_FILTER)
     528 
     529+dnl ------------------------------------------------------------------
     530+dnl VIMSHELL configure thingies
     531+dnl needs -lutil, but not on MacOS X
     532+dnl The $MACOSX variable isn't set on the Mac I can use for testing, so we
     533+dnl have to use other means to find out if this is a Mac. uname for example.
     534+if test "$(uname)" = "Darwin"; then
     535+      LIBS="$LIBS"
     536+else
     537+      LIBS="$LIBS -lutil"
     538+fi
     539+AC_CHECK_HEADERS(pty.h libutil.h stdint.h)
     540+AC_CHECK_FUNCS(forkpty)
     541+if test $ac_cv_func_forkpty = no; then
     542+    AC_MSG_ERROR(vimshell needs forkpty - sorry.)
     543+fi
     544+dnl ------------------------------------------------------------------
     545+
     546 dnl write output files
     547 AC_OUTPUT(auto/config.mk:config.mk.in)
     548 
     549diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/eval.c ./src/eval.c
     550--- ../vim72.orig/src/eval.c    2009-10-02 13:39:24.000000000 +0100
     551+++ ./src/eval.c        2009-10-02 13:39:57.000000000 +0100
     552@@ -11836,6 +11836,9 @@
     553 #if defined(UNIX) && defined(FEAT_X11)
     554        "X11",
     555 #endif
     556+#ifdef FEAT_VIMSHELL
     557+       "vimshell",
     558+#endif
     559        NULL
     560     };
     561 
     562diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_cmds.h ./src/ex_cmds.h
     563--- ../vim72.orig/src/ex_cmds.h 2009-10-02 13:39:25.000000000 +0100
     564+++ ./src/ex_cmds.h     2009-10-02 13:39:57.000000000 +0100
     565@@ -1007,6 +1007,10 @@
     566                        BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
     567 EX(CMD_view,           "view",         ex_edit,
     568                        BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
     569+#ifdef FEAT_VIMSHELL
     570+EX(CMD_vimshell,       "vimshell",     ex_vimshell,
     571+                       EXTRA|BANG|TRLBAR|CMDWIN),
     572+#endif
     573 EX(CMD_vimgrep,                "vimgrep",      ex_vimgrep,
     574                        RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
     575 EX(CMD_vimgrepadd,     "vimgrepadd",   ex_vimgrep,
     576diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ex_docmd.c ./src/ex_docmd.c
     577--- ../vim72.orig/src/ex_docmd.c        2009-10-02 13:39:25.000000000 +0100
     578+++ ./src/ex_docmd.c    2009-10-02 13:39:57.000000000 +0100
     579@@ -143,6 +143,7 @@
     580 static void    ex_quit __ARGS((exarg_T *eap));
     581 static void    ex_cquit __ARGS((exarg_T *eap));
     582 static void    ex_quit_all __ARGS((exarg_T *eap));
     583+static void    ex_vimshell __ARGS((exarg_T *eap));
     584 #ifdef FEAT_WINDOWS
     585 static void    ex_close __ARGS((exarg_T *eap));
     586 static void    ex_win_close __ARGS((int forceit, win_T *win, tabpage_T *tp));
     587@@ -11109,3 +11110,115 @@
     588     ml_clearmarked();     /* clear rest of the marks */
     589 }
     590 #endif
     591+
     592+#ifdef FEAT_VIMSHELL
     593+/*
     594+ * ":vimshell": creates an empty buffer in the current window and starts a
     595+ * VIM-Shell inside.
     596+ * ":vimshellac": same as "vimshell" but closes the window after the shell
     597+ * terminated (ac = "auto-close"). This is useful for redefinitions of 'Man'
     598+ * etc.
     599+ */
     600+    static void
     601+ex_vimshell(eap)
     602+    exarg_T    *eap;
     603+{
     604+    unsigned char *argv[50], argidx, *p;
     605+    unsigned char cmdline[500];
     606+    char cmdbuf[50];
     607+
     608+    if(curbuf->is_shell!=0)
     609+    {
     610+       emsg("VIMSHELL: current buffer is already a shell!");
     611+       return;
     612+    }
     613+
     614+    snprintf(cmdbuf, sizeof(cmdbuf), ":enew%s", eap->forceit==TRUE ? "!" : "");
     615+
     616+    /*
     617+     * Do a ":enew" command to get a new buffer in the current window.
     618+     * Also assures that we don't throw away any unsaved changes the user
     619+     * made to the previous buffer.
     620+     */
     621+    did_emsg=FALSE;
     622+    if(do_cmdline_cmd(cmdbuf)==FAIL || did_emsg==TRUE)
     623+    {
     624+       return;
     625+    }
     626+
     627+    /*
     628+     * Set buffer read only (the user can't write into it anyway, but just
     629+     * to make sure. We want to be able to close the buffer without any
     630+     * problems any time).
     631+     */
     632+    curbuf->b_p_ro=TRUE;
     633+
     634+    /*
     635+     * Parse command line arguments. If none given, default to '/bin/sh'
     636+     */
     637+    snprintf(cmdline, sizeof(cmdline), "%s", eap->arg);
     638+    p=cmdline;
     639+    argidx=0;
     640+    if(!strcmp(p, ""))
     641+    {
     642+       argv[0]="/bin/sh";
     643+    }
     644+    else
     645+    {
     646+       argv[argidx]=p;
     647+       do
     648+       {
     649+           if(*p==' ')
     650+           {
     651+               argidx++;
     652+               if(argidx+1 >= sizeof(argv)/sizeof(argv[0]))
     653+               {
     654+                   /*
     655+                    * Too many command line arguments, drop out
     656+                    */
     657+                   emsg("VIMSHELL: too many command line arguments");
     658+                   return;
     659+               }
     660+
     661+               /*
     662+                * Convert all ' ' to \0
     663+                */
     664+               for(;*p==' ';p++)
     665+                   *p=0;
     666+               if(*p!=0)
     667+               {
     668+                   argv[argidx]=p;
     669+               }
     670+           }
     671+       } while(*p++);
     672+    }
     673+    argv[++argidx]=NULL;
     674+
     675+    /*
     676+     * Convert the current buffer into a shell window.
     677+     */
     678+    curbuf->shell=(struct vim_shell_window *)vim_shell_new(W_WIDTH(curwin), curwin->w_height);
     679+    if(curbuf->shell==NULL)
     680+    {
     681+       EMSG2("VIMSHELL: error creating a new shell: %s", vim_shell_strerror());
     682+       return;
     683+    }
     684+    curbuf->is_shell=1;
     685+    curbuf->gtk_input_id=0;
     686+
     687+    /*
     688+     * start the shell
     689+     */
     690+    if(vim_shell_start(curbuf->shell, (char **)argv)<0)
     691+    {
     692+       EMSG2("VIMSHELL: error starting the shell: %s", vim_shell_strerror());
     693+
     694+       vim_shell_delete(curbuf);
     695+       return;
     696+    }
     697+
     698+    /*
     699+     * we're up and running.
     700+     */
     701+}
     702+#endif
     703diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/feature.h ./src/feature.h
     704--- ../vim72.orig/src/feature.h 2009-10-02 13:39:26.000000000 +0100
     705+++ ./src/feature.h     2009-10-02 13:39:57.000000000 +0100
     706@@ -1267,6 +1267,15 @@
     707 #endif
     708 
     709 /*
     710+ * The VIM-Shell. Only works on UNIX for now (more specifically,
     711+ * only Linux, *BSD and MacOS X, others not tested. Generally, if
     712+ * a system has a forkpty call, it should be working.)
     713+ */
     714+#if defined(FEAT_NORMAL) && (defined(UNIX) || defined(MACOS_X))
     715+#define FEAT_VIMSHELL
     716+#endif
     717+
     718+/*
     719  * +autochdir          'autochdir' option.
     720  */
     721 #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
     722diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/gui_gtk_x11.c ./src/gui_gtk_x11.c
     723--- ../vim72.orig/src/gui_gtk_x11.c     2009-10-02 13:39:25.000000000 +0100
     724+++ ./src/gui_gtk_x11.c 2009-10-02 13:39:57.000000000 +0100
     725@@ -6470,6 +6470,65 @@
     726 }
     727 #endif
     728 
     729+#ifdef FEAT_VIMSHELL
     730+/*
     731+ * VIM-Shell callback, called when a shell file descriptor has data
     732+ * available.
     733+ */
     734+    static void
     735+vimshell_request_cb(
     736+    gpointer   data,
     737+    gint       source_fd,
     738+    GdkInputCondition condition)
     739+{
     740+    buf_T *buf;
     741+    int did_redraw=0;
     742+
     743+    /*
     744+     * Search the right buffer.
     745+     */
     746+    for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
     747+    {
     748+       if(buf->is_shell!=0 && buf->shell && buf->shell->fd_master==source_fd)
     749+       {
     750+           int r;
     751+
     752+           r=vim_shell_do_read_lowlevel(buf);
     753+           if(r>did_redraw)
     754+               did_redraw=r;
     755+
     756+           if(r==1 && updating_screen==FALSE)
     757+               redraw_buf_later(buf, VALID);
     758+           else if(r==2)
     759+           {
     760+               /*
     761+                * Shell died, so remove the GTK-input
     762+                * VIMSHELL TODO: this should really be happening inside vim_shell_delete
     763+                */
     764+               gdk_input_remove(buf->gtk_input_id);
     765+               buf->gtk_input_id=0;
     766+               if(updating_screen==FALSE)
     767+                   redraw_buf_later(buf, CLEAR);
     768+           }
     769+       }
     770+    }
     771+
     772+    if(updating_screen==FALSE)
     773+    {
     774+       if(did_redraw==1)
     775+           update_screen(VALID);
     776+       else if(did_redraw==2)
     777+       {
     778+           update_screen(CLEAR);
     779+           out_flush();
     780+       }
     781+    }
     782+
     783+    if (gtk_main_level() > 0)
     784+       gtk_main_quit();
     785+}
     786+#endif
     787+
     788 /*
     789  * GUI input routine called by gui_wait_for_chars().  Waits for a character
     790  * from the keyboard.
     791@@ -6506,6 +6565,23 @@
     792     }
     793 #endif
     794 
     795+#ifdef FEAT_VIMSHELL
     796+    /*
     797+     * Go through all buffers, see if we have to add not yet added inputs
     798+     */
     799+    {
     800+       buf_T *buf;
     801+       for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
     802+       {
     803+           if(buf->is_shell!=0 && buf->shell && buf->gtk_input_id==0)
     804+           {
     805+               buf->gtk_input_id=gdk_input_add(buf->shell->fd_master,
     806+                       GDK_INPUT_READ, vimshell_request_cb, NULL);
     807+           }
     808+       }
     809+    }
     810+#endif
     811+
     812     timed_out = FALSE;
     813 
     814     /* this timeout makes sure that we will return if no characters arrived in
     815diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/main.c ./src/main.c
     816--- ../vim72.orig/src/main.c    2009-10-02 13:39:24.000000000 +0100
     817+++ ./src/main.c        2009-10-02 13:39:57.000000000 +0100
     818@@ -180,6 +180,10 @@
     819      */
     820     mch_early_init();
     821 
     822+#ifdef FEAT_VIMSHELL
     823+    vim_shell_init();
     824+#endif
     825+
     826     /* Many variables are in "params" so that we can pass them to invoked
     827      * functions without a lot of arguments.  "argc" and "argv" are also
     828      * copied, so that they can be changed. */
     829diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/move.c ./src/move.c
     830--- ../vim72.orig/src/move.c    2009-10-02 13:39:24.000000000 +0100
     831+++ ./src/move.c        2009-10-02 13:39:57.000000000 +0100
     832@@ -675,6 +675,14 @@
     833     void
     834 validate_cursor()
     835 {
     836+#ifdef FEAT_VIMSHELL
     837+    /*
     838+     * The vimshell repositions its artificial cursor in vim_shell_redraw. Don't do the
     839+     * checks below.
     840+     */
     841+    if(curwin->w_buffer && curwin->w_buffer->is_shell!=0)
     842+       return;
     843+#endif
     844     check_cursor_moved(curwin);
     845     if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
     846        curs_columns(TRUE);
     847diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/normal.c ./src/normal.c
     848--- ../vim72.orig/src/normal.c  2009-10-02 13:39:24.000000000 +0100
     849+++ ./src/normal.c      2009-10-02 13:41:52.000000000 +0100
     850@@ -646,11 +646,50 @@
     851     dont_scroll = FALSE;       /* allow scrolling here */
     852 #endif
     853 
     854+#ifdef FEAT_VIMSHELL
     855+    /*
     856+     * We reroute ALL characters to the shell, EXCEPT Ctrl_W, so all
     857+     * Window-Commands should still be working (not unimportant, think of
     858+     * leaving the window ...)
     859+     * VIMSHELL TODO: what about mouse commands, GUI commands, etc
     860+     */
     861+    if(curbuf->is_shell)
     862+    {
     863+      no_mapping++;
     864+      allow_keys++;
     865+      c = safe_vgetc();
     866+      no_mapping--;
     867+      allow_keys--;
     868+
     869+      if(curbuf->is_shell && c!=Ctrl_W)
     870+      {
     871+          if(vim_shell_write(curbuf->shell, c)<0)
     872+          {
     873+                  /*
     874+                   * The shell died, clean up
     875+                   */
     876+                  vim_shell_delete(curbuf);
     877+                  curbuf->is_shell=0;
     878+                  curbuf->b_p_ro=FALSE;
     879+
     880+                  redraw_later(CLEAR);
     881+                  update_screen(CLEAR);
     882+          }
     883+          return;
     884+      }
     885+    }
     886+    else
     887+    {
     888+      c = safe_vgetc();
     889+      LANGMAP_ADJUST(c, TRUE);
     890+    }
     891+#else
     892     /*
     893      * Get the command character from the user.
     894      */
     895     c = safe_vgetc();
     896     LANGMAP_ADJUST(c, TRUE);
     897+#endif
     898 
     899 #ifdef FEAT_VISUAL
     900     /*
     901diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/os_unix.c ./src/os_unix.c
     902--- ../vim72.orig/src/os_unix.c 2009-10-02 13:39:25.000000000 +0100
     903+++ ./src/os_unix.c     2009-10-02 13:39:57.000000000 +0100
     904@@ -4809,7 +4809,7 @@
     905 # endif
     906 #endif
     907 #ifndef HAVE_SELECT
     908-       struct pollfd   fds[5];
     909+       struct pollfd   fds[50];
     910        int             nfd;
     911 # ifdef FEAT_XCLIPBOARD
     912        int             xterm_idx = -1;
     913@@ -4820,6 +4820,15 @@
     914 # ifdef USE_XSMP
     915        int             xsmp_idx = -1;
     916 # endif
     917+# ifdef FEAT_VIMSHELL
     918+       struct
     919+       {
     920+           int idx;
     921+           struct vim_shell_window *shell;
     922+           buf_T *buffer;
     923+       }               vimshell_idxs[50];
     924+       int             vimshell_idx_cnt;
     925+# endif
     926        int             towait = (int)msec;
     927 
     928 # ifdef FEAT_MZSCHEME
     929@@ -4870,6 +4879,49 @@
     930            nfd++;
     931        }
     932 # endif
     933+# ifdef FEAT_VIMSHELL
     934+       {
     935+           /*
     936+            * Loop through all windows and see if they contain vimshells.
     937+            * If yes, add the master-fd to the list of polled fds.
     938+            */
     939+           memset(vimshell_idxs, 0, sizeof(vimshell_idxs));
     940+           vimshell_idx_cnt=0;
     941+           for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
     942+           {
     943+               buf_T *buf;
     944+               if(buf->is_shell!=0)
     945+               {
     946+                   vimshell_idxs[vimshell_idx_count].idx=nfd;
     947+                   vimshell_idxs[vimshell_idx_count].buffer=buf;
     948+                   vimshell_idxs[vimshell_idx_count].shell=buf->shell;
     949+
     950+                   /*
     951+                    * We will first run out of fds before we run out of
     952+                    * vimshell_idxs-slots, so no check here.
     953+                    */
     954+                   vimshell_idx_count++;
     955+
     956+                   if(buf->shell==NULL)
     957+                   {
     958+                       // VIMSHELL TODO: error message here
     959+                       continue;
     960+                   }
     961+                   fds[nfd].fd = buf->shell->fd_master;
     962+                   fds[nfd].events = POLLIN;
     963+                   nfd++;
     964+                   if(nfd>=sizeof(fds)/sizeof(fds[0]))
     965+                   {
     966+                       /*
     967+                        * no more fds-slots left! aieeee
     968+                        */
     969+                       // VIMSHELL TODO: issue a warning here or something
     970+                       break;
     971+                   }
     972+               }
     973+           }
     974+       }
     975+# endif
     976 
     977        ret = poll(fds, nfd, towait);
     978 # ifdef FEAT_MZSCHEME
     979@@ -4923,6 +4975,38 @@
     980                finished = FALSE;       /* Try again */
     981        }
     982 # endif
     983+# ifdef FEAT_VIMSHELL
     984+#error "VIMSHELL: probably doesn't work with poll(), never tested, sorry (use select)"
     985+       {
     986+           /*
     987+            * See if any of the shell's fds have a read request ready
     988+            * If yes, call the shell's read handler.
     989+            */
     990+           int i;
     991+           int did_redraw=0;
     992+           for(i=0;i<vimshell_idx_cnt;i++)
     993+           {
     994+               if(fds[vimshell_idxs[i].idx].revents & POLLIN)
     995+               {
     996+                   if(vim_shell_read(vimshell_idxs[i].shell)<0)
     997+                   {
     998+                       // VIMSHELL TODO: handle error here
     999+                       continue;
     1000+                   }
     1001+
     1002+                   redraw_buf_later(vimshell_idxs[i].buffer, NOT_VALID);
     1003+
     1004+                   did_redraw=1;
     1005+               }
     1006+               // VIMSHELL TODO: handle POLLHUP here too (shell terminated)
     1007+           }
     1008+           if(did_redraw==1)
     1009+           {
     1010+               update_screen(NOT_VALID);
     1011+               out_flush();
     1012+           }
     1013+       }
     1014+# endif
     1015 
     1016 
     1017 #else /* HAVE_SELECT */
     1018@@ -5004,6 +5088,25 @@
     1019                maxfd = xsmp_icefd;
     1020        }
     1021 # endif
     1022+# ifdef FEAT_VIMSHELL
     1023+       {
     1024+           /*
     1025+            * Loop through all windows and see if they contain vimshells.
     1026+            * If yes, add the master-fd to the list of fds
     1027+            */
     1028+           win_T *win;
     1029+           FOR_ALL_WINDOWS(win)
     1030+           {
     1031+               buf_T *buf=win->w_buffer;
     1032+               if(buf->is_shell!=0)
     1033+               {
     1034+                   FD_SET(buf->shell->fd_master, &rfds);
     1035+                   if (maxfd < buf->shell->fd_master)
     1036+                       maxfd = buf->shell->fd_master;
     1037+               }
     1038+           }
     1039+       }
     1040+# endif
     1041 
     1042 # ifdef OLD_VMS
     1043        /* Old VMS as v6.2 and older have broken select(). It waits more than
     1044@@ -5081,6 +5184,16 @@
     1045            }
     1046        }
     1047 # endif
     1048+# ifdef FEAT_VIMSHELL
     1049+       if((maxfd=vim_shell_do_read_select(rfds))!=0)
     1050+       {
     1051+           ret-=maxfd;
     1052+#  ifdef MAY_LOOP
     1053+           if (ret == 0)
     1054+               finished = FALSE;   /* keep going if event was only one */
     1055+#  endif
     1056+       }
     1057+# endif
     1058 
     1059 #endif /* HAVE_SELECT */
     1060 
     1061diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/screen.c ./src/screen.c
     1062--- ../vim72.orig/src/screen.c  2009-10-02 13:39:26.000000000 +0100
     1063+++ ./src/screen.c      2009-10-02 13:39:57.000000000 +0100
     1064@@ -91,13 +91,21 @@
     1065 /*
     1066  * The attributes that are actually active for writing to the screen.
     1067  */
     1068+#ifdef FEAT_VIMSHELL
     1069+int            screen_attr = 0;
     1070+#else
     1071 static int     screen_attr = 0;
     1072+#endif
     1073 
     1074 /*
     1075  * Positioning the cursor is reduced by remembering the last position.
     1076  * Mostly used by windgoto() and screen_char().
     1077  */
     1078+#ifdef FEAT_VIMSHELL
     1079+int            screen_cur_row, screen_cur_col; /* last known cursor position */
     1080+#else
     1081 static int     screen_cur_row, screen_cur_col; /* last known cursor position */
     1082+#endif
     1083 
     1084 #ifdef FEAT_SEARCH_EXTRA
     1085 static match_T search_hl;      /* used for 'hlsearch' highlight matching */
     1086@@ -141,7 +149,11 @@
     1087 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
     1088 static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
     1089 #endif
     1090+#ifdef FEAT_VIMSHELL
     1091+void screen_start_highlight __ARGS((int attr));
     1092+#else
     1093 static void screen_start_highlight __ARGS((int attr));
     1094+#endif
     1095 static void screen_char __ARGS((unsigned off, int row, int col));
     1096 #ifdef FEAT_MBYTE
     1097 static void screen_char_2 __ARGS((unsigned off, int row, int col));
     1098@@ -833,6 +845,7 @@
     1099     }
     1100 #endif
     1101 
     1102+
     1103 #ifdef FEAT_SEARCH_EXTRA
     1104     /* Setup for match and 'hlsearch' highlighting.  Disable any previous
     1105      * match */
     1106@@ -1477,6 +1490,7 @@
     1107     win_foldinfo.fi_level = 0;
     1108 #endif
     1109 
     1110+
     1111     /*
     1112      * Update all the window rows.
     1113      */
     1114@@ -1903,9 +1917,19 @@
     1115        else if (dollar_vcol == 0)
     1116            wp->w_botline = lnum;
     1117 
     1118+#ifdef FEAT_VIMSHELL
     1119+       /*
     1120+        * We don't want '~' to appear right in the middle of our shells ...
     1121+        */
     1122+       if(wp->w_buffer->is_shell==0)
     1123+       {
     1124+#endif
     1125        /* make sure the rest of the screen is blank */
     1126        /* put '~'s on rows that aren't part of the file. */
     1127        win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_AT);
     1128+#ifdef FEAT_VIMSHELL
     1129+       }
     1130+#endif
     1131     }
     1132 
     1133     /* Reset the type of redrawing required, the window has been updated. */
     1134@@ -1953,6 +1977,18 @@
     1135     if (!got_int)
     1136        got_int = save_got_int;
     1137 #endif
     1138+
     1139+#ifdef FEAT_VIMSHELL
     1140+    /*
     1141+     * If this window contains a shell, redraw the shell.
     1142+     */
     1143+    if(wp->w_buffer->is_shell != 0)
     1144+    {
     1145+       wp->w_buffer->shell->force_redraw=(type>=NOT_VALID ? 1 : 0);
     1146+       vim_shell_redraw(wp->w_buffer->shell, wp);
     1147+       return;
     1148+    }
     1149+#endif
     1150 }
     1151 
     1152 #ifdef FEAT_SIGNS
     1153@@ -6756,7 +6792,11 @@
     1154 }
     1155 #endif
     1156 
     1157+#ifdef FEAT_VIMSHELL
     1158+      void
     1159+#else
     1160       static void
     1161+#endif
     1162 screen_start_highlight(attr)
     1163       int      attr;
     1164 {
     1165@@ -6956,7 +6996,11 @@
     1166  * Put character ScreenLines["off"] on the screen at position "row" and "col",
     1167  * using the attributes from ScreenAttrs["off"].
     1168  */
     1169+#ifdef FEAT_VIMSHELL
     1170+    void
     1171+#else
     1172     static void
     1173+#endif
     1174 screen_char(off, row, col)
     1175     unsigned   off;
     1176     int                row;
     1177diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/structs.h ./src/structs.h
     1178--- ../vim72.orig/src/structs.h 2009-10-02 13:39:26.000000000 +0100
     1179+++ ./src/structs.h     2009-10-02 13:39:57.000000000 +0100
     1180@@ -1145,6 +1145,10 @@
     1181 
     1182 typedef struct file_buffer buf_T;
     1183 
     1184+#ifdef FEAT_VIMSHELL
     1185+struct vim_shell_window;
     1186+#endif
     1187+
     1188 struct file_buffer
     1189 {
     1190     memline_T  b_ml;           /* associated memline (also contains line
     1191@@ -1591,6 +1595,11 @@
     1192     int                b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */
     1193 #endif
     1194 
     1195+#ifdef FEAT_VIMSHELL
     1196+    char       is_shell;                /* (flag) Is this buffer a shell? (0 = false) */
     1197+    struct     vim_shell_window *shell; /* Pointer to the shell struct, or NULL */
     1198+    int                gtk_input_id;            /* GTK-input id returned by gdk_input_add, only for GUI */
     1199+#endif
     1200 };
     1201 
     1202 
     1203diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/syntax.c ./src/syntax.c
     1204--- ../vim72.orig/src/syntax.c  2009-10-02 13:39:24.000000000 +0100
     1205+++ ./src/syntax.c      2009-10-02 13:39:57.000000000 +0100
     1206@@ -6005,6 +6005,10 @@
     1207 syntax_present(buf)
     1208     buf_T      *buf;
     1209 {
     1210+#ifdef FEAT_VIMSHELL
     1211+    if(buf->is_shell!=0)
     1212+       return 0;
     1213+#endif
     1214     return (buf->b_syn_patterns.ga_len != 0
     1215            || buf->b_syn_clusters.ga_len != 0
     1216            || buf->b_keywtab.ht_used > 0
     1217diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/terminal.c ./src/terminal.c
     1218--- ../vim72.orig/src/terminal.c        1970-01-01 01:00:00.000000000 +0100
     1219+++ ./src/terminal.c    2009-10-02 13:39:57.000000000 +0100
     1220@@ -0,0 +1,1933 @@
     1221+/*
     1222+ * terminal.c
     1223+ *
     1224+ * This is the screen-like terminal emulator; it is a better vt100 and supports the
     1225+ * same commands that screen does (including color etc).
     1226+ *
     1227+ * The interface is vim_shell_terminal_input and vim_shell_terminal_output. These
     1228+ * functions get characters from the shell (or from the user) and process them
     1229+ * accordingly to the terminal rules (ESC sequences etc). They then work directly
     1230+ * on the vim_shell-window-buffer, updating its contents.
     1231+ *
     1232+ * VIMSHELL TODO: *) don't scroll scroll region if cursor is outside
     1233+ *                *) change the buffer name according to the window title
     1234+ *                *) CSI (0x9B)
     1235+ *                *) Get the ESC codes for switching charsets from terminfo/termcap
     1236+ *                *) Origin mode
     1237+ *                *) "erase with background color"
     1238+ *
     1239+ * This file is part of the VIM-Shell project. http://vimshell.wana.at
     1240+ *
     1241+ * Author: Thomas Wana <thomas@wana.at>
     1242+ *
     1243+ */
     1244+
     1245+static char *RCSID="$Id$";
     1246+
     1247+#include <string.h>
     1248+#include <stdlib.h>
     1249+#include <unistd.h>
     1250+#include <ctype.h>
     1251+#include <errno.h>
     1252+
     1253+#include "vim.h"
     1254+
     1255+#ifdef FEAT_VIMSHELL
     1256+#ifdef VIMSHELL_DEBUG
     1257+#  define ESCDEBUG
     1258+/*
     1259+ * Really extreme logging
     1260+ * Log *every* character we write to the shell
     1261+ */
     1262+//#  define VERBOSE
     1263+#endif
     1264+
     1265+#ifdef ESCDEBUG
     1266+#  define ESCDEBUGPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
     1267+#else
     1268+#  define ESCDEBUGPRINTF(a...)
     1269+#endif
     1270+
     1271+#ifdef VERBOSE
     1272+#  define VERBOSEPRINTF(a...) if(vimshell_debug_fp) { fprintf(vimshell_debug_fp, a); fflush(vimshell_debug_fp); }
     1273+#else
     1274+#  define VERBOSEPRINTF(a...)
     1275+#endif
     1276+
     1277+/*
     1278+ * These are the VIM keynames.
     1279+ */
     1280+#define VIMSHELL_KEY_DOWN      K_DOWN
     1281+#define VIMSHELL_KEY_UP                K_UP
     1282+#define VIMSHELL_KEY_LEFT      K_LEFT
     1283+#define VIMSHELL_KEY_RIGHT     K_RIGHT
     1284+#define VIMSHELL_KEY_HOME      K_HOME
     1285+#define VIMSHELL_KEY_BACKSPACE K_BS
     1286+#define VIMSHELL_KEY_F1                K_F1
     1287+#define VIMSHELL_KEY_F2                K_F2
     1288+#define VIMSHELL_KEY_F3                K_F3
     1289+#define VIMSHELL_KEY_F4                K_F4
     1290+#define VIMSHELL_KEY_F5                K_F5
     1291+#define VIMSHELL_KEY_F6                K_F6
     1292+#define VIMSHELL_KEY_F7                K_F7
     1293+#define VIMSHELL_KEY_F8                K_F8
     1294+#define VIMSHELL_KEY_F9                K_F9
     1295+#define VIMSHELL_KEY_F10       K_F10
     1296+#define VIMSHELL_KEY_F11       K_F11
     1297+#define VIMSHELL_KEY_F12       K_F12
     1298+#define VIMSHELL_KEY_DC                K_DEL
     1299+#define VIMSHELL_KEY_END       K_END
     1300+#define VIMSHELL_KEY_IC                K_INS
     1301+#define VIMSHELL_KEY_NPAGE     K_PAGEDOWN
     1302+#define VIMSHELL_KEY_PPAGE     K_PAGEUP
     1303+#define VIMSHELL_KEY_K0                K_K0
     1304+#define VIMSHELL_KEY_K1                K_K1
     1305+#define VIMSHELL_KEY_K2                K_K2
     1306+#define VIMSHELL_KEY_K3                K_K3
     1307+#define VIMSHELL_KEY_K4                K_K4
     1308+#define VIMSHELL_KEY_K5                K_K5
     1309+#define VIMSHELL_KEY_K6                K_K6
     1310+#define VIMSHELL_KEY_K7                K_K7
     1311+#define VIMSHELL_KEY_K8                K_K8
     1312+#define VIMSHELL_KEY_K9                K_K9
     1313+#define VIMSHELL_KEY_KPLUS     K_KPLUS
     1314+#define VIMSHELL_KEY_KMINUS    K_KMINUS
     1315+#define VIMSHELL_KEY_KDIVIDE   K_KDIVIDE
     1316+#define VIMSHELL_KEY_KMULTIPLY K_KMULTIPLY
     1317+#define VIMSHELL_KEY_KENTER    K_KENTER
     1318+#define VIMSHELL_KEY_KPOINT    K_KPOINT
     1319+
     1320+static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20]);
     1321+static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20]);
     1322+static int terminal_flush_output(struct vim_shell_window *shell);
     1323+
     1324+/*
     1325+ * A routine that prints a buffer in 'hexdump -C'-style via printf
     1326+ */
     1327+static void hexdump(FILE *fp, unsigned char *buffer, long len)
     1328+{
     1329+       unsigned long pos=0;
     1330+
     1331+       while(len>0)
     1332+       {
     1333+               int i;
     1334+               fprintf(fp,"%08x  ",(unsigned int)pos);
     1335+               for(i=0;i<16 && i<len;i++)
     1336+               {
     1337+                       fprintf(fp,"%02x ",buffer[pos+i]);
     1338+                       if(i==7 || i==15)
     1339+                               fprintf(fp," ");
     1340+               }
     1341+               fprintf(fp,"|");
     1342+               for(i=0;i<16 && i<len;i++)
     1343+               {
     1344+                       unsigned char c=buffer[pos+i];
     1345+                       if(isprint(c))
     1346+                       {
     1347+                               fprintf(fp,"%c",c);
     1348+                       }
     1349+                       else
     1350+                       {
     1351+                               fprintf(fp,".");
     1352+                       }
     1353+               }
     1354+               fprintf(fp,"|\n");
     1355+               len-=16;
     1356+               pos+=16;
     1357+       }
     1358+}
     1359+
     1360+/*
     1361+ * Tabulation Clear (TBC)
     1362+ *
     1363+ * 9/11 6/7
     1364+ * CSI   g
     1365+ *
     1366+ *     Clears a horizontal tab stop at cursor position.
     1367+ *
     1368+ *     9/11 3/0 6/7
     1369+ *     CSI   0   g
     1370+ *
     1371+ *             Clears a horizontal tab stop at cursor position.
     1372+ *
     1373+ *             9/11 3/3 6/7
     1374+ *             CSI   3   g
     1375+ *
     1376+ *                     Clears all horizontal tab stops.
     1377+ */
     1378+static void terminal_TBC(struct vim_shell_window *shell, int argc, char argv[20][20])
     1379+{
     1380+       int param;
     1381+
     1382+       if(argc==0)
     1383+       {
     1384+               param=0;
     1385+       }
     1386+       else if(argc>1)
     1387+       {
     1388+               ESCDEBUGPRINTF("%s: sequence error\n", __FUNCTION__);
     1389+               return;
     1390+       }
     1391+
     1392+       // VIMSHELL TODO: DRINGEND! wenn argc==0 dann ist argv[0] NULL und wir crashen
     1393+       // hier ... passiert in einigen Funktionen, dank copy+paste! Super gmocht Tom!
     1394+       param=strtol(argv[0], NULL, 10);
     1395+       switch(param)
     1396+       {
     1397+               case 0:
     1398+                       shell->tabline[shell->cursor_x]=0;
     1399+                       break;
     1400+               case 3:
     1401+                       memset(shell->tabline, 0, shell->size_x);
     1402+                       break;
     1403+               default:
     1404+                       ESCDEBUGPRINTF( "%s: sequence error (2)\n", __FUNCTION__);
     1405+       }
     1406+}
     1407+
     1408+/*
     1409+ * CUB . Cursor Backward . Host to VT100 and VT100 to Host
     1410+ * ESC [ Pn D  default value: 1
     1411+ *
     1412+ * The CUB sequence moves the active position to the left. The distance moved is
     1413+ * determined by the parameter. If the parameter value is zero or one, the active
     1414+ * position is moved one position to the left. If the parameter value is n, the active
     1415+ * position is moved n positions to the left. If an attempt is made to move the cursor
     1416+ * to the left of the left margin, the cursor stops at the left margin. Editor Function
     1417+ */
     1418+static void terminal_CUB(struct vim_shell_window *shell, int argc, char argv[20][20])
     1419+{
     1420+       int distance;
     1421+
     1422+       if(argc==0)
     1423+       {
     1424+               distance=1;
     1425+       }
     1426+       else if(argc>1)
     1427+       {
     1428+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     1429+               return;
     1430+       }
     1431+
     1432+       distance=strtol(argv[0], NULL, 10);
     1433+       if(distance==0)
     1434+               distance=1;
     1435+
     1436+       if(shell->cursor_x<distance)
     1437+               shell->cursor_x=0;
     1438+       else
     1439+               shell->cursor_x-=distance;
     1440+}
     1441+
     1442+/*
     1443+ * CUU . Cursor Up . Host to VT100 and VT100 to Host
     1444+ * ESC [ Pn A  default value: 1
     1445+ *
     1446+ * Moves the active position upward without altering the column position. The
     1447+ * number of lines moved is determined by the parameter. A parameter value of zero
     1448+ * or one moves the active position one line upward. A parameter value of n moves the
     1449+ * active position n lines upward. If an attempt is made to move the cursor above the
     1450+ * top margin, the cursor stops at the top margin. Editor Function
     1451+ */
     1452+static void terminal_CUU(struct vim_shell_window *shell, int argc, char argv[20][20])
     1453+{
     1454+       int distance;
     1455+
     1456+       if(argc==0)
     1457+       {
     1458+               distance=1;
     1459+       }
     1460+       else if(argc>1)
     1461+       {
     1462+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     1463+               return;
     1464+       }
     1465+
     1466+       distance=strtol(argv[0], NULL, 10);
     1467+       if(distance==0)
     1468+               distance=1;
     1469+
     1470+       if((int)shell->cursor_y-distance<shell->scroll_top_margin)
     1471+               shell->cursor_y=shell->scroll_top_margin;
     1472+       else
     1473+               shell->cursor_y-=distance;
     1474+}
     1475+
     1476+
     1477+/*
     1478+ * CUD . Cursor Down . Host to VT100 and VT100 to Host
     1479+ * ESC [ Pn B  default value: 1
     1480+ *
     1481+ * The CUD sequence moves the active position downward without altering the column
     1482+ * position. The number of lines moved is determined by the parameter. If the parameter
     1483+ * value is zero or one, the active position is moved one line downward. If the parameter
     1484+ * value is n, the active position is moved n lines downward. In an attempt is made to
     1485+ * move the cursor below the bottom margin, the cursor stops at the bottom margin. Editor Function
     1486+ */
     1487+static void terminal_CUD(struct vim_shell_window *shell, int argc, char argv[20][20])
     1488+{
     1489+       int distance;
     1490+
     1491+       if(argc==0)
     1492+       {
     1493+               distance=1;
     1494+       }
     1495+       else if(argc>1)
     1496+       {
     1497+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     1498+               return;
     1499+       }
     1500+
     1501+       distance=strtol(argv[0], NULL, 10);
     1502+       if(distance==0)
     1503+               distance=1;
     1504+
     1505+       shell->cursor_y+=distance;
     1506+       if(shell->cursor_y+1>=shell->scroll_bottom_margin)
     1507+               shell->cursor_y=shell->scroll_bottom_margin;
     1508+}
     1509+
     1510+/*
     1511+ * CUF . Cursor Forward . Host to VT100 and VT100 to Host
     1512+ * ESC [ Pn C  default value: 1
     1513+ *
     1514+ * The CUF sequence moves the active position to the right. The distance moved is
     1515+ * determined by the parameter. A parameter value of zero or one moves the active
     1516+ * position one position to the right. A parameter value of n moves the active position n
     1517+ * positions to the right. If an attempt is made to move the cursor to the right
     1518+ * of the right margin, the cursor stops at the right margin. Editor Function
     1519+ */
     1520+static void terminal_CUF(struct vim_shell_window *shell, int argc, char argv[20][20])
     1521+{
     1522+       int distance;
     1523+
     1524+       if(argc==0)
     1525+       {
     1526+               distance=1;
     1527+       }
     1528+       else if(argc>1)
     1529+       {
     1530+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     1531+               return;
     1532+       }
     1533+
     1534+       distance=strtol(argv[0], NULL, 10);
     1535+       if(distance==0)
     1536+               distance=1;
     1537+
     1538+       shell->cursor_x+=distance;
     1539+       if(shell->cursor_x+1>=shell->size_x)
     1540+               shell->cursor_x=shell->size_x+1;
     1541+}
     1542+
     1543+/*
     1544+ * SGR . Select Graphic Rendition
     1545+ * ESC [ Ps ; . . . ; Ps m     default value: 0
     1546+ *
     1547+ * Invoke the graphic rendition specified by the parameter(s). All following characters
     1548+ * transmitted to the VT100 are rendered according to the parameter(s) until the next
     1549+ * occurrence of SGR. Format Effector
     1550+ *
     1551+ * Parameter   Parameter Meaning
     1552+ * 0   Attributes off
     1553+ * 1   Bold or increased intensity
     1554+ * 4   Underscore
     1555+ * 5   Blink
     1556+ * 7   Negative (reverse) image
     1557+ *
     1558+ * All other parameter values are ignored.
     1559+ *
     1560+ * With the Advanced Video Option, only one type of character attribute is possible as
     1561+ * determined by the cursor selection; in that case specifying either the underscore or
     1562+ * the reverse attribute will activate the currently selected attribute. (See cursor
     1563+ * selection in Chapter 1).
     1564+ */
     1565+static void terminal_SGR(struct vim_shell_window *shell, int argc, char argv[20][20])
     1566+{
     1567+       if(argc==0)
     1568+       {
     1569+               shell->rendition=0;
     1570+               shell->fgcolor=VIMSHELL_COLOR_DEFAULT;  // default fgcolor
     1571+               shell->bgcolor=VIMSHELL_COLOR_DEFAULT;  // default bgcolor
     1572+       }
     1573+       else
     1574+       {
     1575+               int i;
     1576+               for(i=0;i<argc;i++)
     1577+               {
     1578+                       int val;
     1579+                       switch((val=strtol(argv[i], NULL, 10)))
     1580+                       {
     1581+                               case 0:
     1582+                                       shell->rendition=0;
     1583+                                       shell->fgcolor=VIMSHELL_COLOR_DEFAULT;
     1584+                                       shell->bgcolor=VIMSHELL_COLOR_DEFAULT;
     1585+                                       break;
     1586+                               case 1:
     1587+                                       shell->rendition|=RENDITION_BOLD;
     1588+                                       break;
     1589+                               case 2:
     1590+                                       shell->rendition|=RENDITION_DIM;
     1591+                                       break;
     1592+                               case 4:
     1593+                                       shell->rendition|=RENDITION_UNDERSCORE;
     1594+                                       break;
     1595+                               case 5:
     1596+                                       shell->rendition|=RENDITION_BLINK;
     1597+                                       break;
     1598+                               case 7:
     1599+                                       shell->rendition|=RENDITION_NEGATIVE;
     1600+                                       break;
     1601+                               case 8:
     1602+                                       shell->rendition|=RENDITION_HIDDEN;
     1603+                                       break;
     1604+                               case 22:
     1605+                                       shell->rendition&=~RENDITION_BOLD;
     1606+                                       break;
     1607+                               case 24:
     1608+                                       shell->rendition&=~RENDITION_UNDERSCORE;
     1609+                                       break;
     1610+                               case 25:
     1611+                                       shell->rendition&=~RENDITION_BLINK;
     1612+                                       break;
     1613+                               case 27:
     1614+                                       shell->rendition&=~RENDITION_NEGATIVE;
     1615+                                       break;
     1616+                               default:
     1617+                                       if(val>=30 && val<=37)
     1618+                                               shell->fgcolor=val-30;
     1619+                                       else if(val>=40 && val<=47)
     1620+                                               shell->bgcolor=val-40;
     1621+                                       else if(val==39)
     1622+                                               shell->fgcolor=VIMSHELL_COLOR_DEFAULT; // default fgcolor
     1623+                                       else if(val==49)
     1624+                                               shell->bgcolor=VIMSHELL_COLOR_DEFAULT; // default bgcolor
     1625+                                       else
     1626+                                               ESCDEBUGPRINTF( "%s: unknown rendition %s\n",
     1627+                                                               __FUNCTION__, argv[i]);
     1628+                       }
     1629+               }
     1630+       }
     1631+       ESCDEBUGPRINTF("%s: rendition is now: %04x\n", __FUNCTION__, shell->rendition);
     1632+       ESCDEBUGPRINTF("%s: foreground color: %d, background color: %d\n", __FUNCTION__,
     1633+                       shell->fgcolor, shell->bgcolor);
     1634+}
     1635+
     1636+/*
     1637+ * Copy the screen contents to the alternate screen.
     1638+ */
     1639+static void terminal_backup_screen(struct vim_shell_window *shell)
     1640+{
     1641+       size_t len;
     1642+       if(shell->alt!=NULL)
     1643+       {
     1644+               ESCDEBUGPRINTF( "%s: WARNING: alternate screen taken\n", __FUNCTION__);
     1645+               vim_shell_free(shell->alt->winbuf);
     1646+               vim_shell_free(shell->alt->bgbuf);
     1647+               vim_shell_free(shell->alt->fgbuf);
     1648+               vim_shell_free(shell->alt->rendbuf);
     1649+               vim_shell_free(shell->alt->tabline);
     1650+               vim_shell_free(shell->alt->charset);
     1651+               vim_shell_free(shell->alt);
     1652+               shell->alt=NULL;
     1653+       }
     1654+
     1655+       shell->alt=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
     1656+       if(shell->alt==NULL)
     1657+       {
     1658+               ESCDEBUGPRINTF( "%s: ERROR: unable to allocate a new screen\n", __FUNCTION__);
     1659+               return;
     1660+       }
     1661+
     1662+       *(shell->alt)=*shell;
     1663+
     1664+       len=shell->size_x*shell->size_y;
     1665+       shell->alt->winbuf=(uint8_t *)vim_shell_malloc(len);
     1666+       shell->alt->fgbuf=(uint8_t *)vim_shell_malloc(len);
     1667+       shell->alt->bgbuf=(uint8_t *)vim_shell_malloc(len);
     1668+       shell->alt->rendbuf=(uint8_t *)vim_shell_malloc(len);
     1669+       shell->alt->tabline=(uint8_t *)vim_shell_malloc(shell->size_x);
     1670+       shell->alt->charset=(uint8_t *)vim_shell_malloc(len);
     1671+       if(shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL || shell->alt->winbuf==NULL ||
     1672+                       shell->alt->charset==NULL || shell->alt->tabline==NULL)
     1673+       {
     1674+               ESCDEBUGPRINTF( "%s: ERROR: unable to allocate buffers\n", __FUNCTION__);
     1675+               if(shell->alt->winbuf) vim_shell_free(shell->alt->winbuf);
     1676+               if(shell->alt->fgbuf) vim_shell_free(shell->alt->fgbuf);
     1677+               if(shell->alt->bgbuf) vim_shell_free(shell->alt->bgbuf);
     1678+               if(shell->alt->rendbuf) vim_shell_free(shell->alt->rendbuf);
     1679+               if(shell->alt->tabline) vim_shell_free(shell->alt->tabline);
     1680+               if(shell->alt->charset) vim_shell_free(shell->alt->charset);
     1681+               vim_shell_free(shell->alt);
     1682+               shell->alt=NULL;
     1683+               return;
     1684+       }
     1685+
     1686+       memcpy(shell->alt->winbuf, shell->winbuf, len);
     1687+       memcpy(shell->alt->fgbuf, shell->fgbuf, len);
     1688+       memcpy(shell->alt->bgbuf, shell->bgbuf, len);
     1689+       memcpy(shell->alt->rendbuf, shell->rendbuf, len);
     1690+       memcpy(shell->alt->charset, shell->charset, len);
     1691+       memcpy(shell->alt->tabline, shell->tabline, shell->size_x);
     1692+}
     1693+
     1694+/*
     1695+ * Restore the alternate screen
     1696+ */
     1697+static void terminal_restore_screen(struct vim_shell_window *shell)
     1698+{
     1699+       struct vim_shell_window *alt;
     1700+       if(shell->alt==NULL)
     1701+       {
     1702+               ESCDEBUGPRINTF( "%s: WARNING: nothing to restore\n", __FUNCTION__);
     1703+               return;
     1704+       }
     1705+
     1706+       vim_shell_free(shell->winbuf);
     1707+       vim_shell_free(shell->rendbuf);
     1708+       vim_shell_free(shell->tabline);
     1709+       vim_shell_free(shell->fgbuf);
     1710+       vim_shell_free(shell->bgbuf);
     1711+       vim_shell_free(shell->charset);
     1712+
     1713+       alt=shell->alt;
     1714+       *shell=*(shell->alt);
     1715+       shell->alt=NULL;
     1716+
     1717+       vim_shell_free(alt);
     1718+
     1719+       /*
     1720+        * Invalidate the shell so it will be fully redrawn
     1721+        */
     1722+       shell->force_redraw=1;
     1723+}
     1724+
     1725+/*
     1726+ * Erases the whole screen and homes the cursor.
     1727+ */
     1728+static void terminal_init_screen(struct vim_shell_window *shell)
     1729+{
     1730+       char ed_argv[20][20];
     1731+
     1732+       strcpy(ed_argv[0], "2");
     1733+
     1734+       /*
     1735+        * Erase all of the display.
     1736+        */
     1737+       terminal_ED(shell, 1, ed_argv);
     1738+
     1739+       /*
     1740+        * Cursor to HOME position.
     1741+        */
     1742+       terminal_CUP(shell, 0, NULL);
     1743+}
     1744+
     1745+static void terminal_mode(struct vim_shell_window *shell, int set, int argc, char argv[20][20])
     1746+{
     1747+       int i;
     1748+
     1749+       for(i=0;i<argc;i++)
     1750+       {
     1751+               if(!strcmp(argv[i], "4"))
     1752+               {
     1753+                       shell->insert_mode=set;
     1754+                       ESCDEBUGPRINTF( "%s: insert mode: %d\n", __FUNCTION__, set);
     1755+               }
     1756+               else if(!strcmp(argv[i], "?1"))
     1757+               {
     1758+                       shell->application_cursor_mode=set;
     1759+                       ESCDEBUGPRINTF( "%s: application cursor mode: %d\n", __FUNCTION__, set);
     1760+               }
     1761+               else if(!strcmp(argv[i], "?5"))
     1762+               {
     1763+                       ESCDEBUGPRINTF("%s: background dark/light mode ignored\n", __FUNCTION__);
     1764+               }
     1765+               else if(!strcmp(argv[i], "?6"))
     1766+               {
     1767+                       ESCDEBUGPRINTF("%s: set terminal width ignored\n", __FUNCTION__);
     1768+               }
     1769+               else if(!strcmp(argv[i], "?7"))
     1770+               {
     1771+                       shell->wraparound=set;
     1772+                       ESCDEBUGPRINTF( "%s: wraparound: %d\n", __FUNCTION__, set);
     1773+               }
     1774+               else if(!strcmp(argv[i], "34") || !strcmp(argv[i], "?25"))
     1775+               {
     1776+                       shell->cursor_visible=set;
     1777+                       ESCDEBUGPRINTF( "%s: cursor visible: %d\n", __FUNCTION__, set);
     1778+               }
     1779+               else if(!strcmp(argv[i], "?4"))
     1780+               {
     1781+                       ESCDEBUGPRINTF("%s: selection between smooth and jump scrolling ignored\n",__FUNCTION__);
     1782+               }
     1783+               else if(!strcmp(argv[i], "?1049") || !strcmp(argv[i], "?1047"))
     1784+               {
     1785+                       if(set==1)
     1786+                       {
     1787+                               terminal_backup_screen(shell);
     1788+                               terminal_init_screen(shell);
     1789+                               ESCDEBUGPRINTF( "%s: terminal screen backed up.\n", __FUNCTION__);
     1790+                       }
     1791+                       else
     1792+                       {
     1793+                               terminal_restore_screen(shell);
     1794+                               ESCDEBUGPRINTF( "%s: terminal screen restored from backup.\n", __FUNCTION__);
     1795+                       }
     1796+               }
     1797+               else
     1798+               {
     1799+                       ESCDEBUGPRINTF( "%s: unimplemented terminal mode: %s\n", __FUNCTION__, argv[i]);
     1800+               }
     1801+       }
     1802+}
     1803+
     1804+/*
     1805+ * EL . Erase In Line
     1806+ * ESC [ Ps K  default value: 0
     1807+ *
     1808+ * Erases some or all characters in the active line according to the parameter. Editor Function
     1809+ *
     1810+ * Parameter   Parameter Meaning
     1811+ * 0   Erase from the active position to the end of the line, inclusive (default)
     1812+ * 1   Erase from the start of the line to the active position, inclusive
     1813+ * 2   Erase all of the line, inclusive
     1814+ */
     1815+static void terminal_EL(struct vim_shell_window *shell, int argc, char argv[20][20])
     1816+{
     1817+       int i, size, pos;
     1818+
     1819+       if(argc==0)
     1820+               i=0;
     1821+       else if(argc==1)
     1822+               i=strtol(argv[0], NULL, 10);
     1823+       else
     1824+       {
     1825+               /*
     1826+                * Error in sequence
     1827+                */
     1828+               ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
     1829+               return;
     1830+       }
     1831+
     1832+       size=shell->size_x*shell->size_y;
     1833+       pos=shell->cursor_y*shell->size_x+shell->cursor_x;
     1834+       if(i==0)
     1835+       {
     1836+               /*
     1837+                * erase from the active position to the end of line
     1838+                */
     1839+
     1840+               memset(shell->winbuf+pos, ' ', shell->size_x-shell->cursor_x);
     1841+               memset(shell->fgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
     1842+               memset(shell->bgbuf+pos,  VIMSHELL_COLOR_DEFAULT, shell->size_x-shell->cursor_x);
     1843+               memset(shell->rendbuf+pos, 0, shell->size_x-shell->cursor_x);
     1844+               memset(shell->charset+pos, 0, shell->size_x-shell->cursor_x);
     1845+               ESCDEBUGPRINTF( "%s: erase from active position to end of line\n", __FUNCTION__);
     1846+
     1847+       }
     1848+       else if(i==1)
     1849+       {
     1850+               /*
     1851+                * erase from start of the line to the active position, inclusive
     1852+                */
     1853+
     1854+               memset(shell->winbuf+shell->cursor_y*shell->size_x, ' ', shell->cursor_x);
     1855+               memset(shell->fgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
     1856+               memset(shell->bgbuf+ shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->cursor_x);
     1857+               memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
     1858+               memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->cursor_x);
     1859+               ESCDEBUGPRINTF( "%s: erase from start of line to active position\n", __FUNCTION__);
     1860+       }
     1861+       else if(i==2)
     1862+       {
     1863+               /*
     1864+                * Erase all of the line
     1865+                */
     1866+
     1867+               memset(shell->winbuf +shell->cursor_y*shell->size_x, ' ', shell->size_x);
     1868+               memset(shell->fgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     1869+               memset(shell->bgbuf  +shell->cursor_y*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     1870+               memset(shell->rendbuf+shell->cursor_y*shell->size_x, 0, shell->size_x);
     1871+               memset(shell->charset+shell->cursor_y*shell->size_x, 0, shell->size_x);
     1872+               ESCDEBUGPRINTF( "%s: erase all of the line\n", __FUNCTION__);
     1873+       }
     1874+       else
     1875+       {
     1876+               ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
     1877+               return;
     1878+       }
     1879+}
     1880+
     1881+/*
     1882+ * ED . Erase In Display
     1883+ * ESC [ Ps J  default value: 0
     1884+ *
     1885+ * This sequence erases some or all of the characters in the display according
     1886+ * to the parameter. Any complete line erased by this sequence will return that
     1887+ * line to single width mode. Editor Function
     1888+ *
     1889+ * Parameter   Parameter Meaning
     1890+ * 0   Erase from the active position to the end of the screen, inclusive (default)
     1891+ * 1   Erase from start of the screen to the active position, inclusive
     1892+ * 2   Erase all of the display . all lines are erased, changed to single-width, and the cursor does not move.
     1893+ */
     1894+static void terminal_ED(struct vim_shell_window *shell, int argc, char argv[20][20])
     1895+{
     1896+       int i, size, pos;
     1897+
     1898+       if(argc==0)
     1899+               i=0;
     1900+       else if(argc==1)
     1901+               i=strtol(argv[0], NULL, 10);
     1902+       else
     1903+       {
     1904+               /*
     1905+                * Error in sequence
     1906+                */
     1907+               ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
     1908+               return;
     1909+       }
     1910+
     1911+       size=shell->size_x*shell->size_y;
     1912+       pos=shell->cursor_y*shell->size_x+shell->cursor_x;
     1913+       if(i==0)
     1914+       {
     1915+               /*
     1916+                * erase from the active position to the end of screen
     1917+                */
     1918+
     1919+               memset(shell->winbuf+pos, ' ', size-pos);
     1920+               memset(shell->fgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
     1921+               memset(shell->bgbuf+pos, VIMSHELL_COLOR_DEFAULT, size-pos);
     1922+               memset(shell->rendbuf+pos, 0, size-pos);
     1923+               memset(shell->charset+pos, 0, size-pos);
     1924+               ESCDEBUGPRINTF( "%s: erase from active position to end of screen\n", __FUNCTION__);
     1925+
     1926+       }
     1927+       else if(i==1)
     1928+       {
     1929+               /*
     1930+                * erase from start of the screen to the active position, inclusive
     1931+                */
     1932+
     1933+               memset(shell->winbuf, ' ', pos);
     1934+               memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, pos);
     1935+               memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, pos);
     1936+               memset(shell->rendbuf, 0, pos);
     1937+               memset(shell->charset, 0, pos);
     1938+               ESCDEBUGPRINTF( "%s: erase from start of screen to active position\n", __FUNCTION__);
     1939+       }
     1940+       else if(i==2)
     1941+       {
     1942+               /*
     1943+                * Erase all of the display
     1944+                */
     1945+
     1946+               memset(shell->winbuf, ' ', size);
     1947+               memset(shell->fgbuf, VIMSHELL_COLOR_DEFAULT, size);
     1948+               memset(shell->bgbuf, VIMSHELL_COLOR_DEFAULT, size);
     1949+               memset(shell->rendbuf, 0, size);
     1950+               memset(shell->charset, 0, size);
     1951+               ESCDEBUGPRINTF( "%s: erase all of the display\n", __FUNCTION__);
     1952+       }
     1953+       else
     1954+       {
     1955+               ESCDEBUGPRINTF( "%s: error in sequence (2)\n", __FUNCTION__);
     1956+               return;
     1957+       }
     1958+}
     1959+
     1960+/*
     1961+ * CUP . Cursor Position
     1962+ * ESC [ Pn ; Pn H     default value: 1
     1963+ *
     1964+ * The CUP sequence moves the active position to the position specified by
     1965+ * the parameters. This sequence has two parameter values, the first specifying
     1966+ * the line position and the second specifying the column position. A parameter
     1967+ * value of zero or one for the first or second parameter moves the active
     1968+ * position to the first line or column in the display, respectively. The default
     1969+ * condition with no parameters present is equivalent to a cursor to home action.
     1970+ * In the VT100, this control behaves identically with its format effector
     1971+ * counterpart, HVP. Editor Function
     1972+ *
     1973+ * The numbering of lines depends on the state of the Origin Mode (DECOM).
     1974+ */
     1975+static void terminal_CUP(struct vim_shell_window *shell, int argc, char argv[20][20])
     1976+{
     1977+       if(argc==0)
     1978+       {
     1979+               /*
     1980+                * goto home position
     1981+                */
     1982+               shell->cursor_x=0;
     1983+               shell->cursor_y=0;
     1984+       }
     1985+       else if(argc==2)
     1986+       {
     1987+               int x, y;
     1988+
     1989+               y=strtol(argv[0], NULL, 10);
     1990+               x=strtol(argv[1], NULL, 10);
     1991+               if(x==0)
     1992+                       x++;
     1993+               if(y==0)
     1994+                       y++;
     1995+
     1996+               shell->cursor_y=y-1;
     1997+               shell->cursor_x=x-1;
     1998+
     1999+               // VIMSHELL TODO: if origin mode enabled, position at the
     2000+               //                top margin or so :)
     2001+
     2002+               if(shell->cursor_x>=shell->size_x)
     2003+                       shell->cursor_x=shell->size_x-1;
     2004+               if(shell->cursor_y>=shell->size_y)
     2005+                       shell->cursor_y=shell->size_y-1;
     2006+       }
     2007+       else
     2008+       {
     2009+               /*
     2010+                * Error in sequence
     2011+                */
     2012+               ESCDEBUGPRINTF( "%s: error in sequence\n", __FUNCTION__);
     2013+               return;
     2014+       }
     2015+       ESCDEBUGPRINTF( "%s: moved to X = %d, Y = %d\n", __FUNCTION__, shell->cursor_x, shell->cursor_y);
     2016+}
     2017+
     2018+/*
     2019+ * DECSTBM . Set Top and Bottom Margins (DEC Private)
     2020+ * ESC [ Pn; Pn r      default values: see below
     2021+ *
     2022+ * This sequence sets the top and bottom margins to define the scrolling region.
     2023+ * The first parameter is the line number of the first line in the scrolling region; the
     2024+ * second parameter is the line number of the bottom line in the scrolling region. Default
     2025+ * is the entire screen (no margins). The minimum size of the scrolling region allowed is
     2026+ * two lines, i.e., the top margin must be less than the bottom margin. The cursor is placed
     2027+ * in the home position (see Origin Mode DECOM).
     2028+ */
     2029+static void terminal_DECSTBM(struct vim_shell_window *shell, int argc, char argv[20][20])
     2030+{
     2031+       if(argc!=2)
     2032+       {
     2033+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     2034+               return;
     2035+       }
     2036+
     2037+       shell->scroll_top_margin=strtol(argv[0], NULL, 10)-1;
     2038+       shell->scroll_bottom_margin=strtol(argv[1], NULL, 10)-1;
     2039+
     2040+       ESCDEBUGPRINTF( "%s: top margin = %d, bottom margin = %d\n", __FUNCTION__,
     2041+                       shell->scroll_top_margin, shell->scroll_bottom_margin);
     2042+
     2043+       if(shell->scroll_top_margin>=shell->scroll_bottom_margin)
     2044+       {
     2045+               ESCDEBUGPRINTF( "%s: scroll margin error %d >= %d\n", __FUNCTION__,
     2046+                               shell->scroll_top_margin, shell->scroll_bottom_margin);
     2047+
     2048+               shell->scroll_top_margin=0;
     2049+               shell->scroll_bottom_margin=shell->size_y-1;
     2050+
     2051+               return;
     2052+       }
     2053+
     2054+       // Move cursor into home position
     2055+       terminal_CUP(shell, 0, NULL);
     2056+}
     2057+
     2058+
     2059+// Status: 100%
     2060+static void terminal_scroll_up(struct vim_shell_window *shell)
     2061+{
     2062+       // VIMSHELL TODO: maintain a scrollback buffer? copy the first line into
     2063+       // a scrollback buffer.
     2064+
     2065+       /*
     2066+        * scroll up by moving up the screen buffer a whole line. blank out
     2067+        * the last line.
     2068+        */
     2069+       int len, from, to;
     2070+
     2071+       ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
     2072+
     2073+       len=shell->scroll_bottom_margin-shell->scroll_top_margin;
     2074+       len*=shell->size_x;
     2075+
     2076+       to=shell->scroll_top_margin*shell->size_x;
     2077+       from=shell->size_x+shell->scroll_top_margin*shell->size_x;
     2078+
     2079+       memmove(shell->winbuf+to, shell->winbuf+from, len);
     2080+       memmove(shell->fgbuf+to, shell->fgbuf+from, len);
     2081+       memmove(shell->bgbuf+to, shell->bgbuf+from, len);
     2082+       memmove(shell->rendbuf+to, shell->rendbuf+from, len);
     2083+       memmove(shell->charset+to, shell->charset+from, len);
     2084+
     2085+       memset(shell->winbuf+shell->scroll_bottom_margin*shell->size_x, ' ', shell->size_x);
     2086+       memset(shell->fgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     2087+       memset(shell->bgbuf+shell->scroll_bottom_margin*shell->size_x, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     2088+       memset(shell->rendbuf+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
     2089+       memset(shell->charset+shell->scroll_bottom_margin*shell->size_x, 0, shell->size_x);
     2090+}
     2091+
     2092+// Status: unknown
     2093+static void terminal_scroll_down(struct vim_shell_window *shell)
     2094+{
     2095+       /*
     2096+        * scroll down by moving the screen buffer down a whole line, overwriting
     2097+        * the last line. Then, blank out the first line.
     2098+        */
     2099+       size_t len;
     2100+       int from, to;
     2101+
     2102+       ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
     2103+
     2104+       len=shell->scroll_bottom_margin-shell->scroll_top_margin;
     2105+       len*=shell->size_x;
     2106+
     2107+       to=shell->scroll_top_margin*shell->size_x+shell->size_x;
     2108+       from=shell->scroll_top_margin*shell->size_x;
     2109+
     2110+       memmove(shell->winbuf+to, shell->winbuf+from, len);
     2111+       memmove(shell->fgbuf+to, shell->fgbuf+from, len);
     2112+       memmove(shell->bgbuf+to, shell->bgbuf+from, len);
     2113+       memmove(shell->rendbuf+to, shell->rendbuf+from, len);
     2114+       memmove(shell->charset+to, shell->charset+from, len);
     2115+
     2116+       memset(shell->winbuf+from, ' ', shell->size_x);
     2117+       memset(shell->fgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     2118+       memset(shell->bgbuf+from, VIMSHELL_COLOR_DEFAULT, shell->size_x);
     2119+       memset(shell->rendbuf+from, 0, shell->size_x);
     2120+       memset(shell->charset+from, 0, shell->size_x);
     2121+}
     2122+
     2123+/*
     2124+ * Insert Line(s) (ANSI).
     2125+ * ESC [ Pn L
     2126+ * Inserts Pn lines at the cursor. If fewer than Pn lines remain from the current line to the
     2127+ * end of the scrolling region, the number of lines inserted is the lesser number. Lines within
     2128+ * the scrolling region at and below the cursor move down. Lines moved past the bottom margin
     2129+ * are lost. The cursor is reset to the first column. This sequence is ignored when the
     2130+ * cursor is outside the scrolling region.
     2131+ */
     2132+// Status: unknown
     2133+static void terminal_IL(struct vim_shell_window *shell, int argc, char argv[20][20])
     2134+{
     2135+       int lines, bak_top;
     2136+       if(argc>1)
     2137+       {
     2138+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     2139+               return;
     2140+       }
     2141+
     2142+       if(argc==0)
     2143+               lines=1;
     2144+       else
     2145+       {
     2146+               lines=strtol(argv[0], NULL, 10);
     2147+               if(lines==0)
     2148+                       lines=1;
     2149+       }
     2150+
     2151+       if(shell->scroll_bottom_margin-shell->cursor_y < lines)
     2152+               lines=shell->scroll_bottom_margin-shell->cursor_y;
     2153+
     2154+       bak_top=shell->scroll_top_margin;
     2155+
     2156+       ESCDEBUGPRINTF( "%s: inserted %d lines\n", __FUNCTION__, lines);
     2157+
     2158+       /*
     2159+        * Set a scrolling region around the part we want to move and scroll down 'lines' times.
     2160+        */
     2161+       shell->scroll_top_margin=shell->cursor_y;
     2162+       while(lines--)
     2163+               terminal_scroll_down(shell);
     2164+
     2165+       shell->scroll_top_margin=bak_top;
     2166+
     2167+       shell->cursor_x=0;
     2168+}
     2169+
     2170+/*
     2171+ * Delete Line(s) (ANSI).
     2172+ * ESC [ Pn M
     2173+ * Deletes Pn lines starting at the line with the cursor. If fewer than Pn lines remain from
     2174+ * the current line to the end of the scrolling region, the number of lines deleted is the
     2175+ * lesser number. As lines are deleted, lines within the scrolling region and below the cursor move
     2176+ * up, and blank lines are added at the bottom of the scrolling region. The cursor is reset to the
     2177+ * first column. This sequence is ignored when the cursor is outside the scrolling region.
     2178+ * VIMSHELL TODO last sentence
     2179+ */
     2180+// Status: unknown
     2181+static void terminal_DL(struct vim_shell_window *shell, int argc, char argv[20][20])
     2182+{
     2183+       int lines, bak_top;
     2184+       if(argc>1)
     2185+       {
     2186+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     2187+               return;
     2188+       }
     2189+
     2190+       if(argc==0)
     2191+               lines=1;
     2192+       else
     2193+       {
     2194+               lines=strtol(argv[0], NULL, 10);
     2195+               if(lines==0)
     2196+                       lines=1;
     2197+       }
     2198+
     2199+       if(shell->scroll_bottom_margin-shell->cursor_y < lines)
     2200+               lines=shell->scroll_bottom_margin-shell->cursor_y;
     2201+
     2202+       bak_top=shell->scroll_top_margin;
     2203+
     2204+       ESCDEBUGPRINTF( "%s: deleted %d lines\n", __FUNCTION__, lines);
     2205+
     2206+       /*
     2207+        * Set a scrolling region around the part we want to move and scroll up 'lines' times.
     2208+        */
     2209+       shell->scroll_top_margin=shell->cursor_y;
     2210+       while(lines--)
     2211+               terminal_scroll_up(shell);
     2212+
     2213+       shell->scroll_top_margin=bak_top;
     2214+
     2215+       shell->cursor_x=0;
     2216+}
     2217+
     2218+/*
     2219+ * Insert Characters (ANSI)
     2220+ * ESC [ Pn @
     2221+ * Insert Pn blank characters at the cursor position, with the character attributes set to
     2222+ * normal. The cursor does not move and remains at the beginning of the inserted blank characters.
     2223+ * A parameter of 0 or 1 inserts one blank character. Data on the line is shifted forward as
     2224+ * in character insertion.
     2225+ */
     2226+static void terminal_ICH(struct vim_shell_window *shell, int argc, char argv[20][20])
     2227+{
     2228+       int chars;
     2229+       int curpos;
     2230+       size_t len;
     2231+       if(argc>1)
     2232+       {
     2233+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     2234+               return;
     2235+       }
     2236+
     2237+       if(argc==0)
     2238+               chars=1;
     2239+       else
     2240+       {
     2241+               chars=strtol(argv[0], NULL, 10);
     2242+               if(chars==0)
     2243+                       chars=1;
     2244+       }
     2245+
     2246+       curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
     2247+       len=shell->size_x-shell->cursor_x-1;
     2248+
     2249+       ESCDEBUGPRINTF( "%s: inserted %d characters\n", __FUNCTION__, chars);
     2250+
     2251+       while(chars--)
     2252+       {
     2253+               memmove(shell->winbuf+curpos+1, shell->winbuf+curpos, len);
     2254+               memmove(shell->fgbuf+curpos+1, shell->fgbuf+curpos, len);
     2255+               memmove(shell->bgbuf+curpos+1, shell->bgbuf+curpos, len);
     2256+               memmove(shell->rendbuf+curpos+1, shell->rendbuf+curpos, len);
     2257+               memmove(shell->charset+curpos+1, shell->charset+curpos, len);
     2258+
     2259+               memset(shell->winbuf+curpos, ' ', 1);
     2260+               memset(shell->fgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
     2261+               memset(shell->bgbuf+curpos, VIMSHELL_COLOR_DEFAULT, 1);
     2262+               memset(shell->rendbuf+curpos, 0, 1);
     2263+               memset(shell->charset+curpos, 0, 1);
     2264+       }
     2265+}
     2266+
     2267+/*
     2268+ * Delete Characters (ANSI)
     2269+ * ESC [ Pn P
     2270+ * Deletes Pn characters starting with the character at the cursor position. When a character
     2271+ * is deleted, all characters to the right of the cursor move to the left. This creates a space
     2272+ * character at the right margin for each character deleted. Character attributes move with the
     2273+ * characters. The spaces created at the end of the line have all their character attributes off.
     2274+ */
     2275+static void terminal_DCH(struct vim_shell_window *shell, int argc, char argv[20][20])
     2276+{
     2277+       int chars;
     2278+       int curpos;
     2279+       size_t len;
     2280+       if(argc>1)
     2281+       {
     2282+               ESCDEBUGPRINTF( "%s: sequence error\n", __FUNCTION__);
     2283+               return;
     2284+       }
     2285+
     2286+       if(argc==0)
     2287+               chars=1;
     2288+       else
     2289+       {
     2290+               chars=strtol(argv[0], NULL, 10);
     2291+               if(chars==0)
     2292+                       chars=1;
     2293+       }
     2294+
     2295+       curpos=shell->cursor_y*shell->size_x+shell->cursor_x;
     2296+       len=shell->size_x-shell->cursor_x-1;
     2297+
     2298+       ESCDEBUGPRINTF( "%s: deleted %d characters\n", __FUNCTION__, chars);
     2299+
     2300+       while(chars--)
     2301+       {
     2302+               memmove(shell->winbuf+curpos, shell->winbuf+curpos+1, len);
     2303+               memmove(shell->fgbuf+curpos, shell->fgbuf+curpos+1, len);
     2304+               memmove(shell->bgbuf+curpos, shell->bgbuf+curpos+1, len);
     2305+               memmove(shell->rendbuf+curpos, shell->rendbuf+curpos+1, len);
     2306+               memmove(shell->charset+curpos, shell->charset+curpos+1, len);
     2307+
     2308+               memset(shell->winbuf+curpos+len, ' ', 1);
     2309+               memset(shell->fgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
     2310+               memset(shell->bgbuf+curpos+len, VIMSHELL_COLOR_DEFAULT, 1);
     2311+               memset(shell->rendbuf+curpos+len, 0, 1);
     2312+               memset(shell->charset+curpos+len, 0, 1);
     2313+       }
     2314+}
     2315+
     2316+static void terminal_BEL(struct vim_shell_window *shell)
     2317+{
     2318+       /*
     2319+        * "Sound bell tone from keyboard."
     2320+        * Sure.
     2321+        */
     2322+}
     2323+
     2324+static void terminal_BS(struct vim_shell_window *shell)
     2325+{
     2326+       /*
     2327+        * "Move the cursor to the left one character position,
     2328+        * unless it is at the left margin, in which case no action occurs."
     2329+        */
     2330+       if(shell->cursor_x>0)
     2331+               shell->cursor_x--;
     2332+}
     2333+
     2334+static void terminal_LF(struct vim_shell_window *shell)
     2335+{
     2336+       /*
     2337+        * "This code causes a line feed or a new line operation."
     2338+        */
     2339+
     2340+       if(shell->just_wrapped_around==1)
     2341+       {
     2342+               /*
     2343+                * Terminals which have the xenl capability ignore a linefeed after
     2344+                * an auto margin wrap.
     2345+                */
     2346+               VERBOSEPRINTF( "%s: ignored LF because of earlier wrap around\n",
     2347+                               __FUNCTION__);
     2348+               return;
     2349+       }
     2350+
     2351+       shell->cursor_y++;
     2352+       if(shell->cursor_y-1==shell->scroll_bottom_margin)
     2353+       {
     2354+               shell->cursor_y--;
     2355+               terminal_scroll_up(shell);
     2356+       }
     2357+
     2358+       VERBOSEPRINTF( "%s: did LF, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
     2359+                       shell->cursor_x, shell->cursor_y);
     2360+}
     2361+
     2362+static void terminal_CR(struct vim_shell_window *shell)
     2363+{
     2364+       /*
     2365+        * "Move cursor to the left margin on the current line."
     2366+        */
     2367+       if(shell->just_wrapped_around==1)
     2368+       {
     2369+               /*
     2370+                * Terminals which have the xenl capability ignore a linefeed after
     2371+                * an auto margin wrap.
     2372+                */
     2373+               VERBOSEPRINTF( "%s: ignored CR because of earlier wrap around\n",
     2374+                               __FUNCTION__);
     2375+               return;
     2376+       }
     2377+       shell->cursor_x=0;
     2378+       VERBOSEPRINTF( "%s: did CR, cursor is now at X = %u, Y = %u\n", __FUNCTION__,
     2379+                       shell->cursor_x, shell->cursor_y);
     2380+}
     2381+
     2382+/*
     2383+ * RI . Reverse Index
     2384+ * ESC M
     2385+ *
     2386+ * Move the active position to the same horizontal position on the preceding line. If the
     2387+ * active position is at the top margin, a scroll down is performed. Format Effector
     2388+ */
     2389+static void terminal_RI(struct vim_shell_window *shell)
     2390+{
     2391+       ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
     2392+       if(shell->cursor_y==shell->scroll_top_margin)
     2393+               terminal_scroll_down(shell);
     2394+       else
     2395+               shell->cursor_y--;
     2396+}
     2397+
     2398+/*
     2399+ * IND . Index
     2400+ * ESC D
     2401+ *
     2402+ * This sequence causes the active position to move downward one line without changing the
     2403+ * column position. If the active position is at the bottom margin, a scroll up is performed.
     2404+ * Format Effector
     2405+ */
     2406+static void terminal_IND(struct vim_shell_window *shell)
     2407+{
     2408+       ESCDEBUGPRINTF( "%s: done\n", __FUNCTION__);
     2409+       if(shell->cursor_y==shell->scroll_bottom_margin)
     2410+               terminal_scroll_up(shell);
     2411+       else
     2412+               shell->cursor_y++;
     2413+}
     2414+
     2415+/*
     2416+ * ESC 7
     2417+ * ESC [s (ANSI)
     2418+ * Saves the current terminal rendering settings
     2419+ */
     2420+static void terminal_save_attributes(struct vim_shell_window *shell)
     2421+{
     2422+       shell->saved_cursor_x=shell->cursor_x;
     2423+       shell->saved_cursor_y=shell->cursor_y;
     2424+       shell->saved_rendition=shell->rendition;
     2425+       shell->saved_fgcolor=shell->fgcolor;
     2426+       shell->saved_bgcolor=shell->bgcolor;
     2427+       shell->saved_G0_charset=shell->G0_charset;
     2428+       shell->saved_G1_charset=shell->G1_charset;
     2429+       shell->saved_application_keypad_mode=shell->application_keypad_mode;
     2430+       shell->saved_application_cursor_mode=shell->application_cursor_mode;
     2431+       shell->saved_insert_mode=shell->insert_mode;
     2432+}
     2433+
     2434+/*
     2435+ * ESC 8
     2436+ * ESC [u (ANSI)
     2437+ * Restores the current terminal rendering settings
     2438+ */
     2439+static void terminal_restore_attributes(struct vim_shell_window *shell)
     2440+{
     2441+       shell->cursor_x=shell->saved_cursor_x;
     2442+       shell->cursor_y=shell->saved_cursor_y;
     2443+       shell->rendition=shell->saved_rendition;
     2444+       shell->fgcolor=shell->saved_fgcolor;
     2445+       shell->bgcolor=shell->saved_bgcolor;
     2446+       shell->G0_charset=shell->saved_G0_charset;
     2447+       shell->G1_charset=shell->saved_G1_charset;
     2448+       shell->application_keypad_mode=shell->saved_application_keypad_mode;
     2449+       shell->application_cursor_mode=shell->saved_application_cursor_mode;
     2450+       shell->insert_mode=shell->saved_insert_mode;
     2451+}
     2452+
     2453+#define ADVANCE_PSEQ { pseq++; if(*pseq==0) return; }
     2454+
     2455+/*
     2456+ * Attempts to parse the escape sequence stored in shell->esc_sequence.
     2457+ * When it succeeds, it removes that escape sequence from the buffer and
     2458+ * possibly clears shell->in_esc_sequence when there are no characters left,
     2459+ * leaving ESC mode.
     2460+ */
     2461+static void terminal_parse_esc_sequence(struct vim_shell_window *shell)
     2462+{
     2463+       char *pseq;
     2464+
     2465+       if(shell->in_esc_sequence==0 || shell->esc_sequence[0]!=033)
     2466+       {
     2467+               ESCDEBUGPRINTF( "%s: invalid esc sequence in esc buffer\n",
     2468+                               __FUNCTION__);
     2469+               /*
     2470+                * We would stick here forever, so flush the buffer
     2471+                */
     2472+               shell->in_esc_sequence=0;
     2473+               terminal_flush_output(shell);
     2474+
     2475+               return;
     2476+       }
     2477+
     2478+       if(shell->in_esc_sequence==1)
     2479+       {
     2480+               ESCDEBUGPRINTF( "%s: not much in the buffer ...\n", __FUNCTION__);
     2481+               return;
     2482+       }
     2483+
     2484+       shell->esc_sequence[shell->in_esc_sequence]=0;
     2485+       pseq=shell->esc_sequence+1;
     2486+
     2487+       if(*pseq=='[')
     2488+       {
     2489+               /*
     2490+                * Got a Control Sequence Introducer (CSI) = ESC [
     2491+                * Parse Parameters.
     2492+                */
     2493+
     2494+               int argc=0;
     2495+               char argv[20][20];
     2496+
     2497+               ADVANCE_PSEQ;
     2498+
     2499+               memset(argv, 0, sizeof(argv));
     2500+
     2501+               if((*pseq>='0' && *pseq<='9') || *pseq=='?' || *pseq==';')
     2502+               {
     2503+                       int cont;
     2504+                       do
     2505+                       {
     2506+                               cont=0;
     2507+                               while((*pseq>='0' && *pseq<='9') || *pseq=='?')
     2508+                               {
     2509+                                       char dummy[2];
     2510+                                       dummy[0]=*pseq;
     2511+                                       dummy[1]=0;
     2512+                                       strcat(argv[argc], dummy);
     2513+                                       ADVANCE_PSEQ;
     2514+                               }
     2515+                               if(argv[argc][0]==0)
     2516+                               {
     2517+                                       strcpy(argv[argc], "0");
     2518+                               }
     2519+
     2520+                               argc++;
     2521+                               if(*pseq==';')
     2522+                               {
     2523+                                       cont=1;
     2524+                                       ADVANCE_PSEQ;
     2525+                               }
     2526+                       } while(cont==1);
     2527+               }
     2528+
     2529+#ifdef ESCDEBUG
     2530+               ESCDEBUGPRINTF("%s: sequence = '%s', argc = %d, ", __FUNCTION__, shell->esc_sequence, argc);
     2531+               {
     2532+                       int i;
     2533+                       for(i=0;i<argc;i++)
     2534+                       {
     2535+                               ESCDEBUGPRINTF("argv[%d] = '%s', ",i, argv[i]);
     2536+                       }
     2537+               }
     2538+               ESCDEBUGPRINTF("\n");
     2539+#endif
     2540+
     2541+               switch(*pseq)
     2542+               {
     2543+                       case 'f':
     2544+                       case 'H':
     2545+                               terminal_CUP(shell, argc, argv);
     2546+                               break;
     2547+                       case 'J':
     2548+                               terminal_ED(shell, argc, argv);
     2549+                               break;
     2550+                       case 'K':
     2551+                               terminal_EL(shell, argc, argv);
     2552+                               break;
     2553+                       case 'C':
     2554+                               terminal_CUF(shell, argc, argv);
     2555+                               break;
     2556+                       case 'l':
     2557+                               terminal_mode(shell, 0, argc, argv);
     2558+                               break;
     2559+                       case 'h':
     2560+                               terminal_mode(shell, 1, argc, argv);
     2561+                               break;
     2562+                       case 'm':
     2563+                               terminal_SGR(shell, argc, argv);
     2564+                               break;
     2565+                       case 'r': // set scroll margins
     2566+                               terminal_DECSTBM(shell, argc, argv);
     2567+                               break;
     2568+                       case 'B': // cursor down
     2569+                               terminal_CUD(shell, argc, argv);
     2570+                               break;
     2571+                       case 'D': // cursor backward
     2572+                               terminal_CUB(shell, argc, argv);
     2573+                               break;
     2574+                       case 'A': // cursor up
     2575+                               terminal_CUU(shell, argc, argv);
     2576+                               break;
     2577+                       case 'M': // delete line
     2578+                               terminal_DL(shell, argc, argv);
     2579+                               break;
     2580+                       case 'L': // insert line
     2581+                               terminal_IL(shell, argc, argv);
     2582+                               break;
     2583+                       case '@': // insert characters
     2584+                               terminal_ICH(shell, argc, argv);
     2585+                               break;
     2586+                       case 'P': // delete characters
     2587+                               terminal_DCH(shell, argc, argv);
     2588+                               break;
     2589+                       case 'E': // new line
     2590+                               terminal_CR(shell);
     2591+                               terminal_LF(shell);
     2592+                               break;
     2593+                       case 's': // Save Cursor and attributes
     2594+                               terminal_save_attributes(shell);
     2595+                               break;
     2596+                       case 'u': // Restore Cursor and attributes
     2597+                               terminal_restore_attributes(shell);
     2598+                               break;
     2599+                       case 'g': // Tabulator clear
     2600+                               terminal_TBC(shell, argc, argv);
     2601+                               break;
     2602+                       default:
     2603+                               ESCDEBUGPRINTF( "%s: unimplemented CSI code: %c\n",
     2604+                                               __FUNCTION__, *pseq);
     2605+               }
     2606+       }
     2607+       else
     2608+       {
     2609+               ESCDEBUGPRINTF( "%s: sequence is (probably not yet complete) '%s'\n",
     2610+                               __FUNCTION__, shell->esc_sequence);
     2611+               switch(*pseq)
     2612+               {
     2613+                       case '#':
     2614+                               ADVANCE_PSEQ;
     2615+                               if(*pseq=='8') // fill screen with E's
     2616+                               {
     2617+                                       memset(shell->winbuf, 'E', shell->size_x*shell->size_y);
     2618+                               }
     2619+                               break;
     2620+                       case '(': // switch G0 charset
     2621+                               ADVANCE_PSEQ;
     2622+                               shell->G0_charset=*pseq;
     2623+                               ESCDEBUGPRINTF( "%s: G0 character set is now: %c\n", __FUNCTION__, *pseq);
     2624+                               break;
     2625+                       case ')': // switch G1 charset
     2626+                               ADVANCE_PSEQ;
     2627+                               shell->G1_charset=*pseq;
     2628+                               ESCDEBUGPRINTF( "%s: G1 character set is now: %c\n", __FUNCTION__, *pseq);
     2629+                               break;
     2630+                       case 'D': // index
     2631+                               terminal_IND(shell);
     2632+                               break;
     2633+                       case 'M': // reverse index
     2634+                               terminal_RI(shell);
     2635+                               break;
     2636+                       case '7': // Save Cursor
     2637+                               terminal_save_attributes(shell);
     2638+                               break;
     2639+                       case '8': // Restore Cursor
     2640+                               terminal_restore_attributes(shell);
     2641+                               break;
     2642+                       case '=': // Application Keypad Mode
     2643+                               shell->application_keypad_mode=1;
     2644+                               ESCDEBUGPRINTF( "%s: keypad switched to application mode\n", __FUNCTION__);
     2645+                               break;
     2646+                       case '>': // Numeric Keypad Mode
     2647+                               shell->application_keypad_mode=0;
     2648+                               ESCDEBUGPRINTF( "%s: keypad switched to numeric mode\n", __FUNCTION__);
     2649+                               break;
     2650+                       case 'H': // Set Horizontal Tab
     2651+                               shell->tabline[shell->cursor_x]=1;
     2652+                               break;
     2653+                       case 'E': // NEL - Moves cursor to first position on next line. If cursor is
     2654+                                 // at bottom margin, screen performs a scroll-up.
     2655+                               terminal_IND(shell);
     2656+                               shell->cursor_x=0;
     2657+                               break;
     2658+                       case ']': // This could be the beginning of the xterm title hack
     2659+                               ADVANCE_PSEQ;
     2660+                               if(*pseq=='1' || *pseq=='2' || *pseq=='0')
     2661+                               {
     2662+                                       char title[50];
     2663+                                       ADVANCE_PSEQ;
     2664+                                       if(*pseq==';')
     2665+                                       {
     2666+                                               int end;
     2667+                                               title[0]=0;
     2668+                                               /*
     2669+                                                * I know this loop is ugly but ADVANCE_PSEQ
     2670+                                                * is a macro, sorry
     2671+                                                */
     2672+                                               for(end=0;!end;)
     2673+                                               {
     2674+                                                       ADVANCE_PSEQ;
     2675+                                                       if(strlen(title)>sizeof(title)-2)
     2676+                                                               end=1;
     2677+                                                       if(*pseq==7)
     2678+                                                               end=1;
     2679+                                                       else
     2680+                                                       {
     2681+                                                               char dummy[2];
     2682+                                                               dummy[0]=*pseq;
     2683+                                                               dummy[1]=0;
     2684+                                                               strcat(title, dummy);
     2685+                                                       }
     2686+                                               }
     2687+
     2688+                                               snprintf(shell->windowtitle, sizeof(shell->windowtitle),
     2689+                                                               "%s", title);
     2690+
     2691+                                               ESCDEBUGPRINTF( "%s: changing title to '%s'\n",
     2692+                                                               __FUNCTION__, shell->windowtitle);
     2693+                                       }
     2694+                                       else
     2695+                                       {
     2696+                                               ESCDEBUGPRINTF( "%s: error in xterm title hack "
     2697+                                                               "sequence: %c\n", __FUNCTION__, *pseq);
     2698+                                       }
     2699+                               }
     2700+                               else
     2701+                               {
     2702+                                       ESCDEBUGPRINTF( "%s: unimplemented xterm title hack "
     2703+                                                       "code: %d\n", __FUNCTION__, *pseq);
     2704+                               }
     2705+                               break;
     2706+                       default:
     2707+                               ESCDEBUGPRINTF( "%s: unimplemented esc code: %c\n",
     2708+                                               __FUNCTION__, *pseq);
     2709+               }
     2710+       }
     2711+
     2712+       /*
     2713+        * when we end up here, we successfully completed the sequence.
     2714+        */
     2715+       shell->in_esc_sequence=0;
     2716+       terminal_flush_output(shell);
     2717+
     2718+#ifdef ESCDEBUG
     2719+       pseq++;
     2720+       if(*pseq!=0)
     2721+       {
     2722+               ESCDEBUGPRINTF( "WARNING: %s: sequence is not over! left in buffer: '%s'\n",
     2723+                               __FUNCTION__, pseq);
     2724+       }
     2725+#endif
     2726+}
     2727+
     2728+
     2729+/*
     2730+ * Main character write part.
     2731+ * This here runs most of the time, just writing the character to the
     2732+ * right cursor position.
     2733+ */
     2734+static void terminal_normal_char(struct vim_shell_window *shell, char input)
     2735+{
     2736+       int pos;
     2737+       uint8_t charset;
     2738+
     2739+       shell->just_wrapped_around=0;
     2740+       /*
     2741+        * If the cursor is currently in the 'virtual' column (that is the column
     2742+        * after the physical line end), we wrap around now.
     2743+        */
     2744+       if(shell->cursor_x==shell->size_x)
     2745+       {
     2746+               if(shell->wraparound==1)
     2747+               {
     2748+                       terminal_CR(shell);
     2749+                       terminal_LF(shell);
     2750+                       shell->just_wrapped_around=1;
     2751+                       VERBOSEPRINTF( "%s: auto margin - wrapped around!\n",__FUNCTION__);
     2752+               }
     2753+               else
     2754+               {
     2755+                       shell->cursor_x--;
     2756+               }
     2757+       }
     2758+
     2759+       /*
     2760+        * write the character at its right position.
     2761+        */
     2762+       if(shell->insert_mode!=0)
     2763+       {
     2764+               /*
     2765+                * If insert mode is on, move all characters from the current position+1 to
     2766+                * the end of the row. The last character on the row falls out.
     2767+                * Fortunately, we already implemented this kind of operation :)
     2768+                */
     2769+                terminal_ICH(shell, 0, NULL);
     2770+       }
     2771+       pos=shell->cursor_y*shell->size_x+shell->cursor_x;
     2772+
     2773+       /*
     2774+        * Select which character to display.
     2775+        */
     2776+       if(shell->active_charset==1)
     2777+               charset=shell->G1_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
     2778+       else
     2779+               charset=shell->G0_charset=='0' ? VIMSHELL_CHARSET_DRAWING : VIMSHELL_CHARSET_USASCII;
     2780+
     2781+       shell->winbuf[pos]=input;
     2782+       shell->fgbuf[pos]=shell->fgcolor;
     2783+       shell->bgbuf[pos]=shell->bgcolor;
     2784+       shell->rendbuf[pos]=shell->rendition;
     2785+       shell->charset[pos]=charset;
     2786+       VERBOSEPRINTF( "%s: writing char '%c' to position X = %u, Y = %u (col: 0x%02x,0x%02x)\n", __FUNCTION__,
     2787+                       input, shell->cursor_x, shell->cursor_y, current_fg, current_bg);
     2788+       shell->cursor_x++;
     2789+}
     2790+
     2791+/*
     2792+ * Here, all characters between 000 and 037 are processed. This is in a
     2793+ * separate function because control characters can be in the normal
     2794+ * flow of characters or in the middle of escape sequences.
     2795+ */
     2796+static void terminal_process_control_char(struct vim_shell_window *shell, char input)
     2797+{
     2798+       switch(input)
     2799+       {
     2800+               case 007: // BEL, Bell, 0x07
     2801+                       terminal_BEL(shell);
     2802+                       break;
     2803+               case 010: // BS, Backspace, 0x08
     2804+                       terminal_BS(shell);
     2805+                       break;
     2806+               case 011: // TAB
     2807+                       {
     2808+                               /*
     2809+                                * Move to the next tabstop or stop at the right margin if no
     2810+                                * tabstop found.
     2811+                                */
     2812+                               int i, found;
     2813+                               for(found=0, i=shell->cursor_x+1;i<shell->size_x && !found;i++)
     2814+                               {
     2815+                                       if(shell->tabline[i]==1)
     2816+                                       {
     2817+                                               shell->cursor_x=i;
     2818+                                               found=1;
     2819+                                       }
     2820+                               }
     2821+                               if(found==0)
     2822+                               {
     2823+                                       shell->cursor_x=shell->size_x-1;
     2824+                               }
     2825+                       }
     2826+                       break;
     2827+               case 013:
     2828+               case 014:
     2829+               case 012: // LF, Line Feed, 0x0a, \n
     2830+                       terminal_LF(shell);
     2831+                       break;
     2832+               case 015: // CR, Carriage Return, 0x0d, \r
     2833+                       terminal_CR(shell);
     2834+                       break;
     2835+               case 016: // SO, Invoke G1 character set, as designated by SCS control sequence.
     2836+                       shell->active_charset=1;
     2837+                       break;
     2838+               case 017: // SI, Select G0 character set, as selected by ESC ( sequence.
     2839+                       shell->active_charset=0;
     2840+                       break;
     2841+               case 030:
     2842+               case 032: // CAN or SUB - cancel escape sequence
     2843+                       shell->in_esc_sequence=0;
     2844+                       // VIMSHELL TODO: display substitution character?
     2845+                       ESCDEBUGPRINTF("%s: WARNING: possible source of rendering faults: "
     2846+                                       "substitution characters after CAN or SUB?\n", __FUNCTION__);
     2847+                       break;
     2848+               case 033: // ESC, Escape
     2849+                       /*
     2850+                        * Note: This also fulfills the requirement that a ESC occuring while processing
     2851+                        *       an escape sequence should restart the sequence.
     2852+                        */
     2853+                       shell->in_esc_sequence=1;
     2854+                       shell->esc_sequence[0]=033;
     2855+                       break;
     2856+               default:
     2857+                       ESCDEBUGPRINTF("%s: unimplemented control character: %u\n", __FUNCTION__, input);
     2858+                       break;
     2859+       }
     2860+}
     2861+
     2862+static void terminal_input_char(struct vim_shell_window *shell, char input)
     2863+{
     2864+       if(shell->in_esc_sequence==0)
     2865+       {
     2866+               if(input>=0 && input<=037)
     2867+               {
     2868+                       /*
     2869+                        * A control character, process it
     2870+                        */
     2871+                       terminal_process_control_char(shell, input);
     2872+               }
     2873+               else
     2874+               {
     2875+                       // all normal characters are processed here
     2876+                       terminal_normal_char(shell, input);
     2877+               }
     2878+       }
     2879+       else
     2880+       {
     2881+               if(input>=0 && input<=037)
     2882+               {
     2883+                       /*
     2884+                        * That's right, control characters can appear even in
     2885+                        * the middle of escape sequences.
     2886+                        */
     2887+                       terminal_process_control_char(shell, input);
     2888+                       return;
     2889+               }
     2890+
     2891+               /*
     2892+                * Aha, we are right in the middle of an escape sequence.
     2893+                * Add this character and attempt to parse the sequence.
     2894+                */
     2895+               shell->esc_sequence[shell->in_esc_sequence]=input;
     2896+               shell->in_esc_sequence++;
     2897+
     2898+               if(shell->in_esc_sequence>=sizeof(shell->esc_sequence))
     2899+               {
     2900+                       /*
     2901+                        * about to overrun esc sequence buffer ...
     2902+                        * Should never happen, but still: kill the sequence, or we'd loop
     2903+                        * forever.
     2904+                        */
     2905+
     2906+                       shell->in_esc_sequence=0;
     2907+                       terminal_flush_output(shell);
     2908+                       return;
     2909+               }
     2910+
     2911+               terminal_parse_esc_sequence(shell);
     2912+       }
     2913+}
     2914+
     2915+/*
     2916+ * If we are ready, flush the outbuf into the shell.
     2917+ * CHECK: should always be called when shell->in_esc_sequence goes back to zero,
     2918+ *        so characters that are waiting for a sequence to become complete can be
     2919+ *        flushed out.
     2920+ */
     2921+static int terminal_flush_output(struct vim_shell_window *shell)
     2922+{
     2923+       if(/*shell->in_esc_sequence==0 && */ shell->outbuf_pos>0)
     2924+       {
     2925+               int len;
     2926+#ifdef ESCDEBUG
     2927+               ESCDEBUGPRINTF( "%s: sending:\n",__FUNCTION__);
     2928+               hexdump(vimshell_debug_fp, shell->outbuf, shell->outbuf_pos);
     2929+#endif
     2930+               len=write(shell->fd_master, shell->outbuf, shell->outbuf_pos);
     2931+               if(len<0)
     2932+               {
     2933+                       ESCDEBUGPRINTF( "%s: ERROR: write failed: %s\n",
     2934+                                       __FUNCTION__,strerror(errno));
     2935+                       shell->outbuf_pos=0;
     2936+                       return -1;
     2937+               }
     2938+
     2939+               if(shell->outbuf_pos!=len)
     2940+                       memmove(shell->outbuf, shell->outbuf+len, len);
     2941+               shell->outbuf_pos-=len;
     2942+
     2943+               return len;
     2944+       }
     2945+       return 0;
     2946+}
     2947+
     2948+/*
     2949+ * Main Terminal processing method (VIM <- Shell).
     2950+ * Gets a buffer with input data from the shell, interprets it and updates
     2951+ * the shell window's windowbuffer accordingly.
     2952+ */
     2953+void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len)
     2954+{
     2955+       int i;
     2956+       for(i=0;i<len;i++)
     2957+       {
     2958+               terminal_input_char(shell, input[i]);
     2959+       }
     2960+}
     2961+
     2962+/*
     2963+ * Main Terminal output method (VIM -> Shell).
     2964+ * Translates the character 'c' into an appropriate escape sequence (if necessary)
     2965+ * and puts it into the out buffer.
     2966+ */
     2967+int vim_shell_terminal_output(struct vim_shell_window *shell, int c)
     2968+{
     2969+       char outbuf[50];
     2970+       size_t written;
     2971+
     2972+       outbuf[1]=0;
     2973+
     2974+       switch(c)
     2975+       {
     2976+               case VIMSHELL_KEY_BACKSPACE:
     2977+                       sprintf(outbuf, "\177");
     2978+                       ESCDEBUGPRINTF( "%s: key is backspace\n", __FUNCTION__);
     2979+                       break;
     2980+               case VIMSHELL_KEY_UP:
     2981+                       sprintf(outbuf, "\033%cA", shell->application_cursor_mode ? 'O' : '[');
     2982+                       ESCDEBUGPRINTF( "%s: key is cursor up\n", __FUNCTION__);
     2983+                       break;
     2984+               case VIMSHELL_KEY_DOWN:
     2985+                       sprintf(outbuf, "\033%cB", shell->application_cursor_mode ? 'O' : '[');
     2986+                       ESCDEBUGPRINTF( "%s: key is cursor down\n", __FUNCTION__);
     2987+                       break;
     2988+               case VIMSHELL_KEY_LEFT:
     2989+                       sprintf(outbuf, "\033%cD", shell->application_cursor_mode ? 'O' : '[');
     2990+                       ESCDEBUGPRINTF( "%s: key is cursor left\n", __FUNCTION__);
     2991+                       break;
     2992+               case VIMSHELL_KEY_RIGHT:
     2993+                       sprintf(outbuf, "\033%cC", shell->application_cursor_mode ? 'O' : '[');
     2994+                       ESCDEBUGPRINTF( "%s: key is cursor right\n", __FUNCTION__);
     2995+                       break;
     2996+               case VIMSHELL_KEY_HOME:
     2997+                       sprintf(outbuf, "\033[1~");
     2998+                       ESCDEBUGPRINTF( "%s: key is home\n", __FUNCTION__);
     2999+                       break;
     3000+               case VIMSHELL_KEY_F1:
     3001+                       sprintf(outbuf, "\033OP");
     3002+                       ESCDEBUGPRINTF( "%s: key is F1\n", __FUNCTION__);
     3003+                       break;
     3004+               case VIMSHELL_KEY_F2:
     3005+                       sprintf(outbuf, "\033OQ");
     3006+                       ESCDEBUGPRINTF( "%s: key is F2\n", __FUNCTION__);
     3007+                       break;
     3008+               case VIMSHELL_KEY_F3:
     3009+                       sprintf(outbuf, "\033OR");
     3010+                       ESCDEBUGPRINTF( "%s: key is F3\n", __FUNCTION__);
     3011+                       break;
     3012+               case VIMSHELL_KEY_F4:
     3013+                       sprintf(outbuf, "\033OS");
     3014+                       ESCDEBUGPRINTF( "%s: key is F4\n", __FUNCTION__);
     3015+                       break;
     3016+               case VIMSHELL_KEY_F5:
     3017+                       sprintf(outbuf, "\033[15~");
     3018+                       ESCDEBUGPRINTF( "%s: key is F5\n", __FUNCTION__);
     3019+                       break;
     3020+               case VIMSHELL_KEY_F6:
     3021+                       sprintf(outbuf, "\033[17~");
     3022+                       ESCDEBUGPRINTF( "%s: key is F6\n", __FUNCTION__);
     3023+                       break;
     3024+               case VIMSHELL_KEY_F7:
     3025+                       sprintf(outbuf, "\033[18~");
     3026+                       ESCDEBUGPRINTF( "%s: key is F7\n", __FUNCTION__);
     3027+                       break;
     3028+               case VIMSHELL_KEY_F8:
     3029+                       sprintf(outbuf, "\033[19~");
     3030+                       ESCDEBUGPRINTF( "%s: key is F8\n", __FUNCTION__);
     3031+                       break;
     3032+               case VIMSHELL_KEY_F9:
     3033+                       sprintf(outbuf, "\033[20~");
     3034+                       ESCDEBUGPRINTF( "%s: key is F9\n", __FUNCTION__);
     3035+                       break;
     3036+               case VIMSHELL_KEY_F10:
     3037+                       sprintf(outbuf, "\033[21~");
     3038+                       ESCDEBUGPRINTF( "%s: key is F10\n", __FUNCTION__);
     3039+                       break;
     3040+               case VIMSHELL_KEY_F11:
     3041+                       sprintf(outbuf, "\033[23~");
     3042+                       ESCDEBUGPRINTF( "%s: key is F11\n", __FUNCTION__);
     3043+                       break;
     3044+               case VIMSHELL_KEY_F12:
     3045+                       sprintf(outbuf, "\033[24~");
     3046+                       ESCDEBUGPRINTF( "%s: key is F12\n", __FUNCTION__);
     3047+                       break;
     3048+               case VIMSHELL_KEY_DC:
     3049+                       sprintf(outbuf, "\033[3~");
     3050+                       ESCDEBUGPRINTF( "%s: key is delete character\n", __FUNCTION__);
     3051+                       break;
     3052+               case VIMSHELL_KEY_END:
     3053+                       sprintf(outbuf, "\033[4~");
     3054+                       ESCDEBUGPRINTF( "%s: key is end\n", __FUNCTION__);
     3055+                       break;
     3056+               case VIMSHELL_KEY_IC:
     3057+                       sprintf(outbuf, "\033[2~");
     3058+                       ESCDEBUGPRINTF( "%s: key is insert character\n", __FUNCTION__);
     3059+                       break;
     3060+               case VIMSHELL_KEY_NPAGE:
     3061+                       sprintf(outbuf, "\033[6~");
     3062+                       ESCDEBUGPRINTF( "%s: key is page down\n", __FUNCTION__);
     3063+                       break;
     3064+               case VIMSHELL_KEY_PPAGE:
     3065+                       sprintf(outbuf, "\033[5~");
     3066+                       ESCDEBUGPRINTF( "%s: key is page up\n", __FUNCTION__);
     3067+                       break;
     3068+               case VIMSHELL_KEY_K0:
     3069+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Op" : "0");
     3070+                       ESCDEBUGPRINTF( "%s: key is keypad 0\n", __FUNCTION__);
     3071+                       break;
     3072+               case VIMSHELL_KEY_K1:
     3073+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oq" : "1");
     3074+                       ESCDEBUGPRINTF( "%s: key is keypad 1\n", __FUNCTION__);
     3075+                       break;
     3076+               case VIMSHELL_KEY_K2:
     3077+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Or" : "2");
     3078+                       ESCDEBUGPRINTF( "%s: key is keypad 2\n", __FUNCTION__);
     3079+                       break;
     3080+               case VIMSHELL_KEY_K3:
     3081+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Os" : "3");
     3082+                       ESCDEBUGPRINTF( "%s: key is keypad 3\n", __FUNCTION__);
     3083+                       break;
     3084+               case VIMSHELL_KEY_K4:
     3085+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ot" : "4");
     3086+                       ESCDEBUGPRINTF( "%s: key is keypad 4\n", __FUNCTION__);
     3087+                       break;
     3088+               case VIMSHELL_KEY_K5:
     3089+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ou" : "5");
     3090+                       ESCDEBUGPRINTF( "%s: key is keypad 5\n", __FUNCTION__);
     3091+                       break;
     3092+               case VIMSHELL_KEY_K6:
     3093+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ov" : "6");
     3094+                       ESCDEBUGPRINTF( "%s: key is keypad 6\n", __FUNCTION__);
     3095+                       break;
     3096+               case VIMSHELL_KEY_K7:
     3097+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ow" : "7");
     3098+                       ESCDEBUGPRINTF( "%s: key is keypad 7\n", __FUNCTION__);
     3099+                       break;
     3100+               case VIMSHELL_KEY_K8:
     3101+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ox" : "8");
     3102+                       ESCDEBUGPRINTF( "%s: key is keypad 8\n", __FUNCTION__);
     3103+                       break;
     3104+               case VIMSHELL_KEY_K9:
     3105+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oy" : "9");
     3106+                       ESCDEBUGPRINTF( "%s: key is keypad 9\n", __FUNCTION__);
     3107+                       break;
     3108+               case VIMSHELL_KEY_KPLUS:
     3109+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Ok" : "+");
     3110+                       ESCDEBUGPRINTF( "%s: key is keypad plus\n", __FUNCTION__);
     3111+                       break;
     3112+               case VIMSHELL_KEY_KMINUS:
     3113+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Om" : "-");
     3114+                       ESCDEBUGPRINTF( "%s: key is keypad minus\n", __FUNCTION__);
     3115+                       break;
     3116+               case VIMSHELL_KEY_KDIVIDE:
     3117+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oo" : "/");
     3118+                       ESCDEBUGPRINTF( "%s: key is keypad divide\n", __FUNCTION__);
     3119+                       break;
     3120+               case VIMSHELL_KEY_KMULTIPLY:
     3121+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033Oj" : "*");
     3122+                       ESCDEBUGPRINTF( "%s: key is keypad multiply\n", __FUNCTION__);
     3123+                       break;
     3124+               case VIMSHELL_KEY_KENTER:
     3125+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033OM" : "\015");
     3126+                       ESCDEBUGPRINTF( "%s: key is keypad enter\n", __FUNCTION__);
     3127+                       break;
     3128+               case VIMSHELL_KEY_KPOINT:
     3129+                       sprintf(outbuf, "%s", shell->application_keypad_mode ? "\033On" : ".");
     3130+                       ESCDEBUGPRINTF( "%s: key is keypad point\n", __FUNCTION__);
     3131+                       break;
     3132+               default:
     3133+                       outbuf[0]=(char)c;
     3134+       }
     3135+
     3136+       if(shell->outbuf_pos+strlen(outbuf)>=sizeof(shell->outbuf))
     3137+       {
     3138+               written=sizeof(shell->outbuf)-shell->outbuf_pos;
     3139+               ESCDEBUGPRINTF( "%s: WARNING: prevented from overflowing the outbuf, help!\n",
     3140+                               __FUNCTION__);
     3141+       }
     3142+       else
     3143+               written=strlen(outbuf);
     3144+
     3145+       memcpy(shell->outbuf+shell->outbuf_pos, outbuf, written);
     3146+       shell->outbuf_pos+=written;
     3147+
     3148+       if(terminal_flush_output(shell)<0)
     3149+               return -1;
     3150+
     3151+       return written;
     3152+}
     3153+#endif
     3154diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/ui.c ./src/ui.c
     3155--- ../vim72.orig/src/ui.c      2009-10-02 13:39:25.000000000 +0100
     3156+++ ./src/ui.c  2009-10-02 13:39:57.000000000 +0100
     3157@@ -1786,6 +1786,64 @@
     3158     len = 0;   /* to avoid gcc warning */
     3159     for (try = 0; try < 100; ++try)
     3160     {
     3161+#  ifdef FEAT_VIMSHELL
     3162+       {
     3163+           /*
     3164+            * When we use the VIM shell, we use select to look if there was
     3165+            * some activity on the shells. This is because the read below after
     3166+            * this block blocks, and this sucks.
     3167+            *
     3168+            * This loop is basically here so the shells can send updates while
     3169+            * we are waiting for the read(2) on the read_cmd_fd to become available.
     3170+            */
     3171+#  ifndef HAVE_SELECT
     3172+#error sorry - vimshell needs select. programmer is too lazy to write this with poll (at this time)
     3173+#  endif
     3174+           fd_set rdfd;
     3175+           buf_T *buf;
     3176+           int maxfd, ret, done;
     3177+
     3178+           done=0;
     3179+           while(!done)
     3180+           {
     3181+               FD_ZERO(&rdfd);
     3182+               FD_SET(read_cmd_fd, &rdfd);
     3183+               maxfd=read_cmd_fd;
     3184+
     3185+               for(buf=firstbuf; buf!=NULL; buf=buf->b_next)
     3186+               {
     3187+                   if(buf->is_shell!=0)
     3188+                   {
     3189+                       FD_SET(buf->shell->fd_master, &rdfd);
     3190+                       if( maxfd < buf->shell->fd_master)
     3191+                           maxfd = buf->shell->fd_master;
     3192+                   }
     3193+               }
     3194+
     3195+               ret=select(maxfd+1, &rdfd, NULL, NULL, NULL);
     3196+               if(ret<0)
     3197+               {
     3198+                   /*
     3199+                    * we fsck'd something up ... let's just get out of here
     3200+                    */
     3201+                   done=1;
     3202+               }
     3203+               else if(ret>0)
     3204+               {
     3205+                   if(FD_ISSET(read_cmd_fd, &rdfd))
     3206+                   {
     3207+                       /*
     3208+                        * we have what we came here for. exit this loop
     3209+                        * (but only after processing available shell reads)
     3210+                        */
     3211+                       done=1;
     3212+                   }
     3213+
     3214+                   vim_shell_do_read_select(rdfd);
     3215+               }
     3216+           } // while(!done)
     3217+       }
     3218+#  endif
     3219 #  ifdef VMS
     3220        len = vms_read(
     3221 #  else
     3222diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/version.c ./src/version.c
     3223--- ../vim72.orig/src/version.c 2009-10-02 13:39:26.000000000 +0100
     3224+++ ./src/version.c     2009-10-02 13:39:57.000000000 +0100
     3225@@ -581,6 +581,11 @@
     3226 #else
     3227        "-vertsplit",
     3228 #endif
     3229+#ifdef FEAT_VIMSHELL
     3230+       "+vimshell",
     3231+#else
     3232+       "-vimshell",
     3233+#endif
     3234 #ifdef FEAT_VIRTUALEDIT
     3235        "+virtualedit",
     3236 #else
     3237diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim.h ./src/vim.h
     3238--- ../vim72.orig/src/vim.h     2009-10-02 13:39:24.000000000 +0100
     3239+++ ./src/vim.h 2009-10-02 13:39:57.000000000 +0100
     3240@@ -396,6 +396,14 @@
     3241 
     3242 /*
     3243  * The characters and attributes cached for the screen.
     3244+ * VIM-Shell: the VIM-shell really needs more than one byte for the attributes.
     3245+ *            Despite of a single warning during compilation, it seems to work
     3246+ *            fine to simply change the type here.
     3247+ *            We use the sattr_T as follows:
     3248+ *            The lowest byte is handled the same as before, for rendering attributes.
     3249+ *            The remaining byte is split, the uppermost 4 bits for the active foreground
     3250+ *            color, and the lowermost 4 bits for the active background color (at this
     3251+ *            screen position).
     3252  */
     3253 typedef char_u schar_T;
     3254 #ifdef FEAT_SYN_HL
     3255@@ -2054,6 +2062,10 @@
     3256 # include <XSUB.h>
     3257 #endif
     3258 
     3259+#ifdef FEAT_VIMSHELL
     3260+#include "vim_shell.h"
     3261+#endif
     3262+
     3263 /* values for vim_handle_signal() that are not a signal */
     3264 #define SIGNAL_BLOCK   -1
     3265 #define SIGNAL_UNBLOCK  -2
     3266diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.c ./src/vim_shell.c
     3267--- ../vim72.orig/src/vim_shell.c       1970-01-01 01:00:00.000000000 +0100
     3268+++ ./src/vim_shell.c   2009-10-02 13:39:57.000000000 +0100
     3269@@ -0,0 +1,926 @@
     3270+/*
     3271+ * vim_shell.c
     3272+ *
     3273+ * This is the interface layer of the VIM-Shell. VIM only calls functions from this module,
     3274+ * e.g. create a new VIM-Shell, read characters from the shell or write characters to the
     3275+ * shell. The respective functions pass these things down to the terminal layer, implemented
     3276+ * in terminal.c.
     3277+ *
     3278+ * This file is part of the VIM-Shell project. http://vimshell.wana.at
     3279+ *
     3280+ * Author: Thomas Wana <thomas@wana.at>
     3281+ *
     3282+ */
     3283+
     3284+
     3285+static char *RCSID="$Id$";
     3286+
     3287+#include "vim.h"
     3288+
     3289+#ifdef FEAT_VIMSHELL
     3290+#include <errno.h>
     3291+#include <stdlib.h>
     3292+#include <string.h>
     3293+#include <unistd.h>
     3294+#include <ctype.h>
     3295+#include <sys/types.h>
     3296+#include <sys/wait.h>
     3297+#include <signal.h>
     3298+#ifdef HAVE_PTY_H
     3299+#include <pty.h>
     3300+#endif
     3301+#ifdef HAVE_TERMIOS_H
     3302+#include <termios.h>
     3303+#endif
     3304+#ifdef HAVE_LIBUTIL_H
     3305+#include <libutil.h>
     3306+#endif
     3307+#include <fcntl.h>
     3308+
     3309+#if !defined(TIOCSWINSZ)
     3310+#  error "VIMSHELL: needs TIOCSWINSZ at the moment, not available on your system, sorry."
     3311+#endif
     3312+
     3313+#ifdef VIMSHELL_DEBUG
     3314+#  define CHILDDEBUG
     3315+#  define SIGDEBUG
     3316+#endif
     3317+
     3318+#ifdef CHILDDEBUG
     3319+#  define CHILDDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
     3320+#else
     3321+#  define CHILDDEBUGPRINTF(a...)
     3322+#endif
     3323+
     3324+#ifdef SIGDEBUG
     3325+#  define SIGDEBUGPRINTF(a...) if(vimshell_debug_fp) fprintf(vimshell_debug_fp, a)
     3326+#else
     3327+#  define SIGDEBUGPRINTF(a...)
     3328+#endif
     3329+
     3330+
     3331+int vimshell_errno;
     3332+
     3333+FILE *vimshell_debug_fp=NULL;
     3334+
     3335+/*
     3336+ * Main initialization function. Sets up global things always needed for the VIM shell.
     3337+ */
     3338+int vim_shell_init()
     3339+{
     3340+#ifdef VIMSHELL_DEBUG
     3341+       vimshell_debug_fp=fopen("vimshell.debug", "w");
     3342+#endif
     3343+
     3344+       /*
     3345+        * Everything went OK
     3346+        */
     3347+       return 0;
     3348+}
     3349+
     3350+/*
     3351+ * A routine that prints a buffer in 'hexdump -C'-style via printf
     3352+ */
     3353+static void hexdump(FILE *fp, unsigned char *buffer, long len)
     3354+{
     3355+       unsigned long pos=0;
     3356+
     3357+       while(len>0)
     3358+       {
     3359+               int i;
     3360+               fprintf(fp,"%08x  ",(unsigned int)pos);
     3361+               for(i=0;i<16 && i<len;i++)
     3362+               {
     3363+                       fprintf(fp,"%02x ",buffer[pos+i]);
     3364+                       if(i==7 || i==15)
     3365+                               fprintf(fp," ");
     3366+               }
     3367+               fprintf(fp,"|");
     3368+               for(i=0;i<16 && i<len;i++)
     3369+               {
     3370+                       unsigned char c=buffer[pos+i];
     3371+                       if(isprint(c))
     3372+                       {
     3373+                               fprintf(fp,"%c",c);
     3374+                       }
     3375+                       else
     3376+                       {
     3377+                               fprintf(fp,".");
     3378+                       }
     3379+               }
     3380+               fprintf(fp,"|\n");
     3381+               len-=16;
     3382+               pos+=16;
     3383+       }
     3384+}
     3385+
     3386+/*
     3387+ * Create a new window.
     3388+ * @return: pointer to a new struct vim_shell_window on success
     3389+ *          NULL on failure
     3390+ */
     3391+struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height)
     3392+{
     3393+       struct vim_shell_window *rval;
     3394+       int i;
     3395+
     3396+       rval=(struct vim_shell_window *)vim_shell_malloc(sizeof(struct vim_shell_window));
     3397+       if(rval==NULL)
     3398+       {
     3399+               vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
     3400+               return NULL;
     3401+       }
     3402+
     3403+       memset(rval, 0, sizeof(struct vim_shell_window));
     3404+
     3405+       rval->size_x=width;
     3406+       rval->size_y=height;
     3407+
     3408+       rval->fgcolor=VIMSHELL_COLOR_DEFAULT;
     3409+       rval->bgcolor=VIMSHELL_COLOR_DEFAULT;
     3410+
     3411+       rval->G0_charset='B';  // United States (USASCII)
     3412+       rval->G1_charset='0';  // Special graphics characters and line drawing set
     3413+       rval->active_charset=0;
     3414+
     3415+       rval->winbuf=(uint8_t *)vim_shell_malloc(width*height);
     3416+       rval->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
     3417+       rval->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
     3418+       rval->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
     3419+       rval->charset=(uint8_t *)vim_shell_malloc(width*height);
     3420+       rval->tabline=(uint8_t *)vim_shell_malloc(width);
     3421+       //rval->phys_screen=(uint32_t *)vim_shell_malloc(width*height*4);
     3422+       if(rval->winbuf==NULL || rval->fgbuf==NULL || rval->bgbuf==NULL || rval->rendbuf==NULL || rval->charset==NULL ||
     3423+                       rval->tabline==NULL /* || rval->phys_screen==NULL */)
     3424+       {
     3425+               vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
     3426+               // VIMSHELL TODO: cleanup, free the buffers that were successfully allocated
     3427+               vim_shell_free(rval);
     3428+               return NULL;
     3429+       }
     3430+       memset(rval->winbuf, ' ', width*height);
     3431+       memset(rval->fgbuf, rval->fgcolor, width*height);
     3432+       memset(rval->bgbuf, rval->bgcolor, width*height);
     3433+       memset(rval->rendbuf, 0, width*height);
     3434+       memset(rval->charset, 0, width*height);
     3435+       memset(rval->tabline, 0, width);
     3436+
     3437+#if 0
     3438+       for(i=0;i<width*height;i++)
     3439+       {
     3440+               /*
     3441+                * This is: default foreground, default background, no rendering attributes, ' ' as character
     3442+                */
     3443+               rval->phys_screen[i]=0x09090020;
     3444+       }
     3445+#endif
     3446+
     3447+       /*
     3448+        * Set a tab every 8 columns (default)
     3449+        */
     3450+       for(i=1;i<width;i++)
     3451+       {
     3452+               if((i+1)%8==0 && i+1<width)
     3453+                       rval->tabline[i]=1;
     3454+       }
     3455+
     3456+       rval->wraparound=1;
     3457+
     3458+       rval->cursor_x=0;
     3459+       rval->cursor_y=0;
     3460+       rval->cursor_visible=1;
     3461+
     3462+       rval->scroll_top_margin=0;
     3463+       rval->scroll_bottom_margin=height-1;
     3464+
     3465+       CHILDDEBUGPRINTF("%s: vimshell created, width = %d, height = %d\n",
     3466+                       __FUNCTION__, width, height);
     3467+
     3468+       vimshell_errno=VIMSHELL_SUCCESS;
     3469+       return rval;
     3470+}
     3471+
     3472+/*
     3473+ * start the program in argv in the shell window.
     3474+ */
     3475+int vim_shell_start(struct vim_shell_window *shell, char *argv[])
     3476+{
     3477+       struct winsize winsize;
     3478+       struct termios termios;
     3479+
     3480+       memset(&termios, 0, sizeof(struct termios));
     3481+
     3482+       /*
     3483+        * Set terminal parameters.
     3484+        */
     3485+       termios.c_iflag=ICRNL;
     3486+       termios.c_oflag=ONLCR | OPOST;
     3487+       termios.c_cflag=CS8 | CREAD | HUPCL;
     3488+       termios.c_lflag=ECHO | ECHOE | ECHOK | ECHOKE | ISIG | ECHOCTL | ICANON;
     3489+       termios.c_cc[VMIN]=1;
     3490+       termios.c_cc[VTIME]=0;
     3491+       termios.c_cc[VINTR]=003;
     3492+       termios.c_cc[VQUIT]=034;
     3493+       termios.c_cc[VERASE]=0177;
     3494+       termios.c_cc[VKILL]=025;
     3495+       termios.c_cc[VEOF]=004;
     3496+       termios.c_cc[VSTART]=021;
     3497+       termios.c_cc[VSTOP]=023;
     3498+       termios.c_cc[VSUSP]=032;
     3499+
     3500+       winsize.ws_row=shell->size_y;
     3501+       winsize.ws_col=shell->size_x;
     3502+       winsize.ws_xpixel=0;
     3503+       winsize.ws_ypixel=0;
     3504+
     3505+       /*
     3506+        * allocate a pty, fork and exec the command
     3507+        */
     3508+       shell->pid=forkpty(&shell->fd_master, NULL, &termios, &winsize);
     3509+       if(shell->pid==0)
     3510+       {
     3511+               /*
     3512+                * child code
     3513+                */
     3514+               setenv("TERM", "screen", 1);
     3515+               if(execvp(*argv, argv)<0)
     3516+               {
     3517+                       vimshell_errno=VIMSHELL_EXECV_ERROR;
     3518+                       // VIMSHELL TODO close fds??
     3519+                       return -1;
     3520+               }
     3521+       }
     3522+       else if(shell->pid<0)
     3523+       {
     3524+               vimshell_errno=VIMSHELL_FORKPTY_ERROR;
     3525+               return -1;
     3526+       }
     3527+
     3528+       /*
     3529+        * Set the file descriptor to non-blocking
     3530+        */
     3531+       if(fcntl(shell->fd_master, F_SETFL, fcntl(shell->fd_master, F_GETFL) | O_NONBLOCK)<0)
     3532+       {
     3533+               vimshell_errno=VIMSHELL_FCNTL_ERROR;
     3534+               return -1;
     3535+       }
     3536+
     3537+       /*
     3538+        * parent code
     3539+        */
     3540+       if(ioctl(shell->fd_master, TIOCSWINSZ, &winsize)<0)
     3541+       {
     3542+               CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
     3543+                               __FUNCTION__,strerror(errno));
     3544+       }
     3545+
     3546+       return 0;
     3547+}
     3548+
     3549+/*
     3550+ * this is much like strerror, only with vimshell_errno. Additionally, if errno is not
     3551+ * null, the formatted error message (strerror) will be appended to the output.
     3552+ */
     3553+char *vim_shell_strerror()
     3554+{
     3555+       static char errbuf[200];
     3556+       static char *errmsg[]={"Success",
     3557+               "Out of memory",
     3558+               "forkpty error",
     3559+               "read error",
     3560+               "write error",
     3561+               "execv error",
     3562+               "sigaction error",
     3563+               "read (EOF)",
     3564+               "fcntl error"};
     3565+
     3566+       if(errno==0)
     3567+               return errmsg[vimshell_errno];
     3568+
     3569+       snprintf(errbuf, sizeof(errbuf), "%s: %s", errmsg[vimshell_errno], strerror(errno));
     3570+       return errbuf;
     3571+}
     3572+
     3573+/*
     3574+ * Read what is available from the master pty and tear it through the
     3575+ * terminal emulation. This will fill the window buffer.
     3576+ */
     3577+int vim_shell_read(struct vim_shell_window *shell)
     3578+{
     3579+       // for now, copy what we have into the window buffer.
     3580+       char input[2000];
     3581+       int rval;
     3582+
     3583+retry:
     3584+       if((rval=read(shell->fd_master, input, sizeof(input)))<0)
     3585+       {
     3586+               if(errno==EINTR)
     3587+                       goto retry;
     3588+               if(errno==EAGAIN)
     3589+               {
     3590+                       /*
     3591+                        * This function should only be called when there really
     3592+                        * are bytes available to read from the fd_master. This
     3593+                        * is ensured by calling select() before this function.
     3594+                        * But it seems that there is a race with a SIGWINSZ right
     3595+                        * in the middle of a select() (reporting there are characters
     3596+                        * available) and the following read() that will block forever.
     3597+                        * It seems that SIGWINSZ flushes the processes input queue, at
     3598+                        * least on Linux.
     3599+                        *
     3600+                        * So if we get here although there is nothing to read, don't
     3601+                        * report an error, just return successfully.
     3602+                        */
     3603+                       goto success;
     3604+               }
     3605+
     3606+               vimshell_errno=VIMSHELL_READ_ERROR;
     3607+               return -1;
     3608+       }
     3609+
     3610+       if(rval==0)
     3611+       {
     3612+               /*
     3613+                * This means end-of-file, the subprocess exited.
     3614+                */
     3615+               vimshell_errno=VIMSHELL_READ_EOF;
     3616+               return -1;
     3617+       }
     3618+
     3619+#ifdef RAWDEBUG
     3620+       fprintf(vimshell_debug_fp, "\nincoming bytes:\n");
     3621+       hexdump(vimshell_debug_fp, input, rval);
     3622+#endif
     3623+
     3624+       /*
     3625+        * Interface to the terminal layer: give the input buffer to the
     3626+        * terminal emulator for processing.
     3627+        */
     3628+       vim_shell_terminal_input(shell, input, rval);
     3629+
     3630+success:
     3631+       vimshell_errno=VIMSHELL_SUCCESS;
     3632+       return 0;
     3633+}
     3634+
     3635+/*
     3636+ * Write a character to the VIM-Shell.
     3637+ * Blow it through terminal_output so it gets translated correctly etc...
     3638+ */
     3639+int vim_shell_write(struct vim_shell_window *shell, int c)
     3640+{
     3641+       if(vim_shell_terminal_output(shell, c)<0)
     3642+       {
     3643+               vimshell_errno=VIMSHELL_WRITE_ERROR;
     3644+               return -1;
     3645+       }
     3646+
     3647+       vimshell_errno=VIMSHELL_SUCCESS;
     3648+       return 0;
     3649+}
     3650+
     3651+/*
     3652+ * Free everything that is associated with this shell window.
     3653+ * Also terminates the process. The shell pointer will be set to NULL.
     3654+ * The buffer will be restored to a usable, empty buffer.
     3655+ */
     3656+void vim_shell_delete(buf_T *buf)
     3657+{
     3658+       struct vim_shell_window *sh=buf->shell;
     3659+       int status;
     3660+       pid_t pid;
     3661+
     3662+       /*
     3663+        * First, kill the child and wait for it.
     3664+        * VIMSHELL TODO: this can be extended a lot. e.g. using a SIGCHLD handler
     3665+        * or an SIGALRM handler and kill(SIGKILL) the process when the alarm fires
     3666+        * etc. But for now (and most of all cases) this should be OK.
     3667+        */
     3668+       pid=sh->pid;
     3669+       if(pid>0)
     3670+       {
     3671+               kill(pid, SIGTERM);
     3672+               kill(pid, SIGHUP);
     3673+               while(waitpid(pid, &status, 0)<0 && errno==EINTR);
     3674+               CHILDDEBUGPRINTF( "%s: PID %u terminated, exit status = %d\n", __FUNCTION__, pid,
     3675+                       WEXITSTATUS(status));
     3676+       }
     3677+
     3678+       /*
     3679+        * The child is dead. Clean up
     3680+        */
     3681+       close(sh->fd_master);
     3682+       if(sh->alt)
     3683+       {
     3684+               vim_shell_free(sh->alt->winbuf);
     3685+               vim_shell_free(sh->alt->fgbuf);
     3686+               vim_shell_free(sh->alt->bgbuf);
     3687+               vim_shell_free(sh->alt->rendbuf);
     3688+               vim_shell_free(sh->alt->tabline);
     3689+               vim_shell_free(sh->alt->charset);
     3690+               vim_shell_free(sh->alt);
     3691+               sh->alt=NULL;
     3692+       }
     3693+       vim_shell_free(sh->winbuf);
     3694+       vim_shell_free(sh->fgbuf);
     3695+       vim_shell_free(sh->bgbuf);
     3696+       vim_shell_free(sh->rendbuf);
     3697+       vim_shell_free(sh->tabline);
     3698+       vim_shell_free(sh->charset);
     3699+       vim_shell_free(sh);
     3700+
     3701+       CHILDDEBUGPRINTF( "%s: vimshell %p freed.\n", __FUNCTION__, sh);
     3702+
     3703+       buf->is_shell=0;
     3704+       buf->shell=NULL;
     3705+       buf->b_p_ro=FALSE;
     3706+}
     3707+
     3708+/*
     3709+ * Does the work of actually resizing the shell's buffers. Deallocating them,
     3710+ * reallocating them, copying over the old contents to the right places, etc...
     3711+ * rval: 0 = success, <0 = error
     3712+ */
     3713+static int internal_screenbuf_resize(struct vim_shell_window *shell, int width, int height)
     3714+{
     3715+       uint8_t *owinbuf, *ofgbuf, *obgbuf, *orendbuf, *otabline, *ocharset;
     3716+       int x, y, len, vlen;
     3717+       uint16_t oldwidth, oldheight;
     3718+
     3719+       oldwidth=shell->size_x;
     3720+       oldheight=shell->size_y;
     3721+       shell->size_x=(uint16_t)width;
     3722+       shell->size_y=(uint16_t)height;
     3723+
     3724+       owinbuf=shell->winbuf;
     3725+       ofgbuf=shell->fgbuf;
     3726+       obgbuf=shell->bgbuf;
     3727+       orendbuf=shell->rendbuf;
     3728+       ocharset=shell->charset;
     3729+       otabline=shell->tabline;
     3730+
     3731+       shell->winbuf=(uint8_t *)vim_shell_malloc(width*height);
     3732+       shell->fgbuf=(uint8_t *)vim_shell_malloc(width*height);
     3733+       shell->bgbuf=(uint8_t *)vim_shell_malloc(width*height);
     3734+       shell->rendbuf=(uint8_t *)vim_shell_malloc(width*height);
     3735+       shell->charset=(uint8_t *)vim_shell_malloc(width*height);
     3736+       shell->tabline=(uint8_t *)vim_shell_malloc(width);
     3737+       if(shell->winbuf==NULL || shell->fgbuf==NULL || shell->bgbuf==NULL || shell->rendbuf==NULL || shell->charset==NULL ||
     3738+                       shell->tabline==NULL)
     3739+       {
     3740+               vimshell_errno=VIMSHELL_OUT_OF_MEMORY;
     3741+               if(shell->winbuf) vim_shell_free(shell->winbuf);
     3742+               if(shell->fgbuf) vim_shell_free(shell->fgbuf);
     3743+               if(shell->bgbuf) vim_shell_free(shell->bgbuf);
     3744+               if(shell->rendbuf) vim_shell_free(shell->rendbuf);
     3745+               if(shell->charset) vim_shell_free(shell->charset);
     3746+               if(shell->tabline) vim_shell_free(shell->tabline);
     3747+
     3748+               /*
     3749+                * Reassign the old buffers, they are still valid. And bring the shell
     3750+                * back to a sane state.
     3751+                */
     3752+               shell->winbuf=owinbuf;
     3753+               shell->fgbuf=ofgbuf;
     3754+               shell->bgbuf=obgbuf;
     3755+               shell->rendbuf=orendbuf;
     3756+               shell->charset=ocharset;
     3757+               shell->tabline=otabline;
     3758+
     3759+               shell->size_x=oldwidth;
     3760+               shell->size_y=oldheight;
     3761+
     3762+               return -1;
     3763+       }
     3764+       memset(shell->winbuf, ' ', width*height);
     3765+       memset(shell->fgbuf, shell->fgcolor, width*height);
     3766+       memset(shell->bgbuf, shell->bgcolor, width*height);
     3767+       memset(shell->rendbuf, 0, width*height);
     3768+       memset(shell->charset, 0, width*height);
     3769+       memset(shell->tabline, 0, width);
     3770+
     3771+       CHILDDEBUGPRINTF( "%s: width = %d, height = %d, oldwidth = %d, oldheight = %d\n",__FUNCTION__,width,height,
     3772+                       oldwidth,oldheight);
     3773+
     3774+       /*
     3775+        * copy over the old contents of the screen, line by line (!)
     3776+        */
     3777+       len=(oldwidth<width ? oldwidth : width);
     3778+       vlen=(oldheight<height ? oldheight : height);
     3779+       for(y=0;y<vlen;y++)
     3780+       {
     3781+               int y_off;
     3782+               y_off=oldheight-vlen;
     3783+               memcpy(shell->winbuf+y*width, owinbuf+(y+y_off)*oldwidth, len);
     3784+               memcpy(shell->fgbuf+y*width, ofgbuf+(y+y_off)*oldwidth, len);
     3785+               memcpy(shell->bgbuf+y*width, obgbuf+(y+y_off)*oldwidth, len);
     3786+               memcpy(shell->rendbuf+y*width, orendbuf+(y+y_off)*oldwidth, len);
     3787+               memcpy(shell->charset+y*width, ocharset+(y+y_off)*oldwidth, len);
     3788+       }
     3789+       memcpy(shell->tabline, otabline, len);
     3790+
     3791+       /*
     3792+        * free the old contents
     3793+        */
     3794+       vim_shell_free(owinbuf);
     3795+       vim_shell_free(ofgbuf);
     3796+       vim_shell_free(obgbuf);
     3797+       vim_shell_free(orendbuf);
     3798+       vim_shell_free(otabline);
     3799+       vim_shell_free(ocharset);
     3800+
     3801+       /*
     3802+        * Correct tabs
     3803+        */
     3804+       if(oldwidth<width)
     3805+       {
     3806+               for(x=oldwidth;x<width;x++)
     3807+               {
     3808+                       if((x+1)%8==0 && x+1<width)
     3809+                               shell->tabline[x]=1;
     3810+               }
     3811+       }
     3812+
     3813+       /*
     3814+        * Correct cursor
     3815+        */
     3816+       if(shell->cursor_x>=shell->size_x)
     3817+               shell->cursor_x=shell->size_x-1;
     3818+       if(shell->cursor_y>=shell->size_y)
     3819+               shell->cursor_y=shell->size_y-1;
     3820+
     3821+       /*
     3822+        * Update scroll region
     3823+        */
     3824+       shell->scroll_top_margin=0;
     3825+       shell->scroll_bottom_margin=shell->size_y-1;
     3826+
     3827+       /*
     3828+        * Invalidate the vimshell screen buffer, so vim_shell_redraw redraws the whole
     3829+        * screen.
     3830+        */
     3831+       shell->force_redraw=1;
     3832+
     3833+       return 0;
     3834+}
     3835+
     3836+/*
     3837+ * Resizes the shell.
     3838+ * It reallocates all the size dependant buffers and instructs the shell to change
     3839+ * its size.
     3840+ * The width and height parameters are the *desired* width and height. The actual
     3841+ * width and height is dependant on wether all windows that currently render this shell
     3842+ * are able to display this width and height.
     3843+ */
     3844+void vim_shell_resize(struct vim_shell_window *shell, int want_width, int want_height)
     3845+{
     3846+       int width, height;
     3847+       struct winsize ws;
     3848+       win_T *win;
     3849+
     3850+       width=want_width;
     3851+       height=want_height;
     3852+       FOR_ALL_WINDOWS(win)
     3853+       {
     3854+               if(win->w_buffer && win->w_buffer->is_shell && win->w_buffer->shell==shell)
     3855+               {
     3856+                       if(win->w_width<width)
     3857+                               width=win->w_width;
     3858+                       if(win->w_height<height)
     3859+                               height=win->w_height;
     3860+               }
     3861+       }
     3862+
     3863+       CHILDDEBUGPRINTF( "%s: resizing to %d, %d\n",__FUNCTION__,width,height);
     3864+
     3865+       if(internal_screenbuf_resize(shell, width, height)<0)
     3866+       {
     3867+               CHILDDEBUGPRINTF("%s: error while resizing.\n", __FUNCTION__);
     3868+               return;
     3869+       }
     3870+       if(shell->alt!=NULL)
     3871+       {
     3872+               if(internal_screenbuf_resize(shell->alt, width, height)<0)
     3873+               {
     3874+                       CHILDDEBUGPRINTF("%s: error while resizing the backup screen. Recovering...\n", __FUNCTION__);
     3875+
     3876+                       /*
     3877+                        * We now really have a problem. The main shell window is already
     3878+                        * resized and this one didn't work. What should we do? Just destroy the screen
     3879+                        * backup so it never gets restored. internal_screenbuf_resize already did
     3880+                        * the job to of freeing the SINGle buffers, we just have to free the remaining struct.
     3881+                        */
     3882+                       vim_shell_free(shell->alt);
     3883+                       shell->alt=NULL;
     3884+               }
     3885+       }
     3886+
     3887+       /*
     3888+        * Tell the shell that the size has changed.
     3889+        */
     3890+       ws.ws_row=height;
     3891+       ws.ws_col=width;
     3892+       ws.ws_xpixel=0;
     3893+       ws.ws_ypixel=0;
     3894+       if(ioctl(shell->fd_master, TIOCSWINSZ, &ws)<0)
     3895+       {
     3896+               CHILDDEBUGPRINTF( "%s: ERROR: ioctl to change window size: %s\n",
     3897+                               __FUNCTION__,strerror(errno));
     3898+       }
     3899+}
     3900+
     3901+/*
     3902+ * Draws the Shell-Buffer into the VIM-Window.
     3903+ */
     3904+void vim_shell_redraw(struct vim_shell_window *shell, win_T *win)
     3905+{
     3906+       int x, y;
     3907+       int win_row, win_col;
     3908+       int off;
     3909+       int last_set_fg, last_set_bg;
     3910+       int cs_state;
     3911+       int term_is_bold, term_is_underline, term_is_negative;
     3912+       int saved_screen_cur_row, saved_screen_cur_col;
     3913+       int force_redraw;
     3914+       int using_gui=0;
     3915+       int t_colors_original=t_colors;
     3916+
     3917+       if(t_colors>15)
     3918+       {
     3919+               t_colors = 15;
     3920+       }
     3921+
     3922+#ifdef FEAT_GUI
     3923+       if(gui.in_use)
     3924+       {
     3925+               using_gui=1;
     3926+       }
     3927+#endif
     3928+
     3929+       win_row=W_WINROW(win);
     3930+       win_col=W_WINCOL(win);
     3931+
     3932+       force_redraw=shell->force_redraw;
     3933+
     3934+       // invalidate the color cache
     3935+       last_set_fg=last_set_bg=-1;
     3936+       cs_state=VIMSHELL_CHARSET_USASCII;
     3937+
     3938+       saved_screen_cur_row=screen_cur_row;
     3939+       saved_screen_cur_col=screen_cur_col;
     3940+
     3941+       // go to normal mode
     3942+       term_is_bold=term_is_underline=term_is_negative=0;
     3943+       screen_stop_highlight();
     3944+
     3945+       for(y=0;y<shell->size_y;y++)
     3946+       {
     3947+               size_t index=y*shell->size_x;
     3948+               int skipped, y_reposition_necessary;
     3949+
     3950+               off=LineOffset[win_row+y]+win_col;
     3951+               skipped=0;
     3952+               y_reposition_necessary=1;
     3953+               for(x=0;x<shell->size_x;x++)
     3954+               {
     3955+                       uint8_t c=shell->winbuf[index];
     3956+                       sattr_T r=(sattr_T)shell->rendbuf[index];
     3957+                       uint8_t fg=shell->fgbuf[index];
     3958+                       uint8_t bg=shell->bgbuf[index];
     3959+                       uint8_t cs=shell->charset[index];
     3960+                       uint8_t fg_color=fg&0xF;
     3961+                       uint8_t bg_color=bg&0xF;
     3962+                       if(t_colors > 15)
     3963+                       {
     3964+                               bg_color=0x00;
     3965+                               fg_color=0x03;
     3966+                       }
     3967+
     3968+                       /*
     3969+                        * Switch terminal charset if necessary
     3970+                        */
     3971+                       if(cs_state!=cs)
     3972+                       {
     3973+                               cs_state=cs;
     3974+                               if(cs==VIMSHELL_CHARSET_USASCII)
     3975+                               {
     3976+                                       // VIMSHELL TODO: make a term code out of this hack
     3977+                                       out_str_nf("\033(B");
     3978+                                       CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
     3979+                               }
     3980+                               else if(cs==VIMSHELL_CHARSET_DRAWING)
     3981+                               {
     3982+                                       // VIMSHELL TODO: make a term code out of this hack
     3983+                                       out_str_nf("\033(0");
     3984+                                       CHILDDEBUGPRINTF( "%s: switched terminal to alternate charset\n",__FUNCTION__);
     3985+                               }
     3986+                       }
     3987+
     3988+                       /*
     3989+                        * Store the foreground and background color along with the rendering attributes.
     3990+                        */
     3991+                       r |= (fg&0x0F)<<12 | (bg&0x0F)<<8;
     3992+
     3993+                       /*
     3994+                        * Only do an update if render attributes or the character
     3995+                        * has changed at this position.
     3996+                        */
     3997+                       if(ScreenLines[off]!=c || ScreenAttrs[off]!=r || force_redraw)
     3998+                       {
     3999+                               // render attributes
     4000+                               if( ((r & RENDITION_BOLD)==0) == (term_is_bold==0) &&
     4001+                                               ((r & RENDITION_UNDERSCORE)==0) == (term_is_underline==0) &&
     4002+                                               ((r & RENDITION_NEGATIVE)==0) == (term_is_negative==0))
     4003+                               {
     4004+                                       /*
     4005+                                        * already in the right rendition mode ...
     4006+                                        */
     4007+                               }
     4008+                               else if(using_gui==0)
     4009+                               {
     4010+                                       out_str_nf(T_ME);
     4011+                                       term_is_bold=term_is_underline=term_is_negative=0;
     4012+                                       last_set_fg=last_set_bg=-1;
     4013+                                       if ((r & RENDITION_BOLD) && !term_is_bold)
     4014+                                       {
     4015+                                               if(T_MD!=NULL)
     4016+                                                       out_str_nf(T_MD);
     4017+                                               term_is_bold=1;
     4018+                                       }
     4019+                                       if ((r & RENDITION_UNDERSCORE) && !term_is_underline)
     4020+                                       {
     4021+                                               if(T_US != NULL)
     4022+                                                       out_str_nf(T_US);
     4023+                                               term_is_underline=1;
     4024+                                       }
     4025+                                       if ((r & RENDITION_NEGATIVE) && !term_is_negative)
     4026+                                       {
     4027+                                               if(T_MR!=NULL)
     4028+                                                       out_str_nf(T_MR);
     4029+                                               term_is_negative=1;
     4030+                                       }
     4031+                               }
     4032+
     4033+                               // colors
     4034+                               if(t_colors > 1 && using_gui==0)
     4035+                               {
     4036+                                       // VIMSHELL TODO: not every terminal will understand these colors ...
     4037+                                       // look at tag:cterm_normal_fg_color
     4038+                                       if(last_set_fg!=fg_color)
     4039+                                       {
     4040+                                               term_fg_color(fg_color);
     4041+                                               last_set_fg=fg_color;
     4042+                                       }
     4043+                                       if(last_set_bg!=bg_color)
     4044+                                       {
     4045+                                               term_bg_color(bg_color);
     4046+                                               last_set_bg=bg_color;
     4047+                                       }
     4048+                               }
     4049+
     4050+                               ScreenLines[off]=c;
     4051+                               ScreenAttrs[off]=r;
     4052+
     4053+                               if(y_reposition_necessary || skipped>0)
     4054+                               {
     4055+                                       /*
     4056+                                        * Bring the cursor to where we need it.
     4057+                                        */
     4058+                                       term_windgoto(win_row+y, win_col+x);
     4059+                                       skipped=0;
     4060+                                       y_reposition_necessary=0;
     4061+                               }
     4062+
     4063+                               // print it
     4064+                               out_char(c);
     4065+                       }
     4066+                       else
     4067+                       {
     4068+                               skipped++;
     4069+                       }
     4070+
     4071+                       off++;
     4072+                       index++;
     4073+               }
     4074+       }
     4075+       /*
     4076+        * Always leave this function with the normal ASCII charset enabled and
     4077+        * with sane rendering attributes (normal mode).
     4078+        */
     4079+       if(cs_state!=VIMSHELL_CHARSET_USASCII)
     4080+       {
     4081+               // VIMSHELL TODO: make a term code out of this hack
     4082+               out_str_nf("\033(B");
     4083+               CHILDDEBUGPRINTF( "%s: switched terminal to normal charset\n",__FUNCTION__);
     4084+       }
     4085+
     4086+       /*
     4087+        * Move the cursor to where VIM thinks it is :)
     4088+        */
     4089+       term_windgoto(saved_screen_cur_row, saved_screen_cur_col);
     4090+
     4091+       /*
     4092+        * Position the cursor.
     4093+        * VIMSHELL TODO: we could cache that, e.g. when the cursor didn't move don't turn
     4094+        * it on again etc.
     4095+        */
     4096+       win->w_wrow=shell->cursor_y;
     4097+       win->w_wcol=shell->cursor_x;
     4098+       setcursor();
     4099+       cursor_on();
     4100+
     4101+       /*
     4102+        * Restore the rendering attributes
     4103+        */
     4104+       out_str_nf(T_ME);
     4105+       screen_start_highlight(screen_attr);
     4106+       out_flush();
     4107+
     4108+       if(shell->force_redraw)
     4109+               shell->force_redraw=0;
     4110+
     4111+       t_colors = t_colors_original;
     4112+}
     4113+
     4114+/*
     4115+ * Really do the read, finally :)
     4116+ * Returns 1 if the contents of the window are VALID (in VIM speak)
     4117+ * Returns 2 if the contents have to be CLEARed (after the shell has died)
     4118+ */
     4119+int vim_shell_do_read_lowlevel(buf_T *buf)
     4120+{
     4121+       int rval=1;
     4122+       if(vim_shell_read(buf->shell)<0)
     4123+       {
     4124+               /*
     4125+                * Shell died? Cleanup. Also remove the RO attribute from the
     4126+                * buffer.
     4127+                */
     4128+               vim_shell_delete(buf);
     4129+               rval=2;
     4130+       }
     4131+
     4132+       return rval;
     4133+}
     4134+
     4135+/*
     4136+ * This function is called from two places: os_unix.c and ui.c, and handles
     4137+ * shell reads that are necessary because a select() became ready. This function
     4138+ * is here to avoid identical code in both places.
     4139+ * It returns the number of shell-reads.
     4140+ * If there was no activity in any of the shells, it returns 0.
     4141+ */
     4142+int vim_shell_do_read_select(fd_set rfds)
     4143+{
     4144+       /*
     4145+        * Loop through all buffers and see if they are vimshells.
     4146+        * If yes, check if there are read events ready for the appropriate
     4147+        * fds. If so, call the shell's read handler.
     4148+        */
     4149+       buf_T *buf;
     4150+       int did_redraw=0;
     4151+       int rval=0;
     4152+
     4153+       for(buf=firstbuf;buf!=NULL;buf=buf->b_next)
     4154+       {
     4155+               if(buf->is_shell != 0)
     4156+               {
     4157+                       if(FD_ISSET(buf->shell->fd_master, &rfds))
     4158+                       {
     4159+                               int r;
     4160+
     4161+                               r=vim_shell_do_read_lowlevel(buf);
     4162+                               if(r>did_redraw)
     4163+                                       did_redraw=r;
     4164+
     4165+                               rval++;
     4166+
     4167+                               if(r==1 && updating_screen==FALSE)
     4168+                                       redraw_buf_later(buf, VALID);
     4169+                               else if(r==2 && updating_screen==FALSE)
     4170+                                       redraw_buf_later(buf, CLEAR);
     4171+                       }
     4172+               }
     4173+       }
     4174+
     4175+       /*
     4176+        * Only redraw if we aren't currently redrawing, to avoid endless recursions.
     4177+        * update_screen calls win_update, which calls win_line, which calls breakcheck,
     4178+        * which again calls RealWaitForChar which calls this function ...
     4179+        */
     4180+       if(updating_screen==FALSE)
     4181+       {
     4182+               if(did_redraw==1)
     4183+               {
     4184+                       update_screen(VALID);
     4185+               }
     4186+               else if(did_redraw==2 || did_redraw==3)
     4187+               {
     4188+                       update_screen(CLEAR);
     4189+                       out_flush();
     4190+               }
     4191+       }
     4192+
     4193+       return rval;
     4194+}
     4195+#endif
     4196diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/vim_shell.h ./src/vim_shell.h
     4197--- ../vim72.orig/src/vim_shell.h       1970-01-01 01:00:00.000000000 +0100
     4198+++ ./src/vim_shell.h   2009-10-02 13:39:57.000000000 +0100
     4199@@ -0,0 +1,273 @@
     4200+/*
     4201+ * vim_shell.h
     4202+ *
     4203+ * Global include file for VIM-Shell. Defines structures and interfaces.
     4204+ *
     4205+ * This file is part of the VIM-Shell project. http://vimshell.wana.at
     4206+ *
     4207+ * Author: Thomas Wana <thomas@wana.at>
     4208+ *
     4209+ * $Id$
     4210+ */
     4211+
     4212+#ifndef __VIMSHELL_H
     4213+
     4214+#define __VIMSHELL_H
     4215+
     4216+#include "vim.h"
     4217+
     4218+#include <stdio.h>
     4219+#ifdef HAVE_STDINT_H
     4220+#include <stdint.h>
     4221+#endif
     4222+#include <sys/types.h>
     4223+#include <sys/select.h>
     4224+
     4225+/*
     4226+ * Master debug flag. Disable this and no debug messages at all will
     4227+ * be written anywhere.
     4228+ */
     4229+//#define VIMSHELL_DEBUG
     4230+
     4231+/*
     4232+ * Rendition constants
     4233+ */
     4234+#define RENDITION_BOLD 1
     4235+#define RENDITION_UNDERSCORE 2
     4236+#define RENDITION_BLINK 4
     4237+#define RENDITION_NEGATIVE 8
     4238+#define RENDITION_DIM 16
     4239+#define RENDITION_HIDDEN 32
     4240+
     4241+/*
     4242+ * charset constants
     4243+ */
     4244+#define VIMSHELL_CHARSET_USASCII 0
     4245+#define VIMSHELL_CHARSET_DRAWING 1
     4246+
     4247+/*
     4248+ * Color constants
     4249+ */
     4250+#define VIMSHELL_COLOR_BLACK 0
     4251+#define VIMSHELL_COLOR_RED 1
     4252+#define VIMSHELL_COLOR_GREEN 2
     4253+#define VIMSHELL_COLOR_YELLOW 3
     4254+#define VIMSHELL_COLOR_BLUE 4
     4255+#define VIMSHELL_COLOR_MAGENTA 5
     4256+#define VIMSHELL_COLOR_CYAN 6
     4257+#define VIMSHELL_COLOR_WHITE 7
     4258+#define VIMSHELL_COLOR_DEFAULT 9
     4259+
     4260+#define vim_shell_malloc alloc
     4261+#define vim_shell_free vim_free
     4262+
     4263+/*
     4264+ * The main vim_shell_window struct.
     4265+ * Holds everything that is needed to know about a single
     4266+ * vim shell. (like file descriptors, window buffers, window
     4267+ * positions, etc)
     4268+ */
     4269+struct vim_shell_window
     4270+{
     4271+       /*
     4272+        * current dimensions of the window
     4273+        */
     4274+       uint16_t size_x;
     4275+       uint16_t size_y;
     4276+
     4277+       /*
     4278+        * cursor position and visible flag
     4279+        */
     4280+       uint16_t cursor_x;
     4281+       uint16_t cursor_y;
     4282+       uint16_t cursor_visible;
     4283+
     4284+       /*
     4285+        * Saved cursor positions (ESC 7, ESC 8)
     4286+        */
     4287+       uint16_t saved_cursor_x;
     4288+       uint16_t saved_cursor_y;
     4289+
     4290+       /*
     4291+        * We support the xterm title hack and store the title in this buffer.
     4292+        */
     4293+       char windowtitle[50];
     4294+
     4295+       /*
     4296+        * The output buffer. This is necessary because writes to the shell can be delayed,
     4297+        * e.g. if we are waiting for an incoming ESC sequence to complete.
     4298+        */
     4299+       uint8_t outbuf[100];
     4300+       uint8_t outbuf_pos;
     4301+
     4302+       /*
     4303+        * Pointer to the window buffer.
     4304+        * The window buffer is the internal representation of the
     4305+        * window's content. The vim shell receives characters from
     4306+        * the terminal, which the terminal emulation translates into
     4307+        * e.g. cursor positions or actual characters. These are placed
     4308+        * here at the right screen position. Its size is size_y*size_x.
     4309+        */
     4310+       uint8_t *winbuf;
     4311+       uint8_t *fgbuf;
     4312+       uint8_t *bgbuf;
     4313+       uint8_t *rendbuf;
     4314+       uint8_t *charset;
     4315+
     4316+       /*
     4317+        * The tabulator line. It represents a single row. Zero means no
     4318+        * tab at this position, 1 means there is a tab.
     4319+        */
     4320+       uint8_t *tabline;
     4321+
     4322+       /*
     4323+        * These buffers hold what's currently physical on the screen.
     4324+        * Note, not on the "virtual" screen, that is the image of the shell,
     4325+        * but the real screen that is printed out in vim_shell_redraw.
     4326+        * This is mainly to implement caching features...
     4327+        * We hold here:
     4328+        * 1 byte foreground-color
     4329+        * 1 byte background-color
     4330+        * 1 byte rendering attributes
     4331+        * 1 byte the actual character
     4332+        */
     4333+       uint32_t *phys_screen;
     4334+
     4335+       /*
     4336+        * Flag that determines if we are right in the middle of an
     4337+        * escape sequence coming in.
     4338+        */
     4339+       uint8_t in_esc_sequence;
     4340+
     4341+       /*
     4342+        * Buffer for a escape sequence in progress (see in_esc_sequence).
     4343+        */
     4344+       uint8_t esc_sequence[50];
     4345+
     4346+       /*
     4347+        * Auto-Margin enabled?
     4348+        */
     4349+       uint8_t wraparound;
     4350+
     4351+       /*
     4352+        * Caused the last character a warp around?
     4353+        */
     4354+       uint8_t just_wrapped_around;
     4355+
     4356+       /*
     4357+        * The currently used rendition of the shell.
     4358+        */
     4359+       uint8_t rendition;
     4360+       uint8_t saved_rendition;
     4361+
     4362+       /*
     4363+        * The currently active colors.
     4364+        */
     4365+       uint8_t fgcolor;
     4366+       uint8_t bgcolor;
     4367+       uint8_t saved_fgcolor;
     4368+       uint8_t saved_bgcolor;
     4369+
     4370+       /*
     4371+        * Scroll region.
     4372+        */
     4373+       uint8_t scroll_top_margin;
     4374+       uint8_t scroll_bottom_margin;
     4375+
     4376+       /*
     4377+        * Charset configuration.
     4378+        */
     4379+       uint8_t G0_charset;
     4380+       uint8_t G1_charset;
     4381+       uint8_t active_charset;
     4382+       uint8_t saved_G0_charset;
     4383+       uint8_t saved_G1_charset;
     4384+       uint8_t saved_active_charset;
     4385+
     4386+       /*
     4387+        * Mode switches.
     4388+        */
     4389+       uint8_t application_keypad_mode;
     4390+       uint8_t application_cursor_mode;
     4391+       uint8_t saved_application_keypad_mode;
     4392+       uint8_t saved_application_cursor_mode;
     4393+
     4394+       uint8_t insert_mode;
     4395+       uint8_t saved_insert_mode;
     4396+
     4397+       /*
     4398+        * This flag determines if the shell should be completely redrawn in the next
     4399+        * vim_shell_redraw, regardless of what we think to know about the screen.
     4400+        */
     4401+       uint8_t force_redraw;
     4402+
     4403+       /*
     4404+        * Pointer to the alternate screen. If NULL, there is no alternate screen.
     4405+        * If not NULL, this holds a backup of the screen contents and properties
     4406+        * before the screen switch. Switching back means to copy back the contents
     4407+        * of the alternate screen to the main screen and freeing the alternate screen.
     4408+        */
     4409+       struct vim_shell_window *alt;
     4410+
     4411+       /*
     4412+        * file descriptor of the master side of the pty
     4413+        */
     4414+       int fd_master;
     4415+
     4416+       /*
     4417+        * pid of the subshell
     4418+        */
     4419+       pid_t pid;
     4420+
     4421+};
     4422+
     4423+/*
     4424+ * This is set when something goes wrong in one of the
     4425+ * vim_shell functions.
     4426+ */
     4427+extern int vimshell_errno;
     4428+
     4429+/*
     4430+ * The debug handle where debug-messages will be written
     4431+ */
     4432+extern FILE *vimshell_debug_fp;
     4433+
     4434+#define VIMSHELL_SUCCESS 0
     4435+#define VIMSHELL_OUT_OF_MEMORY 1
     4436+#define VIMSHELL_FORKPTY_ERROR 2
     4437+#define VIMSHELL_READ_ERROR 3
     4438+#define VIMSHELL_WRITE_ERROR 4
     4439+#define VIMSHELL_EXECV_ERROR 5
     4440+#define VIMSHELL_SIGACTION_ERROR 6
     4441+#define VIMSHELL_READ_EOF 7
     4442+#define VIMSHELL_FCNTL_ERROR 8
     4443+
     4444+/*
     4445+ * vim_shell.c
     4446+ */
     4447+extern int vim_shell_init();
     4448+extern struct vim_shell_window *vim_shell_new(uint16_t width, uint16_t height);
     4449+extern int vim_shell_start(struct vim_shell_window *shell, char *argv[]);
     4450+extern char *vim_shell_strerror();
     4451+extern int vim_shell_read(struct vim_shell_window *shell);
     4452+extern int vim_shell_write(struct vim_shell_window *shell, int c);
     4453+extern void vim_shell_redraw(struct vim_shell_window *shell, win_T *win);
     4454+extern int vim_shell_do_read_select(fd_set rfds);
     4455+extern int vim_shell_do_read_lowlevel(buf_T *buf);
     4456+extern void vim_shell_delete(buf_T *buf);
     4457+extern void vim_shell_resize(struct vim_shell_window *shell, int width, int height);
     4458+
     4459+/*
     4460+ * terminal.c
     4461+ */
     4462+extern void vim_shell_terminal_input(struct vim_shell_window *shell, char *input, int len);
     4463+extern int vim_shell_terminal_output(struct vim_shell_window *shell, int c);
     4464+
     4465+/*
     4466+ * screen.c
     4467+ */
     4468+extern int screen_cur_row, screen_cur_col;     /* last known cursor position */
     4469+extern void screen_start_highlight __ARGS((int attr));
     4470+extern int screen_attr;
     4471+
     4472+#endif
     4473diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/src/window.c ./src/window.c
     4474--- ../vim72.orig/src/window.c  2009-10-02 13:39:25.000000000 +0100
     4475+++ ./src/window.c      2009-10-02 13:39:57.000000000 +0100
     4476@@ -119,6 +119,12 @@
     4477 # define CHECK_CMDWIN
     4478 #endif
     4479 
     4480+#ifdef FEAT_VIMSHELL
     4481+# define CHECK_VIMSHELL if (curwin->w_buffer->is_shell != 0) { EMSG("VIMSHELL: command not available for shell windows"); break; }
     4482+#else
     4483+# define CHECK_VIMSHELL
     4484+#endif
     4485+
     4486     switch (nchar)
     4487     {
     4488 /* split current window in two parts, horizontally */
     4489@@ -486,6 +492,7 @@
     4490 #if defined(FEAT_QUICKFIX)
     4491     case '}':
     4492                CHECK_CMDWIN
     4493+               CHECK_VIMSHELL
     4494                if (Prenum)
     4495                    g_do_tagpreview = Prenum;
     4496                else
     4497@@ -495,6 +502,7 @@
     4498     case ']':
     4499     case Ctrl_RSB:
     4500                CHECK_CMDWIN
     4501+               CHECK_VIMSHELL
     4502 #ifdef FEAT_VISUAL
     4503                reset_VIsual_and_resel();       /* stop Visual mode */
     4504 #endif
     4505@@ -515,6 +523,7 @@
     4506     case Ctrl_F:
     4507 wingotofile:
     4508                CHECK_CMDWIN
     4509+               CHECK_VIMSHELL
     4510 
     4511                ptr = grab_file_name(Prenum1, &lnum);
     4512                if (ptr != NULL)
     4513@@ -553,6 +562,7 @@
     4514     case 'd':                      /* Go to definition, using 'define' */
     4515     case Ctrl_D:
     4516                CHECK_CMDWIN
     4517+               CHECK_VIMSHELL
     4518                if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
     4519                    break;
     4520                find_pattern_in_path(ptr, 0, len, TRUE,
     4521@@ -584,6 +594,7 @@
     4522     case 'g':
     4523     case Ctrl_G:
     4524                CHECK_CMDWIN
     4525+               CHECK_VIMSHELL
     4526 #ifdef USE_ON_FLY_SCROLL
     4527                dont_scroll = TRUE;             /* disallow scrolling here */
     4528 #endif
     4529@@ -5555,6 +5566,15 @@
     4530     wp->w_redr_status = TRUE;
     4531 #endif
     4532     invalidate_botline_win(wp);
     4533+
     4534+#ifdef FEAT_VIMSHELL
     4535+    if(wp->w_buffer->is_shell!=0)
     4536+    {
     4537+       struct vim_shell_window *shell=wp->w_buffer->shell;
     4538+       vim_shell_resize(shell, shell->size_x, height);
     4539+       redraw_win_later(wp, CLEAR);
     4540+    }
     4541+#endif
     4542 }
     4543 
     4544 #ifdef FEAT_VERTSPLIT
     4545@@ -5577,6 +5597,14 @@
     4546     }
     4547     redraw_win_later(wp, NOT_VALID);
     4548     wp->w_redr_status = TRUE;
     4549+#ifdef FEAT_VIMSHELL
     4550+    if(wp->w_buffer->is_shell!=0)
     4551+    {
     4552+       struct vim_shell_window *shell=wp->w_buffer->shell;
     4553+       vim_shell_resize(shell, width, shell->size_y);
     4554+       redraw_win_later(wp, CLEAR);
     4555+    }
     4556+#endif
     4557 }
     4558 #endif
     4559 
     4560diff -uNr -x '*.orig' -x '*.rej' ../vim72.orig/test.txt ./test.txt
     4561--- ../vim72.orig/test.txt      1970-01-01 01:00:00.000000000 +0100
     4562+++ ./test.txt  2009-10-02 13:39:57.000000000 +0100
     4563@@ -0,0 +1,2 @@
     4564+asdfasdfA
     4565+:q
  • Portfile

     
    113113    configure.args-append --with-xim
    114114}
    115115
     116variant shell description {Enables shell windows} {
     117    patchfiles-append       patch-vimshell.diff
     118}
     119
    116120variant perl description {Enable Perl scripting} {
    117121    configure.args-append   --enable-perlinterp
    118122    depends_lib-append      path:bin/perl:perl5