#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/subs/pr.c,v 2.11 1995/10/11 03:00:05 empire Exp $";
#endif

/*
 * pr.c
 *
 * The pr routine historically arranged for nonbuffered i/o
 * because stdio didn't used to automatically flush stdout before
 * it read something from stdin.  Now pr() prepends an "output id"
 * in front of each line of text, informing the user interface
 * what sort of item it is seeing; prompt, noecho prompt,
 * more input data, etc.
 *
 * Dave Pare, 1986, 1989
 */

#include <ctype.h>
#include <varargs.h>
#include "proto.h"
#include "misc.h"
#include "player.h"
#include "nat.h"
#include "io.h"
#include "file.h"
#include "com.h"
#include "news.h"
#include "tel.h"
extern	int update_pending;

void outid();

/*VARARGS*/
pr(va_alist)
	va_dcl
{
	s_char	buf[4096];
	s_char	*format;
	va_list	ap;

	va_start(ap);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	pr_player(player, C_DATA, buf);
}

prnf(buf)
	s_char *buf;
{
	pr_player(player, C_DATA, buf);
}

/*VARARGS*/
pr_id(va_alist)
	va_dcl
{
	s_char	buf[4096];
	s_char	*format;
	va_list	ap;
	int	id;
	struct	player *p;

	va_start(ap);
	p = va_arg(ap, struct player *);
	if (p->bol == 0) {
		io_puts(p->iop, "\n");
		p->bol++;
	}
	id = va_arg(ap, int);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	pr_player(p, id, buf);
}

pr_flash(va_alist)
	va_dcl
{
	s_char	buf[4096];
	struct	player *pl;
	s_char	*format;
	va_list	ap;

	va_start(ap);
	pl = va_arg(ap, struct player *);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	pr_player(pl, C_FLASH, buf);
	io_output(pl->iop, IO_NOWAIT);
}

pr_inform(va_alist)
	va_dcl
{
	s_char	buf[4096];
	struct	player *pl;
	s_char	*format;
	va_list	ap;

	va_start(ap);
	pl = va_arg(ap, struct player *);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	pr_player(pl, C_INFORM, buf);
	io_output(pl->iop, IO_NOWAIT);
}

pr_async(va_alist)
	va_dcl
{
	s_char	buf[4096];
	int	cnum;
	struct	player	*pl;
	struct	natstr	*natp;
	s_char	*format;
	va_list	ap;

	va_start(ap);
	cnum = va_arg(ap, int);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);

	if (cnum == player->cnum)
		pl = player;
	else
		pl = getplayer(cnum);

	natp = getnatp(cnum);
	if (!(natp->nat_flags & (cnum==player->cnum?NF_SYNC:NF_ASYNC))) {
		return;
	}
	if (pl) {
		pr_player(pl, C_SYNC, buf);
		io_output(pl->iop, IO_NOWAIT);
	} else
		spool_sync(cnum, buf);
}

pr_sync(va_alist)
	va_dcl
{
	s_char	buf[4096];
	s_char	*format;
	struct	natstr	*natp;
	va_list	ap;

	natp = getnatp(player->cnum);
	if (!(natp->nat_flags & NF_SYNC))
		return;

	va_start(ap);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	pr_player(player, C_SYNC, buf);
	io_output(player->iop, IO_NOWAIT);
}

pr_wall(va_alist)
	va_dcl
{
	s_char	buf[4096];
	struct	player *p;
	s_char	*format;
	va_list	ap;

	va_start(ap);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	for (p = player_next(0); p; p = player_next(p)) {
		if (p->state != PS_PLAYING)
			continue;
		pr_player(p, C_FLASH, buf);
		io_output(p->iop, IO_NOWAIT);
	}
}

pr_player(pl, id, buf)
	struct	player *pl;
	int	id;
	s_char	*buf;
{
	register s_char *p;
	register s_char *bp;
	register int len;

	bp = buf;
	while (*bp != '\0') {
		if (pl->bol) {
			outid(pl, id);
		}
		p = index(bp, '\n');
		if (p != 0) {
			len = (p - bp) + 1;
			if (pl->command && (pl->command->c_flags & C_MOD))
				io_write(pl->iop, bp, len, IO_NOWAIT);
			else
				io_write(pl->iop, bp, len, IO_WAIT);
			bp += len;
			pl->bol++;
		} else {
			len = io_puts(pl->iop, bp);
			bp += len;
		}
	}
}

