home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / BBCHAIN.C next >
Encoding:
C/C++ Source or Header  |  1990-06-06  |  10.5 KB  |  556 lines

  1. /*
  2.     bbchain.c  jdc  11/08/88
  3.  
  4.     % block chain routines
  5.  
  6.     OWL 1.2
  7.     Copyright (c) 1988, by Oakland Group, Inc.
  8.     ALL RIGHTS RESERVED.
  9.  
  10.     Revision History:
  11.     -----------------
  12.     12/13/88 jmd    Added casts to orealloc call
  13.      6/14/89 gam    Added some comments
  14.      7/20/89 jdc    Added b->next->row = -1L in bbc_work, offset == 0
  15.  
  16.     11/07/89 jdc    changed > to >= in offset loop for bbc_work
  17.     11/09/89 jdc    fixed that
  18.     11/29/89 jmd    preened, added casts
  19.      3/03/90 jdc    changed char's to byte's
  20.      3/19/90 jdc    fixed b->len == 0 problem?!?
  21.      3/28/90 jmd    ansi-fied
  22.      4/28/90 jdc    tried to fix the realloc failure problem
  23.      5/04/90 jdc    fixed grow error, preened
  24.      6/06/90 jmd/pm    rewrote loop bblock_close to avoid VMS error
  25. */
  26.  
  27. #include "oakhead.h"
  28.  
  29. #include "bbcdecl.h"
  30.  
  31. bbc_type bbc_Open(unsigned int esize, unsigned int bsize, unsigned int asize)
  32. {
  33.     bbc_type bbc;
  34.  
  35.     if ((bbc = (bbc_type) omalloc(OA_BBCHAIN, sizeof(bbc_struct))) == NULL) {
  36.         return(NULL);
  37.     }
  38.     if (bsize % 2 != 0) {
  39.         bsize += 1;
  40.     }
  41.  
  42.     if (asize > bsize) {
  43.         asize = bsize;
  44.     }
  45.     else if (bsize % asize != 0) {
  46.         asize = bsize / 2;
  47.     }
  48.  
  49.     bbc->esize = esize;
  50.     bbc->bsize = bsize * esize;
  51.     bbc->asize = asize * esize;
  52.  
  53.     if ((bbc->b = bblock_open(bbc, (long)bbc->asize, NULL, 0)) == NULL) {
  54.         ofree(OA_BBCHAIN, (VOID *)bbc);
  55.         return(NULL);
  56.     }
  57.     return(bbc);
  58. }        
  59.  
  60. long bbc_work(bbc_type bbc, long offset, char *line, byte chr, long len, int mode)
  61. /*
  62.     if line == NULL then bbset, else bbcpy
  63.  
  64.     'offset' is in ELEMENTS
  65.     'len'     is in ELEMENTS
  66.     'mode'      either BBC_SET, BBC_INSERT, or BBC_GET
  67. */
  68. {
  69.     bblock_type b;
  70.     char *t;
  71.     unsigned int end, i;
  72.     long count = 0L;
  73.  
  74.     if (len <= 0L) {
  75.         return(0L);
  76.     }
  77.  
  78.     len *= bbc->esize;
  79.     offset *= bbc->esize;
  80.  
  81.     b = bbc->b;
  82.     offset += (long)b->off;
  83.  
  84.     while (offset > b->len) {        /* find the block we want */
  85.         if (b->next == NULL) {        /* point the the end */
  86.             break;
  87.         }
  88.         else {
  89.             offset -= b->len;
  90.             b = b->next;
  91.         }
  92.     }
  93.  
  94.     if (mode == BBC_ENDINS) {
  95.         if (offset == b->len && b->next != NULL) {
  96.             /* begin filling in the next block */
  97.  
  98.             offset -= b->len;        
  99.             b = b->next;
  100.         }
  101.         mode = BBC_INSERT;
  102.     }
  103.     else if (mode == BBC_INSERT && offset == 0L && b->prev != NULL
  104.     && b->prev->len + len <= bbc->bsize) {
  105.  
  106.         /* try to back-fill in not an implict ENDINS */
  107.  
  108.         b = b->prev;
  109.         offset = b->len;
  110.         if (bbc->b == b->next) {
  111.             bbc->b = b;
  112.             b->row = b->next->row;
  113.             b->off = b->len;
  114.             b->next->row = -1L;
  115.         }
  116.     }
  117.  
  118.     if (mode == BBC_INSERT) {
  119.  
  120.         if ((unsigned int)offset == bbc->bsize && b->next != NULL) {
  121.             offset = 0L;
  122.             b = b->next;
  123.         }
  124.         i = b->len + (unsigned int)len;
  125.  
  126.         if (i > bbc->bsize) {
  127.  
  128.             if (bblock_split(bbc, b, offset) == NULL
  129.             ||  bblock_grow(bbc, b, len) == NULL) {
  130.  
  131.                 return(0L);
  132.             }
  133.         }
  134.         else {
  135.             if (i > b->size && bblock_grow(bbc, b, len) == NULL) {
  136.                 return(0L);
  137.             }
  138.             t = b->start + (unsigned int)offset;
  139.             memmove((VOID *) (t + (unsigned int)len), t, b->len - (unsigned int)offset);
  140.             b->len += (unsigned int)len;
  141.         }
  142.     }
  143.  
  144.     while (TRUE) {            /* loop through blocks */
  145.  
  146.         t = b->start;
  147.         i = (unsigned int)offset;
  148.         end = (mode == BBC_INSERT || b->next == NULL) ? b->size : b->len;
  149.         if (end > i + (unsigned int)len) {
  150.             end = i + (unsigned int)len;
  151.         }
  152.  
  153.         if (line == NULL) {
  154.             for (; i < end; i++, count++) {
  155.                 t[i] = chr;
  156.             }
  157.         }
  158.         else if (mode == BBC_GET) {    
  159.             for (; i < end; i++, count++) {
  160.                 line[(unsigned int)count] = t[i];
  161.             }
  162.         }
  163.         else {    /* mode == BBC_SET || BBC_INSERT */
  164.             for (; i < end; i++, count++) {
  165.                 t[i] = line[(unsigned int)count];
  166.             }
  167.         }
  168.  
  169.         if (i > b->len) {
  170.             b->len = i;
  171.         }
  172.  
  173.         len -= (i - offset);
  174.  
  175.         if (len <= 0) {                    /* done*/
  176.             break;
  177.         }
  178.  
  179.         if (b->next == NULL) {
  180.  
  181.             if (mode == BBC_GET) {
  182.                 break;
  183.             }
  184.             if (bblock_grow(bbc, b, len) == NULL) {
  185.                 return(count);
  186.             }
  187.             offset = (long)b->len;
  188.         }
  189.         else {
  190.             b = b->next;
  191.             offset = 0L;
  192.         }
  193.     }
  194.     return(count);
  195. }
  196.  
  197. boolean bbc_Attr(bbc_type bbc, long offset, byte attr, long len)
  198. /*
  199.     'offset' and 'len' are in ELEMENTS
  200. */ 
  201. {
  202.     bblock_type b;
  203.  
  204.     if (len <= 0L) {
  205.         return(TRUE);
  206.     }
  207.  
  208.     len *= bbc->esize;
  209.     offset *= bbc->esize;
  210.  
  211.     b = bbc->b;
  212.     offset += (long)b->off;
  213.  
  214.     while (offset >= b->len) {
  215.         if (b->next == NULL) {
  216.             break;
  217.         }
  218.         else {
  219.             offset -= b->len;
  220.             b = b->next;
  221.         }
  222.     }
  223.  
  224.     if (attr != b->attr && offset > 0) {
  225.         if ((b = bblock_split(bbc, b, offset)) == NULL) {
  226.             return(FALSE);
  227.         }
  228.         if (b->prev->off >= b->prev->len) {
  229.             b->off = b->prev->off - b->prev->len;
  230.             b->row = b->prev->row;
  231.             b->prev->row = -1;
  232.             b->prev->off = 0;
  233.             if (bbc->b == b->prev) {
  234.                 bbc->b = b;
  235.             }
  236.         }
  237.     }
  238.     while (b != NULL && len > 0L) {
  239.         if (b->attr != attr && len < (long)b->len) {
  240.             if (bblock_split(bbc, b, len) == NULL) {
  241.                 return(FALSE);
  242.             }
  243.         }
  244.         b->attr = attr;
  245.         len -= (long)b->len;
  246.         b = b->next;
  247.     }
  248.     return(TRUE);
  249. }
  250.  
  251. long bbc_Del(bbc_type bbc, long offset, long len)
  252. /*
  253.     returns: number of elements deleted
  254.     'offset' and 'len' are in ELEMENTS
  255. */
  256. {
  257.     bblock_type b, f;
  258.     long count;
  259.  
  260.     if (len <= 0L) {
  261.         return(0L);
  262.     }
  263.  
  264.     len *= bbc->esize;
  265.     offset *= bbc->esize;
  266.  
  267.     b = bbc->b;
  268.     offset += (long)b->off;
  269.  
  270.     while (offset >= b->len) {
  271.         if (b->next == NULL) {
  272.             break;
  273.         }
  274.         else {
  275.             offset -= b->len;
  276.             b = b->next;
  277.         }
  278.     }
  279.  
  280.     if (offset > 0) {
  281.         if ((b = bblock_split(bbc, b, offset)) == NULL) {
  282.             return(0L);
  283.         }
  284.         if (b->prev->off >= b->prev->len) {
  285.             b->off = b->prev->off - b->prev->len;
  286.             b->row = b->prev->row;
  287.             b->prev->row = -1;
  288.             b->prev->off = b->prev->len - 1;
  289.             if (bbc->b == b->prev) {
  290.                 bbc->b = b;
  291.             }
  292.         }
  293.     }
  294.     count = 0L;
  295.     while (b != NULL && len > 0) {
  296.         if (len < (long)b->len) {
  297.             if (bblock_split(bbc, b, len) == NULL) {
  298.                 return(0L);
  299.             }
  300.         }
  301.         count += (long)b->len;
  302.         len -= (long)b->len;
  303.  
  304.         if (b->prev == NULL) {
  305.             if (b->next == NULL) {
  306.                 /* don't free the last block */
  307.                 b->len = 0;
  308.                 b->off = 0;
  309.                 b->row = 0L;
  310.                 break;
  311.             }
  312.         }
  313.         else {
  314.               b->prev->next = b->next;
  315.         }
  316.         if (b->next != NULL) {
  317.             b->next->prev = b->prev;
  318.         }
  319.         f = b;
  320.         b = b->next;
  321.         if (f == bbc->b) {
  322.             if (b != NULL) {
  323.                 b->row = f->row;
  324.                 b->off = 0;
  325.                 bbc->b = b;
  326.             }
  327.             else {
  328.                 bbc->b = f->prev;
  329.             }
  330.         }
  331.         ofree(OA_BBDATA, (VOID *)f->start);
  332.         ofree(OA_BBLOCK, (VOID *)f);
  333.     }
  334.     return(count/(long)bbc->esize);
  335. }
  336.  
  337. void bbc_Close(bbc_type bbc)
  338. {
  339.     bbc->b = bblock_rewind(bbc->b);
  340.  
  341.     bblock_close(bbc->b, BBC_BELOW);
  342.  
  343.     ofree(OA_BBCHAIN, (VOID *)bbc);
  344. }
  345.  
  346. bblock_type bblock_open(bbc_type bbc, long size, bblock_type prev, byte attr)
  347. /*
  348. */
  349. {
  350.     bblock_type    b, top;
  351.     long asize;
  352.     int    first = TRUE;
  353.  
  354.     top = prev;
  355.     if (size > 0 && size % bbc->asize > 0) {
  356.         /* grow by muliples of asize */
  357.         asize = (size / bbc->asize + 1) * bbc->asize;
  358.     }
  359.  
  360.     while (size > 0L) {
  361.  
  362.         asize = size;
  363.         if (asize > (long)bbc->bsize) {
  364.             asize = (long)bbc->bsize;
  365.         }
  366.         if ((b = (bblock_type) omalloc(OA_BBLOCK, sizeof(struct bblock_struct))) == NULL) {
  367.             return(NULL);
  368.         }
  369.         if ((b->start = (char *) omalloc(OA_BBDATA, (unsigned int)asize)) == NULL) {
  370.             ofree(OA_BBLOCK, (VOID *)b);
  371.             return(NULL);
  372.         }
  373.         if (first) {
  374.             top = b;
  375.             first = FALSE;
  376.         }
  377.         b->prev = prev;                    /* insert new bblock into chain */
  378.         if (prev == NULL) {
  379.             b->next = NULL;
  380.         }
  381.         else {
  382.             b->next = prev->next;    
  383.             if (prev->next != NULL) {
  384.                 prev->next->prev = b;
  385.             }
  386.             prev->next = b;
  387.         }            
  388.         b->size = (unsigned int)asize;
  389.         b->len = 0;
  390.         b->off = 0;
  391.         b->row = -1L;
  392.         b->attr = attr;
  393.  
  394.         size -= asize;
  395.         prev = b;
  396.     }
  397.     return(top);
  398. }
  399.  
  400. bblock_type bblock_grow(bbc_type bbc, bblock_type b, long size)
  401. /*
  402. */
  403. {
  404.     long asize;
  405.     
  406.     size += b->len;
  407.     if (size <= (long)b->size) {
  408.         return(b);
  409.     }
  410.     
  411.     if (size > b->size) {
  412.  
  413.         asize = size;
  414.         if (asize > (long)bbc->bsize) {
  415.             asize = (long)bbc->bsize;
  416.         }
  417.         else if (asize < (long)bbc->asize) {
  418.             asize = (long)bbc->asize;
  419.         }
  420.         if ((b->start = (char *) orealloc(OA_BBDATA, b->start, (unsigned int)asize)) == NULL) {
  421.             /*  try to recoup, doesn't work!
  422.              *    b->start = (char *) orealloc(OA_BBDATA, b->start, b->size);
  423.              *    let's try something else 
  424.              */
  425.             if (b->next != NULL) {
  426.                 b->next->prev = b->prev;
  427.             }
  428.             if (b->prev != NULL) {
  429.                 b->prev->next = b->next;
  430.             }
  431.             if (bbc->b == b) {
  432.                 bbc->b = (b->prev == NULL) ? b->next:b->prev;
  433.             }
  434.             ofree(OA_BBLOCK, (VOID *)b);
  435.             return(NULL);
  436.         }
  437.         b->size = (unsigned int)asize;
  438.     }
  439.     size -= (long)b->size;
  440.  
  441.     if (bblock_open(bbc, size, b, b->attr) == NULL) {
  442.         return(NULL);
  443.     }
  444.     return(b);
  445. }
  446.  
  447. bblock_type bblock_split(bbc_type bbc, bblock_type top, long offset)
  448. /*
  449. */
  450. {
  451.     bblock_type b;
  452.     struct bblock_struct temp;
  453.     long len;
  454.     int copy;
  455.     
  456.     b = top;
  457.     if ((len = (long)top->len - offset) > 0) {
  458.     
  459.         if ((b = bblock_open(bbc, len, top, top->attr)) == NULL) {
  460.             return(NULL);
  461.         }
  462.         if (offset == 0) {
  463.             /* swap blocks' innards */
  464.             copy = sizeof(struct bblock_struct) - 2*sizeof(bblock_type);
  465.             memcpy((VOID *)&(temp.start),(VOID *)&(b->start), copy);
  466.             memcpy((VOID *)&(b->start),  (VOID *)&(top->start), copy);
  467.             memcpy((VOID *)&(top->start),(VOID *)&(temp.start), copy);
  468.             top->row = b->row;
  469.         }                
  470.         else {
  471.             memcpy((VOID *) b->start, (VOID *) (top->start + (unsigned int)offset), (unsigned int)len);
  472.             b->len = (unsigned int)len;
  473.             top->len = (unsigned int)offset;
  474.         }
  475.     }
  476.     return(b);
  477. }
  478.  
  479. void bblock_close(bblock_type b, int flag)
  480. /* 
  481.     flag ==  BBC_SINGLE: close only b, 
  482.     else BBC_BELOW : close b and below.
  483. */
  484. {
  485.     bblock_type next;
  486.  
  487.     while (b != NULL) {
  488.  
  489.         if (b->next != NULL) {
  490.             b->next->prev = b->prev;
  491.         }
  492.         if (b->prev != NULL) {
  493.             b->prev->next = b->next;
  494.         }
  495.         if (flag == BBC_SINGLE) {
  496.             break;
  497.         }
  498.  
  499.         next = b->next;
  500.         ofree(OA_BBDATA, (VOID *)b->start);
  501.         ofree(OA_BBLOCK, (VOID *)b);
  502.         b = next;
  503.     }
  504. }
  505.  
  506. bblock_type bblock_rewind(bblock_type b)
  507. /* 
  508.     sets b to the first block in its chain
  509. */
  510. {
  511.     while (b->prev != NULL) {
  512.         b = b->prev;
  513.     }
  514.     return(b);
  515. }
  516.  
  517. int bbpeek(bbpeek_type bp)
  518. /* 
  519.     get a peek at strings in blocks
  520.     returns valid ptr length
  521. */
  522. {
  523.     int ret;
  524.     bblock_type b;
  525.  
  526.     b = bp->b;
  527.     while (bp->off < 0) {
  528.         if (b->prev == NULL) {    
  529.             return(0);
  530.         }
  531.         else {
  532.             b = b->prev;
  533.             bp->off += b->len;
  534.         }
  535.     }
  536.     while ((ret = (int)b->len - bp->off) <= 0) {
  537.         if (b->next == NULL) {
  538.             return(0);
  539.         }
  540.         else {
  541.             bp->off -= b->len;
  542.             b = b->next;
  543.         }
  544.     }
  545.     if (bp->len < (long)ret) {
  546.         ret = (int)(bp->len);
  547.     }
  548.  
  549.     bp->p = b->start + bp->off;
  550.     bp->b = b;
  551.  
  552.     return(ret);
  553. }
  554.  
  555.  
  556.