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