/*************************************************************************
Conference Client written by Jeffrey A. Litz

litz@cs.uwp.edu  -or-  Jeff_Litz@EDTNG.Kenosha.WI.US

Copyright ©1994 JL Productions.
*************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/semaphores.h>

#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>

#include <workbench/workbench.h>
#include <workbench/startup.h>

#include <dos/dostags.h>

#include <libraries/gadtools.h>

#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>

#include <utility/tagitem.h>

#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/dos_protos.h>
#include <clib/nipc_protos.h>
#include <clib/services_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/icon_protos.h>

#include <devices/timer.h>

#include <envoy/nipc.h>
#include <envoy/services.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/nipc_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/services_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/utility_pragmas.h>

#include <string.h>

#include "conf.h"

static UBYTE version[32] = {"$VER: Conference Client v1.12"};

extern KPrintF(STRPTR,...);

extern long SetupScreen(void);
extern void CloseDownScreen(void);
extern void Project0Render(void);
extern long OpenProject0Window(void);
extern void CloseProject0Window(void);
extern UBYTE ProcessError(ULONG);
extern void BusyOn(void);
extern void BusyOff(void);
extern void FreeCList(void);
extern void FreeMList(void);
extern void TalkConf(void);
extern UBYTE StartTalk(ULONG);
extern struct List *Get_Conference_List(UBYTE *);
extern void _main(void);
extern void Send_PrivateMsg(void);
extern void Send_ToggleMode(void);
extern void Process_CLI(ULONG);
extern struct Node *CFindName(struct List *, STRPTR);

// oopss... should go in conf.h

ULONG pending=0;




/*
** The "main guts" of the program.  Handles the WorkBench and Shell
** interface.
*/

