1 /* $XConsortium: widget.c /main/4 1995/11/01 15:57:40 rswiston $ */
3 /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
4 /* All Rights Reserved */
6 /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
7 /* UNIX System Laboratories, Inc. */
8 /* The copyright notice above does not evidence any */
9 /* actual or intended publication of such source code. */
14 #include <X11/Intrinsic.h>
15 #include <X11/IntrinsicP.h>
16 #include <X11/Shell.h>
17 #include <X11/StringDefs.h>
19 #include <Xm/XmStrDefs.h>
20 #include <Xm/DialogS.h>
31 #include "xmwidgets.h"
34 /* values for the flags field of the W array */
36 #define RESOURCE_HASHSIZE 64
37 #define CLASS_HASHSIZE 32
38 #define WIDGETALLOC 16 /* Will realloc the widget array in this increment */
43 int Wtab_free = 0; /* A count of how many table entries have been freed */
47 char str_0123456789[] = "0123456789";
54 static void fixupresources(
58 static int rescompare(
61 static void _pr_class(
63 static void _pr_resource_list(
65 static void sort_and_print_res( void ) ;
66 static void gather_resource_list(
70 static void _pr_resource(
73 static void pr_resource(
81 static char * getname(
85 static void pr_widinfo(
87 static void pr_widheader( void ) ;
94 register int i, n = 0;
100 if (C[0].class != NULL)
103 toolkit_init_widgets();
105 Wclasses = hashalloc(NULL, 0);
107 for (i = 0; C[i].cname != NULL; i++) {
108 if ((nam = hashput(Wclasses, C[i].cname, (char *)(&C[i]))) == NULL)
110 errhdr = strdup(GetSharedMsg(DT_ERROR));
111 errmsg = strdup(GETMESSAGE(14,1,
112 "Internal hash table failure during widget class initialization; exiting"));
113 printerr(errhdr, errmsg, NULL);
121 * The array of widget records starts out big enough to
122 * hold WIDGETALLOC widgets, and will grow in increments
123 * of WIDGETALLOC as it overflows.
125 W = (wtab_t **)XtMalloc(WIDGETALLOC*sizeof(wtab_t *));
126 wentries = (wtab_t *)XtCalloc(WIDGETALLOC, sizeof(wtab_t));
127 for (i = 0; i < WIDGETALLOC; i++)
130 wentries[i].type = TAB_EMPTY;
136 * string to widgetclass
144 register int i, j, n;
151 XmSecondaryResourceData * blockArray;
154 * If it looks like a handle, look it up and return the
155 * class of the widget associated with the handle.
157 if (s[0] == 'W' && strspn(&s[1], str_0123456789) == strlen(&s[1]))
159 wtab_t *w = str_to_wtab(arg0, s);
164 if ((nam = hashget(Wclasses, s)) != NULL)
166 ret = (classtab_t *)nam;
167 if (ret->res == NULL)
169 XtResourceList resources;
170 Cardinal numresources;
172 /* First reference of a given widget class
173 * Automatically causes that widget class to
174 * be initialized, it's resources read and
177 ret->res = (char *)hashalloc(NULL, 0);
180 * Have to force the class init
181 * of this widget to execute, else we won't
182 * get a complete list of resources, and any
183 * converters added by this widget won't be
186 XtInitializeWidgetClass(ret->class);
188 XtGetResourceList(ret->class, &resources, &numresources);
189 for (i = 0; i < numresources; i++)
191 if ((nam = (char *)hashput((Hash_table_t*)ret->res,
192 resources[i].resource_name, (char *)&resources[i])) == NULL)
194 errhdr = strdup(GetSharedMsg(DT_ERROR));
195 errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
196 printerrf(errhdr, errmsg, resources[i].resource_name,
197 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
203 /* Load any of Motif's secondary resources */
205 * The following is a special hack to work around a Motif bug
206 * (which has been reported). DialogShell is a grandchild class of
207 * VendorShell, which defines secondary resources. DialogShell is
208 * also a child class of TransientShell. Secondary resource
209 * information is contained within extension records, which the
210 * TransientShell class knows nothing about, thus preventing
211 * XmGetSecondaryResourceData from getting any secondary resources
212 * further up the inheritance chain.
214 if (ret->class == xmDialogShellWidgetClass)
216 numBlocks = XmGetSecondaryResourceData(vendorShellWidgetClass,
220 numBlocks = XmGetSecondaryResourceData(ret->class, &blockArray);
224 for (i = 0; i < numBlocks; i++)
226 for (j = 0; j < blockArray[i]->num_resources; j++)
228 if ((nam = (char *)hashput((Hash_table_t*)ret->res,
229 blockArray[i]->resources[j].resource_name,
230 (char *)&(blockArray[i]->resources[j]))) == NULL)
232 errhdr = strdup(GetSharedMsg(DT_ERROR));
233 errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
234 printerrf(errhdr, errmsg,
235 blockArray[i]->resources[j].resource_name,
236 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
242 * We can't free up the actual array of resources, since we
243 * hashed a reference to the entries into our resource hash
245 * XtFree((char *)blockArray[i]->resources);
247 XtFree((char *)blockArray[i]);
251 /* Perform any special resource fixing up */
252 fixupresources(s, (Hash_table_t *)ret->res,
253 (resfixup_t *)&ret->resfix[0]);
256 * Get constraint resources, if there are any
258 XtGetConstraintResourceList(ret->class, &resources, &numresources);
259 if (resources != NULL)
261 ret->con = (char *)hashalloc(NULL, 0);
262 for (i = 0; i < numresources; i++)
264 if ((nam = (char *)hashput((Hash_table_t*)ret->con,
265 resources[i].resource_name, &resources[i])) == NULL)
267 errhdr =strdup(GetSharedMsg(DT_ERROR));
268 errmsg=strdup(GetSharedMsg(DT_HASHING_FAILURE));
269 printerrf(errhdr, errmsg, resources[i].resource_name,
270 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
275 fixupresources(s, (Hash_table_t *)ret->con,
276 (resfixup_t *)&ret->confix[0]);
284 errmsg = strdup(GETMESSAGE(14,2,
285 "Could not find a widget class named '%s'"));
286 printerrf(arg0, errmsg, s, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
301 if (s == NULL || *s == '\0')
304 if (W == NULL || W[0] == NULL) {
305 errhdr = strdup(GetSharedMsg(DT_WARNING));
306 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
307 printerr(errhdr, errmsg, NULL);
312 len = strlen(W[0]->wname);
313 if (strncmp(s, W[0]->wname, len) == 0) {
317 return(XtNameToWidget(Toplevel, &s[len+1]));
323 * Take a character string and translate it into a wtab_t.
324 * The string should be of the form: W<num>. The <num> must
325 * point to a valid index in the W array.
327 * If the name is not of the correct form, we use XtNameToWidget
328 * to try to convert the name to a widget id.
339 if (v == NULL || strcmp(v, "NULL") == 0)
342 if (v[0] != 'W' || (len = strlen(v)) < 2 ||
343 strspn(&v[1], str_0123456789) != len-1) {
346 if ((wid = DtkshNameToWidget(v)) == NULL) {
349 errmsg = strdup(GETMESSAGE(14,3,
350 "The identifier '%s' is not a valid widget handle"));
351 printerrf(arg0, errmsg, v,
352 NULL, NULL, NULL, NULL, NULL,
359 return(widget_to_wtab(wid));
362 if (index < 0 || index >= NumW) {
365 errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
366 printerrf(arg0, errmsg, v, NULL,
367 NULL, NULL, NULL, NULL, NULL, NULL);
372 if (W[index]->type == TAB_EMPTY && W[index]->w == NULL) {
375 errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
376 printerrf(arg0, errmsg, v, NULL, NULL,
377 NULL, NULL, NULL, NULL, NULL);
390 wtab_t *w = str_to_wtab(arg0, handle);
399 * This function takes a widget and finds the wtab associated with it.
400 * This operation is performed infrequently, for example if the user
401 * gets a resource that is a widget. So, we're just using a linear
402 * search right now. If profiling reveals this to be too slow we'll
403 * have to introduce another hash table or something.
415 for (i = 0; i < NumW; i++) {
416 if ((W[i]->type != TAB_EMPTY) && (W[i]->w == w))
420 * If we failed to find the widget id in the
421 * internal table then this was probably a widget that
422 * was created as a side effect of another widget's creation,
423 * or perhaps was created by a user-defined builtin or something.
424 * So, we'll create a new table entry for it using set_up_w().
425 * Of course, set_up_w() needs to know the widget's parent's
426 * wtab_t, which we get by recursively calling ourself. Also,
427 * we need the widget's class.
430 wtab_t *pwtab; /* parent wtab */
431 WidgetClass wclass; /* class record */
432 classtab_t *class; /* widget's class */
434 if ((pwtab = widget_to_wtab(XtParent(w))) == NULL) {
435 errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
436 printerr("widget_to_wtab", errmsg, NULL);
442 * Again, we have to go linear searching for this
446 for (i = 0; C[i].cname != NULL; i++) {
447 if (C[i].class == wclass) {
453 errmsg = strdup(GETMESSAGE(14,4,
454 "Unable to find the widget class"));
455 printerr("widget_to_wtab", errmsg, NULL);
460 * If this class has not been initialized, we
461 * better force it to be set up by calling
464 if (class->res == NULL)
465 str_to_class("widget_to_wtab", class->cname);
466 return(set_up_w(w, pwtab, NULL, NULL, class));
479 * If there has been a destroywidget call, then one or more
480 * table entries may have been freed. We might want to make
481 * a free list for this stuff someday, but for now we do a
482 * linear search for the free slot. Most applications don't
483 * do much widget destroying anyway, so this should rarely
484 * execute and thus I'm not too dismayed by the linear search.
488 for (i = 0; i < NumW; i++) {
489 if (W[i]->type == TAB_EMPTY) {
504 W = (wtab_t **)XtRealloc((char *)W, sizeof(wtab_t *)*MaxW);
505 wentries = (wtab_t *)XtMalloc(sizeof(wtab_t)*WIDGETALLOC);
506 for (j = 0; j < WIDGETALLOC; j++)
508 W[oldmax+j] = &wentries[j];
509 wentries[j].type = TAB_EMPTY;
514 sprintf(name, "W%d", i);
525 XtResource *resource;
532 for (i = 0; fixups[i].name != NULL; i++) {
533 resource = (XtResource *)hashget(res, fixups[i].name);
535 * We could be either adding a new resource or
536 * modifying an old one.
538 if (resource == NULL)
539 resource = (XtResource *)XtMalloc(sizeof(XtResource));
541 * The only fields dtksh uses are the name, class, type and
542 * size, so that's all we attempt to fix up.
544 * NOTE: THE CLASS NAME IS REQUIRED, BECAUSE IF WE ARE ADDING
545 * A NEW RESOURCE (VERSUS REPLACING AN EXISTING ONE),
546 * THEN THE RESOURCE ENDS UP HAVING A 'NULL' CLASS
547 * NAME. SINCE DtWidgetInfo DISPLAYS THE RESOURCE CLASS
548 * NAME, THIS TIDBIT OF USEFUL INFORMATION WOULD BE
551 resource->resource_name = (String)fixups[i].name;
552 resource->resource_class = (String)fixups[i].class;
553 resource->resource_type = (String)fixups[i].type;
554 resource->resource_size = fixups[i].size;
555 hashput(res, fixups[i].name, (char *)resource);
564 classtab_t *classtab;
574 errmsg = strdup(GETMESSAGE(14,5,
575 "Usage: DtLoadWidget widgetClassName widgetClassRecordName"));
576 printerr(str_nill, errmsg, NULL);
581 if ((address = (void *)fsym(argv[2], -1)) == NULL)
583 errmsg = strdup(GETMESSAGE(14,6,
584 "Unable to locate a widget class record named '%s'"));
585 printerrf(argv[0], errmsg,
586 argv[2], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
592 classtab = (classtab_t *)XtMalloc(sizeof(classtab_t));
593 memset(classtab, '\0', sizeof(classtab_t));
594 classtab->cname = (char *)strdup(argv[1]);
595 classtab->class = ((WidgetClass *)address)[0];
596 if ((nam = hashput(Wclasses, classtab->cname, (char *)classtab)) == NULL)
598 errhdr = strdup(GetSharedMsg(DT_ERROR));
599 errmsg= strdup(GETMESSAGE(14,7,
600 "Internal hash table failure during initialization of widget class '%s'"));
601 printerrf(errhdr, errmsg, classtab->cname,
602 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
611 static XtResource *Res[1024];
619 return(strcmp(r1[0]->resource_name, r2[0]->resource_name));
626 printf("%s\n", c->cname);
633 printf("\t%-24.24s %-24.24s %s\n", res->resource_name, res->resource_class, res->resource_type);
637 sort_and_print_res( void )
640 qsort(Res, Nres, sizeof(XtResource *), (int (*)())rescompare);
641 for (i = 0; i < Nres; i++) {
642 _pr_resource_list(Res[i]);
647 gather_resource_list(
652 XtResource *res = (XtResource *)r;
657 static int Show_constraint;
668 str_to_class("DtWidgetInfo", c->cname);
670 if (Show_constraint && c->con == NULL) /* No constraint resources */
673 errmsg = strdup(GETMESSAGE(14,8, "\n%sRESOURCES FOR %s%s%s:\n"));
674 errmsg2 = strdup(Show_constraint ? GETMESSAGE(14,9, "CONSTRAINT ") :
676 printf(errmsg, errmsg2,
679 w ? w->widid : str_nill);
685 hashwalk((Hash_table_t*)(Show_constraint ? c->con : c->res), 0, (int (*)())gather_resource_list, NULL);
686 if (!Show_constraint && w && w->parent != NULL &&
687 XtIsConstraint(w->parent->w)) {
688 hashwalk((Hash_table_t *)w->parent->wclass->con, 0, (int (*)())gather_resource_list, NULL);
692 sort_and_print_res();
701 classtab_t *c = (classtab_t *)r;
703 _pr_resource(c, NULL);
712 classtab_t *class = (classtab_t *)c;
726 /* calculate a widget's name. Goes backwards through the
727 * list of parents, filling in the names backwards in the
728 * buffer, then returns a pointer to the start of the name
730 p = &buf[max]; /* that's right, buf[max] not buf[max-1] */
731 for ( ; w; w = w->parent) {
732 if (p - (len = strlen(w->wname)) < buf+3) { /* overflow! */
739 if (p + len != buf + max - 1)
752 static char * errmsg = NULL;
753 static char * realizedStr = NULL;
754 static char * managedStr = NULL;
755 static char * sensitiveStr = NULL;
756 char * realized, * managed, * sensitive;
760 errmsg = strdup(GETMESSAGE(14,13,
761 "%-15s %-6s %-6s %-18s %-6s %s\n"));
762 realizedStr = strdup(GETMESSAGE(14,10, "R"));
763 managedStr = strdup(GETMESSAGE(14,11, "M"));
764 sensitiveStr = strdup(GETMESSAGE(14,12, "S"));
767 name = getname(w, namebuf, sizeof(namebuf));
768 realized = XtIsRealized(w->w) ? realizedStr : str_nill;
769 managed = XtIsManaged(w->w) ? managedStr : str_nill;
770 sensitive = XtIsSensitive(w->w) ? sensitiveStr : str_nill;
771 sprintf(statbuf, "%s%s%s", realized, managed, sensitive);
776 w->parent ? w->parent->widid : "none",
787 errmsg = strdup(GETMESSAGE(14,14,
788 "ENV VARIABLE HANDLE PARENT CLASS STATUS NAME\n"));
794 * DtWidgetInfo -r [widget|class] print resources and their types for widgets
795 * DtWidgetInfo -R [widget|class] print constraint resources for widgets
796 * DtWidgetInfo -c [class] print info about a class
797 * DtWidgetInfo -h [handle] print widget handles [or widget name]
798 * DtWidgetInfo print summary info about all widgets
814 if (C[0].class == NULL) {
815 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
816 printerr(argv[0], errmsg, NULL);
820 if (argc == 1 || argv[1][0] != '-') {
821 /* Print long listing of each widget */
824 for (i = 0; i < NumW; i++) {
825 if (W[i]->type == TAB_EMPTY)
830 for (i = 1; i < argc; i++) {
831 if ((w = str_to_wtab(argv[0], argv[i])) != NULL)
835 } else if (argv[1][0] == '-') {
836 if ((Show_constraint = strcmp(argv[1], "-r")) == 0 ||
837 strcmp(argv[1], "-R") == 0) {
838 /* print all the resources in each widget or class */
840 hashwalk((Hash_table_t *)Wclasses, 0,
841 (int (*)())pr_resource, 0);
844 for (i = 2; i < argc; i++) {
845 if ((c = str_to_class(argv[0], argv[i])) != NULL) {
846 if (Show_constraint && c->con == NULL)
849 if (!Show_constraint && c-> res == NULL)
852 w = str_to_wtab(NULL, argv[i]);
858 } else if (strcmp(argv[1], "-c") == 0) {
860 * print all the available classes, or check if a
864 hashwalk((Hash_table_t *)Wclasses, 0, (int (*)())pr_class, 0);
866 for (i = 2; i < argc; i++) {
867 if ((c = str_to_class(argv[0], argv[i])) != NULL)
872 } else if (strcmp(argv[1], "-h") == 0) {
873 /* print active widget handles */
875 for (i = 0; i < NumW; i++) {
876 if (W[i]->type == TAB_EMPTY)
878 printf("%s\n", W[i]->widid);
881 for (i = 2; i < argc; i++) {
882 if ((w = str_to_wtab(argv[0], argv[i])) == NULL) {
886 printf("%s\n", w->wname);
890 errmsg = strdup(GetSharedMsg(DT_UNKNOWN_OPTION));
891 printerrf(argv[0], errmsg, argv[1], NULL,
892 NULL, NULL, NULL, NULL, NULL, NULL);
895 errmsg = strdup(GETMESSAGE(14,15, "\nUsage:\tDtWidgetInfo [widgetHandle]\n\tDtWidgetInfo -r <widgetHandle|className>\n\tDtWidgetInfo -R <widgetHandle|className>\n\tDtWidgetInfo -c [className]\n\tDtWidgetInfo -h [widgetHandle]"));
896 printerr(str_nill, errmsg, NULL);
906 * If the incoming environment variable is "-", then print the value out,
907 * instead of placing it into the environment.
915 if (strcmp(variable, "-") == 0)
918 env_set_var(variable, value);