Dec 222017
 
A collection of useful Quick Basic routines.
File QBFAQR01.ZIP from The Programmer’s Corner in
Category BASIC Language
A collection of useful Quick Basic routines.
File Name File Size Zip Size Zip Type
ANSI 0 0 stored
PANSI.BAS 16397 5162 deflated
PANSI.BI 343 174 deflated
PANSI.EX1 520 320 deflated
PANSI.EX2 505 364 deflated
COMM 0 0 stored
ANSIDET.BAS 514 274 deflated
BAUDDET.BAS 1188 442 deflated
CDECT.BAS 499 243 deflated
CLRBUFF.BAS 193 148 deflated
DTRON.QRM 1304 678 deflated
GETBAUD.BAS 1221 526 deflated
DATE 0 0 stored
DAYWEEK.BAS 603 281 deflated
JUL.BAS 10222 1900 deflated
DBASE 0 0 stored
DBASE.DOC 9278 2800 deflated
DISABLE 0 0 stored
CAD.BAS 608 333 deflated
DISCTRLC.BAS 640 310 deflated
DISKEYB.BAS 340 165 deflated
DISPRT.BAS 376 169 deflated
DISPRT.QRM 1971 997 deflated
DOS 0 0 stored
CLINE.BAS 8643 3012 deflated
COPY.BAS 805 316 deflated
CURDIR.BAS 1669 621 deflated
DIR.BAS 2948 1112 deflated
DIR.BI 1220 395 deflated
DIR.MAK 22 18 deflated
DIR2ARRY.BAS 4817 1476 deflated
DIRREAD.BAS 5170 1583 deflated
DIRSUBS.BAS 6301 1953 deflated
DOS.BAS 12565 2950 deflated
ERRLEV1.BAS 219 160 deflated
ERRLEV2.BAS 314 196 deflated
GWINT.BAS 2700 1271 deflated
LABEL.BAS 5301 1484 deflated
PAGER.BAS 1417 676 deflated
PSP.BAS 5891 2063 deflated
PSP.DOC 4473 1882 deflated
QBREDIR.DOC 2977 1364 deflated
REDIR.OBJ 1148 838 deflated
RWSTAT.BAS 2126 836 deflated
ENCRYPT.BAS 1334 507 deflated
GRAPHIC 0 0 stored
3D.BAS 13852 4391 deflated
CGAOUTP.BAS 445 218 deflated
CGETCLR.BAS 445 242 deflated
CIRCLER.DOC 3357 1456 deflated
CSRPOS.BAS 299 200 deflated
DECGIF.BAS 5753 2000 deflated
EGASAVE.BAS 2604 852 deflated
FADE13-1.BAS 2370 1171 deflated
FADE13-2.BAS 1497 727 deflated
FONTEST.BAS 1809 892 deflated
GETCLR.BAS 323 220 deflated
ISCLRMON.BAS 233 172 deflated
NOBLINK.BAS 1710 730 deflated
PANDEM.BAS 1387 586 deflated
PCXREAD.BAS 1721 752 deflated
PRINTC.BAS 452 238 deflated
SAVESCR.QRM 3220 1213 deflated
SCRINF.QRM 7696 1853 deflated
TBLINK.BAS 523 237 deflated
VIDTYPE.BAS 2275 1052 deflated
KEYBOARD 0 0 stored
CAPS.QRM 1596 604 deflated
KEYCODE.DOC 1955 843 deflated
KEYWAIT.BAS 1470 609 deflated
TEXT3WIN.BAS 7088 1959 deflated
USEKEYB.BAS 920 472 deflated
LIST 3133 1547 deflated
MATH 0 0 stored
ARCSINE.BAS 648 391 deflated
DEC2ANY.BAS 1150 509 deflated
DECODER.BAS 4582 1608 deflated
ENCRYPT.BAS 1334 507 deflated
ERATOS.BAS 774 397 deflated
HUFFMAN2.BAS 15545 3905 deflated
HUFFMAN2.MAK 27 24 deflated
MBF2NUM.QRM 2381 1130 deflated
MISC 0 0 stored
MOUSECUR.DOC 856 415 deflated
POSTIT27.QRM 7357 5520 deflated
QWKFMT.DOC 23524 6594 deflated
SYSTYP.BAS 1366 634 deflated
WC.BAS 2432 1015 deflated
ZIPHEAD.BAS 2848 840 deflated
MIXLANG 0 0 stored
A86.DOC 4462 1798 deflated
A86TEST.DOC 4018 1457 deflated
MIXLANG.DOC 13490 4394 deflated
MOUSE 0 0 stored
TXTCUR.BAS 16275 11928 deflated
NETWORK 0 0 stored
NETID.BAS 1929 800 deflated
NETID2.BAS 2137 893 deflated
PSP 0 0 stored
CMDLINE.BAS 604 355 deflated
QB 0 0 stored
QBFAQ 3756 1805 deflated
LIB2QLB.BAT 595 384 deflated
LIBPATCH.DOC 1521 823 deflated
MAKEQLB.DOC 1199 630 deflated
RESOURCE 0 0 stored
BASPRO.MAG 78 78 stored
CRESADDR.QRM 229 163 deflated
LIBCAT.TXT 231 180 deflated
QBIBINF.QRM 545 338 deflated
SOUND 0 0 stored
QBSPEAK1.QRM 6498 4495 deflated
TPCREAD.ME 199 165 deflated

