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