---------------------------------------------------------
The Liberty Basic Newsletter - Issue #61 - JAN 2000
       1999, Cliff Bros and Alyce Watson
             All Rights Reserved
---------------------------------------------------------
In this issue:
    Single-Dimensioned Arrays
    3D Dialog Windows
    Open Source Liberty BASIC Editor - Part Four
        Accessing Branch Labels
    About the Open Source Editor Series

In future issues:
    Adding to the Open Source Editor -
        bitmap previewer
        wav previewer
        font change
        your suggestions?
    Installers
---------------------------------------------------------
SINGLE-DIMENSIONED ARRAYS

Go find a sheet of ruled paper and a pencil or pen.  (Do
you remember them?)  Write numbers in a column along the
left side, starting at the top with "1" and ending with
"12".  On the line next to each number, write the name of
the corresponding month.  Next to "1" you will write
"January", next to "2" you will write "February" and so on.

Congratulations!  You have just created an array.  If you
had a non-English speaking friend, who wanted to know the
English name for the 8th month, he could simply find the
entry on line #8.

An array is no more than a list of information.  We'll 
use a string array, which holds character strings, because
we will need that type of an array for the listbox in the
open source editor.  Have a look at newsletters #1, #38 and
especially #39 for more detailed information on arrays.
For a great step-by-step tutorial on using arrays, work
through the Liberty BASIC Tutorial helpfile!


Holding information in arrays is more flexible than having
a bunch of separate variables.  Consider the following
tiny program.  Our array is called color$().  We fill it
to begin so that it contains three LB colors.  We can then
access the color information from the array.  The command

print color$(1)   ' would result in output:
red

No big deal, right?  Okay, look at this:

index = 1
print color$(index) '  would result in output:
red

Putting information into arrays allows us to cycle through
and manipulate it quite easily and quickly.  Cut and paste 
the little program here into Liberty BASIC and run it
for a working example of using an array.  Also, read the
last section of this newsletter, concerning branch label
access.



---------------------------------------------------------
nomainwin
color$(1)="red"
color$(2)="green"
color$(3)="blue"

button #col, "Change",[change],UL,10,50
open "Color Change" for graphics as #col
print #col, "trapclose [quitcol]"
print #col, "down; fill blue"

[colloop]
    input aVar$

[change]
    index=index+1           'increment index number
    if index=4 then index=1 'reset, if too large
    print #col, "fill ";color$(index)
    goto [colloop]

[quitcol]
    close #col:end



---------------------------------------------------------
3D DIALOG WINDOWS

Dialog windows are great tools to use for obtaining
information and choices from a user.  They do look a bit
plain, though.  We have a really, easy way to make our
dialog windows look nice.  Really easy!  We do this with
ctl3d.dll and three, little function calls.  Of course,
we must open the dll:

    open "ctl3d.dll" for dll as #ctl3d

Then we must register as a user and make the call to
AutoSubclass.  That is all we need to do!

    calldll #ctl3d,"Ctl3dRegister",0 as short,result as short
    calldll #ctl3d,"Ctl3dAutoSubclass",0 as short,result as short

Now, instead of having plain, white backgrounds, our dialog
windows will match the user's system colors.  The controls
will also have a three-dimensional appearance.  The best part
of it?  We hardly lifted a finger!  When we close our program,
we must Unregister, and close the dll:

    calldll #ctl3d,"Ctl3dUnregister",0 as short,result as short
    close #ctl3d



---------------------------------------------------------
ACCESSING BRANCH LABELS IN THE OPEN SOURCE EDITOR

When we use this editor, if our code is fairly short, then
we can scroll though it to find the section we need.  If
it is a longer program, we'll need to do an awful lot
of scrolling!  In the default LB editor, Carl Gundel has
provided us with easy access to sections of our code as
defined by the branch labels.  He places them into a listbox
in a dialog window, in the order in which they appear in
the code.  When we choose a branch from the listbox, the
LB editor displays that section of code.

We can do that here, also!  We'll add a menu for this and
future tools:

menu #1, "&Tools",_
    "&Branch Labels",[branchlabels]

Our dialog window will look quite nice, because we have 
used the ctl3d.dll.  Let's set up the window.  We'll want 
a listbox to hold the branch labels, a button to accept 
the chosen label, a button to cancel the operation, and 
of course, our window.  Let's take advantage of the 
dialog_modal window type.  With this type of window, the 
user must close the window before he can do anything else 
in the program.

    WindowWidth=420:WindowHeight=440
    button #2.okay,   "OKAY",  [branch],      UL, 320,10,80,26
    button #2.cancel, "CANCEL",[cancelbranch],UL, 320,40,80,26
    listbox #2.branch, branch$(, [branch],10, 10, 300,380
    open "Branch Labels" for dialog_modal as #2

