EditresCom.c

Go to the documentation of this file.
00001 /* $Xorg: EditresCom.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
00002 
00003 /*
00004 
00005 Copyright 1989, 1998  The Open Group
00006 
00007 Permission to use, copy, modify, distribute, and sell this software and its
00008 documentation for any purpose is hereby granted without fee, provided that
00009 the above copyright notice appear in all copies and that both that
00010 copyright notice and this permission notice appear in supporting
00011 documentation.
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00019 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 Except as contained in this notice, the name of The Open Group shall not be
00024 used in advertising or otherwise to promote the sale, use or other dealings
00025 in this Software without prior written authorization from The Open Group.
00026 
00027 */
00028 /* $XFree86: xc/lib/Xmu/EditresCom.c,v 1.21 2003/10/24 15:44:05 tsi Exp $ */
00029 
00030 /*
00031  * Author:  Chris D. Peterson, Dave Sternlicht, MIT X Consortium
00032  */
00033 
00034 #include <X11/IntrinsicP.h>     /* To get into the composite and core widget
00035                                    structures. */
00036 #include <X11/ObjectP.h>        /* For XtIs<Classname> macros. */
00037 #include <X11/StringDefs.h>     /* for XtRString. */
00038 #include <X11/ShellP.h>         /* for Application Shell Widget class. */
00039 
00040 #include <X11/Xatom.h>
00041 #include <X11/Xos.h>            /* for strcpy declaration */
00042 #include <X11/Xfuncs.h>
00043 #include <X11/Xmu/EditresP.h>
00044 #include <X11/Xmd.h>
00045 #include <X11/Xmu/CharSet.h>
00046 #include <X11/Xmu/SysUtil.h>
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 
00051 #define _XEditResPutBool _XEditResPut8  
00052 #define _XEditResPutResourceType _XEditResPut8
00053 
00054 /*
00055  * Types
00056  */
00057 typedef enum {
00058   BlockNone,
00059   BlockSetValues,
00060   BlockAll
00061 } EditresBlock;
00062 
00063 typedef struct _SetValuesEvent {
00064   EditresCommand type;          /* first field must be type */
00065   WidgetInfo *widgets;
00066   unsigned short num_entries;   /* number of set values requests */
00067   char *name;
00068   char *res_type;
00069     XtPointer value;
00070     unsigned short value_len;
00071 } SetValuesEvent;
00072 
00073 typedef struct _SVErrorInfo {
00074   SetValuesEvent *event;
00075   ProtocolStream *stream;
00076   unsigned short *count;
00077   WidgetInfo *entry;
00078 } SVErrorInfo;
00079 
00080 typedef struct _GetValuesEvent {
00081   EditresCommand type;          /* first field must be type */
00082   WidgetInfo *widgets;
00083   unsigned short num_entries;   /* number of get values requests */
00084   char *name;
00085 } GetValuesEvent;
00086 
00087 typedef struct _FindChildEvent {
00088   EditresCommand type;          /* first field must be type */
00089   WidgetInfo *widgets;
00090     short x, y;
00091 } FindChildEvent;
00092 
00093 typedef struct _GenericGetEvent {
00094   EditresCommand type;          /* first field must be type */
00095   WidgetInfo *widgets;
00096   unsigned short num_entries;   /* number of set values requests */
00097 } GenericGetEvent, GetResEvent, GetGeomEvent;
00098 
00099 /*
00100  * Common to all events
00101  */
00102 typedef struct _AnyEvent {
00103   EditresCommand type;          /* first field must be type */
00104   WidgetInfo *widgets;
00105 } AnyEvent;
00106 
00107 /*
00108  * The event union
00109  */
00110 typedef union _EditresEvent {
00111     AnyEvent any_event;
00112     SetValuesEvent set_values_event;
00113     GetResEvent get_resources_event;
00114     GetGeomEvent get_geometry_event;
00115     FindChildEvent find_child_event;
00116 } EditresEvent;
00117 
00118 typedef struct _Globals {
00119     EditresBlock block;
00120     SVErrorInfo error_info;
00121     ProtocolStream stream;
00122   ProtocolStream *command_stream;       /* command stream */
00123 #if defined(LONG64) || defined(WORD64)
00124     unsigned long base_address;
00125 #endif
00126 } Globals;
00127 
00128 #define CURRENT_PROTOCOL_VERSION 5L
00129 
00130 #define streq(a,b) (strcmp((a), (b)) == 0)
00131 
00132 /*
00133  * Prototypes
00134  */
00135 static Widget _FindChild(Widget, int, int);
00136 static void _XEditresGetStringValues(Widget, Arg*, int);
00137 static XtPointer BuildReturnPacket(ResIdent, EditResError, ProtocolStream*);
00138 static void CommandDone(Widget, Atom*, Atom*);
00139 static Boolean ConvertReturnCommand(Widget, Atom*, Atom*, Atom*, XtPointer*,
00140                                     unsigned long*, int*);
00141 static Boolean CvtStringToBlock(Display*, XrmValue*, Cardinal*,
00142                                 XrmValue*, XrmValue*, XtPointer*);
00143 static EditresEvent *BuildEvent(Widget, Atom, XtPointer, ResIdent,
00144                                 unsigned long);
00145 static char *DoFindChild(Widget, EditresEvent*, ProtocolStream*);
00146 static char *DoGetGeometry(Widget, EditresEvent*, ProtocolStream*);
00147 static char *DoGetResources(Widget, EditresEvent*, ProtocolStream*);
00148 static char *DoSetValues(Widget, EditresEvent*, ProtocolStream*);
00149 static void DumpChildren(Widget, ProtocolStream*, unsigned short*);
00150 static char *DumpValues(Widget, EditresEvent*, ProtocolStream*);
00151 static char *DumpWidgets(Widget, EditresEvent*, ProtocolStream*);
00152 static void ExecuteCommand(Widget, Atom, ResIdent, EditresEvent*);
00153 static void ExecuteGetGeometry(Widget, ProtocolStream*);
00154 static void ExecuteGetResources(Widget w, ProtocolStream *stream);
00155 static void ExecuteSetValues(Widget, SetValuesEvent*, WidgetInfo*,
00156                              ProtocolStream*, unsigned short*);
00157 static void FreeEvent(EditresEvent*);
00158 static void GetCommand(Widget w, XtPointer, Atom*, Atom*, XtPointer,
00159                        unsigned long*, int*);
00160 static void HandleToolkitErrors(String, String, String, String,
00161                                 String*, Cardinal*);
00162 static void InsertWidget(ProtocolStream*, Widget);
00163 static Bool IsChild(Widget, Widget, Widget);
00164 static Bool isApplicationShell(Widget);
00165 static void LoadResources(Widget);
00166 static Bool PositionInChild(Widget, int, int);
00167 static int qcmp_widget_list(register _Xconst void*, register _Xconst void*);
00168 static void SendCommand(Widget, Atom, ResIdent, EditResError,
00169                         ProtocolStream*);
00170 static void SendFailure(Widget, Atom, ResIdent, char*);
00171 static char *VerifyWidget(Widget, WidgetInfo*);
00172 
00173 /*
00174  * External
00175  */
00176 void _XEditResCheckMessages(Widget, XtPointer, XEvent*, Boolean*);
00177 
00178 /*
00179  * Initialization
00180  */
00181 static Atom res_editor_command, res_editor_protocol, client_value;
00182 static Globals globals;
00183 
00184 /************************************************************
00185  * Resource Editor Communication Code
00186  ************************************************************/
00187 /*
00188  * Function:
00189  *      _XEditResCheckMessages
00190  *
00191  * Parameters:
00192  *      data  - unused
00193  *      event - The X Event that triggered this handler
00194  *      cont  - unused
00195  *
00196  * Description:
00197  *        This callback routine is set on all shell widgets, and checks to
00198  *      see if a client message event has come from the resource editor.
00199  */
00200 /*ARGSUSED*/
00201 void
00202 _XEditResCheckMessages(Widget w, XtPointer data, XEvent *event, Boolean *cont)
00203 {
00204     Time time;
00205     ResIdent ident;
00206   static Boolean first_time = False;
00207     static Atom res_editor, res_comm;
00208   Display *dpy;
00209 
00210   if (event->type == ClientMessage)
00211     {
00212       XClientMessageEvent * c_event = (XClientMessageEvent *)event;
00213         dpy = XtDisplay(w);
00214 
00215       if (!first_time)
00216         {
00217             Atom atoms[4];
00218           static char *names[] = {
00219                 EDITRES_NAME, EDITRES_COMMAND_ATOM,
00220             EDITRES_PROTOCOL_ATOM, EDITRES_CLIENT_VALUE
00221           };
00222                 
00223           first_time = True;
00224           XInternAtoms(dpy, names, 4, False, atoms);
00225             res_editor = atoms[0];
00226             res_editor_command = atoms[1];
00227             res_editor_protocol = atoms[2];
00228           /* Used in later procedures */
00229             client_value = atoms[3];
00230             LoadResources(w);
00231         }
00232 
00233       if ((c_event->message_type != res_editor)
00234           || (c_event->format != EDITRES_SEND_EVENT_FORMAT))
00235             return;
00236 
00237         time = c_event->data.l[0];
00238         res_comm = c_event->data.l[1];
00239         ident = (ResIdent) c_event->data.l[2];
00240       if (c_event->data.l[3] != CURRENT_PROTOCOL_VERSION)
00241         {
00242             _XEditResResetStream(&globals.stream);
00243             _XEditResPut8(&globals.stream, (unsigned int) CURRENT_PROTOCOL_VERSION);
00244             SendCommand(w, res_comm, ident, ProtocolMismatch, &globals.stream);
00245             return;
00246         }
00247 
00248         XtGetSelectionValue(w, res_comm, res_editor_command,
00249                           GetCommand, (XtPointer)(long)ident, time);
00250     }
00251 }
00252 
00253 /*
00254  * Function:
00255  *      BuildEvent
00256  *
00257  * Parameters:
00258  *      w      - widget to own selection, in case of error
00259  *      sel    - selection to send error message beck in
00260  *      data   - the data for the request
00261  *      ident  - the id number we are looking for
00262  *      length - length of request
00263  *
00264  * Description:
00265  *        Takes the info out the protocol stream an constructs
00266  *                   the proper event structure.
00267  *
00268  * Returns:
00269  *      the event, or NULL
00270  */
00271 #if defined(ERROR_MESSAGE)
00272 #undef ERROR_MESSAGE
00273 #endif
00274 #define ERROR_MESSAGE "Client: Improperly formatted protocol request"
00275 static EditresEvent *
00276 BuildEvent(Widget w, Atom sel, XtPointer data, ResIdent ident,
00277            unsigned long length)
00278 {
00279   EditresEvent *event;
00280     ProtocolStream alloc_stream, *stream;
00281     unsigned char temp;
00282     register unsigned int i;
00283 
00284   stream = &alloc_stream;
00285   stream->current = stream->top = (unsigned char *)data;
00286   stream->size = HEADER_SIZE;           /* size of header */
00287 
00288     /*
00289    * Retrieve the Header
00290      */
00291   if (length < HEADER_SIZE)
00292     {
00293       SendFailure(w, sel, ident, ERROR_MESSAGE);
00294       return (NULL);
00295     }
00296 
00297   (void)_XEditResGet8(stream, &temp);
00298   if (temp != ident)                    /* Id's don't match, ignore request */
00299     return (NULL);
00300 
00301   event = (EditresEvent *)XtCalloc(sizeof(EditresEvent), 1);
00302 
00303   (void)_XEditResGet8(stream, &temp);
00304   event->any_event.type = (EditresCommand)temp;
00305   (void)_XEditResGet32(stream, &stream->size);
00306   stream->top = stream->current;        /* reset stream to top of value */
00307         
00308     /*
00309    * Now retrieve the data segment
00310      */
00311   switch(event->any_event.type)
00312     {
00313     case SendWidgetTree:
00314         break;                  /* no additional info */
00315     case SetValues:
00316         {
00317         SetValuesEvent *sv_event = (SetValuesEvent *)event;
00318             
00319         if (!(_XEditResGetString8(stream, &sv_event->name)
00320               && _XEditResGetString8(stream, &sv_event->res_type)))
00321                 goto done;
00322 
00323             /*
00324              * Since we need the value length, we have to pull the
00325          * value out by hand
00326              */
00327         if (!_XEditResGet16(stream, &sv_event->value_len))
00328                 goto done;
00329 
00330         sv_event->value = XtMalloc(sizeof(char) * (sv_event->value_len + 1));
00331 
00332         for (i = 0; i < sv_event->value_len; i++)
00333           if (!_XEditResGet8(stream, (unsigned char *)sv_event->value + i))
00334                     goto done;
00335 
00336         ((char*)sv_event->value)[i] = '\0';
00337 
00338         if (!_XEditResGet16(stream, &sv_event->num_entries))
00339                 goto done;
00340 
00341             sv_event->widgets = (WidgetInfo *)
00342                 XtCalloc(sizeof(WidgetInfo), sv_event->num_entries);
00343             
00344         for (i = 0; i < sv_event->num_entries; i++)
00345                 if (!_XEditResGetWidgetInfo(stream, sv_event->widgets + i))
00346                     goto done;
00347             }
00348         break;
00349     case FindChild:
00350         {
00351         FindChildEvent *find_event = (FindChildEvent *)event;
00352             
00353         find_event->widgets = (WidgetInfo *)XtCalloc(sizeof(WidgetInfo), 1);
00354 
00355         if (!(_XEditResGetWidgetInfo(stream, find_event->widgets)
00356               && _XEditResGetSigned16(stream, &find_event->x)
00357               && _XEditResGetSigned16(stream, &find_event->y)))
00358                 goto done;
00359             }                                   
00360         break;
00361     case GetGeometry:
00362     case GetResources:
00363         {
00364         GenericGetEvent *get_event = (GenericGetEvent *)event;
00365             
00366         if (!_XEditResGet16(stream, &get_event->num_entries))
00367                 goto done;
00368                 
00369             get_event->widgets = (WidgetInfo *)
00370                 XtCalloc(sizeof(WidgetInfo), get_event->num_entries);
00371 
00372         for (i = 0; i < get_event->num_entries; i++)
00373                 if (!_XEditResGetWidgetInfo(stream, get_event->widgets + i)) 
00374                     goto done;
00375             }
00376         break;
00377     case GetValues: 
00378         {
00379         GetValuesEvent *gv_event = (GetValuesEvent *)event;
00380 
00381         _XEditResGetString8(stream, &gv_event->name);
00382         _XEditResGet16(stream, &gv_event->num_entries);
00383             gv_event->widgets = (WidgetInfo *)
00384                 XtCalloc(sizeof(WidgetInfo), gv_event->num_entries);
00385             _XEditResGetWidgetInfo(stream, gv_event->widgets);
00386         }
00387         break;  
00388     default:
00389         {
00390             char buf[BUFSIZ];
00391             
00392             XmuSnprintf(buf, sizeof(buf),
00393                     "Unknown Protocol request %d.", event->any_event.type);
00394             SendFailure(w, sel, ident, buf);
00395         FreeEvent(event);
00396         return (NULL);
00397         }
00398     }
00399 
00400   return (event);
00401 
00402  done:
00403     SendFailure(w, sel, ident, ERROR_MESSAGE);
00404     FreeEvent(event);
00405   return (NULL);
00406 }    
00407 
00408 /*
00409  * Function:
00410  *      FreeEvent
00411  *
00412  * Parameters:
00413  *      event - event to free
00414  *
00415  * Description:
00416  *      Frees the event structure and any other pieces in it that need freeing.
00417  */
00418 static void
00419 FreeEvent(EditresEvent *event)
00420 {
00421     if (event->any_event.widgets != NULL)
00422       {
00423         XtFree((char *)event->any_event.widgets->ids);
00424         XtFree((char *)event->any_event.widgets);
00425     }
00426 
00427     if (event->any_event.type == SetValues)
00428       {
00429         XtFree(event->set_values_event.name);
00430         XtFree(event->set_values_event.res_type);
00431     }
00432         
00433     XtFree((char *)event);
00434 }
00435 
00436 /*
00437  * Function:
00438  *      GetCommand
00439  *
00440  * Parameters:
00441  *      (See Xt XtConvertSelectionProc)
00442  *      data - contains the ident number for the command
00443  *
00444  * Description:
00445  *      Gets the Command out of the selection asserted by the resource manager.
00446  */
00447 /*ARGSUSED*/
00448 static void
00449 GetCommand(Widget w, XtPointer data, Atom *selection, Atom *type,
00450            XtPointer value, unsigned long *length, int *format)
00451 {
00452   ResIdent ident = (ResIdent)(long)data;
00453   EditresEvent *event;
00454 
00455   if (*type != res_editor_protocol || *format != EDITRES_FORMAT)
00456         return;
00457 
00458   if ((event = BuildEvent(w, *selection, value, ident, *length)) != NULL)
00459     {
00460         ExecuteCommand(w, *selection, ident, event);
00461         FreeEvent(event);
00462     }
00463 }
00464 
00465 /*
00466  * Function:
00467  *      ExecuteCommand
00468  *
00469  * Parameters:
00470  *      w       - widget
00471  *      command - the command to execute
00472  *      value   - the associated with the command
00473  *
00474  * Description:
00475  *      Executes a command string received from the resource editor.
00476  */
00477 /*ARGSUSED*/
00478 static void
00479 ExecuteCommand(Widget w, Atom sel, ResIdent ident, EditresEvent *event)
00480 {
00481   char *(*func)(Widget, EditresEvent*, ProtocolStream*);
00482   char *str;
00483 
00484   if (globals.block == BlockAll)
00485     {
00486         SendFailure(w, sel, ident, 
00487                     "This client has blocked all Editres commands.");
00488         return;
00489     }
00490   else if (globals.block == BlockSetValues
00491            && event->any_event.type == SetValues)
00492     {
00493         SendFailure(w, sel, ident, 
00494                     "This client has blocked all SetValues requests.");
00495         return;
00496     }
00497 
00498   switch(event->any_event.type)
00499     {
00500     case SendWidgetTree:
00501 #if defined(LONG64) || defined(WORD64)
00502         globals.base_address = (unsigned long)w & 0xFFFFFFFF00000000;
00503 #endif
00504         func = DumpWidgets;
00505         break;
00506     case SetValues:
00507         func = DoSetValues;
00508         break;
00509     case FindChild:
00510         func = DoFindChild;
00511         break;
00512     case GetGeometry:
00513         func = DoGetGeometry;
00514         break;
00515     case GetResources:
00516         func = DoGetResources;
00517         break;
00518     case GetValues:
00519         func = DumpValues;
00520     break;
00521     default: 
00522         {
00523             char buf[BUFSIZ];
00524 
00525             XmuSnprintf(buf, sizeof(buf),
00526                         "Unknown Protocol request %d.",event->any_event.type);
00527             SendFailure(w, sel, ident, buf);
00528             return;
00529         }
00530     }
00531 
00532     _XEditResResetStream(&globals.stream);
00533     if ((str = (*func)(w, event, &globals.stream)) == NULL)
00534         SendCommand(w, sel, ident, PartialSuccess, &globals.stream);
00535   else
00536         SendFailure(w, sel, ident, str);
00537 }
00538 
00539 /*
00540  * Function:
00541  *      ConvertReturnCommand
00542  *
00543  * Parameters:
00544  *      w          - the widget that owns the selection
00545  *      selection  - selection to convert
00546  *      target     - target type for this selection
00547  *      type_ret   - type of the selection
00548  *      value_ret  - selection value
00549  *      length_ret - lenght of this selection
00550  *      format_ret - the format the selection is in
00551  *
00552  * Description:
00553  *      Converts a selection
00554  *
00555  * Returns:
00556  *      True if conversion was sucessful
00557  */
00558 /*ARGSUSED*/
00559 static Boolean
00560 ConvertReturnCommand(Widget w, Atom *selection, Atom *target, Atom *type_ret,
00561                      XtPointer *value_ret, unsigned long *length_ret,
00562                      int *format_ret)
00563 {
00564     /*
00565    * I assume the intrinsics give me the correct selection back
00566      */
00567     if ((*target != client_value))
00568     return (False);
00569 
00570     *type_ret = res_editor_protocol;
00571   *value_ret = (XtPointer)globals.command_stream->real_top;
00572     *length_ret = globals.command_stream->size + HEADER_SIZE;
00573     *format_ret = EDITRES_FORMAT;
00574 
00575   return (True);
00576 }
00577 
00578 /*
00579  * Function:
00580  *      CommandDone
00581  *
00582  * Parameters:
00583  *      widget    - unused
00584  *      selection - unused
00585  *      target    - unused
00586  *
00587  * Description:
00588  *      done with the selection
00589  */
00590 /*ARGSUSED*/
00591 static void
00592 CommandDone(Widget widget, Atom *selection, Atom *target)
00593 {
00594     /* Keep the toolkit from automaticaly freeing the selection value */
00595 }
00596 
00597 /*
00598  * Function:
00599  *      SendFailure
00600  *
00601  * Paramters:
00602  *      w     - widget to own the selection
00603  *      sel   - selection to assert
00604  *      ident - identifier
00605  *      str   - error message
00606  *
00607  * Description:
00608  *      Sends a failure message
00609  */
00610 static void
00611 SendFailure(Widget w, Atom sel, ResIdent ident, char *str)
00612 {
00613     _XEditResResetStream(&globals.stream);
00614     _XEditResPutString8(&globals.stream, str);
00615     SendCommand(w, sel, ident, Failure, &globals.stream);
00616 }
00617 
00618 /*
00619  * Function:
00620  *      BuildReturnPacket
00621  *
00622  * Parameters:
00623  *      ident   - identifier
00624  *      command - command code
00625  *      stream  - protocol stream
00626  * Description:
00627  *      Builds a return packet, given the data to send
00628  *
00629  * Returns:
00630  *      packet to send
00631  */
00632 static XtPointer
00633 BuildReturnPacket(ResIdent ident, EditResError error, ProtocolStream *stream)
00634 {
00635     long old_alloc, old_size;
00636     unsigned char *old_current;
00637     
00638     /*
00639      * We have cleverly keep enough space at the top of the header
00640      * for the return protocol stream, so all we have to do is
00641      * fill in the space
00642      */
00643     /* 
00644      * Fool the insert routines into putting the header in the right
00645      * place while being damn sure not to realloc (that would be very bad.)
00646      */
00647     old_current = stream->current;
00648     old_alloc = stream->alloc;
00649     old_size = stream->size;
00650 
00651     stream->current = stream->real_top;
00652     stream->alloc = stream->size + (2 * HEADER_SIZE);   
00653     
00654     _XEditResPut8(stream, ident);
00655     _XEditResPut8(stream, (unsigned char)error);
00656     _XEditResPut32(stream, old_size);
00657 
00658     stream->alloc = old_alloc;
00659     stream->current = old_current;
00660     stream->size = old_size;
00661     
00662   return ((XtPointer)stream->real_top);
00663 }    
00664 
00665 /*
00666  * Function:
00667  *      SendCommand
00668  * Parameters:
00669  *      w       - widget to own the selection
00670  *      sel     - selection to assert
00671  *      ident   - identifier
00672  *      command - command code
00673  *      stream  - protocol stream
00674  *
00675  * Description:
00676  *      Builds a return command line
00677  */
00678 static void
00679 SendCommand(Widget w, Atom sel, ResIdent ident, EditResError error,
00680             ProtocolStream *stream)
00681 {
00682     BuildReturnPacket(ident, error, stream);
00683     globals.command_stream = stream;    
00684 
00685   /*
00686  * I REALLY want to own the selection.  Since this was not triggered
00687  * by a user action, and I am the only one using this atom it is safe to
00688    * use CurrentTime
00689  */
00690   XtOwnSelection(w, sel, CurrentTime, ConvertReturnCommand, NULL, CommandDone);
00691 }
00692 
00693 /************************************************************
00694  * Generic Utility Functions
00695  ************************************************************/
00696 static int
00697 qcmp_widget_list(register _Xconst void *left, register _Xconst void *right)
00698 { 
00699   return (char *)*(Widget **)left - (char *)*(Widget **)right;
00700 }
00701 
00702 /*
00703  * Function:
00704  *      FindChildren
00705  *
00706  * Parameters:
00707  *      parent   - parent widget
00708  *      children - list of children
00709  *      normal   - return normal children
00710  *      popup    - return popup children
00711  *      extra    - return extra children
00712  *
00713  * Description:
00714  *      Retuns all children (popup, normal and otherwise) of this widget
00715  *
00716  * Returns:
00717  *      number of children
00718  */
00719 static int
00720 FindChildren(Widget parent, Widget **children, Bool normal, Bool popup,
00721              Bool extra)
00722 {
00723   CompositeWidget cw = (CompositeWidget)parent;
00724   Cardinal i, num_children, current = 0;
00725   Widget *extra_widgets = NULL;
00726   Cardinal num_extra = 0;
00727     
00728     num_children = 0;
00729 
00730     if (XtIsWidget(parent) && popup)
00731         num_children += parent->core.num_popups;
00732         
00733     if (XtIsComposite(parent) && normal) 
00734         num_children += cw->composite.num_children; 
00735 
00736   if (XtIsWidget(parent) && extra)
00737     {
00738       XtResourceList norm_list, cons_list;
00739       Cardinal num_norm, num_cons;
00740       Arg args[1];
00741       Widget widget;
00742 
00743       XtGetResourceList(XtClass(parent), &norm_list, &num_norm);
00744 
00745       if (XtParent(parent) != NULL)
00746         XtGetConstraintResourceList(XtClass(XtParent(parent)),
00747                                     &cons_list, &num_cons);
00748       else
00749         num_cons = 0;
00750 
00751       extra_widgets = (Widget *)XtMalloc(sizeof(Widget));
00752       for (i = 0; i < num_norm; i++)
00753         if (strcmp(norm_list[i].resource_type, XtRWidget) == 0)
00754           {
00755             widget = NULL;
00756             XtSetArg(args[0], norm_list[i].resource_name, &widget);
00757             XtGetValues(parent, args, 1);
00758             if (widget && XtParent(widget) == parent)
00759               {
00760                 ++num_extra;
00761                 extra_widgets = (Widget *)
00762                   XtRealloc((char *)extra_widgets, num_extra * sizeof(Widget));
00763                 extra_widgets[num_extra - 1] = widget;
00764               }
00765           }
00766       for (i = 0; i < num_cons; i++)
00767         if (strcmp(cons_list[i].resource_type, XtRWidget) == 0)
00768           {
00769             widget = NULL;
00770             XtSetArg(args[0], cons_list[i].resource_name, &widget);
00771             XtGetValues(parent, args, 1);
00772             if (widget && XtParent(widget) == parent)
00773               {
00774                 ++num_extra;
00775                 extra_widgets = (Widget *)
00776                   XtRealloc((char *)extra_widgets, num_extra * sizeof(Widget));
00777                 extra_widgets[num_extra - 1] = widget;
00778               }
00779           }
00780       if (num_norm)
00781         XtFree((char *)norm_list);
00782       if (num_cons)
00783         XtFree((char *)cons_list);
00784     }
00785 
00786   if ((num_children + num_extra) == 0)
00787     {
00788         *children = NULL; 
00789       return (0);
00790     }
00791 
00792   *children = (Widget *)XtMalloc(sizeof(Widget) * (num_children + num_extra));
00793 
00794     if (XtIsComposite(parent) && normal)
00795     for (i = 0; i < cw->composite.num_children; i++, current++)
00796             (*children)[current] = cw->composite.children[i]; 
00797 
00798     if (XtIsWidget(parent) && popup)
00799     for (i = 0; i < parent->core.num_popups; i++, current++)
00800             (*children)[current] = parent->core.popup_list[i];
00801 
00802   if (num_extra)
00803     /* Check for dups */
00804     {
00805       Cardinal j, old_num_extra = num_extra;
00806 
00807       qsort(extra_widgets, num_extra, sizeof(Widget), qcmp_widget_list);
00808       for (i = 0; i < num_extra - 1; i++)
00809         while (i < num_extra - 1 && extra_widgets[i] == extra_widgets[i + 1])
00810           {
00811             memmove(&extra_widgets[i], &extra_widgets[i + 1],
00812                     (num_extra - i) * sizeof(Widget));
00813             --num_extra;
00814           }
00815 
00816       for (i = 0; i < num_children; i++)
00817         for (j = 0; j < num_extra; j++)
00818           if ((*children)[i] == extra_widgets[j])
00819             {
00820               if ((j + 1) < num_extra)
00821                 memmove(&extra_widgets[j], &extra_widgets[j + 1],
00822                         (num_extra - j) * sizeof(Widget));
00823               --num_extra;
00824             }
00825 
00826       if (old_num_extra != num_extra)
00827         *children = (Widget *)XtRealloc((char *)*children, sizeof(Widget)
00828                                         * (num_children + num_extra));
00829 
00830       if (num_extra)
00831         memcpy(&(*children)[num_children], extra_widgets,
00832                sizeof(Widget) * num_extra);
00833     }
00834   if (extra_widgets)
00835     XtFree((char *)extra_widgets);
00836   if (num_children + num_extra == 0)
00837     {
00838       XtFree((char *)*children);
00839       *children = NULL;
00840     }
00841 
00842   return (num_children + num_extra);
00843 }
00844                 
00845 /*
00846  * Function:
00847  *      IsChild
00848  *
00849  * parameters:
00850  *      top    - top of the tree
00851  *      parent - parent widget
00852  *      child  - child widget
00853  *
00854  * Description:
00855  *      Check to see of child is a child of parent
00856  */
00857 static Bool
00858 IsChild(Widget top, Widget parent, Widget child)
00859 {
00860     int i, num_children;
00861   Widget *children;
00862 
00863     if (parent == NULL)
00864     return (top == child);
00865 
00866   num_children = FindChildren(parent, &children, True, True, True);
00867 
00868   for (i = 0; i < num_children; i++)
00869     if (children[i] == child)
00870       {
00871             XtFree((char *)children);
00872         return (True);
00873     }
00874 
00875     XtFree((char *)children);
00876   return (False);
00877 }
00878 
00879 /*
00880  * Function:
00881  *      VerifyWidget
00882  *
00883  * Parameters:
00884  *      w    - any widget in the tree
00885  *      info - info about the widget to verify
00886  *
00887  * Description:
00888  *      Makes sure all the widgets still exist
00889  */
00890 static char * 
00891 VerifyWidget(Widget w, WidgetInfo *info)
00892 {
00893     Widget top;
00894     register int count;
00895     register Widget parent;
00896   register unsigned long *child;
00897 
00898   for (top = w; XtParent(top) != NULL; top = XtParent(top))
00899     ;
00900 
00901     parent = NULL;
00902     child = info->ids;
00903     count = 0;
00904 
00905   while (True)
00906     {
00907         if (!IsChild(top, parent, (Widget) *child)) 
00908         return ("This widget no longer exists in the client.");
00909 
00910         if (++count == info->num_widgets)
00911             break;
00912 
00913       parent = (Widget)*child++;
00914     }
00915 
00916   info->real_widget = (Widget)*child;
00917 
00918   return (NULL);
00919 }
00920 
00921 /************************************************************
00922  * Code to Perform SetValues operations
00923  ************************************************************/
00924 /*
00925  * Function:
00926  *      DoSetValues
00927  *
00928  * Parameters:
00929  *      w      - a widget in the tree
00930  *      event  - event that caused this action
00931  *      stream - protocol stream to add
00932  *
00933  * Description:
00934  *      Performs the setvalues requested
00935  *
00936  * Returns:
00937  *      NULL
00938  */
00939 static char *
00940 DoSetValues(Widget w, EditresEvent *event, ProtocolStream *stream)
00941 {
00942   char *str;
00943     register unsigned i;
00944     unsigned short count = 0;
00945   SetValuesEvent *sv_event = (SetValuesEvent *)event;
00946     
00947   _XEditResPut16(stream, count);  /* insert 0, will be overwritten later */
00948 
00949   for (i = 0; i < sv_event->num_entries; i++)
00950     {
00951       if ((str = VerifyWidget(w, &sv_event->widgets[i])) != NULL)
00952         {
00953           _XEditResPutWidgetInfo(stream, &sv_event->widgets[i]);
00954             _XEditResPutString8(stream, str);
00955             count++;
00956         }
00957         else 
00958             ExecuteSetValues(sv_event->widgets[i].real_widget, 
00959                              sv_event, sv_event->widgets + i, stream, &count);
00960     }
00961 
00962     /*
00963      * Overwrite the first 2 bytes with the real count.
00964      */
00965     *(stream->top) = count >> XER_NBBY;
00966     *(stream->top + 1) = count;
00967 
00968   return (NULL);
00969 }
00970 
00971 /*
00972  * Function:
00973  *      HandleToolkitErrors
00974  *
00975  * Parameters:
00976  *      name       - name of the error
00977  *      type       - type of the error
00978  *      class      - class of the error
00979  *      msg        - the default message
00980  *      params     - the extra parameters for this message
00981  *      num_params - ""
00982  *
00983  *      Description: Handles X Toolkit Errors.
00984  */
00985 /* ARGSUSED */
00986 static void
00987 HandleToolkitErrors(String name, String type, String class, String msg,
00988                     String *params, Cardinal *num_params)
00989 {
00990   SVErrorInfo *info = &globals.error_info;
00991   char buf[BUFSIZ];
00992 
00993   if (streq(name, "unknownType"))
00994         XmuSnprintf(buf, sizeof(buf),
00995                     "The `%s' resource is not used by this widget.",
00996                     info->event->name);
00997   else if (streq(name, "noColormap"))
00998         XmuSnprintf(buf, sizeof(buf), msg, params[0]);
00999     else if (streq(name, "conversionFailed") || streq(name, "conversionError"))
01000     {
01001         if (streq((String)info->event->value, XtRString))
01002             XmuSnprintf(buf, sizeof(buf),
01003                         "Could not convert the string '%s' for the `%s' "
01004                         "resource.", (String)info->event->value,
01005                         info->event->name);
01006         else
01007             XmuSnprintf(buf, sizeof(buf),
01008                         "Could not convert the `%s' resource.",
01009                         info->event->name);
01010     }
01011   else
01012         XmuSnprintf(buf, sizeof(buf),
01013                     "Name: %s, Type: %s, Class: %s, Msg: %s",
01014                     name, type, class, msg);
01015 
01016     /*
01017    * Insert this info into the protocol stream, and update the count
01018      */ 
01019     (*(info->count))++;
01020     _XEditResPutWidgetInfo(info->stream, info->entry);
01021     _XEditResPutString8(info->stream, buf);
01022 }
01023 
01024 /*
01025  * Function:
01026  *      ExecuteSetValues
01027  *
01028  * Parameters:
01029  *      w        - widget to perform the set_values on
01030  *      sv_event - set values event
01031  *      sv_info  - set_value info
01032  *.
01033  * Description:
01034  *      Performs a setvalues for a given command
01035  */
01036 static void
01037 ExecuteSetValues(Widget w, SetValuesEvent *sv_event, WidgetInfo *entry,
01038                  ProtocolStream *stream, unsigned short *count)
01039 {
01040     XtErrorMsgHandler old;
01041   SVErrorInfo *info = &globals.error_info;
01042     
01043     info->event = sv_event;     /* No data can be passed to */
01044     info->stream = stream;      /* an error handler, so we */
01045   info->count = count;          /* have to use a global */
01046     info->entry = entry;
01047 
01048     old = XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w),
01049                                     HandleToolkitErrors);
01050 
01051     XtVaSetValues(w, XtVaTypedArg,
01052                   sv_event->name, sv_event->res_type,
01053                   sv_event->value, sv_event->value_len,
01054                   NULL);
01055 
01056     (void)XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w), old);
01057 }
01058 
01059 /************************************************************
01060  * Code for Creating and dumping widget tree.
01061  ************************************************************/
01062 /* Function:
01063  *      DumpWidgets
01064  *
01065  * Parameters:
01066  *      w      - a widget in the tree
01067  *      event  - event that caused this action
01068  *      stream - protocol stream to add
01069  *
01070  * Description:
01071  *        Given a widget it builds a protocol packet containing the entire
01072  *      widget heirarchy.
01073  *
01074  * Returns:
01075  *      NULL
01076  */
01077 #define TOOLKIT_TYPE ("Xt")
01078 /*ARGSUSED*/
01079 static char * 
01080 DumpWidgets(Widget w, EditresEvent *event, ProtocolStream *stream)
01081 {
01082     unsigned short count = 0;
01083         
01084   /* Find Tree's root */
01085   for (; XtParent(w) != NULL; w = XtParent(w))
01086     ;
01087     
01088     /*
01089    * hold space for count, overwritten later
01090      */
01091   _XEditResPut16(stream, (unsigned int)0);
01092 
01093     DumpChildren(w, stream, &count);
01094 
01095     /*
01096    * write out toolkit type
01097      */
01098     _XEditResPutString8(stream, TOOLKIT_TYPE);
01099 
01100     /*
01101    * Overwrite the first 2 bytes with the real count
01102      */
01103     *(stream->top) = count >> XER_NBBY;
01104     *(stream->top + 1) = count;
01105 
01106   return (NULL);
01107 }
01108 
01109 /*
01110  * Function:
01111  *       DumpChildren
01112  *
01113  * Parameters:
01114  *      w      - widget to dump
01115  *      stream - stream to dump to
01116  *      count  - number of dumps we have performed
01117  *
01118  * Description:
01119  *      Adds a child's name to the list.
01120  */
01121 /* This is a trick/kludge.  To make shared libraries happier (linking
01122  * against Xmu but not linking against Xt, and apparently even work
01123  * as we desire on SVR4, we need to avoid an explicit data reference
01124  * to applicationShellWidgetClass.  XtIsTopLevelShell is known
01125  * (implementation dependent assumption!) to use a bit flag.  So we
01126  * go that far.  Then, we test whether it is an applicationShellWidget
01127  * class by looking for an explicit class name.  Seems pretty safe.
01128  */
01129 static Bool
01130 isApplicationShell(Widget w)
01131 {
01132     register WidgetClass c;
01133 
01134     if (!XtIsTopLevelShell(w))
01135     return (False);
01136   for (c = XtClass(w); c; c = c->core_class.superclass)
01137     if (strcmp(c->core_class.class_name, "ApplicationShell") == 0)
01138       return (True);
01139 
01140   return (False);
01141 }
01142 
01143 static void
01144 DumpChildren(Widget w, ProtocolStream *stream, unsigned short *count)
01145 {
01146     int i, num_children;
01147     Widget *children;
01148     unsigned long window;
01149   char *c_class;
01150 
01151     (*count)++;
01152         
01153   InsertWidget(stream, w);              /* Insert the widget into the stream */
01154 
01155     _XEditResPutString8(stream, XtName(w)); /* Insert name */
01156 
01157     if (isApplicationShell(w))
01158     c_class = ((ApplicationShellWidget)w)->application.class;
01159     else
01160     c_class = XtClass(w)->core_class.class_name;
01161 
01162   _XEditResPutString8(stream, c_class);         /* Insert class */
01163 
01164      if (XtIsWidget(w))
01165          if (XtIsRealized(w))
01166             window = XtWindow(w);
01167         else
01168             window = EDITRES_IS_UNREALIZED;
01169      else
01170          window = EDITRES_IS_OBJECT;
01171 
01172   _XEditResPut32(stream, window);               /* Insert window id */
01173 
01174     /*
01175    * Find children and recurse
01176      */
01177   num_children = FindChildren(w, &children, True, True, True);
01178     for (i = 0; i < num_children; i++) 
01179         DumpChildren(children[i], stream, count);
01180 
01181     XtFree((char *)children);
01182 }
01183 
01184 /************************************************************
01185  * Code for getting the geometry of widgets
01186  ************************************************************/
01187 /*
01188  * Function:
01189  *      DoGetGeometry
01190  *
01191  * Parameters:
01192  *      w      - widget in the tree
01193  *      event  - event that caused this action
01194  *      stream - protocol stream to add
01195  *
01196  * Description:
01197  *      Retrieves the Geometry of each specified widget.
01198  *
01199  * Returns:
01200  *      NULL
01201  */
01202 static char *
01203 DoGetGeometry(Widget w, EditresEvent *event, ProtocolStream *stream)
01204 {
01205     unsigned i;
01206   char *str;
01207   GetGeomEvent *geom_event = (GetGeomEvent *)event;
01208     
01209     _XEditResPut16(stream, geom_event->num_entries);
01210 
01211   for (i = 0; i < geom_event->num_entries; i++)
01212     {
01213         /* 
01214        * Send out the widget id
01215          */
01216       _XEditResPutWidgetInfo(stream, &geom_event->widgets[i]);
01217 
01218       if ((str = VerifyWidget(w, &geom_event->widgets[i])) != NULL)
01219         {
01220           _XEditResPutBool(stream, True);       /* an error occured */
01221           _XEditResPutString8(stream, str);     /* set message */
01222         }
01223         else 
01224             ExecuteGetGeometry(geom_event->widgets[i].real_widget, stream);
01225     }
01226 
01227   return (NULL);
01228 }
01229 
01230 /*
01231  * Function:
01232  *      ExecuteGetGeometry
01233  *
01234  * Parameters:
01235  *      w      - widget to get geometry
01236  *      stream - stream to append to
01237  *
01238  * Description:
01239  *      Gets the geometry for each widget specified.
01240  *
01241  * Returns:
01242  *      True if no error occured.
01243  */
01244 static void
01245 ExecuteGetGeometry(Widget w, ProtocolStream *stream)
01246 {
01247     int i;
01248     Boolean mapped_when_man;
01249     Dimension width, height, border_width;
01250     Arg args[8];
01251     Cardinal num_args = 0;
01252     Position x, y;
01253     
01254   if (!XtIsRectObj(w) || (XtIsWidget(w) && !XtIsRealized(w)))
01255     {
01256       _XEditResPutBool(stream, False);          /* no error */
01257         _XEditResPutBool(stream, False);        /* not visable */
01258         for (i = 0; i < 5; i++)         /* fill in extra space with 0's */
01259             _XEditResPut16(stream, 0);
01260         return;
01261     }
01262 
01263     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
01264     XtSetArg(args[num_args], XtNheight, &height); num_args++;
01265     XtSetArg(args[num_args], XtNborderWidth, &border_width); num_args++;
01266     XtSetArg(args[num_args], XtNmappedWhenManaged, &mapped_when_man);
01267     num_args++;
01268     XtGetValues(w, args, num_args);
01269 
01270   if (!(XtIsManaged(w) && mapped_when_man) && XtIsWidget(w))
01271     {
01272         XWindowAttributes attrs;
01273         
01274         /* 
01275          * The toolkit does not maintain mapping state, we have
01276        * to go to the server
01277          */
01278       if (XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attrs) != 0)
01279         {
01280           if (attrs.map_state != IsViewable)
01281             {
01282               _XEditResPutBool(stream, False);  /* no error */
01283               _XEditResPutBool(stream, False);  /* not visable */
01284               for (i = 0; i < 5; i++)   /* fill in extra space with 0's */
01285                     _XEditResPut16(stream, 0);
01286                 return;
01287             }
01288         }
01289       else
01290         {
01291             _XEditResPut8(stream, True); /* Error occured. */
01292             _XEditResPutString8(stream, "XGetWindowAttributes failed.");
01293             return;
01294         }
01295     }
01296 
01297     XtTranslateCoords(w, -((int) border_width), -((int) border_width), &x, &y);
01298 
01299   _XEditResPutBool(stream, False);      /* no error */
01300   _XEditResPutBool(stream, True);       /* Visable */
01301     _XEditResPut16(stream, x);
01302     _XEditResPut16(stream, y);
01303     _XEditResPut16(stream, width);
01304     _XEditResPut16(stream, height);
01305     _XEditResPut16(stream, border_width);
01306 }
01307 
01308 /************************************************************
01309  * Code for executing FindChild
01310  ************************************************************/
01311 /*
01312  * Function:
01313  *      PositionInChild
01314  *
01315  * Parameters:
01316  *      child - child widget to check
01317  *      x     - location of point to check in the parent's coord space
01318  *      y     - ""
01319  *
01320  * Description:
01321  *      Returns true if this location is in the child.
01322  */
01323 static Bool
01324 PositionInChild(Widget child, int x, int y)
01325 {
01326     Arg args[6];
01327     Cardinal num;
01328     Dimension width, height, border_width;
01329     Position child_x, child_y;
01330     Boolean mapped_when_managed;
01331 
01332   if (!XtIsRectObj(child))      /* we must at least be a rect obj */
01333         return (False);
01334 
01335     num = 0;
01336     XtSetArg(args[num], XtNmappedWhenManaged, &mapped_when_managed); num++;
01337     XtSetArg(args[num], XtNwidth, &width); num++;
01338     XtSetArg(args[num], XtNheight, &height); num++;
01339     XtSetArg(args[num], XtNx, &child_x); num++;
01340     XtSetArg(args[num], XtNy, &child_y); num++;
01341     XtSetArg(args[num], XtNborderWidth, &border_width); num++;
01342     XtGetValues(child, args, num);
01343  
01344     /*
01345      * The only way we will know of the widget is mapped is to see if
01346      * mapped when managed is True and this is a managed child.  Otherwise
01347    * we will have to ask the server if this window is mapped
01348      */
01349   if (XtIsWidget(child) && !(mapped_when_managed && XtIsManaged(child)))
01350     {
01351         XWindowAttributes attrs;
01352 
01353       if (XGetWindowAttributes(XtDisplay(child), XtWindow(child), &attrs)
01354           &&  attrs.map_state != IsViewable)
01355         return (False);
01356     }
01357 
01358   return ((x >= child_x)
01359           && (x <= (child_x + (Position)width + 2 * (Position)border_width))
01360           && (y >= child_y)
01361           && (y <= (child_y + (Position)height + 2 * (Position)border_width)));
01362 }
01363 
01364 /*
01365  * Function:
01366  *      _FindChild
01367  *
01368  * Parameters:
01369  *      parent - widget that is known to contain the point specified
01370  *      x      - point in coordinates relative to the widget specified
01371  *      y      - ""
01372  *
01373  * Description:
01374  *      Finds the child that actually contains the point shown.
01375  */
01376 static Widget 
01377 _FindChild(Widget parent, int x, int y)
01378 {
01379   Widget *children;
01380   int i = FindChildren(parent, &children, True, False, True);
01381 
01382   while (i > 0)
01383     {
01384         i--;
01385 
01386       if (PositionInChild(children[i], x, y))
01387         {
01388             Widget child = children[i];
01389             
01390             XtFree((char *)children);
01391           return (_FindChild(child, x - child->core.x, y - child->core.y));
01392         }
01393     }
01394 
01395     XtFree((char *)children);
01396 
01397   return (parent);
01398 }
01399 
01400 /*
01401  * Function:
01402  *      DoFindChild
01403  *
01404  * Parameters:
01405  *      w      - widget in the tree
01406  *      event  - event that caused this action
01407  *      stream - protocol stream to add
01408  * Description:
01409  *      Finds the child that contains the location specified.
01410  *
01411  * Returns:
01412  *        An allocated error message if something went horribly wrong and
01413  *      no set values were performed, else NULL.
01414  */
01415 static char *
01416 DoFindChild(Widget w, EditresEvent *event, ProtocolStream *stream)
01417 {
01418   char *str;
01419     Widget parent, child;
01420     Position parent_x, parent_y;
01421   FindChildEvent *find_event = (FindChildEvent *)event;
01422     
01423     if ((str = VerifyWidget(w, find_event->widgets)) != NULL) 
01424     return (str);
01425 
01426     parent = find_event->widgets->real_widget;
01427 
01428     XtTranslateCoords(parent, (Position) 0, (Position) 0,
01429                       &parent_x, &parent_y);
01430     
01431     child = _FindChild(parent, find_event->x - (int) parent_x,
01432                        find_event->y - (int) parent_y);
01433 
01434     InsertWidget(stream, child);
01435 
01436   return (NULL);
01437 }
01438 
01439 /************************************************************
01440  * Procedures for performing GetResources
01441  ************************************************************/
01442 /*
01443  * Function:
01444  *      DoGetResources
01445  *
01446  * Parameters:
01447  *      w      - widget in the tree
01448  *      event  - event that caused this action
01449  *      stream - protocol stream to add
01450  *
01451  * Description:
01452  *      Gets the Resources associated with the widgets passed.
01453  *
01454  * Returns:
01455  *      NULL
01456  */
01457 static char *
01458 DoGetResources(Widget w, EditresEvent *event, ProtocolStream *stream)
01459 {
01460     unsigned int i;
01461   char *str;
01462   GetResEvent *res_event = (GetResEvent *)event;
01463     
01464     _XEditResPut16(stream, res_event->num_entries); /* number of replys */
01465 
01466   for (i = 0; i < res_event->num_entries; i++)
01467     {
01468         /* 
01469        * Send out the widget id
01470          */
01471       _XEditResPutWidgetInfo(stream, &res_event->widgets[i]);
01472       if ((str = VerifyWidget(w, &res_event->widgets[i])) != NULL)
01473         {
01474           _XEditResPutBool(stream, True);       /* an error occured */
01475           _XEditResPutString8(stream, str);     /* set message */
01476         }
01477       else
01478         {
01479           _XEditResPutBool(stream, False);      /* no error occured */
01480           ExecuteGetResources(res_event->widgets[i].real_widget, stream);
01481         }
01482     }
01483 
01484   return (NULL);
01485 }
01486 
01487 /* Function:
01488  *      ExecuteGetResources
01489  *
01490  * Parameters:
01491  *      w      - widget to get resources on
01492  *      stream - protocol stream
01493  *
01494  * Description:
01495  *      Gets the resources for any individual widget
01496  */
01497 static void
01498 ExecuteGetResources(Widget w, ProtocolStream *stream)
01499 {
01500     XtResourceList norm_list, cons_list;
01501     Cardinal num_norm, num_cons;
01502     register Cardinal i;
01503 
01504     /* 
01505    * Get Normal Resources
01506      */
01507     XtGetResourceList(XtClass(w), &norm_list, &num_norm);
01508 
01509     if (XtParent(w) != NULL) 
01510     XtGetConstraintResourceList(XtClass(XtParent(w)), &cons_list,&num_cons);
01511     else
01512         num_cons = 0;
01513 
01514   _XEditResPut16(stream, num_norm + num_cons);  /* how many resources */
01515     
01516     /*
01517    * Insert all the normal resources
01518      */
01519   for (i = 0; i < num_norm; i++)
01520     {
01521         _XEditResPutResourceType(stream, NormalResource);
01522         _XEditResPutString8(stream, norm_list[i].resource_name);
01523         _XEditResPutString8(stream, norm_list[i].resource_class);
01524         _XEditResPutString8(stream, norm_list[i].resource_type);
01525     }
01526   XtFree((char *)norm_list);
01527 
01528     /*
01529    * Insert all the constraint resources
01530      */
01531   if (num_cons > 0)
01532     {
01533       for (i = 0; i < num_cons; i++)
01534         {
01535             _XEditResPutResourceType(stream, ConstraintResource);
01536             _XEditResPutString8(stream, cons_list[i].resource_name);
01537             _XEditResPutString8(stream, cons_list[i].resource_class);
01538             _XEditResPutString8(stream, cons_list[i].resource_type);
01539         }
01540       XtFree((char *)cons_list);
01541     }
01542 }
01543 
01544 /*
01545  * Function:
01546  *      DumpValues
01547  *
01548  * Parameters:
01549  *      event  - event that caused this action
01550  *      stream - protocol stream to add
01551  *
01552  * Description:
01553  *      Returns resource values to the resource editor.
01554  *
01555  * Returns:
01556  *      NULL
01557  */
01558 /*ARGSUSED*/
01559 static char *
01560 DumpValues(Widget w, EditresEvent* event, ProtocolStream* stream)
01561 {
01562   char *str;
01563   Arg warg[1];
01564   String res_value = NULL;
01565   GetValuesEvent *gv_event = (GetValuesEvent *)event;
01566 
01567   /* put the count in the stream */
01568   _XEditResPut16(stream, (unsigned int)1);
01569 
01570   /*
01571    * Get the resource of the widget asked for by the
01572    * resource editor and insert it into the stream
01573    */
01574   XtSetArg(warg[0], gv_event->name, &res_value);
01575 
01576   if ((str = VerifyWidget(w, &gv_event->widgets[0])) != NULL)
01577     _XEditResPutString8(stream, str);
01578   else
01579     {
01580       _XEditresGetStringValues(gv_event->widgets[0].real_widget, warg, 1);
01581       if (!res_value)
01582         res_value = "NoValue";
01583   _XEditResPutString8(stream, res_value);
01584     }
01585 
01586   return (NULL);
01587 }
01588 
01589 /************************************************************
01590  * Code for inserting values into the protocol stream
01591  ************************************************************/
01592 /*
01593  * Function:
01594  *      InsertWidget
01595  *
01596  * Parameters:
01597  *      stream - protocol stream
01598  *      w      - widget to insert
01599  *
01600  * Description:
01601  *        Inserts the full parent hierarchy of this widget into the protocol
01602  *      stream as a widget list.
01603  */
01604 static void
01605 InsertWidget(ProtocolStream *stream, Widget w)
01606 {
01607     Widget temp;
01608   unsigned long *widget_list;
01609     register int i, num_widgets;
01610 
01611   for (temp = w, i = 0; temp != 0; temp = XtParent(temp), i++)
01612     ;
01613 
01614     num_widgets = i;
01615   widget_list = (unsigned long *)XtMalloc(sizeof(unsigned long) * num_widgets);
01616 
01617     /*
01618    * Put the widgets into the list
01619    * make sure that they are inserted in the list from parent -> child
01620      */
01621     for (i--, temp = w; temp != NULL; temp = XtParent(temp), i--) 
01622     widget_list[i] = (unsigned long)temp;
01623         
01624   _XEditResPut16(stream, num_widgets);          /* insert number of widgets */
01625   for (i = 0; i < num_widgets; i++)             /* insert Widgets themselves */
01626         _XEditResPut32(stream, widget_list[i]);
01627     
01628     XtFree((char *)widget_list);
01629 }
01630 
01631 /************************************************************
01632  * All of the following routines are public
01633  ************************************************************/
01634 /*
01635  * Function:
01636  *      _XEditResPutString8
01637  *
01638  * Parameters:
01639  *      stream - stream to insert string into
01640  *      str    - string to insert
01641  *
01642  * Description:
01643  *      Inserts a string into the protocol stream.
01644  */
01645 void
01646 _XEditResPutString8(ProtocolStream *stream, char *str)
01647 {
01648     int i, len = strlen(str);
01649 
01650     _XEditResPut16(stream, len);
01651   for (i = 0; i < len; i++, str++)
01652         _XEditResPut8(stream, *str);
01653 }
01654 
01655 /*
01656  * Function:
01657  *      _XEditResPut8
01658  *
01659  * Parameters:
01660  *      stream - stream to insert string into
01661  *      value  - value to insert
01662  *
01663  * Description:
01664  *      Inserts an 8 bit integer into the protocol stream.
01665  */
01666 void
01667 _XEditResPut8(ProtocolStream *stream, unsigned int value)
01668 {
01669     unsigned char temp;
01670 
01671   if (stream->size >= stream->alloc)
01672     {
01673         stream->alloc += 100;
01674       stream->real_top = (unsigned char *)
01675         XtRealloc((char *)stream->real_top, stream->alloc + HEADER_SIZE);
01676         stream->top = stream->real_top + HEADER_SIZE;
01677         stream->current = stream->top + stream->size;
01678     }
01679 
01680     temp = (unsigned char) (value & BYTE_MASK);
01681     *((stream->current)++) = temp;
01682     (stream->size)++;
01683 }
01684 
01685 /*
01686  * Function:
01687  *      _XEditResPut16
01688  *
01689  * Arguments:
01690  *      stream - stream to insert string into
01691  *      value  - value to insert
01692  *
01693  * Description:
01694  *      Inserts a 16 bit integer into the protocol stream.
01695  */
01696 void
01697 _XEditResPut16(ProtocolStream *stream, unsigned int value)
01698 {
01699     _XEditResPut8(stream, (value >> XER_NBBY) & BYTE_MASK);
01700     _XEditResPut8(stream, value & BYTE_MASK);
01701 }
01702 
01703 /*
01704  * Function:
01705  *      _XEditResPut32
01706  *
01707  * Arguments:
01708  *      stream - stream to insert string into
01709  *      value  - value to insert
01710  *
01711  * Description:
01712  *      Inserts a 32 bit integer into the protocol stream.
01713  */
01714 void
01715 _XEditResPut32(ProtocolStream *stream, unsigned long value)
01716 {
01717     int i;
01718 
01719     for (i = 3; i >= 0; i--) 
01720     _XEditResPut8(stream, (value >> (XER_NBBY * i)) & BYTE_MASK);
01721 }
01722 
01723 /*
01724  * Function:
01725  *      _XEditResPutWidgetInfo
01726  *
01727  * Parameters:
01728  *      stream - stream to insert widget info into
01729  *      info   - info to insert
01730  *
01731  * Description:
01732  *      Inserts the widget info into the protocol stream.
01733  */
01734 void
01735 _XEditResPutWidgetInfo(ProtocolStream *stream, WidgetInfo *info)
01736 {
01737     unsigned int i;
01738 
01739     _XEditResPut16(stream, info->num_widgets);
01740     for (i = 0; i < info->num_widgets; i++) 
01741         _XEditResPut32(stream, info->ids[i]);
01742 }
01743 
01744 /************************************************************
01745  * Code for retrieving values from the protocol stream
01746  ************************************************************/
01747 /*
01748  * Function:
01749  *      _XEditResResetStream
01750  *
01751  * Parameters:
01752  *      stream - stream to reset
01753  *
01754  * Description:
01755  *      Resets the protocol stream.
01756  */
01757 void
01758 _XEditResResetStream(ProtocolStream *stream)
01759 {
01760     stream->current = stream->top;
01761     stream->size = 0;
01762   if (stream->real_top == NULL)
01763     {
01764       stream->real_top = (unsigned char *)
01765         XtRealloc((char *)stream->real_top, stream->alloc + HEADER_SIZE);
01766         stream->top = stream->real_top + HEADER_SIZE;
01767         stream->current = stream->top + stream->size;
01768     }
01769 }
01770 
01771 /*
01772  * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 
01773  *
01774  * The only modified field if the "current" field
01775  *
01776  * The only fields that must be set correctly are the "current", "top"
01777  * and "size" fields.
01778  */
01779 /*
01780  * Function:
01781  *      _XEditResGetg8
01782  *
01783  * Parameters:
01784  *      stream - protocol stream
01785  *      value  - a pointer to value to return
01786  *
01787  * Description:
01788  *      Retrieves an unsigned 8 bit value from the protocol stream.
01789  *
01790  * Returns:
01791  *      True if sucessful
01792  */
01793 Bool
01794 _XEditResGet8(ProtocolStream *stream, unsigned char *value)
01795 {
01796   if (stream->size < (unsigned long)(stream->current - stream->top))
01797     return (False);
01798 
01799   *value = *((stream->current)++);
01800   return (True);
01801 }
01802 
01803 /*
01804  * Function:
01805  *      _XEditResGet16
01806  *
01807  * Parameters:
01808  *      stream - protocol stream
01809  *      value  - pointer to return value
01810  *
01811  * Description:
01812  *      Retrieves an unsigned 16 bit value from the protocol stream.
01813  *
01814  * Returns:
01815  *      True if sucessful
01816  */
01817 Bool
01818 _XEditResGet16(ProtocolStream *stream, unsigned short *value)
01819 {
01820     unsigned char temp1, temp2;
01821 
01822   if (!(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2)))
01823     return (False);
01824     
01825   *value = ((unsigned short)temp1 << XER_NBBY) + (unsigned short)temp2;
01826   return (True);
01827 }
01828 
01829 /*
01830  * Function:
01831  *      _XEditResGetSigned16
01832  *
01833  * Parameters:
01834  *      stream - protocol stream
01835  *      value  - pointer to return value
01836  *
01837  * Description:
01838  *      Retrieves an signed 16 bit value from the protocol stream.
01839  *
01840  * Returns:
01841  *      True if sucessful
01842  */
01843 Bool
01844 _XEditResGetSigned16(ProtocolStream *stream, short *value)
01845 {
01846     unsigned char temp1, temp2;
01847 
01848   if (!(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2)))
01849     return (False);
01850     
01851   if (temp1 & (1 << (XER_NBBY - 1)))    /* If the sign bit is active */
01852     {
01853       *value = -1;                      /* store all 1's */
01854       *value &= (temp1 << XER_NBBY);    /* Now and in the MSB */
01855       *value &= temp2;                   /* and LSB */
01856     }
01857     else 
01858     *value = ((unsigned short)temp1 << XER_NBBY) + (unsigned short)temp2;
01859 
01860   return (True);
01861 }
01862 
01863 /*
01864  * Function:
01865  *      _XEditResGet32
01866  *
01867  * Parameters:
01868  *      stream - protocol stream
01869  *      value  - pointer to return value
01870  *
01871  * Description:
01872  *      Retrieves an unsigned 32 bit value from the protocol stream.
01873  *
01874  * Returns:
01875  *      True if sucessful
01876  */
01877 Bool
01878 _XEditResGet32(ProtocolStream *stream, unsigned long *value)
01879 {
01880     unsigned short temp1, temp2;
01881 
01882   if (!(_XEditResGet16(stream, &temp1) && _XEditResGet16(stream, &temp2)))
01883     return (False);
01884     
01885   *value = ((unsigned short)temp1 << (XER_NBBY * 2)) + (unsigned short)temp2;
01886   return (True);
01887 }
01888 
01889 /* Function:
01890  *      _XEditResGetString8
01891  *
01892  * Parameters:
01893  *      stream - protocol stream
01894  *      str    - string to retrieve
01895  *
01896  * Description:
01897  *      Retrieves an 8 bit string value from the protocol stream.
01898  *
01899  * Returns:
01900  *      True if retrieval was successful
01901  */
01902 Bool
01903 _XEditResGetString8(ProtocolStream *stream, char **str)
01904 {
01905     unsigned short len;
01906     register unsigned i;
01907 
01908   if (!_XEditResGet16(stream, &len))
01909     return (False);
01910 
01911     *str = XtMalloc(sizeof(char) * (len + 1));
01912 
01913   for (i = 0; i < len; i++)
01914     {
01915       if (!_XEditResGet8(stream, (unsigned char *)*str + i))
01916         {
01917             XtFree(*str);
01918             *str = NULL;
01919           return (False);
01920         }
01921     }
01922   (*str)[i] = '\0';
01923 
01924   return (True);
01925 }
01926 
01927 /*
01928  * Function:
01929  *      _XEditResGetWidgetInfo
01930  *
01931  * Parameters:
01932  *      stream - protocol stream
01933  *      info   - widget info struct to store into
01934  *
01935  * Description:
01936  *        Retrieves the list of widgets that follow and stores them in the
01937  *      widget info structure provided.
01938  *
01939  * Returns:
01940  *      True if retrieval was successful
01941  */
01942 Bool
01943 _XEditResGetWidgetInfo(ProtocolStream *stream, WidgetInfo *info)
01944 {
01945     unsigned int i;
01946 
01947   if (!_XEditResGet16(stream, &info->num_widgets))
01948     return (False);
01949 
01950   info->ids = (unsigned long *)XtMalloc(sizeof(long) * info->num_widgets);
01951 
01952   for (i = 0; i < info->num_widgets; i++)
01953     {
01954       if (!_XEditResGet32(stream, info->ids + i))
01955         {
01956             XtFree((char *)info->ids);
01957             info->ids = NULL;
01958           return (False);
01959         }
01960 #if defined(LONG64) || defined(WORD64)
01961         info->ids[i] |= globals.base_address;
01962 #endif
01963     }
01964   return (True);
01965 }
01966             
01967 /************************************************************
01968  * Code for Loading the EditresBlock resource
01969  ************************************************************/
01970 /*
01971  * Function:
01972  *      CvStringToBlock
01973  *
01974  * Parameters:
01975  *      dpy            - display
01976  *      args           - unused
01977  *      num_args       - unused
01978  *      from_val       - value to convert
01979  *      to_val         - where to store
01980  *      converter_data - unused
01981  *
01982  * Description:
01983  *      Converts a string to an editres block value.
01984  *
01985  * Returns:
01986  *      True if conversion was sucessful
01987  */
01988 /*ARGSUSED*/
01989 static Boolean
01990 CvtStringToBlock(Display *dpy, XrmValue *args, Cardinal *num_args,
01991                  XrmValue *from_val, XrmValue *to_val,
01992                  XtPointer *converter_data)
01993 {
01994     char ptr[16];
01995     static EditresBlock block;
01996 
01997     XmuNCopyISOLatin1Lowered(ptr, from_val->addr, sizeof(ptr));
01998 
01999     if (streq(ptr, "none")) 
02000         block = BlockNone;
02001     else if (streq(ptr, "setvalues")) 
02002         block = BlockSetValues;
02003     else if (streq(ptr, "all")) 
02004         block = BlockAll;
02005   else
02006     {
02007         Cardinal num_params = 1;
02008         String params[1];
02009 
02010         params[0] = from_val->addr;
02011         XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
02012                         "CvtStringToBlock", "unknownValue", "EditresError",
02013                         "Could not convert string \"%s\" to EditresBlock.",
02014                         params, &num_params);
02015         return FALSE;
02016     }
02017 
02018   if (to_val->addr != NULL)
02019     {
02020       if (to_val->size < sizeof(EditresBlock))
02021         {
02022             to_val->size = sizeof(EditresBlock);
02023             return FALSE;
02024         }
02025         *(EditresBlock *)(to_val->addr) = block;
02026     }
02027     else 
02028     to_val->addr = (XtPointer)block;
02029 
02030     to_val->size = sizeof(EditresBlock);
02031     return TRUE;
02032 }
02033 
02034 #define XtREditresBlock         "EditresBlock"
02035 /*
02036  * Function:
02037  *      LoadResources
02038  *
02039  * Parameters:
02040  *      w - any widget in the tree
02041  *
02042  * Description:
02043  *        Loads a global resource the determines of this application should
02044  *      allow Editres requests.
02045  */
02046 static void
02047 LoadResources(Widget w)
02048 {
02049     static XtResource resources[] = {
02050         {"editresBlock", "EditresBlock", XtREditresBlock, sizeof(EditresBlock),
02051      XtOffsetOf(Globals, block), XtRImmediate, (XtPointer)BlockNone}
02052     };
02053 
02054   for (; XtParent(w) != NULL; w = XtParent(w))
02055     ;
02056 
02057     XtAppSetTypeConverter(XtWidgetToApplicationContext(w),
02058                           XtRString, XtREditresBlock, CvtStringToBlock,
02059                         NULL, 0, XtCacheAll, NULL);
02060 
02061   XtGetApplicationResources(w, (XtPointer)&globals, resources,
02062                             XtNumber(resources), NULL, 0);
02063 }
02064 
02065 /*
02066  * Function:
02067  *      _XEditresGetStringValues
02068  *
02069  * Parameters:
02070  *      w       - widget
02071  *      warg    - where to store result
02072  *      numargs - unused
02073  */
02074 /*ARGSUSED*/
02075 static void
02076 _XEditresGetStringValues(Widget w, Arg *warg, int numargs)
02077 {
02078   static char buffer[32];
02079   XtResourceList res_list;
02080   Cardinal num_res;
02081   XtResource *res = NULL;
02082   long value;
02083   Cardinal i;
02084   char *string = "";
02085   Arg args[1];
02086   XrmValue to, from;
02087 
02088   /*
02089    * Look for the resource
02090    */
02091   XtGetResourceList(XtClass(w), &res_list, &num_res);
02092   for (i = 0; i < num_res; i++)
02093     if (strcmp(res_list[i].resource_name, warg->name) == 0)
02094       {
02095         res = &res_list[i];
02096         break;
02097       }
02098 
02099   if (res == NULL && XtParent(w) != NULL)
02100     {
02101       XtFree((char *)res_list);
02102       XtGetConstraintResourceList(XtClass(XtParent(w)), &res_list, &num_res);
02103       for (i = 0; i < num_res; i++)
02104         if (strcmp(res_list[i].resource_name, warg->name) == 0)
02105           {
02106             res = &res_list[i];
02107             break;
02108           }
02109     }
02110 
02111   if (res == NULL)
02112     {
02113       /* Couldn't find resource */
02114     
02115       XtFree((char *)res_list);
02116       *(XtPointer *)warg->value = NULL;
02117       return;
02118     }
02119 
02120   /* try to get the value in the proper size */
02121   switch (res->resource_size)
02122     {
02123 #ifdef LONG_64
02124       long v8;
02125 #endif
02126       int v4;
02127       short v2;
02128       char v1;
02129 
02130     case 1:
02131       XtSetArg(args[0], res->resource_name, &v1);
02132       XtGetValues(w, args, 1);
02133       value = (int)v1;
02134       break;
02135     case 2:
02136       XtSetArg(args[0], res->resource_name, &v2);
02137       XtGetValues(w, args, 1);
02138       value = (int)v2;
02139       break;
02140     case 4:
02141       XtSetArg(args[0], res->resource_name, &v4);
02142       XtGetValues(w, args, 1);
02143       value = (int)v4;
02144       break;
02145 #ifdef LONG_64
02146     case 8:
02147       XtSetArg(args[0], res->resource_name, &v8);
02148       XtGetValues(w, args, 1);
02149       value = (long)v8;
02150       break;
02151 #endif
02152     default:
02153       fprintf(stderr, "_XEditresGetStringValues: bad size %d\n",
02154               res->resource_size);
02155       string = "bad size";
02156       *(char **)(warg->value) = string;
02157       XtFree((char *)res_list);
02158       return;
02159     }
02160 
02161   /*
02162    * If the resource is already String, no conversion needed
02163    */
02164   if (strcmp(XtRString, res->resource_type) == 0)
02165     {
02166       if (value == 0)
02167         string = "(null)";
02168       else
02169         string = (char *)value;
02170     }
02171   else
02172     {
02173       from.size = res->resource_size;
02174       from.addr = (XPointer)&value;
02175       to.addr = NULL;
02176       to.size = 0;
02177 
02178       if (XtConvertAndStore(w,res->resource_type, &from, XtRString, &to))
02179         string = to.addr;
02180       else
02181         {
02182           string = buffer;
02183           /*
02184            * Conversion failed, fall back to representing it as integer
02185            */
02186           switch (res->resource_size)
02187             {
02188             case sizeof(char):
02189               XmuSnprintf(buffer, sizeof(buffer), "%d", (int)(value & 0xff));
02190               break;
02191             case sizeof(short):
02192               XmuSnprintf(buffer, sizeof(buffer), "%d", (int)(value & 0xffff));
02193               break;
02194             case sizeof(int):
02195               XmuSnprintf(buffer, sizeof(buffer), "0x%08x", (int)value);
02196               break;
02197 #ifdef LONG_64
02198             case sizeof(long):
02199               XmuSnprintf(buffer, sizeof(buffer), "0x%016lx", value);
02200               break;
02201 #endif
02202             }
02203         }
02204     }
02205 
02206   if (string == NULL)
02207     string = "";
02208 
02209   *(char **)(warg->value) = string;
02210   XtFree((char *)res_list);
02211 }

Generated on Sun Mar 4 15:03:56 2007 for Scilab [trunk] by  doxygen 1.5.1