Patch 8.1.1218
Problem:    Cannot set a directory for a tab page.
Solution:   Add the tab-local directory. (Yegappan Lakshmanan, closes #4212)
Files:      runtime/doc/autocmd.txt, runtime/doc/editing.txt,
            runtime/doc/eval.txt, runtime/doc/index.txt,
            runtime/doc/options.txt, runtime/doc/usr_22.txt,
            runtime/doc/usr_41.txt, src/eval.c, src/evalfunc.c,
            src/ex_cmdidxs.h, src/ex_cmds.h, src/ex_docmd.c, src/if_py_both.h,
            src/proto/eval.pro, src/proto/ex_docmd.pro, src/structs.h,
            src/testdir/test_getcwd.vim, src/testdir/test_mksession.vim,
            src/window.c


*** ../vim-8.1.1217/runtime/doc/autocmd.txt     2019-04-08 18:15:36.464223229 
+0200
--- runtime/doc/autocmd.txt     2019-04-27 20:06:26.758264881 +0200
***************
*** 686,704 ****
                                change or when doing |:diffupdate|.
                                                        *DirChanged*
  DirChanged                    The working directory has changed in response
!                               to the |:cd| or |:lcd| commands, or as a
!                               result of the 'autochdir' option.
                                The pattern can be:
!                                       "window" to trigger on `:lcd`
!                                       "global" to trigger on `:cd`
!                                       "auto"   to trigger on 'autochdir'.
!                                       "drop"   to trigger on editing a file
                                <afile> is set to the new directory name.
                                                        *ExitPre*
  ExitPre                               When using `:quit`, `:wq` in a way it 
makes
                                Vim exit, or using `:qall`, just after
                                |QuitPre|.  Can be used to close any
!                               non-essential window.
                                                        *FileChangedShell*
  FileChangedShell              When Vim notices that the modification time of
                                a file has changed since editing started.
--- 690,712 ----
                                change or when doing |:diffupdate|.
                                                        *DirChanged*
  DirChanged                    The working directory has changed in response
!                               to the |:cd| or |:tcd| or |:lcd| commands, or
!                               as a result of the 'autochdir' option.
                                The pattern can be:
!                                       "window"  to trigger on `:lcd`
!                                       "tabpage" to trigger on `:tcd`
!                                       "global"  to trigger on `:cd`
!                                       "auto"    to trigger on 'autochdir'.
!                                       "drop"    to trigger on editing a file
                                <afile> is set to the new directory name.
                                                        *ExitPre*
  ExitPre                               When using `:quit`, `:wq` in a way it 
makes
                                Vim exit, or using `:qall`, just after
                                |QuitPre|.  Can be used to close any
!                               non-essential window.  Exiting may still be
!                               cancelled if there is a modified buffer that
!                               isn't automatically saved, use |VimLeavePre|
!                               for really exiting.
                                                        *FileChangedShell*
  FileChangedShell              When Vim notices that the modification time of
                                a file has changed since editing started.
*** ../vim-8.1.1217/runtime/doc/editing.txt     2018-05-17 13:40:51.000000000 
+0200
--- runtime/doc/editing.txt     2019-04-27 20:11:37.192857657 +0200
***************
*** 1304,1312 ****
  ==============================================================================
  7. The current directory                              *current-directory*
  
! You may use the |:cd| and |:lcd| commands to change to another directory, so
! you will not have to type that directory name in front of the file names.  It
! also makes a difference for executing external commands, e.g. ":!ls".
  
  Changing directory fails when the current buffer is modified, the '.' flag is
  present in 'cpoptions' and "!" is not used in the command.
--- 1304,1313 ----
  ==============================================================================
  7. The current directory                              *current-directory*
  
! You can use the |:cd|, |:tcd| and |:lcd| commands to change to another
! directory, so you will not have to type that directory name in front of the
! file names.  It also makes a difference for executing external commands, e.g.
! ":!ls".
  
  Changing directory fails when the current buffer is modified, the '.' flag is
  present in 'cpoptions' and "!" is not used in the command.
***************
*** 1334,1339 ****
--- 1335,1351 ----
                                                        *:chd* *:chdir*
  :chd[ir][!] [path]    Same as |:cd|.
  
+                                                       *:tcd*
+ :tcd[!] {path}                Like |:cd|, but only set the directory for the 
current
+                       tab.  The current window will also use this directory.
+                       The current directory is not changed for windows in
+                       other tabs and for windows in the current tab that
+                       have their own window-local directory.
+                       {not in Vi}
+ 
+                                                       *:tch* *:tchdir*
+ :tch[dir][!]          Same as |:tcd|. {not in Vi}
+ 
                                                        *:lc* *:lcd*
  :lc[d][!] {path}      Like |:cd|, but only set the current directory when
                        the cursor is in the current window.  The current
***************
*** 1348,1364 ****
  :pw[d]                        Print the current directory name.  {Vi: no pwd}
                        Also see |getcwd()|.
  
! So long as no |:lcd| command has been used, all windows share the same current
! directory.  Using a command to jump to another window doesn't change anything
! for the current directory.
  When a |:lcd| command has been used for a window, the specified directory
  becomes the current directory for that window.  Windows where the |:lcd|
! command has not been used stick to the global current directory.  When jumping
! to another window the current directory will become the last specified local
! current directory.  If none was specified, the global current directory is
! used.
! When a |:cd| command is used, the current window will lose his local current
! directory and will use the global current directory from now on.
  
  After using |:cd| the full path name will be used for reading and writing
  files.  On some networked file systems this may cause problems.  The result of
--- 1360,1385 ----
  :pw[d]                        Print the current directory name.  {Vi: no pwd}
                        Also see |getcwd()|.
  
! So long as no |:lcd| or |:tcd| command has been used, all windows share the
! same current directory.  Using a command to jump to another window doesn't
! change anything for the current directory.
! 
  When a |:lcd| command has been used for a window, the specified directory
  becomes the current directory for that window.  Windows where the |:lcd|
! command has not been used stick to the global or tab-local current directory.
! When jumping to another window the current directory will become the last
! specified local current directory.  If none was specified, the global or
! tab-local current directory is used.
! 
! When a |:tcd| command has been used for a tab page, the specified directory
! becomes the current directory for the current tab page and the current window.
! The current directory of other tab pages is not affected.  When jumping to
! another tab page, the current directory will become the last specified local
! directory for that tab page. If the current tab has no local current directory
! the global current directory is used.
! 
! When a |:cd| command is used, the current window and tab page will lose the
! local current directory and will use the global current directory from now on.
  
  After using |:cd| the full path name will be used for reading and writing
  files.  On some networked file systems this may cause problems.  The result of
*** ../vim-8.1.1217/runtime/doc/eval.txt        2019-04-27 13:03:20.012715914 
+0200
--- runtime/doc/eval.txt        2019-04-27 20:14:41.136007351 +0200
***************
*** 2377,2382 ****
--- 2398,2404 ----
  has_key({dict}, {key})                Number  |TRUE| if {dict} has entry {key}
  haslocaldir([{winnr} [, {tabnr}]])
                                Number  |TRUE| if the window executed |:lcd|
+                                       or |:tcd|
  hasmapto({what} [, {mode} [, {abbr}]])
                                Number  |TRUE| if mapping to {what} exists
  histadd({history}, {item})    String  add an item to a history
***************
*** 4880,4886 ****
  getcwd([{winnr} [, {tabnr}]])
                The result is a String, which is the name of the current
                working directory.
-               Without arguments, for the current window.
  
                With {winnr} return the local current directory of this window
                in the current tab page.  {winnr} can be the window number or
--- 4911,4916 ----
***************
*** 4889,4897 ****
                directory.  See also |haslocaldir()|.
  
                With {winnr} and {tabnr} return the local current directory of
!               the window in the specified tab page.
                Return an empty string if the arguments are invalid.
  
  getfsize({fname})                                     *getfsize()*
                The result is a Number, which is the size in bytes of the
                given file {fname}.
--- 4919,4946 ----
                directory.  See also |haslocaldir()|.
  
                With {winnr} and {tabnr} return the local current directory of
!               the window in the specified tab page. If {winnr} is -1 return
!               the working directory of the tabpage.
!               If {winnr} is zero use the current window, if {tabnr} is zero
!               use the current tabpage.
!               Without any arguments, return the working directory of the
!               current window.
                Return an empty string if the arguments are invalid.
  
+               Examples: >
+                       " Get the working directory of the current window
+                       :echo getcwd()
+                       :echo getcwd(0)
+                       :echo getcwd(0, 0)
+                       " Get the working directory of window 3 in tabpage 2
+                       :echo getcwd(3, 2)
+                       " Get the global working directory
+                       :echo getcwd(-1)
+                       " Get the working directory of tabpage 3
+                       :echo getcwd(-1, 3)
+                       " Get the working directory of current tabpage
+                       :echo getcwd(-1, 0)
+ <
  getfsize({fname})                                     *getfsize()*
                The result is a Number, which is the size in bytes of the
                given file {fname}.
***************
*** 5449,5464 ****
                an entry with key {key}.  Zero otherwise.
  
  haslocaldir([{winnr} [, {tabnr}]])                    *haslocaldir()*
!               The result is a Number, which is 1 when the window has set a
!               local path via |:lcd|, and 0 otherwise.
  
                Without arguments use the current window.
                With {winnr} use this window in the current tab page.
                With {winnr} and {tabnr} use the window in the specified tab
                page.
                {winnr} can be the window number or the |window-ID|.
                Return 0 if the arguments are invalid.
  
  hasmapto({what} [, {mode} [, {abbr}]])                        *hasmapto()*
                The result is a Number, which is 1 if there is a mapping that
                contains {what} in somewhere in the rhs (what it is mapped to)
--- 5498,5536 ----
                an entry with key {key}.  Zero otherwise.
  
  haslocaldir([{winnr} [, {tabnr}]])                    *haslocaldir()*
!               The result is a Number:
!                   1   when the window has set a local directory via |:lcd|
!                   2   when the tab-page has set a local directory via |:tcd|
!                   0   otherwise.
  
                Without arguments use the current window.
                With {winnr} use this window in the current tab page.
                With {winnr} and {tabnr} use the window in the specified tab
                page.
                {winnr} can be the window number or the |window-ID|.
+               If {winnr} is -1 it is ignored and only the tabpage is used.
                Return 0 if the arguments are invalid.
+               Examples: >
+                       if haslocaldir() == 1
+                         " window local directory case
+                       elseif haslocaldir() == 2
+                         " tab-local directory case
+                       else
+                         " global directory case
+                       endif
  
+                       " current window
+                       :echo haslocaldir()
+                       :echo haslocaldir(0)
+                       :echo haslocaldir(0, 0)
+                       " window n in current tab page
+                       :echo haslocaldir(n)
+                       :echo haslocaldir(n, 0)
+                       " window n in tab page m
+                       :echo haslocaldir(n, m)
+                       " tab page m
+                       :echo haslocaldir(-1, m)
+ <
  hasmapto({what} [, {mode} [, {abbr}]])                        *hasmapto()*
                The result is a Number, which is 1 if there is a mapping that
                contains {what} in somewhere in the rhs (what it is mapped to)
*** ../vim-8.1.1217/runtime/doc/index.txt       2018-10-19 22:35:04.885189994 
+0200
--- runtime/doc/index.txt       2019-04-27 20:05:21.278555302 +0200
***************
*** 1573,1578 ****
--- 1627,1634 ----
  |:tab|                :tab            create new tab when opening new window
  |:tag|                :ta[g]          jump to tag
  |:tags|               :tags           show the contents of the tag stack
+ |:tcd|                :tcd            change directory for tab page
+ |:tchdir|     :tch[dir]       change directory for tab page
  |:tcl|                :tc[l]          execute Tcl command
  |:tcldo|      :tcld[o]        execute Tcl command for each line
  |:tclfile|    :tclf[ile]      execute Tcl script file
*** ../vim-8.1.1217/runtime/doc/options.txt     2019-02-16 15:09:21.225946157 
+0100
--- runtime/doc/options.txt     2019-04-27 20:05:21.278555302 +0200
***************
*** 1457,1465 ****
                        {not available when compiled without the
                        |+file_in_path| feature}
        This is a list of directories which will be searched when using the
!       |:cd| and |:lcd| commands, provided that the directory being searched
!       for has a relative path, not an absolute part starting with "/", "./"
!       or "../", the 'cdpath' option is not used then.
        The 'cdpath' option's value has the same form and semantics as
        |'path'|.  Also see |file-searching|.
        The default value is taken from $CDPATH, with a "," prepended to look
--- 1455,1463 ----
                        {not available when compiled without the
                        |+file_in_path| feature}
        This is a list of directories which will be searched when using the
!       |:cd|, |:tcd| and |:lcd| commands, provided that the directory being
!       searched for has a relative path, not an absolute part starting with
!       "/", "./" or "../", the 'cdpath' option is not used then.
        The 'cdpath' option's value has the same form and semantics as
        |'path'|.  Also see |file-searching|.
        The default value is taken from $CDPATH, with a "," prepended to look
*** ../vim-8.1.1217/runtime/doc/usr_22.txt      2018-05-17 13:42:03.000000000 
+0200
--- runtime/doc/usr_22.txt      2019-04-27 20:17:02.375349029 +0200
***************
*** 202,215 ****
        :pwd
        /home/Bram/VeryLongFileName
  
! So long as no ":lcd" command has been used, all windows share the same current
! directory.  Doing a ":cd" command in one window will also change the current
  directory of the other window.
!    For a window where ":lcd" has been used a different current directory is
! remembered.  Using ":cd" or ":lcd" in other windows will not change it.
!    When using a ":cd" command in a window that uses a different current
  directory, it will go back to using the shared directory.
  
  ==============================================================================
  *22.3*        Finding a file
  
--- 202,229 ----
        :pwd
        /home/Bram/VeryLongFileName
  
! So long as no `:lcd` command has been used, all windows share the same current
! directory.  Doing a `:cd` command in one window will also change the current
  directory of the other window.
!    For a window where `:lcd` has been used a different current directory is
! remembered.  Using `:cd` or `:lcd` in other windows will not change it.
!    When using a `:cd` command in a window that uses a different current
  directory, it will go back to using the shared directory.
  
+ 
+ TAB LOCAL DIRECTORY
+ 
+ When you open a new tab page, it uses the directory of the window in the
+ previous tab page from which the new tab page was opened. You can change the
+ directory of the current tab page using the `:tcd` command. All the windows in
+ a tab page share this directory except for windows with a window-local
+ directory. Any new windows opened in this tab page will use this directory as
+ the current working directory. Using a `:cd` command in a tab page will not
+ change the working directory of tab pages which have a tab local directory.
+ When the global working directory is changed using the ":cd" command in a tab
+ page, it will also change the current tab page working directory.
+ 
+ 
  ==============================================================================
  *22.3*        Finding a file
  
*** ../vim-8.1.1217/runtime/doc/usr_41.txt      2019-04-06 13:18:06.733335092 
+0200
--- runtime/doc/usr_41.txt      2019-04-27 20:05:21.278555302 +0200
***************
*** 765,771 ****
        isdirectory()           check if a directory exists
        getfsize()              get the size of a file
        getcwd()                get the current working directory
!       haslocaldir()           check if current window used |:lcd|
        tempname()              get the name of a temporary file
        mkdir()                 create a new directory
        delete()                delete a file
--- 766,772 ----
        isdirectory()           check if a directory exists
        getfsize()              get the size of a file
        getcwd()                get the current working directory
!       haslocaldir()           check if current window used |:lcd| or |:tcd|
        tempname()              get the name of a temporary file
        mkdir()                 create a new directory
        delete()                delete a file
*** ../vim-8.1.1217/src/eval.c  2019-04-27 13:03:20.004715961 +0200
--- src/eval.c  2019-04-27 20:17:32.523208020 +0200
***************
*** 8704,8714 ****
  
  /*
   * Find window specified by "wvp" in tabpage "tvp".
   */
      win_T *
  find_tabwin(
!     typval_T  *wvp,   /* VAR_UNKNOWN for current window */
!     typval_T  *tvp)   /* VAR_UNKNOWN for current tab page */
  {
      win_T     *wp = NULL;
      tabpage_T *tp = NULL;
--- 8704,8716 ----
  
  /*
   * Find window specified by "wvp" in tabpage "tvp".
+  * Returns the tab page in 'ptp'
   */
      win_T *
  find_tabwin(
!     typval_T  *wvp,   // VAR_UNKNOWN for current window
!     typval_T  *tvp,   // VAR_UNKNOWN for current tab page
!     tabpage_T **ptp)
  {
      win_T     *wp = NULL;
      tabpage_T *tp = NULL;
***************
*** 8726,8735 ****
--- 8728,8749 ----
            tp = curtab;
  
        if (tp != NULL)
+       {
            wp = find_win_by_nr(wvp, tp);
+           if (wp == NULL && wvp->v_type == VAR_NUMBER
+                                               && wvp->vval.v_number != -1)
+               // A window with the specified number is not found
+               tp = NULL;
+       }
      }
      else
+     {
        wp = curwin;
+       tp = curtab;
+     }
+ 
+     if (ptp != NULL)
+       *ptp = tp;
  
      return wp;
  }
*** ../vim-8.1.1217/src/evalfunc.c      2019-04-27 13:03:20.004715961 +0200
--- src/evalfunc.c      2019-04-27 20:05:21.282555283 +0200
***************
*** 1529,1535 ****
      win_T     *wp;
  
      rettv->vval.v_number = -1;
!     wp = find_tabwin(&argvars[0], &argvars[1]);
      if (wp != NULL)
        rettv->vval.v_number = wp->w_alist->id;
  }