Let's make our controls look good, and give them each a font 
command.  Note that we need to preceed the command with an
exclamation point for the buttons, but not for the listbox:
    print #2.branch,  "font Courier_New 0 16"
    print #2.okay,   "!font Courier_New 0 20"
    print #2.cancel, "!font Courier_New 0 20"

Have a look at the LISTBOX command.  It includes the
branch label to execute when the listbox is clicked - [branch]
its X, Y position - 10, 10
and its width and height - 300, 380.  

It has one more parameter that is very important -  branch$( 

This param designates the array that should be used to fill 
the listbox.  It must be a string array - an array that holds 
character strings, as opposed to an array that holds numeric 
values.  Liberty BASIC allows us to have arrays of up to 10 
entries without DIMensioning them.  We will need to set a 
dimension for this array, because programs written in the 
editor will almost certainly have more than 10 branch labels!

    dim branch$(40)         'array to hold branch labels

We must DIM an array to a literal number.  

We can:  DIM array$(20)

We cannot:  count = 20 : DIM array$(count)




---------------------------------------------------------
FILLING AN ARRAY WITH A LIST OF BRANCH LABELS

As we start our program, the array is empty.  It contains
no information.  When the user accesses the branch label
function, we'll need to fill the array.  Even though we
have given the array a dimension of 40, that may not be
enough.  If we try to use array items above 40, the program
will crash!  We cannot have more branch labels than there are
lines of code, so let's find out how many lines there are, and 
REDIMension the array to that size:

    Print #1.t,"!lines";
    Input #1.t, rowcount

Notice that we ARE able to REDIM the array to a value held in a
variable.      

    REDIM branch$(rowcount)

It is a good idea to add an array item that will return the
editor to the top of the code.  The user may not have placed
a branch label there, but he may want an easy way to return
to the top of his code.

branch$(0)="<start>"

We could just load the array with all of the lines of code, but
that would be really silly!  We'll need to separate the branch
labels from the other text, and load them into the array.  We'll
do this in a FOR...NEXT loop, checking the content of each line.
If we find a branch label, we'll load it into the array and move
to the next line and check again.  If we don't find a branch label,
we'll just move to the next line and check it.  

Let's input one line at a time from the texteditor, using the 
"!line" command.  We'll keep track of the line we are checking by
using the index variable in our FOR...NEXT loop, which we'll call "i".  
We'll check every line, from line 1 to the line number that is equal 
to the rowcount.  Remember that we must place variables OUTSIDE of
the quote marks in commands:

    for i=1 to rowcount
        print #1.t,"!line ";i;"";
        Input #1.t, line$ 
        {code to find branch labels}
    next i

After we issue the "!line" command, we use the Input command to place
the line of text into our receiver variable, line$

We'll check the content of each line for the left-side bracket that
always signals the start of a branch label.  We could do it like this:

	if left$(line$, 1) = "[" then ....{code to fill array}

That command looks at the left-most characters in line$ and takes just
one of them.  If that character is the left-bracket, then we have a
branch label, and we'll load it into the array.  Most of the time, this
method would work, but sometimes people place spaces BEFORE the branch
label on a line of code.  We'll miss those branch labels.  Liberty
BASIC gives us an easy function to strip off leading and trailing
blank spaces in a character string.  It is the TRIM$ function.  Let's
use it, so we won't miss any of the branch labels:

    if left$(trim$(line$),1)="[" then ....{code to fill array}

The variable that counts which line we are evaluating is incremented 
for us, each time through the loop.  We are using "i".  We'll need
to set up another variable that keeps track of the index in the
array to which we add the branch label.  It must be a different
counter variable than "i" because each line of code will not include
a branch label.  We'll want to increment this counter ourselves, each
time we fill an array item with a branch label.  We'll set that
counter variable to "1" to start:

    bx=1

Now we are ready to fill the array.  If we find a left-bracket in
a line, we can load that line into the array:

    branch$(bx)=line$

Wow, what a lot of words to explain such a small routine!  The
consise way we can express complex formulae and algorithms is
part of the beauty and elegance of well-written code.  Here is
the routine:

    for i=1 to rowcount
        print #1.t,"!line ";i;"";
        Input #1.t, line$ 
            if left$(trim$(line$),1)="[" then
                branch$(bx)=line$
                bx=bx+1
            end if
    next i

We can leave it as is, or we can place the branch labels into
alphabetical order with the SORT command:

    SORT branch$(,0,bx

Don't forget to issue a RELOAD command to the listbox, so
that it is updated to contain the new elements in the array.

    Print #2.branch,"reload"
    print #2.branch, "selectindex 1";
    print #2.branch, "setfocus"




---------------------------------------------------------
GO TO THE CHOSEN BRANCH LABEL

Whew!  Now we need to write a routine that retrieves the
branch label chosen by the user, and sets the texteditor
to display that part of the code.  We get the user's
choice with the "selection?" command, placing it into
the variable branchselect$ with the "Input" command:

    print #2.branch,"selection?"
    Input #2.branch,branchselect$ 

Now, we must evaluate each line of code to see if it
contains the branch label selected, and if it does, we
close the branch label dialog, and set the contents of the 
text editor to display the correct part of the code.

Let's use a FOR...NEXT loop, with our counter variable, "i"
again.  We'll check each line, starting at line 1, and ending
at line(rowcount).

    For i = 1 TO rowcount
       print #1.t,"!line ";i;
       Input #1.t,line$

We'll check to see if the user's selection is the same as the
line we are checking:

          If trim$(line$)= branchselect$ Then

If we have a match, we tell the texteditor to display the
section of code that is marked by that branch label.  We do
this by setting the texteditor origin to row "i" and column
0.  Row "i" is the one we just found that matches the user's
branch label selection.  The "origin" of the textbox is in the
upper-left corner.  Using the "!origin" command tells the 
texteditor which row and column of text should appear in the
upper-left corner of the text field.

            Print #1.t, "!origin ";i;" ,0";

We are within a FOR...NEXT loop.  If we have found the correct
line, there is no need to evaluate the rest of the text, is there?
BUT, we are not suppposed to jump out of this loop prematurely!  
This could cause some big problems; perhaps a crash.  The solution
is to set our counter variable, "i" equal to the maximum count,
which in this case is contained in the variable "rowcount".  This
should enable us to exit the loop properly.  So, if we find a
match, we'll set i=rowcount and close the dialog window.

            i=rowcount
            close #2
            goto [loop]




---------------------------------------------------------
DISPLAYING THE TOP OF THE CODE

OOPS!  We must evaluate a special case.  We have added an
array element <start>.  There is NO corresponding branch label
in the user's code to <start>.  Why, it doesn't even have a 
left-bracket!  We know that we want to set the origin to 
1, 1 - the first row, and the first column of text if the user 
chooses <start> so here is that routine:

    if branchselect$="<start>" then
        print #1.t, "!origin 1 1";
        close #2
        goto [loop]
    end if
 
Why did we specify an origin column of "0" earlier, and "1"
here?  It doesn't matter, really.  It is more correct to
call the first row or column "1", but if you call it "0",
Liberty BASIC will not fuss at you!

The last thing we need to do is make a routine that allows
the user to cancel the branch label dialog without
choosing a branch label.  When we began this routine, we
retrieved the row,column location of the text in the editor.
We can use those values now to reset the texteditor to the
spot it displayed before the dialog was opened.  Then, we
need only close the dialog window.  Let's also set the
focus back onto the texteditor, so that keyboard input will
be directed there:

[cancelbranch]
    close #2
    print #1.t, "!origin ";rowVar;" ";columnVar;"";
    print #1.t, "!setfocus";
    goto [loop]


---------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
---------------------------------------------------------
ABOUT THE OPEN SOURCE EDITOR SERIES

Please post comments and suggestions about this open source
editor.  Please, please send in your own versions, so that
we can all learn from one another.

This program is not meant to be a definitive editor, but
rather a starting-point for personalizing, playing, &etc.
For instance, in the branch label routine added in this
installment, we have designated a <start> routine, but
not an <end> routine, nor have we considered numbered
lines as branch labels.

This Editor series will function as a working laboratory
to test, explain, and demonstrate many facets of Liberty
BASIC programming.  It will also serve (we hope) as a 
template, or example of building a complex program one
layer at a time.

The open source editor is not only an editor, but a
vehicle for learning.  Some routines will be comprised
of elementary code techniques, while others may use more
advanced techniques.  Discussion is encouraged!
---------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
---------------------------------------------------------

The source code file for this editor is getting rather 
large, so from this point on, it will be attached as a 
ZIP to the newsletters.  Thanks.  This one is called
open04.bas.

---------------------------------------------------------
Newsletter compiled and edited by: Brosco and Alyce.
Comments, requests or corrections: Hit 'REPLY' now!
mailto:brosco@orac.net.au or mailto:awatson@wctc.net
---------------------------------------------------------
