Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  *
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24  */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 # include "config.h"
     28 #endif
     29 
     30 #include <X11/Intrinsic.h>
     31 #include <X11/Xutil.h>
     32 #include <X11/Xos.h>
     33 #include <X11/Shell.h>
     34 #include <X11/StringDefs.h>
     35 
     36 #include <X11/Xaw/Cardinals.h>
     37 #include <X11/Xaw/Dialog.h>
     38 
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <X11/Xmu/Error.h>
     42 
     43 #include "editresP.h"
     44 
     45 static WNode * FindWidgetFromWindowGivenNode ( WNode * node, Window win );
     46 static WidgetResources * ParseResources ( GetResourcesInfo * info,
     47 					  char **error );
     48 static int CompareResourceEntries ( const void *e1,
     49 				    const void *e2 );
     50 static void AddResource ( ResourceInfo * res_info,
     51 			  WidgetResourceInfo * resource );
     52 static void FreeResources ( WidgetResources * resources );
     53 
     54 
     55 /*	Function Name: SetMessage(w, str)
     56  *	Description: shows the message to the user.
     57  *	Arguments: w - a label widget to show the message in.
     58  *                 str - the string to show.
     59  *	Returns: none.
     60  */
     61 
     62 void
     63 SetMessage(Widget w, const char *str)
     64 {
     65     Arg args[1];
     66 
     67     XtSetArg(args[0], XtNlabel, str);
     68     XtSetValues(w, args, ONE);
     69 }
     70 
     71 /*	Function Name: GetAllStrings
     72  *	Description: Returns a list of strings that have been broken up by
     73  *                   the character specified.
     74  *	Arguments: in - the string to parse.
     75  *                 sep - the separator character.
     76  *                 out - the strings to send out.
     77  *                 num - the number of strings in out.
     78  *	Returns: none
     79  */
     80 
     81 void
     82 GetAllStrings(char *in, char sep, char ***out, int *num)
     83 {
     84     int size, i;
     85     char * ptr;
     86 
     87     if (*in == sep)		/* jump over first char if it is the sep. */
     88 	in++;
     89 
     90     /*
     91      * count the number of strings.
     92      */
     93 
     94     for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++)
     95 	ptr++;
     96 
     97 /*
     98  * Create Enough space for pointers and string.
     99  */
    100 
    101     size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
    102     *out = (char **) XtMalloc( (Cardinal) size);
    103 
    104     ptr = (char *) (*out + *num);
    105     strcpy(ptr, in);
    106 
    107 /*
    108  * Change all `sep' characters to '\0' and stuff the pointer into
    109  * the next pointer slot.
    110  */
    111 
    112     i = 1;
    113     (*out)[0] = ptr;
    114     while (TRUE) {
    115 	if ((ptr = strchr(ptr, sep)) == NULL)
    116 	    break;
    117 
    118 	*ptr++ = '\0';
    119 	(*out)[i++] = ptr;
    120     }
    121 
    122 /*
    123  * If last string is empty then strip it off.
    124  */
    125 
    126     if ( *((*out)[i - 1]) == '\0' )
    127 	(*num)--;
    128 }
    129 
    130 /*	Function Name: AddString
    131  *	Description: Mallocs and strcats the string onto the end of
    132  *                   the given string.
    133  *	Arguments: str - string to add on to.
    134  *                 add - string to add.
    135  *	Returns: none.
    136  */
    137 
    138 void
    139 AddString(char ** str, const char *add)
    140 {
    141     int len_str, len_add;
    142     char * ptr;
    143 
    144     len_str = ((*str) ? strlen(*str) : 0);
    145     len_add = strlen(add);
    146 
    147     *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
    148     ptr = *str + len_str;
    149     strcpy(ptr, add);
    150 }
    151 
    152 /*	Function Name: FindNode
    153  *	Description: Finds a node give the top node, and a node id number.
    154  *	Arguments: top_node - the top node.
    155  *                 id - the node id.
    156  *	Returns: node.
    157  */
    158 
    159 WNode *
    160 FindNode(WNode *top_node, CARD64 *ids, Cardinal number)
    161 {
    162     Cardinal i, j;
    163     WNode *node;
    164 
    165     if (top_node == NULL)
    166 	return(NULL);
    167 
    168     if (ids[0] != top_node->id)
    169 	return(NULL);
    170 
    171     for (node = top_node, i = 1 ; i < number; i++) {
    172 	Boolean found_it = FALSE;
    173 
    174 	for (j = 0; j < node->num_children; j++) {
    175 	    if (node->children[j]->id == ids[i]) {
    176 		node = node->children[j];
    177 		found_it = TRUE;
    178 		break;
    179 	    }
    180 	}
    181 	if (!found_it)
    182 	    return(NULL);
    183     }
    184     return(node);
    185 }
    186 
    187 /*	Function Name: FindWidgetFromWindow
    188  *	Description: finds a widget in the current tree given its window id.
    189  *	Arguments: tree_info - information about this tree.
    190  *                 win - window to search for.
    191  *	Returns: node - the node corrosponding to this widget.
    192  */
    193 
    194 WNode *
    195 FindWidgetFromWindow(TreeInfo *tree_info, Window win)
    196 {
    197     if (tree_info == NULL)
    198 	return(NULL);
    199 
    200     return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
    201 }
    202 
    203 /*	Function Name: FindWidgetFromWindowGivenNode
    204  *	Description: finds a widget in the current tree given its window id.
    205  *	Arguments: node - current node.
    206  *                 win - window to search for.
    207  *	Returns: node - the node corrosponding to this widget.
    208  */
    209 
    210 static WNode *
    211 FindWidgetFromWindowGivenNode(WNode *node, Window win)
    212 {
    213     Cardinal i;
    214     WNode * ret_node;
    215 
    216     if (node->window == win)
    217 	return(node);
    218 
    219     for (i = 0; i < node->num_children; i++) {
    220 	ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
    221 	if (ret_node != NULL)
    222 	    return(ret_node);
    223     }
    224     return(NULL);
    225 }
    226 
    227 /*	Function Name: HandleXErrors
    228  *	Description: Handles error codes from the server.
    229  *	Arguments: display - the display.
    230  *                 error - error information.
    231  *	Returns: none.
    232  */
    233 
    234 /* ARGSUSED */
    235 int
    236 HandleXErrors(Display *display, XErrorEvent *error)
    237 {
    238     if (error->serial != global_serial_num) {
    239 	(*global_old_error_handler) (display, error);
    240 	return(0);
    241     }
    242 
    243     if (error->error_code == BadWindow)
    244 	global_error_code = NO_WINDOW;
    245     else {
    246 	if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
    247 	    exit(1);
    248     }
    249     return(0);
    250 }
    251 
    252 /*	Function Name: _DumpTreeToFile
    253  *	Description: Dumps the widget tree to a file
    254  *	Arguments: w - a random widget in the application on the
    255  *                     currently active display
    256  *                 tree_ptr - pointer to the widget tree info.
    257  *                 filename - name of the file.
    258  *	Returns: none.
    259  */
    260 
    261 /* ARGSUSED */
    262 
    263 void
    264 _DumpTreeToFile(Widget w, XtPointer tree_ptr, XtPointer filename)
    265 {
    266     TreeInfo * tree_info = (TreeInfo *) tree_ptr;
    267     FILE * fp;
    268 
    269     if (tree_info == NULL) {
    270 	SetMessage(global_screen_data.info_label,
    271 		   res_labels[17]);
    272 	return;
    273     }
    274 
    275     if ( (fp = fopen((char *)filename, "w")) == NULL ) {
    276 	char buf[BUFSIZ];
    277 
    278 	snprintf(buf, sizeof(buf), res_labels[24], (char *)filename);
    279 	SetMessage(global_screen_data.info_label, buf);
    280 	return;
    281     }
    282 
    283     PerformTreeToFileDump(tree_info->top_node, 0, fp);
    284     fclose(fp);
    285 }
    286 
    287 /************************************************************
    288  *
    289  * The file dialog boxes are handled with this code.
    290  *
    291  * It automatically calls the function specified when the
    292  * user selects okay, or hits <CR>.
    293  *
    294  * A translation is required in the app-defaults file.
    295  *
    296  ************************************************************/
    297 
    298 /*	Function Name: _PopupFileDialog
    299  *	Description: Puts up a dialog box to get the filename.
    300  *	Arguments: str - message.
    301  *                 default_value - the default value of the filename;
    302  *                 func - function to call when filename has been entered.
    303  *                 data - generic data to pass to func.
    304  *	Returns: none
    305  */
    306 
    307 static XContext file_dialog_context = None;
    308 
    309 typedef struct _FileDialogInfo {
    310     XtCallbackProc func;
    311     XtPointer data;
    312 } FileDialogInfo;
    313 
    314 void
    315 _PopupFileDialog(Widget w, const char *str, const char *default_value,
    316 		 XtCallbackProc func, XtPointer data)
    317 {
    318     FileDialogInfo * file_info;
    319     Widget shell, dialog;
    320     Arg args[2];
    321     Cardinal num_args;
    322 
    323     if (file_dialog_context == None)
    324 	file_dialog_context = XUniqueContext();
    325 
    326     shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
    327 			       NULL, ZERO);
    328 
    329     num_args = 0;
    330     XtSetArg(args[num_args], XtNlabel, str); num_args++;
    331     XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
    332     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
    333 				   shell, args, num_args);
    334 
    335     file_info = XtNew(FileDialogInfo);
    336 
    337     file_info->func = func;
    338     file_info->data = data;
    339 
    340     if  (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
    341 		      (XPointer) file_info) != 0) {
    342 	SetMessage(global_screen_data.info_label,
    343 	    "Error while trying to save Context\nAborting file dialog popup.");
    344 	XtDestroyWidget(shell);
    345 	return;
    346     }
    347 
    348     XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
    349     XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
    350 
    351     PopupCentered(NULL, shell, XtGrabNone);
    352 }
    353 
    354 /*	Function Name: PopupCentered
    355  *	Description: Pops up the window specified under the location passed
    356  *                   in the event, or under the cursor.
    357  *	Arguments: event - the event that we should use.
    358  *                 w - widget to popup.
    359  *                 mode - mode to pop it up in.
    360  *	Returns: none
    361  */
    362 
    363 void
    364 PopupCentered(XEvent *event, Widget w, XtGrabKind mode)
    365 {
    366     Boolean get_from_cursor = FALSE;
    367     Arg args[3];
    368     Cardinal num_args;
    369     Dimension width, height, b_width;
    370     int x, y, max_x, max_y;
    371 
    372     XtRealizeWidget(w);
    373 
    374     if (event == NULL)
    375 	get_from_cursor = TRUE;
    376     else {
    377 	switch (event->type) {
    378 	case ButtonPress:
    379 	case ButtonRelease:
    380 	    x = event->xbutton.x_root;
    381 	    y = event->xbutton.y_root;
    382 	    break;
    383 	case KeyPress:
    384 	case KeyRelease:
    385 	    x = event->xkey.x_root;
    386 	    y = event->xkey.y_root;
    387 	    break;
    388 	default:
    389 	    get_from_cursor = TRUE;
    390 	    break;
    391 	}
    392     }
    393 
    394     if (get_from_cursor) {
    395 	Window root, child;
    396 	int win_x, win_y;
    397 	unsigned int mask;
    398 
    399 	XQueryPointer(XtDisplay(w), XtWindow(w),
    400 		      &root, &child, &x, &y, &win_x, &win_y, &mask);
    401     }
    402 
    403     num_args = 0;
    404     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
    405     XtSetArg(args[num_args], XtNheight, &height); num_args++;
    406     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
    407     XtGetValues(w, args, num_args);
    408 
    409     width += 2 * b_width;
    410     height += 2 * b_width;
    411 
    412     x -= ((int) width/2);
    413     if (x < 0)
    414 	x = 0;
    415     if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
    416 	x = max_x;
    417 
    418     y -= ( (Position) height/2 );
    419     if (y < 0)
    420 	y = 0;
    421     if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
    422 	y = max_y;
    423 
    424     num_args = 0;
    425     XtSetArg(args[num_args], XtNx, x); num_args++;
    426     XtSetArg(args[num_args], XtNy, y); num_args++;
    427     XtSetValues(w, args, num_args);
    428 
    429     XtPopup(w, mode);
    430 }
    431 
    432 /*	Function Name: _PopdownFileDialog
    433  *	Description: Destroys the file dialog, and calls the correct function.
    434  *	Arguments:  w - a child of the dialog widget.
    435  *                  client_data - TRUE if command was successful.
    436  *                  junk - ** UNUSED **.
    437  *	Returns: none.
    438  */
    439 
    440 /* ARGSUSED */
    441 
    442 void
    443 _PopdownFileDialog(Widget w, XtPointer client_data, XtPointer junk)
    444 {
    445     Widget dialog = XtParent(w);
    446     XPointer file_info_ptr;
    447     FileDialogInfo * file_info;
    448 
    449     if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
    450 		     &file_info_ptr) == XCNOENT) {
    451 	SetMessage(global_screen_data.info_label,
    452 		   "Error while trying to find Context\nAborting...");
    453     }
    454 
    455     (void) XDeleteContext(XtDisplay(dialog), (Window)dialog,
    456 			  file_dialog_context);
    457 
    458     file_info = (FileDialogInfo *) file_info_ptr;
    459 
    460     if ( ((Boolean)(long) client_data) == TRUE ) {
    461 	String filename = XawDialogGetValueString(dialog);
    462 
    463 	(*file_info->func)(w, file_info->data, filename); /* call handler */
    464     }
    465 
    466     XtFree( (XtPointer) file_info); /* Free data. */
    467 
    468     XtPopdown(XtParent(dialog));
    469     XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
    470 }
    471 
    472 /************************************************************
    473  *
    474  * Functions for dealing with the Resource Box.
    475  *
    476  ************************************************************/
    477 
    478 /*    Function Name: GetNamesAndClasses
    479  *    Description: Gets a list of names and classes for this widget.
    480  *    Arguments: node - this widget's node.
    481  *                 names, classes - list of names and classes. ** RETURNED **
    482  *    Returns: none.
    483  */
    484 
    485 void
    486 GetNamesAndClasses(WNode *node, char ***names, char ***classes)
    487 {
    488     int i, total_widgets;
    489     WNode * temp = node;
    490 
    491     for (total_widgets = 1 ; temp->parent != NULL ;
    492        total_widgets++, temp = temp->parent) {}
    493 
    494     *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
    495     *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
    496 
    497     (*names)[total_widgets] = (*classes)[total_widgets] = NULL;
    498 
    499     for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
    500       (*names)[i] = node->name;
    501       (*classes)[i] = node->class;
    502     }
    503 }
    504 
    505 /*	Function Name: HandleGetResources
    506  *	Description: Gets the resources.
    507  *	Arguments: event - the information from the client.
    508  *	Returns: an error message to display.
    509  */
    510 
    511 char *
    512 HandleGetResources(Event *event)
    513 {
    514     GetResourcesEvent * get_event = (GetResourcesEvent *) event;
    515     char buf[BUFSIZ], * errors = NULL;
    516     int i;
    517     WNode * node;
    518 
    519     for (i = 0; i < (int)get_event->num_entries; i++) {
    520 	node = FindNode(global_tree_info->top_node,
    521 			get_event->info[i].widgets.ids,
    522 			get_event->info[i].widgets.num_widgets);
    523 
    524 	if (node == NULL) {
    525 	    snprintf(buf, sizeof(buf), res_labels[16]);
    526 	    AddString(&errors, buf);
    527 	    continue;
    528 	}
    529 
    530 	if (node->resources != NULL)
    531 	    FreeResources(node->resources);
    532 
    533 	if (!get_event->info[i].error) {
    534 	    node->resources = ParseResources(get_event->info + i, &errors);
    535 	    CreateResourceBox(node, &errors);
    536 	}
    537 	else {
    538 	    AddString(&errors, get_event->info[i].message);
    539 	    AddString(&errors, "\n");
    540 	}
    541     }
    542 
    543     return(errors);
    544 }
    545 
    546 /*	Function Name: CreateResourceBox
    547  *	Description: Creates a resource box for the widget specified.
    548  *	Arguments: node - the node of the widget in question.
    549  *                 errors - an error string.
    550  *	Returns: none.
    551  */
    552 
    553 void
    554 CreateResourceBox(WNode *node, char **errors)
    555 {
    556     WidgetResources * resources = node->resources;
    557     char ** names, ** cons_names;
    558     int i;
    559 
    560     if (global_resource_box_up) {
    561 	AddString(errors, res_labels[34]);
    562 	return;
    563     }
    564     else
    565 	global_resource_box_up = TRUE;
    566 
    567     if (resources->num_normal > 0) {
    568 	names = (char **) XtMalloc(sizeof(char *) *
    569 				   (resources->num_normal + 1));
    570 	for (i = 0 ; i < resources->num_normal ; i++)
    571 	    names[i] = resources->normal[i].name;
    572 	names[i] = NULL;
    573     }
    574     else
    575 	names = NULL;
    576 
    577     if (resources->num_constraint > 0) {
    578 	cons_names = (char **) XtMalloc(sizeof(char *) *
    579 					(resources->num_constraint + 1));
    580 
    581 	for (i = 0 ; i < resources->num_constraint ; i++)
    582 	    cons_names[i] = resources->constraint[i].name;
    583 	cons_names[i] = NULL;
    584     }
    585     else
    586 	cons_names = NULL;
    587 
    588     CreateResourceBoxWidgets(node, names, cons_names);
    589 }
    590 
    591 /*	Function Name: ParseResources
    592  *	Description: Parses the resource values returned from the client
    593  *                   into a resources structure.
    594  *	Arguments: info - info about a widget's resources.
    595  *                 error - where to place error info.
    596  *	Returns: The resource information.
    597  */
    598 
    599 static WidgetResources *
    600 ParseResources(GetResourcesInfo *info, char **error)
    601 {
    602     WidgetResources * resources;
    603     WidgetResourceInfo * normal;
    604     int i;
    605 
    606     resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources));
    607 
    608     /*
    609      * Allocate enough space for both the normal and constraint resources,
    610      * then add the normal resources from the top, and the constraint resources
    611      * from the bottom.  This assures that enough memory is allocated, and
    612      * that there is no overlap.
    613      */
    614 
    615     resources->normal = (WidgetResourceInfo *)
    616 	            XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
    617 
    618     normal = resources->normal;
    619     resources->constraint = resources->normal + info->num_resources - 1;
    620 
    621     resources->num_constraint = resources->num_normal = 0;
    622 
    623     for (i = 0; i < (int)info->num_resources; i++) {
    624 	switch((int) info->res_info[i].res_type) {
    625 	case NormalResource:
    626 	    resources->num_normal++;
    627 	    AddResource(info->res_info + i, normal++);
    628 	    break;
    629 	case ConstraintResource:
    630 	    resources->num_constraint++;
    631 	    AddResource(info->res_info + i, resources->constraint--);
    632 	    break;
    633 	default:
    634 	    {
    635 		char buf[BUFSIZ];
    636 		snprintf(buf, sizeof(buf), "Unknown resource type %d\n",
    637                          info->res_info[i].res_type);
    638 		AddString(error, buf);
    639 	    }
    640 	    break;
    641 	}
    642     }
    643 
    644     /*
    645      * Sort the resources alphabetically.
    646      */
    647 
    648     qsort(resources->normal, resources->num_normal,
    649 	  sizeof(WidgetResourceInfo), CompareResourceEntries);
    650 
    651     if (resources->num_constraint > 0) {
    652 	resources->constraint++;
    653 	qsort(resources->constraint, resources->num_constraint,
    654 	      sizeof(WidgetResourceInfo), CompareResourceEntries);
    655     }
    656     else
    657 	resources->constraint = NULL;
    658 
    659     return(resources);
    660 }
    661 
    662 /*	Function Name: CompareResourceEntries
    663  *	Description: Compares two resource entries.
    664  *	Arguments: e1, e2 - the entries to compare.
    665  *	Returns: an integer >, < or = 0.
    666  */
    667 
    668 static int
    669 CompareResourceEntries(const void *e1, const void *e2)
    670 {
    671     return (strcmp(((WidgetResourceInfo *)e1)->name,
    672 		   ((WidgetResourceInfo *)e2)->name));
    673 }
    674 
    675 /*	Function Name: AddResource
    676  *	Description: Parses the resource string a stuffs in individual
    677  *                   parts into the resource info struct.
    678  *	Arguments: res_info - the resource info from the event.
    679  *                 resource - location to stuff the resource into.
    680  *	Returns: none.
    681  */
    682 
    683 static void
    684 AddResource(ResourceInfo *res_info, WidgetResourceInfo *resource)
    685 {
    686     resource->name = res_info->name;
    687     res_info->name = NULL;	/* Keeps it from being deallocated. */
    688     resource->class = res_info->class;
    689     res_info->class = NULL;	/* Keeps it from being deallocated. */
    690     resource->type = res_info->type;
    691     res_info->type = NULL;	/* Keeps it from being deallocated. */
    692 }
    693 
    694 
    695 /*	Function Name: FreeResources
    696  *	Description: frees the resource information.
    697  *	Arguments: resources.
    698  *	Returns: none.
    699  */
    700 
    701 static void
    702 FreeResources(WidgetResources *resources)
    703 {
    704     int i;
    705 
    706     if (resources->num_normal > 0) {
    707 	for (i = 0; i < resources->num_normal; i++) {
    708 	    XtFree(resources->normal[i].name);
    709 	    XtFree(resources->normal[i].class);
    710 	    XtFree(resources->normal[i].type);
    711 	}
    712 	XFree((char *)resources->normal);
    713     }
    714 
    715     if (resources->num_constraint > 0) {
    716 	for (i = 0; i < resources->num_constraint; i++) {
    717 	    XtFree(resources->constraint[i].name);
    718 	    XtFree(resources->constraint[i].class);
    719 	    XtFree(resources->constraint[i].type);
    720 	}
    721 	XFree((char *)resources->constraint);
    722     }
    723 
    724     XFree((char *)resources);
    725 }
    726 
    727 
    728 /*	Function Name: CheckDatabase
    729  *	Description: Checks to see if the node is in the database.
    730  *	Arguments: db - the db to check
    731  *                 names, classes - names and classes, represented as quarks.
    732  *	Returns: True if this entry is found.
    733  */
    734 
    735 Boolean
    736 CheckDatabase(XrmDatabase db, XrmQuarkList names, XrmQuarkList classes)
    737 {
    738     XrmRepresentation junk;
    739     XrmValue garbage;
    740 
    741     return(XrmQGetResource(db, names, classes, &junk, &garbage));
    742 }
    743 
    744 /*	Function Name: Quarkify
    745  *	Description: Quarkifies the string list specified.
    746  *	Arguments: list - list of strings to quarkify
    747  *                 ptr - an additional string to quarkify.
    748  *	Returns: none.
    749  */
    750 
    751 XrmQuarkList
    752 Quarkify(char **list, const char *ptr)
    753 {
    754     int i;
    755     char ** tlist;
    756     XrmQuarkList quarks, tquarks;
    757 
    758     for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
    759     if (ptr != NULL)
    760 	i++;
    761     i++;			/* leave space for NULLQUARK */
    762 
    763     quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
    764 
    765     for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++)
    766 	*tquarks = XrmStringToQuark(*tlist);
    767 
    768     if (ptr != NULL)
    769 	*tquarks++ = XrmStringToQuark(ptr);
    770 
    771     *tquarks = NULLQUARK;
    772     return(quarks);
    773 }
    774 
    775 /*	Function Name: ExecuteOverAllNodes
    776  *	Description: Executes the given function over all nodes.
    777  *	Arguments: top_node - top node of the tree.
    778  *                 func - the function to execute.
    779  *                 data - a data pointer to pass to the function.
    780  *	Returns: none
    781  */
    782 
    783 void
    784 ExecuteOverAllNodes(WNode *top_node, void (*func)(WNode *, XtPointer),
    785 		    XtPointer data)
    786 {
    787     Cardinal i;
    788 
    789     (*func)(top_node, data);
    790 
    791     for (i = 0; i < top_node->num_children; i++)
    792 	ExecuteOverAllNodes(top_node->children[i], func, data);
    793 }
    794 
    795 /*	Function Name: InsertWidgetFromNode
    796  *	Description: Inserts the widget info for this widget represented
    797  *                   by this node.
    798  *	Arguments: stream - the stream to insert it info into.
    799  *                 none - the widget node to insert.
    800  *	Returns: none
    801  */
    802 
    803 void
    804 InsertWidgetFromNode(ProtocolStream *stream, WNode *node)
    805 {
    806     WNode *temp;
    807     CARD64 *widget_list;
    808     register int i, num_widgets;
    809 
    810     for (temp = node, i = 0; temp != NULL; temp = temp->parent, i++) {}
    811 
    812     num_widgets = i;
    813     widget_list = (CARD64 *)XtMalloc(sizeof(CARD64) * num_widgets);
    814 
    815     /*
    816      * Put the widgets into the list.
    817      * Make sure that they are inserted in the list from parent -> child.
    818      */
    819 
    820     for (i--, temp = node; temp != NULL; temp = temp->parent, i--)
    821 	widget_list[i] = temp->id;
    822 
    823     _XEditResPut16(stream, num_widgets);	/* insert number of widgets. */
    824     for (i = 0; i < num_widgets; i++) 	/* insert Widgets themselves. */
    825 	_XEditResPut64(stream, widget_list[i]);
    826 
    827     XtFree((char *)widget_list);
    828 }
    829 
    830 /*	Function Name: GetFailureMesssage
    831  *	Description: returns the message returned from a failed request.
    832  *	Arguments: stream - the protocol stream containing the message.
    833  *	Returns: message to show.
    834  */
    835 
    836 char *
    837 GetFailureMessage(ProtocolStream *stream)
    838 {
    839     char * return_str;
    840 
    841     if (_XEditResGetString8(stream, &return_str))
    842 	return(return_str);
    843 
    844     return(XtNewString(res_labels[35]));
    845 }
    846 
    847 /*	Function Name: ProtocolFailure
    848  *	Description: Gets the version of the protocol the client is
    849  *                   willing to speak.
    850  *	Arguments: stream - the protocol stream containing the message.
    851  *	Returns: message to show.
    852  */
    853 
    854 char *
    855 ProtocolFailure(ProtocolStream *stream)
    856 {
    857     char buf[128];
    858     unsigned char version;
    859 
    860     if (!_XEditResGet8(stream, &version))
    861 	return(XtNewString(res_labels[35]));
    862 
    863     snprintf(buf, sizeof(buf), res_labels[36],
    864              CURRENT_PROTOCOL_VERSION, version);
    865     return(XtNewString(buf));
    866 }
    867 
    868