spec cleanup
[platform/upstream/libXmu.git] / src / EditresCom.c
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 - lenght 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 sucessful
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 automaticaly freeing the selection value */
596 }
597
598 /*
599  * Function:
600  *      SendFailure
601  *
602  * Paramters:
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  *      Retuns 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 heirarchy.
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     char *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 occured */
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 occured.
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 visable */
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 visable */
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 occured. */
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);     /* Visable */
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 replys */
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 occured */
1477             _XEditResPutString8(stream, str);   /* set message */
1478         }
1479         else
1480         {
1481             _XEditResPutBool(stream, False);    /* no error occured */
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  *      _XEditResGetg8
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 sucessful
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 sucessful
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 sucessful
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 sucessful
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 short)temp1 << (XER_NBBY * 2)) + (unsigned short)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  *      CvStringToBlock
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 sucessful
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     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) = 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) = string;
2212     XtFree((char *)res_list);
2213 }