forked from aniani/vim
patch 7.4.1318
Problem: Channel with pipes doesn't work in GUI. Solution: Register input handlers for pipes.
This commit is contained in:
404
src/channel.c
404
src/channel.c
@@ -213,6 +213,7 @@ static int next_ch_id = 0;
|
||||
channel_T *
|
||||
add_channel(void)
|
||||
{
|
||||
int which;
|
||||
channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
|
||||
|
||||
if (channel == NULL)
|
||||
@@ -221,21 +222,23 @@ add_channel(void)
|
||||
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;
|
||||
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_inputHandler = (XtInputId)NULL;
|
||||
channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
|
||||
#endif
|
||||
#ifdef FEAT_GUI_GTK
|
||||
channel->ch_inputHandler = 0;
|
||||
channel->ch_pfd[which].ch_inputHandler = 0;
|
||||
#endif
|
||||
#ifdef FEAT_GUI_W32
|
||||
channel->ch_inputHandler = -1;
|
||||
channel->ch_pfd[which].ch_inputHandler = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
channel->ch_timeout = 2000;
|
||||
|
||||
@@ -290,7 +293,7 @@ channel_read_netbeans(int id)
|
||||
if (channel == NULL)
|
||||
ch_errorn(NULL, "Channel %d not found", id);
|
||||
else
|
||||
channel_read(channel, FALSE, "messageFromNetbeans");
|
||||
channel_read(channel, -1, "messageFromNetbeans");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -318,43 +321,54 @@ messageFromNetbeans(gpointer clientData,
|
||||
#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;
|
||||
|
||||
/* 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
|
||||
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
|
||||
}
|
||||
|
||||
@@ -368,37 +382,47 @@ channel_gui_register_all(void)
|
||||
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_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)
|
||||
{
|
||||
/* 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
|
||||
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
|
||||
}
|
||||
|
||||
@@ -440,6 +464,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
{
|
||||
ch_error(NULL, "in socket() in channel_open().\n");
|
||||
PERROR("E898: socket() in channel_open()");
|
||||
channel_free(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -453,6 +478,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
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,6 +498,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
|
||||
errno);
|
||||
sock_close(sd);
|
||||
channel_free(channel);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -492,6 +519,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
errno);
|
||||
PERROR(_("E902: Cannot connect to port"));
|
||||
sock_close(sd);
|
||||
channel_free(channel);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -513,12 +541,14 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
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,6 +572,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
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,12 +606,13 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
||||
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_SOCK = sd;
|
||||
channel->ch_close_cb = close_cb;
|
||||
|
||||
#ifdef FEAT_GUI
|
||||
@@ -594,9 +626,9 @@ 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)
|
||||
{
|
||||
channel->ch_in = in;
|
||||
channel->ch_out = out;
|
||||
channel->ch_err = err;
|
||||
channel->CH_IN = in;
|
||||
channel->CH_OUT = out;
|
||||
channel->CH_ERR = err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1115,9 +1147,9 @@ may_invoke_callback(channel_T *channel)
|
||||
int
|
||||
channel_can_write_to(channel_T *channel)
|
||||
{
|
||||
return channel != NULL && (channel->ch_sock >= 0
|
||||
return channel != NULL && (channel->CH_SOCK >= 0
|
||||
#ifdef CHANNEL_PIPES
|
||||
|| channel->ch_in >= 0
|
||||
|| channel->CH_IN >= 0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
@@ -1129,11 +1161,11 @@ channel_can_write_to(channel_T *channel)
|
||||
int
|
||||
channel_is_open(channel_T *channel)
|
||||
{
|
||||
return channel != NULL && (channel->ch_sock >= 0
|
||||
return channel != NULL && (channel->CH_SOCK >= 0
|
||||
#ifdef CHANNEL_PIPES
|
||||
|| channel->ch_in >= 0
|
||||
|| channel->ch_out >= 0
|
||||
|| channel->ch_err >= 0
|
||||
|| channel->CH_IN >= 0
|
||||
|| channel->CH_OUT >= 0
|
||||
|| channel->CH_ERR >= 0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
@@ -1160,10 +1192,10 @@ channel_close(channel_T *channel)
|
||||
{
|
||||
ch_log(channel, "Closing channel");
|
||||
|
||||
if (channel->ch_sock >= 0)
|
||||
if (channel->CH_SOCK >= 0)
|
||||
{
|
||||
sock_close(channel->ch_sock);
|
||||
channel->ch_sock = -1;
|
||||
sock_close(channel->CH_SOCK);
|
||||
channel->CH_SOCK = -1;
|
||||
channel->ch_close_cb = NULL;
|
||||
#ifdef FEAT_GUI
|
||||
channel_gui_unregister(channel);
|
||||
@@ -1172,20 +1204,20 @@ channel_close(channel_T *channel)
|
||||
channel->ch_callback = NULL;
|
||||
}
|
||||
#if defined(CHANNEL_PIPES)
|
||||
if (channel->ch_in >= 0)
|
||||
if (channel->CH_IN >= 0)
|
||||
{
|
||||
close(channel->ch_in);
|
||||
channel->ch_in = -1;
|
||||
close(channel->CH_IN);
|
||||
channel->CH_IN = -1;
|
||||
}
|
||||
if (channel->ch_out >= 0)
|
||||
if (channel->CH_OUT >= 0)
|
||||
{
|
||||
close(channel->ch_out);
|
||||
channel->ch_out = -1;
|
||||
close(channel->CH_OUT);
|
||||
channel->CH_OUT = -1;
|
||||
}
|
||||
if (channel->ch_err >= 0)
|
||||
if (channel->CH_ERR >= 0)
|
||||
{
|
||||
close(channel->ch_err);
|
||||
channel->ch_err = -1;
|
||||
close(channel->CH_ERR);
|
||||
channel->CH_ERR = -1;
|
||||
}
|
||||
#endif
|
||||
channel_clear(channel);
|
||||
@@ -1351,17 +1383,16 @@ channel_get_id(void)
|
||||
|
||||
/*
|
||||
* Get the file descriptor to read from, either the socket or stdout.
|
||||
* TODO: never gets stderr.
|
||||
*/
|
||||
static int
|
||||
get_read_fd(channel_T *channel, int use_stderr)
|
||||
get_read_fd(channel_T *channel)
|
||||
{
|
||||
if (channel->ch_sock >= 0)
|
||||
return channel->ch_sock;
|
||||
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;
|
||||
if (channel->CH_OUT >= 0)
|
||||
return channel->CH_OUT;
|
||||
#endif
|
||||
ch_error(channel, "channel_read() called while socket is closed\n");
|
||||
return -1;
|
||||
@@ -1369,10 +1400,11 @@ get_read_fd(channel_T *channel, int use_stderr)
|
||||
|
||||
/*
|
||||
* 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 use_stderr, char *func)
|
||||
channel_read(channel_T *channel, int which, char *func)
|
||||
{
|
||||
static char_u *buf = NULL;
|
||||
int len = 0;
|
||||
@@ -1380,10 +1412,13 @@ channel_read(channel_T *channel, int use_stderr, char *func)
|
||||
int fd;
|
||||
int use_socket = FALSE;
|
||||
|
||||
fd = get_read_fd(channel, use_stderr);
|
||||
if (which < 0)
|
||||
fd = get_read_fd(channel);
|
||||
else
|
||||
fd = channel->ch_pfd[which].ch_fd;
|
||||
if (fd < 0)
|
||||
return;
|
||||
use_socket = channel->ch_sock >= 0;
|
||||
use_socket = fd == channel->CH_SOCK;
|
||||
|
||||
/* Allocate a buffer to read into. */
|
||||
if (buf == NULL)
|
||||
@@ -1450,7 +1485,7 @@ channel_read(channel_T *channel, int use_stderr, char *func)
|
||||
else
|
||||
{
|
||||
close(fd);
|
||||
channel->ch_out = -1;
|
||||
channel->CH_OUT = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1480,13 +1515,14 @@ channel_read_block(channel_T *channel)
|
||||
ch_log(channel, "Reading raw\n");
|
||||
if (channel_peek(channel) == NULL)
|
||||
{
|
||||
int fd = get_read_fd(channel, FALSE);
|
||||
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, FALSE, "channel_read_block");
|
||||
channel_read(channel, -1, "channel_read_block");
|
||||
}
|
||||
|
||||
/* TODO: only get the first message */
|
||||
@@ -1526,11 +1562,11 @@ channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
|
||||
continue;
|
||||
|
||||
/* Wait for up to the channel timeout. */
|
||||
fd = get_read_fd(channel, FALSE);
|
||||
fd = get_read_fd(channel);
|
||||
if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout)
|
||||
== FAIL)
|
||||
break;
|
||||
channel_read(channel, FALSE, "channel_read_json_block");
|
||||
channel_read(channel, -1, "channel_read_json_block");
|
||||
}
|
||||
}
|
||||
channel->ch_block_id = 0;
|
||||
@@ -1539,24 +1575,28 @@ channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
|
||||
|
||||
# if defined(WIN32) || defined(PROTO)
|
||||
/*
|
||||
* Lookup the channel from the socket.
|
||||
* 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)
|
||||
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)
|
||||
if (channel->ch_sock == fd
|
||||
# if defined(CHANNEL_PIPES)
|
||||
|| channel->ch_out == fd
|
||||
|| channel->ch_err == fd
|
||||
# ifdef CHANNEL_PIPES
|
||||
for (i = CHAN_SOCK; i < CHAN_IN; ++i)
|
||||
# else
|
||||
i = CHAN_SOCK;
|
||||
# endif
|
||||
)
|
||||
return channel;
|
||||
if (channel->ch_pfd[i].ch_fd == fd)
|
||||
{
|
||||
*whichp = i;
|
||||
return channel
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
# endif
|
||||
@@ -1574,14 +1614,14 @@ channel_send(channel_T *channel, char_u *buf, char *fun)
|
||||
int fd = -1;
|
||||
int use_socket = FALSE;
|
||||
|
||||
if (channel->ch_sock >= 0)
|
||||
if (channel->CH_SOCK >= 0)
|
||||
{
|
||||
fd = channel->ch_sock;
|
||||
fd = channel->CH_SOCK;
|
||||
use_socket = TRUE;
|
||||
}
|
||||
#if defined(CHANNEL_PIPES)
|
||||
else if (channel->ch_in >= 0)
|
||||
fd = channel->ch_in;
|
||||
else if (channel->CH_IN >= 0)
|
||||
fd = channel->CH_IN;
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
@@ -1634,41 +1674,23 @@ 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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@@ -1682,29 +1704,22 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@@ -1721,29 +1736,23 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@@ -1758,29 +1767,22 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
@@ -9970,12 +9970,12 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
|
||||
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);
|
||||
}
|
||||
rettv->vval.v_channel = channel;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -1262,7 +1262,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The +job feature requires +eval and Unix or MS-Widndows.
|
||||
* The +job feature requires +eval and Unix or MS-Windows.
|
||||
*/
|
||||
#if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL)
|
||||
# define FEAT_JOB
|
||||
|
@@ -1780,14 +1780,15 @@ process_message(void)
|
||||
#ifdef FEAT_CHANNEL
|
||||
if (msg.message == WM_NETBEANS)
|
||||
{
|
||||
channel_T *channel = channel_fd2channel((sock_T)msg.wParam);
|
||||
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, FALSE, "process_message");
|
||||
channel_read(channel, what, "process_message");
|
||||
--emsg_off;
|
||||
}
|
||||
return;
|
||||
|
@@ -5116,10 +5116,15 @@ mch_start_job(char **argv, job_T *job)
|
||||
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]);
|
||||
|
@@ -5039,12 +5039,19 @@ mch_start_job(char *cmd, job_T *job)
|
||||
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;
|
||||
return;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
@@ -5062,9 +5069,9 @@ mch_start_job(char *cmd, job_T *job)
|
||||
{
|
||||
CloseHandle(jo);
|
||||
job->jv_status = JOB_FAILED;
|
||||
goto failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (!AssignProcessToJobObject(jo, pi.hProcess))
|
||||
{
|
||||
/* if failing, switch the way to terminate
|
||||
@@ -5077,7 +5084,25 @@ mch_start_job(char *cmd, job_T *job)
|
||||
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 *
|
||||
|
@@ -2,6 +2,7 @@
|
||||
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,10 +22,10 @@ char_u *channel_peek(channel_T *channel);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
@@ -1301,27 +1301,48 @@ typedef enum
|
||||
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
|
||||
#ifdef FEAT_GUI_GTK
|
||||
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 */
|
||||
|
||||
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
|
||||
chan_fd_T ch_pfd[4]; /* info for socket, in, out and err */
|
||||
|
||||
readq_T ch_head; /* dummy node, header for circular queue */
|
||||
|
||||
@@ -1330,16 +1351,6 @@ struct channel_S {
|
||||
* 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 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
|
||||
|
@@ -747,6 +747,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1318,
|
||||
/**/
|
||||
1317,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user