/*
BEGIN DOCUMENTATION

Name: TCMTINS.C					Created: 05/11/84  DTS
					    Last Update: 05/18/84

Title: Text collection management text insert function.

Index: TCM text editor

Abstract: Implements "TXTINS" function of TCM to add text to an
	  existing "window" on the screen.

Usage:	See "TCM.DOC"

Parameters: srbuf.row & srbuf.col has position to insert text.

Environment: RSX11M V4.0, DECUS C Compiler

See Also: TCM.C, TCMPTXTIN.C, TCMCREATE.C, TCM.DOC

Description: Inserts text at given cursor location into named text window.
	     Calls function to re-display text on screen.

Example(s):  See "TCM.DOC"

Uses:

Internal: Makes room for maximum amount of text at current cursor location
	  receives text or file name from remote task & then closes text
	  buffer.

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"
#include "tcmedopt.h"

/* Forward reference */

extern boolean wrapline();


/***	(TXTINS) Text Insertion: Add text to window buffer    ***/

txtins()
{
    register struct twindcb	*win;
    register int	emptyspc,cnt;
    charpointer		bufptr,oldstart,oldend;
    int			oldbot,oldmax,spacecnt;
    static int		ccount;

	iff (win = fndwnd()) == NULL then
	{
	    ccount = 0;
	    bufptr = line;		/* Point somewhere */
	    ret.cd = TE_NSW;
	}
	else
	{
	    ret.cd = TS_SUC;		/* Default to successful */
	    oldstart = win->bufstart;	/* Save current window buffer state */
	    oldend = win->bufend;
	    oldbot = win->botline;
	    oldmax = win->curmax;
	    cnt = ifx (srbuf.row > 0) thenx srbuf.row elsex win->edlinnum;
	    iff cnt > oldbot then cnt = oldbot;
	    iff win->edlinnum != cnt then
	    {
		win->edline = fndlin(oldstart,oldend,cnt);	/* Point to selected line */
		win->edlinnum = cnt;
	    }
	    win->column = ifx (srbuf.col > 0) and (srbuf.col < win->width) thenx 
		srbuf.col elsex win->width - 1;
	    cnt = virlen(win->edline) + 1;
	    spacecnt = ifx win->column > cnt thenx
		win->column - cnt elsex 0;		/* Count of pad chars */
	    bufptr = virchr(win->edline,win->column - spacecnt); /* Point to insert location */
	    emptyspc = oldend - oldstart;
	    ccount = emptyspc = (emptyspc - oldmax);	/* Room available in buffer */
	    iff (emptyspc > 1) and (bufptr < (oldstart + oldmax)) then
	    {
		cnt = bufptr - oldstart;
		cnt = oldmax - cnt;			/* Char count from bufptr to end */
		moveup(bufptr,bufptr+emptyspc,cnt);	/* Make room in contiguous buffer */
		while ((spacecnt-- > 0) and (emptyspc > 0))
		{
		    *bufptr++ = ' ';			/* Pad line with spaces */
		    emptyspc--;
		    oldmax++;
		}
		ccount = emptyspc;			/* Space still open */
	    }
	    else
	    {
		bufptr = oldstart + oldmax;		/* End of text in buffer */
		emptyspc = ifx oldend > bufptr thenx oldend - bufptr elsex 0;
		cnt = 0;					/* No char move */
	    }
	}
	iff vrecv(&mastsk,bufptr,&ccount) != IS_SUC then	/* Always receive */
	    error("TXTINS: RCV error");
	iff ret.cd == TS_SUC then
	{
	    win->bufend = bufptr + emptyspc;
	    win->botline = 1;
	    iff *bufptr == '@' then
		win->bufstart = bufptr;
	    else
	    {
		win->bufstart = win->edline;		/* Set buffer to opened area */
		ccount += (int) (bufptr - win->edline); /* put current line in buffer */
		oldmax -= (int) (bufptr - win->edline); /* don't chars count twice */
		bufptr = win->edline;
	    }
	    inittext(win,ccount);		/* Initialize new text in buffer */
#ifdef debug
	sprintf(temp,"New text = '%s' empty = %d, new = %d, moved chars = %d",bufptr,emptyspc,ccount,cnt);
	scout(vtlin,1,temp);
	scout(0,0,NULL);
	lin[vtlin].fircol = tempmsg;
#endif
	    ccount = win->curmax - 2;		/* number of new characters */
	    iff (oldmax + ccount) > win->max_chars then
		tcmerr(TS_BFP);			/* Buffer full */
	    else iff (win->botline + oldbot - 1) > win->virt_lines then
		tcmerr(TS_MCP);
	    iff (ret.cd == TS_SUC) then		/* Count new text */
	    {
		iff wrapline(&(win->edline),win->width) then	/* Test for line wrap */
    		    win->botline++;
		win->edline = fndlin(win->edline,win->bufend,win->botline);
		ret.bcol = win->column = virlen(win->edline) + 1;
		iff cnt > 0 then
		    movedn(win->bufend, bufptr+ccount, cnt);	/* Close buffer */
		win->edlinnum += (win->botline - 1);		/* End of insert */
		bufptr = win->edline;
		iff wrapline(&bufptr,win->width) then		/* Test for line wrap */
    		    win->botline++;
		win->botline += (oldbot - 1);
		win->curmax = oldmax + ccount;
	    }
	    else				/* restore entire buffer, undo insert */
	    {
		win->botline = oldbot;
		win->curmax = oldmax;
		ret.bcol = win->column;
		iff cnt > 0 then
		    movedn(win->bufend,bufptr,cnt);
	    }
	    ret.bline = win->edlinnum;
	    win->bufstart = oldstart;		/* Restore buffer pointers   */
	    win->bufend = oldend;
	}
	iff ret.cd == TS_SUC then		/* add iniout() ?	     */
	{
	    lin[curline].fircol = newlin;
	    setout(win);
	}
	iff ret.cd == TS_SUC then
	{
	    lin[curline].fircol = newlin;	/* Redisplay current line    */
	    refresh();				/* Display window changes    */
	    rstout(win);
	}
} /* end txtins */


/***	WRAPLINE:  Break line at last space, or right column    ***/



boolean				/* Return true if line wrapped, else false */
wrapline(lptr,lwid)
    register charpointer *lptr;	/* Line pointer, set to 2nd half if line wrapped */
	     int	 lwid;	/* Maximum allowed width */
{
	register charpointer p,sp;

	iff virlen(*lptr) > lwid then
	{						/* Break line	 */
	    sp = virchr(*lptr,lwid);
	    for (p = sp; p > *lptr; p--)
	    {
		iff *p == ' ' then			/* At last space */
		    {sp = p; break;}
	    }
	    *sp++ = eos;
	    *lptr = sp;
	    return(true);
	}
	else
	    return(false);
} /* end wrapline */
