Applications and Geodes: 3.2 Saving User Options: The GEOS.INI File

Up: GEOS SDK TechDocs | Up | Prev: 3.1 Saving Generic Object Options | Next: 4 General System Utilities

GEOS can use multiple initialization files in network situations, but only the local GEOS.INI is editable. The local GEOS.INI (referred to hereafter simply as GEOS.INI or "the INI file") is read first into a moveable, swappable buffer, and it contains the path names of any other INI files to be used. The other INI files are subsequently loaded into other buffers. When the kernel searches for a specific entry in one of the INI files, it looks first in the local INI's buffer and then in any others in the order they were loaded. When it reaches what it wants, it stops searching. Thus, multiple entries are allowed but are not used, and the local INI file has precedence over all others.

Configuration of the INI File

The GEOS.INI file has a very specific format and syntax. It is segmented into categories , each of which contains several keys that determine how GEOS will perform. (For an example of an INI file, see Example GEOS.INI File Entries .) Note that typically the GEOS.INI file should not be accessed directly because its format is subject to change.

A category is essentially a group of keys. Certain geodes will work with their own categories, and certain categories will be used by several geodes. For example, the system category is used by the kernel and the UI to determine several of the default system settings. Each category is set in GEOS.INI by putting its name within square brackets. The text within the brackets is case-insensitive and ignores white space, so [My category], [mycategory], and [MY CATEGORY] are all equivalent.

A key is any setting that the system or an application can recognize and assign a value to. A single key may exist in several different categories; since both category and key define an entry, the entries will be unique if either key or category is different. Keys may be text strings, integers, or Boolean values, and every key is identified by its name, which is an ASCII string. Data may also be read from and written to the file in binary form; the kernel will automatically convert this into ASCII hexadecimal for storage and will revert it to binary during retrieval.

Both category names and key fields are called "entries." Each entry may exist on a single line or may cover several lines. An entry that contains carriage returns is technically known as a "blob." Each blob will automatically be enclosed in curly braces when it is written into the file. Any blob that contains curly braces will automatically have backslashes inserted before the closing braces so GEOS doesn't mistake them for the blob delimiters.

Comments may be added to the INI file by putting a semicolon at the beginning of the line. The file has several standard categories and keys that can be set within them. These are detailed in the INI File chapter .

Code Display 7-3 Example GEOS.INI File Entries

; The category "system" is used by the kernel and the UI to set certain system
; defaults such as the number of handles, the default system font and size, and
; the types of memory drivers to be loaded.
[system]
; The handles key is assigned an integer that determines the number of handle
; spaces allocated for the system's Handle Table.
handles = 2500
; The font key is assigned a character string that represents a file name
; or a list of file names separated by spaces.
; The listed file(s) will be read in as the font driver geode.
font = nimbus.geo
; The memory key is assigned a blob of text containing all the names of the memory
; drivers available to the system.
memory = {
disk.geo
emm.geo
xms.geo
}
; The category "MyApp's Category" is set for example only. It is used by the MyApp
; application.
[My App's Category]
; The myappHiScore key is an integer key set by the MyApp application.
myappHiScore = 52
; The myappBoolean key is a Boolean value. Booleans are case-insensitive, so True,
; true, and TRUE are all equated to "true". This is actually a Boolean value and
; is translated by the read and write routines that work with Boolean values.
myappBoolean = true
; The myappHiName is a text string that, in this case, contains carriage returns,
; backslash characters, and curly brace characters. The original text looked like
; this:
;		this is a multi-line
;		blob of text with curly
;		brace ({,}) characters }} in it
; It is automatically given backslashes in front of the closing braces, and it
; is automatically surrounded with curly braces.
myappHiName = {this is a multi-line
blob of text with curly
brace ({,\}) characters \}\} in it}

Managing the INI File

InitFileSave(), InitFileRevert(), InitFileGetTimeLastModified(), InitFileCommit()

Because the INI file is common to all geodes and to all threads in the system, only one thread at a time may access it. This synchronization is handled by the kernel whenever a routine to read from or write to the INI file is used. Additionally, the INI file is loaded into a buffer when the system is first run; all operations on the INI file actually work on this buffer, and the buffer may be flushed to disk only by the kernel.

There are, however, four routines that work directly on the INI file. One saves the file, another reverts it from the last save, the third checks the time the file was last modified, and the fourth commits any pending INI file changes to disk.

To save the local GEOS.INI, use the routine InitFileSave() ; this saves the changes to the backup file. It requires no parameters and returns an error flag if the file could not be saved. InitFileRevert() reverts the GEOS.INI file to its state the last time it was backed up. This routine takes no parameters, and it returns an error flag if the revert can not be accomplished.

InitFileGetTimeLastModified() returns the system counter's value stored the last time GEOS.INI was modified.

InitFileCommit() takes all the changes made since the file was last modified and flushes them to disk. This commits all the changes and should be used only from the kernel. It should not be used by applications.

Writing Data to the INI File

