/***************************************************************************
 *                                                                         *
 *   MJRTLC.C                                                              *
 *                                                                         *
 *   Copyright (c) 1987-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the Worldgroup default teleconference handler.                *
 *                                                                         *
 *                                            - T. Stryker 6/29/86         *
 *                                                                         *
 *   Worldgroup mods.                         - Bill Hyatt 10/4/94         *
 *                                                                         *
 ***************************************************************************/

#include "tlc.h"
#include "oprlow.h"

#define FILREV "$Revision: 13 $"

VOID joint(USHORT chan);
GBOOL tlclon(VOID);
GBOOL tlcinp(VOID);
static CHAR *prspow(CHAR *start,INT mnum,INT prec,INT *count);
static VOID chat(VOID);
static VOID whisper(CHAR *whoto,INT mnum);
VOID tlctck(VOID);
VOID tlcfin(VOID);

struct module telecon={            /* module interface block               */
     "",                           /*    name used to refer to this module */
     NULL,                         /*    user logon supplemental routine   */
     tlcinp,                       /*    input routine if selected         */
     dfsthn,                       /*    status-input routine if selected  */
     NULL,                         /*    "injoth" routine for this module  */
     NULL,                         /*    user logoff supplemental routine  */
     tlchup,                       /*    hangup (lost carrier) routine     */
     NULL,                         /*    midnight cleanup routine          */
     NULL,                         /*    delete-account routine            */
     tlcfin                        /*    finish-up (sys shutdown) routine  */
};

INT tlcstt;                   /* teleconferencing state number             */

#define NEEDCO -1             /* target user-id count when colon is needed */

HMCVFILE tlcmb;               /* teleconf named-message file block handle  */

struct tlc *tlclst,           /* dynamic array of tele volatile user area  */
           *tlcptr,*tptr;     /* handy pointers for speed                  */

/*--- OPTIONS FROM GALTLC.MSG ---*/

INT nswchx,                   /* max times can switch chans or on-off/15sec*/
    tlcovr,                   /* does the tele cc rate over-ride Forums'?  */
    tlcccr,                   /* teleconference credit consumption rate    */
    reqint,                   /* minimum interval bewteen requesting a user*/
    npaymx,                   /* max times can talk per session if no pay  */
    tinpsz,                   /* allowable input size for teleconference   */
    swtfrm;                   /* allow usrs to swt to & from Forum chans?  */

UINT maxfre;                       /* top freeloader telecon channel       */

CHAR *modkey,                      /* key req'd to moderate tele channels  */
     *unlkey;                      /* key req'd for unlimited tele use     */

static CHAR *somoth;          /* displaying names of users in telecon      */

VOID *pageCmdInfo;

VOID EXPORT
init__galtlc(VOID)            /* initialize teleconference module          */
{
     stzcpy(telecon.descrp,gmdnam("galtlc.mdf"),MNMSIZ);
     tlcstt=register_module(&telecon);
     tlcmb=opnmsg("galtlc.mcv");
     tlclst=(struct tlc *)alczer(nterms*sizeof(struct tlc));
     npaymx=numopt(NPAYMX,0,32767);
     nswchx=numopt(NSWCHX,1,32767);
     maxfre=(unsigned)lngopt(MAXFRE,1L,65535L);
     reqint=numopt(REQINT,0,32767);
     tinpsz=numopt(TINPSZ,1,255);
     tlcccr=numopt(TLCCCR,-32767,32767);
     tlcovr=ynopt(TLCOVR);
     somoth=stgopt(SOMOTH);
     swtfrm=(tlcovr || ynopt(SWTFRM));
     modkey=stgopt(MODKEY);
     unlkey=stgopt(UNLKEY);
     if (tjoinrou == NULL) {
          tjoinrou=joint;
     }
     rtkick(10,tlctck);
     inicstlc();
     pageCmdInfo=(VOID *)alczer(512);
}

VOID
joint(chan)                        /* join teleconference from other module*/
USHORT chan;
{
     tlcptr=&tlclst[usrnum];
     if (!(usrptr->flags&X2MAIN)) {
          tlcptr->flags|=RSTX2M;
          usrptr->flags|=X2MAIN;
     }
     tlcptr->retstt=usrptr->state;
     tlcptr->retsub=usrptr->substt;
     tlcptr->retrat=usrptr->crdrat;
     tlcptr->flags|=XTOOTH;
     tlcptr->channel=chan+1;
     usrptr->state=tlcstt;
     usrptr->substt=0;
     tlcinp();
}

