/* $XConsortium: RegEdit.c /main/5 1995/07/15 20:44:04 drk $ */ /* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA * */ /* * HISTORY */ #include #include #include #include "RegEdit.h" #include "RegEditI.h" /* static forward. move from global in the original Editres code */ static void _XEditResCheckMessages(); static void _XEditResPutString8(); static void _XEditResPut8(); static void _XEditResPut16(); static void _XEditResPut32(); static void _XEditResPutWidgetInfo(); static void _XEditResResetStream(); static Boolean _XEditResGet8(); static Boolean _XEditResGet16(); static Boolean _XEditResGetSigned16(); static Boolean _XEditResGet32(); static Boolean _XEditResGetString8(); static Boolean _XEditResGetWidgetInfo(); /* the only entry point here */ void XmdRegisterEditres(Widget toplevel) { XtAddEventHandler(toplevel, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL); } /************************************************************ * * Dump the content of the R5 lib/Xmu/EditresCom.c module. * just move global as static. * ************************************************************/ #define _XEditResPutBool _XEditResPut8 #define _XEditResPutResourceType _XEditResPut8 /************************************************************ * * Local structure definitions. * ************************************************************/ typedef enum { BlockNone, BlockSetValues, BlockAll } EditresBlock; typedef struct _SetValuesEvent { EditresCommand type; /* first field must be type. */ WidgetInfo * widgets; unsigned short num_entries; /* number of set values requests. */ char * name; char * res_type; XtPointer value; unsigned short value_len; } SetValuesEvent; typedef struct _SVErrorInfo { SetValuesEvent * event; ProtocolStream * stream; unsigned short * count; WidgetInfo * entry; } SVErrorInfo; typedef struct _FindChildEvent { EditresCommand type; /* first field must be type. */ WidgetInfo * widgets; short x, y; } FindChildEvent; typedef struct _GenericGetEvent { EditresCommand type; /* first field must be type. */ WidgetInfo * widgets; unsigned short num_entries; /* number of set values requests. */ } GenericGetEvent, GetResEvent, GetGeomEvent; /* * Things that are common to all events. */ typedef struct _AnyEvent { EditresCommand type; /* first field must be type. */ WidgetInfo * widgets; } AnyEvent; /* * The event union. */ typedef union _EditresEvent { AnyEvent any_event; SetValuesEvent set_values_event; GetResEvent get_resources_event; GetGeomEvent get_geometry_event; FindChildEvent find_child_event; } EditresEvent; typedef struct _Globals { EditresBlock block; SVErrorInfo error_info; ProtocolStream stream; ProtocolStream * command_stream; /* command stream. */ } Globals; #define CURRENT_PROTOCOL_VERSION 4L #define streq(a,b) (strcmp( (a), (b) ) == 0) static Atom res_editor_command, res_editor_protocol, client_value; static Globals globals; static void SendFailure(), SendCommand(), InsertWidget(), ExecuteCommand(); static void FreeEvent(), ExecuteSetValues(), ExecuteGetGeometry(); static void ExecuteGetResources(); static void GetCommand(); static void LoadResources(); static Boolean IsChild(); static void DumpChildren(); static char *DumpWidgets(), *DoSetValues(), *DoFindChild(); static char *DoGetGeometry(), *DoGetResources(); /************************************************************ * * Resource Editor Communication Code * ************************************************************/ /* Function Name: _XEditResCheckMessages * Description: This callback routine is set on all shell widgets, * and checks to see if a client message event * has come from the resource editor. * Arguments: w - the shell widget. * data - *** UNUSED *** * event - The X Event that triggered this handler. * cont - *** UNUSED ***. * Returns: none. */ /* ARGSUSED */ static void _XEditResCheckMessages(w, data, event, cont) Widget w; XtPointer data; XEvent *event; Boolean *cont; { Time time; ResIdent ident; static Boolean first_time = FALSE; static Atom res_editor, res_comm; Display * dpy; if (event->type == ClientMessage) { XClientMessageEvent * c_event = (XClientMessageEvent *) event; dpy = XtDisplay(w); if (!first_time) { first_time = TRUE; res_editor = XInternAtom(dpy, EDITRES_NAME, False); res_editor_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False); res_editor_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False); /* Used in later procedures. */ client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False); LoadResources(w); } if ((c_event->message_type != res_editor) || (c_event->format != EDITRES_SEND_EVENT_FORMAT)) return; time = c_event->data.l[0]; res_comm = c_event->data.l[1]; ident = (ResIdent) c_event->data.l[2]; if (c_event->data.l[3] != CURRENT_PROTOCOL_VERSION) { _XEditResResetStream(&globals.stream); _XEditResPut8(&globals.stream, CURRENT_PROTOCOL_VERSION); SendCommand(w, res_comm, ident, ProtocolMismatch, &globals.stream); return; } XtGetSelectionValue(w, res_comm, res_editor_command, GetCommand, (XtPointer) (long) ident, time); } } /* Function Name: BuildEvent * Description: Takes the info out the protocol stream an constructs * the proper event structure. * Arguments: w - widget to own selection, in case of error. * sel - selection to send error message beck in. * data - the data for the request. * ident - the id number we are looking for. * length - length of request. * Returns: the event, or NULL. */ #define ERROR_MESSAGE ("Client: Improperly formatted protocol request") static EditresEvent * BuildEvent(w, sel, data, ident, length) Widget w; Atom sel; XtPointer data; ResIdent ident; unsigned long length; { EditresEvent * event; ProtocolStream alloc_stream, *stream; unsigned char temp; register unsigned int i; stream = &alloc_stream; /* easier to think of it this way... */ stream->current = stream->top = (unsigned char *) data; stream->size = HEADER_SIZE; /* size of header. */ /* * Retrieve the Header. */ if (length < HEADER_SIZE) { SendFailure(w, sel, ident, Failure, ERROR_MESSAGE); return(NULL); } (void) _XEditResGet8(stream, &temp); if (temp != ident) /* Id's don't match, ignore request. */ return(NULL); event = (EditresEvent *) XtCalloc(sizeof(EditresEvent), 1); (void) _XEditResGet8(stream, &temp); event->any_event.type = (EditresCommand) temp; (void) _XEditResGet32(stream, &(stream->size)); stream->top = stream->current; /* reset stream to top of value.*/ /* * Now retrieve the data segment. */ switch(event->any_event.type) { case SendWidgetTree: break; /* no additional info */ case SetValues: { SetValuesEvent * sv_event = (SetValuesEvent *) event; if ( !(_XEditResGetString8(stream, &(sv_event->name)) && _XEditResGetString8(stream, &(sv_event->res_type)))) { goto done; } /* * Since we need the value length, we have to pull the * value out by hand. */ if (!_XEditResGet16(stream, &(sv_event->value_len))) goto done; sv_event->value = XtMalloc(sizeof(char) * (sv_event->value_len + 1)); for (i = 0; i < sv_event->value_len; i++) { if (!_XEditResGet8(stream, (unsigned char *) sv_event->value + i)) { goto done; } } ((char*)sv_event->value)[i] = '\0'; /* NULL terminate that sucker. */ if (!_XEditResGet16(stream, &(sv_event->num_entries))) goto done; sv_event->widgets = (WidgetInfo *) XtCalloc(sizeof(WidgetInfo), sv_event->num_entries); for (i = 0; i < sv_event->num_entries; i++) { if (!_XEditResGetWidgetInfo(stream, sv_event->widgets + i)) goto done; } } break; case FindChild: { FindChildEvent * find_event = (FindChildEvent *) event; find_event->widgets = (WidgetInfo *) XtCalloc(sizeof(WidgetInfo), 1); if (!(_XEditResGetWidgetInfo(stream, find_event->widgets) && _XEditResGetSigned16(stream, &(find_event->x)) && _XEditResGetSigned16(stream, &(find_event->y)))) { goto done; } } break; case GetGeometry: case GetResources: { GenericGetEvent * get_event = (GenericGetEvent *) event; if (!_XEditResGet16(stream, &(get_event->num_entries))) goto done; get_event->widgets = (WidgetInfo *) XtCalloc(sizeof(WidgetInfo), get_event->num_entries); for (i = 0; i < get_event->num_entries; i++) { if (!_XEditResGetWidgetInfo(stream, get_event->widgets + i)) goto done; } } break; default: { char buf[BUFSIZ]; sprintf(buf, "Unknown Protocol request %d.",event->any_event.type); SendFailure(w, sel, ident, buf); return(NULL); } } return(event); done: SendFailure(w, sel, ident, ERROR_MESSAGE); FreeEvent(event); return(NULL); } /* Function Name: FreeEvent * Description: Frees the event structure and any other pieces * in it that need freeing. * Arguments: event - the event to free. * Returns: none. */ static void FreeEvent(event) EditresEvent * event; { if (event->any_event.widgets != NULL) { XtFree((char *)event->any_event.widgets->ids); XtFree((char *)event->any_event.widgets); } if (event->any_event.type == SetValues) { XtFree(event->set_values_event.name); /* XtFree does not free if */ XtFree(event->set_values_event.res_type); /* value is NULL. */ } XtFree((char *)event); } /* Function Name: GetCommand * Description: Gets the Command out of the selection asserted by the * resource manager. * Arguments: (See Xt XtConvertSelectionProc) * data - contains the ident number for the command. * Returns: none. */ /* ARGSUSED */ static void GetCommand(w, data, selection, type, value, length, format) Widget w; XtPointer data, value; Atom *selection, *type; unsigned long *length; int * format; { ResIdent ident = (ResIdent) (long) data; EditresEvent * event; if ( (*type != res_editor_protocol) || (*format != EDITRES_FORMAT) ) return; if ((event = BuildEvent(w, *selection, value, ident, *length)) != NULL) { ExecuteCommand(w, *selection, ident, event); FreeEvent(event); } } /* Function Name: ExecuteCommand * Description: Executes a command string received from the * resource editor. * Arguments: w - a widget. * command - the command to execute. * value - the associated with the command. * Returns: none. * * NOTES: munges str */ /* ARGSUSED */ static void ExecuteCommand(w, sel, ident, event) Widget w; Atom sel; ResIdent ident; EditresEvent * event; { char * (*func)(); char * str; if (globals.block == BlockAll) { SendFailure(w, sel, ident, "This client has blocked all Editres commands."); return; } else if ((globals.block == BlockSetValues) && (event->any_event.type == SetValues)) { SendFailure(w, sel, ident, "This client has blocked all SetValues requests."); return; } switch(event->any_event.type) { case SendWidgetTree: func = DumpWidgets; break; case SetValues: func = DoSetValues; break; case FindChild: func = DoFindChild; break; case GetGeometry: func = DoGetGeometry; break; case GetResources: func = DoGetResources; break; default: { char buf[BUFSIZ]; sprintf(buf,"Unknown Protocol request %d.",event->any_event.type); SendFailure(w, sel, ident, buf); return; } } _XEditResResetStream(&globals.stream); if ((str = (*func)(w, event, &globals.stream)) == NULL) SendCommand(w, sel, ident, PartialSuccess, &globals.stream); else { SendFailure(w, sel, ident, str); XtFree(str); } } /* Function Name: ConvertReturnCommand * Description: Converts a selection. * Arguments: w - the widget that owns the selection. * selection - selection to convert. * target - target type for this selection. * type_ret - type of the selection. * value_ret - selection value; * length_ret - lenght of this selection. * format_ret - the format the selection is in. * Returns: True if conversion was sucessful. */ /* ARGSUSED */ static Boolean ConvertReturnCommand(w, selection, target, type_ret, value_ret, length_ret, format_ret) Widget w; Atom * selection, * target, * type_ret; XtPointer *value_ret; unsigned long * length_ret; int * format_ret; { /* * I assume the intrinsics give me the correct selection back. */ if ((*target != client_value)) return(FALSE); *type_ret = res_editor_protocol; *value_ret = (XtPointer) globals.command_stream->real_top; *length_ret = globals.command_stream->size + HEADER_SIZE; *format_ret = EDITRES_FORMAT; return(TRUE); } /* Function Name: CommandDone * Description: done with the selection. * Arguments: *** UNUSED *** * Returns: none. */ /* ARGSUSED */ static void CommandDone(widget, selection, target) Widget widget; Atom *selection; Atom *target; { /* Keep the toolkit from automaticaly freeing the selection value */ } /* Function Name: SendFailure * Description: Sends a failure message. * Arguments: w - the widget to own the selection. * sel - the selection to assert. * ident - the identifier. * str - the error message. * Returns: none. */ static void SendFailure(w, sel, ident, str) Widget w; Atom sel; ResIdent ident; char * str; { _XEditResResetStream(&globals.stream); _XEditResPutString8(&globals.stream, str); SendCommand(w, sel, ident, Failure, &globals.stream); } /* Function Name: BuildReturnPacket * Description: Builds a return packet, given the data to send. * Arguments: ident - the identifier. * command - the command code. * stream - the protocol stream. * Returns: packet - the packet to send. */ static XtPointer BuildReturnPacket(ident, command, stream) ResIdent ident; EditresCommand command; ProtocolStream * stream; { long old_alloc, old_size; unsigned char * old_current; /* * We have cleverly keep enough space at the top of the header * for the return protocol stream, so all we have to do is * fill in the space. */ /* * Fool the insert routines into putting the header in the right * place while being damn sure not to realloc (that would be very bad. */ old_current = stream->current; old_alloc = stream->alloc; old_size = stream->size; stream->current = stream->real_top; stream->alloc = stream->size + (2 * HEADER_SIZE); _XEditResPut8(stream, ident); _XEditResPut8(stream, (unsigned char) command); _XEditResPut32(stream, old_size); stream->alloc = old_alloc; stream->current = old_current; stream->size = old_size; return((XtPointer) stream->real_top); } /* Function Name: SendCommand * Description: Builds a return command line. * Arguments: w - the widget to own the selection. * sel - the selection to assert. * ident - the identifier. * command - the command code. * stream - the protocol stream. * Returns: none. */ static void SendCommand(w, sel, ident, command, stream) Widget w; Atom sel; ResIdent ident; EditresCommand command; ProtocolStream * stream; { BuildReturnPacket(ident, command, stream); globals.command_stream = stream; /* * I REALLY want to own the selection. Since this was not triggered * by a user action, and I am the only one using this atom it is safe to * use CurrentTime. */ XtOwnSelection(w, sel, CurrentTime, ConvertReturnCommand, NULL, CommandDone); } /************************************************************ * * Generic Utility Functions. * ************************************************************/ /* Function Name: FindChildren * Description: Retuns all children (popup, normal and otherwise) * of this widget * Arguments: parent - the parent widget. * children - the list of children. * normal - return normal children. * popup - return popup children. * Returns: the number of children. */ static int FindChildren(parent, children, normal, popup) Widget parent, **children; Boolean normal, popup; { CompositeWidget cw = (CompositeWidget) parent; int i, num_children, current = 0; num_children = 0; if (XtIsWidget(parent) && popup) num_children += parent->core.num_popups; if (XtIsComposite(parent) && normal) num_children += cw->composite.num_children; if (num_children == 0) { *children = NULL; return(0); } *children =(Widget*) XtMalloc((Cardinal) sizeof(Widget) * num_children); if (XtIsComposite(parent) && normal) for (i = 0; i < cw->composite.num_children; i++,current++) (*children)[current] = cw->composite.children[i]; if (XtIsWidget(parent) && popup) for ( i = 0; i < parent->core.num_popups; i++, current++) (*children)[current] = parent->core.popup_list[i]; return(num_children); } /* Function Name: IsChild * Description: check to see of child is a child of parent. * Arguments: top - the top of the tree. * parent - the parent widget. * child - the child. * Returns: none. */ static Boolean IsChild(top, parent, child) Widget top, parent, child; { int i, num_children; Widget * children; if (parent == NULL) return(top == child); num_children = FindChildren(parent, &children, TRUE, TRUE); for (i = 0; i < num_children; i++) { if (children[i] == child) { XtFree((char *)children); return(TRUE); } } XtFree((char *)children); return(FALSE); } /* Function Name: VerifyWidget * Description: Makes sure all the widgets still exist. * Arguments: w - any widget in the tree. * info - the info about the widget to verify. * Returns: an error message or NULL. */ static char * VerifyWidget(w, info) Widget w; WidgetInfo *info; { Widget top; register int count; register Widget parent; register unsigned long * child; for (top = w; XtParent(top) != NULL; top = XtParent(top)) {} parent = NULL; child = info->ids; count = 0; while (TRUE) { if (!IsChild(top, parent, (Widget) *child)) return(XtNewString("This widget no longer exists in the client.")); if (++count == info->num_widgets) break; parent = (Widget) *child++; } info->real_widget = (Widget) *child; return(NULL); } /************************************************************ * * Code to Perform SetValues operations. * ************************************************************/ /* Function Name: DoSetValues * Description: performs the setvalues requested. * Arguments: w - a widget in the tree. * event - the event that caused this action. * stream - the protocol stream to add. * Returns: NULL. */ static char * DoSetValues(w, event, stream) Widget w; EditresEvent * event; ProtocolStream * stream; { char * str; register unsigned i; unsigned short count = 0; SetValuesEvent * sv_event = (SetValuesEvent *) event; _XEditResPut16(stream, count); /* insert 0, will be overwritten later. */ for (i = 0 ; i < sv_event->num_entries; i++) { if ((str = VerifyWidget(w, &(sv_event->widgets[i]))) != NULL) { _XEditResPutWidgetInfo(stream, &(sv_event->widgets[i])); _XEditResPutString8(stream, str); XtFree(str); count++; } else ExecuteSetValues(sv_event->widgets[i].real_widget, sv_event, sv_event->widgets + i, stream, &count); } /* * Overwrite the first 2 bytes with the real count. */ *(stream->top) = count >> XER_NBBY; *(stream->top + 1) = count; return(NULL); } /* Function Name: HandleToolkitErrors * Description: Handles X Toolkit Errors. * Arguments: name - name of the error. * type - type of the error. * class - class of the error. * msg - the default message. * params, num_params - the extra parameters for this message. * Returns: none. */ /* ARGSUSED */ static void HandleToolkitErrors(name, type, class, msg, params, num_params) String name, type, class, msg, *params; Cardinal * num_params; { SVErrorInfo * info = &globals.error_info; char buf[BUFSIZ]; if ( streq(name, "unknownType") ) sprintf(buf, "The `%s' resource is not used by this widget.", info->event->name); else if ( streq(name, "noColormap") ) sprintf(buf, msg, params[0]); else if (streq(name, "conversionFailed") || streq(name, "conversionError")) { if (streq(info->event->value, XtRString)) sprintf(buf, "Could not convert the string '%s' for the `%s' resource.", (char*)info->event->value, info->event->name); else sprintf(buf, "Could not convert the `%s' resource.", info->event->name); } else sprintf(buf, "Name: %s, Type: %s, Class: %s, Msg: %s", name, type, class, msg); /* * Insert this info into the protocol stream, and update the count. */ (*(info->count))++; _XEditResPutWidgetInfo(info->stream, info->entry); _XEditResPutString8(info->stream, buf); } /* Function Name: ExecuteSetValues * Description: Performs a setvalues for a given command. * Arguments: w - the widget to perform the set_values on. * sv_event - the set values event. * sv_info - the set_value info. * Returns: none. */ static void ExecuteSetValues(w, sv_event, entry, stream, count) Widget w; SetValuesEvent * sv_event; WidgetInfo * entry; ProtocolStream * stream; unsigned short * count; { XtErrorMsgHandler old; SVErrorInfo * info = &globals.error_info; info->event = sv_event; /* No data can be passed to */ info->stream = stream; /* an error handler, so we */ info->count = count; /* have to use a global, YUCK... */ info->entry = entry; old = XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w), HandleToolkitErrors); XtVaSetValues(w, XtVaTypedArg, sv_event->name, sv_event->res_type, sv_event->value, sv_event->value_len, NULL); (void)XtAppSetWarningMsgHandler(XtWidgetToApplicationContext(w), old); } /************************************************************ * * Code for Creating and dumping widget tree. * ************************************************************/ /* Function Name: DumpWidgets * Description: Given a widget it builds a protocol packet * containing the entire widget heirarchy. * Arguments: w - a widget in the tree. * event - the event that caused this action. * stream - the protocol stream to add. * Returns: NULL */ /* ARGSUSED */ static char * DumpWidgets(w, event, stream) Widget w; EditresEvent * event; /* UNUSED */ ProtocolStream * stream; { unsigned short count = 0; /* Find Tree's root. */ for ( ; XtParent(w) != NULL; w = XtParent(w)) {} /* * hold space for count, overwritten later. */ _XEditResPut16(stream, (unsigned int) 0); DumpChildren(w, stream, &count); /* * Overwrite the first 2 bytes with the real count. */ *(stream->top) = count >> XER_NBBY; *(stream->top + 1) = count; return(NULL); } /* Function Name: DumpChildren * Description: Adds a child's name to the list. * Arguments: w - the widget to dump. * stream - the stream to dump to. * count - number of dumps we have performed. * Returns: none. */ /* This is a trick/kludge. To make shared libraries happier (linking * against Xmu but not linking against Xt, and apparently even work * as we desire on SVR4, we need to avoid an explicit data reference * to applicationShellWidgetClass. XtIsTopLevelShell is known * (implementation dependent assumption!) to use a bit flag. So we * go that far. Then, we test whether it is an applicationShellWidget * class by looking for an explicit class name. Seems pretty safe. */ static Bool isApplicationShell(w) Widget w; { register WidgetClass c; if (!XtIsTopLevelShell(w)) return False; for (c = XtClass(w); c; c = c->core_class.superclass) { if (!strcmp(c->core_class.class_name, "ApplicationShell")) return True; } return False; } static void DumpChildren(w, stream, count) Widget w; ProtocolStream * stream; unsigned short *count; { int i, num_children; Widget *children; unsigned long window; char * class; (*count)++; InsertWidget(stream, w); /* Insert the widget into the stream. */ _XEditResPutString8(stream, XtName(w)); /* Insert name */ if (isApplicationShell(w)) class = ((ApplicationShellWidget) w)->application.class; else class = XtClass(w)->core_class.class_name; _XEditResPutString8(stream, class); /* Insert class */ if (XtIsWidget(w)) if (XtIsRealized(w)) window = XtWindow(w); else window = EDITRES_IS_UNREALIZED; else window = EDITRES_IS_OBJECT; _XEditResPut32(stream, window); /* Insert window id. */ /* * Find children and recurse. */ num_children = FindChildren(w, &children, TRUE, TRUE); for (i = 0; i < num_children; i++) DumpChildren(children[i], stream, count); XtFree((char *)children); } /************************************************************ * * Code for getting the geometry of widgets. * ************************************************************/ /* Function Name: DoGetGeometry * Description: retrieves the Geometry of each specified widget. * Arguments: w - a widget in the tree. * event - the event that caused this action. * stream - the protocol stream to add. * Returns: NULL */ static char * DoGetGeometry(w, event, stream) Widget w; EditresEvent * event; ProtocolStream * stream; { unsigned i; char * str; GetGeomEvent * geom_event = (GetGeomEvent *) event; _XEditResPut16(stream, geom_event->num_entries); for (i = 0 ; i < geom_event->num_entries; i++) { /* * Send out the widget id. */ _XEditResPutWidgetInfo(stream, &(geom_event->widgets[i])); if ((str = VerifyWidget(w, &(geom_event->widgets[i]))) != NULL) { _XEditResPutBool(stream, True); /* an error occured. */ _XEditResPutString8(stream, str); /* set message. */ XtFree(str); } else ExecuteGetGeometry(geom_event->widgets[i].real_widget, stream); } return(NULL); } /* Function Name: ExecuteGetGeometry * Description: Gets the geometry for each widget specified. * Arguments: w - the widget to get geom on. * stream - stream to append to. * Returns: True if no error occured. */ static void ExecuteGetGeometry(w, stream) Widget w; ProtocolStream * stream; { int i; Boolean mapped_when_man; Dimension width, height, border_width; Arg args[8]; Cardinal num_args = 0; Position x, y; if ( !XtIsRectObj(w) || (XtIsWidget(w) && !XtIsRealized(w)) ) { _XEditResPutBool(stream, False); /* no error. */ _XEditResPutBool(stream, False); /* not visable. */ for (i = 0; i < 5; i++) /* fill in extra space with 0's. */ _XEditResPut16(stream, 0); return; } XtSetArg(args[num_args], XtNwidth, &width); num_args++; XtSetArg(args[num_args], XtNheight, &height); num_args++; XtSetArg(args[num_args], XtNborderWidth, &border_width); num_args++; XtSetArg(args[num_args], XtNmappedWhenManaged, &mapped_when_man); num_args++; XtGetValues(w, args, num_args); if (!(XtIsManaged(w) && mapped_when_man) && XtIsWidget(w)) { XWindowAttributes attrs; /* * The toolkit does not maintain mapping state, we have * to go to the server. */ if (XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attrs) != 0) { if (attrs.map_state != IsViewable) { _XEditResPutBool(stream, False); /* no error. */ _XEditResPutBool(stream, False); /* not visable. */ for (i = 0; i < 5; i++) /* fill in extra space with 0's. */ _XEditResPut16(stream, 0); return; } } else { _XEditResPut8(stream, True); /* Error occured. */ _XEditResPutString8(stream, "XGetWindowAttributes failed."); return; } } XtTranslateCoords(w, -((int) border_width), -((int) border_width), &x, &y); _XEditResPutBool(stream, False); /* no error. */ _XEditResPutBool(stream, True); /* Visable. */ _XEditResPut16(stream, x); _XEditResPut16(stream, y); _XEditResPut16(stream, width); _XEditResPut16(stream, height); _XEditResPut16(stream, border_width); } /************************************************************ * * Code for executing FindChild. * ************************************************************/ /* Function Name: PositionInChild * Description: returns true if this location is in the child. * Arguments: child - the child widget to check. * x, y - location of point to check in the parent's * coord space. * Returns: TRUE if the position is in this child. */ static Boolean PositionInChild(child, x, y) Widget child; int x, y; { Arg args[6]; Cardinal num; Dimension width, height, border_width; Position child_x, child_y; Boolean mapped_when_managed; if (!XtIsRectObj(child)) /* we must at least be a rect obj. */ return(FALSE); num = 0; XtSetArg(args[num], XtNmappedWhenManaged, &mapped_when_managed); num++; XtSetArg(args[num], XtNwidth, &width); num++; XtSetArg(args[num], XtNheight, &height); num++; XtSetArg(args[num], XtNx, &child_x); num++; XtSetArg(args[num], XtNy, &child_y); num++; XtSetArg(args[num], XtNborderWidth, &border_width); num++; XtGetValues(child, args, num); /* * The only way we will know of the widget is mapped is to see if * mapped when managed is True and this is a managed child. Otherwise * we will have to ask the server if this window is mapped. */ if (XtIsWidget(child) && !(mapped_when_managed && XtIsManaged(child)) ) { XWindowAttributes attrs; if (XGetWindowAttributes(XtDisplay(child), XtWindow(child), &attrs) != 0) { /* oops */ } else if (attrs.map_state != IsViewable) return(FALSE); } return (x >= child_x) && (x <= (child_x + (Position)width + 2 * (Position)border_width)) && (y >= child_y) && (y <= (child_y + (Position)height + 2 * (Position)border_width)); } /* Function Name: _FindChild * Description: Finds the child that actually contatians the point shown. * Arguments: parent - a widget that is known to contain the point * specified. * x, y - The point in coordinates relative to the * widget specified. * Returns: none. */ static Widget _FindChild(parent, x, y) Widget parent; int x, y; { Widget * children; int i = FindChildren(parent, &children, TRUE, FALSE); while (i > 0) { i--; if (PositionInChild(children[i], x, y)) { Widget child = children[i]; XtFree((char *)children); return(_FindChild(child, x - child->core.x, y - child->core.y)); } } XtFree((char *)children); return(parent); } /* Function Name: DoFindChild * Description: finds the child that contains the location specified. * Arguments: w - a widget in the tree. * event - the event that caused this action. * stream - the protocol stream to add. * Returns: an allocated error message if something went horribly * wrong and no set values were performed, else NULL. */ static char * DoFindChild(w, event, stream) Widget w; EditresEvent * event; ProtocolStream * stream; { char * str; Widget parent, child; Position parent_x, parent_y; FindChildEvent * find_event = (FindChildEvent *) event; if ((str = VerifyWidget(w, find_event->widgets)) != NULL) return(str); parent = find_event->widgets->real_widget; XtTranslateCoords(parent, (Position) 0, (Position) 0, &parent_x, &parent_y); child = _FindChild(parent, find_event->x - (int) parent_x, find_event->y - (int) parent_y); InsertWidget(stream, child); return(NULL); } /************************************************************ * * Procedures for performing GetResources. * ************************************************************/ /* Function Name: DoGetResources * Description: Gets the Resources associated with the widgets passed. * Arguments: w - a widget in the tree. * event - the event that caused this action. * stream - the protocol stream to add. * Returns: NULL */ static char * DoGetResources(w, event, stream) Widget w; EditresEvent * event; ProtocolStream * stream; { unsigned int i; char * str; GetResEvent * res_event = (GetResEvent *) event; _XEditResPut16(stream, res_event->num_entries); /* number of replys */ for (i = 0 ; i < res_event->num_entries; i++) { /* * Send out the widget id. */ _XEditResPutWidgetInfo(stream, &(res_event->widgets[i])); if ((str = VerifyWidget(w, &(res_event->widgets[i]))) != NULL) { _XEditResPutBool(stream, True); /* an error occured. */ _XEditResPutString8(stream, str); /* set message. */ XtFree(str); } else { _XEditResPutBool(stream, False); /* no error occured. */ ExecuteGetResources(res_event->widgets[i].real_widget, stream); } } return(NULL); } /* Function Name: ExecuteGetResources. * Description: Gets the resources for any individual widget. * Arguments: w - the widget to get resources on. * stream - the protocol stream. * Returns: none. */ static void ExecuteGetResources(w, stream) Widget w; ProtocolStream * stream; { XtResourceList norm_list, cons_list; Cardinal num_norm, num_cons; register int i; /* * Get Normal Resources. */ XtGetResourceList(XtClass(w), &norm_list, &num_norm); if (XtParent(w) != NULL) XtGetConstraintResourceList(XtClass(XtParent(w)),&cons_list,&num_cons); else num_cons = 0; _XEditResPut16(stream, num_norm + num_cons); /* how many resources. */ /* * Insert all the normal resources. */ for ( i = 0; i < (int) num_norm; i++) { _XEditResPutResourceType(stream, NormalResource); _XEditResPutString8(stream, norm_list[i].resource_name); _XEditResPutString8(stream, norm_list[i].resource_class); _XEditResPutString8(stream, norm_list[i].resource_type); } XtFree((char *) norm_list); /* * Insert all the constraint resources. */ if (num_cons > 0) { for ( i = 0; i < (int) num_cons; i++) { _XEditResPutResourceType(stream, ConstraintResource); _XEditResPutString8(stream, cons_list[i].resource_name); _XEditResPutString8(stream, cons_list[i].resource_class); _XEditResPutString8(stream, cons_list[i].resource_type); } XtFree((char *) cons_list); } } /************************************************************ * * Code for inserting values into the protocol stream. * ************************************************************/ /* Function Name: InsertWidget * Description: Inserts the full parent heirarchy of this * widget into the protocol stream as a widget list. * Arguments: stream - the protocol stream. * w - the widget to insert. * Returns: none */ static void InsertWidget(stream, w) ProtocolStream * stream; Widget w; { Widget temp; unsigned long * widget_list; register int i, num_widgets; for (temp = w, i = 0; temp != 0; temp = XtParent(temp), i++) {} num_widgets = i; widget_list = (unsigned long *) XtMalloc(sizeof(unsigned long) * num_widgets); /* * Put the widgets into the list. * make sure that they are inserted in the list from parent -> child. */ for (i--, temp = w; temp != NULL; temp = XtParent(temp), i--) widget_list[i] = (unsigned long) temp; _XEditResPut16(stream, num_widgets); /* insert number of widgets. */ for (i = 0; i < num_widgets; i++) /* insert Widgets themselves. */ _XEditResPut32(stream, widget_list[i]); XtFree((char *)widget_list); } /************************************************************ * * All of the following routines are public. * ************************************************************/ /* Function Name: _XEditResPutString8 * Description: Inserts a string into the protocol stream. * Arguments: stream - stream to insert string into. * str - string to insert. * Returns: none. */ static void _XEditResPutString8(stream, str) ProtocolStream * stream; char * str; { int i, len = strlen(str); _XEditResPut16(stream, len); for (i = 0 ; i < len ; i++, str++) _XEditResPut8(stream, *str); } /* Function Name: _XEditResPut8 * Description: Inserts an 8 bit integer into the protocol stream. * Arguments: stream - stream to insert string into. * value - value to insert. * Returns: none */ static void _XEditResPut8(stream, value) ProtocolStream * stream; unsigned int value; { unsigned char temp; if (stream->size >= stream->alloc) { stream->alloc += 100; stream->real_top = (unsigned char *) XtRealloc( (char *)stream->real_top, stream->alloc + HEADER_SIZE); stream->top = stream->real_top + HEADER_SIZE; stream->current = stream->top + stream->size; } temp = (unsigned char) (value & BYTE_MASK); *((stream->current)++) = temp; (stream->size)++; } /* Function Name: _XEditResPut16 * Description: Inserts a 16 bit integer into the protocol stream. * Arguments: stream - stream to insert string into. * value - value to insert. * Returns: void */ static void _XEditResPut16(stream, value) ProtocolStream * stream; unsigned int value; { _XEditResPut8(stream, (value >> XER_NBBY) & BYTE_MASK); _XEditResPut8(stream, value & BYTE_MASK); } /* Function Name: _XEditResPut32 * Description: Inserts a 32 bit integer into the protocol stream. * Arguments: stream - stream to insert string into. * value - value to insert. * Returns: void */ static void _XEditResPut32(stream, value) ProtocolStream * stream; unsigned long value; { int i; for (i = 3; i >= 0; i--) _XEditResPut8(stream, (value >> (XER_NBBY*i)) & BYTE_MASK); } /* Function Name: _XEditResPutWidgetInfo * Description: Inserts the widget info into the protocol stream. * Arguments: stream - stream to insert widget info into. * info - info to insert. * Returns: none */ static void _XEditResPutWidgetInfo(stream, info) ProtocolStream * stream; WidgetInfo * info; { unsigned int i; _XEditResPut16(stream, info->num_widgets); for (i = 0; i < info->num_widgets; i++) _XEditResPut32(stream, info->ids[i]); } /************************************************************ * * Code for retrieving values from the protocol stream. * ************************************************************/ /* Function Name: _XEditResResetStream * Description: resets the protocol stream * Arguments: stream - the stream to reset. * Returns: none. */ static void _XEditResResetStream(stream) ProtocolStream * stream; { stream->current = stream->top; stream->size = 0; if (stream->real_top == NULL) { stream->real_top = (unsigned char *) XtRealloc( (char *)stream->real_top, stream->alloc + HEADER_SIZE); stream->top = stream->real_top + HEADER_SIZE; stream->current = stream->top + stream->size; } } /* * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE * * The only modified field if the "current" field. * * The only fields that must be set correctly are the "current", "top" * and "size" fields. */ /* Function Name: _XEditResGetg8 * Description: Retrieves an unsigned 8 bit value * from the protocol stream. * Arguments: stream. * val - a pointer to value to return. * Returns: TRUE if sucessful. */ static Boolean _XEditResGet8(stream, val) ProtocolStream * stream; unsigned char * val; { if (stream->size < (stream->current - stream->top)) return(FALSE); *val = *((stream->current)++); return(TRUE); } /* Function Name: _XEditResGet16 * Description: Retrieves an unsigned 16 bit value * from the protocol stream. * Arguments: stream. * val - a pointer to value to return. * Returns: TRUE if sucessful. */ static Boolean _XEditResGet16(stream, val) ProtocolStream * stream; unsigned short * val; { unsigned char temp1, temp2; if ( !(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2)) ) return(FALSE); *val = (((unsigned short) temp1 << XER_NBBY) + ((unsigned short) temp2)); return(TRUE); } /* Function Name: _XEditResGetSigned16 * Description: Retrieves an signed 16 bit value from the protocol stream. * Arguments: stream. * val - a pointer to value to return. * Returns: TRUE if sucessful. */ static Boolean _XEditResGetSigned16(stream, val) ProtocolStream * stream; short * val; { unsigned char temp1, temp2; if ( !(_XEditResGet8(stream, &temp1) && _XEditResGet8(stream, &temp2)) ) return(FALSE); if (temp1 & (1 << (XER_NBBY - 1))) { /* If the sign bit is active. */ *val = -1; /* store all 1's */ *val &= (temp1 << XER_NBBY); /* Now and in the MSB */ *val &= temp2; /* and LSB */ } else *val = (((unsigned short) temp1 << XER_NBBY) + ((unsigned short) temp2)); return(TRUE); } /* Function Name: _XEditResGet32 * Description: Retrieves an unsigned 32 bit value * from the protocol stream. * Arguments: stream. * val - a pointer to value to return. * Returns: TRUE if sucessful. */ static Boolean _XEditResGet32(stream, val) ProtocolStream * stream; unsigned long * val; { unsigned short temp1, temp2; if ( !(_XEditResGet16(stream, &temp1) && _XEditResGet16(stream, &temp2)) ) return(FALSE); *val = (((unsigned short) temp1 << (XER_NBBY * 2)) + ((unsigned short) temp2)); return(TRUE); } /* Function Name: _XEditResGetString8 * Description: Retrieves an 8 bit string value from the protocol stream. * Arguments: stream - the protocol stream * str - the string to retrieve. * Returns: True if retrieval was successful. */ static Boolean _XEditResGetString8(stream, str) ProtocolStream * stream; char ** str; { unsigned short len; register unsigned i; if (!_XEditResGet16(stream, &len)) { return(FALSE); } *str = XtMalloc(sizeof(char) * (len + 1)); for (i = 0; i < len; i++) { if (!_XEditResGet8(stream, (unsigned char *) *str + i)) { XtFree(*str); *str = NULL; return(FALSE); } } (*str)[i] = '\0'; /* NULL terminate that sucker. */ return(TRUE); } /* Function Name: _XEditResGetWidgetInfo * Description: Retrieves the list of widgets that follow and stores * them in the widget info structure provided. * Arguments: stream - the protocol stream * info - the widget info struct to store into. * Returns: True if retrieval was successful. */ static Boolean _XEditResGetWidgetInfo(stream, info) ProtocolStream * stream; WidgetInfo * info; { unsigned int i; if (!_XEditResGet16(stream, &(info->num_widgets))) return(FALSE); info->ids = (unsigned long *) XtMalloc(sizeof(long) * (info->num_widgets)); for (i = 0; i < info->num_widgets; i++) { if (!_XEditResGet32(stream, info->ids + i)) { XtFree((char *)info->ids); info->ids = NULL; return(FALSE); } } return(TRUE); } /************************************************************ * * Code for Loading the EditresBlock resource. * ************************************************************/ /* Function Name: CvStringToBlock * Description: Converts a string to an editres block value. * Arguments: dpy - the display. * args, num_args - **UNUSED ** * from_val, to_val - value to convert, and where to put result * converter_data - ** UNUSED ** * Returns: TRUE if conversion was sucessful. */ /* ARGSUSED */ static Boolean CvtStringToBlock(dpy, args, num_args, from_val, to_val, converter_data) Display * dpy; XrmValue * args; Cardinal * num_args; XrmValue * from_val, * to_val; XtPointer * converter_data; { char ptr[BUFSIZ]; static EditresBlock block; /* XmuCopyISOLatin1Lowered(ptr, from_val->addr);*/ if (streq(ptr, "none")) block = BlockNone; else if (streq(ptr, "setvalues")) block = BlockSetValues; else if (streq(ptr, "all")) block = BlockAll; else { Cardinal num_params = 1; String params[1]; params[0] = from_val->addr; XtAppWarningMsg(XtDisplayToApplicationContext(dpy), "CvtStringToBlock", "unknownValue", "EditresError", "Could not convert string \"%s\" to EditresBlock.", params, &num_params); return(FALSE); } if (to_val->addr != NULL) { if (to_val->size < sizeof(EditresBlock)) { to_val->size = sizeof(EditresBlock); return(FALSE); } *(EditresBlock *)(to_val->addr) = block; } else to_val->addr = (XtPointer) block; to_val->size = sizeof(EditresBlock); return(TRUE); } #define XtREditresBlock ("EditresBlock") /* Function Name: LoadResources * Description: Loads a global resource the determines of this * application should allow Editres requests. * Arguments: w - any widget in the tree. * Returns: none. */ static void LoadResources(w) Widget w; { static XtResource resources[] = { {"editresBlock", "EditresBlock", XtREditresBlock, sizeof(EditresBlock), XtOffsetOf(Globals, block), XtRImmediate, (XtPointer) BlockNone} }; for (; XtParent(w) != NULL; w = XtParent(w)) {} XtAppSetTypeConverter(XtWidgetToApplicationContext(w), XtRString, XtREditresBlock, CvtStringToBlock, NULL, (Cardinal) 0, XtCacheAll, NULL); XtGetApplicationResources( w, (caddr_t) &globals, resources, XtNumber(resources), NULL, (Cardinal) 0); }