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

The Liberty Basic Newsletter - Issue #75 - JUN 2000

© 2000, Side by Side Software

http://alyce.50megs.com/sss/

All Rights Reserved

In this issue:

In future issues:


"Opportunity is missed by most people because it is dressed in overalls and looks like work."

- Thomas Edison


RUNNING A WINDOWS HELPFILE

The engine that runs helpfiles is called "Winhelp." and we can access it easily with Liberty BASIC's RUN command. To run a specific helpfile, we include the name of the desired file in the RUN command string. Here is the way we called the Liberty BASIC helpfile from our open source editor:

[help]
    run "winhelp liberty.hlp"
    goto [loop]

The RUN command allows us to specify a mode for running. Here is an example from the helpfile:

RUN "WINFILE.EXE", SHOWMAXIMIZED  ' run the File Manager maximized

We could specify a mode in the open source editor. If we wanted the helpfile to run, but to be mimimized (on the taskbar in Win95+):

[help]
    run "winhelp liberty.hlp", SHOWMINIMIZED
    goto [loop]

Other possible RUN modes:

	HIDE
	SHOWNORMAL  (this is the default)
	SHOWMINIMIZED
	SHOWMAXIMIZED
	SHOWNOACTIVE
	SHOW
	MINIMIZE
	SHOWMINNOACTIVE
	SHOWNA
	RESTORE

In the previous newsletter, we discussed running files with their associated applications with the ShellExecute command. The extension ".hlp" is associated with "Winhelp.exe." This sample program allows the user to choose and run any helpfile in minimized mode. It relies on ShellExecute to find the executable associated with "*.hlp" files:

filedialog "Choose a helpfile...","*.hlp",help$ 
if help$="" then end
 
    lpFile$=help$+chr$(0)
    lpOperation$ = "open" + chr$(0)
    lpParameters$ = "" + chr$(0)
    lpDirectory$ = "" + chr$(0)
    nShowCmd = _SW_SHOWMINIMIZED
 
    open "shell.dll" for dll as #shell
    calldll #shell, "ShellExecute", _
        hWindow as word, _          'parent window
        lpOperation$ as ptr, _      'open or print
        lpFile$ as ptr, _           'file name
        lpParameters$ as ptr, _     'parameters for executable
        lpDirectory$ as ptr, _      'default directory
        nShowCmd as short, _        'show window flag
        result as word
    close #shell

Here is another, very similar example. This one names "Winhelp.exe" as the executable to run, and passes the helpfile name as the parameter. Either method works fine. This one will maximize the chosen helpfile:

filedialog "Choose a helpfile...","*.hlp",help$ 
if help$="" then end
 
    lpFile$="Winhelp.exe"+chr$(0)
    lpOperation$ = "open" + chr$(0)
    lpParameters$ = help$ + chr$(0)
    lpDirectory$ = "" + chr$(0)
    nShowCmd = _SW_SHOWMAXIMIZED
 
    open "shell.dll" for dll as #shell
    calldll #shell, "ShellExecute", _
        hWindow as word, _          'parent window
        lpOperation$ as ptr, _      'open or print
        lpFile$ as ptr, _           'file name
        lpParameters$ as ptr, _     'parameters for executable
        lpDirectory$ as ptr, _      'default directory
        nShowCmd as short, _        'show window flag
        result as word
    close #shell


HOW-TO FOR HELPFILE MAKING

Helpfiles are compiled by a help compiler. Microsoft makes these compilers freely available, and there are several different versions in both 16- and 32- bit. You might use hc31.exe, hcp.exe, hcrtf.exe, etc.

The help compiler requires a rich text format (RTF) file. It is possible to create this file yourself if you have access to an editor that will produce .RTF files. You must include all of the proper tags. This is not as easy as it sounds. I once worked through part of a tutorial on creating a helpfile.rtf. It was tremendously complicated and I got lost early-on and never actually completed anything.


CREATING A WINDOWS HELPFILE

There are many helpfile maker utilities that can be downloaded on the 'net. Look at any download site, like these:

http://www.zdnet.com/ 
http://shareware.cnet.com/ 
http://www.winsite.com/

Freeware and shareware Win95+ help authoring tools:

http://winfiles.cnet.com/apps/98/helpfile.html

All have different features, but most of the help authoring utilities I've tried make it easy to write a text file, have it converted automatically into an RTF file with the proper tags, and call the help compiler to compile it.


CREATING A 32-BIT HELPFILE WITH OASIS SE (WIN95+ only)

There is a 32-bit freeware help authoring tool called Oasis SE. As of June 6, 2000, it was available for download here:

http://www.helpmaster.com/help/standalone/popoasis.htm

You will also need the help compiler provided by Microsoft. The compiler and its necessary DLL are included in the attachment to this newsletter.

hctrf.exe
hwdll.dll

This utility will work on Win95+ systems only, and it creates helpfiles that are suitable for Win95+ systems. It is sometimes unstable, and it has some bugs. I have used it quite successfully, however.

There is a sample project in the zip file that is attached to this newsletter. To work properly all files must be in c:\helptemp\. Please create "c:\helptemp\" and move the files there. The reason the files must be in this directory is explained later in this article.

nl0075.rtf
nl0075.cnt
nl0075.hlp
nl0075.ohp
nl0075.hpj
 
