/*
BEGIN DOCUMENTATION

Name: Daniel T. Soldahl				Created: 01/06/84
					    Last Update: 04/23/84
Title: TCMBUF.C - Text collection management text buffer subroutines.

Index:

Abstract: Handles inserting, removing, and managing text window buffer.

Usage:

Parameters:


Environment: DECUS C, RSX11M V4.0

See Also: TCM.C, TCMEDIT.C, TCMEDFUNC.C, TCM.DOC

Description: These routines manipulate the text buffer for the 
	     currently edited window.

Example(s):

Uses:

Internal:   Text for TCM is currently stored as a single string of
	    characters where each line is terminated by a null 
	    character (eos).  The line currently being edited is
	    kept in a fixed character array (line).  Some routines
	    set line pointers into the buffer which are used by the
	    screen refresh routines (see TCMSCRN.C).
	    

Update History:

END DOCUMENTATION
*/

/* #define debug 0 */

#include <clang.c>
#include <stdio.h>
#include <cx.h>
#include "tcmdefs.h"
#include "tcmerr.h"
#include "tcmpublic.h"



/*	Globals affected by these routines only		*/

    int	linevir;	/* Number of displayable characters in current line */
    int	oldlen;		/* Length of edit line when fetched from buffer	*/

/***	FNDLIN: Locate line in buffer by line number    ***/

charpointer
fndlin(buf,bufend,linnum)
    charpointer buf,bufend;
    int linnum;
{
    register charpointer str;
    register int ln;

	for (str=buf,ln=1; (ln<linnum) and (str<bufend); ln++)
	{   /* count from buffer start to current line */
	    while(*str != eos) str++;	/* skip to next string */
	    str++;
	}
	return(str);	/* Return correct line or end of buffer */
} /* end fndlin */


/***	FNDLAST: Locate previous line in buffer    ***/

charpointer
fndlast(cptr,bufst)
    register charpointer cptr;	/* Input: start of current line */
    register charpointer bufst;	/* Input: start of line buffer */
{
	cptr--;
	while(cptr > bufst)
	    iff *(--cptr) == eos then
		{ cptr++; break; }
	return(cptr);		/* Output: start of previous line */
} /* end fndlast */



/***	GETLIN: Get current line from window into global line	***/
/***	buffer.  Return pointer to current char in line.	***/

charpointer
getlin(edline)
    register charpointer edline;
{
    register charpointer last;
    
	last = cpystr(line,edline);	/* Copy current line into fixed buffer */
	lin[0].start = line;
	lin[0].len = oldlen = (last - line) + 1; /* strlen(line) + 1 */
	iff (edline == lin[curline].start) and (oldlen == lin[curline].len) then	/* Assume line on screen */
	{
	    lin[0].fircol = lin[curline].fircol;
	    lin[0].firchr = lin[curline].firchr;
	    lin[0].laschr = lin[curline].laschr;
	}
	else lin[0].fircol = newlin;
	lin[curline].fircol = current;	/* Signal that current line is in lin[0] */
	linevir = virlen(line);
	curwin->curmax -= oldlen;	/* Don't count this line in total */
	return(virchr(line,bufcol));	/* Return current char, Skips enhanced chars */
} /* end getlin */



/***	SAVLIN: Save current line to window from line buffer	***/
/***	Strip spaces from end of line				***/

