Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtksh / widget.c
1 /* $XConsortium: widget.c /main/4 1995/11/01 15:57:40 rswiston $ */
2
3 /*      Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
4 /*      All Rights Reserved     */
5
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.     */
10
11 #include        "name.h"
12 #include        "shell.h"
13 #include <string.h>
14 #include <X11/Intrinsic.h>
15 #include <X11/IntrinsicP.h>
16 #include <X11/Shell.h>
17 #include <X11/StringDefs.h>
18 #include <Xm/Xm.h>
19 #include <Xm/XmStrDefs.h>
20 #include <Xm/DialogS.h>
21 #include "hash.h"
22 #include "stdio.h"
23 #define NO_AST
24 #include "dtksh.h"
25 #undef NO_AST
26 #include "xmksh.h"
27 #include "dtkcmds.h"
28 #include "xmcvt.h"
29 #include "widget.h"
30 #include "extra.h"
31 #include "xmwidgets.h"
32 #include "msgs.h"
33
34 /* values for the flags field of the W array */
35
36 #define RESOURCE_HASHSIZE       64
37 #define CLASS_HASHSIZE          32
38 #define WIDGETALLOC             16      /* Will realloc the widget array in this increment */
39
40 wtab_t **W = NULL;
41 int NumW = 0;
42 int MaxW = 0;
43 int Wtab_free = 0;      /* A count of how many table entries have been freed */
44
45
46 /* CONSTANTS */
47 char str_0123456789[] = "0123456789";
48
49 Hashtab_t *Wclasses;
50
51
52
53
54 static void fixupresources( 
55                         char *name,
56                         Hash_table_t *res,
57                         resfixup_t *fixups) ;
58 static int rescompare( 
59                         XtResource **r1,
60                         XtResource **r2) ;
61 static void _pr_class( 
62                         classtab_t *c) ;
63 static void _pr_resource_list( 
64                         XtResource *res) ;
65 static void sort_and_print_res( void ) ;
66 static void gather_resource_list( 
67                         char *name,
68                         char *r,
69                         void *notUsed) ;
70 static void _pr_resource( 
71                         classtab_t *c,
72                         wtab_t *w) ;
73 static void pr_resource( 
74                         char *name,
75                         char *r,
76                         void *notUsed) ;
77 static void pr_class( 
78                         char *name,
79                         char *c,
80                         void *notUsed) ;
81 static char * getname( 
82                         wtab_t *w,
83                         char *buf,
84                         int max) ;
85 static void pr_widinfo( 
86                         wtab_t *w) ;
87 static void pr_widheader( void ) ;
88
89
90
91 void
92 init_widgets( void )
93 {
94         register int i, n = 0;
95         char *nam;
96         wtab_t *wentries;
97         char * errmsg;
98         char * errhdr;
99
100         if (C[0].class != NULL)
101                 return;
102
103         toolkit_init_widgets();
104
105         Wclasses = hashalloc(NULL, 0);
106
107         for (i = 0; C[i].cname != NULL; i++) {
108                 if ((nam = hashput(Wclasses, C[i].cname, (char *)(&C[i]))) == NULL) 
109                 {
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);
114                          free(errhdr);
115                          free(errmsg);
116                          exit(1);
117                 }
118         }
119
120         /*
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.
124          */
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++)
128         {
129                 W[i] = &wentries[i];
130                 wentries[i].type = TAB_EMPTY;
131         }
132         MaxW = WIDGETALLOC;
133 }
134
135 /*
136  * string to widgetclass
137  */
138
139 classtab_t *
140 str_to_class(
141         char *arg0,
142         char *s )
143 {
144    register int i, j, n;
145    Widget w;
146    char *nam;
147    classtab_t *ret;
148    char * errhdr;
149    char * errmsg;
150    Cardinal numBlocks;
151    XmSecondaryResourceData * blockArray;
152
153    /*
154     * If it looks like a handle, look it up and return the
155     * class of the widget associated with the handle.
156     */
157    if (s[0] == 'W' && strspn(&s[1], str_0123456789) == strlen(&s[1])) 
158    {
159       wtab_t *w = str_to_wtab(arg0, s);
160       if (w != NULL)
161          return(w->wclass);
162    }
163
164    if ((nam = hashget(Wclasses, s)) != NULL) 
165    {
166       ret = (classtab_t *)nam;
167       if (ret->res == NULL) 
168       {
169          XtResourceList resources;
170          Cardinal numresources;
171
172          /* First reference of a given widget class
173           * Automatically causes that widget class to
174           * be initialized, it's resources read and
175           * hashed.
176           */
177          ret->res = (char *)hashalloc(NULL, 0);
178
179          /*
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
184           * available.
185           */
186          XtInitializeWidgetClass(ret->class);
187
188          XtGetResourceList(ret->class, &resources, &numresources);
189          for (i = 0; i < numresources; i++) 
190          {
191             if ((nam = (char *)hashput((Hash_table_t*)ret->res, 
192                 resources[i].resource_name, (char *)&resources[i])) == NULL) 
193             {
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);
198                free(errhdr);
199                free(errmsg);
200             } 
201          }
202
203          /* Load any of Motif's secondary resources */
204          /*
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.
213           */
214          if (ret->class == xmDialogShellWidgetClass)
215          {
216             numBlocks = XmGetSecondaryResourceData(vendorShellWidgetClass, 
217                                                    &blockArray);
218          }
219          else
220             numBlocks = XmGetSecondaryResourceData(ret->class, &blockArray);
221
222          if (numBlocks > 0)
223          {
224             for (i = 0; i < numBlocks; i++)
225             {
226                for (j = 0; j < blockArray[i]->num_resources; j++)
227                {
228                   if ((nam = (char *)hashput((Hash_table_t*)ret->res, 
229                              blockArray[i]->resources[j].resource_name, 
230                              (char *)&(blockArray[i]->resources[j]))) == NULL)
231                   {
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);
237                      free(errhdr);
238                      free(errmsg);
239                   } 
240                }
241                /*
242                 * We can't free up the actual array of resources, since we
243                 * hashed a reference to the entries into our resource hash
244                 * table:
245                 * XtFree((char *)blockArray[i]->resources); 
246                 */
247                XtFree((char *)blockArray[i]);
248             }
249          }
250
251          /* Perform any special resource fixing up */
252          fixupresources(s, (Hash_table_t *)ret->res, 
253                         (resfixup_t *)&ret->resfix[0]);
254
255          /*
256           * Get constraint resources, if there are any
257           */
258          XtGetConstraintResourceList(ret->class, &resources, &numresources);
259          if (resources != NULL) 
260          {
261             ret->con = (char *)hashalloc(NULL, 0);
262             for (i = 0; i < numresources; i++) 
263             {
264                if ((nam = (char *)hashput((Hash_table_t*)ret->con, 
265                     resources[i].resource_name, &resources[i])) == NULL) 
266                {
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);
271                   free(errhdr);
272                   free(errmsg);
273                } 
274             }
275             fixupresources(s, (Hash_table_t *)ret->con, 
276                            (resfixup_t *)&ret->confix[0]);
277          } 
278          else 
279             ret->con = NULL;
280       }
281       return(ret);
282    }
283
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);
287    free(errmsg);
288    return(NULL);
289 }
290
291 Widget
292 DtkshNameToWidget(
293         String s )
294 {
295         Widget w;
296         char *p;
297         int len;
298         char * errhdr;
299         char * errmsg;
300
301         if (s == NULL || *s == '\0')
302                 return(NULL);
303
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);
308                 free(errhdr);
309                 free(errmsg);
310                 return(NULL);
311         }
312         len = strlen(W[0]->wname);
313         if (strncmp(s, W[0]->wname, len) == 0) {
314                 if (s[len] == '\0')
315                         return(Toplevel);
316                 if (s[len] == '.')
317                         return(XtNameToWidget(Toplevel, &s[len+1]));
318         }
319         return(NULL);
320 }
321
322 /*
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.
326  *
327  * If the name is not of the correct form, we use XtNameToWidget
328  * to try to convert the name to a widget id.
329  */
330
331 wtab_t *
332 str_to_wtab(
333         char *arg0,
334         char *v )
335 {
336         int index, len;
337         char * errmsg;
338
339         if (v == NULL || strcmp(v, "NULL") == 0)
340                 return(NULL);
341
342         if (v[0] != 'W' || (len = strlen(v)) < 2 ||
343                 strspn(&v[1], str_0123456789) != len-1) {
344                 Widget wid;
345
346                 if ((wid = DtkshNameToWidget(v)) == NULL) {
347                         if (arg0)
348                         {
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,
353                                           NULL, NULL);
354                                 free(errmsg);
355                         }
356                         return(NULL);
357                 }
358
359                 return(widget_to_wtab(wid));
360         }
361         index = atoi(&v[1]);
362         if (index < 0 || index >= NumW) {
363                 if (arg0)
364                 {
365                         errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
366                         printerrf(arg0, errmsg, v, NULL,
367                                   NULL, NULL, NULL, NULL, NULL, NULL);
368                         free(errmsg);
369                 }
370                 return(NULL);
371         }
372         if (W[index]->type == TAB_EMPTY && W[index]->w == NULL) {
373                 if (arg0)
374                 {
375                         errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
376                         printerrf(arg0, errmsg, v, NULL, NULL,
377                                   NULL, NULL, NULL, NULL, NULL);
378                         free(errmsg);
379                 }
380                 return(NULL);
381         }
382         return(W[index]);
383 }
384
385 Widget
386 handle_to_widget(
387         char *arg0,
388         char *handle )
389 {
390         wtab_t *w = str_to_wtab(arg0, handle);
391
392         if (w)
393                 return(w->w);
394         else
395                 return(NULL);
396 }
397
398 /*
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.
404  */
405
406 wtab_t *
407 widget_to_wtab(
408         Widget w )
409 {
410         register int i;
411         char * errmsg;
412
413         if (w == NULL)
414                 return(NULL);
415         for (i = 0; i < NumW; i++) {
416                 if ((W[i]->type != TAB_EMPTY) && (W[i]->w == w))
417                         return(W[i]);
418         }
419         /*
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.
428          */
429         {
430                 wtab_t *pwtab;          /* parent wtab */
431                 WidgetClass wclass;     /* class record */
432                 classtab_t *class;      /* widget's class */
433
434                 if ((pwtab = widget_to_wtab(XtParent(w))) == NULL) {
435                         errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
436                         printerr("widget_to_wtab", errmsg, NULL);
437                         free(errmsg);
438                         return(NULL);
439                 }
440                 wclass = XtClass(w);
441                 /*
442                  * Again, we have to go linear searching for this
443                  * right now.
444                  */
445                 class = NULL;
446                 for (i = 0; C[i].cname != NULL; i++) {
447                         if (C[i].class == wclass) {
448                                 class = &C[i];
449                                 break;
450                         }
451                 }
452                 if (class == NULL) {
453                         errmsg = strdup(GETMESSAGE(14,4, 
454                               "Unable to find the widget class"));
455                         printerr("widget_to_wtab", errmsg, NULL);
456                         free(errmsg);
457                         return(NULL);
458                 }
459                 /*
460                  * If this class has not been initialized, we
461                  * better force it to be set up by calling
462                  * str_to_class();
463                  */
464                 if (class->res == NULL)
465                         str_to_class("widget_to_wtab", class->cname);
466                 return(set_up_w(w, pwtab, NULL, NULL, class));
467         }
468 }
469
470 void
471 get_new_wtab(
472         wtab_t **w,
473         char *name )
474
475 {
476         register int i;
477
478         /*
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.
485          */
486         i = NumW;
487         if (Wtab_free > 0) {
488                 for (i = 0; i < NumW; i++) {
489                         if (W[i]->type == TAB_EMPTY) {
490                                 Wtab_free--;
491                                 break;
492                         }
493                 }
494         }
495         if (i == NumW) {
496                 if (NumW < MaxW) {
497                         i = NumW++;
498                 } else {
499                         register int j;
500                         int oldmax = MaxW;
501                         wtab_t *wentries;
502
503                         MaxW += WIDGETALLOC;
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++)
507                         {
508                                 W[oldmax+j] = &wentries[j];
509                                 wentries[j].type = TAB_EMPTY;
510                         }
511                         i = NumW++;
512                 }
513         }
514         sprintf(name, "W%d", i);
515         *w = W[i];
516         return;
517 }
518
519 static void
520 fixupresources(
521         char *name,
522         Hash_table_t *res,
523         resfixup_t *fixups )
524 {
525         XtResource *resource;
526         register int i;
527         char *nam;
528
529         if (fixups == NULL)
530                 return;
531
532         for (i = 0; fixups[i].name != NULL; i++) {
533                 resource = (XtResource *)hashget(res, fixups[i].name);
534                 /*
535                  * We could be either adding a new resource or
536                  * modifying an old one.
537                  */
538                 if (resource == NULL)
539                         resource = (XtResource *)XtMalloc(sizeof(XtResource));
540                 /*
541                  * The only fields dtksh uses are the name, class, type and
542                  * size, so that's all we attempt to fix up.
543                  *
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 
549                  *       MISSING.
550                  */
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);
556         }
557 }
558
559 int
560 do_DtLoadWidget(
561         int argc,
562         char *argv[] )
563 {
564    classtab_t *classtab;
565    void *address;
566    char *nam;
567    char * errhdr;
568    char * errmsg;
569
570    init_widgets();
571
572    if (argc != 3) 
573    {
574       errmsg = strdup(GETMESSAGE(14,5, 
575                "Usage: DtLoadWidget widgetClassName widgetClassRecordName"));
576       printerr(str_nill, errmsg, NULL);
577       free(errmsg);
578       return(1);
579    }
580
581    if ((address = (void *)fsym(argv[2], -1)) == NULL) 
582    {
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);
587       free(errmsg);
588       return(1);
589    } 
590    else 
591    {
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)
597       {
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);
603          free(errhdr);
604          free(errmsg);
605          return(1);
606       }
607    }
608    return(0);
609 }
610
611 static XtResource *Res[1024];
612 static int Nres;
613
614 static int
615 rescompare(
616         XtResource **r1,
617         XtResource **r2 )
618 {
619         return(strcmp(r1[0]->resource_name, r2[0]->resource_name));
620 }
621
622 static void
623 _pr_class(
624         classtab_t *c )
625 {
626         printf("%s\n", c->cname);
627 }
628
629 static void
630 _pr_resource_list(
631         XtResource *res )
632 {
633         printf("\t%-24.24s %-24.24s %s\n", res->resource_name, res->resource_class, res->resource_type);
634 }
635
636 static void
637 sort_and_print_res( void )
638 {
639         register int i;
640         qsort(Res, Nres, sizeof(XtResource *), (int (*)())rescompare);
641         for (i = 0; i < Nres; i++) {
642                 _pr_resource_list(Res[i]);
643         }
644 }
645
646 static void
647 gather_resource_list(
648         char *name,
649         char *r,
650         void *notUsed )
651 {
652         XtResource *res = (XtResource *)r;
653
654         Res[Nres++] = res;
655 }
656
657 static int Show_constraint;
658
659 static void
660 _pr_resource(
661         classtab_t *c,
662         wtab_t *w )
663 {
664         char * errmsg;
665         char * errmsg2;
666
667         if (c->res == NULL)
668                 str_to_class("DtWidgetInfo", c->cname);
669
670         if (Show_constraint && c->con == NULL)  /* No constraint resources */
671                 return;
672
673         errmsg = strdup(GETMESSAGE(14,8, "\n%sRESOURCES FOR %s%s%s:\n"));
674         errmsg2 = strdup(Show_constraint ? GETMESSAGE(14,9, "CONSTRAINT ") : 
675                          str_nill);
676         printf(errmsg, errmsg2,
677                 c->cname,
678                 w ? " " : str_nill, 
679                 w ? w->widid : str_nill);
680         free(errmsg);
681         free(errmsg2);
682
683         Nres = 0;
684
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);
689
690         }
691
692         sort_and_print_res();
693 }
694
695 static void
696 pr_resource(
697         char *name,
698         char *r,
699         void *notUsed )
700 {
701         classtab_t *c = (classtab_t *)r;
702
703         _pr_resource(c, NULL);
704 }
705
706 static void
707 pr_class(
708         char *name,
709         char *c,
710         void *notUsed )
711 {
712         classtab_t *class = (classtab_t *)c;
713
714         _pr_class(class);
715 }
716
717 static char *
718 getname(
719         wtab_t *w,
720         char *buf,
721         int max )
722 {
723         char *p;
724         int len;
725
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
729          */
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! */
733                         p--;
734                         *p = '*';
735                         return(p);
736                 }
737                 p -= len+1;
738                 strcpy(p, w->wname);
739                 if (p + len != buf + max - 1)
740                         p[len] = '.';
741         }
742         return(p);
743 }
744
745 static void
746 pr_widinfo(
747         wtab_t *w )
748 {
749         char namebuf[256];
750         char *name;
751         char statbuf[8];
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;
757
758         if (errmsg == NULL)
759         {
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"));
765         }
766
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);
772
773         printf(errmsg,
774                 w->envar,
775                 w->widid, 
776                 w->parent ? w->parent->widid : "none", 
777                 w->wclass->cname,
778                 statbuf,
779                 name);
780 }
781
782 static void
783 pr_widheader( void )
784 {
785    char * errmsg;
786
787    errmsg = strdup(GETMESSAGE(14,14, 
788             "ENV VARIABLE    HANDLE PARENT CLASS              STATUS NAME\n"));
789    printf(errmsg);
790    free(errmsg);
791 }
792
793 /*
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 
799  */
800
801
802 int
803 do_DtWidgetInfo(
804         int argc,
805         char *argv[] )
806 {
807         register int i, j;
808         char buf[1024];
809         wtab_t *w;
810         classtab_t *c;
811         int errs = 0;
812         char * errmsg;
813
814         if (C[0].class == NULL) {
815                 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
816                 printerr(argv[0], errmsg, NULL);
817                 free(errmsg);
818                 return(1);
819         }
820         if (argc == 1 || argv[1][0] != '-') {
821                 /* Print long listing of each widget */
822                 pr_widheader();
823                 if (argc == 1) {
824                         for (i = 0; i < NumW; i++) {
825                                 if (W[i]->type == TAB_EMPTY)
826                                         continue;
827                                 pr_widinfo(W[i]);
828                         }
829                 } else {
830                         for (i = 1; i < argc; i++) {
831                                 if ((w = str_to_wtab(argv[0], argv[i])) != NULL)
832                                         pr_widinfo(w);
833                         }
834                 }
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 */
839                         if (argc == 2) {
840                                 hashwalk((Hash_table_t *)Wclasses, 0, 
841                                            (int (*)())pr_resource, 0);
842                                 return(0);
843                         } else {
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)
847                                                         return(0);
848
849                                                 if (!Show_constraint && c-> res == NULL)
850                                                         return(0);
851
852                                                 w = str_to_wtab(NULL, argv[i]);
853                                                 _pr_resource(c, w);
854                                         }
855                                 }
856                         }
857                         return(0);
858                 } else if (strcmp(argv[1], "-c") == 0) {
859                         /*
860                          * print all the available classes, or check if a
861                          * class is available
862                          */
863                         if (argc == 2) {
864                                 hashwalk((Hash_table_t *)Wclasses, 0, (int (*)())pr_class, 0);
865                         } else {
866                                 for (i = 2; i < argc; i++) {
867                                         if ((c = str_to_class(argv[0], argv[i])) != NULL)
868                                                 _pr_class(c);
869                                 }
870                         }
871                         return(0);
872                 } else if (strcmp(argv[1], "-h") == 0) {
873                         /* print active widget handles */
874                         if (argc == 2) {
875                                 for (i = 0; i < NumW; i++) {
876                                         if (W[i]->type == TAB_EMPTY)
877                                                 continue;
878                                         printf("%s\n", W[i]->widid);
879                                 }
880                         } else {
881                                 for (i = 2; i < argc; i++) {
882                                         if ((w = str_to_wtab(argv[0], argv[i])) == NULL) {
883                                                 errs++;
884                                                 continue;
885                                         }
886                                         printf("%s\n", w->wname);
887                                 }
888                         }
889                 } else {
890                         errmsg = strdup(GetSharedMsg(DT_UNKNOWN_OPTION));
891                         printerrf(argv[0], errmsg, argv[1], NULL,
892                                   NULL, NULL, NULL, NULL, NULL, NULL);
893                         free(errmsg);
894
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);
897                         free(errmsg);
898                         return(255);
899                 }
900         }
901         return(errs);
902 }
903
904
905 /*
906  * If the incoming environment variable is "-", then print the value out,
907  * instead of placing it into the environment.
908  */
909
910 void
911 alt_env_set_var(
912         char *variable,
913         char *value )
914 {
915    if (strcmp(variable, "-") == 0)
916       puts(value);
917    else
918       env_set_var(variable, value);
919 }