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