Problems:
P.1) Two INI files: system vs. user INI file
P.2) Multiple sections within the same INI file
P.3) Multiple values within the same section
P.4) Multiple values within separate sections of the same name
P.5) Modification of values (from the view of the performance)
P.6) Outsourcing INI access
P.7) How to interprete the stored data

Discussion:

D.1	Two INI files

The problem to use two INI files (instead only one) was choosen with
intention. This separation shall help administrators to maintain programs:
1) application default values: are hard coded within the application itself,
	they come into effect, if no other value was specified at all.
2) system default values: are choosen by the maintainer of the application
	or the part of the installation of machines to achieve the best
	... (whatever the sysop had in mind).
3) user values: reflect the user's personal mind in how the application
	shall act, this can include so interesting things like "background
	picture", "application open sound", or such less interesting stuff
	like "how many spaces a TAB represents" or "if the DEL command shall
	run interactively by default".

Values 1) are hard coded into the application, every application has (or,
in my mind, should have) default values for each option, if the option
permits a default value by its nature (consider a "rm -fr" or "deltree /y"
to have "*" as its default value).

Values 2) and 3) simply tunes the application into different views of
how the application should react. For instance, the sysop decides to
activate maximum savety for new users and renders the default behaviour
of "rm" and "deltree" to _always_ run interactively and actively prompts
the user if to delete a file. An advanced user would definitely alter
the default behaviour of "rm" to "-fr" and "deltree" to "/y".

So there are two different views about the applications default
behaviour, therefore the implementation decision was to parse
two INI files, one provided by the sysop (aka "system INI file") and
one by the user (aka "user INI file").

Why _two_ and not "if there is no user INI file, copy the system INI
file into the user INI file and use this"?

There are a lot of options most don't want to fiddle with at all, for
instance consider a mail client. The sysop configures the system INI
file to target the correct send host and the correct recieve host and
specifies the correct options for the send/recieve protocols.
Now the send host dies, the sysop upgrades the server to a better
protocol, or simply found the reason why the server dumps core
frequently in an ill-choosen option of the clients; instead of
having all the user come crying to the sysop "My mail client is
broken", the sysop can change the system settings and directly
updates all the mail clients. [Who pretends I carved this scenario
out of the clear sky?! :-(]

Why not the Windows registry variant?

Have you lately maintained hundreds of roaming users on systems with
"roaming applications" as well? It wasn't easy when each program had
its INI file right in the Windows directory, nor was it easy when all
the programs modified the same WIN.INI; but clever sysops could easily
alter plain ASCII files themselves and could overcome many the
restrictments of so-called clever modern programming style.

However, it is not the basic implementation of the registry itself
(the binary represantation of configuration data), that nearly
renders itself unable to be maintainable, but the fact that every
application keeps the stuff, where it likes, and that every machine
has its own, standalone version of it. The sysop cannot make sure that
changes in server-side stored application are distributed into every
registry, without booting all the machines to make _actively_ sure
they are updated; however, when the application keeps server-
specific data in the user-specific area, this is useless as well.
[Um, of course, one can buy management systems that entitle themselves
 to handle this. Well, try it yourself. ;-)]


D.2) Sections with the same name in the same INI file

That there is one section of the name 'XYZ' in the user INI file and
one in the system INI file, is clear because of the two-file design.

But what's related to the fact that the same section appears more
than once in the same INI file?

From the presumption that INI files are probably not the best method
to keep configuration data (consider an installation in which each
application shall use the same way to perform some tasks, e.g. to
highlite/emphase text on the screen or whether or not to beep on
an error condition or to be noisy when overwriting files etc.,
one would either need to put the same configuration data into all
individual INI files or one must include INI files into other ones),
one must ask oneself, if two sections named equally are always
distinctable and, if so, there is any need to do so.

Why would one want to have two (or more) sections of the same name in
the same INI file?
1) Hide the second section by the first one.
--> If one need to hide it, why put it in the INI file at all, at the
first place. Why not rename the section, then?
2) Span the section through the INI file, makes updates quite easy.
--> To aquire the values of a section will be significantly slower,
because the complete INI file must be scanned for the value, it is
not enough to just find one proper section and scan this particular
part of the INI file.
3) The last section superceeds all the previous ones.
--> This sounds like a nice one, but would cause that one need to
compress the INI files in order to remove superceeded sections; this
will steadily increase the size of INI files, especially when one
updates different sections alternatingly.

