1 /* 2 3 Copyright 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in this Software without prior written authorization from The Open Group. 24 25 */ 26 27 /* 28 * Author: Chris D. Peterson, Dave Sternlicht, MIT X Consortium 29 */ 30 31 #ifdef HAVE_CONFIG_H 32 #include <config.h> 33 #endif 34 #include <X11/IntrinsicP.h> /* To get into the composite and core widget 35 structures. */ 36 #include <X11/ObjectP.h> /* For XtIs<Classname> macros. */ 37 #include <X11/StringDefs.h> /* for XtRString. */ 38 #include <X11/ShellP.h> /* for Application Shell Widget class. */ 39 40 #include <X11/Xatom.h> 41 #include <X11/Xos.h> /* for strcpy declaration */ 42 #include <X11/Xfuncs.h> 43 #include <X11/Xmu/EditresP.h> 44 #include <X11/Xmd.h> 45 #include <X11/Xmu/CharSet.h> 46 #include <X11/Xmu/SysUtil.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 51 #define _XEditResPutBool _XEditResPut8 52 #define _XEditResPutResourceType _XEditResPut8 53 54 /* 55 * Types 56 */ 57 typedef enum { 58 BlockNone, 59 BlockSetValues, 60 BlockAll 61 } EditresBlock; 62 63 typedef struct _SetValuesEvent { 64 EditresCommand type; /* first field must be type */ 65 WidgetInfo *widgets; 66 unsigned short num_entries; /* number of set values requests */ 67 char *name; 68 char *res_type; 69 XtPointer value; 70 unsigned short value_len; 71 } SetValuesEvent; 72 73 typedef struct _SVErrorInfo { 74 SetValuesEvent *event; 75 ProtocolStream *stream; 76 unsigned short *count; 77 WidgetInfo *entry; 78 } SVErrorInfo; 79 80 typedef struct _GetValuesEvent { 81 EditresCommand type; /* first field must be type */ 82 WidgetInfo *widgets; 83 unsigned short num_entries; /* number of get values requests */ 84 char *name; 85 } GetValuesEvent; 86 87 typedef struct _FindChildEvent { 88 EditresCommand type; /* first field must be type */ 89 WidgetInfo *widgets; 90 short x, y; 91 } FindChildEvent; 92 93 typedef struct _GenericGetEvent { 94 EditresCommand type; /* first field must be type */ 95 WidgetInfo *widgets; 96 unsigned short num_entries; /* number of set values requests */ 97 } GenericGetEvent, GetResEvent, GetGeomEvent; 98 99 /* 100 * Common to all events 101 */ 102 typedef struct _AnyEvent { 103 EditresCommand type; /* first field must be type */ 104 WidgetInfo *widgets; 105 } AnyEvent; 106 107 /* 108 * The event union 109 */ 110 typedef union _EditresEvent { 111 AnyEvent any_event; 112 SetValuesEvent set_values_event; 113 GetResEvent get_resources_event; 114 GetGeomEvent get_geometry_event; 115 FindChildEvent find_child_event; 116 } EditresEvent; 117 118 typedef struct _Globals { 119 EditresBlock block; 120 SVErrorInfo error_info; 121 ProtocolStream stream; 122 ProtocolStream *command_stream; /* command stream */ 123 } Globals; 124 125 #define CURRENT_PROTOCOL_VERSION 6L 126 127 #define streq(a,b) (strcmp((a), (b)) == 0) 128 129 /* 130 * Prototypes 131 */ 132 static Widget _FindChild(Widget, int, int); 133 static void _XEditresGetStringValues(Widget, Arg*, int); 134 static XtPointer BuildReturnPacket(ResIdent, EditResError, ProtocolStream*); 135 static void CommandDone(Widget, Atom*, Atom*); 136 static Boolean ConvertReturnCommand(Widget, Atom*, Atom*, Atom*, XtPointer*, 137 unsigned long*, int*); 138 static Boolean CvtStringToBlock(Display*, XrmValue*, Cardinal*, 139 XrmValue*, XrmValue*, XtPointer*); 140 static EditresEvent *BuildEvent(Widget, Atom, XtPointer, ResIdent, 141 unsigned long); 142 static _Xconst char *DoFindChild(Widget, EditresEvent*, ProtocolStream*); 143 static _Xconst char *DoGetGeometry(Widget, EditresEvent*, ProtocolStream*); 144 static _Xconst char *DoGetResources(Widget, EditresEvent*, ProtocolStream*); 145 static _Xconst char *DoSetValues(Widget, EditresEvent*, ProtocolStream*); 146 static void DumpChildren(Widget, ProtocolStream*, unsigned short*); 147 static _Xconst char *DumpValues(Widget, EditresEvent*, ProtocolStream*); 148 static _Xconst char *DumpWidgets(Widget, EditresEvent*, ProtocolStream*); 149 static void ExecuteCommand(Widget, Atom, ResIdent, EditresEvent*); 150 static void ExecuteGetGeometry(Widget, ProtocolStream*); 151 static void ExecuteGetResources(Widget w, ProtocolStream *stream); 152 static void ExecuteSetValues(Widget, SetValuesEvent*, WidgetInfo*, 153 ProtocolStream*, unsigned short*); 154 static void FreeEvent(EditresEvent*); 155 static void GetCommand(Widget w, XtPointer, Atom*, Atom*, XtPointer, 156 unsigned long*, int*); 157 static void HandleToolkitErrors(String, String, String, String, 158 String*, Cardinal*); 159 static void InsertWidget(ProtocolStream*, Widget); 160 static Bool IsChild(Widget, Widget, Widget); 161 static Bool isApplicationShell(Widget); 162 static void LoadResources(Widget); 163 static Bool PositionInChild(Widget, int, int); 164 static int qcmp_widget_list(register _Xconst void*, register _Xconst void*); 165 static void SendCommand(Widget, Atom, ResIdent, EditResError, 166 ProtocolStream*); 167 static void SendFailure(Widget, Atom, ResIdent, _Xconst char*); 168 static _Xconst char *VerifyWidget(Widget, WidgetInfo*); 169 170 /* 171 * External 172 */ 173 void _XEditResCheckMessages(Widget, XtPointer, XEvent*, Boolean*); 174 void _XEditResCleanup(void); 175 176 /* 177 * Initialization 178 */ 179 static Atom res_editor_command, res_editor_protocol, client_value; 180 static Globals globals; 181 182 /************************************************************ 183 * Resource Editor Communication Code 184 ************************************************************/ 185 /* 186 * Function: 187 * _XEditResCheckMessages 188 * 189 * Parameters: 190 * data - unused 191 * event - The X Event that triggered this handler 192 * cont - unused 193 * 194 * Description: 195 * This callback routine is set on all shell widgets, and checks to 196 * see if a client message event has come from the resource editor. 197 */ 198 /*ARGSUSED*/ 199 void 200 _XEditResCheckMessages(Widget w, XtPointer data, XEvent *event, Boolean *cont) 201 { 202 Time time; 203 ResIdent ident; 204 static Boolean first_time = False; 205 static Atom res_editor, res_comm; 206 Display *dpy; 207 208 if (event->type == ClientMessage) 209 { 210 XClientMessageEvent * c_event = (XClientMessageEvent *)event; 211 dpy = XtDisplay(w); 212 213 if (!first_time) 214 { 215 Atom atoms[4]; 216 static _Xconst char *names[] = { 217 EDITRES_NAME, EDITRES_COMMAND_ATOM, 218 EDITRES_PROTOCOL_ATOM, EDITRES_CLIENT_VALUE 219 }; 220 221 first_time = True; 222 XInternAtoms(dpy, (char **) names, 4, False, atoms); 223 res_editor = atoms[0]; 224 res_editor_command = atoms[1]; 225 res_editor_protocol = atoms[2]; 226 /* Used in later procedures */ 227 client_value = atoms[3]; 228 LoadResources(w); 229 } 230 231 if ((c_event->message_type != res_editor) 232 || (c_event->format != EDITRES_SEND_EVENT_FORMAT)) 233 return; 234 235 time = XtLastTimestampProcessed(dpy); 236 res_comm = c_event->data.l[1]; 237 ident = (ResIdent) c_event->data.l[2]; 238 if (c_event->data.l[3] != CURRENT_PROTOCOL_VERSION) 239 { 240 _XEditResResetStream(&globals.stream); 241 _XEditResPut8(&globals.stream, 242 (unsigned int) CURRENT_PROTOCOL_VERSION); 243 SendCommand(w, res_comm, ident, ProtocolMismatch, &globals.stream); 244 return; 245 } 246 247 XtGetSelectionValue(w, res_comm, res_editor_command, 248 GetCommand, (XtPointer)(long)ident, time); 249 } 250 } 251 252 /* 253 * Function: 254 * _XEditResCleanup 255 * 256 * Description: 257 * Free the protocol stream. 258 */ 259 void 260 _XEditResCleanup(void) 261 { 262 _XEditResFreeStream(&globals.stream); 263 _XEditResFreeStream(globals.command_stream); 264 memset(&globals.stream, 0, sizeof globals.stream); 265 globals.command_stream = NULL; 266 } 267 268 /* 269 * Function: 270 * BuildEvent 271 * 272 * Parameters: 273 * w - widget to own selection, in case of error 274 * sel - selection to send error message beck in 275 * data - the data for the request 276 * ident - the id number we are looking for 277 * length - length of request 278 * 279 * Description: 280 * Takes the info out the protocol stream an constructs 281 * the proper event structure. 282 * 283 * Returns: 284 * the event, or NULL 285 */ 286 #if defined(ERROR_MESSAGE) 287 #undef ERROR_MESSAGE 288 #endif 289 #define ERROR_MESSAGE "Client: Improperly formatted protocol request" 290 static EditresEvent * 291 BuildEvent(Widget w, Atom sel, XtPointer data, ResIdent ident, 292 unsigned long length) 293 { 294 EditresEvent *event; 295 ProtocolStream alloc_stream, *stream; 296 unsigned char temp; 297 register unsigned int i; 298 299 stream = &alloc_stream; 300 stream->current = stream->top = (unsigned char *)data; 301 stream->size = HEADER_SIZE; /* size of header */ 302 303 /* 304 * Retrieve the Header 305 */ 306 if (length < HEADER_SIZE) 307 { 308 SendFailure(w, sel, ident, ERROR_MESSAGE); 309 return (NULL); 310 } 311 312 (void)_XEditResGet8(stream, &temp); 313 if (temp != ident) /* Id's don't match, ignore request */ 314 return (NULL); 315 316 event = (EditresEvent *)XtCalloc(sizeof(EditresEvent), 1); 317 318 (void)_XEditResGet8(stream, &temp); 319 event->any_event.type = (EditresCommand)temp; 320 (void)_XEditResGet32(stream, &stream->size); 321 stream->top = stream->current; /* reset stream to top of value */ 322 323 /* 324 * Now retrieve the data segment 325 */ 326 switch(event->any_event.type) 327 { 328 case SendWidgetTree: 329 break; /* no additional info */ 330 case SetValues: 331 { 332 SetValuesEvent *sv_event = (SetValuesEvent *)event; 333 334 if (!(_XEditResGetString8(stream, &sv_event->name) 335 && _XEditResGetString8(stream, &sv_event->res_type))) 336 goto done; 337 338 /* 339 * Since we need the value length, we have to pull the 340 * value out by hand 341 */ 342 if (!_XEditResGet16(stream, &sv_event->value_len)) 343 goto done; 344 345 sv_event->value = XtMalloc(sizeof(char) * (sv_event->value_len + 1)); 346 347 for (i = 0; i < sv_event->value_len; i++) 348 if (!_XEditResGet8(stream, (unsigned char *)sv_event->value + i)) 349 goto done; 350 351 ((char*)sv_event->value)[i] = '\0'; 352 353 if (!_XEditResGet16(stream, &sv_event->num_entries)) 354 goto done; 355 356 sv_event->widgets = (WidgetInfo *) 357 XtCalloc(sizeof(WidgetInfo), sv_event->num_entries); 358 359 for (i = 0; i < sv_event->num_entries; i++) 360 if (!_XEditResGetWidgetInfo(stream, sv_event->widgets + i)) 361 goto done; 362 } 363 break; 364 case FindChild: 365 { 366 FindChildEvent *find_event = (FindChildEvent *)event; 367 368 find_event->widgets = (WidgetInfo *)XtCalloc(sizeof(WidgetInfo), 1); 369 370 if (!(_XEditResGetWidgetInfo(stream, find_event->widgets) 371 && _XEditResGetSigned16(stream, &find_event->x) 372 && _XEditResGetSigned16(stream, &find_event->y))) 373 goto done; 374 } 375 break; 376 case GetGeometry: 377 case GetResources: 378 { 379 GenericGetEvent *get_event = (GenericGetEvent *)event; 380 381 if (!_XEditResGet16(stream, &get_event->num_entries)) 382 goto done; 383 384 get_event->widgets = (WidgetInfo *) 385 XtCalloc(sizeof(WidgetInfo), get_event->num_entries); 386 387 for (i = 0; i < get_event->num_entries; i++) 388 if (!_XEditResGetWidgetInfo(stream, get_event->widgets + i)) 389 goto done; 390 } 391 break; 392 case GetValues: 393 { 394 GetValuesEvent *gv_event = (GetValuesEvent *)event; 395 396 _XEditResGetString8(stream, &gv_event->name); 397 _XEditResGet16(stream, &gv_event->num_entries); 398 gv_event->widgets = (WidgetInfo *) 399 XtCalloc(sizeof(WidgetInfo), gv_event->num_entries); 400 _XEditResGetWidgetInfo(stream, gv_event->widgets); 401 } 402 break; 403 default: 404 { 405 char buf[BUFSIZ]; 406 407 XmuSnprintf(buf, sizeof(buf), 408 "Unknown Protocol request %d.", event->any_event.type); 409 SendFailure(w, sel, ident, buf); 410 FreeEvent(event); 411 return (NULL); 412 } 413 } 414 415 return (event); 416 417 done: 418 SendFailure(w, sel, ident, ERROR_MESSAGE); 419 FreeEvent(event); 420 return (NULL); 421 } 422 423 /* 424 * Function: 425 * FreeEvent 426 * 427 * Parameters: 428 * event - event to free 429 * 430 * Description: 431 * Frees the event structure and any other pieces in it that need freeing. 432 */ 433 static void 434 FreeEvent(EditresEvent *event) 435 { 436 if (event->any_event.widgets != NULL) 437 { 438 XtFree((char *)event->any_event.widgets->ids); 439 XtFree((char *)event->any_event.widgets); 440 } 441 442 if (event->any_event.type == SetValues) 443 { 444 XtFree(event->set_values_event.name); 445 XtFree(event->set_values_event.res_type); 446 } 447 448 XtFree((char *)event); 449 } 450 451 /* 452 * Function: 453 * GetCommand 454 * 455 * Parameters: 456 * (See Xt XtConvertSelectionProc) 457 * data - contains the ident number for the command 458 * 459 * Description: 460 * Gets the Command out of the selection asserted by the resource manager. 461 */ 462 /*ARGSUSED*/ 463 static void 464 GetCommand(Widget w, XtPointer data, Atom *selection, Atom *type, 465 XtPointer value, unsigned long *length, int *format) 466 { 467 ResIdent ident = (ResIdent)(long)data; 468 EditresEvent *event; 469 470 if (*type != res_editor_protocol || *format != EDITRES_FORMAT) 471 return; 472 473 if ((event = BuildEvent(w, *selection, value, ident, *length)) != NULL) 474 { 475 ExecuteCommand(w, *selection, ident, event); 476 FreeEvent(event); 477 } 478 } 479 480 /* 481 * Function: 482 * ExecuteCommand 483 * 484 * Parameters: 485 * w - widget 486 * command - the command to execute 487 * value - the associated with the command 488 * 489 * Description: 490 * Executes a command string received from the resource editor. 491 */ 492 /*ARGSUSED*/ 493 static void 494 ExecuteCommand(Widget w, Atom sel, ResIdent ident, EditresEvent *event) 495 { 496 _Xconst char *(*func)(Widget, EditresEvent*, ProtocolStream*); 497 _Xconst char *str; 498 499 if (globals.block == BlockAll) 500 { 501 SendFailure(w, sel, ident, 502 "This client has blocked all Editres commands."); 503 return; 504 } 505 else if (globals.block == BlockSetValues 506 && event->any_event.type == SetValues) 507 { 508 SendFailure(w, sel, ident, 509 "This client has blocked all SetValues requests."); 510 return; 511 } 512 513 switch(event->any_event.type) 514 { 515 case SendWidgetTree: 516 func = DumpWidgets; 517 break; 518 case SetValues: 519 func = DoSetValues; 520 break; 521 case FindChild: 522 func = DoFindChild; 523 break; 524 case GetGeometry: 525 func = DoGetGeometry; 526 break; 527 case GetResources: 528 func = DoGetResources; 529 break; 530 case GetValues: 531 func = DumpValues; 532 break; 533 default: 534 { 535 char buf[BUFSIZ]; 536 537 XmuSnprintf(buf, sizeof(buf), 538 "Unknown Protocol request %d.",event->any_event.type); 539 SendFailure(w, sel, ident, buf); 540 return; 541 } 542 } 543 544 _XEditResResetStream(&globals.stream); 545 if ((str = (*func)(w, event, &globals.stream)) == NULL) 546 SendCommand(w, sel, ident, PartialSuccess, &globals.stream); 547 else 548 SendFailure(w, sel, ident, str); 549 } 550 551 /* 552 * Function: 553 * ConvertReturnCommand 554 * 555 * Parameters: 556 * w - the widget that owns the selection 557 * selection - selection to convert 558 * target - target type for this selection 559 * type_ret - type of the selection 560 * value_ret - selection value 561 * length_ret - length of this selection 562 * format_ret - the format the selection is in 563 * 564 * Description: 565 * Converts a selection 566 * 567 * Returns: 568 * True if conversion was successful 569 */ 570 /*ARGSUSED*/ 571 static Boolean 572 ConvertReturnCommand(Widget w, Atom *selection, Atom *target, Atom *type_ret, 573 XtPointer *value_ret, unsigned long *length_ret, 574 int *format_ret) 575 { 576 /* 577 * I assume the intrinsics give me the correct selection back 578 */ 579 if ((*target != client_value)) 580 return (False); 581 582 *type_ret = res_editor_protocol; 583 *value_ret = (XtPointer)globals.command_stream->real_top; 584 *length_ret = globals.command_stream->size + HEADER_SIZE; 585 *format_ret = EDITRES_FORMAT; 586 587 return (True); 588 } 589 590 /* 591 * Function: 592 * CommandDone 593 * 594 * Parameters: 595 * widget - unused 596 * selection - unused 597 * target - unused 598 * 599 * Description: 600 * done with the selection 601 */ 602 /*ARGSUSED*/ 603 static void 604 CommandDone(Widget widget, Atom *selection, Atom *target) 605 { 606 /* Keep the toolkit from automatically freeing the selection value */ 607 } 608 609 /* 610 * Function: 611 * SendFailure 612 * 613 * Parameters: 614 * w - widget to own the selection 615 * sel - selection to assert 616 * ident - identifier 617 * str - error message 618 * 619 * Description: 620 * Sends a failure message 621 */ 622 static void 623 SendFailure(Widget w, Atom sel, ResIdent ident, _Xconst char *str) 624 { 625 _XEditResResetStream(&globals.stream); 626 _XEditResPutString8(&globals.stream, str); 627 SendCommand(w, sel, ident, Failure, &globals.stream); 628 } 629 630 /* 631 * Function: 632 * BuildReturnPacket 633 * 634 * Parameters: 635 * ident - identifier 636 * command - command code 637 * stream - protocol stream 638 * Description: 639 * Builds a return packet, given the data to send 640 * 641 * Returns: 642 * packet to send 643 */ 644 static XtPointer 645 BuildReturnPacket(ResIdent ident, EditResError error, ProtocolStream *stream) 646 { 647 long old_alloc, old_size; 648 unsigned char *old_current; 649 650 /* 651 * We have cleverly keep enough space at the top of the header 652 * for the return protocol stream, so all we have to do is 653 * fill in the space 654 */ 655 /* 656 * Fool the insert routines into putting the header in the right 657 * place while being damn sure not to realloc (that would be very bad.) 658 */ 659 old_current = stream->current; 660 old_alloc = stream->alloc; 661 old_size = stream->size; 662 663 stream->current = stream->real_top; 664 stream->alloc = stream->size + (2 * HEADER_SIZE); 665 666 _XEditResPut8(stream, ident); 667 _XEditResPut8(stream, (unsigned char)error); 668 _XEditResPut32(stream, old_size); 669 670 stream->alloc = old_alloc; 671 stream->current = old_current; 672 stream->size = old_size; 673 674 return ((XtPointer)stream->real_top); 675 } 676 677 /* 678 * Function: 679 * SendCommand 680 * Parameters: 681 * w - widget to own the selection 682 * sel - selection to assert 683 * ident - identifier 684 * command - command code 685 * stream - protocol stream 686 * 687 * Description: 688 * Builds a return command line 689 */ 690 static void 691 SendCommand(Widget w, Atom sel, ResIdent ident, EditResError error, 692 ProtocolStream *stream) 693 { 694 BuildReturnPacket(ident, error, stream); 695 globals.command_stream = stream; 696 697 /* 698 * I REALLY want to own the selection. Since this was not triggered 699 * by a user action, and I am the only one using this atom it is safe to 700 * use CurrentTime 701 */ 702 XtOwnSelection(w, sel, CurrentTime, ConvertReturnCommand, NULL, CommandDone); 703 } 704 705 /************************************************************ 706 * Generic Utility Functions 707 ************************************************************/ 708 static int 709 qcmp_widget_list(register _Xconst void *left, register _Xconst void *right) 710 { 711 return (char *)*(Widget **)left - (char *)*(Widget **)right; 712 } 713 714 /* 715 * Function: 716 * FindChildren 717 * 718 * Parameters: 719 * parent - parent widget 720 * children - list of children 721 * normal - return normal children 722 * popup - return popup children 723 * extra - return extra children 724 * 725 * Description: 726 * Returns all children (popup, normal and otherwise) of this widget 727 * 728 * Returns: 729 * number of children 730 */ 731 static int 732 FindChildren(Widget parent, Widget **children, Bool normal, Bool popup, 733 Bool extra) 734 { 735 CompositeWidget cw = (CompositeWidget)parent; 736 Cardinal i, num_children, current = 0; 737 Widget *extra_widgets = NULL; 738 Cardinal num_extra = 0; 739 740 num_children = 0; 741 742 if (XtIsWidget(parent) && popup) 743 num_children += parent->core.num_popups; 744 745 if (XtIsComposite(parent) && normal) 746 num_children += cw->composite.num_children; 747 748 if (XtIsWidget(parent) && extra) 749 { 750 XtResourceList norm_list, cons_list; 751 Cardinal num_norm, num_cons; 752 Arg args[1]; 753 Widget widget; 754 755 XtGetResourceList(XtClass(parent), &norm_list, &num_norm); 756 757 if (XtParent(parent) != NULL) 758 XtGetConstraintResourceList(XtClass(XtParent(parent)), 759 &cons_list, &num_cons); 760 else 761 num_cons = 0; 762 763 extra_widgets = (Widget *)XtMalloc(sizeof(Widget)); 764 for (i = 0; i < num_norm; i++) 765 if (strcmp(norm_list[i].resource_type, XtRWidget) == 0) 766 { 767 widget = NULL; 768 XtSetArg(args[0], norm_list[i].resource_name, &widget); 769 XtGetValues(parent, args, 1); 770 if (widget && XtParent(widget) == parent) 771 { 772 ++num_extra; 773 extra_widgets = (Widget *) XtRealloc( 774 (char *)extra_widgets, num_extra * sizeof(Widget)); 775 extra_widgets[num_extra - 1] = widget; 776 } 777 } 778 for (i = 0; i < num_cons; i++) 779 if (strcmp(cons_list[i].resource_type, XtRWidget) == 0) 780 { 781 widget = NULL; 782 XtSetArg(args[0], cons_list[i].resource_name, &widget); 783 XtGetValues(parent, args, 1); 784 if (widget && XtParent(widget) == parent) 785 { 786 ++num_extra; 787 extra_widgets = (Widget *) XtRealloc( 788 (char *)extra_widgets, num_extra * sizeof(Widget)); 789 extra_widgets[num_extra - 1] = widget; 790 } 791 } 792 if (num_norm) 793 XtFree((char *)norm_list); 794 if (num_cons) 795 XtFree((char *)cons_list); 796 } 797 798 if ((num_children + num_extra) == 0) 799 { 800 *children = NULL; 801 return (0); 802 } 803 804 *children = (Widget *)XtMalloc(sizeof(Widget) * (num_children + num_extra)); 805 806 if (XtIsComposite(parent) && normal) 807 for (i = 0; i < cw->composite.num_children; i++, current++) 808 (*children)[current] = cw->composite.children[i]; 809 810 if (XtIsWidget(parent) && popup) 811 for (i = 0; i < parent->core.num_popups; i++, current++) 812 (*children)[current] = parent->core.popup_list[i]; 813 814 if (num_extra) 815 /* Check for dups */ 816 { 817 Cardinal j, old_num_extra = num_extra; 818 819 qsort(extra_widgets, num_extra, sizeof(Widget), qcmp_widget_list); 820 for (i = 0; i < num_extra - 1; i++) 821 while (i < num_extra - 1 && 822 extra_widgets[i] == extra_widgets[i + 1]) 823 { 824 memmove(&extra_widgets[i], &extra_widgets[i + 1], 825 (num_extra - i) * sizeof(Widget)); 826 --num_extra; 827 } 828 829 for (i = 0; i < num_children; i++) 830 for (j = 0; j < num_extra; j++) 831 if ((*children)[i] == extra_widgets[j]) 832 { 833 if ((j + 1) < num_extra) 834 memmove(&extra_widgets[j], &extra_widgets[j + 1], 835 (num_extra - j) * sizeof(Widget)); 836 --num_extra; 837 } 838 839 if (old_num_extra != num_extra) 840 *children = (Widget *)XtRealloc((char *)*children, sizeof(Widget) 841 * (num_children + num_extra)); 842 843 if (num_extra) 844 memcpy(&(*children)[num_children], extra_widgets, 845 sizeof(Widget) * num_extra); 846 } 847 if (extra_widgets) 848 XtFree((char *)extra_widgets); 849 if (num_children + num_extra == 0) 850 { 851 XtFree((char *)*children); 852 *children = NULL; 853 } 854 855 return (num_children + num_extra); 856 } 857 858 /* 859 * Function: 860 * IsChild 861 * 862 * parameters: 863 * top - top of the tree 864 * parent - parent widget 865 * child - child widget 866 * 867 * Description: 868 * Check to see of child is a child of parent 869 */ 870 static Bool 871 IsChild(Widget top, Widget parent, Widget child) 872 { 873 int i, num_children; 874 Widget *children; 875 876 if (parent == NULL) 877 return (top == child); 878 879 num_children = FindChildren(parent, &children, True, True, True); 880 881 for (i = 0; i < num_children; i++) 882 if (children[i] == child) 883 { 884 XtFree((char *)children); 885 return (True); 886 } 887 888 XtFree((char *)children); 889 return (False); 890 } 891 892 /* 893 * Function: 894 * VerifyWidget 895 * 896 * Parameters: 897 * w - any widget in the tree 898 * info - info about the widget to verify 899 * 900 * Description: 901 * Makes sure all the widgets still exist 902 */ 903 static _Xconst char * 904 VerifyWidget(Widget w, WidgetInfo *info) 905 { 906 Widget top; 907 register int count; 908 register Widget parent; 909 CARD64 *child; 910 911 for (top = w; XtParent(top) != NULL; top = XtParent(top)) 912 ; 913 914 parent = NULL; 915 child = info->ids; 916 count = 0; 917 918 while (True) 919 { 920 if (!IsChild(top, parent, ID2WIDGET(*child))) 921 return ("This widget no longer exists in the client."); 922 923 if (++count == info->num_widgets) 924 break; 925 926 parent = ID2WIDGET(*child++); 927 } 928 929 info->real_widget = ID2WIDGET(*child); 930 return (NULL); 931 } 932 933 /************************************************************ 934 * Code to Perform SetValues operations 935 ************************************************************/ 936 /* 937 * Function: 938 * DoSetValues 939 * 940 * Parameters: 941 * w - a widget in the tree 942 * event - event that caused this action 943 * stream - protocol stream to add 944 * 945 * Description: 946 * Performs the setvalues requested 947 * 948 * Returns: 949 * NULL 950 */ 951 static _Xconst char * 952 DoSetValues(Widget w, EditresEvent *event, ProtocolStream *stream) 953 { 954 _Xconst char *str; 955 register unsigned i; 956 unsigned short count = 0; 957 SetValuesEvent *sv_event = (SetValuesEvent *)event; 958 959 _XEditResPut16(stream, count); /* insert 0, will be overwritten later */ 960 961 for (i = 0; i < sv_event->num_entries; i++) 962 { 963 if ((str = VerifyWidget(w, &sv_event->widgets[i])) != NULL) 964 { 965 _XEditResPutWidgetInfo(stream, &sv_event->widgets[i]); 966 _XEditResPutString8(stream, str); 967 count++; 968 } 969 else 970 ExecuteSetValues(sv_event->widgets[i].real_widget, 971 sv_event, sv_event->widgets + i, stream, &count); 972 } 973 974 /* 975 * Overwrite the first 2 bytes with the real count. 976 */ 977 *(stream->top) = count >> XER_NBBY; 978 *(stream->top + 1) = count; 979 980 return (NULL); 981 } 982 983 /* 984 * Function: 985 * HandleToolkitErrors 986 * 987 * Parameters: 988 * name - name of the error 989 * type - type of the error 990 * class - class of the error 991 * msg - the default message 992 * params - the extra parameters for this message 993 * num_params - "" 994 * 995 * Description: Handles X Toolkit Errors. 996 */ 997 /* ARGSUSED */ 998 static void 999 HandleToolkitErrors(String name, String type, String class, String msg, 1000 String *params, Cardinal *num_params) 1001 { 1002 SVErrorInfo *info = &globals.error_info; 1003 char buf[BUFSIZ]; 1004 1005 if (streq(name, "unknownType")) 1006 XmuSnprintf(buf, sizeof(buf), 1007 "The `%s' resource is not used by this widget.", 1008 info->event->name); 1009 else if (streq(name, "noColormap")) 1010 XmuSnprintf(buf, sizeof(buf), msg, params[0]); 1011 else if (streq(name, "conversionFailed") || streq(name, "conversionError")) 1012 { 1013 if (streq((String)info->event->value, XtRString)) 1014 XmuSnprintf(buf, sizeof(buf), 1015 "Could not convert the string '%s' for the `%s' " 1016 "resource.", (String)info->event->value, 1017 info->event->name); 1018 else 1019 XmuSnprintf(buf, sizeof(buf), 1020 "Could not convert the `%s' resource.", 1021 info->event->name); 1022 } 1023 else 1024 XmuSnprintf(buf, sizeof(buf), 1025 "Name: %s, Type: %s, Class: %s, Msg: %s", 1026 name, type, class, msg); 1027 1028 /* 1029 * Insert this info into the protocol stream, and update the count 1030 */ 1031 (*(info->count))++; 1032 _XEditResPutWidgetInfo(info->stream, info->entry); 1033 _XEditResPutString8(info->stream, buf); 1034 } 1035 1036 /* 1037 * Function: 1038 * ExecuteSetValues 1039 * 1040 * Parameters: 1041 * w - widget to perform the set_values on 1042 * sv_event - set values event 1043 * sv_info - set_value info 1044 *. 1045 * Description: 1046 * Performs a setvalues for a given command 1047 */ 1048 static void 1049 ExecuteSetValues(Widget w, SetValuesEvent *sv_event, WidgetInfo *entry, 1050 ProtocolStream *stream, unsigned short *count) 1051 { 1052 XtErrorMsgHandler old; 1053 SVErrorInfo *info = &globals.error_info; 1054 1055 info->event = sv_event; /* No data can be passed to */ 1056 info->stream = stream; /* an error handler, so we */ 1057 info->count = count; /* have to use a global */ 1058 info->entry = entry; 1059 1060 old = XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w), 1061 HandleToolkitErrors); 1062 1063 XtVaSetValues(w, XtVaTypedArg, 1064 sv_event->name, sv_event->res_type, 1065 sv_event->value, sv_event->value_len, 1066 NULL); 1067 1068 (void)XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w), old); 1069 } 1070 1071 /************************************************************ 1072 * Code for Creating and dumping widget tree. 1073 ************************************************************/ 1074 /* Function: 1075 * DumpWidgets 1076 * 1077 * Parameters: 1078 * w - a widget in the tree 1079 * event - event that caused this action 1080 * stream - protocol stream to add 1081 * 1082 * Description: 1083 * Given a widget it builds a protocol packet containing the entire 1084 * widget hierarchy. 1085 * 1086 * Returns: 1087 * NULL 1088 */ 1089 #define TOOLKIT_TYPE ("Xt") 1090 /*ARGSUSED*/ 1091 static _Xconst char * 1092 DumpWidgets(Widget w, EditresEvent *event, ProtocolStream *stream) 1093 { 1094 unsigned short count = 0; 1095 1096 /* Find Tree's root */ 1097 for (; XtParent(w) != NULL; w = XtParent(w)) 1098 ; 1099 1100 /* 1101 * hold space for count, overwritten later 1102 */ 1103 _XEditResPut16(stream, (unsigned int)0); 1104 1105 DumpChildren(w, stream, &count); 1106 1107 /* 1108 * write out toolkit type 1109 */ 1110 _XEditResPutString8(stream, TOOLKIT_TYPE); 1111 1112 /* 1113 * Overwrite the first 2 bytes with the real count 1114 */ 1115 *(stream->top) = count >> XER_NBBY; 1116 *(stream->top + 1) = count; 1117 1118 return (NULL); 1119 } 1120 1121 /* 1122 * Function: 1123 * DumpChildren 1124 * 1125 * Parameters: 1126 * w - widget to dump 1127 * stream - stream to dump to 1128 * count - number of dumps we have performed 1129 * 1130 * Description: 1131 * Adds a child's name to the list. 1132 */ 1133 /* This is a trick/kludge. To make shared libraries happier (linking 1134 * against Xmu but not linking against Xt, and apparently even work 1135 * as we desire on SVR4, we need to avoid an explicit data reference 1136 * to applicationShellWidgetClass. XtIsTopLevelShell is known 1137 * (implementation dependent assumption!) to use a bit flag. So we 1138 * go that far. Then, we test whether it is an applicationShellWidget 1139 * class by looking for an explicit class name. Seems pretty safe. 1140 */ 1141 static Bool 1142 isApplicationShell(Widget w) 1143 { 1144 register WidgetClass c; 1145 1146 if (!XtIsTopLevelShell(w)) 1147 return (False); 1148 for (c = XtClass(w); c; c = c->core_class.superclass) 1149 if (strcmp(c->core_class.class_name, "ApplicationShell") == 0) 1150 return (True); 1151 1152 return (False); 1153 } 1154 1155 static void 1156 DumpChildren(Widget w, ProtocolStream *stream, unsigned short *count) 1157 { 1158 int i, num_children; 1159 Widget *children; 1160 CARD64 window; 1161 String c_class; 1162 1163 (*count)++; 1164 1165 InsertWidget(stream, w); /* Insert the widget into the stream */ 1166 1167 _XEditResPutString8(stream, XtName(w)); /* Insert name */ 1168 1169 if (isApplicationShell(w)) 1170 c_class = ((ApplicationShellWidget)w)->application.class; 1171 else 1172 c_class = XtClass(w)->core_class.class_name; 1173 1174 _XEditResPutString8(stream, c_class); /* Insert class */ 1175 1176 if (XtIsWidget(w)) 1177 if (XtIsRealized(w)) 1178 window = XtWindow(w); 1179 else 1180 window = EDITRES_IS_UNREALIZED; 1181 else 1182 window = EDITRES_IS_OBJECT; 1183 1184 _XEditResPut64(stream, window); /* Insert window id */ 1185 1186 /* 1187 * Find children and recurse 1188 */ 1189 num_children = FindChildren(w, &children, True, True, True); 1190 for (i = 0; i < num_children; i++) 1191 DumpChildren(children[i], stream, count); 1192 1193 XtFree((char *)children); 1194 } 1195 1196 /************************************************************ 1197 * Code for getting the geometry of widgets 1198 ************************************************************/ 1199 /* 1200 * Function: 1201 * DoGetGeometry 1202 * 1203 * Parameters: 1204 * w - widget in the tree 1205 * event - event that caused this action 1206 * stream - protocol stream to add 1207 * 1208 * Description: 1209 * Retrieves the Geometry of each specified widget. 1210 * 1211 * Returns: 1212 * NULL 1213 */ 1214 static _Xconst char * 1215 DoGetGeometry(Widget w, EditresEvent *event, ProtocolStream *stream) 1216 { 1217 unsigned i; 1218 _Xconst char *str; 1219 GetGeomEvent *geom_event = (GetGeomEvent *)event; 1220 1221 _XEditResPut16(stream, geom_event->num_entries); 1222 1223 for (i = 0; i < geom_event->num_entries; i++) 1224 { 1225 /* 1226 * Send out the widget id 1227 */ 1228 _XEditResPutWidgetInfo(stream, &geom_event->widgets[i]); 1229 1230 if ((str = VerifyWidget(w, &geom_event->widgets[i])) != NULL) 1231 { 1232 _XEditResPutBool(stream, True); /* an error occurred */ 1233 _XEditResPutString8(stream, str); /* set message */ 1234 } 1235 else 1236 ExecuteGetGeometry(geom_event->widgets[i].real_widget, stream); 1237 } 1238 1239 return (NULL); 1240 } 1241 1242 /* 1243 * Function: 1244 * ExecuteGetGeometry 1245 * 1246 * Parameters: 1247 * w - widget to get geometry 1248 * stream - stream to append to 1249 * 1250 * Description: 1251 * Gets the geometry for each widget specified. 1252 * 1253 * Returns: 1254 * True if no error occurred. 1255 */ 1256 static void 1257 ExecuteGetGeometry(Widget w, ProtocolStream *stream) 1258 { 1259 int i; 1260 Boolean mapped_when_man; 1261 Dimension width, height, border_width; 1262 Arg args[8]; 1263 Cardinal num_args = 0; 1264 Position x, y; 1265 1266 if (!XtIsRectObj(w) || (XtIsWidget(w) && !XtIsRealized(w))) 1267 { 1268 _XEditResPutBool(stream, False); /* no error */ 1269 _XEditResPutBool(stream, False); /* not visible */ 1270 for (i = 0; i < 5; i++) /* fill in extra space with 0's */ 1271 _XEditResPut16(stream, 0); 1272 return; 1273 } 1274 1275 XtSetArg(args[num_args], XtNwidth, &width); num_args++; 1276 XtSetArg(args[num_args], XtNheight, &height); num_args++; 1277 XtSetArg(args[num_args], XtNborderWidth, &border_width); num_args++; 1278 XtSetArg(args[num_args], XtNmappedWhenManaged, &mapped_when_man); 1279 num_args++; 1280 XtGetValues(w, args, num_args); 1281 1282 if (!(XtIsManaged(w) && mapped_when_man) && XtIsWidget(w)) 1283 { 1284 XWindowAttributes attrs; 1285 1286 /* 1287 * The toolkit does not maintain mapping state, we have 1288 * to go to the server 1289 */ 1290 if (XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attrs) != 0) 1291 { 1292 if (attrs.map_state != IsViewable) 1293 { 1294 _XEditResPutBool(stream, False); /* no error */ 1295 _XEditResPutBool(stream, False); /* not visible */ 1296 for (i = 0; i < 5; i++) /* fill in extra space with 0's */ 1297 _XEditResPut16(stream, 0); 1298 return; 1299 } 1300 } 1301 else 1302 { 1303 _XEditResPut8(stream, True); /* Error occurred. */ 1304 _XEditResPutString8(stream, "XGetWindowAttributes failed."); 1305 return; 1306 } 1307 } 1308 1309 XtTranslateCoords(w, -((int) border_width), -((int) border_width), &x, &y); 1310 1311 _XEditResPutBool(stream, False); /* no error */ 1312 _XEditResPutBool(stream, True); /* Visible */ 1313 _XEditResPut16(stream, x); 1314 _XEditResPut16(stream, y); 1315 _XEditResPut16(stream, width); 1316 _XEditResPut16(stream, height); 1317 _XEditResPut16(stream, border_width); 1318 } 1319 1320 /************************************************************ 1321 * Code for executing FindChild 1322 ************************************************************/ 1323 /* 1324 * Function: 1325 * PositionInChild 1326 * 1327 * Parameters: 1328 * child - child widget to check 1329 * x - location of point to check in the parent's coord space 1330 * y - "" 1331 * 1332 * Description: 1333 * Returns true if this location is in the child. 1334 */ 1335 static Bool 1336 PositionInChild(Widget child, int x, int y) 1337 { 1338 Arg args[6]; 1339 Cardinal num; 1340 Dimension width, height, border_width; 1341 Position child_x, child_y; 1342 Boolean mapped_when_managed; 1343 1344 if (!XtIsRectObj(child)) /* we must at least be a rect obj */ 1345 return (False); 1346 1347 num = 0; 1348 XtSetArg(args[num], XtNmappedWhenManaged, &mapped_when_managed); num++; 1349 XtSetArg(args[num], XtNwidth, &width); num++; 1350 XtSetArg(args[num], XtNheight, &height); num++; 1351 XtSetArg(args[num], XtNx, &child_x); num++; 1352 XtSetArg(args[num], XtNy, &child_y); num++; 1353 XtSetArg(args[num], XtNborderWidth, &border_width); num++; 1354 XtGetValues(child, args, num); 1355 1356 /* 1357 * The only way we will know of the widget is mapped is to see if 1358 * mapped when managed is True and this is a managed child. Otherwise 1359 * we will have to ask the server if this window is mapped 1360 */ 1361 if (XtIsWidget(child) && !(mapped_when_managed && XtIsManaged(child))) 1362 { 1363 XWindowAttributes attrs; 1364 1365 if (XGetWindowAttributes(XtDisplay(child), XtWindow(child), &attrs) 1366 && attrs.map_state != IsViewable) 1367 return (False); 1368 } 1369 1370 return ((x >= child_x) 1371 && (x <= (child_x + (Position)width + 2 * (Position)border_width)) 1372 && (y >= child_y) 1373 && (y <= (child_y + (Position)height + 2 * (Position)border_width))); 1374 } 1375 1376 /* 1377 * Function: 1378 * _FindChild 1379 * 1380 * Parameters: 1381 * parent - widget that is known to contain the point specified 1382 * x - point in coordinates relative to the widget specified 1383 * y - "" 1384 * 1385 * Description: 1386 * Finds the child that actually contains the point shown. 1387 */ 1388 static Widget 1389 _FindChild(Widget parent, int x, int y) 1390 { 1391 Widget *children; 1392 int i = FindChildren(parent, &children, True, False, True); 1393 1394 while (i > 0) 1395 { 1396 i--; 1397 1398 if (PositionInChild(children[i], x, y)) 1399 { 1400 Widget child = children[i]; 1401 1402 XtFree((char *)children); 1403 return (_FindChild(child, x - child->core.x, y - child->core.y)); 1404 } 1405 } 1406 1407 XtFree((char *)children); 1408 1409 return (parent); 1410 } 1411 1412 /* 1413 * Function: 1414 * DoFindChild 1415 * 1416 * Parameters: 1417 * w - widget in the tree 1418 * event - event that caused this action 1419 * stream - protocol stream to add 1420 * Description: 1421 * Finds the child that contains the location specified. 1422 * 1423 * Returns: 1424 * An allocated error message if something went horribly wrong and 1425 * no set values were performed, else NULL. 1426 */ 1427 static _Xconst char * 1428 DoFindChild(Widget w, EditresEvent *event, ProtocolStream *stream) 1429 { 1430 _Xconst char *str; 1431 Widget parent, child; 1432 Position parent_x, parent_y; 1433 FindChildEvent *find_event = (FindChildEvent *)event; 1434 1435 if ((str = VerifyWidget(w, find_event->widgets)) != NULL) 1436 return (str); 1437 1438 parent = find_event->widgets->real_widget; 1439 1440 XtTranslateCoords(parent, (Position) 0, (Position) 0, 1441 &parent_x, &parent_y); 1442 1443 child = _FindChild(parent, find_event->x - (int) parent_x, 1444 find_event->y - (int) parent_y); 1445 1446 InsertWidget(stream, child); 1447 1448 return (NULL); 1449 } 1450 1451 /************************************************************ 1452 * Procedures for performing GetResources 1453 ************************************************************/ 1454 /* 1455 * Function: 1456 * DoGetResources 1457 * 1458 * Parameters: 1459 * w - widget in the tree 1460 * event - event that caused this action 1461 * stream - protocol stream to add 1462 * 1463 * Description: 1464 * Gets the Resources associated with the widgets passed. 1465 * 1466 * Returns: 1467 * NULL 1468 */ 1469 static _Xconst char * 1470 DoGetResources(Widget w, EditresEvent *event, ProtocolStream *stream) 1471 { 1472 unsigned int i; 1473 _Xconst char *str; 1474 GetResEvent *res_event = (GetResEvent *)event; 1475 1476 _XEditResPut16(stream, res_event->num_entries); /* number of replies */ 1477 1478 for (i = 0; i < res_event->num_entries; i++) 1479 { 1480 /* 1481 * Send out the widget id 1482 */ 1483 _XEditResPutWidgetInfo(stream, &res_event->widgets[i]); 1484 if ((str = VerifyWidget(w, &res_event->widgets[i])) != NULL) 1485 { 1486 _XEditResPutBool(stream, True); /* an error occurred */ 1487 _XEditResPutString8(stream, str); /* set message */ 1488 } 1489 else 1490 { 1491 _XEditResPutBool(stream, False); /* no error occurred */ 1492 ExecuteGetResources(res_event->widgets[i].real_widget, stream); 1493 } 1494 } 1495 1496 return (NULL); 1497 } 1498 1499 /* Function: 1500 * ExecuteGetResources 1501 * 1502 * Parameters: 1503 * w - widget to get resources on 1504 * stream - protocol stream 1505 * 1506 * Description: 1507 * Gets the resources for any individual widget 1508 */ 1509 static void 1510 ExecuteGetResources(Widget w, ProtocolStream *stream) 1511 { 1512 XtResourceList norm_list, cons_list; 1513 Cardinal num_norm, num_cons; 1514 register Cardinal i; 1515 1516 /* 1517 * Get Normal Resources 1518 */ 1519 XtGetResourceList(XtClass(w), &norm_list, &num_norm); 1520 1521 if (XtParent(w) != NULL) 1522 XtGetConstraintResourceList(XtClass(XtParent(w)), &cons_list,&num_cons); 1523 else 1524 num_cons = 0; 1525 1526 _XEditResPut16(stream, num_norm + num_cons); /* how many resources */ 1527 1528 /* 1529 * Insert all the normal resources 1530 */ 1531 for (i = 0; i < num_norm; i++) 1532 { 1533 _XEditResPutResourceType(stream, NormalResource); 1534 _XEditResPutString8(stream, norm_list[i].resource_name); 1535 _XEditResPutString8(stream, norm_list[i].resource_class); 1536 _XEditResPutString8(stream, norm_list[i].resource_type); 1537 } 1538 XtFree((char *)norm_list); 1539 1540 /* 1541 * Insert all the constraint resources 1542 */ 1543 if (num_cons > 0) 1544 { 1545 for (i = 0; i < num_cons; i++) 1546 { 1547 _XEditResPutResourceType(stream, ConstraintResource); 1548 _XEditResPutString8(stream, cons_list[i].resource_name); 1549 _XEditResPutString8(stream, cons_list[i].resource_class); 1550 _XEditResPutString8(stream, cons_list[i].resource_type); 1551 } 1552 XtFree((char *)cons_list); 1553 } 1554 } 1555 1556 /* 1557 * Function: 1558 * DumpValues 1559 * 1560 * Parameters: 1561 * event - event that caused this action 1562 * stream - protocol stream to add 1563 * 1564 * Description: 1565 * Returns resource values to the resource editor. 1566 * 1567 * Returns: 1568 * NULL 1569 */ 1570 /*ARGSUSED*/ 1571 static _Xconst char * 1572 DumpValues(Widget w, EditresEvent* event, ProtocolStream* stream) 1573 { 1574 _Xconst char *str; 1575 Arg warg[1]; 1576 _Xconst _XtString res_value = NULL; 1577 GetValuesEvent *gv_event = (GetValuesEvent *)event; 1578 1579 /* put the count in the stream */ 1580 _XEditResPut16(stream, (unsigned int)1); 1581 1582 /* 1583 * Get the resource of the widget asked for by the 1584 * resource editor and insert it into the stream 1585 */ 1586 XtSetArg(warg[0], gv_event->name, &res_value); 1587 1588 if ((str = VerifyWidget(w, &gv_event->widgets[0])) != NULL) 1589 _XEditResPutString8(stream, str); 1590 else 1591 { 1592 _XEditresGetStringValues(gv_event->widgets[0].real_widget, warg, 1); 1593 if (!res_value) 1594 res_value = "NoValue"; 1595 _XEditResPutString8(stream, res_value); 1596 } 1597 1598 return (NULL); 1599 } 1600 1601 /************************************************************ 1602 * Code for inserting values into the protocol stream 1603 ************************************************************/ 1604 /* 1605 * Function: 1606 * InsertWidget 1607 * 1608 * Parameters: 1609 * stream - protocol stream 1610 * w - widget to insert 1611 * 1612 * Description: 1613 * Inserts the full parent hierarchy of this widget into the protocol 1614 * stream as a widget list. 1615 */ 1616 static void 1617 InsertWidget(ProtocolStream *stream, Widget w) 1618 { 1619 Widget temp; 1620 CARD64 *widget_list; 1621 register int i, num_widgets; 1622 1623 for (temp = w, i = 0; temp != NULL; temp = XtParent(temp), i++) 1624 ; 1625 1626 num_widgets = i; 1627 widget_list = (CARD64 *)XtMalloc(sizeof(*widget_list) * num_widgets); 1628 1629 /* 1630 * Put the widgets into the list 1631 * make sure that they are inserted in the list from parent -> child 1632 */ 1633 for (i--, temp = w; temp != NULL; temp = XtParent(temp), i--) 1634 widget_list[i] = (CARD64)(uintptr_t)temp; 1635 1636 _XEditResPut16(stream, num_widgets); /* insert number of widgets */ 1637 for (i = 0; i < num_widgets; i++) /* insert Widgets themselves */ 1638 _XEditResPut64(stream, widget_list[i]); 1639 1640 XtFree((char *)widget_list); 1641 } 1642 1643 /************************************************************ 1644 * All of the following routines are public 1645 ************************************************************/ 1646 /* 1647 * Function: 1648 * _XEditResPutString8 1649 * 1650 * Parameters: 1651 * stream - stream to insert string into 1652 * str - string to insert 1653 * 1654 * Description: 1655 * Inserts a string into the protocol stream. 1656 */ 1657 void 1658 _XEditResPutString8(ProtocolStream *stream, _Xconst char *str) 1659 { 1660 int i, len = strlen(str); 1661 1662 _XEditResPut16(stream, len); 1663 for (i = 0; i < len; i++, str++) 1664 _XEditResPut8(stream, *str); 1665 } 1666 1667 /* 1668 * Function: 1669 * _XEditResPut8 1670 * 1671 * Parameters: 1672 * stream - stream to insert string into 1673 * value - value to insert 1674 * 1675 * Description: 1676 * Inserts an 8 bit integer into the protocol stream. 1677 */ 1678 void 1679 _XEditResPut8(ProtocolStream *stream, unsigned int value) 1680 { 1681 unsigned char temp; 1682 1683 if (stream->size >= stream->alloc) 1684 { 1685 stream->alloc += 100; 1686 stream->real_top = (unsigned char *) 1687 XtRealloc((char *)stream->real_top, stream->alloc + HEADER_SIZE); 1688 stream->top = stream->real_top + HEADER_SIZE; 1689 stream->current = stream->top + stream->size; 1690 } 1691 1692 temp = (unsigned char) (value & BYTE_MASK); 1693 *((stream->current)++) = temp; 1694 (stream->size)++; 1695 } 1696 1697 /* 1698 * Function: 1699 * _XEditResPut16 1700 * 1701 * Arguments: 1702 * stream - stream to insert string into 1703 * value - value to insert 1704 * 1705 * Description: 1706 * Inserts a 16 bit integer into the protocol stream. 1707 */ 1708 void 1709 _XEditResPut16(ProtocolStream *stream, unsigned int value) 1710 { 1711 _XEditResPut8(stream, (value >> XER_NBBY) & BYTE_MASK); 1712 _XEditResPut8(stream, value & BYTE_MASK); 1713 } 1714 1715 /* 1716 * Function: 1717 * _XEditResPut32 1718 * 1719 * Arguments: 1720 * stream - stream to insert string into 1721 * value - value to insert 1722 * 1723 * Description: 1724 * Inserts a 32 bit integer into the protocol stream. 1725 */ 1726 void 1727 _XEditResPut32(ProtocolStream *stream, unsigned long value) 1728 { 1729 int i; 1730 1731 for (i = 3; i >= 0; i--) 1732 _XEditResPut8(stream, (value >> (XER_NBBY * i)) & BYTE_MASK); 1733 } 1734 1735 /* 1736 * Function: 1737 * _XEditResPut64 1738 * 1739 * Arguments: 1740 * stream - stream to insert string into 1741 * value - value to insert 1742 * 1743 * Description: 1744 * Inserts a 64 bit integer into the protocol stream. 1745 */ 1746 void 1747 _XEditResPut64(ProtocolStream *stream, CARD64 value) 1748 { 1749 int i; 1750 1751 for (i = 7; i >= 0; i--) 1752 _XEditResPut8(stream, (value >> (XER_NBBY * i)) & BYTE_MASK); 1753 } 1754 1755 /* 1756 * Function: 1757 * _XEditResPutWidgetInfo 1758 * 1759 * Parameters: 1760 * stream - stream to insert widget info into 1761 * info - info to insert 1762 * 1763 * Description: 1764 * Inserts the widget info into the protocol stream. 1765 */ 1766 void 1767 _XEditResPutWidgetInfo(ProtocolStream *stream, WidgetInfo *info) 1768 { 1769 unsigned int i; 1770 1771 _XEditResPut16(stream, info->num_widgets); 1772 for (i = 0; i < info->num_widgets; i++) 1773 _XEditResPut64(stream, info->ids[i]); 1774 } 1775 1776 /************************************************************ 1777 * Code for retrieving values from the protocol stream 1778 ************************************************************/ 1779 /* 1780 * Function: 1781 * _XEditResResetStream 1782 * 1783 * Parameters: 1784 * stream - stream to reset 1785 * 1786 * Description: 1787 * Resets the protocol stream. 1788 */ 1789 void 1790 _XEditResResetStream(ProtocolStream *stream) 1791 { 1792 stream->current = stream->top; 1793 stream->size = 0; 1794 if (stream->real_top == NULL) 1795 { 1796 stream->real_top = (unsigned char *) 1797 XtRealloc((char *)stream->real_top, stream->alloc + HEADER_SIZE); 1798 stream->top = stream->real_top + HEADER_SIZE; 1799 stream->current = stream->top + stream->size; 1800 } 1801 } 1802 1803 /* 1804 * Function: 1805 * _XEditResFreeStream 1806 * 1807 * Parameters: 1808 * stream - stream to free 1809 * 1810 * Description: 1811 * Free the memory allocated to the stream. 1812 */ 1813 void 1814 _XEditResFreeStream(ProtocolStream *stream) 1815 { 1816 if (!stream->real_top) 1817 return; 1818 1819 XtFree((XtPointer)stream->real_top); 1820 stream->real_top = NULL; 1821 } 1822 1823 /* 1824 * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 1825 * 1826 * The only modified field if the "current" field 1827 * 1828 * The only fields that must be set correctly are the "current", "top" 1829 * and "size" fields. 1830 */ 1831 /* 1832 * Function: 1833 * _XEditResGet8 1834 * 1835 * Parameters: 1836 * stream - protocol stream 1837 * value - a pointer to value to return 1838 * 1839 * Description: 1840 * Retrieves an unsigned 8 bit value from the protocol stream. 1841 * 1842 * Returns: 1843 * True if successful 1844 */ 1845 Bool 1846 _XEditResGet8(ProtocolStream *stream, unsigned char *value) 1847 { 1848 if (stream->size < (unsigned long)(stream->current - stream->top)) 1849 return (False); 1850 1851 *value = *((stream->current)++); 1852 return (True); 1853 } 1854 1855 /* 1856 * Function: 1857 * _XEditResGet16 1858 * 1859 * Parameters: 1860 * stream - protocol stream 1861 * value - pointer to return value 1862 * 1863 * Description: 1864 * Retrieves an unsigned 16 bit value from the protocol stream. 1865 * 1866 * Returns: 1867 * True if successful 1868 */ 1869 Bool 1870 _XEditResGet16(ProtocolStream *stream, unsigned short *value) 1871 { 1872 unsigned char temp1, temp2; 1873 1874 if (!(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2))) 1875 return (False); 1876 1877 *value = ((unsigned short)temp1 << XER_NBBY) + (unsigned short)temp2; 1878 return (True); 1879 } 1880 1881 /* 1882 * Function: 1883 * _XEditResGetSigned16 1884 * 1885 * Parameters: 1886 * stream - protocol stream 1887 * value - pointer to return value 1888 * 1889 * Description: 1890 * Retrieves an signed 16 bit value from the protocol stream. 1891 * 1892 * Returns: 1893 * True if successful 1894 */ 1895 Bool 1896 _XEditResGetSigned16(ProtocolStream *stream, short *value) 1897 { 1898 unsigned char temp1, temp2; 1899 1900 if (!(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2))) 1901 return (False); 1902 1903 if (temp1 & (1 << (XER_NBBY - 1))) /* If the sign bit is active */ 1904 { 1905 *value = -1; /* store all 1's */ 1906 *value &= (temp1 << XER_NBBY); /* Now and in the MSB */ 1907 *value &= temp2; /* and LSB */ 1908 } 1909 else 1910 *value = ((unsigned short)temp1 << XER_NBBY) + (unsigned short)temp2; 1911 1912 return (True); 1913 } 1914 1915 /* 1916 * Function: 1917 * _XEditResGet32 1918 * 1919 * Parameters: 1920 * stream - protocol stream 1921 * value - pointer to return value 1922 * 1923 * Description: 1924 * Retrieves an unsigned 32 bit value from the protocol stream. 1925 * 1926 * Returns: 1927 * True if successful 1928 */ 1929 Bool 1930 _XEditResGet32(ProtocolStream *stream, unsigned long *value) 1931 { 1932 unsigned short temp1, temp2; 1933 1934 if (!(_XEditResGet16(stream, &temp1) && _XEditResGet16(stream, &temp2))) 1935 return (False); 1936 1937 *value = ((unsigned long)temp1 << (XER_NBBY * 2)) + (unsigned long)temp2; 1938 return (True); 1939 } 1940 1941 /* 1942 * Function: 1943 * _XEditResGet64 1944 * 1945 * Parameters: 1946 * stream - protocol stream 1947 * value - pointer to return value 1948 * 1949 * Description: 1950 * Retrieves an unsigned 64 bit value from the protocol stream. 1951 * 1952 * Returns: 1953 * True if successful 1954 */ 1955 Bool 1956 _XEditResGet64(ProtocolStream *stream, CARD64 *value) 1957 { 1958 unsigned long temp1, temp2; 1959 1960 if (!(_XEditResGet32(stream, &temp1) && _XEditResGet32(stream, &temp2))) 1961 return (False); 1962 1963 *value = ((CARD64)temp1 << (XER_NBBY * 4)) + temp2; 1964 return (True); 1965 } 1966 1967 /* Function: 1968 * _XEditResGetString8 1969 * 1970 * Parameters: 1971 * stream - protocol stream 1972 * str - string to retrieve 1973 * 1974 * Description: 1975 * Retrieves an 8 bit string value from the protocol stream. 1976 * 1977 * Returns: 1978 * True if retrieval was successful 1979 */ 1980 Bool 1981 _XEditResGetString8(ProtocolStream *stream, char **str) 1982 { 1983 unsigned short len; 1984 register unsigned i; 1985 1986 if (!_XEditResGet16(stream, &len)) 1987 return (False); 1988 1989 *str = XtMalloc(sizeof(char) * (len + 1)); 1990 1991 for (i = 0; i < len; i++) 1992 { 1993 if (!_XEditResGet8(stream, (unsigned char *)*str + i)) 1994 { 1995 XtFree(*str); 1996 *str = NULL; 1997 return (False); 1998 } 1999 } 2000 (*str)[i] = '\0'; 2001 2002 return (True); 2003 } 2004 2005 /* 2006 * Function: 2007 * _XEditResGetWidgetInfo 2008 * 2009 * Parameters: 2010 * stream - protocol stream 2011 * info - widget info struct to store into 2012 * 2013 * Description: 2014 * Retrieves the list of widgets that follow and stores them in the 2015 * widget info structure provided. 2016 * 2017 * Returns: 2018 * True if retrieval was successful 2019 */ 2020 Bool 2021 _XEditResGetWidgetInfo(ProtocolStream *stream, WidgetInfo *info) 2022 { 2023 unsigned int i; 2024 2025 if (!_XEditResGet16(stream, &info->num_widgets)) 2026 return (False); 2027 2028 info->ids = (CARD64 *)XtMalloc(sizeof(*info->ids) * info->num_widgets); 2029 2030 for (i = 0; i < info->num_widgets; i++) 2031 { 2032 if (!_XEditResGet64(stream, info->ids + i)) 2033 { 2034 XtFree((char *)info->ids); 2035 info->ids = NULL; 2036 return (False); 2037 } 2038 } 2039 return (True); 2040 } 2041 2042 /************************************************************ 2043 * Code for Loading the EditresBlock resource 2044 ************************************************************/ 2045 /* 2046 * Function: 2047 * CvtStringToBlock 2048 * 2049 * Parameters: 2050 * dpy - display 2051 * args - unused 2052 * num_args - unused 2053 * from_val - value to convert 2054 * to_val - where to store 2055 * converter_data - unused 2056 * 2057 * Description: 2058 * Converts a string to an editres block value. 2059 * 2060 * Returns: 2061 * True if conversion was successful 2062 */ 2063 /*ARGSUSED*/ 2064 static Boolean 2065 CvtStringToBlock(Display *dpy, XrmValue *args, Cardinal *num_args, 2066 XrmValue *from_val, XrmValue *to_val, 2067 XtPointer *converter_data) 2068 { 2069 char ptr[16]; 2070 static EditresBlock block; 2071 2072 XmuNCopyISOLatin1Lowered(ptr, from_val->addr, sizeof(ptr)); 2073 2074 if (streq(ptr, "none")) 2075 block = BlockNone; 2076 else if (streq(ptr, "setvalues")) 2077 block = BlockSetValues; 2078 else if (streq(ptr, "all")) 2079 block = BlockAll; 2080 else 2081 { 2082 Cardinal num_params = 1; 2083 String params[1]; 2084 2085 params[0] = from_val->addr; 2086 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2087 "CvtStringToBlock", "unknownValue", "EditresError", 2088 "Could not convert string \"%s\" to EditresBlock.", 2089 params, &num_params); 2090 return FALSE; 2091 } 2092 2093 if (to_val->addr != NULL) 2094 { 2095 if (to_val->size < sizeof(EditresBlock)) 2096 { 2097 to_val->size = sizeof(EditresBlock); 2098 return FALSE; 2099 } 2100 *(EditresBlock *)(to_val->addr) = block; 2101 } 2102 else 2103 to_val->addr = (XtPointer)block; 2104 2105 to_val->size = sizeof(EditresBlock); 2106 return TRUE; 2107 } 2108 2109 #define XtREditresBlock "EditresBlock" 2110 /* 2111 * Function: 2112 * LoadResources 2113 * 2114 * Parameters: 2115 * w - any widget in the tree 2116 * 2117 * Description: 2118 * Loads a global resource the determines of this application should 2119 * allow Editres requests. 2120 */ 2121 static void 2122 LoadResources(Widget w) 2123 { 2124 static XtResource resources[] = { 2125 {"editresBlock", "EditresBlock", XtREditresBlock, sizeof(EditresBlock), 2126 XtOffsetOf(Globals, block), XtRImmediate, (XtPointer)BlockNone} 2127 }; 2128 2129 for (; XtParent(w) != NULL; w = XtParent(w)) 2130 ; 2131 2132 XtAppSetTypeConverter(XtWidgetToApplicationContext(w), 2133 XtRString, XtREditresBlock, CvtStringToBlock, 2134 NULL, 0, XtCacheAll, NULL); 2135 2136 XtGetApplicationResources(w, (XtPointer)&globals, resources, 2137 XtNumber(resources), NULL, 0); 2138 } 2139 2140 /* 2141 * Function: 2142 * _XEditresGetStringValues 2143 * 2144 * Parameters: 2145 * w - widget 2146 * warg - where to store result 2147 * numargs - unused 2148 */ 2149 /*ARGSUSED*/ 2150 static void 2151 _XEditresGetStringValues(Widget w, Arg *warg, int numargs) 2152 { 2153 static char buffer[32]; 2154 XtResourceList res_list; 2155 Cardinal num_res; 2156 XtResource *res = NULL; 2157 long value; 2158 Cardinal i; 2159 const char *string = ""; 2160 Arg args[1]; 2161 XrmValue to, from; 2162 2163 /* 2164 * Look for the resource 2165 */ 2166 XtGetResourceList(XtClass(w), &res_list, &num_res); 2167 for (i = 0; i < num_res; i++) 2168 if (strcmp(res_list[i].resource_name, warg->name) == 0) 2169 { 2170 res = &res_list[i]; 2171 break; 2172 } 2173 2174 if (res == NULL && XtParent(w) != NULL) 2175 { 2176 XtFree((char *)res_list); 2177 XtGetConstraintResourceList(XtClass(XtParent(w)), &res_list, &num_res); 2178 for (i = 0; i < num_res; i++) 2179 if (strcmp(res_list[i].resource_name, warg->name) == 0) 2180 { 2181 res = &res_list[i]; 2182 break; 2183 } 2184 } 2185 2186 if (res == NULL) 2187 { 2188 /* Couldn't find resource */ 2189 2190 XtFree((char *)res_list); 2191 *(XtPointer *)warg->value = NULL; 2192 return; 2193 } 2194 2195 /* try to get the value in the proper size */ 2196 switch (res->resource_size) 2197 { 2198 #ifdef LONG64 2199 long v8; 2200 #endif 2201 int v4; 2202 short v2; 2203 char v1; 2204 2205 case 1: 2206 XtSetArg(args[0], res->resource_name, &v1); 2207 XtGetValues(w, args, 1); 2208 value = (int)v1; 2209 break; 2210 case 2: 2211 XtSetArg(args[0], res->resource_name, &v2); 2212 XtGetValues(w, args, 1); 2213 value = (int)v2; 2214 break; 2215 case 4: 2216 XtSetArg(args[0], res->resource_name, &v4); 2217 XtGetValues(w, args, 1); 2218 value = (int)v4; 2219 break; 2220 #ifdef LONG64 2221 case 8: 2222 XtSetArg(args[0], res->resource_name, &v8); 2223 XtGetValues(w, args, 1); 2224 value = (long)v8; 2225 break; 2226 #endif 2227 default: 2228 fprintf(stderr, "_XEditresGetStringValues: bad size %d\n", 2229 res->resource_size); 2230 string = "bad size"; 2231 *(char **)(warg->value) = (char *) string; 2232 XtFree((char *)res_list); 2233 return; 2234 } 2235 2236 /* 2237 * If the resource is already String, no conversion needed 2238 */ 2239 if (strcmp(XtRString, res->resource_type) == 0) 2240 { 2241 if (value == 0) 2242 string = "(null)"; 2243 else 2244 string = (char *)value; 2245 } 2246 else 2247 { 2248 from.size = res->resource_size; 2249 from.addr = (XPointer)&value; 2250 to.addr = NULL; 2251 to.size = 0; 2252 2253 if (XtConvertAndStore(w,res->resource_type, &from, XtRString, &to)) 2254 string = to.addr; 2255 else 2256 { 2257 string = buffer; 2258 /* 2259 * Conversion failed, fall back to representing it as integer 2260 */ 2261 switch (res->resource_size) 2262 { 2263 case sizeof(char): 2264 XmuSnprintf(buffer, sizeof(buffer), "%d", (int)(value & 0xff)); 2265 break; 2266 case sizeof(short): 2267 XmuSnprintf(buffer, sizeof(buffer), "%d", (int)(value & 0xffff)); 2268 break; 2269 case sizeof(int): 2270 XmuSnprintf(buffer, sizeof(buffer), "0x%08x", (int)value); 2271 break; 2272 #ifdef LONG64 2273 case sizeof(long): 2274 XmuSnprintf(buffer, sizeof(buffer), "0x%016lx", value); 2275 break; 2276 #endif 2277 } 2278 } 2279 } 2280 2281 if (string == NULL) 2282 string = ""; 2283 2284 *(char **)(warg->value) = (char *) string; 2285 XtFree((char *)res_list); 2286 } 2287