Mercurial > vim
annotate runtime/tools/xcmdsrv_client.c @ 34336:d2ad8733db75 v9.1.0101
patch 9.1.0101: upper-case of German sharp s should be U+1E9E
Commit: https://github.com/vim/vim/commit/bd1232a1faf56b614a1e74c4ce51bc6e0650ae00
Author: glepnir <glephunter@gmail.com>
Date: Mon Feb 12 22:14:53 2024 +0100
patch 9.1.0101: upper-case of German sharp s should be U+1E9E
Problem: upper-case of ? should be U+1E9E (CAPITAL LETTER SHARP S)
(fenuks)
Solution: Make gU, ~ and g~ convert the U+00DF LATIN SMALL LETTER SHARP S (?)
to U+1E9E LATIN CAPITAL LETTER SHARP S (?), update tests
(glepnir)
This is part of Unicode 5.1.0 from April 2008, so should be fairly safe
to use now and since 2017 is part of the German standard orthography,
according to Wikipedia:
https://en.wikipedia.org/wiki/Capital_%E1%BA%9E#cite_note-auto-12
There is however one exception: UnicodeData.txt for U+00DF
LATIN SMALL LETTER SHARP S does NOT define U+1E9E LATIN CAPITAL LETTER
SHARP S as its upper case version. Therefore, toupper() won't be able
to convert from lower sharp s to upper case sharp s (the other way
around however works, since U+00DF is considered the lower case
character of U+1E9E and therefore tolower() works correctly for the
upper case version).
fixes: #5573
closes: #14018
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 12 Feb 2024 22:45:02 +0100 |
parents | 1629cc65d78d |
children |
rev | line source |
---|---|
7 | 1 /* vi:set ts=8 sts=4 sw=4: |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * X-Windows communication 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 * Client for sending commands to an '+xcmdsrv' enabled vim. | |
11 * This is mostly a de-Vimified version of if_xcmdsrv.c in vim. | |
12 * See that file for a protocol specification. | |
13 * | |
14 * You can make a test program with a Makefile like: | |
15 * xcmdsrv_client: xcmdsrv_client.c | |
16 * cc -o $@ -g -DMAIN -I/usr/X11R6/include -L/usr/X11R6/lib $< -lX11 | |
17 * | |
18 */ | |
19 | |
20 #include <stdio.h> | |
21 #include <string.h> | |
22 #ifdef HAVE_SELECT | |
23 #include <sys/time.h> | |
24 #include <sys/types.h> | |
25 #include <unistd.h> | |
26 #else | |
27 #include <sys/poll.h> | |
28 #endif | |
29 #include <X11/Intrinsic.h> | |
30 #include <X11/Xatom.h> | |
31 | |
32 /* Client API */ | |
7807
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
33 char * sendToVim(Display *dpy, char *name, char *cmd, int asKeys, int *code); |
7 | 34 |
35 #ifdef MAIN | |
36 /* A sample program */ | |
37 main(int argc, char **argv) | |
38 { | |
39 char *res; | |
40 int code; | |
41 | |
42 if (argc == 4) | |
43 { | |
44 if ((res = sendToVim(XOpenDisplay(NULL), argv[2], argv[3], | |
45 argv[1][0] != 'e', &code)) != NULL) | |
46 { | |
47 if (code) | |
48 printf("Error code returned: %d\n", code); | |
49 puts(res); | |
50 } | |
51 exit(0); | |
52 } | |
53 else | |
54 fprintf(stderr, "Usage: %s {k|e} <server> <command>", argv[0]); | |
55 | |
56 exit(1); | |
57 } | |
58 #endif | |
59 | |
60 /* | |
61 * Maximum size property that can be read at one time by | |
62 * this module: | |
63 */ | |
64 | |
65 #define MAX_PROP_WORDS 100000 | |
66 | |
67 /* | |
68 * Forward declarations for procedures defined later in this file: | |
69 */ | |
70 | |
7807
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
71 static int x_error_check(Display *dpy, XErrorEvent *error_event); |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
72 static int AppendPropCarefully(Display *display, |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
73 Window window, Atom property, char *value, int length); |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
74 static Window LookupName(Display *dpy, char *name, |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
75 int delete, char **loose); |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
76 static int SendInit(Display *dpy); |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
77 static char *SendEventProc(Display *dpy, XEvent *eventPtr, |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
78 int expect, int *code); |
1a5d34492798
commit https://github.com/vim/vim/commit/d99df423c559d85c17779b3685426c489554908c
Christian Brabandt <cb@256bit.org>
parents:
7
diff
changeset
|
79 static int IsSerialName(char *name); |
7 | 80 |
81 /* Private variables */ | |
82 static Atom registryProperty = None; | |
83 static Atom commProperty = None; | |
84 static Window commWindow = None; | |
85 static int got_x_error = FALSE; | |
86 | |
87 | |
88 /* | |
89 * sendToVim -- | |
90 * Send to an instance of Vim via the X display. | |
91 * | |
92 * Results: | |
93 * A string with the result or NULL. Caller must free if non-NULL | |
94 */ | |
95 | |
96 char * | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
97 sendToVim( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
98 Display *dpy, /* Where to send. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
99 char *name, /* Where to send. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
100 char *cmd, /* What to send. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
101 int asKeys, /* Interpret as keystrokes or expr ? */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
102 int *code) /* Return code. 0 => OK */ |
7 | 103 { |
104 Window w; | |
105 Atom *plist; | |
106 XErrorHandler old_handler; | |
107 #define STATIC_SPACE 500 | |
108 char *property, staticSpace[STATIC_SPACE]; | |
109 int length; | |
110 int res; | |
111 static int serial = 0; /* Running count of sent commands. | |
112 * Used to give each command a | |
113 * different serial number. */ | |
114 XEvent event; | |
115 XPropertyEvent *e = (XPropertyEvent *)&event; | |
116 time_t start; | |
117 char *result; | |
118 char *loosename = NULL; | |
119 | |
120 if (commProperty == None && dpy != NULL) | |
121 { | |
122 if (SendInit(dpy) < 0) | |
123 return NULL; | |
124 } | |
125 | |
126 /* | |
127 * Bind the server name to a communication window. | |
128 * | |
129 * Find any survivor with a serialno attached to the name if the | |
130 * original registrant of the wanted name is no longer present. | |
131 * | |
132 * Delete any lingering names from dead editors. | |
133 */ | |
134 | |
135 old_handler = XSetErrorHandler(x_error_check); | |
136 while (TRUE) | |
137 { | |
138 got_x_error = FALSE; | |
139 w = LookupName(dpy, name, 0, &loosename); | |
140 /* Check that the window is hot */ | |
141 if (w != None) | |
142 { | |
143 plist = XListProperties(dpy, w, &res); | |
144 XSync(dpy, False); | |
145 if (plist != NULL) | |
146 XFree(plist); | |
147 if (got_x_error) | |
148 { | |
149 LookupName(dpy, loosename ? loosename : name, | |
150 /*DELETE=*/TRUE, NULL); | |
151 continue; | |
152 } | |
153 } | |
154 break; | |
155 } | |
156 if (w == None) | |
157 { | |
158 fprintf(stderr, "no registered server named %s\n", name); | |
159 return NULL; | |
160 } | |
161 else if (loosename != NULL) | |
162 name = loosename; | |
163 | |
164 /* | |
165 * Send the command to target interpreter by appending it to the | |
166 * comm window in the communication window. | |
167 */ | |
168 | |
169 length = strlen(name) + strlen(cmd) + 10; | |
170 if (length <= STATIC_SPACE) | |
171 property = staticSpace; | |
172 else | |
173 property = (char *) malloc((unsigned) length); | |
174 | |
175 serial++; | |
176 sprintf(property, "%c%c%c-n %s%c-s %s", | |
177 0, asKeys ? 'k' : 'c', 0, name, 0, cmd); | |
178 if (name == loosename) | |
179 free(loosename); | |
180 if (!asKeys) | |
181 { | |
182 /* Add a back reference to our comm window */ | |
183 sprintf(property + length, "%c-r %x %d", 0, (uint) commWindow, serial); | |
184 length += strlen(property + length + 1) + 1; | |
185 } | |
186 | |
187 res = AppendPropCarefully(dpy, w, commProperty, property, length + 1); | |
188 if (length > STATIC_SPACE) | |
189 free(property); | |
190 if (res < 0) | |
191 { | |
192 fprintf(stderr, "Failed to send command to the destination program\n"); | |
193 return NULL; | |
194 } | |
195 | |
196 if (asKeys) /* There is no answer for this - Keys are sent async */ | |
197 return NULL; | |
198 | |
199 | |
200 /* | |
201 * Enter a loop processing X events & pooling chars until we see the result | |
202 */ | |
203 | |
204 #define SEND_MSEC_POLL 50 | |
205 | |
206 time(&start); | |
207 while ((time((time_t *) 0) - start) < 60) | |
208 { | |
209 /* Look out for the answer */ | |
210 #ifndef HAVE_SELECT | |
211 struct pollfd fds; | |
212 | |
213 fds.fd = ConnectionNumber(dpy); | |
214 fds.events = POLLIN; | |
215 if (poll(&fds, 1, SEND_MSEC_POLL) < 0) | |
216 break; | |
217 #else | |
218 fd_set fds; | |
219 struct timeval tv; | |
220 | |
221 tv.tv_sec = 0; | |
222 tv.tv_usec = SEND_MSEC_POLL * 1000; | |
223 FD_ZERO(&fds); | |
224 FD_SET(ConnectionNumber(dpy), &fds); | |
225 if (select(ConnectionNumber(dpy) + 1, &fds, NULL, NULL, &tv) < 0) | |
226 break; | |
227 #endif | |
228 while (XEventsQueued(dpy, QueuedAfterReading) > 0) | |
229 { | |
230 XNextEvent(dpy, &event); | |
231 if (event.type == PropertyNotify && e->window == commWindow) | |
232 if ((result = SendEventProc(dpy, &event, serial, code)) != NULL) | |
233 return result; | |
234 } | |
235 } | |
236 return NULL; | |
237 } | |
238 | |
239 | |
240 /* | |
241 * SendInit -- | |
242 * This procedure is called to initialize the | |
243 * communication channels for sending commands and | |
244 * receiving results. | |
245 */ | |
246 | |
247 static int | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
248 SendInit(Display *dpy) |
7 | 249 { |
250 XErrorHandler old_handler; | |
251 | |
252 /* | |
253 * Create the window used for communication, and set up an | |
254 * event handler for it. | |
255 */ | |
256 old_handler = XSetErrorHandler(x_error_check); | |
257 got_x_error = FALSE; | |
258 | |
259 commProperty = XInternAtom(dpy, "Comm", False); | |
260 /* Change this back to "InterpRegistry" to talk to tk processes */ | |
261 registryProperty = XInternAtom(dpy, "VimRegistry", False); | |
262 | |
263 if (commWindow == None) | |
264 { | |
265 commWindow = | |
266 XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), | |
267 getpid(), 0, 10, 10, 0, | |
268 WhitePixel(dpy, DefaultScreen(dpy)), | |
269 WhitePixel(dpy, DefaultScreen(dpy))); | |
270 XSelectInput(dpy, commWindow, PropertyChangeMask); | |
271 } | |
272 | |
273 XSync(dpy, False); | |
274 (void) XSetErrorHandler(old_handler); | |
275 | |
276 return got_x_error ? -1 : 0; | |
277 } | |
278 | |
279 /* | |
280 * LookupName -- | |
281 * Given an interpreter name, see if the name exists in | |
282 * the interpreter registry for a particular display. | |
283 * | |
284 * Results: | |
285 * If the given name is registered, return the ID of | |
286 * the window associated with the name. If the name | |
287 * isn't registered, then return 0. | |
288 */ | |
289 | |
290 static Window | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
291 LookupName( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
292 Display *dpy, /* Display whose registry to check. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
293 char *name, /* Name of an interpreter. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
294 int delete, /* If non-zero, delete info about name. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
295 char **loose) /* Do another search matching -999 if not found |
7 | 296 Return result here if a match is found */ |
297 { | |
298 unsigned char *regProp, *entry; | |
299 unsigned char *p; | |
300 int result, actualFormat; | |
301 unsigned long numItems, bytesAfter; | |
302 Atom actualType; | |
303 Window returnValue; | |
304 | |
305 /* | |
306 * Read the registry property. | |
307 */ | |
308 | |
309 regProp = NULL; | |
310 result = XGetWindowProperty(dpy, RootWindow(dpy, 0), registryProperty, 0, | |
311 MAX_PROP_WORDS, False, XA_STRING, &actualType, | |
312 &actualFormat, &numItems, &bytesAfter, | |
313 ®Prop); | |
314 | |
315 if (actualType == None) | |
316 return 0; | |
317 | |
318 /* | |
319 * If the property is improperly formed, then delete it. | |
320 */ | |
321 | |
322 if ((result != Success) || (actualFormat != 8) || (actualType != XA_STRING)) | |
323 { | |
324 if (regProp != NULL) | |
325 XFree(regProp); | |
326 XDeleteProperty(dpy, RootWindow(dpy, 0), registryProperty); | |
327 return 0; | |
328 } | |
329 | |
330 /* | |
331 * Scan the property for the desired name. | |
332 */ | |
333 | |
334 returnValue = None; | |
335 entry = NULL; /* Not needed, but eliminates compiler warning. */ | |
336 for (p = regProp; (p - regProp) < numItems; ) | |
337 { | |
338 entry = p; | |
34074
1629cc65d78d
patch 9.1.0006: is*() and to*() function may be unsafe
Christian Brabandt <cb@256bit.org>
parents:
25402
diff
changeset
|
339 while ((*p != 0) && (!isspace((unsigned char)*p))) |
7 | 340 p++; |
341 if ((*p != 0) && (strcasecmp(name, p + 1) == 0)) | |
342 { | |
343 sscanf(entry, "%x", (uint*) &returnValue); | |
344 break; | |
345 } | |
346 while (*p != 0) | |
347 p++; | |
348 p++; | |
349 } | |
350 | |
351 if (loose != NULL && returnValue == None && !IsSerialName(name)) | |
352 { | |
353 for (p = regProp; (p - regProp) < numItems; ) | |
354 { | |
355 entry = p; | |
34074
1629cc65d78d
patch 9.1.0006: is*() and to*() function may be unsafe
Christian Brabandt <cb@256bit.org>
parents:
25402
diff
changeset
|
356 while ((*p != 0) && (!isspace((unsigned char)*p))) |
7 | 357 p++; |
358 if ((*p != 0) && IsSerialName(p + 1) | |
359 && (strncmp(name, p + 1, strlen(name)) == 0)) | |
360 { | |
361 sscanf(entry, "%x", (uint*) &returnValue); | |
362 *loose = strdup(p + 1); | |
363 break; | |
364 } | |
365 while (*p != 0) | |
366 p++; | |
367 p++; | |
368 } | |
369 } | |
370 | |
371 /* | |
372 * Delete the property, if that is desired (copy down the | |
373 * remainder of the registry property to overlay the deleted | |
374 * info, then rewrite the property). | |
375 */ | |
376 | |
377 if ((delete) && (returnValue != None)) | |
378 { | |
379 int count; | |
380 | |
381 while (*p != 0) | |
382 p++; | |
383 p++; | |
384 count = numItems - (p-regProp); | |
385 if (count > 0) | |
386 memcpy(entry, p, count); | |
387 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, | |
388 8, PropModeReplace, regProp, | |
389 (int) (numItems - (p-entry))); | |
390 XSync(dpy, False); | |
391 } | |
392 | |
393 XFree(regProp); | |
394 return returnValue; | |
395 } | |
396 | |
397 static char * | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
398 SendEventProc( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
399 Display *dpy, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
400 XEvent *eventPtr, /* Information about event. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
401 int expected, /* The one were waiting for */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
402 int *code) /* Return code. 0 => OK */ |
7 | 403 { |
404 unsigned char *propInfo; | |
405 unsigned char *p; | |
406 int result, actualFormat; | |
407 int retCode; | |
408 unsigned long numItems, bytesAfter; | |
409 Atom actualType; | |
410 | |
411 if ((eventPtr->xproperty.atom != commProperty) | |
412 || (eventPtr->xproperty.state != PropertyNewValue)) | |
413 { | |
414 return; | |
415 } | |
416 | |
417 /* | |
418 * Read the comm property and delete it. | |
419 */ | |
420 | |
421 propInfo = NULL; | |
422 result = XGetWindowProperty(dpy, commWindow, commProperty, 0, | |
423 MAX_PROP_WORDS, True, XA_STRING, &actualType, | |
424 &actualFormat, &numItems, &bytesAfter, | |
425 &propInfo); | |
426 | |
427 /* | |
428 * If the property doesn't exist or is improperly formed | |
429 * then ignore it. | |
430 */ | |
431 | |
432 if ((result != Success) || (actualType != XA_STRING) | |
433 || (actualFormat != 8)) | |
434 { | |
435 if (propInfo != NULL) | |
436 { | |
437 XFree(propInfo); | |
438 } | |
439 return; | |
440 } | |
441 | |
442 /* | |
443 * Several commands and results could arrive in the property at | |
444 * one time; each iteration through the outer loop handles a | |
445 * single command or result. | |
446 */ | |
447 | |
448 for (p = propInfo; (p - propInfo) < numItems; ) | |
449 { | |
450 /* | |
451 * Ignore leading NULs; each command or result starts with a | |
452 * NUL so that no matter how badly formed a preceding command | |
453 * is, we'll be able to tell that a new command/result is | |
454 * starting. | |
455 */ | |
456 | |
457 if (*p == 0) | |
458 { | |
459 p++; | |
460 continue; | |
461 } | |
462 | |
463 if ((*p == 'r') && (p[1] == 0)) | |
464 { | |
465 int serial, gotSerial; | |
466 char *res; | |
467 | |
468 /* | |
469 * This is a reply to some command that we sent out. Iterate | |
470 * over all of its options. Stop when we reach the end of the | |
471 * property or something that doesn't look like an option. | |
472 */ | |
473 | |
474 p += 2; | |
475 gotSerial = 0; | |
476 res = ""; | |
477 retCode = 0; | |
478 while (((p-propInfo) < numItems) && (*p == '-')) | |
479 { | |
480 switch (p[1]) | |
481 { | |
482 case 'r': | |
483 if (p[2] == ' ') | |
484 res = p + 3; | |
485 break; | |
486 case 's': | |
487 if (sscanf(p + 2, " %d", &serial) == 1) | |
488 gotSerial = 1; | |
489 break; | |
490 case 'c': | |
491 if (sscanf(p + 2, " %d", &retCode) != 1) | |
492 retCode = 0; | |
493 break; | |
494 } | |
495 while (*p != 0) | |
496 p++; | |
497 p++; | |
498 } | |
499 | |
500 if (!gotSerial) | |
501 continue; | |
502 | |
503 if (code != NULL) | |
504 *code = retCode; | |
505 return serial == expected ? strdup(res) : NULL; | |
506 } | |
507 else | |
508 { | |
509 /* | |
510 * Didn't recognize this thing. Just skip through the next | |
511 * null character and try again. | |
25402 | 512 * Also, throw away commands that we can't process anyway. |
7 | 513 */ |
514 | |
515 while (*p != 0) | |
516 p++; | |
517 p++; | |
518 } | |
519 } | |
520 XFree(propInfo); | |
521 } | |
522 | |
523 /* | |
524 * AppendPropCarefully -- | |
525 * | |
526 * Append a given property to a given window, but set up | |
527 * an X error handler so that if the append fails this | |
528 * procedure can return an error code rather than having | |
529 * Xlib panic. | |
530 * | |
531 * Return: | |
532 * 0 on OK - -1 on error | |
533 *-------------------------------------------------------------- | |
534 */ | |
535 | |
536 static int | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
537 AppendPropCarefully( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
538 Display *dpy, /* Display on which to operate. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
539 Window window, /* Window whose property is to |
7 | 540 * be modified. */ |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
541 Atom property, /* Name of property. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
542 char *value, /* Characters to append to property. */ |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
543 int length) /* How much to append */ |
7 | 544 { |
545 XErrorHandler old_handler; | |
546 | |
547 old_handler = XSetErrorHandler(x_error_check); | |
548 got_x_error = FALSE; | |
549 XChangeProperty(dpy, window, property, XA_STRING, 8, | |
550 PropModeAppend, value, length); | |
551 XSync(dpy, False); | |
552 (void) XSetErrorHandler(old_handler); | |
553 return got_x_error ? -1 : 0; | |
554 } | |
555 | |
556 | |
557 /* | |
558 * Another X Error handler, just used to check for errors. | |
559 */ | |
560 /* ARGSUSED */ | |
561 static int | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
562 x_error_check(Display *dpy, XErrorEvent *error_event) |
7 | 563 { |
564 got_x_error = TRUE; | |
565 return 0; | |
566 } | |
567 | |
568 /* | |
569 * Check if "str" looks like it had a serial number appended. | |
570 * Actually just checks if the name ends in a digit. | |
571 */ | |
572 static int | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
7807
diff
changeset
|
573 IsSerialName(char *str) |
7 | 574 { |
575 int len = strlen(str); | |
576 | |
34074
1629cc65d78d
patch 9.1.0006: is*() and to*() function may be unsafe
Christian Brabandt <cb@256bit.org>
parents:
25402
diff
changeset
|
577 return (len > 1 && isdigit((unsigned char)str[len - 1])); |
7 | 578 } |