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