Patch 7.4.1318
Problem:    Channel with pipes doesn't work in GUI.
Solution:   Register input handlers for pipes.
Files:      src/structs.h, src/feature.h, src/channel.c, src/eval.c,
            src/os_unix.c, src/os_win32.c, src/gui_w48.c, src/proto/channel.pro


*** ../vim-7.4.1317/src/structs.h       2016-02-13 23:22:35.077363718 +0100
--- src/structs.h       2016-02-14 19:05:06.792167742 +0100
***************
*** 1301,1335 ****
      MODE_JS
  } ch_mode_T;
  
! struct channel_S {
!     channel_T *ch_next;
!     channel_T *ch_prev;
! 
!     int               ch_id;          /* ID of the channel */
  
!     sock_T    ch_sock;        /* the socket, -1 for a closed channel */
  
  #ifdef UNIX
  # define CHANNEL_PIPES
-     int               ch_in;          /* stdin of the job, -1 if not used */
-     int               ch_out;         /* stdout of the job, -1 if not used */
-     int               ch_err;         /* stderr of the job, -1 if not used */
  
! # if defined(UNIX) && !defined(HAVE_SELECT)
!     int               ch_sock_idx;    /* used by channel_poll_setup() */
!     int               ch_in_idx;      /* used by channel_poll_setup() */
!     int               ch_out_idx;     /* used by channel_poll_setup() */
!     int               ch_err_idx;     /* used by channel_poll_setup() */
! # endif
  #endif
  
!     readq_T   ch_head;        /* dummy node, header for circular queue */
  
-     int               ch_error;       /* When TRUE an error was reported.  
Avoids
-                                * giving pages full of error messages when
-                                * the other side has exited, only mention the
-                                * first error until the connection works
-                                * again. */
  #ifdef FEAT_GUI_X11
      XtInputId ch_inputHandler; /* Cookie for input */
  #endif
--- 1301,1330 ----
      MODE_JS
  } ch_mode_T;
  
! /* Ordering matters: IN is last, only SOCK/OUT/ERR are polled */
  
! #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
! # define CHAN_IN    3
! # define CH_OUT           ch_pfd[CHAN_OUT].ch_fd
! # define CH_ERR           ch_pfd[CHAN_ERR].ch_fd
! # define CH_IN            ch_pfd[CHAN_IN].ch_fd
  #endif
  
