/*---------------------------------------------------------------------------*
*
* BinkleyTerm
*
* (C) Copyright 1987-96, Bit Bucket Software Co.
* For license and contact information see /doc/orig_260/license.260.
*
* This version was modified by the BinkleyTerm XE Team.
* For contact information see /doc/team.lst and /doc/join.us.
* For a complete list of changes see /doc/xe_user.doc and /doc/xe_hist.doc.
*
* Filename : $Source: /cvsroot/btxe/btnt/sources/chat.cpp,v $
* Revision : $Revision: 1.1 $
* Tagname : $Name: $
* Last updated: $Date: 2005/01/01 15:18:12 $
* State : $State: Exp $
*
* Description : Hydra Chat
*
*---------------------------------------------------------------------------*/
/* Include this file before any other includes or defines! */
#include "includes.h"
/****************************************************************************/
/* local static data */
/****************************************************************************/
static REGIONP callwinsave;
static REGIONP chatwinl, chatwinr;
static char *chatstart = "\007\007 * Chat mode start\r\n";
static char *chatend = "\007\007\r\n * Chat mode end\r\n";
static char *chattime = "\007\007\r\n * Chat mode timeout\r\n";
char HaveChat_Bell[] = " * Remote has chat facility (bell enabled)\n";
char HaveChat_NoBell[] = " * Remote has chat facility (bell disabled)\n";
char RemoteHasChat[] = " has chat ";
// MR 970329 not used
// char RemoteHasNoChat[] = " has no chat ";
static word chatfill;
static long lasttimer;
static BOOL msgsent = FALSE;
static BOOL chatting = FALSE;
extern REGIONP modemwin; /* AS 970315 */
char RemInitials[40], LocInitials[40];
/****************************************************************************/
/* local prototypes */
/****************************************************************************/
void chatautostart (void);
/****************************************************************************/
/* functions */
/****************************************************************************/
#if 0
#ifdef DOS16 /* MR 961122 changed DOS to DOS16 */
#define CHATBUFSIZE 256
#else
#define CHATBUFSIZE HYDRATXBUFSIZE
#endif
static char buffer1[CHATBUFSIZE], buffer2[CHATBUFSIZE]; /* chat buffers */
static int bufpos = 0;
void
chat_prepare (void)
{
bufpos = 0;
}
#define CHATDELAY 30 /* how many 10ms units min. delay between packets */
int
chat_putc (int c)
{
static long flushtimer;
int ret = 0;
if (!nohydrachat)
{
if (c >= 0)
{
if (bufpos > 0 && (c == '\n' || c == ' ')) /* if this is not the 1st char and we */
flushtimer = timerset (1); /* have a blank/newline, don't wait long */
else /* do not immediately send char, but */
flushtimer = timerset (CHATDELAY); /* wait for some others maybe following */
if (bufpos < CHATBUFSIZE)
{
buffer1[bufpos++] = (char) c;
ret = 0;
}
else
ret = -1;
}
if (bufpos && hydra_devfree ()
&& (timeup (flushtimer) || (bufpos > CHATBUFSIZE / 2)))
{
strncpy (buffer2, buffer1, bufpos);
hydra_devsend ("CON", buffer2, bufpos);
bufpos = 0;
}
}
return ret;
}
void
chat_puts (char *s)
{
if (!nohydrachat)
while (*s)
chat_putc (*s++);
}
#endif /* 0 */
void
chatsendstring (char *s)
{
hydra_devsend ("CON", (byte *) s, (word) strlen (s));
sb_puts (chatwinl, s);
}
void
chatautostart (void)
{
if (autochatopen && chattimer == 0L)
{
chat_init ();
sb_puts (chatwinl, &chatstart[2]);
css_upd ();
chattimer = lasttimer = unix_time (NULL) + CHAT_TIMEOUT;
}
}
int
chatprocess (char *sorig, int islocal)
{
int isfor = 2;
char *c, *s, fn[80], line[80], *back;
back = s = (char *) malloc (strlen (sorig) + 1);
if (s == NULL)
return 0;
strcpy (s, sorig);
while ((c = strchr (s, '\n')) != NULL)
strcpy (c, c + 1);
while ((c = strchr (s, '\r')) != NULL)
strcpy (c, c + 1);
while ((c = strchr (s, 7)) != NULL)
strcpy (c, c + 1);
if (ChatLogHandle)
fprintf (ChatLogHandle, "%s>%s\n", islocal ? LocInitials : RemInitials,
s);
if (strstrci (s, "/btloc") == s)
isfor = 1;
else if (strstrci (s, "/btrem") == s)
isfor = 0;
if (islocal != isfor) /* Ignore btloc from remote and btrem from local */
{
free (s);
return 0;
}
s += 6;
while (*s == ' ')
strcpy (s, s + 1);
if (strstrci (s, "log") == s)
{
if (islocal)
{
if (!ChatLogDir)
status_line ("Directory for chat logs not defined, can't log.");
else if (ChatLogHandle == NULL)
{
c = skip_to_word (s + 3);
if (!*c)
#if defined(OS_2) | defined(_WIN32)
sprintf (fn, "%s%s.CHT", ChatLogDir, remote_sysop);
#else
sprintf (fn, "%s%s.CHT", ChatLogDir, RemInitials);
#endif
else
sprintf (fn, "%s%s", ChatLogDir, c);
ChatLogHandle = share_fopen (fn, append_ascii, DENY_WRITE);
if (ChatLogHandle == NULL)
sprintf (line, "Warning: Failed to open chat log file %s", fn);
else
sprintf (line, "\nNow logging to %s\n", fn);
chatsendstring (line);
}
else
{
fclose (ChatLogHandle);
status_line ("Chat log file closed.");
}
}
else
chatsendstring ("\nLog is only available for the local user.\n");
}
status_line (":Received command: %s", s);
free (back);
return 0;
}
void
chat_prepare (void)
{
chatfill = 0;
chattimer = -1L;
lasttimer = 0L;
msgsent = FALSE;
chatting = FALSE;
RemCommandBuf[0] = LocCommandBuf[0] = 0; /* CFS 970426 */
}
void
chat_init (void)
{
short rows, rows_call, rows_chl, rows_chr;
short chatwinl_size, chatwinr_size; /* AS 960315 */
char junk[256], *c;
/* ---------------------------------------------------------------------------- */
/* Init. initials for chat logging (for example CFS for Carlos Fernandez Sanz) */
/* ---------------------------------------------------------------------------- */
LocInitials[0] = RemInitials[0] = 0;
c = remote_sysop;
while (c)
{
if (!*c)
break;
if (*c != ' ')
sprintf (RemInitials + strlen (RemInitials), "%c", *c);
c = skip_to_word (c);
}
c = sysop;
while (c)
{
if (!*c)
break;
if (*c != ' ')
sprintf (LocInitials + strlen (LocInitials), "%c", *c);
c = skip_to_word (c);
}
if (!nohydrachat && un_attended && !do_chat)
{
chatting = TRUE;
RemCommandBuf[0] = LocCommandBuf[0] = 0; /* CFS 970426 */
hydra_devsend ("CON", (byte *) chatstart, (word) strlen (chatstart));
callwinsave = callwin;
rows = CALLWIN_HIGH;
if (rows < 21)
rows_call = 4;
else
rows_call = 10;
rows -= rows_call;
rows_chl = rows / 2;
rows_chr = rows - rows_chl;
sprintf (junk, MSG_TXT (M_CHAT_WINLOCAL), sysop);
/*
* AS 970315, check for existing modemwin and calculate the proper size
* for the two chat windows and the new (reduced in size) callwin.
*/
if (modemwin)
{
chatwinl_size = SB_COLS - (modemwin->sc1 - modemwin->sc0) - 2;
chatwinr_size = chatwinl_size;
}
else
chatwinl_size = chatwinr_size = SB_COLS;
chatwinl = sb_new_win (TOP_PARTS_ROWS, 0,
rows_chl, (short) chatwinl_size,
' ', colors.call, boxtype, colors.frames, junk);
chatwinl->wflags = 0;
chatwinl->wflags |= SB_SCROLL | SB_WRAP | SB_ADDCR | SB_ADDLF;
/* MR 970512 we ONLY get LFs and must add CRs */
sprintf (junk, MSG_TXT (M_CHAT_WINREMOTE), remote_sysop);
chatwinr = sb_new_win (TOP_PARTS_ROWS + rows_chl, 0,
rows_chr, (short) chatwinr_size,
' ', colors.call, boxtype, colors.frames, junk);
chatwinr->wflags = 0;
chatwinr->wflags |= SB_SCROLL | SB_WRAP | SB_ADDCR | SB_ADDLF;
/* MR 970512 we ONLY get LFs and must add CRs */
callwin = sb_new_win ((short) (TOP_PARTS_ROWS + rows_chl + rows_chr), 0,
rows_call, (short) chatwinl_size,
' ', colors.call,
boxtype, colors.frames,
MSG_TXT (M_RECENT_ACTIVITY));
callwin->linesize = callwinsave->linesize;
callwin->buffer = callwinsave->buffer;
callwin->endbuff = callwinsave->endbuff;
callwin->lastline = callwinsave->lastline;
callwin->lastshown = callwinsave->lastshown;
sb_box (callwin, boxtype, colors.frames);
sb_caption (callwin, MSG_TXT (M_RECENT_ACTIVITY), colors.frames);
redraw_callwin ();
if (modemwin) /* MR 970327 */
ctrl_modemwin (1);
do_chat = 1;
}
}
void
chat_put_remote (char *s)
{
char buf[150];
char *d;
int i;
if (!nohydrachat)
{
d = s;
buf[0] = 0;
// status_line (":Entered with [%s]",s);
while (*d)
{
// sprintf (buf+strlen (buf),"%02X ",*d);
switch (*d)
{
case '\n':
/* status_line (":Remote sent %s",RemCommandBuf); */
chatprocess (RemCommandBuf, 0);
RemCommandBuf[0] = 0;
break;
case '\b':
if (strlen (RemCommandBuf))
RemCommandBuf[strlen (LocCommandBuf) - 1] = 0;
break;
default:
RemCommandBuf[strlen (RemCommandBuf) + 1] = 0;
RemCommandBuf[strlen (RemCommandBuf)] = *d;
break;
}
d++;
}
// status_line (":Hex: %s",buf);
if (chatwinr)
{
sb_puts (chatwinr, s);
css_upd ();
}
else
{
if (!chatting)
{
if (strstr (s, RemoteHasChat)) /* update remote sysop info */
show_nodes_name (" (Chat) "); /* in "recent activity" */
}
while (*s)
{
strcpy (buf, "*HCON: ");
i = 0;
d = buf + 7;
while (*s && (*s != '\n') && (i < 132))
{ /* break up into lines */
*d++ = *s++;
i++;
}
if (*s == '\n')
s++;
*d = '\0';
status_line (buf);
}
}
}
}
void
chat_exit (void)
{
chatting = FALSE;
if (!nohydrachat && un_attended && do_chat)
{
hydra_devsend ("CON", (byte *) chatend, (word) strlen (chatend));
sb_puts (chatwinl, &chatend[2]);
do_chat = 0;
callwinsave->linesize = callwin->linesize;
callwinsave->buffer = callwin->buffer;
callwinsave->endbuff = callwin->endbuff;
callwinsave->lastline = callwin->lastline;
callwinsave->lastshown = callwin->lastshown;
/* MR 970215 added free; shouldn't we give back allocated memory!? */
free (callwin);
free (chatwinr);
free (chatwinl);
callwin = callwinsave;
chatwinr = NULL;
chatwinl = NULL;
sb_fill (callwin, ' ', colors.call); /* MR 970307 sb_filla -> sb_fill */
sb_box (callwin, boxtype, colors.frames);
sb_caption (callwin, MSG_TXT (M_RECENT_ACTIVITY), colors.frames);
redraw_callwin ();
if (modemwin) /* MR 970327 */
ctrl_modemwin (1);
}
}
#if 0
int
chat_get_key (void)
{
int ret = 0;
char c;
while (KEYPRESS ())
{
c = READKB ();
ret = 0;
if (!do_chat)
{
switch (c)
{
case 27:
while (KEYPRESS ())
READKB ();
ret = 27;
break;
case '!':
chat_init ();
break;
}
}
else
{ /* do_chat */
switch (c)
{
case 27:
chat_exit ();
break;
case '\r':
c = '\n';
/* fall through into default */
default:
sb_putc (chatwinl, c);
chat_putc (c);
break;
}
}
}
chat_putc (-1); /* if there's something old to send, send it! */
return ret;
}
#endif
BOOL keyabort (void)
{
#define CHATLEN 256
static byte chatbuf1[CHATLEN + 5], chatbuf2[CHATLEN + 5], *curbuf =
chatbuf1;
static BOOL warned = FALSE;
BOOL esc = FALSE;
char *p;
word c;
if (chattimer > 0L)
{
if (unix_time (NULL) > (unsigned long) chattimer)
{
chattimer = lasttimer = 0L;
hydra_devsend ("CON", (byte *) chattime, (word) strlen (chattime));
sb_puts (chatwinl, &chattime[2]);
sb_show ();
chat_exit ();
}
else if ((unix_time (NULL) + 10L) > (unsigned long) chattimer && !warned)
{
if (!autochatopen)
sb_puts (chatwinl,
"\007\r\n * Warning: chat mode timeout in 10 seconds\r\n");
css_upd ();
warned = TRUE;
}
}
else if (chattimer != lasttimer)
{
if (chattimer == 0L && !msgsent)
{ /* other side has DEV capacity */
if (!nohydrachat)
{
if (gong_allowed)
p = HaveChat_Bell;
else
p = HaveChat_NoBell;
hydra_devsend ("CON", (byte *) p, (word) strlen (p));
}
msgsent = TRUE;
/* commented out ...
status_line(" * Hydra session in progress, chat facility now available");
*/
}
/* commented out ...
else if (chattimer == -1L)
status_line(" * Hydra session in init state, can't chat yet\r\n");
else if (chattimer == -2L)
status_line(" * Remote has no chat facility available\r\n");
else if (chattimer == -3L)
status_line(" * Hydra session in exit state, can't chat anymore\r\n");
*/
lasttimer = chattimer;
}
/* HJK 20001013 - Fixes bug with NoHydraChat */
if (nohydrachat || !un_attended) /* fixes nohydrachat */
{
while (KEYPRESS ())
{
#ifndef _WIN32
c = (word) get_key ();
#else
c = GetKBKey ();
#endif
if (!CommonProtocolKeyCheck (c))
switch (c)
{
case ESC:
esc = TRUE; /* exit hydra */
break;
default:
esc = FALSE;
break;
}
}
return (esc);
}
while (KEYPRESS ())
{
#ifndef _WIN32
c = (word) get_key ();
#else
c = GetKBKey ();
#endif
if (!CommonProtocolKeyCheck (c))
switch (c)
{
case ESC:
if (chattimer == 0L)
{ /* ESC: if in chat mode: exit chat mode */
esc = TRUE; /* if not in chat mode: exit hydra */
}
else if (chattimer > 0L)
{
chattimer = lasttimer = 0L;
chat_exit ();
}
else
esc = TRUE;
break;
case 0x2e00:
if (chattimer == 0L)
{
chat_init ();
sb_puts (chatwinl, &chatstart[2]);
css_upd ();
chattimer = lasttimer = unix_time (NULL) + CHAT_TIMEOUT;
}
else if (chattimer > 0L)
{
chattimer = lasttimer = 0L;
chat_exit ();
}
else if (!autochatopen)
sb_putc (chatwinl, '\007');
break;
default:
if (c < ' ' || c == 127 || c == 255) /*AGL:23apr93 */
break;
case '\r':
case '\a':
case '\b':
if (chattimer <= 0L)
break;
if (c == '\r')
{
/* status_line ("#Got this line: %s",LocCommandBuf); */
chatprocess (LocCommandBuf, 1);
LocCommandBuf[0] = 0;
}
chattimer = unix_time (NULL) + CHAT_TIMEOUT;
warned = FALSE;
if (chatfill >= CHATLEN)
sb_putc (chatwinl, '\007');
else
{
switch (c)
{
case '\r':
curbuf[chatfill++] = '\n';
sb_putc (chatwinl, '\n');
break;
case '\b':
if (strlen (LocCommandBuf))
LocCommandBuf[strlen (LocCommandBuf) - 1] = 0;
if (chatfill > 0 && curbuf[chatfill - 1] != '\n')
chatfill--;
else
{
curbuf[chatfill++] = '\b';
curbuf[chatfill++] = ' ';
curbuf[chatfill++] = '\b';
}
sb_puts (chatwinl, "\b \b");
break;
default:
LocCommandBuf[strlen (LocCommandBuf) + 1] = 0;
LocCommandBuf[strlen (LocCommandBuf)] = (byte) c;
curbuf[chatfill++] = (byte) c;
if (c != 7)
sb_putc (chatwinl, c);
break;
}
}
break;
}
}
if (chatfill > 0)
{
if (hydra_devsend ("CON", curbuf, chatfill))
{
curbuf = (curbuf == chatbuf1) ? chatbuf2 : chatbuf1;
chatfill = 0;
}
css_upd ();
}
return (esc);
} /*keyabort() */
/* $Id: chat.cpp,v 1.1 2005/01/01 15:18:12 vildanov Exp $ */