void _main(void)
{
   struct List *conf_list,*memb_list;
   struct Node *ln;

   struct c_membnode *current_ln;
   struct c_worknode *ln2;
   
   struct IntuiMessage *mess;

/*
** not implemented yet
** UBYTE machine_name[32];
*/

   void *entity;
   ULONG args[4];
   UBYTE done=0;
   struct RDArgs *lpargs;
   ULONG Code,MClass;
   UWORD GADID;
   ULONG loop;
   UBYTE host_name[32];
   struct MsgPort *ConfPort;
   struct Message *ConfMsg;
   struct WBStartup *wbmsg;
   struct WBArg *wbarg;
   char **toolarray;
   char *s;
   struct DiskObject *dobj;
   LONG olddir;
   struct Gadget *gad;
   struct TagItem cbtags[2];
   struct c_membnode *flag_node;

   geta4();

   cbtags[0].ti_Tag=ENT_AllocSignal;
   cbtags[0].ti_Data=NULL;
   cbtags[1].ti_Tag=TAG_END;
   cbtags[1].ti_Data=NULL;

   SysBase=*((struct Library **)4L);

   myproc = (struct Process *) FindTask(0L);
   if(!myproc->pr_CLI)
   {
      /* do workbench startup */
   
      WaitPort(&myproc->pr_MsgPort);
      wbmsg=(struct WBStartup *)GetMsg(&myproc->pr_MsgPort);
   }

   NewList(&c_worklist);
   NewList(&c_memblist);
   GLB_Error=0;

   if(UtilityBase=OpenLibrary("utility.library",37L))
   {
      if (DOSBase = OpenLibrary("dos.library", 37L))
      {
         if (NIPCBase = OpenLibrary("nipc.library", 0L))
         {  
            if (ServicesBase = OpenLibrary("services.library", 37L))
            {
               args[0]=args[1]=args[2]=args[3]=0;
               
               if(lpargs = ReadArgs("Conference,Host/K,LIST/S,Alias/K",args,NULL))
               {
                  if(ConfPort=CreateMsgPort())
                  {
   
// create a unique message port that can be found...  slight overkill
                     
                     sprintf(Conf_Port_Name,"%ld_Conf_Port",myproc);
                     ConfPort->mp_Node.ln_Name=Conf_Port_Name;
                     ConfPort->mp_Node.ln_Pri=1;
                     AddPort(ConfPort);

                     if(GetVar("ConferenceHost",conf_host,31,GVF_GLOBAL_ONLY) == -1)
                        conf_host[0]=0;

                     if(GetVar("ConferenceAlias",alias,31,GVF_GLOBAL_ONLY) == -1)
                        alias[0]=0;
         
                     if(!myproc->pr_CLI)
                     {
                        /* Process Tool Types */
      
                        if(IconBase=OpenLibrary("icon.library",37l))
                        {
                           wbarg=wbmsg->sm_ArgList;
                           olddir=-1;
                           if((wbarg->wa_Lock) && (*wbarg->wa_Name))
                           {
                              olddir=CurrentDir(wbarg->wa_Lock);
                           }
                           if((*wbarg->wa_Name) && (dobj=GetDiskObject(wbarg->wa_Name)))
                           {
                              toolarray=(char **)dobj->do_ToolTypes;
                              if(s=(char *)FindToolType(toolarray,"Host"))
                              {
                                 strcpy(conf_host,s);
                                 args[1]=(ULONG)&conf_host[0];
                              }
                              if(s=(char *)FindToolType(toolarray,"Alias"))
                              {
                                 strcpy(alias,s);
                                 args[3]=(ULONG)&alias[0];
                              }
                              FreeDiskObject(dobj);
                           } else if(olddir != -1)
                           {
                              CurrentDir(olddir);
                           }
                           CloseLibrary(IconBase);
                        }   
                     }

                     if(args[0])
                        strcpy(conf_name,(UBYTE *)args[0]);
                     if(args[1])
                        strcpy(conf_host,(UBYTE *)args[1]);
                     if(args[3])
                        strcpy(alias,(UBYTE *)args[3]);
                        
                     if(entity = CreateEntityA((struct TagItem *) cbtags))
                     {
                        GetHostName(entity,host_name,31);
                        DeleteEntity(entity);
                        if(!alias[0])
                           strcpy(alias,host_name);
                     }
                     else
                        strcpy(host_name,""); 
                     if(!myproc->pr_CLI)
                     {
                        if(IntuitionBase=OpenLibrary("intuition.library",37L))
                        {
                           if(GadToolsBase=OpenLibrary("gadtools.library",37L))
                           {
                              if(!SetupScreen())
                              {
                                 if(!OpenProject0Window())
                                 {
                                    InitRequester(&null_request);
   
                                    if(alias[0])
                                       GT_SetGadgetAttrs(Project0Gadgets[7],Project0Wnd,NULL, GTST_String, alias, TAG_DONE);
                                    if(conf_host[0])
                                    {
                                       GT_SetGadgetAttrs(Project0Gadgets[6],Project0Wnd,NULL, GTST_String, conf_host, TAG_DONE);
                                       GT_SetGadgetAttrs(Project0Gadgets[4],Project0Wnd,NULL,GA_Disabled,FALSE,TAG_DONE);
                                       GT_SetGadgetAttrs(Project0Gadgets[3],Project0Wnd,NULL,GA_Disabled,FALSE,TAG_DONE);
                                       GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                       conf_list=Get_Conference_List(NULL);
                                       GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,conf_list,TAG_END);
                                       ProcessError(GLB_Error);
                                    }
                                    while(!done)
                                    {
                                       Wait((1<<Project0Wnd->UserPort->mp_SigBit) | (1<<ConfPort->mp_SigBit));
                                       while((!done) && (mess=GT_GetIMsg(Project0Wnd->UserPort)))
                                       {
                                          gad=(struct Gadget *)mess->IAddress;
                                          Code=mess->Code;
                                          MClass=mess->Class;
                                          GT_ReplyIMsg(mess);
                                          switch(MClass)
                                          {
                                             case IDCMP_GADGETUP:
                                                GADID=gad->GadgetID;
                                                switch(GADID)
                                                {
                                                   case GD_Gadget00:
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled, FALSE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled, FALSE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                      for(ln=c_worklist.lh_Head,loop=0;((ln->ln_Succ) && (loop<Code));++loop,ln=ln->ln_Succ);
                                                      strcpy(conf_name,ln->ln_Name);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL, GTST_String, conf_name, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                      memb_list=Get_Conference_List(conf_name);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels,memb_list,TAG_END);
                                                      ProcessError(GLB_Error);
                                                      break;
                                                   case GD_Gadget10:
                                                      strcpy(conf_name,((struct StringInfo *)Project0Gadgets[1]->SpecialInfo)->Buffer);
                                                      if(strlen(conf_name))
                                                      {
                                                         StartTalk(TKCMD_CONFERENCE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String, NULL, TAG_DONE);
                                                         if(GLB_Error)
                                                         {
                                                            GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                            GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                            ProcessError(GLB_Error);
                                                         }
                                                         else
                                                         {
                                                            GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                            conf_list=Get_Conference_List(NULL);
                                                            GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,conf_list,TAG_END);
                                                            GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                            memb_list=Get_Conference_List(conf_name);
                                                            GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels,memb_list,TAG_END);
                                                         }
                                                      }
                                                      else
                                                      {
                                                         GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String, NULL, TAG_DONE);
                                                      }
                                                      break;
                                                   case GD_Gadget20:
                                                      GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      StartTalk(TKCMD_CONFERENCE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                      memb_list=Get_Conference_List(conf_name);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels,memb_list,TAG_END);
                                                      ProcessError(GLB_Error);
                                                      break;
                                                   case GD_Gadget30:
                                                      GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, NULL, TAG_END);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, FALSE, GTST_String, NULL, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      ActivateGadget(Project0Gadgets[1],Project0Wnd,NULL);
                                                      break;
                                                   case GD_Gadget40:
                                                      GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                      conf_list=Get_Conference_List(NULL);
                                                      GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,conf_list,TAG_END);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, NULL, TAG_END);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GTST_String,NULL,TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[3],Project0Wnd,NULL,GA_Disabled, FALSE, TAG_DONE);
                                                      ProcessError(GLB_Error);
                                                      break;
                                                   case GD_Gadget50:
                                                      GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                      memb_list=Get_Conference_List(conf_name);
                                                      GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels,memb_list,TAG_END);
                                                      ProcessError(GLB_Error);
                                                      break;
                                                   case GD_Gadget60:
                                                      strcpy(conf_host,((struct StringInfo *)Project0Gadgets[6]->SpecialInfo)->Buffer);
                                                      GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                                      conf_list=Get_Conference_List(NULL);
                                                      GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,conf_list,TAG_END);
                                                      if(GLB_Error)
                                                      {
                                                         GT_SetGadgetAttrs(Project0Gadgets[4],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[3],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GTST_String,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled,TRUE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels,NULL,TAG_END);
                                                         GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,NULL,TAG_END);
                                                         ProcessError(GLB_Error);
                                                      }
                                                      else
                                                      {
                                                         GT_SetGadgetAttrs(Project0Gadgets[4],Project0Wnd,NULL,GA_Disabled,FALSE,TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[3],Project0Wnd,NULL,GA_Disabled,FALSE,TAG_DONE);
                                                      }
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String, NULL, TAG_DONE);
                                                      break;
                                                   case GD_Gadget70:
                                                      strcpy(alias,((struct StringInfo *)Project0Gadgets[7]->SpecialInfo)->Buffer);
                                                      break;
                                                   case GD_Gadget80:
                                                      for(ln=c_memblist.lh_Head,loop=0;((ln->ln_Succ) && (loop<Code));++loop,ln=ln->ln_Succ);
                                                      strcpy(machine_name,((struct c_membnode *)ln)->name);
   
                                                      if(CFindName(&c_memblist,alias))
                                                      {
                                                         /* If I'm in the list... */
                                                         
                                                         if(!Stricmp(machine_name,host_name))
                                                         {
                                                             /* Hey - I selected myself!!! */
   
                                                             GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                             GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                             GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                             GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, GTCY_Active,0,TAG_DONE);
                                                         } else
                                                         {
                                                             /* Hey - I selected someone else!!! */
                                                             
                                                             if(flag_node=(struct c_membnode *)CFindName(&c_memblist,machine_name))
                                                             {
                                                                 GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, FALSE, TAG_DONE);
                                                                 GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, FALSE, GTCY_Active,flag_node->flags,TAG_DONE);
                                                             } else
                                                             {
                                                                 GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                                 GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, GTCY_Active,0,TAG_DONE);
                                                             }
                                                             GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                             GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                        }
                                                      }
                                                      else
                                                      {
                                                         /* Hey - I not even in the conference!!! Disable ALL */
                                                         
                                                         GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL, TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                         GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, GTCY_Active,0,TAG_DONE);
                                                      }
                                                      break;
                                                   case GD_Gadget90:
                                                      GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String,NULL,TAG_DONE);
   
                                                      cycle_mode=Code;
                                                      Send_ToggleMode();
   
                                                      if(flag_node=(struct c_membnode *)CFindName(&c_memblist,machine_name))
                                                      {
                                                          flag_node->flags=cycle_mode;
                                                      }
   
                                                      break;
                                                   case GD_Gadget100:
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, FALSE, GTST_String, NULL, TAG_DONE);
                                                      ActivateGadget(Project0Gadgets[11],Project0Wnd,NULL);
                                                      break;
                                                   case GD_Gadget110:
                                                      strcpy(pri_msg,((struct StringInfo *)Project0Gadgets[11]->SpecialInfo)->Buffer);
                                                      GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled, TRUE, GTST_String, NULL, TAG_DONE);
                                                      Send_PrivateMsg();
                                                      break;
                                                }
                                                break;
                                             case IDCMP_CLOSEWINDOW:
                                                done=1;
                                                break;
                                          }
                                       }
                                       if(ConfMsg=GetMsg(ConfPort))
                                       {
                                          GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels, ~0, TAG_END);
                                          conf_list=Get_Conference_List(NULL);
                                          GT_SetGadgetAttrs(Project0Gadgets[0],Project0Wnd,NULL,GTLV_Labels,conf_list,TAG_END);
                                          GT_SetGadgetAttrs(Project0Gadgets[8],Project0Wnd,NULL,GTLV_Labels, NULL, TAG_END);
                                          GT_SetGadgetAttrs(Project0Gadgets[1],Project0Wnd,NULL,GA_Disabled,TRUE,GTST_String,NULL,TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[5],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[9],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[2],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[3],Project0Wnd,NULL,GA_Disabled, FALSE, TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[11],Project0Wnd,NULL,GA_Disabled,TRUE,GTST_String,NULL,TAG_DONE);
                                          GT_SetGadgetAttrs(Project0Gadgets[10],Project0Wnd,NULL,GA_Disabled, TRUE, TAG_DONE);
                                          ProcessError(GLB_Error);
                                       }
                                    }
                                 }
                                 CloseProject0Window();
                              }
                              CloseDownScreen();
                           }
                           CloseLibrary(GadToolsBase);
                        }
                        CloseLibrary(IntuitionBase);
                     }
                     else
                     {
                        if(!strlen(conf_host))
                           FPrintf(Output(),"\nConference host name not supplied.\n\n");
                        else
                        {
                           if(args[2])
                           {
                              if(!strlen(conf_name))
                              {
                                 conf_list=Get_Conference_List(NULL);
                                 if(!GLB_Error)
                                 {
                                   if(conf_list)
                                   {
                                    FPrintf(Output(),"\nAvailable conferences on %s\n",conf_host);
                                    for(ln=conf_list->lh_Head;ln->ln_Succ;ln=ln->ln_Succ)
                                    {
                                       ln2=(struct c_worknode *)ln;
                                       FPrintf(Output(),"%s\n",ln2->name);
                                    }
                                   } else
                                   {
                                    FPrintf(Output(),"\nNo conferences available on %s\n",conf_host);
                                   }
                                 }
                                 else
                                    Process_CLI(GLB_Error);
                              }
                              else
                              {
                                 memb_list=Get_Conference_List(conf_name);
                                 if(!GLB_Error)
                                 {
                                    if(memb_list)
                                    {
                                           FPrintf(Output(),"Users in conference %s on %s\n",conf_name,conf_host);
                                            for(ln=memb_list->lh_Head;ln->ln_Succ;ln=ln->ln_Succ)
                                            {
                                               current_ln=(struct c_membnode *)ln;
                                               FPrintf(Output(),"%-32s - %-32s\n",current_ln->name,current_ln->alias);
                                            }
                                    } else
                                    {
                                           FPrintf(Output(),"\n%s conference does not exist on %s\n",conf_name,conf_host);
                                    }
                                 }
                                 else
                                    Process_CLI(GLB_Error);
                              }
                           }
                           else
                           {
                              if(strlen(conf_name))
                              {
                                 StartTalk(TKCMD_CONFERENCE);
                                 if(GLB_Error)
                                 {
                                    Process_CLI(GLB_Error);
                                 }
                              }
                              else
                                 FPrintf(Output(),"\nConference name not supplied.\n");
                           }
                           FPrintf(Output(),"\n");
                        }
                     }
                     FreeCList();
                     FreeMList();
                     while(pending)
                     {
                        Wait(1<<ConfPort->mp_SigBit);
                     }
                     RemPort(ConfPort);
                     DeleteMsgPort(ConfPort);
                  }   
                  FreeArgs(lpargs);
               }
               CloseLibrary(ServicesBase);
            }
            CloseLibrary(NIPCBase);
         }
         CloseLibrary(DOSBase);
      }
      CloseLibrary(UtilityBase);
   }
   if(!myproc->pr_CLI)
   {
      Forbid();
      ReplyMsg((struct Message *)wbmsg);
   }
}