! /* The per-fd info for a channel. */
! typedef struct {
!     sock_T    ch_fd;      /* socket/stdin/stdout/stderr, -1 if not used */
! 
! # if defined(UNIX) && !defined(HAVE_SELECT)
!     int               ch_poll_idx;    /* used by channel_poll_setup() */
! # endif
  
  #ifdef FEAT_GUI_X11
      XtInputId ch_inputHandler; /* Cookie for input */
  #endif
***************
*** 1337,1345 ****
      gint      ch_inputHandler; /* Cookie for input */
  #endif
  #ifdef WIN32
!     int               ch_inputHandler; /* simply ret.value of 
WSAAsyncSelect() */
  #endif
  
      void      (*ch_close_cb)(void); /* callback for when channel is closed */
  
      int               ch_block_id;    /* ID that channel_read_json_block() is
--- 1332,1356 ----
      gint      ch_inputHandler; /* Cookie for input */
  #endif
  #ifdef WIN32
!     int               ch_inputHandler; /* ret.value of WSAAsyncSelect() */
  #endif
+ } chan_fd_T;
+ 
+ struct channel_S {
+     channel_T *ch_next;
+     channel_T *ch_prev;
+ 
+     int               ch_id;          /* ID of the channel */
+ 
+     chan_fd_T ch_pfd[4];      /* info for socket, in, out and err */
  
+     readq_T   ch_head;        /* dummy node, header for circular queue */
+ 
+     int               ch_error;       /* When TRUE an error was reported.  
Avoids
+                                * giving pages full of error messages when
+                                * the other side has exited, only mention the
+                                * first error until the connection works
+                                * again. */
      void      (*ch_close_cb)(void); /* callback for when channel is closed */
  
      int               ch_block_id;    /* ID that channel_read_json_block() is
*** ../vim-7.4.1317/src/feature.h       2016-02-07 19:57:12.192788494 +0100
--- src/feature.h       2016-02-13 23:45:26.674898639 +0100
***************
*** 1262,1268 ****
  #endif
  
  /*
!  * The +job feature requires +eval and Unix or MS-Widndows.
   */
  #if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL)
  # define FEAT_JOB
--- 1262,1268 ----
  #endif
  
  /*
!  * The +job feature requires +eval and Unix or MS-Windows.
   */
  #if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL)
  # define FEAT_JOB
*** ../vim-7.4.1317/src/channel.c       2016-02-13 23:22:35.085363634 +0100
--- src/channel.c       2016-02-14 19:04:42.060425893 +0100
***************
*** 213,219 ****
      channel_T *
  add_channel(void)
  {
!     channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
  
      if (channel == NULL)
        return NULL;
--- 213,220 ----
      channel_T *
  add_channel(void)
  {
!     int               which;
!     channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
  
      if (channel == NULL)
        return NULL;
***************
*** 221,241 ****
      channel->ch_id = next_ch_id++;
      ch_log(channel, "Opening channel\n");
  
-     channel->ch_sock = (sock_T)-1;
  #ifdef CHANNEL_PIPES
!     channel->ch_in = -1;
!     channel->ch_out = -1;
!     channel->ch_err = -1;
  #endif
  #ifdef FEAT_GUI_X11
!     channel->ch_inputHandler = (XtInputId)NULL;
  #endif
  #ifdef FEAT_GUI_GTK
!     channel->ch_inputHandler = 0;
  #endif
  #ifdef FEAT_GUI_W32
!     channel->ch_inputHandler = -1;
  #endif
  
      channel->ch_timeout = 2000;
  
--- 222,244 ----
      channel->ch_id = next_ch_id++;
      ch_log(channel, "Opening channel\n");
  
  #ifdef CHANNEL_PIPES
!     for (which = CHAN_SOCK; which <= CHAN_IN; ++which)
! #else
!     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
  #ifdef FEAT_GUI_GTK
!       channel->ch_pfd[which].ch_inputHandler = 0;
  #endif
  #ifdef FEAT_GUI_W32
!       channel->ch_pfd[which].ch_inputHandler = -1;
  #endif
+     }
  
      channel->ch_timeout = 2000;
  
***************
*** 290,296 ****
      if (channel == NULL)
        ch_errorn(NULL, "Channel %d not found", id);
      else
!       channel_read(channel, FALSE, "messageFromNetbeans");
  }
  #endif
  
--- 293,299 ----
      if (channel == NULL)
        ch_errorn(NULL, "Channel %d not found", id);
      else
!       channel_read(channel, -1, "messageFromNetbeans");
  }
  #endif
  
***************
*** 318,363 ****
  #endif
  
      static void
! channel_gui_register(channel_T *channel)
  {
-     if (!CH_HAS_GUI)
-       return;
- 
-     /* TODO: pipes */
  # ifdef FEAT_GUI_X11
!     /* tell notifier we are interested in being called
!      * when there is input on the editor connection socket
!      */
!     if (channel->ch_inputHandler == (XtInputId)NULL)
!       channel->ch_inputHandler =
!           XtAppAddInput((XtAppContext)app_context, channel->ch_sock,
!                        (XtPointer)(XtInputReadMask + XtInputExceptMask),
!                       messageFromNetbeans, (XtPointer)(long)channel->ch_id);
  # else
  #  ifdef FEAT_GUI_GTK
!     /*
!      * Tell gdk we are interested in being called when there
!      * is input on the editor connection socket
!      */
!     if (channel->ch_inputHandler == 0)
!       channel->ch_inputHandler =
!           gdk_input_add((gint)channel->ch_sock, (GdkInputCondition)
!                            ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
!                        messageFromNetbeans, (gpointer)(long)channel->ch_id);
  #  else
  #   ifdef FEAT_GUI_W32
!     /*
!      * Tell Windows we are interested in receiving message when there
!      * is input on the editor connection socket.
!      */
!     if (channel->ch_inputHandler == -1)
!       channel->ch_inputHandler =
!           WSAAsyncSelect(channel->ch_sock, s_hwnd, WM_NETBEANS, FD_READ);
  #   endif
  #  endif
  # endif
  }
  
  /*
   * Register any of our file descriptors with the GUI event handling system.
   * Called when the GUI has started.
--- 321,377 ----
  #endif
  
      static void
! channel_gui_register_one(channel_T *channel, int which)
  {
  # ifdef FEAT_GUI_X11
!     /* Tell notifier we are interested in being called
!      * when there is input on the editor connection socket. */
!     if (channel->ch_pfd[which].ch_inputHandler == (XtInputId)NULL)
!       channel->ch_pfd[which].ch_inputHandler = XtAppAddInput(
!               (XtAppContext)app_context,
!               channel->ch_pfd[which].ch_fd,
!               (XtPointer)(XtInputReadMask + XtInputExceptMask),
!               messageFromNetbeans,
!               (XtPointer)(long)channel->ch_id);
  # else
  #  ifdef FEAT_GUI_GTK
