home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c185 / 2.ddi / OWLSRC.EXE / CSCAPE / SOURCE / BBCHAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-11  |  9.7 KB  |  513 lines

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