--- 1529,1535 ----
      win_T     *wp;
  
      rettv->vval.v_number = -1;
!     wp = find_tabwin(&argvars[0], &argvars[1], NULL);
      if (wp != NULL)
        rettv->vval.v_number = wp->w_alist->id;
  }
***************
*** 5126,5150 ****
  
  /*
   * "getcwd()" function
   */
      static void
  f_getcwd(typval_T *argvars, typval_T *rettv)
  {
      win_T     *wp = NULL;
      char_u    *cwd;
      int               global = FALSE;
  
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     if (argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number == -1)
        global = TRUE;
      else
!       wp = find_tabwin(&argvars[0], &argvars[1]);
  
      if (wp != NULL && wp->w_localdir != NULL)
        rettv->vval.v_string = vim_strsave(wp->w_localdir);
!     else if (wp != NULL || global)
      {
        if (globaldir != NULL)
            rettv->vval.v_string = vim_strsave(globaldir);
--- 5126,5169 ----
  
  /*
   * "getcwd()" function
+  *
+  * Return the current working directory of a window in a tab page.
+  * First optional argument 'winnr' is the window number or -1 and the second
+  * optional argument 'tabnr' is the tab page number.
+  *
+  * If no arguments are supplied, then return the directory of the current
+  * window.
+  * If only 'winnr' is specified and is not -1 or 0 then return the directory 
of
+  * the specified window.
+  * If 'winnr' is 0 then return the directory of the current window.
+  * If both 'winnr and 'tabnr' are specified and 'winnr' is -1 then return the
+  * directory of the specified tab page.  Otherwise return the directory of the
+  * specified window in the specified tab page.
+  * If the window or the tab page doesn't exist then return NULL.
   */
      static void
  f_getcwd(typval_T *argvars, typval_T *rettv)
  {
      win_T     *wp = NULL;
+     tabpage_T *tp = NULL;
      char_u    *cwd;
      int               global = FALSE;
  
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     if (argvars[0].v_type == VAR_NUMBER
!           && argvars[0].vval.v_number == -1
!           && argvars[1].v_type == VAR_UNKNOWN)
        global = TRUE;
      else
!       wp = find_tabwin(&argvars[0], &argvars[1], &tp);
  
      if (wp != NULL && wp->w_localdir != NULL)
        rettv->vval.v_string = vim_strsave(wp->w_localdir);
!     else if (tp != NULL && tp->tp_localdir != NULL)
!       rettv->vval.v_string = vim_strsave(tp->tp_localdir);
!     else if (wp != NULL || tp != NULL || global)
      {
        if (globaldir != NULL)
            rettv->vval.v_string = vim_strsave(globaldir);
***************
*** 5333,5339 ****
        return;
  
  #ifdef FEAT_JUMPLIST
!     wp = find_tabwin(&argvars[0], &argvars[1]);
      if (wp == NULL)
        return;
  
--- 5352,5358 ----
        return;
  
  #ifdef FEAT_JUMPLIST
!     wp = find_tabwin(&argvars[0], &argvars[1], NULL);
      if (wp == NULL)
        return;
  
***************
*** 6824,6833 ****
      static void
  f_haslocaldir(typval_T *argvars, typval_T *rettv)
  {
      win_T     *wp = NULL;
  
!     wp = find_tabwin(&argvars[0], &argvars[1]);
!     rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL);
  }
  
  /*
--- 6843,6860 ----
      static void
  f_haslocaldir(typval_T *argvars, typval_T *rettv)
  {
+     tabpage_T *tp = NULL;
      win_T     *wp = NULL;
  
!     wp = find_tabwin(&argvars[0], &argvars[1], &tp);
! 
!     // Check for window-local and tab-local directories
!     if (wp != NULL && wp->w_localdir != NULL)
!       rettv->vval.v_number = 1;
!     else if (tp != NULL && tp->tp_localdir != NULL)
!       rettv->vval.v_number = 2;
!     else
!       rettv->vval.v_number = 0;
  }
  
  /*
*** ../vim-8.1.1217/src/ex_cmdidxs.h    2019-04-04 18:15:05.770857065 +0200
--- src/ex_cmdidxs.h    2019-04-27 20:05:21.282555283 +0200
***************
*** 25,36 ****
    /* r */ 351,
    /* s */ 371,
    /* t */ 439,
!   /* u */ 482,
!   /* v */ 493,
!   /* w */ 511,
!   /* x */ 525,
!   /* y */ 534,
!   /* z */ 535
  };
  
  /*
--- 25,36 ----
    /* r */ 351,
    /* s */ 371,
    /* t */ 439,
!   /* u */ 484,
!   /* v */ 495,
!   /* w */ 513,
!   /* x */ 527,
!   /* y */ 536,
!   /* z */ 537
  };
  
  /*
***************
*** 60,66 ****
    /* q */ {  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* r */ {  0,  0,  0,  0,  0,  0,  0,  0, 12,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0, 14, 19,  0,  0,  0,  0 },
    /* s */ {  2,  6, 15,  0, 19, 23,  0, 25, 26,  0,  0, 29, 31, 35, 39, 41,  
0, 49,  0, 50,  0, 62, 63,  0, 64,  0 },
!   /* t */ {  2,  0, 19,  0, 22, 24,  0, 25,  0, 26,  0, 27, 31, 34, 36, 37,  
0, 38, 40,  0, 41,  0,  0,  0,  0,  0 },
    /* u */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* v */ {  0,  0,  0,  0,  1,  0,  0,  0,  4,  0,  0,  0,  9, 12,  0,  0,  
0,  0, 15,  0, 16,  0,  0,  0,  0,  0 },
    /* w */ {  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  8,  0,  9, 
10,  0,  0,  0, 12, 13,  0,  0,  0,  0 },
--- 60,66 ----
    /* q */ {  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* r */ {  0,  0,  0,  0,  0,  0,  0,  0, 12,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0, 14, 19,  0,  0,  0,  0 },
    /* s */ {  2,  6, 15,  0, 19, 23,  0, 25, 26,  0,  0, 29, 31, 35, 39, 41,  
0, 49,  0, 50,  0, 62, 63,  0, 64,  0 },
!   /* t */ {  2,  0, 19,  0, 24, 26,  0, 27,  0, 28,  0, 29, 33, 36, 38, 39,  
0, 40, 42,  0, 43,  0,  0,  0,  0,  0 },
    /* u */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* v */ {  0,  0,  0,  0,  1,  0,  0,  0,  4,  0,  0,  0,  9, 12,  0,  0,  
0,  0, 15,  0, 16,  0,  0,  0,  0,  0 },
    /* w */ {  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  8,  0,  9, 
10,  0,  0,  0, 12, 13,  0,  0,  0,  0 },
***************
*** 69,72 ****
    /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
  };
  
! static const int command_count = 548;
--- 69,72 ----
    /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
  };
  
! static const int command_count = 550;
*** ../vim-8.1.1217/src/ex_cmds.h       2019-04-27 13:03:20.004715961 +0200
--- src/ex_cmds.h       2019-04-27 20:18:38.294899911 +0200
***************
*** 1479,1484 ****
--- 1479,1490 ----
  EX(CMD_tabs,          "tabs",         ex_tabs,
                        TRLBAR|CMDWIN,
                        ADDR_TABS),
+ EX(CMD_tcd,           "tcd",          ex_cd,
+                       BANG|FILE1|TRLBAR|CMDWIN,
+                       ADDR_OTHER),
+ EX(CMD_tchdir,                "tchdir",       ex_cd,
+                       BANG|FILE1|TRLBAR|CMDWIN,
+                       ADDR_OTHER),
  EX(CMD_tcl,           "tcl",          ex_tcl,
                        RANGE|EXTRA|NEEDARG|CMDWIN|RESTRICT,
                        ADDR_LINES),
*** ../vim-8.1.1217/src/ex_docmd.c      2019-04-27 13:03:20.004715961 +0200
--- src/ex_docmd.c      2019-04-27 20:05:21.282555283 +0200
***************
*** 3692,3697 ****
--- 3692,3699 ----
            break;
        case CMD_cd:
        case CMD_chdir:
+       case CMD_tcd:
+       case CMD_tchdir:
        case CMD_lcd:
        case CMD_lchdir:
            if (xp->xp_context == EXPAND_FILES)
***************
*** 7435,7447 ****
  
  /*
   * Deal with the side effects of changing the current directory.
!  * When "local" is TRUE then this was after an ":lcd" command.
   */
      void
! post_chdir(int local)
  {
      VIM_CLEAR(curwin->w_localdir);
!     if (local)
      {
        /* If still in global directory, need to remember current
         * directory as global directory. */
--- 7437,7453 ----
  
  /*
   * Deal with the side effects of changing the current directory.
!  * When "tablocal" is TRUE then this was after an ":tcd" command.
!  * When "winlocal" is TRUE then this was after an ":lcd" command.
   */
      void
! post_chdir(int tablocal, int winlocal)
  {
+     if (!winlocal)
+       // Clear tab local directory for both :cd and :tcd
+       VIM_CLEAR(curtab->tp_localdir);
      VIM_CLEAR(curwin->w_localdir);
!     if (winlocal || tablocal)
      {
        /* If still in global directory, need to remember current
         * directory as global directory. */
***************
*** 7449,7455 ****
            globaldir = vim_strsave(prev_dir);
        /* Remember this local directory for the window. */
        if (mch_dirname(NameBuff, MAXPATHL) == OK)
!           curwin->w_localdir = vim_strsave(NameBuff);
      }
      else
      {
--- 7455,7466 ----
            globaldir = vim_strsave(prev_dir);
        /* Remember this local directory for the window. */
        if (mch_dirname(NameBuff, MAXPATHL) == OK)
!       {
!           if (tablocal)
!               curtab->tp_localdir = vim_strsave(NameBuff);
!           else
!               curwin->w_localdir = vim_strsave(NameBuff);
!       }
      }
      else
      {
***************
*** 7463,7469 ****
  
  
  /*
!  * ":cd", ":lcd", ":chdir" and ":lchdir".
   */
      void
  ex_cd(exarg_T *eap)
--- 7474,7480 ----
  
  
  /*
!  * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
   */
      void
  ex_cd(exarg_T *eap)
***************
*** 7532,7550 ****
            emsg(_(e_failed));
        else
        {
!           int is_local_chdir = eap->cmdidx == CMD_lcd
                                                  || eap->cmdidx == CMD_lchdir;
  
!           post_chdir(is_local_chdir);
  
            /* Echo the new current directory if the command was typed. */
            if (KeyTyped || p_verbose >= 5)
                ex_pwd(eap);
  
            if (dir_differs)
!               apply_autocmds(EVENT_DIRCHANGED,
!                     is_local_chdir ? (char_u *)"window" : (char_u *)"global",
                      new_dir, FALSE, curbuf);
        }
        vim_free(tofree);
      }
--- 7543,7571 ----
            emsg(_(e_failed));
        else
        {
!           char_u  *acmd_fname;
!           int is_winlocal_chdir = eap->cmdidx == CMD_lcd
                                                  || eap->cmdidx == CMD_lchdir;
+           int is_tablocal_chdir = eap->cmdidx == CMD_tcd
+                                                 || eap->cmdidx == CMD_tchdir;
  
!           post_chdir(is_tablocal_chdir, is_winlocal_chdir);
  
            /* Echo the new current directory if the command was typed. */
            if (KeyTyped || p_verbose >= 5)
                ex_pwd(eap);
  
            if (dir_differs)
!           {
!               if (is_winlocal_chdir)
!                   acmd_fname = (char_u *)"window";
!               else if (is_tablocal_chdir)
!                   acmd_fname = (char_u *)"tabpage";
!               else
!                   acmd_fname = (char_u *)"global";
!               apply_autocmds(EVENT_DIRCHANGED, acmd_fname,
                      new_dir, FALSE, curbuf);
+           }
        }
        vim_free(tofree);
      }
***************
*** 9729,9740 ****
      }
      for (tabnr = 1; ; ++tabnr)
      {
        int     need_tabnext = FALSE;
        int     cnr = 1;
  
        if ((ssop_flags & SSOP_TABPAGES))
        {
!           tabpage_T *tp = find_tabpage(tabnr);
  
            if (tp == NULL)
                break;          /* done all tab pages */
--- 9750,9762 ----
      }
      for (tabnr = 1; ; ++tabnr)
      {
+       tabpage_T *tp = NULL;
        int     need_tabnext = FALSE;
        int     cnr = 1;
  
        if ((ssop_flags & SSOP_TABPAGES))
        {
!           tp = find_tabpage(tabnr);
  
            if (tp == NULL)
                break;          /* done all tab pages */
***************
*** 9833,9838 ****
--- 9855,9872 ----
        if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
            return FAIL;
  
+       // Restore the tab-local working directory if specified
+       // Do this before the windows, so that the window-local directory can
+       // override the tab-local directory.
+       if (tp != NULL && tp->tp_localdir != NULL && ssop_flags & SSOP_CURDIR)
+       {
+           if (fputs("tcd ", fd) < 0
+                   || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
+                   || put_eol(fd) == FAIL)
+               return FAIL;
+           did_lcd = TRUE;
+       }
+ 
        /*
         * Restore the view of the window (options, file, cursor, etc.).
         */
*** ../vim-8.1.1217/src/if_py_both.h    2019-03-30 12:51:18.626808012 +0100
--- src/if_py_both.h    2019-04-27 20:05:21.282555283 +0200
***************
*** 1032,1038 ****
      Py_DECREF(newwd);
      Py_XDECREF(todecref);
  
!     post_chdir(FALSE);
  
      if (VimTryEnd())
      {
--- 1032,1038 ----
      Py_DECREF(newwd);
      Py_XDECREF(todecref);
  
!     post_chdir(FALSE, FALSE);
  
      if (VimTryEnd())
      {
*** ../vim-8.1.1217/src/proto/eval.pro  2019-04-05 22:50:35.025737353 +0200
--- src/proto/eval.pro  2019-04-27 20:05:21.286555269 +0200
***************
*** 116,122 ****
  void ex_execute(exarg_T *eap);
  win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp);
  win_T *find_win_by_nr_or_id(typval_T *vp);
! win_T *find_tabwin(typval_T *wvp, typval_T *tvp);
  void getwinvar(typval_T *argvars, typval_T *rettv, int off);
  void setwinvar(typval_T *argvars, typval_T *rettv, int off);
  char_u *autoload_name(char_u *name);
--- 116,122 ----
  void ex_execute(exarg_T *eap);
  win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp);
  win_T *find_win_by_nr_or_id(typval_T *vp);
! win_T *find_tabwin(typval_T *wvp, typval_T *tvp, tabpage_T **ptp);
  void getwinvar(typval_T *argvars, typval_T *rettv, int off);
  void setwinvar(typval_T *argvars, typval_T *rettv, int off);
  char_u *autoload_name(char_u *name);
*** ../vim-8.1.1217/src/proto/ex_docmd.pro      2019-04-27 13:03:20.004715961 
+0200
--- src/proto/ex_docmd.pro      2019-04-27 20:05:21.286555269 +0200
***************
*** 37,43 ****
  void tabpage_new(void);
  void do_exedit(exarg_T *eap, win_T *old_curwin);
  void free_cd_dir(void);
! void post_chdir(int local);
  void ex_cd(exarg_T *eap);
  void do_sleep(long msec);
  void ex_may_print(exarg_T *eap);
--- 37,43 ----
  void tabpage_new(void);
  void do_exedit(exarg_T *eap, win_T *old_curwin);
  void free_cd_dir(void);
! void post_chdir(int tablocal, int winlocal);
  void ex_cd(exarg_T *eap);
  void do_sleep(long msec);
  void ex_may_print(exarg_T *eap);
*** ../vim-8.1.1217/src/structs.h       2019-04-27 13:03:20.008715938 +0200
--- src/structs.h       2019-04-27 20:05:21.286555269 +0200
***************
*** 2574,2579 ****
--- 2574,2582 ----
      int                   tp_prev_which_scrollbars[3];
                                    /* previous value of which_scrollbars */
  #endif
+ 
+     char_u        *tp_localdir;       // absolute path of local directory or
+                                       // NULL
  #ifdef FEAT_DIFF
      diff_T        *tp_first_diff;
      buf_T         *(tp_diffbuf[DB_COUNT]);
*** ../vim-8.1.1217/src/testdir/test_getcwd.vim 2019-01-09 23:00:57.997176121 
+0100
--- src/testdir/test_getcwd.vim 2019-04-27 20:05:21.286555269 +0200
***************
*** 97,102 ****
--- 97,113 ----
    call assert_equal("y Xdir2 1", GetCwdInfo(2, tp_nr))
    call assert_equal("z Xdir3 1", GetCwdInfo(1, tp_nr))
    call assert_equal(g:topdir, getcwd(-1))
+   " Non existing windows and tab pages
+   call assert_equal('', getcwd(100))
+   call assert_equal(0, haslocaldir(100))
+   call assert_equal('', getcwd(10, 1))
+   call assert_equal(0, haslocaldir(10, 1))
+   call assert_equal('', getcwd(1, 5))
+   call assert_equal(0, haslocaldir(1, 5))
+   call assert_fails('call getcwd([])', 'E745:')
+   call assert_fails('call getcwd(1, [])', 'E745:')
+   call assert_fails('call haslocaldir([])', 'E745:')
+   call assert_fails('call haslocaldir(1, [])', 'E745:')
  endfunc
  
  function Test_GetCwd_lcd_shellslash()
***************
*** 110,112 ****
--- 121,264 ----
      call assert_equal(cwd[-1:], '\')
    endif
  endfunc
+ 
+ " Test for :tcd
+ function Test_Tab_Local_Cwd()
+   enew | only | tabonly
+ 
+   call mkdir('Xtabdir1')
+   call mkdir('Xtabdir2')
+   call mkdir('Xwindir1')
+   call mkdir('Xwindir2')
+   call mkdir('Xwindir3')
+ 
+   " Create three tabpages with three windows each
+   edit a
+   botright new b
+   botright new c
+   tabnew m
+   botright new n
+   botright new o
+   tabnew x
+   botright new y
+   botright new z
+ 
+   " Setup different directories for the tab pages and windows
+   tabrewind
+   1wincmd w
+   lcd Xwindir1
+   tabnext
+   tcd Xtabdir1
+   2wincmd w
+   lcd ../Xwindir2
+   tabnext
+   tcd Xtabdir2
+   3wincmd w
+   lcd ../Xwindir3
+ 
+   " Check the directories of various windows
+   call assert_equal("a Xwindir1 1", GetCwdInfo(1, 1))
+   call assert_equal("b Xtopdir 0", GetCwdInfo(2, 1))
+   call assert_equal("c Xtopdir 0", GetCwdInfo(3, 1))
+   call assert_equal("m Xtabdir1 2", GetCwdInfo(1, 2))
+   call assert_equal("n Xwindir2 1", GetCwdInfo(2, 2))
+   call assert_equal("o Xtabdir1 2", GetCwdInfo(3, 2))
+   call assert_equal("x Xtabdir2 2", GetCwdInfo(1, 3))
+   call assert_equal("y Xtabdir2 2", GetCwdInfo(2, 3))
+   call assert_equal("z Xwindir3 1", GetCwdInfo(3, 3))
+ 
+   " Check the tabpage directories
+   call assert_equal('Xtopdir', fnamemodify(getcwd(-1, 1), ':t'))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(-1, 2), ':t'))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(-1, 3), ':t'))
+   call assert_equal('', fnamemodify(getcwd(-1, 4), ':t'))
+ 
+   " Jump to different windows in the tab pages and check the current directory
+   tabrewind | 1wincmd w
+   call assert_equal('Xwindir1', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xwindir1', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xwindir1', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_true(haslocaldir(0))
+   call assert_equal(0, haslocaldir(-1, 0))
+   call assert_equal('Xtopdir', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+   2wincmd w
+   call assert_equal('Xtopdir', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xtopdir', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xtopdir', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_false(haslocaldir(0))
+   call assert_equal(0, haslocaldir(-1, 0))
+   call assert_equal('Xtopdir', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+   tabnext | 1wincmd w
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_true(haslocaldir(0))
+   call assert_equal(2, haslocaldir(-1, 0))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+   2wincmd w
+   call assert_equal('Xwindir2', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xwindir2', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xwindir2', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_true(haslocaldir(0))
+   call assert_equal(2, haslocaldir(-1, 0))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+   tabnext | 1wincmd w
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_true(haslocaldir(0))
+   call assert_equal(2, haslocaldir(-1, 0))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+   3wincmd w
+   call assert_equal('Xwindir3', fnamemodify(getcwd(), ':t'))
+   call assert_equal('Xwindir3', fnamemodify(getcwd(0), ':t'))
+   call assert_equal('Xwindir3', fnamemodify(getcwd(0, 0), ':t'))
+   call assert_true(haslocaldir(0))
+   call assert_equal(2, haslocaldir(-1, 0))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(-1, 0), ':t'))
+   call assert_equal(g:topdir, getcwd(-1))
+ 
+   " A new tab page should inherit the directory of the current tab page
+   tabrewind | 1wincmd w
+   tabnew g
+   call assert_equal("g Xwindir1 1", GetCwdInfo(0, 0))
+   tabclose | tabrewind
+   2wincmd w
+   tabnew h
+   call assert_equal("h Xtopdir 0", GetCwdInfo(0, 0))
+   tabclose
+   tabnext 2 | 1wincmd w
+   tabnew j
+   call assert_equal("j Xtabdir1 2", GetCwdInfo(0, 0))
+   tabclose
+ 
+   " Change the global directory for the first tab page
+   tabrewind | 1wincmd w
+   cd ../Xdir1
+   call assert_equal("a Xdir1 0", GetCwdInfo(1, 1))
+   call assert_equal("b Xdir1 0", GetCwdInfo(2, 1))
+   call assert_equal("m Xtabdir1 2", GetCwdInfo(1, 2))
+   call assert_equal("n Xwindir2 1", GetCwdInfo(2, 2))
+ 
+   " Change the global directory for the second tab page
+   tabnext | 1wincmd w
+   cd ../Xdir3
+   call assert_equal("m Xdir3 0", GetCwdInfo(1, 2))
+   call assert_equal("n Xwindir2 1", GetCwdInfo(2, 2))
+   call assert_equal("o Xdir3 0", GetCwdInfo(3, 2))
+ 
+   " Change the tab-local directory for the third tab page
+   tabnext | 1wincmd w
+   cd ../Xdir1
+   call assert_equal("x Xdir1 0", GetCwdInfo(1, 3))
+   call assert_equal("y Xdir1 0", GetCwdInfo(2, 3))
+   call assert_equal("z Xwindir3 1", GetCwdInfo(3, 3))
+ 
+   enew | only | tabonly
+   new
+ endfunc
*** ../vim-8.1.1217/src/testdir/test_mksession.vim      2019-02-03 
14:52:42.505867463 +0100
--- src/testdir/test_mksession.vim      2019-04-27 20:05:21.286555269 +0200
***************
*** 210,215 ****
--- 210,257 ----
    call delete('Xtest_mks.out')
  endfunc
  
+ " Test for tabpage-local directory
+ func Test_mksession_tcd_multiple_tabs()
+   let save_cwd = getcwd()
+   call mkdir('Xtopdir')
+   cd Xtopdir
+   call mkdir('Xtabdir1')
+   call mkdir('Xtabdir2')
+   call mkdir('Xtabdir3')
+   call mkdir('Xwindir1')
+   call mkdir('Xwindir2')
+   call mkdir('Xwindir3')
+   tcd Xtabdir1
+   botright new
+   wincmd t
+   lcd ../Xwindir1
+   tabnew
+   tcd ../Xtabdir2
+   botright new
+   lcd ../Xwindir2
+   tabnew
+   tcd ../Xtabdir3
+   botright new
+   lcd ../Xwindir3
+   tabfirst
+   1wincmd w
+   mksession! Xtest_mks.out
+   only | tabonly
+   source Xtest_mks.out
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(-1, 1), ':t'))
+   call assert_equal('Xwindir1', fnamemodify(getcwd(1, 1), ':t'))
+   call assert_equal('Xtabdir1', fnamemodify(getcwd(2, 1), ':t'))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(-1, 2), ':t'))
+   call assert_equal('Xtabdir2', fnamemodify(getcwd(1, 2), ':t'))
+   call assert_equal('Xwindir2', fnamemodify(getcwd(2, 2), ':t'))
+   call assert_equal('Xtabdir3', fnamemodify(getcwd(-1, 3), ':t'))
+   call assert_equal('Xtabdir3', fnamemodify(getcwd(1, 3), ':t'))
+   call assert_equal('Xwindir3', fnamemodify(getcwd(2, 3), ':t'))
+   only | tabonly
+   exe 'cd ' . save_cwd
+   call delete("Xtopdir", "rf")
+ endfunc
+ 
  func Test_mksession_blank_tabs()
    tabnew
    tabnew
*** ../vim-8.1.1217/src/window.c        2019-04-26 20:32:57.086296530 +0200
--- src/window.c        2019-04-27 20:05:21.286555269 +0200
***************
*** 3625,3630 ****
--- 3625,3632 ----
      unref_var_dict(tp->tp_vars);
  #endif
  
+     vim_free(tp->tp_localdir);
+ 
  #ifdef FEAT_PYTHON
      python_tabpage_free(tp);
  #endif
***************
*** 3662,3667 ****
--- 3664,3671 ----
      }
      curtab = newtp;
  
