/* * $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.6 2001/12/14 20:00:43 dawes Exp $ */ #include #include #include #include #include #include #include #include #include #include #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 . * * 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)); }