I don't see any good reason to accept two or more sections to achieve
a goal, one cannot catch with one section; therefore the implementation
states that two or more sections of the same name tends to undefined
behaviour. This is especially true, when the plain INI files are
replaced by an access optimized value database.


D.3) Multiple values within the same section

There seems to be no real need for two sections within the same INI
file, could there be one for the same value name in one section?

I think so, consider the "device=" values in the [386enh] section
or the CONFIG.SYS file, and given that this section seems to be the
native place to put other options as well. One could, of course,
define that each line is uniquely identified by a number, e.g.:
|device_1=fdxms.sys
|device_2=fdems.sys
|device_3=fdcd.sys
but when the device list must be changed, all the numbers must be
adjusted, or at least it must be made sure that no number is specified
more than once. This is even more disturbing when such list is
maintained manually by an user (or the sysop ;).

Therefore the following rules are applied in this situation:
1) The sequence (order) of equally named values is retained.
2) When such value is randomly read (not sequentially), always the
first value is returned.
3) Values from the user INI files always preceeds the ones from the
system INI file.
4) The values need not follow immediately themselves.

What these rules do to the performance:
case: consider that value "VALUE1" has exactly one entry in the section
+ if this value is requested and this value is currently cached somewhere,
this value must be discarded, because we don't know this is the first
entry of 'VALUE1', nor do we know that it has exactly one entry in this
section. Even a flag is hard to maintain, if the section is mixedly read
randomly and sequentially.
However, how large is the possibility that the requested value is cached,
unless we cache all the values and, therefrom, know whether or not the
value is the first entry?
But if we do know what value comes next or is in the cache, why don't
we read the INI file sequentially?
+ If we don't know nothing about the value, we must start searching for
it at the start of the section anyway.
+ When the user access the values only randomly, only the first entries
will be retreived. Possibly, when updating the section, the other
values will be discarded.


D.4) More than one value of the same name in different sections

Case #1: the sections lay in the same file --> undefined behaviour,
	see D.2

Case #2: there is one section in the user INI file and one in the
	system INI file

These two types of INI files where implemented to allow an user
to superceed (override) the system defaults the sysop specified.

In this sense, if a value is located in the user INI file, it is
completely ignored within the system INI file. This is the default
behaviour of the implementation, too.

However, it might be necessary to access all values or only values
from a specific INI file. Therefore, the implementation offers
both: The default behaviour where user entries effectively overrides
system entries, and a random access to values in particular INI files.


D.5) Performance when to modify a value

DOS always had one great problem: available memory.

In the sense of accessing INI files this automatically eliminates the
solution to read the INI file into memory, access (read/write) it there,
and before to terminate the application the INI file is written back
to the hard disk.

Although enhanced versions of the INI subsystem might be written to
take advantage of XMS, EMS, binary files etc., this subsystem is
designed to work with tight resources as well, so the implementation
not even reads a complete section into memory when accessing it;
consider tiny or small programs for instance.

Therefore the basic design is that every write access directly modifies
the INI file and because INI files are plain text files, that possibly
are edited manually by an human, both to add a new value and to grow the
data of an already existing value a value require to copy the complete
INI file, during which process the necessary changes are made.

However, when a value is deleted or the data portion shrinks, the
value could be overwritten by whitespaces or simply transformed into
a comment, but how much _human_ readeble such INI file becomes and
how and when shall those deleted areas be reclaimed?

For all, I don't believe that the special behaviour in the latter
case will do any good, although providing better performance. Therefore
_any_ modification directly inflicts to copy the complete INI file.

For writing stuff into an INI file two approaches are available:
1) Write the complete INI file
	This approach lets the user open an INI file (which is represented
	by a temporary filename until this file is _successfully_ closed)
	and dump the _whole_ contents of it during this session. Because
	the INI file is not replaced by the newly generated INI file, one
	can create algorithms to read some values out of the old INI file
	and dumping them into the newly opened write-only one. When the new
	INI file is completed, it is closed and the read-only INI file is
	resetted to take note of the changed INI file.
	In fact, methods 2) base on this technique.
2) Write only parts of the INI file
2.1) Write individual values.
	This approach lets the user specify one value to be changed at
	a time. This involves copying the complete INI file for this
	little action during which the value is added/modified/removed,
	then the copy is closed and replaces the original INI file and
	the INI file is resetted to reflect the change of the INI file.
