Mercurial > vim
comparison src/main.c @ 19920:5e41b2e63c73 v8.2.0516
patch 8.2.0516: client-server code is spread out
Commit: https://github.com/vim/vim/commit/f87a0400fd81862c33d6ad2291a56e178db7dddd
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Apr 5 20:21:03 2020 +0200
patch 8.2.0516: client-server code is spread out
Problem: Client-server code is spread out.
Solution: Move client-server code to a new file. (Yegappan Lakshmanan,
closes #5885)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 05 Apr 2020 20:30:35 +0200 |
parents | 031184ace7c5 |
children | aadd1cae2ff5 |
comparison
equal
deleted
inserted
replaced
19919:b4b102849236 | 19920:5e41b2e63c73 |
---|---|
51 static void source_startup_scripts(mparm_T *parmp); | 51 static void source_startup_scripts(mparm_T *parmp); |
52 static void main_start_gui(void); | 52 static void main_start_gui(void); |
53 static void check_swap_exists_action(void); | 53 static void check_swap_exists_action(void); |
54 # ifdef FEAT_EVAL | 54 # ifdef FEAT_EVAL |
55 static void set_progpath(char_u *argv0); | 55 static void set_progpath(char_u *argv0); |
56 # endif | |
57 # if defined(FEAT_CLIENTSERVER) || defined(PROTO) | |
58 static void exec_on_server(mparm_T *parmp); | |
59 static void prepare_server(mparm_T *parmp); | |
60 static void cmdsrv_main(int *argc, char **argv, char_u *serverName_arg, char_u **serverStr); | |
61 static char_u *serverMakeName(char_u *arg, char *cmd); | |
62 # endif | 56 # endif |
63 #endif | 57 #endif |
64 | 58 |
65 | 59 |
66 /* | 60 /* |
3712 vim_free(path); | 3706 vim_free(path); |
3713 # endif | 3707 # endif |
3714 } | 3708 } |
3715 | 3709 |
3716 #endif // NO_VIM_MAIN | 3710 #endif // NO_VIM_MAIN |
3717 | |
3718 #if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO) | |
3719 | |
3720 /* | |
3721 * Common code for the X command server and the Win32 command server. | |
3722 */ | |
3723 | |
3724 static char_u *build_drop_cmd(int filec, char **filev, int tabs, int sendReply); | |
3725 | |
3726 /* | |
3727 * Do the client-server stuff, unless "--servername ''" was used. | |
3728 */ | |
3729 static void | |
3730 exec_on_server(mparm_T *parmp) | |
3731 { | |
3732 if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL) | |
3733 { | |
3734 # ifdef MSWIN | |
3735 // Initialise the client/server messaging infrastructure. | |
3736 serverInitMessaging(); | |
3737 # endif | |
3738 | |
3739 /* | |
3740 * When a command server argument was found, execute it. This may | |
3741 * exit Vim when it was successful. Otherwise it's executed further | |
3742 * on. Remember the encoding used here in "serverStrEnc". | |
3743 */ | |
3744 if (parmp->serverArg) | |
3745 { | |
3746 cmdsrv_main(&parmp->argc, parmp->argv, | |
3747 parmp->serverName_arg, &parmp->serverStr); | |
3748 parmp->serverStrEnc = vim_strsave(p_enc); | |
3749 } | |
3750 | |
3751 // If we're still running, get the name to register ourselves. | |
3752 // On Win32 can register right now, for X11 need to setup the | |
3753 // clipboard first, it's further down. | |
3754 parmp->servername = serverMakeName(parmp->serverName_arg, | |
3755 parmp->argv[0]); | |
3756 # ifdef MSWIN | |
3757 if (parmp->servername != NULL) | |
3758 { | |
3759 serverSetName(parmp->servername); | |
3760 vim_free(parmp->servername); | |
3761 } | |
3762 # endif | |
3763 } | |
3764 } | |
3765 | |
3766 /* | |
3767 * Prepare for running as a Vim server. | |
3768 */ | |
3769 static void | |
3770 prepare_server(mparm_T *parmp) | |
3771 { | |
3772 # if defined(FEAT_X11) | |
3773 /* | |
3774 * Register for remote command execution with :serversend and --remote | |
3775 * unless there was a -X or a --servername '' on the command line. | |
3776 * Only register nongui-vim's with an explicit --servername argument, | |
3777 * or when compiling with autoservername. | |
3778 * When running as root --servername is also required. | |
3779 */ | |
3780 if (X_DISPLAY != NULL && parmp->servername != NULL && ( | |
3781 # if defined(FEAT_AUTOSERVERNAME) || defined(FEAT_GUI) | |
3782 ( | |
3783 # if defined(FEAT_AUTOSERVERNAME) | |
3784 1 | |
3785 # else | |
3786 gui.in_use | |
3787 # endif | |
3788 # ifdef UNIX | |
3789 && getuid() != ROOT_UID | |
3790 # endif | |
3791 ) || | |
3792 # endif | |
3793 parmp->serverName_arg != NULL)) | |
3794 { | |
3795 (void)serverRegisterName(X_DISPLAY, parmp->servername); | |
3796 vim_free(parmp->servername); | |
3797 TIME_MSG("register server name"); | |
3798 } | |
3799 else | |
3800 serverDelayedStartName = parmp->servername; | |
3801 # endif | |
3802 | |
3803 /* | |
3804 * Execute command ourselves if we're here because the send failed (or | |
3805 * else we would have exited above). | |
3806 */ | |
3807 if (parmp->serverStr != NULL) | |
3808 { | |
3809 char_u *p; | |
3810 | |
3811 server_to_input_buf(serverConvert(parmp->serverStrEnc, | |
3812 parmp->serverStr, &p)); | |
3813 vim_free(p); | |
3814 } | |
3815 } | |
3816 | |
3817 static void | |
3818 cmdsrv_main( | |
3819 int *argc, | |
3820 char **argv, | |
3821 char_u *serverName_arg, | |
3822 char_u **serverStr) | |
3823 { | |
3824 char_u *res; | |
3825 int i; | |
3826 char_u *sname; | |
3827 int ret; | |
3828 int didone = FALSE; | |
3829 int exiterr = 0; | |
3830 char **newArgV = argv + 1; | |
3831 int newArgC = 1, | |
3832 Argc = *argc; | |
3833 int argtype; | |
3834 #define ARGTYPE_OTHER 0 | |
3835 #define ARGTYPE_EDIT 1 | |
3836 #define ARGTYPE_EDIT_WAIT 2 | |
3837 #define ARGTYPE_SEND 3 | |
3838 int silent = FALSE; | |
3839 int tabs = FALSE; | |
3840 # ifndef FEAT_X11 | |
3841 HWND srv; | |
3842 # else | |
3843 Window srv; | |
3844 | |
3845 setup_term_clip(); | |
3846 # endif | |
3847 | |
3848 sname = serverMakeName(serverName_arg, argv[0]); | |
3849 if (sname == NULL) | |
3850 return; | |
3851 | |
3852 /* | |
3853 * Execute the command server related arguments and remove them | |
3854 * from the argc/argv array; We may have to return into main() | |
3855 */ | |
3856 for (i = 1; i < Argc; i++) | |
3857 { | |
3858 res = NULL; | |
3859 if (STRCMP(argv[i], "--") == 0) // end of option arguments | |
3860 { | |
3861 for (; i < *argc; i++) | |
3862 { | |
3863 *newArgV++ = argv[i]; | |
3864 newArgC++; | |
3865 } | |
3866 break; | |
3867 } | |
3868 | |
3869 if (STRICMP(argv[i], "--remote-send") == 0) | |
3870 argtype = ARGTYPE_SEND; | |
3871 else if (STRNICMP(argv[i], "--remote", 8) == 0) | |
3872 { | |
3873 char *p = argv[i] + 8; | |
3874 | |
3875 argtype = ARGTYPE_EDIT; | |
3876 while (*p != NUL) | |
3877 { | |
3878 if (STRNICMP(p, "-wait", 5) == 0) | |
3879 { | |
3880 argtype = ARGTYPE_EDIT_WAIT; | |
3881 p += 5; | |
3882 } | |
3883 else if (STRNICMP(p, "-silent", 7) == 0) | |
3884 { | |
3885 silent = TRUE; | |
3886 p += 7; | |
3887 } | |
3888 else if (STRNICMP(p, "-tab", 4) == 0) | |
3889 { | |
3890 tabs = TRUE; | |
3891 p += 4; | |
3892 } | |
3893 else | |
3894 { | |
3895 argtype = ARGTYPE_OTHER; | |
3896 break; | |
3897 } | |
3898 } | |
3899 } | |
3900 else | |
3901 argtype = ARGTYPE_OTHER; | |
3902 | |
3903 if (argtype != ARGTYPE_OTHER) | |
3904 { | |
3905 if (i == *argc - 1) | |
3906 mainerr_arg_missing((char_u *)argv[i]); | |
3907 if (argtype == ARGTYPE_SEND) | |
3908 { | |
3909 *serverStr = (char_u *)argv[i + 1]; | |
3910 i++; | |
3911 } | |
3912 else | |
3913 { | |
3914 *serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1, | |
3915 tabs, argtype == ARGTYPE_EDIT_WAIT); | |
3916 if (*serverStr == NULL) | |
3917 { | |
3918 // Probably out of memory, exit. | |
3919 didone = TRUE; | |
3920 exiterr = 1; | |
3921 break; | |
3922 } | |
3923 Argc = i; | |
3924 } | |
3925 # ifdef FEAT_X11 | |
3926 if (xterm_dpy == NULL) | |
3927 { | |
3928 mch_errmsg(_("No display")); | |
3929 ret = -1; | |
3930 } | |
3931 else | |
3932 ret = serverSendToVim(xterm_dpy, sname, *serverStr, | |
3933 NULL, &srv, 0, 0, 0, silent); | |
3934 # else | |
3935 // Win32 always works? | |
3936 ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, 0, silent); | |
3937 # endif | |
3938 if (ret < 0) | |
3939 { | |
3940 if (argtype == ARGTYPE_SEND) | |
3941 { | |
3942 // Failed to send, abort. | |
3943 mch_errmsg(_(": Send failed.\n")); | |
3944 didone = TRUE; | |
3945 exiterr = 1; | |
3946 } | |
3947 else if (!silent) | |
3948 // Let vim start normally. | |
3949 mch_errmsg(_(": Send failed. Trying to execute locally\n")); | |
3950 break; | |
3951 } | |
3952 | |
3953 # ifdef FEAT_GUI_MSWIN | |
3954 // Guess that when the server name starts with "g" it's a GUI | |
3955 // server, which we can bring to the foreground here. | |
3956 // Foreground() in the server doesn't work very well. | |
3957 if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G') | |
3958 SetForegroundWindow(srv); | |
3959 # endif | |
3960 | |
3961 /* | |
3962 * For --remote-wait: Wait until the server did edit each | |
3963 * file. Also detect that the server no longer runs. | |
3964 */ | |
3965 if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT) | |
3966 { | |
3967 int numFiles = *argc - i - 1; | |
3968 int j; | |
3969 char_u *done = alloc(numFiles); | |
3970 char_u *p; | |
3971 # ifdef FEAT_GUI_MSWIN | |
3972 NOTIFYICONDATA ni; | |
3973 int count = 0; | |
3974 extern HWND message_window; | |
3975 # endif | |
3976 | |
3977 if (numFiles > 0 && argv[i + 1][0] == '+') | |
3978 // Skip "+cmd" argument, don't wait for it to be edited. | |
3979 --numFiles; | |
3980 | |
3981 # ifdef FEAT_GUI_MSWIN | |
3982 ni.cbSize = sizeof(ni); | |
3983 ni.hWnd = message_window; | |
3984 ni.uID = 0; | |
3985 ni.uFlags = NIF_ICON|NIF_TIP; | |
3986 ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM"); | |
3987 sprintf(ni.szTip, _("%d of %d edited"), count, numFiles); | |
3988 Shell_NotifyIcon(NIM_ADD, &ni); | |
3989 # endif | |
3990 | |
3991 // Wait for all files to unload in remote | |
3992 vim_memset(done, 0, numFiles); | |
3993 while (memchr(done, 0, numFiles) != NULL) | |
3994 { | |
3995 # ifdef MSWIN | |
3996 p = serverGetReply(srv, NULL, TRUE, TRUE, 0); | |
3997 if (p == NULL) | |
3998 break; | |
3999 # else | |
4000 if (serverReadReply(xterm_dpy, srv, &p, TRUE, -1) < 0) | |
4001 break; | |
4002 # endif | |
4003 j = atoi((char *)p); | |
4004 if (j >= 0 && j < numFiles) | |
4005 { | |
4006 # ifdef FEAT_GUI_MSWIN | |
4007 ++count; | |
4008 sprintf(ni.szTip, _("%d of %d edited"), | |
4009 count, numFiles); | |
4010 Shell_NotifyIcon(NIM_MODIFY, &ni); | |
4011 # endif | |
4012 done[j] = 1; | |
4013 } | |
4014 } | |
4015 # ifdef FEAT_GUI_MSWIN | |
4016 Shell_NotifyIcon(NIM_DELETE, &ni); | |
4017 # endif | |
4018 } | |
4019 } | |
4020 else if (STRICMP(argv[i], "--remote-expr") == 0) | |
4021 { | |
4022 if (i == *argc - 1) | |
4023 mainerr_arg_missing((char_u *)argv[i]); | |
4024 # ifdef MSWIN | |
4025 // Win32 always works? | |
4026 if (serverSendToVim(sname, (char_u *)argv[i + 1], | |
4027 &res, NULL, 1, 0, FALSE) < 0) | |
4028 # else | |
4029 if (xterm_dpy == NULL) | |
4030 mch_errmsg(_("No display: Send expression failed.\n")); | |
4031 else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1], | |
4032 &res, NULL, 1, 0, 1, FALSE) < 0) | |
4033 # endif | |
4034 { | |
4035 if (res != NULL && *res != NUL) | |
4036 { | |
4037 // Output error from remote | |
4038 mch_errmsg((char *)res); | |
4039 VIM_CLEAR(res); | |
4040 } | |
4041 mch_errmsg(_(": Send expression failed.\n")); | |
4042 } | |
4043 } | |
4044 else if (STRICMP(argv[i], "--serverlist") == 0) | |
4045 { | |
4046 # ifdef MSWIN | |
4047 // Win32 always works? | |
4048 res = serverGetVimNames(); | |
4049 # else | |
4050 if (xterm_dpy != NULL) | |
4051 res = serverGetVimNames(xterm_dpy); | |
4052 # endif | |
4053 if (did_emsg) | |
4054 mch_errmsg("\n"); | |
4055 } | |
4056 else if (STRICMP(argv[i], "--servername") == 0) | |
4057 { | |
4058 // Already processed. Take it out of the command line | |
4059 i++; | |
4060 continue; | |
4061 } | |
4062 else | |
4063 { | |
4064 *newArgV++ = argv[i]; | |
4065 newArgC++; | |
4066 continue; | |
4067 } | |
4068 didone = TRUE; | |
4069 if (res != NULL && *res != NUL) | |
4070 { | |
4071 mch_msg((char *)res); | |
4072 if (res[STRLEN(res) - 1] != '\n') | |
4073 mch_msg("\n"); | |
4074 } | |
4075 vim_free(res); | |
4076 } | |
4077 | |
4078 if (didone) | |
4079 { | |
4080 display_errors(); // display any collected messages | |
4081 exit(exiterr); // Mission accomplished - get out | |
4082 } | |
4083 | |
4084 // Return back into main() | |
4085 *argc = newArgC; | |
4086 vim_free(sname); | |
4087 } | |
4088 | |
4089 /* | |
4090 * Build a ":drop" command to send to a Vim server. | |
4091 */ | |
4092 static char_u * | |
4093 build_drop_cmd( | |
4094 int filec, | |
4095 char **filev, | |
4096 int tabs, // Use ":tab drop" instead of ":drop". | |
4097 int sendReply) | |
4098 { | |
4099 garray_T ga; | |
4100 int i; | |
4101 char_u *inicmd = NULL; | |
4102 char_u *p; | |
4103 char_u *cdp; | |
4104 char_u *cwd; | |
4105 | |
4106 if (filec > 0 && filev[0][0] == '+') | |
4107 { | |
4108 inicmd = (char_u *)filev[0] + 1; | |
4109 filev++; | |
4110 filec--; | |
4111 } | |
4112 // Check if we have at least one argument. | |
4113 if (filec <= 0) | |
4114 mainerr_arg_missing((char_u *)filev[-1]); | |
4115 | |
4116 // Temporarily cd to the current directory to handle relative file names. | |
4117 cwd = alloc(MAXPATHL); | |
4118 if (cwd == NULL) | |
4119 return NULL; | |
4120 if (mch_dirname(cwd, MAXPATHL) != OK) | |
4121 { | |
4122 vim_free(cwd); | |
4123 return NULL; | |
4124 } | |
4125 cdp = vim_strsave_escaped_ext(cwd, | |
4126 #ifdef BACKSLASH_IN_FILENAME | |
4127 (char_u *)"", // rem_backslash() will tell what chars to escape | |
4128 #else | |
4129 PATH_ESC_CHARS, | |
4130 #endif | |
4131 '\\', TRUE); | |
4132 vim_free(cwd); | |
4133 if (cdp == NULL) | |
4134 return NULL; | |
4135 ga_init2(&ga, 1, 100); | |
4136 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd "); | |
4137 ga_concat(&ga, cdp); | |
4138 | |
4139 // Call inputsave() so that a prompt for an encryption key works. | |
4140 ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|"); | |
4141 if (tabs) | |
4142 ga_concat(&ga, (char_u *)"tab "); | |
4143 ga_concat(&ga, (char_u *)"drop"); | |
4144 for (i = 0; i < filec; i++) | |
4145 { | |
4146 // On Unix the shell has already expanded the wildcards, don't want to | |
4147 // do it again in the Vim server. On MS-Windows only escape | |
4148 // non-wildcard characters. | |
4149 p = vim_strsave_escaped((char_u *)filev[i], | |
4150 #ifdef UNIX | |
4151 PATH_ESC_CHARS | |
4152 #else | |
4153 (char_u *)" \t%#" | |
4154 #endif | |
4155 ); | |
4156 if (p == NULL) | |
4157 { | |
4158 vim_free(ga.ga_data); | |
4159 return NULL; | |
4160 } | |
4161 ga_concat(&ga, (char_u *)" "); | |
4162 ga_concat(&ga, p); | |
4163 vim_free(p); | |
4164 } | |
4165 ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>"); | |
4166 | |
4167 // The :drop commands goes to Insert mode when 'insertmode' is set, use | |
4168 // CTRL-\ CTRL-N again. | |
4169 ga_concat(&ga, (char_u *)"<C-\\><C-N>"); | |
4170 | |
4171 // Switch back to the correct current directory (prior to temporary path | |
4172 // switch) unless 'autochdir' is set, in which case it will already be | |
4173 // correct after the :drop command. With line breaks and spaces: | |
4174 // if !exists('+acd') || !&acd | |
4175 // if haslocaldir() | |
4176 // cd - | |
4177 // lcd - | |
4178 // elseif getcwd() ==# 'current path' | |
4179 // cd - | |
4180 // endif | |
4181 // endif | |
4182 ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|"); | |
4183 ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '"); | |
4184 ga_concat(&ga, cdp); | |
4185 ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>"); | |
4186 vim_free(cdp); | |
4187 | |
4188 if (sendReply) | |
4189 ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>"); | |
4190 ga_concat(&ga, (char_u *)":"); | |
4191 if (inicmd != NULL) | |
4192 { | |
4193 // Can't use <CR> after "inicmd", because an "startinsert" would cause | |
4194 // the following commands to be inserted as text. Use a "|", | |
4195 // hopefully "inicmd" does allow this... | |
4196 ga_concat(&ga, inicmd); | |
4197 ga_concat(&ga, (char_u *)"|"); | |
4198 } | |
4199 // Bring the window to the foreground, goto Insert mode when 'im' set and | |
4200 // clear command line. | |
4201 ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>"); | |
4202 ga_append(&ga, NUL); | |
4203 return ga.ga_data; | |
4204 } | |
4205 | |
4206 /* | |
4207 * Make our basic server name: use the specified "arg" if given, otherwise use | |
4208 * the tail of the command "cmd" we were started with. | |
4209 * Return the name in allocated memory. This doesn't include a serial number. | |
4210 */ | |
4211 static char_u * | |
4212 serverMakeName(char_u *arg, char *cmd) | |
4213 { | |
4214 char_u *p; | |
4215 | |
4216 if (arg != NULL && *arg != NUL) | |
4217 p = vim_strsave_up(arg); | |
4218 else | |
4219 { | |
4220 p = vim_strsave_up(gettail((char_u *)cmd)); | |
4221 // Remove .exe or .bat from the name. | |
4222 if (p != NULL && vim_strchr(p, '.') != NULL) | |
4223 *vim_strchr(p, '.') = NUL; | |
4224 } | |
4225 return p; | |
4226 } | |
4227 #endif // FEAT_CLIENTSERVER | |
4228 | |
4229 #if defined(FEAT_CLIENTSERVER) || defined(PROTO) | |
4230 /* | |
4231 * Replace termcodes such as <CR> and insert as key presses if there is room. | |
4232 */ | |
4233 void | |
4234 server_to_input_buf(char_u *str) | |
4235 { | |
4236 char_u *ptr = NULL; | |
4237 char_u *cpo_save = p_cpo; | |
4238 | |
4239 // Set 'cpoptions' the way we want it. | |
4240 // B set - backslashes are *not* treated specially | |
4241 // k set - keycodes are *not* reverse-engineered | |
4242 // < unset - <Key> sequences *are* interpreted | |
4243 // The last but one parameter of replace_termcodes() is TRUE so that the | |
4244 // <lt> sequence is recognised - needed for a real backslash. | |
4245 p_cpo = (char_u *)"Bk"; | |
4246 str = replace_termcodes((char_u *)str, &ptr, REPTERM_DO_LT, NULL); | |
4247 p_cpo = cpo_save; | |
4248 | |
4249 if (*ptr != NUL) // trailing CTRL-V results in nothing | |
4250 { | |
4251 /* | |
4252 * Add the string to the input stream. | |
4253 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes. | |
4254 * | |
4255 * First clear typed characters from the typeahead buffer, there could | |
4256 * be half a mapping there. Then append to the existing string, so | |
4257 * that multiple commands from a client are concatenated. | |
4258 */ | |
4259 if (typebuf.tb_maplen < typebuf.tb_len) | |
4260 del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen); | |
4261 (void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE); | |
4262 | |
4263 // Let input_available() know we inserted text in the typeahead | |
4264 // buffer. | |
4265 typebuf_was_filled = TRUE; | |
4266 } | |
4267 vim_free((char_u *)ptr); | |
4268 } | |
4269 | |
4270 /* | |
4271 * Evaluate an expression that the client sent to a string. | |
4272 */ | |
4273 char_u * | |
4274 eval_client_expr_to_string(char_u *expr) | |
4275 { | |
4276 char_u *res; | |
4277 int save_dbl = debug_break_level; | |
4278 int save_ro = redir_off; | |
4279 funccal_entry_T funccal_entry; | |
4280 int did_save_funccal = FALSE; | |
4281 | |
4282 // Evaluate the expression at the toplevel, don't use variables local to | |
4283 // the calling function. Except when in debug mode. | |
4284 if (!debug_mode) | |
4285 { | |
4286 save_funccal(&funccal_entry); | |
4287 did_save_funccal = TRUE; | |
4288 } | |
4289 | |
4290 // Disable debugging, otherwise Vim hangs, waiting for "cont" to be | |
4291 // typed. | |
4292 debug_break_level = -1; | |
4293 redir_off = 0; | |
4294 // Do not display error message, otherwise Vim hangs, waiting for "cont" | |
4295 // to be typed. Do generate errors so that try/catch works. | |
4296 ++emsg_silent; | |
4297 | |
4298 res = eval_to_string(expr, NULL, TRUE); | |
4299 | |
4300 debug_break_level = save_dbl; | |
4301 redir_off = save_ro; | |
4302 --emsg_silent; | |
4303 if (emsg_silent < 0) | |
4304 emsg_silent = 0; | |
4305 if (did_save_funccal) | |
4306 restore_funccal(); | |
4307 | |
4308 // A client can tell us to redraw, but not to display the cursor, so do | |
4309 // that here. | |
4310 setcursor(); | |
4311 out_flush_cursor(FALSE, FALSE); | |
4312 | |
4313 return res; | |
4314 } | |
4315 | |
4316 /* | |
4317 * Evaluate a command or expression sent to ourselves. | |
4318 */ | |
4319 int | |
4320 sendToLocalVim(char_u *cmd, int asExpr, char_u **result) | |
4321 { | |
4322 if (asExpr) | |
4323 { | |
4324 char_u *ret; | |
4325 | |
4326 ret = eval_client_expr_to_string(cmd); | |
4327 if (result != NULL) | |
4328 { | |
4329 if (ret == NULL) | |
4330 { | |
4331 char *err = _(e_invexprmsg); | |
4332 size_t len = STRLEN(cmd) + STRLEN(err) + 5; | |
4333 char_u *msg; | |
4334 | |
4335 msg = alloc(len); | |
4336 if (msg != NULL) | |
4337 vim_snprintf((char *)msg, len, "%s: \"%s\"", err, cmd); | |
4338 *result = msg; | |
4339 } | |
4340 else | |
4341 *result = ret; | |
4342 } | |
4343 else | |
4344 vim_free(ret); | |
4345 return ret == NULL ? -1 : 0; | |
4346 } | |
4347 server_to_input_buf(cmd); | |
4348 return 0; | |
4349 } | |
4350 | |
4351 /* | |
4352 * If conversion is needed, convert "data" from "client_enc" to 'encoding' and | |
4353 * return an allocated string. Otherwise return "data". | |
4354 * "*tofree" is set to the result when it needs to be freed later. | |
4355 */ | |
4356 char_u * | |
4357 serverConvert( | |
4358 char_u *client_enc UNUSED, | |
4359 char_u *data, | |
4360 char_u **tofree) | |
4361 { | |
4362 char_u *res = data; | |
4363 | |
4364 *tofree = NULL; | |
4365 if (client_enc != NULL && p_enc != NULL) | |
4366 { | |
4367 vimconv_T vimconv; | |
4368 | |
4369 vimconv.vc_type = CONV_NONE; | |
4370 if (convert_setup(&vimconv, client_enc, p_enc) != FAIL | |
4371 && vimconv.vc_type != CONV_NONE) | |
4372 { | |
4373 res = string_convert(&vimconv, data, NULL); | |
4374 if (res == NULL) | |
4375 res = data; | |
4376 else | |
4377 *tofree = res; | |
4378 } | |
4379 convert_setup(&vimconv, NULL, NULL); | |
4380 } | |
4381 return res; | |
4382 } | |
4383 #endif |