diff options
Diffstat (limited to 'RegEdit.c')
-rw-r--r-- | RegEdit.c | 1795 |
1 files changed, 1795 insertions, 0 deletions
diff --git a/RegEdit.c b/RegEdit.c new file mode 100644 index 0000000..fa01b88 --- /dev/null +++ b/RegEdit.c @@ -0,0 +1,1795 @@ +/* $XConsortium: RegEdit.c /main/5 1995/07/15 20:44:04 drk $ */ +/* + * @OPENGROUP_COPYRIGHT@ + * COPYRIGHT NOTICE + * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. + * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group + * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for + * the full copyright text. + * + * This software is subject to an open license. It may only be + * used on, with or for operating systems which are themselves open + * source systems. You must contact The Open Group for a license + * allowing distribution and sublicensing of this software on, with, + * or for operating systems which are not Open Source programs. + * + * See http://www.opengroup.org/openmotif/license for full + * details of the license agreement. Any use, reproduction, or + * distribution of the program constitutes recipient's acceptance of + * this agreement. + * + * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS + * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY + * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY + * OR FITNESS FOR A PARTICULAR PURPOSE + * + * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT + * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE + * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ +/* + * HISTORY + */ +#include <stdio.h> +#include <Xm/XmP.h> +#include <X11/ShellP.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); +} + + |