/*
BEGIN DOCUMENTATION

Name: TCMCREATE.C				Created:  7/20/83  DTS
					    Last Update: 04/23/84

Title: Text collection management system slave task.

Index: TCM text editor

Abstract: Implements "TWINCR" function of TCM to allocate and initialize
	  a rectangular "window" on the screen.

Usage:	See "TCM.DOC"

Parameters:

Environment: RSX11M V4.0, DECUS C Compiler

See Also: TCM.C, TCMPLI.C, TCMSCRN.C, TCM.DOC

Description: Allocates space for tcm window (TWINDCB & buffer) and
	     initializes all parameters in text window control block.
	     Does not call refresh function to display text on screen.

Example(s):  See "TCM.DOC"

Uses:

Internal: Window control blocks are a linked list pointed to by
	  "twindroot" and linked via win.twinptr.  "malloc" and
	  "mfree" are used to allocate & free memory.

Update History:

END DOCUMENTATION
*/

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


/***	(TWINCR) Create Window:  allocate & initialize twindcb & buffer    ***/

create()
{
    register struct twindcb	*wptr;
    register int	siz,i,optn;
    charpointer		bufptr;

	/* allocate window */
	ret.cd = TS_SUC;			/* default to good */
	bufptr = &temp;				/* Point somewhere */
	siz = sizeof(temp) - 1;
	optn = (int) srbuf.opflag;
	iff (optn & BORDER) != 0 then
	{
	    srbuf.height -= 2;	srbuf.width -= 2;
	    srbuf.row += 1;	srbuf.col += 1;
	}
	iff (wptr = fndwnd()) != NULL then	/* replace existing window */
	    mfree(wptr->bufstart);		/* Free up buffer */
	else iff srbuf.height < 1 then
	    ret.cd = TE_BDH;
	else iff srbuf.width < 2 then
	    ret.cd = TE_BDW;
	else iff (wptr = malloc(sizeof(struct twindcb))) != NULL then
	{
	    wptr->twinptr = twinroot;	/* Put new window on list */
	    twinroot = wptr;
	    wptr->fillchr = ' ';	/* Default to blank background */
	}
	else
	    ret.cd = TE_IDS;	/* Insuff. dynamic storage */

	/* Allocate buffer */
	iff ret.cd == TS_SUC then
	{
	    i = ifx srbuf.width <= 0 thenx wptr->width elsex srbuf.width;
	    iff srbuf.max_chars == 0 then
		srbuf.max_chars = srbuf.virt_lines  * (i + 4);	/* End of line + extra for esc sequences */
	    siz = srbuf.max_chars * sizeof(char);
	    iff (bufptr = malloc(siz)) == NULL then
	    {
		bufptr = &temp;
		siz = sizeof(temp) - 1;
		ret.cd = TE_IDS;
		twinroot = wptr->twinptr;	/* Undo window allocation */
		mfree(wptr);
	    }
	    else				/* Set buffer pointer */
		wptr->bufstart = bufptr;
	}

	iff (optn & INITEXT) != 0 then
	{				/* Receive data or file name (always) */
	    count = siz - 2;
	    iff vrecv(&mastsk,bufptr,&count) != IS_SUC then
		error("Receive data error");
	}
	iff ret.cd == TS_SUC then
	{
	    /* Initialize control block */

	    iff (optn & BORDER) != 0 then
		wptr->border = true;
	    else wptr->border = false;
	    iff srbuf.row > 0 then wptr->row = srbuf.row;
	    iff srbuf.col > 0 then wptr->col = srbuf.col;
	    iff srbuf.height > 0 then wptr->height = srbuf.height;
	    iff srbuf.width > 0 then wptr->width = srbuf.width;
	    iff srbuf.virt_lines > 0 then wptr->virt_lines = srbuf.virt_lines;
	    iff srbuf.fillchr != eos then wptr->fillchr = srbuf.fillchr;
	    strcpy(wptr->name,srbuf.name);
    	    wptr->max_chars = srbuf.max_chars;
	    {
		wptr->bufend = wptr->bufstart + siz;
		wptr->edline = wptr->bufstart;
		wptr->column = 1;
		wptr->scroll = (wptr->height * 2) / 3;
		wptr->topline = wptr->botline = 1;
		wptr->edlinnum = 1;
		wptr->curmax = 2;
		iff (optn & INITEXT) != 0 then
		    inittext(wptr,count);
		else
		{
		    *wptr->bufstart++ = eos;	/* Clear buffer */
		    *wptr->bufstart-- = line[0] = eos;
		}
		iff ret.cd == TS_SUC then
		    { iniout(); setout(wptr); }
		iff ret.cd == TS_SUC then
		{
		 
		    refresh();			/* Display (clear) window */
		    rstout(wptr);
		}
		else delwind(wptr);
	    }
	}
} /* end create */


/***	Initialize text buffer with default data    ***/

inittext(win,txtlen)
    register struct twindcb *win;
    int		txtlen;
{
    register	charpointer s;
    register	int slen,linelen,linecnt,maxlen;
    charpointer	spptr;

	s = win->bufstart;
	iff *s++ == '@' then
	{
	    *(s + txtlen - 1) = eos;	/* Mark end of file name */
	    count = (win->bufend - win->bufstart) - 2;	/* Buffer size */
	    ret.cd = tcmget(s,&(win->file),win->bufstart,&count);
	    txtlen = count - 1;		/* Remove last newline */
	}
	iff ret.cd == TS_SUC then
	{
	    win->curmax = txtlen + 2;
	    /* Change <CR> to NULL & mark end */
	    linecnt = linelen = 1;	/* init line count */
	    spptr = NULL;
	    maxlen = win->width;
	    for (slen = 1,s = win->bufstart; slen <= txtlen; slen++, s++) /* s++ should be s = nxtchr(s); for enhancements */
	    {
		iff (*s == '\t') then *s = ' ';	/* Change tabs to spaces */
		iff (*s == ' ') then spptr = s;
		iff (*s == '\r') or (*s == '\n') then *s = eos;
		else iff linelen++ > maxlen then /* Break line if too long */
		{
		    iff spptr != NULL then
		    {
			slen -= (s - spptr);	/* Backup up & */
		        s = spptr;		/* break at word if possible */
		    }
		    *s = eos;		
		}
		iff *s == eos then
		    { linecnt++; linelen = 1; spptr = NULL; }
	    }
	    *s++ = eos; *s = eos;		/* Mark end with extra EOS */
	    win->botline = linecnt;
	    s = fndlast(--s,win->bufstart);	/* Last line in buffer */
	}
	else
	    ret.dsw = $dsw;
} /* end inittext */



/***	(TWINDE) Delete window & free up space    ***/

windel()
{
    register struct twindcb *win;
    register struct twindcb *last;

	ret.cd = TS_SUC;		/* default */
	last = NULL;
	/* Set window from name */
	for(win = twinroot; win != NULL;win = win->twinptr)
	{
	    iff streq(win->name,srbuf.name) then
		loopexit;
	    last = win;
	}
	iff win == NULL then		/* Name not found */
	    ret.cd = TE_NSW;
	else
	{
	    tcmcls(&(win->file));	/* Close associated file if open */
	    iff last == NULL then
		twinroot = win->twinptr; /* remove from list */
	    else
		last->twinptr = win->twinptr;
	    delwind(win);		/* Free up memory */
	}
} /* end windel */


/***	Free memory from deleted text window    ***/

delwind(wptr)
    struct twindcb *wptr;
{
	mfree(wptr->bufstart);		/* Deallocate buffer memory */
	mfree(wptr);			/* Deallocate twindcb */
} /* end delwind */
