home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / DBMANP.ZIP / DBMANIP.C < prev    next >
Text File  |  1992-07-15  |  22KB  |  984 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.     remove(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 = NULL;
  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] = (RECSTART - 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] = 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.     MemFree(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. MemFree(fieldinfo[curdb]) ;
  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 = RECLNGTH ;
  225.     info->numflds =(SHORT) ((RECSTART - 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 = fieldinfo[curdb] ;
  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 = NULL;
  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. newrec = (CHAR *) MemAlloc(RECLNGTH) ;
  273. if(newrec == 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. end = FileSize() ;
  290. if(end  < RECSTART)
  291.    return DB_SEEK_ERR ;
  292.  
  293. Offset = 0L ;
  294. Range =  (LONG) end ;
  295.  
  296. if(Lock(Offset, Range, LOCK))
  297.     rc =  DB_LOCK_ERR ;
  298. else if (RefressDBheader())
  299.     rc = DB_UPDATE_ERR ;
  300. else if (RecordWrite(newrec, dbdata[curdb].maxrec) )
  301.     rc = DB_WRITE_ERR ;
  302. else
  303.     {
  304.     Lock(Offset, Range, UNLOCK) ;
  305.     *recnum = dbdata[curdb].maxrec ;
  306.     rc = UpdateDBheader(1) ;
  307.     }
  308.  
  309.  
  310. if(lockstatus  && rc == OK)
  311.     {
  312.     Offset = (LONG) end ;
  313.     Range = (LONG) RECLNGTH ;
  314.     if(Lock(Offset, Range, LOCK) )
  315.         rc = DB_LOCK_ERR ;
  316.     }
  317. if(newrec != NULL)
  318.     MemFree(newrec) ;
  319. return rc;
  320. }
  321.  
  322.  
  323. SHORT EXPENTRY PutRec(SHORT dbhndl, CHAR *recdata, LONG recnum)
  324. {
  325. SHORT rc = OK;
  326.  
  327. curdb = dbhndl ;
  328.  
  329. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  330.     rc = DB_INVALID_HANDLE ;
  331. else if(openmode[curdb] == READONLY)
  332.      rc = DB_READONLY ;
  333. else if(RefressDBheader())
  334.     rc = DB_READ_ERR ;
  335. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  336.     rc = DB_INVALID_RECORD ;
  337.  
  338. else if (RecordWrite(recdata, recnum))
  339.     rc = DB_WRITE_ERR ;
  340. return rc;
  341. }
  342.  
  343.  
  344. SHORT EXPENTRY GetRec(SHORT dbhndl, CHAR *recdata, LONG recnum)
  345. {
  346. SHORT rc = OK;
  347.  
  348. curdb = dbhndl ;
  349.  
  350. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  351.     rc = DB_INVALID_HANDLE ;
  352. else if(RefressDBheader())
  353.     rc = DB_READ_ERR ;
  354. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  355.     rc = DB_INVALID_RECORD ;
  356.  
  357. else if (RecordRead(recdata, recnum))
  358.         rc = DB_READ_ERR ;
  359.  
  360. return rc;
  361. }
  362.  
  363. SHORT EXPENTRY DeleteRec(SHORT dbhndl, LONG recnum)
  364. {
  365. SHORT rc = OK;
  366.  
  367. curdb = dbhndl ;
  368.  
  369. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  370.     rc = DB_INVALID_HANDLE ;
  371. else if(RefressDBheader())
  372.     rc = DB_READ_ERR ;
  373. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  374.     rc = DB_INVALID_RECORD ;
  375.  
  376. else if(openmode[curdb] == READONLY)
  377.     rc = DB_READONLY ;
  378.  
  379. else if (RecordSeek(recnum) == 0)
  380.     rc = DB_SEEK_ERR ;
  381.  
  382. else if (Write(dbptr[curdb], "*", 1))
  383.     rc = DB_WRITE_ERR ;
  384.  
  385. return rc ;
  386. }
  387.  
  388.  
  389. SHORT EXPENTRY RecoverRec(SHORT dbhndl, LONG recnum)
  390. {
  391. CHAR record;
  392. SHORT rc = OK;
  393.  
  394. curdb = dbhndl ;
  395.  
  396. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  397.     rc = DB_INVALID_HANDLE ;
  398. else if(openmode[curdb] == READONLY)
  399.     rc = DB_READONLY ;
  400. else if(RefressDBheader())
  401.     rc = DB_READ_ERR ;
  402. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  403.     rc = DB_INVALID_RECORD ;
  404. else if (RecordSeek(recnum) == 0)
  405.     rc = DB_SEEK_ERR ;
  406. else if (Read(dbptr[curdb], &record, 1))
  407.     rc = DB_READ_ERR ;
  408. else if(record == ' ')
  409.     rc = DB_NOT_DELETED ;
  410. else if (RecordSeek(recnum) == 0)
  411.     rc = DB_SEEK_ERR ;
  412. else if (Write(dbptr[curdb], " ", 1))
  413.     rc = DB_WRITE_ERR ;
  414.  
  415. return rc ;
  416. }
  417.  
  418. SHORT EXPENTRY CheckRec(SHORT dbhndl, LONG recnum)
  419. {
  420. CHAR record;
  421. SHORT rc;
  422.  
  423. curdb = dbhndl ;
  424.  
  425. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  426.     rc = DB_INVALID_HANDLE ;
  427. else if(RefressDBheader())
  428.     rc = DB_READ_ERR ;
  429. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  430.     rc = DB_INVALID_RECORD ;
  431. else
  432.     {
  433.     if(RecordSeek(recnum) == 0)
  434.         rc = DB_SEEK_ERR ;
  435.     else
  436.         {
  437.         if(Read(dbptr[curdb], &record, sizeof(record)) )
  438.             rc = DB_READ_ERR ;
  439.         else
  440.             {
  441.             if(record == '*')
  442.                 rc = 0 ;
  443.             else
  444.                 rc = 1 ;
  445.             }
  446.         }
  447.     }
  448. return rc ;
  449. }
  450.  
  451. SHORT EXPENTRY LockRec(SHORT dbhndl, LONG recnum)
  452. {
  453. LONG Offset, Range ;
  454. SHORT x, rc = OK;
  455.  
  456. curdb = dbhndl ;
  457.  
  458. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  459.     rc = DB_INVALID_HANDLE ;
  460.  
  461. else if(openmode[curdb] == READONLY)
  462.     rc = DB_READONLY ;
  463. else if(RefressDBheader())
  464.     rc = DB_READ_ERR ;
  465. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  466.     rc = DB_INVALID_RECORD ;
  467. else
  468.     {
  469.     if( (Offset = RecordSeek(recnum) ) == 0)
  470.         rc = DB_SEEK_ERR ;
  471.     else
  472.         {
  473.         Range = RECLNGTH ;
  474.         rc = Lock(Offset, Range, LOCK) ;
  475.         }
  476.     }
  477. return rc ;
  478. }
  479.  
  480.  
  481. SHORT EXPENTRY UnLockRec(SHORT dbhndl, LONG recnum)
  482. {
  483. LONG Offset, Range ;
  484. SHORT x, rc;
  485.  
  486. curdb = dbhndl ;
  487.  
  488. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  489.     rc = DB_INVALID_HANDLE ;
  490.  
  491. else if(openmode[curdb] == READONLY)
  492.     rc = DB_READONLY ;
  493. else if(RefressDBheader())
  494.     rc = DB_READ_ERR ;
  495. else if(recnum < 0 || recnum >= dbdata[curdb].maxrec)
  496.     rc = DB_INVALID_RECORD ;
  497.  
  498. else
  499.     {
  500.     Offset = RecordSeek(recnum) ;
  501.     if(Offset == 0)
  502.         rc = DB_SEEK_ERR ;
  503.     else
  504.         {
  505.         Range = RECLNGTH ;
  506.         rc = Lock(Offset, Range, UNLOCK) ;
  507.         }
  508.     }
  509. return rc ;
  510. }
  511.  
  512.  
  513. SHORT EXPENTRY GetField(SHORT dbhndl, LONG recnum, CHAR *buff, SHORT fldnm)
  514. {
  515. static CHAR recbuff[MAXRECLNGTH + 1], fldbuff[MAXFLDLNGTH + 1] ;
  516. static SHORT rc = OK, type, offset, length;
  517.  
  518. curdb = dbhndl ;
  519. rc = OK ;
  520. memset(recbuff, 0, MAXRECLNGTH + 1) ;
  521. memset(fldbuff, 0, MAXFLDLNGTH + 1) ;
  522.  
  523. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  524.     rc = DB_INVALID_HANDLE ;
  525.  
  526. else if(RefressDBheader())
  527.     rc = DB_READ_ERR ;
  528. else if (recnum < 0 || recnum >= dbdata[curdb].maxrec)
  529.         rc = DB_INVALID_RECORD ;
  530. else if (RecordRead(recbuff, recnum) )
  531.         rc = DB_READ_ERR ;
  532. else
  533.     {
  534.     type = FieldType(fldnm) ;
  535.     offset = FieldOffset(fldnm) ;
  536.     length = FieldLength(fldnm) ;
  537.     switch(type)
  538.         {
  539.         case 'C':
  540.             memcpy(fldbuff, &recbuff[offset], length) ;
  541.             strcpy(buff, rtrim(fldbuff)) ;
  542.             break ;
  543.         case 'L':
  544.             buff[0] = recbuff[offset] ;
  545.             buff[1] = 0 ;
  546.             break ;
  547.         case 'D':
  548.             memmove(fldbuff, &recbuff[offset + 4], 2) ;
  549.             fldbuff[2] = '/' ;
  550.             memmove(&fldbuff[3], &recbuff[offset + 6], 2) ;
  551.             fldbuff[5] = '/' ;
  552.             memmove(&fldbuff[6], &recbuff[offset + 2], 2) ;
  553.             strcpy(buff, fldbuff) ;
  554.             break ;
  555.         case 'N':
  556.             memcpy(fldbuff, &recbuff[offset], length) ;
  557.             strcpy(buff, ltrim(fldbuff) ) ;
  558.             break ;
  559.         default:
  560.             rc = DB_INVALID_FIELD ;
  561.             break ;
  562.         }
  563.     }
  564. return rc ;
  565. }
  566.  
  567.  
  568.  
  569. SHORT EXPENTRY PutField(SHORT dbhndl, LONG recnum, CHAR *buff, SHORT fldnm)
  570. {
  571. static CHAR recbuff[MAXRECLNGTH + 1], fldbuff[MAXFLDLNGTH + 1] ;
  572. static SHORT x, rc, type, offset, length ;
  573.  
  574. rc = OK ;
  575. curdb = dbhndl ;
  576. memset(recbuff, 0, MAXRECLNGTH + 1) ;
  577. memset(fldbuff, 0, MAXFLDLNGTH + 1) ;
  578. strcpy(fldbuff, buff) ;
  579.  
  580. if(curdb < 0 || curdb >= MAXDB || dbptr[curdb] == 0)
  581.     rc = DB_INVALID_HANDLE ;
  582. else if(openmode[curdb] == READONLY)
  583.     rc = DB_READONLY ;
  584. else if(RefressDBheader())
  585.     rc = DB_READ_ERR ;
  586. else if (recnum < 0 || recnum >= dbdata[curdb].maxrec)
  587.         rc = DB_INVALID_RECORD ;
  588. else if (RecordRead(recbuff, recnum) )
  589.         rc = DB_READ_ERR ;
  590. else
  591.     {
  592.     type = FieldType(fldnm) ;
  593.      offset = FieldOffset(fldnm) ;
  594.     length = FieldLength(fldnm) ;
  595.     switch(type)
  596.         {
  597.         case 'C':
  598.             if(strlen(fldbuff) > length)
  599.                 rc = DB_FLD_LNGTH ;
  600.             else
  601.                 {
  602.                 for(x = strlen(fldbuff) ; x < length ; x++)
  603.                     fldbuff[x] = ' ' ;
  604.                 memcpy(&recbuff[offset], fldbuff, length) ;
  605.                 }
  606.             break ;
  607.         case 'L':
  608.             recbuff[offset] = toupper(fldbuff[0]);
  609.             break ;
  610.         case 'D':
  611.             if(strlen(fldbuff) == 8)
  612.                 {
  613.                 memmove(&recbuff[offset], "19", 2) ;
  614.                 memmove(&recbuff[offset + 2], &fldbuff[6], 2) ;
  615.                 }
  616.             else if (strlen(fldbuff) == 10)
  617.                 memmove(&recbuff[offset], &fldbuff[6], 4) ;
  618.             else
  619.                 rc = DB_INVALID_DATE ;
  620.             if(rc == OK)
  621.                 {
  622.                 memmove(&recbuff[offset + 4], fldbuff, 2) ;
  623.                 memmove(&recbuff[offset + 6], &fldbuff[3], 2) ;
  624.                 }
  625.             break ;
  626.         case 'N':
  627.             if(FormatNumber(fldnm, fldbuff) )
  628.                 rc = DB_INVALID_NUMBER ;
  629.             else
  630.                 memcpy(&recbuff[offset], fldbuff, length) ;
  631.             break ;
  632.         default:
  633.             rc = DB_INVALID_FIELD ;
  634.             break ;
  635.         }
  636.     }
  637. if(rc == OK)
  638.     rc = RecordWrite(recbuff, recnum) ;
  639. return rc ;
  640. }
  641.  
  642.  
  643. /*
  644.     INTERNAL FUNCTIONS
  645. */
  646.  
  647. SHORT UpdateDBheader(SHORT direction)
  648. {
  649. SHORT rc = OK, x, locked = FALSE ;
  650. LONG Offset, Range ;
  651. CHAR day, month, year ;
  652.  
  653. Offset = 0L ;
  654. Range = sizeof(DBHEADER) ;
  655.  
  656. GetDate(&day, &month, &year) ;
  657. dbdata[curdb].updatey = year ;
  658. dbdata[curdb].updatem = month;
  659. dbdata[curdb].updated = day;
  660.  
  661. if(Lock(Offset, Range, LOCK))
  662.     rc = DB_UPDATE_ERR ;
  663. else if (Seek(0L))
  664.     rc = DB_UPDATE_ERR ;
  665. else if(Read(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER) ) )
  666.     rc = DB_UPDATE_ERR ;
  667. else
  668.     {
  669.     dbdata[curdb].maxrec += direction ;
  670.     if (Seek(0L))
  671.         rc = DB_UPDATE_ERR ;
  672.     else if(Write(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER)) )
  673.         rc = DB_UPDATE_ERR ;
  674.     }
  675.  
  676. Lock(Offset, Range, UNLOCK) ;
  677. return rc ;
  678. }
  679.  
  680.  
  681. SHORT RefressDBheader(VOID)
  682. {
  683. SHORT rc = OK ;
  684.  
  685. if (Seek(0L))
  686.     rc = DB_UPDATE_ERR ;
  687. else if(Read(dbptr[curdb], &dbdata[curdb], sizeof(DBHEADER) ) )
  688.     rc = DB_UPDATE_ERR ;
  689. return rc ;
  690. }
  691.  
  692.  
  693.  
  694. SHORT RecordWrite(CHAR *record, LONG recnum)
  695. {
  696. SHORT rc = OK ;
  697.  
  698. if(RecordSeek(recnum) == 0 )
  699.     rc = DB_SEEK_ERR ;
  700. else if (Write(dbptr[curdb], record, RECLNGTH))
  701.     rc = DB_WRITE_ERR ;
  702. return rc ;
  703. }
  704.  
  705. SHORT RecordRead(CHAR *record, LONG recnum)
  706. {
  707. SHORT rc = OK ;
  708.  
  709. if(RecordSeek(recnum) == 0)
  710.     rc = DB_SEEK_ERR ;
  711. else if (Read(dbptr[curdb], record, RECLNGTH))
  712.     rc = DB_READ_ERR ;
  713. return rc ;
  714. }
  715.  
  716. SHORT FieldDecimal(SHORT fldnum)
  717. {
  718. FLDHEADER *fldinfo ;
  719.  
  720. if(fldnum >= fldcnt[curdb])
  721.     return DB_INVALID_FIELD ;
  722. fldinfo = (FLDHEADER *) fieldinfo[curdb] ;
  723. return(fldinfo[fldnum].decimal) ;
  724. }
  725.  
  726.  
  727. SHORT FieldType(SHORT fldnum)
  728. {
  729. FLDHEADER *fldinfo ;
  730.  
  731. if(fldnum >= fldcnt[curdb])
  732.     return DB_INVALID_FIELD ;
  733.  
  734. fldinfo = (FLDHEADER *) fieldinfo[curdb] ;
  735. return(fldinfo[fldnum].type) ;
  736. }
  737.  
  738. SHORT FieldOffset(SHORT fldnum)
  739. {
  740. SHORT offset, x;
  741. FLDHEADER *fldinfo ;
  742.  
  743. if(fldnum >= fldcnt[curdb])
  744.     return DB_INVALID_FIELD ;
  745.  
  746. offset = 1 ;
  747. fldinfo = (FLDHEADER *) fieldinfo[curdb] ;
  748. for(x = 0 ;  x < fldnum ; x++)
  749.     offset += fldinfo[x].length ;
  750. return offset ;
  751. }
  752.  
  753. SHORT FieldLength(SHORT fldnum)
  754. {
  755. FLDHEADER *fldinfo ;
  756.  
  757. if(fldnum >= fldcnt[curdb])
  758.     return DB_INVALID_FIELD ;
  759.  
  760. fldinfo = (FLDHEADER *) fieldinfo[curdb] ;
  761. return(fldinfo[fldnum].length) ;
  762. }
  763.  
  764. SHORT FldName2Num(CHAR *name)
  765. {
  766. SHORT x ;
  767. FLDHEADER *fldinfo ;
  768. CHAR fldname[12] ;
  769. strcpy(fldname, strupr(name)) ;
  770.  
  771. fldinfo = (FLDHEADER *) fieldinfo[curdb] ;
  772.  
  773. for(x = 0 ; x < fldcnt[curdb] ; x++)
  774.     {
  775.     if(strcmp(fldname, strupr(fldinfo[x].name) ) == 0)
  776.         break ;
  777.     }
  778. if(x >= fldcnt[curdb] )
  779.     x = DB_INVALID_FIELD ;
  780. return x ;
  781. }
  782.  
  783. CHAR *rtrim(CHAR *text)
  784. {
  785. SHORT x ;
  786. x = strlen(text) - 1 ;
  787. while(text[x] == ' ')
  788.     text[x--] = 0 ;
  789. return text ;
  790. }
  791.  
  792. CHAR *ltrim(CHAR *text)
  793. {
  794. SHORT x ;
  795. x = 0 ;
  796. while(text[x] == ' ') x++ ;
  797. return &text[x] ;
  798. }
  799.  
  800. SHORT FormatNumber(SHORT fldnum, CHAR *text)
  801. {
  802. SHORT origlength,
  803.     origright,
  804.     origleft,
  805.     destright,
  806.     destleft,
  807.     destlength,
  808.     pad,
  809.     x ;
  810. CHAR frmttext[20], *period ;
  811.  
  812. destlength = FieldLength(fldnum) ;
  813. destright = FieldDecimal(fldnum) ;
  814. if(destright > 0)
  815.     destright ++ ; /*add for decimal*/
  816. else
  817.     destright = 0 ;
  818. destleft = destlength - destright ;
  819. origlength = strlen(text) ;
  820. if( (period = strchr(text, '.')) != NULL)
  821.     origright = origlength - strcspn(text, ".") ;
  822. else
  823.     origright = 0 ;
  824. origleft = origlength - origright ;
  825. if(origleft > destleft)
  826.     return DB_INVALID_NUM ;
  827. pad = destleft - origleft;
  828.  
  829. /*left pad with spaces and move left side of decimal over*/
  830. for(x = 0 ;  x < pad; x++)
  831.     frmttext[x] = ' ' ;
  832. memcpy(&frmttext[x], text, origleft) ;
  833.  
  834. if(destright > 0)
  835.     {
  836.     frmttext[destleft] = '.' ;
  837.     if(origright > 0)
  838.         memcpy(&frmttext[destleft + 1], period + 1, min(destright, origright)) ;
  839.     if(destright > origright)
  840.         {
  841.         for(x = destleft + origright + 1; x < destlength ; x++)
  842.             frmttext[x] ='0' ;
  843.         }
  844.     }
  845. strcpy(text, frmttext) ;
  846. return OK ;
  847. }
  848.  
  849.  
  850. /*
  851.     All functions with OS/2 Calls are located below
  852. */
  853.  
  854. ULONG RecordSeek(LONG recnum)
  855. {
  856. ULONG newpos ;
  857. if(DosSetFilePtr(dbptr[curdb],
  858.                 (LONG) RECSTART + ((LONG) recnum * (LONG) RECLNGTH),
  859.                  FILE_BEGIN, &newpos) )
  860.     newpos = 0 ;
  861. return newpos ;
  862. }
  863.  
  864. VOID *MemAlloc(USHORT size)
  865. {
  866. VOID *ptr ;
  867. ptr = malloc((size_t)size) ;
  868. return ptr ;
  869. }
  870.  
  871. VOID MemFree(VOID *ptr)
  872. {
  873. free(ptr) ;
  874. }
  875.  
  876. SHORT Write(USHORT handle, VOID *data, USHORT length)
  877. {
  878. ULONG written ;
  879. SHORT rc = OK;
  880.  
  881. if(DosWrite(handle, data, length, &written))
  882.     rc = DB_WRITE_ERR ;
  883. else if(written != length)
  884.     rc = DB_WRITE_ERR ;
  885. return rc ;
  886. }
  887.  
  888. SHORT Read(USHORT handle, VOID *data, USHORT length)
  889. {
  890. ULONG read ;
  891. SHORT rc = OK;
  892. APIRET apiret = 0 ;
  893. if((apiret = DosRead(handle, data, length, &read)) != 0)
  894.     rc = DB_READ_ERR ;
  895. else if(read != length)
  896.     rc = DB_READ_ERR ;
  897. return rc ;
  898. }
  899.  
  900. SHORT Seek(LONG distance)
  901. {
  902. ULONG newpos ;
  903. SHORT rc = OK ;
  904. APIRET apiret = 0 ;
  905. if((apiret = DosSetFilePtr(dbptr[curdb], distance, FILE_BEGIN, &newpos) ) != 0)
  906.     rc = DB_SEEK_ERR ;
  907. return rc ;
  908. }
  909.  
  910. SHORT FileSize(VOID)
  911. {
  912. ULONG size ;
  913. APIRET rc ;
  914. if((rc = DosSetFilePtr(dbptr[curdb], 0L, FILE_END, &size)) != 0)
  915.     size = 0 ;
  916. return size ;
  917. }
  918.  
  919. SHORT Lock(LONG offset, LONG range, BOOL action)
  920. {
  921. FILELOCK flock, flock2 ;
  922. SHORT rc = OK ;
  923.  
  924. flock.lOffset = offset ;
  925. flock.lRange = range ;
  926. flock2.lOffset = 0 ;
  927. flock2.lRange = 0 ;
  928. if(action)
  929.     {
  930.     if(DosSetFileLocks(dbptr[curdb], &flock2, &flock, 2000L, 0L ) != 0)
  931.         rc = DB_LOCK_ERR ;
  932.     }
  933. else
  934.     {
  935.     if(DosSetFileLocks(dbptr[curdb], &flock, &flock2, 2000L, 0L ) != 0)
  936.         rc = DB_UNLOCK_ERR ;
  937.     }
  938.  
  939. return rc ;
  940. }
  941.  
  942. SHORT GetDate(CHAR *day, CHAR *month, CHAR *year)
  943. {
  944. DATETIME dt ;
  945. DosGetDateTime(&dt) ;
  946. *day = dt.day ;
  947. *month = dt.month ;
  948. *year = dt.year - 1900 ;
  949. }
  950.  
  951. VOID Sleep(LONG time)
  952. {
  953. DosSleep((ULONG) time) ;
  954. return ;
  955. }
  956.  
  957. SHORT Close(USHORT handle)
  958. {
  959. if(DosClose((HFILE) handle) )
  960.     return DB_CLOSE_ERR ;
  961. }
  962.  
  963. SHORT Open(CHAR *name, ULONG *handle, USHORT flags, USHORT mode)
  964. {
  965. ULONG action, rc, x ;
  966.  
  967. /*make 3 attempts to open file*/
  968. for(x = 0 ; x < 3 ; x++)
  969.     {
  970.     rc = DosOpen(name, handle, &action, 0L,
  971.                      FILE_NORMAL,
  972.                      flags, mode, 0L) ;
  973.     if(rc == 0)
  974.         break ;
  975.     Sleep(100L) ;
  976.     }
  977.  
  978. if(rc == ERROR_ACCESS_DENIED ||
  979.    rc == ERROR_INVALID_ACCESS)
  980.     return DB_ACCESS_DENIED ;
  981. else if (rc != 0)
  982.     return DB_OPEN_ERR ;
  983. }
  984.