Patch 7.4.1182
Problem:    Still socket code intertwined with netbeans.
Solution:   Move code from netbeans.c to channel.c
Files:      src/channel.c, src/netbeans.c, src/proto/channel.pro,
            src/proto/netbeans.pro, src/gui.c, src/gui_w48.c


*** ../vim-7.4.1181/src/channel.c       2016-01-24 20:36:18.850082515 +0100
--- src/channel.c       2016-01-26 23:20:41.536676106 +0100
***************
*** 14,30 ****
  
  #if defined(FEAT_CHANNEL) || defined(PROTO)
  
  typedef struct {
!     sock_T  ch_fd;
!     int           ch_idx;
  } channel_T;
  
  static channel_T *channels = NULL;
  static int channel_count = 0;
  
  /*
   * Add a new channel slot, return the index.
!  * Returns -1 if out of space.
   */
      static int
  add_channel(void)
--- 14,119 ----
  
  #if defined(FEAT_CHANNEL) || defined(PROTO)
  
+ /*
+  * Change the zero to 1 to enable debugging.
+  * This will write a file "channel_debug.log".
+  */
+ #if 0
+ # define CHERROR(fmt, arg) cherror(fmt, arg)
+ # define CHLOG(idx, send, buf) chlog(idx, send, buf)
+ # define CHFILE "channel_debug.log"
+ 
+ static void cherror(char *fmt, char *arg);
+ static void chlog(int send, char_u *buf);
+ #else
+ # define CHERROR(fmt, arg)
+ # define CHLOG(idx, send, buf)
+ #endif
+ 
+ /* TRUE when netbeans is running with a GUI. */
+ #ifdef FEAT_GUI
+ # define CH_HAS_GUI (gui.in_use || gui.starting)
+ #endif
+ 
+ /* Note: when making changes here also adjust configure.in. */
+ #ifdef WIN32
+ /* WinSock API is separated from C API, thus we can't use read(), write(),
+  * errno... */
+ # define SOCK_ERRNO errno = WSAGetLastError()
+ # undef ECONNREFUSED
+ # define ECONNREFUSED WSAECONNREFUSED
+ # ifdef EINTR
+ #  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>
+ 
+ # include <sys/socket.h>
+ # ifdef HAVE_LIBGEN_H
+ #  include <libgen.h>
+ # endif
+ # define SOCK_ERRNO
+ # 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)
+ #endif
+ 
+ #ifdef FEAT_GUI_W32
+ extern HWND s_hwnd;                   /* Gvim's Window handle */
+ #endif
+ 
+ struct readqueue
+ {
+     char_u            *buffer;
+     struct readqueue  *next;
+     struct readqueue  *prev;
+ };
+ typedef struct readqueue queue_T;
+ 
  typedef struct {
!     sock_T  ch_fd;    /* the socket, -1 for a closed channel */
!     int           ch_idx;     /* used by channel_poll_setup() */
!     queue_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
! #ifdef FEAT_GUI_GTK
!     gint ch_inputHandler;     /* Cookie for input */
! #endif
! #ifdef FEAT_GUI_W32
!     int  ch_inputHandler = -1;        /* simply ret.value of WSAAsyncSelect() 
*/
! #endif
! 
!     void (*ch_close_cb)(void);        /* callback invoked when channel is 
closed */
  } channel_T;
  
+ /*
+  * Information about all channels.
+  * There can be gaps for closed channels, they will be reused later.
+  */
  static channel_T *channels = NULL;
  static int channel_count = 0;
  
  /*
+  * TODO: open debug file when desired.
+  */
+ FILE *debugfd = NULL;
+ 
+ /*
   * Add a new channel slot, return the index.
!  * The channel isn't actually used into ch_fd is set >= 0;
!  * Returns -1 if all channels are in use.
   */
      static int
  add_channel(void)
***************
*** 39,97 ****
                return idx;
      if (channel_count == MAX_OPEN_CHANNELS)
        return -1;
!     new_channels = (channel_T *)alloc(sizeof(channel_T) * channel_count + 1);
      if (new_channels == NULL)
        return -1;
      if (channels != NULL)
        mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
      channels = new_channels;
      channels[channel_count].ch_fd = (sock_T)-1;
  
      return channel_count++;
  }
  
! #if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
! static int netbeans_channel = -1;
  
  /*
!  * Add the netbeans socket to the channels.
!  * Return the channel index.
   */
      int
! channel_add_netbeans(sock_T fd)
  {
!     int idx = add_channel();
  
!     if (idx >= 0)
      {
!       channels[idx].ch_fd = fd;
!       netbeans_channel = idx;
      }
      return idx;
  }
  
!     void
! channel_remove_netbeans()
  {
!     channels[netbeans_channel].ch_fd = (sock_T)-1;
!     netbeans_channel = -1;
  }
  #endif
  
!     static void
  channel_read(int idx)
  {
! # ifdef FEAT_NETBEANS_INTG
!     if (idx == netbeans_channel)
!       netbeans_read();
!     else
  # endif
      {
!       ; /* TODO: read */
      }
  }
  