savlin(win)
    register struct twindcb *win;
{
    register	int	ln;
    		int	ldif;
    register	charpointer src;
    		charpointer txtend;

	src = &line[lin[0].len-1];
	while((--src >= line) and (*src == ' '))
	    lin[0].len--; 			/* Strip spaces from end */
	*(++src) = eos;				/* Mark end of string */
	src = win->edline + oldlen - 1;
#ifdef debug
	iff lin[0].len != strlen(line) + 1 then
	{
	    sprintf(temp,"*SAVLIN* max = %d, stlen = %d, linlen = %d, '%s'",win->curmax,strlen(line),lin[0].len,line);
	    scout(vtlin,1,temp);
	    scout(curline,curcol,NULL);
	    lin[vtlin].fircol = tempmsg;
	}
#endif
	ldif = lin[0].len - oldlen;
	txtend = win->bufstart + win->curmax + oldlen;
	iff ldif < 0 then 			/* Close buffer, new line shorter */
	    movedn(src, src+ldif, txtend - src);
	else iff ldif > 0 then 			/* Open buffer, new line longer */
	    moveup(src, src+ldif, txtend - src);
	lin[curline].start = strcpy(win->edline,line);	/* Copy current line into fixed buffer */
	lin[curline].len = lin[0].len;
	lin[curline].fircol = lin[0].fircol;
	lin[curline].firchr = lin[0].firchr;
	lin[curline].laschr = lin[0].laschr;
	win->curmax += lin[0].len;		/* Add new length into total */
	iff ldif != 0 then	/* adjust screen pointers */
	    for (ln = curline + 1; ln <= bot; ln++)
		lin[ln].start += ldif;
} /* end savlin */



/***	ADDLIN: Add a line worth of text to max count, check for full    ***/

boolean
addlin()
{
    register struct twindcb *win;

	win = curwin;
	iff win->botline >= win->virt_lines then
	{
	    tcmerr(TS_MCI);		/* buffer full */
	    return(false);
	}
	else
	    win->botline++;		/* Count new line in buffer */
	linevir = 0;
	return(true);
} /* end addlin */



/***	ADDCHR: Add character to count for current line    ***/

boolean
addchr()
{
    register struct twindcb *win;

	win = curwin;
	iff win->curmax + lin[0].len >= win->max_chars then
	    tcmerr(TS_BFI);
	else
	{
	    linevir++;
	    lin[0].len++;
	    return(true);
	}
	return(false);
} /* end addchr */



/***	SUBLIN: Subtract a line worth of characters from current window buffer   ***/

sublin()
{
	curwin->botline--;		/* Subtract line from buffer */
} /* end sublin */



/***	SUBCHR: Subtract character count for char on current line    ***/

subchr()
{
	lin[0].len--;
	linevir--;
} /* end subchr */



/***	MOVEUP: Move section of text from low to high, (open buffer)    ***/

moveup(src,dest,cnt)
    register	int	cnt;
    register	char	*dest,*src;
{
	iff cnt > 0 then
	{
	    dest += cnt;		/* Compute end of block */
	    src += cnt;
	    while(cnt--)
		*(--dest) = *(--src);	/* Move last char first */
	}
} /* end moveup */



/***	MOVEDN: Move section of text from high to low, (close buffer)    ***/

movedn(src,dest,cnt)
    register	int	cnt;
    register	char	*dest,*src;
{
	iff cnt > 0 then
	{
	    while(cnt--)
		*dest++ = *src++;	/* Move low memory first */
	}
} /* end movedn */



/***	VIRLEN: Return number of displayable characters in string    ***/

int
virlen(str)
    register charpointer str;
{
	return(strlen(str));	/*** temporary until implemented ***/
} /* end virlen */



/***	VIRCHR: Return pointer to nth displayable character in string    ***/

charpointer
virchr(str,n)
    register charpointer str;
    register int n;
{
	return(str + (n - 1));	/*** temporary until implemented ***/
} /* end virchr */



/***	NXTCHR: Return pointer to next text character (skip enhancements)    ***/

charpointer
nxtchr(chr)
    charpointer chr;
{
	return(++chr);		/*** temporary until enhancements implemented ***/
} /* end nxtchr */



/***	LSTCHR: Return pointer to next text character (skip enhancements)    ***/

charpointer
lstchr(chr)
    charpointer chr;
{
	return(--chr);		/*** temporary until enhancements implemented ***/
} /* end lstchr */
