1 /* 2 3 Copyright 1990, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 30 /* 31 * This file contains the code to communicate with the client that is 32 * being edited. 33 */ 34 35 #ifdef HAVE_CONFIG_H 36 # include "config.h" 37 #endif 38 39 #include <X11/Intrinsic.h> 40 #include <X11/StringDefs.h> /* Get standard string definitions. */ 41 #include <X11/Xatom.h> 42 #include <X11/cursorfont.h> /* For crosshair cursor. */ 43 #include <X11/Xproto.h> 44 #include <X11/Xos.h> /* for XtNewString */ 45 46 #include <stdio.h> 47 #include <X11/Xmu/Error.h> 48 #include <X11/Xmu/WinUtil.h> 49 50 #include "editresP.h" 51 52 /* 53 * static Globals. 54 */ 55 56 static Atom atom_comm, atom_command, atom_resource_editor, atom_client_value; 57 static Atom atom_editres_protocol; 58 59 static void ClientTimedOut ( XtPointer data, XtIntervalId * id ); 60 static void TellUserAboutMessage ( Widget label, ResCommand command ); 61 static Boolean ConvertCommand ( Widget w, Atom * selection, Atom * target, 62 Atom * type_ret, XtPointer *value_ret, 63 unsigned long * length_ret, int * format_ret ); 64 static void SelectionDone ( Widget w, Atom *sel, Atom *targ ); 65 static void LoseSelection ( Widget w, Atom * sel ); 66 static void GetClientValue ( Widget w, XtPointer data, Atom *selection, 67 Atom *type, XtPointer value, 68 unsigned long *length, int * format ); 69 static void BuildHeader ( CurrentClient * client_data ); 70 static Event * BuildEvent ( ProtocolStream * stream ); 71 static void FreeEvent ( Event * event ); 72 static char * DispatchEvent ( Event * event ); 73 74 75 77 /* Function Name: ClientTimedOut 78 * Description: Called if the client takes too long to take our selection. 79 * Arguments: data - The widget that owns the client 80 * communication selection. 81 * id - *** UNUSED *** 82 * Returns: none. 83 */ 84 85 /* ARGSUSED */ 86 static void 87 ClientTimedOut(XtPointer data, XtIntervalId *id) 88 { 89 char msg[BUFSIZ]; 90 Widget w = (Widget) data; 91 92 global_client.ident = NO_IDENT; 93 XtDisownSelection(w, global_client.atom, 94 XtLastTimestampProcessed(XtDisplay(w))); 95 96 snprintf(msg, sizeof(msg), res_labels[4], "the Editres Protocol."); 97 SetMessage(global_screen_data.info_label, msg); 98 } 99 100 101 103 /* Function Name: GetClientWindow 104 * Description: Gets the Client's window by asking the user. 105 * Arguments: w - a widget. 106 * Returns: a clients window, or None. 107 */ 108 109 Window 110 GetClientWindow(Widget w, int *x, int *y) 111 { 112 int status; 113 Cursor cursor; 114 XEvent event; 115 int buttons = 0; 116 Display * dpy = XtDisplayOfObject(w); 117 Window target_win = None, root = RootWindowOfScreen(XtScreenOfObject(w)); 118 XtAppContext app = XtWidgetToApplicationContext(w); 119 120 /* Make the target cursor */ 121 cursor = XCreateFontCursor(dpy, XC_crosshair); 122 123 /* Grab the pointer using target cursor, letting it room all over */ 124 status = XGrabPointer(dpy, root, False, 125 ButtonPressMask|ButtonReleaseMask, GrabModeSync, 126 GrabModeAsync, root, cursor, CurrentTime); 127 if (status != GrabSuccess) { 128 SetMessage(global_screen_data.info_label, res_labels[5]); 129 return(None); 130 } 131 132 /* Let the user select a window... */ 133 while ((target_win == None) || (buttons != 0)) { 134 /* allow one more event */ 135 XAllowEvents(dpy, SyncPointer, CurrentTime); 136 XtAppNextEvent(app, &event); 137 switch (event.type) { 138 case ButtonPress: 139 if (event.xbutton.window != root) { 140 XtDispatchEvent(&event); 141 break; 142 } 143 144 if (target_win == None) { 145 target_win = event.xbutton.subwindow; /* window selected */ 146 if (x != NULL) 147 *x = event.xbutton.x_root; 148 if (y != NULL) 149 *y = event.xbutton.y_root; 150 } 151 buttons++; 152 break; 153 case ButtonRelease: 154 if (event.xbutton.window != root) { 155 XtDispatchEvent(&event); 156 break; 157 } 158 159 if (buttons > 0) /* There may have been some 160 down before we started */ 161 buttons--; 162 break; 163 default: 164 XtDispatchEvent(&event); 165 break; 166 } 167 } 168 169 XUngrabPointer(dpy, CurrentTime); /* Done with pointer */ 170 171 return(XmuClientWindow(dpy, target_win)); 172 } 173 174 175 177 /* Function Name: SetCommand 178 * Description: Causes this widget to own the resource editor's 179 * command selection. 180 * Arguments: w - the widget that will own the selection. 181 * command - command to send to client. 182 * msg - message to prompt the user to select a client. 183 * Returns: none. 184 */ 185 186 /* ARGSUSED */ 187 void 188 SetCommand(Widget w, ResCommand command, String msg) 189 { 190 XClientMessageEvent client_event; 191 Display * dpy = XtDisplay(w); 192 193 if (msg == NULL) 194 msg = res_labels[6]; 195 196 SetMessage(global_screen_data.info_label, msg); 197 198 if (global_client.window == None) 199 if ( (global_client.window = GetClientWindow(w, NULL, NULL)) == None) 200 return; 201 202 global_client.ident = GetNewIdent(); 203 204 global_client.command = command; 205 global_client.atom = atom_comm; 206 207 BuildHeader(&(global_client)); 208 209 if (!XtOwnSelection(w, global_client.atom, CurrentTime, ConvertCommand, 210 LoseSelection, SelectionDone)) 211 SetMessage(global_screen_data.info_label, 212 res_labels[7]); 213 214 client_event.window = global_client.window; 215 client_event.type = ClientMessage; 216 client_event.message_type = atom_resource_editor; 217 client_event.format = EDITRES_SEND_EVENT_FORMAT; 218 client_event.data.l[0] = XtLastTimestampProcessed(dpy); 219 client_event.data.l[1] = global_client.atom; 220 client_event.data.l[2] = (long) global_client.ident; 221 client_event.data.l[3] = global_effective_protocol_version; 222 223 global_error_code = NO_ERROR; /* Reset Error code. */ 224 global_old_error_handler = XSetErrorHandler(HandleXErrors); 225 global_serial_num = NextRequest(dpy); 226 227 XSendEvent(dpy, global_client.window, FALSE, (long) 0, 228 (XEvent *) &client_event); 229 230 XSync(dpy, FALSE); 231 XSetErrorHandler(global_old_error_handler); 232 if (global_error_code == NO_WINDOW) { 233 char error_buf[BUFSIZ] = 234 "The communication window with the" 235 " application is no longer available\n" 236 "Please select a new widget tree."; 237 238 global_error_code = NO_ERROR; /* Reset Error code. */ 239 global_client.window = None; 240 SetCommand(w, LocalSendWidgetTree, error_buf); 241 return; 242 } 243 244 TellUserAboutMessage(global_screen_data.info_label, command); 245 global_client.timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w), 246 CLIENT_TIME_OUT, 247 ClientTimedOut, (XtPointer) w); 248 } 249 250 251 253 /* Function Name: TellUserAboutMessage 254 * Description: Informs the user that we have sent a message to the client 255 * Arguments: label - the info label. 256 * command - command that we have executed. 257 * Returns: none. 258 */ 259 260 static void 261 TellUserAboutMessage(Widget label, ResCommand command) 262 { 263 char msg[BUFSIZ]; 264 const char *str; 265 266 switch(command) { 267 case LocalSendWidgetTree: 268 str = " asking for widget tree"; 269 break; 270 case LocalSetValues: 271 str = " asking it to perform SetValues()"; 272 break; 273 case LocalFlashWidget: 274 case LocalGetGeometry: 275 str = " asking it to perform GetGeometry()"; 276 break; 277 case LocalGetResources: 278 str = " asking it to get a widget's resource list"; 279 break; 280 case LocalFindChild: 281 str = " asking it to find the child Widget."; 282 break; 283 default: 284 str = ""; 285 break; 286 } 287 288 snprintf(msg, sizeof(msg), res_labels[8], str); 289 SetMessage(label, msg); 290 } 291 292 293 295 /* Function Name: ConvertCommand 296 * Description: Converts the command string into a selection that can 297 * be sent to the client. 298 * Arguments: (see Xt) 299 * Returns: TRUE if we could convert the selection and target asked for. 300 */ 301 302 /* ARGSUSED */ 303 static Boolean 304 ConvertCommand(Widget w, Atom *selection, Atom *target, Atom *type_ret, 305 XtPointer *value_ret, unsigned long *length_ret, int *format_ret) 306 { 307 if ((*selection != atom_comm) || (*target != atom_command)) 308 return(FALSE); 309 310 *type_ret = atom_editres_protocol; 311 *value_ret = (XtPointer) global_client.stream.real_top; 312 *length_ret = global_client.stream.size + HEADER_SIZE; 313 *format_ret = EDITRES_FORMAT; 314 315 return(TRUE); 316 } 317 318 319 321 /* Function Name: SelectionDone 322 * Description: done with the selection. 323 * Arguments: *** UNUSED *** 324 * Returns: none. 325 */ 326 327 /* ARGSUSED */ 328 static void 329 SelectionDone(Widget w, Atom *sel, Atom *targ) 330 { 331 /* Keep the toolkit from automatically freeing the selection value */ 332 } 333 334 335 337 /* Function Name: LoseSelection 338 * Description: Called when we have lost the selection, asks client 339 * for the selection value. 340 * Arguments: w - the widget that just lost the selection. 341 * sel - the selection. 342 * Returns: none. 343 */ 344 345 static void 346 LoseSelection(Widget w, Atom *sel) 347 { 348 if (global_client.timeout != 0) { 349 XtRemoveTimeOut(global_client.timeout); 350 global_client.timeout = 0; 351 } 352 353 XtGetSelectionValue(w, *sel, atom_client_value, GetClientValue, 354 NULL, XtLastTimestampProcessed(XtDisplay(w))); 355 } 356 357 358 360 /* Function Name: GetClientValue 361 * Description: Gets the value out of the client, and does good things 362 * to it. 363 * Arguments: w - the widget that asked for the selection. 364 * data - client_data *** UNUSED ***. 365 * sel - the selection. 366 * type - the type of the selection. 367 * value - the selection's value. 368 * length - the length of the selection's value. 369 * format - the format of the selection. 370 * Returns: none. 371 */ 372 373 static Boolean reset_protocol_level = True; 374 375 /* ARGSUSED */ 376 static void 377 GetClientValue(Widget w, XtPointer data, Atom *selection, Atom *type, 378 XtPointer value, unsigned long *length, int *format) 379 { 380 Event * event; 381 ProtocolStream alloc_stream, *stream; 382 unsigned char ident, error_code; 383 char * error_str = NULL, msg[BUFSIZ]; 384 385 if (*length == 0) 386 return; 387 388 stream = &alloc_stream; /* easier to think of it this way... */ 389 390 stream->current = stream->top = (unsigned char *) value; 391 stream->size = HEADER_SIZE; /* size of header. */ 392 393 /* 394 * Retrieve the Header. 395 */ 396 397 if (*length < HEADER_SIZE) { 398 SetMessage(global_screen_data.info_label, 399 res_labels[9]); 400 return; 401 } 402 403 (void) _XEditResGet8(stream, &ident); 404 if (global_client.ident != ident) { 405 #ifdef DEBUG 406 if (global_resources.debug) 407 printf("Incorrect ident from client.\n"); 408 #endif 409 if (!XtOwnSelection(w, *selection, CurrentTime, ConvertCommand, 410 LoseSelection, SelectionDone)) 411 SetMessage(global_screen_data.info_label, 412 res_labels[10]); 413 return; 414 } 415 416 (void) _XEditResGet8(stream, &error_code); 417 (void) _XEditResGet32(stream, &(stream->size)); 418 stream->top = stream->current; /* reset stream to top of value.*/ 419 420 switch ((int) error_code) { 421 case PartialSuccess: 422 if ((event = BuildEvent(stream)) != NULL) { 423 error_str = DispatchEvent(event); 424 FreeEvent(event); 425 } 426 else { 427 snprintf(msg, sizeof(msg), "Unable to unpack protocol request."); 428 error_str = XtNewString(msg); 429 } 430 break; 431 case Failure: 432 error_str = GetFailureMessage(stream); 433 break; 434 case ProtocolMismatch: 435 error_str = ProtocolFailure(stream); 436 if (!--global_effective_protocol_version) 437 break; 438 /* normally protocol version is reset to current during a SendWidgetTree 439 * request, however, after a protocol failure this is skipped once for 440 * a retry. 441 */ 442 reset_protocol_level = False; 443 SetCommand(w, LocalSendWidgetTree, NULL); 444 break; 445 default: 446 snprintf(msg, sizeof(msg), res_labels[11], (int) error_code); 447 SetMessage(global_screen_data.info_label, msg); 448 break; 449 } 450 451 if (error_str == NULL) { 452 WNode * top; 453 454 if (global_tree_info == NULL) 455 return; 456 457 top = global_tree_info->top_node; 458 snprintf(msg, sizeof(msg), res_labels[12], top->name, top->class); 459 SetMessage(global_screen_data.info_label, msg); 460 return; 461 } 462 SetMessage(global_screen_data.info_label, error_str); 463 XtFree(error_str); 464 } 465 466 467 469 /* Function Name: BuildHeader 470 * Description: Puts the header into the message. 471 * Arguments: client_data - the client data. 472 * Returns: none. 473 */ 474 475 static void 476 BuildHeader(CurrentClient *client_data) 477 { 478 unsigned long old_alloc, old_size; 479 unsigned char * old_current; 480 EditresCommand command; 481 ProtocolStream * stream = &(client_data->stream); 482 483 /* 484 * We have cleverly keep enough space at the top of the header 485 * for the return protocol stream, so all we have to do is 486 * fill in the space. 487 */ 488 489 /* 490 * Fool the insert routines into putting the header in the right 491 * place while being damn sure not to realloc (that would be very bad. 492 */ 493 494 old_current = stream->current; 495 old_alloc = stream->alloc; 496 old_size = stream->size; 497 498 stream->current = stream->real_top; 499 stream->alloc = stream->size + (2 * HEADER_SIZE); 500 501 _XEditResPut8(stream, client_data->ident); 502 switch(client_data->command) { 503 case LocalSendWidgetTree: 504 if (reset_protocol_level) global_effective_protocol_version = 505 CURRENT_PROTOCOL_VERSION; 506 reset_protocol_level = True; 507 command = SendWidgetTree; 508 break; 509 case LocalSetValues: 510 command = SetValues; 511 break; 512 case LocalFlashWidget: 513 command = GetGeometry; 514 break; 515 case LocalGetResources: 516 command = GetResources; 517 break; 518 case LocalFindChild: 519 command = FindChild; 520 break; 521 case LocalGetValues: 522 command = GetValues; 523 break; 524 default: 525 command = SendWidgetTree; 526 break; 527 } 528 529 _XEditResPut8(stream, (unsigned char) command); 530 _XEditResPut32(stream, old_size); 531 532 stream->alloc = old_alloc; 533 stream->current = old_current; 534 stream->size = old_size; 535 } 536 537 538 540 /* Function Name: BuildEvent 541 * Description: Builds the event structure from the 542 * Arguments: stream - the protocol data stream. 543 * Returns: event - the event. 544 */ 545 546 static Event * 547 BuildEvent(ProtocolStream *stream) 548 { 549 int i; 550 Event * event = (Event *) XtCalloc(sizeof(Event), 1); 551 552 /* 553 * The return value will be different depending upon the 554 * request sent out. 555 */ 556 557 switch(global_client.command) { 558 case LocalSendWidgetTree: 559 { 560 SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event; 561 562 send_event->type = SendWidgetTree; 563 564 if (!_XEditResGet16(stream, &(send_event->num_entries))) 565 goto done; 566 567 send_event->info = (WidgetTreeInfo *) 568 XtCalloc(sizeof(WidgetTreeInfo), 569 send_event->num_entries); 570 571 for (i = 0; i < (int)send_event->num_entries; i++) { 572 WidgetTreeInfo * info = send_event->info + i; 573 if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 574 _XEditResGetString8(stream, &(info->name)) && 575 _XEditResGetString8(stream, &(info->class)) && 576 _XEditResGet64(stream, &(info->window)))) 577 { 578 goto done; 579 } 580 } 581 582 if (global_effective_protocol_version == 583 CURRENT_PROTOCOL_VERSION) { 584 /* get toolkit type and reset if necessary */ 585 if (!_XEditResGetString8(stream, &(send_event->toolkit))) 586 goto done; 587 } 588 /* set the command menu entries senitive */ 589 SetEntriesSensitive(&CM_entries[CM_OFFSET], CM_NUM, True); 590 /* set the tree menu entries senitive */ 591 SetEntriesSensitive(TM_entries, TM_NUM, True); 592 if (global_effective_protocol_version == 593 CURRENT_PROTOCOL_VERSION) { 594 if (!strcmp(send_event->toolkit, "InterViews")) 595 RebuildMenusAndLabel("iv"); 596 } 597 else 598 RebuildMenusAndLabel("xt"); 599 } 600 break; 601 case LocalSetValues: 602 { 603 SetValuesEvent * sv_event = (SetValuesEvent *) event; 604 605 sv_event->type = SetValues; 606 607 if (!_XEditResGet16(stream, &(sv_event->num_entries))) 608 goto done; 609 610 sv_event->info = (SetValuesInfo *) XtCalloc(sizeof(SetValuesInfo), 611 sv_event->num_entries); 612 613 for (i = 0; i < (int)sv_event->num_entries; i++) { 614 SetValuesInfo * info = sv_event->info + i; 615 if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 616 _XEditResGetString8(stream, &(info->message)))) 617 { 618 goto done; 619 } 620 } 621 } 622 break; 623 case LocalGetResources: 624 { 625 GetResourcesEvent * res_event = (GetResourcesEvent *) event; 626 627 res_event->type = GetGeometry; 628 629 if (!_XEditResGet16(stream, &(res_event->num_entries))) 630 goto done; 631 632 res_event->info = (GetResourcesInfo *) 633 XtCalloc(sizeof(GetResourcesInfo), 634 res_event->num_entries); 635 636 for (i = 0; i < (int)res_event->num_entries; i++) { 637 GetResourcesInfo * res_info = res_event->info + i; 638 if (!(_XEditResGetWidgetInfo(stream, &(res_info->widgets)) && 639 _XEditResGetBoolean(stream, &(res_info->error)))) 640 { 641 goto done; 642 } 643 if (res_info->error) { 644 if (!_XEditResGetString8(stream, &(res_info->message))) 645 goto done; 646 } 647 else { 648 unsigned int j; 649 650 if (!_XEditResGet16(stream, &(res_info->num_resources))) 651 goto done; 652 653 res_info->res_info = (ResourceInfo *) 654 XtCalloc(sizeof(ResourceInfo), 655 res_info->num_resources); 656 657 for (j = 0; j < res_info->num_resources; j++) { 658 unsigned char temp; 659 ResourceInfo * info = res_info->res_info + j; 660 if (!(_XEditResGetResType(stream, &(temp)) && 661 _XEditResGetString8(stream, &(info->name)) && 662 _XEditResGetString8(stream, &(info->class)) && 663 _XEditResGetString8(stream, &(info->type)))) 664 { 665 goto done; 666 } 667 else 668 info->res_type = (ResourceType) temp; 669 } /* for */ 670 } /* else */ 671 } /* for */ 672 } 673 break; 674 case LocalFlashWidget: 675 case LocalGetGeometry: 676 { 677 GetGeomEvent * geom_event = (GetGeomEvent *) event; 678 679 geom_event->type = GetGeometry; 680 681 if (!_XEditResGet16(stream, &(geom_event->num_entries))) 682 goto done; 683 684 geom_event->info = (GetGeomInfo *) XtCalloc(sizeof(GetGeomInfo), 685 geom_event->num_entries); 686 687 for (i = 0; i < (int)geom_event->num_entries; i++) { 688 GetGeomInfo * info = geom_event->info + i; 689 if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 690 _XEditResGetBoolean(stream, &(info->error)))) 691 { 692 goto done; 693 } 694 if (info->error) { 695 if (!_XEditResGetString8(stream, &(info->message))) 696 goto done; 697 } 698 else { 699 if (!(_XEditResGetBoolean(stream, &(info->visible)) && 700 _XEditResGetSigned16(stream, &(info->x)) && 701 _XEditResGetSigned16(stream, &(info->y)) && 702 _XEditResGet16(stream, &(info->width)) && 703 _XEditResGet16(stream, &(info->height)) && 704 _XEditResGet16(stream, &(info->border_width)))) 705 { 706 goto done; 707 } 708 } 709 } 710 } 711 break; 712 case LocalFindChild: 713 { 714 FindChildEvent * find_event = (FindChildEvent *) event; 715 716 find_event->type = FindChild; 717 718 if (!_XEditResGetWidgetInfo(stream, &(find_event->widgets))) 719 goto done; 720 } 721 break; 722 case LocalGetValues: /* This is for REPLY... */ 723 { 724 Arg args[1]; 725 GetValuesEvent * gv_event = (GetValuesEvent *) event; 726 727 gv_event->type = GetValues; 728 729 if (!_XEditResGet16(stream, &(gv_event->num_entries))) 730 goto done; 731 732 gv_event->info = (GetValuesInfo*)XtCalloc(sizeof(GetValuesInfo),1); 733 734 { 735 GetValuesInfo * info = gv_event->info; 736 if (!(_XEditResGetString8(stream, &(info->value)))) 737 { 738 goto done; 739 } 740 741 /* set the string value of the asciitext widget. note that only 742 * one active node is dealt with here. This is ok because only 743 * one node can be active when the resource box is up. 744 */ 745 746 XtSetArg (args[0], XtNstring, info->value); 747 748 XtSetValues( 749 global_tree_info->active_nodes[0]->resources->res_box->value_wid, 750 args, 1 751 ); 752 } 753 } 754 break; 755 756 default: 757 goto done; 758 } 759 760 return(event); 761 762 done: 763 FreeEvent(event); 764 return(NULL); 765 } 766 767 768 770 /* Function Name: FreeEvent 771 * Description: Frees all memory associated with the event. 772 * Arguments: event - the event. 773 * Returns: none. 774 * 775 * NOTE: XtFree() returns w/o freeing if ptr is NULL. 776 */ 777 778 static void 779 FreeEvent(Event *event) 780 { 781 unsigned int i; 782 783 switch(event->any_event.type) { 784 case SendWidgetTree: 785 { 786 SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event; 787 WidgetTreeInfo * info = send_event->info; 788 789 if (info != NULL) { 790 for (i = 0; i < send_event->num_entries; i++, info++) { 791 XtFree((char *)info->widgets.ids); 792 XtFree(info->name); 793 XtFree(info->class); 794 } 795 XtFree((char *)send_event->info); 796 } 797 } 798 break; 799 case SetValues: 800 { 801 SetValuesEvent * sv_event = (SetValuesEvent *) event; 802 SetValuesInfo * info = sv_event->info; 803 804 if (info != NULL) { 805 for (i = 0; i < sv_event->num_entries; i++, info++) { 806 XtFree((char *)info->widgets.ids); 807 XtFree(info->message); 808 } 809 XtFree((char *)sv_event->info); 810 } 811 } 812 break; 813 case GetResources: 814 { 815 GetResourcesEvent * get_event = (GetResourcesEvent *) event; 816 GetResourcesInfo * info = get_event->info; 817 818 if (info != NULL) { 819 for (i = 0; i < get_event->num_entries; i++, info++) { 820 XtFree((char *)info->widgets.ids); 821 if (info->error) 822 XtFree(info->message); 823 else { 824 unsigned int j; 825 ResourceInfo * res_info = info->res_info; 826 827 if (res_info != NULL) { 828 for (j = 0; 829 j < info->num_resources; j++, res_info++) 830 { 831 XtFree(res_info->name); 832 XtFree(res_info->class); 833 XtFree(res_info->type); 834 } 835 XtFree((char *)info->res_info); 836 } 837 } 838 } 839 XtFree((char *)get_event->info); 840 } 841 } 842 break; 843 case GetGeometry: 844 { 845 GetGeomEvent * geom_event = (GetGeomEvent *) event; 846 GetGeomInfo * info = geom_event->info; 847 848 if (info != NULL) { 849 for (i = 0; i < geom_event->num_entries; i++, info++) { 850 XtFree((char *)info->widgets.ids); 851 if (info->error) 852 XtFree(info->message); 853 } 854 XtFree((char *)geom_event->info); 855 } 856 } 857 break; 858 case FindChild: 859 { 860 FindChildEvent * find_event = (FindChildEvent *) event; 861 862 XtFree((char *)find_event->widgets.ids); 863 } 864 break; 865 default: 866 break; 867 } 868 } 869 870 871 873 /* Function Name: DispatchEvent 874 * Description: Handles the event, calling the proper function. 875 * Arguments: event - the event. 876 * Returns: one. 877 */ 878 879 static char * 880 DispatchEvent(Event *event) 881 { 882 char * error = NULL; 883 884 switch(global_client.command) { 885 case LocalSendWidgetTree: 886 BuildVisualTree(global_tree_parent, event); 887 break; 888 case LocalSetValues: 889 error = PrintSetValuesError(event); 890 break; 891 case LocalFlashWidget: 892 error = HandleFlashWidget(event); 893 break; 894 case LocalGetResources: 895 error = HandleGetResources(event); 896 break; 897 case LocalFindChild: 898 DisplayChild(event); 899 break; 900 case LocalGetValues: 901 break; 902 default: 903 { 904 char msg[BUFSIZ]; 905 snprintf(msg, sizeof(msg), "Internal error: Unknown command %d.", 906 global_client.command); 907 error = XtNewString(msg); 908 } 909 break; 910 } 911 return(error); 912 } 913 914 915 917 /* Function Name: InternAtoms 918 * Description: interns all static atoms. 919 * Arguments: display - the current display. 920 * Returns: none. 921 */ 922 923 void 924 InternAtoms(Display * dpy) 925 { 926 atom_comm = XInternAtom(dpy, EDITRES_COMM_ATOM, False); 927 atom_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False); 928 atom_resource_editor = XInternAtom(dpy, EDITRES_NAME, False); 929 atom_client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False); 930 atom_editres_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False); 931 } 932 933 ResIdent 934 GetNewIdent(void) 935 { 936 static ResIdent ident = 1; 937 938 return(ident++); 939 } 940