Bug Summary

File:ResConfig.c
Location:line 728, column 6
Description:Array access (from variable 'remainder') results in a null pointer dereference

Annotated Source Code

1/*
2
3Copyright 1987, 1988, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26/*****************************************************************
27
28(C) COPYRIGHT International Business Machines Corp. 1992,1997
29 All Rights Reserved
30
31Permission is hereby granted, free of charge, to any person obtaining a copy
32of this software and associated documentation files (the "Software"), to deal
33in the Software without restriction, including without limitation the rights
34to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35copies of the Software.
36
37The above copyright notice and this permission notice shall be included in
38all copies or substantial portions of the Software.
39
40THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43THE IBM CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
44BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
45WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
46IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
47
48Except as contained in this notice, the name of the IBM Corporation shall
49not be used in advertising or otherwise to promote the sale, use or other
50dealings in this Software without prior written authorization from the IBM
51Corporation.
52
53******************************************************************/
54
55#ifdef HAVE_CONFIG_H1
56#include <config.h>
57#endif
58#include "Intrinsic.h"
59#include "IntrinsicI.h"
60#include "Core.h"
61#include "CoreP.h"
62#include "ShellP.h"
63#include "StringDefs.h"
64#include "ResConfigP.h"
65#include <X11/Xatom.h>
66#include <stdio.h>
67#include <stdlib.h>
68
69#define MAX_BUFFER512 512
70
71static void _search_child(Widget, char *, char *, char *, char *, char, char *);
72static void _set_and_search(Widget, char *, char *, char *, char *, char , char *);
73static int _locate_children(Widget, Widget **);
74
75#if defined(sun) && !defined(SVR4)
76# define Strtoul(a,b,c)strtoul(a,b,c) (unsigned long)strtol(a,b,c)
77#else
78# define Strtoul(a,b,c)strtoul(a,b,c) strtoul(a,b,c)
79#endif
80
81
82/*
83 * NAME: _set_resource_values
84 *
85 * FUNCTION:
86 * This function sets the value on the widget. It must first determine
87 * if the last part is a valid resource for that widget. (eg.
88 * labelString is a valid resource for label but not for bulletin board)
89 * It must also add the resource to the application's resource database
90 * and then query it out using specific resource strings that it builds
91 * from the widget information. This ensures that a customizing tool
92 * on-the-fly paradigm is followed: an application that is
93 * instantaneously updated should look the same as one that is restarted
94 * and uses the .Xdefaults file.
95 *
96 * PARAMETERS:
97 * w the widget to match
98 * resource the resource string to be matched
99 * value the value to be set
100 * last_part the last resource part (e.g. *background)
101 *
102 * RETURN VALUES: void
103 *
104 * ERRORS: none
105 */
106static void
107_set_resource_values (
108 Widget w,
109 char *resource,
110 char *value,
111 char *last_part)
112{
113 XrmDatabase db = NULL((void*)0);
114 char *resource_name = NULL((void*)0);
115 char *resource_class = NULL((void*)0);
116 char *return_type;
117 XrmValue return_value;
118 char *resource_value;
119 Widget cur = w;
120 char *temp;
121 XtResourceList resources_return = NULL((void*)0);
122 Cardinal num_resources_return = 0;
123 Cardinal res_index;
124 Boolean found_resource = False0;
125 Display *dpy;
126 XrmDatabase tmp_db;
127
128 if (!XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
)
129 dpy = XtDisplay (w->core.parent)(((w->core.parent)->core.screen)->display);
130 else
131 dpy = XtDisplay (w)(((w)->core.screen)->display);
132 tmp_db = XtDatabase(dpy);
133
134 /*
135 * get a list of all the valid resources for this widget
136 */
137 XtGetResourceList (w->core.widget_class,
138 &resources_return, &num_resources_return);
139
140 /*
141 * try to match the last_part of the resource string with
142 * a resource in this resource list
143 */
144 for (res_index=0; res_index<num_resources_return; res_index++) {
145 if ((strcmp (last_part,
146 resources_return[res_index].resource_name) == 0) ||
147 (strcmp (last_part,
148 resources_return[res_index].resource_class) == 0)) {
149 found_resource = True1;
150 break;
151 }
152 }
153
154 /*
155 * if resource is not a valid resource for this widget
156 * or the resource name or class are NULL
157 * then exit this function
158 */
159 if (!found_resource
160 || !resources_return[res_index].resource_name
161 || !resources_return[res_index].resource_class) {
162 XtFree ((char *) resources_return);
163 return;
164 }
165
166 /*
167 * build the full resource name and class specifications so
168 * that you can query the resource database
169 * eg: .app.button1.foreground
170 * .App.XmPushButton.Foreground
171 */
172 while (cur != NULL((void*)0)) {
173 /*
174 * create resource name string
175 */
176 if (resource_name) {
177 XtAsprintf (&temp, ".%s%s", cur->core.name, resource_name);
178 XtFree (resource_name);
179 } else if (!XtIsWidget (cur)(((Object)(cur))->object.widget_class->core_class.class_inited
& 0x04)
|| !cur->core.name) {
180 cur = XtParent(cur)((cur)->core.parent);
181 continue;
182 } else {
183 XtAsprintf (&temp, ".%s", cur->core.name);
184 }
185 resource_name = temp;
186
187 /*
188 * create resource class string
189 */
190 if ((XtIsTopLevelShell (cur)(((Object)(cur))->object.widget_class->core_class.class_inited
& 0x80)
) && (XtParent (cur)((cur)->core.parent) == NULL((void*)0))) {
191 ApplicationShellWidget top =
192 (ApplicationShellWidget) (cur);
193
194 if (resource_class) {
195 XtAsprintf (&temp, ".%s%s",
196 top->application.class, resource_class);
197 } else {
198 XtAsprintf (&temp, ".%s",
199 top->application.class);
200 }
201 } else {
202 if (resource_class) {
203 XtAsprintf (&temp, ".%s%s",
204 cur->core.widget_class->core_class.class_name,
205 resource_class);
206 } else {
207 XtAsprintf (&temp, ".%s",
208 cur->core.widget_class->core_class.class_name);
209 }
210 }
211 if (resource_class != NULL((void*)0))
212 XtFree (resource_class);
213 resource_class = temp;
214
215 cur = XtParent(cur)((cur)->core.parent);
216 }
217
218 /*
219 * add the resource name to the end of the resource name string
220 */
221 XtAsprintf (&temp, "%s.%s", resource_name,
222 resources_return[res_index].resource_name);
223 if (resource_name != NULL((void*)0))
224 XtFree (resource_name);
225 resource_name = temp;
226
227 /*
228 * add the resource class to the end of the resource class string
229 */
230 XtAsprintf (&temp, "%s.%s", resource_class,
231 resources_return[res_index].resource_class);
232 if (resource_class != NULL((void*)0))
233 XtFree (resource_class);
234 resource_class = temp;
235
236#ifdef DEBUG
237 fprintf (stderrstderr, "resource_name = %s\n", resource_name);
238 fprintf (stderrstderr, "resource_class = %s\n", resource_class);
239#endif
240
241 /*
242 * put the resource and its value in a resource database and
243 * then query it back out again using the specific name and
244 * class resource strings that were built above. This is
245 * necessary to maintain a precedence similar to the .Xdefaults
246 * file
247 */
248 XrmPutStringResource (&db, resource, value);
249 XrmMergeDatabases (db, &tmp_db);
250 XrmGetResource (tmp_db, resource_name, resource_class,
251 &return_type, &return_value);
252 if (return_type)
253 resource_value = XtNewString (return_value.addr)((return_value.addr) != ((void*)0) ? (strcpy(XtMalloc((unsigned
)strlen(return_value.addr) + 1), return_value.addr)) : ((void
*)0))
;
254 else
255 resource_value = XtNewString (value)((value) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(value
) + 1), value)) : ((void*)0))
;
256
257#ifdef DEBUG
258 fprintf (stderrstderr,
259 "Apply:\n\twidget = %s\n\tlast_part = %s\n\tvalue = %s\n",
260 (w->core.name == NULL((void*)0)) ? "NULL" : w->core.name,
261 resources_return[res_index].resource_name,
262 resource_value);
263#endif
264 /*
265 * use XtVaSetValues with XtVaTypedArg to convert the value of
266 * type String the the same type as the resource (last_part).
267 * Then set the value.
268 */
269 XtVaSetValues (w,
270 XtVaTypedArg"XtVaTypedArg", resources_return[res_index].resource_name,
271 XtRString((char*)&XtStrings[1797]), resource_value,
272 strlen (resource_value) + 1,
273 NULL((void*)0));
274
275 XtFree ((char *) resources_return);
276 XtFree (resource_name);
277 XtFree (resource_class);
278 XtFree (resource_value);
279}
280
281/*
282 * NAME: _apply_values_to_children
283 *
284 * FUNCTION:
285 * Once the resource string matches the value must be applied to
286 * all children if applicable. (eg. App*Form.background must apply
287 * background to all children of the Form widget)
288 *
289 * PARAMETERS:
290 * w the widget to match
291 * remainder the part of the resource string left over
292 * resource the resource string to be matched
293 * value the value to be set
294 * last_token the last * or . before the final resoruce part
295 * last_part the last resource part (e.g. *background)
296 *
297 * RETURN VALUES: void
298 *
299 * ERRORS: none
300 */
301static void
302_apply_values_to_children (
303 Widget w,
304 char *remainder,
305 char *resource,
306 char *value,
307 char last_token,
308 char *last_part)
309{
310 int i;
311 int num_children;
312 Widget *children;
313
314 /*
315 * Recursively search through the children
316 */
317 num_children = _locate_children (w, &children);
318
319 for (i=0; i<num_children; i++) {
320
321#ifdef DEBUG
322 if (XtIsWidget (children[i])(((Object)(children[i]))->object.widget_class->core_class
.class_inited & 0x04)
&& XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
)
323 fprintf (stderrstderr, "searching child %s of parent %s\n",
324 children[i]->core.name, w->core.name);
325 else
326 fprintf (stderrstderr,"searching child (NULL) of parent %s\n",
327 w->core.name);
328 if (!XtIsWidget (children[i])(((Object)(children[i]))->object.widget_class->core_class
.class_inited & 0x04)
)
329 fprintf (stderrstderr, "children[%d] is NOT a widget\n", i);
330 if (!XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
)
331 fprintf (stderrstderr, "w is NOT a widget\n");
332#endif
333
334 _set_resource_values (children[i], resource, value, last_part);
335 _apply_values_to_children (children[i], remainder,
336 resource, value, last_token, last_part);
337 }
338
339 XtFree ((char *)children);
340}
341
342/*
343 * NAME: _search_child
344 *
345 * FUNCTION:
346 * descends through each child of the tree
347 *
348 * PARAMETERS:
349 * w the widget whose children are to be searched
350 * indx index into the resource string
351 * remainder the remaining part of the resource string
352 * resource the resource string to be matched
353 * value the value to be applied
354 * last_token the last * or . before the final resoruce part
355 * last_part the last resource part (e.g. *background)
356 *
357 * RETURN VALUES: none
358 *
359 * ERRORS: none
360 */
361static void
362_search_child (
363 Widget w,
364 char *indx,
365 char *remainder,
366 char *resource,
367 char *value,
368 char last_token,
369 char *last_part)
370{
371 int i;
372 int num_children;
373 Widget *children;
374
375 /*
376 * Recursively search through the children
377 */
378 num_children = _locate_children (w, &children);
379 for (i=0; i<num_children; i++) {
380 _set_and_search (children[i], indx, remainder, resource,
381 value, last_token, last_part);
382 }
383
384 XtFree ((char *)children);
385}
386
387/*
388 * NAME: _get_part
389 *
390 * FUNCTION:
391 * This routine will return the token and following part of the resource
392 * when given the current index it will update the index accordingly
393 *
394 * PARAMETERS:
395 * remainder the part of the resource string left over
396 * indx the index into the resource string
397 * part the parsed off part of the resource string
398 *
399 * RETURN VALUES:
400 * char the token (* or . or ?) preceding the resource part
401 * indx the index into the resource string
402 * part the parsed off part of the resource string
403 *
404 * ERRORS: none
405 */
406/* ARGSUSED */
407static char
408_get_part (
409 char *remainder,
410 char **indx,
411 char **part)
412{
413 char buffer[MAX_BUFFER512];
414 char *buf_ptr;
415 char token = **indx;
416 int i = 0;
417
418 /*
419 * copy the remainder part into the buffer
420 */
421 buf_ptr = buffer;
422 (*indx)++; /* get rid of the token */
423 while (**indx && (**indx != '.') && (**indx != '*')) {
424 *buf_ptr++ = *(*indx)++;
425 if (++i >= MAX_BUFFER512 - 1)
426 break;
427 }
428 *buf_ptr = '\0';
429
430 *part = XtNewString (buffer)((buffer) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(buffer
) + 1), buffer)) : ((void*)0))
; /* return a new string to part */
431
432 if (strcmp (*indx, "") == 0)
433 *indx = NULL((void*)0);
434
435 return (token); /* return the token */
436}
437
438/*
439 * NAME: _match_resource_to_widget
440 *
441 * FUNCTION:
442 * This function matches the resource part to the widget name or class
443 *
444 * PARAMETERS:
445 * w the widget to match
446 * part the parsed off part of the resource string
447 *
448 * RETURN VALUES:
449 * Boolean true if a match occurs
450 *
451 * ERRORS: none
452 */
453static Boolean
454_match_resource_to_widget (
455 Widget w,
456 char *part)
457{
458 /*
459 * Match any widget at this level if the ? is used
460 */
461 if (strcmp (part, "?") == 0)
462 return (True1);
463
464 /*
465 * if the object is really a widget then its name can be matched
466 * otherwise only use its class. Note that if you try to reference
467 * a widget name when the object is not a widget, you may get a
468 * core dump from an invalid pointer reference.
469 */
470 if (XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
) {
471 if ((strcmp (w->core.name, part) == 0) ||
472 (strcmp (w->core.widget_class->core_class.class_name,
473 part) == 0))
474 return (True1);
475 else
476 return (False0);
477 } else {
478 if ((strcmp (w->core.widget_class->core_class.class_name,
479 part) == 0))
480 return (True1);
481 else
482 return (False0);
483 }
484}
485
486/*
487 * NAME: _set_and_search
488 *
489 * FUNCTION:
490 * The algorithm to search the widget tree and apply a resource string
491 *
492 * PARAMETERS:
493 * w the widget to match
494 * indx the index into the resource string
495 * remainder the part of the resource string left over
496 * resource the resource string to be matched
497 * value the value to be set
498 * last_token the last * or . before the final resoruce part
499 * last_part the last resource part (e.g. *background)
500 *
501 * RETURN VALUES: none
502 *
503 * ERRORS: none
504 *
505 * ALGORITHM:
506 * loop (look at all children)
507 * if (resource segment and current widget match)
508 * if '.'
509 * if at end of resource string
510 * set values ( .=over all children
511 * *=this widget only)
512 * else
513 * descend the widget tree
514 * and parse off resource segment
515 * exit the loop
516 * if '*'
517 * if at end of resource string
518 * set values ( .=over all children
519 * *=this widget only)
520 * descend and parse
521 * else
522 * if '.'
523 * continue looping
524 * if '*'
525 * descend but don't parse
526 * continue looping
527 * end loop
528 *
529 * NOTE: the _set_resource_values routine will not allow a value to be
530 * set on a resource against the rules of the resource database manager
531 */
532static void
533_set_and_search (
534 Widget w,
535 char *indx,
536 char *remainder,
537 char *resource,
538 char *value,
539 char last_token,
540 char *last_part)
541{
542 char *part;
543 char *local_index = indx;
544 char token;
545
546 /*
547 * parse off one part, return token and the new index
548 */
549 token = _get_part (remainder, &local_index, &part);
550
551 if (_match_resource_to_widget (w, part)) {
552 if (token == '.') {
553 if (local_index == NULL((void*)0)) {
554 if (last_token == '.') {
555 _set_resource_values (w, resource,
556 value, last_part);
557 } else if (last_token == '*') {
558 _set_resource_values (w, resource,
559 value, last_part);
560 _apply_values_to_children (w,
561 remainder, resource, value,
562 last_token, last_part);
563 }
564 } else
565 _search_child (w, local_index, remainder,
566 resource, value, last_token, last_part);
567 return;
568 }
569 if (token == '*') {
570 if (local_index == NULL((void*)0)) {
571 if (last_token == '.') {
572 _set_resource_values (w, resource,
573 value, last_part);
574 } else if (last_token == '*') {
575 _set_resource_values (w, resource,
576 value, last_part);
577 _apply_values_to_children ( w,
578 remainder, resource, value,
579 last_token, last_part);
580 }
581 } else
582 _search_child (w, local_index, remainder,
583 resource, value, last_token, last_part);
584 }
585 } else {/* if the widget name and class don't match the part */
586 /* if (token == '.') just continue looping */
587
588 if (token == '*') {
589 _search_child (w, indx, remainder, resource, value,
590 last_token, last_part);
591 }
592 }
593
594 XtFree (part);
595}
596
597/*
598 * NAME: _get_last_part
599 *
600 * FUNCTION:
601 * This routine will parse off the last segment of a resource string
602 * and its token and return them. the remainder of resource is also
603 * returned. strcoll is used to guarantee no problems with
604 * international strings.
605 *
606 * PARAMETERS:
607 * remainder the part of the resource string left over
608 * part the parsed off part of the resource string
609 *
610 * RETURN VALUES:
611 * char the token (* or . or ?) preceding the resource part
612 * remainder the part of the resource string left over
613 * part the parsed off part of the resource string
614 *
615 * ERRORS: none
616 */
617static char
618_get_last_part (
619 char *remainder,
620 char **part)
621{
622 char *loose, *tight;
623
624 loose = strrchr (remainder, '*');
625 tight = strrchr (remainder, '.');
626
627 if ((loose == NULL((void*)0)) && (tight == NULL((void*)0))) {
628 *part = XtNewString (remainder)((remainder) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen
(remainder) + 1), remainder)) : ((void*)0))
;
629 return ('.');
630 }
631 if ((loose == NULL((void*)0)) || (tight && (strcoll (loose, tight) < 0))) {
632 *tight++ = '\0'; /* shorten the remainder string */
633 *part = XtNewString (tight)((tight) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(tight
) + 1), tight)) : ((void*)0))
;
634 return ('.');
635 }
636 if ((tight == NULL((void*)0)) || (loose && (strcoll (tight, loose) < 0))) {
637 *loose++ = '\0';
638 *part = XtNewString (loose)((loose) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(loose
) + 1), loose)) : ((void*)0))
;
639 return ('*');
640 }
641 *part = NULL((void*)0);
642
643 return ('0'); /* error - return 0 */
644}
645
646/*
647 * NAME: _search_widget_tree
648 *
649 * FUNCTION:
650 * This function tries to match a resource string to the widgets
651 * it applies to. The functions it invokes to do this then set
652 * the value for that resource to each widget.
653 *
654 * The resource string has to be parsed into the following format:
655 * resource = App*Form*button1.background
656 * remainder = *Form*button1
657 * last_part = background last_token = .
658 * As the widget tree is recursively descended, these variables are
659 * passed. The remainder is parsed at each level in the widget
660 * tree as the _set_and_search function attempts to match
661 * the resource part (eg. part = Form token = *) to a widget. When
662 * the entire resource string has been matched, the _set_resource_values
663 * functions is called to apply the value to the widget or widgets.
664 *
665 * PARAMETERS:
666 * w a widget from whose toplevel shell ancestor
667 * the search will start
668 * resource the resource string to match
669 * value the value to apply
670 *
671 * RETURN VALUES: none
672 *
673 * ERRORS: none
674 */
675static void
676_search_widget_tree (
677 Widget w,
678 char *resource,
679 char *value)
680{
681 Widget parent = w;
682 char *last_part;
683 char *remainder = NULL((void*)0);
684 char last_token;
685 char *indx, *copy;
686 char *loose, *tight;
687 int loose_len, tight_len;
688
689 /*
690 * Find the root of the tree given any widget
691 */
692 while (XtParent(parent)((parent)->core.parent) != NULL((void*)0)) {
1
Loop condition is false. Execution continues on line 707
693 parent = XtParent(parent)((parent)->core.parent);
694 }
695#ifdef DEBUG
696 if (XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
&& XtIsWidget (parent)(((Object)(parent))->object.widget_class->core_class.class_inited
& 0x04)
)
697 fprintf (stderrstderr, "widget = %s parent = %s\n",
698 w->core.name, parent->core.name);
699 else
700 fprintf (stderrstderr, "widget = NULL parent = NULL\n");
701#endif
702
703 /*
704 * parse off the Class name that was prepended to this string in
705 * a customizing tool
706 */
707 loose = strchr (resource, '*');
708 tight = strchr (resource, '.');
709 if ((loose == NULL((void*)0)) && (tight == NULL((void*)0)))
2
Assuming 'loose' is not equal to null
3
Taking false branch
710 return;
711
712 loose_len = (loose) ? strlen (loose) : 0;
4
'?' condition is true
713 tight_len = (tight) ? strlen (tight) : 0;
5
Assuming 'tight' is non-null
6
'?' condition is true
714
715 if ((loose == NULL((void*)0)) || (tight_len > loose_len))
7
Taking false branch
716 remainder = XtNewString (tight)((tight) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(tight
) + 1), tight)) : ((void*)0))
;
717 else if ((tight == NULL((void*)0)) || (loose_len > tight_len))
8
Taking false branch
718 remainder = XtNewString (loose)((loose) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen(loose
) + 1), loose)) : ((void*)0))
;
719
720 /*
721 * Parse last segment off of resource string, (eg. background, font,
722 * etc.)
723 */
724 last_token = _get_last_part (remainder, &last_part);
725 /*
726 * this case covers resources of only one level (eg. *background)
727 */
728 if (remainder[0] == 0) {
9
Array access (from variable 'remainder') results in a null pointer dereference
729 _set_resource_values (w, resource, value, last_part);
730 if (last_token == '*')
731 _apply_values_to_children (parent, remainder, resource,
732 value, last_token, last_part);
733 /*
734 * all other resource strings are recursively applied to the widget tree.
735 * Prepend a '.' to the remainder string if there is no leading token.
736 */
737 } else {
738 if (remainder[0] != '*' && remainder[0] != '.') {
739 XtAsprintf (&copy, ".%s", remainder);
740 XtFree (remainder);
741 remainder = copy;
742 }
743 indx = remainder;
744 _set_and_search (parent, indx, remainder, resource, value,
745 last_token, last_part);
746 }
747
748 XtFree (remainder);
749 XtFree (last_part);
750}
751
752/*
753 * NAME: _locate_children
754 *
755 * FUNCTION:
756 * returns a list of all of a widget's children
757 *
758 * PARAMETERS:
759 * w the parent to search for its children
760 * children the list of children that is created
761 * normal flag for normal children
762 * popup flag for popup children
763 *
764 * RETURN VALUES:
765 * int the number of children
766 * children the list of children found
767 *
768 * ERRORS: none
769 */
770static int
771_locate_children (
772 Widget parent,
773 Widget **children)
774{
775 CompositeWidget comp = (CompositeWidget) parent;
776 Cardinal i;
777 int num_children = 0;
778 int current = 0;
779
780 /*
781 * count the number of children
782 */
783 if (XtIsWidget (parent)(((Object)(parent))->object.widget_class->core_class.class_inited
& 0x04)
)
784 num_children += parent->core.num_popups;
785 if (XtIsComposite (parent)(((Object)(parent))->object.widget_class->core_class.class_inited
& 0x08)
)
786 num_children += comp->composite.num_children;
787 if (num_children == 0) {
788 *children = NULL((void*)0);
789 return (0);
790 }
791
792 *children = (Widget *)
793 XtMalloc ((Cardinal) sizeof(Widget) * num_children);
794
795 if (XtIsComposite (parent)(((Object)(parent))->object.widget_class->core_class.class_inited
& 0x08)
) {
796 for (i=0; i<comp->composite.num_children; i++) {
797 (*children)[current] = comp->composite.children[i];
798 current++;
799 }
800 }
801
802 if (XtIsWidget (parent)(((Object)(parent))->object.widget_class->core_class.class_inited
& 0x04)
) {
803 for (i=0; i<parent->core.num_popups; i++) {
804 (*children)[current] = comp->core.popup_list[i];
805 current++;
806 }
807 }
808
809 return (num_children);
810}
811
812#ifdef DEBUG
813/*
814 * NAME: dump_widget_tree
815 *
816 * FUNCTION:
817 * recursively printout entire widget tree
818 *
819 * PARAMETERS:
820 * w the widget to match
821 * indent the amount to indent each line
822 *
823 * RETURN VALUES: void
824 *
825 * ERRORS: none
826 */
827static void
828dump_widget_tree (
829 Widget w,
830 int indent)
831{
832 int i,j;
833 int num_children;
834 Widget *children;
835
836 /*
837 * Recursively search through the children
838 */
839 num_children = _locate_children (w, &children);
840 indent += 2;
841 for (i=0; i<num_children; i++) {
842 if (children[i] != NULL((void*)0)) {
843 for (j=0; j<indent; j++)
844 fprintf (stderrstderr, " ");
845 if (XtIsWidget (children[i])(((Object)(children[i]))->object.widget_class->core_class
.class_inited & 0x04)
) {
846 fprintf (stderrstderr, "(%s)\t",children[i]->core.name);
847 fprintf (stderrstderr, "(%s)\n",
848 children[i]->core.widget_class->core_class.class_name);
849 } else {
850 fprintf (stderrstderr, "(NULL)\t");
851 fprintf (stderrstderr, "(%s)\n",
852 children[i]->core.widget_class->core_class.class_name);
853 }
854 }
855 dump_widget_tree (children[i], indent);
856 }
857
858 XtFree ((char *)children);
859}
860#endif
861
862/*
863 * NAME: _XtResourceConfiguationEH
864 *
865 * FUNCTION:
866 * This function is the event handler for the on-the-fly communication
867 * with a resource customization tool. This event handler must be
868 * registered for the toplevel shell of each app. This is best done
869 * in the _XtCreatePopupShell and _XtAppCreateShell functions in Xt's
870 * Create.c source file.
871 *
872 * The property used to communicate with a customizing tool is
873 * placed on the toplevel shell window of the application. The
874 * customizing tool places a property on this window which causes
875 * this event handler to be invoked via the PropertyNotify event.
876 * This event handler reads the property and then deletes it from
877 * the server. The contents of the property are a resource string
878 * and value. The event handler then calls functions to walk the
879 * applications widget tree, determining which widgets are affected
880 * by the resource string, and then applying the value with XtSetValues.
881 *
882 * PARAMETERS:
883 * w the widget that invoked this event handler
884 * client_data not used
885 * event the event structure
886 *
887 * RETURN VALUES: none
888 *
889 * ERRORS: none
890 */
891/* ARGSUSED */
892void
893_XtResourceConfigurationEH (
894 Widget w,
895 XtPointer client_data,
896 XEvent *event)
897{
898 Atom actual_type;
899 int actual_format;
900 unsigned long nitems;
901 unsigned long leftover;
902 unsigned char *data = NULL((void*)0);
903 unsigned long resource_len;
904 char *data_ptr;
905 char *resource;
906 char *value;
907#ifdef DEBUG
908 int indent = 0;
909#endif
910 XtPerDisplay pd;
911
912#ifdef DEBUG
913 fprintf (stderrstderr, "in _XtResourceConfiguationEH atom = %d\n",event->xproperty.atom);
914 fprintf (stderrstderr, " window = %x\n", XtWindow (w)((w)->core.window));
915 if (XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
)
916 fprintf (stderrstderr, " widget = %x name = %s\n", w, w->core.name);
917#endif
918
919 pd = _XtGetPerDisplay (XtDisplay (w)(((w)->core.screen)->display));
920
921 /*
922 * The window on which a customizing tool places the property
923 * is determined at this point. It should be the applications
924 * toplevel shell window.
925 *
926 * A customizing tool sends a "ping" to the application on
927 * the RCM_INIT property. The application answers the ping
928 * by deleting the property.
929 */
930 if (event->xproperty.atom == pd->rcm_init) {
931 XDeleteProperty (XtDisplay(w)(((w)->core.screen)->display), XtWindow (w)((w)->core.window), pd->rcm_init);
932
933#ifdef DEBUG
934 if (XtIsWidget (w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
)
935 fprintf (stderrstderr, "%s\n", w->core.name);
936 else
937 fprintf (stderrstderr, "NULL name\n");
938 dump_widget_tree(w, indent);
939
940 fprintf (stderrstderr, "answer ping\n");
941#endif
942 }
943
944 /*
945 * This event handler ignores any property notify events that
946 * are not RCM_INIT or RCM_DATA
947 */
948 if (event->xproperty.atom != pd->rcm_data)
949 return;
950
951 /*
952 * Retrieve the data from the property
953 */
954#ifdef DEBUG
955 fprintf (stderrstderr, "receiving RCM_DATA property\n");
956#endif
957 if (XGetWindowProperty (XtDisplay(w)(((w)->core.screen)->display),
958 XtWindow (w)((w)->core.window),
959 pd->rcm_data, 0L, 8192L,
960 TRUE1, XA_STRING((Atom) 31),
961 &actual_type, &actual_format, &nitems, &leftover,
962 &data ) == Success0 && actual_type == XA_STRING((Atom) 31)
963 && actual_format == 8) {
964 /*
965 * data format is:
966 *
967 * resource_length, resource, value
968 *
969 * convert the resource_length to a long, skip over it, put a
970 * zero byte at the end of the resource, and pick off the
971 * resource and value fields.
972 */
973 if (data) {
974 resource_len = Strtoul ((void *)data, &data_ptr, 10)strtoul((void *)data,&data_ptr,10);
975 data_ptr++;
976
977 data_ptr[resource_len] = '\0';
978
979 resource = XtNewString (data_ptr)((data_ptr) != ((void*)0) ? (strcpy(XtMalloc((unsigned)strlen
(data_ptr) + 1), data_ptr)) : ((void*)0))
;
980 value = XtNewString (&data_ptr[resource_len + 1])((&data_ptr[resource_len + 1]) != ((void*)0) ? (strcpy(XtMalloc
((unsigned)strlen(&data_ptr[resource_len + 1]) + 1), &
data_ptr[resource_len + 1])) : ((void*)0))
;
981#ifdef DEBUG
982 fprintf (stderrstderr, "resource_len=%d\n",resource_len);
983 fprintf (stderrstderr, "resource = %s\t value = %s\n",
984 resource, value);
985#endif
986 /*
987 * descend the application widget tree and
988 * apply the value to the appropriate widgets
989 */
990 _search_widget_tree (w, resource, value);
991
992 XtFree (resource);
993 XtFree (value);
994 }
995 }
996
997 if (data)
998 XFree ((char *)data);
999}