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