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