torch.bmp
hlp.bmp

 


CORRUPT PROJECT

Oasis SE has some bugs. It is best to save all project files in a separate zip file from time to time, so that all work is not lost if a project becomes corrupted. Help projects cannot be moved easily to different directories, because file paths for all project files are set within the project. This is why it is easiest to back up the project by saving in a zip file.

GETTING STARTED

Helpfiles are created as projects. Choose NEW from the file menu or click the NEW button on the toolbar to begin a new project. A question icon with the title "New Topic" will appear in the topic listbox. You can rename this by highlighting it and going to the TOPIC menu. Choose EDIT CAPTION.

TOPICS

A TOPIC is the text that will appear in one helpfile window. It can be quite long. Scrollbars will be added automatically if needed. To write the topic, simply type text into the textedit portion of the Oasis window.

You can also copy text in another application and paste it into this texteditor.

PARAGRAPHS

Carriage returns and tabs are preserved in the project, just as they are typed into the editor. Paragraphs can be justified left/center/right as desired by clicking the justification buttons on the upper toolbar.

FONTS

There is a font combobox on the upper toolbar that allows you to choose a fontname. I must guess that it is best to choose standard fonts like Arial, to make sure they exist on every user's system. Again, this is a guess, but I think that a default font will be substituted if the named font is not available. There is a second combobox that allows you to choose the size of font. There are buttons that allow you to make text bold, italic, etc. You may also choose a font color from the drop-down color list. Fonts in different styles, sizes and colors may all appear within one topic.

NEW TOPIC

You can create a new topic by choosing this option from the menu, or by clicking the question mark button on the toolbar. You can change the topic caption at any time.

MOVE TOPICS

You can rearrange topics or delete them by highlighting a topic and clicking on the arrow buttons or X button, or chosing MOVE or DELETE from the topic menu. Topics will appear in the compiled help contents window in the order they appear in the topic tree listbox.

DEFAULT TOPIC

There is an option to set a topic to be the default topic that displays when a helpfile is first opened. DO NOT USE THIS OPTION!!! It always corrupts the project when I try to use it. See above for advice about saving projects.

HEADERS

You can gather topics together under headers, but this is optional. To create a new header, choose NEW from the TOPIC menu, or click the "purple book" button on the toolbar. Give the header the desired name by typing into the textbox beside the book icon in the topic tree listbox. Headers can be created in the root of the tree, or within other topics or headers. Headers appear in the compiled help contents window in the order in which they are listed in the topic tree listbos.

SUBTOPICS

A subtopic appears within a header. Highlight the header that is to contain a new subtopic, then click the purple arrow button that appears under the purple book button, or choose NEW from the TOPIC menu. Subtopics work exactly the same as topics. Unlike regular topics, they do not appear in the help contents window of a compiled project until the icon for the header that contains them is clicked.

HIDDEN TOPICS

Any topic or subtopic can be hidden. When the desired topic is highlighted in the topic tree listbox, choose HIDDEN from the TOPIC menu or right click and choose HIDDEN from the popup menu. The icon question mark will now show a "!" also in the topic tree listbox. A topic that is hidden does not show in the contents window of the helpfile. It must be accessed by a jump link or popup link from within another topic.

JUMP LINKS

There are three LINK menu choices in the TOPIC menu, with three corresponding LINK buttons on the toolbar. A jump link accesses a different topic and loads it into the help window. This topic can be listed in the contents window of the helpfile, or it can be hidden. To create a jump link, place the cursor in the texteditor of the desired topic, making sure it is at the position where the link should appear.

Choose JUMP LINK. The topic tree assumes a different appearance. Now, simply click on the topic within the topic tree. The topic tree returns to its normal appearance, and a text link to that topic will appear in the current topic's texteditor at the cursor location. It is underlined to show that it is a link. Delete the text link if you need to remove the link. In the compiled help project, this text will show as an underlined link. When the user clicks it, the linked topic will replace the current topic in the help window.

POPUP LINKS

Although a popup link can be listed in the helpfile contents window, it is more often a hidden topic. When the popup link is clicked, the topic pops up in a new window, leaving the previous topic window as it was. You may choose to make a popup link either from the TOPIC menu or by clicking the popup link button on the toolbar. Just as with the jump link, the text cursor should be located in the texteditor at the spot where the popup link will appear. The topic tree assumes an altered appearance. Navigate the topic tree and click on the topic that is to be accessed by the popup link.

The topic tree will return to its normal appearance, and the topic caption will appear in the texteditor as underlined text. In the compiled helpfile, this underlined text will cause the topic referenced to popup in a new window.

URL LINKS

Choose to make a URL hotlink from the menu, or from the associated button on the toolbar. You wil be presented with a dialog box containing two textboxes. The top box must contain the URL for the link. It will be in this form: http://www.libertybasic.com/

The second textbox must be filled with the text that defines the URL. For the above URL, it might be "The Liberty BASIC Homepage!" To delete a URL link from a topic, highlight it and delete it as any other text.

WINDOW OPTIONS

COLOR -- You may set the colors for the body backgrounds of the help window and for the nonscrolling region here. You may select from the standard palette, or choose a custom color. This option appears to work perfectly.