2.2) Write a whole section
	This works much like 1) but instead of creating a wholely new
	INI file, the INI file is copied until it reaches the specific
	section, then _all_ the values of the section are written,
	then the remaining part of the INI file is copied. Then the
	newly generated INI file replaces the old one and a reset
	forces to re-read the INI file.
	No value previously available in the section is copied
	automatically.

Method 2.1) will be the easiest one to use today and with future
versions of INI file handling, however, it currently offers the
worst performance.

Method 1) currently has the best performance, I think, for flat
INI files, which holds almost no sections but lots of values. Usually
INI files which act as "swapfiles", when an application dumps out its
current internal state, to re-enter an almost identical one later,
for instance in a session management.
In future relases, this operation might include a huge overhead,
because the changes are not made immediately, but must be cached
until all changes are written; consider the binary file method:
all the newly written values and sections must be kept in this
file, but must be inaccessable, until the Close() function has been
called, when the new values must superceed (override, replace) the
old entries.


Method 2.2) seems to lie in between, perhaps a little more related to
Method 1). It is designed for applications updating one or two
sections within a (probably) larger INI file.


D.6) to outsource access to INI files

This would be ideal.

A central instance would accept requests of values (read access) and
modifications would be passed there, too. In a multi-tasking environment
this would ensure that every program definitly uses the most current
key.

The central instance would move most of the code related to INI file
handling from each individual program into one, it could be highly
optimized and, if properly designed, can be easily adjusted to future
improvements without any help from the application (e.g. porting nor
even re-compiling).

The worse of this tale? -- DOS
Such central instance would be some kind of TSR or driver. The application
must either install such TSR, if none is currently available, or simply
hope that this service is available.

In the first way (install TSR if not present), each application comes
with its version, possibly incompatible with Can already installed one etc.
The second way (pre-installed TSR), most DOS users don't like such thing,
because this or that program makes no use of it and there is no memory
to waste.


D.7) representation of data for the values

Another annoying point with INI files is that every applications
interpretes the data (that part of an entry of a value right of
the equal sign '=') for its own. Whereas app #1 honors the DOS NLS
and accepts "7,5" (',' == decimal point), others don't.
Some accept "true" for boolean options, others "on" only.

It would be nice, if all applications would read and write INI files
the same way. There exceptions from this rule, as always, but
basically, if a value is a boolean one, then all values should be
parsed like all the other boolean values in the INI files.

Therefore a set of functions is provided to convert the data into an
useable internal interpretation of it, and there is an optional "type"
information attached to all values; currently only to help an human
to pick the correct kind of value.

Currently three data types are available:
+ Boolean: for values that can be on/off, true/false, 1/0.
	The internal representation is (int), 0 == false.
+ Integer: for signed or unsigned integer numericals
	The internal representation is (int), also useable as (unsigned)
	naturally
+ String: for character strings
	The internal representation is (char*).

There is another "data type", which can only be "applied" when retrieving
the data: "Unformated". The three formatted data types will ignore
leading and trailing whitespace, eventually surrounding quotes, and
comments; the unformatted data type returns anything right of the equal
sign unmodified back to the application.

Currently one modifier (flag) is availabel:
+ Expand: If set, the data is searched for environment variables, which
	are expanded before interpreting/returning the data.


There is another thing: _comments_

Although, often not supplied in INI files, they can be very helpful,
when an human editor adds them in the INI file or an application marks
its changes to INI files normally alien to the application.

This implementation accepts four kinds of comments:
1) blank lines, either empty or completely filled with withespaces
2) comment lines, whose first non-whitespace character is ';' or '#'
3) anything to the right of the right bracket in a section line,
	e.g.: 	[sectionname]	comment
4) anything to the right of the leftmost ';' when the data is
	retreived in a formatted data type

For the implementation, comments are useless, but are preserved, if
possible. This is usually the case when a line is copied from INI
file to another one; but never when a value is changed.

Why using ';' within the data part of a value, and no other character,
for instance the unix-like hash mark '#'?

Well, it seems that is common praxis to use the semicolon ';' within
Windows and DOS environments, even in CONFIG.SYS the ';' is the
comment character. To accept '#' in type 2) comments should offer
a good enough possibility for this comment sign as well.