Download File QBFAQR01.ZIP Here

Contents of the DBASE.DOC file


===========================================================================
BBS: PC Connect
Date: 03-03-92 (20:46) Number: 9964
From: NICK DAVIS Refer#: NONE
To: FRANK HAGAN Recvd: NO
Subj: DATABASE Conf: (11) R-QBasic
---------------------------------------------------------------------------
I created this TYPE-variable method of using the db/LIB routines for
reading and writing dBASE-format files because normally this is a
three-step process with db/LIB:

1) Get the record number, given a key, with GetKEY
2) Get the record with GetREC
3) Parse the record with multiple calls to GetFLD, one for each field

With over 600 data files and over 1,000 programs to worry about, I was
overwhelmed by the number of lines of code I'd have to put in each
program just to read and write records. I was also concerned that if
I didn't completely parse each record into its individual fields, I
would invariably mix up data from different records, leading to
disaster. I was also afraid of trying to keep track of a gazillion
variable names. Therefore, I came up with this technique for using
TYPE variables with db/LIB.

First, I created an INCLUDE file for each data file which describes
its layout. Note that the variable 'DeleteCode' must be the first
because db/LIB adds it to keep track of whether or not a record has
been deleted. I used ten- or fewer-character variable subnames and
made them match exactly the field names as db/LIB knew them. Finally,
the TYPE variable was made to match the file name for clarity's sake.
Following is an abbreviated version of one of the INCLUDE files:

TYPE CLIENTType'--------------------------------------------
'
' | File/Variable Name: CLIENT
' | Record Length: 184
' | Description: Client Master File
'
DeleteCode AS STRING * 1
' --------------------------D
KEY AS STRING * 6' CLIENT NO.
FIRM AS STRING * 30' Name of Firm
ADDRESS1 AS STRING * 30' Address Line 1
ADDRESS2 AS STRING * 30' Address Line 2
ADDRESS3 AS STRING * 30' Address Line 3
CITY AS STRING * 15' City
STATE AS STRING * 2' State
ZIP AS STRING * 10' Zip Code
ATTENTION AS STRING * 30' Contact
END TYPE
'
COMMON SHARED /Common.CLIENT/ CLIENT AS CLIENTType' Variable
COMMON SHARED /Common.CLIENT/ DBF.CLIENT, NDX.CLIENT' File Handles

Next, I created another INCLUDE file for each data file to do some
housework each time a data file was needed in a program. One such is:

OpenDBF DBF.CLIENT, Status, "CLIENT.DBF", DBFileType, mode
IF Status THEN PRINT "CLIENT"; Status: END
DBParams(DBF.CLIENT).Segment = VARSEG(CLIENT)
DBParams(DBF.CLIENT).Offset = VARPTR(CLIENT)
DBParams(DBF.CLIENT).Length = LEN(CLIENT)
OpenNDX NDX.CLIENT, Status, "CLIENT.NDX", NDXtype, NDXmode,_
KeyExp$, KeyLen, KeyType, mode
IF Status THEN PRINT "CLIENT"; Status: END

Note that the file handles which db/LIB creates for the data file and
the index file are called DBF.FileName and NDX.FileName in each case -
- again, keeping 600 files straight.

Finally, I created a general purpose INCLUDE file to go with every
program. It is:

'---------------------------------------------------------------------
' Parameters for dBASE File Read/Writes w/ TYPEs
'---------------------------------------------------------------------
'
TYPE dBParamsType
Segment AS INTEGER
Offset AS INTEGER
Length AS INTEGER
END TYPE
'
DIM dBParams(1 TO 100) AS dBParamsType
COMMON SHARED /Common.dBParams/ dBParams() AS dBParamsType

Note that the use of labelled COMMONs lets me freely add data file
INCLUDE files to a program at any time without having to worry about
conflict with existing COMMON blocks.

Then, a sample program would look something like this:

DEFINT A-Z
'$INCLUDE: 'CLIENT.BI'
'$INCLUDE: 'DBPARAMS.BI'
mode = 0 ' Existing File (Add 16 for network use)
'$INCLUDE: 'CLIENT.OP'

This last INCLUDE file is the one described above which opens a data
file and its corresponding index file.

Then, to read or write any data file, I created the following three
routines:
' SET a TYPE Variable to All Blanks
SUB Blank.Rec (n) STATIC
+++9E"kA FOR i =ATE0 S7=60 S11=75 V1 X4 s0=0

