home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
clipper
/
doors10.zip
/
DOORS.501
/
DOORS.DOC
next >
Wrap
Text File
|
1993-06-13
|
76KB
|
1,804 lines
▄▄▄▄▄▄▄ Keep our Earth green,
██ █ Our air clean,
██ .█ █▀▀▀▀ and code lean and mean.
██ █ ▄▄▄▄▄ ▄▄▄▄▄ █▄▄▄▄ █▄▄▄▄
██ █ █ █ █ █ █ ▀ █ Re-cycle and RE - USE.
▀▀▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀ ▀▀▀▀▀
Copyright (C) 1991, 92, 93
Codesmythe, Inc.
All Rights Reserved.
CSERVE [73057,3204]
(214) 319-8517
DOORSxxx.ZIP License
Copyright (c) 1993 Codesmythe, Inc. All Rights Reserved.
This product has been redered to the PUBLIC DOMAIN. You are free to
use, copy and distribute DOORSxxx.ZIP providing that:
NO FEE IS CHARGED FOR USE, COPYING OR DISTRIBUTION.
IT IS NOT MODIFIED IN ANY WAY.
ALL DOCUMENTATION FILES ARE (UNMODIFIED) AND ACCOMPANY ALL COPIES.
This program is provided AS IS without any warranty, expressed or
implied, including but not limited to fitness for a particular
purpose.
dBASE II, dBASE III, dBASE IV are trademarks of Ashton-Tate. Clipper is a
trademark of Computer Associates. FoxBASE, FoxBASE+ and FoxPro are
trademarks of Microsoft Corp.
For Warrantee information please refer to LICENSE.DOC
DOORS.LIB
TABLE of CONTENTS
TOPIC PAGE
──────────────────────────────────────────────────────────────────────
I. INTRODUCTION TO / PURPOSE OF DOORS 1
II. FEATURES OF DOORS 1
III. USING DOORS 2
A. Installation. 2
B. Out of the Box. 2
C. HOW THE LIBRARY IS ORGANIZED (DF VS. DP VS. DB) 3
D. INCLUDING HEADER FILES and 1ST Level Optimization. 3
E. REGS and SREGS 5
F. LINKING WITH DOORS 5
IV. MULTIPLE DEVELOPER LEVELS. 6
A. USING HEADER FILES 6
B. CHANGING HEADER FILES 7
1. MODIFYING #XTRANSLATES 8
2. CREATING #XTRANSLATES 8
C. CREATING NEW LIBRARY FUNCTIONS 8
D. OPTIMIZING for SIZE or SPEED 8
V. SOME PITFALLS IN USING DOORS 9
A. DONT GET BIT BY AN INTERRUPT 9
B. WARNINGS ON INLINE OPERATORS (++) 9
C. SCOPE 9
VI. MODIFYING SUPPLIED CODE 10
A. WHY? 10
B. WHEN? 10
C. MAINTAINABILITY 10
VII. ADVANCED TOPICS. 11
A. Networking 11
C. Fonts 11
D. Mouse 11
E. Memory Accessing 11
VIII. FUNCTIONS. 12
A. DF_DOS. 12
B. DF_AT. 14
C. DF_PSEC() 15
D. DF_ASCVAL() 15
i
TABLE of CONTENTS
TOPIC PAGE
──────────────────────────────────────────────────────────────────────
IX. DOS.CH DP_ Pseudo Function Calls. 16
A. dp_ver() 16
B. dp_curdrive() 16
C. dp_driveno(<x>) 17
D. dp_changedrive(<x>) 17
E. dp_lastdrive() 17
F. dp_drivesize([<x>]) 18
G. dp_curdir([<x>]) 18
H. dp_mkdir(<x>) 19
I. dp_rmdir(<x>) 19
J. dp_chdir(<x>) 19
K. dp_getdate() 20
L. dp_setdate( <ddate> [,<day> ,<yr>] ) 20
M. dp_gettime() 21
N. dp_settime( <hr> [,<min> ] [, <sec>] ) 21
O. dp_isverify() 22
P. dp_setverify(<x>) 23
Q. dp_getpsp() => 23
R. dp_getcmdline() 23
S. dp_maxfiles() 24
X. THE FUTURE of DOORS. 25
APPENDICIES 26
ii
DOORS.LIB
I. INTRODUCTION TO / PURPOSE OF DOORS
Thank you for purchasing Doors, the only user expandable
programming library for Clipper. Doors is a library that gives Clipper
programmers access to low level operating system calls and routines to
allow a graceful extension to the capabilities of their Clipper
programs. At the heart of Doors are a select number of reliable and
efficient routines. These provide a firm foundation for a library
that can be molded to meet your specific needs. Before you can start
using Doors to its full potential, you need to be introduced to the
ideas behind Doors and the way Doors works. The following sections are
designed to give you a running start in using Doors. If you would
prefer to skip the manual and simply "wing it" -- at least read the
overview and consult the online documentation when necessary. Thanks
again for your support. We at Codesmythe hope that Doors will play a
large role in the development of your Clipper applications.
II. FEATURES OF DOORS
Doors has a lot to offer because of it's size, relative speed, and
extensibility. Doors is written almost entirely in assembly language,
and it's size and speed should reflect this. Doors is also granular,
i.e. there are few interlibrary calls, by design. This granularity
reduces the size of the executable because only what is directly called
is linked.
Doors is the first User Definable Library. We say User
Definable because one doesn't NEED to LINK precompiled code to further
extend the library. There are very few true Doors functions. Most of
the Doors routines are #xtranslates (functions beginning with DP --
Doors Preprocessed functions) which are contained in header files. You
can construct similar #xtranslates or #defines that will take you in
any direction you need to go. The headers supplied with Doors are a
collection of the most commonly used interrupt routines. Which
routines you add to the library is totally up to you--all you need is a
good DOS reference and you can add any DOS interrupt routine to your
clipper program as you need or desire it.
OR you can register the software and get the .ch files and support
tools that have already been developed and tested in distributed
applications. The point NOW you have a choice.
PAGE 1
III. USING DOORS
A. Installation.
It is highly recommended to unzip the DOORS.ZIP file used for
distribution in it's own subdirectory. At that point copy the .lib
files to you clipper lib directory (probably C:\CLIPPER5\LIB ).
Then modify the environment variable INCLUDE to point to the doors
directory you created. This keeps the .ch files seperate and easily
maintained.
For example, if your include files are in C:\CLIPPER5\INCLUDE and
you setup doors in C:\DOORS, then modify your .bat file that sets up
the clipper environment with :
SET INCLUDE=C:\CLIPPER5\INCLUDE;C:\DOORS
B. Out of the Box.
Now that you're set up, using DOORS 'out of the box' is really a
matter of including the header file and typing the PSEUDO function
name for the servive you desire. No other set up is needed. Oh, you
can make new .ch files and additionally optimize the speed of doors,
but the basic steps are as identified above.
Here's a simple test function for displaying the current directory:
#include "dos.ch"
func test()
? dp_curdir()
return nil
Now pop this into a file and compile it. Link with :
RTLINK fi xxx lib doors
or
BLINKER fi xxx lib doors
(or Blinker fi xxx allocate doors ) (Great for saving some
space).
DF_DOS() is the most important function in the doors
libary. Many of the functions in Doors are actually #xtranslates
that are contained within header files. These extremely small
#xtranslates will give you access to commonly used interrupt
routines without having to consult a DOS reference manual on how to
call a specific interrupt. Using these #xtranslates as your model
you can extend Doors in any direction you want. Doors gives you
priveledged access to the operating system. Doors allows you to call
ALMOST any DOS interrupt from Clipper using one function --
DF_DOS(). This one function is the cornerstone of the Doors
library. These #xtranslates call DF_DOS() for their interrupt
services. Doors is designed to be user definable because you can use
DF_DOS() as the bases for many different functions and codeblocks.
Doors provides all of this without violating the integrity of
Clipper because it follows Nantucket's standards for the Clipper
Extend system, to the letter. Doors should be primarily compatable
with all versions of Clipper after 5.0.
PAGE 2
Using Doors is quite easy. First, find the Doors function you need
using the appendix, making note of the required header file(s).
The online documentation also includes the proper
syntax for using the routine and an example. After including the
proper header file(s) ( and optionally optimizing by declaring the
proper local variables), simply make the call to the Doors routine.
When linking your program, you need to include the Doors library,
ie: cl myprog
rtlink fi myprog lib doors
or blinker fi myprog lib doors (BLINKER 1.4/5)
or blinker fi myprog allocate doors, extend (BLINKER 2.0+)
C. HOW THE LIBRARY IS ORGANIZED (DF VS. DP VS. DB)
Throughout this manual, you will see references to Doors functions,
Doors Clipper Functions, and Doors DP functions. Doors functions (they
are the functions that start with a DF_ ) are the functions that are
actually complied in the library itself. There are only 40 or less of
these assembly/Clipper language routines. Doors functions can
be called by your own functions and by Doors Clipper and Doors DP
functions. Some Doors Clipper functions are also compiled into the
library. The Doors DP functions are not really part of the actual
library, but instead are found in the Doors include files. These
PSEUDO-functions are #XTRANSLATES (DP means Doors Preprocessed).
These DP functions are comprised of doors DB (doors block definitions).
Why codeblocks and xtranslates? The intrinsic difference between
doors and ALL other libraries is that it is A USER DEFINABLE
LIBRARY, it is OPTIMIZABLE (with a little work can be made faster),
very GRANULAR (what you don't call won't get linked in), and USER
MODIFIABLE. Doors is an interrupt call library.
Doors is user definable by creating header files of the DATA to be
used with a dos interrupt, Clipper can be used to place the data
and an associated codeblock ON DISK until needed. This provides you
with the information you need NOT in a FUNCTION in a symbol table
which has to be examined, but in a codeblock in the local symbol
space for fast retrevial.
Additionally, if something doesn't work on a machine the way it
should OR heaven forbid, Microsoft or IBM decides to change the
behavior of an INTERNAL DOS interrupt, you WON'T have to wait on me,
YOU can fix it! You have the Clipper compatable code and the dos()
funciton to do it. Simply copy the .ch involved and modify the call
to the new data.
Additionally, because of the NATURE of a codeblocks storage
requirments, you have COMPLETE freedom to pursue learing more about
DOS and Clipper. Additionally, you have two more ways of OPTIMIZING
the behavior of your calls. See Section III.D for additional details
on the way to optimize doors.
D. INCLUDING HEADER FILES and 1ST Level Optimization.
To find out which header files to include for your Doors calls look
at appendixes, or the norton guides, for which header files reference
the 'DP_XXX()' calls. Remember, DF_XXX() are for true functions.
PAGE 3
One can gain a level of better speed and smaller size by a
little work. Lets go back to the CURDIR example from earlier.
#define I_CONTROLL
#include "DOS.CH"
func test()
local regs
local sregs
? dp_curdir()
RETURN nil
Doesn't look much different, does it? Just three line changes.
What's that "#define I_CONTROLL" thingy? Thats an identifier that
the include files recognize. It's telling the Clipper preprocessor
that you've read the documentation and DEFINED the needed vars for
allowing the optimized versions of the xtranslates to run.
Optimized versions? Won't that enlarge the amount of symbol space
at compile time? Only slightly, as ONLY ONE set gets defined at compile
time.
What gets defined? The include files build codeblock and codeblock
evaluation definitions.
Codeblocks? Yes. This way you have complete flexibility in your
prgs for the way to capture and express the methods and algorithms
now available to a compiler with advanced parsing. You could just as
easily have done this:
local regs
local sregs
local mycurdir := db_curdir
? eval( db_curdir)
return nil
While these function will do the same as the first, it is at least
7-10% faster and 2K smaller than if built without the two locals.
We've done a fair amount of 'C' and ASM work. THREE of the things
we've learned in DOS to keep our code smaller and more maintainable
is REUSE DEBUGED CODE, REUSE DEBUGGED CODE, and REUSE DEBUGGED CODE.
It IS faster to have a DEDICATED function hide the data, IF IT ISN'T
in an OVERLAY! It will not contribute to a smaller .exe and will add
overhead in the form of maintenance, especially if it's only called
once or twice per .exe. Therefore, this library is designed with
you, the developer, in mind.
When you need to get something working, take the shortcuts and use
the includes 'out of the box'. When you need more speed and size
optimization, just follow these examples.
PAGE 4
III. E. REGS and SREGS.
Regs and SREGS are var names used throughout the DOORS include
systems. These var take their names from the MICROSFT introduced
function INT86() and INT86X() funcitons. These two functions are to
'C' programmers what DF_DOS() is to Clipper. In 'C' one need only
fill the specified fields of a named REGS union ( and a SREGS struct
if calling int86x()) to pass information to the CPU for calling an
internal DOS function.
Optionally you could use the defines in REGS.CH.
USES <scope> REGISTERS
USES <scope> SEGMENT REGISTERS
where <scope> may be LOCAL, STATIC, PUBLIC or PRIVATE. The POINT is
to define the vars REGS (and optionally SREGS) if you wish to gain
the 1 level of optimization and to define I_CONTROLL. If I_CONTROLL
is defined, IT IS YOUR RESPONSIBILITY TO CONTROL THE APPLICATION!!!
The reason for doing this is that the call to DF_DOS() passes
these variables by reference. This is how the results of the function
call are returned to your Clipper application. It is HIGHLY
RECOMMENDED to use locals in all cases for 3 reasons.
1. Scoping.
Having local scope means that after a call to DF_DOS() any
other call to DF_DOS() not in the same SCOPE of code
PRESERVES the contents of the return value of the last local
call.
2. Automatic memory management.
Once the function that makes the DF_DOS() call completes ALL
locals will be recollected into the FREE MEMORY POOL
automatically.
3. Speed.
It is simply faster to access LOCALs / STATICS throuht
the modules' symbol table rather than PUBLICs or PRIVATEs
through the PUBLIC symbol table. Local symbol tables are
discarded upon exit.
Many Doors functions use these same variables so if you make
several calls to Doors routines from within a block of code, make sure
you preserve a copy if you need one to keep track of which variables
are being changed. (For details, see Section V., C)
F. LINKING WITH DOORS
Doors has been developed over the last 2+ years. Seems like
every time some stability was gained, a new feature was added to the
linkers which needed further testing. We've worked hard nights,
evenings and weekends to try bring a LIBRARY of choice to the Clipper
Community. One we believe will prove to be smaller and more useful
than anything previously seen.
PAGE 5
IV. MULTIPLE DEVELOPER LEVELS.
One nice aspect of Doors is that, in addition to being able to be
used right out of the box, it can also be modified and extended if you
need more than what has been already provided. Thus there are several
levels to using doors in your development. This may range from simply
using what has already been provided to extending Doors to the limits
of your imagination.
A. USING HEADER FILES
At first, most Clipper programmers will be satisfied in just using
what has already been provided in Doors. At this preliminary level,
the most important things to worry about are the header files. The
header files contain the DB_ blocks and DP_ functions (that are not
in the library itself) and the #defines that go along with these
functions. Very little knowledge of the Clipper preprocessor is
needed to use Doors in this manner. Your main job in using Doors
will be making sure that you have included the proper header files
( and optionally defined the proper local variables) before calling
a Doors function.
A simple illustration was given in Section III.B with some
optimizaiton shown in Section III.D. Compile that example with
the /p switch. This tells the compiler to generate a .PPO file with
the translated code. The examle above should generate a line like
this:
? EVAL({|z| IIF( z = NIL, z := 0, z := ASC(SUBSTR(UPPER(z),1,1))-64),;
REGS := { B2INT(x47),,,z,,,}, SREGS := {REPLICATE(CHR(0),64),}, ;
IIF( df_dos( x21, @REGS , @SREGS ), DS, "") } , )
Very strange to look at isn't it? Well this is just the
evaluation of a percompiled codeblock which says create a local
parameter (z). If z is nil there was nothing passed so set it to
zero for the INT 21, subfunction x47 (decimal 71 ) call.
What the heck is an x47? Because of the structure of the DOS
operating system and the documentation for it, I constucted a
header file with x0 to xFF defined so I didn't have to translate
the HEX notation to decimal in my head and worry every time I read
it if I had specified the correct value. See HEX.CH if you wish
to know more.
REGS := { B2INT(x47),,,z,,,}, SREGS := {REPLICATE(CHR(0),64),}, ;
PAGE 6
To continue, the var REGS is assigned an array of 7 elements,
where each element represents one of the 9 primary CPU registers.
Why only 7 elements, well just as it isn't nice to fool MOTHER NATURE
it ISN'T nice to fool with the stack frame pointers, BP and SP. So
they aren't referenced ( althought BP is settable, for this call
it's not needed). SP isn't settable. You may pass A flag
setting, but the current code won't allow you to set it. The
registers which you have priveledged access to are (NOTE the
underscores used for references) :
_AX, _BX, _CX, _DX, _SI, _DI, _FLAGS [, _BP] ( See, 7 [8]!)
[_AH,_AL] The high register of _AX to _DX and the low are
individually accessable and AFFECT the _AX value.
[_BH,_BL]
[_CH,_CL]
[_DH,_DL]
The next var is SREGS and with it you are allowed to access up to
two strings for the interrup requests. The first is _DS and the
second is _ES. This is how strings and structures for files,
filename, and other resources are passed and returned. Also, note
that in the DF_DOS() call itself the arrays are passed by REFERENCE
(use the @ symbol). This is how DF_DOS() returns the results and
additionally how you will get information back on what happened.
DF_DOS() is priveledged, so you know if an error occured upon
return, as ERRORSYS() will NOT get called. This gives you a great
deal of power as you don't have to modify ERRORSYS() to TAKE DIRECT
CORRECTIVE ACTION as you see fit, or igore the return and process some
other condition.
You should see by now that DF_DOS() returns a TRUE/FALSE status
depending upon the result of the operation requested. So, I put this
call into an immediate IIF() to return the contents of _DS if a true
was returned ( See the replicate( chr(0) in initializing the call) or
an empty string otherwise.
You will see and learn as much about the nature of the DOS
operating system as YOU choose. With DOORs, you have more freedom,
with comlete access to a depth NEVER before shared by ANY developer
with the PRIVELEDGE of DIRECT ACCESS to the INNER CIRCLE of the CPU.
B. CHANGING HEADER FILES
As you become more comfortable with using Doors, you might become
curious as to how Doors does it's job. This is where you need to
know more about what is in the header files. Understanding the header
files is the key to extending Doors. You will need some knowledge of
the Clipper preprocessor to modify Doors's header files because
#xtranslates and #defines are used heavily. If you ever have to
modify a Doors function that uses DF_DOS(), it would be wise to
consult a DOS manual about calling a particular interrupt. If you
don't have such a manual, there is a list of several good ones in
Appendix D.
PAGE 7
1. MODIFYING #XTRANSLATES
Learning how to modify the existing #xtranslates is the first
step in learning how to extend Doors. The existing #xtranslates
can be modified to suit your specific needs. It is far easier to
find an #xtranslate that does something close to what you want to
do and modify it than it would be to make your own #xtranslate. Be
sure to document your changes, though, to prevent confusion.
Also, copy the base document BEFORE making changes.
2. CREATING #XTRANSLATES
After you've had some experience modifying #xtranslates, you'll
be ready to write some of your own. Essentially, now this is my design
criteria, it should be a FUNCTION type of return ( I really don't like
COMMANDs as I DON'T know if they successfully completed).
C. CREATING NEW LIBRARY FUNCTIONS
1. Use THE PREPROCESSOR TO CREATE NEW HEADER FILES
2. CREATING NEW FUNCTIONS -- LIB'ED INTO A CUSTOM LIBRARY
D. OPTIMIZING for SIZE or SPEED
By now you should see that including a header with a defined
block in a module or prg repeatedly can add size to you .exe. As
stated, there is a simple method to OPTIMIZING this situation.
1. The default inclusion of a codeblock with an evaluaiton help
optimize for size.
2. The 1St level of optimization is gained by adding speed with the
use of the I_CONTROLL #define and scoped vars REGS and SREGS.
3. The 2nd level of optimization is to create a FUNCTION from the
codeblock that takes the same paramteres and returns the state of
the defined block.
#define I_CONTROLL
#include "DOS.CH"
FUNCTION DF_CURDIR()
local regs
local sregs
return dp_curdir()
/* Done! */
Now you can call df_curdir() like any other funciton you write.
4. The final level of optimization is to rewrite the function
INLINE. For detail and examples please refer to the example in
Appendix E.
PAGE 8
V. SOME PITFALLS IN USING DOORS
A. DONT GET BIT BY AN INTERRUPT
Along with the power that interrupts provide comes the danger that
you could really foul something up by accidently calling the wrong
interrupt. Be careful and pay very close attention when writing the
data passed to these functions. They have proven reliable and quick but,
because something as simple as a typo could lead to disaster, PAY
attention.
Imagine mistakingly calling interrupt 13 subfuntion 7
(format drive) instead of subfunction 8 (find drive parameters).
Such a bug could be disasterous if it was not caught before the
first trial run of the program <g>.
This example is ONLY meant to scare those looking into adding or
adapting the current doors headers or functions. By makeing mistakes,
we learn, since we've learned so much, you can only guess at the number
of mistakes we've make.
B. WARNINGS ON INLINE OPERATORS (++)
When using DP functions, be careful what you pass. The DP_
functions are text substitutions so if you pass expressions that modify
the variables being passed, you could run into trouble. If for
instance you have the following CodeBlock.
#xtranslate getmax(<x>, <y>) => ;
EVAL({|max| IIF( <x> > <y>, max := <x>, max := <y>)})
Imagine what would happen if called this:
c := getmax(a++, b++)
what would have been in the code would be:
c := EVAL({|max| IIF( a++ > b++, max := a++, max := b++)})
and assuming a > b, then a was incremented twice while b was
incremented once. This unintended result can cause some pretty hard to
find bugs. As a rule do not pass parameters that modify themselves
to any #xtranslates.
C. SCOPE
You could inadvertantly pass some extra values to a routine because
they were left in REGS or SREGS from a previous routine. Or call a
DF_DOS() translate for the value to place into the var just after
partially filling the structure.
PAGE 9
VI. MODIFYING SUPPLIED CODE
A. WHY?
The real importance of the supplied headers and source code (to
those which register the product) is in being able to fix oversights
or respond to irregularites within the environments within which we
all must produce code.
Working on 3com I found a condition which was contrary to the
documentation on the 503c cards. The hardware returned failure
codes but the request to the netbios layer worked correctly!!
Further checking indicated that 3com's nb.exe (partial netbios,
returned a version of 0.0 and the network cards id was reversed (a
card with an id of '1234' was returning '4321'! So, I wrote a
3COM_NETID() function and documented it as OVERRIDDING the one in
the library in which I ignored the return status of the hardware
interface and checked the contents of the netbios version to
determine how to evalute the the correct order of the ID to return.
This would not have been possible for them without the source as
a guide!
B. WHEN?
The main reasons are:
1) Something doesn't work as expected, described, or documented.
Heavens forbid that something not work as docuemnted!!!
Since commercial class programmmers NEVER make mistakes it may
never happen that you need to modify the behavior of some define,
directive, or function.
2) Extending the functionality. I've overlooked something or
some new feature comes out (MS DOS 111.2.1, <g>).
C. MAINTAINABILITY
This can be the reason to avoid making small changes. IF you
change a directive or function and put it back into the
directories replacing the current one, you may loose it and have
to undo it on a update or upgrade. ALWAYS, absolutely ALWAYS,
create a secondary subdir and copy the changed file there and put
it in the path (INCLUDEs specifically may be chained). On an
update you have a copy to bring forward or edit easily for the
differences.
(SET INCLUDE=C:\CLIPPER6\INCLUDE;C:\ASPEN;C:\MASM . . . )
PAGE 10
VII. ADVANCED TOPICS.
A. Networking
Thank goodness for the improvements to Netware, Lan Manager, 3+,
and all the smaller market netbios compatable networks available
to the general public. The coming years will see a growing
exansion in the demand for network and group aware software that
resolves, reliably and quickly, the mundane tasks for businesses.
Networking has been found to be quick and simple with the
addition of DOORs to the Clipper environment. Doors has been
designed to be network aware (NOT for a specific Network). The
Microsoft design for device redirection allows the NETWORK
software to hook into the DOS operating system, and therefore
the most common services needed are available as an INT request.
C. Fonts
Yes, Font mapping and manipulation is avialable to registered
users.
D. Mouse
Yes, the mouse is availbe to registered users.
E. Memory Accessing
Yes, DIRECT memory accessing is availble to registered users.
PAGE 11
VIII. FUNCTIONS.
NOTE: Granularity ratings are an indication of the NUMBER of external
references made by a function to other library routines. The
higher the number the more references there are and the WORSE
the link impact.
A. DF_DOS.
SYNTAX: DF_DOS( iInt, @Regs, @Sregs, lTrim1, lTrim2 )
GRANULARITY: 0
ARGUMENTS: iInt REQUIRED - Numeric, valid values 0 to 255
x0 to xFF
aRegs REQUIRED - SIZE 7, all Numerics, EACH REQUIRED
Eight is OPTIONAL
^RHIGHLY RECOMMENDED TO PASS BY REFERENCE^R
^bRegs[1]^b Number to be placed in the CPU's AX Register
^bRegs[2]^b Number to be placed in the CPU's BX Register
^bRegs[3]^b Number to be placed in the CPU's CX Register
^bRegs[4]^b Number to be placed in the CPU's DX Register
^bRegs[5]^b Number to be placed in the CPU's SI Register
^bRegs[6]^b Number to be placed in the CPU's DI Register
^bRegs[7]^b Number to be returned from the CPU's FLAGS Register
^bRegs[7]^b Number to be placed in the CPU's BP Register
Sregs OPTIONAL - Used to pass strings and SEGMENT
registers into the INTERRUPT Call
^bSregs[1]^b Number to be placed in the CPU's DS Register
^bSregs[1]^b Number to be placed in the CPU's ES Register
lTrim1, lTrim2 Either is OPTIONAL and indicate whether to
TRIM() the return in the DS and/or ES
register (Sregs[1] and/or Sregs[2]). Both
defaul to .T.
^rNOTE:^r ^bRegs and Sregs SHOULD Always be passed^b
^bBY REFERENCE so VMM won't swap them to disk^b
^band forget to update them IF there is a delayed^b
^breturn or a deep function CALLSTACK.^b
RETURNS: Logical (TRUE if CARRY FLAG not set, FALSE if CARRY FLAG set )
^uCOMMENTS:^u Could write a thesis (AND maybe I'll go back for a Master's
and do just that) on this function alone. I had the original
concept in August, '90 and started coding it in MS 'C', 6.0.
Well, MICROSOFT wanted Licensing options on the INT86() and INT86x()
functions called out of the library. The first version was about
4 K in size, but ran well. Anyway, I taught myself all about
the DOS interrupt system, MASM 5.10 (ugggggh) and rewrote it.
The version in this library is about 2 times faster, is compatible
with MASM 6.0 (the assembler used for this package) and with
all the string trimming code INLINE is less than 2 K, TOTAL.
PAGE 12
The concept is objective in nature and the function is basically
a translator from CLIPPER structures into CPU values and structures,
and back. You'll find it to be quick. I'm studying how to optimize
it for speed, not just size. There are well over 100 Possible
uses for this function with the array passing and the Network
systems available.
Although the carry flag is generally used to signify the success
of the dos function, be aware that not all dos functions will set
the carry flag, so it's a good idea to also check AX for an error
condition.
The current version is in it's 5th incarnation. But it basically
is the workhorse of the INCLUDE FILE Codeblocks. Why codeblocks?
Entry is in the module SYMBOL Table (More memory for apps). Reusable so
it can be linked into the root to minimize overlay paging.
Objective so that we can use the Code provided by the operating
system, AS IT STANDS (Inheriting Code is Nice, you know it
probably works).
This function doesn't pretend to have the speed of some other
libraries, just better size and STRICT OBEDIENCE to Clipper's
extend system.
There are ^rABSOLUTELY NO INTERNAL^r calls to Clipper. There are
^uZERO Macro's^u, there are ^uZERO xgrabs, xfrees, and xalloc calls^u.
This thing is so small and modular it'll go whereever Clipper
goes. It'll travel NOW as a .OBJ LIB, and Later as a CLASS .DLL.
It's going to be easy to support, and I think of it as the
^bFIRST^b ^RUSER DEFINED LIBRARY^r. Handily, it will expand as
MS DOS expands.
EXAMPLE:
^rFUNCTION CURDRIVE()^r // EXAMPLE ONLY, NOT the recommended
LOCAL REGS // way to do it.
REGS := { B2INT(x19),,,,,,}
// NOTE that arrays is 7 (6 Commas)
// Need them going in if you want
// Something BACK (like the results)
// x19 is Decimal 25, B2INT(x)
// becomes ((25)*256)
// which puts x2500 into AX
RETURN IIF( DF_DOS( x21, @REGS ), CHR(AL+1), "" )
// IF carry not set after the interrupt return
// the char value from the lower half of AX after
// adding 1, else return ""
// AL #defines to (REGS[1]%256)
// which is the lower 8 bits
PAGE 13
^rFUNCITON CURDIR(cDrive)^r
LOCAL REGS, SREGS
REGS := { B2INT(x47),,,ASC(SUBSTR(cDrive,1,1))-1,,,}
// NOTE that arrays are 7 and 2
SREGS := { REPLICATE(CHR(0),64) , } // Just provide a buffer to
// to be filled by the INT request
// FOR SPEED the DF_DOS() function does
// ONLY THE MOST MINIMIAL PARAM TESTING
// You're a Programmer, PASS the correct paramters
// You can break this funciton if really want to,
// OR you can RE-USE it easily by passing correct params
RETURN IIF( DF_DOS( x21, @REGS , @SREGS ), SREGS[1], "") } )
B. DF_AT.
Just like clippers' AT() but much more powerful.
SYNTAX: DF_AT(cChar, cString, iTimes, lNomatch)
GRANULARITY: 0
ARGUMENTS: cChar REQUIRED - character or substring sought
cString REQUIRED - character sting holding substring (maybe)
iTimes OPTIONAL - Numeric, if true scans like RAT()
Defaults to 1, MAX repeat is 127
MIN back repeat is -128
lNomatch OPTIONAL - Logical, (the twist) scan for first
NON matching
RETURNS: iFoundat (Numeric, 0 if not found)
^uCOMMENTS:^u The two main features of this function are that it can
search from either direction and that it can search for the
first matching character or the xth NON matching character.
These features are controlled by the two options iTimes and
lNomatch. If no paramaters are passed for these flags, they
will default to 1 and false and the function will search
fowards for the first matching character. There are times,
however, when setting these flags can greatly simplify a
problem. If for instance, you have a displayable string
that has been centered by using spaces, you could easily
find the last character in the string by setting both
lBackwards and lNomatch to true, and searching backwards for
the first non-space character.
EXAMPLE: DF_AT("a", "Char") --> 3
DF_AT("aBa","Haba", -1) --> 2 (Scaned from right)
DF_AT(" ", " WHAT ",, .T.) --> 4 ( 'W' is first
non-space from left )
DF_AT(" ", " WHAT ",-1, .T.) --> 7 ( 'T' is first
non-space from right)
DF_AT("xz", "This is a xz or xz a is This", 2) --> 17
DF_AT("ab", "-4 ab -2 ab -1 ab", -3) --> 4
SOURCEFILE: AT.ASM
PAGE 14
C. DF_PSEC()
Finally, someone has added a true relative timer to Clipper.
DF_PSEC() is IT!
SYNTAX: DF_PSEC( [iPrecision] )
GRANULARITY: 2
ARGUMENTS: iPrecision OPTIONAL - Numeric, the number of place after
the decimal for rounding.
Defaults to 4, MAX DOUBLE limitati
MIN 0
RETURNS: iSeconds ( SSS.xxxx, in Clipper DOUBLE format)
^uCOMMENTS:^u The primary feature of this function is to get MORE
precise timings. This function is as Accurate as SECONDS(),
except that it uses some assembler to monitor the decay
value in the 825x timers.
This Function isn't ABSOLUTELY accurate. The PC isn't an
atomic clock, and therefore this function is only relatively
accurate. The real value of this function is in relative
timings. This means that the two readings relative to each
other will yield more precise information that two simialar
calls to SECONDS().
EXAMPLE: t = df_psec() --> 1001.2122
? at('?', "Question ?")
? df_psec() - t --> 0.0012 (Timing on 386-33).
D. DF_ASCVAL()
Save a SUBSTR() CAll.
SYNTAX: DF_ASCVAL(cChar, ioff)
GRANULARITY: 0
ARGUMENTS: cChar REQUIRED - character or substring to conver
iOff OPTIONAL - Numeric, if true scans like RAT()
Defaults to 0, MAX is 65535
RETURNS: iASCII (Numeric, ASCII value of 'S' would be 83)
^uCOMMENTS:^u The main feature of this function is that it saves
calls to SUBSTR().
EXAMPLE: DF_ASCVAL( "A" ) == ASC("A") --> 65
DF_ASCVAL( "ABCEFG1", 7) == ASC( SUBSTR("ABCEFG1",7,1) )
SOURCEFILE: ASCVAL.ASM
PAGE 15
IX. DOS.CH DP_ Pseudo Function Calls.
A. dp_ver()
SYNTAX: dp_ver() Numeric Dos version information.
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Numeric, two place DOS Version.
^uCOMMENTS:^u MS-DOS 5.00 Aware. Even with SETVER aimed at your
program, you'll get the correct DOS Version.
EXAMPLE:
#include "dos.ch"
func startup
LOCAL REGS // RECOMMENDED USAGE TO AVOID private clashes
Local version := dp_ver()
IF version > 3.1
ELSE
// Shutdown processing after notifing user
ENDIF
return nil
B. dp_curdrive()
SYNTAX: dp_curdrive() Get the Numeric drive ID for the
CURRENT Drive
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Upper case Character Drive Designator
OR
"" if there was an error
PAGE 16
EXAMPLE:
#include "dos.ch"
func startup
LOCAL REGS // RECOMMENDED USAGE TO AVOID private clashes
Local iCurrdrive := dp_curdrive()
IF iCurdrive < "C"
IF ! dp_changedrive("C")
// IF can't get to a harddisk forget running
// a Clipper App, BUT Someday it ought to check
// if we're running on a 21 Meg. Floppy!
// Use dp_drivesize() for that.
ENDIF
ENDIF
return nil
C. dp_driveno(<x>) This is an INLINE substition for getting
the numeric drive ID from a STRING.
(ASC(UPPER( SUBSTR( <x>, 1,1)))-64)
D. dp_changedrive(<x>)
SYNTAX: dp_changedrive(cDrive) Change to or make the specified drive active
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDrive REQUIRED, character
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Logical (success/fail)
EXAMPLE: See dp_curdrive()
E. dp_lastdrive()
SYNTAX: dp_lastdrive() Determine the Last Logical Drive Setting
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Character ( 'A', ... 'Z')
^uCOMMENTS:^u Don't bother opening and reading the CONFIG.SYS, just place a
CALL TO DP_LASTDRIVE()
PAGE 17
EXAMPLE:
#include "dos.ch"
func startup
LOCAL REGS // RECOMMENDED USAGE TO AVOID private clashes
Local cLast := dp_lastdrive()
IF cLast > "B"
//
ELSE
// Shutdown processing after notifing user of LASTDRIVE
// OR Open config.sys
IF (ihand := fopen("c:\config.sys")) > 0
// Read in and process
ELSE
// Give UP.
ENDIF
ENDIF
return nil
F. dp_drivesize([<x>])
SYNTAX: dp_drivesize(cDrive) Determine the TOTAL Disk Volume (bytes) of a Drive
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDrive Optional, If nil, assumes the current drive
Character
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Numeric (Total bytes of drive, NOT KBytes, BYTES)
^uCOMMENTS:^u Please note that to specify a drive using this function, pass
the character representation of the drive--not the defines from
BIOS.CH.
EXAMPLE: #define I_CONTROLL
#include "dos.ch"
func percentfree
LOCAL REGS // RECOMMENDED USAGE TO AVOID private clashes
Local iTotbytes := dp_drivesize('a')
return (diskspace('a')/iTotbytes) * 100
G. dp_curdir([<x>])
SYNTAX: dp_curdir(cDrive) Get the current directory from a specified Drive
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDrive Optional, character, "C", etc.
IF NIL assumes the current drive
RECOMMENDED LOCALS: ^bREGS, SREGS^b
RETURNS: cDirectory (NO preceding drive path: "dos" not "c:\dos")
^uCOMMENTS:^u Similar to Clipper's curdir() but smaller
PAGE 18
EXAMPLE:
LOCAL REGS, SREGS
? dp_curdir() // Pass a nil
? dp_curdir("A") // Returns "", means at the root
? dp_curdir("C")
H. dp_mkdir(<x>)
SYNTAX: dp_mkdir(cDirectory) Create or Make a directory
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDirectory REQUIRED
RECOMMENDED LOCALS: ^bREGS, SREGS^b
RETURNS: Logical (success/failure)
^uCOMMENTS:^u "cDirectory" must be a valid MSDOS directory. It may not
contain any wildcards.
EXAMPLE: Look at about line 50 of DIRR.PRG (+- 200 Lines, HA)
LOCAL REGS, SREGS
IF( dp_mkdir(dirr), NIL, DOS_Quit( REGS ) ) // IF ok, do nada, else outta here
I. dp_rmdir(<x>)
SYNTAX: dp_rmdir(cDirectory) Remove a directory
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDirectory REQUIRED
RECOMMENDED LOCALS: ^bREGS, SREGS^b
RETURNS: Logical (success/failure)
EXAMPLE: Look at about line 100 of DIRR.PRG
LOCAL REGS, SREGS
IF ! dp_chdir("..") .OR. ! dp_rmdir(dirr) // NOTE: Relative directory
// spec ".."
J. dp_chdir(<x>)
SYNTAX: dp_chdir(cDirectory) Change to a directory
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cDirectory REQUIRED, character, can specify full path
(ie, c:\other\dir)
RECOMMENDED LOCALS: ^bREGS, SREGS^b
PAGE 19
RETURNS: Logical (success/failure)
^uCOMMENTS^u This function takes as an argument the destination directory.
The destination directory may be preceeded by a drive
specification. If no drive specification is given, dp_chdir()
assumes the current drive.
EXAMPLE: Look at about line 100 of DIRR.PRG
LOCAL REGS, SREGS
IF ! dp_chdir("..") .OR. ! dp_rmdir(dirr)
// NOTE: Relative parent directory spec ".."
K. dp_getdate()
SYNTAX: dp_getdate() Get the system Date
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: ARRAY ({iWeekday,iMonth,iDay,iYear})
iWeek 0 to 6, -1 on Error (Seems odd, but that's the way it is)
iMonth 1 to 12 (Don't ask me, I'm not the designer, just inheritor)
iDay 1 to 31
iYear 1980 to 2099
^uCOMMENTS:^u Check the date() and set it without a run to the DATE command.
See dp_setdate(). Not extremely important in the USA, but try
getting the date on a box that's running in Japan or Europe. Date()
MAY work there, but this WILL work anywhere.
EXAMPLE:
LOCAL REGS
LOCAL aIdateinfo := dp_getdate()
L. dp_setdate( <ddate> [,<day> ,<yr>] )
SYNTAX: dp_setdate(iMo,iDay,ar) the system Date
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: dMo REQUIRED - DATE
--- OR ---
iMo Numeric, 1 to 12 REQUIRED
iDay Numeric, 1 to 31
iYear Numeric, 1980 to 2099
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Logical (success/failure)
PAGE 20
Example:
ddate = ctod('07/04/1993')
if dp_setdate( ddate )
? 'System date reset.'
endif
----- OR ------
if dp_setdate( 7, 4, 1993)
? 'System date reset'
endif
M. dp_gettime()
SYNTAX: dp_gettime() Get the System Time
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: ARRAY ({iHour,iMinute,iSecs,iHundreths})
iHour 0 to 23 ( Military Time )
iMinute 0 to 59
iSecs 0 to 29 (Mul by 2 to get Seconds. {I know, I know.})
iHundreths 0 to 99
^uCOMMENTS:^u If there is an error, iHour will be -1.
EXAMPLE:
#include "dos.ch"
LOCAL REGS
LOCAL theTime
theTime := dp_gettime()
? "The current time is " theTime[1] ":" theTime[2] ":" ( 2 * theTime[3] )
N. dp_settime( <hr> [,<min> ] [, <sec>] )
SYNTAX: dp_settime(iHr,iMin, iSec) Set the system clock
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: cHr Character Time string as returned by TIME()
--- OR ---
iHr 0 TO 23 REQUIRED
iMin 0 to 59
iSec 0 to 59
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Logical (Time set as requested, if true)
PAGE 21
EXAMPLE:
include "DOS.CH"
FUNCTION ChangTime( cTime )
LOCAL cString := " "
LOCAL REGS
LOCAL newHours, newMinutes, newSeconds
IF cTime == NIL
@ 0,0 SAY "Enter the new time " GET cString PICT "@R XX:XX:XX"
READ
ELSE
cString := cTime
ENDIF
IF EMPTY( cString )
RETURN .F.
ELSE
newHours := Substr( cString, 1, 2 ) // parse out the hours,
newMinutes := Substr( cString, 3, 2 ) // minutes, and seconds
newSeconds := Substr( cString, 5, 2 ) // from the time string
ENDIF
newHours := IIF( EMPTY( newHours ), seconds() / 3600, newHours )
newMinutes := IIF( EMPTY( newMinutes ), seconds() % 3600, newMinutes )
newSeconds := IIF( EMPTY( newSeconds ), newMinutes % 60, newSeconds )
// make sure the string wasn't empty
RETURN dp_settime( newHours, newMinutes, newSeconds )
// make the call to dp_settime to set the time
---- OR -----
return dp_settime("06:13:22")
O. dp_isverify()
SYNTAX: dp_isverify() Determine the status of VERIFY (File Writes)
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Logical (Verify on if true)
EXAMPLE:
LOCAL REGS // Available definitions
// #define DO_NOT_VERIFY 0
// #define VERIFY_WRITES 1
IF dp_isverify()
// Haven't had much occassion to try this. Try it.
// Time it if it's on--you may want to turn if off to speed up
// disk writes.
ENDIF
PAGE 22
P. dp_setverify(<x>)
SYNTAX: dp_setverify( iOnoff ) Set the STATE of Write Verifications
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: iOnoff REQUIRED - 0 turns WRITE VERIFICATION OFF
(Numeric) 1 turns WRITE VERIFICATION ON
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Logical (success/fail)
^uCOMMENTS:^u Verification request on a NETWORK workstation writing to the
server are NOT GUARANTEED under DOS. Verification slows the
system down, so only use this feature for critical files for when
your application is running stand-alone. There are significant
doubts about the accuracy of the DOS SETVERIFY behavior on a
network.
EXAMPLE:
include "DOS.CH"
LOCAL REGS
IF dp_setverify( VERIFY_WRITES ) // if the verification was successfully turned on
write_important_file() // write the file that needs verifying
dp_setverify( DO_NOT_VERIFY ) // turn verification off
ELSE
return_error() // there was an error turning on the verification
ENDIF // so let the user know his file is not verified
Q. dp_getpsp() =>
SYNTAX: dp_getpsp() Get the current programs' Program Segment Prefix
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: Numeric (Representing the FIRST Segment of the CLIPPER Code)
EXAMPLE:
LOCAL REGS
LOCAL iPsp
iPsp := dp_getpsp() // Now can access info in the PSP Table
R. dp_getcmdline()
SYNTAX: dp_getcmdline() Get command line parameters.
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
PAGE 23
RETURNS: cCommandline
^uCOMMENTS:^u This function returns the command line parameters that were
passed from DOS when your application was loaded. See the
exmaple below. Also, reading command line parameters can be handy
for debugging purposes.
EXAMPLE:
LOCAL REGS
LOCAL cDevrequest := dp_getcmdline()
// cDevrequest now contains the command line parameters that were
// issued when your program was loaded by DOS
// ie. If your program is called "MYPROG.EXE" and the user
// typed "MYPROG c:\files\myfile.doc -d" at the DOS prompt
// cDevrequest would return a string containing:
// "c:\files\myfile.doc -d"
// If no parameter was passed from the DOS prompt, dp_getcmdline()
// returns an empty string.
// In this example, "-d" might be used to put the program into
// debugging mode
S. dp_maxfiles()
SYNTAX: dp_maxfiles() Determine MAXIMUM AVAILABLE files to Program
^rINCLUDE FILE:^r ^bDOS.CH^b
ARGUMENTS: None.
RECOMMENDED LOCALS: ^bREGS^b
RETURNS: iMaxfiles (available)
^uCOMMENTS:^u This function checks the maximum number of files that can be
open at any one time. It knows to count the standard dos files
(PRN, CON, AUX, etc), but does not check to see if these files
are in use. Even though this does not fully track down resource
consumption, it does provide a fast method of checking resource
allocation.
EXAMPLE:
LOCAL REGS
IF dp_maxfiles() < 33
// Notify User and shut down.
ENDIF
PAGE 24
X. THE FUTURE of DOORS.
The future for doors is left in the hands of the community to which
it is being delivered. If YOU like the concept of minimized size with
GOOD speed AND are willing to support this with your dollars and use,
I'LL guarantee to offer support and extensions in the future. If
we can survive off this library, I'll take it into the event driven
arena. In case you haven't thought of it, DOING DOS BASED GRAPHIC
programming is just a INTERRUPT away, right now with this library.
Anyone fimailiar with the NOVELL API's should see the possibilities
in this library for growth.
An archive utility is available via WORKing compression and
decompression technology. Not as compact as PKZIP, but 10 times
smaller code and twice as fast. Additionally, .ini files for your
Clipper application becomes a SNAP to use with INI_xxx() services.
We have ideas for doing a training video on DOORS, CLIPPER and another
on the extend system. As ASPEN arrives, I hope that we will be
among the first with a .DLL supporting the GLITZY User Interfaces.
Additionally, windowing, file utilities, relationaly manipulation
and referential integrity are capabilites which are available. We
are a known contractor in the DALLAS, TX telecommunications market
(hopefully WELL known, <g>) at Ericsson, GTE, and NationsBank.
All of these are technologies with which we're comfortable and for
which superior working code can be delivered.
We at Codesmythe are dedicated to pushing the limits of code size,
algorithm speed and diversity, and reusability. As the world of OOP
catches up to the production environments, we have every intention of
helping to provide the tools necessary to make the developer's life
and work easier and faster, with the ultimate goal of providing
user friendly features which are as FAST as possible within the
design constraints.
PAGE 25
IX. APPENDIXES
A. DOORS FUNCTIONS
B. CLIPDOOR FUNCTIONS
B. DP_FUNCTIONS
1. FILE FUNCTIONS
2. DIRECTORY FUNCTIONS
3. DISK FUNCTIONS
4. VIDEO FUNCTIONS
5. PRINTER FUNCTIONS
6. MOUSE FUNCTIONS
7. NETWORK FUNCTIONS
8. DATE / TIME / COUNTRY FUNCTIONS
9. MISC DOS FUNCTIONS
10. MISC HARDWARE FUNCTIONS
11. KEYBOARD I/O FUNCTIONS
12. BIT, NIBBLE, AND BYTE FUNCTIONS
D. DOS REFERENCE MANUALS
E. 4Th Level Optimization
PAGE 26
APPENDIXES
APPENDIX A: DOORS FUNCTIONS
NOTE: Those functions which are network aware are indicated as
such with a 'N' preceeding the name and the description. An 'I'
indicates INTERNATIONAL support.
NI DF_DOS() The cornerstone of the Library. Fire that INTERRUPT.
I DF_AT() Replacement AT(), RAT() Function with a TWIST
DF_ASCVAL() Replacement/speedup for ASC( substr( string, at('a',string), 1) )
I DF_CPUIS() Find the Current CPU Type, XT, AT, 386, 486.
I DF_DOSFILE() Determine System Files available to the application.
NI DF_EXEPATH() Reports the location from which the application began
NI DF_FHAVAIL() Determine FILE HANDLEs Available at RUNTIME.
DF_INT33() What are you doing you rodent you? (Talk to MICE)
DF_ISBIT() Determine if a particular bit is set in a Numeric
DF_ISVID() Determine the video adapter type in the System
DF_JUMP() Make the Far jump to SEGMENT:OFFSET
DF_MASKBIT() Numerical AND, OR, NOT, and XOR of values
DF_MEMSET() Read/Write Byte, Word or Sting into Memory (Direct)
N DF_NBEXEC() Handles calls to the NETBIOS and IPX/SPX ACCESS Layer
DF_PTIME() Report the current FIXED presion count of 8253 Timer.
DF_PTINIT() Check on and set the precision state of 8253 Timer.
DF_SHIFT() Shift bits left or right in an INTEGER value.
DF_DIMAT() Dim string attributes for DISPLAY shadowing.
DF_STRTYPE() Determine the contents of string by NUMERIC Code.
(ie a REAL isalpha(), isdigit(), etc)
DF_VSPAINT() Paint strings with positional offsets, odd or even
fill, etc.
/* The following functions are PRGS */
N DF_ALLDRIVES() Determine all available drive specifications
N DF_DRIVETYPE() ID the drive type, Local/remote/floppy (Defs regs.ch.)
DF_MDSORT() Multi Dimensional ARRAY sorter/Indexer
N DF_NETCMD() General purpose NETBIOS call interface.
N DF_NBERR() Get the NET ERROR if DF_NETCMD() returns .F.
N DF_NBETEXT() Returns the string description for a NET ERROR.
N DF_NETID() Get the adapter ID from Netbios.
N DF_NETRESULT() Get the resultant array after a NETBIOS Call.
N DF_NETTIME() Get the Date and time as an ARRAY from a SERVER.
DF_PSEC() Similar to Clipper's SECONDS(), but 4 Place precision.
NOTE: Will require use of INTEL 8253 or 8254 Timer.
I DF_QSEARCH() Quickly find which item in ordered ARRAYS.
N DF_SETTONETTIME() Set the workstations date\time from a SERVER.
APPENDIX B: CLIPDOOR FUNCTIONS
NOTE: Those functions used for networking are indicated as
such with a 'N' preceeding the name and the description. Those with
an 'I' indicate INTERNATIONAL codepage support.
DF_ARCOLORS() Array color function for testing, setting
I DF_ASCIISCR() READ ON SCREEN TEXT
DF_COLORCHR() Get a Numeric color from a character spec
I DF_DATEFORMAT() Determine Recommended Date format from Codepage
DF_DBL_CLK_DELAY() Query / set mouse Double Click Delay period
DF_INEVENT() MOUSE/KEY Wait state function similar to INKEY()
DF_LASTEVENT() Query the DF_LASTEVENT() status.
DF_KADVANCE() @ GET .. WHEN Cursor Locator(++)
DF_MBUTTONS() Query for number of mouse buttons.
I DF_MONEYSTRING() Format a Numeric to Country Currency for display
DF_MOUSE() Query or initialize the internal mouse TRACKER
DF_MSAYSPOT() Display a Mouseable event spot with KEY info
DF_MSHOWN() Query / set mouse visibility
DF_MTEST() Test if mouse event is in a particular area
DF_ONKEY() Event key test function and Loop controller.
DF_PROPCASE() Convert a string to proper case (Leading Caps).
DF_REPAINT() Highlight SCREEN area in alternate Attribute.
DF_READWHILE() A 'SAVE CHANGES' Shell for readmodal().
N DF_REDLIST() Lists available redirected device and server resources
I DF_TIMESTRING() Query / format the current time using Codepage info
I DF_WHEREAMI() Country setup function.
I DF_WHICHCOUNTRY() Query the code page and Country text string
APPENDIX C: DP_FUNCTIONS
NOTE: Those 'dp_' translates which are network aware are indicated as
such with a 'N' preceeding the name and the description.
Also, There is an equivalent db_ codeblock defined for each of the
'dp_' pseudo functions.
1. FILE FUNCTIONS - DOS.CH and FILES.CH
N dp_clrattrib() Clear a File attribute such as Hidden or Read Only
N dp_isattrib() Query for current file attributes
dp_isverify() Determine the status of VERIFY (File Writes)
dp_maxfiles() Determine MAXIMUM ALLOWED files to Program
dp_nofile() Available error check after calling dp_isattrib()
dp_noexist() Available error check after calling dp_isattrib()
dp_nochange() Available error check after calling dp_isattrib()
N dp_rename() Rename a file or MOVE a file on the SAME drive
N dp_setattrib() Set a file attirbute such as Hidden or Readonly
dp_setverify() Set the STATE of Write Verifications
N dp_tempfile() Create a temparary file in an identified Directory
2. DIRECTORY FUNCTIONS - DOS.CH
N dp_chdir() Change to a directory
N dp_curdir() Get the current directory from a specified Drive
N dp_mkdir() Create or Make a directory
N dp_rmdir() Remove a directory
3. DRIVE FUNCTIONS - DOS.CH and BIOS.CH
N dp_chdrive() Change to or make the specified drive active
N dp_curdrive() Get the Numeric drive ID for the CURRENT Drive
dp_diskchanged() Determine if floppy disk volume changed
N dp_drivesize() Determine the TOTAL Disk Volume (bytes) of a Drive
dp_floppytype() Determine Drive Parameters information
dp_hasfloppy() Determines if there is a Floppy disk available.
dp_isdrive() Determine FLOPPY Drive status before access
N dp_lastdrive() Determine the Last Logical Drive Setting
dp_numfloppy() Determines how many floppy disk drives attached
4. VIDEO FUNCTIONS - BIOS.CH
dp_cgapalette() Change the CGA Pallette to desired 2 of 4 Colors
dp_egapalette() Change the EGA/VGA Color spectrum to your choosing
dp_getvmode() Returns cryptic information about the video mode
dp_getvpage() Determine the current active video page
dp_setvpage() Set a new or different video page to be active
5. PRINTER FUNCTIONS - BIOS.CH
N dp_isprinter() Finally a REAL is printer, even on a NETWORK
dp_lptinit() Initilaize the printer specified, unless error
dp_lpttimeout() Available error check after calling dp_isprinter()
dp_lptio() Available error check after calling dp_isprinter()
dp_lptselect() Available error check after calling dp_isprinter()
dp_lptnopaper() Available error check after calling dp_isprinter()
dp_lptack() Available error check after calling dp_isprinter()
dp_lptbusy() Available error check after calling dp_isprinter()
dp_numlpts() Determines how many printer ports are attached
NOTE: The following ARE ONLY for the event that PRINT.COM is loaded.
dp_printcancel() Delete's a specific file from the PRINT.COM Queue
dp_printclear() Clears all files from the PRINT.COM Queue
dp_printstatus() Determines status or installed state of PRINT.COM
6. MOUSE FUNCTIONS - MOUSE.CH
dp_m_is() Query to find if there is a Mouse in the Box!
dp_m_reset() Reset the mouse for different video modes, etc.
dp_m_show() Show the mouse cursor
dp_m_hide() Hide the mouse cursor
dp_m_stat() Determine the current button status on the mouse
dp_m_to() Relocate the mouse cursor to x,y
dp_m_downs() Query for the count of button click downs
dp_m_ups() Query for the count of mouse button releases
dp_m_climit() Sets a column barrier for mouse movement
dp_m_rlimit() Sets a row barrier to the mouse movement
dp_m_gcshape() Set the graphical mouse cursor
dp_m_tctype() Query or set the mouse text cursor type
dp_m_motion() Returns the mouse movements since last queried
7. NETWORK FUNCTIONS - NET.CH
N dp_netname() Returns the net work adapter card tag string
N dp_netdelete() UNUSE a redirected network resource
N dp_netuse() Redirect a device available on the network
N dp_reditem() Returns information about redirected devices
N dp_reddrive() Determine if a Drive is redirected
8. DATE / TIME / COUNTRY FUNCTIONS - DOS.CH and COUNTRY.CH
dp_getdate() Get the system Date
dp_gettime() Set the System Time
dp_setcountryinfo()) Set the country code information
dp_setdate() Set the system Date
dp_settime() Set the system clock
dp_whereintheworld() Sets up Country info, returns numeric ID
9. MISC DOS FUNCTIONS - DOS.CH and BIOS.CH
dp_appendstatus() Determines status or installed state of APPEND.EXE
dp_assignstatus() Determines status or installed state of ASSIGN.COM
dp_coldboot() Restart the computer, reinitialize ALL Hardware
dp_dosram() Determine system DOS Ram (Below 640 K)
dp_getcmdline() Get the command line as the user entered it.
dp_getpsp() Get the current programs' Program Segment Prefix
dp_sharestatus() Determines status or installed state of SHARE.EXE
dp_ver() Numeric Dos version information. MS DOS 5.0 aware.
dp_warmboot() Reboot the computer. Just what we all need.
10. MISC HARDWARE FUNCTIONS - BIOS.CH
dp_equiplist() The first step in finding available hardware.
dp_hasgame() Determines if there is a game port.
dp_hasmodem() Is there an internal modem?
dp_numserial() Determines the number of serial Ports
11. KEYBOARD I/O FUNCTIONS - BIOS.CH
dp_isextkey() Bios interface to checking EXTENDED Shift keys
dp_iskeydown() Bios interface to check CAPS, ALT, CTRL, etc.
12. BIT, NIBBLE, AND BYTE FUNCTIONS - REGS.CH
NOTE: The following are case SENSATIVE as they are defines.
B2INT() Promotes a byte value to a 16 Bit Word (INTEGER)
DP_HIGHNIB() Determine the value of the high 4 bits in a Byte
DP_LOWNIB() Determine the value of the low 4 bits in a byte
HIGHBYTE() Determine high byte value from an INTEGER
LOWBYTE() Determine the low byte value from an Integer
APPENDIX D: DOS REFERENCE MANUALS
'The MS-DOS Bible', The Waite Group, 1989, Howard W. Sams ~ $44.00
'The MS-DOS Encyclopedia', Duncan,1988, Microsoft Press ~ 65.00
'The Programmer's PC Sourcebook, 2Nd Edition', Thom Hogan, 1988,
Microsort Press ~$39.00
'The Waite Groups MS-DOS Developers Guide', The Waite Group, 1989,
Howard W. Sams ~ 35.00
'The Peter Norton Programmer's Guide to the IBM PC', 2nd Edition',
Peter Norton, 1988, Microsoft Press
'The MS-DOS Programmer's Reference', Microsoft Press, 1991, ~25.00
Special Topics:
'Network Programming in 'C''., Nance, B., Que, 1990, ~29.95 with disk
'Microsoft Mouse Programmer's Reference', Microsoft Press, 1991, ~34.95
I'm sure there is a PLETHORA of others. The ones listed I own or have
browsed. This isn't an endorcement or recommendation for any one of
the books, just a suggestion for a good resource. Do remember, you get
what you pay for in these books.
APPENDIX E: Fourth Level Optimization.
The fourth level of optimization is RESERVED for paying customers.
Hey, my wife thinks I shouldn't put out ANYTHING for free! <g>.
(Quick, while she isn't looking - you can directly access and assign
to _AX, _AH, _AL etc and call DF_DOS() directly to write you own
DOS calls INLINE. Can't give away too much, you might not order and
I MUST keep peace on the home front at ALL costs.<g>)