Liberty Basic is develeopped by Carl Gundel
Original Newsletter compiled by Alyce Watson and Brosco
Translation to HTML: Raymond Roumeas

The Liberty Basic Newsletter - Issue #66 - MAR 2000

© 2000, Cliff Bros and Alyce Watson

All Rights Reserved

In this issue: 

In future issues:


Several months ago, Chris Robertson posted some very useful code that allowed a user to select a font face, width and height. To retrieve the fonts on the user's system, Chris ran regedit and output the font list to a file, for loading into an array. We will add his code here, almost unchanged, to allow users to choose a font for our open source editor.

      
        THANK YOU VERY MUCH, CHRIS ROBERTSON!
 
      Chris Robertson -- mailto:donna-@ihug.co.nz
 

Chris' routine makes good use of the Liberty BASIC FILES command, loading arrays, and string parsing, so there is a lot there to discuss and emulate. We will also write the user's font choice to an ini file, so that the next time he uses the open source editor, the font of his choice will automatically be used in the texteditor.


CHRIS ROBERTSON'S FONT CHOICE

Here are some variables to add to the open source editor, for use in the font routines:

 
'** NEW **
'drv$               variable for drive in font list routine
'path$              variable for path in font list routine
'ttf$               name of font loaded from list
'sp,f,fs            counter variables in font routine
'font$              font name in font routine
'fX$                width of font
'fY$                height of font
'setFont$           LB fontname and size info for chosen font
'font$              facename of font
'fX$                font size width
'fY$                font size height
 
'for font choice routine:
    dim fontList$(500)  'array of font names
    dim fontSize$(31)   'array of font sizes
    dim temp$(10,10)    'for files statement in font routine
 
    fontsLoaded = 0     'flag for fontloading routine
 

Chris relies on the Windows registry editor, regedit, to read the registry information about fonts and write the output to an ascii text file. He has designated the name, "\font.lst" for this file. Look in the following routine to see this name and the parameters required to run regedit and retrieve fonts. Note that he uses LB's RUN command, with the parameter SW_HIDE. This causes regedit to be hidden from the user's view while it does its work:

 

'** export font list from registry
    run "regedit /e ";DefaultDir$;"\font.lst
Hkey_Local_Machine\Software\Microsoft\Windows\CurrentVersion\Fonts", SW_HIDE

 

Before we can even think about reading this file, we must be sure that regedit has completed its task and closed the output file. If we try to open a file that is currently in use by another application, our program will crash with a file sharing violation error. We'll do our checking with the LB FILES command.


THE FILES COMMAND:

 

Chris' routine sets up the directory and path for the output file, which will be needed in the FILES command:

drv$ = left$(DefaultDir$,3)
path$ = right$(DefaultDir$, len(DefaultDir$)-3)+"\font.lst"
 

The DefaultDir$ is the directory from which the program is running.

The drv$ variable contains the leftmost three characters of the default directory. The left$() function returns the number of characters specified in the string, starting at the beginning of the string. The drv$ variable might look like this when printed out:

	print drv$ = output "c:\"
 

The right$ function is used to obtain the path$ part of the DefaultDir$ variable. Right$ works in a similar manner to left$, but it takes the number of characters specified from the end of the string, rather than from the beginning. We know that we want all of the characters after the first three, that we put into the drv$ variable. That means that we shall want a length equal to the length of the string, DefaultDir$, minus three, or len(DefaultDir$)-3:

path$ = right$(DefaultDir$, len(DefaultDir$)-3)

We will need to add the actual filename to the path, for use in the FILES command. The name we will be giving the file is "font.lst". We need to remember to separate the file name from the directory information with a backslash, so we will actually want "\font.lst". Here is the entire path$ information:

path$ = right$(DefaultDir$, len(DefaultDir$)-3)+"\font.lst"

Chris does his file checking in the subroutine:

    gosub [check4DosOutput]
 

Let's talk about the FILES command before we see how Chris uses it. I think that I'll just sit back and let Carl Gundel explain this one, since he does it well in the LB helpfile:

 
          <<BEGIN HELPFILE SNIPPET>>
FILES
Description:
 
  The FILES statement collects file and directory information 
from any disk and or directory and fills a double-dimensioned 
array with the information.  Also good for determining if a 
specific file exists (see below).
 
Usage: 
 
    'you must predimension info$(, even though FILES will
    'redimension it to fit the information it provides.
    dim info$(10, 10)
    files "c:\", info$(
 