! #if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
  /*
   * Add open channels to the poll struct.
   * Return the adjusted struct index.
--- 128,686 ----
                return idx;
      if (channel_count == MAX_OPEN_CHANNELS)
        return -1;
!     new_channels = (channel_T *)alloc(sizeof(channel_T) * (channel_count + 
1));
      if (new_channels == NULL)
        return -1;
      if (channels != NULL)
        mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
      channels = new_channels;
+     (void)vim_memset(&channels[channel_count], 0, sizeof(channel_T));
+ 
      channels[channel_count].ch_fd = (sock_T)-1;
+ #ifdef FEAT_GUI_X11
+     channels[channel_count].ch_inputHandler = (XtInputId)NULL;
+ #endif
+ #ifdef FEAT_GUI_GTK
+     channels[channel_count].ch_inputHandler = 0;
+ #endif
+ #ifdef FEAT_GUI_W32
+     channels[channel_count].ch_inputHandler = -1;
+ #endif
  
      return channel_count++;
  }
  
! #if defined(FEAT_GUI) || defined(PROTO)
! /*
!  * Read a command from netbeans.
!  */
! #ifdef FEAT_GUI_X11
!     static void
! messageFromNetbeans(XtPointer clientData,
!                   int *unused1 UNUSED,
!                   XtInputId *unused2 UNUSED)
! {
!     channel_read((int)(long)clientData);
! }
! #endif
! 
! #ifdef FEAT_GUI_GTK
!     static void
! messageFromNetbeans(gpointer clientData,
!                   gint unused1 UNUSED,
!                   GdkInputCondition unused2 UNUSED)
! {
!     channel_read((int)(long)clientData);
! }
! #endif
! 
!     static void
! channel_gui_register(int idx)
! {
!     channel_T *channel = &channels[idx];
! 
!     if (!CH_HAS_GUI)
!       return;
! 
! # 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_fd,
!                        (XtPointer)(XtInputReadMask + XtInputExceptMask),
!                                       messageFromNetbeans, (XtPointer)idx);
! # 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_fd, (GdkInputCondition)
!                            ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
!                                   messageFromNetbeans, (gpointer)(long)idx);
! #  else
! #   ifdef FEAT_GUI_W32
!     /*
!      * Tell Windows we are interested in receiving message when there
!      * is input on the editor connection socket.
!      * TODO: change WM_NETBEANS to something related to the channel index.
!      */
!     if (channel->ch_inputHandler == -1)
!       channel->ch_inputHandler =
!           WSAAsyncSelect(channel->ch_fd, 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.
!  */
!     void
! channel_gui_register_all(void)
! {
!     int i;
! 
!     for (i = 0; i < channel_count; ++i)
!       if (channels[i].ch_fd >= 0)
!           channel_gui_register(i);
! }
! 
!     static void
! channel_gui_unregister(int idx)
! {
!     channel_T *channel = &channels[idx];
! 
! # 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(nbsock, s_hwnd, 0, 0);
!       channel->ch_inputHandler = -1;
!     }
! #   endif
! #  endif
! # endif
! }
! 
! #endif
  
  /*
!  * Open a channel to "hostname":"port".
!  * Returns the channel number for success.
!  * Returns a negative number for failure.
   */
      int
! channel_open(char *hostname, int port_in, void (*close_cb)(void))
  {
!     int                       sd;
!     struct sockaddr_in        server;
!     struct hostent *  host;
! #ifdef FEAT_GUI_W32
!     u_short           port = port_in;
! #else
!     int                       port = port_in;
! #endif
!     int                       idx;
! 
! #ifdef FEAT_GUI_W32
!     channel_init_winsock();
! #endif
  
!     idx = add_channel();
!     if (idx < 0)
      {
!       CHERROR("All channels are in use\n", "");
!       EMSG(_("E999: All channels are in use"));
!       return -1;
!     }
! 
!     if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
!     {
!       CHERROR("error in socket() in channel_open()\n", "");
!       PERROR("E999: socket() in channel_open()");
!       return -1;
!     }
! 
!     /* Get the server internet address and put into addr structure */
!     /* fill in the socket address structure and connect to server */
!     vim_memset((char *)&server, 0, sizeof(server));
!     server.sin_family = AF_INET;
!     server.sin_port = htons(port);
!     if ((host = gethostbyname(hostname)) == NULL)
!     {
!       CHERROR("error in gethostbyname() in channel_open()\n", "");
!       PERROR("E999: gethostbyname() in channel_open()");
!       sock_close(sd);
!       return -1;
!     }
!     memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
! 
!     /* Connect to server */
!     if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
!     {
!       SOCK_ERRNO;
!       CHERROR("channel_open: Connect failed with errno %d\n", errno);
!       if (errno == ECONNREFUSED)
!       {
!           sock_close(sd);
!           if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
!           {
!               SOCK_ERRNO;
!               CHERROR("socket() retry in channel_open()\n", "");
!               PERROR("E999: socket() retry in channel_open()");
!               return -1;
!           }
!           if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
!           {
!               int retries = 36;
!               int success = FALSE;
! 
!               SOCK_ERRNO;
!               while (retries-- && ((errno == ECONNREFUSED)
!                                                        || (errno == EINTR)))
!               {
!                   CHERROR("retrying...\n", "");
!                   mch_delay(3000L, TRUE);
!                   ui_breakcheck();
!                   if (got_int)
!                   {
!                       errno = EINTR;
!                       break;
!                   }
!                   if (connect(sd, (struct sockaddr *)&server,
!                                                        sizeof(server)) == 0)
!                   {
!                       success = TRUE;
!                       break;
!                   }
!                   SOCK_ERRNO;
!               }
!               if (!success)
!               {
!                   /* Get here when the server can't be found. */
!                   CHERROR("Cannot connect to port after retry\n", "");
!                   PERROR(_("E999: Cannot connect to port after retry2"));
!                   sock_close(sd);
!                   return -1;
!               }
!           }
!       }
!       else
!       {
!           CHERROR("Cannot connect to port\n", "");
!           PERROR(_("E999: Cannot connect to port"));
!           sock_close(sd);
!           return -1;
!       }
      }
+ 
+     channels[idx].ch_fd = sd;
+     channels[idx].ch_close_cb = close_cb;
+ 
+ #ifdef FEAT_GUI
+     channel_gui_register(idx);
+ #endif
+ 
      return idx;
  }
  
! /*
!  * Return TRUE when channel "idx" is open.
!  */
!     int
! channel_is_open(int idx)
  {
!     return channels[idx].ch_fd >= 0;
  }
+ 
+ /*
+  * Close channel "idx".
+  * This does not trigger the close callback.
+  */
+     void
+ channel_close(int idx)
+ {
+     channel_T         *channel = &channels[idx];
+ 
+     if (channel->ch_fd >= 0)
+     {
+       sock_close(channel->ch_fd);
+       channel->ch_fd = -1;
+ #ifdef FEAT_GUI
+       channel_gui_unregister(idx);
  #endif
+     }
+ }
  