!     /* Tell gdk we are interested in being called when there
!      * is input on the editor connection socket. */
!     if (channel->ch_pfd[which].ch_inputHandler == 0)
!       channel->ch_pfd[which].ch_inputHandler = gdk_input_add(
!               (gint)channel->ch_pfd[which].ch_fd, (GdkInputCondition)
!               ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
!               messageFromNetbeans,
!               (gpointer)(long)channel->ch_id);
  #  else
  #   ifdef FEAT_GUI_W32
!     /* Tell Windows we are interested in receiving message when there
!      * is input on the editor connection socket.  */
!     if (channel->ch_pfd[which].ch_inputHandler == -1)
!       channel->ch_pfd[which].ch_inputHandler = WSAAsyncSelect(
!               channel->ch_pfd[which].ch_fd,
!               s_hwnd, WM_NETBEANS, FD_READ);
  #   endif
  #  endif
  # endif
  }
  
+     void
+ channel_gui_register(channel_T *channel)
+ {
+     if (!CH_HAS_GUI)
+       return;
+ 
+     if (channel->ch_pfd[CHAN_SOCK].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_SOCK);
+ # ifdef CHANNEL_PIPES
+     if (channel->ch_pfd[CHAN_OUT].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_OUT);
+     if (channel->ch_pfd[CHAN_ERR].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_ERR);
+ # endif
+ }
+ 
  /*
   * Register any of our file descriptors with the GUI event handling system.
   * Called when the GUI has started.
***************
*** 368,407 ****
      channel_T *channel;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
!       /* TODO: pipes */
!       if (channel->ch_sock >= 0)
!           channel_gui_register(channel);
  }
  
      static void
! channel_gui_unregister(channel_T *channel)
  {
-     /* TODO: pipes */
  # ifdef FEAT_GUI_X11
!     if (channel->ch_inputHandler != (XtInputId)NULL)
      {
!       XtRemoveInput(channel->ch_inputHandler);
!       channel->ch_inputHandler = (XtInputId)NULL;
      }
  # else
  #  ifdef FEAT_GUI_GTK
!     if (channel->ch_inputHandler != 0)
      {
!       gdk_input_remove(channel->ch_inputHandler);
!       channel->ch_inputHandler = 0;
      }
  #  else
  #   ifdef FEAT_GUI_W32
!     if (channel->ch_inputHandler == 0)
      {
!       WSAAsyncSelect(channel->ch_sock, s_hwnd, 0, 0);
!       channel->ch_inputHandler = -1;
      }
  #   endif
  #  endif
  # endif
  }
  
  #endif
  
  /*
--- 382,431 ----
      channel_T *channel;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
!       channel_gui_register(channel);
  }
  
      static void
! channel_gui_unregister_one(channel_T *channel, int which)
  {
  # ifdef FEAT_GUI_X11
!     if (channel->ch_pfd[which].ch_inputHandler != (XtInputId)NULL)
      {
!       XtRemoveInput(channel->ch_pfd[which].ch_inputHandler);
!       channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
      }
  # else
  #  ifdef FEAT_GUI_GTK
!     if (channel->ch_pfd[which].ch_inputHandler != 0)
      {
!       gdk_input_remove(channel->ch_pfd[which].ch_inputHandler);
!       channel->ch_pfd[which].ch_inputHandler = 0;
      }
  #  else
  #   ifdef FEAT_GUI_W32
!     if (channel->ch_pfd[which].ch_inputHandler == 0)
      {
!       WSAAsyncSelect(channel->ch_pfd[which].ch_fd, s_hwnd, 0, 0);
!       channel->ch_pfd[which].ch_inputHandler = -1;
      }
  #   endif
  #  endif
  # endif
  }
  
+     static void
+ channel_gui_unregister(channel_T *channel)
+ {
+     if (channel->ch_pfd[CHAN_SOCK].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_SOCK);
+ # ifdef CHANNEL_PIPES
+     if (channel->ch_pfd[CHAN_OUT].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_OUT);
+     if (channel->ch_pfd[CHAN_ERR].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_ERR);
+ # endif
+ }
+ 
  #endif
  
  /*
***************
*** 440,445 ****
--- 464,470 ----
      {
        ch_error(NULL, "in socket() in channel_open().\n");
        PERROR("E898: socket() in channel_open()");
+       channel_free(channel);
        return NULL;
      }
  
***************
*** 453,458 ****
--- 478,484 ----
        ch_error(NULL, "in gethostbyname() in channel_open()\n");
        PERROR("E901: gethostbyname() in channel_open()");
        sock_close(sd);
+       channel_free(channel);
        return NULL;
      }
      memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
***************
*** 472,477 ****
--- 498,504 ----
            ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
                                                                       errno);
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
      }
***************
*** 492,497 ****
--- 519,525 ----
                                                                       errno);
            PERROR(_("E902: Cannot connect to port"));
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
      }
***************
*** 513,524 ****
--- 541,554 ----
                                                                       errno);
            PERROR(_("E902: Cannot connect to port"));
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
        if (!FD_ISSET(sd, &wfds))
        {
            /* don't give an error, we just timed out. */
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
      }
