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