home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- **
- ** Copyright 1982-1997 Pervasive Software Inc. All Rights Reserved
- **
- *************************************************************************/
- /***************************************************************************
- CBBMain.cpp
- This is a simple sample designed to allow you to confirm your
- ability to compile, link, and execute a Btrieve application for
- your target environment using your compiler tools.
-
- This program demonstrates the C/C++ interface for Btrieve for MS
- Windows NT and Windows 95 with Borland's C++ Builder.
-
- This program does the following operations on the sample database:
- - gets the Microkernel Database Engine version
- - opens sample.btr
- - gets a record on a known value of Key 0
- - displays the retrieved record
- - performs a stat operation
- - creates an empty 'clone' of sample.btr and opens it
- - performs a 'Get Next Extended' operation to extract a subset
- of the records in sample.btr
- - inserts those records into the cloned file
- - closes both files
-
- To compile this sample, you must make the following files from the
- Btrieve "C" interface directory available to the IDE:
- - btrapi.c
- - btrapi.h
- - btrconst.h
-
- IMPORTANT:
- You must specify the complete path to the directory that contains
- the sample Btrieve data file, 'sample.btr'. See IMPORTANT, below.
-
- ****************************************************************************/
- //---------------------------------------------------------------------------
- #include <vcl\vcl.h>
- #pragma hdrstop
-
- #include "CBBMain.h"
- #include <btrapi.h>
- #include <btrconst.h>
- //---------------------------------------------------------------------------
- #pragma resource "*.dfm"
-
- /***************************************************************************
- Constants
- ****************************************************************************/
- #define EXIT_WITH_ERROR 1
- #define TRUE 1
- #define FALSE 0
- #define VERSION_OFFSET 0
- #define REVISION_OFFSET 2
- #define PLATFORM_ID_OFFSET 4
- #define MY_THREAD_ID 50
-
-
- /* Don't pad our structures */
- /* Borland's help says this is the default. Don't believe it. */
- #pragma option -a1
-
- /***************************************************************************
- Type definitions for Client ID and version Structures
- ****************************************************************************/
- typedef struct
- {
- BTI_CHAR networkAndNode[12];
- BTI_CHAR applicationID[2];
- BTI_WORD threadID;
- } CLIENT_ID;
-
- typedef struct
- {
- BTI_SINT Version;
- BTI_SINT Revision;
- BTI_CHAR MKDEId;
- } VERSION_STRUCT;
-
- /***************************************************************************
- Definition of record from 'sample.btr'
- ****************************************************************************/
- typedef struct
- {
- BTI_LONG ID;
- BTI_CHAR FirstName[16];
- BTI_CHAR LastName[26];
- BTI_CHAR Street[31];
- BTI_CHAR City[31];
- BTI_CHAR State[3];
- BTI_CHAR Zip[11];
- BTI_CHAR Country[21];
- BTI_CHAR Phone[14];
- } PERSON_STRUCT;
-
- /***************************************************************************
- Type definitions for Stat/Create structure
- ****************************************************************************/
- typedef struct
- {
- BTI_SINT recLength;
- BTI_SINT pageSize;
- BTI_SINT indexCount;
- BTI_CHAR reserved[4];
- BTI_SINT flags;
- BTI_BYTE dupPointers;
- BTI_BYTE notUsed;
- BTI_SINT allocations;
- } FILE_SPECS;
-
- typedef struct
- {
- BTI_SINT position;
- BTI_SINT length;
- BTI_SINT flags;
- BTI_CHAR reserved[4];
- BTI_CHAR type;
- BTI_CHAR null;
- BTI_CHAR notUsed[2];
- BTI_BYTE manualKeyNumber;
- BTI_BYTE acsNumber;
- } KEY_SPECS;
-
- typedef struct
- {
- FILE_SPECS fileSpecs;
- KEY_SPECS keySpecs[5];
- } FILE_CREATE_BUF;
-
- /***************************************************************************
- Structure type definitions for Get Next Extended operation
- ****************************************************************************/
- typedef struct
- {
- BTI_SINT descriptionLen;
- BTI_CHAR currencyConst[2];
- BTI_SINT rejectCount;
- BTI_SINT numberTerms;
- } GNE_HEADER;
-
- typedef struct
- {
- BTI_CHAR fieldType;
- BTI_SINT fieldLen;
- BTI_SINT fieldOffset;
- BTI_CHAR comparisonCode;
- BTI_CHAR connector;
- BTI_CHAR value[3];
- } TERM_HEADER;
-
- typedef struct
- {
- BTI_SINT maxRecsToRetrieve;
- BTI_SINT noFieldsToRetrieve;
- } RETRIEVAL_HEADER;
-
- typedef struct
- {
- BTI_SINT fieldLen;
- BTI_SINT fieldOffset;
- } FIELD_RETRIEVAL_HEADER;
-
- typedef struct
- {
- GNE_HEADER gneHeader;
- TERM_HEADER term1;
- TERM_HEADER term2;
- RETRIEVAL_HEADER retrieval;
- FIELD_RETRIEVAL_HEADER recordRet;
- } PRE_GNE_BUFFER;
-
- typedef struct
- {
- BTI_SINT recLen;
- BTI_LONG recPos;
- PERSON_STRUCT personRecord;
- } RETURNED_REC;
-
- typedef struct
- {
- BTI_SINT numReturned;
- RETURNED_REC recs[20];
- } POST_GNE_BUFFER;
-
- typedef union
- {
- PRE_GNE_BUFFER preBuf;
- POST_GNE_BUFFER postBuf;
- } GNE_BUFFER, BTI_FAR* GNE_BUFFER_PTR;
-
- //---------------------------------------------------------------------------
- // non-exported forward declarations
- void printLB(TListBox *LB, char *msg);
-
- TForm1 *Form1;
- //---------------------------------------------------------------------------
- __fastcall TForm1::TForm1(TComponent* Owner)
- : TForm(Owner)
- {
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::ExitButtonClick(TObject *Sender)
- {
- Form1->Close();
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::RunButtonClick(TObject *Sender)
- {
- runTest();
- }
-
- /************************************************************************
- Helper function to write to ListBox
- ************************************************************************/
- void printLB(TListBox *LB, char *msg)
- {
- LB->Items->Add(msg);
- }
-
-
- /************************************************************************
- This is where all the work gets done
- ************************************************************************/
- BTI_SINT runTest(void)
- {
- /* Btrieve function parameters */
- BTI_BYTE posBlock1[128];
- BTI_BYTE posBlock2[128];
- BTI_BYTE dataBuf[255];
- BTI_WORD dataLen;
- BTI_BYTE keyBuf1[255];
- BTI_BYTE keyBuf2[255];
- BTI_WORD keyNum = 0;
-
- BTI_BYTE btrieveLoaded = FALSE;
- BTI_LONG personID;
- BTI_BYTE file1Open = FALSE;
- BTI_BYTE file2Open = FALSE;
- BTI_SINT status;
- BTI_SINT getStatus;
- BTI_SINT i;
- BTI_SINT posCtr;
-
- CLIENT_ID clientID;
- VERSION_STRUCT versionBuffer[3];
- FILE_CREATE_BUF fileCreateBuf;
- GNE_BUFFER_PTR gneBuffer;
- PERSON_STRUCT personRecord;
-
- BTI_CHAR tmpBuf[1024];
-
- /************************************************************************
- Print the program title
- ************************************************************************/
- printLB(Form1->ListBox1,
- "**** Btrieve -- C++ Builder Sample ****" );
-
- /* set up the Client ID */
- memset(clientID.networkAndNode, 0, sizeof(clientID.networkAndNode));
- memcpy(clientID.applicationID, "MT", 2); /* must be greater than "AA" */
- clientID.threadID = MY_THREAD_ID;
-
- memset(versionBuffer, 0, sizeof(versionBuffer));
- dataLen = sizeof(versionBuffer);
-
- status = BTRVID(
- B_VERSION,
- posBlock1,
- &versionBuffer,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- if (status == B_NO_ERROR)
- {
- strcpy(tmpBuf, "Btrieve Versions returned are: " );
- printLB(Form1->ListBox1, tmpBuf);
- for (i = 0; i < 3; i++) {
- if (versionBuffer[i].Version != 0)
- {
- sprintf(tmpBuf, " %d.%d %c", versionBuffer[i].Version,
- versionBuffer[i].Revision,
- versionBuffer[i].MKDEId );
- printLB(Form1->ListBox1, tmpBuf);
- }
- }
- printLB(Form1->ListBox1, "");
- btrieveLoaded = TRUE;
- }
- else
- {
- sprintf(tmpBuf, "Btrieve B_VERSION status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- if ( status != B_RECORD_MANAGER_INACTIVE )
- {
- btrieveLoaded = TRUE;
- }
- }
-
- /* clear buffers */
- if (status == B_NO_ERROR)
- {
- memset(dataBuf, 0, sizeof(dataBuf));
- memset(keyBuf1, 0, sizeof(keyBuf1));
- memset(keyBuf2, 0, sizeof(keyBuf2));
- }
-
- /* open sample.btr */
- if (status == B_NO_ERROR)
- {
- /********************************************************************
- IMPORTANT: You should modify the following to specify the
- complete path to 'sample.btr' for your environment.
- ********************************************************************/
- strcpy((BTI_CHAR *)keyBuf1, "c:\\pvsw\\samples\\sample.btr");
- strcpy((BTI_CHAR *)keyBuf2, "c:\\pvsw\\samples\\sample2.btr");
-
- keyNum = 0;
- dataLen = 0;
-
- status = BTRVID(
- B_OPEN,
- posBlock1,
- dataBuf,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_OPEN status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- if (status == B_NO_ERROR)
- {
- file1Open = TRUE;
- }
- }
-
- /* get the record with key 0 = 263512477 using B_GET_EQUAL */
- if (status == B_NO_ERROR)
- {
- memset(&personRecord, 0, sizeof(personRecord));
- dataLen = sizeof(personRecord);
- personID = 263512477; /* this is really a social security number */
- *(BTI_LONG BTI_FAR *)&keyBuf1[0] = personID;
- keyNum = 0;
-
- status = BTRVID(
- B_GET_EQUAL,
- posBlock1,
- &personRecord,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_GET_EQUAL status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- if (status == B_NO_ERROR)
- {
- sprintf(tmpBuf, "" );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "The retrieved record is:" );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "ID: %ld", personRecord.ID );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "Name: %s %s", personRecord.FirstName,
- personRecord.LastName );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "Street: %s", personRecord.Street );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "City: %s", personRecord.City );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "State: %s", personRecord.State );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "Zip: %s", personRecord.Zip );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "Country: %s", personRecord.Country );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "Phone: %s", personRecord.Phone );
- printLB(Form1->ListBox1, tmpBuf);
- sprintf(tmpBuf, "" );
- printLB(Form1->ListBox1, tmpBuf);
- }
- }
-
- /* perform a stat operation to populate the create buffer */
-
- memset(&fileCreateBuf, 0, sizeof(fileCreateBuf));
- dataLen = sizeof(fileCreateBuf);
- keyNum = (BTI_WORD)-1;
-
- status = BTRVID(B_STAT,
- posBlock1,
- &fileCreateBuf,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- if (status == B_NO_ERROR)
- {
- /* create and open sample2.btr */
- keyNum = 0;
- dataLen = sizeof(fileCreateBuf);
- status = BTRVID(B_CREATE,
- posBlock2,
- &fileCreateBuf,
- &dataLen,
- keyBuf2,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_CREATE status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- }
-
- if (status == B_NO_ERROR)
- {
- keyNum = 0;
- dataLen = 0;
-
- status = BTRVID(
- B_OPEN,
- posBlock2,
- dataBuf,
- &dataLen,
- keyBuf2,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_OPEN status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- if (status == B_NO_ERROR)
- {
- file2Open = TRUE;
- }
- }
-
- /* now extract data from the original file, insert into new one */
- if (status == B_NO_ERROR)
- {
- /* getFirst to establish currency */
- keyNum = 2; /* STATE-CITY index */
- memset(&personRecord, 0, sizeof(personRecord));
- memset(&keyBuf2[0], 0, sizeof(keyBuf2));
- dataLen = sizeof(personRecord);
-
- getStatus = BTRVID(
- B_GET_FIRST,
- posBlock1,
- &personRecord,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_GET_FIRST status = %d", getStatus );
- printLB(Form1->ListBox1, tmpBuf);
- }
-
- gneBuffer = (GNE_BUFFER_PTR)malloc(sizeof(GNE_BUFFER));
- if (gneBuffer == NULL)
- {
- strcpy(tmpBuf, "Insufficient memory to allocate buffer" );
- printLB(Form1->ListBox1, tmpBuf);
- return(EXIT_WITH_ERROR);
- }
- memset(gneBuffer, 0, sizeof(GNE_BUFFER));
- memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "UC", 2);
- while (getStatus == B_NO_ERROR)
- {
- gneBuffer->preBuf.gneHeader.rejectCount = 0;
- gneBuffer->preBuf.gneHeader.numberTerms = 2;
- posCtr = sizeof(GNE_HEADER);
-
- /* fill in the first condition */
- gneBuffer->preBuf.term1.fieldType = 11;
- gneBuffer->preBuf.term1.fieldLen = 3;
- gneBuffer->preBuf.term1.fieldOffset = 108;
- gneBuffer->preBuf.term1.comparisonCode = 1;
- gneBuffer->preBuf.term1.connector = 2;
- memcpy(&gneBuffer->preBuf.term1.value[0], "TX", 2);
- posCtr += sizeof(TERM_HEADER);
-
- /* fill in the second condition */
- gneBuffer->preBuf.term2.fieldType = 11;
- gneBuffer->preBuf.term2.fieldLen = 3;
- gneBuffer->preBuf.term2.fieldOffset = 108;
- gneBuffer->preBuf.term2.comparisonCode = 1;
- gneBuffer->preBuf.term2.connector = 0;
- memcpy(&gneBuffer->preBuf.term2.value[0], "CA", 2);
- posCtr += sizeof(TERM_HEADER);
-
- /* fill in the projection header to retrieve whole record */
- gneBuffer->preBuf.retrieval.maxRecsToRetrieve = 20;
- gneBuffer->preBuf.retrieval.noFieldsToRetrieve = 1;
- posCtr += sizeof(RETRIEVAL_HEADER);
- gneBuffer->preBuf.recordRet.fieldLen = sizeof(PERSON_STRUCT);
- gneBuffer->preBuf.recordRet.fieldOffset = 0;
- posCtr += sizeof(FIELD_RETRIEVAL_HEADER);
- gneBuffer->preBuf.gneHeader.descriptionLen = posCtr;
-
- dataLen = sizeof(GNE_BUFFER);
- getStatus = BTRVID(
- B_GET_NEXT_EXTENDED,
- posBlock1,
- gneBuffer,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_GET_NEXT_EXTENDED status = %d", getStatus );
- printLB(Form1->ListBox1, tmpBuf);
-
- /* Get Next Extended can reach end of file and still return some records */
- if ((getStatus == B_NO_ERROR) || (getStatus == B_END_OF_FILE))
- {
- sprintf(tmpBuf, "GetNextExtended returned %d records.", gneBuffer->postBuf.numReturned);
- printLB(Form1->ListBox1, tmpBuf);
- for (i = 0; i < gneBuffer->postBuf.numReturned; i++)
- {
- dataLen = sizeof(PERSON_STRUCT);
- memcpy(dataBuf, &gneBuffer->postBuf.recs[i].personRecord, dataLen);
- status = BTRVID(
- B_INSERT,
- posBlock2,
- dataBuf,
- &dataLen,
- keyBuf2,
- -1, /* no currency change */
- (BTI_BUFFER_PTR)&clientID);
- }
- sprintf(tmpBuf, "Inserted %d records in new file, status = %d",
- gneBuffer->postBuf.numReturned, status);
- printLB(Form1->ListBox1, tmpBuf);
- }
- memset(gneBuffer, 0, sizeof(GNE_BUFFER));
- memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "EG", 2);
- }
-
- free(gneBuffer);
- gneBuffer = NULL;
-
- /* close open files */
- if (file1Open)
- {
- dataLen = 0;
-
- status = BTRVID(
- B_CLOSE,
- posBlock1,
- dataBuf,
- &dataLen,
- keyBuf1,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_CLOSE status (sample.btr) = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- }
-
- if (file2Open)
- {
- dataLen = 0;
-
- status = BTRVID(
- B_CLOSE,
- posBlock2,
- dataBuf,
- &dataLen,
- keyBuf2,
- keyNum,
- (BTI_BUFFER_PTR)&clientID);
-
- sprintf(tmpBuf, "Btrieve B_CLOSE status (sample2.btr) = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- }
-
- /**********************************************************************
- ISSUE THE BTRIEVE STOP OPERATION - For multi-tasking environments,
- such as MS Windows, OS2, and NLM, 'stop' frees all Btrieve resources
- for this client. In DOS and Extended DOS, it removes the Btrieve
- engine from memory. In multi-tasking environments, the engine will
- not unload on 'stop' unless it has no more clients.
- ***********************************************************************/
- if (btrieveLoaded)
- {
- dataLen = 0;
- status = BTRVID(B_STOP, posBlock1, dataBuf, &dataLen, keyBuf1, keyNum,
- (BTI_BUFFER_PTR)&clientID);
- sprintf(tmpBuf, "Btrieve B_STOP status = %d", status );
- printLB(Form1->ListBox1, tmpBuf);
- if (status != B_NO_ERROR)
- {
- status = EXIT_WITH_ERROR;
- }
- }
-
- return(status);
- }
-
-