***************
*** 542,547 ****
--- 572,578 ----
            SOCK_ERRNO;
            ch_log(NULL, "socket() retry in channel_open()\n");
            PERROR("E900: socket() retry in channel_open()");
+           channel_free(channel);
            return NULL;
        }
        if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
***************
*** 575,586 ****
                ch_error(NULL, "Cannot connect to port after retry\n");
                PERROR(_("E899: Cannot connect to port after retry2"));
                sock_close(sd);
                return NULL;
            }
        }
      }
  
!     channel->ch_sock = sd;
      channel->ch_close_cb = close_cb;
  
  #ifdef FEAT_GUI
--- 606,618 ----
                ch_error(NULL, "Cannot connect to port after retry\n");
                PERROR(_("E899: Cannot connect to port after retry2"));
                sock_close(sd);
+               channel_free(channel);
                return NULL;
            }
        }
      }
  
!     channel->CH_SOCK = sd;
      channel->ch_close_cb = close_cb;
  
  #ifdef FEAT_GUI
***************
*** 594,602 ****
      void
  channel_set_pipes(channel_T *channel, int in, int out, int err)
  {
!     channel->ch_in = in;
!     channel->ch_out = out;
!     channel->ch_err = err;
  }
  #endif
  
--- 626,634 ----
      void
  channel_set_pipes(channel_T *channel, int in, int out, int err)
  {
!     channel->CH_IN = in;
!     channel->CH_OUT = out;
!     channel->CH_ERR = err;
  }
  #endif
  
***************
*** 1115,1123 ****
      int
  channel_can_write_to(channel_T *channel)
  {
!     return channel != NULL && (channel->ch_sock >= 0
  #ifdef CHANNEL_PIPES
!                         || channel->ch_in >= 0
  #endif
                          );
  }
--- 1147,1155 ----
      int
  channel_can_write_to(channel_T *channel)
  {
!     return channel != NULL && (channel->CH_SOCK >= 0
  #ifdef CHANNEL_PIPES
!                         || channel->CH_IN >= 0
  #endif
                          );
  }
***************
*** 1129,1139 ****
      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
                          );
  }
--- 1161,1171 ----
      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
                          );
  }
