Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!igor!amber!geb From: geb@amber.Rational.COM (Gary E. Barnes) Newsgroups: comp.windows.x Subject: Re: Programs relying on app-defaults files Message-ID: <571@igor.Rational.COM> Date: 25 May 89 03:26:57 GMT References: <1242@harrier.ukc.ac.uk> <1045@sragwa.sra.JUNET> Sender: news@Rational.COM Reply-To: geb@amber.Rational.COM (Gary E. Barnes) Organization: Rational, Santa Clara, CA Lines: 131 What you want to do with resource defaults is very reasonable. I have the same bone to pick with the X toolkits. I don't believe in "normal" applications that fail to function just because some parameter file is not in place. It is very nice (even vital) to be able to change virtually any behavior of a program but the author of a program should have the option of creating a totally self contained application. Something like Emacs may be somewhat silly without several (hundreds?) of separate files but many other utilites (like xclock) would be silly if they required app-defaults files in order to function properly. If nothing else an application should be able to fail "gracefully" if a required file or a set of required parameterizations are not present. The toolkit gives you no way of knowing whether your app-defaults file existed (and was readable/useable/complete). Below is a very-stripped-down piece of code that I use when I have some resources that I want to set up within the program. My default values are used "first" but any and all of them can be overridden by an appropriately named app-defaults file, a .Xdefaults file entry, or the command line; just like in any other X application. There are two ways to accomplish what you want with the current toolkit intrinsics. The first scenario is this: 1) do XtInitialize - this reads in all of the normal resource sources 2) do XtGetApplicationResources - this gets you either a) your internal-to-the- program default values or else the system/user/cmd-line-supplied values 3) destroy the top level widget that XtInitialize gave you; it isn't usable because it was not created with your default values in mind 4) use XtSetArg with the resources we got in step 2 to create an ArgList and then do an XtCreateApplicationShell(toplevelShellWidgetClass) to get a shell with the same name and class as we got from XtInitialize but which has your/the-system's/the-user's/the-cmd-line's resource values in it An alternative scenario that works just as well is: 1) do toplevel = XtInitialize - this reads the normal resources and gets you a toplevel widget 2) do XrmPutLineResource call(s) to create a database called my_db which then contains only your internal-to-the-program default resource values 3) reach into XtDisplay(toplevel)->db to get the database created by the toolkit and do XrmMergeDatabase(XtDisplay(toplevel)->db,my_db) to merge the toolkit's database into your database (thus overriding your internal defaults with the system/user/command-line values) and then put your merged database into XtDisplay(toplevel)->db = my_db. This step is of course "bad form" because it uses "knowledge" about the Display structure; ie. the code "knows" that there is a db field that contains the database. 4) destroy the toplevel widget you got from XtInitialize 5) use XtCreateApplicationShell(topLevelShellWidgetClass) to get the "real" top level shell for your application. Here is the very-stripped-down sample code for the first scenario: ------------------------------------------------------------------------- typedef struct _Dragon_Resources_Rec{ Boolean Input; /* A random resource */ } Dragon_Resources_Rec, *Dragon_Resources_Ptr; static XtResource dragon_resources[] = { {XtNinput, XtCInput, XtRBoolean, sizeof(Boolean), XtOffset(Dragon_Resources_Ptr, Input), XtRBoolean, (caddr_t)"off"} }; static XrmOptionDescRec command_line_options[] = { {"-input", ".input", XrmoptionNoArg, (caddr_t)"on" }, }; int main (argc, argv) int argc; String *argv; { Arg args[40]; int argi = 0; #define SETARG(name,value) \ XtSetArg( args[argi], name, (XtArgVal)value ); ++argi; /*--Start up the toolkit. This creates a shell widget. Unfortunately the * only way the toolkit allows you to specify default application resources * is by having a /usr/lib/X11/app-defaults/Application resouce file. I'm * not interested in doing this. If some site wants to create one in order * to customize the program then that is fine. However, I want my program * to be "standalone"; ie. if you have the binary executable then you have * all you *must-have*. So, I will Destroy this widget shortly. */ Program_Name = argv[0]; Dragon = XtInitialize ( "dragon", "Dragon", command_line_options, XtNumber(command_line_options), &argc, argv ); /*--Now get the application resources. */ XtGetApplicationResources( Dragon, (caddr_t)&Dragon_Resources, dragon_resources, XtNumber(dragon_resources), (ArgList)NULL, (Cardinal)0 ); /*--Now we set up our "real" application shell. */ XtDestroyWidget( Dragon ); /*--Set up various other controls on our top level widget that we require. * Especially note that we are using *topLevelShellWidgetClass*. This is * the only shell class that will use our main "Dragon" class name when * looking up resources in the database! */ SETARG( XtNinput, Dragon_Resources.Input ); Dragon = XtCreateApplicationShell( "dragon", topLevelShellWidgetClass, args, (Cardinal)argi ); /*--Other stuff and eventually we do... */ XtMainLoop(); } /* main */