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