***************
*** 1160,1169 ****
  {
      ch_log(channel, "Closing channel");
  
!     if (channel->ch_sock >= 0)
      {
!       sock_close(channel->ch_sock);
!       channel->ch_sock = -1;
        channel->ch_close_cb = NULL;
  #ifdef FEAT_GUI
        channel_gui_unregister(channel);
--- 1192,1201 ----
  {
      ch_log(channel, "Closing channel");
  
!     if (channel->CH_SOCK >= 0)
      {
!       sock_close(channel->CH_SOCK);
!       channel->CH_SOCK = -1;
        channel->ch_close_cb = NULL;
  #ifdef FEAT_GUI
        channel_gui_unregister(channel);
***************
*** 1172,1191 ****
        channel->ch_callback = NULL;
      }
  #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
      channel_clear(channel);
--- 1204,1223 ----
        channel->ch_callback = NULL;
      }
  #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
      channel_clear(channel);
***************
*** 1351,1367 ****
  
  /*
   * Get the file descriptor to read from, either the socket or stdout.
   */
      static int
! get_read_fd(channel_T *channel, int use_stderr)
  {
!     if (channel->ch_sock >= 0)
!       return channel->ch_sock;
  #if defined(CHANNEL_PIPES)
!     if (!use_stderr && channel->ch_out >= 0)
!       return channel->ch_out;
!     if (use_stderr && channel->ch_err >= 0)
!       return channel->ch_err;
  #endif
      ch_error(channel, "channel_read() called while socket is closed\n");
      return -1;
--- 1383,1398 ----
  
  /*
   * Get the file descriptor to read from, either the socket or stdout.
+  * TODO: never gets 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;
***************
*** 1369,1378 ****
  
  /*
   * Read from channel "channel" for as long as there is something to read.
   * The data is put in the read queue.
   */
      void
! channel_read(channel_T *channel, int use_stderr, char *func)
  {
      static char_u     *buf = NULL;
      int                       len = 0;
--- 1400,1410 ----
  
  /*
   * Read from channel "channel" for as long as there is something to read.
+  * "which" is CHAN_SOCK, CHAN_OUT or CHAN_ERR.  When -1 guess.
   * The data is put in the read queue.
   */
      void
! channel_read(channel_T *channel, int which, char *func)
  {
      static char_u     *buf = NULL;
      int                       len = 0;
***************
*** 1380,1389 ****
      int                       fd;
      int                       use_socket = FALSE;
  
!     fd = get_read_fd(channel, use_stderr);
      if (fd < 0)
        return;
!     use_socket = channel->ch_sock >= 0;
  
      /* Allocate a buffer to read into. */
      if (buf == NULL)
--- 1412,1424 ----
      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;
  
      /* Allocate a buffer to read into. */
      if (buf == NULL)
***************
*** 1450,1456 ****
        else
        {
            close(fd);
!           channel->ch_out = -1;
        }
  #endif
  
--- 1485,1491 ----
        else
        {
            close(fd);
!           channel->CH_OUT = -1;
        }
  #endif
  
***************
*** 1480,1492 ****
      ch_log(channel, "Reading raw\n");
      if (channel_peek(channel) == NULL)
      {
!       int fd = get_read_fd(channel, FALSE);
  
        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, FALSE, "channel_read_block");
      }
  
      /* TODO: only get the first message */
--- 1515,1528 ----
      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");
      }
  
      /* TODO: only get the first message */
***************
*** 1526,1536 ****
                continue;
  
            /* Wait for up to the channel timeout. */
!           fd = get_read_fd(channel, FALSE);
            if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout)
                                                                      == FAIL)
                break;
!           channel_read(channel, FALSE, "channel_read_json_block");
        }
      }
      channel->ch_block_id = 0;
--- 1562,1572 ----
                continue;
  
            /* 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");
        }
      }
      channel->ch_block_id = 0;
***************
*** 1539,1562 ****
  
  # if defined(WIN32) || defined(PROTO)
  /*
!  * Lookup the channel from the socket.
   * Returns NULL when the socket isn't found.
   */
      channel_T *
! channel_fd2channel(sock_T fd)
  {
!     channel_T *channel;
  
      if (fd >= 0)
        for (channel = first_channel; channel != NULL;
                                                   channel = channel->ch_next)
!           if (channel->ch_sock == fd
! #  if defined(CHANNEL_PIPES)
!                   || channel->ch_out == fd
!                   || channel->ch_err == fd
  #  endif
!                   )
!               return channel;
      return NULL;
  }
  # endif
--- 1575,1602 ----
  
  # if defined(WIN32) || defined(PROTO)
  /*
!  * Lookup the channel from the socket.  Set "which" to the fd index.
   * Returns NULL when the socket isn't found.
   */
      channel_T *
! channel_fd2channel(sock_T fd, int *whichp)
  {
!     channel_T *channel;
!     int               i;
  
      if (fd >= 0)
        for (channel = first_channel; channel != NULL;
                                                   channel = channel->ch_next)
! #  ifdef CHANNEL_PIPES
!           for (i = CHAN_SOCK; i < CHAN_IN; ++i)
! #  else
!           i = CHAN_SOCK;
  #  endif
!               if (channel->ch_pfd[i].ch_fd == fd)
!               {
!                   *whichp = i;
!                   return channel
!               }
      return NULL;
  }
  # endif
