1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: cmdXResource.c **
8 | ** First Edition: 1991/10/23 **
9 | ** **
10 | ** Authors: John Furlan, jlf@behere.com **
11 | ** Leif Hedstrom<hedstrom"@boot.org> **
12 | ** Jens Hamisch, jens@Strawberry.COM **
13 | ** **
14 | ** Description: Module command to merge/remove resources from the X11**
15 | ** resource manager. The database is update internally, **
16 | ** ie. its not done at evaluation of string modulecmd **
17 | ** returns. It will do something like "xrdb -merge" **
18 | ** using the default display ($DISPLAY). **
19 | ** **
20 | ** Exports: xresourceFinish **
21 | ** cmdXResource **
22 | ** **
23 | ** Notes: Fragments of this code are from the original xrdb **
24 | ** source, Copyright 1987 & 1991 by DIGITAL EQUIPMENT **
25 | ** CORPORATION. Xrdb was written and modified by: **
26 | ** **
27 | ** Jim Gettys, August 28, 1987 **
28 | ** Phil Karlton, January 5, 1987 **
29 | ** Bob Scheifler, February, 1991 **
30 | ** **
31 | ** ToDo/Bugs: + The command only handles screen independant re- **
32 | ** sources. **
33 | ** ************************************************************************ **
34 | ****/
35 |
36 | /** ** Copyright *********************************************************** **
37 | ** **
38 | ** Copyright 1991-1994 by John L. Furlan. **
39 | ** see LICENSE.GPL, which must be provided, for details **
40 | ** **
41 | ** ************************************************************************ **/
42 |
43 | static char Id[] = "@(#)$Id: cmdXResource.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
44 | static void *UseId[] = { &UseId, Id };
45 |
46 | /** ************************************************************************ **/
47 | /** HEADERS **/
48 | /** ************************************************************************ **/
49 |
50 | #include "modules_def.h"
51 |
52 | #ifdef HAS_X11LIBS
53 | #include <X11/Xlib.h>
54 | #include <X11/Xatom.h>
55 | #endif
56 |
57 | /** ************************************************************************ **/
58 | /** LOCAL DATATYPES **/
59 | /** ************************************************************************ **/
60 |
61 | #ifdef HAS_X11LIBS
62 | typedef struct _ResourceDB {
63 | Tcl_HashTable *data;
64 | Window root;
65 | Atom prop;
66 | } ResourceDB;
67 | #endif
68 |
69 | /** ************************************************************************ **/
70 | /** CONSTANTS **/
71 | /** ************************************************************************ **/
72 |
73 | #ifndef R_OK
74 | #define F_OK 0 /** does file exist **/
75 | #define X_OK 1 /** is it executable by caller **/
76 | #define W_OK 2 /** is it writable by caller **/
77 | #define R_OK 4 /** is it readable by caller **/
78 | #endif
79 |
80 | /** ************************************************************************ **/
81 | /** MACROS **/
82 | /** ************************************************************************ **/
83 |
84 | #ifdef HAS_X11LIBS
85 | #define MAXHOSTNAME 255
86 | #define Resolution( pixels, mm) (((pixels * 100000 / mm) + 50) / 100)
87 | #endif
88 |
89 | /** ************************************************************************ **/
90 | /** LOCAL DATA **/
91 | /** ************************************************************************ **/
92 |
93 | static char module_name[] = "cmdXResource.c"; /** File name of this module **/
94 |
95 | #if WITH_DEBUGGING_UTIL_2
96 | static char _proc_addDef[] = "addDef";
97 | static char _proc_addNum[] = "addNum";
98 | #endif
99 | #if WITH_DEBUGGING_UTIL_1
100 | static char _proc_doDisplayDefines[] = "doDisplayDefines";
101 | static char _proc_doScreenDefines[] = "doScreenDefines";
102 | static char _proc_readFile[] = "readFile";
103 | static char _proc_getEntries[] = "getEntries";
104 | static char _proc_storeResProp[] = "storeResProp";
105 | static char _proc_getOld[] = "getOld";
106 | static char _proc_initBuffers[] = "initBuffers";
107 | static char _proc_xresourceFinish[] = "xresourceFinish";
108 | #endif
109 | #if WITH_DEBUGGING_CALLBACK
110 | static char _proc_cmdXResource[] = "cmdXResource";
111 | #endif
112 |
113 | #ifdef HAS_X11LIBS
114 | static Display *dpy = (Display *) NULL;
115 | static char *defines = (char *) NULL;
116 | static int def_base = 0;
117 | static Tcl_DString *buffer = (Tcl_DString *) NULL;
118 | static ResourceDB resDB = { NULL, (Window) 0, (Atom) 0 };
119 | #endif
120 |
121 | /** ************************************************************************ **/
122 | /** PROTOTYPES **/
123 | /** ************************************************************************ **/
124 |
125 | static void addDef( char*, char*);
126 | static void addNum( char*, int);
127 | static void doDisplayDefines(void);
128 | static void doScreenDefines( int);
129 | static int readFile( register FILE *, int);
130 | static ErrType getEntries(Tcl_Interp*, Tcl_HashTable*, register char*, int);
131 | #ifdef HAS_X11LIBS
132 | static void storeResProp( register ResourceDB* );
133 | #endif
134 | static ErrType getOld( register char**);
135 | static ErrType initBuffers(Tcl_Interp*, register int );
136 |
137 | #ifdef HAS_X11LIBS
138 |
139 | /*++++
140 | ** ** Function-Header ***************************************************** **
141 | ** **
142 | ** Function: addDef, addNum **
143 | ** **
144 | ** Description: Adds DEFINES to the define buffer. This code is main-**
145 | ** ly the same as in the original xrdb.c **
146 | ** **
147 | ** First Edition: 1991/10/23 **
148 | ** **
149 | ** Parameters: char *title Name of the resource **
150 | ** char *value and its value **
151 | ** **
152 | ** Result: - **
153 | ** **
154 | ** Attached Globals: defines Buffer for all DEFINES which will be **
155 | ** written here in command lien syntax: **
156 | ** -D <titel>=<value> **
157 | ** **
158 | ** ************************************************************************ **
159 | ++++*/
160 |
161 | static void addDef( char *title,
162 | char *value)
163 | {
164 | register int quote;
165 |
166 | #if WITH_DEBUGGING_UTIL_2
167 | ErrorLogger( NO_ERR_START, LOC, _proc_addDef, NULL);
168 | #endif
169 |
170 | /**
171 | ** Add '-D title' at first
172 | **/
173 |
174 | if( title && *title) {
175 |
176 | strcat( defines, " -D");
177 | strcat( defines, title);
178 |
179 | /**
180 | ** Add the value if there is one
181 | **/
182 |
183 | if( value && *value) {
184 |
185 | quote = (value && strchr( value, ' '));
186 | strcat( defines, (quote ? "=\"" : "="));
187 | strcat( defines, value);
188 | if( quote)
189 | strcat( defines,"\"");
190 |
191 | } /** if( value) **/
192 | } /** if( title) **/
193 |
194 | } /** End of 'addDef' **/
195 |
196 | static void addNum( char *title,
197 | int value)
198 | {
199 | char num[ 20];
200 |
201 | #if WITH_DEBUGGING_UTIL_2
202 | ErrorLogger( NO_ERR_START, LOC, _proc_addNum, NULL);
203 | #endif
204 |
205 | sprintf( num, "%d", value);
206 | addDef( title, num);
207 |
208 | } /** End of 'addNum' **/
209 |
210 | /*++++
211 | ** ** Function-Header ***************************************************** **
212 | ** **
213 | ** Function: doDisplayDefines **
214 | ** **
215 | ** Description: Put the client and server specific defines on the **
216 | ** define buffer **
217 | ** **
218 | ** First Edition: 1991/10/23 **
219 | ** **
220 | ** Parameters: - **
221 | ** **
222 | ** Result: - **
223 | ** **
224 | ** Attached Globals: dpy For seeking the name of the display **
225 | ** defines (via addDef and addNum) **
226 | ** **
227 | ** ************************************************************************ **
228 | ++++*/
229 |
230 | static void doDisplayDefines()
231 | {
232 | char client[ MAXHOSTNAME], /** X client name buffer **/
233 | server[ MAXHOSTNAME], /** X server name buffer **/
234 | *colon; /** Pointer for seeking the **/
235 | /** colon in the server name **/
236 | #if WITH_DEBUGGING_UTIL_1
237 | ErrorLogger( NO_ERR_START, LOC, _proc_doDisplayDefines, NULL);
238 | #endif
239 |
240 | /**
241 | ** Get client and server hostname. Remove everything after the ':' from
242 | ** the server name. If there's no server name available, the server de-
243 | ** faults to the client.
244 | **/
245 |
246 | gethostname(client,MAXHOSTNAME);
247 | strcpy( server, XDisplayName( NULL));
248 |
249 | if( colon = strchr( server, ':'))
250 | *colon = '\0';
251 | if( !*server)
252 | strcpy( server, client);
253 |
254 | /**
255 | ** Add the standard defines now ...
256 | **/
257 |
258 | addDef( "HOST", server);
259 | addDef( "SERVERHOST", server);
260 | addDef( "CLIENTHOST", client);
261 | addNum( "VERSION", ProtocolVersion( dpy));
262 | addNum( "REVISION", ProtocolRevision( dpy));
263 | addDef( "VENDOR", ServerVendor( dpy));
264 | addNum( "RELEASE", VendorRelease( dpy));
265 |
266 | } /** End of 'doDisplayDefines' **/
267 |
268 | /*++++
269 | ** ** Function-Header ***************************************************** **
270 | ** **
271 | ** Function: doScreenDefines **
272 | ** **
273 | ** Description: Put the screen specific defines on the define buffer **
274 | ** **
275 | ** First Edition: 1991/10/23 **
276 | ** **
277 | ** Parameters: int scrno Screen number **
278 | ** **
279 | ** Result: - **
280 | ** **
281 | ** Attached Globals: dpy For seeking the name of the display **
282 | ** defines (via addDef and addNum) **
283 | ** **
284 | ** ************************************************************************ **
285 | ++++*/
286 |
287 | static void doScreenDefines( int scrno)
288 | {
289 | register Screen *screen;
290 | register Visual *visual;
291 |
292 | #if WITH_DEBUGGING_UTIL_1
293 | ErrorLogger( NO_ERR_START, LOC, _proc_doScreenDefines, NULL);
294 | #endif
295 |
296 | /**
297 | ** Get screen data at first
298 | **/
299 |
300 | screen = ScreenOfDisplay( dpy, scrno);
301 | visual = DefaultVisualOfScreen( screen);
302 |
303 | /**
304 | ** Put screen data on the defines buffer
305 | **/
306 |
307 | addNum( "WIDTH", screen->width);
308 | addNum( "HEIGHT", screen->height);
309 | addNum( "X_RESOLUTION", Resolution( screen->width, screen->mwidth));
310 | addNum( "Y_RESOLUTION", Resolution( screen->height, screen->mheight));
311 | addNum( "PLANES", DisplayPlanes( dpy, scrno));
312 | addNum( "BITS_PER_RGB", visual->bits_per_rgb);
313 |
314 | /**
315 | ** The CLASS and COLOR do depend on the screen class
316 | **/
317 |
318 | switch(visual->class) {
319 |
320 | case StaticGray: addDef( "CLASS", "StaticGray");
321 | break;
322 |
323 | case GrayScale: addDef( "CLASS", "GrayScale");
324 | break;
325 |
326 | case StaticColor: addDef( "CLASS", "StaticColor");
327 | addDef( "COLOR", NULL);
328 | break;
329 |
330 | case PseudoColor: addDef( "CLASS", "PseudoColor");
331 | addDef( "COLOR", NULL);
332 | break;
333 |
334 | case TrueColor: addDef( "CLASS", "TrueColor");
335 | addDef( "COLOR", NULL);
336 | break;
337 |
338 | case DirectColor: addDef( "CLASS", "DirectColor");
339 | addDef( "COLOR", NULL);
340 | break;
341 | } /** switch **/
342 |
343 | } /** End of 'doScreenDefines' **/
344 |
345 | /*++++
346 | ** ** Function-Header ***************************************************** **
347 | ** **
348 | ** Function: readFile **
349 | ** **
350 | ** Description: Read resource from a file, which normally is a pipe **
351 | ** opened with popen. **
352 | ** The file will be closed, when reading is finished **
353 | ** **
354 | ** Note: This routine uses the global variable 'line', declar-**
355 | ** ed in another file!!! **
356 | ** **
357 | ** First Edition: 1991/10/23 **
358 | ** **
359 | ** Parameters: register FILE *input The stream to be read from **
360 | ** int do_cpp Differs betweem a pipe or a **
361 | ** file being assigned to input **
362 | ** **
363 | ** Result: - **
364 | ** **
365 | ** Attached Globals: line Buffer for a line to be read **
366 | ** buffer Buffer for the whole resource file **
367 | ** image **
368 | ** **
369 | ** ************************************************************************ **
370 | ++++*/
371 |
372 | static int readFile( register FILE *input,
373 | int do_cpp)
374 | {
375 | register int bytes;
376 |
377 | #if WITH_DEBUGGING_UTIL_1
378 | ErrorLogger( NO_ERR_START, LOC, _proc_readFile, NULL);
379 | #endif
380 |
381 | while( !feof( input) && (bytes = fread( line, 1, LINELENGTH, input)))
382 | Tcl_DStringAppend( buffer, line, bytes);
383 |
384 | if( do_cpp) {
385 | if( -1 == pclose( input))
386 | if( OK != ErrorLogger( ERR_PCLOSE, LOC, NULL))
387 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
388 | } else {
389 | if( EOF == fclose( input))
390 | if( OK != ErrorLogger( ERR_CLOSE, LOC, NULL))
391 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
392 | }
393 |
394 | return( TCL_OK);
395 |
396 | } /** End of 'readFile' **/
397 |
398 | /*++++
399 | ** ** Function-Header ***************************************************** **
400 | ** **
401 | ** Function: getEntries **
402 | ** **
403 | ** Description: Updates the resources database (which is a Tcl hash **
404 | ** table) with the resources passed in the buffer. The **
405 | ** buffer contains a X resource lookalike text image. **
406 | ** **
407 | ** First Edition: 1991/10/23 **
408 | ** **
409 | ** Parameters: Tcl_Interp *interp According Tcl interp.**
410 | ** Tcl_HashTable *data The hash tables holding the **
411 | ** resource data **
412 | ** register char *buf The buffer containing the **
413 | ** resources to be modified in **
414 | ** X resource syntax **
415 | ** int remove Remove or add resources **
416 | ** **
417 | ** Result: ErrType NO_ERR Success **
418 | ** ERR_PARSE Parse error **
419 | ** **
420 | ** Attached Globals: - **
421 | ** **
422 | ** ************************************************************************ **
423 | ++++*/
424 |
425 | static ErrType getEntries( Tcl_Interp *interp,
426 | Tcl_HashTable *data,
427 | register char *buf,
428 | int remove)
429 | {
430 | Tcl_RegExp res_exp = (Tcl_RegExp) NULL;
431 | register Tcl_HashEntry *entry;
432 | char *end;
433 | int new_res;
434 |
435 | #if WITH_DEBUGGING_UTIL_1
436 | ErrorLogger( NO_ERR_START, LOC, _proc_getEntries, NULL);
437 | #endif
438 |
439 | /**
440 | ** The following regular expression matches pattern like
441 | **
442 | ** <resource>: <value>
443 | **
444 | ** The resource will be returned as \1 and the value as \2
445 | ** Set the regexp pointer only, if it hasn't already been set. This
446 | ** is a constant regexp!
447 | **/
448 |
449 | if( !res_exp)
450 | res_exp = Tcl_RegExpCompile(interp,
451 | "^[ \t]*([^ \t]*)[ \t]*:[ \t]*(.*)[ \t]*$");
452 |
453 | /**
454 | ** Seek for the lines (buffers) end. Put a terminator there. Take care of
455 | ** escaped newlines!
456 | **/
457 |
458 | for( end = buf; *end; end++)
459 | if( *end == '\\' && *(end+1) == '\n')
460 | end++;
461 | else if( *end == '\n')
462 | *end = '\0';
463 |
464 | /**
465 | ** Now read the whole buffer.
466 | ** At first, we have to ignore comments
467 | **/
468 |
469 | while( buf <= end) {
470 |
471 | if( *buf == '#' || *buf == '!' || !*buf) {
472 | while( *buf++) ;
473 |
474 | /**
475 | ** Otherwise we're seeking for a syntacticl correct X resource entry
476 | **/
477 |
478 | } else if( !Tcl_RegExpExec(interp, res_exp, buf, buf)) {
479 | if( OK != ErrorLogger( ERR_PARSE, LOC, NULL)) {
480 | return( ERR_PARSE); /** ------ EXIT (PARSE ERROR) -----> **/
481 | }
482 |
483 | } else {
484 |
485 | /**
486 | ** Valid entry found. Set up buf pointing behind the pattern
487 | ** that has matched and put a terminator at the end of either the
488 | ** resource name and its value.
489 | **/
490 |
491 | char *startp, *endp;
492 | Tcl_RegExpRange(res_exp, 0,
493 | (CONST84 char **) &startp, (CONST84 char **) &endp);
494 | buf = endp + 1;
495 | Tcl_RegExpRange(res_exp, 1,
496 | (CONST84 char **) &startp, (CONST84 char **) &endp);
497 | *endp = '\0';
498 | Tcl_RegExpRange(res_exp, 2,
499 | (CONST84 char **) &startp, (CONST84 char **) &endp);
500 | *endp = '\0';
501 |
502 | /**
503 | ** Now create (or remove) a hash entry for the parsed resource
504 | **/
505 |
506 | if( remove) {
507 | Tcl_RegExpRange(res_exp, 1,
508 | (CONST84 char **) &startp, (CONST84 char **) &endp);
509 | if( entry = Tcl_FindHashEntry( data, startp)) {
510 | null_free((void *) &( Tcl_GetHashValue( entry)));
511 | Tcl_DeleteHashEntry( entry);
512 | }
513 | } else {
514 | Tcl_RegExpRange(res_exp, 1,
515 | (CONST84 char **) &startp, (CONST84 char **) &endp);
516 | entry = Tcl_CreateHashEntry( data, startp, &new_res);
517 | if( !new_res)
518 | null_free((void *) &( Tcl_GetHashValue( entry)));
519 | Tcl_RegExpRange(res_exp, 2,
520 | (CONST84 char **) &startp, (CONST84 char **) &endp);
521 | Tcl_SetHashValue( entry, strdup( startp));
522 | }
523 |
524 | } /** if( reg exp matched) **/
525 | } /** while **/
526 |
527 | /**
528 | ** Return on success
529 | **/
530 |
531 | return( NO_ERR);
532 |
533 | } /** end of 'getEntries' **/
534 |
535 | /*++++
536 | ** ** Function-Header ***************************************************** **
537 | ** **
538 | ** Function: storeResProp **
539 | ** **
540 | ** Description: Update the X11 resource property, adding new resour- **
541 | ** ces. **
542 | ** **
543 | ** First Edition: 1991/10/23 **
544 | ** **
545 | ** Parameters: register ResourceDB *rdb Resource database **
546 | ** **
547 | ** Result: - **
548 | ** **
549 | ** Attached Globals: - **
550 | ** **
551 | ** ************************************************************************ **
552 | ++++*/
553 |
554 | #ifdef HAS_X11LIBS
555 | static void storeResProp( register ResourceDB *rdb)
556 | {
557 | Tcl_HashSearch search;
558 | register int mode = PropModeReplace;
559 | register int max = (XMaxRequestSize( dpy) << 2) - 28;
560 | register int left;
561 | register Tcl_HashEntry *entry = Tcl_FirstHashEntry( rdb->data, &search);
562 | unsigned char *buf;
563 |
564 | #if WITH_DEBUGGING_UTIL_1
565 | ErrorLogger( NO_ERR_START, LOC, _proc_storeResProp, NULL);
566 | #endif
567 |
568 | /**
569 | ** Write all attached resources into the buffer. Follow the X
570 | ** resource syntax:
571 | **
572 | ** <resource>: <value>
573 | **/
574 |
575 | Tcl_DStringTrunc( buffer, 0);
576 | while( entry) {
577 | Tcl_DStringAppend( buffer, Tcl_GetHashKey(rdb->data, entry), -1);
578 | Tcl_DStringAppend( buffer, ":\t", 2);
579 | Tcl_DStringAppend( buffer, (char *)Tcl_GetHashValue( entry), -1);
580 | Tcl_DStringAppend( buffer, "\n", 1);
581 | entry = Tcl_NextHashEntry( &search);
582 | }
583 |
584 | /**
585 | ** In case of the request being larger than the largest request the X
586 | ** server may handle, spool it block by block until the final one.
587 | **/
588 |
589 | buf = (unsigned char *) Tcl_DStringValue( buffer);
590 | if( max < (left = Tcl_DStringLength( buffer))) {
591 | XGrabServer( dpy);
592 | mode = PropModeAppend;
593 | do {
594 | XChangeProperty( dpy, rdb->root, rdb->prop, XA_STRING, 8, mode, buf,
595 | max);
596 | buf += max;
597 | } while( max < (left -= max));
598 | }
599 |
600 | /**
601 | ** Put the final request block (which may be the only one, if the if-
602 | ** statement above doesn't match) to the X server
603 | **/
604 |
605 | XChangeProperty( dpy, rdb->root, rdb->prop, XA_STRING, 8, mode, buf, left);
606 |
607 | if( mode != PropModeReplace)
608 | XUngrabServer( dpy);
609 |
610 | } /** End of 'storeResProp' **/
611 | #endif
612 |
613 | /*++++
614 | ** ** Function-Header ***************************************************** **
615 | ** **
616 | ** Function: getOld **
617 | ** **
618 | ** Description: First, we have to find the resources already loaded **
619 | ** into the X11 resource property. This routine current-**
620 | ** ly only handles one screen, the default screen for **
621 | ** the DISPLAY. This routine should only be called if **
622 | ** resDB.data is NULL. **
623 | ** **
624 | ** First Edition: 1991/10/23 **
625 | ** **
626 | ** Parameters: register char **buf Buffer for the old resource **
627 | ** database **
628 | ** **
629 | ** Result: ErrType ERR_PARAM resDB.data != NULL **
630 | ** ERR_ALLOC out of memory **
631 | ** NO_ERR Success **
632 | ** **
633 | ** Attached Globals: resDB The data area will be installed as a **
634 | ** Tcl hash table **
635 | ** dpy The current display **
636 | ** **
637 | ** ************************************************************************ **
638 | ++++*/
639 |
640 | static ErrType getOld( register char **buf)
641 | {
642 |
643 | #if WITH_DEBUGGING_UTIL_1
644 | ErrorLogger( NO_ERR_START, LOC, _proc_getOld, NULL);
645 | #endif
646 |
647 | /**
648 | ** Allocate memory for the hash table
649 | **/
650 |
651 | if( resDB.data)
652 | if( OK != ErrorLogger( ERR_PARAM, LOC, "Resource database", NULL))
653 | return( ERR_PARAM); /** ------- EXIT (PARAMETER) -----> **/
654 |
655 | if( !(resDB.data = (Tcl_HashTable *) malloc( sizeof( Tcl_HashTable))))
656 | if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
657 | return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/
658 |
659 | /**
660 | ** Initialize the hash table and read in the old resources
661 | **/
662 |
663 | Tcl_InitHashTable( resDB.data, TCL_STRING_KEYS);
664 | resDB.root = RootWindow( dpy, 0);
665 | resDB.prop = XA_RESOURCE_MANAGER;
666 | *buf = XResourceManagerString( dpy);
667 |
668 | /**
669 | ** Success
670 | **/
671 |
672 | return( NO_ERR);
673 |
674 | } /** End of 'getOld' **/
675 |
676 | /*++++
677 | ** ** Function-Header ***************************************************** **
678 | ** **
679 | ** Function: initBuffers **
680 | ** **
681 | ** Description: Initilize buffers if not already done, or reinitia- **
682 | ** lize some variables if buffers already exists. **
683 | ** **
684 | ** First Edition: 1991/10/23 **
685 | ** **
686 | ** Parameters: Tcl_Interp *interp According Tcl interp.**
687 | ** register int is_file Differs between a single X **
688 | ** resource to be modified or **
689 | ** a resource file to be merged**
690 | ** **
691 | ** Result: ErrType ERR_DISPLAY Cannot open DISPLAY **
692 | ** ERR_ALLOC ALLOC failure **
693 | ** ERR_EXTRACT **
694 | ** NO_ERR Success **
695 | ** **
696 | ** Attached Globals: dpy Display will be openend **
697 | ** resDB Resource database will be filled up **
698 | ** with the current setup **
699 | ** defines **
700 | ** **
701 | ** ************************************************************************ **
702 | ++++*/
703 |
704 | static ErrType initBuffers( Tcl_Interp *interp,
705 | register int is_file)
706 | {
707 | char *tmpbuf;
708 |
709 | #if WITH_DEBUGGING_UTIL_1
710 | ErrorLogger( NO_ERR_START, LOC, _proc_initBuffers, NULL);
711 | #endif
712 |
713 | /**
714 | ** Open the display
715 | **/
716 |
717 | if( !dpy && !(dpy = XOpenDisplay( NULL)))
718 | if( OK != ErrorLogger( ERR_DISPLAY, LOC, NULL))
719 | return( ERR_DISPLAY); /** -------- EXIT (FAILURE) -------> **/
720 |
721 | /**
722 | ** Read in the old setup at first and put it into the resource database
723 | **/
724 |
725 | if( !resDB.data) {
726 |
727 | if( getOld( &tmpbuf) != NO_ERR) /** NULL if no resources exists **/
728 | if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
729 | return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/
730 |
731 | if( tmpbuf && (getEntries(interp, resDB.data, tmpbuf, 0) != NO_ERR))
732 | if( OK != ErrorLogger( ERR_EXTRACT, LOC, NULL))
733 | return( ERR_EXTRACT);
734 | }
735 |
736 | /**
737 | ** Conditionally allocate a buffer and initialize this guy
738 | **/
739 |
740 | if( !buffer) {
741 | if( !(buffer = (Tcl_DString *) malloc( sizeof( Tcl_DString)))) {
742 | if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
743 | return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/
744 | } else
745 | Tcl_DStringInit( buffer);
746 | } else
747 | Tcl_DStringTrunc( buffer, 0);
748 |
749 | /**
750 | ** Set up all the defines according display and screen
751 | **/
752 |
753 | if( defines)
754 | defines[ def_base] = '\0';
755 | else if( is_file) {
756 |
757 | if( !(defines = (char *) malloc( BUFSIZ * sizeof( char))))
758 | if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
759 | return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/
760 |
761 | /* sprintf( defines, "%s %s ", CPPSTDIN, CPPMINUS); */
762 | strcpy( defines, CPPSTDIN);
763 | strcat( defines, " ");
764 | strcat( defines, CPPMINUS);
765 | strcat( defines, " ");
766 | doDisplayDefines();
767 | doScreenDefines( DefaultScreen( dpy));
768 | def_base = strlen( strcat( defines, " "));
769 | }
770 |
771 | /**
772 | ** Return on success
773 | **/
774 |
775 | return( NO_ERR);
776 |
777 | } /** End of 'initBuffers' **/
778 | #endif
779 |
780 | /*++++
781 | ** ** Function-Header ***************************************************** **
782 | ** **
783 | ** Function: xresourceFinish **
784 | ** **
785 | ** Description: Update the resource property if everything is ok. **
786 | ** This routine should be called when all properies have**
787 | ** been defines or updated. Remember that this routine **
788 | ** always will be called, even if there was no **
789 | ** "x-resource" command in the module! **
790 | ** **
791 | ** First Edition: 1991/10/23 **
792 | ** **
793 | ** Parameters: **
794 | ** **
795 | ** Result: **
796 | ** **
797 | ** Attached Globals: - **
798 | ** **
799 | ** ************************************************************************ **
800 | ++++*/
801 |
802 | void xresourceFinish(register int no_errors)
803 | {
804 |
805 | #if WITH_DEBUGGING_UTIL_1
806 | ErrorLogger( NO_ERR_START, LOC, _proc_xresourceFinish, NULL);
807 | #endif
808 |
809 | #ifdef HAS_X11LIBS
810 |
811 | /**
812 | ** If there is data stored in the resource database, spool it to the
813 | ** according X server
814 | **/
815 |
816 | if( resDB.data && no_errors)
817 | storeResProp( &resDB);
818 |
819 | /**
820 | ** Close the display and free what has been used
821 | **/
822 |
823 | if( dpy)
824 | XCloseDisplay( dpy);
825 | if( buffer)
826 | Tcl_DStringFree( buffer);
827 |
828 | #endif
829 |
830 | } /** End of 'xresourceFinish' **/
831 |
832 | /*++++
833 | ** ** Function-Header ***************************************************** **
834 | ** **
835 | ** Function: cmdXResource **
836 | ** **
837 | ** Description: Callback function for 'x-resource'. The function **
838 | ** sets up a hash table containing all resources to be **
839 | ** passed to the X server. This hash table will be **
840 | ** flushed whenever the function xresourceFinish is cal-**
841 | ** led. **
842 | ** **
843 | ** First Edition: 1991/10/23 **
844 | ** **
845 | ** Parameters: ClientData client_data **
846 | ** Tcl_Interp *interp According Tcl interp.**
847 | ** int argc Number of arguments **
848 | ** char *argv[] Argument array **
849 | ** **
850 | ** Result: int TCL_OK Successfull completion **
851 | ** TCL_ERROR Any error **
852 | ** **
853 | ** Attached Globals: g_flags These are set up accordingly before **
854 | ** this function is called in order to **
855 | ** control everything **
856 | ** **
857 | ** ************************************************************************ **
858 | ++++*/
859 |
860 | int cmdXResource( ClientData client_data,
861 | Tcl_Interp *interp,
862 | int argc,
863 | CONST84 char *argv[])
864 | {
865 | register FILE *inp;
866 | int is_file, i,
867 | do_cpp = 1,
868 | opt_ind = 1;
869 |
870 | #if WITH_DEBUGGING_CALLBACK
871 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdXResource, NULL);
872 | #endif
873 |
874 | /**
875 | ** Whatis mode?
876 | **/
877 |
878 | if( g_flags & (M_WHATIS | M_HELP))
879 | return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/
880 |
881 | if( !getenv("DISPLAY")) {
882 | /* don't bother trying to set display variables, if there is no display */
883 | return(TCL_OK);
884 | }
885 |
886 |
887 | /**
888 | ** Parameter check
889 | **/
890 |
891 | if( argc > 1 && !strcmp( argv[1], "-nocpp")) {
892 | do_cpp = 0;
893 | opt_ind++;
894 | }
895 |
896 | if( argc <= opt_ind) {
897 | if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "[ -nocpp ] strings", NULL))
898 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
899 | }
900 |
901 | /**
902 | ** Ok, now let's treat all remaining arguments as X resources or
903 | ** X resource files. At first let's check if it is a file ...
904 | **/
905 |
906 | while( opt_ind < argc) {
907 | is_file = (access( argv[ opt_ind], R_OK & F_OK) == 0);
908 |
909 | #ifdef HAS_X11LIBS
910 |
911 | if( g_flags & M_DISPLAY) {
912 | fprintf( stderr, "xrdb -merge\t ");
913 | for( i=1; i<argc; i++)
914 | fprintf( stderr, "%s ", argv[ i]);
915 | fprintf( stderr, "\n");
916 |
917 | } else {
918 |
919 | /**
920 | ** Initialize read buffers
921 | **/
922 |
923 | if( NO_ERR != initBuffers(interp, is_file))
924 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
925 |
926 | /**
927 | ** This puts all required resources into a text image buffer ...
928 | **/
929 |
930 | if( !is_file) {
931 | Tcl_DStringAppend( buffer, argv[ opt_ind], -1);
932 | } else {
933 |
934 | if( NULL == (inp = (do_cpp ?
935 | popen( strcat( defines, argv[ opt_ind]), "r") :
936 | fopen( argv[ opt_ind], "r")) ) )
937 | if( OK != ErrorLogger( (do_cpp ? ERR_POPEN : ERR_OPEN), LOC,
938 | "argv[ opt_ind]", "reading" ))
939 | return( TCL_ERROR); /** ---- EXIT (FAILURE) ---> **/
940 |
941 | if( TCL_ERROR == readFile( inp, do_cpp))
942 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
943 | }
944 |
945 | /**
946 | ** ... and this transforms the text image buffer into a Tcl hash
947 | ** table
948 | **/
949 |
950 | if( NO_ERR != getEntries(interp, resDB.data,
951 | Tcl_DStringValue( buffer), g_flags & M_REMOVE)) {
952 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
953 | }
954 | }
955 | #else
956 | if( g_flags & M_DISPLAY) {
957 | fprintf( stderr, "xrdb -merge\t ");
958 | for( i=1; i<argc; i++)
959 | fprintf( stderr, "%s ", argv[ i]);
960 | fprintf( stderr, "*** ignored ***\n");
961 | }
962 | #endif
963 |
964 | opt_ind++;
965 |
966 | } /** while **/
967 |
968 | #if WITH_DEBUGGING_CALLBACK
969 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdXResource, NULL);
970 | #endif
971 |
972 | return( TCL_OK);
973 |
974 | } /** End of 'cmdXResource' **/