widget.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  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. /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
  25. /* All Rights Reserved */
  26. /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
  27. /* UNIX System Laboratories, Inc. */
  28. /* The copyright notice above does not evidence any */
  29. /* actual or intended publication of such source code. */
  30. #include "name.h"
  31. #include "shell.h"
  32. #include <string.h>
  33. #include <X11/Intrinsic.h>
  34. #include <X11/IntrinsicP.h>
  35. #include <X11/Shell.h>
  36. #include <X11/StringDefs.h>
  37. #include <Xm/Xm.h>
  38. #include <Xm/XmStrDefs.h>
  39. #include <Xm/DialogS.h>
  40. #include "hash.h"
  41. #include "stdio.h"
  42. #define NO_AST
  43. #include "dtksh.h"
  44. #undef NO_AST
  45. #include "xmksh.h"
  46. #include "dtkcmds.h"
  47. #include "xmcvt.h"
  48. #include "widget.h"
  49. #include "extra.h"
  50. #include "xmwidgets.h"
  51. #include "msgs.h"
  52. /* values for the flags field of the W array */
  53. #define RESOURCE_HASHSIZE 64
  54. #define CLASS_HASHSIZE 32
  55. #define WIDGETALLOC 16 /* Will realloc the widget array in this increment */
  56. wtab_t **W = NULL;
  57. int NumW = 0;
  58. int MaxW = 0;
  59. int Wtab_free = 0; /* A count of how many table entries have been freed */
  60. /* CONSTANTS */
  61. char str_0123456789[] = "0123456789";
  62. Hashtab_t *Wclasses;
  63. static void fixupresources(
  64. char *name,
  65. Hash_table_t *res,
  66. resfixup_t *fixups) ;
  67. static int rescompare(
  68. XtResource **r1,
  69. XtResource **r2) ;
  70. static void _pr_class(
  71. classtab_t *c) ;
  72. static void _pr_resource_list(
  73. XtResource *res) ;
  74. static void sort_and_print_res( void ) ;
  75. static void gather_resource_list(
  76. char *name,
  77. char *r,
  78. void *notUsed) ;
  79. static void _pr_resource(
  80. classtab_t *c,
  81. wtab_t *w) ;
  82. static void pr_resource(
  83. char *name,
  84. char *r,
  85. void *notUsed) ;
  86. static void pr_class(
  87. char *name,
  88. char *c,
  89. void *notUsed) ;
  90. static char * getname(
  91. wtab_t *w,
  92. char *buf,
  93. int max) ;
  94. static void pr_widinfo(
  95. wtab_t *w) ;
  96. static void pr_widheader( void ) ;
  97. void
  98. init_widgets( void )
  99. {
  100. register int i, n = 0;
  101. char *nam;
  102. wtab_t *wentries;
  103. char * errmsg;
  104. char * errhdr;
  105. if (C[0].class != NULL)
  106. return;
  107. toolkit_init_widgets();
  108. Wclasses = hashalloc(NULL, 0);
  109. for (i = 0; C[i].cname != NULL; i++) {
  110. if ((nam = hashput(Wclasses, C[i].cname, (char *)(&C[i]))) == NULL)
  111. {
  112. errhdr = strdup(GetSharedMsg(DT_ERROR));
  113. errmsg = strdup(GETMESSAGE(14,1,
  114. "Internal hash table failure during widget class initialization; exiting"));
  115. printerr(errhdr, errmsg, NULL);
  116. free(errhdr);
  117. free(errmsg);
  118. exit(1);
  119. }
  120. }
  121. /*
  122. * The array of widget records starts out big enough to
  123. * hold WIDGETALLOC widgets, and will grow in increments
  124. * of WIDGETALLOC as it overflows.
  125. */
  126. W = (wtab_t **)XtMalloc(WIDGETALLOC*sizeof(wtab_t *));
  127. wentries = (wtab_t *)XtCalloc(WIDGETALLOC, sizeof(wtab_t));
  128. for (i = 0; i < WIDGETALLOC; i++)
  129. {
  130. W[i] = &wentries[i];
  131. wentries[i].type = TAB_EMPTY;
  132. }
  133. MaxW = WIDGETALLOC;
  134. }
  135. /*
  136. * string to widgetclass
  137. */
  138. classtab_t *
  139. str_to_class(
  140. char *arg0,
  141. char *s )
  142. {
  143. register int i, j, n;
  144. Widget w;
  145. char *nam;
  146. classtab_t *ret;
  147. char * errhdr;
  148. char * errmsg;
  149. Cardinal numBlocks;
  150. XmSecondaryResourceData * blockArray;
  151. /*
  152. * If it looks like a handle, look it up and return the
  153. * class of the widget associated with the handle.
  154. */
  155. if (s[0] == 'W' && strspn(&s[1], str_0123456789) == strlen(&s[1]))
  156. {
  157. wtab_t *w = str_to_wtab(arg0, s);
  158. if (w != NULL)
  159. return(w->wclass);
  160. }
  161. if ((nam = hashget(Wclasses, s)) != NULL)
  162. {
  163. ret = (classtab_t *)nam;
  164. if (ret->res == NULL)
  165. {
  166. XtResourceList resources;
  167. Cardinal numresources;
  168. /* First reference of a given widget class
  169. * Automatically causes that widget class to
  170. * be initialized, it's resources read and
  171. * hashed.
  172. */
  173. ret->res = (char *)hashalloc(NULL, 0);
  174. /*
  175. * Have to force the class init
  176. * of this widget to execute, else we won't
  177. * get a complete list of resources, and any
  178. * converters added by this widget won't be
  179. * available.
  180. */
  181. XtInitializeWidgetClass(ret->class);
  182. XtGetResourceList(ret->class, &resources, &numresources);
  183. for (i = 0; i < numresources; i++)
  184. {
  185. if ((nam = (char *)hashput((Hash_table_t*)ret->res,
  186. resources[i].resource_name, (char *)&resources[i])) == NULL)
  187. {
  188. errhdr = strdup(GetSharedMsg(DT_ERROR));
  189. errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
  190. printerrf(errhdr, errmsg, resources[i].resource_name,
  191. ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
  192. free(errhdr);
  193. free(errmsg);
  194. }
  195. }
  196. /* Load any of Motif's secondary resources */
  197. /*
  198. * The following is a special hack to work around a Motif bug
  199. * (which has been reported). DialogShell is a grandchild class of
  200. * VendorShell, which defines secondary resources. DialogShell is
  201. * also a child class of TransientShell. Secondary resource
  202. * information is contained within extension records, which the
  203. * TransientShell class knows nothing about, thus preventing
  204. * XmGetSecondaryResourceData from getting any secondary resources
  205. * further up the inheritance chain.
  206. */
  207. if (ret->class == xmDialogShellWidgetClass)
  208. {
  209. numBlocks = XmGetSecondaryResourceData(vendorShellWidgetClass,
  210. &blockArray);
  211. }
  212. else
  213. numBlocks = XmGetSecondaryResourceData(ret->class, &blockArray);
  214. if (numBlocks > 0)
  215. {
  216. for (i = 0; i < numBlocks; i++)
  217. {
  218. for (j = 0; j < blockArray[i]->num_resources; j++)
  219. {
  220. if ((nam = (char *)hashput((Hash_table_t*)ret->res,
  221. blockArray[i]->resources[j].resource_name,
  222. (char *)&(blockArray[i]->resources[j]))) == NULL)
  223. {
  224. errhdr = strdup(GetSharedMsg(DT_ERROR));
  225. errmsg=strdup(GetSharedMsg( DT_HASHING_FAILURE));
  226. printerrf(errhdr, errmsg,
  227. blockArray[i]->resources[j].resource_name,
  228. ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
  229. free(errhdr);
  230. free(errmsg);
  231. }
  232. }
  233. /*
  234. * We can't free up the actual array of resources, since we
  235. * hashed a reference to the entries into our resource hash
  236. * table:
  237. * XtFree((char *)blockArray[i]->resources);
  238. */
  239. XtFree((char *)blockArray[i]);
  240. }
  241. }
  242. /* Perform any special resource fixing up */
  243. fixupresources(s, (Hash_table_t *)ret->res,
  244. (resfixup_t *)&ret->resfix[0]);
  245. /*
  246. * Get constraint resources, if there are any
  247. */
  248. XtGetConstraintResourceList(ret->class, &resources, &numresources);
  249. if (resources != NULL)
  250. {
  251. ret->con = (char *)hashalloc(NULL, 0);
  252. for (i = 0; i < numresources; i++)
  253. {
  254. if ((nam = (char *)hashput((Hash_table_t*)ret->con,
  255. resources[i].resource_name, &resources[i])) == NULL)
  256. {
  257. errhdr =strdup(GetSharedMsg(DT_ERROR));
  258. errmsg=strdup(GetSharedMsg(DT_HASHING_FAILURE));
  259. printerrf(errhdr, errmsg, resources[i].resource_name,
  260. ret->cname, NULL, NULL, NULL, NULL, NULL, NULL);
  261. free(errhdr);
  262. free(errmsg);
  263. }
  264. }
  265. fixupresources(s, (Hash_table_t *)ret->con,
  266. (resfixup_t *)&ret->confix[0]);
  267. }
  268. else
  269. ret->con = NULL;
  270. }
  271. return(ret);
  272. }
  273. errmsg = strdup(GETMESSAGE(14,2,
  274. "Could not find a widget class named '%s'"));
  275. printerrf(arg0, errmsg, s, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  276. free(errmsg);
  277. return(NULL);
  278. }
  279. Widget
  280. DtkshNameToWidget(
  281. String s )
  282. {
  283. Widget w;
  284. char *p;
  285. int len;
  286. char * errhdr;
  287. char * errmsg;
  288. if (s == NULL || *s == '\0')
  289. return(NULL);
  290. if (W == NULL || W[0] == NULL) {
  291. errhdr = strdup(GetSharedMsg(DT_WARNING));
  292. errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
  293. printerr(errhdr, errmsg, NULL);
  294. free(errhdr);
  295. free(errmsg);
  296. return(NULL);
  297. }
  298. len = strlen(W[0]->wname);
  299. if (strncmp(s, W[0]->wname, len) == 0) {
  300. if (s[len] == '\0')
  301. return(Toplevel);
  302. if (s[len] == '.')
  303. return(XtNameToWidget(Toplevel, &s[len+1]));
  304. }
  305. return(NULL);
  306. }
  307. /*
  308. * Take a character string and translate it into a wtab_t.
  309. * The string should be of the form: W<num>. The <num> must
  310. * point to a valid index in the W array.
  311. *
  312. * If the name is not of the correct form, we use XtNameToWidget
  313. * to try to convert the name to a widget id.
  314. */
  315. wtab_t *
  316. str_to_wtab(
  317. char *arg0,
  318. char *v )
  319. {
  320. int index, len;
  321. char * errmsg;
  322. if (v == NULL || strcmp(v, "NULL") == 0)
  323. return(NULL);
  324. if (v[0] != 'W' || (len = strlen(v)) < 2 ||
  325. strspn(&v[1], str_0123456789) != len-1) {
  326. Widget wid;
  327. if ((wid = DtkshNameToWidget(v)) == NULL) {
  328. if (arg0)
  329. {
  330. errmsg = strdup(GETMESSAGE(14,3,
  331. "The identifier '%s' is not a valid widget handle"));
  332. printerrf(arg0, errmsg, v,
  333. NULL, NULL, NULL, NULL, NULL,
  334. NULL, NULL);
  335. free(errmsg);
  336. }
  337. return(NULL);
  338. }
  339. return(widget_to_wtab(wid));
  340. }
  341. index = atoi(&v[1]);
  342. if (index < 0 || index >= NumW) {
  343. if (arg0)
  344. {
  345. errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
  346. printerrf(arg0, errmsg, v, NULL,
  347. NULL, NULL, NULL, NULL, NULL, NULL);
  348. free(errmsg);
  349. }
  350. return(NULL);
  351. }
  352. if (W[index]->type == TAB_EMPTY && W[index]->w == NULL) {
  353. if (arg0)
  354. {
  355. errmsg = strdup(GetSharedMsg(DT_BAD_WIDGET_HANDLE));
  356. printerrf(arg0, errmsg, v, NULL, NULL,
  357. NULL, NULL, NULL, NULL, NULL);
  358. free(errmsg);
  359. }
  360. return(NULL);
  361. }
  362. return(W[index]);
  363. }
  364. Widget
  365. handle_to_widget(
  366. char *arg0,
  367. char *handle )
  368. {
  369. wtab_t *w = str_to_wtab(arg0, handle);
  370. if (w)
  371. return(w->w);
  372. else
  373. return(NULL);
  374. }
  375. /*
  376. * This function takes a widget and finds the wtab associated with it.
  377. * This operation is performed infrequently, for example if the user
  378. * gets a resource that is a widget. So, we're just using a linear
  379. * search right now. If profiling reveals this to be too slow we'll
  380. * have to introduce another hash table or something.
  381. */
  382. wtab_t *
  383. widget_to_wtab(
  384. Widget w )
  385. {
  386. register int i;
  387. char * errmsg;
  388. if (w == NULL)
  389. return(NULL);
  390. for (i = 0; i < NumW; i++) {
  391. if ((W[i]->type != TAB_EMPTY) && (W[i]->w == w))
  392. return(W[i]);
  393. }
  394. /*
  395. * If we failed to find the widget id in the
  396. * internal table then this was probably a widget that
  397. * was created as a side effect of another widget's creation,
  398. * or perhaps was created by a user-defined builtin or something.
  399. * So, we'll create a new table entry for it using set_up_w().
  400. * Of course, set_up_w() needs to know the widget's parent's
  401. * wtab_t, which we get by recursively calling ourself. Also,
  402. * we need the widget's class.
  403. */
  404. {
  405. wtab_t *pwtab; /* parent wtab */
  406. WidgetClass wclass; /* class record */
  407. classtab_t *class; /* widget's class */
  408. if ((pwtab = widget_to_wtab(XtParent(w))) == NULL) {
  409. errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
  410. printerr("widget_to_wtab", errmsg, NULL);
  411. free(errmsg);
  412. return(NULL);
  413. }
  414. wclass = XtClass(w);
  415. /*
  416. * Again, we have to go linear searching for this
  417. * right now.
  418. */
  419. class = NULL;
  420. for (i = 0; C[i].cname != NULL; i++) {
  421. if (C[i].class == wclass) {
  422. class = &C[i];
  423. break;
  424. }
  425. }
  426. if (class == NULL) {
  427. errmsg = strdup(GETMESSAGE(14,4,
  428. "Unable to find the widget class"));
  429. printerr("widget_to_wtab", errmsg, NULL);
  430. free(errmsg);
  431. return(NULL);
  432. }
  433. /*
  434. * If this class has not been initialized, we
  435. * better force it to be set up by calling
  436. * str_to_class();
  437. */
  438. if (class->res == NULL)
  439. str_to_class("widget_to_wtab", class->cname);
  440. return(set_up_w(w, pwtab, NULL, NULL, class));
  441. }
  442. }
  443. void
  444. get_new_wtab(
  445. wtab_t **w,
  446. char *name )
  447. {
  448. register int i;
  449. /*
  450. * If there has been a destroywidget call, then one or more
  451. * table entries may have been freed. We might want to make
  452. * a free list for this stuff someday, but for now we do a
  453. * linear search for the free slot. Most applications don't
  454. * do much widget destroying anyway, so this should rarely
  455. * execute and thus I'm not too dismayed by the linear search.
  456. */
  457. i = NumW;
  458. if (Wtab_free > 0) {
  459. for (i = 0; i < NumW; i++) {
  460. if (W[i]->type == TAB_EMPTY) {
  461. Wtab_free--;
  462. break;
  463. }
  464. }
  465. }
  466. if (i == NumW) {
  467. if (NumW < MaxW) {
  468. i = NumW++;
  469. } else {
  470. register int j;
  471. int oldmax = MaxW;
  472. wtab_t *wentries;
  473. MaxW += WIDGETALLOC;
  474. W = (wtab_t **)XtRealloc((char *)W, sizeof(wtab_t *)*MaxW);
  475. wentries = (wtab_t *)XtMalloc(sizeof(wtab_t)*WIDGETALLOC);
  476. for (j = 0; j < WIDGETALLOC; j++)
  477. {
  478. W[oldmax+j] = &wentries[j];
  479. wentries[j].type = TAB_EMPTY;
  480. }
  481. i = NumW++;
  482. }
  483. }
  484. sprintf(name, "W%d", i);
  485. *w = W[i];
  486. return;
  487. }
  488. static void
  489. fixupresources(
  490. char *name,
  491. Hash_table_t *res,
  492. resfixup_t *fixups )
  493. {
  494. XtResource *resource;
  495. register int i;
  496. char *nam;
  497. if (fixups == NULL)
  498. return;
  499. for (i = 0; fixups[i].name != NULL; i++) {
  500. resource = (XtResource *)hashget(res, fixups[i].name);
  501. /*
  502. * We could be either adding a new resource or
  503. * modifying an old one.
  504. */
  505. if (resource == NULL)
  506. resource = (XtResource *)XtMalloc(sizeof(XtResource));
  507. /*
  508. * The only fields dtksh uses are the name, class, type and
  509. * size, so that's all we attempt to fix up.
  510. *
  511. * NOTE: THE CLASS NAME IS REQUIRED, BECAUSE IF WE ARE ADDING
  512. * A NEW RESOURCE (VERSUS REPLACING AN EXISTING ONE),
  513. * THEN THE RESOURCE ENDS UP HAVING A 'NULL' CLASS
  514. * NAME. SINCE DtWidgetInfo DISPLAYS THE RESOURCE CLASS
  515. * NAME, THIS TIDBIT OF USEFUL INFORMATION WOULD BE
  516. * MISSING.
  517. */
  518. resource->resource_name = (String)fixups[i].name;
  519. resource->resource_class = (String)fixups[i].class;
  520. resource->resource_type = (String)fixups[i].type;
  521. resource->resource_size = fixups[i].size;
  522. hashput(res, fixups[i].name, (char *)resource);
  523. }
  524. }
  525. int
  526. do_DtLoadWidget(
  527. int argc,
  528. char *argv[] )
  529. {
  530. classtab_t *classtab;
  531. void *address;
  532. char *nam;
  533. char * errhdr;
  534. char * errmsg;
  535. init_widgets();
  536. if (argc != 3)
  537. {
  538. errmsg = strdup(GETMESSAGE(14,5,
  539. "Usage: DtLoadWidget widgetClassName widgetClassRecordName"));
  540. printerr(str_nill, errmsg, NULL);
  541. free(errmsg);
  542. return(1);
  543. }
  544. if ((address = (void *)fsym(argv[2], -1)) == NULL)
  545. {
  546. errmsg = strdup(GETMESSAGE(14,6,
  547. "Unable to locate a widget class record named '%s'"));
  548. printerrf(argv[0], errmsg,
  549. argv[2], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  550. free(errmsg);
  551. return(1);
  552. }
  553. else
  554. {
  555. classtab = (classtab_t *)XtMalloc(sizeof(classtab_t));
  556. memset(classtab, '\0', sizeof(classtab_t));
  557. classtab->cname = (char *)strdup(argv[1]);
  558. classtab->class = ((WidgetClass *)address)[0];
  559. if ((nam = hashput(Wclasses, classtab->cname, (char *)classtab)) == NULL)
  560. {
  561. errhdr = strdup(GetSharedMsg(DT_ERROR));
  562. errmsg= strdup(GETMESSAGE(14,7,
  563. "Internal hash table failure during initialization of widget class '%s'"));
  564. printerrf(errhdr, errmsg, classtab->cname,
  565. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  566. free(errhdr);
  567. free(errmsg);
  568. return(1);
  569. }
  570. }
  571. return(0);
  572. }
  573. static XtResource *Res[1024];
  574. static int Nres;
  575. static int
  576. rescompare(
  577. XtResource **r1,
  578. XtResource **r2 )
  579. {
  580. return(strcmp(r1[0]->resource_name, r2[0]->resource_name));
  581. }
  582. static void
  583. _pr_class(
  584. classtab_t *c )
  585. {
  586. printf("%s\n", c->cname);
  587. }
  588. static void
  589. _pr_resource_list(
  590. XtResource *res )
  591. {
  592. printf("\t%-24.24s %-24.24s %s\n", res->resource_name, res->resource_class, res->resource_type);
  593. }
  594. static void
  595. sort_and_print_res( void )
  596. {
  597. register int i;
  598. qsort(Res, Nres, sizeof(XtResource *), (int (*)())rescompare);
  599. for (i = 0; i < Nres; i++) {
  600. _pr_resource_list(Res[i]);
  601. }
  602. }
  603. static void
  604. gather_resource_list(
  605. char *name,
  606. char *r,
  607. void *notUsed )
  608. {
  609. XtResource *res = (XtResource *)r;
  610. Res[Nres++] = res;
  611. }
  612. static int Show_constraint;
  613. static void
  614. _pr_resource(
  615. classtab_t *c,
  616. wtab_t *w )
  617. {
  618. char * errmsg;
  619. char * errmsg2;
  620. if (c->res == NULL)
  621. str_to_class("DtWidgetInfo", c->cname);
  622. if (Show_constraint && c->con == NULL) /* No constraint resources */
  623. return;
  624. errmsg = strdup(GETMESSAGE(14,8, "\n%sRESOURCES FOR %s%s%s:\n"));
  625. errmsg2 = strdup(Show_constraint ? GETMESSAGE(14,9, "CONSTRAINT ") :
  626. str_nill);
  627. printf(errmsg, errmsg2,
  628. c->cname,
  629. w ? " " : str_nill,
  630. w ? w->widid : str_nill);
  631. free(errmsg);
  632. free(errmsg2);
  633. Nres = 0;
  634. hashwalk((Hash_table_t*)(Show_constraint ? c->con : c->res), 0, (int (*)())gather_resource_list, NULL);
  635. if (!Show_constraint && w && w->parent != NULL &&
  636. XtIsConstraint(w->parent->w)) {
  637. hashwalk((Hash_table_t *)w->parent->wclass->con, 0, (int (*)())gather_resource_list, NULL);
  638. }
  639. sort_and_print_res();
  640. }
  641. static void
  642. pr_resource(
  643. char *name,
  644. char *r,
  645. void *notUsed )
  646. {
  647. classtab_t *c = (classtab_t *)r;
  648. _pr_resource(c, NULL);
  649. }
  650. static void
  651. pr_class(
  652. char *name,
  653. char *c,
  654. void *notUsed )
  655. {
  656. classtab_t *class = (classtab_t *)c;
  657. _pr_class(class);
  658. }
  659. static char *
  660. getname(
  661. wtab_t *w,
  662. char *buf,
  663. int max )
  664. {
  665. char *p;
  666. int len;
  667. /* calculate a widget's name. Goes backwards through the
  668. * list of parents, filling in the names backwards in the
  669. * buffer, then returns a pointer to the start of the name
  670. */
  671. p = &buf[max]; /* that's right, buf[max] not buf[max-1] */
  672. for ( ; w; w = w->parent) {
  673. if (p - (len = strlen(w->wname)) < buf+3) { /* overflow! */
  674. p--;
  675. *p = '*';
  676. return(p);
  677. }
  678. p -= len+1;
  679. strcpy(p, w->wname);
  680. if (p + len != buf + max - 1)
  681. p[len] = '.';
  682. }
  683. return(p);
  684. }
  685. static void
  686. pr_widinfo(
  687. wtab_t *w )
  688. {
  689. char namebuf[256];
  690. char *name;
  691. char statbuf[8];
  692. static char * errmsg = NULL;
  693. static char * realizedStr = NULL;
  694. static char * managedStr = NULL;
  695. static char * sensitiveStr = NULL;
  696. char * realized, * managed, * sensitive;
  697. if (errmsg == NULL)
  698. {
  699. errmsg = strdup(GETMESSAGE(14,13,
  700. "%-15s %-6s %-6s %-18s %-6s %s\n"));
  701. realizedStr = strdup(GETMESSAGE(14,10, "R"));
  702. managedStr = strdup(GETMESSAGE(14,11, "M"));
  703. sensitiveStr = strdup(GETMESSAGE(14,12, "S"));
  704. }
  705. name = getname(w, namebuf, sizeof(namebuf));
  706. realized = XtIsRealized(w->w) ? realizedStr : str_nill;
  707. managed = XtIsManaged(w->w) ? managedStr : str_nill;
  708. sensitive = XtIsSensitive(w->w) ? sensitiveStr : str_nill;
  709. sprintf(statbuf, "%s%s%s", realized, managed, sensitive);
  710. printf(errmsg,
  711. w->envar,
  712. w->widid,
  713. w->parent ? w->parent->widid : "none",
  714. w->wclass->cname,
  715. statbuf,
  716. name);
  717. }
  718. static void
  719. pr_widheader( void )
  720. {
  721. char * errmsg;
  722. errmsg = strdup(GETMESSAGE(14,14,
  723. "ENV VARIABLE HANDLE PARENT CLASS STATUS NAME\n"));
  724. printf(errmsg);
  725. free(errmsg);
  726. }
  727. /*
  728. * DtWidgetInfo -r [widget|class] print resources and their types for widgets
  729. * DtWidgetInfo -R [widget|class] print constraint resources for widgets
  730. * DtWidgetInfo -c [class] print info about a class
  731. * DtWidgetInfo -h [handle] print widget handles [or widget name]
  732. * DtWidgetInfo print summary info about all widgets
  733. */
  734. int
  735. do_DtWidgetInfo(
  736. int argc,
  737. char *argv[] )
  738. {
  739. register int i, j;
  740. char buf[1024];
  741. wtab_t *w;
  742. classtab_t *c;
  743. int errs = 0;
  744. char * errmsg;
  745. if (C[0].class == NULL) {
  746. errmsg = strdup(GetSharedMsg(DT_TK_NOT_INIT));
  747. printerr(argv[0], errmsg, NULL);
  748. free(errmsg);
  749. return(1);
  750. }
  751. if (argc == 1 || argv[1][0] != '-') {
  752. /* Print long listing of each widget */
  753. pr_widheader();
  754. if (argc == 1) {
  755. for (i = 0; i < NumW; i++) {
  756. if (W[i]->type == TAB_EMPTY)
  757. continue;
  758. pr_widinfo(W[i]);
  759. }
  760. } else {
  761. for (i = 1; i < argc; i++) {
  762. if ((w = str_to_wtab(argv[0], argv[i])) != NULL)
  763. pr_widinfo(w);
  764. }
  765. }
  766. } else if (argv[1][0] == '-') {
  767. if ((Show_constraint = strcmp(argv[1], "-r")) == 0 ||
  768. strcmp(argv[1], "-R") == 0) {
  769. /* print all the resources in each widget or class */
  770. if (argc == 2) {
  771. hashwalk((Hash_table_t *)Wclasses, 0,
  772. (int (*)())pr_resource, 0);
  773. return(0);
  774. } else {
  775. for (i = 2; i < argc; i++) {
  776. if ((c = str_to_class(argv[0], argv[i])) != NULL) {
  777. if (Show_constraint && c->con == NULL)
  778. return(0);
  779. if (!Show_constraint && c-> res == NULL)
  780. return(0);
  781. w = str_to_wtab(NULL, argv[i]);
  782. _pr_resource(c, w);
  783. }
  784. }
  785. }
  786. return(0);
  787. } else if (strcmp(argv[1], "-c") == 0) {
  788. /*
  789. * print all the available classes, or check if a
  790. * class is available
  791. */
  792. if (argc == 2) {
  793. hashwalk((Hash_table_t *)Wclasses, 0, (int (*)())pr_class, 0);
  794. } else {
  795. for (i = 2; i < argc; i++) {
  796. if ((c = str_to_class(argv[0], argv[i])) != NULL)
  797. _pr_class(c);
  798. }
  799. }
  800. return(0);
  801. } else if (strcmp(argv[1], "-h") == 0) {
  802. /* print active widget handles */
  803. if (argc == 2) {
  804. for (i = 0; i < NumW; i++) {
  805. if (W[i]->type == TAB_EMPTY)
  806. continue;
  807. printf("%s\n", W[i]->widid);
  808. }
  809. } else {
  810. for (i = 2; i < argc; i++) {
  811. if ((w = str_to_wtab(argv[0], argv[i])) == NULL) {
  812. errs++;
  813. continue;
  814. }
  815. printf("%s\n", w->wname);
  816. }
  817. }
  818. } else {
  819. errmsg = strdup(GetSharedMsg(DT_UNKNOWN_OPTION));
  820. printerrf(argv[0], errmsg, argv[1], NULL,
  821. NULL, NULL, NULL, NULL, NULL, NULL);
  822. free(errmsg);
  823. 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]"));
  824. printerr(str_nill, errmsg, NULL);
  825. free(errmsg);
  826. return(255);
  827. }
  828. }
  829. return(errs);
  830. }
  831. /*
  832. * If the incoming environment variable is "-", then print the value out,
  833. * instead of placing it into the environment.
  834. */
  835. void
  836. alt_env_set_var(
  837. char *variable,
  838. char *value )
  839. {
  840. if (strcmp(variable, "-") == 0)
  841. puts(value);
  842. else
  843. env_set_var(variable, value);
  844. }