comm.c revision ad47b356
133c89af1Smrg/*
233c89af1Smrg
333c89af1SmrgCopyright 1990, 1998  The Open Group
433c89af1Smrg
533c89af1SmrgPermission to use, copy, modify, distribute, and sell this software and its
633c89af1Smrgdocumentation for any purpose is hereby granted without fee, provided that
733c89af1Smrgthe above copyright notice appear in all copies and that both that
833c89af1Smrgcopyright notice and this permission notice appear in supporting
933c89af1Smrgdocumentation.
1033c89af1Smrg
1133c89af1SmrgThe above copyright notice and this permission notice shall be included
1233c89af1Smrgin all copies or substantial portions of the Software.
1333c89af1Smrg
1433c89af1SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1533c89af1SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1633c89af1SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1733c89af1SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1833c89af1SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1933c89af1SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2033c89af1SmrgOTHER DEALINGS IN THE SOFTWARE.
2133c89af1Smrg
2233c89af1SmrgExcept as contained in this notice, the name of The Open Group shall
2333c89af1Smrgnot be used in advertising or otherwise to promote the sale, use or
2433c89af1Smrgother dealings in this Software without prior written authorization
2533c89af1Smrgfrom The Open Group.
2633c89af1Smrg
2733c89af1Smrg*/
2833c89af1Smrg
2933c89af1Smrg
3033c89af1Smrg/*
3133c89af1Smrg * This file contains the code to communicate with the client that is
3233c89af1Smrg * being edited.
3333c89af1Smrg */
3433c89af1Smrg
3533c89af1Smrg#include <X11/Intrinsic.h>
3633c89af1Smrg#include <X11/StringDefs.h>	/* Get standard string definitions. */
3733c89af1Smrg#include <X11/Xatom.h>
3833c89af1Smrg#include <X11/cursorfont.h>	/* For crosshair cursor. */
3933c89af1Smrg#include <X11/Xproto.h>
4033c89af1Smrg#include <X11/Xos.h>		/* for XtNewString */
4133c89af1Smrg
4233c89af1Smrg#include <stdio.h>
4333c89af1Smrg#include <X11/Xmu/Error.h>
4433c89af1Smrg#include <X11/Xmu/WinUtil.h>
4533c89af1Smrg
4633c89af1Smrg#include "editresP.h"
4733c89af1Smrg
4833c89af1Smrg/*
4933c89af1Smrg * static Globals.
5033c89af1Smrg */
5133c89af1Smrg
5233c89af1Smrgstatic Atom atom_comm, atom_command, atom_resource_editor, atom_client_value;
5333c89af1Smrgstatic Atom atom_editres_protocol;
5433c89af1Smrg
5533c89af1Smrgextern Widget CM_entries[NUM_CM_ENTRIES], TM_entries[NUM_TM_ENTRIES];
5633c89af1Smrg
5733c89af1Smrgstatic void ClientTimedOut ( XtPointer data, XtIntervalId * id );
5833c89af1Smrgstatic void TellUserAboutMessage ( Widget label, ResCommand command );
59ad47b356Smrgstatic Boolean ConvertCommand ( Widget w, Atom * selection, Atom * target,
60ad47b356Smrg				Atom * type_ret, XtPointer *value_ret,
6133c89af1Smrg				unsigned long * length_ret, int * format_ret );
6233c89af1Smrgstatic void SelectionDone ( Widget w, Atom *sel, Atom *targ );
6333c89af1Smrgstatic void LoseSelection ( Widget w, Atom * sel );
64ad47b356Smrgstatic void GetClientValue ( Widget w, XtPointer data, Atom *selection,
65ad47b356Smrg			     Atom *type, XtPointer value,
6633c89af1Smrg			     unsigned long *length, int * format );
6733c89af1Smrgstatic void BuildHeader ( CurrentClient * client_data );
6833c89af1Smrgstatic Event * BuildEvent ( ProtocolStream * stream );
6933c89af1Smrgstatic void FreeEvent ( Event * event );
7033c89af1Smrgstatic char * DispatchEvent ( Event * event );
7133c89af1Smrg
7233c89af1Smrg
7333c89af1Smrg
7433c89af1Smrg/*	Function Name: ClientTimedOut
7533c89af1Smrg *	Description: Called if the client takes too long to take our selection.
76ad47b356Smrg *	Arguments: data - The widget that owns the client
7733c89af1Smrg *                        communication selection.
7833c89af1Smrg *                 id - *** UNUSED ***
7933c89af1Smrg *	Returns: none.
8033c89af1Smrg */
8133c89af1Smrg
8233c89af1Smrg/* ARGSUSED */
8333c89af1Smrgstatic void
84278eca22SmrgClientTimedOut(XtPointer data, XtIntervalId *id)
8533c89af1Smrg{
8633c89af1Smrg  char msg[BUFSIZ];
8733c89af1Smrg  Widget w = (Widget) data;
88ad47b356Smrg
8933c89af1Smrg  global_client.ident = NO_IDENT;
90ad47b356Smrg  XtDisownSelection(w, global_client.atom,
9133c89af1Smrg		    XtLastTimestampProcessed(XtDisplay(w)));
92ad47b356Smrg
93ad47b356Smrg  snprintf(msg, sizeof(msg), res_labels[4], "the Editres Protocol.");
9433c89af1Smrg  SetMessage(global_screen_data.info_label, msg);
9533c89af1Smrg}
9633c89af1Smrg
9733c89af1Smrg
9833c89af1Smrg
9933c89af1Smrg/*	Function Name: GetClientWindow
10033c89af1Smrg *	Description: Gets the Client's window by asking the user.
10133c89af1Smrg *	Arguments: w - a widget.
10233c89af1Smrg *	Returns: a clients window, or None.
10333c89af1Smrg */
10433c89af1Smrg
105ad47b356SmrgWindow
106278eca22SmrgGetClientWindow(Widget w, int *x, int *y)
10733c89af1Smrg{
10833c89af1Smrg  int status;
10933c89af1Smrg  Cursor cursor;
11033c89af1Smrg  XEvent event;
11133c89af1Smrg  int buttons = 0;
11233c89af1Smrg  Display * dpy = XtDisplayOfObject(w);
11333c89af1Smrg  Window target_win = None, root = RootWindowOfScreen(XtScreenOfObject(w));
11433c89af1Smrg  XtAppContext app = XtWidgetToApplicationContext(w);
115ad47b356Smrg
11633c89af1Smrg  /* Make the target cursor */
11733c89af1Smrg  cursor = XCreateFontCursor(dpy, XC_crosshair);
118ad47b356Smrg
11933c89af1Smrg  /* Grab the pointer using target cursor, letting it room all over */
12033c89af1Smrg  status = XGrabPointer(dpy, root, False,
12133c89af1Smrg			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
12233c89af1Smrg			GrabModeAsync, root, cursor, CurrentTime);
12333c89af1Smrg  if (status != GrabSuccess) {
12433c89af1Smrg    SetMessage(global_screen_data.info_label, res_labels[5]);
12533c89af1Smrg    return(None);
12633c89af1Smrg  }
127ad47b356Smrg
12833c89af1Smrg  /* Let the user select a window... */
12933c89af1Smrg  while ((target_win == None) || (buttons != 0)) {
13033c89af1Smrg    /* allow one more event */
13133c89af1Smrg    XAllowEvents(dpy, SyncPointer, CurrentTime);
13233c89af1Smrg    XtAppNextEvent(app, &event);
13333c89af1Smrg    switch (event.type) {
13433c89af1Smrg    case ButtonPress:
13533c89af1Smrg      if (event.xbutton.window != root) {
13633c89af1Smrg	XtDispatchEvent(&event);
13733c89af1Smrg	break;
13833c89af1Smrg      }
139ad47b356Smrg
14033c89af1Smrg      if (target_win == None) {
14133c89af1Smrg	target_win = event.xbutton.subwindow; /* window selected */
14233c89af1Smrg	if (x != NULL)
14333c89af1Smrg	  *x = event.xbutton.x_root;
14433c89af1Smrg	if (y != NULL)
14533c89af1Smrg	  *y = event.xbutton.y_root;
14633c89af1Smrg      }
14733c89af1Smrg      buttons++;
14833c89af1Smrg      break;
14933c89af1Smrg    case ButtonRelease:
15033c89af1Smrg      if (event.xbutton.window != root) {
15133c89af1Smrg	XtDispatchEvent(&event);
15233c89af1Smrg	break;
15333c89af1Smrg      }
154ad47b356Smrg
15533c89af1Smrg      if (buttons > 0) /* There may have been some
15633c89af1Smrg			  down before we started */
15733c89af1Smrg	buttons--;
15833c89af1Smrg      break;
15933c89af1Smrg    default:
16033c89af1Smrg      XtDispatchEvent(&event);
16133c89af1Smrg      break;
16233c89af1Smrg    }
163ad47b356Smrg  }
164ad47b356Smrg
16533c89af1Smrg  XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
166ad47b356Smrg
16733c89af1Smrg  return(XmuClientWindow(dpy, target_win));
16833c89af1Smrg}
16933c89af1Smrg
17033c89af1Smrg
17133c89af1Smrg
17233c89af1Smrg/*	Function Name: SetCommand
173ad47b356Smrg *	Description: Causes this widget to own the resource editor's
17433c89af1Smrg *                   command selection.
17533c89af1Smrg *	Arguments: w - the widget that will own the selection.
17633c89af1Smrg *                 command - command to send to client.
17733c89af1Smrg *                 msg - message to prompt the user to select a client.
17833c89af1Smrg *	Returns: none.
17933c89af1Smrg */
18033c89af1Smrg
18133c89af1Smrg/* ARGSUSED */
18233c89af1Smrgvoid
183278eca22SmrgSetCommand(Widget w, ResCommand command, char *msg)
18433c89af1Smrg{
18533c89af1Smrg  XClientMessageEvent client_event;
18633c89af1Smrg  Display * dpy = XtDisplay(w);
187ad47b356Smrg
188ad47b356Smrg  if (msg == NULL)
18933c89af1Smrg    msg = res_labels[6];
190ad47b356Smrg
19133c89af1Smrg  SetMessage(global_screen_data.info_label, msg);
192ad47b356Smrg
19333c89af1Smrg  if (global_client.window == None)
194ad47b356Smrg    if ( (global_client.window = GetClientWindow(w, NULL, NULL)) == None)
19533c89af1Smrg      return;
19633c89af1Smrg
19733c89af1Smrg  global_client.ident = GetNewIdent();
198ad47b356Smrg
19933c89af1Smrg  global_client.command = command;
20033c89af1Smrg  global_client.atom = atom_comm;
20133c89af1Smrg
202ad47b356Smrg  BuildHeader(&(global_client));
20333c89af1Smrg
204ad47b356Smrg  if (!XtOwnSelection(w, global_client.atom, CurrentTime, ConvertCommand,
20533c89af1Smrg		      LoseSelection, SelectionDone))
20633c89af1Smrg    SetMessage(global_screen_data.info_label,
20733c89af1Smrg	       res_labels[7]);
20833c89af1Smrg
20933c89af1Smrg  client_event.window = global_client.window;
21033c89af1Smrg  client_event.type = ClientMessage;
21133c89af1Smrg  client_event.message_type = atom_resource_editor;
21233c89af1Smrg  client_event.format = EDITRES_SEND_EVENT_FORMAT;
21333c89af1Smrg  client_event.data.l[0] = XtLastTimestampProcessed(dpy);
21433c89af1Smrg  client_event.data.l[1] = global_client.atom;
21533c89af1Smrg  client_event.data.l[2] = (long) global_client.ident;
21633c89af1Smrg  client_event.data.l[3] = global_effective_protocol_version;
217ad47b356Smrg
21833c89af1Smrg  global_error_code = NO_ERROR;                 /* Reset Error code. */
21933c89af1Smrg  global_old_error_handler = XSetErrorHandler(HandleXErrors);
22033c89af1Smrg  global_serial_num = NextRequest(dpy);
221ad47b356Smrg
222ad47b356Smrg  XSendEvent(dpy, global_client.window, FALSE, (long) 0,
22333c89af1Smrg	     (XEvent *) &client_event);
224ad47b356Smrg
22533c89af1Smrg  XSync(dpy, FALSE);
22633c89af1Smrg  XSetErrorHandler(global_old_error_handler);
22733c89af1Smrg  if (global_error_code == NO_WINDOW) {
228ad47b356Smrg    char error_buf[BUFSIZ] =
229ad47b356Smrg        "The communication window with the"
230ad47b356Smrg        " application is no longer available\n"
231ad47b356Smrg        "Please select a new widget tree.";
232ad47b356Smrg
23333c89af1Smrg    global_error_code = NO_ERROR;	/* Reset Error code. */
23433c89af1Smrg    global_client.window = None;
23533c89af1Smrg    SetCommand(w, LocalSendWidgetTree, error_buf);
23633c89af1Smrg    return;
237ad47b356Smrg  }
238ad47b356Smrg
23933c89af1Smrg  TellUserAboutMessage(global_screen_data.info_label, command);
24033c89af1Smrg  global_client.timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
241ad47b356Smrg					  CLIENT_TIME_OUT,
24233c89af1Smrg					  ClientTimedOut, (XtPointer) w);
24333c89af1Smrg}
24433c89af1Smrg
24533c89af1Smrg
24633c89af1Smrg
24733c89af1Smrg/*	Function Name: TellUserAboutMessage
24833c89af1Smrg *	Description: Informs the user that we have sent a message to the client
24933c89af1Smrg *	Arguments: label - the info label.
25033c89af1Smrg *                 command - command that we have executed.
25133c89af1Smrg *	Returns: none.
25233c89af1Smrg */
25333c89af1Smrg
25433c89af1Smrgstatic void
255278eca22SmrgTellUserAboutMessage(Widget label, ResCommand command)
25633c89af1Smrg{
25733c89af1Smrg    char msg[BUFSIZ], *str;
25833c89af1Smrg
25933c89af1Smrg    switch(command) {
26033c89af1Smrg    case LocalSendWidgetTree:
26133c89af1Smrg	str = " asking for widget tree";
26233c89af1Smrg	break;
26333c89af1Smrg    case LocalSetValues:
26433c89af1Smrg	str = " asking it to perform SetValues()";
26533c89af1Smrg	break;
26633c89af1Smrg    case LocalFlashWidget:
26733c89af1Smrg    case LocalGetGeometry:
26833c89af1Smrg	str = " asking it to perform GetGeometry()";
26933c89af1Smrg	break;
27033c89af1Smrg    case LocalGetResources:
27133c89af1Smrg	str = " asking it to get a widget's resource list";
27233c89af1Smrg	break;
27333c89af1Smrg    case LocalFindChild:
27433c89af1Smrg	str = " asking it to find the child Widget.";
27533c89af1Smrg	break;
27633c89af1Smrg    default:
27733c89af1Smrg	str = "";
27833c89af1Smrg	break;
27933c89af1Smrg    }
28033c89af1Smrg
281ad47b356Smrg    snprintf(msg, sizeof(msg), res_labels[8], str);
28233c89af1Smrg    SetMessage(label, msg);
28333c89af1Smrg}
28433c89af1Smrg
28533c89af1Smrg
28633c89af1Smrg
28733c89af1Smrg/*	Function Name: ConvertCommand
28833c89af1Smrg *	Description: Converts the command string into a selection that can
28933c89af1Smrg *                   be sent to the client.
29033c89af1Smrg *	Arguments: (see Xt)
29133c89af1Smrg *	Returns: TRUE if we could convert the selection and target asked for.
29233c89af1Smrg */
29333c89af1Smrg
29433c89af1Smrg/* ARGSUSED */
29533c89af1Smrgstatic Boolean
296278eca22SmrgConvertCommand(Widget w, Atom *selection, Atom *target, Atom *type_ret,
297278eca22Smrg	       XtPointer *value_ret, unsigned long *length_ret, int *format_ret)
29833c89af1Smrg{
29933c89af1Smrg    if ((*selection != atom_comm) || (*target != atom_command))
30033c89af1Smrg	return(FALSE);
30133c89af1Smrg
30233c89af1Smrg    *type_ret = atom_editres_protocol;
30333c89af1Smrg    *value_ret = (XtPointer) global_client.stream.real_top;
30433c89af1Smrg    *length_ret = global_client.stream.size + HEADER_SIZE;
30533c89af1Smrg    *format_ret = EDITRES_FORMAT;
306ad47b356Smrg
30733c89af1Smrg    return(TRUE);
30833c89af1Smrg}
30933c89af1Smrg
31033c89af1Smrg
31133c89af1Smrg
31233c89af1Smrg/*	Function Name: SelectionDone
31333c89af1Smrg *	Description: done with the selection.
31433c89af1Smrg *	Arguments: *** UNUSED ***
31533c89af1Smrg *	Returns: none.
31633c89af1Smrg */
31733c89af1Smrg
31833c89af1Smrg/* ARGSUSED */
31933c89af1Smrgstatic void
320278eca22SmrgSelectionDone(Widget w, Atom *sel, Atom *targ)
32133c89af1Smrg{
32233c89af1Smrg    /* Keep the toolkit from automaticaly freeing the selection value */
32333c89af1Smrg}
32433c89af1Smrg
32533c89af1Smrg
32633c89af1Smrg
32733c89af1Smrg/*	Function Name: LoseSelection
32833c89af1Smrg *	Description: Called when we have lost the selection, asks client
32933c89af1Smrg *                   for the selection value.
33033c89af1Smrg *	Arguments: w - the widget that just lost the selection.
33133c89af1Smrg *                 sel - the selection.
33233c89af1Smrg *	Returns: none.
33333c89af1Smrg */
33433c89af1Smrg
33533c89af1Smrgstatic void
336278eca22SmrgLoseSelection(Widget w, Atom *sel)
33733c89af1Smrg{
33833c89af1Smrg    if (global_client.timeout != 0) {
33933c89af1Smrg	XtRemoveTimeOut(global_client.timeout);
34033c89af1Smrg	global_client.timeout = 0;
34133c89af1Smrg    }
34233c89af1Smrg
34333c89af1Smrg    XtGetSelectionValue(w, *sel, atom_client_value, GetClientValue,
34433c89af1Smrg			NULL, XtLastTimestampProcessed(XtDisplay(w)));
34533c89af1Smrg}
34633c89af1Smrg
34733c89af1Smrg
34833c89af1Smrg
34933c89af1Smrg/*	Function Name: GetClientValue
35033c89af1Smrg *	Description: Gets the value out of the client, and does good things
35133c89af1Smrg *                   to it.
35233c89af1Smrg *	Arguments: w - the widget that asked for the selection.
35333c89af1Smrg *                 data - client_data *** UNUSED ***.
35433c89af1Smrg *                 sel - the selection.
35533c89af1Smrg *                 type - the type of the selection.
35633c89af1Smrg *                 value - the selection's value.
35733c89af1Smrg *                 length - the length of the selection's value.
35833c89af1Smrg *                 format - the format of the selection.
35933c89af1Smrg *	Returns: none.
36033c89af1Smrg */
36133c89af1Smrg
36233c89af1Smrgstatic Boolean reset_protocol_level = True;
36333c89af1Smrg
36433c89af1Smrg/* ARGSUSED */
36533c89af1Smrgstatic void
366278eca22SmrgGetClientValue(Widget w, XtPointer data, Atom *selection, Atom *type,
367278eca22Smrg	       XtPointer value, unsigned long *length, int *format)
36833c89af1Smrg{
36933c89af1Smrg    Event * event;
37033c89af1Smrg    ProtocolStream alloc_stream, *stream;
37133c89af1Smrg    unsigned char ident, error_code;
37233c89af1Smrg    char * error_str = NULL, msg[BUFSIZ];
37333c89af1Smrg
37433c89af1Smrg    if (*length == 0)
37533c89af1Smrg	return;
37633c89af1Smrg
37733c89af1Smrg    stream = &alloc_stream;	/* easier to think of it this way... */
37833c89af1Smrg
37933c89af1Smrg    stream->current = stream->top = (unsigned char *) value;
38033c89af1Smrg    stream->size = HEADER_SIZE;		/* size of header. */
38133c89af1Smrg
38233c89af1Smrg    /*
38333c89af1Smrg     * Retrieve the Header.
38433c89af1Smrg     */
38533c89af1Smrg
38633c89af1Smrg    if (*length < HEADER_SIZE) {
38733c89af1Smrg	SetMessage(global_screen_data.info_label,
38833c89af1Smrg		   res_labels[9]);
38933c89af1Smrg	return;
39033c89af1Smrg    }
39133c89af1Smrg
39233c89af1Smrg    (void) _XEditResGet8(stream, &ident);
39333c89af1Smrg    if (global_client.ident != ident) {
39433c89af1Smrg#ifdef DEBUG
39533c89af1Smrg	if (global_resources.debug)
39633c89af1Smrg	    printf("Incorrect ident from client.\n");
397ad47b356Smrg#endif
398ad47b356Smrg	if (!XtOwnSelection(w, *selection, CurrentTime, ConvertCommand,
39933c89af1Smrg			    LoseSelection, SelectionDone))
40033c89af1Smrg	    SetMessage(global_screen_data.info_label,
40133c89af1Smrg		       res_labels[10]);
40233c89af1Smrg	return;
40333c89af1Smrg    }
40433c89af1Smrg
405ad47b356Smrg    (void) _XEditResGet8(stream, &error_code);
40633c89af1Smrg    (void) _XEditResGet32(stream, &(stream->size));
40733c89af1Smrg    stream->top = stream->current; /* reset stream to top of value.*/
40833c89af1Smrg
40933c89af1Smrg    switch ((int) error_code) {
41033c89af1Smrg    case PartialSuccess:
41133c89af1Smrg/*****
41233c89af1Smrg        if (global_client.command == LocalSendWidgetTree &&
41333c89af1Smrg	    global_effective_protocol_version < CURRENT_PROTOCOL_VERSION)
41433c89af1Smrg	  ++global_effective_protocol_version;
41533c89af1Smrg*****/
41633c89af1Smrg	if ((event = BuildEvent(stream)) != NULL) {
41733c89af1Smrg	    error_str = DispatchEvent(event);
41833c89af1Smrg	    FreeEvent(event);
41933c89af1Smrg	}
42033c89af1Smrg	else {
421ad47b356Smrg	    snprintf(msg, sizeof(msg), "Unable to unpack protocol request.");
42233c89af1Smrg	    error_str = XtNewString(msg);
42333c89af1Smrg	}
42433c89af1Smrg	break;
42533c89af1Smrg    case Failure:
42633c89af1Smrg	error_str = GetFailureMessage(stream);
42733c89af1Smrg	break;
42833c89af1Smrg    case ProtocolMismatch:
42933c89af1Smrg	error_str = ProtocolFailure(stream);
43033c89af1Smrg	--global_effective_protocol_version;
43133c89af1Smrg	/* normaly protocol version is reset to current during a SendWidgetTree
43233c89af1Smrg         * request, however, after a protocol failure this is skiped once for
43333c89af1Smrg         * a retry.
43433c89af1Smrg         */
43533c89af1Smrg	reset_protocol_level = False;
43633c89af1Smrg	SetCommand(w, LocalSendWidgetTree, NULL);
43733c89af1Smrg	break;
43833c89af1Smrg    default:
439ad47b356Smrg	snprintf(msg, sizeof(msg), res_labels[11], (int) error_code);
44033c89af1Smrg	SetMessage(global_screen_data.info_label, msg);
44133c89af1Smrg	break;
44233c89af1Smrg    }
44333c89af1Smrg
44433c89af1Smrg    if (error_str == NULL) {
44533c89af1Smrg	WNode * top;
446ad47b356Smrg
44733c89af1Smrg	if (global_tree_info == NULL)
44833c89af1Smrg	    return;
449ad47b356Smrg
45033c89af1Smrg	top = global_tree_info->top_node;
451ad47b356Smrg	snprintf(msg, sizeof(msg), res_labels[12], top->name, top->class);
45233c89af1Smrg	SetMessage(global_screen_data.info_label, msg);
45333c89af1Smrg	return;
45433c89af1Smrg    }
45533c89af1Smrg    SetMessage(global_screen_data.info_label, error_str);
45633c89af1Smrg    XtFree(error_str);
45733c89af1Smrg}
45833c89af1Smrg
45933c89af1Smrg
46033c89af1Smrg
46133c89af1Smrg/*	Function Name: BuildHeader
46233c89af1Smrg *	Description: Puts the header into the message.
46333c89af1Smrg *	Arguments: client_data - the client data.
46433c89af1Smrg *	Returns: none.
46533c89af1Smrg */
46633c89af1Smrg
46733c89af1Smrgstatic void
468278eca22SmrgBuildHeader(CurrentClient *client_data)
46933c89af1Smrg{
47033c89af1Smrg    unsigned long old_alloc, old_size;
47133c89af1Smrg    unsigned char * old_current;
47233c89af1Smrg    EditresCommand command;
47333c89af1Smrg    ProtocolStream * stream = &(client_data->stream);
47433c89af1Smrg
47533c89af1Smrg    /*
47633c89af1Smrg     * We have cleverly keep enough space at the top of the header
47733c89af1Smrg     * for the return protocol stream, so all we have to do is
47833c89af1Smrg     * fill in the space.
47933c89af1Smrg     */
48033c89af1Smrg
481ad47b356Smrg    /*
48233c89af1Smrg     * Fool the insert routines into putting the header in the right
48333c89af1Smrg     * place while being damn sure not to realloc (that would be very bad.
48433c89af1Smrg     */
485ad47b356Smrg
48633c89af1Smrg    old_current = stream->current;
48733c89af1Smrg    old_alloc = stream->alloc;
48833c89af1Smrg    old_size = stream->size;
48933c89af1Smrg
49033c89af1Smrg    stream->current = stream->real_top;
491ad47b356Smrg    stream->alloc = stream->size + (2 * HEADER_SIZE);
492ad47b356Smrg
49333c89af1Smrg    _XEditResPut8(stream, client_data->ident);
49433c89af1Smrg    switch(client_data->command) {
495ad47b356Smrg    case LocalSendWidgetTree:
496ad47b356Smrg        if (reset_protocol_level) global_effective_protocol_version =
49733c89af1Smrg	  CURRENT_PROTOCOL_VERSION;
49833c89af1Smrg        reset_protocol_level = True;
49933c89af1Smrg	command = SendWidgetTree;
50033c89af1Smrg	break;
50133c89af1Smrg    case LocalSetValues:
50233c89af1Smrg	command = SetValues;
50333c89af1Smrg	break;
50433c89af1Smrg    case LocalFlashWidget:
50533c89af1Smrg	command = GetGeometry;
50633c89af1Smrg	break;
50733c89af1Smrg    case LocalGetResources:
50833c89af1Smrg	command = GetResources;
50933c89af1Smrg	break;
51033c89af1Smrg    case LocalFindChild:
51133c89af1Smrg	command = FindChild;
51233c89af1Smrg	break;
51333c89af1Smrg    case LocalGetValues:
51433c89af1Smrg	command = GetValues;
51533c89af1Smrg	break;
51633c89af1Smrg    default:
51733c89af1Smrg	command = SendWidgetTree;
51833c89af1Smrg	break;
51933c89af1Smrg    }
520ad47b356Smrg
52133c89af1Smrg    _XEditResPut8(stream, (unsigned char) command);
52233c89af1Smrg    _XEditResPut32(stream, old_size);
52333c89af1Smrg
52433c89af1Smrg    stream->alloc = old_alloc;
52533c89af1Smrg    stream->current = old_current;
52633c89af1Smrg    stream->size = old_size;
52733c89af1Smrg}
52833c89af1Smrg
52933c89af1Smrg
53033c89af1Smrg
53133c89af1Smrg/*	Function Name: BuildEvent
532ad47b356Smrg *	Description: Builds the event structure from the
53333c89af1Smrg *	Arguments: stream - the protocol data stream.
53433c89af1Smrg *	Returns: event - the event.
53533c89af1Smrg */
53633c89af1Smrg
537ad47b356Smrgstatic Event *
538278eca22SmrgBuildEvent(ProtocolStream *stream)
53933c89af1Smrg{
54033c89af1Smrg    int i;
54133c89af1Smrg    Event * event = (Event *) XtCalloc(sizeof(Event), 1);
54233c89af1Smrg
54333c89af1Smrg    /*
54433c89af1Smrg     * The return value will be different depending upon the
54533c89af1Smrg     * request sent out.
54633c89af1Smrg     */
54733c89af1Smrg
54833c89af1Smrg    switch(global_client.command) {
54933c89af1Smrg    case LocalSendWidgetTree:
55033c89af1Smrg        {
55133c89af1Smrg	    SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
55233c89af1Smrg
55333c89af1Smrg	    send_event->type = SendWidgetTree;
55433c89af1Smrg
55533c89af1Smrg	    if (!_XEditResGet16(stream, &(send_event->num_entries)))
55633c89af1Smrg		goto done;
557ad47b356Smrg
55833c89af1Smrg	    send_event->info = (WidgetTreeInfo *)
55933c89af1Smrg		                XtCalloc(sizeof(WidgetTreeInfo),
56033c89af1Smrg					 send_event->num_entries);
56133c89af1Smrg
56233c89af1Smrg	    for (i = 0; i < (int)send_event->num_entries; i++) {
56333c89af1Smrg		WidgetTreeInfo * info = send_event->info + i;
56433c89af1Smrg		if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
56533c89af1Smrg		      _XEditResGetString8(stream, &(info->name)) &&
56633c89af1Smrg		      _XEditResGetString8(stream, &(info->class)) &&
567ad47b356Smrg		      _XEditResGet32(stream, &(info->window))))
56833c89af1Smrg		{
56933c89af1Smrg		    goto done;
57033c89af1Smrg		}
57133c89af1Smrg	    }
57233c89af1Smrg
573ad47b356Smrg	    if (global_effective_protocol_version ==
57433c89af1Smrg		CURRENT_PROTOCOL_VERSION) {
57533c89af1Smrg				/* get toolkit type and reset if necessary */
57633c89af1Smrg	      if (!_XEditResGetString8(stream, &(send_event->toolkit)))
57733c89af1Smrg 	        goto done;
57833c89af1Smrg	    }
57933c89af1Smrg	    /* set the command menu entries senitive */
58033c89af1Smrg	    SetEntriesSensitive(&CM_entries[CM_OFFSET], CM_NUM, True);
58133c89af1Smrg	    /* set the tree menu entries senitive */
58233c89af1Smrg	    SetEntriesSensitive(TM_entries, TM_NUM, True);
583ad47b356Smrg	    if (global_effective_protocol_version ==
58433c89af1Smrg		CURRENT_PROTOCOL_VERSION) {
585ad47b356Smrg	      if (!strcmp(send_event->toolkit, "InterViews"))
58633c89af1Smrg	        RebuildMenusAndLabel("iv");
587ad47b356Smrg            }
58833c89af1Smrg            else
58933c89af1Smrg              RebuildMenusAndLabel("xt");
59033c89af1Smrg	}
59133c89af1Smrg	break;
59233c89af1Smrg    case LocalSetValues:
59333c89af1Smrg        {
59433c89af1Smrg	    SetValuesEvent * sv_event = (SetValuesEvent *) event;
59533c89af1Smrg
59633c89af1Smrg	    sv_event->type = SetValues;
59733c89af1Smrg
59833c89af1Smrg	    if (!_XEditResGet16(stream, &(sv_event->num_entries)))
59933c89af1Smrg		goto done;
600ad47b356Smrg
60133c89af1Smrg	    sv_event->info = (SetValuesInfo *) XtCalloc(sizeof(SetValuesInfo),
60233c89af1Smrg							sv_event->num_entries);
60333c89af1Smrg
60433c89af1Smrg	    for (i = 0; i < (int)sv_event->num_entries; i++) {
60533c89af1Smrg		SetValuesInfo * info = sv_event->info + i;
60633c89af1Smrg		if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
60733c89af1Smrg		      _XEditResGetString8(stream, &(info->message))))
60833c89af1Smrg		{
60933c89af1Smrg		    goto done;
61033c89af1Smrg		}
61133c89af1Smrg	    }
61233c89af1Smrg	}
61333c89af1Smrg	break;
61433c89af1Smrg    case LocalGetResources:
61533c89af1Smrg        {
61633c89af1Smrg	    GetResourcesEvent * res_event = (GetResourcesEvent *) event;
617ad47b356Smrg
61833c89af1Smrg	    res_event->type = GetGeometry;
61933c89af1Smrg
62033c89af1Smrg	    if (!_XEditResGet16(stream, &(res_event->num_entries)))
62133c89af1Smrg		goto done;
62233c89af1Smrg
623ad47b356Smrg	    res_event->info = (GetResourcesInfo *)
62433c89af1Smrg		                   XtCalloc(sizeof(GetResourcesInfo),
62533c89af1Smrg					    res_event->num_entries);
62633c89af1Smrg
62733c89af1Smrg	    for (i = 0; i < (int)res_event->num_entries; i++) {
62833c89af1Smrg		GetResourcesInfo * res_info = res_event->info + i;
62933c89af1Smrg		if (!(_XEditResGetWidgetInfo(stream, &(res_info->widgets)) &&
63033c89af1Smrg		      _XEditResGetBoolean(stream, &(res_info->error))))
63133c89af1Smrg		{
63233c89af1Smrg		    goto done;
63333c89af1Smrg		}
63433c89af1Smrg		if (res_info->error) {
635ad47b356Smrg		    if (!_XEditResGetString8(stream, &(res_info->message)))
63633c89af1Smrg			goto done;
63733c89af1Smrg		}
63833c89af1Smrg		else {
63933c89af1Smrg		    unsigned int j;
64033c89af1Smrg
64133c89af1Smrg		    if (!_XEditResGet16(stream, &(res_info->num_resources)))
64233c89af1Smrg			goto done;
64333c89af1Smrg
644ad47b356Smrg		    res_info->res_info = (ResourceInfo *)
64533c89af1Smrg			                  XtCalloc(sizeof(ResourceInfo),
64633c89af1Smrg						   res_info->num_resources);
64733c89af1Smrg
64833c89af1Smrg		    for (j = 0; j < res_info->num_resources; j++) {
64933c89af1Smrg			unsigned char temp;
65033c89af1Smrg			ResourceInfo * info = res_info->res_info + j;
65133c89af1Smrg			if (!(_XEditResGetResType(stream, &(temp)) &&
65233c89af1Smrg			      _XEditResGetString8(stream, &(info->name)) &&
65333c89af1Smrg			      _XEditResGetString8(stream, &(info->class)) &&
65433c89af1Smrg			      _XEditResGetString8(stream, &(info->type))))
65533c89af1Smrg			{
65633c89af1Smrg			    goto done;
65733c89af1Smrg			}
65833c89af1Smrg			else
65933c89af1Smrg			    info->res_type = (ResourceType) temp;
66033c89af1Smrg		    } /* for */
66133c89af1Smrg		} /* else */
66233c89af1Smrg	    } /* for */
66333c89af1Smrg	}
66433c89af1Smrg	break;
66533c89af1Smrg    case LocalFlashWidget:
66633c89af1Smrg    case LocalGetGeometry:
66733c89af1Smrg        {
66833c89af1Smrg	    GetGeomEvent * geom_event = (GetGeomEvent *) event;
66933c89af1Smrg
67033c89af1Smrg	    geom_event->type = GetGeometry;
67133c89af1Smrg
67233c89af1Smrg	    if (!_XEditResGet16(stream, &(geom_event->num_entries)))
67333c89af1Smrg		goto done;
674ad47b356Smrg
67533c89af1Smrg	    geom_event->info = (GetGeomInfo *) XtCalloc(sizeof(GetGeomInfo),
67633c89af1Smrg						      geom_event->num_entries);
67733c89af1Smrg
67833c89af1Smrg	    for (i = 0; i < (int)geom_event->num_entries; i++) {
67933c89af1Smrg		GetGeomInfo * info = geom_event->info + i;
68033c89af1Smrg		if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
68133c89af1Smrg		      _XEditResGetBoolean(stream, &(info->error))))
68233c89af1Smrg		{
68333c89af1Smrg		    goto done;
68433c89af1Smrg		}
68533c89af1Smrg		if (info->error) {
68633c89af1Smrg		    if (!_XEditResGetString8(stream, &(info->message)))
68733c89af1Smrg			goto done;
68833c89af1Smrg		}
68933c89af1Smrg		else {
69033c89af1Smrg		    if (!(_XEditResGetBoolean(stream, &(info->visable)) &&
69133c89af1Smrg			  _XEditResGetSigned16(stream, &(info->x)) &&
69233c89af1Smrg			  _XEditResGetSigned16(stream, &(info->y)) &&
69333c89af1Smrg			  _XEditResGet16(stream, &(info->width)) &&
69433c89af1Smrg			  _XEditResGet16(stream, &(info->height)) &&
69533c89af1Smrg			  _XEditResGet16(stream, &(info->border_width))))
69633c89af1Smrg		    {
69733c89af1Smrg			goto done;
69833c89af1Smrg		    }
69933c89af1Smrg		}
70033c89af1Smrg	    }
70133c89af1Smrg	}
70233c89af1Smrg	break;
70333c89af1Smrg    case LocalFindChild:
70433c89af1Smrg        {
70533c89af1Smrg	    FindChildEvent * find_event = (FindChildEvent *) event;
70633c89af1Smrg
70733c89af1Smrg	    find_event->type = FindChild;
70833c89af1Smrg
70933c89af1Smrg	    if (!_XEditResGetWidgetInfo(stream, &(find_event->widgets)))
71033c89af1Smrg		goto done;
71133c89af1Smrg	}
71233c89af1Smrg	break;
71333c89af1Smrg    case LocalGetValues: /* This is for REPLY... */
71433c89af1Smrg	{
71533c89af1Smrg	  Arg args[1];
71633c89af1Smrg	  GetValuesEvent * gv_event = (GetValuesEvent *) event;
717ad47b356Smrg
71833c89af1Smrg	  gv_event->type = GetValues;
719ad47b356Smrg
72033c89af1Smrg	  if (!_XEditResGet16(stream, &(gv_event->num_entries)))
72133c89af1Smrg	    goto done;
72233c89af1Smrg
72333c89af1Smrg	  gv_event->info = (GetValuesInfo*)XtCalloc(sizeof(GetValuesInfo),1);
72433c89af1Smrg
72533c89af1Smrg	  {
72633c89af1Smrg	    GetValuesInfo * info = gv_event->info;
72733c89af1Smrg	    if (!(_XEditResGetString8(stream, &(info->value))))
72833c89af1Smrg	      {
72933c89af1Smrg		goto done;
73033c89af1Smrg	      }
73133c89af1Smrg
73233c89af1Smrg	    /* set the string value of the asciitext widget. note that only
73333c89af1Smrg             * one active node is dealt with here.  This is ok because only
73433c89af1Smrg	     * one node can be active when the resource box is up.
73533c89af1Smrg	     */
73633c89af1Smrg
73733c89af1Smrg	    XtSetArg (args[0], XtNstring, info->value);
73833c89af1Smrg
73933c89af1Smrg	    XtSetValues(
74033c89af1Smrg	      global_tree_info->active_nodes[0]->resources->res_box->value_wid,
74133c89af1Smrg 	      args, 1
74233c89af1Smrg	    );
74333c89af1Smrg	  }
74433c89af1Smrg	}
74533c89af1Smrg	break;
74633c89af1Smrg
74733c89af1Smrg    default:
74833c89af1Smrg	goto done;
74933c89af1Smrg    }
75033c89af1Smrg
75133c89af1Smrg    return(event);
75233c89af1Smrg
75333c89af1Smrg done:
75433c89af1Smrg    FreeEvent(event);
75533c89af1Smrg    return(NULL);
75633c89af1Smrg}
75733c89af1Smrg
75833c89af1Smrg
75933c89af1Smrg
76033c89af1Smrg/*	Function Name: FreeEvent
761ad47b356Smrg *	Description: Frees all memory associated with the event.
76233c89af1Smrg *	Arguments: event - the event.
76333c89af1Smrg *	Returns: none.
76433c89af1Smrg *
76533c89af1Smrg * NOTE: XtFree() returns w/o freeing if ptr is NULL.
76633c89af1Smrg */
76733c89af1Smrg
76833c89af1Smrgstatic void
769278eca22SmrgFreeEvent(Event *event)
77033c89af1Smrg{
77133c89af1Smrg    unsigned int i;
77233c89af1Smrg
77333c89af1Smrg    switch(event->any_event.type) {
77433c89af1Smrg    case SendWidgetTree:
77533c89af1Smrg        {
77633c89af1Smrg	    SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
77733c89af1Smrg	    WidgetTreeInfo * info = send_event->info;
778ad47b356Smrg
77933c89af1Smrg	    if (info != NULL) {
78033c89af1Smrg		for (i = 0; i < send_event->num_entries; i++, info++) {
78133c89af1Smrg		    XtFree((char *)info->widgets.ids);
78233c89af1Smrg		    XtFree(info->name);
78333c89af1Smrg		    XtFree(info->class);
78433c89af1Smrg		}
78533c89af1Smrg		XtFree((char *)send_event->info);
78633c89af1Smrg	    }
78733c89af1Smrg	}
78833c89af1Smrg	break;
78933c89af1Smrg    case SetValues:
79033c89af1Smrg        {
79133c89af1Smrg	    SetValuesEvent * sv_event = (SetValuesEvent *) event;
79233c89af1Smrg	    SetValuesInfo * info = sv_event->info;
793ad47b356Smrg
79433c89af1Smrg	    if (info != NULL) {
79533c89af1Smrg		for (i = 0; i < sv_event->num_entries; i++, info++) {
79633c89af1Smrg		    XtFree((char *)info->widgets.ids);
79733c89af1Smrg		    XtFree(info->message);
79833c89af1Smrg		}
79933c89af1Smrg		XtFree((char *)sv_event->info);
80033c89af1Smrg	    }
80133c89af1Smrg	}
80233c89af1Smrg	break;
80333c89af1Smrg    case GetResources:
80433c89af1Smrg        {
80533c89af1Smrg	    GetResourcesEvent * get_event = (GetResourcesEvent *) event;
80633c89af1Smrg	    GetResourcesInfo * info = get_event->info;
80733c89af1Smrg
80833c89af1Smrg	    if (info != NULL) {
80933c89af1Smrg		for (i = 0; i < get_event->num_entries; i++, info++) {
81033c89af1Smrg		    XtFree((char *)info->widgets.ids);
811ad47b356Smrg		    if (info->error)
81233c89af1Smrg			XtFree(info->message);
81333c89af1Smrg		    else {
81433c89af1Smrg			unsigned int j;
81533c89af1Smrg			ResourceInfo * res_info = info->res_info;
816ad47b356Smrg
81733c89af1Smrg			if (res_info != NULL) {
818ad47b356Smrg			    for (j = 0;
819ad47b356Smrg				 j < info->num_resources; j++, res_info++)
82033c89af1Smrg			    {
82133c89af1Smrg				XtFree(res_info->name);
82233c89af1Smrg				XtFree(res_info->class);
82333c89af1Smrg				XtFree(res_info->type);
82433c89af1Smrg			    }
82533c89af1Smrg			    XtFree((char *)info->res_info);
82633c89af1Smrg			}
82733c89af1Smrg		    }
828ad47b356Smrg		}
82933c89af1Smrg		XtFree((char *)get_event->info);
83033c89af1Smrg	    }
83133c89af1Smrg	}
83233c89af1Smrg	break;
83333c89af1Smrg    case GetGeometry:
83433c89af1Smrg        {
83533c89af1Smrg	    GetGeomEvent * geom_event = (GetGeomEvent *) event;
83633c89af1Smrg	    GetGeomInfo * info = geom_event->info;
83733c89af1Smrg
83833c89af1Smrg	    if (info != NULL) {
83933c89af1Smrg		for (i = 0; i < geom_event->num_entries; i++, info++) {
84033c89af1Smrg		    XtFree((char *)info->widgets.ids);
841ad47b356Smrg		    if (info->error)
84233c89af1Smrg			XtFree(info->message);
84333c89af1Smrg		}
84433c89af1Smrg		XtFree((char *)geom_event->info);
84533c89af1Smrg	    }
84633c89af1Smrg	}
84733c89af1Smrg	break;
84833c89af1Smrg    case FindChild:
84933c89af1Smrg        {
85033c89af1Smrg	    FindChildEvent * find_event = (FindChildEvent *) event;
851ad47b356Smrg
85233c89af1Smrg	    XtFree((char *)find_event->widgets.ids);
85333c89af1Smrg	}
85433c89af1Smrg	break;
85533c89af1Smrg    default:
85633c89af1Smrg	break;
85733c89af1Smrg    }
85833c89af1Smrg}
85933c89af1Smrg
86033c89af1Smrg
86133c89af1Smrg
86233c89af1Smrg/*	Function Name: DispatchEvent
86333c89af1Smrg *	Description: Handles the event, calling the proper function.
86433c89af1Smrg *	Arguments: event - the event.
86533c89af1Smrg *	Returns: one.
86633c89af1Smrg */
867ad47b356Smrg
86833c89af1Smrgstatic char *
869278eca22SmrgDispatchEvent(Event *event)
87033c89af1Smrg{
87133c89af1Smrg    char * error = NULL;
87233c89af1Smrg
87333c89af1Smrg    switch(global_client.command) {
87433c89af1Smrg    case LocalSendWidgetTree:
87533c89af1Smrg	BuildVisualTree(global_tree_parent, event);
87633c89af1Smrg	break;
87733c89af1Smrg    case LocalSetValues:
87833c89af1Smrg	error = PrintSetValuesError(event);
87933c89af1Smrg	break;
88033c89af1Smrg    case LocalFlashWidget:
88133c89af1Smrg	error = HandleFlashWidget(event);
88233c89af1Smrg	break;
88333c89af1Smrg    case LocalGetResources:
88433c89af1Smrg	error = HandleGetResources(event);
88533c89af1Smrg	break;
88633c89af1Smrg    case LocalFindChild:
88733c89af1Smrg	DisplayChild(event);
88833c89af1Smrg	break;
88933c89af1Smrg    case LocalGetValues:
89033c89af1Smrg	break;
89133c89af1Smrg    default:
89233c89af1Smrg        {
89333c89af1Smrg	    char msg[BUFSIZ];
894ad47b356Smrg	    snprintf(msg, sizeof(msg), "Internal error: Unknown command %d.",
895ad47b356Smrg                     global_client.command);
89633c89af1Smrg	    error = XtNewString(msg);
89733c89af1Smrg	}
89833c89af1Smrg	break;
89933c89af1Smrg    }
90033c89af1Smrg    return(error);
90133c89af1Smrg}
90233c89af1Smrg
90333c89af1Smrg
90433c89af1Smrg
90533c89af1Smrg/*	Function Name: InternAtoms
90633c89af1Smrg *	Description: interns all static atoms.
90733c89af1Smrg *	Arguments: display - the current display.
90833c89af1Smrg *	Returns: none.
90933c89af1Smrg */
91033c89af1Smrg
91133c89af1Smrgvoid
912278eca22SmrgInternAtoms(Display * dpy)
91333c89af1Smrg{
91433c89af1Smrg    atom_comm = XInternAtom(dpy, EDITRES_COMM_ATOM, False);
91533c89af1Smrg    atom_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False);
91633c89af1Smrg    atom_resource_editor = XInternAtom(dpy, EDITRES_NAME, False);
91733c89af1Smrg    atom_client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False);
91833c89af1Smrg    atom_editres_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False);
91933c89af1Smrg}
92033c89af1Smrg
92133c89af1SmrgResIdent
922278eca22SmrgGetNewIdent(void)
92333c89af1Smrg{
92433c89af1Smrg    static ResIdent ident = 1;
92533c89af1Smrg
92633c89af1Smrg    return(ident++);
92733c89af1Smrg}
92833c89af1Smrg
929