summaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c915
1 files changed, 915 insertions, 0 deletions
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..bcb9a1b
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,915 @@
+/*
+ * $Xorg: utils.c,v 1.4 2001/02/09 02:05:30 xorgcvs Exp $
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ */
+
+#include <X11/Intrinsic.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Shell.h>
+#include <X11/StringDefs.h>
+
+#include <X11/Xaw/Cardinals.h>
+#include <X11/Xaw/Dialog.h>
+
+#include <stdio.h>
+
+#include "editresP.h"
+
+static WidgetResources * ParseResources();
+static int CompareResourceEntries();
+static void FreeResources(), AddResource();
+static WNode * FindWidgetFromWindowGivenNode();
+
+void CreateResourceBox();
+
+extern void PopupCentered(), PerformTreeToFileDump();
+
+/* Function Name: SetMessage(w, str)
+ * Description: shows the message to the user.
+ * Arguments: w - a label widget to show the message in.
+ * str - the string to show.
+ * Returns: none.
+ */
+
+void
+SetMessage(w, str)
+Widget w;
+char * str;
+{
+ Arg args[1];
+
+ XtSetArg(args[0], XtNlabel, str);
+ XtSetValues(w, args, ONE);
+}
+
+/* Function Name: GetAllStrings
+ * Description: Returns a list of strings that have been borken up by
+ * the character specified.
+ * Arguments: in - the string to parse.
+ * sep - the separator character.
+ * out - the strings to send out.
+ * num - the number of strings in out.
+ * Returns: none
+ */
+
+void
+GetAllStrings(in, sep, out, num)
+char *in, sep, ***out;
+int * num;
+{
+ int size, i;
+ char * ptr;
+
+ if (*in == sep) /* jump over first char if it is the sep. */
+ in++;
+
+ /*
+ * count the number of strings.
+ */
+
+ for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++)
+ ptr++;
+
+/*
+ * Create Enough space for pointers and string.
+ */
+
+ size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
+ *out = (char **) XtMalloc( (Cardinal) size);
+
+ ptr = (char *) (*out + *num);
+ strcpy(ptr, in);
+
+/*
+ * Change all `sep' characters to '\0' and stuff the pointer into
+ * the next pointer slot.
+ */
+
+ i = 1;
+ (*out)[0] = ptr;
+ while (TRUE) {
+ if ((ptr = strchr(ptr, sep)) == NULL)
+ break;
+
+ *ptr++ = '\0';
+ (*out)[i++] = ptr;
+ }
+
+/*
+ * If last string is empty then strip it off.
+ */
+
+ if ( *((*out)[i - 1]) == '\0' )
+ (*num)--;
+}
+
+/* Function Name: AddString
+ * Description: Mallocs and strcats the string onto the end of
+ * the given string.
+ * Arguments: str - string to add on to.
+ * add - string to add.
+ * Returns: none.
+ */
+
+void
+AddString(str, add)
+char ** str, *add;
+{
+ int len_str, len_add;
+ char * ptr;
+
+ len_str = ((*str) ? strlen(*str) : 0);
+ len_add = strlen(add);
+
+ *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
+ ptr = *str + len_str;
+ strcpy(ptr, add);
+}
+
+/* Function Name: FindNode
+ * Description: Finds a node give the top node, and a node id number.
+ * Arguments: top_node - the top node.
+ * id - the node id.
+ * Returns: node.
+ */
+
+WNode *
+FindNode(top_node, ids, number)
+WNode *top_node;
+unsigned long * ids;
+Cardinal number;
+{
+ int i, j;
+ WNode *node;
+
+ if (top_node == NULL)
+ return(NULL);
+
+ if (ids[0] != top_node->id)
+ return(NULL);
+
+ for (node = top_node, i = 1 ; i < number; i++) {
+ Boolean found_it = FALSE;
+
+ for (j = 0; j < node->num_children; j++) {
+ if (node->children[j]->id == ids[i]) {
+ node = node->children[j];
+ found_it = TRUE;
+ break;
+ }
+ }
+ if (!found_it)
+ return(NULL);
+ }
+ return(node);
+}
+
+/* Function Name: FindWidgetFromWindow
+ * Description: finds a widget in the current tree given its window id.
+ * Arguments: tree_info - information about this tree.
+ * win - window to search for.
+ * Returns: node - the node corrosponding to this widget.
+ */
+
+WNode *
+FindWidgetFromWindow(tree_info, win)
+TreeInfo * tree_info;
+Window win;
+{
+ if (tree_info == NULL)
+ return(NULL);
+
+ return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
+}
+
+/* Function Name: FindWidgetFromWindowGivenNode
+ * Description: finds a widget in the current tree given its window id.
+ * Arguments: node - current node.
+ * win - window to search for.
+ * Returns: node - the node corrosponding to this widget.
+ */
+
+static WNode *
+FindWidgetFromWindowGivenNode(node, win)
+WNode * node;
+Window win;
+{
+ int i;
+ WNode * ret_node;
+
+ if (node->window == win)
+ return(node);
+
+ for (i = 0; i < node->num_children; i++) {
+ ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
+ if (ret_node != NULL)
+ return(ret_node);
+ }
+ return(NULL);
+}
+
+/* Function Name: HandleXErrors
+ * Description: Handles error codes from the server.
+ * Arguments: display - the display.
+ * error - error information.
+ * Returns: none.
+ */
+
+/* ARGSUSED */
+int
+HandleXErrors(display, error)
+Display * display;
+XErrorEvent * error;
+{
+ if (error->serial != global_serial_num) {
+ (*global_old_error_handler) (display, error);
+ return(0);
+ }
+
+ if (error->error_code == BadWindow)
+ global_error_code = NO_WINDOW;
+ else {
+ if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
+ exit(1);
+ }
+ return(0);
+}
+
+/* Function Name: _DumpTreeToFile
+ * Description: Dumps the widget tree to a file
+ * Arguments: w - a random widget in the application on the
+ * currently active display
+ * tree_ptr - pointer to the widget tree info.
+ * filename - name of the file.
+ * Returns: none.
+ */
+
+/* ARGSUSED */
+
+void
+_DumpTreeToFile(w, tree_ptr, filename)
+Widget w;
+XtPointer tree_ptr;
+char * filename;
+{
+ TreeInfo * tree_info = (TreeInfo *) tree_ptr;
+ FILE * fp;
+
+ if (tree_info == NULL) {
+ SetMessage(global_screen_data.info_label,
+ res_labels[17]);
+ return;
+ }
+
+ if ( (fp = fopen(filename, "w")) == NULL ) {
+ char buf[BUFSIZ];
+
+ sprintf(buf, res_labels[24], filename);
+ SetMessage(global_screen_data.info_label, buf);
+ return;
+ }
+
+ PerformTreeToFileDump(tree_info->top_node, 0, fp);
+ fclose(fp);
+}
+
+/************************************************************
+ *
+ * The file dialog boxes are handled with this code.
+ *
+ * It automatically calls the function specified when the
+ * user selects okay, or hits <CR>.
+ *
+ * A translation is required in the app-defaults file.
+ *
+ ************************************************************/
+
+/* Function Name: _PopupFileDialog
+ * Description: Puts up a dialog box to get the filename.
+ * Arguments: str - message.
+ * default_value - the default value of the filename;
+ * func - function to call when filename has been entered.
+ * data - generic data to pass to func.
+ * Returns: none
+ */
+
+static XContext file_dialog_context = None;
+
+typedef struct _FileDialogInfo {
+ void (*func)();
+ XtPointer data;
+} FileDialogInfo;
+
+void
+_PopupFileDialog(w, str, default_value, func, data)
+Widget w;
+String str, default_value;
+void (*func)();
+XtPointer data;
+{
+ FileDialogInfo * file_info;
+ Widget shell, dialog;
+ Arg args[2];
+ Cardinal num_args;
+ void _PopdownFileDialog();
+
+ if (file_dialog_context == None)
+ file_dialog_context = XUniqueContext();
+
+ shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
+ NULL, ZERO);
+
+ num_args = 0;
+ XtSetArg(args[num_args], XtNlabel, str); num_args++;
+ XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
+ dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
+ shell, args, num_args);
+
+ file_info = XtNew(FileDialogInfo);
+
+ file_info->func = func;
+ file_info->data = data;
+
+ if (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
+ (XPointer) file_info) != 0) {
+ SetMessage(global_screen_data.info_label,
+ "Error while trying to save Context\nAborting file dialog popup.");
+ XtDestroyWidget(shell);
+ return;
+ }
+
+ XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
+ XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
+
+ PopupCentered(NULL, shell, XtGrabNone);
+}
+
+/* Function Name: PopupCentered
+ * Description: Pops up the window specified under the location passed
+ * in the event, or under the cursor.
+ * Arguments: event - the event that we should use.
+ * w - widget to popup.
+ * mode - mode to pop it up in.
+ * Returns: none
+ */
+
+void
+PopupCentered(event, w, mode)
+XEvent * event;
+Widget w;
+XtGrabKind mode;
+{
+ Boolean get_from_cursor = FALSE;
+ Arg args[3];
+ Cardinal num_args;
+ Dimension width, height, b_width;
+ int x, y, max_x, max_y;
+
+ XtRealizeWidget(w);
+
+ if (event == NULL)
+ get_from_cursor = TRUE;
+ else {
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ x = event->xbutton.x_root;
+ y = event->xbutton.y_root;
+ break;
+ case KeyPress:
+ case KeyRelease:
+ x = event->xkey.x_root;
+ y = event->xkey.y_root;
+ break;
+ default:
+ get_from_cursor = TRUE;
+ break;
+ }
+ }
+
+ if (get_from_cursor) {
+ Window root, child;
+ int win_x, win_y;
+ unsigned int mask;
+
+ XQueryPointer(XtDisplay(w), XtWindow(w),
+ &root, &child, &x, &y, &win_x, &win_y, &mask);
+ }
+
+ num_args = 0;
+ XtSetArg(args[num_args], XtNwidth, &width); num_args++;
+ XtSetArg(args[num_args], XtNheight, &height); num_args++;
+ XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
+ XtGetValues(w, args, num_args);
+
+ width += 2 * b_width;
+ height += 2 * b_width;
+
+ x -= ((int) width/2);
+ if (x < 0)
+ x = 0;
+ if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
+ x = max_x;
+
+ y -= ( (Position) height/2 );
+ if (y < 0)
+ y = 0;
+ if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
+ y = max_y;
+
+ num_args = 0;
+ XtSetArg(args[num_args], XtNx, x); num_args++;
+ XtSetArg(args[num_args], XtNy, y); num_args++;
+ XtSetValues(w, args, num_args);
+
+ XtPopup(w, mode);
+}
+
+/* Function Name: _PopdownFileDialog
+ * Description: Destroys the file dialog, and calls the correct function.
+ * Arguments: w - a child of the dialog widget.
+ * client_data - TRUE if command was sucessful.
+ * junk - ** UNUSED **.
+ * Returns: none.
+ */
+
+/* ARGSUSED */
+
+void
+_PopdownFileDialog(w, client_data, junk)
+Widget w;
+XtPointer client_data, junk;
+{
+ Widget dialog = XtParent(w);
+ XPointer file_info_ptr;
+ FileDialogInfo * file_info;
+
+ if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
+ &file_info_ptr) == XCNOENT) {
+ SetMessage(global_screen_data.info_label,
+ "Error while trying to find Context\nAborting...");
+ }
+
+ (void) XDeleteContext(XtDisplay(dialog), (Window)dialog,
+ file_dialog_context);
+
+ file_info = (FileDialogInfo *) file_info_ptr;
+
+ if ( ((Boolean)(long) client_data) == TRUE ) {
+ String filename = XawDialogGetValueString(dialog);
+
+ (*file_info->func)(w, file_info->data, filename); /* call handler */
+ }
+
+ XtFree( (XtPointer) file_info); /* Free data. */
+
+ XtPopdown(XtParent(dialog));
+ XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
+}
+
+/************************************************************
+ *
+ * Functions for dealing with the Resource Box.
+ *
+ ************************************************************/
+
+/* Function Name: GetNamesAndClasses
+ * Description: Gets a list of names and classes for this widget.
+ * Arguments: node - this widget's node.
+ * names, classes - list of names and classes. ** RETURNED **
+ * Returns: none.
+ */
+
+void
+GetNamesAndClasses(node, names, classes)
+WNode * node;
+char *** names, ***classes;
+{
+ int i, total_widgets;
+ WNode * temp = node;
+
+ for (total_widgets = 1 ; temp->parent != NULL ;
+ total_widgets++, temp = temp->parent) {}
+
+ *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
+ *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
+
+ (*names)[total_widgets] = (*classes)[total_widgets] = NULL;
+
+ for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
+ (*names)[i] = node->name;
+ (*classes)[i] = node->class;
+ }
+}
+
+/* Function Name: HandleGetResources
+ * Description: Gets the resources.
+ * Arguments: event - the information from the client.
+ * Returns: an error message to display.
+ */
+
+char *
+HandleGetResources(event)
+Event * event;
+{
+ GetResourcesEvent * get_event = (GetResourcesEvent *) event;
+ char buf[BUFSIZ], * errors = NULL;
+ int i;
+ WNode * node;
+
+ for (i = 0; i < (int)get_event->num_entries; i++) {
+ node = FindNode(global_tree_info->top_node,
+ get_event->info[i].widgets.ids,
+ get_event->info[i].widgets.num_widgets);
+
+ if (node == NULL) {
+ sprintf(buf, res_labels[16]);
+ AddString(&errors, buf);
+ continue;
+ }
+
+ if (node->resources != NULL)
+ FreeResources(node->resources);
+
+ if (!get_event->info[i].error) {
+ node->resources = ParseResources(get_event->info + i, &errors);
+ CreateResourceBox(node, &errors);
+ }
+ else {
+ AddString(&errors, get_event->info[i].message);
+ AddString(&errors, "\n");
+ }
+ }
+
+ return(errors);
+}
+
+/* Function Name: CreateResourceBox
+ * Description: Creates a resource box for the widget specified.
+ * Arguments: node - the node of the widget in question.
+ * errors - an error string.
+ * Returns: none.
+ */
+
+void
+CreateResourceBox(node, errors)
+WNode * node;
+char ** errors;
+{
+ void CreateResourceBoxWidgets();
+ WidgetResources * resources = node->resources;
+ char ** names, ** cons_names;
+ int i;
+
+ if (global_resource_box_up) {
+ AddString(errors, res_labels[34]);
+ return;
+ }
+ else
+ global_resource_box_up = TRUE;
+
+ if (resources->num_normal > 0) {
+ names = (char **) XtMalloc(sizeof(char *) *
+ (resources->num_normal + 1));
+ for (i = 0 ; i < resources->num_normal ; i++)
+ names[i] = resources->normal[i].name;
+ names[i] = NULL;
+ }
+ else
+ names = NULL;
+
+ if (resources->num_constraint > 0) {
+ cons_names = (char **) XtMalloc(sizeof(char *) *
+ (resources->num_constraint + 1));
+
+ for (i = 0 ; i < resources->num_constraint ; i++)
+ cons_names[i] = resources->constraint[i].name;
+ cons_names[i] = NULL;
+ }
+ else
+ cons_names = NULL;
+
+ CreateResourceBoxWidgets(node, names, cons_names);
+}
+
+/* Function Name: ParseResources
+ * Description: Parses the resource values returned from the client
+ * into a resources structure.
+ * Arguments: info - info about a widget's resources.
+ * error - where to place error info.
+ * Returns: The resource information.
+ */
+
+static WidgetResources *
+ParseResources(info, error)
+GetResourcesInfo * info;
+char **error;
+{
+ WidgetResources * resources;
+ WidgetResourceInfo * normal;
+ int i;
+
+ resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources));
+
+ /*
+ * Allocate enough space for both the normal and constraint resources,
+ * then add the normal resources from the top, and the constraint resources
+ * from the bottom. This assures that enough memory is allocated, and
+ * that there is no overlap.
+ */
+
+ resources->normal = (WidgetResourceInfo *)
+ XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
+
+ normal = resources->normal;
+ resources->constraint = resources->normal + info->num_resources - 1;
+
+ resources->num_constraint = resources->num_normal = 0;
+
+ for (i = 0; i < (int)info->num_resources; i++) {
+ switch((int) info->res_info[i].res_type) {
+ case NormalResource:
+ resources->num_normal++;
+ AddResource(info->res_info + i, normal++);
+ break;
+ case ConstraintResource:
+ resources->num_constraint++;
+ AddResource(info->res_info + i, resources->constraint--);
+ break;
+ default:
+ {
+ char buf[BUFSIZ];
+ sprintf(buf, "Unknown resource type %d\n",
+ info->res_info[i].res_type);
+ AddString(error, buf);
+ }
+ break;
+ }
+ }
+
+ /*
+ * Sort the resources alphabetically.
+ */
+
+ qsort(resources->normal, resources->num_normal,
+ sizeof(WidgetResourceInfo), CompareResourceEntries);
+
+ if (resources->num_constraint > 0) {
+ resources->constraint++;
+ qsort(resources->constraint, resources->num_constraint,
+ sizeof(WidgetResourceInfo), CompareResourceEntries);
+ }
+ else
+ resources->constraint = NULL;
+
+ return(resources);
+}
+
+/* Function Name: CompareResourceEntries
+ * Description: Compares two resource entries.
+ * Arguments: e1, e2 - the entries to compare.
+ * Returns: an integer >, < or = 0.
+ */
+
+static int
+CompareResourceEntries(e1, e2)
+WidgetResourceInfo *e1, *e2;
+{
+ return (strcmp(e1->name, e2->name));
+}
+
+/* Function Name: AddResource
+ * Description: Parses the resource string a stuffs in individual
+ * parts into the resource info struct.
+ * Arguments: res_info - the resource info from the event.
+ * resource - location to stuff the resource into.
+ * Returns: none.
+ */
+
+static void
+AddResource(res_info, resource)
+ResourceInfo * res_info;
+WidgetResourceInfo * resource;
+{
+ resource->name = res_info->name;
+ res_info->name = NULL; /* Keeps it from being deallocated. */
+ resource->class = res_info->class;
+ res_info->class = NULL; /* Keeps it from being deallocated. */
+ resource->type = res_info->type;
+ res_info->type = NULL; /* Keeps it from being deallocated. */
+}
+
+
+/* Function Name: FreeResources
+ * Description: frees the resource inforation.
+ * Arguments: resources.
+ * Returns: none.
+ */
+
+static void
+FreeResources(resources)
+WidgetResources * resources;
+{
+ int i;
+
+ if (resources->num_normal > 0) {
+ for (i = 0; i < resources->num_normal; i++) {
+ XtFree(resources->normal[i].name);
+ XtFree(resources->normal[i].class);
+ XtFree(resources->normal[i].type);
+ }
+ XFree((char *)resources->normal);
+ }
+
+ if (resources->num_constraint > 0) {
+ for (i = 0; i < resources->num_constraint; i++) {
+ XtFree(resources->constraint[i].name);
+ XtFree(resources->constraint[i].class);
+ XtFree(resources->constraint[i].type);
+ }
+ XFree((char *)resources->constraint);
+ }
+
+ XFree((char *)resources);
+}
+
+
+/* Function Name: CheckDatabase
+ * Description: Checks to see if the node is in the database.
+ * Arguments: db - the db to check
+ * names, clases - names and clases, represented as quarks.
+ * Returns: True if this entry is found.
+ */
+
+Boolean
+CheckDatabase(db, names, classes)
+XrmDatabase db;
+XrmQuarkList names, classes;
+{
+ XrmRepresentation junk;
+ XrmValue garbage;
+
+ return(XrmQGetResource(db, names, classes, &junk, &garbage));
+}
+
+/* Function Name: Quarkify
+ * Description: Quarkifies the string list specifed.
+ * Arguments: list - list of strings to quarkify
+ * ptr - an additional string to quarkify.
+ * Returns: none.
+ */
+
+XrmQuarkList
+Quarkify(list, ptr)
+char ** list;
+char * ptr;
+{
+ int i;
+ char ** tlist;
+ XrmQuarkList quarks, tquarks;
+
+ for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
+ if (ptr != NULL)
+ i++;
+ i++; /* leave space for NULLQUARK */
+
+ quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
+
+ for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++)
+ *tquarks = XrmStringToQuark(*tlist);
+
+ if (ptr != NULL)
+ *tquarks++ = XrmStringToQuark(ptr);
+
+ *tquarks = NULLQUARK;
+ return(quarks);
+}
+
+/* Function Name: ExecuteOverAllNodes
+ * Description: Executes the given function over all nodes.
+ * Arguments: top_node - top node of the tree.
+ * func - the function to execute.
+ * data - a data pointer to pass to the function.
+ * Returns: none
+ */
+
+void
+ExecuteOverAllNodes(top_node, func, data)
+WNode * top_node;
+void (*func)();
+XtPointer data;
+{
+ int i;
+
+ (*func)(top_node, data);
+
+ for (i = 0; i < top_node->num_children; i++)
+ ExecuteOverAllNodes(top_node->children[i], func, data);
+}
+
+/* Function Name: InsertWidgetFromNode
+ * Description: Inserts the widget info for this widget represented
+ * by this node.
+ * Arguments: stream - the stream to insert it info into.
+ * none - the widget node to insert.
+ * Returns: none
+ */
+
+void
+InsertWidgetFromNode(stream, node)
+ProtocolStream * stream;
+WNode * node;
+{
+ WNode *temp;
+ unsigned long * widget_list;
+ register int i, num_widgets;
+
+ for (temp = node, i = 0; temp != 0; temp = temp->parent, 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 = node; temp != 0; temp = temp->parent, i--)
+ widget_list[i] = temp->id;
+
+ _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);
+}
+
+/* Function Name: GetFailureMesssage
+ * Description: returns the message returned from a failed request.
+ * Arguments: stream - the protocol stream containing the message.
+ * Returns: message to show.
+ */
+
+char *
+GetFailureMessage(stream)
+ProtocolStream * stream;
+{
+ char * return_str;
+
+ if (_XEditResGetString8(stream, &return_str))
+ return(return_str);
+
+ return(XtNewString(res_labels[35]));
+}
+
+/* Function Name: ProtocolFailure
+ * Description: Gets the version of the protocol the client is
+ * willing to speak.
+ * Arguments: stream - the protocol stream containing the message.
+ * Returns: message to show.
+ */
+
+char *
+ProtocolFailure(stream)
+ProtocolStream * stream;
+{
+ char buf[BUFSIZ];
+ unsigned char version;
+ char* old_version_string;
+
+ if (!_XEditResGet8(stream, &version))
+ return(XtNewString(res_labels[35]));
+
+ switch ((int)version) {
+ case PROTOCOL_VERSION_ONE_POINT_ZERO: old_version_string = "1.0"; break;
+ default: old_version_string = "1.0";
+ }
+
+ sprintf(buf, res_labels[36],
+ CURRENT_PROTOCOL_VERSION_STRING, old_version_string);
+ return(XtNewString(buf));
+}
+