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 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 * 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 89f87a0400SBram Moolenaar res = eval_to_string(expr, NULL, 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 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 * 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 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 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 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 476*7d41aa88SBram 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 * 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. 599f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|"); 600f87a0400SBram Moolenaar if (tabs) 601f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"tab "); 602f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"drop"); 603f87a0400SBram Moolenaar for (i = 0; i < filec; i++) 604f87a0400SBram Moolenaar { 605f87a0400SBram Moolenaar // On Unix the shell has already expanded the wildcards, don't want to 606f87a0400SBram Moolenaar // do it again in the Vim server. On MS-Windows only escape 607f87a0400SBram Moolenaar // non-wildcard characters. 608f87a0400SBram Moolenaar p = vim_strsave_escaped((char_u *)filev[i], 609f87a0400SBram Moolenaar #ifdef UNIX 610f87a0400SBram Moolenaar PATH_ESC_CHARS 611f87a0400SBram Moolenaar #else 612f87a0400SBram Moolenaar (char_u *)" \t%#" 613f87a0400SBram Moolenaar #endif 614f87a0400SBram Moolenaar ); 615f87a0400SBram Moolenaar if (p == NULL) 616f87a0400SBram Moolenaar { 617f87a0400SBram Moolenaar vim_free(ga.ga_data); 618f87a0400SBram Moolenaar return NULL; 619f87a0400SBram Moolenaar } 620f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)" "); 621f87a0400SBram Moolenaar ga_concat(&ga, p); 622f87a0400SBram Moolenaar vim_free(p); 623f87a0400SBram Moolenaar } 624f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>"); 625f87a0400SBram Moolenaar 626f87a0400SBram Moolenaar // The :drop commands goes to Insert mode when 'insertmode' is set, use 627f87a0400SBram Moolenaar // CTRL-\ CTRL-N again. 628f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"<C-\\><C-N>"); 629f87a0400SBram Moolenaar 630f87a0400SBram Moolenaar // Switch back to the correct current directory (prior to temporary path 631f87a0400SBram Moolenaar // switch) unless 'autochdir' is set, in which case it will already be 632f87a0400SBram Moolenaar // correct after the :drop command. With line breaks and spaces: 633f87a0400SBram Moolenaar // if !exists('+acd') || !&acd 634f87a0400SBram Moolenaar // if haslocaldir() 635f87a0400SBram Moolenaar // cd - 636f87a0400SBram Moolenaar // lcd - 637f87a0400SBram Moolenaar // elseif getcwd() ==# 'current path' 638f87a0400SBram Moolenaar // cd - 639f87a0400SBram Moolenaar // endif 640f87a0400SBram Moolenaar // endif 641f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|"); 642f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '"); 643f87a0400SBram Moolenaar ga_concat(&ga, cdp); 644f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>"); 645f87a0400SBram Moolenaar vim_free(cdp); 646f87a0400SBram Moolenaar 647f87a0400SBram Moolenaar if (sendReply) 648f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>"); 649f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)":"); 650f87a0400SBram Moolenaar if (inicmd != NULL) 651f87a0400SBram Moolenaar { 652f87a0400SBram Moolenaar // Can't use <CR> after "inicmd", because an "startinsert" would cause 653f87a0400SBram Moolenaar // the following commands to be inserted as text. Use a "|", 654f87a0400SBram Moolenaar // hopefully "inicmd" does allow this... 655f87a0400SBram Moolenaar ga_concat(&ga, inicmd); 656f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"|"); 657f87a0400SBram Moolenaar } 658f87a0400SBram Moolenaar // Bring the window to the foreground, goto Insert mode when 'im' set and 659f87a0400SBram Moolenaar // clear command line. 660f87a0400SBram Moolenaar ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>"); 661f87a0400SBram Moolenaar ga_append(&ga, NUL); 662f87a0400SBram Moolenaar return ga.ga_data; 663f87a0400SBram Moolenaar } 664f87a0400SBram Moolenaar 665f87a0400SBram Moolenaar /* 666f87a0400SBram Moolenaar * Make our basic server name: use the specified "arg" if given, otherwise use 667f87a0400SBram Moolenaar * the tail of the command "cmd" we were started with. 668f87a0400SBram Moolenaar * Return the name in allocated memory. This doesn't include a serial number. 669f87a0400SBram Moolenaar */ 670f87a0400SBram Moolenaar static char_u * 671f87a0400SBram Moolenaar serverMakeName(char_u *arg, char *cmd) 672f87a0400SBram Moolenaar { 673f87a0400SBram Moolenaar char_u *p; 674f87a0400SBram Moolenaar 675f87a0400SBram Moolenaar if (arg != NULL && *arg != NUL) 676f87a0400SBram Moolenaar p = vim_strsave_up(arg); 677f87a0400SBram Moolenaar else 678f87a0400SBram Moolenaar { 679f87a0400SBram Moolenaar p = vim_strsave_up(gettail((char_u *)cmd)); 680f87a0400SBram Moolenaar // Remove .exe or .bat from the name. 681f87a0400SBram Moolenaar if (p != NULL && vim_strchr(p, '.') != NULL) 682f87a0400SBram Moolenaar *vim_strchr(p, '.') = NUL; 683f87a0400SBram Moolenaar } 684f87a0400SBram Moolenaar return p; 685f87a0400SBram Moolenaar } 686f87a0400SBram Moolenaar #endif // FEAT_CLIENTSERVER 687f87a0400SBram Moolenaar 688f87a0400SBram Moolenaar #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) 689f87a0400SBram Moolenaar static void 690f87a0400SBram Moolenaar make_connection(void) 691f87a0400SBram Moolenaar { 692f87a0400SBram Moolenaar if (X_DISPLAY == NULL 693f87a0400SBram Moolenaar # ifdef FEAT_GUI 694f87a0400SBram Moolenaar && !gui.in_use 695f87a0400SBram Moolenaar # endif 696f87a0400SBram Moolenaar ) 697f87a0400SBram Moolenaar { 698f87a0400SBram Moolenaar x_force_connect = TRUE; 699f87a0400SBram Moolenaar setup_term_clip(); 700f87a0400SBram Moolenaar x_force_connect = FALSE; 701f87a0400SBram Moolenaar } 702f87a0400SBram Moolenaar } 703f87a0400SBram Moolenaar 704f87a0400SBram Moolenaar static int 705f87a0400SBram Moolenaar check_connection(void) 706f87a0400SBram Moolenaar { 707f87a0400SBram Moolenaar make_connection(); 708f87a0400SBram Moolenaar if (X_DISPLAY == NULL) 709f87a0400SBram Moolenaar { 710f87a0400SBram Moolenaar emsg(_("E240: No connection to the X server")); 711f87a0400SBram Moolenaar return FAIL; 712f87a0400SBram Moolenaar } 713f87a0400SBram Moolenaar return OK; 714f87a0400SBram Moolenaar } 715f87a0400SBram Moolenaar #endif 716f87a0400SBram Moolenaar 717f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 718f87a0400SBram Moolenaar static void 719f87a0400SBram Moolenaar remote_common(typval_T *argvars, typval_T *rettv, int expr) 720f87a0400SBram Moolenaar { 721f87a0400SBram Moolenaar char_u *server_name; 722f87a0400SBram Moolenaar char_u *keys; 723f87a0400SBram Moolenaar char_u *r = NULL; 724f87a0400SBram Moolenaar char_u buf[NUMBUFLEN]; 725f87a0400SBram Moolenaar int timeout = 0; 726f87a0400SBram Moolenaar # ifdef MSWIN 727f87a0400SBram Moolenaar HWND w; 728f87a0400SBram Moolenaar # else 729f87a0400SBram Moolenaar Window w; 730f87a0400SBram Moolenaar # endif 731f87a0400SBram Moolenaar 732f87a0400SBram Moolenaar if (check_restricted() || check_secure()) 733f87a0400SBram Moolenaar return; 734f87a0400SBram Moolenaar 735f87a0400SBram Moolenaar # ifdef FEAT_X11 736f87a0400SBram Moolenaar if (check_connection() == FAIL) 737f87a0400SBram Moolenaar return; 738f87a0400SBram Moolenaar # endif 739f87a0400SBram Moolenaar if (argvars[2].v_type != VAR_UNKNOWN 740f87a0400SBram Moolenaar && argvars[3].v_type != VAR_UNKNOWN) 741f87a0400SBram Moolenaar timeout = tv_get_number(&argvars[3]); 742f87a0400SBram Moolenaar 743f87a0400SBram Moolenaar server_name = tv_get_string_chk(&argvars[0]); 744f87a0400SBram Moolenaar if (server_name == NULL) 745f87a0400SBram Moolenaar return; // type error; errmsg already given 746f87a0400SBram Moolenaar keys = tv_get_string_buf(&argvars[1], buf); 747f87a0400SBram Moolenaar # ifdef MSWIN 748f87a0400SBram Moolenaar if (serverSendToVim(server_name, keys, &r, &w, expr, timeout, TRUE) < 0) 749f87a0400SBram Moolenaar # else 750f87a0400SBram Moolenaar if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, timeout, 751f87a0400SBram Moolenaar 0, TRUE) < 0) 752f87a0400SBram Moolenaar # endif 753f87a0400SBram Moolenaar { 754f87a0400SBram Moolenaar if (r != NULL) 755f87a0400SBram Moolenaar { 756f87a0400SBram Moolenaar emsg((char *)r); // sending worked but evaluation failed 757f87a0400SBram Moolenaar vim_free(r); 758f87a0400SBram Moolenaar } 759f87a0400SBram Moolenaar else 760f87a0400SBram Moolenaar semsg(_("E241: Unable to send to %s"), server_name); 761f87a0400SBram Moolenaar return; 762f87a0400SBram Moolenaar } 763f87a0400SBram Moolenaar 764f87a0400SBram Moolenaar rettv->vval.v_string = r; 765f87a0400SBram Moolenaar 766f87a0400SBram Moolenaar if (argvars[2].v_type != VAR_UNKNOWN) 767f87a0400SBram Moolenaar { 768f87a0400SBram Moolenaar dictitem_T v; 769f87a0400SBram Moolenaar char_u str[30]; 770f87a0400SBram Moolenaar char_u *idvar; 771f87a0400SBram Moolenaar 772f87a0400SBram Moolenaar idvar = tv_get_string_chk(&argvars[2]); 773f87a0400SBram Moolenaar if (idvar != NULL && *idvar != NUL) 774f87a0400SBram Moolenaar { 775f87a0400SBram Moolenaar sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w); 776f87a0400SBram Moolenaar v.di_tv.v_type = VAR_STRING; 777f87a0400SBram Moolenaar v.di_tv.vval.v_string = vim_strsave(str); 778f87a0400SBram Moolenaar set_var(idvar, &v.di_tv, FALSE); 779f87a0400SBram Moolenaar vim_free(v.di_tv.vval.v_string); 780f87a0400SBram Moolenaar } 781f87a0400SBram Moolenaar } 782f87a0400SBram Moolenaar } 783f87a0400SBram Moolenaar #endif 784f87a0400SBram Moolenaar 785f87a0400SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO) 786f87a0400SBram Moolenaar /* 787f87a0400SBram Moolenaar * "remote_expr()" function 788f87a0400SBram Moolenaar */ 789f87a0400SBram Moolenaar void 790f87a0400SBram Moolenaar f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv) 791f87a0400SBram Moolenaar { 792f87a0400SBram Moolenaar rettv->v_type = VAR_STRING; 793f87a0400SBram Moolenaar rettv->vval.v_string = NULL; 794f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 795f87a0400SBram Moolenaar remote_common(argvars, rettv, TRUE); 796f87a0400SBram Moolenaar #endif 797f87a0400SBram Moolenaar } 798f87a0400SBram Moolenaar 799f87a0400SBram Moolenaar /* 800f87a0400SBram Moolenaar * "remote_foreground()" function 801f87a0400SBram Moolenaar */ 802f87a0400SBram Moolenaar void 803f87a0400SBram Moolenaar f_remote_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 804f87a0400SBram Moolenaar { 805f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 806f87a0400SBram Moolenaar # ifdef MSWIN 807f87a0400SBram Moolenaar // On Win32 it's done in this application. 808f87a0400SBram Moolenaar { 809f87a0400SBram Moolenaar char_u *server_name = tv_get_string_chk(&argvars[0]); 810f87a0400SBram Moolenaar 811f87a0400SBram Moolenaar if (server_name != NULL) 812f87a0400SBram Moolenaar serverForeground(server_name); 813f87a0400SBram Moolenaar } 814f87a0400SBram Moolenaar # else 815f87a0400SBram Moolenaar // Send a foreground() expression to the server. 816f87a0400SBram Moolenaar argvars[1].v_type = VAR_STRING; 817f87a0400SBram Moolenaar argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()"); 818f87a0400SBram Moolenaar argvars[2].v_type = VAR_UNKNOWN; 819f87a0400SBram Moolenaar rettv->v_type = VAR_STRING; 820f87a0400SBram Moolenaar rettv->vval.v_string = NULL; 821f87a0400SBram Moolenaar remote_common(argvars, rettv, TRUE); 822f87a0400SBram Moolenaar vim_free(argvars[1].vval.v_string); 823f87a0400SBram Moolenaar # endif 824f87a0400SBram Moolenaar #endif 825f87a0400SBram Moolenaar } 826f87a0400SBram Moolenaar 827f87a0400SBram Moolenaar void 828f87a0400SBram Moolenaar f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv) 829f87a0400SBram Moolenaar { 830f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 831f87a0400SBram Moolenaar dictitem_T v; 832f87a0400SBram Moolenaar char_u *s = NULL; 833f87a0400SBram Moolenaar # ifdef MSWIN 834f87a0400SBram Moolenaar long_u n = 0; 835f87a0400SBram Moolenaar # endif 836f87a0400SBram Moolenaar char_u *serverid; 837f87a0400SBram Moolenaar 838f87a0400SBram Moolenaar if (check_restricted() || check_secure()) 839f87a0400SBram Moolenaar { 840f87a0400SBram Moolenaar rettv->vval.v_number = -1; 841f87a0400SBram Moolenaar return; 842f87a0400SBram Moolenaar } 843f87a0400SBram Moolenaar serverid = tv_get_string_chk(&argvars[0]); 844f87a0400SBram Moolenaar if (serverid == NULL) 845f87a0400SBram Moolenaar { 846f87a0400SBram Moolenaar rettv->vval.v_number = -1; 847f87a0400SBram Moolenaar return; // type error; errmsg already given 848f87a0400SBram Moolenaar } 849f87a0400SBram Moolenaar # ifdef MSWIN 850f87a0400SBram Moolenaar sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n); 851f87a0400SBram Moolenaar if (n == 0) 852f87a0400SBram Moolenaar rettv->vval.v_number = -1; 853f87a0400SBram Moolenaar else 854f87a0400SBram Moolenaar { 855f87a0400SBram Moolenaar s = serverGetReply((HWND)n, FALSE, FALSE, FALSE, 0); 856f87a0400SBram Moolenaar rettv->vval.v_number = (s != NULL); 857f87a0400SBram Moolenaar } 858f87a0400SBram Moolenaar # else 859f87a0400SBram Moolenaar if (check_connection() == FAIL) 860f87a0400SBram Moolenaar return; 861f87a0400SBram Moolenaar 862f87a0400SBram Moolenaar rettv->vval.v_number = serverPeekReply(X_DISPLAY, 863f87a0400SBram Moolenaar serverStrToWin(serverid), &s); 864f87a0400SBram Moolenaar # endif 865f87a0400SBram Moolenaar 866f87a0400SBram Moolenaar if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0) 867f87a0400SBram Moolenaar { 868f87a0400SBram Moolenaar char_u *retvar; 869f87a0400SBram Moolenaar 870f87a0400SBram Moolenaar v.di_tv.v_type = VAR_STRING; 871f87a0400SBram Moolenaar v.di_tv.vval.v_string = vim_strsave(s); 872f87a0400SBram Moolenaar retvar = tv_get_string_chk(&argvars[1]); 873f87a0400SBram Moolenaar if (retvar != NULL) 874f87a0400SBram Moolenaar set_var(retvar, &v.di_tv, FALSE); 875f87a0400SBram Moolenaar vim_free(v.di_tv.vval.v_string); 876f87a0400SBram Moolenaar } 877f87a0400SBram Moolenaar #else 878f87a0400SBram Moolenaar rettv->vval.v_number = -1; 879f87a0400SBram Moolenaar #endif 880f87a0400SBram Moolenaar } 881f87a0400SBram Moolenaar 882f87a0400SBram Moolenaar void 883f87a0400SBram Moolenaar f_remote_read(typval_T *argvars UNUSED, typval_T *rettv) 884f87a0400SBram Moolenaar { 885f87a0400SBram Moolenaar char_u *r = NULL; 886f87a0400SBram Moolenaar 887f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 888f87a0400SBram Moolenaar char_u *serverid = tv_get_string_chk(&argvars[0]); 889f87a0400SBram Moolenaar 890f87a0400SBram Moolenaar if (serverid != NULL && !check_restricted() && !check_secure()) 891f87a0400SBram Moolenaar { 892f87a0400SBram Moolenaar int timeout = 0; 893f87a0400SBram Moolenaar # ifdef MSWIN 894f87a0400SBram Moolenaar // The server's HWND is encoded in the 'id' parameter 895f87a0400SBram Moolenaar long_u n = 0; 896f87a0400SBram Moolenaar # endif 897f87a0400SBram Moolenaar 898f87a0400SBram Moolenaar if (argvars[1].v_type != VAR_UNKNOWN) 899f87a0400SBram Moolenaar timeout = tv_get_number(&argvars[1]); 900f87a0400SBram Moolenaar 901f87a0400SBram Moolenaar # ifdef MSWIN 902f87a0400SBram Moolenaar sscanf((char *)serverid, SCANF_HEX_LONG_U, &n); 903f87a0400SBram Moolenaar if (n != 0) 904f87a0400SBram Moolenaar r = serverGetReply((HWND)n, FALSE, TRUE, TRUE, timeout); 905f87a0400SBram Moolenaar if (r == NULL) 906f87a0400SBram Moolenaar # else 907f87a0400SBram Moolenaar if (check_connection() == FAIL 908f87a0400SBram Moolenaar || serverReadReply(X_DISPLAY, serverStrToWin(serverid), 909f87a0400SBram Moolenaar &r, FALSE, timeout) < 0) 910f87a0400SBram Moolenaar # endif 911f87a0400SBram Moolenaar emsg(_("E277: Unable to read a server reply")); 912f87a0400SBram Moolenaar } 913f87a0400SBram Moolenaar #endif 914f87a0400SBram Moolenaar rettv->v_type = VAR_STRING; 915f87a0400SBram Moolenaar rettv->vval.v_string = r; 916f87a0400SBram Moolenaar } 917f87a0400SBram Moolenaar 918f87a0400SBram Moolenaar /* 919f87a0400SBram Moolenaar * "remote_send()" function 920f87a0400SBram Moolenaar */ 921f87a0400SBram Moolenaar void 922f87a0400SBram Moolenaar f_remote_send(typval_T *argvars UNUSED, typval_T *rettv) 923f87a0400SBram Moolenaar { 924f87a0400SBram Moolenaar rettv->v_type = VAR_STRING; 925f87a0400SBram Moolenaar rettv->vval.v_string = NULL; 926f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 927f87a0400SBram Moolenaar remote_common(argvars, rettv, FALSE); 928f87a0400SBram Moolenaar #endif 929f87a0400SBram Moolenaar } 930f87a0400SBram Moolenaar 931f87a0400SBram Moolenaar /* 932f87a0400SBram Moolenaar * "remote_startserver()" function 933f87a0400SBram Moolenaar */ 934f87a0400SBram Moolenaar void 935f87a0400SBram Moolenaar f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 936f87a0400SBram Moolenaar { 937f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 938f87a0400SBram Moolenaar char_u *server = tv_get_string_chk(&argvars[0]); 939f87a0400SBram Moolenaar 940f87a0400SBram Moolenaar if (server == NULL) 941f87a0400SBram Moolenaar return; // type error; errmsg already given 942f87a0400SBram Moolenaar if (serverName != NULL) 943f87a0400SBram Moolenaar emsg(_("E941: already started a server")); 944f87a0400SBram Moolenaar else 945f87a0400SBram Moolenaar { 946f87a0400SBram Moolenaar # ifdef FEAT_X11 947f87a0400SBram Moolenaar if (check_connection() == OK) 948f87a0400SBram Moolenaar serverRegisterName(X_DISPLAY, server); 949f87a0400SBram Moolenaar # else 950f87a0400SBram Moolenaar serverSetName(server); 951f87a0400SBram Moolenaar # endif 952f87a0400SBram Moolenaar } 953f87a0400SBram Moolenaar #else 954f87a0400SBram Moolenaar emsg(_("E942: +clientserver feature not available")); 955f87a0400SBram Moolenaar #endif 956f87a0400SBram Moolenaar } 957f87a0400SBram Moolenaar 958f87a0400SBram Moolenaar void 959f87a0400SBram Moolenaar f_server2client(typval_T *argvars UNUSED, typval_T *rettv) 960f87a0400SBram Moolenaar { 961f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 962f87a0400SBram Moolenaar char_u buf[NUMBUFLEN]; 963f87a0400SBram Moolenaar char_u *server = tv_get_string_chk(&argvars[0]); 964f87a0400SBram Moolenaar char_u *reply = tv_get_string_buf_chk(&argvars[1], buf); 965f87a0400SBram Moolenaar 966f87a0400SBram Moolenaar rettv->vval.v_number = -1; 967f87a0400SBram Moolenaar if (server == NULL || reply == NULL) 968f87a0400SBram Moolenaar return; 969f87a0400SBram Moolenaar if (check_restricted() || check_secure()) 970f87a0400SBram Moolenaar return; 971f87a0400SBram Moolenaar # ifdef FEAT_X11 972f87a0400SBram Moolenaar if (check_connection() == FAIL) 973f87a0400SBram Moolenaar return; 974f87a0400SBram Moolenaar # endif 975f87a0400SBram Moolenaar 976f87a0400SBram Moolenaar if (serverSendReply(server, reply) < 0) 977f87a0400SBram Moolenaar { 978f87a0400SBram Moolenaar emsg(_("E258: Unable to send to client")); 979f87a0400SBram Moolenaar return; 980f87a0400SBram Moolenaar } 981f87a0400SBram Moolenaar rettv->vval.v_number = 0; 982f87a0400SBram Moolenaar #else 983f87a0400SBram Moolenaar rettv->vval.v_number = -1; 984f87a0400SBram Moolenaar #endif 985f87a0400SBram Moolenaar } 986f87a0400SBram Moolenaar 987f87a0400SBram Moolenaar void 988f87a0400SBram Moolenaar f_serverlist(typval_T *argvars UNUSED, typval_T *rettv) 989f87a0400SBram Moolenaar { 990f87a0400SBram Moolenaar char_u *r = NULL; 991f87a0400SBram Moolenaar 992f87a0400SBram Moolenaar #ifdef FEAT_CLIENTSERVER 993f87a0400SBram Moolenaar # ifdef MSWIN 994f87a0400SBram Moolenaar r = serverGetVimNames(); 995f87a0400SBram Moolenaar # else 996f87a0400SBram Moolenaar make_connection(); 997f87a0400SBram Moolenaar if (X_DISPLAY != NULL) 998f87a0400SBram Moolenaar r = serverGetVimNames(X_DISPLAY); 999f87a0400SBram Moolenaar # endif 1000f87a0400SBram Moolenaar #endif 1001f87a0400SBram Moolenaar rettv->v_type = VAR_STRING; 1002f87a0400SBram Moolenaar rettv->vval.v_string = r; 1003f87a0400SBram Moolenaar } 1004f87a0400SBram Moolenaar #endif 1005