BUTTONS -- There is an option that allows you to choose the default buttons that will appear on the help window. Changing these settings can corrupt the project, so I suggest leaving it as it is.

GENERAL -- Click the 'general' tab and fill in the desired title that will appear as the caption on the titlebar.

POSITION -- There is an option to change the help window's size and position. It doesn't appear to work properly.

PROJECT OPTIONS

HELP TITLE -- You may fill in this textbox to give the project a title. You may leave it blank.

VERSION -- Fill in this textbox to add your own information to the window that appears when VERSION is chosen from the helpfile menu by a user. You may leave it blank.

APPEND COPY TEXT -- The text you placed here will automatically be added to the text in the topic article, when COPY is chosen by a helpfile's user. You may leave it blank.

COMPRESSION -- Changing the compression type in and Oasis SE help project is likely to corrupt the project. If the project becomes corrupted, try setting compression back to NONE. If compression is desired, try CUSTOM with only the ZECK COMPRESSION box checked. This seems to work fine. Compression will make a smaller help file. This is more important for larger files, of course.

FTS -- This is the Full Text Search set of options. Choose the level of searching that should be available to users.

COMPILER -- Set the path to the help compiler here, so that Oasis SE can find it! You may place hctrf.exe and hwdll.dll in the directory of your choice. If you move them from the "c:\helptemp" directory in the sample project, be sure to change the path with this OPTION --> COMPILER feature.

SORTING -- There is no need to alter any settings here.

KEYWORDS

Keywords are the words that appear in the INDEX listbox of a compiled help project. Clicking on a word takes the user to the associated topic. If you do not add any keywords to the project, the INDEX tab will be disabled.

It is easy to add keywords to topics. Highlight the desired word in the texteditor displaying a topic. Right click and choose to make it a keyword. It will then appear in the KEYWORDS listbox. To remove a keyword, highlight it in the KEYWORDS listbox, and right click to delete it.

NON-SCROLLING REGION

You can have an optional banner at the top of a help window. This is called a non-scrolling region because it is always there and does not disappear when scroll bars are activated by a user. Each topic sets this individually, so some topics may have a non-scrolling region while others so not. Type into this region just as you type into the texteditor portion of the topic. This is a good place to use bold text, center justified, to place a topic title or other important information. You can also place links here.

SAVE AND COMPILE

Be sure to save the project before compiling. It will be saved as an OHP file, which stands for Oasis Help Project.

You will need to make sure that Oasis SE knows where to find the help compiler. Go to the PROJECT menu and choose OPTIONS. Click on the COMPILER tab and fill in the path to the compiler on your system.

Compile by choosing COMPILE from the menu, or clicking the grinder button. Compiling successfully will create an HLP file and a CNT file, along with an HPJ (Help ProJect) file and the RTF (Rich Text Format) file required by the help compiler.

HLP AND CNT

You may distribute the *.hlp file alone, if desired. If you also include the *.cnt file in your distribution, the user will be able to access the standard Win95 help contents popup window. This is the window that contains the purple book and question icons for headers and topics. Your user can navigate the helpfile easily with this window. This window also contains the INDEX tab. Clicking INDEX accesses the listbox of keywords you have added to the project. Clicking a keyword opens the associated topic in the help window. The FIND tab allows the user to search the entire helpfile for the desired word or phrase.

BITMAPS

The use of bitmaps is explained in the Oasis SE helpfile:

In order to insert a bitmap into your topic. Type in text of following form:

{bmx[t] filename}

where x can be one of following:

c

Aligns the bitmap as a text character on the baseline of the type in exactly the same place in the paragraph where the reference occurs. Because the bitmap is treated as text, any paragraph formatting properties assigned to the paragraph also apply to the bitmap.

l

Aligns the bitmap along the left margin. Text is aligned with the upper right corner of the bitmap and wraps along the right edge of the image.

r

Aligns the bitmap along the right margin. Text is aligned with the upper left corner of the bitmap and wraps along the left edge of the image.

t

An optional parameter specifying that the white background of the graphic should be replaced by the background color of a Help topic. This character can be specified in addition to any of the other values. It can be used only with 16-color bitmaps. The square brackets is not to be included in the statement.

filename

is the name of the bitmap file to be inserted. Don't forget to include the curly-brackets!

e.g

{bmct ./bmp/button.bmp}


LB HELP SIMULATION

It is also possible to create a help feature using Liberty BASIC code. This type of help is limited only by the programmer's imagination, and the abilities of Liberty BASIC. There are two types of helpfiles in LB syntax available at the following URL:

http://alyce.50megs.com/brosco/

The files to look for:

lbhelp.zip by Brosco
helpdemo.zip by Bob Oakes

If a small amount of information is to be contained in the help feature, it is possible to place it all into a NOTICE message. Here is an example:

notice "Type the desired text into the textbox and click the OKAY button to finish. Click the CANCEL button to abort the operation."

For a larger amount of information, a text window can be used. The desired text can be printed directly into the text window, or loaded from an associated file. If a separate text file will be used, be sure to check for the file's existence before attempting to load it. Be sure to set a flag if the help text window is open. The program will crash if it tries to open a window that was opened previously. Here are some examples:

 
'using a separate file:
nomainwin
    if FileExist(DefaultDir$,"lbasic.ini")<1 then
        notice "Error"+chr$(13)+"File does not exist."
        end
    end if
 