***************
*** 1574,1587 ****
      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)
      {
--- 1614,1627 ----
      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)
      {
***************
*** 1631,1674 ****
      int
  channel_poll_setup(int nfd_in, void *fds_in)
  {
!     int nfd = nfd_in;
!     channel_T *channel;
!     struct pollfd *fds = fds_in;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-     {
-       if (channel->ch_sock >= 0)
-       {
-           channel->ch_sock_idx = nfd;
-           fds[nfd].fd = channel->ch_sock;
-           fds[nfd].events = POLLIN;
-           nfd++;
-       }
-       else
-           channel->ch_sock_idx = -1;
- 
  #  ifdef CHANNEL_PIPES
!       if (channel->ch_out >= 0)
!       {
!           channel->ch_out_idx = nfd;
!           fds[nfd].fd = channel->ch_out;
!           fds[nfd].events = POLLIN;
!           nfd++;
!       }
!       else
!           channel->ch_out_idx = -1;
! 
!       if (channel->ch_err >= 0)
!       {
!           channel->ch_err_idx = nfd;
!           fds[nfd].fd = channel->ch_err;
!           fds[nfd].events = POLLIN;
!           nfd++;
!       }
!       else
!           channel->ch_err_idx = -1;
  #  endif
!     }
  
      return nfd;
  }
--- 1671,1696 ----
      int
  channel_poll_setup(int nfd_in, void *fds_in)
  {
!     int               nfd = nfd_in;
!     channel_T *channel;
!     struct    pollfd *fds = fds_in;
!     int               which;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
  #  ifdef CHANNEL_PIPES
!       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
! #  else
!       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;
!               fds[nfd].events = POLLIN;
!               nfd++;
!           }
!           else
!               channel->ch_pfd[which].ch_poll_idx = -1;
  
      return nfd;
  }
***************
*** 1679,1711 ****
      int
  channel_poll_check(int ret_in, void *fds_in)
  {
!     int ret = ret_in;
!     channel_T *channel;
!     struct pollfd *fds = fds_in;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-     {
-       if (ret > 0 && channel->ch_sock_idx != -1
-                            && fds[channel->ch_sock_idx].revents & POLLIN)
-       {
-           channel_read(channel, FALSE, "channel_poll_check");
-           --ret;
-       }
  #  ifdef CHANNEL_PIPES
!       if (ret > 0 && channel->ch_out_idx != -1
!                              && fds[channel->ch_out_idx].revents & POLLIN)
!       {
!           channel_read(channel, FALSE, "channel_poll_check");
!           --ret;
!       }
!       if (ret > 0 && channel->ch_err_idx != -1
!                              && fds[channel->ch_err_idx].revents & POLLIN)
        {
!           channel_read(channel, TRUE, "channel_poll_check");
!           --ret;
        }
- #  endif
-     }
  
      return ret;
  }
--- 1701,1726 ----
      int
  channel_poll_check(int ret_in, void *fds_in)
  {
!     int               ret = ret_in;
!     channel_T *channel;
!     struct    pollfd *fds = fds_in;
!     int               which;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
  #  ifdef CHANNEL_PIPES
!       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
! #  else
!       which = CHAN_SOCK;
! #  endif
        {
!           int idx = channel->ch_pfd[which].ch_poll_idx;
! 
!           if (ret > 0 && idx != -1 && fds[idx].revents & POLLIN)
!           {
!               channel_read(channel, which, "channel_poll_check");
!               --ret;
!           }
        }
  
      return ret;
  }
***************
*** 1718,1750 ****
      int
  channel_select_setup(int maxfd_in, void *rfds_in)
  {
!     int           maxfd = maxfd_in;
!     channel_T *channel;
!     fd_set  *rfds = rfds_in;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-     {
-       if (channel->ch_sock >= 0)
-       {
-           FD_SET(channel->ch_sock, rfds);
-           if (maxfd < channel->ch_sock)
-               maxfd = channel->ch_sock;
-       }
  #  ifdef CHANNEL_PIPES
!       if (channel->ch_out >= 0)
!       {
!           FD_SET(channel->ch_out, rfds);
!           if (maxfd < channel->ch_out)
!               maxfd = channel->ch_out;
!       }
!       if (channel->ch_err >= 0)
        {
!           FD_SET(channel->ch_err, rfds);
!           if (maxfd < channel->ch_err)
!               maxfd = channel->ch_err;
        }
- #  endif
-     }
  
      return maxfd;
  }