! /*
!  * Store "buf[len]" on channel "idx".
!  */
!     void
! channel_save(int idx, char_u *buf, int len)
! {
!     queue_T *node;
!     queue_T *head = &channels[idx].ch_head;
! 
!     node = (queue_T *)alloc(sizeof(queue_T));
!     if (node == NULL)
!       return;     /* out of memory */
!     node->buffer = alloc(len + 1);
!     if (node->buffer == NULL)
!     {
!       vim_free(node);
!       return;     /* out of memory */
!     }
!     mch_memmove(node->buffer, buf, (size_t)len);
!     node->buffer[len] = NUL;
! 
!     if (head->next == NULL)   /* initialize circular queue */
!     {
!       head->next = head;
!       head->prev = head;
!     }
! 
!     /* insert node at tail of queue */
!     node->next = head;
!     node->prev = head->prev;
!     head->prev->next = node;
!     head->prev = node;
! 
!     if (debugfd != NULL)
!     {
!       fprintf(debugfd, "RECV on %d: ", idx);
!       fwrite(buf, len, 1, debugfd);
!       fprintf(debugfd, "\n");
!     }
! }
! 
! /*
!  * Return the first buffer from the channel without removing it.
!  * Returns NULL if there is nothing.
!  */
!     char_u *
! channel_peek(int idx)
! {
!     queue_T *head = &channels[idx].ch_head;
! 
!     if (head->next == head || head->next == NULL)
!       return NULL;
!     return head->next->buffer;
! }
! 
! /*
!  * Return the first buffer from the channel and remove it.
!  * The caller must free it.
!  * Returns NULL if there is nothing.
!  */
!     char_u *
! channel_get(int idx)
! {
!     queue_T *head = &channels[idx].ch_head;
!     queue_T *node;
!     char_u *p;
! 
!     if (head->next == head || head->next == NULL)
!       return NULL;
!     node = head->next;
!     /* dispose of the node but keep the buffer */
!     p = node->buffer;
!     head->next = node->next;
!     node->next->prev = node->prev;
!     vim_free(node);
!     return p;
! }
! 
! /*
!  * Collapses the first and second buffer in the channel "idx".
!  * Returns FAIL if that is not possible.
!  */
!     int
! channel_collapse(int idx)
! {
!     queue_T *head = &channels[idx].ch_head;
!     queue_T *node = head->next;
!     char_u  *p;
! 
!     if (node == head || node == NULL || node->next == head)
!       return FAIL;
! 
!     p = alloc((unsigned)(STRLEN(node->buffer)
!                                          + STRLEN(node->next->buffer) + 1));
!     if (p == NULL)
!       return FAIL;        /* out of memory */
!     STRCPY(p, node->buffer);
!     STRCAT(p, node->next->buffer);
!     vim_free(node->next->buffer);
!     node->next->buffer = p;
! 
!     /* dispose of the node and buffer */
!     head->next = node->next;
!     node->next->prev = node->prev;
!     vim_free(node->buffer);
!     vim_free(node);
!     return OK;
! }
! 
! /*
!  * Clear the read buffer on channel "idx".
!  */
!     void
! channel_clear(int idx)
! {
!     queue_T *head = &channels[idx].ch_head;
!     queue_T *node = head->next;
!     queue_T *next;
! 
!     while (node != NULL && node != head)
!     {
!       next = node->next;
!       vim_free(node->buffer);
!       vim_free(node);
!       if (next == head)
!       {
!           head->next = head;
!           head->prev = head;
!           break;
!       }
!       node = next;
!     }
! }
! 
! /* Sent when the channel is found closed when reading. */
! #define DETACH_MSG "\"DETACH\"\n"
! 
! /* Buffer size for reading incoming messages. */
! #define MAXMSGSIZE 4096
! 
! /*
!  * Read from channel "idx".  The data is put in the read queue.
!  */
!     void
  channel_read(int idx)
  {
!     static char_u     *buf = NULL;
!     int                       len = 0;
!     int                       readlen = 0;
! #ifdef HAVE_SELECT
!     struct timeval    tval;
!     fd_set            rfds;
! #else
! # ifdef HAVE_POLL
!     struct pollfd     fds;
  # endif
+ #endif
+     channel_T         *channel = &channels[idx];
+ 
+     if (channel->ch_fd < 0)
+     {
+       CHLOG(idx, FALSE, "channel_read() called while socket is closed\n");
+       return;
+     }
+ 
+     /* Allocate a buffer to read into. */
+     if (buf == NULL)
      {
!       buf = alloc(MAXMSGSIZE);
!       if (buf == NULL)
!           return;     /* out of memory! */
      }
+ 
+     /* Keep on reading for as long as there is something to read.
+      * Use select() or poll() to avoid blocking on a message that is exactly
+      * MAXMSGSIZE long. */
+     for (;;)
+     {
+ #ifdef HAVE_SELECT
+       FD_ZERO(&rfds);
+       FD_SET(channel->ch_fd, &rfds);
+       tval.tv_sec = 0;
+       tval.tv_usec = 0;
+       if (select(channel->ch_fd + 1, &rfds, NULL, NULL, &tval) <= 0)
+           break;
+ #else
+ # ifdef HAVE_POLL
+       fds.fd = channel->ch_fd;
+       fds.events = POLLIN;
+       if (poll(&fds, 1, 0) <= 0)
+           break;
+ # endif
+ #endif
+       len = sock_read(channel->ch_fd, buf, MAXMSGSIZE);
+       if (len <= 0)
+           break;      /* error or nothing more to read */
+ 
+       /* Store the read message in the queue. */
+       channel_save(idx, buf, len);
+       readlen += len;
+       if (len < MAXMSGSIZE)
+           break;      /* did read everything that's available */
+     }
+ 
+     /* Reading a socket disconnection (readlen == 0), or a socket error. */
+     if (readlen <= 0)
+     {
+       /* Queue a "DETACH" netbeans message in the command queue in order to
+        * terminate the netbeans session later. Do not end the session here
+        * directly as we may be running in the context of a call to
+        * netbeans_parse_messages():
+        *      netbeans_parse_messages
+        *          -> autocmd triggered while processing the netbeans cmd
+        *              -> ui_breakcheck
+        *                  -> gui event loop or select loop
+        *                      -> channel_read()
+        */
+       channel_save(idx, (char_u *)DETACH_MSG, (int)STRLEN(DETACH_MSG));
+ 
+       channel_close(idx);
+       if (channel->ch_close_cb != NULL)
+           (*channel->ch_close_cb)();
+ 
+       if (len < 0)
+       {
+           /* Todo: which channel? */
+           CHERROR("%s(): cannot from channel\n", "channel_read");
+           PERROR(_("E999: read from channel"));
+       }
+     }
+ 
+ #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK)
+     if (CH_HAS_GUI && gtk_main_level() > 0)
+       gtk_main_quit();
+ #endif
+ }
+ 
+ /*
+  * Write "buf" (NUL terminated string) to channel "idx".
+  * When "fun" is not NULL an error message might be given.
+  */
+     void
+ channel_send(int idx, char_u *buf, char *fun)
+ {
+     channel_T *channel = &channels[idx];
+     int               len = (int)STRLEN(buf);
+ 
+     if (channel->ch_fd < 0)
+     {
+       if (!channel->ch_error && fun != NULL)
+       {
+           CHERROR("    %s(): write while not connected\n", fun);
+           EMSG2("E630: %s(): write while not connected", fun);
+       }
+       channel->ch_error = TRUE;
+     }
+     else if (sock_write(channel->ch_fd, buf, len) != len)
+     {
+       if (!channel->ch_error && fun != NULL)
+       {
+           CHERROR("    %s(): write failed\n", fun);
+           EMSG2("E631: %s(): write failed", fun);
+       }
+       channel->ch_error = TRUE;
+     }
+     else
+       channel->ch_error = FALSE;
  }
  