/**************************************************************************
User Interface Created with GadToolsBox - will be replaced with my font
sensitive layout engine some day if I find a practical use for this
program.
**************************************************************************/

long SetupScreen( void )
{
    if ( NOT( Scr = LockPubScreen( NULL )))
        return( 1L );

    if ( NOT( VisualInfo = GetVisualInfo( Scr, TAG_DONE )))
        return( 2L );

    return( NULL );
}

void CloseDownScreen( void )
{
    if ( VisualInfo ) {
        FreeVisualInfo( VisualInfo );
        VisualInfo = NULL;
    }

    if ( Scr        ) {
        UnlockPubScreen( NULL, Scr );
        Scr = NULL;
    }
}

void Project0Render( void )
{
    UWORD        offx, offy;

    offx = Project0Wnd->BorderLeft;
    offy = Project0Wnd->BorderTop;

    PrintIText( Project0Wnd->RPort, Project0IText, offx, offy );
}

long OpenProject0Window( void )
{
    struct NewGadget     ng;
    struct Gadget       *g;
    UWORD               offx, offy;

    offx = Scr->WBorLeft;
    offy = Scr->WBorTop + Scr->RastPort.TxHeight + 1;

    if ( NOT( g = CreateContext( &Project0GList )))
        return( 1L );

    ng.ng_LeftEdge        =    offx + 16;
    ng.ng_TopEdge         =    offy + 16;
    ng.ng_Width           =    233;
    ng.ng_Height          =    125;
    ng.ng_GadgetText      =    (UBYTE *)"Conference";
    ng.ng_TextAttr        =    &topaz8;
    ng.ng_GadgetID        =    GD_Gadget00;
    ng.ng_Flags           =    PLACETEXT_ABOVE|NG_HIGHLABEL;
    ng.ng_VisualInfo      =    VisualInfo;

    g = CreateGadget( LISTVIEW_KIND, g, &ng, GTLV_Labels, NULL, TAG_DONE );

    Project0Gadgets[ 0 ] = g;

    ng.ng_TopEdge         =    offy + 140;

// Layout Fix!!
// ng.ng_Height          =    13;

    ng.ng_Height = 14;
    ng.ng_GadgetText      =    NULL;
    ng.ng_GadgetID        =    GD_Gadget10;
    ng.ng_Flags           =    0;

    g = CreateGadget( STRING_KIND, g, &ng, GTST_MaxChars, 256, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 1 ] = g;

    ng.ng_TopEdge         =    offy + 154;
    ng.ng_Width           =    117;
    ng.ng_Height          =    15;
    ng.ng_GadgetText      =    (UBYTE *)"Enter";
    ng.ng_GadgetID        =    GD_Gadget20;

    g = CreateGadget( BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 2 ] = g;

    ng.ng_LeftEdge        =    offx + 133;
    ng.ng_Width           =    116;
    ng.ng_GadgetText      =    (UBYTE *)"Create";
    ng.ng_GadgetID        =    GD_Gadget30;

    g = CreateGadget( BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 3 ] = g;

    ng.ng_LeftEdge        =    offx + 16;
    ng.ng_TopEdge         =    offy + 169;
    ng.ng_Width           =    117;
    ng.ng_GadgetText      =    (UBYTE *)"List";
    ng.ng_GadgetID        =    GD_Gadget40;

    g = CreateGadget( BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 4 ] = g;

    ng.ng_LeftEdge        =    offx + 133;
    ng.ng_Width           =    116;
    ng.ng_GadgetText      =    (UBYTE *)"Members";
    ng.ng_GadgetID        =    GD_Gadget50;

    g = CreateGadget( BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 5 ] = g;

    ng.ng_LeftEdge        =    offx + 321;
    ng.ng_TopEdge         =    offy + 16;
    ng.ng_Width           =    229;
    ng.ng_Height = 14;
    ng.ng_GadgetText      =    (UBYTE *)"Host";
    ng.ng_GadgetID        =    GD_Gadget60;
    ng.ng_Flags           =    PLACETEXT_LEFT;

    g = CreateGadget( STRING_KIND, g, &ng, GTST_MaxChars, 256, TAG_DONE );

    Project0Gadgets[ 6 ] = g;

    ng.ng_TopEdge         =    offy + 37;
    ng.ng_GadgetText      =    (UBYTE *)"Alias";
    ng.ng_GadgetID        =    GD_Gadget70;

    g = CreateGadget( STRING_KIND, g, &ng, GTST_MaxChars, 256, TAG_DONE );

    Project0Gadgets[ 7 ] = g;

    ng.ng_LeftEdge        =    offx + 276;
    ng.ng_TopEdge         =    offy + 72;
    ng.ng_Width           =    275;
    ng.ng_Height          =    81;
    ng.ng_GadgetText      =    (UBYTE *)"Members of Conference";
    ng.ng_GadgetID        =    GD_Gadget80;
    ng.ng_Flags           =    PLACETEXT_ABOVE|NG_HIGHLABEL;

    g = CreateGadget( LISTVIEW_KIND, g, &ng, GTLV_Labels, NULL, GTLV_ShowSelected, NULL, TAG_DONE );

    Project0Gadgets[ 8 ] = g;

    ng.ng_TopEdge         =    offy + 152;
    ng.ng_Width           =    139;
    ng.ng_Height          =    15;
    ng.ng_GadgetText      =    NULL;
    ng.ng_GadgetID        =    GD_Gadget90;
    ng.ng_Flags           =    0;

    g = CreateGadget( CYCLE_KIND, g, &ng, GTCY_Active,0,GTCY_Labels, &Gadget900Labels[0], GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 9 ] = g;

    ng.ng_LeftEdge        =    offx + 415;
    ng.ng_Width           =    136;
    ng.ng_GadgetText      =    (UBYTE *)"Private Msg";
    ng.ng_GadgetID        =    GD_Gadget100;
    ng.ng_Flags           =    PLACETEXT_IN;

    g = CreateGadget( BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 10 ] = g;

    ng.ng_LeftEdge        =    offx + 276;
    ng.ng_TopEdge         =    offy + 167;
    ng.ng_Width           =    275;
    ng.ng_Height = 14;
    ng.ng_GadgetText      =    NULL;
    ng.ng_GadgetID        =    GD_Gadget110;
    ng.ng_Flags           =    0;

    g = CreateGadget( STRING_KIND, g, &ng, GTST_MaxChars, 256, GA_Disabled, TRUE, TAG_DONE );

    Project0Gadgets[ 11 ] = g;

    if ( NOT g )
        return( 2L );

    if ( NOT( Project0Wnd = OpenWindowTags( NULL,
                    WA_Left,          Project0Left,
                    WA_Top,           Project0Top,
                    WA_Width,         Project0Width,
                    WA_Height,        Project0Height + offy,
                    WA_IDCMP,         LISTVIEWIDCMP|STRINGIDCMP|BUTTONIDCMP|CYCLEIDCMP|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
                    WA_Flags,         WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH,
                    WA_Gadgets,       Project0GList,
                    WA_Title,         Project0Wdt,
                    WA_ScreenTitle,   "Conference v1.0",
                    WA_PubScreen,     Scr,
                        TAG_DONE )))
        return( 4L );

    GT_RefreshWindow( Project0Wnd, NULL );

    Project0Render();

    return( NULL );
}