--- 1733,1759 ----
      int
  channel_select_setup(int maxfd_in, void *rfds_in)
  {
!     int               maxfd = maxfd_in;
!     channel_T *channel;
!     fd_set    *rfds = rfds_in;
!     int               which;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
  #  ifdef CHANNEL_PIPES
!       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
! #  else
!       which = CHAN_SOCK;
! #  endif
        {
!           sock_T fd = channel->ch_pfd[which].ch_fd;
! 
!           if (fd >= 0)
!           {
!               FD_SET(fd, rfds);
!               if (maxfd < fd)
!                   maxfd = fd;
!           }
        }
  
      return maxfd;
  }
***************
*** 1755,1787 ****
      int
  channel_select_check(int ret_in, void *rfds_in)
  {
!     int           ret = ret_in;
!     channel_T *channel;
!     fd_set  *rfds = rfds_in;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-     {
-       if (ret > 0 && channel->ch_sock >= 0
-                                      && FD_ISSET(channel->ch_sock, rfds))
-       {
-           channel_read(channel, FALSE, "channel_select_check");
-           --ret;
-       }
  #  ifdef CHANNEL_PIPES
!       if (ret > 0 && channel->ch_out >= 0
!                                      && FD_ISSET(channel->ch_out, rfds))
!       {
!           channel_read(channel, FALSE, "channel_select_check");
!           --ret;
!       }
!       if (ret > 0 && channel->ch_err >= 0
!                                      && FD_ISSET(channel->ch_err, rfds))
        {
!           channel_read(channel, TRUE, "channel_select_check");
!           --ret;
        }
- #  endif
-     }
  
      return ret;
  }
--- 1764,1789 ----
      int
  channel_select_check(int ret_in, void *rfds_in)
  {
!     int               ret = ret_in;
!     channel_T *channel;
!     fd_set    *rfds = rfds_in;
!     int               which;
  
      for (channel = first_channel; channel != NULL; channel = channel->ch_next)
  #  ifdef CHANNEL_PIPES
!       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
! #  else
!       which = CHAN_SOCK;
! #  endif
        {
!           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;
!           }
        }
  
      return ret;
  }
*** ../vim-7.4.1317/src/eval.c  2016-02-13 23:50:03.743961279 +0100
--- src/eval.c  2016-02-14 00:11:04.998605012 +0100
***************
*** 9970,9981 ****
      channel = channel_open((char *)address, port, waittime, NULL);
      if (channel != NULL)
      {
        channel_set_json_mode(channel, ch_mode);
        channel_set_timeout(channel, timeout);
        if (callback != NULL && *callback != NUL)
            channel_set_callback(channel, callback);
      }
-     rettv->vval.v_channel = channel;
  }
  
  /*
--- 9970,9981 ----
      channel = channel_open((char *)address, port, waittime, NULL);
      if (channel != NULL)
      {
+       rettv->vval.v_channel = channel;
        channel_set_json_mode(channel, ch_mode);
        channel_set_timeout(channel, timeout);
        if (callback != NULL && *callback != NUL)
            channel_set_callback(channel, callback);
      }
  }
  
  /*
*** ../vim-7.4.1317/src/os_unix.c       2016-02-13 23:28:17.637753771 +0100
--- src/os_unix.c       2016-02-14 13:42:05.002296825 +0100
***************
*** 5116,5125 ****
--- 5116,5130 ----
      close(fd_err[1]);
      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
  
      return;
  
  failed:
+     if (channel != NULL)
+       channel_free(channel);
      if (fd_in[0] >= 0)
      {
        close(fd_in[0]);
*** ../vim-7.4.1317/src/os_win32.c      2016-02-12 19:30:20.353885756 +0100
--- src/os_win32.c      2016-02-14 13:44:21.720867994 +0100
***************
*** 5039,5050 ****
      STARTUPINFO               si;
      PROCESS_INFORMATION       pi;
      HANDLE            jo;
  
      jo = CreateJobObject(NULL, NULL);
      if (jo == NULL)
      {
        job->jv_status = JOB_FAILED;
!       return;
      }
  
      ZeroMemory(&pi, sizeof(pi));
--- 5039,5057 ----
      STARTUPINFO               si;
      PROCESS_INFORMATION       pi;
      HANDLE            jo;
+ #ifdef FEAT_CHANNEL
+     channel_T *channel;
+ 
+     channel = add_channel();
+     if (channel == NULL)
+       return;
+ #endif
  
      jo = CreateJobObject(NULL, NULL);
      if (jo == NULL)
      {
        job->jv_status = JOB_FAILED;
!       goto failed;
      }
  
      ZeroMemory(&pi, sizeof(pi));
***************
*** 5062,5083 ****
      {
        CloseHandle(jo);
        job->jv_status = JOB_FAILED;
      }
!     else
      {
!       if (!AssignProcessToJobObject(jo, pi.hProcess))
!       {
!           /* if failing, switch the way to terminate
!            * process with TerminateProcess. */
!           CloseHandle(jo);
!           jo = NULL;
!       }
!       ResumeThread(pi.hThread);
!       CloseHandle(job->jv_proc_info.hThread);
!       job->jv_proc_info = pi;
!       job->jv_job_object = jo;
!       job->jv_status = JOB_STARTED;
      }
  }
  
      char *
