home *** CD-ROM | disk | FTP | other *** search
-
-
- DOCUMENTATION FOR THE MULKEY SYSTEM
-
- Copyright 1986, 1987 and 1988 by Mark R. Boler - All Rights Reserved.
- This source code must not be distributed without prior written
- permission.
-
- !! IMPORTANT NOTICE !!
-
- These routines require the use of the Btrieve file manager system by
- Softcraft, Version 4.10 or equivalent. It must have this version
- since earlier versions don't deal with Turbo Pascal strings
- correctly. These routines were tested as well as could be expected
- but I assume no responsibility for any errors, omissions, problems
- etc. It is your responsibility to test these routines thouroughly!
- This code is provided "AS IS" without warranty of any kind. Further,
- neither PMI nor Mark R. Boler warrant, guarantee, or make any claims
- of suitability to a particular purpose with reguard to this software.
- The entire risk as to the results and/or performance of this software
- is assumed by you. Neither PMI nor Mark R. Boler shall be liable for
- any direct, indirect, consequential, or incidental damages including,
- but not limited to, loss of profits, loss of information and the
- like. By using this software you agree to the above terms and
- condiions.
-
- -=-=-=-=-=-=-=-=-=-=-=-< MULKEY DEFINITION >-=-=-=-=-=-=-=-=-=-=-=-
-
- First an appology for the documentation. I did not attempt to write a
- user manual for Mulkey. The documentation is terrible. All the
- required information is there for use of Mulkey, only in bad form.
-
- MULKEY is a collection of routines written in Turbo Pascal for
- compilation with Turbo Pascal version 4.xx. This is version 3.00A.
- Version 1.xx of Mulkey was written for compilation using Turbo Pascal
- version 3.xx. Version 2.xx of Mulkey was rewritten for compilation
- using Turbo Pascal version 4.0. Version 3.xx of Mulkey has changed,
- among other things, the master FileDesc file layout. Your other data
- files are still the same. Only the master file has to be changed. You
- may use the convert option to translate the master file description
- files to the new version.
-
- Mulkey is finally fairly stable now and does not seem to have any
- more major bugs. You still use Mulkey at your own risk but I have
- used it for very large (10 files in one program averaging over 2
- megabytes per file) databases with 24 keys in one file now without
- problems.
-
- These routines interface with the product from Novell (formerly
- Softcraft) called Btrieve. They are for database applications and
- deal with indexed data files. With these routines you simply put a
- key value in a parameter to a procedure and Mulkey, with the aid of
- Btrieve will find it. You no longer have to worry about any file
- access, record locking in a network environment. Mulkey simplifies
- the set-up requirements of Btrieve and maintains them for you.
-
- Mulkey will not work without Btrieve. Using Mulkey is not a
- substitute for the Btrieve manual. You still must be familiar with
- the workings of Btrieve to make these work for you.
-
- The program MULKEY.EXE is a utility for setting up and maintaining
- master file description files. MULKEY.PAS is the source code for the
- MULKEY.TPU unit you "use" in your program. Your program must also
- "use" the following units: Dos, - For DOS functions, Btrieve, - The
- Btrv function which calls Btrieve, Env, - Environment variable
- access, Strings, - Various string functions, Convert - Various data
- conversion routines
-
- These routines are kept in separate unit files because many
- programmers already have pre-written functions for these that already
- do the same things and duplication of code is not exactly good for
- program size and efficiency. You will probably not want to write your
- own Btrv() function but if you do, make sure you know about the inner
- workings of Btrieve or you may have very undesirable results.
-
- You can contact me (Mark Boler) at P.O. BOX 81211, Corpus Christi TX
- 78412. This software is distributed under the shareware concept. If
- you use them in your program, you must register by sending $20.00
- to the above address. You will be kept informed of the latest
- revisions of Mulkey automatically after doing so. No support will be
- provided for un-registered copies unless you are still trying the
- software out (for a reasonable period please).
-
- Setup:
- Mulkey requires an environment variable (so i hope you have lots of
- environment space free - as almost every other program requires). The
- environment variable is FILEDESC = and must be a complete drive, path
- and filename of the master file description file you wish to use or
- create. MULKEY.EXE will not run unless it can find this environment
- variable. Mulkey itself will. This variable is Mulkeys link to what
- it should do in the case it is called upon to open a file that does
- not exist. Btrieve stores in each file, the file configuration (key
- locations, number of keys, etc.) that it needs to use that file. Your
- application will open these files, when Mulkey goes out to open a
- file, it first tries to open the file normally, but when the file is
- not found, it then tries to create a new one. When Mulkey creates a
- file, it must know the number of keys, position, type of key, etc.
- This is where the master file description file comes in. It searches
- the environment for the FILEDESC variable and opens the master file
- (that you created with MULKEY.EXE) and uses the information in that
- file to create the new data file. After the data file is created,
- Mulkey no longer opens the master description file anymore unless
- creating another file. Therefore if you change the master description
- file after a file has been created, that file will NOT get the
- change. The master file is opened only when a data file has to be
- created. MULKEY.EXE must have the environment variable available to
- create this master file. You do not have to have it in your
- application but if you don't you must have empty data files created
- by your application to distribute since mulkey will not create a file
- without it. If you choose to distibute your master description file
- then your application can create its own empty data files
- automatically at run time since it has access to the master
- description file through the environment variable FILDESC. Each file
- description in the master file is accessed by a 25 character or less
- name called a TypeName by Mulkey. This TypeName is used whenever you
- open a file so that if the file is not found, the file layout is used
- to create it. If you have not previously set up this TypeName through
- the MULKEY.EXE utility, Mulkey will not find it and the open will
- fail. There is also a 25 character or less SYSTEM name you can add in
- MULKEY.EXE. The OpenFile function will return a number of type WORD
- as a handle for the open file. If it returns a 0 then something went
- wrong. These handles are NOT the same handles as the DOS file handle.
- DO NOT use them as such. These are handles that have meaning only to
- Mulkey. Mulkey insulates you from having to worry about DOS handles.
- Mulkey for Turbo Pascal must have Btrieve version 4.10 or later so it
- can handle Turbo Pascal strings properly.
-
-
- If you use MULKEY.EXE you need to provide a printer driver in the
- form of an environment variable called PRINTDEF= and name one of the
- printer driver files supplied. This program will also read and accept
- a printer driver file in the format supplied by Borland in the editor
- toolbox package with Microstar. I can not provide you with one of
- those drivers since they are Borlands.
-
- ------------------------------------------------------------------
-
- This source code is intended for use with DOS 3.xx or later since the
- use of GetEnv() uses a function call only avaiable in that version.
- To use this code under DOS 2.xx also, you will need to rewrite the
- code for GetEnv. GetEnv is a function in the unit ENV:
-
- GetEnv(EnvVar: STRING): STRING;
-
- GetEnv will provide the complete pathname of the file DOS executed if
- you use GetEnv(''); This works only under DOS 3.xx or later.
-
- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- When this is running, the master file description file must be
- available in an environment variable called FILEDESC = <path> and
- must give a valid path complete with file name and extension of the
- master file description file to use for the create function in
- openfile. If this can't be found or opened, the openfile procedure
- will fail when opening a file that does not yet exist. I suppose this
- could be a feature. If you only want an application to open only
- existing files that you have opened and prepared, don't use the
- environment variable or don't have the file description master file
- available. When changes are made to the structure of the types below,
- make changes to the master file editing and creation utility as well!
-
- As of May 5, 1988, Mulkey is version 3.00A:
-
- Revisions:
-
- 1.00A: Original version of Mulkey - ran under Turbo Pascal 3.xx
- 1.01A: Corrected a bug in the CloseFile procedure that would cause
- Turbo Pascal to hang when DISPOSE() was called. Also corrected
- a FILLCHAR that would overwrite pointers after their
- allocation in the Key Buffers on AddRecord
- 1.02A: Corrected a problem with pre-allocation of a file if it was
- requested and later not allowed, Mulkey would pre-allocate a
- random number of pages anyway
- 1.03A: Corrected a minor problem with the memory allocation of key
- buffers and minor screen changes Added the date to the Mulkey
- version routine Corrected a bug that would not allow a key to
- be the last field in a record Corrected a bug in MULKEY.COM
- print routine that would not shut off underline mode on all
- printers. ( Turbo 3.xx )
- 1.04A: Added GetEqGreater() and GetEqLessThan() procedures
- 1.05A: Minor changes to Longint arrangement and declarations
- 1.06A: Removed some redundant code from MULKEY.INC
- 2.00A: Modified code to conform with Turbo Pascal 4.0. This was a
- rewrite to take advantage of Turbo Pascals new features, not a
- translation just to get it to compile. The MULKEY.COM utility
- is now MULKEY.EXE.
- 2.01A: Changed the meaning of GetDirect GetPosition and added
- GetMarked. Added MulkeyError function.
- 2.02A: Added ability to keep Mulkey from automatically closing files
- when the program is halted. Use with care!
- 2.03A: Took away the ability in 2.02A above, plan to have Mulkey do
- this automatically in future.
- 2.04A: Minor revision - unreleased.
- 2.05A: Added ability of Mulkey to sense that it is running on top of
- itself and not to reset all of the resources of a node if so.
- If mulkey is running in a shell and another copy of it is
- active below it in memory, Mulkey will only close the files it
- has opened in the shell, otherwise it will issue the request
- to close all resources held by the station. It also exports a
- new function: AllowShell: BOOLEAN; which will tell your
- application if the automatic sensing feature has worked.
- Otherwise a shell to another Mulkey operation could damage the
- operation below. This feature used the Intra-Application
- Communications area so it should not be run with programs that
- make use of that area.
- 2.06A: Rewrote memory allocation routines and added extra protection
- in the case that the heap memory runs out during an open.
- 2.07A: Optimized the most repetitive functions.
- 3.00A: Mulkey was modified to accomodate all the extended data types
- of Btrieve version 4.10 and the data file layouts were
- changed. Corrected a problem in NumRecords() that would return
- 0 if there were more than 14 keys in your file. This was not
- considered a bug since Mulkey was originally designed to only
- handle 14 keys but now it can handle Btrieves maximum of 24
- keys and will open files created with BUTIL -Create and Butil
- -SIndex. The length for FDesc has been increased from 20 to 25
- characters as was the System field length. Your master
- FileDesc files are no longer compatible with this version.
- CNVMULKY.EXE was created to translate these files. The data
- files you have created with the old version of Mulkey are
- still the same. ONLY the master FileDesc file has changed. The
- Mulkey array of pointers now exists in the Data segment
- instead of on the heap since it was always allocated anyway.
- The functions BtVersion and MulkeyVersion were changed to
- strings instead of functions for increased speed since they
- never change after program initialization anyway. The ability
- to set locking attributes for each file was added. If no
- explicit locking attributes are set for each file, a default
- is used. The procedures GetMarked() and MarkPosition() are
- gone. If you need them it is very easy to write them using the
- new procedures GetPosition() and GetDirect(). They were just
- duplication of code and were never used. Mulkey no longer uses
- the intra- applications communications area and it no longer
- releases all resources of the workstation when it terminates.
- 3.01A Minor changes in MULKEY.EXE
-
- --------------------------------------------------------
-
- You have 25 characters for the Type Name - This is the name of the
- file layout itself. There are 25 characters for the system name.
- Starting with theis version, Mulkey will not find a FileDesc record
- unless the System names also match or a system name is not given.
-
- ------------------------------------------------------------------
-
- The following are some defininitions of constants and variables:
-
- The next six variables are maintained by mulkey and should NEVER be
- changed by your program directly! They are variables instead of
- functions for efficiency and speed.
-
- MulkeyActive : BOOLEAN { True if Mulkey itself has been initialized }
- TransActive : BOOLEAN { True if a transaction is active }
- IndexError : BOOLEAN { True if last op resulted in error }
- LastErrCode : WORD { Set to last Btrieve error code, initially 0 }
- BtVersion : STRING[45] { Returns the version of Btrieve loaded }
- MulkeyVersion: STRING[45] { Returns the version Mulkey being used }
-
- These constants and types are exported by the Mulkey unit:
-
- FDescLen = 25; { Length of a file description string }
- FSystLen = 25; { Length of a file system name string }
- MaxKeys = 24; { If these are changed, the record structure of }
- { the master file layout files must be modified. }
- MaxKeyLen = 128; { Maximum length of any key possible. }
- MaxMulkey = 40; { Maximum number of mulkey files open at once. }
- { MaxMulkey MUST never be allowed to be > 255 }
-
- TYPE { Exported Types }
- FDescStr = STRING[FDescLen];
- FSystStr = STRING[FSystLen];
-
- The next variables are to be set by your program and will be obeyed by
- Mulkey:
-
- SystemName : STRING[FSystStr] = ''; { '' will find any FileDesc -def }
- WaitLocks : BOOLEAN = TRUE; { Set to true if use waitlocks -def }
- MultiLocks : BOOLEAN = FALSE; { Set to true if multi-record locks }
- UseLocks : BOOLEAN = TRUE; { Set to true if using those locks -def}
- KeyOnly : BOOLEAN = FALSE; { Set to true for "get key" only +50 }
- DefAllowRO : BOOLEAN = FALSE; { Set to true to allow RO on creates }
- DefEncrypt : BOOLEAN = FALSE; { Set to true to encrypt on creates }
-
-
- ----------------------------------------------------------------
-
- The Key Type descriptor given to Btrieve can be on of the following:
-
- VALUE DESCRIPTION ALLOWABLE LENGTH
- ------------------------------------------------------------------
- 0 Array of Character 1 - ?? (variable)
- 1 Signed Whole Number (binary) Even Number of Bytes
- 2 IEEE Floating Point Real 4 or 8 bytes
- 3 Date 4 bytes
- 4 Time 4 bytes
- 5 Decimal (semi-BCD) 1 - ?? (variable)
- 6 Money (same as Decimal) 1 - ?? (variable)
- 7 Logical (Boolean) 1 or 2 bytes
- 8 Numeric 1 - ?? (variable)
- 9 BFloat 4 or 8 bytes (Microsoft Real)
- 10 lString (pascal string) 1 - 256 (max length = 255)
- 11 zString (null terminated) 1 - ?? (C string)
- 14 Unsigned Whole Number (binary) Even Number of Bytes
-
- Mulkey allows you to use them all however there are some that just
- probably wouldn't be efficient in Turbo Pascal. Since you may be
- reading a file created by another language, or using XQL or another
- report generator that requires them, these types are described below:
-
- Type 0: Array of Character
- All characters in the array are significant. BASIC uses this
- type of string padded with blanks ASCII Hex 20.
-
- Type 1: Signed Whole Number
- Normally use this for INTEGER (2 bytes) or LONGINT (4
- bytes). It must be an even number of bytes so don't use this
- for BYTE or SHORTINT values. (Use logical).
-
- Type 2: IEEE Floating Point
- A 4 or 8 bytes IEEE floating point real number. Use this for
- SINGLE or DOUBLE real types.
-
- Type 3: Date
- This is a 4 byte type that corresponds to:
-
- RECORD
- Day : BYTE; { day number }
- Month: BYTE; { month number }
- Year : WORD; { stored as the year, not an offset like 1988 }
- END;
-
- Type 4: Time
- This is a 4 byte type that corresponds to:
-
- RECORD
- Hundredths: BYTE; { hundredths of a second }
- Second : BYTE; { Second }
- Minute : BYTE; { Minute }
- Hour : BYTE; { Hour }
- END;
-
- Type 5: Decimal
- This is an ANSI-74 standard COBOL type stored in a BCD
- format.
-
- Type 6: Money
- This format is exactly the same as Decimal above.
-
- Type 7: Logical
- A 1 or 2 byte value. Btrieve will actually sort and store
- these as a 1 or 2 byte array of character but it will still
- work with unsigned numeric values, etc. With Turbo Pascal,
- use these only for storage of BOOLEAN, One or Two byte
- enumerated types, or for one byte numerical values such as
- BYTE or SHORTINT. As of the time this is created, Novell has
- acknowledged to me, a bug with version 4.10 and they say not
- to use this type for now.
-
- Type 8: Numeric
- Numeric values stored as ascii strings that are right
- justified with leading zeros. The rightmost byte of the
- number contains an embedded sign. The table below shows how
- to make a number contain a negative sign. A positive number
- evaluates to the same as a number without a negative sign.
-
- NUMBER POSITIVE SIGN NEGATIVE SIGN
- --------------------------------------------------------------
- 1 A J
- 2 B K
- 3 C L
- 4 D M
- 5 E N
- 6 F O
- 7 G P
- 8 H Q
- 9 I R
- 0 { }
-
- Type 9: BFloat
- This is the old Microsoft real format used by old MASM and
- the older BASIC compilers and interpreters. It is 4 or 8
- bytes long.
-
- Type 10: lString
- This is for the standard Turbo Pascal string.
-
- Type 11: zString
- This is for a null terminated string. C compilers usually
- use these types of strings.
-
- Type 14: Unsigned Whole Number
- Must contain an even number of bytes. Use this for WORD or
- your own user produced integer type numbers that are
- unsigned and are even number of bytes long.
-
- -------------- MULKEY FUNCTIONS AND PROCEDURES --------------
-
- This sets the error codes maintained by Mulkey -- to clear out an
- error just do: SetErr(0);
-
- PROCEDURE SetErr(Status: WORD); { sets error codes }
-
- BEGIN {seterr}
- LastErrCode:= Status;
- IndexError := (Status <> 0);
- END; {seterr}
-
- ----------------------------------------
-
- FUNCTION HandleActive(Handle: WORD): BOOLEAN;
-
- ----------------------------------------
-
- FUNCTION BtVersion: STRING;
-
- ----------------------------------------
-
- FUNCTION MulkeyVersion: STRING;
-
- ----------------------------------------
-
- FUNCTION OpenFile(FDesc : STRING; { The description name }
- OpenMode: INTEGER; { Use 0 for now - see Btrieve }
- Owner : STRING; { The name of the files owner }
- FileName: STRING): WORD; { The file pathname }
-
- Openfile will return a handle in the range of 1 - MaxMulkey. This numeric
- handle is how you refer to the open file from here on. A handle of 0 means
- something went wrong and you should check IndexError and LastErrCode.
- The handle returned by Mulkey is NOT the same as the DOS file handle
- corresponding to your file by DOS. Btrieve conveniently takes care of
- this for you. The handle returned by this function will be in the range
- of 1 through MaxMulkey in the CONST declarations unless an error occured
- in which case you should get a 0 back by this function.
-
- ----------------------------------------
-
- PROCEDURE CloseFile(Handle: WORD);
-
- ----------------------------------------
-
- PROCEDURE AbortTransaction;
-
- ----------------------------------------
-
- PROCEDURE EndTransaction;
-
- ----------------------------------------
-
- PROCEDURE BeginTransaction;
-
- ----------------------------------------
-
- PROCEDURE ResetFiles;
-
- ResetFiles closes any open files, releases any locks or resources held by
- this station. Usually, you would only want to do this when you must
- terminate the program, but it can be used any time and does release the
- handles held by Mulkey.
-
- ----------------------------------------
-
- PROCEDURE SetOwner(Handle : WORD; { what file to add owner to }
- Owner : STRING; { only 8 characters please }
- AllowRO: BOOLEAN; { allow read only without an owner }
- Encrypt: BOOLEAN); { encrypt the data stored in file }
-
- Make sure you only specify 8 characters for an owner.
-
- ----------------------------------------
-
- PROCEDURE ClearOwner(Handle: WORD); { what file to clear on }
-
- ----------------------------------------
-
- PROCEDURE Unlock(Handle: WORD); { what file to unlock }
-
- This procedure will release any locks accumulated on a file.
-
- ----------------------------------------
-
- PROCEDURE Stat(Handle: WORD);
-
- This procedure does a stat operation on the file. All information is
- stored into the files data records in the FileDescType. It does nothing
- unless the file handle is an active handle. IndexError will be set if not.
- For more information on this, see the Btrieve documentation.
-
- ----------------------------------------
-
- FUNCTION NumRecords(Handle: WORD): LONGINT;
-
- This function will return the number of records in a file. It returns 0.0
- if the handle is not active and sets IndexError (set in Stat). This
- function uses the Stat() procedure. It will also, of course return 0.0
- if there are no data records in the file.
-
- ----------------------------------------
-
- PROCEDURE AddRecord(Handle: WORD; { what file to use }
- VAR d); { what data to put into the file }
-
- Add record d to the file. IndexError usually indicates a duplicate key.
-
- ----------------------------------------
-
- PROCEDURE UpdateRecord(Handle: WORD; { what file to use }
- VAR d); { what data to put in the file }
-
- Updates the last retrieved record (you must have just used a get operation)
- with data from record d. IndexError usually indicates a duplicate key in a
- unique key index.
-
- ----------------------------------------
-
- PROCEDURE DeleteRecord(Handle: WORD); { what file to use }
-
- Deletes the last retrieved record (you must have just used a get operation)
- from the database and all its keys. IndexError usually indicates no valid
- last record retrieved.
-
- ----------------------------------------
-
- FUNCTION GetPosition(Handle: WORD): LONGINT;
-
- This function returns the position of the file maintained by Btrieve.
-
- ----------------------------------------
-
- The following are the get record procedures, they are filtered by procedure
- RPN_Record, which does the work. This is where KeyOnly gets reset, not in
- AdjOp(). If KeyOnly was set, it is set to FALSE after function execution.
-
- PROCEDURE GetDirect(Handle: WORD; { the file to use }
- p: LONGINT; { The position }
- VAR d); { the data to read }
-
- This procedure uses the position (p) to get the record that corresponds to it.
- This procedure will destroy the contents of the data record position in the
- data type FileDescType.
-
- ----------------------------------------
-
- PROCEDURE GetLowest(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR d); { where the data goes to }
-
- Read lowest record from the database with KeyNum. IndexError usually
- indicates no key found.
-
- ----------------------------------------
-
- PROCEDURE GetHighest(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR d); { where the data goes to }
-
- Read highest record from the database with KeyNum. IndexError usually
- indicates no key found.
-
- ----------------------------------------
-
- PROCEDURE StepDirect(Handle: WORD; { what file number to use }
- VAR d); { where the data goes to }
-
- This procedure should be used when the data file is damaged and must
- be opened to recover it. See the Btrieve documentation
-
- ----------------------------------------
-
- PROCEDURE GetEqual(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR k; { the key value itself }
- VAR d); { where the data goes to }
-
- Read record from the database with a key equal to k.
- IndexError usually indicates search key not found.
-
- ----------------------------------------
-
- PROCEDURE GetGreater(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR k; { the key value itself }
- VAR d); { where the data goes to }
-
- Read record from the database with a key greater than k.
- IndexError usually indicates search key not found.
-
- ----------------------------------------
-
- PROCEDURE GetLessThan(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR k; { the key value itself }
- VAR d); { where the data goes to }
-
- Read record from the database with a key less than k.
- IndexError usually indicates search key not found.
-
- ----------------------------------------
-
- PROCEDURE GetGreaterOrEqual(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR k; { the key value itself }
- VAR d); { where the data goes to }
-
- { Read record from the database with a key equal to or greater than k.
- IndexError usually indicates search key not found. }
-
- ----------------------------------------
-
- PROCEDURE GetLessThanOrEqual(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR k; { the key value itself }
- VAR d); { where the data goes to }
-
- { Read record from the database with a key equal to or less than k.
- IndexError usually indicates search key not found. }
-
- ----------------------------------------
-
- PROCEDURE NextRecord(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR d); { where the data goes to }
-
- Read next record by last key from database.
- IndexError usually indicates end of file by key.
-
- ----------------------------------------
-
- PROCEDURE PrevRecord(Handle: WORD; { what file number to use }
- KeyNum: WORD; { what key number to use }
- VAR d); { where the data goes to }
-
- Read previous record by last key from the database.
- IndexError usually indicates end (start) of file by key }
-
- ----------------------------------------
-
- FUNCTION AllowShell: BOOLEAN; { True if a transaction is not active }
-
- ----------------------------------------
-
- FUNCTION BtError(Code: WORD): STRING;
-
- Returns a text string explaining error codes.
-
- FUNCTION MulkeyError: STRING;
-
- Returns a text string explaining the last error code in the form of
-
- 'MULKEY ERROR: '<explanation>
-
- - or -
-
- 'NO MULKEY ERROR' if none occurred.
-
- Note: Using either of these functions in your program will add a
- significant amount of code to your .EXE file.
-
- ----------------------------------------