home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / CSSRC / TEXTBUF.C < prev    next >
C/C++ Source or Header  |  1990-12-04  |  7KB  |  327 lines

  1. /*
  2.     textbuf.c
  3.  
  4.     % Text Buffer Routines
  5.  
  6.     written by stephen ng.
  7.     rewritten by Joe DeSantis  (who is not afraid of uppercase letters).
  8.     REwritten by John Cooke       (who is not afraid of Joe DeSantis!).
  9.  
  10.     Textbuf is an abstraction used to store and replay text at different
  11.     relative positions.  (an understatement at best!)
  12.  
  13.     C-scape 3.2
  14.     Copyright (c) 1986, 1987, 1988 by Oakland Group, Inc.
  15.     ALL RIGHTS RESERVED.
  16.  
  17.     Revision History:
  18.     ---------------------
  19.     12/11/86 jmd:    Rewrote with new structure.
  20.      1/26/87 jmd:    Removed width restrictions.
  21.      2/11/87 jmd:    Added tb_DrawLine.
  22.      2/19/87 jmd    added draw_ functions to tb_DrawLines.
  23.      2/21/87 jmd    replaced cs_Asserts.
  24.      2/23/87 jmd     fixed bug in tb_realloc().
  25.      3/10/87 jmd    added startcol to tb_DrawLines.
  26.      5/03/87 jmd    changed realloc strategy
  27.      5/05/87 jmd    fixed bug in tb_DrawLines (hz offset)
  28.      7/27/87 jmd    fixed trailing color problem in tb_Puts
  29.      9/09/87 jmd     added NO_PROTO option
  30.     11/15/87 jmd    changed memcpy to memmove
  31.     11/18/87 jmd    changed unsigned's to unsigned int's
  32.      4/10/88 jdc    rewrote it for live text editing
  33.      8/21/88 jmd    added omalloc
  34.     10/06/88 jdc    fixed overwrite mode bug in tb_put
  35.     11/28/88 jmd    removed startsize from tb_Open
  36.     12/03/88 jdc    created tb_setup and put tb_Clear in here
  37.     12/13/88 jdc    removed tb_put to menu_putTB
  38.     12/22/88 jmd    added check for b == NULL in FindLine
  39.  
  40.      5/19/89 jmd    renamed exp to expan to shut up lint
  41.      7/28/89 jdc    fixed tiny block bug (tb_FindLine)
  42.      8/04/89 jdc    refixed tiny block bug (tb_FindLine)
  43.      3/19/90 jdc    added cs_Assert in FindLine
  44.      3/28/90 jmd    ansi-fied
  45.      5/01/90 jdc    removed trailing '\n' requirement
  46.      8/09/90 jdc    added wrap_char
  47.     11/01/90 ted    put (void) in arg list of tb_Open.
  48.     12/03/90 jdc    added NULL check for tb_setup in tb_Open
  49. */
  50.  
  51. #include "textbuf.h"
  52.  
  53. /**** Creators *****/
  54.  
  55. tb_type tb_Open(void)
  56. /*
  57.     effects:    creates a new textbuf.
  58.  
  59.     returns:    the textbuf created.
  60. */
  61. {
  62.     tb_type tb;
  63.  
  64.     if ((tb = (tb_type)omalloc(CSA_TEXTBUF, sizeof(struct tb_struct))) == NULL) {
  65.         return(NULL);
  66.     }
  67.     if (tb_setup(tb) == NULL) {
  68.         ofree(CSA_TEXTBUF, (VOID *) tb);
  69.         return(NULL);
  70.     }
  71.  
  72.     tb->width = 32000;
  73.     tb->limit = FALSE;
  74.     tb->insert = TED_OVERWRITE;
  75.     tb->refresh = TRUE;
  76.     tb->newline_char = ' ';
  77.     tb->tab_char = ' ';
  78.     tb->tab_size = 4;
  79.     tb->wrap_char = ' ';
  80.  
  81.     return(tb);
  82. }
  83.  
  84. tb_type tb_setup(tb_type tb)
  85. {
  86.     if ((tb->bbc = bbc_Open(1, TB_BSIZE, TB_ASIZE)) == NULL) {
  87.         return(NULL);
  88.     }
  89.     bbc_Set(tb->bbc, 0L, '\n', 1L, FALSE);
  90.  
  91.     tb->offset = tb->cursor = 0L;
  92.     tb->bbc->b->row = tb->col = tb->xcol = 0;
  93.     tb->len = tb->exp_len = 0;
  94.     tb->nend = TRUE;
  95.     tb->size = 1L;
  96.     tb->cursor_set = TRUE;
  97.     tb->mark = TED_NOMARK;
  98.     tb->buf_type = TED_NOMARK;
  99.     tb->m_stop = FALSE;
  100.  
  101.     return(tb);
  102. }
  103.  
  104. /**** Observers *****/
  105.  
  106. boolean tb_Ok(tb_type textbuf)
  107. /*
  108.     effects:    checks to see if a textbuf is ok.
  109.  
  110.     returns:    TRUE if she is, FALSE if she ain't.
  111. */
  112. {
  113.     return(textbuf != NULL);
  114. }
  115.  
  116. int tb_GetRow(tb_type tb)
  117. {
  118.     return((int)tb->bbc->b->row);
  119. }
  120.  
  121. unsigned int tb_GetCursor(tb_type tb)
  122. {
  123.     return((unsigned int)(tb->cursor - tb->offset));
  124. }
  125.  
  126. int tb_FindLine(tb_type tb, int line)
  127. /*
  128.     effects:    Finds a line of text in the text buffer.
  129.                 Sets hints for previous bblocks as it searches forward.
  130.                 Sets line length hints for found line.
  131.  
  132.     returns:    TRUE if the line is found.
  133.                 -(last row) if not found.
  134. */
  135. {
  136.     int i, width, s_col, row, back, off;
  137.     char *t;
  138.     long space, offset;
  139.     bblock_type b;
  140.  
  141.     b = tb->bbc->b;
  142.     offset = tb->offset;
  143.  
  144.     /* find the closest prev bblock */
  145.     while ( (long)line < b->row || b->row == -1L ) {
  146.  
  147.         if ( b->prev == NULL ) {                /* no prev, set to line = 0 */
  148.             b->off = 0;
  149.             b->row = 0L;
  150.             offset = 0;
  151.             break;
  152.         }
  153.         else {                                    /* back up to earlier hints */
  154.             if (b->row == -1L) {
  155.                 offset -= b->len;
  156.             }
  157.             else {
  158.                 offset -= b->off;
  159.             }
  160.             if ((b = b->prev)->row != -1L) {
  161.                 offset -= b->len - b->off;
  162.             }
  163.         }
  164.     }
  165.     tb->bbc->b = b;
  166.     t = b->start;
  167.     tb->offset = offset;
  168.     row = (int)b->row;
  169.     width = tb->width;
  170.  
  171.     for ( off = b->off; line >= row; ) {
  172.         /* if == search once more to set length hints */
  173.  
  174.         space = -1L;
  175.         i = 0;
  176.         tb->nend = FALSE;
  177.         while ( TRUE ) {
  178.  
  179.             if ( t[off] == ' ' || t[off] == '\t' || t[off] == tb->wrap_char ) {
  180.                 if ( i >= width + WRAP_CUTOFF ) {
  181.                     space = -1L;
  182.                     break;
  183.                 }
  184.                 i += tb_translate(tb, i, &t[off]);
  185.                 offset++;
  186.                 space = offset;
  187.                 s_col = i;
  188.             }
  189.             else if ( t[off] == '\n' ) {
  190.                 i++;
  191.                 offset++;
  192.                 off++;
  193.                 tb->nend = TRUE;
  194.                 space = -1L;
  195.                 break;
  196.             }
  197.             else if ( i >= width ) {
  198.                 break;
  199.             }
  200.             else {
  201.                 i++;
  202.                 offset++;
  203.             }
  204.             off++;
  205.             if ( off >= b->len ) {
  206.                 if ((b = b->next) == NULL) {
  207.  
  208.                     i++;
  209.                     offset++;
  210.                     off++;
  211.                     tb->nend = TRUE;
  212.                     space = -1L;
  213.                     break;
  214.                 }
  215.                 else {
  216. /*                    cs_Assert((b = b->next) != NULL, CS_TB_FL_BBC666, 0);*/
  217.                     t = b->start;
  218.                     b->row = -1L;
  219.                     off = 0;
  220.                 }
  221.  
  222.             }
  223.         }
  224.         if ( space != -1L ) {
  225.             back = (int)(offset - space);                    /* walk back bblocks */
  226.             while ( back > off ) {
  227.                 back -= (off + 1);
  228.                 b = b->prev;
  229.                 off = b->len - 1;
  230.             }
  231.             t = b->start;
  232.             off -= back;
  233.             offset = space;
  234.             i = s_col;
  235.         }
  236.         else if (b != NULL &&  off >= b->len) {
  237.             b = b->next;
  238.             if (b != NULL) {
  239.                 t = b->start;    
  240.                 b->row = -1L;
  241.             }
  242.             off = 0;
  243.         }
  244.         tb->len = (unsigned int)(offset - tb->offset);     /* length hints */
  245.         tb->exp_len = i;
  246.  
  247.         if (line == row) {
  248.             return(TRUE);
  249.         }
  250.         else if ( b == NULL ) {
  251.             return(-(int)(tb->bbc->b->row));
  252.         }
  253.  
  254.         b->off = off;                                    /* position hints */
  255.         b->row = ++row;
  256.         tb->bbc->b = b;
  257.         tb->offset = offset;
  258.     }
  259.     return(TRUE);
  260. }
  261.  
  262. int tb_FindPosition(tb_type tb, int row, int col)
  263. /*
  264.     places cursor hints for displayed row, col.
  265. */
  266. {
  267.     unsigned int expan, i, lcol;
  268.     bbpeek_struct bp;
  269.     int endrow, dlen;
  270.              
  271.     tb->cursor_set = TRUE;
  272.  
  273.     if ( (endrow = tb_FindLine(tb, row)) == TRUE ) {
  274.         bp.len = tb->cursor - tb->offset;
  275.         if ( bp.len < 0 || bp.len >= (long)tb->len || col < tb->col ) {
  276.             tb->cursor = tb->offset;
  277.             tb->col = 0;
  278.         }    
  279.         else if ( col == tb->col ) {
  280.             return(TRUE);
  281.         }
  282.     }
  283.     if ( endrow <= 0 || col >= tb->exp_len ) {
  284.         /* put tb cursor on last char */
  285.         tb->cursor = tb->offset + tb->len - 1;
  286.         tb->col = tb->exp_len - 1;
  287.         tb->cursor_set = FALSE;
  288.         return(FALSE);
  289.     }
  290.     else if ( col != tb->col ) {
  291.         bp.b = tb->bbc->b;
  292.         bp.off = bp.b->off + tb_GetCursor(tb);
  293.         bp.len = (long)tb->len;
  294.  
  295.         expan = lcol = tb->col;
  296.         do {
  297.             for ( dlen = bbpeek(&bp), i = 0; i < dlen; i++ ) {
  298.  
  299.                 if ( (expan += tb_translate(tb, lcol, bp.p + i)) > col ) {
  300.                     tb->cursor += i;
  301.                     tb->col = lcol;
  302.                     return(TRUE);
  303.                 }
  304.                 lcol = expan;
  305.             }
  306.             tb->cursor += i;
  307.             bp.off += dlen;
  308.             bp.len -= (long)dlen;    
  309.  
  310.         } while( dlen > 0 );
  311.     }
  312.     return(TRUE);
  313. }
  314.  
  315. /**** Destructors *****/
  316.  
  317. void tb_Close(tb_type tb)
  318. /*
  319.     effects:    destroys a textbuf so it can never be used again.
  320. */
  321. {
  322.     cs_Assert(tb_Ok(tb), CS_TB_C_TB, 0);
  323.  
  324.     bbc_Close(tb->bbc);
  325.     ofree(CSA_TEXTBUF, (VOID *) tb);
  326. }
  327.