/***************************************************************************
 *                                                                         *
 *   TLCTRANS.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1997  Galacticomm, Inc.        All Rights Reserved      *
 *                                                                         *
 *   Baseline Teleconference Transport Classes                             *
 *   Implementation                                                        *
 *                                               - Phil Henning 5/14/97    *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "tlcapi.hpp"
#include "tlcfsd.h"
#include "tlccmdm.h"

#define FILREV "$Revision: 85 $"

const INT SMBSWAP=10;              // number of SMB regions under DOS

typedef struct transUsers {
     CHAR Name[TLCUIDSIZ];
} TRANSUSERS, *LPTRANSUSERS ;

SMBKEYTABLE smbTransUsrKey[]={
     {offsetof(transUsers,Name),smbCompareString},
     {0,NULL}
};

/* function definitions start here */

MARKSOURCE(tlctrans);

/* base transport class */

CTlcTransport::CTlcTransport() : m_fFlags(0)
{
     m_smbUsers = new CSmb(sizeof(TRANSUSERS),smbTransUsrKey,SMBSWAP);
}

CTlcTransport::~CTlcTransport()
{
     if (m_smbUsers != NULL) {
          delete m_smbUsers;
          m_smbUsers=NULL;
     }
}

CHAR*
CTlcTransport::GetName()
{
     return(m_transport);
}

VOID
CTlcTransport::SetName(
const CHAR* name)
{
     stlcpy(m_transport,name,TRANSNAMSIZ);
}

VOID
CTlcTransport::AddUser(            // Add a user to the transport
CTlcUser* pUser)                   //  Pointer to tele user object to add
{
     TRANSUSERS tu;

     ASSERT(pUser != NULL);
     ASSERT(m_smbUsers != NULL);

     stzcpy(tu.Name,pUser->GetName(),TLCUIDSIZ);
     if (m_smbUsers->GetEqual(pUser->GetName(),0) == NULL) {
          m_smbUsers->Insert(&tu);
     }
}

VOID
CTlcTransport::RemoveUser(         // Remove a user from the transport
CTlcUser* pUser)                   //  Pointer to the tele user to remove
{
     ASSERT(pUser != NULL);
     ASSERT(m_smbUsers != NULL);

     while (m_smbUsers->GetEqual(pUser->GetName(),0) != NULL) {
          m_smbUsers->Delete();
     }
}

CTlcUser*                          //  Pointer to a CTlcUser
CTlcTransport::GetFirstUser(       // Get first user in transport
CTlcChannel* pChannel)             //  Channel to limit to (NULL=all chans)
{
     CHAR* userid;
     CTlcUser* pUser=NULL;

     ASSERT(m_smbUsers != NULL);
     userid=static_cast<CHAR*>(m_smbUsers->GetLow(0));
     while (userid != NULL) {
          if (pChannel != NULL) {
               pUser=tlcAPI->chanFindUser(pChannel->GetName(),userid);
          }
          else {
               pUser=tlcAPI->usrGetByName(userid);
          }
          if (pUser != NULL) {
               break;
          }
          userid=static_cast<CHAR*>(m_smbUsers->GetNext());
     }
     return(pUser);
}

CTlcUser*                          //  Pointer to a CTlcUser
CTlcTransport::GetNextUser(        // Get next user in transport
CTlcChannel* pChannel)             //  Channel to limit to (NULL=all chans)
{
     CHAR* userid;
     CTlcUser* pUser=NULL;

     ASSERT(m_smbUsers != NULL);
     while ((userid=static_cast<CHAR*>(m_smbUsers->GetNext())) != NULL) {
          if (pChannel != NULL) {
               pUser=tlcAPI->chanFindUser(pChannel->GetName(),userid);
          }
          else {
               pUser=tlcAPI->usrGetByName(userid);
          }
          if (pUser != NULL) {
               break;
          }
     }
     return(pUser);
}