void CloseProject0Window( void )
{
    if ( Project0Wnd        ) {
        CloseWindow( Project0Wnd );
        Project0Wnd = NULL;
    }

    if ( Project0GList      ) {
        FreeGadgets( Project0GList );
        Project0GList = NULL;
    }
}




// Process error code passed to it
// Could be optimized...

UBYTE ProcessError(ULONG error)
{
   UBYTE answer;
   struct EasyStruct es = {sizeof(struct EasyStruct),0,"Conference Request",NULL,"Cancel"};
      
   temp_request=Request(&null_request,Project0Wnd);
   if(error == 1)
   {
      es.es_TextFormat="General Error";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error == 2)
   {
      es.es_TextFormat="Unable to find conference\nservice and host";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error == 3)
   {
      es.es_TextFormat="Already in this conference!";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error == 4)
   {
      es.es_TextFormat="Conference doesn't exist anymore.";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error == 5)
   {
      es.es_TextFormat="Conference already exists!";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error == 13)
   {
      es.es_TextFormat="Server couldn't finish request!";
      answer=EasyRequest(NULL,&es,NULL,NULL,NULL);
   }
   else if(error & 0x10000)
   {
      es.es_TextFormat="Transaction failure: %ld";
      answer=EasyRequest(NULL,&es,NULL,(error & 0x0ffff),NULL);
   }
   if(temp_request)
      EndRequest(&null_request,Project0Wnd);
   return(answer);
}         



