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