home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / kdbf / bcursor.cpp next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  115.8 KB  |  4,488 lines

  1. /*********************************************************************
  2. **
  3. **                          BCURSOR.CPP
  4. **
  5. ** This file contains member functions of the BCursor class.
  6. **  
  7. **
  8. *********************************************************************/
  9.  
  10. // DBF - (C) Copyright 1994 by Borland International
  11.  
  12. #include "kdbf.h"
  13. #pragma hdrstop
  14.  
  15. #ifdef __DLL__
  16.    #define EXPORT _export
  17. #else
  18.    #define EXPORT
  19. #endif
  20.  
  21. Retcode EXPORT addCursor(dbdef *, BCursor *);    // Prototype for utility 
  22.                                                  // function.
  23.  
  24. void EXPORT deleteCursor(dbdef *, BCursor *);    // Prototype for utility
  25.                                                  // function.
  26.  
  27. Retcode getDesc(TABLEHANDLE,int&, FieldDesc far *);  // Prototype utility
  28.                                                      // function in BDatabas.
  29.  
  30. Retcode EXPORT convertFld(void *, PXFieldType, int,  // Source value.
  31.                           void *, PXFieldType, int); // Destination.
  32.  
  33. int getPdxRecSize(FieldDesc far *desc, int numFields);
  34.  
  35. // Make only the object, not any Paradox cursors.
  36.  
  37. BCursor::BCursor()
  38. {
  39.     genericRec = 0;
  40.     curdef *co = 0;
  41.  
  42.     try
  43.     {
  44.         co = new curdef;       // See the INTSTRCT.H file.
  45.         lastError = DBIERR_NONE;
  46.         lastChange = 0;
  47.         co->handleCnt = 0;
  48.         co->fieldCnt = 0;
  49.         co->recList = 0;
  50.         curobj = (void *)co;
  51.         co->dbH = 0;
  52.         isOpen = FALSE;
  53.         curStatus = atBegin;
  54.         masterTabH = NULL;
  55.         tabname = NULL;
  56.         tabH = NULL;
  57.     }
  58.     catch(xalloc)
  59.     {
  60.         if (co)
  61.         {
  62.             delete co;
  63.         }
  64.         lastError = DBIERR_NOMEMORY;
  65.         return;
  66.     }
  67.  
  68. }
  69.  
  70. // Create the object and open a table of the same type as the database
  71. // (by default)
  72.  
  73. BCursor::BCursor(BDatabase *db,
  74.                  const char *tableName,
  75.                  int indexID,
  76.                  BOOL saveEveryChange,
  77.                  DBIOpenMode openMode,
  78.                  DBIShareMode shareMode,
  79.                  XLTMode xltMode)
  80. {
  81.     curdef       *co = 0;
  82.     CHAR         tblType[DBIMAXNAMELEN + 1];
  83.     FieldDesc    *fldDescs = 0;
  84.  
  85.     tabH = 0;
  86.     tabname = 0;
  87.  
  88.     try
  89.     {
  90.         co = new curdef;         // See the INTSTRCT.H file.
  91.  
  92.         co->handleCnt = 0;
  93.         co->recList = 0;
  94.         co->indexID = indexID;
  95.         co->fieldCnt = 0;
  96.         co->saveEveryChange = saveEveryChange;
  97.         curobj = (void *)co;
  98.         isOpen = FALSE;
  99.         curStatus = atBegin;
  100.         co->dbH = 0;
  101.         masterTabH = NULL;
  102.  
  103.         if (!db->isOpen)
  104.         {
  105.             lastError = PXERR_DBNOTOPEN;
  106.             throw lastError;
  107.         }
  108.  
  109.         strcpy(tblType, db->Driver);
  110.  
  111.         // Open the table
  112.  
  113.         lastError = openTable(db, tableName, tblType, indexID,
  114.                               openMode, shareMode, xltMode);
  115.  
  116.         if (lastError != DBIERR_NONE)
  117.         {
  118.             throw lastError;
  119.         }
  120.  
  121.         isOpen = TRUE;
  122.  
  123.         tabname = new char[(strlen(tableName)+1)];
  124.  
  125.         strcpy(tabname, tableName);
  126.         strcpy(tabtype, tblType);
  127.  
  128.         // Allocate descriptors, add this cursor to the database, and create a
  129.         // generic record. If any of these result in error, close the cursor
  130.         // and return an error.
  131.  
  132.         genericRec = new BRecord(this);
  133.         if (genericRec->lastError != DBIERR_NONE)
  134.         {
  135.             lastError = genericRec->lastError;
  136.             delete genericRec;
  137.             genericRec = 0;
  138.         }
  139.         else if ((lastError = addCursor((dbdef *)db->dbobj, this)) ==
  140.                   DBIERR_NONE)
  141.         {
  142.             co->dbH = db;
  143.             co->fieldCnt = db->getFieldCount(tableName);
  144.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  145.                                                   co->fieldCnt);
  146.             if (!co->desc)
  147.             {
  148.                 lastError = DBIERR_NOMEMORY;
  149.                 throw lastError;
  150.             }
  151.             else
  152.             {
  153.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  154.             }
  155.         }
  156.         if (lastError)
  157.         {
  158.             DbiCloseCursor(&tabH);
  159.             delete tabname;
  160.             isOpen = FALSE;
  161.         }
  162.     }
  163.     catch(xalloc)
  164.     {
  165.         if (tabname)
  166.         {
  167.             delete tabname;
  168.         }
  169.         if (fldDescs)
  170.         {
  171.             delete fldDescs;
  172.         }
  173.         lastError = DBIERR_NOMEMORY;
  174.         isOpen = FALSE;
  175.         if (tabH)
  176.         {
  177.             DbiCloseCursor(&tabH);
  178.         }
  179.         return;
  180.     }
  181.     catch(Retcode)
  182.     {
  183.         if (tabH)
  184.         {
  185.             DbiCloseCursor(&tabH);
  186.         }
  187.         if (fldDescs)
  188.         {
  189.             delete fldDescs;
  190.         }
  191.         if (tabname)
  192.         {
  193.             delete tabname;
  194.         }
  195.         isOpen = FALSE;
  196.         return;
  197.     }
  198. }
  199.  
  200. BCursor::BCursor(BDatabase *db,
  201.                  const char *tableName,
  202.                  const char *tableType,
  203.                  int indexID,
  204.                  DBIOpenMode openMode,
  205.                  DBIShareMode shareMode,
  206.                  XLTMode xltMode)
  207. {
  208.     curdef       *co = 0;
  209.     CHAR         tblType[DBIMAXNAMELEN + 1];
  210.     FieldDesc    *fldDescs = NULL;
  211.  
  212.     tabH = 0;
  213.     tabname = 0;
  214.  
  215.     try
  216.     {
  217.         co = new curdef;         // See the INTSTRCT.H file.
  218.  
  219.         co->handleCnt = 0;
  220.         co->recList = 0;
  221.         co->indexID = indexID;
  222.         co->fieldCnt = 0;
  223.         co->saveEveryChange = TRUE;
  224.         curobj = (void *)co;
  225.         isOpen = FALSE;
  226.         curStatus = atBegin;
  227.         co->dbH = 0;
  228.         masterTabH = NULL;
  229.         
  230.         if (!db->isOpen)
  231.         {
  232.             lastError = PXERR_DBNOTOPEN;
  233.             throw lastError;
  234.         }
  235.  
  236.         if (tableType == NULL)
  237.         {
  238.             strcpy(tblType, db->Driver);
  239.         }
  240.         else
  241.         {
  242.             strcpy(tblType, tableType);
  243.         }
  244.  
  245.         // Open the table
  246.         lastError = openTable(db, tableName, tblType, indexID,
  247.                               openMode, shareMode, xltMode);
  248.  
  249.         if (lastError != DBIERR_NONE)
  250.         {
  251.             throw lastError;
  252.         }
  253.         
  254.         isOpen = TRUE;
  255.  
  256.         tabname = new char[(strlen(tableName)+1)];
  257.         strcpy(tabname, tableName);
  258.         strcpy(tabtype, tblType);
  259.  
  260.         // Allocate descriptors, add this cursor to the database, and create a
  261.         // generic record. If any of these result in error, close the cursor
  262.         // and return an error.
  263.  
  264.         genericRec = new BRecord(this);
  265.  
  266.         if (genericRec->lastError != DBIERR_NONE)
  267.         {
  268.             lastError = genericRec->lastError;
  269.             delete genericRec;
  270.             genericRec = 0;
  271.         }
  272.         else if ((lastError = addCursor((dbdef *)db->dbobj, this)) ==
  273.                                         DBIERR_NONE)
  274.         {
  275.             co->dbH = db;
  276.             co->fieldCnt = db->getFieldCount(tableName);
  277.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  278.                                                   co->fieldCnt);
  279.             if (!co->desc)
  280.             {
  281.                 lastError = DBIERR_NOMEMORY;
  282.                 throw lastError;
  283.             }
  284.             else
  285.             {
  286.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  287.             }
  288.         }
  289.         if (lastError)
  290.         {
  291.             DbiCloseCursor(&tabH);
  292.             delete tabname;
  293.             isOpen = FALSE;
  294.         }
  295.     }
  296.     catch(xalloc)
  297.     {
  298.         if (tabname)
  299.         {
  300.             delete tabname;
  301.         }
  302.  
  303.         if (fldDescs)
  304.         {
  305.             delete fldDescs;
  306.         }
  307.         lastError = DBIERR_NOMEMORY;
  308.         isOpen = FALSE;
  309.         if (tabH)
  310.         {
  311.             DbiCloseCursor(&tabH);
  312.         }
  313.         return;
  314.     }
  315.     catch(Retcode)
  316.     {
  317.         if (tabH)
  318.         {
  319.             DbiCloseCursor(&tabH);
  320.         }
  321.         if (tabname)
  322.         {
  323.             delete tabname;
  324.         }
  325.  
  326.         if (fldDescs)
  327.         {
  328.             delete fldDescs;
  329.         }
  330.         isOpen = FALSE;
  331.         return;
  332.     }
  333. }
  334.  
  335. BCursor::BCursor(BDatabase *db,
  336.                  const char *tableName,
  337.                  const char *indexName,
  338.                  DBIOpenMode openMode,
  339.                  DBIShareMode shareMode,
  340.                  XLTMode xltMode)
  341. {
  342.     curdef       *co = 0;
  343.     CHAR         tblType[DBIMAXNAMELEN + 1];
  344.     CHAR         idxName[DBIMAXNAMELEN + 1];
  345.     unsigned int indexSeqNo;
  346.     FieldDesc    *fldDescs = NULL;
  347.     IDXDesc      idxDesc;
  348.  
  349.     tabH = 0;
  350.     tabname = 0;
  351.  
  352.     try
  353.     {
  354.         co = new curdef;         // See the INTSTRCT.H file.
  355.  
  356.         co->handleCnt = 0;
  357.         co->recList = 0;
  358.         co->indexID = 0;
  359.         co->fieldCnt = 0;
  360.         co->saveEveryChange = TRUE;
  361.         curobj = (void *)co;
  362.         isOpen = FALSE;
  363.         curStatus = atBegin;
  364.         co->dbH = 0;
  365.         masterTabH = NULL;
  366.         
  367.         if (!db->isOpen)
  368.         {
  369.             lastError = PXERR_DBNOTOPEN;
  370.             throw lastError;
  371.         }
  372.  
  373.         strcpy(tblType, db->Driver);
  374.  
  375.         // Open the table on the given index. Method depends on table type.
  376.  
  377.         if (!strcmp(tblType, szDBASE))
  378.         {
  379.             strcpy(idxName, tableName);
  380.             strncat(idxName, ".MDX", DBIMAXNAMELEN);
  381.             idxName[DBIMAXNAMELEN] = 0;
  382.             
  383.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  384.                                      (pCHAR)idxName, (pCHAR)indexName,
  385.                                      0, openMode, shareMode,
  386.                                      xltMode, FALSE, NULL, &tabH);
  387.         }
  388.         else
  389.         {
  390.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  391.                                      (pCHAR)indexName, NULL, 0,
  392.                                      openMode, shareMode, xltMode,
  393.                                      FALSE, NULL, &tabH);
  394.         }
  395.  
  396.         if (lastError != DBIERR_NONE)
  397.         {
  398.             throw lastError;
  399.         }
  400.  
  401.         isOpen = TRUE;
  402.  
  403.         // Get information about the index.
  404.  
  405.         if (!strcmp(tblType, szPARADOX))
  406.         {
  407.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL, NULL,
  408.                                          &indexSeqNo);
  409.             if (lastError == DBIERR_NONE)
  410.             {
  411.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  412.                 if (lastError == DBIERR_NONE)
  413.                 {
  414.                     co->indexID = idxDesc.iIndexId;
  415.                     strcpy(co->indexName, idxDesc.szName);
  416.                     strcpy(co->indexTag, idxDesc.szTagName);
  417.                 }
  418.             }
  419.             else
  420.             {
  421.                 co->indexID = 0;
  422.                 strcpy(co->indexName, "");
  423.                 strcpy(co->indexTag, "");
  424.             }
  425.         }
  426.         else if (!strcmp(tblType, szDBASE))
  427.         {
  428.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)idxName,
  429.                                          (pCHAR)indexName,
  430.                                          NULL, &indexSeqNo);
  431.             if (lastError == DBIERR_NONE)
  432.             {
  433.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  434.                 if (lastError == DBIERR_NONE)
  435.                 {
  436.                     co->indexID = idxDesc.iIndexId;
  437.                     strcpy(co->indexName, idxDesc.szName);
  438.                     strcpy(co->indexTag, idxDesc.szTagName);
  439.                 }
  440.             }
  441.             else
  442.             {
  443.                 co->indexID = 0;
  444.                 strcpy(co->indexName, "");
  445.                 strcpy(co->indexTag, "");
  446.             }
  447.         }
  448.         else
  449.         {
  450.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL,
  451.                                          NULL, &indexSeqNo);
  452.             if (lastError == DBIERR_NONE)
  453.             {
  454.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  455.                 if (lastError == DBIERR_NONE)
  456.                 {
  457.                     co->indexID = idxDesc.iIndexId;
  458.                     strcpy(co->indexName, idxDesc.szName);
  459.                     strcpy(co->indexTag, idxDesc.szTagName);
  460.                 }
  461.             }
  462.             else
  463.             {
  464.                 co->indexID = 0;
  465.                 strcpy(co->indexName, "");
  466.                 strcpy(co->indexTag, "");
  467.             }
  468.         }
  469.        
  470.         tabname = new char[(strlen(tableName)+1)];
  471.         strcpy(tabname, tableName);
  472.         strcpy(tabtype, tblType);
  473.  
  474.         // Allocate descriptors, add this cursor to the database, and create a
  475.         // generic record. If any of these result in error, close the cursor
  476.         // and return an error.
  477.  
  478.         genericRec = new BRecord(this);
  479.  
  480.         if (genericRec->lastError != DBIERR_NONE)
  481.         {
  482.             lastError = genericRec->lastError;
  483.             delete genericRec;
  484.             genericRec = 0;
  485.         }
  486.         else if ((lastError = addCursor((dbdef *)db->dbobj, this)) ==
  487.                                         DBIERR_NONE)
  488.         {
  489.             co->dbH = db;
  490.             co->fieldCnt = db->getFieldCount(tableName);
  491.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  492.                                                   co->fieldCnt);
  493.             if (!co->desc)
  494.             {
  495.                 lastError = DBIERR_NOMEMORY;
  496.                 throw lastError;
  497.             }
  498.             else
  499.             {
  500.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  501.             }
  502.         }
  503.         if (lastError)
  504.         {
  505.             DbiCloseCursor(&tabH);
  506.             delete tabname;
  507.             isOpen = FALSE;
  508.         }
  509.     }
  510.     catch(xalloc)
  511.     {
  512.         if (tabname)
  513.         {
  514.             delete tabname;
  515.         }
  516.  
  517.         if (fldDescs)
  518.         {
  519.             delete fldDescs;
  520.         }
  521.         lastError = DBIERR_NOMEMORY;
  522.         isOpen = FALSE;
  523.         if (tabH)
  524.         {
  525.             DbiCloseCursor(&tabH);
  526.         }
  527.         return;
  528.     }
  529.     catch(Retcode)
  530.     {
  531.         if (tabH)
  532.         {
  533.             DbiCloseCursor(&tabH);
  534.         }
  535.         if (tabname)
  536.         {
  537.             delete tabname;
  538.         }
  539.  
  540.         if (fldDescs)
  541.         {
  542.             delete fldDescs;
  543.         }
  544.         isOpen = FALSE;
  545.         return;
  546.     }
  547. }
  548.  
  549. BCursor::BCursor(BDatabase *db,
  550.                  const char *tableName,
  551.                  const char *indexName,
  552.                  const char *indexTagName,
  553.                  DBIOpenMode openMode,
  554.                  DBIShareMode shareMode,
  555.                  XLTMode xltMode)
  556. {
  557.     curdef       *co = 0;
  558.     CHAR         tblType[DBIMAXNAMELEN + 1];
  559.     unsigned int indexSeqNo;
  560.     FieldDesc    *fldDescs = NULL;
  561.     IDXDesc      idxDesc;
  562.  
  563.     tabH = 0;
  564.     tabname = 0;
  565.  
  566.     try
  567.     {
  568.         co = new curdef;         // See the INTSTRCT.H file.
  569.  
  570.         co->handleCnt = 0;
  571.         co->recList = 0;
  572.         co->indexID = 0;
  573.         co->fieldCnt = 0;
  574.         co->saveEveryChange = TRUE;
  575.         curobj = (void *)co;
  576.         isOpen = FALSE;
  577.         curStatus = atBegin;
  578.         co->dbH = 0;
  579.         masterTabH = NULL;
  580.         
  581.         if (!db->isOpen)
  582.         {
  583.             lastError = PXERR_DBNOTOPEN;
  584.             throw lastError;
  585.         }
  586.  
  587.         strcpy(tblType, db->Driver);
  588.  
  589.         // Open the table on the specified index. Note that the method
  590.         //   depends on the table format.
  591.  
  592.         if (!strcmp(tblType, szDBASE))
  593.         {
  594.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  595.                                      (pCHAR)indexName, (pCHAR)indexTagName,
  596.                                      0, openMode, shareMode,
  597.                                      xltMode, FALSE, NULL, &tabH);
  598.         }
  599.         else
  600.         {
  601.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  602.                                      (pCHAR)indexName, NULL, 0,
  603.                                      openMode, shareMode, xltMode,
  604.                                      FALSE, NULL, &tabH);
  605.         }
  606.  
  607.         if (lastError != DBIERR_NONE)
  608.         {
  609.             throw lastError;
  610.         }
  611.  
  612.         isOpen = TRUE;
  613.  
  614.         // Get information about the index.
  615.  
  616.         if (!strcmp(tblType, szPARADOX))
  617.         {
  618.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL, NULL,
  619.                                          &indexSeqNo);
  620.             if (lastError == DBIERR_NONE)
  621.             {
  622.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  623.                 if (lastError == DBIERR_NONE)
  624.                 {
  625.                     co->indexID = idxDesc.iIndexId;
  626.                     strcpy(co->indexName, idxDesc.szName);
  627.                     strcpy(co->indexTag, idxDesc.szTagName);
  628.                 }
  629.             }
  630.             else
  631.             {
  632.                 co->indexID = 0;
  633.                 strcpy(co->indexName, "");
  634.                 strcpy(co->indexTag, "");
  635.             }
  636.         }
  637.         else if (!strcmp(tblType, szDBASE))
  638.         {
  639.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName,
  640.                                          (pCHAR)indexTagName,
  641.                                          NULL, &indexSeqNo);
  642.             if (lastError == DBIERR_NONE)
  643.             {
  644.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  645.                 if (lastError == DBIERR_NONE)
  646.                 {
  647.                     co->indexID = idxDesc.iIndexId;
  648.                     strcpy(co->indexName, idxDesc.szName);
  649.                     strcpy(co->indexTag, idxDesc.szTagName);
  650.                 }
  651.             }
  652.             else
  653.             {
  654.                 co->indexID = 0;
  655.                 strcpy(co->indexName, "");
  656.                 strcpy(co->indexTag, "");
  657.             }
  658.         }
  659.         else
  660.         {
  661.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL,
  662.                                          NULL, &indexSeqNo);
  663.             if (lastError == DBIERR_NONE)
  664.             {
  665.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  666.                 if (lastError == DBIERR_NONE)
  667.                 {
  668.                     co->indexID = idxDesc.iIndexId;
  669.                     strcpy(co->indexName, idxDesc.szName);
  670.                     strcpy(co->indexTag, idxDesc.szTagName);
  671.                 }
  672.             }
  673.             else
  674.             {
  675.                 co->indexID = 0;
  676.                 strcpy(co->indexName, "");
  677.                 strcpy(co->indexTag, "");
  678.             }
  679.         }
  680.        
  681.         tabname = new char[(strlen(tableName)+1)];
  682.         strcpy(tabname, tableName);
  683.         strcpy(tabtype, tblType);
  684.  
  685.         // Allocate descriptors, add this cursor to the database, and create a
  686.         // generic record. If any of these result in error, close the cursor
  687.         // and return an error.
  688.  
  689.         genericRec = new BRecord(this);
  690.  
  691.         if (genericRec->lastError != DBIERR_NONE)
  692.         {
  693.             lastError = genericRec->lastError;
  694.             delete genericRec;
  695.             genericRec = 0;
  696.         }
  697.         else if ((lastError = addCursor((dbdef *)db->dbobj, this)) ==
  698.                                         DBIERR_NONE)
  699.         {
  700.             co->dbH = db;
  701.             co->fieldCnt = db->getFieldCount(tableName);
  702.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  703.                                                   co->fieldCnt);
  704.             if (!co->desc)
  705.             {
  706.                 lastError = DBIERR_NOMEMORY;
  707.                 throw lastError;
  708.             }
  709.             else
  710.             {
  711.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  712.             }
  713.         }
  714.         if (lastError)
  715.         {
  716.             DbiCloseCursor(&tabH);
  717.             delete tabname;
  718.             isOpen = FALSE;
  719.         }
  720.     }
  721.     catch(xalloc)
  722.     {
  723.         if (tabname)
  724.         {
  725.             delete tabname;
  726.         }
  727.  
  728.         if (fldDescs)
  729.         {
  730.             delete fldDescs;
  731.         }
  732.         lastError = DBIERR_NOMEMORY;
  733.         isOpen = FALSE;
  734.         if (tabH)
  735.         {
  736.             DbiCloseCursor(&tabH);
  737.         }
  738.         return;
  739.     }
  740.     catch(Retcode)
  741.     {
  742.         if (tabH)
  743.         {
  744.             DbiCloseCursor(&tabH);
  745.         }
  746.         if (tabname)
  747.         {
  748.             delete tabname;
  749.         }
  750.  
  751.         if (fldDescs)
  752.         {
  753.             delete fldDescs;
  754.         }
  755.         isOpen = FALSE;
  756.         return;
  757.     }
  758. }
  759.  
  760. // Destructor that closes the cursor if it's open.
  761.  
  762. BCursor::~BCursor()
  763. {
  764.     if (isOpen)
  765.     {
  766.         close();
  767.     }
  768.  
  769.     curdef *co  = (curdef *)curobj;
  770.     if (co)
  771.     {
  772.         if (co->handleCnt)
  773.         {
  774.             delete [] co->recList;    // Delete the array of record handles.
  775.         }
  776.  
  777.         if (co->dbH)                // If database object exists, disconnect
  778.         {
  779.             deleteCursor((dbdef *)    // cursor from the database.
  780.                          co->dbH->dbobj, this);
  781.         }
  782.         delete co;
  783.     }
  784. }
  785.  
  786. // Open a cursor on the specified table. indexID specifies the index to use,
  787. // with 0 representing the primary index.
  788.  
  789. Retcode BCursor::open(BDatabase *db,
  790.                       const char *tableName,
  791.                       int indexID,
  792.                       BOOL saveEveryChange,
  793.                       DBIOpenMode openMode,
  794.                       DBIShareMode shareMode,
  795.                       XLTMode xltMode)
  796. {
  797.     CHAR              tblType[DBIMAXNAMELEN + 1];
  798.     curdef            *co = (curdef *)curobj;
  799.     FieldDesc         *fldDescs = NULL;
  800.  
  801.     if (isOpen)
  802.     {
  803.         lastError = PXERR_CURSORALREADYOPEN;
  804.         return lastError;
  805.     }
  806.  
  807.     if (!db->isOpen)
  808.     {
  809.         lastError = PXERR_DBNOTOPEN;
  810.         return lastError;
  811.     }
  812.  
  813.     tabH = NULL;
  814.     tabname = NULL;
  815.  
  816.     try
  817.     {
  818.         strcpy(tblType, db->Driver);
  819.  
  820.         // Open the table
  821.  
  822.         lastError = openTable(db, tableName, tblType, indexID,
  823.                               openMode, shareMode, xltMode);
  824.  
  825.         if (lastError != DBIERR_NONE)
  826.         {
  827.             throw lastError;
  828.         }
  829.  
  830.         isOpen = TRUE;
  831.  
  832.         curStatus = atBegin;
  833.         if (co->dbH != db)
  834.         {
  835.             // If the database for the cursor is changed, delete old context
  836.             // and add the new one.
  837.  
  838.             if (co->dbH)                        // If database object exists,
  839.             {
  840.                 deleteCursor((dbdef *)              // delete cursor from list.
  841.                              co->dbH->dbobj, this);
  842.             } 
  843.             addCursor((dbdef *) db->dbobj, this);
  844.         }
  845.         co->dbH = db;
  846.         co->indexID = indexID;
  847.         co->saveEveryChange = saveEveryChange;
  848.  
  849.         tabname = new char[strlen(tableName)+1];
  850.         strcpy(tabname, tableName);
  851.         strcpy(tabtype, tblType);
  852.  
  853.         // Create generic record and store the table description
  854.         // with every open cursor so that:
  855.         //
  856.         // 1. All records for a cursor share the same table description.
  857.         //
  858.         // 2. The BDE is not called for the type of a field
  859.         //    with every Get and Put field operation performed on generic
  860.         //    and custom records.
  861.  
  862.         genericRec = new BRecord(this);
  863.         if (genericRec->lastError != DBIERR_NONE)
  864.         {
  865.             lastError = genericRec->lastError;
  866.             delete genericRec;
  867.             genericRec = 0;
  868.         }
  869.         else
  870.         {
  871.             co->fieldCnt = db->getFieldCount(tableName);
  872.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  873.                                                   co->fieldCnt);
  874.             if (!co->desc)
  875.             {
  876.                 lastError = DBIERR_NOMEMORY;
  877.                 throw lastError;
  878.             }
  879.             else
  880.             {
  881.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  882.             }
  883.         }
  884.         if (lastError)
  885.         {
  886.             DbiCloseCursor(&tabH);
  887.             delete tabname;
  888.             isOpen = FALSE;
  889.         }
  890.     }
  891.     catch(xalloc)
  892.     {
  893.         if (tabname)
  894.         {
  895.             delete tabname;
  896.         }
  897.         if (fldDescs)
  898.         {
  899.             delete fldDescs;
  900.         }
  901.         lastError = DBIERR_NOMEMORY;
  902.         isOpen = FALSE;
  903.         if (tabH)
  904.         {
  905.             DbiCloseCursor(&tabH);
  906.         }
  907.         return lastError;
  908.     }
  909.     catch(...)
  910.     {
  911.         if (tabH)
  912.         {
  913.             DbiCloseCursor(&tabH);
  914.         }
  915.         if (tabname)
  916.         {
  917.             delete tabname;
  918.         }
  919.         if (fldDescs)
  920.         {
  921.             delete fldDescs;
  922.         }
  923.         isOpen = FALSE;
  924.         return lastError;
  925.     }
  926.  
  927.     return lastError;
  928. }
  929.  
  930. Retcode BCursor::open(BDatabase *db,
  931.                       const char *tableName,
  932.                       const char *tableType,
  933.                       int indexID,
  934.                       DBIOpenMode openMode,
  935.                       DBIShareMode shareMode,
  936.                       XLTMode xltMode)
  937. {
  938.     char              tblType[DBIMAXNAMELEN+1];
  939.     curdef            *co = (curdef *)curobj;
  940.  
  941.     if (isOpen)
  942.     {
  943.         lastError = PXERR_CURSORALREADYOPEN;
  944.         return lastError;
  945.     }
  946.  
  947.     if (!db->isOpen)
  948.     {
  949.         return lastError;
  950.     }
  951.  
  952.     tabH = NULL;
  953.     tabname = NULL;
  954.  
  955.     try
  956.     {
  957.         if (tableType == NULL)
  958.         {
  959.             strcpy(tblType, db->Driver);
  960.         }
  961.         else
  962.         {
  963.             strcpy(tblType, tableType);
  964.         }
  965.  
  966.         // Open the table
  967.         lastError = openTable(db, tableName, tblType, indexID,
  968.                               openMode, shareMode, xltMode);
  969.  
  970.         if (lastError != DBIERR_NONE)
  971.         {
  972.             throw lastError;
  973.         }
  974.         
  975.         isOpen = TRUE;
  976.  
  977.         curStatus = atBegin;
  978.         if (co->dbH != db)
  979.         {
  980.             // If the database for the cursor is changed, delete old context
  981.             // and add the new one.
  982.  
  983.             if (co->dbH)                         // If database object exists,
  984.             {
  985.                 deleteCursor((dbdef *)              // delete cursor from list.
  986.                              co->dbH->dbobj, this);
  987.             }
  988.             addCursor((dbdef *) db->dbobj, this);
  989.         }
  990.         co->dbH = db;
  991.         co->saveEveryChange = TRUE;
  992.         tabname = new char[strlen(tableName)+1];
  993.         strcpy(tabname, tableName);
  994.         strcpy(tabtype, tblType);
  995.  
  996.         // Create generic record and store the table description
  997.         // with every open cursor so that:
  998.         //
  999.         // 1. All records for a cursor share the same table description.
  1000.         //
  1001.         // 2. The Paradox Engine is not called for the type of a field
  1002.         //    with every Get and Put field operation performed on generic
  1003.         //    and custom records.
  1004.  
  1005.         genericRec = new BRecord(this);
  1006.         
  1007.         if (genericRec->lastError != DBIERR_NONE)
  1008.         {
  1009.             lastError = genericRec->lastError;
  1010.             delete genericRec;
  1011.             genericRec = 0;
  1012.         }
  1013.         else
  1014.         {
  1015.             co->fieldCnt = db->getFieldCount(tableName);
  1016.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  1017.                                                   co->fieldCnt);
  1018.             if (!co->desc)
  1019.             {
  1020.                 lastError = DBIERR_NOMEMORY;
  1021.                 throw lastError;
  1022.             }
  1023.             else
  1024.             {
  1025.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  1026.             }
  1027.         }
  1028.         if (lastError)
  1029.         {
  1030.             DbiCloseCursor(&tabH);
  1031.             delete tabname;
  1032.             isOpen = FALSE;
  1033.         }
  1034.     }
  1035.     catch(xalloc)
  1036.     {
  1037.         if (tabname)
  1038.         {
  1039.             delete tabname;
  1040.         }
  1041.         lastError = DBIERR_NOMEMORY;
  1042.         isOpen = FALSE;
  1043.         if (tabH)
  1044.         {
  1045.             DbiCloseCursor(&tabH);
  1046.         }
  1047.         return lastError;
  1048.     }
  1049.     catch(...)
  1050.     {
  1051.         if ((lastError == PXERR_CURSORALREADYOPEN) ||
  1052.             (lastError == PXERR_DBNOTOPEN))
  1053.         {
  1054.             return lastError;
  1055.         }
  1056.         if (tabH)
  1057.         {
  1058.             DbiCloseCursor(&tabH);
  1059.         }
  1060.         if ((tabname) && (isOpen))
  1061.         {
  1062.             delete tabname;
  1063.         }
  1064.         isOpen = FALSE;
  1065.         return lastError;
  1066.     }
  1067.  
  1068.     return lastError;
  1069. }
  1070.  
  1071. Retcode BCursor::open(BDatabase *db,
  1072.                       const char *tableName,
  1073.                       const char *indexName,
  1074.                       DBIOpenMode openMode,
  1075.                       DBIShareMode shareMode,
  1076.                       XLTMode xltMode)
  1077. {
  1078.     CHAR              tblType[DBIMAXNAMELEN+1];
  1079.     CHAR              idxName[DBIMAXNAMELEN+1];
  1080.     curdef            *co = (curdef *)curobj;
  1081.     unsigned int      indexSeqNo;
  1082.     IDXDesc           idxDesc;
  1083.  
  1084.     if (isOpen)
  1085.     {
  1086.         lastError = PXERR_CURSORALREADYOPEN;
  1087.         return lastError;
  1088.     }
  1089.  
  1090.     if (!db->isOpen)
  1091.     {
  1092.         return lastError;
  1093.     }
  1094.  
  1095.     tabH = NULL;
  1096.     tabname = NULL;
  1097.  
  1098.     try
  1099.     {                        
  1100.         strcpy(tblType, db->Driver);
  1101.  
  1102.         // Open the table. Index used depends on the type of the table
  1103.         if (!strcmp(tblType, szDBASE))
  1104.         {
  1105.             strcpy(idxName, tableName);
  1106.             strncat(idxName, ".MDX", DBIMAXNAMELEN);
  1107.             idxName[DBIMAXNAMELEN] = 0;
  1108.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  1109.                                      (pCHAR)idxName, (pCHAR)indexName,
  1110.                                      NULL, openMode, shareMode,
  1111.                                      xltMode, FALSE, NULL, &tabH);
  1112.         }
  1113.         else
  1114.         {
  1115.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  1116.                                      (pCHAR)indexName, NULL, NULL,
  1117.                                      openMode, shareMode, xltMode,
  1118.                                      FALSE, NULL, &tabH);
  1119.         }
  1120.  
  1121.         if (lastError != DBIERR_NONE)
  1122.         {
  1123.             throw lastError;
  1124.         }
  1125.  
  1126.         isOpen = TRUE;
  1127.  
  1128.         // Get information about the index. Depends on table type
  1129.         if (!strcmp(tblType, szPARADOX))
  1130.         {
  1131.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL, NULL,
  1132.                                          &indexSeqNo);
  1133.             if (lastError == DBIERR_NONE)
  1134.             {
  1135.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1136.                 if (lastError == DBIERR_NONE)
  1137.                 {
  1138.                     co->indexID = idxDesc.iIndexId;
  1139.                     strcpy(co->indexName, idxDesc.szName);
  1140.                     strcpy(co->indexTag, idxDesc.szTagName);
  1141.                 }
  1142.             }
  1143.             else
  1144.             {
  1145.                 co->indexID = 0;
  1146.                 strcpy(co->indexName, "");
  1147.                 strcpy(co->indexTag, "");
  1148.             }
  1149.         }
  1150.         else if (!strcmp(tblType, szDBASE))
  1151.         {
  1152.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)idxName,
  1153.                                          (pCHAR)indexName,
  1154.                                          NULL, &indexSeqNo);
  1155.             if (lastError == DBIERR_NONE)
  1156.             {
  1157.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1158.                 if (lastError == DBIERR_NONE)
  1159.                 {
  1160.                     co->indexID = idxDesc.iIndexId;
  1161.                     strcpy(co->indexName, idxDesc.szName);
  1162.                     strcpy(co->indexTag, idxDesc.szTagName);
  1163.                 }
  1164.             }
  1165.             else
  1166.             {
  1167.                 co->indexID = 0;
  1168.                 strcpy(co->indexName, "");
  1169.                 strcpy(co->indexTag, "");
  1170.             }
  1171.         }
  1172.         else
  1173.         {
  1174.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL,
  1175.                                          NULL, &indexSeqNo);
  1176.             if (lastError == DBIERR_NONE)
  1177.             {
  1178.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1179.                 if (lastError == DBIERR_NONE)
  1180.                 {
  1181.                     co->indexID = idxDesc.iIndexId;
  1182.                     strcpy(co->indexName, idxDesc.szName);
  1183.                     strcpy(co->indexTag, idxDesc.szTagName);
  1184.                 }
  1185.             }
  1186.             else
  1187.             {
  1188.                 co->indexID = 0;
  1189.                 strcpy(co->indexName, "");
  1190.                 strcpy(co->indexTag, "");
  1191.             }
  1192.         }
  1193.  
  1194.         curStatus = atBegin;
  1195.         if (co->dbH != db)
  1196.         {
  1197.             // If the database for the cursor is changed, delete old context
  1198.             // and add the new one.
  1199.  
  1200.             if (co->dbH)                         // If database object exists,
  1201.             {
  1202.                 deleteCursor((dbdef *)              // delete cursor from list.
  1203.                              co->dbH->dbobj, this);
  1204.             }
  1205.             addCursor((dbdef *) db->dbobj, this);
  1206.         }
  1207.         co->dbH = db;
  1208.         co->saveEveryChange = TRUE;
  1209.         tabname = new char[strlen(tableName)+1];
  1210.         strcpy(tabname, tableName);
  1211.         strcpy(tabtype, tblType);
  1212.  
  1213.         // Create generic record and store the table description
  1214.         // with every open cursor so that:
  1215.         //
  1216.         // 1. All records for a cursor share the same table description.
  1217.         //
  1218.         // 2. The Paradox Engine is not called for the type of a field
  1219.         //    with every Get and Put field operation performed on generic
  1220.         //    and custom records.
  1221.  
  1222.         genericRec = new BRecord(this);
  1223.         
  1224.         if (genericRec->lastError != DBIERR_NONE)
  1225.         {
  1226.             lastError = genericRec->lastError;
  1227.             delete genericRec;
  1228.             genericRec = 0;
  1229.         }
  1230.         else
  1231.         {
  1232.             co->fieldCnt = db->getFieldCount(tableName);
  1233.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  1234.                                                   co->fieldCnt);
  1235.             if (!co->desc)
  1236.             {
  1237.                 lastError = DBIERR_NOMEMORY;
  1238.                 throw lastError;
  1239.             }
  1240.             else
  1241.             {
  1242.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  1243.             }
  1244.         }
  1245.         if (lastError)
  1246.         {
  1247.             DbiCloseCursor(&tabH);
  1248.             delete tabname;
  1249.             isOpen = FALSE;
  1250.         }
  1251.     }
  1252.     catch(xalloc)
  1253.     {
  1254.         if (tabname)
  1255.         {
  1256.             delete tabname;
  1257.         }
  1258.         lastError = DBIERR_NOMEMORY;
  1259.         isOpen = FALSE;
  1260.         if (tabH)
  1261.         {
  1262.             DbiCloseCursor(&tabH);
  1263.         }
  1264.         return lastError;
  1265.     }
  1266.     catch(...)
  1267.     {
  1268.         if ((lastError == PXERR_CURSORALREADYOPEN) ||
  1269.             (lastError == PXERR_DBNOTOPEN))
  1270.         {
  1271.             return lastError;
  1272.         }
  1273.         if (tabH)
  1274.         {
  1275.             DbiCloseCursor(&tabH);
  1276.         }
  1277.         if ((tabname) && (isOpen))
  1278.         {
  1279.             delete tabname;
  1280.         }
  1281.         isOpen = FALSE;
  1282.         return lastError;
  1283.     }
  1284.  
  1285.     return lastError;
  1286. }
  1287.  
  1288. Retcode BCursor::open(BDatabase *db,
  1289.                       const char *tableName,
  1290.                       const char *indexName,
  1291.                       const char *indexTagName,
  1292.                       DBIOpenMode openMode,
  1293.                       DBIShareMode shareMode,
  1294.                       XLTMode xltMode)
  1295. {
  1296.     char              tblType[DBIMAXNAMELEN+1];
  1297.     curdef            *co = (curdef *)curobj;
  1298.     unsigned int      indexSeqNo;
  1299.     IDXDesc           idxDesc;
  1300.  
  1301.     if (isOpen)
  1302.     {
  1303.         lastError = PXERR_CURSORALREADYOPEN;
  1304.         return lastError;
  1305.     }
  1306.  
  1307.     if (!db->isOpen)
  1308.     {
  1309.         return lastError;
  1310.     }
  1311.  
  1312.     tabH = NULL;
  1313.     tabname = NULL;
  1314.  
  1315.     try
  1316.     {                        
  1317.         strcpy(tblType, db->Driver);
  1318.  
  1319.         // Open the table. Index depends on data source.
  1320.         if (!strcmp(tblType, szDBASE))
  1321.         {
  1322.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  1323.                                      (pCHAR)indexName, (pCHAR)indexTagName,
  1324.                                      NULL, openMode, shareMode,
  1325.                                      xltMode, FALSE, NULL, &tabH);
  1326.         }
  1327.         else
  1328.         {
  1329.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  1330.                                      (pCHAR)indexName, NULL, NULL,
  1331.                                      openMode, shareMode, xltMode,
  1332.                                      FALSE, NULL, &tabH);
  1333.         }
  1334.  
  1335.         if (lastError != DBIERR_NONE)
  1336.         {
  1337.             throw lastError;
  1338.         }
  1339.  
  1340.         isOpen = TRUE;
  1341.  
  1342.         // Get information about the index. Method depends on data source.
  1343.  
  1344.         if (!strcmp(tblType, szPARADOX))
  1345.         {
  1346.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL, NULL,
  1347.                                          &indexSeqNo);
  1348.             if (lastError == DBIERR_NONE)
  1349.             {
  1350.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1351.                 if (lastError == DBIERR_NONE)
  1352.                 {
  1353.                     co->indexID = idxDesc.iIndexId;
  1354.                     strcpy(co->indexName, idxDesc.szName);
  1355.                     strcpy(co->indexTag, idxDesc.szTagName);
  1356.                 }
  1357.             }
  1358.             else
  1359.             {
  1360.                 co->indexID = 0;
  1361.                 strcpy(co->indexName, "");
  1362.                 strcpy(co->indexTag, "");
  1363.             }
  1364.         }
  1365.         else if (!strcmp(tblType, szDBASE))
  1366.         {
  1367.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName,
  1368.                                          (pCHAR)indexTagName,
  1369.                                          NULL, &indexSeqNo);
  1370.             if (lastError == DBIERR_NONE)
  1371.             {
  1372.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1373.                 if (lastError == DBIERR_NONE)
  1374.                 {
  1375.                     co->indexID = idxDesc.iIndexId;
  1376.                     strcpy(co->indexName, idxDesc.szName);
  1377.                     strcpy(co->indexTag, idxDesc.szTagName);
  1378.                 }
  1379.             }
  1380.             else
  1381.             {
  1382.                 co->indexID = 0;
  1383.                 strcpy(co->indexName, "");
  1384.                 strcpy(co->indexTag, "");
  1385.             }
  1386.         }
  1387.         else
  1388.         {
  1389.             lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, NULL,
  1390.                                          NULL, &indexSeqNo);
  1391.             if (lastError == DBIERR_NONE)
  1392.             {
  1393.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  1394.                 if (lastError == DBIERR_NONE)
  1395.                 {
  1396.                     co->indexID = idxDesc.iIndexId;
  1397.                     strcpy(co->indexName, idxDesc.szName);
  1398.                     strcpy(co->indexTag, idxDesc.szTagName);
  1399.                 }
  1400.             }
  1401.             else
  1402.             {
  1403.                 co->indexID = 0;
  1404.                 strcpy(co->indexName, "");
  1405.                 strcpy(co->indexTag, "");
  1406.             }
  1407.         }
  1408.  
  1409.         curStatus = atBegin;
  1410.         if (co->dbH != db)
  1411.         {
  1412.             // If the database for the cursor is changed, delete old context
  1413.             // and add the new one.
  1414.  
  1415.             if (co->dbH)                         // If database object exists,
  1416.             {
  1417.                 deleteCursor((dbdef *)              // delete cursor from list.
  1418.                              co->dbH->dbobj, this);
  1419.             }
  1420.             addCursor((dbdef *) db->dbobj, this);
  1421.         }
  1422.         co->dbH = db;
  1423.         co->saveEveryChange = TRUE;
  1424.         tabname = new char[strlen(tableName)+1];
  1425.         strcpy(tabname, tableName);
  1426.         strcpy(tabtype, tblType);
  1427.  
  1428.         // Create generic record and store the table description
  1429.         // with every open cursor so that:
  1430.         //
  1431.         // 1. All records for a cursor share the same table description.
  1432.         //
  1433.         // 2. The Paradox Engine is not called for the type of a field
  1434.         //    with every Get and Put field operation performed on generic
  1435.         //    and custom records.
  1436.  
  1437.         genericRec = new BRecord(this);
  1438.         
  1439.         if (genericRec->lastError != DBIERR_NONE)
  1440.         {
  1441.             lastError = genericRec->lastError;
  1442.             delete genericRec;
  1443.             genericRec = 0;
  1444.         }
  1445.         else
  1446.         {
  1447.             co->fieldCnt = db->getFieldCount(tableName);
  1448.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  1449.                                                   co->fieldCnt);
  1450.             if (!co->desc)
  1451.             {
  1452.                 lastError = DBIERR_NOMEMORY;
  1453.                 throw lastError;
  1454.             }
  1455.             else
  1456.             {
  1457.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  1458.             }
  1459.         }
  1460.         if (lastError)
  1461.         {
  1462.             DbiCloseCursor(&tabH);
  1463.             delete tabname;
  1464.             isOpen = FALSE;
  1465.         }
  1466.     }
  1467.     catch(xalloc)
  1468.     {
  1469.         if (tabname)
  1470.         {
  1471.             delete tabname;
  1472.         }
  1473.         lastError = DBIERR_NOMEMORY;
  1474.         isOpen = FALSE;
  1475.         if (tabH)
  1476.         {
  1477.             DbiCloseCursor(&tabH);
  1478.         }
  1479.         return lastError;
  1480.     }
  1481.     catch(...)
  1482.     {
  1483.         if ((lastError == PXERR_CURSORALREADYOPEN) ||
  1484.             (lastError == PXERR_DBNOTOPEN))
  1485.         {
  1486.             return lastError;
  1487.         }
  1488.         if (tabH)
  1489.         {
  1490.             DbiCloseCursor(&tabH);
  1491.         }
  1492.         if ((tabname) && (isOpen))
  1493.         {
  1494.             delete tabname;
  1495.         }
  1496.         isOpen = FALSE;
  1497.         return lastError;
  1498.     }
  1499.  
  1500.     return lastError;
  1501. }
  1502.  
  1503. Retcode BCursor::attach(BDatabase *db, TABLEHANDLE tableHandle)
  1504. {
  1505.     CURProps    curProps;
  1506.  
  1507.     if (isOpen)
  1508.     {
  1509.         lastError = PXERR_CURSORALREADYOPEN;
  1510.         return lastError;
  1511.     }
  1512.  
  1513.     if (!db->isOpen)
  1514.     {
  1515.         lastError = PXERR_DBNOTOPEN;
  1516.         return lastError;
  1517.     }
  1518.  
  1519.     tabH = NULL;
  1520.     tabname = NULL;
  1521.  
  1522.     try
  1523.     {
  1524.         if ((lastError = DbiCloneCursor(tableHandle, FALSE, FALSE, &tabH))
  1525.              != DBIERR_NONE)
  1526.         {
  1527.             throw lastError;
  1528.         }
  1529.  
  1530.         lastError = DbiGetCursorProps(tabH, &curProps);
  1531.         if (lastError)
  1532.         {
  1533.             throw lastError;
  1534.         }
  1535.  
  1536.         isOpen = TRUE;
  1537.  
  1538.         curStatus = atBegin;
  1539.         curdef *co = (curdef *)curobj;
  1540.         if (co->dbH != db)
  1541.         {
  1542.             // If the database for the cursor is changed, delete old context
  1543.             // and add the new one.
  1544.  
  1545.             if (co->dbH)  // If database object exists,
  1546.             {
  1547.                 deleteCursor((dbdef *) // delete cursor from list.
  1548.                              co->dbH->dbobj, this);
  1549.             } 
  1550.             addCursor((dbdef *) db->dbobj, this);
  1551.         }
  1552.         co->dbH = db;
  1553.         co->indexID = 0;
  1554.         co->saveEveryChange = TRUE;
  1555.  
  1556.         tabname = new char[strlen(curProps.szName)+1];
  1557.         strcpy(tabname, curProps.szName);
  1558.         strcpy(tabtype, curProps.szTableType);
  1559.  
  1560.         // Create generic record and store the table description
  1561.         // with every open cursor so that:
  1562.         //
  1563.         // 1. All records for a cursor share the same table description.
  1564.         //
  1565.         // 2. The Paradox Engine is not called for the type of a field
  1566.         //    with every Get and Put field operation performed on generic
  1567.         //    and custom records.
  1568.  
  1569.         genericRec = new BRecord(this);
  1570.         if (genericRec->lastError != DBIERR_NONE)
  1571.         {
  1572.             lastError = genericRec->lastError;
  1573.             delete genericRec;
  1574.             genericRec = 0;
  1575.         }
  1576.         else
  1577.         {
  1578.             co->fieldCnt = curProps.iFields;
  1579.             co->desc = (FieldDesc far *) _fmalloc(sizeof(FieldDesc) *
  1580.                                                   co->fieldCnt);
  1581.             if (!co->desc)
  1582.             {
  1583.                 lastError = DBIERR_NOMEMORY;
  1584.                 throw lastError;
  1585.             }
  1586.             else
  1587.             {
  1588.                 lastError = getDesc(tabH, co->fieldCnt, co->desc);
  1589.             }
  1590.         }
  1591.         if (lastError)
  1592.         {
  1593.             DbiCloseCursor(&tabH);
  1594.             delete tabname;
  1595.             isOpen = FALSE;
  1596.         }
  1597.     }
  1598.     catch(xalloc)
  1599.     {
  1600.         if (tabname)
  1601.         {
  1602.             delete tabname;
  1603.         }
  1604.         lastError = DBIERR_NOMEMORY;
  1605.         isOpen = FALSE;
  1606.         if (tabH)
  1607.         {
  1608.             DbiCloseCursor(&tabH);
  1609.         }
  1610.         return lastError;
  1611.     }
  1612.     catch(...)
  1613.     {
  1614.         if ((lastError == PXERR_CURSORALREADYOPEN) ||
  1615.             (lastError == PXERR_DBNOTOPEN))
  1616.         {
  1617.             return lastError;
  1618.         }
  1619.         if (tabH)
  1620.         {
  1621.             DbiCloseCursor(&tabH);
  1622.         }
  1623.         if ((tabname) && (isOpen))
  1624.         {
  1625.             delete tabname;
  1626.         }
  1627.         isOpen = FALSE;
  1628.         return lastError;
  1629.     }
  1630.  
  1631.     return lastError;
  1632. }
  1633.  
  1634. // Closes the cursor if it's open.
  1635.  
  1636. Retcode BCursor::close()
  1637. {
  1638.     int i;
  1639.  
  1640.     if (!isOpen)
  1641.     {
  1642.         return (lastError = PXERR_CURSORNOTOPEN);
  1643.     }
  1644.  
  1645.     curdef *co = (curdef *) curobj;
  1646.     for (i=0; i < co->handleCnt; i++)
  1647.     {
  1648.         if (co->recList[i])
  1649.         {
  1650.             co->recList[i]->detach();
  1651.         }
  1652.     }
  1653.  
  1654.     if ((lastError = DbiCloseCursor(&tabH)) != DBIERR_NONE)
  1655.     {
  1656.         return lastError;
  1657.     }
  1658.     isOpen = FALSE;
  1659.     curStatus = atEnd;
  1660.     tabH = 0;
  1661.     delete genericRec;
  1662.     genericRec = 0;
  1663.     if (co->fieldCnt != 0)
  1664.     {
  1665.         _ffree(co->desc);   // Delete previous descriptor.
  1666.         co->fieldCnt = 0;
  1667.     }
  1668.     delete tabname;
  1669.     tabname = 0;
  1670.  
  1671.     return lastError;
  1672. }
  1673.  
  1674.  
  1675. //  Append a record to the end of the table using regular and raw I/O.
  1676.  
  1677. Retcode BCursor::appendRec(BRecord *rec)
  1678. {
  1679.     int i;
  1680.  
  1681.     if (!isOpen)
  1682.     {
  1683.         return (lastError = PXERR_CURSORNOTOPEN);
  1684.     }
  1685.  
  1686.     if ((lastError = rec->preprocess()) != DBIERR_NONE)
  1687.     {
  1688.         return lastError;
  1689.     }
  1690.  
  1691.     // Transfer field values from custom fields if this is a custom record.
  1692.  
  1693.     if (strcmp(rec->nameOf(),"BRecord"))
  1694.     {
  1695.         // Transfer data to custom record's fields.
  1696.  
  1697.         char *buf;
  1698.         try
  1699.         {
  1700.             buf = new char[256];
  1701.         }
  1702.         catch(xalloc)
  1703.         {
  1704.             return (lastError = DBIERR_NOMEMORY);
  1705.         }
  1706.  
  1707.         PXFieldType    fldType1, fldType2;
  1708.  
  1709.         PXFieldSubtype fldSubtype;
  1710.         int            fldLen1, fldLen2;
  1711.         int            tblFld;
  1712.         BOOL           fNull;
  1713.  
  1714.         int cnt = rec->getFieldCount();
  1715.         for (i=1; i <= cnt; i++)
  1716.         {
  1717.             if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  1718.             {
  1719.                 if (rec->isNull(i))
  1720.                 {
  1721.                     lastError = rec->BRecord::setNull(tblFld);
  1722.                     continue;
  1723.                 }
  1724.  
  1725.                 // Get Paradox table generic record and custom descriptors.
  1726.  
  1727.                 rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  1728.                 rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  1729.  
  1730.                 if (fldType1 == fldBlob)
  1731.                 {
  1732.                     continue;                      // BLOB handling is separate.
  1733.                 }
  1734.                 // To transfer values from a custom record to Paradox, the
  1735.                 // record handle associated with the BRecord class is used
  1736.                 // rather than the genericRec of Cursor. This is done because
  1737.                 // any BLOBs that were constructed for the record are
  1738.                 // associated with BRecord's record handle.
  1739.  
  1740.                 if ((lastError = rec->getField(i,(void *) buf, 255, fNull))
  1741.                      == DBIERR_NONE)
  1742.                 {
  1743.                     if (fldType1 != fldType2)
  1744.                     {
  1745.                         lastError = convertFld((void *)buf,fldType1,fldLen1,
  1746.                                                (void *)buf,fldType2,fldLen2);
  1747.                     }
  1748.                     if (!lastError)
  1749.                     {
  1750.                         lastError = rec->BRecord::putField(tblFld, (void *)buf);
  1751.                     }
  1752.                 }
  1753.             }
  1754.             if (lastError)
  1755.             {
  1756.                 delete buf;
  1757.                 return lastError;
  1758.             }            
  1759.         }
  1760.         delete buf;
  1761.     }
  1762.  
  1763.     if ((lastError = DbiAppendRecord(tabH, rec->recH)) == DBIERR_NONE)
  1764.     {
  1765.         curStatus = atRecord;
  1766.     }
  1767.  
  1768.     curdef *co = (curdef *)curobj;
  1769.  
  1770.     for (i = 0; i < co->fieldCnt; i++)
  1771.     {
  1772.         if  (co->desc[i].fldType == fldBlob)
  1773.         {
  1774.             rec->closeBlob((i + 1), FALSE);
  1775.         }
  1776.     }
  1777.  
  1778.     return lastError;
  1779. }
  1780.  
  1781. Retcode BCursor::appendRec(const void far *buffer, int size)
  1782. {
  1783.     XLTMode     xltState;
  1784.     UINT16      iLen;
  1785.     DBIResult   tmpRslt = DBIERR_NONE;
  1786.  
  1787.     if (!isOpen)
  1788.     {
  1789.         return (lastError = PXERR_CURSORNOTOPEN);
  1790.     }
  1791.  
  1792.     // Save the current translation mode
  1793.     getProp(curXLTMODE, &xltState, sizeof(XLTMode), iLen);
  1794.     if (lastError)
  1795.     {
  1796.         return lastError;
  1797.     }
  1798.  
  1799.     if (xltState != xltNONE)
  1800.     {
  1801.         // Change the translation mode to xltNONE to do Raw I/O
  1802.         setProp(curXLTMODE, xltNONE);
  1803.         if (lastError)
  1804.         {
  1805.             return lastError;
  1806.         }
  1807.     }
  1808.  
  1809.     memcpy((pVOID)(genericRec->recH), buffer, size);
  1810.  
  1811.     if ((lastError = DbiAppendRecord(tabH, genericRec->recH)) == DBIERR_NONE)
  1812.     {
  1813.         curStatus = atRecord;
  1814.     }
  1815.  
  1816.     curdef *co = (curdef *)curobj;
  1817.  
  1818.     for (int i = 0; i < co->fieldCnt; i++)
  1819.     {
  1820.         if  (co->desc[i].fldType == fldBlob)
  1821.         {
  1822.             genericRec->closeBlob((i + 1), FALSE);
  1823.         }
  1824.     }
  1825.  
  1826.     // Reset the translate mode. Note that we need to store the error value.
  1827.  
  1828.     tmpRslt = lastError;
  1829.  
  1830.     setProp(curXLTMODE, xltState);
  1831.  
  1832.     lastError = tmpRslt;
  1833.  
  1834.     return lastError;
  1835. }
  1836.  
  1837. Retcode BCursor::insertRec()
  1838. {
  1839.   return insertRec(genericRec);
  1840. }
  1841.  
  1842. // Insert a record to the table using regular and raw I/O.
  1843.  
  1844. Retcode BCursor::insertRec(BRecord *rec)
  1845. {
  1846.  
  1847.     if (!isOpen)
  1848.     {
  1849.         return (lastError = PXERR_CURSORNOTOPEN);
  1850.     }
  1851.  
  1852.     if (curStatus == atBegin && getRecCount() > 0)
  1853.     {
  1854.         if ((lastError = DbiSetToBegin(tabH)) != DBIERR_NONE)
  1855.         {
  1856.             return lastError;
  1857.         }
  1858.     }
  1859.  
  1860.     if ((lastError = rec->preprocess()) != DBIERR_NONE)
  1861.     {
  1862.         return lastError;
  1863.     }
  1864.  
  1865.     // Transfer field values from custom fields if this is a custom record.
  1866.  
  1867.     if (strcmp(rec->nameOf(),"BRecord"))
  1868.     {
  1869.         // Transfer data to the custom record's fields.
  1870.  
  1871.         char *buf;
  1872.         try
  1873.         {
  1874.             buf = new char[256];
  1875.         }
  1876.         catch(xalloc)
  1877.         {
  1878.             return (lastError = DBIERR_NOMEMORY);
  1879.         }
  1880.  
  1881.         PXFieldType    fldType1, fldType2;
  1882.         PXFieldSubtype fldSubtype;
  1883.         int            fldLen1, fldLen2;
  1884.         int            tblFld;
  1885.         BOOL           fNull;
  1886.  
  1887.         int cnt = rec->getFieldCount();
  1888.         for (int i=1; i <= cnt; i++)
  1889.         {
  1890.             if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  1891.             {
  1892.                 if (rec->isNull(i))
  1893.                 {
  1894.                     lastError = rec->BRecord::setNull(tblFld);
  1895.                       continue;
  1896.                 }
  1897.                 // Get the Paradox table generic record and custom descriptors.
  1898.  
  1899.                 rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  1900.                 rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  1901.                 if (fldType1 == fldBlob)
  1902.                 {
  1903.                     continue;                  // BLOB handling is separate.
  1904.                 }
  1905.               
  1906.                 // To transfer values from a custom record to Paradox, we use
  1907.                 // the record handle associated with the BRecord class rather
  1908.                 // than the genericRec of Cursor. This is done because any BLOBs
  1909.                 // that were constructed for the record are associated with
  1910.                 // BRecord's record handle.
  1911.  
  1912.                 if ((lastError = rec->getField(i,(void *) buf,
  1913.                                                255, fNull))==DBIERR_NONE)
  1914.                 {
  1915.                     if (fldType1 != fldType2)
  1916.                     {
  1917.                         lastError = convertFld((void *)buf,fldType1,fldLen1,
  1918.                                                (void *)buf,fldType2,fldLen2);
  1919.                     }
  1920.                     if (!lastError)
  1921.                     {
  1922.                         lastError = rec->BRecord::putField(tblFld, (void *)buf);
  1923.                     }
  1924.                 }
  1925.                 if (lastError)
  1926.                 {
  1927.                     delete buf;
  1928.                     return lastError;
  1929.                 }
  1930.             }
  1931.         }
  1932.         delete buf;
  1933.     }
  1934.     if (curStatus == atEnd)
  1935.     {
  1936.         lastError = DbiAppendRecord(tabH, rec->recH);
  1937.     }
  1938.     else
  1939.     {
  1940.         lastError = DbiInsertRecord(tabH, dbiNOLOCK, rec->recH);
  1941.     }
  1942.  
  1943.     if (lastError == DBIERR_NONE)
  1944.     {
  1945.         curStatus = atRecord;
  1946.     }
  1947.  
  1948.     curdef *co = (curdef *)curobj;
  1949.  
  1950.     for (int i = 0; i < co->fieldCnt; i++)
  1951.     {
  1952.         if  (co->desc[i].fldType == fldBlob)
  1953.         {
  1954.             rec->closeBlob((i + 1), FALSE);
  1955.         }
  1956.     }
  1957.  
  1958.     return lastError;
  1959. }
  1960.  
  1961. Retcode BCursor::insertRec(const void far *buffer, int size)
  1962. {
  1963.     XLTMode     xltState;
  1964.     UINT16      iLen;
  1965.     DBIResult   tmpRslt;
  1966.  
  1967.     if (!isOpen)
  1968.     {
  1969.         return (lastError = PXERR_CURSORNOTOPEN);
  1970.     }
  1971.  
  1972.     if (curStatus == atBegin && getRecCount() > 0)
  1973.     {
  1974.         if ((lastError = DbiSetToBegin(tabH)) != DBIERR_NONE)
  1975.         {
  1976.             return lastError;
  1977.         }
  1978.     }
  1979.  
  1980.     // Save the current translation mode
  1981.     getProp(curXLTMODE, &xltState, sizeof(XLTMode), iLen);
  1982.     if (lastError)
  1983.     {
  1984.         return lastError;
  1985.     }
  1986.  
  1987.     if (xltState != xltNONE)
  1988.     {
  1989.         // Change the translation mode to xltNONE to do Raw I/O
  1990.         setProp(curXLTMODE, xltNONE);
  1991.         if (lastError)
  1992.         {
  1993.             return lastError;
  1994.         }
  1995.     }
  1996.  
  1997.     memcpy((pVOID)(genericRec->recH), buffer, size);
  1998.  
  1999.     if (curStatus == atEnd)
  2000.     {
  2001.         lastError = DbiAppendRecord(tabH, genericRec->recH);
  2002.     }
  2003.     else
  2004.     {
  2005.         lastError = DbiInsertRecord(tabH, dbiNOLOCK, genericRec->recH);
  2006.     }
  2007.  
  2008.     if (!lastError)
  2009.     {
  2010.         curStatus = atRecord;
  2011.     }
  2012.  
  2013.     curdef *co = (curdef *)curobj;
  2014.  
  2015.     for (int i = 0; i < co->fieldCnt; i++)
  2016.     {
  2017.         if (co->desc[i].fldType == fldBlob)
  2018.         {
  2019.             genericRec->closeBlob((i + 1), FALSE);
  2020.         }
  2021.     }
  2022.  
  2023.     tmpRslt = lastError;
  2024.  
  2025.     // Reset the translate mode to the origional state.
  2026.     setProp(curXLTMODE, xltState);
  2027.  
  2028.     lastError = tmpRslt;
  2029.  
  2030.     return lastError;
  2031. }
  2032.  
  2033. // Delete the current record of the cursor.
  2034.  
  2035. Retcode BCursor::deleteRec()
  2036. {
  2037.     PXCursorStatus cs;
  2038.  
  2039.     if (!isOpen)
  2040.     {
  2041.         return (lastError = PXERR_CURSORNOTOPEN);
  2042.     }
  2043.  
  2044.     if (curStatus != atRecord)
  2045.     {
  2046.         return (lastError = PXERR_INVCURRRECORD);
  2047.     }
  2048.  
  2049.     if (getRecCount() == getCurRecNum())           // Last record ?
  2050.     {
  2051.         cs = atEnd;
  2052.     }
  2053.     else
  2054.     {
  2055.         cs = atCrack;
  2056.     }
  2057.  
  2058.     if ((lastError = DbiDeleteRecord(tabH, NULL)) == DBIERR_NONE)
  2059.     {
  2060.         curStatus = cs;
  2061.     }
  2062.  
  2063.     return lastError;
  2064. }
  2065.  
  2066. Retcode BCursor::updateRec()
  2067. {
  2068.     return updateRec(genericRec);
  2069. }
  2070.  
  2071. // Update the current record of the cursor using regular and raw I/O.
  2072.  
  2073. Retcode BCursor::updateRec(BRecord *rec)
  2074. {                
  2075.     if (!isOpen)
  2076.     {
  2077.         return (lastError = PXERR_CURSORNOTOPEN);
  2078.     }
  2079.  
  2080.     if (curStatus != atRecord)
  2081.     {
  2082.         return (lastError = PXERR_INVCURRRECORD);
  2083.     }
  2084.  
  2085.     if ((lastError = rec->preprocess()) != DBIERR_NONE)
  2086.     {
  2087.         return lastError;
  2088.     }
  2089.  
  2090.     // Transfer field values from custom fields if this is a custom record.
  2091.  
  2092.     if (strcmp(rec->nameOf(),"BRecord"))
  2093.     {
  2094.         // Transfer data to the custom record's fields.
  2095.  
  2096.         char *buf;
  2097.         try
  2098.         {
  2099.             buf = new char[256];
  2100.         }
  2101.         catch(xalloc)
  2102.         {
  2103.             return (lastError = DBIERR_NOMEMORY);
  2104.         } 
  2105.  
  2106.         PXFieldType    fldType1, fldType2;
  2107.         PXFieldSubtype fldSubtype;
  2108.         int            fldLen1, fldLen2;
  2109.         int            tblFld;
  2110.         BOOL           fNull;
  2111.  
  2112.         int cnt = rec->getFieldCount();
  2113.         for (int i=1; i <= cnt; i++)
  2114.         if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  2115.         {
  2116.             if (rec->isNull(i))
  2117.             {
  2118.                 lastError = rec->BRecord::setNull(tblFld);
  2119.                 continue;
  2120.             }
  2121.  
  2122.             // Get the Paradox table generic record and custom descriptors.
  2123.  
  2124.             rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  2125.             rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  2126.             if (fldType1 == fldBlob)
  2127.             {
  2128.                 continue;                  // BLOB handling is separate.
  2129.             }
  2130.  
  2131.             // To transfer values from a custom record to Paradox, the
  2132.             // record handle associated with the BRecord class is used rather
  2133.             // than the genericRec of Cursor. This is done because any BLOBs
  2134.             // that were constructed for the record are associated with
  2135.             // BRecord's record handle.
  2136.  
  2137.             if ((lastError = rec->getField(i, (void *) buf, 255, fNull))
  2138.                  == DBIERR_NONE)
  2139.             {
  2140.                 if (fldType1 != fldType2)
  2141.                 {
  2142.                     lastError = convertFld((void *)buf,fldType1,fldLen1,
  2143.                                            (void *)buf,fldType2,fldLen2);
  2144.                 }
  2145.  
  2146.                 if (!lastError)
  2147.                 {
  2148.                     lastError = rec->BRecord::putField(tblFld, (void *)buf);
  2149.                 }
  2150.             }
  2151.             if (lastError)
  2152.             {
  2153.                 delete buf;
  2154.                 return (lastError);
  2155.             }
  2156.  
  2157.         }
  2158.         delete buf;
  2159.     }
  2160.  
  2161.     lastError = DbiModifyRecord(tabH, rec->recH, FALSE);
  2162.     if (lastError != DBIERR_NONE)
  2163.     {
  2164.         return lastError;
  2165.     }
  2166.  
  2167.     curdef *co = (curdef *)curobj;
  2168.  
  2169.     for (int i = 0; i < co->fieldCnt; i++)
  2170.     {
  2171.         if  (co->desc[i].fldType == fldBlob)
  2172.         {
  2173.             rec->closeBlob((i + 1), FALSE);
  2174.         }
  2175.     }
  2176.  
  2177.     return lastError;
  2178. }
  2179.  
  2180. Retcode BCursor::updateRec(const void far *buffer, int size)
  2181. {
  2182.     XLTMode     xltState;
  2183.     UINT16      iLen;
  2184.     DBIResult   tmpRslt;
  2185.  
  2186.     if (!isOpen)
  2187.     {
  2188.         return (lastError = PXERR_CURSORNOTOPEN);
  2189.     }
  2190.  
  2191.     if (curStatus != atRecord)
  2192.     {
  2193.         return (lastError = PXERR_INVCURRRECORD);
  2194.     }
  2195.  
  2196.     // Save the current translation mode
  2197.     getProp(curXLTMODE, &xltState, sizeof(XLTMode), iLen);
  2198.     if (lastError)
  2199.     {
  2200.         return lastError;
  2201.     }
  2202.  
  2203.     // Set the translate mode to xltNONE in order to use Raw I/O
  2204.     if (xltState != xltNONE)
  2205.     {
  2206.         setProp(curXLTMODE, xltNONE);
  2207.     }
  2208.     
  2209.     memcpy((pVOID)(genericRec->recH), buffer, size);
  2210.  
  2211.     lastError = DbiModifyRecord(tabH, genericRec->recH, FALSE);
  2212.     if (lastError != DBIERR_NONE)
  2213.     {
  2214.         return lastError;
  2215.     }
  2216.  
  2217.     curdef *co = (curdef *)curobj;
  2218.  
  2219.     for (int i = 0; i < co->fieldCnt; i++)
  2220.     {
  2221.         if  (co->desc[i].fldType == fldBlob)
  2222.         {
  2223.             genericRec->closeBlob((i + 1), FALSE);
  2224.         }
  2225.     }
  2226.  
  2227.     tmpRslt = lastError;
  2228.  
  2229.     // Reset the translate mode to the origional state.
  2230.     setProp(curXLTMODE, xltState);
  2231.  
  2232.     lastError = tmpRslt;
  2233.  
  2234.     return lastError;
  2235. }
  2236.  
  2237. // Position before the first record of the table. This function
  2238. // is provided, instead of gotoFirst, to maintain compatibility
  2239. // with future Borland database products.
  2240.  
  2241. Retcode BCursor::gotoBegin()
  2242. {
  2243.     if (!isOpen)
  2244.     {
  2245.         return (lastError = PXERR_CURSORNOTOPEN);
  2246.     }
  2247.  
  2248.     lastError = DbiSetToBegin(tabH);
  2249.     if (lastError == DBIERR_NONE)
  2250.     {
  2251.         curStatus = atBegin;
  2252.     }
  2253.  
  2254.     return lastError;
  2255. }
  2256.  
  2257. // Go to the end of the table.
  2258.  
  2259. Retcode BCursor::gotoEnd()
  2260. {
  2261.     if (!isOpen)
  2262.     {
  2263.         return (lastError = PXERR_CURSORNOTOPEN);
  2264.     }
  2265.  
  2266.     lastError = DbiSetToEnd(tabH);
  2267.     if (lastError == DBIERR_NONE)
  2268.     {
  2269.         curStatus = atEnd;
  2270.     }
  2271.  
  2272.     return lastError;
  2273. }
  2274.  
  2275. // Go to a specific record number in the table.
  2276.  
  2277. Retcode BCursor::gotoRec(RECORDNUMBER recNum)
  2278. {
  2279.     if (!isOpen)
  2280.     {
  2281.         return (lastError = PXERR_CURSORNOTOPEN);
  2282.     }
  2283.  
  2284.     if (!strcmp((((curdef *)curobj)->dbH)->Driver, szPARADOX))
  2285.     {
  2286.         if ((lastError = DbiSetToSeqNo(tabH, recNum)) == DBIERR_NONE)
  2287.         {
  2288.             curStatus = atRecord;
  2289.         }
  2290.     }
  2291.     else if (!strcmp((((curdef *)curobj)->dbH)->Driver, szDBASE))
  2292.     {
  2293.         if ((lastError = DbiSetToRecordNo(tabH, recNum)) == DBIERR_NONE)
  2294.         {
  2295.             curStatus = atRecord;
  2296.         }
  2297.     }
  2298.     else
  2299.     {
  2300.         lastError = DBIERR_NOTSUPPORTED;
  2301.         return lastError;
  2302.     }
  2303.  
  2304.     return lastError;
  2305. }
  2306.  
  2307. // Go to the next record of the table.
  2308.  
  2309. Retcode BCursor::gotoNext()
  2310. {
  2311.     if (!isOpen)
  2312.     {
  2313.         return (lastError = PXERR_CURSORNOTOPEN);
  2314.     }
  2315.  
  2316.     if (curStatus == atBegin)
  2317.     {
  2318.         if ((lastError = DbiGetNextRecord(tabH, dbiNOLOCK, NULL, NULL))
  2319.             == DBIERR_NONE)
  2320.         {
  2321.             curStatus = atRecord;
  2322.         }
  2323.  
  2324.         return lastError;
  2325.     }
  2326.  
  2327.     if (curStatus == atEnd)
  2328.     {
  2329.         return (lastError = DBIERR_EOF);
  2330.     }
  2331.  
  2332.     // Go to the next record.
  2333.     if ((lastError = DbiGetNextRecord(tabH, dbiNOLOCK, NULL, NULL))
  2334.         == DBIERR_NONE)                               
  2335.     {
  2336.         curStatus = atRecord;
  2337.     }
  2338.     else if (lastError == DBIERR_EOF)
  2339.     {
  2340.         DbiGetPriorRecord(tabH, dbiNOLOCK, NULL, NULL);
  2341.     }
  2342.  
  2343.     return lastError;
  2344. }
  2345.  
  2346. // Go to the previous record of the table.
  2347.  
  2348. Retcode BCursor::gotoPrev()
  2349. {
  2350.     if (!isOpen)
  2351.     {
  2352.         return (lastError = PXERR_CURSORNOTOPEN);
  2353.     }
  2354.  
  2355.     if (curStatus == atEnd)
  2356.     {
  2357.         if ((lastError = DbiGetPriorRecord(tabH, dbiNOLOCK, NULL, NULL))
  2358.             == DBIERR_NONE)
  2359.         {
  2360.             curStatus = atRecord;
  2361.         }
  2362.  
  2363.         return lastError;
  2364.     }
  2365.  
  2366.     if (curStatus == atBegin)
  2367.     {
  2368.         return (lastError = DBIERR_BOF);
  2369.     }
  2370.  
  2371.     if ((lastError = DbiGetPriorRecord(tabH, dbiNOLOCK, NULL, NULL))
  2372.         == DBIERR_NONE)
  2373.     {
  2374.         curStatus = atRecord;
  2375.     }
  2376.     else if (lastError == DBIERR_BOF)
  2377.     {
  2378.         DbiGetNextRecord(tabH, dbiNOLOCK, NULL, NULL);
  2379.     }
  2380.  
  2381.     return lastError;
  2382. }
  2383.  
  2384. // Get the record number of the current record. 
  2385.  
  2386. RECORDNUMBER BCursor::getCurRecNum()
  2387. {
  2388.     RECORDNUMBER recNum = 0;
  2389.     RECProps recProps;
  2390.  
  2391.     if (!isOpen)
  2392.     {
  2393.         lastError = PXERR_CURSORNOTOPEN;
  2394.         return 0;
  2395.     }
  2396.  
  2397.     if (curStatus != atRecord)
  2398.     {
  2399.         lastError = PXERR_INVCURRRECORD;
  2400.         return 0;
  2401.     }
  2402.  
  2403.     if (!strcmp((((curdef *)curobj)->dbH)->Driver, szPARADOX))
  2404.     {
  2405.         lastError = DbiGetSeqNo(tabH, (pUINT32)&recNum);
  2406.     }
  2407.     else if (!strcmp((((curdef *)curobj)->dbH)->Driver, szDBASE))
  2408.     {
  2409.         lastError = DbiGetRecord(tabH, dbiNOLOCK, NULL, &recProps);
  2410.         recNum = recProps.iPhyRecNum;
  2411.     }
  2412.     else
  2413.     {
  2414.         lastError = DBIERR_NOTSUPPORTED;
  2415.     }
  2416.  
  2417.     return recNum;
  2418. }
  2419.  
  2420. // Get the current record of the cursor. The three different
  2421. // signatures of the getRecord function are the following:
  2422. //
  2423. //   1. User-supplied record object.
  2424. //
  2425. //   2. Cursor's generic record object.
  2426. // 
  2427. //   3. Raw I/O.
  2428.  
  2429. Retcode BCursor::getRecord(BRecord *rec)
  2430. {
  2431.     int i;
  2432.     if (!isOpen)
  2433.     {
  2434.         return (lastError = PXERR_CURSORNOTOPEN);
  2435.     }
  2436.  
  2437.     if (curStatus != atRecord)
  2438.     {
  2439.         return (lastError = PXERR_INVCURRRECORD);
  2440.     }
  2441.  
  2442.     if (rec->clear())
  2443.     {
  2444.         return rec->lastError;
  2445.     }
  2446.  
  2447.     if ((lastError = DbiGetRecord(tabH, dbiNOLOCK, rec->recH, NULL))
  2448.         != DBIERR_NONE)
  2449.     {
  2450.         return lastError;
  2451.     }
  2452.  
  2453.     // Register the fact that the BLOBs in the record are now closed.
  2454.  
  2455.     recdef *ro = (recdef *) rec->recobj;
  2456.     for (i=0;i < ro->handleCnt; i++)
  2457.     {
  2458.         if (ro->recblb[i].blbRecH == rec->recH)
  2459.         {
  2460.             ro->recblb[i].state = blbClosed;
  2461.             lastError = DbiFreeBlob(tabH, rec->recH, 0);
  2462.             if (lastError != DBIERR_NONE)
  2463.             {
  2464.                 // If BLOB's previously closed, does not matter
  2465.                 if (lastError == DBIERR_BLOBNOTOPENED)
  2466.                 {
  2467.                     lastError = DBIERR_NONE;
  2468.                 }
  2469.             }
  2470.         }
  2471.     }
  2472.  
  2473.     if (!strcmp(rec->nameOf(), "BRecord"))     // Nothing else to do
  2474.     {
  2475.         lastError = rec->postprocess();
  2476.         curChange();
  2477.         return lastError;  // for generic records.
  2478.     }
  2479.  
  2480.     // Transfer data to the custom record's fields.
  2481.  
  2482.     char *buf;
  2483.     try
  2484.     {
  2485.         buf = new char[256];
  2486.     }
  2487.     catch(xalloc)
  2488.     {
  2489.         return (lastError = DBIERR_NOMEMORY);
  2490.     }
  2491.  
  2492.     PXFieldType    fldType1, fldType2;
  2493.     PXFieldSubtype fldSubtype;
  2494.     int            fldLen1, fldLen2;
  2495.     int            tblFld;
  2496.     BOOL           fNull;
  2497.  
  2498.     int cnt = rec->getFieldCount();
  2499.     for (i=1; i <= cnt; i++)
  2500.     {
  2501.         if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  2502.         {
  2503.             // Force getField to get data by calling the Paradox Engine.
  2504.  
  2505.             if (rec->BRecord::isNull(tblFld))
  2506.             {
  2507.                 rec->setNull(i);
  2508.                 continue;
  2509.             }
  2510.             rec->clearNull(i);
  2511.  
  2512.             // Get the Paradox table generic record and custom descriptors.
  2513.  
  2514.             rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  2515.             rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  2516.             if (fldType1 == fldBlob)
  2517.             {
  2518.                 continue;     // BLOB handling is separate.
  2519.             }
  2520.  
  2521.             if ((lastError = rec->BRecord::getField(tblFld, (void *) buf,
  2522.                 255, fNull)) == DBIERR_NONE)
  2523.             {
  2524.                 if (fldType1 != fldType2)
  2525.                 {
  2526.                     lastError = convertFld((void *)buf,fldType2,fldLen2,
  2527.                                            (void *)buf,fldType1,fldLen1);
  2528.                 }
  2529.                 if (!lastError)
  2530.                 {
  2531.                     lastError = rec->putField(i, (void *) buf);
  2532.                 }
  2533.             }
  2534.             if (lastError)
  2535.             {
  2536.                 delete buf;
  2537.                 return lastError;
  2538.             }
  2539.         }
  2540.     }
  2541.     delete buf;
  2542.  
  2543.     lastError = rec->postprocess();
  2544.  
  2545.     curChange();
  2546.  
  2547.     return lastError;
  2548. }
  2549.  
  2550. Retcode BCursor::getRecord()
  2551. {
  2552.   return getRecord(genericRec);
  2553. }
  2554.  
  2555. Retcode BCursor::getRecord(void far *buffer, int size)
  2556. {
  2557.     XLTMode     xltState;
  2558.     UINT16      iLen;
  2559.     DBIResult   tmpRslt;
  2560.  
  2561.     if (!isOpen)
  2562.     {
  2563.         return (lastError = PXERR_CURSORNOTOPEN);
  2564.     }
  2565.  
  2566.     if (curStatus != atRecord)
  2567.     {
  2568.         return (lastError = PXERR_INVCURRRECORD);
  2569.     }
  2570.  
  2571.     // Save the current translation mode
  2572.     getProp(curXLTMODE, &xltState, sizeof(XLTMode), iLen);
  2573.     if (lastError)
  2574.     {
  2575.         return lastError;
  2576.     }
  2577.  
  2578.     if (xltState != xltNONE)
  2579.     {
  2580.         // Change the translation mode to xltNONE to do Raw I/O
  2581.         setProp(curXLTMODE, xltNONE);
  2582.         if (lastError)
  2583.         {
  2584.             return lastError;
  2585.         }
  2586.     }
  2587.  
  2588.     if (genericRec->clear())
  2589.     {
  2590.         return genericRec->lastError;
  2591.     }
  2592.  
  2593.     if ((lastError = DbiGetRecord(tabH, dbiNOLOCK, genericRec->recH, NULL))
  2594.         != DBIERR_NONE)
  2595.     {
  2596.         return lastError;
  2597.     }
  2598.  
  2599.     memcpy(buffer, genericRec->recH, size);
  2600.  
  2601.     lastError = DbiFreeBlob(tabH, genericRec->recH, 0);
  2602.     if (lastError != DBIERR_NONE)
  2603.     {
  2604.         // If BLOB's previously closed, does not matter
  2605.         if (lastError == DBIERR_BLOBNOTOPENED)
  2606.         {
  2607.             lastError = DBIERR_NONE;
  2608.         }
  2609.     }
  2610.  
  2611.     curdef *co = (curdef *)curobj;
  2612.  
  2613.     for (int i = 0; i < co->fieldCnt; i++)
  2614.     {
  2615.         if  (co->desc[i].fldType == fldBlob)
  2616.         {
  2617.             ((recdef *)(genericRec->recobj))->recblb[i].state = blbClosed;
  2618.         }
  2619.     }
  2620.  
  2621.     tmpRslt = lastError;
  2622.  
  2623.     setProp(curXLTMODE, xltState);
  2624.  
  2625.     lastError = tmpRslt;
  2626.  
  2627.     curChange();
  2628.  
  2629.     return lastError;
  2630. }
  2631.  
  2632. // Get the Next record of the cursor. The two different
  2633. // signatures of the getRecord function are the following:
  2634. //
  2635. //   1. User-supplied record object.
  2636. //
  2637. //   2. Cursor's generic record object.
  2638.  
  2639. Retcode BCursor::getNextRecord(BRecord *rec)
  2640. {
  2641.     int i;
  2642.     if (!isOpen)
  2643.     {
  2644.         return (lastError = PXERR_CURSORNOTOPEN);
  2645.     }
  2646.  
  2647.     if (curStatus == atEnd)
  2648.     {
  2649.         return (lastError = PXERR_INVCURRRECORD);
  2650.     }
  2651.  
  2652.     if (rec->clear())
  2653.     {
  2654.         return rec->lastError;
  2655.     }
  2656.  
  2657.     if ((lastError = DbiGetNextRecord(tabH, dbiNOLOCK, rec->recH, NULL))
  2658.         != DBIERR_NONE)
  2659.     {
  2660.         if (lastError == DBIERR_EOF)
  2661.         {
  2662.             curStatus = atEnd;
  2663.         }
  2664.  
  2665.         return lastError;
  2666.     }
  2667.  
  2668.     curStatus = atRecord;
  2669.  
  2670.     // Register the fact that the BLOBs in the record are now closed.
  2671.  
  2672.     recdef *ro = (recdef *) rec->recobj;
  2673.     for (i=0;i < ro->handleCnt; i++)
  2674.     {
  2675.         if (ro->recblb[i].blbRecH == rec->recH)
  2676.         {
  2677.             ro->recblb[i].state = blbClosed;
  2678.             lastError = DbiFreeBlob(tabH, rec->recH, 0);
  2679.             if (lastError != DBIERR_NONE)
  2680.             {
  2681.                 // If BLOB's previously closed, does not matter
  2682.                 if (lastError == DBIERR_BLOBNOTOPENED)
  2683.                 {
  2684.                     lastError = DBIERR_NONE;
  2685.                 }
  2686.             }
  2687.         }
  2688.     }
  2689.  
  2690.     if (!strcmp(rec->nameOf(), "BRecord"))     // Nothing else to do
  2691.     {
  2692.         lastError = rec->postprocess();
  2693.  
  2694.         curChange();
  2695.  
  2696.         return lastError;  // for generic records.
  2697.     }
  2698.  
  2699.     // Transfer data to the custom record's fields.
  2700.  
  2701.     char *buf;
  2702.     try
  2703.     {
  2704.         buf = new char[256];
  2705.     }
  2706.     catch(xalloc)
  2707.     {
  2708.         return (lastError = DBIERR_NOMEMORY);
  2709.     }
  2710.  
  2711.     PXFieldType    fldType1, fldType2;
  2712.     PXFieldSubtype fldSubtype;
  2713.     int            fldLen1, fldLen2;
  2714.     int            tblFld;
  2715.     BOOL           fNull;
  2716.  
  2717.     int cnt = rec->getFieldCount();
  2718.     for (i=1; i <= cnt; i++)
  2719.     {
  2720.         if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  2721.         {
  2722.             // Force getField to get data by calling the Paradox Engine.
  2723.  
  2724.             if (rec->BRecord::isNull(tblFld))
  2725.             {
  2726.                 rec->setNull(i);
  2727.                 continue;
  2728.             }
  2729.             rec->clearNull(i);
  2730.  
  2731.             // Get the Paradox table generic record and custom descriptors.
  2732.  
  2733.             rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  2734.             rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  2735.             if (fldType1 == fldBlob)
  2736.             {
  2737.                 continue;     // BLOB handling is separate.
  2738.             }
  2739.  
  2740.             if ((lastError = rec->BRecord::getField(tblFld, (void *) buf,
  2741.                 255, fNull)) == DBIERR_NONE)
  2742.             {
  2743.                 if (fldType1 != fldType2)
  2744.                 {
  2745.                     lastError = convertFld((void *)buf,fldType2,fldLen2,
  2746.                                            (void *)buf,fldType1,fldLen1);
  2747.                 }
  2748.                 if (!lastError)
  2749.                 {
  2750.                     lastError = rec->putField(i, (void *) buf);
  2751.                 }
  2752.             }
  2753.             if (lastError)
  2754.             {
  2755.                 delete buf;
  2756.                 return lastError;
  2757.             }
  2758.         }
  2759.     }
  2760.     delete buf;
  2761.  
  2762.     lastError = rec->postprocess();
  2763.  
  2764.     if (lastError == DBIERR_NONE)
  2765.     {
  2766.         curChange();
  2767.     }
  2768.  
  2769.     return lastError;
  2770. }
  2771.  
  2772. Retcode BCursor::getNextRecord()
  2773. {
  2774.   return getNextRecord(genericRec);
  2775. }
  2776.  
  2777. // Get the Previous record of the cursor. The two different
  2778. // signatures of the getRecord function are the following:
  2779. //
  2780. //   1. User-supplied record object.
  2781. //
  2782. //   2. Cursor's generic record object.
  2783.  
  2784. Retcode BCursor::getPreviousRecord(BRecord *rec)
  2785. {
  2786.     int i;
  2787.     if (!isOpen)
  2788.     {
  2789.         return (lastError = PXERR_CURSORNOTOPEN);
  2790.     }
  2791.  
  2792.     if (curStatus == atBegin) // 3/23/95
  2793.     {
  2794.         return (lastError = PXERR_INVCURRRECORD);
  2795.     }
  2796.  
  2797.     if (rec->clear())
  2798.     {
  2799.         return rec->lastError;
  2800.     }
  2801.  
  2802.     if ((lastError = DbiGetPriorRecord(tabH, dbiNOLOCK, rec->recH, NULL))
  2803.         != DBIERR_NONE)
  2804.     {
  2805.         if (lastError == DBIERR_BOF)
  2806.         {
  2807.             curStatus = atEnd;
  2808.         }
  2809.         return lastError;
  2810.     }
  2811.  
  2812.     curStatus = atRecord;
  2813.  
  2814.     // Register the fact that the BLOBs in the record are now closed.
  2815.  
  2816.     recdef *ro = (recdef *) rec->recobj;
  2817.     for (i=0;i < ro->handleCnt; i++)
  2818.     {
  2819.         if (ro->recblb[i].blbRecH == rec->recH)
  2820.         {
  2821.             ro->recblb[i].state = blbClosed;
  2822.             lastError = DbiFreeBlob(tabH, rec->recH, 0);
  2823.             if (lastError != DBIERR_NONE)
  2824.             {
  2825.                 // If BLOB's previously closed, does not matter
  2826.                 if (lastError == DBIERR_BLOBNOTOPENED)
  2827.                 {
  2828.                     lastError = DBIERR_NONE;
  2829.                 }
  2830.             }
  2831.         }
  2832.     }
  2833.  
  2834.     if (!strcmp(rec->nameOf(), "BRecord"))     // Nothing else to do
  2835.     {
  2836.         lastError = rec->postprocess();
  2837.  
  2838.         if (lastError == DBIERR_NONE)
  2839.         {
  2840.             curChange();
  2841.         }
  2842.  
  2843.         return lastError;  // for generic records.
  2844.     }
  2845.  
  2846.     // Transfer data to the custom record's fields.
  2847.  
  2848.     char *buf;
  2849.     try
  2850.     {
  2851.         buf = new char[256];
  2852.     }
  2853.     catch(xalloc)
  2854.     {
  2855.         return (lastError = DBIERR_NOMEMORY);
  2856.     }
  2857.  
  2858.     PXFieldType    fldType1, fldType2;
  2859.     PXFieldSubtype fldSubtype;
  2860.     int            fldLen1, fldLen2;
  2861.     int            tblFld;
  2862.     BOOL           fNull;
  2863.  
  2864.     int cnt = rec->getFieldCount();
  2865.     for (i=1; i <= cnt; i++)
  2866.     {
  2867.         if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  2868.         {
  2869.             // Force getField to get data by calling the Paradox Engine.
  2870.  
  2871.             if (rec->BRecord::isNull(tblFld))
  2872.             {
  2873.                 rec->setNull(i);
  2874.                 continue;
  2875.             }
  2876.             rec->clearNull(i);
  2877.  
  2878.             // Get the Paradox table generic record and custom descriptors.
  2879.  
  2880.             rec->BRecord::getFieldDesc(tblFld,fldType2,fldSubtype,fldLen2);
  2881.             rec->getFieldDesc(i,fldType1,fldSubtype,fldLen1);
  2882.             if (fldType1 == fldBlob)
  2883.             {
  2884.                 continue;     // BLOB handling is separate.
  2885.             }
  2886.  
  2887.             if ((lastError = rec->BRecord::getField(tblFld, (void *) buf,
  2888.                 255, fNull)) == DBIERR_NONE)
  2889.             {
  2890.                 if (fldType1 != fldType2)
  2891.                 {
  2892.                     lastError = convertFld((void *)buf,fldType2,fldLen2,
  2893.                                            (void *)buf,fldType1,fldLen1);
  2894.                 }
  2895.                 if (!lastError)
  2896.                 {
  2897.                     lastError = rec->putField(i, (void *) buf);
  2898.                 }
  2899.             }
  2900.             if (lastError)
  2901.             {
  2902.                 delete buf;
  2903.                 return lastError;
  2904.             }
  2905.         }
  2906.     }
  2907.     delete buf;
  2908.  
  2909.     lastError = rec->postprocess();
  2910.  
  2911.     if (lastError == DBIERR_NONE)
  2912.     {
  2913.         curChange();
  2914.     }
  2915.  
  2916.     return lastError;
  2917. }
  2918.  
  2919. Retcode BCursor::getPreviousRecord()
  2920. {
  2921.   return getPreviousRecord(genericRec);
  2922. }
  2923.  
  2924. // Lock the table in a shared environment by calling PXNetTblLock.
  2925.  
  2926. Retcode BCursor::lockTable(PXLockMode lockMode)
  2927. {
  2928.     if (!isOpen)
  2929.     {
  2930.         return (lastError = PXERR_CURSORNOTOPEN);
  2931.     }
  2932.  
  2933.     switch (lockMode)
  2934.     {
  2935.         case pxFL:
  2936.         case pxWL:
  2937.             lastError = DbiAcqTableLock(tabH, dbiWRITELOCK);
  2938.             break;
  2939.         case pxPWL:
  2940.         case pxPFL:
  2941.             lastError = DbiAcqTableLock(tabH, dbiREADLOCK);
  2942.             break;
  2943.     }
  2944.  
  2945.     return lastError;
  2946. }
  2947.  
  2948. // Release a previously acquired lock on a table.
  2949.  
  2950. Retcode BCursor::unlockTable(PXLockMode lockMode)
  2951. {
  2952.     if (!isOpen)
  2953.     {
  2954.         return (lastError = PXERR_CURSORNOTOPEN);
  2955.     }
  2956.  
  2957.     switch (lockMode)
  2958.     {
  2959.         case pxFL:
  2960.         case pxWL:
  2961.             lastError = DbiRelTableLock(tabH, FALSE, dbiWRITELOCK);
  2962.             break;
  2963.         case pxPWL:
  2964.         case pxPFL:
  2965.             lastError = DbiRelTableLock(tabH, FALSE, dbiREADLOCK);
  2966.             break;
  2967.     }
  2968.  
  2969.     return lastError;
  2970. }
  2971.  
  2972. // Get a lock for the current record of the cursor.
  2973.  
  2974. LOCKHANDLE BCursor::lockRecord()
  2975. {
  2976.     LOCKHANDLE lckH = 0;
  2977.     if (!isOpen)
  2978.     {
  2979.         lastError = PXERR_CURSORNOTOPEN;
  2980.         return 0;
  2981.     }
  2982.  
  2983.     if (curStatus != atRecord)
  2984.     {
  2985.         lastError = PXERR_INVCURRRECORD;
  2986.         return 0;
  2987.     }
  2988.  
  2989.     if ((lastError = DbiGetRecord(tabH, dbiWRITELOCK, NULL, NULL))
  2990.         != DBIERR_NONE)
  2991.     {
  2992.         return 0;
  2993.     }
  2994.     else
  2995.     {
  2996.         lckH = getCurRecNum();
  2997.         // Expect error if table type is not Paradox or dBASE
  2998.         if (lastError == DBIERR_NOTSUPPORTED)
  2999.         {
  3000.             lastError = DBIERR_NONE;
  3001.         }
  3002.         return lckH;
  3003.     }
  3004. }
  3005.  
  3006. // Release the previously acquired lock on a record.
  3007.  
  3008. Retcode BCursor::unlockRecord(LOCKHANDLE lckH)
  3009. {
  3010.     if (!isOpen)
  3011.     {
  3012.         return (lastError = PXERR_CURSORNOTOPEN);
  3013.     }
  3014.  
  3015.     gotoRec(lckH);
  3016.      
  3017.     return (lastError = DbiRelRecordLock(tabH, FALSE));
  3018. }
  3019.  
  3020. Retcode BCursor::unlockRecord()
  3021. {
  3022.     if (!isOpen)
  3023.     {
  3024.         return (lastError = PXERR_CURSORNOTOPEN);
  3025.     }
  3026.  
  3027.     return (lastError = DbiRelRecordLock(tabH, FALSE));
  3028. }
  3029.  
  3030. // Determine whether the current record of the cursor is 
  3031. // locked by another user.
  3032.  
  3033. BOOL BCursor::isLocked()
  3034. {   
  3035.     BOOL locked = 0;
  3036.      
  3037.     if (!isOpen)
  3038.     {
  3039.         lastError = PXERR_CURSORNOTOPEN;
  3040.         return FALSE;
  3041.     }
  3042.  
  3043.     if (curStatus != atRecord)
  3044.     {
  3045.         lastError = PXERR_INVCURRRECORD;
  3046.         return FALSE;
  3047.     }
  3048.  
  3049.     lastError = DbiIsRecordLocked(tabH, &locked);
  3050.     return (locked);
  3051. }
  3052.  
  3053. // Determine if the cursor table has been changed by any other user.
  3054. // Not yet implemented....
  3055.  
  3056. BOOL BCursor::hasChanged()
  3057. {
  3058.     // Note that this currenly doesn't do anything....
  3059.     //   Can add a call to refresh(), which would force the
  3060.     //   buffers to be refreshed, but this would be a performance hit....
  3061.     return FALSE;
  3062. }
  3063.  
  3064. // Refresh the cursor's buffer to reflect changes.
  3065.  
  3066. Retcode BCursor::refresh()
  3067. {
  3068.  
  3069.     if (!isOpen)
  3070.     {
  3071.         return (lastError = PXERR_CURSORNOTOPEN);
  3072.     }
  3073.  
  3074.     lastError = DbiForceReread(tabH);
  3075.  
  3076.     return lastError;
  3077. }
  3078.  
  3079. // Find the number of records in the cursor (or table).
  3080.  
  3081. RECORDNUMBER BCursor::getRecCount()
  3082. {
  3083.     RECORDNUMBER nRecs = 0;
  3084.     if (!isOpen)
  3085.     {
  3086.         lastError = PXERR_CURSORNOTOPEN;
  3087.         return 0;
  3088.     }
  3089.     lastError = DbiGetRecordCount(tabH, (pUINT32)&nRecs);
  3090.  
  3091.     return nRecs;
  3092. }
  3093.  
  3094. //  Clones the cursor with its associated properties.
  3095.  
  3096. BCursor * BCursor::clone(BOOL stayCurrent)
  3097. {
  3098.     if (!isOpen)
  3099.     {
  3100.         lastError = PXERR_CURSORNOTOPEN;
  3101.         return 0;
  3102.     }
  3103.  
  3104.     curdef *co = (curdef *)curobj;
  3105.  
  3106.     BCursor *newcur;
  3107.     try
  3108.     {
  3109.         newcur = new BCursor(co->dbH, tabname,
  3110.                              co->indexID, co->saveEveryChange);
  3111.     }
  3112.     catch(xalloc)
  3113.     {
  3114.         lastError = DBIERR_NOMEMORY;
  3115.         return newcur;
  3116.     }
  3117.  
  3118.     if ((lastError = newcur->lastError) != DBIERR_NONE)
  3119.     {
  3120.         delete newcur;
  3121.         return 0;
  3122.     }
  3123.  
  3124.     if (curStatus == atBegin || ! stayCurrent)
  3125.     {
  3126.         newcur->curStatus = atBegin;
  3127.     }
  3128.     else
  3129.     {
  3130.         if (curStatus == atEnd)
  3131.         {
  3132.             newcur->curStatus = atEnd;
  3133.         }
  3134.         else
  3135.         {
  3136.             newcur->curStatus = curStatus;
  3137.         }
  3138.  
  3139.     }
  3140.  
  3141.     lastError = DbiCloseCursor(&(newcur->tabH));
  3142.     if (lastError != DBIERR_NONE)
  3143.     {
  3144.         delete newcur;
  3145.         return 0;
  3146.     }                                         
  3147.  
  3148.     lastError = DbiCloneCursor(tabH, FALSE, FALSE, &(newcur->tabH));
  3149.     if (lastError != DBIERR_NONE)
  3150.     {
  3151.         delete newcur;
  3152.         return 0;
  3153.     }
  3154.  
  3155.     return newcur;
  3156. }
  3157.  
  3158. /***********************************************************************
  3159.   The following four functions are used instead of the Paradox Engine's
  3160.   search functions and reflect the direction of new Borland database
  3161.   products.
  3162. *********************************************************************/
  3163.  
  3164. //  Position the cursor on the same record as the current record
  3165. //  of another cursor.
  3166.  
  3167. Retcode BCursor::setToCursor(BCursor *otherCursor)
  3168. {
  3169.     if (!otherCursor->isOpen || !isOpen)
  3170.     {
  3171.         return (lastError = PXERR_CURSORNOTOPEN);
  3172.     }
  3173.  
  3174.     if (strcmp(tabname, otherCursor->tabname))
  3175.     {
  3176.         return (lastError = PXERR_TABLESDIFFER);
  3177.     }
  3178.  
  3179.     lastError = DbiSetToCursor(tabH, otherCursor->tabH);
  3180.     if (lastError != DBIERR_NONE)
  3181.     {
  3182.         return lastError;
  3183.     }
  3184.  
  3185.     curStatus = otherCursor->curStatus;
  3186.  
  3187.     return (lastError);
  3188. }
  3189.  
  3190.  
  3191. // Search the table for the record that matches key values in keyRec; use
  3192. // the currently open index.
  3193.  
  3194. Retcode BCursor::searchIndex(const BRecord *keyRec,
  3195.                              PXSearchMode mode, int fldCnt)
  3196. {
  3197.     BRecord *rec = (BRecord *) keyRec;
  3198.     curdef  *co = (curdef *)curobj;
  3199.     int     lastFld = 0;
  3200.  
  3201.     if (!isOpen)
  3202.     {
  3203.         return (lastError = PXERR_CURSORNOTOPEN);
  3204.     }
  3205.  
  3206.     if (strcmp(rec->nameOf(),"BRecord"))
  3207.     {
  3208.         // Transfer data from the custom record's fields to record buffer.
  3209.  
  3210.         char *buf;
  3211.         try
  3212.         {
  3213.             buf = new char[256];
  3214.         }
  3215.         catch(xalloc)
  3216.         {
  3217.             lastError = DBIERR_NOMEMORY;
  3218.             return lastError;
  3219.         }
  3220.  
  3221.         BOOL fNull;
  3222.  
  3223.         int tblFld, i = 1;
  3224.  
  3225.         if (co->indexID == 0)
  3226.         {
  3227.             lastFld = (((curdef *)curobj)->dbH)->getNumPFields(tabname);
  3228.         }
  3229.         else
  3230.         {
  3231.             if (co->indexID <= 255)
  3232.             {
  3233.                 i = lastFld = co->indexID;
  3234.             }
  3235.         }
  3236.  
  3237.         if (!lastFld)
  3238.         {
  3239.             lastFld = rec->getFieldCount();
  3240.         }
  3241.  
  3242.         for (; i <= lastFld; i++)
  3243.         {
  3244.             if ((tblFld = rec->getTblFieldNumber(i)) > 0)
  3245.             {
  3246.                 // Force getField to get data by calling the Paradox Engine.
  3247.  
  3248.                 if (rec->isNull(i))
  3249.                 {
  3250.                     lastError = genericRec->setNull(tblFld);
  3251.                 }
  3252.                 else
  3253.                 {
  3254.                     if ((lastError = rec->getField(i, (void *) buf,
  3255.                                                    255, fNull)) == DBIERR_NONE)
  3256.                     {
  3257.                         lastError = genericRec->putField(tblFld, (void *) buf);
  3258.                     }
  3259.                 }
  3260.             }
  3261.         }
  3262.         delete buf;
  3263.         rec = genericRec;
  3264.     }
  3265.  
  3266.     if (mode == pxSearchNext)
  3267.     {
  3268.         gotoNext();
  3269.         if (lastError == PXSUCCESS)
  3270.         {
  3271.             int CompResult = 0;
  3272.  
  3273.             // If we still have the same key value, then use it.
  3274.             Retcode retVal = DbiCompareKeys(tabH, rec->recH, NULL,
  3275.                                             fldCnt, 0, &CompResult);
  3276.             if (CompResult == 0 && retVal == PXSUCCESS)
  3277.             {
  3278.                 lastError = PXSUCCESS;
  3279.                 curStatus = atRecord;
  3280.                 return lastError;
  3281.             }
  3282.             else
  3283.             {
  3284.                 // Restore to the previous record
  3285.                 gotoPrev();
  3286.                 lastError = DBIERR_RECNOTFOUND;
  3287.                 return lastError;
  3288.             }
  3289.         }
  3290.         lastError = DBIERR_RECNOTFOUND;
  3291.         return lastError;
  3292.     }
  3293.     else
  3294.     {
  3295.         if (curStatus == atEnd)
  3296.         {
  3297.             if ((lastError = DbiSetToEnd(tabH)) != DBIERR_NONE)
  3298.             {
  3299.                 return lastError;
  3300.             }
  3301.         }
  3302.     }
  3303.  
  3304.     if (co->indexID == 0)          // Primary key or no key.
  3305.     {
  3306.         if (fldCnt != lastFld)
  3307.         {
  3308.             lastError = DbiSetToKey(tabH, (DBISearchCond)mode, FALSE, fldCnt, 0,
  3309.                                     rec->recH);
  3310.         }
  3311.         else
  3312.         {
  3313.             // Search on entire key
  3314.             lastError = DbiSetToKey(tabH, (DBISearchCond)mode, FALSE, 0, 0,
  3315.                                     rec->recH);
  3316.         }
  3317.     }
  3318.     else
  3319.     {
  3320.         if (co->indexID < 256)
  3321.         {
  3322.             lastError = DbiSetToKey(tabH, (DBISearchCond)mode, FALSE, 1, 0,
  3323.                                     rec->recH);
  3324.         }
  3325.         else
  3326.         {
  3327.             lastError = DbiSetToKey(tabH, (DBISearchCond)mode, FALSE, fldCnt, 0,
  3328.                                     rec->recH);
  3329.         }
  3330.     }
  3331.  
  3332.     if (!lastError || (mode==pxClosestRecord && lastError==DBIERR_RECNOTFOUND))
  3333.     {
  3334.         DbiGetNextRecord(tabH, dbiNOLOCK, NULL, NULL);
  3335.         curStatus = atRecord;
  3336.     }
  3337.  
  3338.     return lastError;
  3339. }
  3340.  
  3341. // Search the table for a record that matches key values specified in the
  3342. // variable count argument list. Otherwise, its operation is the same
  3343. // as other search methods.
  3344.  
  3345. Retcode BCursor::searchIndex(PXSearchMode mode, int fldCnt, ...)
  3346. {
  3347.     int startFld, ind, fld;
  3348.     BDate dt;
  3349.     BTime tm;
  3350.     BTimeStamp ts;
  3351.     TIME Time;
  3352.     DATE Date;
  3353.     TIMESTAMP TimeStamp;
  3354.     va_list ap;
  3355.     va_start(ap, fldCnt);
  3356.  
  3357.     curdef *co = (curdef *)curobj;
  3358.     engdef *eo = (engdef *) ((((dbdef *)co->dbH->dbobj)->engH)->engobj);
  3359.  
  3360.     lastError = DBIERR_NONE;
  3361.     if (!isOpen)
  3362.     {
  3363.         return (lastError = PXERR_CURSORNOTOPEN);
  3364.     }
  3365.  
  3366.     if (fldCnt < 1)
  3367.     {
  3368.         return (lastError = PXERR_INVKEYCOUNT);
  3369.     }
  3370.  
  3371.     if (co->indexID == 0)
  3372.     {
  3373.         startFld = 1;
  3374.     }
  3375.     else
  3376.     {
  3377.         if (co->indexID <= 255)
  3378.         {
  3379.             startFld = co->indexID;           // Single field secondary index.
  3380.             if (fldCnt > 1)
  3381.             {
  3382.                 return (lastError = PXERR_INVKEYCOUNT);
  3383.             }
  3384.         }
  3385.         else
  3386.         {
  3387.             for (ind = 0; ind < eo->compIdxCnt; ind++)
  3388.             {
  3389.                 if (eo->keymap[ind].indexId == co->indexID &&
  3390.                     ! strcmp(eo->keymap[ind].tableName,tabname))
  3391.                 {
  3392.                     break;
  3393.                 }
  3394.             }
  3395.         }
  3396.  
  3397.         if (! eo->compIdxCnt || ind == eo->compIdxCnt)
  3398.         {
  3399.             return (lastError = PXERR_NOKEYMAP);
  3400.         }
  3401.  
  3402.         if (fldCnt < 1 || fldCnt > eo->keymap[ind].keyCnt)
  3403.         {
  3404.             return (lastError = PXERR_INVKEYCOUNT);
  3405.         }
  3406.     }
  3407.  
  3408.     for (int i=0; i < fldCnt; i++)
  3409.     {
  3410.         if (co->indexID <= 255)
  3411.         {
  3412.             fld = startFld;
  3413.         }
  3414.         else
  3415.         {
  3416.             fld = eo->keymap[ind].fieldArray[i];
  3417.         }
  3418.         switch (co->desc[fld-1].fldType)
  3419.         {
  3420.             case fldChar:
  3421.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3422.                                         (pBYTE) (CHAR *)va_arg(ap, CHAR *));
  3423.                 break;
  3424.             case fldBool:
  3425.             {
  3426.                 BOOL temp = (BOOL)va_arg(ap, BOOL);
  3427.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3428.                                         (pBYTE) &temp);
  3429.                 break;
  3430.             }
  3431.             case fldShort:
  3432.             {
  3433.                 INT16 temp = (INT16)va_arg(ap, INT16);
  3434.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3435.                                         (pBYTE) &temp);
  3436.                 break;
  3437.             }
  3438.             case fldUInt16:
  3439.             {
  3440.                 UINT16 temp = (UINT16)va_arg(ap, UINT16);
  3441.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3442.                                         (pBYTE) &temp);
  3443.                 break;
  3444.             }
  3445.             case fldLong:
  3446.             {
  3447.                 INT32 temp = (INT32)va_arg(ap, INT32);
  3448.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3449.                                         (pBYTE) &temp);
  3450.                 break;
  3451.             }
  3452.             case fldUInt32:
  3453.             {
  3454.                 UINT32 temp = (UINT32)va_arg(ap, UINT32);
  3455.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3456.                                         (pBYTE) &temp);
  3457.                 break;
  3458.             }
  3459.             case fldDouble:
  3460.             {
  3461.                 FLOAT temp = (FLOAT)va_arg(ap, FLOAT);
  3462.                 lastError = DbiPutField(tabH, fld, genericRec->recH,
  3463.                                         (pBYTE) &temp);
  3464.                 break;
  3465.             }
  3466.             case fldDate:
  3467.                 #ifdef _MSC_VER                      // Microsoft C++.
  3468.                     dt =  va_arg(ap, BDate);
  3469.                 #else
  3470.                     dt =  (BDate) va_arg(ap, BDate);
  3471.                 #endif
  3472.  
  3473.                 if ((lastError = DbiDateEncode((UINT16)dt.month, (UINT16)dt.day,
  3474.                                                  dt.year, &Date)) == DBIERR_NONE)
  3475.                 {
  3476.                     lastError = DbiPutField(tabH, fld, genericRec->recH,
  3477.                                             (pBYTE) &Date);
  3478.                 }
  3479.                 break;
  3480.             case fldTime:
  3481.                 #ifdef _MSC_VER                      // Microsoft C++.
  3482.                     tm =  va_arg(ap, BTime);
  3483.                 #else
  3484.                     tm =  (BTime) va_arg(ap, BTime);
  3485.                 #endif
  3486.  
  3487.                 if ((lastError = DbiTimeEncode(tm.hour, tm.minute,
  3488.                                                tm.milSec, &Time)) == DBIERR_NONE)
  3489.                 {
  3490.                     lastError = DbiPutField(tabH, fld, genericRec->recH,
  3491.                                             (pBYTE) &Time);
  3492.                 }
  3493.                 break;
  3494.           case fldTimeStamp:
  3495.                 #ifdef _MSC_VER                      // Microsoft C++.
  3496.                     ts =  va_arg(ap, BTimeStamp);
  3497.                 #else
  3498.                     ts =  (BTimeStamp)va_arg(ap, BTimeStamp);
  3499.                 #endif
  3500.  
  3501.  
  3502.                 if ((lastError = DbiDateEncode((UINT16)ts.BDay.month,
  3503.                                                (UINT16)ts.BDay.day,
  3504.                                                ts.BDay.year, &Date))
  3505.                     == DBIERR_NONE)
  3506.                 {
  3507.                     if ((lastError = DbiTimeEncode(ts.BHour.hour,
  3508.                                                    ts.BHour.minute,
  3509.                                                    ts.BHour.milSec, &Time))
  3510.                         == DBIERR_NONE)
  3511.                     {
  3512.                         if ((lastError = DbiTimeStampEncode(Date, Time,
  3513.                                                             &TimeStamp))
  3514.                             == DBIERR_NONE)
  3515.                         {
  3516.                             lastError = DbiPutField(tabH, fld, genericRec->recH,
  3517.                                                     (pBYTE) &TimeStamp);
  3518.                         }
  3519.                     }
  3520.                 }
  3521.                 break;
  3522.         }
  3523.         startFld += 1;
  3524.     }
  3525.  
  3526.     va_end(ap);
  3527.  
  3528.     if (lastError)
  3529.     {
  3530.         return lastError;
  3531.     }
  3532.  
  3533.     return (searchIndex(genericRec, mode, fldCnt));
  3534. }
  3535.  
  3536. Retcode BCursor::switchToIndex(const char *indexName, const char *tagName)
  3537. {
  3538.     IDXDesc         idxDesc;
  3539.     unsigned int    indexSeqNo;
  3540.     
  3541.     if (!isOpen)
  3542.     {
  3543.         return (lastError = PXERR_CURSORNOTOPEN);
  3544.     }
  3545.  
  3546.     lastError = DbiSwitchToIndex(&tabH, (pCHAR)indexName, (pCHAR)tagName,
  3547.                                  0, TRUE);
  3548.     if (lastError != DBIERR_NONE)
  3549.     {
  3550.         return lastError;
  3551.     }
  3552.  
  3553.     lastError = DbiGetIndexSeqNo(tabH, (pCHAR)indexName, (pCHAR)tagName, 0,
  3554.                                  &indexSeqNo);
  3555.     if (lastError != DBIERR_NONE)
  3556.     {
  3557.         return lastError;
  3558.     }
  3559.  
  3560.     lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  3561.     if (lastError != DBIERR_NONE)
  3562.     {
  3563.         return lastError;
  3564.     }
  3565.  
  3566.     curdef *co = (curdef *)curobj;
  3567.  
  3568.     co->indexID = idxDesc.iIndexId;
  3569.     strcpy(co->indexName, idxDesc.szName);
  3570.     strcpy(co->indexTag, idxDesc.szTagName);
  3571.  
  3572.     return lastError;
  3573. }
  3574.  
  3575. Retcode BCursor::switchToIndex(int indexID)
  3576. {
  3577.     IDXDesc         idxDesc;
  3578.     unsigned int    indexSeqNo;
  3579.  
  3580.     if (!isOpen)
  3581.     {
  3582.         return (lastError = PXERR_CURSORNOTOPEN);
  3583.     }
  3584.  
  3585.     lastError = DbiSwitchToIndex(&tabH, NULL, NULL, indexID, TRUE);
  3586.     if (lastError != DBIERR_NONE)
  3587.     {
  3588.         return lastError;
  3589.     }
  3590.  
  3591.     lastError = DbiGetIndexSeqNo(tabH, NULL, NULL, indexID,
  3592.                                  &indexSeqNo);
  3593.     if (lastError != DBIERR_NONE)
  3594.     {
  3595.         return lastError;
  3596.     }
  3597.  
  3598.     lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  3599.     if (lastError != DBIERR_NONE)
  3600.     {
  3601.         return lastError;
  3602.     }
  3603.  
  3604.     curdef *co = (curdef *)curobj;
  3605.  
  3606.     co->indexID = indexID;
  3607.     strcpy(co->indexName, idxDesc.szName);
  3608.     strcpy(co->indexTag, idxDesc.szTagName);
  3609.  
  3610.     return lastError;
  3611. }
  3612.  
  3613. Retcode BCursor::setRange(BRecord &highRecord, BRecord &lowRecord,
  3614.                           BOOL includeHigh, BOOL includeLow)
  3615. {
  3616.     if (!isOpen)
  3617.     {
  3618.         return (lastError = PXERR_CURSORNOTOPEN);
  3619.     }
  3620.  
  3621.     if (highRecord.recH == NULL)
  3622.     {
  3623.         return (lastError = PXERR_RECNOTATT);
  3624.     }
  3625.  
  3626.     if (lowRecord.recH == NULL)
  3627.     {
  3628.         return (lastError = PXERR_RECNOTATT);
  3629.     }
  3630.     
  3631.     lastError = DbiSetRange(tabH, FALSE, 0, 0, lowRecord.recH, includeLow, 0, 0,
  3632.                             highRecord.recH, includeHigh);
  3633.  
  3634.     return lastError;
  3635. }
  3636.  
  3637. Retcode BCursor::resetRange()
  3638. {
  3639.     if (!isOpen)
  3640.     {
  3641.         return (lastError = PXERR_CURSORNOTOPEN);
  3642.     }
  3643.  
  3644.     lastError = DbiResetRange(tabH);
  3645.  
  3646.     return lastError;
  3647. }
  3648.  
  3649. Retcode BCursor::addFilter(pCANExpr canExpr, hDBIFilter &filterHandle)
  3650. {
  3651.     if (!isOpen)
  3652.     {
  3653.         return (lastError = PXERR_CURSORNOTOPEN);
  3654.     }
  3655.  
  3656.     if (canExpr == NULL)
  3657.     {
  3658.         return (lastError = DBIERR_INVALIDFILTER);
  3659.     }
  3660.     
  3661.     lastError = DbiAddFilter(tabH, 0L, 0, FALSE, (pCANExpr)canExpr,
  3662.                              NULL, &filterHandle);
  3663.  
  3664.     return lastError;
  3665. }
  3666.  
  3667. Retcode BCursor::activateFilter(hDBIFilter filterHandle)
  3668. {
  3669.     if (!isOpen)
  3670.     {
  3671.         return (lastError = PXERR_CURSORNOTOPEN);
  3672.     }
  3673.  
  3674.     lastError = DbiActivateFilter(tabH, filterHandle);
  3675.  
  3676.     return lastError;
  3677. }
  3678.  
  3679. Retcode BCursor::deactivateFilter(hDBIFilter filterHandle)
  3680. {
  3681.     if (!isOpen)
  3682.     {
  3683.         return (lastError = PXERR_CURSORNOTOPEN);
  3684.     }
  3685.  
  3686.     lastError = DbiDeactivateFilter(tabH, filterHandle);
  3687.  
  3688.     return lastError;
  3689. }
  3690.  
  3691. Retcode BCursor::dropFilter(hDBIFilter filterHandle)
  3692. {
  3693.     if (!isOpen)
  3694.     {
  3695.         return (lastError = PXERR_CURSORNOTOPEN);
  3696.     }
  3697.  
  3698.     lastError = DbiDropFilter(tabH, filterHandle);
  3699.  
  3700.     return lastError;
  3701. }
  3702.  
  3703. Retcode BCursor::linkToCursor(BCursor &masterCursor, pUINT16 masterFields,
  3704.                                pUINT16 detailFields)
  3705. {
  3706.     if (!isOpen)
  3707.     {
  3708.         return (lastError = PXERR_CURSORNOTOPEN);
  3709.     }
  3710.  
  3711.     if (!masterCursor.isOpen)
  3712.     {
  3713.         return (lastError = PXERR_CURSORNOTOPEN);
  3714.     }
  3715.  
  3716.     if (masterTabH != NULL)
  3717.     {
  3718.         return (lastError = DBIERR_FIELDMULTILINKED);
  3719.     }
  3720.  
  3721.     if (masterFields == NULL)
  3722.     {
  3723.         return (lastError = DBIERR_INVALIDPARAM);
  3724.     }
  3725.  
  3726.     if (detailFields == NULL)
  3727.     {
  3728.         return (lastError = DBIERR_INVALIDPARAM);
  3729.     }
  3730.  
  3731.     masterTabH = &(masterCursor.tabH);
  3732.     
  3733.     lastError = DbiBeginLinkMode(masterTabH);
  3734.     if (lastError != DBIERR_NONE)
  3735.     {
  3736.         return lastError;
  3737.     }
  3738.  
  3739.     lastError = DbiBeginLinkMode(&tabH);
  3740.     if (lastError != DBIERR_NONE)
  3741.     {
  3742.         return lastError;
  3743.     }
  3744.  
  3745.     // Link the two tables, specifying which fields
  3746.     // will be linked in the last two parameters.
  3747.     // Specifically, link the first field of Customers
  3748.     // to the indexed second field of Orders
  3749.     lastError = DbiLinkDetail(*masterTabH, tabH, 1, masterFields,
  3750.                               detailFields);
  3751.     if (lastError != DBIERR_NONE)
  3752.     {
  3753.         return lastError;
  3754.     }
  3755.  
  3756.     return lastError;
  3757. }
  3758.  
  3759. Retcode BCursor::unlinkFromCursor()
  3760. {
  3761.     if (!isOpen)
  3762.     {
  3763.         return (lastError = PXERR_CURSORNOTOPEN);
  3764.     }
  3765.  
  3766.     if (masterTabH == NULL)
  3767.     {
  3768.         return (lastError = PXERR_CURSORNOTOPEN);
  3769.     }
  3770.  
  3771.     lastError = DbiUnlinkDetail(tabH);
  3772.     if (lastError != DBIERR_NONE)
  3773.     {
  3774.         return lastError;
  3775.     }
  3776.  
  3777.     // Tell the master table to go out of link mode
  3778.     lastError = DbiEndLinkMode(masterTabH);
  3779.     if (lastError != DBIERR_NONE)
  3780.     {
  3781.         return lastError;
  3782.     }
  3783.  
  3784.     // Tell the detail table to go out of link mode
  3785.     lastError = DbiEndLinkMode(&tabH);
  3786.     if (lastError != DBIERR_NONE)
  3787.     {
  3788.         return lastError;
  3789.     }
  3790.  
  3791.     masterTabH = NULL;
  3792.  
  3793.     return lastError;
  3794. }
  3795.  
  3796. Retcode BCursor::setProp(UINT32 prop, UINT32 value)
  3797. {
  3798.     if (!isOpen)
  3799.     {
  3800.         lastError = PXERR_CURSORNOTOPEN;
  3801.         return lastError;
  3802.     }
  3803.  
  3804.     lastError = DbiSetProp((hDBIObj)tabH, prop, value);
  3805.  
  3806.     return lastError;
  3807. }
  3808.  
  3809. Retcode BCursor::getProp(UINT32 prop, pVOID value, UINT16 maxLen,
  3810.                          UINT16 &retLen)
  3811. {
  3812.     if (!isOpen)
  3813.     {
  3814.         lastError = PXERR_CURSORNOTOPEN;
  3815.         return lastError;
  3816.     }
  3817.  
  3818.     lastError = DbiGetProp((hDBIObj)tabH, prop, value, maxLen, &retLen);
  3819.  
  3820.     return lastError;
  3821. }
  3822.  
  3823. Retcode BCursor::getProperties(CURProps &curProps)
  3824. {
  3825.     if (!isOpen)
  3826.     {
  3827.         lastError = PXERR_CURSORNOTOPEN;
  3828.         return lastError;
  3829.     }
  3830.  
  3831.     lastError = DbiGetCursorProps(tabH, &curProps);
  3832.  
  3833.     return lastError;
  3834. }
  3835.  
  3836.  
  3837. Retcode BCursor::getBookMark(BOOKMARK& bookMark)
  3838. {
  3839.     CURProps    curProps;
  3840.     
  3841.     if (!isOpen)
  3842.     {
  3843.         lastError = PXERR_CURSORNOTOPEN;
  3844.         return lastError;
  3845.     }
  3846.  
  3847.     lastError = DbiGetCursorProps(tabH, &curProps);
  3848.     if (lastError != DBIERR_NONE)
  3849.     {
  3850.         return lastError;
  3851.     }
  3852.  
  3853.     try
  3854.     {
  3855.         bookMark = new BYTE[curProps.iBookMarkSize];
  3856.     }
  3857.     catch (xalloc)
  3858.     {
  3859.         bookMark = NULL;
  3860.         lastError = DBIERR_NOMEMORY;
  3861.         return lastError;
  3862.     }
  3863.     
  3864.     lastError = DbiGetBookMark(tabH, bookMark);
  3865.  
  3866.     return lastError;
  3867. }
  3868.  
  3869. Retcode BCursor::setToBookMark(BOOKMARK bookMark)
  3870. {
  3871.     if (!isOpen)
  3872.     {
  3873.         lastError = PXERR_CURSORNOTOPEN;
  3874.         return lastError;
  3875.     }
  3876.  
  3877.     if (bookMark == NULL)
  3878.     {
  3879.         lastError = DBIERR_INVALIDBOOKMARK;
  3880.         return lastError;
  3881.     }
  3882.  
  3883.     lastError = DbiSetToBookMark(tabH, bookMark);
  3884.  
  3885.     if (lastError == DBIERR_NONE)
  3886.     {
  3887.         curStatus = atRecord;
  3888.     }
  3889.  
  3890.     return lastError;
  3891. }
  3892.  
  3893. Retcode BCursor::freeBookMark(BOOKMARK bookMark)
  3894. {
  3895.     if (!isOpen)
  3896.     {
  3897.         lastError = PXERR_CURSORNOTOPEN;
  3898.         return lastError;
  3899.     }
  3900.  
  3901.     if (bookMark == NULL)
  3902.     {
  3903.         lastError = DBIERR_INVALIDBOOKMARK;
  3904.         return lastError;
  3905.     }
  3906.  
  3907.     delete bookMark;
  3908.  
  3909.     return lastError;
  3910. }
  3911.  
  3912. Retcode BCursor::compareBookMarks(BOOKMARK bookMark1, BOOKMARK bookMark2,
  3913.                                   CMPBkMkRslt &rslt)
  3914. {
  3915.     if (!isOpen)
  3916.     {
  3917.         lastError = PXERR_CURSORNOTOPEN;
  3918.         return lastError;
  3919.     }
  3920.  
  3921.     if (bookMark1 == NULL)
  3922.     {
  3923.         lastError = DBIERR_INVALIDBOOKMARK;
  3924.         return lastError;
  3925.     }
  3926.  
  3927.     if (bookMark1 == NULL)
  3928.     {
  3929.         lastError = DBIERR_INVALIDBOOKMARK;
  3930.         return lastError;
  3931.     }
  3932.  
  3933.     lastError = DbiCompareBookMarks(tabH, bookMark1, bookMark2, &rslt);
  3934.  
  3935.     return lastError;
  3936. }
  3937.  
  3938. // Redefine pure virtuals from the BDbObject class.
  3939.  
  3940. char * BCursor::nameOf() const
  3941. {
  3942.     return ("BCursor");
  3943. }
  3944.  
  3945. void BCursor::printOn( ostream& os)
  3946. {
  3947.     os << nameOf() << "{ Table Name = " << tabname
  3948.        << ", Open Status = " << (int) isOpen << "}\n";
  3949. }
  3950.  
  3951. // Needs code to refresh any associated BRecord objects....
  3952.  
  3953. Retcode BCursor::setFieldMap(UINT16 numberOfFields, FLDDesc *fieldDesc)
  3954. {
  3955.     curdef          *co = (curdef *)curobj;
  3956.  
  3957.     if (!isOpen)
  3958.     {
  3959.         return (lastError = PXERR_CURSORNOTOPEN);
  3960.     }
  3961.  
  3962.     lastError = DbiSetFieldMap(tabH, numberOfFields, fieldDesc);
  3963.     if (lastError != DBIERR_NONE)
  3964.     {
  3965.         return lastError;
  3966.     }
  3967.  
  3968.     lastError = getDesc(tabH, co->fieldCnt, co->desc);
  3969.  
  3970.     return lastError;
  3971. }
  3972.  
  3973. // Needs code to refresh any associated BRecord objects....
  3974.  
  3975. Retcode BCursor::dropFieldMap()
  3976. {
  3977.     curdef          *co = (curdef *)curobj;
  3978.  
  3979.     if (!isOpen)
  3980.     {
  3981.         return (lastError = PXERR_CURSORNOTOPEN);
  3982.     }
  3983.  
  3984.     lastError = DbiSetFieldMap(tabH, 0, 0);
  3985.     if (lastError != DBIERR_NONE)
  3986.     {
  3987.         return lastError;
  3988.     }
  3989.  
  3990.     lastError = getDesc(tabH, co->fieldCnt, co->desc);
  3991.  
  3992.     return lastError;
  3993. }
  3994.  
  3995. // Only supported for dBASE tables
  3996.  
  3997. Retcode BCursor::undeleteRecord()
  3998. {
  3999.     if (!isOpen)
  4000.     {
  4001.         return (lastError = PXERR_CURSORNOTOPEN);
  4002.     }
  4003.  
  4004.     lastError = DbiUndeleteRecord(tabH);
  4005.  
  4006.     return lastError;
  4007. }
  4008.  
  4009. // Only supported for dBASE tables
  4010.  
  4011. Retcode BCursor::packTable(BOOL regenIndexes)
  4012. {
  4013.     curdef      *co = (curdef *)curobj;
  4014.  
  4015.     if (!isOpen)
  4016.     {
  4017.         return (lastError = PXERR_CURSORNOTOPEN);
  4018.     }
  4019.  
  4020.     lastError = DbiPackTable((co->dbH)->hDb, tabH, NULL, NULL, regenIndexes);
  4021.  
  4022.     return lastError;
  4023. }
  4024.  
  4025. TABLEHANDLE BCursor::getHandle()
  4026. {
  4027.     if (!isOpen)
  4028.     {
  4029.         lastError = PXERR_CURSORNOTOPEN;
  4030.         return 0;
  4031.     }
  4032.  
  4033.     lastError = DBIERR_NONE;
  4034.     return tabH;
  4035. }
  4036.  
  4037. Retcode BCursor::openTable(BDatabase *db,
  4038.                            const char *tableName,
  4039.                            const char *tblType,
  4040.                            int indexID,
  4041.                            DBIOpenMode openMode,
  4042.                            DBIShareMode shareMode,
  4043.                            XLTMode xltMode)
  4044. {
  4045.     curdef      *co = (curdef *)curobj;
  4046.     INT16       numFields = 0;
  4047.     FieldDesc   *fldDescs = NULL;
  4048.     CHAR        indexName[DBIMAXNAMELEN + 1];
  4049.     UINT16      indexSeqNo;
  4050.     IDXDesc     idxDesc;
  4051.  
  4052.     try
  4053.     {
  4054.         if (!strcmp(tblType, szPARADOX))
  4055.         {
  4056.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  4057.                                      NULL, NULL, indexID, openMode,
  4058.                                      shareMode, xltMode, FALSE, NULL, &tabH);
  4059.         }
  4060.         else if (!strcmp(tblType, szDBASE))
  4061.         {
  4062.             // If primary index
  4063.             if (indexID == 0)
  4064.             {
  4065.                 // Attempt to open on simulated primary index
  4066.                 lastError = DbiOpenTable(db->hDb, (pCHAR)tableName, (pCHAR)tblType,
  4067.                                          (pCHAR)tableName, "Primary", 0,
  4068.                                          openMode, shareMode, xltMode,
  4069.                                          FALSE, NULL, &tabH);
  4070.                 if (lastError == DBIERR_NOSUCHINDEX)
  4071.                 {
  4072.                     // On failure, open in natural order
  4073.                     lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4074.                                              (pCHAR)tblType, NULL, NULL, 0,
  4075.                                              openMode, shareMode, xltMode,
  4076.                                              FALSE, NULL, &tabH);
  4077.                     co->indexID = 0;
  4078.                     strcpy(co->indexName, "");
  4079.                     strcpy(co->indexTag, "");
  4080.                 }
  4081.                 else
  4082.                 {
  4083.                     co->indexID = 0;
  4084.                     strcpy(co->indexName, (pCHAR)tableName);
  4085.                     strcpy(co->indexTag, "Primary");
  4086.                 }
  4087.             }
  4088.             // attempt to open secondary index
  4089.             else
  4090.             {
  4091.                 lastError = db->getDescVector((pCHAR)tableName, numFields,
  4092.                                                fldDescs);
  4093.                 if (lastError != DBIERR_NONE)
  4094.                 {
  4095.                     throw lastError;
  4096.                 }
  4097.  
  4098.                 if (indexID > numFields)
  4099.                 {
  4100.                     lastError = DBIERR_NOSUCHINDEX;
  4101.                     throw lastError;
  4102.                 }
  4103.  
  4104.                 strncpy(indexName, tableName, 3);
  4105.                 indexName[3] = 0;
  4106.                 strncat(indexName, fldDescs[indexID-1].fldName, 8);
  4107.                 indexName[8] = 0;
  4108.                 strcat(indexName, ".NDX");
  4109.                 // Check if the index exist as an .NDX index
  4110.                 // This is our simulated non-maintained index
  4111.                 if (!access(indexName, 00))
  4112.                 {
  4113.                     lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4114.                                              (pCHAR)tblType,
  4115.                                              indexName, NULL, 0, openMode,
  4116.                                              shareMode, xltMode, FALSE,
  4117.                                              NULL, &tabH);
  4118.                     if (lastError == DBIERR_NONE)
  4119.                     {
  4120.                         co->indexID = indexID;
  4121.                         strcpy(co->indexName, (pCHAR)indexName);
  4122.                         strcpy(co->indexTag, "");
  4123.                     }
  4124.                 }
  4125.                 // This is our simulated maintained index
  4126.                 else
  4127.                 {
  4128.                     lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4129.                                              (pCHAR)tblType, (pCHAR)tableName,
  4130.                                              fldDescs[indexID-1].fldName, 0,
  4131.                                              openMode, shareMode,
  4132.                                              xltMode, FALSE, NULL, &tabH);
  4133.                     if (lastError == DBIERR_NONE)
  4134.                     {
  4135.                         co->indexID = indexID;
  4136.                         strcpy(co->indexName, fldDescs[indexID-1].fldName);
  4137.                         strcpy(co->indexTag, "");
  4138.                     }
  4139.                 }
  4140.                 delete fldDescs;
  4141.                 fldDescs = 0;
  4142.             }
  4143.         }
  4144.         else if (!strcmp(tblType, szASCII))
  4145.         {
  4146.             // On failure, open in natural order
  4147.             lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4148.                                      (pCHAR)tblType, NULL, NULL, 0,
  4149.                                      openMode, shareMode,
  4150.                                      xltMode, FALSE, NULL, &tabH);
  4151.             if (lastError == DBIERR_NONE)
  4152.             {
  4153.                 co->indexID = 0;
  4154.                 strcpy(co->indexName, "");
  4155.                 strcpy(co->indexTag, "");
  4156.             }
  4157.         }
  4158.         else // if SQL Table
  4159.         {
  4160.             // If primary index
  4161.             if (indexID == 0)
  4162.             {
  4163.                 strcpy(indexName, tableName);
  4164.                 strncat(indexName, "_", DBIMAXNAMELEN);
  4165.                 indexName[DBIMAXNAMELEN] = 0;
  4166.                 strncat(indexName, "Primary", DBIMAXNAMELEN);
  4167.                 indexName[DBIMAXNAMELEN] = 0;
  4168.  
  4169.                 // Attempt to open on simulated primary index
  4170.                 lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4171.                                          (pCHAR)tblType, (pCHAR)indexName, NULL,
  4172.                                          0, openMode, shareMode,
  4173.                                          xltMode, FALSE, NULL, &tabH);
  4174.                 if ((lastError == DBIERR_NOSUCHINDEX) ||
  4175.                     (lastError == DBIERR_NOTINDEXED))
  4176.                 {
  4177.                     // On failure, open in natural order
  4178.                     lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4179.                                              (pCHAR)tblType, NULL, NULL, 0,
  4180.                                              openMode, shareMode,
  4181.                                              xltMode, FALSE, NULL, &tabH);
  4182.                     if (lastError == DBIERR_NONE)
  4183.                     {
  4184.                         co->indexID = 0;
  4185.                         strcpy(co->indexName, "");
  4186.                         strcpy(co->indexTag, "");
  4187.                     }
  4188.                 }
  4189.                 else if (lastError == DBIERR_NONE)
  4190.                 {
  4191.                     co->indexID = indexID;
  4192.                     strcpy(co->indexName, indexName);
  4193.                     strcpy(co->indexTag, "");
  4194.                 }
  4195.                 else
  4196.                 {
  4197.                     co->indexID = 0;
  4198.                     strcpy(co->indexName, "");
  4199.                     strcpy(co->indexTag, "");
  4200.                 }
  4201.             }
  4202.             else
  4203.             {
  4204.                 lastError = db->getDescVector((pCHAR)tableName, numFields,
  4205.                                                fldDescs);
  4206.                 if (lastError != DBIERR_NONE)
  4207.                 {
  4208.                     throw lastError;
  4209.                 }
  4210.  
  4211.                 if (indexID > numFields)
  4212.                 {
  4213.                     lastError = DBIERR_NOSUCHINDEX;
  4214.                     throw lastError;
  4215.                 }
  4216.  
  4217.                 strcpy(indexName, tableName);
  4218.                 strncat(indexName, "_", DBIMAXNAMELEN);
  4219.                 indexName[DBIMAXNAMELEN] = 0;
  4220.                 strncat(indexName, fldDescs[indexID-1].fldName, DBIMAXNAMELEN);
  4221.                 indexName[DBIMAXNAMELEN] = 0;
  4222.  
  4223.                 lastError = DbiOpenTable(db->hDb, (pCHAR)tableName,
  4224.                                          (pCHAR)tblType, (pCHAR)indexName,
  4225.                                          NULL, 0, openMode, shareMode,
  4226.                                          xltMode, FALSE, NULL, &tabH);
  4227.                 if (lastError == DBIERR_NONE)
  4228.                 {
  4229.                     co->indexID = indexID;
  4230.                     strcpy(co->indexName, indexName);
  4231.                     strcpy(co->indexTag, "");
  4232.                 }
  4233.             }
  4234.         }
  4235.  
  4236.         if (lastError != DBIERR_NONE)
  4237.         {
  4238.             throw lastError;
  4239.         }
  4240.  
  4241.         isOpen = TRUE;
  4242.  
  4243.         if (!strcmp(tblType, szPARADOX))
  4244.         {
  4245.             lastError = DbiGetIndexSeqNo(tabH, NULL, NULL, indexID,
  4246.                                          &indexSeqNo);
  4247.             if (lastError == DBIERR_NONE)
  4248.             {
  4249.                 lastError = DbiGetIndexDesc(tabH, indexSeqNo, &idxDesc);
  4250.                 if (lastError == DBIERR_NONE)
  4251.                 {
  4252.                     co->indexID = idxDesc.iIndexId;
  4253.                     if (co->indexID != 0)
  4254.                     {
  4255.                         strcpy(co->indexName, idxDesc.szName);
  4256.                     }
  4257.                     else
  4258.                     {
  4259.                         strcpy(co->indexName, idxDesc.szName);
  4260.                     }
  4261.  
  4262.                     strcpy(co->indexTag, "");
  4263.                 }
  4264.             }
  4265.             else
  4266.             {
  4267.                 co->indexID = 0;
  4268.                 strcpy(co->indexName, "");
  4269.                 strcpy(co->indexTag, "");
  4270.                 if ( (indexID == 0) && (lastError == DBIERR_NOSUCHINDEX))
  4271.                 {
  4272.                     lastError = DBIERR_NONE;
  4273.                 }
  4274.             }
  4275.  
  4276.         }
  4277.     }
  4278.     catch(...)
  4279.     {
  4280.         if (fldDescs)
  4281.         {
  4282.             delete fldDescs;
  4283.         }
  4284.     }
  4285.  
  4286.     return lastError;
  4287. }
  4288.  
  4289. // Return the status of the cursor - if on a atBegin, atRecord,
  4290. // atCrack, or atEnd.
  4291.  
  4292. PXCursorStatus
  4293. BCursor::getCurStatus()
  4294. {
  4295.     return curStatus;
  4296. }
  4297.  
  4298. //
  4299. //    Used to clear any open blobs. This function should be called
  4300. //    if any blobs have been written to a record, but appendRec(),
  4301. //    insertRec() or updateRec() was never called successfully.
  4302. //
  4303. //    For example, if there is a locking conflict, and a decision
  4304. //    is made not to post a record having had blobs written to its
  4305. //    record buffer, clearRec() should be called to free those blob
  4306. //    resources. clearRec() may be called even after the blobs have
  4307. //    already been closed by appendRec(), insertRec() or updateRec().
  4308. //
  4309. //    In summary, whenever a blob is written to a BRecord, it MUST
  4310. //    be followed by a successfull call to one of the following BCursor
  4311. //    functions, or    BLOB resources will not be freed:
  4312. //        appendRec()
  4313. //        clearRec()
  4314. //        insertRec()
  4315. //        updateRec()
  4316. //
  4317. Retcode
  4318. BCursor::clearRec (BRecord* rec)
  4319. {
  4320.     curdef *co = (curdef *)curobj;
  4321.  
  4322.     for (int i = 0; i < co->fieldCnt; i++)
  4323.     {
  4324.         if  (co->desc[i].fldType == fldBlob)
  4325.         {
  4326.             lastError = rec->closeBlob((i + 1), FALSE);
  4327.             switch (lastError)
  4328.             {
  4329.                 case DBIERR_NONE:
  4330.                     break;
  4331.                 case DBIERR_BLOBNOTOPENED: //appendRec(), insertRec() or
  4332.                                            // updateRec() must have already
  4333.                                            // been called, or this BLOB
  4334.                                            // was never opened
  4335.                     lastError = DBIERR_NONE;
  4336.                     break;
  4337.                 default :
  4338.                     return lastError;
  4339.             }
  4340.         }
  4341.     }
  4342.  
  4343.     if (rec->clear())
  4344.     {
  4345.         return rec->lastError;
  4346.     }
  4347.  
  4348.     lastError = DBIERR_NONE;
  4349.     return lastError;
  4350. }
  4351.  
  4352. Retcode
  4353. BCursor::clearRec ()
  4354. {
  4355.     curdef *co = (curdef *)curobj;
  4356.  
  4357.     for (int i = 0; i < co->fieldCnt; i++)
  4358.     {
  4359.         if  (co->desc[i].fldType == fldBlob)
  4360.         {
  4361.             lastError = genericRec->closeBlob((i + 1), FALSE);
  4362.             switch (lastError)
  4363.             {
  4364.                 case DBIERR_NONE:
  4365.                     break;
  4366.                 case DBIERR_BLOBNOTOPENED: //appendRec(), insertRec() or
  4367.                                            // updateRec() must have already
  4368.                                            // been called, or this BLOB
  4369.                                            // was never opened
  4370.                     lastError = DBIERR_NONE;
  4371.                     break;
  4372.                 default :
  4373.                     return lastError;
  4374.             }
  4375.         }
  4376.     }
  4377.  
  4378.     if (genericRec->clear())
  4379.     {
  4380.         return genericRec->lastError;
  4381.     }
  4382.  
  4383.     lastError = DBIERR_NONE;
  4384.     return lastError;
  4385. }
  4386.  
  4387. Retcode
  4388. BCursor::curChange()
  4389. {
  4390.     return DBIERR_NONE;
  4391. }
  4392.  
  4393. // The following two routines are used to maintain a list of cursors for
  4394. // a database. The Database Framework layer does not assume the presence
  4395. // of any Class library (not even Borland's container Classlib).
  4396. // Consequently, no List class is used.
  4397.  
  4398. Retcode addCursor(dbdef *db, BCursor *cur)
  4399. {
  4400.     // Add this Cursor object to the Cursor vector in the Database.
  4401.     int i;
  4402.     BCursor **newvec;
  4403.     for (i = 0; i < db->handleCnt; i++)
  4404.     {
  4405.         if (! db->curList[i])     // empty slot ?
  4406.         {
  4407.             db->curList[i] = cur;
  4408.             return DBIERR_NONE;
  4409.         }
  4410.     }
  4411.     try
  4412.     {
  4413.         // 4 more handles
  4414.         newvec = new BCursor *[db->handleCnt+4];
  4415.     }
  4416.     catch(xalloc)
  4417.     {
  4418.         return DBIERR_NOMEMORY;
  4419.     }
  4420.  
  4421.     for (i = 0; i < db->handleCnt; i++)
  4422.     {
  4423.         newvec[i] = db->curList[i];
  4424.     }
  4425.  
  4426.     newvec[i++] = cur;
  4427.     newvec[i] = newvec[i+1] = newvec[i+2] = 0;
  4428.  
  4429.     if (db->handleCnt)
  4430.     {
  4431.         delete [] db->curList;     // Delete old vector.
  4432.     }
  4433.     db->handleCnt += 4;
  4434.     db->curList = newvec;
  4435.  
  4436.     return DBIERR_NONE;
  4437. }
  4438.  
  4439. // Delete the cursor object from the known cursor list in its database.
  4440.  
  4441. void deleteCursor(dbdef *db, BCursor *cur)
  4442. {
  4443.     for (int i = 0; i < db->handleCnt; i++)
  4444.     {
  4445.         if (db->curList[i] == cur)
  4446.         {
  4447.             db->curList[i] = 0;
  4448.             return;
  4449.         }
  4450.     }
  4451. }
  4452.  
  4453. // Compute the total size of first numFields of the descriptor.
  4454. // This function is not used and has not been updated for IDAPI
  4455.  
  4456. int getPdxRecSize(FieldDesc far *desc, int numFields)
  4457. {
  4458.     int size = 0;
  4459.     for (int i = 0; i < numFields; i++)
  4460.     {
  4461.         if  (desc[i].fldType == fldBlob)
  4462.         {
  4463.             size += desc[i].fldLen + 10;   // BLOB field in Paradox is
  4464.                                            // 10 + header.
  4465.         }
  4466.         else if  (desc[i].fldType == fldShort)
  4467.         {
  4468.             size += 2;
  4469.         }
  4470.         else if  (desc[i].fldType == fldDate)
  4471.         {
  4472.             size += 4;
  4473.         }
  4474.         else if  (desc[i].fldType == fldDouble)
  4475.         {
  4476.             size += 8;
  4477.         }
  4478.         else
  4479.         {
  4480.             size += desc[i].fldLen;
  4481.         }
  4482.     }
  4483.  
  4484.     return size;
  4485. }
  4486.  
  4487.  
  4488.