home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
basic
/
library
/
pb
/
pbwiz10
/
pbwiz.doc
< prev
next >
Wrap
Text File
|
1991-12-03
|
36KB
|
871 lines
The PowerBASIC Wizard's Library
=-----------------------------=
Version 1.0
PBWIZ Copyright (c) 1991 Thomas G. Hanlin III
This is PBWiz, a library of assembly language and BASIC routines for use with
PowerBASIC version 2.0. Full source code is available with registration. The
PBWiz collection is copyrighted and may be distributed only under the
following conditions:
1) No fee of over $10.00 may be charged for distribution. This
restriction applies only to physical copies and is not meant to
prevent distribution by telecommunication services.
2) All PBWiz files must be distributed together in original, unaltered
form. This includes BIBLIO.TXT, CATALOG.TXT, PBWIZ.DOC, PBWIZ.NEW,
REGISTER.TXT, WHERE.BBS, and the two archives, INCLUDES and UNITS.
3) No files may be added to the PBWiz collection. This applies most
specifically to the practice of adding BBS ads to archives, which I
find seriously offensive.
You use this library at your own risk. It has been tested by me on my own
computer, but I will not assume any responsibility for any problems which
PBWiz may cause you. If you do encounter a problem, please let me know
about it, and I will do my best to verify and repair the error.
It is expected that if you find PBWiz useful, you will register your copy.
You may not use PBWiz routines in programs intended for sale unless you have
registered. Registration entitles you to receive the latest version of
PBWiz, complete with full source code in assembly language and BASIC. The
assembly code is designed for the MASM 6.0 assembler and may require minor
modifications if you wish to use it with OPTASM, TASM, or earlier versions of
MASM.
Warning: Use of PBWiz for more than 30 days without registering has been
determined to cause fatal nose warts in penguins! It may also encourage the
author to practice the tuba under your window at night.
Table of Contents page 2
Overview and Legal Info .................................................. 1
Table of Contents ........................................................ 2
Archives ................................................................. 3
Dates and Times .......................................................... 5
Equipment Info ........................................................... 6
Extended Math ............................................................ 9
Graphics ................................................................ 12
Mouse Support ........................................................... 15
Strings ................................................................. 18
Credits ................................................................. 21
Archives page 3
When I started in the microcomputer industry, there were a variety of file
archivers, all (more or less) compatible. They did not provide compression,
which was relegated to another large selection of more-or-less compatible
utilities. Then came SEA's ARC. It was very slow, but it did compression as
well as archiving, and included CRC checks so you could know whether the
files were intact. It swept the BBS scene in short order, becoming the new
standard. A few other archivers competed on about a level footing, providing
only minor variances on the ARC theme. Then SEA decided to sue one of the
more successful competitors, Phil Katz (PKARC). The end result was the ZIP
standard... but in the chaos resulting from the breaking of the ARC standard,
many other archivers came into being: ARJ, LZH, PAK, ZOO, and so forth.
PBWiz helps resolve the confusion by providing a single set of routines which
allow you to view the contents of archives in any of the above-mentioned
formats: ARC, ARJ, LZH, PAK, ZIP, or ZOO. Only archive directories are
provided at this time. Other formats will also be added as they arise. If
you have details on the format of an archive that you'd like me to add,
please send them my way. I'll do what I can to get it into PBWiz.
This unit requires the STRING unit (discussed later) as well. To use it in
your program, you need to include both units:
$INCLUDE "string.inc" ' (only if you need STRING in your programs)
$INCLUDE "archives.inc"
$LINK "stringa.obj"
$LINK "stringb.pbu"
$LINK "archives.pbu"
Viewing archive directories is handled in roughly the same fashion as you
might view a DOS file directory. This makes it possible to treat an archive
and a subdirectory in a similar manner.
When you're looking for the first file in an archive, use the FindFirstA
function. You must specify the archive name and a file name. The archive
name may include a drive and path specification, and does not need to have
the archive extension. If you leave off the extension, FindFirstA will use
the first archive it comes across that matches the rest of the specification.
Note that the archive specification may not contain wildcards. In contrast,
the search file name may not contain drive or path specs, but may contain
wildcards.
CALL FindFirstA (Archive$, Filename$, ErrCode%)
Archives page 4
If there are no files to be found, or if the archive specification was bad,
an error code will be returned. If there was no error, there may well be
more files to be found. You can find each of them with FindNextA:
CALL FindNextA (ErrCode%)
Of course, just finding a matching file doesn't do you much good unless you
can retrieve information about it. You can use any of the following routines
to provide information about a matched file:
Nam$ = GetNameA$
Dat$ = GetDateA$
Tim$ = GetTimeA$
CRC$ = GetCRCA$
StorageMethod$ = GetStoreA$
CALL GetSizeA (OriginalSize&, CurrentSize&)
When you're done viewing an archive, be sure to close it:
CALL CloseA
Let's try an example. Given that you've already written the $INCLUDE and
$LINK lines as specified on the previous page, you could see all of the files
in an archive using a program like this:
CALL FindFirstA (Archive$, "*.*", ErrCode%)
DO UNTIL ErrCode%
PRINT GetNameA$
CALL FindNextA (ErrCode%)
LOOP
CALL FCloseA
This program fragment also assumes that you have set Archive$ to the name of
an archive. It might be convenient to set it to the command line for testing
purposes:
Archive$ = UCASE$(LTRIM$(RTRIM$(COMMAND$)))
Dates and Times page 5
This unit allows you to validate and compare dates. It also provides the day
of the week, given the date. Dates may not be before the year 1900. Date
strings may be in the form "01/01/91" or "01-01-1991" (the delimiter is not
significant and years may be two or four digits; two-digit years will be
assumed to be in the 20th century).
To use the routines in this unit, include the following lines at the top of
your program:
$INCLUDE "timedate.inc"
$LINK "timedate.pbu"
Let's start off with date validation. It's often important to know if a date
entered into your program is a valid date.
IF GoodDate%(DateSt$) THEN PRINT "The date is valid."
It can also be helpful to know on which day of the week a given date falls.
Day$ = WeekDay$(DateSt$)
There are many useful things you can accomplish by turning a date into a
number which represents that date (or vice versa). This allows you to
compare two dates, which is important if you want to sort by date; find out
what the date will be in a given number of days, or what it was some number
of days ago; find the number of days between two dates; display a calendar;
and so forth. This is easy to do with PBWiz:
DateNr& = Date2Num&(DateSt$)
DateSt$ = Num2Date$(DateNr&)
The DateNr& represents the number of days since January 1, 1900. This is
less than 65,535 for dates that go up to around the year 2070 or so, so you
may wish to store the dates in compressed two-byte form if your required
range of dates is not that large:
CrunchDate% = CVI(LEFT$(MKL$(DateNr&), 2))
This can be reversed simply:
DateNr& = CVL(MKI$(CrunchDate%) + STRING$(2, 0))
Note that dates crunched this way are only useful for storage purposes, since
the numbers greater than 32,767 are stored as negative numbers due to the
signed integer format BASIC uses. You must uncompress them before doing any
comparisons or date calculations. Still, at half the size, it can be worth
the hassle to convert back and forth.
Equipment Info page 6
The equipment unit gives you information about the computing environment.
This includes both installed software and hardware. You can use the
equipment information routines by including these lines in your program:
$INCLUDE "equipmen.inc"
$LINK "equipmen.obj"
The first function allows you to determine if an "enhanced" keyboard
(101-key) is installed. It may not be able to figure out what the keyboard
is on some older not-quite-clone PCs, in which case it will take the safe way
out and report that there is no enhanced keyboard. This function returns -1
if there is an enhanced keyboard present, 0 if not.
Enhanced% = KbdType%
Want to know the type of processor (CPU) being used? Can do!
CPU% = Processor%
The results will be reported as a number which can be decoded as follow:
0 NEC V20
1 8088 or 8086
2 80186
3 80286
4 80386 or 80486
If anyone knows how to differentiate between an 80386 and an 80486, please
let me know. I've only seen one test which could do it, and it wasn't
reliable.
Maybe you'd like to check for a CD-ROM drive:
Drives% = CDROM%
This tells you how many logical drives exist, if there is a CD-ROM available.
If not, it will return 0. Note that the CD-ROM installation check conflicts
with the GRAPHICS.COM installation check for DOS 4.0, due to some screw-up at
IBM or Microsoft. I'm not yet sure whether DOS 5.0 is similarly afflicted.
The number of floppy drives installed is retrieved like this:
Drives% = Floppies%
Equipment Info page 7
Now, there may be up to four floppy drives in a system; however, the AT CMOS
data area only directly supports two. This makes it easy to find out what
kind of drives the first two are, but not the second two. Oh well, guess
we'll have to settle for what we can get, right?
CALL FloppyType (Drive1, Drive2)
The results from FloppyType are returned as follows:
0 no drive
1 5 1/4" 360K
2 5 1/4" 1.2M
3 3 1/2" 720K
4 3 1/2" 1.44M
Result codes of 5-7 are available, but not yet defined. One might guess that
the 2.88M drive supported by DOS 5.0 will be drive type 5. Has anybody seen
one of those puppies yet?
New memory types sure have burgeoned over the years... expanded, extended,
and now XMS. There are routines to check all of these:
BaseExt& = AllExtMem& ' amount of extended memory actually installed
NowExt& = GetExtM& ' amount of BIOS extended memory available
CALL GetEMSm (TotalPages%, FreePages%) ' amount of expanded memory
CALL GetXMSm (LargestFree&, TotalFree&) ' amount of XMS memory
When you're dealing with extended memory, whether it be BIOS-type or using
the XMS standard, the results are returned in kilobytes. Multiply 'em by
1024 to convert to bytes. When you're dealing with expanded memory (EMS),
the results are in pages of 16,384 bytes.
I might note, by the way, that Microsoft seems to have intentionally crippled
the XMS standard. It can only support a maximum of 64 megabytes. This may
seem like a lot now, but I can remember when my first PC (a Compaq portable)
was the awe of the neighborhood with 384K RAM! A few years down the road,
the artificial limitations of XMS are going to be a real nuisance.
A few more routines to get the versions of the EMS and XMS drivers, if any:
CALL GetEMSv (MajorV%, MinorV%)
CALL GetXMSv (MajorV%, MinorV%)
These return the major and minor version numbers as two separate integers.
For example, EMS 4.0 would return major version 4, minor version 0.
Equipment Info page 8
It's nice to know a little about the operating environment. With the below
routines, you can find out what the DOS version is; what version of 4DOS, if
any, is in use; and whether Microsoft Windows is running.
CALL GetDOSv (MajorV%, MinorV%)
CALL Get4DOSv (MajorV%, MinorV%)
CALL WinCheck (MajorV%, MinorV%)
These return results as major and minor version numbers, as discussed on the
previous page. The Get4DOSv and WinCheck routines return zeroes if 4DOS and
Windows, respectively, are not available.
There are a couple of curious features of GetDOSv to keep in mind. If the
version is 10 or higher, you're running in OS/2 compatibility mode. DOS
version 10 is actually OS/2 1.0, version 20 is OS/2 2.0, and so on.
Secondly, if you're using DOS 5.0, the version reported may not be 5.0-- DOS
5.0 can be told to reply with a lower version number to allow some older
software (which checks for a specific DOS version) to run properly.
One final routine that should be of some value is the one that allows you to
find out what kind of display is available. It tells you the specific
adapter and whether the display is color or monochrome. There is one case in
which it can be confused, however-- if the adapter is CGA, the display is
assumed to be color, since there is no way for the computer to know any
differently. So, although this routine provides a good idea of what is
available, it would be a good idea to provide an option to tell the program
that a monochrome display is attached. Microsoft normally uses "/B" for this
purpose, so that might be a good standard to stick with.
CALL GetDisplay (Adapter%, Mono%)
IF Mono% THEN
PRINT "Monochrome monitor"
ELSE
PRINT "Color monitor"
END IF
SELECT CASE Adapter%
CASE 1: PRINT "MDA"
CASE 2: PRINT "Hercules"
CASE 3: PRINT "CGA"
CASE 4: PRINT "EGA"
CASE 5: PRINT "MCGA"
CASE 6: PRINT "VGA"
END SELECT
Extended Math page 9
The extended math unit provides an expression evaluator and extensions to
BASIC's math. The math extensions include hyperbolic and inverse trig
functions, a few handy constants, conversions, and more. You can use the new
math routines by including this at the top of your program:
$INCLUDE "extmath.inc"
$LINK "extmath.pbu"
The expression evaluator allows you to find the result of an expression
contained in a string. Normal algebraic precedence is used, e.g. 4+3*5
evaluates to 19. The usual numeric operators (*, /, +, -, ^) are supported
(multiply, divide, add, subtract, and raise to a power). Use of negative
numbers is just fine, of course. Parentheses for overriding the default
order of operations are also supported.
You may use either a double asterisk ("**") or a caret ("^") symbols to
indicate exponentiation.
To evaluate an expression, you pass it to the evaluator as a string. You
will get back either an error code or a single-precision result. Try this
example to see how the expression evaluator works:
$STACK 4096
$INCLUDE "extmath.inc"
$LINK "extmath.pbu"
DO
INPUT "Expression? "; Expr$
IF LEN(Expr$) THEN
CALL Evaluate (Expr$, Result!, ErrCode%)
IF ErrCode% THEN
PRINT "Invalid expression. Error = "; ErrCode%
ELSE
PRINT "Result: "; Result!
END IF
END IF
LOOP WHILE LEN(Expr$)
END
An expression evaluator adds convenience to any program that needs to accept
numbers. Why make someone reach for a calculator when number crunching is
what a computer does best?
NOTE: The expression evaluator uses recursion and will require more than the
default amount of stack space. That's why the $STACK metacommand is used.
Extended Math page 10
The new math functions are pretty much self-explanatory, so I'll just list
them here. A few general notes are given on the next page.
Result% = GCDI%(Nr1%, Nr2%) ' greatest common denominator
Result& = GCDL&(Nr1&, Nr2&) ' greatest common denominator
Result! = ArcCosHS!(Nr!) ' inverse hyperbolic cosine
Result! = ArcSinHS!(Nr!) ' inverse hyperbolic sine
Result! = ArcTanHS!(Nr!) ' inverse hyperbolic tangent
Result! = ArcCosS!(Nr!) ' arc cosine (1 >= Nr >= -1)
Result! = ArcSinS!(Nr!) ' arc sine (1 >= Nr >= -1)
Result! = ErfS!(Nr!) ' error function
Result! = FactS!(Nr%) ' factorial
Result! = CotS!(Nr!) ' cotangent
Result! = CscS!(Nr!) ' cosecant
Result! = SecS!(Nr!) ' secant
Result! = CosHS!(Nr!) ' hyperbolic cosine
Result! = SinHS!(Nr!) ' hyperbolic sine
Result! = TanHS!(Nr!) ' hyperbolic tangent
Result! = Deg2RadS!(Nr!) ' convert degrees to radians
Result! = Rad2DegS!(Nr!) ' convert radians to degrees
Result! = Cent2Fahr!(Nr!) ' convert centigrade to Fahrenheit
Result! = Fahr2Cent!(Nr!) ' convert Fahrenheit to centigrade
Result! = Kg2Pound!(Nr!) ' convert kilograms to pounds
Result! = Pound2Kg!(Nr!) ' convert pounds to kilograms
Pi! = PiS! ' the constant "pi"
e! = eS! ' the constant "e"
Result# = ArcCosHD#(Nr#) ' inverse hyperbolic cosine
Result# = ArcSinHD#(Nr#) ' inverse hyperbolic sine
Result# = ArcTanHD#(Nr#) ' inverse hyperbolic tangent
Result# = ArcCosD#(Nr#) ' arc cosine (1 >= Nr >= -1)
Result# = ArcSinD#(Nr#) ' arc sine (1 >= Nr >= -1)
Result# = ErfD#(Nr#) ' error function
Result# = FactD#(Nr%) ' factorial
Result# = CotD#(Nr#) ' cotangent
Result# = CscD#(Nr#) ' cosecant
Result# = SecD#(Nr#) ' secant
Result# = CosHD#(Nr#) ' hyperbolic cosine
Result# = SinHD#(Nr#) ' hyperbolic sine
Result# = TanHD#(Nr#) ' hyperbolic tangent
Result# = Deg2RadD#(Nr#) ' convert degrees to radians
Result# = Rad2DegD#(Nr#) ' convert radians to degrees
Pi# = PiD# ' the constant "pi"
e# = eD# ' the constant "e"
Extended Math page 11
Like BASIC's trig functions, these trig functions expect the angle to be in
radians. Conversion functions are provided in case you prefer degrees.
Note that there is no ArcTanS! or ArcTanD# function for the simple reason
that BASIC supplies an ATN function.
Constants are expressed to the maximum precision available.
If you are not familiar with variable postfix symbols, here's a summary:
Symbol Meaning Range (approximate)
------ -------- -----------------------------------
% integer +- 32767
& long integer +- 2 * 10^9
! single precision +- 1 * 10^38 (7-digit precision)
# double precision +- 1 * 10^308 (15-digit precision)
See your BASIC manual or PowerBASIC's online help for further details.
Graphics Support page 12
I was rather surprised to find that PowerBASIC lacks support for one of the
standard VGA modes-- SCREEN 13, the 320x200 256-color mode. I immediately
decided to add support for that mode: dots, lines, boxes, polygons, and (of
course) text. While I was at it, I thought I'd add support for a nonstandard
VGA mode: 360x480 in 256 colors. This mode will work on almost any plain VGA
system, although it might not work on some older not-quite-compatible setups.
I'll be adding other modes as I go along, including SuperVGA modes. For now,
there are only two modes:
13 320x200, 256 colors, 40x25 text, standard (any VGA)
N0 360x480, 256 colors, 45x30 text, nonstandard (almost any VGA)
The graphics routines all use the same nomenclature: a G, followed by a mode
number, followed by the specific name. This generic naming convention is
used so that this chapter can refer to all available modes. For example, if
I say "G#Color" and you're using mode 13, you'd actually use "G13Color" in
your program. Ok?
There are two sets of routines for each mode-- the ones written in ASM and
the ones written in BASIC. The file names for these will be suffixed with
"A" for ASM and "B" for BASIC. For instance, to use the SCREEN 13 routines,
you would add the following at the top of your program:
$INCLUDE "g13.inc"
$LINK "g13a.obj"
$LINK "g13b.pbu"
The first thing you will always have to do is to put the screen into the
proper mode. This is done with the G#Mode routine:
CALL G#Mode (Graphics%)
Use 0 to switch to text mode or any other value to switch to graphics mode.
One difference between BASIC and BasWiz is that, instead of each "draw"
command requiring a color parameter as in BASIC, the PBWiz library provides
a separate color command:
CALL G#Color (Foreground%, Background%)
The "foreground" color is used by all graphics routines. The background
color is used by the G#Cls routine. Both foreground and background colors
are used in the G#Write and G#WriteLn routines.
Graphics Support page 13
Here is a list of the corresponding routines, first BASIC, then PBWiz
(replace the "#" with the appropriate mode number):
' get the color of a specified point
colour% = POINT(x%, y%)
colour% = G#GetPel%(x%, y%)
' set the color of a specified point
PSET (x%, y%), colour%
CALL G#Color (colour%, backgnd%): CALL G#Plot (x%, y%)
' draw a line of a specified color
LINE (x1%, y1%) - (x2%, y2%), colour%
CALL G#Color (colour%, backgnd%): CALL G#Line (x1%, y1%, x2%, y2%)
' draw a box frame of a specified color
LINE (x1%, y1%) - (x2%, y2%), colour%, B
CALL G#Color (colour%, backgnd%): CALL G#Box (x1%, y1%, x2%, y2%, 0)
' draw a box of a specified color and fill it in
LINE (x1%, y1%) - (x2%, y2%), colour%, BF
CALL G#Color (colour%, backgnd%): CALL G#Box (x1%, y1%, x2%, y2%, 1)
' clear the screen and home the cursor
CLS
CALL G#Cls
' get the current cursor position
Row% = CSRLIN: Column% = POS(0)
CALL G#GetLocate (Row%, Column%)
' set the current cursor position
LOCATE Row%, Column%
CALL G#Locate (Row%, Column%)
' display a string without a carriage return and linefeed
PRINT St$;
CALL G#Write (St$)
' display a string with a carriage return and linefeed
PRINT St$
CALL G#WriteLn (St$)
Note that PBWiz, unlike BASIC, allows both foreground and background colors
for text in graphics mode.
Graphics Support page 14
If you need to print a number rather than a string, just use the BASIC
function STR$ to convert it. If you don't want a leading space, use this
approach:
St$ = LTRIM$(STR$(Number))
The PBWiz library has other routines which have no BASIC equivalent. One
allows you to get the current colors:
CALL G#GetColor (Foreground%, Background%)
Circles and ellipses can be drawn with the Ellipse routine. This is similar
to the BASIC CIRCLE statement. You specify the center of the ellipse (X,Y),
plus the X and Y radius values:
CALL G#Ellipse (CenterX%, CenterY%, XRadius%, YRadius%)
A circle is an ellipse with a constant radius. So, to draw a circle, just
set both radius values to the same value.
As well as the usual points, lines, and ellipses, PBWiz also allows you to
draw regular polygons: triangles, squares, pentagons, hexagons, and so on.
CALL G#Polygon (X%, Y%, Radius%, Vertices%, Angle!)
The X% and Y% values represent the coordinates of the center of the polygon.
The Radius% is the radius of the polygon (as if you were fitting it into a
circle). Vertices% is the number of angles (also the number of sides) for
the polygon to have. Angle! specifies the rotation of the polygon, and is
specified in radians.
Mouse Support page 15
The mouse unit provides full-featured mouse support. You can see if a mouse
is available and how many buttons it has, get the cursor position (either the
current position or the position at the last press or release of a specified
button), set the cursor position, change the cursor, set the mouse range, get
hardware information about the mouse, and so on.
This unit is called MOUSE, so you access it by including the following lines
at the top of your program:
$INCLUDE "mouse.inc"
$LINK "mouse.obj"
There are two unusual mouse modes to be aware of. One is text mode, which is
mapped to a 640x200 virtual display. So, to convert the results to text
format, you need to divide the cursor position by eight and add one. To
convert from text format, subtract one and multiply by eight.
The second unusual mode is 320x200 CGA mode, which is also mapped to 640x200.
To convert the coordinates to this mode, divide X by two. To convert from
this mode, multiply the X coordinate by two.
All other modes use the actual display coordinates instead of a bizarro
virtual screen. Why the peculiar CGA and text modes? Well, evidently
Microsoft never thought there'd be any video adapters besides MDA and CGA,
and decided to create a single virtual screen size that worked for all modes.
Not a bad idea, I guess, but rather shortsighted. Oh well.
One other nuisance that you may run into is that the mouse cursor can't be
directly turned on or off. A "cursor visibility" count is maintained-- if
the mouse cursor was turned on twice, you'll need to turn it off twice before
it will actually disappear.
Before using the mouse, you must initialize it. The initialization routine
also checks to make sure that a mouse is installed and tells you how many
buttons it has. It's best to initialize the mouse after setting the screen
mode, so the mouse driver understands what mode you're using. Not all mouse
drivers support all screen modes, but you can reasonably expect any current
mouse driver to support MDA, CGA, EGA, and VGA. Hercules graphics mode is
rarely supported, as it must be set through direct hardware access rather
than the standard techniques, so the mouse driver has little way of knowing
that you've changed the mode.
The mouse routines will work equally well with two-button or three-button
rodents. The middle button functions will return 0 with two-button mice.
I won't go into great detail on these routines, because they're pretty much
self-explanatory. The mouse is a fairly easy device to deal with.
Mouse Support page 16
You can initialize the mouse driver like so:
Buttons% = MouseInit%
This returns the number of mouse buttons available. If there is no mouse,
zero will be returned. Initialize the mouse after setting the screen mode.
You can make the mouse cursor visible or invisible. It will function just as
well in either state. See the previous page for some quirks.
CALL MouseShow ' show the cursor
CALL MouseHide ' hide the cursor
There are many ways to get the mouse cursor position. You can get the
current position, the position at which the mouse was located when a
particular button was pressed, or the position when a button was released.
If you choose a past position, you can also find out how many presses or
releases of the button have taken place since you last checked.
X% = MouseWhereX% ' return current X coordinate
Y% = MouseWhereY% ' return current Y coordinate
CALL MouseLClick (Count%, X%, Y%) ' left presses and posn at last press
CALL MouseMClick (Count%, X%, Y%) ' middle presses & posn at last press
CALL MouseRClick (Count%, X%, Y%) ' right presses & posn at last press
CALL MouseLRelease (Count%, X%, Y%) ' left releases and posn at last rel.
CALL MouseMRelease (Count%, X%, Y%) ' middle releases & posn at last rel.
CALL MouseRRelease (Count%, X%, Y%) ' right releases & posn at last rel.
If you'd prefer to find out which buttons are currently pressed, no problem:
Pressed% = MouseLButton% ' whether the left button is pressed
Pressed% = MouseMButton% ' whether the middle button is pressed
Pressed% = MouseRButton% ' whether the right button is pressed
Of course, if you can get the cursor position, you must be able to set it:
CALL MouseLocate (X%, Y%) ' set the mouse cursor position
The mouse cursor range can be restricted to a given area of the screen. This
area is expressed by giving the upper left corner and lower right corner of
the rectangular area to which to restrict the cursor.
CALL MouseWindow (X1%, Y1%, X2%, Y2%)
Mouse Support page 17
There are a variety of cursor shapes available for graphics mode:
0 hourglass (standard "please wait, I'm working" symbol)
1 pointing arrow (default)
2 pointing hand
3 crosshair
4 target (box in a box)
5 grabbing hand
If you have ideas for more, let me know and I'll see what I can do.
The cursor image is set like so:
CALL MouseCursorG (CursorNr%)
Strings page 18
One of the true strengths of BASIC lies in its powerful string handling
capability. I'd be remiss if I didn't provide extensions which improve it
even further. This unit can be accessed by including these lines at the top
of your program:
$INCLUDE "string.inc"
$LINK "stringa.obj"
$LINK "stringb.pbu"
The simplest of the PBWiz string routines may seem somewhat whimsical, but it
has proven useful to me on several occasions in the past. It reverses the
order of characters in a string.
CALL Reverse (St$)
One of the places this has come in useful is in searching a string from the
end-- a reverse INSTR routine:
CALL RInstr (MainSt$, SubSt$, Posn%)
Rather than returning the first occurrence of a substring within a main
string, it returns the last occurrence. Another handy string search allows
you to search for various types of characters, rather than a specific
substring:
CALL TInstr (MainSt$, Types%, Posn%)
The type(s) may be specified using any combination of the following. Just
add them together.
1 alphabetic
2 numeric
4 symbolic
8 control
16 graphics
32 space
Since you can search for any specific types, you can also readily invert the
search to look for any characters that are NOT of a given type or types:
Types% = NOT Types%
This gives you complete control. A typical use for TInstr might be to clean
up user input and make sure that it's valid. It's also good for parsing.
Strings page 19
Another routine that is useful for cleaning up and parsing user input is
called Crunch. It allows you to eliminate adjacent duplicates of a character
or list of characters. One use for this, for instance, would be to eliminate
repeated spaces, converting an input string from "*.* *.BAK /B" to a more
manageable "*.* *.BAK /B".
Result$ = Crunch$(St$, CharList$)
There are a pair of routines that you'll find valuable if you need to check
the validity of a string. These are designed to be compatible with the
Xmodem and Ymodem file transfer protocols, so you can use them for error
checking in telecommunications as well.
Chk% = CheckSum% (St$)
CALL CRC16 (St$, HiCRC%, LoCRC%)
Another pair of string routines provide a simple encryption/decryption system
for text. The method used is not particularly secure but are very fast and
will be adequate for many purposes. As always, it helps to use a long and/or
complex password.
CALL Cipher (St$, Password$)
CALL CipherP (St$, Password$)
Both of these routines will encipher text on the first run-through and
decipher on the second, so you can use the same routine either to encrypt or
decrypt a message. They are different in one respect: the encrypted result
of Cipher may contain control characters, so it can't be used in a plain
sequential-access file. The CipherP routine does not allow use of extended
ASCII characters (CHR$(128) - CHR$(255)), as it sets the high bit on each
character after encrypting it. This causes the results of CipherP to be
printable (and useful in sequential-access files), although they will look
very strange.
The strings are encrypted (or decrypted) in place. This provides a certain
extra measure of security for encryption-- the original plaintext strings are
not left floating around in memory where someone might see them.
One function is as much a file manipulation routine as it is a string
function. It allows you to compare a file name to a file pattern (which may
contain wildcards) to see if they match. Only bare filespecs are supported--
you may not use drive or path specifications in the names.
IF MatchFile%(Pattern$, Filename$) THEN PRINT Filename$
This can be used in creating your own DOS-style utilities: DIR, COPY, and so
forth. Besides the usual "accept file if it matches" approach, it can also
be used to implement the opposite: "exclude file if it matches." This gives
you more flexibility than DOS itself supplies.
Strings page 20
The PowerBASIC compiler provides a very nice function called Extract$. This
allows you to retrieve a substring running from the left side of a main
string to a specified character delimiter. Not bad, but it might be handy to
be able to grab a numbered substring from any part of a main string, and to
be able to use a substring delimiter. For instance, you might load a record
from a database which contains an address, where each line is delimited by a
carriage return and linefeed. Rather than mucking around with Extract$,
which really wasn't designed with that sort of thing in mind, you'd do better
to use the PBWiz function called DelimExtract$:
SubSt$ = DelimExtract$(St$, Delimiter$, Index%)
The index starts at 1 with the first substring. If you choose the index of a
substring which doesn't actually exist, a null string will be returned.
Credits page 21
I'd like to thank Dave Navarro for letting me in on the world of PowerBASIC.
His assistance has been most valuable to me in many respects. Without him,
this library would have taken much longer to get off the ground or would
perhaps not even exist. Dave runs the excellent Bard's Lair BBS-- see my
WHERE.BBS file for more details.
I would also like to thank Spectra, publishers of PowerBASIC, for sending me
the evaluation copy which led to my decision to write this library.