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