Patch 7.4.1324
Problem:    Channels with pipes don't work on MS-Windows.
Solution:   Add pipe I/O support. (Yasuhiro Matsumoto)
Files:      src/channel.c, src/os_win32.c, src/proto/channel.pro,
            src/structs.h, src/vim.h, src/testdir/test_channel.vim


*** ../vim-7.4.1323/src/channel.c       2016-02-15 20:39:42.585803341 +0100
--- src/channel.c       2016-02-15 21:40:03.567647945 +0100
***************
*** 32,41 ****
  #  undef EINTR
  # endif
  # define EINTR WSAEINTR
! # define sock_write(sd, buf, len) send(sd, buf, len, 0)
! # define sock_read(sd, buf, len) recv(sd, buf, len, 0)
! # define sock_close(sd) closesocket(sd)
! # define sleep(t) Sleep(t*1000) /* WinAPI Sleep() accepts milliseconds */
  #else
  # include <netdb.h>
  # include <netinet/in.h>
--- 32,40 ----
  #  undef EINTR
  # endif
  # define EINTR WSAEINTR
! # define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0)
! # define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0)
! # define sock_close(sd) closesocket((SOCKET)sd)
  #else
  # include <netdb.h>
  # include <netinet/in.h>
***************
*** 48,59 ****
--- 47,92 ----
  # define sock_write(sd, buf, len) write(sd, buf, len)
  # define sock_read(sd, buf, len) read(sd, buf, len)
  # define sock_close(sd) close(sd)
+ # define fd_read(fd, buf, len, timeout) read(fd, buf, len)
+ # define fd_write(sd, buf, len) write(sd, buf, len)
+ # define fd_close(sd) close(sd)
  #endif
  
  #ifdef FEAT_GUI_W32
  extern HWND s_hwnd;                   /* Gvim's Window handle */
  #endif
  
+ #ifdef WIN32
+     static int
+ fd_read(sock_T fd, char_u *buf, size_t len, int timeout)
+ {
+     HANDLE h = (HANDLE)fd;
+     DWORD nread;
+ 
+     if (!ReadFile(h, buf, (DWORD)len, &nread, NULL))
+       return -1;
+     return (int)nread;
+ }
+ 
+     static int
+ fd_write(sock_T fd, char_u *buf, size_t len)
+ {
+     HANDLE h = (HANDLE)fd;
+     DWORD nwrite;
+ 
+     if (!WriteFile(h, buf, (DWORD)len, &nwrite, NULL))
+       return -1;
+     return (int)nwrite;
+ }
+ 
+     static void
+ fd_close(sock_T fd)
+ {
+     HANDLE h = (HANDLE)fd;
+ 
+     CloseHandle(h);
+ }
+ #endif
  
  /* Log file opened with ch_logfile(). */
  static FILE *log_fd = NULL;
***************
*** 228,234 ****
      which = CHAN_SOCK;
  #endif
      {
!       channel->ch_pfd[which].ch_fd = (sock_T)-1;
  #ifdef FEAT_GUI_X11
        channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
  #endif
--- 261,267 ----
      which = CHAN_SOCK;
  #endif
      {
!       channel->ch_pfd[which].ch_fd = CHAN_FD_INVALID;
  #ifdef FEAT_GUI_X11
        channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
  #endif
***************
*** 363,374 ****
      if (!CH_HAS_GUI)
        return;
  
!     if (channel->CH_SOCK >= 0)
        channel_gui_register_one(channel, CHAN_SOCK);
  # ifdef CHANNEL_PIPES
!     if (channel->CH_OUT >= 0)
        channel_gui_register_one(channel, CHAN_OUT);
!     if (channel->CH_ERR >= 0)
        channel_gui_register_one(channel, CHAN_ERR);
  # endif
  }
--- 396,407 ----
      if (!CH_HAS_GUI)
        return;
  
!     if (channel->CH_SOCK != CHAN_FD_INVALID)
        channel_gui_register_one(channel, CHAN_SOCK);
  # ifdef CHANNEL_PIPES
!     if (channel->CH_OUT != CHAN_FD_INVALID)
        channel_gui_register_one(channel, CHAN_OUT);
!     if (channel->CH_ERR != CHAN_FD_INVALID)
        channel_gui_register_one(channel, CHAN_ERR);
  # endif
  }