// Should be combined with ProcessError()
 
void Process_CLI(ULONG error)
{
   UBYTE string[80];
   
   if(error == 1)
   {
      strcpy(string,"General Error.");
   }
   else if(error == 2)
   {
      strcpy(string,"Unable to find conference service and host.");
   }
   else if(error == 3)
   {
      strcpy(string,"Already in this conference!");
   }
   else if(error == 4)
   {
      strcpy(string,"Conference doesn't exist anymore.");
   }
   else if(error == 5)
   {
      strcpy(string,"Conference already exists!");
   }
   else if(error = 13)
   {
      strcpy(string,"Server couldn't finish request!");
   }
   else if(error & 0x10000)
   {
      sprintf(string,"Transaction failure: %ld",(error & 0x0ffff));
   }
   FPrintf(Output(),"\n%s\n\n",string);
}         



/* Turn on busy pointer */

void BusyOn(void)
{
   extern UWORD __chip waitPointer[];
   
   if(!myproc->pr_CLI)
   {
      temp_request=Request(&null_request,Project0Wnd);
      SetPointer(Project0Wnd,waitPointer,16,16,-6,0);
   }
}



/* Turn off busy pointer */

void BusyOff(void)
{
   extern UWORD __chip waitPointer[];
   
   if(!myproc->pr_CLI)
   {
      ClearPointer(Project0Wnd);
      if(temp_request)
         EndRequest(&null_request,Project0Wnd);
   }
}

   

/* Free up the conference list */

void FreeCList(void)
{
   struct Node *ln;
   
   while(ln=RemHead(&c_worklist))
      FreeMem(ln,sizeof(struct c_worknode));
   NewList(&c_worklist);
}



/* Free up the member list of a conference */

void FreeMList(void)
{
   struct Node *ln;
   
   while(ln=RemHead(&c_memblist))
      FreeMem(ln,sizeof(struct c_membnode));
   NewList(&c_memblist);
}




/*
** Attempts to startup a conference.  If successful, it opens an input
** and output window for that conference.
**
** Error Code (in GLB_Error):
**
** 1 - General failure
** 2 - Unable to find host/serivce
** 0x10000 - Transaction error
**
**
**
** Poor choice to use global vars with a routine that's called multiple
** times simulatenously.
**
*/

