/*
BEGIN DOCUMENTATION

Name: TCM.C					Created: 7/20/83  DTS
					    Last Update:05/22/84

Title: TCM.C: Text collection management system slave task.

Index: text editor, FMS, editor

Abstract: Acquires textual data from a CRT that is being used
    	  concurrently by FMS.  Allows text editing within a
    	  rectangular "window" on the screen.

Usage:	See "TCM.DOC"

Parameters:

Environment: RSX11M V4.0, DECUS C Compiler

See Also:

Description: This task receives commands from the master task
	     and dispatches to the appropriate routine.  It also
	     connects to the master task so that if the caller is
	     aborted this task will exit with an error message.

Example(s):  See "TCM.DOC"

Uses:

Internal: User interface uses Send/Receive to communicate with
	  this program.  This program attaches terminal and
	  executes commands on behalf of user program.  Globals
	  referenced in "TCMPUBLIC.H" and other globals that must
	  be in the root segement are also defined here.

Update History:

END DOCUMENTATION
*/

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

/* #define debug 0 */

/***	External Procedures (not in tcmdefs)    ***/

extern	int vsend();
extern	int vrecv();
extern	int vrecva();
extern	int conect();

/***	Forward references    ***/

extern	char getcmd();
extern	windel();
extern	delwind();
extern	rdastinit();
extern	char inchar();
extern	charpointer getlin();
extern	charpointer wdwrap();


    /* global parameters for this task */

    struct rad50	mastsk;		/* Master task name */
    struct cmdbuff 	srbuf;		/* Fixed Send/Receive buffer */
    struct retbuf	ret;		/* Command/ Return Status */
    struct twindcb 	*twinroot;	/* Pointer to first Window */
    struct twindcb 	*curwin;	/* Pointer to current window */

    /* Parameters for the edit session */

    boolean	wrap = true;		/* Word wrap always on */
    boolean	insert = false;		/* Default to overtype */
    boolean	select = false;		/* Select range not active */
    boolean	tabdisp = false;	/* Tab display is off */
    boolean	coldisp = true;		/* Column display is on */
    boolean	underline = false;	/* Underscore is off */
    boolean	bold = false;		/* Bold face is off */
    boolean	rdonly = false;		/* Display only flag for editor */

    boolean	eddone;			/* Edit complete flag */
    charpointer	selchr;			/* Ptr to selected char */
    int		curline,curcol;		/* Current line & col # on screen */
    int		bufline,bufcol;		/* Current line & col in buffer */
    int		top,bot,rtmar,lfmar;	/* Current margins */
    int		vttype;			/* Video terminal type */
    int		vtlin;			/* Maximum line on terminal */
    int		vtmar = 0;		/* Maximum column on terminal */
    boolean	hdscrl = false;		/* Hardware scrolling flag */
    int		scrlcnt = 0;		/* Number of lines to scroll */
    int		errlvl;			/* Error level during edit session */

    int		count;			/* Temporary Static Variable */
    char	**oldbuf;		/* Place to keep Screen buffer */
    char	temp[MAXLEN];		/* Temporary CRT sequences */

    /* Misc. permanente buffers */

    char	sidebar[sizeof(BOXSIDE)+3];	/* String for side border */
    char	delbuf[MAXLEN] = "";	/* last deleted string */
    char	line[MAXLEN];		/* Current line buffer */
    charpointer	paste;			/* Paste buffer */
    struct	dsplin lin[CRTLIN+1];   /* Display pointers & status */
					/* 0 is current line buffer */

    /* Tabrack, used only by TCMTAB.C */

    char	tabs[CRTLEN+1] = INITTABS;
    int		tabcnt = TABCOUNT;	/* Number of tabs set in INITTABS */




main(argc,argv)
char *argv[];
{

    register 	char cmd;
    register	char *chr;
    register	int i;

    /***    Get parameter sent via spawn    ***/

	iff argc != 2 then
	    error("Error: TCM must be started via TINIT subroutine");
	chr = cpystr(&temp,argv[1]);	/* ASCII task name */
	for(i = strlen(argv[1]); i<6; i++)
	    *chr++ = ' ';
	ascr50(6,&temp,&mastsk);	/* Set rad50 master task name */
	iff conect(&mastsk) < 0 then
	    error("TCM connect error");

    /***    General initialization    ***/

	twinroot = NULL;
	cmd = 'I';

	while (cmd != 'X')
	{
	    switch(cmd)		/* Dispatch to command */
	    {
	    case 'I':	init();		break;	/* TINIT */
	    case 'C':	create();	break;	/* TWINCR */
	    case 'D':	windel();	break;	/* TWINDE */
	    case 'E':	edit();		break;	/* TCOLL */
	    case 'R':	retrieve();	break;	/* TRETRV */
	    case 'F':	winsave();	break;	/* TWINSA */
	    case 'S':	srefresh();	break;	/* TWINRF */
	    case 'K':	txtdel();	break;	/* TXTDEL */
	    case 'T':	txtins();	break;	/* TXTINS */
	    }

	/* Send status to caller & receive next command */

	    cmd = getcmd();

	} /* end while */
} /* end main */


/***	Send current completion status & get new command    ***/

char
getcmd()
{
	iff vsend(&mastsk,&ret,sizeof(ret)) != IS_SUC then
	    error("\nTCM send error dsw = %d.",$dsw);
	count = sizeof(srbuf);
	iff vrecv(&mastsk,&srbuf.cmd,&count) != IS_SUC then
	{
	    iff $dsw == IS_SET then
		error("\nTCM exiting, caller aborted");
	    else
		error("\nTCM receive error, dsw = %d.",$dsw);
	}
	iff count < sizeof(srbuf) then
	    error("\nTCM receive error, bad size");
	return(srbuf.cmd);
}


/***	Find window on chain by name    ***/

struct twindcb *
fndwnd()		/* perhaps should: set curwin & ret.cd (TE_NSW) */
{
    struct twindcb *win;

	for(win = twinroot; win != NULL;win = win->twinptr)
	    iff streq(win->name,srbuf.name) then
		loopexit;
	return(win);	/* Return NULL if not found, else pointer */
}
