1478 lines
69 KiB
Plaintext
1478 lines
69 KiB
Plaintext
|
From ts@uwasa.fi Sat Mar 30 00:00:00 1996
|
||
|
Subject: FAQPAS.TXT contents
|
||
|
|
||
|
Copyright (c) 1993-1996 by Timo Salmi
|
||
|
All rights reserved
|
||
|
|
||
|
FAQPAS.TXT Frequently (and not so frequently) asked Turbo Pascal
|
||
|
questions with Timo's answers. The items are in no particular order.
|
||
|
|
||
|
You are free to quote brief passages from this file provided you
|
||
|
clearly indicate the source with a proper acknowledgment.
|
||
|
|
||
|
Comments and corrections are solicited. But if you wish to have
|
||
|
individual Turbo Pascal consultation, please post your questions to
|
||
|
a suitable Usenet newsgroup like news:comp.lang.pascal.borland. It
|
||
|
is much more efficient than asking me by email. I'd like to help,
|
||
|
but I am very pressed for time. I prefer to pick the questions I
|
||
|
answer from the Usenet news. Thus I can answer publicly at one go if
|
||
|
I happen to have an answer. Besides, newsgroups have a number of
|
||
|
readers who might know a better or an alternative answer. Don't be
|
||
|
discouraged, though, if you get a reply like this from me. I am
|
||
|
always glad to hear from fellow Turbo Pascal users.
|
||
|
|
||
|
If you are an experienced Turbo Pascal programmer with Turbo Pascal
|
||
|
material you would like to circulate publicly world-wide, you are
|
||
|
welcome to submit your material to the Garbo MS-DOS archives at the
|
||
|
University of Vaasa. To do that you *FIRST* must *CAREFULLY* read
|
||
|
the uploading instructions and the formal requirements in the file
|
||
|
ftp://garbo.uwasa.fi/pc/UPLOAD.INF. You are also welcome to contact
|
||
|
me by email for these instructions if you are not familiar with
|
||
|
downloading them from the Garbo archives.
|
||
|
|
||
|
....................................................................
|
||
|
Prof. Timo Salmi Co-moderator of news:comp.archives.msdos.announce
|
||
|
Moderating at ftp:// & http://garbo.uwasa.fi archives 193.166.120.5
|
||
|
Department of Accounting and Business Finance ; University of Vaasa
|
||
|
ts@uwasa.fi http://uwasa.fi/~ts BBS 961-3170972; FIN-65101, Finland
|
||
|
|
||
|
--------------------------------------------------------------------
|
||
|
1) How do I disable or capture the break key in Turbo Pascal?
|
||
|
2) How do I get a printed documentation of my students' TP runs?
|
||
|
3) What is the code for the weekday of a given date?
|
||
|
4) Need a program to format Turbo Pascal source code consistently
|
||
|
5) Can someone give me advice for writing a tsr program?
|
||
|
6) Why can't I read / write the com ports?
|
||
|
7) What are interrupts and how to use them in Turbo Pascal?
|
||
|
8) Should I upgrade my Turbo Pascal version?
|
||
|
9) How do I execute an MS-DOS command from within a TP program?
|
||
|
10) How is millisecond timing done?
|
||
|
11) How can I customize the text characters to my own liking?
|
||
|
12) How to find the files in a directory and subdirectories?
|
||
|
13) I need a power function but there is none in Turbo Pascal.
|
||
|
14) How can I create arrays that are larger than 64 kilobytes?
|
||
|
15) How can I test that the printer is ready?
|
||
|
16) How can I clear the keyboard type-ahead buffer?
|
||
|
17) How can I utilize expanded memory (EMS) in my programs?
|
||
|
18) How can I obtain the entire command line?
|
||
|
19) How do I redirect text from printer to file in my TP program?
|
||
|
20) Turbo Pascal is for wimps. Use standard Pascal or C instead?
|
||
|
21) How do I turn the cursor off?
|
||
|
22) How to find all roots of a polynomial?
|
||
|
23) What is all this talk about "Pascal homework on the net"?
|
||
|
24) How can I link graphics drivers directly into my executable?
|
||
|
25) How can I trap a runtime error?
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
Unless otherwise stated the answers cover versions 4.0, 5.0, 5.5,
|
||
|
6.0 and 7.0 (real mode). The Q&As are not for Turbo Pascal version 3
|
||
|
or earlier. Objects, TVision, Windows, Delphi, etc are not covered.
|
||
|
(I do not use them myself.)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:01 1996
|
||
|
Subject: Disabling or capturing the break key
|
||
|
|
||
|
1. *****
|
||
|
Q: I don't want the Break key to be able to interrupt my TP
|
||
|
programs. How is this done?
|
||
|
Q2: I want to be able to capture the Break key in my TP program.
|
||
|
How is this done?
|
||
|
Q3: How do I detect if a certain key has been pressed? (Often, how
|
||
|
do I detect, for example, if the CursorUp key has been pressed?)
|
||
|
Q4: How do I detect if a cursor key or a function key has been
|
||
|
pressed?
|
||
|
|
||
|
A: This set of frequently asked questions is basically a case of
|
||
|
RTFM (read the f*ing manual). But this feature is, admittedly, not
|
||
|
very prominently displayed in the Turbo Pascal reference. (As a
|
||
|
general rule we should not use the newsgroups as a replacement for
|
||
|
our possibly missing manuals, but enough of this line.)
|
||
|
I'll only explain Q and Q2. The other two, Q3 and Q4 should be
|
||
|
evident from the example code.
|
||
|
There is a CheckBreak variable in the Crt unit, which is true by
|
||
|
default. To turn it off use
|
||
|
uses Crt;
|
||
|
:
|
||
|
CheckBreak := false;
|
||
|
:
|
||
|
Besides turning off break checking this enables you to capture the
|
||
|
pressing of the break key as you would capture pressing ctrl-c. In
|
||
|
other words you can use e.g.
|
||
|
:
|
||
|
procedure TEST;
|
||
|
var key : char;
|
||
|
begin
|
||
|
repeat
|
||
|
if KeyPressed then
|
||
|
begin
|
||
|
key := ReadKey;
|
||
|
case key of
|
||
|
#0 : begin
|
||
|
key := ReadKey;
|
||
|
case key of
|
||
|
#59 : write ('F1 ');
|
||
|
#72 : write ('CursUp '); { Detecting these }
|
||
|
#75 : write ('CursLf '); { is often asked! }
|
||
|
#77 : write ('CursRg ');
|
||
|
#80 : write ('CursDn ');
|
||
|
else write ('0 ', ord(key), ' ');
|
||
|
end; {case}
|
||
|
end;
|
||
|
#3 : begin {ctrl-c or break}
|
||
|
writeln ('Break');
|
||
|
halt(1);
|
||
|
end; { Terminate the program, or whatever }
|
||
|
#27 : begin
|
||
|
write ('<esc> ');
|
||
|
exit; { Exit test, continue program }
|
||
|
end;
|
||
|
else write (key, ' ');
|
||
|
end; {case}
|
||
|
end; {if}
|
||
|
until false;
|
||
|
end; (* test *)
|
||
|
:
|
||
|
IMPORTANT: Don't test the ctrl-break feature just from within the TP
|
||
|
IDE, because it has ctlr-break handler ("interceptor") of its own
|
||
|
and may confuse you into thinking that ctrl-break cannot be
|
||
|
circumvented by the method given above.
|
||
|
The above example has a double purpose. It also shows the
|
||
|
rudiments how you can detect if a certain key has been pressed. This
|
||
|
enables you to give input without echoing it to the screen, which is
|
||
|
a later FAQ in this collection.
|
||
|
This is, however, not all there can be to break checking, since
|
||
|
the capturing is possible only at input time. It is also possible to
|
||
|
write a break handler to interrupt a TP program at any time. For
|
||
|
more details see Ohlsen & Stoker, Turbo Pascal Advanced Techniques,
|
||
|
Chapter 7. (For the bibliography, see FAQPASB.TXT in this same FAQ
|
||
|
collection).
|
||
|
|
||
|
A2: This frequent question also elicits one of the most frequent
|
||
|
false answers. It is often suggested erroneously that the relevant
|
||
|
code would be
|
||
|
uses dos;
|
||
|
SetCBreak(false);
|
||
|
This is not so. It confuses MS-DOS and TP break checking with each
|
||
|
other. SetCBreak(false) will _*NOT*_ disable the Ctrl-Break key for
|
||
|
your Turbo Pascal program. What it does is "Sets the state of
|
||
|
Ctrl-Break checking in DOS". SetCBreak sets the state of Ctrl+Break
|
||
|
checking in DOS. When off (False), DOS only checks for Ctrl+Break
|
||
|
during I/O to console, printer, or communication devices. When on
|
||
|
(True), checks are made at every system call."
|
||
|
This item goes to shows how important it is carefully to check
|
||
|
one's code and facts before claiming something.
|
||
|
|
||
|
A3: Using the "CheckBreak := false;" method is not the only
|
||
|
alternative, however. Here is an example code for disabling
|
||
|
Ctrl-Break and Ctrl-C with interrupts
|
||
|
uses Dos;
|
||
|
var OldIntr1B : pointer; { Ctrl-Break address }
|
||
|
OldIntr23 : pointer; { Ctrl-C interrupt handler }
|
||
|
answer : string; { For readln test }
|
||
|
{$F+}
|
||
|
procedure NewIntr1B (flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp : word);
|
||
|
Interrupt;
|
||
|
{$F-} begin end;
|
||
|
{$F+}
|
||
|
procedure NewIntr23 (flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp : word);
|
||
|
Interrupt;
|
||
|
{$F-} begin end;
|
||
|
begin
|
||
|
GetIntVec ($1B, OldIntr1B);
|
||
|
SetIntVec ($1B, @NewIntr1B); { Disable Ctrl-Break }
|
||
|
GetIntVec ($23, OldIntr23);
|
||
|
SetIntVec ($23, @NewIntr23); { Disable Ctrl-C }
|
||
|
writeln ('Try breaking, disabled');
|
||
|
readln (answer);
|
||
|
SetIntVec ($1B, OldIntr1B); { Enable Ctrl-Break }
|
||
|
SetIntVec ($23, OldIntr23); { Enable Ctrl-C }
|
||
|
writeln ('Try breaking, enabled');
|
||
|
readln (answer);
|
||
|
writeln ('Done');
|
||
|
end.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:02 1996
|
||
|
Subject: Directing output also to printer
|
||
|
|
||
|
2. *****
|
||
|
Q: I want to have a printed documentation of my students' Turbo
|
||
|
Pascal program exercises. How is all input and output directed also
|
||
|
to the printer?
|
||
|
|
||
|
A1: Use a screen capturing program to put everything that comes
|
||
|
onto the screen into a file, and print the file. See FAQPROGS.TXT in
|
||
|
ftp://garbo.uwasa.fi/pc/ts/tsfaqn43.zip (or whatever version number
|
||
|
is the current) for more about these programs. Available by
|
||
|
anonymous FTP or mail server from garbo.uwasa.fi.
|
||
|
|
||
|
A2: See the code in TSPAS.NWS (item: Redirecting writes to the
|
||
|
printer) in the ftp://garbo.uwasa.fi/pc/ts/tspa3470.zip (or whatever
|
||
|
is the current version number) Turbo Pascal units package (70 = 40,
|
||
|
50, 55, 60, or 70 depending on your TP version). Alternatively use
|
||
|
USECON and USEPRN routines in the TSUNTG unit of the same package.
|
||
|
|
||
|
+------------------------------------------+
|
||
|
! To get these and other packages given as !
|
||
|
! /dir/subdir/name !
|
||
|
! see the instructions in PD2ANS.TXT !
|
||
|
+------------------------------------------+
|
||
|
|
||
|
A3: But the really elegant solution to the problem of getting a
|
||
|
logfile (or a printed list) of a Turbo Pascal run is to rewrite the
|
||
|
write(ln) and read(ln) device driver functions. In itself writing
|
||
|
such driver redirections is very advanced Turbo Pascal programming,
|
||
|
but when the programming has once been done, the system is extremely
|
||
|
easy to use as many times as you like. It goes like this. The driver
|
||
|
redirections are programmed into a unit (say, tpulog or tpuprn). All
|
||
|
that is needed after that is to include the following uses statement
|
||
|
into the program (the target program) which has to be logged:
|
||
|
uses TPULOG; ( or ) uses TPUPRN;
|
||
|
This is all there is to it. Just adding one simple line to the
|
||
|
target program. (If you call any other units, "uses tpulog" must
|
||
|
come AFTER the system units (e.g. Dos), but BEFORE any which you may
|
||
|
define yourself!)
|
||
|
The reason that I have named two units here instead of just one
|
||
|
in the above example is that the preferred log for the target
|
||
|
program may be a logfile or the printer. The better solution of
|
||
|
these two is to use the logfile option, and then print it. The
|
||
|
reason is simple. If the target program itself prints something,
|
||
|
your printout will look confused.
|
||
|
The logging also has obvious limitations. It works for standard
|
||
|
input and output (read(ln) and write(ln)) only. 1) It does not
|
||
|
support graphics, in other words it is for the textmode. 2) It does
|
||
|
not support direct (Crt) screen writes. 3) And, naturally it only
|
||
|
shows the input and output that comes to the screen. Not any other
|
||
|
input or output, such as from or to a file. 4) Furthermore, you are
|
||
|
not allowed to reassign input or output. Statements like assign
|
||
|
(output, '') will result in a crash, because the rewritten output
|
||
|
device redirections are invalidated by such statements. 5) The
|
||
|
device on the default drive must not be write protected, since else
|
||
|
the logfile cannot be written to it. 6) It does not work for Turbo
|
||
|
Pascal 4.0. Despite these restrictions, the method is perfectly
|
||
|
suited for logging students' Turbo Pascal escapades.
|
||
|
It is advisable first to test and run your target program without
|
||
|
"tpulog", so that if you get any strange errors you'll know whether
|
||
|
they are caused by the logging.
|
||
|
Where to get such a unit. The code can be found in Michael
|
||
|
Tischer (1990), Turbo Pascal Internals, Abacus, Section 4.2. Next a
|
||
|
few of my own tips on this unit Tischer calls Prot. 1) The code is
|
||
|
in incorrect order. The code that is listed on pages 142 - 145 goes
|
||
|
between pages 139 and 140. 2) You can change the logfile name (const
|
||
|
prot_name) to lpt1 for a printed list of the target program run. In
|
||
|
that case it is advisable to include a test for the online status of
|
||
|
the printer within Tischer's unit. 3) I see no reason why the two
|
||
|
lines in Tischer's interface section couldn't be transferred to the
|
||
|
implementation section. Why have any global definitions? But all in
|
||
|
all, it works like magic!
|
||
|
|
||
|
A4: From: abcscnuk@csunb.csun.edu (Naoto Kimura (ACM))
|
||
|
Subject: Re: Printing a log of students' exercises revisited
|
||
|
To: ts@uwasa.fi
|
||
|
Date: Fri, 2 Nov 90 20:52:03 pdt
|
||
|
[Reproduced with Naoto's kind permission]
|
||
|
By the way, several months ago, I had submitted a file (nktools.zip)
|
||
|
file on SimTel that contains sources to a unit (LOGGER), which
|
||
|
allows logging of I/O going through the standard input and output
|
||
|
files, while still being able to use the program interactively. I
|
||
|
believe that I also submitted a copy to your site. It was something
|
||
|
I put together for use by students here at California State
|
||
|
University at Northridge. The source works equally well in all
|
||
|
presently available versions of Turbo Pascal.
|
||
|
The only requirements are that
|
||
|
* you place it as one of the last entries in the USES clause. If
|
||
|
there is anything that redirects the standard input and output
|
||
|
file variables, you should put that unit before my unit in the
|
||
|
USES clause, so that it can see the I/O stream.
|
||
|
* Don't use the GotoXY and similar screen display control
|
||
|
procedures in the Crt unit and expect it to come out the same way
|
||
|
you had it on the display. Since all my unit does is just
|
||
|
capture the I/O stream to send it through the normal channels and
|
||
|
also to the log file, all screen control information is not sent
|
||
|
to the log file.
|
||
|
* All I/O you want logged should go through the standard input and
|
||
|
output file variables.
|
||
|
* Don't close the standard input and output file variables, because
|
||
|
it will cause problems. Basically, as far as I have checked, it
|
||
|
just causes the logging to stop at that point.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:03 1996
|
||
|
Subject: Code to give the weekday of a date
|
||
|
|
||
|
3. *****
|
||
|
Q: I want code that gives the weekday of the given date.
|
||
|
|
||
|
A1: There is a WKDAYFN function in my Turbo Pascal units collection
|
||
|
ftp://garbo.uwasa.fi/pc/ts/tspa3470.zip (or whatever version number
|
||
|
is the latest, and where 70 is 40 50 55 60 and 70) Turbo Pascal
|
||
|
units collection to give the modern weekday based on Zeller's
|
||
|
congruence. Available by anonymous FTP or mail server from
|
||
|
garbo.uwasa.fi. Also you can find a more extensive Julian and
|
||
|
Gregorian weekday algorithm with source code in Dr.Dobb's Journal,
|
||
|
June 1989, p. 148. Furthermore Press & Flannery & al (1986),
|
||
|
Numerical Recipes, Cambridge University Press, present a weekday
|
||
|
code. The Numerical Recipes codes are available as
|
||
|
ftp://garbo.uwasa.fi/pc/turbopas/nrpas13.zip (big, 404k!).
|
||
|
|
||
|
A2: Some will recommend the following kludge. Store the current
|
||
|
date, change it, and let MS-DOS get you the weekday. Don't use it!
|
||
|
It is a bad suggestion. On top of being sloppy programming, there
|
||
|
are several snags. The trick works only for years 1980-2079. A
|
||
|
crash the program may leave the clock at a wrong date. And even if
|
||
|
multitasking is rare, in a multitasking environment havoc may result
|
||
|
for the other tasks. And you may have a TSR that requires the
|
||
|
correct date, etc.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:04 1996
|
||
|
Subject: Pretty printers (or uniform code)
|
||
|
|
||
|
4. *****
|
||
|
Q: Where can I find a program that formats my (or my students')
|
||
|
Turbo Pascal code in a consistent matter.
|
||
|
|
||
|
A: What you are asking for is often called "a pretty printer".
|
||
|
TurboPower Software's (the usual disclaimer applies) commercial
|
||
|
Turbo Analyst has a facility for this with many options. There are
|
||
|
also PD and shareware pretty printers, such as
|
||
|
:
|
||
|
16830 Nov 28 1989 ftp://garbo.uwasa.fi/pc/turbopas/ppdk50.zip
|
||
|
ppdk50.zip Pascal Prettypringting Program, tweak, D.Kirschbaum
|
||
|
:
|
||
|
10015 Mar 29 1991 ftp://garbo.uwasa.fi/pc/turbopas/ppp.zip
|
||
|
ppp.zip Pretty Print Pascal, with Turbo Pascal 5+ source, M.Bless
|
||
|
:
|
||
|
38021 Nov 5 1994 ftp://garbo.uwasa.fi/pc/turbopas/bp7sb104.zip
|
||
|
bp7sb104.zip Borland and TP Source Beautifier, crippleware, J.Ferincz
|
||
|
:
|
||
|
25100 Jul 4 1992 ftp://garbo.uwasa.fi/pc/turbopas/epb232.zip
|
||
|
epb232.zip Ed's Pascal Beautifier, E.Lee
|
||
|
:
|
||
|
and others at garbo.uwasa.fi available by anonymous FTP or mail
|
||
|
server. See ftp://garbo.uwasa.fi/pc/INDEX.ZIP for the list of the
|
||
|
files.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:05 1996
|
||
|
Subject: How to write TSR programs
|
||
|
|
||
|
5. *****
|
||
|
Q: Can someone give me advice for writing a tsr program?
|
||
|
|
||
|
A: Writing a terminate and stay resident program can be considered
|
||
|
advanced programming and is beyond the scope of an electronic
|
||
|
message with limited space. Instead, here are some references to
|
||
|
Turbo Pascal books and papers which have a coverage of the subject.
|
||
|
Stephen O'Brien, Turbo Pascal, The Complete Reference, Chapter 16;
|
||
|
Stephen O'Brien, Turbo Pascal, Advanced Programmer's Guide, Chapter
|
||
|
6; Michael Tischer, Turbo Pascal Internals, Chapter 11 (a definite
|
||
|
bible of TP programming!); Michael Tischer (1992), PC Intern System
|
||
|
Programming, Chapter 32; Michael Yester, Using Turbo Pascal, Chapter
|
||
|
19; Kent Pottebaum, "Creating TSR Programs with Turbo Pascal", Dr.
|
||
|
Dobb's Journal, May 1989 and June 1989; Kris Jamsa, Dos Power User's
|
||
|
Guide, pp. 649-; Edward Mitchell (1993), Borland Pascal Developer's
|
||
|
Guide, Section "Writing TSRs", pp. 370-400, with 778 lines of sample
|
||
|
code.
|
||
|
Also see example code files like
|
||
|
ftp://garbo.uwasa.fi/pc/turboobj/tsrhelp.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopa45/tess-5.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopa45/tsrunit.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopa7/pptsr10.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopa7/tsrsrc35.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopas/deltsr.zip,
|
||
|
ftp://garbo.uwasa.fi/pc/turbopas/tp4_tsr.zip.
|
||
|
Furthermore, you should see the TSR.SWG examples in the fine SWAG
|
||
|
(SourceWare Archival Group's) collection of TP sources. Available
|
||
|
from the /pc/turbopas directory at Garbo. For the current references
|
||
|
to the SWAG files see ftp://garbo.uwasa.fi/pc/INDEX.ZIP.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:06 1996
|
||
|
Subject: Programming com ports
|
||
|
|
||
|
6. *****
|
||
|
Q: Why can't I read / write the com ports.
|
||
|
|
||
|
A: Com port programming (most often writing telecommunication
|
||
|
programs) is much much more complicated than simply trying to use
|
||
|
write (com, whatever);
|
||
|
read (com, whatever);
|
||
|
This is a very advanced subject (frankly, beyond me), and the best
|
||
|
way to learn is to try to obtain some code to show you how. One
|
||
|
place to look at is Turbo Pascal text-books (I have a long list of
|
||
|
them at garbo.uwasa.fi archives in my collection of Turbo Pascal
|
||
|
units ftp://garbo.uwasa.fi/pc/ts/tsfaqp3470.zip. There also is an
|
||
|
example by David Rind in ftp://garbo.uwasa.fi/pc/pd2/faquote.zip.
|
||
|
Another source is International FidoNet pascal conference at some
|
||
|
bulletin board near you. The conference has had some very good
|
||
|
discussions in it. (No, I don't have them stored for distribution,
|
||
|
nor any further information.) Some files you might wish to look at:
|
||
|
ftp://garbo.uwasa.fi/pc/turbopas/comm_tp5.zip and comtty30.zip.
|
||
|
Furthermore, you should see the COMM.SWG examples in the fine
|
||
|
SWAG (SourceWare Archival Group's) collection of TP sources.
|
||
|
Available from the /pc/turbopas directory at Garbo. For the current
|
||
|
references to the SWAG files see ftp://garbo.uwasa.fi/pc/INDEX.ZIP.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:07 1996
|
||
|
Subject: Primers to interrupt programming
|
||
|
|
||
|
7. *****
|
||
|
Q: What are interrupts and how to use them in Turbo Pascal?
|
||
|
|
||
|
A: An interrupt is a signal to the processor from a program, a
|
||
|
hardware device, or the processor itself, to suspend temporarily
|
||
|
what the program is doing, and to perform a routine that is stored
|
||
|
in the operating system. There are 256 such interrupt routines, with
|
||
|
many subservices stored in memory at locations, which are given in
|
||
|
the so called interrupt table. Turbo Pascal (somewhat like C) has a
|
||
|
special keyword Intr, and a predefined variable registers (in the
|
||
|
Dos unit) to access these interrupt routines. One way of looking at
|
||
|
them is as Turbo Pascal (complicated lowlevel) subroutines that are
|
||
|
already there ready for you to call.
|
||
|
A detailed description of interrupt routines is way beyond a
|
||
|
single message with limited space. Instead, I shall give a simple
|
||
|
example, and good references to the subject. (For a somewhat more
|
||
|
comprehensive description of what an interrupt is, see INTERRUP.PRI
|
||
|
in Ralf Brown's ftp://garbo.uwasa.fi/pc/programming/inter48b.zip.)
|
||
|
:
|
||
|
uses Dos;
|
||
|
(* This procedure turns on the border color for CGA and VGA *)
|
||
|
procedure BORDER (color : byte);
|
||
|
var regs : registers; (* Predeclared in the Dos unit *)
|
||
|
begin
|
||
|
FillChar (regs, SizeOf(regs), 0); (* A precaution *)
|
||
|
regs.ax := $0B00; (* Service number *)
|
||
|
regs.bh := $00; (* Subservice number *)
|
||
|
regs.bl := color;
|
||
|
Intr ($10, regs); (* ROM BIOS video driver interrupt *)
|
||
|
end; (* border *)
|
||
|
If you are new the subject and / or want ideas on the most useful
|
||
|
interrupts in Turbo Pascal programming, Ben Ezzel (1989),
|
||
|
Programming the IBM User Interface Using Turbo Pascal, is definitely
|
||
|
the best reference to look at. There are also many other good
|
||
|
references for a novice interrupt user, such as Jamsa & Nameroff,
|
||
|
Turbo Pascal Programmer's Library.
|
||
|
If you are a more advanced interrupt user you'll find the
|
||
|
following references very useful. Michael Tischer (1990), Turbo
|
||
|
Pascal Internals; Norton & Wilton (1988), The New Peter Norton
|
||
|
Programmer's guide to the IBM PC & PS/2; Ray Duncan (1988), Advanced
|
||
|
MS-DOS Programming; Terry Dettmann (1989), Dos Programmer's
|
||
|
Reference, Second edition, Que. Furthermore, there is an impressive
|
||
|
list of interrupts collected and maintained by Ralf Brown. His
|
||
|
extensive ftp://garbo.uwasa.fi:/pc/programming/inter48a.zip,
|
||
|
inter48b.zip, inter48c.zip, inter48d.zip, inter48e.zip and
|
||
|
inter48f.zip (or whatever are the current versions when you read
|
||
|
this) is available by anonymous FTP or mail server from
|
||
|
garbo.uwasa.fi. A definite must for an advanced user. Also see the
|
||
|
reference to Brown's and Kyle's book in the bibliography at the end
|
||
|
of this FAQ. There is also a good hypertext advanced programmer's
|
||
|
quick reference ftp://garbo.uwasa.fi/pc/programming/helppc21.zip
|
||
|
which you might find useful.
|
||
|
One more point for Turbo Pascal users. When Borland upgraded from
|
||
|
version 3 to 4.0 quite a number of tasks that needed to be done
|
||
|
using interrupts (such as getting the current time) were included as
|
||
|
normal TP routines. This means that while definitely useful,
|
||
|
interrupt programming is now relevant only in advanced Turbo Pascal
|
||
|
programming. Turbo Pascal 5.0 introduced a few more, but you can
|
||
|
find some of the missing TP 4.0 routines in the compatibility unit
|
||
|
in my ftp://garbo.uwasa.fi/pc/ts/tspa3440.zip TP units collection.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:08 1996
|
||
|
Subject: Borland's Turbo Pascal upgrades
|
||
|
|
||
|
8. *****
|
||
|
Q: Should I upgrade my Turbo Pascal version?
|
||
|
|
||
|
A1: Depends on what version you are using, and for what purposes.
|
||
|
If you are using version 3, the answer is a definite yes. There are
|
||
|
so many useful additions in the later version, including the concept
|
||
|
of units, and a great number of new useful keywords. The only reason
|
||
|
that I can think of for using TP 3 is that it makes .com files
|
||
|
(which reside in one memory segment only) instead of .exe files. As
|
||
|
an accounting and business finance teacher and researcher I've been
|
||
|
somewhat surprised to see postings stating that some users still
|
||
|
have to program in TP 3.0 because their employer doesn't want to
|
||
|
take the cost of upgrading. I find this cost argument ridiculous.
|
||
|
How about some consideration for cost effectiveness and
|
||
|
productivity?
|
||
|
If you are currently using version 4.0, the most important point
|
||
|
in considering upgrading is the integrated debugger in the later
|
||
|
versions. It is really good, and useful if you write much code.
|
||
|
There are some minor considerations, as well. Later versions contain
|
||
|
some useful routines which 4.0 does not. I have programmed many of
|
||
|
them to be available also for 4.0 in my units collection
|
||
|
ftp://garbo.uwasa.fi/pc/ts/tspa3440.zip (or whatever is the latest
|
||
|
when you read this). Furthermore, I find somewhat annoying that the
|
||
|
executables will always end up in the default directory.
|
||
|
If you are currently using version 5.0 the rational reasons for
|
||
|
upgrading are needing objects, and a better overlay manager. I have
|
||
|
also version 5.5 myself, but switched back to version 5.0 after I
|
||
|
had some problems with its linking of object files. (This is a false
|
||
|
statement from me, since it turned out that I had made a mistake
|
||
|
myself. My thanks are due to bj_stedm@gould2.bristol-poly.ac.uk
|
||
|
(Bruce Stedman) for questioning this item). Anyway, I don't use nor
|
||
|
need OOP objects (don't confuse linking object files and object
|
||
|
oriented programming here). One further point for 5.5. It has a
|
||
|
better help function than 5.0, and a few more procedures and
|
||
|
predefined constants. The TP 5.5 help includes examples, which can
|
||
|
be even pasted into your program. This is handy.
|
||
|
The real snag in upgrading (waiving the reasonable cost) is the
|
||
|
fact that the units of the different versions are incompatible. If
|
||
|
you have a large library of units (as I do) you will have to
|
||
|
recompile the lot. This is something that has caused a fair amount
|
||
|
of justifiable flak against an otherwise excellent product.
|
||
|
A tip. Don't throw away your Turbo Pascal version 3.0 manual, if
|
||
|
you have one. It is of use if you resort to the Turbo3 and Graph3
|
||
|
compatibility units. They give you access e.g. to turtle graphics.
|
||
|
At the time of first writing this Turbo Pascal 6.0 version had
|
||
|
just been announced. I didn't have it yet myself, but I had been
|
||
|
(correctly) informed that its units are not compatible with the
|
||
|
earlier versions. I now have Turbo Pascal 6.0, and I must say that
|
||
|
my reactions have been disappointment and frustration. This is
|
||
|
probably partly (but not entirely) my own fault, since Turbo Pascal
|
||
|
seems to be headed from a common programming language into a full
|
||
|
professional's specialized tool, with many features I don't know how
|
||
|
to utilize. The only advancement from my point of view really is the
|
||
|
multiple file editing, but I have long had alternative programs for
|
||
|
that. If I used assembler (I don't) I am sure that I would find
|
||
|
useful TP 6.0's potential to include assembler code as such instead
|
||
|
of having to use the cumbersome Inline procedure of entering the
|
||
|
assembler code.
|
||
|
There is also a Windows Turbo Pascal, as the latest addition to
|
||
|
the plethora. Since I don't use Windows at all, I have no further
|
||
|
information on it.
|
||
|
I think a pattern is emerging here. Rather than being different
|
||
|
versions of the same product, the consecutive Turbo Pascals are
|
||
|
really different products for different purposes. Version 3.0 was a
|
||
|
simple programming language. Version 4.0 extended it into a full
|
||
|
scale programming modular platform. Version 5.0 introduced the
|
||
|
debugger. And there an advanced hobbyist's path ended. Version 5.5
|
||
|
introduced object oriented programming, which I'm sure is important
|
||
|
for the initiated, but personally I just don't need it even if I
|
||
|
write a lot of programs. And with the 6.0 we go completely out of
|
||
|
the realm of conventional programming into Turbo Pascal visions.
|
||
|
And Windows Turbo Pascal is for a different platform, altogether.
|
||
|
I find the new integrated user interface of TP 6.0 awkward in
|
||
|
comparison to what was used in the 4.0, 5.0, and 5.5 versions. The
|
||
|
IDE of TP leaves less free memory than the previous versions.
|
||
|
Furthermore TP 6.0 IDE performs frequent disk accesses which cause
|
||
|
slowdowns making it virtually unusable from a floppy. And I
|
||
|
wonder why Borland didn't at once go all the way to Windows, because
|
||
|
that is what 6.0 really is. An intermediate, incomplete step in that
|
||
|
direction. This means that we have a 5th upgrade in line with
|
||
|
incompatible units. This is aggravating even for a TP fan, isn't it?
|
||
|
For information on Turbo Pascal version 7.0 and Borland email
|
||
|
contact numbers see ftp://garbo.uwasa.fi/pc/turbopa7/bp7-info.zip.
|
||
|
Also see ftp://garbo.uwasa.fi/pc/turbspec/bp7bugs2.zip by Duncan
|
||
|
Murdoch. Turbo Pascal 7.0 or more extensively Borland Pascal 7.0 is
|
||
|
a full professional's tool, and far beyond for example my moderate
|
||
|
programming needs. To list only a few of the features are protected
|
||
|
mode programming, handling of large programs, very fast compiling,
|
||
|
and a daunting amount of material elbowing its away on one's disk
|
||
|
space if one ever has the patience to look through it all. I would
|
||
|
use the word "overwhelming". But for a serious programmer this is an
|
||
|
impressive and a very worthwhile tool. One should not be misled
|
||
|
skipping it because of my comments which were written from a
|
||
|
hobbyist's point of view. As a general trend in programs, the
|
||
|
well-known columnist John C. Dvorak calls this increasing product
|
||
|
complexity trend "featurism" in PC Computing, May 1993. But TP 7.0
|
||
|
(7.01) has some important features also from a hobbyist's point of
|
||
|
view. So much so that I have finally succumbed to 7.01 myself. I
|
||
|
particularly like the color coding of the keywords, and the TPX
|
||
|
version enabling compiling very large programs (utilizing extended
|
||
|
memory). A very welcome addition are the new keywords break and
|
||
|
continue to exit or recycle a for, while or a repeat loop are.
|
||
|
Besides they make using the outcast goto statements virtually
|
||
|
unnecessary.
|
||
|
|
||
|
A2: From: dmurdoch@watstat.waterloo.edu (Duncan Murdoch),
|
||
|
Newsgroups: comp.lang.pascal. Included with Duncan's kind
|
||
|
permission. [Duncan is one of the most knowledgeable and useful
|
||
|
contributors to the comp.lang.pascal UseNet newsgroup (later
|
||
|
replaced by comp.lang.pascal.borland for TP)].
|
||
|
One other reason: there's a bug in the code generator for 4.0
|
||
|
and 5.0 that makes it handle the Extended (10 byte) real type
|
||
|
poorly. The code generated makes very poor use of the 8 element
|
||
|
internal stack on the coprocessor, so that expressions with lots of
|
||
|
operands like
|
||
|
e1+e2+e3+e4+e5+e6+e7+e8+e9
|
||
|
always fail, if all the e's are of type extended. (The generated
|
||
|
code pushes each operand onto the stack, then does all the adds.
|
||
|
It's smarter to push and add them one at a time.)
|
||
|
This makes it a real pain translating numerical routines from
|
||
|
Fortran, especially since constants are taken to be of type
|
||
|
extended.
|
||
|
The bug was fixed in 5.5.
|
||
|
|
||
|
A3: From: Bengt Oehman (d92bo@efd.lth.se): A difference between
|
||
|
v4.0 and v5.5 is that you can calculate constants in tp55, but not
|
||
|
in 4.0. I see this as a big advantage. For example:
|
||
|
CONST MaxW = 10;
|
||
|
MaxH = 20;
|
||
|
MaxSize = MaxW*MaxH;
|
||
|
{ or }
|
||
|
MaxX = 100;
|
||
|
HalfMaxX = MaxX DIV 2;
|
||
|
cannot be compiled with 4.0.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:09 1996
|
||
|
Subject: Shelling from a TP program
|
||
|
|
||
|
9. *****
|
||
|
Q: How do I execute an MS-DOS command from within a TP program?
|
||
|
|
||
|
A: The best way to answer this question is to give an example.
|
||
|
{$M 2048, 0, 0} (* <-- Important *)
|
||
|
program outside;
|
||
|
uses dos;
|
||
|
begin
|
||
|
write ('Directory call from within TP by Timo Salmi');
|
||
|
SwapVectors;
|
||
|
Exec (GetEnv('comspec'), '/c dir *.*'); (* Execution *)
|
||
|
SwapVectors;
|
||
|
(* Testing for errors is recommended *)
|
||
|
if DosError <> 0 then
|
||
|
writeln ('Dos error number ', DosError)
|
||
|
else
|
||
|
writeln ('Mission accomplished, exit code ', DosExitCode);
|
||
|
(* For DosError and DosExitCode details see the TP manual *)
|
||
|
end.
|
||
|
Alternatively, take a look at execdemo.pas from demos.arc which
|
||
|
should be on the disk accompanying Turbo Pascal.
|
||
|
What the above Exec does is that it executes the command
|
||
|
processor. The /c specifies that the command interpreter is to
|
||
|
perform the command, and then stop (not halt).
|
||
|
I have also seen it asked how one can swap the Turbo Pascal
|
||
|
program to the disk when shelling. It is unnecessary to program that
|
||
|
separately because there is an excellent program to do that for you.
|
||
|
It is ftp://garbo.uwasa.fi/pc/sysutil/shrom24b.zip.
|
||
|
Somewhat surprisingly some users have had difficulties with
|
||
|
redirecting shelled output. It is straight-forward. In the above
|
||
|
code one would use, for example
|
||
|
Exec (GetEnv('comspec'), '/c dir *.* > tmp');
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:10 1996
|
||
|
Subject: Millisecond timing
|
||
|
|
||
|
10. *****
|
||
|
Q: How is millisecond timing done?
|
||
|
|
||
|
A: A difficult task, but the facilities are readily available.
|
||
|
TurboPower Software's commercial Turbo Professional (don't confuse
|
||
|
with Borland's Turbo Professional) has a unit for this. (The usual
|
||
|
disclaimer applies). It is called tptimer and is part of the
|
||
|
ftp://garbo.uwasa.fi/pc/turbopas/bonus507.zip package. This one has
|
||
|
been released to the PD. I have also seen a SimTel upload
|
||
|
announcement of a ztimer11.zip for C and ASM, but I have no further
|
||
|
information on that. ftp://garbo.uwasa.fi/pc/turbopas/qwktimer.zip
|
||
|
is another option. It is not quite as accurate as tptimer.
|
||
|
To test the tptimer unit in bonus507.zip you can use the
|
||
|
following example code
|
||
|
uses Crt, tptimer;
|
||
|
var time1, time2 : longint;
|
||
|
begin
|
||
|
InitializeTimer;
|
||
|
time1 := ReadTimer;
|
||
|
Delay (1356); (* Or whatever code you wish to benchmark *)
|
||
|
time2 := ReadTimer;
|
||
|
RestoreTimer;
|
||
|
writeln ('Elapsed = ', ElapsedTime (time1, time2)/1000.0 : 0 : 3);
|
||
|
end.
|
||
|
It is quite another question when you really need the millisecond
|
||
|
timing. The most common purpose for millisecond timing is testing
|
||
|
the efficiency of alternative procedures and functions, right? The
|
||
|
way I compare mine is simple. I call the procedures or functions I
|
||
|
want to compare for speed, say, a thousand times in a loop. And
|
||
|
test this for elapsed time. This way the normal resolution (18.2
|
||
|
cycles per second) of the system clock becomes sufficient. This is
|
||
|
accurate enough for the comparisons.
|
||
|
var elapsed : real; i : word;
|
||
|
elapsed := TIMERFN; (* e.g. from /pc/ts/tspa3455.zip *)
|
||
|
for i := 1 to 1000 do YOURTEST; (* Try out the alternatives *)
|
||
|
elapsed := TIMERFN - elapsed;
|
||
|
writeln ('Elapsed : ', elapsed : 0 : 2);
|
||
|
Incidentally, if you want to make more elaborate evaluations of the
|
||
|
efficiency of your code, Borland's Turbo Profiler is a useful tool.
|
||
|
(The usual disclaimer naturally applies.)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:11 1996
|
||
|
Subject: Text font customizing
|
||
|
|
||
|
11. *****
|
||
|
Q: How can I customize the text characters to my own liking?
|
||
|
|
||
|
A: As far as I know, text-mode characters are hard-coded, and
|
||
|
cannot be customized at all unless you have an EGA or VGA adapter.
|
||
|
But you can always retrieve the bitmap information for the ascii
|
||
|
characters from your PC.
|
||
|
The bitmap table for the lower part of the character set (0-127)
|
||
|
starts at memory position $F000 and ends at $FA6E. The upper part is
|
||
|
not at a fixed memory location. The pointer to the memory address of
|
||
|
upper part of the ascii table (provided that graftabl has been
|
||
|
loaded) is at an address $007C. One way of saying this is that the
|
||
|
segment address of the upper part's memory location is at $007E, and
|
||
|
its offset at $007C.
|
||
|
Going into more details is beyond the scope of this posting. If
|
||
|
you want more information see Michael Tischer (1992), PC Intern
|
||
|
System Programming, "Selecting and Programming Fonts", pp. 197-210.
|
||
|
It also has information on a remotely related task of using sprites
|
||
|
(pp. 305-373), a concept familiar from the days of the Commodore 64
|
||
|
games programming. For another reference to customizing characters
|
||
|
see Kent Porter (1987), Stretching Turbo Pascal, Chapter 12, and
|
||
|
Kent Porter & Mike Floyd (1990), Stretching Turbo Pascal. Version
|
||
|
5.5. Revised Edition. Brady, Chapter 11.
|
||
|
If you are interested in a demonstration of utilizing the
|
||
|
bitmapped character information (no source code available), take a
|
||
|
look at the demo in the garbo.uwasa.fi anonymous FTP archives file
|
||
|
ftp://garbo.uwasa.fi/pc/ts/tsdemo16.zip (or whatever version number
|
||
|
is current).
|
||
|
Turbo Pascal also supports what is called stroked fonts (the
|
||
|
.chr) files which draw characters instead of bitmapping them. The
|
||
|
user should be able to write one's own .chr definitions, but I have
|
||
|
no experience nor information on how this can be done.
|
||
|
There is something called bgikit10.zip which has facilities for
|
||
|
making fonts and adding graphics drivers. The problem is that I
|
||
|
cannot make it publicly available, since I think that it is not PD.
|
||
|
I am still missing the information. Unfortunately, it is not even
|
||
|
the only case where I encountered the fact that Borland does not
|
||
|
seem at all interested in the UseNet users' queries about the status
|
||
|
and distributability of their material.
|
||
|
(From Leonard Erickson Leonard.Erickson@f51.n105.z1.fidonet.org
|
||
|
Well, you can *also* do it if you have a Hercules Graphics Card Plus
|
||
|
or Hercules InColor card (as far as I know, the only cards that
|
||
|
implemented Hercules RamFont 'standard'). And you can modify the
|
||
|
upper 128 characters on a CGA card. BTW, the RamFont cards are
|
||
|
*nice* pity it appeared too late to become a standard. It's a *lot*
|
||
|
more flexible than EGA/VGA fonts (I can have several *dozen* fonts
|
||
|
resident).)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:12 1996
|
||
|
Subject: Finding files in TP
|
||
|
|
||
|
12. *****
|
||
|
Q: How to find the files in a directory AND subdirectories?
|
||
|
|
||
|
A: Writing a program that goes through the files of the directory,
|
||
|
and all the subdirectories below it, is based on Turbo Pascal's file
|
||
|
finding commands and recursion. This is universal whether you are
|
||
|
writing, for example, a directory listing program, or a program that
|
||
|
deletes, say, all the .bak files, or some other similar task.
|
||
|
To find (for listing or other purposes) the files in a directory
|
||
|
you need above all the FindFirst and FindNext keywords, and testing
|
||
|
the predefined file attributes. You make these a procedure, and call
|
||
|
it recursively. If you want good examples with source code, please
|
||
|
see PC World, April 1989, p. 154; Kent Porter & Mike Floyd (1990),
|
||
|
Stretching Turbo Pascal. Version 5.5. Revised Edition, Chapter 23;
|
||
|
Michael Yester (1989), Using Turbo Pascal, p. 437; Michael Tischer
|
||
|
(1992), PC Intern System Programming, pp. 796-798.
|
||
|
The simple (non-recursive) example listing all the read-only
|
||
|
files in the current directory shows the rudiments of the principle
|
||
|
of Using FindFirst, FindNext, and the file attributes, because some
|
||
|
users find it hard to use these keywords. Also see the code in the
|
||
|
item "How to establish if a name refers to a directory or not?" of
|
||
|
this same FAQ collection you are now reading.
|
||
|
uses Dos;
|
||
|
var FileInfo : SearchRec;
|
||
|
begin
|
||
|
FindFirst ('*.*', AnyFile, FileInfo);
|
||
|
while DosError = 0 do
|
||
|
begin
|
||
|
if (FileInfo.Attr and ReadOnly) > 0 then
|
||
|
writeln (FileInfo.Name);
|
||
|
FindNext (FileInfo);
|
||
|
end;
|
||
|
end. (* test *)
|
||
|
|
||
|
A2: While we are on the subject related to FindFirst and FindNext,
|
||
|
here are two useful examples:
|
||
|
|
||
|
(* Number of files in a directory (not counting directories) *)
|
||
|
function DFILESFN (dirName : string) : word;
|
||
|
var nberOfFiles : word;
|
||
|
FileInfo : searchRec;
|
||
|
begin
|
||
|
if dirName[Length(dirName)] <> '\' then dirName := dirName + '\';
|
||
|
dirName := dirName + '*.*';
|
||
|
{}
|
||
|
nberOfFiles := 0;
|
||
|
FindFirst (dirName, AnyFile, FileInfo);
|
||
|
while DosError = 0 do
|
||
|
begin
|
||
|
if ((FileInfo.Attr and VolumeId) = 0) then
|
||
|
if (FileInfo.Attr and Directory) = 0 then
|
||
|
Inc (nberOfFiles);
|
||
|
FindNext (FileInfo);
|
||
|
end; {while}
|
||
|
dfilesfn := nberOfFiles;
|
||
|
end; (* dfilesfn *)
|
||
|
|
||
|
(* Number of immediate subdirectories in a directory *)
|
||
|
function DDIRSFN (dirName : string) : word;
|
||
|
var nberOfDirs : word;
|
||
|
FileInfo : searchRec;
|
||
|
begin
|
||
|
if dirName[Length(dirName)] <> '\' then dirName := dirName + '\';
|
||
|
dirName := dirName + '*.*';
|
||
|
{}
|
||
|
nberOfDirs:= 0;
|
||
|
FindFirst (dirName, AnyFile, FileInfo);
|
||
|
while DosError = 0 do
|
||
|
begin
|
||
|
if ((FileInfo.Attr and VolumeId) = 0) then
|
||
|
if (FileInfo.Attr and Directory) > 0 then
|
||
|
if (FileInfo.Name <> '.') and (FileInfo.Name <> '..') then
|
||
|
Inc (nberOfDirs);
|
||
|
FindNext (FileInfo);
|
||
|
end; {while}
|
||
|
ddirsfn := nberOfDirs;
|
||
|
end; (* ddirsfn *)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:13 1996
|
||
|
Subject: A generic power function code for TP
|
||
|
|
||
|
13. *****
|
||
|
Q: I need a power function but there is none in Turbo Pascal.
|
||
|
|
||
|
A: Pascals do not have an inbuilt power function. You have to write
|
||
|
one yourself. The common, but non-general method is defining
|
||
|
function POWERFN (number, exponent : real) : real;
|
||
|
begin
|
||
|
powerfn := Exp(exponent*Ln(number));
|
||
|
end;
|
||
|
To make it general use:
|
||
|
(* Generalized power function by Prof. Timo Salmi *)
|
||
|
function GENPOWFN (number, exponent : real) : real;
|
||
|
begin
|
||
|
if (exponent = 0.0) then
|
||
|
genpowfn := 1.0
|
||
|
else if number = 0.0 then
|
||
|
genpowfn := 0.0
|
||
|
else if abs(exponent*Ln(abs(number))) > 87.498 then
|
||
|
begin writeln ('Overflow in GENPOWFN expression'); halt; end
|
||
|
else if number > 0.0 then
|
||
|
genpowfn := Exp(exponent*Ln(number))
|
||
|
else if (number < 0.0) and (Frac(exponent) = 0.0) then
|
||
|
if Odd(Round(exponent)) then
|
||
|
genpowfn := -GENPOWFN (-number, exponent)
|
||
|
else
|
||
|
genpowfn := GENPOWFN (-number, exponent)
|
||
|
else
|
||
|
begin writeln ('Invalid GENPOWFN expression'); halt; end;
|
||
|
end; (* genpowfn *)
|
||
|
On the lighter side of things an extract from an answer of mine in
|
||
|
the late comp.lang.pascal UseNet newsgroup:
|
||
|
>anyone point out why X**Y is not allowed in Turbo Pascal?
|
||
|
The situation in TP is a left-over from standard
|
||
|
Pascal. You'll recall that Pascal was originally
|
||
|
devised for teaching programming, not for
|
||
|
something as silly and frivolous as actually
|
||
|
writing programs. :-)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:14 1996
|
||
|
Subject: Arrays > 64K
|
||
|
|
||
|
14. *****
|
||
|
Q: How can I create arrays that are larger than 64 kilobytes?
|
||
|
|
||
|
A: Turbo Pascal does not directly support the so-called huge arrays
|
||
|
but you can get by this problem with a clever use of pointers as
|
||
|
presented in Kent Porter, "Handling Huge Arrays", Dr.Dobb's Journal,
|
||
|
March 1988. In this method you point to an element of a two
|
||
|
dimensional array using a^[row].col^[column]. The idea involves too
|
||
|
much code and explanation to be repeated here, so you'll have to see
|
||
|
the original reference. But I know from my own experience, that the
|
||
|
code works like magic. (The code is available from garbo.uwasa.fi
|
||
|
archives as ftp://garbo.uwasa.fi/pc/turbopas/ddj8803.zip). Kent
|
||
|
Porter, "Huge Arrays Revisited", Dr.Dobb's Journal, October 1988,
|
||
|
presents the extension of the idea to huge virtual arrays. (Virtual
|
||
|
arrays mean arrays that utilize disk space).
|
||
|
Another possibility is using TurboPower Software's (the usual
|
||
|
disclaimer applies) commercial Turbo Professional (don't confuse
|
||
|
with Borland's Turbo Professional) package. It has facilities for
|
||
|
huge arrays, but they involve much more overhead than Kent Porter's
|
||
|
excellent method.
|
||
|
|
||
|
(* =================================================================
|
||
|
My code below is based on a UseNet posting in the late
|
||
|
comp.lang.pascal by Naji Mouawad nmouawad@watmath.waterloo.edu.
|
||
|
Naji's idea was for a vector, my adaptation is for a
|
||
|
two-dimensional matrix. The realization of the idea is simpler
|
||
|
than the one presented by Kent Porter in Dr.Dobb's Journal, March
|
||
|
1988. (Is something wrong, this is experimental.)
|
||
|
================================================================= *)
|
||
|
{}
|
||
|
const maxm = 150;
|
||
|
maxn = 250;
|
||
|
{}
|
||
|
type BigVectorType = array [1..maxn] of real;
|
||
|
BigMatrixType = array [1..maxm] of ^BigVectorType;
|
||
|
{}
|
||
|
var BigAPtr : BigMatrixType;
|
||
|
{}
|
||
|
(* Create the dynamic variables *)
|
||
|
procedure MAKEBIG;
|
||
|
var i : word;
|
||
|
heapNeeded : longint;
|
||
|
begin
|
||
|
heapNeeded := maxm * maxn * SizeOf(real) + maxm * 4 + 8196;
|
||
|
if (MaxAvail <= heapNeeded) then
|
||
|
begin writeln ('Out of memory'); halt; end;
|
||
|
for i := 1 to maxm do New (BigAPtr[i]);
|
||
|
end; (* makebig *)
|
||
|
{}
|
||
|
(* Test that it works *)
|
||
|
procedure TEST;
|
||
|
var i, j : word;
|
||
|
begin
|
||
|
for i := 1 to maxm do
|
||
|
for j := 1 to maxn do
|
||
|
BigAPtr[i]^[j] := i * j;
|
||
|
{}
|
||
|
writeln (BigAPtr[5]^[7] : 0:0);
|
||
|
writeln (BigAPtr[maxm]^[maxn] : 0:0);
|
||
|
end; (* test *)
|
||
|
{}
|
||
|
(* The main program *)
|
||
|
begin
|
||
|
writeln ('Big arrays test by Prof. Timo Salmi, Vaasa, Finland');
|
||
|
writeln;
|
||
|
MAKEBIG;
|
||
|
TEST;
|
||
|
end.
|
||
|
(For a better test of the heap than in MAKEBIG see Swan (1989), pp.
|
||
|
462-463.)
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:15 1996
|
||
|
Subject: Testing printer status
|
||
|
|
||
|
15. *****
|
||
|
Q: How can I test that the printer is ready?
|
||
|
|
||
|
A: Strictly speaking there is no guaranteed way to detect the
|
||
|
printer status on a PC. As Brian Key Brian@fantasia.demon.co.uk
|
||
|
wrote "Any book dealing with the PC BIOS support of a printer will
|
||
|
quickly show you that there is no hardware definition which deals
|
||
|
with the printer power status. It simply wasn't designed (and I use
|
||
|
the word loosely!) into the IBM hardware specs."
|
||
|
|
||
|
The usually advocated method in Turbo Pascal is to test the
|
||
|
status of regs.ah after a call to interrupt 17 Hex (the parallel
|
||
|
port driver interrupt), service 02:
|
||
|
regs.dx := PrinterNumber; (* LPT1 = 0 *)
|
||
|
regs.ah := $02; (* var regs : registers, uses DOS *)
|
||
|
Intr ($17,regs); (* Interrupt 17 Hex *)
|
||
|
status := regs.ah (* var status : byte *)
|
||
|
But this is not a good method since the combinations of the status
|
||
|
bits which indicate a ready state can vary from printer to printer
|
||
|
and PC to PC. If you want a list of the status bits, see e.g. Ray
|
||
|
Duncan (1988), Advanced MS-DOS Programming, p. 587. For an example
|
||
|
of a code using interrupt 17 Hex see Douglas Stivison (1986), Turbo
|
||
|
Pascal Library, pp. 118-120. Also see Michael Yester (1989), Using
|
||
|
Turbo Pascal, pp. 494-495.
|
||
|
The more generic alternative is to try to write a #13 to the
|
||
|
printer having the i/o checking off, that is, while {$I-} is in
|
||
|
effect, and testing the IOResult. But then you must first alter the
|
||
|
printer retry times default (and restore it afterwards). Else the
|
||
|
method can take up to a minute instead of an immediate response.
|
||
|
Also, you must have set the FileMode for LPT1 appropriately (and
|
||
|
restore it afterwards). Sounds a bit complicated, but you don't have
|
||
|
to do all this yourself. There is a boolean function "LPTONLFN Get
|
||
|
the online status of the first parallel printer" for this purpose in
|
||
|
my ftp://garbo.uwasa.fi/pc/ts/tspa3470.zip (or whatever version
|
||
|
number is the latest) Turbo Pascal units collection available by
|
||
|
anonymous FTP or mail server from garbo.uwasa.fi.
|
||
|
|
||
|
A2: One potential, somewhat advanced solution is to use the Device
|
||
|
Driver Control (IOCTL) information. Here is the code.
|
||
|
uses Dos;
|
||
|
function PRNSTAFN : boolean;
|
||
|
var regs : registers;
|
||
|
handle : ^word;
|
||
|
f : file;
|
||
|
begin
|
||
|
prnstafn := false;
|
||
|
if swap(Dosversion) < $0200 then exit; { At least MS-DOS 2.0 }
|
||
|
Assign (f, 'prn'); { Printer }
|
||
|
Reset (f);
|
||
|
FillChar (regs, SizeOf(regs), 0); { Just to make sure }
|
||
|
regs.ah := $44; { Function $44 }
|
||
|
regs.al := $07; { Subfunction $07 }
|
||
|
handle := @f; { Establish a file handle }
|
||
|
regs.bx := handle^;
|
||
|
Msdos (regs); { Call interrupt $21 }
|
||
|
Close (f);
|
||
|
if regs.flags and FCarry <> 0 then exit; { Is the carry flag set? }
|
||
|
if regs.al <> $FF then exit; { regs.al = $FF signals success}
|
||
|
prnstafn := true;
|
||
|
end; (* prnstafn *)
|
||
|
{}
|
||
|
begin
|
||
|
if PRNSTAFN then writeln ('Printer ready')
|
||
|
else writeln ('Printer not ready');
|
||
|
readln;
|
||
|
end.
|
||
|
|
||
|
A3: Another advanced method is using ports. This solution is based
|
||
|
on a posting by Joerg Kunze joerg@ang-physik.uni-kiel.de. A warning.
|
||
|
Do not experiment with the port parameters unless you know exactly
|
||
|
what you are doing. A serious loss of data might follow.
|
||
|
function PRNON : boolean;
|
||
|
var dr : word absolute $40:$08;
|
||
|
begin
|
||
|
prnon := port[dr+1] and $18=$18;
|
||
|
end;
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:16 1996
|
||
|
Subject: Clearing the keyboard buffer
|
||
|
|
||
|
16. *****
|
||
|
Q: How can I clear the keyboard type-ahead buffer?
|
||
|
|
||
|
A: Three methods are usually suggested for solving this problem.
|
||
|
a) The first is to use something like
|
||
|
uses Crt;
|
||
|
while KeyPressed do ReadKey;
|
||
|
This kludge-type method has the disadvantage of requiring the Crt
|
||
|
unit. Also, in connection with procedures relying on ReadKey for
|
||
|
input, it may cause havoc on the programs logic.
|
||
|
b) The second method accesses directly the circular keyboard buffer
|
||
|
var head : word absolute $0040:$001A;
|
||
|
tail : word absolute $0040:$001C;
|
||
|
procedure FLUSHKB; begin head := tail; end;
|
||
|
For a slightly different formulation of the same method see Michael
|
||
|
Tischer (1992), PC Intern System Programming, p. 462.
|
||
|
c) The third method is to call interrupt 21Hex (the MS-DOS
|
||
|
interrupt) with the ax register set as $0C00. This method has the
|
||
|
advantage of not being "hard-coded" like the second method, and thus
|
||
|
should be less prone to incompatibility.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:17 1996
|
||
|
Subject: Utilizing expanded memory
|
||
|
|
||
|
17. *****
|
||
|
Q: How can I utilize expanded memory (EMS) in my programs?
|
||
|
|
||
|
A: I have no experience (yet?) on this subject myself, but I can
|
||
|
give you a list of references: Michael Tischer (1990), Turbo Pascal
|
||
|
Internals, Abacus, Chapter 9; Michael Tischer (1992), PC Intern
|
||
|
System Programming, Chapter 12; Stephen O'Brien (1988), Turbo
|
||
|
Pascal, Advanced Programmer's Guide, Borland-Osborne, Chapter 4;
|
||
|
Chris Ohlsen & Gary Stoker (1989), Turbo Pascal Advanced Techniques,
|
||
|
Que, Chapter 11, Robert Jourdain (1992), Programmer's Problem
|
||
|
Solver, 2nd ed., Brady Publishing, pp. 68-87, and, maybe most
|
||
|
importantly, Dorfman & Neuberger, Turbo Pascal Memory Management
|
||
|
Techniques (with lots of code).
|
||
|
Furthermore, Turbo Pascal delivery disks (at least 5.0) contain a
|
||
|
demos.arc archive which includes an ems.pas file.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:18 1996
|
||
|
Subject: Capturing the entire command line
|
||
|
|
||
|
18. *****
|
||
|
Q: How can I obtain the entire command line (spaces and all)?
|
||
|
|
||
|
A: ParamCount and ParamStr are for parsed parts of the command line
|
||
|
and cannot be used to get the command line exactly as it was. See
|
||
|
what happens if you try to capture
|
||
|
"Hello. I'm here"
|
||
|
you'll end up with a false number of blanks. For obtaining the
|
||
|
command line unaltered use
|
||
|
type CommandLineType = string[127];
|
||
|
var CommandLinePtr : ^CommandLineType;
|
||
|
begin
|
||
|
CommandLinePtr := Ptr(PrefixSeg, $80);
|
||
|
writeln (CommandLinePtr^);
|
||
|
end;
|
||
|
A warning. If you want to get this correct (the same goes for TP's
|
||
|
own ParamStr and ParamCount) apply them early in your program. At
|
||
|
least they must be used before any disk I/O takes place!
|
||
|
:
|
||
|
A related example demonstrating a function giving the number of
|
||
|
characters on the command line
|
||
|
function CMDNBRFN : byte;
|
||
|
var paramPtr : ^byte;
|
||
|
begin
|
||
|
paramPtr := Ptr (PrefixSeg, $80);
|
||
|
cmdnbrfn := paramPtr^
|
||
|
end; (* cmdnbrfn *)
|
||
|
For the contents of the Program Segment Prefix (PSP) see Tischer,
|
||
|
Michael (1992), PC Intern System Programming, p. 753.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:19 1996
|
||
|
Subject: Redirecting from printer to file
|
||
|
|
||
|
19. *****
|
||
|
Q: How do I redirect text from printer to file in my TP program?
|
||
|
|
||
|
A: Simple. This is done in Turbo Pascal by using the assign command
|
||
|
(think what the word 'assign' implies). Here is a simple example of
|
||
|
the idea.
|
||
|
uses Printer;
|
||
|
begin
|
||
|
assign (lst, 'printer.log');
|
||
|
rewrite (lst);
|
||
|
writeln (lst, 'Hello world');
|
||
|
close (lst);
|
||
|
end.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:20 1996
|
||
|
Subject: Turbo Pascal users are just wimps
|
||
|
|
||
|
20. *****
|
||
|
Q: Turbo Pascal is for wimps. Why don't you use standard Pascal or
|
||
|
better still why don't you use C?
|
||
|
|
||
|
A: These kinds of "real-programmers" statements often reflect what
|
||
|
is called self-over-others attitude, and they are a part of a kind
|
||
|
of a programming lore or cult. Basically, these attitudes waive the
|
||
|
simple fact that one should select one's tools according to the task
|
||
|
at hand, not vice versa. On the other hand one's productivity is
|
||
|
usually best when being able to use tools which one is familiar and
|
||
|
comfortable with. (Note however that the real-programmer's lore is
|
||
|
not really interested in producing results.)
|
||
|
In very rough terms there are two attitudes to programming
|
||
|
languages. They can be seen as tools for writing applications, or
|
||
|
(by surprisingly many) as ends themselves.
|
||
|
If we first look at standard Pascal (versus Turbo Pascal),
|
||
|
considering the language primary and its usage secondary is common.
|
||
|
This results from the history of Pascal, since as we all know it was
|
||
|
originally meant as a means for teaching programming concepts, not
|
||
|
at all for writing applications. But because Pascal turned out to be
|
||
|
useful also for writing applications, it has been extended for some
|
||
|
operating systems, most notably MS-DOS (Turbo Pascal) and VAX/VMS
|
||
|
(VAX Pascal). Both remedy a lot of flaws from the application
|
||
|
programmer's point of view. Most importantly they have a true file
|
||
|
I/O interface, and enhanced string handling. Turbo Pascal (the more
|
||
|
generic of these two) clearly draws from the structure and ideas of
|
||
|
advanced BASICs (and vice versa). While in standard Pascal the
|
||
|
language is an end by itself, for Turbo Pascal the only relevant
|
||
|
issue is its usefulness for writing applications.
|
||
|
One problem that one encounters when moving away from standard
|
||
|
Pascal is the problem of portability. This is a truly serious
|
||
|
problem, since most often extensive rewriting is necessary from
|
||
|
converting say Turbo Pascal to, say, Unix Pascal. I have taken Unix
|
||
|
Pascal as the extreme example, since Unix Pascal is almost nothing
|
||
|
but the standard Pascal having no useful file I/O.
|
||
|
If one considers C, its best aspect from applications point of
|
||
|
view is portability, and its strength for system programming. But it
|
||
|
is not an easy language to learn. Proponents of C also often have
|
||
|
the tendency discussed above, that is seeing the language as
|
||
|
primary, and its utilization as secondary. Now why this tendency,
|
||
|
not only for C, but in general? I've had the opportunity of writing
|
||
|
programs starting from the late 1960's, and one observation I have
|
||
|
made, and often propounded the view is that it is not writing code
|
||
|
that is the really difficult part. What is really difficult it is
|
||
|
coming up with good and original ideas for programs to write. I see
|
||
|
applications as primary, and the tools as secondary. As to Turbo
|
||
|
Pascal, I've written in many languages (including Cobol, Fortran,
|
||
|
several Basics and Pascals, and command languages) and I like Turbo
|
||
|
Pascal because it is one of the most convenient and flexible tools
|
||
|
for writing the kind of applications that I usually write and
|
||
|
distribute for the Public Domain. That is I use Turbo Pascal because
|
||
|
I'm comfortable with it in writing applications, and have thus
|
||
|
gathered a very useful modular library for it over the years, not
|
||
|
because of any inherent value attached to Turbo Pascal per se.
|
||
|
|
||
|
A2: Another, a somewhat resembling line is made up by the arguments
|
||
|
about standards in Pascal which were recycled in the late
|
||
|
comp.lang.pascal time after time. Very often they end up with
|
||
|
purists vs pragmatists arguing about the true or imaginary viles of
|
||
|
using GOTOs. I find all this somewhat futile, although I understand
|
||
|
the academic nature of the background. As you'll recall, Pascal was
|
||
|
first developed for academic teaching programming concepts, not for
|
||
|
any practical programming. That came later, and the ensuing
|
||
|
popularity of Pascal in practical applications must have come as a
|
||
|
surprise way back then. I admit being biased in not sympathizing
|
||
|
with Pascal standard stalwarts. I am far more interested in getting
|
||
|
the job done than in defending a barren orthodoxy.
|
||
|
Since Turbo Pascal version 7.0 introduced the "break" and
|
||
|
"continue" keywords to handle jumps in loops, GOTOs are much easier
|
||
|
to avoid without undue complications.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:21 1996
|
||
|
Subject: Turning off the cursor
|
||
|
|
||
|
21. *****
|
||
|
Q: How do I turn the cursor off?
|
||
|
|
||
|
A: The usually advocated trick for turning the cursor off is to
|
||
|
equate the lower and the upper scan line of the cursor as explained
|
||
|
e.g. in Stephen O'Brien (1988), Turbo Pascal, Advanced Programmer's
|
||
|
Guide.
|
||
|
uses Dos;
|
||
|
var regs : registers;
|
||
|
begin
|
||
|
regs.ax := $0100; (* Service $01 *)
|
||
|
regs.cl := $20; (* Top scan line *)
|
||
|
regs.ch := $20; (* Bottom scan line *)
|
||
|
Intr ($10, regs); (* ROM BIOS video driver interrupt *)
|
||
|
end;
|
||
|
To turn the cursor back on this (and many other) sources suggest
|
||
|
setting regs.ch and regs.cl as 12 and 13 for mono screen, and 6 and
|
||
|
7 for others.
|
||
|
This is not a good solution since it is equipment dependent, and
|
||
|
may thus produce unexpected results. Better to store the current
|
||
|
scan line settings, and turn off the cursor bit. Below is the code
|
||
|
from ftp://garbo.uwasa.fi/pc/ts/tspa3470.zip (or whatever version
|
||
|
number is the latest) available by anonymous FTP from garbo.uwasa.fi
|
||
|
archives. The general idea is that regs.ch bit 5 toggles the cursor
|
||
|
on / off state. Thus to set the cursor off, apply
|
||
|
regs.ch := regs.ch or $20; (* $20 = 00100000 *)
|
||
|
and to set it on, apply
|
||
|
regs.ch := regs.ch and $DF; (* $DF = 11011111 *)
|
||
|
(* From TSUNTE unit, which also has a CURSON procedure *)
|
||
|
procedure CURSOFF;
|
||
|
var regs : registers;
|
||
|
begin
|
||
|
FillChar (regs, SizeOf(regs), 0); (* Initialize, a precaution *)
|
||
|
{... find out the current cursor size (regs.ch, regs.cl) ...}
|
||
|
regs.ah := $03;
|
||
|
regs.bh := $00; (* page 1, superfluous because of FillChar *)
|
||
|
Intr ($10, regs); (* ROM BIOS video driver interrupt *)
|
||
|
{... turn off the cursor without changing its size ...}
|
||
|
regs.ah := $01; (* Below are bits 76543210 *)
|
||
|
regs.ch := regs.ch or $20; (* Turn on bit 5; $20 = 00100000 *)
|
||
|
Intr ($10, regs);
|
||
|
end; (* cursoff *)
|
||
|
|
||
|
A2: A comment from Leonard Erickson leonard@qiclab.scn.rain.com.
|
||
|
Reprinted with permission. There's a *reason* those sources don't
|
||
|
suggest storing the current scan line settings. On IBM Monochrome
|
||
|
Display Adapters (MDA), Hercules Graphics Cards, and the various
|
||
|
clones of both, the "read cursor start and end scan lines" function
|
||
|
*always* returns the same values. And those values are almost never
|
||
|
the actual settings. Most cards return 6 & 7. Some return 12 & 13.
|
||
|
But they return these values even if the cursor has been set to
|
||
|
something else.
|
||
|
So you are *still* stuck with checking the hardware type if the
|
||
|
screen is in mode 7.
|
||
|
See the Interrupt list for details on this mess.
|
||
|
|
||
|
A3: Another solution that has been suggested is putting the cursor
|
||
|
outside the screen. But you can't do this with the Crt's GotoXY
|
||
|
procedure, since it ignores off screen positions, as observed by
|
||
|
Luiz Marques luiz.marques%mandic@ibase.org.br. You'll need to use
|
||
|
video interrupt, that is $10, function $02. Fair enough, but
|
||
|
somewhat complicated. Besides, how do you write on the screen if the
|
||
|
cursor position is off it?
|
||
|
|
||
|
A4: This snippet of disabling the cursor at hardware level was
|
||
|
posted to comp.lang.pascal (now news:comp.lang.pascal.borland) by
|
||
|
JAB@ib.rl.ac.uk. Corrections due to John Stockton. John also points
|
||
|
out that this probably needs a VGA to work.
|
||
|
procedure turn_off_cursor;
|
||
|
var num : word;
|
||
|
begin
|
||
|
port[$03D4]:=$0A; num:=port[$03D5];
|
||
|
port[$03D4]:=$0A; port[$03D5]:=num or 32;
|
||
|
end;
|
||
|
{}
|
||
|
procedure turn_on_cursor;
|
||
|
var num : word;
|
||
|
begin
|
||
|
port[$03D4]:=$0A; num:=port[$03D5];
|
||
|
port[$03D4]:=$0A; port[$03D5]:=num and not 32;
|
||
|
end;
|
||
|
{}
|
||
|
procedure toggle_cursor;
|
||
|
var num : word;
|
||
|
begin
|
||
|
port[$03D4]:=$0A; num:=port[$03D5];
|
||
|
port[$03D4]:=$0A; port[$03D5]:=num xor 32;
|
||
|
end;
|
||
|
|
||
|
A5: (Not to be taken seriously). Simple, turn off your computer and
|
||
|
the cursor stops showing :-).
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:22 1996
|
||
|
Subject: Finding the roots of a polynomial
|
||
|
|
||
|
22. *****
|
||
|
Q: How to find all roots of a polynomial?
|
||
|
|
||
|
A: If you need the code, see Turbo Pascal Numerical Toolbox and/or
|
||
|
Press & Flannery & Teukolsky & Vetterling (1986), Numerical Recipes,
|
||
|
The Art of Scientific Computing, Cambridge University Press. The
|
||
|
Numerical Recipes codes are available as /pc/turbopas/nrpas13.zip
|
||
|
(big, 404k!). If you just need to solve such a task (without code
|
||
|
available), get ftp://garbo.uwasa.fi/pc/ts/tsnum12.zip (or whatever
|
||
|
version number is the latest) from garbo.uwasa.fi archives by
|
||
|
anonymous FTP or mail server.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:23 1996
|
||
|
Subject: Pascal homework on the net
|
||
|
|
||
|
23. *****
|
||
|
Q: What is all this talk about "Pascal homework on the net"?
|
||
|
|
||
|
A: This is one of the subjects that seems to pop up at regular
|
||
|
intervals, cause some heated exchange for awhile, and then die down
|
||
|
again leaving some users harboring warranted or unwarranted grudges.
|
||
|
Some posters to comp.lang.pascal (later comp.lang.pascal.borland)
|
||
|
have been very concerned of the possibility that the questions posed
|
||
|
on the net are related to students' homework assignments. I don't
|
||
|
have any unequivocal answers or a clear-cut stand on this question,
|
||
|
just some comments.
|
||
|
The most important task of a newsgroup like comp.lang.pascal.borland
|
||
|
is the exchange of information between the users. If you think that
|
||
|
what you are going to post is interesting and useful to the group,
|
||
|
that should be your topmost criterion.
|
||
|
If it is really a student that wants his/her work done on the net
|
||
|
(how do we know anyway?) also consider the following fact. Being
|
||
|
able to use a newsgroup amounts to having learned at least something
|
||
|
about using computers, and that is something per se.
|
||
|
Even if the student may short-sightedly not realize it, providing
|
||
|
ALL the code for a student's homework is detrimental to the student,
|
||
|
since it is she/he that foregoes understanding what he/she is doing.
|
||
|
The group should not condone outright cheating. Being (partly) a
|
||
|
teacher myself, I understand also this view.
|
||
|
If a student is stuck with a problem in his/her code, I don't see
|
||
|
any real harm in helping out, especially if the problem has general
|
||
|
interest. Instructing is what teaching is about, anyway, isn't it?
|
||
|
But, on the other hand, I must admit that I find a it rather
|
||
|
flagrant if a posting asks for something of the kind "I have to
|
||
|
complete my term assignment to write a function plotter by the end
|
||
|
of this month. Send me the code, since I'm too busy with my other
|
||
|
exams to write it myself" (a true quote).
|
||
|
Finally, let's not jump to premature conclusions about anyone's
|
||
|
questions. That's what most often triggers off a vicious circle of
|
||
|
flaming.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:24 1996
|
||
|
Subject: Linking bgi drivers into executables
|
||
|
|
||
|
24. *****
|
||
|
Q: How can I link graphics drivers directly into my executable?
|
||
|
|
||
|
A: This is a complicated, yet a very useful task, because then you
|
||
|
won't need any separate graphics drivers (or fonts) to go separately
|
||
|
along with your program. Unfortunately, Turbo Pascal documentation
|
||
|
on this task is a bit confusing.
|
||
|
1) The very first step is to get the necessary files from the
|
||
|
Turbo Pascal disks to your working directory. To start with, you'll
|
||
|
need binobj.exe and all the .bgi files.
|
||
|
2) Run the following commands (best to place them in a batch,
|
||
|
call it e.g. makeobj.bat):
|
||
|
binobj cga.bgi cga CGADriverProc
|
||
|
binobj egavga.bgi egavga EGAVGADriverProc
|
||
|
binobj herc.bgi herc HercDriverProc
|
||
|
binobj pc3270.bgi pc3270 PC3270DriverProc
|
||
|
binobj att.bgi att ATTDriverProc
|
||
|
rem binobj ibm8514.bgi 8514 IBM8514DriverProc
|
||
|
3) Get drivers.pas from the Turbo Pascal disk and compile it with
|
||
|
Turbo Pascal. Now you have a drivers.tpu unit which contains all the
|
||
|
graphics drivers.
|
||
|
4) Now you won't need the .bgi and the .obj files any more. You
|
||
|
may delete them from your working directory.
|
||
|
5) Write your graphics program in the usual manner. But before
|
||
|
putting your program in the graphics mode use the following
|
||
|
procedure if you want to link e.g. the EGAVGA graphics driver
|
||
|
directly into your executable. (Link just the driver(s) you'll need,
|
||
|
since the drivers take up a lot of space.)
|
||
|
uses Graph, Drivers;
|
||
|
:
|
||
|
procedure EGAVGA2EXE;
|
||
|
begin
|
||
|
if RegisterBGIdriver(@EGAVGADriverProc) < 0 then
|
||
|
begin
|
||
|
writeln ('EGA/VGA: ', GraphErrorMsg(GraphResult));
|
||
|
halt(1);
|
||
|
end;
|
||
|
end; (* egavga2exe *)
|
||
|
:
|
||
|
Linking the .bgi and .chr drivers is also covered in Swan (1989),
|
||
|
Mastering Turbo Pascal 5.5 pp. 355-359 and Mitchell (1993), Borland
|
||
|
Pascal Developer's Guide , pp. 221-229.
|
||
|
If you have Turbo Pascal 7.0 its help function gives you an
|
||
|
example code. One way of getting at it is the following. In the
|
||
|
Turbo Pascal IDE (that is in the editor) type RegisterBGIdriver.
|
||
|
Then place the cursor on it and press alt-F1 for help of that
|
||
|
keyword. Press alt-F10 and select "Copy example". Press first <ESC>
|
||
|
then alt-F10 and select Paste. The example code is pasted within
|
||
|
your program for you to study.
|
||
|
Incidentally, although this is a slightly different matter, you
|
||
|
can link any data material into your executable. See Stephen
|
||
|
O'Brien, (1988), Turbo Pascal, Advanced Programmer's Guide, pp. 31 -
|
||
|
35 for more details.
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
From ts@uwasa.fi Sat Mar 30 00:00:25 1996
|
||
|
Subject: Trapping runtime errors
|
||
|
|
||
|
25. *****
|
||
|
Q: How can I trap a runtime error?
|
||
|
|
||
|
A: What you are probably asking for is a method writing a program
|
||
|
termination routine of your own. To do this, you have to replace
|
||
|
Turbo Pascal's ExitProc with your own customized exec procedure.
|
||
|
Several Turbo Pascal text books show ho to do this. See e.g. Tom
|
||
|
Swan (1989), Mastering Turbo Pascal 5.5, Third edition, Hayden
|
||
|
Books, pp. 440-454; Michael Yester (1989), Using Turbo Pascal, Que,
|
||
|
pp. 376-382; Stephen O'Brien (1988), Turbo Pascal, Advanced
|
||
|
Programmer's Guide, pp. 28-30; Tom Rugg & Phil Feldman (1989), Turbo
|
||
|
Pascal Programmer's Toolkit, Que, pp. 510-515. Here is an example
|
||
|
var OldExitProcAddress : Pointer;
|
||
|
x : real;
|
||
|
{$F+} procedure MyExitProcedure; {$F-}
|
||
|
begin
|
||
|
if ErrorAddr <> nil then
|
||
|
begin
|
||
|
writeln ('Runtime error number ', ExitCode, ' has occurred');
|
||
|
writeln ('The error address in decimal is ',
|
||
|
Seg(ErrorAddr^):5,':',Ofs(ErrorAddr^):5);
|
||
|
writeln ('That''s all folks, bye bye');
|
||
|
ErrorAddr := nil;
|
||
|
ExitCode := 0;
|
||
|
end;
|
||
|
{... Restore the pointer to the original exit procedure ...}
|
||
|
ExitProc := OldExitProcAddress;
|
||
|
end; (* MyExitProcedure *)
|
||
|
(* Main *)
|
||
|
begin
|
||
|
OldExitProcAddress := ExitProc;
|
||
|
ExitProc := @MyExitProcedure;
|
||
|
x := 7.0; writeln (1.0/x);
|
||
|
x := 0.0; writeln (1.0/x); {The trap}
|
||
|
x := 7.0; writeln (4.0/x); {We won't get this far}
|
||
|
end.
|
||
|
:
|
||
|
Actually, I utilize this idea in my /pc/ts/tspa3470.zip Turbo Pascal
|
||
|
units collection, which includes a TSERR.TPU. If you put TSERR in
|
||
|
your program's uses statement, all the run time errors will be given
|
||
|
verbally besides the usual, cryptic error number. That's all there
|
||
|
is to it. That is, the inclusion to the uses statement to your main
|
||
|
program (if you have the program in several units) is all you have
|
||
|
to do to enable this handy feature.
|
||
|
:
|
||
|
Hans.Siemons@f149.n512.z2.fidonet.org notes "This line:
|
||
|
ExitProc := OldExitProcAddress;
|
||
|
should IMHO never be placed at the end of your exit handler. If for
|
||
|
one reason or another your own handler should cause a runtime error,
|
||
|
it would go in an endless loop. If the first statement restores the
|
||
|
exit chain, this can never happen. I do agree that is not very
|
||
|
likely that your exit handler produces any runtime error, but it
|
||
|
performs I/O, and since it is located in a FAQ, people are bound to
|
||
|
use, and maybe extend it with more tricky stuff."
|
||
|
--------------------------------------------------------------------
|
||
|
|