diff options
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 915 |
1 files changed, 915 insertions, 0 deletions
@@ -0,0 +1,915 @@ +/* + * $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. + */ + +#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 "editresP.h" + +static WidgetResources * ParseResources(); +static int CompareResourceEntries(); +static void FreeResources(), AddResource(); +static WNode * FindWidgetFromWindowGivenNode(); + +void CreateResourceBox(); + +extern void PopupCentered(), PerformTreeToFileDump(); + +/* 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(in, sep, out, num) +char *in, sep, ***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; +char * 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(filename, "w")) == NULL ) { + char buf[BUFSIZ]; + + sprintf(buf, res_labels[24], 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 { + void (*func)(); + XtPointer data; +} FileDialogInfo; + +void +_PopupFileDialog(w, str, default_value, func, data) +Widget w; +String str, default_value; +void (*func)(); +XtPointer data; +{ + FileDialogInfo * file_info; + Widget shell, dialog; + Arg args[2]; + Cardinal num_args; + void _PopdownFileDialog(); + + 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; +{ + void CreateResourceBoxWidgets(); + 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) +WidgetResourceInfo *e1, *e2; +{ + return (strcmp(e1->name, 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)(); +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)); +} + |