if helpopen = 1 then [loop]
helpopen = 1
 
open "Help Window" for text as #help
open "lbasic.ini" for input as #ini
print #help, "!contents #ini";
close #ini
print #help, "!origin 1 1";
print #help, "!trapclose [quit]";
input a$ 
[quit]
close #help
helpopen = 0
goto [loop]
 
    function FileExist(fPath$,fFile$)
        dim info$(10,10)
        files fPath$,fFile$,info$(
        FileExist=val(info$(0,0))
        end function
 
[loop]
'this will be the main program's input loop
end  'end is used for this example only
 
 
 
'print directly to text window:
 
nomainwin
if helpopen = 1 then [loop]
helpopen = 1
open "Help Window" for text as #help
print #help, "Here is some help."
print #help, "Thank you."
print #help, "!origin 1 1";
print #help, "!trapclose [quit]";
input a$ 
[quit]
close #help
helpopen = 0
goto [loop]
 
[loop]
'this will be the main program's input loop
end  'end is used for this example only


ADDING A HELP WINDOW TO THE OPEN SOURCE EDITOR

Here is the code to add a rudimentary help window to the open source editor. Notice that a flag called "helpopen" is equal to "1" when the window is open and "0" when the window is closed. The program would crash if a user attempted to open the help window if it was already open, and the use of a flag will prevent that. The full editor code is attached to this newsletter: open14.bas. Feel free to modify it and share your version with the group.

 
[edithelp]
    if helpopen = 1 then
        notice "Help window is already open!"
        goto [loop]
    end if
 
    helpopen = 1
    WindowWidth=400:WindowHeight=300
    open "Help" for text as #help
    print #help, "Use this editor to write, edit and run"
    print #help, "Liberty BASIC source code."
    print #help, "Be sure to try out the many"
    print #help, "programming tools provided."
    print #help, "This program is in the public domain."
    print #help, "Feel free to use and modify."
    print #help, "!origin 1 1";
    print #help, "!trapclose [quit.edithelp]";
 
    input a$ 
 
    [quit.edithelp]
    close #help
    helpopen = 0
    goto [loop]


HTML HELP

HTML helpfiles are becoming more common. They can be created with a simple texteditor. There are also many commercial, shareware, and freeware html editors available, including some that have been written in Liberty BASIC.

Some Help Authoring tools contain an option to create the file in HTML format. Newsletter #52 provides the basics of writing HTML.

To run a helpfile in HTML format, use the ShellExecute function that was explained in newsletter #74. The "html" and "htm" extensions will be associated with a user's default browser, so the ShellExecute command will launch the default browser with the specified file displayed. In the previous newsletter, we launched a browser with a URL. It also works to launch it, as we are doing here, with an HTML file.

    RunFile$="myhelp.htm"+chr$(0)
    lpOperation$ = "open" + chr$(0)
    lpParameters$ = "" + chr$(0)
    lpDirectory$ = "" + chr$(0)
    nShowCmd = _SW_SHOWNORMAL
 
    open "shell.dll" for dll as #shell
    calldll #shell, "ShellExecute", _
        hWindow as word, _          'parent window
        lpOperation$ as ptr, _      'open or print
        RunFile$ as ptr, _          'file name
        lpParameters$ as ptr, _     'null
        lpDirectory$ as ptr, _      'default directory
        nShowCmd as short, _        'show window flag
        result as word
    close #shell


MAKING PROGRESS

"To climb steep hills requires slow pace at first."

- William Shakespeare

We have a lot of people who are new to Liberty BASIC in our group, and in general. I sometimes see messages from people who are newbies, and they are trying to accomplish complex tasks. When this is the case, people usually become very frustrated.

Consider; if you begin to learn the piano, you do not try to play a Chopin concerto as one of your first pieces! You would begin with "Twinkle, Twinkle, Little Star" and work to improve over time.

To learn, first work with Liberty BASIC commands and functions. Leave the API stuff for much later. Don't look at a blank screen in the editor.

Open up one of the demos that comes with LB, or a simple demo from another source. First step; see if you understand the function of each line. Try running the code in the debugger, choosing STEP mode and checking the changing values of variables as you go along. If something puzzles you, have a closer look. If you can't work it out, post a question!

Once you understand the program, try to modify it. Do this a little at a time, so you will know exactly which part of the code is at fault when you encounter an error. A lot of people start with the Tic Tac Toe demo that comes with LB, and I've seen some very clever versions of this over the years.

Make use of the tutorials that Carl Gundel has provided. I learned to program from them!

Try using all of the different window and control types. READ THE HELPFILE! Even experienced LBers would benefit from reading the helpfile from time to time. Every time I read it, it seems I find some gem that I've overlooked or forgotten.

Once you have a thorough knowledge of LB windows/controls/commands/functions, then you can move on to more complex techniques. If you try to tackle the tough stuff at the beginning, you are setting yourself up for frustration, if not failure!


SORTING ALGORITHMS BY DAVID SZAFRANSKI

 

' A Comparison of Various Sorting Algorithms
' ------------------------------------------
' updated 08/31/98 by David Szafranski   http://libertynow.webjump.com/
' I found this demo on the newsgroup alt.lang.basic and have converted
' it to run on LB. It was written by Edward Collins.
 
' This demo compares the times to sort a numeric array
' using a variety of sorting algorithms:
 
' Bubble Sort, Bubble Sort(Enhanced1), Bubble Sort(Enhanced2),
' Exchange Sort, Heap Sort, Insertion Sort, QSort,
' Shell Sort, and Liberty Basic's Sort Command.
 
' You might notice that the "QuickSort" algorithm is missing from this list...
' The reason this is not included is that it requires recursion which is
' not yet possible using LB. (please correct me if I am wrong here!)
 
' The number of items to sort is held in the variable
' "nmbrOfItems".
 
' The program displays the results to the screen.
 
' The array "theArray()" is sorted starting with element 1, not element 0,
' so if you intend to use any of these algorithms, you should subtract 1
' from the index, ie change each to "theArray(...-1)"
 
' The sorting algorithms are timed using the API call GetTickCount
 
' If you have an extremely fast PII or PIII processor, then you may want to
increase
' the number of items to be sorted from 200 to some larger number like 1000
inorder
' to increase the total calculation time.
 
' For each algorithm, four types of arrays are sorted:
' The "already sorted" array is just that... already sorted.
 
' The "complete opposite" array is in the exact opposite order from what
' is desired.
 
' The "random mixup" array is like a well-shuffled deck of cards.
 
' The "nearly sorted" array is sorted fine for the first (in this case)
' 180 items.  However, the final 20 elements that are in the array need
' to be sorted within the main body.  (This number 20 can be altered.)
 
 
' To add your own algorithm...
' ----------------------------
'  1) Increase the variable "nmbrOfAlgorithms" from 9 to 10
'  2) name your algorithm in the algorithm$() array
'  3) Create your own subroutine for it.  The array
'        named "theArray()" holds the data to sort
'  4) call this new subroutine from the subroutine
'        named "Sort.The.Array"
 
 
    nmbrOfItems = 200     ' change this for larger or smaller arrays
    nmbrOfAlgorithms = 9    ' change this if you add another algorithm
 
' ------------------------------------------------------
    arraySize = nmbrOfItems + 1     'The original version of this program uses
    redim theArray(arraySize)       'arrays which begin with 1... whereas LB
    redim results(4, nmbrOfAlgorithms)   'starts arrays with 0...
    redim algorithm$(nmbrOfAlgorithms)
 
    algorithm$(0) = "Bubble Sort           "
    algorithm$(1) = "Bubble Sort(Enhanced1)"
    algorithm$(2) = "Bubble Sort(Enhanced2)"
    algorithm$(3) = "Exchange Sort         "
    algorithm$(4) = "Heap Sort             "
    algorithm$(5) = "Insertion Sort        "
    algorithm$(6) = "QSort                 "
    algorithm$(7) = "Shell Sort            "
    algorithm$(8) = "LB Sort Command       "
    'algorithm$(9) = "Your algorithm here  "
 
            print "Working...";
 
    FOR array.type = 0 TO 3
        FOR algorithm = 0 TO nmbrOfAlgorithms-1
 
            gosub [Create.Array.Items]    'create 4 types of arrays to sort
 
'            gosub [print.starting.array]    'uncomment this to show
starting array
 
            open "user.dll" for dll as #user        'start timing
                calldll #user, "GetTickCount", _
                result as long
            close #user
 
            start = result
 
            gosub [Sort.The.Array]     '(algorithm)
 
            open "user.dll" for dll as #user        'finish timing
                calldll #user, "GetTickCount", _
                result as long
            close #user
 
            finish = result
 
            results(array.type, algorithm) = finish - start    'total time
elapsed
 
'            gosub [print.resulting.array]   'uncomment this to check the
results
            print ".";
 
        NEXT algorithm
        print ".";
 
    NEXT array.type
 
    print ""
 
    gosub [Show.Results]
 
 
    END
 
 
'============== Start of Subroutines ===================================
 
[Sort.The.Array]
    if algorithm = 0 then gosub [Bubble.Sort]
    if algorithm = 1 then gosub [Bubble.Sort.Enhncd]
    if algorithm = 2 then gosub [Bubble.Sort.Enhncd2]
    if algorithm = 3 then gosub [Exchange.Sort]
    if algorithm = 4 then gosub [Heap.Sort]
    if algorithm = 5 then gosub [Insertion.Sort]
    if algorithm = 6 then gosub [Qsort.Sort]
    if algorithm = 7 then gosub [Shell.Sort]
    if algorithm = 8 then gosub [LB.Sort]
'   if algorithm = 9 then gosub [your.algorithm.here]
 
return
 
 
'======================================================================
 
[Show.Results]
 
PRINT " Comparison of Various Sorting Algorithms."
PRINT " The times listed are the     "
PRINT " number of seconds that it    "
PRINT " takes to sort an array of ";
PRINT nmbrOfItems; " elements."
 
 
PRINT
"========================================================================="
 
 
PRINT "                         Already   Complete  Random    Nearly"
PRINT "                         Sorted    Opposite  Mixup     Sorted     AVG"
PRINT
"========================================================================="
 
FOR count = 0 TO nmbrOfAlgorithms-1
 
    PRINT algorithm$(count); "  ";
        sum = 0
        FOR array.type = 0 TO 3
            print using("##.###", results(array.type, count)/1000);
            print "    ";
            sum = sum + results(array.type,count)/1000
        NEXT array.type
        print using("##.###", sum/4);
    print ""
NEXT count
return
 
 
 
'======================================================================
 
[print.starting.array]
        for i = 1 to nmbrOfItems
        print theArray(i); " ";
        next i
        print ""
        print "========"
return
 
 
'======================================================================
 
[print.resulting.array]
 
        for i = 1 to nmbrOfItems      'check the results
        print theArray(i); " ";
        next i
        print ""
        print "========"
return
 
' ============================== Bubble Sort ===========================
' The Bubble Sort algorithm cycles through the array, comparing adjacent
' elements and swapping pairs that are out of order.
' ======================================================================
[Bubble.Sort]
FOR a = 1 TO nmbrOfItems - 1
  FOR b = 1 TO nmbrOfItems - 1
     IF theArray(b) > theArray(b + 1) THEN
'        SWAP theArray(b), theArray(b + 1)
        temp1 = theArray(b)
        temp2 = theArray(b + 1)
        theArray(b) = temp2
        theArray(b + 1) = temp1
     END IF
  NEXT b
NEXT a
return
 
 
 
 
' ============================== Bubble Sort Enhanced1 ==================
' The Bubble Sort algorithm cycles through the array, comparing adjacent
' elements and swapping pairs that are out of order.  It continues to
' do this until no pairs are swapped.
' ======================================================================
[Bubble.Sort.Enhncd]
array.is.sorted = 0
 
while array.is.sorted = 0
  array.is.sorted = 1            ' this flag is what makes it "enhanced"
  FOR count = 1 TO nmbrOfItems - 1
     IF theArray(count) > theArray(count + 1) THEN
'        SWAP theArray(count), theArray(count + 1)
        temp1 = theArray(count)
        temp2 = theArray(count + 1)
        theArray(count) = temp2
        theArray(count + 1) = temp1
        array.is.sorted = 0
     END IF
  NEXT count
wend
return
 
 
 
' ============================== Bubble Sort Enhanced2 ===============
' The Bubble Sort algorithm cycles through the array, comparing adjacent
' elements and swapping pairs that are out of order.  After the inside
' FOR loop finishes for the first time, the largest element is positioned
' in it's proper place.  Therefore we don't ever have to compare that
' number anymore.  So for that next cycle, we have one less element to
' compare each time.  This is the enhancement over the previous two
' Bubble Sorts.
' ======================================================================
[Bubble.Sort.Enhncd2]
    a = nmbrOfItems
    array.is.sorted = 0
    while a >= 1 and array.is.sorted <> 1
'    FOR a = nmbrOfItems TO 1 STEP -1
    array.is.sorted = 1
        FOR b = 2 TO a
            IF theArray(b - 1) > theArray(b) THEN
'                SWAP the.array(b - 1), the.array(b)
                temp1 = theArray(b-1)
                temp2 = theArray(b)
                theArray(b-1) = temp2
                theArray(b) = temp1
                array.is.sorted = 0
            END IF
        NEXT b
'        IF array.is.sorted = 1 THEN EXIT FOR
'    NEXT a
    a = a -1
    wend
return
 
 
' ============================= Exchange Sort ========================
' The Exchange Sort compares each element in the array, starting with
' the first element, with every following element.  If any of the
' following elements are smaller than the current element, it is
' exchanged with the current element and the process is repeated
' for the next element in the array.
' ====================================================================
[Exchange.Sort]
FOR a = 1 TO nmbrOfItems
   less = a
   FOR b = less + 1 TO nmbrOfItems
      IF theArray(b) < theArray(less) THEN less = b
   NEXT b
   IF less > a THEN
'      SWAP theArray(a), theArray(less)
        temp1 = theArray(a)
        temp2 = theArray(less)
        theArray(a) = temp2
        theArray(less) = temp1
 
   END IF
NEXT a
return
 
 
' =============================== Heap Sort ===============================
'  The Heap Sort procedure works by calling two other procedures -
'  Percolate.Up and Percolate.Down.  Percolate Up turns the array into
'  a "heap," which has the properties outlined in the diagram below:
'
'                               theArray(1)
'                               /          \
'                    theArray(2)           theArray(3)
'                   /          \             /         \
'         theArray(4)   theArray(5)    theArray(6)  theArray(7)
'          /      \       /       \        /      \      /      \
'        ...      ...   ...       ...    ...      ...  ...      ...
'
'
'  where each "parent node" is greater than each of its "child nodes"; for
'  example, array(1) is greater than array(2) or array(3), array(3) is
'  greater than array(6) or array(7), and so forth.
'
'  Therefore, once the first FOR...NEXT loop in the Heap Sort is finished,
'  the largest element is in array(1).
'
'  The second FOR...NEXT loop in Heap Sort swaps the element in array(1)
'  with the element in nmbrOfItems, rebuilds the heap (with Percolate Down)
'  for nmbrOfItems - 1, then swaps the element in array(1) with the element
'  in nmbrOfItems - 1, rebuilds the heap for nmbrOfItems - 2, and
'  continues in this way until the array is sorted.
' =========================================================================
[Heap.Sort]
   FOR I = 2 TO nmbrOfItems
      gosub [Percolate.Up]  '(I)
   NEXT I
 
   FOR I = nmbrOfItems TO 2 STEP -1
'      SWAP theArray(1), theArray(I)
        temp1 = theArray(1)
        temp2 = theArray(I)
        theArray(1) = temp2
        theArray(I) = temp1
      gosub [Percolate.Down]  '(I - 1)
   NEXT I
return
 
 
[Percolate.Down]  '(maxlevel)
' ============================ Percolate Down ============================
' The Percolate Down procedure restores the elements of the array from 1
' to MaxLevel to a "heap" (see the diagram with the HeapSort procedure)
' ========================================================================
   maxlevel = I-1
   J = 1
 
' ----------------------------------------------------------------
' Move the value in the array(1) down the heap until it has reached
' its proper node (that is, until it is less than its parent node
' or until it has reached maxlevel, the bottom of the current heap)
' ----------------------------------------------------------------
    flag1 = 0
    while flag1 = 0
      child = 2 * J             ' Get the subscript for the child node.
 
' Reached the bottom of the heap, so exit this procedure
      IF child > maxlevel THEN flag1 = 1 : goto [getout]
 
' ----------------------------------------------------------
' If there are two child nodes, find out which one is bigger
' ----------------------------------------------------------
      IF child + 1 <= maxlevel THEN
         IF theArray(child + 1) > theArray(child) THEN
            child = child + 1
         END IF
      END IF
 
' ---------------------------------------------
' Move the value down if it is still not bigger
' than either one of its children
' ---------------------------------------------
 
      IF theArray(J) < theArray(child) THEN
'         SWAP theArray(J), theArray(child)
            temp1 = theArray(J)
            temp2 = theArray(child)
            theArray(J) = temp2
            theArray(child) = temp1
         J = child
 
' -------------------------------------------
' Otherwise, the array has been restored to a
' heap from 1 to maxlevel, so exit:
' -------------------------------------------
      ELSE
         flag1 = 1 : goto [getout]
      END IF
[getout]
   wend
return
 
[Percolate.Up]  ' (maxlevel)
' ============================== Percolate Up ==============================
'   The Percolate.Up procedure converts the elements from 1 to maxlevel in
'   the array into a "heap" (see the diagram with the HeapSort procedure).
' ==========================================================================
    maxlevel = I
    J = maxlevel
 
' --------------------------------------------------------------------
' Move the value in the array(maxlevel) up the heap until it has
' reached its proper node (that is, until it is greater than either
' of its child nodes, or until it has reached 1, the top of the heap)
' --------------------------------------------------------------------
 
    while J <> 1
      parent = int(J / 2)            ' Get the subscript for the parent node.
 
' --------------------------------------------------------------------
' The value at the current node is still bigger than the value at
' its parent node, so swap these two array elements
' --------------------------------------------------------------------
      IF theArray(J) > theArray(parent) THEN
'         SWAP theArray(parent), theArray(J)
            temp1 = theArray(parent)
            temp2 = theArray(J)
            theArray(parent) = temp2
            theArray(J) = temp1
         J = parent
 
' --------------------------------------------------------------------
' Otherwise, the element has reached its proper place in the heap,
' so exit this procedure
' --------------------------------------------------------------------
      ELSE
         J = 1 : goto [leave]
      END IF
[leave]
    wend
return
 
 
 
' ============================= Insertion Sort =========================
' The Insertion Sort procedure compares the length of each successive
' element in the array with the lengths of all the preceding elements.
' When the procedure finds the appropriate place for the new element, it
' inserts the element in its new place, and moves all the other elements
' down one place.
' ======================================================================
[Insertion.Sort]
 
    FOR a = 2 TO nmbrOfItems
        temp1 = theArray(a)
        temp2 = temp1
 
        b = a
        flag = 1
        while b >= 2 and flag <> 0
'        FOR b = a TO 2 STEP -1
            IF theArray(b - 1) > temp2 THEN
                theArray(b) = theArray(b - 1)
            ELSE
'                EXIT FOR
                flag = 0 : goto [partir]
            END IF
            b = b - 1
[partir]
        wend
'        NEXT b
 
        theArray(b) = temp1
 
    NEXT a
return
 
 
 
 
' ============================== Qsort (No recursion) =====================
' This algorithm is iterative instead of recursive, and fairs much better
' than the recursive version.  The algorithm is from Ethan Winer's 'BASIC
' Techniques and Utilities' (WINER.ZIP).
' The Quick Sort version presented here avoids recursion, and instead uses
' a local array as a form of stack.  This array stores the upper and lower
' bounds showing which section of the array is currently being considered.
' Another refinement added is to avoid making a copy of elements in the
' array.  As the Quicksort progresses, it examines one element selected
' arbitrarily from the middle of the array, and compares it to the elements
' that lie above and below it.  To avoid assigning a temporary copy this
' version simply keeps track of the selected element number.
' =========================================================================
[Qsort.Sort]
    first = 1: last = nmbrOfItems
    zed = int(last/5 + 10)
    REDIM QStack(zed)
flag = 1
stackptr = 0
'DO
while flag <> 0
'  DO
   WHILE first < last
    xVar = int(last/2)+int(first/2)
    temp = theArray(xVar)
    I = first: J = last
'   do
    flag1 = 1
    while I <= J and flag1 <> 0
 
        WHILE theArray(I) < temp
        I = I + 1
        wend
 
        WHILE theArray(J) > temp
        J = J - 1
        wend
 
'      IF I > J THEN EXIT DO
        if I > J then flag1 = 0 : goto [skip]
'      IF I < J THEN SWAP theArray(I), theArray(J)
        if I < J then
        temp1 = theArray(I)
        temp2 = theArray(J)
        theArray(I) = temp2
        theArray(J) = temp1
        end if
 
        I = I + 1
        J = J - 1
[skip]
    wend
'    LOOP WHILE I <= J
 
    IF I < last THEN
       QStack(stackptr) = I
       QStack(stackptr + 1) = last
       stackptr = stackptr + 2
    END IF
 
    last = J
   wend
'  LOOP WHILE first < last
 
'  IF stackptr = 0 THEN EXIT DO
    if stackptr = 0 then flag = 0 : goto [skipit]
  stackptr = stackptr - 2
  first = QStack(stackptr)
  last = QStack(stackptr + 1)
'LOOP
[skipit]
wend
'ERASE QStack
return
 
 
 
 
' =============================== Shell Sort ===============================
' The Shell Sort procedure is similar to the Bubble Sort procedure.
' However, the Shell Sort begins by comparing elements that are far apart
' (separated by the value of the offset variable, which is initially half
' the distance between the first and last element), then comparing elements
' that are closer together. (When offset is one, the last iteration of this
' procedure is merely a bubble sort.)
' =========================================================================
[Shell.Sort]
    center = int(nmbrOfItems / 2)
    WHILE center > 0
    boundary = nmbrOfItems - center
        flag = 1
        while flag <> 0
            flag = 0
                FOR a = 1 TO boundary
                    IF theArray(a) > theArray(a + center) THEN
            '           SWAP theArray(a), theArray(a + center)
                        temp1 = theArray(a)
                        temp2 = theArray(a + center)
                        theArray(a) = temp2
                        theArray(a + center) = temp1
                        flag = a
                    END IF
                NEXT a
            boundary = flag - center
        wend
    center = int(center / 2)
    wend
return
 
 
 
 
' ============================== LB Sort     ===========================
' This uses the sort command included in Liberty Basic
' This is the fastest way to sort arrays using LB!
' ======================================================================
[LB.Sort]
  SORT theArray(, 1, nmbrOfItems
return
 
 
'==================== End of Sort Algorithms ===========================
 
[Create.Array.Items]
    if array.type = 0 then
 
  ' ----------------------------------------
  ' Best case scenario.  The array is already
  ' in the order that we want.
  ' ----------------------------------------
    FOR count = 1 TO nmbrOfItems
        theArray(count) = count
    NEXT count
    end if
 
    if array.type = 1 then
  ' ----------------------------------------
  ' Worst case scenario. The array is in the
  ' exact opposite order of what we want!
  ' ----------------------------------------
    position = 0
    FOR count = nmbrOfItems TO 1 STEP -1
        position = position + 1
        theArray(position) = count
    NEXT count
    end if
 
    if array.type = 2 then
  ' ----------------------------------------
  ' A completely random scenario, like a
  ' well shuffled deck of cards.
  ' ----------------------------------------
 
    FOR count = 1 TO nmbrOfItems
         theArray(count) = count
    NEXT count
 
    FOR count = 1 TO nmbrOfItems
        random.nmbr = INT(RND(1) * nmbrOfItems) + 1
        temp1 = theArray(count)
        temp2 = theArray(random.nmbr)
        theArray(count) = temp2
        theArray(random.nmbr) = temp1
'        SWAP the.array(count), the.array(random.nmbr)
    NEXT count
    end if
 
    if array.type = 3 then
    x = 20
    ' ----------------------------------------
    ' The first (nmbrOfItems - x) are in order.
    ' However the final x items, located all at the
    ' end of the array, need to be sorted.
    ' example: 1 2 3 5 6 7 9 10 11 13 14 15 4 12 8
    ' ----------------------------------------
 
    FOR count = 1 TO nmbrOfItems
       theArray(count) = count
    NEXT count
 
    FOR a = 1 TO x
        random.nmbr = INT(RND(1) * nmbrOfItems) + 1
 
'        SWAP theArray(random.nmbr), theArray(nmbrOfItems)
        temp1 = theArray(random.nmbr)
        temp2 = theArray(nmbrOfItems)
        theArray(random.nmbr) = temp2
        theArray(nmbrOfItems) = temp1
 
        FOR b = random.nmbr TO (nmbrOfItems - 2)
 
'            SWAP theArray(b), theArray(b + 1)
            temp1 = theArray(b)
            temp2 = theArray(b+1)
            theArray(b) = temp2
            theArray(b+1) = temp1
        NEXT b
    NEXT a
    end if
 
return

Comments, requests or corrections: Hit 'REPLY' now! Dean Hodgson -- mailto:Hodgson.Dean@saugov.sa.gov.au Alyce Watson -- mailto:awatson@wctc.net