void privchat(void)
{
	uchar	str[128],ch,c,*p;
	int 	in,out,i,j,n,done,echo=1,x,y;
	node_t	node;

n=getnodetopage(0,0);
if(!n)
	return;
if(n==node_num) {
	bputs(text[NoNeedToPageSelf]);
	return; }
getnodedat(n,&node,0);
if(node.action==NODE_PCHT && node.aux!=node_num) {
	bprintf(text[NodeNAlreadyInPChat],n);
	return; }
if((node.action!=NODE_PAGE || node.aux!=node_num)
	&& node.misc&NODE_POFF && !SYSOP) {
	bprintf(text[CantPageNode],node.misc&NODE_ANON
		? text[UNKNOWN_USER] : username(node.useron,tmp));
	return; }
if(node.action!=NODE_PAGE) {
	bprintf("\r\n\1n\1mPaging \1h%s #%u\1n\1m for private chat\r\n"
		,username(node.useron,tmp),node.useron);
	sprintf(str,text[NodePChatPageMsg]
		,node_num,thisnode.misc&NODE_ANON
			? text[UNKNOWN_USER] : useron.alias);
	putnmsg(n,str);
	sprintf(str,"Paged %s on node %d to private chat"
		,username(node.useron,tmp),n);
	logline("C",str); }

getnodedat(node_num,&thisnode,1);
thisnode.action=action=NODE_PAGE;
thisnode.aux=n;
putnodedat(node_num,thisnode);

if(node.action!=NODE_PAGE || node.aux!=node_num) {
	bprintf(text[WaitingForNodeInPChat],n);
	while(online && !(sys_status&SS_ABORT)) {
		getnodedat(n,&node,0);
		if((node.action==NODE_PAGE || node.action==NODE_PCHT)
			&& node.aux==node_num) {
			bprintf(text[NodeJoinedPrivateChat]
				,n,username(node.useron,tmp));
			break; }
		if(!inkey(0))
			mswait(1);
		action=NODE_PAGE;
		checkline();
		gettimeleft();
		SYNC; } }

getnodedat(node_num,&thisnode,1);
thisnode.action=action=NODE_PCHT;
putnodedat(node_num,thisnode);

if(!online || sys_status&SS_ABORT)
	return;

if(!(useron.misc&EXPERT))
	menu("PRIVCHAT");
bputs(text[WelcomeToPrivateChat]);

sprintf(str,"%sCHAT.DAB",node_dir);
if((out=open(str,O_RDWR|O_DENYNONE|O_CREAT|O_BINARY
	,S_IREAD|S_IWRITE))==-1) {
	errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE|O_CREAT);
	return; }

sprintf(str,"%sCHAT.DAB",node_path[n-1]);
if(!fexist(str))		/* Wait while it's created for the first time */
	mswait(2000);
if((in=open(str,O_RDWR|O_DENYNONE|O_CREAT|O_BINARY
	,S_IREAD|S_IWRITE))==-1) {
	close(out);
	errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE|O_CREAT);
	return; }

if((p=(char *)MALLOC(PCHAT_LEN))==NULL) {
	close(in);
	close(out);
	errormsg(WHERE,ERR_ALLOC,str,PCHAT_LEN);
	return; }
memset(p,0,PCHAT_LEN);
write(in,p,PCHAT_LEN);
write(out,p,PCHAT_LEN);
FREE(p);
lseek(in,0L,SEEK_SET);
lseek(out,0L,SEEK_SET);

getnodedat(node_num,&thisnode,1);
thisnode.misc&=~NODE_RPCHT; 		/* Clear "reset pchat flag" */
putnodedat(node_num,thisnode);

getnodedat(n,&node,1);
node.misc|=NODE_RPCHT;				/* Set "reset pchat flag" */
putnodedat(n,node); 				/* on other node */

									/* Wait for other node */
									/* to acknowledge and reset */
while(online && !(sys_status&SS_ABORT)) {
	getnodedat(n,&node,0);
	if(!(node.misc&NODE_RPCHT))
		break;
	getnodedat(node_num,&thisnode,0);
	if(thisnode.misc&NODE_RPCHT)
		break;
	checkline();
	gettimeleft();
	SYNC;
	inkey(0);
	mswait(1); }

i=0;
done=0;

/***
x=lclwx();
y=lclwy();
GOTOXY(1,13);
ANSI_SAVE();
GOTOXY(x,y);
***/