void TalkConf(void)
{
   struct Transaction *trans,*a_trans;
   void *entity,*dest,*a_entity;
   UBYTE host_name[32],work_space[512],userinput[256];
   BPTR input_w,output_w;
   struct MsgPort *port,*replyport,*Conf_Port;
   struct StandardPacket *packet;
   UBYTE done=0;
   ULONG error;
   ULONG waitmask,signal,howmany,m_id,sigbit=0;
   struct TagItem cetags[4];
   struct TagItem cbtags[2];
   struct TagItem ttags[3];


   geta4();
   
   cetags[0].ti_Tag=ENT_Name;
   cetags[0].ti_Data=NULL;
   cetags[1].ti_Tag=ENT_Public;
   cetags[1].ti_Data=NULL;
   cetags[2].ti_Tag=ENT_AllocSignal;
   cetags[2].ti_Data=NULL;
   cetags[3].ti_Tag=TAG_END;
   cetags[3].ti_Data=NULL;

   cbtags[0].ti_Tag=ENT_AllocSignal;
   cbtags[0].ti_Data=NULL;
   cbtags[1].ti_Tag=TAG_END;
   cbtags[1].ti_Data=NULL;
   
   ttags[0].ti_Tag=TRN_AllocReqBuffer;
   ttags[0].ti_Data=516;
   ttags[1].ti_Tag=TRN_AllocRespBuffer;
   ttags[1].ti_Data=4;
   ttags[2].ti_Tag=TAG_END;
   ttags[2].ti_Data=NULL;
   
   error=1;
   if(entity = CreateEntityA((struct TagItem *) cbtags))
   {
      error=2;
      if(dest = FindServiceA(conf_host, "Conf_Service", entity, NULL))
      {
         error=1;
         if(trans = AllocTransactionA((struct TagItem *) ttags))
         {
            cetags[2].ti_Data=(ULONG) &sigbit;
            cetags[0].ti_Data=(ULONG) conf_name;
            if(a_entity=CreateEntityA((struct TagItem *) cetags))
            {
               GetHostName(entity,host_name,31);
               strcpy(((UBYTE *)trans->trans_RequestData+4),conf_name);
               strcpy(((UBYTE *)trans->trans_RequestData+36),host_name);
               strcpy(((UBYTE *)trans->trans_RequestData+68),alias);
               trans->trans_ReqDataActual=strlen(alias)+69;
               trans->trans_Command=TKCommand;
               trans->trans_Timeout=10;
               DoTransaction(dest,entity,trans);

               error=trans->trans_Error | 0x10000;

               if(!trans->trans_Error)
               {
                  error=1;
                  m_id=*(ULONG *)trans->trans_ResponseData;

                  /*
                  if(alias[0])
                  {
                     strcpy(host_name,alias);
                  }
                  */
                  
                  sprintf(work_space,"CON:0/0/640/150/Output - %s",conf_name);
                  if(output_w=(BPTR)Open(work_space,MODE_NEWFILE))
                  {
                        
                     //sprintf(work_space,"ID #: %ld\n\n",m_id);
                     //Write(output_w,work_space,strlen(work_space));

                     sprintf(work_space,"CON:0/150/640/50/Input - %s/CLOSE",conf_name);
                     if(input_w=(BPTR)Open(work_space,MODE_NEWFILE))
                     {
                        if(packet=(struct StandardPacket *)AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR))
                        {
                           port=(struct MsgPort *) (((struct FileHandle *)((ULONG)input_w<<2))->fh_Type);
                           if(replyport=(struct MsgPort *) CreateMsgPort())
                           {
                              ++pending;
                              error=0;
                              GLB_Error=error;
                              Signal(TKProc, TKSignalMask);                                                           

// broadcast that you've entered the conference - could be optimized

                              sprintf(work_space,"[%s has entered.]\n",alias);
                              Write(output_w,work_space,strlen(work_space));
                              trans->trans_Command=TKCMD_CONDATA;
                              strcpy(((UBYTE *)trans->trans_RequestData+4),work_space);
                              *(ULONG *)trans->trans_RequestData=m_id;
                              trans->trans_ReqDataActual=strlen(work_space)+5;
                              trans->trans_Timeout=10;
                              DoTransaction(dest,entity,trans);

// process trans failure!!!
// Not very critical...

                              packet->sp_Msg.mn_Node.ln_Name=(char *)&(packet->sp_Pkt);
                              packet->sp_Pkt.dp_Link=&(packet->sp_Msg);
                              packet->sp_Pkt.dp_Port=replyport;
                              packet->sp_Pkt.dp_Type=ACTION_WAIT_CHAR;
                              packet->sp_Pkt.dp_Arg1=34000;
                              SendPkt(&packet->sp_Pkt,port,replyport);
                                             
                              waitmask = (1<<replyport->mp_SigBit) | (1<<sigbit);

                              while(!done)
                              {
                                 signal = Wait(waitmask);
                                 
                                 if(signal & (1<<replyport->mp_SigBit))
                                 { 
                                    if(GetMsg(replyport))
                                    {
                                       if(packet->sp_Pkt.dp_Res1)
                                       {
                                          if(!(howmany=Read(input_w,userinput,255)))
                                          {

// broadcast that you're leaving the conference - could be optimized

                                             sprintf(work_space,"[%s has exited.]\n",alias);
                                             Write(output_w,work_space,strlen(work_space));
                                             trans->trans_Command=TKCMD_CONDATA;
                                             strcpy(((UBYTE *)trans->trans_RequestData+4),work_space);
                                             *(ULONG *)trans->trans_RequestData=m_id;
                                             trans->trans_ReqDataActual=strlen(work_space)+5;
                                             trans->trans_Timeout=10;
                                             DoTransaction(dest,entity,trans);
// process trans failure!!!
// Not very critical

                                             done=2;
                                          }
                                          else
                                          {
                                             if(howmany)
                                             {
                                                if(userinput[howmany-1] == '\n')
                                                {
                                                    --howmany;
                                                }
                                             }
                                             userinput[howmany]=0;
 
                                             sprintf(work_space,"(%s) %s\n",alias,userinput);

                                             Write(output_w,work_space,strlen(work_space));
                                             
                                             trans->trans_Command=TKCMD_CONDATA;
                                             strcpy(((UBYTE *)trans->trans_RequestData+4),work_space);
                                             *(ULONG *)trans->trans_RequestData=m_id;
                                             trans->trans_ReqDataActual=strlen(work_space)+5;
                                             trans->trans_Timeout=10;
                                             DoTransaction(dest,entity,trans);
// Process a transaction failure!!!                                             
// Not very critical

                                          }
                                       }
                                       packet->sp_Pkt.dp_Port=replyport;
                                       packet->sp_Pkt.dp_Type=ACTION_WAIT_CHAR;
                                       packet->sp_Pkt.dp_Arg1=34000;
                                       SendPkt(&packet->sp_Pkt,port,replyport);
                                    }
                                 }
                                 
                                 if(signal & (1<<sigbit))
                                 {
                                    if(a_trans=GetTransaction(a_entity))
                                    {
                                       if(a_trans->trans_Command == TKCMD_CONDATA)
                                       {
                                          Write(output_w,(UBYTE *)((UBYTE *)a_trans->trans_RequestData+4),a_trans->trans_ReqDataActual-4);
                                       }
                                       else if(a_trans->trans_Command == TKCMD_ABORT)
                                          done=1;
                                       ReplyTransaction(a_trans);
                                    }
                                 }
                              }
                              --pending;
                              while((ULONG *)GetMsg(replyport) != (ULONG *)&packet->sp_Msg);
                              DeleteMsgPort(replyport);
                           }
                           FreeMem(packet,(long)sizeof(struct StandardPacket));
                        }
                        Close(input_w);
                     }
                     Close(output_w);
                  }
                  if(done == 2)
                  {
                     trans->trans_ReqDataActual=4;
                     trans->trans_Command=TKCMD_CONEND;
                     *(ULONG *)trans->trans_RequestData=m_id;
                     trans->trans_Timeout=10;
                     DoTransaction(dest,entity,trans);
                  }
               }
               DeleteEntity(a_entity);
            }
            trans->trans_ReqDataLength = 516;
            FreeTransaction(trans);
         }
         LoseService(dest);
      }
      DeleteEntity(entity);
   }
   if(error)
   {
      GLB_Error=error;
      Signal(TKProc, TKSignalMask);
   }
   Forbid();
   if(Conf_Port=FindPort(Conf_Port_Name))
      PutMsg(Conf_Port,&Conf_Msg);
   Permit();
}



/*
** Attempt to start a conference defined.  The conference name (conf_name),
** conference host (conf_host), and alias (alias) are all defined globally
** to make "passing" vars to a CreateNewProc() a little easier.
**
** Error Results:
**
** 0 - CreateNewProc() appears to have succeeded
** 1 - CreateNewProc() appears to have failed
*/

UBYTE StartTalk(ULONG start_command)
{
   ULONG cptags[5];
   UBYTE N_Name[64];
   struct Process *talkproc;
   UBYTE  sigbit;
   UBYTE error=1;
   
   geta4();
   ++Start_Count;
   BusyOn();
   if(sigbit = AllocSignal(-1L))
   {
      TKProc = FindTask(0L);
      TKSignalMask = (1L<<sigbit);

// Give each Conference a *UNIQUE* Process Name!
// didn't help any

      sprintf(N_Name,"%ld_%ld_%s",Start_Count,TKProc,conf_name);

      cptags[0] = NP_Entry;
      cptags[1] = (ULONG) TalkConf;
      cptags[2] = NP_Name;
      cptags[3] = (ULONG) N_Name;
      cptags[4] = TAG_DONE;
      
      TKCommand = start_command;

      if(talkproc = CreateNewProc((struct TagItem *)cptags))
      {
         Wait(1L<<sigbit);
         error=0;
      }
      FreeSignal(sigbit);
   }

   BusyOff();
   return(error);
}




