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