***************
*** 457,463 ****
        return NULL;
      }
  
!     if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
      {
        ch_error(NULL, "in socket() in channel_open().\n");
        PERROR("E898: socket() in channel_open()");
--- 490,496 ----
        return NULL;
      }
  
!     if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
      {
        ch_error(NULL, "in socket() in channel_open().\n");
        PERROR("E898: socket() in channel_open()");
***************
*** 564,570 ****
      if (errno == ECONNREFUSED && close_cb != NULL)
      {
        sock_close(sd);
!       if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
        {
            SOCK_ERRNO;
            ch_log(NULL, "socket() retry in channel_open()\n");
--- 597,603 ----
      if (errno == ECONNREFUSED && close_cb != NULL)
      {
        sock_close(sd);
!       if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            SOCK_ERRNO;
            ch_log(NULL, "socket() retry in channel_open()\n");
***************
*** 609,615 ****
        }
      }
  
!     channel->CH_SOCK = sd;
      channel->ch_close_cb = close_cb;
  
  #ifdef FEAT_GUI
--- 642,648 ----
        }
      }
  
!     channel->CH_SOCK = (sock_T)sd;
      channel->ch_close_cb = close_cb;
  
  #ifdef FEAT_GUI
***************
*** 621,627 ****
  
  #if defined(CHANNEL_PIPES) || defined(PROTO)
      void
