home *** CD-ROM | disk | FTP | other *** search
- TECHINFO - Technical information on the file formats used by PC-File+ 3.0
-
- This information is provided for programmers who wish to use PC-File+
- databases with their own programs--BASIC, Turbo Pascal, "C" or other
- languages.
-
- PC-File+ makes an excellent "Front End" program for other systems
- which you might develop. You can use PC-File+ to handle the file
- maintenance functions, and concentrate your efforts on the rest of the
- system.
-
- File Formats
-
- The file "filename.DTA" (where "filename" is the name you gave the
- database), is the main data file. Each field of the record is stored
- in a fixed length format (the length that you defined for it) and
- padded on the right if necessary with blanks. The fields appear in
- the record in the same order that they are accessed in PC-File+.
-
- Deleted records which have not been re-used have a slash "/" in the
- first position of the record. A carriage return character (HEX 0D)
- marks the end of each record. A special record containing a backslash
- "\" as its first character is stored at the end of the database to
- mark the end of the file. All records in the file are the same
- length.
-
- Records are usually stored in the same sequence in which they were
- originally entered. New records will be added to the end of the file
- unless there are deleted records. If there are deleted records,
- PC-File+ will write the new record in place of a deleted one. The
- sort command does not resequence the data portion of the database; it
- only affects the index.
-
- The file "filename.INX" is the index file for your database. There is
- one index record for each data record, including deleted records.
- Each index record is composed of the first two bytes from every data
- field, followed by a two-byte (binary format) pointer to the relative
- record number of the record in filename.DTA.
-
- There is also a "filename.HDR" file for each database. This is a
- standard ASCII file. The first line is similar to this:
-
- PCF+3;00123,Sample database
-
- The first part of this line identifies this file as a PC-File+ 3.0
- file. The next available unique number appears after the semicolon.
- The database description, which may be blank, appears after the comma.
-
- After the database description line, there are two lines for each
- field in the database. The first line is the field name followed by
- its optional mask, constant and/or calculation. The field name always
- takes up the first 12 bytes. The mask, constant and/or calculation
- can start at any point thereafter.
-
- The second line contains the field length, starting row, starting
- column, and window size of the field. These are stored in ASCII
- character format, and are separated by commas. An example:
-
- ZIP_CODE :09--:
- 10,9,12,10
-
- This entry is for a field named ZIP_CODE which has a mask of :09--:
- Its field length is 10, screen row is 9, screen column is 12, and
- window display size is 10. Since the field length and window size are
- the same, this field is not a "window field".
-
- There is one more part of the header file. It's a "picture" of the
- data entry screen. This portion was not always created by earlier
- versions of PC-File+, but is always created by PC-File+ 3.0. Each
- line in the picture starts with the "|" character. This section is
- quite long -- up to 1680 bytes in length.
-
- Sample Programs
-
- Here are sample BASIC and C programs to show you how to process the
- Index and Data records in your PC-File+ 3.0 database. Note that
- these are very limited programs; we are providing them only as
- working demonstrations of how to access PC-File+ database files.
-
- Please note: Due to limitations in BASICA and GWBASIC, this BASIC
- program is NOT able to process databases containing more than
- 32,767 records.
-
- ______________________________________________________________________
-
- 10 '+-----------------------------------------------------+
- 20 ': PC-File+ Sample BASIC program. :
- 40 '+-----------------------------------------------------+
- 60 '* This program reads a database (named "SAMPLE")
- 70 '* in sequence by the Index.
- 80 '* For each record read, a line is printed.
- 100 '*
- 110 '* The sample database was defined as follows:
- 120 '* NAM 20
- 140 '* CITY 12
- 150 '* STATE 2
- 160 '* ZIP 5
- 180 '* = (39) total lngth of all fields
- 200 '* The lngth of an index record in this database:
- 210 '* 2 * (number of fields) + 2. 2 * 4 + 2 = 10.
- 240 '* The lngth of a data record in this database:
- 250 '* (Lngth of data fields) + 1. 39 + 1 = 40
- 320 '
- 360 INX.LEN = 10 'this length was calculated above
- 370 DTA.LEN = 40 'this length was calculated above
- 380 '
- 390 '.......... OPEN FILES FOR PROCESSING ..................
- 410 OPEN "SAMPLE.INX" AS #1 LEN=INX.LEN
- 420 FIELD#1,2 AS NM$,2 AS CI$,2 AS ST$,2 AS ZI$,2 AS PT.DTA$
- 430 ' Each of the above fields contains the 1st 2 bytes of
- 440 ' the corresponding field in the data file.
- 450 ' The last 2 bytes of the above index rcrd are a binary
- 460 ' pointer to the relative rcrd no. in the data file.
- 480 OPEN "SAMPLE.DTA" AS #2 LEN=DTA.LEN
- 490 FIELD #2, 20 AS NAM$, 12 AS CITY$, 2 AS STATE$,5 AS ZIP$
- 500 '
- 510 '.....FOR EACH INX RCRD, GET CORRESPONDING DTA RCRD.....
- 530 GET #1 'Get nxt INX rcd.
- 540 IF LEFT$(NM$,1) = "/" THEN 530 'Bypass deleted rcrd.
- 550 IF LEFT$(NM$,1) = "\" THEN 600 'End of file. " "
- 560 POINTER = CVI(PT.DTA$) 'Get ptr into DTA file.
- 570 GET #2,POINTER 'Random get DTA record.
- 580 LPRINT NAM$;" ";CITY$;" ";STATE$;" ";ZIP$
- 590 GOTO 530 'Loop until end file.
- 600 '
- 610 '..... PROCESSING IS COMPLETE. SHUT DOWN .............
- 630 CLOSE 'Close all files
- 640 END 'Leave the program
-
- ______________________________________________________________________
-
- /* Sample C program
-
- This program was compiled with Microsoft C 5.1. Note that you
- may have to change the #include statements for other compilers.
-
- This program reads a PC-File+ 3.0 database (named "SAMPLE")
- in sequence by the index. For each record read, a line
- is printed on the printer.
-
- The SAMPLE database is defined as follows:
-
- Name 20
- City 12
- State 2
- Zip 5
- = [39] total length of data fields
-
- The length of an index record in this database is:
- 2 * (number of fields) + 2 --> 2 * 4 + 2 = 10
- The length of a data record in this database is:
- Length of the data fields + 1 --> 39 + 1 = 40
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <io.h>
- #include <fcntl.h>
-
- #define namelen 20
- #define citylen 12
- #define statelen 2
- #define ziplen 5
- #define numflds 4
- #define inxlen numflds * 2 + 2
- #define dtalen 1 + namelen + citylen + statelen + ziplen
-
- static int dtafile; /* data file handle */
- static int inxfile; /* index file handle */
- static int fldlen[numflds]; /* array for field lengths */
- struct db { /* structure for the sample database */
- char name[namelen];
- char city[citylen]; /* This structure will need to be */
- char state[statelen]; /* modified for different databases */
- char zip[ziplen];
- } sample;
- union {
- char dtastring[dtalen]; /* Length of dtastring will need to */
- struct db sample; /* be changed for different databases */
- } rcd;
-
- main()
- {
- register unsigned datarecno;
- char inxstring[inxlen+1];
-
- initialize();
-
- inxfile = open("SAMPLE.INX",O_RDWR|O_BINARY);
- dtafile = open("SAMPLE.DTA",O_RDWR|O_BINARY);
-
- for ( ; ; ) {
- read(inxfile,inxstring,inxlen); /* read an index record */
- if (inxstring[0] == '\\') /* end of file */
- break; /* stop processing */
- if (inxstring[0] == '/') /* deleted record */
- continue; /* skip deleted record */
- datarecno = inxptr(inxstring); /* resolve index pointer */
- getrcd(datarecno); /* retrieve data */
- printrcd(); /* print data */
- }
-
- close(inxfile);
- close(dtafile);
- }
-
-
- /*.................. initialize ..............*/
- static initialize()
- {
- fldlen[0] = namelen;
- fldlen[1] = citylen;
- fldlen[2] = statelen;
- fldlen[3] = ziplen;
- }
-
- /*.................. inxptr ..............*/
- static inxptr(string)
- char *string;
- {
- union {
- unsigned binx;
- char charx[2];
- } inx;
-
- /* The last two characters of an index record are a binary
- pointer to the data record in the DTA file. This routine
- will determine the binary pointer given the index string,
- and will return the pointer to the data record. */
-
- inx.charx[0] = string[inxlen - 2];
- inx.charx[1] = string[inxlen - 1];
- return(--inx.binx);
- }
-
- /*.................. getrcd ...............*/
- static getrcd(recno)
- unsigned int recno;
- {
- register long offset;
- register int x;
-
- x = dtalen;
- offset = (long)recno * (long)x;
- lseek(dtafile,offset,0); /* seek the record */
- read(dtafile,rcd.dtastring,dtalen-1); /* read the record */
- }
-
- /*.................. printrcd ................*/
- static printrcd()
- {
- register int len;
- char scratch[dtalen+numflds+3];
-
- len = build_output(scratch);
- write(4,scratch,len); /* printer handle == 4 */
- }
-
- /*.................. build_output ............*/
- static build_output(string)
- char *string;
- {
- register int x;
- register int y;
- int z;
-
- /* This routine will move the data for one field into the string
- variable, add a space, move the data for the next field into
- the string variable, add a space, etc. After all fields have
- been moved into the string variable, carriage return and
- line-feed characters will be appended to the end of the string. */
-
- x = y = z = 0;
- for (x = 0; x < numflds; x++) { /* loop for number of fields */
- for (y = 0; y < fldlen[x]; y++,z++) /* loop for field length */
- string[z] = rcd.dtastring[z - x]; /* move data */
- string[z++] = ' '; /* add a space after the field */
- }
- string[z++] = '\r'; /* append carriage return */
- string[z++] = '\n'; /* append line feed */
- return(z); /* return length of string */
- }
-
- ______________________________________________________________________
-