Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 42.  Managing User Preferences

App-Defaults Files

We will assume that it is sufficient to have two sources of application defaults: a per-application database and a per-user database. In addition, we will allow for some resources to be specific to color and monochrome displays. The following example initializes the preference package by reading in the per-application and per-user resource specification files. There is also an initialization of the global array pref that will be used to hold state information about the preferences package. The Pref_Init procedure is called like this:

Pref_Init $library/foo-defaults ~/.foo-defaults

We assume $library is the directory holding support files for the foo application, and that per-user defaults will be kept in ~/.foo-defaults. These are UNIX-oriented file names. When you write cross-platform Tk applications, you will find that some file names are inherently platform-specific. The platform-independent operations described in Chapter 9 are great, but they do not change the fact that user preferences may be stored in c:/webtk/userpref.txt on Windows, Hard Disk:System:Preferences:WebTk Prefs on Macintosh, and ~/.webtk on UNIX. I find it useful to have a small amount of platform-specific startup code that defines these pathnames. The preference package uses resource files that work on all platforms:

Example 42-1 Preferences initialization.
proc Pref_Init { userDefaults appDefaults } {
   global pref

   set pref(uid) 0 ;# for a unique identifier for widgets
   set pref(userDefaults) $userDefaults
   set pref(appDefaults) $appDefaults
   PrefReadFile $appDefaults startup
   if [file exists $userDefaults] {
      PrefReadFile $userDefaults user
proc PrefReadFile { basename level } {
   if [catch {option readfile $basename $level}err] {
      Status "Error in $basename: $err"
   if {[string match *color* [winfo visual .]]} {
      if [file exists $basename-color] {
         if [catch {option readfile \
               $basename-color $level}err] {
            Status "Error in $basename-color: $err"
   } else {
     if [file exists $basename-mono] {
        if [catch {option readfile $basename-mono \
              $level}err] {
           Status "Error in $basename-mono: $err"

The PrefReadFile procedure reads a resource file and then looks for another file with the suffix -color or -mono depending on the characteristics of the display. With this scheme, a UNIX user puts generic settings in ~/.foo-defaults. They put color specifications in ~/.foo-defaults-color. They put specifications for black and white displays in ~/.foo-defaults-mono. You could extend PrefReadFile to allow for per-host files as well.

Throughout this chapter we assume that the Status procedure displays messages to the user. It could be as simple as:

proc Status { s } {puts stderr $s }

      Previous section   Next section