! channel_set_pipes(channel_T *channel, int in, int out, int err)
  {
      channel->CH_IN = in;
      channel->CH_OUT = out;
--- 654,660 ----
  
  #if defined(CHANNEL_PIPES) || defined(PROTO)
      void
! channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
  {
      channel->CH_IN = in;
      channel->CH_OUT = out;
***************
*** 1144,1152 ****
      int
  channel_can_write_to(channel_T *channel)
  {
!     return channel != NULL && (channel->CH_SOCK >= 0
  #ifdef CHANNEL_PIPES
!                         || channel->CH_IN >= 0
  #endif
                          );
  }
--- 1177,1185 ----
      int
  channel_can_write_to(channel_T *channel)
  {
!     return channel != NULL && (channel->CH_SOCK != CHAN_FD_INVALID
  #ifdef CHANNEL_PIPES
!                         || channel->CH_IN != CHAN_FD_INVALID
  #endif
                          );
  }
***************
*** 1158,1168 ****
      int
  channel_is_open(channel_T *channel)
  {
!     return channel != NULL && (channel->CH_SOCK >= 0
  #ifdef CHANNEL_PIPES
!                         || channel->CH_IN >= 0
!                         || channel->CH_OUT >= 0
!                         || channel->CH_ERR >= 0
  #endif
                          );
  }
--- 1191,1201 ----
      int
  channel_is_open(channel_T *channel)
  {
!     return channel != NULL && (channel->CH_SOCK != CHAN_FD_INVALID
  #ifdef CHANNEL_PIPES
!                         || channel->CH_IN != CHAN_FD_INVALID
!                         || channel->CH_OUT != CHAN_FD_INVALID
!                         || channel->CH_ERR != CHAN_FD_INVALID
  #endif
                          );
  }
***************
*** 1193,1218 ****
      channel_gui_unregister(channel);
  #endif
  
!     if (channel->CH_SOCK >= 0)
      {
        sock_close(channel->CH_SOCK);
!       channel->CH_SOCK = -1;
      }
  #if defined(CHANNEL_PIPES)
!     if (channel->CH_IN >= 0)
      {
!       close(channel->CH_IN);
!       channel->CH_IN = -1;
      }
!     if (channel->CH_OUT >= 0)
      {
!       close(channel->CH_OUT);
!       channel->CH_OUT = -1;
      }
!     if (channel->CH_ERR >= 0)
      {
!       close(channel->CH_ERR);
!       channel->CH_ERR = -1;
      }
  #endif
  
--- 1226,1251 ----
      channel_gui_unregister(channel);
  #endif
  
!     if (channel->CH_SOCK != CHAN_FD_INVALID)
      {
        sock_close(channel->CH_SOCK);
!       channel->CH_SOCK = CHAN_FD_INVALID;
      }
  #if defined(CHANNEL_PIPES)
!     if (channel->CH_IN != CHAN_FD_INVALID)
      {
!       fd_close(channel->CH_IN);
!       channel->CH_IN = CHAN_FD_INVALID;
      }
!     if (channel->CH_OUT != CHAN_FD_INVALID)
      {
!       fd_close(channel->CH_OUT);
!       channel->CH_OUT = CHAN_FD_INVALID;
      }
!     if (channel->CH_ERR != CHAN_FD_INVALID)
      {
!       fd_close(channel->CH_ERR);
!       channel->CH_ERR = CHAN_FD_INVALID;
      }
  #endif
  
***************
*** 1325,1331 ****
   * Always returns OK for FEAT_GUI_W32.
   */
      static int
! channel_wait(channel_T *channel, int fd, int timeout)
  {
  #if defined(HAVE_SELECT) && !defined(FEAT_GUI_W32)
      struct timeval    tval;
--- 1358,1364 ----
   * Always returns OK for FEAT_GUI_W32.
   */
      static int
! channel_wait(channel_T *channel, sock_T fd, int timeout)
  {
  #if defined(HAVE_SELECT) && !defined(FEAT_GUI_W32)
      struct timeval    tval;
***************
*** 1334,1346 ****
  
      if (timeout > 0)
        ch_logn(channel, "Waiting for %d msec\n", timeout);
      FD_ZERO(&rfds);
!     FD_SET(fd, &rfds);
      tval.tv_sec = timeout / 1000;
      tval.tv_usec = (timeout % 1000) * 1000;
      for (;;)
      {
!       ret = select(fd + 1, &rfds, NULL, NULL, &tval);
  # ifdef EINTR
        if (ret == -1 && errno == EINTR)
            continue;
--- 1367,1404 ----
  
      if (timeout > 0)
        ch_logn(channel, "Waiting for %d msec\n", timeout);
+ 
+ 
+ # ifdef WIN32
+     if (channel->CH_SOCK == CHAN_FD_INVALID)
+     {
+       DWORD   nread;
+       int     diff;
+       DWORD   deadline = GetTickCount() + timeout;
+ 
+       /* reading from a pipe, not a socket */
+       while (TRUE)
+       {
+           if (PeekNamedPipe(fd, NULL, 0, NULL, &nread, NULL) && nread > 0)
+               return OK;
+           diff = deadline - GetTickCount();
+           if (diff < 0)
+               break;
+           /* Wait for 5 msec.
+            * TODO: increase the sleep time when looping more often */
+           Sleep(5);
+       }
+       return FAIL;
+     }
+ #endif
+ 
      FD_ZERO(&rfds);
!     FD_SET((int)fd, &rfds);
      tval.tv_sec = timeout / 1000;
      tval.tv_usec = (timeout % 1000) * 1000;
      for (;;)
      {
!       ret = select((int)fd + 1, &rfds, NULL, NULL, &tval);
  # ifdef EINTR
        if (ret == -1 && errno == EINTR)
            continue;
***************
*** 1385,1401 ****
   * Get the file descriptor to read from, either the socket or stdout.
   * TODO: should have a way to read stderr.
   */
!     static int
  get_read_fd(channel_T *channel)
  {
!     if (channel->CH_SOCK >= 0)
        return channel->CH_SOCK;
  #if defined(CHANNEL_PIPES)
!     if (channel->CH_OUT >= 0)
        return channel->CH_OUT;
  #endif
      ch_error(channel, "channel_read() called while socket is closed\n");
!     return -1;
  }
  
  /*
--- 1443,1459 ----
   * Get the file descriptor to read from, either the socket or stdout.
   * TODO: should have a way to read stderr.
   */
!     static sock_T
  get_read_fd(channel_T *channel)
  {
!     if (channel->CH_SOCK != CHAN_FD_INVALID)
        return channel->CH_SOCK;
  #if defined(CHANNEL_PIPES)
!     if (channel->CH_OUT != CHAN_FD_INVALID)
        return channel->CH_OUT;
  #endif
      ch_error(channel, "channel_read() called while socket is closed\n");
!     return CHAN_FD_INVALID;
  }
  
  /*
***************
*** 1410,1423 ****
      static char_u     *buf = NULL;
      int                       len = 0;
      int                       readlen = 0;
!     int                       fd;
      int                       use_socket = FALSE;
  
      if (which < 0)
        fd = get_read_fd(channel);
      else
        fd = channel->ch_pfd[which].ch_fd;
!     if (fd < 0)
        return;
      use_socket = fd == channel->CH_SOCK;
  
--- 1468,1481 ----
      static char_u     *buf = NULL;
      int                       len = 0;
      int                       readlen = 0;
!     sock_T            fd;
      int                       use_socket = FALSE;
  
      if (which < 0)
        fd = get_read_fd(channel);
      else
        fd = channel->ch_pfd[which].ch_fd;
!     if (fd == CHAN_FD_INVALID)
        return;
      use_socket = fd == channel->CH_SOCK;
  
***************
*** 1439,1445 ****
        if (use_socket)
            len = sock_read(fd, buf, MAXMSGSIZE);
        else
!           len = read(fd, buf, MAXMSGSIZE);
        if (len <= 0)
            break;      /* error or nothing more to read */
  
--- 1497,1503 ----
        if (use_socket)
            len = sock_read(fd, buf, MAXMSGSIZE);
        else
!           len = fd_read(fd, buf, MAXMSGSIZE, channel->ch_timeout);
        if (len <= 0)
            break;      /* error or nothing more to read */
  
***************
*** 1509,1520 ****
      ch_log(channel, "Reading raw\n");
      if (channel_peek(channel) == NULL)
      {
!       int fd = get_read_fd(channel);
  
        /* TODO: read both out and err if they are different */
        ch_log(channel, "No readahead\n");
        /* Wait for up to the channel timeout. */
!       if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout) == FAIL)
            return NULL;
        channel_read(channel, -1, "channel_read_block");
      }
--- 1567,1579 ----
      ch_log(channel, "Reading raw\n");
      if (channel_peek(channel) == NULL)
      {
!       sock_T fd = get_read_fd(channel);
  
        /* TODO: read both out and err if they are different */
        ch_log(channel, "No readahead\n");
        /* Wait for up to the channel timeout. */
!       if (fd == CHAN_FD_INVALID
!               || channel_wait(channel, fd, channel->ch_timeout) == FAIL)
            return NULL;
        channel_read(channel, -1, "channel_read_block");
      }
***************
*** 1533,1539 ****
  channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
  {
      int               more;
!     int               fd;
  
      ch_log(channel, "Reading JSON\n");
      channel->ch_block_id = id;
--- 1592,1598 ----
  channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
  {
      int               more;
!     sock_T    fd;
  
      ch_log(channel, "Reading JSON\n");
      channel->ch_block_id = id;
***************
*** 1557,1564 ****
  
            /* Wait for up to the channel timeout. */
            fd = get_read_fd(channel);
!           if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout)
!                                                                     == FAIL)
                break;
            channel_read(channel, -1, "channel_read_json_block");
        }
--- 1616,1623 ----
  
            /* Wait for up to the channel timeout. */
            fd = get_read_fd(channel);
!           if (fd == CHAN_FD_INVALID
!                   || channel_wait(channel, fd, channel->ch_timeout) == FAIL)
                break;
            channel_read(channel, -1, "channel_read_json_block");
        }
***************
*** 1578,1584 ****
      channel_T *channel;
      int               i;
  
!     if (fd >= 0)
        for (channel = first_channel; channel != NULL;
                                                   channel = channel->ch_next)
        {
--- 1637,1643 ----
      channel_T *channel;
      int               i;
  
!     if (fd != CHAN_FD_INVALID)
        for (channel = first_channel; channel != NULL;
                                                   channel = channel->ch_next)
        {
***************
*** 1607,1625 ****
  {
      int               len = (int)STRLEN(buf);
      int               res;
!     int               fd = -1;
      int               use_socket = FALSE;
  
!     if (channel->CH_SOCK >= 0)
      {
        fd = channel->CH_SOCK;
        use_socket = TRUE;
      }
  #if defined(CHANNEL_PIPES)
!     else if (channel->CH_IN >= 0)
        fd = channel->CH_IN;
  #endif
!     if (fd < 0)
      {
        if (!channel->ch_error && fun != NULL)
        {
--- 1666,1684 ----
  {
      int               len = (int)STRLEN(buf);
      int               res;
!     sock_T    fd = CHAN_FD_INVALID;
      int               use_socket = FALSE;
  
!     if (channel->CH_SOCK != CHAN_FD_INVALID)
      {
        fd = channel->CH_SOCK;
        use_socket = TRUE;
      }
  #if defined(CHANNEL_PIPES)
!     else if (channel->CH_IN != CHAN_FD_INVALID)
        fd = channel->CH_IN;
  #endif
!     if (fd == CHAN_FD_INVALID)
      {
        if (!channel->ch_error && fun != NULL)
        {
***************
*** 1642,1648 ****
      if (use_socket)
        res = sock_write(fd, buf, len);
      else
!       res = write(fd, buf, len);
      if (res != len)
      {
        if (!channel->ch_error && fun != NULL)
--- 1701,1707 ----
      if (use_socket)
        res = sock_write(fd, buf, len);
      else
!       res = fd_write(fd, buf, len);
      if (res != len)
      {
        if (!channel->ch_error && fun != NULL)
***************
*** 1680,1686 ****
        which = CHAN_SOCK;
  #  endif
        {
!           if (channel->ch_pfd[which].ch_fd >= 0)
            {
                channel->ch_pfd[which].ch_poll_idx = nfd;
                fds[nfd].fd = channel->ch_pfd[which].ch_fd;
--- 1739,1745 ----
        which = CHAN_SOCK;
  #  endif
        {
!           if (channel->ch_pfd[which].ch_fd != CHAN_FD_INVALID)
            {
                channel->ch_pfd[which].ch_poll_idx = nfd;
                fds[nfd].fd = channel->ch_pfd[which].ch_fd;
***************
*** 1750,1760 ****
        {
            sock_T fd = channel->ch_pfd[which].ch_fd;
  
!           if (fd >= 0)
            {
!               FD_SET(fd, rfds);
!               if (maxfd < fd)
!                   maxfd = fd;
            }
        }
      }
--- 1809,1819 ----
        {
            sock_T fd = channel->ch_pfd[which].ch_fd;
  
!           if (fd != CHAN_FD_INVALID)
            {
!               FD_SET((int)fd, rfds);
!               if (maxfd < (int)fd)
!                   maxfd = (int)fd;
            }
        }
      }
***************
*** 1783,1789 ****
        {
            sock_T fd = channel->ch_pfd[which].ch_fd;
  
!           if (ret > 0 && fd >= 0 && FD_ISSET(fd, rfds))
            {
                channel_read(channel, which, "channel_select_check");
                --ret;
--- 1842,1848 ----
        {
            sock_T fd = channel->ch_pfd[which].ch_fd;
  
!           if (ret > 0 && fd != CHAN_FD_INVALID && FD_ISSET(fd, rfds))
            {
                channel_read(channel, which, "channel_select_check");
                --ret;
*** ../vim-7.4.1323/src/os_win32.c      2016-02-15 12:44:16.221956302 +0100
--- src/os_win32.c      2016-02-15 21:45:01.180513293 +0100
***************
*** 5041,5046 ****
--- 5041,5057 ----
      HANDLE            jo;
  # ifdef FEAT_CHANNEL
      channel_T         *channel;
+     HANDLE            ifd[2];
+     HANDLE            ofd[2];
+     HANDLE            efd[2];
+     SECURITY_ATTRIBUTES saAttr;
+ 
+     ifd[0] = INVALID_HANDLE_VALUE;
+     ifd[1] = INVALID_HANDLE_VALUE;
+     ofd[0] = INVALID_HANDLE_VALUE;
+     ofd[1] = INVALID_HANDLE_VALUE;
+     efd[0] = INVALID_HANDLE_VALUE;
+     efd[1] = INVALID_HANDLE_VALUE;
  
      channel = add_channel();
      if (channel == NULL)
***************
*** 5057,5066 ****
      ZeroMemory(&pi, sizeof(pi));
      ZeroMemory(&si, sizeof(si));
      si.cb = sizeof(si);
!     si.dwFlags = STARTF_USESHOWWINDOW;
      si.wShowWindow = SW_HIDE;
  
!     if (!vim_create_process(cmd, FALSE,
            CREATE_SUSPENDED |
            CREATE_DEFAULT_ERROR_MODE |
            CREATE_NEW_PROCESS_GROUP |
--- 5068,5092 ----
      ZeroMemory(&pi, sizeof(pi));
      ZeroMemory(&si, sizeof(si));
      si.cb = sizeof(si);
!     si.dwFlags |= STARTF_USESHOWWINDOW;
      si.wShowWindow = SW_HIDE;
  
!     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
!     saAttr.bInheritHandle = TRUE;
!     saAttr.lpSecurityDescriptor = NULL;
!     if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
!        || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)
!        || !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
!        || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)
!        || !CreatePipe(&efd[0], &efd[1], &saAttr, 0)
!        || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0))
!       goto failed;
!     si.dwFlags |= STARTF_USESTDHANDLES;
!     si.hStdInput = ifd[0];
!     si.hStdOutput = ofd[1];
!     si.hStdError = efd[1];
! 
!     if (!vim_create_process(cmd, TRUE,
            CREATE_SUSPENDED |
            CREATE_DEFAULT_ERROR_MODE |
            CREATE_NEW_PROCESS_GROUP |
***************
*** 5085,5106 ****
      job->jv_job_object = jo;
      job->jv_status = JOB_STARTED;
  
  # ifdef FEAT_CHANNEL
- #  if 0
-     /* TODO: connect stdin/stdout/stderr */
      job->jv_channel = channel;
!     channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]);
      channel_set_job(channel, job);
  
  #   ifdef FEAT_GUI
       channel_gui_register(channel);
  #   endif
- #  endif
  # endif
      return;
  
  failed:
  # ifdef FEAT_CHANNEL
      channel_free(channel);
  # else
      ;  /* make compiler happy */
--- 5111,5139 ----
      job->jv_job_object = jo;
      job->jv_status = JOB_STARTED;
  
+     CloseHandle(ifd[0]);
+     CloseHandle(ofd[1]);
+     CloseHandle(efd[1]);
+ 
  # ifdef FEAT_CHANNEL
      job->jv_channel = channel;
!     channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], 
(sock_T)efd[0]);
      channel_set_job(channel, job);
  
  #   ifdef FEAT_GUI
       channel_gui_register(channel);
  #   endif
  # endif
      return;
  
  failed:
  # ifdef FEAT_CHANNEL
+     CloseHandle(ifd[0]);
+     CloseHandle(ofd[0]);
+     CloseHandle(efd[0]);
+     CloseHandle(ifd[1]);
+     CloseHandle(ofd[1]);
+     CloseHandle(efd[1]);
      channel_free(channel);
  # else
      ;  /* make compiler happy */
*** ../vim-7.4.1323/src/proto/channel.pro       2016-02-14 23:02:29.838701624 
+0100
--- src/proto/channel.pro       2016-02-15 21:45:20.188313115 +0100
***************
*** 5,11 ****
  void channel_gui_register(channel_T *channel);
  void channel_gui_register_all(void);
  channel_T *channel_open(char *hostname, int port_in, int waittime, void 
(*close_cb)(void));
! void channel_set_pipes(channel_T *channel, int in, int out, int err);
  void channel_set_job(channel_T *channel, job_T *job);
  void channel_set_json_mode(channel_T *channel, ch_mode_T ch_mode);
  void channel_set_timeout(channel_T *channel, int timeout);
--- 5,11 ----
  void channel_gui_register(channel_T *channel);
  void channel_gui_register_all(void);
  channel_T *channel_open(char *hostname, int port_in, int waittime, void 
(*close_cb)(void));
! void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
  void channel_set_job(channel_T *channel, job_T *job);
  void channel_set_json_mode(channel_T *channel, ch_mode_T ch_mode);
  void channel_set_timeout(channel_T *channel, int timeout);
*** ../vim-7.4.1323/src/structs.h       2016-02-14 23:02:29.834701666 +0100
--- src/structs.h       2016-02-15 21:45:44.444057673 +0100
***************
*** 1306,1313 ****
  #define CHAN_SOCK   0
  #define CH_SOCK           ch_pfd[CHAN_SOCK].ch_fd
  
! #ifdef UNIX
  # define CHANNEL_PIPES
  
  # define CHAN_OUT   1
  # define CHAN_ERR   2
--- 1306,1314 ----
  #define CHAN_SOCK   0
  #define CH_SOCK           ch_pfd[CHAN_SOCK].ch_fd
  
! #if defined(UNIX) || defined(WIN32)
  # define CHANNEL_PIPES
+ # define CHAN_FD_INVALID  (-1)
  
  # define CHAN_OUT   1
  # define CHAN_ERR   2
*** ../vim-7.4.1323/src/vim.h   2016-02-13 17:24:20.462210990 +0100
--- src/vim.h   2016-02-15 21:26:44.828064835 +0100
***************
*** 1730,1736 ****
  typedef int proftime_T;           /* dummy for function prototypes */
  #endif
  
! #ifdef WIN64
  typedef __int64 sock_T;
  #else
  typedef int sock_T;
--- 1730,1736 ----
  typedef int proftime_T;           /* dummy for function prototypes */
  #endif
  
! #ifdef _WIN64
  typedef __int64 sock_T;
  #else
  typedef int sock_T;
*** ../vim-7.4.1323/src/testdir/test_channel.vim        2016-02-15 
20:39:42.585803341 +0100
--- src/testdir/test_channel.vim        2016-02-15 21:46:18.383700257 +0100
***************
*** 280,286 ****
  endfunc
  
  func Test_pipe()
!   if !has('job') || !has('unix')
      return
    endif
    let job = job_start("python test_channel_pipe.py")
--- 280,286 ----
  endfunc
  
  func Test_pipe()
!   if !has('job')
      return
    endif
    let job = job_start("python test_channel_pipe.py")
*** ../vim-7.4.1323/src/version.c       2016-02-15 21:22:06.470999629 +0100
--- src/version.c       2016-02-15 21:27:34.463541603 +0100
***************
*** 749,750 ****
--- 749,752 ----
  {   /* Add new patch number below this line */
+ /**/
+     1324,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
269. You receive an e-mail from the wife of a deceased president, offering
     to send you twenty million dollar, and you are not even surprised.

 /// Bram Moolenaar -- [email protected] -- 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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui