home *** CD-ROM | disk | FTP | other *** search
- /*
- textbuf.c
-
- % Text Buffer Routines
-
- written by stephen ng.
- rewritten by Joe DeSantis (who is not afraid of uppercase letters).
- REwritten by John Cooke (who is not afraid of Joe DeSantis!).
-
- Textbuf is an abstraction used to store and replay text at different
- relative positions. (an understatement at best!)
-
- C-scape 3.2
- Copyright (c) 1986, 1987, 1988 by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- ---------------------
- 12/11/86 jmd: Rewrote with new structure.
- 1/26/87 jmd: Removed width restrictions.
- 2/11/87 jmd: Added tb_DrawLine.
- 2/19/87 jmd added draw_ functions to tb_DrawLines.
- 2/21/87 jmd replaced cs_Asserts.
- 2/23/87 jmd fixed bug in tb_realloc().
- 3/10/87 jmd added startcol to tb_DrawLines.
- 5/03/87 jmd changed realloc strategy
- 5/05/87 jmd fixed bug in tb_DrawLines (hz offset)
- 7/27/87 jmd fixed trailing color problem in tb_Puts
- 9/09/87 jmd added NO_PROTO option
- 11/15/87 jmd changed memcpy to memmove
- 11/18/87 jmd changed unsigned's to unsigned int's
- 4/10/88 jdc rewrote it for live text editing
- 8/21/88 jmd added omalloc
- 10/06/88 jdc fixed overwrite mode bug in tb_put
- 11/28/88 jmd removed startsize from tb_Open
- 12/03/88 jdc created tb_setup and put tb_Clear in here
- 12/13/88 jdc removed tb_put to menu_putTB
- 12/22/88 jmd added check for b == NULL in FindLine
-
- 5/19/89 jmd renamed exp to expan to shut up lint
- 7/28/89 jdc fixed tiny block bug (tb_FindLine)
- 8/04/89 jdc refixed tiny block bug (tb_FindLine)
- 3/19/90 jdc added cs_Assert in FindLine
- 3/28/90 jmd ansi-fied
- 5/01/90 jdc removed trailing '\n' requirement
- 8/09/90 jdc added wrap_char
- 11/01/90 ted put (void) in arg list of tb_Open.
- 12/03/90 jdc added NULL check for tb_setup in tb_Open
- */
-
- #include "textbuf.h"
-
- /**** Creators *****/
-
- tb_type tb_Open(void)
- /*
- effects: creates a new textbuf.
-
- returns: the textbuf created.
- */
- {
- tb_type tb;
-
- if ((tb = (tb_type)omalloc(CSA_TEXTBUF, sizeof(struct tb_struct))) == NULL) {
- return(NULL);
- }
- if (tb_setup(tb) == NULL) {
- ofree(CSA_TEXTBUF, (VOID *) tb);
- return(NULL);
- }
-
- tb->width = 32000;
- tb->limit = FALSE;
- tb->insert = TED_OVERWRITE;
- tb->refresh = TRUE;
- tb->newline_char = ' ';
- tb->tab_char = ' ';
- tb->tab_size = 4;
- tb->wrap_char = ' ';
-
- return(tb);
- }
-
- tb_type tb_setup(tb_type tb)
- {
- if ((tb->bbc = bbc_Open(1, TB_BSIZE, TB_ASIZE)) == NULL) {
- return(NULL);
- }
- bbc_Set(tb->bbc, 0L, '\n', 1L, FALSE);
-
- tb->offset = tb->cursor = 0L;
- tb->bbc->b->row = tb->col = tb->xcol = 0;
- tb->len = tb->exp_len = 0;
- tb->nend = TRUE;
- tb->size = 1L;
- tb->cursor_set = TRUE;
- tb->mark = TED_NOMARK;
- tb->buf_type = TED_NOMARK;
- tb->m_stop = FALSE;
-
- return(tb);
- }
-
- /**** Observers *****/
-
- boolean tb_Ok(tb_type textbuf)
- /*
- effects: checks to see if a textbuf is ok.
-
- returns: TRUE if she is, FALSE if she ain't.
- */
- {
- return(textbuf != NULL);
- }
-
- int tb_GetRow(tb_type tb)
- {
- return((int)tb->bbc->b->row);
- }
-
- unsigned int tb_GetCursor(tb_type tb)
- {
- return((unsigned int)(tb->cursor - tb->offset));
- }
-
- int tb_FindLine(tb_type tb, int line)
- /*
- effects: Finds a line of text in the text buffer.
- Sets hints for previous bblocks as it searches forward.
- Sets line length hints for found line.
-
- returns: TRUE if the line is found.
- -(last row) if not found.
- */
- {
- int i, width, s_col, row, back, off;
- char *t;
- long space, offset;
- bblock_type b;
-
- b = tb->bbc->b;
- offset = tb->offset;
-
- /* find the closest prev bblock */
- while ( (long)line < b->row || b->row == -1L ) {
-
- if ( b->prev == NULL ) { /* no prev, set to line = 0 */
- b->off = 0;
- b->row = 0L;
- offset = 0;
- break;
- }
- else { /* back up to earlier hints */
- if (b->row == -1L) {
- offset -= b->len;
- }
- else {
- offset -= b->off;
- }
- if ((b = b->prev)->row != -1L) {
- offset -= b->len - b->off;
- }
- }
- }
- tb->bbc->b = b;
- t = b->start;
- tb->offset = offset;
- row = (int)b->row;
- width = tb->width;
-
- for ( off = b->off; line >= row; ) {
- /* if == search once more to set length hints */
-
- space = -1L;
- i = 0;
- tb->nend = FALSE;
- while ( TRUE ) {
-
- if ( t[off] == ' ' || t[off] == '\t' || t[off] == tb->wrap_char ) {
- if ( i >= width + WRAP_CUTOFF ) {
- space = -1L;
- break;
- }
- i += tb_translate(tb, i, &t[off]);
- offset++;
- space = offset;
- s_col = i;
- }
- else if ( t[off] == '\n' ) {
- i++;
- offset++;
- off++;
- tb->nend = TRUE;
- space = -1L;
- break;
- }
- else if ( i >= width ) {
- break;
- }
- else {
- i++;
- offset++;
- }
- off++;
- if ( off >= b->len ) {
- if ((b = b->next) == NULL) {
-
- i++;
- offset++;
- off++;
- tb->nend = TRUE;
- space = -1L;
- break;
- }
- else {
- /* cs_Assert((b = b->next) != NULL, CS_TB_FL_BBC666, 0);*/
- t = b->start;
- b->row = -1L;
- off = 0;
- }
-
- }
- }
- if ( space != -1L ) {
- back = (int)(offset - space); /* walk back bblocks */
- while ( back > off ) {
- back -= (off + 1);
- b = b->prev;
- off = b->len - 1;
- }
- t = b->start;
- off -= back;
- offset = space;
- i = s_col;
- }
- else if (b != NULL && off >= b->len) {
- b = b->next;
- if (b != NULL) {
- t = b->start;
- b->row = -1L;
- }
- off = 0;
- }
- tb->len = (unsigned int)(offset - tb->offset); /* length hints */
- tb->exp_len = i;
-
- if (line == row) {
- return(TRUE);
- }
- else if ( b == NULL ) {
- return(-(int)(tb->bbc->b->row));
- }
-
- b->off = off; /* position hints */
- b->row = ++row;
- tb->bbc->b = b;
- tb->offset = offset;
- }
- return(TRUE);
- }
-
- int tb_FindPosition(tb_type tb, int row, int col)
- /*
- places cursor hints for displayed row, col.
- */
- {
- unsigned int expan, i, lcol;
- bbpeek_struct bp;
- int endrow, dlen;
-
- tb->cursor_set = TRUE;
-
- if ( (endrow = tb_FindLine(tb, row)) == TRUE ) {
- bp.len = tb->cursor - tb->offset;
- if ( bp.len < 0 || bp.len >= (long)tb->len || col < tb->col ) {
- tb->cursor = tb->offset;
- tb->col = 0;
- }
- else if ( col == tb->col ) {
- return(TRUE);
- }
- }
- if ( endrow <= 0 || col >= tb->exp_len ) {
- /* put tb cursor on last char */
- tb->cursor = tb->offset + tb->len - 1;
- tb->col = tb->exp_len - 1;
- tb->cursor_set = FALSE;
- return(FALSE);
- }
- else if ( col != tb->col ) {
- bp.b = tb->bbc->b;
- bp.off = bp.b->off + tb_GetCursor(tb);
- bp.len = (long)tb->len;
-
- expan = lcol = tb->col;
- do {
- for ( dlen = bbpeek(&bp), i = 0; i < dlen; i++ ) {
-
- if ( (expan += tb_translate(tb, lcol, bp.p + i)) > col ) {
- tb->cursor += i;
- tb->col = lcol;
- return(TRUE);
- }
- lcol = expan;
- }
- tb->cursor += i;
- bp.off += dlen;
- bp.len -= (long)dlen;
-
- } while( dlen > 0 );
- }
- return(TRUE);
- }
-
- /**** Destructors *****/
-
- void tb_Close(tb_type tb)
- /*
- effects: destroys a textbuf so it can never be used again.
- */
- {
- cs_Assert(tb_Ok(tb), CS_TB_C_TB, 0);
-
- bbc_Close(tb->bbc);
- ofree(CSA_TEXTBUF, (VOID *) tb);
- }
-