CONFIG_FILE
Applications use configuration files to store information that otherwise would be lost when an application is closed. These files typically contain such kind of information as user preferences, configuration of the application, information about the last working session and so on.
In Microsoft Windows applications a configuration file called initialization file and usually is stored in the WINDOWS directory with the .ini extension. The configuration file consists of a number of sections with a number of entries in each section. Each entry has an associated string value.
The structure of typical configuration file is the following one:
[Section1] Entry1=Value Entry2=Value Entry3=Value [Section2] Entry4=Value
More precise:
{"["Section_name"]"[{entry_name"="[entry_value]}]}
In square brackets the names of section are placed to represent a group (section) of the configuration parameters. The entry items are placed after. Each of them has zero or more pieces of information to be stored with this entry. To access the information you must specify its section and entry name.
For example configuration files can look like as follows:
[My program settings] Version=1.31 WorkDir=C:\TMP Options=2 [Last session] WorkFile1=SIMPLE.TXT WorkFile2= AutoCheck=On
Under Windows 95 and Windows NT registry database exists for storing applications settings. It will be also supported in the next versions of GRAPE and our new products which are currently under development, for example -WINE.
This chapter describes how to support the configuration files in your applications.
First we discuss class CONFIG_FILE. Then discuss a piece of code that illustrates
the usage of it.
This is a very simple class of the configuration file objects. In the creation procedure you can specify the configuration file name. Then you should call feature open. After you can read and write the configuration entries information and finally you should call feature close to save all of your modifications (if any) .
Since the access to the file is rather slow it should not be used for persistency.
make ( file_name : STRING )
Create a configuration file object with the specified file name. Parameter file_name must contain a valid file name.
Note Neither feature make nor feature open does not create a configuration file on disk if it doesn't exist. The file will be created only after you have put some information into it and then call feature close.
get_string ( section_name, entry_name, default_value : STRING ) : STRING
Retrieve the value of entry in the specified section or the default value if the entry cannot be found in the initialization file.
Hint: Even if the config file does not exist on disk it however can be opened. When your application runs first without a config file it is assumed that you are working with the default values for every entry.
put_string ( section_name, entry_name, entry_value : STRING )
Place the specified value to the specified entry of the specified section. If the entry_name parameter is Void then the specified entry is deleted. If entry_name is Void then the section is deleted. If the section or entry does not exist they will be created immediately.
Now we are ready to discuss a small example that might conclude the chapter. The complete example, as usual , is placed in the \EXAMPLES\PROFILE directory. Here we present only some features that deal with the material discussed above. This example contains a dialog box that can be used as a prototype for the Settings dialog in your applications. Here are some controls that display the state of some application objects. User can edit it via this Settings dialog box.
feature -- dialog controls ok_button, rev_button, cancel_button : TEXT_BUTTON path : TEXT_LINE_ENTRY; rb1, rb2, rb3 : RADIO_BUTTON; cb1, cb2, cb3 : CHECK_BUTTON; cb : COMBO_BOX;
Next we define an object of class CONFIG_FILE and some string constants which are used as the names of the sections and entries.
config : CONFIG_FILE feature -- Profile items Profile_name : STRING is "profile.ini"; Section : STRING is "Setup"; Path_entry : STRING is "Path"; Select_entry : STRING is "Select"; Check1_entry : STRING is "Check1"; Check2_entry : STRING is "Check2"; Check3_entry : STRING is "Check3"; List_entry : STRING is "ListItem"; On : STRING is "On"; Off : STRING is "Off"; One : STRING is "&One"; Two : STRING is "T&wo"; Three : STRING is "Thr&ee";
Feature on_create is a good place to create the configuration file and open it.
on_create() : INTEGER is do !!config.make( Profile_name ); config.open(); ... end;
Feature on_destroy is a proper place to close the configuration file.
on_destroy () : INTEGER is do config.close(); end;
Feature set_data is the right place to load the current configuration.
set_data() is do load_profile end; -- set_data load_profile is local val : STRING; fmt : FORMAT; pos : INTEGER; do !!fmt if config.is_opened() then val := config.get_string( Section, Path_entry, "C:\" ); -- if value is missed val := "C:\" path.set_name ( val ); val := config.get_string( Section, Select_entry, On ); -- press on of radio buttons if val.is_equal( One ) then rb1.press elseif val.is_equal( Two ) then rb2.press else rb3.press end; rb3.press end; val := config.get_string( Section, Check1_entry, On ); if val.is_equal( On ) then cb1.press end; val := config.get_string( Section, Check2_entry, On ); if val.is_equal( On ) then cb2.press end; val := config.get_string( Section, Check3_entry, On ); if val.is_equal( On ) then cb3.press end; val := config.get_string( Section, List_entry, "3" ); -- select specified listbox entry pos := fmt.s2i( val ); if pos > 0 then cb.set_current_pos ( pos ); end; end end
Feature get_data can be used to obtain the modified configuration and store it back to the config file.
get_data ( code: INTEGER ) is do if code = CTX_OK then -- If User press OK button save_profile; end; end; -- get_data save_profile is local fmt : FORMAT; pos : STRING; do !!fmt if config.is_opened() then config.put_string( Section, Path_entry, path.get_text ); if rb1.is_pressed then config.put_string( Section, Select_entry, One ); end; if rb2.is_pressed then config.put_string( Section, Select_entry, Two ); end; if rb3.is_pressed then config.put_string( Section, Select_entry, Three ); end; if cb1.is_pressed then config.put_string( Section, Check1_entry, On ); else config.put_string( Section, Check1_entry, Off ); end if cb2.is_pressed then config.put_string( Section, Check2_entry, On ); else config.put_string( Section, Check2_entry, Off ); end if cb3.is_pressed then config.put_string( Section, Check3_entry, On ); else config.put_string( Section, Check3_entry, Off ); end pos := fmt.i2s( "1", cb.get_current_pos ); config.put_string( Section, List_entry, pos ); end end