GBOOL
tlcinp(VOID)                       /* main teleconferencing input handler  */
{
     LONG actchn;
     struct tlc *tp;
     INT chkres;
     CHAR *chn,*tpc;

     setmbk(tlcmb);
     tlcptr=&tlclst[usrnum];
     switch (usrptr->substt) {
     case 0:
          usrptr->substt=1;
          btumil(usrnum,tinpsz);
          btuxnf(usrnum,0,19);
          if (!(usrptr->flags&INVISB)) {
               outtlc(ENTTLC,ALLU,usrnum,-1,usaptr->userid,flgbyt(usrnum),NULL);
          }
          prfmsg(INTRO);
          tlcctx();
          if (tlcovr || !(tlcptr->flags&XTOOTH)) {
               usrptr->crdrat=tlcccr;
          }
          break;
     case 1:
          if (margc == 0) {
               tlcctx();
               break;
          }
          if (margc == 1) {
               if (sameas(margv[0],"?")
             || sameas(margv[0],"'?'")
             || sameas(margv[0],"\"?\"")
             || sameas(margv[0],"help")) {
                    prfmsg(TLCHLP);
                    break;
               }
               if (sameas(margv[0],"nopage")) {
                    (*spageset)(FALSE,FALSE);
                    break;
               }
               if (sameas(margv[0],"exit") || sameas(margv[0],"x")) {
                    if ((tlcptr->flags&JUSTEX) && !(usrptr->flags&OPCHAT)) {
                         prfmsg(NANNOY);
                         break;
                    }
                    tlcptr->flags|=JUSTEX;
                    if (!(usrptr->flags&INVISB)) {
                         outtlc(LVITLC,ALLU,usrnum,-1,usaptr->userid,NULL,NULL);
                    }
                    rmvcht(-1);
                    rstrxf();
                    if (tlcptr->flags&XTOOTH) {
                         tlcptr->channel=0;
                         if (tlcptr->flags&RSTX2M) {
                              usrptr->flags&=~X2MAIN;
                         }
                         tlcptr->flags&=~(XTOOTH+RSTX2M);
                         condex();
                         usrptr->state=tlcptr->retstt;
                         usrptr->substt=tlcptr->retsub;
                         usrptr->crdrat=tlcptr->retrat;
                         injacr();
                         return(TRUE);
                    }
                    return(FALSE);
               }
               if (sameas(margv[0],"scan")) {
                    prfmsg(NSCNHDR);
                    for (tp=tlclst,othusn=0 ; othusn < nterms ; tp++,othusn++) {
                         if (inscan(othusn,tp)) {
                              prf("%-30s... ",uacoff(othusn)->userid);
                              chn=scnchn(othusn,tp);
                              tpc=scntpc(tp);
                              if (sameas(chn,"(Chat)")) {
                                   prf("%s\r",chn);
                              }
                              else {
                                   if (tpc != NULL) {
                                        prf("%s%s%s\r",chn,
                                            sameas(chn,"(Unlisted)")
                                                   ? "  " : "       ",
                                            tpc);
                                   }
                                   else {
                                        prf("%s\r",chn);
                                   }
                              }
                         }
                    }
                    break;
               }
               if (sameas(margv[0],"unlist")) {
                    tlcptr->flags&=~SHWCHN;
                    tlcptr->flags|=LUISSU;
                    prfmsg(UNLSTC);
                    break;
               }
               if (sameas(margv[0],"list")) {
                    tlcptr->flags|=(SHWCHN+LUISSU);
                    prfmsg(LSTCHN);
                    break;
               }
          }
          if (margc <= 2) {
               if (sameas(margv[0],"channel")) {
                    if (margc == 1) {
                         prfmsg(WHATCH,tlcptr->channel+1);
                    }
                    else if (strlen(margv[1]) > 5) {
                         prfmsg(OUTORG);
                    }
                    else {
                         actchn=atol(margv[1]);
                         switch (chkres=chkchn(actchn)) {
                         case OUTORG:
                         case YOURCH:
                         case CANTLV:
                         case CANTGO:
                         case PRVLCH:
                         case NANNOY:
                              prfmsg(chkres);
                              break;
                         case PAYONL:
                              prfmsg(PAYONL,maxfre);
                              howbuy();
                              break;
                         case CHANOK:
                              swtchn(actchn);
                              tlcctx();
                              break;
                         }
                    }
                    break;
               }
          }
          if (sameas(margv[0],"squelch") || sameas(margv[0],"unsquelch")) {
               if (margc == 1) {
                    prfmsg(NUIHLP);
               }
               else {
                    rstrin();
                    squsqu(margv[1],sameto("squelch",margv[0]));
               }
               break;
          }
          if (sameas(margv[0],"appoint")) {
               if (margc == 1) {
                    prfmsg(NUIHLP);
               }
               else {
                    rstrin();
                    xfrmod(margv[1]);
               }
               break;
          }
          if (sameas(margv[0],"chat")) {
               chat();
               break;
          }
          if (sameas(margv[0],"page")) {
               (*hdlPageCmdRou)((*parsePageCmdRou)(NULL,pageCmdInfo),
                                pageCmdInfo);
               break;
          }
          if (ck4pfn() != NOPFN) {
               break;
          }
          if (sameas(margv[0],"moderate")) {
               if (urinv()) {
               }
               else if (margc == 1) {
                    xfrmod(NULL);
               }
               else if (tlcptr->channel == 0) {
                    prfmsg(NOMCH1);
               }
               else if (fidxst(tlcptr->channel)) {
                    prfmsg(NOOVRS);
               }
               else if (ck4mod(usrnum)) {
                    prfmsg(ANOMOD,uacoff(othusn)->userid);
               }
               else if (!haskey(modkey)) {
                    prfmsg(MODLIV);
                    howbuy();
               }
               else {
                    rstrin();
                    *(margv[1]+CTPSIZ-1)='\0';
                    strcpy(tlcptr->topic,margv[1]);
                    ntfyres(tlcptr->channel);
                    tlcptr->modchn=tlcptr->channel;
                    outtlc(BGNCON,ALLU,usrnum,-1,usaptr->userid,tlcptr->topic,NULL);
                    prfmsg(BMODER,tlcptr->topic);
               }
               break;
          }
          if (tlcptr->flags&SQUCHD) {
               prfmsg(TLKSQU);
               break;
          }
          if (!haskey(unlkey) && (tlcptr->inpcnt)++ >= npaymx) {
               prfmsg(NPAYXC,npaymx);
               howbuy();
               break;
          }
          if (urinv()) {
               break;
          }
          if (sameas(margv[0],"whisper")) {
               if (margc < 4) {
                    prfmsg(WHSFMT);
               }
               else {
                    whisper(margv[2],2);
               }
               break;
          }
          if (margv[0][0] == '/') {
               whisper(margv[0]+1,0);
               break;
          }
          rstrin();
          outtlc(NMTALK,ALLU,usrnum,-1,usaptr->userid,input,NULL);
          if (chncnt() == 1) {
               prfmsg(BYSELF,tlcptr->channel+1);
          }
          else {
               prfmsg(MSGSNT);
          }
          break;
     case 2:
          if (margc == 1 && sameas(margv[0],"x")) {
               xitcht(0);
          }
          return(TRUE);
     }
     if (usrptr->substt == 1 && *prfbuf != '\0') {
          prfmsg(TLCPMT);
     }
     outprf(usrnum);
     return(TRUE);
}

