utils.c revision ad47b356
133c89af1Smrg/*
233c89af1Smrg *
333c89af1SmrgCopyright 1989, 1998  The Open Group
433c89af1Smrg
533c89af1SmrgPermission to use, copy, modify, distribute, and sell this software and its
633c89af1Smrgdocumentation for any purpose is hereby granted without fee, provided that
733c89af1Smrgthe above copyright notice appear in all copies and that both that
833c89af1Smrgcopyright notice and this permission notice appear in supporting
933c89af1Smrgdocumentation.
1033c89af1Smrg
1133c89af1SmrgThe above copyright notice and this permission notice shall be included in
1233c89af1Smrgall copies or substantial portions of the Software.
1333c89af1Smrg
1433c89af1SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1533c89af1SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1633c89af1SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1733c89af1SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1833c89af1SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1933c89af1SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2033c89af1Smrg
2133c89af1SmrgExcept as contained in this notice, the name of The Open Group shall not be
2233c89af1Smrgused in advertising or otherwise to promote the sale, use or other dealings
2333c89af1Smrgin this Software without prior written authorization from The Open Group.
2433c89af1Smrg */
2533c89af1Smrg
2633c89af1Smrg#include <X11/Intrinsic.h>
2733c89af1Smrg#include <X11/Xutil.h>
2833c89af1Smrg#include <X11/Xos.h>
2933c89af1Smrg#include <X11/Shell.h>
3033c89af1Smrg#include <X11/StringDefs.h>
3133c89af1Smrg
3233c89af1Smrg#include <X11/Xaw/Cardinals.h>
3333c89af1Smrg#include <X11/Xaw/Dialog.h>
3433c89af1Smrg
3533c89af1Smrg#include <stdio.h>
3633c89af1Smrg#include <stdlib.h>
3733c89af1Smrg#include <X11/Xmu/Error.h>
3833c89af1Smrg
3933c89af1Smrg#include "editresP.h"
4033c89af1Smrg
4133c89af1Smrgstatic WNode * FindWidgetFromWindowGivenNode ( WNode * node, Window win );
42ad47b356Smrgstatic WidgetResources * ParseResources ( GetResourcesInfo * info,
4333c89af1Smrg					  char **error );
44ad47b356Smrgstatic int CompareResourceEntries ( const void *e1,
4533c89af1Smrg				    const void *e2 );
46ad47b356Smrgstatic void AddResource ( ResourceInfo * res_info,
4733c89af1Smrg			  WidgetResourceInfo * resource );
4833c89af1Smrgstatic void FreeResources ( WidgetResources * resources );
4933c89af1Smrg
5033c89af1Smrg
5133c89af1Smrg/*	Function Name: SetMessage(w, str)
5233c89af1Smrg *	Description: shows the message to the user.
5333c89af1Smrg *	Arguments: w - a label widget to show the message in.
5433c89af1Smrg *                 str - the string to show.
5533c89af1Smrg *	Returns: none.
5633c89af1Smrg */
5733c89af1Smrg
5833c89af1Smrgvoid
59278eca22SmrgSetMessage(Widget w, char *str)
6033c89af1Smrg{
6133c89af1Smrg    Arg args[1];
6233c89af1Smrg
6333c89af1Smrg    XtSetArg(args[0], XtNlabel, str);
6433c89af1Smrg    XtSetValues(w, args, ONE);
6533c89af1Smrg}
6633c89af1Smrg
6733c89af1Smrg/*	Function Name: GetAllStrings
6833c89af1Smrg *	Description: Returns a list of strings that have been borken up by
6933c89af1Smrg *                   the character specified.
7033c89af1Smrg *	Arguments: in - the string to parse.
7133c89af1Smrg *                 sep - the separator character.
7233c89af1Smrg *                 out - the strings to send out.
7333c89af1Smrg *                 num - the number of strings in out.
7433c89af1Smrg *	Returns: none
7533c89af1Smrg */
7633c89af1Smrg
7733c89af1Smrgvoid
7833c89af1SmrgGetAllStrings(char *in, char sep, char ***out, int *num)
7933c89af1Smrg{
8033c89af1Smrg    int size, i;
8133c89af1Smrg    char * ptr;
8233c89af1Smrg
8333c89af1Smrg    if (*in == sep)		/* jump over first char if it is the sep. */
8433c89af1Smrg	in++;
8533c89af1Smrg
8633c89af1Smrg    /*
8733c89af1Smrg     * count the number of strings.
8833c89af1Smrg     */
8933c89af1Smrg
9033c89af1Smrg    for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++)
9133c89af1Smrg	ptr++;
9233c89af1Smrg
9333c89af1Smrg/*
9433c89af1Smrg * Create Enough space for pointers and string.
9533c89af1Smrg */
9633c89af1Smrg
9733c89af1Smrg    size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
9833c89af1Smrg    *out = (char **) XtMalloc( (Cardinal) size);
9933c89af1Smrg
10033c89af1Smrg    ptr = (char *) (*out + *num);
10133c89af1Smrg    strcpy(ptr, in);
10233c89af1Smrg
10333c89af1Smrg/*
10433c89af1Smrg * Change all `sep' characters to '\0' and stuff the pointer into
10533c89af1Smrg * the next pointer slot.
10633c89af1Smrg */
10733c89af1Smrg
10833c89af1Smrg    i = 1;
10933c89af1Smrg    (*out)[0] = ptr;
11033c89af1Smrg    while (TRUE) {
11133c89af1Smrg	if ((ptr = strchr(ptr, sep)) == NULL)
11233c89af1Smrg	    break;
11333c89af1Smrg
11433c89af1Smrg	*ptr++ = '\0';
11533c89af1Smrg	(*out)[i++] = ptr;
11633c89af1Smrg    }
11733c89af1Smrg
11833c89af1Smrg/*
11933c89af1Smrg * If last string is empty then strip it off.
12033c89af1Smrg */
12133c89af1Smrg
12233c89af1Smrg    if ( *((*out)[i - 1]) == '\0' )
12333c89af1Smrg	(*num)--;
12433c89af1Smrg}
12533c89af1Smrg
12633c89af1Smrg/*	Function Name: AddString
12733c89af1Smrg *	Description: Mallocs and strcats the string onto the end of
12833c89af1Smrg *                   the given string.
12933c89af1Smrg *	Arguments: str - string to add on to.
13033c89af1Smrg *                 add - string to add.
13133c89af1Smrg *	Returns: none.
13233c89af1Smrg */
13333c89af1Smrg
13433c89af1Smrgvoid
135278eca22SmrgAddString(char ** str, char *add)
13633c89af1Smrg{
13733c89af1Smrg    int len_str, len_add;
13833c89af1Smrg    char * ptr;
13933c89af1Smrg
14033c89af1Smrg    len_str = ((*str) ? strlen(*str) : 0);
14133c89af1Smrg    len_add = strlen(add);
14233c89af1Smrg
14333c89af1Smrg    *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
14433c89af1Smrg    ptr = *str + len_str;
14533c89af1Smrg    strcpy(ptr, add);
14633c89af1Smrg}
147ad47b356Smrg
14833c89af1Smrg/*	Function Name: FindNode
14933c89af1Smrg *	Description: Finds a node give the top node, and a node id number.
15033c89af1Smrg *	Arguments: top_node - the top node.
15133c89af1Smrg *                 id - the node id.
15233c89af1Smrg *	Returns: node.
15333c89af1Smrg */
15433c89af1Smrg
15533c89af1SmrgWNode *
156278eca22SmrgFindNode(WNode *top_node, unsigned long *ids, Cardinal number)
15733c89af1Smrg{
158ad47b356Smrg    Cardinal i, j;
15933c89af1Smrg    WNode *node;
16033c89af1Smrg
16133c89af1Smrg    if (top_node == NULL)
16233c89af1Smrg	return(NULL);
16333c89af1Smrg
16433c89af1Smrg    if (ids[0] != top_node->id)
16533c89af1Smrg	return(NULL);
16633c89af1Smrg
16733c89af1Smrg    for (node = top_node, i = 1 ; i < number; i++) {
16833c89af1Smrg	Boolean found_it = FALSE;
16933c89af1Smrg
17033c89af1Smrg	for (j = 0; j < node->num_children; j++) {
17133c89af1Smrg	    if (node->children[j]->id == ids[i]) {
17233c89af1Smrg		node = node->children[j];
17333c89af1Smrg		found_it = TRUE;
17433c89af1Smrg		break;
17533c89af1Smrg	    }
17633c89af1Smrg	}
17733c89af1Smrg	if (!found_it)
17833c89af1Smrg	    return(NULL);
179ad47b356Smrg    }
18033c89af1Smrg    return(node);
18133c89af1Smrg}
18233c89af1Smrg
18333c89af1Smrg/*	Function Name: FindWidgetFromWindow
18433c89af1Smrg *	Description: finds a widget in the current tree given its window id.
18533c89af1Smrg *	Arguments: tree_info - information about this tree.
18633c89af1Smrg *                 win - window to search for.
18733c89af1Smrg *	Returns: node - the node corrosponding to this widget.
18833c89af1Smrg */
18933c89af1Smrg
190ad47b356SmrgWNode *
191278eca22SmrgFindWidgetFromWindow(TreeInfo *tree_info, Window win)
19233c89af1Smrg{
19333c89af1Smrg    if (tree_info == NULL)
19433c89af1Smrg	return(NULL);
19533c89af1Smrg
19633c89af1Smrg    return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
19733c89af1Smrg}
19833c89af1Smrg
19933c89af1Smrg/*	Function Name: FindWidgetFromWindowGivenNode
20033c89af1Smrg *	Description: finds a widget in the current tree given its window id.
20133c89af1Smrg *	Arguments: node - current node.
20233c89af1Smrg *                 win - window to search for.
20333c89af1Smrg *	Returns: node - the node corrosponding to this widget.
20433c89af1Smrg */
20533c89af1Smrg
20633c89af1Smrgstatic WNode *
207278eca22SmrgFindWidgetFromWindowGivenNode(WNode *node, Window win)
20833c89af1Smrg{
209ad47b356Smrg    Cardinal i;
21033c89af1Smrg    WNode * ret_node;
21133c89af1Smrg
21233c89af1Smrg    if (node->window == win)
21333c89af1Smrg	return(node);
21433c89af1Smrg
21533c89af1Smrg    for (i = 0; i < node->num_children; i++) {
21633c89af1Smrg	ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
21733c89af1Smrg	if (ret_node != NULL)
21833c89af1Smrg	    return(ret_node);
21933c89af1Smrg    }
22033c89af1Smrg    return(NULL);
22133c89af1Smrg}
22233c89af1Smrg
22333c89af1Smrg/*	Function Name: HandleXErrors
22433c89af1Smrg *	Description: Handles error codes from the server.
22533c89af1Smrg *	Arguments: display - the display.
22633c89af1Smrg *                 error - error information.
22733c89af1Smrg *	Returns: none.
22833c89af1Smrg */
22933c89af1Smrg
23033c89af1Smrg/* ARGSUSED */
23133c89af1Smrgint
232278eca22SmrgHandleXErrors(Display *display, XErrorEvent *error)
23333c89af1Smrg{
23433c89af1Smrg    if (error->serial != global_serial_num) {
23533c89af1Smrg	(*global_old_error_handler) (display, error);
23633c89af1Smrg	return(0);
23733c89af1Smrg    }
23833c89af1Smrg
23933c89af1Smrg    if (error->error_code == BadWindow)
240ad47b356Smrg	global_error_code = NO_WINDOW;
24133c89af1Smrg    else {
24233c89af1Smrg	if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
24333c89af1Smrg	    exit(1);
24433c89af1Smrg    }
24533c89af1Smrg    return(0);
24633c89af1Smrg}
24733c89af1Smrg
24833c89af1Smrg/*	Function Name: _DumpTreeToFile
24933c89af1Smrg *	Description: Dumps the widget tree to a file
25033c89af1Smrg *	Arguments: w - a random widget in the application on the
25133c89af1Smrg *                     currently active display
25233c89af1Smrg *                 tree_ptr - pointer to the widget tree info.
25333c89af1Smrg *                 filename - name of the file.
25433c89af1Smrg *	Returns: none.
25533c89af1Smrg */
25633c89af1Smrg
25733c89af1Smrg/* ARGSUSED */
25833c89af1Smrg
25933c89af1Smrgvoid
260278eca22Smrg_DumpTreeToFile(Widget w, XtPointer tree_ptr, XtPointer filename)
26133c89af1Smrg{
26233c89af1Smrg    TreeInfo * tree_info = (TreeInfo *) tree_ptr;
263ad47b356Smrg    FILE * fp;
26433c89af1Smrg
26533c89af1Smrg    if (tree_info == NULL) {
26633c89af1Smrg	SetMessage(global_screen_data.info_label,
26733c89af1Smrg		   res_labels[17]);
26833c89af1Smrg	return;
26933c89af1Smrg    }
27033c89af1Smrg
27133c89af1Smrg    if ( (fp = fopen((char *)filename, "w")) == NULL ) {
27233c89af1Smrg	char buf[BUFSIZ];
27333c89af1Smrg
274ad47b356Smrg	snprintf(buf, sizeof(buf), res_labels[24], (char *)filename);
27533c89af1Smrg	SetMessage(global_screen_data.info_label, buf);
27633c89af1Smrg	return;
27733c89af1Smrg    }
27833c89af1Smrg
27933c89af1Smrg    PerformTreeToFileDump(tree_info->top_node, 0, fp);
28033c89af1Smrg    fclose(fp);
28133c89af1Smrg}
28233c89af1Smrg
28333c89af1Smrg/************************************************************
284ad47b356Smrg *
28533c89af1Smrg * The file dialog boxes are handled with this code.
28633c89af1Smrg *
28733c89af1Smrg * It automatically calls the function specified when the
28833c89af1Smrg * user selects okay, or hits <CR>.
28933c89af1Smrg *
29033c89af1Smrg * A translation is required in the app-defaults file.
29133c89af1Smrg *
29233c89af1Smrg ************************************************************/
29333c89af1Smrg
29433c89af1Smrg/*	Function Name: _PopupFileDialog
29533c89af1Smrg *	Description: Puts up a dialog box to get the filename.
29633c89af1Smrg *	Arguments: str - message.
29733c89af1Smrg *                 default_value - the default value of the filename;
29833c89af1Smrg *                 func - function to call when filename has been entered.
29933c89af1Smrg *                 data - generic data to pass to func.
30033c89af1Smrg *	Returns: none
30133c89af1Smrg */
30233c89af1Smrg
30333c89af1Smrgstatic XContext file_dialog_context = None;
30433c89af1Smrg
30533c89af1Smrgtypedef struct _FileDialogInfo {
30633c89af1Smrg    XtCallbackProc func;
30733c89af1Smrg    XtPointer data;
30833c89af1Smrg} FileDialogInfo;
30933c89af1Smrg
31033c89af1Smrgvoid
311278eca22Smrg_PopupFileDialog(Widget w, String str, String default_value,
312278eca22Smrg		 XtCallbackProc func, XtPointer data)
31333c89af1Smrg{
31433c89af1Smrg    FileDialogInfo * file_info;
31533c89af1Smrg    Widget shell, dialog;
31633c89af1Smrg    Arg args[2];
31733c89af1Smrg    Cardinal num_args;
31833c89af1Smrg
31933c89af1Smrg    if (file_dialog_context == None)
32033c89af1Smrg	file_dialog_context = XUniqueContext();
32133c89af1Smrg
32233c89af1Smrg    shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
32333c89af1Smrg			       NULL, ZERO);
32433c89af1Smrg
32533c89af1Smrg    num_args = 0;
32633c89af1Smrg    XtSetArg(args[num_args], XtNlabel, str); num_args++;
32733c89af1Smrg    XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
328ad47b356Smrg    dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
32933c89af1Smrg				   shell, args, num_args);
33033c89af1Smrg
33133c89af1Smrg    file_info = XtNew(FileDialogInfo);
33233c89af1Smrg
33333c89af1Smrg    file_info->func = func;
33433c89af1Smrg    file_info->data = data;
33533c89af1Smrg
336ad47b356Smrg    if  (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
33733c89af1Smrg		      (XPointer) file_info) != 0) {
33833c89af1Smrg	SetMessage(global_screen_data.info_label,
33933c89af1Smrg	    "Error while trying to save Context\nAborting file dialog popup.");
34033c89af1Smrg	XtDestroyWidget(shell);
34133c89af1Smrg	return;
34233c89af1Smrg    }
34333c89af1Smrg
34433c89af1Smrg    XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
34533c89af1Smrg    XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
34633c89af1Smrg
34733c89af1Smrg    PopupCentered(NULL, shell, XtGrabNone);
34833c89af1Smrg}
34933c89af1Smrg
35033c89af1Smrg/*	Function Name: PopupCentered
35133c89af1Smrg *	Description: Pops up the window specified under the location passed
35233c89af1Smrg *                   in the event, or under the cursor.
35333c89af1Smrg *	Arguments: event - the event that we should use.
35433c89af1Smrg *                 w - widget to popup.
35533c89af1Smrg *                 mode - mode to pop it up in.
35633c89af1Smrg *	Returns: none
35733c89af1Smrg */
35833c89af1Smrg
35933c89af1Smrgvoid
360278eca22SmrgPopupCentered(XEvent *event, Widget w, XtGrabKind mode)
36133c89af1Smrg{
36233c89af1Smrg    Boolean get_from_cursor = FALSE;
36333c89af1Smrg    Arg args[3];
36433c89af1Smrg    Cardinal num_args;
36533c89af1Smrg    Dimension width, height, b_width;
36633c89af1Smrg    int x, y, max_x, max_y;
36733c89af1Smrg
36833c89af1Smrg    XtRealizeWidget(w);
36933c89af1Smrg
37033c89af1Smrg    if (event == NULL)
37133c89af1Smrg	get_from_cursor = TRUE;
37233c89af1Smrg    else {
37333c89af1Smrg	switch (event->type) {
37433c89af1Smrg	case ButtonPress:
37533c89af1Smrg	case ButtonRelease:
37633c89af1Smrg	    x = event->xbutton.x_root;
37733c89af1Smrg	    y = event->xbutton.y_root;
37833c89af1Smrg	    break;
37933c89af1Smrg	case KeyPress:
38033c89af1Smrg	case KeyRelease:
38133c89af1Smrg	    x = event->xkey.x_root;
38233c89af1Smrg	    y = event->xkey.y_root;
38333c89af1Smrg	    break;
38433c89af1Smrg	default:
38533c89af1Smrg	    get_from_cursor = TRUE;
38633c89af1Smrg	    break;
38733c89af1Smrg	}
38833c89af1Smrg    }
38933c89af1Smrg
39033c89af1Smrg    if (get_from_cursor) {
39133c89af1Smrg	Window root, child;
39233c89af1Smrg	int win_x, win_y;
39333c89af1Smrg	unsigned int mask;
394ad47b356Smrg
39533c89af1Smrg	XQueryPointer(XtDisplay(w), XtWindow(w),
39633c89af1Smrg		      &root, &child, &x, &y, &win_x, &win_y, &mask);
39733c89af1Smrg    }
39833c89af1Smrg
39933c89af1Smrg    num_args = 0;
40033c89af1Smrg    XtSetArg(args[num_args], XtNwidth, &width); num_args++;
40133c89af1Smrg    XtSetArg(args[num_args], XtNheight, &height); num_args++;
40233c89af1Smrg    XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
40333c89af1Smrg    XtGetValues(w, args, num_args);
40433c89af1Smrg
40533c89af1Smrg    width += 2 * b_width;
40633c89af1Smrg    height += 2 * b_width;
40733c89af1Smrg
40833c89af1Smrg    x -= ((int) width/2);
409ad47b356Smrg    if (x < 0)
41033c89af1Smrg	x = 0;
41133c89af1Smrg    if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
41233c89af1Smrg	x = max_x;
41333c89af1Smrg
41433c89af1Smrg    y -= ( (Position) height/2 );
415ad47b356Smrg    if (y < 0)
41633c89af1Smrg	y = 0;
41733c89af1Smrg    if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
41833c89af1Smrg	y = max_y;
419ad47b356Smrg
42033c89af1Smrg    num_args = 0;
42133c89af1Smrg    XtSetArg(args[num_args], XtNx, x); num_args++;
42233c89af1Smrg    XtSetArg(args[num_args], XtNy, y); num_args++;
42333c89af1Smrg    XtSetValues(w, args, num_args);
42433c89af1Smrg
42533c89af1Smrg    XtPopup(w, mode);
42633c89af1Smrg}
42733c89af1Smrg
42833c89af1Smrg/*	Function Name: _PopdownFileDialog
42933c89af1Smrg *	Description: Destroys the file dialog, and calls the correct function.
43033c89af1Smrg *	Arguments:  w - a child of the dialog widget.
43133c89af1Smrg *                  client_data - TRUE if command was sucessful.
43233c89af1Smrg *                  junk - ** UNUSED **.
43333c89af1Smrg *	Returns: none.
43433c89af1Smrg */
43533c89af1Smrg
43633c89af1Smrg/* ARGSUSED */
43733c89af1Smrg
438ad47b356Smrgvoid
439278eca22Smrg_PopdownFileDialog(Widget w, XtPointer client_data, XtPointer junk)
44033c89af1Smrg{
44133c89af1Smrg    Widget dialog = XtParent(w);
44233c89af1Smrg    XPointer file_info_ptr;
44333c89af1Smrg    FileDialogInfo * file_info;
44433c89af1Smrg
44533c89af1Smrg    if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
44633c89af1Smrg		     &file_info_ptr) == XCNOENT) {
447ad47b356Smrg	SetMessage(global_screen_data.info_label,
448ad47b356Smrg		   "Error while trying to find Context\nAborting...");
44933c89af1Smrg    }
45033c89af1Smrg
451ad47b356Smrg    (void) XDeleteContext(XtDisplay(dialog), (Window)dialog,
45233c89af1Smrg			  file_dialog_context);
45333c89af1Smrg
45433c89af1Smrg    file_info = (FileDialogInfo *) file_info_ptr;
45533c89af1Smrg
45633c89af1Smrg    if ( ((Boolean)(long) client_data) == TRUE ) {
45733c89af1Smrg	String filename = XawDialogGetValueString(dialog);
45833c89af1Smrg
45933c89af1Smrg	(*file_info->func)(w, file_info->data, filename); /* call handler */
46033c89af1Smrg    }
46133c89af1Smrg
46233c89af1Smrg    XtFree( (XtPointer) file_info); /* Free data. */
46333c89af1Smrg
46433c89af1Smrg    XtPopdown(XtParent(dialog));
46533c89af1Smrg    XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
46633c89af1Smrg}
46733c89af1Smrg
46833c89af1Smrg/************************************************************
46933c89af1Smrg *
47033c89af1Smrg * Functions for dealing with the Resource Box.
47133c89af1Smrg *
47233c89af1Smrg ************************************************************/
47333c89af1Smrg
47433c89af1Smrg/*    Function Name: GetNamesAndClasses
47533c89af1Smrg *    Description: Gets a list of names and classes for this widget.
47633c89af1Smrg *    Arguments: node - this widget's node.
47733c89af1Smrg *                 names, classes - list of names and classes. ** RETURNED **
47833c89af1Smrg *    Returns: none.
47933c89af1Smrg */
48033c89af1Smrg
48133c89af1Smrgvoid
482278eca22SmrgGetNamesAndClasses(WNode *node, char ***names, char ***classes)
48333c89af1Smrg{
48433c89af1Smrg    int i, total_widgets;
48533c89af1Smrg    WNode * temp = node;
48633c89af1Smrg
48733c89af1Smrg    for (total_widgets = 1 ; temp->parent != NULL ;
48833c89af1Smrg       total_widgets++, temp = temp->parent) {}
48933c89af1Smrg
49033c89af1Smrg    *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
49133c89af1Smrg    *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
49233c89af1Smrg
49333c89af1Smrg    (*names)[total_widgets] = (*classes)[total_widgets] = NULL;
49433c89af1Smrg
49533c89af1Smrg    for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
49633c89af1Smrg      (*names)[i] = node->name;
49733c89af1Smrg      (*classes)[i] = node->class;
49833c89af1Smrg    }
49933c89af1Smrg}
50033c89af1Smrg
50133c89af1Smrg/*	Function Name: HandleGetResources
50233c89af1Smrg *	Description: Gets the resources.
50333c89af1Smrg *	Arguments: event - the information from the client.
50433c89af1Smrg *	Returns: an error message to display.
50533c89af1Smrg */
50633c89af1Smrg
50733c89af1Smrgchar *
508278eca22SmrgHandleGetResources(Event *event)
50933c89af1Smrg{
51033c89af1Smrg    GetResourcesEvent * get_event = (GetResourcesEvent *) event;
51133c89af1Smrg    char buf[BUFSIZ], * errors = NULL;
51233c89af1Smrg    int i;
51333c89af1Smrg    WNode * node;
51433c89af1Smrg
51533c89af1Smrg    for (i = 0; i < (int)get_event->num_entries; i++) {
51633c89af1Smrg	node = FindNode(global_tree_info->top_node,
517ad47b356Smrg			get_event->info[i].widgets.ids,
51833c89af1Smrg			get_event->info[i].widgets.num_widgets);
51933c89af1Smrg
52033c89af1Smrg	if (node == NULL) {
521ad47b356Smrg	    snprintf(buf, sizeof(buf), res_labels[16]);
522ad47b356Smrg	    AddString(&errors, buf);
523ad47b356Smrg	    continue;
52433c89af1Smrg	}
52533c89af1Smrg
526ad47b356Smrg	if (node->resources != NULL)
52733c89af1Smrg	    FreeResources(node->resources);
52833c89af1Smrg
52933c89af1Smrg	if (!get_event->info[i].error) {
53033c89af1Smrg	    node->resources = ParseResources(get_event->info + i, &errors);
53133c89af1Smrg	    CreateResourceBox(node, &errors);
53233c89af1Smrg	}
53333c89af1Smrg	else {
53433c89af1Smrg	    AddString(&errors, get_event->info[i].message);
53533c89af1Smrg	    AddString(&errors, "\n");
53633c89af1Smrg	}
53733c89af1Smrg    }
53833c89af1Smrg
53933c89af1Smrg    return(errors);
54033c89af1Smrg}
54133c89af1Smrg
54233c89af1Smrg/*	Function Name: CreateResourceBox
54333c89af1Smrg *	Description: Creates a resource box for the widget specified.
54433c89af1Smrg *	Arguments: node - the node of the widget in question.
54533c89af1Smrg *                 errors - an error string.
54633c89af1Smrg *	Returns: none.
54733c89af1Smrg */
54833c89af1Smrg
54933c89af1Smrgvoid
550278eca22SmrgCreateResourceBox(WNode *node, char **errors)
55133c89af1Smrg{
55233c89af1Smrg    WidgetResources * resources = node->resources;
55333c89af1Smrg    char ** names, ** cons_names;
55433c89af1Smrg    int i;
55533c89af1Smrg
55633c89af1Smrg    if (global_resource_box_up) {
55733c89af1Smrg	AddString(errors, res_labels[34]);
55833c89af1Smrg	return;
55933c89af1Smrg    }
56033c89af1Smrg    else
56133c89af1Smrg	global_resource_box_up = TRUE;
56233c89af1Smrg
56333c89af1Smrg    if (resources->num_normal > 0) {
56433c89af1Smrg	names = (char **) XtMalloc(sizeof(char *) *
56533c89af1Smrg				   (resources->num_normal + 1));
566ad47b356Smrg	for (i = 0 ; i < resources->num_normal ; i++)
56733c89af1Smrg	    names[i] = resources->normal[i].name;
56833c89af1Smrg	names[i] = NULL;
56933c89af1Smrg    }
57033c89af1Smrg    else
57133c89af1Smrg	names = NULL;
57233c89af1Smrg
57333c89af1Smrg    if (resources->num_constraint > 0) {
57433c89af1Smrg	cons_names = (char **) XtMalloc(sizeof(char *) *
57533c89af1Smrg					(resources->num_constraint + 1));
576ad47b356Smrg
577ad47b356Smrg	for (i = 0 ; i < resources->num_constraint ; i++)
57833c89af1Smrg	    cons_names[i] = resources->constraint[i].name;
57933c89af1Smrg	cons_names[i] = NULL;
58033c89af1Smrg    }
58133c89af1Smrg    else
58233c89af1Smrg	cons_names = NULL;
58333c89af1Smrg
58433c89af1Smrg    CreateResourceBoxWidgets(node, names, cons_names);
58533c89af1Smrg}
58633c89af1Smrg
58733c89af1Smrg/*	Function Name: ParseResources
58833c89af1Smrg *	Description: Parses the resource values returned from the client
58933c89af1Smrg *                   into a resources structure.
59033c89af1Smrg *	Arguments: info - info about a widget's resources.
59133c89af1Smrg *                 error - where to place error info.
59233c89af1Smrg *	Returns: The resource information.
59333c89af1Smrg */
59433c89af1Smrg
595ad47b356Smrgstatic WidgetResources *
596278eca22SmrgParseResources(GetResourcesInfo *info, char **error)
59733c89af1Smrg{
59833c89af1Smrg    WidgetResources * resources;
59933c89af1Smrg    WidgetResourceInfo * normal;
60033c89af1Smrg    int i;
60133c89af1Smrg
602ad47b356Smrg    resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources));
603ad47b356Smrg
60433c89af1Smrg    /*
60533c89af1Smrg     * Allocate enough space for both the normal and constraint resources,
60633c89af1Smrg     * then add the normal resources from the top, and the constraint resources
60733c89af1Smrg     * from the bottom.  This assures that enough memory is allocated, and
60833c89af1Smrg     * that there is no overlap.
60933c89af1Smrg     */
61033c89af1Smrg
611ad47b356Smrg    resources->normal = (WidgetResourceInfo *)
61233c89af1Smrg	            XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
61333c89af1Smrg
61433c89af1Smrg    normal = resources->normal;
61533c89af1Smrg    resources->constraint = resources->normal + info->num_resources - 1;
61633c89af1Smrg
61733c89af1Smrg    resources->num_constraint = resources->num_normal = 0;
61833c89af1Smrg
61933c89af1Smrg    for (i = 0; i < (int)info->num_resources; i++) {
62033c89af1Smrg	switch((int) info->res_info[i].res_type) {
62133c89af1Smrg	case NormalResource:
62233c89af1Smrg	    resources->num_normal++;
623ad47b356Smrg	    AddResource(info->res_info + i, normal++);
62433c89af1Smrg	    break;
62533c89af1Smrg	case ConstraintResource:
62633c89af1Smrg	    resources->num_constraint++;
62733c89af1Smrg	    AddResource(info->res_info + i, resources->constraint--);
62833c89af1Smrg	    break;
62933c89af1Smrg	default:
63033c89af1Smrg	    {
63133c89af1Smrg		char buf[BUFSIZ];
632ad47b356Smrg		snprintf(buf, sizeof(buf), "Unknown resource type %d\n",
633ad47b356Smrg                         info->res_info[i].res_type);
63433c89af1Smrg		AddString(error, buf);
63533c89af1Smrg	    }
63633c89af1Smrg	    break;
63733c89af1Smrg	}
63833c89af1Smrg    }
63933c89af1Smrg
64033c89af1Smrg    /*
641ad47b356Smrg     * Sort the resources alphabetically.
64233c89af1Smrg     */
64333c89af1Smrg
64433c89af1Smrg    qsort(resources->normal, resources->num_normal,
64533c89af1Smrg	  sizeof(WidgetResourceInfo), CompareResourceEntries);
64633c89af1Smrg
64733c89af1Smrg    if (resources->num_constraint > 0) {
64833c89af1Smrg	resources->constraint++;
64933c89af1Smrg	qsort(resources->constraint, resources->num_constraint,
65033c89af1Smrg	      sizeof(WidgetResourceInfo), CompareResourceEntries);
65133c89af1Smrg    }
65233c89af1Smrg    else
65333c89af1Smrg	resources->constraint = NULL;
65433c89af1Smrg
65533c89af1Smrg    return(resources);
65633c89af1Smrg}
65733c89af1Smrg
65833c89af1Smrg/*	Function Name: CompareResourceEntries
65933c89af1Smrg *	Description: Compares two resource entries.
66033c89af1Smrg *	Arguments: e1, e2 - the entries to compare.
66133c89af1Smrg *	Returns: an integer >, < or = 0.
66233c89af1Smrg */
66333c89af1Smrg
664ad47b356Smrgstatic int
665278eca22SmrgCompareResourceEntries(const void *e1, const void *e2)
66633c89af1Smrg{
667ad47b356Smrg    return (strcmp(((WidgetResourceInfo *)e1)->name,
66833c89af1Smrg		   ((WidgetResourceInfo *)e2)->name));
66933c89af1Smrg}
67033c89af1Smrg
67133c89af1Smrg/*	Function Name: AddResource
67233c89af1Smrg *	Description: Parses the resource string a stuffs in individual
67333c89af1Smrg *                   parts into the resource info struct.
67433c89af1Smrg *	Arguments: res_info - the resource info from the event.
67533c89af1Smrg *                 resource - location to stuff the resource into.
67633c89af1Smrg *	Returns: none.
67733c89af1Smrg */
67833c89af1Smrg
67933c89af1Smrgstatic void
680278eca22SmrgAddResource(ResourceInfo *res_info, WidgetResourceInfo *resource)
68133c89af1Smrg{
68233c89af1Smrg    resource->name = res_info->name;
68333c89af1Smrg    res_info->name = NULL;	/* Keeps it from being deallocated. */
68433c89af1Smrg    resource->class = res_info->class;
68533c89af1Smrg    res_info->class = NULL;	/* Keeps it from being deallocated. */
68633c89af1Smrg    resource->type = res_info->type;
68733c89af1Smrg    res_info->type = NULL;	/* Keeps it from being deallocated. */
68833c89af1Smrg}
68933c89af1Smrg
69033c89af1Smrg
69133c89af1Smrg/*	Function Name: FreeResources
69233c89af1Smrg *	Description: frees the resource inforation.
69333c89af1Smrg *	Arguments: resources.
69433c89af1Smrg *	Returns: none.
69533c89af1Smrg */
69633c89af1Smrg
69733c89af1Smrgstatic void
698278eca22SmrgFreeResources(WidgetResources *resources)
69933c89af1Smrg{
70033c89af1Smrg    int i;
70133c89af1Smrg
70233c89af1Smrg    if (resources->num_normal > 0) {
70333c89af1Smrg	for (i = 0; i < resources->num_normal; i++) {
70433c89af1Smrg	    XtFree(resources->normal[i].name);
70533c89af1Smrg	    XtFree(resources->normal[i].class);
70633c89af1Smrg	    XtFree(resources->normal[i].type);
70733c89af1Smrg	}
70833c89af1Smrg	XFree((char *)resources->normal);
70933c89af1Smrg    }
71033c89af1Smrg
71133c89af1Smrg    if (resources->num_constraint > 0) {
71233c89af1Smrg	for (i = 0; i < resources->num_constraint; i++) {
71333c89af1Smrg	    XtFree(resources->constraint[i].name);
71433c89af1Smrg	    XtFree(resources->constraint[i].class);
71533c89af1Smrg	    XtFree(resources->constraint[i].type);
71633c89af1Smrg	}
71733c89af1Smrg	XFree((char *)resources->constraint);
71833c89af1Smrg    }
71933c89af1Smrg
72033c89af1Smrg    XFree((char *)resources);
72133c89af1Smrg}
722ad47b356Smrg
72333c89af1Smrg
72433c89af1Smrg/*	Function Name: CheckDatabase
72533c89af1Smrg *	Description: Checks to see if the node is in the database.
72633c89af1Smrg *	Arguments: db - the db to check
72733c89af1Smrg *                 names, clases - names and clases, represented as quarks.
72833c89af1Smrg *	Returns: True if this entry is found.
72933c89af1Smrg */
73033c89af1Smrg
73133c89af1SmrgBoolean
732278eca22SmrgCheckDatabase(XrmDatabase db, XrmQuarkList names, XrmQuarkList classes)
73333c89af1Smrg{
73433c89af1Smrg    XrmRepresentation junk;
73533c89af1Smrg    XrmValue garbage;
73633c89af1Smrg
73733c89af1Smrg    return(XrmQGetResource(db, names, classes, &junk, &garbage));
73833c89af1Smrg}
73933c89af1Smrg
74033c89af1Smrg/*	Function Name: Quarkify
74133c89af1Smrg *	Description: Quarkifies the string list specifed.
74233c89af1Smrg *	Arguments: list - list of strings to quarkify
74333c89af1Smrg *                 ptr - an additional string to quarkify.
74433c89af1Smrg *	Returns: none.
74533c89af1Smrg */
74633c89af1Smrg
74733c89af1SmrgXrmQuarkList
748278eca22SmrgQuarkify(char **list, char *ptr)
74933c89af1Smrg{
75033c89af1Smrg    int i;
75133c89af1Smrg    char ** tlist;
75233c89af1Smrg    XrmQuarkList quarks, tquarks;
75333c89af1Smrg
75433c89af1Smrg    for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
75533c89af1Smrg    if (ptr != NULL)
75633c89af1Smrg	i++;
75733c89af1Smrg    i++;			/* leave space for NULLQUARK */
75833c89af1Smrg
75933c89af1Smrg    quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
76033c89af1Smrg
761ad47b356Smrg    for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++)
76233c89af1Smrg	*tquarks = XrmStringToQuark(*tlist);
76333c89af1Smrg
764ad47b356Smrg    if (ptr != NULL)
76533c89af1Smrg	*tquarks++ = XrmStringToQuark(ptr);
766ad47b356Smrg
76733c89af1Smrg    *tquarks = NULLQUARK;
76833c89af1Smrg    return(quarks);
76933c89af1Smrg}
77033c89af1Smrg
77133c89af1Smrg/*	Function Name: ExecuteOverAllNodes
77233c89af1Smrg *	Description: Executes the given function over all nodes.
77333c89af1Smrg *	Arguments: top_node - top node of the tree.
77433c89af1Smrg *                 func - the function to execute.
77533c89af1Smrg *                 data - a data pointer to pass to the function.
77633c89af1Smrg *	Returns: none
77733c89af1Smrg */
77833c89af1Smrg
77933c89af1Smrgvoid
780278eca22SmrgExecuteOverAllNodes(WNode *top_node, void (*func)(WNode *, XtPointer),
781278eca22Smrg		    XtPointer data)
78233c89af1Smrg{
783ad47b356Smrg    Cardinal i;
78433c89af1Smrg
78533c89af1Smrg    (*func)(top_node, data);
78633c89af1Smrg
787ad47b356Smrg    for (i = 0; i < top_node->num_children; i++)
78833c89af1Smrg	ExecuteOverAllNodes(top_node->children[i], func, data);
78933c89af1Smrg}
79033c89af1Smrg
79133c89af1Smrg/*	Function Name: InsertWidgetFromNode
79233c89af1Smrg *	Description: Inserts the widget info for this widget represented
79333c89af1Smrg *                   by this node.
79433c89af1Smrg *	Arguments: stream - the stream to insert it info into.
79533c89af1Smrg *                 none - the widget node to insert.
79633c89af1Smrg *	Returns: none
79733c89af1Smrg */
79833c89af1Smrg
79933c89af1Smrgvoid
800278eca22SmrgInsertWidgetFromNode(ProtocolStream *stream, WNode *node)
80133c89af1Smrg{
80233c89af1Smrg    WNode *temp;
80333c89af1Smrg    unsigned long * widget_list;
80433c89af1Smrg    register int i, num_widgets;
80533c89af1Smrg
806278eca22Smrg    for (temp = node, i = 0; temp != NULL; temp = temp->parent, i++) {}
80733c89af1Smrg
80833c89af1Smrg    num_widgets = i;
809ad47b356Smrg    widget_list = (unsigned long *)
81033c89af1Smrg	          XtMalloc(sizeof(unsigned long) * num_widgets);
81133c89af1Smrg
81233c89af1Smrg    /*
81333c89af1Smrg     * Put the widgets into the list.
81433c89af1Smrg     * Make sure that they are inserted in the list from parent -> child.
81533c89af1Smrg     */
81633c89af1Smrg
817ad47b356Smrg    for (i--, temp = node; temp != NULL; temp = temp->parent, i--)
81833c89af1Smrg	widget_list[i] = temp->id;
819ad47b356Smrg
82033c89af1Smrg    _XEditResPut16(stream, num_widgets);	/* insert number of widgets. */
82133c89af1Smrg    for (i = 0; i < num_widgets; i++) 	/* insert Widgets themselves. */
82233c89af1Smrg	_XEditResPut32(stream, widget_list[i]);
823ad47b356Smrg
82433c89af1Smrg    XtFree((char *)widget_list);
82533c89af1Smrg}
82633c89af1Smrg
82733c89af1Smrg/*	Function Name: GetFailureMesssage
82833c89af1Smrg *	Description: returns the message returned from a failed request.
82933c89af1Smrg *	Arguments: stream - the protocol stream containing the message.
83033c89af1Smrg *	Returns: message to show.
83133c89af1Smrg */
83233c89af1Smrg
833ad47b356Smrgchar *
834278eca22SmrgGetFailureMessage(ProtocolStream *stream)
83533c89af1Smrg{
83633c89af1Smrg    char * return_str;
83733c89af1Smrg
838ad47b356Smrg    if (_XEditResGetString8(stream, &return_str))
83933c89af1Smrg	return(return_str);
84033c89af1Smrg
84133c89af1Smrg    return(XtNewString(res_labels[35]));
84233c89af1Smrg}
84333c89af1Smrg
84433c89af1Smrg/*	Function Name: ProtocolFailure
84533c89af1Smrg *	Description: Gets the version of the protocol the client is
84633c89af1Smrg *                   willing to speak.
84733c89af1Smrg *	Arguments: stream - the protocol stream containing the message.
84833c89af1Smrg *	Returns: message to show.
84933c89af1Smrg */
85033c89af1Smrg
851ad47b356Smrgchar *
852278eca22SmrgProtocolFailure(ProtocolStream *stream)
85333c89af1Smrg{
85433c89af1Smrg    char buf[BUFSIZ];
85533c89af1Smrg    unsigned char version;
85633c89af1Smrg    char* old_version_string;
85733c89af1Smrg
858ad47b356Smrg    if (!_XEditResGet8(stream, &version))
85933c89af1Smrg	return(XtNewString(res_labels[35]));
86033c89af1Smrg
86133c89af1Smrg    switch ((int)version) {
86233c89af1Smrg    case PROTOCOL_VERSION_ONE_POINT_ZERO: old_version_string = "1.0"; break;
86333c89af1Smrg    default: old_version_string = "1.0";
86433c89af1Smrg    }
865ad47b356Smrg
866ad47b356Smrg    snprintf(buf, sizeof(buf), res_labels[36],
867ad47b356Smrg             CURRENT_PROTOCOL_VERSION_STRING, old_version_string);
86833c89af1Smrg    return(XtNewString(buf));
86933c89af1Smrg}
870ad47b356Smrg
871