1 /* vi:set ts=8 sts=4 sw=4 noet: 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 /* 25 * This file provides procedures that implement the command server 26 * functionality of Vim when in contact with an X11 server. 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 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: 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 * 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 * 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 170 typedef int (*EndCond)(void *); 171 172 struct x_cmdqueue 173 { 174 char_u *propInfo; 175 long_u len; 176 struct x_cmdqueue *next; 177 struct x_cmdqueue *prev; 178 }; 179 180 typedef struct x_cmdqueue x_queue_T; 181 182 // dummy node, header for circular queue 183 static x_queue_T head = {NULL, 0, NULL, NULL}; 184 185 /* 186 * Forward declarations for procedures defined later in this file: 187 */ 188 189 static Window LookupName(Display *dpy, char_u *name, int delete, char_u **loose); 190 static int SendInit(Display *dpy); 191 static int DoRegisterName(Display *dpy, char_u *name); 192 static void DeleteAnyLingerer(Display *dpy, Window w); 193 static int GetRegProp(Display *dpy, char_u **regPropp, long_u *numItemsp, int domsg); 194 static int WaitForPend(void *p); 195 static int WindowValid(Display *dpy, Window w); 196 static void ServerWait(Display *dpy, Window w, EndCond endCond, void *endData, int localLoop, int seconds); 197 static int AppendPropCarefully(Display *display, Window window, Atom property, char_u *value, int length); 198 static int x_error_check(Display *dpy, XErrorEvent *error_event); 199 static int IsSerialName(char_u *name); 200 static void save_in_queue(char_u *buf, long_u len); 201 static void server_parse_message(Display *dpy, char_u *propInfo, long_u numItems); 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 215 serverRegisterName( 216 Display *dpy, // display to register with 217 char_u *name) // the name that will be used as a base 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 { 231 msg_attr(_("Unable to register a command server name"), 232 HL_ATTR(HLF_W)); 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 253 DoRegisterName(Display *dpy, char_u *name) 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 331 serverChangeRegisteredWindow( 332 Display *dpy, // Display to register with 333 Window newwin) // Re-register to this ID 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 367 serverSendToVim( 368 Display *dpy, // Where to send. 369 char_u *name, // Where to send. 370 char_u *cmd, // What to send. 371 char_u **result, // Result of eval'ed expression 372 Window *server, // Actual ID of receiving app 373 Bool asExpr, // Interpret as keystrokes or expr ? 374 int timeout, // seconds to wait or zero 375 Bool localLoop, // Throw away everything but result 376 int silent) // don't complain about no server 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)) 401 return sendToLocalVim(cmd, asExpr, result); 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); 421 vim_free(loosename); 422 continue; 423 } 424 } 425 break; 426 } 427 if (w == None) 428 { 429 if (!silent) 430 semsg(_(e_noserver), name); 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. 441 * Length must be computed exactly! 442 */ 443 length = STRLEN(name) + STRLEN(p_enc) + STRLEN(cmd) + 14; 444 property = alloc(length + 30); 445 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); 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); 454 // Add length of what "-r %x %d" resulted in, skipping the NUL. 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 { 461 emsg(_("E248: Failed to send command to the destination program")); 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 479 ServerWait(dpy, w, WaitForPend, &pending, localLoop, 480 timeout > 0 ? timeout : 600); 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 508 WaitForPend(void *p) 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 518 WindowValid(Display *dpy, Window w) 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 547 ServerWait( 548 Display *dpy, 549 Window w, 550 EndCond endCond, 551 void *endData, 552 int localLoop, 553 int seconds) 554 { 555 time_t start; 556 time_t now; 557 XEvent event; 558 559 #define UI_MSEC_DELAY 53 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 575 576 time(&start); 577 while (TRUE) 578 { 579 while (XCheckWindowEvent(dpy, commWindow, PropertyChangeMask, &event)) 580 serverEventProc(dpy, &event, 1); 581 server_parse_messages(); 582 583 if (endCond(endData) != 0) 584 break; 585 if (!WindowValid(dpy, w)) 586 break; 587 time(&now); 588 if (seconds >= 0 && (now - start) >= seconds) 589 break; 590 591 #ifdef FEAT_TIMERS 592 check_due_timer(); 593 #endif 594 595 // Just look out for the answer without calling back into Vim 596 if (localLoop) 597 { 598 #ifndef HAVE_SELECT 599 if (poll(&fds, 1, SEND_MSEC_POLL) < 0) 600 break; 601 #else 602 if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) < 0) 603 break; 604 #endif 605 } 606 else 607 { 608 if (got_int) 609 break; 610 ui_delay((long)UI_MSEC_DELAY, TRUE); 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 * 624 serverGetVimNames(Display *dpy) 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); 649 for (p = regProp; (long_u)(p - regProp) < numItems; p++) 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); 669 ga_append(&ga, NUL); 670 return ga.ga_data; 671 } 672 673 ///////////////////////////////////////////////////////////// 674 // Reply stuff 675 676 static struct ServerReply * 677 ServerReplyFind(Window w, enum ServerReplyOp op) 678 { 679 struct ServerReply *p; 680 struct ServerReply e; 681 int i; 682 683 p = (struct ServerReply *) serverReply.ga_data; 684 for (i = 0; i < serverReply.ga_len; i++, p++) 685 if (p->id == w) 686 break; 687 if (i >= serverReply.ga_len) 688 p = NULL; 689 690 if (p == NULL && op == SROP_Add) 691 { 692 if (serverReply.ga_growsize == 0) 693 ga_init2(&serverReply, sizeof(struct ServerReply), 1); 694 if (ga_grow(&serverReply, 1) == OK) 695 { 696 p = ((struct ServerReply *) serverReply.ga_data) 697 + serverReply.ga_len; 698 e.id = w; 699 ga_init2(&e.strings, 1, 100); 700 mch_memmove(p, &e, sizeof(e)); 701 serverReply.ga_len++; 702 } 703 } 704 else if (p != NULL && op == SROP_Delete) 705 { 706 ga_clear(&p->strings); 707 mch_memmove(p, p + 1, (serverReply.ga_len - i - 1) * sizeof(*p)); 708 serverReply.ga_len--; 709 } 710 711 return p; 712 } 713 714 /* 715 * Convert string to windowid. 716 * Issue an error if the id is invalid. 717 */ 718 Window 719 serverStrToWin(char_u *str) 720 { 721 unsigned id = None; 722 723 sscanf((char *)str, "0x%x", &id); 724 if (id == None) 725 semsg(_("E573: Invalid server id used: %s"), str); 726 727 return (Window)id; 728 } 729 730 /* 731 * Send a reply string (notification) to client with id "name". 732 * Return -1 if the window is invalid. 733 */ 734 int 735 serverSendReply(char_u *name, char_u *str) 736 { 737 char_u *property; 738 int length; 739 int res; 740 Display *dpy = X_DISPLAY; 741 Window win = serverStrToWin(name); 742 743 if (commProperty == None) 744 { 745 if (SendInit(dpy) < 0) 746 return -2; 747 } 748 if (!WindowValid(dpy, win)) 749 return -1; 750 751 length = STRLEN(p_enc) + STRLEN(str) + 14; 752 if ((property = alloc(length + 30)) != NULL) 753 { 754 sprintf((char *)property, "%cn%c-E %s%c-n %s%c-w %x", 755 0, 0, p_enc, 0, str, 0, (unsigned int)commWindow); 756 // Add length of what "%x" resulted in. 757 length += STRLEN(property + length); 758 res = AppendPropCarefully(dpy, win, commProperty, property, length + 1); 759 vim_free(property); 760 return res; 761 } 762 return -1; 763 } 764 765 static int 766 WaitForReply(void *p) 767 { 768 Window *w = (Window *) p; 769 770 return ServerReplyFind(*w, SROP_Find) != NULL; 771 } 772 773 /* 774 * Wait for replies from id (win) 775 * When "timeout" is non-zero wait up to this many seconds. 776 * Return 0 and the malloc'ed string when a reply is available. 777 * Return -1 if the window becomes invalid while waiting. 778 */ 779 int 780 serverReadReply( 781 Display *dpy, 782 Window win, 783 char_u **str, 784 int localLoop, 785 int timeout) 786 { 787 int len; 788 char_u *s; 789 struct ServerReply *p; 790 791 ServerWait(dpy, win, WaitForReply, &win, localLoop, 792 timeout > 0 ? timeout : -1); 793 794 if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0) 795 { 796 *str = vim_strsave(p->strings.ga_data); 797 len = STRLEN(*str) + 1; 798 if (len < p->strings.ga_len) 799 { 800 s = (char_u *) p->strings.ga_data; 801 mch_memmove(s, s + len, p->strings.ga_len - len); 802 p->strings.ga_len -= len; 803 } 804 else 805 { 806 // Last string read. Remove from list 807 ga_clear(&p->strings); 808 ServerReplyFind(win, SROP_Delete); 809 } 810 return 0; 811 } 812 return -1; 813 } 814 815 /* 816 * Check for replies from id (win). 817 * Return TRUE and a non-malloc'ed string if there is. Else return FALSE. 818 */ 819 int 820 serverPeekReply(Display *dpy, Window win, char_u **str) 821 { 822 struct ServerReply *p; 823 824 if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0) 825 { 826 if (str != NULL) 827 *str = p->strings.ga_data; 828 return 1; 829 } 830 if (!WindowValid(dpy, win)) 831 return -1; 832 return 0; 833 } 834 835 836 /* 837 * Initialize the communication channels for sending commands and receiving 838 * results. 839 */ 840 static int 841 SendInit(Display *dpy) 842 { 843 XErrorHandler old_handler; 844 845 /* 846 * Create the window used for communication, and set up an 847 * event handler for it. 848 */ 849 old_handler = XSetErrorHandler(x_error_check); 850 got_x_error = FALSE; 851 852 if (commProperty == None) 853 commProperty = XInternAtom(dpy, "Comm", False); 854 if (vimProperty == None) 855 vimProperty = XInternAtom(dpy, "Vim", False); 856 if (registryProperty == None) 857 registryProperty = XInternAtom(dpy, "VimRegistry", False); 858 859 if (commWindow == None) 860 { 861 commWindow = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), 862 getpid(), 0, 10, 10, 0, 863 WhitePixel(dpy, DefaultScreen(dpy)), 864 WhitePixel(dpy, DefaultScreen(dpy))); 865 XSelectInput(dpy, commWindow, PropertyChangeMask); 866 // WARNING: Do not step through this while debugging, it will hangup 867 // the X server! 868 XGrabServer(dpy); 869 DeleteAnyLingerer(dpy, commWindow); 870 XUngrabServer(dpy); 871 } 872 873 // Make window recognizable as a vim window 874 XChangeProperty(dpy, commWindow, vimProperty, XA_STRING, 875 8, PropModeReplace, (char_u *)VIM_VERSION_SHORT, 876 (int)STRLEN(VIM_VERSION_SHORT) + 1); 877 878 XSync(dpy, False); 879 (void)XSetErrorHandler(old_handler); 880 881 return got_x_error ? -1 : 0; 882 } 883 884 /* 885 * Given a server name, see if the name exists in the registry for a 886 * particular display. 887 * 888 * If the given name is registered, return the ID of the window associated 889 * with the name. If the name isn't registered, then return 0. 890 * 891 * Side effects: 892 * If the registry property is improperly formed, then it is deleted. 893 * If "delete" is non-zero, then if the named server is found it is 894 * removed from the registry property. 895 */ 896 static Window 897 LookupName( 898 Display *dpy, // Display whose registry to check. 899 char_u *name, // Name of a server. 900 int delete, // If non-zero, delete info about name. 901 char_u **loose) // Do another search matching -999 if not found 902 // Return result here if a match is found 903 { 904 char_u *regProp, *entry; 905 char_u *p; 906 long_u numItems; 907 int_u returnValue; 908 909 /* 910 * Read the registry property. 911 */ 912 if (GetRegProp(dpy, ®Prop, &numItems, FALSE) == FAIL) 913 return 0; 914 915 /* 916 * Scan the property for the desired name. 917 */ 918 returnValue = (int_u)None; 919 entry = NULL; // Not needed, but eliminates compiler warning. 920 for (p = regProp; (long_u)(p - regProp) < numItems; ) 921 { 922 entry = p; 923 while (*p != 0 && !isspace(*p)) 924 p++; 925 if (*p != 0 && STRICMP(name, p + 1) == 0) 926 { 927 sscanf((char *)entry, "%x", &returnValue); 928 break; 929 } 930 while (*p != 0) 931 p++; 932 p++; 933 } 934 935 if (loose != NULL && returnValue == (int_u)None && !IsSerialName(name)) 936 { 937 for (p = regProp; (long_u)(p - regProp) < numItems; ) 938 { 939 entry = p; 940 while (*p != 0 && !isspace(*p)) 941 p++; 942 if (*p != 0 && IsSerialName(p + 1) 943 && STRNICMP(name, p + 1, STRLEN(name)) == 0) 944 { 945 sscanf((char *)entry, "%x", &returnValue); 946 *loose = vim_strsave(p + 1); 947 break; 948 } 949 while (*p != 0) 950 p++; 951 p++; 952 } 953 } 954 955 /* 956 * Delete the property, if that is desired (copy down the 957 * remainder of the registry property to overlay the deleted 958 * info, then rewrite the property). 959 */ 960 if (delete && returnValue != (int_u)None) 961 { 962 int count; 963 964 while (*p != 0) 965 p++; 966 p++; 967 count = numItems - (p - regProp); 968 if (count > 0) 969 mch_memmove(entry, p, count); 970 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, 971 8, PropModeReplace, regProp, 972 (int)(numItems - (p - entry))); 973 XSync(dpy, False); 974 } 975 976 if (regProp != empty_prop) 977 XFree(regProp); 978 return (Window)returnValue; 979 } 980 981 /* 982 * Delete any lingering occurrence of window id. We promise that any 983 * occurrence is not ours since it is not yet put into the registry (by us) 984 * 985 * This is necessary in the following scenario: 986 * 1. There is an old windowid for an exit'ed vim in the registry 987 * 2. We get that id for our commWindow but only want to send, not register. 988 * 3. The window will mistakenly be regarded valid because of own commWindow 989 */ 990 static void 991 DeleteAnyLingerer( 992 Display *dpy, // Display whose registry to check. 993 Window win) // Window to remove 994 { 995 char_u *regProp, *entry = NULL; 996 char_u *p; 997 long_u numItems; 998 int_u wwin; 999 1000 /* 1001 * Read the registry property. 1002 */ 1003 if (GetRegProp(dpy, ®Prop, &numItems, FALSE) == FAIL) 1004 return; 1005 1006 // Scan the property for the window id. 1007 for (p = regProp; (long_u)(p - regProp) < numItems; ) 1008 { 1009 if (*p != 0) 1010 { 1011 sscanf((char *)p, "%x", &wwin); 1012 if ((Window)wwin == win) 1013 { 1014 int lastHalf; 1015 1016 // Copy down the remainder to delete entry 1017 entry = p; 1018 while (*p != 0) 1019 p++; 1020 p++; 1021 lastHalf = numItems - (p - regProp); 1022 if (lastHalf > 0) 1023 mch_memmove(entry, p, lastHalf); 1024 numItems = (entry - regProp) + lastHalf; 1025 p = entry; 1026 continue; 1027 } 1028 } 1029 while (*p != 0) 1030 p++; 1031 p++; 1032 } 1033 1034 if (entry != NULL) 1035 { 1036 XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, 1037 XA_STRING, 8, PropModeReplace, regProp, 1038 (int)(p - regProp)); 1039 XSync(dpy, False); 1040 } 1041 1042 if (regProp != empty_prop) 1043 XFree(regProp); 1044 } 1045 1046 /* 1047 * Read the registry property. Delete it when it's formatted wrong. 1048 * Return the property in "regPropp". "empty_prop" is used when it doesn't 1049 * exist yet. 1050 * Return OK when successful. 1051 */ 1052 static int 1053 GetRegProp( 1054 Display *dpy, 1055 char_u **regPropp, 1056 long_u *numItemsp, 1057 int domsg) // When TRUE give error message. 1058 { 1059 int result, actualFormat; 1060 long_u bytesAfter; 1061 Atom actualType; 1062 XErrorHandler old_handler; 1063 1064 *regPropp = NULL; 1065 old_handler = XSetErrorHandler(x_error_check); 1066 got_x_error = FALSE; 1067 1068 result = XGetWindowProperty(dpy, RootWindow(dpy, 0), registryProperty, 0L, 1069 (long)MAX_PROP_WORDS, False, 1070 XA_STRING, &actualType, 1071 &actualFormat, numItemsp, &bytesAfter, 1072 regPropp); 1073 1074 XSync(dpy, FALSE); 1075 (void)XSetErrorHandler(old_handler); 1076 if (got_x_error) 1077 return FAIL; 1078 1079 if (actualType == None) 1080 { 1081 // No prop yet. Logically equal to the empty list 1082 *numItemsp = 0; 1083 *regPropp = empty_prop; 1084 return OK; 1085 } 1086 1087 // If the property is improperly formed, then delete it. 1088 if (result != Success || actualFormat != 8 || actualType != XA_STRING) 1089 { 1090 if (*regPropp != NULL) 1091 XFree(*regPropp); 1092 XDeleteProperty(dpy, RootWindow(dpy, 0), registryProperty); 1093 if (domsg) 1094 emsg(_("E251: VIM instance registry property is badly formed. Deleted!")); 1095 return FAIL; 1096 } 1097 return OK; 1098 } 1099 1100 1101 /* 1102 * This procedure is invoked by the various X event loops throughout Vims when 1103 * a property changes on the communication window. This procedure reads the 1104 * property and enqueues command requests and responses. If immediate is true, 1105 * it runs the event immediately instead of enqueuing it. Immediate can cause 1106 * unintended behavior and should only be used for code that blocks for a 1107 * response. 1108 */ 1109 void 1110 serverEventProc( 1111 Display *dpy, 1112 XEvent *eventPtr, // Information about event. 1113 int immediate) // Run event immediately. Should mostly be 0. 1114 { 1115 char_u *propInfo; 1116 int result, actualFormat; 1117 long_u numItems, bytesAfter; 1118 Atom actualType; 1119 1120 if (eventPtr != NULL) 1121 { 1122 if (eventPtr->xproperty.atom != commProperty 1123 || eventPtr->xproperty.state != PropertyNewValue) 1124 return; 1125 } 1126 1127 /* 1128 * Read the comm property and delete it. 1129 */ 1130 propInfo = NULL; 1131 result = XGetWindowProperty(dpy, commWindow, commProperty, 0L, 1132 (long)MAX_PROP_WORDS, True, 1133 XA_STRING, &actualType, 1134 &actualFormat, &numItems, &bytesAfter, 1135 &propInfo); 1136 1137 // If the property doesn't exist or is improperly formed then ignore it. 1138 if (result != Success || actualType != XA_STRING || actualFormat != 8) 1139 { 1140 if (propInfo != NULL) 1141 XFree(propInfo); 1142 return; 1143 } 1144 if (immediate) 1145 server_parse_message(dpy, propInfo, numItems); 1146 else 1147 save_in_queue(propInfo, numItems); 1148 } 1149 1150 /* 1151 * Saves x clientserver commands in a queue so that they can be called when 1152 * vim is idle. 1153 */ 1154 static void 1155 save_in_queue(char_u *propInfo, long_u len) 1156 { 1157 x_queue_T *node; 1158 1159 node = ALLOC_ONE(x_queue_T); 1160 if (node == NULL) 1161 return; // out of memory 1162 node->propInfo = propInfo; 1163 node->len = len; 1164 1165 if (head.next == NULL) // initialize circular queue 1166 { 1167 head.next = &head; 1168 head.prev = &head; 1169 } 1170 1171 // insert node at tail of queue 1172 node->next = &head; 1173 node->prev = head.prev; 1174 head.prev->next = node; 1175 head.prev = node; 1176 } 1177 1178 /* 1179 * Parses queued clientserver messages. 1180 */ 1181 void 1182 server_parse_messages(void) 1183 { 1184 x_queue_T *node; 1185 1186 if (!X_DISPLAY) 1187 return; // cannot happen? 1188 while (head.next != NULL && head.next != &head) 1189 { 1190 node = head.next; 1191 head.next = node->next; 1192 node->next->prev = node->prev; 1193 server_parse_message(X_DISPLAY, node->propInfo, node->len); 1194 vim_free(node); 1195 } 1196 } 1197 1198 /* 1199 * Returns a non-zero value if there are clientserver messages waiting 1200 * int the queue. 1201 */ 1202 int 1203 server_waiting(void) 1204 { 1205 return head.next != NULL && head.next != &head; 1206 } 1207 1208 /* 1209 * Prases a single clientserver message. A single message may contain multiple 1210 * commands. 1211 * "propInfo" will be freed. 1212 */ 1213 static void 1214 server_parse_message( 1215 Display *dpy, 1216 char_u *propInfo, // A string containing 0 or more X commands 1217 long_u numItems) // The size of propInfo in bytes. 1218 { 1219 char_u *p; 1220 int code; 1221 char_u *tofree; 1222 1223 /* 1224 * Several commands and results could arrive in the property at 1225 * one time; each iteration through the outer loop handles a 1226 * single command or result. 1227 */ 1228 for (p = propInfo; (long_u)(p - propInfo) < numItems; ) 1229 { 1230 /* 1231 * Ignore leading NULs; each command or result starts with a 1232 * NUL so that no matter how badly formed a preceding command 1233 * is, we'll be able to tell that a new command/result is 1234 * starting. 1235 */ 1236 if (*p == 0) 1237 { 1238 p++; 1239 continue; 1240 } 1241 1242 if ((*p == 'c' || *p == 'k') && (p[1] == 0)) 1243 { 1244 Window resWindow; 1245 char_u *name, *script, *serial, *end; 1246 Bool asKeys = *p == 'k'; 1247 char_u *enc; 1248 1249 /* 1250 * This is an incoming command from some other application. 1251 * Iterate over all of its options. Stop when we reach 1252 * the end of the property or something that doesn't look 1253 * like an option. 1254 */ 1255 p += 2; 1256 name = NULL; 1257 resWindow = None; 1258 serial = (char_u *)""; 1259 script = NULL; 1260 enc = NULL; 1261 while ((long_u)(p - propInfo) < numItems && *p == '-') 1262 { 1263 switch (p[1]) 1264 { 1265 case 'r': 1266 end = skipwhite(p + 2); 1267 resWindow = 0; 1268 while (vim_isxdigit(*end)) 1269 { 1270 resWindow = 16 * resWindow + (long_u)hex2nr(*end); 1271 ++end; 1272 } 1273 if (end == p + 2 || *end != ' ') 1274 resWindow = None; 1275 else 1276 { 1277 p = serial = end + 1; 1278 clientWindow = resWindow; // Remember in global 1279 } 1280 break; 1281 case 'n': 1282 if (p[2] == ' ') 1283 name = p + 3; 1284 break; 1285 case 's': 1286 if (p[2] == ' ') 1287 script = p + 3; 1288 break; 1289 case 'E': 1290 if (p[2] == ' ') 1291 enc = p + 3; 1292 break; 1293 } 1294 while (*p != 0) 1295 p++; 1296 p++; 1297 } 1298 1299 if (script == NULL || name == NULL) 1300 continue; 1301 1302 if (serverName != NULL && STRICMP(name, serverName) == 0) 1303 { 1304 script = serverConvert(enc, script, &tofree); 1305 if (asKeys) 1306 server_to_input_buf(script); 1307 else 1308 { 1309 char_u *res; 1310 1311 res = eval_client_expr_to_string(script); 1312 if (resWindow != None) 1313 { 1314 garray_T reply; 1315 1316 // Initialize the result property. 1317 ga_init2(&reply, 1, 100); 1318 (void)ga_grow(&reply, 50 + STRLEN(p_enc)); 1319 sprintf(reply.ga_data, "%cr%c-E %s%c-s %s%c-r ", 1320 0, 0, p_enc, 0, serial, 0); 1321 reply.ga_len = 14 + STRLEN(p_enc) + STRLEN(serial); 1322 1323 // Evaluate the expression and return the result. 1324 if (res != NULL) 1325 ga_concat(&reply, res); 1326 else 1327 { 1328 ga_concat(&reply, (char_u *)_(e_invexprmsg)); 1329 ga_append(&reply, 0); 1330 ga_concat(&reply, (char_u *)"-c 1"); 1331 } 1332 ga_append(&reply, NUL); 1333 (void)AppendPropCarefully(dpy, resWindow, commProperty, 1334 reply.ga_data, reply.ga_len); 1335 ga_clear(&reply); 1336 } 1337 vim_free(res); 1338 } 1339 vim_free(tofree); 1340 } 1341 } 1342 else if (*p == 'r' && p[1] == 0) 1343 { 1344 int serial, gotSerial; 1345 char_u *res; 1346 PendingCommand *pcPtr; 1347 char_u *enc; 1348 1349 /* 1350 * This is a reply to some command that we sent out. Iterate 1351 * over all of its options. Stop when we reach the end of the 1352 * property or something that doesn't look like an option. 1353 */ 1354 p += 2; 1355 gotSerial = 0; 1356 res = (char_u *)""; 1357 code = 0; 1358 enc = NULL; 1359 while ((long_u)(p - propInfo) < numItems && *p == '-') 1360 { 1361 switch (p[1]) 1362 { 1363 case 'r': 1364 if (p[2] == ' ') 1365 res = p + 3; 1366 break; 1367 case 'E': 1368 if (p[2] == ' ') 1369 enc = p + 3; 1370 break; 1371 case 's': 1372 if (sscanf((char *)p + 2, " %d", &serial) == 1) 1373 gotSerial = 1; 1374 break; 1375 case 'c': 1376 if (sscanf((char *)p + 2, " %d", &code) != 1) 1377 code = 0; 1378 break; 1379 } 1380 while (*p != 0) 1381 p++; 1382 p++; 1383 } 1384 1385 if (!gotSerial) 1386 continue; 1387 1388 /* 1389 * Give the result information to anyone who's 1390 * waiting for it. 1391 */ 1392 for (pcPtr = pendingCommands; pcPtr != NULL; pcPtr = pcPtr->nextPtr) 1393 { 1394 if (serial != pcPtr->serial || pcPtr->result != NULL) 1395 continue; 1396 1397 pcPtr->code = code; 1398 res = serverConvert(enc, res, &tofree); 1399 if (tofree == NULL) 1400 res = vim_strsave(res); 1401 pcPtr->result = res; 1402 break; 1403 } 1404 } 1405 else if (*p == 'n' && p[1] == 0) 1406 { 1407 Window win = 0; 1408 unsigned int u; 1409 int gotWindow; 1410 char_u *str; 1411 struct ServerReply *r; 1412 char_u *enc; 1413 1414 /* 1415 * This is a (n)otification. Sent with serverreply_send in Vim 1416 * script. Execute any autocommand and save it for later retrieval 1417 */ 1418 p += 2; 1419 gotWindow = 0; 1420 str = (char_u *)""; 1421 enc = NULL; 1422 while ((long_u)(p - propInfo) < numItems && *p == '-') 1423 { 1424 switch (p[1]) 1425 { 1426 case 'n': 1427 if (p[2] == ' ') 1428 str = p + 3; 1429 break; 1430 case 'E': 1431 if (p[2] == ' ') 1432 enc = p + 3; 1433 break; 1434 case 'w': 1435 if (sscanf((char *)p + 2, " %x", &u) == 1) 1436 { 1437 win = u; 1438 gotWindow = 1; 1439 } 1440 break; 1441 } 1442 while (*p != 0) 1443 p++; 1444 p++; 1445 } 1446 1447 if (!gotWindow) 1448 continue; 1449 str = serverConvert(enc, str, &tofree); 1450 if ((r = ServerReplyFind(win, SROP_Add)) != NULL) 1451 { 1452 ga_concat(&(r->strings), str); 1453 ga_append(&(r->strings), NUL); 1454 } 1455 { 1456 char_u winstr[30]; 1457 1458 sprintf((char *)winstr, "0x%x", (unsigned int)win); 1459 apply_autocmds(EVENT_REMOTEREPLY, winstr, str, TRUE, curbuf); 1460 } 1461 vim_free(tofree); 1462 } 1463 else 1464 { 1465 /* 1466 * Didn't recognize this thing. Just skip through the next 1467 * null character and try again. 1468 * Even if we get an 'r'(eply) we will throw it away as we 1469 * never specify (and thus expect) one 1470 */ 1471 while (*p != 0) 1472 p++; 1473 p++; 1474 } 1475 } 1476 XFree(propInfo); 1477 } 1478 1479 /* 1480 * Append a given property to a given window, but set up an X error handler so 1481 * that if the append fails this procedure can return an error code rather 1482 * than having Xlib panic. 1483 * Return: 0 for OK, -1 for error 1484 */ 1485 static int 1486 AppendPropCarefully( 1487 Display *dpy, // Display on which to operate. 1488 Window window, // Window whose property is to be modified. 1489 Atom property, // Name of property. 1490 char_u *value, // Characters to append to property. 1491 int length) // How much to append 1492 { 1493 XErrorHandler old_handler; 1494 1495 old_handler = XSetErrorHandler(x_error_check); 1496 got_x_error = FALSE; 1497 XChangeProperty(dpy, window, property, XA_STRING, 8, 1498 PropModeAppend, value, length); 1499 XSync(dpy, False); 1500 (void) XSetErrorHandler(old_handler); 1501 return got_x_error ? -1 : 0; 1502 } 1503 1504 1505 /* 1506 * Another X Error handler, just used to check for errors. 1507 */ 1508 static int 1509 x_error_check(Display *dpy UNUSED, XErrorEvent *error_event UNUSED) 1510 { 1511 got_x_error = TRUE; 1512 return 0; 1513 } 1514 1515 /* 1516 * Check if "str" looks like it had a serial number appended. 1517 * Actually just checks if the name ends in a digit. 1518 */ 1519 static int 1520 IsSerialName(char_u *str) 1521 { 1522 int len = STRLEN(str); 1523 1524 return (len > 1 && vim_isdigit(str[len - 1])); 1525 } 1526 #endif // FEAT_CLIENTSERVER 1527