while(online && !(sys_status&SS_ABORT) && !done) {
	lncntr=0;

	action=NODE_PCHT;
	if(!i) {
		attr(LIGHTGRAY);
		SYNC; }
	if((ch=inkey(K_GETSTR))!=0) {
		if(echo) {
			attr(color[clr_chatlocal]);
			/*
			ANSI_SAVE();
			GOTOXY(x,y);
			*/
			}
		else
			lclatr(color[clr_chatlocal]);
		if(ch==CR) {
			if(echo) {
				CRLF; }
			else
				lputs(crlf);
			i=0; }
		else if(ch==BS) {
			if(i) {
				if(echo)
					bputs("\b \b");
				else
					lputs("\b \b");
				i--; } }
		else if(ch==TAB) {
			if(echo)
				outchar(SP);
			else
				lputc(SP);
			i++;
			while(i<78 && i%8) {
				if(echo)
					outchar(SP);
				else
					lputc(SP);
				i++; } }
		else if(ch>=SP) {
			if(ch=='/' && !i) {
				bputs(text[MultiChatCommandPrompt]);
				ch=getkeys("?QEL@",0);
				switch(ch) {
					case '@':
						bprintf("in:%lu\r\nout:%lu\r\n"
							,tell(in),tell(out));
						break;
					case '?':
						menu("PRIVCHAT");
						break;
					case 'Q':
						lncntr=0;
						done=1;
						break;
					case 'E':   /* toggle echo */
						echo=!echo;
						bprintf(text[EchoIsNow]
							,echo ? text[ON]:text[OFF]);
						break;
					case 'L':   /* list nodes */
						CRLF;
						for(j=1;j<=sys_nodes && j<=sys_lastnode
							;j++) {
							getnodedat(j,&node,0);
							printnodedat(j,node); }
						CRLF;
						break; }
				/***
				x=lclwx();
				y=lclwy();
				ANSI_RESTORE();
				***/
				continue; }
			if(echo)
				outchar(ch);
			else
				lputc(ch);
			if((i>70 && ch==SP) || ++i>78) {
				if(echo) {
					CRLF; }
				else
					lputs(crlf);
				SYNC;
				i=0; } }

		read(out,&c,1);
		lseek(out,-1L,SEEK_CUR);
		if(!c)		/* hasn't wrapped */
			write(out,&ch,1);
		else {
			if(!tell(out))
				lseek(out,0L,SEEK_END);
			lseek(out,-1L,SEEK_CUR);
			ch=0;
			write(out,&ch,1);
			lseek(out,-1L,SEEK_CUR); }
		if(tell(out)>=PCHAT_LEN)
			lseek(out,0L,SEEK_SET);
		/***
		x=lclwx();
		y=lclwy();
		ANSI_RESTORE();
		***/
		}
	else {
		if(tell(in)>=PCHAT_LEN)
			lseek(in,0L,SEEK_SET);
		ch=0;
		read(in,&ch,1);
		lseek(in,-1L,SEEK_CUR);
		if(ch) {								/* char from other node */
			/*
			ANSI_RESTORE();
			*/
			attr(color[clr_chatremote]);
			if(ch==CR) {
				CRLF;
				i=0; }
			else if(ch==BS) {
				if(i) {
					bputs("\b \b");
					i--; } }
			else if(ch==TAB) {
				outchar(SP);
				i++;
				while(i<78 && i%8) {
					outchar(SP);
					i++; } }
			else if(ch>=SP) {
				outchar(ch);
				if((i>68 && ch==SP) || ++i>78) {
					CRLF;
					SYNC;
					i=0; } }
			ch=0;
			write(in,&ch,1);
			/*
			ANSI_SAVE();
			*/ }
		else {									/* no action so chk node.dab */
			getnodedat(n,&node,0);
			if((node.action!=NODE_PCHT && node.action!=NODE_PAGE)
				|| node.aux!=node_num) {
				bprintf(text[NodeLeftPrivateChat]
					,n,username(node.useron,tmp));
				break; }
			getnodedat(node_num,&thisnode,0);
			if(thisnode.misc&NODE_RPCHT) {		/* pchat has been reset */
				lseek(in,0L,SEEK_SET);			/* so seek to beginning */
				lseek(out,0L,SEEK_SET);
				getnodedat(node_num,&thisnode,1);
				thisnode.misc&=~NODE_RPCHT;
				putnodedat(node_num,thisnode); }
			mswait(0); } }
	checkline();
	gettimeleft(); }
close(in);
close(out);
}
