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