! # if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
  /*
   * Add open channels to the poll struct.
   * Return the adjusted struct index.
***************
*** 138,146 ****
  
      return ret;
  }
! #endif /* UNIX && !HAVE_SELECT */
  
! #if (defined(UNIX) && defined(HAVE_SELECT)) || defined(PROTO)
  /*
   * The type of "rfds" is hidden to avoid problems with the function proto.
   */
--- 727,735 ----
  
      return ret;
  }
! # endif /* UNIX && !HAVE_SELECT */
  
! # if (defined(UNIX) && defined(HAVE_SELECT)) || defined(PROTO)
  /*
   * The type of "rfds" is hidden to avoid problems with the function proto.
   */
***************
*** 182,187 ****
  
      return ret;
  }
! #endif /* UNIX && HAVE_SELECT */
  
  #endif /* FEAT_CHANNEL */
--- 771,776 ----
  
      return ret;
  }
! # endif /* UNIX && HAVE_SELECT */
  
  #endif /* FEAT_CHANNEL */
*** ../vim-7.4.1181/src/netbeans.c      2016-01-24 22:16:58.462876040 +0100
--- src/netbeans.c      2016-01-26 23:25:14.061818941 +0100
***************
*** 27,62 ****
  
  #if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
  
! /* Note: when making changes here also adjust configure.in. */
! #ifdef WIN32
! # ifdef DEBUG
! #  include <tchar.h>  /* for _T definition for TRACEn macros */
! # endif
! /* WinSock API is separated from C API, thus we can't use read(), write(),
!  * errno... */
! # define SOCK_ERRNO errno = WSAGetLastError()
! # undef ECONNREFUSED
! # define ECONNREFUSED WSAECONNREFUSED
! # ifdef EINTR
! #  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>
- 
- # include <sys/socket.h>
  # ifdef HAVE_LIBGEN_H
  #  include <libgen.h>
  # endif
- # define SOCK_ERRNO
- # 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)
  #endif
  
  #include "version.h"
--- 27,37 ----
  
  #if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
  
! #ifndef WIN32
  # include <netdb.h>
  # ifdef HAVE_LIBGEN_H
  #  include <libgen.h>
  # endif
  #endif
  
  #include "version.h"
***************
*** 83,117 ****
  static void nb_init_graphics __ARGS((void));
  static void coloncmd __ARGS((char *cmd, ...));
  static void nb_set_curbuf __ARGS((buf_T *buf));
- #ifdef FEAT_GUI_X11
- static void messageFromNetbeans __ARGS((XtPointer, int *, XtInputId *));
- #endif
- #ifdef FEAT_GUI_GTK
- static void messageFromNetbeans __ARGS((gpointer, gint, GdkInputCondition));
- #endif
  static void nb_parse_cmd __ARGS((char_u *));
  static int  nb_do_cmd __ARGS((int, char_u *, int, int, char_u *));
  static void nb_send __ARGS((char *buf, char *fun));
  static void nb_free __ARGS((void));
  
! /* TRUE when netbeans is running with a GUI. */
! #ifdef FEAT_GUI
! # define NB_HAS_GUI (gui.in_use || gui.starting)
! #endif
  
- static sock_T nbsock = -1;            /* socket fd for Netbeans connection */
- #define NETBEANS_OPEN (nbsock != -1)
- 
- #ifdef FEAT_GUI_X11
- static XtInputId inputHandler = (XtInputId)NULL;  /* Cookie for input */
- #endif
- #ifdef FEAT_GUI_GTK
- static gint inputHandler = 0;         /* Cookie for input */
- #endif
- #ifdef FEAT_GUI_W32
- static int  inputHandler = -1;                /* simply ret.value of 
WSAAsyncSelect() */
- extern HWND s_hwnd;                   /* Gvim's Window handle */
- #endif
  static int r_cmdno;                   /* current command number for reply */
  static int dosetvisible = FALSE;
  
--- 58,71 ----
  static void nb_init_graphics __ARGS((void));
  static void coloncmd __ARGS((char *cmd, ...));
  static void nb_set_curbuf __ARGS((buf_T *buf));
  static void nb_parse_cmd __ARGS((char_u *));
  static int  nb_do_cmd __ARGS((int, char_u *, int, int, char_u *));
  static void nb_send __ARGS((char *buf, char *fun));
  static void nb_free __ARGS((void));
  
