1 /*
2  *  This file is part of the XForms library package.
3  *
4  *  XForms is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU Lesser General Public License as
6  *  published by the Free Software Foundation; either version 2.1, or
7  *  (at your option) any later version.
8  *
9  *  XForms is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with XForms.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /**
20  * \file flresource.c
21  *
22  *  This file is part of the XForms library package.
23  *  Copyright (c) 1996-2002  T.C. Zhao
24  *  All rights reserved.
25  *
26  *  Handle XResources. Only rudimetry support is implemented. However,
27  *  using this minimum implementation, more powerful and application
28  *  specific resources can be developed easily.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include "include/forms.h"
36 #include "flinternal.h"
37 #include "private/flsnprintf.h"
38 #include <X11/Xresource.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 
42 #if 0
43 #include <locale.h>
44 #endif
45 
46 #ifdef FL_WIN32
47 #include <X11/Xw32defs.h>
48 #endif
49 
50 
51 FLI_WM_STUFF fli_wmstuff;       /* also used in win.c */
52 static XrmDatabase fldatabase;  /* final merged database */
53 static XrmDatabase cmddb;       /* command line database */
54 static char *fl_app_name,
55             *fl_app_class,
56             *fl_ori_app_name;
57 
58 static void fli_init_resources( void );
59 static void fli_set_debug_level( int );
60 
61 /* Command line options */
62 
63 static XrmOptionDescRec copt[ ] =
64 {
65     { "-fldebug",   "*fldebug",          XrmoptionSepArg, ( caddr_t ) "0" },
66     { "-flversion", "*flversion",        XrmoptionNoArg,  ( caddr_t ) "1" },
67     { "-flhelp",    "*flhelp",           XrmoptionNoArg,  ( caddr_t ) "1" },
68     { "-name",      ".name",             XrmoptionSepArg, ( caddr_t ) 0   },
69     { "-display",   ".display",          XrmoptionSepArg, ( caddr_t ) 0   },
70     { "-sync",      "*sync",             XrmoptionNoArg,  ( caddr_t ) "1" },
71     { "-depth",     "*depth",            XrmoptionSepArg, ( caddr_t ) 0   },
72     { "-visual",    "*visual",           XrmoptionSepArg, ( caddr_t ) 0   },
73     { "-private",   "*privateColormap",  XrmoptionNoArg,  ( caddr_t ) "1" },
74     { "-shared",    "*sharedColormap",   XrmoptionNoArg,  ( caddr_t ) "1" },
75     { "-standard",  "*standardColormap", XrmoptionNoArg,  ( caddr_t ) "1" },
76     { "-stdcmap",   "*standardColormap", XrmoptionNoArg,  ( caddr_t ) "1" },
77     { "-double",    "*doubleBuffer",     XrmoptionNoArg,  ( caddr_t ) "1" },
78     { "-bw",        "*borderWidth",      XrmoptionSepArg, ( caddr_t ) 0   },
79     { "-vid",       "*visualID",         XrmoptionSepArg, ( caddr_t ) 0   },
80 
81 #ifdef DO_GAMMA_CORRECTION
82     { "-rgamma",    "*rgamma",           XrmoptionSepArg, ( caddr_t ) 0   },
83     { "-bgamma",    "*bgamma",           XrmoptionSepArg, ( caddr_t ) 0   },
84     { "-ggamma",    "*ggamma",           XrmoptionSepArg, ( caddr_t ) 0   },
85 #endif
86 
87     { "-bs",        "*backingStore",     XrmoptionNoArg, ( caddr_t ) "0"   }
88 };
89 
90 #define Ncopt  ( sizeof copt / sizeof *copt )
91 
92 
93 /* Other resources */
94 
95 #define PV( a )  &( fli_cntl.a )
96 #define PS( a )  ( fli_cntl.a )
97 #define NS( a )  #a
98 
99 
100 /* xform and XForm will be generated on the fly */
101 
102 typedef char Bop[ 8 ];      /* Boolean default */
103 typedef char Iop[ 8 ];      /* Integer default */
104 static Bop OpPrivateMap,
105            OpSharedMap,
106            OpStandardMap,
107            OpDouble;
108 static Bop OpSync,
109            OpULW = "1";
110 static Iop OpDebug,
111            OpDepth,
112            OpULT = "-1";
113 static char OpBS[ 12 ]       = "1"; /* whenmapped */
114 static char OpSafe[ 12 ];
115 static char OpSCBT[ 16 ]     = "thin";
116 static char OpBLsize[ 20 ]   = NS( FL_DEFAULT_SIZE );
117 static char OpMLsize[ 20 ]   = NS( FL_DEFAULT_SIZE );
118 static char OpBrFsize[ 20 ]  = NS( FL_DEFAULT_SIZE );
119 static char OpChFsize[ 20 ]  = NS( FL_DEFAULT_SIZE );
120 static char OpSLsize[ 20 ]   = NS( FL_DEFAULT_SIZE );
121 static char OpLLsize[ 20 ]   = NS( FL_DEFAULT_SIZE );
122 static char OpILsize[ 20 ]   = NS( FL_DEFAULT_SIZE );
123 static char OpIBW[ 20 ]      = NS( FL_BOUND_WIDTH  );
124 static char OpPsize[ 20 ]    = NS( FL_DEFAULT_SIZE );
125 static char OpVisualID[ 20 ] = "0";
126 
127 #ifdef DO_GAMMA_CORRECTION
128 static char OpRgamma[ 12 ] = "1";
129 static char OpGgamma[ 12 ] = "1";
130 static char OpBgamma[ 12 ] = "1";
131 #endif
132 
133 static char OpCoordUnit[ 32 ];
134 
135 static FLI_VN_PAIR vn_coordunit[ ] =
136 {
137     { FL_COORD_PIXEL,      "pixel"      },
138     { FL_COORD_MM,         "mm"         },
139     { FL_COORD_POINT,      "point"      },
140     { FL_COORD_centiPOINT, "centipoint" },
141     { FL_COORD_centiPOINT, "cp"         },
142     { FL_COORD_centiMM,    "centimm"    },
143     { FL_COORD_centiMM,    "cmm"        },
144     { -1,                  "Invalid"    },
145     { -1,                   NULL         }
146 };
147 
148 
149 #define SetR( name, rclass, type, deft, buflen ) \
150        { #name, rclass, type, &fli_cntl.name, deft, buflen }
151 
152 
153 static FL_resource internal_resources[ ] =
154 {
155     SetR( debug, "Debug", FL_INT,  OpDebug, 0 ),
156     SetR( sync,  "Sync",  FL_BOOL, OpSync,  0 ),
157 
158 #ifdef DO_GAMMA_CORRECTION
159     SetR( rgamma, "Gamma", FL_FLOAT, OpRgamma, 0 ),
160     SetR( ggamma, "Gamma", FL_FLOAT, OpGgamma, 0 ),
161     SetR( bgamma, "Gamma", FL_FLOAT, OpBgamma, 0 ),
162 #endif
163 
164     SetR( depth, "Depth", FL_INT, OpDepth, 0 ),
165     { "visual", "Visual", FL_STRING, PS( vname ), PS( vname ), 20 },
166     { "scrollbarType", "ScrollbarType", FL_STRING, OpSCBT, OpSCBT, 16 },
167     SetR( doubleBuffer, "DoubleBuffer", FL_BOOL, OpDouble, 0 ),
168     SetR( ulThickness, "ULThickness", FL_INT, OpULT, 0 ),
169     SetR( privateColormap, "PrivateColormap", FL_BOOL, OpPrivateMap, 0 ),
170     SetR( sharedColormap, "SharedColormap", FL_BOOL, OpSharedMap, 0 ),
171     SetR( standardColormap, "StandardColormap", FL_BOOL, OpStandardMap, 0 ),
172     SetR( buttonFontSize, "FontSize", FL_INT, OpBLsize, 0 ),
173     SetR( menuFontSize, "FontSize", FL_INT, OpMLsize, 0 ),
174     SetR( choiceFontSize, "FontSize", FL_INT, OpChFsize, 0 ),
175     SetR( browserFontSize, "FontSize", FL_INT, OpBrFsize, 0 ),
176     SetR( labelFontSize, "FontSize", FL_INT, OpLLsize, 0 ),
177     SetR( sliderLabelSize, "FontSize", FL_INT, OpSLsize, 0 ),
178     SetR( inputLabelSize, "FontSize", FL_INT, OpILsize, 0 ),
179     SetR( pupFontSize, "PupFontSize", FL_INT, OpPsize, 0 ),
180     SetR( borderWidth, "BorderWidth", FL_INT, OpIBW, 0 ),
181     SetR( ulPropWidth, "ULWidth", FL_BOOL, OpULW, 0 ),
182     SetR( backingStore, "BackingStore", FL_INT, OpBS, 0 ),
183     SetR( safe, "Safe", FL_INT, OpSafe, 0 ),
184     { "coordUnit", "CoordUnit", FL_STRING, OpCoordUnit, OpCoordUnit, 32 },
185     { "visualID", "VisualID", FL_LONG, &fli_requested_vid, OpVisualID, 0 }
186 };
187 
188 #define Niopt ( sizeof internal_resources / sizeof *internal_resources )
189 
190 
191 /* Program can set its own default, overriding XForms default */
192 
193 #define SetMember( a )   fli_cntl.a = cntl->a
194 
195 
196 /***************************************
197  ***************************************/
198 
199 void
fl_set_defaults(unsigned long mask,FL_IOPT * cntl)200 fl_set_defaults( unsigned long   mask,
201                  FL_IOPT       * cntl )
202 {
203     if ( mask & FL_PDPrivateMap )
204     {
205         SetMember( privateColormap );
206         sprintf( OpPrivateMap, "%d", cntl->privateColormap != 0 );
207     }
208 
209     if ( mask & FL_PDSharedMap )
210     {
211         SetMember( sharedColormap );
212         sprintf( OpSharedMap, "%d", cntl->sharedColormap != 0 );
213     }
214 
215     if ( mask & FL_PDStandardMap )
216     {
217         SetMember( standardColormap );
218         sprintf( OpStandardMap, "%d", cntl->standardColormap != 0 );
219     }
220 
221     if ( mask & FL_PDDouble )
222     {
223         SetMember( doubleBuffer );
224         sprintf( OpDouble, "%d", cntl->doubleBuffer != 0 );
225     }
226 
227     if ( mask & FL_PDDepth )
228     {
229         SetMember( depth );
230         sprintf( OpDepth, "%d", cntl->depth );
231     }
232 
233     if ( mask & FL_PDVisual )
234     {
235         SetMember( vclass );
236         strcpy( fli_cntl.vname, fli_vclass_name( cntl->vclass ) );
237     }
238 
239     if ( mask & FL_PDButtonFontSize )
240     {
241         SetMember( buttonFontSize );
242         sprintf( OpBLsize, "%d", cntl->buttonFontSize );
243     }
244 
245     if ( mask & FL_PDBrowserFontSize )
246     {
247         SetMember( browserFontSize );
248         sprintf( OpBrFsize, "%d", cntl->browserFontSize );
249     }
250 
251     if ( mask & FL_PDMenuFontSize )
252     {
253         SetMember( menuFontSize );
254         sprintf( OpMLsize, "%d", cntl->menuFontSize );
255     }
256 
257     if ( mask & FL_PDChoiceFontSize )
258     {
259         SetMember( choiceFontSize );
260         sprintf( OpChFsize, "%d", cntl->choiceFontSize );
261     }
262 
263     if ( mask & FL_PDSliderFontSize )
264     {
265         SetMember( sliderFontSize );
266         sprintf( OpSLsize, "%d", cntl->sliderFontSize );
267     }
268 
269     if ( mask & FL_PDInputFontSize )
270     {
271         SetMember( inputFontSize );
272         sprintf( OpILsize, "%d", cntl->inputFontSize );
273     }
274 
275     if ( mask & FL_PDLabelFontSize )
276     {
277         SetMember( labelFontSize );
278         sprintf( OpLLsize, "%d", cntl->labelFontSize );
279     }
280 
281     if ( mask & FL_PDBorderWidth )
282         fl_set_border_width( cntl->borderWidth );
283 
284     if ( mask & FL_PDScrollbarType )
285         fl_set_scrollbar_type( cntl->scrollbarType );
286 
287     if ( mask & FL_PDPupFontSize )
288     {
289         SetMember( pupFontSize );
290         sprintf( OpPsize, "%d", cntl->pupFontSize );
291     }
292 
293     if ( mask & FL_PDSafe )
294     {
295         SetMember( safe );
296         sprintf( OpSafe, "%d", cntl->safe );
297     }
298 
299     if ( mask & FL_PDBS )
300     {
301         SetMember( backingStore );
302         sprintf( OpBS, "%d", cntl->backingStore );
303     }
304 
305     if ( mask & FL_PDCoordUnit )
306         fl_set_coordunit( cntl->coordUnit );
307 
308     if ( mask & FL_PDDebug )
309         fli_set_debug_level( cntl->debug );
310 }
311 
312 
313 /***************************************
314  * Convenience functions
315  ***************************************/
316 
317 void
fl_set_coordunit(int u)318 fl_set_coordunit( int u )
319 {
320     const char * cu = fli_get_vn_name( vn_coordunit, u );
321 
322     if ( cu == NULL )
323     {
324         M_err( "fl_set_coordunit",
325                "Invald coord unit, defaulting to \"pixel\"" );
326         u = FL_COORD_PIXEL;
327         cu = "pixel";
328     }
329 
330     fli_cntl.coordUnit = u;
331     strcpy( OpCoordUnit, cu );
332 }
333 
334 
335 /***************************************
336  ***************************************/
337 
338 void
fl_set_border_width(int bw)339 fl_set_border_width( int bw )
340 {
341     fli_cntl.borderWidth = bw;
342     sprintf( OpIBW, "%d", bw );
343 }
344 
345 
346 /***************************************
347  ***************************************/
348 
349 void
fl_set_scrollbar_type(int t)350 fl_set_scrollbar_type( int t )
351 {
352     fli_cntl.scrollbarType = t;
353 
354     if ( t == FL_NORMAL_SCROLLBAR )
355         strcpy( OpSCBT, "normal" );
356     else if ( t == FL_NICE_SCROLLBAR )
357         strcpy( OpSCBT, "nice" );
358     else if ( t == FL_PLAIN_SCROLLBAR )
359         strcpy( OpSCBT, "plain" );
360     else
361         strcpy( OpSCBT, "thin" );
362 }
363 
364 
365 /***************************************
366  ***************************************/
367 
368 void
fl_set_visualID(long id)369 fl_set_visualID( long id )
370 {
371     fli_requested_vid = id;
372     sprintf( OpVisualID, "0x%lx", id );
373 }
374 
375 
376 /***************************************
377  ***************************************/
378 
379 int
fl_get_border_width(void)380 fl_get_border_width( void )
381 {
382     return fli_cntl.borderWidth;
383 }
384 
385 
386 /***************************************
387  ***************************************/
388 
389 int
fl_get_coordunit(void)390 fl_get_coordunit( void )
391 {
392     return fli_cntl.coordUnit;
393 }
394 
395 
396 /***************************************
397  ***************************************/
398 
399 static void
fli_set_debug_level(int l)400 fli_set_debug_level( int l )
401 {
402     fli_cntl.debug = l;
403     sprintf( OpDebug, "%d", fli_cntl.debug );
404     fli_set_msg_threshold( fli_cntl.debug );
405 }
406 
407 
408 /***************************************
409  * Handle XAPPLRESDIR (colon seperated directories) specification.
410  * Ignore the %T %N stuff
411  ***************************************/
412 
413 static void
handle_applresdir(const char * rstr,const char * appclass)414 handle_applresdir( const char * rstr,
415                    const char * appclass )
416 {
417     char *tok;
418     char rbuf[ 512 ],
419          buf[ 512 ];
420     XrmDatabase fdb = 0;
421 
422     strcpy( rbuf, rstr );
423     for ( tok = strtok( rbuf, ":" ); tok; tok = strtok( 0, ":" ) )
424     {
425         fli_snprintf( buf, sizeof buf,"%s/%s", tok,appclass );
426         M_info( "handle_applresdir", "Trying XAPPLRESDIR: %s", buf );
427         if ( ( fdb = XrmGetFileDatabase( buf ) ) )
428         {
429             XrmMergeDatabases( fdb, &fldatabase );
430             M_warn( "handle_applresdir", "XAPPLRESDIR %s loaded", buf );
431         }
432     }
433 }
434 
435 
436 /***************************************
437  * Routine to merge all resource databases, excluding the commandline,
438  * which is  done in fl_initialize.
439  ***************************************/
440 
441 static void
init_resource_database(const char * appclass)442 init_resource_database( const char *appclass )
443 {
444     char   buf[ FL_PATH_MAX + 127 ],
445          * rstr;
446     XrmDatabase fdb = 0;
447 
448     if ( ! fl_display )
449     {
450         M_err( "init_resource_database", "fl_initialize is not called" );
451         return;
452     }
453 
454     if ( fldatabase )
455         return;
456 
457     XrmInitialize( );
458 
459 #ifdef __VMS
460     /* For the VMS version try to load the resources from, in this order,
461 
462        DECW$SYSTEM_DEFAULTS:appclass.DAT
463        DECW$USER_DEFAULTS:appclass.DAT
464        DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT
465        The window resource manager for this display
466     */
467 
468     fli_snprintf( buf, sizeof buf, "DECW$SYSTEM_DEFAULTS:%s.DAT", appclass );
469     M_info( "init_resource_database", "Trying Sys_default: %s", buf );
470     if ( ( fdb = XrmGetFileDatabase( buf ) ) )
471     {
472         XrmMergeDatabases( fdb, &fldatabase );
473         M_warn( "init_resource_database", "System default %s loaded", buf );
474     }
475 
476     fli_snprintf( buf, sizeof buf, "DECW$USER_DEFAULTS:%s.DAT", appclass );
477     M_info( "init_resource_database", "Trying User_default: %s", buf );
478     if ( ( fdb = XrmGetFileDatabase( buf ) ) )
479     {
480         XrmMergeDatabases( fdb, &fldatabase );
481         M_warn( "init_resource_database", "System default %s loaded", buf );
482     }
483 
484     fli_snprintf( buf, sizeof buf, "DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT" );
485     M_info( "init_resource_database", "Trying Sys_default: %s", buf );
486     if ( ( fdb = XrmGetFileDatabase( buf ) ) )
487     {
488         XrmMergeDatabases( fdb, &fldatabase );
489         M_warn( "init_resource_database", "System default %s loaded", buf );
490     }
491 
492     M_info( "init_resource_database", "Trying RESOURCE_MANAGER" );
493     if ( ( rstr = XResourceManagerString( fl_display ) ) )
494     {
495         if ( ( fdb = XrmGetStringDatabase( rstr ) ) )
496         {
497             XrmMergeDatabases( fdb, &fldatabase );
498             M_warn( "init_resource_database", "RESOURCE_MANAGER loaded" );
499         }
500     }
501 #else /* !VMS */
502 
503     fli_snprintf( buf, sizeof buf, "/usr/lib/X11/app-defaults/%s", appclass );
504     M_info( "init_resource_database", "Trying Sys_default: %s", buf );
505     if ( ( fdb = XrmGetFileDatabase( buf ) ) )
506     {
507         XrmMergeDatabases( fdb, &fldatabase );
508         M_warn( "init_resource_database", "System default %s loaded", buf );
509     }
510 
511     /* try XAPPLRESDIR */
512 
513     M_info( "init_resource_database", "Trying XAPPLRESDIR" );
514     if ( ( rstr = getenv( "XAPPLRESDIR" ) ) )
515         handle_applresdir( rstr, appclass );
516 
517     /* try server defined resources */
518 
519     M_info( "init_resource_database", "Trying RESOURCE_MANAGER" );
520     if ( ( rstr = XResourceManagerString( fl_display ) ) )
521     {
522         if ( ( fdb = XrmGetStringDatabase( rstr ) ) )
523         {
524             XrmMergeDatabases( fdb, &fldatabase );
525             M_warn( "init_resource_database", "RESOURCE_MANAGER loaded" );
526         }
527     }
528     else
529     {
530         /* Try ~/.Xdefaults   */
531 
532         if ( ( rstr = getenv( "HOME" ) ) )
533         {
534             fli_snprintf( buf, sizeof buf,"%s/.Xdefaults", rstr );
535             M_info( "init_resource_database", "Trying %s", buf );
536             if ( ( fdb = XrmGetFileDatabase( buf ) ) )
537             {
538                 XrmMergeDatabases( fdb, &fldatabase );
539                 M_warn( "init_resource_database", "%s loaded", buf );
540             }
541         }
542     }
543 
544     /* Load file XENVIRONMENT */
545 
546     M_info( "init_resource_database",
547             "Trying environment variable XEVIRONMENT" );
548     if ( ( rstr = getenv( "XENVIRONMENT" ) ) )
549     {
550         if ( ( fdb = XrmGetFileDatabase( rstr ) ) )
551         {
552             XrmMergeDatabases( fdb, &fldatabase );
553             M_warn( "init_resource_database", "%s loaded", rstr );
554         }
555     }
556     else
557     {
558         /* ~/.Xdefaults-<hostname> */
559 
560         M_info( "init_resource_database", "Trying ~/.Xdefaults-<hostname>" );
561         if ( ( rstr = getenv( "HOME" ) ) )
562         {
563             int l;
564 
565             fli_snprintf( buf, sizeof buf,"%s/.Xdefaults", rstr );
566             l = strlen( strcat( buf, "-" ) );
567             gethostname( buf + l, sizeof buf - l );
568             M_info( "init_resource_database", "Trying %s", buf );
569             if ( ( fdb = XrmGetFileDatabase( buf ) ) )
570             {
571                 XrmMergeDatabases( fdb, &fldatabase );
572                 M_warn( "init_resource_database", "%s loaded", buf );
573             }
574         }
575     }
576 #endif /* VMS */
577 
578     errno = 0;
579 
580     if ( ! fldatabase )
581     {
582         M_warn( "init_resource_database",
583                 "Can't find any resource databases!" );
584         return;
585     }
586 }
587 
588 
589 /***************************************
590  ***************************************/
591 
592 static int
is_true(const char * s)593 is_true( const char * s )
594 {
595     return    strncmp( s, "True", 4 ) == 0
596            || strncmp( s, "true", 4 ) == 0
597            || strncmp( s, "Yes",  3 ) == 0
598            || strncmp( s, "yes",  3 ) == 0
599            || strncmp( s, "On",   2 ) == 0
600            || strncmp( s, "on",   2 ) == 0
601            || *s == '1';
602 }
603 
604 
605 /***************************************
606  * The resource routine of the lowest level. Only adds the application
607  * name.
608  *
609  * Return the string representation of the resource value
610  ***************************************/
611 
612 const char *
fl_get_resource(const char * rname,const char * cname,FL_RTYPE dtype,const char * defval,void * val,int size)613 fl_get_resource( const char * rname,    /* resource name */
614                  const char * cname,    /* class name    */
615                  FL_RTYPE     dtype,    /* data type     */
616                  const char * defval,   /* default       */
617                  void *       val,      /* variable      */
618                  int          size )    /* buffer size if string */
619 {
620     XrmValue entry = { 0, NULL };
621     char * type = NULL;
622     char res_name[ 256 ]  = "",
623          res_class[ 256 ] = "";
624 
625 
626     if ( ! ( rname && * rname ) && ! ( cname && *cname ) )
627         return NULL;
628 
629     if ( rname && *rname )
630         fli_snprintf( res_name, sizeof res_name, "%s.%s", fl_app_name, rname );
631     else
632         fli_snprintf( res_class, sizeof res_class, "%s.%s",
633                      fl_app_class, cname );
634 
635     /* Just checking the return value of XrmGetResource() doesn't seem to
636        work (as it should, unless I completely misunderstand the man
637        page), and 'entry' seems to return the same data as on a previous
638        call (despite the initialization!), but 'type' seems to get set to
639        NULL in cases of failure to find the requested resource in the
640        database. So in that case we try to use the default value.       JTT */
641 
642     if (    ! XrmGetResource( fldatabase, res_name, res_class, &type, &entry )
643          || ! type
644          || strcmp( type, "String" )
645          || ! entry.addr )
646     {
647         M_warn( "fl_get_resource", "%s (%s): not found", res_name, res_class );
648         entry.addr = ( XPointer ) defval;
649     }
650     else
651         M_info( "fl_get_resource", "%s (%s): %s", res_name, res_class,
652                 entry.addr );
653 
654     if ( dtype == FL_NONE || ! entry.addr )
655         return entry.addr;
656 
657     switch ( dtype )
658     {
659         case FL_SHORT:
660             * ( short * ) val = strtol( entry.addr, NULL, 10 );
661             break;
662 
663         case FL_INT:
664             * ( int * ) val = strtol( entry.addr, NULL, 10 );
665             break;
666 
667         case FL_BOOL:
668             * ( int * ) val = is_true( entry.addr );
669             break;
670 
671         case FL_LONG:
672             * ( long * ) val = strtol( entry.addr, NULL, 10 );
673             break;
674 
675         case FL_FLOAT:
676             * ( float * ) val = atof( entry.addr );
677             break;
678 
679         case FL_STRING:
680             if ( val && val != entry.addr && size > 0 )
681             {
682                 strncpy( val, entry.addr, size );
683                 ( ( char * ) val )[ size - 1 ] = '\0';
684             }
685             break;
686 
687         default:
688             M_err( "fl_get_resource", "Unknown type %d", dtype );
689             return NULL;
690     }
691 
692     return entry.addr;
693 }
694 
695 
696 /***************************************
697  ***************************************/
698 
699 void
fl_set_resource(const char * str,const char * val)700 fl_set_resource( const char * str,
701                  const char * val )
702 {
703     char res_name[ 256 ];
704 
705     fli_snprintf( res_name, sizeof res_name, "%s.%s", fl_app_name, str );
706     XrmPutStringResource( &fldatabase, res_name, ( char * ) val );
707 }
708 
709 
710 /***************************************
711  * internal resource initialization
712  ***************************************/
713 
714 static void
fli_init_resources(void)715 fli_init_resources( void )
716 {
717     char res[ 256 ],
718          cls[ 256 ],
719          ores[ 256 ];
720     char * appname = fl_app_name,
721          * appclass = fl_app_class;
722     char * ori_appname = fl_ori_app_name;
723 
724     /* internal resources need to be prefixed xform and XForm. need to
725        generate for all names */
726 
727     fli_snprintf( cls, sizeof cls, "%s.XForm", fl_app_class );
728     fl_app_class = cls;
729     fli_snprintf( res, sizeof res, "%s.xform", fl_app_name );
730     fl_app_name = res;
731     fli_snprintf( ores, sizeof ores, "%s.xform", fl_ori_app_name );
732     fl_ori_app_name = ores;
733     fl_get_app_resources( internal_resources, Niopt );
734 
735     fl_app_name = appname;
736     fl_app_class = appclass;
737     fl_ori_app_name = ori_appname;
738 
739     if ( fli_cntl.sync )
740     {
741         XSynchronize( fl_display, 1 );
742         M_err( "fli_init_resources", "**** Synchronous Mode ********" );
743         fli_set_debug_level( 4 );
744     }
745 }
746 
747 
748 static int fli_argc;
749 static char ** fli_argv;
750 
751 
752 /***************************************
753  ***************************************/
754 
755 static void
dup_argv(char ** argv,int n)756 dup_argv( char ** argv,
757           int     n )
758 {
759     int i;
760 
761     if ( ! argv )
762         return;
763 
764     if ( ! fli_argv )
765         fli_argv = fl_malloc( ( n + 1 ) * sizeof *fli_argv );
766 
767     for ( i = 0; i < n; i++ )
768         fli_argv[ i ] = fl_strdup( argv[ i ] );
769 
770     fli_argv[ i ] = NULL;
771 }
772 
773 
774 /***************************************
775  ***************************************/
776 
777 char **
fl_get_cmdline_args(int * n)778 fl_get_cmdline_args( int * n )
779 {
780     *n = fli_argc;
781     return fli_argv;
782 }
783 
784 
785 /***************************************
786  ***************************************/
787 
788 void
fli_free_cmdline_args(void)789 fli_free_cmdline_args( void )
790 {
791     size_t i;
792 
793     if ( ! fli_argv )
794         return;
795 
796     for ( i = 0; fli_argv[ i ]; i++ )
797         fli_safe_free( fli_argv[ i ] );
798 
799     fli_safe_free( fli_argv );
800 }
801 
802 
803 /***************************************
804  * find the command name from arg[0] and return a copy of it
805  ***************************************/
806 
807 static char *
get_command_name(const char * arg0)808 get_command_name( const char * arg0 )
809 {
810     char *p;
811     char *s = fl_strdup( arg0 );
812     char *cmd_name = s;
813 
814 #ifdef __VMS
815     /* vms command disk:[path]command.exe  */
816 
817     if ( ( p = strrchr( s, ']' ) ) )
818         cmd_name = p + 1;
819 #else
820 #ifdef FL_WIN32
821     _splitpath( arg0, NULL, NULL, cmd_name, NULL );
822 #else
823     if ( ( p = strrchr( s, '/' ) ) )
824         cmd_name = p + 1;
825 #endif
826 #endif
827 
828     /* Remove the extension and the period */
829 
830     if ( ( p = strrchr( cmd_name, '.' ) ) )
831         *p = '\0';
832 
833     /* Prevent a valgrind warning about a possible memory leak. */
834 
835     if ( s != cmd_name )
836     {
837         cmd_name = fl_strdup( cmd_name );
838         fl_free( s );
839     }
840 
841     return cmd_name;
842 }
843 
844 
845 /*
846  * Global Routines to do the initialization and resource management
847  *
848  */
849 
850 #define DumpD( a )    fprintf( stderr,"\t%s:%d\n", #a, fli_cntl.a )
851 #define DumpS( a )    fprintf( stderr,"\t%s:%s\n", #a, fli_cntl.a )
852 #define DumpF( a )    fprintf( stderr,"\t%s:%.3f\n", #a, fli_cntl.a )
853 
854 static Window fli_GetVRoot( Display *,
855                             int );
856 
857 
858 /***************************************
859  * initialize context
860  ***************************************/
861 
862 void
fli_init_context(void)863 fli_init_context( void )
864 {
865     if ( fli_context )
866         return;
867 
868     if ( ! ( fli_context = fl_calloc( 1, sizeof *fli_context ) ) )
869     {
870         M_err( "fli_init_context", "Running out of memory" );
871         exit( 1 );
872     }
873 
874     fli_context->io_rec        = NULL;
875     fli_context->idle_rec      = NULL;
876     fli_context->atclose       = NULL;
877     fli_context->signal_rec    = NULL;
878     fli_context->idle_delta    = FLI_TIMER_RES;
879     fli_context->hscb          = FL_HOR_THIN_SCROLLBAR;
880     fli_context->vscb          = FL_VERT_THIN_SCROLLBAR;
881     fli_context->navigate_mask = ShiftMask;   /* to navigate input field */
882     fli_context->xim = NULL;
883     fli_context->xic = NULL;
884 }
885 
886 
887 /***************************************
888  ***************************************/
889 
890 void
fli_set_input_navigate(unsigned int mask)891 fli_set_input_navigate( unsigned int mask )
892 {
893      fli_init_context( );
894 
895      if ( mask == ShiftMask || mask == Mod1Mask || mask == ControlMask )
896          fli_context->navigate_mask = mask;
897 }
898 
899 
900 /***************************************
901  ***************************************/
902 
903 Display *
fl_initialize(int * na,char * arg[],const char * appclass,FL_CMD_OPT * appopt,int nappopt)904 fl_initialize( int        * na,
905                char       * arg[ ],
906                const char * appclass,
907                FL_CMD_OPT * appopt,
908                int          nappopt )
909 {
910     char disp_name[ 256 ],
911          disp_cls[ 256 ],
912          buf[ 256 ];
913     XrmValue xval;
914     char *type;
915     float xdpi,
916           ydpi;
917 
918     if ( fl_display )
919     {
920         M_warn( "fl_initialize", "XForms: already initialized" );
921         return fl_display;
922     }
923 
924     /* Be paranoid */
925 
926     if ( ! na || ! *na )
927     {
928         M_err( "fl_initialize",
929                "XForms: argc == 0 or argv == NULL detected\n" );
930         exit( 1 );
931     }
932 
933     fli_internal_init( );
934 
935     XrmInitialize( );
936 
937     /* Save a copy of the command line for later WM hints */
938 
939     fli_argc = *na;
940     dup_argv( arg, *na );
941 
942     /* Get appname and class, but without any leading paths  */
943 
944     fl_ori_app_name = fl_app_name = get_command_name( arg[ 0 ] );
945     fl_app_class = fl_strdup( ( appclass && *appclass ) ?
946                               appclass : fl_app_name );
947 
948     /* Make class name upper case if non supplied */
949 
950     if ( ! appclass || ! *appclass )
951     {
952         fl_app_class[ 0 ] = toupper( fl_app_class[ 0 ] );
953         if ( fl_app_class[ 0 ] == 'X' )
954             fl_app_class[ 1 ] = toupper( fl_app_class[ 1 ] );
955     }
956 
957     /* Do form internal resouces first */
958 
959     XrmParseCommand( &cmddb, copt, Ncopt, fl_app_name, na, arg );
960 
961     /* if there are still more left and  appopt is not zero */
962 
963     if ( appopt && na && *na )
964         XrmParseCommand( &cmddb, appopt, nappopt,
965                          ( char * ) fl_ori_app_name, na, arg );
966 
967     /* Check version request */
968 
969     fli_snprintf( disp_name, sizeof disp_name, "%s.fl_version", fl_app_name );
970     fli_snprintf( disp_cls, sizeof disp_cls, "%s.flversion", fl_app_name );
971 
972     if ( XrmGetResource( cmddb, disp_name, disp_cls, &type, &xval ) )
973         fli_print_version( 0 );
974 
975     /* Get the display name first before doing anything */
976 
977     fli_snprintf( disp_name, sizeof disp_name, "%s.display", fl_ori_app_name );
978     fli_snprintf( disp_cls , sizeof disp_cls , "%s.Display", fl_app_class );
979 
980     *buf = '\0';
981 
982     if ( XrmGetResource( cmddb, disp_name, disp_cls, &type, &xval ) )
983     {
984         strncpy( buf, xval.addr, sizeof buf );
985         buf[ sizeof buf - 1 ] = '\0';
986     }
987 
988     /* Open display and quit on failure */
989 
990     if ( ! ( fl_display = XOpenDisplay( buf ) ) )
991     {
992         /* if no display is set, there is no guarantee that buf
993            is long enough to contain the DISPLAY setting */
994 
995         M_err( "fl_initialize", "%s: Can't open display %s", fli_argv[ 0 ],
996                XDisplayName( buf[ 0 ] ? buf : 0 ) );
997         return 0;
998     }
999 
1000     flx->display = fl_display;
1001     flx->screen  = fl_screen;
1002 
1003     /* Get debug level settings since all error reporting will be controled
1004        by it */
1005 
1006     fli_snprintf( disp_name, sizeof disp_name, "%s.fldebug", fl_app_name );
1007     fli_snprintf( disp_cls , sizeof disp_cls , "%s.flDebug", fl_app_class );
1008     if ( XrmGetResource( cmddb, disp_name, disp_cls, &type, &xval ) )
1009         fli_set_debug_level( atoi( xval.addr ) );
1010 
1011     /* print help */
1012 
1013     fli_snprintf( disp_name, sizeof disp_name, "%s.flhelp", fl_app_name );
1014     fli_snprintf( disp_cls , sizeof disp_cls , "%s.flhelp", fl_app_class );
1015 
1016     if ( XrmGetResource( cmddb, disp_name, disp_cls, &type, &xval ) )
1017     {
1018         size_t i = 0;
1019 
1020         while ( i < Ncopt )
1021         {
1022             if ( i == 0 )
1023                 fprintf( stderr, "%s: ", fli_argv[ 0 ] );
1024             else
1025                 fprintf( stderr, "%*s  ",
1026                          ( int ) strlen( fli_argv[ 0 ] ), "" );
1027 
1028             fprintf( stderr, " %s", copt[ i ].option );
1029 
1030             if ( copt[ i ].argKind == XrmoptionSepArg )
1031                 fprintf( stderr, " \t[arg]" );
1032             fprintf( stderr, "\n" );
1033             i++;
1034         }
1035 
1036         exit(1);
1037     }
1038 
1039     /* Check if -name is present */
1040 
1041     fli_snprintf( disp_name, sizeof disp_name, "%s.name", fl_app_name );
1042     fli_snprintf( disp_cls,  sizeof disp_cls , "%s.Name", fl_app_class );
1043 
1044     M_warn( "fl_initialize", "Trying display %s", disp_name );
1045 
1046     if ( XrmGetResource( cmddb, disp_name, disp_cls, &type, &xval ) )
1047     {
1048         fl_app_name = fl_strdup( xval.addr );
1049         M_warn( "fl_initialize", "Changed AppName from %s to %s",
1050                 fl_ori_app_name, fl_app_name );
1051     }
1052 
1053     /* Merge  other resource database */
1054 
1055     init_resource_database( fl_app_class );
1056 
1057     /* Override any options in the database with the command line opt */
1058 
1059     XrmMergeDatabases( cmddb, &fldatabase );
1060 
1061     /* Load FL resources */
1062 
1063     fli_init_resources( );
1064 
1065     fli_cntl.vclass = fli_vclass_val( fli_cntl.vname );
1066     fli_cntl.coordUnit = fli_get_vn_value( vn_coordunit, OpCoordUnit );
1067     if ( fli_cntl.coordUnit == -1 )
1068         fli_cntl.coordUnit = FL_COORD_PIXEL;
1069 
1070 #if FL_DEBUG >= ML_WARN
1071     if ( fli_cntl.debug )
1072     {
1073         fprintf( stderr, "Options Set\n" );
1074         DumpD( debug );
1075         fprintf( stderr, "\tVisual:%s (%d)\n",
1076                  fli_cntl.vclass >= 0 ?
1077                  fli_vclass_name( fli_cntl.vclass ) : "To be set",
1078                  fli_cntl.vclass );
1079         DumpD( depth );
1080         DumpD( privateColormap );
1081         DumpD( sharedColormap );
1082         DumpD( standardColormap );
1083         DumpD( doubleBuffer );
1084         DumpD( ulPropWidth );
1085         DumpD( ulThickness );
1086         DumpD( scrollbarType );
1087         DumpD( backingStore );
1088         fprintf( stderr, "\t%s:%s\n", "coordUnit",
1089                  fli_get_vn_name( vn_coordunit, fli_cntl.coordUnit ) );
1090         fprintf( stderr, "\t%s: 0x%lx\n", "VisualId", fli_requested_vid );
1091 
1092 #ifdef DO_GAMMA_CORRECTION
1093         DumpF( rgamma );
1094         DumpF( ggamma );
1095         DumpF( bgamma );
1096 #endif
1097     }
1098 #endif
1099 
1100 #ifdef DO_GAMMA_CORRECTION
1101     fl_set_gamma( fli_cntl.rgamma, fli_cntl.ggamma, fli_cntl.bgamma );
1102 #endif
1103 
1104     fli_set_ul_property( fli_cntl.ulPropWidth, fli_cntl.ulThickness );
1105 
1106     fli_cntl.vclass = fli_vclass_val( fli_cntl.vname );
1107 
1108     /* Get the current keyboard state */
1109 
1110     {
1111         XKeyboardState xks;
1112 
1113         XGetKeyboardControl( fl_display, &xks );
1114         fli_keybdcontrol.auto_repeat_mode = xks.global_auto_repeat;
1115         fli_keybdmask = KBAutoRepeatMode;
1116     }
1117 
1118     /* Other initializations */
1119 
1120     fl_screen = flx->screen = DefaultScreen( fl_display );
1121     fl_root                 = RootWindow( fl_display, fl_screen );
1122     fl_vroot                = fli_GetVRoot( fl_display, fl_screen );
1123     fli_wmstuff.pos_request = USPosition;
1124 
1125     if ( fl_root != fl_vroot )
1126     {
1127         M_warn( "fl_initialize", "fl_root = %lu fl_vroot = %lu",
1128                 fl_root, fl_vroot );
1129 
1130         /* tvtwm requires this to position a window relative to the current
1131            desktop */
1132 
1133         fli_wmstuff.pos_request = PPosition;
1134     }
1135 
1136     fl_scrh = DisplayHeight( fl_display, fl_screen );
1137     fl_scrw = DisplayWidth( fl_display, fl_screen );
1138 
1139     xdpi = fl_scrw * 25.4 / DisplayWidthMM( fl_display, fl_screen );
1140     ydpi = fl_scrh * 25.4 / DisplayHeightMM( fl_display, fl_screen );
1141 
1142     if ( xdpi / ydpi > 1.05 || ydpi / xdpi < 0.95 )
1143         M_warn( "fl_initialize", "NonSquarePixel %.1f %.1f", xdpi, ydpi );
1144 
1145     fl_dpi = ( xdpi + ydpi ) / 2;
1146     fl_dpi = FL_nint( fl_dpi * 10.0 + 0.5 ) * 0.1;
1147 
1148     M_info( "fl_initialize", "screen DPI = %f", fl_dpi );
1149 
1150     fl_vmode = fli_initialize_program_visual( );
1151     fli_init_colormap( fl_vmode );
1152     fli_init_font( );
1153     fli_init_context( );
1154 
1155 #ifdef XlibSpecificationRelease
1156     if ( XSupportsLocale( ) )
1157     {
1158         XSetLocaleModifiers( "" );
1159 
1160         /* Use the same input method throughout xforms */
1161 
1162         fli_context->xim = XOpenIM( fl_display, NULL, NULL, NULL );
1163 
1164         /* Also use the same input context */
1165 
1166         if ( fli_context->xim )
1167         {
1168             int style =  XIMPreeditNothing | XIMStatusNothing;
1169 
1170             fli_context->xic = XCreateIC( fli_context->xim,
1171                                           XNInputStyle, style,
1172                                           ( char * ) NULL );
1173 
1174         /* Clean-up on failure */
1175 
1176             if ( ! fli_context->xic )
1177             {
1178                 M_err( "fl_initialize", "Could not create an input context" );
1179                 XCloseIM( fli_context->xim );
1180             }
1181         }
1182         else
1183             M_err( "fl_initialize", "Could not create an input method" );
1184     }
1185 #endif
1186 
1187     fli_default_xswa( );
1188     fli_init_stipples( );
1189 
1190     /* If using non-default visual or private colormap, need a window with
1191        correct visual/colormap and depth */
1192 
1193     fl_state[ fl_vmode ].trailblazer = fl_root;
1194 
1195     if (    fli_visual( fl_vmode ) != DefaultVisual( fl_display, fl_screen )
1196          || fl_state[ fl_vmode ].pcm )
1197     {
1198         fl_state[ fl_vmode ].trailblazer =
1199            fli_create_window( fl_root, fli_colormap( fl_vmode ),
1200                               "trailblazer" );
1201     }
1202 
1203     if ( strcmp( OpSCBT, "plain" ) == 0 )
1204     {
1205         fli_context->hscb = FL_HOR_PLAIN_SCROLLBAR;
1206         fli_context->vscb = FL_VERT_PLAIN_SCROLLBAR;
1207     }
1208     else if ( strcmp( OpSCBT, "normal" ) == 0 )
1209     {
1210         fli_context->hscb = FL_HOR_SCROLLBAR;
1211         fli_context->vscb = FL_VERT_SCROLLBAR;
1212     }
1213     else if ( ! strcmp( OpSCBT, "thin" ) )
1214     {
1215         fli_context->hscb = FL_HOR_THIN_SCROLLBAR;
1216         fli_context->vscb = FL_VERT_THIN_SCROLLBAR;
1217     }
1218     else if ( ! strcmp( OpSCBT, "nice" ) )
1219     {
1220         fli_context->hscb = FL_HOR_NICE_SCROLLBAR;
1221         fli_context->vscb = FL_VERT_NICE_SCROLLBAR;
1222     }
1223 
1224     fli_context->max_request_size = XMaxRequestSize( fl_display );
1225 
1226     if ( fli_context->max_request_size < 4096 )
1227     {
1228         M_err( "fl_initialize", "Something is wrong with max_request_size: %ld",
1229                fli_context->max_request_size );
1230         fli_context->max_request_size = 4096;
1231     }
1232 
1233 
1234 #if XlibSpecificationRelease >= 6
1235     fli_context->ext_request_size = XExtendedMaxRequestSize( fl_display );
1236 #else
1237     fli_context->ext_request_size = 0;
1238 #endif
1239 
1240     if ( ! fli_context->ext_request_size )
1241         fli_context->ext_request_size = fli_context->max_request_size;
1242 
1243     fli_context->max_request_size -= 8;
1244     fli_context->ext_request_size -= 8;
1245     fli_context->tooltip_time = 600;
1246 
1247     fl_add_io_callback( ConnectionNumber( fl_display ), FL_READ, NULL, NULL );
1248 
1249     /* Has to be here, otherwise fl_add_symbol won't be able to replace the
1250        built-in */
1251 
1252     fli_init_symbols( );
1253 
1254     /* Hang the database on the display so application can get it */
1255 
1256     XrmSetDatabase( fl_display, fldatabase );
1257 
1258     /* Initialize popup system */
1259 
1260     fli_popup_init( );
1261 
1262     return fl_display;
1263 }
1264 
1265 
1266 /***************************************
1267  * Cleanup everything. At the moment, only need to restore the keyboard
1268  * settings and deallocate memory used for the object and event queue etc.
1269  ***************************************/
1270 
1271 void
fl_finish(void)1272 fl_finish( void )
1273 {
1274     /* Make sure the connection is alive */
1275 
1276     if ( ! flx->display )
1277         return;
1278 
1279     XChangeKeyboardControl( flx->display, fli_keybdmask,
1280                             &fli_keybdcontrol );
1281 
1282     fli_remove_all_signal_callbacks( );
1283     fli_remove_all_timeouts( );
1284 
1285     /* Get rid of all forms, first hide all of them */
1286 
1287     while ( fli_int.formnumb > 0 )
1288         fl_hide_form( fli_int.forms[ 0 ] );
1289 
1290     /* Now also delete them (to deallocate memory) - problem is that the
1291        tooltip form may only be deleted as the very last one since the objects
1292        that have a tooltip (and that get deleted in the process of deleting
1293        the form they belong to) still try to access the tooltip form */
1294 
1295     while ( fli_int.hidden_formnumb > 0 )
1296     {
1297         if (    fli_int.hidden_formnumb > 1
1298              && fli_is_tooltip_form( fli_int.forms[ 0 ] ) )
1299             fl_free_form( fli_int.forms[ 1 ] );
1300         else
1301             fl_free_form( fli_int.forms[ 0 ] );
1302     }
1303 
1304     /* Delete the object and event queue */
1305 
1306     fli_obj_queue_delete( );
1307     fli_event_queue_delete( );
1308 
1309     /* Free memory allocated in xtext.c */
1310 
1311     fli_free_xtext_workmem( );
1312 
1313     /* Release memory used for symbols */
1314 
1315     fli_release_symbols( );
1316 
1317     /* Release memory allocated in goodies */
1318 
1319     fli_goodies_cleanup( );
1320 
1321     /* Release memory allocated for file selectors */
1322 
1323     fli_free_fselectors( );
1324 
1325     /* Release memory used by the popup system */
1326 
1327     fli_popup_finish( );
1328 
1329     /* Release memory used for the copy of the command line arguments */
1330 
1331     fli_free_cmdline_args( );
1332 
1333     /* Release memory used for cursors */
1334 
1335     fli_free_cursors( );
1336 
1337     /* Free memory used for colormaps */
1338 
1339     fli_free_colormap( fl_vmode );
1340 
1341     /* Get rid of memory for input methods */
1342 
1343 #ifdef XlibSpecificationRelease
1344     if ( fli_context && XSupportsLocale( ) && fli_context->xim )
1345     {
1346         if ( fli_context->xic )
1347             XDestroyIC( fli_context->xic );
1348         XCloseIM( fli_context->xim );
1349     }
1350 #endif
1351 
1352     if ( fli_context )
1353         while ( fli_context->io_rec )
1354             fl_remove_io_callback( fli_context->io_rec->source,
1355                                    fli_context->io_rec->mask,
1356                                    fli_context->io_rec->callback );
1357 
1358     fli_safe_free( fli_context );
1359 
1360     /* Close the display */
1361 
1362     XCloseDisplay( flx->display );
1363     flx->display = fl_display = None;
1364 }
1365 
1366 
1367 /***************************************
1368  * Find out about virtual root. Taken from XFaq
1369  ***************************************/
1370 
1371 #include <X11/Xatom.h>
1372 
1373 static int
xerror_handler(Display * d FL_UNUSED_ARG,XErrorEvent * xev)1374 xerror_handler( Display     * d  FL_UNUSED_ARG,
1375                 XErrorEvent * xev )
1376 {
1377     return xev->error_code;
1378 }
1379 
1380 
1381 static Window
fli_GetVRoot(Display * dpy,int scr)1382 fli_GetVRoot( Display * dpy,
1383               int       scr )
1384 {
1385     Window rootReturn;
1386     Window parentReturn;
1387     Window *children;
1388     unsigned int numChildren;
1389     Window root = RootWindow( dpy, scr );
1390     Atom __SWM_VROOT = None;
1391     unsigned int i;
1392     int ( * oldhandler )( Display *, XErrorEvent * );
1393 
1394     __SWM_VROOT = XInternAtom( dpy, "__SWM_VROOT", False );
1395     XQueryTree( dpy, root, &rootReturn, &parentReturn, &children,
1396                 &numChildren );
1397 
1398     /* For some reasons XQueryTree sometimes seems to return an invalid window
1399        in the list of children (perhaps the window  vanishes between the call
1400        of XQueryTree() and the subsequent call of XGetWindowProperty()?). To
1401        avoid a program using XForms aborting with a strange X error message on
1402        start-up, we catch these errors with a temporary error handler (which
1403        gets reset before leaving the function). */
1404 
1405     oldhandler = XSetErrorHandler( xerror_handler );
1406 
1407     for ( i = 0; i < numChildren; i++ )
1408     {
1409         Atom actual_type;
1410         int actual_format;
1411         unsigned long nitems, bytesafter;
1412         Window *newRoot = NULL;
1413 
1414         /* Kludge here: the ( void * ) bit in
1415            ( unsigned char ** ) ( void * ) &newRoot
1416            is there to avoid a spurious  GCC warning         JTT */
1417 
1418         children[ i ] = 0;
1419         if (    XGetWindowProperty( dpy, children[ i ], __SWM_VROOT, 0, 1,
1420                                     False, XA_WINDOW, &actual_type,
1421                                     &actual_format, &nitems, &bytesafter,
1422                                     ( unsigned char ** ) ( void * ) &newRoot )
1423                                                                     == Success
1424              && newRoot )
1425         {
1426             root = *newRoot;
1427             break;
1428         }
1429     }
1430 
1431     XSetErrorHandler( oldhandler );
1432     XFree( ( char * ) children );
1433     return root;
1434 }
1435 
1436 
1437 /***************************************
1438  * For Application programs
1439  ***************************************/
1440 
1441 static void
fli_get_app_resource(FL_resource * appresource,int n)1442 fli_get_app_resource( FL_resource * appresource,
1443                       int           n )
1444 {
1445     FL_resource *flr = appresource,
1446                 *flrs = flr + n;
1447 
1448     for ( ; flr < flrs; flr++ )
1449         if ( flr->type == FL_STRING && flr->nbytes == 0 )
1450             M_err( "fl_get_app_resources", "%s: buflen == 0", flr->res_name );
1451     else
1452         fl_get_resource( flr->res_name, flr->res_class,
1453                          flr->type, flr->defval, flr->var, flr->nbytes );
1454 }
1455 
1456 
1457 /***************************************
1458  ***************************************/
1459 
1460 void
fl_get_app_resources(FL_resource * appresource,int n)1461 fl_get_app_resources( FL_resource * appresource,
1462                       int           n )
1463 {
1464     char *tmp = fl_app_name;
1465 
1466     fl_app_name = fl_ori_app_name;
1467     fli_get_app_resource( appresource, n );
1468 
1469     if ( fl_app_name != tmp )
1470     {
1471         fl_app_name = tmp;
1472         fli_get_app_resource( appresource, n );
1473     }
1474 }
1475 
1476 
1477 /***************************************
1478  ***************************************/
1479 
1480 void
fl_flip_yorigin(void)1481 fl_flip_yorigin( void )
1482 {
1483     if ( ! fl_display )
1484         fli_inverted_y = 1;
1485     else
1486         M_err( "fl_flip_yorigin", "Only supported before fl_initialize" );
1487 }
1488 
1489 
1490 /***************************************
1491  ***************************************/
1492 
1493 void
fli_set_app_name(const char * n,const char * c)1494 fli_set_app_name( const char * n,
1495                   const char * c )
1496 {
1497     if ( n )
1498         fl_app_name = fl_strdup( n );
1499     if ( c )
1500         fl_app_class = fl_strdup( c );
1501 }
1502 
1503 
1504 /*
1505  * Local variables:
1506  * tab-width: 4
1507  * indent-tabs-mode: nil
1508  * End:
1509  */
1510