PCRelay:SPACE -> #606 RelayNet (tm)
4.11 Menlo Park, CA (415) 323-4193 * 10 lines 3gB
===========================================================================
BBS: PC Connect
Date: 03-03-92 (23:09) Number: 9975
From: NICK DAVIS Refer#: 9964
To: FRANK HAGAN Recvd: NO
Subj: DATABASE (2/3) Conf: (11) R-QBasic
---------------------------------------------------------------------------
----- Continued -----

Finally, I created a general purpose INCLUDE file, DBPARAMS.BI, to be
used with every program. It is:

'---------------------------------------------------------------------
' Parameters for dBASE File Read/Writes w/ TYPEs
'---------------------------------------------------------------------
'
TYPE dBParamsType
Segment AS INTEGER
Offset AS INTEGER
Length AS INTEGER
END TYPE
'
DIM dBParams(1 TO 100) AS dBParamsType
COMMON SHARED /Common.dBParams/ dBParams() AS dBParamsType

Note that the use of labelled COMMONs lets me freely add data file
INCLUDE files to a program at any time without having to worry about
conflict with existing COMMON blocks.

Then, a sample program would look something like this:

DEFINT A-Z
'$INCLUDE: 'CLIENT.BI'
'$INCLUDE: 'DBPARAMS.BI'
mode = 0 ' Existing File (Add 16 for network use)
'$INCLUDE: 'CLIENT.OP'

This last INCLUDE file is the one described above which opens a data
file and its corresponding index file.

Then, to read or write any data file, I created the following three
routines:
' SET a TYPE Variable to All Blanks
SUB Blank.Rec (n) STATIC
Segment = DBParams(n).Segment
Firstx = DBParams(n).Offset
First& = Firstx - (Firstx < 0) * 65536
Last& = First& + DBParams(n).Length - 1
DEF SEG = Segment
FOR i& = First& TO Last&: POKE i&, 32: NEXT
DEF SEG
END SUB
' GET a Record into a TYPE Variable
SUB GetFullREC (FileNumber, Status, RecordNumber#) STATIC
GetREC FileNumber, Status, RecordNumber#, a$
IF Status THEN EXIT SUB' db/LIB ERROR
IF LEFT$(a$, 1) = "*" THEN Status = -1: EXIT SUB' Record Deleted
ASegment = SSEG(a$)
AOffsetx = SADD(a$)
AOffset& = AOffsetx - (AOffsetx < 0) * 65536
Segment = DBParams(FileNumber).Segment
Offsetx = DBParams(FileNumber).Offset
Offset& = Offsetx - (Offsetx < 0) * 65536
L = LEN(a$) - 1
FOR i = 0 TO L
DEF SEG = ASegment: n = PEEK(AOffset& + i)
DEF SEG = Segment: POKE Offset& + i, n
NEXT
DEF SEG
END SUB

----- Continued Next Message -----

PCRelay:SPACE -> #606 RelayNet (tm)
4.11 Menlo Park, CA (415) 323-4193 * 10 lines 3gB
===========================================================================
BBS: PC Connect
Date: 03-03-92 (23:10) Number: 9976
From: NICK DAVIS Refer#: 9964
To: FRANK HAGAN Recvd: NO
Subj: DATABASE (3/3) Conf: (11) R-QBasic
---------------------------------------------------------------------------
----- Continued -----

' PUT a TYPE Variable into a Record
SUB PutFullREC (FileNumber, Status, RecordNumber#) STATIC
Length = DBParams(FileNumber).Length
a$ = STRING$(Length, 32)
ASegment = SSEG(a$)
AOffsetx = SADD(a$)
AOffset& = AOffsetx - (AOffsetx < 0) * 65536
Segment = DBParams(FileNumber).Segment
Offsetx = DBParams(FileNumber).Offset
Offset& = Offsetx - (Offsetx < 0) * 65536
L = Length - 1
FOR i = 0 TO L
DEF SEG = Segment: n = PEEK(Offset& + i)
DEF SEG = ASegment: POKE AOffset& + i, n
NEXT
DEF SEG
PutREC FileNumber, Status, RecordNumber#, a$
END SUB

Then, assuming that I've used GetKEY to get a record number given a
key, I can then use:

Blank.Rec DBF.CLIENT' -- Just in case
GetFullREC DBF.CLIENT, Status, record#

I now have available CLIENT.KEY, CLIENT.FIRM, etc., assuming that
Status = 0.

All the PEEK and POKE stuff above can be avoided (and the program
speeded up) if you have a block memory move routine such as BCopy from
QuickPack Pro.

I know that this seems like a lot of overhead to worry about, but once
these building blocks are in place, life becomes a lot easier
witqdb/LIB, particularly in some of my programs which open 40+ files at
once. Note that I've left out all the stuff related to checking to
see if a record is locked in a network environment, but that's a story
for another day.

== Nick ==


PCRelay:SPACE -> #606 RelayNet (tm)
4.11 Menlo Park, CA (415) 323-4193 * 10 lines 3gB


 December 22, 2017  Add comments

Leave a Reply