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