home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / DBPROC.ZIP / DBMANIP.C < prev    next >
C/C++ Source or Header  |  1992-05-24  |  21KB  |  995 lines

  1. #define INCL_BASE
  2. #define INCL_DOSFILEMGR
  3. #define INCL_DOSDATETIME
  4. #include <os2.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <math.h>
  9. #include "dbmanip.h"
  10. #include "dberr.h"
  11.  
  12.  
  13. SHORT EXPENTRY DbCreate(CHAR *file, SHORT fldcount, FLDDATA *info)
  14. {
  15. DBHEADER header ;
  16. FLDHEADER fldhdr ;
  17. SHORT x, rc ;
  18. CHAR filename[256], EOHeader[2] = {0xD, 0x1A}, day, month, year ;
  19. HFILE hndl ;
  20. USHORT action, fsOpenMode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE ;
  21.  
  22. //check passed information
  23. if(file[0] == 0 || file == NULL)
  24.     return DB_FILE_NAME_ERR ;
  25.  
  26. strcpy(filename, file) ;
  27. if(strstr(strupr(filename), ".DBF") == NULL)
  28.     strcat(filename, ".DBF") ;
  29.  
  30. if(fldcount > MAXFIELDS)
  31.     return DB_MAX_FIELDS ;
  32.  
  33. for(x = 0 ; x < fldcount ; x++)
  34.     {
  35.     if(strlen(info[x].name) > 10 || strlen(info[x].name) < 1)
  36.         return DB_BAD_FLDNAME ;
  37.     switch(info[x].type)
  38.         {
  39.         case 'C':
  40.         case 'c':
  41.             if(info[x].length > MAXFLDLNGTH || info[x].length < 1)
  42.                 return DB_FLD_LNGTH ;
  43.             info[x].decimal = 0 ;
  44.             break ;
  45.         case 'D':
  46.         case 'd':
  47.             info[x].length = 8 ;
  48.             info[x].decimal = 0 ;
  49.             break ;
  50.         case 'L':
  51.         case 'l':
  52.             info[x].length = 1 ;
  53.             info[x].decimal = 0 ;
  54.             break ;
  55.         case 'N':
  56.         case 'n':
  57.             if(info[x].length > MAXNUMLNGTH || info[x].length < 1)
  58.                 return DB_FLD_LNGTH ;
  59.             if(info[x].decimal < 0 || info[x].decimal > MAXDECLNGTH || info[x].decimal > info[x].length - 2)
  60.                 return DB_DEC_LNGTH ;
  61.             break ;
  62.         case 'M':
  63.         case 'm':
  64.             info[x].length = 8 ;
  65.             info[x].decimal = 0 ;
  66.             break ;
  67.         default:
  68.             return DB_INVALID_FIELD ;
  69.         }
  70.     }
  71.  
  72. GetDate(&day, &month, &year) ;
  73. memset(header.reserved, 0, 20) ;
  74.  
  75. header.reclngth = 1 ;    //1 larger than requested to hold deleted marker
  76. for(x = 0 ; x < fldcount ; x++)
  77.     header.reclngth += info[x].length ;
  78.  
  79. if(header.reclngth > MAXRECLNGTH)
  80.     return DB_REC_TOO_LONG ;
  81. header.hdrlngth = (sizeof(DBHEADER) + 1 + (sizeof(FLDHEADER) * fldcount) );
  82. header.version    = 3 ;
  83. header.updatey    = year;
  84. header.updatem    = month;
  85. header.updated    = day;
  86. header.maxrec    = 0L ;
  87. action = Open(filename, &hndl, FILE_TRUNCATE | FILE_CREATE , fsOpenMode) ;
  88. if(action)
  89.     return action ;
  90. rc = OK ;
  91. if(Write(hndl, &header, sizeof(header) ) )
  92.     rc = DB_WRITE_ERR ;
  93. else
  94.     {
  95.     memset(fldhdr.reserved1, 0, 4) ;
  96.     memset(fldhdr.reserved2, 0, 14) ;
  97.     for(x = 0 ; x < fldcount ; x++)
  98.         {
  99.         memset(fldhdr.name, 0, 11) ;
  100.         fldhdr.type = toupper(info[x].type) ;
  101.         strcpy(fldhdr.name, info[x].name ) ;
  102.         strupr(fldhdr.name) ;
  103.         fldhdr.length = info[x].length ;
  104.         fldhdr.decimal = info[x].decimal ;
  105.         if(Write(hndl, &fldhdr, sizeof(fldhdr)) )
  106.             {
  107.             rc = DB_WRITE_ERR ;
  108.             break ;
  109.             }
  110.         }
  111.     }
  112. if (Write(hndl, EOHeader, 2) )
  113.     rc = DB_WRITE_ERR ;
  114. Close(hndl) ;
  115. if(rc)
  116.     unlink(filename) ;
  117. return rc ;
  118. }
  119.  
  120.  
  121. SHORT EXPENTRY DbOpen(CHAR *file, SHORT readwrite)
  122. {
  123. CHAR filename[256] ;
  124. USHORT action, fsOpenMode ;
  125. FLDHEADER *flds ;
  126. SHORT rc = OK, x ;
  127.  
  128. strcpy(filename, file) ;
  129. if(strstr(strupr(filename), ".DBF") == NULL)
  130.     strcat(filename, ".DBF") ;
  131.  
  132. //find free file handle entry
  133. for (curdb = 0; curdb < MAXDB; curdb++)
  134.     if (dbptr[curdb] == 0)
  135.         break;
  136.  
  137. //all file handle entries in use
  138. if (curdb == MAXDB)
  139.     return DB_NO_HANDLES;
  140.  
  141. openmode[curdb] = readwrite ;
  142.  
  143. if(readwrite)
  144.     // get access to write to the database
  145.     fsOpenMode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE |
  146.                   OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_WRITE_THROUGH;
  147. else
  148.     fsOpenMode = OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE ;
  149.  
  150. if( (action = Open(filename, &dbptr[curdb], FILE_OPEN, fsOpenMode)) != OK)
  151.     return action ;
  152.  
  153. if(RefressDBheader())
  154.     {
  155.     Close(dbptr[curdb]) ;
  156.     dbptr[curdb] = 0 ;
  157.     return DB_UPDATE_ERR ;
  158.     }
  159.  
  160. fldcnt[curdb] = (dbdata[curdb].hdrlngth - sizeof(DBHEADER)) / sizeof(FLDHEADER) ;
  161.  
  162. if((flds = (FLDHEADER *) MemAlloc(fldcnt[curdb] * sizeof(FLDHEADER))) == NULL)
  163.     {
  164.     Close(dbptr[curdb]) ;
  165.     dbptr[curdb] = 0 ;
  166.     return DB_MEM_ERR ;
  167.     }
  168.  
  169. fieldinfo[curdb] = SELECTOROF(flds) ;
  170. if(Seek(sizeof(DBHEADER)))
  171.     rc = DB_SEEK_ERR ;
  172. else
  173.     {
  174.     for(x = 0 ; x < fldcnt[curdb]; x++)
  175.         {
  176.         if(Read(dbptr[curdb], &flds[x], sizeof(FLDHEADER)) )
  177.             {
  178.             rc = DB_READ_ERR ;
  179.             break ;
  180.             }
  181.         }
  182.     }
  183. if(rc)
  184.     {
  185.     Free(flds) ;
  186.     Close(dbptr[curdb]) ;
  187.     dbptr[curdb] = 0 ;
  188.     curdb = rc ;
  189.     }
  190. return curdb ;
  191. }
  192.  
  193.  
  194. SHORT EXPENTRY DbClose(SHORT dbhndl)
  195. {
  196. curdb = dbhndl ;
  197.  
  198. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  199.     return DB_INVALID_HANDLE ;
  200.  
  201. Free(MAKEP(fieldinfo[curdb], 0)) ;
  202. Close(dbptr[curdb]) ;
  203. dbptr[curdb] = 0 ;
  204. return 0 ;
  205. }
  206.  
  207. SHORT EXPENTRY DbInfo(SHORT hndl, DBREPORT *info)
  208. {
  209. SHORT rc ;
  210.  
  211. curdb = hndl ;
  212.  
  213. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  214.     rc = DB_INVALID_HANDLE ;
  215.  
  216. else if(RefressDBheader() )
  217.     rc = DB_READ_ERR ;
  218. else
  219.     {
  220.     info->updatey =  dbdata[curdb].updatey ;
  221.     info->updatem =  dbdata[curdb].updatem ;
  222.     info->updated =  dbdata[curdb].updated ;
  223.     info->maxrec  =  dbdata[curdb].maxrec ;
  224.     info->reclngth = dbdata[curdb].reclngth ;
  225.     info->numflds =(SHORT) ((dbdata[curdb].hdrlngth - sizeof(DBHEADER) - 1) / sizeof(FLDHEADER)) ;
  226.     rc = OK ;
  227.     }
  228. return rc ;
  229. }
  230.  
  231. SHORT EXPENTRY FldInfo(SHORT hndl, SHORT fldnum, FLDDATA FAR *fldinfo)
  232. {
  233. FLDHEADER *fldheader ;
  234.  
  235. curdb = hndl ;
  236. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  237.     return DB_INVALID_HANDLE ;
  238.  
  239. if(fldnum >= fldcnt[curdb])
  240.     return DB_INVALID_FIELD ;
  241.  
  242. fldheader = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  243. memcpy(fldinfo->name, fldheader[fldnum].name, 11) ;
  244. fldinfo->type = fldheader[fldnum].type ;
  245. fldinfo->length = fldheader[fldnum].length ;
  246. fldinfo->decimal = fldheader[fldnum].decimal ;
  247. return 0 ;
  248. }
  249.  
  250.  
  251.  
  252. SHORT EXPENTRY AddRec(SHORT dbhndl, CHAR *recdata, LONG *recnum, SHORT lockstatus)
  253. {
  254. SHORT rc = OK, rc2 = OK ;
  255. ULONG end ;
  256. CHAR *newrec ;
  257. LONG Offset, Range ;
  258.  
  259. curdb = dbhndl ;
  260.  
  261. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  262.     return DB_INVALID_HANDLE ;
  263.  
  264. if(openmode[curdb] == READONLY)
  265.     return DB_READONLY ;
  266.  
  267. /*
  268.   Allocate a buffer for the New record.  if NULL is sent as
  269.   the record pointer then set to all spaces.  Add this to the
  270.   database as the new record.
  271. */
  272.  
  273. if( (newrec = (CHAR *) MemAlloc(RECLNGTH)) == NULL)
  274.     return DB_MEM_ERR ;
  275.  
  276. if(recdata == NULL)
  277.     memset(newrec, ' ', RECLNGTH) ;
  278. else
  279.     memcpy(newrec, recdata, RECLNGTH) ;
  280.  
  281. /*
  282.  Lock the database while we add the new record to the database.
  283.  Compute the new records number and set the database header to
  284.  reflect the new maxrecords value.
  285.  
  286.  Then unlock the total database and if requested by calling routine
  287.  lock the new record.
  288. */
  289. if( (end = FileSize()) < RECSTART)
  290.    return DB_SEEK_ERR ;
  291.  
  292. Offset = 0L ;
  293. Range =  (LONG) end ;
  294.  
  295. if(Lock(Offset, Range, LOCK))
  296.     rc =  DB_LOCK_ERR ;
  297. else if (RefressDBheader())
  298.     rc = DB_UPDATE_ERR ;
  299. else if (RecordWrite(newrec, dbdata[curdb].maxrec) )
  300.     rc = DB_WRITE_ERR ;
  301. else
  302.     {
  303.     *recnum = dbdata[curdb].maxrec ;
  304.     rc = UpdateDBheader(1) ;
  305.     }
  306.  
  307. Lock(Offset, Range, UNLOCK) ;
  308.  
  309. if(lockstatus  && rc == OK)
  310.     {
  311.     Offset = (LONG) end ;
  312.     Range = (LONG) RECLNGTH ;
  313.     if(Lock(Offset, Range, LOCK) )
  314.         rc = DB_LOCK_ERR ;
  315.     }
  316. if(newrec)
  317.     Free(newrec) ;
  318. return rc;
  319. }
  320.  
  321.  
  322. SHORT EXPENTRY PutRec(SHORT dbhndl, CHAR *recdata, LONG recnum)
  323. {
  324. SHORT rc = OK;
  325.  
  326. curdb = dbhndl ;
  327.  
  328. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  329.     rc = DB_INVALID_HANDLE ;
  330. else if(openmode[curdb] == READONLY)
  331.      rc = DB_READONLY ;
  332. else if(RefressDBheader())
  333.     rc = DB_READ_ERR ;
  334. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  335.     rc = DB_INVALID_RECORD ;
  336.  
  337. else if (RecordWrite(recdata, recnum))
  338.     rc = DB_WRITE_ERR ;
  339. return rc;
  340. }
  341.  
  342.  
  343. SHORT EXPENTRY GetRec(SHORT dbhndl, CHAR *recdata, LONG recnum)
  344. {
  345. SHORT rc = OK;
  346.  
  347. curdb = dbhndl ;
  348.  
  349. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  350.     rc = DB_INVALID_HANDLE ;
  351. else if(RefressDBheader())
  352.     rc = DB_READ_ERR ;
  353. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  354.     rc = DB_INVALID_RECORD ;
  355.  
  356. else if (RecordRead(recdata, recnum))
  357.         rc = DB_READ_ERR ;
  358.  
  359. return rc;
  360. }
  361.  
  362. SHORT EXPENTRY DeleteRec(SHORT dbhndl, LONG recnum)
  363. {
  364. SHORT rc = OK;
  365.  
  366. curdb = dbhndl ;
  367.  
  368. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  369.     rc = DB_INVALID_HANDLE ;
  370. else if(RefressDBheader())
  371.     rc = DB_READ_ERR ;
  372. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  373.     rc = DB_INVALID_RECORD ;
  374.  
  375. else if(openmode[curdb] == READONLY)
  376.     rc = DB_READONLY ;
  377.  
  378. else if (RecordSeek(recnum) == 0)
  379.     rc = DB_SEEK_ERR ;
  380.  
  381. else if (Write(dbptr[curdb], "*", 1))
  382.     rc = DB_WRITE_ERR ;
  383.  
  384. return rc ;
  385. }
  386.  
  387.  
  388. SHORT EXPENTRY RecoverRec(SHORT dbhndl, LONG recnum)
  389. {
  390. CHAR record;
  391. SHORT rc = OK;
  392.  
  393. curdb = dbhndl ;
  394.  
  395. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  396.     rc = DB_INVALID_HANDLE ;
  397. else if(openmode[curdb] == READONLY)
  398.     rc = DB_READONLY ;
  399. else if(RefressDBheader())
  400.     rc = DB_READ_ERR ;
  401. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  402.     rc = DB_INVALID_RECORD ;
  403. else if (RecordSeek(recnum) == 0)
  404.     rc = DB_SEEK_ERR ;
  405. else if (Read(dbptr[curdb], &record, 1))
  406.     rc = DB_READ_ERR ;
  407. else if(record == ' ')
  408.     rc = DB_NOT_DELETED ;
  409. else if (RecordSeek(recnum) == 0)
  410.     rc = DB_SEEK_ERR ;
  411. else if (Write(dbptr[curdb], " ", 1))
  412.     rc = DB_WRITE_ERR ;
  413.  
  414. return rc ;
  415. }
  416.  
  417. SHORT EXPENTRY CheckRec(SHORT dbhndl, LONG recnum)
  418. {
  419. CHAR record;
  420. SHORT rc;
  421.  
  422. curdb = dbhndl ;
  423.  
  424. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  425.     rc = DB_INVALID_HANDLE ;
  426. else if(RefressDBheader())
  427.     rc = DB_READ_ERR ;
  428. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  429.     rc = DB_INVALID_RECORD ;
  430. else
  431.     {
  432.     if(RecordSeek(recnum) == 0)
  433.         rc = DB_SEEK_ERR ;
  434.     else
  435.         {
  436.         if(Read(dbptr[curdb], &record, sizeof(record)) )
  437.             rc = DB_READ_ERR ;
  438.         else
  439.             {
  440.             if(record == '*')
  441.                 rc = 0 ;
  442.             else
  443.                 rc = 1 ;
  444.             }
  445.         }
  446.     }
  447. return rc ;
  448. }
  449.  
  450. SHORT EXPENTRY LockRec(SHORT dbhndl, LONG recnum)
  451. {
  452. LONG Offset, Range ;
  453. SHORT x, rc = OK;
  454.  
  455. curdb = dbhndl ;
  456.  
  457. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  458.     rc = DB_INVALID_HANDLE ;
  459.  
  460. else if(openmode[curdb] == READONLY)
  461.     rc = DB_READONLY ;
  462. else if(RefressDBheader())
  463.     rc = DB_READ_ERR ;
  464. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  465.     rc = DB_INVALID_RECORD ;
  466. else
  467.     {
  468.     if( (Offset = RecordSeek(recnum) ) == 0)
  469.         rc = DB_SEEK_ERR ;
  470.     else
  471.         {
  472.         Range = RECLNGTH ;
  473.         rc = Lock(Offset, Range, LOCK) ;
  474.         }
  475.     }
  476. return rc ;
  477. }
  478.  
  479.  
  480. SHORT EXPENTRY UnLockRec(SHORT dbhndl, LONG recnum)
  481. {
  482. LONG Offset, Range ;
  483. SHORT x, rc;
  484.  
  485. curdb = dbhndl ;
  486.  
  487. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  488.     rc = DB_INVALID_HANDLE ;
  489.  
  490. else if(openmode[curdb] == READONLY)
  491.     rc = DB_READONLY ;
  492. else if(RefressDBheader())
  493.     rc = DB_READ_ERR ;
  494. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  495.     rc = DB_INVALID_RECORD ;
  496.  
  497. else
  498.     {
  499.     Offset = RecordSeek(recnum) ;
  500.     if(Offset == 0)
  501.         rc = DB_SEEK_ERR ;
  502.     else
  503.         {
  504.         Range = RECLNGTH ;
  505.         rc = Lock(Offset, Range, UNLOCK) ;
  506.         }
  507.     }
  508. return rc ;
  509. }
  510.  
  511.  
  512. SHORT EXPENTRY GetField(SHORT dbhndl, LONG recnum, CHAR *buff, SHORT fldnm)
  513. {
  514. static CHAR recbuff[MAXRECLNGTH + 1], fldbuff[MAXFLDLNGTH + 1] ;
  515. static SHORT rc = OK, type, offset, length;
  516.  
  517. curdb = dbhndl ;
  518. rc = OK ;
  519. memset(recbuff, 0, MAXRECLNGTH + 1) ;
  520. memset(fldbuff, 0, MAXFLDLNGTH + 1) ;
  521.  
  522. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  523.     rc = DB_INVALID_HANDLE ;
  524.  
  525. else if(RefressDBheader())
  526.     rc = DB_READ_ERR ;
  527. else if (recnum < 0 || recnum >= dbdata[curdb].maxrec)
  528.         rc = DB_INVALID_RECORD ;
  529. else if (RecordRead(recbuff, recnum) )
  530.         rc = DB_READ_ERR ;
  531. else
  532.     {
  533.     type = FieldType(fldnm) ;
  534.     offset = FieldOffset(fldnm) ;
  535.     length = FieldLength(fldnm) ;
  536.     switch(type)
  537.         {
  538.         case 'C':
  539.             memcpy(fldbuff, &recbuff[offset], length) ;
  540.             strcpy(buff, rtrim(fldbuff)) ;
  541.             break ;
  542.         case 'L':
  543.             buff[0] = recbuff[offset] ;
  544.             buff[1] = 0 ;
  545.             break ;
  546.         case 'D':
  547.             memmove(fldbuff, &recbuff[offset + 4], 2) ;
  548.             fldbuff[2] = '/' ;
  549.             memmove(&fldbuff[3], &recbuff[offset + 6], 2) ;
  550.             fldbuff[5] = '/' ;
  551.             memmove(&fldbuff[6], &recbuff[offset + 2], 2) ;
  552.             strcpy(buff, fldbuff) ;
  553.             break ;
  554.         case 'N':
  555.             memcpy(fldbuff, &recbuff[offset], length) ;
  556.             strcpy(buff, ltrim(fldbuff) ) ;
  557.             break ;
  558.         default:
  559.             rc = DB_INVALID_FIELD ;
  560.             break ;
  561.         }
  562.     }
  563. return rc ;
  564. }
  565.  
  566.  
  567.  
  568. SHORT EXPENTRY PutField(SHORT dbhndl, LONG recnum, CHAR *buff, SHORT fldnm)
  569. {
  570. static CHAR recbuff[MAXRECLNGTH + 1], fldbuff[MAXFLDLNGTH + 1] ;
  571. static SHORT x, rc, type, offset, length ;
  572.  
  573. rc = OK ;
  574. curdb = dbhndl ;
  575. memset(recbuff, 0, MAXRECLNGTH + 1) ;
  576. memset(fldbuff, 0, MAXFLDLNGTH + 1) ;
  577. strcpy(fldbuff, buff) ;
  578.  
  579. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  580.     rc = DB_INVALID_HANDLE ;
  581. else if(openmode[curdb] == READONLY)
  582.     rc = DB_READONLY ;
  583. else if(RefressDBheader())
  584.     rc = DB_READ_ERR ;
  585. else if (recnum < 0 || recnum >= dbdata[curdb].maxrec)
  586.         rc = DB_INVALID_RECORD ;
  587. else if (RecordRead(recbuff, recnum) )
  588.         rc = DB_READ_ERR ;
  589. else
  590.     {
  591.     type = FieldType(fldnm) ;
  592.      offset = FieldOffset(fldnm) ;
  593.     length = FieldLength(fldnm) ;
  594.     switch(type)
  595.         {
  596.         case 'C':
  597.             if(strlen(fldbuff) > length)
  598.                 rc = DB_FLD_LNGTH ;
  599.             else
  600.                 {
  601.                 for(x = strlen(fldbuff) ; x < length ; x++)
  602.                     fldbuff[x] = ' ' ;
  603.                 memcpy(&recbuff[offset], fldbuff, length) ;
  604.                 }
  605.             break ;
  606.         case 'L':
  607.             recbuff[offset] = toupper(fldbuff[0]);
  608.             break ;
  609.         case 'D':
  610.             if(strlen(fldbuff) == 8)
  611.                 {
  612.                 memmove(&recbuff[offset], "19", 2) ;
  613.                 memmove(&recbuff[offset + 2], &fldbuff[6], 2) ;
  614.                 }
  615.             else if (strlen(fldbuff) == 10)
  616.                 memmove(&recbuff[offset], &fldbuff[6], 4) ;
  617.             else
  618.                 rc = DB_INVALID_DATE ;
  619.             if(rc == OK)
  620.                 {
  621.                 memmove(&recbuff[offset + 4], fldbuff, 2) ;
  622.                 memmove(&recbuff[offset + 6], &fldbuff[3], 2) ;
  623.                 }
  624.             break ;
  625.         case 'N':
  626.             if(FormatNumber(fldnm, fldbuff) )
  627.                 rc = DB_INVALID_NUMBER ;
  628.             else
  629.                 memcpy(&recbuff[offset], fldbuff, length) ;
  630.             break ;
  631.         default:
  632.             rc = DB_INVALID_FIELD ;
  633.             break ;
  634.         }
  635.     }
  636. if(rc == OK)
  637.     rc = RecordWrite(recbuff, recnum) ;
  638. return rc ;
  639. }
  640.  
  641.  
  642. /*
  643.     INTERNAL FUNCTIONS
  644. */
  645.  
  646. SHORT UpdateDBheader(SHORT direction)
  647. {
  648. SHORT rc = OK, x, locked = FALSE ;
  649. LONG Offset, Range ;
  650. CHAR day, month, year ;
  651.  
  652. Offset = 0L ;
  653. Range = sizeof(DBHEADER) ;
  654.  
  655. GetDate(&day, &month, &year) ;
  656. dbdata[curdb].updatey = year ;
  657. dbdata[curdb].updatem = month;
  658. dbdata[curdb].updated = day;
  659.  
  660. if(Lock(Offset, Range, LOCK))
  661.     rc = DB_UPDATE_ERR ;
  662. else if (Seek(0L))
  663.     rc = DB_UPDATE_ERR ;
  664. else if(Read(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER) ) )
  665.     rc = DB_UPDATE_ERR ;
  666. else
  667.     {
  668.     dbdata[curdb].maxrec += direction ;
  669.     if (Seek(0L))
  670.         rc = DB_UPDATE_ERR ;
  671.     else if(Write(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER)) )
  672.         rc = DB_UPDATE_ERR ;
  673.     }
  674.  
  675. Lock(Offset, Range, UNLOCK) ;
  676. return rc ;
  677. }
  678.  
  679.  
  680. SHORT RefressDBheader(VOID)
  681. {
  682. SHORT rc = OK ;
  683.  
  684. if (Seek(0L))
  685.     rc = DB_UPDATE_ERR ;
  686. else if(Read(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER) ) )
  687.     rc = DB_UPDATE_ERR ;
  688. return rc ;
  689. }
  690.  
  691.  
  692.  
  693. SHORT RecordWrite(CHAR *record, LONG recnum)
  694. {
  695. SHORT rc = OK ;
  696.  
  697. if(RecordSeek(recnum) == 0 )
  698.     rc = DB_SEEK_ERR ;
  699. else if (Write(dbptr[curdb], record, RECLNGTH))
  700.     rc = DB_WRITE_ERR ;
  701. return rc ;
  702. }
  703.  
  704. SHORT RecordRead(CHAR *record, LONG recnum)
  705. {
  706. SHORT rc = OK ;
  707.  
  708. if(RecordSeek(recnum) == 0)
  709.     rc = DB_SEEK_ERR ;
  710. else if (Read(dbptr[curdb], record, RECLNGTH))
  711.     rc = DB_READ_ERR ;
  712. return rc ;
  713. }
  714.  
  715. SHORT FieldDecimal(SHORT fldnum)
  716. {
  717. FLDHEADER *fldinfo ;
  718.  
  719. if(fldnum >= fldcnt[curdb])
  720.     return DB_INVALID_FIELD ;
  721. fldinfo = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  722. return(fldinfo[fldnum].decimal) ;
  723. }
  724.  
  725.  
  726. SHORT FieldType(SHORT fldnum)
  727. {
  728. FLDHEADER *fldinfo ;
  729.  
  730. if(fldnum >= fldcnt[curdb])
  731.     return DB_INVALID_FIELD ;
  732.  
  733. fldinfo = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  734. return(fldinfo[fldnum].type) ;
  735. }
  736.  
  737. SHORT FieldOffset(SHORT fldnum)
  738. {
  739. SHORT offset, x;
  740. FLDHEADER *fldinfo ;
  741.  
  742. if(fldnum >= fldcnt[curdb])
  743.     return DB_INVALID_FIELD ;
  744.  
  745. offset = 1 ;
  746. fldinfo = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  747. for(x = 0 ;  x < fldnum ; x++)
  748.     offset += fldinfo[x].length ;
  749. return offset ;
  750. }
  751.  
  752. SHORT FieldLength(SHORT fldnum)
  753. {
  754. FLDHEADER *fldinfo ;
  755.  
  756. if(fldnum >= fldcnt[curdb])
  757.     return DB_INVALID_FIELD ;
  758.  
  759. fldinfo = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  760. return(fldinfo[fldnum].length) ;
  761. }
  762.  
  763. SHORT FldName2Num(CHAR *name)
  764. {
  765. SHORT x ;
  766. FLDHEADER *fldinfo ;
  767. CHAR fldname[12] ;
  768. strcpy(fldname, strupr(name)) ;
  769.  
  770. fldinfo = (FLDHEADER *) MAKEP(fieldinfo[curdb], 0) ;
  771.  
  772. for(x = 0 ; x < fldcnt[curdb] ; x++)
  773.     {
  774.     if(strcmp(fldname, strupr(fldinfo[x].name) ) == 0)
  775.         break ;
  776.     }
  777. if(x >= fldcnt[curdb] )
  778.     x = DB_INVALID_FIELD ;
  779. return x ;
  780. }
  781.  
  782. CHAR *rtrim(CHAR *text)
  783. {
  784. SHORT x ;
  785. x = strlen(text) - 1 ;
  786. while(text[x] == ' ')
  787.     text[x--] = 0 ;
  788. return text ;
  789. }
  790.  
  791. CHAR *ltrim(CHAR *text)
  792. {
  793. SHORT x ;
  794. x = 0 ;
  795. while(text[x] == ' ') x++ ;
  796. return &text[x] ;
  797. }
  798.  
  799. SHORT FormatNumber(SHORT fldnum, CHAR *text)
  800. {
  801. SHORT origlength,
  802.     origright,
  803.     origleft,
  804.     destright,
  805.     destleft,
  806.     destlength,
  807.     pad,
  808.     x ;
  809. CHAR frmttext[20], *period ;
  810.  
  811. destlength = FieldLength(fldnum) ;
  812. destright = FieldDecimal(fldnum) ;
  813. if(destright > 0)
  814.     destright ++ ; //add for decimal
  815. else
  816.     destright = 0 ;
  817. destleft = destlength - destright ;
  818. origlength = strlen(text) ;
  819. if( (period = strchr(text, '.')) != NULL)
  820.     origright = origlength - strcspn(text, ".") ;
  821. else
  822.     origright = 0 ;
  823. origleft = origlength - origright ;
  824. if(origleft > destleft)
  825.     return DB_INVALID_NUM ;
  826. pad = destleft - origleft;
  827.  
  828. //left pad with spaces and move left side of decimal over
  829. for(x = 0 ;  x < pad; x++)
  830.     frmttext[x] = ' ' ;
  831. memcpy(&frmttext[x], text, origleft) ;
  832.  
  833. if(destright > 0)
  834.     {
  835.     frmttext[destleft] = '.' ;
  836.     if(origright > 0)
  837.         memcpy(&frmttext[destleft + 1], period + 1, min(destright, origright)) ;
  838.     if(destright > origright)
  839.         {
  840.         for(x = destleft + origright + 1; x < destlength ; x++)
  841.             frmttext[x] ='0' ;
  842.         }
  843.     }
  844. strcpy(text, frmttext) ;
  845. return OK ;
  846. }
  847.  
  848.  
  849. /*
  850.     All functions with OS/2 Calls are located below
  851. */
  852.  
  853. ULONG RecordSeek(LONG recnum)
  854. {
  855. ULONG newpos ;
  856. if(DosChgFilePtr(dbptr[curdb],
  857.                 (LONG) RECSTART + ((LONG) recnum * (LONG) RECLNGTH),
  858.                  FILE_BEGIN, &newpos) )
  859.     newpos = 0 ;
  860. return newpos ;
  861. }
  862.  
  863. VOID *MemAlloc(USHORT size)
  864. {
  865. SEL selrec ;
  866.  
  867. if(DosAllocSeg(size, &selrec, 0))
  868.     return NULL ;
  869. else
  870.     return MAKEP(selrec, 0 ) ;
  871. }
  872.  
  873. VOID Free(VOID *ptr)
  874. {
  875. DosFreeSeg(SELECTOROF(ptr)) ;
  876. }
  877.  
  878. SHORT Write(USHORT handle, VOID *data, USHORT length)
  879. {
  880. USHORT written ;
  881. SHORT rc = OK;
  882.  
  883. if(DosWrite(handle, data, length, &written))
  884.     rc = DB_WRITE_ERR ;
  885. else if(written != length)
  886.     rc = DB_WRITE_ERR ;
  887. return rc ;
  888. }
  889.  
  890. SHORT Read(USHORT handle, VOID *data, USHORT length)
  891. {
  892. USHORT read ;
  893. SHORT rc = OK;
  894.  
  895. if(DosRead(handle, data, length, &read))
  896.     rc = DB_READ_ERR ;
  897. else if(read != length)
  898.     rc = DB_READ_ERR ;
  899. return rc ;
  900. }
  901.  
  902. SHORT Seek(LONG distance)
  903. {
  904. ULONG newpos ;
  905. SHORT rc = OK ;
  906. if(DosChgFilePtr(dbptr[curdb], distance, FILE_BEGIN, &newpos) )
  907.     rc = DB_SEEK_ERR ;
  908. return rc ;
  909. }
  910.  
  911. SHORT FileSize(VOID)
  912. {
  913. ULONG size ;
  914. if(DosChgFilePtr(dbptr[curdb], 0L, FILE_END, &size))
  915.     size = 0 ;
  916. return size ;
  917. }
  918.  
  919. SHORT Lock(LONG offset, LONG range, BOOL action)
  920. {
  921. FILELOCK flock ;
  922. SHORT rc = OK, x ;
  923.  
  924. flock.lOffset = offset ;
  925. flock.lRange = range ;
  926.  
  927. if(action)
  928.     {
  929.     for(x = 0 ; x < 10 ; x++)
  930.         {
  931.         if(DosFileLocks(dbptr[curdb], (PFILELOCK) NULL, &flock ) == 0)
  932.             break ;
  933.         DosSleep(100L) ;
  934.         }
  935.     if(x >= 10)
  936.         rc = DB_LOCK_ERR ;
  937.     }
  938. else
  939.     {
  940.     for(x = 0 ; x < 10 ; x++)
  941.         {
  942.         if(DosFileLocks(dbptr[curdb], &flock, (PFILELOCK) NULL ) == 0)
  943.             break ;
  944.         DosSleep(100L) ;
  945.         }
  946.     if(x >= 10)
  947.         rc = DB_UNLOCK_ERR ;
  948.     }
  949.  
  950. return rc ;
  951. }
  952.  
  953. SHORT GetDate(CHAR *day, CHAR *month, CHAR *year)
  954. {
  955. DATETIME dt ;
  956. DosGetDateTime(&dt) ;
  957. *day = dt.day ;
  958. *month = dt.month ;
  959. *year = dt.year - 1900 ;
  960. }
  961.  
  962. VOID Sleep(LONG time)
  963. {
  964. DosSleep(time) ;
  965. return ;
  966. }
  967.  
  968. SHORT Close(USHORT handle)
  969. {
  970. if(DosClose((HFILE) handle) )
  971.     return DB_CLOSE_ERR ;
  972. }
  973.  
  974. SHORT Open(CHAR *name, USHORT *handle, USHORT flags, USHORT mode)
  975. {
  976. USHORT action, rc, x ;
  977.  
  978. //make 3 attempts to open file
  979. for(x = 0 ; x < 3 ; x++)
  980.     {
  981.     rc = DosOpen2(name, handle, &action, 0L,
  982.                      FILE_NORMAL,
  983.                      flags, mode, NULL, 0L) ;
  984.     if(rc == 0)
  985.         break ;
  986.     Sleep(100L) ;
  987.     }
  988.  
  989. if(rc == ERROR_ACCESS_DENIED ||
  990.    rc == ERROR_INVALID_ACCESS)
  991.     return DB_ACCESS_DENIED ;
  992. else if (rc != 0)
  993.     return DB_OPEN_ERR ;
  994. }
  995.