/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* clientserver.c: functions for Client Server functionality
*/
#include "vim.h"
#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
static void cmdsrv_main(int *argc, char **argv, char_u *serverName_arg, char_u **serverStr);
static char_u *serverMakeName(char_u *arg, char *cmd);
/*
* Replace termcodes such as <CR> and insert as key presses if there is room.
*/
void
server_to_input_buf(char_u *str)
{
char_u *ptr = NULL;
char_u *cpo_save = p_cpo;
// Set 'cpoptions' the way we want it.
// B set - backslashes are *not* treated specially
// k set - keycodes are *not* reverse-engineered
// < unset - <Key> sequences *are* interpreted
// The last but one parameter of replace_termcodes() is TRUE so that the
// <lt> sequence is recognised - needed for a real backslash.
p_cpo = (char_u *)"Bk";
str = replace_termcodes((char_u *)str, &ptr, REPTERM_DO_LT, NULL);
p_cpo = cpo_save;
if (*ptr != NUL) // trailing CTRL-V results in nothing
{
/*
* Add the string to the input stream.
* Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
*
* First clear typed characters from the typeahead buffer, there could
* be half a mapping there. Then append to the existing string, so
* that multiple commands from a client are concatenated.
*/
if (typebuf.tb_maplen < typebuf.tb_len)
del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
(void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE);
// Let input_available() know we inserted text in the typeahead
// buffer.
typebuf_was_filled = TRUE;
}
vim_free((char_u *)ptr);
}
/*
* Evaluate an expression that the client sent to a string.
*/
char_u *
eval_client_expr_to_string(char_u *expr)
{
char_u *res;
int save_dbl = debug_break_level;
int save_ro = redir_off;
funccal_entry_T funccal_entry;
int did_save_funccal = FALSE;
// Evaluate the expression at the toplevel, don't use variables local to
// the calling function. Except when in debug mode.
if (!debug_mode)
{
save_funccal(&funccal_entry);
did_save_funccal = TRUE;
}
// Disable debugging, otherwise Vim hangs, waiting for "cont" to be
// typed.
debug_break_level = -1;
redir_off = 0;
// Do not display error message, otherwise Vim hangs, waiting for "cont"
// to be typed. Do generate errors so that try/catch works.
++emsg_silent;
res = eval_to_string(expr, NULL, TRUE);
debug_break_level = save_dbl;
redir_off = save_ro;
--emsg_silent;
if (emsg_silent < 0)
emsg_silent = 0;
if (did_save_funccal)
restore_funccal();
// A client can tell us to redraw, but not to display the cursor, so do
// that here.
setcursor();
out_flush_cursor(FALSE, FALSE);
return res;
}
/*
* Evaluate a command or expression sent to ourselves.
*/
int
sendToLocalVim(char_u *cmd, int asExpr, char_u **result)
{
if (asExpr)
{
char_u *ret;
ret = eval_client_expr_to_string(cmd);
if (result != NULL)
{
if (ret == NULL)
{
char *err = _(e_invexprmsg);
size_t len = STRLEN(cmd) + STRLEN(err) + 5;
char_u *msg;
msg = alloc(len);
if (msg != NULL)
vim_snprintf((char *)msg, len, "%s: \"%s\"", err, cmd);
*result = msg;
}
else
*result = ret;
}
else
vim_free(ret);
return ret == NULL ? -1 : 0;
}
server_to_input_buf(cmd);
return 0;
}
/*
* If conversion is needed, convert "data" from "client_enc" to 'encoding' and
* return an allocated string. Otherwise return "data".
* "*tofree" is set to the result when it needs to be freed later.
*/
char_u *
serverConvert(
char_u *client_enc UNUSED,
char_u *data,
char_u **tofree)
{
char_u *res = data;
*tofree = NULL;
if (client_enc != NULL && p_enc != NULL)
{
vimconv_T vimconv;
vimconv.vc_type = CONV_NONE;
if (convert_setup(&vimconv, client_enc, p_enc) != FAIL
&& vimconv.vc_type != CONV_NONE)
{
res = string_convert(&vimconv, data, NULL);
if (res == NULL)
res = data;