CTlcUser*                          //   Pointer to a CTlcUser
CTlcTransport::GetUserGT(          // Get greater-than user in transport
const CHAR* pszUserid,             //   User-ID to get greater than
CTlcChannel* pChannel)             //   Channel to limit to (NULL=all chans)
{
     CTlcUser* pUser=NULL;

     ASSERT(m_smbUsers != NULL);
     while ((pszUserid=static_cast<const CHAR*>(m_smbUsers->GetGreater(pszUserid,0))) != NULL) {
          if (pChannel != NULL) {
               pUser=tlcAPI->chanFindUser(pChannel->GetName(),pszUserid);
          }
          else {
               pUser=tlcAPI->usrGetByName(pszUserid);
          }
          if (pUser != NULL) {
               break;
          }
     }
     return(pUser);
}

VOID
CTlcTransport::SendAll(            // Send to all users
const CHAR* pszUseridFrom,         //  Userid message is from
const CHAR* pszUseridTo,           //  Userid message is to
const CHAR* pMsg,                  //  Text to send
SHORT fType,                       //  Type of text
CTlcChannel* pChannel,             //  Send to users on this channel
SHORT iMsgNum,                     //  MSG file template to use
const CHAR* ptr1,                  //  extra information for MSG template
const CHAR* ptr2,                  //  extra information for MSG template
const CHAR* ptr3)                  //  extra information for MSG template
{

     SendAllKey(pszUseridFrom,pszUseridTo,pMsg,fType,pChannel,iMsgNum,
                ptr1,ptr2,ptr3,NULL);
}

VOID
CTlcTransport::SendAllKey(         // Send to all users having a specific key
const CHAR* pszUseridFrom,         //  Userid message is from
const CHAR* pszUseridTo,           //  Userid message is to
const CHAR* pMsg,                  //  Text to send
SHORT fType,                       //  Type of text
CTlcChannel* pChannel,             //  Send to users on this channel
SHORT iMsgNum,                     //  MSG file template to use
const CHAR* ptr1,                  //  extra information for MSG template
const CHAR* ptr2,                  //  extra information for MSG template
const CHAR* ptr3,                  //  extra information for MSG template
const CHAR* key)                   //  key required to get the text
{
     CTlcUser* pUserTo;
     CTlcUser* pUserFrom;

     pUserFrom=tlcAPI->usrGetByName(pszUseridFrom);
     pUserTo=GetFirstUser(pChannel);
     while (pUserTo != NULL) {
          if (key == NULL || pUserTo->CheckAccess(key)) {
               if (!(m_fFlags&TRANS_NOECHO)
                || !sameas(pUserTo->GetName(),pszUseridFrom)) {
                    VOID* SavePos=tlcAPI->usrGetPos();
                    RecvText(pUserFrom,pUserTo,pMsg,fType,iMsgNum,ptr1
                            ,ptr2,ptr3);
                    tlcAPI->usrSetPos(SavePos);
               }
          }
          pUserTo=GetNextUser(pChannel);
     }
     UNREFERENCED(pszUseridTo);
}

VOID
CTlcTransport::SendAllBut(         // Send to all users BUT
const CHAR* pszUseridFrom,         //  Userid message is from
const CHAR* pszUseridTo,           //  Userid message is to
const CHAR* pMsg,                  //  Text to send
SHORT fType,                       //  Type of text
CTlcChannel* pChannel,             //  Send to users on this channel
SHORT iMsgNum,                     //  MSG file template to use
const CHAR* ptr1,                  //  extra information for MSG template
const CHAR* ptr2,                  //  extra information for MSG template
const CHAR* ptr3,                  //  extra information for MSG template
const CHAR* pszUseridNot1,         //  user not to send to
const CHAR* pszUseridNot2)         //  user not to send to
{
     CTlcUser* pUserTo;
     CTlcUser* pUserFrom;

     pUserFrom=tlcAPI->usrGetByName(pszUseridFrom);
     pUserTo=GetFirstUser(pChannel);
     while (pUserTo != NULL) {
          if (pszUseridNot1 != NULL && sameas(pUserTo->GetName(),pszUseridNot1)) {
               pUserTo=GetNextUser(pChannel);
               continue;
          }
          if (pszUseridNot2 != NULL && sameas(pUserTo->GetName(),pszUseridNot2)) {
               pUserTo=GetNextUser(pChannel);
               continue;
          }
          if (!(m_fFlags&TRANS_NOECHO)
           || !sameas(pUserTo->GetName(),pszUseridFrom)) {
               VOID* SavePos=tlcAPI->usrGetPos();
               RecvText(pUserFrom,pUserTo,pMsg,fType,iMsgNum,ptr1,ptr2,ptr3);
               tlcAPI->usrSetPos(SavePos);
          }
          pUserTo=GetNextUser(pChannel);
     }
     UNREFERENCED(pszUseridTo);
}

