comm.c revision 352bf44e
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 5533c89af1Smrgstatic void ClientTimedOut ( XtPointer data, XtIntervalId * id ); 5633c89af1Smrgstatic void TellUserAboutMessage ( Widget label, ResCommand command ); 57ad47b356Smrgstatic Boolean ConvertCommand ( Widget w, Atom * selection, Atom * target, 58ad47b356Smrg Atom * type_ret, XtPointer *value_ret, 5933c89af1Smrg unsigned long * length_ret, int * format_ret ); 6033c89af1Smrgstatic void SelectionDone ( Widget w, Atom *sel, Atom *targ ); 6133c89af1Smrgstatic void LoseSelection ( Widget w, Atom * sel ); 62ad47b356Smrgstatic void GetClientValue ( Widget w, XtPointer data, Atom *selection, 63ad47b356Smrg Atom *type, XtPointer value, 6433c89af1Smrg unsigned long *length, int * format ); 6533c89af1Smrgstatic void BuildHeader ( CurrentClient * client_data ); 6633c89af1Smrgstatic Event * BuildEvent ( ProtocolStream * stream ); 6733c89af1Smrgstatic void FreeEvent ( Event * event ); 6833c89af1Smrgstatic char * DispatchEvent ( Event * event ); 6933c89af1Smrg 7033c89af1Smrg 7133c89af1Smrg 7233c89af1Smrg/* Function Name: ClientTimedOut 7333c89af1Smrg * Description: Called if the client takes too long to take our selection. 74ad47b356Smrg * Arguments: data - The widget that owns the client 7533c89af1Smrg * communication selection. 7633c89af1Smrg * id - *** UNUSED *** 7733c89af1Smrg * Returns: none. 7833c89af1Smrg */ 7933c89af1Smrg 8033c89af1Smrg/* ARGSUSED */ 8133c89af1Smrgstatic void 82278eca22SmrgClientTimedOut(XtPointer data, XtIntervalId *id) 8333c89af1Smrg{ 8433c89af1Smrg char msg[BUFSIZ]; 8533c89af1Smrg Widget w = (Widget) data; 86ad47b356Smrg 8733c89af1Smrg global_client.ident = NO_IDENT; 88ad47b356Smrg XtDisownSelection(w, global_client.atom, 8933c89af1Smrg XtLastTimestampProcessed(XtDisplay(w))); 90ad47b356Smrg 91ad47b356Smrg snprintf(msg, sizeof(msg), res_labels[4], "the Editres Protocol."); 9233c89af1Smrg SetMessage(global_screen_data.info_label, msg); 9333c89af1Smrg} 9433c89af1Smrg 9533c89af1Smrg 9633c89af1Smrg 9733c89af1Smrg/* Function Name: GetClientWindow 9833c89af1Smrg * Description: Gets the Client's window by asking the user. 9933c89af1Smrg * Arguments: w - a widget. 10033c89af1Smrg * Returns: a clients window, or None. 10133c89af1Smrg */ 10233c89af1Smrg 103ad47b356SmrgWindow 104278eca22SmrgGetClientWindow(Widget w, int *x, int *y) 10533c89af1Smrg{ 10633c89af1Smrg int status; 10733c89af1Smrg Cursor cursor; 10833c89af1Smrg XEvent event; 10933c89af1Smrg int buttons = 0; 11033c89af1Smrg Display * dpy = XtDisplayOfObject(w); 11133c89af1Smrg Window target_win = None, root = RootWindowOfScreen(XtScreenOfObject(w)); 11233c89af1Smrg XtAppContext app = XtWidgetToApplicationContext(w); 113ad47b356Smrg 11433c89af1Smrg /* Make the target cursor */ 11533c89af1Smrg cursor = XCreateFontCursor(dpy, XC_crosshair); 116ad47b356Smrg 11733c89af1Smrg /* Grab the pointer using target cursor, letting it room all over */ 11833c89af1Smrg status = XGrabPointer(dpy, root, False, 11933c89af1Smrg ButtonPressMask|ButtonReleaseMask, GrabModeSync, 12033c89af1Smrg GrabModeAsync, root, cursor, CurrentTime); 12133c89af1Smrg if (status != GrabSuccess) { 12233c89af1Smrg SetMessage(global_screen_data.info_label, res_labels[5]); 12333c89af1Smrg return(None); 12433c89af1Smrg } 125ad47b356Smrg 12633c89af1Smrg /* Let the user select a window... */ 12733c89af1Smrg while ((target_win == None) || (buttons != 0)) { 12833c89af1Smrg /* allow one more event */ 12933c89af1Smrg XAllowEvents(dpy, SyncPointer, CurrentTime); 13033c89af1Smrg XtAppNextEvent(app, &event); 13133c89af1Smrg switch (event.type) { 13233c89af1Smrg case ButtonPress: 13333c89af1Smrg if (event.xbutton.window != root) { 13433c89af1Smrg XtDispatchEvent(&event); 13533c89af1Smrg break; 13633c89af1Smrg } 137ad47b356Smrg 13833c89af1Smrg if (target_win == None) { 13933c89af1Smrg target_win = event.xbutton.subwindow; /* window selected */ 14033c89af1Smrg if (x != NULL) 14133c89af1Smrg *x = event.xbutton.x_root; 14233c89af1Smrg if (y != NULL) 14333c89af1Smrg *y = event.xbutton.y_root; 14433c89af1Smrg } 14533c89af1Smrg buttons++; 14633c89af1Smrg break; 14733c89af1Smrg case ButtonRelease: 14833c89af1Smrg if (event.xbutton.window != root) { 14933c89af1Smrg XtDispatchEvent(&event); 15033c89af1Smrg break; 15133c89af1Smrg } 152ad47b356Smrg 15333c89af1Smrg if (buttons > 0) /* There may have been some 15433c89af1Smrg down before we started */ 15533c89af1Smrg buttons--; 15633c89af1Smrg break; 15733c89af1Smrg default: 15833c89af1Smrg XtDispatchEvent(&event); 15933c89af1Smrg break; 16033c89af1Smrg } 161ad47b356Smrg } 162ad47b356Smrg 16333c89af1Smrg XUngrabPointer(dpy, CurrentTime); /* Done with pointer */ 164ad47b356Smrg 16533c89af1Smrg return(XmuClientWindow(dpy, target_win)); 16633c89af1Smrg} 16733c89af1Smrg 16833c89af1Smrg 16933c89af1Smrg 17033c89af1Smrg/* Function Name: SetCommand 171ad47b356Smrg * Description: Causes this widget to own the resource editor's 17233c89af1Smrg * command selection. 17333c89af1Smrg * Arguments: w - the widget that will own the selection. 17433c89af1Smrg * command - command to send to client. 17533c89af1Smrg * msg - message to prompt the user to select a client. 17633c89af1Smrg * Returns: none. 17733c89af1Smrg */ 17833c89af1Smrg 17933c89af1Smrg/* ARGSUSED */ 18033c89af1Smrgvoid 181352bf44eSmrgSetCommand(Widget w, ResCommand command, String msg) 18233c89af1Smrg{ 18333c89af1Smrg XClientMessageEvent client_event; 18433c89af1Smrg Display * dpy = XtDisplay(w); 185ad47b356Smrg 186ad47b356Smrg if (msg == NULL) 18733c89af1Smrg msg = res_labels[6]; 188ad47b356Smrg 18933c89af1Smrg SetMessage(global_screen_data.info_label, msg); 190ad47b356Smrg 19133c89af1Smrg if (global_client.window == None) 192ad47b356Smrg if ( (global_client.window = GetClientWindow(w, NULL, NULL)) == None) 19333c89af1Smrg return; 19433c89af1Smrg 19533c89af1Smrg global_client.ident = GetNewIdent(); 196ad47b356Smrg 19733c89af1Smrg global_client.command = command; 19833c89af1Smrg global_client.atom = atom_comm; 19933c89af1Smrg 200ad47b356Smrg BuildHeader(&(global_client)); 20133c89af1Smrg 202ad47b356Smrg if (!XtOwnSelection(w, global_client.atom, CurrentTime, ConvertCommand, 20333c89af1Smrg LoseSelection, SelectionDone)) 20433c89af1Smrg SetMessage(global_screen_data.info_label, 20533c89af1Smrg res_labels[7]); 20633c89af1Smrg 20733c89af1Smrg client_event.window = global_client.window; 20833c89af1Smrg client_event.type = ClientMessage; 20933c89af1Smrg client_event.message_type = atom_resource_editor; 21033c89af1Smrg client_event.format = EDITRES_SEND_EVENT_FORMAT; 21133c89af1Smrg client_event.data.l[0] = XtLastTimestampProcessed(dpy); 21233c89af1Smrg client_event.data.l[1] = global_client.atom; 21333c89af1Smrg client_event.data.l[2] = (long) global_client.ident; 21433c89af1Smrg client_event.data.l[3] = global_effective_protocol_version; 215ad47b356Smrg 21633c89af1Smrg global_error_code = NO_ERROR; /* Reset Error code. */ 21733c89af1Smrg global_old_error_handler = XSetErrorHandler(HandleXErrors); 21833c89af1Smrg global_serial_num = NextRequest(dpy); 219ad47b356Smrg 220ad47b356Smrg XSendEvent(dpy, global_client.window, FALSE, (long) 0, 22133c89af1Smrg (XEvent *) &client_event); 222ad47b356Smrg 22333c89af1Smrg XSync(dpy, FALSE); 22433c89af1Smrg XSetErrorHandler(global_old_error_handler); 22533c89af1Smrg if (global_error_code == NO_WINDOW) { 226ad47b356Smrg char error_buf[BUFSIZ] = 227ad47b356Smrg "The communication window with the" 228ad47b356Smrg " application is no longer available\n" 229ad47b356Smrg "Please select a new widget tree."; 230ad47b356Smrg 23133c89af1Smrg global_error_code = NO_ERROR; /* Reset Error code. */ 23233c89af1Smrg global_client.window = None; 23333c89af1Smrg SetCommand(w, LocalSendWidgetTree, error_buf); 23433c89af1Smrg return; 235ad47b356Smrg } 236ad47b356Smrg 23733c89af1Smrg TellUserAboutMessage(global_screen_data.info_label, command); 23833c89af1Smrg global_client.timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w), 239ad47b356Smrg CLIENT_TIME_OUT, 24033c89af1Smrg ClientTimedOut, (XtPointer) w); 24133c89af1Smrg} 24233c89af1Smrg 24333c89af1Smrg 24433c89af1Smrg 24533c89af1Smrg/* Function Name: TellUserAboutMessage 24633c89af1Smrg * Description: Informs the user that we have sent a message to the client 24733c89af1Smrg * Arguments: label - the info label. 24833c89af1Smrg * command - command that we have executed. 24933c89af1Smrg * Returns: none. 25033c89af1Smrg */ 25133c89af1Smrg 25233c89af1Smrgstatic void 253278eca22SmrgTellUserAboutMessage(Widget label, ResCommand command) 25433c89af1Smrg{ 255352bf44eSmrg char msg[BUFSIZ]; 256352bf44eSmrg const char *str; 25733c89af1Smrg 25833c89af1Smrg switch(command) { 25933c89af1Smrg case LocalSendWidgetTree: 26033c89af1Smrg str = " asking for widget tree"; 26133c89af1Smrg break; 26233c89af1Smrg case LocalSetValues: 26333c89af1Smrg str = " asking it to perform SetValues()"; 26433c89af1Smrg break; 26533c89af1Smrg case LocalFlashWidget: 26633c89af1Smrg case LocalGetGeometry: 26733c89af1Smrg str = " asking it to perform GetGeometry()"; 26833c89af1Smrg break; 26933c89af1Smrg case LocalGetResources: 27033c89af1Smrg str = " asking it to get a widget's resource list"; 27133c89af1Smrg break; 27233c89af1Smrg case LocalFindChild: 27333c89af1Smrg str = " asking it to find the child Widget."; 27433c89af1Smrg break; 27533c89af1Smrg default: 27633c89af1Smrg str = ""; 27733c89af1Smrg break; 27833c89af1Smrg } 27933c89af1Smrg 280ad47b356Smrg snprintf(msg, sizeof(msg), res_labels[8], str); 28133c89af1Smrg SetMessage(label, msg); 28233c89af1Smrg} 28333c89af1Smrg 28433c89af1Smrg 28533c89af1Smrg 28633c89af1Smrg/* Function Name: ConvertCommand 28733c89af1Smrg * Description: Converts the command string into a selection that can 28833c89af1Smrg * be sent to the client. 28933c89af1Smrg * Arguments: (see Xt) 29033c89af1Smrg * Returns: TRUE if we could convert the selection and target asked for. 29133c89af1Smrg */ 29233c89af1Smrg 29333c89af1Smrg/* ARGSUSED */ 29433c89af1Smrgstatic Boolean 295278eca22SmrgConvertCommand(Widget w, Atom *selection, Atom *target, Atom *type_ret, 296278eca22Smrg XtPointer *value_ret, unsigned long *length_ret, int *format_ret) 29733c89af1Smrg{ 29833c89af1Smrg if ((*selection != atom_comm) || (*target != atom_command)) 29933c89af1Smrg return(FALSE); 30033c89af1Smrg 30133c89af1Smrg *type_ret = atom_editres_protocol; 30233c89af1Smrg *value_ret = (XtPointer) global_client.stream.real_top; 30333c89af1Smrg *length_ret = global_client.stream.size + HEADER_SIZE; 30433c89af1Smrg *format_ret = EDITRES_FORMAT; 305ad47b356Smrg 30633c89af1Smrg return(TRUE); 30733c89af1Smrg} 30833c89af1Smrg 30933c89af1Smrg 31033c89af1Smrg 31133c89af1Smrg/* Function Name: SelectionDone 31233c89af1Smrg * Description: done with the selection. 31333c89af1Smrg * Arguments: *** UNUSED *** 31433c89af1Smrg * Returns: none. 31533c89af1Smrg */ 31633c89af1Smrg 31733c89af1Smrg/* ARGSUSED */ 31833c89af1Smrgstatic void 319278eca22SmrgSelectionDone(Widget w, Atom *sel, Atom *targ) 32033c89af1Smrg{ 321352bf44eSmrg /* Keep the toolkit from automatically freeing the selection value */ 32233c89af1Smrg} 32333c89af1Smrg 32433c89af1Smrg 32533c89af1Smrg 32633c89af1Smrg/* Function Name: LoseSelection 32733c89af1Smrg * Description: Called when we have lost the selection, asks client 32833c89af1Smrg * for the selection value. 32933c89af1Smrg * Arguments: w - the widget that just lost the selection. 33033c89af1Smrg * sel - the selection. 33133c89af1Smrg * Returns: none. 33233c89af1Smrg */ 33333c89af1Smrg 33433c89af1Smrgstatic void 335278eca22SmrgLoseSelection(Widget w, Atom *sel) 33633c89af1Smrg{ 33733c89af1Smrg if (global_client.timeout != 0) { 33833c89af1Smrg XtRemoveTimeOut(global_client.timeout); 33933c89af1Smrg global_client.timeout = 0; 34033c89af1Smrg } 34133c89af1Smrg 34233c89af1Smrg XtGetSelectionValue(w, *sel, atom_client_value, GetClientValue, 34333c89af1Smrg NULL, XtLastTimestampProcessed(XtDisplay(w))); 34433c89af1Smrg} 34533c89af1Smrg 34633c89af1Smrg 34733c89af1Smrg 34833c89af1Smrg/* Function Name: GetClientValue 34933c89af1Smrg * Description: Gets the value out of the client, and does good things 35033c89af1Smrg * to it. 35133c89af1Smrg * Arguments: w - the widget that asked for the selection. 35233c89af1Smrg * data - client_data *** UNUSED ***. 35333c89af1Smrg * sel - the selection. 35433c89af1Smrg * type - the type of the selection. 35533c89af1Smrg * value - the selection's value. 35633c89af1Smrg * length - the length of the selection's value. 35733c89af1Smrg * format - the format of the selection. 35833c89af1Smrg * Returns: none. 35933c89af1Smrg */ 36033c89af1Smrg 36133c89af1Smrgstatic Boolean reset_protocol_level = True; 36233c89af1Smrg 36333c89af1Smrg/* ARGSUSED */ 36433c89af1Smrgstatic void 365278eca22SmrgGetClientValue(Widget w, XtPointer data, Atom *selection, Atom *type, 366278eca22Smrg XtPointer value, unsigned long *length, int *format) 36733c89af1Smrg{ 36833c89af1Smrg Event * event; 36933c89af1Smrg ProtocolStream alloc_stream, *stream; 37033c89af1Smrg unsigned char ident, error_code; 37133c89af1Smrg char * error_str = NULL, msg[BUFSIZ]; 37233c89af1Smrg 37333c89af1Smrg if (*length == 0) 37433c89af1Smrg return; 37533c89af1Smrg 37633c89af1Smrg stream = &alloc_stream; /* easier to think of it this way... */ 37733c89af1Smrg 37833c89af1Smrg stream->current = stream->top = (unsigned char *) value; 37933c89af1Smrg stream->size = HEADER_SIZE; /* size of header. */ 38033c89af1Smrg 38133c89af1Smrg /* 38233c89af1Smrg * Retrieve the Header. 38333c89af1Smrg */ 38433c89af1Smrg 38533c89af1Smrg if (*length < HEADER_SIZE) { 38633c89af1Smrg SetMessage(global_screen_data.info_label, 38733c89af1Smrg res_labels[9]); 38833c89af1Smrg return; 38933c89af1Smrg } 39033c89af1Smrg 39133c89af1Smrg (void) _XEditResGet8(stream, &ident); 39233c89af1Smrg if (global_client.ident != ident) { 39333c89af1Smrg#ifdef DEBUG 39433c89af1Smrg if (global_resources.debug) 39533c89af1Smrg printf("Incorrect ident from client.\n"); 396ad47b356Smrg#endif 397ad47b356Smrg if (!XtOwnSelection(w, *selection, CurrentTime, ConvertCommand, 39833c89af1Smrg LoseSelection, SelectionDone)) 39933c89af1Smrg SetMessage(global_screen_data.info_label, 40033c89af1Smrg res_labels[10]); 40133c89af1Smrg return; 40233c89af1Smrg } 40333c89af1Smrg 404ad47b356Smrg (void) _XEditResGet8(stream, &error_code); 40533c89af1Smrg (void) _XEditResGet32(stream, &(stream->size)); 40633c89af1Smrg stream->top = stream->current; /* reset stream to top of value.*/ 40733c89af1Smrg 40833c89af1Smrg switch ((int) error_code) { 40933c89af1Smrg case PartialSuccess: 41033c89af1Smrg/***** 41133c89af1Smrg if (global_client.command == LocalSendWidgetTree && 41233c89af1Smrg global_effective_protocol_version < CURRENT_PROTOCOL_VERSION) 41333c89af1Smrg ++global_effective_protocol_version; 41433c89af1Smrg*****/ 41533c89af1Smrg if ((event = BuildEvent(stream)) != NULL) { 41633c89af1Smrg error_str = DispatchEvent(event); 41733c89af1Smrg FreeEvent(event); 41833c89af1Smrg } 41933c89af1Smrg else { 420ad47b356Smrg snprintf(msg, sizeof(msg), "Unable to unpack protocol request."); 42133c89af1Smrg error_str = XtNewString(msg); 42233c89af1Smrg } 42333c89af1Smrg break; 42433c89af1Smrg case Failure: 42533c89af1Smrg error_str = GetFailureMessage(stream); 42633c89af1Smrg break; 42733c89af1Smrg case ProtocolMismatch: 42833c89af1Smrg error_str = ProtocolFailure(stream); 42933c89af1Smrg --global_effective_protocol_version; 430352bf44eSmrg /* normally protocol version is reset to current during a SendWidgetTree 431352bf44eSmrg * request, however, after a protocol failure this is skipped once for 43233c89af1Smrg * a retry. 43333c89af1Smrg */ 43433c89af1Smrg reset_protocol_level = False; 43533c89af1Smrg SetCommand(w, LocalSendWidgetTree, NULL); 43633c89af1Smrg break; 43733c89af1Smrg default: 438ad47b356Smrg snprintf(msg, sizeof(msg), res_labels[11], (int) error_code); 43933c89af1Smrg SetMessage(global_screen_data.info_label, msg); 44033c89af1Smrg break; 44133c89af1Smrg } 44233c89af1Smrg 44333c89af1Smrg if (error_str == NULL) { 44433c89af1Smrg WNode * top; 445ad47b356Smrg 44633c89af1Smrg if (global_tree_info == NULL) 44733c89af1Smrg return; 448ad47b356Smrg 44933c89af1Smrg top = global_tree_info->top_node; 450ad47b356Smrg snprintf(msg, sizeof(msg), res_labels[12], top->name, top->class); 45133c89af1Smrg SetMessage(global_screen_data.info_label, msg); 45233c89af1Smrg return; 45333c89af1Smrg } 45433c89af1Smrg SetMessage(global_screen_data.info_label, error_str); 45533c89af1Smrg XtFree(error_str); 45633c89af1Smrg} 45733c89af1Smrg 45833c89af1Smrg 45933c89af1Smrg 46033c89af1Smrg/* Function Name: BuildHeader 46133c89af1Smrg * Description: Puts the header into the message. 46233c89af1Smrg * Arguments: client_data - the client data. 46333c89af1Smrg * Returns: none. 46433c89af1Smrg */ 46533c89af1Smrg 46633c89af1Smrgstatic void 467278eca22SmrgBuildHeader(CurrentClient *client_data) 46833c89af1Smrg{ 46933c89af1Smrg unsigned long old_alloc, old_size; 47033c89af1Smrg unsigned char * old_current; 47133c89af1Smrg EditresCommand command; 47233c89af1Smrg ProtocolStream * stream = &(client_data->stream); 47333c89af1Smrg 47433c89af1Smrg /* 47533c89af1Smrg * We have cleverly keep enough space at the top of the header 47633c89af1Smrg * for the return protocol stream, so all we have to do is 47733c89af1Smrg * fill in the space. 47833c89af1Smrg */ 47933c89af1Smrg 480ad47b356Smrg /* 48133c89af1Smrg * Fool the insert routines into putting the header in the right 48233c89af1Smrg * place while being damn sure not to realloc (that would be very bad. 48333c89af1Smrg */ 484ad47b356Smrg 48533c89af1Smrg old_current = stream->current; 48633c89af1Smrg old_alloc = stream->alloc; 48733c89af1Smrg old_size = stream->size; 48833c89af1Smrg 48933c89af1Smrg stream->current = stream->real_top; 490ad47b356Smrg stream->alloc = stream->size + (2 * HEADER_SIZE); 491ad47b356Smrg 49233c89af1Smrg _XEditResPut8(stream, client_data->ident); 49333c89af1Smrg switch(client_data->command) { 494ad47b356Smrg case LocalSendWidgetTree: 495ad47b356Smrg if (reset_protocol_level) global_effective_protocol_version = 49633c89af1Smrg CURRENT_PROTOCOL_VERSION; 49733c89af1Smrg reset_protocol_level = True; 49833c89af1Smrg command = SendWidgetTree; 49933c89af1Smrg break; 50033c89af1Smrg case LocalSetValues: 50133c89af1Smrg command = SetValues; 50233c89af1Smrg break; 50333c89af1Smrg case LocalFlashWidget: 50433c89af1Smrg command = GetGeometry; 50533c89af1Smrg break; 50633c89af1Smrg case LocalGetResources: 50733c89af1Smrg command = GetResources; 50833c89af1Smrg break; 50933c89af1Smrg case LocalFindChild: 51033c89af1Smrg command = FindChild; 51133c89af1Smrg break; 51233c89af1Smrg case LocalGetValues: 51333c89af1Smrg command = GetValues; 51433c89af1Smrg break; 51533c89af1Smrg default: 51633c89af1Smrg command = SendWidgetTree; 51733c89af1Smrg break; 51833c89af1Smrg } 519ad47b356Smrg 52033c89af1Smrg _XEditResPut8(stream, (unsigned char) command); 52133c89af1Smrg _XEditResPut32(stream, old_size); 52233c89af1Smrg 52333c89af1Smrg stream->alloc = old_alloc; 52433c89af1Smrg stream->current = old_current; 52533c89af1Smrg stream->size = old_size; 52633c89af1Smrg} 52733c89af1Smrg 52833c89af1Smrg 52933c89af1Smrg 53033c89af1Smrg/* Function Name: BuildEvent 531ad47b356Smrg * Description: Builds the event structure from the 53233c89af1Smrg * Arguments: stream - the protocol data stream. 53333c89af1Smrg * Returns: event - the event. 53433c89af1Smrg */ 53533c89af1Smrg 536ad47b356Smrgstatic Event * 537278eca22SmrgBuildEvent(ProtocolStream *stream) 53833c89af1Smrg{ 53933c89af1Smrg int i; 54033c89af1Smrg Event * event = (Event *) XtCalloc(sizeof(Event), 1); 54133c89af1Smrg 54233c89af1Smrg /* 54333c89af1Smrg * The return value will be different depending upon the 54433c89af1Smrg * request sent out. 54533c89af1Smrg */ 54633c89af1Smrg 54733c89af1Smrg switch(global_client.command) { 54833c89af1Smrg case LocalSendWidgetTree: 54933c89af1Smrg { 55033c89af1Smrg SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event; 55133c89af1Smrg 55233c89af1Smrg send_event->type = SendWidgetTree; 55333c89af1Smrg 55433c89af1Smrg if (!_XEditResGet16(stream, &(send_event->num_entries))) 55533c89af1Smrg goto done; 556ad47b356Smrg 55733c89af1Smrg send_event->info = (WidgetTreeInfo *) 55833c89af1Smrg XtCalloc(sizeof(WidgetTreeInfo), 55933c89af1Smrg send_event->num_entries); 56033c89af1Smrg 56133c89af1Smrg for (i = 0; i < (int)send_event->num_entries; i++) { 56233c89af1Smrg WidgetTreeInfo * info = send_event->info + i; 56333c89af1Smrg if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 56433c89af1Smrg _XEditResGetString8(stream, &(info->name)) && 56533c89af1Smrg _XEditResGetString8(stream, &(info->class)) && 566ad47b356Smrg _XEditResGet32(stream, &(info->window)))) 56733c89af1Smrg { 56833c89af1Smrg goto done; 56933c89af1Smrg } 57033c89af1Smrg } 57133c89af1Smrg 572ad47b356Smrg if (global_effective_protocol_version == 57333c89af1Smrg CURRENT_PROTOCOL_VERSION) { 57433c89af1Smrg /* get toolkit type and reset if necessary */ 57533c89af1Smrg if (!_XEditResGetString8(stream, &(send_event->toolkit))) 57633c89af1Smrg goto done; 57733c89af1Smrg } 57833c89af1Smrg /* set the command menu entries senitive */ 57933c89af1Smrg SetEntriesSensitive(&CM_entries[CM_OFFSET], CM_NUM, True); 58033c89af1Smrg /* set the tree menu entries senitive */ 58133c89af1Smrg SetEntriesSensitive(TM_entries, TM_NUM, True); 582ad47b356Smrg if (global_effective_protocol_version == 58333c89af1Smrg CURRENT_PROTOCOL_VERSION) { 584ad47b356Smrg if (!strcmp(send_event->toolkit, "InterViews")) 58533c89af1Smrg RebuildMenusAndLabel("iv"); 586ad47b356Smrg } 58733c89af1Smrg else 58833c89af1Smrg RebuildMenusAndLabel("xt"); 58933c89af1Smrg } 59033c89af1Smrg break; 59133c89af1Smrg case LocalSetValues: 59233c89af1Smrg { 59333c89af1Smrg SetValuesEvent * sv_event = (SetValuesEvent *) event; 59433c89af1Smrg 59533c89af1Smrg sv_event->type = SetValues; 59633c89af1Smrg 59733c89af1Smrg if (!_XEditResGet16(stream, &(sv_event->num_entries))) 59833c89af1Smrg goto done; 599ad47b356Smrg 60033c89af1Smrg sv_event->info = (SetValuesInfo *) XtCalloc(sizeof(SetValuesInfo), 60133c89af1Smrg sv_event->num_entries); 60233c89af1Smrg 60333c89af1Smrg for (i = 0; i < (int)sv_event->num_entries; i++) { 60433c89af1Smrg SetValuesInfo * info = sv_event->info + i; 60533c89af1Smrg if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 60633c89af1Smrg _XEditResGetString8(stream, &(info->message)))) 60733c89af1Smrg { 60833c89af1Smrg goto done; 60933c89af1Smrg } 61033c89af1Smrg } 61133c89af1Smrg } 61233c89af1Smrg break; 61333c89af1Smrg case LocalGetResources: 61433c89af1Smrg { 61533c89af1Smrg GetResourcesEvent * res_event = (GetResourcesEvent *) event; 616ad47b356Smrg 61733c89af1Smrg res_event->type = GetGeometry; 61833c89af1Smrg 61933c89af1Smrg if (!_XEditResGet16(stream, &(res_event->num_entries))) 62033c89af1Smrg goto done; 62133c89af1Smrg 622ad47b356Smrg res_event->info = (GetResourcesInfo *) 62333c89af1Smrg XtCalloc(sizeof(GetResourcesInfo), 62433c89af1Smrg res_event->num_entries); 62533c89af1Smrg 62633c89af1Smrg for (i = 0; i < (int)res_event->num_entries; i++) { 62733c89af1Smrg GetResourcesInfo * res_info = res_event->info + i; 62833c89af1Smrg if (!(_XEditResGetWidgetInfo(stream, &(res_info->widgets)) && 62933c89af1Smrg _XEditResGetBoolean(stream, &(res_info->error)))) 63033c89af1Smrg { 63133c89af1Smrg goto done; 63233c89af1Smrg } 63333c89af1Smrg if (res_info->error) { 634ad47b356Smrg if (!_XEditResGetString8(stream, &(res_info->message))) 63533c89af1Smrg goto done; 63633c89af1Smrg } 63733c89af1Smrg else { 63833c89af1Smrg unsigned int j; 63933c89af1Smrg 64033c89af1Smrg if (!_XEditResGet16(stream, &(res_info->num_resources))) 64133c89af1Smrg goto done; 64233c89af1Smrg 643ad47b356Smrg res_info->res_info = (ResourceInfo *) 64433c89af1Smrg XtCalloc(sizeof(ResourceInfo), 64533c89af1Smrg res_info->num_resources); 64633c89af1Smrg 64733c89af1Smrg for (j = 0; j < res_info->num_resources; j++) { 64833c89af1Smrg unsigned char temp; 64933c89af1Smrg ResourceInfo * info = res_info->res_info + j; 65033c89af1Smrg if (!(_XEditResGetResType(stream, &(temp)) && 65133c89af1Smrg _XEditResGetString8(stream, &(info->name)) && 65233c89af1Smrg _XEditResGetString8(stream, &(info->class)) && 65333c89af1Smrg _XEditResGetString8(stream, &(info->type)))) 65433c89af1Smrg { 65533c89af1Smrg goto done; 65633c89af1Smrg } 65733c89af1Smrg else 65833c89af1Smrg info->res_type = (ResourceType) temp; 65933c89af1Smrg } /* for */ 66033c89af1Smrg } /* else */ 66133c89af1Smrg } /* for */ 66233c89af1Smrg } 66333c89af1Smrg break; 66433c89af1Smrg case LocalFlashWidget: 66533c89af1Smrg case LocalGetGeometry: 66633c89af1Smrg { 66733c89af1Smrg GetGeomEvent * geom_event = (GetGeomEvent *) event; 66833c89af1Smrg 66933c89af1Smrg geom_event->type = GetGeometry; 67033c89af1Smrg 67133c89af1Smrg if (!_XEditResGet16(stream, &(geom_event->num_entries))) 67233c89af1Smrg goto done; 673ad47b356Smrg 67433c89af1Smrg geom_event->info = (GetGeomInfo *) XtCalloc(sizeof(GetGeomInfo), 67533c89af1Smrg geom_event->num_entries); 67633c89af1Smrg 67733c89af1Smrg for (i = 0; i < (int)geom_event->num_entries; i++) { 67833c89af1Smrg GetGeomInfo * info = geom_event->info + i; 67933c89af1Smrg if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) && 68033c89af1Smrg _XEditResGetBoolean(stream, &(info->error)))) 68133c89af1Smrg { 68233c89af1Smrg goto done; 68333c89af1Smrg } 68433c89af1Smrg if (info->error) { 68533c89af1Smrg if (!_XEditResGetString8(stream, &(info->message))) 68633c89af1Smrg goto done; 68733c89af1Smrg } 68833c89af1Smrg else { 689352bf44eSmrg if (!(_XEditResGetBoolean(stream, &(info->visible)) && 69033c89af1Smrg _XEditResGetSigned16(stream, &(info->x)) && 69133c89af1Smrg _XEditResGetSigned16(stream, &(info->y)) && 69233c89af1Smrg _XEditResGet16(stream, &(info->width)) && 69333c89af1Smrg _XEditResGet16(stream, &(info->height)) && 69433c89af1Smrg _XEditResGet16(stream, &(info->border_width)))) 69533c89af1Smrg { 69633c89af1Smrg goto done; 69733c89af1Smrg } 69833c89af1Smrg } 69933c89af1Smrg } 70033c89af1Smrg } 70133c89af1Smrg break; 70233c89af1Smrg case LocalFindChild: 70333c89af1Smrg { 70433c89af1Smrg FindChildEvent * find_event = (FindChildEvent *) event; 70533c89af1Smrg 70633c89af1Smrg find_event->type = FindChild; 70733c89af1Smrg 70833c89af1Smrg if (!_XEditResGetWidgetInfo(stream, &(find_event->widgets))) 70933c89af1Smrg goto done; 71033c89af1Smrg } 71133c89af1Smrg break; 71233c89af1Smrg case LocalGetValues: /* This is for REPLY... */ 71333c89af1Smrg { 71433c89af1Smrg Arg args[1]; 71533c89af1Smrg GetValuesEvent * gv_event = (GetValuesEvent *) event; 716ad47b356Smrg 71733c89af1Smrg gv_event->type = GetValues; 718ad47b356Smrg 71933c89af1Smrg if (!_XEditResGet16(stream, &(gv_event->num_entries))) 72033c89af1Smrg goto done; 72133c89af1Smrg 72233c89af1Smrg gv_event->info = (GetValuesInfo*)XtCalloc(sizeof(GetValuesInfo),1); 72333c89af1Smrg 72433c89af1Smrg { 72533c89af1Smrg GetValuesInfo * info = gv_event->info; 72633c89af1Smrg if (!(_XEditResGetString8(stream, &(info->value)))) 72733c89af1Smrg { 72833c89af1Smrg goto done; 72933c89af1Smrg } 73033c89af1Smrg 73133c89af1Smrg /* set the string value of the asciitext widget. note that only 73233c89af1Smrg * one active node is dealt with here. This is ok because only 73333c89af1Smrg * one node can be active when the resource box is up. 73433c89af1Smrg */ 73533c89af1Smrg 73633c89af1Smrg XtSetArg (args[0], XtNstring, info->value); 73733c89af1Smrg 73833c89af1Smrg XtSetValues( 73933c89af1Smrg global_tree_info->active_nodes[0]->resources->res_box->value_wid, 74033c89af1Smrg args, 1 74133c89af1Smrg ); 74233c89af1Smrg } 74333c89af1Smrg } 74433c89af1Smrg break; 74533c89af1Smrg 74633c89af1Smrg default: 74733c89af1Smrg goto done; 74833c89af1Smrg } 74933c89af1Smrg 75033c89af1Smrg return(event); 75133c89af1Smrg 75233c89af1Smrg done: 75333c89af1Smrg FreeEvent(event); 75433c89af1Smrg return(NULL); 75533c89af1Smrg} 75633c89af1Smrg 75733c89af1Smrg 75833c89af1Smrg 75933c89af1Smrg/* Function Name: FreeEvent 760ad47b356Smrg * Description: Frees all memory associated with the event. 76133c89af1Smrg * Arguments: event - the event. 76233c89af1Smrg * Returns: none. 76333c89af1Smrg * 76433c89af1Smrg * NOTE: XtFree() returns w/o freeing if ptr is NULL. 76533c89af1Smrg */ 76633c89af1Smrg 76733c89af1Smrgstatic void 768278eca22SmrgFreeEvent(Event *event) 76933c89af1Smrg{ 77033c89af1Smrg unsigned int i; 77133c89af1Smrg 77233c89af1Smrg switch(event->any_event.type) { 77333c89af1Smrg case SendWidgetTree: 77433c89af1Smrg { 77533c89af1Smrg SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event; 77633c89af1Smrg WidgetTreeInfo * info = send_event->info; 777ad47b356Smrg 77833c89af1Smrg if (info != NULL) { 77933c89af1Smrg for (i = 0; i < send_event->num_entries; i++, info++) { 78033c89af1Smrg XtFree((char *)info->widgets.ids); 78133c89af1Smrg XtFree(info->name); 78233c89af1Smrg XtFree(info->class); 78333c89af1Smrg } 78433c89af1Smrg XtFree((char *)send_event->info); 78533c89af1Smrg } 78633c89af1Smrg } 78733c89af1Smrg break; 78833c89af1Smrg case SetValues: 78933c89af1Smrg { 79033c89af1Smrg SetValuesEvent * sv_event = (SetValuesEvent *) event; 79133c89af1Smrg SetValuesInfo * info = sv_event->info; 792ad47b356Smrg 79333c89af1Smrg if (info != NULL) { 79433c89af1Smrg for (i = 0; i < sv_event->num_entries; i++, info++) { 79533c89af1Smrg XtFree((char *)info->widgets.ids); 79633c89af1Smrg XtFree(info->message); 79733c89af1Smrg } 79833c89af1Smrg XtFree((char *)sv_event->info); 79933c89af1Smrg } 80033c89af1Smrg } 80133c89af1Smrg break; 80233c89af1Smrg case GetResources: 80333c89af1Smrg { 80433c89af1Smrg GetResourcesEvent * get_event = (GetResourcesEvent *) event; 80533c89af1Smrg GetResourcesInfo * info = get_event->info; 80633c89af1Smrg 80733c89af1Smrg if (info != NULL) { 80833c89af1Smrg for (i = 0; i < get_event->num_entries; i++, info++) { 80933c89af1Smrg XtFree((char *)info->widgets.ids); 810ad47b356Smrg if (info->error) 81133c89af1Smrg XtFree(info->message); 81233c89af1Smrg else { 81333c89af1Smrg unsigned int j; 81433c89af1Smrg ResourceInfo * res_info = info->res_info; 815ad47b356Smrg 81633c89af1Smrg if (res_info != NULL) { 817ad47b356Smrg for (j = 0; 818ad47b356Smrg j < info->num_resources; j++, res_info++) 81933c89af1Smrg { 82033c89af1Smrg XtFree(res_info->name); 82133c89af1Smrg XtFree(res_info->class); 82233c89af1Smrg XtFree(res_info->type); 82333c89af1Smrg } 82433c89af1Smrg XtFree((char *)info->res_info); 82533c89af1Smrg } 82633c89af1Smrg } 827ad47b356Smrg } 82833c89af1Smrg XtFree((char *)get_event->info); 82933c89af1Smrg } 83033c89af1Smrg } 83133c89af1Smrg break; 83233c89af1Smrg case GetGeometry: 83333c89af1Smrg { 83433c89af1Smrg GetGeomEvent * geom_event = (GetGeomEvent *) event; 83533c89af1Smrg GetGeomInfo * info = geom_event->info; 83633c89af1Smrg 83733c89af1Smrg if (info != NULL) { 83833c89af1Smrg for (i = 0; i < geom_event->num_entries; i++, info++) { 83933c89af1Smrg XtFree((char *)info->widgets.ids); 840ad47b356Smrg if (info->error) 84133c89af1Smrg XtFree(info->message); 84233c89af1Smrg } 84333c89af1Smrg XtFree((char *)geom_event->info); 84433c89af1Smrg } 84533c89af1Smrg } 84633c89af1Smrg break; 84733c89af1Smrg case FindChild: 84833c89af1Smrg { 84933c89af1Smrg FindChildEvent * find_event = (FindChildEvent *) event; 850ad47b356Smrg 85133c89af1Smrg XtFree((char *)find_event->widgets.ids); 85233c89af1Smrg } 85333c89af1Smrg break; 85433c89af1Smrg default: 85533c89af1Smrg break; 85633c89af1Smrg } 85733c89af1Smrg} 85833c89af1Smrg 85933c89af1Smrg 86033c89af1Smrg 86133c89af1Smrg/* Function Name: DispatchEvent 86233c89af1Smrg * Description: Handles the event, calling the proper function. 86333c89af1Smrg * Arguments: event - the event. 86433c89af1Smrg * Returns: one. 86533c89af1Smrg */ 866ad47b356Smrg 86733c89af1Smrgstatic char * 868278eca22SmrgDispatchEvent(Event *event) 86933c89af1Smrg{ 87033c89af1Smrg char * error = NULL; 87133c89af1Smrg 87233c89af1Smrg switch(global_client.command) { 87333c89af1Smrg case LocalSendWidgetTree: 87433c89af1Smrg BuildVisualTree(global_tree_parent, event); 87533c89af1Smrg break; 87633c89af1Smrg case LocalSetValues: 87733c89af1Smrg error = PrintSetValuesError(event); 87833c89af1Smrg break; 87933c89af1Smrg case LocalFlashWidget: 88033c89af1Smrg error = HandleFlashWidget(event); 88133c89af1Smrg break; 88233c89af1Smrg case LocalGetResources: 88333c89af1Smrg error = HandleGetResources(event); 88433c89af1Smrg break; 88533c89af1Smrg case LocalFindChild: 88633c89af1Smrg DisplayChild(event); 88733c89af1Smrg break; 88833c89af1Smrg case LocalGetValues: 88933c89af1Smrg break; 89033c89af1Smrg default: 89133c89af1Smrg { 89233c89af1Smrg char msg[BUFSIZ]; 893ad47b356Smrg snprintf(msg, sizeof(msg), "Internal error: Unknown command %d.", 894ad47b356Smrg global_client.command); 89533c89af1Smrg error = XtNewString(msg); 89633c89af1Smrg } 89733c89af1Smrg break; 89833c89af1Smrg } 89933c89af1Smrg return(error); 90033c89af1Smrg} 90133c89af1Smrg 90233c89af1Smrg 90333c89af1Smrg 90433c89af1Smrg/* Function Name: InternAtoms 90533c89af1Smrg * Description: interns all static atoms. 90633c89af1Smrg * Arguments: display - the current display. 90733c89af1Smrg * Returns: none. 90833c89af1Smrg */ 90933c89af1Smrg 91033c89af1Smrgvoid 911278eca22SmrgInternAtoms(Display * dpy) 91233c89af1Smrg{ 91333c89af1Smrg atom_comm = XInternAtom(dpy, EDITRES_COMM_ATOM, False); 91433c89af1Smrg atom_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False); 91533c89af1Smrg atom_resource_editor = XInternAtom(dpy, EDITRES_NAME, False); 91633c89af1Smrg atom_client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False); 91733c89af1Smrg atom_editres_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False); 91833c89af1Smrg} 91933c89af1Smrg 92033c89af1SmrgResIdent 921278eca22SmrgGetNewIdent(void) 92233c89af1Smrg{ 92333c89af1Smrg static ResIdent ident = 1; 92433c89af1Smrg 92533c89af1Smrg return(ident++); 92633c89af1Smrg} 927