InitFileWriteData(), InitFileWriteString(), InitFileWriteStringSection(),
InitFileWriteInteger(), InitFileWriteBoolean()

GEOS provides five routines to write to the INI file, one for each of the allowable data types. Each of these routines will first gain exclusive access to the local INI buffer, then locate the appropriate category for writing. After writing the key and its value, the routine will relinquish exclusive access to the buffer, allowing other threads to write into it. Writing a category or key that does not exist in the local INI file will add it to the file. If you use a routine to write keys or categories to the INI file, be sure to first convert the strings to the acceptable ASCII hex format using InitFileMakeCanonicKeyCategory().

Each of these routines takes at least three arguments: The category is specified as a null-terminated character string; a pointer to the string is passed. The key name is also specified as a null-terminated character string; again, a pointer to the string is passed. The third parameter is specific to the routine and contains the value to which the key will be set.

InitFileWriteData() writes a number of bytes into the INI buffer, and it takes four parameters. The additional parameter is the size of the data. The data will be converted into ASCII hexadecimal when the file is saved and will be converted back when the key is read.

InitFileWriteString() takes a pointer to the null-terminated character string to be written. If the character string contains carriage returns or line feeds, it will automatically be converted into a blob.

InitFileWriteStringSection() writes a new string section (a portion of a blob) into the specified entry. The specified entry must be a blob already, and the string section will be appended to the blob. A string section is a line of a blob delineated by line feeds or carriage returns.

InitFileWriteInteger() takes as its third argument the integer to be written.

InitFileWriteBoolean() takes a Boolean value. A zero value represents false, and any nonzero value represents true. When looking at the INI file with a text editor, the Boolean value will appear as a text string of either "true" or "false"; it will, however, be interpreted as a Boolean rather than a text string.

Getting Data from the INI File

InitFileReadDataBuffer(), InitFileReadDataBlock(), InitFileReadStringBuffer(), InitFileReadStringBlock(), InitFileEnumStringSection() InitFileReadStringSectionBuffer(), InitFileReadStringSectionBlock(), InitFileReadInteger(), InitFileReadBoolean()

When you want to check what a key is set to in the INI file, you should use one of the InitFileRead...() routines. These search the local INI file first and then each of the additional INI files in the order they were loaded. They will return the first occurrence of a given key, so if the key exists in both your local INI file and another INI file, these routines will return only the local value.

All of these routines take at least two parameters. The first is the category of the entry to be retrieved; this is stored as a null-terminated ASCII string, and a pointer to the string is passed. The second is the key of the entry. This, too, is stored as a null-terminated ASCII string, and a pointer to the string is passed.

InitFileReadBoolean() returns the Boolean value of the given key. If the key is set "false," a value of zero (FALSE) will be returned. If the key is set "true," a nonzero value will be returned (-1, the constant TRUE).

InitFileReadInteger() returns the integer value of the given key.

InitFileReadDataBuffer() and InitFileReadDataBlock() both return the data bytes stored in the given key. The first, however, takes the address of a buffer already allocated and puts the data into the buffer. The second allocates a new block on the heap and puts the data into it. If you don't know the size of the data, you should use InitFileReadDataBlock() .

InitFileReadStringBuffer() and InitFileReadStringBlock() both return the null-terminated string stored in the given key. In both cases, curly braces will be stripped off of blobs and backslash characters will be removed if appropriate. The first, however, takes the address of a buffer already allocated and puts the string in the buffer. The second allocates a new block on the heap and returns the string in it. If you don't know the approximate size of the string, use InitFileReadStringBlock() .

InitFileReadStringSectionBuffer() and its counterpart InitFileReadStringSectionBlock() both return a null-terminated section of the string stored in the given key. A string section is defined as any number of contiguous printable ASCII characters and is delimited by carriage returns or line feeds. These routines take the number of the string section desired and return the section (if it exists). InitFileReadStringSectionBuffer() takes the address of a buffer already allocated on the heap and returns the string section in the buffer. InitFileReadStringSectionBlock() allocates a new block on the heap and returns the string section in it. You should use this routine if you don't know the approximate size of the string section.

InitFileEnumStringSection() enumerates the specified blob, executing a specified callback routine on each string section within the blob.

Deleting Items from the INI File

InitFileDeleteEntry(), InitFileDeleteCategory(), InitFileDeleteStringSection()

Besides reading and writing data, you can delete categories and keys that were previously entered. InitFileDeleteEntry() takes pointers to both the null-terminated category name and the null-terminated key name and deletes the entry. InitFileDeleteCategory() takes only a pointer to the null-terminated category name and deletes the entire category, including all the keys stored under it.

In addition, you can delete a single string section from a specified blob. InitFileDeleteStringSection() takes the category and key names of the blob as well as the index of the string section, and it deletes the string section. If the string section does not exist or if either the key or category can not be found, the routine will return an error flag.


Up: GEOS SDK TechDocs | Up | Prev: 3.1 Saving Generic Object Options | Next: 4 General System Utilities