2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: widget.c /main/4 1995/11/01 15:57:40 rswiston $ */
25 /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
26 /* All Rights Reserved */
28 /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
29 /* UNIX System Laboratories, Inc. */
30 /* The copyright notice above does not evidence any */
31 /* actual or intended publication of such source code. */
36 #include <X11/Intrinsic.h>
37 #include <X11/IntrinsicP.h>
38 #include <X11/Shell.h>
39 #include <X11/StringDefs.h>
41 #include <Xm/XmStrDefs.h>
42 #include <Xm/DialogS.h>
53 #include "xmwidgets.h"
56 /* values for the flags field of the W array */
58 #define RESOURCE_HASHSIZE 64
59 #define CLASS_HASHSIZE 32
60 #define WIDGETALLOC 16 /* Will realloc the widget array in this increment */
65 int Wtab_free = 0; /* A count of how many table entries have been freed */
69 char str_0123456789[] = "0123456789";
76 static void fixupresources(
80 static int rescompare(
83 static void _pr_class(
85 static void _pr_resource_list(
87 static void sort_and_print_res( void ) ;
88 static void gather_resource_list(
92 static void _pr_resource(
95 static void pr_resource(
103 static char * getname(
107 static void pr_widinfo(
109 static void pr_widheader( void ) ;
116 register int i, n = 0;
122 if (C[0].class != NULL)
125 toolkit_init_widgets();
127 Wclasses = hashalloc(NULL, 0);
129 for (i = 0; C[i].cname != NULL; i++) {
130 if ((nam = hashput(Wclasses, C[i].cname, (char *)(&C[i]))) == NULL)
132 errhdr = strdup(GetSharedMsg(DT_ERROR));
133 errmsg = strdup(GETMESSAGE(14,1,
134 "Internal hash table failure during widget class initialization; exiting"));
135 printerr(errhdr, errmsg, NULL);
143 * The array of widget records starts out big enough to
144 * hold WIDGETALLOC widgets, and will grow in increments
145 * of WIDGETALLOC as it overflows.
147 W = (wtab_t **)XtMalloc(WIDGETALLOC*sizeof(wtab_t *));
148 wentries = (wtab_t *)XtCalloc(WIDGETALLOC, sizeof(wtab_t));
149 for (i = 0; i < WIDGETALLOC; i++)
152 wentries[i].type = TAB_EMPTY;
158 * string to widgetclass
166 register int i, j, n;
173 XmSecondaryResourceData * blockArray;
176 * If it looks like a handle, look it up and return the
177 * class of the widget associated with the handle.
179 if (s[0] == 'W' && strspn(&s[1], str_0123456789) == strlen(&s[1]))
181 wtab_t *w = str_to_wtab(arg0, s);
186 if ((nam = hashget(Wclasses, s)) != NULL)
188 ret = (classtab_t *)nam;
189 if (ret->res == NULL)
191 XtResourceList resources;
192 Cardinal numresources;
194 /* First reference of a given widget class
195 * Automatically causes that widget class to
196 * be initialized, it's resources read and
199 ret->res = (char *)hashalloc(NULL, 0);
202 * Have to force the class init
203 * of this widget to execute, else we won't
204 * get a complete list of resources, and any
205 * converters added by this widget won't be
208 XtInitializeWidgetClass(ret->class);
210 XtGetResourceList(ret->class, &resources, &numresources);
211 for (i = 0; i < numresources; i++)
213 if ((nam = (char *)hashput((Hash_table_t*)ret->res,
214 resources[i].resource_name, (char *)&resources[i])) == NULL)
216 errhdr = strdup(GetSharedMsg(DT_ERROR));
217 errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
218 printerrf(errhdr, errmsg, resources[i].resource_name,
219 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
225 /* Load any of Motif's secondary resources */
227 * The following is a special hack to work around a Motif bug
228 * (which has been reported). DialogShell is a grandchild class of
229 * VendorShell, which defines secondary resources. DialogShell is
230 * also a child class of TransientShell. Secondary resource
231 * information is contained within extension records, which the
232 * TransientShell class knows nothing about, thus preventing
233 * XmGetSecondaryResourceData from getting any secondary resources
234 * further up the inheritance chain.
236 if (ret->class == xmDialogShellWidgetClass)
238 numBlocks = XmGetSecondaryResourceData(vendorShellWidgetClass,
242 numBlocks = XmGetSecondaryResourceData(ret->class, &blockArray);
246 for (i = 0; i < numBlocks; i++)
248 for (j = 0; j < blockArray[i]->num_resources; j++)
250 if ((nam = (char *)hashput((Hash_table_t*)ret->res,
251 blockArray[i]->resources[j].resource_name,
252 (char *)&(blockArray[i]->resources[j]))) == NULL)
254 errhdr = strdup(GetSharedMsg(DT_ERROR));
255 errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
256 printerrf(errhdr, errmsg,
257 blockArray[i]->resources[j].resource_name,
258 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
264 * We can't free up the actual array of resources, since we
265 * hashed a reference to the entries into our resource hash
267 * XtFree((char *)blockArray[i]->resources);
269 XtFree((char *)blockArray[i]);
273 /* Perform any special resource fixing up */
274 fixupresources(s, (Hash_table_t *)ret->res,
275 (resfixup_t *)&ret->resfix[0]);
278 * Get constraint resources, if there are any
280 XtGetConstraintResourceList(ret->class, &resources, &numresources);
281 if (resources != NULL)
283 ret->con = (char *)hashalloc(NULL, 0);
284 for (i = 0; i < numresources; i++)
286 if ((nam = (char *)hashput((Hash_table_t*)ret->con,
287 resources[i].resource_name, &resources[i])) == NULL)
289 errhdr =strdup(GetSharedMsg(DT_ERROR));
290 errmsg=strdup(GetSharedMsg(DT_HASHING_FAILURE));
291 printerrf(errhdr, errmsg, resources[i].resource_name,
292 ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
297 fixupresources(s, (Hash_table_t *)ret->con,
298 (resfixup_t *)&ret->confix[0]);
306 errmsg = strdup(GETMESSAGE(14,2,
307 "Could not find a widget class named '%s'"));
308 printerrf(arg0, errmsg, s, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
323 if (s == NULL || *s == '\0')
326 if (W == NULL || W[0] == NULL) {
327 errhdr = strdup(GetSharedMsg(DT_WARNING));
328 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
329 printerr(errhdr, errmsg, NULL);
334 len = strlen(W[0]->wname);
335 if (strncmp(s, W[0]->wname, len) == 0) {
339 return(XtNameToWidget(Toplevel, &s[len+1]));
345 * Take a character string and translate it into a wtab_t.
346 * The string should be of the form: W<num>. The <num> must
347 * point to a valid index in the W array.
349 * If the name is not of the correct form, we use XtNameToWidget
350 * to try to convert the name to a widget id.
361 if (v == NULL || strcmp(v, "NULL") == 0)
364 if (v[0] != 'W' || (len = strlen(v)) < 2 ||
365 strspn(&v[1], str_0123456789) != len-1) {
368 if ((wid = DtkshNameToWidget(v)) == NULL) {
371 errmsg = strdup(GETMESSAGE(14,3,
372 "The identifier '%s' is not a valid widget handle"));
373 printerrf(arg0, errmsg, v,
374 NULL, NULL, NULL, NULL, NULL,
381 return(widget_to_wtab(wid));
384 if (index < 0 || index >= NumW) {
387 errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
388 printerrf(arg0, errmsg, v, NULL,
389 NULL, NULL, NULL, NULL, NULL, NULL);
394 if (W[index]->type == TAB_EMPTY && W[index]->w == NULL) {
397 errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
398 printerrf(arg0, errmsg, v, NULL, NULL,
399 NULL, NULL, NULL, NULL, NULL);
412 wtab_t *w = str_to_wtab(arg0, handle);
421 * This function takes a widget and finds the wtab associated with it.
422 * This operation is performed infrequently, for example if the user
423 * gets a resource that is a widget. So, we're just using a linear
424 * search right now. If profiling reveals this to be too slow we'll
425 * have to introduce another hash table or something.
437 for (i = 0; i < NumW; i++) {
438 if ((W[i]->type != TAB_EMPTY) && (W[i]->w == w))
442 * If we failed to find the widget id in the
443 * internal table then this was probably a widget that
444 * was created as a side effect of another widget's creation,
445 * or perhaps was created by a user-defined builtin or something.
446 * So, we'll create a new table entry for it using set_up_w().
447 * Of course, set_up_w() needs to know the widget's parent's
448 * wtab_t, which we get by recursively calling ourself. Also,
449 * we need the widget's class.
452 wtab_t *pwtab; /* parent wtab */
453 WidgetClass wclass; /* class record */
454 classtab_t *class; /* widget's class */
456 if ((pwtab = widget_to_wtab(XtParent(w))) == NULL) {
457 errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
458 printerr("widget_to_wtab", errmsg, NULL);
464 * Again, we have to go linear searching for this
468 for (i = 0; C[i].cname != NULL; i++) {
469 if (C[i].class == wclass) {
475 errmsg = strdup(GETMESSAGE(14,4,
476 "Unable to find the widget class"));
477 printerr("widget_to_wtab", errmsg, NULL);
482 * If this class has not been initialized, we
483 * better force it to be set up by calling
486 if (class->res == NULL)
487 str_to_class("widget_to_wtab", class->cname);
488 return(set_up_w(w, pwtab, NULL, NULL, class));
501 * If there has been a destroywidget call, then one or more
502 * table entries may have been freed. We might want to make
503 * a free list for this stuff someday, but for now we do a
504 * linear search for the free slot. Most applications don't
505 * do much widget destroying anyway, so this should rarely
506 * execute and thus I'm not too dismayed by the linear search.
510 for (i = 0; i < NumW; i++) {
511 if (W[i]->type == TAB_EMPTY) {
526 W = (wtab_t **)XtRealloc((char *)W, sizeof(wtab_t *)*MaxW);
527 wentries = (wtab_t *)XtMalloc(sizeof(wtab_t)*WIDGETALLOC);
528 for (j = 0; j < WIDGETALLOC; j++)
530 W[oldmax+j] = &wentries[j];
531 wentries[j].type = TAB_EMPTY;
536 sprintf(name, "W%d", i);
547 XtResource *resource;
554 for (i = 0; fixups[i].name != NULL; i++) {
555 resource = (XtResource *)hashget(res, fixups[i].name);
557 * We could be either adding a new resource or
558 * modifying an old one.
560 if (resource == NULL)
561 resource = (XtResource *)XtMalloc(sizeof(XtResource));
563 * The only fields dtksh uses are the name, class, type and
564 * size, so that's all we attempt to fix up.
566 * NOTE: THE CLASS NAME IS REQUIRED, BECAUSE IF WE ARE ADDING
567 * A NEW RESOURCE (VERSUS REPLACING AN EXISTING ONE),
568 * THEN THE RESOURCE ENDS UP HAVING A 'NULL' CLASS
569 * NAME. SINCE DtWidgetInfo DISPLAYS THE RESOURCE CLASS
570 * NAME, THIS TIDBIT OF USEFUL INFORMATION WOULD BE
573 resource->resource_name = (String)fixups[i].name;
574 resource->resource_class = (String)fixups[i].class;
575 resource->resource_type = (String)fixups[i].type;
576 resource->resource_size = fixups[i].size;
577 hashput(res, fixups[i].name, (char *)resource);
586 classtab_t *classtab;
596 errmsg = strdup(GETMESSAGE(14,5,
597 "Usage: DtLoadWidget widgetClassName widgetClassRecordName"));
598 printerr(str_nill, errmsg, NULL);
603 if ((address = (void *)fsym(argv[2], -1)) == NULL)
605 errmsg = strdup(GETMESSAGE(14,6,
606 "Unable to locate a widget class record named '%s'"));
607 printerrf(argv[0], errmsg,
608 argv[2], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
614 classtab = (classtab_t *)XtMalloc(sizeof(classtab_t));
615 memset(classtab, '\0', sizeof(classtab_t));
616 classtab->cname = (char *)strdup(argv[1]);
617 classtab->class = ((WidgetClass *)address)[0];
618 if ((nam = hashput(Wclasses, classtab->cname, (char *)classtab)) == NULL)
620 errhdr = strdup(GetSharedMsg(DT_ERROR));
621 errmsg= strdup(GETMESSAGE(14,7,
622 "Internal hash table failure during initialization of widget class '%s'"));
623 printerrf(errhdr, errmsg, classtab->cname,
624 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
633 static XtResource *Res[1024];
641 return(strcmp(r1[0]->resource_name, r2[0]->resource_name));
648 printf("%s\n", c->cname);
655 printf("\t%-24.24s %-24.24s %s\n", res->resource_name, res->resource_class, res->resource_type);
659 sort_and_print_res( void )
662 qsort(Res, Nres, sizeof(XtResource *), (int (*)())rescompare);
663 for (i = 0; i < Nres; i++) {
664 _pr_resource_list(Res[i]);
669 gather_resource_list(
674 XtResource *res = (XtResource *)r;
679 static int Show_constraint;
690 str_to_class("DtWidgetInfo", c->cname);
692 if (Show_constraint && c->con == NULL) /* No constraint resources */
695 errmsg = strdup(GETMESSAGE(14,8, "\n%sRESOURCES FOR %s%s%s:\n"));
696 errmsg2 = strdup(Show_constraint ? GETMESSAGE(14,9, "CONSTRAINT ") :
698 printf(errmsg, errmsg2,
701 w ? w->widid : str_nill);
707 hashwalk((Hash_table_t*)(Show_constraint ? c->con : c->res), 0, (int (*)())gather_resource_list, NULL);
708 if (!Show_constraint && w && w->parent != NULL &&
709 XtIsConstraint(w->parent->w)) {
710 hashwalk((Hash_table_t *)w->parent->wclass->con, 0, (int (*)())gather_resource_list, NULL);
714 sort_and_print_res();
723 classtab_t *c = (classtab_t *)r;
725 _pr_resource(c, NULL);
734 classtab_t *class = (classtab_t *)c;
748 /* calculate a widget's name. Goes backwards through the
749 * list of parents, filling in the names backwards in the
750 * buffer, then returns a pointer to the start of the name
752 p = &buf[max]; /* that's right, buf[max] not buf[max-1] */
753 for ( ; w; w = w->parent) {
754 if (p - (len = strlen(w->wname)) < buf+3) { /* overflow! */
761 if (p + len != buf + max - 1)
774 static char * errmsg = NULL;
775 static char * realizedStr = NULL;
776 static char * managedStr = NULL;
777 static char * sensitiveStr = NULL;
778 char * realized, * managed, * sensitive;
782 errmsg = strdup(GETMESSAGE(14,13,
783 "%-15s %-6s %-6s %-18s %-6s %s\n"));
784 realizedStr = strdup(GETMESSAGE(14,10, "R"));
785 managedStr = strdup(GETMESSAGE(14,11, "M"));
786 sensitiveStr = strdup(GETMESSAGE(14,12, "S"));
789 name = getname(w, namebuf, sizeof(namebuf));
790 realized = XtIsRealized(w->w) ? realizedStr : str_nill;
791 managed = XtIsManaged(w->w) ? managedStr : str_nill;
792 sensitive = XtIsSensitive(w->w) ? sensitiveStr : str_nill;
793 sprintf(statbuf, "%s%s%s", realized, managed, sensitive);
798 w->parent ? w->parent->widid : "none",
809 errmsg = strdup(GETMESSAGE(14,14,
810 "ENV VARIABLE HANDLE PARENT CLASS STATUS NAME\n"));
816 * DtWidgetInfo -r [widget|class] print resources and their types for widgets
817 * DtWidgetInfo -R [widget|class] print constraint resources for widgets
818 * DtWidgetInfo -c [class] print info about a class
819 * DtWidgetInfo -h [handle] print widget handles [or widget name]
820 * DtWidgetInfo print summary info about all widgets
836 if (C[0].class == NULL) {
837 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
838 printerr(argv[0], errmsg, NULL);
842 if (argc == 1 || argv[1][0] != '-') {
843 /* Print long listing of each widget */
846 for (i = 0; i < NumW; i++) {
847 if (W[i]->type == TAB_EMPTY)
852 for (i = 1; i < argc; i++) {
853 if ((w = str_to_wtab(argv[0], argv[i])) != NULL)
857 } else if (argv[1][0] == '-') {
858 if ((Show_constraint = strcmp(argv[1], "-r")) == 0 ||
859 strcmp(argv[1], "-R") == 0) {
860 /* print all the resources in each widget or class */
862 hashwalk((Hash_table_t *)Wclasses, 0,
863 (int (*)())pr_resource, 0);
866 for (i = 2; i < argc; i++) {
867 if ((c = str_to_class(argv[0], argv[i])) != NULL) {
868 if (Show_constraint && c->con == NULL)
871 if (!Show_constraint && c-> res == NULL)
874 w = str_to_wtab(NULL, argv[i]);
880 } else if (strcmp(argv[1], "-c") == 0) {
882 * print all the available classes, or check if a
886 hashwalk((Hash_table_t *)Wclasses, 0, (int (*)())pr_class, 0);
888 for (i = 2; i < argc; i++) {
889 if ((c = str_to_class(argv[0], argv[i])) != NULL)
894 } else if (strcmp(argv[1], "-h") == 0) {
895 /* print active widget handles */
897 for (i = 0; i < NumW; i++) {
898 if (W[i]->type == TAB_EMPTY)
900 printf("%s\n", W[i]->widid);
903 for (i = 2; i < argc; i++) {
904 if ((w = str_to_wtab(argv[0], argv[i])) == NULL) {
908 printf("%s\n", w->wname);
912 errmsg = strdup(GetSharedMsg(DT_UNKNOWN_OPTION));
913 printerrf(argv[0], errmsg, argv[1], NULL,
914 NULL, NULL, NULL, NULL, NULL, NULL);
917 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]"));
918 printerr(str_nill, errmsg, NULL);
928 * If the incoming environment variable is "-", then print the value out,
929 * instead of placing it into the environment.
937 if (strcmp(variable, "-") == 0)
940 env_set_var(variable, value);