1 /**************************************************************************\
2 *
3 * This file is part of the Coin 3D visualization library.
4 * Copyright (C) by Kongsberg Oil & Gas Technologies.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * ("GPL") version 2 as published by the Free Software Foundation.
9 * See the file LICENSE.GPL at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using Coin with software that can not be combined with the GNU
13 * GPL, and for taking advantage of the additional benefits of our
14 * support services, please contact Kongsberg Oil & Gas Technologies
15 * about acquiring a Coin Professional Edition License.
16 *
17 * See http://www.coin3d.org/ for more information.
18 *
19 * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
20 * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
21 *
22 \**************************************************************************/
23
24 #if SOXT_DEBUG
25 static const char rcsid[] =
26 "$Id$";
27 #endif // SOXT_DEBUG
28
29 // *************************************************************************
30
31 /*!
32 \class SoXtResource Inventor/Xt/SoXtResource.h
33 \brief The SoXtResource class is a utility class for fetching X resource
34 values for widgets. Special care is taken for SoXt components.
35 \ingroup misc
36 */
37
38 // *************************************************************************
39
40 #include <assert.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #include <X11/IntrinsicP.h>
45 #include <X11/CoreP.h>
46
47 #include <Inventor/SoLists.h>
48 #include <Inventor/errors/SoDebugError.h>
49
50 #include <soxtdefs.h>
51 #include <Inventor/Xt/SoXt.h>
52 #include <Inventor/Xt/SoXtComponent.h>
53
54 #include <Inventor/Xt/SoXtResource.h>
55
56 // *************************************************************************
57
58 int icstrcmp(const char * str1, const char * str2);
59
60 /*!
61 Constructor. sets up the SoXtResource object to fetch resources for
62 the \a widget Widget.
63 */
64
SoXtResource(const Widget widget)65 SoXtResource::SoXtResource(
66 const Widget widget)
67 {
68 static SbBool initialized = FALSE;
69 if (! initialized) {
70 XrmInitialize();
71 initialized = TRUE;
72 }
73
74 this->hierarchy_depth = 0;
75
76 if (! widget) {
77 this->name_hierarchy = NULL;
78 this->class_hierarchy = NULL;
79 this->display = SoXt::getDisplay();
80 return;
81 }
82
83 this->display = XtDisplay(widget);
84
85 SbIntList quarks;
86 Widget stop = NULL;
87
88 SoXtComponent * component = SoXtComponent::getComponent(widget);
89 if (component != NULL) {
90 Widget cwidget = component->getBaseWidget();
91 if (cwidget != NULL)
92 stop = XtParent(cwidget);
93 }
94
95 Widget w = widget;
96 while (w && w != stop) {
97 quarks.append(((CorePart *) w)->xrm_name);
98 quarks.append(((CoreClassPart *) XtClass(w))->xrm_class);
99 this->hierarchy_depth++;
100 if (XtIsShell(w))
101 break;
102 if ((component == NULL) &&
103 ((component = SoXtComponent::getComponent(w)) != NULL)) {
104 Widget cwidget = component->getWidget();
105 if (cwidget != NULL)
106 stop = XtParent(cwidget);
107 }
108 w = XtParent(w);
109 }
110
111 #if SOXT_DEBUG
112 if (component == NULL)
113 SoDebugError::postInfo("SoXtResource",
114 "using SoXtResource for non-component widget (which is OK)");
115 #endif // SOXT_DEBUG
116
117 this->name_hierarchy = new XrmQuark [ this->hierarchy_depth + 2];
118 this->class_hierarchy = new XrmQuark [ this->hierarchy_depth + 2];
119 int i;
120 for (i = 0; i < this->hierarchy_depth; i++) {
121 this->name_hierarchy[this->hierarchy_depth - i - 1] = quarks[i*2];
122 this->class_hierarchy[this->hierarchy_depth - i - 1] = quarks[i*2+1];
123 }
124 this->name_hierarchy[ this->hierarchy_depth ] = 0;
125 this->name_hierarchy[ this->hierarchy_depth + 1 ] = 0;
126 this->class_hierarchy[ this->hierarchy_depth ] = 0;
127 this->class_hierarchy[ this->hierarchy_depth + 1 ] = 0;
128
129 #if SOXT_DEBUG && 0
130 this->DumpInternals();
131 #endif // SOXT_DEBUG
132 } // SoXtResource()
133
134 /*!
135 Destructor.
136 */
137
~SoXtResource(void)138 SoXtResource::~SoXtResource(
139 void)
140 {
141 delete [] this->name_hierarchy;
142 delete [] this->class_hierarchy;
143 } // ~SoXtResource()
144
145 // *************************************************************************
146
147 /*!
148 This method just dumps the name and class hierarchy of the widget the
149 SoXtResource object is set to.
150 */
151
152 void
DumpInternals(void) const153 SoXtResource::DumpInternals(
154 void) const
155 {
156 SoDebugError::postInfo("SoXtResource::DumpInternals", "dumping");
157 fprintf(stdout, "Classes: ");
158 int i;
159 for (i = 0; i < this->hierarchy_depth; i++) {
160 fprintf(stdout, "%s", XrmQuarkToString(this->class_hierarchy[i]));
161 if (i < (this->hierarchy_depth - 1))
162 fprintf(stdout, ".");
163 }
164 fprintf(stdout, "\n");
165
166 fprintf(stdout, "Names: ");
167 for (i = 0; i < this->hierarchy_depth; i++) {
168 fprintf(stdout, "%s", XrmQuarkToString(this->name_hierarchy[i]));
169 if (i < (this->hierarchy_depth - 1))
170 fprintf(stdout, ".");
171 }
172 fprintf(stdout, "\n");
173 } // DumpInternals()
174
175 // *************************************************************************
176
177 #define GET_RESOURCE() \
178 XrmValue value; \
179 XrmRepresentation format; \
180 char * formatstr = NULL; \
181 do { \
182 SbBool found = FALSE; \
183 XrmDatabase database = XrmGetDatabase(this->display); \
184 if (this->name_hierarchy != NULL) { \
185 this->name_hierarchy[this->hierarchy_depth] = XrmStringToQuark(rname); \
186 this->class_hierarchy[this->hierarchy_depth] = \
187 XrmStringToQuark(rclass); \
188 found = XrmQGetResource(database, this->name_hierarchy, \
189 this->class_hierarchy, &format, &value) ? TRUE : FALSE; \
190 this->name_hierarchy[this->hierarchy_depth] = 0; \
191 this->class_hierarchy[this->hierarchy_depth] = 0; \
192 } \
193 if (! found) \
194 found = XrmGetResource(database, rname, \
195 rclass, &formatstr, &value) ? TRUE : FALSE; \
196 if (! found) \
197 return FALSE; \
198 } while (FALSE)
199
200 // *************************************************************************
201
202 /*!
203 This method retrieves the given X resource and puts it into the
204 SbColor object \a retval.
205
206 TRUE is returned if the resource is found, and FALSE otherwise.
207 */
208
209 SbBool
getResource(const char * const rname,const char * const rclass,SbColor & retval) const210 SoXtResource::getResource(
211 const char * const rname,
212 const char * const rclass,
213 SbColor & retval) const
214 {
215 GET_RESOURCE();
216 SOXT_STUB_ONCE();
217
218 XrmQuark stringq = XrmStringToQuark(XmRString);
219
220 if (formatstr != NULL)
221 format = XrmStringToQuark(formatstr);
222
223 if (format == stringq) {
224 XColor exact, screen;
225 Display * dpy = SoXt::getDisplay();
226 Colormap cmap = 0; // = SoXt::getColormap();
227 if (XLookupColor(dpy, cmap, (char *) value.addr, &exact, &screen)) {
228 retval = SbColor(float(exact.red) / 65535.0f,
229 float(exact.green) / 65535.0f, float(exact.blue) / 65535.0f);
230 return TRUE;
231 }
232 return FALSE;
233 }
234
235 #if SOXT_DEBUG
236 SoDebugError::postInfo("getResource",
237 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
238 #endif // SOXT_DEBUG
239 return FALSE;
240 } // getResource()
241
242 // *************************************************************************
243
244 /*!
245 This method retrieves the given X resource and puts it into the
246 short \a retval.
247
248 TRUE is returned if the resource is found, and FALSE otherwise.
249 */
250
251 SbBool
getResource(const char * const rname,const char * const rclass,short & retval) const252 SoXtResource::getResource(
253 const char * const rname,
254 const char * const rclass,
255 short & retval) const
256 {
257 GET_RESOURCE();
258
259 XrmQuark shortq = XrmStringToQuark(XmRShort);
260 XrmQuark stringq = XrmStringToQuark(XmRString);
261
262 if (formatstr != NULL)
263 format = XrmStringToQuark(formatstr);
264
265 if (format == shortq) {
266 retval = *((short *) value.addr);
267 return TRUE;
268 }
269 if (format == stringq) {
270 retval = atoi((char *) value.addr);
271 return TRUE;
272 }
273
274 #if SOXT_DEBUG
275 SoDebugError::postInfo("getResource",
276 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
277 #endif // SOXT_DEBUG
278 return FALSE;
279 } // getResource()
280
281 // *************************************************************************
282
283 /*!
284 This method retrieves the given X resource and puts it into the
285 unsigned short \a retval.
286
287 TRUE is returned if the resource is found, and FALSE otherwise.
288 */
289
290 SbBool
getResource(const char * const rname,const char * const rclass,unsigned short & retval) const291 SoXtResource::getResource(
292 const char * const rname,
293 const char * const rclass,
294 unsigned short & retval) const
295 {
296 GET_RESOURCE();
297
298 XrmQuark stringq = XrmStringToQuark(XmRString);
299 XrmQuark shortq = XrmStringToQuark(XmRShort);
300
301 if (formatstr != NULL)
302 format = XrmStringToQuark(formatstr);
303
304 if (format == shortq) {
305 retval = *((unsigned short *) value.addr);
306 return TRUE;
307 }
308
309 if (format == stringq) {
310 retval = atoi((char *) value.addr);
311 return TRUE;
312 }
313
314 #if SOXT_DEBUG
315 SoDebugError::postInfo("getResource",
316 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
317 #endif // SOXT_DEBUG
318 return FALSE;
319 } // getResource()
320
321 // *************************************************************************
322
323 /*!
324 This method retrieves the given X resource and points the \a retval
325 pointer to it's data.
326
327 TRUE is returned if the resource is found, and FALSE otherwise.
328 */
329
330 SbBool
getResource(const char * const rname,const char * const rclass,char * & retval) const331 SoXtResource::getResource(
332 const char * const rname,
333 const char * const rclass,
334 char * & retval) const
335 {
336 GET_RESOURCE();
337
338 XrmQuark stringq = XrmStringToQuark(XmRString);
339
340 if (formatstr != NULL)
341 format = XrmStringToQuark(formatstr);
342
343 if (format == stringq) {
344 retval = (char *) value.addr;
345 return TRUE;
346 }
347
348 #if SOXT_DEBUG
349 SoDebugError::postInfo("getResource",
350 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
351 #endif // SOXT_DEBUG
352 return FALSE;
353 } // getResource()
354
355 // *************************************************************************
356
357 /*!
358 This method retrieves the given X resource and puts it into the
359 SbBool \a retval.
360
361 TRUE is returned if the resource is found, and FALSE otherwise.
362 */
363
364 SbBool
getResource(const char * const rname,const char * const rclass,SbBool & retval) const365 SoXtResource::getResource(
366 const char * const rname,
367 const char * const rclass,
368 SbBool & retval) const
369 {
370 GET_RESOURCE();
371
372 XrmQuark stringq = XrmStringToQuark(XmRString);
373 XrmQuark booleanq = XrmStringToQuark(XmRBoolean);
374
375 if (formatstr != NULL)
376 format = XrmStringToQuark(formatstr);
377
378 if (format == booleanq) {
379 retval = *((Boolean *) value.addr) ? TRUE : FALSE;
380 return TRUE;
381 }
382
383 if (format == stringq) {
384 if (icstrcmp((const char *) value.addr, "true") == 0 ||
385 icstrcmp((const char *) value.addr, "on") == 0 ||
386 icstrcmp((const char *) value.addr, "yes") == 0 ||
387 icstrcmp((const char *) value.addr, "enable") == 0 ||
388 icstrcmp((const char *) value.addr, "enabled") == 0 ||
389 icstrcmp((const char *) value.addr, "set") == 0 ||
390 icstrcmp((const char *) value.addr, "1") == 0) {
391 retval = TRUE;
392 return TRUE;
393 } else if (icstrcmp((const char *) value.addr, "false") == 0 ||
394 icstrcmp((const char *) value.addr, "off") == 0 ||
395 icstrcmp((const char *) value.addr, "no") == 0 ||
396 icstrcmp((const char *) value.addr, "disable") == 0 ||
397 icstrcmp((const char *) value.addr, "disabled") == 0 ||
398 icstrcmp((const char *) value.addr, "unset") == 0 ||
399 icstrcmp((const char *) value.addr, "0") == 0) {
400 retval = FALSE;
401 return TRUE;
402 } else {
403 SoDebugError::postWarning("getResource",
404 "string \"%s\" not understood", (char *) value.addr);
405 return FALSE;
406 }
407 }
408
409 #if SOXT_DEBUG
410 SoDebugError::postInfo("getResource",
411 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
412 #endif // SOXT_DEBUG
413 return FALSE;
414 } // getResource()
415
416 // *************************************************************************
417
418 /*!
419 This method retrieves the given X resource and puts it into the
420 float \a retval.
421
422 TRUE is returned if the resource is found, and FALSE otherwise.
423 */
424
425 SbBool
getResource(const char * const rname,const char * const rclass,float & retval) const426 SoXtResource::getResource(
427 const char * const rname,
428 const char * const rclass,
429 float & retval) const
430 {
431 GET_RESOURCE();
432
433 XrmQuark stringq = XrmStringToQuark(XmRString);
434 XrmQuark floatq = XrmStringToQuark(XmRFloat);
435
436 if (formatstr != NULL)
437 format = XrmStringToQuark(formatstr);
438
439 if (format == floatq) {
440 retval = *((float *) value.addr);
441 return TRUE;
442 }
443
444 if (format == stringq) {
445 retval = atof((char *) value.addr);
446 return TRUE;
447 }
448
449 #if SOXT_DEBUG
450 SoDebugError::postInfo("getResource",
451 "resource format \"%s\" not supported\n", XrmQuarkToString(format));
452 #endif // SOXT_DEBUG
453 return FALSE;
454 } // getResource()
455
456 // *************************************************************************
457
upcase(char letter)458 inline char upcase(char letter) {
459 if (letter >= 'a' && letter <= 'z')
460 return letter - 'a' + 'A';
461 return letter;
462 }
463
464 int
icstrcmp(const char * str1,const char * str2)465 icstrcmp(
466 const char * str1,
467 const char * str2)
468 {
469 int i = 0;
470 while (str1[i] && (upcase(str1[i]) == upcase(str2[i]))) i++;
471 return str2[i] - str1[i];
472 } // icstrcmp()
473
474 // *************************************************************************
475
476 #if SOXT_DEBUG
getSoXtResourceRCSId(void)477 static const char * getSoXtResourceRCSId(void) { return rcsid; }
478 #endif // SOXT_DEBUG
479
480