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 #61 - JAN 2000

© 1999, Cliff Bros and Alyce Watson All Rights Reserved


In this issue:

  1. Single-Dimensioned Arrays
  2. 3D Dialog Windows
  3. Open Source Liberty BASIC Editor - Part Four

In future issues:


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 written by: Brosco. Comments, requests or corrections to: brosco@orac.net.au Translated from Australian to English by an American: Alyce Watson. Thanks Alyce.