+     newtp->tp_localdir = (tp->tp_localdir == NULL)
+                                   ? NULL : vim_strsave(tp->tp_localdir);
      /* Create a new empty window. */
      if (win_alloc_firstwin(tp->tp_curwin) == OK)
      {
***************
*** 3839,3844 ****
--- 3843,3851 ----
      tabpage_T *tp;
      int               i = 1;
  
+     if (n == 0)
+       return curtab;
+ 
      for (tp = first_tabpage; tp != NULL && i != n; tp = tp->tp_next)
        ++i;
      return tp;
***************
*** 4451,4461 ****
        curwin->w_cursor.coladd = 0;
      changed_line_abv_curs();  /* assume cursor position needs updating */
  
!     if (curwin->w_localdir != NULL)
      {
!       /* Window has a local directory: Save current directory as global
!        * directory (unless that was done already) and change to the local
!        * directory. */
        if (globaldir == NULL)
        {
            char_u      cwd[MAXPATHL];
--- 4458,4470 ----
        curwin->w_cursor.coladd = 0;
      changed_line_abv_curs();  /* assume cursor position needs updating */
  
!     if (curwin->w_localdir != NULL || curtab->tp_localdir != NULL)
      {
!       char_u  *dirname;
! 
!       // Window or tab has a local directory: Save current directory as
!       // global directory (unless that was done already) and change to the
!       // local directory.
        if (globaldir == NULL)
        {
            char_u      cwd[MAXPATHL];
***************
*** 4463,4469 ****
            if (mch_dirname(cwd, MAXPATHL) == OK)
                globaldir = vim_strsave(cwd);
        }
!       if (mch_chdir((char *)curwin->w_localdir) == 0)
            shorten_fnames(TRUE);
      }
      else if (globaldir != NULL)
--- 4472,4483 ----
            if (mch_dirname(cwd, MAXPATHL) == OK)
                globaldir = vim_strsave(cwd);
        }
!       if (curwin->w_localdir != NULL)
!           dirname = curwin->w_localdir;
!       else
!           dirname = curtab->tp_localdir;
! 
!       if (mch_chdir((char *)dirname) == 0)
            shorten_fnames(TRUE);
      }
      else if (globaldir != NULL)
*** ../vim-8.1.1217/src/version.c       2019-04-27 19:15:41.856806819 +0200
--- src/version.c       2019-04-27 20:04:37.658747152 +0200
***************
*** 769,770 ****
--- 769,772 ----
  {   /* Add new patch number below this line */
+ /**/
+     1218,
  /**/

-- 
WOMAN:   Dennis, there's some lovely filth down here.  Oh -- how d'you do?
ARTHUR:  How do you do, good lady.  I am Arthur, King of the Britons.
         Who's castle is that?
WOMAN:   King of the who?
                                  The Quest for the Holy Grail (Monty Python)

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui