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