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