1 /*----------------------------------------------------------------------------
2 //
3 // Module: xmubCustUtil
4 //
5 // Project: <>
6 // System: <>
7 // Subsystem: <>
8 // Function block: <>
9 //
10 // Description:
11 // <>
12 //
13 // Contents:
14 // <>
15 //
16 // Filename: xmubCustUtil.c
17 //
18 // Author: Ulrika Bornetun
19 // Creation date: 13.10.1994
20 //
21 // Modifications:
22 //
23 // Version / When / Who
24 // What
25 // --------------------------------------------
26 // %StartLog%
27 // %EndLog%
28 //
29 //
30 // Copyright 1994 by Union Bank of Switzerland.
31 //
32 // Permission to use, copy, modify, and distribute this software and its
33 // documentation for any purpose and without fee is hereby granted,
34 // provided that the above copyright notice appear in all copies.
35 // Union Bank of Switzerland makes no representations about the usability
36 // of this software for any purpose. It is provided "as is" without express
37 // or implied warranty.
38 //--------------------------------------------------------------------------*/
39
40 /* SCCS module identifier. */
41 #ifndef lint
42 static char SCCSID[] = "@(#) Module: xmubCustUtil.c, Version: 1.1, Date: 95/02/18 15:10:53";
43 #endif
44
45 /*----------------------------------------------------------------------------
46 // Include files
47 ----------------------------------------------------------------------------*/
48
49 #ifdef VMS
50 #include ctype
51 #include stdlib
52 #include stdio
53 #include string
54 #include "xmubCustUtil.h"
55
56 #else
57 #include <sys/types.h>
58 #include <unistd.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <string.h>
62 #include <ctype.h>
63
64 #include <xmubCustUtil.h>
65
66 #endif
67
68
69 #include <X11/Shell.h>
70
71 /* TEST */
72 /* #undef XlibSpecificationRelease */
73 /* #define XlibSpecificationRelease 4 */
74
75 /*----------------------------------------------------------------------------
76 // Macro definitions
77 ----------------------------------------------------------------------------*/
78
79 /* Definitions used for the mapping file. */
80 #define RESMAP_FILE_NAME "xresource.map"
81 #define MAP_FILE_NAME "xresource"
82 #define MAP_FILE_SUFFIX ".map"
83 #define MAP_FILE_DIRTYPE "app-defaults"
84 #define XRESOURCE_MAP_FILE "XRESOURCE_MAP_FILE"
85
86 /* Defaults. */
87 #define DEFAULT_DELIMITERS " "
88
89 /* "Functions" */
90 #define Max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
91
92 #ifdef VMS
93 #define unlink( filename ) delete( filename )
94 #endif
95
96 #define BUFFER_LENGTH 200
97
98 #if XlibSpecificationRelease < 5
99 #define XrmEnumAllLevels 0
100 #define XrmEnumOneLevel 1
101 #endif
102
103 /*----------------------------------------------------------------------------
104 // Type declarations
105 ----------------------------------------------------------------------------*/
106
107 typedef struct
108 {
109 xmubResourceMappingInfoRef info;
110 XrmQuark keyword_quark;
111 XrmQuark *sets;
112 int num_sets;
113 int set_list_length;
114
115 } ListClassesInfo;
116
117 #if XlibSpecificationRelease < 5
118 typedef void* XPointer;
119 #endif
120
121 typedef Bool (*LoopDatabaseProc)
122 ( XrmDatabase*, XrmBindingList, XrmQuarkList, XrmRepresentation*,
123 XrmValue*, XPointer );
124
125 /*
126 // The parameters for the LoopDatabaseProc function are the same as for
127 // the function called by XrmEnumerateDatabase in X11R5.
128 */
129
130
131 /*----------------------------------------------------------------------------
132 // Global definitions
133 ----------------------------------------------------------------------------*/
134
135 XrmOptionDescRec xmub_options[] = {
136 { "-palette", "*palette", XrmoptionSepArg, NULL },
137 { "-fmap", "*fmap", XrmoptionSepArg, NULL },
138 };
139
140 Cardinal xmub_num_options = XtNumber( xmub_options );
141
142 xmubAppResDesc xmub_resource_sets[] = {
143 { "palette", "Palette" },
144 { "fmap", "Fmap" } };
145
146 Cardinal xmub_num_resource_sets = XtNumber( xmub_resource_sets );
147
148 /*----------------------------------------------------------------------------
149 // Function prototypes
150 ----------------------------------------------------------------------------*/
151
152
153 static Bool
154 ExtractKeywordClass( XrmDatabase *db,
155 XrmBindingList bindings,
156 XrmQuarkList quarks,
157 XrmRepresentation *type,
158 XrmValue *value,
159 XPointer closure );
160
161 static Boolean
162 FileReadAccess( char* file_name );
163
164 static void
165 GetResourceValues( xmubResourceMappingInfoRef info,
166 xmubAppResDesc resource_sets[],
167 Cardinal num_resource_sets,
168 char** values );
169
170 static Bool
171 InsertGeneralMappingResources( XrmDatabase *db,
172 XrmBindingList bindings,
173 XrmQuarkList quarks,
174 XrmRepresentation *type,
175 XrmValue *value,
176 XPointer closure );
177
178 static Bool
179 InsertSpecificMappingResources( XrmDatabase *db,
180 XrmBindingList bindings,
181 XrmQuarkList quarks,
182 XrmRepresentation *type,
183 XrmValue *value,
184 XPointer closure );
185
186 static Bool
187 LoopThroughDatabase( XrmDatabase db,
188 XrmNameList name_prefix,
189 XrmClassList class_prefix,
190 int unsupported,
191 LoopDatabaseProc proc,
192 XPointer client_data );
193 /*
194 // LoopThroughDatabase provides a simple XrmEnumerateDatabase
195 // functionality for X11R4.
196 // name_list and class_list only support lists of length 1.
197 */
198
199 static Bool
200 ModifyKeywordResource( XrmDatabase *db,
201 XrmBindingList bindings,
202 XrmQuarkList quarks,
203 XrmRepresentation *type,
204 XrmValue *value,
205 XPointer closure );
206
207 static Bool
208 ModifySubstringResource( XrmDatabase *db,
209 XrmBindingList bindings,
210 XrmQuarkList quarks,
211 XrmRepresentation *type,
212 XrmValue *value,
213 XPointer closure );
214
215 static int
216 StringComp( const void *s1,
217 const void *s2 );
218
219
220
221 /*----------------------------------------------------------------------------
222 // Functions
223 ----------------------------------------------------------------------------*/
224
225 static Bool
ExtractKeywordClass(XrmDatabase * db,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)226 ExtractKeywordClass( XrmDatabase *db,
227 XrmBindingList bindings,
228 XrmQuarkList quarks,
229 XrmRepresentation *type,
230 XrmValue *value,
231 XPointer closure )
232 {
233
234 int index;
235 int length;
236 ListClassesInfo *listinfo;
237
238 /* Code. */
239
240 listinfo = (ListClassesInfo *) closure;
241
242 /* To be valid, we must have 2 quarks, and the 2nd must match our keyword.
243 In that case, the 1st is our candidate. */
244 for( length = 0; quarks[ length ] != NULLQUARK; length ++ );
245 if( length != 2 )
246 return( False );
247
248 if( quarks[ 1 ] == listinfo -> keyword_quark ){
249 /* Insert the first one in the list. */
250
251 /* Check for duplicates. */
252 for( index = 0; index < listinfo -> num_sets; index ++ ){
253 if( quarks[ 0 ] == listinfo -> sets[ index ] )
254 return( False );
255 }
256
257 /* We can insert it. */
258 if( listinfo -> num_sets == listinfo -> set_list_length ){
259 ( listinfo -> set_list_length ) += 5;
260
261 if( listinfo -> sets == NULL )
262 listinfo -> sets = (XrmQuark *) XtMalloc(
263 sizeof( XrmQuark ) * listinfo -> set_list_length );
264
265 else
266 listinfo -> sets = (XrmQuark *) XtRealloc(
267 (char *) listinfo -> sets,
268 sizeof( XrmQuark ) * listinfo -> set_list_length );
269 }
270
271 listinfo -> sets[ listinfo -> num_sets ] = quarks[ 0 ];
272 ( listinfo -> num_sets ) ++;
273
274 }
275
276
277 return( False );
278
279 }
280
281
282 /*----------------------------------------------------------------------*/
283
284 static Boolean
FileReadAccess(char * file_name)285 FileReadAccess( char* file_name )
286 {
287 /* This function is a replacement for the POSIX function access. */
288 FILE* file;
289
290 file = fopen( file_name, "r" );
291
292 if( file == NULL )
293 return False;
294
295 fclose( file );
296
297 return True;
298
299 }
300
301
302 /*----------------------------------------------------------------------*/
303
304 static void
GetResourceValues(xmubResourceMappingInfoRef info,xmubAppResDesc resource_sets[],Cardinal num_resource_sets,char ** values)305 GetResourceValues( xmubResourceMappingInfoRef info,
306 xmubAppResDesc resource_sets[],
307 Cardinal num_resource_sets,
308 char** values )
309 {
310 int index;
311 int length;
312 int max_length;
313 Bool ok;
314 char* res_class;
315 char* res_name;
316 char* str_type_return;
317 XrmValue value_return;
318
319 /* Code. */
320
321 /* Check max length of strings. */
322 for( index = 0, max_length = 0; index < num_resource_sets; index ++ ){
323
324 /* Name. */
325 if( resource_sets[ index ].res_name != NULL )
326 length = strlen( resource_sets[ index ].res_name );
327 else
328 length = 0;
329
330 max_length = Max( max_length, length );
331
332 if( resource_sets[ index ].res_class != NULL )
333 length = strlen( resource_sets[ index ].res_class );
334 else
335 length = 0;
336
337 max_length = Max( max_length, length );
338
339 }
340
341 res_name = XtMalloc( max_length + strlen( info -> app_name ) + 5 );
342 res_class = XtMalloc( max_length + strlen( info -> app_class ) + 5 );
343
344
345 for( index = 0; index < num_resource_sets; index ++ ){
346 sprintf( res_name, "%s.%s", info -> app_name,
347 resource_sets[ index ].res_name );
348 sprintf( res_class, "%s.%s", info -> app_class,
349 resource_sets[ index ].res_class );
350
351 ok = XrmGetResource( XtDatabase( info -> display ), res_name, res_class,
352 &str_type_return, &value_return );
353
354 if( ok )
355 values[ index ] = XtNewString( value_return.addr );
356 else
357 values[ index ] = NULL;
358
359 }
360
361 XtFree( res_name );
362 XtFree( res_class );
363
364 }
365
366
367 /*----------------------------------------------------------------------*/
368
369 static Bool
InsertGeneralMappingResources(XrmDatabase * db,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)370 InsertGeneralMappingResources( XrmDatabase *db,
371 XrmBindingList bindings,
372 XrmQuarkList quarks,
373 XrmRepresentation *type,
374 XrmValue *value,
375 XPointer closure )
376 {
377
378 xmubResourceMappingInfoRef info;
379
380 /* Code. */
381
382 info = (xmubResourceMappingInfoRef) closure;
383
384 /* The resource should just be inserted in the translation database. */
385 XrmQPutResource( &( info -> translation_db ), bindings,
386 quarks, *type, value );
387
388
389 info -> selected = True;
390
391
392 return( False );
393
394 }
395
396
397 /*----------------------------------------------------------------------*/
398
399 static Bool
InsertSpecificMappingResources(XrmDatabase * db,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)400 InsertSpecificMappingResources( XrmDatabase *db,
401 XrmBindingList bindings,
402 XrmQuarkList quarks,
403 XrmRepresentation *type,
404 XrmValue *value,
405 XPointer closure )
406 {
407
408 xmubResourceMappingInfoRef info;
409 int length;
410
411 /* Code. */
412
413 info = (xmubResourceMappingInfoRef) closure;
414
415 /* Here we will get both general and specific resources. Select just
416 the ones that are specific. */
417 /* For specific resources, the quark list is longer than one item. */
418 for( length = 0; quarks[ length ] != NULLQUARK; length ++ );
419
420 if( length > 1 ){
421
422 char *qs;
423 char *res_spec;
424
425 /* For the specific ones, we have to construct a string name. */
426 qs = XrmQuarkToString( quarks[ 1 ] );
427
428 res_spec = (char *) XtMalloc( strlen( qs ) + 5 );
429 sprintf( res_spec, "*%s", qs );
430
431 XrmPutResource( &( info -> translation_db ), res_spec,
432 XrmRepresentationToString( *type ), value );
433 XtFree( res_spec );
434
435 info -> selected = True;
436
437 }
438
439
440 return( False );
441
442 }
443
444
445 /*----------------------------------------------------------------------*/
446
447 static Bool
LoopThroughDatabase(XrmDatabase db,XrmNameList name_prefix,XrmClassList class_prefix,int unsupported,LoopDatabaseProc proc,XPointer client_data)448 LoopThroughDatabase( XrmDatabase db,
449 XrmNameList name_prefix,
450 XrmClassList class_prefix,
451 int unsupported,
452 LoopDatabaseProc proc,
453 XPointer client_data )
454 {
455
456 XrmBindingList binding_list;
457 char buffer[ BUFFER_LENGTH ];
458 FILE *db_file;
459 char db_filename[ L_tmpnam + 1 ];
460 int index;
461 int length;
462 int num_bindings;
463 XrmQuarkList quark_list;
464 Boolean selected;
465 int start_index;
466 XrmQuark string_rep;
467 Bool terminate = False;
468 XrmValue value;
469 XrmQuark wildcard_quark;
470
471 /* Code. */
472
473 /* Dump the database to a file. */
474 (void) tmpnam( db_filename );
475 XrmPutFileDatabase( db, db_filename );
476
477 db_file = fopen( db_filename, "r" );
478
479 string_rep = XrmStringToRepresentation( "String" );
480 wildcard_quark = XrmStringToQuark( "*" );
481
482
483 /* Read the resource specifications. */
484 while( fgets( buffer, BUFFER_LENGTH, db_file ) != NULL ){
485
486 /* Split resource definition from value. */
487 length = strcspn( buffer, ":" );
488
489 if( length == 0 )
490 continue;
491
492 buffer[ length ] = '\0';
493
494 for( num_bindings = 0, index = 0; buffer[ index ] != '\0'; index ++ ){
495 if( ( buffer[ index ] == '*' ) || ( buffer[ index ] == '.' ) )
496 num_bindings ++;
497 }
498
499
500 binding_list =
501 (XrmBindingList) XtMalloc( ( num_bindings + 3 ) * sizeof( XrmBinding ) );
502 quark_list =
503 (XrmQuarkList) XtMalloc( ( num_bindings + 3 ) * sizeof( XrmQuark ) );
504
505 XrmStringToBindingQuarkList( buffer, binding_list, quark_list );
506
507 /* Find the start of the value. */
508 for( start_index = length + 1;
509 ( buffer[ start_index ] != '\0' ) && isspace( buffer[ start_index ] );
510 start_index ++ );
511
512 value.addr = (XPointer) &( buffer[ start_index ] );
513 value.size = strlen( &( buffer[ start_index ] ) );
514
515 /* Mask away trailing newline and spaces. */
516 while( ( value.size > 0 ) &&
517 isspace( *( (char *) value.addr + value.size - 1 ) ) )
518 value.size --;
519 *( (char *) value.addr + value.size ) = '\0';
520 value.size ++;
521
522 /* Check if selected. */
523 selected = False;
524
525 if( ( name_prefix == NULL ) || ( class_prefix == NULL ) )
526 selected = True;
527 else if( ( name_prefix[ 0 ] == wildcard_quark ) ||
528 ( class_prefix[ 0 ] == wildcard_quark ) ){
529 /* Select if specification starts with "*". */
530 if( buffer[ 0 ] == '*' )
531 selected = True;
532
533 } else {
534 /* The first quark must match name or class quark, or we must start
535 with '*'. */
536 if( buffer[ 0 ] == '*' )
537 selected = True;
538
539 else {
540 if( ( name_prefix[ 0 ] == quark_list[ 0 ] ) ||
541 ( class_prefix[ 0 ] == quark_list[ 0 ] ) )
542 selected = True;
543 }
544 }
545
546 if( selected )
547 terminate = (* ( proc ) ) ( &db, binding_list, quark_list, &string_rep,
548 &value, client_data );
549
550
551 XtFree( (char *) binding_list );
552 XtFree( (char *) quark_list );
553
554 if( terminate )
555 break;
556
557 }
558
559 fclose( db_file );
560 unlink( db_filename );
561
562
563 return terminate;
564
565 }
566
567
568 /*----------------------------------------------------------------------*/
569
570 static Bool
ModifyKeywordResource(XrmDatabase * db,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)571 ModifyKeywordResource( XrmDatabase *db,
572 XrmBindingList bindings,
573 XrmQuarkList quarks,
574 XrmRepresentation *type,
575 XrmValue *value,
576 XPointer closure )
577 {
578
579 Bool bok;
580 Boolean found;
581 int index;
582 xmubResourceMappingInfoRef info;
583 int length;
584 Bool ok;
585 String res_class;
586 String res_name;
587 char *str_type_return;
588 XrmValue value_return;
589
590 /* Code. */
591
592 info = (xmubResourceMappingInfoRef) closure;
593
594
595 /* If the value is a token that has a mapping, it should be replaced
596 with the mapping. */
597
598 /* Only for string resources. */
599 if( *type == info -> string_quark ){
600
601 /* Check number of quarks. */
602 for( length = 0; quarks[ length ] != NULLQUARK; length ++ );
603
604 if( info -> specific && ( length == 1 ) )
605 /* This is a general specification. */
606 return( False );
607
608 /* If a resource selection has been defined, pick the ones we need. */
609 if( info -> num_selections > 0 ){
610
611 found = False;
612
613 for( index = 0; index < info -> num_selections; index ++ ){
614 if( info -> selection[ index ] == quarks[ length - 1 ] ){
615 found = True;
616 break;
617 }
618 }
619
620 if( ( found && !info -> inclusive_selection ) ||
621 ( !found && info -> inclusive_selection ) )
622 return( False );
623 }
624
625
626
627 /* Allocate storage for keyword search. */
628 res_name = (char *) XtMalloc( strlen( info -> app_name ) +
629 value -> size + 5 );
630 res_class = (char *) XtMalloc( strlen( info -> app_class ) +
631 value -> size + 5 );
632
633 /* Check if the token has a mapping. */
634 sprintf( res_name, "%s.", info -> app_name );
635 strncat( res_name, (char *) value -> addr, value -> size );
636 res_name[ strlen( info -> app_name ) + value -> size + 1 ] = '\0';
637
638 sprintf( res_class, "%s.", info -> app_class );
639 strncat( res_class, (char *) value -> addr, value -> size );
640 res_class[ strlen( info -> app_class ) + value -> size + 1 ] = '\0';
641
642 ok = XrmGetResource( info -> translation_db, res_name, res_class,
643 &str_type_return, &value_return );
644
645 if( ok ){
646 /* We have a translation. */
647
648 XrmQPutResource( &( info -> merge_db ), bindings, quarks,
649 XrmStringToRepresentation( str_type_return ),
650 &value_return );
651
652 /* Save original string if required. */
653 if( info -> save_in_orig )
654 XrmQPutResource( &( info -> orig_db ), bindings, quarks,
655 *type, value );
656
657 } else if( info -> replace_substrings ){
658 /* No match for whole keyword, but check if substring matches. */
659
660 XrmQuark class_list[ 3 ];
661 XrmQuark name_list[ 3 ];
662
663 name_list[ 0 ] = XrmStringToQuark( info -> app_name );
664 name_list[ 1 ] = XrmStringToQuark( "_FontLists_" );
665 name_list[ 2 ] = NULLQUARK;
666
667 class_list[ 0 ] = XrmStringToQuark( info -> app_class );
668 class_list[ 1 ] = XrmStringToQuark( "_FontLists_" );
669 class_list[ 2 ] = NULLQUARK;
670
671 info -> replaced = False;
672 info -> value = XtMalloc( value -> size + 1 );
673 strncpy( info -> value, (char *) value -> addr, value -> size );
674 info -> value[ value -> size ] = '\0';
675
676 #if XlibSpecificationRelease > 4
677 bok = XrmEnumerateDatabase(
678 #else
679 bok = LoopThroughDatabase(
680 #endif
681 info -> translation_db, name_list, class_list,
682 XrmEnumAllLevels, ModifySubstringResource, (XPointer) info );
683
684 if( info -> replaced ){
685 XrmQPutStringResource( &( info -> merge_db ), bindings, quarks,
686 info -> value );
687
688 /* Save original string if required. */
689 if( info -> save_in_orig )
690 XrmQPutResource( &( info -> orig_db ), bindings, quarks,
691 *type, value );
692 }
693
694 XtFree( info -> value );
695
696 }
697
698 XtFree( res_name );
699 XtFree( res_class );
700 }
701
702
703 return( False );
704
705 } /* ModifyKeywordResource */
706
707
708 /*----------------------------------------------------------------------*/
709
710 static Bool
ModifySubstringResource(XrmDatabase * db,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)711 ModifySubstringResource( XrmDatabase *db,
712 XrmBindingList bindings,
713 XrmQuarkList quarks,
714 XrmRepresentation *type,
715 XrmValue *value,
716 XPointer closure )
717 {
718
719 xmubResourceMappingInfoRef info;
720 int key_length;
721 char* keyword;
722 int length;
723 char* start_ptr;
724 int tok_index;
725 char* tok_start;
726
727 /* Code. */
728
729 info = (xmubResourceMappingInfoRef) closure;
730
731
732 /* Check if the substring is present in the value. */
733 /* The keyword is in the last quark. */
734 for( length = 0; quarks[ length ] != NULLQUARK; length ++ );
735
736 keyword = XrmQuarkToString( quarks[ length - 1 ] );
737 key_length = strlen( keyword );
738
739
740 start_ptr = info -> value;
741
742 while( start_ptr < ( info -> value + value -> size ) ){
743
744 if( ( tok_start = strstr( start_ptr, keyword ) ) != NULL ){
745
746 tok_index = (int) ( tok_start - start_ptr );
747
748 /* Check if the substring is delimited by the correct characters. */
749 if( ( ( tok_index == 0 ) ||
750 ( strchr( info -> substring_delimiters,
751 info -> value[ tok_index - 1 ] ) != NULL ) ) &&
752 ( ( strlen( tok_start ) == key_length ) ||
753 ( strchr( info -> substring_delimiters,
754 info -> value[ tok_index + key_length ] ) != NULL ) ) ){
755
756 /* Ok. Replace the substring. */
757 /* The translation is in value. */
758
759 if( value -> size - 1 == key_length )
760 strncpy( tok_start, (char *) value -> addr, value -> size - 1 );
761
762 else if( value -> size - 1 < key_length ){
763 strncpy( tok_start, (char *) value -> addr, value -> size - 1 );
764 memmove( (void *) &( info -> value[ tok_index +
765 value -> size - 1 ] ),
766 (void *) &( info -> value[ tok_index + key_length ] ),
767 strlen( &( info -> value[ tok_index + key_length ] ) ) +
768 1 );
769
770 } else {
771 /* The replacement is longer, so we need to extend the string. */
772 info -> value = XtRealloc( info -> value,
773 strlen( info -> value ) + value -> size );
774
775 memmove( (void *) &( info -> value[ tok_index +
776 value -> size - 1 ] ),
777 (void *) &( info -> value[ tok_index + key_length ] ),
778 strlen( &( info -> value[ tok_index + key_length ] ) ) +
779 1 );
780 strncpy( &( info -> value[ tok_index ] ), (char *) value -> addr,
781 value -> size - 1 );
782 }
783
784
785 info -> replaced = True;
786 }
787
788 start_ptr = tok_start + key_length;
789
790
791 } else
792 /* The substring did not occur. */
793 break;
794
795 }
796
797
798 return( False );
799
800 } /* ModifySubstringResource */
801
802
803 /*----------------------------------------------------------------------*/
804
805 static int
StringComp(const void * s1,const void * s2)806 StringComp( const void *s1,
807 const void *s2 )
808 {
809
810 String *str1;
811 String *str2;
812
813 /* Code. */
814
815 str1 = (String *) s1;
816 str2 = (String *) s2;
817
818
819 #ifdef VMS
820 return( strcmp( *str1, *str2 ) );
821 #else
822 return( strcoll( *str1, *str2 ) );
823 #endif
824
825 } /* StringComp */
826
827
828 /*----------------------------------------------------------------------*/
829
830 Boolean
xmubResAddMapFile(xmubResourceMappingInfoRef info,char * file_name,Boolean add_defaults,xmubAppResDesc resource_sets[],Cardinal num_resource_sets)831 xmubResAddMapFile( xmubResourceMappingInfoRef info,
832 char* file_name,
833 Boolean add_defaults,
834 xmubAppResDesc resource_sets[],
835 Cardinal num_resource_sets )
836 {
837
838 Boolean allocated_file_name = False;
839 XrmDatabase file_db;
840 Boolean ok;
841
842 /* Code. */
843
844 if( file_name == NULL ){
845 file_name = xmubResGetMappingFileName( info -> display );
846 allocated_file_name = True;
847 }
848
849 if( file_name == NULL )
850 return False;
851
852 /* Read the contents of the file into a temporary database. */
853 /* The function also tests if the file is accessible. */
854 if( ( file_db = XrmGetFileDatabase( file_name ) ) == NULL )
855 return( False );
856
857 ok = xmubResAddMappings( info, file_db, add_defaults,
858 resource_sets, num_resource_sets );
859
860
861 if( allocated_file_name )
862 XtFree( file_name );
863
864
865 /* Save the mapping base in the mapping database.
866 file_db is automatically destroyed. */
867 XrmMergeDatabases( file_db, &( info -> mapping_db ) );
868
869
870 return( ok );
871
872 }
873
874
875 /*----------------------------------------------------------------------*/
876
877 Boolean
xmubResAddMappings(xmubResourceMappingInfoRef info,XrmDatabase db,Boolean add_defaults,xmubAppResDesc resource_sets[],Cardinal num_resource_sets)878 xmubResAddMappings( xmubResourceMappingInfoRef info,
879 XrmDatabase db,
880 Boolean add_defaults,
881 xmubAppResDesc resource_sets[],
882 Cardinal num_resource_sets )
883 {
884
885 Bool bok;
886 int index;
887 XrmQuark name_list[ 2 ];
888
889 /* Code. */
890
891 info -> selected = False;
892
893 /* Add the general resource specifications. */
894 if( add_defaults ){
895
896 name_list[ 0 ] = XrmStringToQuark( "*" );
897 name_list[ 1 ] = NULLQUARK;
898
899 info -> specific = False;
900
901 #if XlibSpecificationRelease > 4
902 bok = XrmEnumerateDatabase(
903 #else
904 bok = LoopThroughDatabase(
905 #endif
906 db, name_list, name_list, XrmEnumAllLevels,
907 InsertGeneralMappingResources, (XPointer) info );
908 }
909
910
911 /* Specific resources from sets. */
912 if( num_resource_sets > 0 ){
913
914 char** values;
915
916 /* Extract the values for the defined resource sets. */
917 values = (char **) XtMalloc( sizeof( char *) * num_resource_sets );
918 GetResourceValues( info, resource_sets, num_resource_sets, values );
919
920 info -> specific = True;
921
922 /* For some reason, we must call for the different options separately. */
923 for( index = 0; index < num_resource_sets; index ++ ){
924
925 if( values[ index ] != NULL ){
926 name_list[ 0 ] = XrmStringToQuark( values[ index ] );
927 name_list[ 1 ] = NULLQUARK;
928
929 #if XlibSpecificationRelease > 4
930 bok = XrmEnumerateDatabase(
931 #else
932 bok = LoopThroughDatabase(
933 #endif
934 db, name_list, name_list, XrmEnumAllLevels,
935 InsertSpecificMappingResources, (XPointer) info );
936 }
937
938 }
939
940 for( index = 0; index < num_resource_sets; index ++ )
941 if( values[ index ] != NULL )
942 XtFree( values[ index ] );
943
944 XtFree( (char *) values );
945
946 }
947
948 return info -> selected;
949
950 }
951
952
953 /*----------------------------------------------------------------------*/
954
955 void
xmubResAddSetChangedCallback(xmubResourceMappingInfoRef info,xmubResSetChangeCallback callback,XtPointer client_data)956 xmubResAddSetChangedCallback( xmubResourceMappingInfoRef info,
957 xmubResSetChangeCallback callback,
958 XtPointer client_data )
959 {
960 /* Code. */
961
962 info -> num_set_change_callbacks ++;
963
964 /* Extend the list. */
965 if( info -> num_set_change_callbacks == 1 )
966 info -> set_change_callbacks = (xmubResSetChangeCallbackList)
967 XtMalloc( sizeof( xmubResSetChangeCallbackRec ) );
968
969 else
970 info -> set_change_callbacks = (xmubResSetChangeCallbackList)
971 XtRealloc( (char *) info -> set_change_callbacks,
972 sizeof( xmubResSetChangeCallbackRec ) *
973 info -> num_set_change_callbacks );
974
975 /* Insert the information. */
976 info -> set_change_callbacks[
977 info -> num_set_change_callbacks - 1 ].callback = callback;
978 info -> set_change_callbacks[
979 info -> num_set_change_callbacks - 1 ].client_data = client_data;
980
981 }
982
983
984 /*----------------------------------------------------------------------*/
985
986 void
xmubResAddStringMapping(xmubResourceMappingInfoRef info,char * keyword,char * translation)987 xmubResAddStringMapping( xmubResourceMappingInfoRef info,
988 char* keyword,
989 char* translation )
990 {
991 char* specifier;
992
993 /* Code. */
994
995 specifier = XtMalloc( strlen( keyword ) + 2 );
996 sprintf( specifier, "*%s", keyword );
997
998 XrmPutStringResource( &( info -> mapping_db ), specifier, translation );
999 XrmPutStringResource( &( info -> translation_db ), specifier, translation );
1000
1001 XtFree( specifier );
1002
1003 }
1004
1005
1006 /*----------------------------------------------------------------------*/
1007
1008 Widget
xmubAppInitialize(XtAppContext * app_context_return,String application_class,XrmOptionDescList options,Cardinal num_options,Cardinal * argc_in_out,String * argv_in_out,String * fallback_resources,ArgList args,Cardinal num_args,xmubAppResDesc * resource_sets,Cardinal num_resource_sets,xmubResourceMappingInfoRef * ref_return)1009 xmubAppInitialize( XtAppContext *app_context_return,
1010 String application_class,
1011 XrmOptionDescList options,
1012 Cardinal num_options,
1013 Cardinal *argc_in_out,
1014 String *argv_in_out,
1015 String *fallback_resources,
1016 ArgList args,
1017 Cardinal num_args,
1018 xmubAppResDesc *resource_sets,
1019 Cardinal num_resource_sets,
1020 xmubResourceMappingInfoRef *ref_return )
1021 {
1022
1023 XtAppContext app;
1024 Display *display;
1025 Arg iargs[ 5 ];
1026 int index;
1027 xmubResourceMappingInfoRef info;
1028 Cardinal n;
1029 Cardinal orig_argc;
1030 String *orig_argv = NULL;
1031 Widget toplevel;
1032
1033 /* Code. */
1034
1035 /* Make a copy of the original arguments. */
1036 orig_argc = *argc_in_out;
1037
1038 if( orig_argc > 0 ){
1039 orig_argv = (char**) XtMalloc( sizeof( char* ) * orig_argc );
1040
1041 for( index = 0; index < orig_argc; index++ )
1042 orig_argv[ index ] = XtNewString( argv_in_out[ index ] );
1043 }
1044
1045 /* Initialize the application. */
1046 XtToolkitInitialize();
1047 app = XtCreateApplicationContext();
1048
1049 /* Fallback resources. */
1050 if( fallback_resources != NULL )
1051 XtAppSetFallbackResources( app, fallback_resources );
1052
1053 /* Open the display. */
1054 display = XtOpenDisplay( app, NULL, NULL, application_class,
1055 options, num_options,
1056 (int *) argc_in_out, argv_in_out );
1057
1058 xmubInitResourceMapping( display, resource_sets, num_resource_sets, &info );
1059
1060 /* Create the shell. */
1061 n = 0;
1062 XtSetArg( iargs[ n ], XtNargc, orig_argc ); n++;
1063 XtSetArg( iargs[ n ], XtNargv, orig_argv ); n++;
1064 toplevel = XtAppCreateShell( NULL, application_class,
1065 applicationShellWidgetClass,
1066 display, iargs, n );
1067
1068 /* We don't have to free argv. */
1069
1070 /* Set the arguments on the shell. */
1071 XtSetValues( toplevel, args, num_args );
1072
1073
1074 /* Set returned values. */
1075 if( app_context_return != NULL )
1076 *app_context_return = app;
1077
1078 if( ref_return != NULL )
1079 *ref_return = info;
1080 else
1081 xmubResFreeInfo( info );
1082
1083
1084 return( toplevel );
1085
1086 }
1087
1088
1089 /*----------------------------------------------------------------------*/
1090
1091 void
xmubInitResourceMapping(Display * display,xmubAppResDesc resource_sets[],Cardinal num_resource_sets,xmubResourceMappingInfoRef * res_info)1092 xmubInitResourceMapping( Display* display,
1093 xmubAppResDesc resource_sets[],
1094 Cardinal num_resource_sets,
1095 xmubResourceMappingInfoRef *res_info )
1096 {
1097
1098 xmubResourceMappingInfoRef info;
1099 Boolean ok;
1100
1101 /* Code. */
1102
1103 /* Initialize out parameter. */
1104 if( res_info != NULL )
1105 *res_info = NULL;
1106
1107 /* Initialize. */
1108 info = xmubResInitialize( display );
1109 if( info == NULL )
1110 return;
1111
1112 /* Add mappings from the default file. */
1113 ok = xmubResAddMapFile( info, NULL, True, resource_sets, num_resource_sets );
1114 if( ! ok ){
1115 xmubResFreeInfo( info );
1116 return;
1117 }
1118
1119 /* Replace the keywords. */
1120 xmubResReplace( info, NULL );
1121
1122 /* Merge the translations into the display database. */
1123 xmubResMergeMappedResources( info, NULL );
1124
1125 if( res_info != NULL )
1126 *res_info = info;
1127 else
1128 xmubResFreeInfo( info );
1129
1130 }
1131
1132
1133 /*----------------------------------------------------------------------*/
1134
1135 void
xmubResClearInternalDatabases(xmubResourceMappingInfoRef info,Boolean clear_orig_db,Boolean clear_mapping_db,Boolean clear_translation_db,Boolean clear_merge_db)1136 xmubResClearInternalDatabases(
1137 xmubResourceMappingInfoRef info,
1138 Boolean clear_orig_db,
1139 Boolean clear_mapping_db,
1140 Boolean clear_translation_db,
1141 Boolean clear_merge_db )
1142 {
1143
1144 /* Code. */
1145
1146 if( clear_orig_db ){
1147 XrmDestroyDatabase( info -> orig_db );
1148 info -> orig_db = NULL;
1149 }
1150
1151 if( clear_mapping_db ){
1152 XrmDestroyDatabase( info -> mapping_db );
1153 info -> mapping_db = NULL;
1154 }
1155
1156 if( clear_translation_db ){
1157 XrmDestroyDatabase( info -> translation_db );
1158 info -> translation_db = NULL;
1159 }
1160
1161 if( clear_merge_db ){
1162 XrmDestroyDatabase( info -> merge_db );
1163 info -> merge_db = NULL;
1164 }
1165 }
1166
1167
1168 /*----------------------------------------------------------------------*/
1169
1170 void
xmubResFreeInfo(xmubResourceMappingInfoRef info)1171 xmubResFreeInfo( xmubResourceMappingInfoRef info )
1172 {
1173
1174 /* Code. */
1175
1176 /* Destroy the databases. */
1177 xmubResClearInternalDatabases( info, True, True, True, True );
1178
1179 /* Free allocated strings. */
1180 XtFree( info -> app_name );
1181 XtFree( info -> app_class );
1182
1183 /* Temporary fields must be freed by the allocator. */
1184
1185 /* Free the record itself. */
1186 XtFree( (char *) info );
1187
1188 }
1189
1190
1191 /*----------------------------------------------------------------------*/
1192
1193 #ifdef VMS
1194 char*
xmubResGetMappingFileName(Display * display)1195 xmubResGetMappingFileName( Display *display )
1196 {
1197
1198 /* VMS version. */
1199
1200 String app_class;
1201 Boolean class_file;
1202 String filename = NULL;
1203 String fname;
1204 String env;
1205 String name;
1206
1207 /* Code. */
1208
1209 /* Start by trying the environment variable. */
1210 env = getenv( XRESOURCE_MAP_FILE );
1211 if( ( env != NULL ) && FileReadAccess( env ) ){
1212 filename = XtNewString( env );
1213 return( filename );
1214 }
1215
1216 /* File not accessible via environment variable. */
1217 /* Look for file with the name "app-class".map in all paths.
1218 If not found, look for default file "xresource.map" in the same paths. */
1219
1220 XtGetApplicationNameAndClass( display, &name, &app_class );
1221
1222
1223 class_file = True;
1224
1225 for( ;; ){
1226
1227 if( class_file )
1228 fname = app_class;
1229 else
1230 fname = MAP_FILE_NAME;
1231
1232 /* Try user defaults. */
1233 filename = (String) XtMalloc( strlen( fname ) + 30 );
1234 sprintf( filename, "DECW$USER_DEFAULTS:%s%s", fname, MAP_FILE_SUFFIX );
1235
1236 if( FileReadAccess( filename ) )
1237 return( filename );
1238
1239 /* Try system defaults. */
1240 sprintf( filename, "DECW$SYSTEM_DEFAULTS:%s%s", fname, MAP_FILE_SUFFIX );
1241
1242 if( FileReadAccess( filename ) )
1243 return( filename );
1244 else
1245 XtFree( filename );
1246
1247 /* Try local directory. */
1248 sprintf( filename, "%s%s", fname, MAP_FILE_SUFFIX );
1249
1250 if( FileReadAccess( filename ) )
1251 return( filename );
1252 else
1253 XtFree( filename );
1254
1255 /* Second round checks for general file. */
1256 if( class_file )
1257 class_file = False;
1258 else
1259 break;
1260
1261 }
1262
1263
1264 return( NULL );
1265
1266 }
1267
1268 #else
1269
1270
1271 /*----------------------------------------------------------------------*/
1272
1273 char*
xmubResGetMappingFileName(Display * display)1274 xmubResGetMappingFileName( Display *display )
1275 {
1276
1277 /* Unix version. */
1278
1279 String app_class;
1280 Boolean class_file;
1281 String filename = NULL;
1282 String fname;
1283 String env;
1284 String homedir = NULL;
1285 String name;
1286 String path = NULL;
1287
1288 /* Code. */
1289
1290 /* Start by trying the environment variable. */
1291 env = getenv( XRESOURCE_MAP_FILE );
1292 if( ( env != NULL ) && FileReadAccess( env ) ){
1293 filename = XtNewString( env );
1294 return( filename );
1295 }
1296
1297 /* File not accessible via environment variable. */
1298 /* Look for file with the name "app-class".map in all paths.
1299 If not found, look for default file "xresource.map" in the same paths. */
1300
1301 XtGetApplicationNameAndClass( display, &name, &app_class );
1302
1303
1304 class_file = True;
1305
1306 for( ;; ){
1307
1308 if( class_file )
1309 fname = app_class;
1310 else
1311 fname = MAP_FILE_NAME;
1312
1313 /* Try user file search path. */
1314 env = getenv( "XUSERFILESEARCHPATH" );
1315 if( env != NULL ){
1316 /* Copy path so it is not overwritten. */
1317 path = XtNewString( env );
1318
1319 filename = XtResolvePathname( display, MAP_FILE_DIRTYPE, fname,
1320 MAP_FILE_SUFFIX, path,
1321 (Substitution) NULL, 0,
1322 (XtFilePredicate) NULL );
1323
1324 XtFree( path );
1325 path = NULL;
1326
1327 if( ( filename != NULL ) && FileReadAccess( filename ) )
1328 return( filename );
1329 else if( filename != NULL )
1330 XtFree( filename );
1331 }
1332
1333 /* Try application resource directory or home directory. */
1334 homedir = getenv( "HOME" );
1335
1336 env = getenv( "XAPPLRESDIR" );
1337 if( env != NULL ){
1338
1339 /* Construct path containing appl res dir. */
1340 path = (String) XtMalloc( strlen( env ) * 3 +
1341 ( homedir != NULL ? strlen( homedir ) : 0 ) +
1342 40 );
1343 if( homedir != NULL )
1344 sprintf( path, "%s%s:%s%s:%s%s:%s%s:.",
1345 env, "/%L/%N/%S", env, "/%l/%N%S", env, "/%N%S",
1346 homedir, "/%N%S" );
1347 else
1348 sprintf( path, "%s%s:%s%s:%s%s:.",
1349 env, "/%L/%N/%S", env, "/%l/%N%S", env, "/%N%S" );
1350
1351 } else if( homedir != NULL ){
1352 /* XAPPLRESDIR was not defined. Use path with home directory. */
1353 path = (String) XtMalloc( strlen( homedir ) * 3 + 25 );
1354 sprintf( path, "%s%s:%s%s:%s%s:.",
1355 homedir, "/%L/%N%S", homedir, "/%l%N%S",
1356 homedir, "/%N%S" );
1357 }
1358
1359 if( path != NULL ){
1360 filename = XtResolvePathname( display, MAP_FILE_DIRTYPE, fname,
1361 MAP_FILE_SUFFIX, path,
1362 (Substitution) NULL, 0,
1363 (XtFilePredicate) NULL );
1364 XtFree( path );
1365 }
1366
1367 if( ( filename != NULL ) && FileReadAccess( filename ) )
1368 return( filename );
1369 else if( filename != NULL )
1370 XtFree( filename );
1371
1372
1373 /* Last chance is the system default path. */
1374 filename = XtResolvePathname( display, MAP_FILE_DIRTYPE, fname,
1375 MAP_FILE_SUFFIX, NULL,
1376 (Substitution) NULL, 0,
1377 (XtFilePredicate) NULL );
1378
1379 if( ( filename != NULL ) && FileReadAccess( filename ) )
1380 return( filename );
1381 else if( filename != NULL )
1382 XtFree( filename );
1383
1384
1385 /* Second round checks for general file. */
1386 if( class_file )
1387 class_file = False;
1388 else
1389 break;
1390 }
1391
1392
1393 /* If we had found a file we would have returned by now. */
1394
1395 return( NULL );
1396
1397 }
1398 #endif
1399
1400 /*----------------------------------------------------------------------*/
1401
1402 xmubResourceMappingInfoRef
xmubResInitialize(Display * display)1403 xmubResInitialize( Display* display )
1404 {
1405
1406 char* app_class;
1407 char* app_name;
1408 xmubResourceMappingInfoRef info;
1409
1410 /* Code. */
1411
1412 info = (xmubResourceMappingInfoRef) XtMalloc(
1413 sizeof( xmubResourceMappingInfo ) );
1414
1415 XtGetApplicationNameAndClass( display, &app_name, &app_class );
1416
1417 /* Copy the name and class of the application. */
1418 info -> app_name = XtNewString( app_name );
1419 info -> app_class = XtNewString( app_class );
1420
1421 /* Set the database entries to NULL. */
1422 info -> orig_db = NULL;
1423 info -> mapping_db = NULL;
1424 info -> translation_db = NULL;
1425 info -> merge_db = NULL;
1426
1427 info -> display = display;
1428
1429 info -> string_quark = XrmStringToQuark( "String" );
1430
1431 info -> set_change_callbacks = NULL;
1432 info -> num_set_change_callbacks = 0;
1433
1434
1435 return( info );
1436
1437 }
1438
1439
1440 /*----------------------------------------------------------------------*/
1441
1442 char**
xmubResListClasses(xmubResourceMappingInfoRef info,char * keyword,Boolean sorted,XrmDatabase db)1443 xmubResListClasses( xmubResourceMappingInfoRef info,
1444 char* keyword,
1445 Boolean sorted,
1446 XrmDatabase db )
1447 {
1448
1449 Bool bok;
1450 char** class_table;
1451 int index;
1452 ListClassesInfo listinfo;
1453
1454 /* Code. */
1455
1456 if( db == NULL )
1457 db = info -> mapping_db;
1458
1459 if( db == NULL )
1460 return NULL;
1461
1462 /* Loop through all resources. */
1463 listinfo.info = info;
1464 listinfo.keyword_quark = XrmStringToQuark( keyword );
1465 listinfo.sets = NULL;
1466 listinfo.num_sets = 0;
1467 listinfo.set_list_length = 0;
1468
1469 /* XrmEnumerateDatabase cannot handle NULL parameters for name_list
1470 and class_list, but LoopThroughDatabase can!! */
1471 bok = LoopThroughDatabase(
1472 db, NULL, NULL, XrmEnumAllLevels, ExtractKeywordClass,
1473 (XPointer) &listinfo );
1474
1475 if( listinfo.num_sets > 0 ){
1476 class_table = (char **) XtMalloc( sizeof( char* ) *
1477 ( listinfo.num_sets + 1 ) );
1478
1479 for( index = 0; index < listinfo.num_sets; index ++ )
1480 class_table[ index ] =
1481 XtNewString( XrmQuarkToString( listinfo.sets[ index ] ) );
1482
1483 class_table[ listinfo.num_sets ] = NULL;
1484
1485 } else
1486 class_table = NULL;
1487
1488 if( listinfo.sets != NULL )
1489 XtFree( (char *) listinfo.sets );
1490
1491
1492 /* Sort the table. */
1493 if( sorted && ( class_table != NULL ) )
1494 qsort( (void *) class_table, (size_t) listinfo.num_sets,
1495 (size_t) sizeof( char* ), StringComp );
1496
1497
1498 return( class_table );
1499
1500 }
1501
1502
1503 /*----------------------------------------------------------------------*/
1504
1505 void
xmubResMergeMappedResources(xmubResourceMappingInfoRef info,XrmDatabase target_db)1506 xmubResMergeMappedResources( xmubResourceMappingInfoRef info,
1507 XrmDatabase target_db )
1508 {
1509 /* Code. */
1510
1511 if( target_db == NULL )
1512 target_db = XtDatabase( info -> display );
1513
1514 /* This call destroys the merge database. Replace it later. */
1515 XrmMergeDatabases( info -> merge_db, &( target_db ) );
1516
1517 /* The database was destroyed. */
1518 info -> merge_db = NULL;
1519
1520 }
1521
1522
1523 /*----------------------------------------------------------------------*/
1524
1525 void
xmubResRemoveSetChangedCallback(xmubResourceMappingInfoRef info,xmubResSetChangeCallback callback,XtPointer client_data)1526 xmubResRemoveSetChangedCallback( xmubResourceMappingInfoRef info,
1527 xmubResSetChangeCallback callback,
1528 XtPointer client_data )
1529 {
1530
1531 Boolean found = False;
1532 int pos;
1533
1534 /* Code. */
1535
1536 /* Find the callback info position. */
1537 for( pos = 0; pos < info -> num_set_change_callbacks; pos ++ ){
1538 if( ( info -> set_change_callbacks[ pos ].callback == callback ) &&
1539 ( info -> set_change_callbacks[ pos ].client_data == client_data ) ){
1540 found = True;
1541 break;
1542 }
1543 }
1544
1545 if( ! found )
1546 return;
1547
1548 /* The callback was present. */
1549 if( info -> num_set_change_callbacks == 1 ){
1550 info -> num_set_change_callbacks = 0;
1551 XtFree( (char *) info -> set_change_callbacks );
1552 info -> set_change_callbacks = NULL;
1553
1554 return;
1555 }
1556
1557 /* Just overwrite the old one. Don't care about wasted memory. */
1558 memmove( &( info -> set_change_callbacks[ pos ] ),
1559 &( info -> set_change_callbacks[ pos + 1 ] ),
1560 info -> num_set_change_callbacks - pos - 1 );
1561
1562 info -> num_set_change_callbacks --;
1563
1564 }
1565
1566
1567 /*----------------------------------------------------------------------*/
1568
1569 void
xmubResReplace(xmubResourceMappingInfoRef info,XrmDatabase start_db)1570 xmubResReplace( xmubResourceMappingInfoRef info,
1571 XrmDatabase start_db )
1572 {
1573
1574 Boolean allocated_delimiters = False;
1575 char* delimiters;
1576 int index;
1577 Bool ok;
1578 char* res_class;
1579 char* res_name;
1580 char* search_string;
1581 char** str_list;
1582 int str_list_index;
1583 int str_list_size;
1584 char* str_type_return;
1585 char* token;
1586 XrmValue value_return;
1587
1588 /* Code. */
1589
1590 /* First pass, replace without substring support. */
1591 xmubResReplaceKeywords( info, start_db, False, NULL, NULL, 0, False );
1592
1593 /* Get the resource definitions. */
1594 /* We cannot use XtGetApplication resources, since it requires a widget. */
1595 res_name = XtMalloc( strlen( info -> app_name ) + 30 );
1596 res_class = XtMalloc( strlen( info -> app_class ) + 30 );
1597
1598 sprintf( res_name, "%s.%s", info -> app_name, XmUbNsubstringResources );
1599 sprintf( res_class, "%s.%s", info -> app_class, XmUbCSubstringResources );
1600
1601 /* Get the resource first from the source database, if not specified
1602 there, try display database. */
1603 if( start_db != NULL )
1604 ok = XrmGetResource( start_db, res_name, res_class,
1605 &str_type_return, &value_return );
1606 else
1607 ok = (Bool) False;
1608
1609 if( ! ok )
1610 ok = XrmGetResource( XtDatabase( info -> display ), res_name, res_class,
1611 &str_type_return, &value_return );
1612
1613 if( ok ){
1614 /* The resource was specified. */
1615 /* Construct string list from extracted string. */
1616 str_list_size = 5;
1617 str_list_index = 0;
1618 str_list = (char **) XtMalloc( sizeof( char *) * str_list_size );
1619 search_string = (char *) value_return.addr;
1620
1621
1622 while( ( token = strtok( search_string, " " ) ) != NULL ){
1623
1624 if( str_list_index == str_list_size ){
1625 str_list_size += 5;
1626 str_list = (char **) XtRealloc( (char *) str_list,
1627 sizeof( char *) * str_list_size );
1628 }
1629
1630 str_list[ str_list_index ] = XtNewString( token );
1631 str_list_index ++;
1632
1633 /* Nullify for next call. */
1634 search_string = NULL;
1635 }
1636
1637 /* The string list has been constructed. */
1638 /* Get the delimiter list. */
1639 sprintf( res_name, "%s.%s", info -> app_name, XmUbNsubstringDelimiters );
1640 sprintf( res_class, "%s.%s", info -> app_class, XmUbCSubstringDelimiters );
1641
1642 if( start_db != NULL )
1643 ok = XrmGetResource( start_db, res_name, res_class,
1644 &str_type_return, &value_return );
1645 else
1646 ok = (Bool) False;
1647
1648 if( ! ok )
1649 ok = XrmGetResource( XtDatabase( info -> display ), res_name, res_class,
1650 &str_type_return, &value_return );
1651
1652 if( ok ){
1653 delimiters = XtMalloc( sizeof( char ) * ( value_return.size + 1 ) );
1654 strncpy( delimiters, (char *) value_return.addr, value_return.size );
1655 delimiters[ value_return.size ] = '\0';
1656 allocated_delimiters = True;
1657
1658 } else
1659 delimiters = DEFAULT_DELIMITERS;
1660
1661 /* Replace the keywords. */
1662 xmubResReplaceKeywords( info, start_db, True, delimiters,
1663 str_list, str_list_index, True );
1664
1665
1666 /* Free up. */
1667 for( index = 0; index < str_list_index; index ++ )
1668 XtFree( str_list[ index ] );
1669
1670 XtFree( (char *) str_list );
1671 if( allocated_delimiters )
1672 XtFree( delimiters );
1673
1674 }
1675
1676 XtFree( res_name );
1677 XtFree( res_class );
1678
1679 }
1680
1681
1682 /*----------------------------------------------------------------------*/
1683
1684 void
xmubResReplaceKeywords(xmubResourceMappingInfoRef info,XrmDatabase start_db,Boolean replace_substrings,char * substring_delimiters,char ** resource_selection,Cardinal num_resource_selection,Boolean inclusive_selection)1685 xmubResReplaceKeywords( xmubResourceMappingInfoRef info,
1686 XrmDatabase start_db,
1687 Boolean replace_substrings,
1688 char* substring_delimiters,
1689 char** resource_selection,
1690 Cardinal num_resource_selection,
1691 Boolean inclusive_selection )
1692 {
1693
1694 Bool bok;
1695 XrmQuark class_list[ 3 ];
1696 int index;
1697 XrmQuark name_list[ 3 ];
1698
1699 /* Code. */
1700
1701 /* If no input database is defined, take the display database. */
1702 if( start_db == NULL )
1703 start_db = XtDatabase( info -> display );
1704
1705 /* If a resource selection was defined, set it up as quarks, to allow for
1706 faster comparison. */
1707 info -> num_selections = num_resource_selection;
1708
1709 if( num_resource_selection > 0 ){
1710 info -> selection =
1711 (XrmQuark *) XtMalloc( num_resource_selection * sizeof( XrmQuark ) );
1712 info -> inclusive_selection = inclusive_selection;
1713
1714 for( index = 0; index < num_resource_selection; index ++ )
1715 info -> selection[ index ] =
1716 XrmStringToQuark( resource_selection[ index ] );
1717
1718 } else
1719 info -> selection = NULL;
1720
1721
1722 /* We need two passes since we want to insert the general resources first,
1723 and override with the specific ones later. */
1724
1725 /* General resources. */
1726 name_list[ 0 ] = XrmStringToQuark( "*" );
1727 name_list[ 1 ] = NULLQUARK;
1728
1729 class_list[ 0 ] = XrmStringToQuark( "*" );
1730 class_list[ 1 ] = NULLQUARK;
1731
1732 info -> specific = False;
1733
1734 info -> replace_substrings = replace_substrings;
1735 info -> substring_delimiters = substring_delimiters;
1736
1737 if( start_db == info -> orig_db )
1738 info -> save_in_orig = False;
1739 else
1740 info -> save_in_orig = True;
1741
1742 #if XlibSpecificationRelease > 4
1743 bok = XrmEnumerateDatabase(
1744 #else
1745 bok = LoopThroughDatabase(
1746 #endif
1747 start_db, name_list, class_list, XrmEnumAllLevels, ModifyKeywordResource,
1748 (XPointer) info );
1749
1750 /* Application specific resources. */
1751 name_list[ 0 ] = XrmStringToQuark( info -> app_name );
1752 name_list[ 1 ] = XrmStringToQuark( "_FontLists_" );
1753 name_list[ 2 ] = NULLQUARK;
1754
1755 class_list[ 0 ] = XrmStringToQuark( info -> app_class );
1756 class_list[ 1 ] = XrmStringToQuark( "_FontLists_" );
1757 class_list[ 2 ] = NULLQUARK;
1758
1759 info -> specific = True;
1760
1761 #if XlibSpecificationRelease > 4
1762 bok = XrmEnumerateDatabase(
1763 #else
1764 bok = LoopThroughDatabase(
1765 #endif
1766 start_db, name_list, class_list, XrmEnumAllLevels, ModifyKeywordResource,
1767 (XPointer) info );
1768
1769
1770 /* Clean up. */
1771 if( info -> selection != NULL )
1772 XtFree( (char *) info -> selection );
1773
1774 }
1775
1776
1777 /*----------------------------------------------------------------------*/
1778
1779 Boolean
xmubResUpdateAllResources(xmubResourceMappingInfoRef info,xmubAppResDesc resource_sets[],Cardinal num_resource_sets,xmubResSetChangeCallback apply_callback,XtPointer client_data)1780 xmubResUpdateAllResources( xmubResourceMappingInfoRef info,
1781 xmubAppResDesc resource_sets[],
1782 Cardinal num_resource_sets,
1783 xmubResSetChangeCallback apply_callback,
1784 XtPointer client_data )
1785 {
1786
1787 Bool bok;
1788 xmubResSetChangeCallbackStruct cb;
1789 int index;
1790 Boolean ok;
1791 char* res_class;
1792 char* res_name;
1793 int res_number;
1794 char* str_type_return;
1795 XrmValue value_return;
1796
1797 /* Code. */
1798
1799 /* Clear the translation and merge databases. */
1800 xmubResClearInternalDatabases( info, False, False, True, True );
1801
1802 ok = xmubResAddMappings( info, info -> mapping_db, True,
1803 resource_sets, num_resource_sets );
1804
1805 if( ok ){
1806 xmubResReplace( info, info -> orig_db );
1807 xmubResMergeMappedResources( info, NULL );
1808 }
1809
1810 /* Call callbacks for each resource. */
1811
1812 /* Set up the callback structure. */
1813 cb.reason = XMUB_RES_SET_CHANGED;
1814 cb.res_name = NULL;
1815 cb.res_class = NULL;
1816 cb.new_value = NULL;
1817 cb.mapping_changed = ok;
1818
1819 /* Call the apply callback. */
1820 if( apply_callback != NULL )
1821 (* ( apply_callback ) ) ( info, client_data, &cb );
1822
1823 /* Call the resource change callbacks. */
1824 for( res_number = 0; res_number < num_resource_sets; res_number ++ ){
1825
1826 res_name = XtMalloc( strlen( resource_sets[ res_number ].res_name ) +
1827 strlen( info -> app_name ) + 5 );
1828 sprintf( res_name, "%s.%s", info -> app_name,
1829 resource_sets[ res_number ].res_name );
1830
1831 res_class = XtMalloc( strlen( resource_sets[ res_number ].res_class ) +
1832 strlen( info -> app_class ) + 5 );
1833 sprintf( res_class, "%s.%s", info -> app_class,
1834 resource_sets[ res_number ].res_class );
1835
1836 bok = XrmGetResource( XtDatabase( info -> display ), res_name, res_class,
1837 &str_type_return, &value_return );
1838
1839 cb.reason = XMUB_RES_SET_CHANGED;
1840 cb.res_name = resource_sets[ res_number ].res_name;
1841 cb.res_class = resource_sets[ res_number ].res_class;
1842 if( bok )
1843 cb.new_value = (char *) value_return.addr;
1844 else
1845 cb.new_value = NULL;
1846 cb.mapping_changed = True;
1847
1848 for( index = 0; index < info -> num_set_change_callbacks; index ++ )
1849 (* ( info -> set_change_callbacks[ index ].callback ) )
1850 ( info, info -> set_change_callbacks[ index ].client_data, &cb );
1851
1852 XtFree( res_name );
1853 XtFree( res_class );
1854
1855
1856 }
1857
1858 return( ok );
1859
1860 }
1861
1862
1863 /*----------------------------------------------------------------------*/
1864
1865 Boolean
xmubResUpdateResourceSet(xmubResourceMappingInfoRef info,char * res_name,char * res_class,char * new_value,xmubResSetChangeCallback apply_callback,XtPointer client_data)1866 xmubResUpdateResourceSet( xmubResourceMappingInfoRef info,
1867 char* res_name,
1868 char* res_class,
1869 char* new_value,
1870 xmubResSetChangeCallback apply_callback,
1871 XtPointer client_data )
1872 {
1873
1874 xmubResSetChangeCallbackStruct cb;
1875 XrmDatabase db;
1876 int index;
1877 Boolean ok;
1878 char* resource_line;
1879 xmubAppResDesc res_sets;
1880
1881 /* Code. */
1882
1883 /* Set the new resource in the display database. */
1884 resource_line = XtMalloc( strlen( res_name ) + strlen( new_value ) + 5 );
1885 sprintf( resource_line, "*%s: %s", res_name, new_value );
1886 db = XtDatabase( info -> display );
1887
1888 XrmPutLineResource( &db, resource_line );
1889
1890 XtFree( resource_line );
1891
1892 /* Clear the translation and merge databases. */
1893 xmubResClearInternalDatabases( info, False, False, True, True );
1894
1895 /* Select the mappings from the mapping database. */
1896 res_sets.res_name = res_name;
1897 res_sets.res_class = res_class;
1898 ok = xmubResAddMappings( info, info -> mapping_db, False, &res_sets, 1 );
1899
1900 if( ok ){
1901 xmubResReplace( info, info -> orig_db );
1902 xmubResMergeMappedResources( info, NULL );
1903 }
1904
1905 /* Set up the callback structure. */
1906 cb.reason = XMUB_RES_SET_CHANGED;
1907 cb.res_name = res_name;
1908 cb.res_class = res_class;
1909 cb.new_value = new_value;
1910 cb.mapping_changed = ok;
1911
1912 /* Call the apply callback. */
1913 if( apply_callback != NULL )
1914 (* ( apply_callback ) ) ( info, client_data, &cb );
1915
1916 /* Call the resource change callbacks. */
1917 for( index = 0; index < info -> num_set_change_callbacks; index ++ )
1918 (* ( info -> set_change_callbacks[ index ].callback ) )
1919 ( info, info -> set_change_callbacks[ index ].client_data, &cb );
1920
1921
1922 return( ok );
1923
1924 }
1925