/*
 * highlighted characters have hex 80 or'ed in
 * with them to designate their highlightedness
 */
pr_hilite(buf)
	s_char *buf;
{
	register s_char *bp;
	register s_char c;
	s_char	*p;

	p = (s_char *)malloc(strlen(buf) + 1);
	strcpy(p, buf);
	for (bp=p; c = *bp; bp++)
		if (isprint(c))
			*bp |= 0x80;
	pr(p);
	free(p);
}

/*
 * output hex code + space
 */
void
outid(pl, n)
	struct	player *pl;
	int	n;
{
	s_char	c;
	s_char	buf[3];

	if (n > C_LAST) {
		logerror("outid: %d not valid code\n", n);
		return;
	}
	if (n >= 10)
		c = 'a' - 10 + n;
	else
		c = '0' + n;
	buf[0] = c;
	buf[1] = ' ';
	buf[2] = '\0';
	io_puts(pl->iop, buf);
	pl->bol = 0;
}

prredir(redir)
	s_char	*redir;
{
	pr_id(player, *redir == '>' ? C_REDIR : C_PIPE, "%s\n", redir);
}

prexec(file)
	s_char	*file;
{
	pr_id(player, C_EXECUTE, "%s\n", file);
}

prprompt(min, btu)
	int	min;
	int	btu;
{
	pr_id(player, C_PROMPT, "%d %d\n", min, btu);
}

showvers(vers)
	int	vers;
{
	pr_id(player, C_INIT, "%d\n", vers);
}

int
prmptrd(prompt, str, size)
	s_char	*prompt;
	s_char	*str;
	int	size;
{
	int	r;

	pr_id(player, C_FLUSH, "%s\n", prompt);
	if ((r = recvclient(str, size)) < 0)
		return r;
	if (*str == 0)
		return 1;
	return strlen(str);
}

prdate()
{
	extern	s_char *ctime();
	long	now;

	(void) time(&now);
	pr(ctime(&now));
}

/*
 * print x,y formatting as country
 */
prxy(format, x, y, country)
	s_char	*format;
	coord	x;
	coord	y;
	natid	country;
{
	s_char	buf[255];
	struct	natstr *np;

	np = getnatp(country);
	sprintf(buf, format, xrel(np, x), yrel(np, y));
	pr(buf);
}

/*VARARGS*/
PR(va_alist)
        va_dcl
{
        /* XXX should really do this on a per-nation basis */
        static s_char longline[MAXNOC][512];
        int     newline;
        va_list ap;
        natid   cn;
        s_char  *format;
        s_char  buf[1024];

        va_start(ap);
        cn = (natid) va_arg(ap, int);
        format = va_arg(ap, s_char *);
        (void) vsprintf(buf, format, ap);
        va_end(ap);
        newline = strrchr(buf, '\n') ? 1 : 0;
        strcat(longline[cn], buf);
        if (newline){
		if (update_pending || cn && cn != player->cnum)
			typed_wu(0, cn, longline[cn], TEL_BULLETIN);
		else
                        pr_player(player, C_DATA, longline[cn]);
                longline[cn][0] = '\0';
        }
}

PRdate(cn)
        natid   cn;
{
        extern  s_char *ctime();
        long    now;

        (void) time(&now);
        PR(cn, ctime(&now));
}

pr_beep()
{
	struct natstr *np = getnatp(player->cnum);

	if (np->nat_flags & NF_BEEP)
		pr("\07");
}

mpr(va_alist)
	va_dcl
{
	natid	cn;
	s_char	buf[4096];
	s_char	*format;
	va_list ap;

	va_start(ap);
	cn = (natid) va_arg(ap, int);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	if (cn)
		if (update_pending || cn != player->cnum)
			typed_wu(0, cn, buf, TEL_BULLETIN);
		else
			pr_player(player, C_DATA, buf);
}