! #define NETBEANS_OPEN (nb_channel_idx >= 0 && channel_is_open(nb_channel_idx))
! static int nb_channel_idx = -1;
  
  static int r_cmdno;                   /* current command number for reply */
  static int dosetvisible = FALSE;
  
***************
*** 126,173 ****
  static int inAtomic = 0;
  
  /*
!  * Close the socket and remove the input handlers.
   */
      static void
! nb_close_socket(void)
  {
!     buf_T     *buf;
! 
!     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
!       buf->b_has_sign_column = FALSE;
! 
! #ifdef FEAT_GUI_X11
!     if (inputHandler != (XtInputId)NULL)
!     {
!       XtRemoveInput(inputHandler);
!       inputHandler = (XtInputId)NULL;
!     }
! #else
! # ifdef FEAT_GUI_GTK
!     if (inputHandler != 0)
!     {
!       gdk_input_remove(inputHandler);
!       inputHandler = 0;
!     }
! # else
! #  ifdef FEAT_GUI_W32
!     if (inputHandler == 0)
!     {
!       WSAAsyncSelect(nbsock, s_hwnd, 0, 0);
!       inputHandler = -1;
!     }
! #  endif
! # endif
! #endif
! 
!     sock_close(nbsock);
!     nbsock = -1;
!     channel_remove_netbeans();
  }
  
  /*
   * Close the connection and cleanup.
!  * May be called when nb_close_socket() was called earlier.
   */
      static void
  netbeans_close(void)
--- 80,96 ----
  static int inAtomic = 0;
  
  /*
!  * Callback invoked when the channel is closed.
   */
      static void
! nb_channel_closed(void)
  {
!     nb_channel_idx = -1;
  }
  
  /*
   * Close the connection and cleanup.
!  * May be called when the socket was closed earlier.
   */
      static void
  netbeans_close(void)
***************
*** 175,181 ****
      if (NETBEANS_OPEN)
      {
        netbeans_send_disconnect();
!       nb_close_socket();
      }
  
  #ifdef FEAT_BEVAL
--- 98,107 ----
      if (NETBEANS_OPEN)
      {
        netbeans_send_disconnect();
!       if (nb_channel_idx >= 0)
!           /* Close the socket and remove the input handlers. */
!           channel_close(nb_channel_idx);
!       nb_channel_idx = -1;
      }
  
  #ifdef FEAT_BEVAL
***************
*** 209,222 ****
      static int
  netbeans_connect(char *params, int doabort)
  {
!     struct sockaddr_in        server;
!     struct hostent *  host;
! #ifdef FEAT_GUI_W32
!     u_short           port;
! #else
!     int                       port;
! #endif
!     int               sd;
      char      buf[32];
      char      *hostname = NULL;
      char      *address = NULL;
--- 135,141 ----
      static int
  netbeans_connect(char *params, int doabort)
  {
!     int               port;
      char      buf[32];
      char      *hostname = NULL;
      char      *address = NULL;
***************
*** 291,397 ****
        vim_free(password);
        password = (char *)vim_strsave((char_u *)NB_DEF_PASS);
      }
!     if (hostname == NULL || address == NULL || password == NULL)
!       goto theend;        /* out of memory */
! 
! #ifdef FEAT_GUI_W32
!     channel_init_winsock();
! #endif
! 
!     port = atoi(address);
! 
!     if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
!     {
!       nbdebug(("error in socket() in netbeans_connect()\n"));
!       PERROR("socket() in netbeans_connect()");
!       goto theend;
!     }
! 
!     /* Get the server internet address and put into addr structure */
!     /* fill in the socket address structure and connect to server */
!     vim_memset((char *)&server, '\0', sizeof(server));
!     server.sin_family = AF_INET;
!     server.sin_port = htons(port);
!     if ((host = gethostbyname(hostname)) == NULL)
!     {
!       nbdebug(("error in gethostbyname() in netbeans_connect()\n"));
!       PERROR("gethostbyname() in netbeans_connect()");
!       sock_close(sd);
!       goto theend;
!     }
!     memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
!     /* Connect to server */
!     if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
      {
!       SOCK_ERRNO;
!       nbdebug(("netbeans_connect: Connect failed with errno %d\n", errno));
!       if (errno == ECONNREFUSED)
        {
!           sock_close(sd);
!           if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
!           {
!               SOCK_ERRNO;
!               nbdebug(("socket()#2 in netbeans_connect()\n"));
!               PERROR("socket()#2 in netbeans_connect()");
!               goto theend;
!           }
!           if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
!           {
!               int retries = 36;
!               int success = FALSE;
  
!               SOCK_ERRNO;
!               while (retries-- && ((errno == ECONNREFUSED)
!                                                        || (errno == EINTR)))
!               {
!                   nbdebug(("retrying...\n"));
!                   mch_delay(3000L, TRUE);
!                   ui_breakcheck();
!                   if (got_int)
!                   {
!                       errno = EINTR;
!                       break;
!                   }
!                   if (connect(sd, (struct sockaddr *)&server,
!                                                        sizeof(server)) == 0)
!                   {
!                       success = TRUE;
!                       break;
!                   }
!                   SOCK_ERRNO;
!               }
!               if (!success)
!               {
!                   /* Get here when the server can't be found. */
!                   nbdebug(("Cannot connect to Netbeans #2\n"));
!                   PERROR(_("Cannot connect to Netbeans #2"));
!                   sock_close(sd);
!                   if (doabort)
!                       getout(1);
!                   goto theend;
!               }
!           }
!       }
!       else
!       {
!           nbdebug(("Cannot connect to Netbeans\n"));
!           PERROR(_("Cannot connect to Netbeans"));
!           sock_close(sd);
!           if (doabort)
!               getout(1);
!           goto theend;
        }
      }
  
!     nbsock = sd;
!     channel_add_netbeans(nbsock);
!     vim_snprintf(buf, sizeof(buf), "AUTH %s\n", password);
!     nb_send(buf, "netbeans_connect");
! 
!     sprintf(buf, "0:version=0 \"%s\"\n", ExtEdProtocolVersion);
!     nb_send(buf, "externaleditor_version");
  
- theend:
      vim_free(hostname);
      vim_free(address);
      vim_free(password);
--- 210,238 ----
        vim_free(password);
        password = (char *)vim_strsave((char_u *)NB_DEF_PASS);
      }
