Mercurial > vim
annotate src/if_xcmdsrv.c @ 16150:b23048205589 v8.1.1080
patch 8.1.1080: when a screendump test fails, moving the file is a hassle
commit https://github.com/vim/vim/commit/ef7f0e367eeaf6fb31b1caa0e3de1a4b07e86af3
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Mar 30 15:59:51 2019 +0100
patch 8.1.1080: when a screendump test fails, moving the file is a hassle
Problem: When a screendump test fails, moving the file is a hassle.
Solution: Instead of appending ".failed" to the file name, keep the same
file name but put the screendump in the "failed" directory.
Then the file name only needs to be typed once when moving a
screendump.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 30 Mar 2019 16:00:06 +0100 |
parents | 536dd2bc5ac9 |
children | ef00b6bc186b |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
8732
diff
changeset
|
1 /* vi:set ts=8 sts=4 sw=4 noet: |
7 | 2 * |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * X command server by Flemming Madsen | |
5 * | |
6 * Do ":help uganda" in Vim to read copying and usage conditions. | |
7 * Do ":help credits" in Vim to see a list of people who contributed. | |
8 * See README.txt for an overview of the Vim source code. | |
9 * | |
10 * if_xcmdsrv.c: Functions for passing commands through an X11 display. | |
11 * | |
12 */ | |
13 | |
14 #include "vim.h" | |
15 #include "version.h" | |
16 | |
17 #if defined(FEAT_CLIENTSERVER) || defined(PROTO) | |
18 | |
19 # ifdef FEAT_X11 | |
20 # include <X11/Intrinsic.h> | |
21 # include <X11/Xatom.h> | |
22 # endif | |
23 | |
24 /* | |
1121 | 25 * This file provides procedures that implement the command server |
26 * functionality of Vim when in contact with an X11 server. | |
7 | 27 * |
28 * Adapted from TCL/TK's send command in tkSend.c of the tk 3.6 distribution. | |
29 * Adapted for use in Vim by Flemming Madsen. Protocol changed to that of tk 4 | |
30 */ | |
31 | |
32 /* | |
33 * Copyright (c) 1989-1993 The Regents of the University of California. | |
34 * All rights reserved. | |
35 * | |
36 * Permission is hereby granted, without written agreement and without | |
37 * license or royalty fees, to use, copy, modify, and distribute this | |
38 * software and its documentation for any purpose, provided that the | |
39 * above copyright notice and the following two paragraphs appear in | |
40 * all copies of this software. | |
41 * | |
42 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR | |
43 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT | |
44 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF | |
45 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
46 * | |
47 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, | |
48 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
49 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | |
50 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO | |
51 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
52 */ | |
53 | |
54 | |
55 /* | |
56 * When a result is being awaited from a sent command, one of | |
57 * the following structures is present on a list of all outstanding | |
58 * sent commands. The information in the structure is used to | |
59 * process the result when it arrives. You're probably wondering | |
60 * how there could ever be multiple outstanding sent commands. | |
61 * This could happen if Vim instances invoke each other recursively. | |
62 * It's unlikely, but possible. | |
63 */ | |
64 | |
65 typedef struct PendingCommand | |
66 { | |
67 int serial; /* Serial number expected in result. */ | |
68 int code; /* Result Code. 0 is OK */ | |
69 char_u *result; /* String result for command (malloc'ed). | |
70 * NULL means command still pending. */ | |
71 struct PendingCommand *nextPtr; | |
72 /* Next in list of all outstanding commands. | |
73 * NULL means end of list. */ | |
74 } PendingCommand; | |
75 | |
76 static PendingCommand *pendingCommands = NULL; | |
77 /* List of all commands currently | |
78 * being waited for. */ | |
79 | |
80 /* | |
81 * The information below is used for communication between processes | |
82 * during "send" commands. Each process keeps a private window, never | |
83 * even mapped, with one property, "Comm". When a command is sent to | |
84 * an interpreter, the command is appended to the comm property of the | |
85 * communication window associated with the interp's process. Similarly, | |
86 * when a result is returned from a sent command, it is also appended | |
87 * to the comm property. | |
88 * | |
89 * Each command and each result takes the form of ASCII text. For a | |
90 * command, the text consists of a nul character followed by several | |
39 | 91 * nul-terminated ASCII strings. The first string consists of a |
92 * single letter: | |
93 * "c" for an expression | |
94 * "k" for keystrokes | |
95 * "r" for reply | |
96 * "n" for notification. | |
97 * Subsequent strings have the form "option value" where the following options | |
98 * are supported: | |
7 | 99 * |
100 * -r commWindow serial | |
101 * | |
102 * This option means that a response should be sent to the window | |
103 * whose X identifier is "commWindow" (in hex), and the response should | |
104 * be identified with the serial number given by "serial" (in decimal). | |
105 * If this option isn't specified then the send is asynchronous and | |
106 * no response is sent. | |
107 * | |
108 * -n name | |
109 * "Name" gives the name of the application for which the command is | |
110 * intended. This option must be present. | |
111 * | |
39 | 112 * -E encoding |
113 * Encoding name used for the text. This is the 'encoding' of the | |
114 * sender. The receiver may want to do conversion to his 'encoding'. | |
115 * | |
7 | 116 * -s script |
117 * "Script" is the script to be executed. This option must be | |
118 * present. Taken as a series of keystrokes in a "k" command where | |
119 * <Key>'s are expanded | |
120 * | |
121 * The options may appear in any order. The -n and -s options must be | |
122 * present, but -r may be omitted for asynchronous RPCs. For compatibility | |
123 * with future releases that may add new features, there may be additional | |
124 * options present; as long as they start with a "-" character, they will | |
125 * be ignored. | |
126 * | |
127 * A result also consists of a zero character followed by several null- | |
128 * terminated ASCII strings. The first string consists of the single | |
129 * letter "r". Subsequent strings have the form "option value" where | |
130 * the following options are supported: | |
131 * | |
132 * -s serial | |
133 * Identifies the command for which this is the result. It is the | |
134 * same as the "serial" field from the -s option in the command. This | |
135 * option must be present. | |
136 * | |
137 * -r result | |
138 * "Result" is the result string for the script, which may be either | |
139 * a result or an error message. If this field is omitted then it | |
140 * defaults to an empty string. | |
141 * | |
142 * -c code | |
143 * 0: for OK. This is the default. | |
144 * 1: for error: Result is the last error | |
145 * | |
146 * -i errorInfo | |
147 * -e errorCode | |
148 * Not applicable for Vim | |
149 * | |
150 * Options may appear in any order, and only the -s option must be | |
151 * present. As with commands, there may be additional options besides | |
152 * these; unknown options are ignored. | |
153 */ | |
154 | |
155 /* | |
156 * Maximum size property that can be read at one time by | |
157 * this module: | |
158 */ | |
159 | |
160 #define MAX_PROP_WORDS 100000 | |
161 | |
162 struct ServerReply | |
163 { | |
164 Window id; | |
165 garray_T strings; | |
166 }; | |
167 static garray_T serverReply = { 0, 0, 0, 0, 0 }; | |
168 enum ServerReplyOp { SROP_Find, SROP_Add, SROP_Delete }; | |
169 | |
7803
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
170 typedef int (*EndCond)(void *); |
7 | 171 |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
172 struct x_cmdqueue |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
173 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
174 char_u *propInfo; |
7123
077ae8b63e15
commit https://github.com/vim/vim/commit/b8603882b1679385b287f14c527fa61eee60a9dd
Christian Brabandt <cb@256bit.org>
parents:
7109
diff
changeset
|
175 long_u len; |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
176 struct x_cmdqueue *next; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
177 struct x_cmdqueue *prev; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
178 }; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
179 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
180 typedef struct x_cmdqueue x_queue_T; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
181 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
182 /* dummy node, header for circular queue */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
183 static x_queue_T head = {NULL, 0, NULL, NULL}; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
184 |
7 | 185 /* |
186 * Forward declarations for procedures defined later in this file: | |
187 */ | |
188 | |
7803
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
189 static Window LookupName(Display *dpy, char_u *name, int delete, char_u **loose); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
190 static int SendInit(Display *dpy); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
191 static int DoRegisterName(Display *dpy, char_u *name); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
192 static void DeleteAnyLingerer(Display *dpy, Window w); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
193 static int GetRegProp(Display *dpy, char_u **regPropp, long_u *numItemsp, int domsg); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
194 static int WaitForPend(void *p); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
195 static int WindowValid(Display *dpy, Window w); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
196 static void ServerWait(Display *dpy, Window w, EndCond endCond, void *endData, int localLoop, int seconds); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
197 static int AppendPropCarefully(Display *display, Window window, Atom property, char_u *value, int length); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
198 static int x_error_check(Display *dpy, XErrorEvent *error_event); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
199 static int IsSerialName(char_u *name); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
200 static void save_in_queue(char_u *buf, long_u len); |
37c929c4a073
commit https://github.com/vim/vim/commit/92b8b2d307e34117f146319872010b0ccc9d2713
Christian Brabandt <cb@256bit.org>
parents:
7172
diff
changeset
|
201 static void server_parse_message(Display *dpy, char_u *propInfo, long_u numItems); |
7 | 202 |
203 /* Private variables for the "server" functionality */ | |
204 static Atom registryProperty = None; | |
205 static Atom vimProperty = None; | |
206 static int got_x_error = FALSE; | |
207 | |
208 static char_u *empty_prop = (char_u *)""; /* empty GetRegProp() result */ | |
209 | |
210 /* | |
211 * Associate an ASCII name with Vim. Try real hard to get a unique one. | |
212 * Returns FAIL or OK. | |
213 */ | |
214 int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
215 serverRegisterName( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
216 Display *dpy, /* display to register with */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
217 char_u *name) /* the name that will be used as a base */ |
7 | 218 { |
219 int i; | |
220 int res; | |
221 char_u *p = NULL; | |
222 | |
223 res = DoRegisterName(dpy, name); | |
224 if (res < 0) | |
225 { | |
226 i = 1; | |
227 do | |
228 { | |
229 if (res < -1 || i >= 1000) | |
230 { | |
15547
1dd0a47f4be2
patch 8.1.0781: build error when using if_xcmdsrv.c
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
231 msg_attr(_("Unable to register a command server name"), |
11158
501f46f7644c
patch 8.0.0466: still macros that should be all-caps
Christian Brabandt <cb@256bit.org>
parents:
10942
diff
changeset
|
232 HL_ATTR(HLF_W)); |
7 | 233 return FAIL; |
234 } | |
235 if (p == NULL) | |
236 p = alloc(STRLEN(name) + 10); | |
237 if (p == NULL) | |
238 { | |
239 res = -10; | |
240 continue; | |
241 } | |
242 sprintf((char *)p, "%s%d", name, i++); | |
243 res = DoRegisterName(dpy, p); | |
244 } | |
245 while (res < 0) | |
246 ; | |
247 vim_free(p); | |
248 } | |
249 return OK; | |
250 } | |
251 | |
252 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
253 DoRegisterName(Display *dpy, char_u *name) |
7 | 254 { |
255 Window w; | |
256 XErrorHandler old_handler; | |
257 #define MAX_NAME_LENGTH 100 | |
258 char_u propInfo[MAX_NAME_LENGTH + 20]; | |
259 | |
260 if (commProperty == None) | |
261 { | |
262 if (SendInit(dpy) < 0) | |
263 return -2; | |
264 } | |
265 | |
266 /* | |
267 * Make sure the name is unique, and append info about it to | |
268 * the registry property. It's important to lock the server | |
269 * here to prevent conflicting changes to the registry property. | |
270 * WARNING: Do not step through this while debugging, it will hangup the X | |
271 * server! | |
272 */ | |
273 XGrabServer(dpy); | |
274 w = LookupName(dpy, name, FALSE, NULL); | |
275 if (w != (Window)0) | |
276 { | |
277 Status status; | |
278 int dummyInt; | |
279 unsigned int dummyUns; | |
280 Window dummyWin; | |
281 | |
282 /* | |
283 * The name is currently registered. See if the commWindow | |
284 * associated with the name exists. If not, or if the commWindow | |
285 * is *our* commWindow, then just unregister the old name (this | |
286 * could happen if an application dies without cleaning up the | |
287 * registry). | |
288 */ | |
289 old_handler = XSetErrorHandler(x_error_check); | |
290 status = XGetGeometry(dpy, w, &dummyWin, &dummyInt, &dummyInt, | |
291 &dummyUns, &dummyUns, &dummyUns, &dummyUns); | |
292 (void)XSetErrorHandler(old_handler); | |
293 if (status != Success && w != commWindow) | |
294 { | |
295 XUngrabServer(dpy); | |
296 XFlush(dpy); | |
297 return -1; | |
298 } | |
299 (void)LookupName(dpy, name, /*delete=*/TRUE, NULL); | |
300 } | |
301 sprintf((char *)propInfo, "%x %.*s", (int_u)commWindow, | |
302 MAX_NAME_LENGTH, name); | |
303 old_handler = XSetErrorHandler(x_error_check); | |
304 got_x_error = FALSE; | |
305 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, 8, | |
306 PropModeAppend, propInfo, STRLEN(propInfo) + 1); | |
307 XUngrabServer(dpy); | |
308 XSync(dpy, False); | |
309 (void)XSetErrorHandler(old_handler); | |
310 | |
311 if (!got_x_error) | |
312 { | |
313 #ifdef FEAT_EVAL | |
314 set_vim_var_string(VV_SEND_SERVER, name, -1); | |
315 #endif | |
316 serverName = vim_strsave(name); | |
317 #ifdef FEAT_TITLE | |
318 need_maketitle = TRUE; | |
319 #endif | |
320 return 0; | |
321 } | |
322 return -2; | |
323 } | |
324 | |
325 #if defined(FEAT_GUI) || defined(PROTO) | |
326 /* | |
327 * Clean out new ID from registry and set it as comm win. | |
328 * Change any registered window ID. | |
329 */ | |
330 void | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
331 serverChangeRegisteredWindow( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
332 Display *dpy, /* Display to register with */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
333 Window newwin) /* Re-register to this ID */ |
7 | 334 { |
335 char_u propInfo[MAX_NAME_LENGTH + 20]; | |
336 | |
337 commWindow = newwin; | |
338 | |
339 /* Always call SendInit() here, to make sure commWindow is marked as a Vim | |
340 * window. */ | |
341 if (SendInit(dpy) < 0) | |
342 return; | |
343 | |
344 /* WARNING: Do not step through this while debugging, it will hangup the X | |
345 * server! */ | |
346 XGrabServer(dpy); | |
347 DeleteAnyLingerer(dpy, newwin); | |
348 if (serverName != NULL) | |
349 { | |
350 /* Reinsert name if we was already registered */ | |
351 (void)LookupName(dpy, serverName, /*delete=*/TRUE, NULL); | |
352 sprintf((char *)propInfo, "%x %.*s", | |
353 (int_u)newwin, MAX_NAME_LENGTH, serverName); | |
354 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, 8, | |
355 PropModeAppend, (char_u *)propInfo, | |
356 STRLEN(propInfo) + 1); | |
357 } | |
358 XUngrabServer(dpy); | |
359 } | |
360 #endif | |
361 | |
362 /* | |
363 * Send to an instance of Vim via the X display. | |
364 * Returns 0 for OK, negative for an error. | |
365 */ | |
366 int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
367 serverSendToVim( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
368 Display *dpy, /* Where to send. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
369 char_u *name, /* Where to send. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
370 char_u *cmd, /* What to send. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
371 char_u **result, /* Result of eval'ed expression */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
372 Window *server, /* Actual ID of receiving app */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
373 Bool asExpr, /* Interpret as keystrokes or expr ? */ |
11211
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
374 int timeout, /* seconds to wait or zero */ |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
375 Bool localLoop, /* Throw away everything but result */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
376 int silent) /* don't complain about no server */ |
7 | 377 { |
378 Window w; | |
379 char_u *property; | |
380 int length; | |
381 int res; | |
382 static int serial = 0; /* Running count of sent commands. | |
383 * Used to give each command a | |
384 * different serial number. */ | |
385 PendingCommand pending; | |
386 char_u *loosename = NULL; | |
387 | |
388 if (result != NULL) | |
389 *result = NULL; | |
390 if (name == NULL || *name == NUL) | |
391 name = (char_u *)"GVIM"; /* use a default name */ | |
392 | |
393 if (commProperty == None && dpy != NULL) | |
394 { | |
395 if (SendInit(dpy) < 0) | |
396 return -1; | |
397 } | |
398 | |
399 /* Execute locally if no display or target is ourselves */ | |
400 if (dpy == NULL || (serverName != NULL && STRICMP(name, serverName) == 0)) | |
11177
76fb679a310e
patch 8.0.0475: not enough testing for the client-server feature
Christian Brabandt <cb@256bit.org>
parents:
11158
diff
changeset
|
401 return sendToLocalVim(cmd, asExpr, result); |
7 | 402 |
403 /* | |
404 * Bind the server name to a communication window. | |
405 * | |
406 * Find any survivor with a serialno attached to the name if the | |
407 * original registrant of the wanted name is no longer present. | |
408 * | |
409 * Delete any lingering names from dead editors. | |
410 */ | |
411 while (TRUE) | |
412 { | |
413 w = LookupName(dpy, name, FALSE, &loosename); | |
414 /* Check that the window is hot */ | |
415 if (w != None) | |
416 { | |
417 if (!WindowValid(dpy, w)) | |
418 { | |
419 LookupName(dpy, loosename ? loosename : name, | |
420 /*DELETE=*/TRUE, NULL); | |
12399
de1ae9d8ef57
patch 8.0.1079: memory leak when remote_foreground() fails
Christian Brabandt <cb@256bit.org>
parents:
11211
diff
changeset
|
421 vim_free(loosename); |
7 | 422 continue; |
423 } | |
424 } | |
425 break; | |
426 } | |
427 if (w == None) | |
428 { | |
429 if (!silent) | |
15470
55ccc2d353bd
patch 8.1.0743: giving error messages is not flexible
Bram Moolenaar <Bram@vim.org>
parents:
14862
diff
changeset
|
430 semsg(_(e_noserver), name); |
7 | 431 return -1; |
432 } | |
433 else if (loosename != NULL) | |
434 name = loosename; | |
435 if (server != NULL) | |
436 *server = w; | |
437 | |
438 /* | |
439 * Send the command to target interpreter by appending it to the | |
440 * comm window in the communication window. | |
500 | 441 * Length must be computed exactly! |
7 | 442 */ |
500 | 443 length = STRLEN(name) + STRLEN(p_enc) + STRLEN(cmd) + 14; |
39 | 444 property = (char_u *)alloc((unsigned)length + 30); |
7 | 445 |
39 | 446 sprintf((char *)property, "%c%c%c-n %s%c-E %s%c-s %s", |
447 0, asExpr ? 'c' : 'k', 0, name, 0, p_enc, 0, cmd); | |
7 | 448 if (name == loosename) |
449 vim_free(loosename); | |
450 /* Add a back reference to our comm window */ | |
451 serial++; | |
452 sprintf((char *)property + length, "%c-r %x %d", | |
453 0, (int_u)commWindow, serial); | |
500 | 454 /* Add length of what "-r %x %d" resulted in, skipping the NUL. */ |
7 | 455 length += STRLEN(property + length + 1) + 1; |
456 | |
457 res = AppendPropCarefully(dpy, w, commProperty, property, length + 1); | |
458 vim_free(property); | |
459 if (res < 0) | |
460 { | |
15470
55ccc2d353bd
patch 8.1.0743: giving error messages is not flexible
Bram Moolenaar <Bram@vim.org>
parents:
14862
diff
changeset
|
461 emsg(_("E248: Failed to send command to the destination program")); |
7 | 462 return -1; |
463 } | |
464 | |
465 if (!asExpr) /* There is no answer for this - Keys are sent async */ | |
466 return 0; | |
467 | |
468 /* | |
469 * Register the fact that we're waiting for a command to | |
470 * complete (this is needed by SendEventProc and by | |
471 * AppendErrorProc to pass back the command's results). | |
472 */ | |
473 pending.serial = serial; | |
474 pending.code = 0; | |
475 pending.result = NULL; | |
476 pending.nextPtr = pendingCommands; | |
477 pendingCommands = &pending; | |
478 | |
11211
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
479 ServerWait(dpy, w, WaitForPend, &pending, localLoop, |
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
480 timeout > 0 ? timeout : 600); |
7 | 481 |
482 /* | |
483 * Unregister the information about the pending command | |
484 * and return the result. | |
485 */ | |
486 if (pendingCommands == &pending) | |
487 pendingCommands = pending.nextPtr; | |
488 else | |
489 { | |
490 PendingCommand *pcPtr; | |
491 | |
492 for (pcPtr = pendingCommands; pcPtr != NULL; pcPtr = pcPtr->nextPtr) | |
493 if (pcPtr->nextPtr == &pending) | |
494 { | |
495 pcPtr->nextPtr = pending.nextPtr; | |
496 break; | |
497 } | |
498 } | |
499 if (result != NULL) | |
500 *result = pending.result; | |
501 else | |
502 vim_free(pending.result); | |
503 | |
504 return pending.code == 0 ? 0 : -1; | |
505 } | |
506 | |
507 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
508 WaitForPend(void *p) |
7 | 509 { |
510 PendingCommand *pending = (PendingCommand *) p; | |
511 return pending->result != NULL; | |
512 } | |
513 | |
514 /* | |
515 * Return TRUE if window "w" exists and has a "Vim" property on it. | |
516 */ | |
517 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
518 WindowValid(Display *dpy, Window w) |
7 | 519 { |
520 XErrorHandler old_handler; | |
521 Atom *plist; | |
522 int numProp; | |
523 int i; | |
524 | |
525 old_handler = XSetErrorHandler(x_error_check); | |
526 got_x_error = 0; | |
527 plist = XListProperties(dpy, w, &numProp); | |
528 XSync(dpy, False); | |
529 XSetErrorHandler(old_handler); | |
530 if (plist == NULL || got_x_error) | |
531 return FALSE; | |
532 | |
533 for (i = 0; i < numProp; i++) | |
534 if (plist[i] == vimProperty) | |
535 { | |
536 XFree(plist); | |
537 return TRUE; | |
538 } | |
539 XFree(plist); | |
540 return FALSE; | |
541 } | |
542 | |
543 /* | |
544 * Enter a loop processing X events & polling chars until we see a result | |
545 */ | |
546 static void | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
547 ServerWait( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
548 Display *dpy, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
549 Window w, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
550 EndCond endCond, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
551 void *endData, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
552 int localLoop, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
553 int seconds) |
7 | 554 { |
555 time_t start; | |
556 time_t now; | |
557 XEvent event; | |
3670 | 558 |
559 #define UI_MSEC_DELAY 50 | |
560 #define SEND_MSEC_POLL 500 | |
561 #ifndef HAVE_SELECT | |
562 struct pollfd fds; | |
563 | |
564 fds.fd = ConnectionNumber(dpy); | |
565 fds.events = POLLIN; | |
566 #else | |
567 fd_set fds; | |
568 struct timeval tv; | |
569 | |
570 tv.tv_sec = 0; | |
571 tv.tv_usec = SEND_MSEC_POLL * 1000; | |
572 FD_ZERO(&fds); | |
573 FD_SET(ConnectionNumber(dpy), &fds); | |
574 #endif | |
7 | 575 |
576 time(&start); | |
3670 | 577 while (TRUE) |
7 | 578 { |
3670 | 579 while (XCheckWindowEvent(dpy, commWindow, PropertyChangeMask, &event)) |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
580 serverEventProc(dpy, &event, 1); |
8732
29765df3a866
commit https://github.com/vim/vim/commit/1e7885abe8daa793fd9328d0fd6c456214cb467e
Christian Brabandt <cb@256bit.org>
parents:
7823
diff
changeset
|
581 server_parse_messages(); |
3670 | 582 |
583 if (endCond(endData) != 0) | |
584 break; | |
585 if (!WindowValid(dpy, w)) | |
586 break; | |
7 | 587 time(&now); |
588 if (seconds >= 0 && (now - start) >= seconds) | |
589 break; | |
3670 | 590 |
11181
13544aa85dc0
patch 8.0.0477: the client-server test may hang when failing
Christian Brabandt <cb@256bit.org>
parents:
11177
diff
changeset
|
591 #ifdef FEAT_TIMERS |
13544aa85dc0
patch 8.0.0477: the client-server test may hang when failing
Christian Brabandt <cb@256bit.org>
parents:
11177
diff
changeset
|
592 check_due_timer(); |
13544aa85dc0
patch 8.0.0477: the client-server test may hang when failing
Christian Brabandt <cb@256bit.org>
parents:
11177
diff
changeset
|
593 #endif |
13544aa85dc0
patch 8.0.0477: the client-server test may hang when failing
Christian Brabandt <cb@256bit.org>
parents:
11177
diff
changeset
|
594 |
3670 | 595 /* Just look out for the answer without calling back into Vim */ |
7 | 596 if (localLoop) |
597 { | |
598 #ifndef HAVE_SELECT | |
599 if (poll(&fds, 1, SEND_MSEC_POLL) < 0) | |
600 break; | |
601 #else | |
3670 | 602 if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) < 0) |
7 | 603 break; |
604 #endif | |
605 } | |
606 else | |
607 { | |
608 if (got_int) | |
609 break; | |
3670 | 610 ui_delay((long)UI_MSEC_DELAY, TRUE); |
7 | 611 ui_breakcheck(); |
612 } | |
613 } | |
614 } | |
615 | |
616 | |
617 /* | |
618 * Fetch a list of all the Vim instance names currently registered for the | |
619 * display. | |
620 * | |
621 * Returns a newline separated list in allocated memory or NULL. | |
622 */ | |
623 char_u * | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
624 serverGetVimNames(Display *dpy) |
7 | 625 { |
626 char_u *regProp; | |
627 char_u *entry; | |
628 char_u *p; | |
629 long_u numItems; | |
630 int_u w; | |
631 garray_T ga; | |
632 | |
633 if (registryProperty == None) | |
634 { | |
635 if (SendInit(dpy) < 0) | |
636 return NULL; | |
637 } | |
638 | |
639 /* | |
640 * Read the registry property. | |
641 */ | |
642 if (GetRegProp(dpy, ®Prop, &numItems, TRUE) == FAIL) | |
643 return NULL; | |
644 | |
645 /* | |
646 * Scan all of the names out of the property. | |
647 */ | |
648 ga_init2(&ga, 1, 100); | |
1880 | 649 for (p = regProp; (long_u)(p - regProp) < numItems; p++) |
7 | 650 { |
651 entry = p; | |
652 while (*p != 0 && !isspace(*p)) | |
653 p++; | |
654 if (*p != 0) | |
655 { | |
656 w = None; | |
657 sscanf((char *)entry, "%x", &w); | |
658 if (WindowValid(dpy, (Window)w)) | |
659 { | |
660 ga_concat(&ga, p + 1); | |
661 ga_concat(&ga, (char_u *)"\n"); | |
662 } | |
663 while (*p != 0) | |
664 p++; | |
665 } | |
666 } | |
667 if (regProp != empty_prop) | |
668 XFree(regProp); | |
21 | 669 ga_append(&ga, NUL); |
7 | 670 return ga.ga_data; |
671 } | |
672 | |
673 /* ---------------------------------------------------------- | |
674 * Reply stuff | |
675 */ | |
676 | |
677 static struct ServerReply * | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
678 ServerReplyFind(Window w, enum ServerReplyOp op) |
7 | 679 { |
680 struct ServerReply *p; | |
681 struct ServerReply e; | |
682 int i; | |
683 | |
684 p = (struct ServerReply *) serverReply.ga_data; | |
685 for (i = 0; i < serverReply.ga_len; i++, p++) | |
686 if (p->id == w) | |
687 break; | |
688 if (i >= serverReply.ga_len) | |
689 p = NULL; | |
690 | |
691 if (p == NULL && op == SROP_Add) | |
692 { | |
693 if (serverReply.ga_growsize == 0) | |
694 ga_init2(&serverReply, sizeof(struct ServerReply), 1); | |
695 if (ga_grow(&serverReply, 1) == OK) | |
696 { | |
697 p = ((struct ServerReply *) serverReply.ga_data) | |
698 + serverReply.ga_len; | |
699 e.id = w; | |
700 ga_init2(&e.strings, 1, 100); | |
1740 | 701 mch_memmove(p, &e, sizeof(e)); |
7 | 702 serverReply.ga_len++; |
703 } | |
704 } | |
705 else if (p != NULL && op == SROP_Delete) | |
706 { | |
707 ga_clear(&p->strings); | |
708 mch_memmove(p, p + 1, (serverReply.ga_len - i - 1) * sizeof(*p)); | |
709 serverReply.ga_len--; | |
710 } | |
711 | |
712 return p; | |
713 } | |
714 | |
715 /* | |
716 * Convert string to windowid. | |
717 * Issue an error if the id is invalid. | |
718 */ | |
719 Window | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
720 serverStrToWin(char_u *str) |
7 | 721 { |
722 unsigned id = None; | |
723 | |
724 sscanf((char *)str, "0x%x", &id); | |
725 if (id == None) | |
15470
55ccc2d353bd
patch 8.1.0743: giving error messages is not flexible
Bram Moolenaar <Bram@vim.org>
parents:
14862
diff
changeset
|
726 semsg(_("E573: Invalid server id used: %s"), str); |
7 | 727 |
728 return (Window)id; | |
729 } | |
730 | |
731 /* | |
39 | 732 * Send a reply string (notification) to client with id "name". |
7 | 733 * Return -1 if the window is invalid. |
734 */ | |
735 int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
736 serverSendReply(char_u *name, char_u *str) |
7 | 737 { |
738 char_u *property; | |
739 int length; | |
740 int res; | |
741 Display *dpy = X_DISPLAY; | |
742 Window win = serverStrToWin(name); | |
743 | |
744 if (commProperty == None) | |
745 { | |
746 if (SendInit(dpy) < 0) | |
747 return -2; | |
748 } | |
749 if (!WindowValid(dpy, win)) | |
750 return -1; | |
751 | |
500 | 752 length = STRLEN(p_enc) + STRLEN(str) + 14; |
39 | 753 if ((property = (char_u *)alloc((unsigned)length + 30)) != NULL) |
7 | 754 { |
39 | 755 sprintf((char *)property, "%cn%c-E %s%c-n %s%c-w %x", |
756 0, 0, p_enc, 0, str, 0, (unsigned int)commWindow); | |
500 | 757 /* Add length of what "%x" resulted in. */ |
7 | 758 length += STRLEN(property + length); |
759 res = AppendPropCarefully(dpy, win, commProperty, property, length + 1); | |
760 vim_free(property); | |
761 return res; | |
762 } | |
763 return -1; | |
764 } | |
765 | |
766 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
767 WaitForReply(void *p) |
7 | 768 { |
769 Window *w = (Window *) p; | |
11177
76fb679a310e
patch 8.0.0475: not enough testing for the client-server feature
Christian Brabandt <cb@256bit.org>
parents:
11158
diff
changeset
|
770 |
7 | 771 return ServerReplyFind(*w, SROP_Find) != NULL; |
772 } | |
773 | |
774 /* | |
775 * Wait for replies from id (win) | |
11211
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
776 * When "timeout" is non-zero wait up to this many seconds. |
7 | 777 * Return 0 and the malloc'ed string when a reply is available. |
778 * Return -1 if the window becomes invalid while waiting. | |
779 */ | |
780 int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
781 serverReadReply( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
782 Display *dpy, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
783 Window win, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
784 char_u **str, |
11211
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
785 int localLoop, |
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
786 int timeout) |
7 | 787 { |
788 int len; | |
789 char_u *s; | |
790 struct ServerReply *p; | |
791 | |
11211
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
792 ServerWait(dpy, win, WaitForReply, &win, localLoop, |
71311d899b42
patch 8.0.0492: a failing client-server request can make Vim hang
Christian Brabandt <cb@256bit.org>
parents:
11181
diff
changeset
|
793 timeout > 0 ? timeout : -1); |
7 | 794 |
795 if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0) | |
796 { | |
797 *str = vim_strsave(p->strings.ga_data); | |
798 len = STRLEN(*str) + 1; | |
799 if (len < p->strings.ga_len) | |
800 { | |
801 s = (char_u *) p->strings.ga_data; | |
802 mch_memmove(s, s + len, p->strings.ga_len - len); | |
803 p->strings.ga_len -= len; | |
804 } | |
805 else | |
806 { | |
807 /* Last string read. Remove from list */ | |
808 ga_clear(&p->strings); | |
809 ServerReplyFind(win, SROP_Delete); | |
810 } | |
811 return 0; | |
812 } | |
813 return -1; | |
814 } | |
815 | |
816 /* | |
817 * Check for replies from id (win). | |
818 * Return TRUE and a non-malloc'ed string if there is. Else return FALSE. | |
819 */ | |
820 int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
821 serverPeekReply(Display *dpy, Window win, char_u **str) |
7 | 822 { |
823 struct ServerReply *p; | |
824 | |
825 if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0) | |
826 { | |
827 if (str != NULL) | |
828 *str = p->strings.ga_data; | |
829 return 1; | |
830 } | |
831 if (!WindowValid(dpy, win)) | |
832 return -1; | |
833 return 0; | |
834 } | |
835 | |
836 | |
837 /* | |
838 * Initialize the communication channels for sending commands and receiving | |
839 * results. | |
840 */ | |
841 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
842 SendInit(Display *dpy) |
7 | 843 { |
844 XErrorHandler old_handler; | |
845 | |
846 /* | |
847 * Create the window used for communication, and set up an | |
848 * event handler for it. | |
849 */ | |
850 old_handler = XSetErrorHandler(x_error_check); | |
851 got_x_error = FALSE; | |
852 | |
853 if (commProperty == None) | |
854 commProperty = XInternAtom(dpy, "Comm", False); | |
855 if (vimProperty == None) | |
856 vimProperty = XInternAtom(dpy, "Vim", False); | |
857 if (registryProperty == None) | |
858 registryProperty = XInternAtom(dpy, "VimRegistry", False); | |
859 | |
860 if (commWindow == None) | |
861 { | |
862 commWindow = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), | |
863 getpid(), 0, 10, 10, 0, | |
864 WhitePixel(dpy, DefaultScreen(dpy)), | |
865 WhitePixel(dpy, DefaultScreen(dpy))); | |
866 XSelectInput(dpy, commWindow, PropertyChangeMask); | |
867 /* WARNING: Do not step through this while debugging, it will hangup | |
868 * the X server! */ | |
869 XGrabServer(dpy); | |
870 DeleteAnyLingerer(dpy, commWindow); | |
871 XUngrabServer(dpy); | |
872 } | |
873 | |
874 /* Make window recognizable as a vim window */ | |
875 XChangeProperty(dpy, commWindow, vimProperty, XA_STRING, | |
876 8, PropModeReplace, (char_u *)VIM_VERSION_SHORT, | |
877 (int)STRLEN(VIM_VERSION_SHORT) + 1); | |
878 | |
879 XSync(dpy, False); | |
880 (void)XSetErrorHandler(old_handler); | |
881 | |
882 return got_x_error ? -1 : 0; | |
883 } | |
884 | |
885 /* | |
886 * Given a server name, see if the name exists in the registry for a | |
887 * particular display. | |
888 * | |
889 * If the given name is registered, return the ID of the window associated | |
890 * with the name. If the name isn't registered, then return 0. | |
891 * | |
892 * Side effects: | |
893 * If the registry property is improperly formed, then it is deleted. | |
894 * If "delete" is non-zero, then if the named server is found it is | |
895 * removed from the registry property. | |
896 */ | |
897 static Window | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
898 LookupName( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
899 Display *dpy, /* Display whose registry to check. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
900 char_u *name, /* Name of a server. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
901 int delete, /* If non-zero, delete info about name. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
902 char_u **loose) /* Do another search matching -999 if not found |
7 | 903 Return result here if a match is found */ |
904 { | |
905 char_u *regProp, *entry; | |
906 char_u *p; | |
907 long_u numItems; | |
908 int_u returnValue; | |
909 | |
910 /* | |
911 * Read the registry property. | |
912 */ | |
913 if (GetRegProp(dpy, ®Prop, &numItems, FALSE) == FAIL) | |
914 return 0; | |
915 | |
916 /* | |
917 * Scan the property for the desired name. | |
918 */ | |
919 returnValue = (int_u)None; | |
920 entry = NULL; /* Not needed, but eliminates compiler warning. */ | |
1880 | 921 for (p = regProp; (long_u)(p - regProp) < numItems; ) |
7 | 922 { |
923 entry = p; | |
924 while (*p != 0 && !isspace(*p)) | |
925 p++; | |
926 if (*p != 0 && STRICMP(name, p + 1) == 0) | |
927 { | |
928 sscanf((char *)entry, "%x", &returnValue); | |
929 break; | |
930 } | |
931 while (*p != 0) | |
932 p++; | |
933 p++; | |
934 } | |
935 | |
936 if (loose != NULL && returnValue == (int_u)None && !IsSerialName(name)) | |
937 { | |
1880 | 938 for (p = regProp; (long_u)(p - regProp) < numItems; ) |
7 | 939 { |
940 entry = p; | |
941 while (*p != 0 && !isspace(*p)) | |
942 p++; | |
943 if (*p != 0 && IsSerialName(p + 1) | |
944 && STRNICMP(name, p + 1, STRLEN(name)) == 0) | |
945 { | |
946 sscanf((char *)entry, "%x", &returnValue); | |
947 *loose = vim_strsave(p + 1); | |
948 break; | |
949 } | |
950 while (*p != 0) | |
951 p++; | |
952 p++; | |
953 } | |
954 } | |
955 | |
956 /* | |
957 * Delete the property, if that is desired (copy down the | |
958 * remainder of the registry property to overlay the deleted | |
959 * info, then rewrite the property). | |
960 */ | |
961 if (delete && returnValue != (int_u)None) | |
962 { | |
963 int count; | |
964 | |
965 while (*p != 0) | |
966 p++; | |
967 p++; | |
968 count = numItems - (p - regProp); | |
969 if (count > 0) | |
1740 | 970 mch_memmove(entry, p, count); |
7 | 971 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, |
972 8, PropModeReplace, regProp, | |
973 (int)(numItems - (p - entry))); | |
974 XSync(dpy, False); | |
975 } | |
976 | |
977 if (regProp != empty_prop) | |
978 XFree(regProp); | |
979 return (Window)returnValue; | |
980 } | |
981 | |
982 /* | |
1197 | 983 * Delete any lingering occurrence of window id. We promise that any |
984 * occurrence is not ours since it is not yet put into the registry (by us) | |
7 | 985 * |
986 * This is necessary in the following scenario: | |
987 * 1. There is an old windowid for an exit'ed vim in the registry | |
988 * 2. We get that id for our commWindow but only want to send, not register. | |
989 * 3. The window will mistakenly be regarded valid because of own commWindow | |
990 */ | |
991 static void | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
992 DeleteAnyLingerer( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
993 Display *dpy, /* Display whose registry to check. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
994 Window win) /* Window to remove */ |
7 | 995 { |
996 char_u *regProp, *entry = NULL; | |
997 char_u *p; | |
998 long_u numItems; | |
28 | 999 int_u wwin; |
7 | 1000 |
1001 /* | |
1002 * Read the registry property. | |
1003 */ | |
1004 if (GetRegProp(dpy, ®Prop, &numItems, FALSE) == FAIL) | |
1005 return; | |
1006 | |
1007 /* Scan the property for the window id. */ | |
1880 | 1008 for (p = regProp; (long_u)(p - regProp) < numItems; ) |
7 | 1009 { |
1010 if (*p != 0) | |
1011 { | |
28 | 1012 sscanf((char *)p, "%x", &wwin); |
1013 if ((Window)wwin == win) | |
7 | 1014 { |
1015 int lastHalf; | |
1016 | |
1017 /* Copy down the remainder to delete entry */ | |
1018 entry = p; | |
1019 while (*p != 0) | |
1020 p++; | |
1021 p++; | |
1022 lastHalf = numItems - (p - regProp); | |
1023 if (lastHalf > 0) | |
1740 | 1024 mch_memmove(entry, p, lastHalf); |
7 | 1025 numItems = (entry - regProp) + lastHalf; |
1026 p = entry; | |
1027 continue; | |
1028 } | |
1029 } | |
1030 while (*p != 0) | |
1031 p++; | |
1032 p++; | |
1033 } | |
1034 | |
1035 if (entry != NULL) | |
1036 { | |
1037 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, | |
1038 XA_STRING, 8, PropModeReplace, regProp, | |
1039 (int)(p - regProp)); | |
1040 XSync(dpy, False); | |
1041 } | |
1042 | |
1043 if (regProp != empty_prop) | |
1044 XFree(regProp); | |
1045 } | |
1046 | |
1047 /* | |
1048 * Read the registry property. Delete it when it's formatted wrong. | |
1049 * Return the property in "regPropp". "empty_prop" is used when it doesn't | |
1050 * exist yet. | |
1051 * Return OK when successful. | |
1052 */ | |
1053 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1054 GetRegProp( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1055 Display *dpy, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1056 char_u **regPropp, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1057 long_u *numItemsp, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1058 int domsg) /* When TRUE give error message. */ |
7 | 1059 { |
1060 int result, actualFormat; | |
1061 long_u bytesAfter; | |
1062 Atom actualType; | |
819 | 1063 XErrorHandler old_handler; |
7 | 1064 |
1065 *regPropp = NULL; | |
819 | 1066 old_handler = XSetErrorHandler(x_error_check); |
1067 got_x_error = FALSE; | |
1068 | |
7 | 1069 result = XGetWindowProperty(dpy, RootWindow(dpy, 0), registryProperty, 0L, |
1070 (long)MAX_PROP_WORDS, False, | |
1071 XA_STRING, &actualType, | |
1072 &actualFormat, numItemsp, &bytesAfter, | |
1073 regPropp); | |
1074 | |
819 | 1075 XSync(dpy, FALSE); |
1076 (void)XSetErrorHandler(old_handler); | |
1077 if (got_x_error) | |
1078 return FAIL; | |
1079 | |
7 | 1080 if (actualType == None) |
1081 { | |
1082 /* No prop yet. Logically equal to the empty list */ | |
1083 *numItemsp = 0; | |
1084 *regPropp = empty_prop; | |
1085 return OK; | |
1086 } | |
1087 | |
1088 /* If the property is improperly formed, then delete it. */ | |
1089 if (result != Success || actualFormat != 8 || actualType != XA_STRING) | |
1090 { | |
1091 if (*regPropp != NULL) | |
1092 XFree(*regPropp); | |
1093 XDeleteProperty(dpy, RootWindow(dpy, 0), registryProperty); | |
1094 if (domsg) | |
15470
55ccc2d353bd
patch 8.1.0743: giving error messages is not flexible
Bram Moolenaar <Bram@vim.org>
parents:
14862
diff
changeset
|
1095 emsg(_("E251: VIM instance registry property is badly formed. Deleted!")); |
7 | 1096 return FAIL; |
1097 } | |
1098 return OK; | |
1099 } | |
1100 | |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1101 |
7 | 1102 /* |
1197 | 1103 * This procedure is invoked by the various X event loops throughout Vims when |
7 | 1104 * a property changes on the communication window. This procedure reads the |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1105 * property and enqueues command requests and responses. If immediate is true, |
13353
8412df1479a3
patch 8.0.1550: various small problems in source files
Christian Brabandt <cb@256bit.org>
parents:
12399
diff
changeset
|
1106 * it runs the event immediately instead of enqueuing it. Immediate can cause |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1107 * unintended behavior and should only be used for code that blocks for a |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1108 * response. |
7 | 1109 */ |
1110 void | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1111 serverEventProc( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1112 Display *dpy, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1113 XEvent *eventPtr, /* Information about event. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1114 int immediate) /* Run event immediately. Should mostly be 0. */ |
7 | 1115 { |
1116 char_u *propInfo; | |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1117 int result, actualFormat; |
7 | 1118 long_u numItems, bytesAfter; |
1119 Atom actualType; | |
1120 | |
1121 if (eventPtr != NULL) | |
1122 { | |
1123 if (eventPtr->xproperty.atom != commProperty | |
1124 || eventPtr->xproperty.state != PropertyNewValue) | |
1125 return; | |
1126 } | |
1127 | |
1128 /* | |
1129 * Read the comm property and delete it. | |
1130 */ | |
1131 propInfo = NULL; | |
1132 result = XGetWindowProperty(dpy, commWindow, commProperty, 0L, | |
1133 (long)MAX_PROP_WORDS, True, | |
1134 XA_STRING, &actualType, | |
1135 &actualFormat, &numItems, &bytesAfter, | |
1136 &propInfo); | |
1137 | |
1138 /* If the property doesn't exist or is improperly formed then ignore it. */ | |
1139 if (result != Success || actualType != XA_STRING || actualFormat != 8) | |
1140 { | |
1141 if (propInfo != NULL) | |
1142 XFree(propInfo); | |
1143 return; | |
1144 } | |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1145 if (immediate) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1146 server_parse_message(dpy, propInfo, numItems); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1147 else |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1148 save_in_queue(propInfo, numItems); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1149 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1150 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1151 /* |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1152 * Saves x clientserver commands in a queue so that they can be called when |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1153 * vim is idle. |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1154 */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1155 static void |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1156 save_in_queue(char_u *propInfo, long_u len) |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1157 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1158 x_queue_T *node; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1159 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1160 node = (x_queue_T *)alloc(sizeof(x_queue_T)); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1161 if (node == NULL) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1162 return; /* out of memory */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1163 node->propInfo = propInfo; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1164 node->len = len; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1165 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1166 if (head.next == NULL) /* initialize circular queue */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1167 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1168 head.next = &head; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1169 head.prev = &head; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1170 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1171 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1172 /* insert node at tail of queue */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1173 node->next = &head; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1174 node->prev = head.prev; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1175 head.prev->next = node; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1176 head.prev = node; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1177 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1178 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1179 /* |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1180 * Parses queued clientserver messages. |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1181 */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1182 void |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1183 server_parse_messages(void) |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1184 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1185 x_queue_T *node; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1186 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1187 if (!X_DISPLAY) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1188 return; /* cannot happen? */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1189 while (head.next != NULL && head.next != &head) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1190 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1191 node = head.next; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1192 head.next = node->next; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1193 node->next->prev = node->prev; |
7172
ad57f5b5bd6c
commit https://github.com/vim/vim/commit/4e86150ec5b5158da92b28938ea55819dc890a14
Christian Brabandt <cb@256bit.org>
parents:
7123
diff
changeset
|
1194 server_parse_message(X_DISPLAY, node->propInfo, node->len); |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1195 vim_free(node); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1196 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1197 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1198 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1199 /* |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1200 * Returns a non-zero value if there are clientserver messages waiting |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1201 * int the queue. |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1202 */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1203 int |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1204 server_waiting(void) |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1205 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1206 return head.next != NULL && head.next != &head; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1207 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1208 |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1209 /* |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1210 * Prases a single clientserver message. A single message may contain multiple |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1211 * commands. |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1212 * "propInfo" will be freed. |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1213 */ |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1214 static void |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1215 server_parse_message( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1216 Display *dpy, |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1217 char_u *propInfo, /* A string containing 0 or more X commands */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1218 long_u numItems) /* The size of propInfo in bytes. */ |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1219 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1220 char_u *p; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1221 int code; |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1222 char_u *tofree; |
7 | 1223 |
1224 /* | |
1225 * Several commands and results could arrive in the property at | |
1226 * one time; each iteration through the outer loop handles a | |
1227 * single command or result. | |
1228 */ | |
1880 | 1229 for (p = propInfo; (long_u)(p - propInfo) < numItems; ) |
7 | 1230 { |
1231 /* | |
1232 * Ignore leading NULs; each command or result starts with a | |
1233 * NUL so that no matter how badly formed a preceding command | |
1234 * is, we'll be able to tell that a new command/result is | |
1235 * starting. | |
1236 */ | |
1237 if (*p == 0) | |
1238 { | |
1239 p++; | |
1240 continue; | |
1241 } | |
1242 | |
1243 if ((*p == 'c' || *p == 'k') && (p[1] == 0)) | |
1244 { | |
1245 Window resWindow; | |
3668 | 1246 char_u *name, *script, *serial, *end; |
7 | 1247 Bool asKeys = *p == 'k'; |
39 | 1248 char_u *enc; |
7 | 1249 |
1250 /* | |
1251 * This is an incoming command from some other application. | |
1252 * Iterate over all of its options. Stop when we reach | |
1253 * the end of the property or something that doesn't look | |
1254 * like an option. | |
1255 */ | |
1256 p += 2; | |
1257 name = NULL; | |
1258 resWindow = None; | |
1259 serial = (char_u *)""; | |
1260 script = NULL; | |
39 | 1261 enc = NULL; |
1880 | 1262 while ((long_u)(p - propInfo) < numItems && *p == '-') |
7 | 1263 { |
1264 switch (p[1]) | |
1265 { | |
1266 case 'r': | |
1267 end = skipwhite(p + 2); | |
1268 resWindow = 0; | |
1269 while (vim_isxdigit(*end)) | |
1270 { | |
1271 resWindow = 16 * resWindow + (long_u)hex2nr(*end); | |
1272 ++end; | |
1273 } | |
1274 if (end == p + 2 || *end != ' ') | |
1275 resWindow = None; | |
1276 else | |
1277 { | |
1278 p = serial = end + 1; | |
1279 clientWindow = resWindow; /* Remember in global */ | |
1280 } | |
1281 break; | |
1282 case 'n': | |
1283 if (p[2] == ' ') | |
1284 name = p + 3; | |
1285 break; | |
1286 case 's': | |
1287 if (p[2] == ' ') | |
1288 script = p + 3; | |
1289 break; | |
39 | 1290 case 'E': |
1291 if (p[2] == ' ') | |
1292 enc = p + 3; | |
1293 break; | |
7 | 1294 } |
1295 while (*p != 0) | |
1296 p++; | |
1297 p++; | |
1298 } | |
1299 | |
1300 if (script == NULL || name == NULL) | |
1301 continue; | |
1302 | |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1303 if (serverName != NULL && STRICMP(name, serverName) == 0) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1304 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1305 script = serverConvert(enc, script, &tofree); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1306 if (asKeys) |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1307 server_to_input_buf(script); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1308 else |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1309 { |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1310 char_u *res; |
3668 | 1311 |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1312 res = eval_client_expr_to_string(script); |
3668 | 1313 if (resWindow != None) |
1314 { | |
1315 garray_T reply; | |
1316 | |
1317 /* Initialize the result property. */ | |
1318 ga_init2(&reply, 1, 100); | |
7009 | 1319 (void)ga_grow(&reply, 50 + STRLEN(p_enc)); |
3668 | 1320 sprintf(reply.ga_data, "%cr%c-E %s%c-s %s%c-r ", |
39 | 1321 0, 0, p_enc, 0, serial, 0); |
3668 | 1322 reply.ga_len = 14 + STRLEN(p_enc) + STRLEN(serial); |
1323 | |
1324 /* Evaluate the expression and return the result. */ | |
1325 if (res != NULL) | |
1326 ga_concat(&reply, res); | |
1327 else | |
1328 { | |
1329 ga_concat(&reply, (char_u *)_(e_invexprmsg)); | |
1330 ga_append(&reply, 0); | |
1331 ga_concat(&reply, (char_u *)"-c 1"); | |
1332 } | |
1333 ga_append(&reply, NUL); | |
1334 (void)AppendPropCarefully(dpy, resWindow, commProperty, | |
1335 reply.ga_data, reply.ga_len); | |
1336 ga_clear(&reply); | |
1337 } | |
7109
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1338 vim_free(res); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1339 } |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1340 vim_free(tofree); |
fa95595fbc52
commit https://github.com/vim/vim/commit/93c88e0f6a4a8f7634ed84721daf4af46fc0d5db
Christian Brabandt <cb@256bit.org>
parents:
7009
diff
changeset
|
1341 } |
7 | 1342 } |
1343 else if (*p == 'r' && p[1] == 0) | |
1344 { | |
39 | 1345 int serial, gotSerial; |
1346 char_u *res; | |
1347 PendingCommand *pcPtr; | |
1348 char_u *enc; | |
7 | 1349 |
1350 /* | |
1351 * This is a reply to some command that we sent out. Iterate | |
1352 * over all of its options. Stop when we reach the end of the | |
1353 * property or something that doesn't look like an option. | |
1354 */ | |
1355 p += 2; | |
1356 gotSerial = 0; | |
1357 res = (char_u *)""; | |
1358 code = 0; | |
39 | 1359 enc = NULL; |
1880 | 1360 while ((long_u)(p - propInfo) < numItems && *p == '-') |
7 | 1361 { |
1362 switch (p[1]) | |
1363 { | |
1364 case 'r': | |
1365 if (p[2] == ' ') | |
1366 res = p + 3; | |
1367 break; | |
39 | 1368 case 'E': |
1369 if (p[2] == ' ') | |
1370 enc = p + 3; | |
1371 break; | |
7 | 1372 case 's': |
1373 if (sscanf((char *)p + 2, " %d", &serial) == 1) | |
1374 gotSerial = 1; | |
1375 break; | |
1376 case 'c': | |
1377 if (sscanf((char *)p + 2, " %d", &code) != 1) | |
1378 code = 0; | |
1379 break; | |
1380 } | |
1381 while (*p != 0) | |
1382 p++; | |
1383 p++; | |
1384 } | |
1385 | |
1386 if (!gotSerial) | |
1387 continue; | |
1388 | |
1389 /* | |
1390 * Give the result information to anyone who's | |
1391 * waiting for it. | |
1392 */ | |
1393 for (pcPtr = pendingCommands; pcPtr != NULL; pcPtr = pcPtr->nextPtr) | |
1394 { | |
1395 if (serial != pcPtr->serial || pcPtr->result != NULL) | |
1396 continue; | |
1397 | |
1398 pcPtr->code = code; | |
7009 | 1399 res = serverConvert(enc, res, &tofree); |
1400 if (tofree == NULL) | |
1401 res = vim_strsave(res); | |
1402 pcPtr->result = res; | |
7 | 1403 break; |
1404 } | |
1405 } | |
1406 else if (*p == 'n' && p[1] == 0) | |
1407 { | |
1408 Window win = 0; | |
1409 unsigned int u; | |
1410 int gotWindow; | |
1411 char_u *str; | |
1412 struct ServerReply *r; | |
39 | 1413 char_u *enc; |
7 | 1414 |
1415 /* | |
10942
e05695e59f6d
patch 8.0.0360: sometimes VimL is used instead of "Vim script"
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
1416 * This is a (n)otification. Sent with serverreply_send in Vim |
e05695e59f6d
patch 8.0.0360: sometimes VimL is used instead of "Vim script"
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
1417 * script. Execute any autocommand and save it for later retrieval |
7 | 1418 */ |
1419 p += 2; | |
1420 gotWindow = 0; | |
1421 str = (char_u *)""; | |
39 | 1422 enc = NULL; |
1880 | 1423 while ((long_u)(p - propInfo) < numItems && *p == '-') |
7 | 1424 { |
1425 switch (p[1]) | |
1426 { | |
1427 case 'n': | |
1428 if (p[2] == ' ') | |
1429 str = p + 3; | |
1430 break; | |
39 | 1431 case 'E': |
1432 if (p[2] == ' ') | |
1433 enc = p + 3; | |
1434 break; | |
7 | 1435 case 'w': |
1436 if (sscanf((char *)p + 2, " %x", &u) == 1) | |
1437 { | |
1438 win = u; | |
1439 gotWindow = 1; | |
1440 } | |
1441 break; | |
1442 } | |
1443 while (*p != 0) | |
1444 p++; | |
1445 p++; | |
1446 } | |
1447 | |
1448 if (!gotWindow) | |
1449 continue; | |
39 | 1450 str = serverConvert(enc, str, &tofree); |
7 | 1451 if ((r = ServerReplyFind(win, SROP_Add)) != NULL) |
1452 { | |
1453 ga_concat(&(r->strings), str); | |
21 | 1454 ga_append(&(r->strings), NUL); |
7 | 1455 } |
1698 | 1456 { |
1457 char_u winstr[30]; | |
1458 | |
1459 sprintf((char *)winstr, "0x%x", (unsigned int)win); | |
1460 apply_autocmds(EVENT_REMOTEREPLY, winstr, str, TRUE, curbuf); | |
1461 } | |
39 | 1462 vim_free(tofree); |
7 | 1463 } |
1464 else | |
1465 { | |
1466 /* | |
1467 * Didn't recognize this thing. Just skip through the next | |
1468 * null character and try again. | |
1469 * Even if we get an 'r'(eply) we will throw it away as we | |
1470 * never specify (and thus expect) one | |
1471 */ | |
1472 while (*p != 0) | |
1473 p++; | |
1474 p++; | |
1475 } | |
1476 } | |
1477 XFree(propInfo); | |
1478 } | |
1479 | |
1480 /* | |
1481 * Append a given property to a given window, but set up an X error handler so | |
1482 * that if the append fails this procedure can return an error code rather | |
1483 * than having Xlib panic. | |
1484 * Return: 0 for OK, -1 for error | |
1485 */ | |
1486 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1487 AppendPropCarefully( |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1488 Display *dpy, /* Display on which to operate. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1489 Window window, /* Window whose property is to be modified. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1490 Atom property, /* Name of property. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1491 char_u *value, /* Characters to append to property. */ |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1492 int length) /* How much to append */ |
7 | 1493 { |
1494 XErrorHandler old_handler; | |
1495 | |
1496 old_handler = XSetErrorHandler(x_error_check); | |
1497 got_x_error = FALSE; | |
1498 XChangeProperty(dpy, window, property, XA_STRING, 8, | |
1499 PropModeAppend, value, length); | |
1500 XSync(dpy, False); | |
1501 (void) XSetErrorHandler(old_handler); | |
1502 return got_x_error ? -1 : 0; | |
1503 } | |
1504 | |
1505 | |
1506 /* | |
1507 * Another X Error handler, just used to check for errors. | |
1508 */ | |
1509 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1510 x_error_check(Display *dpy UNUSED, XErrorEvent *error_event UNUSED) |
7 | 1511 { |
1512 got_x_error = TRUE; | |
1513 return 0; | |
1514 } | |
1515 | |
1516 /* | |
1517 * Check if "str" looks like it had a serial number appended. | |
1518 * Actually just checks if the name ends in a digit. | |
1519 */ | |
1520 static int | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
7803
diff
changeset
|
1521 IsSerialName(char_u *str) |
7 | 1522 { |
1523 int len = STRLEN(str); | |
1524 | |
1525 return (len > 1 && vim_isdigit(str[len - 1])); | |
1526 } | |
1527 #endif /* FEAT_CLIENTSERVER */ |