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