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
2638d718bdSmrg#ifdef HAVE_CONFIG_H
2738d718bdSmrg# include "config.h"
2838d718bdSmrg#endif
2938d718bdSmrg
3033c89af1Smrg#include <X11/Intrinsic.h>
3133c89af1Smrg#include <X11/Xutil.h>
3233c89af1Smrg#include <X11/Xos.h>
3333c89af1Smrg#include <X11/Shell.h>
3433c89af1Smrg#include <X11/StringDefs.h>
3533c89af1Smrg
3633c89af1Smrg#include <X11/Xaw/Cardinals.h>
3733c89af1Smrg#include <X11/Xaw/Dialog.h>
3833c89af1Smrg
3933c89af1Smrg#include <stdio.h>
4033c89af1Smrg#include <stdlib.h>
4133c89af1Smrg#include <X11/Xmu/Error.h>
4233c89af1Smrg
4333c89af1Smrg#include "editresP.h"
4433c89af1Smrg
4533c89af1Smrgstatic WNode * FindWidgetFromWindowGivenNode ( WNode * node, Window win );
46ad47b356Smrgstatic WidgetResources * ParseResources ( GetResourcesInfo * info,
4733c89af1Smrg					  char **error );
48ad47b356Smrgstatic int CompareResourceEntries ( const void *e1,
4933c89af1Smrg				    const void *e2 );
50ad47b356Smrgstatic void AddResource ( ResourceInfo * res_info,
5133c89af1Smrg			  WidgetResourceInfo * resource );
5233c89af1Smrgstatic void FreeResources ( WidgetResources * resources );
5333c89af1Smrg
5433c89af1Smrg
5533c89af1Smrg/*	Function Name: SetMessage(w, str)
5633c89af1Smrg *	Description: shows the message to the user.
5733c89af1Smrg *	Arguments: w - a label widget to show the message in.
5833c89af1Smrg *                 str - the string to show.
5933c89af1Smrg *	Returns: none.
6033c89af1Smrg */
6133c89af1Smrg
6233c89af1Smrgvoid
6338d718bdSmrgSetMessage(Widget w, const char *str)
6433c89af1Smrg{
6533c89af1Smrg    Arg args[1];
6633c89af1Smrg
6733c89af1Smrg    XtSetArg(args[0], XtNlabel, str);
6833c89af1Smrg    XtSetValues(w, args, ONE);
6933c89af1Smrg}
7033c89af1Smrg
7133c89af1Smrg/*	Function Name: GetAllStrings
72352bf44eSmrg *	Description: Returns a list of strings that have been broken up by
7333c89af1Smrg *                   the character specified.
7433c89af1Smrg *	Arguments: in - the string to parse.
7533c89af1Smrg *                 sep - the separator character.
7633c89af1Smrg *                 out - the strings to send out.
7733c89af1Smrg *                 num - the number of strings in out.
7833c89af1Smrg *	Returns: none
7933c89af1Smrg */
8033c89af1Smrg
8133c89af1Smrgvoid
8233c89af1SmrgGetAllStrings(char *in, char sep, char ***out, int *num)
8333c89af1Smrg{
8433c89af1Smrg    int size, i;
8533c89af1Smrg    char * ptr;
8633c89af1Smrg
8733c89af1Smrg    if (*in == sep)		/* jump over first char if it is the sep. */
8833c89af1Smrg	in++;
8933c89af1Smrg
9033c89af1Smrg    /*
9133c89af1Smrg     * count the number of strings.
9233c89af1Smrg     */
9333c89af1Smrg
9433c89af1Smrg    for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++)
9533c89af1Smrg	ptr++;
9633c89af1Smrg
9733c89af1Smrg/*
9833c89af1Smrg * Create Enough space for pointers and string.
9933c89af1Smrg */
10033c89af1Smrg
10133c89af1Smrg    size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
10233c89af1Smrg    *out = (char **) XtMalloc( (Cardinal) size);
10333c89af1Smrg
10433c89af1Smrg    ptr = (char *) (*out + *num);
10533c89af1Smrg    strcpy(ptr, in);
10633c89af1Smrg
10733c89af1Smrg/*
10833c89af1Smrg * Change all `sep' characters to '\0' and stuff the pointer into
10933c89af1Smrg * the next pointer slot.
11033c89af1Smrg */
11133c89af1Smrg
11233c89af1Smrg    i = 1;
11333c89af1Smrg    (*out)[0] = ptr;
11433c89af1Smrg    while (TRUE) {
11533c89af1Smrg	if ((ptr = strchr(ptr, sep)) == NULL)
11633c89af1Smrg	    break;
11733c89af1Smrg
11833c89af1Smrg	*ptr++ = '\0';
11933c89af1Smrg	(*out)[i++] = ptr;
12033c89af1Smrg    }
12133c89af1Smrg
12233c89af1Smrg/*
12333c89af1Smrg * If last string is empty then strip it off.
12433c89af1Smrg */
12533c89af1Smrg
12633c89af1Smrg    if ( *((*out)[i - 1]) == '\0' )
12733c89af1Smrg	(*num)--;
12833c89af1Smrg}
12933c89af1Smrg
13033c89af1Smrg/*	Function Name: AddString
13133c89af1Smrg *	Description: Mallocs and strcats the string onto the end of
13233c89af1Smrg *                   the given string.
13333c89af1Smrg *	Arguments: str - string to add on to.
13433c89af1Smrg *                 add - string to add.
13533c89af1Smrg *	Returns: none.
13633c89af1Smrg */
13733c89af1Smrg
13833c89af1Smrgvoid
139352bf44eSmrgAddString(char ** str, const char *add)
14033c89af1Smrg{
14133c89af1Smrg    int len_str, len_add;
14233c89af1Smrg    char * ptr;
14333c89af1Smrg
14433c89af1Smrg    len_str = ((*str) ? strlen(*str) : 0);
14533c89af1Smrg    len_add = strlen(add);
14633c89af1Smrg
14733c89af1Smrg    *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
14833c89af1Smrg    ptr = *str + len_str;
14933c89af1Smrg    strcpy(ptr, add);
15033c89af1Smrg}
151ad47b356Smrg
15233c89af1Smrg/*	Function Name: FindNode
15333c89af1Smrg *	Description: Finds a node give the top node, and a node id number.
15433c89af1Smrg *	Arguments: top_node - the top node.
15533c89af1Smrg *                 id - the node id.
15633c89af1Smrg *	Returns: node.
15733c89af1Smrg */
15833c89af1Smrg
15933c89af1SmrgWNode *
160278eca22SmrgFindNode(WNode *top_node, unsigned long *ids, Cardinal number)
16133c89af1Smrg{
162ad47b356Smrg    Cardinal i, j;
16333c89af1Smrg    WNode *node;
16433c89af1Smrg
16533c89af1Smrg    if (top_node == NULL)
16633c89af1Smrg	return(NULL);
16733c89af1Smrg
16833c89af1Smrg    if (ids[0] != top_node->id)
16933c89af1Smrg	return(NULL);
17033c89af1Smrg
17133c89af1Smrg    for (node = top_node, i = 1 ; i < number; i++) {
17233c89af1Smrg	Boolean found_it = FALSE;
17333c89af1Smrg
17433c89af1Smrg	for (j = 0; j < node->num_children; j++) {
17533c89af1Smrg	    if (node->children[j]->id == ids[i]) {
17633c89af1Smrg		node = node->children[j];
17733c89af1Smrg		found_it = TRUE;
17833c89af1Smrg		break;
17933c89af1Smrg	    }
18033c89af1Smrg	}
18133c89af1Smrg	if (!found_it)
18233c89af1Smrg	    return(NULL);
183ad47b356Smrg    }
18433c89af1Smrg    return(node);
18533c89af1Smrg}
18633c89af1Smrg
18733c89af1Smrg/*	Function Name: FindWidgetFromWindow
18833c89af1Smrg *	Description: finds a widget in the current tree given its window id.
18933c89af1Smrg *	Arguments: tree_info - information about this tree.
19033c89af1Smrg *                 win - window to search for.
19133c89af1Smrg *	Returns: node - the node corrosponding to this widget.
19233c89af1Smrg */
19333c89af1Smrg
194ad47b356SmrgWNode *
195278eca22SmrgFindWidgetFromWindow(TreeInfo *tree_info, Window win)
19633c89af1Smrg{
19733c89af1Smrg    if (tree_info == NULL)
19833c89af1Smrg	return(NULL);
19933c89af1Smrg
20033c89af1Smrg    return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
20133c89af1Smrg}
20233c89af1Smrg
20333c89af1Smrg/*	Function Name: FindWidgetFromWindowGivenNode
20433c89af1Smrg *	Description: finds a widget in the current tree given its window id.
20533c89af1Smrg *	Arguments: node - current node.
20633c89af1Smrg *                 win - window to search for.
20733c89af1Smrg *	Returns: node - the node corrosponding to this widget.
20833c89af1Smrg */
20933c89af1Smrg
21033c89af1Smrgstatic WNode *
211278eca22SmrgFindWidgetFromWindowGivenNode(WNode *node, Window win)
21233c89af1Smrg{
213ad47b356Smrg    Cardinal i;
21433c89af1Smrg    WNode * ret_node;
21533c89af1Smrg
21633c89af1Smrg    if (node->window == win)
21733c89af1Smrg	return(node);
21833c89af1Smrg
21933c89af1Smrg    for (i = 0; i < node->num_children; i++) {
22033c89af1Smrg	ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
22133c89af1Smrg	if (ret_node != NULL)
22233c89af1Smrg	    return(ret_node);
22333c89af1Smrg    }
22433c89af1Smrg    return(NULL);
22533c89af1Smrg}
22633c89af1Smrg
22733c89af1Smrg/*	Function Name: HandleXErrors
22833c89af1Smrg *	Description: Handles error codes from the server.
22933c89af1Smrg *	Arguments: display - the display.
23033c89af1Smrg *                 error - error information.
23133c89af1Smrg *	Returns: none.
23233c89af1Smrg */
23333c89af1Smrg
23433c89af1Smrg/* ARGSUSED */
23533c89af1Smrgint
236278eca22SmrgHandleXErrors(Display *display, XErrorEvent *error)
23733c89af1Smrg{
23833c89af1Smrg    if (error->serial != global_serial_num) {
23933c89af1Smrg	(*global_old_error_handler) (display, error);
24033c89af1Smrg	return(0);
24133c89af1Smrg    }
24233c89af1Smrg
24333c89af1Smrg    if (error->error_code == BadWindow)
244ad47b356Smrg	global_error_code = NO_WINDOW;
24533c89af1Smrg    else {
24633c89af1Smrg	if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
24733c89af1Smrg	    exit(1);
24833c89af1Smrg    }
24933c89af1Smrg    return(0);
25033c89af1Smrg}
25133c89af1Smrg
25233c89af1Smrg/*	Function Name: _DumpTreeToFile
25333c89af1Smrg *	Description: Dumps the widget tree to a file
25433c89af1Smrg *	Arguments: w - a random widget in the application on the
25533c89af1Smrg *                     currently active display
25633c89af1Smrg *                 tree_ptr - pointer to the widget tree info.
25733c89af1Smrg *                 filename - name of the file.
25833c89af1Smrg *	Returns: none.
25933c89af1Smrg */
26033c89af1Smrg
26133c89af1Smrg/* ARGSUSED */
26233c89af1Smrg
26333c89af1Smrgvoid
264278eca22Smrg_DumpTreeToFile(Widget w, XtPointer tree_ptr, XtPointer filename)
26533c89af1Smrg{
26633c89af1Smrg    TreeInfo * tree_info = (TreeInfo *) tree_ptr;
267ad47b356Smrg    FILE * fp;
26833c89af1Smrg
26933c89af1Smrg    if (tree_info == NULL) {
27033c89af1Smrg	SetMessage(global_screen_data.info_label,
27133c89af1Smrg		   res_labels[17]);
27233c89af1Smrg	return;
27333c89af1Smrg    }
27433c89af1Smrg
27533c89af1Smrg    if ( (fp = fopen((char *)filename, "w")) == NULL ) {
27633c89af1Smrg	char buf[BUFSIZ];
27733c89af1Smrg
278ad47b356Smrg	snprintf(buf, sizeof(buf), res_labels[24], (char *)filename);
27933c89af1Smrg	SetMessage(global_screen_data.info_label, buf);
28033c89af1Smrg	return;
28133c89af1Smrg    }
28233c89af1Smrg
28333c89af1Smrg    PerformTreeToFileDump(tree_info->top_node, 0, fp);
28433c89af1Smrg    fclose(fp);
28533c89af1Smrg}
28633c89af1Smrg
28733c89af1Smrg/************************************************************
288ad47b356Smrg *
28933c89af1Smrg * The file dialog boxes are handled with this code.
29033c89af1Smrg *
29133c89af1Smrg * It automatically calls the function specified when the
29233c89af1Smrg * user selects okay, or hits <CR>.
29333c89af1Smrg *
29433c89af1Smrg * A translation is required in the app-defaults file.
29533c89af1Smrg *
29633c89af1Smrg ************************************************************/
29733c89af1Smrg
29833c89af1Smrg/*	Function Name: _PopupFileDialog
29933c89af1Smrg *	Description: Puts up a dialog box to get the filename.
30033c89af1Smrg *	Arguments: str - message.
30133c89af1Smrg *                 default_value - the default value of the filename;
30233c89af1Smrg *                 func - function to call when filename has been entered.
30333c89af1Smrg *                 data - generic data to pass to func.
30433c89af1Smrg *	Returns: none
30533c89af1Smrg */
30633c89af1Smrg
30733c89af1Smrgstatic XContext file_dialog_context = None;
30833c89af1Smrg
30933c89af1Smrgtypedef struct _FileDialogInfo {
31033c89af1Smrg    XtCallbackProc func;
31133c89af1Smrg    XtPointer data;
31233c89af1Smrg} FileDialogInfo;
31333c89af1Smrg
31433c89af1Smrgvoid
31538d718bdSmrg_PopupFileDialog(Widget w, const char *str, const char *default_value,
316278eca22Smrg		 XtCallbackProc func, XtPointer data)
31733c89af1Smrg{
31833c89af1Smrg    FileDialogInfo * file_info;
31933c89af1Smrg    Widget shell, dialog;
32033c89af1Smrg    Arg args[2];
32133c89af1Smrg    Cardinal num_args;
32233c89af1Smrg
32333c89af1Smrg    if (file_dialog_context == None)
32433c89af1Smrg	file_dialog_context = XUniqueContext();
32533c89af1Smrg
32633c89af1Smrg    shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
32733c89af1Smrg			       NULL, ZERO);
32833c89af1Smrg
32933c89af1Smrg    num_args = 0;
33033c89af1Smrg    XtSetArg(args[num_args], XtNlabel, str); num_args++;
33133c89af1Smrg    XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
332ad47b356Smrg    dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
33333c89af1Smrg				   shell, args, num_args);
33433c89af1Smrg
33533c89af1Smrg    file_info = XtNew(FileDialogInfo);
33633c89af1Smrg
33733c89af1Smrg    file_info->func = func;
33833c89af1Smrg    file_info->data = data;
33933c89af1Smrg
340ad47b356Smrg    if  (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
34133c89af1Smrg		      (XPointer) file_info) != 0) {
34233c89af1Smrg	SetMessage(global_screen_data.info_label,
34333c89af1Smrg	    "Error while trying to save Context\nAborting file dialog popup.");
34433c89af1Smrg	XtDestroyWidget(shell);
34533c89af1Smrg	return;
34633c89af1Smrg    }
34733c89af1Smrg
34833c89af1Smrg    XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
34933c89af1Smrg    XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
35033c89af1Smrg
35133c89af1Smrg    PopupCentered(NULL, shell, XtGrabNone);
35233c89af1Smrg}
35333c89af1Smrg
35433c89af1Smrg/*	Function Name: PopupCentered
35533c89af1Smrg *	Description: Pops up the window specified under the location passed
35633c89af1Smrg *                   in the event, or under the cursor.
35733c89af1Smrg *	Arguments: event - the event that we should use.
35833c89af1Smrg *                 w - widget to popup.
35933c89af1Smrg *                 mode - mode to pop it up in.
36033c89af1Smrg *	Returns: none
36133c89af1Smrg */
36233c89af1Smrg
36333c89af1Smrgvoid
364278eca22SmrgPopupCentered(XEvent *event, Widget w, XtGrabKind mode)
36533c89af1Smrg{
36633c89af1Smrg    Boolean get_from_cursor = FALSE;
36733c89af1Smrg    Arg args[3];
36833c89af1Smrg    Cardinal num_args;
36933c89af1Smrg    Dimension width, height, b_width;
37033c89af1Smrg    int x, y, max_x, max_y;
37133c89af1Smrg
37233c89af1Smrg    XtRealizeWidget(w);
37333c89af1Smrg
37433c89af1Smrg    if (event == NULL)
37533c89af1Smrg	get_from_cursor = TRUE;
37633c89af1Smrg    else {
37733c89af1Smrg	switch (event->type) {
37833c89af1Smrg	case ButtonPress:
37933c89af1Smrg	case ButtonRelease:
38033c89af1Smrg	    x = event->xbutton.x_root;
38133c89af1Smrg	    y = event->xbutton.y_root;
38233c89af1Smrg	    break;
38333c89af1Smrg	case KeyPress:
38433c89af1Smrg	case KeyRelease:
38533c89af1Smrg	    x = event->xkey.x_root;
38633c89af1Smrg	    y = event->xkey.y_root;
38733c89af1Smrg	    break;
38833c89af1Smrg	default:
38933c89af1Smrg	    get_from_cursor = TRUE;
39033c89af1Smrg	    break;
39133c89af1Smrg	}
39233c89af1Smrg    }
39333c89af1Smrg
39433c89af1Smrg    if (get_from_cursor) {
39533c89af1Smrg	Window root, child;
39633c89af1Smrg	int win_x, win_y;
39733c89af1Smrg	unsigned int mask;
398ad47b356Smrg
39933c89af1Smrg	XQueryPointer(XtDisplay(w), XtWindow(w),
40033c89af1Smrg		      &root, &child, &x, &y, &win_x, &win_y, &mask);
40133c89af1Smrg    }
40233c89af1Smrg
40333c89af1Smrg    num_args = 0;
40433c89af1Smrg    XtSetArg(args[num_args], XtNwidth, &width); num_args++;
40533c89af1Smrg    XtSetArg(args[num_args], XtNheight, &height); num_args++;
40633c89af1Smrg    XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
40733c89af1Smrg    XtGetValues(w, args, num_args);
40833c89af1Smrg
40933c89af1Smrg    width += 2 * b_width;
41033c89af1Smrg    height += 2 * b_width;
41133c89af1Smrg
41233c89af1Smrg    x -= ((int) width/2);
413ad47b356Smrg    if (x < 0)
41433c89af1Smrg	x = 0;
41533c89af1Smrg    if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
41633c89af1Smrg	x = max_x;
41733c89af1Smrg
41833c89af1Smrg    y -= ( (Position) height/2 );
419ad47b356Smrg    if (y < 0)
42033c89af1Smrg	y = 0;
42133c89af1Smrg    if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
42233c89af1Smrg	y = max_y;
423ad47b356Smrg
42433c89af1Smrg    num_args = 0;
42533c89af1Smrg    XtSetArg(args[num_args], XtNx, x); num_args++;
42633c89af1Smrg    XtSetArg(args[num_args], XtNy, y); num_args++;
42733c89af1Smrg    XtSetValues(w, args, num_args);
42833c89af1Smrg
42933c89af1Smrg    XtPopup(w, mode);
43033c89af1Smrg}
43133c89af1Smrg
43233c89af1Smrg/*	Function Name: _PopdownFileDialog
43333c89af1Smrg *	Description: Destroys the file dialog, and calls the correct function.
43433c89af1Smrg *	Arguments:  w - a child of the dialog widget.
435352bf44eSmrg *                  client_data - TRUE if command was successful.
43633c89af1Smrg *                  junk - ** UNUSED **.
43733c89af1Smrg *	Returns: none.
43833c89af1Smrg */
43933c89af1Smrg
44033c89af1Smrg/* ARGSUSED */
44133c89af1Smrg
442ad47b356Smrgvoid
443278eca22Smrg_PopdownFileDialog(Widget w, XtPointer client_data, XtPointer junk)
44433c89af1Smrg{
44533c89af1Smrg    Widget dialog = XtParent(w);
44633c89af1Smrg    XPointer file_info_ptr;
44733c89af1Smrg    FileDialogInfo * file_info;
44833c89af1Smrg
44933c89af1Smrg    if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
45033c89af1Smrg		     &file_info_ptr) == XCNOENT) {
451ad47b356Smrg	SetMessage(global_screen_data.info_label,
452ad47b356Smrg		   "Error while trying to find Context\nAborting...");
45333c89af1Smrg    }
45433c89af1Smrg
455ad47b356Smrg    (void) XDeleteContext(XtDisplay(dialog), (Window)dialog,
45633c89af1Smrg			  file_dialog_context);
45733c89af1Smrg
45833c89af1Smrg    file_info = (FileDialogInfo *) file_info_ptr;
45933c89af1Smrg
46033c89af1Smrg    if ( ((Boolean)(long) client_data) == TRUE ) {
46133c89af1Smrg	String filename = XawDialogGetValueString(dialog);
46233c89af1Smrg
46333c89af1Smrg	(*file_info->func)(w, file_info->data, filename); /* call handler */
46433c89af1Smrg    }
46533c89af1Smrg
46633c89af1Smrg    XtFree( (XtPointer) file_info); /* Free data. */
46733c89af1Smrg
46833c89af1Smrg    XtPopdown(XtParent(dialog));
46933c89af1Smrg    XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
47033c89af1Smrg}
47133c89af1Smrg
47233c89af1Smrg/************************************************************
47333c89af1Smrg *
47433c89af1Smrg * Functions for dealing with the Resource Box.
47533c89af1Smrg *
47633c89af1Smrg ************************************************************/
47733c89af1Smrg
47833c89af1Smrg/*    Function Name: GetNamesAndClasses
47933c89af1Smrg *    Description: Gets a list of names and classes for this widget.
48033c89af1Smrg *    Arguments: node - this widget's node.
48133c89af1Smrg *                 names, classes - list of names and classes. ** RETURNED **
48233c89af1Smrg *    Returns: none.
48333c89af1Smrg */
48433c89af1Smrg
48533c89af1Smrgvoid
486278eca22SmrgGetNamesAndClasses(WNode *node, char ***names, char ***classes)
48733c89af1Smrg{
48833c89af1Smrg    int i, total_widgets;
48933c89af1Smrg    WNode * temp = node;
49033c89af1Smrg
49133c89af1Smrg    for (total_widgets = 1 ; temp->parent != NULL ;
49233c89af1Smrg       total_widgets++, temp = temp->parent) {}
49333c89af1Smrg
49433c89af1Smrg    *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
49533c89af1Smrg    *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
49633c89af1Smrg
49733c89af1Smrg    (*names)[total_widgets] = (*classes)[total_widgets] = NULL;
49833c89af1Smrg
49933c89af1Smrg    for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
50033c89af1Smrg      (*names)[i] = node->name;
50133c89af1Smrg      (*classes)[i] = node->class;
50233c89af1Smrg    }
50333c89af1Smrg}
50433c89af1Smrg
50533c89af1Smrg/*	Function Name: HandleGetResources
50633c89af1Smrg *	Description: Gets the resources.
50733c89af1Smrg *	Arguments: event - the information from the client.
50833c89af1Smrg *	Returns: an error message to display.
50933c89af1Smrg */
51033c89af1Smrg
51133c89af1Smrgchar *
512278eca22SmrgHandleGetResources(Event *event)
51333c89af1Smrg{
51433c89af1Smrg    GetResourcesEvent * get_event = (GetResourcesEvent *) event;
51533c89af1Smrg    char buf[BUFSIZ], * errors = NULL;
51633c89af1Smrg    int i;
51733c89af1Smrg    WNode * node;
51833c89af1Smrg
51933c89af1Smrg    for (i = 0; i < (int)get_event->num_entries; i++) {
52033c89af1Smrg	node = FindNode(global_tree_info->top_node,
521ad47b356Smrg			get_event->info[i].widgets.ids,
52233c89af1Smrg			get_event->info[i].widgets.num_widgets);
52333c89af1Smrg
52433c89af1Smrg	if (node == NULL) {
525ad47b356Smrg	    snprintf(buf, sizeof(buf), res_labels[16]);
526ad47b356Smrg	    AddString(&errors, buf);
527ad47b356Smrg	    continue;
52833c89af1Smrg	}
52933c89af1Smrg
530ad47b356Smrg	if (node->resources != NULL)
53133c89af1Smrg	    FreeResources(node->resources);
53233c89af1Smrg
53333c89af1Smrg	if (!get_event->info[i].error) {
53433c89af1Smrg	    node->resources = ParseResources(get_event->info + i, &errors);
53533c89af1Smrg	    CreateResourceBox(node, &errors);
53633c89af1Smrg	}
53733c89af1Smrg	else {
53833c89af1Smrg	    AddString(&errors, get_event->info[i].message);
53933c89af1Smrg	    AddString(&errors, "\n");
54033c89af1Smrg	}
54133c89af1Smrg    }
54233c89af1Smrg
54333c89af1Smrg    return(errors);
54433c89af1Smrg}
54533c89af1Smrg
54633c89af1Smrg/*	Function Name: CreateResourceBox
54733c89af1Smrg *	Description: Creates a resource box for the widget specified.
54833c89af1Smrg *	Arguments: node - the node of the widget in question.
54933c89af1Smrg *                 errors - an error string.
55033c89af1Smrg *	Returns: none.
55133c89af1Smrg */
55233c89af1Smrg
55333c89af1Smrgvoid
554278eca22SmrgCreateResourceBox(WNode *node, char **errors)
55533c89af1Smrg{
55633c89af1Smrg    WidgetResources * resources = node->resources;
55733c89af1Smrg    char ** names, ** cons_names;
55833c89af1Smrg    int i;
55933c89af1Smrg
56033c89af1Smrg    if (global_resource_box_up) {
56133c89af1Smrg	AddString(errors, res_labels[34]);
56233c89af1Smrg	return;
56333c89af1Smrg    }
56433c89af1Smrg    else
56533c89af1Smrg	global_resource_box_up = TRUE;
56633c89af1Smrg
56733c89af1Smrg    if (resources->num_normal > 0) {
56833c89af1Smrg	names = (char **) XtMalloc(sizeof(char *) *
56933c89af1Smrg				   (resources->num_normal + 1));
570ad47b356Smrg	for (i = 0 ; i < resources->num_normal ; i++)
57133c89af1Smrg	    names[i] = resources->normal[i].name;
57233c89af1Smrg	names[i] = NULL;
57333c89af1Smrg    }
57433c89af1Smrg    else
57533c89af1Smrg	names = NULL;
57633c89af1Smrg
57733c89af1Smrg    if (resources->num_constraint > 0) {
57833c89af1Smrg	cons_names = (char **) XtMalloc(sizeof(char *) *
57933c89af1Smrg					(resources->num_constraint + 1));
580ad47b356Smrg
581ad47b356Smrg	for (i = 0 ; i < resources->num_constraint ; i++)
58233c89af1Smrg	    cons_names[i] = resources->constraint[i].name;
58333c89af1Smrg	cons_names[i] = NULL;
58433c89af1Smrg    }
58533c89af1Smrg    else
58633c89af1Smrg	cons_names = NULL;
58733c89af1Smrg
58833c89af1Smrg    CreateResourceBoxWidgets(node, names, cons_names);
58933c89af1Smrg}
59033c89af1Smrg
59133c89af1Smrg/*	Function Name: ParseResources
59233c89af1Smrg *	Description: Parses the resource values returned from the client
59333c89af1Smrg *                   into a resources structure.
59433c89af1Smrg *	Arguments: info - info about a widget's resources.
59533c89af1Smrg *                 error - where to place error info.
59633c89af1Smrg *	Returns: The resource information.
59733c89af1Smrg */
59833c89af1Smrg
599ad47b356Smrgstatic WidgetResources *
600278eca22SmrgParseResources(GetResourcesInfo *info, char **error)
60133c89af1Smrg{
60233c89af1Smrg    WidgetResources * resources;
60333c89af1Smrg    WidgetResourceInfo * normal;
60433c89af1Smrg    int i;
60533c89af1Smrg
606ad47b356Smrg    resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources));
607ad47b356Smrg
60833c89af1Smrg    /*
60933c89af1Smrg     * Allocate enough space for both the normal and constraint resources,
61033c89af1Smrg     * then add the normal resources from the top, and the constraint resources
61133c89af1Smrg     * from the bottom.  This assures that enough memory is allocated, and
61233c89af1Smrg     * that there is no overlap.
61333c89af1Smrg     */
61433c89af1Smrg
615ad47b356Smrg    resources->normal = (WidgetResourceInfo *)
61633c89af1Smrg	            XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
61733c89af1Smrg
61833c89af1Smrg    normal = resources->normal;
61933c89af1Smrg    resources->constraint = resources->normal + info->num_resources - 1;
62033c89af1Smrg
62133c89af1Smrg    resources->num_constraint = resources->num_normal = 0;
62233c89af1Smrg
62333c89af1Smrg    for (i = 0; i < (int)info->num_resources; i++) {
62433c89af1Smrg	switch((int) info->res_info[i].res_type) {
62533c89af1Smrg	case NormalResource:
62633c89af1Smrg	    resources->num_normal++;
627ad47b356Smrg	    AddResource(info->res_info + i, normal++);
62833c89af1Smrg	    break;
62933c89af1Smrg	case ConstraintResource:
63033c89af1Smrg	    resources->num_constraint++;
63133c89af1Smrg	    AddResource(info->res_info + i, resources->constraint--);
63233c89af1Smrg	    break;
63333c89af1Smrg	default:
63433c89af1Smrg	    {
63533c89af1Smrg		char buf[BUFSIZ];
636ad47b356Smrg		snprintf(buf, sizeof(buf), "Unknown resource type %d\n",
637ad47b356Smrg                         info->res_info[i].res_type);
63833c89af1Smrg		AddString(error, buf);
63933c89af1Smrg	    }
64033c89af1Smrg	    break;
64133c89af1Smrg	}
64233c89af1Smrg    }
64333c89af1Smrg
64433c89af1Smrg    /*
645ad47b356Smrg     * Sort the resources alphabetically.
64633c89af1Smrg     */
64733c89af1Smrg
64833c89af1Smrg    qsort(resources->normal, resources->num_normal,
64933c89af1Smrg	  sizeof(WidgetResourceInfo), CompareResourceEntries);
65033c89af1Smrg
65133c89af1Smrg    if (resources->num_constraint > 0) {
65233c89af1Smrg	resources->constraint++;
65333c89af1Smrg	qsort(resources->constraint, resources->num_constraint,
65433c89af1Smrg	      sizeof(WidgetResourceInfo), CompareResourceEntries);
65533c89af1Smrg    }
65633c89af1Smrg    else
65733c89af1Smrg	resources->constraint = NULL;
65833c89af1Smrg
65933c89af1Smrg    return(resources);
66033c89af1Smrg}
66133c89af1Smrg
66233c89af1Smrg/*	Function Name: CompareResourceEntries
66333c89af1Smrg *	Description: Compares two resource entries.
66433c89af1Smrg *	Arguments: e1, e2 - the entries to compare.
66533c89af1Smrg *	Returns: an integer >, < or = 0.
66633c89af1Smrg */
66733c89af1Smrg
668ad47b356Smrgstatic int
669278eca22SmrgCompareResourceEntries(const void *e1, const void *e2)
67033c89af1Smrg{
671ad47b356Smrg    return (strcmp(((WidgetResourceInfo *)e1)->name,
67233c89af1Smrg		   ((WidgetResourceInfo *)e2)->name));
67333c89af1Smrg}
67433c89af1Smrg
67533c89af1Smrg/*	Function Name: AddResource
67633c89af1Smrg *	Description: Parses the resource string a stuffs in individual
67733c89af1Smrg *                   parts into the resource info struct.
67833c89af1Smrg *	Arguments: res_info - the resource info from the event.
67933c89af1Smrg *                 resource - location to stuff the resource into.
68033c89af1Smrg *	Returns: none.
68133c89af1Smrg */
68233c89af1Smrg
68333c89af1Smrgstatic void
684278eca22SmrgAddResource(ResourceInfo *res_info, WidgetResourceInfo *resource)
68533c89af1Smrg{
68633c89af1Smrg    resource->name = res_info->name;
68733c89af1Smrg    res_info->name = NULL;	/* Keeps it from being deallocated. */
68833c89af1Smrg    resource->class = res_info->class;
68933c89af1Smrg    res_info->class = NULL;	/* Keeps it from being deallocated. */
69033c89af1Smrg    resource->type = res_info->type;
69133c89af1Smrg    res_info->type = NULL;	/* Keeps it from being deallocated. */
69233c89af1Smrg}
69333c89af1Smrg
69433c89af1Smrg
69533c89af1Smrg/*	Function Name: FreeResources
696352bf44eSmrg *	Description: frees the resource information.
69733c89af1Smrg *	Arguments: resources.
69833c89af1Smrg *	Returns: none.
69933c89af1Smrg */
70033c89af1Smrg
70133c89af1Smrgstatic void
702278eca22SmrgFreeResources(WidgetResources *resources)
70333c89af1Smrg{
70433c89af1Smrg    int i;
70533c89af1Smrg
70633c89af1Smrg    if (resources->num_normal > 0) {
70733c89af1Smrg	for (i = 0; i < resources->num_normal; i++) {
70833c89af1Smrg	    XtFree(resources->normal[i].name);
70933c89af1Smrg	    XtFree(resources->normal[i].class);
71033c89af1Smrg	    XtFree(resources->normal[i].type);
71133c89af1Smrg	}
71233c89af1Smrg	XFree((char *)resources->normal);
71333c89af1Smrg    }
71433c89af1Smrg
71533c89af1Smrg    if (resources->num_constraint > 0) {
71633c89af1Smrg	for (i = 0; i < resources->num_constraint; i++) {
71733c89af1Smrg	    XtFree(resources->constraint[i].name);
71833c89af1Smrg	    XtFree(resources->constraint[i].class);
71933c89af1Smrg	    XtFree(resources->constraint[i].type);
72033c89af1Smrg	}
72133c89af1Smrg	XFree((char *)resources->constraint);
72233c89af1Smrg    }
72333c89af1Smrg
72433c89af1Smrg    XFree((char *)resources);
72533c89af1Smrg}
726ad47b356Smrg
72733c89af1Smrg
72833c89af1Smrg/*	Function Name: CheckDatabase
72933c89af1Smrg *	Description: Checks to see if the node is in the database.
73033c89af1Smrg *	Arguments: db - the db to check
731352bf44eSmrg *                 names, classes - names and classes, represented as quarks.
73233c89af1Smrg *	Returns: True if this entry is found.
73333c89af1Smrg */
73433c89af1Smrg
73533c89af1SmrgBoolean
736278eca22SmrgCheckDatabase(XrmDatabase db, XrmQuarkList names, XrmQuarkList classes)
73733c89af1Smrg{
73833c89af1Smrg    XrmRepresentation junk;
73933c89af1Smrg    XrmValue garbage;
74033c89af1Smrg
74133c89af1Smrg    return(XrmQGetResource(db, names, classes, &junk, &garbage));
74233c89af1Smrg}
74333c89af1Smrg
74433c89af1Smrg/*	Function Name: Quarkify
745352bf44eSmrg *	Description: Quarkifies the string list specified.
74633c89af1Smrg *	Arguments: list - list of strings to quarkify
74733c89af1Smrg *                 ptr - an additional string to quarkify.
74833c89af1Smrg *	Returns: none.
74933c89af1Smrg */
75033c89af1Smrg
75133c89af1SmrgXrmQuarkList
752352bf44eSmrgQuarkify(char **list, const char *ptr)
75333c89af1Smrg{
75433c89af1Smrg    int i;
75533c89af1Smrg    char ** tlist;
75633c89af1Smrg    XrmQuarkList quarks, tquarks;
75733c89af1Smrg
75833c89af1Smrg    for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
75933c89af1Smrg    if (ptr != NULL)
76033c89af1Smrg	i++;
76133c89af1Smrg    i++;			/* leave space for NULLQUARK */
76233c89af1Smrg
76333c89af1Smrg    quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
76433c89af1Smrg
765ad47b356Smrg    for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++)
76633c89af1Smrg	*tquarks = XrmStringToQuark(*tlist);
76733c89af1Smrg
768ad47b356Smrg    if (ptr != NULL)
76933c89af1Smrg	*tquarks++ = XrmStringToQuark(ptr);
770ad47b356Smrg
77133c89af1Smrg    *tquarks = NULLQUARK;
77233c89af1Smrg    return(quarks);
77333c89af1Smrg}
77433c89af1Smrg
77533c89af1Smrg/*	Function Name: ExecuteOverAllNodes
77633c89af1Smrg *	Description: Executes the given function over all nodes.
77733c89af1Smrg *	Arguments: top_node - top node of the tree.
77833c89af1Smrg *                 func - the function to execute.
77933c89af1Smrg *                 data - a data pointer to pass to the function.
78033c89af1Smrg *	Returns: none
78133c89af1Smrg */
78233c89af1Smrg
78333c89af1Smrgvoid
784278eca22SmrgExecuteOverAllNodes(WNode *top_node, void (*func)(WNode *, XtPointer),
785278eca22Smrg		    XtPointer data)
78633c89af1Smrg{
787ad47b356Smrg    Cardinal i;
78833c89af1Smrg
78933c89af1Smrg    (*func)(top_node, data);
79033c89af1Smrg
791ad47b356Smrg    for (i = 0; i < top_node->num_children; i++)
79233c89af1Smrg	ExecuteOverAllNodes(top_node->children[i], func, data);
79333c89af1Smrg}
79433c89af1Smrg
79533c89af1Smrg/*	Function Name: InsertWidgetFromNode
79633c89af1Smrg *	Description: Inserts the widget info for this widget represented
79733c89af1Smrg *                   by this node.
79833c89af1Smrg *	Arguments: stream - the stream to insert it info into.
79933c89af1Smrg *                 none - the widget node to insert.
80033c89af1Smrg *	Returns: none
80133c89af1Smrg */
80233c89af1Smrg
80333c89af1Smrgvoid
804278eca22SmrgInsertWidgetFromNode(ProtocolStream *stream, WNode *node)
80533c89af1Smrg{
80633c89af1Smrg    WNode *temp;
80733c89af1Smrg    unsigned long * widget_list;
80833c89af1Smrg    register int i, num_widgets;
80933c89af1Smrg
810278eca22Smrg    for (temp = node, i = 0; temp != NULL; temp = temp->parent, i++) {}
81133c89af1Smrg
81233c89af1Smrg    num_widgets = i;
813ad47b356Smrg    widget_list = (unsigned long *)
81433c89af1Smrg	          XtMalloc(sizeof(unsigned long) * num_widgets);
81533c89af1Smrg
81633c89af1Smrg    /*
81733c89af1Smrg     * Put the widgets into the list.
81833c89af1Smrg     * Make sure that they are inserted in the list from parent -> child.
81933c89af1Smrg     */
82033c89af1Smrg
821ad47b356Smrg    for (i--, temp = node; temp != NULL; temp = temp->parent, i--)
82233c89af1Smrg	widget_list[i] = temp->id;
823ad47b356Smrg
82433c89af1Smrg    _XEditResPut16(stream, num_widgets);	/* insert number of widgets. */
82533c89af1Smrg    for (i = 0; i < num_widgets; i++) 	/* insert Widgets themselves. */
82633c89af1Smrg	_XEditResPut32(stream, widget_list[i]);
827ad47b356Smrg
82833c89af1Smrg    XtFree((char *)widget_list);
82933c89af1Smrg}
83033c89af1Smrg
83133c89af1Smrg/*	Function Name: GetFailureMesssage
83233c89af1Smrg *	Description: returns the message returned from a failed request.
83333c89af1Smrg *	Arguments: stream - the protocol stream containing the message.
83433c89af1Smrg *	Returns: message to show.
83533c89af1Smrg */
83633c89af1Smrg
837ad47b356Smrgchar *
838278eca22SmrgGetFailureMessage(ProtocolStream *stream)
83933c89af1Smrg{
84033c89af1Smrg    char * return_str;
84133c89af1Smrg
842ad47b356Smrg    if (_XEditResGetString8(stream, &return_str))
84333c89af1Smrg	return(return_str);
84433c89af1Smrg
84533c89af1Smrg    return(XtNewString(res_labels[35]));
84633c89af1Smrg}
84733c89af1Smrg
84833c89af1Smrg/*	Function Name: ProtocolFailure
84933c89af1Smrg *	Description: Gets the version of the protocol the client is
85033c89af1Smrg *                   willing to speak.
85133c89af1Smrg *	Arguments: stream - the protocol stream containing the message.
85233c89af1Smrg *	Returns: message to show.
85333c89af1Smrg */
85433c89af1Smrg
855ad47b356Smrgchar *
856278eca22SmrgProtocolFailure(ProtocolStream *stream)
85733c89af1Smrg{
85833c89af1Smrg    char buf[BUFSIZ];
85933c89af1Smrg    unsigned char version;
860352bf44eSmrg    const char* old_version_string;
86133c89af1Smrg
862ad47b356Smrg    if (!_XEditResGet8(stream, &version))
86333c89af1Smrg	return(XtNewString(res_labels[35]));
86433c89af1Smrg
86533c89af1Smrg    switch ((int)version) {
86633c89af1Smrg    case PROTOCOL_VERSION_ONE_POINT_ZERO: old_version_string = "1.0"; break;
86733c89af1Smrg    default: old_version_string = "1.0";
86833c89af1Smrg    }
869ad47b356Smrg
870ad47b356Smrg    snprintf(buf, sizeof(buf), res_labels[36],
871ad47b356Smrg             CURRENT_PROTOCOL_VERSION_STRING, old_version_string);
87233c89af1Smrg    return(XtNewString(buf));
87333c89af1Smrg}
874ad47b356Smrg
875