VOID
CTlcTransport::CmdResult(          // Send output based on a command
CTlcUser* pUser,                   //  user to send to
SHORT iOperation,                  //  operation performed
GBOOL bSuccess,                    //  successful?
SHORT iReason)                     //  reason for success/failure
{
     CTlcListInf* pList;
     CTlcScanInf* pScan;
     CTlcJoinInf* pJoin, *pInvite, *pForget, *pSquelch;
     CTlcWhisInf* pWhisper;
     CTlcActInf* pAction;
     CTlcUser* pOthUser;
     INT SaveUser=usrnum;

     ASSERT(pUser != NULL);
     ASSERT(tlcwrk != NULL);
     setmbk(msgTlc);
     clrprf();
     if (pUser->GetUsrnum() >= 0) {
          curusr(pUser->GetUsrnum());
     }
     else {
          clingo=0;
     }
     switch (iOperation) {
     case CMD_IGNORE:
          pInvite=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               prfmsg(IGNOR3,pInvite->m_strName);
          }
          else {
               switch (iReason) {
               case CMD_IGNORE_NOACS:
                    prfmsg(FGTNOAX2,"ignore");
                    break;
               case CMD_IGNORE_NOONE:
                    prfmsg(IGNHELP2);
                    break;
               case CMD_IGNORE_AMBIG:
                    prfmsg(NPGAMB3,pInvite->m_strName);
                    break;
               case CMD_IGNORE_NOSUCH:
                    prfmsg(NOTON,pInvite->m_strName);
                    break;
               case CMD_IGNORE_ALRDY:
                    prfmsg(IGNALR2,pInvite->m_strName);
                    break;
               case CMD_IGNORE_NOSELF:
                    prfmsg(WHYYOU2,"ignore");
                    break;
               case CMD_IGNORE_TOOMANY:
                    prfmsg(TOOMANY2,"ignored","ignore",n2ign);
                    break;
               case CMD_IGNORE_NOSYS:
                    prfmsg(NODICE4);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_NOTICE:
          pInvite=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               pOthUser=tlcAPI->usrGetByName(pInvite->m_strName);
               ASSERT(pOthUser != NULL);
               prfmsg(NOTICD2,pInvite->m_strName
                     ,(pOthUser->GetSex() == 'F' ? "her" : "his"));
          }
          else {
               switch (iReason) {
               case CMD_NOTICE_NOONE:
                    prfmsg(NOTHELP2);
                    break;
               case CMD_NOTICE_AMBIG:
                    prfmsg(NPGAMB3,pInvite->m_strName);
                    break;
               case CMD_NOTICE_NOSUCH:
                    prfmsg(NOTON,pInvite->m_strName);
                    break;
               case CMD_NOTICE_NOTIGN:
                    prfmsg(NOTIGN2,pInvite->m_strName);
                    break;
               case CMD_NOTICE_NOSELF:
                    prfmsg(WHYYOU2,"notice");
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_ZAPPO:
          if (bSuccess) {
               switch (iReason) {
               case 0:
                    prfmsg(ZAPDOK3);
                    break;
               case CMD_ZAPPO_DELETED:
                    prfmsg(ZAPDDL3);
                    break;
               case CMD_ZAPPO_SUSPENDED:
                    prfmsg(ZAPDSU3);
                    break;
               }
          }
          else {
               switch (iReason) {
               case CMD_ZAPPO_NOUSR:
                    prfmsg(ZAPDNO2);
                    break;
               case CMD_ZAPPO_NODELETE:
                    prfmsg(ZAPDND2);
                    break;
               case CMD_ZAPPO_NOUSRON:
                    prfmsg(ZAPDNO2);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_ECHO:
          switch (iReason) {
          case CMD_ECHO_HELP:
               prfmsg(ECHHLP2);
               break;
          case CMD_ECHO_ON:
               prfmsg(ECHMON2);
               break;
          case CMD_ECHO_OFF:
               prfmsg(ECHMOF2);
               break;
          case CMD_ECHO_PX:
               prfmsg(ECHMPX2);
               break;
          }
          Output(pUser);
          break;
     case CMD_OPEN:
          if (bSuccess) {
               prfmsg(CHNOPEN2);
          }
          else {
               switch (iReason) {
               case CMD_OPEN_ALREADY:
                    prfmsg(CHNAOPN2);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_CLOSE:
          if (bSuccess) {
               prfmsg(CHNCLSD2);
          }
          else {
               switch (iReason) {
               case CMD_CLOSE_ALREADY:
                    prfmsg(CHNACLS2);
                    break;
               case CMD_CLOSE_PRIVATE:
                    prfmsg(CHNCCLS2);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_CHAT:
          if (bSuccess) {
               CHAR* name=itemidx((CHAR*)tlcwrk,0);
               switch (iReason) {
               case CMD_CHAT_NOTIFY:
                    pOthUser=tlcAPI->usrGetByName(name);
                    ASSERT(pOthUser != NULL);
                    prfmsg(CHAREQ2,pOthUser->GetName(),
                       pOthUser->GetSex() == 'F' ? "her" : "him",
                       pOthUser->GetName());
                    break;
               case CMD_CHAT_NOTIFIED:
                    prfmsg(CREQOK2,name);
                    break;
               case CMD_CHAT_ACCEPTED:
                    prfmsg(ACCPCH2,pUser->GetChatUser());
                    // Drop through intentional
               case CMD_CHAT_BEGIN:
                    prfmsg(ENTCHA2);
                    break;
               }
          }
          else {
               CHAR transport[TRANSNAMSIZ];
               CHAR* name=itemidx((CHAR*)tlcwrk,0);
               switch (iReason) {
               case CMD_CHAT_CANT:
                    if (itemcnt((CHAR*)tlcwrk) < 2) {
                         strcpy(transport,"Unknown");
                    }
                    else {
                         stlcpy(transport,itemidx((CHAR*)tlcwrk,1),TRANSNAMSIZ);
                    }
                    name=itemidx((CHAR*)tlcwrk,0);
                    prfmsg(TRANSNO,"request a chat with",name,transport,"CHAT mode");
                    break;
               case CMD_CHAT_CAMBIG:
               case CMD_CHAT_AMBIG:
                    prfmsg(NCHAMB2,name);
                    break;
               case CMD_CHAT_NOSUCH:
                    prfmsg(NCHUID2,name);
                    break;
               case CMD_CHAT_ALREADY:
                    prfmsg(ALRICH2,name);
                    break;
               case CMD_CHAT_SELF:
                    prfmsg(NCHSLF2);
                    break;
               case CMD_CHAT_NOCHAT:
                    prfmsg(CHATOFF,name);
                    break;
               case CMD_CHAT_CANTCHAT:
                    prfmsg(NCHUID2,name);
                    break;
               case CMD_CHAT_TOOSOON:
                    prfmsg(NCHNNW2,name);
                    break;
               case CMD_CHAT_NOACCESS:
                    prfmsg(CANTCH2);
                    break;
               case CMD_CHAT_HELP:
                    prfmsg(CHAFMT2);
                    break;
               case CMD_CHAT_FGT:
                    prfmsg(FORGTN2,name);
                    break;
               case CMD_CHAT_NOCHATU:
                    prfmsg(CHATOFFY,name);
                    break;
               case CMD_CHAT_BUSY:
                    prfmsg(CHATBUS2);
                    break;
               case CMD_CHAT_YOUALREADY:
                    prfmsg(YOUACHT);
                    break;
               }
          }
          Output(pUser);
          clrprf();
          break;
     case CMD_JOIN:
          pJoin=static_cast<CTlcJoinInf*>(tlcwrk);
          if (!bSuccess) {
               switch (iReason) {
               case CMD_JOIN_NOCHAN:
                    prfmsg(NOTON,pJoin->m_strName);
                    break;
               case CMD_JOIN_AMBIG:
                    prfmsg(NPGAMB3,pJoin->m_strName);
                    break;
               case CMD_JOIN_ALREADY:
                    prfmsg(ALRCHN2);
                    break;
               case CMD_JOIN_NOACS:
                    prfmsg(NAXSCHN2);
                    break;
               case CMD_JOIN_NOT_INVITED:
                    prfmsg(NOTINV2,pJoin->m_strName);
                    break;
               case CMD_JOIN_PRIV_ALREADY:
                    prfmsg(ALRTHR3,pJoin->m_strName);
                    break;
               case CMD_JOIN_CANTLFORUM:
                    prfmsg(CANTEX2);
                    break;
               case CMD_JOIN_CANTJFORUM:
                    prfmsg(CANTJN2);
                    break;
               case CMD_JOIN_TOOFAST:
                    prfmsg(NANNOY);
                    break;
               }
               Output(pUser);
          }
          break;
     case CMD_LIST:
          pList=static_cast<CTlcListInf*>(tlcwrk);
          if (bSuccess) {
               prfmsg(LSTFTR2);
          }
          else if (iReason == CMD_LIST_ITEM) {
               prfmsg(LSTCHN5,pList->m_strName,
                  (pList->m_strTopic[0] == '\0' ? "<no topic>" :
                    pList->m_strTopic),
                    pList->m_iUsers);
          }
          else {
               prfmsg(LSTHDR4);
          }
          Output(pUser);
          break;
     case CMD_INVITE:
          pInvite=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               if (iReason == CMD_INVITE_NOTIFY) {
                    pOthUser=tlcAPI->usrGetByName(pInvite->m_strName);
                    ASSERT(pOthUser != NULL);
                    prfmsg(INVITA2,pInvite->m_strName
                           ,(pOthUser->GetSex() == 'F' ? "her" : "his"));
                    prfmsg(INVITJ2,pInvite->m_strName);
               }
               else {
                    prfmsg(OKINVT2,pInvite->m_strName);
               }
          }
          else {
               CHAR transport[TRANSNAMSIZ];
               switch (iReason) {
               case CMD_INVITE_CANT:
                    if (itemcnt((CHAR*)tlcwrk) < 2) {
                         strcpy(transport,"Unknown");
                    }
                    else {
                         stlcpy(transport,itemidx((CHAR*)tlcwrk,1),TRANSNAMSIZ);
                    }
                    prfmsg(TRANSNO,"invite",itemidx((CHAR*)tlcwrk,0),transport,"private channels");
                    break;
               case CMD_INVITE_NOACS:
                    prfmsg(INVNOAC2);
                    break;
               case CMD_INVITE_NOONE:
                    prfmsg(INVHELP2);
                    break;
               case CMD_INVITE_AMBIG:
                    prfmsg(NPGAMB3,pInvite->m_strName);
                    break;
               case CMD_INVITE_NOSUCH:
                    prfmsg(NOTON,pInvite->m_strName);
                    break;
               case CMD_INVITE_ALRDY:
                    prfmsg(ALRINV2,pInvite->m_strName);
                    break;
               case CMD_INVITE_NOSELF:
                    prfmsg(WHYYOU2,"invite");
                    break;
               case CMD_INVITE_TOOMANY:
                    prfmsg(TOOMANY2,"invited","invite",n2inv);
                    break;
               case CMD_INVITE_FGT:
                    prfmsg(FORGTN2,pInvite->m_strName);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_UNINVITE:
          pInvite=static_cast<CTlcJoinInf*>(tlcwrk);
          switch (iReason) {
          case CMD_UNINVITE_MODERATOR:
               prfmsg(NODICE4);
               break;
          case CMD_UNINVITE_NOONE:
               prfmsg(UNINVHP2);
               break;
          case CMD_UNINVITE_AMBIG:
               prfmsg(NPGAMB3,pInvite->m_strName);
               break;
          case CMD_UNINVITE_NOSUCH:
               prfmsg(NOTON,pInvite->m_strName);
               break;
          case CMD_UNINVITE_NOTINV:
               prfmsg(UNNTINV2,pInvite->m_strName);
               break;
          case CMD_UNINVITE_KICK:
               prfmsg(UNVITD3,pInvite->m_strName);
               break;
          case CMD_UNINVITE_MYKICK:
               prfmsg(KUNVIT2,pInvite->m_strName);
               break;
          case CMD_UNINVITE_MYUNINV:
               prfmsg(OKUNVT2,pInvite->m_strName);
               break;
          case CMD_UNINVITE_NOSELF:
               prfmsg(WHYYOU2,"uninvite");
               break;
          }
          Output(pUser);
          break;
     case CMD_FORGET:
          pForget=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               pOthUser=tlcAPI->usrGetByName(pForget->m_strName);
               ASSERT(pOthUser != NULL);
               prfmsg(FORGT3,pForget->m_strName
                     ,(pOthUser->GetSex() == 'F' ? "her" : "his")
                     ,(pOthUser->GetSex() == 'F' ? "she" : "he"));
          }
          else {
               switch (iReason) {
               case CMD_FORGET_NOACS:
                    prfmsg(FGTNOAX2,"forget");
                    break;
               case CMD_FORGET_NOONE:
                    prfmsg(FGTHELP2);
                    break;
               case CMD_FORGET_AMBIG:
                    prfmsg(NPGAMB3,pForget->m_strName);
                    break;
               case CMD_FORGET_NOSUCH:
                    prfmsg(NOTON,pForget->m_strName);
                    break;
               case CMD_FORGET_NOSELF:
                    prfmsg(WHYYOU2,"forget");
                    break;
               case CMD_FORGET_MODERATOR:
                    prfmsg(NODICE4);
                    break;
               case CMD_FORGET_NOFORGET:
                    prfmsg(NOFORG2,pForget->m_strName);
                    break;
               case CMD_FORGET_ALRDY:
                    prfmsg(FGTALR2,pForget->m_strName);
                    break;
               case CMD_FORGET_TOOMANY:
                    prfmsg(TOOMANY2,"forgotten","forget",n2fgt);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_REMEMBER:
          pForget=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               pOthUser=tlcAPI->usrGetByName(pForget->m_strName);
               ASSERT(pOthUser != NULL);
               prfmsg(REMEMD2,pForget->m_strName
                     ,(pOthUser->GetSex() == 'F' ? "her" : "his"));
          }
          else {
               switch (iReason) {
               case CMD_REMEMBER_NOONE:
                    prfmsg(RMBHELP2);
                    break;
               case CMD_REMEMBER_AMBIG:
                    prfmsg(NPGAMB3,pForget->m_strName);
                    break;
               case CMD_REMEMBER_NOSUCH:
                    prfmsg(NOTON,pForget->m_strName);
                    break;
               case CMD_REMEMBER_NOSELF:
                    prfmsg(WHYYOU2,"remember");
                    break;
               case CMD_REMEMBER_NOTFGT:
                    prfmsg(NFGTN2,pForget->m_strName);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_SQUELCH:
          pSquelch=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               prfmsg(SQLSDNE4,pSquelch->m_strName,pSquelch->m_strName);
          }
          else {
               switch (iReason) {
               case CMD_SQUELCH_NOONE:
                    prfmsg(SQLHLP2);
                    break;
               case CMD_SQUELCH_AMBIG:
                    prfmsg(NPGAMB3,pSquelch->m_strName);
                    break;
               case CMD_SQUELCH_NOSUCH:
                    prfmsg(NOTON,pSquelch->m_strName);
                    break;
               case CMD_SQUELCH_NOSELF:
                    prfmsg(WHYYOU2,"squelch");
                    break;
               case CMD_SQUELCH_MODERATOR:
                    prfmsg(SQLNSYS2);
                    break;
               case CMD_SQUELCH_ALRDY:
                    prfmsg(SQLALRY2,pSquelch->m_strName,pSquelch->m_strName);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_UNSQUELCH:
          pSquelch=static_cast<CTlcJoinInf*>(tlcwrk);
          if (bSuccess) {
               prfmsg(SQLSUND3,pSquelch->m_strName,pSquelch->m_strName);
          }
          else {
               switch (iReason) {
               case CMD_UNSQUELCH_NOONE:
                    prfmsg(SQLHLP2);
                    break;
               case CMD_UNSQUELCH_AMBIG:
                    prfmsg(NPGAMB3,pSquelch->m_strName);
                    break;
               case CMD_UNSQUELCH_NOSUCH:
                    prfmsg(NOTON,pSquelch->m_strName);
                    break;
               case CMD_UNSQUELCH_NOTSQ:
                    prfmsg(SQLNOT2,pSquelch->m_strName,pSquelch->m_strName);
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_SCAN:
          pScan=static_cast<CTlcScanInf*>(tlcwrk);
          if (bSuccess) {
               prfmsg(NSCNFTR2);
          }
          else {
               CTlcUser* pScanUser=tlcAPI->usrGetByName(pScan->m_strUserid);
               switch (iReason) {
               case CMD_SCAN_ITEM:
                    prfmsg(NSCNLST3
                      ,colors[(pScanUser->GetSex() == 'M') ? iMale : iFemale]
                      ,pScan->m_strUserid
                      ,(pScan->m_fFlags&USR_FORGOT ? "*" : " ")
                      ,(pScan->m_fFlags&USR_INVITE ? "*" : " ")
                      ,pScan->m_strChan);
                    break;
               default:
                    prfmsg(NSCNHDR3);
               }
          }
          Output(pUser);
          break;
     case CMD_DIRECT:
          pWhisper=static_cast<CTlcWhisInf*>(tlcwrk);
          if (bSuccess) {
               pUser->Talked();
          }
          else {
               switch (iReason) {
               case CMD_DIRECT_NOSUCH:
                    prfmsg(WHSNHR3);
                    break;
               case CMD_DIRECT_DAMBIG:
                    prfmsg(DAMBIG3,pWhisper->m_strName);
                    break;
               case CMD_DIRECT_NOONE:
                    prfmsg(DIRFMT3,dirchr);
                    break;
               case CMD_DIRECT_AMBIG:
                    prfmsg(AMBIG2,pWhisper->m_strName,"directed");
                    break;
               case CMD_DIRECT_FGT:
                    prfmsg(FORGTN2,pWhisper->m_strName);
                    break;
               case CMD_DIRECT_SQ:
                    prfmsg(SQLRBF3);
                    break;
               }
               Output(pUser);
          }
          break;
     case CMD_SPEAK:
          if (!bSuccess) {
               switch (iReason) {
               case CMD_SPEAK_SQUEL:
                    prfmsg(SQLRBF3);
                    break;
               case CMD_SPEAK_INVIS:
                    prfmsg(URINVS2);
                    break;
               case CMD_SPEAK_LIMITED:
                    prfmsg(NPAYXC2,tlcAPI->m_npaymx);
                    break;
               case CMD_SPEAK_TOOFAST:
                    prfmsg(TOOFAST);
                    break;
               }
               Output(pUser);
          }
          else {
               pUser->Talked();
               if (!pUser->IsTypeOf(USR_NORMAL)) {
                    pUser->m_iTimesSpoken++;
                    if (pUser->GetUsrnum() > -1) {
                        ++teltimes[pUser->GetUsrnum()];
                    }
               }
          }
          break;
     case CMD_WHISPER:
          pWhisper=static_cast<CTlcWhisInf*>(tlcwrk);
          if (bSuccess) {
               pUser->Talked();
          }
          else {
               switch (iReason) {
               case CMD_WHISPER_NOSUCH:
                    prfmsg(WHSNHR3);
                    break;
               case CMD_WHISPER_AMBIG:
                    prfmsg(AMBIG2,pWhisper->m_strName,"whisper");
                    break;
               case CMD_WHISPER_NOONE:
                    prfmsg(WHSFMT3);
                    break;
               case CMD_WHISPER_REFAILED:
                    prfmsg(NORWHS2);
                    break;
               case CMD_WHISPER_PAMBIG:
                    prfmsg(PAMBIG2,pWhisper->m_strName,"whisper");
                    break;
               case CMD_WHISPER_PAGATT:
                    prfmsg(CVT2PAG2);
                    break;
               case CMD_WHISPER_FGT:
                    prfmsg(FORGTN2,pWhisper->m_strName);
                    break;
               }
               Output(pUser);
          }
          break;
     case CMD_UNLIST:
          if (bSuccess) {
               prfmsg(LISTST2,"");
          }
          else {
               prfmsg(LISTST2,"un");
          }
          Output(pUser);
          break;
     case CMD_HELP:
          switch (iReason) {
          case CMD_HELP_ALL:
               prfmsg(TLCHLP8,dirchr);
               break;
          }
          Output(pUser);
          break;
     case CMD_EDIT:
          prf("not supported\n");
          Output(pUser);
          break;
     case CMD_MENU:
          prf("not supported\n");
          Output(pUser);
          break;
     case CMD_TOPIC:
          if (bSuccess == FALSE) {
               switch (iReason) {
               case CMD_TOPIC_TOOLONG:
                    prfmsg(TOPLONG2);
                    break;
               default:
                    prfmsg(NOTHEM2);
               }
          }
          else {
               switch (iReason) {
               case CMD_TOPIC_CLEARED:
                    prfmsg(CLRTHE2);
                    break;
               case CMD_TOPIC_CHANGED:
                    prfmsg(URTHEM2,static_cast<CHAR*>(tlcwrk));
                    break;
               }
          }
          Output(pUser);
          break;
     case CMD_ACTION:
          pAction=static_cast<CTlcActInf*>(tlcwrk);
          switch(iReason) {
          case CMD_ACTION_HELP:
               prfmsg(ACTSTF3);
               break;
          case CMD_ACTION_ON:
               prfmsg(NOTICA2);
               break;
          case CMD_ACTION_OFF:
               prfmsg(IGNORA2);
               break;
          case CMD_ACTION_LIST:
               prfmsg(ACT2,pAction->m_act);
               break;
          case CMD_ACTION_EDITOR:
               prfmsg(ACTSTF3);
               break;
          case CMD_ACTION_NOSUCHLIST:
               prfmsg(NOSLST2);
               break;
          case CMD_ACTION_LISTHEADER:
               prfmsg(ACTLIST2,pAction->m_listname);
               break;
          case CMD_ACTION_NEXTLINE:
               prf("\n");
               break;
          case CMD_ACTION_NONE:
               prfmsg(NOACTC2);
               break;
          }
          Output(pUser);
          break;
     case CMD_GENERIC:
          if (!bSuccess) {
               const CHAR* transport=pUser->GetTransport()->GetName();
               prfmsg(NOTFMTR,transport);
               Output(pUser);
          }
          break;
     default:
          shocst("TELECONFERENCE ERROR","TlcTransport::CmdResult switch logic");
          ASSERTM(FALSE,"TlcTransport::CmdResult switch logic");
     }
     rstmbk();
     curusr(SaveUser);
}

VOID
CTlcTransport::OutputFinished()
{
}

bool
CTlcTransport::NeedFromUser(       // does RecvText need a from user context?
SHORT fType,                       //   text type
SHORT iMsgNum)                     //   event code
{
     switch (fType) {
     case RECV_TYPE_WHISPER:
     case RECV_TYPE_WHISPERFR:
     case RECV_TYPE_DIRECTED:
     case RECV_TYPE_ENTEREDEDIT:
     case RECV_TYPE_RETEDIT:
     case RECV_TYPE_ENTRANCE:
     case RECV_TYPE_NEWTOPIC:
     case RECV_TYPE_EXIT:
     case RECV_TYPE_PUBLIC:
          return(true);
     }
     UNREFERENCED(iMsgNum);
     return(false);
}