home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
pascal
/
tpmagic.zip
/
TUTORIAL.TXT
< prev
next >
Wrap
Text File
|
1992-01-18
|
88KB
|
1,802 lines
PASCAL MAGIC
(c) Copyright 1992, Jeff Napier & Another Company
Tutorial File
What Pascal Magic can do for you:
This disk consists of three parts, Magic.Tpu, Magic.Doc
and Tutorial.Txt. Magic.Tpu is an add-in for Borland's Turbo
Pascal version 6.0 which will make your job as a programmer
much easier and your results much more polished. Magic.Doc is
a text file which explains how to use all the features of
Magic.Tpu, and Magic.Tut, the file you are now reading, is a
tutorial which starts at a very beginning level and quickly,
but effortlessly moves into advanced programming techniques.
Specifically, Magic.Tpu offers the following:
* Automatic pop-up text boxes, dialog boxes and light-bar
menus.
* Automatic handling of text files.
* Built-in mouse support for the programs you create.
* Support for graphics programs to make them as easy to write
as text-based programs.
* Incorporation of .BGI and .CHR files directly into finished
.EXE files.
* Sound effects for your programs.
* Simplification of many Turbo Pascal operations.
* Complete color control in text and graphics modes.
* Build cursor control into your programs for laptop LCD
screens.
* Full, documented, easy-to-understand source code is
available so you can learn from and customize the Magic
framework to your own applications.
NOTE:
This is a shareware product. You have our specific
permission to copy and distribute this package as long as all
files remain intact and unchanged.
If you benefit from this tutorial, or if you use the
Magic.Tpu unit in your programs you are expected to register.
To register, send $29.95 to:
Another Company
P.O. Box 298
Applegate, OR 97530
USA
If you would like the full source code with your
registration, send $59.90. Please specify disk size.
QUESTIONS:
If you have questions: 503-846-7884, 9-5 Weekdays, West Coast
time. (We are not always available during those hours.)
THE BEST WAY TO USE THIS TUTORIAL:
Copy Magic.Tpu to the directory where you keep your Pascal
*.tpu files, and copy Tutorial.txt to the directory which
contains your *.pas files. Start your Turbo.Exe and load in
this file, (type: TURBO TUTORIAL.TXT). Since the Turbo Pascal
IDE (Integrated Development Environment) allows you to work
on several files at once, you can read this tutorial in one
window and work on practice programs in another window. If
you don't know how yet, I'll show you. If you are an
experienced programmer, you might want to skip through this
tutorial and concentrate only on the areas that are new to
you.
A COUPLE OF OTHER NOTES:
1. It is assumed that you have legally purchased Turbo Pascal
version 6.0 and therefore have the four valuable printed
manuals that come with the program. If not, you are advised
to go spend a little money and get what you need, because
there are places within this tutorial which will refer you to
those books to complete your knowledge.
2. This is not the last word on Turbo Pascal. It doesn't
teach everything about programming - probably not even 10
percent of what you will eventually learn, but between this
tutorial and the Borland manuals, you'll get pretty good at
programming, and fairly quickly. One of the best ways to
learn this is to experiment frequently. Tear the example
programs apart and try to interject your own ideas into them.
See what you can change or improve, then run the programs you
have modified and see what happens. As you well know, you
can't hurt your computer by typing an incorrect line of code.
3. Turbo Pascal is not sensitive to capitalization or white
space. The exact placement of indentations is not important
and every programmer develops a slightly different style. In
this tutorial, I have tried to capitalize letters within
procedure and function names where such capitalization may
make the source code easier to read. This 'convention' occurs
irregularly throughout this tutorial.
4. This is version 1.0 of what I believe is a wonderful
product, but then, I wrote it. Let me know what you think.
I'm pretty sure I caught all the major bugs, but there may be
some minor ones. Most likely the registered and/or subsequent
shareware versions will be even better!
5. To use Magic.tpu, Video.tpu and Fonts.tpu will also need
to be available in the same sub-directory. Also, Graph.tpu,
furnished with Turbo Pascal must be in the sub-directory.
HERE WE GO:
Here is the simplest program you can write:
begin
end.
Let's try it out. Press [F3]. (First finish reading this
paragraph so you know how to get back.) A window pops up
asking for a file name. Call it Prog1 (or any name you
choose) and type the preceding two-line program. Don't
forget the period after end. In Pascal, there is no need to
care about capitalization, Capitals, small case or mixed-case
makes no difference. Press [F2] to save your valuable work
against power failure, etc. While holding the [Ctrl] key,
press [F9] and the program will run. Did you blink? Since,
the program doesn't actually do anything, it runs very
quickly, then returns to Turbo Pascal. To switch back to the
first window, press [Alt] and [1].
This next program is just like the first, it doesn't do
anything, but it is also a legal program. There is one more
line starting with the word Program. Some versions of Pascal
require this line, but with Turbo Pascal, it is optional.
program prog2;
begin
end.
Next, we'll add something to the program so it will actually
have a purpose:
program prog3;
begin
write('Hello, World!');
end.
This program only does one thing, it "write"s the text
between the single quote marks to the screen. Turbo Pascal,
like all computer applications is sensitive to exact spelling
and punctuation. Make sure you have a colon at the end of the
write('Hello, World!'); line, and that all the other pieces
are in their proper places.
Go ahead and run this program. Press [Alt] and [2] to
get back to the other window you opened, and add the lines to
make the first program into this one. Or, if you wish, you
can make a block around this prog3, using the mouse or with
^KB the arrow keys ^KK, (actually there are several ways to
mark a block). Then press [Alt] and [E], then [C]. This puts
a copy of the marked block in the Turbo Pascal clipboard.
Switch to the other window (use [Alt]-[2], or [Alt]- [W],
[L]). Then press [Alt]-[E], then [P] to paste the block into
the second window. Erase the previous program, then compile
and run the new prog3.
It happened very quickly, didn't it? Lets slow it down in
prog4:
program prog4;
begin
write('Hello, World!');
readln;
end.
In prog4, the line readln causes the computer to wait for the
user to press the [Enter] key. Now you can take time to
contemplate your "Hello, World!" line.
You may notice that the screen wasn't cleared of other
junk when prog4 ran. In prog5, let's clear the screen, giving
the "Hello, World!" line more clarity. We'll use the
procedure clrscr, which Turbo Pascal provides to clear the
screen.
program prog5;
begin
clrscr;
write('Hello, World!');
readln;
end.
What happened? If you tried to run this program, you'll have
noticed that it didn't work. Turbo Pascal does not recognize
"clrscr." Did I misspell it? No. I didn't tell you that
clrscr is not part of Turbo Pascal itself. It is in a library
of operations for screen handling called Crt.
Turbo Pascal provides 5 special libraries of routines,
called units. They are Crt, System, Printer, Printer, and
Dos. You can also create your own custom units, or buy
special units from programmers.
These 5 are special because they are grouped together in a
special file called Turbo.Tpl, but usually units are separate
files with the extension of .Tpu. The corrected prog5a shows
how to use a unit:
program prog5a;
uses crt;
begin
clrscr;
write('Hello, World!');
readln;
end.
As the proper prog5 indicates, to use something within a
unit, simply declare the unit's name in the "uses" line,
which you must type just below the "program" line, or as the
first line in the program.
Let's get a bit fancier, take a look at prog6.
program prog6;
uses crt,magic;
begin
sent[1] := 'Hello, World!';
GetAnyKey(5,11);
end.
Prog6 uses the Magic.Tpu unit. Give this program a try. Kind
of prettier, isn't it? Let's talk about prog6 in detail.
You'll notice that instead of writing "Hello, World!"
directly to the screen, we have assigned that string of
characters to a variable called "sent[1]." In the magic unit,
"sent" is an array of sentences called strings. An array is a
group of something, all of which are the same type and size.
The "sent" array is 46 strings, each of which can contain up
to 76 characters. In prog6, we have used only one of them,
the first one, number [1]. When you want to specify a certain
item from an array of items, you put its number in square
brackets. Until sent[1] was told to equal with ":=" (called
"assignment equals") "Hello, World!," it was nothing. Until
prog6 assigned "Hello, World!" to it, sent[1] was equal to
nothing, like this: sent[1] := ''. In fact, all the other
sent[]s in prog6 are still nothing. The magic unit will use
only the sent[]s which contain data.
The next line, "GetAnyKey(5,11)" calls a procedure that
displays the sent[]s which contain data in a bordered,
shadowed box, and waits for the user to press any key or
click a mouse button. The two numbers following GetAnyKey are
coordinates. These refer to the position on the screen where
the box is to pop up. Specifically, they mark the upper left
corner of the pop-up box.
The first number is the horizontal position on the screen.
If it were 1, then the box would be jammed up against the
left hand edge of the screen. 80 is the right-hand edge of a
standard text screen since it is 80 characters wide, but you
can't put the left edge of a text box there if you want to
see it.
The second number is, of course, the vertical coordinate,
with 1 being the top of the screen and 25 being the bottom.
You'll notice, that clrscr is missing. It is not needed
with the magic unit, since the unit automatically clears the
screen when the program starts. But, I left "Crt" in the uses
statement. This is easy programming practice, because if you
don't use anything from the Crt unit, Turbo Pascal does not
increase the size of the compiled program. Yet, if you need
something from the unit, it is at your disposal. You'll see
that many of my programs "use" the Crt unit, even though they
don't end up using anything in the Crt unit.
Prog7 illustrates a close relative to GetAnyKey, GetYN. While
GetAnyKey waits for the user to press almost anything, GetYN
stalls the program until the user presses [Y] or [N], or
clicks the left or right mouse button. Also, you'll note that
one of the coordinates is a negative number. In the
preceding paragraphs, you'll notice I didn't allow for the
possibility of a negative screen coordinate, and technically
there is no such thing. When the magic unit comes across a
negative coordinate, it ignores the number and automatically
figures out where the center of the screen is and pops up its
box there! In other words, if you pass a negative number for
the vertical location, the box will be between the top and
bottom of the screen. If you use a negative number for the
horzontal location, the box will be centered right to left on
the screen.
program prog7;
uses crt, magic;
begin
sent[1] := 'Do you want to quit? (Y/N)';
sent[2] := '';
sent[3] := 'This is just a test, actually, the program';
sent[4] := 'is gonna quit whether you answer Y or N';
GetYN(-5,3);
end.
Let's make a slight improvement in the next program. Prog8
changes a boolean variable, declared from the magic unit. A
boolean is a variable which can have only two values, true or
false. This particular variable is CenterJustify. Normally,
it is false (the "default" condition) but if changed to true,
then the strings in the sent array will be centered within
any pop-up box. Run prog8 and you'll see what I mean.
program prog8;
uses crt, magic;
begin
sent[1] := 'Do you want to quit? (Y/N)';
sent[2] := '';
sent[3] := 'This is just a test, actually, the program';
sent[4] := 'is gonna quit whether you answer Y or N';
CenterJustify := true;
GetYN(-5,3);
end.
Prog8 is a little prettier, n'est ce pas? Prog9 will walk its
talk, it won't end until the user says "yes" by pressing [Y].
It uses a repeat loop, which simply repeats everything
between the words "repeat" and "until" until the condition
listed after "until" is true. GetAnyKey and GetYN wait for
the user to press a key. The difference is that GetYN is
specific, it waits for the key pressed to be 'Y' or 'N'.
Both of these procedures assign the character of the key
pressed to a global character variable called U. So, when
GetAnyKey or GetYN are done, u becomes what the user pressed.
In the special case of GetYN, if the user pressed a small
case 'y' or 'n', it is automatically converted into a capital
letter. Furthermore, GetYN makes u := 'Y' if the left mouse
button was clicked, and u := 'N' if the right mouse button
was clicked.
program prog9;
uses crt, magic;
begin
repeat
sent[1] := 'Do you want to quit? (Y/N)';
GetYN(-5,3);
until u = 'Y';
end.
Prog10 introduces a new magic procedure called Dialog. With
this, you can pose a question, and have the user type an
answer. Try it.
program prog10;
uses crt, magic;
begin
sent[1] := 'How would you answer this question?';
Dialog(-1,-1);
sent[1] := 'User typed:';
sent[2] := Answer;
GetAnyKey(-1,-1);
end.
Prog10 allows the user to type the answer, then if your
program were more sophisticated that prog10, you could
process that answer. The answer is contained in the global
string variable Answer which GetAnyKey uses to display the
result. Notice that "User typed:" is in single quotes,
telling GetAnyKey to type literally that, but Answer is not
in quotes, telling it to print the string represented by the
variable answer, and not type "Answer".
In prog10, you could make the whole operation more
evident if you used some color control. Try prog11.
program prog11;
uses crt, magic;
begin
sent[1] := 'How would you answer this question?';
Dialog(-1,-1);
BoxBack := White;
Border := LightBlue;
BoxText := Green;
Shadow := Magenta;
sent[1] := 'User typed:';
sent[2] := Answer;
GetAnyKey(-1,-1);
end.
Prog11 is ugly, but you can see how to change the colors
within the text box. The colors seem to be used here as some
sort of variables and they are. They are pre-defined
constants from the Turbo Pascal Crt unit. The Box colors,
Border, and Shadow are global variables from the magic unit.
The Colors could just as easily have been represented by
numbers, as in the following example:
program prog11a;
uses crt, magic;
begin
sent[1] := 'How would you answer this question?';
Dialog(-1,-1);
BoxBack := 15;
Border := 9;
BoxText := 2;
Shadow := 5;
sent[1] := 'User typed:';
sent[2] := Answer;
GetAnyKey(-1,-1);
end.
Lets find out what all the colors are: Here is a slightly
more complex program than any we have made so far:
program prog12;
uses crt, magic;
begin
border := white;
BoxBack := black;
CenterJustify := true;
sent[1] := 'Type a number from 0 to 15.';
dialog(-1,-1);
repeat
BoxText := number;
if (BoxText < 1) or (BoxText > 15) then boxtext := 15;
sent[1] := 'The current color is #' + answer;
sent[2] := 'Type a number from 0 to 15';
sent[3] := 'or type 16 to exit';
dialog(-1,-1);
until answer = '16';
end.
In detail, prog12 does this: First, the Border color and the
BoxBack color are changed. CenterJustify will center text in
the pop up boxes.
Then a one-line dialog box appears. As soon as the user
answers the question in this dialog box, a repeat loop,
starts. The repeat loop changes the BoxText color to the
"number" corresponding to what the user typed in the dialog
box. "Number" is a function from the magic unit. It takes
the Answer string (as returned by Dialog) and converts it
from a string into an integer variable. That way it can be
assigned to BoxText and BoxText will be able to handle it.
Since the only 'seeable' colors range from 1 to 15 (#0 is
black), the line starting with 'if' repairs the boxtext
number if it not suitable.
BoxText is a byte variable (only values it can handle are
0 through 255), but Answer is a string. Number fixes that by
becoming a integer compatible with BoxText.
Within the repeat loop a new box pops up containing three
lines of text written in the color corresponding to the
number the user typed in the dialog box.
This all repeats until the user types "16".
Let's make that program a little cleaner:
program prog13;
uses crt, magic;
begin
border := white;
BoxBack := black;
CenterJustify := true;
sent[1] := 'Type a number from 0 to 15.';
dialog(-1,-1);
repeat
BoxText := number;
if (BoxText < 1) or (BoxText > 15) then boxtext := 15;
sent[1] := 'The current color is #' + answer;
sent[2] := 'Type a number from 0 to 15';
sent[3] := 'or type 16 to exit';
dialog(-1,-1);
until (answer = '16') or (u = #27);
end.
There is only one small change. Can you spot it? The
second-from last line now allows the user out of the loop by
typing "16" or by pressing the [Esc] key which is Ascii #27.
This is because Dialog uses the global character u to build
the Answer string. U always contains the character value of
the last character entered, which in the case of pressing the
[Esc] key would be #27.
Prog14 will be our first program that does something useful
in the real world. It will produce the square of an integer.
I know that's not much. You paid around $1000 for your
computer, but your $5 calculator can do squares, and it can
even do it with floating point numbers, which this example
can't. The importang thing is, once you learn this, you can
build on this program.
program prog14;
uses crt, magic;
var
thing : word;
begin
repeat
sent[1] := 'Type a number to be squared';
sent[2] := 'or press [Esc] to end program';
dialog(3,3);
if u <> #27 then
begin
thing := number * number;
str(thing,answer);
sent[1] := 'The square is ' + answer;
GetAnyKey(40,15);
XClear;
end;
until (u = #27);
end.
Prog14 introduces two new concepts. First we have a line that
contains "var." This line is found before the first begin in
any procedure, or before the body of a program but after the
uses clause. The lines that follow "var" are "user-declared"
variables. If they are declared before the main body of the
program they are "global," usable throughout the program. If
they are declared within a function or procedure, they are
usable only by that function or procedure.
In this case, we have declared, "thing : word." on the
left of the colon (notice no = sign) is any combination of
letters and numbers and "_" allowed by Turbo Pascal (see
manual). On the right of the colon is the type of variable it
is. A word is a integer number with a positive value from 0
to approximately 64000. Other common types appointed by Turbo
Pascal are integer (approx value -32000 to +32000), real
(floating point number), byte (0 to 255), char (Any ASCII
character), string (an array, or group of characters),
pointer (indicating the starting location of a variable of
any type stored in memory) and an array (a group of any of
these items). Additionally, you can make up your own types,
composed of one or more of these basic types in a mixture.
For more information about all this, watch the Var section of
the programs that follow in this tutorial, and see your
Borland manuals.
Furthermore, we introduced "str" which is a Borland
procedure to convert a numeric variable into a string
representing that number in text.
This program is easy to crash. All you have to do is
pick a number that's square is more than the range of a
"word" type variable. (64000)
There are a couple more new things here, but if you are
sharp, you probably already picked them out. One is the "*"
which is computer programming talk for "multiply". The other
is the "<>" which means "not equal to."
This program will be quite confusing, it would have been
confusing to me for the first year or so that I was using
Turbo Pascal, so you might want to study it carefully. Once
you understand what everything does, try making changes and
see if the do what you would expect. Once you get it, you're
well on your way to writing custom programs.
Most of prog15 is similar to the last, but this one is
for converting inches to millimeters. Try it and you'll see a
surprise.
program prog15;
uses crt, magic;
var
millimeters : real;
begin
repeat
sent[1] := 'Enter a number of inches';
sent[2] := 'or press [Esc] when done';
dialog(2,2);
if u <> #27 then
begin
millimeters := number * 25.4;
str(millimeters,answer);
sent[1] := 'That would be ' + answer + ' millimeters';
GetAnyKey(30,20);
xclear;
end;
until u = #27;
end.
The surprise is in the way Turbo Pascal handles real
variables when converted to string variables. Unless you add
specific formatting commands, you'll get scientific notation.
So, prog15a has a small change in the str procedure
parameters, specifically, "millimeters" is followed with
":1:0." See your Borland books for more information, but
basically, if the first integer is anything less than 8, then
up to 8 digits will be displayed. The second integer
determines how many digits after the decimal point will be
considered in the string. For monetary notations, your second
integer would typically be 2, for cents.
program prog15a;
uses crt, magic;
var
millimeters : real;
begin
repeat
sent[1] := 'Enter a number of inches';
sent[2] := 'or press [Esc] when done';
dialog(2,2);
if u <> #27 then
begin
millimeters := number * 25.4;
str(millimeters:1:0,answer);
sent[1] := 'That would be ' + answer
+ ' millimeters';
GetAnyKey(30,20);
xclear;
end;
until u = #27;
end.
Program 16 converts Dupers from the country Xanopieland
to United States Dollars.
program prog16;
uses crt, magic;
var
dollars : real;
begin
centerjustify := true;
sent[1] := 'How many Dupers?';
dialog(-1,-1);
dollars := number * 0.7143; {current duper
conversion rate}
str(dollars:1:2,answer);
sent[3] := '$' + answer;
sent[2] := '';
sent[1] := 'You own this much Xanopieland money:';
(* notice that sent[3] is assigned above *)
sent[4] := '';
sent[5] := 'Press any key to end program...';
GetAnyKey(-1,-1);
end.
Prog16 introduces comments. There are two ways you can put
comments into your source code that won't affect the way your
program is compiled. One is to place it between curly
brackets {} and the other way is to use (* and *) as the
borders of comments. Comments can extend over several lines
as long as the beginning is marked with { or (* and the end
is marked with the matching } or *). You can even nest one
type within another:
{comment (* within a comment *)}
No matter how many comments you put in your source code,
there will be no change in the compiled program's size or run
time speed.
Comments can be very important for you or for others that
have to figure out your programs a long time after you have
created them.
Prog16 also illustrates that Turbo Pascal is not at all
fussy about white space. The only place white space matters
is within strings. The same program can be written this way:
program prog16a; uses crt, magic; var dollars : real; begin
centerjustify := true; sent[1] := 'How many Dupers?';
dialog(-1,1); dollars := number * 0.7143; {current duper}
{conversion rate} str(dollars:1:2,answer); sent[3] := '$' +
answer; sent[2] := ''; sent[1] :=
'You own this much Xanopieland money:'; (* notice that
sent[3] is assigned above *) sent[4] := ''; sent[5] :=
'Press any key to end program...'; GetAnyKey(-1,1); end.
Program 16a is just as easy for the compiler to read, but
much harder for humans to read!
Let's make one more improvement in prog16. In prog16b, we'll
straighten out the way Dupers can be entered. The standard
dialog box is as wide as the widest sent[] and therefore the
answer can be that long. What if you want to limit the user
to a 4-digit answer, for instance? The following technique
works well for use with filling in database forms:
program prog16b;
uses crt, magic;
var
dollars : real;
begin
centerjustify := true;
sent[1] := 'How many Dupers?';
sent[2] := ' '; {must be at least one char}
pop(-1,-1);
textcolor(BoxText);
textbackground(BoxBack);
answer := XReadLn(38,12,4);
restore;
dollars := number * 0.7143;
str(dollars:1:2,answer);
sent[3] := '$' + answer;
sent[2] := '';
sent[1] := 'You own this much Xanopieland money:';
sent[4] := '';
sent[5] := 'Press any key to end program...';
GetAnyKey(-1,-1);
end.
Can you spot the differences? This program does not depend on
Dialog. Instead, we pop up a box with "pop," which is a
simple procedure that remembers what's on the screen, then
puts a box on the screen. Since pop will use only as many
sent[]s as have text, sent[2] is ' ', or one blank, so it
will be included in pop's box. This will give the user a
line within the box on which to type the answer.
Then the current text color and background color are set
to the same as the colors within the box, so that XReadLn,
will work in the proper colors. XReadln is like the Turbo
Pascal ReadLn procedure but with three differences. XReadLn
accepts mouse control (left mouse button is like pressing
[Enter] and right button is like [Esc]), XReadLn requires two
integers to designate the screen coordinates at which it will
echo the text typed by the user, and a third integer which
limits how long a string the user is allowed to type.
Dialog knows when the user is done, and restores the
screen and disappears, but pop doesn't know what is wanted,
so stays on the screen until a specific call to Restore,
which wipes it out and replaces the previous screen image.
Prog17 shows many new techniques. It is the Universal Money
Converter. For simplicity, only the first menu entry has a
procedure installed. Run this program to see what it does,
then study the source code to see how it does it. From a
practical point of view, you can see that with modifications,
this could be used for real money from real countries. For
that matter, the same program could be modified for many
purposes. How about a universal metric converter that
converts lengths, weights, temperatures, etc?
(NOTE: When I first roughed out this tutorial, I got to
thinking about the previous sentence, and an idea was born.
It is now complete and being distributed as shareware.
Perhaps you've seen it, THE UNIVERSAL CONVERTER. This new
program performs over 600 useful calculations and it makes
extensive use of Pascal Magic!)
program prog17;
uses crt, magic;
var
dollars : real;
procedure xano;
begin
sent[1] := 'How many Xanopieland Dupers?';
sent[2] := ' '; {must be at least one char}
pop(-1,-1);
textcolor(BoxText);
textbackground(BoxBack);
answer := XReadLn(38,12,4);
restore;
dollars := number * 0.7143;
str(dollars:1:2,answer);
sent[3] := '$' + answer;
sent[2] := '';
sent[1] := 'You own this much Xanopieland money:';
sent[4] := '';
sent[5] := 'Press any key to continue...';
GetAnyKey(-1,-1);
end;
begin {main}
centerjustify := true;
sent[1] := 'Universal Money Converter';
pop(25,2);
mc := 1;
repeat
sent[1] := 'Xanopieland';
sent[2] := 'Braze Island';
sent[3] := 'Nomania';
sent[4] := 'Grazille';
sent[5] := 'Exit to Dos';
menu(-1,-1);
if u = #13 then
begin
if mc = 1 then xano;
(* if mc = 2 then braze;
if mc = 3 then nomania;
if mc = 4 then Grazille; *)
end;
until (u = #13) and (mc = 5);
CleanUp;
end.
The most noticeable change is the use of a sub-routine,
called a "procedure." And Pascal seems kind of backward at
first - the main program is the bottom-most thing, and the
procedure(s) are at the top. In Pascal, it must be this way.
Any procedure or function that is called from another
procedure or function, or from the main program, must be
above it in the source code. Actually, there are ways around
this (see Forward declaration in your Borland manuals), but
for now, we'll keep it simple.
The procedure Xano is called only when the user selects
the first menu entry.
Now, let's look at the main program to see exactly what it
does. You know CenterJustify. It makes all the sent[]s
centered within the pop-up boxes.
Then a box pops near the top of the screen with the text,
"Universal Money Converter." Then we have a funny line, "mc
:= 1." I'll explain that one in a minute.
Within the repeat loop are 5 sent[]s and a call to the
magic procedure "menu". Menu is like the other pop-up boxes
you are familiar with, but it is a light-bar menu. It allows
the user to highlight any one of the sent[]s by moving the
mouse or using the arrow keys. When the user presses [Enter],
[Esc] or a mouse button, the menu box disappears. A global
integer variable, "mc" is assigned the number of the sent[]
that was highlighted when the menu box disappears. So if the
user has highlighted Nomania (sent[3]), then pressed [Enter],
then mc will equal 3.
And after the menu box disappears, the next line of code
will be executed, which happens to be "if mc = 1 then xano."
Well, if the user selected Nomania, then mc is not 1 and the
procedure xano will not be run. mc = 3, but the line, "if mc
= 3 then nomania" is commented out, so nothing will occur.
However, if the user had selected Xanopieland, then mc would
be 1 and the procedure xano would be executed. And you know
what that does, it is the same as prog16. If the user should
select sent[5] then mc will be 5 and the until clause will
then allow the program to end. The last procedure in the
program is CleanUp which restores everything to the way it
was before the program started. It resets the screen colors,
clears the screen and the program terminates gracefully.
CleanUp should be used at the end of every program. It has a
very specific purpose here. Remember the one-line pop at the
beginning of the program? It held a picture of what's under
that box in memory and is still holding it until calling
CleanUp. We never "Restore"d the first "pop".
Now about that line "mc := 1." Without this line, when
menu is first started, it doesn't know which sent[] to
highlight. You must tell it. If you forget to assign a value
to mc before calling a menu, then a random item will be
highlighted. Notice that "mc := 1" is before the repeat loop.
This is because, once the repeat loop starts, the user may be
most comfortable seeing the menu pop-up with the highlight
where it was last located rather than on the top item every
time.
Prog18 is the same as the last one, except we use DoubleMenu
instead of Menu. Everything is the same, but the menu is
shorter and wider, allowing for situations where you may have
lots of menu choices. You can use up to 36 sent[]s with
DoubleMenu.
program prog18;
uses crt, magic;
var
dollars : real;
procedure xano;
begin
sent[1] := 'How many Xanopieland Dupers?';
sent[2] := ' '; {must be at least one char}
pop(-1,-1);
textcolor(BoxText);
textbackground(BoxBack);
answer := XReadLn(38,12,4);
restore;
dollars := number * 0.7143;
str(dollars:1:2,answer);
sent[3] := '$' + answer;
sent[2] := '';
sent[1] := 'You own this much Xanopieland money:';
sent[4] := '';
sent[5] := 'Press any key to continue...';
GetAnyKey(-1,-1);
end;
begin {main}
centerjustify := true;
sent[1] := 'Universal Money Converter';
pop(25,2);
mc := 1;
repeat
sent[1] := 'Xanopieland';
sent[2] := 'Braze Island';
sent[3] := 'Nomania';
sent[4] := 'Grazille';
sent[5] := 'Exit to Dos';
doublemenu(-1,-1);
if u = #13 then case mc of
1 : xano;
(* 2 : brace;
3 : nomania;
4 : grazille; *)
end;
until (u = #13) and (mc = 5);
end.
In prog18 we have also cleaned up the multiple if statements
by using a "case" statement. But, there are still no
procedures written for 3 of the 5 menu choices, so these are
commented out.
Prog19 adds another case statement allowing the user to
press a key corresponding to the first letter of a menu item
and then that procedure will be run directly.
program prog19;
uses crt, magic;
var
dollars : real;
procedure xano;
begin
sent[1] := 'How many Xanopieland Dupers?';
sent[2] := ' '; {must be at least one char}
pop(-1,-1);
textcolor(BoxText);
textbackground(BoxBack);
answer := XReadLn(38,12,4);
restore;
dollars := number * 0.7143;
str(dollars:1:2,answer);
sent[3] := '$' + answer;
sent[2] := '';
sent[1] := 'You own this much Xanopieland money:';
sent[4] := '';
sent[5] := 'Press any key to continue...';
GetAnyKey(-1,-1);
end;
begin {main}
centerjustify := true;
sent[1] := 'Universal Money Converter';
pop(25,2);
mc := 1;
repeat
sent[1] := 'Xanopieland';
sent[2] := 'Braze Island';
sent[3] := 'Nomania';
sent[4] := 'Grazille';
sent[5] := 'Exit to Dos';
doublemenu(-1,-1);
if (u = #13) then case mc of
1 : xano;
(* 2 : brace;
3 : nomania;
4 : grazille; *)
end
else
case upcase(u) of
'X' : xano;
(* 'B' : braze;
'N' : nomania;
'G' : grazille; *)
'E' : begin
mc := 5;
u := #13;
end;
end;
until (u = #13) and (mc = 5);
end.
There are opportunities for bugs here. You want to make sure
u = #13 (the [Enter] key) before allowing the first "case" to
execute, because otherwise, a procedure may run twice in a
row if the user presses a character key, first when mc =
whatever, then then when u = 'whatever'. Also make sure to
put the second case characters in single quote marks. And
last, notice the "upcase(u)." Without this the user would
have to press the shift key to get the desired result. Upcase
converts u into a capital letter.
Prog20 is going to be a big, but very special program because
it will be something you'll use everyday. Run it and see
what it does, then study the source code to understand it.
program prog20;
uses crt, magic;
procedure extkey; (* 1 *)
var
tempstr : string[3];
ekey : boolean;
begin
XClear; (* 8 *)
sent[1] := 'Press any key to see it''s extended code';
sent[2] := 'Press ''Q'' when done.';
pop(18,3);
sent[1] := ' '; (* 9 *)
sent[2] := '';
repeat
ekey := false;
GetAnyKey(-1,-1);
if u = #0 then
begin
sent[1] := '#0 + ';
u := readkey;
ekey := true;
end;
case u of
#13 : answer := ' '; (* 10 *)
#8 : answer := ' ';
#10 : answer := ' ';
#7 : answer := ' ';
else answer := u;
end; {case}
str(ord(u),tempstr);
sent[1] := sent[1] + answer + ' (#' + tempstr + ')';
until (upcase(u) = 'Q') and (ekey = false);
XClear;
end; {procedure ExtKey}
procedure asciichart;
var
x,y : byte; (* 3 *)
temp : integer;
begin
textcolor(white); textbackground(black);
x := 1;
y := 1;
clrscr;
for temp := 0 to 255 do
begin
u := chr(temp); (* 4 *)
gotoxy(x,y); (* 5 *)
write(' ');
if temp < 10 then write(' ');
if temp < 100 then write(' ');
if (temp <> 7) and (temp <> 8) and (temp <> 10)
and (temp <> 13) and (temp <> 27) (* 11 *)
then write(temp,'=',u,' ')
else write(temp,'=');
inc(y); (* 6 *)
if y > 25 then
begin
y := 1;
x := x + 7;
end;
end; {end of for 0 to 255 loop}
WaitForUser;
xclear; (* 7 *)
end; {procedure Asciichart}
begin {main}
centerjustify := true;
mc := 1;
repeat
BoxBack := red;
sent[1] := 'Programmer''s Tools';
sent[2] := 'Copyright 1991, Freeware by Another Company';
pop(18,2);
BoxBack := green;
sent[1] := 'ASCII Chart';
sent[2] := 'Extended Keys';
sent[3] := 'Quit';
menu(-1,-1);
if u = #13 then
case mc of
1 : AsciiChart; (* 2 *)
2 : ExtKey;
end;
until (u = #13) and (mc = 3);
CleanUp;
end.
I've tagged this file with note numbers surrounded by (* and
*). Note 1) Don't look here to start reading a program, this
is merely a sub-routine. Go way down to the main program
block, where it says "{main}" to get a feel for what's going
on.
Looking at the overall program you'll see that there is
the main program block and two procedures, which may be
called from the case statement in the main block.
Note 2) If the user selects the first menu item, "ASCII
Chart" then MC will be 1, and the AsciiChart procedure will
be called. Now let's go up and take a look at that procedure.
Note 3) Here are some variables being declared within this
procedure. They are not available to the main program. X and
y are bytes, they can hold a value of from 0 to 255. Temp is
an integer, with a possible value of from approx -32000 to
+32000. If you look down a few lines, you'll see that x and y
are specifically set to 1. In Pascal, as in most programming
languages, the act of declaring a variable doesn't set it to
0 or any other value. Unless specifically set to something,
it's value will be random. In this procedure, the values of
x and y need to start with 1.
Note 4) We are in a "for" loop which as it is set up in this
program will start with temp defined as 0 and the contents
of the loop (between the "begin" and "end" will repeat 255
times, and each time, the value of temp will be increased by
1.
The first thing that happens in this loop is that u, a
global char variable, is set to the ASCII character
represented by the value of temp. This is done by the Turbo
Pascal function "chr."
Note 5) The next thing that happens in this loop that
repeats 255 times is "gotoxy." Gotoxy moves the cursor to the
coordinates in the parentheses. Then, with close study,
you'll figure out what is written to the screen by the
program in the several following lines of code.
Following this, are a few lines to make columns on a
single screen rather than simply scrolling down 255 lines.
I'll let you figure out how that's accomplished by studying
the code.
Note 6) This note calls your attention to the line,
"inc(y)." Inc adds 1 to an integer value. It is like saying,
"y := y + 1. By doing this, when the next iteration of the
loop occurs, and the gotoxy is encountered, the next
character will be written one line below the last, because
of y being one number higher.
Note 7) After the 255 executions of the for loop, the
program calls the magic procedure WaitForUser, which waits
for the user to press a key or click a mouse button. The
next line is XClear, which clears the screen in preparation
to return to the main program.
Note 8) is way up high in the code, in the top procedure.
This procedure, ExtKey is the one which pops up the ASCII and
Extended Key information in a little window for each key that
is pressed. First thing this procedure does is clear the
screen again. Then it makes a box with a couple of sent[]s
explaining, "Press any key to see it''s extended code," and
"Press ''Q'' when done." Look at all those single quote
marks! There are two of them after in it''s, and two single
quote marks in a row on either side of the ''Q''. No, they're
not typographical errors. This is how Turbo Pascal
differentiates between the beginning and end of a literal
string, and a string containing a ' in it. When there are two
''s, Pascal prints it on the screen as a single '. When there
is just one ' in the source code, Turbo Pascal thinks you are
trying to mark the beginning or end of a literal string.
Note 9) The first time the ExtKey procedure runs, as you may
recall, a little box containing nothing appears, until you
press a key to fill it. Sent[1] has to be something, or the
program will think there are no sent[]s at all, so sent[1] is
a one-character string containing a space. sent[2] must be
specifically rewritten as a string containing nothing,
because the preceding pop had used two sent[]s, and the
information in sent[]s is not cleared after a call to pop,
as it would be in pop-up boxes that automatically disappear
after they are done.
Notes 10 and 11) Some characters, when written to the
"screen" do funny things. #8 is the backspace character
which will actually back up the cursor and cause something
else to be overwritten. #13 is a carriage return and #10 is
a line feed, which would screw up a chart or anything you try
to display normally. #7 goes "beep!" So such characters must
specifically eliminated if you try to write them literally
to the screen.
This is an excellent program to study in detail. A really
good way to understand it is to modify it. Experiment. Make
changes, and see if when you run the program, your changes
act as you had expected. See if you can improve on this
program or add new features. If you can understand all of
this, you are well on your way to being a GOOD programmer.
Prog21 is derived from prog20. It is a demonstration of
writing to a disk file. The object of this program is to put
a column of ASCII equivalents in a text file, so you can use
it with your word processor, etc. Run prog21, then go look at
the file called ASCII.TXT with the Turbo Pascal IDE or your
favorite word processor. Be aware, prog21 is very slow,
requiring several seconds to run its course.
program prog21;
uses crt,magic;
var
temp : integer;
tempstr : string;
begin
NameOutFile('Ascii.txt');
for temp := 0 to 255 do
begin
str(temp,tempstr);
tempstr := tempstr + ' = ' + chr(temp);
FileWriteLn(tempstr);
end;
end.
There are two special items in the magic unit, "InFile" and
"OutFile." InFile is used to get text in from the disk and
use it within your program. OutFile is used to put
information out to the disk. Essentially, these are pathways
to disk files. You must give them names that will be used in
the disk directory. As usual with disk files, these names
must be DOS-legal, with up to 8 characters, optionally
followed by a period and up to a three-character extension.
Drive designator and sub-directory designations can precede
file names.
So we would use OutFile to convey information to the disk.
The first operation in prog21 is to associate a disk filename
with outfile, using "NameOutFile."
Then a for loop creates a string, "tempstr" containing
each ASCII number and the character represented by that
number. The line in this loop, "FileWriteLn" writes this
tempstr to the disk.
There is another procedure called FileWrite which writes
strings to disk, but does not put each one on a separate
line. This follows the convention of Turbo Pascal's Write
and Writeln.
If you have named a file that does not yet exist on disk,
it will be created automatically with the first call to
FileWriteLn or FileWrite. If the file already exists, the
string passed with FileWriteLn or FileWrite will be appended
to the end of the file.
You'll notice two things about FileWriteLn, one iis that
it is very slow. FileWriteLn is nice, because it
automatically does several things that you would normally
have to write separately into your program, but that's why it
is slow.
The other thing you'll see when you look at the finished
file. Some of the characters do funny things when written to
a file, causing a sort of misalignment. These are things like
line feed (#10) and Bell (#7), which beeps if read by the DOS
type command.
Prog22 is a variation of the previous program that handles
writing to file more manually, resulting in a much faster
program, and eliminates the funny characters.
program prog22;
uses crt,magic;
var
temp : integer;
tempstr : string;
outfile : text;
begin
assign(outfile,'Ascii.txt');
rewrite(outfile);
for temp := 0 to 255 do
begin
str(temp,tempstr);
tempstr := tempstr + ' = ';
if (temp <> 7) and (temp <> 10) and (temp <> 13)
and (temp <> 26) then tempstr := tempstr + chr(temp);
writeln(outfile,tempstr);
end;
close(outfile);
end.
Cleaner and faster, eh? I won't go into the specifics of
file handling here, it is all well documented in your Turbo
Pascal manuals. There are three types of files you can work
with, with text files being the most often used by new
programmers, and there are many things you can do with files
besides simple reading and writing of strings. For that
matter, there's a whole bunch of things you can do with
strings, but all that is well beyond the scope of this humble
tutorial.
The compliment of FileWriteLn is FileReadLn. Prog23 shows it
in operation, using the previously created Ascii.txt.
program prog23;
uses crt,magic;
var
tempstr : string;
begin
clrscr;
NameInFile('Ascii.txt');
repeat
tempstr := FileReadLn;
writeln(tempstr);
until problem;
WaitForUser;
CleanUp;
end.
Not very elegant, since the stuff scrolls right off the
screen, but you get the general idea. Notice the 4th line
from the bottom: "until problem". This introduces something
very excellent about the magic unit. It is always watching
for mistakes. If you ask most of the functions and procedures
in the magic unit to do something that can't be done, they do
not crash the program. Instead, they handle the problem as
gracefully as possible and set a global boolean variable to
true. If there is no problem with your use of the function or
routine problem is false.
In this case, if you try to read beyond the end of the
file, FileReadLn turns problem to true, and this particular
program's repeat until loop falls through, and the program
ends. If you forced the issue or wrote a program that does
not regard "problem" then any subsequent attempts to use
FileReadLn would simply assign #0 to tempstr.
In Turbo Pascal, files that are read from or written to
must first be opened, the operation(s) performed, then
closed. FileWrite and FileWriteLn handle all this
automatically, but FileRead and FileReadLn cannot, because if
you were to make subsequent calls to these and they did open
and close the file each time, each time you read, you would
always get the first line in the file, since opening a file,
resets it to the beginning.
So from the first time you read the file with FileRead or
FileReadLn, InFile remains open. It should be closed before
the program ends, and the best way to do that is to call the
very standard procedure, "CleanUp" which is specifically
designed to be the last line in any program. It closes all
open files, resets the video mode, clears the screen and
frees up memory. It never hurts to have this line at the end
of any program, and it is essential at the end of some.
If you have read several lines in infile, then you want
to start over at the top, do this: "reset(infile)."
Prog24 explores graphics a bit. Compile it, run it, study it.
program prog24;
uses crt, video, magic;
begin
sent[1] := 'This is text mode';
GetAnyKey(-1,-1);
BestVideo;
sent[1] := 'This is a graphics mode';
GetAnyKey(-1,-1);
CleanUp;
end.
As you can see, it is quite simple. There are only two new
things in this program. Can you spot them? The first is the
use of a new unit, "Video." The second is a procedure called
"BestVideo." BestVideo is a procedure that figures out what
type of monitor you have, then sets up the program to run on
your graphics card.
And there is a special surprise. Those of you who have
done some graphics work in Turbo Pascal will recognize it's
benefit right away. When you call BestVideo, it automatically
incorporates the graphics drivers into your compiled .EXE
file. Usually, the Borland Graphics Interface files (*.BGI)
must be distributed on the disk along with your program.
There are several video procedures within the magic unit.
They are CGAVideo, HercVideo, EGAVideo, VGAVideo, BestVideo,
and TextVideo. If you use HercVideo, in place of BestVideo,
then the program will work only on computers equipped to
display Hercules Graphics, but the compiled program will be
much smaller, and you can use absolute coordinates to display
graphics.
BestVideo will link in all the *.BGI files and then
automatically detect which graphics card is present in any
computer, and therefore will run on practically any IBM-clone
that has any graphics card. But BestVideo has to incorporate
all the graphics drivers, and therefore the finished product
is larger. Furthermore, when using BestVideo, you have to
account for different resolutions on different machines. On
a CGA machine, the coordinates 0,180 are near the bottom left
edge of the screen, but on VGA 0,180 is on the left, but
nearer to the top of the screen. With BestVideo, you have to
make calculations based on GetMaxX, and GetMaxY, (see your
Borland books) or use centered pop-up boxes.
TextVideo is the way out of graphics. For instance, if
you write a program that starts in graphics mode to display a
drawing, then you want to switch back to text for faster
handling of strings, you simply call the TextVideo procedure.
Pop, GetYN, GetAnyKey, Dialog, Menu and DoubleMenu all
work almost the same in any graphics mode as in text mode.
program prog25;
uses crt, video, magic;
begin
sent[1] := 'This is text mode';
GetAnyKey(-1,-1);
CGAVideo;
sent[1] := 'This is a graphics mode';
GetAnyKey(-1,-1);
TextVideo;
sent[1] := 'This is text again';
GetAnyKey(-1,-1);
CleanUp;
end.
Prog25 switches to CGA graphics mode, then back to text mode.
Prog26 shows some of the complexity in using BestVideo.
program prog26;
uses crt, video, graph, magic;
begin
sent[1] := 'This is text mode';
GetAnyKey(-1,-1);
BestVideo;
setcolor(yellow);
circle(getmaxx div 2,GetMaxY div 2, GetMaxY div 4);
sent[1] := 'This is a graphics mode';
GetAnyKey(-1,-1);
TextVideo;
CleanUp;
end.
Notice the new unit. We are now using a unit that comes with
Turbo Pascal called Graph.tpu. It allows us to make circles,
rectangles, lines, change colors, and many other things. You
should use Graph in all your graphics programs because those
which don't make use of it will not be much larger than those
that do. Borland's compiler is smart and strips unused code
out of units as the program is compiled.
This one switches to a graphics when a key is pressed. If
you have a VGA system, then you'll see a yellow circle around
a pop-up box. But, then change the "BestVideo" line to
"CGAVideo" and you'll see that the pop-up box partially
covers the circle, even though the circle is supposedly the
same size. It's the pop-up that changed.
Notice that you can change color by simply passing a
color to SetColor.
Prog27 shows a few of the many other things you can do with
the Turbo Pascal Graph unit.
program prog27;
uses crt, video, graph, magic;
begin
BestVideo;
SetColor(white);
circle(100,100,50);
circle(100,100,40);
SetFillStyle(solidfill,white);
FloodFill(51,100,white);
SetColor(lightgreen);
SetLineStyle(0,0,3);
rectangle(70,70,130,130);
SetFillStyle(solidfill,lightmagenta);
bar(90,90,110,110);
WaitForUser;
CleanUp;
end.
Prog28 shows how to work with text in a graphics mode. Turbo
Pascal supplies a default font, which is an 8 x 8 pixel
bitmapped font. It is called DefaultFont.
program prog28;
uses crt, video, graph, magic;
begin
BestVideo;
OutTextXY(10,100,'This is the Default font');
WaitForUser;
CleanUp;
end.
In Prog28 we see that the way to display a string is through
OutTextXY, which is similar to GoToXY combined with Write in
text mode. OutTextXY requires screen coordinates, then a
string. Unlike write and writeln, you must pass only a
string and only one string at a time. You must "str" numbers
before using OutTextXY.
Prog29 shows how to work with different fonts.
program prog29;
uses crt, video, graph, magic;
begin
BestVideo;
Triplex;
SetTextStyle(TriplexFont,HorizDir,4);
OutTextXY(0,0,'This is the Triplex font');
WaitForUser;
CleanUp;
end.
First, you'll see a call to "Triplex." This will cause the
external Triplex.Chr file to be compiled directly into the
.EXE file. You do not have to distribute finished programs
with external *.chr files! But by itself, Triplex has no
other effect on the program. If you want to actually use the
Triplex font, you have to use "SetTextStyle". SetTextStyle
takes three parameters. First is an integer for the font to
use, and these integers also have pre-declared constants in
the graph unit. Triplex can be referred to as "1" or
TriplexFont. The second number or constant is the
orientation of the text. HorizDir is the most common, of
course. It can also be represented with a 0. And finally the
size of the font can be controlled with another integer value
from 1 to 10.
As tempting as it may seem, there are two reasons not to
use any fonts except DefaultFont with Pop, GetYN, GetAnyKey,
Dialog, Menu or Doublemenu. Gothic, Triplex, SansSerif and
Small fonts are drawn rather than bitmapped and therefore
take longer to generate on the screen, slowing the program
perceptably. Furthermore, because of the way they are
generated, they don't line up right relative to the general x
and y coordinates used by these procedures.
If you run prog29 in CGA mode (you can change BestVideo to
CGAVideo to see) you'll notice that the line, "This is
Triplex font." is too long to fit on the screen. So, in
prog30, lets switch to a different CGA graphics mode.
program prog30;
uses crt, video, graph, magic;
begin
CGAVideo;
SetGraphMode(4);
Triplex;
SettextStyle(TriplexFont,HorizDir,4);
outtextxy(0,0,'This is the Triplex font');
WaitForUser;
CleanUp;
end.
The line, "SetGraphMode(4)" changes to the higher resolution,
2 color, 640 x 200 CGA mode.
Prog31 shows off some basic mouse work, and the main
principal of drawing to the screen.
program prog31;
uses crt, video, graph, magic;
var
x,y : word; {"word" is a positive integer value}
begin
BestVideo;
WasteMouse;
repeat
poll(x,y,left,right);
LineTo(x,y);
until left;
CleanUp;
end.
In prog31 a loop repeats until left becomes true. Left is a
global boolean variable that is set to true when the user
clicks the left mouse button. Poll is a function that asks
the mouse to report it's current status. It tells you through
poll, the current screen position, in this case using x and y
as word type variables for coordinates, and the status of the
left and right mouse buttons. Every time the mouse is polled,
a line is drawn from where the last line ended, to where the
mouse is currently.
Notice the line, "WasteMouse." This is a procedure which
stalls the program until both "left" and "right" are false.
(no mouse buttons pressed). Without "WasteMouse" the program
might end immediately.
Prog32 shows you one way to move a rectangle around. This
program will display the mouse pointer until the left mouse
button is clicked, then it will turn it off and show a
movable rectangle until the right mouse button is clicked.
program prog32;
uses crt, video, graph, magic;
var
x,y : word;
begin
BestVideo;
WasteMouse;
PointerToXY(GetMaxX div 2,GetMaxY div 2);
PointerOn;
repeat Poll(x,y,left,right) until left;
PointerOff;
SetWriteMode(XOrPut);
rectangle(x,y, x + 40, y + 20);
repeat
rectangle(x,y, x + 40, y + 20);
Poll(x,y,left,right);
rectangle(x,y, x + 40, y + 20);
until right;
CleanUp;
end.
Prog32 shows you how to turn the mouse pointer on and off,
and shows "SetWriteMode" so that you can eliminate images
which have been created, by merely writing them over
themselves.
Prog33 shows a couple of small improvements:
program prog33;
uses crt, video, graph, magic;
var
x,y,oldx,oldy : word;
begin
BestVideo;
WasteMouse;
SetTextJustify(CenterText,BottomText);
OutTextXY(GetMaxX div 2,GetMaxY - 4,
'Click right mouse button to end program');
SetWriteMode(XOrPut);
rectangle(x,y, x + 40, y + 20);
repeat
repeat
Poll(x,y,left,right);
until (x <> oldx) or (y <> oldy) or right;
rectangle(oldx,oldy, oldx + 40, oldy + 20);
oldx := x;
oldy := y;
rectangle(x,y, x + 40, y + 20);
until right;
CleanUp;
end.
First, we took off the mouse pointer stuff to simplify the
program. Then we use one of the fancy features of the Turbo
Pascal Graph unit to cause text to be centered from left to
right around the x coordinate and the bottom of the string
will be on the y coordinate. And a notice is posted for the
user.
Then using the new variables, "oldx" and "oldy" within the
repeat loop, we check to see if there have been any changes
in position before moving the rectangle. This eliminates
annoying flashing.
In our last program I'll show you how to use the sound
effects in the magic unit, and we'll fool around with text in
graphics modes a bit more.
program prog34;
uses crt, video, graph, magic;
var
x,y,oldx,oldy : word;
begin
SoundUp; (* 1 *)
MainBack := black; (* 2 *)
BestVideo;
Gothic; (* 3 *)
Triplex;
SetColor(LightMagenta);
SetTextJustify(CenterText,TopText); (* 4 *)
SetTextStyle(GothicFont,HorizDir,6);
OutTextXy(GetMaxX div 2,0,'Type Anything');
SetTextStyle(TriplexFont,VertDir,1);
SetTextJustify(LeftText,CenterText);
OutTextXY(20,(GetMaxY div 2) + 30,'Press [Enter]');
OutTextXY(40,(GetMaxY div 2) + 30,'when done.');
SetTextStyle(DefaultFont,HorizDir,2);
SetTextJustify(LeftText,TopText);
SetFillStyle(SolidFill,black); (* 5 *)
SetColor(LightCyan);
Waste; (* 6 *)
answer := '';
repeat
u := ReadKey;
pink; (* 7 *)
if ord(u) > 31 then answer := answer + u; (* 8 *)
if u = #8 then (* 9 *)
begin
bar(70,100,70 + TextWidth(answer), (* 10 *)
100 + TextHeight(answer));
delete(answer,length(answer),1); (* 11 *)
end;
OutTextXY(70,100,answer);
until u = #13;
SoundDown;
delay(500); (* 12 *)
Twinkle;
CleanUp;
end.
Prog34 has notes within (* and *):
Note 1) One of the four sound effects built into the magic
unit. To use one of the effects, simply call it's procedure.
Sometimes sounds don't behave as expected with machines
faster than 33mhz or when heavily multitasked (running
concurrently with other programs) under MS-Windows or
Deskview.
Note 2) By setting the main background color to black before
a call to BestVideo, the video mode will start and run with a
black background.
Note 3) These procedures, Gothic and Triplex hook in the two
fonts besides the default font that this program is going to
use. There will be no need for *.chr files on the disk with a
compiled program.
Note 4) SetTextJustify will center a title on the screen when
set this way.
Note 5) SetFillStyle is used to establish parameters for
"bar," used a few lines down in this program. Bar will make
a solid rectangle in the color specified (black in this case)
This is a good way to erase text in graphics modes.
Note 6) Waste stalls the program until no mouse buttons are
pressed and no characters have been entered from the
keyboard. If a key had been pressed as this program was
starting, it would be reflected as the first character in a
string the user is going to type.
Note 7) "Pink" is a sound effect, typically used to indicate
a small action has occurred, such as a key has been pressed.
Note 8) "Ord" returns the ordinal position in a set of the
variable specified in parentheses. When used with ASCII
characters, Ord returns their ASCII number. What this line
does is eliminates adding characters to the string called
"answer" if they might be unprintable characters.
Note 9) u is ASCII #8 when the backspace key has been
pressed.
Note 10) "Bar" is being used to erase "answer" from the
screen because the backspace key has been pressed and
therefore the user wants to eliminate the last character in
answer. The Bar will erase it, and a newer version of
answer, one which will be one character shorter will be
written in its place. TextWidth and TextHeight are excellent
functions provided by Turbo Pascal to determine how many
pixels wide and how many pixels high a string are, no matter
what font and size are selected.
Note 11) "Delete" is a way to shorten a string. Delete
requires three parameters, the string on which to operate,
the character position in the string at which to delete, and
the number of characters to take out. There are several other
string procedures available from Turbo Pascal including Pos
(find the position of a matching sub-string within a string),
Copy (make a sub-string from a string), and ConCat (add two
strings together). See your Borland Turbo Pascal manuals for
more information about string handling.
Note 12) Delay is called between two sound effects to put
some time between them. Delay requires one number, an integer
representing the number of milliseconds to delay. There are
1000 milliseconds in one second, so this delay is 1/2 second.
While Delay is running, no other actions can take place.
- - -
And that almost wraps up this tutorial! Hope you have had
as much fun reading and experimenting as I did writing it.
There is far more available in Turbo Pascal than this
short tutorial can tell you about. To learn as much as you
can, in a reasonable amount of time, I recommend getting
several books on Turbo Pascal, and experimenting with every
idea that crosses your mind.
In fact, there's quite a bit more to the Magic unit
itself. You can read Magic.Doc to learn more of its
included procedures and functions, and get more technical
information on the ones you already know.
This is shareware. Feel free to copy and distribute Pascal
Magic as long as all files remain intact and unchanged.
If you have paid a professional shareware distributor a
few dollars for this disk, you have paid for the service of
providing a copy.
If you use MAGIC.TPU in your programs, or if you have
found this tutorial helpful, you must pay for the creation of
the product. Send $29.95 to:
Another Company
P.O. Box 298
Applegate, OR 97530
Complete source code is available for the MAGIC.TPU. This
is good for using as a framework for your own very customized
applications, for learning more about Turbo Pascal
Programming, for stripping down top efficiency, and for
improving, since you will probably soon become (or might
already be) a better programmer than I am. For registration
AND source code, send $59.90 and please specify disk size.
This is version 1.0 and you may find a bug or two. I make no
guarantees about it's suitability to your programming needs.
If we find any major bugs, they will probably be corrected
by the time you get your registered version!
If you require technical assistance, you can try to phone me
at 503-846-7884. Best bet is 9-5 weekdays, but I'm not always
available.
Since you are going to write some wonderful programs, you
might as well start making money with them! You won't have to
work in an office doing programming for someone else. You
can write exactly the kind of programs you want to write, and
make money at home!
The 'secret' is shareware. Does it work? You bet! You
can easily have a small success, making some extra spending
money each month, or with some practice, you can have a wild
success, and make a fine living! There are some millionaires
who make their ever-growing fortune entirely through
shareware.
ANOTHER COMPANY shows you everything. Besides our own
shareware successes, including WRITER'S DREAM, BICYCLE
TUNE-UP AND REPAIR, MONEY, BLACKBOARD, BETTER EYESIGHT,
WHAT'S IN THAT BOX? and THE UNIVERSAL CONVERTER, we have
researched the shareware market, we have interviewed other
shareware authors and have learned about all sides of the
rapidly expanding shareware business.
We show you how to write programs that capture the
public's interest, how to make sure your customers
'register', and how to get money by other means through your
shareware. We show you more. We show you frequency charts
indicating which types of programs sell best, we offer
suggestions for programs as yet unwritten, we talk about
your on-disk instruction manuals, we even show you how to
write user-friendliness into your programs.
Can you succeed without SUCCESS WITH SHAREWARE? Yes!
But why do it the hard way? We have learned all the
super-professional approaches, the pitfalls and the
shortcuts. We'll tell you all about it, and then instead of
stumbling around for the first couple of years, you'll be
a professional from the start!
To get your copy of SUCCESS WITH SHAREWARE! (which is not
shareware, itself - only available from Another Company),
send $19.95. Please specify if you need 3.5" disk size.
Thanks,
- Jeff Napier -
January 9, 1992
You can order products by writing your order on plain paper,
or by printing the included ASCII file called Order.frm, or
by phoning 1-503-846-7884, generally weekdays between 9 and
5, west coast time.