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

Brosco's Liberty Basic Newsletter - Issue #6 - May 98

 
 

In this issue

  1. Writing a replacement for Notepad in LB

OK, I know that Notepad does a fine job, plus there are hundreds of freeware and shareware versions of Notepad available. I choose this program for exactly this reason. Everybody knows what Notepad does! But we will put in a few extra features like wordwrap, spell checker and a graphic toolbar.

When I write a program like this, I first write the skeleton code of how I would like the Window to look. I make sure that I have this exactly the way I want it before coding any of the functions.

Here's the skeleton code:

    open "user" for dll as #user
 
    nomainwin
    WindowWidth = 640                   ' *** Note 1
    WindowHeight = 480
    UpperLeftX = 1                      ' *** Note 2
    UpperLeftY = 1
 
    filename$ = DefaultDir$ + ".txt"
 
    menu #w, "&File", _
        "&New", [new.file], _
        "&Open ...", [open.file], _     ' *** Note 3
 
        "&Save", [save.file], _
        "Save &As ...", [save.as], _
        "E&xit", [close.w]
    menu #w, "&Edit"                    ' *** Note 4
    menu #w, "&Options", _
        "&WordWrap", [word.wrap], _
        "&Spell Check", [spell.check]
 
    menu #w, "&Help", _
        "&About", [about]
 
    graphicBox #w.tb, 0, 0, 632, 24      ' *** Note 5
 
    textEditor #w.txt, 0, 24, 632, 407   ' *** Note 6
 
    open "LB NotePad" for window as #w
 
    print #w, "trapclose [close.w]"
 
    print #w.txt, "!autoresize"         ' *** Note 7
 
    print #w.tb, "fill yellow;flush"
 
    gosub [TitleBar]
 
[loop]
    input var$
    goto [loop]
                                        ' *** Note 8
[new.file]
    notice "Not implemented yet"
    goto [loop]
 
[open.file]
    notice "Not implemented yet"
    goto [loop]
 
[save.file]
    notice "Not Implemented yet"
    goto [loop]
 
[save.as]
    notice "Not implemented yet"
    goto [loop]
 
[word.wrap]
 
    notice "Not implemented yet"
    goto [loop]
 
[spell.check]
    notice "Not implemented yet"
    goto [loop]
 
[about]
    notice "About LB Notepad" + _
        chr$(13) + "LB Notepad Version 1.00" + _
        chr$(13) + "Demonstration by Brosco" + _
        chr$(13) + "           May 98"
    goto [loop]
 