--- 5069,5108 ----
      {
        CloseHandle(jo);
        job->jv_status = JOB_FAILED;
+       goto failed;
      }
! 
!     if (!AssignProcessToJobObject(jo, pi.hProcess))
      {
!       /* if failing, switch the way to terminate
!        * process with TerminateProcess. */
!       CloseHandle(jo);
!       jo = NULL;
      }
+     ResumeThread(pi.hThread);
+     CloseHandle(job->jv_proc_info.hThread);
+     job->jv_proc_info = pi;
+     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);
+ #endif
  }
  
      char *
*** ../vim-7.4.1317/src/gui_w48.c       2016-02-13 23:22:35.093363549 +0100
--- src/gui_w48.c       2016-02-14 14:07:47.998167014 +0100
***************
*** 1780,1793 ****
  #ifdef FEAT_CHANNEL
      if (msg.message == WM_NETBEANS)
      {
!       channel_T *channel = channel_fd2channel((sock_T)msg.wParam);
  
        if (channel != NULL)
        {
            /* Disable error messages, they can mess up the display and throw
             * an exception. */
            ++emsg_off;
!           channel_read(channel, FALSE, "process_message");
            --emsg_off;
        }
        return;
--- 1780,1794 ----
  #ifdef FEAT_CHANNEL
      if (msg.message == WM_NETBEANS)
      {
!       int         what;
!       channel_T   *channel = channel_fd2channel((sock_T)msg.wParam, &what);
  
        if (channel != NULL)
        {
            /* Disable error messages, they can mess up the display and throw
             * an exception. */
            ++emsg_off;
!           channel_read(channel, what, "process_message");
            --emsg_off;
        }
        return;
*** ../vim-7.4.1317/src/proto/channel.pro       2016-02-13 23:22:35.093363549 
+0100
--- src/proto/channel.pro       2016-02-14 14:29:38.320487534 +0100
***************
*** 2,7 ****
--- 2,8 ----
  void ch_logfile(FILE *file);
  channel_T *add_channel(void);
  void channel_free(channel_T *channel);
+ 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);
***************
*** 21,30 ****
  void channel_clear(channel_T *channel);
  void channel_free_all(void);
  int channel_get_id(void);
! void channel_read(channel_T *channel, int use_stderr, char *func);
  char_u *channel_read_block(channel_T *channel);
  int channel_read_json_block(channel_T *channel, int id, typval_T **rettv);
! channel_T *channel_fd2channel(sock_T fd);
  int channel_send(channel_T *channel, char_u *buf, char *fun);
  int channel_poll_setup(int nfd_in, void *fds_in);
  int channel_poll_check(int ret_in, void *fds_in);
--- 22,31 ----
  void channel_clear(channel_T *channel);
  void channel_free_all(void);
  int channel_get_id(void);
! void channel_read(channel_T *channel, int what, char *func);
  char_u *channel_read_block(channel_T *channel);
  int channel_read_json_block(channel_T *channel, int id, typval_T **rettv);
! channel_T *channel_fd2channel(sock_T fd, int *what);
  int channel_send(channel_T *channel, char_u *buf, char *fun);
  int channel_poll_setup(int nfd_in, void *fds_in);
  int channel_poll_check(int ret_in, void *fds_in);
*** ../vim-7.4.1317/src/version.c       2016-02-14 00:19:55.088992301 +0100
--- src/version.c       2016-02-14 19:06:22.015378080 +0100
***************
*** 749,750 ****
--- 749,752 ----
  {   /* Add new patch number below this line */
+ /**/
+     1318,
  /**/

-- 
Emacs is a nice OS - but it lacks a good text editor.
That's why I am using Vim.  --Anonymous

 /// 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