2
* $Xorg: utils.c,v 1.4 2001/02/09 02:05:30 xorgcvs Exp $
4
Copyright 1989, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
26
/* $XFree86: xc/programs/editres/utils.c,v 1.6 2001/12/14 20:00:43 dawes Exp $ */
28
#include <X11/Intrinsic.h>
29
#include <X11/Xutil.h>
31
#include <X11/Shell.h>
32
#include <X11/StringDefs.h>
34
#include <X11/Xaw/Cardinals.h>
35
#include <X11/Xaw/Dialog.h>
39
#include <X11/Xmu/Error.h>
43
static WNode * FindWidgetFromWindowGivenNode ( WNode * node, Window win );
44
static WidgetResources * ParseResources ( GetResourcesInfo * info,
46
static int CompareResourceEntries ( const void *e1,
48
static void AddResource ( ResourceInfo * res_info,
49
WidgetResourceInfo * resource );
50
static void FreeResources ( WidgetResources * resources );
53
/* Function Name: SetMessage(w, str)
54
* Description: shows the message to the user.
55
* Arguments: w - a label widget to show the message in.
56
* str - the string to show.
67
XtSetArg(args[0], XtNlabel, str);
68
XtSetValues(w, args, ONE);
71
/* Function Name: GetAllStrings
72
* Description: Returns a list of strings that have been borken up by
73
* the character specified.
74
* Arguments: in - the string to parse.
75
* sep - the separator character.
76
* out - the strings to send out.
77
* num - the number of strings in out.
82
GetAllStrings(char *in, char sep, char ***out, int *num)
87
if (*in == sep) /* jump over first char if it is the sep. */
91
* count the number of strings.
94
for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++)
98
* Create Enough space for pointers and string.
101
size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
102
*out = (char **) XtMalloc( (Cardinal) size);
104
ptr = (char *) (*out + *num);
108
* Change all `sep' characters to '\0' and stuff the pointer into
109
* the next pointer slot.
115
if ((ptr = strchr(ptr, sep)) == NULL)
123
* If last string is empty then strip it off.
126
if ( *((*out)[i - 1]) == '\0' )
130
/* Function Name: AddString
131
* Description: Mallocs and strcats the string onto the end of
133
* Arguments: str - string to add on to.
134
* add - string to add.
142
int len_str, len_add;
145
len_str = ((*str) ? strlen(*str) : 0);
146
len_add = strlen(add);
148
*str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
149
ptr = *str + len_str;
153
/* Function Name: FindNode
154
* Description: Finds a node give the top node, and a node id number.
155
* Arguments: top_node - the top node.
161
FindNode(top_node, ids, number)
169
if (top_node == NULL)
172
if (ids[0] != top_node->id)
175
for (node = top_node, i = 1 ; i < number; i++) {
176
Boolean found_it = FALSE;
178
for (j = 0; j < node->num_children; j++) {
179
if (node->children[j]->id == ids[i]) {
180
node = node->children[j];
191
/* Function Name: FindWidgetFromWindow
192
* Description: finds a widget in the current tree given its window id.
193
* Arguments: tree_info - information about this tree.
194
* win - window to search for.
195
* Returns: node - the node corrosponding to this widget.
199
FindWidgetFromWindow(tree_info, win)
200
TreeInfo * tree_info;
203
if (tree_info == NULL)
206
return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
209
/* Function Name: FindWidgetFromWindowGivenNode
210
* Description: finds a widget in the current tree given its window id.
211
* Arguments: node - current node.
212
* win - window to search for.
213
* Returns: node - the node corrosponding to this widget.
217
FindWidgetFromWindowGivenNode(node, win)
224
if (node->window == win)
227
for (i = 0; i < node->num_children; i++) {
228
ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
229
if (ret_node != NULL)
235
/* Function Name: HandleXErrors
236
* Description: Handles error codes from the server.
237
* Arguments: display - the display.
238
* error - error information.
244
HandleXErrors(display, error)
248
if (error->serial != global_serial_num) {
249
(*global_old_error_handler) (display, error);
253
if (error->error_code == BadWindow)
254
global_error_code = NO_WINDOW;
256
if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
262
/* Function Name: _DumpTreeToFile
263
* Description: Dumps the widget tree to a file
264
* Arguments: w - a random widget in the application on the
265
* currently active display
266
* tree_ptr - pointer to the widget tree info.
267
* filename - name of the file.
274
_DumpTreeToFile(w, tree_ptr, filename)
279
TreeInfo * tree_info = (TreeInfo *) tree_ptr;
282
if (tree_info == NULL) {
283
SetMessage(global_screen_data.info_label,
288
if ( (fp = fopen((char *)filename, "w")) == NULL ) {
291
sprintf(buf, res_labels[24], (char *)filename);
292
SetMessage(global_screen_data.info_label, buf);
296
PerformTreeToFileDump(tree_info->top_node, 0, fp);
300
/************************************************************
302
* The file dialog boxes are handled with this code.
304
* It automatically calls the function specified when the
305
* user selects okay, or hits <CR>.
307
* A translation is required in the app-defaults file.
309
************************************************************/
311
/* Function Name: _PopupFileDialog
312
* Description: Puts up a dialog box to get the filename.
313
* Arguments: str - message.
314
* default_value - the default value of the filename;
315
* func - function to call when filename has been entered.
316
* data - generic data to pass to func.
320
static XContext file_dialog_context = None;
322
typedef struct _FileDialogInfo {
328
_PopupFileDialog(w, str, default_value, func, data)
330
String str, default_value;
334
FileDialogInfo * file_info;
335
Widget shell, dialog;
339
if (file_dialog_context == None)
340
file_dialog_context = XUniqueContext();
342
shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
346
XtSetArg(args[num_args], XtNlabel, str); num_args++;
347
XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
348
dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
349
shell, args, num_args);
351
file_info = XtNew(FileDialogInfo);
353
file_info->func = func;
354
file_info->data = data;
356
if (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
357
(XPointer) file_info) != 0) {
358
SetMessage(global_screen_data.info_label,
359
"Error while trying to save Context\nAborting file dialog popup.");
360
XtDestroyWidget(shell);
364
XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
365
XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
367
PopupCentered(NULL, shell, XtGrabNone);
370
/* Function Name: PopupCentered
371
* Description: Pops up the window specified under the location passed
372
* in the event, or under the cursor.
373
* Arguments: event - the event that we should use.
374
* w - widget to popup.
375
* mode - mode to pop it up in.
380
PopupCentered(event, w, mode)
385
Boolean get_from_cursor = FALSE;
388
Dimension width, height, b_width;
389
int x, y, max_x, max_y;
394
get_from_cursor = TRUE;
396
switch (event->type) {
399
x = event->xbutton.x_root;
400
y = event->xbutton.y_root;
404
x = event->xkey.x_root;
405
y = event->xkey.y_root;
408
get_from_cursor = TRUE;
413
if (get_from_cursor) {
418
XQueryPointer(XtDisplay(w), XtWindow(w),
419
&root, &child, &x, &y, &win_x, &win_y, &mask);
423
XtSetArg(args[num_args], XtNwidth, &width); num_args++;
424
XtSetArg(args[num_args], XtNheight, &height); num_args++;
425
XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
426
XtGetValues(w, args, num_args);
428
width += 2 * b_width;
429
height += 2 * b_width;
431
x -= ((int) width/2);
434
if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
437
y -= ( (Position) height/2 );
440
if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
444
XtSetArg(args[num_args], XtNx, x); num_args++;
445
XtSetArg(args[num_args], XtNy, y); num_args++;
446
XtSetValues(w, args, num_args);
451
/* Function Name: _PopdownFileDialog
452
* Description: Destroys the file dialog, and calls the correct function.
453
* Arguments: w - a child of the dialog widget.
454
* client_data - TRUE if command was sucessful.
455
* junk - ** UNUSED **.
462
_PopdownFileDialog(w, client_data, junk)
464
XtPointer client_data, junk;
466
Widget dialog = XtParent(w);
467
XPointer file_info_ptr;
468
FileDialogInfo * file_info;
470
if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
471
&file_info_ptr) == XCNOENT) {
472
SetMessage(global_screen_data.info_label,
473
"Error while trying to find Context\nAborting...");
476
(void) XDeleteContext(XtDisplay(dialog), (Window)dialog,
477
file_dialog_context);
479
file_info = (FileDialogInfo *) file_info_ptr;
481
if ( ((Boolean)(long) client_data) == TRUE ) {
482
String filename = XawDialogGetValueString(dialog);
484
(*file_info->func)(w, file_info->data, filename); /* call handler */
487
XtFree( (XtPointer) file_info); /* Free data. */
489
XtPopdown(XtParent(dialog));
490
XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
493
/************************************************************
495
* Functions for dealing with the Resource Box.
497
************************************************************/
499
/* Function Name: GetNamesAndClasses
500
* Description: Gets a list of names and classes for this widget.
501
* Arguments: node - this widget's node.
502
* names, classes - list of names and classes. ** RETURNED **
507
GetNamesAndClasses(node, names, classes)
509
char *** names, ***classes;
511
int i, total_widgets;
514
for (total_widgets = 1 ; temp->parent != NULL ;
515
total_widgets++, temp = temp->parent) {}
517
*names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
518
*classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
520
(*names)[total_widgets] = (*classes)[total_widgets] = NULL;
522
for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
523
(*names)[i] = node->name;
524
(*classes)[i] = node->class;
528
/* Function Name: HandleGetResources
529
* Description: Gets the resources.
530
* Arguments: event - the information from the client.
531
* Returns: an error message to display.
535
HandleGetResources(event)
538
GetResourcesEvent * get_event = (GetResourcesEvent *) event;
539
char buf[BUFSIZ], * errors = NULL;
543
for (i = 0; i < (int)get_event->num_entries; i++) {
544
node = FindNode(global_tree_info->top_node,
545
get_event->info[i].widgets.ids,
546
get_event->info[i].widgets.num_widgets);
549
sprintf(buf, res_labels[16]);
550
AddString(&errors, buf);
554
if (node->resources != NULL)
555
FreeResources(node->resources);
557
if (!get_event->info[i].error) {
558
node->resources = ParseResources(get_event->info + i, &errors);
559
CreateResourceBox(node, &errors);
562
AddString(&errors, get_event->info[i].message);
563
AddString(&errors, "\n");
570
/* Function Name: CreateResourceBox
571
* Description: Creates a resource box for the widget specified.
572
* Arguments: node - the node of the widget in question.
573
* errors - an error string.
578
CreateResourceBox(node, errors)
582
WidgetResources * resources = node->resources;
583
char ** names, ** cons_names;
586
if (global_resource_box_up) {
587
AddString(errors, res_labels[34]);
591
global_resource_box_up = TRUE;
593
if (resources->num_normal > 0) {
594
names = (char **) XtMalloc(sizeof(char *) *
595
(resources->num_normal + 1));
596
for (i = 0 ; i < resources->num_normal ; i++)
597
names[i] = resources->normal[i].name;
603
if (resources->num_constraint > 0) {
604
cons_names = (char **) XtMalloc(sizeof(char *) *
605
(resources->num_constraint + 1));
607
for (i = 0 ; i < resources->num_constraint ; i++)
608
cons_names[i] = resources->constraint[i].name;
609
cons_names[i] = NULL;
614
CreateResourceBoxWidgets(node, names, cons_names);
617
/* Function Name: ParseResources
618
* Description: Parses the resource values returned from the client
619
* into a resources structure.
620
* Arguments: info - info about a widget's resources.
621
* error - where to place error info.
622
* Returns: The resource information.
625
static WidgetResources *
626
ParseResources(info, error)
627
GetResourcesInfo * info;
630
WidgetResources * resources;
631
WidgetResourceInfo * normal;
634
resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources));
637
* Allocate enough space for both the normal and constraint resources,
638
* then add the normal resources from the top, and the constraint resources
639
* from the bottom. This assures that enough memory is allocated, and
640
* that there is no overlap.
643
resources->normal = (WidgetResourceInfo *)
644
XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
646
normal = resources->normal;
647
resources->constraint = resources->normal + info->num_resources - 1;
649
resources->num_constraint = resources->num_normal = 0;
651
for (i = 0; i < (int)info->num_resources; i++) {
652
switch((int) info->res_info[i].res_type) {
654
resources->num_normal++;
655
AddResource(info->res_info + i, normal++);
657
case ConstraintResource:
658
resources->num_constraint++;
659
AddResource(info->res_info + i, resources->constraint--);
664
sprintf(buf, "Unknown resource type %d\n",
665
info->res_info[i].res_type);
666
AddString(error, buf);
673
* Sort the resources alphabetically.
676
qsort(resources->normal, resources->num_normal,
677
sizeof(WidgetResourceInfo), CompareResourceEntries);
679
if (resources->num_constraint > 0) {
680
resources->constraint++;
681
qsort(resources->constraint, resources->num_constraint,
682
sizeof(WidgetResourceInfo), CompareResourceEntries);
685
resources->constraint = NULL;
690
/* Function Name: CompareResourceEntries
691
* Description: Compares two resource entries.
692
* Arguments: e1, e2 - the entries to compare.
693
* Returns: an integer >, < or = 0.
697
CompareResourceEntries(e1, e2)
700
return (strcmp(((WidgetResourceInfo *)e1)->name,
701
((WidgetResourceInfo *)e2)->name));
704
/* Function Name: AddResource
705
* Description: Parses the resource string a stuffs in individual
706
* parts into the resource info struct.
707
* Arguments: res_info - the resource info from the event.
708
* resource - location to stuff the resource into.
713
AddResource(res_info, resource)
714
ResourceInfo * res_info;
715
WidgetResourceInfo * resource;
717
resource->name = res_info->name;
718
res_info->name = NULL; /* Keeps it from being deallocated. */
719
resource->class = res_info->class;
720
res_info->class = NULL; /* Keeps it from being deallocated. */
721
resource->type = res_info->type;
722
res_info->type = NULL; /* Keeps it from being deallocated. */
726
/* Function Name: FreeResources
727
* Description: frees the resource inforation.
728
* Arguments: resources.
733
FreeResources(resources)
734
WidgetResources * resources;
738
if (resources->num_normal > 0) {
739
for (i = 0; i < resources->num_normal; i++) {
740
XtFree(resources->normal[i].name);
741
XtFree(resources->normal[i].class);
742
XtFree(resources->normal[i].type);
744
XFree((char *)resources->normal);
747
if (resources->num_constraint > 0) {
748
for (i = 0; i < resources->num_constraint; i++) {
749
XtFree(resources->constraint[i].name);
750
XtFree(resources->constraint[i].class);
751
XtFree(resources->constraint[i].type);
753
XFree((char *)resources->constraint);
756
XFree((char *)resources);
760
/* Function Name: CheckDatabase
761
* Description: Checks to see if the node is in the database.
762
* Arguments: db - the db to check
763
* names, clases - names and clases, represented as quarks.
764
* Returns: True if this entry is found.
768
CheckDatabase(db, names, classes)
770
XrmQuarkList names, classes;
772
XrmRepresentation junk;
775
return(XrmQGetResource(db, names, classes, &junk, &garbage));
778
/* Function Name: Quarkify
779
* Description: Quarkifies the string list specifed.
780
* Arguments: list - list of strings to quarkify
781
* ptr - an additional string to quarkify.
792
XrmQuarkList quarks, tquarks;
794
for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
797
i++; /* leave space for NULLQUARK */
799
quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
801
for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++)
802
*tquarks = XrmStringToQuark(*tlist);
805
*tquarks++ = XrmStringToQuark(ptr);
807
*tquarks = NULLQUARK;
811
/* Function Name: ExecuteOverAllNodes
812
* Description: Executes the given function over all nodes.
813
* Arguments: top_node - top node of the tree.
814
* func - the function to execute.
815
* data - a data pointer to pass to the function.
820
ExecuteOverAllNodes(top_node, func, data)
822
void (*func)(WNode *, XtPointer);
827
(*func)(top_node, data);
829
for (i = 0; i < top_node->num_children; i++)
830
ExecuteOverAllNodes(top_node->children[i], func, data);
833
/* Function Name: InsertWidgetFromNode
834
* Description: Inserts the widget info for this widget represented
836
* Arguments: stream - the stream to insert it info into.
837
* none - the widget node to insert.
842
InsertWidgetFromNode(stream, node)
843
ProtocolStream * stream;
847
unsigned long * widget_list;
848
register int i, num_widgets;
850
for (temp = node, i = 0; temp != 0; temp = temp->parent, i++) {}
853
widget_list = (unsigned long *)
854
XtMalloc(sizeof(unsigned long) * num_widgets);
857
* Put the widgets into the list.
858
* Make sure that they are inserted in the list from parent -> child.
861
for (i--, temp = node; temp != 0; temp = temp->parent, i--)
862
widget_list[i] = temp->id;
864
_XEditResPut16(stream, num_widgets); /* insert number of widgets. */
865
for (i = 0; i < num_widgets; i++) /* insert Widgets themselves. */
866
_XEditResPut32(stream, widget_list[i]);
868
XtFree((char *)widget_list);
871
/* Function Name: GetFailureMesssage
872
* Description: returns the message returned from a failed request.
873
* Arguments: stream - the protocol stream containing the message.
874
* Returns: message to show.
878
GetFailureMessage(stream)
879
ProtocolStream * stream;
883
if (_XEditResGetString8(stream, &return_str))
886
return(XtNewString(res_labels[35]));
889
/* Function Name: ProtocolFailure
890
* Description: Gets the version of the protocol the client is
892
* Arguments: stream - the protocol stream containing the message.
893
* Returns: message to show.
897
ProtocolFailure(stream)
898
ProtocolStream * stream;
901
unsigned char version;
902
char* old_version_string;
904
if (!_XEditResGet8(stream, &version))
905
return(XtNewString(res_labels[35]));
907
switch ((int)version) {
908
case PROTOCOL_VERSION_ONE_POINT_ZERO: old_version_string = "1.0"; break;
909
default: old_version_string = "1.0";
912
sprintf(buf, res_labels[36],
913
CURRENT_PROTOCOL_VERSION_STRING, old_version_string);
914
return(XtNewString(buf));