VOID
tlcctx(VOID)                       /* teleconference channel user display  */
{
     CHAR *curguy,tmpbuf[UIDSIZ+6];
     const CHAR *stp;
     UINT chan;

     initls();
     chan=tlclst[usrnum].channel+1;
     switch (chncnt()) {
     case 0:
     case 1:
          prfmsg(BYSELF,chan);
          break;
     case 2:
          prfmsg(ONEOTH,tlsrui(LSTSCH),chan);
          break;
     case 3:
          strcpy(tmpbuf,tlsrui(LSTSCH));
          prfmsg(TWOOTH,tmpbuf,tlsrui(LSTSCH),chan);
          break;
     default:
          strcpy(tmpbuf,tlsrui(LSTSCH));
          while ((curguy=tlsrui(LSTSCH)) != NULL) {
               prf(somoth,tmpbuf);
               strcpy(tmpbuf,curguy);
          }
          prfmsg(SEVOTH,tmpbuf,chan);
     }
     if (ck4mod(usrnum)) {
          prfmsg(CHNTPC,tptr->topic,uacoff(othusn)->userid);
     }
     else if ((stp=getftpc(tlcptr->channel)) != NULL) {
          prfmsg(STOPIC,stp);
     }
     if (tlcptr->modchn != 0) {
          if (tlcptr->channel == tlcptr->modchn) {
               prfmsg(URMODR,tlcptr->topic);
          }
          else {
               prfmsg(URMODO,tlcptr->modchn+1,tlcptr->topic);
          }
     }
     prfmsg(IROEPI);
}

