  Programming Notes                                 A WindoWatch feature

                     Window Aspect: A Scripting Language
                    A Tutorial: Part Five Ghost BBS v3.20
                        Copyright 1995 by Gregg Hommel

 First.... I'm sorry that I missed writing a column last month. I was
 smack in the middle of finishing off GHOST BBS 3.20 for public release,
 and found myself in need of two additional hands, and at least twice as
 much time on the clock as there is normally. I tried putting Windows
 CLOCK.EXE on my DoubleSpaced drive, but even then, when I ran it, it
 still only had 24 hours in a day - but it was worth the try .

 As a result, I simply ran out of time, and could not finish this column
 before deadline.  Lois was mean and nasty about it, and laid a guilt trip
 on me that you wouldn't believe, but even then, I just did not have
 enough time to do everything. And since, through registration fees, GHOST
 BBS pays me, and Lois doesn't... well, you get the picture....   < Large
 and noisy yawn...lbl>

 In any case, GHOST BBS 3.20 is now finished, and I can get back to doing
 this, before Lois really gets nasty, so here we go....

 There is an old Polish saying that my mother used to use.  Since I have
 begun writing scripts, I have been partial to using myself. I can't
 remember the Polish, and thus, won't inflict that on you, but the English
 translation was something along the lines of...

 "The amazing thing is not how well the Dancing Bear dances... what is
 amazing is the fact that he dances at all!"

 GHOST BBS, in particular, is a "Dancing Bear".  To me, at times, the
 amazing thing about that script is not how well it does some of the
 things that it does, but rather, that it does them at all. (Such modesty!
 Some of this is due to his remarkable coding ability? The life of an
 editor is filled with temperamental writers!) A lot of what GHOST BBS can
 do is tied in with the use of the Windows INI file.

 I know that you are all familiar with the basic INI files used by Windows
 for it's own configuration information, and you all know that the various
 applications that you run under Windows usually have their own INI file
 for their configuration information.

 But the term configuration information can actually have a wide
 latitude in meaning. If we look at INI files as being files to store
 information, rather than just configuration data, where does that take
 us?

 To store information that a script application needs, we could use a
 text file. Wasp has the commands necessary to do that. But to store
 information in the file, we have to open the file (creating it if
 necessary, using different commands for each case, so as not to destroy
 previously stored information) for writing, locate the end of the file,
 and then write the information we want stored using some form of
 identification so we can locate it when we need it.

 To retrieve information, we have to open the file for a read, read a
 line from the file, and compare it's indicator  to that of the
 information we need.  If it doesn't compare, we have to read the next
 line, and go through the same process again, until we find what we want.
 All of this, both writing and reading, takes multiple lines of code,
 multiple if/then statements, and time while the script tries to locate
 the information needed.

 If, on the other hand, we use an INI format file,  and note, the
 extension doesn't need to be INI... it can be anything, so as long as we
 specify the full name, and, if the file is not in the \WINDOWS directory,
 the full path.  The procedure becomes so much simpler. Writing to an INI
 format file involves the single command, PROFILEWR.  If the INI format
 file doesn't exist it is created. If it does exist, the line being
 written is simply added to the file.

 Reading from an INI format file is equally as simple, involving a single
 command, PROFILERD. Using this, we can read either a string or an integer.
 If the locator for that particular line to be read doesn't exist, we are
 then returned a null string if reading a string, or a minus integer value,
 or an integer value. Otherwise, we are quickly and simply returned the
 value we need, within split seconds of time.

 To see how this might be of use to us, let's look at the INI format
 files which GHOST BBS 3.20 uses. This will show some ways they can be
 used, and perhaps help develop ideas for you....

 1) GHOST.INI - This one is the basic INI format file used by GHOST to
 store configuration data re: various run time parameters, file locations,
 etc.  BUT this file also stores a huge variety of information for GHOST.
 That information can include the name and city of the last person to
 call, filenames and so on, to pass to the virus scanner feature, text
 information which become lines in a DOS batch file used to open a door,
 and even the information regarding how your system was set up under
 PCP/Win before GHOST began running. This last makes it possible for GHOST
 to use it later in order to  restore the system to that same state it
 found when it shuts down.

 2) LANG#.PMT - These files, and there may be multiple ones, have the #
 replaced by a language number from 1 to 99. They store the various
 prompts which GHOST uses on the screen while it is running, utilizing
 each of any number of languages from 1 to 99. These files also include
 sections which are translation tables, so that GHOST can receive a prompt
 like O, as in the French Oui for yes, and understand that this is the
 equivalent in this language, of the basic prompt response Y for Yes in
 the default English mode.

 The prompts stored in this file can contain certain pre-defined variables
 in the form of @ONLEFT@  which GHOST will replace with information
 determined while it is running.  Since it has two main sections, one for
 ANSI mode, and the other for non-ANSI mode, they can also contain ANSI
 codes to change items like the colours, bold or flashing, and so on.

 3) GHOST.USR - this little critter is the basic user record file. Windows
 has a limit on the size of an INI format file of 64K, and storing user
 information in such a file can quickly go beyond that size. GHOST always
 checks the size of the actual user record file (see below) before writing
 a new user into it, and if the file is getting too large, it starts a new
 one. This USR file contains only one line per section, that being the
 information telling GHOST where the actual records for that user are
 located.  That is, in which of what might be multiple user record files,
 is the information for a specific user stored.

 4) USER#.REC - This is the INI format file which actually contains the
 information for a particular user which is pointed to by the GHOST.USR
 file. The first file used by GHOST is USER1.REC. As a GHOST user record
 database grows, and exceeds the pre-defined safe limit set in GHOST, new
 files are created, with an incremental number in them, for GHOSt to use.

 In this file is a section for each user, with the information they gave
 to GHOST when they first logged on and completed the new user
 questionnaire. Along with the users default transfer protocol (if set),
 there is information defined by the sysop re: security level, access to
 private areas on a GHOST system, and so on.

 Based upon the above, you can see that it is possible for an application
 to have, and use, more than one INI format file. This can be handy to
 keep configuration information separate from data used while the
 application is running and to modify what appears on screen, etc. GHOST
 BBS stores the different kinds of information it needs, in different INI
 format files, and the Wasp code simply uses the PROFILEWR and PROFILERD
 commands to access the correct file, as instructed.

 Those two commands are simplicity themselves to use, once you understand
 the format of an INI type file. Basically, an INI format file stores
 information in various groups or sections, distinguished by a section
 header, shown in the file as a name enclosed in square brackets, such as
 [Start Up], or [Last User]. In each section are lines which are the
 actual information stored, in the format of info_name=data  with,
 obviously, the text to the left of the  =  being the data indicator used
 to locate it, and the text or number to the right of the =  being the
 data stored there.

 The PROFILEWR command is a really remarkable little fellow, which
 combines the equivalent of a file open, create command, with a file
 open, append type of command. The format of the command is...
 PROFILEWR filename section_name indicator data

 1) filename can be any legitimate DOS file name. If it does not include
 a drive/path, the file is assumed to be in the \WINDOWS directory. If no
 extension is included, it is assumed to be INI. If, however, you want the
 file located in a particular directory, with a particular extension, then
 simply specify the full drive\path\filename.ext. Filename can be either a
 string constant specified for each PROFILEWR command (such as
 "f:\ghost\prompts\lang1.pmt") or a string variable containing such a
 filename.

 2) section_name is whatever name you want for a given section. Don't get too carried away with this. Remember, the maximum size of a string variable is 255 characters, so use something reasonably descrip- tive for your purposes. As example, in GHOST.INI, the information
 GHOST uses when it starts to determine certain run time parameters is in the [Start Up] section of GHOST.INI. Again, this can be a string constant, or a string variable, whichever suits your needs in the script.

 3) indicator is a string representing whatever is to the left of the =
 in an INI format file section line. Again, this can be whatever you want,
 but the same rules apply... don't make it too long, but do make it
 something descriptive to you as to purpose and use, etc. Remember, an INI
 format file is a text file, and can be read in any text editor. If you
 make things descriptive, it makes it easier to check for particular
 settings in that INI format file, and easier for you to remember, in
 code, what it is you want to write.

 4) data is of course, the data that you want written to the right of the
 = in this line. It can be a string, or an integer, and can be a
 constant or a variable.

 As example of using this, suppose I want to have my script change the
 value of the line in GHOST.INI that controls whether autobaud detection
 is on (1) or off (0). It is on now, and we want to turn it off. In GHOST,
 the GHOST.INI file is pre-defined as string variable S0, for a variety of
 reasons we won't go into here, the command to change this entry might be

  PROFILEWR S0 "Start Up" "autobaud" 0

 Or it could as easily be

  PROFILEWR S0 sec_name line_name autoval

 ..where sec_name is a string variable set to "Start Up", line_name is a
 string variable set to "autobaud" and autoval is an integer variable
 determined by a setting in a dialog box, in this example, 0.

 But the power of this command goes beyond just being able to write a
 value into a line in a file.

 If the file named doesn't exist, PROFILEWR will create it. If the
 section specified doesn't exist, PROFILEWR will create it. If the
 indicator line specified doesn't exist, PROFILEWR will create it. So,
 even if the file GHOST.INI does not exist, if my script issues the
 command above, I will end up with a file called GHOST.INI in my \ASPECT
 sub-directory (which is what S0 specifies), that contains the
 following...

 [Start Up]
 autobaud=0

 I don't have to check for it's existence, because PROFILEWR will create
 it if it doesn't exist, and append to it, if it does exist. Same goes for
 the section names in that INI format file, and even the lines in that
 section.

 All of this done with a single command in Wasp!

 The PROFILERD command is as equally remarkable in it's own way. The
 format of that command is almost identical, except that the last item
 (data) must be a variable of the correct type to receive the information
 read from the INI format file. But the other entries in the command can
 be of the same nature as in PROFILEWR, or PROFILERD filename section_name
 indicator data_variable which makes the command to READ the value of the
 autobaud setting in GHOST.INI something like

  PROFILERD S0 "Start Up" "autobaud" autoval

 So what's remarkable about this?  If the value being read is a string,
 and the line containing that data is not in existence, Wasp returns a null
 string for the variable. If you are reading an integer, and the line
 doesn't exist, Wasp returns a - value (generally -1) to indicate that the
 line doesn't exist.

 An integer stored in an INI format file isn't an integer.... if you use
 a string variable to receive the contents of the "line", then you get a
 string consisting of the number stored there. If you use an integer
 variable, you get the number itself, as an integer.

 This means that you can store an integer into an INI format file, and
 use it as a string in a dialog box if you need a string there, or as an
 integer, depending upon what kind of variable you use to read the data.

 And PROFILERD is fast. There is no need to search through the lines read
 from a text file or compare them to some value for an indicator that this
 is the right line, and so on. That's all done by PROFILERD. It opens the
 INI format file for a READ, searches for the section name included in the
 command and then searches under that for the line name included. It then
 reads the value of that line into the variable, using but one
 command...one single line of code instead of the multiple lines that
 would be needed to get the same data from a standard text file!

 But how can this be used, other than in the normal way, to set
 configuration parameters, etc.??

 Wasp 2.0 greatly diminishes the memory restraints we worked under with
 Wasp 1.0. Global variables are no where near the problem they were under
 Wasp 1.0, but there still are limits on them.  Even without those
 constraints, they take up global memory in the data tables, etc.
 Additionally, global variables can sometimes be tricky to deal with,
 especially in a longer script  with many sub-procedures. You just might,
 inadvertently, modify the value of that global variable in one procedure,
 only to find that modified value plays hell with another procedure that
 uses the same global variable.

 However if you use a local variable in a procedure that sets the original
 value of what used to be a global variable, and then write it to a
 section in an INI format file, the other procedure which requires that
 value can also use a local variable.  In other words, creating a
 PROFILERD command to set precisely the value you want for that variable,
 without worries about what another procedure might have done to the
 global variable.

 An INI format file can also give you the ability to pass data from one
 script to another. As you know, you can normally only do this using the
 internal global variables, such as S0, I0, and so on. But there are only
 ten of each type of variable in this category, and that may not be
 enough. You also have to be so very careful with those variables, since
 they are available to any script that you run, and any script can change
 their values. Those designaated values do not remain if you shut down
 PCP/Win and start it up again.

 If you store the values that you want to pass to another script in an INI
 format file, on the other hand, they are at that value unless/until you
 specifically change it in another script. And there isn't a ten variable
 limit on the data that can be passed. All you have to do is have one
 script write values to the INI format file, and the secondary script read
 them. It doesn't matter if the secondary script is run during this
 PCP/Win session, or another one. The values written to the INI format
 file remain, and can be read and used by any script you wish, at any
 time. Talk about being able to pass data from one script to another!

 Well, I see by the clock on the wall  -and the expression on Lois' face-
 that I'm getting long winded here.   I find INI format files to be
 fascinating, simple to use, and quite valuable in script writing, and
 tend to show that. But if I let this column go on any longer, Lois or
 Paul will be redlining it to cut it down in size, and we can't have that.
 We'll continue with some further discussions of using INI format files in
 the next column.

 Gregg Hommel is our resident Aspect and Procomm for Windows guru. As the
 Co-Host for the RIME Windows and Procomm conferences many have met him
 online where he modestly helps users solve problems.  He's the author of
 GHOST and serves on the WindoWatch editorial board.

                                      ww