!     if (hostname != NULL && address != NULL && password != NULL)
      {
!       port = atoi(address);
!       nb_channel_idx = channel_open(hostname, port, nb_channel_closed);
!       if (nb_channel_idx >= 0)
        {
!           /* success */
! # ifdef FEAT_BEVAL
!           bevalServers |= BEVAL_NETBEANS;
! # endif
  
!           /* success, login */
!           vim_snprintf(buf, sizeof(buf), "AUTH %s\n", password);
!           nb_send(buf, "netbeans_connect");
! 
!           sprintf(buf, "0:version=0 \"%s\"\n", ExtEdProtocolVersion);
!           nb_send(buf, "externaleditor_version");
        }
      }
  
!     if (nb_channel_idx < 0 && doabort)
!       getout(1);
  
      vim_free(hostname);
      vim_free(address);
      vim_free(password);
***************
*** 532,642 ****
  }
  
  
- struct cmdqueue
- {
-     char_u        *buffer;
-     struct cmdqueue *next;
-     struct cmdqueue *prev;
- };
- 
- typedef struct cmdqueue queue_T;
- 
- static queue_T head;  /* dummy node, header for circular queue */
- 
- 
- /*
-  * Put the buffer on the work queue; possibly save it to a file as well.
-  */
-     static void
- save(char_u *buf, int len)
- {
-     queue_T *node;
- 
-     node = (queue_T *)alloc(sizeof(queue_T));
-     if (node == NULL)
-       return;     /* out of memory */
-     node->buffer = alloc(len + 1);
-     if (node->buffer == NULL)
-     {
-       vim_free(node);
-       return;     /* out of memory */
-     }
-     mch_memmove(node->buffer, buf, (size_t)len);
-     node->buffer[len] = NUL;
- 
-     if (head.next == NULL)   /* initialize circular queue */
-     {
-       head.next = &head;
-       head.prev = &head;
-     }
- 
-     /* insert node at tail of queue */
-     node->next = &head;
-     node->prev = head.prev;
-     head.prev->next = node;
-     head.prev = node;
- 
- #ifdef NBDEBUG
-     {
-       static int outfd = -2;
- 
-       /* possibly write buffer out to a file */
-       if (outfd == -3)
-           return;
- 
-       if (outfd == -2)
-       {
-           char *file = getenv("__NETBEANS_SAVE");
-           if (file == NULL)
-               outfd = -3;
-           else
-               outfd = mch_open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-       }
- 
-       if (outfd >= 0)
-           write(outfd, buf, len);
-     }
- #endif
- }
- 
- 
  /*
   * While there's still a command in the work queue, parse and execute it.
   */
      void
  netbeans_parse_messages(void)
  {
      char_u    *p;
-     queue_T   *node;
      int               own_node;
  
!     while (head.next != NULL && head.next != &head)
      {
!       node = head.next;
  
        /* Locate the first line in the first buffer. */
!       p = vim_strchr(node->buffer, '\n');
        if (p == NULL)
        {
            /* Command isn't complete.  If there is no following buffer,
             * return (wait for more). If there is another buffer following,
             * prepend the text to that buffer and delete this one.  */
!           if (node->next == &head)
                return;
-           p = alloc((unsigned)(STRLEN(node->buffer)
-                                          + STRLEN(node->next->buffer) + 1));
-           if (p == NULL)
-               return;     /* out of memory */
-           STRCPY(p, node->buffer);
-           STRCAT(p, node->next->buffer);
-           vim_free(node->next->buffer);
-           node->next->buffer = p;
- 
-           /* dispose of the node and buffer */
-           head.next = node->next;
-           node->next->prev = node->prev;
-           vim_free(node->buffer);
-           vim_free(node);
        }
        else
        {
--- 373,403 ----
  }
  
  
  /*
   * While there's still a command in the work queue, parse and execute it.
   */
      void
  netbeans_parse_messages(void)
  {
+     char_u    *buffer;
      char_u    *p;
      int               own_node;
  
!     while (nb_channel_idx >= 0)
      {
!       buffer = channel_peek(nb_channel_idx);
!       if (buffer == NULL)
!           break;      /* nothing to read */
  
        /* Locate the first line in the first buffer. */
!       p = vim_strchr(buffer, '\n');
        if (p == NULL)
        {
            /* Command isn't complete.  If there is no following buffer,
             * return (wait for more). If there is another buffer following,
             * prepend the text to that buffer and delete this one.  */
!           if (channel_collapse(nb_channel_idx) == FAIL)
                return;
        }
        else
        {
***************
*** 648,794 ****
            if (*p == NUL)
            {
                own_node = TRUE;
!               head.next = node->next;
!               node->next->prev = node->prev;
            }
            else
                own_node = FALSE;
  
            /* now, parse and execute the commands */
!           nb_parse_cmd(node->buffer);
  
            if (own_node)
!           {
!               /* buffer finished, dispose of the node and buffer */
!               vim_free(node->buffer);
!               vim_free(node);
!           }
!           /* Check that "head" wasn't changed under our fingers, e.g. when a
!            * DETACH command was handled. */
!           else if (head.next == node)
!           {
!               /* more follows, move to the start */
!               STRMOVE(node->buffer, p);
!           }
        }
      }
  }
  
! /* Buffer size for reading incoming messages. */
! #define MAXMSGSIZE 4096
! 
! /*
!  * Read a command from netbeans.
!  */
! #ifdef FEAT_GUI_X11
!     static void
! messageFromNetbeans(XtPointer clientData UNUSED,
!                   int *unused1 UNUSED,
!                   XtInputId *unused2 UNUSED)
! {
!     netbeans_read();
! }
! #endif
! 
! #ifdef FEAT_GUI_GTK
!     static void
! messageFromNetbeans(gpointer clientData UNUSED,
!                   gint unused1 UNUSED,
!                   GdkInputCondition unused2 UNUSED)
! {
!     netbeans_read();
! }
! #endif
! 
! #define DETACH_MSG "DETACH\n"
! 
      void
  netbeans_read()
  {
!     static char_u     *buf = NULL;
!     int                       len = 0;
!     int                       readlen = 0;
! #ifdef HAVE_SELECT
!     struct timeval    tval;
!     fd_set            rfds;
! #else
! # ifdef HAVE_POLL
!     struct pollfd     fds;
! # endif
! #endif
! 
!     if (!NETBEANS_OPEN)
!     {
!       nbdebug(("messageFromNetbeans() called without a socket\n"));
!       return;
!     }
! 
!     /* Allocate a buffer to read into. */
!     if (buf == NULL)
!     {
!       buf = alloc(MAXMSGSIZE);
!       if (buf == NULL)
!           return;     /* out of memory! */
!     }
! 
!     /* Keep on reading for as long as there is something to read.
!      * Use select() or poll() to avoid blocking on a message that is exactly
!      * MAXMSGSIZE long. */
!     for (;;)
!     {
! #ifdef HAVE_SELECT
!       FD_ZERO(&rfds);
!       FD_SET(nbsock, &rfds);
!       tval.tv_sec = 0;
!       tval.tv_usec = 0;
!       if (select(nbsock + 1, &rfds, NULL, NULL, &tval) <= 0)
!           break;
! #else
! # ifdef HAVE_POLL
!       fds.fd = nbsock;
!       fds.events = POLLIN;
!       if (poll(&fds, 1, 0) <= 0)
!           break;
! # endif
! #endif
!       len = sock_read(nbsock, buf, MAXMSGSIZE);
!       if (len <= 0)
!           break;      /* error or nothing more to read */
! 
!       /* Store the read message in the queue. */
!       save(buf, len);
!       readlen += len;
!       if (len < MAXMSGSIZE)
!           break;      /* did read everything that's available */
!     }
! 
!     /* Reading a socket disconnection (readlen == 0), or a socket error. */
!     if (readlen <= 0)
!     {
!       /* Queue a "DETACH" netbeans message in the command queue in order to
!        * terminate the netbeans session later. Do not end the session here
!        * directly as we may be running in the context of a call to
!        * netbeans_parse_messages():
!        *      netbeans_parse_messages
!        *          -> autocmd triggered while processing the netbeans cmd
!        *              -> ui_breakcheck
!        *                  -> gui event loop or select loop
!        *                      -> netbeans_read()
!        */
!       save((char_u *)DETACH_MSG, (int)strlen(DETACH_MSG));
!       nb_close_socket();
! 
!       if (len < 0)
!       {
!           nbdebug(("read from Netbeans socket\n"));
!           PERROR(_("read from Netbeans socket"));
!       }
!     }
! 
! #if defined(NB_HAS_GUI) && defined(FEAT_GUI_GTK)
!     if (NB_HAS_GUI && gtk_main_level() > 0)
!       gtk_main_quit();
! #endif
  }
  
  /*
--- 409,438 ----
            if (*p == NUL)
            {
                own_node = TRUE;
!               channel_get(nb_channel_idx);
            }
            else
                own_node = FALSE;
  
            /* now, parse and execute the commands */
!           nb_parse_cmd(buffer);
  
            if (own_node)
!               /* buffer finished, dispose of it */
!               vim_free(buffer);
!           else
!               /* more follows, move it to the start */
!               STRMOVE(buffer, p);
        }
      }
  }
  
