home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / editres / comm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-04  |  21.6 KB  |  847 lines

  1. /* $XConsortium: comm.c,v 1.19 91/04/04 21:35:16 gildea Exp $ */
  2. /*
  3.  * Copyright 1990 Massachusetts Institute of Technology
  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, and that the name of M.I.T. not be used in advertising or
  10.  * publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.  M.I.T. makes no representations about the
  12.  * suitability of this software for any purpose.  It is provided "as is"
  13.  * without express or implied warranty.
  14.  */
  15.  
  16. /*
  17.  * This file contains the code to communicate with the client that is
  18.  * being edited.
  19.  */
  20.  
  21. #include <X11/Intrinsic.h>
  22. #include <X11/StringDefs.h>    /* Get standard string definitions. */
  23. #include <X11/Xatom.h>
  24. #include <X11/cursorfont.h>    /* For crosshair cursor. */
  25. #include <X11/Xproto.h>
  26. #include <X11/Xos.h>        /* for XtNewString */
  27.  
  28. #include <stdio.h>
  29. #include <X11/Xmu/Error.h>
  30.  
  31. #include "editresP.h"
  32.  
  33. /*
  34.  * static Globals.
  35.  */
  36.  
  37. static Atom atom_comm, atom_command, atom_resource_editor, atom_client_value;
  38. static Atom atom_editres_protocol;
  39.  
  40. /*
  41.  * external function definitions.
  42.  */
  43.  
  44. extern ResIdent GetNewIdent();
  45. extern void SetMessage(), BuildVisualTree(),DisplayChild();
  46. extern char * GetFormattedSetValuesError(), *HandleFlashWidget();
  47. extern char * HandleGetResources(),  *PrintSetValuesError();
  48. char * GetFailureMessage(), * ProtocolFailure();
  49. extern int HandleXErrors();
  50.  
  51. static void TellUserAboutMessage(), BuildHeader(), FreeEvent();
  52. static Event * BuildEvent();
  53. static char * DispatchEvent();
  54. static void GetClientValue();
  55. static void ClientTimedOut(), LoseSelection(), SelectionDone();
  56. static Boolean ConvertCommand();
  57.  
  58.  
  59. /*    Function Name: ClientTimedOut
  60.  *    Description: Called if the client takes too long to take our selection.
  61.  *    Arguments: data - The widget that owns the client 
  62.  *                        communication selection.
  63.  *                 id - *** UNUSED ***
  64.  *    Returns: none.
  65.  */
  66.  
  67. /* ARGSUSED */
  68. static void
  69. ClientTimedOut(data, id)
  70. XtPointer data;
  71. XtIntervalId * id;
  72. {
  73.     char msg[BUFSIZ];
  74.     Widget w = (Widget) data;
  75.     
  76.     global_client.ident = NO_IDENT;
  77.     XtDisownSelection(w, global_client.atom, 
  78.               XtLastTimestampProcessed(XtDisplay(w)));
  79.  
  80.     sprintf(msg, "It appears that this client does not understand\n%s",
  81.         "the Editres Protocol.");
  82.     SetMessage(global_screen_data.info_label, msg);
  83. }
  84.  
  85. /*    Function Name: GetClientWindow
  86.  *    Description: Gets the Client's window by asking the user.
  87.  *    Arguments: w - a widget.
  88.  *    Returns: a clients window, or None.
  89.  */
  90.  
  91. Window 
  92. GetClientWindow(w, x, y)
  93. Widget w;
  94. int *x, *y;
  95. {
  96.     int status;
  97.     Cursor cursor;
  98.     XEvent event;
  99.     int buttons = 0;
  100.     Display * dpy = XtDisplayOfObject(w);
  101.     Window target_win = None, root = RootWindowOfScreen(XtScreenOfObject(w));
  102.     XtAppContext app = XtWidgetToApplicationContext(w);
  103.     
  104.     /* Make the target cursor */
  105.     cursor = XCreateFontCursor(dpy, XC_crosshair);
  106.     
  107.     /* Grab the pointer using target cursor, letting it room all over */
  108.     status = XGrabPointer(dpy, root, False,
  109.                ButtonPressMask|ButtonReleaseMask, GrabModeSync,
  110.                GrabModeAsync, root, cursor, CurrentTime);
  111.     if (status != GrabSuccess) {
  112.     SetMessage(global_screen_data.info_label, "Can't grab the mouse.\n");
  113.     return(None);
  114.     }
  115.  
  116.     /* Let the user select a window... */
  117.     while ((target_win == None) || (buttons != 0)) {
  118.     /* allow one more event */
  119.     XAllowEvents(dpy, SyncPointer, CurrentTime);
  120.     XtAppNextEvent(app, &event);
  121.     switch (event.type) {
  122.     case ButtonPress:
  123.         if (event.xbutton.window != root) {
  124.         XtDispatchEvent(&event);
  125.         break;
  126.         }
  127.  
  128.         if (target_win == None) {
  129.         target_win = event.xbutton.subwindow; /* window selected */
  130.         if (x != NULL)
  131.             *x = event.xbutton.x_root;
  132.         if (y != NULL)
  133.             *y = event.xbutton.y_root;
  134.         }
  135.         buttons++;
  136.         break;
  137.     case ButtonRelease:
  138.         if (event.xbutton.window != root) {
  139.         XtDispatchEvent(&event);
  140.         break;
  141.         }
  142.  
  143.         if (buttons > 0) /* There may have been some
  144.                 down before we started */
  145.         buttons--;
  146.         break;
  147.     default:
  148.         XtDispatchEvent(&event);
  149.         break;
  150.     }
  151.     } 
  152.     
  153.     XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
  154.  
  155.     return(XmuClientWindow(dpy, target_win));
  156. }
  157.  
  158. /*    Function Name: SetCommand
  159.  *    Description: Causes this widget to own the resource editor's 
  160.  *                   command selection.
  161.  *    Arguments: w - the widget that will own the selection.
  162.  *                 command - command to send to client.
  163.  *                 msg - message to prompt the user to select a client.
  164.  *    Returns: none.
  165.  */
  166.  
  167. /* ARGSUSED */
  168. void
  169. SetCommand(w, command, msg)
  170. Widget w;
  171. ResCommand command;
  172. char * msg;
  173. {
  174.     XClientMessageEvent client_event;
  175.     Display * dpy = XtDisplay(w);
  176.     
  177.     if (msg == NULL) 
  178.     msg = "Click the mouse pointer on any Xaw client.";
  179.  
  180.     SetMessage(global_screen_data.info_label, msg);
  181.           
  182.     if (global_client.window == None) {
  183.     if ( (global_client.window = GetClientWindow(w, NULL, NULL)) == None) 
  184.         return;
  185.     }
  186.  
  187.     global_client.ident = GetNewIdent();
  188.     
  189.     global_client.command = command;
  190.     global_client.atom = atom_comm;
  191.  
  192.     BuildHeader(&(global_client)); 
  193.  
  194.     if (!XtOwnSelection(w, global_client.atom, CurrentTime, ConvertCommand, 
  195.             LoseSelection, SelectionDone))
  196.     SetMessage(global_screen_data.info_label,
  197.            "Unable to own the Resource Selection");
  198.  
  199.     client_event.window = global_client.window;
  200.     client_event.type = ClientMessage;
  201.     client_event.message_type = atom_resource_editor;
  202.     client_event.format = EDITRES_SEND_EVENT_FORMAT;
  203.     client_event.data.l[0] = XtLastTimestampProcessed(dpy);
  204.     client_event.data.l[1] = global_client.atom;
  205.     client_event.data.l[2] = (long) global_client.ident;
  206.     client_event.data.l[3] = CURRENT_PROTOCOL_VERSION;
  207.  
  208.     global_error_code = NO_ERROR;                 /* Reset Error code. */
  209.     global_old_error_handler = XSetErrorHandler(HandleXErrors);
  210.     global_serial_num = NextRequest(dpy);
  211.  
  212.     XSendEvent(dpy, global_client.window, FALSE, (long) 0, 
  213.            (XEvent *) &client_event);
  214.  
  215.     XSync(dpy, FALSE);
  216.     XSetErrorHandler(global_old_error_handler);
  217.     if (global_error_code == NO_WINDOW) {
  218.     char error_buf[BUFSIZ];
  219.     
  220.     global_error_code = NO_ERROR;    /* Reset Error code. */
  221.     sprintf(error_buf, "The communication window with%s%s.",
  222.         " application is no longer avaliable\n",
  223.         "Please select the application manually");
  224.  
  225.     global_client.window = None;
  226.     SetCommand(w, command, error_buf);
  227.     return;
  228.     }   
  229.            
  230.     TellUserAboutMessage(global_screen_data.info_label, command);
  231.     global_client.timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  232.                         CLIENT_TIME_OUT, 
  233.                         ClientTimedOut, (XtPointer) w);
  234. }
  235.  
  236. /*    Function Name: TellUserAboutMessage
  237.  *    Description: Informs the user that we have sent a message to the client
  238.  *    Arguments: label - the info label.
  239.  *                 command - command that we have executed.
  240.  *    Returns: none.
  241.  */
  242.  
  243. static void
  244. TellUserAboutMessage(label, command)
  245. Widget label;
  246. ResCommand command;
  247. {
  248.     char msg[BUFSIZ], *str;
  249.  
  250.     switch(command) {
  251.     case LocalSendWidgetTree:
  252.     str = " asking for widget tree";
  253.     break;
  254.     case LocalSetValues:
  255.     str = " asking it to perform SetValues()";
  256.     break;
  257.     case LocalFlashWidget:
  258.     case LocalGetGeometry:
  259.     str = " asking it to perform GetGeometry()";
  260.     break;
  261.     case LocalGetResources:
  262.     str = " asking it to get a widget's resource list";
  263.     break;
  264.     case LocalFindChild:
  265.     str = " asking it to find the child Widget.";
  266.     break;
  267.     default:
  268.     str = "";
  269.     break;
  270.     }
  271.  
  272.     sprintf(msg, "Message sent to client%s.", str);
  273.     SetMessage(label, msg);
  274. }
  275.  
  276. /*    Function Name: ConvertCommand
  277.  *    Description: Converts the command string into a selection that can
  278.  *                   be sent to the client.
  279.  *    Arguments: (see Xt)
  280.  *    Returns: TRUE if we could convert the selection and target asked for.
  281.  */
  282.  
  283. /* ARGSUSED */
  284. static Boolean
  285. ConvertCommand(w,selection,target,type_ret, value_ret, length_ret, format_ret)
  286. Widget w;
  287. Atom * selection, * target, * type_ret;
  288. XtPointer *value_ret;
  289. unsigned long * length_ret;
  290. int * format_ret;
  291. {
  292.     if ((*selection != atom_comm) || (*target != atom_command))
  293.     return(FALSE);
  294.  
  295.     *type_ret = atom_editres_protocol;
  296.     *value_ret = (XtPointer) global_client.stream.real_top;
  297.     *length_ret = global_client.stream.size + HEADER_SIZE;
  298.     *format_ret = EDITRES_FORMAT;
  299.     
  300.     return(TRUE);
  301. }
  302.  
  303. /*    Function Name: SelectionDone
  304.  *    Description: done with the selection.
  305.  *    Arguments: *** UNUSED ***
  306.  *    Returns: none.
  307.  */
  308.  
  309. /* ARGSUSED */
  310. static void
  311. SelectionDone(w, sel, targ)
  312.     Widget w;
  313.     Atom *sel, *targ;
  314. {
  315.     /* Keep the toolkit from automaticaly freeing the selection value */
  316. }
  317.  
  318. /*    Function Name: LoseSelection
  319.  *    Description: Called when we have lost the selection, asks client
  320.  *                   for the selection value.
  321.  *    Arguments: w - the widget that just lost the selection.
  322.  *                 sel - the selection.
  323.  *    Returns: none.
  324.  */
  325.  
  326. static void
  327. LoseSelection(w, sel)
  328. Widget w;
  329. Atom * sel;
  330. {
  331.     if (global_client.timeout != 0) {
  332.     XtRemoveTimeOut(global_client.timeout);
  333.     global_client.timeout = 0;
  334.     }
  335.  
  336.     XtGetSelectionValue(w, *sel, atom_client_value, GetClientValue,
  337.             NULL, XtLastTimestampProcessed(XtDisplay(w)));
  338. }
  339.  
  340. /*    Function Name: GetClientValue
  341.  *    Description: Gets the value out of the client, and does good things
  342.  *                   to it.
  343.  *    Arguments: w - the widget that asked for the selection.
  344.  *                 data - client_data *** UNUSED ***.
  345.  *                 sel - the selection.
  346.  *                 type - the type of the selection.
  347.  *                 value - the selection's value.
  348.  *                 length - the length of the selection's value.
  349.  *                 format - the format of the selection.
  350.  *    Returns: none.
  351.  */
  352.  
  353.  
  354. /* ARGSUSED */
  355. static void
  356. GetClientValue(w, data, selection, type, value, length, format)
  357. Widget w;
  358. XtPointer data, value;
  359. Atom *selection, *type;
  360. unsigned long *length;
  361. int * format;
  362. {
  363.     Event * event;
  364.     ProtocolStream alloc_stream, *stream;
  365.     unsigned char ident, error_code;
  366.     char * error_str, msg[BUFSIZ];
  367.  
  368.     if (*length == 0)
  369.     return;
  370.  
  371.     stream = &alloc_stream;    /* easier to think of it this way... */
  372.  
  373.     stream->current = stream->top = (unsigned char *) value;
  374.     stream->size = HEADER_SIZE;        /* size of header. */
  375.  
  376.     /*
  377.      * Retrieve the Header.
  378.      */
  379.  
  380.     if (*length < HEADER_SIZE) {
  381.     SetMessage(global_screen_data.info_label,
  382.            "Incorrectly formatted message from client.");
  383.     return;
  384.     }
  385.  
  386.     (void) _XEditResGet8(stream, &ident);
  387.     if (global_client.ident != ident) {
  388. #ifdef DEBUG
  389.     if (global_resources.debug)
  390.         printf("Incorrect ident from client.\n");
  391. #endif 
  392.     if (!XtOwnSelection(w, *selection, CurrentTime, ConvertCommand, 
  393.                 LoseSelection, SelectionDone))
  394.         SetMessage(global_screen_data.info_label,
  395.                "Unable to own the Resource Editor Command Selection");
  396.     return;
  397.     }
  398.  
  399.     (void) _XEditResGet8(stream, &error_code); 
  400.     (void) _XEditResGet32(stream, &(stream->size));
  401.     stream->top = stream->current; /* reset stream to top of value.*/
  402.  
  403.     switch ((int) error_code) {
  404.     case PartialSuccess:
  405.     if ((event = BuildEvent(stream)) != NULL) {
  406.         error_str = DispatchEvent(event);
  407.         FreeEvent(event);
  408.     }
  409.     else {
  410.         sprintf(msg, "Unable to unpack protocol request.");
  411.         error_str = XtNewString(msg);
  412.     }
  413.     break;
  414.     case Failure:
  415.     error_str = GetFailureMessage(stream);
  416.     break;
  417.     case ProtocolMismatch:
  418.     error_str = ProtocolFailure(stream);
  419.     break;
  420.     default:
  421.     sprintf(msg, "Unknown Error code %d", (int) error_code);
  422.     SetMessage(global_screen_data.info_label, msg);
  423.     break;
  424.     }
  425.  
  426.     if (error_str == NULL) {
  427.     WNode * top;
  428.     
  429.     if (global_tree_info == NULL)
  430.         return;
  431.     
  432.     top = global_tree_info->top_node;
  433.     sprintf(msg, "Widget Tree for client %s(%s).", top->name, top->class);
  434.     SetMessage(global_screen_data.info_label, msg);
  435.     return;
  436.     }
  437.     SetMessage(global_screen_data.info_label, error_str);
  438.     XtFree(error_str);
  439. }
  440.  
  441. /*    Function Name: BuildHeader
  442.  *    Description: Puts the header into the message.
  443.  *    Arguments: client_data - the client data.
  444.  *    Returns: none.
  445.  */
  446.  
  447. static void
  448. BuildHeader(client_data)
  449. CurrentClient * client_data;
  450. {
  451.     unsigned long old_alloc, old_size;
  452.     unsigned char * old_current;
  453.     EditresCommand command;
  454.     ProtocolStream * stream = &(client_data->stream);
  455.  
  456.     /*
  457.      * We have cleverly keep enough space at the top of the header
  458.      * for the return protocol stream, so all we have to do is
  459.      * fill in the space.
  460.      */
  461.  
  462.     /* 
  463.      * Fool the insert routines into putting the header in the right
  464.      * place while being damn sure not to realloc (that would be very bad.
  465.      */
  466.     
  467.     old_current = stream->current;
  468.     old_alloc = stream->alloc;
  469.     old_size = stream->size;
  470.  
  471.     stream->current = stream->real_top;
  472.     stream->alloc = stream->size + (2 * HEADER_SIZE);    
  473.     
  474.     _XEditResPut8(stream, client_data->ident);
  475.     switch(client_data->command) {
  476.     case LocalSendWidgetTree:
  477.     command = SendWidgetTree;
  478.     break;
  479.     case LocalSetValues:
  480.     command = SetValues;
  481.     break;
  482.     case LocalFlashWidget:
  483.     command = GetGeometry;
  484.     break;
  485.     case LocalGetResources:
  486.     command = GetResources;
  487.     break;
  488.     case LocalFindChild:
  489.     command = FindChild;
  490.     break;
  491.     default:
  492.     command = SendWidgetTree;
  493.     break;
  494.     }
  495.                   
  496.     _XEditResPut8(stream, (unsigned char) command);
  497.     _XEditResPut32(stream, old_size);
  498.  
  499.     stream->alloc = old_alloc;
  500.     stream->current = old_current;
  501.     stream->size = old_size;
  502. }
  503.  
  504. /*    Function Name: BuildEvent
  505.  *    Description: Builds the event structure from the 
  506.  *    Arguments: stream - the protocol data stream.
  507.  *    Returns: event - the event.
  508.  */
  509.  
  510. static Event * 
  511. BuildEvent(stream)
  512. ProtocolStream * stream;
  513. {
  514.     int i;
  515.     Event * event = (Event *) XtCalloc(sizeof(Event), 1);
  516.  
  517.     /*
  518.      * The return value will be different depending upon the
  519.      * request sent out.
  520.      */
  521.  
  522.     switch(global_client.command) {
  523.     case LocalSendWidgetTree:
  524.         {
  525.         SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  526.  
  527.         send_event->type = SendWidgetTree;
  528.  
  529.         if (!_XEditResGet16(stream, &(send_event->num_entries)))
  530.         goto done;
  531.         
  532.         send_event->info = (WidgetTreeInfo *)
  533.                         XtCalloc(sizeof(WidgetTreeInfo),
  534.                      send_event->num_entries);
  535.  
  536.         for (i = 0; i < (int)send_event->num_entries; i++) {
  537.         WidgetTreeInfo * info = send_event->info + i;
  538.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  539.               _XEditResGetString8(stream, &(info->name)) &&
  540.               _XEditResGetString8(stream, &(info->class)) &&
  541.               _XEditResGet32(stream, &(info->window)))) 
  542.         {
  543.             goto done;
  544.         }
  545.         }
  546.     }
  547.     break;
  548.     case LocalSetValues:
  549.         {
  550.         SetValuesEvent * sv_event = (SetValuesEvent *) event;
  551.  
  552.         sv_event->type = SetValues;
  553.  
  554.         if (!_XEditResGet16(stream, &(sv_event->num_entries)))
  555.         goto done;
  556.         
  557.         sv_event->info = (SetValuesInfo *) XtCalloc(sizeof(SetValuesInfo),
  558.                             sv_event->num_entries);
  559.  
  560.         for (i = 0; i < (int)sv_event->num_entries; i++) {
  561.         SetValuesInfo * info = sv_event->info + i;
  562.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  563.               _XEditResGetString8(stream, &(info->message))))
  564.         {
  565.             goto done;
  566.         }
  567.         }
  568.     }
  569.     break;
  570.     case LocalGetResources:
  571.         {
  572.         GetResourcesEvent * res_event = (GetResourcesEvent *) event;
  573.         
  574.         res_event->type = GetGeometry;
  575.  
  576.         if (!_XEditResGet16(stream, &(res_event->num_entries)))
  577.         goto done;
  578.  
  579.         res_event->info = (GetResourcesInfo *) 
  580.                            XtCalloc(sizeof(GetResourcesInfo),
  581.                         res_event->num_entries);
  582.  
  583.         for (i = 0; i < (int)res_event->num_entries; i++) {
  584.         GetResourcesInfo * res_info = res_event->info + i;
  585.         if (!(_XEditResGetWidgetInfo(stream, &(res_info->widgets)) &&
  586.               _XEditResGetBoolean(stream, &(res_info->error))))
  587.         {
  588.             goto done;
  589.         }
  590.         if (res_info->error) {
  591.             if (!_XEditResGetString8(stream, &(res_info->message))) 
  592.             goto done;
  593.         }
  594.         else {
  595.             unsigned int j;
  596.  
  597.             if (!_XEditResGet16(stream, &(res_info->num_resources)))
  598.             goto done;
  599.  
  600.             res_info->res_info = (ResourceInfo *) 
  601.                               XtCalloc(sizeof(ResourceInfo),
  602.                            res_info->num_resources);
  603.  
  604.             for (j = 0; j < res_info->num_resources; j++) {
  605.             unsigned char temp;
  606.             ResourceInfo * info = res_info->res_info + j;
  607.             if (!(_XEditResGetResType(stream, &(temp)) &&
  608.                   _XEditResGetString8(stream, &(info->name)) &&
  609.                   _XEditResGetString8(stream, &(info->class)) &&
  610.                   _XEditResGetString8(stream, &(info->type))))
  611.             {
  612.                 goto done;
  613.             }
  614.             else
  615.                 info->res_type = (ResourceType) temp;
  616.             } /* for */
  617.         } /* else */
  618.         } /* for */
  619.     }
  620.     break;
  621.     case LocalFlashWidget:
  622.     case LocalGetGeometry:
  623.         {
  624.         GetGeomEvent * geom_event = (GetGeomEvent *) event;
  625.  
  626.         geom_event->type = GetGeometry;
  627.  
  628.         if (!_XEditResGet16(stream, &(geom_event->num_entries)))
  629.         goto done;
  630.         
  631.         geom_event->info = (GetGeomInfo *) XtCalloc(sizeof(GetGeomInfo),
  632.                               geom_event->num_entries);
  633.  
  634.         for (i = 0; i < (int)geom_event->num_entries; i++) {
  635.         GetGeomInfo * info = geom_event->info + i;
  636.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  637.               _XEditResGetBoolean(stream, &(info->error))))
  638.         {
  639.             goto done;
  640.         }
  641.         if (info->error) {
  642.             if (!_XEditResGetString8(stream, &(info->message)))
  643.             goto done;
  644.         }
  645.         else {
  646.             if (!(_XEditResGetBoolean(stream, &(info->visable)) &&
  647.               _XEditResGetSigned16(stream, &(info->x)) &&
  648.               _XEditResGetSigned16(stream, &(info->y)) &&
  649.               _XEditResGet16(stream, &(info->width)) &&
  650.               _XEditResGet16(stream, &(info->height)) &&
  651.               _XEditResGet16(stream, &(info->border_width))))
  652.             {
  653.             goto done;
  654.             }
  655.         }
  656.         }
  657.     }
  658.     break;
  659.     case LocalFindChild:
  660.         {
  661.         FindChildEvent * find_event = (FindChildEvent *) event;
  662.  
  663.         find_event->type = FindChild;
  664.  
  665.         if (!_XEditResGetWidgetInfo(stream, &(find_event->widgets)))
  666.         goto done;
  667.     }
  668.     break;
  669.     default:
  670.     goto done;
  671.     }
  672.  
  673.     return(event);
  674.  
  675.  done:
  676.     FreeEvent(event);
  677.     return(NULL);
  678. }
  679.  
  680.  
  681. /*    Function Name: FreeEvent
  682.  *    Description: Frees all memory associated with the event. 
  683.  *    Arguments: event - the event.
  684.  *    Returns: none.
  685.  *
  686.  * NOTE: XtFree() returns w/o freeing if ptr is NULL.
  687.  */
  688.  
  689. static void
  690. FreeEvent(event)
  691. Event * event;
  692. {
  693.     unsigned int i;
  694.  
  695.     switch(event->any_event.type) {
  696.     case SendWidgetTree:
  697.         {
  698.         SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  699.         WidgetTreeInfo * info = send_event->info;
  700.         
  701.         if (info != NULL) {
  702.         for (i = 0; i < send_event->num_entries; i++, info++) {
  703.             XtFree((char *)info->widgets.ids);
  704.             XtFree(info->name);
  705.             XtFree(info->class);
  706.         }
  707.         XtFree((char *)send_event->info);
  708.         }
  709.     }
  710.     break;
  711.     case SetValues:
  712.         {
  713.         SetValuesEvent * sv_event = (SetValuesEvent *) event;
  714.         SetValuesInfo * info = sv_event->info;
  715.         
  716.         if (info != NULL) {
  717.         for (i = 0; i < sv_event->num_entries; i++, info++) {
  718.             XtFree((char *)info->widgets.ids);
  719.             XtFree(info->message);
  720.         }
  721.         XtFree((char *)sv_event->info);
  722.         }
  723.     }
  724.     break;
  725.     case GetResources:
  726.         {
  727.         GetResourcesEvent * get_event = (GetResourcesEvent *) event;
  728.         GetResourcesInfo * info = get_event->info;
  729.  
  730.         if (info != NULL) {
  731.         for (i = 0; i < get_event->num_entries; i++, info++) {
  732.             XtFree((char *)info->widgets.ids);
  733.             if (info->error) 
  734.             XtFree(info->message);
  735.             else {
  736.             unsigned int j;
  737.             ResourceInfo * res_info = info->res_info;
  738.             
  739.             if (res_info != NULL) {
  740.                 for (j = 0; 
  741.                  j < info->num_resources; j++, res_info++) 
  742.                 {
  743.                 XtFree(res_info->name);
  744.                 XtFree(res_info->class);
  745.                 XtFree(res_info->type);
  746.                 }
  747.                 XtFree((char *)info->res_info);
  748.             }
  749.             }
  750.         } 
  751.         XtFree((char *)get_event->info);
  752.         }
  753.     }
  754.     break;
  755.     case GetGeometry:
  756.         {
  757.         GetGeomEvent * geom_event = (GetGeomEvent *) event;
  758.         GetGeomInfo * info = geom_event->info;
  759.  
  760.         if (info != NULL) {
  761.         for (i = 0; i < geom_event->num_entries; i++, info++) {
  762.             XtFree((char *)info->widgets.ids);
  763.             if (info->error) 
  764.             XtFree(info->message);
  765.         }
  766.         XtFree((char *)geom_event->info);
  767.         }
  768.     }
  769.     break;
  770.     case FindChild:
  771.         {
  772.         FindChildEvent * find_event = (FindChildEvent *) event;
  773.         
  774.         XtFree((char *)find_event->widgets.ids);
  775.     }
  776.     break;
  777.     default:
  778.     break;
  779.     }
  780. }
  781.  
  782. /*    Function Name: DispatchEvent
  783.  *    Description: Handles the event, calling the proper function.
  784.  *    Arguments: event - the event.
  785.  *    Returns: one.
  786.  */
  787.     
  788. static char *
  789. DispatchEvent(event)
  790. Event * event;
  791. {
  792.     char * error = NULL;
  793.  
  794.     switch(global_client.command) {
  795.     case LocalSendWidgetTree:
  796.     BuildVisualTree(global_tree_parent, event);
  797.     break;
  798.     case LocalSetValues:
  799.     error = PrintSetValuesError(event);
  800.     break;
  801.     case LocalFlashWidget:
  802.     error = HandleFlashWidget(event);
  803.     break;
  804.     case LocalGetResources:
  805.     error = HandleGetResources(event);
  806.     break;
  807.     case LocalFindChild:
  808.     DisplayChild(event);
  809.     break;
  810.     default:
  811.         {
  812.         char msg[BUFSIZ];
  813.         sprintf(msg, "Internal error: Unknown command %d.", 
  814.             global_client.command);
  815.         error = XtNewString(msg);
  816.     }
  817.     break;
  818.     }
  819.     return(error);
  820. }
  821.  
  822. /*    Function Name: InternAtoms
  823.  *    Description: interns all static atoms.
  824.  *    Arguments: display - the current display.
  825.  *    Returns: none.
  826.  */
  827.  
  828. void
  829. InternAtoms(dpy)
  830. Display * dpy;
  831. {
  832.     atom_comm = XInternAtom(dpy, EDITRES_COMM_ATOM, False);
  833.     atom_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False);
  834.     atom_resource_editor = XInternAtom(dpy, EDITRES_NAME, False);
  835.     atom_client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False);
  836.     atom_editres_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False);
  837. }
  838.  
  839. ResIdent
  840. GetNewIdent()
  841. {
  842.     static ResIdent ident = 1;
  843.  
  844.     return(ident++);
  845. }
  846.  
  847.