The above FILES statement will fill info$( ) in this fashion:
 
    info$(0, 0) - a string specifying the qty of files found
    info$(0, 1) - a string specifying the qty of subdirectories found
    info$(0, 2) - the drive spec
    info$(0, 3) - the directory path
 
Starting at info$(1, x) you will have file information like so:
 
    info$(1, 0) - the file name
    info$(1, 1) - the file size
    info$(1, 2) - the file date/time stamp
 
Knowing from info$(0, 0) how many files we have (call it n), we know 
that our subdirectory information starts at n + 1, so:
 
    info$(n + 1, 0) - the complete path of a directory entry (ie. \work\math)
    info$(n + 1, 1) - the name of the directory in specified (ie. math)
 
You can optionally specify a wildcard.  This lets you get a list of 
all *.ini files, for example.  This is how you do it:
 
    files DefaultDir$, "*.ini", info$(
 
This also makes it practical to use to check for file existance.  
If you want to know if a file c:\config.bak exists, you could try...
 
    files "c:\", "config.bak", info$(
    If val(info$(0, 0)) > 0, then the file exists.
 
                <<END HELPFILE SNIPPET>>
 

Remember, the FILES command cannot "see" files and folders that are attributed "read only" or "hidden."

Let's see how Chris puts this to work. He has separated the drive and path information, as we've shown above:

drv$ = left$(DefaultDir$,3)
path$ = right$(DefaultDir$, len(DefaultDir$)-3)+"\font.lst"

At the start of his subroutine, he places comments to explain the parameters and usage:

[check4DosOutput] 'checks to see if a command line file has been created
'used to wait for dos output
'requires drv$ = drive\
'requires path$ = \path\*.*
'requires temp$(10,10) array

He next puts the FILES command into a WHILE/WEND loop, which constantly checks for the existence of the "font.lst" file that will be created by regedit. As long as the temp$( array value for (0,0) and for (0,1) are not equal to "1", the file has not been created and closed by regedit.

When the values are "1", then the file is ready for us to use in our program. Here is the rest of Chris' subroutine:

 
    redim temp$(10,10)
    while val(temp$(0,0)) <> 1
        files drv$, path$, temp$(
    wend
 
    while val(temp$(0,1)) = 0
        files drv$, path$, temp$(
    wend
 
    return


FILLING AN ARRAY WITH FONTNAMES

The output file will have entries like this one:

"Arial (TrueType)"="ARIAL.TTF"

We will INPUT each entry in the font.lst file, manipulate the information, and then place it into an array. First, we'll OPEN the file for INPUT: 

    open "font.lst" for input as #list   'load font list to array

Then, we'll input items until we've reached the end of the file. There are several ways this could be done. Chris has used a very clean and efficient method, that again makes use of WHILE/WEND. He checks for the END OF FILE marker, and while that marker has not been reached, he loops through the file. When eof(#list) is no longer equal to "0" then the end of the file has been reached:

while eof(#list)=0

He uses an index counter variable to keep track of the array element to be filled in the array fontList$(f), and increments it each time through the loop: 

        f = f + 1
 

In Liberty BASIC, you may not fill an array directly from a file. You must input elements of the file into a variable, and then set the array element in question to be equal to this variable. Chris is using "ttf$" as his temporary input variable. Each time through the loop, the next item in the text file is placed into the variable "ttf$": 

        input #list, ttf$  

Next, Chris evaluates the entry with a conditional IF/THEN statement. He checks for the existence of Chr$(34), which is the double quote mark: 

        if left$(ttf$,1) = chr$(34) then   'chr$(34) is double quote mark

Remember, the output from regedit creates entries like this, that begin with a double quote mark: 

"Arial (TrueType)"="ARIAL.TTF"

If the double quote exists, Chris then sets a variable equal to the location of the starting bracket that designates (TrueType) with the INSTR() command. 

            fn = instr(ttf$, "(", 2)       'chr$(34), 2) 

The INSTR command looks for the occurance of a second string within the first string, and allows an optional starting position: 

	INSTR(string1, string2, starting)   

Chris is looking for the occurance of the bracket "(" within the input variable, staring at position 2 in the string, ttf$. He knows that there is a blank space just before this bracket, and that everything following the first double quote mark, up to the space before the "(" bracket is the name of the True Type font. 

fontList$(f) = Trim$(mid$(ttf$,2,fn-2)) 

He has used the string function, MID$ to retrieve just the portion of the entry that containes the name of the font. MID$ looks at a string, in this case it is ttf$, starting at the position specified. For this application, the starting point is "2" because we know that the position "1" contains the double quote mark. The third parameter in the MID$ function is optional. If it is not included, MID$ returns a string from the source string that begins at the position stated and includes the remainder of the string. If a position is stated, then is includes all characters in the source string from the starting position to the ending position. 

	MID$(sourceString$, starting, [ending])

Chris makes his next array element for the fontList$ array the part of ttf$ from position "2" to the position of the "(" bracket, minus 2, which eliminates the bracket itself and the space before it. He then uses TRIM$, which strips any leading or trailing blank spaces from a string, for extra insurance. The result of this takes an input string from the file like this: 

"Arial (TrueType)"="ARIAL.TTF" 

and makes an array element like this: 

Arial

When the end of the file is reached, the file is closed, then it is destroyed, to eliminate extra junk from the user's hard drive: 

    close #list
    kill "font.lst" 

Wow, what a lot of explanation for a small routine! Isn't it amazing how much Liberty BASIC can do, with such a small amount of typing on the part of the programmer? Here is the whole array input routine: 

    open "font.lst" for input as #list   'load font list to array
    while eof(#list)=0
        f = f + 1
        input #list, ttf$ 
        if left$(ttf$,1) = chr$(34) then   'chr$(34) is double quote mark
            fn = instr(ttf$, "(", 2)       
            fontList$(f) = Trim$(mid$(ttf$,2,fn-2))
        end if
    wend
    close #list
    kill "font.lst" 

This routine only loads TrueType fonts. Chris has had the forethought to include FixedSys, a non-TrueType font, but one that is often used. He adds it as the final element in the array: 

'add fixedsys font
    f = f + 1
    fontList$(f) = "Fixedsys" 

He then makes it easy for the user to find the fonts in the array by sorting with LB's SORT function:

   if f > 2 then sort fontList$(, 1, f   'sort font list

Since he will provide the user with a size choice, he quickly fills a fontSize array in a for/next loop.

 
    for fs = 1 to 30            'load font size
        fontSize$(fs) = "";fs
    next fs
 

This array will be used for both the width and height choices.


THE FONT CHOICE DIALOG WINDOW

Chris opens a dialog window to allow the user to choose a font face, width and height. It will contain three listboxes, one for each attribute:

 
    listbox #fontBox.fontList, fontList$(, [fontBox.fontListClick], 6, 6, 237, 100
    listbox #fontBox.fontSizeX, fontSize$(, [fontBox.fontListClick], 248, 6, 64, 100
    listbox #fontBox.fontSizeY, fontSize$(, [fontBox.fontListClick], 318, 6, 64, 100

Notice that listboxes must designate the name of the array that will fill them. Notice also that multiple listboxes may make use of the same array. In this case, the listboxes for width and height both use the fontSize array.

IMPORTANT NOTE ABOUT ARRAYS IN LISTBOXES !

When an array is placed into a listbox, Windows keeps its own index records. It gives index numbers beginning at "1" and it does not skip numbers. For this reason, you cannot count on elements in a listbox array having the same index as the one used to place an element in an array. Be careful when accessing listbox elements by index number.

Did you know that you can create listboxes and comboboxes that display an item at startup -- even before the user makes a choice? This looks much nicer than having them blank and it also insures that these controls will contain a default value, should the user fail to make a choice.

In our program, we'll give the variables font$, FX$ and FY$ values, as in this example: 

    font$ = "Fixedsys" 
    FX$   = "8"
    FY$   = "15"

Then, we'll ask the listbox to display these values at startup with the "select string$" command. Remember that variables must be places outside of the quote marks. 

    print #fontBox.fontList, "select ";font$
    print #fontBox.fontSizeX, "select ";fX$
    print #fontBox.fontSizeY, "select ";fY$

We have a good reason for making these values into variables, which we'll discuss later. If we did not need to have variables for these values, we could have coded the routine like this, with hard-coded values inside of the quote marks: 

    print #fontBox.fontList, "select Fixedsys"
    print #fontBox.fontSizeX, "select 8"
    print #fontBox.fontSizeY, "select 15"


EVALUATING THE USER'S CHOICE

When the user makes a choice in the listboxes, we must retrieve the choice and do something with it. We use the "selection?" command and input the chosen item to a variable, as here: 

    print #fontBox.fontList, "selection?": input #fontBox.fontList, font$
    print #fontBox.fontSizeX, "selection?": input #fontBox.fontSizeX, fX$
    print #fontBox.fontSizeY, "selection?": input #fontBox.fontSizeY, fY$

We now know the font name and width and height that the user would like. What do we do with them? Let's print a sample of the choice for the user to see! We can use a statictext control to show the sample: 

    statictext #fontBox.sample, "sample", 6, 121, 232, 25

We'll just send the statictext control a font command when the user makes a selection. Wait a minute! Liberty BASIC doesn't recognize font names like "Courier New" that contain blank spaces. We'll need to replace those blanks with underscore characters for use in Liberty BASIC font commands.

We do that with string manipulation functions. We'll see if a blank space exists in the font name. If it does, we'll chop off the part of the string before the blank space, then add an underscore character, then add the part of the string that occurs after the blank space. Tada! Oops, what if we have a name like "Times New Roman" that has mulitiple blank spaces? Easy, we'll just do as Chris did, and put the routine inside a WHILE/WEND, so that while there is a blank space still existing in the font name, the routine loops back and removes it. When there are no more blank spaces, the routine ends and we have a version of the font name in proper syntax for use with LB's font command. 

    sp = 1   'remove blanks and replace with LB underscores
    while sp > 0
        sp = instr(font$, " ", sp)
        if sp <> 0 then font$ = left$(font$, sp-1);"_";mid$(font$, sp+1)
    wend

Now, we can send a font command to the statictext control, remembering to place variables outside of the quote marks, and remembering to begin the font command with a "!" character. 

    print #fontBox.sample, "!font ";font$;" ";val(fX$);" ";val(fY$)
    print #fontBox.sample,
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
 

When the user has made his final decision, and closes the dialog window, we'll get the font, width and height into a single string variable, and send a font command to our texteditor, so that it will now display contents in the chosen font: 

    setFont$ = font$;" ";val(fX$);" ";val(fY$)
    print #1.t, "!font ";setFont$


INI FILES 

We can insure that the font chosen by the user will be the default font used in the texteditor the next time he opens the program, if we write the choice to an "ini" file. "Ini" stands for "initialization," which is just a fancy way of saying "start up." A program will read an ini file at startup, to read the setup preferences of the user. Did you know that Liberty BASIC keeps your preferences in an ini file? Look in your Liberty BASIC directory for the file, "lbasic.ini" Open it in any text editor, or even in the Liberty BASIC editor. Go do that now. I can wait... 

Okay, pretty simple stuff, right? Let's write the font preference into an ini file, so that it will be used the next time the program is started. When we close the font dialog window, we'll write the ini file:  

    gosub [write.ini.file]

We'll call the file "editor.ini" and put it in the program's default directory. We'll open it for OUTPUT and print the font information to the file, then close it: 

    open DefaultDir$ + "\editor.ini" for output as #inifile
        print #inifile, setFont$
    close #inifile

We'll check for the existence of the ini file when we open the program. We've used the FILES command in other places in this program to check for the existence of a file. There is another way to do this. As you know, if you try to open a file for INPUT and the file does not exist, the program will crash. The same is not true of a file opened for APPEND. A file opened for APPEND can be opened and added to. Writing to a file that is opened for append will add the new material to the end of the file, while opening it for OUTPUT would erase the file's contents and replace them with new material. We'll open the ini file for APPEND, but not to write to it. We'll just check to see if the file has contents, with the LOF(#file) command. This function tells us the length of the given file. If the length of "editor.ini" is not zero, then the file exists and we can close it and then open it for INPUT. If the length of the file is equal to zero, then we'll close it and abort the reading step.

If the file exists, we open it for input and input the font information that it contains, placing it into the variable, setFont$. Then we can close the file.  

    open DefaultDir$ + "\editor.ini" for append as #inifile
        if lof(#inifile) <> 0 then
            close #inifile
            open DefaultDir$ + "\editor.ini" for input as #inifile
            line input #inifile, setFont$
        end if
    close #inifile

We need to check to be sure that setFont$ has a value, and if it does not, we'll make it "Fixedsys 8 15". We'll then send a !font command to the texteditor, so that it displays the user's chosen font.  

    if setFont$="" then setFont$="Fixedsys 8 15"
    print #1.t, "!font ";setFont$  'set font in texteditor  

We should do one, last thing here. We should give values to the font variables that are used in the font dialog, so that if it is called, it will automatically display the user's current font choice:  

    font$ = word$(setFont$, 1)     'facename
    fX$   = word$(setFont$, 2)     'width
    fY$   = word$(setFont$, 3)     'height
    RETURN

Earlier, we used some string functions, left$ and right$ and mid$. There is another handy function that we've used here, which is word$. Again, I'll let Carl Gundel and the LB helpfile explain this one:

<<BEGIN HELPFILE SNIPPET>>
WORD$( s$, n )
 
WORD$( stringExpression, n )
 
Description:
 
This function returns the nth word in stringExpression.  The 
leading and trailing spaces are stripped from stringExpression 
and then it is broken down into 'words' at the remaining spaces 
inside.  If n is less than 1 or greater than the number of words 
in stringExpression, then "" is returned.
 
Usage:
 
  print word$("The quick brown fox jumped over the lazy dog", 5)
 
Produces:
 
  jumped
            <<END HELPFILE SNIPPET>>


SETTING A FLAG 

It takes a bit of work to run regedit and place all of that information into an array. If we've done it already in this programming session, there is really no need to do it again. We can "set a flag" when we load the font array. We set a flag by setting up a variable that will serve as the flag. We'll use the descriptive name "fontsLoaded" for our flag variable. At the program's startup, we'll initialize the flag variable to 0, showing that the flag is not set: 

    fontsLoaded = 0     'flag for fontloading routine

We'll give it a value of "1" if we've run regedit and loaded the fonts.  

    fontsLoaded = 1     'set a flag that fonts have been loaded

Then, when the user chooses the font dialog, we'll check to see if the flag has been "set" and if it has, we can skip the array-loading routine and go right to the dialog window opening routine. 

    if fontsLoaded=1 then [open.font.dialog] 'skip font loading routine 

That's it for this version of the open source editor. We've allowed the user to choose a display font, we've written an ini file so that the font choice can be used at program startup, and we've discussed setting a flag. Once again, please share any variations you have made to this program, so we can all learn from one another. Thanks. Here is the new part of the code. The entire code is attached to this newsletter as a zip file.


THE NEW CODE:

 
'** NEW **
'drv$               variable for drive in font list routine
'path$              variable for path in font list routine
'ttf$               name of font loaded from list
'sp,f,fs            counter variables in font routine
'font$              font name in font routine
'fX$                width of font
'fY$                height of font
'setFont$           LB fontname and size info for chosen font
'font$              facename of font
'fX$                font size width
'fY$                font size height
 
'for font choice routine:
    dim fontList$(500)  'array of font names
    dim fontSize$(31)   'array of font sizes
    dim temp$(10,10)    'for files statement in font routine
 
    fontsLoaded = 0     'flag for fontloading routine
 
 
'** NEW **
menu #1, "&Tools",_
    "&Branch Labels",[branchlabels],_
    "Bit&map Preview",[bmp],_
    "&Wav Preview",[wav],_
    "&Font Change",[fontBox]
 
'** NEW **
    gosub [read.ini.file]
 
    cursor normal
 
[loop]
    input a$
 
'** NEW **
'Chris Robertson, September 9, 1999
'donna-@ihug.co.nz
[fontBox]
 
    if fontsLoaded=1 then [open.font.dialog] 'skip font loading routine
 
'** export font list from registry
    run "regedit /e ";DefaultDir$;"\font.lst
Hkey_Local_Machine\Software\Microsoft\Windows\CurrentVersion\Fonts", SW_HIDE
 
    drv$ = left$(DefaultDir$,3)
    path$ = right$(DefaultDir$, len(DefaultDir$)-3)+"\font.lst"
    gosub [check4DosOutput]
 
''''''sample entry in list: "Arial (TrueType)"="ARIAL.TTF"
 
    open "font.lst" for input as #list   'load font list to array
    while eof(#list)=0
        f = f + 1
        input #list, ttf$ 
        if left$(ttf$,1) = chr$(34) then   'chr$(34) is double quote mark
            fn = instr(ttf$, "(", 2)       
            fontList$(f) = Trim$(mid$(ttf$,2,fn-2))
        end if
    wend
    close #list
    kill "font.lst"
 
 
'add fixedsys font
    f = f + 1
    fontList$(f) = "Fixedsys"
 
    if f > 2 then sort fontList$(, 1, f   'sort font list
 
    for fs = 1 to 30            'load font size
        fontSize$(fs) = "";fs
    next fs
 
[open.font.dialog]
    fontsLoaded = 1     'set a flag that fonts have been loaded
    WindowWidth = 400
    WindowHeight = 175
 
    listbox #fontBox.fontList, fontList$(, [fontBox.fontListClick], 6, 6, 237, 100
    listbox #fontBox.fontSizeX, fontSize$(, [fontBox.fontListClick], 248, 6, 64, 100
    listbox #fontBox.fontSizeY, fontSize$(, [fontBox.fontListClick], 318, 6, 64, 100
    statictext #fontBox.sample, "sample", 6, 121, 232, 25
    button #fontBox.fontAccept, "Accept", [fontBox.fontAcceptClick], UL, 246, 116, 58, 25
    button #fontBox.fontCancel, "Cancel", [fontBox.fontCancelClick], UL, 326, 116, 58, 25
    open "Chris Robertson's Font Selection" for dialog_modal as #fontBox
    print #fontBox, "trapclose [fontBox.fontCancelClick]"
    print #fontBox.fontList, "font Arial 7 17"
    print #fontBox.fontSizeX, "font Arial 7 17"
    print #fontBox.fontSizeY, "font Arial 7 17"
    print #fontBox.fontAccept, "!font Arial 7 17"
    print #fontBox.fontCancel, "!font Arial 7 17"
    print #fontBox.fontList, "singleclickselect"
    print #fontBox.fontSizeX, "singleclickselect"
    print #fontBox.fontSizeY, "singleclickselect"
    print #fontBox.fontList, "select ";font$
    print #fontBox.fontSizeX, "select ";fX$
    print #fontBox.fontSizeY, "select ";fY$
 
[fontBox.fontListClick]   'Perform action for the listbox named 'fontList'
 
    print #fontBox.fontList, "selection?": input #fontBox.fontList, font$
    print #fontBox.fontSizeX, "selection?": input #fontBox.fontSizeX, fX$
    print #fontBox.fontSizeY, "selection?": input #fontBox.fontSizeY, fY$
    sp = 1   'remove blanks and replace with LB underscores
    while sp > 0
        sp = instr(font$, " ", sp)
        if sp <> 0 then font$ = left$(font$, sp-1);"_";mid$(font$, sp+1)
    wend
 
    print #fontBox.sample, "!font ";font$;" ";val(fX$);" ";val(fY$)
    print #fontBox.sample,
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
 
[waitLoop]   'wait here for input event
    input aVar$
    goto [waitLoop]
 
[fontBox.fontAcceptClick]   'Perform action for the button named 'fontAccept'
    setFont$ = font$;" ";val(fX$);" ";val(fY$)
    print #1.t, "!font ";setFont$
 
[fontBox.fontCancelClick]   'Perform action for the button named 'fontCancel'
    close #fontBox
    gosub [write.ini.file]
    goto [loop]
 
'________subroutines_________
 
[check4DosOutput] 'checks to see if a command line file has been created
'used to wait for dos output
'requires drv$ = drive\
'requires path$ = \path\*.*
'requires temp$(10,10) array
 
    redim temp$(10,10)
    while val(temp$(0,0)) <> 1
        files drv$, path$, temp$(
    wend
 
    while val(temp$(0,1)) = 0
        files drv$, path$, temp$(
    wend
 
    return
 
'** NEW **
[write.ini.file]
    open DefaultDir$ + "\editor.ini" for output as #inifile
        print #inifile, setFont$
    close #inifile
    RETURN
 
 
'** NEW **
[read.ini.file]
    open DefaultDir$ + "\editor.ini" for append as #inifile
        if lof(#inifile) <> 0 then
            close #inifile
            open DefaultDir$ + "\editor.ini" for input as #inifile
            line input #inifile, setFont$
        end if
    close #inifile
 
    if setFont$="" then setFont$="Fixedsys 8 15"
    print #1.t, "!font ";setFont$  'set font in texteditor
 
    font$ = word$(setFont$, 1)     'facename
    fX$   = word$(setFont$, 2)     'width
    fY$   = word$(setFont$, 3)     'height
    RETURN
 
 

Brosco and Alyce have written a Book for Liberty BASIC, which is available in electronic form on a CDROM. For details: http://alyce.50megs.com/sss/cd.htm