! /* TODO: remove */
      void
  netbeans_read()
  {
!     if (nb_channel_idx >= 0)
!       channel_read(nb_channel_idx);
  }
  
  /*
***************
*** 825,832 ****
        /* NOTREACHED */
      }
  
!     if (STRCMP(cmd, "DETACH") == 0)
      {
        /* The IDE is breaking the connection. */
        netbeans_close();
        return;
--- 469,481 ----
        /* NOTREACHED */
      }
  
!     if (STRCMP(cmd, "\"DETACH\"") == 0)
      {
+       buf_T   *buf;
+ 
+       for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+           buf->b_has_sign_column = FALSE;
+ 
        /* The IDE is breaking the connection. */
        netbeans_close();
        return;
***************
*** 923,929 ****
  nb_free()
  {
      keyQ_T *key_node = keyHead.next;
-     queue_T *cmd_node = head.next;
      nbbuf_T buf;
      int i;
  
--- 572,577 ----
***************
*** 960,978 ****
      }
  
      /* free the queued netbeans commands */
!     while (cmd_node != NULL && cmd_node != &head)
!     {
!       queue_T *next = cmd_node->next;
!       vim_free(cmd_node->buffer);
!       vim_free(cmd_node);
!       if (next == &head)
!       {
!           head.next = &head;
!           head.prev = &head;
!           break;
!       }
!       cmd_node = next;
!     }
  }
  
  /*
--- 608,615 ----
      }
  
      /* free the queued netbeans commands */
!     if (nb_channel_idx >= 0)
!       channel_clear(nb_channel_idx);
  }
  
  /*
***************
*** 1116,1155 ****
        sprintf(buf, "%d:killed=%d\n", i, r_cmdno);
        nbdebug(("EVT: %s", buf));
        /* nb_send(buf, "netbeans_end");    avoid "write failed" messages */
!       ignored = sock_write(nbsock, buf, (int)STRLEN(buf));
      }
  }
  
  /*
   * Send a message to netbeans.
   */
      static void
  nb_send(char *buf, char *fun)
  {
!     /* Avoid giving pages full of error messages when the other side has
!      * exited, only mention the first error until the connection works again. 
*/
!     static int did_error = FALSE;
! 
!     if (!NETBEANS_OPEN)
!     {
!       if (!did_error)
!       {
!           nbdebug(("    %s(): write while not connected\n", fun));
!           EMSG2("E630: %s(): write while not connected", fun);
!       }
!       did_error = TRUE;
!     }
!     else if (sock_write(nbsock, buf, (int)STRLEN(buf)) != (int)STRLEN(buf))
!     {
!       if (!did_error)
!       {
!           nbdebug(("    %s(): write failed\n", fun));
!           EMSG2("E631: %s(): write failed", fun);
!       }
!       did_error = TRUE;
!     }
!     else
!       did_error = FALSE;
  }
  
  /*
--- 753,771 ----
        sprintf(buf, "%d:killed=%d\n", i, r_cmdno);
        nbdebug(("EVT: %s", buf));
        /* nb_send(buf, "netbeans_end");    avoid "write failed" messages */
