Link with C++ linker
[oweals/cde.git] / cde / programs / dtksh / widget.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* $XConsortium: widget.c /main/4 1995/11/01 15:57:40 rswiston $ */
24
25 /*      Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
26 /*      All Rights Reserved     */
27
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.     */
32
33 #include        "name.h"
34 #include        "shell.h"
35 #include <string.h>
36 #include <X11/Intrinsic.h>
37 #include <X11/IntrinsicP.h>
38 #include <X11/Shell.h>
39 #include <X11/StringDefs.h>
40 #include <Xm/Xm.h>
41 #include <Xm/XmStrDefs.h>
42 #include <Xm/DialogS.h>
43 #include "hash.h"
44 #include "stdio.h"
45 #define NO_AST
46 #include "dtksh.h"
47 #undef NO_AST
48 #include "xmksh.h"
49 #include "dtkcmds.h"
50 #include "xmcvt.h"
51 #include "widget.h"
52 #include "extra.h"
53 #include "xmwidgets.h"
54 #include "msgs.h"
55
56 /* values for the flags field of the W array */
57
58 #define RESOURCE_HASHSIZE       64
59 #define CLASS_HASHSIZE          32
60 #define WIDGETALLOC             16      /* Will realloc the widget array in this increment */
61
62 wtab_t **W = NULL;
63 int NumW = 0;
64 int MaxW = 0;
65 int Wtab_free = 0;      /* A count of how many table entries have been freed */
66
67
68 /* CONSTANTS */
69 char str_0123456789[] = "0123456789";
70
71 Hashtab_t *Wclasses;
72
73
74
75
76 static void fixupresources( 
77                         char *name,
78                         Hash_table_t *res,
79                         resfixup_t *fixups) ;
80 static int rescompare( 
81                         XtResource **r1,
82                         XtResource **r2) ;
83 static void _pr_class( 
84                         classtab_t *c) ;
85 static void _pr_resource_list( 
86                         XtResource *res) ;
87 static void sort_and_print_res( void ) ;
88 static void gather_resource_list( 
89                         char *name,
90                         char *r,
91                         void *notUsed) ;
92 static void _pr_resource( 
93                         classtab_t *c,
94                         wtab_t *w) ;
95 static void pr_resource( 
96                         char *name,
97                         char *r,
98                         void *notUsed) ;
99 static void pr_class( 
100                         char *name,
101                         char *c,
102                         void *notUsed) ;
103 static char * getname( 
104                         wtab_t *w,
105                         char *buf,
106                         int max) ;
107 static void pr_widinfo( 
108                         wtab_t *w) ;
109 static void pr_widheader( void ) ;
110
111
112
113 void
114 init_widgets( void )
115 {
116         register int i, n = 0;
117         char *nam;
118         wtab_t *wentries;
119         char * errmsg;
120         char * errhdr;
121
122         if (C[0].class != NULL)
123                 return;
124
125         toolkit_init_widgets();
126
127         Wclasses = hashalloc(NULL, 0);
128
129         for (i = 0; C[i].cname != NULL; i++) {
130                 if ((nam = hashput(Wclasses, C[i].cname, (char *)(&C[i]))) == NULL) 
131                 {
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);
136                          free(errhdr);
137                          free(errmsg);
138                          exit(1);
139                 }
140         }
141
142         /*
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.
146          */
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++)
150         {
151                 W[i] = &wentries[i];
152                 wentries[i].type = TAB_EMPTY;
153         }
154         MaxW = WIDGETALLOC;
155 }
156
157 /*
158  * string to widgetclass
159  */
160
161 classtab_t *
162 str_to_class(
163         char *arg0,
164         char *s )
165 {
166    register int i, j, n;
167    Widget w;
168    char *nam;
169    classtab_t *ret;
170    char * errhdr;
171    char * errmsg;
172    Cardinal numBlocks;
173    XmSecondaryResourceData * blockArray;
174
175    /*
176     * If it looks like a handle, look it up and return the
177     * class of the widget associated with the handle.
178     */
179    if (s[0] == 'W' && strspn(&s[1], str_0123456789) == strlen(&s[1])) 
180    {
181       wtab_t *w = str_to_wtab(arg0, s);
182       if (w != NULL)
183          return(w->wclass);
184    }
185
186    if ((nam = hashget(Wclasses, s)) != NULL) 
187    {
188       ret = (classtab_t *)nam;
189       if (ret->res == NULL) 
190       {
191          XtResourceList resources;
192          Cardinal numresources;
193
194          /* First reference of a given widget class
195           * Automatically causes that widget class to
196           * be initialized, it's resources read and
197           * hashed.
198           */
199          ret->res = (char *)hashalloc(NULL, 0);
200
201          /*
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
206           * available.
207           */
208          XtInitializeWidgetClass(ret->class);
209
210          XtGetResourceList(ret->class, &resources, &numresources);
211          for (i = 0; i < numresources; i++) 
212          {
213             if ((nam = (char *)hashput((Hash_table_t*)ret->res, 
214                 resources[i].resource_name, (char *)&resources[i])) == NULL) 
215             {
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);
220                free(errhdr);
221                free(errmsg);
222             } 
223          }
224
225          /* Load any of Motif's secondary resources */
226          /*
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.
235           */
236          if (ret->class == xmDialogShellWidgetClass)
237          {
238             numBlocks = XmGetSecondaryResourceData(vendorShellWidgetClass, 
239                                                    &blockArray);
240          }
241          else
242             numBlocks = XmGetSecondaryResourceData(ret->class, &blockArray);
243
244          if (numBlocks > 0)
245          {
246             for (i = 0; i < numBlocks; i++)
247             {
248                for (j = 0; j < blockArray[i]->num_resources; j++)
249                {
250                   if ((nam = (char *)hashput((Hash_table_t*)ret->res, 
251                              blockArray[i]->resources[j].resource_name, 
252                              (char *)&(blockArray[i]->resources[j]))) == NULL)
253                   {
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);
259                      free(errhdr);
260                      free(errmsg);
261                   } 
262                }
263                /*
264                 * We can't free up the actual array of resources, since we
265                 * hashed a reference to the entries into our resource hash
266                 * table:
267                 * XtFree((char *)blockArray[i]->resources); 
268                 */
269                XtFree((char *)blockArray[i]);
270             }
271          }
272
273          /* Perform any special resource fixing up */
274          fixupresources(s, (Hash_table_t *)ret->res, 
275                         (resfixup_t *)&ret->resfix[0]);
276
277          /*
278           * Get constraint resources, if there are any
279           */
280          XtGetConstraintResourceList(ret->class, &resources, &numresources);
281          if (resources != NULL) 
282          {
283             ret->con = (char *)hashalloc(NULL, 0);
284             for (i = 0; i < numresources; i++) 
285             {
286                if ((nam = (char *)hashput((Hash_table_t*)ret->con, 
287                     resources[i].resource_name, &resources[i])) == NULL) 
288                {
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);
293                   free(errhdr);
294                   free(errmsg);
295                } 
296             }
297             fixupresources(s, (Hash_table_t *)ret->con, 
298                            (resfixup_t *)&ret->confix[0]);
299          } 
300          else 
301             ret->con = NULL;
302       }
303       return(ret);
304    }
305
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);
309    free(errmsg);
310    return(NULL);
311 }
312
313 Widget
314 DtkshNameToWidget(
315         String s )
316 {
317         Widget w;
318         char *p;
319         int len;
320         char * errhdr;
321         char * errmsg;
322
323         if (s == NULL || *s == '\0')
324                 return(NULL);
325
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);
330                 free(errhdr);
331                 free(errmsg);
332                 return(NULL);
333         }
334         len = strlen(W[0]->wname);
335         if (strncmp(s, W[0]->wname, len) == 0) {
336                 if (s[len] == '\0')
337                         return(Toplevel);
338                 if (s[len] == '.')
339                         return(XtNameToWidget(Toplevel, &s[len+1]));
340         }
341         return(NULL);
342 }
343
344 /*
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.
348  *
349  * If the name is not of the correct form, we use XtNameToWidget
350  * to try to convert the name to a widget id.
351  */
352
353 wtab_t *
354 str_to_wtab(
355         char *arg0,
356         char *v )
357 {
358         int index, len;
359         char * errmsg;
360
361         if (v == NULL || strcmp(v, "NULL") == 0)
362                 return(NULL);
363
364         if (v[0] != 'W' || (len = strlen(v)) < 2 ||
365                 strspn(&v[1], str_0123456789) != len-1) {
366                 Widget wid;
367
368                 if ((wid = DtkshNameToWidget(v)) == NULL) {
369                         if (arg0)
370                         {
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,
375                                           NULL, NULL);
376                                 free(errmsg);
377                         }
378                         return(NULL);
379                 }
380
381                 return(widget_to_wtab(wid));
382         }
383         index = atoi(&v[1]);
384         if (index < 0 || index >= NumW) {
385                 if (arg0)
386                 {
387                         errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
388                         printerrf(arg0, errmsg, v, NULL,
389                                   NULL, NULL, NULL, NULL, NULL, NULL);
390                         free(errmsg);
391                 }
392                 return(NULL);
393         }
394         if (W[index]->type == TAB_EMPTY && W[index]->w == NULL) {
395                 if (arg0)
396                 {
397                         errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
398                         printerrf(arg0, errmsg, v, NULL, NULL,
399                                   NULL, NULL, NULL, NULL, NULL);
400                         free(errmsg);
401                 }
402                 return(NULL);
403         }
404         return(W[index]);
405 }
406
407 Widget
408 handle_to_widget(
409         char *arg0,
410         char *handle )
411 {
412         wtab_t *w = str_to_wtab(arg0, handle);
413
414         if (w)
415                 return(w->w);
416         else
417                 return(NULL);
418 }
419
420 /*
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.
426  */
427
428 wtab_t *
429 widget_to_wtab(
430         Widget w )
431 {
432         register int i;
433         char * errmsg;
434
435         if (w == NULL)
436                 return(NULL);
437         for (i = 0; i < NumW; i++) {
438                 if ((W[i]->type != TAB_EMPTY) && (W[i]->w == w))
439                         return(W[i]);
440         }
441         /*
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.
450          */
451         {
452                 wtab_t *pwtab;          /* parent wtab */
453                 WidgetClass wclass;     /* class record */
454                 classtab_t *class;      /* widget's class */
455
456                 if ((pwtab = widget_to_wtab(XtParent(w))) == NULL) {
457                         errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
458                         printerr("widget_to_wtab", errmsg, NULL);
459                         free(errmsg);
460                         return(NULL);
461                 }
462                 wclass = XtClass(w);
463                 /*
464                  * Again, we have to go linear searching for this
465                  * right now.
466                  */
467                 class = NULL;
468                 for (i = 0; C[i].cname != NULL; i++) {
469                         if (C[i].class == wclass) {
470                                 class = &C[i];
471                                 break;
472                         }
473                 }
474                 if (class == NULL) {
475                         errmsg = strdup(GETMESSAGE(14,4, 
476                               "Unable to find the widget class"));
477                         printerr("widget_to_wtab", errmsg, NULL);
478                         free(errmsg);
479                         return(NULL);
480                 }
481                 /*
482                  * If this class has not been initialized, we
483                  * better force it to be set up by calling
484                  * str_to_class();
485                  */
486                 if (class->res == NULL)
487                         str_to_class("widget_to_wtab", class->cname);
488                 return(set_up_w(w, pwtab, NULL, NULL, class));
489         }
490 }
491
492 void
493 get_new_wtab(
494         wtab_t **w,
495         char *name )
496
497 {
498         register int i;
499
500         /*
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.
507          */
508         i = NumW;
509         if (Wtab_free > 0) {
510                 for (i = 0; i < NumW; i++) {
511                         if (W[i]->type == TAB_EMPTY) {
512                                 Wtab_free--;
513                                 break;
514                         }
515                 }
516         }
517         if (i == NumW) {
518                 if (NumW < MaxW) {
519                         i = NumW++;
520                 } else {
521                         register int j;
522                         int oldmax = MaxW;
523                         wtab_t *wentries;
524
525                         MaxW += WIDGETALLOC;
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++)
529                         {
530                                 W[oldmax+j] = &wentries[j];
531                                 wentries[j].type = TAB_EMPTY;
532                         }
533                         i = NumW++;
534                 }
535         }
536         sprintf(name, "W%d", i);
537         *w = W[i];
538         return;
539 }
540
541 static void
542 fixupresources(
543         char *name,
544         Hash_table_t *res,
545         resfixup_t *fixups )
546 {
547         XtResource *resource;
548         register int i;
549         char *nam;
550
551         if (fixups == NULL)
552                 return;
553
554         for (i = 0; fixups[i].name != NULL; i++) {
555                 resource = (XtResource *)hashget(res, fixups[i].name);
556                 /*
557                  * We could be either adding a new resource or
558                  * modifying an old one.
559                  */
560                 if (resource == NULL)
561                         resource = (XtResource *)XtMalloc(sizeof(XtResource));
562                 /*
563                  * The only fields dtksh uses are the name, class, type and
564                  * size, so that's all we attempt to fix up.
565                  *
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 
571                  *       MISSING.
572                  */
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);
578         }
579 }
580
581 int
582 do_DtLoadWidget(
583         int argc,
584         char *argv[] )
585 {
586    classtab_t *classtab;
587    void *address;
588    char *nam;
589    char * errhdr;
590    char * errmsg;
591
592    init_widgets();
593
594    if (argc != 3) 
595    {
596       errmsg = strdup(GETMESSAGE(14,5, 
597                "Usage: DtLoadWidget widgetClassName widgetClassRecordName"));
598       printerr(str_nill, errmsg, NULL);
599       free(errmsg);
600       return(1);
601    }
602
603    if ((address = (void *)fsym(argv[2], -1)) == NULL) 
604    {
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);
609       free(errmsg);
610       return(1);
611    } 
612    else 
613    {
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)
619       {
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);
625          free(errhdr);
626          free(errmsg);
627          return(1);
628       }
629    }
630    return(0);
631 }
632
633 static XtResource *Res[1024];
634 static int Nres;
635
636 static int
637 rescompare(
638         XtResource **r1,
639         XtResource **r2 )
640 {
641         return(strcmp(r1[0]->resource_name, r2[0]->resource_name));
642 }
643
644 static void
645 _pr_class(
646         classtab_t *c )
647 {
648         printf("%s\n", c->cname);
649 }
650
651 static void
652 _pr_resource_list(
653         XtResource *res )
654 {
655         printf("\t%-24.24s %-24.24s %s\n", res->resource_name, res->resource_class, res->resource_type);
656 }
657
658 static void
659 sort_and_print_res( void )
660 {
661         register int i;
662         qsort(Res, Nres, sizeof(XtResource *), (int (*)())rescompare);
663         for (i = 0; i < Nres; i++) {
664                 _pr_resource_list(Res[i]);
665         }
666 }
667
668 static void
669 gather_resource_list(
670         char *name,
671         char *r,
672         void *notUsed )
673 {
674         XtResource *res = (XtResource *)r;
675
676         Res[Nres++] = res;
677 }
678
679 static int Show_constraint;
680
681 static void
682 _pr_resource(
683         classtab_t *c,
684         wtab_t *w )
685 {
686         char * errmsg;
687         char * errmsg2;
688
689         if (c->res == NULL)
690                 str_to_class("DtWidgetInfo", c->cname);
691
692         if (Show_constraint && c->con == NULL)  /* No constraint resources */
693                 return;
694
695         errmsg = strdup(GETMESSAGE(14,8, "\n%sRESOURCES FOR %s%s%s:\n"));
696         errmsg2 = strdup(Show_constraint ? GETMESSAGE(14,9, "CONSTRAINT ") : 
697                          str_nill);
698         printf(errmsg, errmsg2,
699                 c->cname,
700                 w ? " " : str_nill, 
701                 w ? w->widid : str_nill);
702         free(errmsg);
703         free(errmsg2);
704
705         Nres = 0;
706
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);
711
712         }
713
714         sort_and_print_res();
715 }
716
717 static void
718 pr_resource(
719         char *name,
720         char *r,
721         void *notUsed )
722 {
723         classtab_t *c = (classtab_t *)r;
724
725         _pr_resource(c, NULL);
726 }
727
728 static void
729 pr_class(
730         char *name,
731         char *c,
732         void *notUsed )
733 {
734         classtab_t *class = (classtab_t *)c;
735
736         _pr_class(class);
737 }
738
739 static char *
740 getname(
741         wtab_t *w,
742         char *buf,
743         int max )
744 {
745         char *p;
746         int len;
747
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
751          */
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! */
755                         p--;
756                         *p = '*';
757                         return(p);
758                 }
759                 p -= len+1;
760                 strcpy(p, w->wname);
761                 if (p + len != buf + max - 1)
762                         p[len] = '.';
763         }
764         return(p);
765 }
766
767 static void
768 pr_widinfo(
769         wtab_t *w )
770 {
771         char namebuf[256];
772         char *name;
773         char statbuf[8];
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;
779
780         if (errmsg == NULL)
781         {
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"));
787         }
788
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);
794
795         printf(errmsg,
796                 w->envar,
797                 w->widid, 
798                 w->parent ? w->parent->widid : "none", 
799                 w->wclass->cname,
800                 statbuf,
801                 name);
802 }
803
804 static void
805 pr_widheader( void )
806 {
807    char * errmsg;
808
809    errmsg = strdup(GETMESSAGE(14,14, 
810             "ENV VARIABLE    HANDLE PARENT CLASS              STATUS NAME\n"));
811    printf(errmsg);
812    free(errmsg);
813 }
814
815 /*
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 
821  */
822
823
824 int
825 do_DtWidgetInfo(
826         int argc,
827         char *argv[] )
828 {
829         register int i, j;
830         char buf[1024];
831         wtab_t *w;
832         classtab_t *c;
833         int errs = 0;
834         char * errmsg;
835
836         if (C[0].class == NULL) {
837                 errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
838                 printerr(argv[0], errmsg, NULL);
839                 free(errmsg);
840                 return(1);
841         }
842         if (argc == 1 || argv[1][0] != '-') {
843                 /* Print long listing of each widget */
844                 pr_widheader();
845                 if (argc == 1) {
846                         for (i = 0; i < NumW; i++) {
847                                 if (W[i]->type == TAB_EMPTY)
848                                         continue;
849                                 pr_widinfo(W[i]);
850                         }
851                 } else {
852                         for (i = 1; i < argc; i++) {
853                                 if ((w = str_to_wtab(argv[0], argv[i])) != NULL)
854                                         pr_widinfo(w);
855                         }
856                 }
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 */
861                         if (argc == 2) {
862                                 hashwalk((Hash_table_t *)Wclasses, 0, 
863                                            (int (*)())pr_resource, 0);
864                                 return(0);
865                         } else {
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)
869                                                         return(0);
870
871                                                 if (!Show_constraint && c-> res == NULL)
872                                                         return(0);
873
874                                                 w = str_to_wtab(NULL, argv[i]);
875                                                 _pr_resource(c, w);
876                                         }
877                                 }
878                         }
879                         return(0);
880                 } else if (strcmp(argv[1], "-c") == 0) {
881                         /*
882                          * print all the available classes, or check if a
883                          * class is available
884                          */
885                         if (argc == 2) {
886                                 hashwalk((Hash_table_t *)Wclasses, 0, (int (*)())pr_class, 0);
887                         } else {
888                                 for (i = 2; i < argc; i++) {
889                                         if ((c = str_to_class(argv[0], argv[i])) != NULL)
890                                                 _pr_class(c);
891                                 }
892                         }
893                         return(0);
894                 } else if (strcmp(argv[1], "-h") == 0) {
895                         /* print active widget handles */
896                         if (argc == 2) {
897                                 for (i = 0; i < NumW; i++) {
898                                         if (W[i]->type == TAB_EMPTY)
899                                                 continue;
900                                         printf("%s\n", W[i]->widid);
901                                 }
902                         } else {
903                                 for (i = 2; i < argc; i++) {
904                                         if ((w = str_to_wtab(argv[0], argv[i])) == NULL) {
905                                                 errs++;
906                                                 continue;
907                                         }
908                                         printf("%s\n", w->wname);
909                                 }
910                         }
911                 } else {
912                         errmsg = strdup(GetSharedMsg(DT_UNKNOWN_OPTION));
913                         printerrf(argv[0], errmsg, argv[1], NULL,
914                                   NULL, NULL, NULL, NULL, NULL, NULL);
915                         free(errmsg);
916
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);
919                         free(errmsg);
920                         return(255);
921                 }
922         }
923         return(errs);
924 }
925
926
927 /*
928  * If the incoming environment variable is "-", then print the value out,
929  * instead of placing it into the environment.
930  */
931
932 void
933 alt_env_set_var(
934         char *variable,
935         char *value )
936 {
937    if (strcmp(variable, "-") == 0)
938       puts(value);
939    else
940       env_set_var(variable, value);
941 }