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