!       nb_send(buf, NULL);
      }
  }
  
  /*
   * Send a message to netbeans.
+  * When "fun" is NULL no error is given.
   */
      static void
  nb_send(char *buf, char *fun)
  {
!     if (nb_channel_idx >= 0)
!       channel_send(nb_channel_idx, (char_u *)buf, fun);
  }
  
  /*
***************
*** 2924,2975 ****
      return NETBEANS_OPEN;
  }
  
- #if defined(FEAT_GUI) || defined(PROTO)
- /*
-  * Register our file descriptor with the gui event handling system.
-  */
-     void
- netbeans_gui_register(void)
- {
-     if (!NB_HAS_GUI || !NETBEANS_OPEN)
-       return;
- 
- # ifdef FEAT_GUI_X11
-     /* tell notifier we are interested in being called
-      * when there is input on the editor connection socket
-      */
-     if (inputHandler == (XtInputId)NULL)
-       inputHandler = XtAppAddInput((XtAppContext)app_context, nbsock,
-                        (XtPointer)(XtInputReadMask + XtInputExceptMask),
-                                              messageFromNetbeans, NULL);
- # else
- #  ifdef FEAT_GUI_GTK
-     /*
-      * Tell gdk we are interested in being called when there
-      * is input on the editor connection socket
-      */
-     if (inputHandler == 0)
-       inputHandler = gdk_input_add((gint)nbsock, (GdkInputCondition)
-           ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
-                                              messageFromNetbeans, NULL);
- #  else
- #   ifdef FEAT_GUI_W32
-     /*
-      * Tell Windows we are interested in receiving message when there
-      * is input on the editor connection socket
-      */
-     if (inputHandler == -1)
-       inputHandler = WSAAsyncSelect(nbsock, s_hwnd, WM_NETBEANS, FD_READ);
- #   endif
- #  endif
- # endif
- 
- # ifdef FEAT_BEVAL
-     bevalServers |= BEVAL_NETBEANS;
- # endif
- }
- #endif
- 
  /*
   * Tell netbeans that the window was opened, ready for commands.
   */
--- 2540,2545 ----
***************
*** 2986,2994 ****
  
      if (netbeans_connect(params, doabort) != OK)
        return;
- #ifdef FEAT_GUI
-     netbeans_gui_register();
- #endif
  
      nbdebug(("EVT: %s", cmd));
      nb_send(cmd, "netbeans_startup_done");
--- 2556,2561 ----
*** ../vim-7.4.1181/src/proto/channel.pro       2016-01-24 20:36:18.854082474 
+0100
--- src/proto/channel.pro       2016-01-26 23:17:36.222619137 +0100
***************
*** 1,6 ****
  /* channel.c */
! int channel_add_netbeans(sock_T fd);
! void channel_remove_netbeans(void);
  int channel_poll_setup(int nfd_in, void *fds_in);
  int channel_poll_check(int ret_in, void *fds_in);
  int channel_select_setup(int maxfd_in, void *rfds_in);
--- 1,15 ----
  /* channel.c */
! void channel_gui_register_all(void);
! int channel_open(char *hostname, int port_in, void (*close_cb)(void));
! int channel_is_open(int idx);
! void channel_close(int idx);
! void channel_save(int idx, char_u *buf, int len);
! char_u *channel_peek(int idx);
! char_u *channel_get(int idx);
! int channel_collapse(int idx);
! void channel_clear(int idx);
! void channel_read(int idx);
! void channel_send(int idx, 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);
  int channel_select_setup(int maxfd_in, void *rfds_in);
*** ../vim-7.4.1181/src/proto/netbeans.pro      2016-01-24 20:36:18.854082474 
+0100
--- src/proto/netbeans.pro      2016-01-26 23:25:18.129776295 +0100
***************
*** 9,15 ****
  void ex_nbstart(exarg_T *eap);
  void netbeans_beval_cb(BalloonEval *beval, int state);
  int netbeans_active(void);
- void netbeans_gui_register(void);
  void netbeans_open(char *params, int doabort);
  void netbeans_send_disconnect(void);
  void netbeans_frame_moved(int new_x, int new_y);
--- 9,14 ----
*** ../vim-7.4.1181/src/gui.c   2016-01-02 22:25:40.670710107 +0100
--- src/gui.c   2016-01-26 22:21:23.945990461 +0100
***************
*** 5004,5011 ****
         * of the argument ending up after the shell prompt. */
        msg_clr_eos_force();
        gui_start();
! #ifdef FEAT_NETBEANS_INTG
!       netbeans_gui_register();
  #endif
      }
      if (!ends_excmd(*eap->arg))
--- 5004,5011 ----
         * of the argument ending up after the shell prompt. */
        msg_clr_eos_force();
        gui_start();
! #ifdef FEAT_CHANNEL
!       channel_gui_register_all();
  #endif
      }
      if (!ends_excmd(*eap->arg))

*** ../vim-7.4.1181/src/gui_w48.c       2016-01-17 20:53:07.962014779 +0100
--- src/gui_w48.c       2016-01-26 23:19:51.565200047 +0100
***************
*** 1779,1787 ****
      }
  #endif
  
! #ifdef FEAT_NETBEANS_INTG
      if (msg.message == WM_NETBEANS)
      {
        netbeans_read();
        return;
      }
--- 1779,1788 ----
      }
  #endif
  
! #ifdef FEAT_CHANNEL
      if (msg.message == WM_NETBEANS)
      {
+       /* TODO: channel_read(idx) */
        netbeans_read();
        return;
      }
*** ../vim-7.4.1181/src/version.c       2016-01-26 19:59:04.571324075 +0100
--- src/version.c       2016-01-26 23:21:40.248060546 +0100
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     1182,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
47. You are so familiar with the WWW that you find the search engines useless.

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