/*
** Get a list of active conferences for a given host (global var) when
** passed a null.  Otherwise, it attempts to get a list of machines in
** the conference named passed to it on the given host (global var).
**
** BUG FIX!
** Added an overall timeout incase the server disappears to prevent
** waiting for a transaction that will NEVER happen.
** 
** Error Codes (in GLB_Error):
**
** 1 - General failure
** 2 - Unable to find service/host
*/   


struct List *Get_Conference_List(UBYTE *c_name)
{
   ULONG sigbit=0,waitmask,signal,mem_p,sigbit2;
   struct c_worknode *c_mem;
   struct c_membnode *m_mem;
   UBYTE done;
   UBYTE host_name[32];
   struct Transaction *trans,*a_trans;
   void *entity,*a_entity,*dest;
   struct List *r_value=NULL;
   struct TagItem cetags[4];
   struct TagItem cbtags[2];
   struct TagItem ttags[3];
   struct MsgPort *TimerMP;
   struct timerequest *TimerIO;
   

   BusyOn();
   
   if(TimerMP=CreateMsgPort())
   {
      if(TimerIO=(struct timerequest *)CreateExtIO(TimerMP,sizeof(struct timerequest)))
      {
         if(!(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0)))
         {
            cetags[0].ti_Tag=ENT_Name;
            cetags[0].ti_Data=NULL;
            cetags[1].ti_Tag=ENT_Public;
            cetags[1].ti_Data=NULL;
            cetags[2].ti_Tag=ENT_AllocSignal;
            cetags[2].ti_Data=NULL;
            cetags[3].ti_Tag=TAG_END;
            cetags[3].ti_Data=NULL;
         
            cbtags[0].ti_Tag=ENT_AllocSignal;
            cbtags[0].ti_Data=NULL;
            cbtags[1].ti_Tag=TAG_END;
            cbtags[1].ti_Data=NULL;
            
            ttags[0].ti_Tag=TRN_AllocReqBuffer;
            ttags[0].ti_Data=516;
            ttags[1].ti_Tag=TRN_AllocRespBuffer;
            ttags[1].ti_Data=4;
            ttags[2].ti_Tag=TAG_END;
            ttags[2].ti_Data=NULL;
         
            GLB_Error=1;
            if(c_name)
               FreeMList();
            else
               FreeCList();
         
            cbtags[0].ti_Data=(ULONG) &sigbit2;
            cetags[2].ti_Data=(ULONG) &sigbit;
         
            if (entity = CreateEntityA((struct TagItem *) cbtags))
            {
               GLB_Error=2;
               if (dest = FindServiceA(conf_host, "Conf_Service", entity, NULL))
               {
                  GLB_Error=1;
                  if (trans = AllocTransactionA((struct TagItem *) ttags))
                  {
                     cetags[0].ti_Data=(ULONG) "Conference_List";
                     GLB_Error=1;
                     if(a_entity=CreateEntityA((struct TagItem *) cetags))
                     {
                        GLB_Error=0;
                        GetHostName(entity,host_name,31);
                        strcpy(((UBYTE *)trans->trans_RequestData+4),host_name);
                        trans->trans_ReqDataActual=strlen(host_name)+5;
                        if(!c_name)
                        {
                           trans->trans_Command=TKCMD_CONLIST;
                        }
                        else
                        {
                           strcpy(((UBYTE *)trans->trans_RequestData+4),c_name);
                           strcpy(((UBYTE *)trans->trans_RequestData+36),host_name);
                           trans->trans_ReqDataActual=strlen(host_name)+37;
                           trans->trans_Command=TKCMD_MALIST;
                        }
         
                        trans->trans_Timeout=10;
                        DoTransaction(dest,entity,trans);
         
                        if(!trans->trans_Error)
                        {
                           waitmask = (1<<sigbit) | (1L << TimerMP->mp_SigBit);
                           
                           TimerIO->tr_node.io_Command=TR_ADDREQUEST;
                           TimerIO->tr_time.tv_secs=20;
                           TimerIO->tr_time.tv_micro=0;
                           SendIO((struct IORequest *)TimerIO);
               
                           done=0;
                           
                           while(!done)
                           {
                              signal = Wait(waitmask);
                              if(signal & (1<<sigbit))
                              {
                                 if(a_trans=GetTransaction(a_entity))
                                 {
                                    if(a_trans->trans_Command == TKCMD_CLDATA)
                                    {
                                       for(mem_p=4;mem_p<a_trans->trans_ReqDataActual;mem_p+=32)
                                       {
                                          if(c_name)
                                          {
                                             if(m_mem=AllocMem(sizeof(struct c_membnode),NULL))
                                             {
                                                m_mem->cnode.ln_Name=m_mem->alias;
                                                strcpy(m_mem->name,(UBYTE *)a_trans->trans_RequestData+mem_p);
                                                strcpy(m_mem->alias,(UBYTE *)a_trans->trans_RequestData+mem_p+32);
                                                m_mem->flags=(ULONG) *((ULONG *)((UBYTE *)a_trans->trans_RequestData+mem_p+64));
                                                AddTail(&c_memblist,(struct Node *)m_mem);
                                                r_value=&c_memblist;
                                                mem_p+=36;
                                             }
                                          }
                                          else
                                          {
                                             if(c_mem=AllocMem(sizeof(struct c_worknode),NULL))
                                             {
                                                c_mem->cnode.ln_Name=c_mem->name;
                                                strcpy(c_mem->name,(UBYTE *)a_trans->trans_RequestData+mem_p);
                                                AddTail(&c_worklist,(struct Node *)c_mem);
                                                r_value=&c_worklist;
                                             }
                                          }
                                       }
                                    }
                                    else if(a_trans->trans_Command == TKCMD_CLEND)
                                    {
                                       done=1;
                                    }
                                    a_trans->trans_Error=0;
                                    ReplyTransaction(a_trans);
               
                                    if(!(CheckIO((struct IORequest *)TimerIO)))
                                    {
                                       AbortIO((struct IORequest *)TimerIO);
                                    }
                                    WaitIO((struct IORequest *)TimerIO);
         
                                    TimerIO->tr_node.io_Command=TR_ADDREQUEST;
                                    TimerIO->tr_time.tv_secs=20;
                                    TimerIO->tr_time.tv_micro=0;
                                    SendIO((struct IORequest *)TimerIO);
                                 }                                    
                              }
                              if(signal & (1L << TimerMP->mp_SigBit))
                              {
                                 if(GetMsg(TimerMP))
                                 {
                                    done=1;
                                    GLB_Error=13;  /* Overall Timeout Error */       
                                 }
                              }
                           }
                        }
                        else
                        {
                           GLB_Error=trans->trans_Error;
                        }
                        
                        if(!(CheckIO((struct IORequest *)TimerIO)))
                        {
                           AbortIO((struct IORequest *)TimerIO);
                        }
                        WaitIO((struct IORequest *)TimerIO);
         
                        DeleteEntity(a_entity);  
                     }                           
                     FreeTransaction(trans);
                  }
                  LoseService(dest);
               }
               DeleteEntity(entity);
            }
            CloseDevice((struct IORequest *)TimerIO);
         }
         DeleteExtIO((struct IORequest *)TimerIO);
      }
      DeleteMsgPort(TimerMP);
   }
   BusyOff();
   return(r_value);
}



