Newer
Older
/* Synchronet real-time chat functions */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#define PCHAT_LEN 1000 /* Size of Private chat file */
const char *weekday[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"
,"Saturday"};
const char *month[]={"January","February","March","April","May","June"
,"July","August","September","October","November","December"};
/****************************************************************************/
/****************************************************************************/
char line[256],str[256],ch,done
,usrs,preusrs,qusrs,*gurubuf=NULL,savch,*p
,pgraph[400],buf[400]
,usr[MAX_NODES],preusr[MAX_NODES],qusr[MAX_NODES];
int file;
long i,j,k,n;
node_t node;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
if(channel<1 || channel>cfg.total_chans)
channel=1;
if(!chan_access(channel-1))
return;
if(useron.misc&(RIP|WIP|HTML) ||!(useron.misc&EXPERT))
menu("multchat");
bputs(text[WelcomeToMultiChat]);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
putnodedat(cfg.node_num,&thisnode);
}
bprintf(text[WelcomeToChannelN],channel,cfg.chan[channel-1]->name);
if(cfg.chan[channel-1]->misc&CHAN_GURU && cfg.chan[channel-1]->guru<cfg.total_gurus
&& chk_ar(cfg.guru[cfg.chan[channel-1]->guru]->ar,&useron,&client)) {
sprintf(str,"%s%s.dat",cfg.ctrl_dir,cfg.guru[cfg.chan[channel-1]->guru]->code);
if((file=nopen(str,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
if((gurubuf=(char *)malloc((size_t)filelength(file)+1))==NULL) {
errormsg(WHERE,ERR_ALLOC,str,(size_t)filelength(file)+1);
(void)read(file,gurubuf,(size_t)filelength(file));
usrs=0;
for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT || node.status!=NODE_INUSE)
continue;
if(node.aux && (node.aux&0xff)!=channel)
continue;
printnodedat(i,&node);
preusrs=usrs;
if(gurubuf)
bprintf(text[NodeInMultiChatLocally]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name,channel);
bputs(text[YoureOnTheAir]);
done=0;
while(online && !done) {
checkline();
gettimeleft();
action=NODE_MCHT;
qusrs=usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| (node.aux && channel && (node.aux&0xff)!=channel))
continue;
if(node.status==NODE_QUIET)
qusr[qusrs++]=(char)i;
else if(node.status==NODE_INUSE)
if(preusrs>usrs) {
if(!usrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
bprintf(text[NodeJoinedMultiChat]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
,channel);
outchar(BEL);
for(i=0;i<preusrs;i++) {
for(j=0;j<usrs;j++)
if(preusr[i]==usr[j])
break;
if(j==usrs) {
getnodedat(preusr[i],&node,0);
if(node.misc&NODE_ANON)
sprintf(str,"%.80s",text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
bprintf(text[NodeLeftMultiChat]
,preusr[i],str,channel);
}
}
else if(preusrs<usrs) {
if(!preusrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
bprintf(text[NodeLeftMultiChat]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
,channel);
outchar(BEL);
for(i=0;i<usrs;i++) {
for(j=0;j<preusrs;j++)
if(usr[i]==preusr[j])
break;
if(j==preusrs) {
getnodedat(usr[i],&node,0);
if(node.misc&NODE_ANON)
sprintf(str,"%.80s",text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
bprintf(text[NodeJoinedMultiChat]
,usr[i],str,channel);
}
}
preusrs=usrs;
for(i=0;i<usrs;i++)
preusr[i]=usr[i];
attr(cfg.color[clr_multichat]);
SYNC;
sys_status&=~SS_ABORT;
if((ch=inkey(K_NONE,250))!=0 || wordwrap[0]) {
if(ch=='/') {
bputs(text[MultiChatCommandPrompt]);
strcpy(str,"ACELWQ?*");
if(SYSOP)
SAFECAT(str,"0");
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
i=getkeys(str,cfg.total_chans);
if(i&0x80000000L) { /* change channel */
savch=(char)(i&~0x80000000L);
if(savch==channel)
continue;
if(!chan_access(savch-1))
continue;
bprintf(text[WelcomeToChannelN]
,savch,cfg.chan[savch-1]->name);
usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| node.status!=NODE_INUSE)
continue;
if(node.aux && (node.aux&0xff)!=savch)
continue;
printnodedat(i,&node);
if(node.aux&0x1f00) { /* password */
bprintf(text[PasswordProtected]
,node.misc&NODE_ANON
? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp));
if(!getstr(str,8,K_UPPER|K_ALPHA|K_LINE))
break;
if(strcmp(str,unpackchatpass(tmp,&node)))
break;
bputs(text[CorrectPassword]);
}
if(i<=cfg.sys_nodes) { /* failed password */
bputs(text[WrongPassword]);
if(cfg.chan[savch-1]->misc&CHAN_GURU
&& cfg.chan[savch-1]->guru<cfg.total_gurus
&& chk_ar(cfg.guru[cfg.chan[savch-1]->guru]->ar,&useron,&client
)) {
sprintf(str,"%s%s.dat",cfg.ctrl_dir
,cfg.guru[cfg.chan[savch-1]->guru]->code);
if((file=nopen(str,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
if((gurubuf=(char *)malloc((size_t)filelength(file)+1))==NULL) {
close(file);
errormsg(WHERE,ERR_ALLOC,str
,(size_t)filelength(file)+1);
(void)read(file,gurubuf,(size_t)filelength(file));
preusrs=usrs;
if(gurubuf)
bprintf(text[NodeInMultiChatLocally]
,cfg.sys_nodes+1
,cfg.guru[cfg.chan[savch-1]->guru]->name
,savch);
channel=savch;
if(!usrs && cfg.chan[savch-1]->misc&CHAN_PW
&& !noyes(text[PasswordProtectChanQ])) {
bputs(text[PasswordPrompt]);
if(getstr(str,8,K_UPPER|K_ALPHA|K_LINE)) {
getnodedat(cfg.node_num,&thisnode,true);
packchatpass(str,&thisnode);
getnodedat(cfg.node_num,&thisnode,true);
thisnode.aux=channel;
}
getnodedat(cfg.node_num,&thisnode,true);
putnodedat(cfg.node_num,&thisnode);
bputs(text[YoureOnTheAir]);
if(cfg.chan[channel-1]->cost
&& !(useron.exempt&FLAG('J')))
subtract_cdt(&cfg,&useron,cfg.chan[channel-1]->cost);
else switch(i) { /* other command */
case '0': /* Global channel */
if(!SYSOP)
break;
usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| node.status!=NODE_INUSE)
continue;
printnodedat(i,&node);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.aux=channel=0;
putnodedat(cfg.node_num,&thisnode);
}
break;
case 'A': /* Action commands */
useron.chat^=CHAT_ACTION;
bprintf("\r\nAction commands are now %s\r\n"
,useron.chat&CHAT_ACTION
? text[ON]:text[OFF]);
putuserchat(useron.number, useron.chat);
break;
case 'C': /* List of action commands */
CRLF;
for(i=0;channel && i<cfg.total_chatacts;i++) {
if(cfg.chatact[i]->actset
!=cfg.chan[channel-1]->actset)
continue;
bprintf("%-*.*s",LEN_CHATACTCMD
,LEN_CHATACTCMD,cfg.chatact[i]->cmd);
if(!((i+1)%8)) {
CRLF;
break;
case 'E': /* Toggle echo */
useron.chat^=CHAT_ECHO;
bprintf(text[EchoIsNow]
,useron.chat&CHAT_ECHO
? text[ON]:text[OFF]);
putuserchat(useron.number, useron.chat);
break;
case 'L': /* list nodes */
CRLF;
for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
CRLF;
break;
case 'W': /* page node(s) */
j=getnodetopage(0,0);
if(!j)
break;
for(i=0;i<usrs;i++)
if(usr[i]==j)
break;
if(i>=usrs) {
bputs(text[UserNotFound]);
bputs(text[NodeMsgPrompt]);
if(!getstr(line,66,K_LINE|K_MSG))
break;
sprintf(buf,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,'*',line);
SAFECAT(buf,crlf);
if(useron.chat&CHAT_ECHO)
bputs(buf);
putnmsg(&cfg,j,buf);
break;
case 'Q': /* quit */
done=1;
break;
case '*':
if(!menu("chan", P_NOERROR)) {
bputs(text[ChatChanLstHdr]);
bputs(text[ChatChanLstTitles]);
if(cfg.total_chans>=10) {
bputs(" ");
bputs(text[ChatChanLstTitles]);
CRLF;
bputs(text[ChatChanLstUnderline]);
if(cfg.total_chans>=10) {
bputs(" ");
bputs(text[ChatChanLstUnderline]);
CRLF;
if(cfg.total_chans>=10)
j=(cfg.total_chans/2)+(cfg.total_chans&1);
else
j=cfg.total_chans;
for(i=0;i<j && !msgabort();i++) {
bprintf(text[ChatChanLstFmt],i+1
,cfg.chan[i]->name
,cfg.chan[i]->cost);
if(cfg.total_chans>=10) {
k=(cfg.total_chans/2)
+i+(cfg.total_chans&1);
if(k<cfg.total_chans) {
bputs(" ");
bprintf(text[ChatChanLstFmt]
,k+1
,cfg.chan[k]->name
,cfg.chan[k]->cost);
}
break;
case '?': /* menu */
menu("multchat");
ungetkey(ch);
j=0;
pgraph[0]=0;
while(j<5) {
if(!getstr(line,66,K_WRAP|K_MSG|K_CHAT))
break;
if(j) {
sprintf(str,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,':',nulstr);
SAFECAT(pgraph,tmp);
SAFECAT(pgraph,line);
SAFECAT(pgraph,crlf);
if(channel && useron.chat&CHAT_ACTION) {
for(i=0;i<cfg.total_chatacts;i++) {
if(cfg.chatact[i]->actset
!=cfg.chan[channel-1]->actset)
continue;
sprintf(str,"%s ",cfg.chatact[i]->cmd);
if(!strnicmp(str,pgraph,strlen(str)))
break;
sprintf(str,"%.*s"
,LEN_CHATACTCMD+2,pgraph);
str[strlen(str)-2]=0;
if(!stricmp(cfg.chatact[i]->cmd,str))
if(i<cfg.total_chatacts) {
p=pgraph+strlen(str);
n=atoi(p);
for(j=0;j<usrs;j++) {
getnodedat(usr[j],&node,0);
if(usrs==1) /* no need to search */
break;
if(n) {
if(usr[j]==n)
break;
username(&cfg,node.useron,str);
if(!strnicmp(str,p,strlen(str)))
break;
getuserstr(&cfg, node.useron, USER_HANDLE, str, sizeof(str));
if(!usrs
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
strcpy(str
,cfg.guru[cfg.chan[channel-1]->guru]->name);
else if(j>=usrs)
strcpy(str,"everyone");
else if(node.misc&NODE_ANON)
strcpy(str,text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
/* Display on same node */
bprintf(cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,str);
CRLF;
if(usrs && j<usrs) {
/* Display to dest user */
sprintf(buf,cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,"you");
SAFECAT(buf,crlf);
putnmsg(&cfg,usr[j],buf);
/* Display to all other users */
sprintf(buf,cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,str);
SAFECAT(buf,crlf);
for(i=0;i<usrs;i++) {
if(i==j)
continue;
getnodedat(usr[i],&node,0);
putnmsg(&cfg,usr[i],buf);
for(i=0;i<qusrs;i++) {
getnodedat(qusr[i],&node,0);
putnmsg(&cfg,qusr[i],buf);
sprintf(buf,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,':',pgraph);
if(useron.chat&CHAT_ECHO)
bputs(buf);
for(i=0;i<usrs;i++) {
getnodedat(usr[i],&node,0);
putnmsg(&cfg,usr[i],buf);
for(i=0;i<qusrs;i++) {
getnodedat(qusr[i],&node,0);
putnmsg(&cfg,qusr[i],buf);
if(!usrs && channel && gurubuf
&& cfg.chan[channel-1]->misc&CHAN_GURU)
guruchat(pgraph,gurubuf,cfg.chan[channel-1]->guru,guru_lastanswer);
if(gurubuf != NULL)
free(gurubuf);
/****************************************************************************/
/****************************************************************************/
bool sbbs_t::guru_page(void)
{
char path[MAX_PATH+1];
char* gurubuf;
int file;
long i;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
if(!cfg.total_gurus) {
bprintf(text[SysopIsNotAvailable],"The Guru");
if(cfg.total_gurus==1 && chk_ar(cfg.guru[0]->ar,&useron,&client))
i=0;
else {
for(i=0;i<cfg.total_gurus;i++)
uselect(1,i,nulstr,cfg.guru[i]->name,cfg.guru[i]->ar);
i=uselect(0,0,0,0,0);
if(i<0)
}
sprintf(path,"%s%s.dat",cfg.ctrl_dir,cfg.guru[i]->code);
if((file=nopen(path,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,path,O_RDONLY);
long length = (long)filelength(file);
if(length < 0) {
errormsg(WHERE ,ERR_CHK, path, length);
close(file);
return false;
}
if((gurubuf=(char *)malloc(length + 1))==NULL) {
errormsg(WHERE, ERR_ALLOC, path, length + 1);
if(read(file,gurubuf,length) != length)
errormsg(WHERE, ERR_READ, path, length);
gurubuf[length]=0;
return(true);
}
/****************************************************************************/
/* The chat section */
/****************************************************************************/
void sbbs_t::chatsection()
{
char str[256],ch,no_rip_menu;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
if(useron.misc&(RIP|WIP|HTML) || !(useron.misc&EXPERT))

rswindell
committed
menu("chat");
ASYNC;
bputs(text[ChatPrompt]);
while(online) {
no_rip_menu=0;
ch=(char)getkeys("ACDJPQST?\r",0);
logch(ch,0);
switch(ch) {
case 'S':
useron.chat^=CHAT_SPLITP;
putuserchat(useron.number, useron.chat);
bprintf("\r\nPrivate split-screen chat is now: %s\r\n"
,useron.chat&CHAT_SPLITP ? text[ON]:text[OFF]);
break;
case 'A':
CRLF;
useron.chat^=CHAT_NOACT;
putuserchat(useron.number, useron.chat);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc^=NODE_AOFF;
printnodedat(cfg.node_num,&thisnode);
}
putnodedat(cfg.node_num,&thisnode);
no_rip_menu=true;
break;
case 'D':
CRLF;
useron.chat^=CHAT_NOPAGE;
putuserchat(useron.number, useron.chat);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc^=NODE_POFF;
printnodedat(cfg.node_num,&thisnode);
}
putnodedat(cfg.node_num,&thisnode);
no_rip_menu=true;
break;
case 'J':
break;
case 'P': /* private node-to-node chat */
privchat();
break;
case 'C':
no_rip_menu=1;
if(cfg.total_gurus && chk_ar(cfg.guru[0]->ar,&useron,&client) && text[ChatWithGuruInsteadQ][0]) {
SAFEPRINTF(str,text[ChatWithGuruInsteadQ],cfg.guru[0]->name);
no_rip_menu=1;
break;
case '?':
if(useron.misc&EXPERT)

rswindell
committed
menu("chat");
break;
default: /* 'Q' or <CR> */
lncntr=0;
if(!(useron.misc&EXPERT) || useron.misc&(WIP|HTML)
|| (useron.misc&RIP && !no_rip_menu)) {
bputs(text[ChatPrompt]);
}
/****************************************************************************/
/****************************************************************************/
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
return(false);
}
if(sysop_available(&cfg)
|| (cfg.sys_chat_ar[0] && chk_ar(cfg.sys_chat_ar,&useron,&client))
if(!(sys_status&SS_SYSPAGE)) {
logline("C", "paged sysop for chat");
sprintf(str, "%s paged you to chat", useron.alias);
notify(&cfg, 1, str, NULL);
ftouch(syspage_semfile);
}
break;
if(i<cfg.total_pages) {
bprintf(text[PagingGuru],cfg.sys_op);
long mode = 0;
if(cfg.page[i]->misc&XTRN_STDIO)
mode |= EX_STDIO;
if(cfg.page[i]->misc&XTRN_NATIVE)
mode|= EX_NATIVE;
if(cfg.page[i]->misc&XTRN_SH)
mode |= EX_SH;
external(cmdstr(cfg.page[i]->cmd,nulstr,nulstr,NULL,mode), mode);
else if(cfg.sys_misc&SM_SHRTPAGE) {
bprintf(text[PagingGuru],cfg.sys_op);
for(i=0;i<10 && !lkbrd(1);i++) {
sbbs_beep(1000,200);
mswait(200);
outchar('.');
}
CRLF;
}
else {
sys_status^=SS_SYSPAGE;
bprintf(text[SysopPageIsNow]
,sys_status&SS_SYSPAGE ? text[ON] : text[OFF]);
nosound();
}
if(!(sys_status&SS_SYSPAGE))
remove(syspage_semfile);
return(true);
}
bprintf(text[SysopIsNotAvailable],cfg.sys_op);
return(false);
}
/****************************************************************************/
/* Returns 1 if user online has access to channel "channum" */
/****************************************************************************/
bool sbbs_t::chan_access(uint cnum)
{
if(!cfg.total_chans || cnum>=cfg.total_chans || !chk_ar(cfg.chan[cnum]->ar,&useron,&client)) {
bputs(text[CantAccessThatChannel]);
return(false);
}
if(!(useron.exempt&FLAG('J')) && cfg.chan[cnum]->cost>useron.cdt+useron.freecdt) {
bputs(text[NotEnoughCredits]);
return(false);
}
/****************************************************************************/
/* Private split-screen (or interspersed) chat with node or local sysop */
/****************************************************************************/

Rob Swindell
committed
void sbbs_t::privchat(bool forced, int node_num)
{
char str[128],c,*p,localbuf[5][81],remotebuf[5][81]
,localline=0,remoteline=0,localchar=0,remotechar=0
,*sep=text[PrivateChatSeparator]
,*local_sep=text[SysopChatSeparator]
;
char outpath[MAX_PATH+1];
char inpath[MAX_PATH+1];
int in,out,i,n,echo=1,x,y,activity,remote_activity;
int local_y=1,remote_y=1;
time_t last_nodechk=0;

Rob Swindell
committed
if(forced)
n = node_num;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
return;
}
n=getnodetopage(0,0);
if(!n)
return;
if(n==cfg.node_num) {
bputs(text[NoNeedToPageSelf]);
getnodedat(n,&node,0);
if(node.action==NODE_PCHT && node.aux!=cfg.node_num) {
bprintf(text[NodeNAlreadyInPChat],n);

Rob Swindell
committed
if(SYSOP && getnodedat(n, &node, true) == 0) {
node.misc |= NODE_FCHAT;
putnodedat(n, &node);
} else {
if((node.action!=NODE_PAGE || node.aux!=cfg.node_num)
&& node.misc&NODE_POFF) {
bprintf(text[CantPageNode],node.misc&NODE_ANON
? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
return;
}
if(node.action!=NODE_PAGE) {
bprintf(text[PagingUser]
,node.misc&NODE_ANON ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp)
,node.misc&NODE_ANON ? 0 : node.useron);
sprintf(str,text[NodePChatPageMsg]
,cfg.node_num,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias);
putnmsg(&cfg,n,str);
sprintf(str,"paged %s on node %d to private chat"
,username(&cfg,node.useron,tmp),n);
logline("C",str);
}
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action=NODE_PAGE;
thisnode.aux=n;
putnodedat(cfg.node_num,&thisnode);
}
if(node.action!=NODE_PAGE || node.aux!=cfg.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==cfg.node_num) {
bprintf(text[NodeJoinedPrivateChat]
,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp));
action=NODE_PAGE;
checkline();
gettimeleft();
inkey(K_NONE,500);
gettimeleft();
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action=NODE_PCHT;
thisnode.aux=n;

Rob Swindell
committed
thisnode.misc&=~ (NODE_LCHAT|NODE_FCHAT);
putnodedat(cfg.node_num,&thisnode);
}

Rob Swindell
committed
if(!online || (!forced && (sys_status&SS_ABORT)))

Rob Swindell
committed
if(forced && n == 0) {
/* If an external sysop chat event handler is installed, just run that and do nothing else */
if(user_event(EVENT_LOCAL_CHAT))
return;
}
if(((sys_status&SS_USERON && useron.chat&CHAT_SPLITP) || !(sys_status&SS_USERON))
&& term_supports(ANSI) && rows>=24 && cols>=80)
else
sys_status&=~SS_SPLITP;
/*
if(!(useron.misc&EXPERT))

rswindell
committed
menu("privchat");
*/
if(!(sys_status&SS_SPLITP)) {

Rob Swindell
committed
if(forced)
bprintf(text[SysopIsHere],cfg.sys_op);
else
bputs(text[WelcomeToPrivateChat]);
}
sprintf(outpath,"%schat.dab",cfg.node_dir);
if((out=sopen(outpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,DEFFILEMODE))==-1) {
errormsg(WHERE,ERR_OPEN,outpath,O_RDWR|O_DENYNONE|O_CREAT);
return;
}

Rob Swindell
committed
if(forced && n == 0)
sprintf(inpath,"%slchat.dab",cfg.node_dir);
sprintf(inpath,"%schat.dab",cfg.node_path[n-1]);
if(!fexist(inpath)) /* Wait while it's created for the first time */
if((in=sopen(inpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,DEFFILEMODE))==-1) {
errormsg(WHERE,ERR_OPEN,inpath,O_RDWR|O_DENYNONE|O_CREAT);
errormsg(WHERE,ERR_ALLOC,nulstr,PCHAT_LEN);
memset(p,0,PCHAT_LEN);
write(in,p,PCHAT_LEN);
write(out,p,PCHAT_LEN);
lseek(in,0L,SEEK_SET);
lseek(out,0L,SEEK_SET);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_RPCHT; /* Clear "reset pchat flag" */
putnodedat(cfg.node_num,&thisnode);
}

Rob Swindell
committed
if(n) { // not local
if(getnodedat(n,&node,true)==0) {
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(cfg.node_num,&thisnode,0);
if(thisnode.misc&NODE_RPCHT)
break;
checkline();
gettimeleft();
SYNC;
}
action=NODE_PCHT;
SYNC;
if(sys_status&SS_SPLITP) {
lncntr=0;
CLS;
ansi_save();
ansi_gotoxy(1,13);

Rob Swindell
committed
bprintf(forced ? local_sep : sep
,thisnode.misc&NODE_MSGW ? 'T':' '
,thisnode.misc&NODE_NMSG ? 'M':' ');
ansi_gotoxy(1,14);

Rob Swindell
committed
while(online && (forced || !(sys_status&SS_ABORT))) {
lncntr=0;
if(sys_status&SS_SPLITP)
lbuflen=0;
action=NODE_PCHT;
activity=0;
remote_activity=0;
if((ch=inkey(K_GETSTR,100))!=0) {
activity=1;
if(echo)
attr(cfg.color[clr_chatlocal]);
if(ch==BS || ch==DEL) {
localbuf[localline][localchar]=0;
}
}
else if(ch==TAB) {
if(echo)
outchar(' ');
localbuf[localline][localchar]=' ';
localchar++;
while(localchar<78 && localchar%8) {
if(echo)
localbuf[localline][localchar++]=' ';
}
}
if(sys_status&SS_SPLITP) {
CLS;
attr(cfg.color[clr_chatremote]);
remotebuf[remoteline][remotechar]=0;
for(i=0;i<=remoteline;i++) {
bputs(remotebuf[i]);
if(i!=remoteline)
bputs(crlf);
}
remote_y=1+remoteline;
bputs("\1i_\1n"); /* Fake cursor */