static CHAR *
prspow(start,mnum,prec,count)      /* parse destination of some action     */
CHAR *start;
INT mnum,prec,*count;
{
     CHAR *msg;
     INT gobl,i;

     for (i=0 ; i < margc ; i++) {
          margn[i][0]='\0';
     }
     if ((*count=howmny(start,prec,0)) == 0) {
          msg=margn[mnum];
          if (*(msg-1) == ':') {
               *(msg-1)='\0';
               *count=howmny(start,prec,1);
               if (mnum != margc-1) {
                    msg++;
               }
          }
          else {
               msg="";
          }
          rstrin();
     }
     else if (*count == 1) {
          rstrin();
          for (i=mnum+1 ; i < margc ; i++) {
               msg=margn[i];
               if (*(msg-1) == ':') {
                    *(msg-1)='\0';
                    if (!sameto(start,othuap->userid)) {
                         *(msg-1)=':';
                    }
                    else {
                         i++;
                    }
                    break;
               }
               else {
                    *msg='\0';
                    gobl=sameto(start,othuap->userid);
                    if (i < margc-1) {
                         *msg=' ';
                    }
               }
               if (!gobl) {
                    break;
               }
          }
          msg=(i == margc ? "" : (CHAR *)margv[i]);
     }
     else {
          rstrin();
          if ((msg=strchr(start,':')) == NULL) {
               margn[mnum][0]='\0';
               *count=NEEDCO;
               msg="";
          }
          else {
               *msg='\0';
               if (*++msg != '\0') {
                    msg++;
               }
               *count=howmny(start,prec,1);
          }
     }
     return(msg);
}

static VOID
chat(VOID)                         /* "chat" function                      */
{
     rstrin();
     switch (chkcht(margc == 1 ? (CHAR *)"" : margv[1])) {
     case URINVS:
          break;
     case CHAFMT:
          prfmsg(CHAFMT);
          break;
     case WHSNHR:
          prfmsg(WHSNHR,margv[1]);
          break;
     case AMBIG:
          prfmsg(AMBIG,margv[1],"chat");
          break;
     case NCHSLF:
          prfmsg(NCHSLF);
          break;
     case NOCHCS2:
          prfmsg(NOCHCS2,othuap->userid,tlcsxp(othuap->sex));
          break;
     case ENTCHA:
          enttcht();
          break;
     case CHTOFF:
          prfmsg(CHTOFF,othuap->userid);
          break;
     case CHAL2M:
          prfmsg(CHAL2M,othuap->userid,(reqint+30)/60);
          break;
     case CHAREQ:
          reqcht();
          break;
     }
}

CHAR
tlchat(chan,ch)                    /* btuchi() chat routine, A/A->A/A      */
INT chan;
INT ch;
{
     INT oth;
     CHAR c;

     oth=tlclst[chan].chatch;
     c=((CHAR)ch)&eurmsk;
     switch (c) {
     case '\r':
          chiinp(oth,c);
          chiout(oth,c);
          chiout(oth,'\n');
          return(c);
     case '\b':
          chiinp(oth,c);
          chiout(oth,c);
          chiout(oth,' ');
          chiout(oth,c);
          return(c);
     default:
          if (c >= 32) {
               if (!(tlclst[chan].flags&TYPING)) {
                    if (uacoff(oth)->ansifl&ANSON) {
                         chious(oth,"\33[32m");
                    }
                    if (uacoff(chan)->ansifl&ANSON) {
                         chious(chan,"\33[33m");
                    }
                    tlclst[chan].flags|=TYPING;
                    tlclst[oth].flags&=~TYPING;
               }
               chiinp(oth,c);
               chiout(oth,c);
               return(c);
          }
     }
     return(0);
}

static VOID
whisper(                           /* "whisper" function                   */
CHAR *whoto,                       /*   uid to whisper to                  */
INT mnum)                          /*   idx into margv[] where msg starts  */
{
     INT count;
     CHAR *what;

     what=prspow(whoto,mnum,2,&count);
     if (count == NEEDCO) {
          prfmsg(PAMBIG,whoto,"whisper to");
     }
     else if (count == 0) {
          prfmsg(WHSNHR,whoto);
     }
     else if (count != 1) {
          prfmsg(AMBIG,whoto,"whisper");
     }
     else if (*what == '\0') {
          prfmsg(WHSFMT);
     }
     else {
          sndwsp(what);
     }
}

VOID
tlctck(VOID)                       /* real-time teleconference kicker      */
{
     struct tlc *tlcptr;

     for (usrnum=0,tlcptr=tlclst ; usrnum < nterms ; usrnum++,tlcptr++) {
          if (tlcptr->reqcha != 0) {
               tlcptr->reqcha--;
          }
          tlcptr->swchan=0;
          tlcptr->flags&=~JUSTEX;
          tlcptr->flags&=~JUSTDB;
     }
     rtkick(15,tlctck);
}

VOID
tlcfin(VOID)                       /* close teleconference files for shut  */
{
     clsmsg(tlcmb);
}