[TitleBar]
    title$ = "LB Notepad: " + filename$ 
    h = hwnd(#w)
    calldll #user, "SetWindowText", _
        h as word, _
        title$ as ptr, _
 
        result as void
    return
 
[close.w]
    close #w
    close #user
    END
 
*** Note 1
    WindowWidth = 640                   ' *** Note 1
    WindowHeight = 480

I have set the Window Width and Height to the size of the smallest display commonly supported by Windows - you can, of course change this.

*** Note 2
    UpperLeftX = 1                      ' *** Note 2
    UpperLeftY = 1

If the user has a bigger screen than 640x480, the UpperLeftX,Y will force the window into the top left corner. If I had used values of 0,0 - the window would be 'free floating'

 
*** Note 3
        "&Open ...", [open.file], _     ' *** Note 3

For the MENU Item 'OPEN' I have also put '...' in the item title. This is a Window's convention. The '...' indicates to the user that if he selects this option he will be presented with a Dialog requesting further information.

 
*** Note 4
    menu #w, "&Edit"                    ' *** Note 4

The TextEditor control automatically generates an "Edit" menu for us. By placing this here, we are simply placing the "Edit" menu item where we want it to appear on the MenuBar.

 
*** Note 5
    graphicBox #w.tb, 0, 0, 632, 24     ' *** Note 5

The GraphicBox is where we will be placing the Graphic toolbar.

 
*** Note 6
    textEditor #w.txt, 0, 24, 632, 407   ' *** Note 6

The TextEditor control is given dimensions to neatly take up all the remaining visible window.

 
*** Note 7
    print #w.txt, "!autoresize"         ' *** Note 7
 

The 'autoresize' command will resize the TextEditor control in case the user resizes the Window.

 
*** Note 8
[new.file]
    notice "Not implemented yet"
    goto [loop]

I now code all of the functions with a 'Not implemented yet' message. This allows me to test the way the program will look to my user. This is what we call a prototype - if I was developing this program for someone else, I could demo it to them to ensure that I had understood their requirements.

Now we can start coding the functions. First the 'New File' function:

 
[new.file]
    gosub [isModified]
    if modified.result = 2 then goto [loop]
 
    print #w.txt, "!cls";
 
    gosub [getLastDir]
    filename$ = lastPath$ + "untitled.txt"
    gosub [TitleBar]
    goto [loop]
 

First we use a subroutine to test if the contents of the TextEditor box have been modified. We will get to this in a moment, but just accept the fact that if the user decides to CANCEL this option, 'modified.result' will have a value of 2 - and so we stop any further processing. We then 'clear' the screen.

The [getLastDir] subroutine is used to split a filename into Path info and the 8.3 name. The default filename$ for the new file is the Current Directory plus "untitled.txt". This is written to the TitleBar with the [TitleBar] subroutine.

 
[isModified]
    modified.result = 0
    print #w.txt, "!modified?";
    input #w.txt, ans$
    if ans$ = "false" then return
 
    h=hwnd(#w)
    wtype = 4131            ' Yes, No, Cancel
    message$ = "The text in " + filename$ + " has changed." + _
                chr$(13) +"Do you wish to save these changes?"
    title$ = "LB NotePad"
    sound = _MB_ICONQUESTION
    calldll #user, "MessageBeep", _
        sound as word, _
        result as void
    calldll #user, "Messagebox", _
        h as word, _
        message$ as ptr, _
        title$ as ptr, _
        wtype as word, _
        modified.result as short
 
' Possible modified.result values are
' 2 = Cancel Button Pushed
' 6 = Yes Button Pushed
' 7 = No Button Pushed
 
    if modified.result = 6 then gosub [save.changes]
    return
 

The [isModified] routine checks to see if the contents of the TextEditor control has been modified. If not - no further processing is performed by this subroutine.

If it has - the user is presented with a MessageBox to determine what action should be taken. If the user requests the changes to be saved (modified.result=6) the subroutine: [save.changes] is called.

[save.changes]
    print #w.txt, "!contents?";
    input #w.txt, txt$
    print #w.txt, "!origin?";
    input #w.txt, row, column
 
    open filename$ for output as #f
    print #f, txt$
    close #f
'                   Reset the Window's Modified flag
    print #w.txt, "!cls";
    print #w.txt, "!contents txt$";
'                   Restore scroll position
    print #w.txt, "!origin ";row;" ";column;
 
    return
 

[save.changes] retrieves the contents of the TextEditor and also the 'scroll' position within the text. The text contents are written to a file, then the contents are 'rePrinted' to the control so that the 'modified' flag is reset. Finally, the scroll position is restored.

[getLastDir]
    lastPath$ = DefaultDir$
    lastFile$ = filename$
    slash = instr(filename$, ", 1)
    while slash <> 0
        lastSlash = slash
        slash = instr(filename$, ", lastSlash + 1)
 
        wend
    if lastSlash = 0 then return
    lastPath$ = left$(filename$, lastSlash)
    lastFile$ = right$(filename$, len(filename$) - lastSlash)
    return
 

[getLastDir] simply splits the full filename into its components of Path and File.

[open.file]
    gosub [isModified]
    if modified.result = 2 then goto [loop]
 
    gosub [getLastDir]
    fileDialog "Open File", lastPath$ + "*.txt", newFilename$
    if newFilename$ = "" then goto [loop]
 
    filename$ = newFilename$
 
    open filename$ for input as #f
    txt$ = input$(#f, lof(#f))
    close #f
 
    print #w.txt, "!cls";
    print #w.txt, "!contents txt$";
    gosub [TitleBar]
    goto [loop]
 

[open.file] first tests if the current contents of the control have been modified. This processing is the same as discussed for [new.file].

Then we split the last filename into path and file. This is done so that the FileDialog will start at the last directory that was used for saving or loading a file.

We then load the file, display it and finally, update the Titlebar of the Window.

[save.file]
    gosub [save.changes]
    goto [loop]
 

[save.file] is very easy - we don't have to perform any checking - we simply save the file.

[save.as]
    fileDialog "Open File", filename$, newFilename$
    if newFilename$ = "" then goto [loop]
 
    filename$ = newFilename$
    gosub [save.changes]
    gosub [TitleBar]
    goto [loop]

[save.as] presents the user with a fileDialog, but uses the existing filename as the default. If the user continues with this option - the file is saved with the new name and the TitleBar is updated.

In the next issue of the newsletter we will add the Graphics Toolbar, WordWrap and the Spellchecker. To test the program as it currently stands - you can cut and paste each of the functions discussed into the skeleton program, or you can download the complete program from:

http://users.orac.net.au/~brosco/newsltr/lbnote.zip

This zip file also conatains a TKN file of the final program - you will get the source next issue. If you have any questions about the program, please post them on my message board at:

    http://users.orac.net.au/~brosco 

Also see - Writing a replacement for Notepad in LB - Part 2


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.