/*
**
** Attempts to send a private message to a specific user.
**
*/ 

void Send_PrivateMsg(void)
{
   ULONG sigbit2;
   struct Transaction *trans;
   void *entity,*dest;
   UBYTE host_name[32],work_space[512];
   struct TagItem cbtags[2];
   struct TagItem ttags[3];


   BusyOn();

   cbtags[0].ti_Tag=ENT_AllocSignal;
   cbtags[0].ti_Data=(ULONG) &sigbit2;
   cbtags[1].ti_Tag=TAG_END;
   cbtags[1].ti_Data=NULL;
   
   ttags[0].ti_Tag=TRN_AllocReqBuffer;
   ttags[0].ti_Data=516;
   ttags[1].ti_Tag=TRN_AllocRespBuffer;
   ttags[1].ti_Data=4;
   ttags[2].ti_Tag=TAG_END;
   ttags[2].ti_Data=NULL;

   GLB_Error=1;
   if(entity = CreateEntityA((struct TagItem *) cbtags))
   {
      GLB_Error=2;
      if (dest = FindServiceA(conf_host, "Conf_Service", entity, NULL))
      {
         GLB_Error=1;
         if (trans = AllocTransactionA((struct TagItem *) ttags))
         {
            GetHostName(entity,host_name,31);
            GLB_Error=0;
            if(alias[0])
               sprintf(work_space,"}%s{ %s\n",alias,pri_msg);
            else
               sprintf(work_space,"}%s{ %s\n",host_name,pri_msg);
            *(ULONG *)trans->trans_RequestData=0xffffffff;
            strcpy(((UBYTE *)trans->trans_RequestData+4),machine_name);
            strcpy(((UBYTE *)trans->trans_RequestData+36),conf_name);
            strcpy(((UBYTE *)trans->trans_RequestData+68),work_space);
            trans->trans_Command=TKCMD_PRIVATE;
            trans->trans_ReqDataActual=strlen(work_space)+68;
            trans->trans_Timeout=10;
            DoTransaction(dest,entity,trans);

            if(trans->trans_Error)
            {
                GLB_Error=trans->trans_Error | 0x10000;
            } else
            {
                strcpy(((UBYTE *)trans->trans_RequestData+4),host_name);
                trans->trans_Timeout=10;
                DoTransaction(dest,entity,trans);
            }

            FreeTransaction(trans);
         }
         LoseService(dest);
      }
      DeleteEntity(entity);
   }
   BusyOff();
}




/*
**
** Attempts to change the TALKING & LISTENING status of a user
**
*/ 

void Send_ToggleMode(void)
{
   ULONG sigbit2;
   struct Transaction *trans;
   UBYTE host_name[32];
   void *entity,*dest;
   struct TagItem cbtags[2];
   struct TagItem ttags[3];


   BusyOn();

   cbtags[0].ti_Tag=ENT_AllocSignal;
   cbtags[0].ti_Data=(ULONG) &sigbit2;
   cbtags[1].ti_Tag=TAG_END;
   cbtags[1].ti_Data=NULL;
   
   ttags[0].ti_Tag=TRN_AllocReqBuffer;
   ttags[0].ti_Data=516;
   ttags[1].ti_Tag=TRN_AllocRespBuffer;
   ttags[1].ti_Data=4;
   ttags[2].ti_Tag=TAG_END;
   ttags[2].ti_Data=NULL;

   GLB_Error=1;
   if(entity = CreateEntityA((struct TagItem *) cbtags))
   {
      GLB_Error=2;
      if (dest = FindServiceA(conf_host, "Conf_Service", entity, NULL))
      {
         GLB_Error=1;
         if (trans = AllocTransactionA((struct TagItem *) ttags))
         {
            GetHostName(entity,host_name,31);
            GLB_Error=0;

            *(ULONG *)trans->trans_RequestData=0xffffffff;
            strcpy(((UBYTE *)trans->trans_RequestData+4),machine_name);
            strcpy(((UBYTE *)trans->trans_RequestData+36),conf_name);
            strcpy(((UBYTE *)trans->trans_RequestData+68),host_name);
            *(LONG *)((UBYTE *)trans->trans_RequestData+100)=cycle_mode;
            
            trans->trans_Command=TKCMD_STATUS;
            trans->trans_ReqDataActual=105;
            trans->trans_Timeout=10;
            DoTransaction(dest,entity,trans);
            
            if(trans->trans_Error)
               GLB_Error=trans->trans_Error | 0x10000;
            FreeTransaction(trans);
         }
         LoseService(dest);
      }
      DeleteEntity(entity);
   }
   BusyOff();
}
 



/*
**
** Since FindName() is case sensitive, I can't use it...
**
*/

struct Node *CFindName(struct List *cc_list,UBYTE *string)
{
   struct Node *r_value=NULL,*ln;
   
   for(ln=cc_list->lh_Head;ln->ln_Succ;ln=ln->ln_Succ)
   {
      if(!Stricmp(ln->ln_Name,string))
      {
         r_value=ln;
         break;
      }
   }
   return(r_value);
}
