/*
 * n2.c
 *
 * output, cleanup
 */

#define _BSD_SOURCE 1	/* popen */
#include "tdef.h"
#include "fns.h"
#include "ext.h"
#include <setjmp.h>

#ifdef STRICT
	/* not in ANSI or POSIX */
FILE*	popen(char*, char*);
#endif


extern	jmp_buf	sjbuf;
int	toolate;
int	error;

char	obuf[2*BUFSIZ];
char	*obufp = obuf;

	/* pipe command structure; allows redicously long commends for .pi */
struct Pipe {
	char	*buf;
	int	tick;
	int	cnt;
} Pipe;


int	xon	= 0;	/* records if in middle of \X */

int pchar(Tchar i)
{
	int j;
	static int hx = 0;	/* records if have seen HX */

	if (hx) {
		hx = 0;
		j = absmot(i);
		if (isnmot(i)) {
			if (j > dip->blss)
				dip->blss = j;
		} else {
			if (j > dip->alss)
				dip->alss = j;
			ralss = dip->alss;
		}
		return 0;
	}
	if (ismot(i)) {
		pchar1(i); 
		return 0;
	}
	switch (j = cbits(i)) {
	case 0:
	case IMP:
	case RIGHT:
	case LEFT:
		return 0;
	case HX:
		hx = 1;
		return 0;
	case XON:
		xon++;
		break;
	case XOFF:
		xon--;
		break;
	case PRESC:
		if (!xon && !tflg && dip == &d[0])
			j = eschar;	/* fall through */
	default:
		setcbits(i, trtab[j]);
	}
	if (NROFF & xon)	/* rob fix for man2html */
		return 0;
	pchar1(i);
	return 0;
}


void pchar1(Tchar i)
{
	int j;

	j = cbits(i);
	if (dip != &d[0]) {
		wbf(i);
		dip->op = offset;
		return;
	}
	if (!tflg && !print) {
		if (j == '\n')
			dip->alss = dip->blss = 0;
		return;
	}
	if (j == FILLER && !xon)
		return;
	if (tflg) {	/* transparent mode, undiverted */
		if (print)			/* assumes that it's ok to print */
			/* OUT "%c", j PUT;	/* i.e., is ascii */
			outascii(i);
		return;
	}
	if (TROFF && ascii)
		outascii(i);
	else
		ptout(i);
}


void outweird(int k)	/* like ptchname() but ascii */
{
	char *chn = chname(k);

	switch (chn[0]) {
	case MBchar:
		OUT "%s", chn+1 PUT;	/* \n not needed? */
		break;
	case Number:
		OUT "\\N'%s'", chn+1 PUT;
		break;
	case Troffchar:
		if (strlen(chn+1) == 2)
			OUT "\\(%s", chn+1 PUT;
		else
			OUT "\\C'%s'", chn+1 PUT;
		break;
	default:
		OUT " %s? ", chn PUT;
		break;
	}
}

void outascii(Tchar i)	/* print i in best-guess ascii */
{
	int j = cbits(i);

/* is this ever called with NROFF set? probably doesn't work at all. */

	if (ismot(i))
		oput(' ');
	else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t')
		oput(j);
	else if (j == DRAWFCN)
		oputs("\\D");
	else if (j == HYPHEN)
		oput('-');
	else if (j == MINUS)	/* special pleading for strange encodings */
		oputs("\\-");
	else if (j == PRESC)
		oputs("\\e");
	else if (j == FILLER)
		oputs("\\&");
	else if (j == UNPAD)
		oputs("\\ ");
	else if (j == OHC)	/* this will never occur;  stripped out earlier */
		oputs("\\%");
	else if (j == XON)
		oputs("\\X");
	else if (j == XOFF)
		oputs(" ");
	else if (j == LIG_FI)
		oputs("fi");
	else if (j == LIG_FL)
		oputs("fl");
	else if (j == LIG_FF)
		oputs("ff");
	else if (j == LIG_FFI)
		oputs("ffi");
	else if (j == LIG_FFL)
		oputs("ffl");
	else if (j == WORDSP) {		/* nothing at all */
		if (xon)		/* except in \X */
			oput(' ');

	} else
		outweird(j);
}

int flusho(void)
{
	if (NROFF && !toolate && t.twinit)
			fwrite(t.twinit, strlen(t.twinit), 1, ptid);

	if (obufp > obuf) {
		if (pipeflg && !toolate) {
			/* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */
			if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL)
				ERROR "pipe %s not created.", Pipe.buf WARN;
			if (Pipe.buf)
				free(Pipe.buf);
		}
		if (!toolate)
			toolate++;
		*obufp = 0;
		fputs(obuf, ptid);
		fflush(ptid);
		obufp = obuf;
	}
	return 1;
}


void caseex(void)
{
	done(0);
}


void done(int x) 
{
	int i;

	error |= x;
	app = ds = lgf = 0;
	if (i = em) {
		donef = -1;
		eschar = '\\';
		em = 0;
		if (control(i, 0))
			longjmp(sjbuf, 1);
	}
	if (!nfo)
		done3(0);
	mflg = 0;
	dip = &d[0];
	if (woff)	/* BUG!!! This isn't set anywhere */
		wbf((Tchar)0);
	if (pendw)
		getword(1);
	pendnf = 0;
	if (donef == 1)
		done1(0);
	donef = 1;
	ip = 0;
	frame = stk;
	nxf = frame + 1;
	if (!ejf)
		tbreak();
	nflush++;
	eject((Stack *)0);
	longjmp(sjbuf, 1);
}


void done1(int x) 
{
	error |= x;
	if (numtabp[NL].val) {
		trap = 0;
		eject((Stack *)0);
		longjmp(sjbuf, 1);
	}
	if (!ascii)
		pttrailer();
	done2(0);
}


void done2(int x) 
{
	ptlead();
	if (TROFF && !ascii)
		ptstop();
	flusho();
	done3(x);
}

void done3(int x) 
{
	error |= x;
	flusho();
	if (NROFF)
		twdone();
	if (pipeflg)
		pclose(ptid);
	exit(error);
}


void edone(int x) 
{
	frame = stk;
	nxf = frame + 1;
	ip = 0;
	done(x);
}


void casepi(void)
{
	int j;
	char buf[NTM];

	if (Pipe.buf == NULL) {
		if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) {
			ERROR "No buf space for pipe cmd" WARN;
			return;
		}
		Pipe.tick = 1;
	} else
		Pipe.buf[Pipe.cnt++] = '|';

	getline(buf, NTM);
	j = strlen(buf);
	if (toolate) {
		ERROR "Cannot create pipe to %s", buf WARN;
		return;
	}
	Pipe.cnt += j;
	if (j >= NTM +1) {
		Pipe.tick++;
		if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) {
			ERROR "No more buf space for pipe cmd" WARN;
			return;
		}
	}
	strcat(Pipe.buf, buf);
	pipeflg++;
}
