xref: /vim-8.2.3635/src/clientserver.c (revision 4490ec4e)
1f87a0400SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2f87a0400SBram Moolenaar  *
3f87a0400SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4f87a0400SBram Moolenaar  *
5f87a0400SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6f87a0400SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7f87a0400SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8f87a0400SBram Moolenaar  */
9f87a0400SBram Moolenaar 
10f87a0400SBram Moolenaar /*
11f87a0400SBram Moolenaar  * clientserver.c: functions for Client Server functionality
12f87a0400SBram Moolenaar  */
13f87a0400SBram Moolenaar 
14f87a0400SBram Moolenaar #include "vim.h"
15f87a0400SBram Moolenaar 
16f87a0400SBram Moolenaar #if defined(FEAT_CLIENTSERVER) || defined(PROTO)
17f87a0400SBram Moolenaar 
18f87a0400SBram Moolenaar static void cmdsrv_main(int *argc, char **argv, char_u *serverName_arg, char_u **serverStr);
19f87a0400SBram Moolenaar static char_u *serverMakeName(char_u *arg, char *cmd);
20f87a0400SBram Moolenaar 
21f87a0400SBram Moolenaar /*
22f87a0400SBram Moolenaar  * Replace termcodes such as <CR> and insert as key presses if there is room.
23f87a0400SBram Moolenaar  */
24f87a0400SBram Moolenaar     void
server_to_input_buf(char_u * str)25f87a0400SBram Moolenaar server_to_input_buf(char_u *str)
26f87a0400SBram Moolenaar {
27f87a0400SBram Moolenaar     char_u      *ptr = NULL;
28f87a0400SBram Moolenaar     char_u      *cpo_save = p_cpo;
29f87a0400SBram Moolenaar 
30f87a0400SBram Moolenaar     // Set 'cpoptions' the way we want it.
31f87a0400SBram Moolenaar     //    B set - backslashes are *not* treated specially
32f87a0400SBram Moolenaar     //    k set - keycodes are *not* reverse-engineered
33f87a0400SBram Moolenaar     //    < unset - <Key> sequences *are* interpreted
34f87a0400SBram Moolenaar     //  The last but one parameter of replace_termcodes() is TRUE so that the
35f87a0400SBram Moolenaar     //  <lt> sequence is recognised - needed for a real backslash.
36f87a0400SBram Moolenaar     p_cpo = (char_u *)"Bk";
37f87a0400SBram Moolenaar     str = replace_termcodes((char_u *)str, &ptr, REPTERM_DO_LT, NULL);
38f87a0400SBram Moolenaar     p_cpo = cpo_save;
39f87a0400SBram Moolenaar 
40f87a0400SBram Moolenaar     if (*ptr != NUL)	// trailing CTRL-V results in nothing
41f87a0400SBram Moolenaar     {
42f87a0400SBram Moolenaar 	/*
43f87a0400SBram Moolenaar 	 * Add the string to the input stream.
44f87a0400SBram Moolenaar 	 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
45f87a0400SBram Moolenaar 	 *
46f87a0400SBram Moolenaar 	 * First clear typed characters from the typeahead buffer, there could
47f87a0400SBram Moolenaar 	 * be half a mapping there.  Then append to the existing string, so
48f87a0400SBram Moolenaar 	 * that multiple commands from a client are concatenated.
49f87a0400SBram Moolenaar 	 */
50f87a0400SBram Moolenaar 	if (typebuf.tb_maplen < typebuf.tb_len)
51f87a0400SBram Moolenaar 	    del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
52f87a0400SBram Moolenaar 	(void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE);
53f87a0400SBram Moolenaar 
54f87a0400SBram Moolenaar 	// Let input_available() know we inserted text in the typeahead
55f87a0400SBram Moolenaar 	// buffer.
56f87a0400SBram Moolenaar 	typebuf_was_filled = TRUE;
57f87a0400SBram Moolenaar     }
58f87a0400SBram Moolenaar     vim_free((char_u *)ptr);
59f87a0400SBram Moolenaar }
60f87a0400SBram Moolenaar 
61f87a0400SBram Moolenaar /*
62f87a0400SBram Moolenaar  * Evaluate an expression that the client sent to a string.
63f87a0400SBram Moolenaar  */
64f87a0400SBram Moolenaar     char_u *
eval_client_expr_to_string(char_u * expr)65f87a0400SBram Moolenaar eval_client_expr_to_string(char_u *expr)
66f87a0400SBram Moolenaar {
67f87a0400SBram Moolenaar     char_u	*res;
68f87a0400SBram Moolenaar     int		save_dbl = debug_break_level;
69f87a0400SBram Moolenaar     int		save_ro = redir_off;
70f87a0400SBram Moolenaar     funccal_entry_T funccal_entry;
71f87a0400SBram Moolenaar     int		did_save_funccal = FALSE;
72f87a0400SBram Moolenaar 
73f87a0400SBram Moolenaar     // Evaluate the expression at the toplevel, don't use variables local to
74f87a0400SBram Moolenaar     // the calling function. Except when in debug mode.
75f87a0400SBram Moolenaar     if (!debug_mode)
76f87a0400SBram Moolenaar     {
77f87a0400SBram Moolenaar 	save_funccal(&funccal_entry);
78f87a0400SBram Moolenaar 	did_save_funccal = TRUE;
79f87a0400SBram Moolenaar     }
80f87a0400SBram Moolenaar 
81f87a0400SBram Moolenaar      // Disable debugging, otherwise Vim hangs, waiting for "cont" to be
82f87a0400SBram Moolenaar      // typed.
83f87a0400SBram Moolenaar     debug_break_level = -1;
84f87a0400SBram Moolenaar     redir_off = 0;
85f87a0400SBram Moolenaar     // Do not display error message, otherwise Vim hangs, waiting for "cont"
86f87a0400SBram Moolenaar     // to be typed.  Do generate errors so that try/catch works.
87f87a0400SBram Moolenaar     ++emsg_silent;
88f87a0400SBram Moolenaar 
89b171fb17SBram Moolenaar     res = eval_to_string(expr, TRUE);
90f87a0400SBram Moolenaar 
91f87a0400SBram Moolenaar     debug_break_level = save_dbl;
92f87a0400SBram Moolenaar     redir_off = save_ro;
93f87a0400SBram Moolenaar     --emsg_silent;
94f87a0400SBram Moolenaar     if (emsg_silent < 0)
95f87a0400SBram Moolenaar 	emsg_silent = 0;
96f87a0400SBram Moolenaar     if (did_save_funccal)
97f87a0400SBram Moolenaar 	restore_funccal();
98f87a0400SBram Moolenaar 
99f87a0400SBram Moolenaar     // A client can tell us to redraw, but not to display the cursor, so do
100f87a0400SBram Moolenaar     // that here.
101f87a0400SBram Moolenaar     setcursor();
102f87a0400SBram Moolenaar     out_flush_cursor(FALSE, FALSE);
103f87a0400SBram Moolenaar 
104f87a0400SBram Moolenaar     return res;
105f87a0400SBram Moolenaar }
106f87a0400SBram Moolenaar 
107f87a0400SBram Moolenaar /*
108f87a0400SBram Moolenaar  * Evaluate a command or expression sent to ourselves.
109f87a0400SBram Moolenaar  */
110f87a0400SBram Moolenaar     int
sendToLocalVim(char_u * cmd,int asExpr,char_u ** result)111f87a0400SBram Moolenaar sendToLocalVim(char_u *cmd, int asExpr, char_u **result)
112f87a0400SBram Moolenaar {
113f87a0400SBram Moolenaar     if (asExpr)
114f87a0400SBram Moolenaar     {
115f87a0400SBram Moolenaar 	char_u *ret;
116f87a0400SBram Moolenaar 
117f87a0400SBram Moolenaar 	ret = eval_client_expr_to_string(cmd);
118f87a0400SBram Moolenaar 	if (result != NULL)
119f87a0400SBram Moolenaar 	{
120f87a0400SBram Moolenaar 	    if (ret == NULL)
121f87a0400SBram Moolenaar 	    {
122f87a0400SBram Moolenaar 		char	*err = _(e_invexprmsg);
123f87a0400SBram Moolenaar 		size_t	len = STRLEN(cmd) + STRLEN(err) + 5;
124f87a0400SBram Moolenaar 		char_u	*msg;
125f87a0400SBram Moolenaar 
126f87a0400SBram Moolenaar 		msg = alloc(len);
127f87a0400SBram Moolenaar 		if (msg != NULL)
128f87a0400SBram Moolenaar 		    vim_snprintf((char *)msg, len, "%s: \"%s\"", err, cmd);
129f87a0400SBram Moolenaar 		*result = msg;
130f87a0400SBram Moolenaar 	    }
131f87a0400SBram Moolenaar 	    else
132f87a0400SBram Moolenaar 		*result = ret;
133f87a0400SBram Moolenaar 	}
134f87a0400SBram Moolenaar 	else
135f87a0400SBram Moolenaar 	    vim_free(ret);
136f87a0400SBram Moolenaar 	return ret == NULL ? -1 : 0;
137f87a0400SBram Moolenaar     }
138f87a0400SBram Moolenaar     server_to_input_buf(cmd);
139f87a0400SBram Moolenaar     return 0;
140f87a0400SBram Moolenaar }
141f87a0400SBram Moolenaar 
142f87a0400SBram Moolenaar /*
143f87a0400SBram Moolenaar  * If conversion is needed, convert "data" from "client_enc" to 'encoding' and
144f87a0400SBram Moolenaar  * return an allocated string.  Otherwise return "data".
145f87a0400SBram Moolenaar  * "*tofree" is set to the result when it needs to be freed later.
146f87a0400SBram Moolenaar  */
147f87a0400SBram Moolenaar     char_u *
serverConvert(char_u * client_enc UNUSED,char_u * data,char_u ** tofree)148f87a0400SBram Moolenaar serverConvert(
149f87a0400SBram Moolenaar     char_u *client_enc UNUSED,
150f87a0400SBram Moolenaar     char_u *data,
151f87a0400SBram Moolenaar     char_u **tofree)
152f87a0400SBram Moolenaar {
153f87a0400SBram Moolenaar     char_u	*res = data;
154f87a0400SBram Moolenaar 
155f87a0400SBram Moolenaar     *tofree = NULL;
156f87a0400SBram Moolenaar     if (client_enc != NULL && p_enc != NULL)
157f87a0400SBram Moolenaar     {
158f87a0400SBram Moolenaar 	vimconv_T	vimconv;
159f87a0400SBram Moolenaar 
160f87a0400SBram Moolenaar 	vimconv.vc_type = CONV_NONE;
161f87a0400SBram Moolenaar 	if (convert_setup(&vimconv, client_enc, p_enc) != FAIL
162f87a0400SBram Moolenaar 					      && vimconv.vc_type != CONV_NONE)
163f87a0400SBram Moolenaar 	{
164f87a0400SBram Moolenaar 	    res = string_convert(&vimconv, data, NULL);
165f87a0400SBram Moolenaar 	    if (res == NULL)
166f87a0400SBram Moolenaar 		res = data;
167f87a0400SBram Moolenaar 	    else
168f87a0400SBram Moolenaar 		*tofree = res;
169f87a0400SBram Moolenaar 	}
170f87a0400SBram Moolenaar 	convert_setup(&vimconv, NULL, NULL);
171f87a0400SBram Moolenaar     }
172f87a0400SBram Moolenaar     return res;
173f87a0400SBram Moolenaar }
174f87a0400SBram Moolenaar #endif
175f87a0400SBram Moolenaar 
176f87a0400SBram Moolenaar #if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO)
177f87a0400SBram Moolenaar 
178f87a0400SBram Moolenaar /*
179f87a0400SBram Moolenaar  * Common code for the X command server and the Win32 command server.
180f87a0400SBram Moolenaar  */
181f87a0400SBram Moolenaar 
182f87a0400SBram Moolenaar static char_u *build_drop_cmd(int filec, char **filev, int tabs, int sendReply);
183f87a0400SBram Moolenaar 
184f87a0400SBram Moolenaar /*
185f87a0400SBram Moolenaar  * Do the client-server stuff, unless "--servername ''" was used.
186f87a0400SBram Moolenaar  */
187f87a0400SBram Moolenaar     void
exec_on_server(mparm_T * parmp)188f87a0400SBram Moolenaar exec_on_server(mparm_T *parmp)
189f87a0400SBram Moolenaar {
190f87a0400SBram Moolenaar     if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL)
191f87a0400SBram Moolenaar     {
192f87a0400SBram Moolenaar # ifdef MSWIN
193f87a0400SBram Moolenaar 	// Initialise the client/server messaging infrastructure.
194f87a0400SBram Moolenaar 	serverInitMessaging();
195f87a0400SBram Moolenaar # endif
196f87a0400SBram Moolenaar 
197f87a0400SBram Moolenaar 	/*
198f87a0400SBram Moolenaar 	 * When a command server argument was found, execute it.  This may
199f87a0400SBram Moolenaar 	 * exit Vim when it was successful.  Otherwise it's executed further
200f87a0400SBram Moolenaar 	 * on.  Remember the encoding used here in "serverStrEnc".
201f87a0400SBram Moolenaar 	 */
202f87a0400SBram Moolenaar 	if (parmp->serverArg)
203f87a0400SBram Moolenaar 	{
204f87a0400SBram Moolenaar 	    cmdsrv_main(&parmp->argc, parmp->argv,
205f87a0400SBram Moolenaar 				    parmp->serverName_arg, &parmp->serverStr);
206f87a0400SBram Moolenaar 	    parmp->serverStrEnc = vim_strsave(p_enc);
207f87a0400SBram Moolenaar 	}
208f87a0400SBram Moolenaar 
209f87a0400SBram Moolenaar 	// If we're still running, get the name to register ourselves.
210f87a0400SBram Moolenaar 	// On Win32 can register right now, for X11 need to setup the
211f87a0400SBram Moolenaar 	// clipboard first, it's further down.
212f87a0400SBram Moolenaar 	parmp->servername = serverMakeName(parmp->serverName_arg,
213f87a0400SBram Moolenaar 							      parmp->argv[0]);
214f87a0400SBram Moolenaar # ifdef MSWIN
215f87a0400SBram Moolenaar 	if (parmp->servername != NULL)
216f87a0400SBram Moolenaar 	{
217f87a0400SBram Moolenaar 	    serverSetName(parmp->servername);
218f87a0400SBram Moolenaar 	    vim_free(parmp->servername);
219f87a0400SBram Moolenaar 	}
220f87a0400SBram Moolenaar # endif
221f87a0400SBram Moolenaar     }
222f87a0400SBram Moolenaar }
223f87a0400SBram Moolenaar 
224f87a0400SBram Moolenaar /*
225f87a0400SBram Moolenaar  * Prepare for running as a Vim server.
226f87a0400SBram Moolenaar  */
227f87a0400SBram Moolenaar     void
prepare_server(mparm_T * parmp)228f87a0400SBram Moolenaar prepare_server(mparm_T *parmp)
229f87a0400SBram Moolenaar {
230f87a0400SBram Moolenaar # if defined(FEAT_X11)
231f87a0400SBram Moolenaar     /*
232f87a0400SBram Moolenaar      * Register for remote command execution with :serversend and --remote
233f87a0400SBram Moolenaar      * unless there was a -X or a --servername '' on the command line.
234f87a0400SBram Moolenaar      * Only register nongui-vim's with an explicit --servername argument,
235f87a0400SBram Moolenaar      * or when compiling with autoservername.
236f87a0400SBram Moolenaar      * When running as root --servername is also required.
237f87a0400SBram Moolenaar      */
238f87a0400SBram Moolenaar     if (X_DISPLAY != NULL && parmp->servername != NULL && (
239f87a0400SBram Moolenaar #  if defined(FEAT_AUTOSERVERNAME) || defined(FEAT_GUI)
240f87a0400SBram Moolenaar 		(
241f87a0400SBram Moolenaar #   if defined(FEAT_AUTOSERVERNAME)
242f87a0400SBram Moolenaar 		    1
243f87a0400SBram Moolenaar #   else
244f87a0400SBram Moolenaar 		    gui.in_use
245f87a0400SBram Moolenaar #   endif
246f87a0400SBram Moolenaar #   ifdef UNIX
247f87a0400SBram Moolenaar 		 && getuid() != ROOT_UID
248f87a0400SBram Moolenaar #   endif
249f87a0400SBram Moolenaar 		) ||
250f87a0400SBram Moolenaar #  endif
251f87a0400SBram Moolenaar 		parmp->serverName_arg != NULL))
252f87a0400SBram Moolenaar     {
253f87a0400SBram Moolenaar 	(void)serverRegisterName(X_DISPLAY, parmp->servername);
254f87a0400SBram Moolenaar 	vim_free(parmp->servername);
255f87a0400SBram Moolenaar 	TIME_MSG("register server name");
256f87a0400SBram Moolenaar     }
257f87a0400SBram Moolenaar     else
258f87a0400SBram Moolenaar 	serverDelayedStartName = parmp->servername;
259f87a0400SBram Moolenaar # endif
260f87a0400SBram Moolenaar 
261f87a0400SBram Moolenaar     /*
262f87a0400SBram Moolenaar      * Execute command ourselves if we're here because the send failed (or
263f87a0400SBram Moolenaar      * else we would have exited above).
264f87a0400SBram Moolenaar      */
265f87a0400SBram Moolenaar     if (parmp->serverStr != NULL)
266f87a0400SBram Moolenaar     {
267f87a0400SBram Moolenaar 	char_u *p;
268f87a0400SBram Moolenaar 
269f87a0400SBram Moolenaar 	server_to_input_buf(serverConvert(parmp->serverStrEnc,
270f87a0400SBram Moolenaar 						       parmp->serverStr, &p));
271f87a0400SBram Moolenaar 	vim_free(p);
272f87a0400SBram Moolenaar     }
273f87a0400SBram Moolenaar }
274f87a0400SBram Moolenaar 
275f87a0400SBram Moolenaar     static void
cmdsrv_main(int * argc,char ** argv,char_u * serverName_arg,char_u ** serverStr)276f87a0400SBram Moolenaar cmdsrv_main(
277f87a0400SBram Moolenaar     int		*argc,
278f87a0400SBram Moolenaar     char	**argv,
279f87a0400SBram Moolenaar     char_u	*serverName_arg,
280f87a0400SBram Moolenaar     char_u	**serverStr)
281f87a0400SBram Moolenaar {
282f87a0400SBram Moolenaar     char_u	*res;
283f87a0400SBram Moolenaar     int		i;
284f87a0400SBram Moolenaar     char_u	*sname;
285f87a0400SBram Moolenaar     int		ret;
286f87a0400SBram Moolenaar     int		didone = FALSE;
287f87a0400SBram Moolenaar     int		exiterr = 0;
288f87a0400SBram Moolenaar     char	**newArgV = argv + 1;
289f87a0400SBram Moolenaar     int		newArgC = 1,
290f87a0400SBram Moolenaar 		Argc = *argc;
291f87a0400SBram Moolenaar     int		argtype;
292f87a0400SBram Moolenaar #define ARGTYPE_OTHER		0
293f87a0400SBram Moolenaar #define ARGTYPE_EDIT		1
294f87a0400SBram Moolenaar #define ARGTYPE_EDIT_WAIT	2
295f87a0400SBram Moolenaar #define ARGTYPE_SEND		3
296f87a0400SBram Moolenaar     int		silent = FALSE;
297f87a0400SBram Moolenaar     int		tabs = FALSE;
298f87a0400SBram Moolenaar # ifndef FEAT_X11
299f87a0400SBram Moolenaar     HWND	srv;
300f87a0400SBram Moolenaar # else
301f87a0400SBram Moolenaar     Window	srv;
302f87a0400SBram Moolenaar 
303f87a0400SBram Moolenaar     setup_term_clip();
304f87a0400SBram Moolenaar # endif
305f87a0400SBram Moolenaar 
306f87a0400SBram Moolenaar     sname = serverMakeName(serverName_arg, argv[0]);
307f87a0400SBram Moolenaar     if (sname == NULL)
308f87a0400SBram Moolenaar 	return;
309f87a0400SBram Moolenaar 
310f87a0400SBram Moolenaar     /*
311f87a0400SBram Moolenaar      * Execute the command server related arguments and remove them
312f87a0400SBram Moolenaar      * from the argc/argv array; We may have to return into main()
313f87a0400SBram Moolenaar      */
314f87a0400SBram Moolenaar     for (i = 1; i < Argc; i++)
315f87a0400SBram Moolenaar     {
316f87a0400SBram Moolenaar 	res = NULL;
317f87a0400SBram Moolenaar 	if (STRCMP(argv[i], "--") == 0)	// end of option arguments
318f87a0400SBram Moolenaar 	{
319f87a0400SBram Moolenaar 	    for (; i < *argc; i++)
320f87a0400SBram Moolenaar 	    {
321f87a0400SBram Moolenaar 		*newArgV++ = argv[i];
322f87a0400SBram Moolenaar 		newArgC++;
323f87a0400SBram Moolenaar 	    }
324f87a0400SBram Moolenaar 	    break;
325f87a0400SBram Moolenaar 	}
326f87a0400SBram Moolenaar 
327f87a0400SBram Moolenaar 	if (STRICMP(argv[i], "--remote-send") == 0)
328f87a0400SBram Moolenaar 	    argtype = ARGTYPE_SEND;
329f87a0400SBram Moolenaar 	else if (STRNICMP(argv[i], "--remote", 8) == 0)
330f87a0400SBram Moolenaar 	{
331f87a0400SBram Moolenaar 	    char	*p = argv[i] + 8;
332f87a0400SBram Moolenaar 
333f87a0400SBram Moolenaar 	    argtype = ARGTYPE_EDIT;
334f87a0400SBram Moolenaar 	    while (*p != NUL)
335f87a0400SBram Moolenaar 	    {
336f87a0400SBram Moolenaar 		if (STRNICMP(p, "-wait", 5) == 0)
337f87a0400SBram Moolenaar 		{
338f87a0400SBram Moolenaar 		    argtype = ARGTYPE_EDIT_WAIT;
339f87a0400SBram Moolenaar 		    p += 5;
340f87a0400SBram Moolenaar 		}
341f87a0400SBram Moolenaar 		else if (STRNICMP(p, "-silent", 7) == 0)
342f87a0400SBram Moolenaar 		{
343f87a0400SBram Moolenaar 		    silent = TRUE;
344f87a0400SBram Moolenaar 		    p += 7;
345f87a0400SBram Moolenaar 		}
346f87a0400SBram Moolenaar 		else if (STRNICMP(p, "-tab", 4) == 0)
347f87a0400SBram Moolenaar 		{
348f87a0400SBram Moolenaar 		    tabs = TRUE;
349f87a0400SBram Moolenaar 		    p += 4;
350f87a0400SBram Moolenaar 		}
351f87a0400SBram Moolenaar 		else
352f87a0400SBram Moolenaar 		{
353f87a0400SBram Moolenaar 		    argtype = ARGTYPE_OTHER;
354f87a0400SBram Moolenaar 		    break;
355f87a0400SBram Moolenaar 		}
356f87a0400SBram Moolenaar 	    }
357f87a0400SBram Moolenaar 	}
358f87a0400SBram Moolenaar 	else
359f87a0400SBram Moolenaar 	    argtype = ARGTYPE_OTHER;
360f87a0400SBram Moolenaar 
361f87a0400SBram Moolenaar 	if (argtype != ARGTYPE_OTHER)
362f87a0400SBram Moolenaar 	{
363f87a0400SBram Moolenaar 	    if (i == *argc - 1)
364f87a0400SBram Moolenaar 		mainerr_arg_missing((char_u *)argv[i]);
365f87a0400SBram Moolenaar 	    if (argtype == ARGTYPE_SEND)
366f87a0400SBram Moolenaar 	    {
367f87a0400SBram Moolenaar 		*serverStr = (char_u *)argv[i + 1];
368f87a0400SBram Moolenaar 		i++;
369f87a0400SBram Moolenaar 	    }
370f87a0400SBram Moolenaar 	    else
371f87a0400SBram Moolenaar 	    {
372f87a0400SBram Moolenaar 		*serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1,
373f87a0400SBram Moolenaar 					  tabs, argtype == ARGTYPE_EDIT_WAIT);
374f87a0400SBram Moolenaar 		if (*serverStr == NULL)
375f87a0400SBram Moolenaar 		{
376f87a0400SBram Moolenaar 		    // Probably out of memory, exit.
377f87a0400SBram Moolenaar 		    didone = TRUE;
378f87a0400SBram Moolenaar 		    exiterr = 1;
379f87a0400SBram Moolenaar 		    break;
380f87a0400SBram Moolenaar 		}
381f87a0400SBram Moolenaar 		Argc = i;
382f87a0400SBram Moolenaar 	    }
383f87a0400SBram Moolenaar # ifdef FEAT_X11
384f87a0400SBram Moolenaar 	    if (xterm_dpy == NULL)
385f87a0400SBram Moolenaar 	    {
386f87a0400SBram Moolenaar 		mch_errmsg(_("No display"));
387f87a0400SBram Moolenaar 		ret = -1;
388f87a0400SBram Moolenaar 	    }
389f87a0400SBram Moolenaar 	    else
390f87a0400SBram Moolenaar 		ret = serverSendToVim(xterm_dpy, sname, *serverStr,
391f87a0400SBram Moolenaar 						  NULL, &srv, 0, 0, 0, silent);
392f87a0400SBram Moolenaar # else
393f87a0400SBram Moolenaar 	    // Win32 always works?
394f87a0400SBram Moolenaar 	    ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, 0, silent);
395f87a0400SBram Moolenaar # endif
396f87a0400SBram Moolenaar 	    if (ret < 0)
397f87a0400SBram Moolenaar 	    {
398f87a0400SBram Moolenaar 		if (argtype == ARGTYPE_SEND)
399f87a0400SBram Moolenaar 		{
400f87a0400SBram Moolenaar 		    // Failed to send, abort.
401f87a0400SBram Moolenaar 		    mch_errmsg(_(": Send failed.\n"));
402f87a0400SBram Moolenaar 		    didone = TRUE;
403f87a0400SBram Moolenaar 		    exiterr = 1;
404f87a0400SBram Moolenaar 		}
405f87a0400SBram Moolenaar 		else if (!silent)
406f87a0400SBram Moolenaar 		    // Let vim start normally.
407f87a0400SBram Moolenaar 		    mch_errmsg(_(": Send failed. Trying to execute locally\n"));
408f87a0400SBram Moolenaar 		break;
409f87a0400SBram Moolenaar 	    }
410f87a0400SBram Moolenaar 
411f87a0400SBram Moolenaar # ifdef FEAT_GUI_MSWIN
412f87a0400SBram Moolenaar 	    // Guess that when the server name starts with "g" it's a GUI
413f87a0400SBram Moolenaar 	    // server, which we can bring to the foreground here.
414f87a0400SBram Moolenaar 	    // Foreground() in the server doesn't work very well.
415f87a0400SBram Moolenaar 	    if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G')
416f87a0400SBram Moolenaar 		SetForegroundWindow(srv);
417f87a0400SBram Moolenaar # endif
418f87a0400SBram Moolenaar 
419f87a0400SBram Moolenaar 	    /*
420f87a0400SBram Moolenaar 	     * For --remote-wait: Wait until the server did edit each
421f87a0400SBram Moolenaar 	     * file.  Also detect that the server no longer runs.
422f87a0400SBram Moolenaar 	     */
423f87a0400SBram Moolenaar 	    if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT)
424f87a0400SBram Moolenaar 	    {
425f87a0400SBram Moolenaar 		int	numFiles = *argc - i - 1;
426f87a0400SBram Moolenaar 		int	j;
427f87a0400SBram Moolenaar 		char_u  *done = alloc(numFiles);
428f87a0400SBram Moolenaar 		char_u  *p;
429f87a0400SBram Moolenaar # ifdef FEAT_GUI_MSWIN
430f87a0400SBram Moolenaar 		NOTIFYICONDATA ni;
431f87a0400SBram Moolenaar 		int	count = 0;
432f87a0400SBram Moolenaar 		extern HWND message_window;
433f87a0400SBram Moolenaar # endif
434f87a0400SBram Moolenaar 
435f87a0400SBram Moolenaar 		if (numFiles > 0 && argv[i + 1][0] == '+')
436f87a0400SBram Moolenaar 		    // Skip "+cmd" argument, don't wait for it to be edited.
437f87a0400SBram Moolenaar 		    --numFiles;
438f87a0400SBram Moolenaar 
439f87a0400SBram Moolenaar # ifdef FEAT_GUI_MSWIN
440f87a0400SBram Moolenaar 		ni.cbSize = sizeof(ni);
441f87a0400SBram Moolenaar 		ni.hWnd = message_window;
442f87a0400SBram Moolenaar 		ni.uID = 0;
443f87a0400SBram Moolenaar 		ni.uFlags = NIF_ICON|NIF_TIP;
444f87a0400SBram Moolenaar 		ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM");
445f87a0400SBram Moolenaar 		sprintf(ni.szTip, _("%d of %d edited"), count, numFiles);
446f87a0400SBram Moolenaar 		Shell_NotifyIcon(NIM_ADD, &ni);
447f87a0400SBram Moolenaar # endif
448f87a0400SBram Moolenaar 
449f87a0400SBram Moolenaar 		// Wait for all files to unload in remote
450f87a0400SBram Moolenaar 		vim_memset(done, 0, numFiles);
451f87a0400SBram Moolenaar 		while (memchr(done, 0, numFiles) != NULL)
452f87a0400SBram Moolenaar 		{
453f87a0400SBram Moolenaar # ifdef MSWIN
454f87a0400SBram Moolenaar 		    p = serverGetReply(srv, NULL, TRUE, TRUE, 0);
455f87a0400SBram Moolenaar 		    if (p == NULL)
456f87a0400SBram Moolenaar 			break;
457f87a0400SBram Moolenaar # else
458f87a0400SBram Moolenaar 		    if (serverReadReply(xterm_dpy, srv, &p, TRUE, -1) < 0)
459f87a0400SBram Moolenaar 			break;
460f87a0400SBram Moolenaar # endif
461f87a0400SBram Moolenaar 		    j = atoi((char *)p);
462f87a0400SBram Moolenaar 		    if (j >= 0 && j < numFiles)
463f87a0400SBram Moolenaar 		    {
464f87a0400SBram Moolenaar # ifdef FEAT_GUI_MSWIN
465f87a0400SBram Moolenaar 			++count;
466f87a0400SBram Moolenaar 			sprintf(ni.szTip, _("%d of %d edited"),
467f87a0400SBram Moolenaar 							     count, numFiles);
468f87a0400SBram Moolenaar 			Shell_NotifyIcon(NIM_MODIFY, &ni);
469f87a0400SBram Moolenaar # endif
470f87a0400SBram Moolenaar 			done[j] = 1;
471f87a0400SBram Moolenaar 		    }
472f87a0400SBram Moolenaar 		}
473f87a0400SBram Moolenaar # ifdef FEAT_GUI_MSWIN
474f87a0400SBram Moolenaar 		Shell_NotifyIcon(NIM_DELETE, &ni);
475f87a0400SBram Moolenaar # endif
4767d41aa88SBram Moolenaar 		vim_free(done);
477f87a0400SBram Moolenaar 	    }
478f87a0400SBram Moolenaar 	}
479f87a0400SBram Moolenaar 	else if (STRICMP(argv[i], "--remote-expr") == 0)
480f87a0400SBram Moolenaar 	{
481f87a0400SBram Moolenaar 	    if (i == *argc - 1)
482f87a0400SBram Moolenaar 		mainerr_arg_missing((char_u *)argv[i]);
483f87a0400SBram Moolenaar # ifdef MSWIN
484f87a0400SBram Moolenaar 	    // Win32 always works?
485f87a0400SBram Moolenaar 	    if (serverSendToVim(sname, (char_u *)argv[i + 1],
486f87a0400SBram Moolenaar 						  &res, NULL, 1, 0, FALSE) < 0)
487f87a0400SBram Moolenaar # else
488f87a0400SBram Moolenaar 	    if (xterm_dpy == NULL)
489f87a0400SBram Moolenaar 		mch_errmsg(_("No display: Send expression failed.\n"));
490f87a0400SBram Moolenaar 	    else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1],
491f87a0400SBram Moolenaar 					       &res, NULL, 1, 0, 1, FALSE) < 0)
492f87a0400SBram Moolenaar # endif
493f87a0400SBram Moolenaar 	    {
494f87a0400SBram Moolenaar 		if (res != NULL && *res != NUL)
495f87a0400SBram Moolenaar 		{
496f87a0400SBram Moolenaar 		    // Output error from remote
497f87a0400SBram Moolenaar 		    mch_errmsg((char *)res);
498f87a0400SBram Moolenaar 		    VIM_CLEAR(res);
499f87a0400SBram Moolenaar 		}
500f87a0400SBram Moolenaar 		mch_errmsg(_(": Send expression failed.\n"));
501f87a0400SBram Moolenaar 	    }
502f87a0400SBram Moolenaar 	}
503f87a0400SBram Moolenaar 	else if (STRICMP(argv[i], "--serverlist") == 0)
504f87a0400SBram Moolenaar 	{
505f87a0400SBram Moolenaar # ifdef MSWIN
506f87a0400SBram Moolenaar 	    // Win32 always works?
507f87a0400SBram Moolenaar 	    res = serverGetVimNames();
508f87a0400SBram Moolenaar # else
509f87a0400SBram Moolenaar 	    if (xterm_dpy != NULL)
510f87a0400SBram Moolenaar 		res = serverGetVimNames(xterm_dpy);
511f87a0400SBram Moolenaar # endif
512f87a0400SBram Moolenaar 	    if (did_emsg)
513f87a0400SBram Moolenaar 		mch_errmsg("\n");
514f87a0400SBram Moolenaar 	}
515f87a0400SBram Moolenaar 	else if (STRICMP(argv[i], "--servername") == 0)
516f87a0400SBram Moolenaar 	{
517f87a0400SBram Moolenaar 	    // Already processed. Take it out of the command line
518f87a0400SBram Moolenaar 	    i++;
519f87a0400SBram Moolenaar 	    continue;
520f87a0400SBram Moolenaar 	}
521f87a0400SBram Moolenaar 	else
522f87a0400SBram Moolenaar 	{
523f87a0400SBram Moolenaar 	    *newArgV++ = argv[i];
524f87a0400SBram Moolenaar 	    newArgC++;
525f87a0400SBram Moolenaar 	    continue;
526f87a0400SBram Moolenaar 	}
527f87a0400SBram Moolenaar 	didone = TRUE;
528f87a0400SBram Moolenaar 	if (res != NULL && *res != NUL)
529f87a0400SBram Moolenaar 	{
530f87a0400SBram Moolenaar 	    mch_msg((char *)res);
531f87a0400SBram Moolenaar 	    if (res[STRLEN(res) - 1] != '\n')
532f87a0400SBram Moolenaar 		mch_msg("\n");
533f87a0400SBram Moolenaar 	}
534f87a0400SBram Moolenaar 	vim_free(res);
535f87a0400SBram Moolenaar     }
536f87a0400SBram Moolenaar 
537f87a0400SBram Moolenaar     if (didone)
538f87a0400SBram Moolenaar     {
539f87a0400SBram Moolenaar 	display_errors();	// display any collected messages
540f87a0400SBram Moolenaar 	exit(exiterr);	// Mission accomplished - get out
541f87a0400SBram Moolenaar     }
542f87a0400SBram Moolenaar 
543f87a0400SBram Moolenaar     // Return back into main()
544f87a0400SBram Moolenaar     *argc = newArgC;
545f87a0400SBram Moolenaar     vim_free(sname);
546f87a0400SBram Moolenaar }
547f87a0400SBram Moolenaar 
548f87a0400SBram Moolenaar /*
549f87a0400SBram Moolenaar  * Build a ":drop" command to send to a Vim server.
550f87a0400SBram Moolenaar  */
551f87a0400SBram Moolenaar     static char_u *
build_drop_cmd(int filec,char ** filev,int tabs,int sendReply)552f87a0400SBram Moolenaar build_drop_cmd(
553f87a0400SBram Moolenaar     int		filec,
554f87a0400SBram Moolenaar     char	**filev,
555f87a0400SBram Moolenaar     int		tabs,		// Use ":tab drop" instead of ":drop".
556f87a0400SBram Moolenaar     int		sendReply)
557f87a0400SBram Moolenaar {
558f87a0400SBram Moolenaar     garray_T	ga;
559f87a0400SBram Moolenaar     int		i;
560f87a0400SBram Moolenaar     char_u	*inicmd = NULL;
561f87a0400SBram Moolenaar     char_u	*p;
562f87a0400SBram Moolenaar     char_u	*cdp;
563f87a0400SBram Moolenaar     char_u	*cwd;
564f87a0400SBram Moolenaar 
565f87a0400SBram Moolenaar     if (filec > 0 && filev[0][0] == '+')
566f87a0400SBram Moolenaar     {
567f87a0400SBram Moolenaar 	inicmd = (char_u *)filev[0] + 1;
568f87a0400SBram Moolenaar 	filev++;
569f87a0400SBram Moolenaar 	filec--;
570f87a0400SBram Moolenaar     }
571f87a0400SBram Moolenaar     // Check if we have at least one argument.
572f87a0400SBram Moolenaar     if (filec <= 0)
573f87a0400SBram Moolenaar 	mainerr_arg_missing((char_u *)filev[-1]);
574f87a0400SBram Moolenaar 
575f87a0400SBram Moolenaar     // Temporarily cd to the current directory to handle relative file names.
576f87a0400SBram Moolenaar     cwd = alloc(MAXPATHL);
577f87a0400SBram Moolenaar     if (cwd == NULL)
578f87a0400SBram Moolenaar 	return NULL;
579f87a0400SBram Moolenaar     if (mch_dirname(cwd, MAXPATHL) != OK)
580f87a0400SBram Moolenaar     {
581f87a0400SBram Moolenaar 	vim_free(cwd);
582f87a0400SBram Moolenaar 	return NULL;
583f87a0400SBram Moolenaar     }
584f87a0400SBram Moolenaar     cdp = vim_strsave_escaped_ext(cwd,
585f87a0400SBram Moolenaar #ifdef BACKSLASH_IN_FILENAME
586f87a0400SBram Moolenaar 	    (char_u *)"",  // rem_backslash() will tell what chars to escape
587f87a0400SBram Moolenaar #else
588f87a0400SBram Moolenaar 	    PATH_ESC_CHARS,
589f87a0400SBram Moolenaar #endif
590f87a0400SBram Moolenaar 	    '\\', TRUE);
591f87a0400SBram Moolenaar     vim_free(cwd);
592f87a0400SBram Moolenaar     if (cdp == NULL)
593f87a0400SBram Moolenaar 	return NULL;
594f87a0400SBram Moolenaar     ga_init2(&ga, 1, 100);
595f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
596f87a0400SBram Moolenaar     ga_concat(&ga, cdp);
597f87a0400SBram Moolenaar 
598f87a0400SBram Moolenaar     // Call inputsave() so that a prompt for an encryption key works.
599a9a47d15SBram Moolenaar     ga_concat(&ga, (char_u *)
600a9a47d15SBram Moolenaar 		       "<CR>:if exists('*inputsave')|call inputsave()|endif|");
601f87a0400SBram Moolenaar     if (tabs)
602f87a0400SBram Moolenaar 	ga_concat(&ga, (char_u *)"tab ");
603f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"drop");
604f87a0400SBram Moolenaar     for (i = 0; i < filec; i++)
605f87a0400SBram Moolenaar     {
606f87a0400SBram Moolenaar 	// On Unix the shell has already expanded the wildcards, don't want to
607f87a0400SBram Moolenaar 	// do it again in the Vim server.  On MS-Windows only escape
608f87a0400SBram Moolenaar 	// non-wildcard characters.
609f87a0400SBram Moolenaar 	p = vim_strsave_escaped((char_u *)filev[i],
610f87a0400SBram Moolenaar #ifdef UNIX
611f87a0400SBram Moolenaar 		PATH_ESC_CHARS
612f87a0400SBram Moolenaar #else
613f87a0400SBram Moolenaar 		(char_u *)" \t%#"
614f87a0400SBram Moolenaar #endif
615f87a0400SBram Moolenaar 		);
616f87a0400SBram Moolenaar 	if (p == NULL)
617f87a0400SBram Moolenaar 	{
618f87a0400SBram Moolenaar 	    vim_free(ga.ga_data);
619f87a0400SBram Moolenaar 	    return NULL;
620f87a0400SBram Moolenaar 	}
621f87a0400SBram Moolenaar 	ga_concat(&ga, (char_u *)" ");
622f87a0400SBram Moolenaar 	ga_concat(&ga, p);
623f87a0400SBram Moolenaar 	vim_free(p);
624f87a0400SBram Moolenaar     }
625a9a47d15SBram Moolenaar     ga_concat(&ga, (char_u *)
626a9a47d15SBram Moolenaar 		  "|if exists('*inputrestore')|call inputrestore()|endif<CR>");
627f87a0400SBram Moolenaar 
628f87a0400SBram Moolenaar     // The :drop commands goes to Insert mode when 'insertmode' is set, use
629f87a0400SBram Moolenaar     // CTRL-\ CTRL-N again.
630f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"<C-\\><C-N>");
631f87a0400SBram Moolenaar 
632f87a0400SBram Moolenaar     // Switch back to the correct current directory (prior to temporary path
633f87a0400SBram Moolenaar     // switch) unless 'autochdir' is set, in which case it will already be
634f87a0400SBram Moolenaar     // correct after the :drop command. With line breaks and spaces:
635f87a0400SBram Moolenaar     //  if !exists('+acd') || !&acd
636f87a0400SBram Moolenaar     //    if haslocaldir()
637f87a0400SBram Moolenaar     //	    cd -
638f87a0400SBram Moolenaar     //      lcd -
639f87a0400SBram Moolenaar     //    elseif getcwd() ==# 'current path'
640f87a0400SBram Moolenaar     //      cd -
641f87a0400SBram Moolenaar     //    endif
642f87a0400SBram Moolenaar     //  endif
643f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|");
644f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '");
645f87a0400SBram Moolenaar     ga_concat(&ga, cdp);
646f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>");
647f87a0400SBram Moolenaar     vim_free(cdp);
648f87a0400SBram Moolenaar 
649f87a0400SBram Moolenaar     if (sendReply)
650f87a0400SBram Moolenaar 	ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>");
651f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)":");
652f87a0400SBram Moolenaar     if (inicmd != NULL)
653f87a0400SBram Moolenaar     {
654f87a0400SBram Moolenaar 	// Can't use <CR> after "inicmd", because an "startinsert" would cause
655f87a0400SBram Moolenaar 	// the following commands to be inserted as text.  Use a "|",
656f87a0400SBram Moolenaar 	// hopefully "inicmd" does allow this...
657f87a0400SBram Moolenaar 	ga_concat(&ga, inicmd);
658f87a0400SBram Moolenaar 	ga_concat(&ga, (char_u *)"|");
659f87a0400SBram Moolenaar     }
660f87a0400SBram Moolenaar     // Bring the window to the foreground, goto Insert mode when 'im' set and
661f87a0400SBram Moolenaar     // clear command line.
662f87a0400SBram Moolenaar     ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>");
663f87a0400SBram Moolenaar     ga_append(&ga, NUL);
664f87a0400SBram Moolenaar     return ga.ga_data;
665f87a0400SBram Moolenaar }
666f87a0400SBram Moolenaar 
667f87a0400SBram Moolenaar /*
668f87a0400SBram Moolenaar  * Make our basic server name: use the specified "arg" if given, otherwise use
669f87a0400SBram Moolenaar  * the tail of the command "cmd" we were started with.
670f87a0400SBram Moolenaar  * Return the name in allocated memory.  This doesn't include a serial number.
671f87a0400SBram Moolenaar  */
672f87a0400SBram Moolenaar     static char_u *
serverMakeName(char_u * arg,char * cmd)673f87a0400SBram Moolenaar serverMakeName(char_u *arg, char *cmd)
674f87a0400SBram Moolenaar {
675f87a0400SBram Moolenaar     char_u *p;
676f87a0400SBram Moolenaar 
677f87a0400SBram Moolenaar     if (arg != NULL && *arg != NUL)
678f87a0400SBram Moolenaar 	p = vim_strsave_up(arg);
679f87a0400SBram Moolenaar     else
680f87a0400SBram Moolenaar     {
681f87a0400SBram Moolenaar 	p = vim_strsave_up(gettail((char_u *)cmd));
682f87a0400SBram Moolenaar 	// Remove .exe or .bat from the name.
683f87a0400SBram Moolenaar 	if (p != NULL && vim_strchr(p, '.') != NULL)
684f87a0400SBram Moolenaar 	    *vim_strchr(p, '.') = NUL;
685f87a0400SBram Moolenaar     }
686f87a0400SBram Moolenaar     return p;
687f87a0400SBram Moolenaar }
688f87a0400SBram Moolenaar #endif // FEAT_CLIENTSERVER
689f87a0400SBram Moolenaar 
690f87a0400SBram Moolenaar #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
691f87a0400SBram Moolenaar     static void
make_connection(void)692f87a0400SBram Moolenaar make_connection(void)
693f87a0400SBram Moolenaar {
694f87a0400SBram Moolenaar     if (X_DISPLAY == NULL
695f87a0400SBram Moolenaar # ifdef FEAT_GUI
696f87a0400SBram Moolenaar 	    && !gui.in_use
697f87a0400SBram Moolenaar # endif
698f87a0400SBram Moolenaar 	    )
699f87a0400SBram Moolenaar     {
700f87a0400SBram Moolenaar 	x_force_connect = TRUE;
701f87a0400SBram Moolenaar 	setup_term_clip();
702f87a0400SBram Moolenaar 	x_force_connect = FALSE;
703f87a0400SBram Moolenaar     }
704f87a0400SBram Moolenaar }
705f87a0400SBram Moolenaar 
706f87a0400SBram Moolenaar     static int
check_connection(void)707f87a0400SBram Moolenaar check_connection(void)
708f87a0400SBram Moolenaar {
709f87a0400SBram Moolenaar     make_connection();
710f87a0400SBram Moolenaar     if (X_DISPLAY == NULL)
711f87a0400SBram Moolenaar     {
712f87a0400SBram Moolenaar 	emsg(_("E240: No connection to the X server"));
713f87a0400SBram Moolenaar 	return FAIL;
714f87a0400SBram Moolenaar     }
715f87a0400SBram Moolenaar     return OK;
716f87a0400SBram Moolenaar }
717f87a0400SBram Moolenaar #endif
718f87a0400SBram Moolenaar 
719f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
720f87a0400SBram Moolenaar     static void
remote_common(typval_T * argvars,typval_T * rettv,int expr)721f87a0400SBram Moolenaar remote_common(typval_T *argvars, typval_T *rettv, int expr)
722f87a0400SBram Moolenaar {
723f87a0400SBram Moolenaar     char_u	*server_name;
724f87a0400SBram Moolenaar     char_u	*keys;
725f87a0400SBram Moolenaar     char_u	*r = NULL;
726f87a0400SBram Moolenaar     char_u	buf[NUMBUFLEN];
727f87a0400SBram Moolenaar     int		timeout = 0;
728f87a0400SBram Moolenaar # ifdef MSWIN
729f87a0400SBram Moolenaar     HWND	w;
730f87a0400SBram Moolenaar # else
731f87a0400SBram Moolenaar     Window	w;
732f87a0400SBram Moolenaar # endif
733f87a0400SBram Moolenaar 
734f87a0400SBram Moolenaar     if (check_restricted() || check_secure())
735f87a0400SBram Moolenaar 	return;
736f87a0400SBram Moolenaar 
737f87a0400SBram Moolenaar # ifdef FEAT_X11
738f87a0400SBram Moolenaar     if (check_connection() == FAIL)
739f87a0400SBram Moolenaar 	return;
740f87a0400SBram Moolenaar # endif
741f87a0400SBram Moolenaar     if (argvars[2].v_type != VAR_UNKNOWN
742f87a0400SBram Moolenaar 	    && argvars[3].v_type != VAR_UNKNOWN)
743f87a0400SBram Moolenaar 	timeout = tv_get_number(&argvars[3]);
744f87a0400SBram Moolenaar 
745f87a0400SBram Moolenaar     server_name = tv_get_string_chk(&argvars[0]);
746f87a0400SBram Moolenaar     if (server_name == NULL)
747f87a0400SBram Moolenaar 	return;		// type error; errmsg already given
748f87a0400SBram Moolenaar     keys = tv_get_string_buf(&argvars[1], buf);
749f87a0400SBram Moolenaar # ifdef MSWIN
750f87a0400SBram Moolenaar     if (serverSendToVim(server_name, keys, &r, &w, expr, timeout, TRUE) < 0)
751f87a0400SBram Moolenaar # else
752f87a0400SBram Moolenaar     if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, timeout,
753f87a0400SBram Moolenaar 								  0, TRUE) < 0)
754f87a0400SBram Moolenaar # endif
755f87a0400SBram Moolenaar     {
756f87a0400SBram Moolenaar 	if (r != NULL)
757f87a0400SBram Moolenaar 	{
758f87a0400SBram Moolenaar 	    emsg((char *)r);	// sending worked but evaluation failed
759f87a0400SBram Moolenaar 	    vim_free(r);
760f87a0400SBram Moolenaar 	}
761f87a0400SBram Moolenaar 	else
762f87a0400SBram Moolenaar 	    semsg(_("E241: Unable to send to %s"), server_name);
763f87a0400SBram Moolenaar 	return;
764f87a0400SBram Moolenaar     }
765f87a0400SBram Moolenaar 
766f87a0400SBram Moolenaar     rettv->vval.v_string = r;
767f87a0400SBram Moolenaar 
768f87a0400SBram Moolenaar     if (argvars[2].v_type != VAR_UNKNOWN)
769f87a0400SBram Moolenaar     {
770f87a0400SBram Moolenaar 	dictitem_T	v;
771f87a0400SBram Moolenaar 	char_u		str[30];
772f87a0400SBram Moolenaar 	char_u		*idvar;
773f87a0400SBram Moolenaar 
774f87a0400SBram Moolenaar 	idvar = tv_get_string_chk(&argvars[2]);
775f87a0400SBram Moolenaar 	if (idvar != NULL && *idvar != NUL)
776f87a0400SBram Moolenaar 	{
777f87a0400SBram Moolenaar 	    sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
778f87a0400SBram Moolenaar 	    v.di_tv.v_type = VAR_STRING;
779f87a0400SBram Moolenaar 	    v.di_tv.vval.v_string = vim_strsave(str);
780f87a0400SBram Moolenaar 	    set_var(idvar, &v.di_tv, FALSE);
781f87a0400SBram Moolenaar 	    vim_free(v.di_tv.vval.v_string);
782f87a0400SBram Moolenaar 	}
783f87a0400SBram Moolenaar     }
784f87a0400SBram Moolenaar }
785f87a0400SBram Moolenaar #endif
786f87a0400SBram Moolenaar 
787f87a0400SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
788f87a0400SBram Moolenaar /*
789f87a0400SBram Moolenaar  * "remote_expr()" function
790f87a0400SBram Moolenaar  */
791f87a0400SBram Moolenaar     void
f_remote_expr(typval_T * argvars UNUSED,typval_T * rettv)792f87a0400SBram Moolenaar f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv)
793f87a0400SBram Moolenaar {
794f87a0400SBram Moolenaar     rettv->v_type = VAR_STRING;
795f87a0400SBram Moolenaar     rettv->vval.v_string = NULL;
79683494b4aSYegappan Lakshmanan 
79783494b4aSYegappan Lakshmanan     if (in_vim9script()
79883494b4aSYegappan Lakshmanan 	    && (check_for_string_arg(argvars, 0) == FAIL
79983494b4aSYegappan Lakshmanan 		|| check_for_string_arg(argvars, 1) == FAIL
80083494b4aSYegappan Lakshmanan 		|| check_for_opt_string_arg(argvars, 2) == FAIL
80183494b4aSYegappan Lakshmanan 		|| (argvars[2].v_type != VAR_UNKNOWN
80283494b4aSYegappan Lakshmanan 		    && check_for_opt_number_arg(argvars, 3) == FAIL)))
80383494b4aSYegappan Lakshmanan 	return;
80483494b4aSYegappan Lakshmanan 
805f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
806f87a0400SBram Moolenaar     remote_common(argvars, rettv, TRUE);
807f87a0400SBram Moolenaar #endif
808f87a0400SBram Moolenaar }
809f87a0400SBram Moolenaar 
810f87a0400SBram Moolenaar /*
811f87a0400SBram Moolenaar  * "remote_foreground()" function
812f87a0400SBram Moolenaar  */
813f87a0400SBram Moolenaar     void
f_remote_foreground(typval_T * argvars UNUSED,typval_T * rettv UNUSED)814f87a0400SBram Moolenaar f_remote_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
815f87a0400SBram Moolenaar {
816f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
817*4490ec4eSYegappan Lakshmanan     if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
818*4490ec4eSYegappan Lakshmanan 	return;
819*4490ec4eSYegappan Lakshmanan 
820f87a0400SBram Moolenaar # ifdef MSWIN
821f87a0400SBram Moolenaar     // On Win32 it's done in this application.
822f87a0400SBram Moolenaar     {
823f87a0400SBram Moolenaar 	char_u	*server_name = tv_get_string_chk(&argvars[0]);
824f87a0400SBram Moolenaar 
825f87a0400SBram Moolenaar 	if (server_name != NULL)
826f87a0400SBram Moolenaar 	    serverForeground(server_name);
827f87a0400SBram Moolenaar     }
828f87a0400SBram Moolenaar # else
829f87a0400SBram Moolenaar     // Send a foreground() expression to the server.
830f87a0400SBram Moolenaar     argvars[1].v_type = VAR_STRING;
831f87a0400SBram Moolenaar     argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
832f87a0400SBram Moolenaar     argvars[2].v_type = VAR_UNKNOWN;
833f87a0400SBram Moolenaar     rettv->v_type = VAR_STRING;
834f87a0400SBram Moolenaar     rettv->vval.v_string = NULL;
835f87a0400SBram Moolenaar     remote_common(argvars, rettv, TRUE);
836f87a0400SBram Moolenaar     vim_free(argvars[1].vval.v_string);
837f87a0400SBram Moolenaar # endif
838f87a0400SBram Moolenaar #endif
839f87a0400SBram Moolenaar }
840f87a0400SBram Moolenaar 
841f87a0400SBram Moolenaar     void
f_remote_peek(typval_T * argvars UNUSED,typval_T * rettv)842f87a0400SBram Moolenaar f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv)
843f87a0400SBram Moolenaar {
844f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
845f87a0400SBram Moolenaar     dictitem_T	v;
846f87a0400SBram Moolenaar     char_u	*s = NULL;
847f87a0400SBram Moolenaar # ifdef MSWIN
848f87a0400SBram Moolenaar     long_u	n = 0;
849f87a0400SBram Moolenaar # endif
850f87a0400SBram Moolenaar     char_u	*serverid;
851f87a0400SBram Moolenaar 
852f87a0400SBram Moolenaar     rettv->vval.v_number = -1;
853*4490ec4eSYegappan Lakshmanan     if (check_restricted() || check_secure())
854f87a0400SBram Moolenaar 	return;
855*4490ec4eSYegappan Lakshmanan 
856*4490ec4eSYegappan Lakshmanan     if (in_vim9script()
857*4490ec4eSYegappan Lakshmanan 	    && (check_for_string_arg(argvars, 0) == FAIL
858*4490ec4eSYegappan Lakshmanan 		|| check_for_opt_string_arg(argvars, 1) == FAIL))
859*4490ec4eSYegappan Lakshmanan 	return;
860*4490ec4eSYegappan Lakshmanan 
861f87a0400SBram Moolenaar     serverid = tv_get_string_chk(&argvars[0]);
862f87a0400SBram Moolenaar     if (serverid == NULL)
863f87a0400SBram Moolenaar 	return;		// type error; errmsg already given
864f87a0400SBram Moolenaar # ifdef MSWIN
865f87a0400SBram Moolenaar     sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n);
866f87a0400SBram Moolenaar     if (n == 0)
867f87a0400SBram Moolenaar 	rettv->vval.v_number = -1;
868f87a0400SBram Moolenaar     else
869f87a0400SBram Moolenaar     {
870f87a0400SBram Moolenaar 	s = serverGetReply((HWND)n, FALSE, FALSE, FALSE, 0);
871f87a0400SBram Moolenaar 	rettv->vval.v_number = (s != NULL);
872f87a0400SBram Moolenaar     }
873f87a0400SBram Moolenaar # else
874f87a0400SBram Moolenaar     if (check_connection() == FAIL)
875f87a0400SBram Moolenaar 	return;
876f87a0400SBram Moolenaar 
877f87a0400SBram Moolenaar     rettv->vval.v_number = serverPeekReply(X_DISPLAY,
878f87a0400SBram Moolenaar 						serverStrToWin(serverid), &s);
879f87a0400SBram Moolenaar # endif
880f87a0400SBram Moolenaar 
881f87a0400SBram Moolenaar     if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
882f87a0400SBram Moolenaar     {
883f87a0400SBram Moolenaar 	char_u		*retvar;
884f87a0400SBram Moolenaar 
885f87a0400SBram Moolenaar 	v.di_tv.v_type = VAR_STRING;
886f87a0400SBram Moolenaar 	v.di_tv.vval.v_string = vim_strsave(s);
887f87a0400SBram Moolenaar 	retvar = tv_get_string_chk(&argvars[1]);
888f87a0400SBram Moolenaar 	if (retvar != NULL)
889f87a0400SBram Moolenaar 	    set_var(retvar, &v.di_tv, FALSE);
890f87a0400SBram Moolenaar 	vim_free(v.di_tv.vval.v_string);
891f87a0400SBram Moolenaar     }
892f87a0400SBram Moolenaar #else
893f87a0400SBram Moolenaar     rettv->vval.v_number = -1;
894f87a0400SBram Moolenaar #endif
895f87a0400SBram Moolenaar }
896f87a0400SBram Moolenaar 
897f87a0400SBram Moolenaar     void
f_remote_read(typval_T * argvars UNUSED,typval_T * rettv)898f87a0400SBram Moolenaar f_remote_read(typval_T *argvars UNUSED, typval_T *rettv)
899f87a0400SBram Moolenaar {
900f87a0400SBram Moolenaar     char_u	*r = NULL;
901f87a0400SBram Moolenaar 
902f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
9031a71d31bSYegappan Lakshmanan     char_u	*serverid;
904f87a0400SBram Moolenaar 
9051a71d31bSYegappan Lakshmanan     if (in_vim9script()
9061a71d31bSYegappan Lakshmanan 	    && (check_for_string_arg(argvars, 0) == FAIL
90783494b4aSYegappan Lakshmanan 		|| check_for_opt_number_arg(argvars, 1) == FAIL))
9081a71d31bSYegappan Lakshmanan 	return;
9091a71d31bSYegappan Lakshmanan 
9101a71d31bSYegappan Lakshmanan     serverid = tv_get_string_chk(&argvars[0]);
911f87a0400SBram Moolenaar     if (serverid != NULL && !check_restricted() && !check_secure())
912f87a0400SBram Moolenaar     {
913f87a0400SBram Moolenaar 	int timeout = 0;
914f87a0400SBram Moolenaar # ifdef MSWIN
915f87a0400SBram Moolenaar 	// The server's HWND is encoded in the 'id' parameter
916f87a0400SBram Moolenaar 	long_u		n = 0;
917f87a0400SBram Moolenaar # endif
918f87a0400SBram Moolenaar 
919f87a0400SBram Moolenaar 	if (argvars[1].v_type != VAR_UNKNOWN)
920f87a0400SBram Moolenaar 	    timeout = tv_get_number(&argvars[1]);
921f87a0400SBram Moolenaar 
922f87a0400SBram Moolenaar # ifdef MSWIN
923f87a0400SBram Moolenaar 	sscanf((char *)serverid, SCANF_HEX_LONG_U, &n);
924f87a0400SBram Moolenaar 	if (n != 0)
925f87a0400SBram Moolenaar 	    r = serverGetReply((HWND)n, FALSE, TRUE, TRUE, timeout);
926f87a0400SBram Moolenaar 	if (r == NULL)
927f87a0400SBram Moolenaar # else
928f87a0400SBram Moolenaar 	if (check_connection() == FAIL
929f87a0400SBram Moolenaar 		|| serverReadReply(X_DISPLAY, serverStrToWin(serverid),
930f87a0400SBram Moolenaar 						       &r, FALSE, timeout) < 0)
931f87a0400SBram Moolenaar # endif
932f87a0400SBram Moolenaar 	    emsg(_("E277: Unable to read a server reply"));
933f87a0400SBram Moolenaar     }
934f87a0400SBram Moolenaar #endif
935f87a0400SBram Moolenaar     rettv->v_type = VAR_STRING;
936f87a0400SBram Moolenaar     rettv->vval.v_string = r;
937f87a0400SBram Moolenaar }
938f87a0400SBram Moolenaar 
939f87a0400SBram Moolenaar /*
940f87a0400SBram Moolenaar  * "remote_send()" function
941f87a0400SBram Moolenaar  */
942f87a0400SBram Moolenaar     void
f_remote_send(typval_T * argvars UNUSED,typval_T * rettv)943f87a0400SBram Moolenaar f_remote_send(typval_T *argvars UNUSED, typval_T *rettv)
944f87a0400SBram Moolenaar {
945f87a0400SBram Moolenaar     rettv->v_type = VAR_STRING;
946f87a0400SBram Moolenaar     rettv->vval.v_string = NULL;
94783494b4aSYegappan Lakshmanan 
94883494b4aSYegappan Lakshmanan     if (in_vim9script()
94983494b4aSYegappan Lakshmanan 	    && (check_for_string_arg(argvars, 0) == FAIL
95083494b4aSYegappan Lakshmanan 		|| check_for_string_arg(argvars, 1) == FAIL
95183494b4aSYegappan Lakshmanan 		|| check_for_opt_string_arg(argvars, 2) == FAIL))
95283494b4aSYegappan Lakshmanan 	return;
95383494b4aSYegappan Lakshmanan 
954f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
955f87a0400SBram Moolenaar     remote_common(argvars, rettv, FALSE);
956f87a0400SBram Moolenaar #endif
957f87a0400SBram Moolenaar }
958f87a0400SBram Moolenaar 
959f87a0400SBram Moolenaar /*
960f87a0400SBram Moolenaar  * "remote_startserver()" function
961f87a0400SBram Moolenaar  */
962f87a0400SBram Moolenaar     void
f_remote_startserver(typval_T * argvars UNUSED,typval_T * rettv UNUSED)963f87a0400SBram Moolenaar f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
964f87a0400SBram Moolenaar {
965f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
966*4490ec4eSYegappan Lakshmanan     char_u	*server;
967f87a0400SBram Moolenaar 
968*4490ec4eSYegappan Lakshmanan     if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
969*4490ec4eSYegappan Lakshmanan 	return;
970*4490ec4eSYegappan Lakshmanan 
971*4490ec4eSYegappan Lakshmanan     server = tv_get_string_chk(&argvars[0]);
972f87a0400SBram Moolenaar     if (server == NULL)
973f87a0400SBram Moolenaar 	return;		// type error; errmsg already given
974f87a0400SBram Moolenaar     if (serverName != NULL)
975f87a0400SBram Moolenaar 	emsg(_("E941: already started a server"));
976f87a0400SBram Moolenaar     else
977f87a0400SBram Moolenaar     {
978f87a0400SBram Moolenaar # ifdef FEAT_X11
979f87a0400SBram Moolenaar 	if (check_connection() == OK)
980f87a0400SBram Moolenaar 	    serverRegisterName(X_DISPLAY, server);
981f87a0400SBram Moolenaar # else
982f87a0400SBram Moolenaar 	serverSetName(server);
983f87a0400SBram Moolenaar # endif
984f87a0400SBram Moolenaar     }
985f87a0400SBram Moolenaar #else
986f87a0400SBram Moolenaar     emsg(_("E942: +clientserver feature not available"));
987f87a0400SBram Moolenaar #endif
988f87a0400SBram Moolenaar }
989f87a0400SBram Moolenaar 
990f87a0400SBram Moolenaar     void
f_server2client(typval_T * argvars UNUSED,typval_T * rettv)991f87a0400SBram Moolenaar f_server2client(typval_T *argvars UNUSED, typval_T *rettv)
992f87a0400SBram Moolenaar {
993f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
994f87a0400SBram Moolenaar     char_u	buf[NUMBUFLEN];
995*4490ec4eSYegappan Lakshmanan     char_u	*server;
996*4490ec4eSYegappan Lakshmanan     char_u	*reply;
997f87a0400SBram Moolenaar 
998f87a0400SBram Moolenaar     rettv->vval.v_number = -1;
999f87a0400SBram Moolenaar     if (check_restricted() || check_secure())
1000f87a0400SBram Moolenaar 	return;
1001*4490ec4eSYegappan Lakshmanan 
1002*4490ec4eSYegappan Lakshmanan     if (in_vim9script()
1003*4490ec4eSYegappan Lakshmanan 	    && (check_for_string_arg(argvars, 0) == FAIL
1004*4490ec4eSYegappan Lakshmanan 		|| check_for_string_arg(argvars, 1) == FAIL))
1005*4490ec4eSYegappan Lakshmanan 	return;
1006*4490ec4eSYegappan Lakshmanan 
1007*4490ec4eSYegappan Lakshmanan     server = tv_get_string_chk(&argvars[0]);
1008*4490ec4eSYegappan Lakshmanan     reply = tv_get_string_buf_chk(&argvars[1], buf);
1009*4490ec4eSYegappan Lakshmanan     if (server == NULL || reply == NULL)
1010*4490ec4eSYegappan Lakshmanan 	return;
1011*4490ec4eSYegappan Lakshmanan 
1012f87a0400SBram Moolenaar # ifdef FEAT_X11
1013f87a0400SBram Moolenaar     if (check_connection() == FAIL)
1014f87a0400SBram Moolenaar 	return;
1015f87a0400SBram Moolenaar # endif
1016f87a0400SBram Moolenaar 
1017f87a0400SBram Moolenaar     if (serverSendReply(server, reply) < 0)
1018f87a0400SBram Moolenaar     {
1019f87a0400SBram Moolenaar 	emsg(_("E258: Unable to send to client"));
1020f87a0400SBram Moolenaar 	return;
1021f87a0400SBram Moolenaar     }
1022f87a0400SBram Moolenaar     rettv->vval.v_number = 0;
1023f87a0400SBram Moolenaar #else
1024f87a0400SBram Moolenaar     rettv->vval.v_number = -1;
1025f87a0400SBram Moolenaar #endif
1026f87a0400SBram Moolenaar }
1027f87a0400SBram Moolenaar 
1028f87a0400SBram Moolenaar     void
f_serverlist(typval_T * argvars UNUSED,typval_T * rettv)1029f87a0400SBram Moolenaar f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
1030f87a0400SBram Moolenaar {
1031f87a0400SBram Moolenaar     char_u	*r = NULL;
1032f87a0400SBram Moolenaar 
1033f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER
1034f87a0400SBram Moolenaar # ifdef MSWIN
1035f87a0400SBram Moolenaar     r = serverGetVimNames();
1036f87a0400SBram Moolenaar # else
1037f87a0400SBram Moolenaar     make_connection();
1038f87a0400SBram Moolenaar     if (X_DISPLAY != NULL)
1039f87a0400SBram Moolenaar 	r = serverGetVimNames(X_DISPLAY);
1040f87a0400SBram Moolenaar # endif
1041f87a0400SBram Moolenaar #endif
1042f87a0400SBram Moolenaar     rettv->v_type = VAR_STRING;
1043f87a0400SBram Moolenaar     rettv->vval.v_string = r;
1044f87a0400SBram Moolenaar }
1045f87a0400SBram Moolenaar #endif
1046